服务端 API/任务 v2/任务/任务功能概述
# 任务功能概述

## 常规使用

使用[创建任务](https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/task-v2/task/create)接口创建一个任务。创建的同时，可以添加任务的初始成员，开始/截止时间，提醒时间等，也可以在创建的任务的同时将其加入1个或多个清单。

使用[获取任务详情](https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/task-v2/task/get)接口可以获取到一个任务的全部数据。

使用[删除任务](https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/task-v2/task/delete)接口可以删除一个任务。对删除的任务无法做任何操作。已删除的任务也无法恢复。

使用[列取任务列表](https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/task-v2/task/list)接口可以获取调用者负责的所有任务。

使用[更新任务](https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/task-v2/task/patch)接口可以修改一个任务的属性，包括标题，描述，截止时间等。但对于任务成员、提醒时间和加入/移出清单有单独的接口。

如要修改任务成员，需要使用[添加任务成员](https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/task-v2/task/add_members)
和[移除任务成员](https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/task-v2/task/remove_members)接口。

如要修改任务提醒，需要使用[添加任务提醒](https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/task-v2/task/add_reminders)和[移除任务提醒](https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/task-v2/task/remove_reminders)接口。

如要变更任务所在的清单，需要使用[任务加入清单](https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/task-v2/task/add_tasklist)和[任务移出清单]( https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/task-v2/task/remove_tasklist)接口。可以通过[列取任务所在清单](https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/task-v2/task/tasklists)接口查看一个任务所在的所有清单。

如需要变更一个任务的依赖，可以使用[添加依赖](https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/task-v2/task/add_dependencies)和[移除依赖](https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/task-v2/task/remove_dependencies)接口。

## 任务是如何鉴权的？
如果调用接口获取/编辑任务数据时得到`1470403`错误码（无权限访问），可以阅读本节内容来检查接口使用的access_token对应的身份是否对任务数据有读取/编辑权限。

任务有两种权限：

* **读取**: 可以查看任务的各种数据，以及其任意子任务。可以对任务发起评论；
* **编辑**: 可以修改任务的标题、描述、截止时间等，可以添加/移除任务成员，可以将任务完成/恢复至未完成，可以添加子任务等。

任务中有两个主要角色：

* 负责人（assignee），拥有对任务的读取和编辑权限；
* 关注人（follower），拥有对任务的读取权限。

此外任务的创建人自动获得任务的读取和编辑权限。

除了任务成员之外，任务还可以通过群组分享，加入清单等方式授权。总体上当一个用户满足如下条件时，可以**读取**该任务的数据：

* 用户是该任务的创建人，负责人或者关注人；
* 用户通过群组收到了这个任务的分享消息；
* 这个任务是一个文档任务（在Lark文档上可以创建任务并同步到Lark任务），该用户是文档的协作人；或者
* 这个任务属于一个清单，而用户是清单的协作成员，
* 这个任务是一个子任务，而用户对该任务的父任务链条上的任何一个任务有读取权限

当一个用户满足如下条件时，可以**编辑**该任务的数据（例如，修改任务标题，增删任务的负责人等）：

* 用户是该任务的创建人或负责人；
* 这个任务是一个文档任务（在Lark文档上可以创建任务并同步到Lark任务），该用户是文档的可编辑协作成员；
* 这个任务属于一个清单，而用户是清单的可编辑成员/所有者，
* 这个任务是一个子任务，而用户对该任务的父任务链条上的任何一个任务有可编辑权限

## 如何完成一个任务或者恢复一个任务为未完成？

使用更新任务接口，将`completed_at`字段设为一个具体的时间戳(ms)表示完成任务。
```json
PATCH /task/v2/tasks/:task_guid
{
  "task": {
     "completed_at": "1688529478195"
  },
  "update_fields":["completed_at"]
}
```

将`completed_at`设为0表示恢复完成任务。

```json
PATCH /task/v2/tasks/:task_guid
{
  "task": {
     "completed_at": "0"
  },
  "update_fields":["completed_at"]
}
```

