This commit is contained in:
zjf committed 2025-07-29 11:34:44 +08:00
1 parent d9a6808066
commit 3e7389ce16
8 files changed
+113 -29

No files matched your search

@@ -13,6 +13,16 @@
<artifactId>pjcloud-integrated-biz</artifactId>
<dependencies>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
@@ -35,12 +35,20 @@ import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import cn.hutool.extra.qrcode.QrConfig;
import java.awt.Image;
import cn.hutool.core.img.ImgUtil;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.util.Base64;
import javax.imageio.ImageIO;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import java.io.IOException;
/**
* 访客用户
@@ -127,11 +135,42 @@ public class AppVisitorController {
}
/**
* 获取动态二维码(用于门卫/机器核验,5分钟刷新一次,预约未过期时一直可用)
* @param token uuid生成的
* @param logoUrl 可选logo图片url
* 生成真正的二维码(使用ZXing库)
*/
@GetMapping("/visitorQr")
private String generateQRCode(String content) {
try {
QRCodeWriter qrCodeWriter = new QRCodeWriter();
// 设置二维码参数
Map<EncodeHintType, Object> hints = new HashMap<>();
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
hints.put(EncodeHintType.MARGIN, 2);
// 生成二维码矩阵
BitMatrix bitMatrix = qrCodeWriter.encode(content, BarcodeFormat.QR_CODE, 300, 300, hints);
// 转换为图片
BufferedImage image = new BufferedImage(300, 300, BufferedImage.TYPE_INT_RGB);
for (int x = 0; x < 300; x++) {
for (int y = 0; y < 300; y++) {
image.setRGB(x, y, bitMatrix.get(x, y) ? Color.BLACK.getRGB() : Color.WHITE.getRGB());
}
}
// 转换为Base64
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(image, "PNG", baos);
byte[] imageBytes = baos.toByteArray();
return Base64.getEncoder().encodeToString(imageBytes);
} catch (WriterException | IOException e) {
// 如果生成失败,返回一个简单的占位符
return "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==";
}
}
@GetMapping("/app/visitorQr")
@Operation(summary = "获取动态二维码" , description = "用于门卫/机器核验,5分钟刷新一次,预约未过期时一直可用" )
public R<Map<String, Object>> getVisitorQr(
@RequestParam("token") String token,
@@ -166,18 +205,8 @@ public class AppVisitorController {
// 3. 二维码内容
String qrContent = token + ":" + now5Min + ":" + sign;
// 4. 配置二维码参数
QrConfig qrConfig = new QrConfig(300, 300);
String targetType = "png";
Image logo = null;
if (logoUrl != null && !logoUrl.isEmpty()) {
try {
logo = ImgUtil.read(logoUrl);
} catch (Exception e) {
// logo读取失败可忽略
}
}
String qrBase64 = cn.hutool.extra.qrcode.QrCodeUtil.generateAsBase64(qrContent, qrConfig, targetType, logo);
// 4. 生成真正的二维码
String qrBase64 = generateQRCode(qrContent);
Map<String, Object> result = new HashMap<>();
result.put("qrBase64", qrBase64);
@@ -128,6 +128,7 @@ public class VisitorsController {
}
//-----------------------APP----------------------------
@@ -106,4 +106,11 @@ public class VisitorUserEntity extends Model<VisitorUserEntity> {
*/
@Schema(description="租户编号")
private Long tenantId;
@Schema(description="身份证号")
private String idCard;
@Schema(description="人脸图片")
private String faceUrl;
}
@@ -197,4 +197,8 @@ public class VisitorsEntity extends Model<VisitorsEntity> {
@Schema(description="邀约id")
private Long yyId;
@Schema(description="到访单位名称")
private String deptName;
}
@@ -11,6 +11,7 @@ import com.bsd.pjcloud.common.core.exception.ServiceException;
import com.bsd.pjcloud.common.core.util.BeanUtils;
import com.bsd.pjcloud.common.core.util.R;
import com.bsd.pjcloud.common.core.util.TimeUtils;
import com.bsd.pjcloud.common.core.util.WebUtils;
import com.bsd.pjcloud.common.data.datascope.DataScope;
import com.bsd.pjcloud.common.security.service.PjcloudUser;
import com.bsd.pjcloud.common.security.util.SecurityUtils;
@@ -21,21 +22,25 @@ import com.bsd.pjcloud.flow.task.entity.Process;
import com.bsd.pjcloud.integrated.constant.DictTypeEnum;
import com.bsd.pjcloud.integrated.constant.IntegratedFlowConstant;
import com.bsd.pjcloud.integrated.constant.VisitorTypeEnum;
import com.bsd.pjcloud.integrated.controller.AppVisitorUserController;
import com.bsd.pjcloud.integrated.dto.visitor.app.VisitorsAppDTO;
import com.bsd.pjcloud.integrated.dto.visitor.app.VisitorsCarAppDTO;
import com.bsd.pjcloud.integrated.dto.visitor.app.VisitorsPeopleAppDTO;
import com.bsd.pjcloud.integrated.dto.visitor.app.VisitorsYYAppDTO;
import com.bsd.pjcloud.integrated.entity.VisitorUserEntity;
import com.bsd.pjcloud.integrated.entity.VisitorsCarEntity;
import com.bsd.pjcloud.integrated.entity.VisitorsEntity;
import com.bsd.pjcloud.integrated.entity.VisitorsPeopleEntity;
import com.bsd.pjcloud.integrated.mapper.VisitorsCarMapper;
import com.bsd.pjcloud.integrated.mapper.VisitorsMapper;
import com.bsd.pjcloud.integrated.mapper.VisitorsPeopleMapper;
import com.bsd.pjcloud.integrated.service.VisitorUserService;
import com.bsd.pjcloud.integrated.service.VisitorsService;
import com.bsd.pjcloud.integrated.vo.visitor.app.VisitorsAppPageVo;
import com.bsd.pjcloud.integrated.vo.visitor.app.VisitorsAppVo;
import com.bsd.pjcloud.integrated.vo.visitor.app.VisitorsCarAppVo;
import com.bsd.pjcloud.integrated.vo.visitor.app.VisitorsPeopleAppVo;
import com.bsd.pjcloud.thirdparty.api.feign.RemoterThirdPartySmsService;
import com.bsd.pjcloud.thirdparty.api.feign.RemoterVisitorService;
import com.bsd.pjcloud.thirdparty.dto.visitor.AppointmentInfo;
import com.bsd.pjcloud.thirdparty.dto.visitor.VisitorObjectResponse;
@@ -62,13 +67,11 @@ import org.springframework.web.context.request.ServletRequestAttributes;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Value;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import java.util.*;
import java.util.stream.Collectors;
/**
@@ -91,6 +94,9 @@ public class VisitorsServiceImpl extends ServiceImpl<VisitorsMapper, VisitorsEnt
private final RemoterVisitorService remoterVisitorService;
private final RemoterThirdPartySmsService reminderThirdPartySmsService;
private final VisitorUserService visitorUserService;
@Value("${visitor.jwt-secret}")
private String visitorJwtSecret;
@@ -357,22 +363,36 @@ public class VisitorsServiceImpl extends ServiceImpl<VisitorsMapper, VisitorsEnt
if (dataVisitors == null) {
throw new ServiceException("数据不存在");
}
if (!dataVisitors.getCheckStatus().equals(TaskCheckStatusEnum.PADDING.getCode())) {
throw new ServiceException("数据已处理");
}
VisitorUserEntity visitorUserEntity = visitorUserService.getById(dataVisitors.getUserId());
VisitorsEntity visitors = new VisitorsEntity();
visitors.setId(id);
visitors.setCheckStatus(checkStatus);
if (checkStatus.equals(TaskCheckStatusEnum.RESULT.getCode())){
//审核通过
Map<String, String> stringStringHashMap = new HashMap<>();
// params: [ "createTime", "visitorName", "visitorPhone", "visitorTime", "visitorLocal","url" ]
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
stringStringHashMap.put("createTime", visitorUserEntity.getCreateTime().format(formatter));
stringStringHashMap.put("visitorName",visitorUserEntity.getRealName());
stringStringHashMap.put("visitorPhone",visitorUserEntity.getPhone());
stringStringHashMap.put("visitorTime",dataVisitors.getVStartDate()+"至"+dataVisitors.getVEndDate());
stringStringHashMap.put("visitorLocal",dataVisitors.getDeptName());
stringStringHashMap.put("url","http://127.0.0.1:9999/integrated/visitors/app/get/visitorDetail?token=7a3a059ebdf94d07a10f29ecc379094e");
reminderThirdPartySmsService.sendParamsMsg(visitorUserEntity.getPhone(),"20658",stringStringHashMap, WebUtils.getIP());
}
return baseMapper.updateById(visitors);
}
@Override
public Object getPageSQ(Page page, VisitorsEntity visitors) {
// Long userId = SecurityUtils.getUser().getId();
Long currentVisitorUserId = getCurrentVisitorUserId();
LambdaQueryWrapper<VisitorsEntity> wrapper = new LambdaQueryWrapper<>();
// wrapper.eq(VisitorsEntity::getUserId, userId);
wrapper.eq(VisitorsEntity::getUserId, currentVisitorUserId);
wrapper.eq(VisitorsEntity::getType, VisitorTypeEnum.FKSQ.getType());
wrapper.eq(StrUtils.isNotBlank(visitors.getCheckStatus()),VisitorsEntity::getCheckStatus, visitors.getCheckStatus());
wrapper.orderByDesc(VisitorsEntity::getCreateTime);
@@ -17,5 +17,7 @@
<result property="updateTime" column="update_time"/>
<result property="delFlag" column="del_flag"/>
<result property="tenantId" column="tenant_id"/>
<result property="idCard" column="id_card"/>
<result property="faceUrl" column="face_url"/>
</resultMap>
</mapper>
@@ -118,8 +118,19 @@ sms:
content: "您好,您的验证码是{code},有效时间{date}分钟,请勿转发!"
params: [ "code", "date" ]
20658:
content: "您的访客预约申请已通过,请通过地址{url}查看详情!"
params: [ "url" ]
content: "您于{createTime}申请的访客预约现已通过审核!
▶ 访客姓名:{visitorName}
▶ 访客手机号:{visitorPhone}
▶ 到访时间:{visitorTime}
▶ 访问地点:{visitorLocal}
请及时登录系统查看详情:{url}"
params: [ "createTime", "visitorName", "visitorPhone", "visitorTime", "visitorLocal","url" ]
27694: # 验证码模板
content: "尊敬的{visitorName}先生/女士:
{yyName}邀请您于{visitorTime}访问{deptName},为保障您的顺利通行,请通过地址:{url}
查看详情。"
params: [ "visitorName", "yyName", "visitorTime", "deptName", "url" ]
settings:
default-ext-code: "123"
timeout-seconds: 300