服务端 API/任务 v2/自定义字段/自定义字段概述
# 自定义字段功能概述
任务功能支持在任务中扩充自定义字段，更清晰地添加任务关键信息，高效管理任务，辅助协作推进。任务的使用者可以在使用“任务截止时间”，“任务负责人”……等系统字段之外，自行定义如”优先级“，”项目发布日期“，”价格“等和使用场景密切相关的字段。

自定义字段需要区分“**自定义字段的设置**”和“**自定义字段的值**”两个关联的概念。

自定义字段的设置是是自定义字段的元数据，包含名称、类型和具体设置。每个自定义字段必须有一个名字。

当前已经支持的自定义字段类型如下：

| **字段类型** | **描述**                           |
| --------  | -------------------------------- |
| 数字(number)      | 支持表达一个数值，并以不同的格式在App显示  |
| 人员(member)      | 支持添加内外部联系人；可同时选择多个人员             |
| 日期(datetime)      | 支持表达一个具体的日期                   |
| 单选(single_select) | 用于给任务添加标签，支持自定义标签内容与颜色；仅可选择一个标签  |
| 多选(multi_select)  | 用于给任务添加标签，支持自定义标签内容与颜色；可同时选择多个标签 |
| 文本(text)          | 用于添加一段自定义的文本描述  |

每种类型的设置各不相同，比如对于数字类型，可以设置数字格式，是否显示自定义符号，以及符号的位置等；对于日期类型，可以设置日期的显示格式；对于单选/多选，可以设置选项。

自定义字段的设置相关接口包括：

* [创建自定义字段](https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/task-v2/custom_field/create)
* [更新自定义字段](https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/task-v2/custom_field/patch)
* [获取自定义字段](https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/task-v2/custom_field/get)
* [列取自定义字段](https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/task-v2/custom_field/list)
* [将自定义字段加入资源](https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/task-v2/custom_field/add)
* [将自定义字段移出资源](https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/task-v2/custom_field/remove)

针对单选/多选两种类型的字段中的选项，支持：
* [创建自定义字段选项](https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/task-v2/custom_field-option/create)
* [更新自定义字段选项](https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/task-v2/custom_field-option/patch)

自定义字段的值类似于系统内建字段的值。在某个清单定义了自定义字段后，就可以给该清单里的任务设置字段值。比如，可以通过[更新任务](https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/task-v2/task/patch)接口来设置自定义字段的值，也可以通过[创建任务](https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/task-v2/task/create)接口在任务创建时就设置自定义字段的值。同时，用户可以通过[获取任务详情](https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/task-v2/task/get)接口查看该任务的自定义字段值。

## 数据模型和鉴权

自定义字段和清单是多对多的关系。一个清单里可以定义多个自定义字段。一个自定义字段也可以被加入多个清单。

自定义字段的权限是根据清单来定义的。一个用户对一个自定义字段有编辑/读取权限，就意味着至少存在一条用户-清单-自定义字段的关联关系，且用户对该清单有编辑/读取权限（关于清单的鉴权方式见[清单功能概述](https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/task-v2/tasklist/overview)）。如果用户和自定义字段之间存在多条“清单”的管理，用户对自定义字段的权限取其中最大的一条边的权限。因此[创建自定义字段](https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/task-v2/custom_field/create)时，总是要关联到清单才能添加这些清单的自定义字段；也可以通过[将自定义字段加入资源](https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/task-v2/custom_field/add)接口将某个自定义字段添加入其他的清单。添加后，清单界面的“字段设置”中就可以查看该字段；同时该清单的所有其他协作成员也会获取该字段的相应权限。如不希望一个字段在某个清单上显示，可以通过[将自定义字段移出资源](https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/task-v2/custom_field/remove)接口将其移出。移出后，原清单的协作成员将失去该字段的权限，除非他们通过其他清单也能访问到该自定义字段。

例如，存在一个用户U1，对清单L1有编辑权限，对清单L2有阅读权限。L1拥有自定义字段F1，F2；L2拥有自定义字段F2和F3。则用户对F1和F2有编辑权限；对F3有阅读权限。如果还有一个清单L3，U1无法访问，L3拥有自定义字段F3和F4。则用户对F4无权限。但如果刚好有另外一个用户U2同时拥有对L1和L3的编辑权限。U2就获得了F4编辑权限。他可以将F4添加到L1中，之后U1就也对F4拥有可编辑权限了。如下图所示：

