邀请活动-二维码
This commit is contained in:
@@ -72,11 +72,6 @@
|
||||
<artifactId>tomcat-embed-core</artifactId>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.zxing</groupId>
|
||||
<artifactId>javase</artifactId>
|
||||
<version>${zxing.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Sa-Token 权限认证, 在线文档:https://sa-token.cc/ -->
|
||||
<dependency>
|
||||
|
@@ -5,14 +5,13 @@ import cn.hutool.core.date.DatePattern;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.accompany.admin.dto.link.ShortLinkAdminDto;
|
||||
import com.accompany.admin.service.link.ShortLinkAdminService;
|
||||
import com.accompany.admin.util.QrCodeUtil;
|
||||
import com.accompany.business.util.QrCodeUtil;
|
||||
import com.accompany.admin.vo.link.ShortLinkAdminVo;
|
||||
import com.accompany.business.enums.link.ShortLinkTypeEnum;
|
||||
import com.accompany.business.model.link.ShortLink;
|
||||
import com.accompany.business.model.link.ShortLinkRecord;
|
||||
import com.accompany.business.mybatismapper.link.ShortLinkMapper;
|
||||
import com.accompany.business.mybatismapper.link.ShortLinkRecordMapper;
|
||||
import com.accompany.business.service.api.QinniuService;
|
||||
import com.accompany.common.constant.Constant;
|
||||
import com.accompany.common.model.PageReq;
|
||||
import com.accompany.common.tencent.cos.TencentCosUploadService;
|
||||
@@ -109,7 +108,7 @@ public class ShortLinkAdminServiceImpl implements ShortLinkAdminService {
|
||||
String url = linkUrl + code;
|
||||
InputStream inputStream = null;
|
||||
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
|
||||
QrCodeUtil.encode(url, 200, 200, outputStream);
|
||||
QrCodeUtil.encode(url, outputStream);
|
||||
inputStream = new ByteArrayInputStream(outputStream.toByteArray());
|
||||
String fileName = UUIDUtil.get() + ".png";
|
||||
qrcode = uploadService.uploadByStream(inputStream, fileName);
|
||||
|
@@ -1,42 +0,0 @@
|
||||
package com.accompany.admin.util;
|
||||
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
import com.google.zxing.EncodeHintType;
|
||||
import com.google.zxing.MultiFormatWriter;
|
||||
import com.google.zxing.client.j2se.MatrixToImageWriter;
|
||||
import com.google.zxing.common.BitMatrix;
|
||||
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
|
||||
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 二维码生成工具类
|
||||
*/
|
||||
public class QrCodeUtil {
|
||||
|
||||
/**
|
||||
* 生成二维码
|
||||
* David
|
||||
*
|
||||
* @param url url 网址
|
||||
* @param width 二维码宽度
|
||||
* @param height 二维码高度
|
||||
*/
|
||||
public static void encode(String url, int width, int height, OutputStream outputStream) {
|
||||
Map<EncodeHintType, Object> hints = new Hashtable<>();
|
||||
// 指定纠错等级
|
||||
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);
|
||||
// 指定编码格式
|
||||
hints.put(EncodeHintType.CHARACTER_SET, "UTF8");
|
||||
try {
|
||||
BitMatrix bitMatrix = new MultiFormatWriter().encode(url, BarcodeFormat.QR_CODE, width, height, hints);
|
||||
MatrixToImageWriter.writeToStream(bitMatrix, "png", outputStream);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -3,9 +3,11 @@ package com.accompany.business.model;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
public class UserInviteCode {
|
||||
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
@@ -35,86 +37,10 @@ public class UserInviteCode {
|
||||
@TableField("gen_scene")
|
||||
private Byte genScene;
|
||||
|
||||
@TableField("qr_code_url")
|
||||
private String qrCodeUrl;
|
||||
|
||||
@TableField("creator")
|
||||
private String creator;
|
||||
|
||||
public Byte getGenScene() {
|
||||
return genScene;
|
||||
}
|
||||
|
||||
public void setGenScene(Byte genScene) {
|
||||
this.genScene = genScene;
|
||||
}
|
||||
|
||||
public String getCreator() {
|
||||
return creator;
|
||||
}
|
||||
|
||||
public void setCreator(String creator) {
|
||||
this.creator = creator;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Long getUid() {
|
||||
return uid;
|
||||
}
|
||||
|
||||
public void setUid(Long uid) {
|
||||
this.uid = uid;
|
||||
}
|
||||
|
||||
public String getInviteCode() {
|
||||
return inviteCode;
|
||||
}
|
||||
|
||||
public void setInviteCode(String inviteCode) {
|
||||
this.inviteCode = inviteCode == null ? null : inviteCode.trim();
|
||||
}
|
||||
|
||||
public Date getCreateTime() {
|
||||
return createTime;
|
||||
}
|
||||
|
||||
public void setCreateTime(Date createTime) {
|
||||
this.createTime = createTime;
|
||||
}
|
||||
|
||||
public Date getUpdateTime() {
|
||||
return updateTime;
|
||||
}
|
||||
|
||||
public void setUpdateTime(Date updateTime) {
|
||||
this.updateTime = updateTime;
|
||||
}
|
||||
|
||||
public Byte getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(Byte status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public Boolean getIsPrimary() {
|
||||
return isPrimary;
|
||||
}
|
||||
|
||||
public void setIsPrimary(Boolean isPrimary) {
|
||||
this.isPrimary = isPrimary;
|
||||
}
|
||||
|
||||
public Integer getInviteCodeType() {
|
||||
return inviteCodeType;
|
||||
}
|
||||
|
||||
public void setInviteCodeType(Integer inviteCodeType) {
|
||||
this.inviteCodeType = inviteCodeType;
|
||||
}
|
||||
}
|
@@ -1,5 +1,6 @@
|
||||
package com.accompany.business.vo.invite;
|
||||
|
||||
import com.accompany.common.annotation.ReplaceAppDomain;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
@@ -43,4 +44,7 @@ public class UserInviteProfitVo {
|
||||
@ApiModelProperty("间接邀请收益")
|
||||
private Long indirectProfit = 0L;
|
||||
|
||||
@ReplaceAppDomain
|
||||
@ApiModelProperty("二维码url")
|
||||
private String qRCodeUrl;
|
||||
}
|
||||
|
@@ -105,6 +105,11 @@
|
||||
<artifactId>cloudauth20190307</artifactId>
|
||||
<version>${cloudauth20190307.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.zxing</groupId>
|
||||
<artifactId>javase</artifactId>
|
||||
<version>${zxing.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
@@ -3,11 +3,21 @@ package com.accompany.business.service.user;
|
||||
import com.accompany.business.model.UserInviteCode;
|
||||
import com.accompany.business.mybatismapper.UserInviteCodeMapper;
|
||||
import com.accompany.business.util.InviteCodeUtil;
|
||||
import com.accompany.business.util.QrCodeUtil;
|
||||
import com.accompany.common.constant.AppEnum;
|
||||
import com.accompany.common.tencent.cos.TencentCosUploadService;
|
||||
import com.accompany.common.utils.UUIDUtil;
|
||||
import com.accompany.core.base.SpringContextHolder;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -16,6 +26,7 @@ import java.util.stream.Collectors;
|
||||
* 3 * @Date: 2018/10/26 10:44
|
||||
* 4
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class UserInviteCodeService extends ServiceImpl<UserInviteCodeMapper, UserInviteCode> {
|
||||
|
||||
@@ -69,8 +80,34 @@ public class UserInviteCodeService extends ServiceImpl<UserInviteCodeMapper, Use
|
||||
userInviteCodeMapper.insert(userInviteCode);
|
||||
}
|
||||
|
||||
|
||||
public void updateUserAllInviteCodeNoPrimary(Long uid) {
|
||||
userInviteCodeMapper.updateUserAllInviteCodeNoPrimary(uid);
|
||||
}
|
||||
|
||||
public void buildInviteQRCodeUrl(UserInviteCode userInviteCode){
|
||||
String linkUrl = String.format("https//%s/%s/modules/game/register.html?inviteCode=%s&shareUid=%d",
|
||||
AppEnum.getCurApp().getApiDomain(), AppEnum.getCurApp().getH5RootDir(), userInviteCode.getInviteCode(), userInviteCode.getUid());
|
||||
|
||||
String fileName = String.format("invite_qrCode_%d_%s.png", userInviteCode.getUid(), userInviteCode.getInviteCode());
|
||||
|
||||
String url = null;
|
||||
|
||||
InputStream inputStream = null;
|
||||
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
|
||||
QrCodeUtil.encodeWithLogo(linkUrl, outputStream);
|
||||
inputStream = new ByteArrayInputStream(outputStream.toByteArray());
|
||||
url = SpringContextHolder.getBean(TencentCosUploadService.class).uploadByStream(inputStream, fileName);
|
||||
log.info("[邀请二维码] uid {} code {} 生成邀请二维码成功 {}", userInviteCode.getUid(), userInviteCode.getInviteCode(), url);
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
} finally {
|
||||
IOUtils.closeQuietly(inputStream);
|
||||
}
|
||||
|
||||
lambdaUpdate().set(UserInviteCode::getQrCodeUrl, url)
|
||||
.eq(UserInviteCode::getId, userInviteCode.getId())
|
||||
.update();
|
||||
|
||||
userInviteCode.setQrCodeUrl(url);
|
||||
}
|
||||
}
|
||||
|
@@ -13,6 +13,7 @@ import com.accompany.common.constant.Constant;
|
||||
import com.accompany.common.exception.ApiException;
|
||||
import com.accompany.core.base.UidContextHolder;
|
||||
import com.accompany.core.service.SysConfService;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -30,7 +31,7 @@ import java.util.List;
|
||||
public class UserInviteService {
|
||||
|
||||
@Autowired
|
||||
private UserInviteCodeMapper userInviteCodeMapper;
|
||||
private UserInviteCodeService userInviteCodeService;
|
||||
|
||||
@Autowired
|
||||
private UserInviteFissionRewardRecordMapper userInviteFissionRewardRecordMapper;
|
||||
@@ -45,9 +46,10 @@ public class UserInviteService {
|
||||
return profit;
|
||||
}
|
||||
profit.setUid(uid);
|
||||
List<UserInviteCode> userInviteCodes = userInviteCodeMapper.selectList(Wrappers.<UserInviteCode>lambdaQuery()
|
||||
List<UserInviteCode> userInviteCodes = userInviteCodeService.lambdaQuery()
|
||||
.eq(UserInviteCode::getUid, uid)
|
||||
.eq(UserInviteCode::getStatus, UserInviteCodeService.INVITE_CODE_STATUS_VALID));
|
||||
.eq(UserInviteCode::getStatus, UserInviteCodeService.INVITE_CODE_STATUS_VALID)
|
||||
.list();
|
||||
if (CollectionUtil.isEmpty(userInviteCodes)) {
|
||||
return profit;
|
||||
}
|
||||
@@ -57,6 +59,13 @@ public class UserInviteService {
|
||||
}
|
||||
UserInviteCode userInviteCode = userInviteCodes.get(0);
|
||||
profit.setInviteCode(userInviteCode.getInviteCode());
|
||||
|
||||
//todo 如有性能问题可异步
|
||||
if (StringUtils.isEmpty(userInviteCode.getQrCodeUrl())) {
|
||||
userInviteCodeService.buildInviteQRCodeUrl(userInviteCode);
|
||||
}
|
||||
profit.setQRCodeUrl(userInviteCode.getQrCodeUrl());
|
||||
|
||||
List<UserInviteFissionRewardRecord> records = userInviteFissionRewardRecordMapper.selectList(Wrappers.<UserInviteFissionRewardRecord>lambdaQuery()
|
||||
.eq(UserInviteFissionRewardRecord::getUid, uid)
|
||||
.between(config.getStartTime() != null && config.getEndTime() != null, UserInviteFissionRewardRecord::getCreateTime, config.getStartTime(), config.getEndTime()));
|
||||
|
@@ -0,0 +1,97 @@
|
||||
package com.accompany.business.util;
|
||||
|
||||
import com.accompany.common.config.TencentCosConfig;
|
||||
import com.accompany.common.tencent.cos.TencentCosUploadService;
|
||||
import com.accompany.core.base.SpringContextHolder;
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
import com.google.zxing.EncodeHintType;
|
||||
import com.google.zxing.MultiFormatWriter;
|
||||
import com.google.zxing.client.j2se.MatrixToImageConfig;
|
||||
import com.google.zxing.client.j2se.MatrixToImageWriter;
|
||||
import com.google.zxing.common.BitMatrix;
|
||||
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
|
||||
import lombok.SneakyThrows;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.*;
|
||||
import java.awt.geom.RoundRectangle2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.util.HashMap;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 二维码生成工具类
|
||||
*/
|
||||
public class QrCodeUtil {
|
||||
|
||||
private static final String LOGO_FILE = "piko_logo_60x60.png";
|
||||
|
||||
/**
|
||||
* 生成二维码
|
||||
* David
|
||||
*
|
||||
* @param url url 网址
|
||||
* @return
|
||||
*/
|
||||
@SneakyThrows
|
||||
public static void encode(String url, OutputStream outputStream) {
|
||||
Map<EncodeHintType, Object> hints = new Hashtable<>();
|
||||
// 指定纠错等级
|
||||
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);
|
||||
// 指定编码格式
|
||||
hints.put(EncodeHintType.CHARACTER_SET, "UTF8");
|
||||
BitMatrix bitMatrix = new MultiFormatWriter().encode(url, BarcodeFormat.QR_CODE, 200, 200, hints);
|
||||
MatrixToImageWriter.writeToStream(bitMatrix, "png", outputStream);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成二维码
|
||||
*/
|
||||
@SneakyThrows
|
||||
public static void encodeWithLogo(String url, OutputStream outputStream) {
|
||||
Map<EncodeHintType, Object> hints = new HashMap<>();
|
||||
//内容编码格式
|
||||
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
|
||||
// 指定纠错等级
|
||||
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
|
||||
//设置二维码边的空度,非负数
|
||||
hints.put(EncodeHintType.MARGIN, 1);
|
||||
BitMatrix bitMatrix = new MultiFormatWriter().encode(url, BarcodeFormat.QR_CODE, 150, 150, hints);
|
||||
//MatrixToImageWriter.writeToPath(bitMatrix, "png", new File("C:\\Users\\84232\\Desktop\\321.png").toPath());// 输出原图片
|
||||
MatrixToImageConfig matrixToImageConfig = new MatrixToImageConfig(0xFF000001, 0xFFFFFFFF);
|
||||
BufferedImage logoImage = LogoMatrix(MatrixToImageWriter.toBufferedImage(bitMatrix,matrixToImageConfig));
|
||||
ImageIO.write(logoImage, "png", outputStream);
|
||||
}
|
||||
|
||||
/**
|
||||
* 二维码添加logo
|
||||
* @return 返回带有logo的二维码图片
|
||||
*/
|
||||
@SneakyThrows
|
||||
public static BufferedImage LogoMatrix(BufferedImage bufferedImage) {
|
||||
Graphics2D g2 = bufferedImage.createGraphics();
|
||||
|
||||
int matrixWidth = bufferedImage.getWidth();
|
||||
int matrixHeigh = bufferedImage.getHeight();
|
||||
|
||||
String url = SpringContextHolder.getBean(TencentCosConfig.class).getUrlPrefix() + "/" + LOGO_FILE;
|
||||
BufferedImage logo = ImageIO.read(new URL(url));
|
||||
|
||||
//开始绘制图片
|
||||
g2.drawImage(logo,matrixWidth/5*2,matrixHeigh/5*2, matrixWidth/5, matrixHeigh/5, null);//绘制
|
||||
BasicStroke stroke = new BasicStroke(5,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND);
|
||||
g2.setStroke(stroke);// 设置笔画对象
|
||||
|
||||
g2.dispose();
|
||||
bufferedImage.flush() ;
|
||||
|
||||
return bufferedImage ;
|
||||
}
|
||||
|
||||
}
|
@@ -10,6 +10,8 @@ import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
||||
/**
|
||||
* @author: liaozetao
|
||||
* @date: 2024/3/12 15:26
|
||||
|
@@ -99,7 +99,7 @@
|
||||
<hippo4j-core.version>1.5.0</hippo4j-core.version>
|
||||
<android-json.version>0.0.20131108.vaadin1</android-json.version>
|
||||
<bcprov-jdk15on.version>1.64</bcprov-jdk15on.version>
|
||||
<zxing.version>3.2.0</zxing.version>
|
||||
<zxing.version>3.5.3</zxing.version>
|
||||
<bitwalker.version>1.20</bitwalker.version>
|
||||
<sa-token.version>1.34.0</sa-token.version>
|
||||
<pinyin4j.version>2.5.1</pinyin4j.version>
|
||||
|
Reference in New Issue
Block a user