From 6e31701403ba1009f78b521a49b3dd131b661085 Mon Sep 17 00:00:00 2001 From: chen-xin-zhi <3588068430@qq.com> Date: Fri, 15 Aug 2025 08:18:57 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=BA=86=E8=BD=AE=E6=92=AD?= =?UTF-8?q?=E5=9B=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../promotion/constant/UserConstant.java | 7 +- .../controller/course/BannerController.java | 149 ++++++++++++++++++ .../userInfo/UserInfoController.java | 34 +++- 3 files changed, 187 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/greenorange/promotion/controller/course/BannerController.java diff --git a/src/main/java/com/greenorange/promotion/constant/UserConstant.java b/src/main/java/com/greenorange/promotion/constant/UserConstant.java index 845854c..9ee2bf1 100644 --- a/src/main/java/com/greenorange/promotion/constant/UserConstant.java +++ b/src/main/java/com/greenorange/promotion/constant/UserConstant.java @@ -59,7 +59,12 @@ public interface UserConstant { String STAFF_ROLE = "staff"; /** - * 申请通知 + * 员工申请须知 */ String APPLY_NOTICE_KEY = "applyNotice"; + + /** + * 课程购买须知 + */ + String COURSE_DESC_KEY = "courseDesc"; } diff --git a/src/main/java/com/greenorange/promotion/controller/course/BannerController.java b/src/main/java/com/greenorange/promotion/controller/course/BannerController.java new file mode 100644 index 0000000..4b71b8a --- /dev/null +++ b/src/main/java/com/greenorange/promotion/controller/course/BannerController.java @@ -0,0 +1,149 @@ +package com.greenorange.promotion.controller.course; + + +import com.greenorange.promotion.annotation.RequiresPermission; +import com.greenorange.promotion.common.BaseResponse; +import com.greenorange.promotion.common.ErrorCode; +import com.greenorange.promotion.common.ResultUtils; +import com.greenorange.promotion.constant.UserConstant; +import com.greenorange.promotion.exception.BusinessException; +import com.greenorange.promotion.model.dto.CommonStringRequest; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import lombok.extern.slf4j.Slf4j; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 轮播图 控制器 + */ +@RestController +@RequestMapping("banner") +@Slf4j +@Tag(name = "轮播图模块") +@Transactional +public class BannerController { + + @Resource + private RedisTemplate redisTemplate; + + + private static final String BANNER_KEY = "banners:list"; + + private static final String TOMBSTONE = "\u0000__DEL__\u0000"; // 删除占位符,极低冲突 + + + + /** + * web端管理员添加轮播图 + * @param commonStringRequest 图片view值 + * @return 是否添加成功 + */ + @PostMapping("add") + @Operation(summary = "web端管理员添加轮播图", description = "参数:图片view值,权限:管理员,方法名:addBanner") + @RequiresPermission(mustRole = UserConstant.ADMIN_ROLE) + public BaseResponse addBanner(@Valid @RequestBody CommonStringRequest commonStringRequest) { + String view = commonStringRequest.getTemplateString(); + redisTemplate.opsForList().rightPush(BANNER_KEY, view); + return ResultUtils.success(true); + } + + + /** + * 删除轮播图(根据索引) + * @param index 索引 + * @return 是否添加成功 + */ + @PostMapping("del") + @Operation(summary = "删除轮播图(根据索引)", description = "参数:图片view值,权限:管理员,方法名:delBanner") + @RequiresPermission(mustRole = UserConstant.ADMIN_ROLE) + public BaseResponse delBanner(@RequestParam long index) { + long len = getLenOrThrow(); + long idx = normalizeIndex(index, len); + try { + // 先把该位置设置为占位符 + redisTemplate.opsForList().set(BANNER_KEY, idx, TOMBSTONE); + // 再删除第一个占位符 + Long removed = redisTemplate.opsForList().remove(BANNER_KEY, 1, TOMBSTONE); + boolean ok = removed != null && removed > 0; + log.info("按索引删除轮播图:index={}, removed={}", idx, ok); + return ResultUtils.success(ok); + } catch (Exception e) { + throw new BusinessException(ErrorCode.PARAMS_ERROR, "索引越界或参数错误"); + } + } + + + /** + * 修改轮播图(根据索引) + * @param index 索引 + * @param newView 新的图片view值 + * @return 是否添加成功 + */ + @PostMapping("modify") + @Operation(summary = "修改轮播图(根据索引)", description = "参数:图片view值,权限:管理员,方法名:delBanner") + @RequiresPermission(mustRole = UserConstant.ADMIN_ROLE) + public BaseResponse modifyBanner(@RequestParam long index, @RequestParam String newView) { + long len = getLenOrThrow(); + long idx = normalizeIndex(index, len); // 支持 -1 + try { + redisTemplate.opsForList().set(BANNER_KEY, idx, newView); + log.info("更新轮播图:index={} -> {}", idx, newView); + return ResultUtils.success(true); + } catch (Exception e) { + throw new BusinessException(ErrorCode.PARAMS_ERROR, "索引越界或参数错误"); + } + } + + + /** + * web端获取所有轮播图(按添加顺序) + */ + @GetMapping("web/list") + @Operation(summary = "web端获取所有轮播图(按添加顺序)", description = "按添加顺序返回") + @RequiresPermission(mustRole = UserConstant.ADMIN_ROLE) + public BaseResponse> webListBanners() { + List banners = redisTemplate.opsForList().range(BANNER_KEY, 0, -1); + return ResultUtils.success(banners); + } + + + /** + * 小程序端获取所有轮播图(按添加顺序) + */ + @GetMapping("mini/list") + @Operation(summary = "小程序端获取所有轮播图(按添加顺序)", description = "按添加顺序返回") + @RequiresPermission(mustRole = UserConstant.DEFAULT_ROLE) + public BaseResponse> miniListBanners() { + List banners = redisTemplate.opsForList().range(BANNER_KEY, 0, -1); + return ResultUtils.success(banners); + } + + + + /* ===== 工具方法 ===== */ + + /** 获取列表长度,不存在或为空时抛错 */ + private long getLenOrThrow() { + Long len = redisTemplate.opsForList().size(BANNER_KEY); + if (len == null || len == 0) { + throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "轮播图列表为空"); + } + return len; + } + + /** 归一化索引(支持负索引),并做范围校验 */ + private long normalizeIndex(long index, long len) { + long idx = index < 0 ? len + index : index; // -1 -> len-1 + if (idx < 0 || idx >= len) { + throw new BusinessException(ErrorCode.PARAMS_ERROR, "索引越界:" + index); + } + return idx; + } + +} diff --git a/src/main/java/com/greenorange/promotion/controller/userInfo/UserInfoController.java b/src/main/java/com/greenorange/promotion/controller/userInfo/UserInfoController.java index b5a0e9d..9ce46a3 100644 --- a/src/main/java/com/greenorange/promotion/controller/userInfo/UserInfoController.java +++ b/src/main/java/com/greenorange/promotion/controller/userInfo/UserInfoController.java @@ -121,7 +121,7 @@ public class UserInfoController { * @return 是否修改成功 */ @PostMapping("modify/applyNotice") - @Operation(summary = "web端修改员工申请须知", description = "参数:昵称,权限:管理员(boss, admin),方法名:modifyApplyNotice") + @Operation(summary = "web端修改员工申请须知", description = "参数:修改内容,权限:管理员(boss, admin),方法名:modifyApplyNotice") @RequiresPermission(mustRole = UserConstant.ADMIN_ROLE) public BaseResponse modifyApplyNotice(@Valid @RequestBody CommonStringRequest commonStringRequest) { String applyNotice = commonStringRequest.getTemplateString(); @@ -136,13 +136,43 @@ public class UserInfoController { */ @PostMapping("query/applyNotice") @Operation(summary = "小程序端查询员工申请须知", description = "参数:无,权限:管理员(boss, admin),方法名:queryApplyNotice") - @RequiresPermission(mustRole = UserConstant.ADMIN_ROLE) + @RequiresPermission(mustRole = UserConstant.DEFAULT_ROLE) public BaseResponse queryApplyNotice() { String applyNotice = redisTemplate.opsForValue().get(UserConstant.APPLY_NOTICE_KEY); return ResultUtils.success(applyNotice); } + /** + * web端修改课程购买须知 + * @param commonStringRequest 修改内容 + * @return 是否修改成功 + */ + @PostMapping("modify/courseDesc") + @Operation(summary = "web端修改课程购买须知", description = "参数:修改内容,权限:管理员(boss, admin),方法名:modifyCourseDesc") + @RequiresPermission(mustRole = UserConstant.ADMIN_ROLE) + public BaseResponse modifyCourseDesc(@Valid @RequestBody CommonStringRequest commonStringRequest) { + String courseDesc = commonStringRequest.getTemplateString(); + redisTemplate.opsForValue().set(UserConstant.COURSE_DESC_KEY, courseDesc); + return ResultUtils.success(true); + } + + + /** + * 小程序端查询课程购买须知 + * @return 是否修改成功 + */ + @PostMapping("query/courseDesc") + @Operation(summary = "小程序端查询课程购买须知", description = "参数:无,权限:管理员(boss, admin),方法名:queryApplyNotice") + @RequiresPermission(mustRole = UserConstant.DEFAULT_ROLE) + public BaseResponse queryCourseDesc() { + String courseDesc = redisTemplate.opsForValue().get(UserConstant.COURSE_DESC_KEY); + return ResultUtils.success(courseDesc); + } + + + + /** * 小程序端用户修改用户昵称 * @param commonStringRequest 昵称