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:
Zhou Weidong committed 2026-10-17 02:24:25 +08:00
1 parent efe8af6c9b
commit 5f9483a86c
140 files changed
+1357 -19

No files matched your search

@@ -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 = "重置管理员密码")
@@ -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 = "修改用户状态")
@@ -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) {
@@ -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) {
@@ -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 = "删除评论")
@@ -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 = "修改系统设置")
@@ -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 = "重置创作者密码")
@@ -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() {
@@ -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 = "配置分集价格")
@@ -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() {
@@ -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() {
@@ -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 = "清理过期下载授权")
@@ -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 = "删除短剧类型")
@@ -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) {
@@ -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,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 = "调整剧集顺序")
@@ -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,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 = "删除菜单")
@@ -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) {
@@ -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 = "订单退款")
@@ -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() {
@@ -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 = "配置分集价格")
@@ -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 = "手动对账")
@@ -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,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 = "删除角色分类")
@@ -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 = "修改角色权限")
@@ -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 = "删除敏感词")
@@ -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 = "提交审核")
@@ -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 = "人工补币")
@@ -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}