pj访客接口

This commit is contained in:
zjf committed 2025-07-23 12:34:47 +08:00
1 parent cf667b8960
commit cd9b010c00
5 files changed
+84 -91

No files matched your search

@@ -24,6 +24,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpHeaders;
import org.springframework.security.access.prepost.PreAuthorize;
@@ -46,7 +47,7 @@ import cn.hutool.core.img.ImgUtil;
@RestController
@RequiredArgsConstructor
@RequestMapping("/app/visitor" )
@Tag(description = "visitorUser" , name = "访客用户管理" )
@Tag(description = "visitorUser" , name = "h5访客接口" )
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
@Inner(value = false)
public class AppVisitorController {
@@ -57,6 +58,9 @@ public class AppVisitorController {
private final VisitorsService visitorsService;
@Value("${visitor.qr-secret}")
private String visitorQrSecret;
@Operation(summary = "分页查询" , description = "分页查询" )
@GetMapping("/page" )
public R getCarInfoPage(@ParameterObject Page page, @ParameterObject CarInfoEntity carInfo) {
@@ -67,7 +71,7 @@ public class AppVisitorController {
@Operation(summary = "app新增访客" , description = "app新增访客" )
@SysLog("新增访客" )
@PostMapping("/app/save")
@PostMapping("/save")
@Idempotent(expireTime = 10, info = "请勿重复提交")
public R saveFK(@RequestBody VisitorsAppDTO visitors) {
return R.ok(visitorsService.vistorsSave(visitors));
@@ -82,7 +86,7 @@ public class AppVisitorController {
* @return R
*/
@Operation(summary = "通过token查询" , description = "通过token查询" )
@GetMapping("/app/get/visitorDetail" )
@GetMapping("/get/visitorDetail" )
public R<VisitorsAppVo> getByToken(@RequestParam("token") String token) {
return R.ok(visitorsService.getByToken(token));
@@ -121,7 +125,8 @@ public class AppVisitorController {
* @param token uuid生成的
* @param logoUrl 可选logo图片url
*/
@GetMapping("/app/visitorQr")
@GetMapping("/visitorQr")
@Operation(summary = "获取动态二维码" , description = "用于门卫/机器核验,5分钟刷新一次,预约未过期时一直可用" )
public R<Map<String, Object>> getVisitorQr(
@RequestParam("token") String token,
@RequestParam(value = "logoUrl", required = false) String logoUrl
@@ -130,10 +135,14 @@ public class AppVisitorController {
VisitorsAppVo visitor = visitorsService.getByToken(token);
if (visitor == null) return R.failed("无效token");
if (visitor.getVEndDate() == null || visitor.getVEndDate().isBefore(java.time.LocalDateTime.now())) return R.failed("预约已过期");
// 新增:只有审核通过才显示二维码
if (!TaskCheckStatusEnum.RESULT.getCode().equals(visitor.getCheckStatus())) {
return R.failed("预约未审核通过,无法获取二维码");
}
// 2. 生成动态部分(每5分钟变化一次)
long now5Min = System.currentTimeMillis() / (1000 * 60 * 5);
String secret = "your-visitor-qr-secret";
String secret = visitorQrSecret; // 从yml读取
String sign = cn.hutool.crypto.SecureUtil.hmacSha256(secret).digestHex(token + now5Min);
// 3. 二维码内容
@@ -158,17 +167,77 @@ public class AppVisitorController {
return R.ok(result);
}
@GetMapping("/app/sq/page")
@SysLog("获取我的新增记录" )
/**
* 核验二维码接口
* @param qrContent 二维码内容(token:now5min:sign)
* @return R
*/
@PostMapping("/verifyQr")
@Operation(summary = "核验二维码", description = "核验二维码合法性和有效性")
public R verifyQr(@RequestParam("qrContent") String qrContent) {
if (qrContent == null || !qrContent.contains(":")) {
return R.failed("二维码内容格式不正确");
}
String[] parts = qrContent.split(":");
if (parts.length != 3) {
return R.failed("二维码内容格式不正确");
}
String token = parts[0];
String now5Min = parts[1];
String sign = parts[2];
// 1. 校验签名
String expectSign = cn.hutool.crypto.SecureUtil.hmacSha256(visitorQrSecret).digestHex(token + now5Min);
if (!expectSign.equals(sign)) {
return R.failed("二维码签名无效");
}
// 2. 校验时间窗口(允许前后1个周期容忍,防止客户端时间误差)
long now = System.currentTimeMillis() / (1000 * 60 * 5);
long qrTime;
try {
qrTime = Long.parseLong(now5Min);
} catch (Exception e) {
return R.failed("二维码时间戳无效");
}
if (Math.abs(now - qrTime) > 1) {
return R.failed("二维码已过期,请刷新二维码");
}
// 3. 校验预约状态
VisitorsAppVo visitor = visitorsService.getByToken(token);
if (visitor == null) return R.failed("无效token");
if (visitor.getVEndDate() == null || visitor.getVEndDate().isBefore(java.time.LocalDateTime.now())) return R.failed("预约已过期");
if (!TaskCheckStatusEnum.RESULT.getCode().equals(visitor.getCheckStatus())) {
return R.failed("预约未审核通过");
}
// 校验通过,返回访客信息
return R.ok(visitor);
}
@GetMapping("/page")
@SysLog("我的访客预约记录" )
@Operation(summary = "我的访客预约记录" , description = "我的访客预约记录" )
public R getPage(@ParameterObject Page page, @ParameterObject VisitorsEntity visitors) {
return R.ok( visitorsService.getPageSQ(page, visitors));
}
@GetMapping("/app/cancelVisitor")
@GetMapping("/cancelVisitor")
@SysLog("取消访客预约" )
@Operation(summary = "取消访客预约" , description = "取消访客预约" )
public R cancelVisitor(@RequestParam("id")Long id) {
return R.ok( visitorsService.cancelVisitor(id));
}
/**
* 通过类型参数字典数据
* @param type 1 拜访原因
* @return
*/
@GetMapping("/getDictListByType")
@SysLog("根据字典类型查询数据" )
public R getDictListByType(@RequestParam("type")Long type) {
return visitorsService.getDictListByType(type);
}
}
@@ -22,8 +22,6 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import com.bsd.pjcloud.integrated.vo.lostandfound.LostAndFoundScreenVo;
import java.util.stream.Collectors;
import java.util.List;
import java.util.Objects;
@@ -151,27 +149,4 @@ public class LostAndFoundController {
return R.ok(lostAndFoundPageVoPage);
}
/**
* 大屏失物招领简要列表
* 只返回未认领的标题、发现地点、发现日期,最多10条
*/
@GetMapping("/screen/list")
@Operation(summary = "大屏失物招领简要列表", description = "大屏只展示标题、发现地点、发现日期")
public R<List<LostAndFoundScreenVo>> getScreenLostAndFoundList() {
LambdaQueryWrapper<LostAndFoundEntity> wrapper = Wrappers.lambdaQuery();
// 只查未认领(假设未认领状态为0,如有不同请调整)
wrapper.eq(LostAndFoundEntity::getStatus, "0");
wrapper.orderByDesc(LostAndFoundEntity::getCreateTime);
wrapper.last("limit 10");
List<LostAndFoundEntity> list = lostAndFoundService.list(wrapper);
List<LostAndFoundScreenVo> voList = list.stream().map(e -> {
LostAndFoundScreenVo vo = new LostAndFoundScreenVo();
vo.setTitle(e.getTitle());
vo.setFoundLocation(e.getLocation());
vo.setFoundDate(e.getDateFound() );
return vo;
}).collect(Collectors.toList());
return R.ok(voList);
}
}
@@ -153,11 +153,11 @@ public class VisitorsController {
public R getPageBF(@ParameterObject Page page, @ParameterObject VisitorsEntity visitors) {
return R.ok( visitorsService.getPageYY(page, visitors));
}
@GetMapping("/app/haveVisitor")
@SysLog("已到访" )
public R haveVisitor(@RequestParam("id")Long id) {
return R.ok( visitorsService.haveVisitor(id));
}
// @GetMapping("/app/haveVisitor")
// @SysLog("已到访" )
// public R haveVisitor(@RequestParam("id")Long id) {
// return R.ok( visitorsService.haveVisitor(id));
// }
@GetMapping("/app/updateCheckStatus")
@SysLog("更新状态" )
public R updateCheckStatus(@RequestParam("id")Long id,@RequestParam("checkStatus")String checkStatus) {
@@ -166,12 +166,4 @@ public class VisitorsController {
@GetMapping("/app/getDictListByType")
@SysLog("根据字典类型查询数据" )
public R getDictListByType(@RequestParam("type")Long type) {
return visitorsService.getDictListByType(type);
}
}
@@ -189,11 +189,7 @@ public class VisitorsServiceImpl extends ServiceImpl<VisitorsMapper, VisitorsEnt
visitorsEntityLambdaQueryWrapper.eq(VisitorsEntity::getToken,token);
VisitorsEntity visitors = baseMapper.selectOne(visitorsEntityLambdaQueryWrapper);
VisitorsAppVo bean = BeanUtils.toBean(visitors, VisitorsAppVo.class);
// 只有当审核状态为审核通过(check_status=2)时,才携带qrcode相关信息
if (!TaskCheckStatusEnum.RESULT.getCode().equals(visitors.getCheckStatus())) {
bean.setQrcode(null);
}
List<VisitorsCarEntity> visitorsCarEntities =
visitorsCarMapper.selectList(new LambdaQueryWrapper<VisitorsCarEntity>().eq(VisitorsCarEntity::getVisitorsId, visitors.getId()));
@@ -307,33 +303,6 @@ public class VisitorsServiceImpl extends ServiceImpl<VisitorsMapper, VisitorsEnt
VisitorsEntity visitors = new VisitorsEntity();
visitors.setId(id);
visitors.setCheckStatus(checkStatus);
//todo 电梯接口
//梯控
//审核通过
// if (checkStatus.equals(TaskCheckStatusEnum.RESULT.getCode())){
// VisitorAppointmentRequest visitorAppointmentRequest = new VisitorAppointmentRequest();
// //拜访人固定,安防系统中创建
// visitorAppointmentRequest.setReceptionistId("1");
//
// String startTime = dataVisitors.getVStartDate()
// .atZone(ZoneId.of("Asia/Shanghai"))
// .format(DateTimeFormatter.ISO_OFFSET_DATE_TIME);
// String endTime = dataVisitors.getVEndDate()
// .atZone(ZoneId.of("Asia/Shanghai"))
// .format(DateTimeFormatter.ISO_OFFSET_DATE_TIME);
// visitorAppointmentRequest.setVisitStartTime(startTime);
// visitorAppointmentRequest.setVisitEndTime(endTime);
// VisitorInfo visitorInfo = new VisitorInfo();
// visitorInfo.setVisitorName(dataVisitors.getName());
// //默认全部设置男
// visitorInfo.setGender(1);
// visitorInfo.setPhoneNo(dataVisitors.getMobile());
// //身份证默认为111
// visitorInfo.setCertificateType(111);
//// visitorInfo.setCertificateNo(dataVisitors.getIdCard());
//// visitorAppointmentRequest.setVisitorInfoList(Arrays.asList(visitorInfo));
//// remoterVisitorService.createVisitorAppointment(visitorAppointmentRequest);
// }
return baseMapper.updateById(visitors);
}
@@ -373,11 +342,6 @@ public class VisitorsServiceImpl extends ServiceImpl<VisitorsMapper, VisitorsEnt
visitors.setId(id);
visitors.setCheckStatus(TaskCheckStatusEnum.CANCEL.getCode());
String appointRecordId = dataVisitors.getAppointRecordId();
List<String> list = Arrays.asList(appointRecordId);
remoterVisitorService.cancelAppointments(list);
return baseMapper.updateById(visitors);
}
@@ -395,14 +359,6 @@ public class VisitorsServiceImpl extends ServiceImpl<VisitorsMapper, VisitorsEnt
VisitorsEntity visitors = new VisitorsEntity();
visitors.setId(id);
visitors.setCheckStatus(TaskCheckStatusEnum.HAVE_VISIT.getCode());
RegisterAppointmentRequest registerAppointmentRequest = new RegisterAppointmentRequest();
registerAppointmentRequest.setOrderId(dataVisitors.getOrderId());
String endTime = dataVisitors.getVEndDate()
.atZone(ZoneId.of("Asia/Shanghai"))
.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME);
registerAppointmentRequest.setVisitEndTime(endTime);
remoterVisitorService.registerAppointment(registerAppointmentRequest);
return baseMapper.updateById(visitors);
}
@@ -25,3 +25,4 @@ spring:
# url: jdbc:mysql://pjcloud-mysql:3306/pjcloudx_integrated?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8&allowMultiQueries=true
visitor:
jwt-secret: "u8Jk2n3Lk4pQ5r6T7s8V9w0X1y2Z3a4B"
qr-secret: "Qw8eR2t9Yp3sV6bN1mZ4xT7cL0vB5nH2" # 新增二维码secret,随机生成