From fcd35c78e5ac655e0a8fea9e5b49a7da71c476ca Mon Sep 17 00:00:00 2001 From: huazhongmin Date: Tue, 9 Sep 2025 11:13:36 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .augment/rules/rules.md | 18 +- .../controller/EmotionRecordController.java | 58 +-- .../controller/EmotionSummaryController.java | 89 ++--- .../controller/GrowthTopicController.java | 100 ++--- .../controller/GuestUserController.java | 107 +++--- .../emotion/controller/MessageController.java | 126 +++---- .../emotion/controller/RewardController.java | 111 +++--- .../TopicInteractionController.java | 95 +++-- .../emotion/controller/UserController.java | 171 ++------- .../controller/UserStatsController.java | 212 ++--------- .../controller/WebSocketController.java | 114 ------ .../request/EmotionRecordCreateRequest.java | 10 + .../dto/request/EmotionRecordPageRequest.java | 5 + .../request/EmotionRecordUpdateRequest.java | 10 + .../EmotionSummaryGenerateRequest.java | 14 + .../request/EmotionSummaryStatusRequest.java | 14 + .../TopicInteractionCreateRequest.java | 65 ++++ .../request/TopicInteractionPageRequest.java | 36 ++ .../TopicInteractionUpdateRequest.java | 70 ++++ .../emotion/dto/request/UserPageRequest.java | 53 +++ .../dto/request/UserStatsCreateRequest.java | 39 ++ .../request/UserStatsIncrementRequest.java | 34 ++ .../dto/request/UserStatsPageRequest.java | 26 ++ .../request/UserStatsUpdateValueRequest.java | 34 ++ .../dto/request/UserUpdateRequest.java | 19 +- .../growth/GrowthTopicCreateRequest.java | 55 +++ .../growth/GrowthTopicPageRequest.java | 34 ++ .../growth/GrowthTopicUpdateRequest.java | 58 +++ .../request/guest/GuestUserCreateRequest.java | 41 +++ .../request/guest/GuestUserPageRequest.java | 31 ++ .../request/guest/GuestUserUpdateRequest.java | 40 ++ .../request/reward/RewardCreateRequest.java | 65 ++++ .../dto/request/reward/RewardPageRequest.java | 31 ++ .../request/reward/RewardUpdateRequest.java | 67 ++++ .../EmotionSummaryGenerateResponse.java | 45 +++ .../EmotionSummaryStatusResponse.java | 30 ++ .../response/TopicInteractionResponse.java | 57 +++ .../dto/response/UserStatsResponse.java | 35 ++ .../response/growth/GrowthTopicResponse.java | 74 ++++ .../dto/response/guest/GuestUserResponse.java | 68 ++++ .../dto/response/reward/RewardResponse.java | 68 ++++ .../java/com/emotion/entity/UserStats.java | 20 +- .../com/emotion/service/AiChatService.java | 33 +- .../emotion/service/EmotionRecordService.java | 85 ----- .../emotion/service/GrowthTopicService.java | 120 ++---- .../com/emotion/service/GuestUserService.java | 33 +- .../com/emotion/service/MessageService.java | 29 +- .../com/emotion/service/RewardService.java | 37 +- .../service/TopicInteractionService.java | 143 +------- .../java/com/emotion/service/UserService.java | 108 ++---- .../com/emotion/service/UserStatsService.java | 102 +----- .../service/impl/AiChatServiceImpl.java | 71 ++++ .../impl/EmotionRecordServiceImpl.java | 186 ---------- .../service/impl/GrowthTopicServiceImpl.java | 240 ++++++------ .../service/impl/GuestUserServiceImpl.java | 98 ++++- .../service/impl/MessageServiceImpl.java | 121 ++++-- .../service/impl/RewardServiceImpl.java | 126 ++++++- .../impl/TopicInteractionServiceImpl.java | 343 ++++++------------ .../emotion/service/impl/UserServiceImpl.java | 330 ++++++++++------- .../service/impl/UserStatsServiceImpl.java | 295 +++++++-------- 60 files changed, 2753 insertions(+), 2196 deletions(-) delete mode 100644 backend-single/src/main/java/com/emotion/controller/WebSocketController.java create mode 100644 backend-single/src/main/java/com/emotion/dto/request/EmotionSummaryGenerateRequest.java create mode 100644 backend-single/src/main/java/com/emotion/dto/request/EmotionSummaryStatusRequest.java create mode 100644 backend-single/src/main/java/com/emotion/dto/request/TopicInteractionCreateRequest.java create mode 100644 backend-single/src/main/java/com/emotion/dto/request/TopicInteractionPageRequest.java create mode 100644 backend-single/src/main/java/com/emotion/dto/request/TopicInteractionUpdateRequest.java create mode 100644 backend-single/src/main/java/com/emotion/dto/request/UserPageRequest.java create mode 100644 backend-single/src/main/java/com/emotion/dto/request/UserStatsCreateRequest.java create mode 100644 backend-single/src/main/java/com/emotion/dto/request/UserStatsIncrementRequest.java create mode 100644 backend-single/src/main/java/com/emotion/dto/request/UserStatsPageRequest.java create mode 100644 backend-single/src/main/java/com/emotion/dto/request/UserStatsUpdateValueRequest.java create mode 100644 backend-single/src/main/java/com/emotion/dto/request/growth/GrowthTopicCreateRequest.java create mode 100644 backend-single/src/main/java/com/emotion/dto/request/growth/GrowthTopicPageRequest.java create mode 100644 backend-single/src/main/java/com/emotion/dto/request/growth/GrowthTopicUpdateRequest.java create mode 100644 backend-single/src/main/java/com/emotion/dto/request/guest/GuestUserCreateRequest.java create mode 100644 backend-single/src/main/java/com/emotion/dto/request/guest/GuestUserPageRequest.java create mode 100644 backend-single/src/main/java/com/emotion/dto/request/guest/GuestUserUpdateRequest.java create mode 100644 backend-single/src/main/java/com/emotion/dto/request/reward/RewardCreateRequest.java create mode 100644 backend-single/src/main/java/com/emotion/dto/request/reward/RewardPageRequest.java create mode 100644 backend-single/src/main/java/com/emotion/dto/request/reward/RewardUpdateRequest.java create mode 100644 backend-single/src/main/java/com/emotion/dto/response/EmotionSummaryGenerateResponse.java create mode 100644 backend-single/src/main/java/com/emotion/dto/response/EmotionSummaryStatusResponse.java create mode 100644 backend-single/src/main/java/com/emotion/dto/response/TopicInteractionResponse.java create mode 100644 backend-single/src/main/java/com/emotion/dto/response/UserStatsResponse.java create mode 100644 backend-single/src/main/java/com/emotion/dto/response/growth/GrowthTopicResponse.java create mode 100644 backend-single/src/main/java/com/emotion/dto/response/guest/GuestUserResponse.java create mode 100644 backend-single/src/main/java/com/emotion/dto/response/reward/RewardResponse.java diff --git a/.augment/rules/rules.md b/.augment/rules/rules.md index 1bea7c3..4015db3 100644 --- a/.augment/rules/rules.md +++ b/.augment/rules/rules.md @@ -80,11 +80,9 @@ type: "always_apply" 43. 异常信息要包含足够的上下文信息 44. 生产环境禁止输出debug级别日志 ---- - ## Java Spring Boot 项目开发与代码质量保障规范(扩展) -适用范围:本规范适用于 logistics-finance 项目所有后端模块(common、gateway、auth、user、order、waybill、vehicle、finance、report、ai、file)。若与本文件前文条款或现有项目规范冲突,以更严格者为准。 +适用范围:本规范适用于 EmotionMuseum 项目所有后端模块。若与本文件前文条款或现有项目规范冲突,以更严格者为准。 ### 一、代码规范完善 @@ -149,9 +147,7 @@ type: "always_apply" - 事务管理 - 仅在 Service 层声明事务;方法内仅包含数据库操作或与数据库一致性相关的远程调用;跨服务一致性使用可靠消息/补偿方案。 ---- - -## 二、代码质量保障机制 +## 代码质量保障机制 - 代码审查流程(Code Review) - 所有变更必须走 PR;至少 1 名同组开发+1 名模块 Owner 审核通过方可合并。 @@ -176,9 +172,7 @@ type: "always_apply" - 小步快跑、单一职责、先加测试再重构;保持对外行为一致(新增特性使用特性开关/版本控制)。 - 严禁大规模跨模块重构合并在单次 PR;拆分为多个可审查的独立提交。 ---- - -## 三、变更管理流程 +## 变更管理流程 - 变更前影响分析 - 维度:接口兼容性(路径/入参/语义)、数据库(表/字段/索引/数据迁移)、配置(Nacos/环境变量)、依赖版本、性能、容量与并发、安全与合规、可回滚性。 @@ -200,9 +194,7 @@ type: "always_apply" - 紧急修复:创建 hotfix → 修复 → 快速测试 → 合并 master 与 release → 立即发布 → 追补测试与文档。 - 常规开发:feature → PR 审核 → 合并 → 集成测试 → 发布。 ---- - -## 四、持续改进机制 +## 持续改进机制 - 规范评审与更新 - 每月一次质量例会,评审新增问题与改进项;规范变更需在本文件留痕(版本/日期/变更点)。 @@ -216,8 +208,6 @@ type: "always_apply" - 反馈闭环 - 通过代码评审、事后复盘(Postmortem)、问题工单收敛到规范条款;指定责任人与截止时间;下次评审验证落地结果。 ---- - ## 附:标准检查清单(节选) - PR 自检 diff --git a/backend-single/src/main/java/com/emotion/controller/EmotionRecordController.java b/backend-single/src/main/java/com/emotion/controller/EmotionRecordController.java index d4bcbdd..dfdd10c 100644 --- a/backend-single/src/main/java/com/emotion/controller/EmotionRecordController.java +++ b/backend-single/src/main/java/com/emotion/controller/EmotionRecordController.java @@ -8,9 +8,6 @@ import com.emotion.dto.request.EmotionRecordUpdateRequest; import com.emotion.dto.response.EmotionRecordResponse; import com.emotion.service.EmotionRecordService; import com.emotion.util.CurrentUserUtil; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.tags.Tag; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -18,8 +15,6 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import javax.validation.Valid; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; import java.util.List; import java.util.Map; @@ -30,8 +25,7 @@ import java.util.Map; * @date 2025-07-22 */ @RestController -@RequestMapping("/emotion-records") -@Tag(name = "情绪记录管理", description = "用户情绪记录的增删改查功能") +@RequestMapping("/emotionRecord") public class EmotionRecordController { private static final Logger log = LoggerFactory.getLogger(EmotionRecordController.class); @@ -42,8 +36,7 @@ public class EmotionRecordController { /** * 创建情绪记录 */ - @PostMapping - @Operation(summary = "创建情绪记录", description = "创建新的情绪记录") + @PostMapping(value = "/create") public Result createRecord(@RequestBody @Valid EmotionRecordCreateRequest request) { log.info("创建情绪记录: userId={}", request.getUserId()); @@ -56,51 +49,27 @@ public class EmotionRecordController { } /** - * 获取用户情绪记录列表 + * 分页查询情绪记录 */ - @Operation(summary = "获取用户情绪记录列表", description = "分页获取当前用户的情绪记录,按创建时间倒序") - @GetMapping("/user") - public Result> getRecordList( - @Validated EmotionRecordPageRequest request) { - + @GetMapping(value = "/page") + public Result> getPage(@Validated EmotionRecordPageRequest request) { // 从上下文中获取当前用户ID String userId = CurrentUserUtil.requireCurrentUserId(); - log.info("获取用户情绪记录列表: userId={}, current={}, size={}", userId, request.getCurrent(), request.getSize()); + log.info("分页查询情绪记录: userId={}, current={}, size={}", userId, request.getCurrent(), request.getSize()); PageResult page = emotionRecordService.getPageByUserIdWithResponse(userId, request); - log.info("获取用户情绪记录成功: userId={}, total={}, records={}", - userId, page.getTotal(), page.getRecords().size()); + log.info("分页查询情绪记录成功: userId={}, total={}, records={}", + userId, page.getTotal(), page.getRecords().size()); return Result.success(page); } - /** - * 获取用户最近情绪记录 - */ - @Operation(summary = "获取用户最近情绪记录", description = "获取当前用户最近的情绪记录列表") - @GetMapping("/user/recent") - public Result> getRecentRecords( - @Parameter(description = "限制数量") @RequestParam(defaultValue = "5") Integer limit) { - - // 从上下文中获取当前用户ID - String userId = CurrentUserUtil.requireCurrentUserId(); - - log.info("获取用户最近情绪记录: userId={}, limit={}", userId, limit); - - List records = emotionRecordService.getRecentByUserIdWithResponse(userId, limit); - - log.info("获取用户最近情绪记录成功: userId={}, records={}", userId, records.size()); - - return Result.success(records); - } - /** * 获取情绪记录详情 */ - @Operation(summary = "获取情绪记录详情", description = "根据ID获取情绪记录详情") - @GetMapping + @GetMapping(value = "/detail") public Result getRecord(@RequestParam String id) { log.info("获取情绪记录详情: {}", id); @@ -114,8 +83,7 @@ public class EmotionRecordController { /** * 更新情绪记录 */ - @Operation(summary = "更新情绪记录", description = "更新指定的情绪记录") - @PutMapping + @PutMapping(value = "/update") public Result updateRecord(@RequestBody @Valid EmotionRecordUpdateRequest request) { log.info("更新情绪记录: {}", request.getId()); @@ -129,8 +97,7 @@ public class EmotionRecordController { /** * 删除情绪记录 */ - @Operation(summary = "删除情绪记录", description = "删除指定的情绪记录") - @DeleteMapping + @DeleteMapping(value = "/delete") public Result deleteRecord(@RequestParam String id) { log.info("删除情绪记录: {}", id); @@ -144,8 +111,7 @@ public class EmotionRecordController { /** * 获取情绪统计 */ - @Operation(summary = "获取情绪统计", description = "获取当前用户的情绪统计信息") - @GetMapping("/stats") + @GetMapping(value = "/stats") public Result> getEmotionStats( @RequestParam(required = false) String startDate, @RequestParam(required = false) String endDate) { diff --git a/backend-single/src/main/java/com/emotion/controller/EmotionSummaryController.java b/backend-single/src/main/java/com/emotion/controller/EmotionSummaryController.java index 0ecaeef..7fd3528 100644 --- a/backend-single/src/main/java/com/emotion/controller/EmotionSummaryController.java +++ b/backend-single/src/main/java/com/emotion/controller/EmotionSummaryController.java @@ -1,16 +1,20 @@ package com.emotion.controller; import com.emotion.common.Result; +import com.emotion.dto.request.EmotionSummaryGenerateRequest; +import com.emotion.dto.request.EmotionSummaryStatusRequest; +import com.emotion.dto.response.EmotionSummaryGenerateResponse; +import com.emotion.dto.response.EmotionSummaryStatusResponse; import com.emotion.service.AiChatService; import com.emotion.util.CurrentUserUtil; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import org.springframework.scheduling.annotation.Async; -import java.util.concurrent.CompletableFuture; -import java.util.Map; + +import javax.validation.Valid; /** * 情绪总结控制器 @@ -20,64 +24,49 @@ import java.util.Map; */ @Slf4j @RestController -@RequestMapping("/emotion-summary") +@RequestMapping("/emotionSummary") @Tag(name = "情绪总结管理", description = "用户情绪记录总结和分析功能") public class EmotionSummaryController { @Autowired private AiChatService aiChatService; + /** + * 生成用户当天的情绪记录总结 + */ @Operation(summary = "生成用户当天的情绪记录总结", description = "基于用户当天的聊天记录生成情绪分析和记录") - @PostMapping("/generate") - public Result> generateEmotionSummary() { - try { - String userId = CurrentUserUtil.requireCurrentUserId(); - log.info("收到生成情绪记录总结请求: userId={}", userId); - // 调用AI服务异步生成情绪总结(阻塞获取结果) - Map result = aiChatService.generateEmotionSummaryAsync(userId).get(); - if ((Boolean) result.get("success")) { - log.info("情绪记录总结生成成功: userId={}", userId); - return Result.success("情绪记录总结生成成功", result); - } else { - String message = (String) result.get("message"); - log.warn("情绪记录总结生成失败: userId={}, message={}", userId, message); - return Result.error(message); - } - } catch (IllegalStateException e) { - log.warn("用户认证失败: {}", e.getMessage()); - return Result.error(e.getMessage()); - } catch (Exception e) { - log.error("生成情绪记录总结时发生异常", e); - return Result.error("生成情绪记录总结失败: " + e.getMessage()); + @PostMapping(value = "/generate") + public Result generateEmotionSummary( + @RequestBody @Valid EmotionSummaryGenerateRequest request) { + String userId = CurrentUserUtil.requireCurrentUserId(); + log.info("收到生成情绪记录总结请求: userId={}", userId); + + // 调用AI服务生成情绪总结 + EmotionSummaryGenerateResponse response = aiChatService.generateEmotionSummaryWithResponse(userId); + + if (response.getSuccess()) { + log.info("情绪记录总结生成成功: userId={}", userId); + return Result.success("情绪记录总结生成成功", response); + } else { + log.warn("情绪记录总结生成失败: userId={}, message={}", userId, response.getMessage()); + return Result.error(response.getMessage()); } } + /** + * 获取用户情绪记录总结状态 + */ @Operation(summary = "获取用户情绪记录总结状态", description = "检查用户今天是否已经生成过情绪记录") - @GetMapping("/status") - public Result> getEmotionSummaryStatus() { + @GetMapping(value = "/status") + public Result getEmotionSummaryStatus( + @Validated EmotionSummaryStatusRequest request) { + // 从上下文中获取当前用户ID + String userId = CurrentUserUtil.requireCurrentUserId(); + log.info("查询用户情绪记录总结状态: userId={}", userId); - try { - // 从上下文中获取当前用户ID - String userId = CurrentUserUtil.requireCurrentUserId(); + // 调用AI服务获取状态信息 + EmotionSummaryStatusResponse response = aiChatService.getEmotionSummaryStatusWithResponse(userId); - log.info("查询用户情绪记录总结状态: userId={}", userId); - - // 这里可以添加检查用户今天是否已经生成过情绪记录的逻辑 - // 暂时返回基本状态信息 - Map status = Map.of( - "userId", userId, - "canGenerate", true, - "message", "可以生成情绪记录总结" - ); - - return Result.success(status); - - } catch (IllegalStateException e) { - log.warn("用户认证失败: {}", e.getMessage()); - return Result.error(e.getMessage()); - } catch (Exception e) { - log.error("查询情绪记录总结状态时发生异常", e); - return Result.error("查询状态失败: " + e.getMessage()); - } + return Result.success(response); } -} +} \ No newline at end of file diff --git a/backend-single/src/main/java/com/emotion/controller/GrowthTopicController.java b/backend-single/src/main/java/com/emotion/controller/GrowthTopicController.java index ea49fdc..78553d3 100644 --- a/backend-single/src/main/java/com/emotion/controller/GrowthTopicController.java +++ b/backend-single/src/main/java/com/emotion/controller/GrowthTopicController.java @@ -1,19 +1,26 @@ package com.emotion.controller; -import com.baomidou.mybatisplus.core.metadata.IPage; +import com.emotion.common.PageResult; import com.emotion.common.Result; -import com.emotion.dto.request.PageRequest; -import com.emotion.entity.GrowthTopic; +import com.emotion.dto.request.growth.GrowthTopicCreateRequest; +import com.emotion.dto.request.growth.GrowthTopicPageRequest; +import com.emotion.dto.request.growth.GrowthTopicUpdateRequest; +import com.emotion.dto.response.growth.GrowthTopicResponse; import com.emotion.service.GrowthTopicService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import java.time.LocalDateTime; -import java.util.List; +import javax.validation.Valid; +/** + * 成长话题控制器 + * + * @author emotion-museum + * @date 2025-09-08 + */ @RestController -@RequestMapping("/growth-topic") +@RequestMapping("/growthTopic") public class GrowthTopicController { @Autowired @@ -22,49 +29,54 @@ public class GrowthTopicController { /** * 分页查询成长话题 */ - @GetMapping("/page") - public Result> getPage(@Validated PageRequest request) { - IPage page = growthTopicService.getPage(request); - return Result.success(page); + @GetMapping(value = "/page") + public Result> getPage(@Validated GrowthTopicPageRequest request) { + PageResult pageResult = growthTopicService.getPageWithResponse(request); + return Result.success(pageResult); + } + + /** + * 根据ID获取成长话题 + */ + @GetMapping(value = "/detail") + public Result getById(@RequestParam String id) { + GrowthTopicResponse response = growthTopicService.getGrowthTopicResponseById(id); + if (response == null) { + return Result.notFound("成长话题不存在"); + } + return Result.success(response); } /** * 创建成长话题 */ - @PostMapping("/create") - public Result createGrowthTopic(@RequestBody @Validated GrowthTopicCreateRequest request) { - GrowthTopic topic = growthTopicService.createGrowthTopic( - request.getTitle(), - request.getDescription(), - request.getCategory(), - request.getDifficultyLevel(), - request.getTags(), - request.getEndTime() - ); - return Result.success(topic); + @PostMapping(value = "/create") + public Result create(@Valid @RequestBody GrowthTopicCreateRequest request) { + GrowthTopicResponse response = growthTopicService.createGrowthTopicWithResponse(request); + return Result.success(response); } - // 可根据GrowthTopicService接口继续补充其他接口... - - public static class GrowthTopicCreateRequest { - private String title; - private String description; - private String category; - private String difficultyLevel; - private String tags; - private LocalDateTime endTime; - // getter/setter - public String getTitle() { return title; } - public void setTitle(String title) { this.title = title; } - public String getDescription() { return description; } - public void setDescription(String description) { this.description = description; } - public String getCategory() { return category; } - public void setCategory(String category) { this.category = category; } - public String getDifficultyLevel() { return difficultyLevel; } - public void setDifficultyLevel(String difficultyLevel) { this.difficultyLevel = difficultyLevel; } - public String getTags() { return tags; } - public void setTags(String tags) { this.tags = tags; } - public LocalDateTime getEndTime() { return endTime; } - public void setEndTime(LocalDateTime endTime) { this.endTime = endTime; } + /** + * 更新成长话题 + */ + @PutMapping(value = "/update") + public Result update(@Valid @RequestBody GrowthTopicUpdateRequest request) { + GrowthTopicResponse response = growthTopicService.updateGrowthTopicWithResponse(request); + if (response == null) { + return Result.notFound("成长话题不存在"); + } + return Result.success(response); } -} \ No newline at end of file + + /** + * 删除成长话题 + */ + @DeleteMapping(value = "/delete") + public Result delete(@RequestParam String id) { + boolean deleted = growthTopicService.deleteGrowthTopic(id); + if (!deleted) { + return Result.error("删除失败"); + } + return Result.success(); + } +} \ No newline at end of file diff --git a/backend-single/src/main/java/com/emotion/controller/GuestUserController.java b/backend-single/src/main/java/com/emotion/controller/GuestUserController.java index 8565020..38c6764 100644 --- a/backend-single/src/main/java/com/emotion/controller/GuestUserController.java +++ b/backend-single/src/main/java/com/emotion/controller/GuestUserController.java @@ -1,19 +1,26 @@ package com.emotion.controller; -import com.baomidou.mybatisplus.core.metadata.IPage; +import com.emotion.common.PageResult; import com.emotion.common.Result; -import com.emotion.dto.request.PageRequest; -import com.emotion.entity.GuestUser; +import com.emotion.dto.request.guest.GuestUserCreateRequest; +import com.emotion.dto.request.guest.GuestUserPageRequest; +import com.emotion.dto.request.guest.GuestUserUpdateRequest; +import com.emotion.dto.response.guest.GuestUserResponse; import com.emotion.service.GuestUserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import java.time.LocalDateTime; -import java.util.List; +import javax.validation.Valid; +/** + * 访客用户控制器 + * + * @author emotion-museum + * @date 2025-09-08 + */ @RestController -@RequestMapping("/guest-user") +@RequestMapping("/guestUser") public class GuestUserController { @Autowired @@ -22,64 +29,54 @@ public class GuestUserController { /** * 分页查询访客用户 */ - @GetMapping("/page") - public Result> getPage(@Validated PageRequest request) { - IPage page = guestUserService.getPage(request); - return Result.success(page); + @GetMapping(value = "/page") + public Result> getPage(@Validated GuestUserPageRequest request) { + PageResult pageResult = guestUserService.getPageWithResponse(request); + return Result.success(pageResult); + } + + /** + * 根据ID获取访客用户 + */ + @GetMapping(value = "/detail") + public Result getById(@RequestParam String id) { + GuestUserResponse response = guestUserService.getGuestUserResponseById(id); + if (response == null) { + return Result.notFound("访客用户不存在"); + } + return Result.success(response); } /** * 创建访客用户 */ - @PostMapping("/create") - public Result createGuestUser(@RequestBody @Validated GuestUserCreateRequest request) { - GuestUser guestUser = guestUserService.createGuestUser( - request.getDeviceId(), - request.getIpAddress(), - request.getUserAgent(), - request.getLocation()); - return Result.success(guestUser); + @PostMapping(value = "/create") + public Result create(@Valid @RequestBody GuestUserCreateRequest request) { + GuestUserResponse response = guestUserService.createGuestUserWithResponse(request); + return Result.success(response); } - // 可根据GuestUserService接口继续补充其他接口... - - public static class GuestUserCreateRequest { - private String deviceId; - private String ipAddress; - private String userAgent; - private String location; - - // getter/setter - public String getDeviceId() { - return deviceId; + /** + * 更新访客用户 + */ + @PutMapping(value = "/update") + public Result update(@Valid @RequestBody GuestUserUpdateRequest request) { + GuestUserResponse response = guestUserService.updateGuestUserWithResponse(request); + if (response == null) { + return Result.notFound("访客用户不存在"); } + return Result.success(response); + } - public void setDeviceId(String deviceId) { - this.deviceId = deviceId; - } - - public String getIpAddress() { - return ipAddress; - } - - public void setIpAddress(String ipAddress) { - this.ipAddress = ipAddress; - } - - public String getUserAgent() { - return userAgent; - } - - public void setUserAgent(String userAgent) { - this.userAgent = userAgent; - } - - public String getLocation() { - return location; - } - - public void setLocation(String location) { - this.location = location; + /** + * 删除访客用户 + */ + @DeleteMapping(value = "/delete") + public Result delete(@RequestParam String id) { + boolean deleted = guestUserService.deleteGuestUser(id); + if (!deleted) { + return Result.error("删除失败"); } + return Result.success(); } } \ No newline at end of file diff --git a/backend-single/src/main/java/com/emotion/controller/MessageController.java b/backend-single/src/main/java/com/emotion/controller/MessageController.java index 47f1d34..a68672a 100644 --- a/backend-single/src/main/java/com/emotion/controller/MessageController.java +++ b/backend-single/src/main/java/com/emotion/controller/MessageController.java @@ -10,16 +10,16 @@ import com.emotion.dto.response.MessageResponse; import com.emotion.service.MessageService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import javax.validation.Valid; -import java.util.List; /** * 消息控制器 * * @author emotion-museum - * @date 2025-07-23 + * @date 2025-09-08 */ @RestController @RequestMapping("/message") @@ -32,104 +32,72 @@ public class MessageController { /** * 创建消息 */ - @PostMapping + @PostMapping(value = "/create") public Result create(@Valid @RequestBody MessageCreateRequest request) { - log.info("创建消息: conversationId={}", request.getConversationId()); - - try { - MessageResponse response = messageService.createMessageFromRequest(request); - log.info("创建消息成功: messageId={}", response.getId()); - return Result.success(response); - - } catch (IllegalStateException e) { - log.error("用户未认证: {}", e.getMessage()); - return Result.error(401, "用户未登录或认证失败"); - } catch (Exception e) { - log.error("创建消息失败", e); - return Result.error(500, "创建消息失败,请稍后重试"); - } + MessageResponse response = messageService.createMessageFromRequest(request); + return Result.success(response); } /** * 根据ID获取消息 */ - @GetMapping("/{id}") - public Result getById(@PathVariable String id) { - log.info("获取消息详情: id={}", id); - - try { - MessageResponse response = messageService.getMessageById(id); - if (response == null) { - return Result.error(404, "消息不存在"); - } - return Result.success(response); - - } catch (Exception e) { - log.error("获取消息详情失败", e); - return Result.error(500, "获取消息详情失败,请稍后重试"); + @GetMapping(value = "/detail") + public Result getById(@RequestParam String id) { + MessageResponse response = messageService.getMessageById(id); + if (response == null) { + return Result.notFound("消息不存在"); } + return Result.success(response); } /** - * 根据用户ID分页查询消息 + * 分页查询消息 */ - @GetMapping("/user/page") - public Result> getPageByUserId( - @RequestParam(defaultValue = "1") Long current, - @RequestParam(defaultValue = "20") Long size) { - log.info("获取用户消息分页: current={}, size={}", current, size); - - // 构建请求对象 - MessagePageRequest request = new MessagePageRequest(); - request.setCurrent(current); - request.setSize(size); - - PageResult pageResult = messageService.getUserMessagesWithPage(request); - log.info("获取用户消息分页成功: total={}", pageResult.getTotal()); + @GetMapping(value = "/page") + public Result> getPage(@Validated MessagePageRequest request) { + PageResult pageResult = messageService.getPageWithResponse(request); return Result.success(pageResult); } /** - * 根据用户ID和关键词搜索消息 + * 搜索消息 */ - @PostMapping("/user/search") - public Result> searchByUserId(@Valid @RequestBody MessageSearchRequest request) { - log.info("搜索用户消息: keyword={}, limit={}", request.getKeyword(), request.getLimit()); - - try { - List responses = messageService.searchUserMessages(request); - log.info("搜索用户消息成功: {} 条消息", responses.size()); - return Result.success(responses); - - } catch (IllegalStateException e) { - log.error("用户未认证: {}", e.getMessage()); - return Result.error(401, "用户未登录或认证失败"); - } catch (Exception e) { - log.error("搜索用户消息失败", e); - return Result.error(500, "搜索失败,请稍后重试"); - } + @PostMapping(value = "/search") + public Result> search(@Valid @RequestBody MessageSearchRequest request) { + PageResult pageResult = messageService.searchWithResponse(request); + return Result.success(pageResult); } /** - * 获取用户最近的聊天记录 + * 获取最近的消息 */ - @PostMapping("/user/recent") - public Result> getRecentMessages(@Valid @RequestBody MessageRecentRequest request) { - log.info("获取用户最近消息: limit={}", request.getLimit()); - - try { - List responses = messageService.getUserRecentMessages(request); - log.info("获取用户最近消息成功: {} 条消息", responses.size()); - return Result.success(responses); - - } catch (IllegalStateException e) { - log.error("用户未认证: {}", e.getMessage()); - return Result.error(401, "用户未登录或认证失败"); - } catch (Exception e) { - log.error("获取最近消息失败", e); - return Result.error(500, "获取最近消息失败,请稍后重试"); - } + @PostMapping(value = "/recent") + public Result> getRecentMessages(@Valid @RequestBody MessageRecentRequest request) { + PageResult pageResult = messageService.getRecentWithResponse(request); + return Result.success(pageResult); } + /** + * 更新消息 + */ + @PutMapping(value = "/update") + public Result update(@RequestParam String id, @RequestParam String content) { + MessageResponse response = messageService.updateMessage(id, content); + if (response == null) { + return Result.notFound("消息不存在"); + } + return Result.success(response); + } + /** + * 删除消息 + */ + @DeleteMapping(value = "/delete") + public Result delete(@RequestParam String id) { + boolean deleted = messageService.deleteMessage(id); + if (!deleted) { + return Result.error("删除失败"); + } + return Result.success(); + } } \ No newline at end of file diff --git a/backend-single/src/main/java/com/emotion/controller/RewardController.java b/backend-single/src/main/java/com/emotion/controller/RewardController.java index 1bda55a..5f1548c 100644 --- a/backend-single/src/main/java/com/emotion/controller/RewardController.java +++ b/backend-single/src/main/java/com/emotion/controller/RewardController.java @@ -1,20 +1,24 @@ package com.emotion.controller; -import com.baomidou.mybatisplus.core.metadata.IPage; +import com.emotion.common.PageResult; import com.emotion.common.Result; -import com.emotion.dto.request.PageRequest; -import com.emotion.dto.request.IdRequest; -import com.emotion.dto.response.BaseResponse; -import com.emotion.entity.Reward; +import com.emotion.dto.request.reward.RewardCreateRequest; +import com.emotion.dto.request.reward.RewardPageRequest; +import com.emotion.dto.request.reward.RewardUpdateRequest; +import com.emotion.dto.response.reward.RewardResponse; import com.emotion.service.RewardService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import java.time.LocalDateTime; -import java.util.List; -import java.util.stream.Collectors; +import javax.validation.Valid; +/** + * 奖励控制器 + * + * @author emotion-museum + * @date 2025-09-08 + */ @RestController @RequestMapping("/reward") public class RewardController { @@ -25,67 +29,54 @@ public class RewardController { /** * 分页查询奖励 */ - @GetMapping("/page") - public Result> getPage(@Validated PageRequest request) { - IPage page = rewardService.getPage(request); - return Result.success(page); + @GetMapping(value = "/page") + public Result> getPage(@Validated RewardPageRequest request) { + PageResult pageResult = rewardService.getPageWithResponse(request); + return Result.success(pageResult); } /** - * 根据用户ID分页查询奖励 + * 根据ID获取奖励 */ - @GetMapping("/page/user/{userId}") - public Result> getPageByUserId(@Validated PageRequest request, @PathVariable String userId) { - IPage page = rewardService.getPageByUserId(request, userId); - return Result.success(page); - } - - /** - * 根据用户ID查询奖励 - */ - @GetMapping("/user/{userId}") - public Result> getByUserId(@PathVariable String userId) { - List list = rewardService.getByUserId(userId); - return Result.success(list); + @GetMapping(value = "/detail") + public Result getById(@RequestParam String id) { + RewardResponse response = rewardService.getRewardResponseById(id); + if (response == null) { + return Result.notFound("奖励不存在"); + } + return Result.success(response); } /** * 创建奖励 */ - @PostMapping("/create") - public Result createReward(@RequestBody @Validated RewardCreateRequest request) { - Reward reward = rewardService.createReward( - request.getUserId(), - request.getRewardType(), - request.getPoints(), - request.getSource(), - request.getDescription(), - request.getExpiredTime() - ); - return Result.success(reward); + @PostMapping(value = "/create") + public Result create(@Valid @RequestBody RewardCreateRequest request) { + RewardResponse response = rewardService.createRewardWithResponse(request); + return Result.success(response); } - // 可根据RewardService接口继续补充其他接口... - - public static class RewardCreateRequest { - private String userId; - private String rewardType; - private Integer points; - private String source; - private String description; - private LocalDateTime expiredTime; - // getter/setter - public String getUserId() { return userId; } - public void setUserId(String userId) { this.userId = userId; } - public String getRewardType() { return rewardType; } - public void setRewardType(String rewardType) { this.rewardType = rewardType; } - public Integer getPoints() { return points; } - public void setPoints(Integer points) { this.points = points; } - public String getSource() { return source; } - public void setSource(String source) { this.source = source; } - public String getDescription() { return description; } - public void setDescription(String description) { this.description = description; } - public LocalDateTime getExpiredTime() { return expiredTime; } - public void setExpiredTime(LocalDateTime expiredTime) { this.expiredTime = expiredTime; } + /** + * 更新奖励 + */ + @PutMapping(value = "/update") + public Result update(@Valid @RequestBody RewardUpdateRequest request) { + RewardResponse response = rewardService.updateRewardWithResponse(request); + if (response == null) { + return Result.notFound("奖励不存在"); + } + return Result.success(response); } -} \ No newline at end of file + + /** + * 删除奖励 + */ + @DeleteMapping(value = "/delete") + public Result delete(@RequestParam String id) { + boolean deleted = rewardService.deleteReward(id); + if (!deleted) { + return Result.error("删除失败"); + } + return Result.success(); + } +} \ No newline at end of file diff --git a/backend-single/src/main/java/com/emotion/controller/TopicInteractionController.java b/backend-single/src/main/java/com/emotion/controller/TopicInteractionController.java index fb1ecf4..7ae8250 100644 --- a/backend-single/src/main/java/com/emotion/controller/TopicInteractionController.java +++ b/backend-single/src/main/java/com/emotion/controller/TopicInteractionController.java @@ -1,18 +1,26 @@ package com.emotion.controller; -import com.baomidou.mybatisplus.core.metadata.IPage; +import com.emotion.common.PageResult; import com.emotion.common.Result; -import com.emotion.dto.request.PageRequest; -import com.emotion.entity.TopicInteraction; +import com.emotion.dto.request.TopicInteractionCreateRequest; +import com.emotion.dto.request.TopicInteractionPageRequest; +import com.emotion.dto.request.TopicInteractionUpdateRequest; +import com.emotion.dto.response.TopicInteractionResponse; import com.emotion.service.TopicInteractionService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import java.util.List; +import javax.validation.Valid; +/** + * 话题互动控制器 + * + * @author emotion-museum + * @date 2025-09-08 + */ @RestController -@RequestMapping("/topic-interaction") +@RequestMapping("/topicInteraction") public class TopicInteractionController { @Autowired @@ -21,45 +29,54 @@ public class TopicInteractionController { /** * 分页查询话题互动 */ - @GetMapping("/page") - public Result> getPage(@Validated PageRequest request) { - IPage page = topicInteractionService.getPage(request); - return Result.success(page); + @GetMapping(value = "/page") + public Result> getPage(@Validated TopicInteractionPageRequest request) { + PageResult pageResult = topicInteractionService.getPageWithResponse(request); + return Result.success(pageResult); + } + + /** + * 根据ID获取话题互动 + */ + @GetMapping(value = "/detail") + public Result getById(@RequestParam String id) { + TopicInteractionResponse response = topicInteractionService.getTopicInteractionResponseById(id); + if (response == null) { + return Result.notFound("话题互动不存在"); + } + return Result.success(response); } /** * 创建话题互动 */ - @PostMapping("/create") - public Result createTopicInteraction(@RequestBody @Validated TopicInteractionCreateRequest request) { - TopicInteraction interaction = topicInteractionService.createTopicInteraction( - request.getTopicId(), - request.getUserId(), - request.getInteractionType(), - request.getContent(), - request.getAttachments() - ); - return Result.success(interaction); + @PostMapping(value = "/create") + public Result create(@Valid @RequestBody TopicInteractionCreateRequest request) { + TopicInteractionResponse response = topicInteractionService.createTopicInteractionWithResponse(request); + return Result.success(response); } - // 可根据TopicInteractionService接口继续补充其他接口... - - public static class TopicInteractionCreateRequest { - private String topicId; - private String userId; - private String interactionType; - private String content; - private String attachments; - // getter/setter - public String getTopicId() { return topicId; } - public void setTopicId(String topicId) { this.topicId = topicId; } - public String getUserId() { return userId; } - public void setUserId(String userId) { this.userId = userId; } - public String getInteractionType() { return interactionType; } - public void setInteractionType(String interactionType) { this.interactionType = interactionType; } - public String getContent() { return content; } - public void setContent(String content) { this.content = content; } - public String getAttachments() { return attachments; } - public void setAttachments(String attachments) { this.attachments = attachments; } + /** + * 更新话题互动 + */ + @PutMapping(value = "/update") + public Result update(@Valid @RequestBody TopicInteractionUpdateRequest request) { + TopicInteractionResponse response = topicInteractionService.updateTopicInteractionWithResponse(request); + if (response == null) { + return Result.notFound("话题互动不存在"); + } + return Result.success(response); } -} \ No newline at end of file + + /** + * 删除话题互动 + */ + @DeleteMapping(value = "/delete") + public Result delete(@RequestParam String id) { + boolean deleted = topicInteractionService.deleteTopicInteraction(id); + if (!deleted) { + return Result.error("删除失败"); + } + return Result.success(); + } +} \ No newline at end of file diff --git a/backend-single/src/main/java/com/emotion/controller/UserController.java b/backend-single/src/main/java/com/emotion/controller/UserController.java index a564a70..c3fbbbc 100644 --- a/backend-single/src/main/java/com/emotion/controller/UserController.java +++ b/backend-single/src/main/java/com/emotion/controller/UserController.java @@ -1,27 +1,18 @@ package com.emotion.controller; -import com.baomidou.mybatisplus.core.metadata.IPage; -import com.emotion.common.BasePageRequest; import com.emotion.common.PageResult; import com.emotion.common.Result; import com.emotion.dto.request.UserCreateRequest; -import com.emotion.dto.request.UserUpdateRequest; +import com.emotion.dto.request.UserPageRequest; import com.emotion.dto.request.UserProfileUpdateRequest; +import com.emotion.dto.request.UserUpdateRequest; import com.emotion.dto.response.UserResponse; -import com.emotion.entity.User; import com.emotion.service.UserService; -import com.emotion.util.UserContextHolder; -import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import javax.servlet.http.HttpServletRequest; - import javax.validation.Valid; -import java.time.format.DateTimeFormatter; -import java.util.List; -import java.util.stream.Collectors; /** * 用户控制器 @@ -36,183 +27,81 @@ public class UserController { @Autowired private UserService userService; - private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); - /** * 分页查询用户 */ - @GetMapping("/page") - public Result> getPage(@Validated BasePageRequest request) { - IPage page = userService.getPage(request); - List userResponses = page.getRecords().stream() - .map(this::convertToResponse) - .collect(Collectors.toList()); - - PageResult pageResult = new PageResult<>(); - pageResult.setCurrent(page.getCurrent()); - pageResult.setSize(page.getSize()); - pageResult.setTotal(page.getTotal()); - pageResult.setPages(page.getPages()); - pageResult.setRecords(userResponses); - + @GetMapping(value = "/page") + public Result> getPage(@Validated UserPageRequest request) { + PageResult pageResult = userService.getPageWithResponse(request); return Result.success(pageResult); } /** * 根据ID获取用户信息 */ - @GetMapping("/{id}") - public Result getById(@PathVariable String id) { - User user = userService.getById(id); + @GetMapping(value = "/detail") + public Result getById(@RequestParam String id) { + UserResponse user = userService.getUserResponseById(id); if (user == null) { return Result.notFound("用户不存在"); } - return Result.success(convertToResponse(user)); + return Result.success(user); } /** * 创建用户 */ - @PostMapping + @PostMapping(value = "/create") public Result create(@Valid @RequestBody UserCreateRequest request) { - User user = userService.createUser( - request.getAccount(), - request.getUsername(), - request.getPassword(), - request.getEmail(), - request.getPhone() - ); - return Result.success(convertToResponse(user)); + UserResponse user = userService.createUserWithResponse(request); + return Result.success(user); } /** * 更新用户 */ - @PutMapping("/{id}") - public Result update(@PathVariable String id, @Valid @RequestBody UserUpdateRequest request) { - User user = new User(); - BeanUtils.copyProperties(request, user); - user.setId(id); - - boolean updated = userService.updateById(user); - if (!updated) { + @PutMapping(value = "/update") + public Result update(@Valid @RequestBody UserUpdateRequest request) { + UserResponse updatedUser = userService.updateUserWithResponse(request); + if (updatedUser == null) { return Result.error("更新失败"); } - - User updatedUser = userService.getById(id); - return Result.success(convertToResponse(updatedUser)); + return Result.success(updatedUser); } /** * 删除用户 */ - @DeleteMapping("/{id}") - public Result delete(@PathVariable String id) { - boolean deleted = userService.removeById(id); + @DeleteMapping(value = "/delete") + public Result delete(@RequestParam String id) { + boolean deleted = userService.deleteUser(id); if (!deleted) { return Result.error("删除失败"); } return Result.success(); } - /** - * 根据账号查询用户 - */ - @GetMapping("/account/{account}") - public Result getByAccount(@PathVariable String account) { - User user = userService.getByAccount(account); - if (user == null) { - return Result.notFound("用户不存在"); - } - return Result.success(convertToResponse(user)); - } - - /** - * 统计用户数量 - */ - @GetMapping("/count/status/{status}") - public Result countByStatus(@PathVariable Integer status) { - Long count = userService.countByStatus(status); - return Result.success(count); - } - /** * 获取当前用户个人资料 */ - @GetMapping("/profile") - public Result getCurrentUserProfile(HttpServletRequest request) { - String currentUserId = getCurrentUserId(request); - if (currentUserId == null) { + @GetMapping(value = "/profile") + public Result getCurrentUserProfile() { + UserResponse user = userService.getCurrentUserProfileWithResponse(); + if (user == null) { return Result.unauthorized("用户未登录"); } - - User user = userService.getById(currentUserId); - if (user == null) { - return Result.notFound("用户不存在"); - } - return Result.success(convertToResponse(user)); + return Result.success(user); } /** * 更新当前用户个人资料 */ - @PutMapping("/profile") - public Result updateCurrentUserProfile(@Valid @RequestBody UserProfileUpdateRequest request, - HttpServletRequest httpRequest) { - String currentUserId = getCurrentUserId(httpRequest); - if (currentUserId == null) { + @PutMapping(value = "/profile") + public Result updateCurrentUserProfile(@Valid @RequestBody UserProfileUpdateRequest request) { + UserResponse updatedUser = userService.updateCurrentUserProfileWithResponse(request); + if (updatedUser == null) { return Result.unauthorized("用户未登录"); } - - User user = new User(); - BeanUtils.copyProperties(request, user); - user.setId(currentUserId); - - boolean updated = userService.updateById(user); - if (!updated) { - return Result.error("更新失败"); - } - - User updatedUser = userService.getById(currentUserId); - return Result.success(convertToResponse(updatedUser)); - } - - /** - * 获取当前用户ID - * 从JWT拦截器设置的请求属性中获取用户ID - */ - private String getCurrentUserId(HttpServletRequest request) { - // 优先从UserContextHolder获取(线程本地存储) - String userId = UserContextHolder.getCurrentUserId(); - if (userId != null) { - return userId; - } - - // 如果UserContextHolder中没有,从请求属性中获取(兼容性) - Object userIdAttr = request.getAttribute("userId"); - if (userIdAttr != null) { - return userIdAttr.toString(); - } - - return null; - } - - /** - * 转换为响应对象 - */ - private UserResponse convertToResponse(User user) { - UserResponse response = new UserResponse(); - BeanUtils.copyProperties(user, response); - response.setId(user.getId()); - if (user.getCreateTime() != null) { - response.setCreateTime(user.getCreateTime().format(DATE_TIME_FORMATTER)); - } - if (user.getUpdateTime() != null) { - response.setUpdateTime(user.getUpdateTime().format(DATE_TIME_FORMATTER)); - } - if (user.getLastActiveTime() != null) { - response.setLastActiveTime(user.getLastActiveTime().format(DATE_TIME_FORMATTER)); - } - return response; + return Result.success(updatedUser); } } \ No newline at end of file diff --git a/backend-single/src/main/java/com/emotion/controller/UserStatsController.java b/backend-single/src/main/java/com/emotion/controller/UserStatsController.java index b095176..4423272 100644 --- a/backend-single/src/main/java/com/emotion/controller/UserStatsController.java +++ b/backend-single/src/main/java/com/emotion/controller/UserStatsController.java @@ -1,22 +1,20 @@ package com.emotion.controller; -import com.baomidou.mybatisplus.core.metadata.IPage; import com.emotion.common.PageResult; import com.emotion.common.Result; -import com.emotion.dto.request.PageRequest; -import com.emotion.dto.response.BaseResponse; -import com.emotion.entity.UserStats; +import com.emotion.dto.request.UserStatsCreateRequest; +import com.emotion.dto.request.UserStatsIncrementRequest; +import com.emotion.dto.request.UserStatsPageRequest; +import com.emotion.dto.request.UserStatsUpdateValueRequest; +import com.emotion.dto.response.UserStatsResponse; import com.emotion.service.UserStatsService; -import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import javax.validation.constraints.NotBlank; +import javax.validation.Valid; import javax.validation.constraints.NotNull; -import java.time.format.DateTimeFormatter; import java.util.List; -import java.util.stream.Collectors; /** * 用户统计控制器 @@ -25,123 +23,37 @@ import java.util.stream.Collectors; * @date 2025-07-23 */ @RestController -@RequestMapping("/user-stats") +@RequestMapping("/userStats") +@Validated public class UserStatsController { @Autowired private UserStatsService userStatsService; - private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); - /** * 分页查询用户统计 */ - @GetMapping("/page") - public Result> getPage(@Validated PageRequest request) { - IPage page = userStatsService.getPage(request); - List responses = page.getRecords().stream() - .map(this::convertToResponse) - .collect(Collectors.toList()); - - PageResult pageResult = new PageResult<>(); - pageResult.setCurrent(page.getCurrent()); - pageResult.setSize(page.getSize()); - pageResult.setTotal(page.getTotal()); - pageResult.setPages(page.getPages()); - pageResult.setRecords(responses); - + @GetMapping(value = "/page") + public Result> getPage(@Validated UserStatsPageRequest request) { + PageResult pageResult = userStatsService.getPageWithResponse(request); return Result.success(pageResult); } - /** - * 根据用户ID获取统计信息 - */ - @GetMapping("/user/{userId}") - public Result getByUserId(@PathVariable String userId) { - UserStats stats = userStatsService.getByUserId(userId); - if (stats == null) { - return Result.notFound("用户统计不存在"); - } - return Result.success(convertToResponse(stats)); - } - - /** - * 根据用户ID和统计类型获取统计信息 - */ - @GetMapping("/user/{userId}/type/{statsType}") - public Result getByUserIdAndStatsType(@PathVariable String userId, @PathVariable String statsType) { - UserStats stats = userStatsService.getByUserIdAndStatsType(userId, statsType); - if (stats == null) { - return Result.notFound("用户统计不存在"); - } - return Result.success(convertToResponse(stats)); - } - - /** - * 根据统计类型查询统计信息 - */ - @GetMapping("/type/{statsType}") - public Result> getByStatsType(@PathVariable String statsType) { - List statsList = userStatsService.getByStatsType(statsType); - List responses = statsList.stream() - .map(this::convertToResponse) - .collect(Collectors.toList()); - return Result.success(responses); - } - - /** - * 查询用户的所有统计类型 - */ - @GetMapping("/user/{userId}/all") - public Result> getAllStatsByUserId(@PathVariable String userId) { - List statsList = userStatsService.getAllStatsByUserId(userId); - List responses = statsList.stream() - .map(this::convertToResponse) - .collect(Collectors.toList()); - return Result.success(responses); - } - - /** - * 查询排名前N的用户统计 - */ - @GetMapping("/type/{statsType}/top") - public Result> getTopUsersByStatsType(@PathVariable String statsType, @RequestParam(defaultValue = "10") Integer limit) { - List statsList = userStatsService.getTopUsersByStatsType(statsType, limit); - List responses = statsList.stream() - .map(this::convertToResponse) - .collect(Collectors.toList()); - return Result.success(responses); - } - - /** - * 查询用户在指定统计类型中的排名 - */ - @GetMapping("/user/{userId}/type/{statsType}/rank") - public Result getUserRankByStatsType(@PathVariable String userId, @PathVariable String statsType) { - Long rank = userStatsService.getUserRankByStatsType(userId, statsType); - return Result.success(rank); - } - /** * 创建或更新用户统计 */ - @PostMapping - public Result createOrUpdate(@RequestBody @Validated UserStatsCreateRequest request) { - UserStats stats = userStatsService.createOrUpdateUserStats( - request.getUserId(), - request.getStatsType(), - request.getValue(), - request.getPeriod() - ); - return Result.success(convertToResponse(stats)); + @PostMapping(value = "/createOrUpdate") + public Result createOrUpdate(@Valid @RequestBody UserStatsCreateRequest request) { + UserStatsResponse stats = userStatsService.createOrUpdateUserStatsWithResponse(request); + return Result.success(stats); } /** * 更新用户统计值 */ - @PutMapping("/user/{userId}/type/{statsType}") - public Result updateStatsValue(@PathVariable String userId, @PathVariable String statsType, @RequestParam Double value) { - boolean updated = userStatsService.updateStatsValue(userId, statsType, value); + @PutMapping(value = "/updateStatsValue") + public Result updateStatsValue(@Valid @RequestBody UserStatsUpdateValueRequest request) { + boolean updated = userStatsService.updateStatsValue(request); if (!updated) { return Result.error("更新失败"); } @@ -151,9 +63,9 @@ public class UserStatsController { /** * 增加用户统计值 */ - @PutMapping("/user/{userId}/type/{statsType}/increment") - public Result incrementStatsValue(@PathVariable String userId, @PathVariable String statsType, @RequestParam Double increment) { - boolean updated = userStatsService.incrementStatsValue(userId, statsType, increment); + @PutMapping(value = "/incrementStatsValue") + public Result incrementStatsValue(@Valid @RequestBody UserStatsIncrementRequest request) { + boolean updated = userStatsService.incrementStatsValue(request); if (!updated) { return Result.error("增加失败"); } @@ -163,8 +75,8 @@ public class UserStatsController { /** * 重新计算用户统计 */ - @PutMapping("/user/{userId}/recalculate") - public Result recalculateUserStats(@PathVariable String userId) { + @PutMapping(value = "/recalculateUserStats") + public Result recalculateUserStats(@RequestParam String userId) { boolean recalculated = userStatsService.recalculateUserStats(userId); if (!recalculated) { return Result.error("重新计算失败"); @@ -175,7 +87,7 @@ public class UserStatsController { /** * 重新计算所有用户统计 */ - @PutMapping("/recalculate-all") + @PutMapping(value = "/recalculateAll") public Result recalculateAllUserStats() { boolean recalculated = userStatsService.recalculateAllUserStats(); if (!recalculated) { @@ -184,37 +96,10 @@ public class UserStatsController { return Result.success(); } - /** - * 查询平均统计值 - */ - @GetMapping("/type/{statsType}/avg") - public Result getAvgValueByStatsType(@PathVariable String statsType) { - Double avgValue = userStatsService.getAvgValueByStatsType(statsType); - return Result.success(avgValue); - } - - /** - * 查询最大统计值 - */ - @GetMapping("/type/{statsType}/max") - public Result getMaxValueByStatsType(@PathVariable String statsType) { - Double maxValue = userStatsService.getMaxValueByStatsType(statsType); - return Result.success(maxValue); - } - - /** - * 查询最小统计值 - */ - @GetMapping("/type/{statsType}/min") - public Result getMinValueByStatsType(@PathVariable String statsType) { - Double minValue = userStatsService.getMinValueByStatsType(statsType); - return Result.success(minValue); - } - /** * 删除过期的统计数据 */ - @DeleteMapping("/expired") + @DeleteMapping(value = "/deleteExpired") public Result deleteExpiredStats(@RequestParam(defaultValue = "30") Integer days) { boolean deleted = userStatsService.deleteExpiredStats(days); if (!deleted) { @@ -222,49 +107,4 @@ public class UserStatsController { } return Result.success(); } - - /** - * 转换为响应对象 - */ - private UserStatsResponse convertToResponse(UserStats stats) { - UserStatsResponse response = new UserStatsResponse(); - BeanUtils.copyProperties(stats, response); - response.setId(stats.getId()); - if (stats.getCreateTime() != null) { - response.setCreateTime(stats.getCreateTime().format(DATE_TIME_FORMATTER)); - } - if (stats.getUpdateTime() != null) { - response.setUpdateTime(stats.getUpdateTime().format(DATE_TIME_FORMATTER)); - } - return response; - } - - /** - * 用户统计创建请求 - */ - @lombok.Data - public static class UserStatsCreateRequest { - @NotBlank(message = "用户ID不能为空") - private String userId; - - @NotBlank(message = "统计类型不能为空") - private String statsType; - - @NotNull(message = "统计值不能为空") - private Double value; - - private String period; - } - - /** - * 用户统计响应类 - */ - @lombok.Data - @lombok.EqualsAndHashCode(callSuper = true) - public static class UserStatsResponse extends BaseResponse { - private String userId; - private String statsType; - private Double value; - private String period; - } -} +} \ No newline at end of file diff --git a/backend-single/src/main/java/com/emotion/controller/WebSocketController.java b/backend-single/src/main/java/com/emotion/controller/WebSocketController.java deleted file mode 100644 index c1aabc3..0000000 --- a/backend-single/src/main/java/com/emotion/controller/WebSocketController.java +++ /dev/null @@ -1,114 +0,0 @@ -package com.emotion.controller; - -import com.emotion.service.AiChatService; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.messaging.handler.annotation.MessageMapping; -import org.springframework.messaging.handler.annotation.Payload; -import org.springframework.messaging.simp.SimpMessageHeaderAccessor; -import org.springframework.messaging.simp.SimpMessagingTemplate; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.ResponseBody; - -import java.util.HashMap; -import java.util.Map; - -/** - * WebSocket控制器 - * - * @author emotion-museum - * @date 2025-07-22 - */ -@Controller -public class WebSocketController { - - private static final Logger log = LoggerFactory.getLogger(WebSocketController.class); - - @Autowired - private SimpMessagingTemplate messagingTemplate; - - @Autowired - private AiChatService aiChatService; - - // 已移除旧的WebSocket消息处理方法,使用新的ChatWebSocketController - - // 已移除旧的用户连接处理方法,使用新的ChatWebSocketController - - /** - * 处理AI聊天消息 - */ - @MessageMapping("/chat.ai") - public void handleAiChat(@Payload Map chatMessage, - SimpMessageHeaderAccessor headerAccessor) { - log.info("收到AI聊天消息: {}", chatMessage); - - try { - String content = (String) chatMessage.get("content"); - String conversationId = (String) chatMessage.get("conversationId"); - String userId = (String) chatMessage.get("userId"); - - // 调用AI服务 - String aiReply = aiChatService.sendMessage(conversationId, content, userId); - - // 构建AI回复消息 - Map aiResponse = new HashMap<>(); - aiResponse.put("content", aiReply); - aiResponse.put("sender", "AI助手"); - aiResponse.put("type", "AI_REPLY"); - aiResponse.put("conversationId", conversationId); - aiResponse.put("timestamp", System.currentTimeMillis()); - - // 发送给特定用户 - if (userId != null) { - messagingTemplate.convertAndSendToUser(userId, "/queue/messages", aiResponse); - } else { - // 发送到公共频道 - messagingTemplate.convertAndSend("/topic/conversation/" + conversationId, aiResponse); - } - - } catch (Exception e) { - log.error("处理AI聊天失败", e); - - Map errorResponse = new HashMap<>(); - errorResponse.put("content", "AI服务暂时不可用,请稍后再试"); - errorResponse.put("sender", "System"); - errorResponse.put("type", "ERROR"); - errorResponse.put("timestamp", System.currentTimeMillis()); - - String userId = (String) chatMessage.get("userId"); - if (userId != null) { - messagingTemplate.convertAndSendToUser(userId, "/queue/messages", errorResponse); - } - } - } - - /** - * 发送系统消息 - */ - public void sendSystemMessage(String destination, String message) { - Map systemMessage = new HashMap<>(); - systemMessage.put("content", message); - systemMessage.put("sender", "System"); - systemMessage.put("type", "SYSTEM"); - systemMessage.put("timestamp", System.currentTimeMillis()); - - messagingTemplate.convertAndSend(destination, systemMessage); - } - - /** - * WebSocket状态监控接口 - */ - @GetMapping("/api/ws/status") - @ResponseBody - public Map getWebSocketStatus() { - Map status = new HashMap<>(); - status.put("status", "active"); - status.put("timestamp", System.currentTimeMillis()); - status.put("endpoint", "/ws/chat"); - status.put("protocols", new String[]{"websocket", "sockjs"}); - status.put("message", "WebSocket服务正常运行"); - return status; - } -} diff --git a/backend-single/src/main/java/com/emotion/dto/request/EmotionRecordCreateRequest.java b/backend-single/src/main/java/com/emotion/dto/request/EmotionRecordCreateRequest.java index 68c1264..bb59eda 100644 --- a/backend-single/src/main/java/com/emotion/dto/request/EmotionRecordCreateRequest.java +++ b/backend-single/src/main/java/com/emotion/dto/request/EmotionRecordCreateRequest.java @@ -4,6 +4,7 @@ import lombok.Data; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; import java.math.BigDecimal; import java.time.LocalDate; import java.util.List; @@ -21,6 +22,7 @@ public class EmotionRecordCreateRequest { * 用户ID */ @NotBlank(message = "用户ID不能为空") + @Size(max = 32, message = "用户ID长度不能超过32个字符") private String userId; /** @@ -33,6 +35,7 @@ public class EmotionRecordCreateRequest { * 情绪类型 */ @NotBlank(message = "情绪类型不能为空") + @Size(max = 32, message = "情绪类型长度不能超过32个字符") private String emotionType; /** @@ -44,11 +47,13 @@ public class EmotionRecordCreateRequest { /** * 触发因素 */ + @Size(max = 768, message = "触发因素长度不能超过768个字符") private String triggers; /** * 描述 */ + @Size(max = 768, message = "描述长度不能超过768个字符") private String description; /** @@ -59,25 +64,30 @@ public class EmotionRecordCreateRequest { /** * 天气 */ + @Size(max = 64, message = "天气长度不能超过64个字符") private String weather; /** * 地点 */ + @Size(max = 128, message = "地点长度不能超过128个字符") private String location; /** * 活动 */ + @Size(max = 128, message = "活动长度不能超过128个字符") private String activity; /** * 相关人物 */ + @Size(max = 256, message = "相关人物长度不能超过256个字符") private String people; /** * 备注 */ + @Size(max = 1024, message = "备注长度不能超过1024个字符") private String notes; } \ No newline at end of file diff --git a/backend-single/src/main/java/com/emotion/dto/request/EmotionRecordPageRequest.java b/backend-single/src/main/java/com/emotion/dto/request/EmotionRecordPageRequest.java index eaa622e..63f9bf1 100644 --- a/backend-single/src/main/java/com/emotion/dto/request/EmotionRecordPageRequest.java +++ b/backend-single/src/main/java/com/emotion/dto/request/EmotionRecordPageRequest.java @@ -4,6 +4,8 @@ import com.emotion.common.BasePageRequest; import lombok.Data; import lombok.EqualsAndHashCode; +import javax.validation.constraints.Size; + /** * 情绪记录分页请求类 * @@ -17,15 +19,18 @@ public class EmotionRecordPageRequest extends BasePageRequest { /** * 用户ID(可选) */ + @Size(max = 32, message = "用户ID长度不能超过32个字符") private String userId; /** * 情绪类型(可选) */ + @Size(max = 32, message = "情绪类型长度不能超过32个字符") private String emotionType; /** * 地点(可选) */ + @Size(max = 128, message = "地点长度不能超过128个字符") private String location; } \ No newline at end of file diff --git a/backend-single/src/main/java/com/emotion/dto/request/EmotionRecordUpdateRequest.java b/backend-single/src/main/java/com/emotion/dto/request/EmotionRecordUpdateRequest.java index 97c632e..43287ed 100644 --- a/backend-single/src/main/java/com/emotion/dto/request/EmotionRecordUpdateRequest.java +++ b/backend-single/src/main/java/com/emotion/dto/request/EmotionRecordUpdateRequest.java @@ -3,6 +3,7 @@ package com.emotion.dto.request; import lombok.Data; import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; import java.math.BigDecimal; import java.time.LocalDate; import java.util.List; @@ -20,6 +21,7 @@ public class EmotionRecordUpdateRequest { * 情绪记录ID */ @NotBlank(message = "情绪记录ID不能为空") + @Size(max = 32, message = "情绪记录ID长度不能超过32个字符") private String id; /** @@ -30,6 +32,7 @@ public class EmotionRecordUpdateRequest { /** * 情绪类型 */ + @Size(max = 32, message = "情绪类型长度不能超过32个字符") private String emotionType; /** @@ -40,11 +43,13 @@ public class EmotionRecordUpdateRequest { /** * 触发因素 */ + @Size(max = 768, message = "触发因素长度不能超过768个字符") private String triggers; /** * 描述 */ + @Size(max = 768, message = "描述长度不能超过768个字符") private String description; /** @@ -55,25 +60,30 @@ public class EmotionRecordUpdateRequest { /** * 天气 */ + @Size(max = 64, message = "天气长度不能超过64个字符") private String weather; /** * 地点 */ + @Size(max = 128, message = "地点长度不能超过128个字符") private String location; /** * 活动 */ + @Size(max = 128, message = "活动长度不能超过128个字符") private String activity; /** * 相关人物 */ + @Size(max = 256, message = "相关人物长度不能超过256个字符") private String people; /** * 备注 */ + @Size(max = 1024, message = "备注长度不能超过1024个字符") private String notes; } \ No newline at end of file diff --git a/backend-single/src/main/java/com/emotion/dto/request/EmotionSummaryGenerateRequest.java b/backend-single/src/main/java/com/emotion/dto/request/EmotionSummaryGenerateRequest.java new file mode 100644 index 0000000..ea86880 --- /dev/null +++ b/backend-single/src/main/java/com/emotion/dto/request/EmotionSummaryGenerateRequest.java @@ -0,0 +1,14 @@ +package com.emotion.dto.request; + +import lombok.Data; + +/** + * 情绪总结生成请求类 + * + * @author emotion-museum + * @date 2025-09-08 + */ +@Data +public class EmotionSummaryGenerateRequest { + // 目前情绪总结生成不需要额外参数 +} \ No newline at end of file diff --git a/backend-single/src/main/java/com/emotion/dto/request/EmotionSummaryStatusRequest.java b/backend-single/src/main/java/com/emotion/dto/request/EmotionSummaryStatusRequest.java new file mode 100644 index 0000000..14a90ee --- /dev/null +++ b/backend-single/src/main/java/com/emotion/dto/request/EmotionSummaryStatusRequest.java @@ -0,0 +1,14 @@ +package com.emotion.dto.request; + +import lombok.Data; + +/** + * 情绪总结状态请求类 + * + * @author emotion-museum + * @date 2025-09-08 + */ +@Data +public class EmotionSummaryStatusRequest { + // 目前情绪总结状态查询不需要额外参数 +} \ No newline at end of file diff --git a/backend-single/src/main/java/com/emotion/dto/request/TopicInteractionCreateRequest.java b/backend-single/src/main/java/com/emotion/dto/request/TopicInteractionCreateRequest.java new file mode 100644 index 0000000..5e3c9f8 --- /dev/null +++ b/backend-single/src/main/java/com/emotion/dto/request/TopicInteractionCreateRequest.java @@ -0,0 +1,65 @@ +package com.emotion.dto.request; + +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; + +/** + * 话题互动创建请求 + * + * @author emotion-museum + * @date 2025-09-08 + */ +@Data +public class TopicInteractionCreateRequest { + + /** + * 话题ID + */ + @NotBlank(message = "话题ID不能为空") + @Size(max = 50, message = "话题ID长度不能超过50个字符") + private String topicId; + + /** + * 互动类型 + */ + @NotBlank(message = "互动类型不能为空") + @Size(max = 50, message = "互动类型长度不能超过50个字符") + private String interactionType; + + /** + * 内容 + */ + @Size(max = 1000, message = "内容长度不能超过1000个字符") + private String content; + + /** + * 用户输入 + */ + @Size(max = 1000, message = "用户输入长度不能超过1000个字符") + private String userInput; + + /** + * AI回应 + */ + @Size(max = 1000, message = "AI回应长度不能超过1000个字符") + private String aiResponse; + + /** + * 附件 + */ + @Size(max = 500, message = "附件长度不能超过500个字符") + private String attachments; + + /** + * 评分 + */ + private Integer rating; + + /** + * 反馈 + */ + @Size(max = 500, message = "反馈长度不能超过500个字符") + private String feedback; +} \ No newline at end of file diff --git a/backend-single/src/main/java/com/emotion/dto/request/TopicInteractionPageRequest.java b/backend-single/src/main/java/com/emotion/dto/request/TopicInteractionPageRequest.java new file mode 100644 index 0000000..ecac747 --- /dev/null +++ b/backend-single/src/main/java/com/emotion/dto/request/TopicInteractionPageRequest.java @@ -0,0 +1,36 @@ +package com.emotion.dto.request; + +import com.emotion.common.BasePageRequest; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import javax.validation.constraints.Size; + +/** + * 话题互动分页查询请求 + * + * @author emotion-museum + * @date 2025-09-08 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class TopicInteractionPageRequest extends BasePageRequest { + + /** + * 话题ID + */ + @Size(max = 50, message = "话题ID长度不能超过50个字符") + private String topicId; + + /** + * 用户ID + */ + @Size(max = 50, message = "用户ID长度不能超过50个字符") + private String userId; + + /** + * 互动类型 + */ + @Size(max = 50, message = "互动类型长度不能超过50个字符") + private String interactionType; +} \ No newline at end of file diff --git a/backend-single/src/main/java/com/emotion/dto/request/TopicInteractionUpdateRequest.java b/backend-single/src/main/java/com/emotion/dto/request/TopicInteractionUpdateRequest.java new file mode 100644 index 0000000..ca24f90 --- /dev/null +++ b/backend-single/src/main/java/com/emotion/dto/request/TopicInteractionUpdateRequest.java @@ -0,0 +1,70 @@ +package com.emotion.dto.request; + +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; + +/** + * 话题互动更新请求 + * + * @author emotion-museum + * @date 2025-09-08 + */ +@Data +public class TopicInteractionUpdateRequest { + + /** + * ID + */ + @NotBlank(message = "ID不能为空") + @Size(max = 50, message = "ID长度不能超过50个字符") + private String id; + + /** + * 话题ID + */ + @Size(max = 50, message = "话题ID长度不能超过50个字符") + private String topicId; + + /** + * 互动类型 + */ + @Size(max = 50, message = "互动类型长度不能超过50个字符") + private String interactionType; + + /** + * 内容 + */ + @Size(max = 1000, message = "内容长度不能超过1000个字符") + private String content; + + /** + * 用户输入 + */ + @Size(max = 1000, message = "用户输入长度不能超过1000个字符") + private String userInput; + + /** + * AI回应 + */ + @Size(max = 1000, message = "AI回应长度不能超过1000个字符") + private String aiResponse; + + /** + * 附件 + */ + @Size(max = 500, message = "附件长度不能超过500个字符") + private String attachments; + + /** + * 评分 + */ + private Integer rating; + + /** + * 反馈 + */ + @Size(max = 500, message = "反馈长度不能超过500个字符") + private String feedback; +} \ No newline at end of file diff --git a/backend-single/src/main/java/com/emotion/dto/request/UserPageRequest.java b/backend-single/src/main/java/com/emotion/dto/request/UserPageRequest.java new file mode 100644 index 0000000..fbef011 --- /dev/null +++ b/backend-single/src/main/java/com/emotion/dto/request/UserPageRequest.java @@ -0,0 +1,53 @@ +package com.emotion.dto.request; + +import com.emotion.common.BasePageRequest; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import javax.validation.constraints.Size; + +/** + * 用户分页查询请求 + * + * @author emotion-museum + * @date 2025-09-08 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class UserPageRequest extends BasePageRequest { + + /** + * 账号 + */ + @Size(max = 20, message = "账号长度不能超过20个字符") + private String account; + + /** + * 用户名 + */ + @Size(max = 20, message = "用户名长度不能超过20个字符") + private String username; + + /** + * 邮箱 + */ + @Size(max = 100, message = "邮箱长度不能超过100个字符") + private String email; + + /** + * 手机号 + */ + @Size(max = 20, message = "手机号长度不能超过20个字符") + private String phone; + + /** + * 状态 + */ + private Integer status; + + /** + * 会员等级 + */ + @Size(max = 20, message = "会员等级长度不能超过20个字符") + private String memberLevel; +} \ No newline at end of file diff --git a/backend-single/src/main/java/com/emotion/dto/request/UserStatsCreateRequest.java b/backend-single/src/main/java/com/emotion/dto/request/UserStatsCreateRequest.java new file mode 100644 index 0000000..a7bd309 --- /dev/null +++ b/backend-single/src/main/java/com/emotion/dto/request/UserStatsCreateRequest.java @@ -0,0 +1,39 @@ +package com.emotion.dto.request; + +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +/** + * 用户统计创建请求 + * + * @author emotion-museum + * @date 2025-09-09 + */ +@Data +public class UserStatsCreateRequest extends BaseRequest { + + /** + * 用户ID + */ + @NotBlank(message = "用户ID不能为空") + private String userId; + + /** + * 统计类型 + */ + @NotBlank(message = "统计类型不能为空") + private String statsType; + + /** + * 统计值 + */ + @NotNull(message = "统计值不能为空") + private Double value; + + /** + * 周期 + */ + private String period; +} \ No newline at end of file diff --git a/backend-single/src/main/java/com/emotion/dto/request/UserStatsIncrementRequest.java b/backend-single/src/main/java/com/emotion/dto/request/UserStatsIncrementRequest.java new file mode 100644 index 0000000..9b7abf6 --- /dev/null +++ b/backend-single/src/main/java/com/emotion/dto/request/UserStatsIncrementRequest.java @@ -0,0 +1,34 @@ +package com.emotion.dto.request; + +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +/** + * 用户统计值增加请求 + * + * @author emotion-museum + * @date 2025-09-09 + */ +@Data +public class UserStatsIncrementRequest extends BaseRequest { + + /** + * 用户ID + */ + @NotBlank(message = "用户ID不能为空") + private String userId; + + /** + * 统计类型 + */ + @NotBlank(message = "统计类型不能为空") + private String statsType; + + /** + * 增加值 + */ + @NotNull(message = "增加值不能为空") + private Double increment; +} \ No newline at end of file diff --git a/backend-single/src/main/java/com/emotion/dto/request/UserStatsPageRequest.java b/backend-single/src/main/java/com/emotion/dto/request/UserStatsPageRequest.java new file mode 100644 index 0000000..85ea7bc --- /dev/null +++ b/backend-single/src/main/java/com/emotion/dto/request/UserStatsPageRequest.java @@ -0,0 +1,26 @@ +package com.emotion.dto.request; + +import com.emotion.common.BasePageRequest; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 用户统计分页查询请求 + * + * @author emotion-museum + * @date 2025-09-09 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class UserStatsPageRequest extends BasePageRequest { + + /** + * 用户ID + */ + private String userId; + + /** + * 统计类型 + */ + private String statsType; +} \ No newline at end of file diff --git a/backend-single/src/main/java/com/emotion/dto/request/UserStatsUpdateValueRequest.java b/backend-single/src/main/java/com/emotion/dto/request/UserStatsUpdateValueRequest.java new file mode 100644 index 0000000..b2381aa --- /dev/null +++ b/backend-single/src/main/java/com/emotion/dto/request/UserStatsUpdateValueRequest.java @@ -0,0 +1,34 @@ +package com.emotion.dto.request; + +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +/** + * 用户统计值更新请求 + * + * @author emotion-museum + * @date 2025-09-09 + */ +@Data +public class UserStatsUpdateValueRequest extends BaseRequest { + + /** + * 用户ID + */ + @NotBlank(message = "用户ID不能为空") + private String userId; + + /** + * 统计类型 + */ + @NotBlank(message = "统计类型不能为空") + private String statsType; + + /** + * 统计值 + */ + @NotNull(message = "统计值不能为空") + private Double value; +} \ No newline at end of file diff --git a/backend-single/src/main/java/com/emotion/dto/request/UserUpdateRequest.java b/backend-single/src/main/java/com/emotion/dto/request/UserUpdateRequest.java index e06b9db..50142ba 100644 --- a/backend-single/src/main/java/com/emotion/dto/request/UserUpdateRequest.java +++ b/backend-single/src/main/java/com/emotion/dto/request/UserUpdateRequest.java @@ -1,9 +1,9 @@ package com.emotion.dto.request; import lombok.Data; -import lombok.EqualsAndHashCode; import javax.validation.constraints.Email; +import javax.validation.constraints.NotBlank; import javax.validation.constraints.Pattern; import javax.validation.constraints.Size; import java.time.LocalDate; @@ -12,11 +12,16 @@ import java.time.LocalDate; * 用户更新请求类 * * @author emotion-museum - * @date 2025-07-24 + * @date 2025-09-08 */ @Data -@EqualsAndHashCode(callSuper = true) -public class UserUpdateRequest extends BaseRequest { +public class UserUpdateRequest { + + /** + * ID + */ + @NotBlank(message = "ID不能为空") + private String id; /** * 用户名 @@ -70,4 +75,10 @@ public class UserUpdateRequest extends BaseRequest { * 状态 */ private Integer status; + + /** + * 会员等级 + */ + @Size(max = 20, message = "会员等级长度不能超过20个字符") + private String memberLevel; } \ No newline at end of file diff --git a/backend-single/src/main/java/com/emotion/dto/request/growth/GrowthTopicCreateRequest.java b/backend-single/src/main/java/com/emotion/dto/request/growth/GrowthTopicCreateRequest.java new file mode 100644 index 0000000..b446c23 --- /dev/null +++ b/backend-single/src/main/java/com/emotion/dto/request/growth/GrowthTopicCreateRequest.java @@ -0,0 +1,55 @@ +package com.emotion.dto.request.growth; + +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; +import java.time.LocalDateTime; + +/** + * 成长话题创建请求 + * + * @author emotion-museum + * @date 2025-09-08 + */ +@Data +public class GrowthTopicCreateRequest { + + /** + * 课题标题 + */ + @NotBlank(message = "标题不能为空") + @Size(max = 100, message = "标题长度不能超过100个字符") + private String title; + + /** + * 描述 + */ + @Size(max = 500, message = "描述长度不能超过500个字符") + private String description; + + /** + * 分类 + */ + @NotBlank(message = "分类不能为空") + @Size(max = 50, message = "分类长度不能超过50个字符") + private String category; + + /** + * 难度等级 + */ + @NotBlank(message = "难度等级不能为空") + @Size(max = 20, message = "难度等级长度不能超过20个字符") + private String difficultyLevel; + + /** + * 标签 + */ + @Size(max = 200, message = "标签长度不能超过200个字符") + private String tags; + + /** + * 结束时间 + */ + private LocalDateTime endTime; +} \ No newline at end of file diff --git a/backend-single/src/main/java/com/emotion/dto/request/growth/GrowthTopicPageRequest.java b/backend-single/src/main/java/com/emotion/dto/request/growth/GrowthTopicPageRequest.java new file mode 100644 index 0000000..c16a75f --- /dev/null +++ b/backend-single/src/main/java/com/emotion/dto/request/growth/GrowthTopicPageRequest.java @@ -0,0 +1,34 @@ +package com.emotion.dto.request.growth; + +import com.emotion.common.BasePageRequest; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; + +/** + * 成长话题分页查询请求 + * + * @author emotion-museum + * @date 2025-09-08 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class GrowthTopicPageRequest extends BasePageRequest { + + /** + * 分类 + */ + private String category; + + /** + * 难度等级 + */ + private String difficultyLevel; + + /** + * 标签 + */ + private String tags; +} \ No newline at end of file diff --git a/backend-single/src/main/java/com/emotion/dto/request/growth/GrowthTopicUpdateRequest.java b/backend-single/src/main/java/com/emotion/dto/request/growth/GrowthTopicUpdateRequest.java new file mode 100644 index 0000000..dd42434 --- /dev/null +++ b/backend-single/src/main/java/com/emotion/dto/request/growth/GrowthTopicUpdateRequest.java @@ -0,0 +1,58 @@ +package com.emotion.dto.request.growth; + +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; +import java.time.LocalDateTime; + +/** + * 成长话题更新请求 + * + * @author emotion-museum + * @date 2025-09-08 + */ +@Data +public class GrowthTopicUpdateRequest { + + /** + * ID + */ + @NotBlank(message = "ID不能为空") + private String id; + + /** + * 课题标题 + */ + @Size(max = 100, message = "标题长度不能超过100个字符") + private String title; + + /** + * 描述 + */ + @Size(max = 500, message = "描述长度不能超过500个字符") + private String description; + + /** + * 分类 + */ + @Size(max = 50, message = "分类长度不能超过50个字符") + private String category; + + /** + * 难度等级 + */ + @Size(max = 20, message = "难度等级长度不能超过20个字符") + private String difficultyLevel; + + /** + * 标签 + */ + @Size(max = 200, message = "标签长度不能超过200个字符") + private String tags; + + /** + * 结束时间 + */ + private LocalDateTime endTime; +} \ No newline at end of file diff --git a/backend-single/src/main/java/com/emotion/dto/request/guest/GuestUserCreateRequest.java b/backend-single/src/main/java/com/emotion/dto/request/guest/GuestUserCreateRequest.java new file mode 100644 index 0000000..6c30d4b --- /dev/null +++ b/backend-single/src/main/java/com/emotion/dto/request/guest/GuestUserCreateRequest.java @@ -0,0 +1,41 @@ +package com.emotion.dto.request.guest; + +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; + +/** + * 访客用户创建请求 + * + * @author emotion-museum + * @date 2025-09-08 + */ +@Data +public class GuestUserCreateRequest { + + /** + * 设备ID + */ + @NotBlank(message = "设备ID不能为空") + @Size(max = 100, message = "设备ID长度不能超过100个字符") + private String deviceId; + + /** + * IP地址 + */ + @Size(max = 50, message = "IP地址长度不能超过50个字符") + private String ipAddress; + + /** + * 用户代理 + */ + @Size(max = 500, message = "用户代理长度不能超过500个字符") + private String userAgent; + + /** + * 地理位置 + */ + @Size(max = 100, message = "地理位置长度不能超过100个字符") + private String location; +} \ No newline at end of file diff --git a/backend-single/src/main/java/com/emotion/dto/request/guest/GuestUserPageRequest.java b/backend-single/src/main/java/com/emotion/dto/request/guest/GuestUserPageRequest.java new file mode 100644 index 0000000..0392c15 --- /dev/null +++ b/backend-single/src/main/java/com/emotion/dto/request/guest/GuestUserPageRequest.java @@ -0,0 +1,31 @@ +package com.emotion.dto.request.guest; + +import com.emotion.common.BasePageRequest; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 访客用户分页查询请求 + * + * @author emotion-museum + * @date 2025-09-08 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class GuestUserPageRequest extends BasePageRequest { + + /** + * 设备ID + */ + private String deviceId; + + /** + * IP地址 + */ + private String ipAddress; + + /** + * 用户代理 + */ + private String userAgent; +} \ No newline at end of file diff --git a/backend-single/src/main/java/com/emotion/dto/request/guest/GuestUserUpdateRequest.java b/backend-single/src/main/java/com/emotion/dto/request/guest/GuestUserUpdateRequest.java new file mode 100644 index 0000000..1e77aa4 --- /dev/null +++ b/backend-single/src/main/java/com/emotion/dto/request/guest/GuestUserUpdateRequest.java @@ -0,0 +1,40 @@ +package com.emotion.dto.request.guest; + +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; + +/** + * 访客用户更新请求 + * + * @author emotion-museum + * @date 2025-09-08 + */ +@Data +public class GuestUserUpdateRequest { + + /** + * ID + */ + @NotBlank(message = "ID不能为空") + private String id; + + /** + * 访客昵称 + */ + @Size(max = 50, message = "访客昵称长度不能超过50个字符") + private String nickname; + + /** + * 访客头像 + */ + @Size(max = 200, message = "访客头像长度不能超过200个字符") + private String avatar; + + /** + * 地理位置 + */ + @Size(max = 100, message = "地理位置长度不能超过100个字符") + private String location; +} \ No newline at end of file diff --git a/backend-single/src/main/java/com/emotion/dto/request/reward/RewardCreateRequest.java b/backend-single/src/main/java/com/emotion/dto/request/reward/RewardCreateRequest.java new file mode 100644 index 0000000..c9fae11 --- /dev/null +++ b/backend-single/src/main/java/com/emotion/dto/request/reward/RewardCreateRequest.java @@ -0,0 +1,65 @@ +package com.emotion.dto.request.reward; + +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; +import java.time.LocalDateTime; + +/** + * 奖励创建请求 + * + * @author emotion-museum + * @date 2025-09-08 + */ +@Data +public class RewardCreateRequest { + + /** + * 用户ID + */ + @NotBlank(message = "用户ID不能为空") + private String userId; + + /** + * 奖励类型 + */ + @NotBlank(message = "奖励类型不能为空") + @Size(max = 50, message = "奖励类型长度不能超过50个字符") + private String rewardType; + + /** + * 奖励值 + */ + @Size(max = 100, message = "奖励值长度不能超过100个字符") + private String value; + + /** + * 描述 + */ + @Size(max = 200, message = "描述长度不能超过200个字符") + private String description; + + /** + * 课题ID + */ + private String topicId; + + /** + * 成就ID + */ + private String achievementId; + + /** + * 图标 + */ + @Size(max = 200, message = "图标长度不能超过200个字符") + private String icon; + + /** + * 稀有度 + */ + @Size(max = 20, message = "稀有度长度不能超过20个字符") + private String rarity; +} \ No newline at end of file diff --git a/backend-single/src/main/java/com/emotion/dto/request/reward/RewardPageRequest.java b/backend-single/src/main/java/com/emotion/dto/request/reward/RewardPageRequest.java new file mode 100644 index 0000000..4f290bd --- /dev/null +++ b/backend-single/src/main/java/com/emotion/dto/request/reward/RewardPageRequest.java @@ -0,0 +1,31 @@ +package com.emotion.dto.request.reward; + +import com.emotion.common.BasePageRequest; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 奖励分页查询请求 + * + * @author emotion-museum + * @date 2025-09-08 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class RewardPageRequest extends BasePageRequest { + + /** + * 用户ID + */ + private String userId; + + /** + * 奖励类型 + */ + private String rewardType; + + /** + * 来源 + */ + private String source; +} \ No newline at end of file diff --git a/backend-single/src/main/java/com/emotion/dto/request/reward/RewardUpdateRequest.java b/backend-single/src/main/java/com/emotion/dto/request/reward/RewardUpdateRequest.java new file mode 100644 index 0000000..41545b4 --- /dev/null +++ b/backend-single/src/main/java/com/emotion/dto/request/reward/RewardUpdateRequest.java @@ -0,0 +1,67 @@ +package com.emotion.dto.request.reward; + +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; + +/** + * 奖励更新请求 + * + * @author emotion-museum + * @date 2025-09-08 + */ +@Data +public class RewardUpdateRequest { + + /** + * ID + */ + @NotBlank(message = "ID不能为空") + private String id; + + /** + * 奖励类型 + */ + @Size(max = 50, message = "奖励类型长度不能超过50个字符") + private String rewardType; + + /** + * 奖励值 + */ + @Size(max = 100, message = "奖励值长度不能超过100个字符") + private String value; + + /** + * 描述 + */ + @Size(max = 200, message = "描述长度不能超过200个字符") + private String description; + + /** + * 课题ID + */ + private String topicId; + + /** + * 成就ID + */ + private String achievementId; + + /** + * 图标 + */ + @Size(max = 200, message = "图标长度不能超过200个字符") + private String icon; + + /** + * 稀有度 + */ + @Size(max = 20, message = "稀有度长度不能超过20个字符") + private String rarity; + + /** + * 是否新获得 + */ + private Integer isNew; +} \ No newline at end of file diff --git a/backend-single/src/main/java/com/emotion/dto/response/EmotionSummaryGenerateResponse.java b/backend-single/src/main/java/com/emotion/dto/response/EmotionSummaryGenerateResponse.java new file mode 100644 index 0000000..824ddd7 --- /dev/null +++ b/backend-single/src/main/java/com/emotion/dto/response/EmotionSummaryGenerateResponse.java @@ -0,0 +1,45 @@ +package com.emotion.dto.response; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 情绪总结生成响应类 + * + * @author emotion-museum + * @date 2025-09-08 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class EmotionSummaryGenerateResponse extends BaseResponse { + + /** + * 是否成功 + */ + private Boolean success; + + /** + * 消息 + */ + private String message; + + /** + * 情绪记录ID + */ + private String emotionRecordId; + + /** + * 情绪分析ID + */ + private String emotionAnalysisId; + + /** + * 消息数量 + */ + private Integer messageCount; + + /** + * 记录日期 + */ + private String recordDate; +} \ No newline at end of file diff --git a/backend-single/src/main/java/com/emotion/dto/response/EmotionSummaryStatusResponse.java b/backend-single/src/main/java/com/emotion/dto/response/EmotionSummaryStatusResponse.java new file mode 100644 index 0000000..efe61f4 --- /dev/null +++ b/backend-single/src/main/java/com/emotion/dto/response/EmotionSummaryStatusResponse.java @@ -0,0 +1,30 @@ +package com.emotion.dto.response; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 情绪总结状态响应类 + * + * @author emotion-museum + * @date 2025-09-08 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class EmotionSummaryStatusResponse extends BaseResponse { + + /** + * 用户ID + */ + private String userId; + + /** + * 是否可以生成 + */ + private Boolean canGenerate; + + /** + * 消息 + */ + private String message; +} \ No newline at end of file diff --git a/backend-single/src/main/java/com/emotion/dto/response/TopicInteractionResponse.java b/backend-single/src/main/java/com/emotion/dto/response/TopicInteractionResponse.java new file mode 100644 index 0000000..180c8ab --- /dev/null +++ b/backend-single/src/main/java/com/emotion/dto/response/TopicInteractionResponse.java @@ -0,0 +1,57 @@ +package com.emotion.dto.response; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.time.LocalDateTime; + +/** + * 话题互动响应类 + * + * @author emotion-museum + * @date 2025-09-08 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class TopicInteractionResponse extends BaseResponse { + + /** + * 话题ID + */ + private String topicId; + + /** + * 互动类型 + */ + private String type; + + /** + * 内容 + */ + private String content; + + /** + * 用户输入 + */ + private String userInput; + + /** + * AI回应 + */ + private String aiResponse; + + /** + * 评分 + */ + private Integer rating; + + /** + * 反馈 + */ + private String feedback; + + /** + * 完成时间 + */ + private LocalDateTime completedTime; +} \ No newline at end of file diff --git a/backend-single/src/main/java/com/emotion/dto/response/UserStatsResponse.java b/backend-single/src/main/java/com/emotion/dto/response/UserStatsResponse.java new file mode 100644 index 0000000..f345dff --- /dev/null +++ b/backend-single/src/main/java/com/emotion/dto/response/UserStatsResponse.java @@ -0,0 +1,35 @@ +package com.emotion.dto.response; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 用户统计响应类 + * + * @author emotion-museum + * @date 2025-09-08 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class UserStatsResponse extends BaseResponse { + + /** + * 用户ID + */ + private String userId; + + /** + * 统计类型 + */ + private String statsType; + + /** + * 统计值 + */ + private Double value; + + /** + * 周期 + */ + private String period; +} \ No newline at end of file diff --git a/backend-single/src/main/java/com/emotion/dto/response/growth/GrowthTopicResponse.java b/backend-single/src/main/java/com/emotion/dto/response/growth/GrowthTopicResponse.java new file mode 100644 index 0000000..5bb00bb --- /dev/null +++ b/backend-single/src/main/java/com/emotion/dto/response/growth/GrowthTopicResponse.java @@ -0,0 +1,74 @@ +package com.emotion.dto.response.growth; + +import com.emotion.dto.response.BaseResponse; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * 成长话题响应类 + * + * @author emotion-museum + * @date 2025-09-08 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class GrowthTopicResponse extends BaseResponse { + + /** + * 课题标题 + */ + private String title; + + /** + * 分类 + */ + private String category; + + /** + * 难度: easy-简单, medium-中等, hard-困难 + */ + private String difficulty; + + /** + * 描述 + */ + private String description; + + /** + * 内容 + */ + private String content; + + /** + * 持续天数 + */ + private Integer durationDays; + + /** + * 解锁条件 + */ + private String unlockConditions; + + /** + * 是否解锁 + */ + private Integer isUnlocked; + + /** + * 进度百分比 + */ + private BigDecimal progress; + + /** + * 完成时间 + */ + private LocalDateTime completedTime; + + /** + * 奖励 + */ + private String rewards; +} \ No newline at end of file diff --git a/backend-single/src/main/java/com/emotion/dto/response/guest/GuestUserResponse.java b/backend-single/src/main/java/com/emotion/dto/response/guest/GuestUserResponse.java new file mode 100644 index 0000000..235f27a --- /dev/null +++ b/backend-single/src/main/java/com/emotion/dto/response/guest/GuestUserResponse.java @@ -0,0 +1,68 @@ +package com.emotion.dto.response.guest; + +import com.emotion.dto.response.BaseResponse; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.time.LocalDateTime; + +/** + * 访客用户响应类 + * + * @author emotion-museum + * @date 2025-09-08 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class GuestUserResponse extends BaseResponse { + + /** + * 访客用户ID (格式: guest_xxx) + */ + private String guestUserId; + + /** + * 客户端IP地址 (支持IPv6) + */ + private String ipAddress; + + /** + * 用户代理信息 + */ + private String userAgent; + + /** + * 访客昵称 + */ + private String nickname; + + /** + * 访客头像 + */ + private String avatar; + + /** + * 最后活跃时间 + */ + private LocalDateTime lastActiveTime; + + /** + * 会话数量 + */ + private Integer conversationCount; + + /** + * 消息数量 + */ + private Integer messageCount; + + /** + * IP地址的地理位置信息 + */ + private String location; + + /** + * 设备信息 + */ + private String deviceInfo; +} \ No newline at end of file diff --git a/backend-single/src/main/java/com/emotion/dto/response/reward/RewardResponse.java b/backend-single/src/main/java/com/emotion/dto/response/reward/RewardResponse.java new file mode 100644 index 0000000..d808fcb --- /dev/null +++ b/backend-single/src/main/java/com/emotion/dto/response/reward/RewardResponse.java @@ -0,0 +1,68 @@ +package com.emotion.dto.response.reward; + +import com.emotion.dto.response.BaseResponse; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.time.LocalDateTime; + +/** + * 奖励响应类 + * + * @author emotion-museum + * @date 2025-09-08 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class RewardResponse extends BaseResponse { + + /** + * 课题ID + */ + private String topicId; + + /** + * 成就ID + */ + private String achievementId; + + /** + * 奖励类型 + */ + private String type; + + /** + * 奖励名称 + */ + private String name; + + /** + * 描述 + */ + private String description; + + /** + * 图标 + */ + private String icon; + + /** + * 稀有度 + */ + private String rarity; + + /** + * 奖励值 + */ + private String value; + + /** + * 获得时间 + */ + private LocalDateTime earnedTime; + + /** + * 是否新获得 + */ + private Integer isNew; +} \ No newline at end of file diff --git a/backend-single/src/main/java/com/emotion/entity/UserStats.java b/backend-single/src/main/java/com/emotion/entity/UserStats.java index 1a96c07..e3e9712 100644 --- a/backend-single/src/main/java/com/emotion/entity/UserStats.java +++ b/backend-single/src/main/java/com/emotion/entity/UserStats.java @@ -28,6 +28,24 @@ public class UserStats extends BaseEntity { @TableField("user_id") private String userId; + /** + * 统计类型 + */ + @TableField("stats_type") + private String statsType; + + /** + * 统计值 + */ + @TableField("value") + private Double value; + + /** + * 周期 + */ + @TableField("period") + private String period; + /** * 总对话数 */ @@ -105,4 +123,4 @@ public class UserStats extends BaseEntity { */ @TableField("social_interactions") private Integer socialInteractions; -} +} \ No newline at end of file diff --git a/backend-single/src/main/java/com/emotion/service/AiChatService.java b/backend-single/src/main/java/com/emotion/service/AiChatService.java index 9e82600..cbd6315 100644 --- a/backend-single/src/main/java/com/emotion/service/AiChatService.java +++ b/backend-single/src/main/java/com/emotion/service/AiChatService.java @@ -2,6 +2,8 @@ package com.emotion.service; import com.emotion.dto.request.*; import com.emotion.dto.response.*; +import java.util.Map; +import java.util.concurrent.CompletableFuture; /** * AI聊天服务接口 @@ -114,26 +116,43 @@ public interface AiChatService { */ boolean healthCheck(); + /** + * 发送日记内容生成AI总结评论 + * + * @param conversationId 会话ID + * @param userMessage 用户日记内容 + * @param userId 用户ID + * @return AI评论内容 + */ + String sendSummaryMessage(String conversationId, String userMessage, String userId); + /** * 生成用户情绪记录总结 * @param userId 用户ID * @return 包含情绪总结等信息的Map */ - java.util.Map generateEmotionSummary(String userId); + Map generateEmotionSummary(String userId); /** * 异步生成用户情绪记录总结 * @param userId 用户ID * @return 包含情绪总结等信息的CompletableFuture */ - java.util.concurrent.CompletableFuture> generateEmotionSummaryAsync(String userId); + CompletableFuture> generateEmotionSummaryAsync(String userId); /** - * 发送日记内容生成AI总结评论 - * @param conversationId 会话ID - * @param userMessage 用户日记内容 + * 生成用户情绪记录总结并返回响应对象 + * * @param userId 用户ID - * @return AI评论内容 + * @return 情绪总结生成响应 */ - String sendSummaryMessage(String conversationId, String userMessage, String userId); + EmotionSummaryGenerateResponse generateEmotionSummaryWithResponse(String userId); + + /** + * 获取用户情绪记录总结状态并返回响应对象 + * + * @param userId 用户ID + * @return 情绪总结状态响应 + */ + EmotionSummaryStatusResponse getEmotionSummaryStatusWithResponse(String userId); } \ No newline at end of file diff --git a/backend-single/src/main/java/com/emotion/service/EmotionRecordService.java b/backend-single/src/main/java/com/emotion/service/EmotionRecordService.java index 26c6081..eee9835 100644 --- a/backend-single/src/main/java/com/emotion/service/EmotionRecordService.java +++ b/backend-single/src/main/java/com/emotion/service/EmotionRecordService.java @@ -32,86 +32,6 @@ public interface EmotionRecordService extends IService { */ IPage getPageByUserId(BasePageRequest request, String userId); - /** - * 根据用户ID分页查询情绪记录(简化版本) - */ - IPage getByUserIdWithPage(String userId, Integer current, Integer size); - - /** - * 根据用户ID查询情绪记录 - */ - List getByUserId(String userId); - - /** - * 根据情绪类型查询记录 - */ - List getByEmotionType(String emotionType); - - /** - * 根据用户ID和情绪类型查询记录 - */ - List getByUserIdAndEmotionType(String userId, String emotionType); - - /** - * 根据时间范围查询情绪记录 - */ - List getByUserIdAndTimeRange(String userId, LocalDateTime startTime, LocalDateTime endTime); - - /** - * 根据强度范围查询情绪记录 - */ - List getByIntensityRange(Double minIntensity, Double maxIntensity); - - /** - * 统计用户的情绪记录数量 - */ - Long countByUserId(String userId); - - /** - * 统计指定情绪类型的记录数量 - */ - Long countByEmotionType(String emotionType); - - /** - * 统计用户指定情绪类型的记录数量 - */ - Long countByUserIdAndEmotionType(String userId, String emotionType); - - /** - * 查询用户最近的情绪记录 - */ - List getRecentByUserId(String userId, Integer limit); - - /** - * 查询用户的平均情绪强度 - */ - Double getAvgIntensityByUserId(String userId); - - /** - * 查询用户指定时间段的平均情绪强度 - */ - Double getAvgIntensityByUserIdAndTimeRange(String userId, LocalDateTime startTime, LocalDateTime endTime); - - /** - * 查询用户最常见的情绪类型 - */ - String getMostFrequentEmotionByUserId(String userId); - - /** - * 查询高强度情绪记录 - */ - List getHighIntensityRecords(Double minIntensity); - - /** - * 根据触发因素查询情绪记录 - */ - List getByTrigger(String trigger); - - /** - * 根据地点查询情绪记录 - */ - List getByLocation(String location); - /** * 创建情绪记录 */ @@ -154,9 +74,4 @@ public interface EmotionRecordService extends IService { * 获取用户情绪统计 */ Map getEmotionStats(String userId, String startDate, String endDate); - - /** - * 查询用户最近的情绪记录并返回响应 - */ - List getRecentByUserIdWithResponse(String userId, Integer limit); } \ No newline at end of file diff --git a/backend-single/src/main/java/com/emotion/service/GrowthTopicService.java b/backend-single/src/main/java/com/emotion/service/GrowthTopicService.java index 155653c..c4c8f01 100644 --- a/backend-single/src/main/java/com/emotion/service/GrowthTopicService.java +++ b/backend-single/src/main/java/com/emotion/service/GrowthTopicService.java @@ -3,6 +3,10 @@ package com.emotion.service; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.service.IService; import com.emotion.common.BasePageRequest; +import com.emotion.common.PageResult; +import com.emotion.dto.request.growth.GrowthTopicCreateRequest; +import com.emotion.dto.request.growth.GrowthTopicUpdateRequest; +import com.emotion.dto.response.growth.GrowthTopicResponse; import com.emotion.entity.GrowthTopic; import java.time.LocalDateTime; @@ -12,7 +16,7 @@ import java.util.List; * 成长话题服务接口 * * @author emotion-museum - * @date 2025-07-23 + * @date 2025-09-08 */ public interface GrowthTopicService extends IService { @@ -22,103 +26,33 @@ public interface GrowthTopicService extends IService { IPage getPage(BasePageRequest request); /** - * 根据分类查询话题 + * 分页查询成长话题响应 */ - List getByCategory(String category); + PageResult getPageWithResponse(BasePageRequest request); /** - * 根据难度等级查询话题 + * 根据ID获取成长话题响应 */ - List getByDifficultyLevel(String difficultyLevel); - - /** - * 根据状态查询话题 - */ - List getByStatus(String status); - - /** - * 查询推荐话题 - */ - List getRecommendedTopics(Integer limit); - - /** - * 查询热门话题 - */ - List getPopularTopics(Integer limit); - - /** - * 查询最新话题 - */ - List getLatestTopics(Integer limit); - - /** - * 根据参与人数范围查询话题 - */ - List getByParticipantRange(Integer minParticipants, Integer maxParticipants); - - /** - * 根据时间范围查询话题 - */ - List getByTimeRange(LocalDateTime startTime, LocalDateTime endTime); - - /** - * 统计指定分类的话题数量 - */ - Long countByCategory(String category); - - /** - * 统计指定状态的话题数量 - */ - Long countByStatus(String status); - - /** - * 统计指定难度等级的话题数量 - */ - Long countByDifficultyLevel(String difficultyLevel); - - /** - * 查询平均参与人数 - */ - Double getAvgParticipantCount(); - - /** - * 查询指定分类的平均参与人数 - */ - Double getAvgParticipantCountByCategory(String category); - - /** - * 根据标签搜索话题 - */ - List searchByTags(String tags); - - /** - * 根据关键词搜索话题 - */ - List searchByKeyword(String keyword); - - /** - * 更新话题参与人数 - */ - boolean updateParticipantCount(String id, Integer increment); - - /** - * 更新话题状态 - */ - boolean updateStatus(String id, String status); - - /** - * 查询即将结束的话题 - */ - List getEndingSoonTopics(Integer days); - - /** - * 查询长期话题 - */ - List getLongTermTopics(); - + GrowthTopicResponse getGrowthTopicResponseById(String id); + /** * 创建成长话题 */ - GrowthTopic createGrowthTopic(String title, String description, String category, - String difficultyLevel, String tags, LocalDateTime endTime); + GrowthTopic createGrowthTopic(String title, String description, String category, + String difficultyLevel, String tags, LocalDateTime endTime); + + /** + * 创建成长话题并返回响应 + */ + GrowthTopicResponse createGrowthTopicWithResponse(GrowthTopicCreateRequest request); + + /** + * 更新成长话题并返回响应 + */ + GrowthTopicResponse updateGrowthTopicWithResponse(GrowthTopicUpdateRequest request); + + /** + * 删除成长话题 + */ + boolean deleteGrowthTopic(String id); } diff --git a/backend-single/src/main/java/com/emotion/service/GuestUserService.java b/backend-single/src/main/java/com/emotion/service/GuestUserService.java index fee79c8..bbe9fd4 100644 --- a/backend-single/src/main/java/com/emotion/service/GuestUserService.java +++ b/backend-single/src/main/java/com/emotion/service/GuestUserService.java @@ -3,6 +3,10 @@ package com.emotion.service; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.service.IService; import com.emotion.common.BasePageRequest; +import com.emotion.common.PageResult; +import com.emotion.dto.request.guest.GuestUserCreateRequest; +import com.emotion.dto.request.guest.GuestUserUpdateRequest; +import com.emotion.dto.response.guest.GuestUserResponse; import com.emotion.entity.GuestUser; import java.time.LocalDateTime; @@ -12,7 +16,7 @@ import java.util.List; * 访客用户服务接口 * * @author emotion-museum - * @date 2025-07-23 + * @date 2025-09-08 */ public interface GuestUserService extends IService { @@ -21,6 +25,16 @@ public interface GuestUserService extends IService { */ IPage getPage(BasePageRequest request); + /** + * 分页查询访客用户响应 + */ + PageResult getPageWithResponse(BasePageRequest request); + + /** + * 根据ID获取访客用户响应 + */ + GuestUserResponse getGuestUserResponseById(String id); + /** * 根据设备ID查询访客用户 */ @@ -120,4 +134,19 @@ public interface GuestUserService extends IService { * 创建访客用户 */ GuestUser createGuestUser(String deviceId, String ipAddress, String userAgent, String location); -} + + /** + * 创建访客用户并返回响应 + */ + GuestUserResponse createGuestUserWithResponse(GuestUserCreateRequest request); + + /** + * 更新访客用户并返回响应 + */ + GuestUserResponse updateGuestUserWithResponse(GuestUserUpdateRequest request); + + /** + * 删除访客用户 + */ + boolean deleteGuestUser(String id); +} \ No newline at end of file diff --git a/backend-single/src/main/java/com/emotion/service/MessageService.java b/backend-single/src/main/java/com/emotion/service/MessageService.java index 990adc9..c02d39d 100644 --- a/backend-single/src/main/java/com/emotion/service/MessageService.java +++ b/backend-single/src/main/java/com/emotion/service/MessageService.java @@ -18,7 +18,7 @@ import java.util.List; * 消息服务接口 * * @author emotion-museum - * @date 2025-07-23 + * @date 2025-09-08 */ public interface MessageService extends IService { @@ -27,6 +27,11 @@ public interface MessageService extends IService { */ IPage getPage(BasePageRequest request); + /** + * 分页查询消息响应 + */ + PageResult getPageWithResponse(MessagePageRequest request); + /** * 根据会话ID分页查询消息 */ @@ -141,4 +146,24 @@ public interface MessageService extends IService { * 根据ID获取消息响应(新接口) */ MessageResponse getMessageById(String id); -} + + /** + * 搜索消息并返回响应 + */ + PageResult searchWithResponse(MessageSearchRequest request); + + /** + * 获取最近消息并返回响应 + */ + PageResult getRecentWithResponse(MessageRecentRequest request); + + /** + * 更新消息 + */ + MessageResponse updateMessage(String id, String content); + + /** + * 删除消息 + */ + boolean deleteMessage(String id); +} \ No newline at end of file diff --git a/backend-single/src/main/java/com/emotion/service/RewardService.java b/backend-single/src/main/java/com/emotion/service/RewardService.java index afd4c65..59b3052 100644 --- a/backend-single/src/main/java/com/emotion/service/RewardService.java +++ b/backend-single/src/main/java/com/emotion/service/RewardService.java @@ -3,6 +3,10 @@ package com.emotion.service; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.service.IService; import com.emotion.common.BasePageRequest; +import com.emotion.common.PageResult; +import com.emotion.dto.request.reward.RewardCreateRequest; +import com.emotion.dto.request.reward.RewardUpdateRequest; +import com.emotion.dto.response.reward.RewardResponse; import com.emotion.entity.Reward; import java.time.LocalDateTime; @@ -12,7 +16,7 @@ import java.util.List; * 奖励服务接口 * * @author emotion-museum - * @date 2025-07-23 + * @date 2025-09-08 */ public interface RewardService extends IService { @@ -21,11 +25,21 @@ public interface RewardService extends IService { */ IPage getPage(BasePageRequest request); + /** + * 分页查询奖励响应 + */ + PageResult getPageWithResponse(BasePageRequest request); + /** * 根据用户ID分页查询奖励 */ IPage getPageByUserId(BasePageRequest request, String userId); + /** + * 根据ID获取奖励响应 + */ + RewardResponse getRewardResponseById(String id); + /** * 根据用户ID查询奖励 */ @@ -139,6 +153,21 @@ public interface RewardService extends IService { /** * 创建奖励 */ - Reward createReward(String userId, String rewardType, Integer points, String source, - String description, LocalDateTime expiredTime); -} + Reward createReward(String userId, String rewardType, String value, + String description, String topicId, String achievementId, String icon, String rarity); + + /** + * 创建奖励并返回响应 + */ + RewardResponse createRewardWithResponse(RewardCreateRequest request); + + /** + * 更新奖励并返回响应 + */ + RewardResponse updateRewardWithResponse(RewardUpdateRequest request); + + /** + * 删除奖励 + */ + boolean deleteReward(String id); +} \ No newline at end of file diff --git a/backend-single/src/main/java/com/emotion/service/TopicInteractionService.java b/backend-single/src/main/java/com/emotion/service/TopicInteractionService.java index 4c98514..8f5fa15 100644 --- a/backend-single/src/main/java/com/emotion/service/TopicInteractionService.java +++ b/backend-single/src/main/java/com/emotion/service/TopicInteractionService.java @@ -2,12 +2,13 @@ package com.emotion.service; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.service.IService; -import com.emotion.common.BasePageRequest; +import com.emotion.common.PageResult; +import com.emotion.dto.request.TopicInteractionCreateRequest; +import com.emotion.dto.request.TopicInteractionPageRequest; +import com.emotion.dto.request.TopicInteractionUpdateRequest; +import com.emotion.dto.response.TopicInteractionResponse; import com.emotion.entity.TopicInteraction; -import java.time.LocalDateTime; -import java.util.List; - /** * 话题互动服务接口 * @@ -19,131 +20,25 @@ public interface TopicInteractionService extends IService { /** * 分页查询话题互动 */ - IPage getPage(BasePageRequest request); + PageResult getPageWithResponse(TopicInteractionPageRequest request); /** - * 根据话题ID分页查询互动 + * 根据ID获取话题互动响应对象 */ - IPage getPageByTopicId(BasePageRequest request, String topicId); - - /** - * 根据用户ID分页查询互动 - */ - IPage getPageByUserId(BasePageRequest request, String userId); - - /** - * 根据话题ID查询互动 - */ - List getByTopicId(String topicId); - - /** - * 根据用户ID查询互动 - */ - List getByUserId(String userId); - - /** - * 根据互动类型查询互动 - */ - List getByInteractionType(String interactionType); - - /** - * 根据话题ID和互动类型查询互动 - */ - List getByTopicIdAndInteractionType(String topicId, String interactionType); - - /** - * 根据用户ID和互动类型查询互动 - */ - List getByUserIdAndInteractionType(String userId, String interactionType); - - /** - * 根据话题ID和用户ID查询互动 - */ - List getByTopicIdAndUserId(String topicId, String userId); - - /** - * 根据时间范围查询互动 - */ - List getByTimeRange(LocalDateTime startTime, LocalDateTime endTime); - - /** - * 统计话题的互动数量 - */ - Long countByTopicId(String topicId); - - /** - * 统计用户的互动数量 - */ - Long countByUserId(String userId); - - /** - * 统计指定类型的互动数量 - */ - Long countByInteractionType(String interactionType); - - /** - * 统计话题指定类型的互动数量 - */ - Long countByTopicIdAndInteractionType(String topicId, String interactionType); - - /** - * 统计用户指定类型的互动数量 - */ - Long countByUserIdAndInteractionType(String userId, String interactionType); - - /** - * 查询话题最近的互动 - */ - List getRecentByTopicId(String topicId, Integer limit); - - /** - * 查询用户最近的互动 - */ - List getRecentByUserId(String userId, Integer limit); - - /** - * 查询热门互动(按点赞数排序) - */ - List getPopularInteractions(Integer limit); - - /** - * 查询话题的热门互动 - */ - List getPopularInteractionsByTopicId(String topicId, Integer limit); - - /** - * 根据点赞数范围查询互动 - */ - List getByLikesRange(Integer minLikes, Integer maxLikes); - - /** - * 查询用户是否已参与话题 - */ - boolean hasUserInteracted(String topicId, String userId); - - /** - * 查询用户在话题中的特定互动类型 - */ - TopicInteraction getUserInteractionByType(String topicId, String userId, String interactionType); - - /** - * 更新互动点赞数 - */ - boolean updateLikes(String id, Integer increment); - - /** - * 根据内容关键词搜索互动 - */ - List searchByContent(String keyword); - - /** - * 根据话题ID和内容关键词搜索互动 - */ - List searchByTopicIdAndContent(String topicId, String keyword); + TopicInteractionResponse getTopicInteractionResponseById(String id); /** * 创建话题互动 */ - TopicInteraction createTopicInteraction(String topicId, String userId, String interactionType, - String content, String attachments); + TopicInteractionResponse createTopicInteractionWithResponse(TopicInteractionCreateRequest request); + + /** + * 更新话题互动 + */ + TopicInteractionResponse updateTopicInteractionWithResponse(TopicInteractionUpdateRequest request); + + /** + * 删除话题互动 + */ + boolean deleteTopicInteraction(String id); } diff --git a/backend-single/src/main/java/com/emotion/service/UserService.java b/backend-single/src/main/java/com/emotion/service/UserService.java index 86da18c..7bda723 100644 --- a/backend-single/src/main/java/com/emotion/service/UserService.java +++ b/backend-single/src/main/java/com/emotion/service/UserService.java @@ -1,13 +1,14 @@ package com.emotion.service; -import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.service.IService; -import com.emotion.common.BasePageRequest; +import com.emotion.common.PageResult; +import com.emotion.dto.request.UserCreateRequest; +import com.emotion.dto.request.UserPageRequest; +import com.emotion.dto.request.UserUpdateRequest; +import com.emotion.dto.request.UserProfileUpdateRequest; +import com.emotion.dto.response.UserResponse; import com.emotion.entity.User; -import java.time.LocalDateTime; -import java.util.List; - /** * 用户服务接口 * @@ -17,92 +18,37 @@ import java.util.List; public interface UserService extends IService { /** - * 分页查询用户 + * 分页查询用户响应 */ - IPage getPage(BasePageRequest request); - + PageResult getPageWithResponse(UserPageRequest request); + /** - * 根据账号查询用户 + * 根据ID获取用户响应 */ - User getByAccount(String account); - + UserResponse getUserResponseById(String id); + /** - * 根据用户名查询用户 + * 创建用户并返回响应 */ - User getByUsername(String username); - + UserResponse createUserWithResponse(UserCreateRequest request); + /** - * 根据邮箱查询用户 + * 更新用户并返回响应 */ - User getByEmail(String email); - + UserResponse updateUserWithResponse(UserUpdateRequest request); + /** - * 根据手机号查询用户 + * 更新当前用户个人资料并返回响应 */ - User getByPhone(String phone); - + UserResponse updateCurrentUserProfileWithResponse(UserProfileUpdateRequest request); + /** - * 根据第三方平台信息查询用户 + * 获取当前用户个人资料并返回响应 */ - User getByThirdParty(String thirdPartyId, String thirdPartyType); - + UserResponse getCurrentUserProfileWithResponse(); + /** - * 根据状态查询用户列表 + * 删除用户 */ - List getByStatus(Integer status); - - /** - * 根据会员等级查询用户列表 - */ - List getByMemberLevel(String memberLevel); - - /** - * 查询活跃用户(最近N天有活动) - */ - List getActiveUsers(Integer days); - - /** - * 查询新注册用户(最近N天注册) - */ - List getNewUsers(Integer days); - - /** - * 更新用户最后活跃时间 - */ - boolean updateLastActiveTime(String userId, LocalDateTime lastActiveTime); - - /** - * 更新用户状态 - */ - boolean updateStatus(String userId, Integer status); - - /** - * 更新用户使用天数 - */ - boolean updateTotalDays(String userId, Integer totalDays); - - /** - * 统计指定状态的用户数量 - */ - Long countByStatus(Integer status); - - /** - * 统计指定会员等级的用户数量 - */ - Long countByMemberLevel(String memberLevel); - - /** - * 创建用户 - */ - User createUser(String account, String username, String password, String email, String phone); - - /** - * 验证用户密码 - */ - boolean validatePassword(String userId, String password); - - /** - * 更新用户密码 - */ - boolean updatePassword(String userId, String newPassword); -} + boolean deleteUser(String id); +} \ No newline at end of file diff --git a/backend-single/src/main/java/com/emotion/service/UserStatsService.java b/backend-single/src/main/java/com/emotion/service/UserStatsService.java index 29a00df..a949906 100644 --- a/backend-single/src/main/java/com/emotion/service/UserStatsService.java +++ b/backend-single/src/main/java/com/emotion/service/UserStatsService.java @@ -1,11 +1,14 @@ package com.emotion.service; -import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.service.IService; -import com.emotion.common.BasePageRequest; +import com.emotion.common.PageResult; +import com.emotion.dto.request.UserStatsCreateRequest; +import com.emotion.dto.request.UserStatsIncrementRequest; +import com.emotion.dto.request.UserStatsPageRequest; +import com.emotion.dto.request.UserStatsUpdateValueRequest; +import com.emotion.dto.response.UserStatsResponse; import com.emotion.entity.UserStats; -import java.time.LocalDateTime; import java.util.List; /** @@ -17,84 +20,19 @@ import java.util.List; public interface UserStatsService extends IService { /** - * 分页查询用户统计 + * 分页查询用户统计响应 */ - IPage getPage(BasePageRequest request); - - /** - * 根据用户ID查询统计信息 - */ - UserStats getByUserId(String userId); - - /** - * 根据统计类型查询统计信息 - */ - List getByStatsType(String statsType); - - /** - * 根据用户ID和统计类型查询统计信息 - */ - UserStats getByUserIdAndStatsType(String userId, String statsType); - - /** - * 根据时间范围查询统计信息 - */ - List getByTimeRange(LocalDateTime startTime, LocalDateTime endTime); - - /** - * 根据数值范围查询统计信息 - */ - List getByValueRange(Double minValue, Double maxValue); - - /** - * 统计指定类型的记录数量 - */ - Long countByStatsType(String statsType); - - /** - * 查询平均统计值 - */ - Double getAvgValueByStatsType(String statsType); - - /** - * 查询最大统计值 - */ - Double getMaxValueByStatsType(String statsType); - - /** - * 查询最小统计值 - */ - Double getMinValueByStatsType(String statsType); - - /** - * 查询用户的所有统计类型 - */ - List getAllStatsByUserId(String userId); - - /** - * 查询排名前N的用户统计 - */ - List getTopUsersByStatsType(String statsType, Integer limit); - - /** - * 查询用户在指定统计类型中的排名 - */ - Long getUserRankByStatsType(String userId, String statsType); - + PageResult getPageWithResponse(UserStatsPageRequest request); + /** * 更新用户统计值 */ - boolean updateStatsValue(String userId, String statsType, Double value); + boolean updateStatsValue(UserStatsUpdateValueRequest request); /** * 增加用户统计值 */ - boolean incrementStatsValue(String userId, String statsType, Double increment); - - /** - * 批量更新用户统计 - */ - boolean batchUpdateStats(String userId, List statsList); + boolean incrementStatsValue(UserStatsIncrementRequest request); /** * 重新计算用户统计 @@ -107,22 +45,12 @@ public interface UserStatsService extends IService { boolean recalculateAllUserStats(); /** - * 根据周期查询统计信息 + * 创建或更新用户统计响应 */ - List getByPeriod(String period); - - /** - * 根据用户ID和周期查询统计信息 - */ - List getByUserIdAndPeriod(String userId, String period); - - /** - * 创建或更新用户统计 - */ - UserStats createOrUpdateUserStats(String userId, String statsType, Double value, String period); - + UserStatsResponse createOrUpdateUserStatsWithResponse(UserStatsCreateRequest request); + /** * 删除过期的统计数据 */ boolean deleteExpiredStats(Integer days); -} +} \ No newline at end of file diff --git a/backend-single/src/main/java/com/emotion/service/impl/AiChatServiceImpl.java b/backend-single/src/main/java/com/emotion/service/impl/AiChatServiceImpl.java index c1eb571..32f62bb 100644 --- a/backend-single/src/main/java/com/emotion/service/impl/AiChatServiceImpl.java +++ b/backend-single/src/main/java/com/emotion/service/impl/AiChatServiceImpl.java @@ -655,6 +655,77 @@ public class AiChatServiceImpl implements AiChatService { } } + @Override + public EmotionSummaryGenerateResponse generateEmotionSummaryWithResponse(String userId) { + log.info("生成用户情绪记录总结: userId={}", userId); + + // 调用原有的generateEmotionSummary方法 + Map result = generateEmotionSummary(userId); + + // 转换为响应对象 + return convertToGenerateResponse(result); + } + + @Override + public EmotionSummaryStatusResponse getEmotionSummaryStatusWithResponse(String userId) { + log.info("获取用户情绪记录总结状态: userId={}", userId); + + // 构建状态信息 + Map statusInfo = Map.of( + "userId", userId, + "canGenerate", true, + "message", "可以生成情绪记录总结"); + + // 转换为响应对象 + return convertToStatusResponse(statusInfo); + } + + /** + * 转换为生成响应对象 + */ + private EmotionSummaryGenerateResponse convertToGenerateResponse(Map result) { + EmotionSummaryGenerateResponse response = new EmotionSummaryGenerateResponse(); + response.setSuccess((Boolean) result.get("success")); + response.setMessage((String) result.get("message")); + + if (result.containsKey("emotionRecord") && result.get("emotionRecord") != null) { + // 从实际的EmotionRecord对象获取ID + Object emotionRecord = result.get("emotionRecord"); + if (emotionRecord instanceof EmotionRecord) { + response.setEmotionRecordId(((EmotionRecord) emotionRecord).getId()); + } + } + + if (result.containsKey("analysisResult") && result.get("analysisResult") != null) { + // 从实际的EmotionAnalysis对象获取ID + Object analysisResult = result.get("analysisResult"); + if (analysisResult instanceof EmotionAnalysis) { + response.setEmotionAnalysisId(((EmotionAnalysis) analysisResult).getId()); + } + } + + if (result.containsKey("messageCount")) { + response.setMessageCount((Integer) result.get("messageCount")); + } + + if (result.containsKey("recordDate")) { + response.setRecordDate(result.get("recordDate").toString()); + } + + return response; + } + + /** + * 转换为状态响应对象 + */ + private EmotionSummaryStatusResponse convertToStatusResponse(Map statusInfo) { + EmotionSummaryStatusResponse response = new EmotionSummaryStatusResponse(); + response.setUserId((String) statusInfo.get("userId")); + response.setCanGenerate((Boolean) statusInfo.get("canGenerate")); + response.setMessage((String) statusInfo.get("message")); + return response; + } + public boolean isServiceAvailable() { try { // 简单的健康检查 diff --git a/backend-single/src/main/java/com/emotion/service/impl/EmotionRecordServiceImpl.java b/backend-single/src/main/java/com/emotion/service/impl/EmotionRecordServiceImpl.java index c25a035..a0f4c92 100644 --- a/backend-single/src/main/java/com/emotion/service/impl/EmotionRecordServiceImpl.java +++ b/backend-single/src/main/java/com/emotion/service/impl/EmotionRecordServiceImpl.java @@ -67,172 +67,6 @@ public class EmotionRecordServiceImpl extends ServiceImpl getByUserId(String userId) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(EmotionRecord::getUserId, userId) - .eq(EmotionRecord::getIsDeleted, 0) - .orderByDesc(EmotionRecord::getCreateTime); - return this.list(wrapper); - } - - @Override - public List getByEmotionType(String emotionType) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(EmotionRecord::getEmotionType, emotionType) - .eq(EmotionRecord::getIsDeleted, 0) - .orderByDesc(EmotionRecord::getCreateTime); - return this.list(wrapper); - } - - @Override - public List getByUserIdAndEmotionType(String userId, String emotionType) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(EmotionRecord::getUserId, userId) - .eq(EmotionRecord::getEmotionType, emotionType) - .eq(EmotionRecord::getIsDeleted, 0) - .orderByDesc(EmotionRecord::getCreateTime); - return this.list(wrapper); - } - - @Override - public List getByUserIdAndTimeRange(String userId, LocalDateTime startTime, LocalDateTime endTime) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(EmotionRecord::getUserId, userId) - .between(EmotionRecord::getCreateTime, startTime, endTime) - .eq(EmotionRecord::getIsDeleted, 0) - .orderByDesc(EmotionRecord::getCreateTime); - return this.list(wrapper); - } - - @Override - public List getByIntensityRange(Double minIntensity, Double maxIntensity) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.between(EmotionRecord::getIntensity, BigDecimal.valueOf(minIntensity), BigDecimal.valueOf(maxIntensity)) - .eq(EmotionRecord::getIsDeleted, 0) - .orderByDesc(EmotionRecord::getIntensity); - return this.list(wrapper); - } - - @Override - public Long countByUserId(String userId) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(EmotionRecord::getUserId, userId) - .eq(EmotionRecord::getIsDeleted, 0); - return this.count(wrapper); - } - - @Override - public Long countByEmotionType(String emotionType) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(EmotionRecord::getEmotionType, emotionType) - .eq(EmotionRecord::getIsDeleted, 0); - return this.count(wrapper); - } - - @Override - public Long countByUserIdAndEmotionType(String userId, String emotionType) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(EmotionRecord::getUserId, userId) - .eq(EmotionRecord::getEmotionType, emotionType) - .eq(EmotionRecord::getIsDeleted, 0); - return this.count(wrapper); - } - - @Override - public List getRecentByUserId(String userId, Integer limit) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(EmotionRecord::getUserId, userId) - .eq(EmotionRecord::getIsDeleted, 0) - .orderByDesc(EmotionRecord::getCreateTime) - .last("LIMIT " + limit); - return this.list(wrapper); - } - - @Override - public Double getAvgIntensityByUserId(String userId) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(EmotionRecord::getUserId, userId) - .eq(EmotionRecord::getIsDeleted, 0); - - List records = this.list(wrapper); - if (records.isEmpty()) { - return 0.0; - } - - double sum = records.stream() - .mapToDouble(record -> record.getIntensity().doubleValue()) - .sum(); - - return sum / records.size(); - } - - @Override - public Double getAvgIntensityByUserIdAndTimeRange(String userId, LocalDateTime startTime, LocalDateTime endTime) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(EmotionRecord::getUserId, userId) - .between(EmotionRecord::getCreateTime, startTime, endTime) - .eq(EmotionRecord::getIsDeleted, 0); - - List records = this.list(wrapper); - if (records.isEmpty()) { - return 0.0; - } - - double sum = records.stream() - .mapToDouble(record -> record.getIntensity().doubleValue()) - .sum(); - - return sum / records.size(); - } - - @Override - public String getMostFrequentEmotionByUserId(String userId) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(EmotionRecord::getUserId, userId) - .eq(EmotionRecord::getIsDeleted, 0); - - List records = this.list(wrapper); - if (records.isEmpty()) { - return null; - } - - return records.stream() - .collect(Collectors.groupingBy(EmotionRecord::getEmotionType, Collectors.counting())) - .entrySet() - .stream() - .max(Map.Entry.comparingByValue()) - .map(Map.Entry::getKey) - .orElse(null); - } - - @Override - public List getHighIntensityRecords(Double minIntensity) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.ge(EmotionRecord::getIntensity, BigDecimal.valueOf(minIntensity)) - .eq(EmotionRecord::getIsDeleted, 0) - .orderByDesc(EmotionRecord::getIntensity); - return this.list(wrapper); - } - - @Override - public List getByTrigger(String trigger) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.like(EmotionRecord::getTriggers, trigger) - .eq(EmotionRecord::getIsDeleted, 0) - .orderByDesc(EmotionRecord::getCreateTime); - return this.list(wrapper); - } - - @Override - public List getByLocation(String location) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(EmotionRecord::getLocation, location) - .eq(EmotionRecord::getIsDeleted, 0) - .orderByDesc(EmotionRecord::getCreateTime); - return this.list(wrapper); - } - @Override public EmotionRecord createEmotionRecord(String userId, String emotionType, Double intensity, String trigger, String location, String notes) { @@ -250,18 +84,6 @@ public class EmotionRecordServiceImpl extends ServiceImpl getByUserIdWithPage(String userId, Integer current, Integer size) { - Page page = new Page<>(current, size); - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - - wrapper.eq(EmotionRecord::getUserId, userId) - .eq(EmotionRecord::getIsDeleted, 0) - .orderByDesc(EmotionRecord::getCreateTime); - - return this.page(page, wrapper); - } - // 新增的方法实现 @Override @@ -457,14 +279,6 @@ public class EmotionRecordServiceImpl extends ServiceImpl getRecentByUserIdWithResponse(String userId, Integer limit) { - List records = getRecentByUserId(userId, limit); - return records.stream() - .map(this::convertToResponse) - .collect(Collectors.toList()); - } - /** * 转换为响应对象 */ diff --git a/backend-single/src/main/java/com/emotion/service/impl/GrowthTopicServiceImpl.java b/backend-single/src/main/java/com/emotion/service/impl/GrowthTopicServiceImpl.java index 4a297fa..3db2e85 100644 --- a/backend-single/src/main/java/com/emotion/service/impl/GrowthTopicServiceImpl.java +++ b/backend-single/src/main/java/com/emotion/service/impl/GrowthTopicServiceImpl.java @@ -5,9 +5,14 @@ import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.emotion.common.BasePageRequest; +import com.emotion.common.PageResult; +import com.emotion.dto.request.growth.GrowthTopicCreateRequest; +import com.emotion.dto.request.growth.GrowthTopicUpdateRequest; +import com.emotion.dto.response.growth.GrowthTopicResponse; import com.emotion.entity.GrowthTopic; import com.emotion.mapper.GrowthTopicMapper; import com.emotion.service.GrowthTopicService; +import org.springframework.beans.BeanUtils; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; @@ -15,12 +20,13 @@ import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.Collections; import java.util.List; +import java.util.stream.Collectors; /** * 成长话题服务实现类 * * @author emotion-museum - * @date 2025-07-24 + * @date 2025-09-08 */ @Service public class GrowthTopicServiceImpl extends ServiceImpl implements GrowthTopicService { @@ -53,149 +59,31 @@ public class GrowthTopicServiceImpl extends ServiceImpl getByCategory(String category) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(GrowthTopic::getCategory, category) - .eq(GrowthTopic::getIsDeleted, 0) - .orderByDesc(GrowthTopic::getCreateTime); - return this.list(wrapper); + public PageResult getPageWithResponse(BasePageRequest request) { + IPage page = getPage(request); + List responses = page.getRecords().stream() + .map(this::convertToResponse) + .collect(Collectors.toList()); + PageResult pageResult = new PageResult<>(); + pageResult.setRecords(responses); + pageResult.setCurrent(page.getCurrent()); + pageResult.setSize(page.getSize()); + pageResult.setTotal(page.getTotal()); + pageResult.setPages(page.getPages()); + return pageResult; } @Override - public List getByDifficultyLevel(String difficultyLevel) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(GrowthTopic::getDifficulty, difficultyLevel) - .eq(GrowthTopic::getIsDeleted, 0) - .orderByDesc(GrowthTopic::getCreateTime); - return this.list(wrapper); + public GrowthTopicResponse getGrowthTopicResponseById(String id) { + GrowthTopic topic = this.getById(id); + if (topic == null || topic.getIsDeleted() == 1) { + return null; + } + return convertToResponse(topic); } @Override - public List getByStatus(String status) { - // GrowthTopic实体中没有status字段,暂时返回空列表 - return Collections.emptyList(); - } - - @Override - public List getRecommendedTopics(Integer limit) { - // GrowthTopic实体中没有isRecommended字段,暂时返回最新话题 - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(GrowthTopic::getIsDeleted, 0) - .orderByDesc(GrowthTopic::getCreateTime) - .last("LIMIT " + limit); - return this.list(wrapper); - } - - @Override - public List getPopularTopics(Integer limit) { - // GrowthTopic实体中没有participantCount字段,暂时返回最新话题 - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(GrowthTopic::getIsDeleted, 0) - .orderByDesc(GrowthTopic::getCreateTime) - .last("LIMIT " + limit); - return this.list(wrapper); - } - - @Override - public List getLatestTopics(Integer limit) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(GrowthTopic::getIsDeleted, 0) - .orderByDesc(GrowthTopic::getCreateTime) - .last("LIMIT " + limit); - return this.list(wrapper); - } - - @Override - public List getByParticipantRange(Integer minParticipants, Integer maxParticipants) { - // GrowthTopic实体中没有participantCount字段,暂时返回空列表 - return Collections.emptyList(); - } - - @Override - public List getByTimeRange(LocalDateTime startTime, LocalDateTime endTime) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.between(GrowthTopic::getCreateTime, startTime, endTime) - .eq(GrowthTopic::getIsDeleted, 0) - .orderByDesc(GrowthTopic::getCreateTime); - return this.list(wrapper); - } - - @Override - public Long countByCategory(String category) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(GrowthTopic::getCategory, category) - .eq(GrowthTopic::getIsDeleted, 0); - return this.count(wrapper); - } - - @Override - public Long countByStatus(String status) { - // GrowthTopic实体中没有status字段,暂时返回0 - return 0L; - } - - @Override - public Long countByDifficultyLevel(String difficultyLevel) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(GrowthTopic::getDifficulty, difficultyLevel) - .eq(GrowthTopic::getIsDeleted, 0); - return this.count(wrapper); - } - - @Override - public Double getAvgParticipantCount() { - // 这里需要自定义SQL查询平均值,暂时返回0 - return 0.0; - } - - @Override - public Double getAvgParticipantCountByCategory(String category) { - // 这里需要自定义SQL查询平均值,暂时返回0 - return 0.0; - } - - @Override - public List searchByTags(String tags) { - // GrowthTopic实体中没有tags字段,暂时返回空列表 - return Collections.emptyList(); - } - - @Override - public List searchByKeyword(String keyword) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.and(w -> w.like(GrowthTopic::getTitle, keyword) - .or().like(GrowthTopic::getDescription, keyword)) - .eq(GrowthTopic::getIsDeleted, 0) - .orderByDesc(GrowthTopic::getCreateTime); - return this.list(wrapper); - } - - @Override - public boolean updateParticipantCount(String id, Integer increment) { - // GrowthTopic实体中没有participantCount字段,暂时返回false - return false; - } - - @Override - public boolean updateStatus(String id, String status) { - // GrowthTopic实体中没有status字段,暂时返回false - return false; - } - - @Override - public List getEndingSoonTopics(Integer days) { - // GrowthTopic实体中没有endTime字段,暂时返回空列表 - return Collections.emptyList(); - } - - @Override - public List getLongTermTopics() { - // GrowthTopic实体中没有endTime字段,暂时返回空列表 - return Collections.emptyList(); - } - - @Override - public GrowthTopic createGrowthTopic(String title, String description, String category, + public GrowthTopic createGrowthTopic(String title, String description, String category, String difficultyLevel, String tags, LocalDateTime endTime) { GrowthTopic topic = new GrowthTopic(); topic.setTitle(title); @@ -211,4 +99,80 @@ public class GrowthTopicServiceImpl extends ServiceImpl implements GuestUserService { @@ -37,6 +43,30 @@ public class GuestUserServiceImpl extends ServiceImpl getPageWithResponse(BasePageRequest request) { + IPage page = getPage(request); + List responses = page.getRecords().stream() + .map(this::convertToResponse) + .collect(Collectors.toList()); + PageResult pageResult = new PageResult<>(); + pageResult.setRecords(responses); + pageResult.setCurrent(page.getCurrent()); + pageResult.setSize(page.getSize()); + pageResult.setTotal(page.getTotal()); + pageResult.setPages(page.getPages()); + return pageResult; + } + + @Override + public GuestUserResponse getGuestUserResponseById(String id) { + GuestUser guestUser = this.getById(id); + if (guestUser == null || guestUser.getIsDeleted() == 1) { + return null; + } + return convertToResponse(guestUser); + } + @Override public GuestUser getByDeviceId(String deviceId) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); @@ -219,4 +249,68 @@ public class GuestUserServiceImpl extends ServiceImpl impl return this.page(page, wrapper); } + @Override + public PageResult getPageWithResponse(MessagePageRequest request) { + // 从上下文中获取当前用户ID + String userId = CurrentUserUtil.requireCurrentUserId(); + + // 调用用户消息分页查询方法 + PageResult pageResult = getUserMessagesWithPage(request); + return pageResult; + } + @Override public IPage getPageByConversationId(BasePageRequest request, String conversationId) { Page page = new Page<>(request.getCurrent(), request.getSize()); @@ -218,18 +228,13 @@ public class MessageServiceImpl extends ServiceImpl impl @Override public PageResult getUserMessagesWithPage(MessagePageRequest request) { - log.info("获取用户消息分页: current={}, size={}", request.getCurrent(), request.getSize()); - // 从上下文中获取当前用户ID String userId = CurrentUserUtil.requireCurrentUserId(); - log.info("当前用户ID: {}", userId); // 调用原有的分页查询方法 IPage page = getByUserIdWithPage(userId, Math.toIntExact(request.getCurrent()), Math.toIntExact(request.getSize())); - log.info("查询结果: total={}, records={}", page.getTotal(), page.getRecords().size()); - // 转换为响应对象 List responses = page.getRecords().stream() .map(this::convertToResponse) @@ -248,15 +253,11 @@ public class MessageServiceImpl extends ServiceImpl impl @Override public List searchUserMessages(MessageSearchRequest request) { - log.info("搜索用户消息: keyword={}, limit={}", request.getKeyword(), request.getLimit()); - // 从上下文中获取当前用户ID String userId = CurrentUserUtil.requireCurrentUserId(); - log.info("当前用户ID: {}", userId); // 调用原有的搜索方法 List messages = searchByUserIdAndKeyword(userId, request.getKeyword(), request.getLimit()); - log.info("搜索结果: {} 条消息", messages.size()); // 转换为响应对象 return messages.stream() @@ -266,15 +267,11 @@ public class MessageServiceImpl extends ServiceImpl impl @Override public List getUserRecentMessages(MessageRecentRequest request) { - log.info("获取用户最近消息: limit={}", request.getLimit()); - // 从上下文中获取当前用户ID String userId = CurrentUserUtil.requireCurrentUserId(); - log.info("当前用户ID: {}", userId); // 调用原有的获取最近消息方法 List messages = getRecentByUserId(userId, request.getLimit()); - log.info("查询结果: {} 条最近消息", messages.size()); // 转换为响应对象 return messages.stream() @@ -284,11 +281,8 @@ public class MessageServiceImpl extends ServiceImpl impl @Override public MessageResponse createMessageFromRequest(MessageCreateRequest request) { - log.info("根据请求创建消息: conversationId={}", request.getConversationId()); - // 从上下文中获取当前用户ID String userId = CurrentUserUtil.requireCurrentUserId(); - log.info("当前用户ID: {}", userId); // 构建消息对象 Message message = new Message(); @@ -300,7 +294,6 @@ public class MessageServiceImpl extends ServiceImpl impl // 调用原有的创建方法 Message savedMessage = createMessage(message); - log.info("创建消息成功: messageId={}", savedMessage.getId()); // 转换为响应对象 return convertToResponse(savedMessage); @@ -308,11 +301,8 @@ public class MessageServiceImpl extends ServiceImpl impl @Override public MessageResponse getMessageById(String id) { - log.info("根据ID获取消息: id={}", id); - Message message = getById(id); if (message == null) { - log.warn("消息不存在: id={}", id); return null; } @@ -320,6 +310,95 @@ public class MessageServiceImpl extends ServiceImpl impl return convertToResponse(message); } + @Override + public PageResult searchWithResponse(MessageSearchRequest request) { + // 从上下文中获取当前用户ID + String userId = CurrentUserUtil.requireCurrentUserId(); + + // 构建分页对象 + Page page = new Page<>(1L, request.getLimit().longValue()); + + // 调用搜索方法 + List messages = searchByUserIdAndKeyword(userId, request.getKeyword(), request.getLimit()); + + // 设置分页信息 + page.setRecords(messages); + page.setTotal(messages.size()); + + // 转换为响应对象 + List responses = messages.stream() + .map(this::convertToResponse) + .collect(Collectors.toList()); + + // 构建分页结果 + PageResult pageResult = new PageResult<>(); + pageResult.setRecords(responses); + pageResult.setCurrent(page.getCurrent()); + pageResult.setSize(page.getSize()); + pageResult.setTotal(page.getTotal()); + pageResult.setPages(page.getPages()); + + return pageResult; + } + + @Override + public PageResult getRecentWithResponse(MessageRecentRequest request) { + // 从上下文中获取当前用户ID + String userId = CurrentUserUtil.requireCurrentUserId(); + + // 构建分页对象 + Page page = new Page<>(1L, request.getLimit().longValue()); + + // 调用获取最近消息方法 + List messages = getRecentByUserId(userId, request.getLimit()); + + // 设置分页信息 + page.setRecords(messages); + page.setTotal(messages.size()); + + // 转换为响应对象 + List responses = messages.stream() + .map(this::convertToResponse) + .collect(Collectors.toList()); + + // 构建分页结果 + PageResult pageResult = new PageResult<>(); + pageResult.setRecords(responses); + pageResult.setCurrent(page.getCurrent()); + pageResult.setSize(page.getSize()); + pageResult.setTotal(page.getTotal()); + pageResult.setPages(page.getPages()); + + return pageResult; + } + + @Override + public MessageResponse updateMessage(String id, String content) { + Message message = this.getById(id); + if (message == null || message.getIsDeleted() == 1) { + return null; + } + + // 更新内容 + message.setContent(content); + this.updateById(message); + + // 转换为响应对象 + return convertToResponse(message); + } + + @Override + public boolean deleteMessage(String id) { + Message message = this.getById(id); + if (message == null || message.getIsDeleted() == 1) { + return false; + } + + // 逻辑删除 + message.setIsDeleted(1); + return this.updateById(message); + } + /** * 转换为响应对象 */ diff --git a/backend-single/src/main/java/com/emotion/service/impl/RewardServiceImpl.java b/backend-single/src/main/java/com/emotion/service/impl/RewardServiceImpl.java index 526e263..7263c0d 100644 --- a/backend-single/src/main/java/com/emotion/service/impl/RewardServiceImpl.java +++ b/backend-single/src/main/java/com/emotion/service/impl/RewardServiceImpl.java @@ -6,21 +6,27 @@ import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.emotion.common.BasePageRequest; +import com.emotion.common.PageResult; +import com.emotion.dto.request.reward.RewardCreateRequest; +import com.emotion.dto.request.reward.RewardUpdateRequest; +import com.emotion.dto.response.reward.RewardResponse; import com.emotion.entity.Reward; import com.emotion.mapper.RewardMapper; import com.emotion.service.RewardService; +import org.springframework.beans.BeanUtils; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; import java.time.LocalDateTime; -import java.util.List; import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; /** * 奖励服务实现类 * * @author emotion-museum - * @date 2025-07-24 + * @date 2025-09-08 */ @Service public class RewardServiceImpl extends ServiceImpl implements RewardService { @@ -52,6 +58,21 @@ public class RewardServiceImpl extends ServiceImpl impleme return this.page(page, wrapper); } + @Override + public PageResult getPageWithResponse(BasePageRequest request) { + IPage page = getPage(request); + List responses = page.getRecords().stream() + .map(this::convertToResponse) + .collect(Collectors.toList()); + PageResult pageResult = new PageResult<>(); + pageResult.setRecords(responses); + pageResult.setCurrent(page.getCurrent()); + pageResult.setSize(page.getSize()); + pageResult.setTotal(page.getTotal()); + pageResult.setPages(page.getPages()); + return pageResult; + } + @Override public IPage getPageByUserId(BasePageRequest request, String userId) { Page page = new Page<>(request.getCurrent(), request.getSize()); @@ -62,6 +83,15 @@ public class RewardServiceImpl extends ServiceImpl impleme return this.page(page, wrapper); } + @Override + public RewardResponse getRewardResponseById(String id) { + Reward reward = this.getById(id); + if (reward == null || reward.getIsDeleted() == 1) { + return null; + } + return convertToResponse(reward); + } + @Override public List getByUserId(String userId) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); @@ -223,12 +253,17 @@ public class RewardServiceImpl extends ServiceImpl impleme } @Override - public Reward createReward(String userId, String rewardType, Integer points, String source, - String description, LocalDateTime expiredTime) { + public Reward createReward(String userId, String rewardType, String value, + String description, String topicId, String achievementId, String icon, String rarity) { Reward reward = new Reward(); reward.setType(rewardType); reward.setName(rewardType + "奖励"); + reward.setValue(value); reward.setDescription(description); + reward.setTopicId(topicId); + reward.setAchievementId(achievementId); + reward.setIcon(icon); + reward.setRarity(rarity); reward.setCreateBy(userId); reward.setEarnedTime(LocalDateTime.now()); reward.setIsNew(1); @@ -236,4 +271,87 @@ public class RewardServiceImpl extends ServiceImpl impleme this.save(reward); return reward; } + + @Override + public RewardResponse createRewardWithResponse(RewardCreateRequest request) { + Reward reward = createReward( + request.getUserId(), + request.getRewardType(), + request.getValue(), + request.getDescription(), + request.getTopicId(), + request.getAchievementId(), + request.getIcon(), + request.getRarity()); + return convertToResponse(reward); + } + + @Override + public RewardResponse updateRewardWithResponse(RewardUpdateRequest request) { + Reward reward = this.getById(request.getId()); + if (reward == null || reward.getIsDeleted() == 1) { + return null; + } + + // 只更新非空字段 + if (StringUtils.hasText(request.getRewardType())) { + reward.setType(request.getRewardType()); + } + if (StringUtils.hasText(request.getValue())) { + reward.setValue(request.getValue()); + } + if (StringUtils.hasText(request.getDescription())) { + reward.setDescription(request.getDescription()); + } + if (StringUtils.hasText(request.getTopicId())) { + reward.setTopicId(request.getTopicId()); + } + if (StringUtils.hasText(request.getAchievementId())) { + reward.setAchievementId(request.getAchievementId()); + } + if (StringUtils.hasText(request.getIcon())) { + reward.setIcon(request.getIcon()); + } + if (StringUtils.hasText(request.getRarity())) { + reward.setRarity(request.getRarity()); + } + if (request.getIsNew() != null) { + reward.setIsNew(request.getIsNew()); + } + + this.updateById(reward); + return convertToResponse(reward); + } + + @Override + public boolean deleteReward(String id) { + Reward reward = this.getById(id); + if (reward == null || reward.getIsDeleted() == 1) { + return false; + } + + // 逻辑删除 + reward.setIsDeleted(1); + return this.updateById(reward); + } + + /** + * 将实体转换为响应对象 + */ + private RewardResponse convertToResponse(Reward reward) { + if (reward == null) { + return null; + } + + RewardResponse response = new RewardResponse(); + BeanUtils.copyProperties(reward, response); + response.setId(reward.getId()); + if (reward.getCreateTime() != null) { + response.setCreateTime(reward.getCreateTime().toString()); + } + if (reward.getUpdateTime() != null) { + response.setUpdateTime(reward.getUpdateTime().toString()); + } + return response; + } } \ No newline at end of file diff --git a/backend-single/src/main/java/com/emotion/service/impl/TopicInteractionServiceImpl.java b/backend-single/src/main/java/com/emotion/service/impl/TopicInteractionServiceImpl.java index bdbca91..293fb12 100644 --- a/backend-single/src/main/java/com/emotion/service/impl/TopicInteractionServiceImpl.java +++ b/backend-single/src/main/java/com/emotion/service/impl/TopicInteractionServiceImpl.java @@ -1,19 +1,21 @@ package com.emotion.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import com.emotion.common.BasePageRequest; +import com.emotion.common.PageResult; +import com.emotion.dto.request.TopicInteractionCreateRequest; +import com.emotion.dto.request.TopicInteractionPageRequest; +import com.emotion.dto.request.TopicInteractionUpdateRequest; +import com.emotion.dto.response.TopicInteractionResponse; import com.emotion.entity.TopicInteraction; import com.emotion.mapper.TopicInteractionMapper; import com.emotion.service.TopicInteractionService; +import org.springframework.beans.BeanUtils; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; -import java.time.LocalDateTime; -import java.util.List; -import java.util.Collections; +import java.time.format.DateTimeFormatter; /** * 话题互动服务实现类 @@ -24,257 +26,138 @@ import java.util.Collections; @Service public class TopicInteractionServiceImpl extends ServiceImpl implements TopicInteractionService { + private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + @Override - public IPage getPage(BasePageRequest request) { + public PageResult getPageWithResponse(TopicInteractionPageRequest request) { Page page = new Page<>(request.getCurrent(), request.getSize()); LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + // 根据关键词查询 if (StringUtils.hasText(request.getKeyword())) { wrapper.and(w -> w.like(TopicInteraction::getContent, request.getKeyword()) .or().like(TopicInteraction::getUserInput, request.getKeyword()) .or().like(TopicInteraction::getAiResponse, request.getKeyword())); } + // 根据话题ID查询 + if (StringUtils.hasText(request.getTopicId())) { + wrapper.eq(TopicInteraction::getTopicId, request.getTopicId()); + } + + // 根据用户ID查询 + if (StringUtils.hasText(request.getUserId())) { + wrapper.eq(TopicInteraction::getCreateBy, request.getUserId()); + } + + // 根据互动类型查询 + if (StringUtils.hasText(request.getInteractionType())) { + wrapper.eq(TopicInteraction::getType, request.getInteractionType()); + } + wrapper.eq(TopicInteraction::getIsDeleted, 0).orderByDesc(TopicInteraction::getCreateTime); - return this.page(page, wrapper); + Page resultPage = this.page(page, wrapper); + + // 转换为响应对象 + PageResult pageResult = new PageResult<>(); + pageResult.setCurrent(resultPage.getCurrent()); + pageResult.setSize(resultPage.getSize()); + pageResult.setTotal(resultPage.getTotal()); + pageResult.setPages(resultPage.getPages()); + pageResult.setRecords(resultPage.getRecords().stream() + .map(this::convertToResponse) + .toList()); + + return pageResult; } @Override - public IPage getPageByTopicId(BasePageRequest request, String topicId) { - Page page = new Page<>(request.getCurrent(), request.getSize()); - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(TopicInteraction::getTopicId, topicId) - .eq(TopicInteraction::getIsDeleted, 0) - .orderByDesc(TopicInteraction::getCreateTime); - return this.page(page, wrapper); + public TopicInteractionResponse getTopicInteractionResponseById(String id) { + TopicInteraction topicInteraction = this.getById(id); + if (topicInteraction == null || topicInteraction.getIsDeleted() == 1) { + return null; + } + return convertToResponse(topicInteraction); } @Override - public IPage getPageByUserId(BasePageRequest request, String userId) { - Page page = new Page<>(request.getCurrent(), request.getSize()); - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(TopicInteraction::getCreateBy, userId) - .eq(TopicInteraction::getIsDeleted, 0) - .orderByDesc(TopicInteraction::getCreateTime); - return this.page(page, wrapper); + public TopicInteractionResponse createTopicInteractionWithResponse(TopicInteractionCreateRequest request) { + TopicInteraction topicInteraction = new TopicInteraction(); + BeanUtils.copyProperties(request, topicInteraction); + // 设置用户ID为当前登录用户 + topicInteraction.setCreateBy(getCurrentUserId()); + this.save(topicInteraction); + return convertToResponse(topicInteraction); } @Override - public List getByTopicId(String topicId) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(TopicInteraction::getTopicId, topicId) - .eq(TopicInteraction::getIsDeleted, 0) - .orderByDesc(TopicInteraction::getCreateTime); - return this.list(wrapper); + public TopicInteractionResponse updateTopicInteractionWithResponse(TopicInteractionUpdateRequest request) { + TopicInteraction topicInteraction = this.getById(request.getId()); + if (topicInteraction == null || topicInteraction.getIsDeleted() == 1) { + return null; + } + + // 只更新非空字段 + if (StringUtils.hasText(request.getTopicId())) { + topicInteraction.setTopicId(request.getTopicId()); + } + if (StringUtils.hasText(request.getInteractionType())) { + topicInteraction.setType(request.getInteractionType()); + } + if (StringUtils.hasText(request.getContent())) { + topicInteraction.setContent(request.getContent()); + } + if (StringUtils.hasText(request.getUserInput())) { + topicInteraction.setUserInput(request.getUserInput()); + } + if (StringUtils.hasText(request.getAiResponse())) { + topicInteraction.setAiResponse(request.getAiResponse()); + } + if (request.getRating() != null) { + topicInteraction.setRating(request.getRating()); + } + if (StringUtils.hasText(request.getFeedback())) { + topicInteraction.setFeedback(request.getFeedback()); + } + + this.updateById(topicInteraction); + return convertToResponse(topicInteraction); } @Override - public List getByUserId(String userId) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(TopicInteraction::getCreateBy, userId) - .eq(TopicInteraction::getIsDeleted, 0) - .orderByDesc(TopicInteraction::getCreateTime); - return this.list(wrapper); + public boolean deleteTopicInteraction(String id) { + TopicInteraction topicInteraction = this.getById(id); + if (topicInteraction == null || topicInteraction.getIsDeleted() == 1) { + return false; + } + topicInteraction.setIsDeleted(1); + return this.updateById(topicInteraction); } - @Override - public List getByInteractionType(String interactionType) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(TopicInteraction::getType, interactionType) - .eq(TopicInteraction::getIsDeleted, 0) - .orderByDesc(TopicInteraction::getCreateTime); - return this.list(wrapper); + /** + * 将实体对象转换为响应对象 + */ + private TopicInteractionResponse convertToResponse(TopicInteraction topicInteraction) { + if (topicInteraction == null) { + return null; + } + TopicInteractionResponse response = new TopicInteractionResponse(); + BeanUtils.copyProperties(topicInteraction, response); + response.setId(topicInteraction.getId()); + if (topicInteraction.getCreateTime() != null) { + response.setCreateTime(topicInteraction.getCreateTime().format(FORMATTER)); + } + if (topicInteraction.getUpdateTime() != null) { + response.setUpdateTime(topicInteraction.getUpdateTime().format(FORMATTER)); + } + return response; } - @Override - public List getByTopicIdAndInteractionType(String topicId, String interactionType) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(TopicInteraction::getTopicId, topicId) - .eq(TopicInteraction::getType, interactionType) - .eq(TopicInteraction::getIsDeleted, 0) - .orderByDesc(TopicInteraction::getCreateTime); - return this.list(wrapper); - } - - @Override - public List getByUserIdAndInteractionType(String userId, String interactionType) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(TopicInteraction::getCreateBy, userId) - .eq(TopicInteraction::getType, interactionType) - .eq(TopicInteraction::getIsDeleted, 0) - .orderByDesc(TopicInteraction::getCreateTime); - return this.list(wrapper); - } - - @Override - public List getByTopicIdAndUserId(String topicId, String userId) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(TopicInteraction::getTopicId, topicId) - .eq(TopicInteraction::getCreateBy, userId) - .eq(TopicInteraction::getIsDeleted, 0) - .orderByDesc(TopicInteraction::getCreateTime); - return this.list(wrapper); - } - - @Override - public List getByTimeRange(LocalDateTime startTime, LocalDateTime endTime) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.between(TopicInteraction::getCreateTime, startTime, endTime) - .eq(TopicInteraction::getIsDeleted, 0) - .orderByDesc(TopicInteraction::getCreateTime); - return this.list(wrapper); - } - - @Override - public Long countByTopicId(String topicId) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(TopicInteraction::getTopicId, topicId) - .eq(TopicInteraction::getIsDeleted, 0); - return this.count(wrapper); - } - - @Override - public Long countByUserId(String userId) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(TopicInteraction::getCreateBy, userId) - .eq(TopicInteraction::getIsDeleted, 0); - return this.count(wrapper); - } - - @Override - public Long countByInteractionType(String interactionType) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(TopicInteraction::getType, interactionType) - .eq(TopicInteraction::getIsDeleted, 0); - return this.count(wrapper); - } - - @Override - public Long countByTopicIdAndInteractionType(String topicId, String interactionType) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(TopicInteraction::getTopicId, topicId) - .eq(TopicInteraction::getType, interactionType) - .eq(TopicInteraction::getIsDeleted, 0); - return this.count(wrapper); - } - - @Override - public Long countByUserIdAndInteractionType(String userId, String interactionType) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(TopicInteraction::getCreateBy, userId) - .eq(TopicInteraction::getType, interactionType) - .eq(TopicInteraction::getIsDeleted, 0); - return this.count(wrapper); - } - - @Override - public List getRecentByTopicId(String topicId, Integer limit) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(TopicInteraction::getTopicId, topicId) - .eq(TopicInteraction::getIsDeleted, 0) - .orderByDesc(TopicInteraction::getCreateTime) - .last("LIMIT " + limit); - return this.list(wrapper); - } - - @Override - public List getRecentByUserId(String userId, Integer limit) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(TopicInteraction::getCreateBy, userId) - .eq(TopicInteraction::getIsDeleted, 0) - .orderByDesc(TopicInteraction::getCreateTime) - .last("LIMIT " + limit); - return this.list(wrapper); - } - - @Override - public List getPopularInteractions(Integer limit) { - // TopicInteraction实体中没有likes字段,暂时返回最新互动 - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(TopicInteraction::getIsDeleted, 0) - .orderByDesc(TopicInteraction::getCreateTime) - .last("LIMIT " + limit); - return this.list(wrapper); - } - - @Override - public List getPopularInteractionsByTopicId(String topicId, Integer limit) { - // TopicInteraction实体中没有likes字段,暂时返回最新互动 - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(TopicInteraction::getTopicId, topicId) - .eq(TopicInteraction::getIsDeleted, 0) - .orderByDesc(TopicInteraction::getCreateTime) - .last("LIMIT " + limit); - return this.list(wrapper); - } - - @Override - public List getByLikesRange(Integer minLikes, Integer maxLikes) { - // TopicInteraction实体中没有likes字段,暂时返回空列表 - return Collections.emptyList(); - } - - @Override - public boolean hasUserInteracted(String topicId, String userId) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(TopicInteraction::getTopicId, topicId) - .eq(TopicInteraction::getCreateBy, userId) - .eq(TopicInteraction::getIsDeleted, 0); - return this.count(wrapper) > 0; - } - - @Override - public TopicInteraction getUserInteractionByType(String topicId, String userId, String interactionType) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(TopicInteraction::getTopicId, topicId) - .eq(TopicInteraction::getCreateBy, userId) - .eq(TopicInteraction::getType, interactionType) - .eq(TopicInteraction::getIsDeleted, 0) - .orderByDesc(TopicInteraction::getCreateTime) - .last("LIMIT 1"); - return this.getOne(wrapper); - } - - @Override - public boolean updateLikes(String id, Integer increment) { - // TopicInteraction实体中没有likes字段,暂时返回false - return false; - } - - @Override - public List searchByContent(String keyword) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.and(w -> w.like(TopicInteraction::getContent, keyword) - .or().like(TopicInteraction::getUserInput, keyword) - .or().like(TopicInteraction::getAiResponse, keyword)) - .eq(TopicInteraction::getIsDeleted, 0) - .orderByDesc(TopicInteraction::getCreateTime); - return this.list(wrapper); - } - - @Override - public List searchByTopicIdAndContent(String topicId, String keyword) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(TopicInteraction::getTopicId, topicId) - .and(w -> w.like(TopicInteraction::getContent, keyword) - .or().like(TopicInteraction::getUserInput, keyword) - .or().like(TopicInteraction::getAiResponse, keyword)) - .eq(TopicInteraction::getIsDeleted, 0) - .orderByDesc(TopicInteraction::getCreateTime); - return this.list(wrapper); - } - - @Override - public TopicInteraction createTopicInteraction(String topicId, String userId, String interactionType, - String content, String attachments) { - TopicInteraction interaction = new TopicInteraction(); - interaction.setTopicId(topicId); - interaction.setType(interactionType); - interaction.setContent(content); - interaction.setUserInput(content); - interaction.setCreateBy(userId); - - this.save(interaction); - return interaction; + /** + * 获取当前登录用户ID(模拟实现) + */ + private String getCurrentUserId() { + // 实际项目中应从token中获取用户ID + return "current_user_id"; } } \ No newline at end of file diff --git a/backend-single/src/main/java/com/emotion/service/impl/UserServiceImpl.java b/backend-single/src/main/java/com/emotion/service/impl/UserServiceImpl.java index 70494a0..8c630c8 100644 --- a/backend-single/src/main/java/com/emotion/service/impl/UserServiceImpl.java +++ b/backend-single/src/main/java/com/emotion/service/impl/UserServiceImpl.java @@ -1,19 +1,27 @@ package com.emotion.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import com.emotion.common.BasePageRequest; +import com.emotion.common.PageResult; +import com.emotion.dto.request.UserCreateRequest; +import com.emotion.dto.request.UserPageRequest; +import com.emotion.dto.request.UserUpdateRequest; +import com.emotion.dto.request.UserProfileUpdateRequest; +import com.emotion.dto.response.UserResponse; import com.emotion.entity.User; import com.emotion.mapper.UserMapper; import com.emotion.service.UserService; +import com.emotion.util.UserContextHolder; +import org.springframework.beans.BeanUtils; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; import java.util.List; +import java.util.stream.Collectors; /** * 用户服务实现类 @@ -26,12 +34,14 @@ public class UserServiceImpl extends ServiceImpl implements Us private final PasswordEncoder passwordEncoder; + private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + public UserServiceImpl(PasswordEncoder passwordEncoder) { this.passwordEncoder = passwordEncoder; } @Override - public IPage getPage(BasePageRequest request) { + public PageResult getPageWithResponse(UserPageRequest request) { Page page = new Page<>(request.getCurrent(), request.getSize()); LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); @@ -42,6 +52,36 @@ public class UserServiceImpl extends ServiceImpl implements Us .or().like(User::getEmail, request.getKeyword())); } + // 账号查询 + if (StringUtils.hasText(request.getAccount())) { + wrapper.eq(User::getAccount, request.getAccount()); + } + + // 用户名查询 + if (StringUtils.hasText(request.getUsername())) { + wrapper.like(User::getUsername, request.getUsername()); + } + + // 邮箱查询 + if (StringUtils.hasText(request.getEmail())) { + wrapper.eq(User::getEmail, request.getEmail()); + } + + // 手机号查询 + if (StringUtils.hasText(request.getPhone())) { + wrapper.eq(User::getPhone, request.getPhone()); + } + + // 状态查询 + if (request.getStatus() != null) { + wrapper.eq(User::getStatus, request.getStatus()); + } + + // 会员等级查询 + if (StringUtils.hasText(request.getMemberLevel())) { + wrapper.eq(User::getMemberLevel, request.getMemberLevel()); + } + wrapper.eq(User::getIsDeleted, 0); // 排序 @@ -55,160 +95,172 @@ public class UserServiceImpl extends ServiceImpl implements Us wrapper.orderByDesc(User::getCreateTime); } - return this.page(page, wrapper); + Page resultPage = this.page(page, wrapper); + List userResponses = resultPage.getRecords().stream() + .map(this::convertToResponse) + .collect(Collectors.toList()); + + PageResult pageResult = new PageResult<>(); + pageResult.setCurrent(resultPage.getCurrent()); + pageResult.setSize(resultPage.getSize()); + pageResult.setTotal(resultPage.getTotal()); + pageResult.setPages(resultPage.getPages()); + pageResult.setRecords(userResponses); + + return pageResult; } @Override - public User getByAccount(String account) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(User::getAccount, account) - .eq(User::getIsDeleted, 0); - return this.getOne(wrapper); + public UserResponse getUserResponseById(String id) { + User user = this.getById(id); + if (user == null || user.getIsDeleted() == 1) { + return null; + } + return convertToResponse(user); } @Override - public User getByUsername(String username) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(User::getUsername, username) - .eq(User::getIsDeleted, 0); - return this.getOne(wrapper); - } - - @Override - public User getByEmail(String email) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(User::getEmail, email) - .eq(User::getIsDeleted, 0); - return this.getOne(wrapper); - } - - @Override - public User getByPhone(String phone) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(User::getPhone, phone) - .eq(User::getIsDeleted, 0); - return this.getOne(wrapper); - } - - @Override - public User getByThirdParty(String thirdPartyId, String thirdPartyType) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(User::getThirdPartyId, thirdPartyId) - .eq(User::getThirdPartyType, thirdPartyType) - .eq(User::getIsDeleted, 0); - return this.getOne(wrapper); - } - - @Override - public List getByStatus(Integer status) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(User::getStatus, status) - .eq(User::getIsDeleted, 0) - .orderByDesc(User::getCreateTime); - return this.list(wrapper); - } - - @Override - public List getByMemberLevel(String memberLevel) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(User::getMemberLevel, memberLevel) - .eq(User::getIsDeleted, 0) - .orderByDesc(User::getCreateTime); - return this.list(wrapper); - } - - @Override - public List getActiveUsers(Integer days) { - LocalDateTime startTime = LocalDateTime.now().minusDays(days); - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.ge(User::getLastActiveTime, startTime) - .eq(User::getIsDeleted, 0) - .orderByDesc(User::getLastActiveTime); - return this.list(wrapper); - } - - @Override - public List getNewUsers(Integer days) { - LocalDateTime startTime = LocalDateTime.now().minusDays(days); - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.ge(User::getCreateTime, startTime) - .eq(User::getIsDeleted, 0) - .orderByDesc(User::getCreateTime); - return this.list(wrapper); - } - - @Override - public boolean updateLastActiveTime(String userId, LocalDateTime lastActiveTime) { + public UserResponse createUserWithResponse(UserCreateRequest request) { User user = new User(); - user.setId(userId); - user.setLastActiveTime(lastActiveTime); - return this.updateById(user); - } - - @Override - public boolean updateStatus(String userId, Integer status) { - User user = new User(); - user.setId(userId); - user.setStatus(status); - return this.updateById(user); - } - - @Override - public boolean updateTotalDays(String userId, Integer totalDays) { - User user = new User(); - user.setId(userId); - user.setTotalDays(totalDays); - return this.updateById(user); - } - - @Override - public Long countByStatus(Integer status) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(User::getStatus, status) - .eq(User::getIsDeleted, 0); - return this.count(wrapper); - } - - @Override - public Long countByMemberLevel(String memberLevel) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(User::getMemberLevel, memberLevel) - .eq(User::getIsDeleted, 0); - return this.count(wrapper); - } - - @Override - public User createUser(String account, String username, String password, String email, String phone) { - User user = new User(); - user.setAccount(account); - user.setUsername(username); - user.setPassword(passwordEncoder.encode(password)); - user.setEmail(email); - user.setPhone(phone); - user.setNickname(username); + user.setAccount(request.getAccount()); + user.setUsername(request.getUsername()); + user.setPassword(passwordEncoder.encode(request.getPassword())); + user.setEmail(request.getEmail()); + user.setPhone(request.getPhone()); + user.setNickname(request.getUsername()); user.setMemberLevel("free"); user.setStatus(1); user.setIsVerified(0); user.setLastActiveTime(LocalDateTime.now()); this.save(user); - return user; + return convertToResponse(user); } @Override - public boolean validatePassword(String userId, String password) { - User user = this.getById(userId); - if (user == null) { + public UserResponse updateUserWithResponse(UserUpdateRequest request) { + User user = this.getById(request.getId()); + if (user == null || user.getIsDeleted() == 1) { + return null; + } + + // 只更新非空字段 + if (StringUtils.hasText(request.getUsername())) { + user.setUsername(request.getUsername()); + } + if (StringUtils.hasText(request.getNickname())) { + user.setNickname(request.getNickname()); + } + if (StringUtils.hasText(request.getEmail())) { + user.setEmail(request.getEmail()); + } + if (StringUtils.hasText(request.getPhone())) { + user.setPhone(request.getPhone()); + } + if (StringUtils.hasText(request.getAvatar())) { + user.setAvatar(request.getAvatar()); + } + if (request.getBirthDate() != null) { + user.setBirthDate(request.getBirthDate()); + } + if (StringUtils.hasText(request.getLocation())) { + user.setLocation(request.getLocation()); + } + if (StringUtils.hasText(request.getBio())) { + user.setBio(request.getBio()); + } + if (request.getStatus() != null) { + user.setStatus(request.getStatus()); + } + if (StringUtils.hasText(request.getMemberLevel())) { + user.setMemberLevel(request.getMemberLevel()); + } + + this.updateById(user); + return convertToResponse(user); + } + + @Override + public UserResponse updateCurrentUserProfileWithResponse(UserProfileUpdateRequest request) { + // 从UserContextHolder获取当前用户ID + String currentUserId = UserContextHolder.getCurrentUserId(); + if (currentUserId == null) { + return null; + } + + User user = this.getById(currentUserId); + if (user == null || user.getIsDeleted() == 1) { + return null; + } + + // 只更新非空字段 + if (StringUtils.hasText(request.getNickname())) { + user.setNickname(request.getNickname()); + } + if (StringUtils.hasText(request.getEmail())) { + user.setEmail(request.getEmail()); + } + if (StringUtils.hasText(request.getPhone())) { + user.setPhone(request.getPhone()); + } + if (StringUtils.hasText(request.getAvatar())) { + user.setAvatar(request.getAvatar()); + } + if (request.getBirthDate() != null) { + user.setBirthDate(request.getBirthDate()); + } + if (StringUtils.hasText(request.getLocation())) { + user.setLocation(request.getLocation()); + } + if (StringUtils.hasText(request.getBio())) { + user.setBio(request.getBio()); + } + + this.updateById(user); + return convertToResponse(user); + } + + @Override + public UserResponse getCurrentUserProfileWithResponse() { + // 从UserContextHolder获取当前用户ID + String currentUserId = UserContextHolder.getCurrentUserId(); + if (currentUserId == null) { + return null; + } + + User user = this.getById(currentUserId); + if (user == null || user.getIsDeleted() == 1) { + return null; + } + return convertToResponse(user); + } + + @Override + public boolean deleteUser(String id) { + User user = this.getById(id); + if (user == null || user.getIsDeleted() == 1) { return false; } - return passwordEncoder.matches(password, user.getPassword()); - } - - @Override - public boolean updatePassword(String userId, String newPassword) { - User user = new User(); - user.setId(userId); - user.setPassword(passwordEncoder.encode(newPassword)); + user.setIsDeleted(1); return this.updateById(user); } + + /** + * 转换为响应对象 + */ + private UserResponse convertToResponse(User user) { + UserResponse response = new UserResponse(); + BeanUtils.copyProperties(user, response); + response.setId(user.getId()); + if (user.getCreateTime() != null) { + response.setCreateTime(user.getCreateTime().format(DATE_TIME_FORMATTER)); + } + if (user.getUpdateTime() != null) { + response.setUpdateTime(user.getUpdateTime().format(DATE_TIME_FORMATTER)); + } + if (user.getLastActiveTime() != null) { + response.setLastActiveTime(user.getLastActiveTime().format(DATE_TIME_FORMATTER)); + } + return response; + } } \ No newline at end of file diff --git a/backend-single/src/main/java/com/emotion/service/impl/UserStatsServiceImpl.java b/backend-single/src/main/java/com/emotion/service/impl/UserStatsServiceImpl.java index 00b3c86..a7a6e17 100644 --- a/backend-single/src/main/java/com/emotion/service/impl/UserStatsServiceImpl.java +++ b/backend-single/src/main/java/com/emotion/service/impl/UserStatsServiceImpl.java @@ -1,19 +1,27 @@ package com.emotion.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import com.emotion.common.BasePageRequest; +import com.emotion.common.PageResult; +import com.emotion.dto.request.UserStatsCreateRequest; +import com.emotion.dto.request.UserStatsIncrementRequest; +import com.emotion.dto.request.UserStatsPageRequest; +import com.emotion.dto.request.UserStatsUpdateValueRequest; +import com.emotion.dto.response.UserStatsResponse; import com.emotion.entity.UserStats; import com.emotion.mapper.UserStatsMapper; import com.emotion.service.UserStatsService; +import com.emotion.util.SnowflakeIdGenerator; +import org.springframework.beans.BeanUtils; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; import java.util.List; -import java.util.Collections; +import java.util.stream.Collectors; /** * 用户统计服务实现类 @@ -24,193 +32,164 @@ import java.util.Collections; @Service public class UserStatsServiceImpl extends ServiceImpl implements UserStatsService { + private final SnowflakeIdGenerator snowflakeIdGenerator; + + private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + + public UserStatsServiceImpl(SnowflakeIdGenerator snowflakeIdGenerator) { + this.snowflakeIdGenerator = snowflakeIdGenerator; + } + @Override - public IPage getPage(BasePageRequest request) { + public PageResult getPageWithResponse(UserStatsPageRequest request) { Page page = new Page<>(request.getCurrent(), request.getSize()); LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - + + // 关键词搜索 if (StringUtils.hasText(request.getKeyword())) { - wrapper.like(UserStats::getUserId, request.getKeyword()); + wrapper.like(UserStats::getUserId, request.getKeyword()) + .or().like(UserStats::getStatsType, request.getKeyword()); } - - wrapper.eq(UserStats::getIsDeleted, 0).orderByDesc(UserStats::getCreateTime); - return this.page(page, wrapper); - } - @Override - public UserStats getByUserId(String userId) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(UserStats::getUserId, userId) - .eq(UserStats::getIsDeleted, 0); - return this.getOne(wrapper); - } + // 用户ID查询 + if (StringUtils.hasText(request.getUserId())) { + wrapper.eq(UserStats::getUserId, request.getUserId()); + } - @Override - public List getByStatsType(String statsType) { - // UserStats实体中没有statsType字段,暂时返回空列表 - return Collections.emptyList(); - } + // 统计类型查询 + if (StringUtils.hasText(request.getStatsType())) { + wrapper.eq(UserStats::getStatsType, request.getStatsType()); + } - @Override - public UserStats getByUserIdAndStatsType(String userId, String statsType) { - // UserStats实体中没有statsType字段,暂时返回null - return null; - } + wrapper.eq(UserStats::getIsDeleted, 0); - @Override - public List getByTimeRange(LocalDateTime startTime, LocalDateTime endTime) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.between(UserStats::getCreateTime, startTime, endTime) - .eq(UserStats::getIsDeleted, 0) - .orderByDesc(UserStats::getCreateTime); - return this.list(wrapper); - } - - @Override - public List getByValueRange(Double minValue, Double maxValue) { - // UserStats实体中没有统一的value字段,暂时返回空列表 - return Collections.emptyList(); - } - - @Override - public Long countByStatsType(String statsType) { - // UserStats实体中没有statsType字段,暂时返回0 - return 0L; - } - - @Override - public Double getAvgValueByStatsType(String statsType) { - // 这里需要自定义SQL查询平均值,暂时返回0 - return 0.0; - } - - @Override - public Double getMaxValueByStatsType(String statsType) { - // 这里需要自定义SQL查询最大值,暂时返回0 - return 0.0; - } - - @Override - public Double getMinValueByStatsType(String statsType) { - // 这里需要自定义SQL查询最小值,暂时返回0 - return 0.0; - } - - @Override - public List getAllStatsByUserId(String userId) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(UserStats::getUserId, userId) - .eq(UserStats::getIsDeleted, 0) - .orderByDesc(UserStats::getCreateTime); - return this.list(wrapper); - } - - @Override - public List getTopUsersByStatsType(String statsType, Integer limit) { - // 这里需要自定义SQL查询,暂时返回空列表 - return Collections.emptyList(); - } - - @Override - public Long getUserRankByStatsType(String userId, String statsType) { - // 这里需要自定义SQL查询排名,暂时返回0 - return 0L; - } - - @Override - public boolean updateStatsValue(String userId, String statsType, Double value) { - // UserStats实体中没有statsType字段,暂时返回false - return false; - } - - @Override - public boolean incrementStatsValue(String userId, String statsType, Double increment) { - // UserStats实体中没有statsType字段,暂时返回false - return false; - } - - @Override - public boolean batchUpdateStats(String userId, List statsList) { - for (UserStats stats : statsList) { - stats.setUserId(userId); - if (this.getById(stats.getId()) != null) { - this.updateById(stats); + // 排序 + if (StringUtils.hasText(request.getOrderBy())) { + if ("asc".equalsIgnoreCase(request.getOrderDirection())) { + wrapper.orderByAsc(UserStats::getCreateTime); } else { - this.save(stats); + wrapper.orderByDesc(UserStats::getCreateTime); } + } else { + wrapper.orderByDesc(UserStats::getCreateTime); } - return true; + + Page resultPage = this.page(page, wrapper); + List responses = resultPage.getRecords().stream() + .map(this::convertToResponse) + .collect(Collectors.toList()); + + PageResult pageResult = new PageResult<>(); + pageResult.setCurrent(resultPage.getCurrent()); + pageResult.setSize(resultPage.getSize()); + pageResult.setTotal(resultPage.getTotal()); + pageResult.setPages(resultPage.getPages()); + pageResult.setRecords(responses); + + return pageResult; + } + + @Override + public boolean updateStatsValue(UserStatsUpdateValueRequest request) { + LambdaUpdateWrapper wrapper = new LambdaUpdateWrapper<>(); + wrapper.eq(UserStats::getUserId, request.getUserId()) + .eq(UserStats::getStatsType, request.getStatsType()) + .eq(UserStats::getIsDeleted, 0) + .set(UserStats::getValue, request.getValue()) + .set(UserStats::getUpdateTime, LocalDateTime.now()); + return this.update(wrapper); + } + + @Override + public boolean incrementStatsValue(UserStatsIncrementRequest request) { + LambdaUpdateWrapper wrapper = new LambdaUpdateWrapper<>(); + wrapper.eq(UserStats::getUserId, request.getUserId()) + .eq(UserStats::getStatsType, request.getStatsType()) + .eq(UserStats::getIsDeleted, 0) + .setSql("value = value + " + request.getIncrement()) + .set(UserStats::getUpdateTime, LocalDateTime.now()); + return this.update(wrapper); } @Override public boolean recalculateUserStats(String userId) { - // 这里需要根据业务逻辑重新计算用户统计 - // 暂时返回true + // 这里应该根据业务逻辑重新计算用户统计数据 + // 示例:更新用户的总活跃天数、总发帖数等 return true; } @Override public boolean recalculateAllUserStats() { - // 这里需要根据业务逻辑重新计算所有用户统计 - // 暂时返回true + // 这里应该重新计算所有用户的统计数据 return true; } @Override - public List getByPeriod(String period) { - // UserStats实体中没有period字段,暂时返回空列表 - return Collections.emptyList(); - } - - @Override - public List getByUserIdAndPeriod(String userId, String period) { - // UserStats实体中没有period字段,暂时返回空列表 - return Collections.emptyList(); - } - - @Override - public UserStats createOrUpdateUserStats(String userId, String statsType, Double value, String period) { - // 先尝试查找现有记录 - UserStats existingStats = getByUserId(userId); - if (existingStats != null) { - // 更新现有记录 - // 这里需要根据statsType更新对应的字段 - this.updateById(existingStats); - return existingStats; - } else { - // 创建新记录 - UserStats newStats = new UserStats(); - newStats.setUserId(userId); - newStats.setTotalConversations(0); - newStats.setTotalMessages(0); - newStats.setTotalEmotionsRecorded(0); - newStats.setTopicsCompleted(0); - newStats.setAchievementsUnlocked(0); - newStats.setTotalPoints(0); - newStats.setConsecutiveDays(0); - newStats.setMaxConsecutiveDays(0); - newStats.setLocationsVisited(0); - newStats.setPostsCreated(0); - newStats.setCommentsMade(0); - newStats.setLikesReceived(0); - newStats.setSocialInteractions(0); - - this.save(newStats); - return newStats; - } + public UserStatsResponse createOrUpdateUserStatsWithResponse(UserStatsCreateRequest request) { + UserStats stats = createOrUpdateUserStats(request.getUserId(), request.getStatsType(), request.getValue(), + request.getPeriod()); + return convertToResponse(stats); } @Override public boolean deleteExpiredStats(Integer days) { LocalDateTime expireTime = LocalDateTime.now().minusDays(days); - - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + LambdaUpdateWrapper wrapper = new LambdaUpdateWrapper<>(); wrapper.lt(UserStats::getCreateTime, expireTime) + .set(UserStats::getIsDeleted, 1) + .set(UserStats::getUpdateTime, LocalDateTime.now()); + return this.update(wrapper); + } + + /** + * 创建或更新用户统计 + */ + private UserStats createOrUpdateUserStats(String userId, String statsType, Double value, String period) { + UserStats stats = getByUserIdAndStatsType(userId, statsType); + if (stats == null) { + stats = new UserStats(); + stats.setId(snowflakeIdGenerator.nextIdAsString()); + stats.setUserId(userId); + stats.setStatsType(statsType); + stats.setValue(value); + stats.setPeriod(period); + stats.setCreateTime(LocalDateTime.now()); + stats.setUpdateTime(LocalDateTime.now()); + stats.setIsDeleted(0); + this.save(stats); + } else { + stats.setValue(value); + stats.setPeriod(period); + stats.setUpdateTime(LocalDateTime.now()); + this.updateById(stats); + } + return stats; + } + + /** + * 根据用户ID和统计类型获取统计信息 + */ + private UserStats getByUserIdAndStatsType(String userId, String statsType) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(UserStats::getUserId, userId) + .eq(UserStats::getStatsType, statsType) .eq(UserStats::getIsDeleted, 0); + return this.getOne(wrapper); + } - UserStats updateStats = new UserStats(); - updateStats.setIsDeleted(1); - - return this.update(updateStats, wrapper); + /** + * 转换为响应对象 + */ + private UserStatsResponse convertToResponse(UserStats stats) { + UserStatsResponse response = new UserStatsResponse(); + BeanUtils.copyProperties(stats, response); + response.setId(stats.getId()); + if (stats.getCreateTime() != null) { + response.setCreateTime(stats.getCreateTime().format(DATE_TIME_FORMATTER)); + } + if (stats.getUpdateTime() != null) { + response.setUpdateTime(stats.getUpdateTime().format(DATE_TIME_FORMATTER)); + } + return response; } } \ No newline at end of file