From b16eec9b38aedda5f5e7e60f749f9b2dbba2a84e Mon Sep 17 00:00:00 2001
From: huminmin <mac@MacBook-Pro.local>
Date: 星期一, 29 六月 2026 18:00:25 +0800
Subject: [PATCH] 特种设备管理

---
 src/main/java/com/ruoyi/safe/specialequipment/service/SpecialEquipmentLedgerService.java                 |    8 
 src/main/java/com/ruoyi/safe/specialequipment/service/impl/SpecialEquipmentRectificationServiceImpl.java |   29 ++
 src/main/java/com/ruoyi/safe/specialequipment/controller/SpecialEquipmentLedgerController.java           |   34 ++
 src/main/java/com/ruoyi/safe/specialequipment/task/SpecialEquipmentReminderTask.java                     |   71 +++++
 src/main/java/com/ruoyi/safe/specialequipment/pojo/SpecialEquipmentRecord.java                           |   34 ++
 src/main/java/com/ruoyi/safe/specialequipment/service/impl/SpecialEquipmentRecordServiceImpl.java        |   55 ++++
 src/main/java/com/ruoyi/safe/specialequipment/service/SpecialEquipmentRecordService.java                 |    8 
 src/main/java/com/ruoyi/safe/specialequipment/controller/SpecialEquipmentRecordController.java           |   31 ++
 src/main/java/com/ruoyi/safe/specialequipment/pojo/SpecialEquipmentLedger.java                           |   50 ++++
 src/main/resources/mapper/safe/specialequipment/SpecialEquipmentRectificationMapper.xml                  |   42 +++
 src/main/java/com/ruoyi/safe/specialequipment/service/SpecialEquipmentRectificationService.java          |    8 
 src/main/java/com/ruoyi/safe/specialequipment/mapper/SpecialEquipmentLedgerMapper.java                   |    9 
 src/main/resources/mapper/safe/specialequipment/SpecialEquipmentRecordMapper.xml                         |   41 +++
 src/main/resources/mapper/safe/specialequipment/SpecialEquipmentLedgerMapper.xml                         |   83 ++++++
 src/main/java/com/ruoyi/safe/specialequipment/pojo/SpecialEquipmentRectification.java                    |   36 +++
 doc/特种设备管理建表SQL.sql                                                                                      |  100 ++++++++
 src/main/java/com/ruoyi/safe/specialequipment/mapper/SpecialEquipmentRectificationMapper.java            |    9 
 src/main/java/com/ruoyi/safe/specialequipment/controller/SpecialEquipmentRectificationController.java    |   32 ++
 src/main/java/com/ruoyi/safe/specialequipment/service/impl/SpecialEquipmentLedgerServiceImpl.java        |   24 ++
 src/main/java/com/ruoyi/safe/specialequipment/mapper/SpecialEquipmentRecordMapper.java                   |    9 
 20 files changed, 713 insertions(+), 0 deletions(-)

