snapshot of https://github.com/twentyhq/twenty.git (main, 2026-09-17; blobs > 131072B omitted)
Some checks failed
App Prod-Parity E2E Dispatch / dispatch (push) Failing after 10s
CD Storybook UI / build (push) Failing after 3m25s
CD Storybook UI / dispatch (push) Has been skipped
CD deploy main / website-changed-files (push) Successful in 18m8s
CI Agent Skills / changed-files-check (push) Successful in 18m9s
CI Create App E2E minimal / changed-files-check (push) Successful in 24s
CI Create App / changed-files-check (push) Successful in 26s
CI Docs / changed-files-check (push) Successful in 26s
CI Emails / changed-files-check (push) Successful in 28s
CI Example App Hello World / changed-files-check (push) Successful in 23s
CI Front / changed-files-check (push) Has been skipped
CI Example App Postcard / changed-files-check (push) Successful in 27s
CI UI / changed-files-check (push) Has been skipped
CI Utils Test / changed-files-check (push) Successful in 45s
CI Twenty Apps / discover (push) Successful in 1m3s
CD deploy main / deploy-main (push) Failing after 3s
CI Agent Skills / agent-skills-validate (push) Has been skipped
CI Create App / create-app-test (lint) (push) Has been skipped
CI Emails / emails-test (push) Has been skipped
CI Front / front-task (lingui:compile) (push) Has been skipped
CI Front / front-task (lint) (push) Has been skipped
CI Example App Postcard / example-app-postcard (push) Has been skipped
CI UI / ui-task (lint) (push) Has been skipped
CI UI / ui-task (pack-size) (push) Has been skipped
CI UI / ui-task (size) (push) Has been skipped
CI UI / ui-task (test) (push) Has been skipped
CI UI / ui-task (typecheck) (push) Has been skipped
CI Utils Test / utils-test (push) Has been skipped
CI Twenty Apps / ${{ matrix.app.name }} (push) Has been skipped
CI Emails / ci-emails-status-check (push) Successful in 2s
CI Example App Hello World / ci-example-app-hello-world-status-check (push) Successful in 2s
CI Example App Postcard / ci-example-app-postcard-status-check (push) Successful in 3s
CI UI / ui-sb-test (push) Has been skipped
CI Utils Test / ci-utils-test-status-check (push) Successful in 2s
CI Twenty Apps / ci-twenty-apps-status-check (push) Successful in 2s
CI UI / ci-ui-status-check (push) Successful in 2s
CI Desktop / desktop (push) Failing after 1m8s
Push docs to Crowdin / Push documentation to Crowdin (push) Failing after 55s
Push translations to Crowdin / Extract and upload translations (push) Failing after 5s
Push website translations to Crowdin / Extract and upload website translations (push) Failing after 5s
CI Create App / create-app-test (test) (push) Has been skipped
CI Create App / create-app-test (typecheck) (push) Has been skipped
CI Docs / docs-lint (push) Has been skipped
CI Example App Hello World / example-app-hello-world (push) Has been skipped
CI Front / front-task (lingui:extract) (push) Has been skipped
CI Front / front-task (test) (push) Has been skipped
CI Front / front-task (typecheck) (push) Has been skipped
CI UI / ui-sb-build (push) Failing after 1m32s
CI Twenty Apps / ${{ matrix.app.name }} (${{ matrix.server-source }}) (push) Has been skipped
CI Agent Skills / agent-skills-publish (push) Has been skipped
CI Create App / ci-create-app-status-check (push) Successful in 2s
CI Agent Skills / agent-skills-remote-source (push) Has been skipped
CI Create App E2E minimal / create-app-e2e-minimal (push) Has been cancelled
CI E2E Main / e2e-test (push) Has been cancelled
CI Front / front-sb-build (push) Has been cancelled
CI Front / front-build (push) Has been cancelled
CI Create App E2E minimal / ci-create-app-e2e-minimal-status-check (push) Has been cancelled
CI E2E Main / ci-e2e-main-status-check (push) Has been cancelled
CI E2E Main / notify-main-ci-failure (push) Has been cancelled
CI E2E Main / qa-scout-comment (push) Has been cancelled
CI Front / front-sb-test (push) Has been cancelled
CI Front / front-sb-screenshots (push) Has been cancelled
CI Front / ci-front-status-check (push) Has been cancelled
DPA Sub-Processor Sync / sync-subprocessors (push) Failing after 3s
AI Catalog Sync / sync-catalog (push) Failing after 2s

