127 lines
4.2 KiB
Markdown
127 lines
4.2 KiB
Markdown
# 新项目 PRD(多租户 + 微信登录/分享 + 余额支付)
|
||
|
||
## 1. 范围与约束
|
||
|
||
### 1.1 多租户(从第一天开始)
|
||
|
||
- 所有站点与 API 都在路径前缀下:`/t/:tenant_code/...`
|
||
- `tenant_code` 规则:不区分大小写,允许字符集 `a-z0-9_-`
|
||
- 系统内部以 `tenant_uuid`(UUID)作为租户在 OSS 的存储分区标识
|
||
- OSS Key:`quyun/<tenant_uuid>/<md5>.<ext>`
|
||
- 数据隔离:所有业务表均包含 `tenant_id`,所有查询必须带 `tenant_id` 过滤
|
||
|
||
### 1.2 微信能力
|
||
|
||
- 保留:微信网页授权登录(OAuth)、JS-SDK 签名与分享
|
||
- 移除:微信支付/退款/回调(多租户版本完全不支持,历史也不兼容)
|
||
|
||
### 1.3 支付能力
|
||
|
||
- 仅支持:余额支付(单位:分),后台可充值余额
|
||
- 可退款:仅余额订单(退款 = 返还余额 + 撤销授权)
|
||
|
||
### 1.4 技术栈约束
|
||
|
||
- 后端开发语言:Golang(Go)
|
||
- 前端技术栈:Vue 3 + Vite
|
||
- UI 组件库(推荐):PrimeVue(配合 TailwindCSS,性能较好且扩展/主题定制能力强)
|
||
|
||
---
|
||
|
||
## 2. 角色与端
|
||
|
||
### 2.1 WeChat H5 端(C 端用户)
|
||
|
||
- 访问曲谱列表、搜索
|
||
- 查看曲谱详情
|
||
- 播放:未购买只能播放“预览版(short=true)”,已购买播放“完整版(short=false)”
|
||
- 余额购买
|
||
- 查看已购列表(快速播放)
|
||
- 查看个人资料与余额
|
||
- 分享(JS-SDK)
|
||
|
||
### 2.2 Admin 管理端(租户运营人员)
|
||
|
||
- 登录(租户维度账号)
|
||
- 仪表盘统计
|
||
- 媒体库管理:上传(预签名)、列表、预览、删除
|
||
- 曲谱管理:创建/编辑/发布/草稿、绑定媒体资源、设置封面(≤3)
|
||
- 用户管理:列表、详情、查看已购、给用户充值余额
|
||
- 订单管理:列表、退款(余额订单)
|
||
- 运营操作:赠送曲谱给指定用户
|
||
|
||
---
|
||
|
||
## 3. 核心业务对象
|
||
|
||
### 3.1 曲谱(Post)
|
||
|
||
- 字段:标题、简介、正文、价格(分)、折扣(0~100)、状态(draft/published)
|
||
- 关联媒体:
|
||
- `head_images`:封面媒体 ID 列表(≤3)
|
||
- `assets`:媒体资产数组(见 MediaAsset),包含视频/音频/文件等
|
||
|
||
### 3.2 媒体(Media)
|
||
|
||
- 字段:name、mime_type、size、hash(md5)、path(OSS key)、metas
|
||
- metas:`short`(是否预览资源)、`duration`、`parent_hash`
|
||
- hash 去重:在租户维度内去重(同租户相同 md5 视为同一资源)
|
||
|
||
### 3.3 授权(UserPosts)
|
||
|
||
- 记录用户购买/赠送后获得的曲谱访问权
|
||
- 唯一约束:同一租户同一用户同一曲谱只能有一条
|
||
|
||
### 3.4 订单(Order)
|
||
|
||
- 仅余额订单:`payment_method = balance`
|
||
- 状态:`pending/completed/refund_success/cancelled`(具体枚举在技术规格中确定)
|
||
|
||
---
|
||
|
||
## 4. 关键流程
|
||
|
||
### 4.1 租户识别
|
||
|
||
- 进入任意页面时,根据 URL 中的 `:tenant_code` 识别租户
|
||
- 服务端需校验:
|
||
- code 正则:`^[a-z0-9_-]+$`(不区分大小写)
|
||
- code 存在且启用
|
||
- 解析成功后,将 `tenant_id`、`tenant_uuid` 注入到请求上下文
|
||
|
||
### 4.2 微信登录
|
||
|
||
1) 未登录请求 API → 401(XHR)或 302 → `/t/:tenant/v1/auth/wechat?redirect=...`
|
||
2) `/auth/wechat` 生成微信授权地址(回调到 `/t/:tenant/v1/auth/login` 并透传 redirect)
|
||
3) `/auth/login` 换取 openid + 用户信息,按 `(tenant_id, open_id)` 获取或创建用户,签发会话 token(cookie)
|
||
|
||
### 4.3 播放策略(预览/完整版)
|
||
|
||
- assets 中选择 `type == "video/mp4"` 的资源:
|
||
- 未购买:选择 `metas.short == true`
|
||
- 已购买:选择 `metas.short == false`
|
||
- 媒体 URL 通过 OSS 预签名下发
|
||
|
||
### 4.4 余额购买与授权
|
||
|
||
- 下单:创建订单 `pending`
|
||
- 校验余额足够:
|
||
- 足够:扣减余额 → 订单 `completed` → 写入 `user_posts`
|
||
- 不足:返回业务错误(提示联系管理员充值)
|
||
|
||
### 4.5 余额退款
|
||
|
||
- 仅允许对 `completed + payment_method=balance` 的订单退款
|
||
- 退款动作:
|
||
- 返还余额
|
||
- 删除/撤销 `user_posts` 授权
|
||
- 订单标记为 `refund_success`
|
||
|
||
---
|
||
|
||
## 5. 非功能性要求(简版)
|
||
|
||
- 所有写操作必须带租户隔离与鉴权校验
|
||
- 关键唯一约束在 DB 层实现(避免并发重复授权/重复订单号)
|
||
- 租户 UUID 由业务代码生成并写入(不依赖 DB 扩展)
|