jinshihui 1 nedēļu atpakaļ
vecāks
revīzija
24b15f07c2
34 mainītis faili ar 1514 papildinājumiem un 407 dzēšanām
  1. 63 34
      nightFragrance-admin/src/main/java/com/ylx/web/controller/common/CommonController.java
  2. 0 13
      nightFragrance-admin/src/main/java/com/ylx/web/controller/massage/TCommentController.java
  3. 91 18
      nightFragrance-admin/src/main/java/com/ylx/web/controller/massage/TCommentUserController.java
  4. 5 0
      nightFragrance-admin/src/main/java/com/ylx/web/controller/massage/WxController.java
  5. 4 4
      nightFragrance-admin/src/main/resources/application-dev.yml
  6. 0 1
      nightFragrance-admin/src/main/resources/application-pro.yml
  7. 0 2
      nightFragrance-admin/src/main/resources/application-test.yml
  8. 1 1
      nightFragrance-admin/src/main/resources/application.yml
  9. 6 0
      nightFragrance-common/src/main/java/com/ylx/common/core/domain/model/WxLoginUser.java
  10. 38 73
      nightFragrance-common/src/main/java/com/ylx/common/utils/file/FileUploadUtils.java
  11. 40 81
      nightFragrance-common/src/main/java/com/ylx/common/utils/file/FileUtils.java
  12. 0 132
      nightFragrance-framework/src/main/java/com/ylx/framework/config/MyBatisConfig.java
  13. 5 10
      nightFragrance-framework/src/main/java/com/ylx/framework/config/MybatisPlusConfig.java
  14. 4 6
      nightFragrance-framework/src/main/java/com/ylx/framework/config/ServerConfig.java
  15. 84 0
      nightFragrance-massage/src/main/java/com/ylx/massage/domain/CommentUserAudit.java
  16. 57 0
      nightFragrance-massage/src/main/java/com/ylx/massage/domain/SensitiveWord.java
  17. 104 19
      nightFragrance-massage/src/main/java/com/ylx/massage/domain/TCommentUser.java
  18. 92 0
      nightFragrance-massage/src/main/java/com/ylx/massage/enums/SensitiveWordCategoryEnum.java
  19. 42 0
      nightFragrance-massage/src/main/java/com/ylx/massage/mapper/SensitiveWordMapper.java
  20. 15 0
      nightFragrance-massage/src/main/java/com/ylx/massage/mapper/TCommentUserAuditMapper.java
  21. 9 0
      nightFragrance-massage/src/main/java/com/ylx/massage/mapper/TCommentUserMapper.java
  22. 46 0
      nightFragrance-massage/src/main/java/com/ylx/massage/service/SensitiveWordService.java
  23. 35 0
      nightFragrance-massage/src/main/java/com/ylx/massage/service/TCommentUserAuditService.java
  24. 22 0
      nightFragrance-massage/src/main/java/com/ylx/massage/service/TCommentUserService.java
  25. 148 0
      nightFragrance-massage/src/main/java/com/ylx/massage/service/impl/SensitiveWordServiceImpl.java
  26. 0 1
      nightFragrance-massage/src/main/java/com/ylx/massage/service/impl/TCommentServiceImpl.java
  27. 100 0
      nightFragrance-massage/src/main/java/com/ylx/massage/service/impl/TCommentUserAuditServiceImpl.java
  28. 77 0
      nightFragrance-massage/src/main/java/com/ylx/massage/service/impl/TCommentUserServiceImpl.java
  29. 62 11
      nightFragrance-massage/src/main/java/com/ylx/massage/service/impl/TbFileServiceImpl.java
  30. 298 0
      nightFragrance-massage/src/main/java/com/ylx/massage/utils/ExcelUtils.java
  31. 1 0
      nightFragrance-massage/src/main/java/com/ylx/massage/utils/WeChatUtil.java
  32. 33 0
      nightFragrance-massage/src/main/resources/mapper/massage/SensitiveWordMapper.xml
  33. 32 0
      nightFragrance-massage/src/main/resources/mapper/massage/TCommentUserMapper.xml
  34. 0 1
      pom.xml

+ 63 - 34
nightFragrance-admin/src/main/java/com/ylx/web/controller/common/CommonController.java

@@ -7,6 +7,7 @@ import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
 import cn.hutool.crypto.digest.DigestUtil;
+import com.alibaba.fastjson.JSON;
 import com.ylx.massage.domain.TbFile;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
@@ -27,6 +28,7 @@ import com.ylx.common.utils.file.FileUploadUtils;
 import com.ylx.common.utils.file.FileUtils;
 import com.ylx.framework.config.ServerConfig;
 import com.ylx.massage.service.TbFileService;
+import com.ylx.massage.service.SensitiveWordService;
 
 /**
  * 通用请求处理
@@ -36,8 +38,7 @@ import com.ylx.massage.service.TbFileService;
 @RestController
 @RequestMapping("/common")
 @Api(tags = {"通用接口"})
-public class CommonController
-{
+public class CommonController {
     private static final Logger log = LoggerFactory.getLogger(CommonController.class);
 
     @Autowired
@@ -46,44 +47,44 @@ public class CommonController
     @Autowired
     private TbFileService fileService;
 
+    @Autowired
+    private SensitiveWordService sensitiveWordService;
+
     private static final String FILE_DELIMETER = ",";
 
     /**
      * 通用下载请求
      *
      * @param fileName 文件名称
-     * @param delete 是否删除
+     * @param delete   是否删除
      */
     @GetMapping("/download")