This commit is contained in:
upstream-mirror
2026-09-17 23:28:13 +05:00
commit e7da97194a
32688 changed files with 4208681 additions and 0 deletions

View File

@@ -0,0 +1,76 @@
---
title: 错误处理与验证
description: 在确认之前,直接在 UI 中查看并修复导入错误。
---
import { VimeoEmbed } from '/snippets/vimeo-embed.mdx';
## 导入前验证
上传文件并完成字段映射后,Twenty 会在导入**之前**验证你的数据。 这样可以在不影响现有数据的情况下捕捉并修复错误。
## 工作原理
1. **上传**您的 CSV 文件
2. **映射**您的列到 Twenty 的字段
3. **查看**黄色高亮的潜在错误
4. 可直接在 UI 中**修复错误**
5. **确认**导入
<VimeoEmbed videoId="1145273857" title="视频演示" />
## 错误显示
存在问题的行会被高亮为**黄色**。 您可以:
* **直接编辑单元格**以修复错误
* **删除该行**以完全跳过该行
这种行内编辑可节省时间——无需返回电子表格、修复错误并重新上传。
## 常见错误类型
### 重复值
**原因**:唯一字段(电子邮件、域名)已在 Twenty 中存在,或在您的文件中出现了两次。
**修复**:
* 在导入 UI 中编辑重复值
* 删除其中一条重复的行
关于如何实施唯一性,详见[唯一性约束](/l/zh/user-guide/data-migration/capabilities/uniqueness-constraints)。
### 格式无效
**原因**:数据与期望的格式不匹配(例如,电子邮件无效、日期格式错误)。
**修复**:编辑单元格,使其符合正确格式。
请参见[字段映射](/l/zh/user-guide/data-migration/capabilities/field-mapping),了解每种字段类型的期望格式。
### 缺少必填字段
**原因**:必填字段为空。
**修复**:在必填字段中输入值,或删除该行。
### 未找到关系
**原因**:被引用的记录不存在(例如,公司域名尚未导入)。
**修复**:
* 先导入父级记录
* 或更正引用值
有关正确的导入顺序及如何关联记录,参见[导入关系](/l/zh/user-guide/data-migration/capabilities/import-relations)。
## 减少错误的建议
1. **下载模板** 以在导入文件前查看预期格式
2. 先在电子表格中,**清理您的数据**
3. **按正确顺序导入文件**以导入关系(公司 → 联系人 → 商机)
4. **用小批量进行测试**,再进行完整导入
5. 在上传前,**检查重复项**
6. **将每个文件限制为1万条记录**

View File