![image.png](//sf16-sg.larksuitecdn.com/obj/open-platform-opendoc-sg/2d0d940e6a0b816c37b84abfa8aaf21f_Yjz98o77AK.png?height=1128&lazyload=true&maxWidth=500&width=1398)

可以通过[列取自定义字段](https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/task-v2/custom_field/list)接口查询调用身份所有有权限的自定义字段，或者通过指定清单GUID查看某一个清单中的自定义字段。

如果一个自定义字段被移出所有的清单，就意味着没有用户再可以访问到它。从用户视角看，被移出所有清单的自定义字段相当于被删除了。但目前并不支持直接删除自定义字段的操作。

自定义字段的值同时归属于任务和自定义字段。用户要查看到一个任务的自定义字段值，必须满足用户对任务有读取权限（详见[任务功能概述](https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/task-v2/task/overview)，同时用户需要拥有自定义字段的读取权限；类似的，用户想要修改一个任务的自定义字段的值，必须同时拥有任务的编辑权限和自定义字段的编辑权限。

例如一个任务T有3个自定义字段的值F1，F2和F3。用户U1可以编辑T，同时对F1和F2有阅读权限，他可以通过[获取任务详情](https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/task-v2/task/get)接口查看到F1和F2对应的值，但F3的值对他不可见。

自定义字段的值也不可以删除，但可以“清空”，即设为“无”。

## 数字类型自定义字段

数字类型自定义字段可以用于显示一个数字，例如

```json
{
  "guid": "d1fd19fd-4810-479d-a093-fb9b0442c6f6",
  "name": "price",
  "type": "number",
  "number_setting": {
    "format": "custom",
    "decimal_count": 2,
    "separator": "thousand",
    "custom_symbol": "€",
    "custom_symbol_position": "right"
  }
}
```
表示按照自定义符号的方式显示数字，小数位数为2位。整数部分显示千分隔符，在数字右侧会显示€符号。除`decimal_count`外的设置仅会影响App中的显示效果，对openapi的字段值的输入输出无影响。

`decimal_count`会影响数字的小数位数，最大支持6位小数。用户输入的字段超过该设置会被自动四舍五入。

此外，当`format`不是"custom"时，`custom_symbol`可以不设置；但如果`format`是"custom"，则`custom_symbol`必须设置为最大4个字符的字符串。

该类型字段支持常规的数字（考虑到json的精度问题，会用字符串的格式来输入输出），比如：
```
PATCH /task/v2/tasks/:task_guid
{
   "task": {
     "custom_fields": [
        {
           "guid": "b78a2bca-b580-4853-b3f8-2ebd477d91ca",
           "number_value": "12.34"
        }
      ]
   },
   "update_fields": ["custom_fields"]
}
```
可以将一个任务的数字自定义字段（custom_field_guid=b78a2bca-b580-4853-b3f8-2ebd477d91ca)设为12.34。

一些合法的数字如：

* "1.23"
* "0.9248"
* "0"
* "-12.45"
* "+6"

而如下输入会被视作非法:

