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 端付费判定。
This commit is contained in:
1 parent
255bcbf02b
commit
8b8ebf944f
12 files changed
+269
-10
No files matched your search
+28
@@ -3,8 +3,11 @@ package com.fruitshorts.admin.controller;
|
||||
import com.fruitshorts.common.pojo.Result;
|
||||
import com.fruitshorts.content.vo.EpisodeRespVO;
|
||||
import com.fruitshorts.content.vo.EpisodeSortReqVO;
|
||||
import com.fruitshorts.content.vo.PriceRespVO;
|
||||
import com.fruitshorts.content.vo.PriceSaveReqVO;
|
||||
import com.fruitshorts.creator.dal.entity.ContentSubmission;
|
||||
import com.fruitshorts.creator.service.CreatorContentService;
|
||||
import com.fruitshorts.creator.vo.CreatorAttachReqVO;
|
||||
import com.fruitshorts.creator.vo.CreatorDramaEditReqVO;
|
||||
import com.fruitshorts.creator.vo.CreatorEpisodeReqVO;
|
||||
import com.fruitshorts.creator.vo.CreatorSubmitReqVO;
|
||||
@@ -118,4 +121,29 @@ public class CreatorContentController {
|
||||
public Result<List<ContentSubmission>> listSubmissions(@PathVariable Long id) {
|
||||
return Result.ok(creatorContentService.listSubmissions(id));
|
||||
}
|
||||
|
||||
/** 把上传好的视频产物挂到自己的分集上(产物必须是本人上传的)。 */
|
||||
@PostMapping("/dramas/{id}/episodes/{episodeId}/attach")
|
||||
@PreAuthorize("@ss.hasPermission('creator-center:upload')")
|
||||
@OperationLog(module = "创作者中心", action = "挂载分集视频")
|
||||
public Result<Void> attachAsset(@PathVariable Long id, @PathVariable Long episodeId,
|
||||
@Valid @RequestBody CreatorAttachReqVO req) {
|
||||
creatorContentService.attachAsset(id, episodeId, req.getAssetId());
|
||||
return Result.ok();
|
||||
}
|
||||
|
||||
/** 分集收费与试看秒数:读现状。 */
|
||||
@GetMapping("/dramas/{id}/prices")
|
||||
@PreAuthorize("@ss.hasPermission('creator-center:view')")
|
||||
public Result<PriceRespVO> priceDetail(@PathVariable Long id) {
|
||||
return Result.ok(creatorContentService.priceDetail(id));
|
||||
}
|
||||
|
||||
/** 分集收费与试看秒数:保存(复用后台同一套 PriceService,改完立即影响付费判定)。 */
|
||||
@PutMapping("/dramas/{id}/prices")
|
||||
@PreAuthorize("@ss.hasPermission('creator-center:price:update')")
|
||||
@OperationLog(module = "创作者中心", action = "配置分集价格")
|
||||
public Result<PriceRespVO> savePrice(@PathVariable Long id, @RequestBody PriceSaveReqVO req) {
|
||||
return Result.ok(creatorContentService.savePrice(id, req));
|
||||
}
|
||||
}
|
||||
+10
-2
@@ -7,6 +7,7 @@ import com.fruitshorts.media.vo.MediaAssetRespVO;
|
||||
import com.fruitshorts.media.vo.UploadCompleteReqVO;
|
||||
import com.fruitshorts.media.vo.UploadInitReqVO;
|
||||
import com.fruitshorts.media.vo.UploadInitRespVO;
|
||||
import com.fruitshorts.media.vo.UploadProgressRespVO;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
@@ -40,14 +41,21 @@ public class MediaController {
|
||||
public Result<Integer> uploadChunk(@RequestParam String uploadId,
|
||||
@RequestParam int index,
|
||||
@RequestParam("file") MultipartFile file) {
|
||||
mediaService.saveChunk(uploadId, index, file);
|
||||
mediaService.saveChunk(uploadId, index, file, SecurityUtils.getUserId());
|
||||
return Result.ok(index);
|
||||
}
|
||||
|
||||
@PostMapping("/upload/complete")
|
||||
@PreAuthorize("@ss.hasAnyPermission('cover:upload','episode:upload')")
|
||||
public Result<MediaAssetRespVO> complete(@Valid @RequestBody UploadCompleteReqVO req) {
|
||||
return Result.ok(mediaService.complete(req));
|
||||
return Result.ok(mediaService.complete(req, SecurityUtils.getUserId()));
|
||||
}
|
||||
|
||||
/** 断点续传:查上传会话进度(只能查自己发起的会话)。 */
|
||||
@GetMapping("/upload/{uploadId}")
|
||||
@PreAuthorize("@ss.hasAnyPermission('cover:upload','episode:upload')")
|
||||
public Result<UploadProgressRespVO> progress(@PathVariable String uploadId) {
|
||||
return Result.ok(mediaService.progress(uploadId, SecurityUtils.getUserId()));
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
|
||||
Reference in new issue
Block a user