diff --git a/DATABASE_DESIGN_OVERVIEW.md b/DATABASE_DESIGN_OVERVIEW.md new file mode 100644 index 0000000..24ad6d0 --- /dev/null +++ b/DATABASE_DESIGN_OVERVIEW.md @@ -0,0 +1,211 @@ +# iShare 数据库设计概要 + +> 基于 DATABASE_DESIGN_V2.md 整理 +> 评审时间:2026-02-17 +> 完整建表 SQL:`db/ishare_schema_v2.sql` +> 完整字段说明:`DATABASE_DESIGN_V2.md` + +--- + +## 一、表总览(23 张表) + +### 1.1 App 基础表(复用 PigX,共 9 张) + +| # | 表名 | 说明 | 变更 | +|---|------|------|------| +| 1 | `app_user` | 用户 | 追加 `invite_code`、`inviter_id` | +| 2 | `app_role` | 角色 | 沿用 | +| 3 | `app_user_role` | 用户角色关联 | 沿用 | +| 4 | `app_social_details` | 第三方登录 | 沿用 | +| 5 | `app_article_category` | 文章分类 | 沿用 | +| 6 | `app_article` | 文章/公告 | 沿用 | +| 7 | `app_article_collect` | 文章收藏 | 沿用 | +| 8 | `app_page` | 页面配置 | 沿用 | +| 9 | `app_tabbar` | 底部导航 | 沿用 | + +### 1.2 业务表(iShare 专属,共 14 张) + +#### 平台与产品 + +| # | 表名 | 说明 | +|---|------|------| +| 10 | `as_platform_type` | 平台分类(视频/音乐/AI等) | +| 11 | `as_platform` | 流媒体平台(Netflix/Spotify等) | +| 12 | `as_sub_plan` | 订阅计划(高级版/家庭版等) | +| 13 | `as_sub_payroll` | 付费方案(月/季/年,含价格) | +| 14 | `as_sub_product` | 合租商品(自营 or 个人发布) | +| 15 | `as_sub_account` | 平台账号凭据(AES 加密存储) | +| 16 | `as_sub_product_comment` | 商品评价 | + +#### 订阅与订单 + +| # | 表名 | 说明 | +|---|------|------| +| 17 | `as_user_sub` | 合租槽/共享池(一个账号对应一个槽) | +| 18 | `as_user_sub_member` | 个人订阅记录(原版缺失最关键表) | +| 19 | `as_order` | 订单(含状态机、价格快照) | + +#### 钱包与推广 + +| # | 表名 | 说明 | +|---|------|------| +| 20 | `as_wallet` | 用户钱包(乐观锁防并发) | +| 21 | `as_wallet_log` | 钱包流水(含余额快照便于对账) | +| 22 | `as_invite` | 邀请关系与返现 | +| 23 | `as_notification` | 系统通知(续费提醒/订单/公告/奖励) | + +--- + +## 二、核心 ER 关系概览 + +``` +as_platform_type (1) ──< (N) as_platform +as_platform (1) ──< (N) as_sub_plan +as_sub_plan (1) ──< (N) as_sub_payroll +as_sub_plan (N) >──< (N) as_sub_product ← sub_plan_ids 逗号分隔(待决策改关联表) +as_platform (1) ──< (N) as_sub_product [platform_id 冗余加速查询] + +as_sub_product (1) ──< (N) as_sub_account [product_id] +as_sub_product (1) ──< (N) as_user_sub [product_id] +as_user_sub (1) ──< (N) as_user_sub_member [sub_id] ← 新增关键关联 + +as_sub_product (1) ──< (N) as_order [product_id] +as_order (1) ──< (1) as_user_sub_member [order_id] + +app_user (1) ──< (1) as_wallet +as_wallet (1) ──< (N) as_wallet_log +app_user (1) ──< (N) as_order +app_user (1) ──< (N) as_user_sub_member +app_user (1) ──< (N) as_invite [as inviter] +app_user (1) ──< (1) as_invite [as invitee] +app_user (1) ──< (N) as_notification +``` + +--- + +## 三、关键状态机 + +### 3.1 订单(as_order) + +``` +[待支付] ─→ 15min 超时 ─→ [已取消] +[待支付] ─→ 支付成功 ─→ [已支付] ─→ 激活订阅 ─→ [已完成] +[已支付/已完成] ─→ 退款 ─→ [已退款] +``` + +### 3.2 个人订阅(as_user_sub_member) + +``` +[待激活] ─→ 订单完成 ─→ [使用中] + ├─→ 到期 ─→ [已到期] ─→ 续费 ─→ [使用中] + └─→ 主动退订 ─→ [已退订] +``` + +### 3.3 合租槽(as_user_sub) + +``` +[可加入(0)] ─→ 席位满(capacity_loaded = capacity) ─→ [已满(1)] +[可加入/已满] ─→ 到期 ─→ [已到期(2)] +[可加入/已满] ─→ 车主关闭 ─→ [已关闭(3)] +``` + +--- + +## 四、关键设计机制 + +### 4.1 席位超卖防护(乐观锁) + +```sql +-- 购买时原子性占位,row affected = 0 则席位已满 +UPDATE as_user_sub +SET capacity_loaded = capacity_loaded + 1 +WHERE id = ? AND capacity_loaded < capacity +``` + +### 4.2 账号凭据加密 + +- 算法:AES-256-GCM(`as_sub_account.encrypt_type = 1`) +- `account_passwd`:密文(Base64) +- `passwd_salt`:随机 IV(16 字节 Base64,**原设计为 int 已修复**) +- 密钥:服务端环境变量,不入库 +- 查看凭据:仅限 `as_user_sub_member.status = 1(使用中)`,服务端解密后返回明文,不记录日志 + +### 4.3 钱包余额并发控制(乐观锁) + +```sql +UPDATE as_wallet +SET balance = balance - ?, version = version + 1 +WHERE user_id = ? AND version = ? AND balance >= ? +-- row affected = 0:并发冲突或余额不足 +``` + +### 4.4 订阅到期定时任务(建议每日 02:00) + +``` +1. expire_time < now() + 7天 且 status=1 → 推送续费提醒通知 +2. expire_time < now() 且 status=1 → 标记 status=2(已到期) + → as_user_sub.capacity_loaded -1(释放席位) +``` + +--- + +## 五、设计评审问题清单 + +> 评审时间:2026-02-17 + +### 🔴 严重(影响核心功能,需修复) + +| # | 问题 | 影响 | 建议方案 | +|---|------|------|----------| +| R1 | **充值流水追踪缺失** | 一旦接入外部支付充值(支付宝/微信),充值过程(待支付→成功)无法追踪,无法对账 | 新增 `as_recharge` 表(order_no / user_id / amount / pay_type / pay_no / status / expire_time / pay_time)| +| R2 | **`as_user_sub_member` 唯一键问题** | `UNIQUE(sub_id, user_id)` 导致续费只能覆盖,历史续费记录丢失,退款/对账有问题 | 去掉唯一键;改为逻辑约束:同 `sub_id+user_id` 只允许一条 `status=1` 记录,续费时新增记录(旧的置为2=已到期) | + +### 🟠 重要(功能不完整,建议修复) + +| # | 问题 | 影响 | 建议方案 | +|---|------|------|----------| +| I1 | **Banner 广告位表缺失** | 首页有 Banner 需求,但无对应表 | 新增 `as_banner`(image_url / link_url / link_type / sort_order / status / start_time / end_time)| +| I2 | **`as_sub_product.sub_plan_ids` 逗号分隔反范式** | 反向查询(某计划关联哪些商品)需 LIKE 模糊查,不走索引 | 改为关联表 `as_product_plan_rel(product_id, plan_id)`(现在改成本最低)| +| I3 | **SYSTEM_DESIGN.md 与 DATABASE_DESIGN_V2.md 字段不一致** | 开发时若参考旧文档会导致实现错误 | 更新 SYSTEM_DESIGN.md ER 图:`user_sub_id→member_id`、`main_account→account_id`、移除已不存在的 `available_seats` | + +### 🟡 轻微(可优化,不影响上线) + +| # | 问题 | 影响 | 建议方案 | +|---|------|------|----------| +| L1 | **广场拼车凭据录入状态未建模** | 个人拼车:用户付款后,车主需事后录入凭据,这段时间状态不明确 | `as_user_sub_member.status` 增加值:`4=等待车主录入凭据` | +| L2 | **缺少关键索引规划** | 高频查询无索引影响性能 | 见下方索引清单 | + +### 建议索引清单 + +```sql +-- 我的订阅列表 +CREATE INDEX idx_member_user_status ON as_user_sub_member(user_id, status); +-- 定时任务扫描到期 +CREATE INDEX idx_member_expire ON as_user_sub_member(expire_time, status); +-- 用户订单列表 +CREATE INDEX idx_order_user_status ON as_order(user_id, status); +-- 订单号查询(已设 UNIQUE,跳过) +-- 未读通知数 +CREATE INDEX idx_notif_user_read ON as_notification(user_id, is_read); +-- 合租槽状态 +CREATE INDEX idx_sub_product_status ON as_user_sub(product_id, status); +-- 账号凭据查询 +CREATE INDEX idx_account_product ON as_sub_account(product_id, status); +``` + +--- + +## 六、待决策项(需 Ami 确认) + +| # | 问题 | 选项 | +|---|------|------| +| 1 | 付费方式一期支持哪些? | A) 仅余额(人工充值)B) 余额+支付宝 C) 三种都支持 | +| 2 | 拼车广场是否需要审核流程? | A) 管理员审核 B) 自动上架 C) 仅自营,无拼车广场 | +| 3 | 账号凭据展示方式? | A) 直接明文 B) 需二次验证(短信/密码)C) 限时展示(30s后隐藏)| +| 4 | 邀请返现比例和条件? | 需定义:返现金额/比例,是否有上限 | +| 5 | `as_sub_product` 的多计划关联是否改为关联表? | A) 保持逗号分隔 B) 改关联表(**推荐**,趁现在改成本最低)| +| 6 | 提现功能是否一期上线? | A) 一期上 B) 二期(一期只充值不提现)| + +--- + +*文档由 AI 评审生成 · 最后更新:2026-02-17*