Browse Source

新增二维码功能
优化聊天记录消息

fangzhen 6 tháng trước cách đây
mục cha
commit
2d9de7e2c4

+ 45 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java

@@ -1,8 +1,11 @@
 package com.ruoyi.web.controller.common;
 
+import com.alibaba.fastjson.JSONObject;
 import com.ruoyi.common.config.RuoYiConfig;
 import com.ruoyi.common.constant.Constants;
 import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.utils.QRCodeUtils;
+import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.file.FileUploadUtils;
 import com.ruoyi.common.utils.file.FileUtils;
@@ -19,6 +22,9 @@ import org.springframework.web.multipart.MultipartFile;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+import java.io.File;
+import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -191,4 +197,43 @@ public class CommonController {
             log.error("下载文件失败", e);
         }
     }
+
+    /**
+     * 生成二维码
+     *
+     * @param
+     * @return
+     */
+    @GetMapping("/loginUserQRCode")
+    public AjaxResult generateAndUploadQRCode() {
+        String fileName = "";
+        try {
+            Long userId = SecurityUtils.getLoginUser().getUser().getUserId();
+            JSONObject userIdObj = new JSONObject();
+            userIdObj.put("userId", userId);
+            // 1. 生成临时二维码图片
+            fileName = "qrcode_" + userId + ".png";
+            Path tempFile = Paths.get(System.getProperty("java.io.tmpdir"), fileName);
+            QRCodeUtils.generateQRCode(userIdObj.toJSONString(), tempFile, 300, 300);
+
+            // 2. 转为 MultipartFile 格式,便于调用 RuoYi 的上传接口
+            File file = tempFile.toFile();
+            MultipartFile multipartFile = FileUtils.convertFileToMultipartFile(file);
+
+            // 3. 使用 RuoYi 的文件上传工具进行上传
+            String uploadPath = FileUploadUtils.upload(RuoYiConfig.getUploadPath(), multipartFile);
+
+            // 4. 拼接访问 URL 并返回给前端
+            String fileUrl = serverConfig.getUrl() + uploadPath;
+            return AjaxResult.success("二维码生成成功", fileUrl);
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            return AjaxResult.error("二维码生成或上传失败");
+        } finally {
+            //清理临时文件
+            FileUtils.cleanTempDir(fileName);
+        }
+    }
+
 }

+ 19 - 0
ruoyi-common/pom.xml

@@ -140,6 +140,25 @@
             <artifactId>aliyun-sdk-oss</artifactId>
             <version>3.11.2</version>
         </dependency>
+
+        <!--二维码-->
+        <dependency>
+            <groupId>com.google.zxing</groupId>
+            <artifactId>core</artifactId>
+            <version>3.4.1</version>
+        </dependency>
+        <dependency>
+            <groupId>com.google.zxing</groupId>
+            <artifactId>javase</artifactId>
+            <version>3.4.1</version>
+        </dependency>
+
+        <dependency>
+            <groupId>commons-fileupload</groupId>
+            <artifactId>commons-fileupload</artifactId>
+            <version>1.4</version>
+        </dependency>
+
     </dependencies>
 
 </project>

+ 30 - 0
ruoyi-common/src/main/java/com/ruoyi/common/utils/QRCodeUtils.java

@@ -0,0 +1,30 @@
+package com.ruoyi.common.utils;
+
+import com.google.zxing.BarcodeFormat;
+import com.google.zxing.EncodeHintType;
+import com.google.zxing.client.j2se.MatrixToImageWriter;
+import com.google.zxing.common.BitMatrix;
+import com.google.zxing.qrcode.QRCodeWriter;
+
+import java.nio.file.Path;
+import java.util.HashMap;
+import java.util.Map;
+
+public class QRCodeUtils {
+    /**
+     * 生成二维码图片
+     * @param jsonData 二维码数据
+     * @param filePath 临时目录
+     * @param width 宽度
+     * @param height 长度
+     * @throws Exception 异常
+     */
+    public static void generateQRCode(String jsonData, Path filePath, int width, int height) throws Exception {
+        QRCodeWriter qrCodeWriter = new QRCodeWriter();
+        Map<EncodeHintType, Object> hints = new HashMap<>();
+        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
+
+        BitMatrix bitMatrix = qrCodeWriter.encode(jsonData, BarcodeFormat.QR_CODE, width, height, hints);
+        MatrixToImageWriter.writeToPath(bitMatrix, "PNG", filePath);
+    }
+}

+ 46 - 0
ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUtils.java

@@ -4,11 +4,13 @@ import com.ruoyi.common.config.RuoYiConfig;
 import com.ruoyi.common.utils.DateUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.uuid.IdUtils;
+import org.apache.commons.fileupload.disk.DiskFileItem;
 import org.apache.commons.io.FilenameUtils;
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang3.ArrayUtils;
 import org.apache.tika.Tika;
 import org.springframework.web.multipart.MultipartFile;
+import org.springframework.web.multipart.commons.CommonsMultipartFile;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
@@ -324,4 +326,48 @@ public class FileUtils {
 
         return process.waitFor() == 0;
     }
