Parcourir la source

二维码底部添加文字

bihuisong il y a 7 mois
Parent
commit
f6c276dd3e

+ 2 - 21
zhjq-business/src/main/java/com/zhjq/controller/QrCodeController.java

@@ -5,8 +5,6 @@ import cn.hutool.core.img.ImgUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.extra.qrcode.QrCodeUtil;
 import cn.hutool.extra.qrcode.QrConfig;
-import com.google.zxing.client.j2se.MatrixToImageWriter;
-import com.google.zxing.common.BitMatrix;
 import com.zhjq.common.config.RuoYiConfig;
 import com.zhjq.common.core.domain.AjaxResult;
 import com.zhjq.common.exception.ServiceException;
@@ -18,7 +16,6 @@ import com.zhjq.domain.QrCodeGenerateDTO;
 import com.zhjq.domain.ZhjqVoice;
 import com.zhjq.service.IZhjqVoiceService;
 import com.zhjq.utils.InMemoryMultipartFile;
-import com.zhjq.utils.QRCodeUtils;
 import lombok.extern.slf4j.Slf4j;
 import net.sourceforge.pinyin4j.PinyinHelper;
 import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
@@ -30,10 +27,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 import org.springframework.web.multipart.MultipartFile;
 
-import javax.imageio.ImageIO;
-import java.awt.image.BufferedImage;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
+import static com.zhjq.utils.QRCodeUtils.createCodeWithText;
 
 @Slf4j
 @RestController
