news 2026/9/11 17:26:25

Focalboard Todoist 数据迁移实战:将 Todoist JSON 归档一键导入 Focalboard 看板

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Focalboard Todoist 数据迁移实战:将 Todoist JSON 归档一键导入 Focalboard 看板

Focalboard Todoist 数据迁移实战:将 Todoist JSON 归档一键导入 Focalboard 看板

【免费下载链接】focalboardFocalboard is an open source, self-hosted alternative to Trello, Notion, and Asana.项目地址: https://gitcode.com/GitHub_Trending/fo/focalboard

导读

本文介绍 Focalboard 官方提供的 Todoist 导入器(focalboard-todoist-importer),讲解如何把 Todoist 的完整数据导出为 JSON 归档,再通过importTodoist.ts脚本转换为 Focalboard 可识别的boardarchive归档文件,最终在 Focalboard 中一键导入为可编辑的看板。读完本文,你将掌握从数据导出、环境安装、命令行运行到源码级映射原理的完整迁移链路,并了解项目(Project)→看板(Board)、分组(Section)→列表选项(Select Option)、任务(Item)→卡片(Card)、备注(Note)→卡片描述等核心映射规则。

一、工作原理概述

Todoist 导入器是一个运行在 Node.js 环境下的命令行应用,其核心思路是"数据中转":

Todoist JSON 归档 │ ▼ importTodoist.ts(数据转换,ts-node 运行) │ ▼ Focalboard 归档(.boardarchive,JSONL 格式) │ ▼ Focalboard 前端 "Import archive"(解析并落库)

整个链路不依赖 Todoist API 的实时鉴权,而是使用 Todoist 官方数据导出服务生成的全量 JSON 文件作为输入,因此迁移过程可重复、可离线、可审计。核心脚本位于 import/todoist/importTodoist.ts,它复用了webapp中 Focalboard 自身的块(Block)与看板(Board)数据模型,保证生成的归档与 Focalboard 内部数据结构完全一致。

二、第一步:从 Todoist 导出全量 JSON 数据

导入器要求输入一个包含 Todoist 全部数据的 JSON 文件。按以下步骤获取:

  1. 访问 Todoist 的开源数据导出服务(darekkay.com 提供的 Todoist Export 工具)。
  2. Export As(导出格式)选项中选择JSON (all data)(JSON 全量数据)。
  3. Archived(已归档)选项被勾选,请取消勾选,以确保导出范围符合预期。
  4. 点击Authorize and Backup(授权并备份)。此时会跳转到你的 Todoist 账号进行授权,请按屏幕提示完成操作。
  5. 记下下载得到的json文件名称与存放位置,后续命令行参数需要引用该路径。

需要说明的是,导出工具与 Todoist 的授权交互属于第三方服务行为,本仓库仅消费其产出的 JSON 文件;从源码结构看,导入器只依赖该 JSON 的结构,不绑定特定导出渠道。

三、第二步:安装依赖

导入器是一个独立的 TypeScript 项目,其声明位于 import/todoist/package.json,运行时依赖minimist(命令行参数解析),开发依赖包括ts-nodetypescripteslint等。由于脚本直接引用webapp下的源码模块(见下文源码解析),因此需要先在webapp目录安装一次依赖。

在仓库根目录下依次执行:

# 1. 安装 Focalboard 前端依赖(提供 Block / Board / Card 等数据模型) cd focalboard/webapp npm install # 2. 安装 Todoist 导入器自身依赖 cd ../import/todoist npm install

说明:focalboard/webapp即本仓库的 webapp 目录;若你已将仓库克隆到其他路径,请按实际路径调整。安装完成后,import/todoist下会出现node_modulests-node可执行环境。

四、第三步:运行导入命令

focalboard/import/todoist目录内执行:

npx ts-node importTodoist.ts -i <path-to-todoist.json> -o archive.boardarchive

其中:

参数含义默认值说明
-i输入的 Todoist JSON 文件路径无(必填)指向第一步下载的 json 文件
-o输出的 Focalboard 归档文件路径archive.boardarchive可自定义,如todoist-import.focalboard

命令成功后会打印Exported to <outputFile>。若文件不存在,程序会输出File not found: <path>并以退出码2结束;若缺少-i参数则调用showHelp()后以退出码1结束(见 importTodoist.ts)。

也可以直接复用项目预置的测试脚本(见 package.json 的scripts段):

npm test # 等价于 ts-node importTodoist.ts -i test/todoist.json -o test/todoist-import.focalboard npm run debug:test # 以调试模式运行(--inspect=5858),可配合 Chrome DevTools 断点调试转换逻辑

五、第四步:在 Focalboard 中导入归档

  1. 启动 Focalboard,进入目标工作区。
  2. 点击界面上的Settings(设置)。
  3. 选择Import archive(导入归档)。
  4. 选中上一步生成的archive.boardarchive文件。

导入完成后,Todoist 中的各个项目会以看板形式出现在工作区中。归档的解析与落库由 Focalboard 前端 archiver.ts 与后端 API 配合完成,前端先使用ArchiveUtils.parseBlockArchive读取 JSONL 内容,再通过导入接口写入存储。

六、源码级解析:Todoist 数据如何映射到 Focalboard

转换的核心逻辑集中在convert(input, project)函数(importTodoist.ts),映射规则如下:

1. 项目 → 看板(Board)

  • 遍历input.projects,每个非 Inbox 的 Todoist 项目生成一个 Focalboard 看板。
  • 看板标题与描述均取项目名project.name
  • 命令行会打印Board: <project.name>便于跟踪进度。

2. 分组(Section)→ 列表选择属性(Select)

  • 项目内的分组(Section)被映射为一个名为List、类型为select的卡片属性(IPropertyTemplate),每个分组对应一个带颜色的选项(option)。
  • 选项颜色从 10 色调色板轮换分配:propColorGraypropColorBrownpropColorOrangepropColorYellowpropColorGreenpropColorBluepropColorPurplepropColorPinkpropColorRed(见 importTodoist.ts)。
  • 关键分支逻辑:getProjectColumns会先收集项目自身的 section;若项目没有任何 section(列表长度不大于 1),则退化为使用五个默认分组:No StatusNext UpIn ProgressCompletedArchived(importTodoist.ts)。这是让无分组项目也能在 Focalboard 看板中呈现列结构的关键设计。

3. 任务(Item)→ 卡片(Card)

  • 每个任务生成一张卡片,标题为任务内容item.content
  • 卡片所属分组通过section_id映射为List属性的选项值;无分组任务归入No Status选项。若映射失败会打印警告Invalid idList: ...但不会中断转换。
  • 卡片在 Focalboard 数据模型中的类型定义可参考 webapp/src/blocks/card.ts。

4. 备注(Note)与附件 → 卡片描述

  • getCardDescription收集该任务下的所有备注(input.notesitem_id匹配的任务),合并为卡片描述文本(以空行分隔)。
  • 若备注带文件附件(file_attachment),描述中会追加 Markdown 链接:Attachment: <title>(importTodoist.ts)。
  • 描述以独立的文本块(Text Block)形式挂载到卡片下,并通过contentOrder建立父子关系;文本块的创建逻辑见 webapp/src/blocks/textBlock.ts。

5. 看板视图(Board View)

  • 每个看板附带一个名为Board View、类型为board的视图块,使导入结果默认以看板(Kanban)形态展示(importTodoist.ts);视图字段结构可对照 webapp/src/blocks/boardView.ts 中的createBoardView

6. 特殊处理:Inbox 项目

  • 名为Inbox的项目会被直接跳过,不生成看板(importTodoist.ts),避免把 Todoist 的收件箱杂项带入工作区。

七、归档文件格式:JSONL 与 ArchiveUtils

生成的.boardarchive是一个JSON Lines(JSONL)文件,由 import/util/archive.ts 中的ArchiveUtils.buildBlockArchive构建:

  • 第一行为头(Header):{"version":1,"date":<时间戳>}
  • 之后每行一个 JSON 对象,typeboardblockdata为对应的看板或块数据。
{"version":1,"date":1699999999999} {"type":"board","data":{...}} {"type":"block","data":{...}}

读取侧parseBlockArchive会校验头版本号(version >= 1),逐行解析并按type分类,解析失败会抛出ERROR parsing line <n>。这种"一行一实体"的格式便于增量扩展与流式处理,源码注释中亦提到未来可扩充更多行类型。

八、Todoist JSON 数据结构速览

import/todoist/todoist.ts 使用 quicktype 根据实际导出样本生成了完整的 TypeScript 类型定义,转换脚本只消费其中四类核心数据:

  • projects:项目数组(含idnameinbox_projectis_archived等字段)。
  • sections:分组数组(含idproject_idnameis_deleted等字段)。
  • items:任务数组(含idproject_idsection_idcontentparent_idpriority等字段)。
  • notes:备注数组(含iditem_idcontentfile_attachment等字段)。

