Эх сурвалжийг харах

意见反馈模块功能开发(用商家端)文件冲突修复

panzhilin 1 долоо хоног өмнө
parent
commit
ccc5af3193

+ 1 - 0
alien-entity/src/main/java/shop/alien/entity/store/LifeFeedbackReply.java

@@ -47,3 +47,4 @@ public class LifeFeedbackReply implements Serializable {
     private Date updateTime;
 }
 
+

+ 1 - 0
alien-entity/src/main/java/shop/alien/mapper/LifeFeedbackReplyMapper.java

@@ -21,3 +21,4 @@ public interface LifeFeedbackReplyMapper extends BaseMapper<LifeFeedbackReply> {
     List<LifeFeedbackReply> selectByFeedbackId(@Param("feedbackId") Integer feedbackId);
 }
 
+

+ 1 - 0
alien-entity/src/main/resources/mapper/LifeFeedbackReplyMapper.xml

@@ -30,3 +30,4 @@
 
 </mapper>
 
+

+ 6 - 22
alien-store/src/main/java/shop/alien/store/controller/LifeFeedbackController.java

@@ -6,8 +6,8 @@ import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.web.bind.annotation.*;
 import shop.alien.entity.result.R;
-import shop.alien.entity.store.dto.FeedbackReplyDto;
 import shop.alien.entity.store.dto.LifeFeedbackDto;
+import shop.alien.entity.store.dto.UserReplyDto;
 import shop.alien.entity.store.vo.LifeFeedbackVo;
 import shop.alien.store.service.LifeFeedbackService;
 
@@ -31,13 +31,6 @@ public class LifeFeedbackController {
         return lifeFeedbackService.submitFeedback(dto);
     }
 
-    @ApiOperation(value = "平台回复反馈", httpMethod = "POST")
-    @PostMapping("/reply")
-    public R<String> replyFeedback(@RequestBody FeedbackReplyDto dto) {
-        log.info("LifeFeedbackController.replyFeedback, dto={}", dto);
-        return lifeFeedbackService.replyFeedback(dto);
-    }
-
     @ApiOperation(value = "查询用户历史反馈列表", httpMethod = "GET")
     @ApiImplicitParams({
             @ApiImplicitParam(name = "userId", value = "用户ID", dataType = "Integer", paramType = "query", required = true),
@@ -67,20 +60,11 @@ public class LifeFeedbackController {
         return lifeFeedbackService.getFeedbackDetail(feedbackId);
     }
 
-    @ApiOperation(value = "更新反馈处理状态", httpMethod = "POST")
-    @ApiImplicitParams({
-            @ApiImplicitParam(name = "feedbackId", value = "反馈ID", dataType = "Integer", paramType = "query", required = true),
-            @ApiImplicitParam(name = "handleStatus", value = "处理状态:0-待处理,1-处理中,2-已完成", dataType = "Integer", paramType = "query", required = true),
-            @ApiImplicitParam(name = "staffId", value = "跟进工作人员ID", dataType = "Integer", paramType = "query", required = false)
-    })
-    @PostMapping("/updateStatus")
-    public R<String> updateHandleStatus(
-            @RequestParam("feedbackId") Integer feedbackId,
-            @RequestParam("handleStatus") Integer handleStatus,
-            @RequestParam(value = "staffId", required = false) Integer staffId) {
-        log.info("LifeFeedbackController.updateHandleStatus, feedbackId={}, handleStatus={}, staffId={}", 
-                feedbackId, handleStatus, staffId);
-        return lifeFeedbackService.updateHandleStatus(feedbackId, handleStatus, staffId);
+    @ApiOperation(value = "用户回复反馈", httpMethod = "POST")
+    @PostMapping("/userReply")
+    public R<String> userReply(@RequestBody UserReplyDto dto) {
+        log.info("LifeFeedbackController.userReply, dto={}", dto);
+        return lifeFeedbackService.userReply(dto);
     }
 }
 

+ 1 - 0
alien-store/src/main/java/shop/alien/store/service/LifeFeedbackReplyService.java

@@ -18,3 +18,4 @@ public interface LifeFeedbackReplyService extends IService<LifeFeedbackReply> {
     List<LifeFeedbackReply> getByFeedbackId(Integer feedbackId);
 }
 
+

+ 5 - 14
alien-store/src/main/java/shop/alien/store/service/LifeFeedbackService.java

@@ -4,8 +4,8 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.IService;
 import shop.alien.entity.result.R;
 import shop.alien.entity.store.LifeFeedback;
-import shop.alien.entity.store.dto.FeedbackReplyDto;
 import shop.alien.entity.store.dto.LifeFeedbackDto;
+import shop.alien.entity.store.dto.UserReplyDto;
 import shop.alien.entity.store.vo.LifeFeedbackVo;
 
 /**
@@ -21,13 +21,6 @@ public interface LifeFeedbackService extends IService<LifeFeedback> {
     R<String> submitFeedback(LifeFeedbackDto dto);
 
     /**
-     * 平台回复反馈
-     * @param dto 回复信息
-     * @return 回复结果
-     */
-    R<String> replyFeedback(FeedbackReplyDto dto);
-
-    /**
      * 查询用户历史反馈列表
      * @param userId 用户ID
      * @param feedbackSource 反馈来源
@@ -45,12 +38,10 @@ public interface LifeFeedbackService extends IService<LifeFeedback> {
     R<LifeFeedbackVo> getFeedbackDetail(Integer feedbackId);
 
     /**
-     * 更新反馈处理状态
-     * @param feedbackId 反馈ID
-     * @param handleStatus 处理状态
-     * @param staffId 跟进人员ID
-     * @return 更新结果
+     * 用户回复反馈
+     * @param dto 回复信息
+     * @return 回复结果
      */
-    R<String> updateHandleStatus(Integer feedbackId, Integer handleStatus, Integer staffId);
+    R<String> userReply(UserReplyDto dto);
 }
 

+ 1 - 0
alien-store/src/main/java/shop/alien/store/service/impl/LifeFeedbackReplyServiceImpl.java

@@ -26,3 +26,4 @@ public class LifeFeedbackReplyServiceImpl extends ServiceImpl<LifeFeedbackReplyM
     }
 }
 
