Vicky
|
6833e01e1f
|
feat: C 端 1-1 邮箱+密码注册(免码不阻塞,带风控)
为什么:客户端要做的第一件事是账号,但现状下邮箱注册走不通 —— RegisterReqVO.code 是 @NotBlank,
而 OTP 通道现在是 LogOtpSender(只写日志、发不出去),等于注册入口堵死。本轮把"邮箱+密码"打通,
同时按口径补上免码必须带的风控。
- RegisterReqVO.code 放开非必填(PHONE 仍必填,必填性按 targetType 在服务端判断)
- 邮箱注册分支:格式校验(AppIdentifier.requireEmailFormat)+ 密码强度(8-64 位且含字母数字);
传了 code 就顺手校验一次,邮箱验证能力保留但不阻塞
- 注册频控:同 IP 24h ≤5、同设备 24h ≤3(数 app_user.register_ip / register_device_id,不新建计数表),超出 429
- 顺带修一个真问题:login() 原来**无条件**把 credential 标成 verified=1,
密码登录并不证明邮箱归用户所有,会把"未验证"状态悄悄抹掉;改成只有验证码登录才置 1
- docs/api-phase1.md 补注册契约表格与残留风险(IP/设备号可伪造、OTP 只写日志、邮箱可达性未验证)
实测:免码注册成功(邮箱大小写与空格被规范化);弱密码/坏邮箱 400;重复 200001;
邮箱+密码登录成功;PHONE 不带码仍报"请先获取验证码";同设备第 4 次、同 IP 第 6 次分别 429;
免码注册后 verified=0 且经一次密码登录仍是 0。
|
2026-10-15 17:20:31 +08:00 |
|
Vicky
|
efeb9fcfaf
|
feat: 创作者中心支持超管只读代看(未绑定不再白屏)
为什么:/creator-center 菜单同时给了超管和创作者,但接口只认"绑定了 creator.admin_user_id 的账号",
而 creator 表为空 —— 超管点进去每个接口都 403,页面全白。这是设计缺口:需要一条"超管代看"的合法路径,
且必须既能让运营排查问题,又不能变成越权入口。
- requireCurrentCreator 改三级解析:① 绑定优先(创作者角色永远走这条)② 未绑定 + creator-center:impersonate
+ 请求头 X-Creator-Id → 只读代看 ③ 其余给可识别错误码(200004 未绑定 / 200005 未选目标)
- 目标走独立请求头而不是查询参数:creator-center 接口继续"不接收 creatorId";
且只有具备 impersonate 权限的账号这个头才生效 —— 创作者自己带也不影响"只看自己的"
- 只读硬边界:代看态下作品编辑、分集增删改/排序、上传会话与产物挂载、提交/撤回、收费配置一律 200006
(写路径统一走 requireWritableDrama/requireWritable;上传会话在 MediaController 里用 ImpersonationGuard 拦)
- 代看进入写 audit_log(AuditLog 实体 + AuditLogService,同人同目标 10 分钟去重),表本来就有、之前无代码引用
- 新增 GET /admin/creator-center/impersonation/targets(仅 impersonate)供顶部下拉取数
- 权限点 creator-center:impersonate 只授予 super_admin(content_operator 第一阶段不给)
- 修掉菜单 26 的路由名冲突:它和 17 号菜单(创作者管理)都叫 CreatorCenter,Vue Router 同名路由互相覆盖,
导致超管整个 /creator-center 子树注册不上(点进去 404)。改名 CreatorWorkspace,并核对全表无重名
实测:创作者带 X-Creator-Id 仍只看自己的、仍能编辑自己的作品;代看下 9 个写操作全 403;
audit_log 有且仅有一条代看记录(12 次代看请求去重成 1 条)。
|
2026-10-15 15:25:22 +08:00 |
|
Vicky
|
a635de7111
|
feat: 07 创作者中心批 5(前端页面所需的菜单、隐藏路由与详情字段)
为什么:创作者中心的四个页面要挂到后台菜单里,但「作品编辑」是详情页(/creator-center/dramas/:id),
不能出现在侧边栏。当前菜单体系只下发 visible=1 的行、且 meta 里没有 hidden 字段,直接加会导致
"要么侧边栏多出一条无意义菜单,要么详情页路由根本不存在(点编辑就 404)"。所以先把这套补上:
- MenuVO.Meta 增加 hidden;MenuService 把 visible=0 翻译成 meta.hidden,
并让路由下发不再过滤 visible(隐藏项仍要注册路由,侧边栏由前端按 meta.hidden 过滤)
- sql/data-phase1.sql 补创作者中心菜单 26-30(目录 + 我的作品 + 隐藏的作品编辑 + 收费配置 + 数据看板),
创作者角色与超管各授权这 5 条;创作者角色**没有任何运营后台菜单**
- CreatorCenterDramaVO 补 subtitle/genre/description/trailerUrl/language:编辑页要回填这些字段,
之前详情接口只给列表用的那几个字段
- docs/api-phase1.md:07 行改「已实现」,2.10 补四个页面清单与菜单隔离说明
|
2026-10-15 14:47:09 +08:00 |
|
Vicky
|
b0fea1d237
|
feat: 07 创作者中心批 4(数据看板,只读)
为什么:创作者在后台能看到自己的作品与定价了,但看不到"有没有人看、有没有收入"。
本批补一个只读看板,数据全部按 drama.creator_id = 当前创作者 收敛,取不到的一律 null + notes。
- 新增 CreatorDashboardService(放 admin-api):和 3-3 的运营大盘同样的理由 —— 跨内容/播放/互动/交易
四域取数,建模块只会把依赖摊开一层;归属解析复用 CreatorCenterService.requireCurrentCreator(),
接口不接收 creatorId
- 新增 GET /admin/creator-center/dashboard(权限点 creator-center:stat:view)
- 口径(逐条写进代码注释与 docs/api-phase1.md):viewTotal/playTotal 是短剧表累计计数;
watchedDramas/finishedDramas 来自 watch_progress(该表唯一索引是 user_id + drama_id,
每用户每剧一条续看进度,**不是按集**,所以字段名按「用户 × 剧」命名);
playEvents7d/playEventsTotal 是 watch_history 流水;finishEvents 是流水中 position>=duration 的完播事件;
favoriteTotal/commentTotal/commentPending 是我的作品的互动;unlockCount/coinIncome 取
entitlement(source=ORDER) 与 coin_ledger(UNLOCK, biz_id=我的分集)
- paidOrderAmount 与 daily 恒为 null:前者要等 Apple/Google 商店接入,后者 creator_stat_daily 表已建但无产出任务
- 权限点 creator-center:stat:view(创作者角色 + 超管)
实测:看板输出与 SQL 手工口径逐项一致;乙的看板只有自己的数(甲 1200 播放 / 2 条评论 / 50 金币未串过去)。
|
2026-10-15 14:28:29 +08:00 |
|
Vicky
|
8b8ebf944f
|
feat: 07 创作者中心批 3(分片上传挂载 + 分集收费与试看)
为什么:创作者传完片子得把产物挂到分集上才能播,而这条链路之前有两个洞:
uploadId 是"凭证",谁拿到都能往别人的会话里塞分片 / 合并;产物挂载也没有归属校验,
拿到别人的 assetId 就能把自己的剧指向别人的素材。定价这边则缺创作者入口与试看秒数配置。
- 上传复用现有 /admin/media/upload/{init,chunk,complete},不重写;新增 GET /admin/media/upload/{uploadId}
做断点续传回显(receivedChunks/totalChunks/percent/status,完成后带 url)
- 上传会话归属校验:chunk / complete / 进度查询都要求会话发起人,别人拿到 uploadId 也操作不了(403)
- 新增 attach 接口:产物必须① 是本次登录的人上传的(media_asset.create_by)② bizType=EPISODE 且状态 ready/uploaded
③ 分集属于自己这部剧且作品可编辑;挂载时把产物时长补到分集上
- 收费配置复用 PriceService:新增创作者侧 GET/PUT /admin/creator-center/dramas/{id}/prices;
PriceSaveReqVO/PriceRespVO 补 previewSeconds(落在已有的 drama_episode.preview_seconds,不新造一套)
- 定价沿用"可编辑状态"口径:draft/offline 可改,已上线要先申请下线;dramaId 以路径为准,别人的 episodeId 被忽略
- 权限点 creator-center:upload / creator-center:price:update;创作者角色同时获得 cover:upload / episode:upload(复用上传接口)
实测:未登录请求付费集返回 {"accessType":"COIN_REQUIRED","unlockCoin":50,"previewSeconds":15},
免费集直接拿到签名播放地址 —— 创作者改的价格确实走到了 C 端付费判定。
|
2026-10-15 14:12:10 +08:00 |
|
Vicky
|
255bcbf02b
|
feat: 07 创作者中心批 2(内容编辑 / 分集 / 提交审核)
为什么:批 1 只给了创作者"看"的能力(工作台、审核进度、通知),内容还是得后台代建。
批 2 补上"改":创作者自己建草稿、编分集、提交审核,后台只管审。落地过程中发现三个必须一起修的问题:
1. 【会卡死创作者】后台驳回提交时不动短剧状态,剧会永远停在 reviewing,
而批 2 里 reviewing 是只读 —— 创作者既改不了也提不了。现在驳回与撤回都会把剧退回 draft。
2. 【上线了却放不出来】C 端只播 status=published 的分集,但没有任何地方在剧上线时把分集带上线。
审核通过 PUBLISH 时,仍处于草稿的分集一并上线。
3. 【编辑会误删字段】底层 apply() 对 null 会写空串/默认值:只想改封面的一次调用会把标题、时长、
排序一起清掉(自测时两集排序都变成 1 才发现)。creator 侧改成"未传字段沿用现值"。
- 新增 CreatorContentService + /admin/creator-center 的 10 个写接口与 2 个读接口,
一律不接收 creatorId,归属走 requireMyDrama,改别人的作品/分集统一 403
- 状态闸:只有 draft / offline 可直接编辑;reviewing / approved / published 只读并给出下一步动作
- 提交矩阵:draft→CREATE(首次)/UPDATE/PUBLISH,offline→UPDATE/PUBLISH,reviewing/approved→PUBLISH,published→OFFLINE;
同剧同时只允许一条在审提交;撤回后作品退回草稿,支持撤回重提
- 权限点 creator-center:drama:edit(创作者角色 + 超管),docs/api-phase1.md 2.10 补批 2 接口与规则表
- 分集收费与试看秒数本批不碰(批 3 的收费配置页负责),新增分集默认免费,避免误定价
|
2026-10-15 13:58:45 +08:00 |
|
Vicky
|
ea875c3e2b
|
feat: 07 创作者中心批 1(账号绑定 + 我的作品 / 审核进度 / 通知)
为什么:创作者要在 Web 端(做进后台管理)看到自己的作品与审核进度,但 creator 模块
此前只有「后台审核视角」的服务,创作者本人没有任何入口;更要紧的是,全项目没有任何
地方把「后台账号」和「创作者主体」关联起来 —— 缺这层映射,横向越权就只能靠每个接口
自觉加 where 过滤,迟早会漏。所以批 1 先把归属判定的地基打好,再给工作台接口。
- creator 增加 admin_user_id(幂等 ALTER + 部分唯一索引,0 = 未绑定,多条 0 不冲突)
- 新增角色 creator 与权限点 creator-center:view(创作者角色 + 超管各授权一条),菜单等页面做好再挂
- 新增 CreatorCenterService:requireCurrentCreator() 是归属判定的唯一入口,requireMyDrama() 供后续批次复用
- 新增 /admin/creator-center 四个接口(profile / dramas/page / dramas/{id} / notices),
一律不接收 creatorId,查询强制 where creator_id = 当前创作者,访问他人作品统一 403
- 通知不新建表:由入驻审核结果 + 内容提交审核结果派生(ops_notice 无产出方,等有公告功能再接)
- 顺手接通 drama.trailer_url:DDL 与实体早就有,但保存 VO / 响应 VO 都没带,预告片存不进也读不出
- ContentSubmissionService 补 typeText + TYPE_* 常量(通知文案与批 2 的提交都要用)
|
2026-10-15 13:45:32 +08:00 |
|
Vicky
|
8b261b71de
|
feat: 08 后台四个页面的菜单与权限点落库 + 契约文档收口
为什么:内容治理 / 订单与权益 / 数据看板这三个页面的菜单此前刻意留空——
3-3 时页面还没做,菜单先落库会让前端动态路由指向不存在的组件。页面这一轮做完了,
把菜单(id 20–25,含组件路径)、权限点与超管授权按幂等写法补进 sql/data-phase1.sql,
刷新后台即生效,不需要清缓存重新登录。
- sql/data-phase1.sql:新增 3 个目录 + 3 个菜单,超管菜单授权 20–25;可重复执行
- docs/api-phase1.md:08 行由「仅剩后台页面(3-4)」改为「已实现」;
新增「2.9 后台前端页面(已实现)」,列出五个页面的路由 / 组件路径 / 依赖权限点 / 覆盖接口
|
2026-10-15 13:29:18 +08:00 |
|
Vicky
|
d67d9daf8c
|
feat: 08 数据看板落地(总览 + 转码看板,只读)
为什么:
1) 前面几块把用户、内容、播放、交易、媒资的数据都落库了,运营需要一个地方一次看完,
否则每个指标都要去查库或翻后台列表。
2) 看板最容易出的问题是"数字看起来对但口径不清",所以每个指标都在代码注释和
docs/api-phase1.md 里写死口径(时间范围、统计维度),前端 tooltip 直接复用。
3) 取不到数据源的指标(DAU、CDN 流量成本、商店订单金额)一律返回 null 并在 notes 里
说明缺什么、怎么补 —— 不用 0 冒充,避免运营拿假数字做判断。
4) 站在接入层做只读聚合而不是新建模块:它跨六个域取数,建模块只会把依赖再摊开一层,
而它只读不写,放在 admin-api 改动面最小。
|
2026-10-15 13:03:58 +08:00 |
|
Vicky
|
1fb8427f28
|
feat: 08 创作者与内容审核落地(入驻审核 / 内容提交审核 / 定时发布 / 分集定价)
为什么:
1) 内容是创作者供的,必须有一条可管控的供给链路:创作者入驻要审、内容提交要审、
审核通过才能真正上架 —— 否则平台无法对内容和主体负责。
2) 审核不能绕过状态机。内容提交审核通过后,是顺着短剧状态机
SUBMIT → APPROVE → PUBLISH 推上去,而不是直接写 status 字段,
这样审核记录与操作日志都不会缺环。
3) 定时发布(publish_at 到点自动上线)同样走状态机,并且做成幂等任务:
重复执行不会把已上线的剧再推一次。
4) 定价落在 is_free / unlock_coin 上,与权益表解耦:改价立即影响播放与下载判定,
但已购用户的权益不受影响,不会因为改价把用户买过的东西收回去。
5) 补齐 PM 草稿未做的部分:5 个权限点 + 3 条后台菜单(含前端组件路径)+ 超管授权(幂等),
以及后台定价页需要的价格读取接口 GET /admin/prices。
|
2026-10-15 12:51:40 +08:00 |
|
Vicky
|
7e730fbbca
|
feat: 08 订单与权益落地(金币解锁 / 权益判定生效 / 补发回收 / 对账)
为什么:
1) 第一阶段要能真正收到钱,而收钱方式是金币解锁分集。本提交把钱包、金币流水、
权益、订单四样打通,客户端可以解锁并立刻播放,不再只是展示。
2) 权益判定此前只是端口占位(一律视为未解锁)。交易模块用 @Primary 提供实现后,
播放入口与下载入口的付费判定同时生效 —— 两条链路一行没改。
3) 钱的事必须可追溯、可幂等:所有金币变动都带幂等键并写 coin_ledger,
余额与流水同事务;订单每次状态流转都写 order_event(月分区),支付争议可回溯。
4) 后台要能兜住线上问题:补发(重复提交幂等)、退款(回收权益 + 扣回金币,
余额不足时留人工跟进备注)、人工补币(先校验用户存在,避免给不存在的用户建钱包)、
手动对账(默认每天 04:20 自动跑前一天)。
5) 09 商店支付按约束只做端口预留:StoreVerifier 未接入时明确报"尚未配置",
宁可不收钱也不产生假订单。
|
2026-10-15 12:26:27 +08:00 |
|
Vicky
|
af1dc48494
|
feat: 06 互动与内容治理落地(评论 / 点赞 / 举报 / 敏感词 / 审核留证)
为什么:
1) 产品侧要先把内容治理闭环跑通才能谈上线:评论可发布、可翻页、可删除,
违规内容能在后台被审核与驳回,举报要有工单可追溯。本提交把这套补齐。
2) 审核不能只靠人肉:敏感词按 BLOCK/REPLACE/REVIEW 三档处置,
机审通过即发布(可配置为 PRE_REVIEW 全部先审后发),人审与机审的结论
都写进 content_audit_record,争议时可回答"当时凭什么放行/驳回"。
3) 举报处理必须与处置打通:结论成立会联动驳回被举报评论,并可选同时封禁被举报用户,
避免"工单处理完了但违规内容还挂着"。
4) 顺带修复一个真实缺陷:user_favorite / content_like 上有唯一索引,而全局配置会把
deleteById 改写成逻辑删除,导致取消收藏/点赞后旧的 deleted 行仍占位,
再次收藏或点赞直接撞唯一索引报错。关系类数据没有留证价值,改为显式物理删除,
并补了"取消后再来一次"的回归自测。
|
2026-10-15 12:03:32 +08:00 |
|
Vicky
|
b3179fc836
|
refactor: 后端标识统一为 FruitShorts,并落地 05 离线下载
为什么:
1) 产品已定名 FruitShorts,但后端仍是 reelshort 系列标识 —— Java 包 com.reelshort、
模块名与 jar 名 reelshort-*、spring.application.name、配置前缀 reelshort.*,
这些会出现在启动日志、命令行和 IDE 里,与产品名不一致。本次整体替换为 fruitshorts,
数据库连接名上一轮已改名,保持不变。
2) 第一阶段下一批第 1 步(05 离线下载)要求把下载授权(设备绑定/有效期/吊销)、
下载任务与断点续传、配额与过期清理、仅 Wi-Fi 规则做成完整接口,本提交一并落地。
3) 顺带修复:schema-phase1.sql 里 playback_ticket / order_event 仍按普通表定义唯一索引,
表分区化之后重跑脚本必定报错(分区表的唯一索引必须包含分区键)。改为在本脚本里就
按分区表定义,并验证脚本可重复执行。
|
2026-10-15 11:44:26 +08:00 |
|