Skip to content

新增独立 ZIP 档案库与可选 macOS App 构建 - #3

Open
LiuHangyuWE wants to merge 1 commit into
crownleo:mainfrom
LiuHangyuWE:feat/zip-archives-macos
Open

新增独立 ZIP 档案库与可选 macOS App 构建#3
LiuHangyuWE wants to merge 1 commit into
crownleo:mainfrom
LiuHangyuWE:feat/zip-archives-macos

Conversation

@LiuHangyuWE

@LiuHangyuWE LiuHangyuWE commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

现有导入会在同一查看状态中合并数据,本地缓存保存的是解析结果。本次新增可选的 ZIP 档案库:每份 ZIP 保留原始字节,切换档案时一起切换聊天、账户、记忆、收藏和标签,并可直接取出未经转换的 ZIP。原有临时导入和旧缓存入口继续保留;原来的 ZIP 解析、消息渲染和搜索功能继续复用。

浏览器档案库存放在独立的 IndexedDB 中。新增的 macos/ 目录提供可选的 AppKit/WebKit 外壳和构建脚本,开发者可以选择是否生成 Mac App;网页版本无需打包也能使用。Mac App 将原件及整理信息保存在 Application Support/ClaudeViewer/Archives,提供导入、切换、重命名、Finder 访问、原样取出和移至废纸篓等操作。

验证包含 12 项浏览器存储与控制器回归测试、原生档案存储与路径边界测试,以及 Apple Silicon 构建和签名检查。实际 Mac 操作验证了 ZIP 导入、独立账号切换、收藏隔离、文件夹刷新发现、原件逐字节一致导出、测试档案移除及重启恢复。测试数据与私人档案不进入提交。

档案库当前一次查看一份 ZIP。需要合并查看分片导出时,仍可使用原有临时导入方式。浏览器档案库受浏览器数据清理影响;Mac App 为本地构建并签名,不包含 Apple 公证。

@vercel

vercel Bot commented Sep 7, 2026

Copy link
Copy Markdown

@LiuHangyuWE is attempting to deploy a commit to the wanggchn-9639's projects Team on Vercel.

A member of the Team first needs to authorize it.

@LiuHangyuWE LiuHangyuWE closed this Sep 7, 2026
@LiuHangyuWE LiuHangyuWE changed the title feat: preserve original ZIP archives and add optional macOS App packaging 新增独立 ZIP 档案库与可选 macOS App 构建 Sep 7, 2026
@LiuHangyuWE LiuHangyuWE reopened this Sep 7, 2026
@LiuHangyuWE
LiuHangyuWE marked this pull request as ready for review September 7, 2026 11:38
crownleo added a commit that referenced this pull request Sep 8, 2026
Claude.ai 的数据导出在 2026 年 9 月改版:由一个 ZIP 变成 manifest JSON +
多个分类 ZIP,并新增 memories/{uuid}.json、reflections/、login_history.json
三类数据。旧的 classifyJson 三处硬编码文件名当场失效,记忆数据被静默丢弃。

本版同时把查看器推进到 ROADMAP 阶段 2「本地归档器」:一份档案 = 一次完整
导出的原始字节,多次备份并存、随时切换、原样取回。

数据层
- classifyJson 支持新版分片布局,旧版单 ZIP 完全兼容
- memory_files 自动并入全局记忆(旧版导出就有,此前从未被读取)
- 新增 reflections(Claude 官方月度回顾)与 login_history 解析
- 对话按 uuid 去重,分批 / 重复导入不再堆叠
- injected_prompt_block 渲染为折叠块,不再被丢弃

导入
- 新增导出文件夹一键导入(选择 + 拖入),复用 v5.6 的双读取后端
- manifest 只做完整性核对不做解析路由;缺片精确报出文件名
- 同一文件夹存在多份导出时可选择打开哪一份
- export_url 不解析、不显示、不请求

界面
- 新增「🪞 回顾」Tab;账户页新增登录记录;记忆 Tab 自动列出记忆文件
- 侧栏头部改两行布局,修复标题与摘要被图标按钮挤到截断换行
- 演示数据补齐回顾 / 登录记录 / 记忆文件

档案库
- 粒度 = 一次导出(manifest + N 个 ZIP),存原始字节于独立 IndexedDB
- 支持切换、重命名、整套导出、逐个取出原件、逐份移除
- 收藏与标签按档案隔离,重开浏览器自动恢复上次的档案
- 导入后的保存弹窗可直接「存入档案库」,不必重选同一批文件
- 自动申请 navigator.storage.persist(),面板显示占用 / 配额 / 获批状态