diff --git "a/doc/\347\211\271\347\247\215\350\256\276\345\244\207\347\256\241\347\220\206\345\273\272\350\241\250SQL.sql" "b/doc/\347\211\271\347\247\215\350\256\276\345\244\207\347\256\241\347\220\206\345\273\272\350\241\250SQL.sql"
new file mode 100644
index 0000000..aed6997
--- /dev/null
+++ "b/doc/\347\211\271\347\247\215\350\256\276\345\244\207\347\256\241\347\220\206\345\273\272\350\241\250SQL.sql"
@@ -0,0 +1,100 @@
+-- 鐗圭璁惧绠$悊
+-- 褰掑睘锛氬畨鍏ㄧ敓浜фā鍧�
+
+DROP TABLE IF EXISTS special_equipment_ledger;
+CREATE TABLE special_equipment_ledger (
+    id BIGINT NOT NULL AUTO_INCREMENT COMMENT '涓婚敭ID',
+    equipment_no VARCHAR(64) DEFAULT NULL COMMENT '璁惧缂栧彿',
+    equipment_name VARCHAR(128) DEFAULT NULL COMMENT '璁惧鍚嶇О',
+    equipment_type VARCHAR(64) DEFAULT NULL COMMENT '璁惧绫诲埆',
+    model_spec VARCHAR(128) DEFAULT NULL COMMENT '瑙勬牸鍨嬪彿',
+    manufacture_date DATE DEFAULT NULL COMMENT '鍒堕�犳棩鏈�',
+    install_location VARCHAR(255) DEFAULT NULL COMMENT '瀹夎浣嶇疆',
+    use_unit VARCHAR(255) DEFAULT NULL COMMENT '浣跨敤鍗曚綅',
+    certificate_no VARCHAR(128) DEFAULT NULL COMMENT '鐗圭璁惧浣跨敤鐧昏璇佸彿',
+    inspection_cycle_days INT DEFAULT NULL COMMENT '妫�楠屽懆鏈�(澶�)',
+    next_inspection_date DATE DEFAULT NULL COMMENT '涓嬫妫�楠屾棩鏈�',
+    maintenance_cycle_days INT DEFAULT NULL COMMENT '缁翠繚鍛ㄦ湡(澶�)',
+    next_maintenance_date DATE DEFAULT NULL COMMENT '涓嬫缁翠繚鏃ユ湡',
+    alarm_days INT DEFAULT 30 COMMENT '棰勮鎻愬墠澶╂暟',
+    manager_id BIGINT DEFAULT NULL COMMENT '璐熻矗浜篒D',
+    manager_name VARCHAR(64) DEFAULT NULL COMMENT '璐熻矗浜�',
+    safety_officer VARCHAR(64) DEFAULT NULL COMMENT '瀹夊叏鍛�',
+    risk_level VARCHAR(32) DEFAULT NULL COMMENT '椋庨櫓绛夌骇',
+    latest_inspection_date DATE DEFAULT NULL COMMENT '鏈�鏂版楠屾棩鏈�',
+    latest_maintenance_date DATE DEFAULT NULL COMMENT '鏈�鏂扮淮淇濇棩鏈�',
+    hazard_status TINYINT DEFAULT 0 COMMENT '闅愭偅鐘舵�� 0-鏃犻殣鎮� 1-寰呮暣鏀� 2-鏁存敼涓� 3-宸查棴鐜�',
+    hazard_description VARCHAR(500) DEFAULT NULL COMMENT '闅愭偅鎻忚堪',
+    rectification_deadline DATE DEFAULT NULL COMMENT '鏁存敼鎴鏃ユ湡',
+    remarks VARCHAR(500) DEFAULT NULL COMMENT '澶囨敞',
+    create_user BIGINT DEFAULT NULL COMMENT '鍒涘缓浜�',
+    create_time DATETIME DEFAULT NULL COMMENT '鍒涘缓鏃堕棿',
+    update_user BIGINT DEFAULT NULL COMMENT '鏇存柊浜�',
+    update_time DATETIME DEFAULT NULL COMMENT '鏇存柊鏃堕棿',
+    tenant_id BIGINT DEFAULT NULL COMMENT '绉熸埛ID',
+    dept_id BIGINT DEFAULT NULL COMMENT '閮ㄩ棬ID',
+    PRIMARY KEY (id),
+    KEY idx_ledger_equipment_no (equipment_no),
+    KEY idx_ledger_next_inspection_date (next_inspection_date),
+    KEY idx_ledger_next_maintenance_date (next_maintenance_date),
+    KEY idx_ledger_tenant_id (tenant_id),
+    KEY idx_ledger_dept_id (dept_id)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='鐗圭璁惧鐢靛瓙鍙拌处';
+
+DROP TABLE IF EXISTS special_equipment_record;
+CREATE TABLE special_equipment_record (
+    id BIGINT NOT NULL AUTO_INCREMENT COMMENT '涓婚敭ID',
+    equipment_id BIGINT DEFAULT NULL COMMENT '璁惧ID',
+    record_type TINYINT DEFAULT NULL COMMENT '璁板綍绫诲瀷 1-妫�楠� 2-缁翠繚',
+    record_no VARCHAR(64) DEFAULT NULL COMMENT '璁板綍缂栧彿',
+    record_date DATE DEFAULT NULL COMMENT '璁板綍鏃ユ湡',
+    execute_result VARCHAR(255) DEFAULT NULL COMMENT '鎵ц缁撴灉',
+    problem_description VARCHAR(500) DEFAULT NULL COMMENT '闂鎻忚堪',
+    dispose_measure VARCHAR(500) DEFAULT NULL COMMENT '澶勭悊鎺柦',
+    executor_id BIGINT DEFAULT NULL COMMENT '鎵ц浜篒D',
+    executor_name VARCHAR(64) DEFAULT NULL COMMENT '鎵ц浜�',
+    next_due_date DATE DEFAULT NULL COMMENT '涓嬫鍒版湡鏃ユ湡',
+    attachment_remark VARCHAR(500) DEFAULT NULL COMMENT '闄勪欢璇存槑',
+    create_user BIGINT DEFAULT NULL COMMENT '鍒涘缓浜�',
+    create_time DATETIME DEFAULT NULL COMMENT '鍒涘缓鏃堕棿',
+    update_user BIGINT DEFAULT NULL COMMENT '鏇存柊浜�',
+    update_time DATETIME DEFAULT NULL COMMENT '鏇存柊鏃堕棿',
+    tenant_id BIGINT DEFAULT NULL COMMENT '绉熸埛ID',
+    dept_id BIGINT DEFAULT NULL COMMENT '閮ㄩ棬ID',
+    PRIMARY KEY (id),
+    KEY idx_record_equipment_id (equipment_id),
+    KEY idx_record_record_type (record_type),
+    KEY idx_record_record_date (record_date),
+    KEY idx_record_next_due_date (next_due_date),
+    KEY idx_record_tenant_id (tenant_id),
+    KEY idx_record_dept_id (dept_id)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='鐗圭璁惧妫�楠岀淮淇濊褰�';
+
+DROP TABLE IF EXISTS special_equipment_rectification;
+CREATE TABLE special_equipment_rectification (
+    id BIGINT NOT NULL AUTO_INCREMENT COMMENT '涓婚敭ID',
+    equipment_id BIGINT DEFAULT NULL COMMENT '璁惧ID',
+    hazard_description VARCHAR(500) DEFAULT NULL COMMENT '闅愭偅鎻忚堪',
+    risk_level VARCHAR(32) DEFAULT NULL COMMENT '椋庨櫓绛夌骇',
+    discovered_date DATE DEFAULT NULL COMMENT '鍙戠幇鏃ユ湡',
+    responsible_user_id BIGINT DEFAULT NULL COMMENT '鏁存敼璐d换浜篒D',
+    responsible_user_name VARCHAR(64) DEFAULT NULL COMMENT '鏁存敼璐d换浜�',
+    rectification_deadline DATE DEFAULT NULL COMMENT '鏁存敼鏈熼檺',
+    rectification_status TINYINT DEFAULT 1 COMMENT '鏁存敼鐘舵�� 1-寰呮暣鏀� 2-鏁存敼涓� 3-寰呭鏍� 4-宸查棴鐜�',
+    rectification_measures VARCHAR(500) DEFAULT NULL COMMENT '鏁存敼鎺柦',
+    rectification_result VARCHAR(500) DEFAULT NULL COMMENT '鏁存敼缁撴灉',
+    closed_date DATE DEFAULT NULL COMMENT '闂幆鏃ユ湡',
+    remarks VARCHAR(500) DEFAULT NULL COMMENT '澶囨敞',
+    create_user BIGINT DEFAULT NULL COMMENT '鍒涘缓浜�',
+    create_time DATETIME DEFAULT NULL COMMENT '鍒涘缓鏃堕棿',
+    update_user BIGINT DEFAULT NULL COMMENT '鏇存柊浜�',
+    update_time DATETIME DEFAULT NULL COMMENT '鏇存柊鏃堕棿',
+    tenant_id BIGINT DEFAULT NULL COMMENT '绉熸埛ID',
+    dept_id BIGINT DEFAULT NULL COMMENT '閮ㄩ棬ID',
+    PRIMARY KEY (id),
+    KEY idx_rect_equipment_id (equipment_id),
+    KEY idx_rect_status (rectification_status),
+    KEY idx_rect_deadline (rectification_deadline),
+    KEY idx_rect_tenant_id (tenant_id),
+    KEY idx_rect_dept_id (dept_id)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='鐗圭璁惧闅愭偅鏁存敼';
diff --git a/src/main/java/com/ruoyi/safe/specialequipment/controller/SpecialEquipmentLedgerController.java b/src/main/java/com/ruoyi/safe/specialequipment/controller/SpecialEquipmentLedgerController.java
new file mode 100644
index 0000000..acbe1fb
--- /dev/null
+++ b/src/main/java/com/ruoyi/safe/specialequipment/controller/SpecialEquipmentLedgerController.java
@@ -0,0 +1,34 @@
+package com.ruoyi.safe.specialequipment.controller;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
+import com.ruoyi.framework.web.controller.BaseController;
+import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.safe.specialequipment.pojo.SpecialEquipmentLedger;
+import com.ruoyi.safe.specialequipment.service.SpecialEquipmentLedgerService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.AllArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+import java.util.List;
+@RestController
+@Tag(name = "瀹夊叏鐢熶骇--鐗圭璁惧鐢靛瓙鍙拌处")
+@RequestMapping("/safe/specialEquipment/ledger")
+@AllArgsConstructor
+public class SpecialEquipmentLedgerController extends BaseController {
+    private final SpecialEquipmentLedgerService service;
+    @GetMapping("/listPage") @Operation(summary = "鐗圭璁惧鍙拌处-鍒嗛〉鏌ヨ")
+    public AjaxResult listPage(Page page, SpecialEquipmentLedger req) { return AjaxResult.success(service.listPage(page, req)); }
+    @GetMapping("/list") @Operation(summary = "鐗圭璁惧鍙拌处-鍒楄〃鏌ヨ")
+    public AjaxResult list(SpecialEquipmentLedger req) { return AjaxResult.success(service.list(Wrappers.lambdaQuery(req))); }
+    @PostMapping("/add") @Log(title = "鐗圭璁惧鍙拌处-鏂板", businessType = BusinessType.INSERT)
+    @Operation(summary = "鐗圭璁惧鍙拌处-鏂板")
+    public AjaxResult add(@RequestBody SpecialEquipmentLedger req) { return service.save(req) ? success() : error(); }
+    @PostMapping("/update") @Log(title = "鐗圭璁惧鍙拌处-淇敼", businessType = BusinessType.UPDATE)
+    @Operation(summary = "鐗圭璁惧鍙拌处-淇敼")
+    public AjaxResult update(@RequestBody SpecialEquipmentLedger req) { return service.updateById(req) ? success() : error(); }
+    @DeleteMapping("/delete") @Log(title = "鐗圭璁惧鍙拌处-鍒犻櫎", businessType = BusinessType.DELETE)
+    @Operation(summary = "鐗圭璁惧鍙拌处-鍒犻櫎")
+    public AjaxResult delete(@RequestBody List<Long> ids) { return service.removeByIds(ids) ? success() : error(); }
+}
diff --git a/src/main/java/com/ruoyi/safe/specialequipment/controller/SpecialEquipmentRecordController.java b/src/main/java/com/ruoyi/safe/specialequipment/controller/SpecialEquipmentRecordController.java
new file mode 100644
index 0000000..b62eb70
--- /dev/null
+++ b/src/main/java/com/ruoyi/safe/specialequipment/controller/SpecialEquipmentRecordController.java
@@ -0,0 +1,31 @@
+package com.ruoyi.safe.specialequipment.controller;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
+import com.ruoyi.framework.web.controller.BaseController;
+import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.safe.specialequipment.pojo.SpecialEquipmentRecord;
+import com.ruoyi.safe.specialequipment.service.SpecialEquipmentRecordService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.AllArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+import java.util.List;
+@RestController
+@Tag(name = "瀹夊叏鐢熶骇--鐗圭璁惧妫�楠岀淮淇濊褰�")
+@RequestMapping("/safe/specialEquipment/record")
+@AllArgsConstructor
+public class SpecialEquipmentRecordController extends BaseController {
+    private final SpecialEquipmentRecordService service;
+    @GetMapping("/listPage") @Operation(summary = "妫�楠岀淮淇濊褰�-鍒嗛〉鏌ヨ")
+    public AjaxResult listPage(Page page, SpecialEquipmentRecord req) { return AjaxResult.success(service.listPage(page, req)); }
+    @PostMapping("/add") @Log(title = "妫�楠岀淮淇濊褰�-鏂板", businessType = BusinessType.INSERT)
+    @Operation(summary = "妫�楠岀淮淇濊褰�-鏂板")
+    public AjaxResult add(@RequestBody SpecialEquipmentRecord req) { return service.save(req) ? success() : error(); }
+    @PostMapping("/update") @Log(title = "妫�楠岀淮淇濊褰�-淇敼", businessType = BusinessType.UPDATE)
+    @Operation(summary = "妫�楠岀淮淇濊褰�-淇敼")
+    public AjaxResult update(@RequestBody SpecialEquipmentRecord req) { return service.updateById(req) ? success() : error(); }
+    @DeleteMapping("/delete") @Log(title = "妫�楠岀淮淇濊褰�-鍒犻櫎", businessType = BusinessType.DELETE)
+    @Operation(summary = "妫�楠岀淮淇濊褰�-鍒犻櫎")
+    public AjaxResult delete(@RequestBody List<Long> ids) { return service.removeByIds(ids) ? success() : error(); }
+}
diff --git a/src/main/java/com/ruoyi/safe/specialequipment/controller/SpecialEquipmentRectificationController.java b/src/main/java/com/ruoyi/safe/specialequipment/controller/SpecialEquipmentRectificationController.java
new file mode 100644
index 0000000..82c2d02
--- /dev/null
+++ b/src/main/java/com/ruoyi/safe/specialequipment/controller/SpecialEquipmentRectificationController.java
@@ -0,0 +1,32 @@
+package com.ruoyi.safe.specialequipment.controller;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
+import com.ruoyi.framework.web.controller.BaseController;
+import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.safe.specialequipment.pojo.SpecialEquipmentRectification;
+import com.ruoyi.safe.specialequipment.service.SpecialEquipmentRectificationService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.AllArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+import java.time.LocalDate;
+import java.util.List;
+@RestController
+@Tag(name = "瀹夊叏鐢熶骇--鐗圭璁惧闅愭偅鏁存敼")
+@RequestMapping("/safe/specialEquipment/rectification")
+@AllArgsConstructor
+public class SpecialEquipmentRectificationController extends BaseController {
+    private final SpecialEquipmentRectificationService service;
+    @GetMapping("/listPage") @Operation(summary = "闅愭偅鏁存敼-鍒嗛〉鏌ヨ")
+    public AjaxResult listPage(Page page, SpecialEquipmentRectification req) { return AjaxResult.success(service.listPage(page, req)); }
+    @PostMapping("/add") @Log(title = "闅愭偅鏁存敼-鏂板", businessType = BusinessType.INSERT)
+    @Operation(summary = "闅愭偅鏁存敼-鏂板")
+    public AjaxResult add(@RequestBody SpecialEquipmentRectification req) { return service.save(req) ? success() : error(); }
+    @PostMapping("/close") @Log(title = "闅愭偅鏁存敼-闂幆", businessType = BusinessType.UPDATE)
+    @Operation(summary = "闅愭偅鏁存敼-闂幆")
+    public AjaxResult close(@RequestBody SpecialEquipmentRectification req) { req.setRectificationStatus(4); req.setClosedDate(LocalDate.now()); return service.updateById(req) ? success() : error(); }
+    @DeleteMapping("/delete") @Log(title = "闅愭偅鏁存敼-鍒犻櫎", businessType = BusinessType.DELETE)
+    @Operation(summary = "闅愭偅鏁存敼-鍒犻櫎")
+    public AjaxResult delete(@RequestBody List<Long> ids) { return service.removeByIds(ids) ? success() : error(); }
+}
diff --git a/src/main/java/com/ruoyi/safe/specialequipment/mapper/SpecialEquipmentLedgerMapper.java b/src/main/java/com/ruoyi/safe/specialequipment/mapper/SpecialEquipmentLedgerMapper.java
new file mode 100644
index 0000000..b303143
--- /dev/null
+++ b/src/main/java/com/ruoyi/safe/specialequipment/mapper/SpecialEquipmentLedgerMapper.java
@@ -0,0 +1,9 @@
+package com.ruoyi.safe.specialequipment.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.safe.specialequipment.pojo.SpecialEquipmentLedger;
+import org.apache.ibatis.annotations.Param;
+public interface SpecialEquipmentLedgerMapper extends BaseMapper<SpecialEquipmentLedger> {
+    IPage<SpecialEquipmentLedger> listPage(Page page, @Param("req") SpecialEquipmentLedger req);
+}
diff --git a/src/main/java/com/ruoyi/safe/specialequipment/mapper/SpecialEquipmentRecordMapper.java b/src/main/java/com/ruoyi/safe/specialequipment/mapper/SpecialEquipmentRecordMapper.java
new file mode 100644
index 0000000..8cf15f8
--- /dev/null
+++ b/src/main/java/com/ruoyi/safe/specialequipment/mapper/SpecialEquipmentRecordMapper.java
@@ -0,0 +1,9 @@
+package com.ruoyi.safe.specialequipment.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.safe.specialequipment.pojo.SpecialEquipmentRecord;
+import org.apache.ibatis.annotations.Param;
+public interface SpecialEquipmentRecordMapper extends BaseMapper<SpecialEquipmentRecord> {
+    IPage<SpecialEquipmentRecord> listPage(Page page, @Param("req") SpecialEquipmentRecord req);
+}
diff --git a/src/main/java/com/ruoyi/safe/specialequipment/mapper/SpecialEquipmentRectificationMapper.java b/src/main/java/com/ruoyi/safe/specialequipment/mapper/SpecialEquipmentRectificationMapper.java
new file mode 100644
index 0000000..747e8f3
--- /dev/null
+++ b/src/main/java/com/ruoyi/safe/specialequipment/mapper/SpecialEquipmentRectificationMapper.java
@@ -0,0 +1,9 @@
+package com.ruoyi.safe.specialequipment.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.safe.specialequipment.pojo.SpecialEquipmentRectification;
+import org.apache.ibatis.annotations.Param;
+public interface SpecialEquipmentRectificationMapper extends BaseMapper<SpecialEquipmentRectification> {
+    IPage<SpecialEquipmentRectification> listPage(Page page, @Param("req") SpecialEquipmentRectification req);
+}
diff --git a/src/main/java/com/ruoyi/safe/specialequipment/pojo/SpecialEquipmentLedger.java b/src/main/java/com/ruoyi/safe/specialequipment/pojo/SpecialEquipmentLedger.java
new file mode 100644
index 0000000..2d079b6
--- /dev/null
+++ b/src/main/java/com/ruoyi/safe/specialequipment/pojo/SpecialEquipmentLedger.java
@@ -0,0 +1,50 @@
+package com.ruoyi.safe.specialequipment.pojo;
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+import java.time.*;
+@Data
+@Schema(description = "鐗圭璁惧鐢靛瓙鍙拌处")
+@TableName("special_equipment_ledger")
+public class SpecialEquipmentLedger {
+    private static final long serialVersionUID = 1L;
+    @TableId(type = IdType.AUTO) private Long id;
+    @Excel(name = "璁惧缂栧彿") private String equipmentNo;
+    @Excel(name = "璁惧鍚嶇О") private String equipmentName;
+    @Excel(name = "璁惧绫诲埆") private String equipmentType;
+    @Excel(name = "瑙勬牸鍨嬪彿") private String modelSpec;
+    @JsonFormat(pattern = "yyyy-MM-dd") @DateTimeFormat(pattern = "yyyy-MM-dd")
+    @Excel(name = "鍒堕�犳棩鏈�", width = 30, dateFormat = "yyyy-MM-dd") private LocalDate manufactureDate;
+    @Excel(name = "瀹夎浣嶇疆") private String installLocation;
+    @Excel(name = "浣跨敤鍗曚綅") private String useUnit;
+    @Excel(name = "鐧昏璇佸彿") private String certificateNo;
+    @Excel(name = "妫�楠屽懆鏈�(澶�)") private Integer inspectionCycleDays;
+    @JsonFormat(pattern = "yyyy-MM-dd") @DateTimeFormat(pattern = "yyyy-MM-dd")
+    @Excel(name = "涓嬫妫�楠屾棩鏈�", width = 30, dateFormat = "yyyy-MM-dd") private LocalDate nextInspectionDate;
+    @Excel(name = "缁翠繚鍛ㄦ湡(澶�)") private Integer maintenanceCycleDays;
+    @JsonFormat(pattern = "yyyy-MM-dd") @DateTimeFormat(pattern = "yyyy-MM-dd")
+    @Excel(name = "涓嬫缁翠繚鏃ユ湡", width = 30, dateFormat = "yyyy-MM-dd") private LocalDate nextMaintenanceDate;
+    @Excel(name = "棰勮鎻愬墠澶╂暟") private Integer alarmDays;
+    private Long managerId;
+    @Excel(name = "璐熻矗浜�") private String managerName;
+    @Excel(name = "瀹夊叏鍛�") private String safetyOfficer;
+    @Excel(name = "椋庨櫓绛夌骇") private String riskLevel;
+    @JsonFormat(pattern = "yyyy-MM-dd") @DateTimeFormat(pattern = "yyyy-MM-dd")
+    @Excel(name = "鏈�鏂版楠屾棩鏈�", width = 30, dateFormat = "yyyy-MM-dd") private LocalDate latestInspectionDate;
+    @JsonFormat(pattern = "yyyy-MM-dd") @DateTimeFormat(pattern = "yyyy-MM-dd")
+    @Excel(name = "鏈�鏂扮淮淇濇棩鏈�", width = 30, dateFormat = "yyyy-MM-dd") private LocalDate latestMaintenanceDate;
+    @Excel(name = "闅愭偅鐘舵��", readConverterExp = "0=鏃犻殣鎮�,1=寰呮暣鏀�,2=鏁存敼涓�,3=宸查棴鐜�") private Integer hazardStatus;
+    @Excel(name = "闅愭偅鎻忚堪") private String hazardDescription;
+    @JsonFormat(pattern = "yyyy-MM-dd") @DateTimeFormat(pattern = "yyyy-MM-dd")
+    @Excel(name = "鏁存敼鎴鏃ユ湡", width = 30, dateFormat = "yyyy-MM-dd") private LocalDate rectificationDeadline;
+    @Excel(name = "澶囨敞") private String remarks;
+    @TableField(fill = FieldFill.INSERT) private Long createUser;
+    @TableField(fill = FieldFill.INSERT) private LocalDateTime createTime;
+    @TableField(fill = FieldFill.UPDATE) private Long updateUser;
+    @TableField(fill = FieldFill.UPDATE) private LocalDateTime updateTime;
+    @TableField(fill = FieldFill.INSERT) private Long tenantId;
+    @TableField(fill = FieldFill.INSERT) private Long deptId;
+}
diff --git a/src/main/java/com/ruoyi/safe/specialequipment/pojo/SpecialEquipmentRecord.java b/src/main/java/com/ruoyi/safe/specialequipment/pojo/SpecialEquipmentRecord.java
new file mode 100644
index 0000000..78f4787
--- /dev/null
+++ b/src/main/java/com/ruoyi/safe/specialequipment/pojo/SpecialEquipmentRecord.java
@@ -0,0 +1,34 @@
+package com.ruoyi.safe.specialequipment.pojo;
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+import java.time.*;
+@Data
+@Schema(description = "鐗圭璁惧妫�楠岀淮淇濊褰�")
+@TableName("special_equipment_record")
+public class SpecialEquipmentRecord {
+    private static final long serialVersionUID = 1L;
+    @TableId(type = IdType.AUTO) private Long id;
+    private Long equipmentId;
+    @Excel(name = "璁板綍绫诲瀷", readConverterExp = "1=妫�楠�,2=缁翠繚") private Integer recordType;
+    @Excel(name = "璁板綍缂栧彿") private String recordNo;
+    @JsonFormat(pattern = "yyyy-MM-dd") @DateTimeFormat(pattern = "yyyy-MM-dd")
+    @Excel(name = "璁板綍鏃ユ湡", width = 30, dateFormat = "yyyy-MM-dd") private LocalDate recordDate;
+    @Excel(name = "鎵ц缁撴灉") private String executeResult;
+    @Excel(name = "闂鎻忚堪") private String problemDescription;
+    @Excel(name = "澶勭悊鎺柦") private String disposeMeasure;
+    private Long executorId;
+    @Excel(name = "鎵ц浜�") private String executorName;
+    @JsonFormat(pattern = "yyyy-MM-dd") @DateTimeFormat(pattern = "yyyy-MM-dd")
+    @Excel(name = "涓嬫鍒版湡鏃ユ湡", width = 30, dateFormat = "yyyy-MM-dd") private LocalDate nextDueDate;
+    @Excel(name = "闄勪欢璇存槑") private String attachmentRemark;
+    @TableField(fill = FieldFill.INSERT) private Long createUser;
+    @TableField(fill = FieldFill.INSERT) private LocalDateTime createTime;
+    @TableField(fill = FieldFill.UPDATE) private Long updateUser;
+    @TableField(fill = FieldFill.UPDATE) private LocalDateTime updateTime;
+    @TableField(fill = FieldFill.INSERT) private Long tenantId;
+    @TableField(fill = FieldFill.INSERT) private Long deptId;
+}
diff --git a/src/main/java/com/ruoyi/safe/specialequipment/pojo/SpecialEquipmentRectification.java b/src/main/java/com/ruoyi/safe/specialequipment/pojo/SpecialEquipmentRectification.java
new file mode 100644
index 0000000..e22e8cc
--- /dev/null
+++ b/src/main/java/com/ruoyi/safe/specialequipment/pojo/SpecialEquipmentRectification.java
@@ -0,0 +1,36 @@
+package com.ruoyi.safe.specialequipment.pojo;
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+import java.time.*;
+@Data
+@Schema(description = "鐗圭璁惧闅愭偅鏁存敼")
+@TableName("special_equipment_rectification")
+public class SpecialEquipmentRectification {
+    private static final long serialVersionUID = 1L;
+    @TableId(type = IdType.AUTO) private Long id;
+    private Long equipmentId;
+    @Excel(name = "闅愭偅鎻忚堪") private String hazardDescription;
+    @Excel(name = "椋庨櫓绛夌骇") private String riskLevel;
+    @JsonFormat(pattern = "yyyy-MM-dd") @DateTimeFormat(pattern = "yyyy-MM-dd")
+    @Excel(name = "鍙戠幇鏃ユ湡", width = 30, dateFormat = "yyyy-MM-dd") private LocalDate discoveredDate;
+    private Long responsibleUserId;
+    @Excel(name = "鏁存敼璐d换浜�") private String responsibleUserName;
+    @JsonFormat(pattern = "yyyy-MM-dd") @DateTimeFormat(pattern = "yyyy-MM-dd")
+    @Excel(name = "鏁存敼鏈熼檺", width = 30, dateFormat = "yyyy-MM-dd") private LocalDate rectificationDeadline;
+    @Excel(name = "鏁存敼鐘舵��", readConverterExp = "1=寰呮暣鏀�,2=鏁存敼涓�,3=寰呭鏍�,4=宸查棴鐜�") private Integer rectificationStatus;
+    @Excel(name = "鏁存敼鎺柦") private String rectificationMeasures;
+    @Excel(name = "鏁存敼缁撴灉") private String rectificationResult;
+    @JsonFormat(pattern = "yyyy-MM-dd") @DateTimeFormat(pattern = "yyyy-MM-dd")
+    @Excel(name = "闂幆鏃ユ湡", width = 30, dateFormat = "yyyy-MM-dd") private LocalDate closedDate;
+    @Excel(name = "澶囨敞") private String remarks;
+    @TableField(fill = FieldFill.INSERT) private Long createUser;
+    @TableField(fill = FieldFill.INSERT) private LocalDateTime createTime;
+    @TableField(fill = FieldFill.UPDATE) private Long updateUser;
+    @TableField(fill = FieldFill.UPDATE) private LocalDateTime updateTime;
+    @TableField(fill = FieldFill.INSERT) private Long tenantId;
+    @TableField(fill = FieldFill.INSERT) private Long deptId;
+}
diff --git a/src/main/java/com/ruoyi/safe/specialequipment/service/SpecialEquipmentLedgerService.java b/src/main/java/com/ruoyi/safe/specialequipment/service/SpecialEquipmentLedgerService.java
new file mode 100644
index 0000000..d04cf17
--- /dev/null
+++ b/src/main/java/com/ruoyi/safe/specialequipment/service/SpecialEquipmentLedgerService.java
@@ -0,0 +1,8 @@
+package com.ruoyi.safe.specialequipment.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.safe.specialequipment.pojo.SpecialEquipmentLedger;
+public interface SpecialEquipmentLedgerService extends IService<SpecialEquipmentLedger> {
+    IPage<SpecialEquipmentLedger> listPage(Page page, SpecialEquipmentLedger req);
+}
diff --git a/src/main/java/com/ruoyi/safe/specialequipment/service/SpecialEquipmentRecordService.java b/src/main/java/com/ruoyi/safe/specialequipment/service/SpecialEquipmentRecordService.java
new file mode 100644
index 0000000..357f36a
--- /dev/null
+++ b/src/main/java/com/ruoyi/safe/specialequipment/service/SpecialEquipmentRecordService.java
@@ -0,0 +1,8 @@
+package com.ruoyi.safe.specialequipment.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.safe.specialequipment.pojo.SpecialEquipmentRecord;
+public interface SpecialEquipmentRecordService extends IService<SpecialEquipmentRecord> {
+    IPage<SpecialEquipmentRecord> listPage(Page page, SpecialEquipmentRecord req);
+}
diff --git a/src/main/java/com/ruoyi/safe/specialequipment/service/SpecialEquipmentRectificationService.java b/src/main/java/com/ruoyi/safe/specialequipment/service/SpecialEquipmentRectificationService.java
new file mode 100644
index 0000000..00cf01d
--- /dev/null
+++ b/src/main/java/com/ruoyi/safe/specialequipment/service/SpecialEquipmentRectificationService.java
@@ -0,0 +1,8 @@
+package com.ruoyi.safe.specialequipment.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.safe.specialequipment.pojo.SpecialEquipmentRectification;
+public interface SpecialEquipmentRectificationService extends IService<SpecialEquipmentRectification> {
+    IPage<SpecialEquipmentRectification> listPage(Page page, SpecialEquipmentRectification req);
+}
diff --git a/src/main/java/com/ruoyi/safe/specialequipment/service/impl/SpecialEquipmentLedgerServiceImpl.java b/src/main/java/com/ruoyi/safe/specialequipment/service/impl/SpecialEquipmentLedgerServiceImpl.java
new file mode 100644
index 0000000..354e463
--- /dev/null
+++ b/src/main/java/com/ruoyi/safe/specialequipment/service/impl/SpecialEquipmentLedgerServiceImpl.java
@@ -0,0 +1,24 @@
+package com.ruoyi.safe.specialequipment.service.impl;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.safe.specialequipment.mapper.SpecialEquipmentLedgerMapper;
+import com.ruoyi.safe.specialequipment.pojo.SpecialEquipmentLedger;
+import com.ruoyi.safe.specialequipment.service.SpecialEquipmentLedgerService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import java.time.LocalDateTime;
+@Service
+@RequiredArgsConstructor
+public class SpecialEquipmentLedgerServiceImpl extends ServiceImpl<SpecialEquipmentLedgerMapper, SpecialEquipmentLedger> implements SpecialEquipmentLedgerService {
+    private final SpecialEquipmentLedgerMapper mapper;
+    public IPage<SpecialEquipmentLedger> listPage(Page page, SpecialEquipmentLedger req) { return mapper.listPage(page, req); }
+    public boolean save(SpecialEquipmentLedger entity) {
+        entity.setHazardStatus(entity.getHazardStatus() == null ? 0 : entity.getHazardStatus());
+        entity.setTenantId(SecurityUtils.getLoginUser().getTenantId());
+        entity.setCreateUser(SecurityUtils.getLoginUser().getUserId());
+        entity.setCreateTime(LocalDateTime.now());
+        return super.save(entity);
+    }
+}
diff --git a/src/main/java/com/ruoyi/safe/specialequipment/service/impl/SpecialEquipmentRecordServiceImpl.java b/src/main/java/com/ruoyi/safe/specialequipment/service/impl/SpecialEquipmentRecordServiceImpl.java
new file mode 100644
index 0000000..ade0335
--- /dev/null
+++ b/src/main/java/com/ruoyi/safe/specialequipment/service/impl/SpecialEquipmentRecordServiceImpl.java
@@ -0,0 +1,55 @@
+package com.ruoyi.safe.specialequipment.service.impl;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.safe.specialequipment.mapper.SpecialEquipmentLedgerMapper;
+import com.ruoyi.safe.specialequipment.mapper.SpecialEquipmentRecordMapper;
+import com.ruoyi.safe.specialequipment.pojo.SpecialEquipmentLedger;
+import com.ruoyi.safe.specialequipment.pojo.SpecialEquipmentRecord;
+import com.ruoyi.safe.specialequipment.service.SpecialEquipmentRecordService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import java.time.LocalDateTime;
+@Service
+@RequiredArgsConstructor
+public class SpecialEquipmentRecordServiceImpl extends ServiceImpl<SpecialEquipmentRecordMapper, SpecialEquipmentRecord> implements SpecialEquipmentRecordService {
+    private final SpecialEquipmentRecordMapper mapper;
+    private final SpecialEquipmentLedgerMapper ledgerMapper;
+
+    public IPage<SpecialEquipmentRecord> listPage(Page page, SpecialEquipmentRecord req) { return mapper.listPage(page, req); }
+
+    public boolean save(SpecialEquipmentRecord entity) {
+        entity.setTenantId(SecurityUtils.getLoginUser().getTenantId());
+        entity.setCreateUser(SecurityUtils.getLoginUser().getUserId());
+        entity.setCreateTime(LocalDateTime.now());
+        boolean saved = super.save(entity);
+        syncLedgerDate(entity);
+        return saved;
+    }
+
+    @Override
+    public boolean updateById(SpecialEquipmentRecord entity) {
+        boolean updated = super.updateById(entity);
+        syncLedgerDate(entity);
+        return updated;
+    }
+
+    private void syncLedgerDate(SpecialEquipmentRecord entity) {
+        if (entity == null || entity.getEquipmentId() == null || entity.getRecordType() == null) {
+            return;
+        }
+        SpecialEquipmentLedger ledger = ledgerMapper.selectById(entity.getEquipmentId());
+        if (ledger == null) {
+            return;
+        }
+        if (entity.getRecordType() == 1) {
+            ledger.setLatestInspectionDate(entity.getRecordDate());
+            ledger.setNextInspectionDate(entity.getNextDueDate());
+        } else if (entity.getRecordType() == 2) {
+            ledger.setLatestMaintenanceDate(entity.getRecordDate());
+            ledger.setNextMaintenanceDate(entity.getNextDueDate());
+        }
+        ledgerMapper.updateById(ledger);
+    }
+}
diff --git a/src/main/java/com/ruoyi/safe/specialequipment/service/impl/SpecialEquipmentRectificationServiceImpl.java b/src/main/java/com/ruoyi/safe/specialequipment/service/impl/SpecialEquipmentRectificationServiceImpl.java
new file mode 100644
index 0000000..0deae68
--- /dev/null
+++ b/src/main/java/com/ruoyi/safe/specialequipment/service/impl/SpecialEquipmentRectificationServiceImpl.java
@@ -0,0 +1,29 @@
+package com.ruoyi.safe.specialequipment.service.impl;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.safe.specialequipment.mapper.SpecialEquipmentRectificationMapper;
+import com.ruoyi.safe.specialequipment.pojo.SpecialEquipmentRectification;
+import com.ruoyi.safe.specialequipment.service.SpecialEquipmentRectificationService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import java.time.LocalDateTime;
+@Service
+@RequiredArgsConstructor
+public class SpecialEquipmentRectificationServiceImpl extends ServiceImpl<SpecialEquipmentRectificationMapper, SpecialEquipmentRectification> implements SpecialEquipmentRectificationService {
+    private final SpecialEquipmentRectificationMapper mapper;
+    public IPage<SpecialEquipmentRectification> listPage(Page page, SpecialEquipmentRectification req) { return mapper.listPage(page, req); }
+    public boolean save(SpecialEquipmentRectification entity) {
+        entity.setTenantId(SecurityUtils.getLoginUser().getTenantId());
+        entity.setCreateUser(SecurityUtils.getLoginUser().getUserId());
+        entity.setCreateTime(LocalDateTime.now());
+        entity.setRectificationStatus(entity.getRectificationStatus() == null ? 1 : entity.getRectificationStatus());
+        return super.save(entity);
+    }
+
+    @Override
+    public boolean updateById(SpecialEquipmentRectification entity) {
+        return super.updateById(entity);
+    }
+}
diff --git a/src/main/java/com/ruoyi/safe/specialequipment/task/SpecialEquipmentReminderTask.java b/src/main/java/com/ruoyi/safe/specialequipment/task/SpecialEquipmentReminderTask.java
new file mode 100644
index 0000000..8acb7d0
--- /dev/null
+++ b/src/main/java/com/ruoyi/safe/specialequipment/task/SpecialEquipmentReminderTask.java
@@ -0,0 +1,71 @@
+package com.ruoyi.safe.specialequipment.task;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.ruoyi.approve.pojo.NotificationManagement;
+import com.ruoyi.approve.service.NotificationManagementService;
+import com.ruoyi.safe.specialequipment.mapper.SpecialEquipmentLedgerMapper;
+import com.ruoyi.safe.specialequipment.pojo.SpecialEquipmentLedger;
+import lombok.RequiredArgsConstructor;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+import java.time.LocalDate;
+import java.time.temporal.ChronoUnit;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+@Component
+@RequiredArgsConstructor
+public class SpecialEquipmentReminderTask {
+    private final SpecialEquipmentLedgerMapper ledgerMapper;
+    private final NotificationManagementService notificationManagementService;
+    private static final int REMIND_DAYS = 30;
+
+    @Scheduled(cron = "0 0 8 * * ?")
+    public void remindExpire() {
+        LocalDate now = LocalDate.now();
+        LocalDate threshold = now.plusDays(REMIND_DAYS);
+        List<SpecialEquipmentLedger> list = ledgerMapper.selectList(Wrappers.<SpecialEquipmentLedger>lambdaQuery()
+                .and(wrapper -> wrapper
+                        .isNotNull(SpecialEquipmentLedger::getNextInspectionDate)
+                        .le(SpecialEquipmentLedger::getNextInspectionDate, threshold)
+                        .or()
+                        .isNotNull(SpecialEquipmentLedger::getNextMaintenanceDate)
+                        .le(SpecialEquipmentLedger::getNextMaintenanceDate, threshold)));
+        for (SpecialEquipmentLedger ledger : list) {
+            syncReminder(ledger, now, threshold, true);
+            syncReminder(ledger, now, threshold, false);
+        }
+    }
+
+    private void syncReminder(SpecialEquipmentLedger ledger, LocalDate now, LocalDate threshold, boolean inspection) {
+        LocalDate dueDate = inspection ? ledger.getNextInspectionDate() : ledger.getNextMaintenanceDate();
+        if (dueDate == null || dueDate.isAfter(threshold)) {
+            return;
+        }
+        long daysLeft = ChronoUnit.DAYS.between(now, dueDate);
+        String reminderType = inspection ? "妫�楠屽埌鏈熸彁閱�" : "缁翠繚鍒版湡鎻愰啋";
+        String title = ledger.getEquipmentName() + "-" + reminderType;
+        String content = String.format("璁惧銆�%s銆�(%s) %s锛�%s锛岃鍙婃椂瀹夋帓澶勭悊銆�",
+                ledger.getEquipmentName(),
+                Optional.ofNullable(ledger.getEquipmentNo()).orElse(""),
+                inspection ? "妫�楠屽嵆灏嗗埌鏈�" : "缁翠繚鍗冲皢鍒版湡",
+                daysLeft < 0 ? ("宸查�炬湡 " + Math.abs(daysLeft) + " 澶�") : ("璺濈鍒版湡杩樻湁 " + daysLeft + " 澶�"));
+        NotificationManagement notification = notificationManagementService.lambdaQuery()
+                .eq(NotificationManagement::getTitle, title)
+                .eq(NotificationManagement::getType, reminderType)
+                .oneOpt()
+                .orElseGet(NotificationManagement::new);
+        notification.setTitle(title);
+        notification.setType(reminderType);
+        notification.setPriority(daysLeft <= 7 ? "楂�" : "涓�");
+        notification.setStatus("1");
+        notification.setExpireDate(dueDate);
+        notification.setContent(content);
+        notification.setDepartments(new ArrayList<>());
+        notification.setSyncMethods(new ArrayList<>());
+        if (notification.getId() == null) {
+            notificationManagementService.save(notification);
+        } else {
+            notificationManagementService.updateById(notification);
+        }
+    }
+}
diff --git a/src/main/resources/mapper/safe/specialequipment/SpecialEquipmentLedgerMapper.xml b/src/main/resources/mapper/safe/specialequipment/SpecialEquipmentLedgerMapper.xml
new file mode 100644
index 0000000..4eab076
--- /dev/null
+++ b/src/main/resources/mapper/safe/specialequipment/SpecialEquipmentLedgerMapper.xml
@@ -0,0 +1,83 @@
+<?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.safe.specialequipment.mapper.SpecialEquipmentLedgerMapper">
+
+    <resultMap id="BaseResultMap" type="com.ruoyi.safe.specialequipment.pojo.SpecialEquipmentLedger">
+        <id column="id" property="id" />
+        <result column="equipment_no" property="equipmentNo" />
+        <result column="equipment_name" property="equipmentName" />
+        <result column="equipment_type" property="equipmentType" />
+        <result column="model_spec" property="modelSpec" />
+        <result column="manufacture_date" property="manufactureDate" />
+        <result column="install_location" property="installLocation" />
+        <result column="use_unit" property="useUnit" />
+        <result column="certificate_no" property="certificateNo" />
+        <result column="inspection_cycle_days" property="inspectionCycleDays" />
+        <result column="next_inspection_date" property="nextInspectionDate" />
+        <result column="maintenance_cycle_days" property="maintenanceCycleDays" />
+        <result column="next_maintenance_date" property="nextMaintenanceDate" />
+        <result column="alarm_days" property="alarmDays" />
+        <result column="manager_id" property="managerId" />
+        <result column="manager_name" property="managerName" />
+        <result column="safety_officer" property="safetyOfficer" />
+        <result column="risk_level" property="riskLevel" />
+        <result column="latest_inspection_date" property="latestInspectionDate" />
+        <result column="latest_maintenance_date" property="latestMaintenanceDate" />
+        <result column="hazard_status" property="hazardStatus" />
+        <result column="hazard_description" property="hazardDescription" />
+        <result column="rectification_deadline" property="rectificationDeadline" />
+        <result column="remarks" property="remarks" />
+        <result column="create_user" property="createUser" />
+        <result column="create_time" property="createTime" />
+        <result column="update_user" property="updateUser" />
+        <result column="update_time" property="updateTime" />
+        <result column="tenant_id" property="tenantId" />
+        <result column="dept_id" property="deptId" />
+    </resultMap>
+
+    <select id="listPage" resultMap="BaseResultMap">
+        select l.id,
+               l.equipment_no,
+               l.equipment_name,
+               l.equipment_type,
+               l.model_spec,
+               l.manufacture_date,
+               l.install_location,
+               l.use_unit,
+               l.certificate_no,
+               l.inspection_cycle_days,
+               l.next_inspection_date,
+               l.maintenance_cycle_days,
+               l.next_maintenance_date,
+               l.alarm_days,
+               l.manager_id,
+               COALESCE(u.nick_name, u.user_name) as manager_name,
+               l.safety_officer,
+               l.risk_level,
+               l.latest_inspection_date,
+               l.latest_maintenance_date,
+               l.hazard_status,
+               l.hazard_description,
+               l.rectification_deadline,
+               l.remarks,
+               l.create_user,
+               l.create_time,
+               l.update_user,
+               l.update_time,
+               l.tenant_id,
+               l.dept_id
+        from special_equipment_ledger l
+                 left join sys_user u on u.user_id = l.manager_id
+        where 1=1
+        <if test="req.equipmentName != null and req.equipmentName != ''">
+            and l.equipment_name like concat('%', #{req.equipmentName}, '%')
+        </if>
+        <if test="req.equipmentType != null and req.equipmentType != ''">
+            and l.equipment_type like concat('%', #{req.equipmentType}, '%')
+        </if>
+        <if test="req.hazardStatus != null">
+            and l.hazard_status = #{req.hazardStatus}
+        </if>
+    </select>
+
+</mapper>
diff --git a/src/main/resources/mapper/safe/specialequipment/SpecialEquipmentRecordMapper.xml b/src/main/resources/mapper/safe/specialequipment/SpecialEquipmentRecordMapper.xml
new file mode 100644
index 0000000..228981c
--- /dev/null
+++ b/src/main/resources/mapper/safe/specialequipment/SpecialEquipmentRecordMapper.xml
@@ -0,0 +1,41 @@
+<?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.safe.specialequipment.mapper.SpecialEquipmentRecordMapper">
+
+    <resultMap id="BaseResultMap" type="com.ruoyi.safe.specialequipment.pojo.SpecialEquipmentRecord">
+        <id column="id" property="id" />
+        <result column="equipment_id" property="equipmentId" />
+        <result column="record_type" property="recordType" />
+        <result column="record_no" property="recordNo" />
+        <result column="record_date" property="recordDate" />
+        <result column="execute_result" property="executeResult" />
+        <result column="problem_description" property="problemDescription" />
+        <result column="dispose_measure" property="disposeMeasure" />
+        <result column="executor_id" property="executorId" />
+        <result column="executor_name" property="executorName" />
+        <result column="next_due_date" property="nextDueDate" />
+        <result column="attachment_remark" property="attachmentRemark" />
+        <result column="create_user" property="createUser" />
+        <result column="create_time" property="createTime" />
+        <result column="update_user" property="updateUser" />
+        <result column="update_time" property="updateTime" />
+        <result column="tenant_id" property="tenantId" />
+        <result column="dept_id" property="deptId" />
+    </resultMap>
+
+    <select id="listPage" resultMap="BaseResultMap">
+        select *
+        from special_equipment_record
+        where 1=1
+        <if test="req.recordType != null">
+            and record_type = #{req.recordType}
+        </if>
+        <if test="req.recordNo != null and req.recordNo != ''">
+            and record_no like concat('%', #{req.recordNo}, '%')
+        </if>
+        <if test="req.equipmentId != null">
+            and equipment_id = #{req.equipmentId}
+        </if>
+    </select>
+
+</mapper>
diff --git a/src/main/resources/mapper/safe/specialequipment/SpecialEquipmentRectificationMapper.xml b/src/main/resources/mapper/safe/specialequipment/SpecialEquipmentRectificationMapper.xml
new file mode 100644
index 0000000..75039e2
--- /dev/null
+++ b/src/main/resources/mapper/safe/specialequipment/SpecialEquipmentRectificationMapper.xml
@@ -0,0 +1,42 @@
+<?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.safe.specialequipment.mapper.SpecialEquipmentRectificationMapper">
+
+    <resultMap id="BaseResultMap" type="com.ruoyi.safe.specialequipment.pojo.SpecialEquipmentRectification">
+        <id column="id" property="id" />
+        <result column="equipment_id" property="equipmentId" />
+        <result column="hazard_description" property="hazardDescription" />
+        <result column="risk_level" property="riskLevel" />
+        <result column="discovered_date" property="discoveredDate" />
+        <result column="responsible_user_id" property="responsibleUserId" />
+        <result column="responsible_user_name" property="responsibleUserName" />
+        <result column="rectification_deadline" property="rectificationDeadline" />
+        <result column="rectification_status" property="rectificationStatus" />
+        <result column="rectification_measures" property="rectificationMeasures" />
+        <result column="rectification_result" property="rectificationResult" />
+        <result column="closed_date" property="closedDate" />
+        <result column="remarks" property="remarks" />
+        <result column="create_user" property="createUser" />
+        <result column="create_time" property="createTime" />
+        <result column="update_user" property="updateUser" />
+        <result column="update_time" property="updateTime" />
+        <result column="tenant_id" property="tenantId" />
+        <result column="dept_id" property="deptId" />
+    </resultMap>
+
+    <select id="listPage" resultMap="BaseResultMap">
+        select *
+        from special_equipment_rectification
+        where 1=1
+        <if test="req.rectificationStatus != null">
+            and rectification_status = #{req.rectificationStatus}
+        </if>
+        <if test="req.hazardDescription != null and req.hazardDescription != ''">
+            and hazard_description like concat('%', #{req.hazardDescription}, '%')
+        </if>
+        <if test="req.equipmentId != null">
+            and equipment_id = #{req.equipmentId}
+        </if>
+    </select>
+
+</mapper>

--
Gitblit v1.9.3