Files
olons_server/docs/工作台迁移对接总结文档.md
T

352 lines
12 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.
# 工作台迁移对接总结文档
> 更新时间:2026-09-14。本文用于后续开启新的 `im_workbench` 工作树时快速接手,覆盖当前迁移边界、接口、鉴权、中间件配置、Kafka 事件、数据库现状和验收步骤。
## 1. 当前结论
工作台已从 `im_server` 拆到独立仓库 `im_workbench`,当前阶段只拆服务和接口边界,数据库暂不迁移。工作台接口统一走 `/v1/workbench/*`,由网关分流到 `im_workbench`;登录仍由 `im_server` 负责,登录成功后把 Token 会话写入 Redis,`im_workbench` 从 Redis 校验登录态。
当前已完成:
| 项目 | 状态 |
|---|---|
| 独立 Go 工程 | 已完成,仓库:`/Users/youshunlai/go_workspace/im_workbench` |
| 独立启动 | 已完成,默认监听 `:6061` |
| 新路由 `/v1/workbench/*` | 已完成 |
| Redis Token 鉴权 | 已完成 |
| 工作台 Kafka 事件生产 | 已完成 |
| 测试环境中间件配置 | 已更新 |
| 数据库迁移 | 暂不迁移,仍使用租户库 `tinode` |
| `im_server` 旧工作台代码 | 暂保留,等新服务稳定后再删 |
最近关键提交:
| 仓库 | Commit | 说明 |
|---|---|---|
| `im_workbench` | `8b5c5e3` | 兼容当前工作台表结构 |
| `im_workbench` | `c1c1156` | 更新新测试环境中间件配置,修复 Kafka 发布 |
## 2. 服务边界
### 2.1 im_workbench 负责
| 模块 | 接口范围 |
|---|---|
| 工作台首页 | `GET /v1/workbench` |
| 组织架构 | `/v1/workbench/organization/*` |
| 考勤 | `/v1/workbench/attendance/*` |
| 会议 | `/v1/workbench/meetings*` |
| 会议笔记 | `/v1/workbench/meeting-notes`、`/v1/workbench/meetings/{id}/notes*` |
| 日报 | `/v1/workbench/reports/daily*` |
| 月报 | `/v1/workbench/reports/monthly*` |
| 总经理信箱 | `/v1/workbench/executive-mailbox/*` |
| 工作台业务事件 | 生产 Kafka 事件到 `im.workbench.event` |
### 2.2 im_server 继续负责
| 能力 | 说明 |
|---|---|
| 登录、注册、Token 签发 | C 端登录仍走 `im_server` |
| Redis 登录态写入 | 登录成功后写 `im:session:token:{sha256(token)}` |
| 文件上传 | 暂由 `/v0/file/u/` 处理,工作台只保存 `file_id` |
| WebSocket 实时下发 | 工作台事件由 `im_server` 消费后转 C 端通知 |
| IM 消息、群、好友、在线状态 | 仍全部留在 `im_server` |
## 3. 网关路由
客户端对外仍访问统一域名,由 Nginx/API Gateway 按路径分流:
```text
/v0/channels -> im_server
/v0/file/u/ -> im_server
/v1/im/* -> im_server
/v1/workbench/* -> im_workbench
```
测试环境域名:
| 域名 | 用途 |
|---|---|
| `https://api.118im.com` | 后端 API,包含 `/v1/workbench/*` |
| `https://api-test.118im.com` | 测试 API 备用域名 |
| `https://web.118im.com` | Web 前端同源代理 |
注意:不要再让 `im_server` 代理工作台新接口。新接口应直接进入 `im_workbench`。
## 4. 请求鉴权
工作台接口和 IM 产品 HTTP 保持同一套公共 Header:
| Header | 必填 | 说明 |
|---|---|---|
| `Authorization` | 是 | `Bearer {token}` |
| `X-MeetingIM-APIKey` | 是 | 客户端 API Key |
| `X-Tenant-Code` | 是 | 当前租户编码,例如 `default` |
| `X-IM-Schema` | 是 | 当前固定 `1` |
| `X-Request-ID` | 建议必填 | 请求链路 ID |
| `Idempotency-Key` | 写接口必填 | 写操作幂等键 |
登录态 Redis Key:
```text
im:session:token:{sha256(token)}
```
Redis Value:
```json
{
"user_id": 1572927143048908800,
"tenant_id": 1,
"tenant_code": "default",
"device_id": "ios-device-1",
"auth_level": "auth",
"state": "active",
"issued_at": "2026-09-14T10:00:00Z",
"expires_at": "2026-09-14T12:00:00Z"
}
```
鉴权流程:
1. `im_workbench` 校验 `X-MeetingIM-APIKey` 非空或命中配置白名单。
2. 从 `Authorization` 读取 Bearer Token。
3. 对 Token 做 `sha256`,查 Redis 登录态。
4. 校验 `state=active`、未过期。
5. 校验 Header 的 `X-Tenant-Code` 与登录态 `tenant_code` 一致。
测试环境当前可用 API Key 以部署文档为准,最近验证可用的是新测试环境文档中的 `TINODE_API_KEY`。
## 5. 测试环境配置
配置文件:
```text
/Users/youshunlai/go_workspace/im_workbench/configs/workbench.test.json
```
当前关键配置:
| 配置 | 值 |
|---|---|
| 服务监听 | `:6061` |
| MySQL | `mysql.118im.com:30306` |
| MySQL 业务库 | `tinode` |
| Redis 数据端口 | `redis.118im.com:30637` |
| Redis Sentinel | `redis.118im.com:30638` |
| Kafka Bootstrap | `kafka.118im.com:30835` |
| Kafka 协议 | `PLAINTEXT` |
| Kafka Topic | `im.workbench.event` |
说明:
1. Kafka 测试环境是明文直连,不配置 SASL/TLS。
2. `im.workbench.event` 已在新 Kafka 集群创建。
3. Redis 数据 NodePort 可能落到主节点或副本。服务正常读登录态没问题;如果本地要写临时测试 session,可能遇到 `READONLY`,需要通过真正主库入口或先走真实登录链路。
4. MySQL、Redis 密码不写入本文,按 `im_server/docs/problems/新测试环境部署与中间件连接信息.md` 或部署 Secret 获取。
## 6. 本地启动
本地开发配置:
```bash
IM_WORKBENCH_CONFIG=configs/workbench.local.json go run ./cmd/workbench
```
连接测试环境配置:
```bash
IM_WORKBENCH_CONFIG=configs/workbench.test.json go run ./cmd/workbench
```
如果只做本地接口调试,可以临时打开开发 Header 鉴权:
```bash
IM_WORKBENCH_CONFIG=configs/workbench.test.json \
IM_WORKBENCH_ALLOW_DEV_HEADER_AUTH=true \
go run ./cmd/workbench
```
开发 Header:
```text
X-User-ID: 1572927143048908800
X-Tenant-ID: 1
X-Tenant-Code: default
X-MeetingIM-APIKey: x
X-IM-Schema: 1
X-Request-ID: {uuid}
```
注意:`IM_WORKBENCH_ALLOW_DEV_HEADER_AUTH=true` 只能本地调试使用,测试/生产部署不要开启。
## 7. Kafka 事件
工作台写操作统一投递:
```text
Topic: im.workbench.event
```
事件体:
```json
{
"event_id": "wbe_xxx",
"trace_id": "request-id",
"tenant_id": 1,
"tenant_code": "default",
"actor_user_id": 42,
"module": "meeting",
"action": "meeting.created",
"resource_id": "mtg_xxx",
"target_user_ids": [42, 43],
"title": "会议通知",
"summary": "项目周会",
"occurred_at": "2026-09-14T06:00:00Z",
"data": {}
}
```
当前事件范围:
| 模块 | Action | 触发场景 |
|---|---|---|
| 考勤 | `attendance.record.updated` | 打卡成功 |
| 考勤 | `attendance.appeal.created` | 提交考勤申诉 |
| 会议 | `meeting.created` | 创建会议 |
| 会议 | `meeting.updated` | 修改会议 |
| 会议 | `meeting.canceled` | 取消会议 |
| 会议 | `meeting.response.updated` | 更新参会回执 |
| 会议笔记 | `meeting_note.file.created` | 新增会议笔记文件 |
| 会议笔记 | `meeting_note.file.replaced` | 替换会议笔记文件 |
| 会议笔记 | `meeting_note.file.deleted` | 删除会议笔记文件 |
| 日报 | `daily_report.draft.created` | 创建日报草稿 |
| 日报 | `daily_report.draft.saved` | 保存日报草稿 |
| 日报 | `daily_report.submitted` | 提交日报 |
| 日报 | `daily_report.reminded` | 日报提醒 |
| 月报 | `monthly_report.draft.created` | 创建月报草稿 |
| 月报 | `monthly_report.draft.saved` | 保存月报草稿 |
| 月报 | `monthly_report.submitted` | 提交月报 |
| 月报 | `monthly_report.reopened` | 重开月报 |
| 信箱 | `mailbox.submitted` | 提交总经理信箱 |
已修复问题:`kafka.Writer` 设置了默认 Topic 后,单条 `kafka.Message` 不再重复设置 Topic,否则 `kafka-go` 会报 `Topic must not be specified for both Writer and Message`。
## 8. 数据库现状
当前数据库不迁移,`im_workbench` 仍连接租户库 `tinode`。
主要表:
| 表 | 用途 |
|---|---|
| `im_workbench_apps` | 工作台模块 |
| `im_org_departments` | 组织部门 |
| `im_org_members` | 组织成员 |
| `im_org_visibility_overrides` | 组织可见范围 |
| `im_attendance_rules` | 考勤规则 |
| `im_attendance_shifts` | 考勤班次 |
| `im_attendance_records` | 考勤记录 |
| `im_attendance_checkins` | 打卡流水 |
| `im_attendance_appeals` | 考勤申诉 |
| `im_meetings` | 会议 |
| `im_meeting_participants` | 会议参与人 |
| `im_meeting_note_files` | 会议笔记文件引用 |
| `im_daily_reports` | 日报 |
| `im_monthly_reports` | 月报 |
| `im_mailbox_config` | 总经理信箱配置 |
| `im_mailbox_submissions` | 总经理信箱提交 |
已兼容当前表结构:
| 表 | 当前结构注意点 | 代码处理 |
|---|---|---|
| `im_org_members` | 成员状态字段是 `employment_state` | 查询时返回为 `status` |
| `im_attendance_rules` | 没有 `appeal_deadline` 字段 | 查询返回 `NULL AS appeal_deadline` |
| `im_mailbox_config` | 没有 `version` 字段 | 用 `notice_updated_at` 派生版本 |
服务启动不自动建库建表,不执行 DDL。所有建表、改字段、初始化数据都走人工 SQL 审核和发布。
## 9. 已验证接口
使用新测试环境配置启动本地 `im_workbench`,并开启本地开发 Header 鉴权后,已验证:
| 接口 | 结果 |
|---|---|
| `GET /v1/workbench` | 200 |
| `GET /v1/workbench/organization/departments` | 200 |
| `GET /v1/workbench/attendance/config` | 200 |
| `GET /v1/workbench/executive-mailbox/config` | 200 |
| `POST /v1/workbench/executive-mailbox/submissions` | 200,Kafka 发布成功 |
同时执行:
```bash
go test ./...
```
结果通过。
## 10. 新工作树接手步骤
1. 拉取 `im_workbench` 的 `dev` 分支。
2. 确认包含提交 `c1c1156` 或更新的提交。
3. 查看 `configs/workbench.test.json`,确认中间件地址是新测试环境域名,不是旧 VM `64.118.137.182`。
4. 执行 `go test ./...`。
5. 本地启动:
```bash
IM_WORKBENCH_CONFIG=configs/workbench.test.json \
IM_WORKBENCH_ALLOW_DEV_HEADER_AUTH=true \
go run ./cmd/workbench
```
6. 用开发 Header 调 `GET /v1/workbench`、组织、考勤、信箱配置。
7. 调一个写接口,例如信箱提交,确认返回 200,并在数据库清理测试数据。
8. 关闭开发 Header 鉴权,走真实登录 Token 验证网关链路。
9. 验证公网 `/v1/workbench/*` 路由已经进入 `im_workbench`,并确认网关透传 `Authorization`、`X-MeetingIM-APIKey`、`X-Tenant-Code`、`X-IM-Schema`、`X-Request-ID`。
## 11. 待后续处理
| 事项 | 说明 |
|---|---|
| 真实登录态联调 | 需要通过 `im_server` 登录后生成 Redis session,再从公网 `/v1/workbench/*` 验证 |
| 网关 Header 透传 | 必须确认 `Authorization` 没被 Nginx/API Gateway 清掉 |
| Redis 写入口 | 数据 NodePort 可能落副本,本地造 session 可能遇到 `READONLY` |
| im_server 消费工作台事件 | `im_server` 消费 `im.workbench.event` 后转系统通知/WS 下发需要继续联调 |
| 工作台数据库迁移 | 现阶段不迁,接口稳定后单独做工作台库迁移 |
| 删除 im_server 旧工作台代码 | 等新服务、网关、前端、通知链路全部稳定后再删 |
## 12. 常见问题
### 12.1 `/v1/workbench` 返回 `AUTH_REQUIRED`
优先检查:
1. 是否带 `Authorization: Bearer {token}`。
2. Redis 是否有 `im:session:token:{sha256(token)}`。
3. session 是否 `state=active` 且未过期。
4. `X-Tenant-Code` 是否和 session 中的 `tenant_code` 一致。
5. 网关是否透传 `Authorization`。
6. `im_workbench` 是否连到了和 `im_server` 相同的 Redis。
### 12.2 写接口返回 `workbench event publish failed`
优先检查:
1. Kafka broker 是否为 `kafka.118im.com:30835`。
2. Kafka 是否为 `PLAINTEXT`,不要配置 SASL。
3. Topic `im.workbench.event` 是否存在。
4. 服务代码是否已经包含 Kafka 双 Topic 修复。
### 12.3 组织或考勤接口 500
优先检查当前表结构是否和代码兼容:
1. `im_org_members` 使用 `employment_state`,不是 `status`。
2. `im_attendance_rules` 当前没有 `appeal_deadline`。
3. `im_mailbox_config` 当前没有 `version`。
这些兼容已在当前代码中处理;如果新工作树仍 500,先确认是否拉到最新提交。