+

+ 135 - 102
alien-store/src/main/java/shop/alien/store/service/impl/LifeFeedbackServiceImpl.java

@@ -11,11 +11,13 @@ import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.CollectionUtils;
 import shop.alien.entity.result.R;
 import shop.alien.entity.store.LifeFeedback;
+import shop.alien.entity.store.LifeFeedbackReply;
 import shop.alien.entity.store.LifeImg;
 import shop.alien.entity.store.LifeLog;
-import shop.alien.entity.store.dto.FeedbackReplyDto;
 import shop.alien.entity.store.dto.LifeFeedbackDto;
+import shop.alien.entity.store.dto.UserReplyDto;
 import shop.alien.entity.store.vo.LifeFeedbackVo;
+import shop.alien.mapper.LifeFeedbackReplyMapper;
 import shop.alien.mapper.LifeFeedbackMapper;
 import shop.alien.mapper.LifeLogMapper;
 import shop.alien.store.service.LifeFeedbackService;
@@ -36,6 +38,7 @@ public class LifeFeedbackServiceImpl extends ServiceImpl<LifeFeedbackMapper, Lif
     private final LifeFeedbackMapper lifeFeedbackMapper;
     private final LifeImgService lifeImgService;
     private final LifeLogMapper lifeLogMapper;
