嘉兴访客系统

This commit is contained in:
zjf committed 2025-06-03 16:10:14 +08:00
1 parent b78c4938c1
commit ac709e77e6
27 files changed
+2166 -5

No files matched your search

@@ -88,4 +88,8 @@ public class VisitorsAppPageVo {
@Schema(description="token")
private String token;
@Schema(description="类型")
private String type;
}
@@ -133,4 +133,13 @@ public class VisitorsAppVo{
@Schema(description="随行人员信息")
private List<VisitorsPeopleAppVo> visitorsPeopleAppVos;
@Schema(description="二维码")
private String qrcode;
@Schema(description="验证码")
private String verificationCode;
}
@@ -22,4 +22,11 @@ public class VisitorsPeopleAppVo {
private String mobile;
@Schema(description="二维码")
private String qrcode;
@Schema(description="验证码")
private String verificationCode;
}
@@ -11,6 +11,7 @@ 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.service.PjcloudUser;
import com.bsd.pjcloud.common.security.util.SecurityUtils;
import com.bsd.pjcloud.flow.task.api.feign.RemoteFlowApiFlowService;
import com.bsd.pjcloud.flow.task.constant.TaskCheckStatusEnum;
@@ -186,6 +187,14 @@ 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())) {
// 清除qrcode相关字段
bean.setQrcode(null);
bean.setVerificationCode(null);
}
List<VisitorsCarEntity> visitorsCarEntities =
visitorsCarMapper.selectList(new LambdaQueryWrapper<VisitorsCarEntity>().eq(VisitorsCarEntity::getVisitorsId, visitors.getId()));
if (!CollectionUtils.isEmpty(visitorsCarEntities)){
@@ -196,6 +205,15 @@ public class VisitorsServiceImpl extends ServiceImpl<VisitorsMapper, VisitorsEnt
visitorsPeopleMapper.selectList(new LambdaQueryWrapper<VisitorsPeopleEntity>().eq(VisitorsPeopleEntity::getVisitorsId, visitors.getId()));
if (!CollectionUtils.isEmpty(visitorsPeopleEntities)){
List<VisitorsPeopleAppVo> visitorsPeopleAppVos = BeanUtils.toBean(visitorsPeopleEntities, VisitorsPeopleAppVo.class);
// 对于其他访客,同样只有审核通过时才携带qrcode信息
if (!TaskCheckStatusEnum.RESULT.getCode().equals(visitors.getCheckStatus())) {
visitorsPeopleAppVos.forEach(peopleVo -> {
peopleVo.setQrcode(null);
peopleVo.setVerificationCode(null);
});
}
bean.setVisitorsPeopleAppVos(visitorsPeopleAppVos);
}
@@ -218,12 +236,14 @@ public class VisitorsServiceImpl extends ServiceImpl<VisitorsMapper, VisitorsEnt
// throw new ServiceException("流程实例启动失败: " + stringR.getMsg());
// }
// String processInstanceId = stringR.getData();
Long deptId = SecurityUtils.getUser().getDeptId();
PjcloudUser user = SecurityUtils.getUser();
Long deptId = user.getDeptId();
VisitorsEntity bean = BeanUtils.toBean(visitors, VisitorsEntity.class);
bean.setType(VisitorTypeEnum.ZDYQ.getType());
// bean.setProcessInstanceId(processInstanceId);
bean.setUserId(user.getId());
bean.setDeptId(deptId);
bean.setCheckStatus(TaskCheckStatusEnum.PADDING.getCode());
bean.setCheckStatus(TaskCheckStatusEnum.RESULT.getCode());
String uniqueToken = UUID.randomUUID().toString();
String token = uniqueToken.replace("-", "");
@@ -254,7 +274,8 @@ public class VisitorsServiceImpl extends ServiceImpl<VisitorsMapper, VisitorsEnt
LambdaQueryWrapper<VisitorsEntity> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(VisitorsEntity::getUserId, userId);
wrapper.eq(StringUtils.isNotBlank(visitors.getCheckStatus()),VisitorsEntity::getCheckStatus, visitors.getCheckStatus());
// wrapper.eq(VisitorsEntity::getType, VisitorTypeEnum.ZDYQ.getType());
wrapper.eq(VisitorsEntity::getType, visitors.getType());
wrapper.orderByDesc(VisitorsEntity::getCreateTime);
Page pageData = baseMapper.selectPage(page, wrapper);
List<VisitorsAppPageVo> records = pageData.getRecords();
@@ -27,6 +27,23 @@ import com.bsd.pjcloud.thirdparty.dto.visitor.request.make.RegisterAppointmentRe
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.dto.person.AddPersonRequest;
import com.bsd.pjcloud.thirdparty.dto.person.AddPersonResponse;
import com.bsd.pjcloud.thirdparty.dto.person.BatchAddPersonRequest;
import com.bsd.pjcloud.thirdparty.dto.person.BatchAddPersonResponse;
import com.bsd.pjcloud.thirdparty.dto.person.UpdatePersonRequest;
import com.bsd.pjcloud.thirdparty.dto.person.UpdatePersonResponse;
import com.bsd.pjcloud.thirdparty.dto.person.BatchDeletePersonRequest;
import com.bsd.pjcloud.thirdparty.dto.person.BatchDeletePersonResponse;
import com.bsd.pjcloud.thirdparty.dto.face.AddFaceRequest;
import com.bsd.pjcloud.thirdparty.dto.face.AddFaceResponse;
import com.bsd.pjcloud.thirdparty.dto.face.UpdateFaceRequest;
import com.bsd.pjcloud.thirdparty.dto.face.DeleteFaceRequest;
import com.bsd.pjcloud.thirdparty.dto.face.DeleteFaceResponse;
import com.bsd.pjcloud.thirdparty.dto.person.GetPersonListRequest;
import com.bsd.pjcloud.thirdparty.dto.person.GetPersonListResponse;
import com.bsd.pjcloud.thirdparty.dto.person.GetPersonInfoRequest;
import com.bsd.pjcloud.thirdparty.dto.person.GetPersonInfoResponse;
import io.swagger.v3.oas.annotations.Operation;
import jakarta.validation.Valid;
import org.springframework.cloud.openfeign.FeignClient;
@@ -73,4 +90,85 @@ public interface RemoterVisitorService {
*/
@PostMapping("/visitors/checkout")
public R checkOut(@Valid @RequestBody CheckOutRequest request);
/**
* 添加人员信息v2
* @param request 添加人员请求参数
* @return 添加人员响应结果
*/
@PostMapping("/person/add")
@Operation(summary = "添加人员信息v2", description = "添加人员信息到海康平台")
public R<AddPersonResponse> addPersonV2(@Valid @RequestBody AddPersonRequest request);
/**
* 批量添加人员信息v1
* @param request 批量添加人员请求参数
* @return 批量添加人员响应结果
*/
@PostMapping("/person/batch-add")
@Operation(summary = "批量添加人员信息v1", description = "批量添加人员信息到海康平台")
public R<BatchAddPersonResponse> batchAddPersonV1(@Valid @RequestBody BatchAddPersonRequest request);
/**
* 修改人员信息v1
* @param request 修改人员请求参数
* @return 修改人员响应结果
*/
@PostMapping("/person/update")
@Operation(summary = "修改人员信息v1", description = "修改海康平台人员信息")
public R<UpdatePersonResponse> updatePersonV1(@Valid @RequestBody UpdatePersonRequest request);
/**
* 批量删除人员信息v1
* @param request 批量删除人员请求参数
* @return 批量删除人员响应结果
*/
@PostMapping("/person/batch-delete")
@Operation(summary = "批量删除人员信息v1", description = "批量删除海康平台人员信息")
public R<BatchDeletePersonResponse> batchDeletePersonV1(@Valid @RequestBody BatchDeletePersonRequest request);
/**
* 添加人脸信息v1
* @param request 添加人脸请求参数
* @return 添加人脸响应结果
*/
@PostMapping("/face/add")
@Operation(summary = "添加人脸信息v1", description = "添加人脸信息到海康平台")
public R<AddFaceResponse> addFaceV1(@Valid @RequestBody AddFaceRequest request);
/**
* 修改人脸信息v1
* @param request 修改人脸请求参数
* @return 修改人脸响应结果
*/
@PostMapping("/face/update")
@Operation(summary = "修改人脸信息v1", description = "修改海康平台人脸信息")
public R<AddFaceResponse> updateFaceV1(@Valid @RequestBody UpdateFaceRequest request);
/**
* 删除人脸信息v1
* @param request 删除人脸请求参数
* @return 删除人脸响应结果
*/
@PostMapping("/face/delete")
@Operation(summary = "删除人脸信息v1", description = "删除海康平台人脸信息")
public R<DeleteFaceResponse> deleteFaceV1(@Valid @RequestBody DeleteFaceRequest request);
/**
* 获取组织下人员列表v2
* @param request 获取人员列表请求参数
* @return 获取人员列表响应结果
*/
@PostMapping("/person/list")
@Operation(summary = "获取组织下人员列表v2", description = "根据组织编号获取组织下的人员信息列表")
public R<GetPersonListResponse> getPersonListV2(@Valid @RequestBody GetPersonListRequest request);
/**
* 根据人员唯一字段获取人员详细信息v1
* @param request 获取人员详细信息请求参数
* @return 获取人员详细信息响应结果
*/
@PostMapping("/person/detail")
@Operation(summary = "根据人员唯一字段获取人员详细信息v1", description = "根据实名标识精确查询人员详细信息")
public R<GetPersonInfoResponse> getPersonInfoV1(@Valid @RequestBody GetPersonInfoRequest request);
}
@@ -0,0 +1,23 @@
package com.bsd.pjcloud.thirdparty.dto.face;
import lombok.Data;
import jakarta.validation.constraints.NotBlank;
/**
* 添加人脸请求DTO
*/
@Data
public class AddFaceRequest {
/**
* 人员Id,必填
*/
@NotBlank(message = "人员ID不能为空")
private String personId;
/**
* 人脸图片base64编码后的字符数据,必填
*/
@NotBlank(message = "人脸图片数据不能为空")
private String faceData;
}
@@ -0,0 +1,44 @@
package com.bsd.pjcloud.thirdparty.dto.face;
import lombok.Data;
/**
* 添加人脸响应VO
*/
@Data
public class AddFaceResponse {
/**
* 返回码,0 – 成功,其他- 失败
*/
private String code;
/**
* 返回说明
*/
private String msg;
/**
* 返回数据
*/
private FaceData data;
@Data
public static class FaceData {
/**
* 人脸Id
*/
private String faceId;
/**
* 人脸图片Url
*/
private String faceUrl;
/**
* 人员ID
*/
private String personId;
}
}
@@ -0,0 +1,18 @@
package com.bsd.pjcloud.thirdparty.dto.face;
import lombok.Data;
import jakarta.validation.constraints.NotBlank;
/**
* 删除人脸请求DTO
*/
@Data
public class DeleteFaceRequest {
/**
* 人脸图片Id,必填
* 添加人脸接口返回报文中的faceId字段,或获取人员列表v2接口返回报文中的personPhotoIndexCode字段
*/
@NotBlank(message = "人脸ID不能为空")
private String faceId;
}
@@ -0,0 +1,25 @@
package com.bsd.pjcloud.thirdparty.dto.face;
import lombok.Data;
/**
* 删除人脸响应VO
*/
@Data
public class DeleteFaceResponse {
/**
* 返回码,0 – 成功,其他- 失败
*/
private String code;
/**
* 返回信息(注意:删除接口返回的是message字段,不是msg)
*/
private String message;
/**
* 删除成功则为空
*/
private String data;
}
@@ -0,0 +1,24 @@
package com.bsd.pjcloud.thirdparty.dto.face;
import lombok.Data;
import jakarta.validation.constraints.NotBlank;
/**
* 修改人脸请求DTO
*/
@Data
public class UpdateFaceRequest {
/**
* 人脸图片Id,必填
* 添加人脸接口返回报文中的faceId字段,或获取人员列表v2接口返回报文中的personPhotoIndexCode字段
*/
@NotBlank(message = "人脸ID不能为空")
private String faceId;
/**
* 人脸图片base64编码后的字符数据,必填
*/
@NotBlank(message = "人脸图片数据不能为空")
private String faceData;
}
@@ -0,0 +1,95 @@
package com.bsd.pjcloud.thirdparty.dto.person;
import lombok.Data;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.Pattern;
import jakarta.validation.Valid;
import java.util.List;
/**
* 添加人员请求DTO
*/
@Data
public class AddPersonRequest {
/**
* 人员ID,可以指定人员personId,不允许与其他人员personId重复,包括已删除的人员。
* 为空时平台自动生成人员ID
*/
private String personId;
/**
* 人员名称,1~32个字符;不能包含 ' / \ : * ? " < >
*/
@NotBlank(message = "人员名称不能为空")
@Size(min = 1, max = 32, message = "人员名称长度必须在1-32个字符之间")
@Pattern(regexp = "^[^'/\\\\:*?\"<>]*$", message = "人员名称不能包含特殊字符:' / \\ : * ? \" < >")
private String personName;
/**
* 性别:1-男,2-女
*/
@NotBlank(message = "性别不能为空")
@Pattern(regexp = "^[12]$", message = "性别只能是1(男)或2(女)")
private String gender;
/**
* 所属组织标识,必须是已存在组织
*/
@NotBlank(message = "所属组织标识不能为空")
private String orgIndexCode;
/**
* 出生日期,举例:1992-09-12
*/
@Pattern(regexp = "^\\d{4}-\\d{2}-\\d{2}$", message = "出生日期格式必须为yyyy-MM-dd")
private String birthday;
/**
* 手机号,1-20位数字,平台上人员信息实名标识选择为手机号码时必填
*/
@Size(min = 1, max = 20, message = "手机号长度必须在1-20位之间")
@Pattern(regexp = "^\\d{1,20}$", message = "手机号只能包含数字")
private String phoneNo;
/**
* 邮箱,举例:hic@163.com
*/
@Email(message = "邮箱格式不正确")
private String email;
/**
* 证件类型,参考附录A数据字典,平台上人员信息实名标识选择为身份证件时必填
*/
private String certificateType;
/**
* 证件号码,1-20位数字字母,平台上人员信息实名标识选择为身份证件时必填
*/
@Size(min = 1, max = 20, message = "证件号码长度必须在1-20位之间")
@Pattern(regexp = "^[a-zA-Z0-9]{1,20}$", message = "证件号码只能包含数字和字母")
private String certificateNo;
/**
* 工号,1-32个字符,平台上人员信息实名标识选择为工号时必填
*/
@Size(min = 1, max = 32, message = "工号长度必须在1-32个字符之间")
private String jobNo;
/**
* 人脸信息
*/
@Valid
private List<FaceInfo> faces;
@Data
public static class FaceInfo {
/**
* 人脸图片base64编码后的字符
*/
@NotBlank(message = "人脸图片数据不能为空")
private String faceData;
}
}
@@ -0,0 +1,38 @@
package com.bsd.pjcloud.thirdparty.dto.person;
import lombok.Data;
/**
* 添加人员响应VO
*/
@Data
public class AddPersonResponse {
/**
* 返回码,0 – 成功,其他- 失败
*/
private String code;
/**
* 返回说明
*/
private String msg;
/**
* 成功添加的人员信息
*/
private PersonData data;
@Data
public static class PersonData {
/**
* 成功添加的人员Id
*/
private String personId;
/**
* 成功添加的人脸Id
*/
private String faceId;
}
}
@@ -0,0 +1,29 @@
package com.bsd.pjcloud.thirdparty.dto.person;
import com.bsd.pjcloud.thirdparty.dto.visitor.PersonInfo;
import lombok.Data;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.Pattern;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.Max;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotEmpty;
import java.util.List;
/**
* 批量添加人员请求DTO
*/
@Data
public class BatchAddPersonRequest {
/**
* 待添加的人员列表,单次操作上限为1000条
*/
@NotEmpty(message = "人员列表不能为空")
@Size(max = 1000, message = "单次操作最多支持1000条记录")
@Valid
private List<PersonInfo> persons;
}
@@ -0,0 +1,73 @@
package com.bsd.pjcloud.thirdparty.dto.person;
import lombok.Data;
import java.util.List;
/**
* 批量添加人员响应VO
*/
@Data
public class BatchAddPersonResponse {
/**
* 返回码,0 – 成功,其他- 失败
*/
private String code;
/**
* 返回说明
*/
private String msg;
/**
* 返回结果
*/
private BatchPersonData data;
@Data
public static class BatchPersonData {
/**
* 批量添加成功的记录
*/
private List<SuccessRecord> successes;
/**
* 批量添加失败的记录
*/
private List<FailureRecord> failures;
}
@Data
public static class SuccessRecord {
/**
* 调用方指定人员临时标志
*/
private Long clientId;
/**
* 服务端生成的唯一标识
*/
private String personId;
}
@Data
public static class FailureRecord {
/**
* 调用方指定Id
*/
private Long clientId;
/**
* 错误码
*/
private String code;
/**
* 错误信息
*/
private String message;
}
}
@@ -0,0 +1,20 @@
package com.bsd.pjcloud.thirdparty.dto.person;
import lombok.Data;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.Size;
import java.util.List;
/**
* 批量删除人员请求DTO
*/
@Data
public class BatchDeletePersonRequest {
/**
* 人员Id列表,单次操作上限为1000条
*/
@NotEmpty(message = "人员ID列表不能为空")
@Size(max = 1000, message = "单次操作最多支持1000条记录")
private List<String> personIds;
}
@@ -0,0 +1,45 @@
package com.bsd.pjcloud.thirdparty.dto.person;
import lombok.Data;
import java.util.List;
/**
* 批量删除人员响应VO
*/
@Data
public class BatchDeletePersonResponse {
/**
* 返回码,0 – 成功,其他- 失败
*/
private String code;
/**
* 返回说明
*/
private String msg;
/**
* 若执行结果为部分删除成功,则返回删除失败的人员标志和错误原因,若全部成功,则该字段为空
*/
private List<DeleteFailureRecord> data;
@Data
public static class DeleteFailureRecord {
/**
* 人员标志
*/
private String personId;
/**
* 错误码
*/
private String code;
/**
* 错误信息
*/
private String msg;
}
}
@@ -0,0 +1,34 @@
package com.bsd.pjcloud.thirdparty.dto.person;
import lombok.Data;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.Size;
import jakarta.validation.constraints.Pattern;
import java.util.List;
/**
* 根据人员唯一字段获取人员详细信息请求DTO
*/
@Data
public class GetPersonInfoRequest {
/**
* 参数名,必填
* certificateNo:证件号码
* personId:人员Id
* phoneNo:手机号码
* jobNo:工号
*/
@NotBlank(message = "参数名不能为空")
@Pattern(regexp = "^(certificateNo|personId|phoneNo|jobNo)$",
message = "参数名只能是:certificateNo、personId、phoneNo、jobNo")
private String paramName;
/**
* 根据入参传对应的值,最大1000个
*/
@NotEmpty(message = "参数值列表不能为空")
@Size(max = 1000, message = "参数值最多支持1000个")
private List<String> paramValue;
}
@@ -0,0 +1,328 @@
package com.bsd.pjcloud.thirdparty.dto.person;
import lombok.Data;
import java.util.List;
/**
* 根据人员唯一字段获取人员详细信息响应VO
*/
@Data
public class GetPersonInfoResponse {
/**
* 返回码,0 – 成功,其他- 失败
*/
private String code;
/**
* 接口执行情况说明信息
*/
private String msg;
/**
* 返回数据
*/
private PersonInfoData data;
@Data
public static class PersonInfoData {
/**
* 结果总数
*/
private Integer total;
/**
* 人员信息列表
*/
private List<DetailedPersonInfo> list;
}
@Data
public static class DetailedPersonInfo {
/**
* 人员ID
*/
private String personId;
/**
* 姓名
*/
private String personName;
/**
* 性别:1-男,2-女
*/
private Integer gender;
/**
* 所属组织目录,以@符号分割,包含本组织,例如@root000000@
*/
private String orgPath;
/**
* 所属组织目录名称,以/分隔
*/
private String orgPathName;
/**
* 所属组织唯一标识码
*/
private String orgIndexCode;
/**
* 证件类型
*/
private Integer certificateType;
/**
* 证件号码
*/
private String certificateNo;
/**
* 工号
*/
private String jobNo;
/**
* 出生日期,例"1990-01-01"
*/
private String birthday;
/**
* 联系电话
*/
private String phoneNo;
/**
* 联系地址
*/
private String address;
/**
* 人员照片信息
*/
private List<PersonPhotoInfo> personPhoto;
/**
* 邮箱
*/
private String email;
/**
* 学历
*/
private Integer education;
/**
* 人员姓氏
*/
private String lastName;
/**
* 人员名称
*/
private String givenName;
/**
* 年龄
*/
private Integer age;
/**
* 职业
*/
private String job;
/**
* 职工性质
*/
private String staffProperty;
/**
* 工作单位
*/
private String company;
/**
* 职位
*/
private String employeePost;
/**
* 员工编号
*/
private String employeeNumber;
/**
* 岗位类别
*/
private String postType;
/**
* 身份类型
*/
private String identityType;
/**
* 国籍
*/
private String nationality;
/**
* 民族
*/
private Integer nation;
/**
* 籍贯
*/
private String birthplace;
/**
* 户籍
*/
private String censusRegister;
/**
* 婚姻状况
*/
private Integer marriaged;
/**
* 政治面貌
*/
private String politicalStatus;
/**
* 宗教
*/
private String religion;
/**
* 房间号
*/
private String roomNum;
/**
* 与户主关系
*/
private String houseHolderRel;
/**
* 学号
*/
private String studentId;
/**
* 学生入学时间,例"1990-01-01"
*/
private String stuStartTime;
/**
* 学生毕业时间,例"1990-01-01"
*/
private String stuEndTime;
/**
* 年级
*/
private String stuGrade;
/**
* 班级
*/
private String stuClass;
/**
* 学院
*/
private String academy;
/**
* 学生专业
*/
private String profession;
/**
* 宿舍楼
*/
private String dormitory;
/**
* 是否住校,1:是;2:否
*/
private Integer lodge;
/**
* 人员描述
*/
private String personDesc;
/**
* 同步标志类型
*/
private Integer syncFlag;
/**
* 拼音
*/
private String pinyin;
/**
* 发证机构
*/
private String certIssuer;
/**
* 发证地址
*/
private String certAddr;
/**
* 证件有效期
*/
private String certExpireTime;
/**
* 状态,小于0则代表资源已被删除
*/
private Integer status;
/**
* 创建时间,ISO8601格式
*/
private String createTime;
/**
* 更新时间,ISO8601格式
*/
private String updateTime;
}
@Data
public static class PersonPhotoInfo {
/**
* 图片唯一标示
*/
private String personPhotoIndexCode;
/**
* 图片相对url,从提取人员图片接口获取图片数据
*/
private String picUri;
/**
* 图片服务器唯一标示
*/
private String serverIndexCode;
/**
* 人员ID
*/
private String personId;
}
}
@@ -0,0 +1,32 @@
package com.bsd.pjcloud.thirdparty.dto.person;
import lombok.Data;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.Max;
/**
* 获取组织下人员列表v2请求DTO
*/
@Data
public class GetPersonListRequest {
/**
* 组织唯一标识码,必填
*/
@NotBlank(message = "组织唯一标识码不能为空")
private String orgIndexCode;
/**
* 当前页码,必填,需大于0
*/
@Min(value = 1, message = "当前页码需大于0")
private Integer pageNo;
/**
* 实际每页记录总数,必填,需大于0且小于等于1000
*/
@Min(value = 1, message = "每页记录数需大于0")
@Max(value = 1000, message = "每页记录数需小于等于1000")
private Integer pageSize;
}
@@ -0,0 +1,145 @@
package com.bsd.pjcloud.thirdparty.dto.person;
import lombok.Data;
import java.util.List;
/**
* 获取组织下人员列表v2响应VO
*/
@Data
public class GetPersonListResponse {
/**
* 返回码,0 – 成功,其他- 失败
*/
private String code;
/**
* 接口执行情况说明信息
*/
private String msg;
/**
* 人员信息结构体
*/
private PersonListData data;
@Data
public static class PersonListData {
/**
* 查询数据记录总数
*/
private Integer total;
/**
* 当前页码
*/
private Integer pageNo;
/**
* 每页记录总数
*/
private Integer pageSize;
/**
* 人员列表
*/
private List<PersonInfo> list;
}
@Data
public static class PersonInfo {
/**
* 人员ID
*/
private String personId;
/**
* 姓名
*/
private String personName;
/**
* 性别:1-男,2-女
*/
private Integer gender;
/**
* 所属组织唯一标识码
*/
private String orgIndexCode;
/**
* 联系电话
*/
private String phoneNo;
/**
* 工号
*/
private String jobNo;
/**
* 证件类型
* 111:身份证, 414:护照, 113:户口簿, 335:驾驶证
* 131:工作证, 133:学生证, 990:其他
*/
private Integer certificateType;
/**
* 证件号码
*/
private String certificateNo;
/**
* 创建时间(ISO8601格式)
*/
private String createTime;
/**
* 更新时间(ISO8601格式)
*/
private String updateTime;
/**
* 所属组织目录,@进行分割,例如 @root000000@
*/
private String orgPath;
/**
* 所属组织名称,@进行分割,如@默认部门@
*/
private String orgPathName;
/**
* 人员图片信息
*/
private PersonPhoto personPhoto;
}
@Data
public static class PersonPhoto {
/**
* 人脸图片唯一标示
*/
private String personPhotoIndexCode;
/**
* 图片相对url,通过提取人员图片接口获取图片数据
*/
private String picUri;
/**
* 图片服务器唯一标示,提取人员图片接口必要参数
*/
private String serverIndexCode;
/**
* 人员ID
*/
private String personId;
}
}
@@ -0,0 +1,81 @@
package com.bsd.pjcloud.thirdparty.dto.person;
import lombok.Data;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.Pattern;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.Max;
/**
* 修改人员请求DTO
*/
@Data
public class UpdatePersonRequest {
/**
* 人员id,必填
*/
@NotBlank(message = "人员ID不能为空")
private String personId;
/**
* 人员名称,1~32个字符;不能包含 ' / \ : * ? " < >
*/
@Size(min = 1, max = 32, message = "人员名称长度必须在1-32个字符之间")
@Pattern(regexp = "^[^'/\\\\:*?\"<>]*$", message = "人员名称不能包含特殊字符:' / \\ : * ? \" < >")
private String personName;
/**
* 所属组织标识,必须是已存在组织
*/
private String orgIndexCode;
/**
* 性别:1-男,2-女
*/
@Min(value = 1, message = "性别值必须为1或2")
@Max(value = 2, message = "性别值必须为1或2")
private Integer gender;
/**
* 出生日期,举例:1992-09-12
*/
@Pattern(regexp = "^\\d{4}-\\d{2}-\\d{2}$", message = "出生日期格式必须为yyyy-MM-dd")
private String birthday;
/**
* 手机号,1-20位数字
*/
@Size(min = 1, max = 20, message = "手机号长度必须在1-20位之间")
@Pattern(regexp = "^\\d{1,20}$", message = "手机号只能包含数字")
private String phoneNo;
/**
* 邮箱,举例:hic@163.com
*/
@Email(message = "邮箱格式不正确")
private String email;
/**
* 证件类型
* 111: 身份证, 414: 护照, 113: 户口簿, 335: 驾驶证
* 131: 工作证, 133: 学生证, 990: 其他
*/
@Pattern(regexp = "^(111|414|113|335|131|133|990)$", message = "证件类型不正确")
private String certificateType;
/**
* 证件号码,1-20位数字字母
*/
@Size(min = 1, max = 20, message = "证件号码长度必须在1-20位之间")
@Pattern(regexp = "^[a-zA-Z0-9]{1,20}$", message = "证件号码只能包含数字和字母")
private String certificateNo;
/**
* 工号,1-32个字符
*/
@Size(min = 1, max = 32, message = "工号长度必须在1-32个字符之间")
private String jobNo;
}
@@ -0,0 +1,25 @@
package com.bsd.pjcloud.thirdparty.dto.person;
import lombok.Data;
/**
* 修改人员响应VO
*/
@Data
public class UpdatePersonResponse {
/**
* 返回码,0 – 成功,其他- 失败
*/
private String code;
/**
* 返回说明
*/
private String msg;
/**
* 成功则data为空
*/
private String data;
}
@@ -14,7 +14,7 @@ public class PersonInfo {
private String personId;
private String personName;
private Integer gender;
private String orgIndexCode;
private String orgIndexCode="1013f7bb18d94ec8962a9fb3eb1df44b";
private String phoneNo;
private String jobNo;
private Integer certificateType;
@@ -9,6 +9,23 @@ import com.bsd.pjcloud.thirdparty.dto.visitor.request.make.VisitorAppointmentReq
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.dto.person.AddPersonRequest;
import com.bsd.pjcloud.thirdparty.dto.person.AddPersonResponse;
import com.bsd.pjcloud.thirdparty.dto.person.BatchAddPersonRequest;
import com.bsd.pjcloud.thirdparty.dto.person.BatchAddPersonResponse;
import com.bsd.pjcloud.thirdparty.dto.person.UpdatePersonRequest;
import com.bsd.pjcloud.thirdparty.dto.person.UpdatePersonResponse;
import com.bsd.pjcloud.thirdparty.dto.person.BatchDeletePersonRequest;
import com.bsd.pjcloud.thirdparty.dto.person.BatchDeletePersonResponse;
import com.bsd.pjcloud.thirdparty.dto.face.AddFaceRequest;
import com.bsd.pjcloud.thirdparty.dto.face.AddFaceResponse;
import com.bsd.pjcloud.thirdparty.dto.face.UpdateFaceRequest;
import com.bsd.pjcloud.thirdparty.dto.face.DeleteFaceRequest;
import com.bsd.pjcloud.thirdparty.dto.face.DeleteFaceResponse;
import com.bsd.pjcloud.thirdparty.dto.person.GetPersonListRequest;
import com.bsd.pjcloud.thirdparty.dto.person.GetPersonListResponse;
import com.bsd.pjcloud.thirdparty.dto.person.GetPersonInfoRequest;
import com.bsd.pjcloud.thirdparty.dto.person.GetPersonInfoResponse;
import com.bsd.pjcloud.thirdparty.service.VisitorService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
@@ -95,7 +112,148 @@ public class VisitorController {
return R.ok();
}
/**
* 添加人员信息v2
* @param request 添加人员请求参数
* @return 添加人员响应结果
*/
@Operation(summary = "添加人员信息v2", description = "添加人员信息到海康平台")
@PostMapping("/person/add")
public R<AddPersonResponse> addPersonV2(@Valid @RequestBody AddPersonRequest request) {
try {
AddPersonResponse response = visitorService.addPersonV2(request);
return R.ok(response);
} catch (Exception e) {
return R.failed("添加人员失败: " + e.getMessage());
}
}
/**
* 批量添加人员信息v1
* @param request 批量添加人员请求参数
* @return 批量添加人员响应结果
*/
@Operation(summary = "批量添加人员信息v1", description = "批量添加人员信息到海康平台")
@PostMapping("/person/batch-add")
public R<BatchAddPersonResponse> batchAddPersonV1(@Valid @RequestBody BatchAddPersonRequest request) {
try {
BatchAddPersonResponse response = visitorService.batchAddPersonV1(request);
return R.ok(response);
} catch (Exception e) {
return R.failed("批量添加人员失败: " + e.getMessage());
}
}
/**
* 修改人员信息v1
* @param request 修改人员请求参数
* @return 修改人员响应结果
*/
@Operation(summary = "修改人员信息v1", description = "修改海康平台人员信息")
@PostMapping("/person/update")
public R<UpdatePersonResponse> updatePersonV1(@Valid @RequestBody UpdatePersonRequest request) {
try {
UpdatePersonResponse response = visitorService.updatePersonV1(request);
return R.ok(response);
} catch (Exception e) {
return R.failed("修改人员失败: " + e.getMessage());
}
}
/**
* 批量删除人员信息v1
* @param request 批量删除人员请求参数
* @return 批量删除人员响应结果
*/
@Operation(summary = "批量删除人员信息v1", description = "批量删除海康平台人员信息")
@PostMapping("/person/batch-delete")
public R<BatchDeletePersonResponse> batchDeletePersonV1(@Valid @RequestBody BatchDeletePersonRequest request) {
try {
BatchDeletePersonResponse response = visitorService.batchDeletePersonV1(request);
return R.ok(response);
} catch (Exception e) {
return R.failed("批量删除人员失败: " + e.getMessage());
}
}
/**
* 添加人脸信息v1
* @param request 添加人脸请求参数
* @return 添加人脸响应结果
*/
@Operation(summary = "添加人脸信息v1", description = "添加人脸信息到海康平台")
@PostMapping("/face/add")
public R<AddFaceResponse> addFaceV1(@Valid @RequestBody AddFaceRequest request) {
try {
AddFaceResponse response = visitorService.addFaceV1(request);
return R.ok(response);
} catch (Exception e) {
return R.failed("添加人脸失败: " + e.getMessage());
}
}
/**
* 修改人脸信息v1
* @param request 修改人脸请求参数
* @return 修改人脸响应结果
*/
@Operation(summary = "修改人脸信息v1", description = "修改海康平台人脸信息")
@PostMapping("/face/update")
public R<AddFaceResponse> updateFaceV1(@Valid @RequestBody UpdateFaceRequest request) {
try {
AddFaceResponse response = visitorService.updateFaceV1(request);
return R.ok(response);
} catch (Exception e) {
return R.failed("修改人脸失败: " + e.getMessage());
}
}
/**
* 删除人脸信息v1
* @param request 删除人脸请求参数
* @return 删除人脸响应结果
*/
@Operation(summary = "删除人脸信息v1", description = "删除海康平台人脸信息")
@PostMapping("/face/delete")
public R<DeleteFaceResponse> deleteFaceV1(@Valid @RequestBody DeleteFaceRequest request) {
try {
DeleteFaceResponse response = visitorService.deleteFaceV1(request);
return R.ok(response);
} catch (Exception e) {
return R.failed("删除人脸失败: " + e.getMessage());
}
}
/**
* 获取组织下人员列表v2
* @param request 获取人员列表请求参数
* @return 获取人员列表响应结果
*/
@Operation(summary = "获取组织下人员列表v2", description = "根据组织编号获取组织下的人员信息列表")
@PostMapping("/person/list")
public R<GetPersonListResponse> getPersonListV2(@Valid @RequestBody GetPersonListRequest request) {
try {
GetPersonListResponse response = visitorService.getPersonListV2(request);
return R.ok(response);
} catch (Exception e) {
return R.failed("获取人员列表失败: " + e.getMessage());
}
}
/**
* 根据人员唯一字段获取人员详细信息v1
* @param request 获取人员详细信息请求参数
* @return 获取人员详细信息响应结果
*/
@Operation(summary = "根据人员唯一字段获取人员详细信息v1", description = "根据实名标识精确查询人员详细信息")
@PostMapping("/person/detail")
public R<GetPersonInfoResponse> getPersonInfoV1(@Valid @RequestBody GetPersonInfoRequest request) {
try {
GetPersonInfoResponse response = visitorService.getPersonInfoV1(request);
return R.ok(response);
} catch (Exception e) {
return R.failed("获取人员详细信息失败: " + e.getMessage());
}
}
}
@@ -27,6 +27,24 @@ import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import com.bsd.pjcloud.thirdparty.dto.person.AddPersonRequest;
import com.bsd.pjcloud.thirdparty.dto.person.AddPersonResponse;
import com.bsd.pjcloud.thirdparty.dto.person.BatchAddPersonRequest;
import com.bsd.pjcloud.thirdparty.dto.person.BatchAddPersonResponse;
import com.bsd.pjcloud.thirdparty.dto.person.UpdatePersonRequest;
import com.bsd.pjcloud.thirdparty.dto.person.UpdatePersonResponse;
import com.bsd.pjcloud.thirdparty.dto.person.BatchDeletePersonRequest;
import com.bsd.pjcloud.thirdparty.dto.person.BatchDeletePersonResponse;
import com.bsd.pjcloud.thirdparty.dto.face.AddFaceRequest;
import com.bsd.pjcloud.thirdparty.dto.face.AddFaceResponse;
import com.bsd.pjcloud.thirdparty.dto.face.UpdateFaceRequest;
import com.bsd.pjcloud.thirdparty.dto.face.DeleteFaceRequest;
import com.bsd.pjcloud.thirdparty.dto.face.DeleteFaceResponse;
import com.bsd.pjcloud.thirdparty.dto.person.GetPersonListRequest;
import com.bsd.pjcloud.thirdparty.dto.person.GetPersonListResponse;
import com.bsd.pjcloud.thirdparty.dto.person.GetPersonInfoRequest;
import com.bsd.pjcloud.thirdparty.dto.person.GetPersonInfoResponse;
@Service
@Slf4j
public class VisitorService extends BaseHikvisionService {
@@ -360,6 +378,744 @@ public class VisitorService extends BaseHikvisionService {
}
}
/**
* 添加人员信息v2
*
* @param request 添加人员请求参数
* @return 添加人员响应结果
*/
@Transactional
public AddPersonResponse addPersonV2(AddPersonRequest request) {
// 1. 参数校验
if (request == null) {
throw new IllegalArgumentException("添加人员请求参数不能为空");
}
if (StringUtils.isBlank(request.getPersonName())) {
throw new IllegalArgumentException("人员名称不能为空");
}
if (StringUtils.isBlank(request.getGender())) {
throw new IllegalArgumentException("性别不能为空");
}
if (StringUtils.isBlank(request.getOrgIndexCode())) {
throw new IllegalArgumentException("所属组织标识不能为空");
}
// 2. 构建API路径
String apiPath = properties.getArtemisPath() + "/api/resource/v2/person/single/add";
// 3. 转换请求体
JSONObject body = convertAddPersonRequestToJSON(request);
// 添加日志便于调试
log.info("添加人员请求体: {}", body.toJSONString());
// 4. 发送请求
String responseJson = ArtemisHttpUtil.doPostStringArtemis(
Map.of("https://", apiPath),
body.toJSONString(),
null, null, "application/json", null
);
// 添加日志便于调试
log.info("添加人员响应: {}", responseJson);
// 5. 处理响应
AddPersonResponse response = parseAddPersonResponse(responseJson);
if (!"0".equals(response.getCode())) {
throw new HikvisionException(response.getCode(), response.getMsg());
}
return response;
}
/**
* 转换添加人员请求为JSON
*/
private JSONObject convertAddPersonRequestToJSON(AddPersonRequest request) {
JSONObject json = new JSONObject();
// 必填字段
json.put("personName", request.getPersonName());
json.put("gender", request.getGender());
json.put("orgIndexCode", request.getOrgIndexCode());
// 可选字段
if (StringUtils.isNotBlank(request.getPersonId())) {
json.put("personId", request.getPersonId());
}
if (StringUtils.isNotBlank(request.getBirthday())) {
json.put("birthday", request.getBirthday());
}
if (StringUtils.isNotBlank(request.getPhoneNo())) {
json.put("phoneNo", request.getPhoneNo());
}
if (StringUtils.isNotBlank(request.getEmail())) {
json.put("email", request.getEmail());
}
if (StringUtils.isNotBlank(request.getCertificateType())) {
json.put("certificateType", request.getCertificateType());
}
if (StringUtils.isNotBlank(request.getCertificateNo())) {
json.put("certificateNo", request.getCertificateNo());
}
if (StringUtils.isNotBlank(request.getJobNo())) {
json.put("jobNo", request.getJobNo());
}
// 处理人脸信息
if (!CollectionUtils.isEmpty(request.getFaces())) {
JSONArray facesArray = new JSONArray();
request.getFaces().forEach(face -> {
JSONObject faceJson = new JSONObject();
faceJson.put("faceData", face.getFaceData());
facesArray.add(faceJson);
});
json.put("faces", facesArray);
}
return json;
}
/**
* 解析添加人员响应
*/
private AddPersonResponse parseAddPersonResponse(String json) {
try {
return JSON.parseObject(json, AddPersonResponse.class);
} catch (JSONException e) {
log.error("解析添加人员响应失败: {}", json, e);
throw new HikvisionException("PARSE_ERROR", "添加人员响应解析失败");
}
}
/**
* 批量添加人员信息v1
*
* @param request 批量添加人员请求参数
* @return 批量添加人员响应结果
*/
@Transactional
public BatchAddPersonResponse batchAddPersonV1(BatchAddPersonRequest request) {
// 1. 参数校验
if (request == null || CollectionUtils.isEmpty(request.getPersons())) {
throw new IllegalArgumentException("批量添加人员请求参数不能为空");
}
// 检查数量限制
if (request.getPersons().size() > 1000) {
throw new IllegalArgumentException("单次操作最多支持1000条记录");
}
// 检查clientId唯一性
// long distinctClientIdCount = request.getPersons().stream()
// .filter(person -> person.getClientId() != null)
// .mapToLong(BatchAddPersonRequest.PersonInfo::getClientId)
// .distinct()
// .count();
// long totalClientIdCount = request.getPersons().stream()
// .filter(person -> person.getClientId() != null)
// .count();
// if (distinctClientIdCount != totalClientIdCount) {
// throw new IllegalArgumentException("请求内的每一条数据的clientId必须唯一");
// }
// 2. 构建API路径
String apiPath = properties.getArtemisPath() + "/api/resource/v1/person/batch/add";
// 3. 转换请求体
JSONArray body = convertBatchAddPersonRequestToJSON(request);
// 添加日志便于调试
log.info("批量添加人员请求体: {}", body.toJSONString());
// 4. 发送请求
String responseJson = ArtemisHttpUtil.doPostStringArtemis(
Map.of("https://", apiPath),
body.toJSONString(),
null, null, "application/json", null
);
// 添加日志便于调试
log.info("批量添加人员响应: {}", responseJson);
// 5. 处理响应
BatchAddPersonResponse response = parseBatchAddPersonResponse(responseJson);
if (!"0".equals(response.getCode())) {
throw new HikvisionException(response.getCode(), response.getMsg());
}
return response;
}
/**
* 转换批量添加人员请求为JSON数组
*/
private JSONArray convertBatchAddPersonRequestToJSON(BatchAddPersonRequest request) {
JSONArray jsonArray = new JSONArray();
request.getPersons().forEach(person -> {
JSONObject personJson = new JSONObject();
// 必填字段
personJson.put("personName", person.getPersonName());
personJson.put("orgIndexCode", person.getOrgIndexCode());
// 可选字段
if (person.getClientId() != null) {
personJson.put("clientId", person.getClientId());
}
if (StringUtils.isNotBlank(person.getPersonId())) {
personJson.put("personId", person.getPersonId());
}
if (person.getGender() != null) {
personJson.put("gender", person.getGender());
}
if (StringUtils.isNotBlank(person.getBirthday())) {
personJson.put("birthday", person.getBirthday());
}
if (StringUtils.isNotBlank(person.getPhoneNo())) {
personJson.put("phoneNo", person.getPhoneNo());
}
if (StringUtils.isNotBlank(person.getEmail())) {
personJson.put("email", person.getEmail());
}
if (StringUtils.isNotBlank(person.getCertificateType())) {
personJson.put("certificateType", person.getCertificateType());
}
if (StringUtils.isNotBlank(person.getCertificateNo())) {
personJson.put("certificateNo", person.getCertificateNo());
}
if (StringUtils.isNotBlank(person.getJobNo())) {
personJson.put("jobNo", person.getJobNo());
}
jsonArray.add(personJson);
});
return jsonArray;
}
/**
* 解析批量添加人员响应
*/
private BatchAddPersonResponse parseBatchAddPersonResponse(String json) {
try {
return JSON.parseObject(json, BatchAddPersonResponse.class);
} catch (JSONException e) {
log.error("解析批量添加人员响应失败: {}", json, e);
throw new HikvisionException("PARSE_ERROR", "批量添加人员响应解析失败");
}
}
/**
* 修改人员信息v1
*
* @param request 修改人员请求参数
* @return 修改人员响应结果
*/
@Transactional
public UpdatePersonResponse updatePersonV1(UpdatePersonRequest request) {
// 1. 参数校验
if (request == null) {
throw new IllegalArgumentException("修改人员请求参数不能为空");
}
if (StringUtils.isBlank(request.getPersonId())) {
throw new IllegalArgumentException("人员ID不能为空");
}
// 2. 构建API路径
String apiPath = properties.getArtemisPath() + "/api/resource/v1/person/single/update";
// 3. 转换请求体
JSONObject body = convertUpdatePersonRequestToJSON(request);
// 添加日志便于调试
log.info("修改人员请求体: {}", body.toJSONString());
// 4. 发送请求
String responseJson = ArtemisHttpUtil.doPostStringArtemis(
Map.of("https://", apiPath),
body.toJSONString(),
null, null, "application/json", null
);
// 添加日志便于调试
log.info("修改人员响应: {}", responseJson);
// 5. 处理响应
UpdatePersonResponse response = parseUpdatePersonResponse(responseJson);
if (!"0".equals(response.getCode())) {
throw new HikvisionException(response.getCode(), response.getMsg());
}
return response;
}
/**
* 转换修改人员请求为JSON
*/
private JSONObject convertUpdatePersonRequestToJSON(UpdatePersonRequest request) {
JSONObject json = new JSONObject();
// 必填字段
json.put("personId", request.getPersonId());
// 可选字段 - 只有非空值才会被包含
if (StringUtils.isNotBlank(request.getPersonName())) {
json.put("personName", request.getPersonName());
}
if (StringUtils.isNotBlank(request.getOrgIndexCode())) {
json.put("orgIndexCode", request.getOrgIndexCode());
}
if (request.getGender() != null) {
json.put("gender", request.getGender());
}
if (StringUtils.isNotBlank(request.getBirthday())) {
json.put("birthday", request.getBirthday());
}
if (StringUtils.isNotBlank(request.getPhoneNo())) {
json.put("phoneNo", request.getPhoneNo());
}
if (StringUtils.isNotBlank(request.getEmail())) {
json.put("email", request.getEmail());
}
if (StringUtils.isNotBlank(request.getCertificateType())) {
json.put("certificateType", request.getCertificateType());
}
if (StringUtils.isNotBlank(request.getCertificateNo())) {
json.put("certificateNo", request.getCertificateNo());
}
if (StringUtils.isNotBlank(request.getJobNo())) {
json.put("jobNo", request.getJobNo());
}
return json;
}
/**
* 解析修改人员响应
*/
private UpdatePersonResponse parseUpdatePersonResponse(String json) {
try {
return JSON.parseObject(json, UpdatePersonResponse.class);
} catch (JSONException e) {
log.error("解析修改人员响应失败: {}", json, e);
throw new HikvisionException("PARSE_ERROR", "修改人员响应解析失败");
}
}
/**
* 批量删除人员信息v1
*
* @param request 批量删除人员请求参数
* @return 批量删除人员响应结果
*/
@Transactional
public BatchDeletePersonResponse batchDeletePersonV1(BatchDeletePersonRequest request) {
// 1. 参数校验
if (request == null || CollectionUtils.isEmpty(request.getPersonIds())) {
throw new IllegalArgumentException("批量删除人员请求参数不能为空");
}
// 检查数量限制
if (request.getPersonIds().size() > 1000) {
throw new IllegalArgumentException("单次操作最多支持1000条记录");
}
// 2. 构建API路径
String apiPath = properties.getArtemisPath() + "/api/resource/v1/person/batch/delete";
// 3. 转换请求体
JSONObject body = convertBatchDeletePersonRequestToJSON(request);
// 添加日志便于调试
log.info("批量删除人员请求体: {}", body.toJSONString());
// 4. 发送请求
String responseJson = ArtemisHttpUtil.doPostStringArtemis(
Map.of("https://", apiPath),
body.toJSONString(),
null, null, "application/json", null
);
// 添加日志便于调试
log.info("批量删除人员响应: {}", responseJson);
// 5. 处理响应
BatchDeletePersonResponse response = parseBatchDeletePersonResponse(responseJson);
if (!"0".equals(response.getCode())) {
// 对于批量删除,即使部分失败也可能返回code=0
// 具体的失败信息在data字段中
if (!CollectionUtils.isEmpty(response.getData())) {
log.warn("批量删除人员部分失败,失败记录数: {}", response.getData().size());
} else {
// 完全失败的情况
throw new HikvisionException(response.getCode(), response.getMsg());
}
}
return response;
}
/**
* 转换批量删除人员请求为JSON
*/
private JSONObject convertBatchDeletePersonRequestToJSON(BatchDeletePersonRequest request) {
JSONObject json = new JSONObject();
json.put("personIds", request.getPersonIds());
return json;
}
/**
* 解析批量删除人员响应
*/
private BatchDeletePersonResponse parseBatchDeletePersonResponse(String json) {
try {
return JSON.parseObject(json, BatchDeletePersonResponse.class);
} catch (JSONException e) {
log.error("解析批量删除人员响应失败: {}", json, e);
throw new HikvisionException("PARSE_ERROR", "批量删除人员响应解析失败");
}
}
/**
* 添加人脸信息v1
*
* @param request 添加人脸请求参数
* @return 添加人脸响应结果
*/
@Transactional
public AddFaceResponse addFaceV1(AddFaceRequest request) {
// 1. 参数校验
if (request == null) {
throw new IllegalArgumentException("添加人脸请求参数不能为空");
}
if (StringUtils.isBlank(request.getPersonId())) {
throw new IllegalArgumentException("人员ID不能为空");
}
if (StringUtils.isBlank(request.getFaceData())) {
throw new IllegalArgumentException("人脸图片数据不能为空");
}
// 2. 构建API路径
String apiPath = properties.getArtemisPath() + "/api/resource/v1/face/single/add";
// 3. 转换请求体
JSONObject body = convertAddFaceRequestToJSON(request);
// 添加日志便于调试(注意:人脸数据通常很大,只记录长度)
log.info("添加人脸请求体: personId={}, faceData length={}",
request.getPersonId(), request.getFaceData().length());
// 4. 发送请求
String responseJson = ArtemisHttpUtil.doPostStringArtemis(
Map.of("https://", apiPath),
body.toJSONString(),
null, null, "application/json", null
);
// 添加日志便于调试
log.info("添加人脸响应: {}", responseJson);
// 5. 处理响应
AddFaceResponse response = parseAddFaceResponse(responseJson);
if (!"0".equals(response.getCode())) {
throw new HikvisionException(response.getCode(), response.getMsg());
}
return response;
}
/**
* 转换添加人脸请求为JSON
*/
private JSONObject convertAddFaceRequestToJSON(AddFaceRequest request) {
JSONObject json = new JSONObject();
json.put("personId", request.getPersonId());
json.put("faceData", request.getFaceData());
return json;
}
/**
* 解析添加人脸响应
*/
private AddFaceResponse parseAddFaceResponse(String json) {
try {
return JSON.parseObject(json, AddFaceResponse.class);
} catch (JSONException e) {
log.error("解析添加人脸响应失败: {}", json, e);
throw new HikvisionException("PARSE_ERROR", "添加人脸响应解析失败");
}
}
/**
* 修改人脸信息v1
*
* @param request 修改人脸请求参数
* @return 修改人脸响应结果
*/
@Transactional
public AddFaceResponse updateFaceV1(UpdateFaceRequest request) {
// 1. 参数校验
if (request == null) {
throw new IllegalArgumentException("修改人脸请求参数不能为空");
}
if (StringUtils.isBlank(request.getFaceId())) {
throw new IllegalArgumentException("人脸ID不能为空");
}
if (StringUtils.isBlank(request.getFaceData())) {
throw new IllegalArgumentException("人脸图片数据不能为空");
}
// 2. 构建API路径
String apiPath = properties.getArtemisPath() + "/api/resource/v1/face/single/update";
// 3. 转换请求体
JSONObject body = convertUpdateFaceRequestToJSON(request);
// 添加日志便于调试(注意:人脸数据通常很大,只记录长度)
log.info("修改人脸请求体: faceId={}, faceData length={}",
request.getFaceId(), request.getFaceData().length());
// 4. 发送请求
String responseJson = ArtemisHttpUtil.doPostStringArtemis(
Map.of("https://", apiPath),
body.toJSONString(),
null, null, "application/json", null
);
// 添加日志便于调试
log.info("修改人脸响应: {}", responseJson);
// 5. 处理响应(修改人脸的响应格式和添加人脸相同)
AddFaceResponse response = parseAddFaceResponse(responseJson);
if (!"0".equals(response.getCode())) {
throw new HikvisionException(response.getCode(), response.getMsg());
}
return response;
}
/**
* 删除人脸信息v1
*
* @param request 删除人脸请求参数
* @return 删除人脸响应结果
*/
@Transactional
public DeleteFaceResponse deleteFaceV1(DeleteFaceRequest request) {
// 1. 参数校验
if (request == null) {
throw new IllegalArgumentException("删除人脸请求参数不能为空");
}
if (StringUtils.isBlank(request.getFaceId())) {
throw new IllegalArgumentException("人脸ID不能为空");
}
// 2. 构建API路径
String apiPath = properties.getArtemisPath() + "/api/resource/v1/face/single/delete";
// 3. 转换请求体
JSONObject body = convertDeleteFaceRequestToJSON(request);
// 添加日志便于调试
log.info("删除人脸请求体: faceId={}", request.getFaceId());
// 4. 发送请求
String responseJson = ArtemisHttpUtil.doPostStringArtemis(
Map.of("https://", apiPath),
body.toJSONString(),
null, null, "application/json", null
);
// 添加日志便于调试
log.info("删除人脸响应: {}", responseJson);
// 5. 处理响应
DeleteFaceResponse response = parseDeleteFaceResponse(responseJson);
if (!"0".equals(response.getCode())) {
throw new HikvisionException(response.getCode(), response.getMessage());
}
return response;
}
/**
* 转换修改人脸请求为JSON
*/
private JSONObject convertUpdateFaceRequestToJSON(UpdateFaceRequest request) {
JSONObject json = new JSONObject();
json.put("faceId", request.getFaceId());
json.put("faceData", request.getFaceData());
return json;
}
/**
* 转换删除人脸请求为JSON
*/
private JSONObject convertDeleteFaceRequestToJSON(DeleteFaceRequest request) {
JSONObject json = new JSONObject();
json.put("faceId", request.getFaceId());
return json;
}
/**
* 解析删除人脸响应
*/
private DeleteFaceResponse parseDeleteFaceResponse(String json) {
try {
return JSON.parseObject(json, DeleteFaceResponse.class);
} catch (JSONException e) {
log.error("解析删除人脸响应失败: {}", json, e);
throw new HikvisionException("PARSE_ERROR", "删除人脸响应解析失败");
}
}
/**
* 获取组织下人员列表v2
*
* @param request 获取人员列表请求参数
* @return 获取人员列表响应结果
*/
@Transactional(readOnly = true)
public GetPersonListResponse getPersonListV2(GetPersonListRequest request) {
// 1. 参数校验
if (request == null) {
throw new IllegalArgumentException("获取人员列表请求参数不能为空");
}
if (StringUtils.isBlank(request.getOrgIndexCode())) {
throw new IllegalArgumentException("组织唯一标识码不能为空");
}
if (request.getPageNo() == null || request.getPageNo() <= 0) {
throw new IllegalArgumentException("当前页码需大于0");
}
if (request.getPageSize() == null || request.getPageSize() <= 0 || request.getPageSize() > 1000) {
throw new IllegalArgumentException("每页记录数需大于0且小于等于1000");
}
// 2. 构建API路径
String apiPath = properties.getArtemisPath() + "/api/resource/v2/person/orgIndexCode/personList";
// 3. 转换请求体
JSONObject body = convertGetPersonListRequestToJSON(request);
// 添加日志便于调试
log.info("获取人员列表请求体: {}", body.toJSONString());
// 4. 发送请求
String responseJson = ArtemisHttpUtil.doPostStringArtemis(
Map.of("https://", apiPath),
body.toJSONString(),
null, null, "application/json", null
);
// 添加日志便于调试
log.info("获取人员列表响应: {}", responseJson);
// 5. 处理响应
GetPersonListResponse response = parseGetPersonListResponse(responseJson);
if (!"0".equals(response.getCode())) {
throw new HikvisionException(response.getCode(), response.getMsg());
}
return response;
}
/**
* 转换获取人员列表请求为JSON
*/
private JSONObject convertGetPersonListRequestToJSON(GetPersonListRequest request) {
JSONObject json = new JSONObject();
json.put("orgIndexCode", request.getOrgIndexCode());
json.put("pageNo", request.getPageNo());
json.put("pageSize", request.getPageSize());
return json;
}
/**
* 解析获取人员列表响应
*/
private GetPersonListResponse parseGetPersonListResponse(String json) {
try {
return JSON.parseObject(json, GetPersonListResponse.class);
} catch (JSONException e) {
log.error("解析获取人员列表响应失败: {}", json, e);
throw new HikvisionException("PARSE_ERROR", "获取人员列表响应解析失败");
}
}
/**
* 根据人员唯一字段获取人员详细信息v1
*
* @param request 获取人员详细信息请求参数
* @return 获取人员详细信息响应结果
*/
@Transactional(readOnly = true)
public GetPersonInfoResponse getPersonInfoV1(GetPersonInfoRequest request) {
// 1. 参数校验
if (request == null) {
throw new IllegalArgumentException("获取人员详细信息请求参数不能为空");
}
if (StringUtils.isBlank(request.getParamName())) {
throw new IllegalArgumentException("参数名不能为空");
}
if (CollectionUtils.isEmpty(request.getParamValue())) {
throw new IllegalArgumentException("参数值列表不能为空");
}
if (request.getParamValue().size() > 1000) {
throw new IllegalArgumentException("参数值最多支持1000个");
}
// 2. 构建API路径
String apiPath = properties.getArtemisPath() + "/api/resource/v1/person/condition/personInfo";
// 3. 转换请求体
JSONObject body = convertGetPersonInfoRequestToJSON(request);
// 添加日志便于调试
log.info("获取人员详细信息请求体: {}", body.toJSONString());
// 4. 发送请求
String responseJson = ArtemisHttpUtil.doPostStringArtemis(
Map.of("https://", apiPath),
body.toJSONString(),
null, null, "application/json", null
);
// 添加日志便于调试
log.info("获取人员详细信息响应: {}", responseJson);
// 5. 处理响应
GetPersonInfoResponse response = parseGetPersonInfoResponse(responseJson);
if (!"0".equals(response.getCode())) {
throw new HikvisionException(response.getCode(), response.getMsg());
}
return response;
}
/**
* 转换获取人员详细信息请求为JSON
*/
private JSONObject convertGetPersonInfoRequestToJSON(GetPersonInfoRequest request) {
JSONObject json = new JSONObject();
json.put("paramName", request.getParamName());
json.put("paramValue", request.getParamValue());
return json;
}
/**
* 解析获取人员详细信息响应
*/
private GetPersonInfoResponse parseGetPersonInfoResponse(String json) {
try {
return JSON.parseObject(json, GetPersonInfoResponse.class);
} catch (JSONException e) {
log.error("解析获取人员详细信息响应失败: {}", json, e);
throw new HikvisionException("PARSE_ERROR", "获取人员详细信息响应解析失败");
}
}
}
@@ -128,7 +128,7 @@ hikvision:
app-key: 21470882
app-secret: lYRm5YwBp90qdg5eb0p6
artemis-path: /artemis
person-id: 639f8b57bb6c438e884ae48c5cd535c8
person-id: 1896952011376566273
apis:
person-list: /api/resource/v2/person/personList # 新增人员列表接口
visitor-appointment: /api/visitor/v2/appointment # 新增访客预约接口
@@ -43,6 +43,9 @@ import com.bsd.pjcloud.common.security.annotation.Inner;
import com.bsd.pjcloud.common.security.util.SecurityUtils;
import com.bsd.pjcloud.flow.task.dto.ProcessNodeRecordAssignUserParamDto;
import com.bsd.pjcloud.thirdparty.api.feign.RemoterVisitorService;
import com.bsd.pjcloud.thirdparty.dto.person.BatchAddPersonRequest;
import com.bsd.pjcloud.thirdparty.dto.visitor.PersonInfo;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
@@ -58,6 +61,7 @@ import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -76,6 +80,8 @@ public class SysUserController {
private final SysUserService userService;
private final RemoterVisitorService remoterVisitorService;
/* ************************************* start 回调 start ************************************* */
@Inner(value = false)
@@ -468,4 +474,27 @@ public class SysUserController {
}
return R.ok(true);
}
@GetMapping("/syncHKUser")
@Schema(description = "同步用户到海康")
public R<Boolean> syncHKUser() {
List<SysUser> list = userService.list();
BatchAddPersonRequest batchAddPersonRequest = new BatchAddPersonRequest();
List<PersonInfo> personInfos = new ArrayList<>();
for (SysUser sysUser : list){
PersonInfo personInfo = new PersonInfo();
personInfo.setPersonName(sysUser.getName());
personInfo.setPhoneNo(sysUser.getPhone());
personInfo.setGender(1);
personInfo.setPersonId(sysUser.getUserId().toString());
personInfos.add(personInfo);
}
batchAddPersonRequest.setPersons(personInfos);
remoterVisitorService.batchAddPersonV1(batchAddPersonRequest);
return R.ok(true);
}
}