如果一个任务已经被完成了，就不能被再次完成。即任务的完成时间只能是第一次从未完成变为完成时的时间。如果尝试向一个已经完成的任务设置新的完成时间，会提示报错code=1470400, msg="cannot set non-zero completed_at for a completed task"。

如果希望重新设置一个已经完成的任务的完成时间，则需要先设置`completed_at`为"0"，将任务恢复为未完成状态，然后再次用新的`completed_at`值完成任务。

## 如何使用开始时间和截止时间？

每个任务可以设置开始时间（start）和截止时间（due）用于任务规划。

开始和截止时间的格式相同，均包含`timestamp`和`is_all_day`两个字段:

```json
{
  "timestamp": "1684652400000",
  "is_all_day": false
}
```

其中`is_all_day`表示是时间戳是否表示一个日期。`is_all_day=true`表示一个日期；`is_all_day=false`表示一个时刻。如果不填写`is_all_day`则默认为false。

当开始/截止时间表示一个时刻时，其timestamp是一个精度为秒的，距离1970-01-01 00:00:00 UTC的以毫秒为单位的时间戳。在展示时刻时，LarkApp会利用用户的时区设置将这个时间戳转换为显示的具体时间。

例如同一个任务，具有截止时间为时刻`timestamp=1684652400000, is_all_day=false`。该任务有两个成员，分别是使用时区+08:00的用户A，和使用时区-07:00的用户B。则用户A在界面上看到的是任务截止于"2023-05-21 15:00:00"，用户B看到的是任务截止于"2023-05-21 00:00:00"。

当开始/截止时间表示一个日期时, 其timestamp是一个精度为天的，距离1970-01-01 00:00:00 UTC的以毫秒为单位的时间戳。例如：

```json
{
  "timestamp": "1682899200000",
  "is_all_day": true
}
```

在展示日期时，不管用户的时区是什么，看到的是同一个日期。例如截止时间为日期`timestamp=1682899200000, is_all_day=true`。该任务有两个成员，分别是使用时区+08:00的用户A，和使用时区-07:00的用户B。则用户A和用户B看到的都是任务截止于"2023-05-01"。

当调用创建任务/更新任务设置开始/截止时间时，如果`timestamp`的数值精度超过了其业务精度，会被自动截取。对于时刻，只保留秒精度的时间戳；对于日期，只保留天精度的时间戳。

如果将开始/截止时间的`timestamp`设为0，表示清除该时间。例如更新任务时，完全将`task.due`设为空和设置`task.due.timestamp`为0是等价的。

```json
PATCH /task/v2/tasks/:task_guid
{
  "task": {
     "due": null
  },
  "update_fields": ["due"]
}

PATCH /task/v2/tasks/:task_guid
{
  "task": {
     "due": {
       "timestamp": "0"
     }
  },
  "update_fields": ["due"]
}
```

`timestamp`也不能被设为负数。这意味着任务的开始/截止时间不能设置1970-01-01之前的时刻/日期。

开始时间和截止时间可以独立设置。一个任务可以完全不设置开始/截止时间；有开始时间，没有截止时间；没有开始时间，有截止时间；或者同时拥有开始开始和截止时间。但**如果同时拥有开始和截止时间，则需要满足如下约束**：
* 开始时间的时间戳必须不晚于截止时间的时间戳，即`start.timestamp <= due.timestamp`；
* 开始/截止时间的"is_all_day"必须同时是true或者同时是false。

## 如何使用Origin?
任务的Origin用来记录一个任务来源，并在任务中心展示。一个应用在创建任务时，可以填写期望显示的Origin信息，便于后续追踪和筛选。Origin是可选的。使用`tenant_access_token`创建任务时，如果不设置Origin，则系统会自动将应用的名称作为Origin的platform_i18n_name。

Origin只能在创建时候设置，一旦设置后就**不可更改**。

