feat(gerp): 空草稿自动丢弃并新增"删除草稿"操作
useDraftAutosave:打开新增表单时,草稿无有效内容(全空值或与表单基线一致)直接丢弃不弹窗;恢复提示按钮改为「恢复草稿/删除草稿」,右上角关闭视为稍后再看(保留草稿)。
This commit is contained in:
1 parent
85fba0ef9f
commit
0e45175bc8
2 files changed
+46
-7
No files matched your search
@@ -203,7 +203,7 @@ const formColumns = computed(() => {
|
||||
|
||||
// ===== 新增表单自动草稿(独立 composable:useDraftAutosave) =====
|
||||
// 防止误关闭/误刷新丢失录入内容;按表维度存 localStorage,
|
||||
// 再次打开"新增"时提示恢复或放弃;提交成功后清除。
|
||||
// 再次打开"新增"时提示「恢复草稿 / 删除草稿」(空草稿直接丢弃,不打扰);提交成功后清除。
|
||||
const draft = useDraftAutosave({
|
||||
table: props.table,
|
||||
editingRow: editingRow as Record<string, unknown>,
|
||||
|
||||
@@ -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'(右上角 ×):保留草稿,下次再提示
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user