feat(gerp): 空草稿自动丢弃并新增"删除草稿"操作

useDraftAutosave:打开新增表单时,草稿无有效内容(全空值或与表单基线一致)直接丢弃不弹窗;恢复提示按钮改为「恢复草稿/删除草稿」,右上角关闭视为稍后再看(保留草稿)。
This commit is contained in:
TermiNexus committed 2026-10-01 16:13:18 +08:00
1 parent 85fba0ef9f
commit 0e45175bc8
2 files changed
+46 -7

No files matched your search

+1 -1
View File
@@ -203,7 +203,7 @@ const formColumns = computed(() => {
// ===== 新增表单自动草稿(独立 composable:useDraftAutosave) =====
// 防止误关闭/误刷新丢失录入内容;按表维度存 localStorage,
// 再次打开"新增"时提示恢复或放弃;提交成功后清除。
// 再次打开"新增"时提示「恢复草稿 / 删除草稿」(空草稿直接丢弃,不打扰);提交成功后清除。
const draft = useDraftAutosave({
table: props.table,
editingRow: editingRow as Record<string, unknown>,
+45 -6
View File
@@ -11,7 +11,10 @@ export interface FormDraft {
* 新增表单自动草稿(防止误关闭/误刷新丢失录入内容)
*
* 按表维度存 localStorage:录入内容每 600ms 防抖自动保存;
* 再次打开"新增"时提示恢复或放弃;提交成功后清除。
* 再次打开"新增"时提示「恢复草稿 / 删除草稿」(右上角关闭 = 稍后再看,保留草稿);
* 提交成功后清除。
*
* 空草稿(没有任何用户录入内容,或与本次基线一致)直接丢弃,不弹窗打扰。
*
* 从 CrudTable.vue 抽出的独立 composable(原 179-273 行逻辑)。
*/
@@ -77,20 +80,56 @@ export function useDraftAutosave(options: {
draftBaseline = JSON.stringify({ ...options.editingRow })
}
/** 检测并提示恢复/放弃草稿;恢复则写入表单(在新增弹窗初始化后调用) */
/**
* 草稿是否"为空":没有任何"用户真正录入"的内容 —— 全部是空值,
* 或与本次打开表单的基线完全一致(只有 CreateTime 等系统预填字段,用户没动过)
*/
function isDraftEmpty(draft: FormDraft): boolean {
const data = draft.data || {}
let base: Record<string, unknown> = {}
if (draftBaseline) {
try {
base = JSON.parse(draftBaseline) as Record<string, unknown>
} catch {
base = {}
}
}
return !Object.entries(data).some(([key, value]) => {
if (value === null || value === undefined || value === '' || (Array.isArray(value) && value.length === 0)) {
return false
}
return JSON.stringify(value) !== JSON.stringify(base[key])
})
}
/**
* 检测并提示恢复/删除草稿;恢复则写入表单(在新增弹窗初始化后调用)。
* 空草稿(无有效内容/与基线一致)直接丢弃,不弹窗打扰用户。
* 弹窗:确定=恢复草稿,取消=删除草稿,右上角关闭=稍后再看(保留草稿)
*/
async function restoreDraftIfAny(): Promise<void> {
const draft = readDraft()
if (!draft || !draft.data || Object.keys(draft.data).length === 0) return
if (!draft || isDraftEmpty(draft)) {
clearDraft() // 空草稿:直接丢弃
return
}
try {
await ElMessageBox.confirm(
`检测到 ${new Date(draft.updatedAt).toLocaleString()} 未提交的草稿,是否恢复继续编辑?`,
'恢复草稿',
{ type: 'warning', confirmButtonText: '恢复草稿', cancelButtonText: '放弃' },
{
type: 'warning',
confirmButtonText: '恢复草稿',
cancelButtonText: '删除草稿',
// 区分"取消"与"关闭":右上角 × 视为稍后再看,草稿保留不删
distinguishCancelAndClose: true,
},
)
Object.assign(options.editingRow, draft.data)
draftBaseline = null // 恢复后允许继续增量保存
} catch {
clearDraft() // 用户放弃 → 清掉旧草稿
} catch (action) {
if (action === 'cancel') clearDraft() // 选择"删除草稿"
// action === 'close'(右上角 ×):保留草稿,下次再提示
}
}