调试修改海康访客-1

This commit is contained in:
zjf committed 2025-05-29 17:07:50 +08:00
1 parent 82fe8afa3e
commit 2ac305e479
14 files changed
+265 -23

No files matched your search

@@ -0,0 +1,20 @@
package com.bsd.pjcloud.common.core.util;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
public class TimeUtils {
public static String LocalDateTimeToISO8601(LocalDateTime localDateTime) {
// 2. 附加时区信息(如北京时间 UTC+8)
ZoneId zone = ZoneId.of("Asia/Shanghai");
ZonedDateTime zonedDateTime = localDateTime.atZone(zone);
// 3. 格式化为 ISO 8601
String isoTime = zonedDateTime.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME);
return isoTime;
}
}
@@ -185,4 +185,12 @@ public class VisitorsEntity extends Model<VisitorsEntity> {
@Schema(description="预约记录ID,可作为修改、取消预约的依据")
private String appointRecordId;
@Schema(description="二维码")
private String qrcode;
@Schema(description="验证码")
private String verificationCode;
}
@@ -59,4 +59,16 @@ public class VisitorsPeopleEntity extends Model<VisitorsPeopleEntity> {
@TableField(fill = FieldFill.INSERT)
@Schema(description="是否删除")
private String delFlag;
@Schema(description="访客记录唯一标识,用于已预约登记、访客签离等操作")
private String orderId;
@Schema(description="二维码")
private String qrcode;
@Schema(description="验证码")
private String verificationCode;
}
@@ -9,6 +9,7 @@ import com.bsd.pjcloud.admin.api.feign.RemoteUserService;
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.data.datascope.DataScope;
import com.bsd.pjcloud.common.security.util.SecurityUtils;
import com.bsd.pjcloud.flow.task.api.feign.RemoteFlowApiFlowService;
@@ -34,9 +35,12 @@ 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.RemoterVisitorService;
import com.bsd.pjcloud.thirdparty.dto.visitor.AppointmentInfo;
import com.bsd.pjcloud.thirdparty.dto.visitor.VisitorObjectResponse;
import com.bsd.pjcloud.thirdparty.dto.visitor.request.make.RegisterAppointmentRequest;
import com.bsd.pjcloud.thirdparty.dto.visitor.request.make.VisitorAppointmentRequest;
import com.bsd.pjcloud.thirdparty.dto.visitor.request.make.VisitorInfo;
import com.bsd.pjcloud.thirdparty.dto.visitor.response.make.AppointmentData;
import com.github.yulichang.toolkit.StrUtils;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
@@ -49,9 +53,11 @@ import org.springframework.util.CollectionUtils;
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.stream.Collectors;
/**
* 访客表
@@ -91,6 +97,17 @@ public class VisitorsServiceImpl extends ServiceImpl<VisitorsMapper, VisitorsEnt
// throw new ServiceException("流程实例启动失败: " + stringR.getMsg());
// }
// String processInstanceId = stringR.getData();
// 1.发起海康预约接口获取预约结果
List<VisitorInfo> visitorInfoList = new ArrayList<>();
VisitorInfo visitorInfo = new VisitorInfo();
VisitorAppointmentRequest visitorAppointmentRequest = new VisitorAppointmentRequest();
visitorAppointmentRequest.setVisitStartTime((TimeUtils.LocalDateTimeToISO8601(visitors.getVStartDate())));
visitorAppointmentRequest.setVisitEndTime(TimeUtils.LocalDateTimeToISO8601(visitors.getVEndDate()));
visitorInfo.setVisitorName(visitors.getName());
visitorInfo.setPhoneNo(visitors.getMobile());
visitorInfoList.add(visitorInfo);
Long userId = SecurityUtils.getUser().getId();
VisitorsEntity bean = BeanUtils.toBean(visitors, VisitorsEntity.class);
@@ -102,7 +119,55 @@ public class VisitorsServiceImpl extends ServiceImpl<VisitorsMapper, VisitorsEnt
String token = uniqueToken.replace("-", "");
bean.setToken(token);
bean.setUserId(userId);
List<VisitorsPeopleAppDTO> visitorsPeopleAppDTOList = visitors.getOtherPeople();
if (!CollectionUtils.isEmpty(visitorsPeopleAppDTOList)){
// List<VisitorsPeopleEntity> visitorsPeopleEntities = BeanUtils.toBean(visitorsPeopleAppDTOList, VisitorsPeopleEntity.class);
visitorsPeopleAppDTOList.forEach(i->{
VisitorInfo itemVisitorInfo = new VisitorInfo();
itemVisitorInfo.setVisitorName(i.getName());
itemVisitorInfo.setPhoneNo(i.getMobile());
visitorInfoList.add(itemVisitorInfo);
});
}
visitorAppointmentRequest.setVisitorInfoList(visitorInfoList);
VisitorObjectResponse<AppointmentData> visitorAppointment = remoterVisitorService.createVisitorAppointment(visitorAppointmentRequest);
AppointmentData appointmentData = visitorAppointment.getData();
String appointRecordId = appointmentData.getAppointRecordId();
bean.setAppointRecordId(appointRecordId);
List<AppointmentInfo> appointmentInfoList = appointmentData.getAppointmentInfoList();
AppointmentInfo mainAppointmentInfo = appointmentInfoList.get(0);
bean.setOrderId(mainAppointmentInfo.getOrderId());
bean.setQrcode(mainAppointmentInfo.getQRCode());
bean.setVerificationCode(mainAppointmentInfo.getVerificationCode());
//大于1说明还有访客,取出访客
List<AppointmentInfo> sxAppointmentInfos = appointmentInfoList.stream()
.skip(1)
.collect(Collectors.toList());
int insert = baseMapper.insert(bean);
if (!CollectionUtils.isEmpty(visitorsPeopleAppDTOList)){
List<VisitorsPeopleEntity> visitorsPeopleEntities = BeanUtils.toBean(visitorsPeopleAppDTOList, VisitorsPeopleEntity.class);
for (int i = 0; i < visitorsPeopleEntities.size(); i++){
VisitorsPeopleEntity visitorsPeopleEntity = visitorsPeopleEntities.get(i);
if (!CollectionUtils.isEmpty(sxAppointmentInfos)){
AppointmentInfo appointmentInfo = sxAppointmentInfos.get(i);
visitorsPeopleEntity.setOrderId(appointmentInfo.getOrderId());
visitorsPeopleEntity.setQrcode(appointmentInfo.getQRCode());
visitorsPeopleEntity.setVerificationCode(appointmentInfo.getVerificationCode());
}
visitorsPeopleEntity.setVisitorsId(bean.getId());
}
visitorsPeopleMapper.insert(visitorsPeopleEntities);
}
List<VisitorsCarAppDTO> visitorsCarAppDTOList = visitors.getCarList();
if (!CollectionUtils.isEmpty(visitorsCarAppDTOList)){
List<VisitorsCarEntity> visitorsCarEntities = BeanUtils.toBean(visitorsCarAppDTOList, VisitorsCarEntity.class);
@@ -111,14 +176,7 @@ public class VisitorsServiceImpl extends ServiceImpl<VisitorsMapper, VisitorsEnt
});
visitorsCarMapper.insert(visitorsCarEntities);
}
List<VisitorsPeopleAppDTO> visitorsPeopleAppDTOList = visitors.getOtherPeople();
if (!CollectionUtils.isEmpty(visitorsPeopleAppDTOList)){
List<VisitorsPeopleEntity> visitorsPeopleEntities = BeanUtils.toBean(visitorsPeopleAppDTOList, VisitorsPeopleEntity.class);
visitorsPeopleEntities.forEach(i->{
i.setVisitorsId(bean.getId());
});
visitorsPeopleMapper.insert(visitorsPeopleEntities);
}
return insert;
}
@@ -33,5 +33,7 @@
<result property="receiveId" column="receive_id"/>
<result property="orderId" column="order_id"/>
<result property="appointRecordId" column="appoint_record_id"/>
<result property="qrcode" column="qrcode"/>
<result property="verificationCode" column="verification_code"/>
</resultMap>
</mapper>
@@ -10,5 +10,8 @@
<result property="mobile" column="mobile"/>
<result property="createTime" column="create_time"/>
<result property="delFlag" column="del_flag"/>
<result property="orderId" column="order_id"/>
<result property="qrcode" column="qrcode"/>
<result property="verificationCode" column="verification_code"/>
</resultMap>
</mapper>
@@ -47,7 +47,7 @@ public interface RemoterVisitorService {
* @return
*/
@PostMapping("/visitors/appointment")
R<VisitorObjectResponse<AppointmentData>> createVisitorAppointment(@Valid @RequestBody VisitorAppointmentRequest request);
VisitorObjectResponse<AppointmentData> createVisitorAppointment(@Valid @RequestBody VisitorAppointmentRequest request);
/**
@@ -1,6 +1,7 @@
package com.bsd.pjcloud.thirdparty.dto.visitor;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
/**
@@ -23,6 +24,7 @@ public class AppointmentInfo {
* 动态二维码内容
* 需转换为二维码图片
*/
private String QRCode;
@@ -20,7 +20,7 @@ public class VisitorAppointmentRequest {
* 被访人唯一标识(必填)
* 通过人员查询接口获取的personId
*/
@NotBlank(message = "被访人ID不能为空")
// @NotBlank(message = "被访人ID不能为空")
private String receptionistId;
/**
@@ -31,10 +31,10 @@ public class VisitorInfo {
* 性别(必填)
* 1-男,2-女
*/
@NotNull(message = "性别不能为空")
// @NotNull(message = "性别不能为空")
@Min(value = 1, message = "性别值无效")
@Max(value = 2, message = "性别值无效")
private Integer gender;
private Integer gender=1;
/**
* 联系电话(必填)
@@ -17,6 +17,7 @@ public class HikvisionProperties {
private String appKey;
private String appSecret;
private String artemisPath;
private String personId;
private Map<String, String> apis = new HashMap<>();
// 初始化配置到SDK
@@ -6,6 +6,7 @@ import com.bsd.pjcloud.thirdparty.dto.visitor.VisitorObjectResponse;
import com.bsd.pjcloud.thirdparty.dto.visitor.request.make.CheckOutRequest;
import com.bsd.pjcloud.thirdparty.dto.visitor.request.make.RegisterAppointmentRequest;
import com.bsd.pjcloud.thirdparty.dto.visitor.request.make.VisitorAppointmentRequest;
import com.bsd.pjcloud.thirdparty.dto.visitor.request.make.VisitorInfo;
import com.bsd.pjcloud.thirdparty.dto.visitor.response.make.AppointmentData;
import com.bsd.pjcloud.thirdparty.dto.visitor.response.make.RegisterAppointmentResponse;
import com.bsd.pjcloud.thirdparty.service.VisitorService;
@@ -20,6 +21,7 @@ import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
@RestController
@@ -39,8 +41,24 @@ public class VisitorController {
*/
@Operation(summary = "访客预约" , description = "访客预约" )
@PostMapping("/appointment")
public R<VisitorObjectResponse<AppointmentData>> createVisitorAppointment(@Valid @RequestBody VisitorAppointmentRequest request) {
return R.ok(visitorService.createVisitorAppointment(request));
public VisitorObjectResponse<AppointmentData> createVisitorAppointment(@Valid @RequestBody VisitorAppointmentRequest request) {
// List<VisitorInfo> visitorInfoList = new ArrayList<>();
// for (int i = 0; i <2;i++){
// VisitorInfo visitorInfo = new VisitorInfo();
// visitorInfo.setVisitorName("张家富"+i);
// visitorInfo.setGender(1);
// visitorInfo.setPhoneNo("1846739904"+i);
// visitorInfoList.add(visitorInfo);
// request.setVisitorInfoList(visitorInfoList);
// }
return visitorService.createVisitorAppointment(request);
/**
* 如果已预约会返回如下
* "code": "0x0531401d",
* "msg": "time conflict",
*/
}
@@ -1,15 +1,15 @@
package com.bsd.pjcloud.thirdparty.service;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.*;
import com.alibaba.nacos.common.utils.CollectionUtils;
import com.bsd.pjcloud.common.core.exception.ServiceException;
import com.bsd.pjcloud.thirdparty.config.HikvisionProperties;
import com.bsd.pjcloud.thirdparty.dto.visitor.AppointmentInfo;
import com.bsd.pjcloud.thirdparty.dto.visitor.VisitorObjectResponse;
import com.bsd.pjcloud.thirdparty.dto.visitor.request.make.CheckOutRequest;
import com.bsd.pjcloud.thirdparty.dto.visitor.request.make.RegisterAppointmentRequest;
import com.bsd.pjcloud.thirdparty.dto.visitor.request.make.VisitorAppointmentRequest;
import com.bsd.pjcloud.thirdparty.dto.visitor.response.make.AppointmentData;
import com.bsd.pjcloud.thirdparty.dto.visitor.response.make.CancelAppointmentResponse;
import com.bsd.pjcloud.thirdparty.dto.visitor.response.make.CheckOutResponse;
import com.bsd.pjcloud.thirdparty.dto.visitor.response.make.RegisterAppointmentResponse;
@@ -21,6 +21,7 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@@ -39,9 +40,125 @@ public class VisitorService extends BaseHikvisionService {
* @return
*/
public VisitorObjectResponse createVisitorAppointment(VisitorAppointmentRequest request) {
request.setReceptionistId(properties.getPersonId());
JSONObject body = convertRequestToJSON(request);
String responseJson = sendPostRequest("visitor-appointment", body);
return JSON.parseObject(responseJson, VisitorObjectResponse.class);
// 添加日志便于调试
log.info("海康返回的原始JSON: {}", responseJson);
// VisitorObjectResponse visitorObjectResponse = JSON.parseObject(responseJson, VisitorObjectResponse.class);
VisitorObjectResponse visitorObjectResponse = parseVisitorResponse(responseJson);
// if (!visitorObjectResponse.getCode().equals("0") ) {
// throw new ServiceException("预约失败,请检查第三方接口");
// }
// 处理不同的错误码
String code = visitorObjectResponse.getCode();
if (code.equals("0")) {
// 成功情况
log.info("海康预约成功,预约记录ID: {}",
visitorObjectResponse.getData() != null ?
visitorObjectResponse.getData().getAppointRecordId() : "null");
} else if (code.equals("0x0531f002")) {
throw new ServiceException("预约时间不能小于当前日期");
} else if (code.equals("0x0531401d")) {
throw new ServiceException("当前时间段已有预约");
} else {
// 其他错误码
log.error("海康预约失败,错误码: {}, 错误信息: {}", code, visitorObjectResponse.getMsg());
throw new ServiceException("预约失败: " + visitorObjectResponse.getMsg());
}
return visitorObjectResponse;
}
/**
* 手动解析响应,处理字段映射问题和不同的data类型
*/
private VisitorObjectResponse parseVisitorResponse(String responseJson) {
try {
JSONObject jsonObject = JSON.parseObject(responseJson);
VisitorObjectResponse response = new VisitorObjectResponse();
response.setCode(jsonObject.getString("code"));
response.setMsg(jsonObject.getString("msg"));
// 处理data部分 - 关键:判断data的类型
Object dataObj = jsonObject.get("data");
if (dataObj != null) {
if (dataObj instanceof JSONObject) {
// 正常情况:data是对象
AppointmentData appointmentData = parseAppointmentData((JSONObject) dataObj);
response.setData(appointmentData);
} else if (dataObj instanceof JSONArray) {
// 异常情况:data是数组,比如 ["张"]
JSONArray dataArray = (JSONArray) dataObj;
log.warn("海康接口返回异常数据格式,data为数组: {}, 错误码: {}, 错误信息: {}",
dataArray.toJSONString(), response.getCode(), response.getMsg());
// 不直接抛异常,让上层的错误码判断逻辑来处理
// response.setData(null); // data设置为null,由错误码判断逻辑处理
} else if (dataObj instanceof String) {
// data是字符串的情况
log.warn("海康接口返回异常数据格式,data为字符串: {}, 错误码: {}, 错误信息: {}",
dataObj.toString(), response.getCode(), response.getMsg());
// 不直接抛异常,让上层的错误码判断逻辑来处理
// response.setData(null);
} else {
// 其他未知类型
log.warn("海康接口返回未知的data类型: {}, 错误码: {}, 完整响应: {}",
dataObj.getClass().getSimpleName(), response.getCode(), responseJson);
// 不直接抛异常,让上层的错误码判断逻辑来处理
// response.setData(null);
}
}
return response;
} catch (JSONException e) {
log.error("解析海康响应JSON失败: {}", responseJson, e);
throw new ServiceException("海康接口响应解析失败");
}
}
/**
* 解析正常的预约数据
*/
private AppointmentData parseAppointmentData(JSONObject dataObj) {
AppointmentData appointmentData = new AppointmentData();
appointmentData.setAppointRecordId(dataObj.getString("appointRecordId"));
// 处理appointmentInfoList
JSONArray appointmentInfoArray = dataObj.getJSONArray("appointmentInfoList");
if (appointmentInfoArray != null) {
List<AppointmentInfo> appointmentInfoList = new ArrayList<>();
for (int i = 0; i < appointmentInfoArray.size(); i++) {
JSONObject infoObj = appointmentInfoArray.getJSONObject(i);
AppointmentInfo info = new AppointmentInfo();
info.setVisitorName(infoObj.getString("visitorName"));
info.setReceptionistId(infoObj.getString("receptionistId"));
info.setReceptionistName(infoObj.getString("receptionistName"));
info.setVerificationCode(infoObj.getString("verificationCode"));
info.setOrderId(infoObj.getString("orderId"));
// info.setVisitorInfoId(infoObj.getString("visitorInfoId"));
info.setSvrIndexCode(infoObj.getString("svrIndexCode"));
info.setPicUri(infoObj.getString("picUri"));
// 关键:手动映射QRCode字段
info.setQRCode(infoObj.getString("QRCode"));
appointmentInfoList.add(info);
}
appointmentData.setAppointmentInfoList(appointmentInfoList);
}
return appointmentData;
}
private JSONObject convertRequestToJSON(VisitorAppointmentRequest request) {
@@ -124,14 +124,15 @@ LianTongSMS:
hikvision:
host: 127.0.0.1:443
app-key: 29180881
app-secret: XO0wCAYGi4KV70ybjznx
host: 60.12.184.22:1443
app-key: 21470882
app-secret: lYRm5YwBp90qdg5eb0p6
artemis-path: /artemis
person-id: 639f8b57bb6c438e884ae48c5cd535c8
apis:
person-list: /api/resource/v2/person/personList # 新增人员列表接口
visitor-appointment: /api/visitor/v2/appointment # 新增访客预约接口
person-detail: /api/resource/v1/person/condition/personInfo # 新增人员详情接口
cancel-appointment: /api/visitor/v1/appointment/cancel # 新增取消预约接口
register-appointment: /api/visitor/v1/order/register # 新增登记接口
visitor-checkout: /api/visitor/v1/visitor/out # 新增签离接口
visitor-checkout: /api/visitor/v1/visitor/out # 新增签离接口