fix(data): 覆盖式导入与快照恢复前自动备份

- importJson / restoreSnapshot 覆盖前先写一份当前数据快照,误操作可回退
- 导入校验增加 id 唯一性检查,宽容读取路径保留首条
- 快照索引对同一时间点的重复写入去重
- 落盘失败时翻转 persistent,恢复后自动撤除告警
- 备份面板提示导入前数据已自动备份
This commit is contained in:
chenshoulin
2026-10-19 17:20:20 +08:00
parent 12c5346f75
commit ede4bfe88f
8 changed files with 214 additions and 14 deletions
+11 -3
View File
@@ -59,9 +59,13 @@ function confirmImport(): void {
const target = pending.value
if (!target) return
// 记录导入前的数量,用于提示「旧数据已自动备份」是否真的发生了
const beforeCount = store.tasks.length
try {
const count = store.importJson(target.text)
message.value = `已从 ${target.fileName} 导入 ${count} 个任务`
const backupNote = beforeCount > 0 ? ',导入前的数据已自动备份' : ''
message.value = `已从 ${target.fileName} 导入 ${count} 个任务${backupNote}`
error.value = null
} catch (cause) {
error.value = cause instanceof Error ? cause.message : '导入失败'
@@ -71,9 +75,12 @@ function confirmImport(): void {
}
function restore(key: string): void {
const beforeCount = store.tasks.length
try {
const count = store.restoreSnapshot(key)
message.value = count > 0 ? `已从备份恢复 ${count} 个任务` : '该备份是空的,未做改动'
const backupNote = beforeCount > 0 ? ',恢复前的数据已自动备份' : ''
message.value =
count > 0 ? `已从备份恢复 ${count} 个任务${backupNote}` : '该备份是空的,未做改动'
error.value = null
} catch (cause) {
error.value = cause instanceof Error ? cause.message : '恢复失败'
@@ -137,7 +144,8 @@ function formatTime(iso: string): string {
>
<p class="text-sm text-amber-900 dark:text-amber-200">
将从「{{ pending.fileName }}」导入 {{ pending.count }} 个任务,
<strong>并覆盖当前全部 {{ store.tasks.length }} 个任务</strong>。此操作不可撤销。
<strong>并覆盖当前全部 {{ store.tasks.length }} 个任务</strong>。 覆盖前会自动把当前数据
存一份到下方「自动备份」,选错文件也能从那里恢复。
</p>
<div class="flex gap-2">
<button