fix(admin): 补全 React hooks 依赖并修复页面稳定性
- 各页面 useCallback/useMemo 依赖补全(modal/mutation/setter 等),避免闭包过期 - ECharts 使用 optionRef、MainLayout 缓存菜单转换函数、main.tsx 增加挂载点校验 - 学生同步结果改用 recordsCount 展示
This commit is contained in:
@@ -44,16 +44,19 @@ const UsersPage: React.FC = () => {
|
||||
const [saving, setSaving] = useState(false);
|
||||
const [showArchived, setShowArchived] = useState(false);
|
||||
|
||||
const handleOpenProfile = async (record: any) => {
|
||||
setProfileUser(record);
|
||||
try {
|
||||
const res = await api.get<UserProfileResponse>(`/rbac/users/${record.id}/profile`);
|
||||
profileForm.setFieldsValue(userProfileResponseToFormValues(res));
|
||||
} catch {
|
||||
profileForm.setFieldsValue({});
|
||||
}
|
||||
setProfileModalOpen(true);
|
||||
};
|
||||
const handleOpenProfile = useCallback(
|
||||
async (record: any) => {
|
||||
setProfileUser(record);
|
||||
try {
|
||||
const res = await api.get<UserProfileResponse>(`/rbac/users/${record.id}/profile`);
|
||||
profileForm.setFieldsValue(userProfileResponseToFormValues(res));
|
||||
} catch {
|
||||
profileForm.setFieldsValue({});
|
||||
}
|
||||
setProfileModalOpen(true);
|
||||
},
|
||||
[profileForm],
|
||||
);
|
||||
|
||||
const handleProfileSubmit = async () => {
|
||||
setSaving(true);
|
||||
@@ -133,15 +136,18 @@ const UsersPage: React.FC = () => {
|
||||
setModalOpen(true);
|
||||
};
|
||||
|
||||
const handleEdit = (record: any) => {
|
||||
setEditing(record);
|
||||
form.setFieldsValue({
|
||||
username: record.username,
|
||||
name: record.name,
|
||||
roleIds: record.roles?.map((r: any) => r.id) || [],
|
||||
});
|
||||
setModalOpen(true);
|
||||
};
|
||||
const handleEdit = useCallback(
|
||||
(record: any) => {
|
||||
setEditing(record);
|
||||
form.setFieldsValue({
|
||||
username: record.username,
|
||||
name: record.name,
|
||||
roleIds: record.roles?.map((r: any) => r.id) || [],
|
||||
});
|
||||
setModalOpen(true);
|
||||
},
|
||||
[form],
|
||||
);
|
||||
|
||||
const handleSubmit = async () => {
|
||||
setSaving(true);
|
||||
@@ -161,39 +167,48 @@ const UsersPage: React.FC = () => {
|
||||
setSaving(false);
|
||||
}
|
||||
};
|
||||
const handleArchive = async (id: number, archive: boolean) => {
|
||||
try {
|
||||
await archiveMutation.mutateAsync({ id, archive });
|
||||
message.success(archive ? '已归档' : '已恢复');
|
||||
} catch {
|
||||
// 错误提示由 useApiMutation 统一处理
|
||||
}
|
||||
};
|
||||
const handleArchive = useCallback(
|
||||
async (id: number, archive: boolean) => {
|
||||
try {
|
||||
await archiveMutation.mutateAsync({ id, archive });
|
||||
message.success(archive ? '已归档' : '已恢复');
|
||||
} catch {
|
||||
// 错误提示由 useApiMutation 统一处理
|
||||
}
|
||||
},
|
||||
[archiveMutation],
|
||||
);
|
||||
|
||||
const handlePurge = (record: any) => {
|
||||
modal.confirm({
|
||||
title: `永久删除账号「${record.name || record.username}」?`,
|
||||
content:
|
||||
'删除后不可恢复,关联学生、任教、排课或考勤操作时将无法删除;角色绑定、通知和 AI 会话将被清除,操作日志保留。确定继续?',
|
||||
okText: '永久删除',
|
||||
okButtonProps: { danger: true },
|
||||
cancelText: '取消',
|
||||
onOk: async () => {
|
||||
try {
|
||||
await purgeMutation.mutateAsync(record.id);
|
||||
message.success('已永久删除(不可恢复)');
|
||||
} catch {
|
||||
// 错误提示由 useApiMutation 统一处理
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
const handlePurge = useCallback(
|
||||
(record: any) => {
|
||||
modal.confirm({
|
||||
title: `永久删除账号「${record.name || record.username}」?`,
|
||||
content:
|
||||
'删除后不可恢复,关联学生、任教、排课或考勤操作时将无法删除;角色绑定、通知和 AI 会话将被清除,操作日志保留。确定继续?',
|
||||
okText: '永久删除',
|
||||
okButtonProps: { danger: true },
|
||||
cancelText: '取消',
|
||||
onOk: async () => {
|
||||
try {
|
||||
await purgeMutation.mutateAsync(record.id);
|
||||
message.success('已永久删除(不可恢复)');
|
||||
} catch {
|
||||
// 错误提示由 useApiMutation 统一处理
|
||||
}
|
||||
},
|
||||
});
|
||||
},
|
||||
[modal, purgeMutation],
|
||||
);
|
||||
|
||||
const handleResetPwd = (record: any) => {
|
||||
setResetTarget(record);
|
||||
pwdForm.resetFields();
|
||||
setPwdModalOpen(true);
|
||||
};
|
||||
const handleResetPwd = useCallback(
|
||||
(record: any) => {
|
||||
setResetTarget(record);
|
||||
pwdForm.resetFields();
|
||||
setPwdModalOpen(true);
|
||||
},
|
||||
[pwdForm],
|
||||
);
|
||||
|
||||
const handlePwdSubmit = async () => {
|
||||
setSaving(true);
|
||||
@@ -353,7 +368,16 @@ const UsersPage: React.FC = () => {
|
||||
),
|
||||
},
|
||||
],
|
||||
[roles, saveCell, canPurgeUser, handlePurge],
|
||||
[
|
||||
roles,
|
||||
saveCell,
|
||||
canPurgeUser,
|
||||
handlePurge,
|
||||
handleOpenProfile,
|
||||
handleEdit,
|
||||
handleArchive,
|
||||
handleResetPwd,
|
||||
],
|
||||
);
|
||||
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user