diff --git a/src/components/CrudTable.vue b/src/components/CrudTable.vue index f3036f2..bce9df6 100644 --- a/src/components/CrudTable.vue +++ b/src/components/CrudTable.vue @@ -203,7 +203,7 @@ const formColumns = computed(() => { // ===== 新增表单自动草稿(独立 composable:useDraftAutosave) ===== // 防止误关闭/误刷新丢失录入内容;按表维度存 localStorage, -// 再次打开"新增"时提示恢复或放弃;提交成功后清除。 +// 再次打开"新增"时提示「恢复草稿 / 删除草稿」(空草稿直接丢弃,不打扰);提交成功后清除。 const draft = useDraftAutosave({ table: props.table, editingRow: editingRow as Record, diff --git a/src/composables/useDraftAutosave.ts b/src/composables/useDraftAutosave.ts index 02dee3c..6b37202 100644 --- a/src/composables/useDraftAutosave.ts +++ b/src/composables/useDraftAutosave.ts @@ -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 = {} + if (draftBaseline) { + try { + base = JSON.parse(draftBaseline) as Record + } 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 { 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'(右上角 ×):保留草稿,下次再提示 } }