From 5f9483a86c0996fd385fce395065d2f6461026ba Mon Sep 17 00:00:00 2001 From: Zhou Weidong <502333560@qq.com> Date: Sat, 17 Oct 2026 02:24:25 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=8E=A5=E5=8F=A3=E5=AD=97=E6=AE=B5?= =?UTF-8?q?=E8=A1=A5=20@Schema=20=E4=B8=AD=E6=96=87=E8=AF=B4=E6=98=8E=20+?= =?UTF-8?q?=20=E7=B2=BE=E7=AE=80=E5=86=97=E4=BD=99=E5=AD=97=E6=AE=B5=20+?= =?UTF-8?q?=20=E6=8E=A5=E5=85=A5=20Prometheus=20=E7=9B=91=E6=8E=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 全部 VO 字段补 @Schema(description) 中文说明,在线文档字段可读 - AppEpisodeVO 精简 duration/isFree 冗余字段(保留 durationSec/locked) - framework 引入 actuator + micrometer-registry-prometheus - SecurityConfig 放行 /actuator/prometheus,双服务配置 management 暴露指标 - 新增 deploy/docker-compose.yml + prometheus.yml 监控部署配置 --- deploy/docker-compose.yml | 32 ++++++++++++++++ deploy/prometheus.yml | 16 ++++++++ .../admin/controller/AdminUserController.java | 10 +++++ .../controller/AppUserAdminController.java | 8 ++++ .../admin/controller/AuthController.java | 8 ++++ .../admin/controller/BannerController.java | 10 +++++ .../controller/CommentAdminController.java | 7 ++++ .../admin/controller/ConfigController.java | 5 +++ .../controller/CreatorAdminController.java | 10 +++++ .../controller/CreatorCenterController.java | 9 +++++ .../controller/CreatorContentController.java | 16 ++++++++ .../controller/DashboardAdminController.java | 5 +++ .../admin/controller/DictController.java | 5 +++ .../controller/DownloadAdminController.java | 7 ++++ .../controller/DramaCategoryController.java | 7 ++++ .../admin/controller/DramaController.java | 14 +++++++ .../EntitlementAdminController.java | 6 +++ .../admin/controller/EpisodeController.java | 8 ++++ .../admin/controller/MediaController.java | 8 ++++ .../admin/controller/MenuController.java | 7 ++++ .../controller/OperationLogController.java | 5 +++ .../controller/OrderAdminController.java | 8 ++++ .../controller/PermissionController.java | 4 ++ .../controller/PriceAdminController.java | 5 +++ .../controller/ReconcileAdminController.java | 5 +++ .../controller/ReportAdminController.java | 5 +++ .../controller/RoleCategoryController.java | 7 ++++ .../admin/controller/RoleController.java | 11 ++++++ .../SensitiveWordAdminController.java | 7 ++++ .../controller/SubmissionAdminController.java | 6 +++ .../controller/WalletAdminController.java | 5 +++ .../admin/vo/AppUserWatchHistoryVO.java | 13 +++++++ .../src/main/resources/application.yml | 12 ++++++ .../app/controller/AppAuthController.java | 8 ++++ .../app/controller/AppCatalogController.java | 6 +++ .../app/controller/AppCommentController.java | 6 +++ .../app/controller/AppCommerceController.java | 7 ++++ .../app/controller/AppDownloadController.java | 11 ++++++ .../app/controller/AppDramaController.java | 5 +++ .../app/controller/AppFavoriteController.java | 6 +++ .../controller/AppInteractionController.java | 5 +++ .../app/controller/AppMeController.java | 9 +++++ .../app/controller/AppWatchController.java | 8 ++++ .../app/service/AppCatalogService.java | 3 -- .../com/fruitshorts/app/vo/AppBannerVO.java | 10 ++++- .../com/fruitshorts/app/vo/AppCategoryVO.java | 4 ++ .../fruitshorts/app/vo/AppDramaCardVO.java | 24 ++++++++++-- .../fruitshorts/app/vo/AppDramaDetailVO.java | 24 ++++++++++++ .../com/fruitshorts/app/vo/AppEpisodeVO.java | 22 +++++++---- .../com/fruitshorts/app/vo/AppFeedVO.java | 4 ++ .../com/fruitshorts/app/vo/AppSectionVO.java | 7 +++- .../src/main/resources/application.yml | 12 ++++++ fruitshorts-framework/pom.xml | 10 +++++ .../framework/security/SecurityConfig.java | 3 +- .../commerce/vo/CoinAdjustReqVO.java | 5 +++ .../commerce/vo/EntitlementGrantReqVO.java | 6 +++ .../commerce/vo/OrderQueryReqVO.java | 12 ++++++ .../fruitshorts/content/vo/BannerRespVO.java | 13 +++++++ .../content/vo/BannerSaveReqVO.java | 7 ++++ .../content/vo/DramaCategoryRespVO.java | 6 +++ .../content/vo/DramaCategorySaveReqVO.java | 4 ++ .../content/vo/DramaPageReqVO.java | 5 +++ .../fruitshorts/content/vo/DramaRespVO.java | 23 +++++++++++ .../content/vo/DramaSaveReqVO.java | 13 +++++++ .../content/vo/DramaStatusReqVO.java | 2 + .../fruitshorts/content/vo/EpisodeRespVO.java | 15 ++++++++ .../content/vo/EpisodeSaveReqVO.java | 11 ++++++ .../content/vo/EpisodeSortReqVO.java | 2 + .../fruitshorts/content/vo/PriceRespVO.java | 13 +++++++ .../content/vo/PriceSaveReqVO.java | 9 +++++ .../creator/vo/CreatorAccountOpenReqVO.java | 2 + .../creator/vo/CreatorAccountRespVO.java | 7 ++++ .../creator/vo/CreatorAttachReqVO.java | 2 + .../creator/vo/CreatorAuditReqVO.java | 4 ++ .../vo/CreatorCenterDramaQueryReqVO.java | 3 ++ .../creator/vo/CreatorCenterDramaVO.java | 23 +++++++++++ .../creator/vo/CreatorCenterNoticeVO.java | 7 ++++ .../creator/vo/CreatorCenterProfileVO.java | 13 +++++++ .../creator/vo/CreatorCenterTargetVO.java | 6 +++ .../creator/vo/CreatorDramaEditReqVO.java | 9 +++++ .../creator/vo/CreatorEpisodeReqVO.java | 7 ++++ .../creator/vo/CreatorQueryReqVO.java | 5 +++ .../creator/vo/CreatorSaveReqVO.java | 9 +++++ .../creator/vo/CreatorSubmitReqVO.java | 2 + .../creator/vo/SubmissionAuditReqVO.java | 4 ++ .../creator/vo/SubmissionQueryReqVO.java | 5 +++ .../interaction/vo/CommentAuditReqVO.java | 5 +++ .../interaction/vo/CommentPublishReqVO.java | 5 +++ .../interaction/vo/CommentQueryReqVO.java | 19 ++++++++++ .../interaction/vo/CommentRespVO.java | 36 ++++++++++++++++++ .../interaction/vo/LikeToggleReqVO.java | 3 ++ .../interaction/vo/LikeToggleRespVO.java | 4 ++ .../interaction/vo/ReportCreateReqVO.java | 5 +++ .../interaction/vo/ReportHandleReqVO.java | 8 ++++ .../interaction/vo/ReportQueryReqVO.java | 12 ++++++ .../interaction/vo/SensitiveWordReqVO.java | 11 ++++++ .../media/vo/MediaAssetRespVO.java | 11 ++++++ .../media/vo/UploadCompleteReqVO.java | 3 ++ .../fruitshorts/media/vo/UploadInitReqVO.java | 5 +++ .../media/vo/UploadInitRespVO.java | 5 +++ .../media/vo/UploadProgressRespVO.java | 12 ++++++ .../playback/vo/DownloadGrantReqVO.java | 4 ++ .../playback/vo/DownloadLicenseRespVO.java | 33 ++++++++++++++++ .../playback/vo/DownloadPolicyRespVO.java | 16 ++++++++ .../playback/vo/DownloadProgressReqVO.java | 12 ++++++ .../playback/vo/DownloadQueryReqVO.java | 10 +++++ .../playback/vo/DownloadSettingReqVO.java | 4 ++ .../playback/vo/FavoriteToggleReqVO.java | 2 + .../fruitshorts/playback/vo/PlayRespVO.java | 22 +++++++++++ .../playback/vo/ProgressRespVO.java | 14 +++++++ .../playback/vo/ProgressSaveReqVO.java | 11 ++++++ .../system/vo/AdminUserPageReqVO.java | 6 +++ .../system/vo/AdminUserRespVO.java | 22 +++++++++++ .../system/vo/AdminUserSaveReqVO.java | 10 +++++ .../fruitshorts/system/vo/ConfigItemVO.java | 6 +++ .../com/fruitshorts/system/vo/LoginReqVO.java | 3 ++ .../fruitshorts/system/vo/LoginRespVO.java | 20 ++++++++++ .../fruitshorts/system/vo/MenuSaveReqVO.java | 22 +++++++++++ .../com/fruitshorts/system/vo/MenuVO.java | 38 +++++++++++++++++++ .../system/vo/OperationLogPageReqVO.java | 10 +++++ .../system/vo/OperationLogRespVO.java | 31 +++++++++++++++ .../system/vo/PasswordChangeReqVO.java | 3 ++ .../system/vo/PermissionGroupVO.java | 8 ++++ .../fruitshorts/system/vo/ProfileRespVO.java | 18 +++++++++ .../system/vo/RoleCategoryRespVO.java | 8 ++++ .../system/vo/RoleCategorySaveReqVO.java | 3 ++ .../system/vo/RolePermissionSaveReqVO.java | 2 + .../com/fruitshorts/system/vo/RoleRespVO.java | 24 ++++++++++++ .../fruitshorts/system/vo/RoleSaveReqVO.java | 11 ++++++ .../user/vo/AppUserAdminRespVO.java | 2 + .../user/vo/AppUserQueryReqVO.java | 12 ++++++ .../fruitshorts/user/vo/AppUserRespVO.java | 30 +++++++++++++++ .../fruitshorts/user/vo/DeactivateReqVO.java | 4 ++ .../com/fruitshorts/user/vo/LoginReqVO.java | 14 +++++++ .../com/fruitshorts/user/vo/LogoutReqVO.java | 4 ++ .../com/fruitshorts/user/vo/OtpSendReqVO.java | 6 +++ .../user/vo/ProfileUpdateReqVO.java | 14 +++++++ .../com/fruitshorts/user/vo/RefreshReqVO.java | 2 + .../fruitshorts/user/vo/RegisterReqVO.java | 20 ++++++++++ .../com/fruitshorts/user/vo/TokenRespVO.java | 12 ++++++ 140 files changed, 1357 insertions(+), 19 deletions(-) create mode 100644 deploy/docker-compose.yml create mode 100644 deploy/prometheus.yml diff --git a/deploy/docker-compose.yml b/deploy/docker-compose.yml new file mode 100644 index 0000000..5c760d6 --- /dev/null +++ b/deploy/docker-compose.yml @@ -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: diff --git a/deploy/prometheus.yml b/deploy/prometheus.yml new file mode 100644 index 0000000..36b2177 --- /dev/null +++ b/deploy/prometheus.yml @@ -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"] diff --git a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/AdminUserController.java b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/AdminUserController.java index af3c139..caf7784 100644 --- a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/AdminUserController.java +++ b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/AdminUserController.java @@ -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> page(AdminUserPageReqVO req) { return Result.ok(adminUserService.page(req)); } + @Operation(summary = "管理员详情") @GetMapping("/{id}") @PreAuthorize("@ss.hasPermission('system:admin-user')") public Result 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 = "重置管理员密码") diff --git a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/AppUserAdminController.java b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/AppUserAdminController.java index 54c7a91..36ebcae 100644 --- a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/AppUserAdminController.java +++ b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/AppUserAdminController.java @@ -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> page(AppUserQueryReqVO req) { return Result.ok(appUserAdminService.page(req)); } + @Operation(summary = "用户详情") @GetMapping("/{id}") @PreAuthorize("@ss.hasPermission('app-user:list')") public Result detail(@PathVariable Long id) { return Result.ok(appUserAdminService.detail(id)); } + @Operation(summary = "封禁与申诉记录") @GetMapping("/{id}/ban-records") @PreAuthorize("@ss.hasPermission('app-user:list')") public Result> 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> 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 = "修改用户状态") diff --git a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/AuthController.java b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/AuthController.java index 7dd8a98..5cf4042 100644 --- a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/AuthController.java +++ b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/AuthController.java @@ -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 login(@Valid @RequestBody LoginReqVO req, HttpServletRequest request) { @@ -37,23 +41,27 @@ public class AuthController { } /** 当前用户的菜单路由树,结构与前端 element-plus-admin 的动态路由一致。 */ + @Operation(summary = "当前用户菜单路由树") @GetMapping("/menus") public Result> menus() { return Result.ok(authService.listMenus(SecurityUtils.getUserId())); } + @Operation(summary = "当前用户资料") @GetMapping("/profile") public Result profile() { return Result.ok(authService.profile(SecurityUtils.getUserId())); } /** JWT 无状态,登出由前端清除 token 即可。 */ + @Operation(summary = "登出(JWT 无状态,前端清除 token 即可)") @PostMapping("/logout") @OperationLog(module = "认证", action = "退出登录") public Result logout() { return Result.ok(); } + @Operation(summary = "修改密码") @PostMapping("/password") @OperationLog(module = "认证", action = "修改密码") public Result changePassword(@Valid @RequestBody PasswordChangeReqVO req) { diff --git a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/BannerController.java b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/BannerController.java index 1ad652f..70dac26 100644 --- a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/BannerController.java +++ b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/BannerController.java @@ -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> 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 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 sort(@RequestBody Map> body) { diff --git a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/CommentAdminController.java b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/CommentAdminController.java index 70ec501..ed3cb11 100644 --- a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/CommentAdminController.java +++ b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/CommentAdminController.java @@ -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> page(CommentQueryReqVO req) { @@ -40,12 +44,14 @@ public class CommentAdminController { } /** 审核留证:机审与人审的完整链路。 */ + @Operation(summary = "审核留证(机审与人审完整链路)") @GetMapping("/{id}/audit-records") @PreAuthorize("@ss.hasPermission('comment:list')") public Result> 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 = "删除评论") diff --git a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/ConfigController.java b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/ConfigController.java index 4828f92..63e1f1e 100644 --- a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/ConfigController.java +++ b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/ConfigController.java @@ -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() { return Result.ok(configService.list()); } + @Operation(summary = "批量修改系统配置") @PutMapping @PreAuthorize("@ss.hasPermission('system:role')") @OperationLog(module = "后台管理", action = "修改系统设置") diff --git a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/CreatorAdminController.java b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/CreatorAdminController.java index 52a92e3..0880e58 100644 --- a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/CreatorAdminController.java +++ b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/CreatorAdminController.java @@ -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> page(CreatorQueryReqVO req) { return Result.ok(creatorService.page(req)); } + @Operation(summary = "创作者详情") @GetMapping("/{id}") @PreAuthorize("@ss.hasPermission('creator:list')") public Result detail(@PathVariable Long id) { @@ -50,12 +55,14 @@ public class CreatorAdminController { } /** 资质文件:审核前要看证件原件。 */ + @Operation(summary = "资质文件(审核前查看证件原件)") @GetMapping("/{id}/documents") @PreAuthorize("@ss.hasPermission('creator:list')") public Result> 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 = "重置创作者密码") diff --git a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/CreatorCenterController.java b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/CreatorCenterController.java index d9a43dc..c658670 100644 --- a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/CreatorCenterController.java +++ b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/CreatorCenterController.java @@ -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 profile() { @@ -44,6 +48,7 @@ public class CreatorCenterController { } /** 我的作品列表(含最近一次提交的审核进度)。 */ + @Operation(summary = "我的作品列表(含最近一次提交的审核进度)") @GetMapping("/dramas/page") @PreAuthorize("@ss.hasPermission('creator-center:view')") public Result> 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 myDrama(@PathVariable Long id) { @@ -58,6 +64,7 @@ public class CreatorCenterController { } /** 我的通知:入驻审核结果 + 我提交内容的审核结果。 */ + @Operation(summary = "我的通知(入驻审核 + 内容审核结果)") @GetMapping("/notices") @PreAuthorize("@ss.hasPermission('creator-center:view')") public Result> notices() { @@ -65,6 +72,7 @@ public class CreatorCenterController { } /** 我的数据看板:播放 / 完播 / 收藏 / 评论 / 解锁收入概览(只读,只含自己的作品)。 */ + @Operation(summary = "我的数据看板(播放/完播/收藏/评论/解锁收入,只读)") @GetMapping("/dashboard") @PreAuthorize("@ss.hasPermission('creator-center:stat:view')") public Result> 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> impersonationTargets() { diff --git a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/CreatorContentController.java b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/CreatorContentController.java index 0bc128c..db6f3f8 100644 --- a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/CreatorContentController.java +++ b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/CreatorContentController.java @@ -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> 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> 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 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 = "配置分集价格") diff --git a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/DashboardAdminController.java b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/DashboardAdminController.java index d1f90f5..9d111d8 100644 --- a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/DashboardAdminController.java +++ b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/DashboardAdminController.java @@ -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> overview() { @@ -33,6 +37,7 @@ public class DashboardAdminController { } /** 转码看板:队列积压与失败任务明细。 */ + @Operation(summary = "转码看板:队列积压与失败任务明细") @GetMapping("/transcode") @PreAuthorize("@ss.hasPermission('dashboard:view')") public Result> transcode() { diff --git a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/DictController.java b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/DictController.java index e8e6dc3..b89c2b3 100644 --- a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/DictController.java +++ b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/DictController.java @@ -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> dramaCategories() { return Result.ok(dramaCategoryService.list()); } + @Operation(summary = "内容状态字典") @GetMapping("/content-status") @PreAuthorize("@ss.hasPermission('drama:list')") public Result>> contentStatus() { diff --git a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/DownloadAdminController.java b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/DownloadAdminController.java index 99f4506..6c7cdd8 100644 --- a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/DownloadAdminController.java +++ b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/DownloadAdminController.java @@ -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> page(DownloadQueryReqVO req) { return Result.ok(downloadService.page(req)); } + @Operation(summary = "授权与任务分布统计") @GetMapping("/stats") @PreAuthorize("@ss.hasPermission('download:list')") public Result> 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 = "清理过期下载授权") diff --git a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/DramaCategoryController.java b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/DramaCategoryController.java index 68a5adc..28de18d 100644 --- a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/DramaCategoryController.java +++ b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/DramaCategoryController.java @@ -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() { 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 = "删除短剧类型") diff --git a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/DramaController.java b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/DramaController.java index 2c3aed1..2f2f6a8 100644 --- a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/DramaController.java +++ b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/DramaController.java @@ -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> page(DramaPageReqVO req) { return Result.ok(dramaService.page(req)); } + @Operation(summary = "短剧详情") @GetMapping("/{id}") @PreAuthorize("@ss.hasPermission('drama:list')") public Result 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> reviewRecords(@PathVariable Long id) { diff --git a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/EntitlementAdminController.java b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/EntitlementAdminController.java index fbe57f5..5ed649d 100644 --- a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/EntitlementAdminController.java +++ b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/EntitlementAdminController.java @@ -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> 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 = "回收权益") diff --git a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/EpisodeController.java b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/EpisodeController.java index 3010bd4..8e21609 100644 --- a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/EpisodeController.java +++ b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/EpisodeController.java @@ -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(@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 = "调整剧集顺序") diff --git a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/MediaController.java b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/MediaController.java index 79965bf..e453008 100644 --- a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/MediaController.java +++ b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/MediaController.java @@ -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 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 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 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 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 get(@PathVariable Long id) { diff --git a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/MenuController.java b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/MenuController.java index 8fcfb6b..32472f3 100644 --- a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/MenuController.java +++ b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/MenuController.java @@ -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> 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 = "删除菜单") diff --git a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/OperationLogController.java b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/OperationLogController.java index 8240202..bd58a95 100644 --- a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/OperationLogController.java +++ b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/OperationLogController.java @@ -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> page(OperationLogPageReqVO req) { return Result.ok(operationLogService.page(req)); } + @Operation(summary = "操作日志详情") @GetMapping("/{id}") @PreAuthorize("@ss.hasPermission('log:list')") public Result get(@PathVariable Long id) { diff --git a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/OrderAdminController.java b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/OrderAdminController.java index 39f7188..a15a790 100644 --- a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/OrderAdminController.java +++ b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/OrderAdminController.java @@ -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> page(OrderQueryReqVO req) { return Result.ok(orderService.page(req)); } + @Operation(summary = "订单详情") @GetMapping("/{orderNo}") @PreAuthorize("@ss.hasPermission('order:list')") public Result detail(@PathVariable String orderNo) { @@ -44,6 +49,7 @@ public class OrderAdminController { } /** 订单状态流转流水:支付争议时的证据链。 */ + @Operation(summary = "订单状态流转流水(支付争议证据链)") @GetMapping("/{orderNo}/events") @PreAuthorize("@ss.hasPermission('order:list')") public Result> 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 = "订单退款") diff --git a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/PermissionController.java b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/PermissionController.java index 6d20842..695ca47 100644 --- a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/PermissionController.java +++ b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/PermissionController.java @@ -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> groups() { diff --git a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/PriceAdminController.java b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/PriceAdminController.java index 6420f29..0d17000 100644 --- a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/PriceAdminController.java +++ b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/PriceAdminController.java @@ -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 detail(@RequestParam Long dramaId) { return Result.ok(priceService.detail(dramaId)); } + @Operation(summary = "保存价格配置(改价立即影响播放与下载判定)") @PutMapping @PreAuthorize("@ss.hasPermission('price:update')") @OperationLog(module = "定价管理", action = "配置分集价格") diff --git a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/ReconcileAdminController.java b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/ReconcileAdminController.java index e6ab683..3c2eaf4 100644 --- a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/ReconcileAdminController.java +++ b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/ReconcileAdminController.java @@ -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> 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 = "手动对账") diff --git a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/ReportAdminController.java b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/ReportAdminController.java index c177d6c..831dd8c 100644 --- a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/ReportAdminController.java +++ b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/ReportAdminController.java @@ -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> page(ReportQueryReqVO req) { @@ -34,6 +38,7 @@ public class ReportAdminController { } /** 处理工单:结论成立会联动驳回被举报评论,可选择同时封禁被举报用户。 */ + @Operation(summary = "处理工单(结论成立联动驳回被举报评论,可选择同时封禁用户)") @PutMapping("/{id}/handle") @PreAuthorize("@ss.hasPermission('report:handle')") @OperationLog(module = "内容治理", action = "处理举报") diff --git a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/RoleCategoryController.java b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/RoleCategoryController.java index c2b0d1c..266bc37 100644 --- a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/RoleCategoryController.java +++ b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/RoleCategoryController.java @@ -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() { 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 = "删除角色分类") diff --git a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/RoleController.java b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/RoleController.java index f825b5f..98179c9 100644 --- a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/RoleController.java +++ b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/RoleController.java @@ -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> 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() { return Result.ok(roleService.listAll()); } + @Operation(summary = "角色详情") @GetMapping("/{id}") @PreAuthorize("@ss.hasPermission('system:role')") public Result 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> permissions(@PathVariable Long id) { return Result.ok(roleService.listCodesByRoleId(id)); } + @Operation(summary = "保存角色权限") @PutMapping("/{id}/permissions") @PreAuthorize("@ss.hasPermission('system:role')") @OperationLog(module = "后台管理", action = "修改角色权限") diff --git a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/SensitiveWordAdminController.java b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/SensitiveWordAdminController.java index 736ca09..a9f2997 100644 --- a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/SensitiveWordAdminController.java +++ b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/SensitiveWordAdminController.java @@ -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> 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 = "删除敏感词") diff --git a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/SubmissionAdminController.java b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/SubmissionAdminController.java index 6ec1e8a..b09b33b 100644 --- a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/SubmissionAdminController.java +++ b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/SubmissionAdminController.java @@ -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> page(SubmissionQueryReqVO req) { return Result.ok(submissionService.page(req)); } + @Operation(summary = "内容提交详情") @GetMapping("/{id}") @PreAuthorize("@ss.hasPermission('submission:list')") public Result detail(@PathVariable Long id) { return Result.ok(submissionService.getExisting(id)); } + @Operation(summary = "审核内容提交(通过后按类型落短剧状态机)") @PutMapping("/{id}/audit") @PreAuthorize("@ss.hasPermission('submission:audit')") @OperationLog(module = "内容审核", action = "提交审核") diff --git a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/WalletAdminController.java b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/WalletAdminController.java index 7ffbd7b..3dbafe1 100644 --- a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/WalletAdminController.java +++ b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/controller/WalletAdminController.java @@ -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> 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 = "人工补币") diff --git a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/vo/AppUserWatchHistoryVO.java b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/vo/AppUserWatchHistoryVO.java index 7bd5557..ac3124f 100644 --- a/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/vo/AppUserWatchHistoryVO.java +++ b/fruitshorts-admin-api/src/main/java/com/fruitshorts/admin/vo/AppUserWatchHistoryVO.java @@ -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; } diff --git a/fruitshorts-admin-api/src/main/resources/application.yml b/fruitshorts-admin-api/src/main/resources/application.yml index 5b4990d..8f8c2f8 100644 --- a/fruitshorts-admin-api/src/main/resources/application.yml +++ b/fruitshorts-admin-api/src/main/resources/application.yml @@ -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} diff --git a/fruitshorts-app-api/src/main/java/com/fruitshorts/app/controller/AppAuthController.java b/fruitshorts-app-api/src/main/java/com/fruitshorts/app/controller/AppAuthController.java index c2ec044..3d1c58d 100644 --- a/fruitshorts-app-api/src/main/java/com/fruitshorts/app/controller/AppAuthController.java +++ b/fruitshorts-app-api/src/main/java/com/fruitshorts/app/controller/AppAuthController.java @@ -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 sendOtp(@Valid @RequestBody OtpSendReqVO req, HttpServletRequest request) { otpService.send(req, WebUtils.getClientIp(request)); return Result.ok(); } + @Operation(summary = "注册账号(手机号/邮箱 + 验证码),返回令牌") @PostMapping("/register") public Result register(@Valid @RequestBody RegisterReqVO req, HttpServletRequest request) { return Result.ok(authService.register(req, WebUtils.getClientIp(request))); } + @Operation(summary = "登录(验证码或密码),返回令牌") @PostMapping("/login") public Result login(@Valid @RequestBody LoginReqVO req, HttpServletRequest request) { return Result.ok(authService.login(req, WebUtils.getClientIp(request))); } + @Operation(summary = "刷新令牌(refresh token 轮换)") @PostMapping("/refresh") public Result refresh(@Valid @RequestBody RefreshReqVO req) { return Result.ok(authService.refresh(req.getRefreshToken())); } /** 登出:默认只吊销当前设备的会话,allDevices=true 时吊销全部。 */ + @Operation(summary = "登出(allDevices=true 时吊销全部设备会话)") @PostMapping("/logout") public Result logout(@RequestBody(required = false) LogoutReqVO req) { authService.logout(SecurityUtils.getUserIdOrNull(), req == null ? new LogoutReqVO() : req); diff --git a/fruitshorts-app-api/src/main/java/com/fruitshorts/app/controller/AppCatalogController.java b/fruitshorts-app-api/src/main/java/com/fruitshorts/app/controller/AppCatalogController.java index ccb3ab6..b35ab51 100644 --- a/fruitshorts-app-api/src/main/java/com/fruitshorts/app/controller/AppCatalogController.java +++ b/fruitshorts-app-api/src/main/java/com/fruitshorts/app/controller/AppCatalogController.java @@ -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 homeFeed() { return Result.ok(appCatalogService.homeFeed()); } + @Operation(summary = "发现页聚合数据") @GetMapping("/discover/feed") public Result discoverFeed() { return Result.ok(appCatalogService.discoverFeed()); } + @Operation(summary = "分类列表") @GetMapping("/categories") public Result> categories() { return Result.ok(appCatalogService.categories()); diff --git a/fruitshorts-app-api/src/main/java/com/fruitshorts/app/controller/AppCommentController.java b/fruitshorts-app-api/src/main/java/com/fruitshorts/app/controller/AppCommentController.java index fcff50c..91ba514 100644 --- a/fruitshorts-app-api/src/main/java/com/fruitshorts/app/controller/AppCommentController.java +++ b/fruitshorts-app-api/src/main/java/com/fruitshorts/app/controller/AppCommentController.java @@ -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 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> 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 delete(@PathVariable Long id) { commentService.delete(SecurityUtils.getAppUserId(), id); diff --git a/fruitshorts-app-api/src/main/java/com/fruitshorts/app/controller/AppCommerceController.java b/fruitshorts-app-api/src/main/java/com/fruitshorts/app/controller/AppCommerceController.java index c685cec..9ffbd13 100644 --- a/fruitshorts-app-api/src/main/java/com/fruitshorts/app/controller/AppCommerceController.java +++ b/fruitshorts-app-api/src/main/java/com/fruitshorts/app/controller/AppCommerceController.java @@ -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> wallet() { Long userId = SecurityUtils.getAppUserId(); @@ -46,17 +50,20 @@ public class AppCommerceController { } /** 金币解锁分集:幂等,重复点击不会重复扣币。 */ + @Operation(summary = "金币解锁分集(幂等,重复调用不重复扣币)") @PostMapping("/episodes/{episodeId}/unlock") public Result> unlock(@PathVariable Long episodeId) { return Result.ok(unlockService.unlock(SecurityUtils.getAppUserId(), episodeId)); } + @Operation(summary = "我的订单列表") @GetMapping("/orders") public Result> orders() { return Result.ok(orderService.listByUser(SecurityUtils.getAppUserId())); } /** 提交商店票据。第一阶段商店未接入,会返回明确的"尚未配置"。 */ + @Operation(summary = "提交商店票据(IAP/Google Play;商店未接入时返回明确业务提示)") @PostMapping("/orders/verify") public Result verify(@RequestBody Map body) { return Result.ok(orderService.verifyAndDeliver(SecurityUtils.getAppUserId(), diff --git a/fruitshorts-app-api/src/main/java/com/fruitshorts/app/controller/AppDownloadController.java b/fruitshorts-app-api/src/main/java/com/fruitshorts/app/controller/AppDownloadController.java index 5fb6c81..21c9e19 100644 --- a/fruitshorts-app-api/src/main/java/com/fruitshorts/app/controller/AppDownloadController.java +++ b/fruitshorts-app-api/src/main/java/com/fruitshorts/app/controller/AppDownloadController.java @@ -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; *

