From 2cfd0045a109b01ac890f0f2e968cbb44415d0ac Mon Sep 17 00:00:00 2001
From: maven <2163098428@qq.com>
Date: 星期五, 19 九月 2025 11:45:43 +0800
Subject: [PATCH] yys 博达商贸-巡检管理
---
src/main/java/com/ruoyi/basic/service/impl/StorageAttachmentServiceImpl.java | 16
src/main/java/com/ruoyi/inspectiontask/service/impl/InspectionTaskServiceImpl.java | 257 ++++++
src/main/java/com/ruoyi/common/utils/MinioUtils.java | 88 ++
src/main/java/com/ruoyi/inspectiontask/mapper/QrCodeScanRecordMapper.java | 11
src/main/java/com/ruoyi/inspectiontask/dto/QrCodeDto.java | 8
src/main/java/com/ruoyi/procurementrecord/service/impl/ProcurementPlanServiceImpl.java | 41 +
src/main/java/com/ruoyi/inspectiontask/pojo/TimingTask.java | 97 ++
src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskJob.java | 65 +
src/main/java/com/ruoyi/inspectiontask/service/impl/QrCodeServiceImpl.java | 54 +
src/main/java/com/ruoyi/basic/pojo/StorageBlob.java | 6
pom.xml | 8
src/main/java/com/ruoyi/inspectiontask/dto/InspectionTaskDto.java | 20
src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskScheduler.java | 234 ++++++
src/main/java/com/ruoyi/procurementrecord/mapper/ProcurementPlanMapper.java | 22
src/main/java/com/ruoyi/procurementrecord/pojo/ProcurementPlan.java | 105 ++
src/main/java/com/ruoyi/inspectiontask/controller/QrCodeScanRecordController.java | 56 +
src/main/java/com/ruoyi/project/system/mapper/SysUserMapper.java | 7
src/main/java/com/ruoyi/inspectiontask/service/impl/QrCodeScanRecordServiceImpl.java | 194 ++++
src/main/java/com/ruoyi/inspectiontask/pojo/QrCodeScanRecord.java | 68 +
src/main/java/com/ruoyi/inspectiontask/controller/QrCodeController.java | 56 +
src/main/java/com/ruoyi/inspectiontask/service/TimingTaskService.java | 23
src/main/java/com/ruoyi/inspectiontask/StorageAttachmentRecordType.java | 23
src/main/java/com/ruoyi/inspectiontask/dto/TimingTaskDto.java | 12
src/main/java/com/ruoyi/inspectiontask/service/QrCodeService.java | 19
src/main/java/com/ruoyi/inspectiontask/pojo/InspectionTask.java | 81 ++
src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskServiceImpl.java | 348 ++++++++
src/main/java/com/ruoyi/inspectiontask/mapper/QrCodeMapper.java | 11
src/main/java/com/ruoyi/inspectiontask/service/InspectionTaskService.java | 20
src/main/java/com/ruoyi/inspectiontask/controller/InspectionTaskController.java | 59 +
src/main/resources/mapper/procurementrecord/ProcurementPlanMapper.xml | 16
src/main/java/com/ruoyi/inspectiontask/dto/QrCodeScanRecordDto.java | 20
src/main/java/com/ruoyi/common/enums/StorageAttachmentRecordType.java | 5
src/main/java/com/ruoyi/inspectiontask/mapper/TimingTaskMapper.java | 11
src/main/java/com/ruoyi/basic/dto/StorageBlobDTO.java | 2
src/main/java/com/ruoyi/basic/service/StorageAttachmentService.java | 3
src/main/java/com/ruoyi/procurementrecord/controller/ProcurementPlanController.java | 67 +
src/main/java/com/ruoyi/procurementrecord/service/ProcurementPlanService.java | 25
src/main/resources/mapper/system/SysUserMapper.xml | 22
src/main/java/com/ruoyi/inspectiontask/controller/TimingTaskController.java | 58 +
src/main/java/com/ruoyi/inspectiontask/mapper/InspectionTaskMapper.java | 11
src/main/java/com/ruoyi/inspectiontask/pojo/QrCode.java | 63 +
src/main/java/com/ruoyi/inspectiontask/service/QrCodeScanRecordService.java | 20
42 files changed, 2,327 insertions(+), 5 deletions(-)
diff --git a/pom.xml b/pom.xml
index 17973d1..316c132 100644
--- a/pom.xml
+++ b/pom.xml
@@ -307,6 +307,14 @@
<fork>true</fork> <!-- 濡傛灉娌℃湁璇ラ厤缃紝devtools涓嶄細鐢熸晥 -->
</configuration>
</plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>16</source>
+ <target>16</target>
+ </configuration>
+ </plugin>
</plugins>
</build>
diff --git a/src/main/java/com/ruoyi/basic/dto/StorageBlobDTO.java b/src/main/java/com/ruoyi/basic/dto/StorageBlobDTO.java
index b868048..17a7d71 100644
--- a/src/main/java/com/ruoyi/basic/dto/StorageBlobDTO.java
+++ b/src/main/java/com/ruoyi/basic/dto/StorageBlobDTO.java
@@ -6,4 +6,6 @@
@Data
public class StorageBlobDTO extends StorageBlob {
private String url;
+
+ private String downloadUrl;
}
diff --git a/src/main/java/com/ruoyi/basic/pojo/StorageBlob.java b/src/main/java/com/ruoyi/basic/pojo/StorageBlob.java
index 8e92865..188d9c5 100644
--- a/src/main/java/com/ruoyi/basic/pojo/StorageBlob.java
+++ b/src/main/java/com/ruoyi/basic/pojo/StorageBlob.java
@@ -64,4 +64,10 @@
*/
@TableField(value = "byte_size")
private Long byteSize;
+
+ /**
+ * 0鐢熶骇鍓� 1鐢熶骇鍚� 2鐢熶骇闂
+ */
+ @TableField(value = "type")
+ private Long type;
}
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/basic/service/StorageAttachmentService.java b/src/main/java/com/ruoyi/basic/service/StorageAttachmentService.java
index e285063..de2c096 100644
--- a/src/main/java/com/ruoyi/basic/service/StorageAttachmentService.java
+++ b/src/main/java/com/ruoyi/basic/service/StorageAttachmentService.java
@@ -34,6 +34,9 @@
*/
public void saveStorageAttachment(List<StorageAttachment> attachments, Long recordId, StorageAttachmentRecordType recordType, StorageAttachmentConstants fileType);
+ public void saveStorageAttachment(List<StorageAttachment> attachments, Long recordId, StorageAttachmentRecordType recordType, String fileType);
+
+
/**
* 鍒犻櫎閫氱敤鏂囦欢涓婁紶鐨勯檮浠朵俊鎭�
* @param storageAttachment 鏂囦欢淇℃伅
diff --git a/src/main/java/com/ruoyi/basic/service/impl/StorageAttachmentServiceImpl.java b/src/main/java/com/ruoyi/basic/service/impl/StorageAttachmentServiceImpl.java
index 78c8647..d0e4b70 100644
--- a/src/main/java/com/ruoyi/basic/service/impl/StorageAttachmentServiceImpl.java
+++ b/src/main/java/com/ruoyi/basic/service/impl/StorageAttachmentServiceImpl.java
@@ -78,6 +78,22 @@
}
@Override
+ public void saveStorageAttachment(List<StorageAttachment> attachments, Long recordId, StorageAttachmentRecordType recordType, String fileType) {
+ // 鍒犻櫎鏃у浘
+ deleteStorageAttachment(new StorageAttachment(fileType.toString(), (long) recordType.ordinal(), recordId));
+ for (StorageAttachment attachment : attachments) {
+ // 鑾峰彇鍏宠仈璁板綍
+ StorageBlob storageBlob = attachment.getStorageBlobDTO();
+ attachment.setName(fileType.toString());
+ attachment.setRecordType((long) recordType.ordinal());
+ attachment.setRecordId(recordId);
+ attachment.setStorageBlobId(storageBlob.getId());
+ storageAttachmentMapper.insert(attachment);
+ }
+
+ }
+
+ @Override
public int deleteStorageAttachment(StorageAttachment storageAttachment) {
// 鍏堝垹闄ゆ槑缁嗚〃
storageBlobService.deleteStorageBlobs(storageAttachment);
diff --git a/src/main/java/com/ruoyi/common/enums/StorageAttachmentRecordType.java b/src/main/java/com/ruoyi/common/enums/StorageAttachmentRecordType.java
index 8b0597e..a4b889d 100644
--- a/src/main/java/com/ruoyi/common/enums/StorageAttachmentRecordType.java
+++ b/src/main/java/com/ruoyi/common/enums/StorageAttachmentRecordType.java
@@ -9,7 +9,10 @@
@AllArgsConstructor
public enum StorageAttachmentRecordType {
// 渚嬪瓙 瀹為檯寮�鍙戣鍒犻櫎
- Template("Template","鑼冧緥");
+ Template("Template","鑼冧緥"),
+ Archives("Archives","鏂囨。绠$悊"),
+ InspectionTasks("InspectionTasks","鐢熶骇宸℃"),
+ QrCodeScanRecords("QrCodeScanRecords","浜岀淮鐮佹壂鐮佽褰曟枃浠�");
private final String code;
diff --git a/src/main/java/com/ruoyi/common/utils/MinioUtils.java b/src/main/java/com/ruoyi/common/utils/MinioUtils.java
index 55af1dd..30e479a 100644
--- a/src/main/java/com/ruoyi/common/utils/MinioUtils.java
+++ b/src/main/java/com/ruoyi/common/utils/MinioUtils.java
@@ -21,12 +21,10 @@
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
+import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
+import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@@ -306,4 +304,86 @@
return null;
}
+ /**
+ * 鐢熸垚棰勮URL
+ * @param bucketFilename 鏂囦欢鍦∕inIO涓殑鍞竴鏍囪瘑
+ * @param bucketName 瀛樺偍妗跺悕绉�
+ * @param useDefaultExpiry 鏄惁浣跨敤榛樿杩囨湡鏃堕棿锛坱rue=浣跨敤榛樿杩囨湡鏃堕棿锛宖alse=姘镐箙鏈夋晥锛�
+ * @return 棰勮URL
+ */
+ public String getPreviewUrls(String bucketFilename, String bucketName, boolean useDefaultExpiry) {
+ if (StringUtils.isBlank(bucketFilename)) {
+ return null;
+ }
+
+ try {
+ // 楠岃瘉鏂囦欢瀛樺湪鎬�
+ minioClient.statObject(StatObjectArgs.builder()
+ .bucket(bucketName)
+ .object(bucketFilename)
+ .build());
+
+ GetPresignedObjectUrlArgs.Builder builder = GetPresignedObjectUrlArgs.builder()
+ .method(Method.GET)
+ .bucket(bucketName)
+ .object(bucketFilename);
+
+ // 璁剧疆杩囨湡鏃堕棿锛歶seDefaultExpiry=true 浣跨敤閰嶇疆鐨勮繃鏈熸椂闂�
+ if (useDefaultExpiry) {
+ builder.expiry(previewExpiry, TimeUnit.HOURS);
+ }
+
+ return minioClient.getPresignedObjectUrl(builder.build());
+ } catch (Exception e) {
+ throw new UtilException("鐢熸垚棰勮URL澶辫触: " + e.getMessage(), e);
+ }
+ }
+
+
+ /**
+ * 鐢熸垚涓嬭浇URL锛堝己鍒舵祻瑙堝櫒涓嬭浇锛�
+ * @param bucketFilename 鏂囦欢鍦∕inIO涓殑鍞竴鏍囪瘑
+ * @param bucketName 瀛樺偍妗跺悕绉�
+ * @param originalFileName 鍘熷鏂囦欢鍚嶏紙鐢ㄤ簬涓嬭浇鏃舵樉绀猴級
+ * @param useDefaultExpiry 鏄惁浣跨敤榛樿杩囨湡鏃堕棿锛坱rue=浣跨敤榛樿锛宖alse=鏃犺繃鏈熸椂闂达級
+ * @return 涓嬭浇URL
+ */
+ public String getDownloadUrls(String bucketFilename, String bucketName, String originalFileName, boolean useDefaultExpiry) {
+ if (StringUtils.isBlank(bucketFilename)) {
+ return null;
+ }
+
+ try {
+ // 楠岃瘉鏂囦欢瀛樺湪鎬�
+ minioClient.statObject(StatObjectArgs.builder()
+ .bucket(bucketName)
+ .object(bucketFilename)
+ .build());
+
+ // 姝g‘缂栫爜鏂囦欢鍚嶏細鏇挎崲 + 涓� %20
+ String encodedFileName = URLEncoder.encode(originalFileName, StandardCharsets.UTF_8)
+ .replace("+", "%20");
+
+ Map<String, String> reqParams = new HashMap<>();
+ reqParams.put("response-content-disposition",
+ "attachment; filename=\"" + encodedFileName + "\"");
+
+ GetPresignedObjectUrlArgs.Builder builder = GetPresignedObjectUrlArgs.builder()
+ .method(Method.GET)
+ .bucket(bucketName)
+ .object(bucketFilename)
+ .extraQueryParams(reqParams);
+
+ // 鏍规嵁鍙傛暟鍐冲畾鏄惁璁剧疆杩囨湡鏃堕棿
+ if (useDefaultExpiry) {
+ // 浣跨敤榛樿杩囨湡鏃堕棿锛堜粠閰嶇疆璇诲彇锛�
+ builder.expiry(previewExpiry, TimeUnit.HOURS);
+ } else {
+ // 涓嶈缃繃鏈熸椂闂达紙MinIO 榛樿7澶╋級
+ }
+ return minioClient.getPresignedObjectUrl(builder.build());
+ } catch (Exception e) {
+ throw new UtilException("鐢熸垚涓嬭浇URL澶辫触: " + e.getMessage(), e);
+ }
+ }
}
diff --git a/src/main/java/com/ruoyi/inspectiontask/StorageAttachmentRecordType.java b/src/main/java/com/ruoyi/inspectiontask/StorageAttachmentRecordType.java
new file mode 100644
index 0000000..e15b741
--- /dev/null
+++ b/src/main/java/com/ruoyi/inspectiontask/StorageAttachmentRecordType.java
@@ -0,0 +1,23 @@
+package com.ruoyi.inspectiontask;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * 闄勪欢璁板綍绫诲瀷鏋氫妇
+ *
+ */
+@Getter
+@AllArgsConstructor
+public enum StorageAttachmentRecordType {
+ // 渚嬪瓙 瀹為檯寮�鍙戣鍒犻櫎
+ Template("Template","鑼冧緥"),
+ Archives("Archives","鏂囨。绠$悊"),
+ InspectionTasks("InspectionTasks","鐢熶骇宸℃"),
+ QrCodeScanRecords("QrCodeScanRecords","浜岀淮鐮佹壂鐮佽褰曟枃浠�");
+
+
+ private final String code;
+ private final String info;
+
+}
diff --git a/src/main/java/com/ruoyi/inspectiontask/controller/InspectionTaskController.java b/src/main/java/com/ruoyi/inspectiontask/controller/InspectionTaskController.java
new file mode 100644
index 0000000..a32dd4b
--- /dev/null
+++ b/src/main/java/com/ruoyi/inspectiontask/controller/InspectionTaskController.java
@@ -0,0 +1,59 @@
+package com.ruoyi.inspectiontask.controller;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.framework.web.controller.BaseController;
+import com.ruoyi.framework.web.domain.R;
+import com.ruoyi.inspectiontask.dto.InspectionTaskDto;
+import com.ruoyi.inspectiontask.pojo.InspectionTask;
+import com.ruoyi.inspectiontask.service.InspectionTaskService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ * @author :yys
+ * @date : 2025/9/19 10:52
+ */
+@RestController
+@Api(tags = "宸℃浠诲姟绠$悊")
+@RequestMapping("/inspectionTask")
+public class InspectionTaskController extends BaseController {
+
+ @Autowired
+ private InspectionTaskService inspectionTaskService;
+
+ /**
+ * 宸℃浠诲姟琛ㄨ〃鏌ヨ
+ */
+ @GetMapping("/list")
+ @ApiOperation("宸℃浠诲姟琛ㄨ〃鏌ヨ")
+ public R<IPage<InspectionTaskDto>> list(Page<InspectionTask> page, InspectionTaskDto inspectionTaskDto) {
+ IPage<InspectionTaskDto> list = inspectionTaskService.selectInspectionTaskList(page,inspectionTaskDto);
+ return R.ok(list);
+ }
+
+ /**
+ * 宸℃浠诲姟琛ㄦ柊澧炰慨鏀�
+ */
+ @PostMapping("/addOrEditInspectionTask")
+ @ApiOperation("宸℃浠诲姟琛ㄦ柊澧炰慨鏀�")
+ @Transactional(rollbackFor = Exception.class)
+ public R addOrEditInspectionTask(@RequestBody InspectionTaskDto inspectionTaskDto) {
+ return R.ok(inspectionTaskService.addOrEditInspectionTask(inspectionTaskDto));
+ }
+
+ /**
+ * 宸℃浠诲姟琛ㄥ垹闄�
+ */
+ @DeleteMapping("/delInspectionTask")
+ @ApiOperation("宸℃浠诲姟琛ㄥ垹闄�")
+ @Transactional(rollbackFor = Exception.class)
+ public R remove(@RequestBody Long[] ids) {
+ return R.ok(inspectionTaskService.delByIds(ids));
+ }
+
+}
diff --git a/src/main/java/com/ruoyi/inspectiontask/controller/QrCodeController.java b/src/main/java/com/ruoyi/inspectiontask/controller/QrCodeController.java
new file mode 100644
index 0000000..3d35be5
--- /dev/null
+++ b/src/main/java/com/ruoyi/inspectiontask/controller/QrCodeController.java
@@ -0,0 +1,56 @@
+package com.ruoyi.inspectiontask.controller;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.framework.web.controller.BaseController;
+import com.ruoyi.framework.web.domain.R;
+import com.ruoyi.inspectiontask.dto.QrCodeDto;
+import com.ruoyi.inspectiontask.pojo.QrCode;
+import com.ruoyi.inspectiontask.service.QrCodeService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ * @author :yys
+ * @date : 2025/9/19 10:52
+ */
+@RestController
+@Api(tags = "浜岀淮鐮佺鐞�")
+@RequestMapping("/qrCode")
+public class QrCodeController extends BaseController {
+
+ @Autowired
+ private QrCodeService qrCodeService;
+
+ /**
+ * 浜岀淮鐮佺鐞嗚〃鏌ヨ
+ */
+ @GetMapping("/list")
+ @ApiOperation("浜岀淮鐮佺鐞嗚〃鏌ヨ")
+ public R<IPage<QrCode>> list(Page page, QrCodeDto qrCodeDto) {
+ IPage<QrCode> list = qrCodeService.selectQrCodeList(page, qrCodeDto);
+ return R.ok(list);
+ }
+
+ /**
+ * 浜岀淮鐮佺鐞嗚〃鏂板淇敼
+ */
+ @PostMapping("/addOrEditQrCode")
+ @ApiOperation("浜岀淮鐮佺鐞嗚〃鏂板淇敼")
+ public R<Long> addOrEditQrCode(@RequestBody QrCodeDto qrCodeDto) {
+ return R.ok(qrCodeService.addOrEditQrCode(qrCodeDto));
+ }
+
+ /**
+ * 浜岀淮鐮佺鐞嗚〃鍒犻櫎
+ */
+ @DeleteMapping("/delQrCode")
+ @ApiOperation("浜岀淮鐮佺鐞嗚〃鍒犻櫎")
+ public R remove(@RequestBody Long[] ids) {
+ return R.ok(qrCodeService.delByIds(ids));
+ }
+
+}
diff --git a/src/main/java/com/ruoyi/inspectiontask/controller/QrCodeScanRecordController.java b/src/main/java/com/ruoyi/inspectiontask/controller/QrCodeScanRecordController.java
new file mode 100644
index 0000000..00329b6
--- /dev/null
+++ b/src/main/java/com/ruoyi/inspectiontask/controller/QrCodeScanRecordController.java
@@ -0,0 +1,56 @@
+package com.ruoyi.inspectiontask.controller;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.framework.web.controller.BaseController;
+import com.ruoyi.framework.web.domain.R;
+import com.ruoyi.inspectiontask.dto.QrCodeScanRecordDto;
+import com.ruoyi.inspectiontask.pojo.QrCodeScanRecord;
+import com.ruoyi.inspectiontask.service.QrCodeScanRecordService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ * @author :yys
+ * @date : 2025/9/19 10:53
+ */
+@RestController
+@Api(tags = "浜岀淮鐮佹壂鎻忚褰曠鐞�")
+@RequestMapping("/qrCodeScanRecord")
+public class QrCodeScanRecordController extends BaseController {
+
+ @Autowired
+ private QrCodeScanRecordService qrCodeScanRecordService;
+
+ /**
+ * 浜岀淮鐮佹壂鐮佽褰曡〃鏌ヨ
+ */
+ @GetMapping("/list")
+ @ApiOperation("浜岀淮鐮佹壂鐮佽褰曡〃鏌ヨ")
+ public R<IPage<QrCodeScanRecordDto>> list(Page<QrCodeScanRecord> page, QrCodeScanRecordDto qrCodeScanRecordDto) {
+ IPage<QrCodeScanRecordDto> list = qrCodeScanRecordService.selectQrCodeScanRecordList(page, qrCodeScanRecordDto);
+ return R.ok(list);
+ }
+
+ /**
+ * 浜岀淮鐮佹壂鐮佽褰曡〃鏂板淇敼
+ */
+ @PostMapping("/addOrEditQrCodeRecord")
+ @ApiOperation("浜岀淮鐮佹壂鐮佽褰曡〃鏂板淇敼")
+ public R addOrEditQrCodeRecord(@RequestBody QrCodeScanRecordDto qrCodeScanRecordDto) {
+ return R.ok(qrCodeScanRecordService.addOrEditQrCodeRecord(qrCodeScanRecordDto));
+ }
+
+ /**
+ * 浜岀淮鐮佹壂鐮佽褰曡〃鍒犻櫎
+ */
+ @DeleteMapping("/delSalesRecord")
+ @ApiOperation("浜岀淮鐮佹壂鐮佽褰曡〃鍒犻櫎")
+ public R remove(@RequestBody Long[] ids) {
+ return R.ok(qrCodeScanRecordService.delByIds(ids));
+ }
+
+}
diff --git a/src/main/java/com/ruoyi/inspectiontask/controller/TimingTaskController.java b/src/main/java/com/ruoyi/inspectiontask/controller/TimingTaskController.java
new file mode 100644
index 0000000..6b80e1b
--- /dev/null
+++ b/src/main/java/com/ruoyi/inspectiontask/controller/TimingTaskController.java
@@ -0,0 +1,58 @@
+package com.ruoyi.inspectiontask.controller;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.framework.web.controller.BaseController;
+import com.ruoyi.framework.web.domain.R;
+import com.ruoyi.inspectiontask.dto.TimingTaskDto;
+import com.ruoyi.inspectiontask.pojo.TimingTask;
+import com.ruoyi.inspectiontask.service.TimingTaskService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import org.quartz.SchedulerException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ * @author :yys
+ * @date : 2025/9/19 10:53
+ */
+@RestController
+@Api(tags = "瀹氭椂浠诲姟绠$悊")
+@RequestMapping("/timingTask")
+public class TimingTaskController extends BaseController {
+
+
+ @Autowired
+ private TimingTaskService timingTaskService;
+
+ /**
+ * 瀹氭椂宸℃浠诲姟琛ㄦ煡璇�
+ */
+ @GetMapping("/list")
+ @ApiOperation(value = "瀹氭椂浠诲姟鍒楄〃")
+ public R<IPage<TimingTaskDto>> list(Page<TimingTask> page, TimingTask timingTask) {
+ IPage<TimingTaskDto> list = timingTaskService.selectTimingTaskList(page,timingTask);
+ return R.ok(list);
+ }
+
+ /**
+ * 瀹氭椂宸℃浠诲姟琛ㄦ柊澧炰慨鏀�
+ */
+ @PostMapping("/addOrEditTimingTask")
+ @ApiOperation(value = "鏂板淇敼瀹氭椂浠诲姟")
+ public R addOrEditTimingTask(@RequestBody TimingTaskDto timingTaskDto) throws SchedulerException {
+ return R.ok(timingTaskService.addOrEditTimingTask(timingTaskDto));
+ }
+
+ /**
+ * 瀹氭椂宸℃浠诲姟琛ㄥ垹闄�
+ */
+ @DeleteMapping("/delTimingTask")
+ @ApiOperation(value = "鍒犻櫎瀹氭椂浠诲姟")
+ public R remove(@RequestBody Long[] ids) {
+ return R.ok(timingTaskService.delByIds(ids));
+ }
+
+}
diff --git a/src/main/java/com/ruoyi/inspectiontask/dto/InspectionTaskDto.java b/src/main/java/com/ruoyi/inspectiontask/dto/InspectionTaskDto.java
new file mode 100644
index 0000000..f92bde5
--- /dev/null
+++ b/src/main/java/com/ruoyi/inspectiontask/dto/InspectionTaskDto.java
@@ -0,0 +1,20 @@
+package com.ruoyi.inspectiontask.dto;
+
+import com.ruoyi.basic.dto.StorageBlobDTO;
+import com.ruoyi.basic.pojo.StorageAttachment;
+import com.ruoyi.inspectiontask.pojo.InspectionTask;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class InspectionTaskDto extends InspectionTask {
+
+ private List<StorageBlobDTO> storageBlobDTO;
+ private List<StorageBlobDTO> beforeProduction;
+ private List<StorageBlobDTO> afterProduction;
+ private List<StorageBlobDTO> productionIssues;
+
+ private List<StorageAttachment> attachments;
+
+}
diff --git a/src/main/java/com/ruoyi/inspectiontask/dto/QrCodeDto.java b/src/main/java/com/ruoyi/inspectiontask/dto/QrCodeDto.java
new file mode 100644
index 0000000..2badd86
--- /dev/null
+++ b/src/main/java/com/ruoyi/inspectiontask/dto/QrCodeDto.java
@@ -0,0 +1,8 @@
+package com.ruoyi.inspectiontask.dto;
+
+import com.ruoyi.inspectiontask.pojo.QrCode;
+import lombok.Data;
+
+@Data
+public class QrCodeDto extends QrCode {
+}
diff --git a/src/main/java/com/ruoyi/inspectiontask/dto/QrCodeScanRecordDto.java b/src/main/java/com/ruoyi/inspectiontask/dto/QrCodeScanRecordDto.java
new file mode 100644
index 0000000..4247330
--- /dev/null
+++ b/src/main/java/com/ruoyi/inspectiontask/dto/QrCodeScanRecordDto.java
@@ -0,0 +1,20 @@
+package com.ruoyi.inspectiontask.dto;
+
+
+import com.ruoyi.basic.dto.StorageBlobDTO;
+import com.ruoyi.inspectiontask.pojo.QrCode;
+import com.ruoyi.inspectiontask.pojo.QrCodeScanRecord;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class QrCodeScanRecordDto extends QrCodeScanRecord {
+
+ private QrCode qrCode;
+
+ private String scanner;
+
+ private List<StorageBlobDTO> storageBlobDTO;
+
+}
diff --git a/src/main/java/com/ruoyi/inspectiontask/dto/TimingTaskDto.java b/src/main/java/com/ruoyi/inspectiontask/dto/TimingTaskDto.java
new file mode 100644
index 0000000..ad26f89
--- /dev/null
+++ b/src/main/java/com/ruoyi/inspectiontask/dto/TimingTaskDto.java
@@ -0,0 +1,12 @@
+package com.ruoyi.inspectiontask.dto;
+
+import com.ruoyi.inspectiontask.pojo.TimingTask;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class TimingTaskDto extends TimingTask {
+
+ private List<String> inspector;
+}
diff --git a/src/main/java/com/ruoyi/inspectiontask/mapper/InspectionTaskMapper.java b/src/main/java/com/ruoyi/inspectiontask/mapper/InspectionTaskMapper.java
new file mode 100644
index 0000000..9c79059
--- /dev/null
+++ b/src/main/java/com/ruoyi/inspectiontask/mapper/InspectionTaskMapper.java
@@ -0,0 +1,11 @@
+package com.ruoyi.inspectiontask.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.inspectiontask.pojo.InspectionTask;
+
+/**
+ * @author :yys
+ * @date : 2025/9/19 10:46
+ */
+public interface InspectionTaskMapper extends BaseMapper<InspectionTask> {
+}
diff --git a/src/main/java/com/ruoyi/inspectiontask/mapper/QrCodeMapper.java b/src/main/java/com/ruoyi/inspectiontask/mapper/QrCodeMapper.java
new file mode 100644
index 0000000..e2a9c6b
--- /dev/null
+++ b/src/main/java/com/ruoyi/inspectiontask/mapper/QrCodeMapper.java
@@ -0,0 +1,11 @@
+package com.ruoyi.inspectiontask.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.inspectiontask.pojo.QrCode;
+
+/**
+ * @author :yys
+ * @date : 2025/9/19 10:46
+ */
+public interface QrCodeMapper extends BaseMapper<QrCode> {
+}
diff --git a/src/main/java/com/ruoyi/inspectiontask/mapper/QrCodeScanRecordMapper.java b/src/main/java/com/ruoyi/inspectiontask/mapper/QrCodeScanRecordMapper.java
new file mode 100644
index 0000000..595a1f5
--- /dev/null
+++ b/src/main/java/com/ruoyi/inspectiontask/mapper/QrCodeScanRecordMapper.java
@@ -0,0 +1,11 @@
+package com.ruoyi.inspectiontask.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.inspectiontask.pojo.QrCodeScanRecord;
+
+/**
+ * @author :yys
+ * @date : 2025/9/19 10:46
+ */
+public interface QrCodeScanRecordMapper extends BaseMapper<QrCodeScanRecord> {
+}
diff --git a/src/main/java/com/ruoyi/inspectiontask/mapper/TimingTaskMapper.java b/src/main/java/com/ruoyi/inspectiontask/mapper/TimingTaskMapper.java
new file mode 100644
index 0000000..94e41e8
--- /dev/null
+++ b/src/main/java/com/ruoyi/inspectiontask/mapper/TimingTaskMapper.java
@@ -0,0 +1,11 @@
+package com.ruoyi.inspectiontask.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.inspectiontask.pojo.TimingTask;
+
+/**
+ * @author :yys
+ * @date : 2025/9/19 10:47
+ */
+public interface TimingTaskMapper extends BaseMapper<TimingTask> {
+}
diff --git a/src/main/java/com/ruoyi/inspectiontask/pojo/InspectionTask.java b/src/main/java/com/ruoyi/inspectiontask/pojo/InspectionTask.java
new file mode 100644
index 0000000..74fd9d2
--- /dev/null
+++ b/src/main/java/com/ruoyi/inspectiontask/pojo/InspectionTask.java
@@ -0,0 +1,81 @@
+package com.ruoyi.inspectiontask.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDateTime;
+
+/**
+ * @author :yys
+ * @date : 2025/9/19 10:25
+ */
+@Data
+@ApiModel
+@TableName("inspection_task")
+public class InspectionTask {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 宸℃浠诲姟鍞竴鏍囪瘑
+ */
+ @TableId(type = IdType.AUTO)
+ private Long id;
+
+ @ApiModelProperty(value = "宸℃浠诲姟鍚嶇О")
+ private String taskName;
+
+ @ApiModelProperty(value = "宸℃浜篒D")
+ private String inspectorId;
+
+ @ApiModelProperty(value = "鎵ц宸℃鐨勪汉鍛樺鍚�")
+ private String inspector;
+
+ @ApiModelProperty(value = "浠诲姟闄勫姞璇存槑鎴栫壒娈婃儏鍐佃褰�")
+ private String remarks;
+
+ @ApiModelProperty(value = "浠诲姟鐧昏浜篒D")
+ private Long registrantId;
+
+ @ApiModelProperty(value = "浠诲姟鐧昏浜哄鍚�")
+ private String registrant;
+
+ @ApiModelProperty(value = "棰戞")
+ private String frequencyType;
+
+ @ApiModelProperty(value = "鏃堕棿缁嗚妭")
+ private String frequencyDetail;
+
+ @ApiModelProperty(value = "宸℃鍦扮偣璇︾粏鎻忚堪")
+ private String inspectionLocation;
+
+ @ApiModelProperty(value = "杞垹闄ゆ爣蹇楋紝0=鏈垹闄わ紝1=宸插垹闄�")
+ private Integer deleted;
+
+ @ApiModelProperty(value = "鍒涘缓璇ヨ褰曠殑鐢ㄦ埛")
+ @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT)
+ private String createUser;
+
+ @ApiModelProperty(value = "璁板綍鍒涘缓鏃堕棿")
+ @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime createTime;
+
+ @ApiModelProperty(value = "鏈�鍚庝慨鏀硅璁板綍鐨勭敤鎴�")
+ @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT_UPDATE)
+ private String updateUser;
+
+ @ApiModelProperty(value = "璁板綍鏈�鍚庢洿鏂版椂闂�")
+ @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT_UPDATE)
+ private LocalDateTime updateTime;
+
+ @ApiModelProperty(value = "绉熸埛")
+ @TableField(fill = FieldFill.INSERT)
+ private Integer tenantId;
+
+}
diff --git a/src/main/java/com/ruoyi/inspectiontask/pojo/QrCode.java b/src/main/java/com/ruoyi/inspectiontask/pojo/QrCode.java
new file mode 100644
index 0000000..be2abbf
--- /dev/null
+++ b/src/main/java/com/ruoyi/inspectiontask/pojo/QrCode.java
@@ -0,0 +1,63 @@
+package com.ruoyi.inspectiontask.pojo;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDateTime;
+
+/**
+ * @author :yys
+ * @date : 2025/9/19 10:29
+ */
+@Data
+@ApiModel
+@TableName("qr_code")
+public class QrCode {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 浜岀淮鐮佸敮涓�鏍囪瘑
+ */
+ @TableId(type = IdType.AUTO)
+ private Long id;
+
+ @ApiModelProperty(value = "璁惧鍚嶇О")
+ private String deviceName;
+
+ @ApiModelProperty(value = "鎵�鍦ㄤ綅缃弿杩�")
+ private String location;
+
+ @ApiModelProperty(value = "绉熸埛ID锛岀敤浜庡绉熸埛闅旂")
+ @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT)
+ private Integer tenantId;
+
+ @ApiModelProperty(value = "杞垹闄ゆ爣蹇楋紝0=鏈垹闄わ紝1=宸插垹闄�")
+ private Integer deleted;
+
+ @ApiModelProperty(value = "鍒涘缓璇ヨ褰曠殑鐢ㄦ埛")
+ @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT)
+ private Integer createUser;
+
+ @ApiModelProperty(value = "璁板綍鍒涘缓鏃堕棿")
+ @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime createTime;
+
+ @ApiModelProperty(value = "鏈�鍚庝慨鏀硅璁板綍鐨勭敤鎴�")
+ @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT_UPDATE)
+ private Integer updateUser;
+
+ @ApiModelProperty(value = "璁板綍鏈�鍚庢洿鏂版椂闂�")
+ @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT_UPDATE)
+ private LocalDateTime updateTime;
+
+}
diff --git a/src/main/java/com/ruoyi/inspectiontask/pojo/QrCodeScanRecord.java b/src/main/java/com/ruoyi/inspectiontask/pojo/QrCodeScanRecord.java
new file mode 100644
index 0000000..fa00d05
--- /dev/null
+++ b/src/main/java/com/ruoyi/inspectiontask/pojo/QrCodeScanRecord.java
@@ -0,0 +1,68 @@
+package com.ruoyi.inspectiontask.pojo;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDateTime;
+
+/**
+ * @author :yys
+ * @date : 2025/9/19 10:29
+ */
+@Data
+@TableName("qr_code_scan_record")
+@ApiModel
+public class QrCodeScanRecord {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 鎵爜璁板綍鍞竴鏍囪瘑
+ */
+ @TableId(type = IdType.AUTO)
+ private Long id;
+
+ @ApiModelProperty(value = "鍏宠仈鐨勪簩缁寸爜ID")
+ private Long qrCodeId;
+
+ @ApiModelProperty(value = "鎵爜浜虹敤鎴稩D")
+ private Long scannerId;
+
+ @ApiModelProperty(value = "瀹為檯鎵爜鏃堕棿")
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime scanTime;
+
+ @ApiModelProperty(value = "绉熸埛ID锛岀敤浜庡绉熸埛闅旂")
+ @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT)
+ private Integer tenantId;
+
+ @ApiModelProperty(value = "杞垹闄ゆ爣蹇楋紝0=鏈垹闄わ紝1=宸插垹闄�")
+ private Integer deleted;
+
+ @ApiModelProperty(value = "鍒涘缓璇ヨ褰曠殑鐢ㄦ埛")
+ @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT)
+ private Integer createUser;
+
+ @ApiModelProperty(value = "璁板綍鍒涘缓鏃堕棿")
+ @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime createTime;
+
+ @ApiModelProperty(value = "鏈�鍚庝慨鏀硅璁板綍鐨勭敤鎴�")
+ @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT_UPDATE)
+ private Integer updateBy;
+
+ @ApiModelProperty(value = "璁板綍鏈�鍚庢洿鏂版椂闂�")
+ @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT_UPDATE)
+ private LocalDateTime updateTime;
+
+}
diff --git a/src/main/java/com/ruoyi/inspectiontask/pojo/TimingTask.java b/src/main/java/com/ruoyi/inspectiontask/pojo/TimingTask.java
new file mode 100644
index 0000000..41099ea
--- /dev/null
+++ b/src/main/java/com/ruoyi/inspectiontask/pojo/TimingTask.java
@@ -0,0 +1,97 @@
+package com.ruoyi.inspectiontask.pojo;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+/**
+ * @author :yys
+ * @date : 2025/9/19 10:27
+ */
+@Data
+@ApiModel
+@TableName("timing_task")
+public class TimingTask {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 涓婚敭ID
+ */
+ @TableId(type = IdType.AUTO)
+ private Long id;
+
+ @ApiModelProperty(value = "浠诲姟鍚嶇О")
+ private String taskName;
+
+ @ApiModelProperty(value = "宸℃浜�")
+ private String inspectorIds;
+
+ @ApiModelProperty(value = "宸℃鍦扮偣")
+ private String inspectionLocation;
+
+ @ApiModelProperty(value = "棰戞")
+ private String frequencyType;
+
+ @ApiModelProperty(value = "棰戞璇︽儏")
+ private String frequencyDetail;
+
+ @ApiModelProperty(value = "涓嬫鎵ц鏃堕棿")
+ private LocalDateTime nextExecutionTime;
+
+ @ApiModelProperty(value = "鏈�鍚庢墽琛屾椂闂�")
+ private LocalDateTime lastExecutionTime;
+
+ @ApiModelProperty(value = "鏄惁婵�娲�")
+ private boolean isActive;
+
+ @ApiModelProperty(value = "澶囨敞")
+ private String remarks;
+
+ @ApiModelProperty(value = "鐧昏浜篿d")
+ private Long registrantId;
+
+ @ApiModelProperty(value = "鐧昏浜�")
+ private String registrant;
+
+ @ApiModelProperty(value = "鐧昏鏃ユ湡")
+ private LocalDate registrationDate;
+
+ @ApiModelProperty(value = "鐘舵��")
+ private String status;
+
+ @ApiModelProperty(value = "杞垹闄ゆ爣蹇楋紝0=鏈垹闄わ紝1=宸插垹闄�")
+ private Integer deleted;
+
+ @ApiModelProperty(value = "鍒涘缓璇ヨ褰曠殑鐢ㄦ埛")
+ @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT)
+ private Integer createUser;
+
+ @ApiModelProperty(value = "璁板綍鍒涘缓鏃堕棿")
+ @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime createTime;
+
+ @ApiModelProperty(value = "鏈�鍚庝慨鏀硅璁板綍鐨勭敤鎴�")
+ @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT_UPDATE)
+ private Integer updateUser;
+
+ @ApiModelProperty(value = "璁板綍鏈�鍚庢洿鏂版椂闂�")
+ @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT_UPDATE)
+ private LocalDateTime updateTime;
+
+ @ApiModelProperty(value = "绉熸埛ID")
+ @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT)
+ private Integer tenantId;
+
+}
diff --git a/src/main/java/com/ruoyi/inspectiontask/service/InspectionTaskService.java b/src/main/java/com/ruoyi/inspectiontask/service/InspectionTaskService.java
new file mode 100644
index 0000000..de175f2
--- /dev/null
+++ b/src/main/java/com/ruoyi/inspectiontask/service/InspectionTaskService.java
@@ -0,0 +1,20 @@
+package com.ruoyi.inspectiontask.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.inspectiontask.dto.InspectionTaskDto;
+import com.ruoyi.inspectiontask.pojo.InspectionTask;
+
+/**
+ * @author :yys
+ * @date : 2025/9/19 10:49
+ */
+public interface InspectionTaskService extends IService<InspectionTask> {
+
+ IPage<InspectionTaskDto> selectInspectionTaskList(Page<InspectionTask> page, InspectionTaskDto inspectionTaskDto);
+
+ int addOrEditInspectionTask(InspectionTaskDto inspectionTaskDto);
+
+ int delByIds(Long[] ids);
+}
diff --git a/src/main/java/com/ruoyi/inspectiontask/service/QrCodeScanRecordService.java b/src/main/java/com/ruoyi/inspectiontask/service/QrCodeScanRecordService.java
new file mode 100644
index 0000000..8d3cbab
--- /dev/null
+++ b/src/main/java/com/ruoyi/inspectiontask/service/QrCodeScanRecordService.java
@@ -0,0 +1,20 @@
+package com.ruoyi.inspectiontask.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.inspectiontask.dto.QrCodeScanRecordDto;
+import com.ruoyi.inspectiontask.pojo.QrCodeScanRecord;
+
+/**
+ * @author :yys
+ * @date : 2025/9/19 10:50
+ */
+public interface QrCodeScanRecordService extends IService<QrCodeScanRecord> {
+
+ IPage<QrCodeScanRecordDto> selectQrCodeScanRecordList(Page<QrCodeScanRecord> page, QrCodeScanRecordDto qrCodeScanRecordDto);
+
+ int addOrEditQrCodeRecord(QrCodeScanRecordDto qrCodeScanRecordDto);
+
+ int delByIds(Long[] ids);
+}
diff --git a/src/main/java/com/ruoyi/inspectiontask/service/QrCodeService.java b/src/main/java/com/ruoyi/inspectiontask/service/QrCodeService.java
new file mode 100644
index 0000000..0eeecd2
--- /dev/null
+++ b/src/main/java/com/ruoyi/inspectiontask/service/QrCodeService.java
@@ -0,0 +1,19 @@
+package com.ruoyi.inspectiontask.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.inspectiontask.dto.QrCodeDto;
+import com.ruoyi.inspectiontask.pojo.QrCode;
+
+/**
+ * @author :yys
+ * @date : 2025/9/19 10:50
+ */
+public interface QrCodeService extends IService<QrCode>{
+ IPage<QrCode> selectQrCodeList(Page page, QrCodeDto qrCodeDto);
+
+ Long addOrEditQrCode(QrCodeDto qrCodeDto);
+
+ int delByIds(Long[] ids);
+}
diff --git a/src/main/java/com/ruoyi/inspectiontask/service/TimingTaskService.java b/src/main/java/com/ruoyi/inspectiontask/service/TimingTaskService.java
new file mode 100644
index 0000000..8d00032
--- /dev/null
+++ b/src/main/java/com/ruoyi/inspectiontask/service/TimingTaskService.java
@@ -0,0 +1,23 @@
+package com.ruoyi.inspectiontask.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.inspectiontask.dto.TimingTaskDto;
+import com.ruoyi.inspectiontask.pojo.TimingTask;
+import org.quartz.SchedulerException;
+
+/**
+ * @author :yys
+ * @date : 2025/9/19 10:51
+ */
+public interface TimingTaskService extends IService<TimingTask> {
+
+ IPage<TimingTaskDto> selectTimingTaskList(Page<TimingTask> page, TimingTask timingTask);
+
+ int addOrEditTimingTask(TimingTaskDto timingTaskDto) throws SchedulerException;
+
+ int delByIds(Long[] ids);
+
+ void updateTaskExecutionTime(Long taskId);
+}
diff --git a/src/main/java/com/ruoyi/inspectiontask/service/impl/InspectionTaskServiceImpl.java b/src/main/java/com/ruoyi/inspectiontask/service/impl/InspectionTaskServiceImpl.java
new file mode 100644
index 0000000..26e3bdd
--- /dev/null
+++ b/src/main/java/com/ruoyi/inspectiontask/service/impl/InspectionTaskServiceImpl.java
@@ -0,0 +1,257 @@
+package com.ruoyi.inspectiontask.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.basic.dto.StorageBlobDTO;
+import com.ruoyi.basic.mapper.StorageAttachmentMapper;
+import com.ruoyi.basic.mapper.StorageBlobMapper;
+import com.ruoyi.basic.pojo.StorageAttachment;
+import com.ruoyi.basic.pojo.StorageBlob;
+import com.ruoyi.basic.service.StorageAttachmentService;
+import com.ruoyi.common.utils.MinioUtils;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.bean.BeanUtils;
+import com.ruoyi.inspectiontask.dto.InspectionTaskDto;
+import com.ruoyi.inspectiontask.mapper.InspectionTaskMapper;
+import com.ruoyi.inspectiontask.pojo.InspectionTask;
+import com.ruoyi.inspectiontask.service.InspectionTaskService;
+import com.ruoyi.project.system.domain.SysUser;
+import com.ruoyi.project.system.mapper.SysUserMapper;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.*;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import static com.ruoyi.common.constant.StorageAttachmentConstants.StorageAttachmentFile;
+import static com.ruoyi.common.enums.StorageAttachmentRecordType.InspectionTasks;
+
+/**
+ * @author :yys
+ * @date : 2025/9/19 10:54
+ */
+@Service
+@Slf4j
+public class InspectionTaskServiceImpl extends ServiceImpl<InspectionTaskMapper, InspectionTask> implements InspectionTaskService {
+
+
+ @Autowired
+ private InspectionTaskMapper inspectionTaskMapper;
+
+ @Autowired
+ private StorageAttachmentService storageAttachmentService;
+
+ @Autowired
+ private StorageBlobMapper storageBlobMapper;
+
+ @Autowired
+ private StorageAttachmentMapper storageAttachmentMapper;
+
+ @Autowired
+ private MinioUtils minioUtils;
+
+ @Autowired
+ private SysUserMapper sysUserMapper;
+
+ @Override
+ public IPage<InspectionTaskDto> selectInspectionTaskList(Page<InspectionTask> page, InspectionTaskDto inspectionTaskDto) {
+ LambdaQueryWrapper<InspectionTask> queryWrapper = new LambdaQueryWrapper<>();
+ queryWrapper.orderByDesc(InspectionTask::getCreateTime);
+ IPage<InspectionTask> entityPage = inspectionTaskMapper.selectPage(page, queryWrapper);
+
+ // 鏃犳暟鎹彁鍓嶈繑鍥�
+ if (CollectionUtils.isEmpty(entityPage.getRecords())) {
+ return new Page<>(entityPage.getCurrent(), entityPage.getSize(), entityPage.getTotal());
+ }
+ // 鑾峰彇id闆嗗悎
+ List<Long> ids = entityPage.getRecords().stream().map(InspectionTask::getId).toList();
+ //鐧昏浜篿ds
+ List<Long> registrantIds = entityPage.getRecords().stream().map(InspectionTask::getRegistrantId).toList();
+ // 鎵归噺鏌ヨ鐧昏浜�
+ Map<Long, SysUser> sysUserMap;
+ if (!registrantIds.isEmpty()) {
+ List<SysUser> sysUsers = sysUserMapper.selectList(registrantIds);
+ sysUserMap = sysUsers.stream().collect(Collectors.toMap(SysUser::getUserId, Function.identity()));
+ } else {
+ sysUserMap = new HashMap<>();
+ }
+ //宸℃浜篿ds
+ List<String> inspectorIds = entityPage.getRecords().stream().map(InspectionTask::getInspectorId).toList();
+
+ //鑾峰彇鎵�鏈変笉閲嶅鐨勭敤鎴稩D
+ Set<Long> allUserIds = entityPage.getRecords().stream()
+ .map(InspectionTask::getInspectorId) // 鑾峰彇"2,3"杩欐牱鐨勫瓧绗︿覆
+ .filter(StringUtils::isNotBlank)
+ .flatMap(idsStr -> Arrays.stream(idsStr.split(",")))
+ .map(idStr -> {
+ try {
+ return Long.parseLong(idStr.trim());
+ } catch (NumberFormatException e) {
+ return null;
+ }
+ })
+ .filter(Objects::nonNull)
+ .collect(Collectors.toSet());
+
+ // 浣跨敤SQL鎵归噺鏌ヨ鐢ㄦ埛淇℃伅
+ Map<Long, String> userIdToNameMap = allUserIds.isEmpty()
+ ? Collections.emptyMap()
+ : sysUserMapper.selectUsersByIds(new ArrayList<>(allUserIds))
+ .stream()
+ .collect(Collectors.toMap(
+ SysUser::getUserId,
+ SysUser::getNickName,
+ (existing, replacement) -> existing));
+
+ //澶勭悊闄勪欢
+ Map<Long, List<StorageAttachment>> attachmentsMap = storageAttachmentMapper.selectList(new LambdaQueryWrapper<StorageAttachment>().in(StorageAttachment::getRecordId, ids)
+ .eq(StorageAttachment::getRecordType, InspectionTasks.ordinal()))
+ .stream()
+ .collect(Collectors.groupingBy(StorageAttachment::getRecordId));
+ // 鎵归噺鏌ヨ鎵�鏈夐渶瑕佺殑鏂囦欢鏁版嵁
+ Set<Long> blobIds = attachmentsMap.values()
+ .stream()
+ .flatMap(List::stream)
+ .map(StorageAttachment::getStorageBlobId)
+ .collect(Collectors.toSet());
+ Map<Long, StorageBlob> blobMap = blobIds.isEmpty()
+ ? Collections.emptyMap()
+ : storageBlobMapper.selectList(new LambdaQueryWrapper<StorageBlob>().in(StorageBlob::getId, blobIds))
+ .stream()
+ .collect(Collectors.toMap(StorageBlob::getId, Function.identity()));
+
+ List<InspectionTaskDto> dtoList = entityPage.getRecords().stream().map(inspectionTask -> {
+ InspectionTaskDto dto = new InspectionTaskDto();
+ BeanUtils.copyProperties(inspectionTask, dto); // 澶嶅埗涓诲璞″睘鎬�
+
+ // 璁剧疆鐧昏浜�
+ SysUser sysUser = sysUserMap.get(inspectionTask.getRegistrantId());
+ if (sysUser != null) {
+ dto.setRegistrant(sysUser.getNickName());
+ }
+ // 澶勭悊宸℃浜哄悕绉�
+ if (StringUtils.isNotBlank(inspectionTask.getInspectorId())) {
+ String inspectorNames = Arrays.stream(inspectionTask.getInspectorId().split(","))
+ .map(String::trim)
+ .map(idStr -> {
+ try {
+ Long userId = Long.parseLong(idStr);
+ return userIdToNameMap.getOrDefault(userId, "鏈煡鐢ㄦ埛(" + idStr + ")");
+ } catch (NumberFormatException e) {
+ return "鏃犳晥ID(" + idStr + ")";
+ }
+ })
+ .collect(Collectors.joining(","));
+ dto.setInspector(inspectorNames);
+ }
+
+ // 鍒濆鍖栦笁涓檮浠跺垪琛�
+ dto.setBeforeProduction(new ArrayList<>());
+ dto.setAfterProduction(new ArrayList<>());
+ dto.setProductionIssues(new ArrayList<>());
+
+ // 澶勭悊闄勪欢鍒嗙被
+ Optional.ofNullable(attachmentsMap.get(inspectionTask.getId()))
+ .orElse(Collections.emptyList())
+ .forEach(attachment -> {
+ StorageBlob blob = blobMap.get(attachment.getStorageBlobId());
+ if (blob != null) {
+ // 鍒涘缓闄勪欢DTO
+ StorageBlobDTO blobDto = createBlobDto(blob);
+
+ // 鏍规嵁type鍒嗙被
+ switch ((int) blob.getType().longValue()) {
+ case 0:
+ dto.getBeforeProduction().add(blobDto);
+ break;
+ case 1:
+ dto.getAfterProduction().add(blobDto);
+ break;
+ case 2:
+ dto.getProductionIssues().add(blobDto);
+ break;
+ default:
+ // 鍙�夛細璁板綍鏈垎绫荤被鍨�
+ break;
+ }
+ }
+ });
+
+ return dto;
+ }).collect(Collectors.toList());
+
+ // 7. 鏋勫缓杩斿洖鍒嗛〉瀵硅薄
+ IPage<InspectionTaskDto> resultPage = new Page<>();
+ BeanUtils.copyProperties(entityPage, resultPage);
+ resultPage.setRecords(dtoList);
+ return resultPage;
+ }
+
+ // 鎻愬彇鍒涘缓BlobDTO鐨勫叕鍏辨柟娉�
+ private StorageBlobDTO createBlobDto(StorageBlob blob) {
+ StorageBlobDTO dto = new StorageBlobDTO();
+ BeanUtils.copyProperties(blob, dto);
+
+ // 璁剧疆URL
+ dto.setUrl(minioUtils.getPreviewUrls(
+ blob.getBucketFilename(),
+ blob.getBucketName(),
+ true
+ ));
+
+ // 璁剧疆涓嬭浇URL
+ dto.setDownloadUrl(minioUtils.getDownloadUrls(
+ blob.getBucketFilename(),
+ blob.getBucketName(),
+ blob.getOriginalFilename(),
+ true
+ ));
+ return dto;
+ }
+
+ @Override
+ public int addOrEditInspectionTask(InspectionTaskDto inspectionTaskDto) {
+ InspectionTask inspectionTask = new InspectionTask();
+ BeanUtils.copyProperties(inspectionTaskDto, inspectionTask);
+ inspectionTask.setRegistrantId(SecurityUtils.getLoginUser().getUserId());
+ inspectionTask.setRegistrant(SecurityUtils.getLoginUser().getUsername());
+ int i;
+ if (Objects.isNull(inspectionTaskDto.getId())) {
+ i = inspectionTaskMapper.insert(inspectionTask);
+ } else {
+ i = inspectionTaskMapper.updateById(inspectionTask);
+ }
+
+ if (inspectionTaskDto.getStorageBlobDTO() != null && !inspectionTaskDto.getStorageBlobDTO().isEmpty()) {
+ List<StorageAttachment> attachments = new ArrayList<>();
+
+ for (StorageBlobDTO storageBlobDTO : inspectionTaskDto.getStorageBlobDTO()) {
+ StorageAttachment storageAttachment = new StorageAttachment(
+ StorageAttachmentFile,
+ (long) InspectionTasks.ordinal(),
+ inspectionTask.getId()
+ );
+ storageAttachment.setStorageBlobDTO(storageBlobDTO);
+ attachments.add(storageAttachment);
+ }
+ storageAttachmentService.saveStorageAttachment(attachments, inspectionTask.getId(), InspectionTasks, StorageAttachmentFile);
+ }
+ return i;
+ }
+
+ @Override
+ public int delByIds(Long[] ids) {
+ // 妫�鏌ュ弬鏁�
+ if (ids == null || ids.length == 0) {
+ return 0;
+ }
+ return inspectionTaskMapper.deleteBatchIds(Arrays.asList(ids));
+ }
+
+}
diff --git a/src/main/java/com/ruoyi/inspectiontask/service/impl/QrCodeScanRecordServiceImpl.java b/src/main/java/com/ruoyi/inspectiontask/service/impl/QrCodeScanRecordServiceImpl.java
new file mode 100644
index 0000000..5ac3038
--- /dev/null
+++ b/src/main/java/com/ruoyi/inspectiontask/service/impl/QrCodeScanRecordServiceImpl.java
@@ -0,0 +1,194 @@
+package com.ruoyi.inspectiontask.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.basic.dto.StorageBlobDTO;
+import com.ruoyi.basic.mapper.StorageAttachmentMapper;
+import com.ruoyi.basic.mapper.StorageBlobMapper;
+import com.ruoyi.basic.pojo.StorageAttachment;
+import com.ruoyi.basic.pojo.StorageBlob;
+import com.ruoyi.basic.service.StorageAttachmentService;
+import com.ruoyi.common.constant.StorageAttachmentConstants;
+import com.ruoyi.common.utils.MinioUtils;
+import com.ruoyi.common.utils.bean.BeanUtils;
+import com.ruoyi.inspectiontask.dto.QrCodeScanRecordDto;
+import com.ruoyi.inspectiontask.mapper.QrCodeMapper;
+import com.ruoyi.inspectiontask.mapper.QrCodeScanRecordMapper;
+import com.ruoyi.inspectiontask.pojo.QrCode;
+import com.ruoyi.inspectiontask.pojo.QrCodeScanRecord;
+import com.ruoyi.inspectiontask.service.QrCodeScanRecordService;
+import com.ruoyi.project.system.domain.SysUser;
+import com.ruoyi.project.system.mapper.SysUserMapper;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.*;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import static com.ruoyi.common.constant.StorageAttachmentConstants.StorageAttachmentFile;
+import static com.ruoyi.common.enums.StorageAttachmentRecordType.QrCodeScanRecords;
+
+/**
+ * @author :yys
+ * @date : 2025/9/19 10:54
+ */
+@Service
+@Slf4j
+public class QrCodeScanRecordServiceImpl extends ServiceImpl<QrCodeScanRecordMapper, QrCodeScanRecord> implements QrCodeScanRecordService {
+
+ @Autowired
+ private QrCodeScanRecordMapper qrCodeScanRecordMapper;
+
+ @Autowired
+ private QrCodeMapper qrCodeMapper;
+
+ @Autowired
+ private StorageAttachmentService storageAttachmentService;
+
+ @Autowired
+ private StorageBlobMapper storageBlobMapper;
+
+ @Autowired
+ private StorageAttachmentMapper storageAttachmentMapper;
+
+ @Autowired
+ private MinioUtils minioUtils;
+
+ @Autowired
+ private SysUserMapper sysUserMapper;
+
+ @Override
+ public IPage<QrCodeScanRecordDto> selectQrCodeScanRecordList(Page<QrCodeScanRecord> page, QrCodeScanRecordDto qrCodeScanRecordDto) {
+ // 1. 鏋勫缓鍩虹鏌ヨ鏉′欢
+ LambdaQueryWrapper<QrCodeScanRecord> queryWrapper = new LambdaQueryWrapper<>();
+ queryWrapper.orderByDesc(QrCodeScanRecord::getCreateTime);
+
+ // 2. 鎵ц鍒嗛〉鏌ヨ
+ IPage<QrCodeScanRecord> scanRecordIPage = qrCodeScanRecordMapper.selectPage(page, queryWrapper);
+
+ // 3. 鏃犳暟鎹彁鍓嶈繑鍥�
+ if (CollectionUtils.isEmpty(scanRecordIPage.getRecords())) {
+ return new Page<>(scanRecordIPage.getCurrent(), scanRecordIPage.getSize(), scanRecordIPage.getTotal());
+ }
+
+ // 4. 鎵归噺鑾峰彇鎵�鏈夎褰旾D鍜屼簩缁寸爜ID
+ List<Long> recordIds = scanRecordIPage.getRecords().stream()
+ .map(QrCodeScanRecord::getId)
+ .collect(Collectors.toList());
+
+ Set<Long> qrCodeIds = scanRecordIPage.getRecords().stream()
+ .map(QrCodeScanRecord::getQrCodeId)
+ .filter(Objects::nonNull)
+ .collect(Collectors.toSet());
+
+ // 5. 鎵归噺鏌ヨ鍏宠仈鏁版嵁锛堜娇鐢ㄦ渶鏂癆PI锛�
+ // 5.1 鏌ヨ浜岀淮鐮佷俊鎭紙鏇挎崲selectBatchIds涓簊electByIds锛�
+ Map<Long, QrCode> qrCodeMap = qrCodeIds.isEmpty()
+ ? Collections.emptyMap()
+ : qrCodeMapper.selectBatchIds(qrCodeIds).stream()
+ .collect(Collectors.toMap(QrCode::getId, Function.identity()));
+
+ // 5.2 鏌ヨ闄勪欢鍏宠仈鍏崇郴
+ Map<Long, List<StorageAttachment>> attachmentsMap = storageAttachmentMapper
+ .selectList(new LambdaQueryWrapper<StorageAttachment>()
+ .in(StorageAttachment::getRecordId, recordIds)
+ .eq(StorageAttachment::getRecordType, QrCodeScanRecords.ordinal()))
+ .stream()
+ .collect(Collectors.groupingBy(StorageAttachment::getRecordId));
+
+ // 5.3 鏌ヨ鏂囦欢鏁版嵁锛堜娇鐢╯electByIds锛�
+ Set<Long> blobIds = attachmentsMap.values().stream()
+ .flatMap(List::stream)
+ .map(StorageAttachment::getStorageBlobId)
+ .collect(Collectors.toSet());
+
+ Map<Long, StorageBlob> blobMap = blobIds.isEmpty()
+ ? Collections.emptyMap()
+ : storageBlobMapper.selectBatchIds(blobIds).stream()
+ .collect(Collectors.toMap(StorageBlob::getId, Function.identity()));
+
+ // 6. 缁勮DTO鏁版嵁
+ List<QrCodeScanRecordDto> dtoList = scanRecordIPage.getRecords().stream().map(record -> {
+ QrCodeScanRecordDto dto = new QrCodeScanRecordDto();
+ BeanUtils.copyProperties(record, dto);
+
+ SysUser sysUser = sysUserMapper.selectUserById(record.getScannerId());
+ dto.setScanner(sysUser.getNickName());
+
+ // 6.1 璁剧疆浜岀淮鐮佷俊鎭�
+ Optional.ofNullable(qrCodeMap.get(record.getQrCodeId()))
+ .ifPresent(qrCode -> {
+ BeanUtils.copyProperties(qrCode, dto); // 澶嶅埗鍒扮埗绫�
+ dto.setQrCode(qrCode); // 璁剧疆瀹屾暣瀵硅薄
+ });
+
+ // 6.2 璁剧疆闄勪欢淇℃伅
+ dto.setStorageBlobDTO(
+ Optional.ofNullable(attachmentsMap.get(record.getId()))
+ .orElse(Collections.emptyList())
+ .stream()
+ .map(att -> {
+ StorageBlobDTO blobDTO = new StorageBlobDTO();
+ Optional.ofNullable(blobMap.get(att.getStorageBlobId()))
+ .ifPresent(blob -> {
+ BeanUtils.copyProperties(blob, blobDTO);
+ blobDTO.setUrl(minioUtils.getPreviewUrls(blob.getBucketFilename(), blob.getBucketName(), true));
+ blobDTO.setDownloadUrl(minioUtils.getDownloadUrls(blob.getBucketFilename(),blob.getBucketName(),blob.getOriginalFilename(),true));
+ });
+ return blobDTO;
+ })
+ .filter(blobDTO -> blobDTO.getId() != null) // 杩囨护鏃犳晥闄勪欢
+ .collect(Collectors.toList())
+ );
+ return dto;
+ }).collect(Collectors.toList());
+
+ // 7. 鏋勫缓杩斿洖鍒嗛〉瀵硅薄
+ IPage<QrCodeScanRecordDto> resultPage = new Page<>();
+ BeanUtils.copyProperties(scanRecordIPage, resultPage);
+ resultPage.setRecords(dtoList);
+
+ return resultPage;
+ }
+
+ @Override
+ public int addOrEditQrCodeRecord(QrCodeScanRecordDto qrCodeScanRecordDto) {
+ QrCodeScanRecord qrCodeScanRecord = new QrCodeScanRecord();
+ BeanUtils.copyProperties(qrCodeScanRecordDto, qrCodeScanRecord);
+ int i;
+ if (Objects.isNull(qrCodeScanRecordDto.getId())) {
+ i = qrCodeScanRecordMapper.insert(qrCodeScanRecord);
+ } else {
+ i = qrCodeScanRecordMapper.updateById(qrCodeScanRecord);
+ }
+
+ if (qrCodeScanRecordDto.getStorageBlobDTO() != null && !qrCodeScanRecordDto.getStorageBlobDTO().isEmpty()) {
+ List<StorageAttachment> attachments = new ArrayList<>();
+
+ for (StorageBlobDTO storageBlobDTO : qrCodeScanRecordDto.getStorageBlobDTO()) {
+ StorageAttachment storageAttachment = new StorageAttachment(
+ StorageAttachmentFile,
+ (long) QrCodeScanRecords.ordinal(),
+ qrCodeScanRecord.getId()
+ );
+ storageAttachment.setStorageBlobDTO(storageBlobDTO);
+ attachments.add(storageAttachment);
+ }
+ storageAttachmentService.saveStorageAttachment(attachments, qrCodeScanRecord.getId(), QrCodeScanRecords, StorageAttachmentFile);
+ }
+ return i;
+ }
+
+ @Override
+ public int delByIds(Long[] ids) {
+ return qrCodeScanRecordMapper.deleteBatchIds(Arrays.asList(ids));
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/inspectiontask/service/impl/QrCodeServiceImpl.java b/src/main/java/com/ruoyi/inspectiontask/service/impl/QrCodeServiceImpl.java
new file mode 100644
index 0000000..e88a5d1
--- /dev/null
+++ b/src/main/java/com/ruoyi/inspectiontask/service/impl/QrCodeServiceImpl.java
@@ -0,0 +1,54 @@
+package com.ruoyi.inspectiontask.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.common.utils.bean.BeanUtils;
+import com.ruoyi.inspectiontask.dto.QrCodeDto;
+import com.ruoyi.inspectiontask.mapper.QrCodeMapper;
+import com.ruoyi.inspectiontask.pojo.QrCode;
+import com.ruoyi.inspectiontask.service.QrCodeService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.Arrays;
+import java.util.Objects;
+
+/**
+ * @author :yys
+ * @date : 2025/9/19 10:55
+ */
+@Service
+@Slf4j
+public class QrCodeServiceImpl extends ServiceImpl<QrCodeMapper, QrCode> implements QrCodeService {
+
+ @Autowired
+ private QrCodeMapper qrCodeMapper;
+
+ @Override
+ public IPage<QrCode> selectQrCodeList(Page page, QrCodeDto qrCodeDto) {
+ LambdaQueryWrapper<QrCode> queryWrapper = new LambdaQueryWrapper<>();
+ queryWrapper.orderByDesc(QrCode::getCreateTime);
+ return qrCodeMapper.selectPage(page, queryWrapper);
+ }
+
+ @Override
+ public Long addOrEditQrCode(QrCodeDto qrCodeDto) {
+ QrCode qrCode = new QrCode();
+ BeanUtils.copyProperties(qrCodeDto, qrCode);
+ if (Objects.isNull(qrCodeDto.getId())) {
+ qrCodeMapper.insert(qrCode);
+ } else {
+ qrCodeMapper.updateById(qrCode);
+ }
+ return qrCode.getId();
+ }
+
+ @Override
+ public int delByIds(Long[] ids) {
+ return qrCodeMapper.deleteBatchIds(Arrays.asList(ids));
+ }
+
+}
diff --git a/src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskJob.java b/src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskJob.java
new file mode 100644
index 0000000..efcd90f
--- /dev/null
+++ b/src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskJob.java
@@ -0,0 +1,65 @@
+package com.ruoyi.inspectiontask.service.impl;
+
+import com.ruoyi.inspectiontask.mapper.InspectionTaskMapper;
+import com.ruoyi.inspectiontask.pojo.InspectionTask;
+import com.ruoyi.inspectiontask.pojo.TimingTask;
+import com.ruoyi.inspectiontask.service.TimingTaskService;
+import org.quartz.*;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component
+@DisallowConcurrentExecution // 绂佹骞跺彂鎵ц鍚屼竴涓狫ob
+public class TimingTaskJob implements Job {
+
+ @Autowired
+ private
+ TimingTaskService timingTaskService;
+
+ @Autowired
+ private InspectionTaskMapper inspectionTaskMapper;
+
+ @Override
+ public void execute(JobExecutionContext context) throws JobExecutionException {
+ JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();
+ Long taskId = jobDataMap.getLong("taskId");
+
+ try {
+ // 1. 鑾峰彇瀹氭椂浠诲姟璇︽儏
+ TimingTask timingTask = timingTaskService.getById(taskId);
+ if (timingTask == null || !timingTask.isActive()) {
+ return;
+ }
+
+ // 2. 鍒涘缓骞朵繚瀛樺贰妫�浠诲姟璁板綍 - 杩欏氨鏄偍鎻愪緵鐨勪唬鐮佸簲璇ユ斁鐨勪綅缃�
+ InspectionTask inspectionTask = createInspectionTask(timingTask);
+ inspectionTaskMapper.insert(inspectionTask);
+
+ // 3. 鏇存柊瀹氭椂浠诲姟鐨勬墽琛屾椂闂�
+ timingTaskService.updateTaskExecutionTime(taskId);
+
+ // 4. 璁板綍鎵ц鏃ュ織
+// timingTaskService.recordExecutionLog(taskId, true, "浠诲姟鎵ц鎴愬姛锛岀敓鎴愬贰妫�浠诲姟ID: " + inspectionTask.getId());
+
+ } catch (Exception e) {
+// timingTaskService.recordExecutionLog(taskId, false, "浠诲姟鎵ц澶辫触: " + e.getMessage());
+ throw new JobExecutionException(e);
+ }
+ }
+
+ // 杩欏氨鏄偍鎻愪緵鐨勪唬鐮佸皝瑁呮垚鐨勬柟娉�
+ private InspectionTask createInspectionTask(TimingTask timingTask) {
+ InspectionTask inspectionTask = new InspectionTask();
+
+ // 澶嶅埗鍩烘湰灞炴��
+ inspectionTask.setTaskName(timingTask.getTaskName());
+ inspectionTask.setInspectorId(timingTask.getInspectorIds());
+ inspectionTask.setInspectionLocation(timingTask.getInspectionLocation());
+ inspectionTask.setRemarks("鑷姩鐢熸垚鑷畾鏃朵换鍔D: " + timingTask.getId());
+ inspectionTask.setRegistrantId(timingTask.getRegistrantId());
+ inspectionTask.setFrequencyType(timingTask.getFrequencyType());
+ inspectionTask.setFrequencyDetail(timingTask.getFrequencyDetail());
+
+ return inspectionTask;
+ }
+}
diff --git a/src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskScheduler.java b/src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskScheduler.java
new file mode 100644
index 0000000..cb63d96
--- /dev/null
+++ b/src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskScheduler.java
@@ -0,0 +1,234 @@
+package com.ruoyi.inspectiontask.service.impl;
+
+import com.ruoyi.inspectiontask.pojo.TimingTask;
+import org.quartz.*;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.time.LocalTime;
+import java.time.ZoneId;
+import java.time.format.DateTimeParseException;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.stream.Collectors;
+
+@Service
+public class TimingTaskScheduler {
+
+ @Autowired
+ private Scheduler scheduler;
+
+ /**
+ * 娣诲姞鏂颁换鍔″埌璋冨害鍣�
+ */
+ public void scheduleTimingTask(TimingTask task) throws SchedulerException {
+ JobDetail jobDetail = buildJobDetail(task);
+ Trigger trigger = buildJobTrigger(task, jobDetail);
+ scheduler.scheduleJob(jobDetail, trigger);
+ }
+
+ /**
+ * 鏇存柊宸叉湁浠诲姟
+ */
+ public void rescheduleTimingTask(TimingTask task) throws SchedulerException {
+ TriggerKey triggerKey = new TriggerKey("trigger_" + task.getId());
+
+ // 鑾峰彇鐜版湁瑙﹀彂鍣ㄥ苟杞崲涓� CronTrigger
+ Trigger oldTrigger = scheduler.getTrigger(triggerKey);
+ if (!(oldTrigger instanceof CronTrigger)) {
+ throw new SchedulerException("Existing trigger is not a CronTrigger");
+ }
+
+ // 鏋勫缓鏂拌Е鍙戝櫒
+ Trigger newTrigger = TriggerBuilder.newTrigger()
+ .withIdentity(triggerKey)
+ .withDescription(task.getTaskName())
+ .withSchedule(CronScheduleBuilder.cronSchedule(convertToCronExpression(task)))
+ .startAt(Date.from(task.getNextExecutionTime().atZone(ZoneId.systemDefault()).toInstant()))
+ .forJob(oldTrigger.getJobKey())
+ .build();
+
+ scheduler.rescheduleJob(triggerKey, newTrigger);
+ }
+
+ /**
+ * 鏆傚仠浠诲姟
+ */
+ public void pauseTimingTask(Long taskId) throws SchedulerException {
+ JobKey jobKey = new JobKey("timingTask_" + taskId);
+ scheduler.pauseJob(jobKey);
+ }
+
+ /**
+ * 鎭㈠浠诲姟
+ */
+ public void resumeTimingTask(Long taskId) throws SchedulerException {
+ JobKey jobKey = new JobKey("timingTask_" + taskId);
+ scheduler.resumeJob(jobKey);
+ }
+
+ /**
+ * 鍒犻櫎浠诲姟
+ */
+ public void unscheduleTimingTask(Long taskId) throws SchedulerException {
+ JobKey jobKey = new JobKey("timingTask_" + taskId);
+ scheduler.deleteJob(jobKey);
+ }
+
+ private JobDetail buildJobDetail(TimingTask task) {
+ JobDataMap jobDataMap = new JobDataMap();
+ jobDataMap.put("taskId", task.getId());
+
+ return JobBuilder.newJob(TimingTaskJob.class)
+ .withIdentity("timingTask_" + task.getId())
+ .withDescription(task.getTaskName())
+ .usingJobData(jobDataMap)
+ .storeDurably()
+ .build();
+ }
+
+ private Trigger buildJobTrigger(TimingTask task, JobDetail jobDetail) {
+ String cronExpression = convertToCronExpression(task);
+
+ TriggerBuilder<CronTrigger> triggerBuilder = TriggerBuilder.newTrigger()
+ .withIdentity("trigger_" + task.getId())
+ .withDescription(task.getTaskName())
+ .withSchedule(CronScheduleBuilder.cronSchedule(cronExpression));
+
+ if (jobDetail != null) {
+ triggerBuilder.forJob(jobDetail);
+ }
+
+ if (task.getNextExecutionTime() != null) {
+ triggerBuilder.startAt(Date.from(task.getNextExecutionTime().atZone(ZoneId.systemDefault()).toInstant()));
+ }
+
+ return triggerBuilder.build();
+ }
+
+ private String convertToCronExpression(TimingTask task) {
+ // 鍙傛暟鏍¢獙
+ if (task == null || task.getFrequencyType() == null || task.getFrequencyDetail() == null) {
+ throw new IllegalArgumentException("浠诲姟鍙傛暟涓嶈兘涓虹┖");
+ }
+
+ // 浣跨敤switch纭繚鏉′欢浜掓枼
+ return switch (task.getFrequencyType().toUpperCase()) { // 缁熶竴杞负澶у啓姣旇緝
+ case "DAILY" -> convertDailyToCron(task.getFrequencyDetail());
+ case "WEEKLY" -> convertWeeklyToCron(task.getFrequencyDetail());
+ case "MONTHLY" -> convertMonthlyToCron(task.getFrequencyDetail());
+ case "QUARTERLY" -> convertQuarterlyToCron(task.getFrequencyDetail());
+ default -> throw new IllegalArgumentException("涓嶆敮鎸佺殑棰戠巼绫诲瀷: " + task.getFrequencyType());
+ };
+ }
+
+ // 姣忔棩浠诲姟杞崲
+ private String convertDailyToCron(String frequencyDetail) {
+ LocalTime time = parseTime(frequencyDetail);
+ return String.format("0 %d %d * * ?", time.getMinute(), time.getHour());
+ }
+
+ // 姣忓懆浠诲姟杞崲
+ private String convertWeeklyToCron(String frequencyDetail) {
+ String[] parts = validateAndSplit(frequencyDetail, ",", 2);
+ String daysOfWeek = convertDayNamesToCron(parts[0]);
+ LocalTime time = parseTime(parts[1]);
+ return String.format("0 %d %d ? * %s", time.getMinute(), time.getHour(), daysOfWeek);
+ }
+
+ // 姣忔湀浠诲姟杞崲
+ private String convertMonthlyToCron(String frequencyDetail) {
+ String[] parts = validateAndSplit(frequencyDetail, ",", 2);
+ int day = validateDayOfMonth(parts[0]);
+ LocalTime time = parseTime(parts[1]);
+ return String.format("0 %d %d %d * ?", time.getMinute(), time.getHour(), day);
+ }
+
+ // 姣忓搴︿换鍔¤浆鎹�
+ private String convertQuarterlyToCron(String frequencyDetail) {
+ String[] parts = validateAndSplit(frequencyDetail, ",", 3);
+ int month = validateMonth(parts[0]); // 楠岃瘉鏈堜唤(1-12)
+ int day = validateDayOfMonth(parts[1]); // 楠岃瘉鏃ユ湡
+ LocalTime time = parseTime(parts[2]); // 瑙f瀽鏃堕棿
+
+ // 璁$畻瀛e害璧峰鏈堜唤(1鏈�=1, 4鏈�=4, 7鏈�=7, 10鏈�=10)
+ int quarterStartMonth = ((month - 1) / 3) * 3 + 1;
+
+ return String.format("0 %d %d %d %d/3 ?",
+ time.getMinute(),
+ time.getHour(),
+ day,
+ quarterStartMonth);
+ }
+
+ // 鏂板楠岃瘉鏈堜唤鐨勬柟娉�(1-12)
+ private int validateMonth(String monthStr) {
+ try {
+ int month = Integer.parseInt(monthStr);
+ if (month < 1 || month > 12) {
+ throw new IllegalArgumentException("鏈堜唤蹇呴』鍦�1-12涔嬮棿");
+ }
+ return month;
+ } catch (NumberFormatException e) {
+ throw new IllegalArgumentException("鏃犳晥鐨勬湀浠芥牸寮�");
+ }
+ }
+
+ // 杈呭姪鏂规硶锛氳В鏋愭椂闂�
+ private LocalTime parseTime(String timeStr) {
+ try {
+ return LocalTime.parse(timeStr);
+ } catch (DateTimeParseException e) {
+ throw new IllegalArgumentException("鏃堕棿鏍煎紡蹇呴』涓篐H:mm", e);
+ }
+ }
+
+ // 杈呭姪鏂规硶锛氶獙璇佸苟鍒嗗壊瀛楃涓�
+ private String[] validateAndSplit(String input, String delimiter, int expectedParts) {
+ String[] parts = input.split(delimiter);
+ if (parts.length != expectedParts) {
+ throw new IllegalArgumentException(
+ String.format("鏍煎紡閿欒锛屽簲涓�%d閮ㄥ垎鐢�'%s'鍒嗛殧", expectedParts, delimiter));
+ }
+ return parts;
+ }
+
+ // 杈呭姪鏂规硶锛氶獙璇佹湀浠戒腑鐨勬棩
+ private int validateDayOfMonth(String dayStr) {
+ int day = Integer.parseInt(dayStr);
+ if (day < 1 || day > 31) {
+ throw new IllegalArgumentException("鏃ユ湡蹇呴』鍦�1-31涔嬮棿");
+ }
+ return day;
+ }
+
+ // 杈呭姪鏂规硶锛氶獙璇佸搴︿腑鐨勬湀
+ private int validateMonthInQuarter(String monthStr) {
+ int month = Integer.parseInt(monthStr);
+ if (month < 1 || month > 3) {
+ throw new IllegalArgumentException("瀛e害鏈堜唤蹇呴』鏄�1銆�2鎴�3");
+ }
+ return month;
+ }
+
+ // 杞崲鏄熸湡鍑犲悕绉�
+ private String convertDayNamesToCron(String dayNames) {
+ return Arrays.stream(dayNames.split("\\|"))
+ .map(this::convertSingleDayName)
+ .collect(Collectors.joining(","));
+ }
+
+ // 杞崲鍗曚釜鏄熸湡鍑犲悕绉�
+ private String convertSingleDayName(String dayName) {
+ switch (dayName.toUpperCase()) {
+ case "MON": return "MON";
+ case "TUE": return "TUE";
+ case "WED": return "WED";
+ case "THU": return "THU";
+ case "FRI": return "FRI";
+ case "SAT": return "SAT";
+ case "SUN": return "SUN";
+ default: throw new IllegalArgumentException("鏃犳晥鐨勬槦鏈熷嚑: " + dayName);
+ }
+ }
+}
diff --git a/src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskServiceImpl.java b/src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskServiceImpl.java
new file mode 100644
index 0000000..511fbd7
--- /dev/null
+++ b/src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskServiceImpl.java
@@ -0,0 +1,348 @@
+package com.ruoyi.inspectiontask.service.impl;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.bean.BeanUtils;
+import com.ruoyi.inspectiontask.dto.TimingTaskDto;
+import com.ruoyi.inspectiontask.mapper.InspectionTaskMapper;
+import com.ruoyi.inspectiontask.mapper.TimingTaskMapper;
+import com.ruoyi.inspectiontask.pojo.TimingTask;
+import com.ruoyi.inspectiontask.service.TimingTaskService;
+import com.ruoyi.project.system.domain.SysUser;
+import com.ruoyi.project.system.mapper.SysUserMapper;
+import lombok.extern.slf4j.Slf4j;
+import org.quartz.SchedulerException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.time.*;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * @author :yys
+ * @date : 2025/9/19 10:55
+ */
+@Service
+@Slf4j
+public class TimingTaskServiceImpl extends ServiceImpl<TimingTaskMapper, TimingTask> implements TimingTaskService {
+
+ @Autowired
+ private TimingTaskMapper timingTaskMapper;
+
+ @Autowired
+ private InspectionTaskMapper inspectionTaskMapper;
+
+ @Autowired
+ private TimingTaskScheduler timingTaskScheduler;
+
+ @Autowired
+ private SysUserMapper sysUserMapper;
+
+
+ @Override
+ public IPage<TimingTaskDto> selectTimingTaskList(Page<TimingTask> page, TimingTask timingTask) {
+ // 1. 鍏堝垎椤垫煡璇㈠畾鏃朵换鍔℃暟鎹�
+ IPage<TimingTask> taskPage = timingTaskMapper.selectPage(page, null);
+
+ // 2. 濡傛灉娌℃湁鏁版嵁锛岀洿鎺ヨ繑鍥炵┖鍒嗛〉
+ if (taskPage.getRecords().isEmpty()) {
+ return new Page<>(taskPage.getCurrent(), taskPage.getSize(), taskPage.getTotal());
+ }
+
+ // 3. 鏀堕泦鎵�鏈夐渶瑕佹煡璇㈢殑鐢ㄦ埛ID
+ Set<Long> userIds = new HashSet<>();
+
+ // 鏀堕泦鐧昏浜篒D
+ taskPage.getRecords().forEach(task -> {
+ if (task.getRegistrantId() != null) {
+ userIds.add(task.getRegistrantId());
+ }
+ });
+
+ // 鏀堕泦宸℃浜篒D锛堝涓狪D浠ラ�楀彿鍒嗛殧锛�
+ taskPage.getRecords().forEach(task -> {
+ if (StringUtils.isNotBlank(task.getInspectorIds())) {
+ Arrays.stream(task.getInspectorIds().split(","))
+ .filter(StringUtils::isNotBlank)
+ .map(Long::valueOf)
+ .forEach(userIds::add);
+ }
+ });
+
+ // 4. 鎵归噺鏌ヨ鐢ㄦ埛淇℃伅
+ Map<Long, String> userNickNameMap = new HashMap<>();
+ if (!userIds.isEmpty()) {
+ List<SysUser> users = sysUserMapper.selectUserByIds((List<Long>) userIds);
+ users.forEach(user -> userNickNameMap.put(user.getUserId(), user.getNickName()));
+ }
+
+ // 5. 杞崲涓篋TO
+ List<TimingTaskDto> dtoList = taskPage.getRecords().stream().map(task -> {
+ TimingTaskDto dto = new TimingTaskDto();
+ // 澶嶅埗鍩烘湰灞炴��
+ BeanUtils.copyProperties(task, dto);
+
+ // 璁剧疆鐧昏浜烘樀绉�
+ if (task.getRegistrantId() != null) {
+ dto.setRegistrant(userNickNameMap.getOrDefault(task.getRegistrantId(), "鏈煡鐢ㄦ埛"));
+ }
+
+ // 璁剧疆宸℃浜烘樀绉板垪琛�
+ if (StringUtils.isNotBlank(task.getInspectorIds())) {
+ List<String> inspectorNickNames = Arrays.stream(task.getInspectorIds().split(","))
+ .filter(StringUtils::isNotBlank)
+ .map(idStr -> {
+ Long id = Long.valueOf(idStr);
+ return userNickNameMap.getOrDefault(id, "鏈煡鐢ㄦ埛");
+ })
+ .toList();
+ dto.setInspector(inspectorNickNames);
+ }
+
+ return dto;
+ }).collect(Collectors.toList());
+
+ // 6. 鏋勫缓杩斿洖鐨勫垎椤靛璞�
+ Page<TimingTaskDto> resultPage = new Page<>(taskPage.getCurrent(), taskPage.getSize(), taskPage.getTotal());
+ resultPage.setRecords(dtoList);
+ return resultPage;
+ }
+
+ @Override
+ @Transactional
+ public int addOrEditTimingTask(TimingTaskDto timingTaskDto) throws SchedulerException {
+ TimingTask timingTask = new TimingTask();
+ BeanUtils.copyProperties(timingTaskDto, timingTask);
+
+ // 璁剧疆鍒涘缓浜轰俊鎭拰榛樿鍊�
+ if (Objects.isNull(timingTaskDto.getId())) {
+ timingTask.setRegistrationDate(LocalDate.now());
+ timingTask.setActive(true);
+
+ // 璁$畻棣栨鎵ц鏃堕棿
+ LocalDateTime firstExecutionTime = calculateFirstExecutionTime(timingTask);
+ timingTask.setNextExecutionTime(firstExecutionTime);
+
+ int result = timingTaskMapper.insert(timingTask);
+ if (result > 0) {
+ // 鏂板鎴愬姛鍚庢坊鍔犲埌璋冨害鍣�
+ timingTaskScheduler.scheduleTimingTask(timingTask);
+ }
+ return result;
+ } else {
+ int result = timingTaskMapper.updateById(timingTask);
+ if (result > 0) {
+ // 鏇存柊鎴愬姛鍚庨噸鏂拌皟搴︿换鍔�
+ timingTaskScheduler.rescheduleTimingTask(timingTask);
+ }
+ return result;
+ }
+ }
+
+ private LocalDateTime calculateFirstExecutionTime(TimingTask task) {
+ // 鏍规嵁棰戠巼绫诲瀷鍜岃鎯呰绠楅娆℃墽琛屾椂闂�
+ return switch (task.getFrequencyType()) {
+ case "DAILY" ->
+ // 濡傛灉鏄瘡澶╂墽琛岋紝璁$畻浠婂ぉ鎴栨槑澶╃殑鍏蜂綋鏃堕棿
+ calculateDailyFirstExecution(task.getFrequencyDetail());
+ case "WEEKLY" ->
+ // 濡傛灉鏄瘡鍛ㄦ墽琛岋紝璁$畻涓嬪懆鐨勫叿浣撴槦鏈熷嚑
+ calculateWeeklyFirstExecution(task.getFrequencyDetail());
+ case "MONTHLY" ->
+ // 濡傛灉鏄瘡鏈堟墽琛岋紝璁$畻涓嬩釜鏈堢殑鍏蜂綋鏃ユ湡
+ calculateMonthlyFirstExecution(task.getFrequencyDetail());
+ case "QUARTERLY" ->
+ // 鑷畾涔夐鐜囷紝濡傛瘡灏忔椂銆佹瘡30鍒嗛挓绛�
+ calculateCustomFirstExecution(task.getFrequencyDetail());
+ default -> throw new IllegalArgumentException("涓嶆敮鎸佺殑棰戠巼绫诲瀷: " + task.getFrequencyType());
+ };
+ }
+
+ private LocalDateTime calculateDailyFirstExecution(String frequencyDetail) {
+ // frequencyDetail鍙兘鏄叿浣撴椂闂达紝濡� "14:30"
+ LocalTime executionTime = LocalTime.parse(frequencyDetail);
+ LocalDateTime now = LocalDateTime.now();
+ LocalDateTime todayExecution = LocalDateTime.of(now.toLocalDate(), executionTime);
+
+ // 濡傛灉浠婂ぉ鐨勬椂闂村凡杩囷紝鍒欏畨鎺掓槑澶╂墽琛�
+ return now.isBefore(todayExecution) ? todayExecution : todayExecution.plusDays(1);
+ }
+
+ private LocalDateTime calculateWeeklyFirstExecution(String frequencyDetail) {
+ return null;
+ }
+
+ private LocalDateTime calculateMonthlyFirstExecution(String frequencyDetail) {
+ return null;
+ }
+
+ private LocalDateTime calculateCustomFirstExecution(String frequencyDetail) {
+ return null;
+ }
+
+ @Override
+ @Transactional
+ public void updateTaskExecutionTime(Long taskId) {
+ TimingTask task = timingTaskMapper.selectById(taskId);
+ if (task == null) {
+ throw new RuntimeException("瀹氭椂浠诲姟涓嶅瓨鍦紝ID: " + taskId);
+ }
+
+ // 鏇存柊鏈�鍚庢墽琛屾椂闂翠负褰撳墠鏃堕棿
+ task.setLastExecutionTime(LocalDateTime.now());
+
+ // 璁$畻涓嬫鎵ц鏃堕棿
+ LocalDateTime nextExecutionTime = calculateNextExecutionTime(
+ task.getFrequencyType(),
+ task.getFrequencyDetail(),
+ LocalDateTime.now()
+ );
+ task.setNextExecutionTime(nextExecutionTime);
+
+ // 鏇存柊鏁版嵁搴�
+ timingTaskMapper.updateById(task);
+ }
+
+ /**
+ * 璁$畻涓嬫鎵ц鏃堕棿
+ */
+ private LocalDateTime calculateNextExecutionTime(String frequencyType,
+ String frequencyDetail,
+ LocalDateTime currentTime) {
+ try {
+ return switch (frequencyType) {
+ case "DAILY" -> calculateDailyNextTime(frequencyDetail, currentTime);
+ case "WEEKLY" -> calculateWeeklyNextTime(frequencyDetail, currentTime);
+ case "MONTHLY" -> calculateMonthlyNextTime(frequencyDetail, currentTime);
+ case "QUARTERLY" -> calculateQuarterlyNextTime(frequencyDetail, currentTime);
+ default -> throw new IllegalArgumentException("涓嶆敮鎸佺殑棰戠巼绫诲瀷: " + frequencyType);
+ };
+ } catch (Exception e) {
+ throw new RuntimeException("璁$畻涓嬫鎵ц鏃堕棿澶辫触: " + e.getMessage(), e);
+ }
+ }
+
+ /**
+ * 璁$畻姣忔棩浠诲姟鐨勪笅娆℃墽琛屾椂闂�
+ */
+ private LocalDateTime calculateDailyNextTime(String timeStr, LocalDateTime current) {
+ LocalTime executionTime = LocalTime.parse(timeStr); // 瑙f瀽鏍煎紡 "HH:mm"
+ LocalDateTime nextTime = LocalDateTime.of(current.toLocalDate(), executionTime);
+
+ // 濡傛灉浠婂ぉ鐨勬椂闂村凡杩囷紝鍒欏畨鎺掓槑澶�
+ return current.isBefore(nextTime) ? nextTime : nextTime.plusDays(1);
+ }
+
+ /**
+ * 璁$畻姣忓懆浠诲姟鐨勪笅娆℃墽琛屾椂闂�
+ */
+ private LocalDateTime calculateWeeklyNextTime(String detail, LocalDateTime current) {
+ String[] parts = detail.split(",");
+ String dayOfWeekStr = parts[0]; // 濡� "MON" 鎴� "MON|WED|FRI"
+ LocalTime time = LocalTime.parse(parts[1]); // 鏃堕棿閮ㄥ垎
+
+ // 瑙f瀽鏄熸湡鍑�(鏀寔澶氫釜鏄熸湡)
+ Set<DayOfWeek> targetDays = parseDayOfWeeks(dayOfWeekStr);
+
+ // 浠庡綋鍓嶆椂闂村紑濮嬫壘涓嬩竴涓鍚堟潯浠剁殑鏄熸湡鍑�
+ LocalDateTime nextTime = current;
+ while (true) {
+ nextTime = nextTime.plusDays(1);
+ if (targetDays.contains(nextTime.getDayOfWeek())) {
+ return LocalDateTime.of(nextTime.toLocalDate(), time);
+ }
+
+ // 闃叉鏃犻檺寰幆(鐞嗚涓婁笉浼氬彂鐢�)
+ if (nextTime.isAfter(current.plusYears(1))) {
+ throw new RuntimeException("鏃犳硶鎵惧埌涓嬫鎵ц鏃堕棿");
+ }
+ }
+ }
+
+ /**
+ * 璁$畻姣忔湀浠诲姟鐨勪笅娆℃墽琛屾椂闂�
+ */
+ private LocalDateTime calculateMonthlyNextTime(String detail, LocalDateTime current) {
+ String[] parts = detail.split(",");
+ int dayOfMonth = Integer.parseInt(parts[0]);
+ LocalTime time = LocalTime.parse(parts[1]);
+
+ // 浠庝笅涓湀寮�濮嬭绠�
+ LocalDateTime nextTime = current.plusMonths(1)
+ .withDayOfMonth(Math.min(dayOfMonth, current.plusMonths(1).toLocalDate().lengthOfMonth()))
+ .with(time);
+
+ return nextTime;
+ }
+
+ /**
+ * 璁$畻姣忓搴︿换鍔$殑涓嬫鎵ц鏃堕棿
+ */
+ private LocalDateTime calculateQuarterlyNextTime(String detail, LocalDateTime current) {
+ String[] parts = detail.split(",");
+ int quarterMonth = Integer.parseInt(parts[0]); // 1=绗�1涓湀锛�2=绗�2涓湀锛�3=绗�3涓湀
+ int dayOfMonth = Integer.parseInt(parts[1]);
+ LocalTime time = LocalTime.parse(parts[2]);
+
+ // 璁$畻褰撳墠瀛e害
+ int currentQuarter = (current.getMonthValue() - 1) / 3 + 1;
+ int currentMonthInQuarter = (current.getMonthValue() - 1) % 3 + 1;
+
+ YearMonth targetYearMonth;
+ if (currentMonthInQuarter < quarterMonth) {
+ // 鏈搴﹀唴杩樻湁鎵ц鏈轰細
+ targetYearMonth = YearMonth.from(current)
+ .plusMonths(quarterMonth - currentMonthInQuarter);
+ } else {
+ // 闇�瑕佸埌涓嬩釜瀛e害
+ targetYearMonth = YearMonth.from(current)
+ .plusMonths(3 - currentMonthInQuarter + quarterMonth);
+ }
+
+ // 澶勭悊鏈堟湯鏃ユ湡
+ int adjustedDay = Math.min(dayOfMonth, targetYearMonth.lengthOfMonth());
+
+ return LocalDateTime.of(
+ targetYearMonth.getYear(),
+ targetYearMonth.getMonthValue(),
+ adjustedDay,
+ time.getHour(),
+ time.getMinute()
+ );
+ }
+
+ /**
+ * 瑙f瀽鏄熸湡鍑犲瓧绗︿覆
+ */
+ private Set<DayOfWeek> parseDayOfWeeks(String dayOfWeekStr) {
+ Set<DayOfWeek> days = new HashSet<>();
+ String[] dayStrs = dayOfWeekStr.split("\\|");
+
+ for (String dayStr : dayStrs) {
+ switch (dayStr) {
+ case "MON": days.add(DayOfWeek.MONDAY); break;
+ case "TUE": days.add(DayOfWeek.TUESDAY); break;
+ case "WED": days.add(DayOfWeek.WEDNESDAY); break;
+ case "THU": days.add(DayOfWeek.THURSDAY); break;
+ case "FRI": days.add(DayOfWeek.FRIDAY); break;
+ case "SAT": days.add(DayOfWeek.SATURDAY); break;
+ case "SUN": days.add(DayOfWeek.SUNDAY); break;
+ default: throw new IllegalArgumentException("鏃犳晥鐨勬槦鏈熷嚑: " + dayStr);
+ }
+ }
+
+ return days;
+ }
+
+
+
+ @Override
+ public int delByIds(Long[] ids) {
+ return timingTaskMapper.deleteBatchIds(Arrays.asList(ids));
+ }
+
+}
diff --git a/src/main/java/com/ruoyi/procurementrecord/controller/ProcurementPlanController.java b/src/main/java/com/ruoyi/procurementrecord/controller/ProcurementPlanController.java
new file mode 100644
index 0000000..64d9dc8
--- /dev/null
+++ b/src/main/java/com/ruoyi/procurementrecord/controller/ProcurementPlanController.java
@@ -0,0 +1,67 @@
+package com.ruoyi.procurementrecord.controller;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.framework.web.controller.BaseController;
+import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.procurementrecord.pojo.ProcurementPlan;
+import com.ruoyi.procurementrecord.service.ProcurementPlanService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletResponse;
+import java.util.List;
+
+/**
+ * @author :yys
+ * @date : 2025/9/18 16:13
+ */
+@RestController
+@Api(tags = "閲囪喘璁″垝")
+@RequestMapping("/procurementPlan")
+public class ProcurementPlanController extends BaseController {
+
+ @Autowired
+ private ProcurementPlanService procurementPlanService;
+
+ @RequestMapping("/listPage")
+ @ApiOperation("閲囪喘璁″垝-鏌ヨ")
+ public AjaxResult listPage(Page page, ProcurementPlan procurementPlan){
+ IPage<ProcurementPlan> result = procurementPlanService.listPage(page, procurementPlan);
+ return AjaxResult.success(result);
+ }
+
+ @PostMapping("/add")
+ @ApiOperation("閲囪喘璁″垝-娣诲姞")
+ public AjaxResult add(@RequestBody ProcurementPlan procurementPlan){
+ boolean result = procurementPlanService.save(procurementPlan);
+ return result ? AjaxResult.success() : AjaxResult.error();
+ }
+
+ @PostMapping("/update")
+ @ApiOperation("閲囪喘璁″垝-淇敼")
+ public AjaxResult update(@RequestBody ProcurementPlan procurementPlan){
+ boolean result = procurementPlanService.updateById(procurementPlan);
+ return result ? AjaxResult.success() : AjaxResult.error();
+ }
+
+ @DeleteMapping("/del")
+ @ApiOperation("閲囪喘璁″垝-鍒犻櫎")
+ public AjaxResult del(@RequestBody List<Long> ids){
+ boolean result = procurementPlanService.removeByIds(ids);
+ return result ? AjaxResult.success() : AjaxResult.error();
+ }
+
+ /**
+ * 瀵煎嚭
+ * @param response
+ */
+ @PostMapping("/export")
+ public void export(HttpServletResponse response) {
+ procurementPlanService.export(response);
+ }
+
+
+}
diff --git a/src/main/java/com/ruoyi/procurementrecord/mapper/ProcurementPlanMapper.java b/src/main/java/com/ruoyi/procurementrecord/mapper/ProcurementPlanMapper.java
new file mode 100644
index 0000000..2745574
--- /dev/null
+++ b/src/main/java/com/ruoyi/procurementrecord/mapper/ProcurementPlanMapper.java
@@ -0,0 +1,22 @@
+package com.ruoyi.procurementrecord.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.procurementrecord.pojo.ProcurementPlan;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * @author :yys
+ * @date : 2025/9/18 16:10
+ */
+public interface ProcurementPlanMapper extends BaseMapper<ProcurementPlan> {
+ /**
+ * 鏌ヨ閲囪喘璁″垝鍒楄〃
+ *
+ * @param page
+ * @param procurementPlan
+ * @return
+ */
+ IPage<ProcurementPlan> listPage(Page page,@Param("req") ProcurementPlan procurementPlan);
+}
diff --git a/src/main/java/com/ruoyi/procurementrecord/pojo/ProcurementPlan.java b/src/main/java/com/ruoyi/procurementrecord/pojo/ProcurementPlan.java
new file mode 100644
index 0000000..56892a3
--- /dev/null
+++ b/src/main/java/com/ruoyi/procurementrecord/pojo/ProcurementPlan.java
@@ -0,0 +1,105 @@
+package com.ruoyi.procurementrecord.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDateTime;
+
+/**
+ * @author :yys
+ * @date : 2025/9/18 16:00
+ */
+@Data
+@TableName("procurement_plan")
+@ApiModel
+public class ProcurementPlan {
+
+ private static final long serialVersionUID = 1L;
+ /**
+ * 搴忓彿
+ */
+ @TableId(type = IdType.AUTO)
+ private Long id;
+
+ @ApiModelProperty(value = "缂栫爜")
+ @Excel(name = "缂栫爜")
+ private String code;
+
+ @ApiModelProperty(value = "鍚嶇О")
+ @Excel(name = "鍚嶇О")
+ private String planName;
+
+ @ApiModelProperty(value = "鎻忚堪")
+ @Excel(name = "鎻忚堪")
+ private String description;
+
+ @ApiModelProperty(value = "鐘舵��")
+ @Excel(name = "鐘舵��", readConverterExp = "disabled=绂佺敤,active=鍚敤")
+ private String status;
+
+ @ApiModelProperty(value = "鏄惁绯荤粺棰勭疆")
+ private Boolean isSystemPreset;
+
+ @ApiModelProperty(value = "鑰冭檻鐜版湁搴撳瓨")
+ private Boolean considerExistingStock;
+
+ @ApiModelProperty(value = "浠撳簱杩愯MRP鐨勬帶鍒�")
+ private Boolean warehouseControl;
+
+ @ApiModelProperty(value = "璁$畻鎬婚渶姹�")
+ private Boolean calculateTotalDemand;
+
+ @ApiModelProperty(value = "鑰冭檻瀹夊叏搴撳瓨")
+ private Boolean considerSafetyStock;
+
+ @ApiModelProperty(value = "鑰冭檻閿佸簱")
+ private Boolean considerLockedStock;
+
+ @ApiModelProperty(value = "涓嶈�冭檻鐗╂枡杈呭姪灞炴��")
+ private Boolean notConsiderMaterialAux;
+
+ @ApiModelProperty(value = "璐熷簱瀛樹綔涓洪渶姹�")
+ private Boolean negativeStockAsDemand;
+
+ @ApiModelProperty(value = "鐗╂枡")
+ private Boolean summaryMaterial;
+
+ @ApiModelProperty(value = "杈呭姪灞炴��")
+ private Boolean summaryAuxAttributes;
+
+ @ApiModelProperty(value = "闇�姹傛棩鏈�")
+ private Boolean summaryDemandDate;
+
+ @ApiModelProperty(value = "璁$畻鍏紡")
+ @Excel(name = "璁$畻鍏紡")
+ private String formula;
+
+ @ApiModelProperty(value = "鍒涘缓鏃堕棿")
+ @TableField(fill = FieldFill.INSERT)
+ private LocalDateTime createTime;
+
+ @ApiModelProperty(value = "鍒涘缓鐢ㄦ埛")
+ @TableField(fill = FieldFill.INSERT)
+ private Integer createUser;
+
+ @ApiModelProperty(value = "淇敼鏃堕棿")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ @Excel(name = "鏈�鍚庤绠楁椂闂�", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime updateTime;
+
+ @ApiModelProperty(value = "淇敼鐢ㄦ埛")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private Integer updateUser;
+
+ @ApiModelProperty(value = "绉熸埛ID")
+ @TableField(fill = FieldFill.INSERT)
+ private Long tenantId;
+
+}
diff --git a/src/main/java/com/ruoyi/procurementrecord/service/ProcurementPlanService.java b/src/main/java/com/ruoyi/procurementrecord/service/ProcurementPlanService.java
new file mode 100644
index 0000000..e96dbe6
--- /dev/null
+++ b/src/main/java/com/ruoyi/procurementrecord/service/ProcurementPlanService.java
@@ -0,0 +1,25 @@
+package com.ruoyi.procurementrecord.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.procurementrecord.pojo.ProcurementPlan;
+
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * @author :yys
+ * @date : 2025/9/18 16:11
+ */
+public interface ProcurementPlanService extends IService<ProcurementPlan> {
+
+ /**
+ * 鏌ヨ
+ * @param page
+ * @param procurementPlan
+ * @return
+ */
+ IPage<ProcurementPlan> listPage(Page page, ProcurementPlan procurementPlan);
+
+ void export(HttpServletResponse response);
+}
diff --git a/src/main/java/com/ruoyi/procurementrecord/service/impl/ProcurementPlanServiceImpl.java b/src/main/java/com/ruoyi/procurementrecord/service/impl/ProcurementPlanServiceImpl.java
new file mode 100644
index 0000000..81216db
--- /dev/null
+++ b/src/main/java/com/ruoyi/procurementrecord/service/impl/ProcurementPlanServiceImpl.java
@@ -0,0 +1,41 @@
+package com.ruoyi.procurementrecord.service.impl;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.procurementrecord.mapper.ProcurementPlanMapper;
+import com.ruoyi.procurementrecord.pojo.ProcurementPlan;
+import com.ruoyi.procurementrecord.pojo.ProcurementPriceManagement;
+import com.ruoyi.procurementrecord.service.ProcurementPlanService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import javax.servlet.http.HttpServletResponse;
+import java.util.List;
+
+/**
+ * @author :yys
+ * @date : 2025/9/18 16:12
+ */
+@Service
+@Slf4j
+public class ProcurementPlanServiceImpl extends ServiceImpl<ProcurementPlanMapper, ProcurementPlan> implements ProcurementPlanService {
+
+ @Autowired
+ private ProcurementPlanMapper procurementPlanMapper;
+
+ @Override
+ public IPage<ProcurementPlan> listPage(Page page, ProcurementPlan procurementPlan) {
+ IPage<ProcurementPlan> result = procurementPlanMapper.listPage(page, procurementPlan);
+ return result;
+ }
+
+ @Override
+ public void export(HttpServletResponse response) {
+ List<ProcurementPlan> procurementPriceManagements = procurementPlanMapper.selectList(null);
+ ExcelUtil<ProcurementPlan> util = new ExcelUtil<ProcurementPlan>(ProcurementPlan.class);
+ util.exportExcel(response, procurementPriceManagements, "閲囪喘璁″垝");
+ }
+}
diff --git a/src/main/java/com/ruoyi/project/system/mapper/SysUserMapper.java b/src/main/java/com/ruoyi/project/system/mapper/SysUserMapper.java
index 9f7003a..550fa51 100644
--- a/src/main/java/com/ruoyi/project/system/mapper/SysUserMapper.java
+++ b/src/main/java/com/ruoyi/project/system/mapper/SysUserMapper.java
@@ -1,10 +1,13 @@
package com.ruoyi.project.system.mapper;
+import java.util.ArrayList;
import java.util.List;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import com.ruoyi.project.system.domain.SysUser;
+import org.springframework.beans.PropertyValues;
/**
* 鐢ㄦ埛琛� 鏁版嵁灞�
@@ -134,4 +137,8 @@
* @return 缁撴灉
*/
public SysUser checkEmailUnique(String email);
+
+ List<SysUser> selectList(List<Long> registrantIds);
+
+ List<SysUser> selectUsersByIds(@Param("userIds") List<Long> userIds);
}
diff --git a/src/main/resources/mapper/procurementrecord/ProcurementPlanMapper.xml b/src/main/resources/mapper/procurementrecord/ProcurementPlanMapper.xml
new file mode 100644
index 0000000..2403bf2
--- /dev/null
+++ b/src/main/resources/mapper/procurementrecord/ProcurementPlanMapper.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+ "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.procurementrecord.mapper.ProcurementPlanMapper">
+
+ <select id="listPage" resultType="com.ruoyi.procurementrecord.pojo.ProcurementPlan">
+ SELECT * FROM procurement_plan
+ <where>
+ <if test="req.status != null and req.status != ''">
+ AND status = #{req.status}
+ </if>
+ <if test="req.planName != null and req.planName != ''">
+ AND plan_name LIKE CONCAT('%',#{req.planName},'%')
+ </if>
+ </where>
+ </select>
+</mapper>
\ No newline at end of file
diff --git a/src/main/resources/mapper/system/SysUserMapper.xml b/src/main/resources/mapper/system/SysUserMapper.xml
index e1a12c6..f77e62c 100644
--- a/src/main/resources/mapper/system/SysUserMapper.xml
+++ b/src/main/resources/mapper/system/SysUserMapper.xml
@@ -158,6 +158,28 @@
#{item}
</foreach>
</select>
+ <select id="selectList" resultType="com.ruoyi.project.system.domain.SysUser">
+ SELECT user_id, nick_name FROM sys_user
+ <where>
+ <if test="list != null and list.size() > 0">
+ user_id IN
+ <foreach item="id" collection="list" open="(" separator="," close=")">
+ #{id}
+ </foreach>
+ </if>
+ <if test="list == null or list.size() == 0">
+ 1=0 <!-- 绌哄垪琛ㄦ椂杩斿洖绌虹粨鏋� -->
+ </if>
+ </where>
+ </select>
+ <select id="selectUsersByIds" resultType="com.ruoyi.project.system.domain.SysUser">
+ SELECT user_id, nick_name
+ FROM sys_user
+ WHERE user_id IN
+ <foreach collection="userIds" item="id" open="(" separator="," close=")">
+ #{id}
+ </foreach>
+ </select>
<insert id="insertUser" parameterType="com.ruoyi.project.system.domain.SysUser" useGeneratedKeys="true" keyProperty="userId">
insert into sys_user(
--
Gitblit v1.9.3