历史记录:每条可展开 diff,连续保存合并进 5 秒窗
备份存的是「改动前」,所以一条记录的 diff 两端是它自己和更新一份的 状态(最新一条对比当前文件)。行级 diff 先掐公共前后缀再做 LCS,一次 改动通常只碰几行,表撑得住;大面积不同时退化成整段删增。 合并窗做在服务端而不是前端防抖:普通保存(opts.merge)发现最新备份 还在窗内就不新建,连点删除共享一条历史、一步撤回。窗锚定在这一串的 第一下,不滚雪球;还原、导入、撤回重做不合并,各占一条。合并时没有 备份文件,重载失败的还原改用刚读出的原文写回。顺带消除了备份名只精 确到秒、同秒保存互相覆盖的隐患。
This commit is contained in:
+11
-1
@@ -14,6 +14,7 @@ import listenerFields from '../shared/listener-fields.json' with { type: 'json'
|
||||
import { isProviderFilePath } from '../shared/provider-files.ts'
|
||||
import {
|
||||
applyConfig,
|
||||
backupDiff,
|
||||
importConfig,
|
||||
listBackups,
|
||||
listRedo,
|
||||
@@ -186,7 +187,8 @@ function makeRoute(env: Env, token: string) {
|
||||
if (!body.data || typeof body.data !== 'object') {
|
||||
return json({ message: '请求缺少 data 字段' }, 400)
|
||||
}
|
||||
const result = await applyConfig(env, body.data, body.baseRevision)
|
||||
// merge:界面上的连续保存在时间窗内合并成一条历史。还原、导入不走这里
|
||||
const result = await applyConfig(env, body.data, body.baseRevision, { merge: true })
|
||||
return result.ok ? json(result) : json(result, applyFailureStatus(result.stage))
|
||||
}
|
||||
|
||||
@@ -231,6 +233,14 @@ function makeRoute(env: Env, token: string) {
|
||||
return result.ok ? json(result) : json(result, applyFailureStatus(result.stage))
|
||||
}
|
||||
|
||||
// 一条历史记录的对比原文:这份备份(改动前)和它之后的状态(改动后)
|
||||
const diffMatch = /^\/api\/config\/backups\/([^/]+)\/diff$/.exec(path)
|
||||
if (diffMatch && req.method === 'GET') {
|
||||
const pair = await backupDiff(env, decodeURIComponent(diffMatch[1]!))
|
||||
if (!pair) return json({ message: '没有这个备份', hint: '刷新一下历史记录再试。' }, 404)
|
||||
return json(pair)
|
||||
}
|
||||
|
||||
const restoreMatch = /^\/api\/config\/backups\/([^/]+)\/restore$/.exec(path)
|
||||
if (restoreMatch && req.method === 'POST') {
|
||||
const name = decodeURIComponent(restoreMatch[1]!)
|
||||
|
||||
Reference in New Issue
Block a user