安全(部分采纳 PR #3)
- 新增 CSP:default-src 'none'; connect-src 'none',把「零外部请求」交由
  浏览器强制执行,并堵住正文外部 Markdown 图片这条跟踪与泄露渠道
- esc() 补全 " 与 ' 转义;清除全部内联 onclick 改为事件委托
- doSaveCache 改真 async 并上报失败(原先抢先置位且静默失败)
- openConv 回调竞态校验;按 appMode 分派查找,避免两模式 uuid 撞车
- ZIP 导入开启 CRC32 校验,检出下载损坏
- IndexedDB open 加超时,避免存储不可用时静默卡死

文档
- README 双语版本历史改为「版本 + 日期 + 要点」格式并同步 v6.0
- 新增 CONTRIBUTING.md:四条产品硬约束、不可手改区域、验证清单
- README 新增「清除浏览器数据会不会删掉聊天」专节与致谢
- ROADMAP 勾掉阶段 2 的对话去重与档案库,并记录格式变动带来的教训

Co-authored-by: LiuHangyuWE <2605172384@qq.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SKTFuLrcjestumEBb5U5wy
@crownleo

crownleo commented Sep 8, 2026

Copy link
Copy Markdown
Owner

你好,感谢这个 PR,这是 ClaudeViewer 收到的第一个有完整设计和测试的外部贡献,我认真读完了。先说结论:档案库的方向我认可,并且会做进 v6.0,但数据模型需要调整;另外 PR 里有几处改动质量很好、和档案库无关,我想先单独合掉。

一、一个上游变化,不是你的问题

就在这个 PR 提交前后,Claude.ai 的数据导出格式变了:从一个 ZIP变成了 manifest JSON + 多个分类 ZIP。我拿 2026-09-07 的真实导出实测:

ZIP 内部路径 变化
conversations-000.zip conversations.json 不变
projects-000.zip projects/{uuid}.json 不变
light_metadata-000.zip users.json + login_history.json 新增登录历史
memories-000.zip memories/{uuid}.json 路径与结构都变了(对象,非数组)
feedback-000.zip reflections/{uuid}.json 新类别

manifest 里还有 part 字段——大账号的 conversations 会切成 -000 / -001 / -002

你写这个 PR 的时候「一个 ZIP = 一次导出」是成立的,所以这不是设计失误,是上游把地基挪了。

二、因此档案粒度需要升一级

现在 validateZip() 要求每个 ZIP 都含 conversations.json

if (!conversations) throw new Error('ZIP 中没有有效的 conversations.json');

拿新导出去跑:conversations-000.zip 能进但只有对话(项目/账户/记忆全丢),另外 4 个 ZIP 全被拒。用户的一次备份会变成「五个碎片,四个进不去」。

所以档案记录需要从「一个 ZIP」改成「一次导出」——即 manifest + N 个 ZIP 的一整套,切换时整体换掉。校验规则相应改为「这一套里至少有一个 conversations 分片,其余按各自 category 校验」。

三、v6.0 已发布,你的贡献已经采纳进去了

Release:https://github.com/crownleo/ClaudeViewer/releases/tag/v6.0

不用再拆 PR 了——这些改动我已经直接搬进 v6.0,并在 commit 里用 Co-authored-by 署了你的名,README 也加了致谢段落。

直接采用你的代码:

  • esc()" / ' 转义
  • 内联 onclick 全部改为 data-* + 事件委托——顺带堵上了 onclick="openConvById('${a.uuid}')" 里 uuid 未转义拼进属性的口子
  • doSaveCache() 改为真 async + 失败告知(原来 isCached=true 抢在写入前就置位,保存失败用户完全不知情)
  • openConv 回调竞态校验
  • openConvappMode 分派查找
  • JSZip checkCRC32:true——新格式要下 5 个文件,这个能直接检出下载损坏,很实用

采用你的设计:

  • 档案库整体思路——原始字节保真、多档案切换、重命名、取出原件、收藏与标签按档案隔离,以及面板的焦点陷阱 / Escape / aria-live 无障碍处理,都来自这个 PR。数据模型按上面说的换成了「一次导出(manifest + N 个 ZIP)」粒度,validateZip 相应改为「整套里至少有一个 conversations 分片,其余按各自 category 校验」。
  • 另外顺着你的思路多做了两点:导入成功的弹窗直接给「📚 存入档案库」(不必再去档案库重选同一批文件),以及自动申请 navigator.storage.persist() 并在面板里显示占用 / 配额 / 获批状态。

因为这个 PR 同时含档案库、独立修复和 macOS 三部分,且档案库需要换数据模型,没办法整体合并,最后是按上面的方式分别落地的。这个 PR 本身就先放着,你如果还想接着做档案库、或者有别的想法,随时提新的。

顺带一提,我把项目的硬约束整理成了 CONTRIBUTING.md——本地优先 / 单文件优先 / 零外部请求 / file:// 必须可用,外加「一个 PR 只做一件事」和验证清单。这次让你在 macOS 那块花了不少功夫却暂时用不上,是我文档没做到位。

四、关于桌面 App

macOS 这块我先搁置,不是否定,是时机和范围的问题:

  • 我的主力开发机是 Windows,build.pyplatform.system() != "Darwin" 直接退出,我连构建都跑不了,也就无法验证。收进主仓的话,往后每次改 claude_viewer.html 都会成为我看不见的悬空风险。
  • 如果真要做桌面版,我倾向 macOS 和 Windows 一起做,只有 Mac 版会让另一半用户的体验割裂。

所以先放着,等后面看实际需求——如果确实有较多用户需要桌面版,我们再一起讨论怎么做,到时候你这套 AppKit/WebKit 外壳会是很好的起点。这期间你完全可以先开一个独立仓库放着,我在主仓 README 里给链接。

对了,验证时有个发现可能对你有用:ClaudeArchiveLibrary 那套在 file:// 下是能跑的——我一度以为 Chromium 会在 file:// 禁掉 IndexedDB,实测(CDP 真实驱动,非 headless 虚拟时间)发现存 Blob 都正常。所以档案库不必依赖原生外壳也能持久保存原件。

再次感谢,这个 PR 的完成度(12 项回归测试、无障碍处理、原件字节保真)比我预期高很多。

Copy link
Copy Markdown
Contributor Author

谢谢你认真审阅、整合贡献和保留署名。把档案单位调整为「一次完整导出」很合理,也谢谢你补充 file:// 下 IndexedDB 的实测结果。

关于桌面版,我想补充一下自己的使用场景和贡献范围:我是 Apple Silicon Mac 用户,这次的 App 是在自己的 Mac 上构建和实际使用、测试的。我目前只打算做和测试 macOS 这一侧,没有 Windows 测试环境,也无法承诺提供或维护 Windows 版。我理解你希望两个平台都有桌面体验,不过想建议允许平台支持逐步补齐:如果以后有 Windows 贡献者,可以再接上,不必把两端同时完成作为 Mac 版可用的前提。

我希望保留 App 的原因,主要是能从应用程序/Dock 直接启动,并把导出的原始文件放在 Application Support/ClaudeViewer/Archives 这样的普通目录里,随时通过 Finder 查看、备份和原样取出。浏览器档案库可以持久保存原件,这一点我理解;原生目录仍然符合我自己的档案管理习惯。

想和你商量一个组织方式:主项目是否可以同时提供单文件网页版,以及由 Mac 贡献者提供构建和实机验证的可选 macOS 打包入口?两者尽量共用同一份网页核心,主仓若接受,只收 Mac 外壳、适配代码、构建脚本和说明,编译好的 App 则作为单独的发布产物提供。这样用户可以按需选择,也不需要你在 Windows 上承担无法完成的 Mac 实机验证。

我也理解这仍然有接口兼容和审阅成本。现有 Mac 实现还是旧版单 ZIP 档案模型,并没有完成 v6.0 的适配,不能直接换一个 HTML 就宣称兼容。如果继续做,会需要跟随你现在「一次完整导出」的模型,尽量复用解析和渲染逻辑,并明确每个 Mac 发布对应、实测通过的上游版本。

我看到新的 CONTRIBUTING.md 写了重型能力作为可选伴侣、不进主仓。所以想先确认,你是否愿意讨论把这种可选 Mac 外壳作为同仓的例外;如果原生包装也统一放在主仓之外,我们就可以沿着你建议的独立 Mac 伴侣仓库方向讨论,通过主仓 README 链接让用户找到。也希望听听你对这两种组织方式的偏好。

Copy link
Copy Markdown
Contributor Author

再补充一个我前面没有讲清楚的使用目标:我希望档案库像一个可以随时拿走的资料柜。不同账号的备份各自独立,同一账号不同日期的备份也可以分别保留;切换档案时,聊天、账户信息、收藏和标签一起切换。我不希望把不同账号的记录自动合并成一个总库。原来「一个 ZIP 一档案」是在用文件边界实现这个隔离,并不是认为一次导出只能永远有一个 ZIP。

所以你提出的「一次完整导出=manifest+多个 ZIP」与这个目标是相容的。我这边正在调整 Mac 实现:一份导出目录作为一份档案,多个目录分别加入;旧版完整 ZIP 仍可单独加入。对于归属不明确的分类 ZIP,会引导选择整份导出目录,避免把不同账号的同名分片误放进同一档案。这是按导出边界隔离,也不把它宣传成已经能够自动识别所有账号。

Mac 侧想保留的特点是:导入时把原始文件复制到 Application Support/ClaudeViewer/Archives,仍以那里的原件作为数据源;原件和收藏、标签等整理信息分开存放。用户也可以按约定把独立导出目录放进去,再刷新发现,或者在 Finder 中直接完整拿走原件。普通删除 App 不应带走这些资料。这样将来不用这个 App,数据仍是普通文件,可以交给其他查看器读取。适配会以复用 v6.0 的解析和显示逻辑为方向,本地验证完成后再讨论具体的提交或独立发布方式。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants