1135 lines
58 KiB
Markdown
1135 lines
58 KiB
Markdown
# 短视频应用开发文档
|
||
|
||
- 版本:v1.0
|
||
- 日期:2026-10-14
|
||
- 适用端:Flutter App(iOS / Android)、Python 后端
|
||
|
||
---
|
||
|
||
## 1. 项目介绍
|
||
|
||
### 1.1 项目概述
|
||
|
||
一款竖屏沉浸式短视频应用(产品形态参考抖音/快手)。核心商业模式为:
|
||
|
||
**免费额度 + 积分付费观看 + 会员订阅**
|
||
|
||
- 所有用户(含游客)每天可免费观看 10 个视频
|
||
- 超出免费额度后,注册用户每观看 1 个视频消耗 1 积分,游客需注册/登录
|
||
- 积分通过充值获得(支付宝 / 微信 / USDT),**1 元 = 10 积分**
|
||
- 积分可开通会员,会员享有**无限观看**和**优先上传**权益
|
||
- 用户可通过评论赚取积分(每评论 10 个视频奖励 1 积分),形成内容互动激励闭环
|
||
|
||
### 1.2 项目组成
|
||
|
||
```
|
||
video/ # 项目根目录(当前目录)
|
||
├── app/ # Flutter 手机端(前端)
|
||
├── server/ # Python 后端服务
|
||
├── admin/ # 管理后台 Web(Vue3,一期包含)
|
||
└── docs/ # 项目文档
|
||
```
|
||
|
||
### 1.3 名词定义
|
||
|
||
| 名词 | 定义 |
|
||
|---|---|
|
||
| 游客 | 未注册/未登录用户,以设备 ID(device_id)标识 |
|
||
| 注册用户 | 通过手机号或邮箱注册并登录的用户 |
|
||
| 会员 | 开通体验/月卡/年卡/终身卡且在有效期内的注册用户 |
|
||
| 积分 | 平台虚拟货币,1 元 = 10 积分,用于观看扣费、开通会员 |
|
||
| 免费额度 | 每个计费主体(游客=设备,注册用户=账号)每天可免费观看的视频数,默认 10 个 |
|
||
| 计费主体 | 观看计费的统计单位:注册用户为 user_id,游客为 device_id |
|
||
| 资产 | 创作者激励体系的虚拟货币,**10 资产 = 1 元**,存放于资产钱包,可提现 |
|
||
| 推荐人/被推荐人 | 通过邀请码绑定的邀请关系双方;推荐人须为会员方可获得奖励 |
|
||
|
||
---
|
||
|
||
## 2. 功能介绍
|
||
|
||
### 2.1 用户模块
|
||
|
||
#### 2.1.1 游客模式
|
||
- 无需注册登录,打开 App 即可观看视频
|
||
- App 首次启动生成唯一 device_id 并本地持久化,之后所有请求携带 `X-Device-ID` 头
|
||
- 游客每天可免费观看 10 个视频,第 11 个视频弹出登录/注册引导
|
||
- 游客不可点赞、收藏、评论、上传
|
||
|
||
#### 2.1.2 注册
|
||
- 注册页**手机号 / 邮箱 Tab 切换**:手机号 + 短信验证码 + 密码,或 邮箱 + 邮箱验证码 + 密码
|
||
- 邮箱验证码由服务端**真实 SMTP 发送**(`POST /auth/email/send`),验证码写 Redis(`email:code:{email}`,600s),与短信验证码同一套校验机制
|
||
- 注册即登录,返回 Token
|
||
- 约束:手机号/邮箱全局唯一;密码 ≥ 8 位,含字母和数字
|
||
|
||
#### 2.1.3 登录
|
||
- 支持**手机号或邮箱**作为账号:手机号 + 密码 / 手机号 + 短信验证码 / 邮箱 + 密码
|
||
- 登录成功后,游客时期的设备 ID 与账号可关联(观看记录合并,可选)
|
||
|
||
#### 2.1.4 资料管理
|
||
- 昵称(默认"用户+尾号")、头像、性别、个人简介
|
||
- 修改手机号/邮箱需验证码验证
|
||
|
||
#### 2.1.5 找回密码与账号注销
|
||
- **找回密码**:已验证的手机号/邮箱 + 验证码 + 新密码完成重置(`POST /auth/password/reset`),重置后旧 Token 全部失效
|
||
- **账号注销**:用户主动发起 → 7 天冻结期(期间登录即撤销)→ 到期匿名化:手机号/邮箱置空释放、昵称头像清空、作品全部下架、钱包余额清零作废、Token 立即失效
|
||
|
||
### 2.2 观看与计费模块(核心业务)
|
||
|
||
#### 2.2.1 计费规则
|
||
1. 会员:观看不限量,不消耗免费额度与积分
|
||
2. 非会员(含游客):每个计费主体每天前 10 个不同视频免费
|
||
3. 免费额度用完后:注册用户每看 1 个视频扣 1 积分;游客拦截并引导登录
|
||
4. 所有"每日"口径均按 Asia/Shanghai(服务器时区)0 点切分
|
||
5. 积分余额不足:拦截播放,引导充值或开通会员
|
||
|
||
#### 2.2.2 计费判定流程
|
||
|
||
```
|
||
用户开始播放视频
|
||
│
|
||
▼
|
||
App 调用「观看上报」接口
|
||
│
|
||
▼
|
||
是否会员? ──是──► 直接放行
|
||
│否
|
||
▼
|
||
该视频今天看过? ──是──► 直接放行(同日去重,不重复扣费)
|
||
│否
|
||
▼
|
||
今日免费额度未用完? ──是──► 占用 1 次免费额度,放行
|
||
│否
|
||
▼
|
||
是游客? ──是──► 返回"需登录",App 弹登录引导
|
||
│否
|
||
▼
|
||
积分 ≥ 1? ──是──► 扣 1 积分(写积分流水),放行
|
||
│否
|
||
▼
|
||
返回"积分不足",App 引导充值/开会员
|
||
```
|
||
|
||
#### 2.2.3 补充规则(对需求的完善)
|
||
- **同日去重**:同一视频当天重复观看,不重复占用免费额度、不重复扣积分
|
||
- **自己的视频免费**:观看自己上传的视频不计费、不占额度
|
||
- **扣费时点**:开始播放即扣费(播放页加载完成上报),简单可解释;退款场景(视频违规下架)通过后台人工处理
|
||
- **额度重置**:每日 00:00(服务器时区)重置,免费额度不可累积
|
||
- **观看记录**:所有观看(免费/扣费)均记录,用于历史列表与风控分析
|
||
|
||
### 2.3 积分模块
|
||
|
||
#### 2.3.1 积分获取
|
||
| 途径 | 规则 |
|
||
|---|---|
|
||
| 充值 | 支付宝/微信/USDT 支付成功到账,1 元 = 10 积分 |
|
||
| 评论奖励 | 每评论满 10 个**不同**视频,奖励 1 积分(循环累计,进度清零重新计) |
|
||
| 推荐奖励 | 会员邀请的新用户激活后,推荐人获 N 积分(默认 10,可配置),见 2.8 |
|
||
| 活动赠送 | 后台手动发放(含体验会员赠送活动) |
|
||
|
||
#### 2.3.2 积分消耗
|
||
| 场景 | 规则 |
|
||
|---|---|
|
||
| 观看视频 | 免费额度用完后,1 积分/个 |
|
||
| 开通会员 | 按套餐价扣减(见 2.4) |
|
||
|
||
#### 2.3.3 评论奖励防刷规则(完善项)
|
||
- 评论内容长度 ≥ 5 字才计入进度
|
||
- 同一视频仅**首次**有效评论计入进度
|
||
- 评论被删除(自删/违规)时,已计入的进度回退;已发放奖励的扣回(余额可为负,后续充值抵扣)
|
||
- 每日评论奖励上限 5 积分(可配置)
|
||
- 同一用户短时间高频评论触发限流(如 10 条/分钟)
|
||
|
||
#### 2.3.4 积分流水
|
||
- 所有积分变动必须写入积分流水表(变动值、变动后余额、业务类型、关联单据)
|
||
- 流水是积分对账、客服处理、风控审计的唯一依据
|
||
|
||
### 2.4 会员模块
|
||
|
||
#### 2.4.1 会员类型(价格/时长均可在配置文件中修改)
|
||
|
||
| 类型 | 时长 | 价格(积分) | 获取方式 |
|
||
|---|---|---|---|
|
||
| 体验会员 | 1 天 | 默认 5 积分(可配置) | 活动赠送 / 积分开通 |
|
||
| 月卡 | 30 天 | 300 | 积分开通 |
|
||
| 年卡 | 365 天 | 3650 | 积分开通 |
|
||
| 终身卡 | 永久 | 10000 | 积分开通 |
|
||
|
||
> 注:按 1 元 = 10 积分折算,即月卡=30 元、年卡=365 元、终身卡=1000 元。各套餐时长与价格均为默认值,可在配置文件中调整。
|
||
|
||
#### 2.4.2 会员权益
|
||
1. **无限观看**:不消耗免费额度和积分
|
||
2. **优先上传**:转码队列优先、审核队列优先
|
||
|
||
#### 2.4.3 会员规则(完善项)
|
||
- 必须注册登录才能开通和使用会员
|
||
- 有效期内重复开通:有效期**叠加**(如月卡剩余 10 天再开月卡 → 40 天)
|
||
- 已是终身卡:不可再开通其它套餐(前端置灰)
|
||
- 体验会员与付费卡互斥逻辑:体验会员期间开通付费卡,按付费卡生效(体验剩余时间不累加,避免活动滥用)
|
||
- 到期自动失效,不自动续费(当前无连续包月需求)
|
||
- **新注册赠送**:新用户注册成功即赠送体验会员(默认 1 天),管理后台可配置开关与天数(system_configs:`register_gift_trial.enabled` / `register_gift_trial.days`),关闭后注册不再赠送,实时生效
|
||
|
||
### 2.5 视频模块
|
||
|
||
#### 2.5.1 视频上传
|
||
- 主流程:App 选择本地视频(mp4 等)→ 上传至服务端/对象存储 → 服务端 **FFmpeg 转码为 HLS(m3u8 + ts 分片)** → 生成封面 → 提交审核 → 发布
|
||
- 兼容流程:也支持直接上传已转码好的 m3u8 + ts 文件包(服务端校验分片完整性后直接进入审核)
|
||
- 上传限制:单文件 ≤ 500MB、时长 5 秒 ~ 10 分钟(可配置)
|
||
- 会员"优先上传":转码任务进入高优先级队列,优先被消费
|
||
|
||
#### 2.5.2 视频转码
|
||
- 统一转 HLS:1080p 源 → 输出 720p(默认),可配置多码率(1080/720/480)自适应
|
||
- 从视频第 1 秒截取封面图
|
||
- 转码失败自动重试 3 次,仍失败则标记失败并通知作者
|
||
|
||
#### 2.5.3 视频审核
|
||
- 状态机:`转码中 → 待审核 → 已发布 / 审核拒绝 / 已下架`
|
||
- 一期采用**管理后台人工审核**:审核员在后台在线预览视频,执行 通过 / 拒绝(填写原因),通过后自动发布上架
|
||
- 仅"已发布"状态进入推荐流
|
||
|
||
#### 2.5.4 视频播放
|
||
- m3u8(HLS)流媒体播放,App 竖屏全屏沉浸式播放
|
||
- 上滑/下滑切换视频;**3 槽播放器池**预加载:当前页播放 + 下一页预缓冲,划走即 stop(断音 + 中断缓存下载)
|
||
- 切到"我的"等页面时播放器池**挂起(suspend)静音断流**,回到 Feed 且首页 Tab 可见才恢复(resume),修复"切页仍出声"问题
|
||
- 网络 m3u8 播放地址改写为 **App 内嵌本地媒体代理**(127.0.0.1 HTTP 服务):m3u8 每次回源保证签名时效,ts 分片落盘缓存(1GB LRU),支持拖动进度条(Range/206);ts 流量直连源站 CDN,不经过业务服务器
|
||
- 进度条拖动时显示**时间气泡**(x时xx分xx秒),标题后带**时长角标**
|
||
- 记录播放量(进入播放即 +1,Redis 计数异步落库)
|
||
|
||
#### 2.5.5 视频标签(Tag)
|
||
- 发布视频时可填写 0~5 个标签,每个标签 1~20 字(字母/数字/中文/下划线)
|
||
- 播放页在**标题后展示标签**(#标签 样式)
|
||
- 点击标签进入"标签视频列表页":展示该标签下全部已发布视频(支持 热度/最新 排序)
|
||
- 标签是推荐策略中个性化加权的主要特征
|
||
- 存量视频标签由**离线脚本批量生成**(server/scripts/build_tags_from_titles.py:jieba TF-IDF topK=6 + 番号/书名号提取 + 噪音过滤,幂等可重跑;已生成 2.2 万+ 标签、9.9 万+ 关联),后台提供"标签管理"页维护
|
||
|
||
#### 2.5.6 视频推荐策略
|
||
Feed 支持五种策略,客户端通过接口参数切换(App 顶部 Tab:推荐 / 最新 / 热度 / 口碑 / 热播,各策略独立保活分页状态):
|
||
|
||
| 策略 | 说明 |
|
||
|---|---|
|
||
| recommend(默认) | 个性化推荐 |
|
||
| latest | 最新发布倒序 |
|
||
| hot | 热度倒序:热度分 = (播放×1 + 点赞×5 + 评论×10) / (1 + 发布天数) |
|
||
| liked(口碑) | 按点赞量倒序 |
|
||
| viewed(热播) | 按播放量倒序 |
|
||
|
||
> liked / viewed 为纯数值排序,游标采用(值, id)双键避免同值翻页丢失。
|
||
|
||
**个性化推荐(recommend)规则:**
|
||
1. 候选池:全部"已发布"视频
|
||
2. 个性化打分:统计用户近 7 天观看/点赞/收藏视频的标签,得出偏好标签及权重,候选视频命中偏好标签加权;游客与无行为新用户退化为热度分
|
||
3. **每日重排**:以"当天日期 + 用户/设备"为随机种子对候选池确定性洗牌,保证**同一用户每天的推荐顺序都不一样**,且同一天内多次刷新顺序稳定(翻页不混乱)
|
||
4. **当日去重**:当天已观看过的视频**尽量不再出现**在推荐流中;候选池耗尽时放开过滤兜底,避免 Feed 刷空
|
||
|
||
#### 2.5.7 作品管理(作者)
|
||
- **编辑**:作者可修改自己视频的标题/描述/分类/标签,仅元信息变更,不影响已发布状态、不重新触发审核(视频文件不可替换)
|
||
- **删除**:作者可删除自己视频 → 软删除(status=5 已删除),立即从 Feed/搜索/标签页下架;播放/点赞等历史数据保留用于对账,资产结算即刻停止
|
||
- 两个操作仅作者本人可用(非作者返回 2107)
|
||
|
||
#### 2.5.8 搜索
|
||
- 一期:按标题、标签做关键词匹配(MySQL LIKE / FULLTEXT),支持 最新/热度 排序;二期接 Elasticsearch
|
||
- 热搜词:近 24h 搜索频次 Top10(Redis ZSet 统计,每小时截断)
|
||
- 搜索历史:App 端本地存储最近 10 条,不上报服务端
|
||
- 搜索词先过敏感词过滤,命中直接返回空结果
|
||
|
||
#### 2.5.9 视频下载(离线缓存)
|
||
- **入口**:Feed 页 / 播放页长按弹出菜单 →「下载」(已下载/下载中置灰)
|
||
- HLS 视频:4 并发下载 ts 分片与 AES-128 密钥,改写为本地 index.m3u8;mp4 整文件直接下载
|
||
- 下载过程展示进度,支持取消;失败自动清理半成品文件
|
||
- 下载列表在「我的 → 已下载」;离线播放走本地媒体代理,支持拖动进度条
|
||
- 已下载视频离线观看**不重复扣积分**(线上播放时已按正常规则计费)
|
||
|
||
### 2.6 互动模块
|
||
|
||
| 功能 | 规则 |
|
||
|---|---|
|
||
| 点赞 | 仅登录用户;同一视频重复点击为取消;视频表冗余 like_count;唯一约束防重 |
|
||
| 收藏 | 仅登录用户;同上;个人中心可查看收藏列表 |
|
||
| 评论 | 仅登录用户;支持一级评论和楼中楼回复(二级);作者可删除自己视频下的评论;评论计数入奖励进度 |
|
||
|
||
#### 2.6.4 消息通知
|
||
- 类型:审核结果(视频通过/拒绝)、提现进度(通过打款/拒绝退回)、系统公告、评论回复
|
||
- 触发即写 notifications 表,Redis 维护未读数;App 我的页消息入口带红点
|
||
- 通知为站内信,一期不做 App 推送(push 二期接厂商通道)
|
||
|
||
#### 2.6.5 举报
|
||
- 举报对象:视频、评论;原因分类:色情低俗/暴力血腥/侵权/广告营销/其他
|
||
- 同一用户对同一对象仅可举报一次(唯一约束,重复返回 2106)
|
||
- 后台处理动作:下架视频 / 删除评论 / 驳回;处理结果通过消息通知告知举报人
|
||
- 举报不自动处置内容,全部人工决策
|
||
|
||
#### 2.6.6 敏感词过滤
|
||
- 评论、昵称、视频标题/描述/标签、搜索词均先过敏感词库(DFA 算法),命中拒绝并返回 2105
|
||
- 词库由运营在管理后台维护(sensitive_words 表),服务端 Redis 缓存 60s
|
||
|
||
### 2.7 支付模块
|
||
|
||
#### 2.7.1 充值套餐(管理后台可在线调整)
|
||
- 默认档位:**10 / 30 / 100 / 200 元**,另开放**自定义金额**(1~10000 元)
|
||
- 到账规则:1 元 = 10 积分;档位可单独配置"赠送积分"(如充 100 元赠 50 积分)
|
||
- 档位存储于数据库 `recharge_packages` 表,**管理后台实时增删改、上下架、排序**,无需改配置、无需重启服务
|
||
|
||
#### 2.7.2 支付方式
|
||
| 方式 | 方案 | 说明 |
|
||
|---|---|---|
|
||
| 支付宝 | 支付宝开放平台 App 支付 | 服务端下单生成 orderString → App 调起 SDK → 异步回调到账 |
|
||
| 微信支付 | 微信支付 V3 App 支付 | 服务端下单 prepay → App 调起 SDK → 异步回调验签到账 |
|
||
| USDT | TRC20 链上收款 | 配置固定收款地址 + 汇率;订单生成"唯一金额"(如 30 USDT + 0.001~0.999 随机尾差),服务端轮询 TronGrid 匹配金额与时间窗,满 19 个确认后入账 |
|
||
|
||
#### 2.7.3 支付通用规则(完善项)
|
||
- 订单有效期 30 分钟,超时自动关闭
|
||
- 到账必须**幂等**:以第三方流水号/tx_hash 唯一约束防重复入账
|
||
- 到账在数据库事务内完成:更新订单状态 + 钱包加积分 + 写积分流水,三步原子
|
||
- 回调验签失败、金额不匹配一律拒绝并告警
|
||
- 所有支付参数(商户号、密钥、证书、USDT 地址/汇率)走配置文件/环境变量,不入库、不进代码仓库
|
||
|
||
#### 2.7.4 退款规则
|
||
- 发起:仅运营/客服在支付平台商户后台(支付宝/微信)人工发起退款;USDT 订单不支持自动退款(人工链上退回并线下登记)
|
||
- 系统处理(退款回调或后台人工登记后):
|
||
1. 订单状态置为 refunded
|
||
2. 扣回该订单已发放积分(余额**允许为负**,后续充值先抵扣负数;负余额用户禁止积分消费)
|
||
3. 扣回推荐人已获得的该笔充值返利资产(biz_type=6,资产允许为负)
|
||
- 退款不改变已发生的观看/会员事实(会员不回收,防止复杂对穿,运营层面约束)
|
||
|
||
### 2.8 推荐与创作者激励(资产体系)
|
||
|
||
平台在积分之外设有**资产钱包**:资产可提现,与人民币固定换算 **10 资产 = 1 元**(与积分同量纲,比例可配置)。所有资产变动写资产流水,变更规范与积分一致(行锁 + 流水 + 乐观锁)。
|
||
|
||
#### 2.8.1 推荐奖励(会员邀请新用户)
|
||
- 每位用户注册自动生成邀请码/邀请链接;**推荐人须为会员**才产生奖励(发放时点校验会员身份)
|
||
- 新用户注册时通过邀请码/分享口令/推广链接自动归因完成绑定(归因方案见 2.8.2),注册后 24h 内可补绑,每人仅能绑定 1 个推荐人
|
||
- 被推荐人"激活"(注册 72h 内累计观看 ≥3 个视频,且次日有登录)后,推荐人获得 **N 积分**(默认 10,可配置),**不限量**
|
||
- **充值返利**:被推荐人每次充值成功,推荐人获得"充值积分 × 5%"的**资产**(不限量,比例可配置);订单退款时对应返利扣回(资产余额允许为负,后续收益抵扣)
|
||
|
||
#### 2.8.2 推广归因(邀请链接 / 分享口令 / 模糊匹配)
|
||
|
||
用户通过推广链接下载 App,安装注册后自动识别推荐人。采用三段式自建归因方案(不依赖第三方 SDK):
|
||
|
||
| 优先级 | 路径 | 说明 |
|
||
|---|---|---|
|
||
| 1(主路径) | 分享口令 | 推广文案内含 `#短视频邀请码XXXXXXXX#` 口令,被邀请人复制后首次打开 App,客户端解析剪贴板 → 注册页自动预填邀请码,准确率 100% |
|
||
| 2(辅助路径) | H5 落地页点击埋点 + 模糊匹配 | 推广链接 `/r/{code}` 打开 H5 落地页时自动上报点击(code+IP+UA 存 Redis 24h);App 首启无口令时上报 device_id,服务端按 IP 就近匹配点击记录,命中结果按 device_id 服务端缓存(7 天),注册时自动带出 |
|
||
| 3(兜底) | 注册页手填邀请码 | 注册表单邀请码选填;注册后 24h 内还可在"邀请好友"页补绑(`/referral/bind`) |
|
||
|
||
- 归因结果**由服务端按 device_id 缓存并一次性消费**,不信任客户端回传,防止伪造归因
|
||
- 绑定优先级:显式 invite_code(口令/手填)> 模糊归因缓存;绑定沿用 2.8.3 全部风控规则
|
||
- 落地页展示邀请人昵称、复制口令按钮与 App 下载入口(下载地址由 system_configs `app.download_url` 驱动,后台可配)
|
||
|
||
#### 2.8.3 推荐防作弊规则
|
||
- 不可绑定自己;同 device_id 已存在账号的设备注册 → 绑定直接无效(防开小号)
|
||
- 注册 IP 与推荐人常用 IP 一致、或同 IP 24h 内注册 >5 个账号 → 标记风险
|
||
- 推荐人 24h 内新增绑定 >10 人 → 超出部分冻结
|
||
- 命中风控的绑定状态置为"风控冻结",奖励暂停发放,管理后台人工审核后可解冻或判无效
|
||
- 未激活的绑定不发放奖励;激活判定由定时任务执行
|
||
|
||
#### 2.8.4 会员视频创作收益
|
||
仅**会员**发布的视频参与资产结算(结算时点校验作者会员身份;非会员期间数据持续累计,成为会员后按增量结算):
|
||
|
||
| 收益项 | 规则 | 说明 |
|
||
|---|---|---|
|
||
| 完整观看收益 | 每累计 1000 次完整观看 → 1 资产 | 完整观看=播放进度 ≥95% 或看到结尾;同一用户/设备同视频每日最多计 1 次;作者本人不计 |
|
||
| 点赞收益 | 每累计 100 次点赞 → 1 资产 | 以累计新增点赞计数;取消点赞回退计数,但已结算发放的资产不扣回 |
|
||
|
||
- 结算由定时任务每 5 分钟按增量执行,按视频独立保留余数(如 2500 次完整观看 → 发 2 资产,余 500 继续累计)
|
||
|
||
#### 2.8.5 资产提现
|
||
- 满 100 资产(=10 元)可申请提现(门槛可配置)
|
||
- 渠道:支付宝 / 微信 / USDT;管理后台**人工审核**后打款
|
||
- 审核拒绝 → 资产原路退回资产钱包;同一时间仅允许一笔审核中的提现
|
||
|
||
### 2.9 管理后台(一期包含,Web 端)
|
||
|
||
独立 Web 管理后台,管理员账号体系与 App 用户完全隔离,分角色控制权限。
|
||
|
||
| 模块 | 功能 |
|
||
|---|---|
|
||
| 仪表盘 | 今日/累计:DAU、新增注册、充值金额、积分发放与消耗、播放量、待审核数 |
|
||
| 视频审核(人工) | 待审核列表(在线预览 m3u8)、通过、拒绝(必填原因)、已发布视频下架 |
|
||
| 用户管理 | 搜索(ID/手机号/邮箱)、用户详情(钱包/会员/作品/流水)、封禁与解封、**修改密码**(重置后 `auth:epoch` 递增,该用户全端 Token 立即失效) |
|
||
| 积分管理 | 用户积分流水查询、手动加/减积分(原因必填 + 二次确认,写流水 biz_type=6) |
|
||
| 订单管理 | 充值订单查询(状态/渠道/时间筛选)、异常订单人工补单(核实已收款后手动入账) |
|
||
| 提现审核 | 提现申请列表、审核通过(线下打款后确认)/ 拒绝(自动退回资产) |
|
||
| 推荐风控 | 推荐关系查询(状态/风控标记筛选)、冻结记录解冻或判无效 |
|
||
| 平台配置 | 注册赠送体验会员开关与天数等运营参数(system_configs 键值对,实时生效) |
|
||
| 充值套餐管理 | 档位与赠送积分增删改、上下架、排序,实时生效 |
|
||
| 活动运营 | 赠送体验会员/积分(支持单个或批量用户) |
|
||
| 标签管理 | 标签列表查询(关联视频数)、重命名、删除(联动清理 video_tags) |
|
||
| 采集源管理 | 采集源 CRUD(分类名 + 列表 URL 模板)、批量添加、单源/全部同步(后台异步采集外部单视频入库) |
|
||
| 管理员管理 | 管理员账号增删、角色分配(超级管理员/审核员/运营)、操作日志查询 |
|
||
|
||
角色权限:超级管理员(全部)、审核员(仅视频审核)、运营(套餐/活动/看板)。
|
||
|
||
### 2.10 二期规划清单
|
||
1. **关注/粉丝**:预留,二期开放
|
||
2. **App 推送**:厂商通道(评论回复、审核结果、提现进度等通知的 push)
|
||
3. **搜索升级**:Elasticsearch、搜索联想词
|
||
4. **分享**:视频分享链接/海报生成
|
||
5. **趋势看板**:管理后台 7/30 天数据曲线、订单导出 CSV
|
||
6. **黑名单**:用户拉黑、内容"不感兴趣"负反馈,深化个性化推荐
|
||
7. **游客数据合并**:注册后游客观看记录正式合并入账号
|
||
8. **实名认证提示**:充值环节按支付合规要求引导实名(依赖支付渠道商户资质)
|
||
9. **运维**:上传临时文件与拒绝视频分片的定时清理、SLO 指标(Feed <300ms、起播 <1.5s)、客户端埋点上报
|
||
|
||
### 2.11 合规提示
|
||
- 短视频平台运营涉及《网络文化经营许可证》《信息网络传播视听节目许可证》或备案要求,上架应用市场需提供对应资质,需提前规划
|
||
- 必须接内容审核,否则存在下架风险
|
||
- USDT 收款存在地区合规风险,请评估主体与运营地区法规
|
||
- **iOS 虚拟支付合规**:苹果要求 App 内虚拟商品(积分/会员)走 IAP,使用支付宝/微信支付存在拒审风险。对策:预留"iOS 支付开关"(system_configs:`ios_payment.enabled`),审核期/风险期切换为引导用户到 H5 网页端充值;安卓端不受限
|
||
- **注册协议**:注册页必须勾选《用户协议》与《隐私政策》后方可提交
|
||
|
||
---
|
||
|
||
## 3. 数据库设计
|
||
|
||
数据库选型:**MySQL 8.0**(InnoDB / utf8mb4),缓存与计数:**Redis 7**。
|
||
详细 DDL、索引策略见《02-技术文档》第 3 章,此处给出表结构定义。
|
||
|
||
### 3.1 表清单
|
||
|
||
现共 **30 张业务表**。Alembic 迁移链:`init_27_tables` → `add_collection_records` → `add_collection_sources`;线上数据量约 1.8 万视频。
|
||
|
||
| 表 | 说明 |
|
||
|---|---|
|
||
| users | 用户表 |
|
||
| user_wallets | 用户钱包(积分余额) |
|
||
| user_membership | 用户当前会员状态 |
|
||
| membership_orders | 会员开通记录 |
|
||
| videos | 视频表 |
|
||
| categories | 视频分类表 |
|
||
| comments | 评论表 |
|
||
| likes | 点赞表 |
|
||
| favorites | 收藏表 |
|
||
| watch_records | 观看记录表 |
|
||
| point_transactions | 积分流水表 |
|
||
| recharge_orders | 充值订单表 |
|
||
| transcode_tasks | 转码任务表 |
|
||
| tags | 标签表 |
|
||
| video_tags | 视频-标签关联表 |
|
||
| recharge_packages | 充值套餐表(后台可配) |
|
||
| admin_users | 管理员表 |
|
||
| admin_logs | 后台操作日志表 |
|
||
| referrals | 推荐关系表 |
|
||
| asset_wallets | 资产钱包表 |
|
||
| asset_transactions | 资产流水表 |
|
||
| withdrawals | 提现记录表 |
|
||
| video_earnings | 视频收益结算表 |
|
||
| notifications | 消息通知表 |
|
||
| reports | 举报表 |
|
||
| sensitive_words | 敏感词表 |
|
||
| series | 系列(合集)表:多条视频组织成集数列表 |
|
||
| collection_sources | 采集源配置表(分类名 + 列表 URL 模板) |
|
||
| collection_records | 采集记录表(外部内容源 → 本站系列/视频映射,幂等导入) |
|
||
|
||
### 3.2 用户域
|
||
|
||
#### users 用户表
|
||
| 字段 | 类型 | 说明 |
|
||
|---|---|---|
|
||
| id | BIGINT PK AUTO_INCREMENT | 用户 ID |
|
||
| phone | VARCHAR(20) NULL | 手机号,**唯一索引**,与 email 至少其一非空 |
|
||
| email | VARCHAR(100) NULL | 邮箱,**唯一索引** |
|
||
| password_hash | VARCHAR(255) | 密码哈希(bcrypt) |
|
||
| nickname | VARCHAR(50) | 昵称 |
|
||
| avatar_url | VARCHAR(500) | 头像 URL |
|
||
| gender | TINYINT DEFAULT 0 | 0未知 1男 2女 |
|
||
| bio | VARCHAR(200) | 简介 |
|
||
| status | TINYINT DEFAULT 1 | 1正常 2封禁 |
|
||
| register_type | TINYINT | 1手机 2邮箱 |
|
||
| invite_code | VARCHAR(10) | 我的邀请码,注册时自动生成,**唯一索引** |
|
||
| register_ip | VARCHAR(45) | 注册 IP(风控) |
|
||
| last_login_at | DATETIME NULL | 最近登录时间(推荐激活判定用) |
|
||
| last_login_ip | VARCHAR(45) | 最近登录 IP |
|
||
| created_at / updated_at | DATETIME | 创建/更新时间 |
|
||
|
||
索引:`uk_phone(phone)`、`uk_email(email)`、`uk_invite_code(invite_code)`、`idx_status_created(status, created_at)`
|
||
|
||
#### user_wallets 钱包表
|
||
| 字段 | 类型 | 说明 |
|
||
|---|---|---|
|
||
| user_id | BIGINT PK FK→users.id | 用户 ID |
|
||
| points | INT UNSIGNED DEFAULT 0 | 当前积分余额 |
|
||
| total_recharge | INT UNSIGNED DEFAULT 0 | 累计充值积分 |
|
||
| total_earned | INT UNSIGNED DEFAULT 0 | 累计奖励积分 |
|
||
| total_consumed | INT UNSIGNED DEFAULT 0 | 累计消耗积分 |
|
||
| version | INT DEFAULT 0 | 乐观锁版本号 |
|
||
| updated_at | DATETIME | 更新时间 |
|
||
|
||
> 余额变更必须走"行锁/乐观锁 + 流水",禁止直接 update 余额。
|
||
|
||
#### user_membership 当前会员状态表(冗余加速查询)
|
||
| 字段 | 类型 | 说明 |
|
||
|---|---|---|
|
||
| user_id | BIGINT PK FK | 用户 ID |
|
||
| is_member | TINYINT DEFAULT 0 | 是否会员(冗余,以 expire_at 判定为准) |
|
||
| current_plan | VARCHAR(20) | 当前套餐:trial/month/year/lifetime |
|
||
| is_lifetime | TINYINT DEFAULT 0 | 是否终身卡 |
|
||
| expire_at | DATETIME NULL | 到期时间(终身卡为 NULL) |
|
||
| updated_at | DATETIME | |
|
||
|
||
#### membership_orders 会员开通记录表
|
||
| 字段 | 类型 | 说明 |
|
||
|---|---|---|
|
||
| id | BIGINT PK | |
|
||
| order_no | VARCHAR(32) | 业务单号,**唯一索引** |
|
||
| user_id | BIGINT FK | |
|
||
| plan_code | VARCHAR(20) | trial/month/year/lifetime |
|
||
| points_cost | INT | 消耗积分(赠送为 0) |
|
||
| duration_days | INT | 时长(0=终身) |
|
||
| start_at / end_at | DATETIME | 生效/到期(终身 end_at 为 NULL) |
|
||
| source | TINYINT | 1积分购买 2活动赠送 |
|
||
| created_at | DATETIME | |
|
||
|
||
索引:`idx_user(user_id, created_at)`
|
||
|
||
### 3.3 视频域
|
||
|
||
#### videos 视频表
|
||
| 字段 | 类型 | 说明 |
|
||
|---|---|---|
|
||
| id | BIGINT PK | |
|
||
| user_id | BIGINT FK | 作者 |
|
||
| category_id | INT | 分类 |
|
||
| title | VARCHAR(100) | 标题 |
|
||
| description | VARCHAR(500) | 描述 |
|
||
| cover_url | VARCHAR(500) | 封面 URL |
|
||
| video_url | VARCHAR(500) | m3u8 播放地址 |
|
||
| duration | INT | 时长(秒) |
|
||
| file_size | BIGINT | 源文件大小 |
|
||
| width / height | INT | 分辨率 |
|
||
| status | TINYINT | 0转码中 1待审核 2已发布 3审核拒绝 4已下架 5转码失败 |
|
||
| reject_reason | VARCHAR(200) | 拒绝/下架原因 |
|
||
| reviewer_id | BIGINT NULL | 审核人(admin_users.id) |
|
||
| reviewed_at | DATETIME NULL | 审核时间 |
|
||
| is_priority | TINYINT DEFAULT 0 | 会员优先标记 |
|
||
| view_count | BIGINT DEFAULT 0 | 播放量 |
|
||
| like_count | INT DEFAULT 0 | 点赞数(冗余) |
|
||
| comment_count | INT DEFAULT 0 | 评论数(冗余) |
|
||
| favorite_count | INT DEFAULT 0 | 收藏数(冗余) |
|
||
| published_at | DATETIME NULL | 发布时间 |
|
||
| created_at / updated_at | DATETIME | |
|
||
|
||
索引:`idx_user_status(user_id, status)`、`idx_feed(status, published_at DESC)`、`idx_category(category_id, status)`
|
||
|
||
#### categories 分类表
|
||
| 字段 | 类型 | 说明 |
|
||
|---|---|---|
|
||
| id | INT PK | |
|
||
| name | VARCHAR(50) | 分类名 |
|
||
| sort | INT DEFAULT 0 | 排序 |
|
||
| status | TINYINT DEFAULT 1 | 1启用 0停用 |
|
||
|
||
#### transcode_tasks 转码任务表
|
||
| 字段 | 类型 | 说明 |
|
||
|---|---|---|
|
||
| id | BIGINT PK | |
|
||
| video_id | BIGINT FK | |
|
||
| source_url | VARCHAR(500) | 源文件地址 |
|
||
| task_status | TINYINT | 0排队 1转码中 2成功 3失败 |
|
||
| priority | TINYINT DEFAULT 0 | 0普通 1优先(会员) |
|
||
| retry_count | INT DEFAULT 0 | 重试次数 |
|
||
| error_msg | VARCHAR(500) | 失败原因 |
|
||
| created_at / updated_at | DATETIME | |
|
||
|
||
索引:`idx_pick(task_status, priority DESC, created_at)`(消费者取任务用)
|
||
|
||
#### tags 标签表
|
||
| 字段 | 类型 | 说明 |
|
||
|---|---|---|
|
||
| id | INT PK AUTO_INCREMENT | |
|
||
| name | VARCHAR(20) | 标签名,**唯一索引**(大小写不敏感) |
|
||
| video_count | INT DEFAULT 0 | 关联视频数(冗余) |
|
||
| created_at | DATETIME | |
|
||
|
||
#### video_tags 视频-标签关联表
|
||
| 字段 | 类型 | 说明 |
|
||
|---|---|---|
|
||
| id | BIGINT PK | |
|
||
| video_id | BIGINT FK | |
|
||
| tag_id | INT FK | |
|
||
|
||
约束:唯一索引 `uk_video_tag(video_id, tag_id)`;索引 `idx_tag(tag_id, video_id)`(标签视频列表页用)
|
||
|
||
### 3.4 互动域
|
||
|
||
#### comments 评论表
|
||
| 字段 | 类型 | 说明 |
|
||
|---|---|---|
|
||
| id | BIGINT PK | |
|
||
| video_id | BIGINT FK | |
|
||
| user_id | BIGINT FK | |
|
||
| parent_id | BIGINT DEFAULT 0 | 0=一级评论,否则为父评论 ID |
|
||
| reply_to_user_id | BIGINT NULL | 被回复人 |
|
||
| content | VARCHAR(500) | 内容 |
|
||
| like_count | INT DEFAULT 0 | |
|
||
| status | TINYINT DEFAULT 1 | 1正常 2已删除 3审核中 |
|
||
| reward_counted | TINYINT DEFAULT 0 | 是否已计入评论奖励进度 |
|
||
| created_at | DATETIME | |
|
||
|
||
索引:`idx_video(video_id, status, created_at)`、`idx_user_video(user_id, video_id)`(查首评用)
|
||
|
||
#### likes 点赞表 / favorites 收藏表(结构相同)
|
||
| 字段 | 类型 | 说明 |
|
||
|---|---|---|
|
||
| id | BIGINT PK | |
|
||
| user_id | BIGINT FK | |
|
||
| video_id | BIGINT FK | |
|
||
| created_at | DATETIME | |
|
||
|
||
约束:**唯一索引 `uk_user_video(user_id, video_id)`** 防重复点赞/收藏;另建 `idx_video(video_id)`。
|
||
|
||
### 3.5 计费域
|
||
|
||
#### watch_records 观看记录表
|
||
| 字段 | 类型 | 说明 |
|
||
|---|---|---|
|
||
| id | BIGINT PK | |
|
||
| subject_type | TINYINT | 1注册用户 2游客 |
|
||
| subject_id | VARCHAR(64) | user_id 或 device_id |
|
||
| video_id | BIGINT | |
|
||
| watch_date | DATE | 观看日期(用于当日去重) |
|
||
| cost_type | TINYINT | 0免费额度 1积分扣减 2会员免费 3作者本人 |
|
||
| cost_points | INT DEFAULT 0 | 本次消耗积分 |
|
||
| watch_duration | INT DEFAULT 0 | 观看时长(秒) |
|
||
| position | INT DEFAULT 0 | 最新播放进度(秒,用于续播) |
|
||
| created_at | DATETIME | |
|
||
|
||
约束:**唯一索引 `uk_dedup(subject_type, subject_id, video_id, watch_date)`**,是"同日同视频不重复扣费"的底层保证。
|
||
|
||
#### point_transactions 积分流水表
|
||
| 字段 | 类型 | 说明 |
|
||
|---|---|---|
|
||
| id | BIGINT PK | |
|
||
| user_id | BIGINT FK | |
|
||
| change_amount | INT | 变动值(正=增,负=减) |
|
||
| balance_after | INT | 变动后余额 |
|
||
| biz_type | TINYINT | 1充值 2观看消耗 3评论奖励 4开通会员 5活动赠送 6后台调整 7奖励扣回 8推荐奖励 |
|
||
| biz_id | VARCHAR(64) | 关联单据号(订单号/视频ID等) |
|
||
| remark | VARCHAR(200) | 备注 |
|
||
| created_at | DATETIME | |
|
||
|
||
索引:`idx_user_created(user_id, created_at)`、`idx_biz(biz_type, biz_id)`
|
||
|
||
#### recharge_orders 充值订单表
|
||
| 字段 | 类型 | 说明 |
|
||
|---|---|---|
|
||
| id | BIGINT PK | |
|
||
| order_no | VARCHAR(32) | 平台订单号,**唯一索引** |
|
||
| user_id | BIGINT FK | |
|
||
| amount_fen | INT | 人民币金额(分) |
|
||
| points | INT | 应到账积分 |
|
||
| pay_method | TINYINT | 1支付宝 2微信 3USDT |
|
||
| status | TINYINT | 0待支付 1已支付 2已关闭 3已退款 |
|
||
| third_trade_no | VARCHAR(64) NULL | 第三方流水号/tx_hash,**唯一索引**(幂等关键) |
|
||
| usdt_amount | DECIMAL(18,6) NULL | USDT 金额(含随机尾差) |
|
||
| usdt_rate | DECIMAL(10,4) NULL | 下单时 USDT 汇率 |
|
||
| paid_at | DATETIME NULL | 支付时间 |
|
||
| expire_at | DATETIME | 过期时间 |
|
||
| created_at / updated_at | DATETIME | |
|
||
|
||
索引:`idx_user_status(user_id, status)`
|
||
|
||
### 3.6 Redis Key 设计(配合数据库)
|
||
|
||
| Key | 类型 | TTL | 用途 |
|
||
|---|---|---|---|
|
||
| `sms:code:{phone}` | String | 5min | 短信验证码 |
|
||
| `email:code:{email}` | String | 10min | 邮箱验证码 |
|
||
| `free:watch:{subject}:{yyyyMMdd}` | Set(video_id) | 48h | 当日免费观看去重与计数 |
|
||
| `comment:prog:{user_id}` | Hash {count, date, daily} | 7d | 评论奖励进度/日上限 |
|
||
| `comment:counted:{user_id}:{video_id}` | String | 永久(或随评论删除) | 同视频首评去重 |
|
||
| `view:video:{video_id}` | String(计数) | 异步落库 | 播放量缓冲 |
|
||
| `token:blacklist:{jti}` | String | token剩余有效期 | 登出拉黑 |
|
||
| `watched:{subject}:{yyyyMMdd}` | Set(video_id) | 48h | 当日已看视频集合(推荐去重) |
|
||
| `rec:seed:{yyyyMMdd}` | String | 48h | 当日推荐重排随机种子 |
|
||
| `cview:{subject}:{video_id}:{yyyyMMdd}` | String | 48h | 完整观看当日去重 |
|
||
| `video:cview:{video_id}` | String(计数) | 异步落库 | 完整观看计数缓冲 |
|
||
| `ref:device:{device_id}` | String | 永久 | 设备已注册标记(防小号绑定) |
|
||
| `ref:risk:{inviter_id}:{yyyyMMdd}` | String(计数) | 48h | 邀请人当日新增绑定计数(风控) |
|
||
| `invite:ip:{ip}` | ZSet(code→点击时间戳) | 24h | 推广点击埋点(按 IP 的归因候选) |
|
||
| `invite:clk:{code}:{ip}` | String(JSON) | 24h | 点击详情(UA/时间戳) |
|
||
| `invite:dup:{ip}:{code}` | String | 60s | 同 IP+code 重复埋点去重 |
|
||
| `invite:attr:{device_id}` | String(邀请码) | 7d | 首启归因结果缓存,注册时一次性消费 |
|
||
| `wd:pending:{user_id}` | String | 审核期间 | 提现在途唯一锁 |
|
||
| `search:hot` | ZSet(word→次数) | 25h | 热搜统计(小时截断) |
|
||
| `notif:unread:{user_id}` | String(计数) | 随读清零 | 未读通知数 |
|
||
| `words:sensitive` | String(词库) | 60s | 敏感词缓存 |
|
||
| `config:system` | Hash | 60s | system_configs 缓存 |
|
||
|
||
### 3.7 管理后台域
|
||
|
||
#### admin_users 管理员表
|
||
| 字段 | 类型 | 说明 |
|
||
|---|---|---|
|
||
| id | BIGINT PK | |
|
||
| username | VARCHAR(50) | 登录名,**唯一索引** |
|
||
| password_hash | VARCHAR(255) | bcrypt |
|
||
| name | VARCHAR(50) | 姓名 |
|
||
| role | VARCHAR(20) | super / reviewer / operator |
|
||
| status | TINYINT DEFAULT 1 | 1正常 0禁用 |
|
||
| last_login_at | DATETIME NULL | |
|
||
| created_at | DATETIME | |
|
||
|
||
#### admin_logs 操作日志表
|
||
| 字段 | 类型 | 说明 |
|
||
|---|---|---|
|
||
| id | BIGINT PK | |
|
||
| admin_id | BIGINT FK | 操作人 |
|
||
| action | VARCHAR(50) | 动作(review/adjust_points/ban...) |
|
||
| target | VARCHAR(100) | 操作对象 |
|
||
| detail | VARCHAR(1000) | 参数与原因 |
|
||
| ip | VARCHAR(45) | 操作 IP |
|
||
| created_at | DATETIME | |
|
||
|
||
索引:`idx_admin_created(admin_id, created_at)`
|
||
|
||
#### system_configs 平台配置表
|
||
| 字段 | 类型 | 说明 |
|
||
|---|---|---|
|
||
| config_key | VARCHAR(50) PK | 配置键 |
|
||
| config_value | VARCHAR(500) | 配置值 |
|
||
| description | VARCHAR(200) | 说明 |
|
||
| updated_by | BIGINT NULL | 最后修改人(admin_users.id) |
|
||
| updated_at | DATETIME | |
|
||
|
||
预置键:`register_gift_trial.enabled`(注册赠送体验会员开关:1/0,默认 1)、`register_gift_trial.days`(赠送天数,默认 1)
|
||
|
||
#### recharge_packages 充值套餐表
|
||
| 字段 | 类型 | 说明 |
|
||
|---|---|---|
|
||
| id | INT PK | |
|
||
| amount_yuan | INT | 充值金额(元) |
|
||
| points | INT | 基础到账积分(= 金额 × 汇率) |
|
||
| bonus_points | INT DEFAULT 0 | 赠送积分 |
|
||
| sort | INT DEFAULT 0 | 排序(越大越靠前) |
|
||
| status | TINYINT DEFAULT 1 | 1上架 0下架 |
|
||
| created_at / updated_at | DATETIME | |
|
||
|
||
### 3.8 激励域
|
||
|
||
#### referrals 推荐关系表
|
||
| 字段 | 类型 | 说明 |
|
||
|---|---|---|
|
||
| id | BIGINT PK | |
|
||
| inviter_id | BIGINT FK | 推荐人 |
|
||
| invitee_id | BIGINT | 被推荐人,**唯一索引**(一人仅一次绑定) |
|
||
| invite_code | VARCHAR(10) | 使用的邀请码 |
|
||
| status | TINYINT | 0待激活 1有效(已发奖) 2无效 3风控冻结 |
|
||
| risk_flag | VARCHAR(50) | 风控标记:same_device/same_ip/batch/inviter_burst |
|
||
| register_ip | VARCHAR(45) | 被推荐人注册 IP |
|
||
| activated_at | DATETIME NULL | 激活时间 |
|
||
| created_at | DATETIME | 绑定时间 |
|
||
|
||
索引:`idx_inviter(inviter_id, created_at)`、`idx_status(status, created_at)`
|
||
|
||
#### asset_wallets 资产钱包表
|
||
| 字段 | 类型 | 说明 |
|
||
|---|---|---|
|
||
| user_id | BIGINT PK FK | |
|
||
| assets | DECIMAL(12,1) DEFAULT 0 | 当前资产(允许为负,返利扣回场景) |
|
||
| total_earned | DECIMAL(14,1) DEFAULT 0 | 累计获得 |
|
||
| total_withdrawn | DECIMAL(14,1) DEFAULT 0 | 累计提现 |
|
||
| version | INT DEFAULT 0 | 乐观锁 |
|
||
| updated_at | DATETIME | |
|
||
|
||
#### asset_transactions 资产流水表
|
||
| 字段 | 类型 | 说明 |
|
||
|---|---|---|
|
||
| id | BIGINT PK | |
|
||
| user_id | BIGINT FK | |
|
||
| change_amount | DECIMAL(12,1) | 变动值(正=增,负=减) |
|
||
| balance_after | DECIMAL(12,1) | 变动后余额 |
|
||
| biz_type | TINYINT | 1充值返利 2完整观看收益 3点赞收益 4提现 5提现退回 6返利扣回 7后台调整 |
|
||
| biz_id | VARCHAR(64) | 关联单据(订单号/视频ID/提现单号) |
|
||
| remark | VARCHAR(200) | |
|
||
| created_at | DATETIME | |
|
||
|
||
索引:`idx_user_created(user_id, created_at)`、`idx_biz(biz_type, biz_id)`
|
||
|
||
#### withdrawals 提现记录表
|
||
| 字段 | 类型 | 说明 |
|
||
|---|---|---|
|
||
| id | BIGINT PK | |
|
||
| withdraw_no | VARCHAR(32) | 提现单号,**唯一索引** |
|
||
| user_id | BIGINT FK | |
|
||
| assets | DECIMAL(12,1) | 申请资产 |
|
||
| amount_fen | INT | 折合人民币(分) |
|
||
| channel | TINYINT | 1支付宝 2微信 3USDT |
|
||
| account | VARCHAR(200) | 收款账号 |
|
||
| status | TINYINT | 0待审核 1已打款 2已拒绝(已退回) |
|
||
| reason | VARCHAR(200) | 拒绝原因 |
|
||
| admin_id | BIGINT NULL | 审核人 |
|
||
| created_at / processed_at | DATETIME | 申请/处理时间 |
|
||
|
||
索引:`idx_user(user_id, created_at)`、`idx_status(status, created_at)`
|
||
|
||
#### video_earnings 视频收益结算表
|
||
| 字段 | 类型 | 说明 |
|
||
|---|---|---|
|
||
| video_id | BIGINT PK | |
|
||
| author_id | BIGINT | 作者(冗余,结算时查会员) |
|
||
| complete_views | INT DEFAULT 0 | 累计完整观看次数 |
|
||
| views_settled | INT DEFAULT 0 | 已结算的完整观看刻度 |
|
||
| likes_accrued | INT DEFAULT 0 | 累计点赞(取消会回退) |
|
||
| likes_settled | INT DEFAULT 0 | 已结算的点赞刻度 |
|
||
| updated_at | DATETIME | |
|
||
|
||
索引:`idx_author(author_id)`
|
||
|
||
### 3.9 通用域
|
||
|
||
#### notifications 消息通知表
|
||
| 字段 | 类型 | 说明 |
|
||
|---|---|---|
|
||
| id | BIGINT PK | |
|
||
| user_id | BIGINT FK | 接收人 |
|
||
| type | TINYINT | 1审核结果 2提现进度 3系统公告 4评论回复 |
|
||
| title | VARCHAR(100) | |
|
||
| content | VARCHAR(500) | |
|
||
| biz_id | VARCHAR(64) | 关联单据(视频ID/提现单号/评论ID) |
|
||
| is_read | TINYINT DEFAULT 0 | 0未读 1已读 |
|
||
| created_at | DATETIME | |
|
||
|
||
索引:`idx_user_read(user_id, is_read, id)`
|
||
|
||
#### reports 举报表
|
||
| 字段 | 类型 | 说明 |
|
||
|---|---|---|
|
||
| id | BIGINT PK | |
|
||
| user_id | BIGINT FK | 举报人 |
|
||
| target_type | TINYINT | 1视频 2评论 |
|
||
| target_id | BIGINT | 对象 ID |
|
||
| reason_type | TINYINT | 1色情低俗 2暴力血腥 3侵权 4广告营销 5其他 |
|
||
| remark | VARCHAR(200) | 补充说明 |
|
||
| status | TINYINT | 0待处理 1已处理 2已驳回 |
|
||
| handle_result | VARCHAR(50) | 处理动作(offline_video/delete_comment) |
|
||
| admin_id | BIGINT NULL | 处理人 |
|
||
| created_at / handled_at | DATETIME | |
|
||
|
||
约束:唯一索引 `uk_user_target(user_id, target_type, target_id)`;索引 `idx_status(status, created_at)`
|
||
|
||
#### sensitive_words 敏感词表
|
||
| 字段 | 类型 | 说明 |
|
||
|---|---|---|
|
||
| id | INT PK AUTO_INCREMENT | |
|
||
| word | VARCHAR(50) | 敏感词,**唯一索引** |
|
||
| created_at | DATETIME | |
|
||
|
||
### 3.10 采集域
|
||
|
||
#### series 系列(合集)表
|
||
| 字段 | 类型 | 说明 |
|
||
|---|---|---|
|
||
| id | BIGINT PK AUTO_INCREMENT | |
|
||
| title | VARCHAR(100) | 系列标题 |
|
||
| cover_url | VARCHAR(500) | 封面 |
|
||
| description | VARCHAR(500) | 简介 |
|
||
| author_id | BIGINT NULL | 作者 |
|
||
| category_id | INT | 分类 |
|
||
| total_episodes | INT DEFAULT 0 | 总集数 |
|
||
| view_count | BIGINT DEFAULT 0 | 播放量 |
|
||
| status | SMALLINT DEFAULT 1 | 1正常 0隐藏 |
|
||
| created_at / updated_at | DATETIME | |
|
||
|
||
索引:`idx_series_cat_status(category_id, status)`、`idx_series_status_created(status, created_at)`;videos 表以 `series_id` 关联所属系列
|
||
|
||
#### collection_sources 采集源配置表
|
||
| 字段 | 类型 | 说明 |
|
||
|---|---|---|
|
||
| id | BIGINT PK AUTO_INCREMENT | |
|
||
| name | VARCHAR(50) | 分类名(添加时自动建/找本站分类) |
|
||
| list_url | VARCHAR(500) | 列表 URL 模板,`{{page}}` 为页码占位 |
|
||
| category_id | INT UNSIGNED | 本站分类 id |
|
||
| status | SMALLINT DEFAULT 1 | 1启用 0停用 |
|
||
| last_sync_at | DATETIME NULL | 最近同步时间 |
|
||
| created_at / updated_at | DATETIME | |
|
||
|
||
#### collection_records 采集记录表
|
||
| 字段 | 类型 | 说明 |
|
||
|---|---|---|
|
||
| id | BIGINT PK AUTO_INCREMENT | |
|
||
| source_key | VARCHAR(50) | 内容源标识 |
|
||
| source_id | BIGINT | 源站内容 id |
|
||
| series_id | BIGINT NULL | 本站系列 id |
|
||
| video_id | BIGINT NULL | 本站视频 id(单视频类) |
|
||
| created_at | DATETIME | |
|
||
|
||
约束:唯一索引 `uk_source(source_key, source_id)` 保证幂等导入(重复同步不产生重复视频);索引 `idx_record_series(series_id)`、`idx_record_video(video_id)`
|
||
|
||
---
|
||
|
||
## 4. 接口设计(概览)
|
||
|
||
- 统一前缀:`/api/v1`
|
||
- 认证:`Authorization: Bearer <access_token>`,游客请求携带 `X-Device-ID`
|
||
- 统一响应:`{ "code": 0, "message": "ok", "data": {...} }`
|
||
- 完整接口定义见《03-接口文档》
|
||
|
||
| 分组 | 接口数 | 说明 |
|
||
|---|---|---|
|
||
| 认证 | 7 | 验证码、注册、登录、找回密码、刷新、登出 |
|
||
| 用户 | 8 | 资料、头像、钱包、积分明细、注销、公开主页、他人作品 |
|
||
| 视频 | 13 | Feed、详情、观看/完整观看上报、上传、发布、编辑、删除、我的作品、分类、标签视频、搜索、热搜 |
|
||
| 互动 | 7 | 点赞、收藏、评论增删查、收藏/历史列表 |
|
||
| 会员 | 3 | 套餐、我的会员、积分开通 |
|
||
| 支付 | 4 + 2回调 | 套餐、下单、查单、取消;支付宝/微信回调(USDT 为服务端轮询) |
|
||
| 激励 | 6 | 邀请信息、绑定邀请码、资产钱包/流水、提现申请/记录 |
|
||
| 推广归因 | 2 + 1 落地页 | 点击埋点、首启归因匹配、H5 推广落地页(/r/{code}) |
|
||
| 消息与通用 | 5 | 版本检查、通知列表/未读数/标记已读、举报 |
|
||
| 后台管理 | 32 | 审核、视频/评论管理、用户、积分、订单、套餐配置、赠送、提现审核、推荐风控、举报处理、敏感词、平台配置、看板、日志(/admin 前缀) |
|
||
|
||
---
|
||
|
||
## 5. 前端设计
|
||
|
||
技术选型:Flutter(一套代码出 iOS/Android)。技术细节见《02-技术文档》第 5 章。
|
||
|
||
### 5.1 页面清单与路由
|
||
|
||
| 路由 | 页面 | 说明 |
|
||
|---|---|---|
|
||
| /splash | 启动页 | 初始化 device_id、Token 续期、配置拉取 |
|
||
| /home | 首页 | 沉浸式视频 Feed(默认页) |
|
||
| /video/:id | 视频播放详情 | 全屏播放 + 互动栏 |
|
||
| /login | 登录/注册 | 手机号 Tab(默认)/ 邮箱 Tab |
|
||
| /mine | 我的 | 个人中心 |
|
||
| /mine/edit | 编辑资料 | |
|
||
| /mine/wallet | 我的钱包 | 积分余额、明细、充值入口 |
|
||
| /mine/recharge | 充值页 | 套餐选择 + 支付方式 |
|
||
| /mine/recharge/usdt | USDT 支付页 | 金额/地址/二维码/倒计时 |
|
||
| /mine/referral | 邀请好友 | 邀请码/链接、累计奖励、推荐列表 |
|
||
| /mine/assets | 资产钱包 | 资产余额、流水、提现入口 |
|
||
| /mine/assets/withdraw | 提现页 | 金额/渠道/账号,提交后查进度 |
|
||
| /mine/vip | 会员中心 | 套餐卡片、权益、开通 |
|
||
| /mine/videos | 我的作品 | 含审核状态 |
|
||
| /mine/favorites | 我的收藏 | |
|
||
| /mine/history | 观看历史 | |
|
||
| /upload | 上传视频 | 选片→剪辑信息→发布 |
|
||
| /search | 搜索 | |
|
||
| /category | 分类页 | 按分类浏览视频 |
|
||
| /tags/:name | 标签视频页 | 某标签下的视频列表 |
|
||
| /mine/downloads | 已下载 | 离线视频列表(进度/删除/播放) |
|
||
| /notifications | 消息通知 | 通知列表、未读标记 |
|
||
| /settings | 设置 | 退出登录等 |
|
||
|
||
### 5.2 核心页面布局
|
||
|
||
#### 5.2.1 首页(视频 Feed)
|
||
- 全屏竖向 PageView,每个页面一个视频播放器(3 槽播放器池:当前页播放 + 下一页预缓冲,划走即停)
|
||
- 顶部:Feed 策略 Tab(推荐 / 最新 / 热度 / 口碑 / 热播)+ 搜索图标;各策略分页状态独立保活,切 Tab 不丢进度
|
||
- 右侧互动栏(自上而下):作者头像(+关注预留)、点赞(红心+计数)、评论(气泡+计数)、收藏(星标+计数)、分享
|
||
- 左下:作者昵称、标题(标题后展示 #标签,点击跳转标签视频页;并带时长角标)、描述(展开/收起)
|
||
- 底部(游客/非会员场景):今日免费剩余次数提示条(剩余 ≤ 3 次时显示)
|
||
|
||
#### 5.2.2 评论页(底部弹层)
|
||
- BottomSheet,高度 2/3 屏;顶部评论总数;列表(头像/昵称/内容/时间/点赞);底部输入框
|
||
- 二级回复:点击评论展开子回复
|
||
|
||
#### 5.2.3 我的
|
||
- 顶部:头像、昵称、ID、会员标识(金色卡片入口)
|
||
- 中部数据行:作品 / 收藏 / 历史
|
||
- 功能列表:我的钱包(积分余额)、资产钱包(可提现)、邀请好友、会员中心、上传视频、设置
|
||
|
||
#### 5.2.4 充值页
|
||
- 积分余额展示;充值套餐网格(后台配置的档位,角标"赠 x 积分")+ 自定义金额输入框
|
||
- 支付方式单选:支付宝 / 微信 / USDT(带图标)
|
||
- 底部"立即支付"按钮;支付结果页(成功/失败/查询中轮询)
|
||
|
||
#### 5.2.5 会员中心
|
||
- 当前会员状态卡片(类型、到期时间)
|
||
- 四张套餐卡:体验/月卡/年卡/终身卡(价格=积分,终身卡高亮"永久")
|
||
- 权益说明列表:无限观看、优先上传
|
||
- 开通按钮 → 积分余额确认弹窗(余额不足跳充值)
|
||
|
||
#### 5.2.6 上传页
|
||
- 三步:选择视频(系统相册/拍摄)→ 填写信息(封面选择、标题、描述、分类)→ 发布
|
||
- 发布后进入"转码中"状态页/ Toast 提示,可在"我的作品"查看进度
|
||
|
||
### 5.3 核心交互设计
|
||
|
||
| 场景 | 交互 |
|
||
|---|---|
|
||
| 切换视频 | 垂直滑动,松手吸附;滑出即暂停,滑入自动播放并**上报观看计费** |
|
||
| 单击屏幕 | 暂停 / 继续播放(暂停时显示播放图标) |
|
||
| 双击屏幕 | 点赞动画(大爱心飘出) |
|
||
| 长按屏幕 | 弹出操作菜单:下载视频 / 倍速 / 分享(已下载或下载中置灰) |
|
||
| 拖动进度条 | 跟随 thumb 显示时间气泡(x时xx分xx秒,两端自动夹在屏内) |
|
||
| 游客超限 | 播放第 11 个视频时弹出登录引导弹窗("注册解锁更多视频,今日已看 10/10") |
|
||
| 用户积分不足 | 弹窗"积分不足":去充值 / 开通会员 两个按钮 |
|
||
| 扣费提示 | 每次扣积分播放时顶部 Toast"本次消耗 1 积分" |
|
||
| 会员标识 | 昵称旁金色 VIP 角标;会员 Center 显示到期时间 |
|
||
| 上传结果 | 转码/审核状态在我的作品实时刷新(轮询或推送) |
|
||
|
||
### 5.4 UI 样式规范
|
||
|
||
| 项 | 规范 |
|
||
|---|---|
|
||
| 主题 | 深色为主(#121212 背景),保证视频沉浸感;浅色可选(二期);**弹窗/底部菜单统一白底亮色**(局部包 `ThemeData.light()`,避免深色背景下文字看不清) |
|
||
| 主色 | #FE2C55(红),辅助色 #25F4EE(青) |
|
||
| 会员色 | 金色渐变 #F7D794 → #D4A017 |
|
||
| 文字 | 主 #FFFFFF,次 #B0B0B0,弱 #6E6E6E |
|
||
| 字体 | 系统默认(中文 PingFang/思源),标题 17sp 加粗,正文 15sp,辅助 12sp |
|
||
| 间距 | 4 的倍数体系:4/8/12/16/24 |
|
||
| 圆角 | 按钮 8dp,卡片 12dp,头像圆形 |
|
||
| 组件 | 统一封装:按钮、弹窗、Toast、空态、骨架屏 |
|
||
|
||
### 5.5 域名发现(API 入口)
|
||
|
||
App 不内置固定 API 域名,启动时按以下流程动态获取:
|
||
|
||
1. **优先:DNS TXT 解析**。解析 `txt.256kb.top` 的 TXT 记录,记录内容即真实 API 域名(如 `api.xxx.com`),拼接 `https://` 作为 Base URL
|
||
2. **兜底:计算域名**。TXT 解析失败或内容为空时,取当前"年月"字符串(格式 `yyyyMM`,如 `202610`)计算 MD5(32 位小写),拼接为 `{md5(yyyyMM)}_jsnbhh.vip`(例如 `d8578ef...9c_jsnbhh.vip`)
|
||
3. 获取成功后写入本地缓存;后续启动优先使用缓存域名,同时后台异步刷新;缓存域名连续请求失败达到阈值时重新走完整发现流程
|
||
4. 所有网络请求统一从该入口获取 Base URL,业务代码中禁止硬编码任何 API 域名
|
||
5. **兜底域名配套**:`jsnbhh.vip` 需配置 DNS 泛解析 + 通配符证书(`*.jsnbhh.vip`)并接入 CDN/网关回源,保证任意 md5 前缀域名开箱可用;每月 1 日前运维确认泛解析与证书有效
|
||
|
||
---
|
||
|
||
### 5.6 设备指纹与公共请求头
|
||
- **device_id**:App 首次启动生成 UUID(v4),Android 存 Keystore 加密的 SharedPreferences,iOS 存 Keychain(卸载重装保留);即游客计费与风控的设备指纹,客户端禁止采集 IMEI/OAID 等系统标识
|
||
- 所有请求携带公共 Header:`X-Device-ID`(必带)、`X-App-Version`(如 1.0.0)、`X-Platform`(android/ios)
|
||
|
||
### 5.7 版本检查与强制更新
|
||
- App 启动及回到前台时调用 `GET /app/version`:返回最新版本号、是否强制更新、下载地址、维护公告
|
||
- 强制更新:弹窗阻断使用并跳转商店/下载页;非强制:可跳过的提示弹窗;维护公告:全 App 只读提示
|
||
|
||
### 5.8 工程结构(与当前代码对齐)
|
||
|
||
```
|
||
app/lib/
|
||
├── screens/ # 页面:splash / home(HomeShell+IndexedStack) / feed / search / category
|
||
│ # / player / membership / payment / wallet / assets / upload
|
||
│ # / profile / auth / settings / notification / downloads
|
||
├── providers/ # Riverpod 状态(12 个):auth / feed / comment / wallet / member
|
||
│ # / payment / profile / search / upload / asset / notification
|
||
│ # / tag_videos
|
||
└── core/ # 子系统:config(环境配置)/ media(local_media_server 本地代理、
|
||
# download_manager 下载)/ network(api_client、域名发现)/
|
||
# player(feed_player_pool 播放器池)/ storage(token、本地存储)/
|
||
# theme / utils
|
||
```
|
||
|
||
- Feed 策略状态按策略保活:`feedProviderFamily(strategy)` 每个策略一个独立 FeedNotifier;`activeFeedStrategyProvider` + `feedTabVisibleProvider` 配合 HomeShell(IndexedStack)在切页/回前台时挂起与恢复正确的播放器池
|
||
- 401 兜底:无 refresh token 或刷新被拒时清登录态并跳登录页,防止"僵尸登录态"
|
||
|
||
## 6. 后端设计
|
||
|
||
### 6.1 框架推荐:**FastAPI**
|
||
|
||
| 对比项 | FastAPI(推荐) | Django REST Framework | Flask |
|
||
|---|---|---|---|
|
||
| 异步支持 | 原生 async/await(IO 密集接口吞吐高) | 3.x 起部分支持 | 需额外方案 |
|
||
| API 文档 | 自动生成 OpenAPI/Swagger | 需 drf-spectacular | 需 flasgger 等 |
|
||
| 数据校验 | Pydantic 类型声明即校验 | Serializer 较繁琐 | 无内置 |
|
||
| 性能 | 高(Starlette + Uvicorn) | 中 | 中 |
|
||
| 学习/维护 | 类型提示友好,适合中小团队快速迭代 | 全家桶偏重 | 灵活但需自行拼装 |
|
||
|
||
本项目接口以高并发短请求 + 文件流转为主,FastAPI 的异步 IO、自动文档(与《03-接口文档》可互验)和 Pydantic 校验最匹配。
|
||
|
||
**技术栈**:Python 3.11 + FastAPI + SQLAlchemy 2.0(异步)+ Alembic + Pydantic v2 + Celery(转码/异步任务)+ MySQL 8 + Redis 7 + FFmpeg + Nginx。
|
||
|
||
### 6.2 模块划分
|
||
|
||
```
|
||
server/
|
||
├── app/
|
||
│ ├── main.py # 应用入口、中间件、路由注册、lifespan(settle 周期任务启动)
|
||
│ ├── core/ # 配置、日志、异常、安全(JWT/密码)
|
||
│ ├── api/v1/ # 路由层(11 个文件):admin / auth / common / incentives
|
||
│ │ # / interactions / invite / media / membership / payments
|
||
│ │ # / users / videos(管理后台同文件 /admin 前缀、独立管理员鉴权)
|
||
│ ├── schemas/ # Pydantic 请求/响应模型
|
||
│ ├── models/ # SQLAlchemy ORM 模型(30 张表)
|
||
│ ├── services/ # 业务逻辑(17 个):user/auth/wallet/video/interaction/membership
|
||
│ │ # /payment/incentive/invite/admin/common/config/sensitive
|
||
│ │ # /storage/transcode/settle/collection
|
||
│ ├── payment/ # 支付适配层:alipay / wechat / usdt
|
||
│ ├── tasks/ # Celery 任务:转码、播放量落库、订单关单
|
||
│ └── utils/ # 短信、邮件、OSS、设备指纹
|
||
├── scripts/ # 离线脚本:build_tags_from_titles.py(标签生成)、采集脚本
|
||
├── alembic/ # 数据库迁移(init_27_tables → collection_records → collection_sources)
|
||
├── config.yaml # 业务参数配置(积分/会员/支付/上传限制)
|
||
├── .env # 密钥类配置(不入库)
|
||
└── docker-compose.yml
|
||
```
|
||
|
||
### 6.3 核心流程设计
|
||
|
||
#### 6.3.1 观看计费(watch 接口内部逻辑)
|
||
1. 解析身份:有 Token → 用户;无 Token → device_id 游客
|
||
2. 会员校验:`user_membership` 终身卡或 `expire_at > now()` → 记录观看(cost_type=2)返回放行
|
||
3. 同日去重:尝试插入 `watch_records`(唯一键冲突 = 今日已看过)→ 放行返回
|
||
4. 免费额度:Redis `SADD free:watch:{subject}:{date} video_id`,若返回 1 且 `SCARD ≤ 10` → 免费占用,落库返回
|
||
5. 超额度:游客 → 返回错误码 `FREE_LIMIT_EXCEEDED`;用户 → 事务内扣积分(锁钱包行 + 写流水 + 落观看记录)→ 返回成功及剩余积分
|
||
6. 积分不足 → 返回错误码 `INSUFFICIENT_POINTS`
|
||
|
||
> 关键:步骤 3-5 的"去重 + 占额度"用 Redis Lua 脚本保证原子性;扣积分用数据库事务 + 行锁保证原子性。
|
||
|
||
#### 6.3.2 支付到账(回调逻辑,三渠道统一)
|
||
1. 验签/验来源(支付宝公钥、微信 V3 平台证书、USDT 链上数据核对)
|
||
2. 按订单号查订单,校验状态为"待支付"且金额一致
|
||
3. 幂等校验:`third_trade_no`/`tx_hash` 唯一索引冲突 → 直接返回成功(重复回调)
|
||
4. 事务:订单置已支付 → 钱包加积分(行锁)→ 写积分流水 → 提交
|
||
5. 返回支付平台要求的成功响应;失败进入重试/告警
|
||
|
||
#### 6.3.3 转码流水线
|
||
1. 上传完成 → 创建 videos(status=0) + transcode_tasks(priority=会员?1:0)
|
||
2. Celery 两个队列:`transcode.high` / `transcode.normal`,Worker 优先消费 high
|
||
3. FFmpeg 转 HLS(输出 m3u8 + ts)→ 上传 OSS → 更新 video_url、时长、封面
|
||
4. 状态流转:转码成功 → 待审核;失败重试 3 次 → 转码失败
|
||
|
||
#### 6.3.4 评论奖励结算
|
||
1. 发表评论(≥5 字、视频有效、同视频首评)→ 写评论 + `comment:counted` 去重标记
|
||
2. Redis `HINCRBY comment:prog:{uid} count 1`;达 10 → 扣减 10 并事务发放 1 积分(写流水,biz_type=3)
|
||
3. 日上限校验:`daily` 字段达 5 则当日不再发放
|
||
4. 评论删除:若 `reward_counted=1` → 进度 -1;若奖励已发放 → 发放 -1 积分流水(biz_type=7)
|
||
|
||
### 6.4 配置文件样例(config.yaml)
|
||
|
||
```yaml
|
||
points:
|
||
points_per_yuan: 10 # 1元=10积分
|
||
watch_cost: 1 # 每视频消耗积分
|
||
daily_free_count: 10 # 每日免费观看数
|
||
comment_reward:
|
||
per_count: 10 # 每评论10个视频
|
||
reward: 1 # 奖励1积分
|
||
min_length: 5
|
||
daily_limit: 5
|
||
membership:
|
||
trial: { days: 1, points: 5, enabled: true }
|
||
monthly: { days: 30, points: 300, enabled: true }
|
||
yearly: { days: 365, points: 3650, enabled: true }
|
||
lifetime: { days: 0, points: 10000, enabled: true } # days=0 表示永久
|
||
recharge:
|
||
# 充值档位在管理后台维护(recharge_packages 表),实时生效,此处不配置
|
||
usdt: { rate: 7.2, network: TRC20, address: "T...", confirmations: 19, order_expire_min: 30 }
|
||
referral:
|
||
register_reward_points: 10 # 邀请有效新用户奖励积分(N),不限量
|
||
rebate_percent: 5 # 被推荐人充值积分返利比例→资产
|
||
activate_watch_count: 3 # 激活条件:72h内观看≥3个视频
|
||
activate_hours: 72
|
||
risk_max_bind_per_day: 10 # 邀请人单日新增绑定上限(超限冻结审核)
|
||
risk_max_register_per_ip: 5 # 同IP单日注册上限(超限标记风险)
|
||
asset:
|
||
assets_per_yuan: 10 # 10资产=1元
|
||
complete_views_per_asset: 1000 # 每1000次完整观看=1资产
|
||
likes_per_asset: 100 # 每100次点赞=1资产
|
||
complete_progress: 0.95 # 完整观看判定进度
|
||
withdraw:
|
||
min_assets: 100 # 最低提现资产(=10元)
|
||
fee_percent: 0 # 提现手续费比例
|
||
channels: [alipay, wechat, usdt]
|
||
upload:
|
||
max_size_mb: 500
|
||
min_duration_s: 5
|
||
max_duration_s: 600
|
||
hls_profiles: ["720p"] # 可配 ["1080p","720p","480p"]
|
||
```
|
||
|
||
### 6.5 安全设计
|
||
- 密码 bcrypt 哈希;登录失败 5 次锁定 15 分钟(Redis 计数)
|
||
- JWT 双 Token:access 2 小时 + refresh 30 天;登出/改密加入黑名单
|
||
- 支付回调只信验签结果,金额以服务端订单为准
|
||
- 接口限流:验证码 1 条/分钟、评论 10 条/分钟、观看上报 60 次/分钟
|
||
- 上传文件类型白名单校验(mp4/mov/m3u8/ts),大小校验
|
||
- SQL 注入防护:ORM 参数化;XSS:评论内容转义输出
|