小程序后端接入 talkingq 共享库并新增消息与定位能力

This commit is contained in:
stu2not
2026-04-20 20:07:35 +08:00
parent e7fe92b863
commit 24b1d1025b
22 changed files with 3469 additions and 762 deletions

View File

@@ -1,4 +1,4 @@
# Banban 统一数据与接口设计文档Mini Program + talkingq-urlV3
# Banban 统一数据与接口设计文档Mini Program + talkingq-urlV4
## 1. 目标与边界
@@ -7,12 +7,14 @@
1. 两个服务使用同一套设备身份(`device_id`)。
2. 保留 `talkingq-url/mysql/init/01-init.sql` 现有表结构不变。
3. 在不改动基础表的前提下,补齐家长/小孩/绑定/聊天/定位能力。
4. 家长账号体系统一采用微信小程序登录,服务端基于 `code2Session` 换取真实 `openid/unionid`
硬性边界:
1. `01-init.sql` 中现有表不改表名、不改字段、不改约束。
2. 所有新增表仅做增量扩展。
3. 新增表字段命名风格对齐现有风格:`snake_case``*_id``is_active``status``created_at``updated_at`
4. 微信 `AppSecret` 只能保存在服务端配置中,小程序端只持有一次性 `code`
## 2. 现有冻结表(来自 01-init.sql
@@ -42,10 +44,20 @@
3. `unionid` VARCHAR(64) NULL
4. `nickname` VARCHAR(64) NULL
5. `avatar_url` VARCHAR(255) NULL
6. `phone` VARCHAR(20) NULL
7. `status` TINYINT NOT NULL DEFAULT 1
8. `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
9. `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
6. `avatar_file_key` VARCHAR(255) NULL
7. `phone` VARCHAR(20) NULL
8. `status` TINYINT NOT NULL DEFAULT 1
9. `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
10. `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
说明:
1. `avatar_file_key` 作为头像主存储值,保存 COS 对象 key。
2. `avatar_url` 作为兼容或展示字段使用,不作为唯一主依据。
3. `openid` 必须存储微信服务端 `code2Session` 返回的真实 OpenID禁止将前端 `code`、测试用户名或设备标识写入该字段。
4. `unionid` 仅在微信返回时写入;历史记录为空时,后续登录可补写,不作为首次登录成功前置条件。
5. `nickname/avatar_url` 为展示资料,可由小程序端在登录时上传并在后续更新,但不参与身份认证。
6. `phone` 为业务补充字段,与微信登录态解耦;如后续接入手机号授权,应基于服务端掌握的 `session_key` 解密后再写入。
索引建议:
@@ -90,25 +102,33 @@
### 3.4 设备归属表 `device_bindings`
用途:表达“当前哪块设备绑定到哪个小孩”,并与 `device_auth` 对齐。
用途:表达“当前哪块设备归属到哪个家长,并可选关联到哪个小孩”,并与 `device_auth` 对齐。
建议字段:
1. `id` BIGINT UNSIGNED PK AUTO_INCREMENT
2. `device_id` VARCHAR(64) NOT NULL
3. `child_id` BIGINT UNSIGNED NOT NULL
4. `status` TINYINT NOT NULL DEFAULT 1
5. `bound_at` DATETIME NOT NULL
6. `unbound_at` DATETIME NULL
7. `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
8. `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
3. `owner_user_id` BIGINT UNSIGNED NOT NULL
4. `child_id` BIGINT UNSIGNED NULL
5. `status` TINYINT NOT NULL DEFAULT 1
6. `bound_at` DATETIME NOT NULL
7. `unbound_at` DATETIME NULL
8. `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
9. `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
说明:
1. 设备可以先归属到家长,再在后续流程中补充关联 `child_id`
2. `child_id` 为空表示当前设备已归属,但尚未绑定到具体小孩。
约束建议:
1. `UNIQUE(device_id)`
2. `UNIQUE(child_id)`
3. `FOREIGN KEY (device_id) REFERENCES device_auth(device_id)`
4. `FOREIGN KEY (child_id) REFERENCES children(child_id)`
3. `INDEX idx_owner_user_id(owner_user_id)`
4. `FOREIGN KEY (device_id) REFERENCES device_auth(device_id)`
5. `FOREIGN KEY (owner_user_id) REFERENCES parents(user_id)`
6. `FOREIGN KEY (child_id) REFERENCES children(child_id)`
### 3.5 绑定会话表 `device_bind_sessions`
@@ -318,13 +338,24 @@
## 5. 核心业务流程
### 5.1 设备注册与鉴权
### 5.1 家长登录流程(微信小程序)
1. 小程序调用 `wx.login` / `Taro.login` 获取一次性 `code`
2. 小程序调用后端 `POST /auth/login`,上传 `code`,并可附带 `nickname/avatar_url` 作为资料字段。
3. 后端使用服务端配置的 `wechat_app_id + wechat_app_secret` 调用微信 `code2Session`
4. 后端从微信响应中获取真实 `openid`、可选 `unionid`,以及仅供服务端使用的 `session_key`
5. 后端以 `openid` 为唯一身份键 upsert `parents`;若本次拿到 `unionid` 且库中为空,则补写 `unionid`
6. 后端签发本地 `access_token(JWT)` 返回给小程序,后续业务接口仍统一使用本地 Bearer Token。
7. 若微信换码失败、`openid` 缺失、`code` 失效或被重复使用,登录直接失败,不创建本地用户。
8. `session_key` 仅用于后续需要的微信敏感数据解密能力(如手机号);当前阶段不作为登录态主键,也不写入 `parents` 主表。
### 5.2 设备注册与鉴权
1. 生产或后台调用 `talkingq-url` 现有注册接口,写入 `device_auth`
2. 手表请求携带 `X-Device-ID``X-Device-Serial`
3. 后端基于 `device_auth` 鉴权通过后继续处理聊天/定位/绑定。
### 5.2 绑定流程(扫码 + 确认码)
### 5.3 绑定流程(扫码 + 确认码)
1. 家长登录后发起 `bind/start`,创建 `device_bind_sessions`
2. 手表上报确认码,更新会话挑战信息。
@@ -335,16 +366,17 @@
7. 追加 `device_bind_history`
8. 更新会话状态为 `confirmed/consumed` 并提交事务。
### 5.3 聊天流程
### 5.4 聊天流程
1. 设备 AI 对话仍走 `conversation_histories + conversation_messages`
2. 家长-小孩、小孩-小孩消息走 `im_conversations + im_messages`
3. IM 消息统一使用 `sender_type/sender_id + receiver_type/receiver_id`,不按场景拆专用发送者字段。
4. 发送接口必须使用 `client_msg_id` 幂等
5. 查询前必须校验 `parent_child_relations` 权限
6. 列表展示优先读取消息快照字段,降低跨表查询成本
4. `mini-program` 侧不再新增独立的 `chat_*` 消息表定义,统一以 `im_*` 为 IM 正表
5. 发送接口必须使用 `client_msg_id` 幂等
6. 查询前必须校验 `parent_child_relations` 权限
7. 列表展示优先读取消息快照字段,降低跨表查询成本。
### 5.4 位置流程
### 5.5 位置流程
1. 手表上报定位写入 `child_location_history`
2. 同事务更新 `child_location_current`
@@ -361,19 +393,91 @@
6. 关键写路径(绑定确认、发消息、位置写入)必须事务化。
7. 腾讯位置服务启用前提:必须配置合法 `key`,并完成域名/来源白名单与配额设置。
8. 地图相关接口统一使用 `gcj02``lat,lng`;禁止混用 `wgs84/bd09` 直接入库。
9. 小程序端只上送一次性 `code`,不得自行调用微信换取 `openid`,更不得持有 `AppSecret`
10. `code` 只用于调用微信 `code2Session`,不得入库为 `openid``unionid` 或任何长期身份字段。
11. `session_key` 不返回前端,不写入 `parents` 主表;如需支持手机号等敏感数据解密,应服务端短期缓存并设置明确过期时间。
12. `nickname/avatar_url` 仅作资料字段,不能作为登录态、账号归并或权限判断依据。
## 7. 分阶段落地
1. 第一阶段:落地 `parents/children/parent_child_relations/device_bind_*`,打通绑定链路
2. 第二阶段:落地 `im_conversations/im_messages`,打通家长与小孩 IM
3. 第三阶段:落地 `child_location_current/history`,打通定位链路
4. 第四阶段:补充审计、告警、实时推送和运营能力
1. 第一阶段:落地微信登录链路,打通 `Taro.login -> /auth/login -> code2Session -> parents -> JWT`
2. 第二阶段:落地 `parents/children/parent_child_relations/device_bind_*`,打通绑定链路
3. 第三阶段:落地 `im_conversations/im_messages`,打通家长与小孩 IM
4. 第四阶段:落地 `child_location_current/history`,打通定位链路
5. 第五阶段:补充审计、告警、实时推送和运营能力。
## 8. 验收标准
1. 不修改 `01-init.sql` 任一现有表,服务可正常启动
2. 设备鉴权、角色配置、OTA能力保持可用
3. 家长可完成扫码绑定、解绑、重绑,且历史保留
4. 家长可查看自己小孩与其他小孩完整双向消息
5. 小程序可查看小孩最新位置与历史轨迹
1. 家长可通过真实微信登录完成换码,并获取本地 Bearer Token
2. `parents.openid` 存储值来自微信返回的真实 OpenID而不是前端 `code` 或测试标识
3. 不修改 `01-init.sql` 任一现有表,服务可正常启动
4. 设备鉴权、角色配置、OTA能力保持可用
5. 家长可完成扫码绑定、解绑、重绑,且历史保留
6. 家长可查看自己小孩与其他小孩完整双向消息。
7. 小程序可查看小孩最新位置与历史轨迹。
## 9. 共享库落地规范
### 9.1 唯一数据库与唯一 Schema
1. `mini-program``talkingq-url` 必须共用同一个 MySQL 数据库:`talkingq`
2. `database/talkingq_shared_schema.sql` 是唯一 schema 真相源。
3. `mini-program/database/init.sql` 仅保留给历史上的“单服务独立开发”场景,不再作为共享部署的建库依据。
### 9.2 表归属Table Ownership
`talkingq-url` 拥有以下表的写入责任:
1. `device_auth`
2. `device_configs`
3. `conversation_histories`
4. `conversation_messages`
5. `roles`
6. `role_languages`
7. `device_firmware_update`
8. `system_config`
`mini-program` 拥有以下表的写入责任:
1. `parents`
2. `children`
3. `parent_child_relations`
4. `device_bindings`
5. `device_bind_sessions`
6. `device_bind_history`
7. `device_settings`
8. `cards`
9. `im_conversations`
10. `im_messages`
11. `child_location_current`
12. `child_location_history`
约束:
1. 两个服务允许跨服务读取共享依赖表,但不允许跨服务写对方负责的主表。
2. `mini-program` 只读 `device_auth`,不直接承担设备注册主流程。
3. `talkingq-url` 不写 `parents/children/device_bindings/im_* /child_location_*`
### 9.3 共享字段与真相源
1. 设备主身份统一以 `device_auth.device_id` 为准。
2. 设备与 AI 的历史消息统一以 `conversation_histories + conversation_messages` 为准。
3. 家长/儿童 IM 统一以 `im_conversations + im_messages` 为准。
4. 设备音量如需双端共享,以 `device_configs.volume` 为真相源;`device_settings.volume` 仅作小程序展示和兼容字段。
### 9.4 迁移原则
1. 目标库固定为 `talkingq`
2. 迁移时以 `talkingq-url` 当前使用的 `talkingq` 数据为准。
3. 历史 `mini_program` 库中的业务数据不并入 `talkingq`,也不作为冲突解决依据。
4. 迁移动作只做两件事:
1.`talkingq` 上补齐 `mini-program` 所需扩展表。
2.`mini-program` 服务配置切换到 `talkingq`
5. `mini_program` 库可在切换验证完成后归档或删除,但不再作为运行时数据库。
### 9.5 启动与建表策略
1. 共享部署下,服务启动默认只检查数据库连通性,不自动执行 ORM `create_all`
2. 只有显式开启开发开关时,`mini-program` 才允许自动建表。
3. 生产、联调、共享测试环境统一通过 `database/talkingq_shared_schema.sql` 或正式 migration 执行建表与变更。