From d17d4d1ac98865d2a71b4f24771b7b76e0839ed3 Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期五, 10 四月 2026 14:08:41 +0800
Subject: [PATCH] yys 1.设备区域 2.设备巡检,维保,保养多选 3.数采

---
 src/main/resources/mapper/measuringinstrumentledger/MeasuringInstrumentLedgerMapper.xml |    6 
 src/main/java/com/ruoyi/device/service/impl/DeviceAreaServiceImpl.java                  |  194 +++++
 src/main/java/com/ruoyi/inspectiontask/service/impl/InspectionTaskServiceImpl.java      |   32 
 src/main/resources/mapper/device/DeviceMaintenanceMapper.xml                            |    6 
 src/main/java/com/ruoyi/device/dto/DeviceMaintenanceDto.java                            |    7 
 src/main/java/com/ruoyi/device/dto/DeviceRepairDto.java                                 |   12 
 src/main/java/com/ruoyi/inspectiontask/pojo/TimingTask.java                             |   33 
 src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskJob.java                  |  199 ++--
 src/main/java/com/ruoyi/http/service/impl/RealTimeEnergyConsumptionServiceImpl.java     |  127 ++-
 src/main/java/com/ruoyi/device/service/impl/DeviceRepairServiceImpl.java                |  103 +-
 src/main/java/com/ruoyi/device/service/impl/DeviceMaintenanceServiceImpl.java           |   84 +
 sql/device_records_add_area_id.sql                                                      |   14 
 src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskJob.java                     |  179 ++--
 src/main/resources/mapper/device/DeviceLedgerMapper.xml                                 |   95 +-
 src/main/java/com/ruoyi/device/pojo/DeviceArea.java                                     |   61 +
 src/main/java/com/ruoyi/device/service/IDeviceAreaService.java                          |   25 
 src/main/java/com/ruoyi/device/pojo/DeviceLedger.java                                   |   64 -
 src/main/java/com/ruoyi/device/dto/DeviceAreaTreeDto.java                               |   26 
 src/main/java/com/ruoyi/inspectiontask/pojo/InspectionTask.java                         |   18 
 src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskServiceImpl.java          |  286 +++----
 src/main/java/com/ruoyi/device/pojo/DeviceRepair.java                                   |    7 
 src/main/java/com/ruoyi/device/pojo/MaintenanceTask.java                                |   37 
 sql/device_area.sql                                                                     |   14 
 src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskServiceImpl.java             |   95 ++
 src/main/java/com/ruoyi/device/execl/DeviceLedgerExeclDto.java                          |   97 -
 src/main/java/com/ruoyi/device/dto/DeviceLedgerDto.java                                 |   61 -
 src/main/resources/mapper/device/DeviceRepairMapper.xml                                 |   10 
 src/main/java/com/ruoyi/device/controller/DeviceAreaController.java                     |   69 +
 sql/timing_task_add_task_ids_str.sql                                                    |    2 
 src/main/java/com/ruoyi/device/mapper/DeviceAreaMapper.java                             |   14 
 src/main/java/com/ruoyi/http/service/controller/JclyController.java                     |   51 +
 src/main/java/com/ruoyi/device/pojo/DeviceMaintenance.java                              |   12 
 src/main/resources/mapper/device/DeviceAreaMapper.xml                                   |   22 
 33 files changed, 1,296 insertions(+), 766 deletions(-)

diff --git a/sql/device_area.sql b/sql/device_area.sql
new file mode 100644
index 0000000..b97b8dd
--- /dev/null
+++ b/sql/device_area.sql
@@ -0,0 +1,14 @@
+CREATE TABLE `device_area` (
+  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '涓婚敭ID',
+  `area_name` varchar(100) NOT NULL COMMENT '鍖哄煙鍚嶇О',
+  `parent_id` bigint DEFAULT NULL COMMENT '鐖剁骇ID',
+  `sort` bigint DEFAULT 0 COMMENT '鎺掑簭',
+  `remark` varchar(255) DEFAULT NULL COMMENT '澶囨敞',
+  `create_time` datetime DEFAULT NULL COMMENT '鍒涘缓鏃堕棿',
+  `update_time` datetime DEFAULT NULL COMMENT '鏇存柊鏃堕棿',
+  `create_user` int DEFAULT NULL COMMENT '鍒涘缓鐢ㄦ埛',
+  `update_user` int DEFAULT NULL COMMENT '鏇存柊鐢ㄦ埛',
+  `tenant_id` bigint DEFAULT NULL COMMENT '绉熸埛ID',
+  `dept_id` bigint DEFAULT NULL COMMENT '閮ㄩ棬ID',
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='璁惧鍖哄煙';
diff --git a/sql/device_records_add_area_id.sql b/sql/device_records_add_area_id.sql
new file mode 100644
index 0000000..66ae477
--- /dev/null
+++ b/sql/device_records_add_area_id.sql
@@ -0,0 +1,14 @@
+ALTER TABLE `device_maintenance`
+    ADD COLUMN `area_id` bigint DEFAULT NULL COMMENT '璁惧鍖哄煙id' AFTER `device_ledger_id`;
+
+ALTER TABLE `device_repair`
+    ADD COLUMN `area_id` bigint DEFAULT NULL COMMENT '璁惧鍖哄煙id' AFTER `device_ledger_id`;
+
+ALTER TABLE `inspection_task`
+    ADD COLUMN `area_id` bigint DEFAULT NULL COMMENT '璁惧鍖哄煙id' AFTER `task_id`;
+
+ALTER TABLE `timing_task`
+    ADD COLUMN `area_id` bigint DEFAULT NULL COMMENT '璁惧鍖哄煙id' AFTER `task_id`;
+
+ALTER TABLE `maintenance_task`
+    ADD COLUMN `area_id` bigint DEFAULT NULL COMMENT '璁惧鍖哄煙id' AFTER `task_id`;
diff --git a/sql/timing_task_add_task_ids_str.sql b/sql/timing_task_add_task_ids_str.sql
new file mode 100644
index 0000000..c58fe8e
--- /dev/null
+++ b/sql/timing_task_add_task_ids_str.sql
@@ -0,0 +1,2 @@
+ALTER TABLE `timing_task`
+    ADD COLUMN `task_ids_str` varchar(1000) DEFAULT NULL COMMENT '璁惧ID闆嗗悎' AFTER `task_id`;
diff --git a/src/main/java/com/ruoyi/device/controller/DeviceAreaController.java b/src/main/java/com/ruoyi/device/controller/DeviceAreaController.java
new file mode 100644
index 0000000..52d4a80
--- /dev/null
+++ b/src/main/java/com/ruoyi/device/controller/DeviceAreaController.java
@@ -0,0 +1,69 @@
+package com.ruoyi.device.controller;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.device.pojo.DeviceArea;
+import com.ruoyi.device.service.IDeviceAreaService;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
+import com.ruoyi.framework.web.domain.AjaxResult;
+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.*;
+
+import java.util.List;
+
+@Api(tags = "璁惧鍖哄煙绠$悊")
+@RestController
+@RequestMapping("/device/area")
+public class DeviceAreaController {
+
+    @Autowired
+    private IDeviceAreaService deviceAreaService;
+
+    @GetMapping("/tree")
+    @ApiOperation("璁惧鍖哄煙鏍�")
+    public AjaxResult tree() {
+        return AjaxResult.success(deviceAreaService.listTree());
+    }
+
+    @GetMapping("/treeWithDevices")
+    @ApiOperation("璁惧鍖哄煙鏍�-鍖呭惈璁惧鍒楄〃")
+    public AjaxResult treeWithDevices() {
+        return AjaxResult.success(deviceAreaService.listTreeWithDevices());
+    }
+
+    @GetMapping("/page")
+    @ApiOperation("璁惧鍖哄煙鍒嗛〉")
+    public AjaxResult page(Page page, DeviceArea deviceArea) {
+        return AjaxResult.success(deviceAreaService.queryPage(page, deviceArea));
+    }
+
+    @GetMapping("/{id}")
+    @ApiOperation("璁惧鍖哄煙璇︽儏")
+    public AjaxResult detail(@PathVariable Long id) {
+        return AjaxResult.success(deviceAreaService.getById(id));
+    }
+
+    @PostMapping
+    @ApiOperation("鏂板璁惧鍖哄煙")
+    @Log(title = "璁惧鍖哄煙", businessType = BusinessType.INSERT)
+    public AjaxResult add(@RequestBody DeviceArea deviceArea) {
+        return deviceAreaService.saveDeviceArea(deviceArea);
+    }
+
+    @PutMapping
+    @ApiOperation("淇敼璁惧鍖哄煙")
+    @Log(title = "璁惧鍖哄煙", businessType = BusinessType.UPDATE)
+    public AjaxResult update(@RequestBody DeviceArea deviceArea) {
+        return deviceAreaService.updateDeviceArea(deviceArea);
+    }
+
+    @DeleteMapping
+    @ApiOperation("鍒犻櫎璁惧鍖哄煙")
+    @Log(title = "璁惧鍖哄煙", businessType = BusinessType.DELETE)
+    public AjaxResult delete(@RequestBody List<Long> ids) {
+        return deviceAreaService.removeDeviceAreas(ids);
+    }
+}
diff --git a/src/main/java/com/ruoyi/device/dto/DeviceAreaTreeDto.java b/src/main/java/com/ruoyi/device/dto/DeviceAreaTreeDto.java
new file mode 100644
index 0000000..8cff44b
--- /dev/null
+++ b/src/main/java/com/ruoyi/device/dto/DeviceAreaTreeDto.java
@@ -0,0 +1,26 @@
+package com.ruoyi.device.dto;
+
+import com.ruoyi.device.pojo.DeviceLedger;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class DeviceAreaTreeDto {
+
+    private Long id;
+
+    private Long parentId;
+
+    private String areaName;
+
+    private String label;
+
+    private Long sort;
+
+    private String remark;
+
+    private List<DeviceLedger> deviceList;
+
+    private List<DeviceAreaTreeDto> children;
+}
diff --git a/src/main/java/com/ruoyi/device/dto/DeviceLedgerDto.java b/src/main/java/com/ruoyi/device/dto/DeviceLedgerDto.java
index 75d9250..17ecb06 100644
--- a/src/main/java/com/ruoyi/device/dto/DeviceLedgerDto.java
+++ b/src/main/java/com/ruoyi/device/dto/DeviceLedgerDto.java
@@ -13,106 +13,56 @@
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 
-/**
- * 璁惧鍙拌处瀹炰綋绫�
- */
 @Data
 @TableName("device_ledger")
 public class DeviceLedgerDto extends DateQueryDto {
 
-    /**
-     * 涓婚敭ID锛岃嚜澧�
-     */
-
     private Long id;
 
-    /**
-     * 璁惧鍚嶇О
-     */
     private String deviceName;
 
-    /**
-     * 瑙勬牸鍨嬪彿
-     */
     private String deviceModel;
 
-    /**
-     * 璁惧鍝佺墝
-     */
     @ApiModelProperty("璁惧鍝佺墝")
     private String deviceBrand;
 
-    /**
-     * 瀛樻斁浣嶇疆
-     */
     @ApiModelProperty("瀛樻斁浣嶇疆")
     private String storageLocation;
 
+    @ApiModelProperty("璁惧鍖哄煙ID")
+    private Long areaId;
 
-    /**
-     * 渚涘簲鍟嗗悕绉�
-     */
+    @ApiModelProperty("璁惧鍖哄煙鍚嶇О")
+    private String areaName;
+
     private String supplierName;
 
-    /**
-     * 鍗曚綅
-     */
     private String unit;
 
-    /**
-     * 鏁伴噺
-     */
     private BigDecimal number;
 
-    /**
-     * 鍚◣鍗曚环
-     */
     private BigDecimal taxIncludingPriceUnit;
 
-    /**
-     * 鍚◣鎬讳环
-     */
     private BigDecimal taxIncludingPriceTotal;
 
-    /**
-     * 绋庣巼
-     */
     private BigDecimal taxRate;
 
-    /**
-     * 涓嶅惈绋庢�讳环
-     */
     private BigDecimal unTaxIncludingPriceTotal;
 
-    /**
-     * 褰曞叆鏃堕棿
-     */
     @TableField(fill = FieldFill.INSERT)
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime createTime;
 
-    /**
-     * 鏇存柊鏃堕棿
-     */
     @TableField(fill = FieldFill.INSERT_UPDATE)
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime updateTime;
 
-    /**
-     * 褰曞叆浜�
-     */
     private String createUser;
 
-    /**
-     * 鏇存柊浜�
-     */
     private String updateUser;
 
-    /**
-     * 绉熸埛ID
-     */
     private Long tenantId;
 
     @ApiModelProperty("鐘舵��")
@@ -135,7 +85,6 @@
 
     @ApiModelProperty("杩愯鏃堕暱")
     private String runtimeDuration;
-
 
     @ApiModelProperty("鏄惁鎶樻棫 1-鏄� 2-鍚�")
     private Integer isDepr;
diff --git a/src/main/java/com/ruoyi/device/dto/DeviceMaintenanceDto.java b/src/main/java/com/ruoyi/device/dto/DeviceMaintenanceDto.java
index 522a324..a1824ee 100644
--- a/src/main/java/com/ruoyi/device/dto/DeviceMaintenanceDto.java
+++ b/src/main/java/com/ruoyi/device/dto/DeviceMaintenanceDto.java
@@ -10,13 +10,18 @@
 @Data
 public class DeviceMaintenanceDto {
 
-
     @ApiModelProperty("璁惧淇濆吇id")
     private Long id;
 
     @ApiModelProperty("璁惧鍙拌处id")
     private Long deviceLedgerId;
 
+    @ApiModelProperty("璁惧鍖哄煙id")
+    private Long areaId;
+
+    @ApiModelProperty("璁惧鍖哄煙鍚嶇О")
+    private String areaName;
+
     @ApiModelProperty("璁惧鍚嶇О")
     private String deviceName;
 
diff --git a/src/main/java/com/ruoyi/device/dto/DeviceRepairDto.java b/src/main/java/com/ruoyi/device/dto/DeviceRepairDto.java
index 92cfe8c..96c2f86 100644
--- a/src/main/java/com/ruoyi/device/dto/DeviceRepairDto.java
+++ b/src/main/java/com/ruoyi/device/dto/DeviceRepairDto.java
@@ -1,6 +1,5 @@
 package com.ruoyi.device.dto;
 
-
 import com.baomidou.mybatisplus.annotation.FieldFill;
 import com.baomidou.mybatisplus.annotation.TableField;
 import io.swagger.annotations.ApiModelProperty;
@@ -18,6 +17,12 @@
     @ApiModelProperty("璁惧鍙拌处id")
     private Long deviceLedgerId;
 
+    @ApiModelProperty("璁惧鍖哄煙id")
+    private Long areaId;
+
+    @ApiModelProperty("璁惧鍖哄煙鍚嶇О")
+    private String areaName;
+
     @ApiModelProperty("璁惧鍚嶇О")
     private String deviceName;
 
@@ -26,7 +31,7 @@
 
     @ApiModelProperty("鎶ヤ慨鏃堕棿")
     private Date repairTime;
-    
+
     private String repairTimeStr;
 
     @ApiModelProperty("鎶ヤ慨浜�")
@@ -68,7 +73,4 @@
     @ApiModelProperty("绉熸埛id")
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
-
-
 }
-
diff --git a/src/main/java/com/ruoyi/device/execl/DeviceLedgerExeclDto.java b/src/main/java/com/ruoyi/device/execl/DeviceLedgerExeclDto.java
index 01906d6..b26c193 100644
--- a/src/main/java/com/ruoyi/device/execl/DeviceLedgerExeclDto.java
+++ b/src/main/java/com/ruoyi/device/execl/DeviceLedgerExeclDto.java
@@ -7,87 +7,50 @@
 import org.springframework.format.annotation.DateTimeFormat;
 
 import java.math.BigDecimal;
-import java.time.LocalDate;
 import java.util.Date;
 
 @Data
 public class DeviceLedgerExeclDto {
 
+    @Excel(name = "璁惧绫诲瀷", sort = 0, combo = {"鐢熶骇璁惧", "鍔炲叕璁惧", "妫�娴嬭澶�", "杩愯緭璁惧", "鍏朵粬璁惧"})
+    private String type;
 
-    /**
-     * 璁惧鍚嶇О
-     */
-    @Excel(name = "璁惧鍚嶇О" ,sort = 1)
+    @Excel(name = "璁惧鍚嶇О", sort = 1)
     private String deviceName;
 
-    /**
-     * 璁惧绫诲瀷
-     */
-    @Excel(name = "璁惧绫诲瀷",sort = 0,combo = {"鐢熶骇璁惧","鍔炲叕璁惧","妫�鏌ヨ澶�","杩愯緭璁惧","鍏朵粬璁惧"})
-    private String type;
+    @Excel(name = "瑙勬牸鍨嬪彿", sort = 2)
+    private String deviceModel;
+
+    @Excel(name = "渚涘簲鍟嗗悕绉�", sort = 3)
+    private String supplierName;
+
+    @Excel(name = "鍗曚綅", sort = 4)
+    private String unit;
+
+    @Excel(name = "鏁伴噺", sort = 5, type = Excel.Type.EXPORT)
+    private BigDecimal number = BigDecimal.ONE;
+
+    @Excel(name = "鍚◣鍗曚环", sort = 6)
+    private BigDecimal taxIncludingPriceUnit;
+
+    @Excel(name = "鍚◣鎬讳环", sort = 7, type = Excel.Type.EXPORT)
+    private BigDecimal taxIncludingPriceTotal;
+
+    @Excel(name = "绋庣巼", sort = 8)
+    private BigDecimal taxRate;
+
+    @Excel(name = "涓嶅惈绋庢�讳环", sort = 9, type = Excel.Type.EXPORT)
+    private BigDecimal unTaxIncludingPriceTotal;
 
     @ApiModelProperty("璁″垝杩愯鏃堕棿")
     @JsonFormat(pattern = "yyyy-MM-dd")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
-    @Excel(name = "璁″垝杩愯鏃堕棿",sort = 10,dateFormat = "yyyy-MM-dd")
+    @Excel(name = "璁″垝杩愯鏃堕棿", sort = 10, dateFormat = "yyyy-MM-dd")
     private Date planRuntimeTime;
 
-    /**
-     * 瑙勬牸鍨嬪彿
-     */
-    @Excel(name = "瑙勬牸鍨嬪彿" ,sort = 2)
-    private String deviceModel;
+    @Excel(name = "璁惧鍖哄煙", sort = 11)
+    private String areaName;
 
-    /**
-     * 渚涘簲鍟嗗悕绉�
-     */
-    @Excel(name = "渚涘簲鍟嗗悕绉�",sort = 3)
-    private String supplierName;
-
-    /**
-     * 鍗曚綅
-     */
-    @Excel(name = "鍗曚綅",sort = 4)
-    private String unit;
-
-    /**
-     * 鏁伴噺
-     */
-    @Excel(name = "鏁伴噺",sort = 5, type = Excel.Type.EXPORT)
-    private BigDecimal number = BigDecimal.ONE;
-
-    /**
-     * 鍚◣鍗曚环
-     */
-    @Excel(name = "鍚◣鍗曚环",sort = 6)
-    private BigDecimal taxIncludingPriceUnit;
-
-    /**
-     * 鍚◣鎬讳环
-     */
-    @Excel(name = "鍚◣鎬讳环",sort = 7, type = Excel.Type.EXPORT)
-    private BigDecimal taxIncludingPriceTotal;
-
-    /**
-     * 绋庣巼
-     */
-    @Excel(name = "绋庣巼",sort = 8)
-    private BigDecimal taxRate;
-
-    /**
-     * 涓嶅惈绋庢�讳环
-     */
-    @Excel(name = "涓嶅惈绋庢�讳环",sort = 9, type = Excel.Type.EXPORT)
-    private BigDecimal unTaxIncludingPriceTotal;
-
-
-    /**
-     * 褰曞叆浜�
-     */
-    @Excel(name = "褰曞叆浜�",sort = 9)
+    @Excel(name = "褰曞叆浜�", sort = 12)
     private String createUser;
-
-
-
-
 }
diff --git a/src/main/java/com/ruoyi/device/mapper/DeviceAreaMapper.java b/src/main/java/com/ruoyi/device/mapper/DeviceAreaMapper.java
new file mode 100644
index 0000000..f60ce8a
--- /dev/null
+++ b/src/main/java/com/ruoyi/device/mapper/DeviceAreaMapper.java
@@ -0,0 +1,14 @@
+package com.ruoyi.device.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.device.pojo.DeviceArea;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+@Mapper
+public interface DeviceAreaMapper extends BaseMapper<DeviceArea> {
+
+    IPage<DeviceArea> queryPage(Page page, @Param("deviceArea") DeviceArea deviceArea);
+}
diff --git a/src/main/java/com/ruoyi/device/pojo/DeviceArea.java b/src/main/java/com/ruoyi/device/pojo/DeviceArea.java
new file mode 100644
index 0000000..de9e08c
--- /dev/null
+++ b/src/main/java/com/ruoyi/device/pojo/DeviceArea.java
@@ -0,0 +1,61 @@
+package com.ruoyi.device.pojo;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+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 io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Data
+@TableName("device_area")
+@ApiModel("璁惧鍖哄煙")
+public class DeviceArea {
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    @ApiModelProperty("鍖哄煙鍚嶇О")
+    private String areaName;
+
+    @ApiModelProperty("鐖剁骇ID")
+    private Long parentId;
+
+    @ApiModelProperty("鎺掑簭")
+    private Long sort;
+
+    @ApiModelProperty("澶囨敞")
+    private String remark;
+
+    @ApiModelProperty("鍒涘缓鏃堕棿")
+    @TableField(fill = FieldFill.INSERT)
+    private LocalDateTime createTime;
+
+    @ApiModelProperty("鏇存柊鏃堕棿")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private LocalDateTime updateTime;
+
+    @ApiModelProperty("鍒涘缓鐢ㄦ埛")
+    @TableField(fill = FieldFill.INSERT)
+    private Integer createUser;
+
+    @ApiModelProperty("鏇存柊鐢ㄦ埛")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private Integer updateUser;
+
+    @ApiModelProperty("绉熸埛ID")
+    @TableField(fill = FieldFill.INSERT)
+    private Long tenantId;
+
+    @ApiModelProperty("閮ㄩ棬ID")
+    @TableField(fill = FieldFill.INSERT)
+    private Long deptId;
+
+    @TableField(exist = false)
+    @ApiModelProperty("鐖剁骇鍚嶇О")
+    private String parentName;
+}
diff --git a/src/main/java/com/ruoyi/device/pojo/DeviceLedger.java b/src/main/java/com/ruoyi/device/pojo/DeviceLedger.java
index f8c9e53..7631866 100644
--- a/src/main/java/com/ruoyi/device/pojo/DeviceLedger.java
+++ b/src/main/java/com/ruoyi/device/pojo/DeviceLedger.java
@@ -13,114 +13,64 @@
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 
-/**
- * 璁惧鍙拌处瀹炰綋绫�
- */
 @Data
 @TableName("device_ledger")
 @ApiModel
 public class DeviceLedger {
 
-    /**
-     * 涓婚敭ID锛岃嚜澧�
-     */
-
     private Long id;
 
-    /**
-     * 璁惧鍚嶇О
-     */
     @ApiModelProperty("璁惧鍚嶇О")
     private String deviceName;
 
-    /**
-     * 瑙勬牸鍨嬪彿
-     */
     @ApiModelProperty("瑙勬牸鍨嬪彿")
     private String deviceModel;
 
-    /**
-     * 璁惧鍝佺墝
-     */
     @ApiModelProperty("璁惧鍝佺墝")
     private String deviceBrand;
 
-    /**
-     * 瀛樻斁浣嶇疆
-     */
     @ApiModelProperty("瀛樻斁浣嶇疆")
     private String storageLocation;
 
-    /**
-     * 渚涘簲鍟嗗悕绉�
-     */
+    @ApiModelProperty("璁惧鍖哄煙ID")
+    private Long areaId;
+
+    @TableField(exist = false)
+    @ApiModelProperty("璁惧鍖哄煙鍚嶇О")
+    private String areaName;
+
     private String supplierName;
 
-    /**
-     * 鍗曚綅
-     */
     private String unit;
 
-    /**
-     * 鏁伴噺
-     */
     private BigDecimal number;
 
-    /**
-     * 鍚◣鍗曚环
-     */
     private BigDecimal taxIncludingPriceUnit;
 
-    /**
-     * 鍚◣鎬讳环
-     */
     private BigDecimal taxIncludingPriceTotal;
 
-    /**
-     * 绋庣巼
-     */
     private BigDecimal taxRate;
 
-    /**
-     * 涓嶅惈绋庢�讳环
-     */
     private BigDecimal unTaxIncludingPriceTotal;
 
-    /**
-     * 褰曞叆鏃堕棿
-     */
     @TableField(fill = FieldFill.INSERT)
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime createTime;
 
-    /**
-     * 鏇存柊鏃堕棿
-     */
     @TableField(fill = FieldFill.INSERT_UPDATE)
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime updateTime;
 
-    /**
-     * 褰曞叆浜�
-     */
     @TableField(fill = FieldFill.INSERT)
     private Integer createUser;
 
-    /**
-     * 鏇存柊浜�
-     */
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private Integer updateUser;
 
-    /**
-     * 绉熸埛ID
-     */
     @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
-
-    /* ***************************     杩愯绠$悊        ***************************   */
 
     @ApiModelProperty("鐘舵��")
     private String status;
diff --git a/src/main/java/com/ruoyi/device/pojo/DeviceMaintenance.java b/src/main/java/com/ruoyi/device/pojo/DeviceMaintenance.java
index c3b73ad..5d7fcb1 100644
--- a/src/main/java/com/ruoyi/device/pojo/DeviceMaintenance.java
+++ b/src/main/java/com/ruoyi/device/pojo/DeviceMaintenance.java
@@ -23,7 +23,14 @@
     @ApiModelProperty("璁惧鍙拌处id")
     private Long deviceLedgerId;
 
-    @ApiModelProperty("淇濆吇浠诲姟id")
+    @ApiModelProperty("璁惧鍖哄煙id")
+    private Long areaId;
+
+    @TableField(exist = false)
+    @ApiModelProperty("璁惧鍙拌处ID闆嗗悎")
+    private Long[] deviceLedgerIds;
+
+    @ApiModelProperty("璁惧淇濆吇浠诲姟id")
     private Long maintenanceTaskId;
 
     @ApiModelProperty(value = "棰戞")
@@ -37,7 +44,6 @@
 
     @ApiModelProperty(value = "鏈�鍚庢墽琛屾椂闂�")
     private LocalDateTime lastExecutionTime;
-
 
     private String deviceName;
 
@@ -69,9 +75,9 @@
     private LocalDateTime createTime;
 
     @ApiModelProperty("鏇存柊鏃堕棿")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
-    @TableField(fill = FieldFill.INSERT_UPDATE)
     private LocalDateTime updateTime;
 
     @ApiModelProperty("鍒涘缓浜�")
diff --git a/src/main/java/com/ruoyi/device/pojo/DeviceRepair.java b/src/main/java/com/ruoyi/device/pojo/DeviceRepair.java
index 055a724..bdcadba 100644
--- a/src/main/java/com/ruoyi/device/pojo/DeviceRepair.java
+++ b/src/main/java/com/ruoyi/device/pojo/DeviceRepair.java
@@ -22,6 +22,13 @@
     @ApiModelProperty("璁惧鍙拌处id")
     private Long deviceLedgerId;
 
+    @ApiModelProperty("璁惧鍖哄煙id")
+    private Long areaId;
+
+    @TableField(exist = false)
+    @ApiModelProperty("璁惧鍙拌处ID闆嗗悎")
+    private Long[] deviceLedgerIds;
+
     private String deviceName;
 
     private String deviceModel;
diff --git a/src/main/java/com/ruoyi/device/pojo/MaintenanceTask.java b/src/main/java/com/ruoyi/device/pojo/MaintenanceTask.java
index a6f4432..73d0933 100644
--- a/src/main/java/com/ruoyi/device/pojo/MaintenanceTask.java
+++ b/src/main/java/com/ruoyi/device/pojo/MaintenanceTask.java
@@ -1,5 +1,6 @@
 package com.ruoyi.device.pojo;
 
+import com.baomidou.mybatisplus.annotation.FieldFill;
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
@@ -14,10 +15,6 @@
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 
-/**
- * @author :yys
- * @date : 2025/9/19 10:27
- */
 @Data
 @ApiModel
 @TableName("maintenance_task")
@@ -28,9 +25,6 @@
     @ApiModelProperty(value = "瑙勬牸鍨嬪彿")
     private String deviceModel;
 
-    /**
-     * 涓婚敭ID
-     */
     @TableId(type = IdType.AUTO)
     private Long id;
 
@@ -40,6 +34,20 @@
 
     @ApiModelProperty(value = "璁惧id")
     private Long taskId;
+
+    @ApiModelProperty(value = "璁惧鍖哄煙id")
+    private Long areaId;
+
+    @TableField(exist = false)
+    @ApiModelProperty(value = "璁惧鍖哄煙鍚嶇О")
+    private String areaName;
+
+    @TableField(exist = false)
+    @ApiModelProperty(value = "璁惧ID闆嗗悎")
+    private Long[] deviceLedgerIds;
+
+    @ApiModelProperty(value = "璁惧ID闆嗗悎瀛楃涓�")
+    private String deviceLedgerIdsStr;
 
     @ApiModelProperty(value = "棰戞")
     @Excel(name = "棰戞")
@@ -78,32 +86,29 @@
     @ApiModelProperty(value = "鐘舵��")
     private String status;
 
-    @ApiModelProperty(value = "杞垹闄ゆ爣蹇楋紝0=鏈垹闄わ紝1=宸插垹闄�")
+    @ApiModelProperty(value = "杞垹闄ゆ爣璁帮紝0=鏈垹闄わ紝1=宸插垹闄�")
     private Integer deleted;
 
     @TableField(exist = false)
     private String dateStr;
 
     @ApiModelProperty(value = "鍒涘缓璇ヨ褰曠殑鐢ㄦ埛")
-    @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT)
+    @TableField(fill = FieldFill.INSERT)
     private Integer createUser;
 
     @ApiModelProperty(value = "璁板綍鍒涘缓鏃堕棿")
-    @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT)
-//    @JsonFormat(pattern = "yyyy-MM-dd")
-//    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    @TableField(fill = FieldFill.INSERT)
     private LocalDateTime createTime;
 
     @ApiModelProperty(value = "鏈�鍚庝慨鏀硅璁板綍鐨勭敤鎴�")
-    @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT_UPDATE)
+    @TableField(fill = FieldFill.INSERT_UPDATE)
     private Integer updateUser;
 
     @ApiModelProperty(value = "璁板綍鏈�鍚庢洿鏂版椂闂�")
-    @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT_UPDATE)
+    @TableField(fill = FieldFill.INSERT_UPDATE)
     private LocalDateTime updateTime;
 
     @ApiModelProperty(value = "绉熸埛ID")
-    @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT)
+    @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
-
 }
diff --git a/src/main/java/com/ruoyi/device/service/IDeviceAreaService.java b/src/main/java/com/ruoyi/device/service/IDeviceAreaService.java
new file mode 100644
index 0000000..ea25046
--- /dev/null
+++ b/src/main/java/com/ruoyi/device/service/IDeviceAreaService.java
@@ -0,0 +1,25 @@
+package com.ruoyi.device.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.device.dto.DeviceAreaTreeDto;
+import com.ruoyi.device.pojo.DeviceArea;
+import com.ruoyi.framework.web.domain.AjaxResult;
+
+import java.util.List;
+
+public interface IDeviceAreaService extends IService<DeviceArea> {
+
+    IPage<DeviceArea> queryPage(Page page, DeviceArea deviceArea);
+
+    List<DeviceAreaTreeDto> listTree();
+
+    List<DeviceAreaTreeDto> listTreeWithDevices();
+
+    AjaxResult saveDeviceArea(DeviceArea deviceArea);
+
+    AjaxResult updateDeviceArea(DeviceArea deviceArea);
+
+    AjaxResult removeDeviceAreas(List<Long> ids);
+}
diff --git a/src/main/java/com/ruoyi/device/service/impl/DeviceAreaServiceImpl.java b/src/main/java/com/ruoyi/device/service/impl/DeviceAreaServiceImpl.java
new file mode 100644
index 0000000..c2ec3e6
--- /dev/null
+++ b/src/main/java/com/ruoyi/device/service/impl/DeviceAreaServiceImpl.java
@@ -0,0 +1,194 @@
+package com.ruoyi.device.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.StringUtils;
+import com.ruoyi.common.utils.bean.BeanUtils;
+import com.ruoyi.device.dto.DeviceAreaTreeDto;
+import com.ruoyi.device.mapper.DeviceAreaMapper;
+import com.ruoyi.device.mapper.DeviceLedgerMapper;
+import com.ruoyi.device.pojo.DeviceArea;
+import com.ruoyi.device.pojo.DeviceLedger;
+import com.ruoyi.device.service.IDeviceAreaService;
+import com.ruoyi.framework.web.domain.AjaxResult;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Service
+public class DeviceAreaServiceImpl extends ServiceImpl<DeviceAreaMapper, DeviceArea> implements IDeviceAreaService {
+
+    @Autowired
+    private DeviceAreaMapper deviceAreaMapper;
+
+    @Autowired
+    private DeviceLedgerMapper deviceLedgerMapper;
+
+    @Override
+    public IPage<DeviceArea> queryPage(Page page, DeviceArea deviceArea) {
+        return deviceAreaMapper.queryPage(page, deviceArea);
+    }
+
+    @Override
+    public List<DeviceAreaTreeDto> listTree() {
+        return buildTree(Collections.emptyMap());
+    }
+
+    @Override
+    public List<DeviceAreaTreeDto> listTreeWithDevices() {
+        LambdaQueryWrapper<DeviceLedger> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.isNotNull(DeviceLedger::getAreaId);
+        queryWrapper.orderByAsc(DeviceLedger::getId);
+        List<DeviceLedger> deviceLedgers = deviceLedgerMapper.selectList(queryWrapper);
+
+        Map<Long, List<DeviceLedger>> deviceMap = new HashMap<>();
+        for (DeviceLedger deviceLedger : deviceLedgers) {
+            deviceMap.computeIfAbsent(deviceLedger.getAreaId(), key -> new ArrayList<>()).add(deviceLedger);
+        }
+        return buildTree(deviceMap);
+    }
+
+    @Override
+    public AjaxResult saveDeviceArea(DeviceArea deviceArea) {
+        if (deviceArea == null || !StringUtils.hasText(deviceArea.getAreaName())) {
+            return AjaxResult.error("鍖哄煙鍚嶇О涓嶈兘涓虹┖");
+        }
+        normalizeDeviceArea(deviceArea);
+        if (existsSameName(deviceArea.getParentId(), deviceArea.getAreaName(), null)) {
+            return AjaxResult.error("鍚岀骇鍖哄煙鍚嶇О宸插瓨鍦�");
+        }
+        if (deviceArea.getParentId() != null && deviceAreaMapper.selectById(deviceArea.getParentId()) == null) {
+            return AjaxResult.error("鐖剁骇鍖哄煙涓嶅瓨鍦�");
+        }
+        return this.save(deviceArea) ? AjaxResult.success() : AjaxResult.error();
+    }
+
+    @Override
+    public AjaxResult updateDeviceArea(DeviceArea deviceArea) {
+        if (deviceArea == null || deviceArea.getId() == null) {
+            return AjaxResult.error("鍖哄煙ID涓嶈兘涓虹┖");
+        }
+        if (!StringUtils.hasText(deviceArea.getAreaName())) {
+            return AjaxResult.error("鍖哄煙鍚嶇О涓嶈兘涓虹┖");
+        }
+        normalizeDeviceArea(deviceArea);
+        DeviceArea current = deviceAreaMapper.selectById(deviceArea.getId());
+        if (current == null) {
+            return AjaxResult.error("鍖哄煙涓嶅瓨鍦�");
+        }
+        if (deviceArea.getParentId() != null && deviceArea.getId().equals(deviceArea.getParentId())) {
+            return AjaxResult.error("鐖剁骇鍖哄煙涓嶈兘閫夋嫨鑷韩");
+        }
+        if (isDescendant(deviceArea.getId(), deviceArea.getParentId())) {
+            return AjaxResult.error("鐖剁骇鍖哄煙涓嶈兘閫夋嫨瀛愯妭鐐�");
+        }
+        if (deviceArea.getParentId() != null && deviceAreaMapper.selectById(deviceArea.getParentId()) == null) {
+            return AjaxResult.error("鐖剁骇鍖哄煙涓嶅瓨鍦�");
+        }
+        if (existsSameName(deviceArea.getParentId(), deviceArea.getAreaName(), deviceArea.getId())) {
+            return AjaxResult.error("鍚岀骇鍖哄煙鍚嶇О宸插瓨鍦�");
+        }
+        return this.updateById(deviceArea) ? AjaxResult.success() : AjaxResult.error();
+    }
+
+    @Override
+    public AjaxResult removeDeviceAreas(List<Long> ids) {
+        if (CollectionUtils.isEmpty(ids)) {
+            return AjaxResult.error("璇烽�夋嫨瑕佸垹闄ょ殑鍖哄煙");
+        }
+        LambdaQueryWrapper<DeviceArea> childWrapper = new LambdaQueryWrapper<>();
+        childWrapper.in(DeviceArea::getParentId, ids);
+        if (deviceAreaMapper.selectCount(childWrapper) > 0) {
+            return AjaxResult.error("瀛樺湪瀛愬尯鍩燂紝涓嶈兘鐩存帴鍒犻櫎");
+        }
+        return this.removeBatchByIds(ids) ? AjaxResult.success() : AjaxResult.error();
+    }
+
+    private List<DeviceAreaTreeDto> buildTree(Map<Long, List<DeviceLedger>> deviceMap) {
+        LambdaQueryWrapper<DeviceArea> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.and(wrapper -> wrapper.isNull(DeviceArea::getParentId).or().eq(DeviceArea::getParentId, 0L));
+        queryWrapper.orderByAsc(DeviceArea::getSort).orderByAsc(DeviceArea::getId);
+        List<DeviceArea> rootList = deviceAreaMapper.selectList(queryWrapper);
+
+        List<DeviceAreaTreeDto> tree = new ArrayList<>();
+        for (DeviceArea deviceArea : rootList) {
+            DeviceAreaTreeDto node = toTreeDto(deviceArea, deviceMap);
+            node.setChildren(buildChildren(deviceArea.getId(), deviceMap));
+            tree.add(node);
+        }
+        return tree;
+    }
+
+    private void normalizeDeviceArea(DeviceArea deviceArea) {
+        if (deviceArea.getParentId() != null && deviceArea.getParentId() == 0L) {
+            deviceArea.setParentId(null);
+        }
+        if (deviceArea.getSort() == null) {
+            deviceArea.setSort(0L);
+        }
+    }
+
+    private boolean existsSameName(Long parentId, String areaName, Long excludeId) {
+        LambdaQueryWrapper<DeviceArea> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(DeviceArea::getAreaName, areaName);
+        if (parentId == null) {
+            queryWrapper.and(wrapper -> wrapper.isNull(DeviceArea::getParentId).or().eq(DeviceArea::getParentId, 0L));
+        } else {
+            queryWrapper.eq(DeviceArea::getParentId, parentId);
+        }
+        if (excludeId != null) {
+            queryWrapper.ne(DeviceArea::getId, excludeId);
+        }
+        return deviceAreaMapper.selectCount(queryWrapper) > 0;
+    }
+
+    private boolean isDescendant(Long currentId, Long parentId) {
+        if (currentId == null || parentId == null) {
+            return false;
+        }
+        Long cursor = parentId;
+        while (cursor != null && cursor != 0L) {
+            if (currentId.equals(cursor)) {
+                return true;
+            }
+            DeviceArea parent = deviceAreaMapper.selectById(cursor);
+            if (parent == null) {
+                return false;
+            }
+            cursor = parent.getParentId();
+        }
+        return false;
+    }
+
+    private List<DeviceAreaTreeDto> buildChildren(Long parentId, Map<Long, List<DeviceLedger>> deviceMap) {
+        LambdaQueryWrapper<DeviceArea> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(DeviceArea::getParentId, parentId);
+        queryWrapper.orderByAsc(DeviceArea::getSort).orderByAsc(DeviceArea::getId);
+        List<DeviceArea> children = deviceAreaMapper.selectList(queryWrapper);
+
+        List<DeviceAreaTreeDto> result = new ArrayList<>();
+        for (DeviceArea child : children) {
+            DeviceAreaTreeDto node = toTreeDto(child, deviceMap);
+            node.setChildren(buildChildren(child.getId(), deviceMap));
+            result.add(node);
+        }
+        return result;
+    }
+
+    private DeviceAreaTreeDto toTreeDto(DeviceArea deviceArea, Map<Long, List<DeviceLedger>> deviceMap) {
+        DeviceAreaTreeDto dto = new DeviceAreaTreeDto();
+        BeanUtils.copyProperties(deviceArea, dto);
+        dto.setLabel(deviceArea.getAreaName());
+        dto.setDeviceList(new ArrayList<>(deviceMap.getOrDefault(deviceArea.getId(), Collections.emptyList())));
+        dto.setChildren(new ArrayList<>());
+        return dto;
+    }
+}
diff --git a/src/main/java/com/ruoyi/device/service/impl/DeviceMaintenanceServiceImpl.java b/src/main/java/com/ruoyi/device/service/impl/DeviceMaintenanceServiceImpl.java
index a5005af..b0c655a 100644
--- a/src/main/java/com/ruoyi/device/service/impl/DeviceMaintenanceServiceImpl.java
+++ b/src/main/java/com/ruoyi/device/service/impl/DeviceMaintenanceServiceImpl.java
@@ -1,6 +1,5 @@
 package com.ruoyi.device.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;