* "1.2.3" (不是个数字)
* "1e9" (不支持科学计数法）
* " 99 " (有空格）
* "0x125" (不支持16进制，带有非数字的符号视作非法)
* "20%" (不支持直接输入带百分号的数字，如输入百分数，要输入实际的值0.2)

空字符串""被视作“空”数字。

数字输入时会自动存储为等值的最简格式，例如:

* 输入"1.200"会只保留"1.2"
* 输入"054"只会保留"54"，0开头的数字不会被当作8进制解析，只会被视作是10进制高位冗余的0
* 输入"+67.1"会只保留"67.1"

数字输入时如果超过了decimal_count规定的值将被四舍五入：
* 输入"20.124", decimal_count=2，会得到"20.12"
* 输入"0.1558"，decimal_count=2，会得到"0.16"

当输入一个百分数`format=percentage`时，依然输入数字的原始的值。比如：
* 输入"0.2"，decimal_count=0, 界面会显示"20%"
* 输入"2.45"，decimal_count=2, 界面会显示"245.00%"

需要留意当输入为百分数时，decimal_count是指显示为百分数之后的小数位数。因此其实际的小数位数比非百分数总是大2。如输入"0.24563", decimal_count=2；
* 当`format`不是百分数时，会得到"0.25"
* 当`format`是百分时，会得到"0.2556"（界面上显示25.56%)

修改一个数字自定义字段的`decimal_count`不会改变已经设置的字段值，但会影响界面上的显示。比如`decimal_count`设为2，然后写入一个该字段的值"1.23"，之后修改`decimal_count`为1。通过openapi获取的字段值依然为"1.23"，但界面上会显示为"1.2"，同时筛选/排序等功能都会按照"1.2"来执行。

## 人员类型自定义字段

人员类型可以填写一个或多个用户。比如：

```json
{
  "guid": "b78a2bca-b580-4853-b3f8-2ebd477d91ca",
  "name": "reviewers",
  "type": "member",
  "member_setting": {
    "multi": true,
  }
}
```
表示设置一个人员类型的字段，字段支持多选，可以在写入值时填写多个用户的信息。

人员类型的值用"member"表示。类似于[添加任务成员](https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/task-v2/task/add_members)中的成员格式，但不支持填写`role`,只能填写`id`和`type`。`type`只支持"user"，同时也是默认值，因此可以省略。`id`必须填写，其格式根据`user_id_type`参数来定义（见[功能概述](https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/task-v2/overview)中的"如何使用user_id_type修改用户ID格式？")，默认为"open_id"。

```
PATCH /task/v2/tasks/:task_guid
{
   "task": {
     "custom_fields": [
        {
           "guid": "b78a2bca-b580-4853-b3f8-2ebd477d91ca",
           "member_value": [
              { "id": "ou_49dadcd6fd55da971d887087c4f3a37a" },
              { "id": "ou_2cefb2f014f8d0c6c2d2eb7bafb0e54f" }
           ]
        }
      ]
   },
   "update_fields": ["custom_fields"]
}
```

当`multi`设为false后，`member_value`只能设置一个元素。如果一个字段值已经设为多个人员，之后字段的`multi`由true改为false后，也不会影响字段值，直到字段值在下一次修改。

当`multi`设为true时，`member_value`中的多个元素不允许重复。

人员类型字段值使用空数组来表示“空”。

## 日期类型自定义字段

日期类型可以填写一个表示日期的时间戳。其设置为：

```json
{
  "guid": "a0fddac1-0fd5-4903-8cae-5b93ccf0f797",
  "name": "release day",
  "type": "datetime",
  "datetime_setting": {
    "format": "yyyy/mm/dd",
  }
}
```

日期自定义字段的设置只影响App显示格式。

日期自定义字段的值使用以毫秒为单位的时间戳格式表示，但精度只保留到天。

```
PATCH /task/v2/tasks/:task_guid
{
   "task": {
     "custom_fields": [
        {
           "guid": "b78a2bca-b580-4853-b3f8-2ebd477d91ca",
           "datetime_value": "1666108800000"
        }
   },
   "update_fields": ["custom_fields"]
}
```

要设置某个日期的字段值，需要用该日期UTC时间的00:00:00的时间戳表示。比如，使用javascript的moment库可以这样产生：

```
let m = require('moment');
m('2022-10-19T00:00:00Z').valueOf();
// 得到1666137600000
```

在设置字段值时，如果精度超过了天，会被自动舍去。比如输入了"1666137600322"，只会保留"1666137600000"。

日期类型字段只支持正数时间戳（即表示1970-01-01之后的日期），填入负数时间戳会提示错误。

日期类型字段值使用空字符串""表示空。

## 单选/多选类型自定义字段

单选和多选的设置类似，都是提供一组选项。区别是单选的值只能设置一个选项；而多选可以设置多个选项。

单选的例子：
```json
{
  "guid": "a0fddac1-0fd5-4903-8cae-5b93ccf0f797",
  "name": "priority",
  "type": "single_select",
  "single_select_setting": {
    "options": [
      {"guid": "734a0135-fcbb-4482-8909-f9589b03d9f1", "name": "high", "color_index": 23, "is_hidden": false},
      {"guid": "89a7d5b0-e29f-4363-a614-1fe47f2d3255", "name": "mid", "color_index": 24, "is_hidden": false},
      {"guid": "f911b99f-c6df-477a-a014-8b76ac40aa00", "name": "low", "color_index": 23, "is_hidden": false},
     ]
  }
}
```

