feat:核销海报
This commit is contained in:
1 parent
a4cddba118
commit
2b34989bfc
11 files changed
+241
-4
No files matched your search
@@ -128,6 +128,12 @@
|
||||
<artifactId>hutool-all</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.google.zxing</groupId>
|
||||
<artifactId>core</artifactId>
|
||||
<version>3.3.3</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>transmittable-thread-local</artifactId>
|
||||
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
package cn.iocoder.yudao.module.trade.controller.app.brokerage;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.user.BrokerageUserCreateReqVO;
|
||||
import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageCodeDO;
|
||||
import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageCodeService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
|
||||
|
||||
@Tag(name = "用户 APP - 分销码")
|
||||
@RestController
|
||||
@RequestMapping("/trade/brokerage-code")
|
||||
@Validated
|
||||
@Slf4j
|
||||
public class AppBrokerageCodeController {
|
||||
|
||||
@Resource
|
||||
private BrokerageCodeService brokerageCodeService;
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获取用户的分销码")
|
||||
public CommonResult<BrokerageCodeDO> createBrokerageUser() {
|
||||
return success(brokerageCodeService.getUserBrokerageCode(getLoginUserId()));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+5
@@ -43,4 +43,9 @@ public class BrokerageCodeDO extends BaseDO {
|
||||
*/
|
||||
private String code;
|
||||
|
||||
/**
|
||||
* 分销链接
|
||||
*/
|
||||
private String url;
|
||||
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
package cn.iocoder.yudao.module.trade.framework.web.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@ConfigurationProperties("brokerage")
|
||||
@Data
|
||||
public class TradeBrokerageConfiguration {
|
||||
|
||||
/**
|
||||
* app下载地址
|
||||
*/
|
||||
private String downloadUrl;
|
||||
|
||||
}
|
||||
+5
-1
@@ -1,7 +1,7 @@
|
||||
package cn.iocoder.yudao.module.trade.service.brokerage;
|
||||
|
||||
import java.util.*;
|
||||
import javax.validation.*;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.code.BrokerageCodePageReqVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.code.BrokerageCodeSaveReqVO;
|
||||
@@ -37,4 +37,8 @@ public interface BrokerageCodeService {
|
||||
*/
|
||||
PageResult<BrokerageCodeDO> getBrokerageCodePage(BrokerageCodePageReqVO pageReqVO);
|
||||
|
||||
/**
|
||||
* 获取用户的分销码
|
||||
*/
|
||||
BrokerageCodeDO getUserBrokerageCode(Long userId);
|
||||
}
|
||||
+64
@@ -1,14 +1,24 @@
|
||||
package cn.iocoder.yudao.module.trade.service.brokerage;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import cn.iocoder.yudao.module.infra.api.file.FileApi;
|
||||
import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.code.BrokerageCodePageReqVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.code.BrokerageCodeSaveReqVO;
|
||||
import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageCodeDO;
|
||||
import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.BrokerageCodeMapper;
|
||||
import cn.iocoder.yudao.module.trade.framework.web.config.TradeBrokerageConfiguration;
|
||||
import cn.iocoder.yudao.module.trade.util.PosterPicGen;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.util.*;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
|
||||
@@ -18,13 +28,20 @@ import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.BROKERAGE_C
|
||||
/**
|
||||
* 分销码 Service 实现类
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@Validated
|
||||
public class BrokerageCodeServiceImpl implements BrokerageCodeService {
|
||||
|
||||
@Resource
|
||||
private TradeBrokerageConfiguration brokerageConfiguration;
|
||||
|
||||
@Resource
|
||||
private BrokerageCodeMapper brokerageCodeMapper;
|
||||
|
||||
@Resource
|
||||
private FileApi fileApi;
|
||||
|
||||
@Override
|
||||
public Long createBrokerageCode(BrokerageCodeSaveReqVO createReqVO) {
|
||||
// 插入
|
||||
@@ -67,4 +84,51 @@ public class BrokerageCodeServiceImpl implements BrokerageCodeService {
|
||||
return brokerageCodeMapper.selectPage(pageReqVO);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户的分销码
|
||||
*/
|
||||
@Override
|
||||
public BrokerageCodeDO getUserBrokerageCode(Long userId) {
|
||||
// 查询用户有没有分销码
|
||||
BrokerageCodeDO brokerageCode = brokerageCodeMapper.selectOne(BrokerageCodeDO::getMemberId, userId);
|
||||
if (ObjectUtil.isNotEmpty(brokerageCode)) return brokerageCode;
|
||||
return generateCode(userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成用户的分销码
|
||||
*/
|
||||
private BrokerageCodeDO generateCode(Long userId) {
|
||||
boolean isRepet = true;
|
||||
String code = null;
|
||||
while (isRepet) {
|
||||
code = RandomUtil.randomNumbers(8);
|
||||
BrokerageCodeDO brokerageCode = brokerageCodeMapper.selectOne(BrokerageCodeDO::getCode, code);
|
||||
isRepet = ObjectUtil.isNotEmpty(brokerageCode);
|
||||
}
|
||||
String url = generatePosterUrl(code, userId);
|
||||
BrokerageCodeDO saveObj = BrokerageCodeDO.builder().memberId(userId).code(code).posterPic(generatePosterPic(code, url)).url(url).build();
|
||||
brokerageCodeMapper.insert(saveObj);
|
||||
return saveObj;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成分销海报图
|
||||
*/
|
||||
private String generatePosterPic(String code, String qrCodeUrl) {
|
||||
try {
|
||||
byte[] fileInputStream = new PosterPicGen().setCode(code).setQrCodeUrl(qrCodeUrl).gen();
|
||||
String file = fileApi.createFile(fileInputStream);
|
||||
return file;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
log.error("|生成分销海报图|,意外的错误error:|{}|", e.getMessage());
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private String generatePosterUrl(String code, Long userId) {
|
||||
return brokerageConfiguration.getDownloadUrl() + "?code=" + code + "&userId=" + userId;
|
||||
}
|
||||
|
||||
}
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
package cn.iocoder.yudao.module.trade.util;
|
||||
|
||||
|
||||
import cn.hutool.core.io.resource.ResourceUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.extra.qrcode.QrCodeUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
||||
/**
|
||||
* 生成海报
|
||||
*/
|
||||
@Slf4j
|
||||
public class PosterPicGen {
|
||||
|
||||
private Graphics2D graphics;
|
||||
|
||||
private int pageWidth = 375;
|
||||
|
||||
private int pageHeight = 700;
|
||||
|
||||
private String title = "荷塘月色";
|
||||
|
||||
private String description = "来自缘分的相遇";
|
||||
|
||||
private String code = "";
|
||||
|
||||
private String qrCodeUrl = "";
|
||||
|
||||
private String bottomDescription = "微信无法打开的用户请更换为其他方式扫码";
|
||||
|
||||
public PosterPicGen setCode(String code) {
|
||||
this.code = code;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PosterPicGen
|
||||
|
||||
setQrCodeUrl(String qrCodeUrl) {
|
||||
this.qrCodeUrl = qrCodeUrl;
|
||||
return this;
|
||||
}
|
||||
|
||||
public byte[] gen() {
|
||||
try {
|
||||
BufferedImage baseImage = ImageIO.read(ResourceUtil.getResource("image/base-poster.png"));
|
||||
baseImage.getScaledInstance(this.pageWidth, this.pageHeight, Image.SCALE_SMOOTH);
|
||||
graphics = baseImage.createGraphics();
|
||||
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
// 设置 title
|
||||
graphics.setFont(new Font("PingFang SC, Microsoft YaHei, sans-serif", Font.BOLD, 18));
|
||||
graphics.setColor(Color.decode("#333333"));
|
||||
graphics.drawString(this.title, 84, 60);
|
||||
// 设置 description
|
||||
graphics.setFont(new Font("PingFang SC, Microsoft YaHei, sans-serif", Font.PLAIN, 14));
|
||||
graphics.setColor(Color.decode("#666666"));
|
||||
graphics.drawString(this.description, 84, 85);
|
||||
// 设置 code
|
||||
writeCenterText(new Font("Arial, sans-serif", Font.BOLD, 28), this.code, 270);
|
||||
// 设置 bottomDescription
|
||||
writeCenterText(new Font("PingFang SC, sans-serif", Font.PLAIN, 12), this.bottomDescription, 640);
|
||||
// 插入二维码
|
||||
if (ObjectUtil.isNotEmpty(this.qrCodeUrl)) {
|
||||
int qrWidth = 150;
|
||||
int qrHeight = 150;
|
||||
BufferedImage generate = QrCodeUtil.generate(this.qrCodeUrl, qrWidth, qrHeight);
|
||||
int x = (baseImage.getWidth() - qrWidth) / 2;
|
||||
int y = 350;
|
||||
graphics.drawImage(generate, x, y, qrWidth, qrHeight, null);
|
||||
}
|
||||
|
||||
graphics.dispose();
|
||||
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
ImageIO.write(baseImage, "png", baos);
|
||||
return baos.toByteArray();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
log.error("|生成海报|,意外的错误error:|{}|", e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void writeCenterText(Font font, String text, int y) {
|
||||
graphics.setFont(font);
|
||||
FontMetrics metrics = graphics.getFontMetrics(font);
|
||||
int x = (this.pageWidth - metrics.stringWidth(text)) / 2;
|
||||
graphics.drawString(text, x, y);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 147 KiB |
@@ -243,4 +243,7 @@ al-config:
|
||||
access-key-secret: EVXWFTS2SB6UkjUVFLhTDBfIvIXgI3
|
||||
face-scene-id: 1000016045
|
||||
face-verify-callback-url: https://rj4jv5rwqs.by.takin.cc
|
||||
face-verify-callback-token: uVuYOzoiQBWPp4A5kPgTddZlKWoSQlzc
|
||||
face-verify-callback-token: uVuYOzoiQBWPp4A5kPgTddZlKWoSQlzc
|
||||
|
||||
brokerage:
|
||||
download-url: https://www.baidu.com
|
||||
@@ -265,4 +265,7 @@ al-config:
|
||||
access-key-secret: EVXWFTS2SB6UkjUVFLhTDBfIvIXgI3
|
||||
face-scene-id: 1000016045
|
||||
face-verify-callback-url: https://rj4jv5rwqs.by.takin.cc
|
||||
face-verify-callback-token: uVuYOzoiQBWPp4A5kPgTddZlKWoSQlzc
|
||||
face-verify-callback-token: uVuYOzoiQBWPp4A5kPgTddZlKWoSQlzc
|
||||
|
||||
brokerage:
|
||||
download-url: https://www.baidu.com
|
||||
@@ -255,4 +255,7 @@ al-config:
|
||||
access-key-secret: EVXWFTS2SB6UkjUVFLhTDBfIvIXgI3
|
||||
face-scene-id: 1000016045
|
||||
face-verify-callback-url: https://rj4jv5rwqs.by.takin.cc
|
||||
face-verify-callback-token: uVuYOzoiQBWPp4A5kPgTddZlKWoSQlzc
|
||||
face-verify-callback-token: uVuYOzoiQBWPp4A5kPgTddZlKWoSQlzc
|
||||
|
||||
brokerage:
|
||||
download-url: https://www.baidu.com
|
||||
Reference in new issue
Block a user