feat: 接口字段补 @Schema 中文说明 + 精简冗余字段 + 接入 Prometheus 监控
- 全部 VO 字段补 @Schema(description) 中文说明,在线文档字段可读 - AppEpisodeVO 精简 duration/isFree 冗余字段(保留 durationSec/locked) - framework 引入 actuator + micrometer-registry-prometheus - SecurityConfig 放行 /actuator/prometheus,双服务配置 management 暴露指标 - 新增 deploy/docker-compose.yml + prometheus.yml 监控部署配置
This commit is contained in:
1 parent
efe8af6c9b
commit
5f9483a86c
140 files changed
+1357
-19
No files matched your search
@@ -0,0 +1,32 @@
|
||||
# Author: fruit.com.cn
|
||||
# 监控组件编排:Prometheus + Grafana(Loki 日志后续接入)
|
||||
services:
|
||||
prometheus:
|
||||
image: prom/prometheus:latest
|
||||
container_name: fruitshorts-prometheus
|
||||
ports:
|
||||
- "9090:9090"
|
||||
volumes:
|
||||
- ./prometheus.yml:/etc/prometheus/prometheus.yml
|
||||
- prometheus-data:/prometheus
|
||||
command:
|
||||
- "--config.file=/etc/prometheus/prometheus.yml"
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway"
|
||||
restart: unless-stopped
|
||||
|
||||
grafana:
|
||||
image: grafana/grafana:latest
|
||||
container_name: fruitshorts-grafana
|
||||
ports:
|
||||
- "3000:3000"
|
||||
volumes:
|
||||
- grafana-data:/var/lib/grafana
|
||||
environment:
|
||||
- GF_SECURITY_ADMIN_USER=admin
|
||||
- GF_SECURITY_ADMIN_PASSWORD=admin
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
prometheus-data:
|
||||
grafana-data:
|
||||
@@ -0,0 +1,16 @@
|
||||
# Author: fruit.com.cn
|
||||
# Prometheus 抓取配置:抓取后端双服务的 actuator 指标
|
||||
global:
|
||||
scrape_interval: 15s
|
||||
evaluation_interval: 15s
|
||||
|
||||
scrape_configs:
|
||||
- job_name: "fruitshorts-app-api"
|
||||
metrics_path: "/actuator/prometheus"
|
||||
static_configs:
|
||||
- targets: ["host.docker.internal:8081"]
|
||||
|
||||
- job_name: "fruitshorts-admin-api"
|
||||
metrics_path: "/actuator/prometheus"
|
||||
static_configs:
|
||||
- targets: ["host.docker.internal:8080"]
|
||||
+10
@@ -10,6 +10,8 @@ import com.fruitshorts.framework.log.OperationLog;
|
||||
import com.fruitshorts.system.vo.AdminUserPageReqVO;
|
||||
import com.fruitshorts.system.vo.AdminUserRespVO;
|
||||
import com.fruitshorts.system.vo.AdminUserSaveReqVO;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
@@ -25,6 +27,7 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Tag(name = "管理员管理")
|
||||
@RestController
|
||||
@RequestMapping("/admin/admin-users")
|
||||
@RequiredArgsConstructor
|
||||
@@ -32,18 +35,21 @@ public class AdminUserController {
|
||||
|
||||
private final AdminUserService adminUserService;
|
||||
|
||||
@Operation(summary = "管理员分页检索")
|
||||
@GetMapping("/page")
|
||||
@PreAuthorize("@ss.hasPermission('system:admin-user')")
|
||||
public Result<PageResult<AdminUserRespVO>> page(AdminUserPageReqVO req) {
|
||||
return Result.ok(adminUserService.page(req));
|
||||
}
|
||||
|
||||
@Operation(summary = "管理员详情")
|
||||
@GetMapping("/{id}")
|
||||
@PreAuthorize("@ss.hasPermission('system:admin-user')")
|
||||
public Result<AdminUserRespVO> get(@PathVariable Long id) {
|
||||
return Result.ok(adminUserService.get(id));
|
||||
}
|
||||
|
||||
@Operation(summary = "新增管理员")
|
||||
@PostMapping
|
||||
@PreAuthorize("@ss.hasPermission('system:admin-user')")
|
||||
@OperationLog(module = "后台管理", action = "新增管理员")
|
||||
@@ -51,6 +57,7 @@ public class AdminUserController {
|
||||
return Result.ok(adminUserService.create(req));
|
||||
}
|
||||
|
||||
@Operation(summary = "编辑管理员")
|
||||
@PutMapping("/{id}")
|
||||
@PreAuthorize("@ss.hasPermission('system:admin-user')")
|
||||
@OperationLog(module = "后台管理", action = "编辑管理员")
|
||||
@@ -59,6 +66,7 @@ public class AdminUserController {
|
||||
return Result.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "删除管理员")
|
||||
@DeleteMapping("/{id}")
|
||||
@PreAuthorize("@ss.hasPermission('system:admin-user')")
|
||||
@OperationLog(module = "后台管理", action = "删除管理员")
|
||||
@@ -67,6 +75,7 @@ public class AdminUserController {
|
||||
return Result.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "修改管理员状态")
|
||||
@PutMapping("/{id}/status")
|
||||
@PreAuthorize("@ss.hasPermission('system:admin-user')")
|
||||
@OperationLog(module = "后台管理", action = "修改管理员状态")
|
||||
@@ -75,6 +84,7 @@ public class AdminUserController {
|
||||
return Result.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "重置管理员密码")
|
||||
@PutMapping("/{id}/password")
|
||||
@PreAuthorize("@ss.hasPermission('system:admin-user')")
|
||||
@OperationLog(module = "后台管理", action = "重置管理员密码")
|
||||
|
||||
+8
@@ -18,6 +18,8 @@ import com.fruitshorts.user.dal.entity.AppUserBanRecord;
|
||||
import com.fruitshorts.user.service.AppUserAdminService;
|
||||
import com.fruitshorts.user.vo.AppUserQueryReqVO;
|
||||
import com.fruitshorts.user.vo.AppUserAdminRespVO;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
@@ -32,6 +34,7 @@ import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/** 后台用户管理。 */
|
||||
@Tag(name = "App 用户管理")
|
||||
@RestController
|
||||
@RequestMapping("/admin/app-users")
|
||||
@RequiredArgsConstructor
|
||||
@@ -42,18 +45,21 @@ public class AppUserAdminController {
|
||||
private final DramaService dramaService;
|
||||
private final EpisodeService episodeService;
|
||||
|
||||
@Operation(summary = "用户分页检索(uid/昵称/手机号/邮箱/状态/国家/注册来源)")
|
||||
@GetMapping("/page")
|
||||
@PreAuthorize("@ss.hasPermission('app-user:list')")
|
||||
public Result<PageResult<AppUserAdminRespVO>> page(AppUserQueryReqVO req) {
|
||||
return Result.ok(appUserAdminService.page(req));
|
||||
}
|
||||
|
||||
@Operation(summary = "用户详情")
|
||||
@GetMapping("/{id}")
|
||||
@PreAuthorize("@ss.hasPermission('app-user:list')")
|
||||
public Result<AppUserAdminRespVO> detail(@PathVariable Long id) {
|
||||
return Result.ok(appUserAdminService.detail(id));
|
||||
}
|
||||
|
||||
@Operation(summary = "封禁与申诉记录")
|
||||
@GetMapping("/{id}/ban-records")
|
||||
@PreAuthorize("@ss.hasPermission('app-user:list')")
|
||||
public Result<List<AppUserBanRecord>> banRecords(@PathVariable Long id) {
|
||||
@@ -61,6 +67,7 @@ public class AppUserAdminController {
|
||||
}
|
||||
|
||||
/** 观看流水明细:客服核对"用户说看了但没记录"这类问题时用,带上剧名与集号。 */
|
||||
@Operation(summary = "观看流水明细(客服核对用,带剧名与集号)")
|
||||
@GetMapping("/{id}/watch-history")
|
||||
@PreAuthorize("@ss.hasPermission('app-user:list')")
|
||||
public Result<List<AppUserWatchHistoryVO>> watchHistory(@PathVariable Long id,
|
||||
@@ -108,6 +115,7 @@ public class AppUserAdminController {
|
||||
}
|
||||
|
||||
/** 状态处置:normal/limited/banned。封禁会立即吊销该用户全部会话。 */
|
||||
@Operation(summary = "修改用户状态(normal/limited/banned,封禁立即吊销全部会话)")
|
||||
@PutMapping("/{id}/status")
|
||||
@PreAuthorize("@ss.hasPermission('app-user:update')")
|
||||
@OperationLog(module = "用户管理", action = "修改用户状态")
|
||||
|
||||
+8
@@ -12,6 +12,8 @@ import com.fruitshorts.system.vo.LoginRespVO;
|
||||
import com.fruitshorts.system.vo.MenuVO;
|
||||
import com.fruitshorts.system.vo.PasswordChangeReqVO;
|
||||
import com.fruitshorts.system.vo.ProfileRespVO;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@@ -23,6 +25,7 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Tag(name = "后台认证")
|
||||
@RestController
|
||||
@RequestMapping("/admin/auth")
|
||||
@RequiredArgsConstructor
|
||||
@@ -30,6 +33,7 @@ public class AuthController {
|
||||
|
||||
private final AuthService authService;
|
||||
|
||||
@Operation(summary = "后台登录,返回 token")
|
||||
@PostMapping("/login")
|
||||
@OperationLog(module = "认证", action = "登录")
|
||||
public Result<LoginRespVO> login(@Valid @RequestBody LoginReqVO req, HttpServletRequest request) {
|
||||
@@ -37,23 +41,27 @@ public class AuthController {
|
||||
}
|
||||
|
||||
/** 当前用户的菜单路由树,结构与前端 element-plus-admin 的动态路由一致。 */
|
||||
@Operation(summary = "当前用户菜单路由树")
|
||||
@GetMapping("/menus")
|
||||
public Result<List<MenuVO>> menus() {
|
||||
return Result.ok(authService.listMenus(SecurityUtils.getUserId()));
|
||||
}
|
||||
|
||||
@Operation(summary = "当前用户资料")
|
||||
@GetMapping("/profile")
|
||||
public Result<ProfileRespVO> profile() {
|
||||
return Result.ok(authService.profile(SecurityUtils.getUserId()));
|
||||
}
|
||||
|
||||
/** JWT 无状态,登出由前端清除 token 即可。 */
|
||||
@Operation(summary = "登出(JWT 无状态,前端清除 token 即可)")
|
||||
@PostMapping("/logout")
|
||||
@OperationLog(module = "认证", action = "退出登录")
|
||||
public Result<Void> logout() {
|
||||
return Result.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "修改密码")
|
||||
@PostMapping("/password")
|
||||
@OperationLog(module = "认证", action = "修改密码")
|
||||
public Result<Void> changePassword(@Valid @RequestBody PasswordChangeReqVO req) {
|
||||
|
||||
+10
@@ -9,6 +9,8 @@ import com.fruitshorts.content.vo.BannerRespVO;
|
||||
import com.fruitshorts.content.vo.BannerSaveReqVO;
|
||||
import com.fruitshorts.framework.security.SecurityUtils;
|
||||
import com.fruitshorts.framework.log.OperationLog;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
@@ -25,6 +27,7 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Tag(name = "轮播图管理")
|
||||
@RestController
|
||||
@RequestMapping("/admin/banners")
|
||||
@RequiredArgsConstructor
|
||||
@@ -32,6 +35,7 @@ public class BannerController {
|
||||
|
||||
private final BannerService bannerService;
|
||||
|
||||
@Operation(summary = "轮播图分页检索(按位置/状态过滤)")
|
||||
@GetMapping("/page")
|
||||
@PreAuthorize("@ss.hasPermission('banner:list')")
|
||||
public Result<PageResult<BannerRespVO>> page(@RequestParam(required = false) String position,
|
||||
@@ -41,12 +45,14 @@ public class BannerController {
|
||||
return Result.ok(bannerService.page(position, status, pageIndex, pageSize));
|
||||
}
|
||||
|
||||
@Operation(summary = "轮播图详情")
|
||||
@GetMapping("/{id}")
|
||||
@PreAuthorize("@ss.hasPermission('banner:list')")
|
||||
public Result<BannerRespVO> get(@PathVariable Long id) {
|
||||
return Result.ok(bannerService.get(id));
|
||||
}
|
||||
|
||||
@Operation(summary = "新增轮播图")
|
||||
@PostMapping
|
||||
@PreAuthorize("@ss.hasPermission('banner:create')")
|
||||
@OperationLog(module = "内容管理", action = "新增轮播图")
|
||||
@@ -54,6 +60,7 @@ public class BannerController {
|
||||
return Result.ok(bannerService.create(req, SecurityUtils.getUserId()));
|
||||
}
|
||||
|
||||
@Operation(summary = "编辑轮播图")
|
||||
@PutMapping("/{id}")
|
||||
@PreAuthorize("@ss.hasPermission('banner:update')")
|
||||
@OperationLog(module = "内容管理", action = "编辑轮播图")
|
||||
@@ -62,6 +69,7 @@ public class BannerController {
|
||||
return Result.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "删除轮播图")
|
||||
@DeleteMapping("/{id}")
|
||||
@PreAuthorize("@ss.hasPermission('banner:delete')")
|
||||
@OperationLog(module = "内容管理", action = "删除轮播图")
|
||||
@@ -70,6 +78,7 @@ public class BannerController {
|
||||
return Result.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "修改轮播图状态")
|
||||
@PutMapping("/{id}/status")
|
||||
@PreAuthorize("@ss.hasPermission('banner:update')")
|
||||
@OperationLog(module = "内容管理", action = "修改轮播图状态")
|
||||
@@ -78,6 +87,7 @@ public class BannerController {
|
||||
return Result.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "调整轮播图排序")
|
||||
@PutMapping("/sort")
|
||||
@PreAuthorize("@ss.hasPermission('banner:update')")
|
||||
public Result<Void> sort(@RequestBody Map<String, List<Long>> body) {
|
||||
|
||||
+7
@@ -11,6 +11,8 @@ import com.fruitshorts.interaction.service.CommentService;
|
||||
import com.fruitshorts.interaction.vo.CommentAuditReqVO;
|
||||
import com.fruitshorts.interaction.vo.CommentQueryReqVO;
|
||||
import com.fruitshorts.interaction.vo.CommentRespVO;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
@@ -25,6 +27,7 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
import java.util.List;
|
||||
|
||||
/** 后台评论审核。 */
|
||||
@Tag(name = "评论治理")
|
||||
@RestController
|
||||
@RequestMapping("/admin/comments")
|
||||
@RequiredArgsConstructor
|
||||
@@ -33,6 +36,7 @@ public class CommentAdminController {
|
||||
private final CommentService commentService;
|
||||
|
||||
/** 检索评论:默认按状态过滤,`status=pending` 即审核队列。 */
|
||||
@Operation(summary = "评论检索(status=pending 即审核队列)")
|
||||
@GetMapping("/page")
|
||||
@PreAuthorize("@ss.hasPermission('comment:list')")
|
||||
public Result<PageResult<CommentRespVO>> page(CommentQueryReqVO req) {
|
||||
@@ -40,12 +44,14 @@ public class CommentAdminController {
|
||||
}
|
||||
|
||||
/** 审核留证:机审与人审的完整链路。 */
|
||||
@Operation(summary = "审核留证(机审与人审完整链路)")
|
||||
@GetMapping("/{id}/audit-records")
|
||||
@PreAuthorize("@ss.hasPermission('comment:list')")
|
||||
public Result<List<ContentAuditRecord>> auditRecords(@PathVariable Long id) {
|
||||
return Result.ok(commentService.auditRecords(id));
|
||||
}
|
||||
|
||||
@Operation(summary = "审核评论(通过/驳回,带原因码与说明)")
|
||||
@PutMapping("/{id}/audit")
|
||||
@PreAuthorize("@ss.hasPermission('comment:audit')")
|
||||
@OperationLog(module = "内容治理", action = "审核评论")
|
||||
@@ -54,6 +60,7 @@ public class CommentAdminController {
|
||||
return Result.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "删除评论")
|
||||
@DeleteMapping("/{id}")
|
||||
@PreAuthorize("@ss.hasPermission('comment:audit')")
|
||||
@OperationLog(module = "内容治理", action = "删除评论")
|
||||
|
||||
+5
@@ -6,6 +6,8 @@ import com.fruitshorts.common.pojo.Result;
|
||||
import com.fruitshorts.system.service.ConfigService;
|
||||
import com.fruitshorts.framework.log.OperationLog;
|
||||
import com.fruitshorts.system.vo.ConfigItemVO;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
@@ -17,6 +19,7 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Tag(name = "系统配置")
|
||||
@RestController
|
||||
@RequestMapping("/admin/configs")
|
||||
@RequiredArgsConstructor
|
||||
@@ -24,12 +27,14 @@ public class ConfigController {
|
||||
|
||||
private final ConfigService configService;
|
||||
|
||||
@Operation(summary = "系统配置列表")
|
||||
@GetMapping
|
||||
@PreAuthorize("@ss.hasAnyPermission('system:role','system:menu')")
|
||||
public Result<List<ConfigItemVO>> list() {
|
||||
return Result.ok(configService.list());
|
||||
}
|
||||
|
||||
@Operation(summary = "批量修改系统配置")
|
||||
@PutMapping
|
||||
@PreAuthorize("@ss.hasPermission('system:role')")
|
||||
@OperationLog(module = "后台管理", action = "修改系统设置")
|
||||
|
||||
+10
@@ -15,6 +15,8 @@ import com.fruitshorts.creator.vo.CreatorAuditReqVO;
|
||||
import com.fruitshorts.creator.vo.CreatorQueryReqVO;
|
||||
import com.fruitshorts.framework.log.OperationLog;
|
||||
import com.fruitshorts.framework.security.SecurityUtils;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
@@ -29,6 +31,7 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
import java.util.List;
|
||||
|
||||
/** 后台创作者:检索、详情、资质、入驻审核。 */
|
||||
@Tag(name = "创作者管理")
|
||||
@RestController
|
||||
@RequestMapping("/admin/creators")
|
||||
@RequiredArgsConstructor
|
||||
@@ -37,12 +40,14 @@ public class CreatorAdminController {
|
||||
private final CreatorService creatorService;
|
||||
private final CreatorAccountService creatorAccountService;
|
||||
|
||||
@Operation(summary = "创作者分页检索")
|
||||
@GetMapping("/page")
|
||||
@PreAuthorize("@ss.hasPermission('creator:list')")
|
||||
public Result<PageResult<Creator>> page(CreatorQueryReqVO req) {
|
||||
return Result.ok(creatorService.page(req));
|
||||
}
|
||||
|
||||
@Operation(summary = "创作者详情")
|
||||
@GetMapping("/{id}")
|
||||
@PreAuthorize("@ss.hasPermission('creator:list')")
|
||||
public Result<Creator> detail(@PathVariable Long id) {
|
||||
@@ -50,12 +55,14 @@ public class CreatorAdminController {
|
||||
}
|
||||
|
||||
/** 资质文件:审核前要看证件原件。 */
|
||||
@Operation(summary = "资质文件(审核前查看证件原件)")
|
||||
@GetMapping("/{id}/documents")
|
||||
@PreAuthorize("@ss.hasPermission('creator:list')")
|
||||
public Result<List<CreatorDocument>> documents(@PathVariable Long id) {
|
||||
return Result.ok(creatorService.documents(id));
|
||||
}
|
||||
|
||||
@Operation(summary = "入驻审核(通过/驳回/冻结)")
|
||||
@PutMapping("/{id}/audit")
|
||||
@PreAuthorize("@ss.hasPermission('creator:audit')")
|
||||
@OperationLog(module = "创作者管理", action = "入驻审核")
|
||||
@@ -64,6 +71,7 @@ public class CreatorAdminController {
|
||||
}
|
||||
|
||||
/** 手工录入创作者主体(C 端申请入驻还没实现,先用它打通链路)。 */
|
||||
@Operation(summary = "手工录入创作者主体(C 端申请未实现前的打通用口)")
|
||||
@PostMapping
|
||||
@PreAuthorize("@ss.hasPermission('creator:audit')")
|
||||
@OperationLog(module = "创作者管理", action = "新增创作者")
|
||||
@@ -72,6 +80,7 @@ public class CreatorAdminController {
|
||||
}
|
||||
|
||||
/** 开通创作者账号:仅审核通过可开;已开通则幂等返回,不重复建号。 */
|
||||
@Operation(summary = "开通创作者账号(仅审核通过可开,幂等)")
|
||||
@PostMapping("/{id}/account")
|
||||
@PreAuthorize("@ss.hasPermission('creator:account')")
|
||||
@OperationLog(module = "创作者管理", action = "开通创作者账号")
|
||||
@@ -81,6 +90,7 @@ public class CreatorAdminController {
|
||||
}
|
||||
|
||||
/** 重置创作者账号密码:一次性明文返回,旧密码立即失效。 */
|
||||
@Operation(summary = "重置创作者账号密码(一次性明文返回)")
|
||||
@PostMapping("/{id}/account/reset-password")
|
||||
@PreAuthorize("@ss.hasPermission('creator:account')")
|
||||
@OperationLog(module = "创作者管理", action = "重置创作者密码")
|
||||
|
||||
+9
@@ -11,6 +11,8 @@ import com.fruitshorts.creator.vo.CreatorCenterNoticeVO;
|
||||
import com.fruitshorts.creator.vo.CreatorCenterProfileVO;
|
||||
import com.fruitshorts.creator.vo.CreatorCenterTargetVO;
|
||||
import com.fruitshorts.admin.service.CreatorDashboardService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
@@ -28,6 +30,7 @@ import java.util.Map;
|
||||
* 归属由 {@link CreatorCenterService#requireCurrentCreator()} 从登录态解析,
|
||||
* 查询强制带 `where creator_id = 当前创作者`;访问他人作品统一 403。
|
||||
*/
|
||||
@Tag(name = "创作者中心")
|
||||
@RestController
|
||||
@RequestMapping("/admin/creator-center")
|
||||
@RequiredArgsConstructor
|
||||
@@ -37,6 +40,7 @@ public class CreatorCenterController {
|
||||
private final CreatorDashboardService creatorDashboardService;
|
||||
|
||||
/** 当前创作者的主体信息与入驻状态。 */
|
||||
@Operation(summary = "当前创作者的主体信息与入驻状态")
|
||||
@GetMapping("/profile")
|
||||
@PreAuthorize("@ss.hasPermission('creator-center:view')")
|
||||
public Result<CreatorCenterProfileVO> profile() {
|
||||
@@ -44,6 +48,7 @@ public class CreatorCenterController {
|
||||
}
|
||||
|
||||
/** 我的作品列表(含最近一次提交的审核进度)。 */
|
||||
@Operation(summary = "我的作品列表(含最近一次提交的审核进度)")
|
||||
@GetMapping("/dramas/page")
|
||||
@PreAuthorize("@ss.hasPermission('creator-center:view')")
|
||||
public Result<PageResult<CreatorCenterDramaVO>> pageMyDramas(CreatorCenterDramaQueryReqVO req) {
|
||||
@@ -51,6 +56,7 @@ public class CreatorCenterController {
|
||||
}
|
||||
|
||||
/** 我的作品详情:id 是别人的作品时返回 403,不区分"不存在"。 */
|
||||
@Operation(summary = "我的作品详情(他人作品返回 403)")
|
||||
@GetMapping("/dramas/{id}")
|
||||
@PreAuthorize("@ss.hasPermission('creator-center:view')")
|
||||
public Result<CreatorCenterDramaVO> myDrama(@PathVariable Long id) {
|
||||
@@ -58,6 +64,7 @@ public class CreatorCenterController {
|
||||
}
|
||||
|
||||
/** 我的通知:入驻审核结果 + 我提交内容的审核结果。 */
|
||||
@Operation(summary = "我的通知(入驻审核 + 内容审核结果)")
|
||||
@GetMapping("/notices")
|
||||
@PreAuthorize("@ss.hasPermission('creator-center:view')")
|
||||
public Result<List<CreatorCenterNoticeVO>> notices() {
|
||||
@@ -65,6 +72,7 @@ public class CreatorCenterController {
|
||||
}
|
||||
|
||||
/** 我的数据看板:播放 / 完播 / 收藏 / 评论 / 解锁收入概览(只读,只含自己的作品)。 */
|
||||
@Operation(summary = "我的数据看板(播放/完播/收藏/评论/解锁收入,只读)")
|
||||
@GetMapping("/dashboard")
|
||||
@PreAuthorize("@ss.hasPermission('creator-center:stat:view')")
|
||||
public Result<Map<String, Object>> dashboard() {
|
||||
@@ -75,6 +83,7 @@ public class CreatorCenterController {
|
||||
* 代看目标下拉的数据源:只有带 `creator-center:impersonate` 的账号(第一阶段 = 超管)能调。
|
||||
* 前端拿它渲染顶部的「当前创作者」下拉;没权限的账号不显示下拉,也不会请求这个接口。
|
||||
*/
|
||||
@Operation(summary = "代看目标下拉数据源(仅持 creator-center:impersonate 可调)")
|
||||
@GetMapping("/impersonation/targets")
|
||||
@PreAuthorize("@ss.hasPermission('creator-center:impersonate')")
|
||||
public Result<List<CreatorCenterTargetVO>> impersonationTargets() {
|
||||
|
||||
+16
@@ -14,6 +14,8 @@ import com.fruitshorts.creator.vo.CreatorDramaEditReqVO;
|
||||
import com.fruitshorts.creator.vo.CreatorEpisodeReqVO;
|
||||
import com.fruitshorts.creator.vo.CreatorSubmitReqVO;
|
||||
import com.fruitshorts.framework.log.OperationLog;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
@@ -34,6 +36,7 @@ import java.util.List;
|
||||
* 与 {@link CreatorCenterController} 一样**不接收 creatorId**:归属由登录态解析,
|
||||
* 服务层强制 `where creator_id = 当前创作者`,改别人的剧或分集一律 403。
|
||||
*/
|
||||
@Tag(name = "创作者作品")
|
||||
@RestController
|
||||
@RequestMapping("/admin/creator-center")
|
||||
@RequiredArgsConstructor
|
||||
@@ -42,6 +45,7 @@ public class CreatorContentController {
|
||||
private final CreatorContentService creatorContentService;
|
||||
|
||||
/** 新建草稿。 */
|
||||
@Operation(summary = "新建作品草稿")
|
||||
@PostMapping("/dramas")
|
||||
@PreAuthorize("@ss.hasPermission('creator-center:drama:edit')")
|
||||
@OperationLog(module = "创作者中心", action = "新建作品")
|
||||
@@ -50,6 +54,7 @@ public class CreatorContentController {
|
||||
}
|
||||
|
||||
/** 编辑作品信息(仅草稿 / 已下线可改)。 */
|
||||
@Operation(summary = "编辑作品信息(仅草稿/已下线可改)")
|
||||
@PutMapping("/dramas/{id}")
|
||||
@PreAuthorize("@ss.hasPermission('creator-center:drama:edit')")
|
||||
@OperationLog(module = "创作者中心", action = "编辑作品")
|
||||
@@ -59,6 +64,7 @@ public class CreatorContentController {
|
||||
}
|
||||
|
||||
/** 分集列表。 */
|
||||
@Operation(summary = "分集列表")
|
||||
@GetMapping("/dramas/{id}/episodes")
|
||||
@PreAuthorize("@ss.hasPermission('creator-center:view')")
|
||||
public Result<List<EpisodeRespVO>> listEpisodes(@PathVariable Long id) {
|
||||
@@ -66,6 +72,7 @@ public class CreatorContentController {
|
||||
}
|
||||
|
||||
/** 新增分集(集号不传自动排到最后)。 */
|
||||
@Operation(summary = "新增分集(不传集号自动排到最后)")
|
||||
@PostMapping("/dramas/{id}/episodes")
|
||||
@PreAuthorize("@ss.hasPermission('creator-center:drama:edit')")
|
||||
@OperationLog(module = "创作者中心", action = "新增分集")
|
||||
@@ -74,6 +81,7 @@ public class CreatorContentController {
|
||||
}
|
||||
|
||||
/** 编辑分集(时长 / 封面 / 片源 / 排序)。 */
|
||||
@Operation(summary = "编辑分集(时长/封面/片源/排序)")
|
||||
@PutMapping("/dramas/{id}/episodes/{episodeId}")
|
||||
@PreAuthorize("@ss.hasPermission('creator-center:drama:edit')")
|
||||
@OperationLog(module = "创作者中心", action = "编辑分集")
|
||||
@@ -84,6 +92,7 @@ public class CreatorContentController {
|
||||
}
|
||||
|
||||
/** 删除分集。 */
|
||||
@Operation(summary = "删除分集")
|
||||
@DeleteMapping("/dramas/{id}/episodes/{episodeId}")
|
||||
@PreAuthorize("@ss.hasPermission('creator-center:drama:edit')")
|
||||
@OperationLog(module = "创作者中心", action = "删除分集")
|
||||
@@ -93,6 +102,7 @@ public class CreatorContentController {
|
||||
}
|
||||
|
||||
/** 批量排序:body 里按新顺序给出分集 id。 */
|
||||
@Operation(summary = "批量排序分集")
|
||||
@PutMapping("/dramas/{id}/episodes/sort")
|
||||
@PreAuthorize("@ss.hasPermission('creator-center:drama:edit')")
|
||||
@OperationLog(module = "创作者中心", action = "调整分集顺序")
|
||||
@@ -102,6 +112,7 @@ public class CreatorContentController {
|
||||
}
|
||||
|
||||
/** 提交审核:CREATE / UPDATE / PUBLISH / OFFLINE。 */
|
||||
@Operation(summary = "提交审核(CREATE/UPDATE/PUBLISH/OFFLINE)")
|
||||
@PostMapping("/dramas/{id}/submit")
|
||||
@PreAuthorize("@ss.hasPermission('creator-center:drama:edit')")
|
||||
@OperationLog(module = "创作者中心", action = "提交审核")
|
||||
@@ -110,6 +121,7 @@ public class CreatorContentController {
|
||||
}
|
||||
|
||||
/** 撤回自己的提交(撤回后作品退回草稿,可继续编辑)。 */
|
||||
@Operation(summary = "撤回提交(撤回后作品退回草稿)")
|
||||
@PostMapping("/submissions/{id}/withdraw")
|
||||
@PreAuthorize("@ss.hasPermission('creator-center:drama:edit')")
|
||||
@OperationLog(module = "创作者中心", action = "撤回提交")
|
||||
@@ -118,6 +130,7 @@ public class CreatorContentController {
|
||||
}
|
||||
|
||||
/** 我的提交历史(审核进度)。 */
|
||||
@Operation(summary = "我的提交历史(审核进度)")
|
||||
@GetMapping("/dramas/{id}/submissions")
|
||||
@PreAuthorize("@ss.hasPermission('creator-center:view')")
|
||||
public Result<List<ContentSubmission>> listSubmissions(@PathVariable Long id) {
|
||||
@@ -125,6 +138,7 @@ public class CreatorContentController {
|
||||
}
|
||||
|
||||
/** 把上传好的视频产物挂到自己的分集上(产物必须是本人上传的)。 */
|
||||
@Operation(summary = "挂载分集视频产物(产物必须是本人上传)")
|
||||
@PostMapping("/dramas/{id}/episodes/{episodeId}/attach")
|
||||
@PreAuthorize("@ss.hasPermission('creator-center:upload')")
|
||||
@OperationLog(module = "创作者中心", action = "挂载分集视频")
|
||||
@@ -135,6 +149,7 @@ public class CreatorContentController {
|
||||
}
|
||||
|
||||
/** 分集收费与试看秒数:读现状。 */
|
||||
@Operation(summary = "分集收费与试看秒数:读取")
|
||||
@GetMapping("/dramas/{id}/prices")
|
||||
@PreAuthorize("@ss.hasPermission('creator-center:view')")
|
||||
public Result<PriceRespVO> priceDetail(@PathVariable Long id) {
|
||||
@@ -142,6 +157,7 @@ public class CreatorContentController {
|
||||
}
|
||||
|
||||
/** 分集收费与试看秒数:保存(复用后台同一套 PriceService,改完立即影响付费判定)。 */
|
||||
@Operation(summary = "分集收费与试看秒数:保存(改完立即影响付费判定)")
|
||||
@PutMapping("/dramas/{id}/prices")
|
||||
@PreAuthorize("@ss.hasPermission('creator-center:price:update')")
|
||||
@OperationLog(module = "创作者中心", action = "配置分集价格")
|
||||
|
||||
+5
@@ -4,6 +4,8 @@ package com.fruitshorts.admin.controller;
|
||||
|
||||
import com.fruitshorts.admin.service.DashboardService;
|
||||
import com.fruitshorts.common.pojo.Result;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
@@ -18,6 +20,7 @@ import java.util.Map;
|
||||
* 指标口径写在 DashboardService 的类注释与 docs/api-phase1.md 里;
|
||||
* 取不到数据源的指标返回 null 并在 notes 里说明,不用 0 冒充。
|
||||
*/
|
||||
@Tag(name = "数据看板")
|
||||
@RestController
|
||||
@RequestMapping("/admin/dashboard")
|
||||
@RequiredArgsConstructor
|
||||
@@ -26,6 +29,7 @@ public class DashboardAdminController {
|
||||
private final DashboardService dashboardService;
|
||||
|
||||
/** 总览:用户 / 内容 / 播放 / 收入 / 成本。 */
|
||||
@Operation(summary = "总览:用户/内容/播放/收入/成本")
|
||||
@GetMapping("/overview")
|
||||
@PreAuthorize("@ss.hasPermission('dashboard:view')")
|
||||
public Result<Map<String, Object>> overview() {
|
||||
@@ -33,6 +37,7 @@ public class DashboardAdminController {
|
||||
}
|
||||
|
||||
/** 转码看板:队列积压与失败任务明细。 */
|
||||
@Operation(summary = "转码看板:队列积压与失败任务明细")
|
||||
@GetMapping("/transcode")
|
||||
@PreAuthorize("@ss.hasPermission('dashboard:view')")
|
||||
public Result<Map<String, Object>> transcode() {
|
||||
|
||||
+5
@@ -6,6 +6,8 @@ import com.fruitshorts.common.pojo.Result;
|
||||
import com.fruitshorts.content.enums.ContentStatus;
|
||||
import com.fruitshorts.content.service.DramaCategoryService;
|
||||
import com.fruitshorts.content.vo.DramaCategoryRespVO;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
@@ -19,6 +21,7 @@ import java.util.Map;
|
||||
/**
|
||||
* 字典接口:题材、内容状态等下拉数据。
|
||||
*/
|
||||
@Tag(name = "数据字典")
|
||||
@RestController
|
||||
@RequestMapping("/admin/dicts")
|
||||
@RequiredArgsConstructor
|
||||
@@ -26,12 +29,14 @@ public class DictController {
|
||||
|
||||
private final DramaCategoryService dramaCategoryService;
|
||||
|
||||
@Operation(summary = "题材字典(下拉数据)")
|
||||
@GetMapping("/drama-category")
|
||||
@PreAuthorize("@ss.hasPermission('drama:list')")
|
||||
public Result<List<DramaCategoryRespVO>> dramaCategories() {
|
||||
return Result.ok(dramaCategoryService.list());
|
||||
}
|
||||
|
||||
@Operation(summary = "内容状态字典")
|
||||
@GetMapping("/content-status")
|
||||
@PreAuthorize("@ss.hasPermission('drama:list')")
|
||||
public Result<List<Map<String, String>>> contentStatus() {
|
||||
|
||||
+7
@@ -8,6 +8,8 @@ import com.fruitshorts.framework.log.OperationLog;
|
||||
import com.fruitshorts.playback.service.DownloadService;
|
||||
import com.fruitshorts.playback.vo.DownloadLicenseRespVO;
|
||||
import com.fruitshorts.playback.vo.DownloadQueryReqVO;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
@@ -20,6 +22,7 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
import java.util.Map;
|
||||
|
||||
/** 后台下载授权管理。 */
|
||||
@Tag(name = "下载管理")
|
||||
@RestController
|
||||
@RequestMapping("/admin/downloads")
|
||||
@RequiredArgsConstructor
|
||||
@@ -27,12 +30,14 @@ public class DownloadAdminController {
|
||||
|
||||
private final DownloadService downloadService;
|
||||
|
||||
@Operation(summary = "下载授权分页检索(含剧名与集号)")
|
||||
@GetMapping("/page")
|
||||
@PreAuthorize("@ss.hasPermission('download:list')")
|
||||
public Result<PageResult<DownloadLicenseRespVO>> page(DownloadQueryReqVO req) {
|
||||
return Result.ok(downloadService.page(req));
|
||||
}
|
||||
|
||||
@Operation(summary = "授权与任务分布统计")
|
||||
@GetMapping("/stats")
|
||||
@PreAuthorize("@ss.hasPermission('download:list')")
|
||||
public Result<Map<String, Object>> stats() {
|
||||
@@ -40,6 +45,7 @@ public class DownloadAdminController {
|
||||
}
|
||||
|
||||
/** 吊销单条授权:用户侧下次联网即失效。 */
|
||||
@Operation(summary = "吊销授权(用户侧下次联网即失效)")
|
||||
@PutMapping("/{id}/revoke")
|
||||
@PreAuthorize("@ss.hasPermission('download:revoke')")
|
||||
@OperationLog(module = "下载管理", action = "吊销下载授权")
|
||||
@@ -49,6 +55,7 @@ public class DownloadAdminController {
|
||||
}
|
||||
|
||||
/** 手动触发过期清理,正常情况下由定时任务每天执行。 */
|
||||
@Operation(summary = "手动清理过期授权(默认每天凌晨自动执行)")
|
||||
@PostMapping("/cleanup")
|
||||
@PreAuthorize("@ss.hasPermission('download:revoke')")
|
||||
@OperationLog(module = "下载管理", action = "清理过期下载授权")
|
||||
|
||||
+7
@@ -8,6 +8,8 @@ import com.fruitshorts.content.vo.DramaCategoryRespVO;
|
||||
import com.fruitshorts.content.vo.DramaCategorySaveReqVO;
|
||||
import com.fruitshorts.framework.security.SecurityUtils;
|
||||
import com.fruitshorts.framework.log.OperationLog;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
@@ -25,6 +27,7 @@ import java.util.List;
|
||||
/**
|
||||
* 短剧类型管理。类型属于短剧域,权限沿用 drama:*,不再单开权限点。
|
||||
*/
|
||||
@Tag(name = "短剧类型")
|
||||
@RestController
|
||||
@RequestMapping("/admin/drama-categories")
|
||||
@RequiredArgsConstructor
|
||||
@@ -32,12 +35,14 @@ public class DramaCategoryController {
|
||||
|
||||
private final DramaCategoryService dramaCategoryService;
|
||||
|
||||
@Operation(summary = "短剧类型列表")
|
||||
@GetMapping
|
||||
@PreAuthorize("@ss.hasPermission('drama:list')")
|
||||
public Result<List<DramaCategoryRespVO>> list() {
|
||||
return Result.ok(dramaCategoryService.list());
|
||||
}
|
||||
|
||||
@Operation(summary = "新增短剧类型")
|
||||
@PostMapping
|
||||
@PreAuthorize("@ss.hasPermission('drama:create')")
|
||||
@OperationLog(module = "内容管理", action = "新增短剧类型")
|
||||
@@ -45,6 +50,7 @@ public class DramaCategoryController {
|
||||
return Result.ok(dramaCategoryService.create(req));
|
||||
}
|
||||
|
||||
@Operation(summary = "编辑短剧类型")
|
||||
@PutMapping("/{id}")
|
||||
@PreAuthorize("@ss.hasPermission('drama:update')")
|
||||
@OperationLog(module = "内容管理", action = "编辑短剧类型")
|
||||
@@ -53,6 +59,7 @@ public class DramaCategoryController {
|
||||
return Result.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "删除短剧类型")
|
||||
@DeleteMapping("/{id}")
|
||||
@PreAuthorize("@ss.hasPermission('drama:delete')")
|
||||
@OperationLog(module = "内容管理", action = "删除短剧类型")
|
||||
|
||||
+14
@@ -12,6 +12,8 @@ import com.fruitshorts.content.vo.DramaSaveReqVO;
|
||||
import com.fruitshorts.content.vo.DramaStatusReqVO;
|
||||
import com.fruitshorts.framework.security.SecurityUtils;
|
||||
import com.fruitshorts.framework.log.OperationLog;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
@@ -26,6 +28,7 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Tag(name = "短剧管理")
|
||||
@RestController
|
||||
@RequestMapping("/admin/dramas")
|
||||
@RequiredArgsConstructor
|
||||
@@ -33,18 +36,21 @@ public class DramaController {
|
||||
|
||||
private final DramaService dramaService;
|
||||
|
||||
@Operation(summary = "短剧分页检索(含热门、状态筛选)")
|
||||
@GetMapping("/page")
|
||||
@PreAuthorize("@ss.hasPermission('drama:list')")
|
||||
public Result<PageResult<DramaRespVO>> page(DramaPageReqVO req) {
|
||||
return Result.ok(dramaService.page(req));
|
||||
}
|
||||
|
||||
@Operation(summary = "短剧详情")
|
||||
@GetMapping("/{id}")
|
||||
@PreAuthorize("@ss.hasPermission('drama:list')")
|
||||
public Result<DramaRespVO> get(@PathVariable Long id) {
|
||||
return Result.ok(dramaService.get(id));
|
||||
}
|
||||
|
||||
@Operation(summary = "新建短剧")
|
||||
@PostMapping
|
||||
@PreAuthorize("@ss.hasPermission('drama:create')")
|
||||
@OperationLog(module = "内容管理", action = "新建短剧")
|
||||
@@ -52,6 +58,7 @@ public class DramaController {
|
||||
return Result.ok(dramaService.create(req, SecurityUtils.getUserId()));
|
||||
}
|
||||
|
||||
@Operation(summary = "编辑短剧")
|
||||
@PutMapping("/{id}")
|
||||
@PreAuthorize("@ss.hasPermission('drama:update')")
|
||||
@OperationLog(module = "内容管理", action = "编辑短剧")
|
||||
@@ -60,6 +67,7 @@ public class DramaController {
|
||||
return Result.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "删除短剧")
|
||||
@DeleteMapping("/{id}")
|
||||
@PreAuthorize("@ss.hasPermission('drama:delete')")
|
||||
@OperationLog(module = "内容管理", action = "删除短剧")
|
||||
@@ -69,6 +77,7 @@ public class DramaController {
|
||||
}
|
||||
|
||||
/** 提交审核:内容运营即可操作。 */
|
||||
@Operation(summary = "提交审核")
|
||||
@PostMapping("/{id}/submit")
|
||||
@PreAuthorize("@ss.hasAnyPermission('drama:review','drama:update')")
|
||||
@OperationLog(module = "内容管理", action = "提交审核")
|
||||
@@ -77,6 +86,7 @@ public class DramaController {
|
||||
return Result.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "审核通过")
|
||||
@PostMapping("/{id}/approve")
|
||||
@PreAuthorize("@ss.hasPermission('drama:review')")
|
||||
@OperationLog(module = "内容管理", action = "审核通过")
|
||||
@@ -85,6 +95,7 @@ public class DramaController {
|
||||
return Result.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "驳回短剧")
|
||||
@PostMapping("/{id}/reject")
|
||||
@PreAuthorize("@ss.hasPermission('drama:review')")
|
||||
@OperationLog(module = "内容管理", action = "驳回短剧")
|
||||
@@ -93,6 +104,7 @@ public class DramaController {
|
||||
return Result.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "短剧上线")
|
||||
@PostMapping("/{id}/publish")
|
||||
@PreAuthorize("@ss.hasPermission('drama:review')")
|
||||
@OperationLog(module = "内容管理", action = "短剧上线")
|
||||
@@ -101,6 +113,7 @@ public class DramaController {
|
||||
return Result.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "短剧下线")
|
||||
@PostMapping("/{id}/offline")
|
||||
@PreAuthorize("@ss.hasPermission('drama:review')")
|
||||
@OperationLog(module = "内容管理", action = "短剧下线")
|
||||
@@ -109,6 +122,7 @@ public class DramaController {
|
||||
return Result.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "审核记录")
|
||||
@GetMapping("/{id}/review-records")
|
||||
@PreAuthorize("@ss.hasPermission('drama:list')")
|
||||
public Result<List<DramaReviewRecord>> reviewRecords(@PathVariable Long id) {
|
||||
|
||||
+6
@@ -8,6 +8,8 @@ import com.fruitshorts.commerce.vo.EntitlementGrantReqVO;
|
||||
import com.fruitshorts.common.pojo.PageResult;
|
||||
import com.fruitshorts.common.pojo.Result;
|
||||
import com.fruitshorts.framework.log.OperationLog;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
@@ -21,6 +23,7 @@ import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/** 后台权益:检索、人工补发、回收。 */
|
||||
@Tag(name = "权益管理")
|
||||
@RestController
|
||||
@RequestMapping("/admin/entitlements")
|
||||
@RequiredArgsConstructor
|
||||
@@ -28,6 +31,7 @@ public class EntitlementAdminController {
|
||||
|
||||
private final EntitlementService entitlementService;
|
||||
|
||||
@Operation(summary = "权益分页检索")
|
||||
@GetMapping("/page")
|
||||
@PreAuthorize("@ss.hasPermission('entitlement:list')")
|
||||
public Result<PageResult<Entitlement>> page(@RequestParam(required = false) Long userId,
|
||||
@@ -39,6 +43,7 @@ public class EntitlementAdminController {
|
||||
}
|
||||
|
||||
/** 客服补偿:直接给用户某集/整剧的播放权益。 */
|
||||
@Operation(summary = "人工补发权益(客服补偿)")
|
||||
@PostMapping
|
||||
@PreAuthorize("@ss.hasPermission('entitlement:update')")
|
||||
@OperationLog(module = "订单管理", action = "人工补发权益")
|
||||
@@ -50,6 +55,7 @@ public class EntitlementAdminController {
|
||||
}
|
||||
|
||||
/** 回收权益:退款、违规处置后用。 */
|
||||
@Operation(summary = "回收权益(退款/违规处置用,播放判定实时生效)")
|
||||
@PutMapping("/{id}/revoke")
|
||||
@PreAuthorize("@ss.hasPermission('entitlement:update')")
|
||||
@OperationLog(module = "订单管理", action = "回收权益")
|
||||
|
||||
+8
@@ -8,6 +8,8 @@ import com.fruitshorts.content.vo.EpisodeRespVO;
|
||||
import com.fruitshorts.content.vo.EpisodeSaveReqVO;
|
||||
import com.fruitshorts.content.vo.EpisodeSortReqVO;
|
||||
import com.fruitshorts.framework.log.OperationLog;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
@@ -23,6 +25,7 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Tag(name = "剧集管理")
|
||||
@RestController
|
||||
@RequestMapping("/admin/episodes")
|
||||
@RequiredArgsConstructor
|
||||
@@ -30,6 +33,7 @@ public class EpisodeController {
|
||||
|
||||
private final EpisodeService episodeService;
|
||||
|
||||
@Operation(summary = "某剧分集列表")
|
||||
@GetMapping
|
||||
@PreAuthorize("@ss.hasPermission('episode:list')")
|
||||
public Result<List<EpisodeRespVO>> list(@RequestParam Long dramaId,
|
||||
@@ -37,6 +41,7 @@ public class EpisodeController {
|
||||
return Result.ok(episodeService.listByDrama(dramaId, status));
|
||||
}
|
||||
|
||||
@Operation(summary = "新增分集")
|
||||
@PostMapping
|
||||
@PreAuthorize("@ss.hasPermission('episode:upload')")
|
||||
@OperationLog(module = "内容管理", action = "新增剧集")
|
||||
@@ -44,6 +49,7 @@ public class EpisodeController {
|
||||
return Result.ok(episodeService.create(req));
|
||||
}
|
||||
|
||||
@Operation(summary = "编辑分集")
|
||||
@PutMapping("/{id}")
|
||||
@PreAuthorize("@ss.hasPermission('episode:upload')")
|
||||
@OperationLog(module = "内容管理", action = "编辑剧集")
|
||||
@@ -52,6 +58,7 @@ public class EpisodeController {
|
||||
return Result.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "删除分集")
|
||||
@DeleteMapping("/{id}")
|
||||
@PreAuthorize("@ss.hasPermission('episode:upload')")
|
||||
@OperationLog(module = "内容管理", action = "删除剧集")
|
||||
@@ -60,6 +67,7 @@ public class EpisodeController {
|
||||
return Result.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "批量排序分集")
|
||||
@PutMapping("/sort")
|
||||
@PreAuthorize("@ss.hasPermission('episode:sort')")
|
||||
@OperationLog(module = "内容管理", action = "调整剧集顺序")
|
||||
|
||||
+8
@@ -11,6 +11,8 @@ 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 io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
@@ -26,6 +28,7 @@ import org.springframework.web.multipart.MultipartFile;
|
||||
/**
|
||||
* 媒资上传(本地存储版):init 建会话 → chunk 传分片 → complete 合并出地址。
|
||||
*/
|
||||
@Tag(name = "媒资上传")
|
||||
@RestController
|
||||
@RequestMapping("/admin/media")
|
||||
@RequiredArgsConstructor
|
||||
@@ -33,6 +36,7 @@ public class MediaController {
|
||||
|
||||
private final MediaService mediaService;
|
||||
|
||||
@Operation(summary = "建上传会话(返回 uploadId / chunkSize / totalChunks)")
|
||||
@PostMapping("/upload/init")
|
||||
@PreAuthorize("@ss.hasAnyPermission('cover:upload','episode:upload')")
|
||||
public Result<UploadInitRespVO> init(@Valid @RequestBody UploadInitReqVO req) {
|
||||
@@ -41,6 +45,7 @@ public class MediaController {
|
||||
return Result.ok(mediaService.init(req, SecurityUtils.getUserId()));
|
||||
}
|
||||
|
||||
@Operation(summary = "上传分片(可重复传同一片)")
|
||||
@PostMapping("/upload/chunk")
|
||||
@PreAuthorize("@ss.hasAnyPermission('cover:upload','episode:upload')")
|
||||
public Result<Integer> uploadChunk(@RequestParam String uploadId,
|
||||
@@ -51,6 +56,7 @@ public class MediaController {
|
||||
return Result.ok(index);
|
||||
}
|
||||
|
||||
@Operation(summary = "合并分片出媒资(同一 uploadId 幂等)")
|
||||
@PostMapping("/upload/complete")
|
||||
@PreAuthorize("@ss.hasAnyPermission('cover:upload','episode:upload')")
|
||||
public Result<MediaAssetRespVO> complete(@Valid @RequestBody UploadCompleteReqVO req) {
|
||||
@@ -59,12 +65,14 @@ public class MediaController {
|
||||
}
|
||||
|
||||
/** 断点续传:查上传会话进度(只能查自己发起的会话)。 */
|
||||
@Operation(summary = "断点续传进度查询(只能查自己发起的会话)")
|
||||
@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()));
|
||||
}
|
||||
|
||||
@Operation(summary = "媒资详情")
|
||||
@GetMapping("/{id}")
|
||||
@PreAuthorize("@ss.hasAnyPermission('cover:upload','episode:upload')")
|
||||
public Result<MediaAssetRespVO> get(@PathVariable Long id) {
|
||||
|
||||
+7
@@ -7,6 +7,8 @@ import com.fruitshorts.system.service.MenuService;
|
||||
import com.fruitshorts.framework.log.OperationLog;
|
||||
import com.fruitshorts.system.vo.MenuSaveReqVO;
|
||||
import com.fruitshorts.system.vo.MenuVO;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
@@ -21,6 +23,7 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Tag(name = "菜单管理")
|
||||
@RestController
|
||||
@RequestMapping("/admin/menus")
|
||||
@RequiredArgsConstructor
|
||||
@@ -28,12 +31,14 @@ public class MenuController {
|
||||
|
||||
private final MenuService menuService;
|
||||
|
||||
@Operation(summary = "菜单树")
|
||||
@GetMapping("/tree")
|
||||
@PreAuthorize("@ss.hasPermission('system:menu')")
|
||||
public Result<List<MenuVO>> tree() {
|
||||
return Result.ok(menuService.listAll());
|
||||
}
|
||||
|
||||
@Operation(summary = "新增菜单")
|
||||
@PostMapping
|
||||
@PreAuthorize("@ss.hasPermission('system:menu')")
|
||||
@OperationLog(module = "后台管理", action = "新增菜单")
|
||||
@@ -41,6 +46,7 @@ public class MenuController {
|
||||
return Result.ok(menuService.create(req));
|
||||
}
|
||||
|
||||
@Operation(summary = "编辑菜单")
|
||||
@PutMapping("/{id}")
|
||||
@PreAuthorize("@ss.hasPermission('system:menu')")
|
||||
@OperationLog(module = "后台管理", action = "编辑菜单")
|
||||
@@ -49,6 +55,7 @@ public class MenuController {
|
||||
return Result.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "删除菜单")
|
||||
@DeleteMapping("/{id}")
|
||||
@PreAuthorize("@ss.hasPermission('system:menu')")
|
||||
@OperationLog(module = "后台管理", action = "删除菜单")
|
||||
|
||||
+5
@@ -7,6 +7,8 @@ import com.fruitshorts.common.pojo.Result;
|
||||
import com.fruitshorts.system.service.OperationLogService;
|
||||
import com.fruitshorts.system.vo.OperationLogPageReqVO;
|
||||
import com.fruitshorts.system.vo.OperationLogRespVO;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
@@ -14,6 +16,7 @@ import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@Tag(name = "操作日志")
|
||||
@RestController
|
||||
@RequestMapping("/admin/operation-logs")
|
||||
@RequiredArgsConstructor
|
||||
@@ -21,12 +24,14 @@ public class OperationLogController {
|
||||
|
||||
private final OperationLogService operationLogService;
|
||||
|
||||
@Operation(summary = "操作日志分页检索")
|
||||
@GetMapping("/page")
|
||||
@PreAuthorize("@ss.hasPermission('log:list')")
|
||||
public Result<PageResult<OperationLogRespVO>> page(OperationLogPageReqVO req) {
|
||||
return Result.ok(operationLogService.page(req));
|
||||
}
|
||||
|
||||
@Operation(summary = "操作日志详情")
|
||||
@GetMapping("/{id}")
|
||||
@PreAuthorize("@ss.hasPermission('log:list')")
|
||||
public Result<OperationLogRespVO> get(@PathVariable Long id) {
|
||||
|
||||
+8
@@ -10,6 +10,8 @@ import com.fruitshorts.common.pojo.PageResult;
|
||||
import com.fruitshorts.common.pojo.Result;
|
||||
import com.fruitshorts.framework.log.OperationLog;
|
||||
import com.fruitshorts.framework.security.SecurityUtils;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
@@ -24,6 +26,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/** 后台订单:检索、补发、退款回收。 */
|
||||
@Tag(name = "订单管理")
|
||||
@RestController
|
||||
@RequestMapping("/admin/orders")
|
||||
@RequiredArgsConstructor
|
||||
@@ -31,12 +34,14 @@ public class OrderAdminController {
|
||||
|
||||
private final OrderService orderService;
|
||||
|
||||
@Operation(summary = "订单分页检索")
|
||||
@GetMapping("/page")
|
||||
@PreAuthorize("@ss.hasPermission('order:list')")
|
||||
public Result<PageResult<Orders>> page(OrderQueryReqVO req) {
|
||||
return Result.ok(orderService.page(req));
|
||||
}
|
||||
|
||||
@Operation(summary = "订单详情")
|
||||
@GetMapping("/{orderNo}")
|
||||
@PreAuthorize("@ss.hasPermission('order:list')")
|
||||
public Result<Orders> detail(@PathVariable String orderNo) {
|
||||
@@ -44,6 +49,7 @@ public class OrderAdminController {
|
||||
}
|
||||
|
||||
/** 订单状态流转流水:支付争议时的证据链。 */
|
||||
@Operation(summary = "订单状态流转流水(支付争议证据链)")
|
||||
@GetMapping("/{orderNo}/events")
|
||||
@PreAuthorize("@ss.hasPermission('order:list')")
|
||||
public Result<List<OrderEvent>> events(@PathVariable String orderNo) {
|
||||
@@ -51,6 +57,7 @@ public class OrderAdminController {
|
||||
}
|
||||
|
||||
/** 补发:已支付未交付的订单重新交付;已交付时幂等返回。 */
|
||||
@Operation(summary = "订单补发(已交付时幂等返回)")
|
||||
@PostMapping("/{orderNo}/compensate")
|
||||
@PreAuthorize("@ss.hasPermission('order:update')")
|
||||
@OperationLog(module = "订单管理", action = "补发订单")
|
||||
@@ -59,6 +66,7 @@ public class OrderAdminController {
|
||||
}
|
||||
|
||||
/** 退款/撤销:回收权益并扣回金币。 */
|
||||
@Operation(summary = "订单退款/撤销(回收权益并扣回金币)")
|
||||
@PostMapping("/{orderNo}/refund")
|
||||
@PreAuthorize("@ss.hasPermission('order:update')")
|
||||
@OperationLog(module = "订单管理", action = "订单退款")
|
||||
|
||||
+4
@@ -5,6 +5,8 @@ package com.fruitshorts.admin.controller;
|
||||
import com.fruitshorts.common.pojo.Result;
|
||||
import com.fruitshorts.system.service.PermissionService;
|
||||
import com.fruitshorts.system.vo.PermissionGroupVO;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
@@ -13,6 +15,7 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Tag(name = "权限管理")
|
||||
@RestController
|
||||
@RequestMapping("/admin/permissions")
|
||||
@RequiredArgsConstructor
|
||||
@@ -21,6 +24,7 @@ public class PermissionController {
|
||||
private final PermissionService permissionService;
|
||||
|
||||
/** 按分组返回权限点,直接喂给前端的角色权限配置页。 */
|
||||
@Operation(summary = "权限点分组列表(角色权限配置页用)")
|
||||
@GetMapping
|
||||
@PreAuthorize("@ss.hasPermission('system:role')")
|
||||
public Result<List<PermissionGroupVO>> groups() {
|
||||
|
||||
+5
@@ -7,6 +7,8 @@ import com.fruitshorts.content.service.PriceService;
|
||||
import com.fruitshorts.content.vo.PriceRespVO;
|
||||
import com.fruitshorts.content.vo.PriceSaveReqVO;
|
||||
import com.fruitshorts.framework.log.OperationLog;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
@@ -17,6 +19,7 @@ import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/** 后台分集价格与免费集配置。 */
|
||||
@Tag(name = "分集价格")
|
||||
@RestController
|
||||
@RequestMapping("/admin/prices")
|
||||
@RequiredArgsConstructor
|
||||
@@ -25,12 +28,14 @@ public class PriceAdminController {
|
||||
private final PriceService priceService;
|
||||
|
||||
/** 当前价格配置:整剧默认 + 分集明细。 */
|
||||
@Operation(summary = "当前价格配置:整剧默认 + 分集明细")
|
||||
@GetMapping
|
||||
@PreAuthorize("@ss.hasPermission('price:update')")
|
||||
public Result<PriceRespVO> detail(@RequestParam Long dramaId) {
|
||||
return Result.ok(priceService.detail(dramaId));
|
||||
}
|
||||
|
||||
@Operation(summary = "保存价格配置(改价立即影响播放与下载判定)")
|
||||
@PutMapping
|
||||
@PreAuthorize("@ss.hasPermission('price:update')")
|
||||
@OperationLog(module = "定价管理", action = "配置分集价格")
|
||||
|
||||
+5
@@ -7,6 +7,8 @@ import com.fruitshorts.commerce.service.ReconcileService;
|
||||
import com.fruitshorts.common.pojo.PageResult;
|
||||
import com.fruitshorts.common.pojo.Result;
|
||||
import com.fruitshorts.framework.log.OperationLog;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
@@ -18,6 +20,7 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
import java.time.LocalDate;
|
||||
|
||||
/** 后台对账:手动触发与历史查看。 */
|
||||
@Tag(name = "对账管理")
|
||||
@RestController
|
||||
@RequestMapping("/admin/reconcile")
|
||||
@RequiredArgsConstructor
|
||||
@@ -25,6 +28,7 @@ public class ReconcileAdminController {
|
||||
|
||||
private final ReconcileService reconcileService;
|
||||
|
||||
@Operation(summary = "对账历史分页")
|
||||
@GetMapping("/page")
|
||||
@PreAuthorize("@ss.hasPermission('order:list')")
|
||||
public Result<PageResult<ReconcileTask>> page(@RequestParam(defaultValue = "1") Integer pageIndex,
|
||||
@@ -33,6 +37,7 @@ public class ReconcileAdminController {
|
||||
}
|
||||
|
||||
/** 手动对账:默认前一天,可指定日期与渠道。 */
|
||||
@Operation(summary = "手动对账(默认前一天,可指定日期与渠道)")
|
||||
@PostMapping("/run")
|
||||
@PreAuthorize("@ss.hasPermission('reconcile:run')")
|
||||
@OperationLog(module = "订单管理", action = "手动对账")
|
||||
|
||||
+5
@@ -10,6 +10,8 @@ import com.fruitshorts.interaction.dal.entity.ContentReport;
|
||||
import com.fruitshorts.interaction.service.ReportService;
|
||||
import com.fruitshorts.interaction.vo.ReportHandleReqVO;
|
||||
import com.fruitshorts.interaction.vo.ReportQueryReqVO;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
@@ -20,6 +22,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/** 后台举报工单。 */
|
||||
@Tag(name = "举报工单")
|
||||
@RestController
|
||||
@RequestMapping("/admin/reports")
|
||||
@RequiredArgsConstructor
|
||||
@@ -27,6 +30,7 @@ public class ReportAdminController {
|
||||
|
||||
private final ReportService reportService;
|
||||
|
||||
@Operation(summary = "举报工单检索(状态/类型/原因)")
|
||||
@GetMapping("/page")
|
||||
@PreAuthorize("@ss.hasPermission('report:list')")
|
||||
public Result<PageResult<ContentReport>> page(ReportQueryReqVO req) {
|
||||
@@ -34,6 +38,7 @@ public class ReportAdminController {
|
||||
}
|
||||
|
||||
/** 处理工单:结论成立会联动驳回被举报评论,可选择同时封禁被举报用户。 */
|
||||
@Operation(summary = "处理工单(结论成立联动驳回被举报评论,可选择同时封禁用户)")
|
||||
@PutMapping("/{id}/handle")
|
||||
@PreAuthorize("@ss.hasPermission('report:handle')")
|
||||
@OperationLog(module = "内容治理", action = "处理举报")
|
||||
|
||||
+7
@@ -7,6 +7,8 @@ import com.fruitshorts.system.service.RoleCategoryService;
|
||||
import com.fruitshorts.framework.log.OperationLog;
|
||||
import com.fruitshorts.system.vo.RoleCategoryRespVO;
|
||||
import com.fruitshorts.system.vo.RoleCategorySaveReqVO;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
@@ -21,6 +23,7 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Tag(name = "角色分类")
|
||||
@RestController
|
||||
@RequestMapping("/admin/role-categories")
|
||||
@RequiredArgsConstructor
|
||||
@@ -28,12 +31,14 @@ public class RoleCategoryController {
|
||||
|
||||
private final RoleCategoryService roleCategoryService;
|
||||
|
||||
@Operation(summary = "角色分类列表")
|
||||
@GetMapping
|
||||
@PreAuthorize("@ss.hasPermission('system:role-category')")
|
||||
public Result<List<RoleCategoryRespVO>> list() {
|
||||
return Result.ok(roleCategoryService.list());
|
||||
}
|
||||
|
||||
@Operation(summary = "新增角色分类")
|
||||
@PostMapping
|
||||
@PreAuthorize("@ss.hasPermission('system:role-category')")
|
||||
@OperationLog(module = "后台管理", action = "新增角色分类")
|
||||
@@ -41,6 +46,7 @@ public class RoleCategoryController {
|
||||
return Result.ok(roleCategoryService.create(req));
|
||||
}
|
||||
|
||||
@Operation(summary = "编辑角色分类")
|
||||
@PutMapping("/{id}")
|
||||
@PreAuthorize("@ss.hasPermission('system:role-category')")
|
||||
@OperationLog(module = "后台管理", action = "编辑角色分类")
|
||||
@@ -49,6 +55,7 @@ public class RoleCategoryController {
|
||||
return Result.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "删除角色分类")
|
||||
@DeleteMapping("/{id}")
|
||||
@PreAuthorize("@ss.hasPermission('system:role-category')")
|
||||
@OperationLog(module = "后台管理", action = "删除角色分类")
|
||||
|
||||
+11
@@ -9,6 +9,8 @@ import com.fruitshorts.framework.log.OperationLog;
|
||||
import com.fruitshorts.system.vo.RolePermissionSaveReqVO;
|
||||
import com.fruitshorts.system.vo.RoleRespVO;
|
||||
import com.fruitshorts.system.vo.RoleSaveReqVO;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
@@ -24,6 +26,7 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Tag(name = "角色管理")
|
||||
@RestController
|
||||
@RequestMapping("/admin/roles")
|
||||
@RequiredArgsConstructor
|
||||
@@ -31,6 +34,7 @@ public class RoleController {
|
||||
|
||||
private final RoleService roleService;
|
||||
|
||||
@Operation(summary = "角色分页检索")
|
||||
@GetMapping("/page")
|
||||
@PreAuthorize("@ss.hasPermission('system:role')")
|
||||
public Result<PageResult<RoleRespVO>> page(@RequestParam(required = false) String keyword,
|
||||
@@ -39,17 +43,20 @@ public class RoleController {
|
||||
return Result.ok(roleService.page(keyword, pageIndex, pageSize));
|
||||
}
|
||||
|
||||
@Operation(summary = "角色全量列表")
|
||||
@GetMapping("/list")
|
||||
public Result<List<RoleRespVO>> list() {
|
||||
return Result.ok(roleService.listAll());
|
||||
}
|
||||
|
||||
@Operation(summary = "角色详情")
|
||||
@GetMapping("/{id}")
|
||||
@PreAuthorize("@ss.hasPermission('system:role')")
|
||||
public Result<RoleRespVO> get(@PathVariable Long id) {
|
||||
return Result.ok(roleService.get(id));
|
||||
}
|
||||
|
||||
@Operation(summary = "新增角色")
|
||||
@PostMapping
|
||||
@PreAuthorize("@ss.hasPermission('system:role')")
|
||||
@OperationLog(module = "后台管理", action = "新增角色")
|
||||
@@ -57,6 +64,7 @@ public class RoleController {
|
||||
return Result.ok(roleService.create(req));
|
||||
}
|
||||
|
||||
@Operation(summary = "编辑角色")
|
||||
@PutMapping("/{id}")
|
||||
@PreAuthorize("@ss.hasPermission('system:role')")
|
||||
@OperationLog(module = "后台管理", action = "编辑角色")
|
||||
@@ -65,6 +73,7 @@ public class RoleController {
|
||||
return Result.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "删除角色")
|
||||
@DeleteMapping("/{id}")
|
||||
@PreAuthorize("@ss.hasPermission('system:role')")
|
||||
@OperationLog(module = "后台管理", action = "删除角色")
|
||||
@@ -73,12 +82,14 @@ public class RoleController {
|
||||
return Result.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "查询角色权限码")
|
||||
@GetMapping("/{id}/permissions")
|
||||
@PreAuthorize("@ss.hasPermission('system:role')")
|
||||
public Result<List<String>> permissions(@PathVariable Long id) {
|
||||
return Result.ok(roleService.listCodesByRoleId(id));
|
||||
}
|
||||
|
||||
@Operation(summary = "保存角色权限")
|
||||
@PutMapping("/{id}/permissions")
|
||||
@PreAuthorize("@ss.hasPermission('system:role')")
|
||||
@OperationLog(module = "后台管理", action = "修改角色权限")
|
||||
|
||||
+7
@@ -8,6 +8,8 @@ import com.fruitshorts.framework.log.OperationLog;
|
||||
import com.fruitshorts.interaction.dal.entity.SensitiveWord;
|
||||
import com.fruitshorts.interaction.service.SensitiveWordService;
|
||||
import com.fruitshorts.interaction.vo.SensitiveWordReqVO;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
@@ -22,6 +24,7 @@ import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/** 后台敏感词库。改动即时生效(服务端词库缓存会失效重建)。 */
|
||||
@Tag(name = "敏感词")
|
||||
@RestController
|
||||
@RequestMapping("/admin/sensitive-words")
|
||||
@RequiredArgsConstructor
|
||||
@@ -29,6 +32,7 @@ public class SensitiveWordAdminController {
|
||||
|
||||
private final SensitiveWordService sensitiveWordService;
|
||||
|
||||
@Operation(summary = "敏感词分页检索")
|
||||
@GetMapping("/page")
|
||||
@PreAuthorize("@ss.hasPermission('sensitive-word:list')")
|
||||
public Result<PageResult<SensitiveWord>> page(@RequestParam(required = false) String keyword,
|
||||
@@ -39,6 +43,7 @@ public class SensitiveWordAdminController {
|
||||
return Result.ok(sensitiveWordService.page(keyword, category, level, pageIndex, pageSize));
|
||||
}
|
||||
|
||||
@Operation(summary = "新增敏感词")
|
||||
@PostMapping
|
||||
@PreAuthorize("@ss.hasPermission('sensitive-word:update')")
|
||||
@OperationLog(module = "内容治理", action = "新增敏感词")
|
||||
@@ -46,6 +51,7 @@ public class SensitiveWordAdminController {
|
||||
return Result.ok(sensitiveWordService.create(req));
|
||||
}
|
||||
|
||||
@Operation(summary = "修改敏感词")
|
||||
@PutMapping("/{id}")
|
||||
@PreAuthorize("@ss.hasPermission('sensitive-word:update')")
|
||||
@OperationLog(module = "内容治理", action = "修改敏感词")
|
||||
@@ -54,6 +60,7 @@ public class SensitiveWordAdminController {
|
||||
return Result.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "删除敏感词")
|
||||
@DeleteMapping("/{id}")
|
||||
@PreAuthorize("@ss.hasPermission('sensitive-word:update')")
|
||||
@OperationLog(module = "内容治理", action = "删除敏感词")
|
||||
|
||||
+6
@@ -10,6 +10,8 @@ import com.fruitshorts.creator.vo.SubmissionAuditReqVO;
|
||||
import com.fruitshorts.creator.vo.SubmissionQueryReqVO;
|
||||
import com.fruitshorts.framework.log.OperationLog;
|
||||
import com.fruitshorts.framework.security.SecurityUtils;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
@@ -20,6 +22,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/** 后台内容提交审核:检索、详情、审核(通过 / 驳回 / 撤回)。 */
|
||||
@Tag(name = "内容提交审核")
|
||||
@RestController
|
||||
@RequestMapping("/admin/submissions")
|
||||
@RequiredArgsConstructor
|
||||
@@ -27,18 +30,21 @@ public class SubmissionAdminController {
|
||||
|
||||
private final ContentSubmissionService submissionService;
|
||||
|
||||
@Operation(summary = "内容提交分页检索")
|
||||
@GetMapping("/page")
|
||||
@PreAuthorize("@ss.hasPermission('submission:list')")
|
||||
public Result<PageResult<ContentSubmission>> page(SubmissionQueryReqVO req) {
|
||||
return Result.ok(submissionService.page(req));
|
||||
}
|
||||
|
||||
@Operation(summary = "内容提交详情")
|
||||
@GetMapping("/{id}")
|
||||
@PreAuthorize("@ss.hasPermission('submission:list')")
|
||||
public Result<ContentSubmission> detail(@PathVariable Long id) {
|
||||
return Result.ok(submissionService.getExisting(id));
|
||||
}
|
||||
|
||||
@Operation(summary = "审核内容提交(通过后按类型落短剧状态机)")
|
||||
@PutMapping("/{id}/audit")
|
||||
@PreAuthorize("@ss.hasPermission('submission:audit')")
|
||||
@OperationLog(module = "内容审核", action = "提交审核")
|
||||
|
||||
+5
@@ -11,6 +11,8 @@ import com.fruitshorts.common.pojo.Result;
|
||||
import com.fruitshorts.framework.log.OperationLog;
|
||||
import com.fruitshorts.framework.security.SecurityUtils;
|
||||
import com.fruitshorts.user.dal.mapper.AppUserMapper;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
@@ -25,6 +27,7 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
import java.util.List;
|
||||
|
||||
/** 后台钱包:人工补币/扣回,全部进流水且必须带幂等键。 */
|
||||
@Tag(name = "钱包管理")
|
||||
@RestController
|
||||
@RequestMapping("/admin/wallets")
|
||||
@RequiredArgsConstructor
|
||||
@@ -33,6 +36,7 @@ public class WalletAdminController {
|
||||
private final WalletService walletService;
|
||||
private final AppUserMapper appUserMapper;
|
||||
|
||||
@Operation(summary = "金币流水查询")
|
||||
@GetMapping("/{userId}/ledger")
|
||||
@PreAuthorize("@ss.hasPermission('order:list')")
|
||||
public Result<List<CoinLedger>> ledger(@PathVariable Long userId,
|
||||
@@ -40,6 +44,7 @@ public class WalletAdminController {
|
||||
return Result.ok(walletService.recentLedger(userId, limit));
|
||||
}
|
||||
|
||||
@Operation(summary = "人工补币/扣回(必须带幂等键,先校验用户存在)")
|
||||
@PostMapping("/coins")
|
||||
@PreAuthorize("@ss.hasPermission('wallet:update')")
|
||||
@OperationLog(module = "订单管理", action = "人工补币")
|
||||
|
||||
+13
@@ -2,6 +2,7 @@
|
||||
|
||||
package com.fruitshorts.admin.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
@@ -15,18 +16,30 @@ import java.time.LocalDateTime;
|
||||
@Data
|
||||
public class AppUserWatchHistoryVO {
|
||||
|
||||
@Schema(description = "ID")
|
||||
private Long id;
|
||||
@Schema(description = "短剧 ID")
|
||||
private Long dramaId;
|
||||
@Schema(description = "剧名")
|
||||
private String dramaTitle;
|
||||
/** 短剧当前是否已上线,用于识别"用户说看了但剧已下线"的情况 */
|
||||
@Schema(description = "短剧当前是否已上线")
|
||||
private Boolean dramaPublished;
|
||||
@Schema(description = "剧集 ID")
|
||||
private Long episodeId;
|
||||
@Schema(description = "集号")
|
||||
private Integer episodeNo;
|
||||
@Schema(description = "播放进度(毫秒)")
|
||||
private Long positionMs;
|
||||
@Schema(description = "时长(毫秒)")
|
||||
private Long durationMs;
|
||||
/** 是否已看完(进度到达片尾 1 秒内) */
|
||||
@Schema(description = "是否已看完")
|
||||
private Boolean finished;
|
||||
@Schema(description = "来源")
|
||||
private String source;
|
||||
@Schema(description = "设备 ID")
|
||||
private String deviceId;
|
||||
@Schema(description = "观看时间")
|
||||
private LocalDateTime watchedAt;
|
||||
}
|
||||
@@ -53,3 +53,15 @@ springdoc:
|
||||
logging:
|
||||
level:
|
||||
com.fruitshorts: debug
|
||||
|
||||
management:
|
||||
endpoints:
|
||||
web:
|
||||
exposure:
|
||||
include: prometheus,health
|
||||
endpoint:
|
||||
health:
|
||||
show-details: always
|
||||
metrics:
|
||||
tags:
|
||||
application: ${spring.application.name}
|
||||
+8
@@ -13,6 +13,8 @@ import com.fruitshorts.user.vo.OtpSendReqVO;
|
||||
import com.fruitshorts.user.vo.RefreshReqVO;
|
||||
import com.fruitshorts.user.vo.RegisterReqVO;
|
||||
import com.fruitshorts.user.vo.TokenRespVO;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@@ -22,6 +24,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/** 客户端账号:验证码、注册、登录、刷新、登出。 */
|
||||
@Tag(name = "账号")
|
||||
@RestController
|
||||
@RequestMapping("/app/auth")
|
||||
@RequiredArgsConstructor
|
||||
@@ -31,30 +34,35 @@ public class AppAuthController {
|
||||
private final AppAuthService authService;
|
||||
|
||||
/** 发送验证码。频控在服务端,客户端不需要自己限流。 */
|
||||
@Operation(summary = "发送验证码(注册/登录/找回密码,服务端频控)")
|
||||
@PostMapping("/otp")
|
||||
public Result<Void> sendOtp(@Valid @RequestBody OtpSendReqVO req, HttpServletRequest request) {
|
||||
otpService.send(req, WebUtils.getClientIp(request));
|
||||
return Result.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "注册账号(手机号/邮箱 + 验证码),返回令牌")
|
||||
@PostMapping("/register")
|
||||
public Result<TokenRespVO> register(@Valid @RequestBody RegisterReqVO req,
|
||||
HttpServletRequest request) {
|
||||
return Result.ok(authService.register(req, WebUtils.getClientIp(request)));
|
||||
}
|
||||
|
||||
@Operation(summary = "登录(验证码或密码),返回令牌")
|
||||
@PostMapping("/login")
|
||||
public Result<TokenRespVO> login(@Valid @RequestBody LoginReqVO req,
|
||||
HttpServletRequest request) {
|
||||
return Result.ok(authService.login(req, WebUtils.getClientIp(request)));
|
||||
}
|
||||
|
||||
@Operation(summary = "刷新令牌(refresh token 轮换)")
|
||||
@PostMapping("/refresh")
|
||||
public Result<TokenRespVO> refresh(@Valid @RequestBody RefreshReqVO req) {
|
||||
return Result.ok(authService.refresh(req.getRefreshToken()));
|
||||
}
|
||||
|
||||
/** 登出:默认只吊销当前设备的会话,allDevices=true 时吊销全部。 */
|
||||
@Operation(summary = "登出(allDevices=true 时吊销全部设备会话)")
|
||||
@PostMapping("/logout")
|
||||
public Result<Void> logout(@RequestBody(required = false) LogoutReqVO req) {
|
||||
authService.logout(SecurityUtils.getUserIdOrNull(), req == null ? new LogoutReqVO() : req);
|
||||
|
||||
+6
@@ -6,6 +6,8 @@ import com.fruitshorts.app.service.AppCatalogService;
|
||||
import com.fruitshorts.app.vo.AppCategoryVO;
|
||||
import com.fruitshorts.app.vo.AppFeedVO;
|
||||
import com.fruitshorts.common.pojo.Result;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
@@ -16,6 +18,7 @@ import java.util.List;
|
||||
/**
|
||||
* 客户端目录接口:首页与发现页各一次请求拿全量聚合数据。
|
||||
*/
|
||||
@Tag(name = "内容浏览")
|
||||
@RestController
|
||||
@RequestMapping("/app")
|
||||
@RequiredArgsConstructor
|
||||
@@ -23,16 +26,19 @@ public class AppCatalogController {
|
||||
|
||||
private final AppCatalogService appCatalogService;
|
||||
|
||||
@Operation(summary = "首页聚合数据(轮播 + 分区卡片,卡片带预览集)")
|
||||
@GetMapping("/home/feed")
|
||||
public Result<AppFeedVO> homeFeed() {
|
||||
return Result.ok(appCatalogService.homeFeed());
|
||||
}
|
||||
|
||||
@Operation(summary = "发现页聚合数据")
|
||||
@GetMapping("/discover/feed")
|
||||
public Result<AppFeedVO> discoverFeed() {
|
||||
return Result.ok(appCatalogService.discoverFeed());
|
||||
}
|
||||
|
||||
@Operation(summary = "分类列表")
|
||||
@GetMapping("/categories")
|
||||
public Result<List<AppCategoryVO>> categories() {
|
||||
return Result.ok(appCatalogService.categories());
|
||||
|
||||
+6
@@ -10,6 +10,8 @@ import com.fruitshorts.interaction.service.CommentService;
|
||||
import com.fruitshorts.interaction.vo.CommentPublishReqVO;
|
||||
import com.fruitshorts.interaction.vo.CommentQueryReqVO;
|
||||
import com.fruitshorts.interaction.vo.CommentRespVO;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@@ -29,6 +31,7 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
* 不传 `rootId` 时返回顶层评论,传了则返回该楼层的回复。
|
||||
* 列表允许匿名浏览;发布与删除需要登录。
|
||||
*/
|
||||
@Tag(name = "评论")
|
||||
@RestController
|
||||
@RequestMapping("/app/comments")
|
||||
@RequiredArgsConstructor
|
||||
@@ -36,6 +39,7 @@ public class AppCommentController {
|
||||
|
||||
private final CommentService commentService;
|
||||
|
||||
@Operation(summary = "发表评论或回复(敏感词处置后按策略发布或转待审)")
|
||||
@PostMapping
|
||||
public Result<CommentRespVO> publish(@Valid @RequestBody CommentPublishReqVO req,
|
||||
HttpServletRequest request) {
|
||||
@@ -43,6 +47,7 @@ public class AppCommentController {
|
||||
WebUtils.getClientIp(request), request.getHeader("X-Device-Id")));
|
||||
}
|
||||
|
||||
@Operation(summary = "评论列表(游标翻页;不传 rootId 为顶层评论,传了为楼层回复)")
|
||||
@GetMapping
|
||||
public Result<CursorResult<CommentRespVO>> page(@RequestParam Long dramaId,
|
||||
@RequestParam(required = false) Long episodeId,
|
||||
@@ -58,6 +63,7 @@ public class AppCommentController {
|
||||
return Result.ok(commentService.page(SecurityUtils.getUserIdOrNull(), query));
|
||||
}
|
||||
|
||||
@Operation(summary = "删除自己的评论(逻辑删除)")
|
||||
@DeleteMapping("/{id}")
|
||||
public Result<Void> delete(@PathVariable Long id) {
|
||||
commentService.delete(SecurityUtils.getAppUserId(), id);
|
||||
|
||||
+7
@@ -8,6 +8,8 @@ import com.fruitshorts.commerce.service.UnlockService;
|
||||
import com.fruitshorts.commerce.service.WalletService;
|
||||
import com.fruitshorts.common.pojo.Result;
|
||||
import com.fruitshorts.framework.security.SecurityUtils;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
@@ -26,6 +28,7 @@ import java.util.Map;
|
||||
* 金币解锁是第一阶段真实的收费方式;真实商店购买走 {@code /app/orders/verify},
|
||||
* 本轮只预留接口(商店未接入时返回明确业务提示,不会产生假订单)。
|
||||
*/
|
||||
@Tag(name = "金币与订单")
|
||||
@RestController
|
||||
@RequestMapping("/app")
|
||||
@RequiredArgsConstructor
|
||||
@@ -36,6 +39,7 @@ public class AppCommerceController {
|
||||
private final OrderService orderService;
|
||||
|
||||
/** 我的钱包:余额 + 最近流水,客户端一处渲染。 */
|
||||
@Operation(summary = "我的钱包:金币余额 + 最近流水")
|
||||
@GetMapping("/wallet")
|
||||
public Result<Map<String, Object>> wallet() {
|
||||
Long userId = SecurityUtils.getAppUserId();
|
||||
@@ -46,17 +50,20 @@ public class AppCommerceController {
|
||||
}
|
||||
|
||||
/** 金币解锁分集:幂等,重复点击不会重复扣币。 */
|
||||
@Operation(summary = "金币解锁分集(幂等,重复调用不重复扣币)")
|
||||
@PostMapping("/episodes/{episodeId}/unlock")
|
||||
public Result<Map<String, Object>> unlock(@PathVariable Long episodeId) {
|
||||
return Result.ok(unlockService.unlock(SecurityUtils.getAppUserId(), episodeId));
|
||||
}
|
||||
|
||||
@Operation(summary = "我的订单列表")
|
||||
@GetMapping("/orders")
|
||||
public Result<List<Orders>> orders() {
|
||||
return Result.ok(orderService.listByUser(SecurityUtils.getAppUserId()));
|
||||
}
|
||||
|
||||
/** 提交商店票据。第一阶段商店未接入,会返回明确的"尚未配置"。 */
|
||||
@Operation(summary = "提交商店票据(IAP/Google Play;商店未接入时返回明确业务提示)")
|
||||
@PostMapping("/orders/verify")
|
||||
public Result<Orders> verify(@RequestBody Map<String, String> body) {
|
||||
return Result.ok(orderService.verifyAndDeliver(SecurityUtils.getAppUserId(),
|
||||
|
||||
+11
@@ -10,6 +10,8 @@ import com.fruitshorts.playback.vo.DownloadLicenseRespVO;
|
||||
import com.fruitshorts.playback.vo.DownloadPolicyRespVO;
|
||||
import com.fruitshorts.playback.vo.DownloadProgressReqVO;
|
||||
import com.fruitshorts.playback.vo.DownloadSettingReqVO;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@@ -31,6 +33,7 @@ import java.util.List;
|
||||
* <p>服务端只发授权与地址,分片由客户端向 CDN 拉取;进度上报用于断点续传与跨端展示。
|
||||
* 设备标识优先取请求体,其次取请求头 X-Device-Id。
|
||||
*/
|
||||
@Tag(name = "离线下载")
|
||||
@RestController
|
||||
@RequestMapping("/app/downloads")
|
||||
@RequiredArgsConstructor
|
||||
@@ -39,6 +42,7 @@ public class AppDownloadController {
|
||||
private final DownloadService downloadService;
|
||||
|
||||
/** 申请下载授权(同一剧集重复申请幂等,只刷新有效期)。 */
|
||||
@Operation(summary = "申请下载授权(同剧集重复申请幂等,只刷新有效期)")
|
||||
@PostMapping
|
||||
public Result<DownloadLicenseRespVO> grant(@Valid @RequestBody DownloadGrantReqVO req,
|
||||
HttpServletRequest request) {
|
||||
@@ -46,17 +50,20 @@ public class AppDownloadController {
|
||||
request.getHeader("X-Device-Id")));
|
||||
}
|
||||
|
||||
@Operation(summary = "下载列表(授权 + 任务进度,可直接渲染)")
|
||||
@GetMapping
|
||||
public Result<List<DownloadLicenseRespVO>> list(@RequestParam(required = false) String deviceId) {
|
||||
return Result.ok(downloadService.list(SecurityUtils.getAppUserId(), deviceId));
|
||||
}
|
||||
|
||||
@Operation(summary = "下载策略与配额(单设备上限/授权天数/仅 Wi-Fi/清晰度上限)")
|
||||
@GetMapping("/policy")
|
||||
public Result<DownloadPolicyRespVO> policy(@RequestParam(required = false) String deviceId) {
|
||||
return Result.ok(downloadService.policy(SecurityUtils.getAppUserId(), deviceId));
|
||||
}
|
||||
|
||||
/** 仅 Wi-Fi 下载、清晰度上限等偏好。 */
|
||||
@Operation(summary = "更新下载偏好(仅 Wi-Fi 下载、最高清晰度)")
|
||||
@PutMapping("/settings")
|
||||
public Result<Void> updateSettings(@RequestBody DownloadSettingReqVO req) {
|
||||
downloadService.updateSettings(SecurityUtils.getAppUserId(), req);
|
||||
@@ -64,6 +71,7 @@ public class AppDownloadController {
|
||||
}
|
||||
|
||||
/** 断点续传前重新取一次地址:授权不变,只有地址是短时效的。 */
|
||||
@Operation(summary = "断点续传前重新获取下载地址(授权不变,地址短时效)")
|
||||
@GetMapping("/{episodeId}/url")
|
||||
public Result<DownloadLicenseRespVO> refreshUrl(@PathVariable Long episodeId,
|
||||
HttpServletRequest request) {
|
||||
@@ -71,6 +79,7 @@ public class AppDownloadController {
|
||||
request.getHeader("X-Device-Id")));
|
||||
}
|
||||
|
||||
@Operation(summary = "上报下载进度(用于断点续传与跨端展示)")
|
||||
@PostMapping("/{episodeId}/progress")
|
||||
public Result<DownloadLicenseRespVO> reportProgress(@PathVariable Long episodeId,
|
||||
@RequestBody DownloadProgressReqVO req,
|
||||
@@ -79,6 +88,7 @@ public class AppDownloadController {
|
||||
request.getHeader("X-Device-Id")));
|
||||
}
|
||||
|
||||
@Operation(summary = "删除单条下载(吊销授权)")
|
||||
@DeleteMapping("/{episodeId}")
|
||||
public Result<Void> revoke(@PathVariable Long episodeId,
|
||||
@RequestParam(required = false) String deviceId,
|
||||
@@ -89,6 +99,7 @@ public class AppDownloadController {
|
||||
}
|
||||
|
||||
/** 清空当前设备的全部下载授权。 */
|
||||
@Operation(summary = "清空当前设备全部下载(返回清除条数)")
|
||||
@DeleteMapping
|
||||
public Result<Integer> clear(@RequestParam(required = false) String deviceId,
|
||||
HttpServletRequest request) {
|
||||
|
||||
+5
@@ -9,6 +9,8 @@ import com.fruitshorts.framework.security.SecurityUtils;
|
||||
import com.fruitshorts.framework.web.WebUtils;
|
||||
import com.fruitshorts.playback.service.PlaybackService;
|
||||
import com.fruitshorts.playback.vo.PlayRespVO;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
@@ -16,6 +18,7 @@ import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@Tag(name = "短剧与播放")
|
||||
@RestController
|
||||
@RequestMapping("/app")
|
||||
@RequiredArgsConstructor
|
||||
@@ -25,6 +28,7 @@ public class AppDramaController {
|
||||
private final PlaybackService playbackService;
|
||||
|
||||
/** 详情:包含剧集列表,客户端进详情页一次请求即可渲染 */
|
||||
@Operation(summary = "短剧详情(含剧集列表,免费集带已签名播放地址)")
|
||||
@GetMapping("/dramas/{id}")
|
||||
public Result<AppDramaDetailVO> detail(@PathVariable Long id) {
|
||||
return Result.ok(appCatalogService.dramaDetail(id));
|
||||
@@ -34,6 +38,7 @@ public class AppDramaController {
|
||||
* 播放票据:服务端判定权益后签发短时效播放地址。
|
||||
* 未登录也能播免费集;付费集未解锁时只返回需要多少金币。
|
||||
*/
|
||||
@Operation(summary = "签发播放票据与签名地址(服务端判定权益:免费/已购/需解锁/无片源)")
|
||||
@GetMapping("/episodes/{id}/play")
|
||||
public Result<PlayRespVO> play(@PathVariable Long id, HttpServletRequest request) {
|
||||
return Result.ok(playbackService.play(
|
||||
|
||||
+6
@@ -8,6 +8,8 @@ import com.fruitshorts.common.pojo.Result;
|
||||
import com.fruitshorts.framework.security.SecurityUtils;
|
||||
import com.fruitshorts.playback.service.FavoriteService;
|
||||
import com.fruitshorts.playback.vo.FavoriteToggleReqVO;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
@@ -21,6 +23,7 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
import java.util.List;
|
||||
|
||||
/** 收藏。 */
|
||||
@Tag(name = "收藏")
|
||||
@RestController
|
||||
@RequestMapping("/app/favorites")
|
||||
@RequiredArgsConstructor
|
||||
@@ -30,18 +33,21 @@ public class AppFavoriteController {
|
||||
private final AppCatalogService appCatalogService;
|
||||
|
||||
/** 切换收藏,返回切换后的状态:true 为已收藏。 */
|
||||
@Operation(summary = "切换收藏状态(返回切换后的结果)")
|
||||
@PostMapping("/toggle")
|
||||
public Result<Boolean> toggle(@Valid @RequestBody FavoriteToggleReqVO req) {
|
||||
return Result.ok(favoriteService.toggle(SecurityUtils.getAppUserId(), req.getDramaId()));
|
||||
}
|
||||
|
||||
/** 收藏列表,卡片结构与首页一致。 */
|
||||
@Operation(summary = "收藏列表(卡片结构与首页一致)")
|
||||
@GetMapping
|
||||
public Result<List<AppDramaCardVO>> list() {
|
||||
return Result.ok(appCatalogService.toCards(
|
||||
favoriteService.listDramas(SecurityUtils.getAppUserId())));
|
||||
}
|
||||
|
||||
@Operation(summary = "取消收藏")
|
||||
@DeleteMapping("/{dramaId}")
|
||||
public Result<Void> remove(@PathVariable Long dramaId) {
|
||||
favoriteService.remove(SecurityUtils.getAppUserId(), dramaId);
|
||||
|
||||
+5
@@ -9,6 +9,8 @@ import com.fruitshorts.interaction.service.ReportService;
|
||||
import com.fruitshorts.interaction.vo.LikeToggleReqVO;
|
||||
import com.fruitshorts.interaction.vo.LikeToggleRespVO;
|
||||
import com.fruitshorts.interaction.vo.ReportCreateReqVO;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
@@ -17,6 +19,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/** 点赞与举报。 */
|
||||
@Tag(name = "点赞与举报")
|
||||
@RestController
|
||||
@RequestMapping("/app")
|
||||
@RequiredArgsConstructor
|
||||
@@ -26,12 +29,14 @@ public class AppInteractionController {
|
||||
private final ReportService reportService;
|
||||
|
||||
/** 点赞/取消点赞,返回切换后的状态与最新计数。 */
|
||||
@Operation(summary = "点赞/取消点赞(支持短剧与评论),返回切换后状态与计数")
|
||||
@PostMapping("/likes/toggle")
|
||||
public Result<LikeToggleRespVO> toggleLike(@Valid @RequestBody LikeToggleReqVO req) {
|
||||
return Result.ok(likeService.toggle(SecurityUtils.getAppUserId(), req));
|
||||
}
|
||||
|
||||
/** 提交举报:同一用户对同一目标只保留一条待处理工单。 */
|
||||
@Operation(summary = "提交举报(评论/用户/短剧,同一目标仅保留一条待处理工单)")
|
||||
@PostMapping("/reports")
|
||||
public Result<Long> report(@Valid @RequestBody ReportCreateReqVO req) {
|
||||
return Result.ok(reportService.create(SecurityUtils.getAppUserId(), req));
|
||||
|
||||
@@ -9,6 +9,8 @@ import com.fruitshorts.user.service.AppUserService;
|
||||
import com.fruitshorts.user.vo.AppUserRespVO;
|
||||
import com.fruitshorts.user.vo.DeactivateReqVO;
|
||||
import com.fruitshorts.user.vo.ProfileUpdateReqVO;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
@@ -23,6 +25,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/** 客户端个人中心:资料、设备、注销、数据导出。 */
|
||||
@Tag(name = "个人中心")
|
||||
@RestController
|
||||
@RequestMapping("/app/me")
|
||||
@RequiredArgsConstructor
|
||||
@@ -30,33 +33,39 @@ public class AppMeController {
|
||||
|
||||
private final AppUserService userService;
|
||||
|
||||
@Operation(summary = "获取当前用户资料")
|
||||
@GetMapping
|
||||
public Result<AppUserRespVO> me() {
|
||||
return Result.ok(userService.me(SecurityUtils.getAppUserId()));
|
||||
}
|
||||
|
||||
@Operation(summary = "修改资料(昵称/头像/性别/生日/语言/时区/区域)")
|
||||
@PutMapping
|
||||
public Result<AppUserRespVO> update(@Valid @RequestBody ProfileUpdateReqVO req) {
|
||||
return Result.ok(userService.updateProfile(SecurityUtils.getAppUserId(), req));
|
||||
}
|
||||
|
||||
@Operation(summary = "登录设备列表")
|
||||
@GetMapping("/devices")
|
||||
public Result<List<AppUserDevice>> devices() {
|
||||
return Result.ok(userService.devices(SecurityUtils.getAppUserId()));
|
||||
}
|
||||
|
||||
/** 商店与隐私法规要求的数据导出,返回账号侧数据;内容侧数据由客户端自行下载。 */
|
||||
@Operation(summary = "数据导出(商店与隐私法规要求,返回账号侧数据)")
|
||||
@GetMapping("/export")
|
||||
public Result<Map<String, Object>> export() {
|
||||
return Result.ok(userService.exportAccount(SecurityUtils.getAppUserId()));
|
||||
}
|
||||
|
||||
/** 申请注销:立即登出全部设备,进入冷静期,期间可撤销。 */
|
||||
@Operation(summary = "申请注销(进入冷静期并登出全部设备,期间可撤销)")
|
||||
@PostMapping("/deactivate")
|
||||
public Result<LocalDateTime> deactivate(@RequestBody(required = false) DeactivateReqVO req) {
|
||||
return Result.ok(userService.requestDeactivation(SecurityUtils.getAppUserId(), req));
|
||||
}
|
||||
|
||||
@Operation(summary = "撤销注销申请")
|
||||
@PostMapping("/deactivate/cancel")
|
||||
public Result<Void> cancelDeactivate() {
|
||||
userService.cancelDeactivation(SecurityUtils.getAppUserId());
|
||||
|
||||
+8
@@ -7,6 +7,8 @@ import com.fruitshorts.framework.security.SecurityUtils;
|
||||
import com.fruitshorts.playback.service.WatchProgressService;
|
||||
import com.fruitshorts.playback.vo.ProgressRespVO;
|
||||
import com.fruitshorts.playback.vo.ProgressSaveReqVO;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
@@ -21,6 +23,7 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
import java.util.List;
|
||||
|
||||
/** 观看进度与观看记录。 */
|
||||
@Tag(name = "观看记录")
|
||||
@RestController
|
||||
@RequestMapping("/app/watch")
|
||||
@RequiredArgsConstructor
|
||||
@@ -29,28 +32,33 @@ public class AppWatchController {
|
||||
private final WatchProgressService progressService;
|
||||
|
||||
/** 上报进度:客户端每 10 秒一次,切集时立即上报一次。 */
|
||||
@Operation(summary = "上报观看进度(建议每 10 秒一次,切集时补报)")
|
||||
@PostMapping("/progress")
|
||||
public Result<ProgressRespVO> save(@Valid @RequestBody ProgressSaveReqVO req) {
|
||||
return Result.ok(progressService.save(SecurityUtils.getAppUserId(), req));
|
||||
}
|
||||
|
||||
/** 某部剧的续看位置,进详情页时用它决定"续看第 N 集"。 */
|
||||
@Operation(summary = "查询某部剧的续看位置")
|
||||
@GetMapping("/progress")
|
||||
public Result<ProgressRespVO> ofDrama(@RequestParam Long dramaId) {
|
||||
return Result.ok(progressService.ofDrama(SecurityUtils.getAppUserId(), dramaId));
|
||||
}
|
||||
|
||||
@Operation(summary = "最近观看列表")
|
||||
@GetMapping("/recent")
|
||||
public Result<List<ProgressRespVO>> recent(@RequestParam(defaultValue = "20") int limit) {
|
||||
return Result.ok(progressService.recent(SecurityUtils.getAppUserId(), limit));
|
||||
}
|
||||
|
||||
@Operation(summary = "删除某部剧的观看记录")
|
||||
@DeleteMapping("/progress/{dramaId}")
|
||||
public Result<Void> remove(@PathVariable Long dramaId) {
|
||||
progressService.remove(SecurityUtils.getAppUserId(), dramaId);
|
||||
return Result.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "清空全部观看记录")
|
||||
@DeleteMapping("/progress")
|
||||
public Result<Void> clear() {
|
||||
progressService.clear(SecurityUtils.getAppUserId());
|
||||
|
||||
@@ -168,10 +168,7 @@ public class AppCatalogService {
|
||||
vo.setNumber(episode.getEpNo());
|
||||
vo.setTitle(episode.getTitle());
|
||||
vo.setDurationSec(episode.getDurationSec());
|
||||
int seconds = episode.getDurationSec() == null ? 0 : episode.getDurationSec();
|
||||
vo.setDuration(String.format("%02d:%02d", seconds / 60, seconds % 60));
|
||||
boolean free = episode.getIsFree() != null && episode.getIsFree() == 1;
|
||||
vo.setIsFree(free);
|
||||
vo.setLocked(!free);
|
||||
vo.setUnlockCoin(episode.getUnlockCoin());
|
||||
if (free) {
|
||||
|
||||
@@ -2,15 +2,21 @@
|
||||
|
||||
package com.fruitshorts.app.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class AppBannerVO {
|
||||
|
||||
@Schema(description = "轮播图 ID")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "图片地址")
|
||||
private String imageUrl;
|
||||
/** NONE / DRAMA / URL */
|
||||
|
||||
@Schema(description = "跳转类型:NONE / DRAMA / URL")
|
||||
private String linkType;
|
||||
/** 短剧 ID 或跳转地址 */
|
||||
|
||||
@Schema(description = "跳转目标:短剧 ID 或跳转地址")
|
||||
private String linkValue;
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
package com.fruitshorts.app.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
@@ -9,6 +10,9 @@ import lombok.Data;
|
||||
@AllArgsConstructor
|
||||
public class AppCategoryVO {
|
||||
|
||||
@Schema(description = "分类 ID")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "分类名称")
|
||||
private String name;
|
||||
}
|
||||
@@ -2,24 +2,40 @@
|
||||
|
||||
package com.fruitshorts.app.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/** 列表卡片,用于首页/发现页/分类分区 */
|
||||
@Data
|
||||
public class AppDramaCardVO {
|
||||
|
||||
@Schema(description = "短剧 ID")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "短剧标题")
|
||||
private String title;
|
||||
|
||||
@Schema(description = "封面地址")
|
||||
private String cover;
|
||||
|
||||
@Schema(description = "简介")
|
||||
private String synopsis;
|
||||
|
||||
@Schema(description = "题材")
|
||||
private String genre;
|
||||
|
||||
@Schema(description = "分类名称")
|
||||
private String category;
|
||||
|
||||
@Schema(description = "总集数")
|
||||
private Integer totalEpisodes;
|
||||
|
||||
@Schema(description = "是否热门")
|
||||
private Boolean isHot;
|
||||
|
||||
@Schema(description = "播放量")
|
||||
private Long viewCount;
|
||||
/**
|
||||
* 首个可播免费集。首页竖屏播放需要在列表阶段就能起播,
|
||||
* 带上这一集可以省掉「点开→请求详情→再请求播放地址」的往返。
|
||||
*/
|
||||
|
||||
@Schema(description = "首个可播免费集;首页竖屏播放可直接起播,省去再请求详情/播放地址的往返")
|
||||
private AppEpisodeVO preview;
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
package com.fruitshorts.app.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
@@ -9,16 +10,39 @@ import java.util.List;
|
||||
@Data
|
||||
public class AppDramaDetailVO {
|
||||
|
||||
@Schema(description = "短剧 ID")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "短剧标题")
|
||||
private String title;
|
||||
|
||||
@Schema(description = "简介")
|
||||
private String synopsis;
|
||||
|
||||
@Schema(description = "封面地址")
|
||||
private String cover;
|
||||
|
||||
@Schema(description = "题材")
|
||||
private String genre;
|
||||
|
||||
@Schema(description = "分类名称")
|
||||
private String category;
|
||||
|
||||
@Schema(description = "总集数")
|
||||
private Integer totalEpisodes;
|
||||
|
||||
@Schema(description = "免费集数")
|
||||
private Integer freeEpisodes;
|
||||
|
||||
@Schema(description = "单集解锁所需金币数")
|
||||
private Integer unlockCoin;
|
||||
|
||||
@Schema(description = "是否热门")
|
||||
private Boolean isHot;
|
||||
|
||||
@Schema(description = "播放量")
|
||||
private Long viewCount;
|
||||
|
||||
@Schema(description = "剧集列表")
|
||||
private List<AppEpisodeVO> episodes;
|
||||
}
|
||||
@@ -2,24 +2,30 @@
|
||||
|
||||
package com.fruitshorts.app.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class AppEpisodeVO {
|
||||
|
||||
@Schema(description = "剧集 ID")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "集号(第几集)")
|
||||
private Integer number;
|
||||
|
||||
@Schema(description = "剧集标题")
|
||||
private String title;
|
||||
/** 展示用时长 mm:ss */
|
||||
private String duration;
|
||||
|
||||
@Schema(description = "时长(秒)")
|
||||
private Integer durationSec;
|
||||
private Boolean isFree;
|
||||
/** true 表示需要解锁后才能播放 */
|
||||
|
||||
@Schema(description = "是否锁定,true 表示需要解锁后才能播放")
|
||||
private Boolean locked;
|
||||
|
||||
@Schema(description = "解锁所需金币数")
|
||||
private Integer unlockCoin;
|
||||
/**
|
||||
* 可播放时的地址;锁定或不含片源时为空。
|
||||
* 详情页拿到就能直接播,不必按集再请求一次播放票据。
|
||||
*/
|
||||
|
||||
@Schema(description = "可播放地址;锁定或无片源时为空")
|
||||
private String playUrl;
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
package com.fruitshorts.app.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
@@ -12,6 +13,9 @@ import java.util.List;
|
||||
@AllArgsConstructor
|
||||
public class AppFeedVO {
|
||||
|
||||
@Schema(description = "轮播图列表")
|
||||
private List<AppBannerVO> banners;
|
||||
|
||||
@Schema(description = "分区列表")
|
||||
private List<AppSectionVO> sections;
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
package com.fruitshorts.app.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
@@ -12,8 +13,12 @@ import java.util.List;
|
||||
@AllArgsConstructor
|
||||
public class AppSectionVO {
|
||||
|
||||
/** 分区标识:hot / new / category-{id},客户端可据此做埋点与样式 */
|
||||
@Schema(description = "分区标识:hot / new / category-{id},客户端据此做埋点与样式")
|
||||
private String code;
|
||||
|
||||
@Schema(description = "分区标题")
|
||||
private String title;
|
||||
|
||||
@Schema(description = "分区内短剧列表")
|
||||
private List<AppDramaCardVO> dramas;
|
||||
}
|
||||
@@ -61,3 +61,15 @@ fruitshorts:
|
||||
logging:
|
||||
level:
|
||||
com.fruitshorts: info
|
||||
|
||||
management:
|
||||
endpoints:
|
||||
web:
|
||||
exposure:
|
||||
include: prometheus,health
|
||||
endpoint:
|
||||
health:
|
||||
show-details: always
|
||||
metrics:
|
||||
tags:
|
||||
application: ${spring.application.name}
|
||||
@@ -66,5 +66,15 @@
|
||||
<groupId>org.springdoc</groupId>
|
||||
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 监控:暴露 actuator 指标供 Prometheus 抓取 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.micrometer</groupId>
|
||||
<artifactId>micrometer-registry-prometheus</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
+2
-1
@@ -48,7 +48,8 @@ public class SecurityConfig {
|
||||
"/swagger-ui/**",
|
||||
"/swagger-ui.html",
|
||||
"/v3/api-docs/**",
|
||||
"/actuator/health"
|
||||
"/actuator/health",
|
||||
"/actuator/prometheus"
|
||||
};
|
||||
|
||||
private final JwtAuthenticationFilter jwtAuthenticationFilter;
|
||||
|
||||
+5
@@ -2,6 +2,7 @@
|
||||
|
||||
package com.fruitshorts.commerce.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
@@ -9,15 +10,19 @@ import lombok.Data;
|
||||
@Data
|
||||
public class CoinAdjustReqVO {
|
||||
|
||||
@Schema(description = "用户ID")
|
||||
@NotNull(message = "缺少 userId")
|
||||
private Long userId;
|
||||
|
||||
/** 正数补发、负数扣回 */
|
||||
@Schema(description = "变动金额(正数补发、负数扣回)")
|
||||
@NotNull(message = "缺少变动金额")
|
||||
private Long amount;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String remark;
|
||||
|
||||
/** 幂等键:同一个工单重复提交只生效一次 */
|
||||
@Schema(description = "幂等键")
|
||||
private String idempotentKey;
|
||||
}
|
||||
+6
@@ -2,6 +2,7 @@
|
||||
|
||||
package com.fruitshorts.commerce.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
@@ -9,17 +10,22 @@ import lombok.Data;
|
||||
@Data
|
||||
public class EntitlementGrantReqVO {
|
||||
|
||||
@Schema(description = "用户ID")
|
||||
@NotNull(message = "缺少 userId")
|
||||
private Long userId;
|
||||
|
||||
@Schema(description = "短剧ID")
|
||||
@NotNull(message = "缺少 dramaId")
|
||||
private Long dramaId;
|
||||
|
||||
/** 传 0 表示整剧权益 */
|
||||
@Schema(description = "剧集ID(传 0 表示整剧权益)")
|
||||
private Long episodeId;
|
||||
|
||||
/** EPISODE/DRAMA */
|
||||
@Schema(description = "权益类型(EPISODE/DRAMA)")
|
||||
private String type = "EPISODE";
|
||||
|
||||
@Schema(description = "原因")
|
||||
private String reason;
|
||||
}
|
||||
+12
@@ -2,17 +2,29 @@
|
||||
|
||||
package com.fruitshorts.commerce.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/** 后台订单检索条件。 */
|
||||
@Data
|
||||
public class OrderQueryReqVO {
|
||||
|
||||
@Schema(description = "用户ID")
|
||||
private Long userId;
|
||||
|
||||
@Schema(description = "订单号")
|
||||
private String orderNo;
|
||||
|
||||
/** CREATED/PAID/DELIVERED/REFUNDED/CLOSED */
|
||||
@Schema(description = "状态(CREATED/PAID/DELIVERED/REFUNDED/CLOSED)")
|
||||
private String status;
|
||||
|
||||
@Schema(description = "平台")
|
||||
private String platform;
|
||||
|
||||
@Schema(description = "页码")
|
||||
private Integer pageIndex = 1;
|
||||
|
||||
@Schema(description = "每页数量")
|
||||
private Integer pageSize = 10;
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
package com.fruitshorts.content.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
|
||||
@@ -10,19 +11,31 @@ import java.time.LocalDateTime;
|
||||
@Data
|
||||
public class BannerRespVO {
|
||||
|
||||
@Schema(description = "轮播图 ID")
|
||||
private Long id;
|
||||
@Schema(description = "图片地址")
|
||||
private String imageUrl;
|
||||
@Schema(description = "展示位置")
|
||||
private String position;
|
||||
@Schema(description = "展示位置文本")
|
||||
private String positionText;
|
||||
@Schema(description = "跳转类型")
|
||||
private String linkType;
|
||||
@Schema(description = "跳转类型文本")
|
||||
private String linkTypeText;
|
||||
@Schema(description = "跳转目标")
|
||||
private String linkValue;
|
||||
/** 跳转目标的展示文案,如短剧名称 */
|
||||
@Schema(description = "跳转目标文案")
|
||||
private String linkText;
|
||||
@Schema(description = "排序")
|
||||
private Integer sort;
|
||||
@Schema(description = "状态")
|
||||
private Integer status;
|
||||
@Schema(description = "状态文本")
|
||||
private String statusText;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@Schema(description = "更新时间")
|
||||
private LocalDateTime updatedAt;
|
||||
}
|
||||
+7
@@ -2,23 +2,30 @@
|
||||
|
||||
package com.fruitshorts.content.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class BannerSaveReqVO {
|
||||
|
||||
@jakarta.validation.constraints.NotBlank(message = "请上传轮播图片")
|
||||
@Schema(description = "轮播图片地址")
|
||||
private String imageUrl;
|
||||
|
||||
/** HOME_TOP / DISCOVER */
|
||||
@Schema(description = "展示位置")
|
||||
private String position;
|
||||
|
||||
/** NONE / DRAMA / URL */
|
||||
@Schema(description = "跳转类型")
|
||||
private String linkType;
|
||||
|
||||
/** 剧集 ID 或跳转地址 */
|
||||
@Schema(description = "跳转目标")
|
||||
private String linkValue;
|
||||
|
||||
@Schema(description = "排序")
|
||||
private Integer sort;
|
||||
@Schema(description = "状态")
|
||||
private Integer status;
|
||||
}
|
||||
+6
@@ -2,15 +2,21 @@
|
||||
|
||||
package com.fruitshorts.content.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class DramaCategoryRespVO {
|
||||
|
||||
@Schema(description = "分类 ID")
|
||||
private Long id;
|
||||
@Schema(description = "分类名称")
|
||||
private String name;
|
||||
@Schema(description = "排序")
|
||||
private Integer sort;
|
||||
@Schema(description = "状态")
|
||||
private Integer status;
|
||||
/** 该类型下的短剧数量 */
|
||||
@Schema(description = "短剧数量")
|
||||
private Integer dramaCount;
|
||||
}
|
||||
+4
@@ -2,6 +2,7 @@
|
||||
|
||||
package com.fruitshorts.content.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
|
||||
@@ -9,8 +10,11 @@ import lombok.Data;
|
||||
public class DramaCategorySaveReqVO {
|
||||
|
||||
@NotBlank(message = "请填写类型名称")
|
||||
@Schema(description = "类型名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "排序")
|
||||
private Integer sort;
|
||||
@Schema(description = "状态")
|
||||
private Integer status;
|
||||
}
|
||||
+5
@@ -2,6 +2,7 @@
|
||||
|
||||
package com.fruitshorts.content.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import com.fruitshorts.common.pojo.PageParam;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
@@ -11,9 +12,13 @@ import lombok.EqualsAndHashCode;
|
||||
public class DramaPageReqVO extends PageParam {
|
||||
|
||||
/** 标题关键字 */
|
||||
@Schema(description = "标题关键字")
|
||||
private String keyword;
|
||||
@Schema(description = "状态")
|
||||
private String status;
|
||||
@Schema(description = "分类 ID")
|
||||
private Long categoryId;
|
||||
/** 是否只看热门 */
|
||||
@Schema(description = "是否热门")
|
||||
private Boolean isHot;
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
package com.fruitshorts.content.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
|
||||
@@ -13,33 +14,55 @@ import java.time.LocalDateTime;
|
||||
@Data
|
||||
public class DramaRespVO {
|
||||
|
||||
@Schema(description = "短剧 ID")
|
||||
private Long id;
|
||||
@Schema(description = "编码")
|
||||
private String code;
|
||||
@Schema(description = "标题")
|
||||
private String title;
|
||||
@Schema(description = "副标题")
|
||||
private String subtitle;
|
||||
@Schema(description = "分类 ID")
|
||||
private Long categoryId;
|
||||
@Schema(description = "分类名称")
|
||||
private String category;
|
||||
@Schema(description = "题材")
|
||||
private String genre;
|
||||
@Schema(description = "简介")
|
||||
private String description;
|
||||
@Schema(description = "封面地址")
|
||||
private String cover;
|
||||
/** 整剧预告片地址 */
|
||||
@Schema(description = "预告片地址")
|
||||
private String trailerUrl;
|
||||
@Schema(description = "语言")
|
||||
private String language;
|
||||
@Schema(description = "总集数")
|
||||
private Integer episodes;
|
||||
@Schema(description = "免费集数")
|
||||
private Integer freeEpisodes;
|
||||
@Schema(description = "解锁金币")
|
||||
private Integer unlockCoin;
|
||||
@Schema(description = "是否热门")
|
||||
private Boolean isHot;
|
||||
@Schema(description = "状态")
|
||||
private String status;
|
||||
@Schema(description = "状态文本")
|
||||
private String statusText;
|
||||
@Schema(description = "播放量")
|
||||
private Long views;
|
||||
@Schema(description = "排序")
|
||||
private Integer sort;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@Schema(description = "发布时间")
|
||||
private LocalDateTime publishAt;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@Schema(description = "创建时间")
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@Schema(description = "更新时间")
|
||||
private LocalDateTime updatedAt;
|
||||
}
|
||||
+13
@@ -2,6 +2,7 @@
|
||||
|
||||
package com.fruitshorts.content.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
|
||||
@@ -9,19 +10,31 @@ import lombok.Data;
|
||||
public class DramaSaveReqVO {
|
||||
|
||||
@NotBlank(message = "请填写短剧名称")
|
||||
@Schema(description = "短剧名称")
|
||||
private String title;
|
||||
|
||||
@Schema(description = "副标题")
|
||||
private String subtitle;
|
||||
@Schema(description = "分类 ID")
|
||||
private Long categoryId;
|
||||
@Schema(description = "题材")
|
||||
private String genre;
|
||||
@Schema(description = "简介")
|
||||
private String description;
|
||||
@Schema(description = "封面地址")
|
||||
private String cover;
|
||||
/** 整剧预告片地址(复用已有的 drama.trailer_url 列) */
|
||||
@Schema(description = "预告片地址")
|
||||
private String trailerUrl;
|
||||
@Schema(description = "语言")
|
||||
private String language;
|
||||
@Schema(description = "免费集数")
|
||||
private Integer freeEpisodes;
|
||||
@Schema(description = "解锁金币")
|
||||
private Integer unlockCoin;
|
||||
/** 是否热门 */
|
||||
@Schema(description = "是否热门")
|
||||
private Boolean isHot;
|
||||
@Schema(description = "排序")
|
||||
private Integer sort;
|
||||
}
|
||||
+2
@@ -2,11 +2,13 @@
|
||||
|
||||
package com.fruitshorts.content.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class DramaStatusReqVO {
|
||||
|
||||
/** 驳回原因,其他动作可空 */
|
||||
@Schema(description = "驳回原因")
|
||||
private String reason;
|
||||
}
|
||||
+15
@@ -2,24 +2,39 @@
|
||||
|
||||
package com.fruitshorts.content.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class EpisodeRespVO {
|
||||
|
||||
@Schema(description = "剧集 ID")
|
||||
private Long id;
|
||||
@Schema(description = "短剧 ID")
|
||||
private Long dramaId;
|
||||
@Schema(description = "集号")
|
||||
private Integer number;
|
||||
@Schema(description = "标题")
|
||||
private String title;
|
||||
/** 展示用时长,mm:ss */
|
||||
@Schema(description = "展示时长(mm:ss)")
|
||||
private String duration;
|
||||
@Schema(description = "时长(秒)")
|
||||
private Integer durationSec;
|
||||
@Schema(description = "封面地址")
|
||||
private String cover;
|
||||
@Schema(description = "视频地址")
|
||||
private String videoUrl;
|
||||
@Schema(description = "是否免费")
|
||||
private Boolean isFree;
|
||||
@Schema(description = "解锁金币")
|
||||
private Integer unlockCoin;
|
||||
@Schema(description = "状态")
|
||||
private String status;
|
||||
@Schema(description = "状态文本")
|
||||
private String statusText;
|
||||
@Schema(description = "播放量")
|
||||
private Long views;
|
||||
@Schema(description = "排序")
|
||||
private Integer sort;
|
||||
}
|
||||
+11
@@ -2,6 +2,7 @@
|
||||
|
||||
package com.fruitshorts.content.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
@@ -9,17 +10,27 @@ import lombok.Data;
|
||||
public class EpisodeSaveReqVO {
|
||||
|
||||
@NotNull(message = "请选择所属短剧")
|
||||
@Schema(description = "短剧 ID")
|
||||
private Long dramaId;
|
||||
|
||||
@NotNull(message = "请填写集号")
|
||||
@Schema(description = "集号")
|
||||
private Integer number;
|
||||
|
||||
@Schema(description = "标题")
|
||||
private String title;
|
||||
@Schema(description = "时长(秒)")
|
||||
private Integer durationSec;
|
||||
@Schema(description = "封面地址")
|
||||
private String cover;
|
||||
@Schema(description = "视频地址")
|
||||
private String videoUrl;
|
||||
@Schema(description = "是否免费")
|
||||
private Boolean isFree;
|
||||
@Schema(description = "解锁金币")
|
||||
private Integer unlockCoin;
|
||||
@Schema(description = "状态")
|
||||
private String status;
|
||||
@Schema(description = "排序")
|
||||
private Integer sort;
|
||||
}
|
||||
+2
@@ -2,6 +2,7 @@
|
||||
|
||||
package com.fruitshorts.content.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import lombok.Data;
|
||||
|
||||
@@ -11,5 +12,6 @@ import java.util.List;
|
||||
public class EpisodeSortReqVO {
|
||||
|
||||
@NotEmpty(message = "请提供排序后的剧集 ID 列表")
|
||||
@Schema(description = "排序后的剧集 ID 列表")
|
||||
private List<Long> ids;
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
package com.fruitshorts.content.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
@@ -10,24 +11,36 @@ import java.util.List;
|
||||
@Data
|
||||
public class PriceRespVO {
|
||||
|
||||
@Schema(description = "短剧 ID")
|
||||
private Long dramaId;
|
||||
@Schema(description = "免费集数")
|
||||
private Integer freeEpisodes;
|
||||
@Schema(description = "解锁金币")
|
||||
private Integer unlockCoin;
|
||||
/** 该剧剧集总数 */
|
||||
@Schema(description = "剧集总数")
|
||||
private Integer episodeCount;
|
||||
/** 本次实际发生变化的剧集数 */
|
||||
@Schema(description = "本次变更剧集数")
|
||||
private Integer changedCount;
|
||||
/** 剧集明细:后台定价页要按集展示当前价格与免费状态 */
|
||||
@Schema(description = "剧集明细")
|
||||
private List<DramaEpisodePriceVO> episodes;
|
||||
|
||||
@Data
|
||||
public static class DramaEpisodePriceVO {
|
||||
@Schema(description = "剧集 ID")
|
||||
private Long episodeId;
|
||||
@Schema(description = "集号")
|
||||
private Integer number;
|
||||
@Schema(description = "标题")
|
||||
private String title;
|
||||
@Schema(description = "是否免费")
|
||||
private Boolean free;
|
||||
@Schema(description = "解锁金币")
|
||||
private Integer unlockCoin;
|
||||
/** 试看秒数,0 = 不限制 */
|
||||
@Schema(description = "试看秒数")
|
||||
private Integer previewSeconds;
|
||||
}
|
||||
}
|
||||
+9
@@ -2,6 +2,7 @@
|
||||
|
||||
package com.fruitshorts.content.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
@@ -10,21 +11,29 @@ import java.util.List;
|
||||
@Data
|
||||
public class PriceSaveReqVO {
|
||||
|
||||
@Schema(description = "短剧 ID")
|
||||
private Long dramaId;
|
||||
/** 整剧免费集数:前 N 集免费,其余按 unlockCoin 收费 */
|
||||
@Schema(description = "整剧免费集数")
|
||||
private Integer freeEpisodes;
|
||||
/** 整剧默认解锁金币(逐集未单独指定时生效) */
|
||||
@Schema(description = "整剧默认解锁金币")
|
||||
private Integer unlockCoin;
|
||||
/** 逐集覆盖,可空;列表里的集优先于整剧默认值 */
|
||||
@Schema(description = "逐集覆盖配置")
|
||||
private List<EpisodePrice> episodes;
|
||||
|
||||
@Data
|
||||
public static class EpisodePrice {
|
||||
@Schema(description = "剧集 ID")
|
||||
private Long episodeId;
|
||||
/** 1 免费 / 0 收费 */
|
||||
@Schema(description = "是否免费")
|
||||
private Integer isFree;
|
||||
@Schema(description = "解锁金币")
|
||||
private Integer unlockCoin;
|
||||
/** 试看秒数:0 = 不限制(复用 drama_episode.preview_seconds,播放接口已经在下发这个字段) */
|
||||
@Schema(description = "试看秒数")
|
||||
private Integer previewSeconds;
|
||||
}
|
||||
}
|
||||
+2
@@ -2,6 +2,7 @@
|
||||
|
||||
package com.fruitshorts.creator.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/** 开通创作者账号:用户名默认取 creator.code 小写,可用这个字段覆盖。 */
|
||||
@@ -9,5 +10,6 @@ import lombok.Data;
|
||||
public class CreatorAccountOpenReqVO {
|
||||
|
||||
/** 覆盖默认登录名;留空则用 creator.code 的小写形式 */
|
||||
@Schema(description = "覆盖默认登录名(留空则用 creator.code 的小写形式)")
|
||||
private String username;
|
||||
}
|
||||
+7
@@ -2,6 +2,7 @@
|
||||
|
||||
package com.fruitshorts.creator.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
@@ -13,13 +14,19 @@ import lombok.Data;
|
||||
@Data
|
||||
public class CreatorAccountRespVO {
|
||||
|
||||
@Schema(description = "创作者 ID")
|
||||
private Long creatorId;
|
||||
@Schema(description = "管理员用户 ID")
|
||||
private Long adminUserId;
|
||||
@Schema(description = "用户名")
|
||||
private String username;
|
||||
/** 一次性明文初始密码;幂等命中时为 null */
|
||||
@Schema(description = "一次性明文初始密码(幂等命中时为 null)")
|
||||
private String password;
|
||||
/** true = 这次真的新建了账号 */
|
||||
@Schema(description = "是否本次新建账号")
|
||||
private Boolean created;
|
||||
/** 给运营看的一句话说明 */
|
||||
@Schema(description = "给运营看的一句话说明")
|
||||
private String message;
|
||||
}
|
||||
+2
@@ -2,6 +2,7 @@
|
||||
|
||||
package com.fruitshorts.creator.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
@@ -10,5 +11,6 @@ import lombok.Data;
|
||||
public class CreatorAttachReqVO {
|
||||
|
||||
@NotNull(message = "缺少媒资 ID")
|
||||
@Schema(description = "媒资 ID")
|
||||
private Long assetId;
|
||||
}
|
||||
+4
@@ -2,6 +2,7 @@
|
||||
|
||||
package com.fruitshorts.creator.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/** 创作者入驻审核请求。 */
|
||||
@@ -9,9 +10,12 @@ import lombok.Data;
|
||||
public class CreatorAuditReqVO {
|
||||
|
||||
/** APPROVE / REJECT / FREEZE */
|
||||
@Schema(description = "操作(APPROVE / REJECT / FREEZE)")
|
||||
private String action;
|
||||
/** 驳回原因码,REJECT 时必填 */
|
||||
@Schema(description = "驳回原因码(REJECT 时必填)")
|
||||
private String rejectCode;
|
||||
/** 审核说明 / 驳回原因 */
|
||||
@Schema(description = "审核说明 / 驳回原因")
|
||||
private String reason;
|
||||
}
|
||||
+3
@@ -3,6 +3,7 @@
|
||||
package com.fruitshorts.creator.vo;
|
||||
|
||||
import com.fruitshorts.common.pojo.PageParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@@ -15,6 +16,8 @@ import lombok.EqualsAndHashCode;
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class CreatorCenterDramaQueryReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "关键字")
|
||||
private String keyword;
|
||||
@Schema(description = "状态")
|
||||
private String status;
|
||||
}
|
||||
+23
@@ -2,6 +2,7 @@
|
||||
|
||||
package com.fruitshorts.creator.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
@@ -12,30 +13,52 @@ import java.time.LocalDateTime;
|
||||
@Data
|
||||
public class CreatorCenterDramaVO {
|
||||
|
||||
@Schema(description = "ID")
|
||||
private Long id;
|
||||
@Schema(description = "编号")
|
||||
private String code;
|
||||
@Schema(description = "标题")
|
||||
private String title;
|
||||
@Schema(description = "副标题")
|
||||
private String subtitle;
|
||||
@Schema(description = "题材")
|
||||
private String genre;
|
||||
/** 简介(实体字段是 synopsis) */
|
||||
@Schema(description = "简介")
|
||||
private String description;
|
||||
@Schema(description = "封面")
|
||||
private String cover;
|
||||
/** 整剧预告片 */
|
||||
@Schema(description = "整剧预告片地址")
|
||||
private String trailerUrl;
|
||||
@Schema(description = "语言")
|
||||
private String language;
|
||||
@Schema(description = "状态")
|
||||
private String status;
|
||||
@Schema(description = "状态文本")
|
||||
private String statusText;
|
||||
@Schema(description = "集数")
|
||||
private Integer episodes;
|
||||
@Schema(description = "观看次数")
|
||||
private Long views;
|
||||
@Schema(description = "更新时间")
|
||||
private LocalDateTime updatedAt;
|
||||
|
||||
/** 最近一次内容提交(没有提交过则为空) */
|
||||
@Schema(description = "最近一次内容提交 ID")
|
||||
private Long submissionId;
|
||||
@Schema(description = "提交类型")
|
||||
private String submissionType;
|
||||
@Schema(description = "提交状态")
|
||||
private String submissionStatus;
|
||||
@Schema(description = "提交状态文本")
|
||||
private String submissionStatusText;
|
||||
@Schema(description = "审核说明")
|
||||
private String reviewNote;
|
||||
@Schema(description = "驳回原因码")
|
||||
private String rejectCode;
|
||||
@Schema(description = "提交时间")
|
||||
private LocalDateTime submitAt;
|
||||
@Schema(description = "审核时间")
|
||||
private LocalDateTime reviewAt;
|
||||
}
|
||||
+7
@@ -2,6 +2,7 @@
|
||||
|
||||
package com.fruitshorts.creator.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
@@ -16,12 +17,18 @@ import java.time.LocalDateTime;
|
||||
public class CreatorCenterNoticeVO {
|
||||
|
||||
/** 来源单据 id */
|
||||
@Schema(description = "来源单据 ID")
|
||||
private Long id;
|
||||
/** CREATOR(入驻审核)/ SUBMISSION(内容提交审核) */
|
||||
@Schema(description = "业务类型(CREATOR / SUBMISSION)")
|
||||
private String bizType;
|
||||
@Schema(description = "标题")
|
||||
private String title;
|
||||
@Schema(description = "内容")
|
||||
private String content;
|
||||
/** 通过 / 驳回 等结果文案 */
|
||||
@Schema(description = "结果文案(通过 / 驳回 等)")
|
||||
private String result;
|
||||
@Schema(description = "时间")
|
||||
private LocalDateTime time;
|
||||
}
|
||||
+13
@@ -2,6 +2,7 @@
|
||||
|
||||
package com.fruitshorts.creator.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
@@ -10,20 +11,32 @@ import java.time.LocalDateTime;
|
||||
@Data
|
||||
public class CreatorCenterProfileVO {
|
||||
|
||||
@Schema(description = "ID")
|
||||
private Long id;
|
||||
@Schema(description = "编号")
|
||||
private String code;
|
||||
@Schema(description = "名称")
|
||||
private String name;
|
||||
/** INDIVIDUAL / COMPANY */
|
||||
@Schema(description = "类型(INDIVIDUAL / COMPANY)")
|
||||
private String type;
|
||||
/** pending / approved / rejected / frozen */
|
||||
@Schema(description = "状态(pending / approved / rejected / frozen)")
|
||||
private String status;
|
||||
@Schema(description = "状态文本")
|
||||
private String statusText;
|
||||
/** 入驻审核意见(驳回时是原因) */
|
||||
@Schema(description = "入驻审核意见(驳回时是原因)")
|
||||
private String auditNote;
|
||||
@Schema(description = "审核时间")
|
||||
private LocalDateTime auditAt;
|
||||
@Schema(description = "联系人姓名")
|
||||
private String contactName;
|
||||
@Schema(description = "联系人邮箱")
|
||||
private String contactEmail;
|
||||
@Schema(description = "国家/地区代码")
|
||||
private String countryCode;
|
||||
/** 我的作品数(只统计自己的) */
|
||||
@Schema(description = "我的作品数")
|
||||
private Long dramaTotal;
|
||||
}
|
||||
+6
@@ -2,15 +2,21 @@
|
||||
|
||||
package com.fruitshorts.creator.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/** 代看目标下拉项:超管选择要看哪个创作者时用(只给 id / 名称 / 状态,不给联系方式)。 */
|
||||
@Data
|
||||
public class CreatorCenterTargetVO {
|
||||
|
||||
@Schema(description = "ID")
|
||||
private Long id;
|
||||
@Schema(description = "编号")
|
||||
private String code;
|
||||
@Schema(description = "名称")
|
||||
private String name;
|
||||
@Schema(description = "状态")
|
||||
private String status;
|
||||
@Schema(description = "状态文本")
|
||||
private String statusText;
|
||||
}
|
||||
+9
@@ -2,6 +2,7 @@
|
||||
|
||||
package com.fruitshorts.creator.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
|
||||
@@ -15,14 +16,22 @@ import lombok.Data;
|
||||
public class CreatorDramaEditReqVO {
|
||||
|
||||
@NotBlank(message = "请填写作品名称")
|
||||
@Schema(description = "标题")
|
||||
private String title;
|
||||
|
||||
@Schema(description = "副标题")
|
||||
private String subtitle;
|
||||
@Schema(description = "分类 ID")
|
||||
private Long categoryId;
|
||||
@Schema(description = "题材")
|
||||
private String genre;
|
||||
@Schema(description = "简介")
|
||||
private String description;
|
||||
@Schema(description = "封面")
|
||||
private String cover;
|
||||
/** 整剧预告片(复用 drama.trailer_url) */
|
||||
@Schema(description = "整剧预告片地址")
|
||||
private String trailerUrl;
|
||||
@Schema(description = "语言")
|
||||
private String language;
|
||||
}
|
||||
+7
@@ -2,6 +2,7 @@
|
||||
|
||||
package com.fruitshorts.creator.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
@@ -14,11 +15,17 @@ import lombok.Data;
|
||||
public class CreatorEpisodeReqVO {
|
||||
|
||||
/** 不传则自动取下一集 */
|
||||
@Schema(description = "集号(不传则自动取下一集)")
|
||||
private Integer epNo;
|
||||
@Schema(description = "标题")
|
||||
private String title;
|
||||
@Schema(description = "时长(秒)")
|
||||
private Integer durationSec;
|
||||
@Schema(description = "封面")
|
||||
private String cover;
|
||||
/** 片源地址(批 3 接分片上传后会写这里) */
|
||||
@Schema(description = "片源地址")
|
||||
private String videoUrl;
|
||||
@Schema(description = "排序")
|
||||
private Integer sort;
|
||||
}
|
||||
+5
@@ -3,6 +3,7 @@
|
||||
package com.fruitshorts.creator.vo;
|
||||
|
||||
import com.fruitshorts.common.pojo.PageParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@@ -12,10 +13,14 @@ import lombok.EqualsAndHashCode;
|
||||
public class CreatorQueryReqVO extends PageParam {
|
||||
|
||||
/** 名称 / 编号 / 联系人 / 联系方式 关键字 */
|
||||
@Schema(description = "名称 / 编号 / 联系人 / 联系方式 关键字")
|
||||
private String keyword;
|
||||
/** pending / approved / rejected / frozen */
|
||||
@Schema(description = "状态(pending / approved / rejected / frozen)")
|
||||
private String status;
|
||||
/** INDIVIDUAL / COMPANY */
|
||||
@Schema(description = "类型(INDIVIDUAL / COMPANY)")
|
||||
private String type;
|
||||
@Schema(description = "国家/地区代码")
|
||||
private String countryCode;
|
||||
}
|
||||
+9
@@ -2,6 +2,7 @@
|
||||
|
||||
package com.fruitshorts.creator.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
|
||||
@@ -14,16 +15,24 @@ import lombok.Data;
|
||||
public class CreatorSaveReqVO {
|
||||
|
||||
@NotBlank(message = "请填写创作者名称")
|
||||
@Schema(description = "名称")
|
||||
private String name;
|
||||
|
||||
/** INDIVIDUAL / COMPANY,默认 INDIVIDUAL */
|
||||
@Schema(description = "类型(INDIVIDUAL / COMPANY,默认 INDIVIDUAL)")
|
||||
private String type;
|
||||
/** 编号:不传则自动生成 CR+日期+序号;也是开账号时默认的登录名(小写) */
|
||||
@Schema(description = "编号(不传则自动生成)")
|
||||
private String code;
|
||||
@Schema(description = "联系人姓名")
|
||||
private String contactName;
|
||||
@Schema(description = "联系人手机号")
|
||||
private String contactMobile;
|
||||
@Schema(description = "联系人邮箱")
|
||||
private String contactEmail;
|
||||
@Schema(description = "国家/地区代码")
|
||||
private String countryCode;
|
||||
/** 可选:绑定已有的 C 端账号 app_user.id */
|
||||
@Schema(description = "绑定的 C 端账号 app_user.id(可选)")
|
||||
private Long userId;
|
||||
}
|
||||
+2
@@ -2,6 +2,7 @@
|
||||
|
||||
package com.fruitshorts.creator.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
|
||||
@@ -10,5 +11,6 @@ import lombok.Data;
|
||||
public class CreatorSubmitReqVO {
|
||||
|
||||
@NotBlank(message = "请选择提交类型")
|
||||
@Schema(description = "提交类型(CREATE / UPDATE / PUBLISH / OFFLINE)")
|
||||
private String type;
|
||||
}
|
||||
+4
@@ -2,6 +2,7 @@
|
||||
|
||||
package com.fruitshorts.creator.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/** 内容提交审核请求。 */
|
||||
@@ -9,9 +10,12 @@ import lombok.Data;
|
||||
public class SubmissionAuditReqVO {
|
||||
|
||||
/** APPROVE / REJECT / WITHDRAW */
|
||||
@Schema(description = "操作(APPROVE / REJECT / WITHDRAW)")
|
||||
private String action;
|
||||
/** 驳回原因码,REJECT 时必填 */
|
||||
@Schema(description = "驳回原因码(REJECT 时必填)")
|
||||
private String rejectCode;
|
||||
/** 审核说明 / 驳回原因 */
|
||||
@Schema(description = "审核说明 / 驳回原因")
|
||||
private String reason;
|
||||
}
|
||||
+5
@@ -3,6 +3,7 @@
|
||||
package com.fruitshorts.creator.vo;
|
||||
|
||||
import com.fruitshorts.common.pojo.PageParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@@ -11,10 +12,14 @@ import lombok.EqualsAndHashCode;
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class SubmissionQueryReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "创作者 ID")
|
||||
private Long creatorId;
|
||||
@Schema(description = "短剧 ID")
|
||||
private Long dramaId;
|
||||
/** DRAFT / SUBMITTED / REVIEWING / APPROVED / REJECTED / WITHDRAWN */
|
||||
@Schema(description = "状态(DRAFT / SUBMITTED / REVIEWING / APPROVED / REJECTED / WITHDRAWN)")
|
||||
private String status;
|
||||
/** CREATE / UPDATE / PUBLISH / OFFLINE */
|
||||
@Schema(description = "类型(CREATE / UPDATE / PUBLISH / OFFLINE)")
|
||||
private String type;
|
||||
}
|
||||
+5
@@ -2,6 +2,7 @@
|
||||
|
||||
package com.fruitshorts.interaction.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
|
||||
@@ -10,9 +11,13 @@ import lombok.Data;
|
||||
public class CommentAuditReqVO {
|
||||
|
||||
/** PASS/REJECT */
|
||||
@Schema(description = "审核结果(PASS/REJECT)")
|
||||
@NotBlank(message = "请选择审核结果")
|
||||
private String result;
|
||||
|
||||
@Schema(description = "原因编码")
|
||||
private String reasonCode;
|
||||
|
||||
@Schema(description = "原因说明")
|
||||
private String reasonText;
|
||||
}
|
||||
+5
@@ -2,6 +2,7 @@
|
||||
|
||||
package com.fruitshorts.interaction.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
@@ -10,14 +11,18 @@ import lombok.Data;
|
||||
@Data
|
||||
public class CommentPublishReqVO {
|
||||
|
||||
@Schema(description = "短剧ID")
|
||||
@NotNull(message = "缺少 dramaId")
|
||||
private Long dramaId;
|
||||
|
||||
@Schema(description = "剧集ID")
|
||||
private Long episodeId;
|
||||
|
||||
@Schema(description = "评论内容")
|
||||
@NotBlank(message = "评论内容不能为空")
|
||||
private String content;
|
||||
|
||||
/** 回复某条评论时传它的 id;顶层评论不传 */
|
||||
@Schema(description = "回复某条评论时传它的 ID;顶层评论不传")
|
||||
private Long parentId;
|
||||
}
|
||||
+19
@@ -2,24 +2,43 @@
|
||||
|
||||
package com.fruitshorts.interaction.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/** 评论列表查询(客户端用游标,后台用分页)。 */
|
||||
@Data
|
||||
public class CommentQueryReqVO {
|
||||
|
||||
@Schema(description = "短剧ID")
|
||||
private Long dramaId;
|
||||
|
||||
@Schema(description = "剧集ID")
|
||||
private Long episodeId;
|
||||
|
||||
/** 只看某个楼层的回复 */
|
||||
@Schema(description = "只看某个楼层的回复")
|
||||
private Long rootId;
|
||||
|
||||
/** 客户端游标:上一页最后一条的 id */
|
||||
@Schema(description = "客户端游标:上一页最后一条的 ID")
|
||||
private Long cursor;
|
||||
|
||||
@Schema(description = "数量")
|
||||
private Integer size;
|
||||
|
||||
/** 后台检索条件 */
|
||||
@Schema(description = "状态")
|
||||
private String status;
|
||||
|
||||
@Schema(description = "用户ID")
|
||||
private Long userId;
|
||||
|
||||
@Schema(description = "关键词")
|
||||
private String keyword;
|
||||
|
||||
@Schema(description = "页码")
|
||||
private Integer pageIndex = 1;
|
||||
|
||||
@Schema(description = "每页数量")
|
||||
private Integer pageSize = 10;
|
||||
}
|
||||
+36
@@ -2,6 +2,7 @@
|
||||
|
||||
package com.fruitshorts.interaction.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
@@ -10,26 +11,61 @@ import java.time.LocalDateTime;
|
||||
@Data
|
||||
public class CommentRespVO {
|
||||
|
||||
@Schema(description = "ID")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "短剧ID")
|
||||
private Long dramaId;
|
||||
|
||||
@Schema(description = "剧集ID")
|
||||
private Long episodeId;
|
||||
|
||||
@Schema(description = "父评论ID")
|
||||
private Long parentId;
|
||||
|
||||
@Schema(description = "根评论ID")
|
||||
private Long rootId;
|
||||
|
||||
@Schema(description = "用户ID")
|
||||
private Long userId;
|
||||
|
||||
/** 对外用户标识与昵称头像,客户端直接渲染 */
|
||||
@Schema(description = "对外用户标识")
|
||||
private String uid;
|
||||
|
||||
@Schema(description = "昵称")
|
||||
private String nickname;
|
||||
|
||||
@Schema(description = "头像地址")
|
||||
private String avatarUrl;
|
||||
|
||||
@Schema(description = "内容")
|
||||
private String content;
|
||||
|
||||
/** pending/published/rejected/deleted */
|
||||
@Schema(description = "状态(pending/published/rejected/deleted)")
|
||||
private String status;
|
||||
|
||||
@Schema(description = "审核原因")
|
||||
private String auditReason;
|
||||
|
||||
@Schema(description = "点赞数")
|
||||
private Integer likeCount;
|
||||
|
||||
@Schema(description = "回复数")
|
||||
private Integer replyCount;
|
||||
|
||||
@Schema(description = "举报数")
|
||||
private Integer reportCount;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
/** 是否本人发表(可删除) */
|
||||
@Schema(description = "是否本人发表")
|
||||
private Boolean mine;
|
||||
|
||||
/** 当前用户是否已点赞 */
|
||||
@Schema(description = "当前用户是否已点赞")
|
||||
private Boolean liked;
|
||||
}
|
||||
+3
@@ -2,6 +2,7 @@
|
||||
|
||||
package com.fruitshorts.interaction.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
@@ -11,9 +12,11 @@ import lombok.Data;
|
||||
public class LikeToggleReqVO {
|
||||
|
||||
/** DRAMA/COMMENT */
|
||||
@Schema(description = "目标类型(DRAMA/COMMENT)")
|
||||
@NotBlank(message = "缺少 targetType")
|
||||
private String targetType;
|
||||
|
||||
@Schema(description = "目标ID")
|
||||
@NotNull(message = "缺少 targetId")
|
||||
private Long targetId;
|
||||
}
|
||||
+4
@@ -2,12 +2,16 @@
|
||||
|
||||
package com.fruitshorts.interaction.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/** 点赞结果:切换后的状态与最新计数。 */
|
||||
@Data
|
||||
public class LikeToggleRespVO {
|
||||
|
||||
@Schema(description = "是否已点赞")
|
||||
private Boolean liked;
|
||||
|
||||
@Schema(description = "数量")
|
||||
private Long count;
|
||||
}
|
||||
+5
@@ -2,6 +2,7 @@
|
||||
|
||||
package com.fruitshorts.interaction.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
@@ -11,14 +12,18 @@ import lombok.Data;
|
||||
public class ReportCreateReqVO {
|
||||
|
||||
/** COMMENT/USER/DRAMA */
|
||||
@Schema(description = "目标类型(COMMENT/USER/DRAMA)")
|
||||
@NotBlank(message = "缺少 targetType")
|
||||
private String targetType;
|
||||
|
||||
@Schema(description = "目标ID")
|
||||
@NotNull(message = "缺少 targetId")
|
||||
private Long targetId;
|
||||
|
||||
@Schema(description = "举报原因编码")
|
||||
@NotBlank(message = "请选择举报原因")
|
||||
private String reasonCode;
|
||||
|
||||
@Schema(description = "描述")
|
||||
private String description;
|
||||
}
|
||||
+8
@@ -2,6 +2,7 @@
|
||||
|
||||
package com.fruitshorts.interaction.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/** 后台处理举报工单。 */
|
||||
@@ -9,10 +10,17 @@ import lombok.Data;
|
||||
public class ReportHandleReqVO {
|
||||
|
||||
/** handled/rejected */
|
||||
@Schema(description = "处理状态(handled/rejected)")
|
||||
private String status = "handled";
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String note;
|
||||
|
||||
/** 是否同时封禁被举报用户(仅 COMMENT/USER 类型有意义) */
|
||||
@Schema(description = "是否同时封禁被举报用户(仅 COMMENT/USER 类型有意义)")
|
||||
private Boolean banTarget;
|
||||
|
||||
/** 封禁原因,留档用 */
|
||||
@Schema(description = "封禁原因")
|
||||
private String banReason;
|
||||
}
|
||||
+12
@@ -2,6 +2,7 @@
|
||||
|
||||
package com.fruitshorts.interaction.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/** 后台举报工单检索条件。 */
|
||||
@@ -9,11 +10,22 @@ import lombok.Data;
|
||||
public class ReportQueryReqVO {
|
||||
|
||||
/** pending/handled/rejected */
|
||||
@Schema(description = "状态(pending/handled/rejected)")
|
||||
private String status;
|
||||
|
||||
/** COMMENT/USER/DRAMA */
|
||||
@Schema(description = "目标类型(COMMENT/USER/DRAMA)")
|
||||
private String targetType;
|
||||
|
||||
@Schema(description = "举报原因编码")
|
||||
private String reasonCode;
|
||||
|
||||
@Schema(description = "举报人ID")
|
||||
private Long reporterId;
|
||||
|
||||
@Schema(description = "页码")
|
||||
private Integer pageIndex = 1;
|
||||
|
||||
@Schema(description = "每页数量")
|
||||
private Integer pageSize = 10;
|
||||
}
|
||||
+11
@@ -2,6 +2,7 @@
|
||||
|
||||
package com.fruitshorts.interaction.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
|
||||
@@ -9,14 +10,24 @@ import lombok.Data;
|
||||
@Data
|
||||
public class SensitiveWordReqVO {
|
||||
|
||||
@Schema(description = "敏感词")
|
||||
@NotBlank(message = "请输入敏感词")
|
||||
private String word;
|
||||
|
||||
/** POLITICS/PORN/ABUSE/AD/RELIGION */
|
||||
@Schema(description = "分类(POLITICS/PORN/ABUSE/AD/RELIGION)")
|
||||
private String category;
|
||||
|
||||
/** BLOCK/REVIEW/REPLACE */
|
||||
@Schema(description = "处理级别(BLOCK/REVIEW/REPLACE)")
|
||||
private String level = "REVIEW";
|
||||
|
||||
@Schema(description = "替换文本")
|
||||
private String replaceText = "*";
|
||||
|
||||
@Schema(description = "语言")
|
||||
private String language = "id-ID";
|
||||
|
||||
@Schema(description = "状态")
|
||||
private Integer status = 1;
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
package com.fruitshorts.media.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
|
||||
@@ -10,16 +11,26 @@ import java.time.LocalDateTime;
|
||||
@Data
|
||||
public class MediaAssetRespVO {
|
||||
|
||||
@Schema(description = "媒资 ID")
|
||||
private Long id;
|
||||
@Schema(description = "业务类型")
|
||||
private String bizType;
|
||||
@Schema(description = "文件名")
|
||||
private String fileName;
|
||||
@Schema(description = "对象存储键")
|
||||
private String objectKey;
|
||||
@Schema(description = "地址")
|
||||
private String url;
|
||||
@Schema(description = "文件大小(字节)")
|
||||
private Long sizeBytes;
|
||||
@Schema(description = "MD5 校验值")
|
||||
private String md5;
|
||||
@Schema(description = "时长(秒)")
|
||||
private Integer durationSec;
|
||||
@Schema(description = "状态")
|
||||
private String status;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@Schema(description = "创建时间")
|
||||
private LocalDateTime createdAt;
|
||||
}
|
||||
+3
@@ -2,6 +2,7 @@
|
||||
|
||||
package com.fruitshorts.media.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
|
||||
@@ -9,8 +10,10 @@ import lombok.Data;
|
||||
public class UploadCompleteReqVO {
|
||||
|
||||
@NotBlank(message = "缺少 uploadId")
|
||||
@Schema(description = "上传 ID")
|
||||
private String uploadId;
|
||||
|
||||
/** 客户端探测到的时长(视频用) */
|
||||
@Schema(description = "时长(秒)")
|
||||
private Integer durationSec;
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
package com.fruitshorts.media.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Positive;
|
||||
import lombok.Data;
|
||||
@@ -10,14 +11,18 @@ import lombok.Data;
|
||||
public class UploadInitReqVO {
|
||||
|
||||
@NotBlank(message = "缺少文件名")
|
||||
@Schema(description = "文件名")
|
||||
private String fileName;
|
||||
|
||||
@Positive(message = "文件大小不合法")
|
||||
@Schema(description = "文件大小")
|
||||
private long fileSize;
|
||||
|
||||
/** DRAMA_COVER / EPISODE / AVATAR */
|
||||
@Schema(description = "业务类型")
|
||||
private String bizType = "EPISODE";
|
||||
|
||||
/** 客户端期望的分片大小,留空则用服务端配置 */
|
||||
@Schema(description = "分片大小")
|
||||
private Long chunkSize;
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
package com.fruitshorts.media.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
@@ -9,8 +10,12 @@ import lombok.Data;
|
||||
@AllArgsConstructor
|
||||
public class UploadInitRespVO {
|
||||
|
||||
@Schema(description = "上传 ID")
|
||||
private String uploadId;
|
||||
@Schema(description = "分片大小")
|
||||
private long chunkSize;
|
||||
@Schema(description = "总分片数")
|
||||
private int totalChunks;
|
||||
@Schema(description = "对象存储键")
|
||||
private String objectKey;
|
||||
}
|
||||
Loaded 100 of 140 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user