Voyager Data Viewer 全解析:在浏览器本地导入与预览文件夹导出数据

原创2026-10-10 02:52:4411 阅读
文章标签:AI 应用前端插件系统提示工程

Voyager Data Viewer 全解析:在浏览器本地导入与预览文件夹导出数据

本文围绕 Voyager 官方文档中的 Data Viewer 页面 展开,讲解如何把 Voyager 扩展导出的文件夹数据(gemini-voyager.folders.v1)在浏览器中离线导入并预览,涵盖交互流程、JSON 数据格式、版本兼容规则以及文档站点与扩展端两侧的源码实现。读完本文,你将理解该数据格式的每个字段含义,掌握导入、校验、浏览与清理数据的完整操作,并能在自己的项目中复刻这套"本地数据查看器"方案。

一、Data Viewer 是什么

Data Viewer 是 Voyager 官方文档站内置的一个纯前端数据查看器:导入从 Voyager 扩展导出的文件夹 JSON 文件后,即可在浏览器中直接查看你的文件夹层级结构和对话列表,无需安装任何额外工具。

它的核心特性由文档站首页描述与源码共同确认:

  • 导入即预览:支持拖拽 JSON 文件到页面,或点击按钮选择文件,随后自动渲染出文件夹树与对话清单;
  • 纯本地处理:文件通过浏览器 FileReader 读取,预览数据仅缓存在当前浏览器的 localStorage 中,不会上传到任何服务器;
  • 零依赖使用:查看器是一个注册为 <FolderViewer /> 的 Vue 组件(见 组件注册),直接内嵌在文档页面中渲染。

适用场景非常直接:导出文件夹数据做迁移前核对、备份完整性检查、跨设备预览组织结构,或者把数据交给不安装扩展的人查看。与 Voyager 的导出能力和文件夹功能配合,就形成了一条"组织 → 导出 → 离线审阅"的完整数据链路。

二、快速上手:三步完成导入与预览

1. 从 Voyager 扩展导出文件夹数据

在 Voyager 扩展的文件夹管理界面中导出数据(扩展端导出实现见 FolderImportExportService.ts)。导出的文件默认按如下格式命名(见 generateExportFilename):

gemini-voyager-folders-YYYYMMDD-HHmmss.json

例如 gemini-voyager-folders-20261009-153000.json。文件由扩展端以 application/json;charset=utf-8 类型通过 Blob 下载生成(见 downloadJSON),内容为格式化(2 空格缩进)的 JSON。

2. 在 Data Viewer 页面导入

打开 Data Viewer 页面后,页面会显示一个虚线框的上传区(源码见 FolderViewer.vue):

  • 拖拽导入:直接把 .json 文件拖入虚线框,松开即触发解析;
  • 点击选择:点击虚线框或"浏览文件"按钮,从文件选择器中选取文件;
  • 格式约束:仅接受 .json 后缀文件,其他扩展名会被直接判为格式无效(见 handleFile)。

导入成功后页面自动展开全部文件夹,并在顶部显示统计信息。

3. 解读预览界面

预览界面分为三块(见 FolderViewer.vue):

界面区域 内容说明
顶部统计栏 文件夹总数、对话总数、导出时间(exportedAt)、数据版本(version)
操作按钮 全部展开(+)、全部收起(−)、重新导入、清除数据
树形列表 文件夹行 + 对话行,支持点击文件夹行展开/收起子级

对话行展示的要素包括:

  • 标题:优先显示 title,为空时回退显示 conversationId;
  • 星标:starred: true 的对话前显示 ★ 标记;
  • Gem 标记:isGem: true 的对话显示 "Gem" 标签;
  • 加入时间:按 addedAt 本地化格式化显示;
  • 可点击跳转:整行是链接,点击后以新标签页打开该对话(target="_blank" + rel="noopener noreferrer",见 对话行模板)。

文件夹行则会显示:展开箭头、文件夹名、对话数量统计,以及两类特殊标签——Pinned(已置顶,pinned: true)和 Project(设置了 instructions 的"文件夹即项目")。

三、数据格式详解:gemini-voyager.folders.v1

