# OA 看板钉钉待办接入方案 ## 结论 正式系统**不能只靠新增环境变量**就直接发送钉钉待办。 原因: 1. 仓库当前只实现了钉钉登录与用户识别,没有“创建 / 更新 / 删除钉钉待办”的服务代码。 2. 当前没有“业务流程记录 <-> 钉钉待办 ID”的持久化表。 3. 当前没有发送幂等、失败重试、关闭待办、升级提醒等基础能力。 但从现有代码基础看,**补一层服务实现后,再由正式环境配置环境变量即可上线**。 ## 现有基础 ### 已具备 1. 钉钉 OAuth 登录能力 - 文件:`src/server/services/dingtalk-auth.service.ts` - 已能完成: - 构建授权地址 - 获取用户 access token - 获取 unionId - 获取 app access token - 用 unionId 换取 userId - 获取用户详情 2. 用户钉钉身份字段 - 系统已保存并使用: - `dingtalkUserId` - `dingtalkUnionId` 3. OA 看板责任人映射 - OA 看板已经能把不同阶段映射到默认责任角色 / 人员字段。 - 例如首单下单待发起时可兜底为 `采购/跟单`。 4. 责任与跟进界面基础 - 页面已有“责任与跟进”区域,适合作为钉钉待办的业务入口。 ### 尚缺失 1. 钉钉待办发送 service 2. 待办投递日志表 3. 待办幂等规则 4. 待办关闭 / 更新规则 5. 定时升级提醒任务 6. 正式环境待办配置项 ## 官方能力判断 根据钉钉开放平台官方文档,待办能力当前支持: 1. 创建工作待办 2. 更新待办 3. 删除待办 4. 查询用户待办 与本项目相关的关键点: 1. 创建待办时需要应用身份和用户身份,不能只知道姓名。 2. 待办通常需要可回跳的 `detailUrl`,跳回本系统详情页或看板页。 3. 如果要做闭环,流程状态变更后还要同步更新或关闭钉钉侧待办。 官方文档参考: - [待办概述](https://open.dingtalk.com/document/development/dingtalk-todo-task-overview) - [创建钉钉待办任务](https://open.dingtalk.com/document/development/add-dingtalk-to-do-task) - [更新钉钉待办任务](https://open.dingtalk.com/document/development/updates-dingtalk-to-do-tasks) - [删除钉钉待办任务](https://open.dingtalk.com/document/development/delete-dingtalk-to-do-tasks) - [更新钉钉待办执行者状态](https://open.dingtalk.com/document/development/update-dingtalk-to-do-status) ## 正式环境建议新增的环境变量 下面这些变量建议作为**待办功能正式接入专用配置**。当前代码尚未消费它们。 ```env # 是否启用 OA 看板钉钉待办 DINGTALK_TODO_ENABLED=false # 钉钉开放平台 API 应用配置(待办、审批等服务端调用) DINGTALK_API_CLIENT_ID= DINGTALK_API_CLIENT_SECRET= # 钉钉网页登录使用独立 OAuth 应用配置,不与 API 应用混用 DINGTALK_LOGIN_CLIENT_ID= DINGTALK_LOGIN_CLIENT_SECRET= DINGTALK_CALLBACK_ORIGIN= # 待办跳转回系统的基础地址 DINGTALK_TODO_DETAIL_BASE_URL= # 用于构造钉钉待办来源标识 / 业务空间 DINGTALK_TODO_SOURCE_APP=oa-board # 是否开启超时升级提醒 DINGTALK_TODO_ESCALATION_ENABLED=false # 超时升级阈值(天) DINGTALK_TODO_ESCALATION_DAYS=3 ``` 如果最终接入方案要求额外的应用标识,还可能需要: ```env DINGTALK_AGENT_ID= ``` 是否必须取决于最终选用的钉钉待办接口版本与应用类型。 ## 建议新增的数据表 建议新增一张专门的待办投递表,避免把钉钉待办状态散落在 JSON 里。 建议表名: - `oa_board_dingtalk_todo_dispatch` 用途: 1. 记录某个业务流程 / 阶段是否已创建钉钉待办 2. 保存钉钉待办 ID / 执行人 / 状态 3. 支持去重、重试、关闭、审计 SQL 草案见: - `scripts/sql/create-oa-board-dingtalk-todo-dispatch-table.sql` ## 建议的发送时机 ### 第一阶段:最小闭环 先只做一类待办: 1. 当流程进入新的“当前审批阶段” 2. 且解析出了唯一责任人 3. 且该阶段还没有有效待办 4. 则创建一条钉钉待办 建议首批接入阶段: 1. `产品设计-外观` 2. `产品设计-结构` 3. `产品生产-首单下单` 4. `限价-发起` 原因: 1. 这些阶段责任人相对清晰 2. 都已经有字段或规则可映射负责人 3. 业务价值高,适合先验证 ### 第二阶段:关闭与更新 当以下任一情况发生时,同步钉钉待办: 1. 当前阶段变化 - 关闭旧待办 - 为新阶段责任人创建新待办 2. 流程完成 / 驳回 / 终止 - 关闭对应待办 3. 负责人变更 - 更新执行人,或关闭旧待办后重建 ### 第三阶段:升级提醒 当流程满足以下条件时再发升级提醒: 1. 阶段超时 2. 原待办已创建 3. 距离上次提醒超过冷却时间 4. 升级接收人可解析 升级对象建议: 1. 当前负责人 2. 当前负责人上级 3. 商品企划 / 荆川 / 管理员可选兜底 ## 负责人解析策略 待办发送目标不能只靠中文名,必须最终落到钉钉身份。 建议解析顺序: 1. 当前运行任务的 `userId` - 直接映射 `dingtalkUserId` 2. 表单中责任人字段 - 如 `appearanceDesigner`、`structureDesigner`、`merchandiserOwner`、`pricingOwner` - 用姓名匹配本地用户 / 员工目录,取 `dingtalkUserId` 3. 阶段默认角色兜底 - 例如 `采购/跟单` - 通过角色到成员名单的映射表进一步解析 如果一个阶段只能解析到“角色名”而不能解析到唯一员工,建议: 1. 不直接发待办 2. 记录 `NEEDS_OWNER_MAPPING` 3. 在看板中提示“负责人映射未完成” ## 需要新增的服务模块 建议至少拆成这几个文件: 1. `src/server/services/dingtalk-todo.service.ts` - 创建 / 更新 / 删除待办 - 管理 app token 2. `src/server/services/oa-board-dingtalk-todo-dispatch.service.ts` - 负责业务规则 - 判断是否该发待办 - 生成 payload - 落库记录 3. `src/server/services/oa-board-owner-resolution.service.ts` - 负责将阶段负责人解析成钉钉用户 4. `scripts/sync-oa-board-todos.ts` - 用于定时补发、关闭、升级 ## 需要新增的 API / 任务 ### 后台任务 建议新增定时任务: 1. `sync:oa-board:todos` - 扫描当前有效流程 - 创建缺失待办 - 关闭失效待办 - 触发升级提醒 ### 管理接口 如有需要,可新增: 1. `POST /api/intake/oa-board/todo-dispatch/retry` - 手工重试失败待办 2. `GET /api/intake/oa-board/todo-dispatch` - 查看待办发送日志 ## 幂等与重试建议 待办系统必须做幂等。 建议唯一业务键: ```text board_key + stage_key + receiver_dingtalk_user_id ``` 规则: 1. 同一个业务键,只允许存在 1 条 `OPEN / PENDING / RETRYING` 记录 2. 接口超时后不立即重发,先查日志状态 3. 网络失败按指数退避重试 ## 正式环境能否“只配置就开” 最终判断: 1. **现在不能** - 因为缺少待办发送代码和日志表 2. **补完代码后可以** - 正式系统只需配置环境变量 - 再开启定时任务即可 ## 推荐落地顺序 ### P1 1. 新增待办投递表 2. 新增 `dingtalk-todo.service.ts` 3. 先打通“创建待办” 4. 先只接 `产品生产-首单下单` ### P2 1. 接入更多阶段 2. 做关闭 / 更新逻辑 3. 做负责人映射异常日志 ### P3 1. 做超时升级提醒 2. 做看板内待办发送状态可视化 3. 做手工重试与运维面板 ## 建议的产品口径 为了降低误发风险,建议待办文案统一包含: 1. 开款编号 2. 当前阶段 3. 目标动作 4. 超时状态 5. 跳转链接 示例: ```text 【OA 新品流程看板】XP2026070900000291 已进入“产品生产-首单下单”,请尽快处理。 ```