From e8ef359fcf498b446b3306c91778b2746452fe7f Mon Sep 17 00:00:00 2001
From: ziin
Date: Thu, 11 Dec 2025 14:58:30 +0800
Subject: [PATCH] =?UTF-8?q?feat(themes):=20=E6=96=B0=E5=A2=9E=E6=8E=A8?=
=?UTF-8?q?=E8=8D=90=E4=B8=BB=E9=A2=98=E4=B8=8E=E7=94=A8=E6=88=B7=E4=B8=BB?=
=?UTF-8?q?=E9=A2=98=E6=89=B9=E9=87=8F=E5=88=A0=E9=99=A4=E5=8A=9F=E8=83=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 新增 getRecommendedThemes:按真实下载量降序返回8个未购买主题
- 新增 batchDeleteUserThemes:支持用户批量逻辑删除已购主题
- 补充接口注释与 Swagger 文档,开放 /themes/recommended 免鉴权路径
---
.../keyborad/config/SaTokenConfigure.java | 3 +-
.../keyborad/controller/ThemesController.java | 8 +++
.../controller/UserThemesController.java | 34 ++++++++++
.../usertheme/BatchDeleteUserThemesReq.java | 20 ++++++
.../service/KeyboardThemesService.java | 7 ++
.../service/KeyboardUserThemesService.java | 10 ++-
.../impl/KeyboardThemesServiceImpl.java | 67 +++++++++++++++++++
.../impl/KeyboardUserThemesServiceImpl.java | 16 ++++-
.../impl/KeyboardUserWalletServiceImpl.java | 5 +-
9 files changed, 165 insertions(+), 5 deletions(-)
create mode 100644 src/main/java/com/yolo/keyborad/controller/UserThemesController.java
create mode 100644 src/main/java/com/yolo/keyborad/model/dto/usertheme/BatchDeleteUserThemesReq.java
diff --git a/src/main/java/com/yolo/keyborad/config/SaTokenConfigure.java b/src/main/java/com/yolo/keyborad/config/SaTokenConfigure.java
index efe584b..2e03108 100644
--- a/src/main/java/com/yolo/keyborad/config/SaTokenConfigure.java
+++ b/src/main/java/com/yolo/keyborad/config/SaTokenConfigure.java
@@ -91,7 +91,8 @@ public class SaTokenConfigure implements WebMvcConfigurer {
"/themes/purchase",
"/themes/purchased",
"/themes/purchase/list",
- "/themes/detail"
+ "/themes/detail",
+ "/themes/recommended"
};
}
@Bean
diff --git a/src/main/java/com/yolo/keyborad/controller/ThemesController.java b/src/main/java/com/yolo/keyborad/controller/ThemesController.java
index 2c2f258..0e6030a 100644
--- a/src/main/java/com/yolo/keyborad/controller/ThemesController.java
+++ b/src/main/java/com/yolo/keyborad/controller/ThemesController.java
@@ -83,4 +83,12 @@ public class ThemesController {
return ResultUtils.success(result);
}
+ @GetMapping("/recommended")
+ @Operation(summary = "推荐主题列表", description = "按真实下载数量降序返回推荐主题")
+ public BaseResponse> getRecommendedThemes() {
+ Long userId = StpUtil.getLoginIdAsLong();
+ List result = themesService.getRecommendedThemes(userId);
+ return ResultUtils.success(result);
+ }
+
}
diff --git a/src/main/java/com/yolo/keyborad/controller/UserThemesController.java b/src/main/java/com/yolo/keyborad/controller/UserThemesController.java
new file mode 100644
index 0000000..283d60e
--- /dev/null
+++ b/src/main/java/com/yolo/keyborad/controller/UserThemesController.java
@@ -0,0 +1,34 @@
+package com.yolo.keyborad.controller;
+
+import cn.dev33.satoken.stp.StpUtil;
+import com.yolo.keyborad.common.BaseResponse;
+import com.yolo.keyborad.common.ResultUtils;
+import com.yolo.keyborad.model.dto.usertheme.BatchDeleteUserThemesReq;
+import com.yolo.keyborad.service.KeyboardUserThemesService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+
+/*
+ * @author: ziin
+ * @date: 2025/12/11
+ */
+@RestController
+@Slf4j
+@RequestMapping("/user-themes")
+@Tag(name = "用户主题")
+public class UserThemesController {
+
+ @Resource
+ private KeyboardUserThemesService userThemesService;
+
+ @PostMapping("/batch-delete")
+ @Operation(summary = "批量删除用户主题", description = "批量逻辑删除用户主题")
+ public BaseResponse batchDeleteUserThemes(@RequestBody BatchDeleteUserThemesReq req) {
+ Long userId = StpUtil.getLoginIdAsLong();
+ userThemesService.batchDeleteUserThemes(userId, req.getThemeIds());
+ return ResultUtils.success(true);
+ }
+}
diff --git a/src/main/java/com/yolo/keyborad/model/dto/usertheme/BatchDeleteUserThemesReq.java b/src/main/java/com/yolo/keyborad/model/dto/usertheme/BatchDeleteUserThemesReq.java
new file mode 100644
index 0000000..2d038c7
--- /dev/null
+++ b/src/main/java/com/yolo/keyborad/model/dto/usertheme/BatchDeleteUserThemesReq.java
@@ -0,0 +1,20 @@
+package com.yolo.keyborad.model.dto.usertheme;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.util.List;
+
+/*
+ * @author: ziin
+ * @date: 2025/12/11
+ */
+@Schema(description = "批量删除用户主题请求")
+@Data
+public class BatchDeleteUserThemesReq {
+ /**
+ * 主题ID列表
+ */
+ @Schema(description = "主题ID列表")
+ private List themeIds;
+}
diff --git a/src/main/java/com/yolo/keyborad/service/KeyboardThemesService.java b/src/main/java/com/yolo/keyborad/service/KeyboardThemesService.java
index 8572a57..8e23099 100644
--- a/src/main/java/com/yolo/keyborad/service/KeyboardThemesService.java
+++ b/src/main/java/com/yolo/keyborad/service/KeyboardThemesService.java
@@ -29,4 +29,11 @@ public interface KeyboardThemesService extends IService{
*/
KeyboardThemesRespVO getThemeDetail(Long themeId, Long userId);
+ /**
+ * 推荐主题列表(按真实下载数量降序)
+ * @param userId 用户ID
+ * @return 推荐主题列表
+ */
+ List getRecommendedThemes(Long userId);
+
}
diff --git a/src/main/java/com/yolo/keyborad/service/KeyboardUserThemesService.java b/src/main/java/com/yolo/keyborad/service/KeyboardUserThemesService.java
index a73dd3e..2b0bb81 100644
--- a/src/main/java/com/yolo/keyborad/service/KeyboardUserThemesService.java
+++ b/src/main/java/com/yolo/keyborad/service/KeyboardUserThemesService.java
@@ -2,12 +2,20 @@ package com.yolo.keyborad.service;
import com.yolo.keyborad.model.entity.KeyboardUserThemes;
import com.baomidou.mybatisplus.extension.service.IService;
- /*
+
+import java.util.List;
+/*
* @author: ziin
* @date: 2025/12/11 13:31
*/
public interface KeyboardUserThemesService extends IService{
+ /**
+ * 批量删除用户主题(逻辑删除)
+ * @param userId 用户ID
+ * @param themeIds 主题ID列表
+ */
+ void batchDeleteUserThemes(Long userId, List themeIds);
}
diff --git a/src/main/java/com/yolo/keyborad/service/impl/KeyboardThemesServiceImpl.java b/src/main/java/com/yolo/keyborad/service/impl/KeyboardThemesServiceImpl.java
index 8786969..22e985d 100644
--- a/src/main/java/com/yolo/keyborad/service/impl/KeyboardThemesServiceImpl.java
+++ b/src/main/java/com/yolo/keyborad/service/impl/KeyboardThemesServiceImpl.java
@@ -27,16 +27,34 @@ public class KeyboardThemesServiceImpl extends ServiceImpl查询规则:
+ *
+ * - 当themeStyle为9999时,查询所有主题并按排序字段升序排列
+ * - 其他情况下,查询指定风格的主题
+ * - 查询结果均过滤已删除和未启用的主题
+ * - 返回的主题列表包含用户的购买状态
+ *
+ *
+ * @param themeStyle 主题风格ID,9999表示查询所有风格
+ * @param userId 用户ID,用于判断主题购买状态
+ * @return 主题列表,包含主题详情和购买状态
+ */
@Override
public List selectThemesByStyle(Long themeStyle, Long userId) {
+ // 根据风格参数查询主题列表
List themesList;
if (themeStyle == 9999) {
+ // 查询所有主题,按排序字段升序
themesList = this.lambdaQuery()
.eq(KeyboardThemes::getDeleted, false)
.eq(KeyboardThemes::getThemeStatus, true)
.orderByAsc(KeyboardThemes::getSort)
.list();
} else {
+ // 查询指定风格的主题
themesList = this.lambdaQuery()
.eq(KeyboardThemes::getDeleted, false)
.eq(KeyboardThemes::getThemeStatus, true)
@@ -44,6 +62,7 @@ public class KeyboardThemesServiceImpl extends ServiceImpl purchasedThemeIds = purchaseService.lambdaQuery()
.eq(KeyboardThemePurchase::getUserId, userId)
.eq(KeyboardThemePurchase::getPayStatus, (short) 1)
@@ -52,6 +71,7 @@ public class KeyboardThemesServiceImpl extends ServiceImpl {
KeyboardThemesRespVO vo = BeanUtil.copyProperties(theme, KeyboardThemesRespVO.class);
vo.setIsPurchased(purchasedThemeIds.contains(theme.getId()));
@@ -59,26 +79,73 @@ public class KeyboardThemesServiceImpl extends ServiceImpl查询指定ID的主题详情,并返回用户对该主题的购买状态
+ *
+ * @param themeId 主题ID
+ * @param userId 用户ID,用于判断购买状态
+ * @return 主题详情VO,包含主题信息和购买状态;如果主题不存在或已删除则返回null
+ */
@Override
public KeyboardThemesRespVO getThemeDetail(Long themeId, Long userId) {
+ // 查询主题详情
KeyboardThemes theme = this.lambdaQuery()
.eq(KeyboardThemes::getId, themeId)
.eq(KeyboardThemes::getDeleted, false)
.eq(KeyboardThemes::getThemeStatus, true)
.one();
+ // 主题不存在或已删除,返回null
if (theme == null) {
return null;
}
+ // 查询用户是否购买该主题
boolean isPurchased = purchaseService.lambdaQuery()
.eq(KeyboardThemePurchase::getUserId, userId)
.eq(KeyboardThemePurchase::getThemeId, themeId)
.eq(KeyboardThemePurchase::getPayStatus, (short) 1)
.exists();
+ // 转换为VO并设置购买状态
KeyboardThemesRespVO vo = BeanUtil.copyProperties(theme, KeyboardThemesRespVO.class);
vo.setIsPurchased(isPurchased);
return vo;
}
+
+ @Override
+ /*
+ 获取推荐主题列表
+ 推荐规则:根据真实下载量降序排序,排除用户已购买的主题,最多返回8个主题
+
+ @param userId 用户ID
+ * @return 推荐主题列表,包含主题详情和购买状态(推荐列表中的主题购买状态均为未购买)
+ */
+ public List getRecommendedThemes(Long userId) {
+ // 查询用户已购买的主题ID集合
+ Set purchasedThemeIds = purchaseService.lambdaQuery()
+ .eq(KeyboardThemePurchase::getUserId, userId)
+ .eq(KeyboardThemePurchase::getPayStatus, (short) 1)
+ .list()
+ .stream()
+ .map(KeyboardThemePurchase::getThemeId)
+ .collect(Collectors.toSet());
+
+ // 查询推荐主题列表:未删除、已启用、未购买、按真实下载量降序、限制8条
+ return this.lambdaQuery()
+ .eq(KeyboardThemes::getDeleted, false)
+ .eq(KeyboardThemes::getThemeStatus, true)
+ .notIn(!purchasedThemeIds.isEmpty(), KeyboardThemes::getId, purchasedThemeIds)
+ .orderByDesc(KeyboardThemes::getRealDownloadCount)
+ .last("LIMIT 8")
+ .list()
+ .stream()
+ .map(theme -> {
+ KeyboardThemesRespVO vo = BeanUtil.copyProperties(theme, KeyboardThemesRespVO.class);
+ // 推荐列表中的主题均为未购买状态
+ vo.setIsPurchased(false);
+ return vo;
+ }).collect(Collectors.toList());
+ }
}
diff --git a/src/main/java/com/yolo/keyborad/service/impl/KeyboardUserThemesServiceImpl.java b/src/main/java/com/yolo/keyborad/service/impl/KeyboardUserThemesServiceImpl.java
index 9f70902..7e6a880 100644
--- a/src/main/java/com/yolo/keyborad/service/impl/KeyboardUserThemesServiceImpl.java
+++ b/src/main/java/com/yolo/keyborad/service/impl/KeyboardUserThemesServiceImpl.java
@@ -1,7 +1,6 @@
package com.yolo.keyborad.service.impl;
import org.springframework.stereotype.Service;
-import org.springframework.beans.factory.annotation.Autowired;
import java.util.List;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yolo.keyborad.model.entity.KeyboardUserThemes;
@@ -15,4 +14,19 @@ import com.yolo.keyborad.service.KeyboardUserThemesService;
@Service
public class KeyboardUserThemesServiceImpl extends ServiceImpl implements KeyboardUserThemesService{
+
+ /**
+ * 批量删除用户主题(逻辑删除)
+ *
+ * @param userId 用户ID
+ * @param themeIds 主题ID列表
+ */
+ @Override
+ public void batchDeleteUserThemes(Long userId, List themeIds) {
+ this.lambdaUpdate()
+ .eq(KeyboardUserThemes::getUserId, userId)
+ .in(KeyboardUserThemes::getThemeId, themeIds)
+ .set(KeyboardUserThemes::getViewDeleted, true)
+ .update();
+ }
}
diff --git a/src/main/java/com/yolo/keyborad/service/impl/KeyboardUserWalletServiceImpl.java b/src/main/java/com/yolo/keyborad/service/impl/KeyboardUserWalletServiceImpl.java
index e863d5e..de7695b 100644
--- a/src/main/java/com/yolo/keyborad/service/impl/KeyboardUserWalletServiceImpl.java
+++ b/src/main/java/com/yolo/keyborad/service/impl/KeyboardUserWalletServiceImpl.java
@@ -9,6 +9,7 @@ import com.yolo.keyborad.model.entity.KeyboardUserWallet;
import com.yolo.keyborad.service.KeyboardUserWalletService;
import java.math.BigDecimal;
+import java.math.RoundingMode;
/*
* @author: ziin
@@ -33,9 +34,9 @@ public class KeyboardUserWalletServiceImpl extends ServiceImpl= 0) {
- BigDecimal kValue = balance.divide(new BigDecimal("1000"), 2, BigDecimal.ROUND_HALF_UP);
+ BigDecimal kValue = balance.divide(new BigDecimal("1000"), 2, RoundingMode.HALF_UP);
return kValue.stripTrailingZeros().toPlainString() + "K";
}
- return balance.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString();
+ return balance.setScale(2, RoundingMode.HALF_UP).toPlainString();
}
}