From c40fe2c4656aeffac2e86bd136379a6ce6b3473f Mon Sep 17 00:00:00 2001 From: lzx_win <2602107437@qq.com> Date: Thu, 25 Sep 2025 11:22:08 +0800 Subject: [PATCH] 1 --- .../applet/service/impl/AppletApiLoginService.java | 1 + .../service/impl/AppletApiWaterServiceImpl.java | 97 ++++++++-------------- .../controller/AppletConfigController.java | 5 ++ .../service/impl/AppletConfigServiceImpl.java | 3 + .../java/org/jeecg/JeecgSystemApplication.java | 2 + 5 files changed, 44 insertions(+), 64 deletions(-) diff --git a/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/src/main/java/org/jeecg/modules/applet/service/impl/AppletApiLoginService.java b/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/src/main/java/org/jeecg/modules/applet/service/impl/AppletApiLoginService.java index a224060..c4cd8b2 100644 --- a/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/src/main/java/org/jeecg/modules/applet/service/impl/AppletApiLoginService.java +++ b/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/src/main/java/org/jeecg/modules/applet/service/impl/AppletApiLoginService.java @@ -191,6 +191,7 @@ public class AppletApiLoginService { user.setCreateTime(new Date()); user.setCreateBy("system"); user.setInviter(inviter); + user.setIsPromote("N"); // TODO: 如果需要unionid字段,需要在AppletUser实体类中添加该字段 // user.setUnionid(unionid); diff --git a/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/src/main/java/org/jeecg/modules/applet/service/impl/AppletApiWaterServiceImpl.java b/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/src/main/java/org/jeecg/modules/applet/service/impl/AppletApiWaterServiceImpl.java index a41516a..6598909 100644 --- a/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/src/main/java/org/jeecg/modules/applet/service/impl/AppletApiWaterServiceImpl.java +++ b/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/src/main/java/org/jeecg/modules/applet/service/impl/AppletApiWaterServiceImpl.java @@ -84,20 +84,21 @@ public class AppletApiWaterServiceImpl implements AppletApiWaterService { // 获取必要的配置信息 String xcxSharePage = appletConfigService.getContentByCode("xcxSharePage"); String backgroundImageUrl = appletConfigService.getContentByCode("qr_code_bg"); + + // 获取二维码位置配置参数 + int qrCodeX = appletConfigService.getContentByCodeAsInt("qr_code_x"); + int qrCodeY = appletConfigService.getContentByCodeAsInt("qr_code_y"); - // 优化缓存策略:使用更精确的缓存key,包含所有影响因素(包括背景图片URL) - String cacheKey = String.format("inviteCode:final:%s:%s:%s:%s", user.getId(), trial, xcxSharePage.hashCode(), backgroundImageUrl.hashCode()); - String imageCacheKey = String.format("inviteCode:image:%s:%s:%s:%s", user.getId(), trial, xcxSharePage.hashCode(), backgroundImageUrl.hashCode()); + // 优化缓存策略:使用更精确的缓存key,包含所有影响因素(包括背景图片URL和二维码位置配置) + String cacheKey = String.format("inviteCode:final:%s:%s:%s:%s:%s:%s", + user.getId(), trial, xcxSharePage.hashCode(), backgroundImageUrl.hashCode(), qrCodeX, qrCodeY); - // 首先检查是否有最终合成图片的缓存 - byte[] cachedImage = (byte[]) redisUtil.get(imageCacheKey); - if (cachedImage != null) { - log.info("从缓存返回邀请码图片,用户ID: {}", user.getId()); - return cachedImage; - } + // 移除图片数据的Redis缓存,避免类型转换错误 + // 直接检查OSS中是否已存在最终图片 // 检查OSS中是否已存在最终图片 - String finalPath = "invite/final/" + user.getId() + "_" + xcxSharePage + "_" + trial + ".jpg"; + String finalPath = String.format("invite/final/%s_%s_%s_%s_%s_%s.jpg", + user.getId(), trial, xcxSharePage.hashCode(), backgroundImageUrl.hashCode(), qrCodeX, qrCodeY); try { InputStream ossFile = OssBootUtil.getOssFile(finalPath, null); if (ossFile != null) { @@ -112,8 +113,7 @@ public class AppletApiWaterServiceImpl implements AppletApiWaterService { buffer.flush(); byte[] ossImageBytes = buffer.toByteArray(); - // 将OSS中的图片缓存到Redis,设置24小时过期 - redisUtil.set(imageCacheKey, ossImageBytes, 24 * 60 * 60); + // 直接返回OSS中的图片,不再缓存到Redis log.info("从OSS返回邀请码图片,用户ID: {}", user.getId()); return ossImageBytes; } finally { @@ -125,26 +125,15 @@ public class AppletApiWaterServiceImpl implements AppletApiWaterService { } try { - // 检查是否有小程序码的缓存 - String qrCodeCacheKey = String.format("inviteCode:qrcode:%s:%s:%s", user.getId(), trial, xcxSharePage.hashCode()); - byte[] cachedQrCode = (byte[]) redisUtil.get(qrCodeCacheKey); - - byte[] qrCodeBytes; - if (cachedQrCode != null) { - log.info("使用缓存的小程序码,用户ID: {}", user.getId()); - qrCodeBytes = cachedQrCode; - } else { - log.info("生成新的小程序码,用户ID: {}", user.getId()); - qrCodeBytes = generateWxQrCode(user, xcxSharePage, trial); - // 缓存小程序码,设置7天过期(小程序码相对稳定) - redisUtil.set(qrCodeCacheKey, qrCodeBytes, 7 * 24 * 60 * 60); - } + // 直接生成小程序码,移除Redis缓存避免类型转换错误 + log.info("生成小程序码,用户ID: {}", user.getId()); + byte[] qrCodeBytes = generateWxQrCode(user, xcxSharePage, trial); - // 生成最终合成图片 - byte[] finalImage = this.generateAndCombineImagesFromUrl2(qrCodeBytes, backgroundImageUrl); + // 生成最终合成图片,传递已获取的配置参数避免重复调用 + byte[] finalImage = this.generateAndCombineImagesFromUrl2(qrCodeBytes, backgroundImageUrl, qrCodeX, qrCodeY); - // 异步上传到OSS并缓存 - uploadAndCacheAsync(finalImage, finalPath, imageCacheKey); + // 异步上传到OSS(移除Redis缓存) + uploadToOssAsync(finalImage, finalPath); return finalImage; } catch (Exception e) { @@ -187,10 +176,10 @@ public class AppletApiWaterServiceImpl implements AppletApiWaterService { } /** - * 异步上传到OSS并缓存到Redis + * 异步上传到OSS */ - private void uploadAndCacheAsync(byte[] imageBytes, String ossPath, String cacheKey) { - // 使用线程池异步执行上传和缓存操作 + private void uploadToOssAsync(byte[] imageBytes, String ossPath) { + // 使用线程池异步执行上传操作 CompletableFuture.runAsync(() -> { try { // 上传到OSS @@ -199,48 +188,28 @@ public class AppletApiWaterServiceImpl implements AppletApiWaterService { } catch (Exception e) { log.error("异步上传OSS失败,路径: {}", ossPath, e); } - }, asyncExecutor).thenRunAsync(() -> { - try { - // 缓存到Redis,设置24小时过期 - redisUtil.set(cacheKey, imageBytes, 24 * 60 * 60); - log.info("异步缓存完成,key: {}", cacheKey); - } catch (Exception e) { - log.error("异步缓存失败,key: {}", cacheKey, e); - } }, asyncExecutor); } - public byte[] generateAndCombineImagesFromUrl2(byte[] qrCodeImageByte, String backgroundUrl) { + public byte[] generateAndCombineImagesFromUrl2(byte[] qrCodeImageByte, String backgroundUrl, int qr_code_x, int qr_code_y) { File file = null; try { - // 缓存背景图片,避免重复下载 - String bgCacheKey = "background_image:" + backgroundUrl.hashCode(); - BufferedImage backgroundImage = (BufferedImage) redisUtil.get(bgCacheKey); - - if (backgroundImage == null) { - // 从URL加载背景图像 - URL backgroundImageUrl = new URL(backgroundUrl); - backgroundImage = ImageIO.read(backgroundImageUrl); - // 缓存背景图片,设置1小时过期 - redisUtil.set(bgCacheKey, backgroundImage, 60 * 60); - log.debug("背景图片已缓存"); - } else { - log.debug("使用缓存的背景图片"); - } + // 直接从URL加载背景图像,移除Redis缓存避免类型转换问题 + URL backgroundImageUrl = new URL(backgroundUrl); + BufferedImage backgroundImage = ImageIO.read(backgroundImageUrl); + log.debug("从URL加载背景图片: {}", backgroundUrl); // 从字节数组加载小程序码图像 BufferedImage qrCodeImage = ImageIO.read(new ByteArrayInputStream(qrCodeImageByte)); - // 获取配置参数 - int qr_code_y = appletConfigService.getContentByCodeAsInt("qr_code_y"); - int qr_code_x = appletConfigService.getContentByCodeAsInt("qr_code_x"); + // 使用传入的配置参数,避免重复调用配置服务 - // 创建一个新的BufferedImage来保存合并后的图像(复制背景图片) + // 直接使用背景图片作为基础,避免创建新的图像导致黑边 BufferedImage combinedImage = new BufferedImage( backgroundImage.getWidth(), backgroundImage.getHeight(), - BufferedImage.TYPE_INT_RGB + backgroundImage.getType() // 使用背景图片的原始类型,保持透明度 ); Graphics2D g2d = combinedImage.createGraphics(); @@ -250,8 +219,8 @@ public class AppletApiWaterServiceImpl implements AppletApiWaterService { g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - // 绘制背景图像 - g2d.drawImage(backgroundImage, 0, 0, null); + // 先绘制背景图像,完全覆盖画布 + g2d.drawImage(backgroundImage, 0, 0, backgroundImage.getWidth(), backgroundImage.getHeight(), null); int wh = backgroundImage.getWidth() / 3; @@ -259,7 +228,7 @@ public class AppletApiWaterServiceImpl implements AppletApiWaterService { int qrCodeX = (backgroundImage.getWidth() - wh) / 2; int qrCodeY = (int) ((backgroundImage.getHeight() - wh) * 0.6); - // 绘制小程序码图像 + // 绘制小程序码图像,使用传入的位置参数 g2d.drawImage(qrCodeImage, qrCodeX + qr_code_x, qrCodeY + qr_code_y, wh, wh, null); // 释放Graphics2D资源 diff --git a/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/src/main/java/org/jeecg/modules/demo/appletConfig/controller/AppletConfigController.java b/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/src/main/java/org/jeecg/modules/demo/appletConfig/controller/AppletConfigController.java index 1f1748b..d8f4362 100644 --- a/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/src/main/java/org/jeecg/modules/demo/appletConfig/controller/AppletConfigController.java +++ b/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/src/main/java/org/jeecg/modules/demo/appletConfig/controller/AppletConfigController.java @@ -29,6 +29,7 @@ import org.jeecgframework.poi.excel.entity.ImportParams; import org.jeecgframework.poi.excel.view.JeecgEntityExcelView; import org.jeecg.common.system.base.controller.JeecgController; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.CacheEvict; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartHttpServletRequest; @@ -90,6 +91,7 @@ public class AppletConfigController extends JeecgController add(@RequestBody AppletConfig appletConfig) { appletConfigService.save(appletConfig); @@ -106,6 +108,7 @@ public class AppletConfigController extends JeecgController edit(@RequestBody AppletConfig appletConfig) { appletConfigService.updateById(appletConfig); return Result.OK("编辑成功!"); @@ -121,6 +124,7 @@ public class AppletConfigController extends JeecgController delete(@RequestParam(name="id",required=true) String id) { appletConfigService.removeById(id); return Result.OK("删除成功!"); @@ -136,6 +140,7 @@ public class AppletConfigController extends JeecgController deleteBatch(@RequestParam(name="ids",required=true) String ids) { this.appletConfigService.removeByIds(Arrays.asList(ids.split(","))); return Result.OK("批量删除成功!"); diff --git a/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/src/main/java/org/jeecg/modules/demo/appletConfig/service/impl/AppletConfigServiceImpl.java b/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/src/main/java/org/jeecg/modules/demo/appletConfig/service/impl/AppletConfigServiceImpl.java index 2b46fc0..31b97aa 100644 --- a/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/src/main/java/org/jeecg/modules/demo/appletConfig/service/impl/AppletConfigServiceImpl.java +++ b/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/src/main/java/org/jeecg/modules/demo/appletConfig/service/impl/AppletConfigServiceImpl.java @@ -3,6 +3,7 @@ package org.jeecg.modules.demo.appletConfig.service.impl; import org.jeecg.modules.demo.appletConfig.entity.AppletConfig; import org.jeecg.modules.demo.appletConfig.mapper.AppletConfigMapper; import org.jeecg.modules.demo.appletConfig.service.IAppletConfigService; +import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; @@ -19,6 +20,7 @@ import java.util.List; public class AppletConfigServiceImpl extends ServiceImpl implements IAppletConfigService { @Override + @Cacheable(value = "appletConfig", key = "#code") public String getContentByCode(String code) { AppletConfig config = lambdaQuery() .eq(AppletConfig::getCode, code) @@ -28,6 +30,7 @@ public class AppletConfigServiceImpl extends ServiceImpl