Skip to content

✨ 完善备份/还原/导入完整性:SC/TM/VM 自定义配置 + 设置备份 + 资源修复#1554

Open
CodFrm wants to merge 21 commits into
mainfrom
worktree-backup-restore-completeness
Open

✨ 完善备份/还原/导入完整性:SC/TM/VM 自定义配置 + 设置备份 + 资源修复#1554
CodFrm wants to merge 21 commits into
mainfrom
worktree-backup-restore-completeness

Conversation

@CodFrm

@CodFrm CodFrm commented Jul 8, 2026

Copy link
Copy Markdown
Member

Checklist / 检查清单

  • Fixes mentioned issues / 修复已提及的问题
  • Code reviewed by human / 代码通过人工检查
  • Changes tested / 已完成测试

Description / 描述

系统性完善备份 / 还原 / 导入的完整性,覆盖 ScriptCat / Tampermonkey / Violentmonkey 三种格式,并把「设置」纳入备份范围。不涉及云同步。

Closes #1483
Closes #1484
Closes #1529
Closes #1533
Closes #684
Closes #841
Closes #1150

相关(部分):#1525 —— 本 PR 完成了「导入导出配置」诉求(设置随主备份往返),但其中「WebDAV 配置合并/共用、导出携带 WebDAV 凭据」属于云同步范畴,本 PR 有意排除,故不关闭。

脚本层

