FeedbackServiceImpl.java 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. package com.xjrsoft.module.feedback.service.impl;
  2. import cn.dev33.satoken.stp.StpUtil;
  3. import cn.hutool.core.bean.BeanUtil;
  4. import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
  5. import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
  6. import com.baomidou.mybatisplus.core.metadata.IPage;
  7. import com.github.yulichang.base.MPJBaseServiceImpl;
  8. import com.github.yulichang.wrapper.MPJLambdaWrapper;
  9. import com.xjrsoft.common.exception.MyException;
  10. import com.xjrsoft.common.page.ConventPage;
  11. import com.xjrsoft.common.utils.VoToColumnUtil;
  12. import com.xjrsoft.module.feedback.dto.*;
  13. import com.xjrsoft.module.feedback.entity.Feedback;
  14. import com.xjrsoft.module.feedback.entity.FeedbackItem;
  15. import com.xjrsoft.module.feedback.mapper.FeedbackItemMapper;
  16. import com.xjrsoft.module.feedback.mapper.FeedbackMapper;
  17. import com.xjrsoft.module.feedback.service.IFeedbackService;
  18. import com.xjrsoft.module.feedback.vo.FeedbackPageVo;
  19. import com.xjrsoft.module.feedback.vo.HistoryPageMobileVo;
  20. import com.xjrsoft.module.feedback.vo.ItemDetailListVo;
  21. import com.xjrsoft.module.system.entity.DictionaryDetail;
  22. import com.xjrsoft.module.system.entity.File;
  23. import com.xjrsoft.module.system.service.IFileService;
  24. import com.xjrsoft.module.teacher.entity.XjrUser;
  25. import lombok.AllArgsConstructor;
  26. import org.apache.commons.collections.CollectionUtils;
  27. import org.apache.commons.lang3.ObjectUtils;
  28. import org.apache.commons.lang3.StringUtils;
  29. import org.springframework.stereotype.Service;
  30. import org.springframework.transaction.annotation.Transactional;
  31. import java.time.LocalDateTime;
  32. import java.util.*;
  33. import java.util.stream.Collectors;
  34. import com.baomidou.mybatisplus.core.toolkit.Wrappers;
  35. /**
  36. * @title: 意见反馈
  37. * @Author phoenix
  38. * @Date: 2025-04-09
  39. * @Version 1.0
  40. */
  41. @Service
  42. @AllArgsConstructor
  43. public class FeedbackServiceImpl extends MPJBaseServiceImpl<FeedbackMapper, Feedback> implements IFeedbackService {
  44. private final FeedbackItemMapper feedbackItemMapper;
  45. private final IFileService fileService;
  46. @Override
  47. public IPage<FeedbackPageVo> pageRubAndHand(FeedbackPageDto dto) {
  48. MPJLambdaWrapper<Feedback> feedbackMPJLambdaWrapper = new MPJLambdaWrapper<>();
  49. feedbackMPJLambdaWrapper
  50. .disableSubLogicDel()
  51. .select(Feedback::getId)
  52. .select(Feedback.class,x -> VoToColumnUtil.fieldsToColumns(FeedbackPageVo.class).contains(x.getProperty()))
  53. .leftJoin(XjrUser.class, XjrUser::getId, Feedback::getUserId,
  54. wrapper -> wrapper
  55. .selectAs(XjrUser::getName, FeedbackPageVo::getUserIdCn)
  56. .like(StringUtils.isNotEmpty(dto.getUserIdCn()), XjrUser::getName, dto.getUserIdCn())
  57. )
  58. .leftJoin(DictionaryDetail.class, DictionaryDetail::getCode, Feedback::getTerminalType,
  59. wrapper -> wrapper
  60. .selectAs(DictionaryDetail::getName, FeedbackPageVo::getTerminalTypeCn)
  61. )
  62. .eq(Feedback::getHandleStatus, dto.getHandleStatus())
  63. .eq(ObjectUtils.isNotEmpty(dto.getUserType()), Feedback::getUserType, dto.getUserType())
  64. .eq(StringUtils.isNotEmpty(dto.getTerminalType()), Feedback::getTerminalType, dto.getTerminalType())
  65. .orderByDesc(Feedback::getCreateDate)
  66. ;
  67. return this.selectJoinListPage(ConventPage.getPage(dto), FeedbackPageVo.class, feedbackMPJLambdaWrapper);
  68. }
  69. @Override
  70. public IPage<HistoryPageMobileVo> historyPageMobile(HistoryPageMobileDto dto) {
  71. Long loginId = StpUtil.getLoginIdAsLong();
  72. MPJLambdaWrapper<Feedback> feedbackMPJLambdaWrapper = new MPJLambdaWrapper<>();
  73. feedbackMPJLambdaWrapper
  74. .disableSubLogicDel()
  75. .select(Feedback::getId)
  76. .select(Feedback.class,x -> VoToColumnUtil.fieldsToColumns(HistoryPageMobileVo.class).contains(x.getProperty()))
  77. .leftJoin(DictionaryDetail.class, DictionaryDetail::getCode, Feedback::getTerminalType,
  78. wrapper -> wrapper
  79. .selectAs(DictionaryDetail::getName, HistoryPageMobileVo::getTerminalTypeCn)
  80. )
  81. .eq(Feedback::getUserId, loginId)
  82. .orderByDesc(Feedback::getHandleReadStatus)
  83. ;
  84. IPage<HistoryPageMobileVo> page = this.selectJoinListPage(ConventPage.getPage(dto), HistoryPageMobileVo.class, feedbackMPJLambdaWrapper);
  85. // 处理最后一条反馈内容
  86. List<HistoryPageMobileVo> dataList = page.getRecords();
  87. if(CollectionUtils.isNotEmpty(dataList)){
  88. List<String> ids = dataList.stream()
  89. .map(HistoryPageMobileVo::getId)
  90. .collect(Collectors.toList());
  91. if(CollectionUtils.isNotEmpty(ids)){
  92. List<FeedbackItem> feedbackItems = feedbackItemMapper.selectList(
  93. Wrappers.lambdaQuery(FeedbackItem.class)
  94. .in(FeedbackItem::getFeedbackId, ids)
  95. );
  96. Map<Long, List<FeedbackItem>> groupByFeedbackId = feedbackItems.stream()
  97. .collect(Collectors.groupingBy(FeedbackItem::getFeedbackId));
  98. for (HistoryPageMobileVo vo : page.getRecords()){
  99. List<FeedbackItem> feedbackItemList = groupByFeedbackId.get(Long.parseLong(vo.getId()));
  100. if(CollectionUtils.isNotEmpty(feedbackItemList)){
  101. feedbackItemList.sort(Comparator.comparing(FeedbackItem::getCreateDate).reversed());
  102. FeedbackItem lastOne = feedbackItemList.get(0);
  103. if(ObjectUtils.isNotEmpty(lastOne)){
  104. vo.setFeedback(lastOne.getFeedback());
  105. vo.setReply(lastOne.getReply());
  106. }
  107. }
  108. }
  109. }
  110. }
  111. return page;
  112. }
  113. @Override
  114. public List<ItemDetailListVo> itemDetailList(ItemDetailListDto dto) {
  115. MPJLambdaWrapper<FeedbackItem> feedbackItemMPJLambdaWrapper = new MPJLambdaWrapper<>();
  116. feedbackItemMPJLambdaWrapper
  117. .disableSubLogicDel()
  118. .select(FeedbackItem::getId)
  119. .select(FeedbackItem.class,x -> VoToColumnUtil.fieldsToColumns(ItemDetailListVo.class).contains(x.getProperty()))
  120. .innerJoin(Feedback.class, Feedback::getId, FeedbackItem::getFeedbackId,
  121. wrapper -> wrapper
  122. .selectAs(Feedback::getUserType, ItemDetailListVo::getUserType)
  123. .selectAs(Feedback::getTerminalType, ItemDetailListVo::getTerminalType)
  124. .leftJoin(DictionaryDetail.class, DictionaryDetail::getCode, Feedback::getTerminalType,
  125. wrap -> wrap
  126. .selectAs(DictionaryDetail::getName, ItemDetailListVo::getTerminalTypeCn)
  127. )
  128. )
  129. .leftJoin(XjrUser.class, XjrUser::getId, FeedbackItem::getCreateUserId,
  130. wrapper -> wrapper
  131. .selectAs(XjrUser::getName, ItemDetailListVo::getCreateUserIdCn)
  132. )
  133. .leftJoin(XjrUser.class, XjrUser::getId, FeedbackItem::getReplyUserId,
  134. wrapper -> wrapper
  135. .selectAs(XjrUser::getName, ItemDetailListVo::getReplyUserIdCn)
  136. )
  137. .eq(FeedbackItem::getFeedbackId, dto.getFeedbackId())
  138. ;
  139. List<ItemDetailListVo> itemDetailListVos = feedbackItemMapper.selectJoinList(ItemDetailListVo.class, feedbackItemMPJLambdaWrapper);
  140. for (ItemDetailListVo vo : itemDetailListVos){
  141. if(ObjectUtils.isNotEmpty(vo.getFeedbackFileId())){
  142. List<File> feedbackFile = fileService.list(Wrappers.<File>query().lambda().eq(File::getFolderId, vo.getFeedbackFileId()));
  143. vo.setFeedbackFiles(feedbackFile);
  144. }
  145. if(ObjectUtils.isNotEmpty(vo.getReplyFileId())){
  146. List<File> replyFile = fileService.list(Wrappers.<File>query().lambda().eq(File::getFolderId, vo.getReplyFileId()));
  147. vo.setFeedbackFiles(replyFile);
  148. }
  149. }
  150. return itemDetailListVos;
  151. }
  152. @Override
  153. @Transactional(rollbackFor = Exception.class)
  154. public Boolean addFeedbackItem(AddFeedbackItemDto dto) {
  155. LocalDateTime nowLocalDateTime = LocalDateTime.now();
  156. Long loginId = StpUtil.getLoginIdAsLong();
  157. // 如果没有传入了意见反馈主键id表示为新增反馈,应该添加主表记录
  158. if(ObjectUtils.isEmpty(dto.getFeedbackId())){
  159. Feedback feedback = new Feedback();
  160. feedback.setCreateDate(nowLocalDateTime);
  161. feedback.setCreateUserId(loginId);
  162. feedback.setUserId(loginId);
  163. // 处理用户类别
  164. if(StpUtil.hasRole("TEACHER")){
  165. feedback.setUserType(1);
  166. } else if(StpUtil.hasRole("STUDENT")){
  167. feedback.setUserType(2);
  168. } else if(StpUtil.hasRole("PARENT")){
  169. feedback.setUserType(3);
  170. } else {
  171. feedback.setUserType(4);
  172. }
  173. if(ObjectUtils.isNotEmpty(dto.getTerminalType())){
  174. feedback.setTerminalType(dto.getTerminalType());
  175. } else {
  176. throw new MyException("请选择终端类型");
  177. }
  178. feedback.setFeedbackTime(nowLocalDateTime);
  179. feedback.setHandleStatus(0);
  180. feedback.setHandleReadStatus(0);
  181. this.save(feedback);
  182. dto.setFeedbackId(feedback.getId());
  183. }
  184. FeedbackItem feedbackItem = BeanUtil.toBean(dto, FeedbackItem.class);
  185. feedbackItem.setCreateDate(nowLocalDateTime);
  186. feedbackItem.setCreateUserId(loginId);
  187. feedbackItemMapper.insert(feedbackItem);
  188. return true;
  189. }
  190. @Override
  191. @Transactional(rollbackFor = Exception.class)
  192. public Boolean replyFeedbackItem(ReplyFeedbackItemDto dto) {
  193. FeedbackItem old = feedbackItemMapper.selectById(dto.getId());
  194. if(ObjectUtils.isEmpty(old)){
  195. throw new MyException("当前反馈已被修改,请刷新重试");
  196. }
  197. LocalDateTime nowLocalDateTime = LocalDateTime.now();
  198. Long loginId = StpUtil.getLoginIdAsLong();
  199. FeedbackItem feedbackItem = BeanUtil.toBean(dto, FeedbackItem.class);
  200. feedbackItem.setModifyDate(nowLocalDateTime);
  201. feedbackItem.setModifyUserId(loginId);
  202. feedbackItem.setReplyStatus(1);
  203. feedbackItem.setReplyUserId(loginId);
  204. feedbackItem.setReplyTime(nowLocalDateTime);
  205. feedbackItem.setReplyReadStatus(0);
  206. feedbackItemMapper.insert(feedbackItem);
  207. // 处理主反馈的状态
  208. Feedback updateFeedback = new Feedback();
  209. updateFeedback.setId(old.getFeedbackId());
  210. updateFeedback.setModifyDate(nowLocalDateTime);
  211. updateFeedback.setModifyUserId(loginId);
  212. // 查询当前主反馈是否还有没有回复的
  213. LambdaQueryWrapper<FeedbackItem> replyLambdaQueryWrapper = new LambdaQueryWrapper<>();
  214. replyLambdaQueryWrapper
  215. .eq(FeedbackItem::getFeedbackId, old.getFeedbackId())
  216. .eq(FeedbackItem::getReplyStatus, 0)
  217. ;
  218. List<FeedbackItem> replyLFeedbackItems = feedbackItemMapper.selectList(replyLambdaQueryWrapper);
  219. if(CollectionUtils.isEmpty(replyLFeedbackItems)){
  220. updateFeedback.setHandleReadStatus(1);
  221. updateFeedback.setHandleTime(nowLocalDateTime);
  222. }
  223. updateFeedback.setHandleReadStatus(0);
  224. this.updateById(updateFeedback);
  225. return true;
  226. }
  227. @Override
  228. @Transactional(rollbackFor = Exception.class)
  229. public Boolean readFeedbackItem(ReadFeedbackItemDto dto) {
  230. Feedback old = this.getById(dto.getId());
  231. if(ObjectUtils.isEmpty(old)){
  232. throw new MyException("当前反馈已被修改,请刷新重试");
  233. }
  234. // 将所有已经处理反馈项阅读
  235. LambdaUpdateWrapper<FeedbackItem> feedbackItemLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
  236. feedbackItemLambdaUpdateWrapper
  237. .set(FeedbackItem::getReplyReadStatus, 1)
  238. .eq(FeedbackItem::getFeedbackId, dto.getId())
  239. .eq(FeedbackItem::getReplyStatus, 1)
  240. ;
  241. feedbackItemMapper.update(new FeedbackItem(), feedbackItemLambdaUpdateWrapper);
  242. this.updateById(new Feedback(){{
  243. setId(dto.getId());
  244. setHandleReadStatus(1);
  245. }});
  246. return true;
  247. }
  248. }