Data Viewer 只接受 Voyager 扩展导出的文件夹格式,格式标识符为 gemini-voyager.folders.v1。该格式在扩展端与查看器两端保持一致:类型定义见 sync.ts 与 FolderViewer.vue 的接口声明。

顶层结构

{
  "format": "gemini-voyager.folders.v1",
  "exportedAt": "2026-10-09T15:30:00.000Z",
  "version": "2.4.1",
  "platform": "chatgpt",
  "data": {
    "folders": [],
    "folderContents": {}
  }
}
字段 类型 说明
format string 固定为 gemini-voyager.folders.v1,用于识别格式并做兼容性判断
exportedAt string ISO 8601 时间戳,导出时间
version string 导出时扩展版本号,来自 manifest.json(见 version.ts)
platform string(可选) 数据来源标记,目前仅 ChatGPT 导出会写入 "chatgpt";Gemini 与 AI Studio 的导出不带此字段(见 exportedPlatform)
data object 主体数据,含 folders 与 folderContents 两个成员

data.folders:文件夹数组

查看器侧接受的文件夹字段(见 Folder 接口):

字段 类型 说明
id string 文件夹唯一标识(持久化 ID,可能是历史或导入产生的任意字符串)
name string 文件夹名称
parentId string | null 父文件夹 ID;为 null 表示顶级文件夹,据此构建树形层级
pinned boolean(可选) 是否置顶
color string(可选) 自定义颜色
sortIndex number(可选) 同级排序权重,升序排列
createdAt / updatedAt number 创建/更新时间戳(毫秒)
instructions string(可选) 文件夹即项目(Folder as Project)的指令文本

扩展端存储的完整 Folder 类型还额外包含 isExpanded 字段,见 folder.ts。

data.folderContents:对话归属映射

{
  "folderContents": {
    "f_001": [
      {
        "conversationId": "conv_abc123",
        "title": "Agentic workflows 调研",
        "url": "https://gemini.google.com/app/conv_abc123",
        "addedAt": 1720000000000,
        "isGem": true,
        "starred": false,
        "sortIndex": 0
      }
    ]
  }
}
字段 类型 说明
conversationId string 对话标识
title string 对话标题,为空时界面回退显示 conversationId
url string 对话链接,预览界面点击跳转
addedAt number 加入文件夹的时间戳
isGem boolean(可选) 是否为 Gem 对话
starred boolean(可选) 是否在文件夹内加星
sortIndex number(可选) 对话在文件夹内的排序权重

完整字段(含 gemId、customTitle、lastOpenedAt、lastTurnAt 等可选元数据)见扩展端类型 folder.ts。未被任何文件夹引用的键所对应的对话,会被查看器集中归入"未归类对话(Unfiled conversations)"分组显示(见 unfiled 处理逻辑)。

四、版本兼容与格式校验

Data Viewer 页面本身只做两层校验(见 loadPayload):

  1. format 必须严格等于 gemini-voyager.folders.v1;
  2. data.folders 与 data.folderContents 必须都存在。

不满足时页面显示"格式无效"提示;JSON.parse 抛异常时显示"解析失败"提示。

而扩展端导入的校验更为严格,位于 validatePayload,还会额外检查:

  • 格式是否受支持:isSupportedFormat 判断 format 是否在注册表中(见 version.ts);
  • 版本是否兼容:getCompatibilityInfo 解析 version 并比较。gemini-voyager.folders.v1 的最低兼容扩展版本为 0.7.0(FORMAT_VERSIONS 常量),低于该版本或版本号非法都会被拒绝;
  • 必填字段:data 缺失、folders / folderContents 结构错误等均会给出明确的错误分类(ValidationErrorType)。

也就是说:Data Viewer 是"宽容"的查看器,扩展端是"严格"的导入器——前者只关心能否渲染,后者还关心能否安全合并回你的文件夹体系。版本比较逻辑(含预发布版本处理)与未来的数据迁移注册表(VERSION_MIGRATIONS)都在 version.ts 中。

五、源码级原理:FolderViewer 组件如何工作