服务端只发授权与地址,分片由客户端向 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 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(@RequestParam(required = false) String deviceId) { return Result.ok(downloadService.list(SecurityUtils.getAppUserId(), deviceId)); } + @Operation(summary = "下载策略与配额(单设备上限/授权天数/仅 Wi-Fi/清晰度上限)") @GetMapping("/policy") public Result policy(@RequestParam(required = false) String deviceId) { return Result.ok(downloadService.policy(SecurityUtils.getAppUserId(), deviceId)); } /** 仅 Wi-Fi 下载、清晰度上限等偏好。 */ + @Operation(summary = "更新下载偏好(仅 Wi-Fi 下载、最高清晰度)") @PutMapping("/settings") public Result updateSettings(@RequestBody DownloadSettingReqVO req) { downloadService.updateSettings(SecurityUtils.getAppUserId(), req); @@ -64,6 +71,7 @@ public class AppDownloadController { } /** 断点续传前重新取一次地址:授权不变,只有地址是短时效的。 */ + @Operation(summary = "断点续传前重新获取下载地址(授权不变,地址短时效)") @GetMapping("/{episodeId}/url") public Result 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 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 revoke(@PathVariable Long episodeId, @RequestParam(required = false) String deviceId, @@ -89,6 +99,7 @@ public class AppDownloadController { } /** 清空当前设备的全部下载授权。 */ + @Operation(summary = "清空当前设备全部下载(返回清除条数)") @DeleteMapping public Result clear(@RequestParam(required = false) String deviceId, HttpServletRequest request) { diff --git a/fruitshorts-app-api/src/main/java/com/fruitshorts/app/controller/AppDramaController.java b/fruitshorts-app-api/src/main/java/com/fruitshorts/app/controller/AppDramaController.java index cb4fb24..9065eaa 100644 --- a/fruitshorts-app-api/src/main/java/com/fruitshorts/app/controller/AppDramaController.java +++ b/fruitshorts-app-api/src/main/java/com/fruitshorts/app/controller/AppDramaController.java @@ -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 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 play(@PathVariable Long id, HttpServletRequest request) { return Result.ok(playbackService.play( diff --git a/fruitshorts-app-api/src/main/java/com/fruitshorts/app/controller/AppFavoriteController.java b/fruitshorts-app-api/src/main/java/com/fruitshorts/app/controller/AppFavoriteController.java index f352a94..961011c 100644 --- a/fruitshorts-app-api/src/main/java/com/fruitshorts/app/controller/AppFavoriteController.java +++ b/fruitshorts-app-api/src/main/java/com/fruitshorts/app/controller/AppFavoriteController.java @@ -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 toggle(@Valid @RequestBody FavoriteToggleReqVO req) { return Result.ok(favoriteService.toggle(SecurityUtils.getAppUserId(), req.getDramaId())); } /** 收藏列表,卡片结构与首页一致。 */ + @Operation(summary = "收藏列表(卡片结构与首页一致)") @GetMapping public Result> list() { return Result.ok(appCatalogService.toCards( favoriteService.listDramas(SecurityUtils.getAppUserId()))); } + @Operation(summary = "取消收藏") @DeleteMapping("/{dramaId}") public Result remove(@PathVariable Long dramaId) { favoriteService.remove(SecurityUtils.getAppUserId(), dramaId); diff --git a/fruitshorts-app-api/src/main/java/com/fruitshorts/app/controller/AppInteractionController.java b/fruitshorts-app-api/src/main/java/com/fruitshorts/app/controller/AppInteractionController.java index c02554a..33b9a5a 100644 --- a/fruitshorts-app-api/src/main/java/com/fruitshorts/app/controller/AppInteractionController.java +++ b/fruitshorts-app-api/src/main/java/com/fruitshorts/app/controller/AppInteractionController.java @@ -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 toggleLike(@Valid @RequestBody LikeToggleReqVO req) { return Result.ok(likeService.toggle(SecurityUtils.getAppUserId(), req)); } /** 提交举报:同一用户对同一目标只保留一条待处理工单。 */ + @Operation(summary = "提交举报(评论/用户/短剧,同一目标仅保留一条待处理工单)") @PostMapping("/reports") public Result report(@Valid @RequestBody ReportCreateReqVO req) { return Result.ok(reportService.create(SecurityUtils.getAppUserId(), req)); diff --git a/fruitshorts-app-api/src/main/java/com/fruitshorts/app/controller/AppMeController.java b/fruitshorts-app-api/src/main/java/com/fruitshorts/app/controller/AppMeController.java index 0b57a66..ead02e8 100644 --- a/fruitshorts-app-api/src/main/java/com/fruitshorts/app/controller/AppMeController.java +++ b/fruitshorts-app-api/src/main/java/com/fruitshorts/app/controller/AppMeController.java @@ -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 me() { return Result.ok(userService.me(SecurityUtils.getAppUserId())); } + @Operation(summary = "修改资料(昵称/头像/性别/生日/语言/时区/区域)") @PutMapping public Result update(@Valid @RequestBody ProfileUpdateReqVO req) { return Result.ok(userService.updateProfile(SecurityUtils.getAppUserId(), req)); } + @Operation(summary = "登录设备列表") @GetMapping("/devices") public Result> devices() { return Result.ok(userService.devices(SecurityUtils.getAppUserId())); } /** 商店与隐私法规要求的数据导出,返回账号侧数据;内容侧数据由客户端自行下载。 */ + @Operation(summary = "数据导出(商店与隐私法规要求,返回账号侧数据)") @GetMapping("/export") public Result> export() { return Result.ok(userService.exportAccount(SecurityUtils.getAppUserId())); } /** 申请注销:立即登出全部设备,进入冷静期,期间可撤销。 */ + @Operation(summary = "申请注销(进入冷静期并登出全部设备,期间可撤销)") @PostMapping("/deactivate") public Result deactivate(@RequestBody(required = false) DeactivateReqVO req) { return Result.ok(userService.requestDeactivation(SecurityUtils.getAppUserId(), req)); } + @Operation(summary = "撤销注销申请") @PostMapping("/deactivate/cancel") public Result cancelDeactivate() { userService.cancelDeactivation(SecurityUtils.getAppUserId()); diff --git a/fruitshorts-app-api/src/main/java/com/fruitshorts/app/controller/AppWatchController.java b/fruitshorts-app-api/src/main/java/com/fruitshorts/app/controller/AppWatchController.java index 2183860..393722a 100644 --- a/fruitshorts-app-api/src/main/java/com/fruitshorts/app/controller/AppWatchController.java +++ b/fruitshorts-app-api/src/main/java/com/fruitshorts/app/controller/AppWatchController.java @@ -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 save(@Valid @RequestBody ProgressSaveReqVO req) { return Result.ok(progressService.save(SecurityUtils.getAppUserId(), req)); } /** 某部剧的续看位置,进详情页时用它决定"续看第 N 集"。 */ + @Operation(summary = "查询某部剧的续看位置") @GetMapping("/progress") public Result ofDrama(@RequestParam Long dramaId) { return Result.ok(progressService.ofDrama(SecurityUtils.getAppUserId(), dramaId)); } + @Operation(summary = "最近观看列表") @GetMapping("/recent") public Result> recent(@RequestParam(defaultValue = "20") int limit) { return Result.ok(progressService.recent(SecurityUtils.getAppUserId(), limit)); } + @Operation(summary = "删除某部剧的观看记录") @DeleteMapping("/progress/{dramaId}") public Result remove(@PathVariable Long dramaId) { progressService.remove(SecurityUtils.getAppUserId(), dramaId); return Result.ok(); } + @Operation(summary = "清空全部观看记录") @DeleteMapping("/progress") public Result clear() { progressService.clear(SecurityUtils.getAppUserId()); diff --git a/fruitshorts-app-api/src/main/java/com/fruitshorts/app/service/AppCatalogService.java b/fruitshorts-app-api/src/main/java/com/fruitshorts/app/service/AppCatalogService.java index 7013217..057e6fd 100644 --- a/fruitshorts-app-api/src/main/java/com/fruitshorts/app/service/AppCatalogService.java +++ b/fruitshorts-app-api/src/main/java/com/fruitshorts/app/service/AppCatalogService.java @@ -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) { diff --git a/fruitshorts-app-api/src/main/java/com/fruitshorts/app/vo/AppBannerVO.java b/fruitshorts-app-api/src/main/java/com/fruitshorts/app/vo/AppBannerVO.java index ab4c09f..baa6689 100644 --- a/fruitshorts-app-api/src/main/java/com/fruitshorts/app/vo/AppBannerVO.java +++ b/fruitshorts-app-api/src/main/java/com/fruitshorts/app/vo/AppBannerVO.java @@ -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; } diff --git a/fruitshorts-app-api/src/main/java/com/fruitshorts/app/vo/AppCategoryVO.java b/fruitshorts-app-api/src/main/java/com/fruitshorts/app/vo/AppCategoryVO.java index 62c1c50..c7d8134 100644 --- a/fruitshorts-app-api/src/main/java/com/fruitshorts/app/vo/AppCategoryVO.java +++ b/fruitshorts-app-api/src/main/java/com/fruitshorts/app/vo/AppCategoryVO.java @@ -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; } diff --git a/fruitshorts-app-api/src/main/java/com/fruitshorts/app/vo/AppDramaCardVO.java b/fruitshorts-app-api/src/main/java/com/fruitshorts/app/vo/AppDramaCardVO.java index 4384d94..a25a22f 100644 --- a/fruitshorts-app-api/src/main/java/com/fruitshorts/app/vo/AppDramaCardVO.java +++ b/fruitshorts-app-api/src/main/java/com/fruitshorts/app/vo/AppDramaCardVO.java @@ -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; } diff --git a/fruitshorts-app-api/src/main/java/com/fruitshorts/app/vo/AppDramaDetailVO.java b/fruitshorts-app-api/src/main/java/com/fruitshorts/app/vo/AppDramaDetailVO.java index 799cf34..34642b7 100644 --- a/fruitshorts-app-api/src/main/java/com/fruitshorts/app/vo/AppDramaDetailVO.java +++ b/fruitshorts-app-api/src/main/java/com/fruitshorts/app/vo/AppDramaDetailVO.java @@ -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 episodes; } diff --git a/fruitshorts-app-api/src/main/java/com/fruitshorts/app/vo/AppEpisodeVO.java b/fruitshorts-app-api/src/main/java/com/fruitshorts/app/vo/AppEpisodeVO.java index 0deb328..72de4f4 100644 --- a/fruitshorts-app-api/src/main/java/com/fruitshorts/app/vo/AppEpisodeVO.java +++ b/fruitshorts-app-api/src/main/java/com/fruitshorts/app/vo/AppEpisodeVO.java @@ -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; } diff --git a/fruitshorts-app-api/src/main/java/com/fruitshorts/app/vo/AppFeedVO.java b/fruitshorts-app-api/src/main/java/com/fruitshorts/app/vo/AppFeedVO.java index 34ec814..69a4a34 100644 --- a/fruitshorts-app-api/src/main/java/com/fruitshorts/app/vo/AppFeedVO.java +++ b/fruitshorts-app-api/src/main/java/com/fruitshorts/app/vo/AppFeedVO.java @@ -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 banners; + + @Schema(description = "分区列表") private List sections; } diff --git a/fruitshorts-app-api/src/main/java/com/fruitshorts/app/vo/AppSectionVO.java b/fruitshorts-app-api/src/main/java/com/fruitshorts/app/vo/AppSectionVO.java index 86bc787..c51bff8 100644 --- a/fruitshorts-app-api/src/main/java/com/fruitshorts/app/vo/AppSectionVO.java +++ b/fruitshorts-app-api/src/main/java/com/fruitshorts/app/vo/AppSectionVO.java @@ -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 dramas; } diff --git a/fruitshorts-app-api/src/main/resources/application.yml b/fruitshorts-app-api/src/main/resources/application.yml index b0d589b..cdcac69 100644 --- a/fruitshorts-app-api/src/main/resources/application.yml +++ b/fruitshorts-app-api/src/main/resources/application.yml @@ -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} diff --git a/fruitshorts-framework/pom.xml b/fruitshorts-framework/pom.xml index a22de97..1509589 100644 --- a/fruitshorts-framework/pom.xml +++ b/fruitshorts-framework/pom.xml @@ -66,5 +66,15 @@ org.springdoc springdoc-openapi-starter-webmvc-ui + + + + org.springframework.boot + spring-boot-starter-actuator + + + io.micrometer + micrometer-registry-prometheus + diff --git a/fruitshorts-framework/src/main/java/com/fruitshorts/framework/security/SecurityConfig.java b/fruitshorts-framework/src/main/java/com/fruitshorts/framework/security/SecurityConfig.java index 4e8ba0d..b0711b3 100644 --- a/fruitshorts-framework/src/main/java/com/fruitshorts/framework/security/SecurityConfig.java +++ b/fruitshorts-framework/src/main/java/com/fruitshorts/framework/security/SecurityConfig.java @@ -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; diff --git a/fruitshorts-module-commerce/src/main/java/com/fruitshorts/commerce/vo/CoinAdjustReqVO.java b/fruitshorts-module-commerce/src/main/java/com/fruitshorts/commerce/vo/CoinAdjustReqVO.java index 7e1bfdb..08bad7b 100644 --- a/fruitshorts-module-commerce/src/main/java/com/fruitshorts/commerce/vo/CoinAdjustReqVO.java +++ b/fruitshorts-module-commerce/src/main/java/com/fruitshorts/commerce/vo/CoinAdjustReqVO.java @@ -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; } diff --git a/fruitshorts-module-commerce/src/main/java/com/fruitshorts/commerce/vo/EntitlementGrantReqVO.java b/fruitshorts-module-commerce/src/main/java/com/fruitshorts/commerce/vo/EntitlementGrantReqVO.java index 3397690..3167dc3 100644 --- a/fruitshorts-module-commerce/src/main/java/com/fruitshorts/commerce/vo/EntitlementGrantReqVO.java +++ b/fruitshorts-module-commerce/src/main/java/com/fruitshorts/commerce/vo/EntitlementGrantReqVO.java @@ -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; } diff --git a/fruitshorts-module-commerce/src/main/java/com/fruitshorts/commerce/vo/OrderQueryReqVO.java b/fruitshorts-module-commerce/src/main/java/com/fruitshorts/commerce/vo/OrderQueryReqVO.java index 901dce3..09ca17f 100644 --- a/fruitshorts-module-commerce/src/main/java/com/fruitshorts/commerce/vo/OrderQueryReqVO.java +++ b/fruitshorts-module-commerce/src/main/java/com/fruitshorts/commerce/vo/OrderQueryReqVO.java @@ -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; } diff --git a/fruitshorts-module-content/src/main/java/com/fruitshorts/content/vo/BannerRespVO.java b/fruitshorts-module-content/src/main/java/com/fruitshorts/content/vo/BannerRespVO.java index 7415005..abc6461 100644 --- a/fruitshorts-module-content/src/main/java/com/fruitshorts/content/vo/BannerRespVO.java +++ b/fruitshorts-module-content/src/main/java/com/fruitshorts/content/vo/BannerRespVO.java @@ -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; } diff --git a/fruitshorts-module-content/src/main/java/com/fruitshorts/content/vo/BannerSaveReqVO.java b/fruitshorts-module-content/src/main/java/com/fruitshorts/content/vo/BannerSaveReqVO.java index 528695b..a911999 100644 --- a/fruitshorts-module-content/src/main/java/com/fruitshorts/content/vo/BannerSaveReqVO.java +++ b/fruitshorts-module-content/src/main/java/com/fruitshorts/content/vo/BannerSaveReqVO.java @@ -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; } diff --git a/fruitshorts-module-content/src/main/java/com/fruitshorts/content/vo/DramaCategoryRespVO.java b/fruitshorts-module-content/src/main/java/com/fruitshorts/content/vo/DramaCategoryRespVO.java index f5abb85..910c845 100644 --- a/fruitshorts-module-content/src/main/java/com/fruitshorts/content/vo/DramaCategoryRespVO.java +++ b/fruitshorts-module-content/src/main/java/com/fruitshorts/content/vo/DramaCategoryRespVO.java @@ -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; } diff --git a/fruitshorts-module-content/src/main/java/com/fruitshorts/content/vo/DramaCategorySaveReqVO.java b/fruitshorts-module-content/src/main/java/com/fruitshorts/content/vo/DramaCategorySaveReqVO.java index 56c6dd8..10fe86f 100644 --- a/fruitshorts-module-content/src/main/java/com/fruitshorts/content/vo/DramaCategorySaveReqVO.java +++ b/fruitshorts-module-content/src/main/java/com/fruitshorts/content/vo/DramaCategorySaveReqVO.java @@ -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; } diff --git a/fruitshorts-module-content/src/main/java/com/fruitshorts/content/vo/DramaPageReqVO.java b/fruitshorts-module-content/src/main/java/com/fruitshorts/content/vo/DramaPageReqVO.java index faee6fe..a513725 100644 --- a/fruitshorts-module-content/src/main/java/com/fruitshorts/content/vo/DramaPageReqVO.java +++ b/fruitshorts-module-content/src/main/java/com/fruitshorts/content/vo/DramaPageReqVO.java @@ -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; } diff --git a/fruitshorts-module-content/src/main/java/com/fruitshorts/content/vo/DramaRespVO.java b/fruitshorts-module-content/src/main/java/com/fruitshorts/content/vo/DramaRespVO.java index 66f416c..8ec2d0f 100644 --- a/fruitshorts-module-content/src/main/java/com/fruitshorts/content/vo/DramaRespVO.java +++ b/fruitshorts-module-content/src/main/java/com/fruitshorts/content/vo/DramaRespVO.java @@ -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; } diff --git a/fruitshorts-module-content/src/main/java/com/fruitshorts/content/vo/DramaSaveReqVO.java b/fruitshorts-module-content/src/main/java/com/fruitshorts/content/vo/DramaSaveReqVO.java index f216637..f37e8ff 100644 --- a/fruitshorts-module-content/src/main/java/com/fruitshorts/content/vo/DramaSaveReqVO.java +++ b/fruitshorts-module-content/src/main/java/com/fruitshorts/content/vo/DramaSaveReqVO.java @@ -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; } diff --git a/fruitshorts-module-content/src/main/java/com/fruitshorts/content/vo/DramaStatusReqVO.java b/fruitshorts-module-content/src/main/java/com/fruitshorts/content/vo/DramaStatusReqVO.java index 00c033c..58deb1a 100644 --- a/fruitshorts-module-content/src/main/java/com/fruitshorts/content/vo/DramaStatusReqVO.java +++ b/fruitshorts-module-content/src/main/java/com/fruitshorts/content/vo/DramaStatusReqVO.java @@ -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; } diff --git a/fruitshorts-module-content/src/main/java/com/fruitshorts/content/vo/EpisodeRespVO.java b/fruitshorts-module-content/src/main/java/com/fruitshorts/content/vo/EpisodeRespVO.java index 3ba15c2..368a8eb 100644 --- a/fruitshorts-module-content/src/main/java/com/fruitshorts/content/vo/EpisodeRespVO.java +++ b/fruitshorts-module-content/src/main/java/com/fruitshorts/content/vo/EpisodeRespVO.java @@ -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; } diff --git a/fruitshorts-module-content/src/main/java/com/fruitshorts/content/vo/EpisodeSaveReqVO.java b/fruitshorts-module-content/src/main/java/com/fruitshorts/content/vo/EpisodeSaveReqVO.java index def045c..dfbc971 100644 --- a/fruitshorts-module-content/src/main/java/com/fruitshorts/content/vo/EpisodeSaveReqVO.java +++ b/fruitshorts-module-content/src/main/java/com/fruitshorts/content/vo/EpisodeSaveReqVO.java @@ -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; } diff --git a/fruitshorts-module-content/src/main/java/com/fruitshorts/content/vo/EpisodeSortReqVO.java b/fruitshorts-module-content/src/main/java/com/fruitshorts/content/vo/EpisodeSortReqVO.java index 536c1b7..4578ae7 100644 --- a/fruitshorts-module-content/src/main/java/com/fruitshorts/content/vo/EpisodeSortReqVO.java +++ b/fruitshorts-module-content/src/main/java/com/fruitshorts/content/vo/EpisodeSortReqVO.java @@ -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 ids; } diff --git a/fruitshorts-module-content/src/main/java/com/fruitshorts/content/vo/PriceRespVO.java b/fruitshorts-module-content/src/main/java/com/fruitshorts/content/vo/PriceRespVO.java index 8171c17..6dd444a 100644 --- a/fruitshorts-module-content/src/main/java/com/fruitshorts/content/vo/PriceRespVO.java +++ b/fruitshorts-module-content/src/main/java/com/fruitshorts/content/vo/PriceRespVO.java @@ -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 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; } } diff --git a/fruitshorts-module-content/src/main/java/com/fruitshorts/content/vo/PriceSaveReqVO.java b/fruitshorts-module-content/src/main/java/com/fruitshorts/content/vo/PriceSaveReqVO.java index 39daf40..3b7f9b8 100644 --- a/fruitshorts-module-content/src/main/java/com/fruitshorts/content/vo/PriceSaveReqVO.java +++ b/fruitshorts-module-content/src/main/java/com/fruitshorts/content/vo/PriceSaveReqVO.java @@ -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 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; } } diff --git a/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/CreatorAccountOpenReqVO.java b/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/CreatorAccountOpenReqVO.java index 9e76c46..9f6f7fd 100644 --- a/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/CreatorAccountOpenReqVO.java +++ b/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/CreatorAccountOpenReqVO.java @@ -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; } diff --git a/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/CreatorAccountRespVO.java b/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/CreatorAccountRespVO.java index f72faf8..30b8178 100644 --- a/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/CreatorAccountRespVO.java +++ b/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/CreatorAccountRespVO.java @@ -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; } diff --git a/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/CreatorAttachReqVO.java b/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/CreatorAttachReqVO.java index af8ea2f..2e0e14a 100644 --- a/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/CreatorAttachReqVO.java +++ b/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/CreatorAttachReqVO.java @@ -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; } diff --git a/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/CreatorAuditReqVO.java b/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/CreatorAuditReqVO.java index bf97d35..173c922 100644 --- a/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/CreatorAuditReqVO.java +++ b/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/CreatorAuditReqVO.java @@ -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; } diff --git a/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/CreatorCenterDramaQueryReqVO.java b/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/CreatorCenterDramaQueryReqVO.java index e5897d6..246b7ff 100644 --- a/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/CreatorCenterDramaQueryReqVO.java +++ b/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/CreatorCenterDramaQueryReqVO.java @@ -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; } diff --git a/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/CreatorCenterDramaVO.java b/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/CreatorCenterDramaVO.java index f5d7564..c929dcd 100644 --- a/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/CreatorCenterDramaVO.java +++ b/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/CreatorCenterDramaVO.java @@ -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; } diff --git a/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/CreatorCenterNoticeVO.java b/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/CreatorCenterNoticeVO.java index cc5b5f1..953b030 100644 --- a/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/CreatorCenterNoticeVO.java +++ b/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/CreatorCenterNoticeVO.java @@ -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; } diff --git a/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/CreatorCenterProfileVO.java b/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/CreatorCenterProfileVO.java index 32789fd..bba82ba 100644 --- a/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/CreatorCenterProfileVO.java +++ b/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/CreatorCenterProfileVO.java @@ -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; } diff --git a/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/CreatorCenterTargetVO.java b/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/CreatorCenterTargetVO.java index eef42ab..ffa7e07 100644 --- a/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/CreatorCenterTargetVO.java +++ b/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/CreatorCenterTargetVO.java @@ -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; } diff --git a/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/CreatorDramaEditReqVO.java b/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/CreatorDramaEditReqVO.java index 5dc6b8b..7112c14 100644 --- a/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/CreatorDramaEditReqVO.java +++ b/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/CreatorDramaEditReqVO.java @@ -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; } diff --git a/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/CreatorEpisodeReqVO.java b/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/CreatorEpisodeReqVO.java index 7f8728d..8b90a50 100644 --- a/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/CreatorEpisodeReqVO.java +++ b/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/CreatorEpisodeReqVO.java @@ -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; } diff --git a/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/CreatorQueryReqVO.java b/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/CreatorQueryReqVO.java index 14c78fc..8d66d06 100644 --- a/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/CreatorQueryReqVO.java +++ b/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/CreatorQueryReqVO.java @@ -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; } diff --git a/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/CreatorSaveReqVO.java b/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/CreatorSaveReqVO.java index 412630a..91dfa07 100644 --- a/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/CreatorSaveReqVO.java +++ b/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/CreatorSaveReqVO.java @@ -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; } diff --git a/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/CreatorSubmitReqVO.java b/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/CreatorSubmitReqVO.java index 4a21d4d..f0ee0f2 100644 --- a/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/CreatorSubmitReqVO.java +++ b/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/CreatorSubmitReqVO.java @@ -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; } diff --git a/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/SubmissionAuditReqVO.java b/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/SubmissionAuditReqVO.java index 13bd96a..d643824 100644 --- a/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/SubmissionAuditReqVO.java +++ b/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/SubmissionAuditReqVO.java @@ -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; } diff --git a/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/SubmissionQueryReqVO.java b/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/SubmissionQueryReqVO.java index b06d810..4c4f653 100644 --- a/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/SubmissionQueryReqVO.java +++ b/fruitshorts-module-creator/src/main/java/com/fruitshorts/creator/vo/SubmissionQueryReqVO.java @@ -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; } diff --git a/fruitshorts-module-interaction/src/main/java/com/fruitshorts/interaction/vo/CommentAuditReqVO.java b/fruitshorts-module-interaction/src/main/java/com/fruitshorts/interaction/vo/CommentAuditReqVO.java index ec7efb9..97336c5 100644 --- a/fruitshorts-module-interaction/src/main/java/com/fruitshorts/interaction/vo/CommentAuditReqVO.java +++ b/fruitshorts-module-interaction/src/main/java/com/fruitshorts/interaction/vo/CommentAuditReqVO.java @@ -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; } diff --git a/fruitshorts-module-interaction/src/main/java/com/fruitshorts/interaction/vo/CommentPublishReqVO.java b/fruitshorts-module-interaction/src/main/java/com/fruitshorts/interaction/vo/CommentPublishReqVO.java index 4d4b0a7..9acbc0e 100644 --- a/fruitshorts-module-interaction/src/main/java/com/fruitshorts/interaction/vo/CommentPublishReqVO.java +++ b/fruitshorts-module-interaction/src/main/java/com/fruitshorts/interaction/vo/CommentPublishReqVO.java @@ -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; } diff --git a/fruitshorts-module-interaction/src/main/java/com/fruitshorts/interaction/vo/CommentQueryReqVO.java b/fruitshorts-module-interaction/src/main/java/com/fruitshorts/interaction/vo/CommentQueryReqVO.java index 6652d49..2b46dd8 100644 --- a/fruitshorts-module-interaction/src/main/java/com/fruitshorts/interaction/vo/CommentQueryReqVO.java +++ b/fruitshorts-module-interaction/src/main/java/com/fruitshorts/interaction/vo/CommentQueryReqVO.java @@ -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; } diff --git a/fruitshorts-module-interaction/src/main/java/com/fruitshorts/interaction/vo/CommentRespVO.java b/fruitshorts-module-interaction/src/main/java/com/fruitshorts/interaction/vo/CommentRespVO.java index 86d7eab..05ad7d2 100644 --- a/fruitshorts-module-interaction/src/main/java/com/fruitshorts/interaction/vo/CommentRespVO.java +++ b/fruitshorts-module-interaction/src/main/java/com/fruitshorts/interaction/vo/CommentRespVO.java @@ -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; } diff --git a/fruitshorts-module-interaction/src/main/java/com/fruitshorts/interaction/vo/LikeToggleReqVO.java b/fruitshorts-module-interaction/src/main/java/com/fruitshorts/interaction/vo/LikeToggleReqVO.java index 5209a11..cb512d7 100644 --- a/fruitshorts-module-interaction/src/main/java/com/fruitshorts/interaction/vo/LikeToggleReqVO.java +++ b/fruitshorts-module-interaction/src/main/java/com/fruitshorts/interaction/vo/LikeToggleReqVO.java @@ -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; } diff --git a/fruitshorts-module-interaction/src/main/java/com/fruitshorts/interaction/vo/LikeToggleRespVO.java b/fruitshorts-module-interaction/src/main/java/com/fruitshorts/interaction/vo/LikeToggleRespVO.java index 694d1d2..3687bde 100644 --- a/fruitshorts-module-interaction/src/main/java/com/fruitshorts/interaction/vo/LikeToggleRespVO.java +++ b/fruitshorts-module-interaction/src/main/java/com/fruitshorts/interaction/vo/LikeToggleRespVO.java @@ -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; } diff --git a/fruitshorts-module-interaction/src/main/java/com/fruitshorts/interaction/vo/ReportCreateReqVO.java b/fruitshorts-module-interaction/src/main/java/com/fruitshorts/interaction/vo/ReportCreateReqVO.java index fe9801f..2f02170 100644 --- a/fruitshorts-module-interaction/src/main/java/com/fruitshorts/interaction/vo/ReportCreateReqVO.java +++ b/fruitshorts-module-interaction/src/main/java/com/fruitshorts/interaction/vo/ReportCreateReqVO.java @@ -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; } diff --git a/fruitshorts-module-interaction/src/main/java/com/fruitshorts/interaction/vo/ReportHandleReqVO.java b/fruitshorts-module-interaction/src/main/java/com/fruitshorts/interaction/vo/ReportHandleReqVO.java index 0856651..efb5de6 100644 --- a/fruitshorts-module-interaction/src/main/java/com/fruitshorts/interaction/vo/ReportHandleReqVO.java +++ b/fruitshorts-module-interaction/src/main/java/com/fruitshorts/interaction/vo/ReportHandleReqVO.java @@ -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; } diff --git a/fruitshorts-module-interaction/src/main/java/com/fruitshorts/interaction/vo/ReportQueryReqVO.java b/fruitshorts-module-interaction/src/main/java/com/fruitshorts/interaction/vo/ReportQueryReqVO.java index f75baff..aee3a67 100644 --- a/fruitshorts-module-interaction/src/main/java/com/fruitshorts/interaction/vo/ReportQueryReqVO.java +++ b/fruitshorts-module-interaction/src/main/java/com/fruitshorts/interaction/vo/ReportQueryReqVO.java @@ -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; } diff --git a/fruitshorts-module-interaction/src/main/java/com/fruitshorts/interaction/vo/SensitiveWordReqVO.java b/fruitshorts-module-interaction/src/main/java/com/fruitshorts/interaction/vo/SensitiveWordReqVO.java index e018b8d..3e60fc0 100644 --- a/fruitshorts-module-interaction/src/main/java/com/fruitshorts/interaction/vo/SensitiveWordReqVO.java +++ b/fruitshorts-module-interaction/src/main/java/com/fruitshorts/interaction/vo/SensitiveWordReqVO.java @@ -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; } diff --git a/fruitshorts-module-media/src/main/java/com/fruitshorts/media/vo/MediaAssetRespVO.java b/fruitshorts-module-media/src/main/java/com/fruitshorts/media/vo/MediaAssetRespVO.java index c5080fb..255b181 100644 --- a/fruitshorts-module-media/src/main/java/com/fruitshorts/media/vo/MediaAssetRespVO.java +++ b/fruitshorts-module-media/src/main/java/com/fruitshorts/media/vo/MediaAssetRespVO.java @@ -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; } diff --git a/fruitshorts-module-media/src/main/java/com/fruitshorts/media/vo/UploadCompleteReqVO.java b/fruitshorts-module-media/src/main/java/com/fruitshorts/media/vo/UploadCompleteReqVO.java index beb3d0e..5e2b016 100644 --- a/fruitshorts-module-media/src/main/java/com/fruitshorts/media/vo/UploadCompleteReqVO.java +++ b/fruitshorts-module-media/src/main/java/com/fruitshorts/media/vo/UploadCompleteReqVO.java @@ -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; } diff --git a/fruitshorts-module-media/src/main/java/com/fruitshorts/media/vo/UploadInitReqVO.java b/fruitshorts-module-media/src/main/java/com/fruitshorts/media/vo/UploadInitReqVO.java index a71db01..47d34db 100644 --- a/fruitshorts-module-media/src/main/java/com/fruitshorts/media/vo/UploadInitReqVO.java +++ b/fruitshorts-module-media/src/main/java/com/fruitshorts/media/vo/UploadInitReqVO.java @@ -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; } diff --git a/fruitshorts-module-media/src/main/java/com/fruitshorts/media/vo/UploadInitRespVO.java b/fruitshorts-module-media/src/main/java/com/fruitshorts/media/vo/UploadInitRespVO.java index 7333f30..9fd164c 100644 --- a/fruitshorts-module-media/src/main/java/com/fruitshorts/media/vo/UploadInitRespVO.java +++ b/fruitshorts-module-media/src/main/java/com/fruitshorts/media/vo/UploadInitRespVO.java @@ -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; } diff --git a/fruitshorts-module-media/src/main/java/com/fruitshorts/media/vo/UploadProgressRespVO.java b/fruitshorts-module-media/src/main/java/com/fruitshorts/media/vo/UploadProgressRespVO.java index 5e5e5ad..b07cd3d 100644 --- a/fruitshorts-module-media/src/main/java/com/fruitshorts/media/vo/UploadProgressRespVO.java +++ b/fruitshorts-module-media/src/main/java/com/fruitshorts/media/vo/UploadProgressRespVO.java @@ -2,6 +2,7 @@ package com.fruitshorts.media.vo; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; /** @@ -12,18 +13,29 @@ import lombok.Data; @Data public class UploadProgressRespVO { + @Schema(description = "上传 ID") private String uploadId; + @Schema(description = "文件名") private String fileName; + @Schema(description = "业务类型") private String bizType; + @Schema(description = "文件大小") private Long fileSize; + @Schema(description = "分片大小") private Integer chunkSize; + @Schema(description = "总分片数") private Integer totalChunks; + @Schema(description = "已收分片数") private Integer receivedChunks; /** 0-100,按已收分片 / 总分片计算 */ + @Schema(description = "进度百分比(0-100)") private Integer percent; /** uploading / completed */ + @Schema(description = "状态") private String status; /** 合并完成后才有 */ + @Schema(description = "媒资 ID") private Long assetId; + @Schema(description = "地址") private String url; } diff --git a/fruitshorts-module-playback/src/main/java/com/fruitshorts/playback/vo/DownloadGrantReqVO.java b/fruitshorts-module-playback/src/main/java/com/fruitshorts/playback/vo/DownloadGrantReqVO.java index c297046..ad6f37e 100644 --- a/fruitshorts-module-playback/src/main/java/com/fruitshorts/playback/vo/DownloadGrantReqVO.java +++ b/fruitshorts-module-playback/src/main/java/com/fruitshorts/playback/vo/DownloadGrantReqVO.java @@ -2,6 +2,7 @@ package com.fruitshorts.playback.vo; +import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import lombok.Data; @@ -9,12 +10,15 @@ import lombok.Data; @Data public class DownloadGrantReqVO { + @Schema(description = "剧集ID") @NotNull(message = "缺少 episodeId") private Long episodeId; /** 期望清晰度,AUTO 表示由客户端按策略决定 */ + @Schema(description = "期望清晰度,AUTO 表示由客户端按策略决定") private String quality; /** 设备标识,绑定授权用;请求头带 X-Device-Id 时可以省略 */ + @Schema(description = "设备标识,绑定授权用;请求头带 X-Device-Id 时可以省略") private String deviceId; } diff --git a/fruitshorts-module-playback/src/main/java/com/fruitshorts/playback/vo/DownloadLicenseRespVO.java b/fruitshorts-module-playback/src/main/java/com/fruitshorts/playback/vo/DownloadLicenseRespVO.java index 206bfc9..2a1f7f8 100644 --- a/fruitshorts-module-playback/src/main/java/com/fruitshorts/playback/vo/DownloadLicenseRespVO.java +++ b/fruitshorts-module-playback/src/main/java/com/fruitshorts/playback/vo/DownloadLicenseRespVO.java @@ -2,6 +2,7 @@ package com.fruitshorts.playback.vo; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import java.time.LocalDateTime; @@ -10,26 +11,58 @@ import java.time.LocalDateTime; @Data public class DownloadLicenseRespVO { + @Schema(description = "授权ID") private Long licenseId; + + @Schema(description = "短剧ID") private Long dramaId; + + @Schema(description = "短剧标题") private String dramaTitle; + + @Schema(description = "剧集ID") private Long episodeId; + + @Schema(description = "集号") private Integer episodeNo; + + @Schema(description = "设备ID") private String deviceId; + + @Schema(description = "清晰度") private String quality; + /** 签名后的下载地址;过期后需要重新申请 */ + @Schema(description = "签名后的下载地址;过期后需要重新申请") private String playUrl; + /** 离线播放校验用 */ + @Schema(description = "离线播放校验密钥") private String licenseKey; + /** ACTIVE/EXPIRED/REVOKED */ + @Schema(description = "状态(ACTIVE/EXPIRED/REVOKED)") private String status; + + @Schema(description = "授权时间") private LocalDateTime grantedAt; + + @Schema(description = "过期时间") private LocalDateTime expireAt; /** QUEUED/DOWNLOADING/PAUSED/COMPLETED/FAILED/CANCELED */ + @Schema(description = "任务状态(QUEUED/DOWNLOADING/PAUSED/COMPLETED/FAILED/CANCELED)") private String taskStatus; + + @Schema(description = "进度百分比") private Integer progressPercent; + + @Schema(description = "已下载字节数") private Long downloadedBytes; + + @Schema(description = "总字节数") private Long totalBytes; + + @Schema(description = "错误信息") private String errorMsg; } diff --git a/fruitshorts-module-playback/src/main/java/com/fruitshorts/playback/vo/DownloadPolicyRespVO.java b/fruitshorts-module-playback/src/main/java/com/fruitshorts/playback/vo/DownloadPolicyRespVO.java index 427e80d..3f260e6 100644 --- a/fruitshorts-module-playback/src/main/java/com/fruitshorts/playback/vo/DownloadPolicyRespVO.java +++ b/fruitshorts-module-playback/src/main/java/com/fruitshorts/playback/vo/DownloadPolicyRespVO.java @@ -2,6 +2,7 @@ package com.fruitshorts.playback.vo; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; /** @@ -10,16 +11,31 @@ import lombok.Data; @Data public class DownloadPolicyRespVO { + @Schema(description = "每设备最大授权数") private Integer maxPerDevice; + + @Schema(description = "授权有效期(天)") private Integer licenseDays; + /** 用户当前的"仅 Wi-Fi 下载"偏好 */ + @Schema(description = "用户当前的“仅 Wi-Fi 下载”偏好") private Boolean wifiOnly; + + @Schema(description = "最高清晰度") private String maxQuality; + /** 预留:单设备占用上限(字节),0 表示不限制 */ + @Schema(description = "单设备占用上限(字节),0 表示不限制") private Long maxStorageBytes; + /** 当前设备已用授权数 */ + @Schema(description = "当前设备已用授权数") private Integer used; + + @Schema(description = "剩余授权数") private Integer remaining; + /** 过期策略说明,用于客户端文案与客服解释 */ + @Schema(description = "过期策略说明,用于客户端文案与客服解释") private String expirePolicyText; } diff --git a/fruitshorts-module-playback/src/main/java/com/fruitshorts/playback/vo/DownloadProgressReqVO.java b/fruitshorts-module-playback/src/main/java/com/fruitshorts/playback/vo/DownloadProgressReqVO.java index c4fba30..de5e000 100644 --- a/fruitshorts-module-playback/src/main/java/com/fruitshorts/playback/vo/DownloadProgressReqVO.java +++ b/fruitshorts-module-playback/src/main/java/com/fruitshorts/playback/vo/DownloadProgressReqVO.java @@ -2,17 +2,29 @@ package com.fruitshorts.playback.vo; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; /** 上报下载进度,用于断点续传与跨端展示。 */ @Data public class DownloadProgressReqVO { + @Schema(description = "设备ID") private String deviceId; + /** QUEUED/DOWNLOADING/PAUSED/COMPLETED/FAILED/CANCELED */ + @Schema(description = "状态(QUEUED/DOWNLOADING/PAUSED/COMPLETED/FAILED/CANCELED)") private String status; + + @Schema(description = "进度百分比") private Integer progressPercent; + + @Schema(description = "已下载字节数") private Long downloadedBytes; + + @Schema(description = "总字节数") private Long totalBytes; + + @Schema(description = "错误信息") private String errorMsg; } diff --git a/fruitshorts-module-playback/src/main/java/com/fruitshorts/playback/vo/DownloadQueryReqVO.java b/fruitshorts-module-playback/src/main/java/com/fruitshorts/playback/vo/DownloadQueryReqVO.java index 06eb03e..f3c1058 100644 --- a/fruitshorts-module-playback/src/main/java/com/fruitshorts/playback/vo/DownloadQueryReqVO.java +++ b/fruitshorts-module-playback/src/main/java/com/fruitshorts/playback/vo/DownloadQueryReqVO.java @@ -2,16 +2,26 @@ package com.fruitshorts.playback.vo; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; /** 后台下载授权检索条件。 */ @Data public class DownloadQueryReqVO { + @Schema(description = "用户ID") private Long userId; + + @Schema(description = "设备ID") private String deviceId; + /** ACTIVE/EXPIRED/REVOKED */ + @Schema(description = "状态(ACTIVE/EXPIRED/REVOKED)") private String status; + + @Schema(description = "页码") private Integer pageIndex = 1; + + @Schema(description = "每页数量") private Integer pageSize = 10; } diff --git a/fruitshorts-module-playback/src/main/java/com/fruitshorts/playback/vo/DownloadSettingReqVO.java b/fruitshorts-module-playback/src/main/java/com/fruitshorts/playback/vo/DownloadSettingReqVO.java index 472738d..7c6c197 100644 --- a/fruitshorts-module-playback/src/main/java/com/fruitshorts/playback/vo/DownloadSettingReqVO.java +++ b/fruitshorts-module-playback/src/main/java/com/fruitshorts/playback/vo/DownloadSettingReqVO.java @@ -2,12 +2,16 @@ package com.fruitshorts.playback.vo; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; /** 下载偏好设置。 */ @Data public class DownloadSettingReqVO { + @Schema(description = "是否仅 Wi-Fi 下载") private Boolean wifiOnly; + + @Schema(description = "最高清晰度") private String maxQuality; } diff --git a/fruitshorts-module-playback/src/main/java/com/fruitshorts/playback/vo/FavoriteToggleReqVO.java b/fruitshorts-module-playback/src/main/java/com/fruitshorts/playback/vo/FavoriteToggleReqVO.java index 8eb3bd7..5bb55dc 100644 --- a/fruitshorts-module-playback/src/main/java/com/fruitshorts/playback/vo/FavoriteToggleReqVO.java +++ b/fruitshorts-module-playback/src/main/java/com/fruitshorts/playback/vo/FavoriteToggleReqVO.java @@ -2,6 +2,7 @@ package com.fruitshorts.playback.vo; +import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import lombok.Data; @@ -9,6 +10,7 @@ import lombok.Data; @Data public class FavoriteToggleReqVO { + @Schema(description = "短剧ID") @NotNull(message = "缺少 dramaId") private Long dramaId; } diff --git a/fruitshorts-module-playback/src/main/java/com/fruitshorts/playback/vo/PlayRespVO.java b/fruitshorts-module-playback/src/main/java/com/fruitshorts/playback/vo/PlayRespVO.java index fed5b25..6247e46 100644 --- a/fruitshorts-module-playback/src/main/java/com/fruitshorts/playback/vo/PlayRespVO.java +++ b/fruitshorts-module-playback/src/main/java/com/fruitshorts/playback/vo/PlayRespVO.java @@ -2,6 +2,7 @@ package com.fruitshorts.playback.vo; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import java.util.List; @@ -10,21 +11,42 @@ import java.util.List; @Data public class PlayRespVO { + @Schema(description = "剧集ID") private Long episodeId; + + @Schema(description = "短剧ID") private Long dramaId; + + @Schema(description = "集号") private Integer number; + + @Schema(description = "标题") private String title; + + @Schema(description = "时长(秒)") private Integer durationSec; + /** 是否可直接播放 */ + @Schema(description = "是否可直接播放") private Boolean accessible; + /** FREE/ENTITLED/TRIAL/COIN_REQUIRED/NO_MEDIA */ + @Schema(description = "访问类型(FREE/ENTITLED/TRIAL/COIN_REQUIRED/NO_MEDIA)") private String accessType; + /** 签名后的播放地址,accessible=false 时为空 */ + @Schema(description = "签名后的播放地址,accessible=false 时为空") private String playUrl; + /** 可用的清晰度档位 */ + @Schema(description = "可用的清晰度档位") private List qualities; + /** 需要多少金币解锁 */ + @Schema(description = "解锁所需金币数") private Integer unlockCoin; + /** 试看秒数,0 表示不限制 */ + @Schema(description = "试看秒数,0 表示不限制") private Integer previewSeconds; } diff --git a/fruitshorts-module-playback/src/main/java/com/fruitshorts/playback/vo/ProgressRespVO.java b/fruitshorts-module-playback/src/main/java/com/fruitshorts/playback/vo/ProgressRespVO.java index 8f9f222..b4e641c 100644 --- a/fruitshorts-module-playback/src/main/java/com/fruitshorts/playback/vo/ProgressRespVO.java +++ b/fruitshorts-module-playback/src/main/java/com/fruitshorts/playback/vo/ProgressRespVO.java @@ -2,6 +2,7 @@ package com.fruitshorts.playback.vo; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import java.time.LocalDateTime; @@ -10,11 +11,24 @@ import java.time.LocalDateTime; @Data public class ProgressRespVO { + @Schema(description = "短剧ID") private Long dramaId; + + @Schema(description = "剧集ID") private Long episodeId; + + @Schema(description = "播放位置(毫秒)") private Long positionMs; + + @Schema(description = "时长(毫秒)") private Long durationMs; + + @Schema(description = "是否已看完") private Boolean finished; + + @Schema(description = "播放次数") private Integer playCount; + + @Schema(description = "更新时间") private LocalDateTime updatedAt; } diff --git a/fruitshorts-module-playback/src/main/java/com/fruitshorts/playback/vo/ProgressSaveReqVO.java b/fruitshorts-module-playback/src/main/java/com/fruitshorts/playback/vo/ProgressSaveReqVO.java index 3e75dc1..62adb69 100644 --- a/fruitshorts-module-playback/src/main/java/com/fruitshorts/playback/vo/ProgressSaveReqVO.java +++ b/fruitshorts-module-playback/src/main/java/com/fruitshorts/playback/vo/ProgressSaveReqVO.java @@ -2,6 +2,7 @@ package com.fruitshorts.playback.vo; +import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import lombok.Data; @@ -9,13 +10,23 @@ import lombok.Data; @Data public class ProgressSaveReqVO { + @Schema(description = "剧集ID") @NotNull(message = "缺少 episodeId") private Long episodeId; + @Schema(description = "播放位置(毫秒)") private Long positionMs; + + @Schema(description = "时长(毫秒)") private Long durationMs; + + @Schema(description = "是否已看完") private Boolean finished; + /** HOME/DETAIL/SEARCH/FAVORITE */ + @Schema(description = "来源(HOME/DETAIL/SEARCH/FAVORITE)") private String source; + + @Schema(description = "设备ID") private String deviceId; } diff --git a/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/AdminUserPageReqVO.java b/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/AdminUserPageReqVO.java index 024c756..d740caf 100644 --- a/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/AdminUserPageReqVO.java +++ b/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/AdminUserPageReqVO.java @@ -2,6 +2,7 @@ package com.fruitshorts.system.vo; +import io.swagger.v3.oas.annotations.media.Schema; import com.fruitshorts.common.pojo.PageParam; import lombok.Data; import lombok.EqualsAndHashCode; @@ -10,7 +11,12 @@ import lombok.EqualsAndHashCode; @EqualsAndHashCode(callSuper = true) public class AdminUserPageReqVO extends PageParam { + @Schema(description = "用户名") private String username; + + @Schema(description = "角色ID") private Long roleId; + + @Schema(description = "状态") private Integer status; } diff --git a/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/AdminUserRespVO.java b/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/AdminUserRespVO.java index 121c687..6f63414 100644 --- a/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/AdminUserRespVO.java +++ b/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/AdminUserRespVO.java @@ -2,6 +2,7 @@ package com.fruitshorts.system.vo; +import io.swagger.v3.oas.annotations.media.Schema; import com.fasterxml.jackson.annotation.JsonFormat; import lombok.Data; @@ -10,20 +11,41 @@ import java.time.LocalDateTime; @Data public class AdminUserRespVO { + @Schema(description = "ID") private Long id; + + @Schema(description = "用户名") private String username; + + @Schema(description = "姓名") private String name; + + @Schema(description = "角色ID") private Long roleId; + + @Schema(description = "角色") private String role; + + @Schema(description = "IP白名单") private String ipWhitelist; + + @Schema(description = "状态") private Integer status; + + @Schema(description = "状态文本") private String statusText; + + @Schema(description = "两步验证") private Integer twoFactor; + + @Schema(description = "两步验证文本") private String twoFactorText; + @Schema(description = "创建时间") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime createdAt; + @Schema(description = "最后登录时间") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime lastLogin; } diff --git a/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/AdminUserSaveReqVO.java b/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/AdminUserSaveReqVO.java index e6b2dac..e4bc1b7 100644 --- a/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/AdminUserSaveReqVO.java +++ b/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/AdminUserSaveReqVO.java @@ -2,6 +2,7 @@ package com.fruitshorts.system.vo; +import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; import lombok.Data; @@ -10,17 +11,26 @@ import lombok.Data; public class AdminUserSaveReqVO { /** 新增时必填,编辑时忽略 */ + @Schema(description = "用户名") private String username; + @Schema(description = "密码") private String password; + @Schema(description = "姓名") @NotBlank(message = "请输入姓名") private String name; + @Schema(description = "角色ID") @NotNull(message = "请选择角色") private Long roleId; + @Schema(description = "IP白名单") private String ipWhitelist; + + @Schema(description = "状态") private Integer status; + + @Schema(description = "两步验证") private Integer twoFactor; } diff --git a/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/ConfigItemVO.java b/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/ConfigItemVO.java index abd4aca..ae81bfa 100644 --- a/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/ConfigItemVO.java +++ b/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/ConfigItemVO.java @@ -2,6 +2,7 @@ package com.fruitshorts.system.vo; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Data; @@ -9,7 +10,12 @@ import lombok.Data; @AllArgsConstructor public class ConfigItemVO { + @Schema(description = "键") private String key; + + @Schema(description = "值") private String value; + + @Schema(description = "备注") private String remark; } diff --git a/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/LoginReqVO.java b/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/LoginReqVO.java index 39e931f..a811572 100644 --- a/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/LoginReqVO.java +++ b/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/LoginReqVO.java @@ -2,15 +2,18 @@ package com.fruitshorts.system.vo; +import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; import lombok.Data; @Data public class LoginReqVO { + @Schema(description = "用户名") @NotBlank(message = "请输入账号") private String username; + @Schema(description = "密码") @NotBlank(message = "请输入密码") private String password; } diff --git a/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/LoginRespVO.java b/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/LoginRespVO.java index 1234d8b..f31736b 100644 --- a/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/LoginRespVO.java +++ b/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/LoginRespVO.java @@ -2,6 +2,7 @@ package com.fruitshorts.system.vo; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; import lombok.Data; @@ -11,16 +12,35 @@ import java.util.List; @Builder public class LoginRespVO { + @Schema(description = "令牌") private String token; + + @Schema(description = "用户ID") private Long userId; + + @Schema(description = "用户名") private String username; + + @Schema(description = "姓名") private String name; + + @Schema(description = "头像") private String avatar; + /** 角色编码,如 super_admin */ + @Schema(description = "角色编码") private String role; + + @Schema(description = "角色名称") private String roleName; + + @Schema(description = "角色ID") private Long roleId; + + @Schema(description = "权限码列表") private List permissions; + /** 首登强制改密:前端据此弹出改密对话框 */ + @Schema(description = "是否必须修改密码") private Boolean mustChangePassword; } diff --git a/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/MenuSaveReqVO.java b/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/MenuSaveReqVO.java index 8d5d98a..694426f 100644 --- a/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/MenuSaveReqVO.java +++ b/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/MenuSaveReqVO.java @@ -2,25 +2,47 @@ package com.fruitshorts.system.vo; +import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; import lombok.Data; @Data public class MenuSaveReqVO { + @Schema(description = "父级ID") private Long parentId; + @Schema(description = "菜单名称") @NotBlank(message = "请输入菜单名称") private String title; + @Schema(description = "路由路径") private String routePath; + + @Schema(description = "路由名称") private String routeName; + + @Schema(description = "组件") private String component; + + @Schema(description = "重定向地址") private String redirect; + + @Schema(description = "图标") private String icon; + + @Schema(description = "权限编码") private String permissionCode; + + @Schema(description = "类型") private String type; + + @Schema(description = "排序") private Integer sort; + + @Schema(description = "是否可见") private Integer visible; + + @Schema(description = "状态") private Integer status; } diff --git a/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/MenuVO.java b/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/MenuVO.java index fa8929b..52e0eab 100644 --- a/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/MenuVO.java +++ b/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/MenuVO.java @@ -2,6 +2,7 @@ package com.fruitshorts.system.vo; +import io.swagger.v3.oas.annotations.media.Schema; import com.fasterxml.jackson.annotation.JsonInclude; import lombok.AllArgsConstructor; import lombok.Data; @@ -14,31 +15,68 @@ import java.util.List; @Data public class MenuVO { + @Schema(description = "ID") private Long id; + + @Schema(description = "父级ID") private Long parentId; + + @Schema(description = "路由路径") private String path; + + @Schema(description = "路由名称") private String name; + + @Schema(description = "组件") private String component; + + @Schema(description = "重定向地址") private String redirect; + + @Schema(description = "图标") private String icon; + /** CATALOG / MENU / BUTTON */ + @Schema(description = "类型") private String type; + + @Schema(description = "权限编码") private String permissionCode; + + @Schema(description = "排序") private Integer sort; + + @Schema(description = "是否可见") private Integer visible; + + @Schema(description = "状态") private Integer status; + + @Schema(description = "元数据") private Meta meta; + + @Schema(description = "子菜单列表") private List children; @Data @AllArgsConstructor @JsonInclude(JsonInclude.Include.NON_NULL) public static class Meta { + + @Schema(description = "标题") private String title; + + @Schema(description = "图标") private String icon; + + @Schema(description = "是否总是显示") private Boolean alwaysShow; + + @Schema(description = "是否固定") private Boolean affix; + /** visible=0 的菜单:路由要注册(详情页靠它),但不进侧边栏 */ + @Schema(description = "是否隐藏") private Boolean hidden; } } diff --git a/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/OperationLogPageReqVO.java b/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/OperationLogPageReqVO.java index b7b4128..0965d04 100644 --- a/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/OperationLogPageReqVO.java +++ b/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/OperationLogPageReqVO.java @@ -2,6 +2,7 @@ package com.fruitshorts.system.vo; +import io.swagger.v3.oas.annotations.media.Schema; import com.fruitshorts.common.pojo.PageParam; import lombok.Data; import lombok.EqualsAndHashCode; @@ -14,17 +15,26 @@ import java.time.LocalDateTime; public class OperationLogPageReqVO extends PageParam { /** 操作人账号,模糊匹配 */ + @Schema(description = "操作人账号") private String username; + /** 模块,精确匹配 */ + @Schema(description = "模块") private String module; + /** 动作,模糊匹配 */ + @Schema(description = "动作") private String action; + /** SUCCESS / FAIL */ + @Schema(description = "状态") private String status; + @Schema(description = "开始时间") @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime startTime; + @Schema(description = "结束时间") @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime endTime; } diff --git a/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/OperationLogRespVO.java b/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/OperationLogRespVO.java index ec02483..9b6754d 100644 --- a/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/OperationLogRespVO.java +++ b/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/OperationLogRespVO.java @@ -2,6 +2,7 @@ package com.fruitshorts.system.vo; +import io.swagger.v3.oas.annotations.media.Schema; import com.fasterxml.jackson.annotation.JsonFormat; import lombok.Data; @@ -10,22 +11,52 @@ import java.time.LocalDateTime; @Data public class OperationLogRespVO { + @Schema(description = "ID") private Long id; + + @Schema(description = "用户ID") private Long userId; + + @Schema(description = "用户名") private String username; + + @Schema(description = "模块") private String module; + + @Schema(description = "操作") private String action; + + @Schema(description = "请求方法") private String requestMethod; + + @Schema(description = "请求地址") private String requestUrl; + + @Schema(description = "请求参数") private String requestParams; + + @Schema(description = "请求体") private String requestBody; + + @Schema(description = "响应体") private String responseBody; + + @Schema(description = "状态") private String status; + + @Schema(description = "状态文本") private String statusText; + + @Schema(description = "错误信息") private String errorMsg; + + @Schema(description = "耗时(毫秒)") private Integer durationMs; + + @Schema(description = "IP地址") private String ip; + @Schema(description = "创建时间") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime createdAt; } diff --git a/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/PasswordChangeReqVO.java b/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/PasswordChangeReqVO.java index b97d6d1..79e5c99 100644 --- a/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/PasswordChangeReqVO.java +++ b/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/PasswordChangeReqVO.java @@ -2,6 +2,7 @@ package com.fruitshorts.system.vo; +import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.Size; import lombok.Data; @@ -9,9 +10,11 @@ import lombok.Data; @Data public class PasswordChangeReqVO { + @Schema(description = "原密码") @NotBlank(message = "请输入原密码") private String oldPassword; + @Schema(description = "新密码") @NotBlank(message = "请输入新密码") @Size(min = 6, max = 32, message = "新密码长度需在 6-32 位之间") private String newPassword; diff --git a/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/PermissionGroupVO.java b/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/PermissionGroupVO.java index a4cc833..b9d1f0f 100644 --- a/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/PermissionGroupVO.java +++ b/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/PermissionGroupVO.java @@ -2,6 +2,7 @@ package com.fruitshorts.system.vo; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Data; @@ -11,13 +12,20 @@ import java.util.List; @AllArgsConstructor public class PermissionGroupVO { + @Schema(description = "名称") private String name; + + @Schema(description = "权限项列表") private List items; @Data @AllArgsConstructor public static class Item { + + @Schema(description = "编码") private String code; + + @Schema(description = "名称") private String name; } } diff --git a/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/ProfileRespVO.java b/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/ProfileRespVO.java index aa20362..4c206a8 100644 --- a/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/ProfileRespVO.java +++ b/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/ProfileRespVO.java @@ -2,6 +2,7 @@ package com.fruitshorts.system.vo; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; import lombok.Data; @@ -14,15 +15,32 @@ import java.util.List; @Builder public class ProfileRespVO { + @Schema(description = "用户ID") private Long userId; + + @Schema(description = "用户名") private String username; + + @Schema(description = "姓名") private String name; + + @Schema(description = "头像") private String avatar; + /** 角色编码,如 super_admin */ + @Schema(description = "角色编码") private String role; + + @Schema(description = "角色名称") private String roleName; + + @Schema(description = "角色ID") private Long roleId; + + @Schema(description = "权限码列表") private List permissions; + /** 首登强制改密:刷新页面后仍然要能拦住 */ + @Schema(description = "是否必须修改密码") private Boolean mustChangePassword; } diff --git a/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/RoleCategoryRespVO.java b/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/RoleCategoryRespVO.java index 5cc6bd0..55602f7 100644 --- a/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/RoleCategoryRespVO.java +++ b/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/RoleCategoryRespVO.java @@ -2,13 +2,21 @@ package com.fruitshorts.system.vo; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @Data public class RoleCategoryRespVO { + @Schema(description = "ID") private Long id; + + @Schema(description = "名称") private String name; + + @Schema(description = "描述") private String description; + + @Schema(description = "角色数量") private Integer roleCount; } diff --git a/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/RoleCategorySaveReqVO.java b/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/RoleCategorySaveReqVO.java index 73e0f7e..f3ddbc3 100644 --- a/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/RoleCategorySaveReqVO.java +++ b/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/RoleCategorySaveReqVO.java @@ -2,14 +2,17 @@ package com.fruitshorts.system.vo; +import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; import lombok.Data; @Data public class RoleCategorySaveReqVO { + @Schema(description = "分类名称") @NotBlank(message = "请输入分类名称") private String name; + @Schema(description = "描述") private String description; } diff --git a/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/RolePermissionSaveReqVO.java b/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/RolePermissionSaveReqVO.java index 585ce2a..094f18d 100644 --- a/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/RolePermissionSaveReqVO.java +++ b/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/RolePermissionSaveReqVO.java @@ -2,6 +2,7 @@ package com.fruitshorts.system.vo; +import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import lombok.Data; @@ -10,6 +11,7 @@ import java.util.List; @Data public class RolePermissionSaveReqVO { + @Schema(description = "权限码列表") @NotNull(message = "权限不能为空") private List permissions; } diff --git a/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/RoleRespVO.java b/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/RoleRespVO.java index ba1b667..fe92815 100644 --- a/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/RoleRespVO.java +++ b/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/RoleRespVO.java @@ -2,6 +2,7 @@ package com.fruitshorts.system.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 RoleRespVO { + @Schema(description = "ID") private Long id; + + @Schema(description = "名称") private String name; + + @Schema(description = "编码") private String code; + + @Schema(description = "描述") private String description; + + @Schema(description = "分类ID") private Long categoryId; + + @Schema(description = "分类") private String category; + + @Schema(description = "级别") private Integer level; + + @Schema(description = "状态") private Integer status; + + @Schema(description = "状态文本") private String statusText; + + @Schema(description = "是否内置") private Boolean builtin; + + @Schema(description = "成员数量") private Integer memberCount; + + @Schema(description = "权限码列表") private List permissions; } diff --git a/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/RoleSaveReqVO.java b/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/RoleSaveReqVO.java index e4c49cb..85499c1 100644 --- a/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/RoleSaveReqVO.java +++ b/fruitshorts-module-system/src/main/java/com/fruitshorts/system/vo/RoleSaveReqVO.java @@ -2,6 +2,7 @@ package com.fruitshorts.system.vo; +import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; import lombok.Data; @@ -10,17 +11,27 @@ import java.util.List; @Data public class RoleSaveReqVO { + @Schema(description = "角色名称") @NotBlank(message = "请输入角色名称") private String name; /** 不传时按名称生成 */ + @Schema(description = "角色编码") private String code; + @Schema(description = "描述") private String description; + + @Schema(description = "分类ID") private Long categoryId; + + @Schema(description = "级别") private Integer level; + + @Schema(description = "状态") private Integer status; /** 角色权限码,传则整体覆盖 */ + @Schema(description = "角色权限码列表") private List permissions; } diff --git a/fruitshorts-module-user/src/main/java/com/fruitshorts/user/vo/AppUserAdminRespVO.java b/fruitshorts-module-user/src/main/java/com/fruitshorts/user/vo/AppUserAdminRespVO.java index d38f535..ca6714e 100644 --- a/fruitshorts-module-user/src/main/java/com/fruitshorts/user/vo/AppUserAdminRespVO.java +++ b/fruitshorts-module-user/src/main/java/com/fruitshorts/user/vo/AppUserAdminRespVO.java @@ -2,6 +2,7 @@ package com.fruitshorts.user.vo; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; @@ -15,5 +16,6 @@ import lombok.EqualsAndHashCode; @EqualsAndHashCode(callSuper = true) public class AppUserAdminRespVO extends AppUserRespVO { + @Schema(description = "自增 ID") private Long id; } diff --git a/fruitshorts-module-user/src/main/java/com/fruitshorts/user/vo/AppUserQueryReqVO.java b/fruitshorts-module-user/src/main/java/com/fruitshorts/user/vo/AppUserQueryReqVO.java index 5980da6..cd3e90f 100644 --- a/fruitshorts-module-user/src/main/java/com/fruitshorts/user/vo/AppUserQueryReqVO.java +++ b/fruitshorts-module-user/src/main/java/com/fruitshorts/user/vo/AppUserQueryReqVO.java @@ -2,6 +2,7 @@ package com.fruitshorts.user.vo; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; /** 后台用户检索条件。 */ @@ -9,10 +10,21 @@ import lombok.Data; public class AppUserQueryReqVO { /** uid / 昵称 / 手机号 / 邮箱 模糊匹配 */ + @Schema(description = "关键字(uid/昵称/手机号/邮箱模糊匹配)") private String keyword; + + @Schema(description = "状态") private String status; + + @Schema(description = "国家代码") private String countryCode; + + @Schema(description = "注册来源") private String registerSource; + + @Schema(description = "页码") private Integer pageIndex = 1; + + @Schema(description = "每页数量") private Integer pageSize = 10; } diff --git a/fruitshorts-module-user/src/main/java/com/fruitshorts/user/vo/AppUserRespVO.java b/fruitshorts-module-user/src/main/java/com/fruitshorts/user/vo/AppUserRespVO.java index e9bfbb0..7393817 100644 --- a/fruitshorts-module-user/src/main/java/com/fruitshorts/user/vo/AppUserRespVO.java +++ b/fruitshorts-module-user/src/main/java/com/fruitshorts/user/vo/AppUserRespVO.java @@ -2,6 +2,7 @@ package com.fruitshorts.user.vo; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import java.time.LocalDateTime; @@ -10,21 +11,50 @@ import java.time.LocalDateTime; @Data public class AppUserRespVO { + @Schema(description = "用户UID") private String uid; + + @Schema(description = "昵称") private String nickname; + + @Schema(description = "头像地址") private String avatarUrl; + + @Schema(description = "性别") private String gender; + + @Schema(description = "国家代码") private String countryCode; + + @Schema(description = "地区代码") private String regionCode; + + @Schema(description = "语言") private String language; + + @Schema(description = "时区") private String timezone; + + @Schema(description = "货币") private String currency; + + @Schema(description = "状态") private String status; + /** 脱敏后的手机号/邮箱,用于"我的"页展示 */ + @Schema(description = "脱敏手机号/邮箱") private String maskedTarget; + + @Schema(description = "创建时间") private LocalDateTime createdAt; + + @Schema(description = "最后登录时间") private LocalDateTime lastLoginAt; + /** 预留:会员等级与到期(第二阶段) */ + @Schema(description = "会员等级") private Integer vipLevel; + + @Schema(description = "会员到期时间") private LocalDateTime vipExpireAt; } diff --git a/fruitshorts-module-user/src/main/java/com/fruitshorts/user/vo/DeactivateReqVO.java b/fruitshorts-module-user/src/main/java/com/fruitshorts/user/vo/DeactivateReqVO.java index 7db4a78..ddbe6cf 100644 --- a/fruitshorts-module-user/src/main/java/com/fruitshorts/user/vo/DeactivateReqVO.java +++ b/fruitshorts-module-user/src/main/java/com/fruitshorts/user/vo/DeactivateReqVO.java @@ -2,12 +2,16 @@ package com.fruitshorts.user.vo; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; /** 申请注销:进入冷静期,期间可撤销。 */ @Data public class DeactivateReqVO { + @Schema(description = "注销原因") private String reason; + + @Schema(description = "密码") private String password; } diff --git a/fruitshorts-module-user/src/main/java/com/fruitshorts/user/vo/LoginReqVO.java b/fruitshorts-module-user/src/main/java/com/fruitshorts/user/vo/LoginReqVO.java index f16ba2f..0fd6f67 100644 --- a/fruitshorts-module-user/src/main/java/com/fruitshorts/user/vo/LoginReqVO.java +++ b/fruitshorts-module-user/src/main/java/com/fruitshorts/user/vo/LoginReqVO.java @@ -2,6 +2,7 @@ package com.fruitshorts.user.vo; +import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; import lombok.Data; @@ -9,21 +10,34 @@ import lombok.Data; @Data public class LoginReqVO { + @Schema(description = "登录方式(PHONE/EMAIL)") @NotBlank(message = "请指定登录方式") private String targetType; + @Schema(description = "手机号或邮箱") @NotBlank(message = "请输入手机号或邮箱") private String target; /** 验证码登录 */ + @Schema(description = "验证码") private String code; /** 密码登录 */ + @Schema(description = "密码") private String password; + @Schema(description = "设备ID") private String deviceId; + + @Schema(description = "设备型号") private String deviceModel; + + @Schema(description = "系统版本") private String osVersion; + + @Schema(description = "应用版本") private String appVersion; + + @Schema(description = "平台") private String platform; } diff --git a/fruitshorts-module-user/src/main/java/com/fruitshorts/user/vo/LogoutReqVO.java b/fruitshorts-module-user/src/main/java/com/fruitshorts/user/vo/LogoutReqVO.java index 16b8e35..041335f 100644 --- a/fruitshorts-module-user/src/main/java/com/fruitshorts/user/vo/LogoutReqVO.java +++ b/fruitshorts-module-user/src/main/java/com/fruitshorts/user/vo/LogoutReqVO.java @@ -2,12 +2,16 @@ package com.fruitshorts.user.vo; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; /** 登出。allDevices=true 时吊销该用户全部会话。 */ @Data public class LogoutReqVO { + @Schema(description = "刷新令牌") private String refreshToken; + + @Schema(description = "是否注销所有设备") private Boolean allDevices; } diff --git a/fruitshorts-module-user/src/main/java/com/fruitshorts/user/vo/OtpSendReqVO.java b/fruitshorts-module-user/src/main/java/com/fruitshorts/user/vo/OtpSendReqVO.java index 9ef2fd2..47c5928 100644 --- a/fruitshorts-module-user/src/main/java/com/fruitshorts/user/vo/OtpSendReqVO.java +++ b/fruitshorts-module-user/src/main/java/com/fruitshorts/user/vo/OtpSendReqVO.java @@ -2,6 +2,7 @@ package com.fruitshorts.user.vo; +import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; import lombok.Data; @@ -10,19 +11,24 @@ import lombok.Data; public class OtpSendReqVO { /** REGISTER/LOGIN/RESET_PWD/BIND */ + @Schema(description = "验证码场景") @NotBlank(message = "请指定验证码场景") private String scene; /** PHONE/EMAIL */ + @Schema(description = "验证方式(PHONE/EMAIL)") @NotBlank(message = "请指定验证方式") private String targetType; /** E.164 手机号或邮箱 */ + @Schema(description = "手机号或邮箱") @NotBlank(message = "请输入手机号或邮箱") private String target; + @Schema(description = "设备ID") private String deviceId; /** 预留:图形验证码票据,触发频控阈值后必填 */ + @Schema(description = "图形验证码票据") private String captchaTicket; } diff --git a/fruitshorts-module-user/src/main/java/com/fruitshorts/user/vo/ProfileUpdateReqVO.java b/fruitshorts-module-user/src/main/java/com/fruitshorts/user/vo/ProfileUpdateReqVO.java index fc7c692..4029caf 100644 --- a/fruitshorts-module-user/src/main/java/com/fruitshorts/user/vo/ProfileUpdateReqVO.java +++ b/fruitshorts-module-user/src/main/java/com/fruitshorts/user/vo/ProfileUpdateReqVO.java @@ -2,6 +2,7 @@ package com.fruitshorts.user.vo; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import java.time.LocalDate; @@ -10,11 +11,24 @@ import java.time.LocalDate; @Data public class ProfileUpdateReqVO { + @Schema(description = "昵称") private String nickname; + + @Schema(description = "头像地址") private String avatarUrl; + + @Schema(description = "性别") private String gender; + + @Schema(description = "生日") private LocalDate birthday; + + @Schema(description = "语言") private String language; + + @Schema(description = "时区") private String timezone; + + @Schema(description = "地区代码") private String regionCode; } diff --git a/fruitshorts-module-user/src/main/java/com/fruitshorts/user/vo/RefreshReqVO.java b/fruitshorts-module-user/src/main/java/com/fruitshorts/user/vo/RefreshReqVO.java index 90089b0..19fae72 100644 --- a/fruitshorts-module-user/src/main/java/com/fruitshorts/user/vo/RefreshReqVO.java +++ b/fruitshorts-module-user/src/main/java/com/fruitshorts/user/vo/RefreshReqVO.java @@ -2,6 +2,7 @@ package com.fruitshorts.user.vo; +import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; import lombok.Data; @@ -9,6 +10,7 @@ import lombok.Data; @Data public class RefreshReqVO { + @Schema(description = "刷新令牌") @NotBlank(message = "缺少 refreshToken") private String refreshToken; } diff --git a/fruitshorts-module-user/src/main/java/com/fruitshorts/user/vo/RegisterReqVO.java b/fruitshorts-module-user/src/main/java/com/fruitshorts/user/vo/RegisterReqVO.java index 48a4f89..7162c27 100644 --- a/fruitshorts-module-user/src/main/java/com/fruitshorts/user/vo/RegisterReqVO.java +++ b/fruitshorts-module-user/src/main/java/com/fruitshorts/user/vo/RegisterReqVO.java @@ -2,6 +2,7 @@ package com.fruitshorts.user.vo; +import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; import lombok.Data; @@ -9,29 +10,48 @@ import lombok.Data; @Data public class RegisterReqVO { + @Schema(description = "注册方式(PHONE/EMAIL)") @NotBlank(message = "请指定注册方式") private String targetType; + @Schema(description = "手机号或邮箱") @NotBlank(message = "请输入手机号或邮箱") private String target; + @Schema(description = "验证码") @NotBlank(message = "请输入验证码") private String code; /** 可选:同时设置密码,之后可用密码登录 */ + @Schema(description = "密码") private String password; + @Schema(description = "昵称") private String nickname; + + @Schema(description = "国家代码") private String countryCode; + + @Schema(description = "设备ID") private String deviceId; + + @Schema(description = "设备型号") private String deviceModel; + + @Schema(description = "系统版本") private String osVersion; + + @Schema(description = "应用版本") private String appVersion; + + @Schema(description = "平台") private String platform; /** 协议版本,注册即视为同意最新版隐私政策与用户协议 */ + @Schema(description = "协议版本") private String agreementVersion; /** 预留:营销与个性化广告同意,未同意不影响注册 */ + @Schema(description = "营销广告同意") private Boolean marketingConsent; } diff --git a/fruitshorts-module-user/src/main/java/com/fruitshorts/user/vo/TokenRespVO.java b/fruitshorts-module-user/src/main/java/com/fruitshorts/user/vo/TokenRespVO.java index b68e39c..77e29e2 100644 --- a/fruitshorts-module-user/src/main/java/com/fruitshorts/user/vo/TokenRespVO.java +++ b/fruitshorts-module-user/src/main/java/com/fruitshorts/user/vo/TokenRespVO.java @@ -2,19 +2,31 @@ package com.fruitshorts.user.vo; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; /** 登录/刷新返回的令牌与用户摘要。 */ @Data public class TokenRespVO { + @Schema(description = "访问令牌") private String accessToken; + /** 不透明随机串,只在客户端保存,服务端只存哈希 */ + @Schema(description = "刷新令牌") private String refreshToken; + /** access token 剩余有效期(秒) */ + @Schema(description = "访问令牌剩余有效期(秒)") private long expiresIn; + + @Schema(description = "令牌类型") private String tokenType = "Bearer"; + + @Schema(description = "用户信息") private AppUserRespVO user; + /** 本次登录是否新建了账号(验证码登录可能顺带注册) */ + @Schema(description = "是否新建账号") private boolean newUser; }