+    private final LifeFeedbackReplyMapper lifeFeedbackReplyMapper;
 
     @Override
     public R<String> submitFeedback(LifeFeedbackDto dto) {
@@ -57,34 +60,37 @@ public class LifeFeedbackServiceImpl extends ServiceImpl<LifeFeedbackMapper, Lif
             // 2. 创建反馈记录(使用MyBatis Plus的save方法)
             LifeFeedback feedback = new LifeFeedback();
             BeanUtils.copyProperties(dto, feedback);
+            // 如果feedbackWay为空,默认为用户主动反馈(0)
+            if (feedback.getFeedbackWay() == null) {
+                feedback.setFeedbackWay(0);
+            }
             feedback.setFeedbackTime(new Date());
             feedback.setHandleStatus(0); // 待处理
-            feedback.setCreatedTime(new Date());
-            feedback.setCreatedUserId(dto.getUserId());
+            // createTime 和 updateTime 由 MyBatis Plus 自动填充,无需手动设置
 
             boolean saveResult = this.save(feedback);
             if (!saveResult) {
                 return R.fail("提交反馈失败");
             }
 
-            // 3. 保存附件图片(使用批量插入)
+            // 3. 保存附件(图片和视频,使用批量插入)
             if (!CollectionUtils.isEmpty(dto.getImgUrlList())) {
                 List<LifeImg> imgList = new java.util.ArrayList<>();
                 int sort = 1;
-                for (String imgUrl : dto.getImgUrlList()) {
+                for (String fileUrl : dto.getImgUrlList()) {
                     LifeImg img = new LifeImg();
                     img.setFeedbackId(feedback.getId());
-                    img.setImgUrl(imgUrl);
+                    img.setImgUrl(fileUrl);
                     img.setImgSort(sort++);
-                    img.setCreatedTime(new Date());
                     img.setCreatedUserId(dto.getUserId());
+                    // createdTime 由 MyBatis Plus 自动填充
                     imgList.add(img);
                 }
                 lifeImgService.batchSave(imgList);
             }
 
-            // 4. 记录日志
-            saveLog("用户提交反馈,ID:" + feedback.getId());
+            // 4. 记录日志(只记录内容)
+            saveLog(feedback.getId(), feedback.getContent(), "0");
 
             return R.success("提交成功");
         } catch (Exception e) {
@@ -94,78 +100,32 @@ public class LifeFeedbackServiceImpl extends ServiceImpl<LifeFeedbackMapper, Lif
     }
 
     @Override
-    public R<String> replyFeedback(FeedbackReplyDto dto) {
-        try {
-            // 1. 参数校验
-            if (dto.getFeedbackId() == null) {
-                return R.fail("反馈ID不能为空");
-            }
-            if (dto.getStaffId() == null) {
-                return R.fail("工作人员ID不能为空");
-            }
-            if (dto.getContent() == null || dto.getContent().trim().isEmpty()) {
-                return R.fail("回复内容不能为空");
-            }
-
-            // 2. 查询原始反馈
-            LifeFeedback originalFeedback = lifeFeedbackMapper.selectById(dto.getFeedbackId());
-            if (originalFeedback == null) {
-                return R.fail("反馈记录不存在");
-            }
-
-            // 3. 创建平台回复记录(使用MyBatis Plus的save方法)
-            LifeFeedback reply = new LifeFeedback();
-            reply.setUserId(originalFeedback.getUserId());
-            reply.setFeedbackSource(originalFeedback.getFeedbackSource());
-            reply.setFeedbackWay(2); // 平台回复
-            reply.setFeedbackType(originalFeedback.getFeedbackType());
-            reply.setContent(dto.getContent());
-            reply.setFeedbackTime(new Date());
-            reply.setFollowUpStaff(dto.getStaffId());
-            reply.setHandleStatus(2); // 已完成
-            reply.setCreatedTime(new Date());
-            reply.setCreatedUserId(dto.getStaffId());
-
-            boolean saveResult = this.save(reply);
-            if (!saveResult) {
-                return R.fail("回复失败");
-            }
-
-            // 4. 更新原始反馈的处理状态和跟进人员(使用MyBatis Plus的updateById方法)
-            LifeFeedback updateFeedback = new LifeFeedback();
-            updateFeedback.setId(dto.getFeedbackId());
-            updateFeedback.setHandleStatus(1); // 处理中
-            updateFeedback.setFollowUpStaff(dto.getStaffId());
-            updateFeedback.setUpdatedTime(new Date());
-            updateFeedback.setUpdatedUserId(dto.getStaffId());
-            this.updateById(updateFeedback);
-
-            // 5. 记录日志
-            saveLog("平台回复反馈,原始反馈ID:" + dto.getFeedbackId() + ",回复ID:" + reply.getId());
-
-            return R.success("回复成功");
-        } catch (Exception e) {
-            log.error("回复反馈失败", e);
-            return R.fail("回复反馈失败:" + e.getMessage());
-        }
-    }
-
-    @Override
     public IPage<LifeFeedbackVo> getFeedbackList(Integer userId, Integer feedbackSource, int page, int size) {
         try {
             // 使用自定义SQL查询(已包含工作人员名称)
+            // 只返回原始反馈(feedback_way=0或1),不包括回复
             Page<LifeFeedbackVo> pageParam = new Page<>(page, size);
             IPage<LifeFeedbackVo> voPage = lifeFeedbackMapper.selectFeedbackListWithStaff(
-                    pageParam, userId, feedbackSource, 1, null
+                    pageParam, userId, feedbackSource, null, null
             );
-
+            
+            // 过滤出原始反馈(feedback_way=0或1)
+            List<LifeFeedbackVo> originalFeedbacks = voPage.getRecords().stream()
+                    .filter(vo -> vo.getFeedbackWay() == 0 || vo.getFeedbackWay() == 1)
+                    .collect(java.util.stream.Collectors.toList());
+            
             // 为每条记录查询附件图片
-            voPage.getRecords().forEach(vo -> {
+            originalFeedbacks.forEach(vo -> {
                 List<String> imgUrls = lifeImgService.getImgUrlsByFeedbackId(vo.getId());
                 vo.setImgUrlList(imgUrls);
             });
+            
+            // 重新设置records
+            Page<LifeFeedbackVo> resultPage = new Page<>(page, size);
+            resultPage.setRecords(originalFeedbacks);
+            resultPage.setTotal(originalFeedbacks.size());
 
-            return voPage;
+            return resultPage;
         } catch (Exception e) {
             log.error("查询反馈列表失败", e);
             return new Page<>(page, size);
@@ -181,17 +141,70 @@ public class LifeFeedbackServiceImpl extends ServiceImpl<LifeFeedbackMapper, Lif
                 return R.fail("反馈记录不存在");
             }
 
-            // 2. 查询附件图片
-            List<String> imgUrls = lifeImgService.getImgUrlsByFeedbackId(feedbackId);
-            vo.setImgUrlList(imgUrls);
-
-            // 3. 查询平台回复列表(如果是主动反馈)
-            if (vo.getFeedbackWay() == 1) {
-                List<LifeFeedbackVo> replyList = lifeFeedbackMapper.selectPlatformReplies(
-                        vo.getUserId(), vo.getFeedbackSource(), vo.getFeedbackTime()
-                );
-                vo.setPlatformReplies(replyList);
+            // 2. 查询所有附件(包括原始反馈和回复的附件)
+            List<LifeImg> allImgs = lifeImgService.getByFeedbackId(feedbackId);
+            
+            // 3. 查询回复列表(从life_feedback_reply表查询)
+            List<LifeFeedbackReply> replyList = lifeFeedbackReplyMapper.selectByFeedbackId(feedbackId);
+            
+            // 4. 获取最早回复时间(用于区分原始反馈附件和回复附件)
+            Date earliestReplyTime = null;
+            if (!replyList.isEmpty()) {
+                earliestReplyTime = replyList.stream()
+                        .map(LifeFeedbackReply::getCreateTime)
+                        .min(Date::compareTo)
+                        .orElse(null);
             }
+            
+            // 5. 通过时间逻辑区分附件归属
+            Date feedbackTime = vo.getFeedbackTime();
+            List<String> originalImgUrls = new java.util.ArrayList<>();
+            List<LifeFeedbackVo> platformReplies = new java.util.ArrayList<>();
+            
+            // 5.1 处理回复列表,为每个回复匹配附件
+            for (LifeFeedbackReply reply : replyList) {
+                LifeFeedbackVo replyVo = new LifeFeedbackVo();
+                replyVo.setId(reply.getId());
+                replyVo.setContent(reply.getReplyContent());
+                replyVo.setFeedbackTime(reply.getCreateTime());
+                replyVo.setFeedbackWay(reply.getReplyType() == 0 ? 2 : 1); // 0-平台回复,1-用户回复
+                // 平台回复通过staffId区分,用户回复staffId为null
+                if (reply.getReplyType() == 0) {
+                    replyVo.setStaffName("平台客服"); // 平台回复显示工作人员名称
+                }
+                
+                // 为回复匹配附件(时间差在5分钟内)
+                List<String> replyImgUrls = new java.util.ArrayList<>();
+                for (LifeImg img : allImgs) {
+                    if (img.getCreatedTime() != null && reply.getCreateTime() != null) {
+                        long timeDiff = Math.abs(img.getCreatedTime().getTime() - reply.getCreateTime().getTime());
+                        if (timeDiff <= 5 * 60 * 1000) { // 5分钟内
+                            // 如果附件时间晚于最早回复时间,则属于回复
+                            if (earliestReplyTime != null && img.getCreatedTime().after(earliestReplyTime)) {
+                                replyImgUrls.add(img.getImgUrl());
+                            }
+                        }
+                    }
+                }
+                replyVo.setImgUrlList(replyImgUrls);
+                platformReplies.add(replyVo);
+            }
+            
+            // 5.2 处理原始反馈附件(时间差在反馈时间5分钟内,且早于最早回复时间)
+            for (LifeImg img : allImgs) {
+                if (img.getCreatedTime() != null && feedbackTime != null) {
+                    long timeDiff = Math.abs(img.getCreatedTime().getTime() - feedbackTime.getTime());
+                    if (timeDiff <= 5 * 60 * 1000) { // 5分钟内
+                        // 如果早于最早回复时间,或没有回复,则属于原始反馈
+                        if (earliestReplyTime == null || img.getCreatedTime().before(earliestReplyTime)) {
+                            originalImgUrls.add(img.getImgUrl());
+                        }
+                    }
+                }
+            }
+            
+            vo.setImgUrlList(originalImgUrls);
+            vo.setPlatformReplies(platformReplies);
 
             return R.data(vo);
         } catch (Exception e) {
@@ -201,37 +214,57 @@ public class LifeFeedbackServiceImpl extends ServiceImpl<LifeFeedbackMapper, Lif
     }
 
     @Override
-    public R<String> updateHandleStatus(Integer feedbackId, Integer handleStatus, Integer staffId) {
+    public R<String> userReply(UserReplyDto dto) {
         try {
-            // 使用MyBatis Plus的updateById方法
-            LifeFeedback feedback = new LifeFeedback();
-            feedback.setId(feedbackId);
-            feedback.setHandleStatus(handleStatus);
-            feedback.setFollowUpStaff(staffId);
-            feedback.setUpdatedTime(new Date());
-            feedback.setUpdatedUserId(staffId);
-
-            boolean result = this.updateById(feedback);
-            if (result) {
-                saveLog("更新反馈处理状态,反馈ID:" + feedbackId + ",状态:" + handleStatus);
-                return R.success("更新成功");
-            }
-            return R.fail("更新失败");
+            // 1. 参数校验
+            if (dto.getUserId() == null) {
+                return R.fail("用户ID不能为空");
+            }
+            if (dto.getFeedbackId() == null) {
+                return R.fail("反馈ID不能为空");
+            }
+            if (dto.getContent() == null || dto.getContent().trim().isEmpty()) {
+                return R.fail("回复内容不能为空");
+            }
+
+            // 2. 查询原始反馈
+            LifeFeedback originalFeedback = lifeFeedbackMapper.selectById(dto.getFeedbackId());
+            if (originalFeedback == null) {
+                return R.fail("反馈记录不存在");
+            }
+
+            // 3. 创建用户回复记录(保存到life_feedback_reply表,reply_type=1)
+            LifeFeedbackReply reply = new LifeFeedbackReply();
+            reply.setFeedbackId(dto.getFeedbackId());
+            reply.setReplyType(1); // 1-用户回复
+            reply.setReplyContent(dto.getContent());
+            // createTime 和 updateTime 由 MyBatis Plus 自动填充
+
+            boolean saveResult = lifeFeedbackReplyMapper.insert(reply) > 0;
+            if (!saveResult) {
+                return R.fail("回复失败");
+            }
+
+            // 注意:根据文档,用户回复不保存附件、不更新反馈状态、不记录操作日志
+
+            return R.success("回复成功");
         } catch (Exception e) {
-            log.error("更新反馈处理状态失败", e);
-            return R.fail("更新失败:" + e.getMessage());
+            log.error("用户回复失败", e);
+            return R.fail("用户回复失败:" + e.getMessage());
         }
     }
 
     /**
      * 保存操作日志
      */
-    private void saveLog(String context) {
+    private void saveLog(Integer feedbackId, String context, String type) {
         try {
-            LifeLog log = new LifeLog();
-            log.setContext(context);
-            log.setCreatedTime(new Date());
-            lifeLogMapper.insert(log);
+            LifeLog lifeLog = new LifeLog();
+            lifeLog.setFeedbackId(feedbackId);
+            lifeLog.setContext(context);
+            lifeLog.setType(type);
+            // createdTime 由 MyBatis Plus 自动填充
+            lifeLogMapper.insert(lifeLog);
         } catch (Exception e) {
             log.error("保存日志失败", e);
         }