-    public void fileDownload(String fileName, Boolean delete, HttpServletResponse response, HttpServletRequest request)
-    {
-        try
-        {
-            if (!FileUtils.checkAllowDownload(fileName))
-            {
+    public void fileDownload(String fileName, Boolean delete, HttpServletResponse response, HttpServletRequest request) {
+        try {
+            if (!FileUtils.checkAllowDownload(fileName)) {
                 throw new Exception(StringUtils.format("文件名称({})非法,不允许下载。 ", fileName));
             }
             String realFileName = System.currentTimeMillis() + fileName.substring(fileName.indexOf("_") + 1);
             String filePath = RuoYiConfig.getDownloadPath() + fileName;
+            log.info("下载文件路径:{}", filePath);
 
             response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
             FileUtils.setAttachmentResponseHeader(response, realFileName);
             FileUtils.writeBytes(filePath, response.getOutputStream());
-            if (delete)
-            {
+            if (delete) {
                 FileUtils.deleteFile(filePath);
             }
-        }
-        catch (Exception e)
-        {
+        } catch (Exception e) {
             log.error("下载文件失败", e);
         }
     }
 
 
-
     /**
      * 通用上传请求(单个)
+     *
+     * @param file 上传的文件
+     * @return AjaxResult 结果
      */
     @ApiOperation("通用上传请求(单个)")
     @PostMapping("/upload")
@@ -105,18 +106,15 @@ public class CommonController
      */
     @ApiOperation("通用上传请求(多个)")
     @PostMapping("/uploads")
-    public AjaxResult uploadFiles(List<MultipartFile> files) throws Exception
-    {
-        try
-        {
+    public AjaxResult uploadFiles(List<MultipartFile> files) throws Exception {
+        try {
             // 上传文件路径
             String filePath = RuoYiConfig.getUploadPath();
             List<String> urls = new ArrayList<String>();
             List<String> fileNames = new ArrayList<String>();
             List<String> newFileNames = new ArrayList<String>();
             List<String> originalFilenames = new ArrayList<String>();
-            for (MultipartFile file : files)
-            {
+            for (MultipartFile file : files) {
                 // 上传并返回新文件名称
                 String fileName = FileUploadUtils.upload(filePath, file);
                 String url = serverConfig.getUrl() + fileName;
@@ -131,9 +129,7 @@ public class CommonController
             ajax.put("newFileNames", StringUtils.join(newFileNames, FILE_DELIMETER));
             ajax.put("originalFilenames", StringUtils.join(originalFilenames, FILE_DELIMETER));
             return ajax;
-        }
-        catch (Exception e)
-        {
+        } catch (Exception e) {
             return AjaxResult.error(e.getMessage());
         }
     }
@@ -143,12 +139,9 @@ public class CommonController
      */
     @GetMapping("/download/resource")
     public void resourceDownload(String resource, HttpServletRequest request, HttpServletResponse response)
-            throws Exception
-    {
-        try
-        {
-            if (!FileUtils.checkAllowDownload(resource))
-            {
+            throws Exception {
+        try {
+            if (!FileUtils.checkAllowDownload(resource)) {
                 throw new Exception(StringUtils.format("资源文件({})非法,不允许下载。 ", resource));
             }
             // 本地资源路径
@@ -160,19 +153,55 @@ public class CommonController
             response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
             FileUtils.setAttachmentResponseHeader(response, downloadName);
             FileUtils.writeBytes(downloadPath, response.getOutputStream());
-        }
-        catch (Exception e)
-        {
+        } catch (Exception e) {
             log.error("下载文件失败", e);
         }
     }
 
+    /**
+     * 上传Excel文件并导入敏感词数据到数据库
+     * <p>
+     * 上传Excel文件并导入敏感词数据到数据库。
+     * 支持的文件格式:.xls, .xlsx
+     * Excel文件格式要求:
+     * - 第一行:表头(敏感词、分类、等级、状态、备注)
+     * - 第二行起:数据行
+     * </p>
+     *
+     * @param file Excel文件
+     * @return AjaxResult 导入结果,包含导入统计信息
+     */
+    @ApiOperation("上传Excel文件并导入敏感词数据到数据库")
+    @PostMapping("/importSensitiveWords")
+    public AjaxResult importSensitiveWords(MultipartFile file) {
+        try {
+            // 上传文件
+            AjaxResult ajaxResult = fileService.uploadFile(file);
+            log.info("上传文件结果:{}", JSON.toJSONString(ajaxResult));
+            int code = (int) ajaxResult.get("code");
+            // 检查上传是否成功
+            if (code != 200) {
+                return ajaxResult;
+            }
+
+            log.info("开始导入敏感词Excel文件,文件名:{}", file.getOriginalFilename());
+
+            // 调用服务层导入数据
+            String result = sensitiveWordService.importFromExcel(file);
+            log.info("敏感词Excel文件导入完成:{}", result);
+            return AjaxResult.success(result);
+        } catch (Exception e) {
+            log.error("导入敏感词Excel文件失败", e);
+            return AjaxResult.error("导入失败:" + e.getMessage());
+        }
+    }
+
 
     /**
      * 删除文件
      *
      * @param fileName 文件名称
-     * @param delete 是否删除
+     * @param delete   是否删除
      */
     @GetMapping("/delete")
     public void filedelete(String fileName, Boolean delete, HttpServletResponse response, HttpServletRequest request) {

+ 0 - 13
nightFragrance-admin/src/main/java/com/ylx/web/controller/massage/TCommentController.java

@@ -38,19 +38,6 @@ public class TCommentController extends BaseController {
     private TOrderService orderService;
 
 
-    /**
-     * 用户端新增评论
-     *
-     * @param comment
-     * @return R
-     */
-    @ApiOperation("新增评论")
-    @RequestMapping(value = "wx/add", method = RequestMethod.POST)
-    public R add(@RequestBody TComment comment) {
-
-        WxLoginUser wxLoginUser = getWxLoginUser();
-        return R.ok(commentService.saveComment(comment,wxLoginUser));
-    }
 
     /**
      * 后台管理新增评论

+ 91 - 18
nightFragrance-admin/src/main/java/com/ylx/web/controller/massage/TCommentUserController.java

@@ -1,18 +1,22 @@
 package com.ylx.web.controller.massage;
 
-
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.github.pagehelper.PageHelper;
 import com.ylx.common.core.controller.BaseController;
 import com.ylx.common.core.domain.R;
+import com.ylx.common.core.domain.model.WxLoginUser;
+import com.ylx.common.utils.SecurityUtils;
+import com.ylx.massage.domain.TComment;
 import com.ylx.massage.domain.TCommentUser;
+import com.ylx.massage.service.TCommentUserAuditService;
 import com.ylx.massage.service.TCommentUserService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import io.swagger.annotations.ApiOperation;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.web.bind.annotation.*;
 
 import javax.annotation.Resource;
@@ -30,35 +34,41 @@ import java.util.List;
 @RequestMapping("tCommentUser")
 @Api(tags = {"用户评论"})
 public class TCommentUserController extends BaseController {
-    /**
-     * 服务对象
-     */
+
     @Resource
     private TCommentUserService tCommentUserService;
 
+    @Resource
+    private TCommentUserAuditService tCommentUserAuditService;
+
     /**
-     * 分页查询所有评论数据
+     * 分页查询所有用户评论数据
      *
-     * @param page         分页对象
+     * @param current
+     * @param size
      * @param tCommentUser
      * @return R
      */
     @GetMapping("selectAll")
     @ApiOperation("分页查询所有评论数据")
-    public R selectAll(Page<TCommentUser> page, TCommentUser tCommentUser) {
-        LambdaQueryWrapper<TCommentUser> tCommentUserLambdaQueryWrapper = new LambdaQueryWrapper<>();
-        tCommentUserLambdaQueryWrapper.eq(TCommentUser::getOpenId, tCommentUser.getOpenId());
-        return R.ok(this.tCommentUserService.page(page, tCommentUserLambdaQueryWrapper));
+    public R selectAll(@RequestParam Integer current, @RequestParam Integer size, TCommentUser tCommentUser) {
+        try {
+            PageHelper.startPage(current, size);
+            return R.ok(tCommentUserService.selectAll(tCommentUser));
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new RuntimeException(e);
+        }
     }
 
     /**
-     * 通过主键查询单条数据
+     * 通过主键查询单条评论数据
      *
      * @param id 主键
-     * @return 单条数据
+     * @return R
      */
     @GetMapping("{id}")
-    @ApiOperation("通过主键查询单条数据")
+    @ApiOperation("通过主键查询单条评论数据")
     public R selectOne(@PathVariable Serializable id) {
         return R.ok(this.tCommentUserService.getById(id));
     }
@@ -76,28 +86,91 @@ public class TCommentUserController extends BaseController {
         return R.ok(this.tCommentUserService.save(tCommentUser));
     }
 
+
+    /**
+     * 新增用户评论(用户端)
+     *
+     * @param commentUser
+     * @return R
+     */
+    @ApiOperation("新增用户评论")
+    @RequestMapping(value = "wx/add", method = RequestMethod.POST)
+    public R add(@RequestBody TCommentUser commentUser) {
+        try {
+            //WxLoginUser wxLoginUser = getWxLoginUser();
+            return R.ok(tCommentUserService.saveComment(commentUser, null));
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new RuntimeException(e);
+        }
+    }
+
     /**
-     * 修改数据
+     * 修改用户评论数据
      *
      * @param tCommentUser 实体对象
      * @return 修改结果
      */
     @PostMapping("update")
-    @ApiOperation("修改数据")
+    @ApiOperation("修改用户评论数据")
     public R update(@RequestBody TCommentUser tCommentUser) {
         return R.ok(this.tCommentUserService.updateById(tCommentUser));
     }
 
     /**
-     * 删除数据
+     * 删除用户评论数据
      *
      * @param idList 主键结合
      * @return 删除结果
      */
     @PostMapping("delete")
-    @ApiOperation("删除数据")
+    @ApiOperation("删除用户评论数据")
     public R delete(@RequestBody List<String> idList) {
         return R.ok(this.tCommentUserService.removeByIds(idList));
     }
+
+    /**
+     * 审核用户评论
+     * <p>
+     * 管理员审核用户提交的评论,可以选择通过或拒绝。
+     * 审核通过后,评论状态更新为"通过";
+     * 审核拒绝时,需要填写拒绝理由,评论状态更新为"拒绝"。
+     * </p>
+     *
+     * @param commentId 评论ID,必填
+     * @param auditStatus 审核状态:1-通过,2-拒绝,必填
+     * @param auditReason 审核原因/拒绝理由,审核拒绝时必填
+     * @return R 操作结果
+     */
+    @PostMapping("audit")
+    @ApiOperation("审核用户评论")
+    public R auditComment(
+            @RequestParam String commentId,
+            @RequestParam Integer auditStatus,
+            @RequestParam(required = false) String auditReason) {
+        try {
+            // 获取当前登录用户信息
+            String auditorId = SecurityUtils.getUserId().toString();
+            String auditorName = SecurityUtils.getUsername();
+
+            // 调用审核服务
+            Boolean result = tCommentUserAuditService.auditComment(
+                    commentId,
+                    auditStatus,
+                    auditReason,
+                    auditorId,
+                    auditorName
+            );
+
+            if (result) {
+                return R.ok("审核成功");
+            } else {
+                return R.fail("审核失败");
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            return R.fail(e.getMessage());
+        }
+    }
 }
 

+ 5 - 0
nightFragrance-admin/src/main/java/com/ylx/web/controller/massage/WxController.java

@@ -233,6 +233,11 @@ public class WxController extends BaseController {
 
     /**
      * 登录接口
+     * @param code
+     * @param encryptedData
+     * @param iv
+     * @param parentOpenId
+     * @return R<Object>
      */
     @ApiOperation("小程序登录")
     @Log(title = "小程序登录", businessType = BusinessType.OTHER)

+ 4 - 4
nightFragrance-admin/src/main/resources/application-dev.yml

@@ -177,7 +177,6 @@ mybatis-plus:
   configLocation: classpath:mybatis/mybatis-config.xml
   global-config:
     db-config:
-      logic-delete-field: flag # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2)
       logic-delete-value: 1 # 逻辑已删除值(默认为 1)
       logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
 
@@ -243,9 +242,10 @@ wx:
   # 微信公众号
 wechat:
 
-  mpAppId: wxa408092ddcec15b8
-
-  mpAppSecret: 3d0953e32e84180b945ace15050365c6
+#  mpAppId: wxa408092ddcec15b8
+#  mpAppSecret: 3d0953e32e84180b945ace15050365c6
+  mpAppId: wxa72f643173a90106
+  mpAppSecret: 6ceb4647506a4f1654bb10773b227357
   # 获取code
   get-code-url: https://open.weixin.qq.com/connect/oauth2/authorize
   # 回调地址

+ 0 - 1
nightFragrance-admin/src/main/resources/application-pro.yml

@@ -245,7 +245,6 @@ wechat:
   # mpAppSecret: 6ceb4647506a4f1654bb10773b227357
   # 广誉源
   mpAppId: wx9dc677bd41e82569
-
   mpAppSecret: 346ed2d83c0cab7816c73a1df2e04df3
   # 获取code
   get-code-url: https://open.weixin.qq.com/connect/oauth2/authorize

+ 0 - 2
nightFragrance-admin/src/main/resources/application-test.yml

@@ -179,7 +179,6 @@ mybatis-plus:
   configLocation: classpath:mybatis/mybatis-config.xml
   global-config:
     db-config:
-      logic-delete-field: flag # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2)
       logic-delete-value: 1 # 逻辑已删除值(默认为 1)
       logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
 
@@ -240,7 +239,6 @@ wx:
 wechat:
 
   mpAppId: wxa72f643173a90106
-
   mpAppSecret: 6ceb4647506a4f1654bb10773b227357
   # 获取code
   get-code-url: https://open.weixin.qq.com/connect/oauth2/authorize

+ 1 - 1
nightFragrance-admin/src/main/resources/application.yml

@@ -1,5 +1,5 @@
 spring:
   profiles:
-    active: dev
+    active: test
 #  profiles:
 #    active: druid

+ 6 - 0
nightFragrance-common/src/main/java/com/ylx/common/core/domain/model/WxLoginUser.java

@@ -53,8 +53,14 @@ public class WxLoginUser implements UserDetails {
      */
     private String os;
 
+    /**
+     * 昵称
+     */
     private String nickName;
 
+    /**
+     * 服务号登录凭证(code)
+     */
     private String code;
 
     /**

+ 38 - 73
nightFragrance-common/src/main/java/com/ylx/common/utils/file/FileUploadUtils.java

@@ -5,6 +5,7 @@ import java.io.FileInputStream;
 import java.io.IOException;
 import java.nio.file.Paths;
 import java.util.Objects;
+
 import org.apache.commons.io.FilenameUtils;
 import org.apache.http.entity.ContentType;
 import org.springframework.mock.web.MockMultipartFile;
@@ -23,8 +24,7 @@ import com.ylx.common.utils.uuid.Seq;
  *
  * @author ylx
  */
-public class FileUploadUtils
-{
+public class FileUploadUtils {
     /**
      * 默认大小 50M
      */
@@ -40,13 +40,11 @@ public class FileUploadUtils
      */
     private static String defaultBaseDir = RuoYiConfig.getProfile();
 
-    public static void setDefaultBaseDir(String defaultBaseDir)
-    {
+    public static void setDefaultBaseDir(String defaultBaseDir) {
         FileUploadUtils.defaultBaseDir = defaultBaseDir;
     }
 
-    public static String getDefaultBaseDir()
-    {
+    public static String getDefaultBaseDir() {
         return defaultBaseDir;
     }
 
@@ -57,14 +55,10 @@ public class FileUploadUtils
      * @return 文件名称
      * @throws Exception
      */
-    public static final String upload(MultipartFile file) throws IOException
-    {
-        try
-        {
+    public static final String upload(MultipartFile file) throws IOException {
+        try {
             return upload(getDefaultBaseDir(), file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
-        }
-        catch (Exception e)
-        {
+        } catch (Exception e) {
             throw new IOException(e.getMessage(), e);
         }
     }
@@ -73,31 +67,26 @@ public class FileUploadUtils
      * 根据文件路径上传
      *
      * @param baseDir 相对应用的基目录
-     * @param file 上传的文件
+     * @param file    上传的文件
      * @return 文件名称
      * @throws IOException
      */
-    public static final String upload(String baseDir, MultipartFile file) throws IOException
-    {
-        try
-        {
+    public static final String upload(String baseDir, MultipartFile file) throws IOException {
+        try {
             return upload(baseDir, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
-        }
-        catch (Exception e)
-        {
+        } catch (Exception e) {
             throw new IOException(e.getMessage(), e);
         }
     }
 
 
-
-    public static MultipartFile getMultipartFile (File file) {
+    public static MultipartFile getMultipartFile(File file) {
 //        String path = "export/demo.xlsx";
 //        File file = new File(path);
         MultipartFile multipartFile;
         try {
             FileInputStream fileInputStream = new FileInputStream(file);
-            multipartFile = new MockMultipartFile("copy"+file.getName(),file.getName(), ContentType.APPLICATION_OCTET_STREAM.toString(),fileInputStream);
+            multipartFile = new MockMultipartFile("copy" + file.getName(), file.getName(), ContentType.APPLICATION_OCTET_STREAM.toString(), fileInputStream);
             System.out.println(multipartFile.getName()); // 输出demo.xlsx
             fileInputStream.close();
         } catch (Exception e) {
@@ -109,22 +98,20 @@ public class FileUploadUtils
     /**
      * 文件上传
      *
-     * @param baseDir 相对应用的基目录
-     * @param file 上传的文件
+     * @param baseDir          相对应用的基目录
+     * @param file             上传的文件
      * @param allowedExtension 上传文件类型
      * @return 返回上传成功的文件名
-     * @throws FileSizeLimitExceededException 如果超出最大大小
+     * @throws FileSizeLimitExceededException       如果超出最大大小
      * @throws FileNameLengthLimitExceededException 文件名太长
-     * @throws IOException 比如读写文件出错时
-     * @throws InvalidExtensionException 文件校验异常
+     * @throws IOException                          比如读写文件出错时
+     * @throws InvalidExtensionException            文件校验异常
      */
     public static final String upload(String baseDir, MultipartFile file, String[] allowedExtension)
             throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException,
-            InvalidExtensionException
-    {
+            InvalidExtensionException {
         int fileNamelength = Objects.requireNonNull(file.getOriginalFilename()).length();
-        if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH)
-        {
+        if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH) {
             throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH);
         }
 
@@ -140,28 +127,23 @@ public class FileUploadUtils
     /**
      * 编码文件名
      */
-    public static final String extractFilename(MultipartFile file)
-    {
+    public static final String extractFilename(MultipartFile file) {
         return StringUtils.format("{}/{}_{}.{}", DateUtils.datePath(),
                 FilenameUtils.getBaseName(file.getOriginalFilename()), Seq.getId(Seq.uploadSeqType), getExtension(file));
     }
 
-    public static final File getAbsoluteFile(String uploadDir, String fileName) throws IOException
-    {
+    public static final File getAbsoluteFile(String uploadDir, String fileName) throws IOException {
         File desc = new File(uploadDir + File.separator + fileName);
 
-        if (!desc.exists())
-        {
-            if (!desc.getParentFile().exists())
-            {
+        if (!desc.exists()) {
+            if (!desc.getParentFile().exists()) {
                 desc.getParentFile().mkdirs();
             }
         }
         return desc;
     }
 
-    public static final String getPathFileName(String uploadDir, String fileName) throws IOException
-    {
+    public static final String getPathFileName(String uploadDir, String fileName) throws IOException {
         int dirLastIndex = RuoYiConfig.getProfile().length() + 1;
         String currentDir = StringUtils.substring(uploadDir, dirLastIndex);
         return Constants.RESOURCE_PREFIX + "/" + currentDir + "/" + fileName;
@@ -176,40 +158,28 @@ public class FileUploadUtils
      * @throws InvalidExtensionException
      */
     public static final void assertAllowed(MultipartFile file, String[] allowedExtension)
-            throws FileSizeLimitExceededException, InvalidExtensionException
-    {
+            throws FileSizeLimitExceededException, InvalidExtensionException {
         long size = file.getSize();
-        if (size > DEFAULT_MAX_SIZE)
-        {
+        if (size > DEFAULT_MAX_SIZE) {
             throw new FileSizeLimitExceededException(DEFAULT_MAX_SIZE / 1024 / 1024);
         }
 
         String fileName = file.getOriginalFilename();
         String extension = getExtension(file);
-        if (allowedExtension != null && !isAllowedExtension(extension, allowedExtension))
-        {
-            if (allowedExtension == MimeTypeUtils.IMAGE_EXTENSION)
-            {
+        if (allowedExtension != null && !isAllowedExtension(extension, allowedExtension)) {
+            if (allowedExtension == MimeTypeUtils.IMAGE_EXTENSION) {
                 throw new InvalidExtensionException.InvalidImageExtensionException(allowedExtension, extension,
                         fileName);
-            }
-            else if (allowedExtension == MimeTypeUtils.FLASH_EXTENSION)
-            {
+            } else if (allowedExtension == MimeTypeUtils.FLASH_EXTENSION) {
                 throw new InvalidExtensionException.InvalidFlashExtensionException(allowedExtension, extension,
                         fileName);
-            }
-            else if (allowedExtension == MimeTypeUtils.MEDIA_EXTENSION)
-            {
+            } else if (allowedExtension == MimeTypeUtils.MEDIA_EXTENSION) {
                 throw new InvalidExtensionException.InvalidMediaExtensionException(allowedExtension, extension,
                         fileName);
-            }
-            else if (allowedExtension == MimeTypeUtils.VIDEO_EXTENSION)
-            {
+            } else if (allowedExtension == MimeTypeUtils.VIDEO_EXTENSION) {
                 throw new InvalidExtensionException.InvalidVideoExtensionException(allowedExtension, extension,
                         fileName);
-            }
-            else
-            {
+            } else {
                 throw new InvalidExtensionException(allowedExtension, extension, fileName);
             }
         }
@@ -222,12 +192,9 @@ public class FileUploadUtils
      * @param allowedExtension
      * @return
      */
-    public static final boolean isAllowedExtension(String extension, String[] allowedExtension)
-    {
-        for (String str : allowedExtension)
-        {
-            if (str.equalsIgnoreCase(extension))
-            {
+    public static final boolean isAllowedExtension(String extension, String[] allowedExtension) {
+        for (String str : allowedExtension) {
+            if (str.equalsIgnoreCase(extension)) {
                 return true;
             }
         }
@@ -240,11 +207,9 @@ public class FileUploadUtils
      * @param file 表单文件
      * @return 后缀名
      */
-    public static final String getExtension(MultipartFile file)
-    {
+    public static final String getExtension(MultipartFile file) {
         String extension = FilenameUtils.getExtension(file.getOriginalFilename());
-        if (StringUtils.isEmpty(extension))
-        {
+        if (StringUtils.isEmpty(extension)) {
             extension = MimeTypeUtils.getExtension(Objects.requireNonNull(file.getContentType()));
         }
         return extension;

+ 40 - 81
nightFragrance-common/src/main/java/com/ylx/common/utils/file/FileUtils.java

@@ -11,6 +11,7 @@ import java.net.URLEncoder;
 import java.nio.charset.StandardCharsets;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang3.ArrayUtils;
 import com.ylx.common.config.RuoYiConfig;
@@ -24,41 +25,32 @@ import org.apache.commons.io.FilenameUtils;
  *
  * @author ylx
  */
-public class FileUtils
-{
+public class FileUtils {
     public static String FILENAME_PATTERN = "[a-zA-Z0-9_\\-\\|\\.\\u4e00-\\u9fa5]+";
 
     /**
      * 输出指定文件的byte数组
      *
      * @param filePath 文件路径
-     * @param os 输出流
+     * @param os       输出流
      * @return
      */
-    public static void writeBytes(String filePath, OutputStream os) throws IOException
-    {
+    public static void writeBytes(String filePath, OutputStream os) throws IOException {
         FileInputStream fis = null;
-        try
-        {
+        try {
             File file = new File(filePath);
-            if (!file.exists())
-            {
+            if (!file.exists()) {
                 throw new FileNotFoundException(filePath);
             }
             fis = new FileInputStream(file);
             byte[] b = new byte[1024];
             int length;
-            while ((length = fis.read(b)) > 0)
-            {
+            while ((length = fis.read(b)) > 0) {
                 os.write(b, 0, length);
             }
-        }
-        catch (IOException e)
-        {
+        } catch (IOException e) {
             throw e;
-        }
-        finally
-        {
+        } finally {
             IOUtils.close(os);
             IOUtils.close(fis);
         }
@@ -71,33 +63,28 @@ public class FileUtils
      * @return 目标文件
      * @throws IOException IO异常
      */
-    public static String writeImportBytes(byte[] data) throws IOException
-    {
+    public static String writeImportBytes(byte[] data) throws IOException {
         return writeBytes(data, RuoYiConfig.getImportPath());
     }
 
     /**
      * 写数据到文件中
      *
-     * @param data 数据
+     * @param data      数据
      * @param uploadDir 目标文件
      * @return 目标文件
      * @throws IOException IO异常
      */
-    public static String writeBytes(byte[] data, String uploadDir) throws IOException
-    {
+    public static String writeBytes(byte[] data, String uploadDir) throws IOException {
         FileOutputStream fos = null;
         String pathName = "";
-        try
-        {
+        try {
             String extension = getFileExtendName(data);
             pathName = DateUtils.datePath() + "/" + IdUtils.fastUUID() + "." + extension;
             File file = FileUploadUtils.getAbsoluteFile(uploadDir, pathName);
             fos = new FileOutputStream(file);
             fos.write(data);
-        }
-        finally
-        {
+        } finally {
             IOUtils.close(fos);
         }
         return FileUploadUtils.getPathFileName(uploadDir, pathName);
@@ -107,15 +94,13 @@ public class FileUtils
      * 删除文件
      *
      * @param filePath 文件
-     * @return
+     * @return boolean
      */
-    public static boolean deleteFile(String filePath)
-    {
+    public static boolean deleteFile(String filePath) {
         boolean flag = false;
         File file = new File(filePath);
         // 路径为文件且不为空则进行删除
-        if (file.isFile() && file.exists())
-        {
+        if (file.isFile() && file.exists()) {
             flag = file.delete();
         }
         return flag;
@@ -127,8 +112,7 @@ public class FileUtils
      * @param filename 文件名称
      * @return true 正常 false 非法
      */
-    public static boolean isValidFilename(String filename)
-    {
+    public static boolean isValidFilename(String filename) {
         return filename.matches(FILENAME_PATTERN);
     }
 
@@ -136,19 +120,16 @@ public class FileUtils
      * 检查文件是否可下载
      *
      * @param resource 需要下载的文件
-     * @return true 正常 false 非法
+     * @return boolean true 正常 false 非法
      */
-    public static boolean checkAllowDownload(String resource)
-    {
+    public static boolean checkAllowDownload(String resource) {
         // 禁止目录上跳级别
-        if (StringUtils.contains(resource, ".."))
-        {
+        if (StringUtils.contains(resource, "..")) {
             return false;
         }
 
         // 检查允许下载的文件规则
-        if (ArrayUtils.contains(MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION, FileTypeUtils.getFileType(resource)))
-        {
+        if (ArrayUtils.contains(MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION, FileTypeUtils.getFileType(resource))) {
             return true;
         }
 
@@ -159,32 +140,24 @@ public class FileUtils
     /**
      * 下载文件名重新编码
      *
-     * @param request 请求对象
+     * @param request  请求对象
      * @param fileName 文件名
      * @return 编码后的文件名
      */
-    public static String setFileDownloadHeader(HttpServletRequest request, String fileName) throws UnsupportedEncodingException
-    {
+    public static String setFileDownloadHeader(HttpServletRequest request, String fileName) throws UnsupportedEncodingException {
         final String agent = request.getHeader("USER-AGENT");
         String filename = fileName;
-        if (agent.contains("MSIE"))
-        {
+        if (agent.contains("MSIE")) {
             // IE浏览器
             filename = URLEncoder.encode(filename, "utf-8");
             filename = filename.replace("+", " ");
-        }
-        else if (agent.contains("Firefox"))
-        {
+        } else if (agent.contains("Firefox")) {
             // 火狐浏览器
             filename = new String(fileName.getBytes(), "ISO8859-1");
-        }
-        else if (agent.contains("Chrome"))
-        {
+        } else if (agent.contains("Chrome")) {
             // google浏览器
             filename = URLEncoder.encode(filename, "utf-8");
-        }
-        else
-        {
+        } else {
             // 其它浏览器
             filename = URLEncoder.encode(filename, "utf-8");
         }
@@ -194,11 +167,10 @@ public class FileUtils
     /**
      * 下载文件名重新编码
      *
-     * @param response 响应对象
+     * @param response     响应对象
      * @param realFileName 真实文件名
      */
-    public static void setAttachmentResponseHeader(HttpServletResponse response, String realFileName) throws UnsupportedEncodingException
-    {
+    public static void setAttachmentResponseHeader(HttpServletResponse response, String realFileName) throws UnsupportedEncodingException {
         String percentEncodedFileName = percentEncode(realFileName);
 
         StringBuilder contentDispositionValue = new StringBuilder();
@@ -220,8 +192,7 @@ public class FileUtils
      * @param s 需要百分号编码的字符串
      * @return 百分号编码后的字符串
      */
-    public static String percentEncode(String s) throws UnsupportedEncodingException
-    {
+    public static String percentEncode(String s) throws UnsupportedEncodingException {
         String encode = URLEncoder.encode(s, StandardCharsets.UTF_8.toString());
         return encode.replaceAll("\\+", "%20");
     }
@@ -232,24 +203,16 @@ public class FileUtils
      * @param photoByte 图像数据
      * @return 后缀名
      */
-    public static String getFileExtendName(byte[] photoByte)
-    {
+    public static String getFileExtendName(byte[] photoByte) {
         String strFileExtendName = "jpg";
         if ((photoByte[0] == 71) && (photoByte[1] == 73) && (photoByte[2] == 70) && (photoByte[3] == 56)
-                && ((photoByte[4] == 55) || (photoByte[4] == 57)) && (photoByte[5] == 97))
-        {
+                && ((photoByte[4] == 55) || (photoByte[4] == 57)) && (photoByte[5] == 97)) {
             strFileExtendName = "gif";
-        }
-        else if ((photoByte[6] == 74) && (photoByte[7] == 70) && (photoByte[8] == 73) && (photoByte[9] == 70))
-        {
+        } else if ((photoByte[6] == 74) && (photoByte[7] == 70) && (photoByte[8] == 73) && (photoByte[9] == 70)) {
             strFileExtendName = "jpg";
-        }
-        else if ((photoByte[0] == 66) && (photoByte[1] == 77))
-        {
+        } else if ((photoByte[0] == 66) && (photoByte[1] == 77)) {
             strFileExtendName = "bmp";
-        }
-        else if ((photoByte[1] == 80) && (photoByte[2] == 78) && (photoByte[3] == 71))
-        {
+        } else if ((photoByte[1] == 80) && (photoByte[2] == 78) && (photoByte[3] == 71)) {
             strFileExtendName = "png";
         }
         return strFileExtendName;
@@ -261,10 +224,8 @@ public class FileUtils
      * @param fileName 路径名称
      * @return 没有文件路径的名称
      */
-    public static String getName(String fileName)
-    {
-        if (fileName == null)
-        {
+    public static String getName(String fileName) {
+        if (fileName == null) {
             return null;
         }
         int lastUnixPos = fileName.lastIndexOf('/');
@@ -279,10 +240,8 @@ public class FileUtils
      * @param fileName 路径名称
      * @return 没有文件路径和后缀的名称
      */
-    public static String getNameNotSuffix(String fileName)
-    {
-        if (fileName == null)
-        {
+    public static String getNameNotSuffix(String fileName) {
+        if (fileName == null) {
             return null;
         }
         String baseName = FilenameUtils.getBaseName(fileName);

+ 0 - 132
nightFragrance-framework/src/main/java/com/ylx/framework/config/MyBatisConfig.java

@@ -1,132 +0,0 @@
-//package com.ylx.framework.config;
-//
-//import java.io.IOException;
-//import java.util.ArrayList;
-//import java.util.Arrays;
-//import java.util.HashSet;
-//import java.util.List;
-//import javax.sql.DataSource;
-//import org.apache.ibatis.io.VFS;
-//import org.apache.ibatis.session.SqlSessionFactory;
-//import org.mybatis.spring.SqlSessionFactoryBean;
-//import org.mybatis.spring.boot.autoconfigure.SpringBootVFS;
-//import org.springframework.beans.factory.annotation.Autowired;
-//import org.springframework.context.annotation.Bean;
-//import org.springframework.context.annotation.Configuration;
-//import org.springframework.core.env.Environment;
-//import org.springframework.core.io.DefaultResourceLoader;
-//import org.springframework.core.io.Resource;
-//import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
-//import org.springframework.core.io.support.ResourcePatternResolver;
-//import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
-//import org.springframework.core.type.classreading.MetadataReader;
-//import org.springframework.core.type.classreading.MetadataReaderFactory;
-//import org.springframework.util.ClassUtils;
-//import com.ylx.common.utils.StringUtils;
-//
-///**
-// * Mybatis支持*匹配扫描包
-// *
-// * @author ylx
-// */
-//@Configuration
-//public class MyBatisConfig
-//{
-//    @Autowired
-//    private Environment env;
-//
-//    static final String DEFAULT_RESOURCE_PATTERN = "**/*.class";
-//
-//    public static String setTypeAliasesPackage(String typeAliasesPackage)
-//    {
-//        ResourcePatternResolver resolver = (ResourcePatternResolver) new PathMatchingResourcePatternResolver();
-//        MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(resolver);
-//        List<String> allResult = new ArrayList<String>();
-//        try
-//        {
-//            for (String aliasesPackage : typeAliasesPackage.split(","))
-//            {
-//                List<String> result = new ArrayList<String>();
-//                aliasesPackage = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
-//                        + ClassUtils.convertClassNameToResourcePath(aliasesPackage.trim()) + "/" + DEFAULT_RESOURCE_PATTERN;
-//                Resource[] resources = resolver.getResources(aliasesPackage);
-//                if (resources != null && resources.length > 0)
-//                {
-//                    MetadataReader metadataReader = null;
-//                    for (Resource resource : resources)
-//                    {
-//                        if (resource.isReadable())
-//                        {
-//                            metadataReader = metadataReaderFactory.getMetadataReader(resource);
-//                            try
-//                            {
-//                                result.add(Class.forName(metadataReader.getClassMetadata().getClassName()).getPackage().getName());
-//                            }
-//                            catch (ClassNotFoundException e)
-//                            {
-//                                e.printStackTrace();
-//                            }
-//                        }
-//                    }
-//                }
-//                if (result.size() > 0)
-//                {
-//                    HashSet<String> hashResult = new HashSet<String>(result);
-//                    allResult.addAll(hashResult);
-//                }
-//            }
-//            if (allResult.size() > 0)
-//            {
-//                typeAliasesPackage = String.join(",", (String[]) allResult.toArray(new String[0]));
-//            }
-//            else
-//            {
-//                throw new RuntimeException("mybatis typeAliasesPackage 路径扫描错误,参数typeAliasesPackage:" + typeAliasesPackage + "未找到任何包");
-//            }
-//        }
-//        catch (IOException e)
-//        {
-//            e.printStackTrace();
-//        }
-//        return typeAliasesPackage;
-//    }
-//
-//    public Resource[] resolveMapperLocations(String[] mapperLocations)
-//    {
-//        ResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver();
-//        List<Resource> resources = new ArrayList<Resource>();
-//        if (mapperLocations != null)
-//        {
-//            for (String mapperLocation : mapperLocations)
-//            {
-//                try
-//                {
-//                    Resource[] mappers = resourceResolver.getResources(mapperLocation);
-//                    resources.addAll(Arrays.asList(mappers));
-//                }
-//                catch (IOException e)
-//                {
-//                    // ignore
-//                }
-//            }
-//        }
-//        return resources.toArray(new Resource[resources.size()]);
-//    }
-//
-//    @Bean
-//    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception
-//    {
-//        String typeAliasesPackage = env.getProperty("mybatis.typeAliasesPackage");
-//        String mapperLocations = env.getProperty("mybatis.mapperLocations");
-//        String configLocation = env.getProperty("mybatis.configLocation");
-//        typeAliasesPackage = setTypeAliasesPackage(typeAliasesPackage);
-//        VFS.addImplClass(SpringBootVFS.class);
-//
-//        final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
-//        sessionFactory.setDataSource(dataSource);
-//        sessionFactory.setTypeAliasesPackage(typeAliasesPackage);
-//        sessionFactory.setMapperLocations(resolveMapperLocations(StringUtils.split(mapperLocations, ",")));
-//        sessionFactory.setConfigLocation(new DefaultResourceLoader().getResource(configLocation));
-//        return sessionFactory.getObject();
-//    }
-//}

+ 5 - 10
nightFragrance-framework/src/main/java/com/ylx/framework/config/MybatisPlusConfig.java

@@ -16,11 +16,9 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
  */
 @EnableTransactionManagement(proxyTargetClass = true)
 @Configuration
-public class MybatisPlusConfig
-{
+public class MybatisPlusConfig {
     @Bean
-    public MybatisPlusInterceptor mybatisPlusInterceptor()
-    {
+    public MybatisPlusInterceptor mybatisPlusInterceptor() {
         MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
         // 分页插件
         interceptor.addInnerInterceptor(paginationInnerInterceptor());
@@ -34,8 +32,7 @@ public class MybatisPlusConfig
     /**
      * 分页插件,自动识别数据库类型 https://baomidou.com/guide/interceptor-pagination.html
      */
-    public PaginationInnerInterceptor paginationInnerInterceptor()
-    {
+    public PaginationInnerInterceptor paginationInnerInterceptor() {
         PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();
         // 设置数据库类型为mysql
         paginationInnerInterceptor.setDbType(DbType.MYSQL);
@@ -47,16 +44,14 @@ public class MybatisPlusConfig
     /**
      * 乐观锁插件 https://baomidou.com/guide/interceptor-optimistic-locker.html
      */
-    public OptimisticLockerInnerInterceptor optimisticLockerInnerInterceptor()
-    {
+    public OptimisticLockerInnerInterceptor optimisticLockerInnerInterceptor() {
         return new OptimisticLockerInnerInterceptor();
     }
 
     /**
      * 如果是对全表的删除或更新操作,就会终止该操作 https://baomidou.com/guide/interceptor-block-attack.html
      */
-    public BlockAttackInnerInterceptor blockAttackInnerInterceptor()
-    {
+    public BlockAttackInnerInterceptor blockAttackInnerInterceptor() {
         return new BlockAttackInnerInterceptor();
     }
 }

+ 4 - 6
nightFragrance-framework/src/main/java/com/ylx/framework/config/ServerConfig.java

@@ -1,6 +1,7 @@
 package com.ylx.framework.config;
 
 import javax.servlet.http.HttpServletRequest;
+
 import org.springframework.stereotype.Component;
 import com.ylx.common.utils.ServletUtils;
 
@@ -10,21 +11,18 @@ import com.ylx.common.utils.ServletUtils;
  * @author ylx
  */
 @Component
-public class ServerConfig
-{
+public class ServerConfig {
     /**
      * 获取完整的请求路径,包括:域名,端口,上下文访问路径
      *
      * @return 服务地址
      */
-    public String getUrl()
-    {
+    public String getUrl() {
         HttpServletRequest request = ServletUtils.getRequest();
         return getDomain(request);
     }
 
-    public static String getDomain(HttpServletRequest request)
-    {
+    public static String getDomain(HttpServletRequest request) {
         StringBuffer url = request.getRequestURL();
         String contextPath = request.getServletContext().getContextPath();
         return url.delete(url.length() - request.getRequestURI().length(), url.length()).append(contextPath).toString();

+ 84 - 0
nightFragrance-massage/src/main/java/com/ylx/massage/domain/CommentUserAudit.java

@@ -0,0 +1,84 @@
+package com.ylx.massage.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableLogic;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+import java.util.Date;
+
+/**
+ * 用户评论审核表
+ */
+@Data
+@TableName("t_comment_user_audit")
+public class CommentUserAudit implements Serializable {
+
+
+    private static final long serialVersionUID = 8877376996541735719L;
+
+    /**
+     * 主键
+     */
+    @TableId(type = IdType.ASSIGN_ID)
+    private String id;
+
+    /**
+     * 评论ID
+     */
+    private String commentId;
+
+    /**
+     * 订单号
+     */
+    private String orderNo;
+
+    /**
+     * 评论内容
+     */
+    private String text;
+
+    /**
+     * 审核状态:0待审核 1通过 2拒绝
+     */
+    private Integer auditStatus;
+
+    /**
+     * 审核原因/拒绝理由
+     */
+    private String auditReason;
+
+    /**
+     * 审核人ID
+     */
+    private String auditorId;
+
+    /**
+     * 审核人姓名
+     */
+    private String auditorName;
+
+    /**
+     * 审核时间
+     */
+    private Date auditTime;
+
+    /**
+     * 创建时间
+     */
+    private Date createTime;
+
+    /**
+     * 修改时间
+     */
+    private Date updateTime;
+
+    /**
+     * 是否删除 0否 1是
+     */
+    @TableLogic
+    private Integer isDelete;
+}

+ 57 - 0
nightFragrance-massage/src/main/java/com/ylx/massage/domain/SensitiveWord.java

@@ -0,0 +1,57 @@
+package com.ylx.massage.domain;
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import java.time.LocalDateTime;
+import java.util.Date;
+
+/**
+ * 敏感词库实体类
+ */
+@Data
+@TableName("t_sensitive_word")
+public class SensitiveWord {
+
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 敏感词
+     */
+    private String word;
+
+    /**
+     * 敏感词分类:政治敏感类、色情低俗类、暴力恐怖类、辱骂攻击类
+     */
+    private String category;
+
+    /**
+     * 敏感等级:1-低 2-中 3-高
+     */
+    private Integer level;
+
+    /**
+     * 状态:0-禁用 1-启用
+     */
+    private Integer status;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+    /**
+     * 创建时间
+     */
+    private Date createTime;
+
+    /**
+     * 更新时间
+     */
+    private Date updateTime;
+
+    /**
+     * 是否删除(0-否 1-是)
+     */
+    @TableLogic
+    private Integer isDelete;
+}

+ 104 - 19
nightFragrance-massage/src/main/java/com/ylx/massage/domain/TCommentUser.java

@@ -2,7 +2,9 @@ package com.ylx.massage.domain;
 
 
 
+import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableLogic;
+import com.baomidou.mybatisplus.annotation.TableName;
 import com.baomidou.mybatisplus.extension.activerecord.Model;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
@@ -12,47 +14,130 @@ import java.io.Serializable;
 import java.util.Date;
 
 /**
- * 用户评论表(TCommentUser)表实体类
+ * 用户评论实体类
+ * <p>
+ * 对应数据库表 t_comment_user,用于存储用户对技师的评论信息。
+ * 继承自 MyBatis-Plus 的 Model 类,支持 ActiveRecord 模式操作。
+ * 使用 Lombok 的 @Data 注解自动生成 getter/setter 等方法。
+ * 启用逻辑删除功能,isDelete 字段标记记录是否已删除(0-有效,1-已删除)。
+ * </p>
  *
- * @author makejava
- * @since 2024-08-08 10:32:07
+ * @author ylx
+ * @version 1.0
+ * @since 2024-08-08
  */
 @Data
 @ApiModel(value = "TCommentUser", description = "用户评论")
+@TableName("t_comment_user")
 @SuppressWarnings("serial")
 public class TCommentUser extends Model<TCommentUser> {
-    //主键
+
+    /**
+     * 主键ID
+     * 唯一标识一条评论记录
+     */
     @ApiModelProperty("主键")
     private String id;
-    //评论内容
-    @ApiModelProperty("评论内容")
-    private String text;
-    //订单号
+
+    /**
+     * 用户OpenID
+     * 微信用户的唯一标识,用于关联评论发布者
+     */
+    @ApiModelProperty("用户openid")
+    private String openId;
+
+    /**
+     * 订单号
+     * 关联的订单编号,用于关联具体的服务订单
+     */
     @ApiModelProperty("订单号")
     private String orderNo;
-    //技师id
+
+    /**
+     * 订单id
+     */
+    @TableField(exist = false)
+    @ApiModelProperty("订单id")
+    private String orderId;
+
+    /**
+     * 评论内容
+     * 用户对本次服务评价的文本内容
+     */
+    @ApiModelProperty("评论内容")
+    private String text;
+
+    /**
+     * 是否敏感词
+     * 0-无敏感词,1-包含敏感词
+     */
+    @ApiModelProperty("是否敏感词")
+    private Integer sensitiveWord;
+
+    /**
+     * 技师ID
+     * 被评论技师的唯一标识
+     */
     @ApiModelProperty("技师id")
     private String jsId;
-    //用户openid
-    @ApiModelProperty("用户openid")
-    private String openId;
-    //评论时间
-    @ApiModelProperty("评论时间")
-    private Date commentTime;
-    //技师姓名
+
+    /**
+     * 技师姓名
+     * 冗余字段,存储被评论技师的姓名,便于查询展示
+     */
     @ApiModelProperty("技师姓名")
     private String name;
-    //系统创建时间
+
+
+    /**
+     * 评论时间
+     * 用户发布评论的时间戳
+     */
+    @ApiModelProperty("评论时间")
+    private Date commentTime;
+
+
+    /**
+     * 系统创建时间
+     * 记录创建的时间戳,由系统自动生成
+     */
     @ApiModelProperty("系统创建时间")
     private Date createTime;
-    //系统修改时间
+
+    /**
+     * 系统修改时间
+     * 记录最后更新的时间戳,由系统自动维护
+     */
     @ApiModelProperty("系统修改时间")
     private Date updateTime;
-    //是否删除0否1是
+
+    /**
+     * 逻辑删除标记
+     * 0-未删除(有效记录),1-已删除
+     * 使用 @TableLogic 注解实现逻辑删除功能
+     */
     @ApiModelProperty("是否删除0否1是")
     @TableLogic
     private Integer isDelete;
 
+    /**
+     * 昵称
+     */
+    @ApiModelProperty("昵称")
+    private String nickName;
+
+     /**
+     * 分数
+     */
+    @ApiModelProperty("分数")
+    private Integer star;
+
+    /**
+     * 审核状态:0待审核 1通过 2拒绝
+     */
+    @TableField(exist = false)
+    private Integer auditStatus;
+
     /**
      * 获取主键值
      *

+ 92 - 0
nightFragrance-massage/src/main/java/com/ylx/massage/enums/SensitiveWordCategoryEnum.java

@@ -0,0 +1,92 @@
+package com.ylx.massage.enums;
+
+/**
+ * 敏感词分类枚举
+ * <p>
+ * 定义系统中各类敏感词的分类类型,用于内容审核和敏感词过滤。
+ * 包含政治、色情、暴力、辱骂、违法犯罪、民族宗教、广告营销、网络违规、其他等多个分类。
+ * </p>
+ *
+ * @author ylx
+ * @version 1.0
+ * @since 2024
+ */
+public enum SensitiveWordCategoryEnum {
+
+    /**
+     * 政治敏感类
+     * 涉及政治人物、政治事件、政治制度等敏感内容
+     */
+    POLITICAL("政治敏感类"),
+
+    /**
+     * 色情低俗类
+     * 涉及色情、低俗、淫秽等内容
+     */
+    PORNOGRAPHY("色情低俗类"),
+
+    /**
+     * 暴力恐怖类
+     * 涉及暴力、恐怖、血腥等内容
+     */
+    VIOLENCE("暴力恐怖类"),
+
+    /**
+     * 辱骂攻击类
+     * 涉及辱骂、人身攻击、歧视等内容
+     */
+    ABUSE("辱骂攻击类"),
+
+    /**
+     * 违法犯罪类
+     * 涉及违法犯罪活动、毒品、诈骗等内容
+     */
+    CRIME("违法犯罪类"),
+
+    /**
+     * 民族宗教类
+     * 涉及民族歧视、宗教敏感、种族冲突等内容
+     */
+    ETHNIC_RELIGION("民族宗教类"),
+
+    /**
+     * 广告营销类
+     * 涉及垃圾广告、营销推广、虚假宣传等内容
+     */
+    ADVERTISEMENT("广告营销类"),
+
+    /**
+     * 网络违规类
+     * 涉及网络谣言、网络欺诈、恶意软件等内容
+     */
+    NETWORK_VIOLATION("网络违规类"),
+
+    /**
+     * 其他敏感类
+     * 其他未分类的敏感内容
+     */
+    OTHER("其他敏感类");
+
+    /**
+     * 分类描述
+     */
+    private final String desc;
+
+    /**
+     * 构造函数
+     *
+     * @param desc 分类描述
+     */
+    SensitiveWordCategoryEnum(String desc) {
+        this.desc = desc;
+    }
+
+    /**
+     * 获取分类描述
+     *
+     * @return 分类描述文本
+     */
+    public String getDesc() {
+        return desc;
+    }
+}

+ 42 - 0
nightFragrance-massage/src/main/java/com/ylx/massage/mapper/SensitiveWordMapper.java

@@ -0,0 +1,42 @@
+package com.ylx.massage.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ylx.massage.domain.SensitiveWord;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * 敏感词库数据访问层
+ * <p>
+ * 提供敏感词数据的增删改查操作,支持批量操作。
+ * </p>
+ *
+ * @author ylx
+ * @version 1.0
+ * @since 2024
+ */
+public interface SensitiveWordMapper extends BaseMapper<SensitiveWord> {
+
+    /**
+     * 批量插入敏感词数据
+     * <p>
+     * 批量插入敏感词记录,提高大批量数据插入的效率。
+     * </p>
+     *
+     * @param entities 敏感词实体列表
+     * @return 影响的行数
+     */
+    int insertBatch(@Param("entities") List<SensitiveWord> entities);
+
+    /**
+     * 根据敏感词查询记录
+     * <p>
+     * 查询指定敏感词是否已存在于数据库中,用于去重判断。
+     * </p>
+     *
+     * @param word 敏感词
+     * @return 敏感词实体,如果不存在则返回null
+     */
+    SensitiveWord selectByWord(@Param("word") String word);
+}

+ 15 - 0
nightFragrance-massage/src/main/java/com/ylx/massage/mapper/TCommentUserAuditMapper.java

@@ -0,0 +1,15 @@
+package com.ylx.massage.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ylx.massage.domain.CommentUserAudit;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 用户评论审核表(TCommentUserAudit)表数据库访问层
+ *
+ * @author makejava
+ * @since 2024-12-30 17:49:08
+ */
+@Mapper
+public interface TCommentUserAuditMapper extends BaseMapper<CommentUserAudit> {
+}

+ 9 - 0
nightFragrance-massage/src/main/java/com/ylx/massage/mapper/TCommentUserMapper.java

@@ -3,6 +3,7 @@ package com.ylx.massage.mapper;
 import java.util.List;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import org.apache.ibatis.annotations.Param;
 import com.ylx.massage.domain.TCommentUser;
 
@@ -31,5 +32,13 @@ public interface TCommentUserMapper extends BaseMapper<TCommentUser> {
      */
     int insertOrUpdateBatch(@Param("entities") List<TCommentUser> entities);
 
+    /**
+     * 分页查询用户评论
+     *
+     * @param tCommentUser
+     * @return Page<TCommentUser>
+     */
+     List<TCommentUser> selectAll(@Param("tCommentUser") TCommentUser tCommentUser);
+
 }
 

+ 46 - 0
nightFragrance-massage/src/main/java/com/ylx/massage/service/SensitiveWordService.java

@@ -0,0 +1,46 @@
+package com.ylx.massage.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ylx.massage.domain.SensitiveWord;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.util.List;
+
+/**
+ * 敏感词库服务接口
+ * <p>
+ * 提供敏感词管理的业务接口,包括敏感词的增删改查、批量导入等功能。
+ * 继承自 MyBatis-Plus 的 IService 接口,提供基础的 CRUD 操作。
+ * </p>
+ *
+ * @author ylx
+ * @version 1.0
+ * @since 2024
+ */
+public interface SensitiveWordService extends IService<SensitiveWord> {
+
+    /**
+     * 批量插入敏感词数据
+     * <p>
+     * 批量插入敏感词记录,提高大批量数据插入的效率。
+     * </p>
+     *
+     * @param entities 敏感词实体列表
+     * @return 成功插入的记录数
+     */
+    int insertBatch(List<SensitiveWord> entities);
+
+    /**
+     * 从Excel文件导入敏感词数据
+     * <p>
+     * 读取Excel文件中的敏感词数据,解析并存储到数据库中。
+     * Excel文件格式要求:
+     * - 第一行:表头(敏感词、分类、等级、状态、备注)
+     * - 第二行起:数据行
+     * </p>
+     *
+     * @param file Excel文件
+     * @return 导入结果统计信息
+     */
+    String importFromExcel(MultipartFile file);
+}

+ 35 - 0
nightFragrance-massage/src/main/java/com/ylx/massage/service/TCommentUserAuditService.java

@@ -0,0 +1,35 @@
+package com.ylx.massage.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ylx.massage.domain.CommentUserAudit;
+
+/**
+ * 用户评论审核服务接口
+ * <p>
+ * 提供用户评论审核功能的业务接口,包括审核通过、审核拒绝等操作。
+ * 继承自 MyBatis-Plus 的 IService 接口,提供基础的 CRUD 操作。
+ * </p>
+ *
+ * @author ylx
+ * @version 1.0
+ * @since 2024
+ */
+public interface TCommentUserAuditService extends IService<CommentUserAudit> {
+
+    /**
+     * 审核用户评论
+     * <p>
+     * 根据审核结果更新评论状态,并记录审核信息到审核表。
+     * 审核通过后,评论状态更新为"通过";
+     * 审核拒绝后,评论状态更新为"拒绝",并可记录拒绝原因。
+     * </p>
+     *
+     * @param commentId 评论ID,用于标识待审核的评论
+     * @param auditStatus 审核状态:1-通过,2-拒绝
+     * @param auditReason 审核原因/拒绝理由,审核拒绝时必填,审核通过时可为空
+     * @param auditorId 审核人ID,当前登录管理员的ID
+     * @param auditorName 审核人姓名,当前登录管理员的姓名
+     * @return 审核是否成功
+     */
+    Boolean auditComment(String commentId, Integer auditStatus, String auditReason, String auditorId, String auditorName);
+}

+ 22 - 0
nightFragrance-massage/src/main/java/com/ylx/massage/service/TCommentUserService.java

@@ -1,8 +1,13 @@
 package com.ylx.massage.service;
 
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.ylx.common.core.domain.model.WxLoginUser;
+import com.ylx.massage.domain.TComment;
 import com.ylx.massage.domain.TCommentUser;
 
+import java.util.List;
+
 /**
  * 用户评论表(TCommentUser)表服务接口
  *
@@ -11,5 +16,22 @@ import com.ylx.massage.domain.TCommentUser;
  */
 public interface TCommentUserService extends IService<TCommentUser> {
 
+    /**
+     * 新增评论
+     * @param comment
+     * @param wxLoginUser
+     * @return Boolean
+     */
+    Boolean saveComment(TCommentUser comment, WxLoginUser wxLoginUser);
+
+
+    /**
+     * 分页查询用户评论
+     * @param page
+     * @param tCommentUser
+     * @return Page<TCommentUser>
+     */
+     List<TCommentUser> selectAll(TCommentUser tCommentUser);
+
 }
 

+ 148 - 0
nightFragrance-massage/src/main/java/com/ylx/massage/service/impl/SensitiveWordServiceImpl.java

@@ -0,0 +1,148 @@
+package com.ylx.massage.service.impl;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ylx.common.exception.ServiceException;
+import com.ylx.massage.domain.SensitiveWord;
+import com.ylx.massage.enums.SensitiveWordCategoryEnum;
+import com.ylx.massage.mapper.SensitiveWordMapper;
+import com.ylx.massage.service.SensitiveWordService;
+import com.ylx.massage.utils.ExcelUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.annotation.Resource;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 敏感词库服务实现类
+ * <p>
+ * 提供敏感词管理功能的具体实现,包括敏感词的增删改查、批量导入等操作。
+ * 支持从Excel文件批量导入敏感词数据,自动去重,并记录导入日志。
+ * </p>
+ *
+ * @author ylx
+ * @version 1.0
+ * @since 2024
+ */
+@Service
+public class SensitiveWordServiceImpl extends ServiceImpl<SensitiveWordMapper, SensitiveWord> implements SensitiveWordService {
+
+    private static final Logger log = LoggerFactory.getLogger(SensitiveWordServiceImpl.class);
+
+    @Resource
+    private SensitiveWordMapper sensitiveWordMapper;
+
+    /**
+     * 批量插入敏感词数据
+     *
+     * @param entities 敏感词实体列表
+     * @return 成功插入的记录数
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public int insertBatch(List<SensitiveWord> entities) {
+        if (CollUtil.isEmpty(entities)) {
+            return 0;
+        }
+        return sensitiveWordMapper.insertBatch(entities);
+    }
+
+    /**
+     * 从Excel文件导入敏感词数据
+     * <p>
+     * 读取Excel文件中的敏感词数据,解析并存储到数据库中。
+     * 支持的Excel格式:.xls, .xlsx
+     * Excel文件格式要求:
+     * - 第一行:表头(敏感词、分类、等级、状态、备注)
+     * - 第二行起:数据行
+     * </p>
+     *
+     * @param file Excel文件
+     * @return 导入结果统计信息
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public String importFromExcel(MultipartFile file) {
+        try {
+            log.info("开始导入敏感词Excel文件,文件名:{}", file.getOriginalFilename());
+
+            // 1. 读取Excel文件数据
+            List<SensitiveWord> wordList = ExcelUtils.parseSensitiveWordExcel(file);
+            log.info("Excel文件解析完成,共读取 {} 行数据", wordList.size());
+
+            if (CollUtil.isEmpty(wordList)) {
+                return "导入失败:Excel文件中没有数据";
+            }
+
+            // 2. 数据校验和去重
+            List<SensitiveWord> validWords = new ArrayList<>();
+            int duplicateCount = 0;
+            int invalidCount = 0;
+
+            for (SensitiveWord word : wordList) {
+                // 校验敏感词
+                if (StrUtil.isBlank(word.getWord())) {
+                    invalidCount++;
+                    continue;
+                }
+
+                // 检查是否已存在
+                SensitiveWord existing = sensitiveWordMapper.selectByWord(word.getWord());
+                if (existing != null) {
+                    duplicateCount++;
+                    continue;
+                }
+
+                // 设置默认值
+                if (word.getLevel() == null) {
+                    // 默认低敏感等级
+                    word.setLevel(1);
+                }
+                if (word.getStatus() == null) {
+                    // 默认启用
+                    word.setStatus(1);
+                }
+                if (word.getIsDelete() == null) {
+                    // 默认未删除
+                    word.setIsDelete(0);
+                }
+                word.setCreateTime(new Date());
+                word.setUpdateTime(new Date());
+                validWords.add(word);
+            }
+
+            log.info("数据校验完成,有效数据 {} 条,重复数据 {} 条,无效数据 {} 条", validWords.size(), duplicateCount, invalidCount);
+
+            if (CollUtil.isEmpty(validWords)) {
+                return "导入失败:没有有效的数据可导入(重复或无效数据)";
+            }
+
+            // 3. 批量插入数据库
+            int batchSize = 500; // 每批最多500条
+            int totalInserted = 0;
+
+            for (int i = 0; i < validWords.size(); i += batchSize) {
+                int end = Math.min(i + batchSize, validWords.size());
+                List<SensitiveWord> batch = validWords.subList(i, end);
+                int inserted = sensitiveWordMapper.insertBatch(batch);
+                totalInserted += inserted;
+                log.info("已插入 {}/{} 条数据", totalInserted, validWords.size());
+            }
+
+            // 4. 返回导入结果
+            String result = String.format("导入成功!共读取 %d 条数据,成功导入 %d 条,重复 %d 条,无效 %d 条", wordList.size(), totalInserted, duplicateCount, invalidCount);
+            log.info(result);
+            return result;
+        } catch (Exception e) {
+            log.error("导入敏感词Excel文件失败", e);
+            throw new ServiceException("导入失败:" + e.getMessage());
+        }
+    }
+}

+ 0 - 1
nightFragrance-massage/src/main/java/com/ylx/massage/service/impl/TCommentServiceImpl.java

@@ -55,6 +55,5 @@ public class TCommentServiceImpl extends ServiceImpl<TCommentMapper, TComment> i
         order.setnStatus(OrderStatusEnum.COMPLETE.getCode());
         order.setcId(comment.getOrderId());
         return orderService.updateById(order);
-
     }
 }

+ 100 - 0
nightFragrance-massage/src/main/java/com/ylx/massage/service/impl/TCommentUserAuditServiceImpl.java

@@ -0,0 +1,100 @@
+package com.ylx.massage.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ylx.common.exception.ServiceException;
+import com.ylx.common.utils.StringUtils;
+import com.ylx.massage.domain.CommentUserAudit;
+import com.ylx.massage.domain.TCommentUser;
+import com.ylx.massage.mapper.TCommentUserAuditMapper;
+import com.ylx.massage.service.TCommentUserAuditService;
+import com.ylx.massage.service.TCommentUserService;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.annotation.Resource;
+import java.util.Date;
+
+/**
+ * 用户评论审核服务实现类
+ * <p>
+ * 提供用户评论审核功能的具体实现,包括审核通过、审核拒绝等操作。
+ * </p>
+ *
+ * @author ylx
+ * @version 1.0
+ * @since 2024
+ */
+@Service
+public class TCommentUserAuditServiceImpl extends ServiceImpl<TCommentUserAuditMapper, CommentUserAudit> implements TCommentUserAuditService {
+
+    @Resource
+    private TCommentUserService tCommentUserService;
+
+    /**
+     * 审核用户评论
+     * <p>
+     * 根据审核结果更新评论状态,并记录审核信息到审核表。
+     * 审核通过后,评论状态更新为"通过";
+     * 审核拒绝后,评论状态更新为"拒绝",并可记录拒绝原因。
+     * </p>
+     *
+     * @param commentId 评论ID,用于标识待审核的评论
+     * @param auditStatus 审核状态:1-通过,2-拒绝
+     * @param auditReason 审核原因/拒绝理由,审核拒绝时必填,审核通过时可为空
+     * @param auditorId 审核人ID,当前登录管理员的ID
+     * @param auditorName 审核人姓名,当前登录管理员的姓名
+     * @return 审核是否成功
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Boolean auditComment(String commentId, Integer auditStatus, String auditReason, String auditorId, String auditorName) {
+        // 参数校验
+        if (StringUtils.isBlank(commentId)) {
+            throw new ServiceException("评论ID不能为空");
+        }
+        if (auditStatus == null || (auditStatus != 1 && auditStatus != 2)) {
+            throw new ServiceException("审核状态无效,必须为1(通过)或2(拒绝)");
+        }
+        if (auditStatus == 2 && StringUtils.isBlank(auditReason)) {
+            throw new ServiceException("审核拒绝时必须填写拒绝理由");
+        }
+        if (StringUtils.isBlank(auditorId) || StringUtils.isBlank(auditorName)) {
+            throw new ServiceException("审核人信息不能为空");
+        }
+
+        // 查询评论是否存在
+        TCommentUser commentUser = tCommentUserService.getById(commentId);
+        if (commentUser == null) {
+            throw new ServiceException("评论不存在");
+        }
+
+        // 查询审核记录是否存在
+        LambdaQueryWrapper<CommentUserAudit> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(CommentUserAudit::getCommentId, commentId);
+        CommentUserAudit auditRecord = this.getOne(queryWrapper);
+
+        if (auditRecord == null) {
+            throw new ServiceException("审核记录不存在");
+        }
+
+        // 检查是否已审核
+        if (auditRecord.getAuditStatus() != 0) {
+            throw new ServiceException("该评论已审核,请勿重复操作");
+        }
+
+        // 更新审核记录
+        auditRecord.setAuditStatus(auditStatus);
+        auditRecord.setAuditReason(auditReason);
+        auditRecord.setAuditorId(auditorId);
+        auditRecord.setAuditorName(auditorName);
+        auditRecord.setAuditTime(new Date());
+        auditRecord.setUpdateTime(new Date());
+        boolean updateResult = this.updateById(auditRecord);
+
+        if (!updateResult) {
+            throw new ServiceException("审核记录更新失败");
+        }
+        return true;
+    }
+}

+ 77 - 0
nightFragrance-massage/src/main/java/com/ylx/massage/service/impl/TCommentUserServiceImpl.java

@@ -1,10 +1,25 @@
 package com.ylx.massage.service.impl;
 
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ylx.common.core.domain.model.WxLoginUser;
+import com.ylx.common.exception.ServiceException;
+import com.ylx.common.utils.StringUtils;
+import com.ylx.massage.domain.CommentUserAudit;
+import com.ylx.massage.domain.TComment;
+import com.ylx.massage.domain.TOrder;
+import com.ylx.massage.enums.OrderStatusEnum;
 import com.ylx.massage.mapper.TCommentUserMapper;
 import com.ylx.massage.domain.TCommentUser;
+import com.ylx.massage.service.TCommentUserAuditService;
 import com.ylx.massage.service.TCommentUserService;
+import com.ylx.massage.service.TOrderService;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.annotation.Resource;
+import java.time.LocalDateTime;
+import java.util.Date;
+import java.util.List;
 
 /**
  * 用户评论表(TCommentUser)表服务实现类
@@ -15,5 +30,67 @@ import org.springframework.stereotype.Service;
 @Service("tCommentUserService")
 public class TCommentUserServiceImpl extends ServiceImpl<TCommentUserMapper, TCommentUser> implements TCommentUserService {
 
+    @Resource
+    private TOrderService orderService;
+
+    @Resource
+    private TCommentUserAuditService commentUserAuditService;
+
+    @Resource
+    private TCommentUserMapper tCommentUserMapper;
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Boolean saveComment(TCommentUser comment, WxLoginUser wxLoginUser) {
+        //订单ID不能为空
+        if(StringUtils.isBlank(comment.getOrderId())){
+            throw new ServiceException("订单id不能为空");
+        }
+        //判断订单是否存在
+        TOrder order1 = orderService.getById(comment.getOrderId());
+        if(order1 == null){
+            throw new ServiceException("订单不存在");
+        }
+        if(StringUtils.isBlank(comment.getOrderNo())){
+            throw new ServiceException("订单号不能为空");
+        }
+        if(StringUtils.isBlank(comment.getText())){
+            throw new ServiceException("评论内容不能空");
+        }
+        if(StringUtils.isBlank(comment.getJsId())){
+            throw new ServiceException("技师id不能空");
+        }
+        if(StringUtils.isBlank(comment.getName())){
+            throw new ServiceException("技师姓名不能空");
+        }
+        //comment.setOpenId(wxLoginUser.getCOpenid());
+        comment.setOpenId("o-HEJ6RAjBDjFvuZcAdHRX8mIZXw");
+        comment.setCommentTime(new Date());
+        this.save(comment);
+
+        //向用户评论审核表中插入数据
+        CommentUserAudit commentUserAudit = new CommentUserAudit();
+        commentUserAudit.setCommentId(comment.getId());
+        commentUserAudit.setOrderNo(comment.getOrderNo());
+        commentUserAudit.setText(comment.getText());
+        //默认审核状态为待审核
+        commentUserAudit.setAuditStatus(0);
+        commentUserAudit.setCreateTime(new Date());
+        commentUserAudit.setUpdateTime(new Date());
+        commentUserAudit.setIsDelete(0);
+        commentUserAuditService.save(commentUserAudit);
+
+        TOrder order = new TOrder();
+        //修改订单状态(已完成)
+        order.setnStatus(OrderStatusEnum.COMPLETE.getCode());
+        order.setcId(comment.getOrderId());
+        return orderService.updateById(order);
+    }
+
+
+     @Override
+    public List<TCommentUser> selectAll(TCommentUser tCommentUser) {
+         return tCommentUserMapper.selectAll(tCommentUser);
+    }
 }
 

+ 62 - 11
nightFragrance-massage/src/main/java/com/ylx/massage/service/impl/TbFileServiceImpl.java

@@ -19,36 +19,85 @@ import org.springframework.web.multipart.MultipartFile;
 import java.io.IOException;
 
 /**
- * (TbFile)表服务实现类
+ * 文件管理服务实现类
+ * <p>
+ * 提供文件上传、文件存储、文件去重等功能的业务实现。
+ * 通过 MD5 值实现文件去重,避免重复上传相同文件。
+ * 继承自 MyBatis-Plus 的 ServiceImpl 类,提供基础的 CRUD 操作。
+ * </p>
  *
  * @author makejava
- * @since 2024-04-27 17:12:46
+ * @version 1.0
+ * @since 2024-04-27
  */
 @Service("tbFileService")
 public class TbFileServiceImpl extends ServiceImpl<TbFileMapper, TbFile> implements TbFileService {
 
     @Autowired
     private ServerConfig serverConfig;
+
+    /**
+     * 根据 MD5 值查询文件记录
+     * <p>
+     * 通过文件的 MD5 值查询数据库中是否已存在相同的文件记录。
+     * 用于文件去重判断,避免重复上传相同内容的文件。
+     * </p>
+     *
+     * @param md5 文件的 MD5 值,用于唯一标识文件内容
+     * @return 如果找到匹配的文件记录则返回该记录,否则返回 null
+     */
     @Override
     public TbFile getByMd5(String md5) {
         LambdaQueryWrapper<TbFile> queryWrapper = new LambdaQueryWrapper<>();
-        queryWrapper.eq(TbFile::getMd5,md5);
+        queryWrapper.eq(TbFile::getMd5, md5);
         return this.getOne(queryWrapper);
     }
 
+    /**
+     * 计算文件的 MD5 值
+     * <p>
+     * 使用 Hutool 工具类计算上传文件的 MD5 哈希值。
+     * MD5 值用于文件内容唯一性校验和去重判断。
+     * </p>
+     *
+     * @param file 上传的文件对象
+     * @return 文件内容的 MD5 哈希值(32位小写十六进制字符串)
+     * @throws IOException 当读取文件内容发生错误时抛出
+     */
     public String calculateMD5(MultipartFile file) throws IOException {
         byte[] bytes = file.getBytes();
         return DigestUtil.md5Hex(bytes);
     }
+
+    /**
+     * 上传文件并返回文件访问信息
+     * <p>
+     * 实现文件上传功能,支持文件去重机制:
+     * 1. 计算上传文件的 MD5 值
+     * 2. 检查数据库中是否已存在相同 MD5 的文件
+     * 3. 如果存在,直接返回已有文件的访问路径(实现秒传)
+     * 4. 如果不存在,将文件上传到服务器并保存文件记录到数据库
+     * </p>
+     *
+     * @param file 上传的文件对象,包含文件内容和元数据
+     * @return AjaxResult 包含文件访问信息的对象:
+     *         - url: 文件的完整访问 URL(包含域名)
+     *         - fileName: 服务器存储的文件路径
+     *         - newFileName: 文件名(不含路径)
+     *         - originalFilename: 原始上传文件名
+     *         如果上传失败,返回错误信息
+     */
     @Override
     public AjaxResult uploadFile(MultipartFile file) {
         AjaxResult ajax = AjaxResult.success();
-        try
-        {
+        try {
+            // 计算文件 MD5 值
             String md5 = calculateMD5(file);
 
+            // 检查是否已存在相同文件(通过 MD5 去重)
             TbFile dbFile = this.getByMd5(md5);
-            if(null != dbFile){
+            if (null != dbFile) {
+                // 文件已存在,直接返回已有文件的访问信息(秒传)
                 ajax.put("url", serverConfig.getUrl() + dbFile.getFileUrl());
                 ajax.put("fileName", dbFile.getFileUrl());
                 ajax.put("newFileName", FileUtils.getName(dbFile.getFileUrl()));
@@ -56,25 +105,27 @@ public class TbFileServiceImpl extends ServiceImpl<TbFileMapper, TbFile> impleme
                 return ajax;
             }
 
-            // 上传文件路径
+            // 文件不存在,上传新文件
+            // 获取上传文件路径配置
             String filePath = RuoYiConfig.getUploadPath();
-            // 上传并返回新文件名称
+            // 上传文件到服务器并返回新文件名称
             String fileName = FileUploadUtils.upload(filePath, file);
+            // 构建文件访问的完整 URL
             String url = serverConfig.getUrl() + fileName;
             ajax.put("url", url);
             ajax.put("fileName", fileName);
             ajax.put("newFileName", FileUtils.getName(fileName));
             ajax.put("originalFilename", file.getOriginalFilename());
 
+            // 保存文件记录到数据库
             TbFile tbFile = new TbFile();
             tbFile.setMd5(md5);
             tbFile.setFileName(file.getOriginalFilename());
             tbFile.setFileUrl(fileName);
             this.save(tbFile);
             return ajax;
-        }
-        catch (Exception e)
-        {
+        } catch (Exception e) {
+            // 上传失败,返回错误信息
             return AjaxResult.error(e.getMessage());
         }
     }

+ 298 - 0
nightFragrance-massage/src/main/java/com/ylx/massage/utils/ExcelUtils.java

@@ -0,0 +1,298 @@
+package com.ylx.massage.utils;
+
+import cn.hutool.core.util.StrUtil;
+import com.ylx.common.exception.ServiceException;
+import com.ylx.massage.domain.SensitiveWord;
+import com.ylx.massage.enums.SensitiveWordCategoryEnum;
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.text.DecimalFormat;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Excel工具类
+ * <p>
+ * 提供Excel文件的读取和解析功能,支持敏感词数据的导入。
+ * 支持.xls和.xlsx两种格式的Excel文件。
+ * </p>
+ *
+ * @author ylx
+ * @version 1.0
+ * @since 2024
+ */
+public class ExcelUtils {
+
+    private static final Logger log = LoggerFactory.getLogger(ExcelUtils.class);
+
+    /**
+     * Excel列索引定义
+     */
+    private static final int COL_WORD = 0;        // 敏感词
+    private static final int COL_CATEGORY = 1;    // 分类
+    private static final int COL_LEVEL = 2;       // 等级
+    private static final int COL_STATUS = 3;      // 状态
+    private static final int COL_REMARK = 4;      // 备注
+
+    /**
+     * 解析敏感词Excel文件
+     * <p>
+     * 从Excel文件中读取敏感词数据并转换为SensitiveWord对象列表。
+     * Excel文件格式要求:
+     * - 第一行:表头(会被跳过)
+     * - 列顺序:敏感词 | 分类 | 等级 | 状态 | 备注
+     * - 第二行起:数据行
+     * </p>
+     *
+     * @param file 上传的Excel文件
+     * @return List<SensitiveWord> 敏感词对象列表
+     * @throws ServiceException 当文件格式错误或读取失败时抛出
+     */
+    public static List<SensitiveWord> parseSensitiveWordExcel(MultipartFile file) {
+        if (file == null || file.isEmpty()) {
+            throw new ServiceException("文件不能为空");
+        }
+
+        String fileName = file.getOriginalFilename();
+        if (fileName == null) {
+            throw new ServiceException("文件名不能为空");
+        }
+
+        // 验证文件格式
+        if (!fileName.endsWith(".xls") && !fileName.endsWith(".xlsx")) {
+            throw new ServiceException("文件格式错误,仅支持.xls或.xlsx格式的Excel文件");
+        }
+
+        List<SensitiveWord> wordList = new ArrayList<>();
+        Workbook workbook = null;
+        InputStream inputStream = null;
+
+        try {
+            inputStream = file.getInputStream();
+
+            // 根据文件后缀创建不同类型的Workbook
+            if (fileName.endsWith(".xlsx")) {
+                workbook = new XSSFWorkbook(inputStream);
+            } else {
+                workbook = new HSSFWorkbook(inputStream);
+            }
+
+            // 获取第一个工作表
+            Sheet sheet = workbook.getSheetAt(0);
+            if (sheet == null) {
+                throw new ServiceException("Excel文件中没有工作表");
+            }
+
+            log.info("开始解析Excel文件,总行数:{}", sheet.getLastRowNum());
+
+            // 遍历所有行(从第二行开始,跳过表头)
+            for (int i = 1; i <= sheet.getLastRowNum(); i++) {
+                Row row = sheet.getRow(i);
+
+                // 跳过空行
+                if (row == null) {
+                    continue;
+                }
+
+                try {
+                    // 解析当前行数据
+                    SensitiveWord word = parseRow(row);
+                    if (word != null) {
+                        wordList.add(word);
+                    }
+                } catch (Exception e) {
+                    log.warn("解析第 {} 行数据失败,跳过该行。错误信息:{}", i + 1, e.getMessage());
+                }
+            }
+
+            log.info("Excel文件解析完成,共解析 {} 条有效数据", wordList.size());
+            return wordList;
+
+        } catch (IOException e) {
+            log.error("读取Excel文件失败", e);
+            throw new ServiceException("读取Excel文件失败:" + e.getMessage());
+        } finally {
+            // 关闭资源
+            if (workbook != null) {
+                try {
+                    workbook.close();
+                } catch (IOException e) {
+                    log.error("关闭Workbook失败", e);
+                }
+            }
+            if (inputStream != null) {
+                try {
+                    inputStream.close();
+                } catch (IOException e) {
+                    log.error("关闭InputStream失败", e);
+                }
+            }
+        }
+    }
+
+    /**
+     * 解析Excel行数据
+     * <p>
+     * 将Excel的一行数据转换为SensitiveWord对象。
+     * </p>
+     *
+     * @param row Excel行对象
+     * @return SensitiveWord 敏感词对象,如果该行数据无效则返回null
+     */
+    private static SensitiveWord parseRow(Row row) {
+        SensitiveWord word = new SensitiveWord();
+
+        try {
+            // 1. 读取敏感词(必填)
+            String wordText = getCellValueAsString(row.getCell(COL_WORD));
+            if (StrUtil.isBlank(wordText)) {
+                log.debug("第 {} 行:敏感词为空,跳过该行", row.getRowNum() + 1);
+                return null;
+            }
+            word.setWord(wordText.trim());
+
+            // 2. 读取分类(必填)
+            String category = getCellValueAsString(row.getCell(COL_CATEGORY));
+            if (StrUtil.isBlank(category)) {
+                log.debug("第 {} 行:分类为空,使用默认分类", row.getRowNum() + 1);
+                word.setCategory(SensitiveWordCategoryEnum.OTHER.getDesc());
+            } else {
+                // 验证分类是否有效
+                if (!isValidCategory(category.trim())) {
+                    log.warn("第 {} 行:分类 '{}' 无效,使用默认分类", row.getRowNum() + 1, category);
+                    word.setCategory(SensitiveWordCategoryEnum.OTHER.getDesc());
+                } else {
+                    word.setCategory(category.trim());
+                }
+            }
+
+            // 3. 读取等级(可选,默认为1)
+            String levelStr = getCellValueAsString(row.getCell(COL_LEVEL));
+            if (StrUtil.isNotBlank(levelStr)) {
+                try {
+                    int level = Integer.parseInt(levelStr.trim());
+                    if (level < 1 || level > 3) {
+                        log.warn("第 {} 行:等级 {} 无效,使用默认值1", row.getRowNum() + 1, level);
+                        word.setLevel(1);
+                    } else {
+                        word.setLevel(level);
+                    }
+                } catch (NumberFormatException e) {
+                    log.warn("第 {} 行:等级格式错误 '{}', 使用默认值1", row.getRowNum() + 1, levelStr);
+                    word.setLevel(1);
+                }
+            } else {
+                word.setLevel(1);
+            }
+
+            // 4. 读取状态(可选,默认为1-启用)
+            String statusStr = getCellValueAsString(row.getCell(COL_STATUS));
+            if (StrUtil.isNotBlank(statusStr)) {
+                try {
+                    int status = Integer.parseInt(statusStr.trim());
+                    if (status != 0 && status != 1) {
+                        log.warn("第 {} 行:状态 {} 无效,使用默认值1", row.getRowNum() + 1, status);
+                        word.setStatus(1);
+                    } else {
+                        word.setStatus(status);
+                    }
+                } catch (NumberFormatException e) {
+                    log.warn("第 {} 行:状态格式错误 '{}', 使用默认值1", row.getRowNum() + 1, statusStr);
+                    word.setStatus(1);
+                }
+            } else {
+                word.setStatus(1);
+            }
+
+            // 5. 读取备注(可选)
+            String remark = getCellValueAsString(row.getCell(COL_REMARK));
+            if (StrUtil.isNotBlank(remark)) {
+                word.setRemark(remark.trim());
+            }
+            return word;
+        } catch (Exception e) {
+            log.error("解析第 {} 行数据时发生错误", row.getRowNum() + 1, e);
+            return null;
+        }
+    }
+
+    /**
+     * 获取单元格的字符串值
+     * <p>
+     * 处理不同类型的单元格,返回字符串表示。
+     * </p>
+     *
+     * @param cell 单元格对象
+     * @return String 单元格的字符串值,如果单元格为空则返回空字符串
+     */
+    private static String getCellValueAsString(Cell cell) {
+        if (cell == null) {
+            return "";
+        }
+
+        switch (cell.getCellType()) {
+            case STRING:
+                return cell.getStringCellValue().trim();
+
+            case NUMERIC:
+                if (DateUtil.isCellDateFormatted(cell)) {
+                    return cell.getDateCellValue().toString();
+                } else {
+                    // 数字类型,转换为字符串(去除小数点)
+                    DecimalFormat df = new DecimalFormat("0");
+                    return df.format(cell.getNumericCellValue());
+                }
+
+            case BOOLEAN:
+                return String.valueOf(cell.getBooleanCellValue());
+
+            case FORMULA:
+                try {
+                    return cell.getStringCellValue();
+                } catch (Exception e) {
+                    try {
+                        DecimalFormat df = new DecimalFormat("0");
+                        return df.format(cell.getNumericCellValue());
+                    } catch (Exception ex) {
+                        return "";
+                    }
+                }
+
+            case BLANK:
+                return "";
+
+            default:
+                return "";
+        }
+    }
+
+    /**
+     * 验证分类是否有效
+     * <p>
+     * 检查分类是否在预定义的分类枚举中。
+     * </p>
+     *
+     * @param category 分类名称
+     * @return 如果分类有效返回true,否则返回false
+     */
+    private static boolean isValidCategory(String category) {
+        if (StrUtil.isBlank(category)) {
+            return false;
+        }
+
+        for (SensitiveWordCategoryEnum categoryEnum : SensitiveWordCategoryEnum.values()) {
+            if (categoryEnum.getDesc().equals(category)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+}

+ 1 - 0
nightFragrance-massage/src/main/java/com/ylx/massage/utils/WeChatUtil.java

@@ -94,6 +94,7 @@ public class WeChatUtil {
                 .append("&secret=").append(wxPayProperties.getMpAppSecret())
                 .append("&code=").append(code)
                 .append("&grant_type=authorization_code");
+        log.info("URL的值:{}", url.toString());
         String rs = HttpUtil.get(url.toString());
         Map<?, ?> map = JSONObject.parseObject(rs, Map.class);
         if (null == map.get(ERROR_CODE)) {

+ 33 - 0
nightFragrance-massage/src/main/resources/mapper/massage/SensitiveWordMapper.xml

@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ylx.massage.mapper.SensitiveWordMapper">
+
+    <resultMap type="com.ylx.massage.domain.SensitiveWord" id="SensitiveWordMap">
+        <result property="id" column="id" jdbcType="BIGINT"/>
+        <result property="word" column="word" jdbcType="VARCHAR"/>
+        <result property="category" column="category" jdbcType="VARCHAR"/>
+        <result property="level" column="level" jdbcType="INTEGER"/>
+        <result property="status" column="status" jdbcType="INTEGER"/>
+        <result property="remark" column="remark" jdbcType="VARCHAR"/>
+        <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
+        <result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/>
+        <result property="isDelete" column="is_delete" jdbcType="INTEGER"/>
+    </resultMap>
+
+    <!-- 批量插入敏感词 -->
+    <insert id="insertBatch" keyProperty="id" useGeneratedKeys="true">
+        INSERT INTO t_sensitive_word (word, category, level, status, remark, create_time, update_time, is_delete)
+        VALUES
+        <foreach collection="entities" item="entity" separator=",">
+            (#{entity.word}, #{entity.category}, #{entity.level}, #{entity.status}, #{entity.remark}, #{entity.createTime}, #{entity.updateTime}, #{entity.isDelete})
+        </foreach>
+    </insert>
+
+    <!-- 根据敏感词查询 -->
+    <select id="selectByWord" resultMap="SensitiveWordMap">
+        SELECT * FROM t_sensitive_word
+        WHERE word = #{word} AND is_delete = 0
+        LIMIT 1
+    </select>
+
+</mapper>

+ 32 - 0
nightFragrance-massage/src/main/resources/mapper/massage/TCommentUserMapper.xml

@@ -36,5 +36,37 @@
         is_delete = values(is_delete)
     </insert>
 
+    <!-- 分页查询用户评论 -->
+    <select id="selectAll" resultType="com.ylx.massage.domain.TCommentUser">
+        SELECT
+            tcu.id as id,
+            tcu.nick_name as nickName,
+            tcu.text as text,
+            tcu.star as star,
+            tcu.comment_time as commentTime,
+            tcu.js_id as jsId,
+            tcu.name as name,
+            tcu.sensitive_word as sensitiveWord,
+            tcua.audit_status as auditStatus
+        FROM
+            t_comment_user tcu
+                LEFT JOIN t_comment_user_audit tcua ON tcu.id = tcua.comment_id
+        WHERE
+            tcu.is_delete = 0
+          AND tcua.is_delete = 0
+          <!-- 技师姓名查询 -->
+        <if test="tCommentUser.name != null and tCommentUser.name != ''">
+            AND tcu.name = #{tCommentUser.name}
+        </if>
+        <!--敏感词查询-->
+        <if test="tCommentUser.sensitiveWord != null">
+            AND tcu.sensitive_word = #{tCommentUser.sensitiveWord}
+        </if>
+        <!-- 审核状态查询 -->
+        <if test="tCommentUser.auditStatus != null">
+            AND tcua.audit_status = #{tCommentUser.auditStatus}
+        </if>
+    </select>
+
 </mapper>
 

+ 0 - 1
pom.xml

@@ -162,7 +162,6 @@
                 <artifactId>nightFragrance-common</artifactId>
                 <version>${ruoyi.version}</version>
             </dependency>
-
         </dependencies>
     </dependencyManagement>