liusheng
2 天以前 27df1079c1d230fab29f565f5209f2a02e0def8a
ruoyi-admin/src/main/java/com/ruoyi/web/controller/smartor/QRCodeController.java
@@ -1,10 +1,12 @@
package com.ruoyi.web.controller.smartor;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.mchange.v2.uid.UidUtils;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.framework.config.ServerConfig;
@@ -21,10 +23,17 @@
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.net.URI;
import java.util.*;
@Slf4j
@@ -41,6 +50,11 @@
    @Value("${ruoyi.profile}")
    private String profile;
    /**
     * 公司logo在classpath中的路径,打包进jar后任何环境都能读取到
     */
    private static final String LOGO_CLASSPATH = "/images/hrslogo.png";
    @Autowired
    private ServerConfig serverConfig;
@@ -122,24 +136,85 @@
    @PostMapping(value = "/getQRcode")
    public AjaxResult getQRcode(@RequestParam("url") String url) {
        log.info("获取问卷二维码的入参:{}", url);
        String uuid = UUID.randomUUID().toString().replace("-", "");
        String filePath = profile + "\\qrpath" + "\\" + uuid + ".png"; // 保存二维码图像的文件路径
        // 尝试从url中提取p参数的值作为图片名称,值为空则用UUID
        String fileName = UUID.randomUUID().toString().replace("-", "");
        try {
            URI uri = new URI(url);
            String query = uri.getQuery();
            if (query != null) {
                for (String param : query.split("&")) {
                    String[] pair = param.split("=", 2);
                    if ("p".equals(pair[0]) && pair.length > 1 && !pair[1].isEmpty()) {
                        fileName = pair[1] + "-" + System.currentTimeMillis();
                        break;
                    }
                }
            }
        } catch (Exception e) {
            log.warn("解析url中的p参数失败,使用UUID作为文件名");
        }
        String filePath = profile + "\\qrpath" + "\\" + fileName + ".png"; // 保存二维码图像的文件路径
        //判断文件夹是否存在
        File file = new File(profile + "\\qrpath");
        if (!file.exists()) {
            file.mkdirs();
        }
        generateQRCode(url, filePath);
        return AjaxResult.success(serverConfig.getUrl() + "/profile/qrpath/" + uuid + ".png");
        return AjaxResult.success(serverConfig.getUrl() + "/profile/qrpath/" + fileName + ".png");
    }
    private void generateQRCode(String url, String filePath) {
        QRCodeWriter qrCodeWriter = new QRCodeWriter();
        try {
            BitMatrix bitMatrix = qrCodeWriter.encode(url, BarcodeFormat.QR_CODE, 500, 500);
            // 使用高容错级别(H级,30%容错),确保二维码中间嵌入logo后仍可正常扫描
            Map<EncodeHintType, Object> hints = new HashMap<>();
            hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
            hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
            hints.put(EncodeHintType.MARGIN, 1);
            BitMatrix bitMatrix = qrCodeWriter.encode(url, BarcodeFormat.QR_CODE, 500, 500, hints);
            // 将BitMatrix转为二值BufferedImage(黑白)
            BufferedImage binaryImage = MatrixToImageWriter.toBufferedImage(bitMatrix);
            // 创建RGB彩色图像,把二维码画上去,否则后续绘制logo会丢失颜色
            BufferedImage qrImage = new BufferedImage(500, 500, BufferedImage.TYPE_INT_RGB);
            Graphics2D graphics = qrImage.createGraphics();
            graphics.setColor(Color.WHITE);
            graphics.fillRect(0, 0, 500, 500);
            graphics.drawImage(binaryImage, 0, 0, null);
            // 从classpath读取logo并绘制到二维码中间
            try (InputStream logoStream = this.getClass().getResourceAsStream(LOGO_CLASSPATH)) {
                if (logoStream != null) {
                    BufferedImage logoImage = ImageIO.read(logoStream);
                    // 计算logo尺寸,设为二维码的1/5
                    int logoWidth = qrImage.getWidth() / 5;
                    int logoHeight = qrImage.getHeight() / 5;
                    // 计算logo居中位置
                    int logoX = (qrImage.getWidth() - logoWidth) / 2;
                    int logoY = (qrImage.getHeight() - logoHeight) / 2;
                    // 绘制白色圆角背景,让logo更突出
                    int padding = 6;
                    graphics.setColor(Color.WHITE);
                    graphics.fillRoundRect(logoX - padding, logoY - padding, logoWidth + padding * 2, logoHeight + padding * 2, 10, 10);
                    // 绘制logo
                    graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
                    graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                    graphics.drawImage(logoImage, logoX, logoY, logoWidth, logoHeight, null);
                } else {
                    log.warn("classpath中未找到二维码logo: {}", LOGO_CLASSPATH);
                }
            }
            graphics.dispose();
            // 输出最终图片
            File outputFile = new File(filePath);
            MatrixToImageWriter.writeToPath(bitMatrix, "PNG", outputFile.toPath());
            ImageIO.write(qrImage, "PNG", outputFile);
        } catch (WriterException | IOException e) {
            e.printStackTrace();
        }