19 KiB
Mission 任务模块 API 文档
更新日期:2026-07-03
本文档面向前端,描述 mission 中立任务模块的对外 API。当前 mission API 仅在 api_v2 提供;已检查 api_v1/urls.py,api_v1 暂无 mission 相关接口。
1. 基本约定
- Base URL:
/api/v2 - 认证:所有 mission 接口均需要登录。
- 当前员工:后端使用
request.user.employee作为当前业务员工。 - 商户隔离:任务、任务分类、参与者、回应均按当前员工所属
merchant隔离。 - 参与者对象:任务参与者是
basic_info.Employee,不是 DjangoUser。 - 删除任务:不提供物理删除任务接口;业务结束请使用取消接口。
- 普通创建/更新接口不允许直接修改状态字段,状态变化必须走独立状态接口。
普通创建/更新禁止提交字段:
| 字段 | 说明 |
|---|---|
is_urgent |
是否紧急,使用 set-urgent 接口修改 |
is_completed |
是否完成,由结束回应、reopen、reject 流程维护 |
is_cancelled |
是否取消,使用 cancel 接口修改 |
cancelled_by |
取消人,由后端写入 |
cancelled_at |
取消时间,由后端写入 |
rejected_by |
回应撤销人,由后端写入 |
rejected_at |
回应撤销时间,由后端写入 |
2. API v1 状态
已检查 api_v1/urls.py 和 api_v1/views,当前没有 mission 模块接口。
如前端需要任务模块,请使用本文档中的 /api/v2/... 接口。
3. 核心数据结构
3.1 EmployeePayload
任务模块中所有人员字段均使用员工对象摘要:
{
"id": 21,
"name": "李四",
"merchant_id": 10
}
3.2 MissionCategory
{
"id": 1,
"merchant": 10,
"name": "通用",
"payload_processor": "",
"speech_enabled": false,
"created_at": "2026-07-03T10:00:00+08:00",
"updated_at": "2026-07-03T10:00:00+08:00"
}
字段说明:
| 字段 | 类型 | 说明 |
|---|---|---|
id |
number | 任务分类 ID |
merchant |
number | 所属商户 ID |
name |
string | 分类名称,同商户内唯一 |
payload_processor |
string | payload 增强器,可为空;当前可选 structured_description_v1 |
speech_enabled |
boolean | 是否启用任务播报 |
created_at |
string | 创建时间 |
updated_at |
string | 更新时间 |
3.3 Mission
{
"id": 1,
"merchant": 10,
"description": "请跟进这张生产单",
"category": 1,
"category_name": "通用",
"is_urgent": false,
"is_completed": false,
"is_cancelled": false,
"notify_if_unreplied": true,
"unreplied_notify_interval_minutes": 30,
"unreplied_notify_max_count": 5,
"unreplied_notify_sent_count": 0,
"unreplied_last_notified_at": null,
"cancelled_at": null,
"creator": {
"id": 20,
"name": "张三",
"merchant_id": 10
},
"cancelled_by": null,
"participants": [
{
"id": 21,
"name": "李四",
"merchant_id": 10
}
],
"content_type": 33,
"content_type_label": "printing.printingorder",
"content_id": 123,
"extra": {
"source": "printing-order"
},
"has_ending_reply": false,
"can_reply": true,
"created_at": "2026-07-03T10:00:00+08:00",
"updated_at": "2026-07-03T10:00:00+08:00"
}
字段说明:
| 字段 | 类型 | 说明 |
|---|---|---|
id |
number | 任务 ID |
merchant |
number | 所属商户 ID |
description |
string | 任务描述 |
category |
number | MissionCategory.id |
category_name |
string | 分类名称 |
is_urgent |
boolean | 是否紧急 |
is_completed |
boolean | 是否完成 |
is_cancelled |
boolean | 是否取消 |
notify_if_unreplied |
boolean | 是否开启未回复提醒 |
unreplied_notify_interval_minutes |
number/null | 未回复提醒间隔,单位分钟 |
unreplied_notify_max_count |
number | 未回复最大提醒次数,默认 5 |
unreplied_notify_sent_count |
number | 已发送未回复提醒次数 |
unreplied_last_notified_at |
string/null | 上一次未回复提醒时间 |
cancelled_at |
string/null | 取消时间 |
creator |
EmployeePayload | 创建员工 |
cancelled_by |
EmployeePayload/null | 取消员工 |
participants |
EmployeePayload[] | 最终展开后的任务参与员工列表 |
content_type |
number/null | django_content_type.id |
content_type_label |
string/null | 可读模型标识,例如 printing.printingorder |
content_id |
number/null | 关联对象 ID |
extra |
object/null | 扩展字段 |
has_ending_reply |
boolean | 是否已有结束任务的有效回应 |
can_reply |
boolean | 当前是否允许继续回应 |
created_at |
string | 创建时间 |
updated_at |
string | 更新时间 |
3.4 MissionLite
MissionLite 用于轻量查询,字段与 Mission 基本一致,但不返回 participants、has_ending_reply、can_reply。
3.5 MissionReply
{
"id": 100,
"mission": 1,
"merchant": 10,
"responder": {
"id": 20,
"name": "张三",
"merchant_id": 10
},
"content": "已处理",
"extra": {
"attachment_ids": [1001, 1002]
},
"replied_at": "2026-07-03T10:10:00+08:00",
"ends_task": true,
"is_rejected": false,
"rejected_by": null,
"rejected_at": null,
"created_at": "2026-07-03T10:10:00+08:00",
"updated_at": "2026-07-03T10:10:00+08:00"
}
字段说明:
| 字段 | 类型 | 说明 |
|---|---|---|
id |
number | 回应 ID |
mission |
number | Mission.id |
merchant |
number | 所属商户 ID |
responder |
EmployeePayload | 回应员工 |
content |
string | 回应内容 |
extra |
object/null | 扩展字段 |
replied_at |
string | 回应时间 |
ends_task |
boolean | 是否结束任务 |
is_rejected |
boolean | 是否已被撤销 |
rejected_by |
EmployeePayload/null | 撤销员工 |
rejected_at |
string/null | 撤销时间 |
created_at |
string | 创建时间 |
updated_at |
string | 更新时间 |
3.6 MissionWithReplies
在 Mission 结构基础上额外返回 replies:
{
"id": 1,
"description": "请跟进这张生产单",
"participants": [],
"replies": [
{
"id": 100,
"mission": 1,
"content": "已处理",
"ends_task": true,
"is_rejected": false
}
]
}
4. 参与者参数规则
任务创建和任务更新支持两类参与者参数:
| 参数 | 类型 | 说明 |
|---|---|---|
participant_ids |
number[] | 显式参与员工列表,传 Employee.id |
employee_type_ids |
number[] | 职位列表,传 EmployeeType.id,后端会展开为该职位下的在职员工 |
最终参与者计算规则:
最终参与者 = participant_ids 中的员工 + employee_type_ids 对应职位下的在职员工
详细规则:
participant_ids传的是Employee.id。employee_type_ids传的是EmployeeType.id。employee_type_ids只允许传当前商户下的职位。- 职位展开时只加入
status=ACTIVE的员工。 - 重复员工会自动去重。
- 职位下没有员工不会报错。
- 传入不存在或跨商户的
EmployeeType.id会返回 400。 PATCH /missions/{mission_id}/中,只要传了participant_ids或employee_type_ids,即表示重新设置最终参与者列表,不是增量追加。PATCH /missions/{mission_id}/中,如果两个参数都不传,则不修改原参与者。
清空参与者:
{
"participant_ids": [],
"employee_type_ids": []
}
5. content_type 规则
content_type 和 content_id 用于把任务挂靠到业务对象上。
content_type是django_content_type.id。content_id是对应业务对象主键。- 两者必须同时提交或同时省略。
- 前端不应硬编码
content_type,不同环境的 ID 可能不同。 - 推荐通过
GET /api/v2/content-types/获取可用值。
响应中的 content_type_label 是只读辅助字段,格式为:
app_label.model
例如:
printing.printingorder
business.salesorder
当前允许前端用于 mission 关联的业务对象:
| content_type_label | 中文说明 |
|---|---|
printing.plateorder |
开版单 |
printing.printingorder |
印刷单 |
printing.printingjob |
印刷任务 |
business.purchaseorder |
采购单 |
business.presalesorder |
预销售单 |
business.salesorder |
销售单 |
business.prepurchaseorder |
预采购单 |
business.purchasereturnorder |
采购退货单 |
business.salesreturnorder |
销售退货单 |
business.paymentorder |
付款单 |
business.receiptorder |
收款单 |
stock.transferorder |
调拨单 |
shipment.shipment |
发货单 |
stateflow.process |
工艺流程实例 |
6. 接口列表
6.1 查询可用 content_type
GET /api/v2/content-types/
响应:200 OK
[
{
"id": 33,
"app_label": "printing",
"model": "printingorder",
"label": "printing.printingorder",
"name": "印刷单"
}
]
6.2 查询任务分类列表
GET /api/v2/mission-categories/
响应:200 OK
[
{
"id": 1,
"merchant": 10,
"name": "通用",
"payload_processor": "",
"speech_enabled": false,
"created_at": "2026-07-03T10:00:00+08:00",
"updated_at": "2026-07-03T10:00:00+08:00"
}
]
6.3 创建任务分类
POST /api/v2/mission-categories/
请求体:
{
"name": "生产跟进",
"speech_enabled": true,
"payload_processor": "structured_description_v1"
}
请求字段:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
name |
string | 是 | 分类名称,同商户内唯一 |
speech_enabled |
boolean | 否 | 是否启用播报,默认 false |
payload_processor |
string | 否 | 可为空;可选 structured_description_v1 |
响应:201 Created,返回 MissionCategory。
常见错误:
{"name": ["分类名称已存在"]}
6.4 查询任务分类详情
GET /api/v2/mission-categories/{category_id}/
响应:200 OK,返回 MissionCategory。
6.5 更新任务分类
PATCH /api/v2/mission-categories/{category_id}/
请求体:
{
"name": "售后跟进",
"speech_enabled": false,
"payload_processor": ""
}
响应:200 OK,返回 MissionCategory。
6.6 删除任务分类
DELETE /api/v2/mission-categories/{category_id}/
响应:
204 No Content:删除成功。400 Bad Request:分类已被任务使用,不能删除。
错误示例:
{"detail": "任务分类已被使用,不能删除"}
6.7 查询任务列表
GET /api/v2/missions/
查询参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
category |
number | 否 | 按任务分类 ID 过滤 |
is_urgent |
boolean | 否 | 按是否紧急过滤,支持 1/0/true/false/yes/no |
is_completed |
boolean | 否 | 按是否完成过滤 |
is_cancelled |
boolean | 否 | 按是否取消过滤 |
content_type |
number | 否 | 按 content_type ID 过滤 |
content_id |
number | 否 | 按关联对象 ID 过滤 |
响应:200 OK,返回 Mission[]。
[
{
"id": 1,
"description": "请跟进这张生产单",
"category": 1,
"category_name": "通用",
"participants": [],
"can_reply": true
}
]
6.8 创建任务
POST /api/v2/missions/
请求体:
{
"description": "请跟进这张生产单",
"category": 1,
"content_type": 33,
"content_id": 123,
"extra": {
"source": "printing-order"
},
"participant_ids": [101, 102],
"employee_type_ids": [3, 4],
"notify_if_unreplied": true,
"unreplied_notify_interval_minutes": 30,
"unreplied_notify_max_count": 5
}
请求字段:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
description |
string | 是 | 任务描述,不能为空 |
category |
number | 否 | MissionCategory.id;不传则使用默认“通用”分类 |
content_type |
number/null | 否 | django_content_type.id;与 content_id 必须同时提供或同时省略 |
content_id |
number/null | 否 | 关联业务对象 ID;与 content_type 必须同时提供或同时省略 |
extra |
object/null | 否 | 扩展字段 |
participant_ids |
number[] | 否 | 显式参与员工 ID 列表,传 Employee.id |
employee_type_ids |
number[] | 否 | 参与职位 ID 列表,传 EmployeeType.id;展开为在职员工 |
notify_if_unreplied |
boolean | 否 | 是否开启未回复提醒,默认 false |
unreplied_notify_interval_minutes |
number/null | 否 | 未回复提醒间隔;开启提醒时必填 |
unreplied_notify_max_count |
number | 否 | 最大提醒次数,默认 5 |
响应:201 Created,返回 Mission。
常见错误:
{"detail": "参与者不存在或不属于任务所属商户"}
{"detail": "员工职位不存在或不属于任务所属商户"}
{"unreplied_notify_interval_minutes": ["开启未回复提醒时必须设置提醒间隔"]}
6.9 查询任务详情
GET /api/v2/missions/{mission_id}/
响应:200 OK,返回 Mission。
6.10 更新任务
PATCH /api/v2/missions/{mission_id}/
请求体示例:
{
"description": "更新后的任务描述",
"category": 2,
"extra": {
"channel": "wechat"
},
"participant_ids": [101],
"employee_type_ids": [3],
"notify_if_unreplied": true,
"unreplied_notify_interval_minutes": 20,
"unreplied_notify_max_count": 8
}
可更新字段:
| 字段 | 类型 | 说明 |
|---|---|---|
description |
string | 任务描述,不能为空 |
category |
number | MissionCategory.id |
content_type |
number/null | 与 content_id 必须同时提交;可提交 null 清空关联 |
content_id |
number/null | 与 content_type 必须同时提交;可提交 null 清空关联 |
extra |
object/null | 扩展字段;提交 null 可清空 |
participant_ids |
number[] | 显式员工参与者列表 |
employee_type_ids |
number[] | 按职位展开的参与者列表 |
notify_if_unreplied |
boolean | 是否开启未回复提醒 |
unreplied_notify_interval_minutes |
number/null | 未回复提醒间隔 |
unreplied_notify_max_count |
number | 未回复最大提醒次数 |
响应:200 OK,返回 Mission。
注意:
participant_ids和employee_type_ids表示重新设置最终参与者列表,不是增量追加。- 如果两个字段都不传,则不修改参与者。
- 若提交
content_type或content_id,两者必须同时出现在请求体中。 - 状态字段不能通过该接口更新。
清空任务关联对象:
{
"content_type": null,
"content_id": null
}
清空参与者:
{
"participant_ids": [],
"employee_type_ids": []
}
6.11 删除任务
DELETE /api/v2/missions/{mission_id}/
不支持。
响应:405 Method Not Allowed
{"detail": "Mission 删除接口未提供,请使用 cancel 接口取消任务"}
6.12 按印刷单查询任务
GET /api/v2/missions/by-printing-order/{printing_order_id}/
查询指定印刷单关联的任务。
查询参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
category_ids |
number[]/string | 否 | 分类过滤。支持重复参数或逗号分隔,例如 ?category_ids=1,2 或 ?category_ids=1&category_ids=2 |
include_details |
boolean | 否 | 是否返回详情。默认 true;false 时返回 MissionLite[] |
响应:
include_details=true或未传:200 OK,返回MissionWithReplies[]。include_details=false:200 OK,返回MissionLite[]。
示例:
GET /api/v2/missions/by-printing-order/123/?category_ids=1,2&include_details=true
常见错误:
{"include_details": "必须是布尔值"}
{"category_ids": "必须是整数 ID 列表"}
6.13 查询任务回应列表
GET /api/v2/missions/{mission_id}/replies/
查询参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
ends_task |
boolean | 否 | 按是否结束任务过滤 |
is_rejected |
boolean | 否 | 按是否已撤销过滤 |
响应:200 OK,返回 MissionReply[]。
6.14 创建任务回应
POST /api/v2/missions/{mission_id}/replies/
请求体:
{
"content": "已处理完成",
"ends_task": true,
"extra": {
"attachment_ids": [1001, 1002]
}
}
请求字段:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
content |
string | 是 | 回应内容,不能为空 |
ends_task |
boolean | 否 | 是否结束任务,默认 false |
extra |
object/null | 否 | 扩展字段 |
响应:201 Created,返回 MissionReply。
行为说明:
- 回应人固定为当前登录用户关联的 Employee。
- 如果
ends_task=true,任务会被标记为完成。 - 已取消任务或已有未撤销结束回应的任务不可继续回应。
6.15 重新打开任务
POST /api/v2/missions/{mission_id}/reopen/
权限要求:当前用户需要 Django 权限 mission.reopen_mission。
响应:200 OK,返回 Mission。
行为说明:
- 用于重新打开已完成任务。
- 会撤销已有结束任务效果,使任务回到未完成状态。
常见错误:
{"detail": "缺少重新打开任务权限"}
6.16 取消任务
POST /api/v2/missions/{mission_id}/cancel/
响应:200 OK,返回 Mission。
行为说明:
- 取消人固定为当前登录用户关联的 Employee。
- 取消后
is_cancelled=true,cancelled_by和cancelled_at由后端写入。
6.17 设置任务紧急状态
POST /api/v2/missions/{mission_id}/set-urgent/
请求体:
{
"is_urgent": true
}
请求字段:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
is_urgent |
boolean | 是 | 是否紧急 |
响应:200 OK,返回 Mission。
6.18 撤销任务回应
POST /api/v2/mission-replies/{reply_id}/reject/
权限要求:当前用户需要 Django 权限 mission.reject_mission_reply。
响应:200 OK,返回 MissionReply。
行为说明:
- 撤销人固定为当前登录用户关联的 Employee。
- 如果撤销的是结束任务回应,任务可能会被重新打开。
常见错误:
{"detail": "缺少撤销任务回应权限"}
7. 常见状态码
| 状态码 | 场景 |
|---|---|
200 OK |
查询、更新、状态操作成功 |
201 Created |
创建任务、分类、回应成功 |
204 No Content |
删除任务分类成功 |
400 Bad Request |
参数非法、跨商户、业务状态不允许 |
401 Unauthorized |
未登录 |
403 Forbidden |
缺少 reopen_mission 或 reject_mission_reply 等权限 |
404 Not Found |
对象不存在或不属于当前商户 |
405 Method Not Allowed |
不支持的删除任务操作 |
8. 前端接入建议
- 创建/更新任务时,
participant_ids使用Employee.id,employee_type_ids使用EmployeeType.id。 - 如果只想按职位添加参与者,可以只传
employee_type_ids。 - 如果 PATCH 不想改变参与者,不要传
participant_ids和employee_type_ids。 - 如果 PATCH 想清空参与者,两个字段都传空数组。
content_type不要硬编码,应从/api/v2/content-types/获取。- 普通任务编辑页不要提交状态字段,紧急、取消、重新打开、撤销回应都走独立接口。
- 响应中的
participants是后端最终展开后的员工列表,前端展示以该字段为准。
更新日期:2026-07-03