fix(admin): 补全 React hooks 依赖并修复页面稳定性
- 各页面 useCallback/useMemo 依赖补全(modal/mutation/setter 等),避免闭包过期 - ECharts 使用 optionRef、MainLayout 缓存菜单转换函数、main.tsx 增加挂载点校验 - 学生同步结果改用 recordsCount 展示
This commit is contained in:
@@ -89,33 +89,6 @@ const ClassesPage: React.FC = () => {
|
||||
const [saving, setSaving] = useState(false);
|
||||
const [showArchived, setShowArchived] = useState(false);
|
||||
|
||||
const handleArchive = async (id: number, archive: boolean) => {
|
||||
try {
|
||||
await archiveMutation.mutateAsync({ id, archive });
|
||||
message.success(archive ? '已归档' : '已恢复');
|
||||
} catch {
|
||||
// 错误提示由 useApiMutation 统一处理
|
||||
}
|
||||
};
|
||||
|
||||
const handlePurge = (record: ClassItem) => {
|
||||
modal.confirm({
|
||||
title: `永久删除班级「${record.name}」?`,
|
||||
content: '删除后不可恢复,存在学生、教师、排课、考试或考勤关联时将无法删除。确定继续?',
|
||||
okText: '永久删除',
|
||||
okButtonProps: { danger: true },
|
||||
cancelText: '取消',
|
||||
onOk: async () => {
|
||||
try {
|
||||
await purgeMutation.mutateAsync(record.id);
|
||||
message.success('已永久删除(不可恢复)');
|
||||
} catch {
|
||||
// 错误提示由 useApiMutation 统一处理
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const {
|
||||
data = [],
|
||||
isLoading,
|
||||
@@ -160,6 +133,39 @@ const ClassesPage: React.FC = () => {
|
||||
{ invalidate: [['classes']] },
|
||||
);
|
||||
|
||||
const handleArchive = useCallback(
|
||||
async (id: number, archive: boolean) => {
|
||||
try {
|
||||
await archiveMutation.mutateAsync({ id, archive });
|
||||
message.success(archive ? '已归档' : '已恢复');
|
||||
} catch {
|
||||
// 错误提示由 useApiMutation 统一处理
|
||||
}
|
||||
},
|
||||
[archiveMutation],
|
||||
);
|
||||
|
||||
const handlePurge = useCallback(
|
||||
(record: ClassItem) => {
|
||||
modal.confirm({
|
||||
title: `永久删除班级「${record.name}」?`,
|
||||
content: '删除后不可恢复,存在学生、教师、排课、考试或考勤关联时将无法删除。确定继续?',
|
||||
okText: '永久删除',
|
||||
okButtonProps: { danger: true },
|
||||
cancelText: '取消',
|
||||
onOk: async () => {
|
||||
try {
|
||||
await purgeMutation.mutateAsync(record.id);
|
||||
message.success('已永久删除(不可恢复)');
|
||||
} catch {
|
||||
// 错误提示由 useApiMutation 统一处理
|
||||
}
|
||||
},
|
||||
});
|
||||
},
|
||||
[modal, purgeMutation],
|
||||
);
|
||||
|
||||
const filtered = useMemo(() => {
|
||||
if (!searchText) return data;
|
||||
const q = searchText.toLowerCase();
|
||||
@@ -174,16 +180,19 @@ const ClassesPage: React.FC = () => {
|
||||
setModalOpen(true);
|
||||
};
|
||||
|
||||
const handleEdit = (record: ClassItem) => {
|
||||
setEditing(record);
|
||||
form.setFieldsValue({
|
||||
...record,
|
||||
notes: record.notes ?? undefined,
|
||||
startDate: record.startDate ? dayjs(record.startDate) : undefined,
|
||||
endDate: record.endDate ? dayjs(record.endDate) : undefined,
|
||||
});
|
||||
setModalOpen(true);
|
||||
};
|
||||
const handleEdit = useCallback(
|
||||
(record: ClassItem) => {
|
||||
setEditing(record);
|
||||
form.setFieldsValue({
|
||||
...record,
|
||||
notes: record.notes ?? undefined,
|
||||
startDate: record.startDate ? dayjs(record.startDate) : undefined,
|
||||
endDate: record.endDate ? dayjs(record.endDate) : undefined,
|
||||
});
|
||||
setModalOpen(true);
|
||||
},
|
||||
[form],
|
||||
);
|
||||
|
||||
const handleSubmit = async () => {
|
||||
setSaving(true);
|
||||
@@ -369,7 +378,7 @@ const ClassesPage: React.FC = () => {
|
||||
),
|
||||
},
|
||||
],
|
||||
[saveCell, canPurgeClass, handlePurge],
|
||||
[saveCell, canPurgeClass, handlePurge, navigate, handleEdit, handleArchive],
|
||||
);
|
||||
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user