Files
sino-mci/docs/superpowers/specs/2026-07-08-channel-conversation-task-boundary-design.md

179 lines
8.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 渠道账号、会话与发送任务数据边界设计
> **版本**v1.0
> **日期**2026-07-08
> **状态**:已确认,待实施
> **关联文档**`docs/architecture/2026-07-06-message-customer-interaction-design.md`
---
## 1. 背景与目标
`2026-07-06-message-customer-interaction-design.md` 已完成整体架构与数据模型设计的基础上,进一步明确中台与业务系统之间的数据边界,以及“配置 + 选取人员 → 任务发送”的最小可用实现路径。
**本次目标**
- 业务系统通过中台 API 维护人员Person、渠道身份ChannelIdentity、会话Conversation、群聊关系
- 中台只保存渠道侧最小数据集,业务属性(机构、供应商、合同等)由业务系统写入;
- 企微官方接口只能拿到有限信息(`userid``external_userid``chat_id`、群名等),同步接口不得覆盖业务系统写入的字段;
- 所有出站发送通过 `/api/v1/send` 任务接口驱动,任务与发送日志合并为 `mci_send_record`
- 当前阶段不拆分 `openapi` 包,所有修改在现有 `mci-server``admin-web` 内完成;跑通后下一阶段再独立拆分第三方接入包。
---
## 2. 数据边界设计
### 2.1 中台保存 vs 业务系统维护
| 数据 | 中台保存 | 业务系统维护 | 说明 |
|------|---------|-------------|------|
| 人员基础信息 `mci_person` | 是 | 可同步 | 中台保存 `person_code``person_name``phone``person_type`;业务系统可写入或同步,中台不强制唯一来源。 |
| 业务属性(机构/供应商/合同) | 是字段,业务系统写入 | 是 | `institution_id``supplier_id``contract_id` 由业务系统赋值,企微同步不覆盖。 |
| 渠道身份 `mci_channel_identity` | 是 | 可同步 | 中台保存渠道用户 ID`userid``external_userid`、个微 `wxid` 等),属于渠道侧最小数据集。 |
| 会话 `mci_conversation` | 是 | 可同步/创建 | 中台保存 `channel_conversation_id`、群名、群主等;业务属性由业务系统写入。 |
| 标签 `mci_tag` | 是 | 可同步 | 标签表达角色、合同、机构、供应商等业务属性,支持层级;业务系统可通过 API 维护。 |
| 账号-会话绑定 `mci_channel_account_conversation` | 是 | 否 | 发送主备、接收主备属于渠道调度能力,由中台管理。 |
| 发送内容 | 否(接收最终内容) | 是 | 业务系统渲染最终消息后调用中台发送接口。 |
| 模板与变量 | 否 | 是 | 中台不保存模板。 |
### 2.2 企微同步的边界
`ChannelAccountService.syncContacts``syncConversations` 只能写入/更新以下字段:
- `mci_person``person_name`(企微返回的昵称/姓名)、`phone`(如有)
- `mci_channel_identity``channel_user_id``channel_user_name``subject_id``channel_type`
- `mci_conversation``conversation_type``channel_type``channel_conversation_id``conversation_name``owner_account_id``subject_id``create_source=1`
- `mci_conversation_participant`:群成员关系
**禁止行为**
- 不得覆盖 `institution_id``supplier_id``contract_id`
- 不得删除业务系统已绑定的标签;
- 不得修改 `channel_account_conversation` 中业务系统未授权的主备绑定。
---
## 3. 发送任务模型
沿用 `mci_send_record` 单表设计:一次 API 调用产生一个 `task_id`,每个最终目标(人/会话)一条记录。
### 3.1 支持的目标类型
| target_type | 说明 | target_value 示例 |
|-------------|------|-------------------|
| `conversation` | 单个会话 | `{"conversation_id": 1001}` |
| `person` | 单个联系人(单聊) | `{"person_id": 2001}` |
| `person_list` | 联系人列表 | `{"person_ids": [2001, 2002]}` |
| `tag` | 标签人群/群聊 | `{"tag_id": 3001, "scope": "all"}` |
| `rule` | 复合受众规则 | `{"logic": "and", "rules": [...]}` |
### 3.2 渠道策略
`channel_strategy` 描述渠道选择偏好:
```json
{
"channel_type": "wecom",
"strategy": "primary",
"fallback": true
}
```
中台根据目标解析结果选择实际账号:
- 群聊:从 `mci_channel_account_conversation` 取发送主号,主号不可用 fallback 到备用号;
- 单聊:取目标人对应的 `ChannelIdentity`,再选择默认 `ChannelAccount`
### 3.3 结果回调
发送请求可携带 `callback_url`,任务完成后按条或按任务聚合回调业务系统。
---
## 4. 本次实施范围(方案 A
### 4.1 后端
1. **校验与边界保护**
-`ConversationService``ChannelAccountService` 的同步方法中增加“业务字段保护”:企微同步不覆盖 `institution_id``supplier_id``contract_id`
-`SendService.resolveByType` 中增加目标存在性、租户隔离、账号可用性校验。
2. **账号-会话绑定补全**
- 确认 `ConversationController.bindAccount` 支持 `binding_type`1 发送主号、2 发送备用号、3 接收主号、4 接收备用号。
- 确认 `SendService.selectSendAccount` 按主备顺序选择。
3. **发送任务端到端**
- 验证 `POST /api/v1/send``POST /api/v1/send/test` 可正常创建任务、拆解记录、返回 `task_id`
- 验证 `SendMessageConsumer` 可调用 `ChannelAdapter` 实际发送并回写状态。
4. **渠道账号初始化**
- 验证 `POST /api/v1/channel-account/init` 支持企微内部账号、企微应用、个微、钉钉/飞书机器人;返回初始化结果或二维码信息。
5. **会话/群聊同步**
- 验证 `POST /api/v1/channel-account/{account_id}/sync-conversations` 能拉取账号所在群聊并创建 `Conversation``ConversationParticipant``ChannelAccountConversation` 默认绑定。
### 4.2 前端
1. **发送页面完善**
- `SendRecord.vue` 已支持测试发送和记录查询,补充“选择标签发送”和“选择规则发送”的测试入口。
- 在会话/人员列表中提供“发送消息”快捷入口,跳转或填充 `SendRecord.vue` 测试表单。
2. **账号-群绑定页面**
-`Conversation.vue` 或新增页面中,支持为会话绑定发送主备号、接收主备号。
3. **标签层级展示**
- `Tag.vue` 已支持层级,确认在人员/会话绑定时可以展示多级标签并直接选择。
4. **管理后台权限**
- 确认租户管理员、运营操作员、只读用户三类角色已落地,页面按钮按角色显隐。
### 4.3 测试验证
1. **单元/接口测试**
- 发送目标解析conversation、person、tag、rule
- 同步边界:企微同步不覆盖业务字段;
- 主备切换:发送主号不可用时启用备用号。
2. **端到端流程**
- 使用 mock 渠道适配器或企微测试企业号,完成:
1. 创建租户/用户;
2. 创建渠道主体;
3. 初始化渠道账号;
4. 同步/创建会话;
5. 绑定发送账号;
6. 调用发送任务;
7. 查询发送记录与统计。
---
## 5. 验收标准
- [ ] 第三方平台可通过 API 完成:创建 Person、绑定 ChannelIdentity、创建/更新 Conversation、绑定标签、绑定发送账号
- [ ] 企微 `sync-contacts` / `sync-conversations` 不覆盖 `institution_id``supplier_id``contract_id`
- [ ] `POST /api/v1/send` 支持 conversation / person / person_list / tag / rule 五种目标类型;
- [ ] 发送任务按目标拆解为 `mci_send_record` 记录,可查询任务状态、记录列表、统计;
- [ ] 前端可在“会话/人员/标签”维度完成测试发送,并查看发送记录;
- [ ] Docker 全栈服务健康,接口可通。
---
## 6. 未来工作
下一阶段(方案 A 验证通过后)将拆分独立的 `openapi` 包:
- 路径前缀 `/api/v1/open/**`
- 面向业务系统的 DTO 更严格,隐藏内部状态字段;
- 独立的鉴权方式(`X-Tenant-Code` + `X-App-Key`
- 管理后台 API 与第三方 API 代码分离,便于文档生成和权限控制。
---
## 7. 关键文件清单
| 模块 | 文件 |
|------|------|
| 发送核心 | `backend/mci-server/src/main/java/com/sino/mci/send/service/SendService.java` |
| 发送控制器 | `backend/mci-server/src/main/java/com/sino/mci/send/controller/SendController.java` |
| 会话管理 | `backend/mci-server/src/main/java/com/sino/mci/channel/service/ConversationService.java` |
| 渠道账号 | `backend/mci-server/src/main/java/com/sino/mci/channel/service/ChannelAccountService.java` |
| 人员管理 | `backend/mci-server/src/main/java/com/sino/mci/crm/service/PersonService.java` |
| 发送页面 | `admin-web/src/views/SendRecord.vue` |
| 会话页面 | `admin-web/src/views/Conversation.vue` |
| 标签页面 | `admin-web/src/views/Tag.vue` |