设置层(#1533 / #684

  • 备份范围扩大到 SystemConfig + Agent 模型 / MCP / 定时任务,随主备份 zip 往返(scriptcat-config.json)。
  • 导入页新增「同时还原设置」开关。
  • 安全:云同步 / WebDAV 凭据键(cloud_sync / backup / cat_file_storage)在序列化时排除,不随明文 zip 外泄。
  • 设置属于备份的一部分,未做成独立的配置导出/导入入口。

资源与覆盖

测试与验证

  • 单测:新增 backup / import / resource 相关用例;pnpm typecheck + 改动文件 lint 全绿。
  • 本地 e2e(真实 dist/ext,一次性 scratch 脚本,不进 CI):5 个端到端场景全绿 —— SC 往返、VM 导入、TM 导入、设置往返、覆盖模式。

Screenshots / 截图

本地 e2e 录屏(真实扩展驱动,git-ignored 本地证据)已覆盖全部 5 条操作流程:SC 备份往返、VM 导入归一化、TM override→selfMetadata 推导、设置随主备份往返、覆盖导入。合入前可补贴录屏 / 截图。

backup-restore.zip

@CodFrm

CodFrm commented Jul 10, 2026

Copy link
Copy Markdown
Member Author

人工验收清单

本清单用于逐项人工确认;完成并符合预期后再勾选。建议在回复中记录浏览器版本、测试 commit、截图/录屏或日志。

0. 环境

  • pnpm run typecheck 通过
  • pnpm test 通过
  • pnpm run dev 后重新加载 dist/ext,扩展正常启动
  • Chrome/Chromium MV3 完成一次完整导出与导入
  • Edge MV3 完成一次完整导出与导入(重点观察资源恢复)
  • 浅色、深色主题下导入页均可正常操作
  • 桌面宽屏、窄窗口/移动布局均无按钮遮挡或无法勾选

1. ScriptCat 自定义配置往返

前置:脚本原始元数据含 match/include/exclude/connect/run-at,安装后在 ScriptCat 修改自定义规则。

  • ZIP 可被 ScriptCat 正常重新识别
  • 自定义 match 完整保留
  • 自定义 include 完整保留
  • 自定义 exclude 完整保留
  • 自定义 connect 完整保留
  • 自定义 run-at 完整保留
  • noframes 完整保留
  • 设置页显示值与备份前一致
  • 实际匹配/排除页面的执行行为符合恢复配置
  • noframes 开启后不在子 frame 执行
  • document-start 等运行时机实际符合配置
  • 自定义规则无重复项
  • 启用/禁用状态与备份前一致
  • 脚本排序位置与备份前一致

2. 替换、合并和空列表

  • “合并”恢复为“原始规则 ∪ 用户新增规则”
  • “替换”恢复后不混入被替换的原始规则
  • 替换列表只有一项时仍只有该项
  • 替换列表为空时保持空列表,不回退为原始规则
  • 未自定义字段不会无故生成 selfMetadata 覆盖原始元数据

3. GM 值

  • 字符串值恢复正确
  • 数字值恢复正确,未退化为字符串
  • 布尔值恢复正确,未退化为字符串
  • 对象/数组及嵌套结构恢复正确
  • 中文、空字符串、特殊字符恢复正确
  • 多脚本之间没有值串用
  • 完成页数据统计正确

4. Tampermonkey 合并语义

  • use_matches 与原始 match 正确合并
  • use_includes 与原始 include 正确合并
  • use_excludes 与原始 exclude 正确合并
  • use_connects 与原始 connect 正确合并
  • 相同规则合并后不重复
  • run_at=document-start 正确转换
  • body/end/idle 至少抽测一项
  • noframes=true 正确恢复
  • 实际运行范围与设置页一致

5. Tampermonkey 替换语义

  • 替换 match 后不残留原始 match
  • 替换 include 后不残留原始 include
  • 替换 exclude 后不残留原始 exclude
  • 替换 connect 后不残留原始 connect
  • 用户设置的新规则完整保留
  • 替换列表为空时保持空列表
  • 原始规则页面不再错误执行
  • 替换后规则页面正常执行

6. Violentmonkey 导入

  • VM 根清单与对应 .user.js 正确关联
  • custom match/include/exclude 正确恢复
  • excludeMatch 正确合并到排除规则
  • origMatch/origInclude/origExclude 的合并/替换语义正确
  • runAt、noframes 正确恢复
  • 启用脚本保持启用
  • 禁用脚本保持禁用
  • position 正确反映到排序
  • 字符串、数字、布尔、对象/数组值正确恢复
  • 名称或 namespace 含中文、空格、特殊字符时 values 仍关联正确
  • 多脚本之间没有值串用
  • 实际匹配/排除行为符合配置

7. 设置随本地 ZIP 往返

  • ZIP 中存在 scriptcat-config.json
  • 含设置时显示“同时还原设置”
  • “同时还原设置”默认勾选
  • 普通 SystemConfig 恢复
  • Agent 模型恢复
  • MCP Server 恢复
  • Agent 定时任务恢复
  • 同 ID 项更新且不产生意外重复
  • 备份中不存在的当前项目仍保留,符合合并语义
  • 重复导入不会不断生成重复项
  • 设置恢复不阻断脚本/订阅/数据导入
  • 完成统计不把设置计入脚本或数据数量
  • 没有独立“导出配置/导入配置”入口

8. 取消还原设置

  • 可以取消“同时还原设置”
  • 取消后脚本、自定义配置、GM 值仍正常导入
  • 取消后当前普通设置保持不变
  • 取消后当前 Agent/MCP/任务保持不变

9. 敏感配置排除

使用唯一假标记 MANUAL_TEST_SECRET_1554,不要使用真实凭据。

  • scriptcat-config.json 中不存在 cloud_sync
  • 不存在 backup 的凭据内容
  • 不存在 cat_file_storage
  • 全文搜索找不到假标记
  • ZIP 中不存在 WebDAV 密码、Token 等明文值
  • 排除敏感项后普通设置仍存在
  • 恢复不会覆盖或清空当前 WebDAV/云同步凭据
  • 确认本 PR 不包含 [Feature] 导入导出功能 包括webdav 配置 #1525 的 WebDAV 凭据导出/配置共用
rg -n "MANUAL_TEST_SECRET_1554|cloud_sync|cat_file_storage" /path/to/unzipped-backup

10. 覆盖导入

前置:本地有 A~J,备份只有 A~E。

  • “导入前删除所有本地脚本”默认未勾选
  • 勾选并选择 A~E 后最终只保留 A~E
  • 本地独有 F~J 被删除
  • A~E 使用备份版本且不重复
  • 勾选但只选择 A、B 时最终只保留 A、B
  • 不误删普通设置、Agent 配置或无关存储
  • 设置恢复仍只由“同时还原设置”控制
  • 点击导入前取消/关闭不会提前删除脚本
  • 单脚本失败时流程仍能结束并如实显示

11. 默认合并导入

  • 不勾选覆盖时 A~E 正常新增/更新
  • 本地独有 F~J 全部保留
  • 默认行为与旧版合并语义一致
  • 已存在脚本更新后不重复

12. 文本资源

  • 删除脚本后断网导入,文本资源仍恢复
  • @require 提供的函数可调用
  • require-css 可应用
  • 新资源实际持久化,不只是内存缓存
  • 重启浏览器后仍可用
  • 成功时显示“已导入”,不是“已跳过”

13. 二进制资源

  • 删除脚本后断网导入,二进制资源仍恢复
  • GM_getResourceURL 返回有效 URL
  • 图片正常解码,宽高正确
  • 字体等内容未被按文本损坏
  • Blob/content type 合理
  • 重启浏览器后仍可用
  • Edge 上复测通过

14. 单资源失败提示

  • 单资源失败不导致脚本本体失败
  • 同脚本正常资源仍可用
  • 显示 warning/“部分资源失败”,不是“已跳过”
  • Tooltip 显示“以下资源导入失败:”
  • Tooltip 显示失败资源名,无名称时显示 URL
  • 不影响其他脚本
  • 流程正常进入完成页
  • 后台日志含 UUID/资源 URL
  • 下一轮导入不残留 warning

15. 兼容性

  • 旧版 ScriptCat ZIP(无配置文件)可正常导入
  • 老备份不显示“同时还原设置”
  • 老备份无 selfMeta 时使用原始元数据
  • 老备份不修改当前设置
  • 纯 TM ZIP 不显示“同时还原设置”
  • 纯 VM ZIP 不显示“同时还原设置”
  • 未知文件不被误判为设置
  • 无配置 bundle 时仍可使用覆盖模式

16. 导入页交互

  • 单选/全选/取消全选正常
  • 两个新开关互相独立
  • 切换选择项不重置开关
  • pending/importing/done/skipped/warning 正确
  • 不可导入项显示“已跳过”
  • 完成数量不大于总数
  • 完成页统计正确
  • Tab/Space 可操作复选框
  • 长文案语言下仍可操作
  • warning/Tooltip 在明暗主题均清晰

17. 设置恢复异常隔离

  • 设置恢复异常时正常脚本仍导入
  • 脚本不误显示“已跳过”
  • 页面不会卡死
  • 日志可定位失败
  • UI 是否提示失败已记录;若静默失败,由维护者明确判断是否接受

18. 云端备份边界(有测试 WebDAV 时)

  • 自定义 match/exclude/run-at/noframes 经云备份恢复后仍存在
  • 云恢复不覆盖/清空 WebDAV 或云同步凭据
  • 普通设置 bundle 未被误认为支持云端往返
  • 结论明确不包含 WebDAV 凭据导出和云配置合并

19. 最终结论

  • SC/TM/VM 均完成至少一次真实导入
  • 文本和二进制资源完成断网恢复及重启复测
  • 敏感信息排除经过解压和全文搜索
  • 覆盖模式的数据删除行为已人工确认
  • 未通过/未执行项均补充原因、日志或后续 issue
  • 人工验收通过,可以合入

建议证据放在本地 test-results/verify/backup-restore-1554/,或回复本评论附截图/录屏;不要上传真实账号、密码或 Token。

@CodFrm CodFrm requested a review from Copilot July 10, 2026 05:55
@CodFrm CodFrm marked this pull request as ready for review July 10, 2026 05:56

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

该 PR 系统性增强了 ScriptCat 的「备份 / 还原 / 导入」完整性:在脚本层面补齐 SC/TM/VM 三种来源的自定义配置往返与归一化导入;在设置层面把 SystemConfig 与 Agent(模型/MCP/任务)纳入同一个主备份 zip 往返;并修复资源导入落库与失败回显能力,配合导入页 UI 支持覆盖导入与按板块选择还原设置。

Changes:

  • 新增 selfMetadata 归一化管线:SC 备份无损往返;TM/VM 导入按 merge/replace 语义推导为 SC 形状后统一落库。
  • 新增设置备份 scriptcat-config.json(ConfigBundle)并在导入页支持“同时还原设置”与按板块筛选还原(含 Agent 配置)。
  • 资源导入改为 save 以确保新资源可落库,并在导入 UI 中对“脚本已导入但部分资源失败”进行 warning 状态与逐项提示。

Reviewed changes

Copilot reviewed 34 out of 34 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/pkg/backup/struct.ts 扩展备份结构:脚本 settings 增加 checkUpdate?、引入 selfMeta?config?,新增 VM 根清单类型
src/pkg/backup/self_metadata.ts 新增 override/custom → selfMetadata 归一化与 VM values 键编码工具
src/pkg/backup/self_metadata.test.ts 覆盖 merge/replace 语义、VM custom 归一化与 values uri 编码测试
src/pkg/backup/import.ts 导入流程支持解析 scriptcat-config.json;增强 VM 根清单导入(enabled/position/selfMeta/values/file_url/checkUpdate)
src/pkg/backup/import.test.ts VM 导入归一化与 config bundle 容错测试
src/pkg/backup/export.ts 备份导出时可选写入 scriptcat-config.json
src/pkg/backup/config_sections.ts 新增设置板块划分与按板块过滤 ConfigBundle 的逻辑
src/pkg/backup/config_sections.test.ts 板块分类/计数与过滤逻辑测试
src/pkg/backup/config_bundle.ts 定义 ConfigBundle 结构、版本校验与过滤本机相关键(STORAGE_LOCAL_KEYS)
src/pkg/backup/config_bundle.test.ts ConfigBundle 解析与过滤规则测试
src/pkg/backup/backup.test.ts 补充 selfMeta 与 config bundle 往返测试
src/pages/import/mobile.tsx 移动端导入页:资源失败 warning 回显;覆盖导入开关;设置还原板块选择(Sheet)与导入按钮文案/可用性更新
src/pages/import/mobile.test.tsx 移动端:设置板块选中时可导入;打开设置自定义面板的可访问性标题断言
src/pages/import/logic.ts 新增 deriveSelfMetadata:SC 直接用 selfMeta;TM 从 override 推导;VM 由 import.ts 预置
src/pages/import/logic.test.ts deriveSelfMetadata 行为测试
src/pages/import/hooks.ts 导入编排增强:覆盖导入(导入前清空脚本);导入时覆盖 selfMetadata;资源失败列表回显;设置板块选择与还原调用
src/pages/import/hooks.test.ts useImport:设置-only 备份可导入;板块默认不勾选;restoreConfigBundle 调用与 checkUpdate/selfMetadata 覆盖相关断言
src/pages/import/components.tsx 桌面端导入页:warning 状态与 tooltip;覆盖导入;设置板块 Popover 选择控件;导入按钮文案/可用性更新
src/pages/import/components.test.tsx 桌面端:设置板块选中可导入;设置触发器点击行为测试
src/pages/components/ui/popover.tsx UI 组件补充 PopoverAnchor 导出以支持自定义触发结构
src/locales/zh-TW/install.json 新增资源失败/覆盖导入/设置还原相关文案与按钮文案;调整 trust_hint
src/locales/zh-CN/install.json 同上(简体中文)
src/locales/en-US/install.json 同上(英文)
src/locales/de-DE/install.json 同上(德文)
src/locales/ja-JP/install.json 同上(日文)
src/locales/ru-RU/install.json 同上(俄文)
src/locales/tr-TR/install.json 同上(土耳其文)
src/locales/vi-VN/install.json 同上(越南文)
src/app/service/service_worker/synchronize.ts 备份导出可选包含 ConfigBundle;新增 get/restore ConfigBundle;资源导入返回失败清单;导出/云备份默认带设置;注册 restoreConfigBundle 消息
src/app/service/service_worker/synchronize.test.ts 覆盖“云端备份也带设置”、默认/摘要模型选择往返、systemConfig 过滤与写回 sync storage 测试
src/app/service/service_worker/script.ts 安装参数新增 overwriteSelfMetadata,用于备份导入覆盖本地自定义元数据
src/app/service/service_worker/resource.ts 资源导入支持二进制(base64);并改用 save 确保新资源可落库
src/app/service/service_worker/resource.test.ts 覆盖二进制/文本资源导入测试
src/app/service/service_worker/client.ts SynchronizeClient:importResources 改为返回失败列表;新增 restoreConfigBundle RPC

Comment on lines 427 to 431
async importResource(uuid: string, data: ResourceBackup, type: ResourceType) {
// 导入资源
if (!data.source) {
// 导入资源:文本资源用 source,二进制资源(如图片/字体)只有 base64(dataURI)
if (!data.source && !data.base64) {
return undefined;
}
Comment on lines +145 to +154
const sync = new ChromeStorage("system", true);
const modelRepo = new AgentModelRepo();
const mcpRepo = new MCPServerRepo();
const taskRepo = new AgentTaskRepo();
await Promise.all([
...Object.entries(bundle.systemConfig || {}).map(([k, v]) => sync.set(k, v)),
...(bundle.agent?.models || []).map((m) => modelRepo.saveModel(m)),
...(bundle.agent?.mcp || []).map((m) => mcpRepo.saveServer(m)),
...(bundle.agent?.tasks || []).map((t) => taskRepo.saveTask(t)),
]);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment