Huly 统一导入格式实战:从示例工作区中的 Classic Margherita Pizza 文档解读数据建模与导入流程
【免费下载链接】platformHuly — All-in-One Project Management Platform (alternative to Linear, Jira, Slack, Notion, Motion)项目地址: https://gitcode.com/GitHub_Trending/platform80/platform
Classic Margherita Pizza.md 是 Huly 开源项目dev/import-tool(Huly Import Tool)示例工作区(example-workspace)中的一份示例文档,它以"配方(Recipe)"为业务载体,完整演示了 Huly 统一导入格式(Unified Import Format)的三大核心能力:YAML frontmatter 元数据建模、Markdown 正文承载、以及文档之间的相对引用。本文以该文档为骨架,结合 统一格式导入指南 与导入工具源码 src/index.ts,逐字段拆解这份示例数据,并给出将其导入真实 Huly 工作区的完整命令与底层原理,帮助你快速掌握如何把任意业务系统数据整理成 Huly 可直接消费的目录结构。
文档在仓库中的定位:一份"可导入"的示例数据
该文档位于示例工作区的 Recipes 目录下:
dev/import-tool/docs/huly/example-workspace/Recipes/Classic Margherita Pizza.md根据 Huly Import Tool 说明,统一导入格式(Unified Import Format)是官方推荐的数据迁移方式:它把工作区数据表示为一棵"人类可读的目录树",其中每个文档/任务是带 YAML frontmatter 的 Markdown 文件,每个空间则由根目录下的*.yaml配置声明。这份披萨配方文档正是该格式的一个最小但完整的样例——它本身没有一行代码,却集中演示了元数据(frontmatter)、正文(Markdown)、标签(Tag 引用)和跨文档关联(相对路径引用)四种格式要素。
逐字段拆解文档 frontmatter 元数据
文档以---包裹的 YAML frontmatter 开头,全部核心业务属性都定义在这里:
--- title: Classic Margherita Pizza tags: - ./DietaryType.yaml cookingTime: 30 minutes servings: 4 difficulty: Medium category: Italian calories: 850 chef: Mario Rossi restrictions: Vegetarian allergens: Gluten, Dairy recommendedDesserts: - ./Chocolate Lava Cake.md ---各字段含义如下:
| 字段 | 示例值 | 说明 |
|---|---|---|
title | Classic Margherita Pizza | 文档标题,必填项之一 |
tags | ./DietaryType.yaml | 标签声明,通过相对路径引用一份 Tag 定义文件(见下文"标签与属性映射") |
cookingTime | 30 minutes | 自定义业务属性(字符串) |
servings | 4 | 自定义业务属性(数字) |
difficulty | Medium | 自定义枚举式属性,可与工作区根目录的 Difficulty.yaml 对应 |
category | Italian | 自定义分类属性 |
calories | 850 | 自定义数值属性 |
chef | Mario Rossi | 自定义人员属性 |
restrictions | Vegetarian | 由tags引用的 Tag 定义的属性之一 |
allergens | Gluten, Dairy | 由tags引用的 Tag 定义的属性之一 |
recommendedDesserts | ./Chocolate Lava Cake.md | 跨文档引用,相对路径指向同目录下的另一份文档 |
对比同目录下的兄弟示例 Mushroom Risotto.md 可以发现,frontmatter 允许出现任意自定义键(如proteinSource、isGlutenFree),导入工具会依据 Tag/空间定义将"已知属性"映射为结构化字段,而将其他键作为文档的附加元数据保留。这正体现了统一格式"灵活、可表示任意系统数据"的设计目标——你完全可以用同一套机制描述客户、订单、设备台账等任意业务对象。
标签与属性映射:tags 指向的不是字符串,而是 YAML 定义
披萨文档中tags的值是./DietaryType.yaml,这是一个指向标签定义文件的相对路径,而不是随便写的一个字符串。打开该文件可以看到标签的完整结构:
class: card:class:Tag title: DietaryType properties: - label: restrictions type: TypeString - label: allergens type: TypeString要点解读:
class: card:class:Tag声明这是一份 Huly 的Tag(标签)定义,card:class:Tag是 Huly 卡片模型中标签类的完整类名。properties定义了该标签携带的结构化属性:restrictions(饮食限制,字符串)与allergens(过敏原,字符串)。- 披萨文档 frontmatter 中的
restrictions: Vegetarian、allergens: Gluten, Dairy正是对应这两个属性的取值——即文档通过tags挂接标签,标签通过properties决定文档上可以有哪些业务字段。
同样的模式也出现在 Vegan/Vegan Recipe.yaml 中,它使用class: card:class:MasterTag定义了proteinSource(字符串)、isGlutenFree(布尔)等属性,并在素食菜谱文档中直接以同名键取值(如isGlutenFree: true)。因此,当你要迁移自有系统时,建议按"标签(Tag)→ 属性(properties)→ 文档取值"三层结构组织元数据,这样导入 Huly 后可以直接获得可检索、可筛选的结构化字段。
跨文档引用:相对路径即关联关系
披萨文档中的recommendedDesserts: ./Chocolate Lava Cake.md与tags: ./DietaryType.yaml共同演示了统一格式的相对引用规则:
- 引用目标与当前文档同级或位于其下时,使用类似
./xxx.md的相对路径; - 跨目录引用时,路径要相对于当前文档所在目录书写。例如 Chocolate Sauce.md 中同时出现了
tags: ../DietaryType.yaml(向上跳一级引用标签)和relatedRecipes: '../Chocolate Lava Cake.md'(同级引用)两种写法; - 反向关联同样存在:Chocolate Lava Cake.md 的 frontmatter 里
recommendedMainDishes: - ./Classic Margherita Pizza.md,与披萨文档形成"主菜 ↔ 甜点"的双向推荐关系。
此外,Chocolate Lava Cake.md 还展示了附件(blob)的引用方式:blobs: - ./files/cake.png。目录中的files/子目录专门存放附件,Markdown 正文中引用的图片等文件会被上传为文档附件。这套"文件即附件、路径即关联"的设计,让整个示例工作区无需数据库即可在文件系统层面完成建模。
目录结构与父子文档:recipe 文档如何挂到空间上
参照 统一格式导入指南 中的结构规则,示例工作区的 Recipes 目录体现了"空间 → 文档 → 子文档"三层组织:
example-workspace/ ├── Recipes.yaml # 空间配置(teamspace) └── Recipes/ ├── Classic Margherita Pizza.md # 顶层文档 ├── Chocolate Lava Cake.md # 顶层文档 ├── Chocolate Lava Cake/ # 与父文档同名的子目录 │ └── Chocolate Sauce.md # 子文档(副标题/附属页) ├── Vegan/ │ ├── Mushroom Risotto.md │ └── Vegan Recipe.yaml # 目录内的标签定义 ├── DietaryType.yaml # 目录内的标签定义 └── files/ └── cake.png # 附件目录格式约定:
- 根目录下的
*.yaml(如 Recipes.yaml、RecipeAssociations.yaml、Difficulty.yaml)用于空间配置与全局元数据; - 子文档放在"与父文档同名"的目录下,
Chocolate Sauce.md之于Chocolate Lava Cake.md即为此模式的实例; - 文件名
settings.yaml被保留,不能用作空间配置; - 缺少
class字段的 frontmatter 文件会在导入时被跳过。
值得一提的细节是,这份披萨文档的正文部分(Ingredients/Instructions/Notes三节)出现了两次重复内容。从格式角度看这并不影响导入:统一格式只依据 frontmatter 中的class判定文档归属,正文作为 Markdown 原样写入 Huly 文档体。这个重复更像是人工编写示例时留下的痕迹,但也恰好提醒读者——frontmatter 才是导入工具消费的关键,正文会按原样保留,准备数据时不必过度处理正文格式。
如何把这份示例工作区导入真实 Huly 工作区
命令行方式
统一格式导入指南 给出了最直接的 Docker 运行方式:
docker run \ -e FRONT_URL="https://huly.app" \ -v /path/to/workspace:/data \ hardcoreeng/import-tool:latest \ -- bundle.js import /data \ --user your.email@company.com \ --password yourpassword \ --workspace workspace-id对应地,把/path/to/workspace换成dev/import-tool/docs/huly/example-workspace所在路径即可导入这套 Recipes 示例数据。关键参数说明:
FRONT_URL:Huly 前端地址,导入工具会从FRONT_URL/config.json读取ACCOUNTS_URL完成账号服务定位;--user / --password:导入账号的邮箱与密码,该账号必须已存在于系统中(见下文限制);--workspace:目标工作区的 URL 标识;import <dir>:统一格式导入子命令,由HulyFormatImporter.importFolder(dir)驱动。
源码层面的执行链路
导入工具入口见 src/__start.ts,它仅一行调用importTool();真正的逻辑在 src/index.ts 中:
authorize()(L64-L111)依次完成:拉取config.json设置账号服务端点 → 调用getAccountClient().login(user, password)登录 → 按workspaceUrl过滤用户工作区 →selectWorkspace()选中目标 →createClient()建立与 Transactor 的长连接,同时用FrontFileUploader准备附件上传通道;import <dir>子命令(L157-L170)实例化HulyFormatImporter并调用importFolder(dir),递归遍历目录、解析每个 YAML 空间配置与 Markdown 文档,按class分发到对应模型写入工作区。
从源码还可以确认:import命令与import-notion-with-teamspaces、import-clickup-tasks等直连导入命令平级,统一格式导入是官方推荐的通用路径,而 Notion、ClickUp 直连只适合简单迁移场景。
导入限制与注意事项
结合 统一格式导入指南 的"Limitations"一节,使用本格式(含本示例)导入时需注意:
- 所有用户必须已存在:
chef、assignee、owners 等引用的用户需先在工作区创建,assignee 按全名匹配; - 空间目录中的文件只有在 Markdown 正文中被引用时才会作为附件上传(如
files/cake.png); - 文档代码唯一性:受控文档文件名方括号中的代码(如
[SOP-001])在所有文档空间中必须唯一;受控文档只能以Draft状态导入,且必须与其模板位于同一空间; - Tags 属性是结构化关键:要在导入后获得可筛选的字段,应像
DietaryType.yaml一样为标签预先声明properties。
总结:从一份披萨配方到你的业务数据
Classic Margherita Pizza.md 虽然只是一份配方示例,却完整展示了 Huly 统一导入格式的四个核心动作:用 frontmatter 声明元数据、用 tags 挂接结构化标签、用相对路径建立跨文档关联、用目录结构表达空间与父子层级。参照 示例工作区 中 Recipes、Documentation、Project Alpha、QMS Documents 四类样例,你可以用同样的 YAML + Markdown 组合,把任意系统的数据整理成 Huly 可导入的目录树,再通过一条 Docker 命令完成迁移。
【免费下载链接】platformHuly — All-in-One Project Management Platform (alternative to Linear, Jira, Slack, Notion, Motion)项目地址: https://gitcode.com/GitHub_Trending/platform80/platform
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考