@@ -62,7 +56,7 @@ public class QrCodeController {
         byte[] qrCodeBytes = null;
         String fileName = convertToPinyin(dto.getVoiceName() + ".png");
         try {
-            qrCodeBytes = generateQRCodeBytes(dto.getVoiceUrl());
+            qrCodeBytes = createCodeWithText(dto.getVoiceUrl(), dto.getVoiceName());
             // 创建 MultipartFile 对象
             MultipartFile file = new InMemoryMultipartFile("file", fileName, "image/png", qrCodeBytes);
             String avatar = FileUploadUtils.upload(RuoYiConfig.getQrcodePath(), file, MimeTypeUtils.IMAGE_EXTENSION);
@@ -125,17 +119,4 @@ public class QrCodeController {
         return pinyin.toString().replace(" ", "");
     }
 
-
-    public static BufferedImage generateQRCodeImage(String text) throws IOException {
-        BitMatrix bitMatrix = QRCodeUtils.createCode(text);
-        return MatrixToImageWriter.toBufferedImage(bitMatrix);
-    }
-
-    public static byte[] generateQRCodeBytes(String text) throws IOException {
-        BufferedImage image = generateQRCodeImage(text);
-        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
-        ImageIO.write(image, "png", outputStream);
-        return outputStream.toByteArray();
-    }
-
 }

+ 77 - 0
zhjq-business/src/main/java/com/zhjq/utils/QRCodeUtils.java

@@ -5,14 +5,20 @@ import com.google.zxing.EncodeHintType;
 import com.google.zxing.MultiFormatWriter;
 import com.google.zxing.WriterException;
 import com.google.zxing.common.BitMatrix;
+import com.google.zxing.qrcode.QRCodeWriter;
 import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
 
+import javax.imageio.ImageIO;
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.util.HashMap;
 import java.util.Map;
 
 public class QRCodeUtils {
 
+
     /**
      * 生成二维码
      *
@@ -47,6 +53,77 @@ public class QRCodeUtils {
     }
 
     /**
+     * 生成带有底部文字的二维码
+     *
+     * @param content 二维码的内容
+     * @param text    底部文字
+     * @throws IOException
+     */
+    public static byte[] createCodeWithText(String content, String text) throws IOException {
+        // 二维码的宽高
+        int width = 300;
+        int height = 300;
+
+        // 其他参数,如字符集编码
+        Map<EncodeHintType, Object> hints = new HashMap<>();
+        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
+        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
+        hints.put(EncodeHintType.MARGIN, 0);
+
+        BitMatrix bitMatrix = null;
+        try {
+            // 生成二维码矩阵
+            QRCodeWriter writer = new QRCodeWriter();
+            bitMatrix = writer.encode(content, BarcodeFormat.QR_CODE, width, height, hints);
+        } catch (WriterException e) {
+            e.printStackTrace();
+        }
+
+        // 创建图像并绘制二维码
+        int imgWidth = width;
+        int imgHeight = height + 30; // 增加额外空间用于文本
+        BufferedImage image = new BufferedImage(imgWidth, imgHeight, BufferedImage.TYPE_INT_RGB);
+        Graphics2D graphics = image.createGraphics();
+
+        // 设置背景色
+        graphics.setColor(Color.WHITE);
+        graphics.fillRect(0, 0, imgWidth, imgHeight);
+
+        // 绘制二维码
+        graphics.setColor(Color.BLACK);
+        for (int x = 0; x < width; x++) {
+            for (int y = 0; y < height; y++) {
+                if (bitMatrix.get(x, y)) {
+                    graphics.fillRect(x, y, 1, 1);
+                }
+            }
+        }
+
+        // 添加底部文字,使用合适的字体
+        graphics.setColor(Color.BLACK);
+        // 使用支持中文的字体
+        Font font = new Font("Microsoft YaHei", Font.BOLD, 16);
+        graphics.setFont(font);
+        FontMetrics metrics = graphics.getFontMetrics(font);
+        int textWidth = metrics.stringWidth(text);
+        // 在底部居中绘制文本
+        graphics.drawString(text, (imgWidth - textWidth) / 2, height + 20);
+
+        graphics.dispose();
+
+        // 保存图像
+        try {
+            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+//            ImageIO.write(image, "png", new File(filePath));
+            ImageIO.write(image, "png", outputStream);
+            return outputStream.toByteArray();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    /**
      * 删除生成的二维码周围的白边,根据审美决定是否删除
      *
      * @param matrix BitMatrix对象

+ 2 - 2
zhjq-ui/.env.development

@@ -1,10 +1,10 @@
 # 页面标题
-VUE_APP_TITLE = 北旅智慧景区
+VUE_APP_TITLE = 北国风光
 
 # 开发环境配置
 ENV = 'development'
 
-# 北旅智慧景区/开发环境
+# 北国风光/开发环境
 VUE_APP_BASE_API = '/dev-api'
 
 # 路由懒加载

+ 2 - 2
zhjq-ui/.env.production

@@ -1,8 +1,8 @@
 # 页面标题
-VUE_APP_TITLE = 北旅智慧景区
+VUE_APP_TITLE = 北国风光
 
 # 生产环境配置
 ENV = 'production'
 
-# 北旅智慧景区/生产环境
+# 北国风光/生产环境
 VUE_APP_BASE_API = '/prod-api'

+ 2 - 2
zhjq-ui/.env.staging

@@ -1,5 +1,5 @@
 # 页面标题
-VUE_APP_TITLE = 北旅智慧景区
+VUE_APP_TITLE = 北国风光
 
 BABEL_ENV = production
 
@@ -8,5 +8,5 @@ NODE_ENV = production
 # 测试环境配置
 ENV = 'staging'
 
-# 北旅智慧景区/测试环境
+# 北国风光/测试环境
 VUE_APP_BASE_API = '/stage-api'

+ 1 - 1
zhjq-ui/package.json

@@ -1,7 +1,7 @@
 {
   "name": "ruoyi",
   "version": "3.8.8",
-  "description": "北旅智慧景区",
+  "description": "北国风光",
   "author": "若依",
   "license": "MIT",
   "scripts": {

+ 1 - 1
zhjq-ui/src/views/login.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="login">
     <el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form">
-      <h3 class="title">北旅智慧景区内容管理系统</h3>
+      <h3 class="title">北国风光内容管理系统</h3>
       <el-form-item prop="username">
         <el-input
           v-model="loginForm.username"

+ 1 - 1
zhjq-ui/src/views/system/voice/index.vue

@@ -202,7 +202,7 @@ export default {
       rules: {
         voiceName: [
           {required: true, message: "景点名称不能为空", trigger: "blur"},
-          {max: 50, message: '长度不能超过50个字符', trigger: 'blur'}
+          {max: 16, message: '长度不能超过16个字符', trigger: 'blur'}
         ],
         voiceUrl: [
           {required: true, message: "语音文件不能为空", trigger: "blur"}

+ 1 - 1
zhjq-ui/vue.config.js

@@ -7,7 +7,7 @@ function resolve(dir) {
 
 const CompressionPlugin = require('compression-webpack-plugin')
 
-const name = process.env.VUE_APP_TITLE || '北旅智慧景区内容管理系统' // 网页标题
+const name = process.env.VUE_APP_TITLE || '北国风光内容管理系统' // 网页标题
 
 const port = process.env.port || process.env.npm_config_port || 80 // 端口