From 14f4f50e189073c86bd4edc39733f50ad114097e Mon Sep 17 00:00:00 2001 From: Jack <46790855@qq.com> Date: Fri, 15 Aug 2025 08:52:52 +0800 Subject: [PATCH] =?UTF-8?q?=E9=AA=8C=E8=AF=81=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- captcha_preview.png | Bin 0 -> 527 bytes .../mall/common/utils/CaptchaUtil.java | 358 ++++++++++++++++++ .../impl/ShopBaseConfigServiceImpl.java | 132 +------ 3 files changed, 361 insertions(+), 129 deletions(-) create mode 100644 captcha_preview.png create mode 100644 mall-common/src/main/java/com/suisung/mall/common/utils/CaptchaUtil.java diff --git a/captcha_preview.png b/captcha_preview.png new file mode 100644 index 0000000000000000000000000000000000000000..c4da507cbebd59cd275e7817fbea27e2346b883f GIT binary patch literal 527 zcmV+q0`UEbP)>!73txU1g$-F)ly)E6wrwwKjM6>$lP#g!d7Qp6ItQo@ zb!GIU4pRYL8C^gpo?N>X&`LIxVi&eshuexef|5oLG`$UQroPYVFH#(9-B^M;PynqA zG{hembzmJ@t5s;?GL}GOkjs(KV zTxnc__O5?1{}jhJEz&2q;Cdv7xQ~{mb})7Dfu4vCCM9}hv<~Zl?7(t@M_m2uh#5wI z&*#M1sl%y{)`2@xD+-~nZ|_bPBMLnPXcXb1yfOiOS{@UniuX(|6KKU~ZDa?zrM~BK z)hI>0r$`tHK2bEl+A`O^m#S*RnQqHl&&gQUJz5SUCwTCQkvC)+&3u`zk3I!gG!Ic1 zLpY^G04=4CdG^iU=rojY8i9d#p5u`5X!pxUPXo?xLxG;R^gjs$Y^XV`&FOskq-Wn4 z0nqbY^ZOvuUvP5&u*xD>P|^vL(cWssE<@BGs^Nnq7|_7#4DZSM0dK%xAL{~r86iq> zBx=GOpyL7JOUfqz&B@&T=5|rE{p8aMf4tofXs5bgK$ktJ>qyD0EUSzTvKPc>X6=?R RY)}9I002ovPDHLkV1iPn?QsAA literal 0 HcmV?d00001 diff --git a/mall-common/src/main/java/com/suisung/mall/common/utils/CaptchaUtil.java b/mall-common/src/main/java/com/suisung/mall/common/utils/CaptchaUtil.java new file mode 100644 index 00000000..265f3368 --- /dev/null +++ b/mall-common/src/main/java/com/suisung/mall/common/utils/CaptchaUtil.java @@ -0,0 +1,358 @@ +/* + * Copyright (c) 2025. Lorem ipsum dolor sit amet, consectetur adipiscing elit. + * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. + * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. + * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. + * Vestibulum commodo. Ut rhoncus gravida arcu. + */ + +package com.suisung.mall.common.utils; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; + +public class CaptchaUtil { + + public static void main(String[] args) throws IOException { + // 生成示例验证码图片 + String captchaCode = generateSimpleCaptcha(4); + System.out.println("生成的验证码: " + captchaCode); + + BufferedImage image = createSimpleCaptchaImage(captchaCode); + + // 保存到文件以便预览 + File output = new File("captcha_preview.png"); + ImageIO.write(image, "png", output); + System.out.println("验证码图片已保存到: " + output.getAbsolutePath()); + } + + /** + * 生成简单的数字和字母验证码 + * + * @param length 验证码长度 + * @return 验证码字符串 + */ + public static String generateSimpleCaptcha(int length) { + String chars = "0123456789"; + StringBuilder captcha = new StringBuilder(); + java.util.Random random = new java.util.Random(); + for (int i = 0; i < length; i++) { + captcha.append(chars.charAt(random.nextInt(chars.length()))); + } + return captcha.toString(); + } + + /** + * 创建简单的验证码图片(不依赖系统字体) + * + * @param captchaCode 验证码 + * @return 验证码图片 + */ + public static BufferedImage createSimpleCaptchaImage(String captchaCode) { + int width = 120; + int height = 40; + + BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + java.awt.Graphics2D g = image.createGraphics(); + + // 设置背景色 + g.setColor(java.awt.Color.WHITE); + g.fillRect(0, 0, width, height); + + // 绘制干扰线 + java.util.Random random = new java.util.Random(); + g.setColor(new java.awt.Color(200, 200, 200)); + for (int i = 0; i < 8; i++) { + int x1 = random.nextInt(width); + int y1 = random.nextInt(height); + int x2 = random.nextInt(width); + int y2 = random.nextInt(height); + g.drawLine(x1, y1, x2, y2); + } + + // 绘制干扰点 + g.setColor(new java.awt.Color(200, 200, 200)); + for (int i = 0; i < 30; i++) { + int x = random.nextInt(width); + int y = random.nextInt(height); + g.fillRect(x, y, 1, 1); + } + + // 绘制验证码字符 + int charWidth = width / (captchaCode.length() + 1); + + for (int i = 0; i < captchaCode.length(); i++) { + char c = captchaCode.charAt(i); + int x = (i + 1) * charWidth - 8; + int y = height / 2 - 10; + + // 添加随机旋转和位置偏移 + java.awt.geom.AffineTransform original = g.getTransform(); + java.awt.geom.AffineTransform transform = new java.awt.geom.AffineTransform(); + transform.translate(x, y); + // 减小旋转角度,避免字符变形过大 + transform.rotate((random.nextDouble() - 0.5) * 0.3); + g.setTransform(transform); + + // 使用点阵方式绘制字符 + drawCharacter(g, c, 0, 0, random); + + // 恢复原始变换 + g.setTransform(original); + } + + g.dispose(); + return image; + } + + /** + * 用点阵方式绘制字符(避免使用字体) + * + * @param g Graphics对象 + * @param c 要绘制的字符 + * @param x x坐标偏移 + * @param y y坐标偏移 + * @param random 随机数生成器 + */ + private static void drawCharacter(java.awt.Graphics2D g, char c, int x, int y, java.util.Random random) { + // 使用5x7点阵绘制字符 + int[][] pattern = getCharacterPattern(c); + + if (pattern != null) { + // 设置画笔颜色 + g.setColor(java.awt.Color.BLACK); + + for (int i = 0; i < pattern.length; i++) { + for (int j = 0; j < pattern[i].length; j++) { + if (pattern[i][j] == 1) { + // 添加轻微随机偏移使字符不那么规整 + int offsetX = random.nextInt(3) - 1; + int offsetY = random.nextInt(3) - 1; + // 使用更清晰的绘制方式,增大像素点 + g.fillRect(x + j * 3, y + i * 3, 2, 2); + } + } + } + } else { + // 如果字符图案未定义,绘制一个简单的替代图形 + g.setColor(java.awt.Color.GRAY); + g.fillOval(x + 5, y + 5, 6, 6); + } + } + + /** + * 获取字符的点阵图案 + * + * @param c 字符 + * @return 点阵图案(二维数组) + */ + private static int[][] getCharacterPattern(char c) { + // 简化的5x7点阵字符图案 + switch (c) { + case '0': + return new int[][]{ + {0, 1, 1, 1, 0}, + {1, 0, 0, 0, 1}, + {1, 0, 0, 0, 1}, + {1, 0, 0, 0, 1}, + {1, 0, 0, 0, 1}, + {1, 0, 0, 0, 1}, + {0, 1, 1, 1, 0} + }; + case '1': + return new int[][]{ + {0, 0, 1, 0, 0}, + {0, 1, 1, 0, 0}, + {1, 0, 1, 0, 0}, + {0, 0, 1, 0, 0}, + {0, 0, 1, 0, 0}, + {0, 0, 1, 0, 0}, + {1, 1, 1, 1, 1} + }; + case '2': + return new int[][]{ + {0, 1, 1, 1, 0}, + {1, 0, 0, 0, 1}, + {0, 0, 0, 0, 1}, + {0, 0, 0, 1, 0}, + {0, 0, 1, 0, 0}, + {0, 1, 0, 0, 0}, + {1, 1, 1, 1, 1} + }; + case '3': + return new int[][]{ + {0, 1, 1, 1, 0}, + {1, 0, 0, 0, 1}, + {0, 0, 0, 0, 1}, + {0, 0, 1, 1, 0}, + {0, 0, 0, 0, 1}, + {1, 0, 0, 0, 1}, + {0, 1, 1, 1, 0} + }; + case '4': + return new int[][]{ + {0, 0, 0, 1, 0}, + {0, 0, 1, 1, 0}, + {0, 1, 0, 1, 0}, + {1, 0, 0, 1, 0}, + {1, 1, 1, 1, 1}, + {0, 0, 0, 1, 0}, + {0, 0, 0, 1, 0} + }; + case '5': + return new int[][]{ + {1, 1, 1, 1, 1}, + {1, 0, 0, 0, 0}, + {1, 0, 0, 0, 0}, + {1, 1, 1, 1, 0}, + {0, 0, 0, 0, 1}, + {0, 0, 0, 0, 1}, + {1, 1, 1, 1, 0} + }; + case '6': + return new int[][]{ + {0, 1, 1, 1, 0}, + {1, 0, 0, 0, 0}, + {1, 0, 0, 0, 0}, + {1, 1, 1, 1, 0}, + {1, 0, 0, 0, 1}, + {1, 0, 0, 0, 1}, + {0, 1, 1, 1, 0} + }; + case '7': + return new int[][]{ + {1, 1, 1, 1, 1}, + {0, 0, 0, 0, 1}, + {0, 0, 0, 1, 0}, + {0, 0, 1, 0, 0}, + {0, 1, 0, 0, 0}, + {0, 1, 0, 0, 0}, + {0, 1, 0, 0, 0} + }; + case '8': + return new int[][]{ + {0, 1, 1, 1, 0}, + {1, 0, 0, 0, 1}, + {1, 0, 0, 0, 1}, + {0, 1, 1, 1, 0}, + {1, 0, 0, 0, 1}, + {1, 0, 0, 0, 1}, + {0, 1, 1, 1, 0} + }; + case '9': + return new int[][]{ + {0, 1, 1, 1, 0}, + {1, 0, 0, 0, 1}, + {1, 0, 0, 0, 1}, + {0, 1, 1, 1, 1}, + {0, 0, 0, 0, 1}, + {0, 0, 0, 0, 1}, + {0, 1, 1, 1, 0} + }; + case 'A': + case 'a': + return new int[][]{ + {0, 0, 1, 0, 0}, + {0, 1, 0, 1, 0}, + {1, 0, 0, 0, 1}, + {1, 0, 0, 0, 1}, + {1, 1, 1, 1, 1}, + {1, 0, 0, 0, 1}, + {1, 0, 0, 0, 1} + }; + case 'B': + case 'b': + return new int[][]{ + {1, 1, 1, 1, 0}, + {1, 0, 0, 0, 1}, + {1, 0, 0, 0, 1}, + {1, 1, 1, 1, 0}, + {1, 0, 0, 0, 1}, + {1, 0, 0, 0, 1}, + {1, 1, 1, 1, 0} + }; + case 'C': + case 'c': + return new int[][]{ + {0, 1, 1, 1, 0}, + {1, 0, 0, 0, 1}, + {1, 0, 0, 0, 0}, + {1, 0, 0, 0, 0}, + {1, 0, 0, 0, 0}, + {1, 0, 0, 0, 1}, + {0, 1, 1, 1, 0} + }; + case 'D': + case 'd': + return new int[][]{ + {1, 1, 1, 1, 0}, + {1, 0, 0, 0, 1}, + {1, 0, 0, 0, 1}, + {1, 0, 0, 0, 1}, + {1, 0, 0, 0, 1}, + {1, 0, 0, 0, 1}, + {1, 1, 1, 1, 0} + }; + case 'E': + case 'e': + return new int[][]{ + {1, 1, 1, 1, 1}, + {1, 0, 0, 0, 0}, + {1, 0, 0, 0, 0}, + {1, 1, 1, 1, 0}, + {1, 0, 0, 0, 0}, + {1, 0, 0, 0, 0}, + {1, 1, 1, 1, 1} + }; + case 'F': + case 'f': + return new int[][]{ + {1, 1, 1, 1, 1}, + {1, 0, 0, 0, 0}, + {1, 0, 0, 0, 0}, + {1, 1, 1, 1, 0}, + {1, 0, 0, 0, 0}, + {1, 0, 0, 0, 0}, + {1, 0, 0, 0, 0} + }; + case 'G': + case 'g': + return new int[][]{ + {0, 1, 1, 1, 0}, + {1, 0, 0, 0, 1}, + {1, 0, 0, 0, 0}, + {1, 0, 1, 1, 1}, + {1, 0, 0, 0, 1}, + {1, 0, 0, 0, 1}, + {0, 1, 1, 1, 0} + }; + case 'H': + case 'h': + return new int[][]{ + {1, 0, 0, 0, 1}, + {1, 0, 0, 0, 1}, + {1, 0, 0, 0, 1}, + {1, 1, 1, 1, 1}, + {1, 0, 0, 0, 1}, + {1, 0, 0, 0, 1}, + {1, 0, 0, 0, 1} + }; + case 'I': + case 'i': + return new int[][]{ + {0, 1, 1, 1, 0}, + {0, 0, 1, 0, 0}, + {0, 0, 1, 0, 0}, + {0, 0, 1, 0, 0}, + {0, 0, 1, 0, 0}, + {0, 0, 1, 0, 0}, + {0, 1, 1, 1, 0} + }; + default: + return null; + } + } + +} \ No newline at end of file diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/base/service/impl/ShopBaseConfigServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/base/service/impl/ShopBaseConfigServiceImpl.java index e4282006..9723b4c4 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/base/service/impl/ShopBaseConfigServiceImpl.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/base/service/impl/ShopBaseConfigServiceImpl.java @@ -6,6 +6,7 @@ import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import com.suisung.mall.common.constant.RedisConstant; import com.suisung.mall.common.modules.base.ShopBaseConfig; +import com.suisung.mall.common.utils.CaptchaUtil; import com.suisung.mall.core.web.service.RedisService; import com.suisung.mall.core.web.service.impl.BaseServiceImpl; import com.suisung.mall.shop.base.mapper.ShopBaseConfigMapper; @@ -116,10 +117,10 @@ public class ShopBaseConfigServiceImpl extends BaseServiceImpl