Files
EasyCard/docs/数据库设计文档.md
陈子默 74543cb9bf docs: 补充项目设计与环境文档
- 增加产品功能、技术方案与数据库设计说明

- 增加本地中间件环境与联调说明
2026-03-20 12:45:23 +08:00

433 lines
9.0 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.
# 电子名片系统数据库设计文档
## 1. 文档目标
本文档用于固定电子名片系统第一阶段的数据库模型,覆盖多租户后台、小程序 `AppID` 绑定、组织/用户/名片、素材、统计、审计等核心模块,并与当前产品文档、技术文档保持一致。
对应初始化脚本:
- [easycard_init.sql](/Users/slience/postgraduate/easycard/database/mysql/easycard_init.sql)
- [V1__create_core_schema.sql](/Users/slience/postgraduate/easycard/backend/easycard-boot/src/main/resources/db/migration/mysql/V1__create_core_schema.sql)
- [V2__seed_platform_base_data.sql](/Users/slience/postgraduate/easycard/backend/easycard-boot/src/main/resources/db/migration/mysql/V2__seed_platform_base_data.sql)
## 2. 设计原则
### 2.1 总体原则
- 数据库MySQL 8.x
- 字符集:`utf8mb4`
- 排序规则:`utf8mb4_0900_ai_ci`
- 架构模式:单库单 Schema多租户共享表结构
- 多租户隔离:业务表统一使用 `tenant_id`
- 小程序租户识别:使用 `miniapp_app_id` 映射到 `tenant_id`
### 2.2 关键约束
- 平台级数据使用 `tenant_id = 0`
- 租户业务数据必须带 `tenant_id > 0`
- 小程序 `AppID` 全平台唯一
- 一个租户在同一环境仅允许一条小程序配置
- 用户、角色、组织编码、专业领域编码等按租户唯一
### 2.3 删除策略
- 核心业务表默认使用逻辑删除字段 `deleted`
- 日志和统计明细表默认不做逻辑删除
- 需要唯一约束的业务表,唯一索引统一带上 `deleted`
### 2.4 主键策略
第一阶段采用:
- `BIGINT UNSIGNED AUTO_INCREMENT`
原因:
- 对当前规模足够简单稳定
- 便于直接落地和排查问题
- 后续如需分布式 ID可在应用层平滑切换
### 2.5 外键策略
第一阶段不强依赖数据库物理外键,采用“应用层维护逻辑关联 + 数据库索引约束”的方式。
原因:
- 更适合多租户共享表结构
- 更利于后续表结构演进
- 避免逻辑删除和历史日志场景下的迁移成本
## 3. 核心实体关系
```mermaid
erDiagram
SYS_TENANT ||--o{ TENANT_MINIAPP_CONFIG : has
SYS_TENANT ||--o{ SYS_USER : owns
SYS_TENANT ||--o{ SYS_ROLE : owns
SYS_TENANT ||--o{ ORG_DEPARTMENT : owns
SYS_TENANT ||--|| ORG_FIRM_PROFILE : owns
SYS_TENANT ||--o{ ORG_FIRM_PRACTICE_AREA : owns
SYS_TENANT ||--o{ CARD_PROFILE : owns
SYS_TENANT ||--o{ FILE_ASSET : owns
SYS_USER ||--o{ SYS_USER_ROLE : has
SYS_ROLE ||--o{ SYS_USER_ROLE : assigned
SYS_ROLE ||--o{ SYS_ROLE_MENU : grants
SYS_MENU ||--o{ SYS_ROLE_MENU : bound
ORG_DEPARTMENT ||--o{ SYS_USER : contains
SYS_USER ||--|| CARD_PROFILE : owns
CARD_PROFILE ||--o{ CARD_PROFILE_SPECIALTY : has
ORG_FIRM_PRACTICE_AREA ||--o{ CARD_PROFILE_SPECIALTY : references
FILE_ASSET ||--o{ FILE_ASSET_USAGE : used_by
CARD_PROFILE ||--o{ CARD_VIEW_LOG : viewed
CARD_PROFILE ||--o{ CARD_SHARE_LOG : shared
CARD_PROFILE ||--o{ CARD_STAT_DAILY : aggregated
```
## 4. 模块划分
### 4.1 平台与租户
- `sys_tenant`
- `tenant_miniapp_config`
- `sys_config`
### 4.2 账号与权限
- `sys_user`
- `sys_role`
- `sys_user_role`
- `sys_menu`
- `sys_role_menu`
### 4.3 基础字典
- `sys_dict_type`
- `sys_dict_item`
### 4.4 组织与事务所信息
- `org_department`
- `org_firm_profile`
- `org_firm_practice_area`
### 4.5 名片与素材
- `card_profile`
- `card_profile_specialty`
- `file_asset`
- `file_asset_usage`
### 4.6 统计与审计
- `card_view_log`
- `card_share_log`
- `card_stat_daily`
- `sys_login_log`
- `sys_operation_log`
## 5. 关键表设计说明
## 5.1 `sys_tenant`
用途:
- 平台租户主表
- 管理事务所基础信息、到期时间、资源上限、启停用状态
关键字段:
- `tenant_code`:租户编码,平台唯一
- `tenant_name`:租户名称
- `tenant_status``ENABLED / DISABLED / EXPIRED`
- `user_limit`:用户上限
- `storage_limit_mb`:素材存储空间上限
## 5.2 `tenant_miniapp_config`
用途:
- 维护租户与微信小程序的映射关系
- 后端通过 `miniapp_app_id` 识别租户
关键字段:
- `tenant_id`
- `env_code``DEV / TEST / PROD`
- `miniapp_app_id`
- `miniapp_app_secret`
- `miniapp_original_id`
- `request_domain`
- `publish_status``UNCONFIGURED / DRAFT / PUBLISHED / DISABLED`
关键约束:
- `miniapp_app_id` 全局唯一
- `tenant_id + env_code + deleted` 唯一
## 5.3 `sys_user`
用途:
- 平台用户与租户用户统一账号表
关键字段:
- `tenant_id`:平台用户固定为 `0`
- `user_type``PLATFORM / TENANT`
- `username`
- `password_hash`
- `dept_id`
- `user_status``ENABLED / DISABLED / LOCKED`
- `must_update_password`
关键约束:
- `tenant_id + username + deleted` 唯一
## 5.4 `sys_role`
用途:
- 平台角色和租户角色统一管理
关键字段:
- `role_scope``PLATFORM / TENANT`
- `role_code`
- `role_name`
- `data_scope``ALL / TENANT / DEPT / SELF`
- `is_builtin`
关键约束:
- `tenant_id + role_code + deleted` 唯一
补充说明:
- 平台初始化脚本仅预置平台超级管理员角色
- `TENANT_ADMIN``TENANT_USER` 这类租户内置角色,应在“创建租户”流程中按租户自动生成
## 5.5 `org_department`
用途:
- 表示总部、分所、部门、业务组等组织树
关键字段:
- `parent_id`
- `dept_type``HEADQUARTERS / BRANCH / DEPARTMENT / GROUP`
- `dept_code`
- `dept_name`
- `leader_user_id`
- `display_order`
说明:
- 小程序前端展示办公机构列表时,可直接读取 `HEADQUARTERS / BRANCH` 类型节点
## 5.6 `org_firm_profile`
用途:
- 事务所对外展示主信息
关键字段:
- `firm_name`
- `firm_short_name`
- `logo_asset_id`
- `hero_asset_id`
- `intro`
- `hotline_phone`
- `hq_address`
- `hq_latitude`
- `hq_longitude`
关键约束:
- 一个租户仅允许一条有效事务所主页记录
## 5.7 `org_firm_practice_area`
用途:
- 租户级专业领域字典
关键字段:
- `area_code`
- `area_name`
- `display_order`
- `area_status`
## 5.8 `card_profile`
用途:
- 用户电子名片主表
关键字段:
- `user_id`
- `card_name`
- `card_title`
- `mobile`
- `email`
- `avatar_asset_id`
- `wechat_qr_asset_id`
- `bio`
- `certificate_no`
- `education_info`
- `honor_info`
- `is_public`
- `publish_status`
- `display_order`
- `view_count`
- `share_count`
关键约束:
- 一个用户默认一张名片,`tenant_id + user_id + deleted` 唯一
## 5.9 `card_profile_specialty`
用途:
- 名片与专业领域的关联表
说明:
- 保留 `specialty_name` 快照,避免租户修改专业领域名称后历史展示失真
## 5.10 `file_asset`
用途:
- 管理头像、Logo、封面图、二维码等素材
关键字段:
- `storage_provider`
- `bucket_name`
- `object_key`
- `original_name`
- `file_ext`
- `mime_type`
- `file_size`
- `file_hash`
- `access_url`
- `asset_status`
## 5.11 `file_asset_usage`
用途:
- 记录素材被哪个业务对象引用
- 支持后台查看图片使用情况
关键字段:
- `asset_id`
- `biz_type`
- `biz_id`
- `field_name`
## 5.12 `card_view_log` / `card_share_log` / `card_stat_daily`
用途:
- `card_view_log`:原始浏览明细
- `card_share_log`:原始分享明细
- `card_stat_daily`:按日聚合统计
说明:
- 原始明细用于追溯
- 聚合表用于后台统计查询
## 5.13 `sys_login_log` / `sys_operation_log`
用途:
- 平台与租户后台的登录审计
- 关键业务操作审计
说明:
- 这两张表是安全审计与问题排查的基础,不建议省略
## 6. 状态字段建议值
### 6.1 租户状态
- `ENABLED`
- `DISABLED`
- `EXPIRED`
### 6.2 用户状态
- `ENABLED`
- `DISABLED`
- `LOCKED`
### 6.3 小程序发布状态
- `UNCONFIGURED`
- `DRAFT`
- `PUBLISHED`
- `DISABLED`
### 6.4 名片发布状态
- `DRAFT`
- `PUBLISHED`
- `OFFLINE`
### 6.5 文件状态
- `UPLOADED`
- `ACTIVE`
- `ARCHIVED`
- `DELETED`
## 7. 索引设计原则
- 所有高频业务表统一创建 `tenant_id` 索引
- 所有按编码查找的字段创建唯一索引或普通索引
- 行为日志按 `tenant_id + card_id + 时间` 建索引
- 聚合统计表按 `tenant_id + stat_date``tenant_id + card_id + stat_date` 建索引
## 8. 初始化脚本说明
初始化脚本文件:
- [easycard_init.sql](/Users/slience/postgraduate/easycard/database/mysql/easycard_init.sql)
- [Flyway 迁移目录](/Users/slience/postgraduate/easycard/backend/easycard-boot/src/main/resources/db/migration/mysql/README.md)
脚本内容包含:
- 数据库创建
- 全部核心表 DDL
- 索引与唯一约束
- 默认平台角色初始化
- 默认基础菜单初始化
- 默认字典类型与字典项初始化
Flyway 版本化脚本拆分为:
- `V1__create_core_schema.sql`:只负责建表和索引
- `V2__seed_platform_base_data.sql`:只负责平台级基础数据
## 9. 后续扩展建议
当项目进入第二阶段,可在当前模型上继续扩展:
- 名片审核表
- 微信用户绑定表
- Excel 导入任务表
- 消息通知表
- 线索与咨询记录表
第一阶段不建议提前引入过多非核心表,优先保证主链路稳定。