查看器全部逻辑位于 docs/.vitepress/theme/components/FolderViewer.vue,由 index.ts 注册为全局组件 <FolderViewer />。核心机制如下。

1. 树形构建与排序

buildTree(L243-L268)先按 id 建索引,再依据 parentId 把节点挂到父节点下(父节点不存在或 parentId 为 null 则视为根),随后对根节点与每个父节点的子级都按 sortIndex 升序排序;每个文件夹下挂载的对话也按 sortIndex 排序。折叠状态由 expandedIds(Set)维护,flattenTree 递归展开为扁平行供模板渲染,空文件夹展开后显示"空文件夹"占位行。

2. 未归类对话的识别

查看器把 folderContents 中所有键不在 folders 的 id 集合里的对话提取出来,渲染为一个特殊的"未归类对话"分组(UNFILED_ID = '__unfiled__')。这正好对应扩展侧的一种真实数据形态:当文件夹被删除或数据不完整时,对话引用仍可能残留。

3. 本地缓存与隐私边界

导入成功后,原始 JSON 字符串会写入 localStorage(键名为 gv-folder-viewer-data,见 L48);页面加载时会自动恢复上次数据(onMounted)。点击"清除数据"则同时清空页面状态与缓存(clearData)。

这条链路完整印证了文档的隐私承诺:文件读取(FileReader)→ 内存解析 → localStorage 持久化,全程发生在浏览器本地,无任何网络请求。

4. 多语言

界面文案内置 10 种语言(zh-CN、zh-TW、en-US、ja-JP、ko-KR、fr-FR、es-ES、pt-PT、ar-SA、ru-RU),跟随文档站点语言自动切换,未匹配时回退英文(i18n 表)。

六、扩展端如何生成这份 JSON

理解数据格式的源头,有助于你确认导出文件的正确性。扩展端文件夹导入/导出服务(FolderImportExportService.ts)是主要生成方:

  • exportToPayload(L42-L52):把 FolderData(含 folders 与 folderContents)包装为 gemini-voyager.folders.v1 载荷,exportedAt 取当前时间,version 自动同步自 manifest;
  • downloadJSON(L486-L503):以 JSON.stringify(payload, null, 2) 生成可读文本,通过 Blob + 临时 <a> 触发下载;
  • parseJSONText(L508-L535):导入时不仅支持纯 JSON,还能自动剥离 ```json ... ``` 围栏代码块、以及截取首个 { 到末尾 } 之间的内容——这正是"AI 自动整理(AI Auto-Organize)"场景中直接粘贴 Gemini 返回的 JSON也能成功导入的原因;
  • importExportLock:导入过程加锁,避免并发导入互相覆盖(L455-L466),导入前还会在 sessionStorage 写入备份,便于失败时回滚。

另外,Google Drive 同步服务在首次上传时也会构造相同格式的载荷(见 GoogleDriveSyncPayloads.ts),说明 gemini-voyager.folders.v1 不仅是手动导出的格式,也是云同步上传云端的同一份数据格式——Data Viewer 因此也天然适用于审阅云同步备份的内容。

七、常见问题排查

现象 原因与处理
页面提示"格式无效" 文件不是 .json,或 format 字段不是 gemini-voyager.folders.v1,或缺少 data.folders / data.folderContents。请确认文件来自 Voyager 扩展导出
页面提示"解析失败" JSON 语法不完整或文件被截断。用任意 JSON 校验工具检查后重新导出
对话显示在"未归类对话"里 该对话引用的文件夹 id 在 folders 中不存在(数据不完整或文件夹已删除),属正常容错展示
想要完全清空 点击预览界面的"清除数据"按钮,会同时删除 localStorage 缓存
想换一份数据 点击"重新导入",直接拖入或选择新的 JSON 文件即可覆盖当前数据

如果需要在扩展内重新导入这份 JSON(迁移或恢复),在文件夹面板菜单中选择"导入文件夹",可粘贴 JSON 文本或选择文件;扩展会执行更严格的版本兼容与结构校验,并在导入前自动备份当前文件夹数据。

八、相关资源

登录后查看全文
voyager