Origin结构体中各字段含义为：
| 字段         | 意义        | 描述        |
| --------- | ---------------  |  --------- |
|platform_i18n_name | 导入来源 | 用于在任务中心详情页展示，使用时需要提供一个字典，多种语言名称映射，应用在使用不同语言时，导入来源也将展示对应的内容。支持的各地区语言名：zh_cn,  en_us, it_it, th_th, ko_kr, es_es, ja_jp, id_id, zh_hk, pt_br, de_de, fr_fr, zh_tw, ru_ru, hi_in, vi_vn。<br>只填写需要支持的语种即可。 |
|href.url|具体链接地址|可以不填写，但如果填写，则必须是合法的url：以http://或者https://开头。|
|href.title|对应链接的标题|可选。如果同时填写了url和title，title将会以链接的方式展示和支持点击跳转。|

在一个Origin中，一般建议`platform_i18n_name`用来指代应用本身的名字；`title`+`url`则填写具体和任务关联的信息的名称和访问url。

例如，企业自己有一个工单系统，开发了一个应用“工单助手”关联工单系统里的工单和Lark任务。当为一个工单创建一个任务时，`platform_i18n_name`应该填写工单系统的名字，或者工单助手这个应用的名字，`title`应该填写具体这个工单的名字，`url`应该填写具体工单的url。这样就可以在Lark任务界面中根据任务的来源做分组和筛选，同时点击任务的来源就可以跳转到工单系统对应的界面上。

请求样例：
```
POST https://open.larksuite.com/open-apis/task/v2/tasks
{
    "summary": "用户点击确认不生效",
    "origin": {
         "platform_i18n_name": {
             "zh_cn": "工单系统Ticket",
             "en_us": "ticket system"
         },
         "href": {
             "title": "用户点击确认不生效",
             "url": "https://abc.com"
         }
    }
}
```
会得到如下效果：

