4.2 KiB
4.2 KiB
新项目 PRD(多租户 + 微信登录/分享 + 余额支付)
1. 范围与约束
1.1 多租户(从第一天开始)
- 所有站点与 API 都在路径前缀下:
/t/:tenant_code/... tenant_code规则:不区分大小写,允许字符集a-z0-9_-- 系统内部以
tenant_uuid(UUID)作为租户在 OSS 的存储分区标识- OSS Key:
quyun/<tenant_uuid>/<md5>.<ext>
- OSS Key:
- 数据隔离:所有业务表均包含
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 存在且启用
- code 正则:
- 解析成功后,将
tenant_id、tenant_uuid注入到请求上下文
4.2 微信登录
- 未登录请求 API → 401(XHR)或 302 →
/t/:tenant/v1/auth/wechat?redirect=... /auth/wechat生成微信授权地址(回调到/t/:tenant/v1/auth/login并透传 redirect)/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 扩展)