Selaa lähdekoodia

动态调整二维码位置

yuhongqi 2 viikkoa sitten
vanhempi
commit
171f290322

+ 81 - 8
fs-service/src/main/java/com/fs/common/QRutils.java

@@ -4,8 +4,12 @@ import cn.hutool.core.codec.Base64;
 import cn.hutool.core.img.ImgUtil;
 import cn.hutool.extra.qrcode.QrCodeUtil;
 import cn.hutool.extra.qrcode.QrConfig;
+import com.fs.common.core.domain.entity.SysDictData;
+import com.fs.common.utils.StringUtils;
+import com.fs.common.utils.spring.SpringUtils;
 import com.fs.system.oss.CloudStorageService;
 import com.fs.system.oss.OSSFactory;
+import com.fs.system.service.ISysDictTypeService;
 
 import javax.imageio.ImageIO;
 import java.awt.*;
@@ -16,8 +20,19 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.net.HttpURLConnection;
 import java.net.URL;
+import java.util.List;
 
 public class QRutils {
+
+    private static final String QR_CODE_EMBED_POSITION = "qr_code_embed_position";
+    /** 字典 dict_sort=1:是否开启二维码字典定位 */
+    private static final long DICT_SORT_QR_POSITION_ENABLED = 1L;
+    /** 字典 dict_sort=2:二维码X坐标 */
+    private static final long DICT_SORT_QR_POSITION_X = 2L;
+    /** 字典 dict_sort=3:二维码Y坐标 */
+    private static final long DICT_SORT_QR_POSITION_Y = 3L;
+    private static final int DEFAULT_QR_CODE_X = 250;
+    private static final int DEFAULT_QR_CODE_Y = 1160;
     public static InputStream downloadAndEncodeImageToInputStream(String imageUrl) throws Exception {
         URL url = new URL(imageUrl);
         HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
@@ -65,14 +80,9 @@ public class QRutils {
         // 绘制主图
         gMain.drawImage(mainImage, 0, 0, null);
 
-        // 在指定位置绘制二维码图片
-//        g.drawImage(qrCodeImage, qrCodeX, qrCodeY, null);
-        // 计算二维码图片的放置位置(距主图左边宽10%,距离上边宽10%)
-//        int qrCodeX = (int)Math.round(mainImage.getWidth() * 0.1); // 左边距1%
-//        int qrCodeY = (int)Math.round(mainImage.getHeight() * 0.1); // 上边距1%
-        int qrCodeX = (int)Math.round(250.0); // 左边距1%
-        int qrCodeY = (int)Math.round(1160.0); // 上边距1%
-        // 在指定位置绘制二维码图片
+        int[] qrPosition = resolveQrCodePosition();
+        int qrCodeX = qrPosition[0];
+        int qrCodeY = qrPosition[1];
         gMain.drawImage(resizedQrCodeImage, qrCodeX, qrCodeY, null);
 
         // 释放图形上下文使用的系统资源
@@ -91,6 +101,69 @@ public class QRutils {
 
     }
 
+    /**
+     * 解析二维码在主图上的坐标:默认 250,1160;字典开启时使用 dict_sort=2/3 的 x/y。
+     */
+    private static int[] resolveQrCodePosition() {
+        if (!isQrCodePositionEnabled()) {
+            return new int[]{DEFAULT_QR_CODE_X, DEFAULT_QR_CODE_Y};
+        }
+        return new int[]{
+                parseQrCodeCoordinate(getQrCodeEmbedDictValue(DICT_SORT_QR_POSITION_X), DEFAULT_QR_CODE_X),
+                parseQrCodeCoordinate(getQrCodeEmbedDictValue(DICT_SORT_QR_POSITION_Y), DEFAULT_QR_CODE_Y)
+        };
+    }
+
+    private static boolean isQrCodePositionEnabled() {
+        List<SysDictData> dictList = getQrCodeEmbedDictList();
+        if (dictList == null || dictList.isEmpty()) {
+            return false;
+        }
+        return dictList.stream()
+                .filter(item -> "0".equals(item.getStatus()))
+                .filter(item -> item.getDictSort() != null && DICT_SORT_QR_POSITION_ENABLED == item.getDictSort())
+                .anyMatch(item -> "1".equals(StringUtils.trimToEmpty(item.getDictValue())));
+    }
+
+    private static String getQrCodeEmbedDictValue(long dictSort) {
+        List<SysDictData> dictList = getQrCodeEmbedDictList();
+        if (dictList == null || dictList.isEmpty()) {
+            return null;
+        }
+        for (SysDictData item : dictList) {
+            if (!"0".equals(item.getStatus())) {
+                continue;
+            }
+            if (item.getDictSort() != null && dictSort == item.getDictSort()) {
+                return StringUtils.trimToEmpty(item.getDictValue());
+            }
+        }
+        return null;
+    }
+
+    private static List<SysDictData> getQrCodeEmbedDictList() {
+        try {
+            ISysDictTypeService sysDictTypeService = SpringUtils.getBean(ISysDictTypeService.class);
+            if (sysDictTypeService == null) {
+                return null;
+            }
+            return sysDictTypeService.selectDictDataByType(QR_CODE_EMBED_POSITION);
+        } catch (Exception ignored) {
+            return null;
+        }
+    }
+
+    private static int parseQrCodeCoordinate(String value, int defaultValue) {
+        if (StringUtils.isBlank(value)) {
+            return defaultValue;
+        }
+        try {
+            return (int) Math.round(Double.parseDouble(value.trim()));
+        } catch (NumberFormatException ignored) {
+            return defaultValue;
+        }
+    }
+
 
     /**
      * 生成二维码图片

+ 18 - 0
fs-service/src/main/resources/db/changelog/dictData/dict_data_update.sql

@@ -113,3 +113,21 @@ INSERT INTO `sys_dict_data`
 VALUES
     (33, '内容留言积分', '33', 'sys_integral_log_type', NULL, 'default', 'N', '0', 'admin', NOW(), '', NULL, NULL);
 --rollback DELETE FROM sys_dict_data WHERE dict_type = 'sys_integral_log_type' AND dict_value = '33';
+
+--changeset yhq:20260708-qr-code-embed-position-dict
+--preconditions onFail:MARK_RAN
+--precondition-sql-check expectedResult:0 SELECT COUNT(*) FROM sys_dict_type WHERE dict_type = 'qr_code_embed_position'
+--precondition-sql-check expectedResult:0 SELECT COUNT(*) FROM sys_dict_data WHERE dict_type = 'qr_code_embed_position'
+INSERT INTO `sys_dict_type`
+(`dict_name`, `dict_type`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`)
+VALUES
+    ('二维码嵌入海报定位', 'qr_code_embed_position', '0', 'admin', NOW(), '', NULL, 'embedQRCode二维码在主图上的坐标配置,第1项值为1时使用第2/3项作为x/y');
+
+INSERT INTO `sys_dict_data`
+(`dict_sort`, `dict_label`, `dict_value`, `dict_type`, `css_class`, `list_class`, `is_default`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`)
+VALUES
+    (1, '是否开启二维码字典定位', '0', 'qr_code_embed_position', '', 'info', 'Y', '0', 'admin', NOW(), '', NULL, '值为1时使用字典配置的x/y定位二维码,默认0使用250/1160,sort就是id不能变'),
+    (2, '二维码X坐标', '250', 'qr_code_embed_position', '', 'default', 'N', '0', 'admin', NOW(), '', NULL, '二维码距主图左侧像素,sort就是id不能变'),
+    (3, '二维码Y坐标', '1160', 'qr_code_embed_position', '', 'default', 'N', '0', 'admin', NOW(), '', NULL, '二维码距主图顶部像素,sort就是id不能变');
+--rollback DELETE FROM sys_dict_data WHERE dict_type = 'qr_code_embed_position';
+--rollback DELETE FROM sys_dict_type WHERE dict_type = 'qr_code_embed_position';