Files
PartsInquiry/doc/数据库设计文档-辅助配置表.md
2025-10-08 19:15:20 +08:00

585 lines
19 KiB
Markdown
Raw Permalink 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.0
**更新时间**: 2025-10-01
**数据库**: MySQL 8.0
**字符集**: utf8mb4 / utf8mb4_0900_ai_ci
---
## 一、VIP会员体系
### 1.1 vip_users会员用户
| 字段 | 类型 | 空值 | 默认值 | 说明 |
|------|------|------|--------|------|
| id | BIGINT UNSIGNED | NO | AUTO_INCREMENT | 主键 |
| shop_id | BIGINT UNSIGNED | NO | | 店铺ID |
| user_id | BIGINT UNSIGNED | NO | | 用户ID |
| is_vip | TINYINT(1) | NO | 1 | 是否VIP1是 0否 |
| status | TINYINT UNSIGNED | NO | 0 | 启用状态1启用 0停用 |
| expire_at | DATETIME | YES | NULL | 到期时间 |
| remark | VARCHAR(255) | YES | NULL | 备注/审核说明 |
| reviewer_id | BIGINT UNSIGNED | YES | NULL | 审核人 |
| reviewed_at | DATETIME | YES | NULL | 审核时间 |
| created_at | TIMESTAMP | NO | CURRENT_TIMESTAMP | 创建时间 |
| updated_at | TIMESTAMP | NO | CURRENT_TIMESTAMP | 更新时间 |
**索引**
- PRIMARY KEY: `id`
- KEY: `idx_vu_shop_user` (`shop_id`, `user_id`)
- KEY: `idx_vu_shop_status` (`shop_id`, `status`)
**外键**
- `fk_vu_shop`: `shop_id``shops(id)`
- `fk_vu_user`: `user_id``users(id)`
- `fk_vu_reviewer`: `reviewer_id``users(id)`
**说明**
- VIP状态判定`status=1 AND is_vip=1 AND (expire_at IS NULL OR expire_at >= NOW())`
- 非VIP用户数据可见性最近60天可配置
- VIP用户查看全部历史数据
---
### 1.2 vip_priceVIP价格
| 字段 | 类型 | 空值 | 默认值 | 说明 |
|------|------|------|--------|------|
| price | DECIMAL(10,2) | NO | | 单月价格(元) |
**索引**:无
**说明**
- 全局配置表,仅一条记录
- 表示平台统一VIP单月价格
- 管理端可读取和修改
---
### 1.3 vip_rechargesVIP充值记录
| 字段 | 类型 | 空值 | 默认值 | 说明 |
|------|------|------|--------|------|
| id | BIGINT UNSIGNED | NO | AUTO_INCREMENT | 主键 |
| shop_id | BIGINT UNSIGNED | NO | | 店铺ID |
| user_id | BIGINT UNSIGNED | NO | | 用户ID |
| price | DECIMAL(10,2) | NO | | 本次充值价格(元) |
| duration_days | INT | NO | | 本次续期天数 |
| expire_from | DATETIME | YES | NULL | 生效前到期时间 |
| expire_to | DATETIME | NO | | 生效后到期时间 |
| channel | VARCHAR(32) | NO | 'oneclick' | 渠道oneclick/... |
| created_at | TIMESTAMP | NO | CURRENT_TIMESTAMP | 创建时间 |
**索引**
- PRIMARY KEY: `id`
- KEY: `idx_vr_shop` (`shop_id`)
- KEY: `idx_vr_user` (`user_id`)
**外键**
- `fk_vr_shop`: `shop_id``shops(id)`
- `fk_vr_user`: `user_id``users(id)`
**说明**记录每次VIP开通/续费的历史,支持对账和查询。
---
## 二、普通管理员体系
### 2.1 normal_admin_audits普通管理员审计
| 字段 | 类型 | 空值 | 默认值 | 说明 |
|------|------|------|--------|------|
| id | BIGINT UNSIGNED | NO | AUTO_INCREMENT | 主键 |
| shop_id | BIGINT UNSIGNED | NO | | 店铺ID |
| user_id | BIGINT UNSIGNED | NO | | 用户ID |
| action | ENUM('apply','approve','reject','revoke','expire') | NO | | 操作类型 |
| remark | VARCHAR(255) | YES | NULL | 备注 |
| operator_admin_id | BIGINT UNSIGNED | YES | NULL | 平台管理员ID |
| previous_role | VARCHAR(32) | YES | NULL | 变更前角色 |
| new_role | VARCHAR(32) | YES | NULL | 变更后角色 |
| created_at | TIMESTAMP | NO | CURRENT_TIMESTAMP | 创建时间 |
**索引**
- PRIMARY KEY: `id`
- KEY: `idx_naudit_shop_time` (`shop_id`, `created_at`)
- KEY: `idx_naudit_user_time` (`user_id`, `created_at`)
**外键**
- `fk_naudit_shop`: `shop_id``shops(id)`
- `fk_naudit_user`: `user_id``users(id)`
- `fk_naudit_admin`: `operator_admin_id``admins(id)`
**说明**
- 普通管理员申请、审批、撤销的完整审计日志
- 当前状态 = 按user_id取最后一条记录的action
- VIP失效触发降级时写入expire审计
---
## 三、身份与认证
### 3.1 user_identities第三方身份映射
| 字段 | 类型 | 空值 | 默认值 | 说明 |
|------|------|------|--------|------|
| id | BIGINT UNSIGNED | NO | AUTO_INCREMENT | 主键 |
| shop_id | BIGINT UNSIGNED | NO | | 店铺ID |
| user_id | BIGINT UNSIGNED | NO | | 用户ID |
| provider | ENUM('wechat_mp','wechat_app') | NO | | 身份提供方 |
| openid | VARCHAR(64) | NO | | 微信openid |
| unionid | VARCHAR(64) | YES | NULL | 微信unionid |
| nickname | VARCHAR(64) | YES | NULL | 昵称 |
| avatar_url | VARCHAR(512) | YES | NULL | 头像URL |
| last_login_at | DATETIME | YES | NULL | 最后登录时间 |
| created_at | TIMESTAMP | NO | CURRENT_TIMESTAMP | 创建时间 |
| updated_at | TIMESTAMP | NO | CURRENT_TIMESTAMP | 更新时间 |
**索引**
- PRIMARY KEY: `id`
- KEY: `idx_identity_user` (`user_id`)
- KEY: `idx_identity_shop` (`shop_id`)
- UNIQUE: `ux_identity_provider_openid` (`provider`, `openid`)
- UNIQUE: `ux_identity_unionid` (`unionid`)
**外键**
- `fk_identity_shop`: `shop_id``shops(id)`
- `fk_identity_user`: `user_id``users(id)`
**说明**
- 支持微信小程序和APP登录
- 短信登录使用users.phone作为全局唯一身份不创建identity记录
---
### 3.2 wechat_sessions微信会话
| 字段 | 类型 | 空值 | 默认值 | 说明 |
|------|------|------|--------|------|
| id | BIGINT UNSIGNED | NO | AUTO_INCREMENT | 主键 |
| provider | ENUM('wechat_mp','wechat_app') | NO | | 提供方 |
| openid | VARCHAR(64) | NO | | 微信openid |
| session_key | VARCHAR(128) | NO | | 会话密钥 |
| expires_at | DATETIME | NO | | 过期时间 |
| created_at | TIMESTAMP | NO | CURRENT_TIMESTAMP | 创建时间 |
**索引**
- PRIMARY KEY: `id`
- KEY: `idx_wechat_session_expires` (`expires_at`)
- UNIQUE: `ux_wechat_session` (`provider`, `openid`)
**说明**:临时存储微信会话密钥。
---
### 3.3 sms_codes短信验证码
| 字段 | 类型 | 空值 | 默认值 | 说明 |
|------|------|------|--------|------|
| id | BIGINT UNSIGNED | NO | AUTO_INCREMENT | 主键 |
| phone | VARCHAR(32) | NO | | 手机号 |
| scene | VARCHAR(32) | NO | 'login' | 场景login/register/... |
| code_hash | CHAR(64) | NO | | 验证码哈希SHA-256 |
| salt | CHAR(32) | NO | | 加盐字符串 |
| expire_at | DATETIME | NO | | 过期时间 |
| status | TINYINT UNSIGNED | NO | 0 | 0=active 1=used 2=expired 3=blocked |
| fail_count | TINYINT UNSIGNED | NO | 0 | 错误次数 |
| ip | VARCHAR(45) | YES | NULL | 发送IP |
| created_at | TIMESTAMP | NO | CURRENT_TIMESTAMP | 创建时间 |
| updated_at | TIMESTAMP | NO | CURRENT_TIMESTAMP | 更新时间 |
**索引**
- PRIMARY KEY: `id`
- KEY: `idx_phone_created_at` (`phone`, `created_at`)
- KEY: `idx_phone_scene_status` (`phone`, `scene`, `status`)
- KEY: `idx_expire_at` (`expire_at`)
- KEY: `idx_ip_created_at` (`ip`, `created_at`)
**说明**
- 验证码采用哈希+盐存储
- 支持多场景(登录、注册、重置密码等)
- 记录失败次数防止暴力破解
---
### 3.4 email_codes邮箱验证码
| 字段 | 类型 | 空值 | 默认值 | 说明 |
|------|------|------|--------|------|
| id | BIGINT UNSIGNED | NO | AUTO_INCREMENT | 主键 |
| email | VARCHAR(128) | NO | | 邮箱 |
| scene | VARCHAR(32) | NO | | 场景login/register/reset |
| code_hash | VARCHAR(64) | NO | | 验证码哈希SHA-256 |
| salt | VARCHAR(64) | NO | | 加盐字符串 |
| expire_at | DATETIME | NO | | 过期时间 |
| status | TINYINT UNSIGNED | NO | 0 | 0=unused 1=used 2=expired |
| fail_count | INT | NO | 0 | 错误次数 |
| ip | VARCHAR(64) | YES | NULL | 发送IP |
| created_at | TIMESTAMP | NO | CURRENT_TIMESTAMP | 创建时间 |
| updated_at | TIMESTAMP | NO | CURRENT_TIMESTAMP | 更新时间 |
**索引**
- PRIMARY KEY: `id`
- KEY: `idx_email_scene_created` (`email`, `scene`, `created_at`)
- KEY: `idx_email_expire` (`expire_at`)
**说明**与sms_codes类似用于邮箱验证场景。
---
## 四、咨询与公告
### 4.1 consults咨询
| 字段 | 类型 | 空值 | 默认值 | 说明 |
|------|------|------|--------|------|
| id | BIGINT UNSIGNED | NO | AUTO_INCREMENT | 主键 |
| shop_id | BIGINT UNSIGNED | NO | | 所属店铺 |
| user_id | BIGINT UNSIGNED | NO | | 提问用户 |
| topic | VARCHAR(120) | NO | | 主题 |
| message | TEXT | NO | | 咨询内容 |
| status | ENUM('open','resolved','closed') | NO | 'open' | 状态 |
| created_at | TIMESTAMP | NO | CURRENT_TIMESTAMP | 创建时间 |
| updated_at | TIMESTAMP | NO | CURRENT_TIMESTAMP | 更新时间 |
**索引**
- PRIMARY KEY: `id`
- KEY: `idx_consult_shop_status` (`shop_id`, `status`)
- KEY: `fk_consult_user` (`user_id`)
**外键**
- `fk_consult_shop`: `shop_id``shops(id)`
- `fk_consult_user`: `user_id``users(id)`
**说明**
- open=未解决resolved=已解决closed=关闭
- 触发器有回复时自动标记为resolved
---
### 4.2 consult_replies咨询回复
| 字段 | 类型 | 空值 | 默认值 | 说明 |
|------|------|------|--------|------|
| id | BIGINT UNSIGNED | NO | AUTO_INCREMENT | 主键 |
| consult_id | BIGINT UNSIGNED | NO | | 所属咨询 |
| user_id | BIGINT UNSIGNED | NO | | 回复人(管理员) |
| content | TEXT | NO | | 回复内容 |
| created_at | TIMESTAMP | NO | CURRENT_TIMESTAMP | 回复时间 |
**索引**
- PRIMARY KEY: `id`
- KEY: `idx_cr_consult` (`consult_id`)
- KEY: `fk_cr_user` (`user_id`)
**外键**
- `fk_cr_consult`: `consult_id``consults(id)`
- `fk_cr_user`: `user_id``users(id)`
**说明**:管理员对咨询的回复记录。
---
### 4.3 notices公告
| 字段 | 类型 | 空值 | 默认值 | 说明 |
|------|------|------|--------|------|
| id | BIGINT UNSIGNED | NO | AUTO_INCREMENT | 主键 |
| title | VARCHAR(120) | NO | | 标题 |
| content | VARCHAR(500) | NO | | 内容(跑马灯) |
| tag | VARCHAR(32) | YES | NULL | 标签(如"活动" |
| is_pinned | TINYINT(1) | NO | 0 | 是否置顶 |
| starts_at | DATETIME | YES | NULL | 生效开始时间 |
| ends_at | DATETIME | YES | NULL | 生效结束时间 |
| status | ENUM('draft','published','offline') | NO | 'published' | 状态 |
| created_at | TIMESTAMP | NO | CURRENT_TIMESTAMP | 创建时间 |
| updated_at | TIMESTAMP | NO | CURRENT_TIMESTAMP | 更新时间 |
| deleted_at | DATETIME | YES | NULL | 软删除标记 |
**索引**
- PRIMARY KEY: `id`
- KEY: `idx_notices_time` (`starts_at`, `ends_at`)
**说明**
- 平台全局公告,与租户无关
- 前台仅显示status='published'且在有效期内的公告
- 排序is_pinned DESC, created_at DESC
---
## 五、系统配置
### 5.1 system_parameters系统参数
| 字段 | 类型 | 空值 | 默认值 | 说明 |
|------|------|------|--------|------|
| id | BIGINT UNSIGNED | NO | AUTO_INCREMENT | 主键 |
| shop_id | BIGINT UNSIGNED | NO | | 店铺ID |
| user_id | BIGINT UNSIGNED | NO | | 创建/修改人 |
| key | VARCHAR(64) | NO | | 参数键 |
| value | JSON | NO | | 参数值JSON |
| created_at | TIMESTAMP | NO | CURRENT_TIMESTAMP | 创建时间 |
| updated_at | TIMESTAMP | NO | CURRENT_TIMESTAMP | 更新时间 |
**索引**
- PRIMARY KEY: `id`
- KEY: `idx_sysparams_shop` (`shop_id`)
- UNIQUE: `ux_sysparams_shop_key` (`shop_id`, `key`)
**外键**
- `fk_sysparams_shop`: `shop_id``shops(id)`
- `fk_sysparams_user`: `user_id``users(id)`
**说明**
- 租户级配置支持JSON格式存储复杂配置
- 常用配置键:
- `vip.dataRetentionDaysForNonVip`: 非VIP数据保留天数默认60
- `normalAdmin.autoApprove`: 普通管理员自动审批默认false
- `normalAdmin.requiredVipActive`: 要求VIP有效默认true
---
### 5.2 finance_categories财务分类
| 字段 | 类型 | 空值 | 默认值 | 说明 |
|------|------|------|--------|------|
| id | BIGINT UNSIGNED | NO | AUTO_INCREMENT | 主键 |
| shop_id | BIGINT UNSIGNED | NO | | 店铺ID0=全局) |
| type | ENUM('income','expense') | NO | | 收入/支出 |
| key | VARCHAR(64) | NO | | 分类key |
| label | VARCHAR(120) | NO | | 分类名称 |
| sort_order | INT | NO | 0 | 排序 |
| status | TINYINT UNSIGNED | NO | 1 | 1=启用 0=停用 |
| created_at | TIMESTAMP | NO | CURRENT_TIMESTAMP | 创建时间 |
| updated_at | TIMESTAMP | NO | CURRENT_TIMESTAMP | 更新时间 |
**索引**
- PRIMARY KEY: `id`
- KEY: `idx_fc_shop_type` (`shop_id`, `type`)
- UNIQUE: `ux_fc_shop_key` (`shop_id`, `key`)
**说明**
- 管理其他收入/支出的分类
- shop_id=0为平台默认分类
- 读取优先级finance_categories表 → system_parameters → application.properties
---
## 六、附件管理
### 6.1 attachments通用附件
| 字段 | 类型 | 空值 | 默认值 | 说明 |
|------|------|------|--------|------|
| id | BIGINT UNSIGNED | NO | AUTO_INCREMENT | 主键 |
| shop_id | BIGINT UNSIGNED | YES | NULL | 店铺ID全局资源可空 |
| user_id | BIGINT UNSIGNED | YES | NULL | 上传人 |
| owner_type | VARCHAR(32) | NO | | 归属类型product/part_submission/... |
| owner_id | BIGINT UNSIGNED | NO | | 归属ID |
| url | VARCHAR(512) | NO | | 文件URL |
| hash | VARCHAR(64) | YES | NULL | 内容哈希SHA-256 |
| meta | JSON | YES | NULL | 元数据 |
| created_at | TIMESTAMP | NO | CURRENT_TIMESTAMP | 创建时间 |
**索引**
- PRIMARY KEY: `id`
- KEY: `idx_attachments_owner` (`owner_type`, `owner_id`)
- UNIQUE: `ux_attachments_hash` (`hash`)
**外键**
- `fk_att_shop`: `shop_id``shops(id)`
- `fk_att_user`: `user_id``users(id)`
**说明**
- 通过hash实现文件去重
- 支持多种归属类型商品、配件提交、全局SKU等
- meta字段存储文件元信息大小、类型等
---
## 七、配件参数字典(扩展)
### 7.1 part_attribute_dictionary参数字典
| 字段 | 类型 | 空值 | 默认值 | 说明 |
|------|------|------|--------|------|
| id | BIGINT UNSIGNED | NO | AUTO_INCREMENT | 主键 |
| attribute_name | VARCHAR(64) | NO | | 参数名称 |
| attribute_unit | VARCHAR(16) | YES | NULL | 单位 |
| attribute_type | ENUM('numeric','text','enum') | NO | 'text' | 类型 |
| enum_values | JSON | YES | NULL | 枚举值 |
| is_searchable | TINYINT(1) | NO | 1 | 是否可搜索 |
| sort_order | INT | NO | 0 | 排序 |
| created_at | TIMESTAMP | NO | CURRENT_TIMESTAMP | 创建时间 |
| updated_at | TIMESTAMP | NO | CURRENT_TIMESTAMP | 更新时间 |
**索引**
- PRIMARY KEY: `id`
- UNIQUE: `ux_pad_name` (`attribute_name`)
**说明**:全局参数字典,定义可用的配件参数。
---
### 7.2 part_categories配件分类
| 字段 | 类型 | 空值 | 默认值 | 说明 |
|------|------|------|--------|------|
| id | BIGINT UNSIGNED | NO | AUTO_INCREMENT | 主键 |
| name | VARCHAR(64) | NO | | 分类名称 |
| parent_id | BIGINT UNSIGNED | YES | NULL | 父分类 |
| sort_order | INT | NO | 0 | 排序 |
| created_at | TIMESTAMP | NO | CURRENT_TIMESTAMP | 创建时间 |
| updated_at | TIMESTAMP | NO | CURRENT_TIMESTAMP | 更新时间 |
**索引**
- PRIMARY KEY: `id`
- KEY: `idx_pc_parent` (`parent_id`)
- UNIQUE: `ux_pc_name` (`name`)
**说明**:配件专用分类,支持层级结构。
---
### 7.3 part_category_attributes分类参数关联
| 字段 | 类型 | 空值 | 默认值 | 说明 |
|------|------|------|--------|------|
| id | BIGINT UNSIGNED | NO | AUTO_INCREMENT | 主键 |
| category_id | BIGINT UNSIGNED | NO | | 分类ID |
| attribute_id | BIGINT UNSIGNED | NO | | 参数ID |
| is_required | TINYINT(1) | NO | 0 | 是否必填 |
| sort_order | INT | NO | 0 | 排序 |
**索引**
- PRIMARY KEY: `id`
- KEY: `idx_pca_category` (`category_id`)
- UNIQUE: `ux_pca_cat_attr` (`category_id`, `attribute_id`)
**外键**
- `fk_pca_category`: `category_id``part_categories(id)` ON DELETE CASCADE
- `fk_pca_attribute`: `attribute_id``part_attribute_dictionary(id)` ON DELETE CASCADE
**说明**:定义每个配件分类应包含哪些参数。
---
### 7.4 part_attribute_templates参数模板
| 字段 | 类型 | 空值 | 默认值 | 说明 |
|------|------|------|--------|------|
| id | BIGINT UNSIGNED | NO | AUTO_INCREMENT | 主键 |
| template_name | VARCHAR(64) | NO | | 模板名称 |
| category_id | BIGINT UNSIGNED | YES | NULL | 关联分类 |
| attributes | JSON | NO | | 参数定义JSON |
| created_at | TIMESTAMP | NO | CURRENT_TIMESTAMP | 创建时间 |
| updated_at | TIMESTAMP | NO | CURRENT_TIMESTAMP | 更新时间 |
**索引**
- PRIMARY KEY: `id`
- KEY: `idx_pat_category` (`category_id`)
- UNIQUE: `ux_pat_name` (`template_name`)
**说明**:预定义的参数模板,快速应用到配件。
---
## 八、配置参数说明
### 8.1 VIP相关配置
| 配置键 | 类型 | 默认值 | 说明 |
|--------|------|--------|------|
| vip.dataRetentionDaysForNonVip | number | 60 | 非VIP数据保留天数 |
| vip.price | number | 15 | VIP单月价格 |
| vip.durationDays | number | 30 | 开通时长(天) |
### 8.2 普通管理员配置
| 配置键 | 类型 | 默认值 | 说明 |
|--------|------|--------|------|
| normalAdmin.autoApprove | boolean | false | 是否自动通过申请 |
| normalAdmin.requiredVipActive | boolean | true | 是否要求VIP有效 |
### 8.3 财务分类配置
**收入分类**income_categories
- operation_income: 经营所得
- interest_income: 利息收入
- other_income: 其它收入
- deposit_ar_income: 收订金/欠款
- investment_income: 投资收入
- sale_income: 销售收入
- account_operation: 账户操作
- fund_transfer_in: 资金转账转入
**支出分类**expense_categories
- operation_expense: 经营支出
- office_supplies: 办公用品
- rent: 房租
- interest_expense: 利息支出
- other_expense: 其它支出
- account_operation: 账户操作
- fund_transfer_out: 资金转账转出
---
## 九、数据安全与性能
### 9.1 敏感数据加密
- 密码SHA-256哈希存储password_hash
- 验证码SHA-256哈希+盐code_hash + salt
- 第三方token加密存储wechat_sessions.session_key
### 9.2 索引策略
- 高频查询字段shop_id, user_id, status, created_at
- 唯一性约束email, phone, openid, hash
- 复合索引:(shop_id, status), (user_id, created_at)
- 全文索引仅用于products.search_text
### 9.3 数据清理
**定期清理**
- sms_codes/email_codes清理7天前expired记录
- wechat_sessions清理过期会话
- inventory_movements归档6个月前数据可选
**软删除**
- 业务表采用deleted_at标记
- 查询默认过滤deleted_at IS NULL
- 定期归档软删除数据
---
## 十、扩展性设计
### 10.1 JSON字段应用
- products.attributes_json: 扩展商品属性
- part_submissions.attributes/images/tags: 灵活配件数据
- attachments.meta: 文件元信息
- system_parameters.value: 动态配置
### 10.2 ENUM类型管理
- 新增枚举值需要ALTER TABLE
- 重要状态采用ENUM确保数据一致性
- 次要分类采用VARCHAR + 配置表
### 10.3 多语言支持预留
- 公告内容可扩展为JSON{zh: "中文", en: "English"}
- 财务分类label可支持多语言
- 当前版本仅支持简体中文
---
**文档维护说明**
- 辅助表主要用于系统配置、认证、审计和扩展功能
- 任何结构变更必须同步更新本文档和`backend/db/db.sql`
- 配置参数变更需同时更新application.properties默认值
- 新增表需评估是否属于核心业务表或辅助表,放入对应文档