+
+    /**
+     * File转换MultipartFile
+     *
+     * @param file 文件
+     * @return MultipartFile
+     * @throws Exception 异常
+     */
+    public static MultipartFile convertFileToMultipartFile(File file) throws Exception {
+        DiskFileItem fileItem = new DiskFileItem("file", "image/png", true, file.getName(), (int) file.length(), file.getParentFile());
+
+        try (FileInputStream input = new FileInputStream(file); OutputStream os = fileItem.getOutputStream()) {
+            IOUtils.copy(input, os);
+        }
+
+        return new CommonsMultipartFile(fileItem);
+    }
+
+
+    /**
+     * 清理临时文件
+     * @param fileName 文件名称
+     */
+    public static void cleanTempDir(String fileName) {
+        String tempDirPath = System.getProperty("java.io.tmpdir");
+        File tempDir = new File(tempDirPath);
+
+        if (tempDir.exists() && tempDir.isDirectory()) {
+            File[] files = tempDir.listFiles();
+            if (files != null) {
+                for (File file : files) {
+                    // 检查是否是临时文件,并尝试删除
+                    if (file.isFile() && file.getName().endsWith(".tmp") || file.getName().startsWith(fileName)) {
+                        boolean deleted = file.delete();
+                        if (deleted) {
+                            System.out.println("删除临时文件成功: " + file.getName());
+                        } else {
+                            System.out.println("删除临时文件失败: " + file.getName());
+                        }
+                    }
+                }
+            }
+        }
+    }
 }

+ 1 - 0
ruoyi-generator/pom.xml

@@ -66,6 +66,7 @@
             <artifactId>alibabacloud-dysmsapi20170525</artifactId>
             <version>3.0.0</version>
         </dependency>
+
     </dependencies>
 
 </project>

+ 28 - 4
ruoyi-generator/src/main/java/com/ruoyi/generator/controller/CommunityChatMsgController.java

@@ -4,9 +4,13 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.entity.SysUser;
 import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.common.utils.bean.BeanUtils;
 import com.ruoyi.system.domain.CommunityChatMsg;
+import com.ruoyi.system.domain.vo.CommunityChatMsgVo;
 import com.ruoyi.system.domain.vo.SysUserVo;
+import com.ruoyi.system.mapper.SysUserMapper;
 import com.ruoyi.system.service.ICommunityChatMsgService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
@@ -15,6 +19,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
 import javax.annotation.Resource;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.stream.Collectors;
 
@@ -31,6 +36,9 @@ public class CommunityChatMsgController extends BaseController {
     @Resource
     private ICommunityChatMsgService communityChatMsgService;
 
+    @Resource
+    private SysUserMapper sysUserMapper;
+
     /**
      * 获取当前登录用户聊天记录
      */
@@ -50,10 +58,26 @@ public class CommunityChatMsgController extends BaseController {
                 .filter(item -> !item.isRead())
                 .map(CommunityChatMsg::getId)
                 .collect(Collectors.toList());
-        CommunityChatMsg chatMsg = new CommunityChatMsg();
-        chatMsg.setRead(true);
-        communityChatMsgService.update(chatMsg, new UpdateWrapper<CommunityChatMsg>().in("id", msgId));
-        return AjaxResult.success(chatMsgList);
+        if (!msgId.isEmpty()) {
+            CommunityChatMsg chatMsg = new CommunityChatMsg();
+            chatMsg.setRead(true);
+            communityChatMsgService.update(chatMsg, new UpdateWrapper<CommunityChatMsg>().in("id", msgId));
+        }
+
+        List<CommunityChatMsgVo> chatMsgVos = new ArrayList<>();
+        CommunityChatMsgVo chatMsgVo = null;
+        for (CommunityChatMsg chatMsg : chatMsgList) {
+            chatMsgVo = new CommunityChatMsgVo();
+            BeanUtils.copyProperties(chatMsg, chatMsgVo);
+            SysUser senderUser = sysUserMapper.selectUserById(chatMsgVo.getSenderId());
+            SysUser receiveUser = sysUserMapper.selectUserById(chatMsgVo.getReceiverId());
+            chatMsgVo.setSenderNickName(senderUser.getNickName());
+            chatMsgVo.setSenderAvatar(senderUser.getAvatar());
+            chatMsgVo.setReceiverNickName(receiveUser.getNickName());
+            chatMsgVo.setReceiverAvatar(receiveUser.getAvatar());
+            chatMsgVos.add(chatMsgVo);
+        }
+        return AjaxResult.success(chatMsgVos);
     }
 
     /**

+ 94 - 0
ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/CommunityChatMsgVo.java

@@ -0,0 +1,94 @@
+package com.ruoyi.system.domain.vo;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import lombok.Data;
+import org.hibernate.validator.constraints.Length;
+
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+* 社区聊天信息
+* @TableName community_chat_msg
+*/
+@Data
+@TableName("community_chat_msg")
+public class CommunityChatMsgVo implements Serializable {
+
+    /**
+    * 唯一Id
+    */
+    @NotNull(message="[唯一Id]不能为空")
+    @TableId("id")
+    @JsonSerialize(using = ToStringSerializer.class)
+    private Long id;
+    /**
+    * 内容
+    */
+    @Size(max= -1,message="编码长度不能超过-1")
+    @Length(max= -1,message="编码长度不能超过-1")
+    private String content;
+    /**
+    * 消息发送人id
+    */
+    private Long senderId;
+    /**
+     * 消息发送人昵称
+     */
+    private String senderNickName;
+    /**
+     * 消息发送人头像
+     */
+    private String senderAvatar;
+    /**
+    * 消息接收人id
+    */
+    private Long receiverId;
+    /**
+     * 消息接收人昵称
+     */
+    private String receiverNickName;
+    /**
+     * 消息接收人头像
+     */
+    private String receiverAvatar;
+    /**
+     * 地址
+     */
+    private String address;
+    /**
+     * 纬度
+     */
+    private Double latitude;
+    /**
+     * 经度
+     */
+    private Double longitude;
+    /**
+     * 文件地址(录音视频)
+     */
+    private String fileUrl;
+    /**
+     * 录音时长
+     */
+    private int time;
+    /**
+     * 消息类型
+     */
+    private int messageType;
+    /**
+     * 是否已读
+     */
+    private boolean isRead;
+    /**
+    * 创建时间
+    */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date createTime;
+}