@@ -0,0 +1,198 @@
---
title: 字段映射
description: 数据导入期间字段映射的工作原理。
---
import { VimeoEmbed } from '/snippets/vimeo-embed.mdx';
## 字段映射的工作原理
当您上传文件时,Twenty 会分析您的列,并尝试将其与现有字段匹配。
### 自动映射
Twenty 将根据以下内容尝试匹配列:
* 列标题名称(精确或相似匹配)
* 数据类型检测(日期、数字、电子邮件)
* 常见字段模式
<Note>**快速提示:** 从您要导入的对象中导出几行数据。 导出的文件将包含 Twenty 期望的精确列名,从而在导入时实现无缝的自动映射。</Note>
### 手动映射选项
对于每一列,您可以:
* **映射到字段**:从下拉列表中选择匹配的 Twenty 字段
* **不进行映射**:完全跳过该列(不会导入数据)
<Note>**字段必须在导入前已存在。** 导入会创建记录,而不是创建字段。 请在导入前于 **设置 → 数据模型** 中创建自定义字段。</Note>
## 字段类型兼容性
数据模型中可用的所有字段类型都支持导入。
您也可以导入 `id` 值,以便为新记录指定特定 ID,或更新现有记录。
<img src="/images/user-guide/fields/all-field-types.png" style={{width:'100%'}} />
## 数据格式要求
<Note>**某些字段有特殊语法。** 我们建议在准备导入之前下载示例文件,以查看每种字段类型的预期语法。</Note>
### 地址字段
地址是一个嵌套字段,包含多个列。 其中一些可以留空。
* **Address / Address 1**:街道地址第 1 行
* **Address / Address 2**:街道地址第 2 行
* **Address / City**:城市名称
* **Address / State**:州或省
* **Address / Country**:国家名称
* **Address / Post Code**:邮政/ZIP 编码
### 数组字段
使用以下格式:
```
["value1","value2"]
```
### 布尔字段
使用 `TRUE` 或 `FALSE`(大写),不要使用 `true` 或 `false`
### 货币字段
货币是一个**嵌套字段**,需要两列,且**两列都必须填写**:
* **Amount / Amount**:数值(例如,`1234.56`)
* **Amount / Currency**:货币代码(例如,`USD`、`EUR`)
### 日期字段
支持的格式:
* `YYYY-MM-DD`(推荐)
* `MM/DD/YYYY`
* `DD/MM/YYYY`
* ISO 8601 格式
### 域名字段
* 建议使用 `https://domain.com` 格式以避免创建重复,因为通过邮箱和日历同步创建的公司会使用该格式
* 可以填写 `Domain Label` 和 `Domain URL`:最佳做法是在标签中填写 `domain.com`,在 url 中填写 `https://domain.com`
* 在 Companies 对象内,域名必须唯一
* **待导入文件中的域名必须唯一**
### 电子邮件字段
* 必须为有效的电子邮件格式
* 在 People 对象内,电子邮件必须唯一
* **待导入文件中的电子邮件必须唯一**
* 对于附加邮箱:主邮箱请使用 **Emails / Primary Email**,附加邮箱请使用 **Emails / Additional Emails**,并采用以下格式:
```
["jane@twenty.com","jane.doe@twenty.com"]
```
### ID 字段
在导入过程中指定 `id` 是可选的。 如未提供,Twenty 将自动生成 ID。
映射 `id` 列的用例:
* **设置特定 ID**:为新创建的记录选择 UUID
* **更新现有记录**:与现有记录进行匹配以更新它们,而不是创建重复项。 在这种情况下,建议不要映射其他唯一字段:仅映射一个唯一字段可确保导入更顺畅。
<Note>如果您提供 `id`,其必须为 UUID 格式(例如,`c776ee49-f608-4a77-8cc8-6fe96ae1e43f`)。</Note>
### JSON 字段
使用有效的 JSON 格式:
```
{"key":"value","key2":"value2"}
```
### 链接字段
与域名字段类似:
* 同时填写标签和 URL 两列:**Links / Link URL** 和 **Links / Link Label**
* 使用完整的 URL 格式:`https://example.com`
* 对于次要链接,请使用 **Links / Secondary Links** 列,并采用以下格式:
```
[{"url":"https://twenty.com","label":"Twenty"}]
```
### 多选字段
使用**API 名称**(而非显示标签),格式如下:
```
["VALUE1","VALUE2"]
```
请参见[此处](#finding-api-names-for-select-fields)了解如何查找 API 名称。
<Note>新的选择项不会通过导入自动创建。 请在导入前于 **设置 → 数据模型** 中添加它们。</Note>
<Warning>
**导入会覆盖,不会追加。**
如果一条记录已选择了 `VALUE2` 和 `VALUE3`,而您导入了 `["VALUE1"]`,则导入后该记录将只保留 `VALUE1`。 之前的选择会被替换,而不是合并。
</Warning>
### 数字字段
* 仅限数字
* 小数使用点号:`1234.56`
* 不使用千位分隔符
### 电话字段
电话是一个包含多列的嵌套字段,且**必须填写**
* **Phones / Primary Phone Number**:电话号码(例如,`4159095555`)
* **Phones / Primary Phone Country Code**:国家代码(例如,`US`)
* **Phones / Primary Phone Calling Code**:拨号代码(例如,`+1`)
### 评分字段
使用 API 名称格式:`RATING_1`、`RATING_2`、`RATING_3`、`RATING_4`、`RATING_5`
### 关系字段
请参阅我们的专门文章:[在对象之间导入关联](/l/zh/user-guide/data-migration/capabilities/import-relations)
### 选择字段
使用选项的**API 名称**(而不是显示标签):
```
VALUE1
```
请参见[此处](#finding-api-names-for-select-fields)了解如何查找 API 名称。
<Note>新的选择项不会通过导入自动创建。 请在导入前于 **设置 → 数据模型** 中添加它们。</Note>
### 文本字段
* 无需特殊格式
* 首尾空格会被移除
## 查找 API 名称
对于具有预定义选项的 Select、Multi-Select 和 Array 字段,必须使用 **API 名称**,而不是显示标签。
### 如何查找 API 名称
1. 进入 **设置 → 数据模型**
2. 选择对象和字段
3. 启用 **高级模式**(在设置页面右下角切换)
4. 查看每个选项的 API 名称
<VimeoEmbed videoId="1144910809" title="视频演示" />

View File

@@ -0,0 +1,48 @@
---
title: 支持的文件格式
description: 在 Twenty 中用于数据导入的受支持文件格式。
---
## 支持的格式
Twenty 支持三种导入文件格式:
| 格式 | 扩展名 | 备注 |
| ------------- | ----- | ----------- |
| **CSV** | .csv | 推荐,兼容性最佳 |
| **Excel** | .xlsx | 现代 Excel 格式 |
| **Excel(旧版)** | .xls | 旧版 Excel 格式 |
## 文件要求
| 要求 | 值 |
| -------- | ----------------- |
| **编码** | 推荐使用 UTF-8 |
| **记录上限** | 每个文件最多 10,000 条记录 |
| **结构** | 第一行必须包含列标题 |
| **内容** | 每个文件仅包含一种对象类型 |
## CSV 最佳实践
* **分隔符**:使用逗号(`,`)或分号(`;`)
* **文本限定符**:对于包含逗号的文本,请使用双引号(`"`)
* **行结束符**:支持 Windows(CRLF)或 Unix(LF)
* **空值**:将单元格留空,不要使用 "NULL" 或 "N/A"
## Excel 最佳实践
从 Excel 导出时:
* 移除公式(仅导出值)
* 删除末尾的空行
* 确保没有合并单元格
* 仅使用第一个工作表
## 大型数据集
对于超过 10,000 条记录的数据集:
* 拆分为多个文件
* 或者使用 [API 导入](/l/zh/user-guide/data-migration/how-tos/import-data-via-api) 以导入无限数量的记录
<Note>对于非常大的迁移(100,000+ 条记录),API 比 CSV 导入明显更快且更可靠。</Note>

View File

@@ -0,0 +1,148 @@
---
title: 导入对象之间的关系
description: 通过 CSV 导入记录之间的关系。
---
## 概览
Twenty 支持在 CSV 导入过程中导入对象之间的关系。 这使您可以在数据迁移过程中关联记录(例如,将人员关联到公司)。
<Note>**当前支持导入**:两侧均指向单一对象类型的一对多关系(例如,人员 → 公司)。 指向多个对象类型的关系目前尚不支持导入/导出。</Note>
## Twenty 中关系的工作方式
### 一对多 / 多对一
Twenty 支持一条记录关联到多条记录的标准关系:
* **一个公司 → 多个人员**:一家公司可以有多名员工,但每个人只隶属于一家公司
* **一个公司 → 多个商机**:一家公司可以有多个商机,但每个商机只属于一家公司
### 可指向多种对象类型的关系
某些关系可以连接到不同类型的对象。 这有两种方式:
**模式 1:来自不同对象类型的多条记录,各自链接到一条记录**
几个笔记或任务可以同时附加到多个对象类型:
* **笔记** 可以同时关联到一个人员、一个公司和一个商机
* **任务** 可以同时关联到一个人员、一个公司和一个商机
在此场景中,笔记/任务位于“多”的一侧。 每条记录在每种对象类型上都仅链接到一条记录。
<img src="/images/user-guide/fields/many-to-one-morph.png" style={{width:'100%'}} />
**模式 2:一条记录接收来自不同对象类型的多条记录的链接**
一个项目可以接收来自不同对象类型的多条记录的链接:
* **一个项目** 可以关联到许多人员、许多公司,并附加许多笔记
在此场景中,项目位于“一”的一侧。 来自不同对象的多条记录都可以链接到同一个项目。
<img src="/images/user-guide/fields/one-to-many-morph.png" style={{width:'100%'}} />
<Warning>
**导入/导出限制**:指向多个对象类型的关系(如 笔记 → 人员/公司/商机)在 CSV 导入或导出中**尚不支持**。
* **导入**:仅支持导入两侧均指向单一对象类型的一对多关系
* **导出**:指向多个对象类型的关系列目前会留空
此功能已在我们的路线图中。
</Warning>
### 当前不支持的内容
**多对多关系** 目前尚不可用。 例如,您目前无法创建如下关系:
* 多个人员关联到多个项目
<Note>多对多关系计划在 2026 年下半年推出。</Note>
## 在导入过程中关联记录
<Note>**提醒**:仅可导入指向单一对象类型的一对多关系(例如,人员 → 公司)。 指向多个对象类型的关系(例如,笔记 → 人员/公司/商机)目前尚不支持。</Note>
### 步骤 1:确定“一”和“多”两侧
首先,确定关系中哪个对象位于“一”侧,哪个对象位于“多”侧。
**示例**:
* **公司** 位于“一”侧(一个公司有许多员工)
* **人员** 位于“多”侧(每个人都隶属于一家公司)
### 步骤 2:确保“一”侧的记录已存在
在导入“多”侧之前,“一”侧的记录必须已在 Twenty 中存在。
* 请先导入或创建“一”侧的记录(例如,公司)
* 验证其唯一标识符。 可以是:
* `id`(Twenty 的 UUID)
* 一个被设置为唯一的字段(例如,公司的 `domain`,或您先前系统中的外部 ID)
<Warning>若引用了不存在的记录,导入将失败。</Warning>
### 步骤 3:准备您的 CSV 文件
在“多”侧的 CSV 文件中添加一列,用于引用“一”侧的记录。
**示例**:对于将人员关联到公司的 CSV 文件:
```
firstName,lastName,email,companyDomain
John,Smith,john@acme.com,https://acme.com
Jane,Doe,jane@widgets.co,https://widgets.co
```
**重要**:
* 该值必须与公司记录上的唯一字段**完全匹配**
* 对于域名,请使用**域名 URL**(例如,`https://acme.com`),而不是域名标签
* 每个关系只映射**一个**唯一标识符:这将使导入更顺畅
### 步骤 4:核实关系字段是否存在
在上传文件之前,确保对象之间已存在关系字段。
如果不存在:
1. 进入 **设置 → 数据模型**
2. 选择您的对象(例如,人员)
3. 创建一个指向目标对象(例如,公司)的关系字段
### 步骤 5:上传并映射关系
1. 通过导入界面上传您的 CSV 文件
2. 在字段映射步骤中,找到您的关系列(例如,`companyDomain`)
3. 将其映射到关系字段(例如,公司)
4. Twenty 将自动把每条记录关联到匹配的父级
### 可用于关系的唯一字段
| 对象 | 可用的唯一字段 |
| ---------------- | ----------------------- |
| **公司** | `id`、`domain`,任何自定义唯一字段 |
| **人员** | `id`、`email`,任何自定义唯一字段 |
| **工作区成员** | `id`、`email`(而非姓名) |
| **其他标准对象和自定义对象** | `id`,或任何标记为唯一的字段 |
<Note>**关联到工作区成员**:当关系指向工作区成员(您的团队登录 Twenty)时,请使用其**电子邮件地址**进行引用,而不是姓名。</Note>
<Note>我们建议对公司使用 `domain`,对人员使用 `email`,因为这些字段可读性强,且易于在电子表格中维护。</Note>
<Note>**提醒**:软删除的记录(可在“命令菜单 → 查看已删除的记录”中查看)计入唯一性判定标准。 如果您导入的记录与某条已删除记录具有相同的唯一值,该已删除记录将被还原。 详见[唯一性约束](/l/zh/user-guide/data-migration/capabilities/uniqueness-constraints)。</Note>
## 导入顺序规则
<Warning>
**务必先导入“一”端!**
1. **公司** 优先(无依赖关系)
2. **人员** 其次(关联到公司)
3. **商机** 第三(关联到公司/人员)
4. **自定义对象**(按其依赖关系)
在引用之前,父级记录必须已存在。
</Warning>

View File

@@ -0,0 +1,72 @@
---
title: 唯一性约束
description: Twenty 如何在导入过程中强制确保数据唯一性。
---
import { VimeoEmbed } from '/snippets/vimeo-embed.mdx';
## 概览
Twenty 会在特定字段上强制唯一性,以防止重复记录并确保数据完整性。 了解这些约束对于成功导入至关重要。
## 默认唯一字段
| 对象 | 唯一字段 |
| --------- | -------------- |
| **人员** | `id`, `email` |
| **公司** | `id`, `domain` |
| **自定义对象** | 仅 `id`(默认) |
<Note>`id` 字段是 Twenty 的内部标识符,为每条记录自动生成。 它使用 UUID 格式(例如,`c776ee49-f608-4a77-8cc8-6fe96ae1e43f`)。</Note>
## 自定义唯一字段
您可以在 **设置 → 数据模型** 下定义其他唯一字段:
1. 进入 **设置 → 数据模型**
2. 选择一个对象
3. 点击某个字段
4. 在字段设置中启用 **Unique**
### 自定义唯一字段的使用场景
* **外部 ID**:存储来自其他系统的 ID(Salesforce ID、HubSpot ID)
* **业务标识符**:员工编号、客户代码
* **替代联系方式**:LinkedIn 资料、电话号码
<Note>字段名 `id` 保留给 Twenty 的内部 ID。 外部标识符请使用 `externalId` 或 `legacyId` 等其他名称。</Note>
## 导入行为
### 创建新记录
如果唯一字段的值不存在,将创建一条新记录。
### 更新现有记录
如果唯一字段的值与现有记录匹配,该记录将使用新数据进行**更新**。
<Warning>要**更新现有记录**,建议**仅匹配一个唯一字段**。</Warning>
### 软删除的记录
<Warning>
**已删除的记录也会计入唯一性。**
软删除的记录(可在“命令菜单 → 查看已删除的记录”中查看)会包含在唯一性检查中。 如果您导入的记录与某条已删除记录具有相同的唯一值,该已删除记录将被**还原**,并使用新数据。
</Warning>
## 导入过程中的重复检测
在验证阶段:
* 文件中的重复项会以黄色高亮显示
* 开始导入前,您可以在界面中编辑或移除重复的行
<VimeoEmbed videoId="1145246326" title="视频演示" />
## 最佳实践
1. 在导入前,**从文件中移除重复项**
2. 在导入前,在 Twenty 中**检查是否存在现有记录**
3. 从其他系统迁移时,**使用外部 ID**
4. 如果您希望更新现有记录,请**包含唯一字段**