数据库规范
基本约定
- 不使用
AutoMigrate:表结构变更一律通过sql/下的版本目录脚本交付,人工执行; - 所有表和字段必须有中文注释;
- 字符集统一
utf8mb4,排序规则统一utf8mb4_general_ci; - 数值枚举从
1开始,0仅表示「未设置/不过滤」,并在internal/common/enums与前端src/enums集中定义; - 软删除使用
deleted_at(GORMgorm.DeletedAt),查询默认排除已删除记录; - 表名:核心表
sys_*前缀;插件业务表plg_{插件ID}_*前缀。
SQL 目录
text
sql/
├── v0.0.1/ # 全量初始化脚本
├── v0.0.2/ # 插件基础设施、操作日志清理
├── v0.0.3/ # 会员用户表与菜单
└── plugins/ # 插件安装器归档的插件迁移新版本脚本放在对应版本目录,脚本应可重复执行(CREATE TABLE IF NOT EXISTS、菜单按业务键判断等),并在对应版本的更新说明中描述执行方式。
索引与一致性
- 主键、唯一约束、查询条件与排序字段按访问方式建立索引;
- 业务唯一性必须由唯一索引兜底,不能只依赖应用层先查后写;
- 可空唯一字段(如会员登录账号)使用 NULL 表示未设置——MySQL 唯一索引允许多个 NULL;
- 并发写入使用事务、条件更新或锁,禁止「先查再无条件写」;保存类接口优先
clause.OnConflictupsert; - 外键约束是否使用与现有项目保持一致,但关联 ID 必须有索引。
字段类型
- 金额类字段使用
decimal(如sys_member.balance为decimal(12,2)),Go 模型与 Resp 用字符串承载,禁止 float/double; - 时间字段
datetime(3),对外输出格式化到秒(不展示毫秒); - 文件字段只保存相对路径,访问地址按当前存储配置动态补全;
- 密钥类字段(私钥、Secret)响应结构一律不返回。
表关系
- Model 只映射当前表字段,不定义关联对象;表关联关系在 Resp 中定义,优先使用 GORM
Preload批量加载,避免 N+1 查询; - 树形结构(菜单、部门、角色)由
pkg/tree.BuildTree生成{data, children}。
核心数据表
| 表 | 作用 |
|---|---|
sys_user | 管理员账号 |
sys_member | 会员(C 端用户)账号 |
sys_user_login | 登录流水 |
sys_role / sys_user_role / sys_role_menu | 角色与授权关系 |
sys_menu | 菜单、页面与按钮权限 |
sys_dept | 部门 |
sys_operation_log | 管理端操作日志 |
sys_storage_config / sys_upload_file | 存储渠道与上传记录 |
sys_sms_config / sys_sms_signature / sys_sms_template / sys_sms_send_log | 短信配置与发送记录 |
sys_wechat_config / sys_payment_config / sys_platform_config | 渠道与平台配置 |
sys_plugin / sys_plugin_migration / sys_plugin_menu / sys_plugin_install_log | 插件基础设施 |