From edccaca25b8b6bdb582c60cbd2983bc05a4e1ff3 Mon Sep 17 00:00:00 2001
From: liujie <1793218484@qq.com>
Date: 星期一, 13 七月 2026 09:42:57 +0800
Subject: [PATCH] update
---
ruoyi-system/src/main/java/com/ruoyi/system/dto/SysVisitorRecordDetailRequest.java | 4
ruoyi-system/src/main/java/com/ruoyi/system/dto/SysDashboardOverviewRequest.java | 8
ruoyi-system/src/main/resources/mapper/system/SysVisitorRecordMapper.xml | 36 ++
ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/SysApiDashboardController.java | 52 +++
ruoyi-system/src/main/java/com/ruoyi/system/dto/SysVisitorRecordPageRequest.java | 32 +
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysVisitorRecordMapper.java | 5
ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/SysApiVisitorRecordController.java | 2
ruoyi-system/src/main/java/com/ruoyi/system/vo/SysDashboardOverviewVO.java | 10
ruoyi-applet/pom.xml | 8
ruoyi-system/src/main/java/com/ruoyi/system/vo/SysDashboardStatusSummaryVO.java | 6
ruoyi-system/src/main/java/com/ruoyi/system/vo/SysDashboardTrendVO.java | 7
ruoyi-system/src/main/java/com/ruoyi/system/vo/SysVisitorRecordVO.java | 31 ++
ruoyi-system/src/main/java/com/ruoyi/system/vo/SysDashboardRegisterSummaryVO.java | 5
ruoyi-system/src/main/java/com/ruoyi/system/vo/SysDashboardTrendDailyVO.java | 8
ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/HikvisionAccessControlApi.java | 100 +++++++
ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/SysApiVisitorRecordManageController.java | 78 +++++
ruoyi-system/src/main/java/com/ruoyi/system/vo/SysVisitorPassRecordVO.java | 17 +
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/SysEmployeeController.java | 148 ++++++++++
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDashboardServiceImpl.java | 5
ruoyi-system/src/main/java/com/ruoyi/system/vo/SysVisitorRecordDetailVO.java | 91 ++++++
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysVisitorRecordServiceImpl.java | 180 ++++++++++++
ruoyi-system/src/main/resources/mapper/system/SysEmployeeMapper.xml | 5
ruoyi-system/src/main/java/com/ruoyi/system/service/ISysVisitorRecordService.java | 2
23 files changed, 823 insertions(+), 17 deletions(-)
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/SysEmployeeController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/SysEmployeeController.java
index a96b684..5581d0c 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/SysEmployeeController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/SysEmployeeController.java
@@ -17,6 +17,7 @@
import com.ruoyi.system.dto.SysEmployeeUnbindRequest;
import com.ruoyi.system.mapper.SysDoorDeviceMapper;
import com.ruoyi.system.service.ISysEmployeeService;
+import com.ruoyi.system.vo.SysEmployeeVO;
import com.ruoyi.web.controller.tool.HikvisionAccessControlApi;
import com.ruoyi.web.controller.tool.MiddlePlatformDataQuery;
import org.apache.poi.ss.usermodel.Cell;
@@ -40,9 +41,11 @@
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
+import java.util.Set;
/**
* 员工管理接口
@@ -177,7 +180,11 @@
@PostMapping("/delete")
public AjaxResult delete(@RequestBody SysEmployeeDeleteRequest request)
{
- return toAjax(employeeService.delete(request, getUsername()));
+ List<SysEmployeeVO> employees = loadDeleteEmployees(request);
+ Map<String, Object> hikvisionDelete = deleteEmployeesFromHikvision(employees);
+ AjaxResult ajax = toAjax(employeeService.delete(request, getUsername()));
+ ajax.put("hikvisionDelete", hikvisionDelete);
+ return ajax;
}
/**
@@ -232,6 +239,133 @@
/**
* 目的:中台查询异常时返回统一业务错误,避免异常栈直接暴露给前端。
*/
+ private List<SysEmployeeVO> loadDeleteEmployees(SysEmployeeDeleteRequest request)
+ {
+ if (request == null || request.getEmployeeIds() == null || request.getEmployeeIds().isEmpty())
+ {
+ throw new ServiceException("请选择员工");
+ }
+
+ List<SysEmployeeVO> employees = new ArrayList<SysEmployeeVO>();
+ Set<Long> uniqueEmployeeIds = new HashSet<Long>();
+ for (Long employeeId : request.getEmployeeIds())
+ {
+ if (employeeId == null || employeeId <= 0)
+ {
+ throw new ServiceException("员工主键不能为空");
+ }
+ if (!uniqueEmployeeIds.add(employeeId))
+ {
+ continue;
+ }
+ SysEmployeeDetailRequest detailRequest = new SysEmployeeDetailRequest();
+ detailRequest.setEmployeeId(employeeId);
+ employees.add(employeeService.detail(detailRequest));
+ }
+ return employees;
+ }
+
+ private Map<String, Object> deleteEmployeesFromHikvision(List<SysEmployeeVO> employees)
+ {
+ Map<String, Object> result = new LinkedHashMap<String, Object>();
+ result.put("employees", employees.size());
+
+ List<SysDoorDevice> devices = doorDeviceMapper.selectEnabledHikvisionDevices();
+ result.put("total", devices.size());
+ if (devices.isEmpty())
+ {
+ result.put("status", "skipped");
+ result.put("message", "未配置启用的海康门禁设备");
+ return result;
+ }
+
+ String username = readHikvisionConfig("hikvision.access.username", "HIKVISION_ACCESS_USERNAME", "admin");
+ String password = readHikvisionConfig("hikvision.access.password", "HIKVISION_ACCESS_PASSWORD", "");
+ if (StringUtils.isEmpty(password))
+ {
+ result.put("status", "skipped");
+ result.put("message", "未配置海康门禁设备密码");
+ handleHikvisionDeleteFailure(result);
+ return result;
+ }
+
+ List<Map<String, Object>> records = new ArrayList<Map<String, Object>>();
+ int successCount = 0;
+ int totalCount = devices.size() * employees.size();
+ for (SysDoorDevice device : devices)
+ {
+ for (SysEmployeeVO employee : employees)
+ {
+ Map<String, Object> record = deleteEmployeeFromHikvisionDevice(device, employee, username, password);
+ records.add(record);
+ if (Boolean.TRUE.equals(record.get("success")))
+ {
+ successCount++;
+ }
+ }
+ }
+ result.put("success", successCount);
+ result.put("failed", totalCount - successCount);
+ result.put("records", records);
+ result.put("status", successCount == totalCount ? "success" : (successCount == 0 ? "failed" : "partial"));
+ handleHikvisionDeleteFailure(result);
+ return result;
+ }
+
+ private Map<String, Object> deleteEmployeeFromHikvisionDevice(SysDoorDevice device, SysEmployeeVO employee,
+ String username, String password)
+ {
+ Map<String, Object> record = new LinkedHashMap<String, Object>();
+ record.put("doorId", device.getDoorId());
+ record.put("deviceName", device.getDeviceName());
+ record.put("deviceId", device.getDeviceId());
+ record.put("employeeId", employee.getEmployeeId());
+ record.put("employeeNo", employee.getEmployeeNo());
+ record.put("cardNo", employee.getCardNo());
+ try
+ {
+ HikvisionAccessControlApi.DeviceConfig deviceConfig = HikvisionAccessControlApi.DeviceConfig
+ .http(device.getDeviceId(), username, password);
+ deviceConfig.setPort(readHikvisionIntConfig("hikvision.access.port", "HIKVISION_ACCESS_PORT", 80));
+ deviceConfig.setHttps(readHikvisionBooleanConfig("hikvision.access.https", "HIKVISION_ACCESS_HTTPS", false));
+
+ HikvisionAccessControlApi.DeleteResult deleteResult = HikvisionAccessControlApi.deleteEmployee(
+ deviceConfig, buildHikvisionDeleteEmployee(employee));
+ boolean success = isHikvisionDeleteSuccess(deleteResult);
+ record.put("success", success);
+ record.put("result", deleteResult);
+ if (!success)
+ {
+ record.put("message", "海康门禁员工删除部分失败");
+ }
+ }
+ catch (Exception e)
+ {
+ record.put("success", false);
+ record.put("message", e.getMessage());
+ }
+ return record;
+ }
+
+ private HikvisionAccessControlApi.EmployeeCredential buildHikvisionDeleteEmployee(SysEmployeeVO employee)
+ {
+ return HikvisionAccessControlApi.EmployeeCredential.of(
+ employee.getEmployeeNo(), employee.getEmployeeName(), employee.getCardNo());
+ }
+
+ private boolean isHikvisionDeleteSuccess(HikvisionAccessControlApi.DeleteResult result)
+ {
+ return result != null
+ && isHikvisionResultSuccess(result.getUserInfo())
+ && isHikvisionResultSuccess(result.getCard())
+ && isHikvisionResultSuccess(result.getFace());
+ }
+
+ private boolean isHikvisionResultSuccess(HikvisionAccessControlApi.HikvisionResult result)
+ {
+ return result == null || result.isSuccess();
+ }
+
private Map<String, Object> issueEmployeeToHikvision(SysEmployeeAddRequest request)
{
Map<String, Object> result = new LinkedHashMap<String, Object>();
@@ -428,6 +562,18 @@
}
}
+ private void handleHikvisionDeleteFailure(Map<String, Object> result)
+ {
+ if (!readHikvisionBooleanConfig("hikvision.access.fail-on-error", "HIKVISION_ACCESS_FAIL_ON_ERROR", false))
+ {
+ return;
+ }
+ if ("failed".equals(result.get("status")) || "partial".equals(result.get("status")))
+ {
+ throw new ServiceException("海康门禁员工删除失败");
+ }
+ }
+
private AjaxResult middlePlatformError(IOException e)
{
return error("中台数据查询失败:" + e.getMessage());
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/HikvisionAccessControlApi.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/HikvisionAccessControlApi.java
index f864d00..3bbb057 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/HikvisionAccessControlApi.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/HikvisionAccessControlApi.java
@@ -33,6 +33,8 @@
private static final String USER_INFO_SET_UP_PATH = "/ISAPI/AccessControl/UserInfo/SetUp?format=json";
private static final String CARD_INFO_SET_UP_PATH = "/ISAPI/AccessControl/CardInfo/SetUp?format=json";
private static final String FACE_DATA_RECORD_PATH = "/ISAPI/Intelligent/FDLib/FaceDataRecord?format=json";
+ private static final String USER_INFO_DELETE_PATH = "/ISAPI/AccessControl/UserInfo/Delete?format=json";
+ private static final String CARD_INFO_DELETE_PATH = "/ISAPI/AccessControl/CardInfo/Delete?format=json";
private static final MediaType JSON_MEDIA_TYPE = MediaType.parse("application/json; charset=utf-8");
private static final MediaType JPEG_MEDIA_TYPE = MediaType.parse("image/jpeg");
private static final MediaType PNG_MEDIA_TYPE = MediaType.parse("image/png");
@@ -66,6 +68,25 @@
result.setFace(face);
ensureSuccess(face, "绑定员工人脸失败");
}
+ return result;
+ }
+
+ /**
+ * 删除门禁人员,并尽量清理绑定卡和人脸凭据。
+ */
+ public static DeleteResult deleteEmployee(DeviceConfig device, EmployeeCredential employee) throws IOException {
+ Objects.requireNonNull(employee, "employee");
+ requireText(employee.getEmployeeNo(), "employeeNo");
+
+ DeleteResult result = new DeleteResult();
+ if (isNotBlank(employee.getCardNo())) {
+ result.setCard(deleteCard(device, employee.getCardNo()));
+ }
+ result.setFace(deleteFace(device, employee.getEmployeeNo()));
+
+ HikvisionResult userInfo = deleteUserInfo(device, employee.getEmployeeNo());
+ result.setUserInfo(userInfo);
+ ensureSuccess(userInfo, "delete user info failed");
return result;
}
@@ -152,6 +173,53 @@
}
/**
+ * 删除设备端人员基础信息。
+ */
+ public static HikvisionResult deleteUserInfo(DeviceConfig device, String employeeNo) throws IOException {
+ requireDevice(device);
+ requireText(employeeNo, "employeeNo");
+
+ JSONObject employeeNoItem = new JSONObject(true);
+ employeeNoItem.put("employeeNo", employeeNo);
+
+ JSONObject userInfoDelCond = new JSONObject(true);
+ userInfoDelCond.put("EmployeeNoList", singletonList(employeeNoItem));
+
+ JSONObject body = new JSONObject(true);
+ body.put("UserInfoDelCond", userInfoDelCond);
+ return executeJson(device, "DELETE", USER_INFO_DELETE_PATH, body);
+ }
+
+ public static HikvisionResult deleteCard(DeviceConfig device, String cardNo) throws IOException {
+ requireDevice(device);
+ requireText(cardNo, "cardNo");
+
+ JSONObject cardNoItem = new JSONObject(true);
+ cardNoItem.put("cardNo", cardNo);
+
+ JSONObject cardInfoDelCond = new JSONObject(true);
+ cardInfoDelCond.put("CardNoList", singletonList(cardNoItem));
+
+ JSONObject body = new JSONObject(true);
+ body.put("CardInfoDelCond", cardInfoDelCond);
+ return executeJson(device, "DELETE", CARD_INFO_DELETE_PATH, body);
+ }
+
+ public static HikvisionResult deleteFace(DeviceConfig device, String employeeNo) throws IOException {
+ requireDevice(device);
+ requireText(employeeNo, "employeeNo");
+
+ JSONObject faceData = new JSONObject(true);
+ faceData.put("faceLibType", "blackFD");
+ faceData.put("FDID", "1");
+ faceData.put("FPID", employeeNo);
+
+ JSONObject body = new JSONObject(true);
+ body.put("FaceDataRecord", faceData);
+ return executeJson(device, "DELETE", FACE_DATA_RECORD_PATH, body);
+ }
+
+ /**
* 通过图片 URL 下载人脸并绑定到员工。
*/
public static HikvisionResult bindFaceByUrl(DeviceConfig device, String employeeNo, String faceImageUrl) throws IOException {
@@ -179,6 +247,8 @@
.header("Accept", "application/json");
if ("POST".equals(method)) {
builder.post(requestBody);
+ } else if ("DELETE".equals(method)) {
+ builder.delete(requestBody);
} else {
builder.put(requestBody);
}
@@ -668,6 +738,36 @@
}
}
+ public static final class DeleteResult {
+ private HikvisionResult userInfo;
+ private HikvisionResult card;
+ private HikvisionResult face;
+
+ public HikvisionResult getUserInfo() {
+ return userInfo;
+ }
+
+ public void setUserInfo(HikvisionResult userInfo) {
+ this.userInfo = userInfo;
+ }
+
+ public HikvisionResult getCard() {
+ return card;
+ }
+
+ public void setCard(HikvisionResult card) {
+ this.card = card;
+ }
+
+ public HikvisionResult getFace() {
+ return face;
+ }
+
+ public void setFace(HikvisionResult face) {
+ this.face = face;
+ }
+ }
+
public static final class IssueResult {
private HikvisionResult userInfo;
private HikvisionResult card;
diff --git a/ruoyi-applet/pom.xml b/ruoyi-applet/pom.xml
index 335f596..4decb47 100644
--- a/ruoyi-applet/pom.xml
+++ b/ruoyi-applet/pom.xml
@@ -71,6 +71,12 @@
<!-- </exclusions>-->
</dependency>
+ <!-- 系统模块-->
+ <dependency>
+ <groupId>com.ruoyi</groupId>
+ <artifactId>ruoyi-system</artifactId>
+ </dependency>
+
<!-- 定时任务-->
<dependency>
<groupId>com.ruoyi</groupId>
@@ -202,4 +208,4 @@
<finalName>${project.artifactId}</finalName>
</build>
-</project>
\ No newline at end of file
+</project>
diff --git a/ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/SysApiDashboardController.java b/ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/SysApiDashboardController.java
new file mode 100644
index 0000000..b886ae5
--- /dev/null
+++ b/ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/SysApiDashboardController.java
@@ -0,0 +1,52 @@
+package com.ruoyi.web.controller.api;
+
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.system.dto.SysDashboardOverviewRequest;
+import com.ruoyi.system.service.ISysDashboardService;
+import com.ruoyi.system.vo.SysDashboardOverviewVO;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiResponse;
+import io.swagger.annotations.ApiResponses;
+import org.springframework.beans.factory.annotation.Autowired;
+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;
+
+/**
+ * 首页数据总览接口
+ *
+ * @author ruoyi
+ */
+@RestController
+@RequestMapping("/api/dashboard")
+@Api(tags = "首页数据总览")
+public class SysApiDashboardController extends BaseController
+{
+ @Autowired
+ private ISysDashboardService dashboardService;
+
+ /**
+ * 查询首页数据总览
+ */
+ @ApiOperation(
+ value = "查询首页数据总览",
+ notes = "返回线上预约、现场登记、访客状态和进出场趋势统计数据",
+ response = SysDashboardOverviewVO.class
+ )
+ @ApiResponses({
+ @ApiResponse(
+ code = 200,
+ message = "成功",
+ response = AjaxResult.class,
+ responseContainer = "Data"
+ )
+ })
+ @PostMapping("/overview")
+ public AjaxResult<SysDashboardOverviewVO> overview(@RequestBody(required = false) SysDashboardOverviewRequest request)
+ {
+ return success(dashboardService.overview(request));
+ }
+}
diff --git a/ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/SysApiVisitorRecordController.java b/ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/SysApiVisitorRecordController.java
index 75eb549..916a734 100644
--- a/ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/SysApiVisitorRecordController.java
+++ b/ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/SysApiVisitorRecordController.java
@@ -83,7 +83,7 @@
}
- @PostMapping("/add")
+ @PostMapping("/add1")
@ApiOperation(value = "身份证签离", notes = "身份证签离")
public AjaxResult idCardOut(
@RequestBody
diff --git a/ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/SysApiVisitorRecordManageController.java b/ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/SysApiVisitorRecordManageController.java
new file mode 100644
index 0000000..d9dacb0
--- /dev/null
+++ b/ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/SysApiVisitorRecordManageController.java
@@ -0,0 +1,78 @@
+package com.ruoyi.web.controller.api;
+
+import com.ruoyi.common.basic.PageInfo;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.system.dto.SysVisitorRecordDetailRequest;
+import com.ruoyi.system.dto.SysVisitorRecordPageRequest;
+import com.ruoyi.system.service.ISysVisitorRecordService;
+import com.ruoyi.system.vo.SysVisitorRecordDetailVO;
+import com.ruoyi.system.vo.SysVisitorRecordVO;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiResponse;
+import io.swagger.annotations.ApiResponses;
+import org.springframework.beans.factory.annotation.Autowired;
+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;
+
+/**
+ * 管理侧访客记录接口
+ *
+ * @author ruoyi
+ */
+@RestController
+@RequestMapping("/api/visitorRecord")
+@Api(tags = "管理侧访客记录")
+public class SysApiVisitorRecordManageController extends BaseController
+{
+ @Autowired
+ private ISysVisitorRecordService visitorRecordService;
+
+ /**
+ * 分页查询访客记录
+ */
+ @ApiOperation(
+ value = "分页查询访客记录",
+ notes = "按访客、被访人、部门、访问区域、来访事由、有效期筛选访客记录",
+ response = SysVisitorRecordVO.class,
+ responseContainer = "Page"
+ )
+ @ApiResponses({
+ @ApiResponse(
+ code = 200,
+ message = "成功",
+ response = AjaxResult.class,
+ responseContainer = "Page"
+ )
+ })
+ @PostMapping("/page")
+ public AjaxResult<PageInfo<SysVisitorRecordVO>> page(@RequestBody(required = false) SysVisitorRecordPageRequest request)
+ {
+ return success(visitorRecordService.pageList(request));
+ }
+
+ /**
+ * 查询访客记录详情
+ */
+ @ApiOperation(
+ value = "查询访客记录详情",
+ notes = "返回访客信息、被访者信息、访问权限、签离记录和通行明细",
+ response = SysVisitorRecordDetailVO.class
+ )
+ @ApiResponses({
+ @ApiResponse(
+ code = 200,
+ message = "成功",
+ response = AjaxResult.class,
+ responseContainer = "Data"
+ )
+ })
+ @PostMapping("/detail")
+ public AjaxResult<SysVisitorRecordDetailVO> detail(@RequestBody SysVisitorRecordDetailRequest request)
+ {
+ return success(visitorRecordService.detail(request));
+ }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/dto/SysDashboardOverviewRequest.java b/ruoyi-system/src/main/java/com/ruoyi/system/dto/SysDashboardOverviewRequest.java
index e0b4b78..6fcccdd 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/dto/SysDashboardOverviewRequest.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/dto/SysDashboardOverviewRequest.java
@@ -1,6 +1,7 @@
package com.ruoyi.system.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@@ -12,19 +13,20 @@
* @author ruoyi
*/
@Data
+@ApiModel(value = "SysDashboardOverviewRequest", description = "首页数据总览查询请求")
public class SysDashboardOverviewRequest
{
/** 统计周期:TODAY今日 RECENT_7_DAYS最近7天 RECENT_30_DAYS最近30天 */
- @ApiModelProperty("统计周期:TODAY今日 RECENT_7_DAYS最近7天 RECENT_30_DAYS最近30天")
+ @ApiModelProperty(value = "统计周期:TODAY今日,RECENT_7_DAYS最近7天,RECENT_30_DAYS最近30天;为空默认最近7天", example = "RECENT_7_DAYS")
private String periodType;
/** 自定义开始时间 */
- @ApiModelProperty("自定义开始时间")
+ @ApiModelProperty(value = "自定义开始时间;beginTime 与 endTime 同时传入且 endTime 晚于 beginTime 时生效", example = "2025-06-01 00:00:00")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date beginTime;
/** 自定义结束时间 */
- @ApiModelProperty("自定义结束时间")
+ @ApiModelProperty(value = "自定义结束时间;统计区间为左闭右开,即包含 beginTime,不包含 endTime", example = "2025-07-01 00:00:00")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date endTime;
}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/dto/SysVisitorRecordDetailRequest.java b/ruoyi-system/src/main/java/com/ruoyi/system/dto/SysVisitorRecordDetailRequest.java
index 970bec5..60f99dc 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/dto/SysVisitorRecordDetailRequest.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/dto/SysVisitorRecordDetailRequest.java
@@ -1,5 +1,6 @@
package com.ruoyi.system.dto;
+import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@@ -9,9 +10,10 @@
* @author ruoyi
*/
@Data
+@ApiModel(value = "SysVisitorRecordDetailRequest", description = "管理侧访客记录详情查询请求")
public class SysVisitorRecordDetailRequest
{
/** 访客登记记录主键 */
- @ApiModelProperty("访客登记记录主键")
+ @ApiModelProperty(value = "访客登记记录主键", required = true, example = "1")
private Long recordId;
}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/dto/SysVisitorRecordPageRequest.java b/ruoyi-system/src/main/java/com/ruoyi/system/dto/SysVisitorRecordPageRequest.java
index 33beab6..d02a4d3 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/dto/SysVisitorRecordPageRequest.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/dto/SysVisitorRecordPageRequest.java
@@ -2,6 +2,7 @@
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.core.domain.BasePage;
+import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
@@ -15,43 +16,56 @@
*/
@Data
@EqualsAndHashCode(callSuper = true)
+@ApiModel(value = "SysVisitorRecordPageRequest", description = "管理侧访客记录分页查询请求")
public class SysVisitorRecordPageRequest extends BasePage
{
/** 被访人 */
- @ApiModelProperty("被访人")
+ @ApiModelProperty(value = "被访人姓名,支持模糊查询", example = "李维")
private String intervieweeName;
+ /** 被访人关键字:姓名 */
+ @ApiModelProperty(value = "被访人关键字,等同于被访人姓名模糊查询", example = "李")
+ private String intervieweeKeyword;
+
/** 被访人部门 */
- @ApiModelProperty("被访人部门")
+ @ApiModelProperty(value = "被访人部门名称", example = "安全部")
private String intervieweeDept;
/** 访问区域ID */
- @ApiModelProperty("访问区域ID")
+ @ApiModelProperty(value = "访问区域ID,按区域树节点筛选", example = "1001")
private Long areaId;
+ /** 访问区域关键字:区域/楼层 */
+ @ApiModelProperty(value = "访问区域关键字,支持区域名称或楼层模糊查询", example = "A区域")
+ private String visitAreaKeyword;
+
/** 有效期开始时间 */
- @ApiModelProperty("有效期开始时间")
+ @ApiModelProperty(value = "来访时间范围开始时间,筛选与有效期有交集的记录", example = "2025-06-01 00:00:00")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date validStartTime;
/** 有效期结束时间 */
- @ApiModelProperty("有效期结束时间")
+ @ApiModelProperty(value = "来访时间范围结束时间,筛选与有效期有交集的记录", example = "2025-06-30 23:59:59")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date validEndTime;
/** 状态 */
- @ApiModelProperty("状态")
+ @ApiModelProperty(value = "访客状态:VISITING来访中,SIGNED_OUT已签离,PENDING_CONFIRM逾期滞留,OVERDUE_AUTO_SIGNED_OUT超期自动,CANCELLED已取消", example = "VISITING")
private String status;
/** 访客 */
- @ApiModelProperty("访客")
+ @ApiModelProperty(value = "访客姓名,支持模糊查询", example = "王丽白")
private String visitorName;
+ /** 访客关键字:姓名/证件号 */
+ @ApiModelProperty(value = "访客关键字,支持访客姓名或证件号模糊查询", example = "510151")
+ private String visitorKeyword;
+
/** 来访事由 */
- @ApiModelProperty("来访事由")
+ @ApiModelProperty(value = "来访事由", example = "商务洽谈")
private String visitReason;
/** 登记类型 */
- @ApiModelProperty("登记类型")
+ @ApiModelProperty(value = "登记类型:APPOINTMENT预约登记,ONSITE现场登记", example = "APPOINTMENT")
private String registerType;
}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysVisitorRecordMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysVisitorRecordMapper.java
index 6b3f50b..2978fec 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysVisitorRecordMapper.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysVisitorRecordMapper.java
@@ -10,6 +10,7 @@
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
+import java.util.Date;
import java.util.List;
/**
@@ -27,6 +28,10 @@
public List<SysVisitorPassRecordVO> selectPassRecordsByRecordId(Long recordId);
+ public int updateExpiredToAutoSignedOut(@Param("now") Date now);
+
+ public int updateVisitingToOverdue(@Param("now") Date now);
+
public int deleteByIds(@Param("recordIds") List<Long> recordIds, @Param("updateBy") String updateBy);
public int insert(SysVisitorRecord record);
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysVisitorRecordService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysVisitorRecordService.java
index 24e2dd1..6343cad 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysVisitorRecordService.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysVisitorRecordService.java
@@ -18,5 +18,7 @@
public SysVisitorRecordDetailVO detail(SysVisitorRecordDetailRequest request);
+ public int refreshVisitorStatus();
+
public int delete(SysVisitorRecordDeleteRequest request, String username);
}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDashboardServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDashboardServiceImpl.java
index 0abc86c..fe539d4 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDashboardServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDashboardServiceImpl.java
@@ -5,6 +5,7 @@
import com.ruoyi.system.dto.SysDashboardOverviewRequest;
import com.ruoyi.system.mapper.SysDashboardMapper;
import com.ruoyi.system.service.ISysDashboardService;
+import com.ruoyi.system.service.ISysVisitorRecordService;
import com.ruoyi.system.vo.SysDashboardOverviewVO;
import com.ruoyi.system.vo.SysDashboardRegisterSummaryVO;
import com.ruoyi.system.vo.SysDashboardStatusSummaryVO;
@@ -44,9 +45,13 @@
@Autowired
private SysDashboardMapper dashboardMapper;
+ @Autowired
+ private ISysVisitorRecordService visitorRecordService;
+
@Override
public SysDashboardOverviewVO overview(SysDashboardOverviewRequest request)
{
+ visitorRecordService.refreshVisitorStatus();
DateRange range = resolveDateRange(request);
SysDashboardOverviewVO overview = new SysDashboardOverviewVO();
overview.setPeriodType(range.getPeriodType());
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysVisitorRecordServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysVisitorRecordServiceImpl.java
index ccb4e51..98fe869 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysVisitorRecordServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysVisitorRecordServiceImpl.java
@@ -2,6 +2,7 @@
import com.ruoyi.common.basic.PageInfo;
import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.dto.SysVisitorRecordDeleteRequest;
import com.ruoyi.system.dto.SysVisitorRecordDetailRequest;
@@ -12,8 +13,14 @@
import com.ruoyi.system.vo.SysVisitorRecordVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.util.Date;
+import java.util.ArrayList;
import java.util.List;
/**
@@ -30,11 +37,15 @@
@Override
public PageInfo<SysVisitorRecordVO> pageList(SysVisitorRecordPageRequest request)
{
+ refreshVisitorStatus();
SysVisitorRecordPageRequest query = request == null ? new SysVisitorRecordPageRequest() : request;
query.setIntervieweeName(StringUtils.trim(query.getIntervieweeName()));
+ query.setIntervieweeKeyword(StringUtils.trim(query.getIntervieweeKeyword()));
query.setIntervieweeDept(StringUtils.trim(query.getIntervieweeDept()));
+ query.setVisitAreaKeyword(StringUtils.trim(query.getVisitAreaKeyword()));
query.setStatus(StringUtils.trim(query.getStatus()));
query.setVisitorName(StringUtils.trim(query.getVisitorName()));
+ query.setVisitorKeyword(StringUtils.trim(query.getVisitorKeyword()));
query.setVisitReason(StringUtils.trim(query.getVisitReason()));
query.setRegisterType(StringUtils.trim(query.getRegisterType()));
PageInfo<SysVisitorRecordVO> pageInfo = new PageInfo<SysVisitorRecordVO>(query.getPageNum(), query.getPageSize());
@@ -46,6 +57,7 @@
@Override
public SysVisitorRecordDetailVO detail(SysVisitorRecordDetailRequest request)
{
+ refreshVisitorStatus();
Long recordId = getRequiredRecordId(request == null ? null : request.getRecordId());
SysVisitorRecordDetailVO detail = visitorRecordMapper.selectDetailById(recordId);
if (detail == null)
@@ -53,7 +65,18 @@
throw new ServiceException("访客登记记录不存在");
}
detail.setPassRecords(visitorRecordMapper.selectPassRecordsByRecordId(recordId));
+ fillDetailDisplayFields(detail);
return detail;
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public int refreshVisitorStatus()
+ {
+ Date now = new Date();
+ int autoSignedOutRows = visitorRecordMapper.updateExpiredToAutoSignedOut(now);
+ int overdueRows = visitorRecordMapper.updateVisitingToOverdue(now);
+ return autoSignedOutRows + overdueRows;
}
@Override
@@ -71,6 +94,163 @@
return visitorRecordMapper.deleteByIds(recordIds, username);
}
+ private void fillDetailDisplayFields(SysVisitorRecordDetailVO detail)
+ {
+ detail.setIdCardMask(maskIdCard(detail.getIdCard()));
+ detail.setRegisterTypeName(registerTypeName(detail.getRegisterType()));
+ detail.setStatusName(statusName(detail.getStatus()));
+ detail.setReceiverVerifyMethodName(verifyMethodName(detail.getReceiverVerifyMethod()));
+ detail.setSignVerifyMethodName(verifyMethodName(detail.getSignVerifyMethod()));
+ detail.setVisitAreaNameList(splitNames(detail.getVisitAreaNames()));
+ detail.setValidTimeText(validTimeText(detail.getValidStartTime(), detail.getValidEndTime()));
+ detail.setRegisterCollectTime(detail.getRegisterTime());
+ detail.setSignCollectTime(detail.getSignTime());
+ }
+
+ private String maskIdCard(String idCard)
+ {
+ if (StringUtils.isBlank(idCard) || idCard.length() <= 10)
+ {
+ return idCard;
+ }
+ return idCard.substring(0, 6) + "********" + idCard.substring(idCard.length() - 4);
+ }
+
+ private List<String> splitNames(String names)
+ {
+ List<String> result = new ArrayList<>();
+ if (StringUtils.isBlank(names))
+ {
+ return result;
+ }
+ String[] splitNames = names.split(",");
+ for (String name : splitNames)
+ {
+ String trimName = StringUtils.trim(name);
+ if (StringUtils.isNotBlank(trimName))
+ {
+ result.add(trimName);
+ }
+ }
+ return result;
+ }
+
+ private String registerTypeName(String registerType)
+ {
+ if ("APPOINTMENT".equals(registerType))
+ {
+ return "预约登记";
+ }
+ if ("ONSITE".equals(registerType))
+ {
+ return "现场登记";
+ }
+ return registerType;
+ }
+
+ private String statusName(String status)
+ {
+ if ("VISITING".equals(status))
+ {
+ return "来访中";
+ }
+ if ("SIGNED_OUT".equals(status))
+ {
+ return "已签离";
+ }
+ if ("PENDING_CONFIRM".equals(status))
+ {
+ return "逾期滞留";
+ }
+ if ("OVERDUE_AUTO_SIGNED_OUT".equals(status))
+ {
+ return "超期自动";
+ }
+ if ("CANCELLED".equals(status))
+ {
+ return "已取消";
+ }
+ return status;
+ }
+
+ private String verifyMethodName(String verifyMethod)
+ {
+ if (StringUtils.isBlank(verifyMethod) || StringUtils.containsAny(verifyMethod, "验证", "确认", "自动"))
+ {
+ return verifyMethod;
+ }
+ if ("FACE".equals(verifyMethod) || "FACE_VERIFY".equals(verifyMethod) || "FACE_RECOGNITION".equals(verifyMethod))
+ {
+ return "人脸验证";
+ }
+ if ("CARD".equals(verifyMethod) || "CARD_VERIFY".equals(verifyMethod))
+ {
+ return "刷卡验证";
+ }
+ if ("ID_CARD".equals(verifyMethod))
+ {
+ return "身份证验证";
+ }
+ if ("MANUAL".equals(verifyMethod))
+ {
+ return "人工确认";
+ }
+ if ("AUTO".equals(verifyMethod))
+ {
+ return "系统自动";
+ }
+ return verifyMethod;
+ }
+
+ private String validTimeText(Date validStartTime, Date validEndTime)
+ {
+ if (validStartTime == null || validEndTime == null)
+ {
+ return null;
+ }
+ LocalDateTime start = DateUtils.dateToLocalDateTime(validStartTime);
+ LocalDateTime end = DateUtils.dateToLocalDateTime(validEndTime);
+ LocalDate startDate = start.toLocalDate();
+ LocalDate endDate = end.toLocalDate();
+ if (startDate.equals(endDate))
+ {
+ return DateUtils.localDateToString(startDate) + " " + dayPartName(start.toLocalTime(), end.toLocalTime());
+ }
+ if (isDayStart(start.toLocalTime()) && isDayEnd(end.toLocalTime()))
+ {
+ return DateUtils.localDateToString(startDate) + " 至 " + DateUtils.localDateToString(endDate) + " 全天";
+ }
+ return DateUtils.parseDateToStr("yyyy-MM-dd HH:mm", validStartTime)
+ + " 至 " + DateUtils.parseDateToStr("yyyy-MM-dd HH:mm", validEndTime);
+ }
+
+ private String dayPartName(LocalTime start, LocalTime end)
+ {
+ if (isDayStart(start) && isDayEnd(end))
+ {
+ return "全天";
+ }
+ if (start.getHour() < 12 && end.getHour() <= 12)
+ {
+ return "上午";
+ }
+ if (start.getHour() >= 12)
+ {
+ return "下午";
+ }
+ return "全天";
+ }
+
+ private boolean isDayStart(LocalTime time)
+ {
+ return time.getHour() == 0 && time.getMinute() == 0;
+ }
+
+ private boolean isDayEnd(LocalTime time)
+ {
+ return time.getHour() == 23 && time.getMinute() == 59;
+ }
+
private Long getRequiredRecordId(Long recordId)
{
if (recordId == null || recordId <= 0)
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/vo/SysDashboardOverviewVO.java b/ruoyi-system/src/main/java/com/ruoyi/system/vo/SysDashboardOverviewVO.java
index 7ca0eb1..b7e40fe 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/vo/SysDashboardOverviewVO.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/vo/SysDashboardOverviewVO.java
@@ -1,6 +1,8 @@
package com.ruoyi.system.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
@@ -11,28 +13,36 @@
* @author ruoyi
*/
@Data
+@ApiModel(value = "SysDashboardOverviewVO", description = "首页数据总览返回对象")
public class SysDashboardOverviewVO
{
/** 当前统计周期 */
+ @ApiModelProperty("当前统计周期:TODAY今日 RECENT_7_DAYS最近7天 RECENT_30_DAYS最近30天 CUSTOM自定义")
private String periodType;
/** 统计开始时间 */
+ @ApiModelProperty("统计开始时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date beginTime;
/** 统计结束时间 */
+ @ApiModelProperty("统计结束时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date endTime;
/** 线上预约统计 */
+ @ApiModelProperty("线上预约板块统计")
private SysDashboardRegisterSummaryVO onlineAppointment;
/** 现场登记统计 */
+ @ApiModelProperty("现场预约板块统计")
private SysDashboardRegisterSummaryVO onsiteAppointment;
/** 访客状态统计 */
+ @ApiModelProperty("访客实时状态统计")
private SysDashboardStatusSummaryVO statusSummary;
/** 登记趋势 */
+ @ApiModelProperty("进出场趋势统计")
private SysDashboardTrendVO trend;
}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/vo/SysDashboardRegisterSummaryVO.java b/ruoyi-system/src/main/java/com/ruoyi/system/vo/SysDashboardRegisterSummaryVO.java
index 36d1b13..37834b8 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/vo/SysDashboardRegisterSummaryVO.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/vo/SysDashboardRegisterSummaryVO.java
@@ -1,5 +1,7 @@
package com.ruoyi.system.vo;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
@@ -8,11 +10,14 @@
* @author ruoyi
*/
@Data
+@ApiModel(value = "SysDashboardRegisterSummaryVO", description = "首页登记统计返回对象")
public class SysDashboardRegisterSummaryVO
{
/** 登记数 */
+ @ApiModelProperty("预约或登记数量")
private Long registerCount;
/** 来访车辆数 */
+ @ApiModelProperty("来访车辆数量")
private Long vehicleCount;
}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/vo/SysDashboardStatusSummaryVO.java b/ruoyi-system/src/main/java/com/ruoyi/system/vo/SysDashboardStatusSummaryVO.java
index d67dcb7..a20f4f5 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/vo/SysDashboardStatusSummaryVO.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/vo/SysDashboardStatusSummaryVO.java
@@ -1,5 +1,7 @@
package com.ruoyi.system.vo;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
@@ -8,14 +10,18 @@
* @author ruoyi
*/
@Data
+@ApiModel(value = "SysDashboardStatusSummaryVO", description = "首页访客状态统计返回对象")
public class SysDashboardStatusSummaryVO
{
/** 来访中数量 */
+ @ApiModelProperty("来访中数量")
private Long visitingCount;
/** 已签离数量 */
+ @ApiModelProperty("已签离数量,包含正常签离和超期自动签离")
private Long signedOutCount;
/** 逾期滞留数量 */
+ @ApiModelProperty("逾期滞留数量,超过有效期但尚未到当天23:59:59自动签离的访客")
private Long overdueCount;
}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/vo/SysDashboardTrendDailyVO.java b/ruoyi-system/src/main/java/com/ruoyi/system/vo/SysDashboardTrendDailyVO.java
index 08746cf..aa739d9 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/vo/SysDashboardTrendDailyVO.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/vo/SysDashboardTrendDailyVO.java
@@ -1,5 +1,7 @@
package com.ruoyi.system.vo;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
@@ -8,20 +10,26 @@
* @author ruoyi
*/
@Data
+@ApiModel(value = "SysDashboardTrendDailyVO", description = "首页每日趋势查询结果")
public class SysDashboardTrendDailyVO
{
/** 日期,格式 yyyy-MM-dd */
+ @ApiModelProperty("日期,格式yyyy-MM-dd")
private String trendDate;
/** 日期标签,格式 MM-dd */
+ @ApiModelProperty("日期标签,格式MM-dd")
private String label;
/** 现场登记数 */
+ @ApiModelProperty("现场登记数")
private Long onsiteCount;
/** 预约登记数 */
+ @ApiModelProperty("预约登记数")
private Long appointmentCount;
/** 来访车辆数 */
+ @ApiModelProperty("来访车辆数")
private Long vehicleCount;
}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/vo/SysDashboardTrendVO.java b/ruoyi-system/src/main/java/com/ruoyi/system/vo/SysDashboardTrendVO.java
index f287146..2bd83d1 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/vo/SysDashboardTrendVO.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/vo/SysDashboardTrendVO.java
@@ -1,5 +1,7 @@
package com.ruoyi.system.vo;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
@@ -10,17 +12,22 @@
* @author ruoyi
*/
@Data
+@ApiModel(value = "SysDashboardTrendVO", description = "首页趋势统计返回对象")
public class SysDashboardTrendVO
{
/** 日期标签 */
+ @ApiModelProperty("日期标签列表,格式MM-dd,与各趋势数组下标一一对应")
private List<String> labels;
/** 现场登记趋势 */
+ @ApiModelProperty("现场登记趋势数组,与labels下标一一对应")
private List<Long> onsite;
/** 预约登记趋势 */
+ @ApiModelProperty("预约登记趋势数组,与labels下标一一对应")
private List<Long> appointment;
/** 来访车辆趋势 */
+ @ApiModelProperty("来访车辆趋势数组,与labels下标一一对应")
private List<Long> vehicle;
}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/vo/SysVisitorPassRecordVO.java b/ruoyi-system/src/main/java/com/ruoyi/system/vo/SysVisitorPassRecordVO.java
index 17a1f0c..c00c680 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/vo/SysVisitorPassRecordVO.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/vo/SysVisitorPassRecordVO.java
@@ -1,6 +1,8 @@
package com.ruoyi.system.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
@@ -11,20 +13,35 @@
* @author ruoyi
*/
@Data
+@ApiModel(value = "SysVisitorPassRecordVO", description = "访客通行明细返回对象")
public class SysVisitorPassRecordVO
{
+ /** 通行明细主键 */
+ @ApiModelProperty("通行明细主键")
private Long passId;
+ /** 访客登记记录主键 */
+ @ApiModelProperty("访客登记记录主键")
private Long recordId;
+ /** 通行类型:IN进场 OUT出场 */
+ @ApiModelProperty("通行类型:IN进场 OUT出场")
private String passType;
+ /** 通行时间 */
+ @ApiModelProperty("通行时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date passTime;
+ /** 门禁设备名称 */
+ @ApiModelProperty("门禁设备名称")
private String doorDeviceName;
+ /** 门禁设备编号 */
+ @ApiModelProperty("门禁设备编号")
private String doorDeviceCode;
+ /** 门禁抓拍图片地址 */
+ @ApiModelProperty("门禁抓拍图片地址")
private String captureImageUrl;
}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/vo/SysVisitorRecordDetailVO.java b/ruoyi-system/src/main/java/com/ruoyi/system/vo/SysVisitorRecordDetailVO.java
index e90110e..74bd25b 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/vo/SysVisitorRecordDetailVO.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/vo/SysVisitorRecordDetailVO.java
@@ -1,6 +1,8 @@
package com.ruoyi.system.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
@@ -12,59 +14,148 @@
* @author ruoyi
*/
@Data
+@ApiModel(value = "SysVisitorRecordDetailVO", description = "管理侧访客记录详情返回对象")
public class SysVisitorRecordDetailVO
{
+ /** 访客登记记录主键 */
+ @ApiModelProperty("访客登记记录主键")
private Long recordId;
+ /** 登记编号 */
+ @ApiModelProperty("登记编号")
private String registerNo;
+ /** 访客姓名 */
+ @ApiModelProperty("访客姓名")
private String visitorName;
+ /** 访客证件号 */
+ @ApiModelProperty("访客证件号")
private String idCard;
+ /** 脱敏后的访客证件号 */
+ @ApiModelProperty("脱敏后的访客证件号")
+ private String idCardMask;
+
+ /** 登记类型:APPOINTMENT预约登记 ONSITE现场登记 */
+ @ApiModelProperty("登记类型:APPOINTMENT预约登记 ONSITE现场登记")
private String registerType;
+ /** 登记类型名称 */
+ @ApiModelProperty("登记类型名称")
+ private String registerTypeName;
+
+ /** 被访人 */
+ @ApiModelProperty("被访人")
private String intervieweeName;
+ /** 被访人部门 */
+ @ApiModelProperty("被访人部门")
private String intervieweeDept;
+ /** 登记接待人 */
+ @ApiModelProperty("登记接待人")
private String receiverName;
+ /** 接待人验证方式编码 */
+ @ApiModelProperty("接待人验证方式编码")
private String receiverVerifyMethod;
+ /** 接待人验证方式名称 */
+ @ApiModelProperty("接待人验证方式名称")
+ private String receiverVerifyMethodName;
+
+ /** 访问区域ID,英文逗号分隔 */
+ @ApiModelProperty("访问区域ID,英文逗号分隔")
private String visitAreaIds;
+ /** 访问区域名称,英文逗号分隔 */
+ @ApiModelProperty("访问区域名称,英文逗号分隔")
private String visitAreaNames;
+ /** 访问区域名称列表 */
+ @ApiModelProperty("访问区域名称列表")
+ private List<String> visitAreaNameList;
+
+ /** 车牌号 */
+ @ApiModelProperty("车牌号")
private String plateNo;
+ /** 来访事由 */
+ @ApiModelProperty("来访事由")
private String visitReason;
+ /** 有效期开始时间 */
+ @ApiModelProperty("有效期开始时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date validStartTime;
+ /** 有效期结束时间 */
+ @ApiModelProperty("有效期结束时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date validEndTime;
+ /** 访客状态:VISITING来访中 SIGNED_OUT已签离 PENDING_CONFIRM逾期滞留 OVERDUE_AUTO_SIGNED_OUT超期自动 CANCELLED已取消 */
+ @ApiModelProperty("访客状态:VISITING来访中 SIGNED_OUT已签离 PENDING_CONFIRM逾期滞留 OVERDUE_AUTO_SIGNED_OUT超期自动 CANCELLED已取消")
private String status;
+ /** 访客状态名称 */
+ @ApiModelProperty("访客状态名称")
+ private String statusName;
+
+ /** 访问有效期展示文本 */
+ @ApiModelProperty("访问有效期展示文本")
+ private String validTimeText;
+
+ /** 登记时间 */
+ @ApiModelProperty("登记时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date registerTime;
+ /** 登记采集时间 */
+ @ApiModelProperty("登记采集时间")
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private Date registerCollectTime;
+
+ /** 登记来源 */
+ @ApiModelProperty("登记来源")
private String registerSource;
+ /** 登记访客人像地址 */
+ @ApiModelProperty("登记访客人像地址")
private String faceImageUrl;
+ /** 签离时间 */
+ @ApiModelProperty("签离时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date signTime;
+ /** 签离接待人 */
+ @ApiModelProperty("签离接待人")
private String signReceiverName;
+ /** 签离验证方式编码 */
+ @ApiModelProperty("签离验证方式编码")
private String signVerifyMethod;
+ /** 签离验证方式名称 */
+ @ApiModelProperty("签离验证方式名称")
+ private String signVerifyMethodName;
+
+ /** 签离人像地址 */
+ @ApiModelProperty("签离人像地址")
private String signImageUrl;
+ /** 签离采集时间 */
+ @ApiModelProperty("签离采集时间")
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private Date signCollectTime;
+
+ /** 备注 */
+ @ApiModelProperty("备注")
private String remark;
+ /** 通行明细列表 */
+ @ApiModelProperty("通行明细列表")
private List<SysVisitorPassRecordVO> passRecords;
}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/vo/SysVisitorRecordVO.java b/ruoyi-system/src/main/java/com/ruoyi/system/vo/SysVisitorRecordVO.java
index 248524e..413b34f 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/vo/SysVisitorRecordVO.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/vo/SysVisitorRecordVO.java
@@ -1,6 +1,8 @@
package com.ruoyi.system.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
@@ -11,36 +13,65 @@
* @author ruoyi
*/
@Data
+@ApiModel(value = "SysVisitorRecordVO", description = "管理侧访客记录列表返回对象")
public class SysVisitorRecordVO
{
+ /** 访客登记记录主键 */
+ @ApiModelProperty("访客登记记录主键")
private Long recordId;
+ /** 登记编号 */
+ @ApiModelProperty("登记编号")
private String registerNo;
+ /** 访客姓名 */
+ @ApiModelProperty("访客姓名")
private String visitorName;
+ /** 访客证件号 */
+ @ApiModelProperty("访客证件号")
private String idCard;
+ /** 登记类型:APPOINTMENT预约登记 ONSITE现场登记 */
+ @ApiModelProperty("登记类型:APPOINTMENT预约登记 ONSITE现场登记")
private String registerType;
+ /** 被访人 */
+ @ApiModelProperty("被访人")
private String intervieweeName;
+ /** 被访人部门 */
+ @ApiModelProperty("被访人部门")
private String intervieweeDept;
+ /** 访问区域名称,英文逗号分隔 */
+ @ApiModelProperty("访问区域名称,英文逗号分隔")
private String visitAreaNames;
+ /** 车牌号 */
+ @ApiModelProperty("车牌号")
private String plateNo;
+ /** 来访事由 */
+ @ApiModelProperty("来访事由")
private String visitReason;
+ /** 有效期开始时间 */
+ @ApiModelProperty("有效期开始时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date validStartTime;
+ /** 有效期结束时间 */
+ @ApiModelProperty("有效期结束时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date validEndTime;
+ /** 访客状态:VISITING来访中 SIGNED_OUT已签离 PENDING_CONFIRM逾期滞留 OVERDUE_AUTO_SIGNED_OUT超期自动 CANCELLED已取消 */
+ @ApiModelProperty("访客状态:VISITING来访中 SIGNED_OUT已签离 PENDING_CONFIRM逾期滞留 OVERDUE_AUTO_SIGNED_OUT超期自动 CANCELLED已取消")
private String status;
+ /** 登记时间 */
+ @ApiModelProperty("登记时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date registerTime;
}
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysEmployeeMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysEmployeeMapper.xml
index cefb99b..2bb95b0 100644
--- a/ruoyi-system/src/main/resources/mapper/system/SysEmployeeMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/SysEmployeeMapper.xml
@@ -227,7 +227,10 @@
<update id="deleteByIds">
update t_employee
- set del_flag = '1',
+ set enabled = 0,
+ card_no = null,
+ face_image = null,
+ del_flag = '1',
update_by = #{updateBy},
update_time = sysdate()
where del_flag = '0'
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysVisitorRecordMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysVisitorRecordMapper.xml
index 659754e..a48a365 100644
--- a/ruoyi-system/src/main/resources/mapper/system/SysVisitorRecordMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/SysVisitorRecordMapper.xml
@@ -93,11 +93,17 @@
<if test="query.intervieweeName != null and query.intervieweeName != ''">
and interviewee_name like concat('%', #{query.intervieweeName}, '%')
</if>
+ <if test="query.intervieweeKeyword != null and query.intervieweeKeyword != ''">
+ and interviewee_name like concat('%', #{query.intervieweeKeyword}, '%')
+ </if>
<if test="query.intervieweeDept != null and query.intervieweeDept != ''">
and interviewee_dept = #{query.intervieweeDept}
</if>
<if test="query.areaId != null">
and find_in_set(#{query.areaId}, visit_area_ids)
+ </if>
+ <if test="query.visitAreaKeyword != null and query.visitAreaKeyword != ''">
+ and visit_area_names like concat('%', #{query.visitAreaKeyword}, '%')
</if>
<if test="query.validStartTime != null">
and valid_end_time >= #{query.validStartTime}
@@ -110,6 +116,12 @@
</if>
<if test="query.visitorName != null and query.visitorName != ''">
and visitor_name like concat('%', #{query.visitorName}, '%')
+ </if>
+ <if test="query.visitorKeyword != null and query.visitorKeyword != ''">
+ and (
+ visitor_name like concat('%', #{query.visitorKeyword}, '%')
+ or id_card like concat('%', #{query.visitorKeyword}, '%')
+ )
</if>
<if test="query.visitReason != null and query.visitReason != ''">
and visit_reason = #{query.visitReason}
@@ -141,6 +153,30 @@
order by pass_time desc, pass_id desc
</select>
+ <update id="updateExpiredToAutoSignedOut">
+ update t_visitor_record
+ set status = 'OVERDUE_AUTO_SIGNED_OUT',
+ sign_time = date_sub(date_add(date(valid_end_time), interval 1 day), interval 1 second),
+ sign_verify_method = 'AUTO',
+ update_by = 'system',
+ update_time = sysdate()
+ where del_flag = '0'
+ and status in ('VISITING', 'PENDING_CONFIRM')
+ and valid_end_time is not null
+ and date_add(date(valid_end_time), interval 1 day) <= #{now}
+ </update>
+
+ <update id="updateVisitingToOverdue">
+ update t_visitor_record
+ set status = 'PENDING_CONFIRM',
+ update_time = sysdate()
+ where del_flag = '0'
+ and status = 'VISITING'
+ and valid_end_time is not null
+ and valid_end_time < #{now}
+ and date_add(date(valid_end_time), interval 1 day) > #{now}
+ </update>
+
<update id="deleteByIds">
update t_visitor_record
set del_flag = '1',
--
Gitblit v1.7.1