From 6d15f93642f006e8562a82154f05d3d6676e7bb9 Mon Sep 17 00:00:00 2001 From: zjf <1799650030@qq.com> Date: Tue, 29 Apr 2025 16:54:34 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B5=B7=E5=BA=B7=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/feign/RemoterVisitorService.java | 76 ++++++++ .../{response/make => }/AppointmentInfo.java | 10 +- .../dto/visitor/ListDetailData.java | 13 ++ .../{request/person => }/PersonInfo.java | 2 +- .../dto/visitor/VisitorObjectResponse.java | 2 +- .../make/CancelAppointmentRequest.java | 22 +++ .../visitor/request/make/CheckOutRequest.java | 16 ++ .../make/RegisterAppointmentRequest.java | 63 +++++++ .../request/person/PersonDetailRequest.java | 30 ++++ .../response/make/AppointmentData.java | 1 + .../make/CancelAppointmentResponse.java | 23 +++ .../response/make/CheckOutResponse.java | 17 ++ .../make/RegisterAppointmentResponse.java | 33 ++++ .../response/person/PersonDetailResponse.java | 86 +++++++++ .../controller/VisitorController.java | 83 +++++++++ .../thirdparty/service/HikvisionService.java | 2 +- .../thirdparty/service/PersonService.java | 79 +++++++- .../thirdparty/service/VisitorService.java | 170 ++++++++++++++++++ .../src/main/resources/application.yml | 7 +- 19 files changed, 727 insertions(+), 8 deletions(-) create mode 100644 pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/api/feign/RemoterVisitorService.java rename pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/dto/visitor/{response/make => }/AppointmentInfo.java (61%) create mode 100644 pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/dto/visitor/ListDetailData.java rename pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/dto/visitor/{request/person => }/PersonInfo.java (92%) create mode 100644 pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/dto/visitor/request/make/CancelAppointmentRequest.java create mode 100644 pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/dto/visitor/request/make/CheckOutRequest.java create mode 100644 pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/dto/visitor/request/make/RegisterAppointmentRequest.java create mode 100644 pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/dto/visitor/request/person/PersonDetailRequest.java create mode 100644 pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/dto/visitor/response/make/CancelAppointmentResponse.java create mode 100644 pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/dto/visitor/response/make/CheckOutResponse.java create mode 100644 pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/dto/visitor/response/make/RegisterAppointmentResponse.java create mode 100644 pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/dto/visitor/response/person/PersonDetailResponse.java create mode 100644 pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/java/com/bsd/pjcloud/thirdparty/controller/VisitorController.java diff --git a/pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/api/feign/RemoterVisitorService.java b/pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/api/feign/RemoterVisitorService.java new file mode 100644 index 000000000..d07109087 --- /dev/null +++ b/pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/api/feign/RemoterVisitorService.java @@ -0,0 +1,76 @@ +/* + * + * Copyright (c) 2018-2025, pjcloud All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * Neither the name of the pig4cloud.com developer nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * Author: pjcloud + * + */ + +package com.bsd.pjcloud.thirdparty.api.feign; + +import com.bsd.pjcloud.common.core.constant.ServiceNameConstants; +import com.bsd.pjcloud.common.core.util.R; +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.RegisterAppointmentResponse; +import io.swagger.v3.oas.annotations.Operation; +import jakarta.validation.Valid; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestParam; + +import java.util.List; +import java.util.Map; + +@FeignClient(contextId = "remoterVisitorService", value = ServiceNameConstants.THIRDPARTY_SERVICE) +public interface RemoterVisitorService { + + + /** + * 访客预约预约 + * @param request + * @return + */ + @PostMapping("/visitors/appointment") + R> createVisitorAppointment(@Valid @RequestBody VisitorAppointmentRequest request); + + + /** + * 取消预约 + * @param recordIds + * @return + */ + @PostMapping("/cancel") + public R cancelAppointments(@RequestBody List recordIds); + + /** + * 预约登记 + * @param request + * @return + */ + @PostMapping("/register") + public R registerAppointment(@Valid @RequestBody RegisterAppointmentRequest request); + + /** + * 访客签离 + * @param request + * @return + */ + @PostMapping("/checkout") + public R checkOut(@Valid @RequestBody CheckOutRequest request); +} diff --git a/pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/dto/visitor/response/make/AppointmentInfo.java b/pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/dto/visitor/AppointmentInfo.java similarity index 61% rename from pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/dto/visitor/response/make/AppointmentInfo.java rename to pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/dto/visitor/AppointmentInfo.java index 245b73622..b61e9ef5e 100644 --- a/pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/dto/visitor/response/make/AppointmentInfo.java +++ b/pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/dto/visitor/AppointmentInfo.java @@ -1,4 +1,4 @@ -package com.bsd.pjcloud.thirdparty.dto.visitor.response.make; +package com.bsd.pjcloud.thirdparty.dto.visitor; import lombok.Data; @@ -25,4 +25,12 @@ public class AppointmentInfo { */ private String QRCode; + + + private String receptionistName; + private String verificationCode; + private String orderId; + private String picUri; + private String svrIndexCode; + } \ No newline at end of file diff --git a/pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/dto/visitor/ListDetailData.java b/pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/dto/visitor/ListDetailData.java new file mode 100644 index 000000000..c0c4c9780 --- /dev/null +++ b/pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/dto/visitor/ListDetailData.java @@ -0,0 +1,13 @@ +package com.bsd.pjcloud.thirdparty.dto.visitor; + + +import com.bsd.pjcloud.thirdparty.dto.visitor.response.person.PersonDetailResponse; +import lombok.Data; + +import java.util.List; + +@Data +public class ListDetailData { + private Integer total; + private List list; +} diff --git a/pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/dto/visitor/request/person/PersonInfo.java b/pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/dto/visitor/PersonInfo.java similarity index 92% rename from pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/dto/visitor/request/person/PersonInfo.java rename to pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/dto/visitor/PersonInfo.java index c789bbf84..622723c72 100644 --- a/pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/dto/visitor/request/person/PersonInfo.java +++ b/pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/dto/visitor/PersonInfo.java @@ -1,4 +1,4 @@ -package com.bsd.pjcloud.thirdparty.dto.visitor.request.person; +package com.bsd.pjcloud.thirdparty.dto.visitor; import java.time.LocalDateTime; diff --git a/pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/dto/visitor/VisitorObjectResponse.java b/pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/dto/visitor/VisitorObjectResponse.java index 1399ac03e..5c2831987 100644 --- a/pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/dto/visitor/VisitorObjectResponse.java +++ b/pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/dto/visitor/VisitorObjectResponse.java @@ -8,7 +8,7 @@ import org.apache.poi.ss.formula.functions.T; * 访客预约响应主类 */ @Data -public class VisitorObjectResponse { +public class VisitorObjectResponse { /** * 返回码 diff --git a/pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/dto/visitor/request/make/CancelAppointmentRequest.java b/pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/dto/visitor/request/make/CancelAppointmentRequest.java new file mode 100644 index 000000000..8d7100f30 --- /dev/null +++ b/pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/dto/visitor/request/make/CancelAppointmentRequest.java @@ -0,0 +1,22 @@ +package com.bsd.pjcloud.thirdparty.dto.visitor.request.make; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.Size; +import lombok.Data; + +import java.util.List; + +@Data +@Schema(description = "取消预约请求参数") +public class CancelAppointmentRequest { +/** + * 预约记录ID列表(必填) + * 最多支持批量取消100条记录 + */ + @NotEmpty(message = "预约记录ID不能为空") + @Size(max = 100, message = "单次最多取消100条预约") + private List<@NotBlank String> appointRecordIds; +} + diff --git a/pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/dto/visitor/request/make/CheckOutRequest.java b/pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/dto/visitor/request/make/CheckOutRequest.java new file mode 100644 index 000000000..16b24e95b --- /dev/null +++ b/pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/dto/visitor/request/make/CheckOutRequest.java @@ -0,0 +1,16 @@ +package com.bsd.pjcloud.thirdparty.dto.visitor.request.make; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +@Data +@Schema(description = "访客签离请求参数") +public class CheckOutRequest { + /** + * 访客记录ID(必填) + * 从查询接口获取的orderId + */ + @NotBlank(message = "访客记录ID不能为空") + private String orderId; +} diff --git a/pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/dto/visitor/request/make/RegisterAppointmentRequest.java b/pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/dto/visitor/request/make/RegisterAppointmentRequest.java new file mode 100644 index 000000000..932632d99 --- /dev/null +++ b/pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/dto/visitor/request/make/RegisterAppointmentRequest.java @@ -0,0 +1,63 @@ +package com.bsd.pjcloud.thirdparty.dto.visitor.request.make; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.*; +import lombok.Data; + +import java.time.LocalDateTime; +import java.util.List; + +@Data +@Schema(description = "预约登记请求参数") +public class RegisterAppointmentRequest { + /** + * 访客记录ID(必填) + * 从查询预约记录接口获取 + */ + @NotBlank(message = "访客记录ID不能为空") + private String orderId; + + /** + * 预计离开时间(必填) + * ISO8601格式,需晚于当前时间 + */ + @NotNull + @Future(message = "离开时间必须是将来的时间") + @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ssXXX") + private LocalDateTime visitEndTime; + + /** + * 门禁卡号(可选) + */ + private String cardNo; + + /** + * 权限配置(可选) + */ + private VisitorPermissionSet visitorPermissionSet; + + /** + * 是否使用预约权限(默认0) + * 0-使用登记权限,1-权限合并 + */ + @Pattern(regexp = "[01]", message = "权限模式参数错误") + private String isUseOrderAuth = "0"; + + @Data + @Schema(description = "访客权限配置") + public static class VisitorPermissionSet { + /** + * 权限组ID列表 + */ + @Size(max = 10, message = "最多选择10个权限组") + private List privilegeGroupIds; + + /** + * 是否使用默认权限组 + * 1-使用,其他-不使用 + */ + @Pattern(regexp = "1|.*", message = "默认权限组标识错误") + private String defaultPrivilegeGroupFlag; + } +} diff --git a/pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/dto/visitor/request/person/PersonDetailRequest.java b/pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/dto/visitor/request/person/PersonDetailRequest.java new file mode 100644 index 000000000..a972fbab5 --- /dev/null +++ b/pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/dto/visitor/request/person/PersonDetailRequest.java @@ -0,0 +1,30 @@ +package com.bsd.pjcloud.thirdparty.dto.visitor.request.person; + +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import lombok.Data; + +import java.util.List; + +@Data +public class PersonDetailRequest { + /** + * 查询参数类型(必填) + * certificateNo-证件号码 | personId-人员ID | phoneNo-手机号 | jobNo-工号 + */ + @NotNull(message = "查询类型不能为空") + private ParamName paramName; + + /** + * 查询值列表(必填) + * 最大支持1000个查询值 + */ + @NotEmpty(message = "查询值不能为空") + @Size(max = 1000, message = "最多支持1000个查询值") + private List paramValue; + + public enum ParamName { + certificateNo, personId, phoneNo, jobNo + } +} \ No newline at end of file diff --git a/pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/dto/visitor/response/make/AppointmentData.java b/pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/dto/visitor/response/make/AppointmentData.java index 9f9d78f31..602aea0fb 100644 --- a/pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/dto/visitor/response/make/AppointmentData.java +++ b/pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/dto/visitor/response/make/AppointmentData.java @@ -1,6 +1,7 @@ package com.bsd.pjcloud.thirdparty.dto.visitor.response.make; +import com.bsd.pjcloud.thirdparty.dto.visitor.AppointmentInfo; import lombok.Data; import java.util.List; diff --git a/pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/dto/visitor/response/make/CancelAppointmentResponse.java b/pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/dto/visitor/response/make/CancelAppointmentResponse.java new file mode 100644 index 000000000..d6b7c4433 --- /dev/null +++ b/pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/dto/visitor/response/make/CancelAppointmentResponse.java @@ -0,0 +1,23 @@ +package com.bsd.pjcloud.thirdparty.dto.visitor.response.make; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +@Schema(description = "取消预约响应结果") +public class CancelAppointmentResponse { + /** + * ("返回码 0-成功") + */ + private String code; + + /** + * "操作结果描述 + */ + private String msg; + + /** + * ("保留字段(始终为null)") + */ + private Object data; // 根据接口文档返回null +} \ No newline at end of file diff --git a/pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/dto/visitor/response/make/CheckOutResponse.java b/pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/dto/visitor/response/make/CheckOutResponse.java new file mode 100644 index 000000000..d1baea11a --- /dev/null +++ b/pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/dto/visitor/response/make/CheckOutResponse.java @@ -0,0 +1,17 @@ +package com.bsd.pjcloud.thirdparty.dto.visitor.response.make; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +@Schema(description = "访客签离响应结果") +public class CheckOutResponse { + @Schema(description = "返回码 0-成功") + private String code; + + @Schema(description = "操作结果描述") + private String msg; + + @Schema(description = "保留字段(始终为null)") + private Object data; // 根据接口文档返回null +} \ No newline at end of file diff --git a/pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/dto/visitor/response/make/RegisterAppointmentResponse.java b/pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/dto/visitor/response/make/RegisterAppointmentResponse.java new file mode 100644 index 000000000..6d2db12dd --- /dev/null +++ b/pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/dto/visitor/response/make/RegisterAppointmentResponse.java @@ -0,0 +1,33 @@ +package com.bsd.pjcloud.thirdparty.dto.visitor.response.make; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +@Schema(description = "预约登记响应结果") +public class RegisterAppointmentResponse { + @Schema(description = "返回码 0-成功") + private String code; + + @Schema(description = "操作结果描述") + private String msg; + + @Schema(description = "登记凭证信息") + private RegisterData data; + + @Data + @Schema(description = "登记凭证数据") + public static class RegisterData { + @Schema(description = "动态二维码内容") + private String QRCode; + + @Schema(description = "访客记录唯一标识") + private String orderId; + + @Schema(description = "图片服务索引码") + private String svrIndexCode; + + @Schema(description = "头像访问路径") + private String picUri; + } +} \ No newline at end of file diff --git a/pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/dto/visitor/response/person/PersonDetailResponse.java b/pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/dto/visitor/response/person/PersonDetailResponse.java new file mode 100644 index 000000000..844bbda81 --- /dev/null +++ b/pjcloud-thirdparty/pjcloud-thirdparty-api/src/main/java/com/bsd/pjcloud/thirdparty/dto/visitor/response/person/PersonDetailResponse.java @@ -0,0 +1,86 @@ +package com.bsd.pjcloud.thirdparty.dto.visitor.response.person; + +import lombok.Data; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Map; + +@Data +public class PersonDetailResponse { + private String code; + private String msg; + private PersonDetailData data; + + @Data + public static class PersonDetailData { + private Integer total; + private List list; + } + + @Data + public static class PersonDetail { + // 基础字段 + private String personId; + private String personName; + private Integer gender; + private String orgPath; + private String orgPathName; + private String orgIndexCode; + private Integer certificateType; + private String certificateNo; + private String jobNo; + private String birthday; + private String phoneNo; + private String address; + + // 教育信息 + private Integer education; + private String academy; + private String profession; + private String studentId; + private String stuGrade; + private String stuClass; + + // 工作信息 + private String company; + private String employeePost; + private String postType; + private String staffProperty; + + // 个人信息 + private Integer age; + private String lastName; + private String givenName; + private Integer nation; + private String birthplace; + private String nationality; + private Integer marriaged; + private String politicalStatus; + private String censusRegister; + + // 证件信息 + private String certIssuer; + private String certAddr; + private String certExpireTime; + + // 系统信息 + private Integer status; + private LocalDateTime createTime; + private LocalDateTime updateTime; + + // 照片信息 + private List personPhoto; + + // 扩展字段(兼容新增属性) + private Map extendedProperties; + + @Data + public static class PersonPhoto { + private String personPhotoIndexCode; + private String picUri; + private String serverIndexCode; + private String personId; + } + } +} \ No newline at end of file diff --git a/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/java/com/bsd/pjcloud/thirdparty/controller/VisitorController.java b/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/java/com/bsd/pjcloud/thirdparty/controller/VisitorController.java new file mode 100644 index 000000000..bb655320f --- /dev/null +++ b/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/java/com/bsd/pjcloud/thirdparty/controller/VisitorController.java @@ -0,0 +1,83 @@ +package com.bsd.pjcloud.thirdparty.controller; + + +import com.bsd.pjcloud.common.core.util.R; +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.RegisterAppointmentResponse; +import com.bsd.pjcloud.thirdparty.service.VisitorService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpHeaders; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +@RestController +@RequestMapping("/visitors") +@RequiredArgsConstructor +@Tag(description = "thirdPartyUser" , name = "浙政钉用户表管理" ) +@SecurityRequirement(name = HttpHeaders.AUTHORIZATION) +public class VisitorController { + + private final VisitorService visitorService; + + + /** + * 访客预约预约 + * @param request + * @return + */ + @Operation(summary = "访客预约" , description = "访客预约" ) + @PostMapping("/appointment") + public R> createVisitorAppointment(@Valid @RequestBody VisitorAppointmentRequest request) { + return R.ok(visitorService.createVisitorAppointment(request)); + } + + + /** + * 取消预约 + * @param recordIds + * @return + */ + @PostMapping("/cancel") + public R cancelAppointments(@RequestBody List recordIds) { + visitorService.cancelAppointments(recordIds); + return R.ok(); + } + + /** + * 预约登记 + * @param request + * @return + */ + @PostMapping("/register") + public R registerAppointment(@Valid @RequestBody RegisterAppointmentRequest request) { + RegisterAppointmentResponse registerAppointmentResponse = visitorService.registerAppointment(request); + return R.ok(registerAppointmentResponse); + } + + /** + * 访客签离 + * @param request + * @return + */ + @PostMapping("/checkout") + public R checkOut(@Valid @RequestBody CheckOutRequest request) { + visitorService.checkOutVisitor(request); + return R.ok(); + } + + + + +} \ No newline at end of file diff --git a/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/java/com/bsd/pjcloud/thirdparty/service/HikvisionService.java b/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/java/com/bsd/pjcloud/thirdparty/service/HikvisionService.java index 811d90b0c..ea3c3cb15 100644 --- a/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/java/com/bsd/pjcloud/thirdparty/service/HikvisionService.java +++ b/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/java/com/bsd/pjcloud/thirdparty/service/HikvisionService.java @@ -9,7 +9,7 @@ import com.bsd.pjcloud.thirdparty.dto.visitor.PageListRequest; import com.bsd.pjcloud.thirdparty.dto.visitor.VisitorResponse; import com.bsd.pjcloud.thirdparty.dto.visitor.request.make.VisitorAppointmentRequest; import com.bsd.pjcloud.thirdparty.dto.visitor.VisitorObjectResponse; -import com.bsd.pjcloud.thirdparty.dto.visitor.request.person.PersonInfo; +import com.bsd.pjcloud.thirdparty.dto.visitor.PersonInfo; import com.bsd.pjcloud.thirdparty.exception.HikvisionException; import com.hikvision.artemis.sdk.ArtemisHttpUtil; import lombok.RequiredArgsConstructor; diff --git a/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/java/com/bsd/pjcloud/thirdparty/service/PersonService.java b/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/java/com/bsd/pjcloud/thirdparty/service/PersonService.java index a969975de..735203ea5 100644 --- a/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/java/com/bsd/pjcloud/thirdparty/service/PersonService.java +++ b/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/java/com/bsd/pjcloud/thirdparty/service/PersonService.java @@ -1,14 +1,22 @@ package com.bsd.pjcloud.thirdparty.service; +import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.TypeReference; import com.bsd.pjcloud.thirdparty.config.HikvisionProperties; import com.bsd.pjcloud.thirdparty.dto.visitor.PageListRequest; import com.bsd.pjcloud.thirdparty.dto.visitor.VisitorResponse; -import com.bsd.pjcloud.thirdparty.dto.visitor.request.person.PersonInfo; +import com.bsd.pjcloud.thirdparty.dto.visitor.PersonInfo; +import com.bsd.pjcloud.thirdparty.dto.visitor.request.person.PersonDetailRequest; +import com.bsd.pjcloud.thirdparty.dto.visitor.response.person.PersonDetailResponse; import com.bsd.pjcloud.thirdparty.exception.HikvisionException; +import com.hikvision.artemis.sdk.ArtemisHttpUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; + +import java.util.Collections; +import java.util.Map; @Service @Slf4j @@ -17,6 +25,12 @@ public class PersonService extends BaseHikvisionService { super(properties); } + + /** + * 获取人员分页列表 + * @param request + * @return + */ public VisitorResponse getPersonList(PageListRequest request) { try { validatePageRequest(request); @@ -26,7 +40,8 @@ public class PersonService extends BaseHikvisionService { body.put("pageSize", request.getPageSize()); String response = sendPostRequest("person-list", body); - return parseResponse(response, new TypeReference>() {}); + return parseResponse(response, new TypeReference>() { + }); } catch (IllegalArgumentException e) { throw new HikvisionException("PARAM_ERROR", e.getMessage()); } @@ -40,4 +55,64 @@ public class PersonService extends BaseHikvisionService { throw new IllegalArgumentException("分页大小需在1-1000之间"); } } + + + /** + * 根据人员唯一字段获取人员详细信息 + */ + public PersonDetailResponse getPersonDetails(PersonDetailRequest request) { + // 1. 构建API路径 + String apiPath = properties.getArtemisPath() + properties.getApis().get("person-detail"); + + // 2. 构建请求体 + JSONObject body = new JSONObject(); + body.put("paramName", request.getParamName().name()); + body.put("paramValue", request.getParamValue()); + + // 3. 发送请求 + String responseJson = ArtemisHttpUtil.doPostStringArtemis( + Map.of("https://", apiPath), + body.toJSONString(), + null, null, "application/json", null + ); + + // 4. 处理响应 + return parseResponse(responseJson); + } + + /** + * 便捷查询方法示例 + */ + public PersonDetailResponse.PersonDetail getByCertificateNo(String certificateNo) { + PersonDetailRequest request = new PersonDetailRequest(); + request.setParamName(PersonDetailRequest.ParamName.certificateNo); + request.setParamValue(Collections.singletonList(certificateNo)); + return getFirstPerson(request); + } + + public PersonDetailResponse.PersonDetail getByPersonId(String personId) { + PersonDetailRequest request = new PersonDetailRequest(); + request.setParamName(PersonDetailRequest.ParamName.personId); + request.setParamValue(Collections.singletonList(personId)); + return getFirstPerson(request); + } + + private PersonDetailResponse.PersonDetail getFirstPerson(PersonDetailRequest request) { + PersonDetailResponse response = getPersonDetails(request); + if (response.getData() != null && + !CollectionUtils.isEmpty(response.getData().getList())) { + return response.getData().getList().get(0); + } + return null; + } + + private PersonDetailResponse parseResponse(String json) { + PersonDetailResponse response = JSON.parseObject(json, PersonDetailResponse.class); + if (!"0".equals(response.getCode())) { + throw new HikvisionException(response.getCode(), response.getMsg()); + } + return response; + } + + } \ No newline at end of file diff --git a/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/java/com/bsd/pjcloud/thirdparty/service/VisitorService.java b/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/java/com/bsd/pjcloud/thirdparty/service/VisitorService.java index 16fa8521b..5df65e4a1 100644 --- a/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/java/com/bsd/pjcloud/thirdparty/service/VisitorService.java +++ b/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/java/com/bsd/pjcloud/thirdparty/service/VisitorService.java @@ -1,14 +1,28 @@ 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.nacos.common.utils.CollectionUtils; import com.bsd.pjcloud.thirdparty.config.HikvisionProperties; 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.CancelAppointmentResponse; +import com.bsd.pjcloud.thirdparty.dto.visitor.response.make.CheckOutResponse; +import com.bsd.pjcloud.thirdparty.dto.visitor.response.make.RegisterAppointmentResponse; +import com.bsd.pjcloud.thirdparty.exception.HikvisionException; +import com.hikvision.artemis.sdk.ArtemisHttpUtil; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import java.time.format.DateTimeFormatter; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; @Service @@ -18,6 +32,12 @@ public class VisitorService extends BaseHikvisionService { super(properties); } + + /** + * 预约 + * @param request + * @return + */ public VisitorObjectResponse createVisitorAppointment(VisitorAppointmentRequest request) { JSONObject body = convertRequestToJSON(request); String responseJson = sendPostRequest("visitor-appointment", body); @@ -69,4 +89,154 @@ public class VisitorService extends BaseHikvisionService { json.put("visitorInfoList", visitorList); return json; } + + + /** + * 批量取消访客预约 + * + * @param recordIds 预约记录ID列表 + * @return 操作结果 + */ + @Transactional + public void cancelAppointments(List recordIds) { + // 1. 参数校验 + if (CollectionUtils.isEmpty(recordIds)) { + throw new IllegalArgumentException("预约记录ID不能为空"); + } + + // 2. 构建请求路径 + String apiPath = properties.getArtemisPath() + + properties.getApis().get("cancel-appointment"); + + // 3. 构建请求体 + JSONObject requestBody = new JSONObject(); + requestBody.put("appointRecordIds", recordIds); + + // 4. 发送请求 + String response = ArtemisHttpUtil.doPostStringArtemis( + Map.of("https://", apiPath), + requestBody.toJSONString(), + null, null, "application/json", null + ); + + // 5. 处理响应 + CancelAppointmentResponse res = parseResponse(response); + if (!"0".equals(res.getCode())) { + throw new HikvisionException(res.getCode(), res.getMsg()); + } + } + + private CancelAppointmentResponse parseResponse(String json) { + try { + return JSON.parseObject(json, CancelAppointmentResponse.class); + } catch (JSONException e) { + throw new HikvisionException("PARSE_ERROR", "响应解析失败"); + } + } + + + + + /** + * 执行预约登记 + */ + @Transactional + public RegisterAppointmentResponse registerAppointment(RegisterAppointmentRequest request) { + // 1. 构建API路径 + String apiPath = properties.getArtemisPath() + + properties.getApis().get("register-appointment"); + + // 2. 转换请求体 + JSONObject body = convertRequestToJSON(request); + + // 3. 发送请求 + String responseJson = ArtemisHttpUtil.doPostStringArtemis( + Map.of("https://", apiPath), + body.toJSONString(), + null, null, "application/json", null + ); + + // 4. 处理响应 + return registerAppointmentParseResponse(responseJson); + } + + private JSONObject convertRequestToJSON(RegisterAppointmentRequest request) { + JSONObject json = new JSONObject(); + json.put("orderId", request.getOrderId()); + json.put("visitEndTime", request.getVisitEndTime() + .format(DateTimeFormatter.ISO_OFFSET_DATE_TIME)); + + if (StringUtils.isNotBlank(request.getCardNo())) { + json.put("cardNo", request.getCardNo()); + } + + if (request.getVisitorPermissionSet() != null) { + JSONObject permission = new JSONObject(); + RegisterAppointmentRequest.VisitorPermissionSet ps = request.getVisitorPermissionSet(); + + if (ps.getPrivilegeGroupIds() != null) { + permission.put("privilegeGroupIds", ps.getPrivilegeGroupIds()); + } + if (StringUtils.isNotBlank(ps.getDefaultPrivilegeGroupFlag())) { + permission.put("defaultPrivilegeGroupFlag", + ps.getDefaultPrivilegeGroupFlag()); + } + json.put("visitorPermissionSet", permission); + } + + json.put("isUseOrderAuth", request.getIsUseOrderAuth()); + return json; + } + + private RegisterAppointmentResponse registerAppointmentParseResponse(String json) { + RegisterAppointmentResponse response = JSON.parseObject(json, + new TypeReference() {}); + + if (!"0".equals(response.getCode())) { + throw new HikvisionException(response.getCode(), response.getMsg()); + } + return response; + } + + + + /** + * 执行访客签离 + */ + @Transactional + public void checkOutVisitor(CheckOutRequest request) { + + // 2. 构建API路径 + String apiPath = properties.getArtemisPath() + + properties.getApis().get("visitor-checkout"); + + // 3. 构建请求体 + JSONObject body = new JSONObject(); + body.put("orderId", request.getOrderId()); + + // 4. 发送请求 + String responseJson = ArtemisHttpUtil.doPostStringArtemis( + Map.of("https://", apiPath), + body.toJSONString(), + null, null, "application/json", null + ); + + // 5. 处理响应 + CheckOutResponse response = checkOutParseResponse(responseJson); + if (!"0".equals(response.getCode())) { + throw new HikvisionException(response.getCode(), response.getMsg()); + } + + } + + private CheckOutResponse checkOutParseResponse(String json) { + try { + return JSON.parseObject(json, CheckOutResponse.class); + } catch (JSONException e) { + throw new HikvisionException("PARSE_ERROR", "响应解析失败"); + } + } + + + } \ No newline at end of file diff --git a/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/resources/application.yml b/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/resources/application.yml index afcd0ff6c..9032bee55 100644 --- a/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/resources/application.yml +++ b/pjcloud-thirdparty/pjcloud-thirdparty-biz/src/main/resources/application.yml @@ -129,6 +129,9 @@ hikvision: app-secret: XO0wCAYGi4KV70ybjznx artemis-path: /artemis apis: - preview-urls: /api/video/v1/cameras/previewURLs person-list: /api/resource/v2/person/personList # 新增人员列表接口 - visitor-appointment: /api/visitor/v2/appointment # 新增访客预约接口 \ No newline at end of file + 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 # 新增签离接口 \ No newline at end of file