有一个表,有两个属性 HEADER 和 BODY。有这样的行:
标头 | 身体 |
---|---|
属性1、属性2、属性3 | 1,2,3,4,5,6,7,8,9 |
我想得到这样的结果:
属性1 | 属性2 | 属性3 |
---|---|---|
1 | 2 | 3 |
4 | 5 | 6 |
7 | 8 | 9 |
我不会引用我自己尝试过的方法,因为...... 根本没有成功。
有一个表,有两个属性 HEADER 和 BODY。有这样的行:
标头 | 身体 |
---|---|
属性1、属性2、属性3 | 1,2,3,4,5,6,7,8,9 |
我想得到这样的结果:
属性1 | 属性2 | 属性3 |
---|---|---|
1 | 2 | 3 |
4 | 5 | 6 |
7 | 8 | 9 |
我不会引用我自己尝试过的方法,因为...... 根本没有成功。
有一个数据模型:
public class Item1
{
public long Addr { get; set; }
public long Pos { get; set; }
public string Description { get; set; }
public long Number { get; set; }
}
public class Item2
{
public long Addr { get; set; }
public string Description { get; set; }
public ulong Pointer{ get; set; }
}
创建了 Item1 和 Item2:
var items1 = new Dictionary<ulong, Item1>();
items1.Add(id, new Item1
{
Addr = Addr,
Pos = Pos,
Description = Description,
Number = Number
Pointer = Pointer
});
var items2 = new Dictionary<ulong, Item2>();
items1.Add(id, new Item2
{
Addr = Addr,
Description = Description,
Pointer = Pointer
});
有一个itemPointers列表,其中包含items1中的匹配id和item2中的Pointer
列出 itemPointers = new();
如何创建这样的 itemPointers列表?
我试图玩itemPointers = items1.Select(e =>items2.ContainsKey(e.Pointer)),我知道在 items2.ContainsKey(e.Pointer) 的某个地方应该有 ForEach,但我不明白我在哪里知道我能做到
foreach (var id in items2)
{
if (items1.ContainsKey(items2[id.Key].Pointer))
{
itemPointers.Add(id.Key);
}
}
但似乎有一种更优雅(更快?)的方式来做到这一点。
我真的请求你的帮助。问题是,我不明白如何在卸载组件之前清理 redux 状态。我有选择链表,当您选择其中任何一个时,会发出一个 api 请求,并且其他的数据会发生变化。一切正常,直到我从一个这样的页面转到另一个页面。那些。我有标签,在一个标签上有链接列表,在另一个标签上。如果我切换选项卡,那么我的请求会加倍,因为 useEffect 中的清理功能没有时间清除状态,因此,当加载组件时,会发生第一个请求链,当观察到 select 时,第二个立即发生。如何在加载另一个选项卡之前等待清理功能完成?
useEffect(() => {
dispatch(fetchCoursesByGroup({ idPlan, idGroup })); // Получаю данные для заполнения первого списка
// В reducer просто обновляю state пустым массивом
return () => {
dispatch(changePlan(planFields)); // Очищаю таблицу, которая была получена на основе выбранных значений из списка
dispatch(setAllFormControl([])); // Очищаю Формы контроля
dispatch(setSemestersCourse([])); // Очищаю курсы
dispatch(setGroupCourses([])); // Очищаю семестры
};
}, []);
我通过相同的 useEffect 获取所有列表,例如:
useEffect(() => {
if (watchCourse) getSemesters(watchCourse); // Если выбран курс, получаю семестры на этот курс
}, [watchCourse]);
最后,执行一个函数,其中也用select中选择的值向服务器发起api请求,获取表。混乱来了。由于 useEffect 没有时间清理课程、学期、控制表格等,数据还在,当页面加载时,立即触发获取表的请求,然后触发下一个 useEffect,其中,当页面被加载,接收第一个列表的数据,这导致链 useEffect 获取后续列表的数据,最后重新查询表......
带有链表的完整组件代码
import React, { useEffect } from 'react';
import { useForm } from 'react-hook-form';
import { useDispatch, useSelector } from 'react-redux';
import { fetchCoursesByGroup } from '../../../store/Actions/coursesAction';
import { fetchSemestersByCourse } from '../../../store/Actions/semestersAction';
import { fetchAllFormControl } from '../../../store/Actions/formControlAction';
import { fetchPlan } from '../../../store/Actions/planAction';
import { planReducer } from '../../../store/Reducers/planReducer';
import { formControlReducer } from '../../../store/Reducers/formControlReducer';
import { semestersReducer } from '../../../store/Reducers/semestersReducer';
import { coursesReducer } from '../../../store/Reducers/coursesReducer';
import { plan as planFields } from '../../../store/fields/planFields';
import Filter from '../../Basic/Filter';
function PlanFilter({ idGroup, idPlan, callbackSemester = () => {}, callbackControl = () => {} }) {
const dispatch = useDispatch();
const { register, watch, setValue } = useForm();
const watchCourse = watch('coursesSelect');
const watchSemester = watch('semestersSelect');
const watchControl = watch('controlsSelect');
const coursesSelect = register('coursesSelect');
const semestersSelect = register('semestersSelect');
const controlsSelect = register('controlsSelect');
const courses = useSelector((state) => state.coursesReducer.groupCourses);
const semesters = useSelector((state) => state.semestersReducer.semestersCourse);
const formControl = useSelector((state) => state.formControlReducer.all);
const { changePlan } = planReducer.actions;
const { setAllFormControl } = formControlReducer.actions;
const { setSemestersCourse } = semestersReducer.actions;
const { setGroupCourses } = coursesReducer.actions;
// Получаю курсы в первый select и очищаю при размонтировании компонента
useEffect(() => {
dispatch(fetchCoursesByGroup({ idPlan, idGroup }));
return () => {
dispatch(changePlan(planFields));
dispatch(setAllFormControl([]));
dispatch(setSemestersCourse([]));
dispatch(setGroupCourses([]));
};
}, []);
// Здесь я хочу чтоб при первой загрузке компонента установился первый элемент из массива как выбранный курс, чтоб воспроизвести цепочку и заполнить все списки сразу при загрузке страницы
useEffect(() => {
if (courses.length > 0 && !watchCourse)
setValue('coursesSelect', courses[0].idCoursePlan.toString());
}, [courses]);
useEffect(() => {
if (semesters.length > 0) setValue('semestersSelect', semesters[0].name.split(' ')[1]);
}, [semesters]);
useEffect(() => {
if (formControl.length > 0) {
setValue('controlsSelect', formControl[0].id.toString());
getPlan(); // Вызов финальной таблицы
}
}, [formControl]);
// При изменении семестра вызываю функцию для получения через api форм контроля на выбранный семестр
useEffect(() => {
if (watchSemester) {
getFormControl();
callbackSemester(watchSemester); // Просто возвращаю выбранный семестр в родителя для других целей
}
}, [watchSemester]);
useEffect(() => {
if (watchCourse) getSemesters(watchCourse);
}, [watchCourse]);
useEffect(() => {
if (watchControl) {
getPlan();
callbackControl(watchControl);
}
}, [watchControl]);
const getSemesters = (idCoursePlan) =>
dispatch(fetchSemestersByCourse({ idCoursePlan, idGroup, withActive: true }));
const getFormControl = () => dispatch(fetchAllFormControl({ withAll: false }));
const getPlan = () => {
if (watchSemester && watchControl && idPlan)
dispatch(fetchPlan({ semester: watchSemester, idControl: watchControl, idPlan }));
};
return (
<Filter.Form classes={['FilterForm FilterForm_position_sticky pb-4']}>
<Filter.Group labelTitle="Курс:">
<Filter.Select registered={coursesSelect}>
{courses.map((course) => (
<Filter.Option key={course.idCoursePlan} value={course.idCoursePlan}>
{course.name}
</Filter.Option>
))}
</Filter.Select>
</Filter.Group>
<Filter.Group labelTitle="Семестр:" classes={['ml-4']}>
<Filter.Select registered={semestersSelect}>
{semesters.map((semester) => (
<Filter.Option key={semester.id} value={semester.name.split(' ')[1]}>
{semester.name}
</Filter.Option>
))}
</Filter.Select>
</Filter.Group>
<Filter.Group labelTitle="Форма контроля:" classes={['ml-4']}>
<Filter.Select registered={controlsSelect}>
{formControl.map((control) => (
<Filter.Option key={control.id} value={control.id}>
{control.name}
</Filter.Option>
))}
</Filter.Select>
</Filter.Group>
</Filter.Form>
);
}
export default PlanFilter;
减速器之一的代码(课程)
import { createSlice } from '@reduxjs/toolkit';
import { fetchCoursesByFacultyLevelForm, fetchCoursesByGroup } from '../Actions/coursesAction';
const initialState = {
groupCourses: [], // вот этот массив используется для select'a
facultyLevelForm: [],
isLoading: false,
error: '',
};
const pendingReducer = (state) => {
state.isLoading = true;
};
const rejectedReducer = (state, action) => {
state.isLoading = false;
if (action) state.error = action.payload.error;
};
const defaultFulfilledReducer = (state) => {
rejectedReducer(state);
};
export const coursesReducer = createSlice({
name: 'courses',
initialState,
reducers: {
setGroupCourses(state, action) {
// Сюда я передаю пустой массив при
// размонтировании компонента, это я и называю очищением
state.groupCourses = action.payload;
},
changeFacultyLevelForm(state, action) {
state.facultyLevelForm = action.payload;
},
},
extraReducers: {
[fetchCoursesByGroup.fulfilled]: (state, action) => {
state.groupCourses = action.payload;
defaultFulfilledReducer(state); // Заполняю курсы с api
},
[fetchCoursesByGroup.pending]: pendingReducer,
[fetchCoursesByGroup.rejected]: rejectedReducer,
[fetchCoursesByFacultyLevelForm.fulfilled]: (state, action) => {
state.facultyLevelForm = action.payload;
defaultFulfilledReducer(state);
},
[fetchCoursesByFacultyLevelForm.pending]: pendingReducer,
[fetchCoursesByFacultyLevelForm.rejected]: rejectedReducer,
},
});
export default coursesReducer.reducer;
所有其他减速器的制造方式完全相同。
安装所有选项卡的主页代码。
<BaseLayout
callbackSelectedGroup={(e) => setSelectedGroup(e)}
tabs={selectedGroup ? ['Контингент', 'Учебный план', 'Успеваемость'] : []}
callbackSelectedTab={(e) => setTab(e)}
>
{tab === 1 && <Contingent idGroup={group.id} />}
{tab === 2 && <Plan idGroup={group.id} />}
{tab === 3 && <Progress idGroup={group.id} />}
</BaseLayout>
代码选项卡计划(课程)
import React, { useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import withReactContent from 'sweetalert2-react-content';
import Swal from 'sweetalert2';
import { PencilAltIcon } from '@heroicons/react/outline';
import FileDropper from '../../FileDropper';
import {
fetchPlan,
fetchPlanIdByGroup,
savePlan as savePlanAction,
uploadPlan as uploadFileDispatch,
} from '../../../store/Actions/planAction';
import HeaderPlan from './HeaderPlan';
import BodyPlan from './BodyPlan';
import PlanFilter from './PlanFilter';
import { ContextItem, ContextList, ContextMenu } from '../../ContextMenu';
import { ReactComponent as NotFoundSvg } from '../../../images/undraw_not_found.svg';
import MTable from '../../Tables/MainTable';
function Plan() {
const TheSwal = withReactContent(Swal);
const dispatch = useDispatch();
// Store
const idPlan = useSelector((store) => store.planReducer.idPlan);
const plan = useSelector((store) => store.planReducer.plan);
const group = useSelector((store) => store.groupsReducer.selectedGroup);
// State
const [editMode, setEditMode] = useState(false);
const [selectedSemester, setSelectedSemester] = useState();
const [selectedControl, setSelectedControl] = useState();
useEffect(() => {
if (group)
dispatch(
fetchPlanIdByGroup({
idSpecialty: group.spesialty_id,
yearAdmission: group.group_date_start,
}),
);
}, [group]);
return (
<div className="Main__ContentContainer">
{idPlan.id && (
{/* Это компонент со связными списками, код которого я предоставил выше*/}
<PlanFilter
idPlan={idPlan.id}
idGroup={group.id}
callbackSemester={(e) => setSelectedSemester(e)}
callbackControl={(e) => setSelectedControl(e)}
/>
)}
{idPlan.id && (
<>
<MTable.Table>
<HeaderPlan
editMode={editMode}
callbackCancelEdit={cancelEdit}
callbackSaveEdit={savePlan}
/>
<BodyPlan
editMode={editMode}
callbackCancelEdit={cancelEdit}
callbackSaveEdit={savePlan}
/>
</MTable.Table>
</>
)}
export default Plan;
再现情况:
我有一个存储票务数据的表门票,它有列
存储票号的 BSONUM
存储销售日期的 DEALDATE
存储票务交易的 OPERTYPE(销售、退款、取消等)
我的任务是在门票表中创建一个 DateSaleForRefund 列,如果票号与票号匹配并且交易 = 退款,则在其中显示门票销售日期。我提出了更新请求,但需要插入每张票才能更新。问题是如何提出请求,以便如果票号与票号匹配,则更新 DateSaleForRefund 列。提前致谢
update s
set s.DateSaleForRefund =(
select b2.DEALDATE
from Tickets b2
where b2.BSONUM = s.BSONUM and b2.OPERTYPE=1)
from Tickets as s
where s.BSONUM='4212435875456' and s.OPERTYPE='5' and s.DateSaleForRefund IS NULL