@@ -9,7 +8,9 @@
 import com.ruoyi.device.dto.DeviceMaintenanceDto;
 import com.ruoyi.device.execl.DeviceMaintenanceExeclDto;
 import com.ruoyi.device.mapper.DeviceMaintenanceMapper;
+import com.ruoyi.device.pojo.DeviceLedger;
 import com.ruoyi.device.pojo.DeviceMaintenance;
+import com.ruoyi.device.service.IDeviceLedgerService;
 import com.ruoyi.device.service.IDeviceMaintenanceService;
 import com.ruoyi.framework.web.domain.AjaxResult;
 import com.ruoyi.measuringinstrumentledger.mapper.SparePartsMapper;
@@ -24,13 +25,11 @@
 import javax.servlet.http.HttpServletResponse;
 import java.math.BigDecimal;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
-
 
 @Service
 public class DeviceMaintenanceServiceImpl extends ServiceImpl<DeviceMaintenanceMapper, DeviceMaintenance> implements IDeviceMaintenanceService {
-
-
 
     @Autowired
     private DeviceMaintenanceMapper deviceMaintenanceMapper;
@@ -38,43 +37,42 @@
     private SparePartsMapper sparePartsMapper;
     @Autowired
     private SparePartsRequisitionRecordService sparePartsRequisitionRecordService;
+    @Autowired
+    private IDeviceLedgerService deviceLedgerService;
 
     @Override
     public IPage<DeviceMaintenanceDto> queryPage(Page page, DeviceMaintenanceDto deviceMaintenanceDto) {
-
         return deviceMaintenanceMapper.queryPage(page, deviceMaintenanceDto);
     }
 
     @Override
     public AjaxResult saveDeviceRepair(DeviceMaintenance deviceMaintenance) {
-        boolean save = this.save(deviceMaintenance);
-        if (save){
-            return AjaxResult.success();
+        List<DeviceMaintenance> records = buildMaintenanceRecords(deviceMaintenance);
+        if (records.isEmpty()) {
+            return AjaxResult.error("璇烽�夋嫨璁惧");
         }
-        return AjaxResult.error();
+        return this.saveBatch(records) ? AjaxResult.success() : AjaxResult.error();
     }
 
     @Override
     @Transactional(rollbackFor = Exception.class)
     public AjaxResult updateDeviceDeviceMaintenance(DeviceMaintenance deviceMaintenance) {
         DeviceMaintenance oldDeviceMaintenance = this.getById(deviceMaintenance.getId());
-        // 澶勭悊澶囦欢浣跨敤鎯呭喌
+        if (oldDeviceMaintenance == null) {
+            return AjaxResult.error("淇濆吇璁板綍涓嶅瓨鍦�");
+        }
         if (com.github.xiaoymin.knife4j.core.util.CollectionUtils.isNotEmpty(deviceMaintenance.getSparePartsUseList())) {
             List<Long> sparePartIds = new ArrayList<>();
             for (DeviceMaintenance.SparePartUse sparePartUse : deviceMaintenance.getSparePartsUseList()) {
-                // 鑾峰彇澶囦欢淇℃伅
                 SpareParts spareParts = sparePartsMapper.selectById(sparePartUse.getId());
                 if (spareParts != null) {
-                    // 妫�鏌ユ暟閲忔槸鍚﹁冻澶�
                     if (spareParts.getQuantity().compareTo(new BigDecimal(sparePartUse.getQuantity())) >= 0) {
-                        // 鏇存柊鏁伴噺
                         spareParts.setQuantity(spareParts.getQuantity().subtract(new BigDecimal(sparePartUse.getQuantity())));
                         sparePartsMapper.updateById(spareParts);
                         sparePartIds.add(sparePartUse.getId());
 
-                        // 鍒涘缓澶囦欢棰嗙敤璁板綍
                         SparePartsRequisitionRecord record = new SparePartsRequisitionRecord();
-                        record.setSourceType(1); // 1 淇濆吇
+                        record.setSourceType(1);
                         record.setSourceId(deviceMaintenance.getId());
                         record.setDeviceLedgerId(oldDeviceMaintenance.getDeviceLedgerId());
                         record.setSparePartsId(sparePartUse.getId());
@@ -85,36 +83,64 @@
                     }
                 }
             }
-            // 鏇存柊澶囦欢IDs瀛楁
             if (!sparePartIds.isEmpty()) {
                 deviceMaintenance.setSparePartsIds(StringUtils.join(sparePartIds, ","));
             }
         }
 
-        if (this.updateById(deviceMaintenance)) {
-            return AjaxResult.success();
-        }
-        return AjaxResult.error();
+        return this.updateById(deviceMaintenance) ? AjaxResult.success() : AjaxResult.error();
     }
 
     @Override
     public void export(HttpServletResponse response, Long[] ids) {
         List<DeviceMaintenance> supplierManageList = deviceMaintenanceMapper.selectList(null);
-        ArrayList<DeviceMaintenanceExeclDto> deviceLedgerExeclDtos = new ArrayList<>();
+        ArrayList<DeviceMaintenanceExeclDto> result = new ArrayList<>();
         supplierManageList.forEach(deviceMaintenance -> {
-            DeviceMaintenanceExeclDto deviceRepairExeclDto = new DeviceMaintenanceExeclDto();
-            BeanUtils.copyProperties(deviceMaintenance,deviceRepairExeclDto);
-            deviceRepairExeclDto.setStatus(deviceMaintenance.getStatus() == 0 ? "寰呯淮淇�" : deviceMaintenance.getStatus() == 1 ? "瀹岀粨" : "澶辫触");
-//            deviceRepairExeclDto.setMaintenanceResult(deviceMaintenance.getMaintenanceResult() != null && deviceMaintenance.getMaintenanceResult() == 0 ? "缁翠慨" : "瀹屽ソ");
-            deviceLedgerExeclDtos.add(deviceRepairExeclDto);
+            DeviceMaintenanceExeclDto dto = new DeviceMaintenanceExeclDto();
+            BeanUtils.copyProperties(deviceMaintenance, dto);
+            dto.setStatus(deviceMaintenance.getStatus() == 0 ? "寰呯淮淇�" : deviceMaintenance.getStatus() == 1 ? "瀹岀粨" : "澶辫触");
+            result.add(dto);
         });
-        ExcelUtil<DeviceMaintenanceExeclDto> util = new ExcelUtil<DeviceMaintenanceExeclDto>(DeviceMaintenanceExeclDto.class);
-        util.exportExcel(response, deviceLedgerExeclDtos, "璁惧鎶ヤ慨瀵煎嚭");
+        ExcelUtil<DeviceMaintenanceExeclDto> util = new ExcelUtil<>(DeviceMaintenanceExeclDto.class);
+        util.exportExcel(response, result, "璁惧淇濆吇瀵煎嚭");
     }
 
     @Override
     public DeviceMaintenanceDto detailById(Long id) {
-
         return deviceMaintenanceMapper.detailById(id);
     }
+
+    private List<DeviceMaintenance> buildMaintenanceRecords(DeviceMaintenance source) {
+        Long[] deviceIds = source.getDeviceLedgerIds();
+        if (deviceIds == null || deviceIds.length == 0) {
+            deviceIds = source.getDeviceLedgerId() == null ? new Long[0] : new Long[]{source.getDeviceLedgerId()};
+        }
+        List<DeviceMaintenance> records = new ArrayList<>();
+        Arrays.stream(deviceIds).distinct().forEach(deviceId -> {
+            DeviceLedger deviceLedger = deviceLedgerService.getById(deviceId);
+            if (deviceLedger == null) {
+                return;
+            }
+            int quantity = resolveQuantity(deviceLedger);
+            for (int i = 0; i < quantity; i++) {
+                DeviceMaintenance record = new DeviceMaintenance();
+                BeanUtils.copyProperties(source, record);
+                record.setId(null);
+                record.setDeviceLedgerIds(null);
+                record.setDeviceLedgerId(deviceLedger.getId());
+                record.setAreaId(deviceLedger.getAreaId());
+                record.setDeviceName(deviceLedger.getDeviceName());
+                record.setDeviceModel(deviceLedger.getDeviceModel());
+                records.add(record);
+            }
+        });
+        return records;
+    }
+
+    private int resolveQuantity(DeviceLedger deviceLedger) {
+        if (deviceLedger == null || deviceLedger.getNumber() == null || deviceLedger.getNumber().compareTo(BigDecimal.ONE) < 0) {
+            return 1;
+        }
+        return Math.max(1, deviceLedger.getNumber().intValue());
+    }
 }
diff --git a/src/main/java/com/ruoyi/device/service/impl/DeviceRepairServiceImpl.java b/src/main/java/com/ruoyi/device/service/impl/DeviceRepairServiceImpl.java
index 9d4c6b3..f0606eb 100644
--- a/src/main/java/com/ruoyi/device/service/impl/DeviceRepairServiceImpl.java
+++ b/src/main/java/com/ruoyi/device/service/impl/DeviceRepairServiceImpl.java
@@ -20,7 +20,6 @@
 import com.ruoyi.measuringinstrumentledger.pojo.SpareParts;
 import com.ruoyi.measuringinstrumentledger.pojo.SparePartsRequisitionRecord;
 import com.ruoyi.measuringinstrumentledger.service.SparePartsRequisitionRecordService;
-import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -34,7 +33,6 @@
 import java.util.List;
 
 @Service
-@AllArgsConstructor
 @Slf4j
 public class DeviceRepairServiceImpl extends ServiceImpl<DeviceRepairMapper, DeviceRepair> implements IDeviceRepairService {
 
@@ -51,43 +49,37 @@
 
     @Override
     public IPage<DeviceRepairDto> queryPage(Page page, DeviceRepairDto deviceRepairDto) {
-
         return deviceRepairMapper.queryPage(page, deviceRepairDto);
     }
 
     @Override
     public AjaxResult saveDeviceRepair(DeviceRepair deviceRepair) {
-        DeviceLedger byId = deviceLedgerService.getById(deviceRepair.getDeviceLedgerId());
-        deviceRepair.setDeviceName(byId.getDeviceName());
-        deviceRepair.setDeviceModel(byId.getDeviceModel());
-        boolean save = this.save(deviceRepair);
-        if (save){
-            return AjaxResult.success();
+        List<DeviceRepair> records = buildRepairRecords(deviceRepair);
+        if (records.isEmpty()) {
+            return AjaxResult.error("璇烽�夋嫨璁惧");
         }
-        return AjaxResult.error();
+        return this.saveBatch(records) ? AjaxResult.success() : AjaxResult.error();
     }
 
     @Override
     @Transactional(rollbackFor = Exception.class)
     public AjaxResult updateDeviceRepair(DeviceRepair deviceRepair) {
         DeviceRepair oldDeviceRepair = this.getById(deviceRepair.getId());
-        // 澶勭悊澶囦欢浣跨敤鎯呭喌
+        if (oldDeviceRepair == null) {
+            return AjaxResult.error("鎶ヤ慨璁板綍涓嶅瓨鍦�");
+        }
         if (CollectionUtils.isNotEmpty(deviceRepair.getSparePartsUseList())) {
             List<Long> sparePartIds = new ArrayList<>();
             for (DeviceRepair.SparePartUse sparePartUse : deviceRepair.getSparePartsUseList()) {
-                // 鑾峰彇澶囦欢淇℃伅
                 SpareParts spareParts = sparePartsMapper.selectById(sparePartUse.getId());
                 if (spareParts != null) {
-                    // 妫�鏌ユ暟閲忔槸鍚﹁冻澶�
                     if (spareParts.getQuantity().compareTo(new BigDecimal(sparePartUse.getQuantity())) >= 0) {
-                        // 鏇存柊鏁伴噺
                         spareParts.setQuantity(spareParts.getQuantity().subtract(new BigDecimal(sparePartUse.getQuantity())));
                         sparePartsMapper.updateById(spareParts);
                         sparePartIds.add(sparePartUse.getId());
 
-                        // 鍒涘缓澶囦欢棰嗙敤璁板綍
                         SparePartsRequisitionRecord record = new SparePartsRequisitionRecord();
-                        record.setSourceType(0); // 0 缁翠慨
+                        record.setSourceType(0);
                         record.setSourceId(deviceRepair.getId());
                         record.setDeviceLedgerId(oldDeviceRepair.getDeviceLedgerId());
                         record.setSparePartsId(sparePartUse.getId());
@@ -98,7 +90,6 @@
                     }
                 }
             }
-            // 鏇存柊澶囦欢IDs瀛楁
             if (!sparePartIds.isEmpty()) {
                 deviceRepair.setSparePartsIds(StringUtils.join(sparePartIds, ","));
             }
@@ -106,12 +97,11 @@
 
         if (this.updateById(deviceRepair)) {
             Long id = deviceRepair.getId();
-            //
             DeviceDefectRecordDto deviceDefectRecordDto = new DeviceDefectRecordDto();
             deviceDefectRecordDto.setDeviceLedgerId(id);
             deviceDefectRecordDto.setStatus("涓ラ噸缂洪櫡");
             List<DeviceDefectRecordDto> records = deviceDefectRecordService.listPage(new Page<>(1, -1), deviceDefectRecordDto).getRecords();
-            if (!records.isEmpty()){
+            if (!records.isEmpty()) {
                 records.forEach(deviceDefectRecord -> {
                     deviceDefectRecord.setStatus("姝e父");
                     deviceDefectRecordService.updateByDDR(deviceDefectRecord);
@@ -124,42 +114,59 @@
 
     @Override
     public void export(HttpServletResponse response, Long[] ids) {
+        List<DeviceRepair> supplierManageList;
         if (ids == null || ids.length == 0) {
-            List<DeviceRepair> supplierManageList = this.list();
-            ArrayList<DeviceRepairExeclDto> deviceLedgerExeclDtos = new ArrayList<>();
-            supplierManageList.stream().forEach(deviceRepair -> {
-                DeviceRepairExeclDto deviceRepairExeclDto = new DeviceRepairExeclDto();
-                BeanUtils.copyProperties(deviceRepair,deviceRepairExeclDto);
-                deviceRepairExeclDto.setStatusStr(deviceRepair.getStatus() == 0 ? "寰呯淮淇�" : deviceRepair.getStatus() == 1 ? "瀹岀粨" : "澶辫触");
-
-                deviceLedgerExeclDtos.add(deviceRepairExeclDto);
-            });
-            ExcelUtil<DeviceRepairExeclDto> util = new ExcelUtil<DeviceRepairExeclDto>(DeviceRepairExeclDto.class);
-            util.exportExcel(response, deviceLedgerExeclDtos, "璁惧鎶ヤ慨瀵煎嚭");
-        }else {
-            ArrayList<Long> arrayList = new ArrayList<>();
-            Arrays.stream(ids).map(id -> {
-                return arrayList.add( id);
-            });
-            List<DeviceRepair> supplierManageList = deviceRepairMapper.selectBatchIds(arrayList);
-            ArrayList<DeviceRepairExeclDto> deviceLedgerExeclDtos = new ArrayList<>();
-            supplierManageList.stream().forEach(deviceRepair -> {
-                DeviceRepairExeclDto deviceRepairExeclDto = new DeviceRepairExeclDto();
-                BeanUtils.copyProperties(deviceRepair,deviceRepairExeclDto);
-                deviceRepairExeclDto.setStatusStr(deviceRepair.getStatus() == 0 ? "寰呯淮淇�" : deviceRepair.getStatus() == 1 ? "瀹岀粨" : "澶辫触");
-
-                deviceLedgerExeclDtos.add(deviceRepairExeclDto);
-            });
-            ExcelUtil<DeviceRepairExeclDto> util = new ExcelUtil<DeviceRepairExeclDto>(DeviceRepairExeclDto.class);
-            util.exportExcel(response, deviceLedgerExeclDtos, "璁惧鎶ヤ慨瀵煎嚭");
+            supplierManageList = this.list();
+        } else {
+            supplierManageList = deviceRepairMapper.selectBatchIds(Arrays.asList(ids));
         }
-
+        ArrayList<DeviceRepairExeclDto> result = new ArrayList<>();
+        supplierManageList.forEach(deviceRepair -> {
+            DeviceRepairExeclDto dto = new DeviceRepairExeclDto();
+            BeanUtils.copyProperties(deviceRepair, dto);
+            dto.setStatusStr(deviceRepair.getStatus() == 0 ? "寰呯淮淇�" : deviceRepair.getStatus() == 1 ? "瀹岀粨" : "澶辫触");
+            result.add(dto);
+        });
+        ExcelUtil<DeviceRepairExeclDto> util = new ExcelUtil<>(DeviceRepairExeclDto.class);
+        util.exportExcel(response, result, "璁惧鎶ヤ慨瀵煎嚭");
     }
 
     @Override
     public DeviceRepairDto detailById(Long id) {
-
         return deviceRepairMapper.detailById(id);
     }
 
+    private List<DeviceRepair> buildRepairRecords(DeviceRepair source) {
+        Long[] deviceIds = source.getDeviceLedgerIds();
+        if (deviceIds == null || deviceIds.length == 0) {
+            deviceIds = source.getDeviceLedgerId() == null ? new Long[0] : new Long[]{source.getDeviceLedgerId()};
+        }
+        List<DeviceRepair> records = new ArrayList<>();
+        Arrays.stream(deviceIds).distinct().forEach(deviceId -> {
+            DeviceLedger deviceLedger = deviceLedgerService.getById(deviceId);
+            if (deviceLedger == null) {
+                return;
+            }
+            int quantity = resolveQuantity(deviceLedger);
+            for (int i = 0; i < quantity; i++) {
+                DeviceRepair record = new DeviceRepair();
+                BeanUtils.copyProperties(source, record);
+                record.setId(null);
+                record.setDeviceLedgerIds(null);
+                record.setDeviceLedgerId(deviceLedger.getId());
+                record.setAreaId(deviceLedger.getAreaId());
+                record.setDeviceName(deviceLedger.getDeviceName());
+                record.setDeviceModel(deviceLedger.getDeviceModel());
+                records.add(record);
+            }
+        });
+        return records;
+    }
+
+    private int resolveQuantity(DeviceLedger deviceLedger) {
+        if (deviceLedger == null || deviceLedger.getNumber() == null || deviceLedger.getNumber().compareTo(BigDecimal.ONE) < 0) {
+            return 1;
+        }
+        return Math.max(1, deviceLedger.getNumber().intValue());
+    }
 }
diff --git a/src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskJob.java b/src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskJob.java
index fca829a..0cabd36 100644
--- a/src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskJob.java
+++ b/src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskJob.java
@@ -1,8 +1,14 @@
 package com.ruoyi.device.service.impl;
 
+import com.ruoyi.device.mapper.DeviceLedgerMapper;
+import com.ruoyi.device.pojo.DeviceLedger;
 import com.ruoyi.device.pojo.DeviceMaintenance;
 import com.ruoyi.device.pojo.MaintenanceTask;
-import org.quartz.*;
+import org.quartz.DisallowConcurrentExecution;
+import org.quartz.Job;
+import org.quartz.JobDataMap;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobExecutionException;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.jdbc.core.BeanPropertyRowMapper;
 import org.springframework.jdbc.core.JdbcTemplate;
@@ -13,14 +19,16 @@
 import java.time.LocalDateTime;
 import java.time.LocalTime;
 import java.time.YearMonth;
+import java.util.Arrays;
+import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 
 @Component
-@DisallowConcurrentExecution // 绂佹骞跺彂鎵ц鍚屼竴涓狫ob
+@DisallowConcurrentExecution
 public class MaintenanceTaskJob implements Job, Serializable {
-    private static final long serialVersionUID = 1L; // 蹇呴』瀹氫箟搴忓垪鍖朓D
+    private static final long serialVersionUID = 1L;
 
     @Autowired
     private DeviceMaintenanceServiceImpl deviceMaintenanceService;
@@ -28,15 +36,15 @@
     @Autowired
     private JdbcTemplate jdbcTemplate;
 
+    @Autowired
+    private DeviceLedgerMapper deviceLedgerMapper;
+
     @Override
     public void execute(JobExecutionContext context) throws JobExecutionException {
         JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();
-        // 淇绫诲瀷杞崲閿欒锛屾纭幏鍙杢askId
         Long taskId = jobDataMap.getLong("maintenanceTaskId");
 
         try {
-            // 3. 灏濊瘯鏌ヨ浣犵殑涓氬姟鏁版嵁
-            // 閫氳繃JDBC妯℃澘鏌ヨ瀹氭椂浠诲姟淇℃伅锛屼娇鐢ㄥ弬鏁板寲鏌ヨ闃叉SQL娉ㄥ叆
             String yourSql = "SELECT * FROM maintenance_task where id = ?";
             List<MaintenanceTask> tasks = jdbcTemplate.query(
                     yourSql,
@@ -45,58 +53,49 @@
             );
             MaintenanceTask timingTask = tasks.isEmpty() ? null : tasks.get(0);
             if (timingTask == null) {
-                throw new JobExecutionException("MaintenanceTaskJob鎵句笉鍒板畾鏃朵换鍔�: " + taskId);
+                throw new JobExecutionException("MaintenanceTaskJob鎵句笉鍒板畾鏃朵换鍔� " + taskId);
             }
 
-            // 2. 鍒涘缓骞朵繚瀛樺贰妫�浠诲姟璁板綍 - 杩欏氨鏄偍鎻愪緵鐨勪唬鐮佸簲璇ユ斁鐨勪綅缃�
-            DeviceMaintenance deviceMaintenance = createInspectionTask(timingTask);
-            deviceMaintenanceService.save(deviceMaintenance);
+            List<Long> deviceIds = resolveDeviceIds(timingTask);
+            List<DeviceMaintenance> maintenanceList = new ArrayList<>();
+            for (Long deviceId : deviceIds) {
+                int quantity = resolveQuantity(deviceId);
+                for (int i = 0; i < quantity; i++) {
+                    maintenanceList.add(createInspectionTask(timingTask, deviceId));
+                }
+            }
+            deviceMaintenanceService.saveBatch(maintenanceList);
 
-            // 3. 鏇存柊瀹氭椂浠诲姟鐨勬墽琛屾椂闂�
             if (!tasks.isEmpty()) {
                 MaintenanceTask task = tasks.get(0);
-
-                // 鏇存柊鏈�鍚庢墽琛屾椂闂翠负褰撳墠鏃堕棿
                 LocalDateTime lastExecutionTime = LocalDateTime.now();
-
-                // 璁$畻涓嬫鎵ц鏃堕棿
                 LocalDateTime nextExecutionTime = calculateNextExecutionTime(
                         task.getFrequencyType(),
                         task.getFrequencyDetail(),
                         lastExecutionTime
                 );
 
-                // 鎵ц鏇存柊鎿嶄綔
-                String updateSql = "UPDATE maintenance_task " +
-                        "SET last_execution_time = ?, next_execution_time = ? " +
-                        "WHERE id = ?";
-
-                jdbcTemplate.update(
-                        updateSql,
-                        lastExecutionTime,
-                        nextExecutionTime,
-                        taskId
-                );
+                String updateSql = "UPDATE maintenance_task SET last_execution_time = ?, next_execution_time = ? WHERE id = ?";
+                jdbcTemplate.update(updateSql, lastExecutionTime, nextExecutionTime, taskId);
             }
         } catch (Exception e) {
             throw new JobExecutionException(e);
         }
     }
 
-    // 杩欏氨鏄偍鎻愪緵鐨勪唬鐮佸皝瑁呮垚鐨勬柟娉�
-    private DeviceMaintenance createInspectionTask(MaintenanceTask timingTask) {
+    private DeviceMaintenance createInspectionTask(MaintenanceTask timingTask, Long deviceLedgerId) {
         DeviceMaintenance inspectionTask = new DeviceMaintenance();
-
-        // 澶嶅埗鍩烘湰灞炴��
-        inspectionTask.setDeviceName(timingTask.getTaskName());
+        DeviceLedger deviceLedger = deviceLedgerMapper.selectById(deviceLedgerId);
+        inspectionTask.setDeviceName(deviceLedger != null ? deviceLedger.getDeviceName() : timingTask.getTaskName());
         inspectionTask.setMaintenanceTaskId(timingTask.getId());
-        inspectionTask.setDeviceLedgerId(timingTask.getTaskId());
+        inspectionTask.setDeviceLedgerId(deviceLedgerId);
+        inspectionTask.setAreaId(timingTask.getAreaId() != null ? timingTask.getAreaId() : (deviceLedger != null ? deviceLedger.getAreaId() : null));
         inspectionTask.setMaintenancePlanTime(LocalDateTime.now());
         inspectionTask.setFrequencyType(timingTask.getFrequencyType());
         inspectionTask.setFrequencyDetail(timingTask.getFrequencyDetail());
         inspectionTask.setTenantId(timingTask.getTenantId());
         inspectionTask.setStatus(0);
-        inspectionTask.setDeviceModel(timingTask.getDeviceModel());
+        inspectionTask.setDeviceModel(deviceLedger != null ? deviceLedger.getDeviceModel() : timingTask.getDeviceModel());
         inspectionTask.setCreateUser(Integer.parseInt(timingTask.getRegistrantId().toString()));
         inspectionTask.setUpdateTime(LocalDateTime.now());
         inspectionTask.setCreateTime(LocalDateTime.now());
@@ -104,13 +103,33 @@
         return inspectionTask;
     }
 
+    private List<Long> resolveDeviceIds(MaintenanceTask timingTask) {
+        if (timingTask.getDeviceLedgerIdsStr() != null && !timingTask.getDeviceLedgerIdsStr().trim().isEmpty()) {
+            return Arrays.stream(timingTask.getDeviceLedgerIdsStr().split(","))
+                    .map(String::trim)
+                    .filter(item -> !item.isEmpty())
+                    .map(Long::valueOf)
+                    .distinct()
+                    .collect(java.util.stream.Collectors.toList());
+        }
+        List<Long> ids = new ArrayList<>();
+        if (timingTask.getTaskId() != null) {
+            ids.add(timingTask.getTaskId());
+        }
+        return ids;
+    }
 
-    /**
-     * 璁$畻涓嬫鎵ц鏃堕棿
-     */
-    private LocalDateTime calculateNextExecutionTime(String frequencyType,
-                                                     String frequencyDetail,
-                                                     LocalDateTime currentTime) {
+    private int resolveQuantity(Long deviceLedgerId) {
+        try {
+            String sql = "SELECT number FROM device_ledger WHERE id = ?";
+            Number quantity = jdbcTemplate.queryForObject(sql, Number.class, deviceLedgerId);
+            return quantity == null || quantity.intValue() < 1 ? 1 : quantity.intValue();
+        } catch (Exception ignored) {
+            return 1;
+        }
+    }
+
+    private LocalDateTime calculateNextExecutionTime(String frequencyType, String frequencyDetail, LocalDateTime currentTime) {
         try {
             switch (frequencyType) {
                 case "DAILY":
@@ -129,84 +148,52 @@
         }
     }
 
-    /**
-     * 璁$畻姣忔棩浠诲姟鐨勪笅娆℃墽琛屾椂闂�
-     */
     private LocalDateTime calculateDailyNextTime(String timeStr, LocalDateTime current) {
-        LocalTime executionTime = LocalTime.parse(timeStr); // 瑙f瀽鏍煎紡 "HH:mm"
+        LocalTime executionTime = LocalTime.parse(timeStr);
         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瀽鏄熸湡鍑�(鏀寔澶氫釜鏄熸湡)
+        String dayOfWeekStr = parts[0];
+        LocalTime time = LocalTime.parse(parts[1]);
         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)
+        return 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 quarterMonth = Integer.parseInt(parts[0]);
         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);
+            targetYearMonth = YearMonth.from(current).plusMonths(quarterMonth - currentMonthInQuarter);
         } else {
-            // 闇�瑕佸埌涓嬩釜瀛e害
-            targetYearMonth = YearMonth.from(current)
-                    .plusMonths(3 - currentMonthInQuarter + quarterMonth);
+            targetYearMonth = YearMonth.from(current).plusMonths(3 - currentMonthInQuarter + quarterMonth);
         }
-
-        // 澶勭悊鏈堟湯鏃ユ湡
         int adjustedDay = Math.min(dayOfMonth, targetYearMonth.lengthOfMonth());
 
         return LocalDateTime.of(
@@ -218,26 +205,36 @@
         );
     }
 
-    /**
-     * 瑙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);
+                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;
     }
 }
diff --git a/src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskServiceImpl.java b/src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskServiceImpl.java
index 0c00da7..5c84b2e 100644
--- a/src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskServiceImpl.java
+++ b/src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskServiceImpl.java
@@ -2,9 +2,14 @@
 
 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.device.mapper.DeviceAreaMapper;
 import com.ruoyi.device.mapper.MaintenanceTaskMapper;
+import com.ruoyi.device.pojo.DeviceArea;
+import com.ruoyi.device.pojo.DeviceLedger;
 import com.ruoyi.device.pojo.MaintenanceTask;
+import com.ruoyi.device.service.IDeviceLedgerService;
 import com.ruoyi.device.service.MaintenanceTaskService;
 import com.ruoyi.framework.web.domain.AjaxResult;
 import com.ruoyi.inspectiontask.pojo.TimingTask;
@@ -16,65 +21,81 @@
 import org.springframework.stereotype.Service;
 
 import java.time.LocalDateTime;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
 
-/**
- * @author :yys
- * @date : 2025/12/22 14:57
- */
 @Service
 @Slf4j
 public class MaintenanceTaskServiceImpl extends ServiceImpl<MaintenanceTaskMapper, MaintenanceTask> implements MaintenanceTaskService {
 
     @Autowired
     private MaintenanceTaskMapper maintenanceTaskMapper;
-
     @Autowired
     private SysUserMapper sysUserMapper;
-
     @Autowired
     private TimingTaskServiceImpl timingTaskService;
-
     @Autowired
     private MaintenanceTaskScheduler maintenanceTaskScheduler;
+    @Autowired
+    private IDeviceLedgerService deviceLedgerService;
+    @Autowired
+    private DeviceAreaMapper deviceAreaMapper;
 
     @Override
     public AjaxResult listPage(Page page, MaintenanceTask maintenanceTask) {
-        Page<MaintenanceTask> taskPage = maintenanceTaskMapper.selectPage(page, null);
-        // 2. 濡傛灉娌℃湁鏁版嵁锛岀洿鎺ヨ繑鍥炵┖鍒嗛〉
+        com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<MaintenanceTask> queryWrapper =
+                new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<>();
+        if (StringUtils.isNotEmpty(maintenanceTask.getTaskName())) {
+            queryWrapper.like(MaintenanceTask::getTaskName, maintenanceTask.getTaskName());
+        }
+        if (maintenanceTask.getAreaId() != null) {
+            queryWrapper.eq(MaintenanceTask::getAreaId, maintenanceTask.getAreaId());
+        }
+        Page<MaintenanceTask> taskPage = maintenanceTaskMapper.selectPage(page, queryWrapper);
         if (taskPage.getRecords().isEmpty()) {
             return AjaxResult.success(taskPage);
         }
 
-        // 3. 鏀堕泦鎵�鏈夐渶瑕佹煡璇㈢殑鐢ㄦ埛ID
         Set<Long> userIds = new HashSet<>();
-
-        // 鏀堕泦鐧昏浜篒D
         taskPage.getRecords().forEach(task -> {
             if (task.getRegistrantId() != null) {
                 userIds.add(task.getRegistrantId());
             }
         });
 
-        // 4. 鎵归噺鏌ヨ鐢ㄦ埛淇℃伅
         Map<Long, String> userNickNameMap = new HashMap<>();
         if (!userIds.isEmpty()) {
-            List<SysUser> users = sysUserMapper.selectUserByIds((new ArrayList<>(userIds)));
+            List<SysUser> users = sysUserMapper.selectUserByIds(new ArrayList<>(userIds));
             users.forEach(user -> userNickNameMap.put(user.getUserId(), user.getNickName()));
         }
+        Map<Long, String> areaNameMap = deviceAreaMapper.selectBatchIds(taskPage.getRecords().stream()
+                        .map(MaintenanceTask::getAreaId)
+                        .filter(java.util.Objects::nonNull)
+                        .distinct()
+                        .collect(Collectors.toList()))
+                .stream()
+                .collect(Collectors.toMap(DeviceArea::getId, DeviceArea::getAreaName, (left, right) -> left, HashMap::new));
         taskPage.getRecords().forEach(task -> {
-            // 璁剧疆鐧昏浜烘樀绉�
             if (task.getRegistrantId() != null) {
                 task.setRegistrant(userNickNameMap.getOrDefault(task.getRegistrantId(), "鏈煡鐢ㄦ埛"));
             }
+            task.setAreaName(areaNameMap.get(task.getAreaId()));
         });
         return AjaxResult.success(taskPage);
     }
 
     @Override
     public AjaxResult add(MaintenanceTask maintenanceTask) {
+        if (!prepareMaintenanceTask(maintenanceTask)) {
+            return AjaxResult.error("璇烽�夋嫨璁惧");
+        }
         maintenanceTask.setActive(true);
-        // 璁$畻棣栨鎵ц鏃堕棿
         TimingTask task = new TimingTask();
         task.setFrequencyType(maintenanceTask.getFrequencyType());
         task.setFrequencyDetail(maintenanceTask.getFrequencyDetail());
@@ -94,6 +115,10 @@
             return AjaxResult.warn("娌℃湁姝ゆ暟鎹�");
         }
         BeanUtils.copyProperties(maintenanceTask, maintenanceTask1);
+        if (!prepareMaintenanceTask(maintenanceTask1)) {
+            return AjaxResult.error("璇烽�夋嫨璁惧");
+        }
+        maintenanceTask1.setDeviceLedgerIds(null);
         int update = maintenanceTaskMapper.updateById(maintenanceTask1);
         if (update > 0) {
             maintenanceTaskScheduler.rescheduleMaintenanceTask(maintenanceTask1);
@@ -105,10 +130,40 @@
     public AjaxResult delete(List<Long> ids) {
         int delete = maintenanceTaskMapper.deleteBatchIds(ids);
         if (delete > 0) {
-            ids.forEach(id -> {
-                maintenanceTaskScheduler.unscheduleMaintenanceTask(id);
-            });
+            ids.forEach(id -> maintenanceTaskScheduler.unscheduleMaintenanceTask(id));
         }
         return AjaxResult.success("鍒犻櫎鎴愬姛");
     }
+
+    private boolean prepareMaintenanceTask(MaintenanceTask task) {
+        Long[] deviceIds = task.getDeviceLedgerIds();
+        if ((deviceIds == null || deviceIds.length == 0) && StringUtils.isNotEmpty(task.getDeviceLedgerIdsStr())) {
+            deviceIds = Arrays.stream(task.getDeviceLedgerIdsStr().split(","))
+                    .filter(StringUtils::isNotEmpty)
+                    .map(Long::valueOf)
+                    .toArray(Long[]::new);
+        }
+        if (deviceIds == null || deviceIds.length == 0) {
+            deviceIds = task.getTaskId() == null ? new Long[0] : new Long[]{task.getTaskId()};
+        }
+        List<Long> validIds = Arrays.stream(deviceIds).distinct().collect(Collectors.toList());
+        if (validIds.isEmpty()) {
+            return false;
+        }
+        List<DeviceLedger> devices = validIds.stream()
+                .map(deviceLedgerService::getById)
+                .filter(device -> device != null)
+                .collect(Collectors.toList());
+        if (devices.isEmpty()) {
+            return false;
+        }
+        task.setTaskId(devices.get(0).getId());
+        if (task.getAreaId() == null) {
+            task.setAreaId(devices.get(0).getAreaId());
+        }
+        task.setDeviceLedgerIdsStr(devices.stream().map(item -> String.valueOf(item.getId())).collect(Collectors.joining(",")));
+        task.setTaskName(devices.stream().map(DeviceLedger::getDeviceName).filter(StringUtils::isNotEmpty).distinct().collect(Collectors.joining(",")));
+        task.setDeviceModel(devices.stream().map(DeviceLedger::getDeviceModel).filter(StringUtils::isNotEmpty).distinct().collect(Collectors.joining(",")));
+        return true;
+    }
 }
diff --git a/src/main/java/com/ruoyi/http/service/controller/JclyController.java b/src/main/java/com/ruoyi/http/service/controller/JclyController.java
new file mode 100644
index 0000000..ed86d62
--- /dev/null
+++ b/src/main/java/com/ruoyi/http/service/controller/JclyController.java
@@ -0,0 +1,51 @@
+package com.ruoyi.http.service.controller;
+
+import com.ruoyi.framework.web.controller.BaseController;
+import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.http.service.impl.RealTimeEnergyConsumptionServiceImpl;
+import io.swagger.annotations.Api;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.naming.ldap.PagedResultsControl;
+import java.util.*;
+
+@RestController
+@RequestMapping("/iot")
+@Api(tags = "鏁伴噰鎺ュ彛")
+public class JclyController extends BaseController {
+
+    @Autowired
+    private RealTimeEnergyConsumptionServiceImpl realTimeEnergyConsumptionService;
+
+    private final String DEVICE_GUID = "90444196515214284663";
+
+    private final String DEVICE_GUID_2 = "90187099059463151919";
+
+    private final String DEVICE_GUID_3 = "90299548548536240693";
+
+    private final String DEVICE_GUID_4 = "90558670647417764794";
+
+    private final String DEVICE_GUID_5 = "90802100373808917949";
+
+    private final String DEVICE_GUID_6 = "90878497978270816672";
+
+    /**
+     * 瀹炴椂鑾峰彇娓╂箍搴︼紝浜屾哀鍖栫⒊鏁版嵁
+     */
+    @GetMapping("/getRealData")
+    public AjaxResult getRealData() {
+        List<Map<String,String>> maps = realTimeEnergyConsumptionService
+                .getRealData(Arrays.
+                        asList(DEVICE_GUID,
+                                DEVICE_GUID_2,
+                                DEVICE_GUID_3,
+                                DEVICE_GUID_4,
+                                DEVICE_GUID_5,
+                                DEVICE_GUID_6));
+        return AjaxResult.success(maps);
+    }
+
+}
diff --git a/src/main/java/com/ruoyi/http/service/impl/RealTimeEnergyConsumptionServiceImpl.java b/src/main/java/com/ruoyi/http/service/impl/RealTimeEnergyConsumptionServiceImpl.java
index 6b10ba2..8b0b28a 100644
--- a/src/main/java/com/ruoyi/http/service/impl/RealTimeEnergyConsumptionServiceImpl.java
+++ b/src/main/java/com/ruoyi/http/service/impl/RealTimeEnergyConsumptionServiceImpl.java
@@ -6,9 +6,11 @@
 import com.ruoyi.common.utils.http.HttpUtils;
 import com.ruoyi.http.service.RealTimeEnergyConsumptionService;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.stereotype.Service;
 
-import java.util.Collections;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -25,7 +27,7 @@
 
     private static final String TOKEN_URL = "/elitechAccess/getToken";
 
-    private static final String REAL_TIME_URL = "/elitechAccess/v2/getRealTimeData"; //鑾峰彇璁惧瀹炴椂鏁版嵁
+    private static final String REAL_TIME_URL = "/elitechAccess/v2/getRealTimeData";
 
     private static final String KET_ID = "75804708";
 
@@ -35,96 +37,121 @@
 
     private static final String PASS_WORD = "y17775163675";
 
-    private static final String DEVICE_GUID = "90444196515214284663";
-
+    @Autowired
+    private RedisTemplate<String, String> redisTemplate;
 
     /**
-     * 鏍规嵁paramCode鎻愬彇鎺㈠ご鍙傛暟
-     * @param paramList 璁惧鍙傛暟鏁扮粍
-     * @param targetCode 鐩爣鎺㈠ご缂栫爜
-     * @return 鎺㈠ご鍙傛暟瀵硅薄锛堝寘鍚玭ame/value/unit锛�
+     * 鏍规嵁 paramCode 鎻愬彇鎺㈠ご鍙傛暟銆�
      */
     private static JSONObject getProbeParam(JSONArray paramList, String targetCode) {
+        if (paramList == null) {
+            return new JSONObject();
+        }
         for (int i = 0; i < paramList.size(); i++) {
             JSONObject paramObj = paramList.getJSONObject(i);
             if (targetCode.equals(paramObj.getString("paramCode"))) {
                 return paramObj;
             }
         }
-        return new JSONObject(); // 鏈尮閰嶅埌杩斿洖绌哄璞★紝閬垮厤绌烘寚閽�
+        return new JSONObject();
     }
 
     /**
-     * 瀹炴椂鑾峰彇娓╂箍搴︼紝浜屾哀鍖栫⒊鏁版嵁
+     * 瀹炴椂鑾峰彇娓╂箍搴︺�佸厜鐓с�佷簩姘у寲纰虫暟鎹��
      */
-    public static void main(String[] args) {
-        String realTimeData = getRealTimeData(getToken());
+    public List<Map<String, String>> getRealData(List<String> guidList) {
+        log.info("寮�濮嬭幏鍙栧疄鏃舵暟鎹�");
+        List<Map<String, String>> listMaps = new ArrayList<>();
+        String realTimeData = getRealTimeData(getToken(), guidList);
         Map<String, Object> map = JSON.parseObject(realTimeData, Map.class);
-        if(map.get("code").equals(0)){
-            // 1. 瑙f瀽澶栧眰data涓篔SON鏁扮粍锛堟帴鍙h繑鍥炵殑璁惧鍒楄〃锛�
-            JSONArray deviceList = JSON.parseArray(map.get("data").toString());
-            // 2. 閬嶅巻璁惧鍒楄〃锛堟澶勪粎鍙栫涓�涓澶囷紝鑻ユ湁澶氫釜璁惧鍙惊鐜鐞嗭級
-            if (!deviceList.isEmpty()) {
-                JSONObject deviceObj = deviceList.getJSONObject(0);
-                // 3. 瑙f瀽璁惧鍐呯殑鍙傛暟鏁扮粍锛堟墍鏈塸aramCode瀵瑰簲鐨勫弬鏁帮級
-                JSONArray paramList = deviceObj.getJSONArray("data");
+        if (!Integer.valueOf(0).equals(map.get("code"))) {
+            return listMaps;
+        }
 
-                // 4. 瀹氫箟鐩爣鎺㈠ご鐨刾aramCode锛屾寜闇�鎵╁睍
-                String[] targetCodes = {"0100", "0110", "0120", "0130"};
-                for (String code : targetCodes) {
-                    // 5. 閬嶅巻鍙傛暟鏁扮粍锛屽尮閰嶇洰鏍噋aramCode
-                    for (int i = 0; i < paramList.size(); i++) {
-                        JSONObject paramObj = paramList.getJSONObject(i);
-                        String currentCode = paramObj.getString("paramCode");
-                        if (code.equals(currentCode)) {
-                            // 6. 鎻愬彇鏍稿績瀛楁锛堝�笺�佸崟浣嶃�佹帰澶村悕绉帮級
-                            String paramName = paramObj.getString("paramName"); // 鎺㈠ご1/鎺㈠ご2...
-                            String value = paramObj.getString("value");       // 鏁板�硷紙345.80/24.90...锛�
-                            String unitCode = paramObj.getString("unitCode"); // 鍗曚綅锛圠ux/鈩�/%RH/ppm锛�
+        JSONArray deviceList = JSON.parseArray(String.valueOf(map.get("data")));
+        if (deviceList == null || deviceList.isEmpty()) {
+            return listMaps;
+        }
 
-                            // 7. 涓氬姟澶勭悊锛氭墦鍗�/璧嬪��/瀛樺偍绛夛紙鎸夐渶淇敼锛�
-                            System.out.println(paramName + "锛�" + value + " " + unitCode);
-                            // 鍖归厤鍒板悗鐩存帴璺冲嚭鍐呭眰寰幆锛屾彁鍗囨晥鐜�
-                            break;
-                        }
-                    }
+        String[] targetCodes = {"0100", "0110", "0120", "0130"};
+        for (int deviceIndex = 0; deviceIndex < deviceList.size(); deviceIndex++) {
+            JSONObject deviceObj = deviceList.getJSONObject(deviceIndex);
+            JSONArray paramList = deviceObj.getJSONArray("data");
+            Map<String, String> deviceData = new HashMap<>();
+            for (String code : targetCodes) {
+                JSONObject paramObj = getProbeParam(paramList, code);
+                if (paramObj.isEmpty()) {
+                    continue;
+                }
+                String paramName = paramObj.getString("paramName");
+                String value = paramObj.getString("value");
+                String unitCode = paramObj.getString("unitCode");
+                log.info("{}: {} {}", paramName, value, unitCode);
+                switch (paramName) {
+                    case "鎺㈠ご1":
+                        deviceData.put("light", value + unitCode);
+                        break;
+                    case "鎺㈠ご2":
+                        deviceData.put("temperature", value + unitCode);
+                        break;
+                    case "鎺㈠ご3":
+                        deviceData.put("humidity", value + unitCode);
+                        break;
+                    case "鎺㈠ご4":
+                        deviceData.put("co2", value + unitCode);
+                        break;
+                    default:
+                        break;
                 }
             }
+            listMaps.add(deviceData);
         }
+        return listMaps;
+    }
+
+    public static void main(String[] args) {
         System.out.println();
     }
 
-    public static String getToken(){
+    public String getToken() {
+        String cachedToken = sanitizeToken(redisTemplate.opsForValue().get("JCLY_TOKEN:"));
+        if (cachedToken != null) {
+            return cachedToken;
+        }
         Map<String, String> param = new HashMap<>();
         param.put("keyId", KET_ID);
         param.put("keySecret", KEY_SECRET);
         param.put("userName", USER_NAME);
         param.put("password", PASS_WORD);
-        log.info("璇锋眰鍙傛暟锛歿}", JSON.toJSONString( param));
+        log.info("璇锋眰鍙傛暟锛歿}", JSON.toJSONString(param));
         String result = HttpUtils.sendPostJson(URL + TOKEN_URL, JSON.toJSONString(param));
         log.info("杩斿洖缁撴灉锛歿}", result);
         Map<String, Object> map = JSON.parseObject(result, Map.class);
-        if (map.get("code").equals(0)) {
+        if (Integer.valueOf(0).equals(map.get("code"))) {
             Object token = map.get("data");
             log.info("token:{}", token);
+            redisTemplate.opsForValue().set("JCLY_TOKEN:", token.toString(), 60 * 60 * 24);
             return token.toString();
         }
         return result;
     }
 
-    public static String getRealTimeData(String  token){
+    private String sanitizeToken(String token) {
+        if (token == null) {
+            return null;
+        }
+        String cleanedToken = token.replace("\0", "").trim();
+        return cleanedToken.isEmpty() ? null : cleanedToken;
+    }
+
+    public static String getRealTimeData(String token, List<String> guidList) {
         Map<String, Object> param = new HashMap<>();
         param.put("keyId", KET_ID);
         param.put("keySecret", KEY_SECRET);
-        param.put("deviceGuids", Collections.singletonList(DEVICE_GUID));
-        log.info("璇锋眰鍙傛暟锛歿}", JSON.toJSONString( param));
-        String result = HttpUtils.sendPostJson(URL + REAL_TIME_URL, JSON.toJSONString(param),token);
+        param.put("deviceGuids", guidList);
+        log.info("璇锋眰鍙傛暟锛歿}", JSON.toJSONString(param));
+        String result = HttpUtils.sendPostJson(URL + REAL_TIME_URL, JSON.toJSONString(param), token);
         log.info("杩斿洖缁撴灉锛歿}", result);
         return result;
     }
-
-
-
-
-
 }
diff --git a/src/main/java/com/ruoyi/inspectiontask/pojo/InspectionTask.java b/src/main/java/com/ruoyi/inspectiontask/pojo/InspectionTask.java
index 4d95a96..ec51527 100644
--- a/src/main/java/com/ruoyi/inspectiontask/pojo/InspectionTask.java
+++ b/src/main/java/com/ruoyi/inspectiontask/pojo/InspectionTask.java
@@ -1,6 +1,10 @@
 package com.ruoyi.inspectiontask.pojo;
 
-import com.baomidou.mybatisplus.annotation.*;
+import com.baomidou.mybatisplus.annotation.FieldFill;
+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 com.ruoyi.framework.aspectj.lang.annotation.Excel;
 import io.swagger.annotations.ApiModel;
@@ -21,9 +25,6 @@
 
     private static final long serialVersionUID = 1L;
 
-    /**
-     * 宸℃浠诲姟鍞竴鏍囪瘑
-     */
     @TableId(type = IdType.AUTO)
     private Long id;
 
@@ -33,6 +34,13 @@
 
     @ApiModelProperty(value = "璁惧id")
     private Integer taskId;
+
+    @ApiModelProperty(value = "璁惧鍖哄煙id")
+    private Long areaId;
+
+    @TableField(exist = false)
+    @ApiModelProperty(value = "璁惧鍖哄煙鍚嶇О")
+    private String areaName;
 
     @ApiModelProperty(value = "宸℃浜篒D")
     private String inspectorId;
@@ -63,7 +71,7 @@
     @ApiModelProperty(value = "宸℃鍦扮偣璇︾粏鎻忚堪")
     private String inspectionLocation;
 
-    @ApiModelProperty(value = "杞垹闄ゆ爣蹇楋紝0=鏈垹闄わ紝1=宸插垹闄�")
+    @ApiModelProperty(value = "杞垹闄ゆ爣璁帮紝0=鏈垹闄わ紝1=宸插垹闄�")
     private Integer deleted;
 
     @ApiModelProperty(value = "鍒涘缓璇ヨ褰曠殑鐢ㄦ埛")
diff --git a/src/main/java/com/ruoyi/inspectiontask/pojo/TimingTask.java b/src/main/java/com/ruoyi/inspectiontask/pojo/TimingTask.java
index fb852be..474d53e 100644
--- a/src/main/java/com/ruoyi/inspectiontask/pojo/TimingTask.java
+++ b/src/main/java/com/ruoyi/inspectiontask/pojo/TimingTask.java
@@ -1,5 +1,6 @@
 package com.ruoyi.inspectiontask.pojo;
 
+import com.baomidou.mybatisplus.annotation.FieldFill;
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
@@ -23,9 +24,6 @@
 
     private static final long serialVersionUID = 1L;
 
-    /**
-     * 涓婚敭ID
-     */
     @TableId(type = IdType.AUTO)
     private Long id;
 
@@ -35,6 +33,16 @@
 
     @ApiModelProperty(value = "璁惧id")
     private Integer taskId;
+
+    @ApiModelProperty(value = "璁惧鍖哄煙id")
+    private Long areaId;
+
+    @TableField(exist = false)
+    @ApiModelProperty(value = "璁惧鍖哄煙鍚嶇О")
+    private String areaName;
+
+    @ApiModelProperty(value = "璁惧ID闆嗗悎")
+    private String taskIdsStr;
 
     @ApiModelProperty(value = "宸℃浜�")
     @Excel(name = "鎵ц宸℃浜�")
@@ -78,32 +86,33 @@
     @ApiModelProperty(value = "鐘舵��")
     private String status;
 
-    @ApiModelProperty(value = "杞垹闄ゆ爣蹇楋紝0=鏈垹闄わ紝1=宸插垹闄�")
+    @ApiModelProperty(value = "杞垹闄ゆ爣璁帮紝0=鏈垹闄わ紝1=宸插垹闄�")
     private Integer deleted;
 
     @TableField(exist = false)
     private String dateStr;
 
+    @TableField(exist = false)
+    @ApiModelProperty(value = "澶氶�夎澶嘔D")
+    private Long[] taskIds;
+
     @ApiModelProperty(value = "鍒涘缓璇ヨ褰曠殑鐢ㄦ埛")
-    @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT)
+    @TableField(fill = FieldFill.INSERT)
     private Integer createUser;
 
     @ApiModelProperty(value = "璁板綍鍒涘缓鏃堕棿")
-    @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT)
-//    @JsonFormat(pattern = "yyyy-MM-dd")
-//    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    @TableField(fill = FieldFill.INSERT)
     private LocalDateTime createTime;
 
     @ApiModelProperty(value = "鏈�鍚庝慨鏀硅璁板綍鐨勭敤鎴�")
-    @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT_UPDATE)
+    @TableField(fill = FieldFill.INSERT_UPDATE)
     private Integer updateUser;
 
     @ApiModelProperty(value = "璁板綍鏈�鍚庢洿鏂版椂闂�")
-    @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT_UPDATE)
+    @TableField(fill = FieldFill.INSERT_UPDATE)
     private LocalDateTime updateTime;
 
     @ApiModelProperty(value = "绉熸埛ID")
-    @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT)
+    @TableField(fill = FieldFill.INSERT)
     private Long tenantId;
-
 }
diff --git a/src/main/java/com/ruoyi/inspectiontask/service/impl/InspectionTaskServiceImpl.java b/src/main/java/com/ruoyi/inspectiontask/service/impl/InspectionTaskServiceImpl.java
index 8c30cb3..b15c7c6 100644
--- a/src/main/java/com/ruoyi/inspectiontask/service/impl/InspectionTaskServiceImpl.java
+++ b/src/main/java/com/ruoyi/inspectiontask/service/impl/InspectionTaskServiceImpl.java
@@ -16,6 +16,10 @@
 import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.bean.BeanUtils;
+import com.ruoyi.device.mapper.DeviceAreaMapper;
+import com.ruoyi.device.mapper.DeviceLedgerMapper;
+import com.ruoyi.device.pojo.DeviceArea;
+import com.ruoyi.device.pojo.DeviceLedger;
 import com.ruoyi.inspectiontask.dto.InspectionTaskDto;
 import com.ruoyi.inspectiontask.mapper.InspectionTaskMapper;
 import com.ruoyi.inspectiontask.pojo.InspectionTask;
@@ -72,12 +76,21 @@
     @Autowired
     private CommonFileServiceImpl commonFileService;
 
+    @Autowired
+    private DeviceLedgerMapper deviceLedgerMapper;
+
+    @Autowired
+    private DeviceAreaMapper deviceAreaMapper;
+
     @Override
     public IPage<InspectionTaskDto> selectInspectionTaskList(Page<InspectionTask> page, InspectionTaskDto inspectionTaskDto) {
         LambdaQueryWrapper<InspectionTask> queryWrapper = new LambdaQueryWrapper<>();
         queryWrapper.orderByDesc(InspectionTask::getCreateTime);
         if (StringUtils.isNotBlank(inspectionTaskDto.getTaskName())) {
             queryWrapper.like(InspectionTask::getTaskName, inspectionTaskDto.getTaskName());
+        }
+        if (inspectionTaskDto.getAreaId() != null) {
+            queryWrapper.eq(InspectionTask::getAreaId, inspectionTaskDto.getAreaId());
         }
         IPage<InspectionTask> entityPage = inspectionTaskMapper.selectPage(page, queryWrapper);
 
@@ -87,6 +100,10 @@
         }
         // 鑾峰彇id闆嗗悎
         List<Long> ids = entityPage.getRecords().stream().map(InspectionTask::getId).collect(Collectors.toList());
+        Map<Long, String> areaNameMap = buildAreaNameMap(entityPage.getRecords().stream()
+                .map(InspectionTask::getAreaId)
+                .filter(Objects::nonNull)
+                .collect(Collectors.toSet()));
         //鐧昏浜篿ds
         List<Long> registrantIds = entityPage.getRecords().stream().map(InspectionTask::getRegistrantId).collect(Collectors.toList());
         // 鎵归噺鏌ヨ鐧昏浜�
@@ -143,6 +160,7 @@
             if (sysUser != null) {
                 dto.setRegistrant(sysUser.getNickName());
             }
+            dto.setAreaName(areaNameMap.get(inspectionTask.getAreaId()));
             // 澶勭悊宸℃浜哄悕绉�
             if (StringUtils.isNotBlank(inspectionTask.getInspectorId())) {
                 String inspectorNames = Arrays.stream(inspectionTask.getInspectorId().split(","))
@@ -177,6 +195,14 @@
         return resultPage;
     }
 
+    private Map<Long, String> buildAreaNameMap(Set<Long> areaIds) {
+        if (areaIds == null || areaIds.isEmpty()) {
+            return Collections.emptyMap();
+        }
+        return deviceAreaMapper.selectBatchIds(new ArrayList<>(areaIds)).stream()
+                .collect(Collectors.toMap(DeviceArea::getId, DeviceArea::getAreaName, (left, right) -> left));
+    }
+
     // 鎻愬彇鍒涘缓BlobDTO鐨勫叕鍏辨柟娉�
     private StorageBlobDTO createBlobDto(StorageBlob blob) {
         StorageBlobDTO dto = new StorageBlobDTO();
@@ -204,6 +230,12 @@
     public int addOrEditInspectionTask(InspectionTaskDto inspectionTaskDto) throws IOException {
         InspectionTask inspectionTask = new InspectionTask();
         BeanUtils.copyProperties(inspectionTaskDto, inspectionTask);
+        if (inspectionTask.getAreaId() == null && inspectionTask.getTaskId() != null) {
+            DeviceLedger deviceLedger = deviceLedgerMapper.selectById(Long.valueOf(inspectionTask.getTaskId()));
+            if (deviceLedger != null) {
+                inspectionTask.setAreaId(deviceLedger.getAreaId());
+            }
+        }
         inspectionTask.setRegistrantId(SecurityUtils.getLoginUser().getUserId());
         inspectionTask.setRegistrant(SecurityUtils.getLoginUser().getUsername());
         int i;
diff --git a/src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskJob.java b/src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskJob.java
index b8ffdf5..b32f82b 100644
--- a/src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskJob.java
+++ b/src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskJob.java
@@ -1,29 +1,41 @@
 package com.ruoyi.inspectiontask.service.impl;
 
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.device.mapper.DeviceLedgerMapper;
+import com.ruoyi.device.pojo.DeviceLedger;
 import com.ruoyi.inspectiontask.mapper.InspectionTaskMapper;
 import com.ruoyi.inspectiontask.mapper.TimingTaskMapper;
 import com.ruoyi.inspectiontask.pojo.InspectionTask;
 import com.ruoyi.inspectiontask.pojo.TimingTask;
 import com.ruoyi.inspectiontask.service.TimingTaskService;
-import org.quartz.*;
+import org.quartz.DisallowConcurrentExecution;
+import org.quartz.Job;
+import org.quartz.JobDataMap;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobExecutionException;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.jdbc.core.BeanPropertyRowMapper;
 import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.stereotype.Component;
 
 import java.io.Serializable;
+import java.math.BigDecimal;
 import java.time.DayOfWeek;
 import java.time.LocalDateTime;
 import java.time.LocalTime;
 import java.time.YearMonth;
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Objects;
 import java.util.Set;
+import java.util.stream.Collectors;
 
 @Component
-@DisallowConcurrentExecution // 绂佹骞跺彂鎵ц鍚屼竴涓狫ob
+@DisallowConcurrentExecution
 public class TimingTaskJob implements Job, Serializable {
-    private static final long serialVersionUID = 1L; // 蹇呴』瀹氫箟搴忓垪鍖朓D
+    private static final long serialVersionUID = 1L;
 
     @Autowired
     private TimingTaskMapper timingTaskMapper;
@@ -37,18 +49,18 @@
     @Autowired
     private JdbcTemplate jdbcTemplate;
 
+    @Autowired
+    private DeviceLedgerMapper deviceLedgerMapper;
+
     @Override
     public void execute(JobExecutionContext context) throws JobExecutionException {
         JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();
-        // 淇绫诲瀷杞崲閿欒锛屾纭幏鍙杢askId
         Long taskId = jobDataMap.getLong("taskId");
 
         try {
-            // 3. 灏濊瘯鏌ヨ浣犵殑涓氬姟鏁版嵁
-            // 閫氳繃JDBC妯℃澘鏌ヨ瀹氭椂浠诲姟淇℃伅锛屼娇鐢ㄥ弬鏁板寲鏌ヨ闃叉SQL娉ㄥ叆
-            String yourSql = "SELECT * FROM timing_task where id = ?";
+            String sql = "SELECT * FROM timing_task WHERE id = ?";
             List<TimingTask> tasks = jdbcTemplate.query(
-                    yourSql,
+                    sql,
                     new BeanPropertyRowMapper<>(TimingTask.class),
                     taskId
             );
@@ -56,74 +68,77 @@
             if (timingTask == null) {
                 throw new JobExecutionException("鎵句笉鍒板畾鏃朵换鍔�: " + taskId);
             }
-            
-//            if (!timingTask.isActive()) {
-//                throw new JobExecutionException("瀹氭椂浠诲姟宸茬鐢�: " + taskId);
-//            }
 
-            // 2. 鍒涘缓骞朵繚瀛樺贰妫�浠诲姟璁板綍 - 杩欏氨鏄偍鎻愪緵鐨勪唬鐮佸簲璇ユ斁鐨勪綅缃�
-            InspectionTask inspectionTask = createInspectionTask(timingTask);
-            inspectionTaskMapper.insert(inspectionTask);
+            List<Long> deviceIds = resolveTaskIds(timingTask);
+            if (deviceIds.isEmpty()) {
+                throw new JobExecutionException("瀹氭椂浠诲姟鏈厤缃澶�: " + taskId);
+            }
 
-            // 3. 鏇存柊瀹氭椂浠诲姟鐨勬墽琛屾椂闂�
+            for (Long deviceId : deviceIds) {
+                DeviceLedger deviceLedger = deviceLedgerMapper.selectById(deviceId);
+                if (deviceLedger == null) {
+                    continue;
+                }
+                int count = getDeviceCount(deviceLedger.getNumber());
+                for (int i = 0; i < count; i++) {
+                    inspectionTaskMapper.insert(createInspectionTask(timingTask, deviceLedger));
+                }
+            }
+
             if (!tasks.isEmpty()) {
-                TimingTask task = tasks.get(0);
-
-                // 鏇存柊鏈�鍚庢墽琛屾椂闂翠负褰撳墠鏃堕棿
                 LocalDateTime lastExecutionTime = LocalDateTime.now();
-
-                // 璁$畻涓嬫鎵ц鏃堕棿
                 LocalDateTime nextExecutionTime = calculateNextExecutionTime(
-                        task.getFrequencyType(),
-                        task.getFrequencyDetail(),
+                        timingTask.getFrequencyType(),
+                        timingTask.getFrequencyDetail(),
                         lastExecutionTime
                 );
-
-                // 鎵ц鏇存柊鎿嶄綔
-                String updateSql = "UPDATE timing_task " +
-                        "SET last_execution_time = ?, next_execution_time = ? " +
-                        "WHERE id = ?";
-
-                jdbcTemplate.update(
-                        updateSql,
-                        lastExecutionTime,
-                        nextExecutionTime,
-                        taskId
-                );
+                String updateSql = "UPDATE timing_task SET last_execution_time = ?, next_execution_time = ? WHERE id = ?";
+                jdbcTemplate.update(updateSql, lastExecutionTime, nextExecutionTime, taskId);
             }
-//            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();
+    private List<Long> resolveTaskIds(TimingTask timingTask) {
+        if (StringUtils.isNotBlank(timingTask.getTaskIdsStr())) {
+            return Arrays.stream(timingTask.getTaskIdsStr().split(","))
+                    .filter(StringUtils::isNotBlank)
+                    .map(String::trim)
+                    .map(Long::valueOf)
+                    .distinct()
+                    .collect(Collectors.toList());
+        }
+        if (timingTask.getTaskId() != null) {
+            return new ArrayList<>(Arrays.asList(timingTask.getTaskId().longValue()));
+        }
+        return new ArrayList<>();
+    }
 
-        // 澶嶅埗鍩烘湰灞炴��
-        inspectionTask.setTaskName(timingTask.getTaskName());
-        inspectionTask.setTaskId(timingTask.getTaskId());
+    private int getDeviceCount(BigDecimal number) {
+        if (number == null) {
+            return 1;
+        }
+        int count = number.intValue();
+        return count > 0 ? count : 1;
+    }
+
+    private InspectionTask createInspectionTask(TimingTask timingTask, DeviceLedger deviceLedger) {
+        InspectionTask inspectionTask = new InspectionTask();
+        inspectionTask.setTaskName(deviceLedger.getDeviceName());
+        inspectionTask.setTaskId(deviceLedger.getId().intValue());
+        inspectionTask.setAreaId(deviceLedger.getAreaId());
         inspectionTask.setInspectorId(timingTask.getInspectorIds());
         inspectionTask.setInspectionLocation(timingTask.getInspectionLocation());
         inspectionTask.setRemarks("鑷姩鐢熸垚鑷畾鏃朵换鍔D: " + timingTask.getId());
         inspectionTask.setRegistrantId(timingTask.getRegistrantId());
+        inspectionTask.setRegistrant(timingTask.getRegistrant());
         inspectionTask.setFrequencyType(timingTask.getFrequencyType());
         inspectionTask.setFrequencyDetail(timingTask.getFrequencyDetail());
         inspectionTask.setTenantId(timingTask.getTenantId());
-
         return inspectionTask;
     }
 
-
-    /**
-     * 璁$畻涓嬫鎵ц鏃堕棿
-     */
     private LocalDateTime calculateNextExecutionTime(String frequencyType,
                                                      String frequencyDetail,
                                                      LocalDateTime currentTime) {
@@ -145,86 +160,54 @@
         }
     }
 
-    /**
-     * 璁$畻姣忔棩浠诲姟鐨勪笅娆℃墽琛屾椂闂�
-     */
     private LocalDateTime calculateDailyNextTime(String timeStr, LocalDateTime current) {
-        LocalTime executionTime = LocalTime.parse(timeStr); // 瑙f瀽鏍煎紡 "HH:mm"
+        LocalTime executionTime = LocalTime.parse(timeStr);
         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瀽鏄熸湡鍑�(鏀寔澶氫釜鏄熸湡)
+        String dayOfWeekStr = parts[0];
+        LocalTime time = LocalTime.parse(parts[1]);
         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)
+        return 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 quarterMonth = Integer.parseInt(parts[0]);
         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);
+            targetYearMonth = YearMonth.from(current).plusMonths(quarterMonth - currentMonthInQuarter);
         } else {
-            // 闇�瑕佸埌涓嬩釜瀛e害
-            targetYearMonth = YearMonth.from(current)
-                    .plusMonths(3 - currentMonthInQuarter + quarterMonth);
+            targetYearMonth = YearMonth.from(current).plusMonths(3 - currentMonthInQuarter + quarterMonth);
         }
 
-        // 澶勭悊鏈堟湯鏃ユ湡
         int adjustedDay = Math.min(dayOfMonth, targetYearMonth.lengthOfMonth());
-
         return LocalDateTime.of(
                 targetYearMonth.getYear(),
                 targetYearMonth.getMonthValue(),
@@ -234,23 +217,35 @@
         );
     }
 
-    /**
-     * 瑙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);
+                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);
             }
         }
 
diff --git a/src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskServiceImpl.java b/src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskServiceImpl.java
index 6607d68..f23a6a4 100644
--- a/src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskServiceImpl.java
+++ b/src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskServiceImpl.java
@@ -6,6 +6,10 @@
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.bean.BeanUtils;
+import com.ruoyi.device.mapper.DeviceAreaMapper;
+import com.ruoyi.device.mapper.DeviceLedgerMapper;
+import com.ruoyi.device.pojo.DeviceArea;
+import com.ruoyi.device.pojo.DeviceLedger;
 import com.ruoyi.inspectiontask.dto.TimingTaskDto;
 import com.ruoyi.inspectiontask.mapper.InspectionTaskMapper;
 import com.ruoyi.inspectiontask.mapper.TimingTaskMapper;
@@ -19,9 +23,23 @@
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
-import java.time.*;
+import java.time.DayOfWeek;
+import java.time.DateTimeException;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.Year;
+import java.time.YearMonth;
 import java.time.format.DateTimeFormatter;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
 import java.util.stream.Collectors;
 
 /**
@@ -44,35 +62,34 @@
     @Autowired
     private SysUserMapper sysUserMapper;
 
+    @Autowired
+    private DeviceLedgerMapper deviceLedgerMapper;
+
+    @Autowired
+    private DeviceAreaMapper deviceAreaMapper;
 
     @Override
     public IPage<TimingTaskDto> selectTimingTaskList(Page<TimingTask> page, TimingTask timingTask) {
-        // 1. 鍏堝垎椤垫煡璇㈠畾鏃朵换鍔℃暟鎹�
-        // 鏋勫缓鏌ヨ鏉′欢
         LambdaQueryWrapper<TimingTask> queryWrapper = new LambdaQueryWrapper<>();
         if (StringUtils.isNotBlank(timingTask.getTaskName())) {
             queryWrapper.like(TimingTask::getTaskName, timingTask.getTaskName());
         }
+        if (timingTask.getAreaId() != null) {
+            queryWrapper.eq(TimingTask::getAreaId, timingTask.getAreaId());
+        }
         IPage<TimingTask> taskPage = timingTaskMapper.selectPage(page, queryWrapper);
-
-        // 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 -> {
-            task.setDateStr(task.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
+            if (task.getCreateTime() != null) {
+                task.setDateStr(task.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
+            }
             if (StringUtils.isNotBlank(task.getInspectorIds())) {
                 Arrays.stream(task.getInspectorIds().split(","))
                         .filter(StringUtils::isNotBlank)
@@ -81,25 +98,27 @@
             }
         });
 
-        // 4. 鎵归噺鏌ヨ鐢ㄦ埛淇℃伅
         Map<Long, String> userNickNameMap = new HashMap<>();
         if (!userIds.isEmpty()) {
-            List<SysUser> users = sysUserMapper.selectUserByIds((new ArrayList<>(userIds)));
+            List<SysUser> users = sysUserMapper.selectUserByIds(new ArrayList<>(userIds));
             users.forEach(user -> userNickNameMap.put(user.getUserId(), user.getNickName()));
         }
 
-        // 5. 杞崲涓篋TO
+        Map<Long, String> areaNameMap = deviceAreaMapper.selectBatchIds(taskPage.getRecords().stream()
+                        .map(TimingTask::getAreaId)
+                        .filter(Objects::nonNull)
+                        .distinct()
+                        .collect(Collectors.toList()))
+                .stream()
+                .collect(Collectors.toMap(DeviceArea::getId, DeviceArea::getAreaName, (left, right) -> left, HashMap::new));
+
         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(), "鏈煡鐢ㄦ埛"));
             }
-
-            // 璁剧疆宸℃浜烘樀绉板垪琛�
+            dto.setAreaName(areaNameMap.get(task.getAreaId()));
             if (StringUtils.isNotBlank(task.getInspectorIds())) {
                 List<String> inspectorNickNames = new ArrayList<>();
                 for (String idStr : task.getInspectorIds().split(",")) {
@@ -110,11 +129,9 @@
                 }
                 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;
@@ -125,58 +142,90 @@
     public int addOrEditTimingTask(TimingTaskDto timingTaskDto) throws SchedulerException {
         TimingTask timingTask = new TimingTask();
         BeanUtils.copyProperties(timingTaskDto, timingTask);
-        // 1. 瑙f瀽瀛楃涓蹭负 LocalDate锛堝彧鍖呭惈骞存湀鏃ワ級
+        prepareTimingTask(timingTask);
+
         DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
         LocalDate localDate = LocalDate.now();
-        if(StringUtils.isNotEmpty(timingTaskDto.getDateStr())){
+        if (StringUtils.isNotEmpty(timingTaskDto.getDateStr())) {
             localDate = LocalDate.parse(timingTaskDto.getDateStr(), formatter);
         }
-        // 2. 鑾峰彇褰撳墠绯荤粺鐨� LocalTime锛堝寘鍚椂鍒嗙锛�
         LocalTime currentTime = LocalTime.now();
+        timingTask.setCreateTime(LocalDateTime.of(localDate, currentTime));
 
-        // 3. 鍚堝苟 LocalDate 鍜屽綋鍓� LocalTime 涓� LocalDateTime
-        LocalDateTime localDateTime = LocalDateTime.of(localDate, currentTime);
-        timingTask.setCreateTime(localDateTime);
-        // 璁剧疆鍒涘缓浜轰俊鎭拰榛樿鍊�
         if (Objects.isNull(timingTaskDto.getId())) {
             timingTask.setRegistrationDate(LocalDate.now());
             timingTask.setActive(true);
-
-            // 璁$畻棣栨鎵ц鏃堕棿
-            LocalDateTime firstExecutionTime = calculateFirstExecutionTime(timingTask);
-            timingTask.setNextExecutionTime(firstExecutionTime);
+            timingTask.setNextExecutionTime(calculateFirstExecutionTime(timingTask));
             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;
         }
+
+        int result = timingTaskMapper.updateById(timingTask);
+        if (result > 0) {
+            timingTaskScheduler.rescheduleTimingTask(timingTask);
+        }
+        return result;
+    }
+
+    private void prepareTimingTask(TimingTask timingTask) {
+        Long[] selectedTaskIds = timingTask.getTaskIds();
+        if ((selectedTaskIds == null || selectedTaskIds.length == 0) && timingTask.getTaskId() != null) {
+            selectedTaskIds = new Long[]{timingTask.getTaskId().longValue()};
+        }
+        if (selectedTaskIds == null || selectedTaskIds.length == 0) {
+            timingTask.setTaskIdsStr(null);
+            return;
+        }
+
+        List<Long> deviceIds = Arrays.stream(selectedTaskIds)
+                .filter(Objects::nonNull)
+                .distinct()
+                .collect(Collectors.toList());
+        if (deviceIds.isEmpty()) {
+            timingTask.setTaskIdsStr(null);
+            return;
+        }
+
+        List<DeviceLedger> devices = deviceLedgerMapper.selectBatchIds(deviceIds);
+        Map<Long, DeviceLedger> deviceMap = devices.stream()
+                .collect(Collectors.toMap(DeviceLedger::getId, device -> device, (left, right) -> left, LinkedHashMap::new));
+
+        List<Long> validDeviceIds = deviceIds.stream()
+                .filter(deviceMap::containsKey)
+                .collect(Collectors.toList());
+        if (validDeviceIds.isEmpty()) {
+            throw new IllegalArgumentException("鎵�閫夎澶囦笉瀛樺湪");
+        }
+
+        timingTask.setTaskIds(validDeviceIds.toArray(new Long[0]));
+        timingTask.setTaskIdsStr(validDeviceIds.stream().map(String::valueOf).collect(Collectors.joining(",")));
+        timingTask.setTaskId(validDeviceIds.get(0).intValue());
+        if (timingTask.getAreaId() == null) {
+            DeviceLedger firstDevice = deviceMap.get(validDeviceIds.get(0));
+            if (firstDevice != null) {
+                timingTask.setAreaId(firstDevice.getAreaId());
+            }
+        }
+        timingTask.setTaskName(validDeviceIds.stream()
+                .map(deviceMap::get)
+                .filter(Objects::nonNull)
+                .map(DeviceLedger::getDeviceName)
+                .filter(StringUtils::isNotBlank)
+                .collect(Collectors.joining(",")));
     }
 
     public LocalDateTime calculateFirstExecutionTime(TimingTask task) {
-        // 鏍规嵁棰戠巼绫诲瀷鍜岃鎯呰绠楅娆℃墽琛屾椂闂�
         String frequencyType = task.getFrequencyType();
         if ("DAILY".equals(frequencyType)) {
-            // 濡傛灉鏄瘡澶╂墽琛岋紝璁$畻浠婂ぉ鎴栨槑澶╃殑鍏蜂綋鏃堕棿
             return calculateDailyFirstExecution(task.getFrequencyDetail());
         } else if ("WEEKLY".equals(frequencyType)) {
-            // 濡傛灉鏄瘡鍛ㄦ墽琛岋紝璁$畻涓嬪懆鐨勫叿浣撴槦鏈熷嚑
             return calculateWeeklyFirstExecution(task.getFrequencyDetail());
         } else if ("MONTHLY".equals(frequencyType)) {
-            // 濡傛灉鏄瘡鏈堟墽琛岋紝璁$畻涓嬩釜鏈堢殑鍏蜂綋鏃ユ湡
             return calculateMonthlyFirstExecution(task.getFrequencyDetail());
         } else if ("QUARTERLY".equals(frequencyType)) {
-            // 鑷畾涔夐鐜囷紝濡傛瘡灏忔椂銆佹瘡30鍒嗛挓绛�
             return calculateCustomFirstExecution(task.getFrequencyDetail());
         } else {
             throw new IllegalArgumentException("涓嶆敮鎸佺殑棰戠巼绫诲瀷: " + task.getFrequencyType());
@@ -184,17 +233,14 @@
     }
 
     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);
     }
 
-    // 鏄犲皠鏄熸湡绠�鍐欎笌DayOfWeek
     private static final Map<String, DayOfWeek> WEEK_DAY_MAP = new HashMap<>();
+
     static {
         WEEK_DAY_MAP.put("MON", DayOfWeek.MONDAY);
         WEEK_DAY_MAP.put("TUE", DayOfWeek.TUESDAY);
@@ -206,47 +252,36 @@
     }
 
     private LocalDateTime calculateWeeklyFirstExecution(String frequencyDetail) {
-        // 瑙f瀽杈撳叆鍙傛暟
         String[] parts = frequencyDetail.split(",");
         if (parts.length != 2) {
-            throw new IllegalArgumentException("鍙傛暟鏍煎紡閿欒锛屽簲涓�'MON,13:43'鏍煎紡");
+            throw new IllegalArgumentException("鍙傛暟鏍煎紡閿欒锛屽簲涓� MON,13:43");
         }
 
         String weekDayStr = parts[0].trim();
         String timeStr = parts[1].trim();
-
-        // 鑾峰彇瀵瑰簲鐨勬槦鏈熷嚑
         DayOfWeek targetDay = WEEK_DAY_MAP.get(weekDayStr);
         if (targetDay == null) {
-            throw new IllegalArgumentException("鏃犳晥鐨勬槦鏈熺畝鍐�: " + weekDayStr);
+            throw new IllegalArgumentException("鏃犳晥鐨勬槦鏈�: " + weekDayStr);
         }
 
-        // 瑙f瀽鏃堕棿
         LocalTime targetTime = LocalTime.parse(timeStr, DateTimeFormatter.ofPattern("HH:mm"));
-
-        // 鑾峰彇褰撳墠鏃堕棿
         LocalDateTime now = LocalDateTime.now();
         LocalDateTime targetDateTime = now.with(targetDay).with(targetTime);
-
-        // 濡傛灉璁$畻鍑虹殑鏃堕棿鍦ㄥ綋鍓嶆椂闂翠箣鍓嶏紝鍒欏姞涓�鍛�
         if (targetDateTime.isBefore(now)) {
             targetDateTime = targetDateTime.plusWeeks(1);
         }
-
         return targetDateTime;
     }
 
     private LocalDateTime calculateMonthlyFirstExecution(String frequencyDetail) {
-        // 瑙f瀽杈撳叆鍙傛暟
         String[] parts = frequencyDetail.split(",");
         if (parts.length != 2) {
-            throw new IllegalArgumentException("鍙傛暟鏍煎紡閿欒锛屽簲涓�'03,17:00'鏍煎紡");
+            throw new IllegalArgumentException("鍙傛暟鏍煎紡閿欒锛屽簲涓� 03,17:00");
         }
 
         String dayStr = parts[0].trim();
         String timeStr = parts[1].trim();
 
-        // 瑙f瀽鏃ユ湡
         int dayOfMonth;
         try {
             dayOfMonth = Integer.parseInt(dayStr);
@@ -254,12 +289,10 @@
             throw new IllegalArgumentException("鏃犳晥鐨勬棩鏈熸牸寮�: " + dayStr, e);
         }
 
-        // 楠岃瘉鏃ユ湡鏈夋晥鎬э紙1-31涔嬮棿锛�
         if (dayOfMonth < 1 || dayOfMonth > 31) {
-            throw new IllegalArgumentException("鏃ユ湡蹇呴』鍦�1-31涔嬮棿: " + dayOfMonth);
+            throw new IllegalArgumentException("鏃ユ湡蹇呴』鍦� 1-31 涔嬮棿: " + dayOfMonth);
         }
 
-        // 瑙f瀽鏃堕棿
         LocalTime targetTime;
         try {
             targetTime = LocalTime.parse(timeStr, DateTimeFormatter.ofPattern("HH:mm"));
@@ -267,32 +300,18 @@
             throw new IllegalArgumentException("鏃犳晥鐨勬椂闂存牸寮�: " + timeStr, e);
         }
 
-        // 鑾峰彇褰撳墠鏃堕棿
         LocalDateTime now = LocalDateTime.now();
         LocalDateTime targetDateTime = now.withDayOfMonth(dayOfMonth).with(targetTime);
-
-        // 妫�鏌ユ棩鏈熸槸鍚﹁鑷姩璋冩暣锛堝31鏃ュ湪灏忔湀浼氳璋冩暣锛�
         boolean isDateAdjusted = targetDateTime.getDayOfMonth() != dayOfMonth;
-
-        // 濡傛灉鐩爣鏃堕棿鍦ㄥ綋鍓嶆椂闂翠箣鍓嶏紝鎴栬�呮棩鏈熻绯荤粺鑷姩璋冩暣浜�
         if (targetDateTime.isBefore(now) || isDateAdjusted) {
-            // 璁$畻涓嬩釜鏈堢殑鏃ユ湡
             LocalDateTime nextMonth = now.plusMonths(1);
-            // 灏濊瘯璁剧疆涓嬩釜鏈堢殑鐩爣鏃ユ湡
             LocalDateTime nextMonthTarget = nextMonth.withDayOfMonth(dayOfMonth).with(targetTime);
-
-            // 濡傛灉涓嬩釜鏈堢殑鏃ユ湡涔熻璋冩暣浜嗭紝灏辩敤涓嬩釜鏈堢殑鏈�鍚庝竴澶�
             if (nextMonthTarget.getDayOfMonth() != dayOfMonth) {
-                // 姝g‘鑾峰彇涓嬩釜鏈堢殑鏈�鍚庝竴澶╋紙淇isLeapYear璋冪敤闂锛�
-                int lastDayOfMonth = nextMonth.getMonth().length(
-                        Year.of(nextMonth.getYear()).isLeap()
-                );
+                int lastDayOfMonth = nextMonth.getMonth().length(Year.of(nextMonth.getYear()).isLeap());
                 nextMonthTarget = nextMonth.withDayOfMonth(lastDayOfMonth).with(targetTime);
             }
-
             targetDateTime = nextMonthTarget;
         }
-
         return targetDateTime;
     }
 
@@ -308,24 +327,16 @@
             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) {
@@ -347,86 +358,54 @@
         }
     }
 
-    /**
-     * 璁$畻姣忔棩浠诲姟鐨勪笅娆℃墽琛屾椂闂�
-     */
     private LocalDateTime calculateDailyNextTime(String timeStr, LocalDateTime current) {
-        LocalTime executionTime = LocalTime.parse(timeStr); // 瑙f瀽鏍煎紡 "HH:mm"
+        LocalTime executionTime = LocalTime.parse(timeStr);
         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瀽鏄熸湡鍑�(鏀寔澶氫釜鏄熸湡)
+        String dayOfWeekStr = parts[0];
+        LocalTime time = LocalTime.parse(parts[1]);
         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)
+        return 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 quarterMonth = Integer.parseInt(parts[0]);
         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);
+            targetYearMonth = YearMonth.from(current).plusMonths(quarterMonth - currentMonthInQuarter);
         } else {
-            // 闇�瑕佸埌涓嬩釜瀛e害
-            targetYearMonth = YearMonth.from(current)
-                    .plusMonths(3 - currentMonthInQuarter + quarterMonth);
+            targetYearMonth = YearMonth.from(current).plusMonths(3 - currentMonthInQuarter + quarterMonth);
         }
 
-        // 澶勭悊鏈堟湯鏃ユ湡
         int adjustedDay = Math.min(dayOfMonth, targetYearMonth.lengthOfMonth());
-
         return LocalDateTime.of(
                 targetYearMonth.getYear(),
                 targetYearMonth.getMonthValue(),
@@ -436,40 +415,47 @@
         );
     }
 
-    /**
-     * 瑙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);
+                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) {
         int i = timingTaskMapper.deleteBatchIds(Arrays.asList(ids));
-        if(i > 0){
+        if (i > 0) {
             for (Long id : ids) {
                 timingTaskScheduler.unscheduleTimingTask(id);
             }
         }
         return i;
     }
-
 }
diff --git a/src/main/resources/mapper/device/DeviceAreaMapper.xml b/src/main/resources/mapper/device/DeviceAreaMapper.xml
new file mode 100644
index 0000000..b797b6d
--- /dev/null
+++ b/src/main/resources/mapper/device/DeviceAreaMapper.xml
@@ -0,0 +1,22 @@
+<?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.device.mapper.DeviceAreaMapper">
+
+    <select id="queryPage" resultType="com.ruoyi.device.pojo.DeviceArea">
+        select
+            da.*,
+            parent.area_name as parentName
+        from device_area da
+        left join device_area parent on da.parent_id = parent.id
+        <where>
+            <if test="deviceArea.areaName != null and deviceArea.areaName != ''">
+                and da.area_name like concat('%', #{deviceArea.areaName}, '%')
+            </if>
+            <if test="deviceArea.parentId != null">
+                and da.parent_id = #{deviceArea.parentId}
+            </if>
+        </where>
+        order by da.parent_id asc, da.sort asc, da.id asc
+    </select>
+</mapper>
diff --git a/src/main/resources/mapper/device/DeviceLedgerMapper.xml b/src/main/resources/mapper/device/DeviceLedgerMapper.xml
index c980120..67522aa 100644
--- a/src/main/resources/mapper/device/DeviceLedgerMapper.xml
+++ b/src/main/resources/mapper/device/DeviceLedgerMapper.xml
@@ -7,86 +7,84 @@
 
     <select id="queryPage" resultType="com.ruoyi.device.dto.DeviceLedgerDto">
         SELECT
-        dl.id,
-        dl.device_name,
-        dl.device_model,
-        dl.supplier_name,
-        dl.device_brand,
-        dl.storage_location,
-        dl.unit,
-        dl.number,
-        dl.status,
-        dl.plan_runtime_time,
-        dl.start_runtime_time,
-        dl.end_runtime_time,
-        dl.runtime_duration,
-        dl.tax_including_price_unit,
-        dl.tax_including_price_total,
-        dl.tax_rate,
-        dl.un_tax_including_price_total,
-        dl.create_time,
-        dl.update_time ,
-        su.nick_name AS createUser,
-        dl.update_user,
-        dl.tenant_id,
-        dl.is_depr,
-        dl.annual_depreciation_amount,
-        dl.type
+            dl.id,
+            dl.device_name,
+            dl.device_model,
+            dl.device_brand,
+            dl.storage_location,
+            dl.area_id,
+            da.area_name,
+            dl.supplier_name,
+            dl.unit,
+            dl.number,
+            dl.status,
+            dl.plan_runtime_time,
+            dl.start_runtime_time,
+            dl.end_runtime_time,
+            dl.runtime_duration,
+            dl.tax_including_price_unit,
+            dl.tax_including_price_total,
+            dl.tax_rate,
+            dl.un_tax_including_price_total,
+            dl.create_time,
+            dl.update_time,
+            su.nick_name AS createUser,
+            dl.update_user,
+            dl.tenant_id,
+            dl.is_depr,
+            dl.annual_depreciation_amount,
+            dl.type
         FROM device_ledger dl
-        left join sys_user su on dl.create_user = su.user_id
+                 LEFT JOIN sys_user su ON dl.create_user = su.user_id
+                 LEFT JOIN device_area da ON dl.area_id = da.id
         <where>
-            <!-- 璁惧鍚嶇О -->
             <if test="deviceLedger.deviceName != null and deviceLedger.deviceName != ''">
-                AND device_name LIKE CONCAT('%', #{deviceLedger.deviceName}, '%')
+                AND dl.device_name LIKE CONCAT('%', #{deviceLedger.deviceName}, '%')
             </if>
-
-            <!-- 瑙勬牸鍨嬪彿 -->
             <if test="deviceLedger.deviceModel != null and deviceLedger.deviceModel != ''">
-                AND device_model LIKE CONCAT('%', #{deviceLedger.deviceModel}, '%')
+                AND dl.device_model LIKE CONCAT('%', #{deviceLedger.deviceModel}, '%')
             </if>
-
-            <!-- 渚涘簲鍟嗗悕绉� -->
             <if test="deviceLedger.supplierName != null and deviceLedger.supplierName != ''">
-                AND supplier_name LIKE CONCAT('%', #{deviceLedger.supplierName}, '%')
+                AND dl.supplier_name LIKE CONCAT('%', #{deviceLedger.supplierName}, '%')
             </if>
-
-            <!-- 鍗曚綅 -->
+            <if test="deviceLedger.areaId != null">
+                AND dl.area_id = #{deviceLedger.areaId}
+            </if>
+            <if test="deviceLedger.areaName != null and deviceLedger.areaName != ''">
+                AND da.area_name LIKE CONCAT('%', #{deviceLedger.areaName}, '%')
+            </if>
             <if test="deviceLedger.unit != null and deviceLedger.unit != ''">
-                AND unit = #{deviceLedger.unit}
+                AND dl.unit = #{deviceLedger.unit}
             </if>
-
-            <!-- 褰曞叆浜� -->
             <if test="deviceLedger.createUser != null and deviceLedger.createUser != ''">
-                AND create_user LIKE CONCAT('%', #{deviceLedger.createUser}, '%')
+                AND dl.create_user LIKE CONCAT('%', #{deviceLedger.createUser}, '%')
             </if>
-
-            <!-- 鏇存柊浜� -->
             <if test="deviceLedger.updateUser != null and deviceLedger.updateUser != ''">
-                AND update_user LIKE CONCAT('%', #{deviceLedger.updateUser}, '%')
+                AND dl.update_user LIKE CONCAT('%', #{deviceLedger.updateUser}, '%')
             </if>
-
             <if test="deviceLedger.entryDateStart != null and deviceLedger.entryDateStart != '' ">
                 AND dl.create_time &gt;= DATE_FORMAT(#{deviceLedger.entryDateStart},'%Y-%m-%d')
             </if>
             <if test="deviceLedger.entryDateEnd != null and deviceLedger.entryDateEnd != '' ">
                 AND dl.create_time &lt;= DATE_FORMAT(#{deviceLedger.entryDateEnd},'%Y-%m-%d')
             </if>
-
-            <!-- 绉熸埛ID -->
             <if test="deviceLedger.tenantId != null">
-                AND tenant_id = #{deviceLedger.tenantId}
+                AND dl.tenant_id = #{deviceLedger.tenantId}
             </if>
         </where>
-        ORDER BY create_time DESC
+        ORDER BY dl.create_time DESC
     </select>
+
     <select id="deviceLedgerExportList" resultType="com.ruoyi.device.execl.DeviceLedgerExeclDto">
 
     </select>
+
     <select id="selectById1" resultType="com.ruoyi.device.pojo.DeviceLedger">
         select *
         from device_ledger
         where id = #{id}
     </select>
+
     <select id="getDeviceTypeDistributionByYear"
             resultType="com.ruoyi.account.dto.DeviceTypeDetail"
             parameterType="java.lang.Integer">
@@ -99,6 +97,5 @@
           AND type IS NOT NULL
         GROUP BY type
     </select>
-
 
 </mapper>
diff --git a/src/main/resources/mapper/device/DeviceMaintenanceMapper.xml b/src/main/resources/mapper/device/DeviceMaintenanceMapper.xml
index 2ed16a4..b9c67cb 100644
--- a/src/main/resources/mapper/device/DeviceMaintenanceMapper.xml
+++ b/src/main/resources/mapper/device/DeviceMaintenanceMapper.xml
@@ -8,6 +8,7 @@
     <select id="queryPage" resultType="com.ruoyi.device.dto.DeviceMaintenanceDto">
         select dm.id,
         dm.device_ledger_id,
+        dm.area_id,
         dm.maintenance_plan_time,
         dm.maintenance_actually_time,
         dm.maintenance_result,
@@ -20,9 +21,11 @@
         dm.maintenance_actually_name,
         dl.device_name,
         dl.device_model,
+        da.area_name,
         su.nick_name as create_user_name
         from device_maintenance dm
         left join device_ledger dl on dm.device_ledger_id = dl.id
+        left join device_area da on dm.area_id = da.id
         left join sys_user su on dm.create_user = su.user_id
         <where>
             1 = 1
@@ -53,6 +56,7 @@
     <select id="detailById" resultType="com.ruoyi.device.dto.DeviceMaintenanceDto">
         select dm.id,
                dm.device_ledger_id,
+               dm.area_id,
                dm.maintenance_plan_time,
                dm.maintenance_actually_time,
                dm.maintenance_result,
@@ -65,9 +69,11 @@
                dm.maintenance_actually_name,
                dl.device_name,
                dl.device_model,
+               da.area_name,
                su.user_name as create_user_name
         from device_maintenance dm
                  left join device_ledger dl on dm.device_ledger_id = dl.id
+                 left join device_area da on dm.area_id = da.id
                  left join sys_user su on dm.create_user = su.user_id
         where dm.id = #{id}
     </select>
diff --git a/src/main/resources/mapper/device/DeviceRepairMapper.xml b/src/main/resources/mapper/device/DeviceRepairMapper.xml
index d093980..9bd2235 100644
--- a/src/main/resources/mapper/device/DeviceRepairMapper.xml
+++ b/src/main/resources/mapper/device/DeviceRepairMapper.xml
@@ -8,6 +8,7 @@
     <select id="queryPage" resultType="com.ruoyi.device.dto.DeviceRepairDto">
         select dr.id,
                dr.device_ledger_id,
+               dr.area_id,
                 dr.repair_time,
                 dr.repair_name,
                 dr.remark,
@@ -21,9 +22,11 @@
                 dr.update_user,
                dr.tenant_id,
                dl.device_name,
-               dl.device_model
+               dl.device_model,
+               da.area_name
         from device_repair dr
         left join device_ledger dl on dr.device_ledger_id = dl.id
+        left join device_area da on dr.area_id = da.id
         <where>
             1 = 1
             <if test="deviceRepairDto.deviceName != null">
@@ -53,6 +56,7 @@
     <select id="detailById" resultType="com.ruoyi.device.dto.DeviceRepairDto">
         select dr.id,
                dr.device_ledger_id,
+               dr.area_id,
                dr.repair_time,
                dr.repair_name,
                dr.remark,
@@ -66,9 +70,11 @@
                dr.update_user,
                dr.tenant_id,
                dl.device_name,
-               dl.device_model
+               dl.device_model,
+               da.area_name
         from device_repair dr
                  left join device_ledger dl on dr.device_ledger_id = dl.id
+                 left join device_area da on dr.area_id = da.id
         where dr.id = #{id}
     </select>
 
diff --git a/src/main/resources/mapper/measuringinstrumentledger/MeasuringInstrumentLedgerMapper.xml b/src/main/resources/mapper/measuringinstrumentledger/MeasuringInstrumentLedgerMapper.xml
index e4200af..266d8b0 100644
--- a/src/main/resources/mapper/measuringinstrumentledger/MeasuringInstrumentLedgerMapper.xml
+++ b/src/main/resources/mapper/measuringinstrumentledger/MeasuringInstrumentLedgerMapper.xml
@@ -15,7 +15,7 @@
         next_date,
         record_date,
         CASE
-        WHEN most_date &gt;=  DATE_FORMAT(now(),'%Y-%m-%d') THEN 1
+        WHEN DATE_ADD(most_date, INTERVAL IFNULL(cycle, 0) DAY) &gt;= CURDATE() THEN 1
         ELSE 2
         END AS status,
         create_user,
@@ -40,10 +40,10 @@
             <if test="req.status != null">
                 <choose>
                     <when test="req.status == 1">
-                        AND most_date &gt;=  DATE_FORMAT(now(),'%Y-%m-%d')
+                        AND DATE_ADD(most_date, INTERVAL IFNULL(cycle, 0) DAY) &gt;= CURDATE()
                     </when>
                     <when test="req.status == 2">
-                        AND most_date &lt;  DATE_FORMAT(now(),'%Y-%m-%d')
+                        AND DATE_ADD(most_date, INTERVAL IFNULL(cycle, 0) DAY) &lt; CURDATE()
                     </when>
                 </choose>
             </if>

--
Gitblit v1.9.3