feat(admin): 弹窗未保存内容保护与空状态引导扩展
- 新增 useDirtyGuard hook:关闭弹窗时若表单被修改,先确认再关闭 - 接入 17 个弹窗:账号/密码/档案、角色、教室、宿舍/床位/柜子、 考勤机、机构、班级、教师、考试、排课、入住/退宿/换房、费用 (子组件弹窗用 useEffect 在回填后快照,时序正确) - 学生列表空状态带「添加学生」引导动作 - 排课创建成功提示「同步钉钉」,考试创建成功提示「去详情录成绩」 aislop scan: 5 引擎 0 issues
This commit is contained in:
51
apps/admin/src/hooks/useDirtyGuard.ts
Normal file
51
apps/admin/src/hooks/useDirtyGuard.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
import { useCallback, useRef } from 'react';
|
||||
import { App } from 'antd';
|
||||
import type { FormInstance } from 'antd';
|
||||
|
||||
/**
|
||||
* 弹窗「未保存内容」保护:关闭弹窗时若表单值已被修改,先确认再关闭,
|
||||
* 避免用户误关丢失已填内容。
|
||||
*
|
||||
* 用法:
|
||||
* const { confirmClose, snapshot } = useDirtyGuard(form);
|
||||
* // 打开弹窗(或编辑回填后)时调用一次 snapshot() 记录初始值
|
||||
* const openEdit = () => { form.setFieldsValue(record); snapshot(); setOpen(true); };
|
||||
* // Modal 的 onCancel 改用确认关闭
|
||||
* <Modal onCancel={() => confirmClose(() => setOpen(false))} ...>
|
||||
*/
|
||||
export function useDirtyGuard(form: FormInstance) {
|
||||
const { modal } = App.useApp();
|
||||
const pristineRef = useRef<string>('');
|
||||
|
||||
/** 记录当前表单值为「未修改」基准;打开弹窗/回填后调用 */
|
||||
const snapshot = useCallback(() => {
|
||||
pristineRef.current = JSON.stringify(form.getFieldsValue());
|
||||
}, [form]);
|
||||
|
||||
/** 表单是否有未保存修改(与 snapshot 时对比) */
|
||||
const isDirty = useCallback(() => {
|
||||
return JSON.stringify(form.getFieldsValue()) !== pristineRef.current;
|
||||
}, [form]);
|
||||
|
||||
const confirmClose = useCallback(
|
||||
(close: () => void) => {
|
||||
if (!isDirty()) {
|
||||
close();
|
||||
return;
|
||||
}
|
||||
modal.confirm({
|
||||
title: '放弃未保存的修改?',
|
||||
content: '当前表单有未保存的内容,关闭后修改将丢失。',
|
||||
okText: '放弃修改',
|
||||
okButtonProps: { danger: true },
|
||||
cancelText: '继续编辑',
|
||||
onOk: close,
|
||||
});
|
||||
},
|
||||
[isDirty, modal],
|
||||
);
|
||||
|
||||
return { confirmClose, snapshot, isDirty };
|
||||
}
|
||||
|
||||
export default useDirtyGuard;
|
||||
Reference in New Issue
Block a user