feat(skill-addresses): 新增技能地址修改记录,支持单次记录回退
后端:
- 每次「应用」写一份 {id}.manifest.json(记录本次 from→to 替换明细/文件数/处数),
放在备份目录的同级,避免被回退误恢复或计入文件数
- GET /backups 返回每条记录的 replaced_total + replacements;POST /rollback/{id} 回退单条
前端:
- 把「撤销上次」升级为「修改记录」面板:每条显示时间/改了哪些地址/文件数,
带「回退此次」(二次确认);应用后自动展开
- BackupEntry 类型扩展 replacedTotal + replacements
同步更新前后端 CLAUDE.md。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
7487395e44
commit
06b169d7a1
5 files changed
+245
-28
No files matched your search
@@ -80,10 +80,18 @@ export interface ApplyResult {
|
||||
warnings: string[];
|
||||
}
|
||||
|
||||
export interface BackupReplacement {
|
||||
from: string;
|
||||
to: string;
|
||||
kind: AddressKind;
|
||||
}
|
||||
|
||||
export interface BackupEntry {
|
||||
backupId: string;
|
||||
files: number;
|
||||
createdAt: string;
|
||||
replacedTotal: number;
|
||||
replacements: BackupReplacement[];
|
||||
}
|
||||
|
||||
/** 扫描进度(逐技能)。 */
|
||||
@@ -249,7 +257,13 @@ export async function applyReplacementsStream(
|
||||
export async function listBackups(): Promise<BackupEntry[]> {
|
||||
const res = await apiFetch(`${BASE()}/backups`, { method: "GET" });
|
||||
const data = await readJson<{ backups: any[] }>(res, "读取备份");
|
||||
return (data.backups ?? []).map((b) => ({ backupId: b.backup_id, files: b.files ?? 0, createdAt: b.created_at ?? "" }));
|
||||
return (data.backups ?? []).map((b) => ({
|
||||
backupId: b.backup_id,
|
||||
files: b.files ?? 0,
|
||||
createdAt: b.created_at ?? "",
|
||||
replacedTotal: b.replaced_total ?? 0,
|
||||
replacements: (b.replacements ?? []).map((r: any) => ({ from: r.from, to: r.to, kind: r.kind })),
|
||||
}));
|
||||
}
|
||||
|
||||
export async function rollbackBackup(backupId: string): Promise<{ restored: number }> {
|
||||
|
||||
Reference in new issue
Block a user