理解该结构有助于排查"某类数据未被迁移"的问题——例如标签(labels)、提醒(reminders)、过滤器(filters)在类型定义中存在,但当前导入器并未做映射,属于已知的覆盖范围边界。

九、其他实现细节与注意事项

  • ID 生成:转换过程中所有 Focalboard 实体 ID 由 import/todoist/utils.ts 的Utils.createGuid()生成(基于crypto.randomBytes的 UUID 实现),保证每次转换生成的归档 ID 互不冲突。
  • 运行环境:脚本顶部有(global.window as any) = {}的兼容处理(importTodoist.ts),用于在 Node 环境复用时让依赖浏览器全局对象的工具函数正常工作。
  • 类型检查tsconfig.json启用了strictstrictNullChecks,若二次开发请保持类型完整,避免引入空值访问。
  • 适用前提:本文命令基于仓库当前版本(typescript ^4.1.5ts-node ^9.1.1minimist ^1.2.6)验证;导入仅覆盖上文所述的映射范围,Todoist 中未映射的数据(如标签、重复任务规则、提醒)不会出现在导入结果中,请在迁移前评估业务影响。

十、小结

Focalboard 的 Todoist 导入器以"JSON 导出 → 命令行转换 → 前端导入"三段式流水线,提供了一条低成本、可复现的数据迁移路径。其设计复用webapp的块模型与统一的 JSONL 归档协议,也让开发者可以参照 import/todoist 的结构,为其他数据源(仓库内另有 asana、jira、trello、notion、nextcloud-deck 等导入器)快速编写同类迁移工具。

【免费下载链接】focalboardFocalboard is an open source, self-hosted alternative to Trello, Notion, and Asana.项目地址: https://gitcode.com/GitHub_Trending/fo/focalboard

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/11 17:23:44

2026年7月上海市崇明区二手房价格深度分析报告

一、报告摘要本报告基于2026年7月上海市崇明区实际成交案例&#xff0c;从成交价格、成交结构、区域分化、购房成本与市场趋势五个维度展开深度分析。数据显示&#xff0c;2026年7月崇明区二手房成交均价约为2.35万元/平方米&#xff0c;环比上涨1.2%&#xff0c;同比上涨3.8%。…

作者头像 李华
网站建设 2026/9/11 17:23:34

维普标红概念界定中的固定定义怎么改:助研君保留专业术语局部降AI

维普标红概念界定中的固定定义怎么改&#xff1a;助研君保留专业术语局部降AI 在管理学、法学、新闻传播学与社会学等学科的硕士与博士毕业论文第二章“核心概念界定与理论基础”中&#xff0c;对核心名词的权威定义&#xff08;如“数字治理”、“企业动态能力”、“平台经济…

作者头像 李华
网站建设 2026/9/11 17:22:48

Simulink模型在VCU开发中的核心技术与实践

1. VCU整车Simulink模型的价值与应用场景在新能源汽车开发领域&#xff0c;VCU&#xff08;Vehicle Control Unit&#xff09;作为整车控制的核心大脑&#xff0c;其开发效率直接影响着车型的上市周期。传统基于代码手写的开发方式不仅耗时费力&#xff0c;更难以应对日益复杂的…

作者头像 李华
网站建设 2026/9/11 17:19:59

如何本地部署 Eigent:多智能体 Cowork 桌面应用完整指南

如何本地部署 Eigent&#xff1a;多智能体 Cowork 桌面应用完整指南 【免费下载链接】eigent Eigent: The Open Source Cowork Desktop - Local and Free Alternative to Claude Cowork and Codex 项目地址: https://gitcode.com/GitHub_Trending/ei/eigent 月底要出一份…

作者头像 李华
网站建设 2026/9/11 17:19:24

ESLint dot-notation 规则完全指南:强制使用点表示法访问对象属性

ESLint dot-notation 规则完全指南&#xff1a;强制使用点表示法访问对象属性 【免费下载链接】eslint Find and fix problems in your JavaScript code. 项目地址: https://gitcode.com/GitHub_Trending/es/eslint dot-notation 是 ESLint 内置的一条 suggestion 类型规…

作者头像 李华
网站建设 2026/9/11 17:18:02

GHelper:免费轻量华硕笔记本控制工具,告别500MB官方后台

GHelper&#xff1a;免费轻量华硕笔记本控制工具&#xff0c;告别500MB官方后台 【免费下载链接】g-helper Lightweight Armoury Crate alternative for Asus laptops with nearly the same functionality. Works with ROG Zephyrus, Flow, TUF, Strix, Scar, ProArt, Vivobook…

作者头像 李华