多选的例子：
```json
{
  "guid": "7748b214-d299-4fc3-9d12-d95ef39979f7",
  "name": "publish regions",
  "type": "multi_select",
  "multi_select_setting": {
    "options": [
      {"guid": "345638bd-35b2-48a3-b3cd-ca17169a674f", "name": "america", "color_index": 10, "is_hidden": false},
      {"guid": "439615eb-2d11-41f6-b1c7-4418fd96dd62", "name": "asia", "color_index": 15, "is_hidden": false},
      {"guid": "f911b99f-c6df-477a-a014-8b76ac40aa00", "name": "europe", "color_index": 14, "is_hidden": false},
     ]
  }
}
```

单选的字段值就是该字段的一个选项的GUID；多选字段的值是本字段一个或多个选项的GUID。同一个多选字段的值中的选项GUID不能重复。
```
PATCH /task/v2/tasks/:task_guid
{
   "task": {
     "custom_fields": [
        {
           "guid": "a0fddac1-0fd5-4903-8cae-5b93ccf0f797",
           "single_select_value": "89a7d5b0-e29f-4363-a614-1fe47f2d3255"
        },
        {
           "guid": "7748b214-d299-4fc3-9d12-d95ef39979f7",
           "multi_select_value": [
             "345638bd-35b2-48a3-b3cd-ca17169a674f",
             "0f8165c6-b6f9-45e6-ad47-618189546007"
           ]
        }
   },
   "update_fields": ["custom_fields"]
}
```

单选字段值使用空字符串表示空；多选使用空数组表示空。

### 关于选项

每个选项包含一个名字，一个颜色索引值，一个隐藏标记(is_hidden) 。选项因为需要关联字段值的缘故，不允许删除，否则字段值就无法找到对应的选项了。但选项可以被标记为隐藏(is_hidden=true)。标记为隐藏的选项将不出现在界面中，openapi也不允许将一个单选/多选的字段值设置为一个隐藏的选项。

一个单选/多选字段最多有100个选项（包含隐藏和可见）。

不被隐藏的选项被称为“可见选项”，单选/多选的设置需要满足如下约束：**同一字段的所有可见选项不得重名**。因此尝试用openapi创建一个带有同名可见选项的单选/多选字段，或者将一个隐藏的字段恢复为可见，刚好与另外一个可见的选项重名都会得到一个错误。

选项的颜色索引（`color_index`)是一个0～54的枚举值。每一个数值代表一个颜色。创建时如果不指定，则会随机选择一个。下图是`color_index`的值与颜色的对应关系。

![image.png](//sf16-sg.larksuitecdn.com/obj/open-platform-opendoc-sg/cced3489eb55a2b84b11aa055d4790a9_PCApI3mDxw.png?height=596&lazyload=true&maxWidth=600&width=2108)

选项存在顺序。可见选项在openapi中的返回顺序就是其在界面中的显示顺序。可以通过[创建自定义字段选项](https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/task-v2/custom_field-option/create)和[更新自定义字段选项](https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/task-v2/custom_field-option/patch)中的`insert_before`或者`insert_after`来调整选项的顺序，或者直接通过[更新自定义字段](https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/task-v2/custom_field/patch)接口来直接设定可见选项的顺序。

## 文本类型自定义字段

文本类型自定义字段允许用户为一个任务填写一段文本描述。文本类型除了通用的字段名外没有类型专用的设置：
```json
{
  "guid": "a0fddac1-0fd5-4903-8cae-5b93ccf0f797",
  "name": "review comment",
  "type": "text",
  "text_setting": {}
}
```

该类型字段支持输入一段文本。输入格式和任务的系统字段标题（`summary` ）完全相同。
```
PATCH /task/v2/tasks/:task_guid
{
   "task": {
     "custom_fields": [
        {
           "guid": "b78a2bca-b580-4853-b3f8-2ebd477d91ca",
           "text_value": "这是一段文本"
        }
      ]
   },
   "update_fields": ["custom_fields"]
}
```

可以使用空字符串""将文本自定义字段的值设为空。

