文件
jw-beauty/docs/design/04-数据库表结构设计.md
T

289 行
12 KiB
Markdown

# 数据库表结构设计
基于 `软件系统说明.docx` 整理。本文档用于把已知数据实体推进到表级字段草案,便于后续直接转成 DDL。
本文档仍然遵循一个原则:不把文档未确认的业务规则写成既定事实。以下字段草案中,凡是来源仅为"推导"而非"文档原文确认"的,会标明"待确认"。所有表名、字段名均为设计阶段讨论名,不代表最终数据库列名。
## 全局设计约定
以下约定建议在所有表统一采用:
- 主键:统一使用自增 `id`,类型 `BIGINT UNSIGNED`,具体方案待确认
- 时间字段:`created_at``updated_at`,类型 `DATETIME`,时区统一为待确认
- 软删:建议统一使用 `deleted_at`,值为 `NULL` 表示未删除,具体策略待确认
- 字符集:建议统一 `utf8mb4`
- 审计:建议所有表至少保留 `created_at``updated_at`
## 已确认逻辑表
- `users`
- `devices`
- `bindings`
- `subscriptions`
- `sessions`
- `treatment_records`
- `pd_data`
- `operation_logs`
## 表级字段草案
### `users`
承载用户身份与账号信息。
| 字段名 | 建议类型 | 是否必填 | 默认值 | 来源 | 说明 |
| --- | --- | --- | --- | --- | --- |
| `id` | `BIGINT UNSIGNED` | 是 | 自增 | 约定 | 主键 |
| `openid` | `VARCHAR(128)` | 是 | 无 | 推导 | 微信用户唯一标识,待确认字段名 |
| `union_id` | `VARCHAR(128)` | 否 | `NULL` | 推导 | 微信开放平台跨应用标识,待确认是否需要 |
| `nickname` | `VARCHAR(64)` | 否 | `NULL` | 推导 | 用户昵称,待确认是否存储 |
| `avatar_url` | `VARCHAR(512)` | 否 | `NULL` | 推导 | 用户头像地址,待确认是否存储 |
| `phone` | `VARCHAR(32)` | 否 | `NULL` | 推导 | 手机号,待确认是否需要 |
| `status` | `TINYINT UNSIGNED` | 是 | `1` | 推导 | 用户状态枚举,待确认 |
| `created_at` | `DATETIME` | 是 | `CURRENT_TIMESTAMP` | 约定 | 创建时间 |
| `updated_at` | `DATETIME` | 是 | `CURRENT_TIMESTAMP ON UPDATE` | 约定 | 更新时间 |
| `deleted_at` | `DATETIME` | 否 | `NULL` | 约定 | 软删时间 |
建议唯一索引:`openid`
建议状态枚举(待确认):
| 值 | 含义 |
| --- | --- |
| `1` | 正常 |
| `2` | 禁用 |
| `3` | 注销 |
### `devices`
承载设备主数据。
| 字段名 | 建议类型 | 是否必填 | 默认值 | 来源 | 说明 |
| --- | --- | --- | --- | --- | --- |
| `id` | `BIGINT UNSIGNED` | 是 | 自增 | 约定 | 主键 |
| `device_sn` | `VARCHAR(64)` | 是 | 无 | 推导 | 设备序列号,作为设备唯一业务标识,待确认字段名和格式 |
| `product_id` | `VARCHAR(64)` | 是 | 无 | 文档确认 | IoT 平台产品 ID |
| `device_name` | `VARCHAR(128)` | 是 | 无 | 文档确认 | IoT 平台设备名称 |
| `firmware_version` | `VARCHAR(32)` | 否 | `NULL` | 推导 | 当前固件版本 |
| `hardware_version` | `VARCHAR(32)` | 否 | `NULL` | 推导 | 硬件版本 |
| `status` | `TINYINT UNSIGNED` | 是 | `1` | 推导 | 设备状态枚举,待确认 |
| `activated_at` | `DATETIME` | 否 | `NULL` | 推导 | 首次激活时间 |
| `created_at` | `DATETIME` | 是 | `CURRENT_TIMESTAMP` | 约定 | 创建时间 |
| `updated_at` | `DATETIME` | 是 | `CURRENT_TIMESTAMP ON UPDATE` | 约定 | 更新时间 |
| `deleted_at` | `DATETIME` | 否 | `NULL` | 约定 | 软删时间 |
建议唯一索引:`device_sn`
建议状态枚举(待确认):
| 值 | 含义 |
| --- | --- |
| `1` | 未激活 |
| `2` | 已激活 |
| `3` | 禁用 |
| `4` | 故障 |
### `bindings`
承载用户与设备的绑定关系。
| 字段名 | 建议类型 | 是否必填 | 默认值 | 来源 | 说明 |
| --- | --- | --- | --- | --- | --- |
| `id` | `BIGINT UNSIGNED` | 是 | 自增 | 约定 | 主键 |
| `user_id` | `BIGINT UNSIGNED` | 是 | 无 | 推导 | 关联 `users.id` |
| `device_id` | `BIGINT UNSIGNED` | 是 | 无 | 推导 | 关联 `devices.id` |
| `status` | `TINYINT UNSIGNED` | 是 | `1` | 推导 | 绑定状态枚举,待确认 |
| `bound_at` | `DATETIME` | 是 | `CURRENT_TIMESTAMP` | 推导 | 绑定时间 |
| `unbound_at` | `DATETIME` | 否 | `NULL` | 推导 | 解绑时间 |
| `created_at` | `DATETIME` | 是 | `CURRENT_TIMESTAMP` | 约定 | 创建时间 |
| `updated_at` | `DATETIME` | 是 | `CURRENT_TIMESTAMP ON UPDATE` | 约定 | 更新时间 |
建议索引:`user_id` + `status``device_id` + `status`
建议状态枚举(待确认):
| 值 | 含义 |
| --- | --- |
| `1` | 有效 |
| `2` | 已解绑 |
待确认关系约束:
- 同一时刻一个用户是否只能绑定一台设备
- 同一时刻一台设备是否只能绑定一个用户
- 解绑后是否保留历史记录
### `subscriptions`
承载试用与正式订阅信息。
| 字段名 | 建议类型 | 是否必填 | 默认值 | 来源 | 说明 |
| --- | --- | --- | --- | --- | --- |
| `id` | `BIGINT UNSIGNED` | 是 | 自增 | 约定 | 主键 |
| `user_id` | `BIGINT UNSIGNED` | 是 | 无 | 推导 | 关联 `users.id`,待确认是否同时关联设备 |
| `device_id` | `BIGINT UNSIGNED` | 否 | `NULL` | 推导 | 关联 `devices.id`,待确认是否需要 |
| `type` | `TINYINT UNSIGNED` | 是 | 无 | 推导 | 订阅类型枚举 |
| `status` | `TINYINT UNSIGNED` | 是 | `1` | 推导 | 订阅状态枚举 |
| `started_at` | `DATETIME` | 是 | 无 | 推导 | 生效时间 |
| `expired_at` | `DATETIME` | 是 | 无 | 推导 | 到期时间 |
| `source` | `VARCHAR(32)` | 否 | `NULL` | 推导 | 来源说明,如 `trial_grant``manual_create``purchase`,待确认 |
| `source_id` | `VARCHAR(64)` | 否 | `NULL` | 推导 | 来源关联 ID,如订单号,待确认是否有订单概念 |
| `created_at` | `DATETIME` | 是 | `CURRENT_TIMESTAMP` | 约定 | 创建时间 |
| `updated_at` | `DATETIME` | 是 | `CURRENT_TIMESTAMP ON UPDATE` | 约定 | 更新时间 |
建议索引:`user_id` + `status``user_id` + `type`
建议类型枚举(待确认):
| 值 | 含义 |
| --- | --- |
| `1` | 试用 |
| `2` | 正式 |
| `3` | 赠送 |
建议状态枚举(待确认):
| 值 | 含义 |
| --- | --- |
| `1` | 有效 |
| `2` | 已过期 |
| `3` | 已停用 |
### `sessions`
承载一次治疗会话的过程态。
| 字段名 | 建议类型 | 是否必填 | 默认值 | 来源 | 说明 |
| --- | --- | --- | --- | --- | --- |
| `id` | `BIGINT UNSIGNED` | 是 | 自增 | 约定 | 主键 |
| `user_id` | `BIGINT UNSIGNED` | 是 | 无 | 推导 | 关联 `users.id` |
| `device_id` | `BIGINT UNSIGNED` | 是 | 无 | 推导 | 关联 `devices.id` |
| `status` | `TINYINT UNSIGNED` | 是 | `1` | 推导 | 会话状态枚举 |
| `started_at` | `DATETIME` | 否 | `NULL` | 推导 | 会话开始时间 |
| `ended_at` | `DATETIME` | 否 | `NULL` | 推导 | 会话结束时间 |
| `created_at` | `DATETIME` | 是 | `CURRENT_TIMESTAMP` | 约定 | 创建时间 |
| `updated_at` | `DATETIME` | 是 | `CURRENT_TIMESTAMP ON UPDATE` | 约定 | 更新时间 |
建议索引:`user_id` + `status``device_id`
建议状态枚举(待确认):
| 值 | 含义 |
| --- | --- |
| `1` | 进行中 |
| `2` | 已完成 |
| `3` | 已中断 |
| `4` | 失败 |
待确认边界:`sessions``treatment_records` 是否一对一。
### `treatment_records`
承载治疗结果记录。
| 字段名 | 建议类型 | 是否必填 | 默认值 | 来源 | 说明 |
| --- | --- | --- | --- | --- | --- |
| `id` | `BIGINT UNSIGNED` | 是 | 自增 | 约定 | 主键 |
| `session_id` | `BIGINT UNSIGNED` | 是 | 无 | 推导 | 关联 `sessions.id`,待确认一对一还是一对多 |
| `user_id` | `BIGINT UNSIGNED` | 是 | 无 | 推导 | 关联 `users.id`,冗余查询用 |
| `device_id` | `BIGINT UNSIGNED` | 是 | 无 | 推导 | 关联 `devices.id`,冗余查询用 |
| `duration_seconds` | `INT UNSIGNED` | 否 | `NULL` | 推导 | 治疗时长秒数,待确认字段名和单位 |
| `mode` | `TINYINT UNSIGNED` | 否 | `NULL` | 推导 | 治疗模式,待确认枚举 |
| `result_summary` | `VARCHAR(512)` | 否 | `NULL` | 推导 | 结果摘要,待确认格式 |
| `sync_status` | `TINYINT UNSIGNED` | 是 | `1` | 推导 | 同步状态,用于追踪异步写入 |
| `synced_at` | `DATETIME` | 否 | `NULL` | 推导 | 同步完成时间 |
| `started_at` | `DATETIME` | 否 | `NULL` | 推导 | 治疗开始时间 |
| `ended_at` | `DATETIME` | 否 | `NULL` | 推导 | 治疗结束时间 |
| `created_at` | `DATETIME` | 是 | `CURRENT_TIMESTAMP` | 约定 | 创建时间 |
| `updated_at` | `DATETIME` | 是 | `CURRENT_TIMESTAMP ON UPDATE` | 约定 | 更新时间 |
建议索引:`user_id` + `started_at``session_id``sync_status`
建议同步状态枚举(待确认):
| 值 | 含义 |
| --- | --- |
| `1` | 待同步 |
| `2` | 已同步 |
| `3` | 同步失败 |
### `pd_data`
承载与 `PD` 相关的数据。
当前只知道该表存在,字段无法推导。
| 字段名 | 建议类型 | 是否必填 | 默认值 | 来源 | 说明 |
| --- | --- | --- | --- | --- | --- |
| `id` | `BIGINT UNSIGNED` | 是 | 自增 | 约定 | 主键 |
| `session_id` | `BIGINT UNSIGNED` | 否 | `NULL` | 推导 | 关联 `sessions.id`,待确认 |
| `device_id` | `BIGINT UNSIGNED` | 否 | `NULL` | 推导 | 关联 `devices.id`,待确认 |
| `data_payload` | 待定义 | 待定义 | 待定义 | 待定义 | 数据内容,格式和结构完全未确认 |
| `recorded_at` | `DATETIME` | 否 | `NULL` | 推导 | 采集时间 |
| `created_at` | `DATETIME` | 是 | `CURRENT_TIMESTAMP` | 约定 | 创建时间 |
待确认:
- `PD` 的含义和数据来源
- 是否为高频时序数据
- 是否需要单独存储引擎
- 是否按会话切片
### `operation_logs`
承载操作日志。
| 字段名 | 建议类型 | 是否必填 | 默认值 | 来源 | 说明 |
| --- | --- | --- | --- | --- | --- |
| `id` | `BIGINT UNSIGNED` | 是 | 自增 | 约定 | 主键 |
| `operator_type` | `TINYINT UNSIGNED` | 是 | 无 | 推导 | 操作者类型,区分管理员和系统 |
| `operator_id` | `BIGINT UNSIGNED` | 否 | `NULL` | 推导 | 操作者 ID,关联 `users` 或后台管理员表 |
| `target_type` | `VARCHAR(32)` | 是 | 无 | 推导 | 操作对象类型,如 `user``device``subscription``binding` |
| `target_id` | `BIGINT UNSIGNED` | 否 | `NULL` | 推导 | 操作对象 ID |
| `action` | `VARCHAR(32)` | 是 | 无 | 推导 | 操作类型,如 `create``update``delete``bind``unbind` |
| `before_snapshot` | `TEXT` | 否 | `NULL` | 推导 | 操作前数据快照,待确认格式 |
| `after_snapshot` | `TEXT` | 否 | `NULL` | 推导 | 操作后数据快照,待确认格式 |
| `ip_address` | `VARCHAR(64)` | 否 | `NULL` | 推导 | 操作来源 IP |
| `user_agent` | `VARCHAR(256)` | 否 | `NULL` | 推导 | 操作来源客户端标识 |
| `remark` | `VARCHAR(256)` | 否 | `NULL` | 推导 | 备注说明 |
| `created_at` | `DATETIME` | 是 | `CURRENT_TIMESTAMP` | 约定 | 创建时间 |
建议索引:`target_type` + `target_id``operator_type` + `operator_id``created_at`
建议操作者类型枚举(待确认):
| 值 | 含义 |
| --- | --- |
| `1` | 管理员 |
| `2` | 系统自动 |
## 实体关系总结
| 关系 | 左侧 | 右侧 | 类型 | 待确认 |
| --- | --- | --- | --- | --- |
| 用户绑定设备 | `users` | `devices` | 通过 `bindings` 多对多 | 是,实际可能接近一对一 |
| 用户拥有订阅 | `users` | `subscriptions` | 一对多 | 否 |
| 设备关联订阅 | `devices` | `subscriptions` | 待确认 | 是,是否需要关联 |
| 用户发起会话 | `users` | `sessions` | 一对多 | 否 |
| 设备执行会话 | `devices` | `sessions` | 一对多 | 否 |
| 会话产生记录 | `sessions` | `treatment_records` | 待确认 | 是,一对一还是一对多 |
| 会话产生 PD 数据 | `sessions` | `pd_data` | 待确认 | 是 |
| 操作日志记录对象 | `operation_logs` | 各业务表 | 多态关联 | 否 |
## 每张表仍需补齐的设计项
后续推进到 DDL 时,每张表至少还需要:
- 确认主键方案
- 确认字段类型和长度
- 确认枚举值
- 确认时区约定
- 确认软删策略
- 补充 DDL
- 补充索引设计
- 补充迁移脚本
## 当前结论
当前说明已经足够把数据库推进到"字段草案"层。所有标为"推导"的字段都需要在下一步被确认或修正。最优先要确认的是 `users``devices` 的绑定约束、`subscriptions` 的归属模型、`sessions``treatment_records` 的关系。