| 任务详情       | 任务列表           |   
| --------- | --------------- |
|![image.png](//sf16-sg.larksuitecdn.com/obj/open-platform-opendoc-sg/cb6ebe8e7d0dd22284b15a167c5a4c9c_Tcl19aS8rp.png?height=514&lazyload=true&width=786)| ![image.png](//sf16-sg.larksuitecdn.com/obj/open-platform-opendoc-sg/a3268cba2924aff063770bde93c9e235_IjLiDAgqP5.png?height=614&lazyload=true&width=1784) | 

## 如何使用任务自定义完成？

任务自定义完成”是指用户可以自定义“任务在套件App界面的任务详情界面点击完成时的动作。该功能主要用于Lark任务和其他第三方系统同步完成状态。

当在界面上点击设置了自定义完成的任务的完成选框时，将跳转到第三方界面或产生提示信息引导用户去往第三方系统。用户第三方系统完成事项后，第三方系统再通过任务api来设置任务完成状态。

例如一个第三方工单系统通过api创建了Lark任务，并设置了自定义完成跳转链接。用户在Lark任务界面点击【完成任务】后，任务不会被设置为完成状态，而是引导用户跳转到第三方的工单系统的对应工单上。在这个界面上，用户可以按照工单的设置填写必要的信息，并完成工单。之后工单系统就可以调用任务的接口将任务设置为完成，实现Lark任务和三方工单系统的工单的完成状态一致。

将任务设置为”自定义完成“的方式是设置任务的`custom_complete`字段。该字段可以在[创建任务](https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/task-v2/task/create)时设置，也可以通过[更新任务](https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/task-v2/task/patch)接口修改。

`custom_complete`字段有两种使用方式，格式如下：

1. 设置点击完成任务后跳转到第三方页面：
```json
{
  "custom_complete":{
    "android":{
      "href":"https://www.wikipedia.org/"
      },
     "ios":{
       "href":"https://www.wikipedia.org/"
      },
     "pc":{
       "href":"https://www.wikipedia.org/"
      }
   }
}
```

可以设置不同终端跳转不同的链接。

例如，将href设置为页面链接`https://www.wikipedia.org/`，点击完成任务后将直接跳转到该页面，点击跳转效果如下：

![屏幕录制2023-07-14 21.24.32.gif](//sf16-sg.larksuitecdn.com/obj/open-platform-opendoc-sg/0ba3ea21943ba9c68e740c72a0c7040f_R97mmGl0yz.gif?height=1978&lazyload=true&width=3450)

2. 设置点击完成任务后展示提示语，可以支持多语言：
```json
{
"custom_complete":{
  "android":{
    "tip":{
      "zh_cn":"请前往指定页面完成任务",
      "en_us":"please go to the designated page to complete the task"
     }
    },
   "ios":{
     "tip":{
       "zh_cn":"请前往指定页面完成任务",
       "en_us":"please go to the designated page to complete the task"
      }
    },
   "pc":{
     "tip":{
       "zh_cn":"请前往指定页面完成任务",
       "en_us":"Please go to the designated page to complete the task"
      }
    }
}
```

该格式支持如下语种: zh_cn, en_us, it_it, th_th, ko_kr, es_es, ja_jp, id_id, zh_hk, pt_br, de_de, fr_fr, zh_tw, ru_ru, hi_in, vi_vn。开发者只需要填写需要支持的语种文案即可。

例如：使用提示语，将"tip"设置为`{"zh_cn":"请前往指定页面完成任务"}`，显示效果如下：
![20a6534f-0a46-4518-9aa7-3eaa866e5fe5.gif](//sf16-sg.larksuitecdn.com/obj/open-platform-opendoc-sg/9ed0fc0ad9b525a8a9f10dd1166e2b88_O4fNEJdw7R.gif?height=1484&lazyload=true&width=2270)

如果同时填写tip和href，则使用href，即”跳转行为“。

## 如何使用重复任务？

如果将一个任务设置了重复规则，就会成为“重复任务”。当将一个重复任务完成后，系统会自动将已完成的任务复制一份，创建一个同样的任务，同时将新任务的截止时间根据重复规则设置为截止时间。

![image.png](//sf16-sg.larksuitecdn.com/obj/open-platform-opendoc-sg/6aaad9ca108aa726fd3dac1e101af68b_NrnVqI5t6j.png?height=453&lazyload=true&width=1280)

例如，创建一个重复任务T1，其截止时间(due)为"2023-03-15 18:00:00"，重复规则是“每天重复”。当将T1完成后，会自动产生一个T1的副本T2，其截止时间被设为"2023-03-16 18:00:00"。

可以在创建任务时直接设置任务的`repeat_rule`字段，或者将一个已有任务通过更新任务接口设置`repeat_rule`字段，将其变为一个重复任务。但留意，要将一个任务设为重复任务，必须首先设置任务的截止时间，否则接口会报错。

如果要将一个重复任务恢复为普通任务，只需要通过调用更新任务接口将其`repeat_rule`的规则设为空即可。

`repeat_rule`字段的值是一个满足[RFC5545](https://datatracker.ietf.org/doc/html/rfc5545)规范的RRULE字符串的子集。比如：
* `FREQ=DAILY;INTERVAL=1`表示新任务截止时间会设为已完成任务截止时间的下一天的同一时刻。
* `FREQ=WEEKLY;INTERVAL=1;BYDAY=MO,TU,WE,TH,FR`表示新任务截止时间会设为已完成任务截止时间的下个工作日（周一到周五）的同一时刻。
* `FREQ=WEEKLY;INTERVAL=2`表示新任务截止时间会设为已完成任务截止时间的下两周的同一时刻。
* `FREQ=MONTHLY;INTERVAL=1;WKST=MO;BYDAY=2FR`表示新任务截止时间会设为已完成任务截止时间的下个月的第二个周五的同一时刻。

由于Lark任务只支持RRULE规范的子集，Lark任务并不能保证可以支持任意符合RFC5545规范的RRULE字符串。如果要构造一个Lark任务可用的`repeat_rule`，一个简单的方式是在Lark任务的界面上设置一个重复规则，然后调用[获取任务详情接口](https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/task-v2/task/get)得到其`repeat_rule`字符串。

当对更新任务时，不能同时更新`repeat_rule`和`completed_at`。因为完成一个任务时会自动删除其重复规则（因此界面上已经完成的重复任务的重复规则提示会消失）。同时修改二者会导致未定义的行为，因此接口会对这样的请求直接报错。

类似，也不能在更新任务设置`repeat_rule`的同时将`due`清除，因为重复任务需要due才能计算完成后的截止时间。
