feat: add Phase D - system design (functions + business flows + DB design)

This commit is contained in:
阿米狗
2026-02-17 19:29:09 +08:00
parent 690c900f81
commit d6af71ec14

371
SYSTEM_DESIGN.md Normal file
View File

@@ -0,0 +1,371 @@
# iShare 系统设计文档
> 优先级:最高(先于所有开发任务)
> 版本v1.0
> 日期2026-02-17
---
## 一、系统角色
| 角色 | 说明 |
|------|------|
| **普通用户** | 注册登录,购买合租商品,获取账号凭据 |
| **车主(发布者)** | 发布自己的合租位(个人拼车广场) |
| **平台运营(管理员)** | 管理平台数据、自营商品、用户、订单 |
| **超级管理员** | 全局配置,含财务、权限管理 |
---
## 二、功能模块清单
### 2.1 用户端 H5 功能
| 模块 | 功能点 |
|------|--------|
| **账号** | 手机号注册/登录、邮箱注册/登录、找回密码(验证码)、微信/社交登录(二期) |
| **首页** | 平台分类Tab、推荐商品卡片、Banner 广告位、热门合租榜 |
| **商品列表** | 按平台类型筛选、按价格/评分排序、关键词搜索 |
| **商品详情** | 平台介绍、套餐选择(月/季/年)、评价列表、剩余席位数、立即购买 |
| **购买流程** | 选套餐 → 确认订单 → 支付(余额/在线支付)→ 获取账号凭据 |
| **我的订阅** | 当前有效订阅列表、账号凭据查看、续费、退订 |
| **广场/拼车** | 浏览他人发起的合租位、申请加入、发起自己的合租 |
| **推广中心** | 邀请码、邀请记录、返现奖励记录 |
| **钱包** | 余额查看、充值、提现(二期)、流水记录 |
| **通知** | 续费提醒、订单状态变更、系统公告 |
| **个人中心** | 基本信息编辑、头像、安全设置(改密)、退出登录 |
### 2.2 管理后台功能
| 模块 | 功能点 |
|------|--------|
| **平台管理** | 平台CRUD、平台分类CRUD、图标上传 |
| **订阅计划管理** | 计划CRUD、付费方案CRUD多地区/多货币) |
| **自营商品管理** | 商品CRUD、上下架、库存账号管理、绑定账号凭据 |
| **订单管理** | 订单列表、状态查看、人工审核、退款处理 |
| **用户管理** | 用户列表、封禁/解封、余额调整、查看订阅记录 |
| **评价管理** | 评价列表、违规删除 |
| **财务管理** | 收入统计、提现申请审核(二期)、优惠券管理(二期) |
| **通知配置** | 系统通知模板、续费提醒开关 |
| **系统配置** | 站点信息、支付配置、短信/邮件配置 |
---
## 三、核心业务流程
### 3.1 用户注册/登录
```
[用户] → 输入手机/邮箱
→ 获取验证码(短信/邮件)
→ 验证 → 首次登录自动注册 app_user
→ 生成 JWT Token复用 pigx-auth
→ 进入首页
```
### 3.2 购买合租商品(核心流程)
```
[用户] → 浏览商品列表as_sub_product, status=上架)
→ 商品详情页
├── 查看剩余席位 = capacity - capacity_loaded来自 as_user_sub 聚合)
└── 选择付费方案as_sub_payroll
→ 点击"立即购买"
→ 创建订单as_order, status=待支付)
→ 支付
├── 余额支付 → 扣减 as_wallet.balance
└── 在线支付 → 支付宝/微信回调 → 更新订单状态
→ 支付成功
├── 订单状态 → 已支付 → 使用中
├── 创建 as_user_sub 记录capacity_loaded +1
├── 返回账号凭据as_sub_account 解密后展示)
└── 推送通知(订阅成功)
```
### 3.3 账号凭据查看
```
[用户] → "我的订阅" → 选择订阅
→ 验证身份(二次密码/生物识别,可选)
→ 从 as_sub_account 查询 account_name + account_passwd
→ AES 解密 account_passwd服务端解密不返回明文密钥
→ 展示账号密码(可设置自动隐藏倒计时)
```
### 3.4 订阅到期/续费
```
[定时任务(每日凌晨)]
→ 扫描 as_user_sub.expire_time < now() + 7天
→ 发送续费提醒通知as_notification
→ 到期当日as_user_sub.status = expired
→ capacity_loaded -1释放席位
[用户续费]
→ 进入"我的订阅" → 点击续费
→ 选择续费套餐 → 走购买流程(复用)
→ 续费成功as_user_sub.expire_time 延长
```
### 3.5 广场拼车(个人发布)
```
[车主]
→ 填写合租信息(平台、计划、价格、总席位数、说明)
→ 创建 as_sub_productproduct_type=2 个人)
→ 提交审核 → 管理员审核通过 → 上架status=active
[拼车者]
→ 广场浏览 → 找到心仪的拼车
→ 申请加入 → 走购买流程
→ 成功后 → 车主将账号凭据录入 as_sub_account
→ 拼车者可查看凭据
```
### 3.6 推广/邀请
```
[用户A] → 分享邀请码/链接
[用户B] → 点击链接注册
→ as_invite 记录inviter=A, invitee=B
[用户B首次购买成功]
→ 触发返现奖励
→ as_wallet_log 记录用户A 获得返现)
→ as_wallet.balance 增加
```
---
## 四、数据库设计(完整版)
### 4.1 现有表评审与修订
#### ⚠️ 现有设计问题
| 表 | 问题 | 修订方案 |
|----|------|----------|
| `as_sub_account` | `passwd_salt` 是 int不够安全缺加密字段标记 | 改为 varchar salt`encrypt_type` 字段 |
| `as_sub_account` | 缺 `status` 字段(账号可能失效/被封) | 加 `status`: 0=正常,1=失效,2=异常 |
| `as_user_sub` | 缺 `status``start_time``expire_time` | 补充状态和时间字段 |
| `as_user_sub` | `remark` 字段类型是 int应为 varchar | 改为 varchar |
| `as_sub_product` | 缺 `status`(上架/下架/售完)、`available_seats` | 补充状态和实时剩余席位 |
| `as_sub_product` | `sub_plan_ids` 用逗号分隔(反范式) | 评估是否改为关联表(影响查询) |
| `as_sub_payroll` | 缺促销价/折扣字段 | 加 `original_price``discount_rate` |
| `as_platform_type` | `platform_type` 是 int0=全部 含义混乱 | 改用独立 sort_order + is_all 标志位 |
### 4.2 核心业务表(完整版)
#### 保留现有(修订后)
- `as_platform`
- `as_platform_type`
- `as_sub_plan`
- `as_sub_payroll`(加 original_price, discount_rate
- `as_sub_account`(加 status, encrypt_type, 改 passwd_salt 为 varchar
- `as_sub_product`(加 status, available_seats
- `as_sub_product_comment`
- `as_user_sub`(加 status, start_time, expire_time, 改 remark 为 varchar
#### 新增表
---
### `as_order` — 订单表
| 字段 | 类型 | 说明 |
|------|------|------|
| `id` | bigint PK | 订单ID |
| `order_no` | varchar(32) | 订单号(唯一,业务用) |
| `user_id` | bigint | 购买用户 |
| `product_id` | bigint | 商品ID (as_sub_product) |
| `payroll_id` | bigint | 付费方案ID (as_sub_payroll) |
| `amount` | decimal(10,2) | 实付金额 |
| `original_amount` | decimal(10,2) | 原价 |
| `discount_amount` | decimal(10,2) | 优惠金额 |
| `pay_type` | tinyint | 支付方式: 1=余额, 2=支付宝, 3=微信 |
| `pay_no` | varchar(64) | 第三方支付单号 |
| `status` | tinyint | 0=待支付, 1=已支付, 2=已完成, 3=已退款, 4=已取消 |
| `user_sub_id` | bigint | 关联的用户订阅ID (创建后填充) |
| `remark` | varchar | 备注 |
| `expire_time` | datetime | 订单过期时间(未支付自动取消) |
| `pay_time` | datetime | 支付时间 |
| `create_time` | datetime | |
| `update_time` | datetime | |
---
### `as_wallet` — 用户钱包
| 字段 | 类型 | 说明 |
|------|------|------|
| `id` | bigint PK | |
| `user_id` | bigint UNIQUE | 用户ID一人一钱包 |
| `balance` | decimal(10,2) | 可用余额 |
| `frozen_amount` | decimal(10,2) | 冻结金额(待退款/提现) |
| `total_income` | decimal(10,2) | 累计收入 |
| `total_expense` | decimal(10,2) | 累计支出 |
| `create_time` | datetime | |
| `update_time` | datetime | |
---
### `as_wallet_log` — 钱包流水
| 字段 | 类型 | 说明 |
|------|------|------|
| `id` | bigint PK | |
| `user_id` | bigint | 用户ID |
| `amount` | decimal(10,2) | 金额(正=收入,负=支出) |
| `type` | tinyint | 1=充值, 2=消费, 3=退款, 4=邀请返现, 5=提现 |
| `order_id` | bigint | 关联订单ID可空 |
| `balance_after` | decimal(10,2) | 操作后余额(快照) |
| `remark` | varchar | 说明(如"订阅 Netflix 高级版" |
| `create_time` | datetime | |
---
### `as_invite` — 邀请关系
| 字段 | 类型 | 说明 |
|------|------|------|
| `id` | bigint PK | |
| `inviter_id` | bigint | 邀请人用户ID |
| `invitee_id` | bigint | 被邀请人用户ID |
| `invite_code` | varchar(16) | 使用的邀请码 |
| `reward_amount` | decimal(10,2) | 返现金额 |
| `reward_status` | tinyint | 0=待发放, 1=已发放(首次购买后触发) |
| `create_time` | datetime | |
| `reward_time` | datetime | 返现时间 |
---
### `as_notification` — 通知消息
| 字段 | 类型 | 说明 |
|------|------|------|
| `id` | bigint PK | |
| `user_id` | bigint | 目标用户ID0=全部用户) |
| `title` | varchar | 通知标题 |
| `content` | varchar | 通知内容 |
| `type` | tinyint | 1=续费提醒, 2=订单通知, 3=系统公告, 4=邀请奖励 |
| `ref_id` | bigint | 关联业务ID如订单ID、订阅ID |
| `is_read` | tinyint | 0=未读, 1=已读 |
| `create_time` | datetime | |
---
### `app_user` 字段补充
在现有 PigX 的 `app_user` 表上补充以下字段via ALTER
| 字段 | 类型 | 说明 |
|------|------|------|
| `invite_code` | varchar(16) UNIQUE | 用户的专属邀请码(注册时生成) |
| `inviter_id` | bigint | 邀请人用户ID注册时记录 |
---
### 4.3 完整 ER 关系图
```
as_platform_type (1) ──< (N) as_platform [platform_type]
as_platform (1) ──< (N) as_sub_plan [platform_id]
as_sub_plan (1) ──< (N) as_sub_payroll [sub_plans]
as_sub_plan (N) >──< (N) as_sub_product [sub_plan_ids]
as_sub_product (1) ──< (N) as_sub_product_comment [product_id]
as_sub_product (1) ──< (N) as_sub_account [product_id]
as_sub_plan (1) ──< (N) as_sub_account [sub_plan_id]
as_sub_payroll (1) ──< (N) as_sub_account [sub_payroll_id]
as_sub_product (1) ──< (N) as_order [product_id]
as_sub_payroll (1) ──< (N) as_order [payroll_id]
as_order (1) ──< (1) as_user_sub [user_sub_id]
as_sub_plan (1) ──< (N) as_user_sub [plan_id]
as_sub_account (1) ──< (N) as_user_sub [main_account]
app_user (1) ──< (1) as_wallet [user_id]
as_wallet (1) ──< (N) as_wallet_log [user_id]
as_order (1) ──< (N) as_wallet_log [order_id]
app_user (1) ──< (N) as_order [user_id]
app_user (1) ──< (N) as_user_sub [user_id]
app_user (1) ──< (N) as_sub_product [user_id — 发布者]
app_user (1) ──< (N) as_sub_account [user_id — 账号持有者]
app_user (1) ──< (N) as_sub_product_comment [user_id]
app_user (1) ──< (N) as_notification [user_id]
app_user (1) ──< (N) as_invite [as inviter] [inviter_id]
app_user (1) ──< (1) as_invite [as invitee] [invitee_id]
```
### 4.4 `as_user_sub` 状态机
```
购买成功
[pending] ──────→ [active] ──→ 到期 ──→ [expired]
│ │
│ 退款/申请退订 │ 续费
↓ ↓
[cancelled] [active]
```
状态值0=待激活, 1=使用中, 2=已到期, 3=已退订
### 4.5 `as_order` 状态机
```
[pending] → 15分钟未支付 → [cancelled]
[pending] → 支付成功 → [paid] → 激活订阅成功 → [completed]
[paid/completed] → 退款申请 → 审核通过 → [refunded]
```
---
## 五、接口设计要点
### 5.1 账号凭据安全
- `account_passwd` 使用 **AES-256-GCM** 加密存储
- 密钥由服务端持有(存配置中心/环境变量),不入库
- `passwd_salt` 用于 AES 的 IV改为 varchar(32)16字节随机
- 凭据查看接口:仅限订阅状态为 `active` 的用户,且需校验 `as_user_sub.user_id == currentUser`
- 返回解密后的明文,但 **不记录日志**(防止泄露)
### 5.2 席位并发控制
- 购买时使用 **数据库乐观锁****Redis 分布式锁** 防止超卖
- `as_sub_product.available_seats` 在下单时 -1乐观锁 version 字段)
- 订单取消/超时后 +1 回补
### 5.3 价格一致性
- 订单金额在创建时 **快照**`as_order.amount`
- 不依赖付费方案的实时价格(防止价格变动导致差异)
---
## 六、设计待决策项(需 Ami 确认)
| # | 问题 | 选项 |
|---|------|------|
| 1 | 付费方式一期支持哪些? | A) 仅余额人工充值B) 余额+支付宝 C) 三种都支持 |
| 2 | 拼车广场是否需要审核流程? | A) 管理员审核 B) 自动上架 C) 仅自营,无拼车广场 |
| 3 | 账号凭据展示方式? | A) 直接明文 B) 需二次验证(短信/密码C) 限时展示30s后隐藏|
| 4 | 邀请返现比例和条件? | 需定义:返现金额/比例,是否有上限 |
| 5 | `as_sub_product` 的多计划关联是否改为关联表? | A) 保持逗号分隔简单B) 改关联表(规范,便于查询)|
| 6 | 提现功能是否一期上线? | A) 一期上 B) 二期(一期只充值不提现)|
---
## 七、调整后的项目阶段
| 阶段 | 内容 | 时间 |
|------|------|------|
| **Phase D当前·最高优先** | 系统设计:功能清单 + 业务流程 + 数据库设计 | 进行中 |
| **Phase 0** | 环境搭建:仓库 + Fork PigX + CI/CD + 建库 SQL | D 完成后 |
| **Phase 1** | 后端核心 CRUD API | 1-2周 |
| **Phase 2** | 管理后台前端 | 1周 |
| **Phase 3** | 用户端 H5 | 2-3周 |
| **Phase 4** | 支付集成 | 按需 |
| **Phase 5** | 测试 + 上线 | — |