# 工作台迁移对接总结文档 > 更新时间: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,先确认是否拉到最新提交。