Quellcode durchsuchen

feat(inspection): 扫码任务补全 4 字段 + verifyQrCode 时间窗口校验

DB schema 新增 3 列:
- punch_device_name varchar(100) 扫码设备名称(展示用)
- scan_start_time datetime 扫码开启时间(二维码生效起始)
- scan_interval_sec int default 1800 扫码间隔(秒),默认 30 分钟

entity/bo/vo 同步 3 字段,弹窗 v-if scanEnabled 时显示:
- 扫码设备名称 / 打卡设备编码 / 扫码开启时间(el-date-picker) / 扫码间隔(s)(el-input-number)

verifyQrCode 时间校验从'±24h 宽松'改为严格窗口校验:
- 二维码时间戳必须落在 [scanStartTime, scanStartTime+scanIntervalSec*1000] 区间内
- 未配置 scanStartTime 的老任务继续放行(向下兼容)
- 间隔 ≤0 兜底为 1800 秒
yangjingjing vor 19 Stunden
Ursprung
Commit
f6614ac736

+ 15 - 0
ruoyi-modules/ruoyi-risk/src/main/java/org/dromara/risk/domain/RiskInspectionTask.java

@@ -157,6 +157,21 @@ public class RiskInspectionTask extends TenantEntity {
      */
     private String punchDeviceCode;
 
+    /**
+     * 扫码设备名称(展示用)
+     */
+    private String punchDeviceName;
+
+    /**
+     * 扫码开启时间(二维码生效起始)
+     */
+    private Date scanStartTime;
+
+    /**
+     * 扫码间隔(秒),默认 1800=30 分钟
+     */
+    private Integer scanIntervalSec;
+
     /**
      * 审核人ID
      */

+ 15 - 0
ruoyi-modules/ruoyi-risk/src/main/java/org/dromara/risk/domain/bo/RiskInspectionTaskBo.java

@@ -157,6 +157,21 @@ public class RiskInspectionTaskBo extends BaseEntity {
      */
     private String punchDeviceCode;
 
+    /**
+     * 扫码设备名称(展示用)
+     */
+    private String punchDeviceName;
+
+    /**
+     * 扫码开启时间(二维码生效起始)
+     */
+    private Date scanStartTime;
+
+    /**
+     * 扫码间隔(秒),默认 1800=30 分钟
+     */
+    private Integer scanIntervalSec;
+
     /**
      * 巡检项目列表(保存/编辑时一并保存)
      */

+ 18 - 0
ruoyi-modules/ruoyi-risk/src/main/java/org/dromara/risk/domain/vo/RiskInspectionTaskVo.java

@@ -197,6 +197,24 @@ public class RiskInspectionTaskVo implements Serializable {
      */
     private String punchDeviceCode;
 
+    /**
+     * 扫码设备名称(展示用)
+     */
+    @ExcelProperty(value = "扫码设备名称")
+    private String punchDeviceName;
+
+    /**
+     * 扫码开启时间(二维码生效起始)
+     */
+    @ExcelProperty(value = "扫码开启时间")
+    private Date scanStartTime;
+
+    /**
+     * 扫码间隔(秒),默认 1800=30 分钟
+     */
+    @ExcelProperty(value = "扫码间隔(秒)")
+    private Integer scanIntervalSec;
+
     /**
      * 审核人ID
      */

+ 23 - 9
ruoyi-modules/ruoyi-risk/src/main/java/org/dromara/risk/service/impl/RiskInspectionTaskServiceImpl.java

@@ -375,7 +375,9 @@ public class RiskInspectionTaskServiceImpl implements IRiskInspectionTaskService
      * <p>
      * 二维码内容格式:「设备编码 [分隔符] 时间」
      * 设备编码部分必须等于 task.punchDeviceCode(开启扫码打卡时必填)
-     * 时间部分必须是 yyyy-MM-dd HH:mm:ss 格式,误差 ±24h 内视为有效
+     * 时间部分必须是 yyyy-MM-dd HH:mm:ss 格式,必须落在
+     * [scanStartTime, scanStartTime + scanIntervalSec] 窗口内
+     * (二维码每 scanIntervalSec 秒切换一次,扫码时这个时间戳应落在当前窗口)
      */
     @Override
     public boolean verifyQrCode(Long taskId, String qrCode) {
@@ -403,20 +405,32 @@ public class RiskInspectionTaskServiceImpl implements IRiskInspectionTaskService
                 taskId, task.getPunchDeviceCode(), deviceCode);
             return false;
         }
-        // 2. 校验时间(误差 ±24 小时)
+        // 2. 校验时间(必须落在 [scanStartTime, scanStartTime+scanIntervalSec] 窗口内)
+        Date qrTime;
         try {
             java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-            Date qrTime = sdf.parse(timeStr);
-            long diffMs = Math.abs(System.currentTimeMillis() - qrTime.getTime());
-            long oneDayMs = 24L * 60 * 60 * 1000;
-            if (diffMs > oneDayMs) {
-                log.warn("二维码时间超出有效期: taskId={}, qrTime={}", taskId, timeStr);
-                return false;
-            }
+            qrTime = sdf.parse(timeStr);
         } catch (java.text.ParseException e) {
             log.warn("二维码时间格式不合法: taskId={}, timeStr={}", taskId, timeStr);
             return false;
         }
+        if (task.getScanStartTime() == null) {
+            // 未配置开启时间(老任务):放行(向下兼容)
+            return true;
+        }
+        long windowStart = task.getScanStartTime().getTime();
+        // 间隔默认 1800 秒;0/负数视为 1800(兜底)
+        int interval = task.getScanIntervalSec() == null || task.getScanIntervalSec() <= 0
+            ? 1800 : task.getScanIntervalSec();
+        long windowEnd = windowStart + interval * 1000L;
+        long qrMs = qrTime.getTime();
+        if (qrMs < windowStart || qrMs > windowEnd) {
+            log.warn("二维码时间不在有效窗口内: taskId={}, qrTime={}, window=[{}, {}]",
+                taskId, timeStr,
+                new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(windowStart)),
+                new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(windowEnd)));
+            return false;
+        }
         return true;
     }