From a217dbfc7378ff9cf5b6d3ca8b229a2b9d932e51 Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期二, 02 六月 2026 11:52:19 +0800
Subject: [PATCH] feat(device): 添加设备保养验收功能和年度定时任务支持

---
 src/main/java/com/ruoyi/quality/service/impl/QualityInspectServiceImpl.java      |   22 
 src/main/resources/mapper/device/DeviceMaintenanceMapper.xml                     |    6 
 src/main/java/com/ruoyi/device/dto/DeviceMaintenanceDto.java                     |    2 
 src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskScheduleUtils.java |   26 
 src/main/java/com/ruoyi/device/dto/DeviceRepairDto.java                          |    3 
 pom.xml                                                                          |    7 
 src/main/java/com/ruoyi/device/controller/MaintenanceTaskController.java         |    7 
 docs/maintenance_task_api.md                                                     |  317 +++++++++
 src/main/resources/static/伟龙模版.doc                                               |    0 
 src/main/java/com/ruoyi/device/service/MaintenanceTaskService.java               |    2 
 doc/20260602_device_maintenance_acceptance.sql                                   |    9 
 src/main/java/com/ruoyi/device/service/impl/DeviceMaintenanceServiceImpl.java    |   63 +
 classpath.txt                                                                    |    1 
 src/main/resources/static/百事模版.doc                                               |    0 
 doc/前端联调文档-设备保养验收人功能.md                                                          |  232 +++++++
 src/main/java/com/ruoyi/device/controller/DeviceMaintenanceController.java       |   10 
 src/main/java/com/ruoyi/quality/utils/QualityInspectTemplateExportHelper.java    |  489 ++++++++++++++
 src/main/java/com/ruoyi/device/service/IDeviceMaintenanceService.java            |    4 
 src/main/resources/static/达利模版.doc                                               |    0 
 doc/前端联调文档-设备报修验收审批功能.md                                                         |  361 ++++++++++
 src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskServiceImpl.java   |   11 
 src/main/java/com/ruoyi/quality/service/IQualityInspectService.java              |   11 
 src/main/java/com/ruoyi/device/pojo/MaintenanceTask.java                         |    3 
 src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskScheduler.java        |   18 
 src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskServiceImpl.java      |   43 +
 src/main/java/com/ruoyi/quality/controller/QualityInspectController.java         |   31 
 doc/前端联调文档-过程检验模板导出功能.md                                                         |  275 ++++++++
 src/main/java/com/ruoyi/device/pojo/DeviceMaintenance.java                       |   13 
 28 files changed, 1,958 insertions(+), 8 deletions(-)

diff --git a/classpath.txt b/classpath.txt
new file mode 100644
index 0000000..cd566cb
--- /dev/null
+++ b/classpath.txt
@@ -0,0 +1 @@
+D:\Maven3.6.3\myRepository\com\github\xiaoymin\knife4j-openapi3-jakarta-spring-boot-starter\4.5.0\knife4j-openapi3-jakarta-spring-boot-starter-4.5.0.jar;D:\Maven3.6.3\myRepository\com\github\xiaoymin\knife4j-core\4.5.0\knife4j-core-4.5.0.jar;D:\Maven3.6.3\myRepository\com\github\xiaoymin\knife4j-openapi3-ui\4.5.0\knife4j-openapi3-ui-4.5.0.jar;D:\Maven3.6.3\myRepository\org\springdoc\springdoc-openapi-starter-webmvc-ui\2.8.17\springdoc-openapi-starter-webmvc-ui-2.8.17.jar;D:\Maven3.6.3\myRepository\org\springdoc\springdoc-openapi-starter-webmvc-api\2.8.17\springdoc-openapi-starter-webmvc-api-2.8.17.jar;D:\Maven3.6.3\myRepository\org\springdoc\springdoc-openapi-starter-common\2.8.17\springdoc-openapi-starter-common-2.8.17.jar;D:\Maven3.6.3\myRepository\io\swagger\core\v3\swagger-core-jakarta\2.2.47\swagger-core-jakarta-2.2.47.jar;D:\Maven3.6.3\myRepository\io\swagger\core\v3\swagger-annotations-jakarta\2.2.47\swagger-annotations-jakarta-2.2.47.jar;D:\Maven3.6.3\myRepository\io\swagger\core\v3\swagger-models-jakarta\2.2.47\swagger-models-jakarta-2.2.47.jar;D:\Maven3.6.3\myRepository\com\fasterxml\jackson\dataformat\jackson-dataformat-yaml\2.18.3\jackson-dataformat-yaml-2.18.3.jar;D:\Maven3.6.3\myRepository\org\webjars\swagger-ui\5.32.2\swagger-ui-5.32.2.jar;D:\Maven3.6.3\myRepository\org\webjars\webjars-locator-lite\1.1.3\webjars-locator-lite-1.1.3.jar;D:\Maven3.6.3\myRepository\org\jspecify\jspecify\1.0.0\jspecify-1.0.0.jar;D:\Maven3.6.3\myRepository\org\springframework\boot\spring-boot-starter\3.5.13\spring-boot-starter-3.5.13.jar;D:\Maven3.6.3\myRepository\org\springframework\boot\spring-boot\3.5.13\spring-boot-3.5.13.jar;D:\Maven3.6.3\myRepository\org\springframework\boot\spring-boot-autoconfigure\3.5.13\spring-boot-autoconfigure-3.5.13.jar;D:\Maven3.6.3\myRepository\org\springframework\boot\spring-boot-starter-logging\3.5.13\spring-boot-starter-logging-3.5.13.jar;D:\Maven3.6.3\myRepository\org\apache\logging\log4j\log4j-to-slf4j\2.24.3\log4j-to-slf4j-2.24.3.jar;D:\Maven3.6.3\myRepository\org\slf4j\jul-to-slf4j\2.0.17\jul-to-slf4j-2.0.17.jar;D:\Maven3.6.3\myRepository\jakarta\annotation\jakarta.annotation-api\2.1.1\jakarta.annotation-api-2.1.1.jar;D:\Maven3.6.3\myRepository\org\springframework\spring-core\6.2.17\spring-core-6.2.17.jar;D:\Maven3.6.3\myRepository\org\springframework\spring-jcl\6.2.17\spring-jcl-6.2.17.jar;D:\Maven3.6.3\myRepository\org\yaml\snakeyaml\2.4\snakeyaml-2.4.jar;D:\Maven3.6.3\myRepository\org\springframework\boot\spring-boot-starter-aop\3.5.13\spring-boot-starter-aop-3.5.13.jar;D:\Maven3.6.3\myRepository\org\springframework\spring-aop\6.2.17\spring-aop-6.2.17.jar;D:\Maven3.6.3\myRepository\org\aspectj\aspectjweaver\1.9.25.1\aspectjweaver-1.9.25.1.jar;D:\Maven3.6.3\myRepository\org\springframework\boot\spring-boot-starter-web\3.5.13\spring-boot-starter-web-3.5.13.jar;D:\Maven3.6.3\myRepository\org\springframework\boot\spring-boot-starter-json\3.5.13\spring-boot-starter-json-3.5.13.jar;D:\Maven3.6.3\myRepository\com\fasterxml\jackson\datatype\jackson-datatype-jdk8\2.18.3\jackson-datatype-jdk8-2.18.3.jar;D:\Maven3.6.3\myRepository\com\fasterxml\jackson\module\jackson-module-parameter-names\2.18.3\jackson-module-parameter-names-2.18.3.jar;D:\Maven3.6.3\myRepository\org\springframework\boot\spring-boot-starter-tomcat\3.5.13\spring-boot-starter-tomcat-3.5.13.jar;D:\Maven3.6.3\myRepository\org\apache\tomcat\embed\tomcat-embed-core\10.1.53\tomcat-embed-core-10.1.53.jar;D:\Maven3.6.3\myRepository\org\apache\tomcat\embed\tomcat-embed-websocket\10.1.53\tomcat-embed-websocket-10.1.53.jar;D:\Maven3.6.3\myRepository\org\springframework\spring-web\6.2.17\spring-web-6.2.17.jar;D:\Maven3.6.3\myRepository\io\micrometer\micrometer-observation\1.15.10\micrometer-observation-1.15.10.jar;D:\Maven3.6.3\myRepository\io\micrometer\micrometer-commons\1.15.10\micrometer-commons-1.15.10.jar;D:\Maven3.6.3\myRepository\org\springframework\spring-webmvc\6.2.17\spring-webmvc-6.2.17.jar;D:\Maven3.6.3\myRepository\org\springframework\spring-expression\6.2.17\spring-expression-6.2.17.jar;D:\Maven3.6.3\myRepository\org\springframework\boot\spring-boot-devtools\3.5.13\spring-boot-devtools-3.5.13.jar;D:\Maven3.6.3\myRepository\org\springframework\boot\spring-boot-starter-security\3.5.13\spring-boot-starter-security-3.5.13.jar;D:\Maven3.6.3\myRepository\org\springframework\security\spring-security-config\6.5.9\spring-security-config-6.5.9.jar;D:\Maven3.6.3\myRepository\org\springframework\security\spring-security-core\6.5.9\spring-security-core-6.5.9.jar;D:\Maven3.6.3\myRepository\org\springframework\security\spring-security-crypto\6.5.9\spring-security-crypto-6.5.9.jar;D:\Maven3.6.3\myRepository\org\springframework\security\spring-security-web\6.5.9\spring-security-web-6.5.9.jar;D:\Maven3.6.3\myRepository\org\springframework\boot\spring-boot-starter-data-redis\3.5.13\spring-boot-starter-data-redis-3.5.13.jar;D:\Maven3.6.3\myRepository\io\lettuce\lettuce-core\6.6.0.RELEASE\lettuce-core-6.6.0.RELEASE.jar;D:\Maven3.6.3\myRepository\redis\clients\authentication\redis-authx-core\0.1.1-beta2\redis-authx-core-0.1.1-beta2.jar;D:\Maven3.6.3\myRepository\io\netty\netty-common\4.1.119.Final\netty-common-4.1.119.Final.jar;D:\Maven3.6.3\myRepository\io\netty\netty-handler\4.1.119.Final\netty-handler-4.1.119.Final.jar;D:\Maven3.6.3\myRepository\io\netty\netty-resolver\4.1.119.Final\netty-resolver-4.1.119.Final.jar;D:\Maven3.6.3\myRepository\io\netty\netty-buffer\4.1.119.Final\netty-buffer-4.1.119.Final.jar;D:\Maven3.6.3\myRepository\io\netty\netty-transport-native-unix-common\4.1.119.Final\netty-transport-native-unix-common-4.1.119.Final.jar;D:\Maven3.6.3\myRepository\io\netty\netty-codec\4.1.119.Final\netty-codec-4.1.119.Final.jar;D:\Maven3.6.3\myRepository\io\netty\netty-transport\4.1.119.Final\netty-transport-4.1.119.Final.jar;D:\Maven3.6.3\myRepository\org\springframework\data\spring-data-redis\3.5.10\spring-data-redis-3.5.10.jar;D:\Maven3.6.3\myRepository\org\springframework\data\spring-data-keyvalue\3.5.10\spring-data-keyvalue-3.5.10.jar;D:\Maven3.6.3\myRepository\org\springframework\spring-tx\6.2.17\spring-tx-6.2.17.jar;D:\Maven3.6.3\myRepository\org\springframework\spring-oxm\6.2.17\spring-oxm-6.2.17.jar;D:\Maven3.6.3\myRepository\org\springframework\boot\spring-boot-starter-data-mongodb\3.5.13\spring-boot-starter-data-mongodb-3.5.13.jar;D:\Maven3.6.3\myRepository\org\mongodb\mongodb-driver-sync\5.5.2\mongodb-driver-sync-5.5.2.jar;D:\Maven3.6.3\myRepository\org\mongodb\bson\5.5.2\bson-5.5.2.jar;D:\Maven3.6.3\myRepository\org\mongodb\mongodb-driver-core\5.5.2\mongodb-driver-core-5.5.2.jar;D:\Maven3.6.3\myRepository\org\springframework\data\spring-data-mongodb\4.5.10\spring-data-mongodb-4.5.10.jar;D:\Maven3.6.3\myRepository\org\springframework\data\spring-data-commons\3.5.10\spring-data-commons-3.5.10.jar;D:\Maven3.6.3\myRepository\org\apache\commons\commons-pool2\2.12.1\commons-pool2-2.12.1.jar;D:\Maven3.6.3\myRepository\dev\langchain4j\langchain4j-spring-boot-starter\1.0.0-beta3\langchain4j-spring-boot-starter-1.0.0-beta3.jar;D:\Maven3.6.3\myRepository\dev\langchain4j\langchain4j\1.0.0-beta3\langchain4j-1.0.0-beta3.jar;D:\Maven3.6.3\myRepository\org\apache\opennlp\opennlp-tools\1.9.4\opennlp-tools-1.9.4.jar;D:\Maven3.6.3\myRepository\dev\langchain4j\langchain4j-pinecone\1.0.0-beta3\langchain4j-pinecone-1.0.0-beta3.jar;D:\Maven3.6.3\myRepository\dev\langchain4j\langchain4j-core\1.0.0-beta3\langchain4j-core-1.0.0-beta3.jar;D:\Maven3.6.3\myRepository\io\pinecone\pinecone-client\3.1.0\pinecone-client-3.1.0.jar;D:\Maven3.6.3\myRepository\io\grpc\grpc-protobuf\1.60.2\grpc-protobuf-1.60.2.jar;D:\Maven3.6.3\myRepository\io\grpc\grpc-api\1.60.2\grpc-api-1.60.2.jar;D:\Maven3.6.3\myRepository\io\grpc\grpc-protobuf-lite\1.60.2\grpc-protobuf-lite-1.60.2.jar;D:\Maven3.6.3\myRepository\io\grpc\grpc-stub\1.60.2\grpc-stub-1.60.2.jar;D:\Maven3.6.3\myRepository\io\grpc\grpc-netty\1.60.2\grpc-netty-1.60.2.jar;D:\Maven3.6.3\myRepository\io\grpc\grpc-core\1.60.2\grpc-core-1.60.2.jar;D:\Maven3.6.3\myRepository\io\netty\netty-codec-http2\4.1.119.Final\netty-codec-http2-4.1.119.Final.jar;D:\Maven3.6.3\myRepository\io\netty\netty-codec-http\4.1.119.Final\netty-codec-http-4.1.119.Final.jar;D:\Maven3.6.3\myRepository\com\google\api\grpc\proto-google-common-protos\2.14.3\proto-google-common-protos-2.14.3.jar;D:\Maven3.6.3\myRepository\com\squareup\okhttp3\logging-interceptor\4.12.0\logging-interceptor-4.12.0.jar;D:\Maven3.6.3\myRepository\com\google\protobuf\protobuf-java\3.25.2\protobuf-java-3.25.2.jar;D:\Maven3.6.3\myRepository\dev\langchain4j\langchain4j-open-ai-spring-boot-starter\1.0.0-beta3\langchain4j-open-ai-spring-boot-starter-1.0.0-beta3.jar;D:\Maven3.6.3\myRepository\dev\langchain4j\langchain4j-open-ai\1.0.0-beta3\langchain4j-open-ai-1.0.0-beta3.jar;D:\Maven3.6.3\myRepository\com\knuddels\jtokkit\1.1.0\jtokkit-1.1.0.jar;D:\Maven3.6.3\myRepository\dev\langchain4j\langchain4j-http-client-spring-restclient\1.0.0-beta3\langchain4j-http-client-spring-restclient-1.0.0-beta3.jar;D:\Maven3.6.3\myRepository\dev\langchain4j\langchain4j-http-client\1.0.0-beta3\langchain4j-http-client-1.0.0-beta3.jar;D:\Maven3.6.3\myRepository\dev\langchain4j\langchain4j-reactor\1.0.0-beta3\langchain4j-reactor-1.0.0-beta3.jar;D:\Maven3.6.3\myRepository\io\projectreactor\reactor-core\3.7.3\reactor-core-3.7.3.jar;D:\Maven3.6.3\myRepository\org\reactivestreams\reactive-streams\1.0.4\reactive-streams-1.0.4.jar;D:\Maven3.6.3\myRepository\dev\langchain4j\langchain4j-ollama-spring-boot-starter\1.0.0-beta3\langchain4j-ollama-spring-boot-starter-1.0.0-beta3.jar;D:\Maven3.6.3\myRepository\dev\langchain4j\langchain4j-ollama\1.0.0-beta3\langchain4j-ollama-1.0.0-beta3.jar;D:\Maven3.6.3\myRepository\dev\langchain4j\langchain4j-community-dashscope-spring-boot-starter\1.0.0-beta3\langchain4j-community-dashscope-spring-boot-starter-1.0.0-beta3.jar;D:\Maven3.6.3\myRepository\dev\langchain4j\langchain4j-community-dashscope\1.0.0-beta3\langchain4j-community-dashscope-1.0.0-beta3.jar;D:\Maven3.6.3\myRepository\com\alibaba\dashscope-sdk-java\2.18.5\dashscope-sdk-java-2.18.5.jar;D:\Maven3.6.3\myRepository\io\reactivex\rxjava2\rxjava\2.2.21\rxjava-2.2.21.jar;D:\Maven3.6.3\myRepository\com\github\victools\jsonschema-generator\4.31.1\jsonschema-generator-4.31.1.jar;D:\Maven3.6.3\myRepository\ch\qos\logback\logback-classic\1.5.32\logback-classic-1.5.32.jar;D:\Maven3.6.3\myRepository\ch\qos\logback\logback-core\1.5.32\logback-core-1.5.32.jar;D:\Maven3.6.3\myRepository\dev\langchain4j\langchain4j-mcp\1.0.0-beta3\langchain4j-mcp-1.0.0-beta3.jar;D:\Maven3.6.3\myRepository\com\fasterxml\jackson\core\jackson-databind\2.18.3\jackson-databind-2.18.3.jar;D:\Maven3.6.3\myRepository\com\squareup\okhttp3\okhttp-sse\4.12.0\okhttp-sse-4.12.0.jar;D:\Maven3.6.3\myRepository\org\jetbrains\kotlin\kotlin-stdlib-jdk8\1.9.25\kotlin-stdlib-jdk8-1.9.25.jar;D:\Maven3.6.3\myRepository\org\jetbrains\kotlin\kotlin-stdlib-jdk7\1.9.25\kotlin-stdlib-jdk7-1.9.25.jar;D:\Maven3.6.3\myRepository\org\freemarker\freemarker\2.3.33\freemarker-2.3.33.jar;D:\Maven3.6.3\myRepository\com\github\pagehelper\pagehelper-spring-boot-starter\2.1.1\pagehelper-spring-boot-starter-2.1.1.jar;D:\Maven3.6.3\myRepository\org\mybatis\spring\boot\mybatis-spring-boot-starter\2.3.2\mybatis-spring-boot-starter-2.3.2.jar;D:\Maven3.6.3\myRepository\org\mybatis\spring\boot\mybatis-spring-boot-autoconfigure\2.3.2\mybatis-spring-boot-autoconfigure-2.3.2.jar;D:\Maven3.6.3\myRepository\com\github\pagehelper\pagehelper-spring-boot-autoconfigure\2.1.1\pagehelper-spring-boot-autoconfigure-2.1.1.jar;D:\Maven3.6.3\myRepository\com\github\pagehelper\pagehelper\6.1.1\pagehelper-6.1.1.jar;D:\Maven3.6.3\myRepository\com\alibaba\druid-spring-boot-3-starter\1.2.23\druid-spring-boot-3-starter-1.2.23.jar;D:\Maven3.6.3\myRepository\com\alibaba\druid\1.2.23\druid-1.2.23.jar;D:\Maven3.6.3\myRepository\org\slf4j\slf4j-api\2.0.17\slf4j-api-2.0.17.jar;D:\Maven3.6.3\myRepository\org\mybatis\mybatis\3.5.16\mybatis-3.5.16.jar;D:\Maven3.6.3\myRepository\com\baomidou\mybatis-plus-spring-boot3-starter\3.5.16\mybatis-plus-spring-boot3-starter-3.5.16.jar;D:\Maven3.6.3\myRepository\com\baomidou\mybatis-plus\3.5.16\mybatis-plus-3.5.16.jar;D:\Maven3.6.3\myRepository\com\baomidou\mybatis-plus-core\3.5.16\mybatis-plus-core-3.5.16.jar;D:\Maven3.6.3\myRepository\com\baomidou\mybatis-plus-annotation\3.5.16\mybatis-plus-annotation-3.5.16.jar;D:\Maven3.6.3\myRepository\com\baomidou\mybatis-plus-spring\3.5.16\mybatis-plus-spring-3.5.16.jar;D:\Maven3.6.3\myRepository\org\mybatis\mybatis-spring\3.0.5\mybatis-spring-3.0.5.jar;D:\Maven3.6.3\myRepository\com\baomidou\mybatis-plus-spring-boot-autoconfigure\3.5.16\mybatis-plus-spring-boot-autoconfigure-3.5.16.jar;D:\Maven3.6.3\myRepository\org\springframework\boot\spring-boot-starter-jdbc\3.5.13\spring-boot-starter-jdbc-3.5.13.jar;D:\Maven3.6.3\myRepository\com\zaxxer\HikariCP\6.3.3\HikariCP-6.3.3.jar;D:\Maven3.6.3\myRepository\org\springframework\spring-jdbc\6.2.17\spring-jdbc-6.2.17.jar;D:\Maven3.6.3\myRepository\com\baomidou\mybatis-plus-jsqlparser\3.5.16\mybatis-plus-jsqlparser-3.5.16.jar;D:\Maven3.6.3\myRepository\com\baomidou\mybatis-plus-jsqlparser-common\3.5.16\mybatis-plus-jsqlparser-common-3.5.16.jar;D:\Maven3.6.3\myRepository\com\baomidou\mybatis-plus-extension\3.5.16\mybatis-plus-extension-3.5.16.jar;D:\Maven3.6.3\myRepository\com\baomidou\mybatis-plus-generator\3.5.16\mybatis-plus-generator-3.5.16.jar;D:\Maven3.6.3\myRepository\com\github\jsqlparser\jsqlparser\4.9\jsqlparser-4.9.jar;D:\Maven3.6.3\myRepository\org\springframework\boot\spring-boot-starter-validation\3.5.13\spring-boot-starter-validation-3.5.13.jar;D:\Maven3.6.3\myRepository\org\apache\tomcat\embed\tomcat-embed-el\10.1.53\tomcat-embed-el-10.1.53.jar;D:\Maven3.6.3\myRepository\org\hibernate\validator\hibernate-validator\8.0.3.Final\hibernate-validator-8.0.3.Final.jar;D:\Maven3.6.3\myRepository\jakarta\validation\jakarta.validation-api\3.0.2\jakarta.validation-api-3.0.2.jar;D:\Maven3.6.3\myRepository\org\jboss\logging\jboss-logging\3.6.3.Final\jboss-logging-3.6.3.Final.jar;D:\Maven3.6.3\myRepository\com\fasterxml\classmate\1.7.3\classmate-1.7.3.jar;D:\Maven3.6.3\myRepository\org\apache\commons\commons-lang3\3.17.0\commons-lang3-3.17.0.jar;D:\Maven3.6.3\myRepository\commons-io\commons-io\2.13.0\commons-io-2.13.0.jar;D:\Maven3.6.3\myRepository\eu\bitwalker\UserAgentUtils\1.21\UserAgentUtils-1.21.jar;D:\Maven3.6.3\myRepository\com\alibaba\fastjson2\fastjson2\2.0.53\fastjson2-2.0.53.jar;D:\Maven3.6.3\myRepository\org\springframework\spring-context-support\6.2.17\spring-context-support-6.2.17.jar;D:\Maven3.6.3\myRepository\org\springframework\spring-beans\6.2.17\spring-beans-6.2.17.jar;D:\Maven3.6.3\myRepository\org\springframework\spring-context\6.2.17\spring-context-6.2.17.jar;D:\Maven3.6.3\myRepository\io\jsonwebtoken\jjwt-api\0.13.0\jjwt-api-0.13.0.jar;D:\Maven3.6.3\myRepository\jakarta\xml\bind\jakarta.xml.bind-api\4.0.4\jakarta.xml.bind-api-4.0.4.jar;D:\Maven3.6.3\myRepository\jakarta\activation\jakarta.activation-api\2.1.4\jakarta.activation-api-2.1.4.jar;D:\Maven3.6.3\myRepository\io\swagger\swagger-annotations\1.6.15\swagger-annotations-1.6.15.jar;D:\Maven3.6.3\myRepository\com\github\oshi\oshi-core\6.6.5\oshi-core-6.6.5.jar;D:\Maven3.6.3\myRepository\net\java\dev\jna\jna\5.15.0\jna-5.15.0.jar;D:\Maven3.6.3\myRepository\net\java\dev\jna\jna-platform\5.15.0\jna-platform-5.15.0.jar;D:\Maven3.6.3\myRepository\org\apache\poi\poi-ooxml\5.2.3\poi-ooxml-5.2.3.jar;D:\Maven3.6.3\myRepository\org\apache\poi\poi\5.2.3\poi-5.2.3.jar;D:\Maven3.6.3\myRepository\commons-codec\commons-codec\1.18.0\commons-codec-1.18.0.jar;D:\Maven3.6.3\myRepository\org\apache\commons\commons-math3\3.6.1\commons-math3-3.6.1.jar;D:\Maven3.6.3\myRepository\com\zaxxer\SparseBitSet\1.2\SparseBitSet-1.2.jar;D:\Maven3.6.3\myRepository\org\apache\poi\poi-ooxml-lite\5.2.3\poi-ooxml-lite-5.2.3.jar;D:\Maven3.6.3\myRepository\org\apache\xmlbeans\xmlbeans\5.1.1\xmlbeans-5.1.1.jar;D:\Maven3.6.3\myRepository\org\apache\commons\commons-compress\1.21\commons-compress-1.21.jar;D:\Maven3.6.3\myRepository\com\github\virtuald\curvesapi\1.07\curvesapi-1.07.jar;D:\Maven3.6.3\myRepository\org\apache\logging\log4j\log4j-api\2.24.3\log4j-api-2.24.3.jar;D:\Maven3.6.3\myRepository\org\apache\commons\commons-collections4\4.4\commons-collections4-4.4.jar;D:\Maven3.6.3\myRepository\org\apache\velocity\velocity-engine-core\2.3\velocity-engine-core-2.3.jar;D:\Maven3.6.3\myRepository\org\quartz-scheduler\quartz\2.5.2\quartz-2.5.2.jar;D:\Maven3.6.3\myRepository\pro\fessional\kaptcha\2.3.3\kaptcha-2.3.3.jar;D:\Maven3.6.3\myRepository\com\jhlabs\filters\2.0.235-1\filters-2.0.235-1.jar;D:\Maven3.6.3\myRepository\org\projectlombok\lombok\1.18.44\lombok-1.18.44.jar;D:\Maven3.6.3\myRepository\io\minio\minio\8.4.3\minio-8.4.3.jar;D:\Maven3.6.3\myRepository\com\carrotsearch\thirdparty\simple-xml-safe\2.7.1\simple-xml-safe-2.7.1.jar;D:\Maven3.6.3\myRepository\com\google\guava\guava\30.1.1-jre\guava-30.1.1-jre.jar;D:\Maven3.6.3\myRepository\com\google\guava\failureaccess\1.0.1\failureaccess-1.0.1.jar;D:\Maven3.6.3\myRepository\com\google\guava\listenablefuture\9999.0-empty-to-avoid-conflict-with-guava\listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar;D:\Maven3.6.3\myRepository\com\google\code\findbugs\jsr305\3.0.2\jsr305-3.0.2.jar;D:\Maven3.6.3\myRepository\org\checkerframework\checker-qual\3.8.0\checker-qual-3.8.0.jar;D:\Maven3.6.3\myRepository\com\google\errorprone\error_prone_annotations\2.5.1\error_prone_annotations-2.5.1.jar;D:\Maven3.6.3\myRepository\com\google\j2objc\j2objc-annotations\1.3\j2objc-annotations-1.3.jar;D:\Maven3.6.3\myRepository\com\fasterxml\jackson\core\jackson-annotations\2.18.3\jackson-annotations-2.18.3.jar;D:\Maven3.6.3\myRepository\com\fasterxml\jackson\core\jackson-core\2.18.3\jackson-core-2.18.3.jar;D:\Maven3.6.3\myRepository\org\bouncycastle\bcprov-jdk15on\1.69\bcprov-jdk15on-1.69.jar;D:\Maven3.6.3\myRepository\org\xerial\snappy\snappy-java\1.1.8.4\snappy-java-1.1.8.4.jar;D:\Maven3.6.3\myRepository\com\squareup\okhttp3\okhttp\4.9.0\okhttp-4.9.0.jar;D:\Maven3.6.3\myRepository\com\squareup\okio\okio\2.8.0\okio-2.8.0.jar;D:\Maven3.6.3\myRepository\org\jetbrains\kotlin\kotlin-stdlib-common\1.9.25\kotlin-stdlib-common-1.9.25.jar;D:\Maven3.6.3\myRepository\org\jetbrains\kotlin\kotlin-stdlib\1.9.25\kotlin-stdlib-1.9.25.jar;D:\Maven3.6.3\myRepository\org\jetbrains\annotations\13.0\annotations-13.0.jar;D:\Maven3.6.3\myRepository\com\deepoove\poi-tl\1.12.2\poi-tl-1.12.2.jar;D:\Maven3.6.3\myRepository\org\apache\xmlgraphics\batik-transcoder\1.17\batik-transcoder-1.17.jar;D:\Maven3.6.3\myRepository\org\apache\xmlgraphics\batik-anim\1.17\batik-anim-1.17.jar;D:\Maven3.6.3\myRepository\org\apache\xmlgraphics\batik-css\1.17\batik-css-1.17.jar;D:\Maven3.6.3\myRepository\org\apache\xmlgraphics\batik-ext\1.17\batik-ext-1.17.jar;D:\Maven3.6.3\myRepository\org\apache\xmlgraphics\batik-parser\1.17\batik-parser-1.17.jar;D:\Maven3.6.3\myRepository\org\apache\xmlgraphics\batik-svg-dom\1.17\batik-svg-dom-1.17.jar;D:\Maven3.6.3\myRepository\org\apache\xmlgraphics\batik-awt-util\1.17\batik-awt-util-1.17.jar;D:\Maven3.6.3\myRepository\org\apache\xmlgraphics\xmlgraphics-commons\2.9\xmlgraphics-commons-2.9.jar;D:\Maven3.6.3\myRepository\org\apache\xmlgraphics\batik-bridge\1.17\batik-bridge-1.17.jar;D:\Maven3.6.3\myRepository\org\apache\xmlgraphics\batik-script\1.17\batik-script-1.17.jar;D:\Maven3.6.3\myRepository\org\apache\xmlgraphics\batik-dom\1.17\batik-dom-1.17.jar;D:\Maven3.6.3\myRepository\xml-apis\xml-apis\1.4.01\xml-apis-1.4.01.jar;D:\Maven3.6.3\myRepository\org\apache\xmlgraphics\batik-gvt\1.17\batik-gvt-1.17.jar;D:\Maven3.6.3\myRepository\org\apache\xmlgraphics\batik-shared-resources\1.17\batik-shared-resources-1.17.jar;D:\Maven3.6.3\myRepository\org\apache\xmlgraphics\batik-svggen\1.17\batik-svggen-1.17.jar;D:\Maven3.6.3\myRepository\org\apache\xmlgraphics\batik-util\1.17\batik-util-1.17.jar;D:\Maven3.6.3\myRepository\org\apache\xmlgraphics\batik-constants\1.17\batik-constants-1.17.jar;D:\Maven3.6.3\myRepository\org\apache\xmlgraphics\batik-i18n\1.17\batik-i18n-1.17.jar;D:\Maven3.6.3\myRepository\org\apache\xmlgraphics\batik-xml\1.17\batik-xml-1.17.jar;D:\Maven3.6.3\myRepository\xml-apis\xml-apis-ext\1.3.04\xml-apis-ext-1.3.04.jar;D:\Maven3.6.3\myRepository\org\apache\xmlgraphics\batik-codec\1.17\batik-codec-1.17.jar;D:\Maven3.6.3\myRepository\com\alibaba\easyexcel\4.0.3\easyexcel-4.0.3.jar;D:\Maven3.6.3\myRepository\com\alibaba\easyexcel-core\4.0.3\easyexcel-core-4.0.3.jar;D:\Maven3.6.3\myRepository\com\alibaba\easyexcel-support\3.3.4\easyexcel-support-3.3.4.jar;D:\Maven3.6.3\myRepository\org\apache\commons\commons-csv\1.11.0\commons-csv-1.11.0.jar;D:\Maven3.6.3\myRepository\org\ehcache\ehcache\3.10.9\ehcache-3.10.9.jar;D:\Maven3.6.3\myRepository\javax\cache\cache-api\1.1.1\cache-api-1.1.1.jar;D:\Maven3.6.3\myRepository\com\google\zxing\core\3.3.3\core-3.3.3.jar;D:\Maven3.6.3\myRepository\com\getui\push\restful-sdk\1.0.7.0\restful-sdk-1.0.7.0.jar;D:\Maven3.6.3\myRepository\org\apache\httpcomponents\httpclient\4.5.13\httpclient-4.5.13.jar;D:\Maven3.6.3\myRepository\org\apache\httpcomponents\httpcore\4.4.16\httpcore-4.4.16.jar;D:\Maven3.6.3\myRepository\commons-logging\commons-logging\1.2\commons-logging-1.2.jar;D:\Maven3.6.3\myRepository\com\google\code\gson\gson\2.13.2\gson-2.13.2.jar;D:\Maven3.6.3\myRepository\cn\hutool\hutool-all\5.8.43\hutool-all-5.8.43.jar;D:\Maven3.6.3\myRepository\com\fasterxml\jackson\datatype\jackson-datatype-jsr310\2.18.3\jackson-datatype-jsr310-2.18.3.jar;D:\Maven3.6.3\myRepository\net\coobird\thumbnailator\0.4.20\thumbnailator-0.4.20.jar
\ No newline at end of file
diff --git a/doc/20260602_device_maintenance_acceptance.sql b/doc/20260602_device_maintenance_acceptance.sql
new file mode 100644
index 0000000..24ccd4e
--- /dev/null
+++ b/doc/20260602_device_maintenance_acceptance.sql
@@ -0,0 +1,9 @@
+-- 璁惧淇濆吇琛ㄦ柊澧為獙鏀朵汉鐩稿叧瀛楁
+ALTER TABLE `device_maintenance`
+    ADD COLUMN `acceptance_name` VARCHAR(100) NULL COMMENT '楠屾敹浜�' AFTER `spare_parts_ids`,
+    ADD COLUMN `acceptance_time` DATETIME NULL COMMENT '楠屾敹鏃堕棿' AFTER `acceptance_name`,
+    ADD COLUMN `acceptance_remark` VARCHAR(500) NULL COMMENT '楠屾敹澶囨敞' AFTER `acceptance_time`;
+
+-- 璁惧淇濆吇瀹氭椂浠诲姟琛ㄦ柊澧炴槸鍚﹀惎鐢ㄥ瓧娈�
+ALTER TABLE `maintenance_task`
+    ADD COLUMN `is_enabled` TINYINT(1) NULL DEFAULT 1 COMMENT '鏄惁鍚敤 0-绂佺敤 1-鍚敤' AFTER `is_active`;
\ No newline at end of file
diff --git "a/doc/\345\211\215\347\253\257\350\201\224\350\260\203\346\226\207\346\241\243-\350\256\276\345\244\207\344\277\235\345\205\273\351\252\214\346\224\266\344\272\272\345\212\237\350\203\275.md" "b/doc/\345\211\215\347\253\257\350\201\224\350\260\203\346\226\207\346\241\243-\350\256\276\345\244\207\344\277\235\345\205\273\351\252\214\346\224\266\344\272\272\345\212\237\350\203\275.md"
new file mode 100644
index 0000000..13f0b51
--- /dev/null
+++ "b/doc/\345\211\215\347\253\257\350\201\224\350\260\203\346\226\207\346\241\243-\350\256\276\345\244\207\344\277\235\345\205\273\351\252\214\346\224\266\344\272\272\345\212\237\350\203\275.md"
@@ -0,0 +1,232 @@
+# 鍓嶇鑱旇皟鏂囨。 - 璁惧淇濆吇楠屾敹浜哄姛鑳�
+
+## 1. 鍙樻洿姒傝堪
+
+鏈鍙樻洿娑夊強璁惧淇濆吇妯″潡鏂板楠屾敹瀹℃壒娴佺▼锛屼笌璁惧鎶ヤ慨楠屾敹娴佺▼淇濇寔涓�鑷达細
+
+- 璁惧淇濆吇纭鍚庢柊澧為獙鏀跺鎵圭幆鑺�
+- 楠屾敹閫氳繃鍚庢墠绠楀畬缁�
+- 鏂板楠屾敹浜恒�侀獙鏀舵椂闂淬�侀獙鏀跺娉ㄥ瓧娈�
+
+---
+
+## 2. 鎺ュ彛娓呭崟
+
+### 2.1 璁惧淇濆吇
+
+鍩虹璺緞锛歚/device/maintenance`
+
+#### 鐘舵�佸畾涔�
+
+| 鐘舵�佸�� | 鍚箟 |
+|---|---|
+| `0` | 寰呬繚鍏� |
+| `3` | 寰呴獙鏀� |
+| `1` | 瀹岀粨 |
+| `2` | 澶辫触 |
+
+---
+
+### 2.2 纭淇濆吇锛堟柊澧烇級
+
+- **POST** `/device/maintenance/maintenance`
+- 璇存槑锛氭彁浜ゅ悗鐘舵�佷粠 `寰呬繚鍏�(0)` 杩涘叆 `寰呴獙鏀�(3)`锛屼笉鍐嶇洿鎺ュ畬缁撱��
+
+#### 璇锋眰鍙傛暟锛圔ody锛�
+
+| 瀛楁 | 绫诲瀷 | 蹇呭~ | 璇存槑 |
+|---|---|---|---|
+| `id` | long | 鏄� | 淇濆吇璁板綍ID |
+| `maintenanceActuallyName` | string | 鍚� | 瀹為檯淇濆吇浜� |
+| `maintenanceActuallyTime` | string | 鍚� | 瀹為檯淇濆吇鏃堕棿锛屾牸寮� `yyyy-MM-dd HH:mm:ss` |
+| `maintenanceResult` | string | 鍚� | 淇濆吇缁撴灉 0-缁翠慨 1-瀹屽ソ |
+| `sparePartsUseList` | array | 鍚� | 浣跨敤澶囦欢鍒楄〃 |
+
+#### 璇锋眰绀轰緥
+
+```json
+{
+  "id": 10001,
+  "maintenanceActuallyName": "寮犱笁",
+  "maintenanceActuallyTime": "2026-06-02 10:30:00",
+  "maintenanceResult": "1",
+  "sparePartsUseList": [
+    {
+      "id": 501,
+      "quantity": 2
+    }
+  ]
+}
+```
+
+#### 甯歌澶辫触鎻愮ず
+
+- `淇濆吇璁板綍涓嶅瓨鍦╜
+- `璇ヤ繚鍏诲凡瀹岀粨锛屼笉鑳介噸澶嶇‘璁や繚鍏籤
+- `璇ヤ繚鍏诲凡鎻愪氦楠屾敹瀹℃壒`
+- `澶囦欢 xxx 鏁伴噺涓嶈冻`
+
+---
+
+### 2.3 楠屾敹瀹℃壒锛堟柊澧烇級
+
+- **POST** `/device/maintenance/acceptance`
+- 璇存槑锛氫粎 `寰呴獙鏀�(3)` 鍙鎵癸紱瀹℃壒閫氳繃鍚庣姸鎬佹敼涓� `瀹岀粨(1)`銆�
+
+#### 璇锋眰鍙傛暟锛圔ody锛�
+
+| 瀛楁 | 绫诲瀷 | 蹇呭~ | 璇存槑 |
+|---|---|---|---|
+| `id` | long | 鏄� | 淇濆吇璁板綍ID |
+| `acceptanceName` | string | 鏄� | 楠屾敹浜� |
+| `acceptanceTime` | string | 鏄� | 楠屾敹鏃堕棿锛屾牸寮� `yyyy-MM-dd HH:mm:ss` |
+| `acceptanceRemark` | string | 鏄� | 楠屾敹澶囨敞 |
+
+#### 璇锋眰绀轰緥
+
+```json
+{
+  "id": 10001,
+  "acceptanceName": "鏉庡洓",
+  "acceptanceTime": "2026-06-02 11:00:00",
+  "acceptanceRemark": "淇濆吇椤规牳楠岄�氳繃锛岃澶囪繍琛屾甯�"
+}
+```
+
+#### 甯歌澶辫触鎻愮ず
+
+- `淇濆吇璁板綍id涓嶈兘涓虹┖`
+- `淇濆吇璁板綍涓嶅瓨鍦╜
+- `璇ヤ繚鍏绘湭杩涘叆寰呴獙鏀剁姸鎬侊紝涓嶈兘瀹℃壒`
+- `楠屾敹浜轰笉鑳戒负绌篳
+- `楠屾敹鏃堕棿涓嶈兘涓虹┖`
+- `楠屾敹澶囨敞涓嶈兘涓虹┖`
+
+---
+
+### 2.4 鏅�氭洿鏂版帴鍙i檺鍒�
+
+- **PUT** `/device/maintenance`
+- 闄愬埗锛氫笉鑳介�氳繃鏅�氭洿鏂扮洿鎺ユ妸鐘舵�佹敼鎴� `瀹岀粨(1)`锛堝繀椤昏蛋楠屾敹瀹℃壒鎺ュ彛锛夈��
+- 澶辫触鎻愮ず锛歚璇峰厛鎻愪氦楠屾敹瀹℃壒锛岄獙鏀堕�氳繃鍚庢墠鍙畬缁揱
+
+---
+
+## 3. 杩斿洖瀛楁鍙樻洿
+
+浠ヤ笅鎺ュ彛杩斿洖宸叉柊澧為獙鏀跺瓧娈碉細
+
+- **GET** `/device/maintenance/page`
+- **GET** `/device/maintenance/{id}`
+
+### 鏂板杩斿洖瀛楁
+
+| 瀛楁 | 绫诲瀷 | 璇存槑 |
+|---|---|---|
+| `acceptanceName` | string | 楠屾敹浜� |
+| `acceptanceTime` | string | 楠屾敹鏃堕棿锛屾牸寮� `yyyy-MM-dd HH:mm:ss` |
+| `acceptanceRemark` | string | 楠屾敹澶囨敞 |
+
+---
+
+## 4. 璁惧鎶ヤ慨楠屾敹娴佺▼锛堝弬鑰冿級
+
+璁惧鎶ヤ慨妯″潡宸叉湁鐩稿悓閫昏緫锛屽彲鍙傝�冨疄鐜帮細
+
+| 鐘舵�佸�� | 鍚箟 |
+|---|---|
+| `0` | 寰呯淮淇� |
+| `3` | 寰呴獙鏀� |
+| `1` | 瀹岀粨 |
+| `2` | 澶辫触 |
+
+### 鎶ヤ慨鐩稿叧鎺ュ彛
+
+| 鎺ュ彛 | 璇存槑 |
+|---|---|
+| **POST** `/device/repair/repair` | 纭缁翠慨锛岀姸鎬� 0鈫�3 |
+| **POST** `/device/repair/acceptance` | 楠屾敹瀹℃壒锛岀姸鎬� 3鈫�1 |
+
+### 鎶ヤ慨楠屾敹璇锋眰绀轰緥
+
+```json
+{
+  "id": 10001,
+  "acceptanceName": "鐜嬩簲",
+  "acceptanceTime": "2026-05-14 11:00:00",
+  "acceptanceRemark": "缁翠慨椤规牳楠岄�氳繃锛岃澶囪繍琛屾甯�"
+}
+```
+
+---
+
+## 5. 鍓嶇鏀归�犲缓璁�
+
+### 5.1 璁惧淇濆吇椤甸潰
+
+1. 鍒楄〃澧炲姞鐘舵�佸�� `3=寰呴獙鏀禶 鐨勫睍绀烘枃妗堜笌绛涢�夐」銆�
+2. "纭淇濆吇"鎸夐挳璋冪敤 `/device/maintenance/maintenance`锛屾垚鍔熷悗鍒锋柊涓哄緟楠屾敹鐘舵�併��
+3. 鏂板"楠屾敹瀹℃壒"寮圭獥锛屽繀濉細
+   - 楠屾敹浜�
+   - 楠屾敹鏃堕棿
+   - 楠屾敹澶囨敞
+4. 绂佹鍦ㄦ櫘閫氱紪杈戦〉鐩存帴灏嗙姸鎬佺疆涓哄畬缁撱��
+
+### 5.2 璁惧鎶ヤ慨椤甸潰
+
+宸叉湁楠屾敹娴佺▼锛岀‘璁ら�昏緫涓庝繚鍏讳竴鑷达細
+- 鐘舵�佹祦杞細`0寰呯淮淇� -> 3寰呴獙鏀� -> 1瀹岀粨`
+- 楠屾敹鎺ュ彛锛歚/device/repair/acceptance`
+
+---
+
+## 6. 鑱旇皟妫�鏌ユ竻鍗�
+
+### 璁惧淇濆吇
+
+1. 淇濆吇鍗曟祦绋嬶細`0寰呬繚鍏� -> 3寰呴獙鏀� -> 1瀹岀粨`銆�
+2. 寰呴獙鏀跺崟鎹湭濉獙鏀朵汉/楠屾敹鏃堕棿/楠屾敹澶囨敞鏃讹紝鍚庣杩斿洖瀵瑰簲閿欒鎻愮ず銆�
+3. 灏濊瘯閫氳繃 `PUT /device/maintenance` 鐩存帴璁句负瀹岀粨鏃讹紝鍚庣杩斿洖鎷︽埅鎻愮ず銆�
+4. 鍒楄〃/璇︽儏鎺ュ彛鑳芥纭繑鍥� `acceptanceName`銆乣acceptanceTime`銆乣acceptanceRemark`銆�
+
+### 璁惧鎶ヤ慨
+
+1. 鎶ヤ慨鍗曟祦绋嬶細`0寰呯淮淇� -> 3寰呴獙鏀� -> 1瀹岀粨`銆�
+2. 寰呴獙鏀跺崟鎹湭濉獙鏀朵汉/楠屾敹鏃堕棿/楠屾敹澶囨敞鏃讹紝鍚庣杩斿洖瀵瑰簲閿欒鎻愮ず銆�
+3. 灏濊瘯閫氳繃 `PUT /device/repair` 鐩存帴璁句负瀹岀粨鏃讹紝鍚庣杩斿洖鎷︽埅鎻愮ず銆�
+
+---
+
+## 7. 鏁版嵁搴撳彉鏇�
+
+鎵ц浠ヤ笅SQL鍓嶈澶囦唤鏁版嵁锛�
+
+```sql
+-- 璁惧淇濆吇琛ㄦ柊澧為獙鏀朵汉鐩稿叧瀛楁
+ALTER TABLE `device_maintenance`
+    ADD COLUMN `acceptance_name` VARCHAR(100) NULL COMMENT '楠屾敹浜�' AFTER `spare_parts_ids`,
+    ADD COLUMN `acceptance_time` DATETIME NULL COMMENT '楠屾敹鏃堕棿' AFTER `acceptance_name`,
+    ADD COLUMN `acceptance_remark` VARCHAR(500) NULL COMMENT '楠屾敹澶囨敞' AFTER `acceptance_time`;
+```
+
+> 鑻ユ湭鎵ц浠ヤ笂SQL锛岀浉鍏虫帴鍙d細鍑虹幇瀛楁涓嶅瓨鍦ㄥ紓甯搞��
+
+---
+
+## 8. 瀛楁瀵圭収琛�
+
+### 璁惧淇濆吇锛坉evice_maintenance锛�
+
+| 鏁版嵁搴撳瓧娈� | Java瀛楁 | 绫诲瀷 | 璇存槑 |
+|---|---|---|---|
+| `acceptance_name` | `acceptanceName` | String | 楠屾敹浜� |
+| `acceptance_time` | `acceptanceTime` | LocalDateTime | 楠屾敹鏃堕棿 |
+| `acceptance_remark` | `acceptanceRemark` | String | 楠屾敹澶囨敞 |
+
+### 璁惧鎶ヤ慨锛坉evice_repair锛�
+
+| 鏁版嵁搴撳瓧娈� | Java瀛楁 | 绫诲瀷 | 璇存槑 |
+|---|---|---|---|
+| `acceptance_name` | `acceptanceName` | String | 楠屾敹浜� |
+| `acceptance_time` | `acceptanceTime` | LocalDateTime | 楠屾敹鏃堕棿 |
+| `acceptance_remark` | `acceptanceRemark` | String | 楠屾敹澶囨敞 |
\ No newline at end of file
diff --git "a/doc/\345\211\215\347\253\257\350\201\224\350\260\203\346\226\207\346\241\243-\350\256\276\345\244\207\346\212\245\344\277\256\351\252\214\346\224\266\345\256\241\346\211\271\345\212\237\350\203\275.md" "b/doc/\345\211\215\347\253\257\350\201\224\350\260\203\346\226\207\346\241\243-\350\256\276\345\244\207\346\212\245\344\277\256\351\252\214\346\224\266\345\256\241\346\211\271\345\212\237\350\203\275.md"
new file mode 100644
index 0000000..8469456
--- /dev/null
+++ "b/doc/\345\211\215\347\253\257\350\201\224\350\260\203\346\226\207\346\241\243-\350\256\276\345\244\207\346\212\245\344\277\256\351\252\214\346\224\266\345\256\241\346\211\271\345\212\237\350\203\275.md"
@@ -0,0 +1,361 @@
+# 鍓嶇鑱旇皟鏂囨。 - 璁惧鎶ヤ慨楠屾敹瀹℃壒鍔熻兘
+
+## 1. 鍔熻兘姒傝堪
+
+璁惧鎶ヤ慨妯″潡瀹炵幇浜嗗畬鏁寸殑楠屾敹瀹℃壒娴佺▼锛�
+
+- 缁翠慨纭鍚庤繘鍏ュ緟楠屾敹鐘舵��
+- 楠屾敹瀹℃壒閫氳繃鍚庢墠绠楀畬缁�
+- 璁板綍楠屾敹浜恒�侀獙鏀舵椂闂淬�侀獙鏀跺娉�
+
+---
+
+## 2. 鐘舵�佸畾涔�
+
+| 鐘舵�佸�� | 鍚箟 | 璇存槑 |
+|---|---|---|
+| `0` | 寰呯淮淇� | 鎶ヤ慨鍗曞垵濮嬬姸鎬� |
+| `3` | 寰呴獙鏀� | 缁翠慨纭鍚庣瓑寰呴獙鏀� |
+| `1` | 瀹岀粨 | 楠屾敹閫氳繃 |
+| `2` | 澶辫触 | 缁翠慨澶辫触 |
+
+### 鐘舵�佹祦杞浘
+
+```
+寰呯淮淇�(0) --> 寰呴獙鏀�(3) --> 瀹岀粨(1)
+                |
+                +--> 澶辫触(2)
+```
+
+---
+
+## 3. 鎺ュ彛娓呭崟
+
+### 3.1 缁翠慨纭
+
+- **POST** `/device/repair/repair`
+- 璇存槑锛氱淮淇汉鍛樺畬鎴愮淮淇悗鎻愪氦锛岀姸鎬佷粠 `寰呯淮淇�(0)` 杩涘叆 `寰呴獙鏀�(3)`
+
+#### 璇锋眰鍙傛暟锛圔ody锛�
+
+| 瀛楁 | 绫诲瀷 | 蹇呭~ | 璇存槑 |
+|---|---|---|---|
+| `id` | Long | 鏄� | 鎶ヤ慨璁板綍ID |
+| `maintenanceName` | String | 鍚� | 缁翠慨浜� |
+| `maintenanceTime` | String | 鍚� | 缁翠慨鏃堕棿锛屾牸寮� `yyyy-MM-dd HH:mm:ss` |
+| `maintenanceResult` | String | 鍚� | 缁翠慨缁撴灉鎻忚堪 |
+| `sparePartsUseList` | Array | 鍚� | 浣跨敤澶囦欢鍒楄〃 |
+| `sparePartsUseList[].id` | Long | 鏄� | 澶囦欢ID |
+| `sparePartsUseList[].quantity` | Integer | 鏄� | 浣跨敤鏁伴噺 |
+
+#### 璇锋眰绀轰緥
+
+```json
+{
+  "id": 10001,
+  "maintenanceName": "鏉庡洓",
+  "maintenanceTime": "2026-06-02 10:30:00",
+  "maintenanceResult": "鏇存崲杞存壙骞惰瘯杩愯姝e父",
+  "sparePartsUseList": [
+    {
+      "id": 501,
+      "quantity": 2
+    },
+    {
+      "id": 502,
+      "quantity": 1
+    }
+  ]
+}
+```
+
+#### 杩斿洖绀轰緥
+
+```json
+{
+  "code": 200,
+  "msg": "鎿嶄綔鎴愬姛"
+}
+```
+
+#### 閿欒鎻愮ず
+
+| 閿欒淇℃伅 | 鍦烘櫙 |
+|---|---|
+| `鎶ヤ慨璁板綍涓嶅瓨鍦╜ | 浼犲叆鐨処D鏃犳晥 |
+| `璇ユ姤淇凡瀹岀粨锛屼笉鑳介噸澶嶇‘璁ょ淮淇甡 | 鐘舵�佸凡涓哄畬缁�(1) |
+| `璇ユ姤淇凡鎻愪氦楠屾敹瀹℃壒` | 鐘舵�佸凡涓哄緟楠屾敹(3) |
+| `澶囦欢 xxx 鏁伴噺涓嶈冻` | 澶囦欢搴撳瓨涓嶈冻 |
+
+---
+
+### 3.2 楠屾敹瀹℃壒
+
+- **POST** `/device/repair/acceptance`
+- 璇存槑锛氶獙鏀朵汉鍛樺寰呴獙鏀跺崟鎹繘琛屽鎵癸紝瀹℃壒閫氳繃鍚庣姸鎬佹敼涓� `瀹岀粨(1)`
+
+#### 璇锋眰鍙傛暟锛圔ody锛�
+
+| 瀛楁 | 绫诲瀷 | 蹇呭~ | 璇存槑 |
+|---|---|---|---|
+| `id` | Long | 鏄� | 鎶ヤ慨璁板綍ID |
+| `acceptanceName` | String | 鏄� | 楠屾敹浜哄鍚� |
+| `acceptanceTime` | String | 鏄� | 楠屾敹鏃堕棿锛屾牸寮� `yyyy-MM-dd HH:mm:ss` |
+| `acceptanceRemark` | String | 鏄� | 楠屾敹澶囨敞 |
+
+#### 璇锋眰绀轰緥
+
+```json
+{
+  "id": 10001,
+  "acceptanceName": "鐜嬩簲",
+  "acceptanceTime": "2026-06-02 11:00:00",
+  "acceptanceRemark": "缁翠慨椤规牳楠岄�氳繃锛岃澶囪繍琛屾甯�"
+}
+```
+
+#### 杩斿洖绀轰緥
+
+```json
+{
+  "code": 200,
+  "msg": "鎿嶄綔鎴愬姛"
+}
+```
+
+#### 閿欒鎻愮ず
+
+| 閿欒淇℃伅 | 鍦烘櫙 |
+|---|---|
+| `鎶ヤ慨璁板綍id涓嶈兘涓虹┖` | 鏈紶鍏d鍙傛暟 |
+| `鎶ヤ慨璁板綍涓嶅瓨鍦╜ | 浼犲叆鐨処D鏃犳晥 |
+| `璇ユ姤淇湭杩涘叆寰呴獙鏀剁姸鎬侊紝涓嶈兘瀹℃壒` | 鐘舵�佷笉鏄緟楠屾敹(3) |
+| `楠屾敹浜轰笉鑳戒负绌篳 | acceptanceName涓虹┖ |
+| `楠屾敹鏃堕棿涓嶈兘涓虹┖` | acceptanceTime涓虹┖ |
+| `楠屾敹澶囨敞涓嶈兘涓虹┖` | acceptanceRemark涓虹┖ |
+| `楠屾敹瀹℃壒澶辫触` | 鏁版嵁搴撴洿鏂板け璐� |
+
+---
+
+### 3.3 鏅�氭洿鏂版帴鍙i檺鍒�
+
+- **PUT** `/device/repair`
+- 璇存槑锛氭櫘閫氱殑鏇存柊鎺ュ彛锛岀敤浜庝慨鏀规姤淇熀鏈俊鎭�
+
+#### 闄愬埗瑙勫垯
+
+- 涓嶈兘閫氳繃姝ゆ帴鍙g洿鎺ュ皢鐘舵�佹敼涓� `瀹岀粨(1)`
+- 蹇呴』璧� `POST /device/repair/repair` -> `POST /device/repair/acceptance` 娴佺▼
+
+#### 閿欒鎻愮ず
+
+| 閿欒淇℃伅 | 鍦烘櫙 |
+|---|---|
+| `璇峰厛鎻愪氦楠屾敹瀹℃壒锛岄獙鏀堕�氳繃鍚庢墠鍙畬缁揱 | 灏濊瘯鐩存帴璁剧疆status=1 |
+
+---
+
+### 3.4 鏌ヨ鎺ュ彛杩斿洖瀛楁
+
+浠ヤ笅鎺ュ彛杩斿洖鏁版嵁涓寘鍚獙鏀剁浉鍏冲瓧娈碉細
+
+- **GET** `/device/repair/page` - 鍒嗛〉鍒楄〃
+- **GET** `/device/repair/{id}` - 璇︽儏
+
+#### 楠屾敹鐩稿叧杩斿洖瀛楁
+
+| 瀛楁 | 绫诲瀷 | 璇存槑 |
+|---|---|---|
+| `acceptanceName` | String | 楠屾敹浜� |
+| `acceptanceTime` | String | 楠屾敹鏃堕棿锛屾牸寮� `yyyy-MM-dd HH:mm:ss` |
+| `acceptanceRemark` | String | 楠屾敹澶囨敞 |
+
+#### 鍒楄〃杩斿洖绀轰緥
+
+```json
+{
+  "code": 200,
+  "msg": "鎿嶄綔鎴愬姛",
+  "data": {
+    "records": [
+      {
+        "id": 10001,
+        "deviceLedgerId": 100,
+        "deviceName": "绌哄帇鏈篈",
+        "deviceModel": "KR-500",
+        "areaId": 1,
+        "areaName": "鐢熶骇杞﹂棿",
+        "repairTime": "2026-06-01 09:00:00",
+        "repairName": "寮犱笁",
+        "remark": "璁惧杩愯寮傚搷",
+        "machineryCategory": "鍔ㄥ姏璁惧",
+        "maintenanceName": "鏉庡洓",
+        "maintenanceTime": "2026-06-02 10:30:00",
+        "maintenanceResult": "鏇存崲杞存壙骞惰瘯杩愯姝e父",
+        "acceptanceName": "鐜嬩簲",
+        "acceptanceTime": "2026-06-02 11:00:00",
+        "acceptanceRemark": "缁翠慨椤规牳楠岄�氳繃锛岃澶囪繍琛屾甯�",
+        "status": 1,
+        "createTime": "2026-06-01 08:30:00",
+        "updateTime": "2026-06-02 11:00:00"
+      }
+    ],
+    "total": 1,
+    "size": 10,
+    "current": 1
+  }
+}
+```
+
+---
+
+## 4. 鍓嶇瀹炵幇寤鸿
+
+### 4.1 鍒楄〃椤甸潰
+
+1. **鐘舵�佺瓫閫�**锛氬鍔� `寰呴獙鏀�(3)` 鐘舵�佺殑绛涢�夐」
+2. **鐘舵�佸睍绀�**锛氭牴鎹畇tatus鍊兼樉绀哄搴旀枃妗堝拰棰滆壊
+
+| 鐘舵�佸�� | 鏂囨 | 寤鸿棰滆壊 |
+|---|---|---|
+| 0 | 寰呯淮淇� | 姗欒壊/璀﹀憡 |
+| 3 | 寰呴獙鏀� | 钃濊壊/淇℃伅 |
+| 1 | 瀹岀粨 | 缁胯壊/鎴愬姛 |
+| 2 | 澶辫触 | 绾㈣壊/閿欒 |
+
+### 4.2 璇︽儏椤甸潰
+
+1. **寰呯淮淇姸鎬�(0)**锛�
+   - 鏄剧ず"纭缁翠慨"鎸夐挳
+   - 鍙紪杈戠淮淇汉銆佺淮淇椂闂淬�佺淮淇粨鏋�
+   - 鍙�夋嫨浣跨敤鐨勫浠�
+
+2. **寰呴獙鏀剁姸鎬�(3)**锛�
+   - 鏄剧ず"楠屾敹瀹℃壒"鎸夐挳
+   - 寮圭獥濉啓锛氶獙鏀朵汉銆侀獙鏀舵椂闂淬�侀獙鏀跺娉�
+
+3. **瀹岀粨鐘舵��(1)**锛�
+   - 鏄剧ず楠屾敹淇℃伅锛堥獙鏀朵汉銆侀獙鏀舵椂闂淬�侀獙鏀跺娉級
+   - 鍙灞曠ず
+
+### 4.3 楠屾敹瀹℃壒寮圭獥
+
+```html
+<!-- 绀轰緥琛ㄥ崟 -->
+<el-form :model="acceptanceForm" :rules="rules">
+  <el-form-item label="楠屾敹浜�" prop="acceptanceName">
+    <el-input v-model="acceptanceForm.acceptanceName" placeholder="璇疯緭鍏ラ獙鏀朵汉" />
+  </el-form-item>
+  <el-form-item label="楠屾敹鏃堕棿" prop="acceptanceTime">
+    <el-date-picker
+      v-model="acceptanceForm.acceptanceTime"
+      type="datetime"
+      placeholder="閫夋嫨楠屾敹鏃堕棿"
+      format="yyyy-MM-dd HH:mm:ss"
+      value-format="yyyy-MM-dd HH:mm:ss"
+    />
+  </el-form-item>
+  <el-form-item label="楠屾敹澶囨敞" prop="acceptanceRemark">
+    <el-input
+      v-model="acceptanceForm.acceptanceRemark"
+      type="textarea"
+      placeholder="璇疯緭鍏ラ獙鏀跺娉�"
+      :rows="3"
+    />
+  </el-form-item>
+</el-form>
+```
+
+### 4.4 琛ㄥ崟楠岃瘉瑙勫垯
+
+```javascript
+const rules = {
+  acceptanceName: [
+    { required: true, message: '楠屾敹浜轰笉鑳戒负绌�', trigger: 'blur' }
+  ],
+  acceptanceTime: [
+    { required: true, message: '楠屾敹鏃堕棿涓嶈兘涓虹┖', trigger: 'change' }
+  ],
+  acceptanceRemark: [
+    { required: true, message: '楠屾敹澶囨敞涓嶈兘涓虹┖', trigger: 'blur' }
+  ]
+}
+```
+
+---
+
+## 5. 鎿嶄綔鎸夐挳鎺у埗
+
+### 5.1 鎸夐挳鏄剧ず閫昏緫
+
+| 鐘舵�� | 纭缁翠慨 | 楠屾敹瀹℃壒 | 缂栬緫 | 鍒犻櫎 |
+|---|---|---|---|---|
+| 寰呯淮淇�(0) | 鉁� 鏄剧ず | 鉂� 闅愯棌 | 鉁� 鏄剧ず | 鉁� 鏄剧ず |
+| 寰呴獙鏀�(3) | 鉂� 闅愯棌 | 鉁� 鏄剧ず | 鉁� 鏄剧ず | 鉁� 鏄剧ず |
+| 瀹岀粨(1) | 鉂� 闅愯棌 | 鉂� 闅愯棌 | 鉂� 绂佺敤 | 鉂� 绂佺敤 |
+| 澶辫触(2) | 鉂� 闅愯棌 | 鉂� 闅愯棌 | 鉁� 鏄剧ず | 鉁� 鏄剧ず |
+
+### 5.2 鐘舵�佹祦杞帶鍒�
+
+```javascript
+// 纭缁翠慨
+async function handleRepair(row) {
+  const res = await post('/device/repair/repair', {
+    id: row.id,
+    maintenanceName: form.maintenanceName,
+    maintenanceTime: form.maintenanceTime,
+    maintenanceResult: form.maintenanceResult,
+    sparePartsUseList: form.sparePartsUseList
+  })
+  if (res.code === 200) {
+    // 鐘舵�佸彉涓哄緟楠屾敹(3)锛屽埛鏂板垪琛�
+    refreshList()
+  }
+}
+
+// 楠屾敹瀹℃壒
+async function handleAcceptance(row) {
+  const res = await post('/device/repair/acceptance', {
+    id: row.id,
+    acceptanceName: form.acceptanceName,
+    acceptanceTime: form.acceptanceTime,
+    acceptanceRemark: form.acceptanceRemark
+  })
+  if (res.code === 200) {
+    // 鐘舵�佸彉涓哄畬缁�(1)锛屽埛鏂板垪琛�
+    refreshList()
+  }
+}
+```
+
+---
+
+## 6. 鏁版嵁搴撳瓧娈�
+
+### device_repair 琛�
+
+| 瀛楁鍚� | 绫诲瀷 | 璇存槑 |
+|---|---|---|
+| `acceptance_name` | VARCHAR(100) | 楠屾敹浜� |
+| `acceptance_time` | DATETIME | 楠屾敹鏃堕棿 |
+| `acceptance_remark` | VARCHAR(500) | 楠屾敹澶囨敞 |
+
+### SQL锛堝凡鎵ц锛�
+
+```sql
+ALTER TABLE device_repair
+  ADD COLUMN acceptance_name VARCHAR(100) NULL COMMENT '楠屾敹浜�',
+  ADD COLUMN acceptance_time DATETIME NULL COMMENT '楠屾敹鏃堕棿',
+  ADD COLUMN acceptance_remark VARCHAR(500) NULL COMMENT '楠屾敹澶囨敞';
+```
+
+---
+
+## 7. 鑱旇皟妫�鏌ユ竻鍗�
+
+- [ ] 寰呯淮淇姸鎬佺殑鎶ヤ慨鍗曪紝鐐瑰嚮"纭缁翠慨"鍚庣姸鎬佸彉涓哄緟楠屾敹(3)
+- [ ] 寰呴獙鏀剁姸鎬佺殑鎶ヤ慨鍗曪紝鐐瑰嚮"楠屾敹瀹℃壒"鍚庣姸鎬佸彉涓哄畬缁�(1)
+- [ ] 楠屾敹瀹℃壒鏃讹紝楠屾敹浜�/楠屾敹鏃堕棿/楠屾敹澶囨敞涓虹┖锛屽悗绔繑鍥炲搴旈敊璇彁绀�
+- [ ] 灏濊瘯閫氳繃鏅�氱紪杈戞帴鍙g洿鎺ュ皢鐘舵�佹敼涓哄畬缁擄紝鍚庣杩斿洖鎷︽埅鎻愮ず
+- [ ] 鍒楄〃/璇︽儏鎺ュ彛姝g‘杩斿洖楠屾敹鐩稿叧瀛楁
+- [ ] 瀹岀粨鐘舵�佺殑鎶ヤ慨鍗曪紝璇︽儏椤靛睍绀洪獙鏀朵俊鎭�
\ No newline at end of file
diff --git "a/doc/\345\211\215\347\253\257\350\201\224\350\260\203\346\226\207\346\241\243-\350\277\207\347\250\213\346\243\200\351\252\214\346\250\241\346\235\277\345\257\274\345\207\272\345\212\237\350\203\275.md" "b/doc/\345\211\215\347\253\257\350\201\224\350\260\203\346\226\207\346\241\243-\350\277\207\347\250\213\346\243\200\351\252\214\346\250\241\346\235\277\345\257\274\345\207\272\345\212\237\350\203\275.md"
new file mode 100644
index 0000000..67fa537
--- /dev/null
+++ "b/doc/\345\211\215\347\253\257\350\201\224\350\260\203\346\226\207\346\241\243-\350\277\207\347\250\213\346\243\200\351\252\214\346\250\241\346\235\277\345\257\274\345\207\272\345\212\237\350\203\275.md"
@@ -0,0 +1,275 @@
+# 鍓嶇鑱旇皟鏂囨。 - 杩囩▼妫�楠屾ā鏉垮鍑哄姛鑳�
+
+## 1. 鍔熻兘姒傝堪
+
+杩囩▼妫�楠屾ā鍧楁敮鎸佷笁绉嶅鎴锋ā鏉跨殑妫�楠岀粨鏋滃鍑猴細
+- **浼熼緳妯℃澘** - 浼熼緳瀹㈡埛涓撶敤妫�楠屾姤鍛婃牸寮�
+- **鐧句簨妯℃澘** - 鐧句簨瀹㈡埛涓撶敤妫�楠屾姤鍛婃牸寮�
+- **杈惧埄妯℃澘** - 杈惧埄瀹㈡埛涓撶敤妫�楠屾姤鍛婃牸寮�
+
+瀵煎嚭鍔熻兘浼氳嚜鍔ㄥ~鍏呮ā鏉夸腑鐨�"缁撴灉"鍒楋紝鏍规嵁妫�楠屽弬鏁颁腑鐨�"椤圭洰鍒�"杩涜鍖归厤銆�
+
+---
+
+## 2. 鎺ュ彛娓呭崟
+
+### 2.1 瀵煎嚭浼熼緳妯℃澘妫�楠岀粨鏋�
+
+- **GET** `/quality/qualityInspect/export/weilong/{id}`
+- 璇存槑锛氬鍑烘寚瀹氳繃绋嬫楠屽崟鐨勪紵榫欐牸寮忔楠屾姤鍛�
+
+#### 璇锋眰鍙傛暟
+
+| 鍙傛暟鍚� | 绫诲瀷 | 浣嶇疆 | 蹇呭~ | 璇存槑 |
+|--------|------|------|------|------|
+| `id` | Long | Path | 鏄� | 杩囩▼妫�楠屽崟ID |
+
+#### 璇锋眰绀轰緥
+
+```
+GET /quality/qualityInspect/export/weilong/123
+```
+
+#### 杩斿洖缁撴灉
+
+杩斿洖Word鏂囨。鏂囦欢娴侊紝鏂囦欢鍚嶏細`浼熼緳妯$増妫�楠岀粨鏋�.doc`
+
+---
+
+### 2.2 瀵煎嚭鐧句簨妯℃澘妫�楠岀粨鏋�
+
+- **GET** `/quality/qualityInspect/export/baishi/{id}`
+- 璇存槑锛氬鍑烘寚瀹氳繃绋嬫楠屽崟鐨勭櫨浜嬫牸寮忔楠屾姤鍛�
+
+#### 璇锋眰鍙傛暟
+
+| 鍙傛暟鍚� | 绫诲瀷 | 浣嶇疆 | 蹇呭~ | 璇存槑 |
+|--------|------|------|------|------|
+| `id` | Long | Path | 鏄� | 杩囩▼妫�楠屽崟ID |
+
+#### 璇锋眰绀轰緥
+
+```
+GET /quality/qualityInspect/export/baishi/123
+```
+
+#### 杩斿洖缁撴灉
+
+杩斿洖Word鏂囨。鏂囦欢娴侊紝鏂囦欢鍚嶏細`鐧句簨妯$増妫�楠岀粨鏋�.doc`
+
+---
+
+### 2.3 瀵煎嚭杈惧埄妯℃澘妫�楠岀粨鏋�
+
+- **GET** `/quality/qualityInspect/export/dali/{id}`
+- 璇存槑锛氬鍑烘寚瀹氳繃绋嬫楠屽崟鐨勮揪鍒╂牸寮忔楠屾姤鍛�
+
+#### 璇锋眰鍙傛暟
+
+| 鍙傛暟鍚� | 绫诲瀷 | 浣嶇疆 | 蹇呭~ | 璇存槑 |
+|--------|------|------|------|------|
+| `id` | Long | Path | 鏄� | 杩囩▼妫�楠屽崟ID |
+
+#### 璇锋眰绀轰緥
+
+```
+GET /quality/qualityInspect/export/dali/123
+```
+
+#### 杩斿洖缁撴灉
+
+杩斿洖Word鏂囨。鏂囦欢娴侊紝鏂囦欢鍚嶏細`杈惧埄妯$増妫�楠岀粨鏋�.doc`
+
+---
+
+## 3. 鏁版嵁鍖归厤瑙勫垯
+
+### 3.1 妯℃澘濉厖閫昏緫
+
+瀵煎嚭鏃剁郴缁熶細鑷姩鍖归厤妫�楠屽弬鏁颁笌妯℃澘涓殑妫�楠岄」鐩細
+
+1. **椤圭洰鍖归厤**锛氭牴鎹楠屽弬鏁拌〃锛坄quality_inspect_param`锛変腑鐨刞parameterItem`锛堟楠岄」鐩級瀛楁涓庢ā鏉胯〃鏍煎乏渚х殑椤圭洰鍒楄繘琛屽尮閰�
+2. **缁撴灉濉厖**锛氬尮閰嶆垚鍔熷悗锛屽皢`testValue`锛堟楠屽�硷級濉厖鍒版ā鏉垮搴旇鐨�"缁撴灉"鍒�
+3. **妫�楠岀粨璁�**锛氱壒娈婅锛堝"璐ㄩ噺璇勫畾"銆�"妫�楠岀粨鏋�"銆�"妫�楠岀粨璁�"锛変細濉厖妫�楠屽崟鐨刞checkResult`瀛楁
+
+### 3.2 鍖归厤浼樺厛绾�
+
+| 浼樺厛绾� | 鍖归厤瑙勫垯 | 璇存槑 |
+|--------|----------|------|
+| 1 | 瀹屽叏鍖归厤 | 椤圭洰鍚嶇О瀹屽叏涓�鑷� |
+| 2 | 鍖呭惈鍖归厤 | 椤圭洰鍚嶇О鍖呭惈鍏崇郴 |
+| 3 | 缁勫悎鍖归厤 | 绗竴鍒�+绗簩鍒楃粍鍚堝尮閰� |
+| 4 | 鍒嗙粍鍖归厤 | 鍒嗙粍鏍囩+椤圭洰鍚嶇О缁勫悎鍖归厤 |
+
+### 3.3 鐗规畩澶勭悊
+
+浠ヤ笅琛屼細鑷姩濉厖妫�楠岀粨璁猴紙`checkResult`锛夛細
+- 璐ㄩ噺璇勫畾
+- 妫�楠岀粨鏋�
+- 妫�楠岀粨璁�
+- Grade estimation
+- Test Results
+
+---
+
+## 4. 鍓嶇瀹炵幇绀轰緥
+
+### 4.1 Vue + Axios 瀵煎嚭绀轰緥
+
+```javascript
+// 瀵煎嚭浼熼緳妯℃澘
+exportWeiLong(row) {
+  const id = row.id;
+  axios({
+    method: 'get',
+    url: `/quality/qualityInspect/export/weilong/${id}`,
+    responseType: 'blob'
+  }).then(response => {
+    const blob = new Blob([response.data], { type: 'application/msword' });
+    const link = document.createElement('a');
+    link.href = URL.createObjectURL(blob);
+    link.download = '浼熼緳妯$増妫�楠岀粨鏋�.doc';
+    link.click();
+    URL.revokeObjectURL(link.href);
+  }).catch(error => {
+    console.error('瀵煎嚭澶辫触', error);
+  });
+}
+
+// 瀵煎嚭鐧句簨妯℃澘
+exportBaiShi(row) {
+  const id = row.id;
+  axios({
+    method: 'get',
+    url: `/quality/qualityInspect/export/baishi/${id}`,
+    responseType: 'blob'
+  }).then(response => {
+    const blob = new Blob([response.data], { type: 'application/msword' });
+    const link = document.createElement('a');
+    link.href = URL.createObjectURL(blob);
+    link.download = '鐧句簨妯$増妫�楠岀粨鏋�.doc';
+    link.click();
+    URL.revokeObjectURL(link.href);
+  }).catch(error => {
+    console.error('瀵煎嚭澶辫触', error);
+  });
+}
+
+// 瀵煎嚭杈惧埄妯℃澘
+exportDaLi(row) {
+  const id = row.id;
+  axios({
+    method: 'get',
+    url: `/quality/qualityInspect/export/dali/${id}`,
+    responseType: 'blob'
+  }).then(response => {
+    const blob = new Blob([response.data], { type: 'application/msword' });
+    const link = document.createElement('a');
+    link.href = URL.createObjectURL(blob);
+    link.download = '杈惧埄妯$増妫�楠岀粨鏋�.doc';
+    link.click();
+    URL.revokeObjectURL(link.href);
+  }).catch(error => {
+    console.error('瀵煎嚭澶辫触', error);
+  });
+}
+```
+
+### 4.2 鎸夐挳閰嶇疆绀轰緥
+
+```html
+<el-table-column label="鎿嶄綔" width="200">
+  <template #default="{ row }">
+    <!-- 鍙湁杩囩▼妫�楠�(inspectType=1)鎵嶆樉绀烘ā鏉垮鍑烘寜閽� -->
+    <el-button v-if="row.inspectType === 1" size="small" @click="exportWeiLong(row)">
+      浼熼緳妯℃澘
+    </el-button>
+    <el-button v-if="row.inspectType === 1" size="small" @click="exportBaiShi(row)">
+      鐧句簨妯℃澘
+    </el-button>
+    <el-button v-if="row.inspectType === 1" size="small" @click="exportDaLi(row)">
+      杈惧埄妯℃澘
+    </el-button>
+  </template>
+</el-table-column>
+```
+
+---
+
+## 5. 閿欒澶勭悊
+
+### 5.1 閿欒鍝嶅簲
+
+| 閿欒淇℃伅 | 鍦烘櫙 |
+|----------|------|
+| `妫�楠屽崟ID涓嶈兘涓虹┖` | 鏈紶鍏d鍙傛暟 |
+| `妫�楠屽崟涓嶅瓨鍦╜ | 浼犲叆鐨処D鏃犳晥 |
+| `妯℃澘鏂囦欢涓嶅瓨鍦╜ | 妯℃澘鏂囦欢缂哄け |
+| `瀵煎嚭澶辫触` | 鏂囦欢澶勭悊寮傚父 |
+
+### 5.2 鍓嶇閿欒澶勭悊
+
+```javascript
+.catch(error => {
+  if (error.response) {
+    // 璇诲彇閿欒淇℃伅
+    const reader = new FileReader();
+    reader.onload = () => {
+      const message = JSON.parse(reader.result).msg || '瀵煎嚭澶辫触';
+      this.$message.error(message);
+    };
+    reader.readAsText(error.response.data);
+  } else {
+    this.$message.error('瀵煎嚭澶辫触锛岃绋嶅悗閲嶈瘯');
+  }
+});
+```
+
+---
+
+## 6. 涓氬姟璇存槑
+
+### 6.1 妫�楠岀被鍨嬪尯鍒�
+
+| inspectType | 绫诲瀷 | 璇存槑 |
+|-------------|------|------|
+| 0 | 鍘熸潗鏂欐楠� | 杩涙枡妫�楠� |
+| 1 | 杩囩▼妫�楠� | 鐢熶骇杩囩▼妫�楠岋紙鏀寔妯℃澘瀵煎嚭锛� |
+| 2 | 鍑哄巶妫�楠� | 鎴愬搧鍑哄巶妫�楠� |
+
+### 6.2 妯℃澘瀵煎嚭閫傜敤鑼冨洿
+
+妯℃澘瀵煎嚭鍔熻兘涓昏鐢ㄤ簬**杩囩▼妫�楠�**锛坄inspectType=1`锛夛紝鍓嶇搴旀牴鎹楠岀被鍨嬪垽鏂槸鍚︽樉绀烘ā鏉垮鍑烘寜閽��
+
+### 6.3 妫�楠屽弬鏁版暟鎹粨鏋�
+
+| 瀛楁 | 绫诲瀷 | 璇存槑 |
+|------|------|------|
+| `parameterItem` | String | 妫�楠岄」鐩悕绉帮紙鐢ㄤ簬鍖归厤妯℃澘锛� |
+| `testValue` | String | 妫�楠屽�硷紙濉厖鍒扮粨鏋滃垪锛� |
+| `standardValue` | String | 鏍囧噯鍊� |
+| `controlValue` | String | 鍐呮帶鍊� |
+| `unit` | String | 鍗曚綅 |
+
+---
+
+## 7. 鑱旇皟妫�鏌ユ竻鍗�
+
+- [ ] 杩囩▼妫�楠屽崟瀵煎嚭浼熼緳妯℃澘鎴愬姛锛屾枃浠跺彲姝e父鎵撳紑
+- [ ] 杩囩▼妫�楠屽崟瀵煎嚭鐧句簨妯℃澘鎴愬姛锛屾枃浠跺彲姝e父鎵撳紑
+- [ ] 杩囩▼妫�楠屽崟瀵煎嚭杈惧埄妯℃澘鎴愬姛锛屾枃浠跺彲姝e父鎵撳紑
+- [ ] 瀵煎嚭鏂囦欢涓楠岀粨鏋滃垪姝g‘濉厖
+- [ ] 妫�楠岀粨璁鸿姝g‘鏄剧ず`checkResult`鍊�
+- [ ] 浼犲叆涓嶅瓨鍦ㄧ殑ID鏃惰繑鍥為敊璇彁绀�
+- [ ] 鍘熸潗鏂欐楠�/鍑哄巶妫�楠屼笉鏄剧ず妯℃澘瀵煎嚭鎸夐挳
+- [ ] 鏂囦欢鍚嶇紪鐮佹纭紝涓枃鏃犱贡鐮�
+
+---
+
+## 8. 妯℃澘鏂囦欢浣嶇疆
+
+| 妯℃澘 | 璺緞 |
+|------|------|
+| 浼熼緳妯$増.doc | `/static/浼熼緳妯$増.doc` |
+| 鐧句簨妯$増.doc | `/static/鐧句簨妯$増.doc` |
+| 杈惧埄妯$増.doc | `/static/杈惧埄妯$増.doc` |
\ No newline at end of file
diff --git a/docs/maintenance_task_api.md b/docs/maintenance_task_api.md
new file mode 100644
index 0000000..91b9224
--- /dev/null
+++ b/docs/maintenance_task_api.md
@@ -0,0 +1,317 @@
+# 璁惧淇濆吇浠诲姟鎺ュ彛鏂囨。
+
+## 姒傝堪
+
+璁惧淇濆吇浠诲姟妯″潡鐢ㄤ簬绠$悊璁惧鐨勫畾鏃朵繚鍏昏鍒掞紝鏀寔澶氱棰戠巼绫诲瀷锛堟瘡鏃ャ�佹瘡鍛ㄣ�佹瘡鏈堛�佹瘡瀛e害銆佹瘡骞达級锛屽苟鍙惎鐢ㄦ垨绂佺敤浠诲姟銆�
+
+---
+
+## 鎺ュ彛鍒楄〃
+
+### 1. 鍒嗛〉鏌ヨ淇濆吇浠诲姟鍒楄〃
+
+**璇锋眰鍦板潃**: `GET /deviceMaintenanceTask/listPage`
+
+**璇锋眰鍙傛暟**:
+
+| 鍙傛暟鍚� | 绫诲瀷 | 蹇呭~ | 璇存槑 |
+|--------|------|------|------|
+| current | Long | 鍚� | 褰撳墠椤电爜锛岄粯璁�1 |
+| size | Long | 鍚� | 姣忛〉鏉℃暟锛岄粯璁�10 |
+| taskName | String | 鍚� | 浠诲姟鍚嶇О锛堟ā绯婃煡璇級 |
+| areaId | Long | 鍚� | 璁惧鍖哄煙ID |
+| isEnabled | Integer | 鍚� | 鏄惁鍚敤锛�1=鍚敤锛�0=绂佺敤锛� |
+
+**鍝嶅簲绀轰緥**:
+
+```json
+{
+  "code": 200,
+  "msg": "鎿嶄綔鎴愬姛",
+  "data": {
+    "records": [
+      {
+        "id": 1,
+        "taskName": "璁惧A,璁惧B",
+        "taskId": 100,
+        "areaId": 10,
+        "areaName": "鐢熶骇杞﹂棿",
+        "deviceModel": "鍨嬪彿A,鍨嬪彿B",
+        "deviceLedgerIdsStr": "100,101",
+        "frequencyType": "WEEKLY",
+        "frequencyDetail": "MON,14:30",
+        "nextExecutionTime": "2026-06-08T14:30:00",
+        "lastExecutionTime": "2026-06-01T14:30:00",
+        "isEnabled": 1,
+        "remarks": "澶囨敞淇℃伅",
+        "registrantId": 1,
+        "registrant": "寮犱笁",
+        "registrationDate": "2026-06-01",
+        "createTime": "2026-06-01T10:00:00",
+        "updateTime": "2026-06-01T10:00:00"
+      }
+    ],
+    "total": 100,
+    "current": 1,
+    "size": 10
+  }
+}
+```
+
+---
+
+### 2. 鏂板淇濆吇浠诲姟
+
+**璇锋眰鍦板潃**: `POST /deviceMaintenanceTask/add`
+
+**璇锋眰澶�**: `Content-Type: application/json`
+
+**璇锋眰鍙傛暟**:
+
+| 鍙傛暟鍚� | 绫诲瀷 | 蹇呭~ | 璇存槑 |
+|--------|------|------|------|
+| taskName | String | 鍚� | 浠诲姟鍚嶇О锛堝涓嶄紶鍒欐牴鎹澶囧悕绉拌嚜鍔ㄧ敓鎴愶級 |
+| taskId | Long | 鍚� | 璁惧ID锛堝崟涓澶囨椂浣跨敤锛� |
+| deviceLedgerIds | Long[] | 鍚� | 璁惧ID鏁扮粍锛堝涓澶囨椂浣跨敤锛� |
+| deviceLedgerIdsStr | String | 鍚� | 璁惧ID瀛楃涓诧紝閫楀彿鍒嗛殧 |
+| areaId | Long | 鍚� | 璁惧鍖哄煙ID |
+| frequencyType | String | 鏄� | 棰戞绫诲瀷锛岃涓嬫柟璇存槑 |
+| frequencyDetail | String | 鏄� | 棰戞璇︽儏锛屾牸寮忚涓嬫柟璇存槑 |
+| isEnabled | Integer | 鍚� | 鏄惁鍚敤锛�1=鍚敤锛�0=绂佺敤锛夛紝榛樿1 |
+| remarks | String | 鍚� | 澶囨敞 |
+
+**鍝嶅簲绀轰緥**:
+
+```json
+{
+  "code": 200,
+  "msg": "娣诲姞鎴愬姛"
+}
+```
+
+---
+
+### 3. 鏇存柊淇濆吇浠诲姟
+
+**璇锋眰鍦板潃**: `POST /deviceMaintenanceTask/update`
+
+**璇锋眰澶�**: `Content-Type: application/json`
+
+**璇锋眰鍙傛暟**: 鍚屾柊澧炴帴鍙o紝闇�棰濆浼犲叆 `id` 瀛楁
+
+| 鍙傛暟鍚� | 绫诲瀷 | 蹇呭~ | 璇存槑 |
+|--------|------|------|------|
+| id | Long | 鏄� | 浠诲姟ID |
+| ... | ... | ... | 鍏朵粬瀛楁鍚屾柊澧炴帴鍙� |
+
+**鍝嶅簲绀轰緥**:
+
+```json
+{
+  "code": 200,
+  "msg": "鏇存柊鎴愬姛"
+}
+```
+
+---
+
+### 4. 鍚敤/绂佺敤淇濆吇浠诲姟
+
+**璇锋眰鍦板潃**: `POST /deviceMaintenanceTask/changeEnable`
+
+**璇锋眰澶�**: `Content-Type: application/json`
+
+**璇锋眰鍙傛暟**:
+
+| 鍙傛暟鍚� | 绫诲瀷 | 蹇呭~ | 璇存槑 |
+|--------|------|------|------|
+| id | Long | 鏄� | 浠诲姟ID |
+| isEnabled | Integer | 鏄� | 鏄惁鍚敤锛�1=鍚敤锛�0=绂佺敤锛� |
+
+**鍝嶅簲绀轰緥**:
+
+```json
+{
+  "code": 200,
+  "msg": "鏇存柊鎴愬姛"
+}
+```
+
+**涓氬姟閫昏緫璇存槑**:
+- 鍚敤浠诲姟鏃朵細鑷姩鎭㈠瀹氭椂璋冨害
+- 绂佺敤浠诲姟鏃朵細鏆傚仠瀹氭椂璋冨害
+- 濡傛灉浠诲姟娌℃湁涓嬫鎵ц鏃堕棿锛屼細鑷姩璁$畻
+
+---
+
+### 5. 鍒犻櫎淇濆吇浠诲姟
+
+**璇锋眰鍦板潃**: `DELETE /deviceMaintenanceTask/delete`
+
+**璇锋眰澶�**: `Content-Type: application/json`
+
+**璇锋眰鍙傛暟**:
+
+| 鍙傛暟鍚� | 绫诲瀷 | 蹇呭~ | 璇存槑 |
+|--------|------|------|------|
+| - | Long[] | 鏄� | 浠诲姟ID鏁扮粍锛堣姹備綋鐩存帴浼犳暟缁勶級 |
+
+**璇锋眰绀轰緥**:
+
+```json
+[1, 2, 3]
+```
+
+**鍝嶅簲绀轰緥**:
+
+```json
+{
+  "code": 200,
+  "msg": "鍒犻櫎鎴愬姛"
+}
+```
+
+---
+
+## 棰戠巼绫诲瀷璇存槑
+
+### frequencyType 鍙�夊��
+
+| 鍊� | 璇存槑 | frequencyDetail 鏍煎紡 |
+|----|------|---------------------|
+| DAILY | 姣忔棩 | `HH:mm` |
+| WEEKLY | 姣忓懆 | `鏄熸湡,HH:mm` |
+| MONTHLY | 姣忔湀 | `鏃�,HH:mm` |
+| QUARTERLY | 姣忓搴� | `璧峰鏈堜唤,鏃�,HH:mm` |
+| YEARLY | 姣忓勾 | `鏈堜唤,鏃�,HH:mm` |
+
+### frequencyDetail 鏍煎紡璇﹁В
+
+#### 1. 姣忔棩锛圖AILY锛�
+
+鏍煎紡锛歚HH:mm`
+
+绀轰緥锛�
+- `14:30` - 姣忓ぉ 14:30 鎵ц
+
+#### 2. 姣忓懆锛圵EEKLY锛�
+
+鏍煎紡锛歚鏄熸湡,HH:mm`
+
+鏄熸湡鍙�夊�硷細`MON`, `TUE`, `WED`, `THU`, `FRI`, `SAT`, `SUN`
+
+绀轰緥锛�
+- `MON,14:30` - 姣忓懆涓� 14:30 鎵ц
+- `FRI,09:00` - 姣忓懆浜� 09:00 鎵ц
+
+#### 3. 姣忔湀锛圡ONTHLY锛�
+
+鏍煎紡锛歚鏃�,HH:mm`
+
+绀轰緥锛�
+- `15,14:30` - 姣忔湀15鏃� 14:30 鎵ц
+- `01,09:00` - 姣忔湀1鏃� 09:00 鎵ц
+- `31,18:00` - 姣忔湀鏈�鍚庝竴澶╋紙濡傛湀浠戒笉瓒�31澶╁垯鍙栨渶鍚庝竴澶╋級
+
+#### 4. 姣忓搴︼紙QUARTERLY锛�
+
+鏍煎紡锛歚璧峰鏈堜唤,鏃�,HH:mm`
+
+璇存槑锛氫粠鎸囧畾鏈堜唤寮�濮嬶紝姣忛殧3涓湀鎵ц涓�娆�
+
+绀轰緥锛�
+- `1,15,14:30` - 1鏈堛��4鏈堛��7鏈堛��10鏈堢殑15鏃� 14:30 鎵ц
+- `3,10,09:00` - 3鏈堛��6鏈堛��9鏈堛��12鏈堢殑10鏃� 09:00 鎵ц
+
+#### 5. 姣忓勾锛圷EARLY锛�
+
+鏍煎紡锛歚鏈堜唤,鏃�,HH:mm`
+
+绀轰緥锛�
+- `6,15,14:30` - 姣忓勾6鏈�15鏃� 14:30 鎵ц
+- `12,31,23:59` - 姣忓勾12鏈�31鏃� 23:59 鎵ц
+
+---
+
+## 鍓嶇浣跨敤绀轰緥
+
+### 鏂板姣忓懆淇濆吇浠诲姟
+
+```javascript
+const task = {
+  deviceLedgerIds: [100, 101],  // 璁惧ID鏁扮粍
+  areaId: 10,                   // 鍖哄煙ID
+  frequencyType: 'WEEKLY',      // 姣忓懆
+  frequencyDetail: 'MON,14:30', // 姣忓懆涓�14:30
+  isEnabled: 1,                 // 鍚敤
+  remarks: '姣忓懆渚嬭淇濆吇'
+};
+
+fetch('/deviceMaintenanceTask/add', {
+  method: 'POST',
+  headers: { 'Content-Type': 'application/json' },
+  body: JSON.stringify(task)
+});
+```
+
+### 鍚敤/绂佺敤浠诲姟
+
+```javascript
+// 鍚敤浠诲姟
+fetch('/deviceMaintenanceTask/changeEnable', {
+  method: 'POST',
+  headers: { 'Content-Type': 'application/json' },
+  body: JSON.stringify({ id: 1, isEnabled: 1 })
+});
+
+// 绂佺敤浠诲姟
+fetch('/deviceMaintenanceTask/changeEnable', {
+  method: 'POST',
+  headers: { 'Content-Type': 'application/json' },
+  body: JSON.stringify({ id: 1, isEnabled: 0 })
+});
+```
+
+---
+
+## 鏁版嵁瀛楀吀
+
+### isEnabled 瀛楁
+
+| 鍊� | 璇存槑 |
+|----|------|
+| 0 | 绂佺敤 |
+| 1 | 鍚敤 |
+
+### 杩斿洖瀛楁璇存槑
+
+| 瀛楁鍚� | 绫诲瀷 | 璇存槑 |
+|--------|------|------|
+| id | Long | 浠诲姟ID |
+| taskName | String | 浠诲姟鍚嶇О锛堝涓澶囩敤閫楀彿鍒嗛殧锛� |
+| taskId | Long | 涓昏澶嘔D |
+| areaId | Long | 璁惧鍖哄煙ID |
+| areaName | String | 璁惧鍖哄煙鍚嶇О |
+| deviceModel | String | 璁惧鍨嬪彿锛堝涓敤閫楀彿鍒嗛殧锛� |
+| deviceLedgerIdsStr | String | 璁惧ID瀛楃涓诧紙閫楀彿鍒嗛殧锛� |
+| frequencyType | String | 棰戞绫诲瀷 |
+| frequencyDetail | String | 棰戞璇︽儏 |
+| nextExecutionTime | DateTime | 涓嬫鎵ц鏃堕棿 |
+| lastExecutionTime | DateTime | 鏈�鍚庢墽琛屾椂闂� |
+| isEnabled | Integer | 鏄惁鍚敤 |
+| remarks | String | 澶囨敞 |
+| registrantId | Long | 褰曞叆浜篒D |
+| registrant | String | 褰曞叆浜哄鍚� |
+| registrationDate | Date | 褰曞叆鏃ユ湡 |
+| createTime | DateTime | 鍒涘缓鏃堕棿 |
+| updateTime | DateTime | 鏇存柊鏃堕棿 |
+
+---
+
+## 娉ㄦ剰浜嬮」
+
+1. **璁惧閫夋嫨**锛氬彲浠ヤ紶鍏� `deviceLedgerIds` 鏁扮粍鎴� `deviceLedgerIdsStr` 瀛楃涓叉寚瀹氬涓澶�
+2. **浠诲姟鍚嶇О**锛氬涓嶄紶 `taskName`锛岀郴缁熶細鏍规嵁璁惧鍚嶇О鑷姩鐢熸垚
+3. **涓嬫鎵ц鏃堕棿**锛氭柊澧炴垨鏇存柊鏃朵細鑷姩璁$畻涓嬫鎵ц鏃堕棿
+4. **鍚敤/绂佺敤**锛氱鐢ㄤ换鍔′笉浼氬垹闄ゅ畾鏃跺櫒锛屽彧鏄殏鍋滄墽琛岋紱鍚敤鍚庝細鎭㈠
+5. **鍒犻櫎浠诲姟**锛氬垹闄や换鍔′細鍚屾椂绉婚櫎鐩稿叧鐨勫畾鏃惰皟搴�
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index e840acd..af88718 100644
--- a/pom.xml
+++ b/pom.xml
@@ -326,6 +326,13 @@
             <version>${poi.version}</version>
         </dependency>
 
+        <!-- word doc鏍煎紡澶勭悊(HWPF) -->
+        <dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi-scratchpad</artifactId>
+            <version>${poi.version}</version>
+        </dependency>
+
 
         <!-- velocity浠g爜鐢熸垚浣跨敤妯℃澘 -->
         <dependency>
diff --git a/src/main/java/com/ruoyi/device/controller/DeviceMaintenanceController.java b/src/main/java/com/ruoyi/device/controller/DeviceMaintenanceController.java
index e34fc37..0f13f80 100644
--- a/src/main/java/com/ruoyi/device/controller/DeviceMaintenanceController.java
+++ b/src/main/java/com/ruoyi/device/controller/DeviceMaintenanceController.java
@@ -57,9 +57,15 @@
     }
 
     @PostMapping ("maintenance")
-    @Operation(summary = "淇敼璁惧淇濆吇")
+    @Operation(summary = "纭璁惧淇濆吇")
     public AjaxResult maintenance(@RequestBody DeviceMaintenanceDto deviceMaintenance) {
-        return deviceMaintenanceService.updateDeviceDeviceMaintenance(deviceMaintenance);
+        return deviceMaintenanceService.confirmMaintenance(deviceMaintenance);
+    }
+
+    @PostMapping ("/acceptance")
+    @Operation(summary = "璁惧淇濆吇楠屾敹瀹℃壒")
+    public AjaxResult acceptance(@RequestBody DeviceMaintenanceDto deviceMaintenance) {
+        return deviceMaintenanceService.approveMaintenanceAcceptance(deviceMaintenance);
     }
 
 
diff --git a/src/main/java/com/ruoyi/device/controller/MaintenanceTaskController.java b/src/main/java/com/ruoyi/device/controller/MaintenanceTaskController.java
index b6f8c27..955df5d 100644
--- a/src/main/java/com/ruoyi/device/controller/MaintenanceTaskController.java
+++ b/src/main/java/com/ruoyi/device/controller/MaintenanceTaskController.java
@@ -57,5 +57,12 @@
         return maintenanceTaskService.delete(ids);
     }
 
+    @PostMapping("/changeEnable")
+    @Operation(summary = "鍚敤/绂佺敤璁惧淇濆吇瀹氭椂浠诲姟")
+    @Log(title = "璁惧淇濆吇瀹氭椂浠诲姟", businessType = BusinessType.UPDATE)
+    public AjaxResult changeEnable(@RequestBody MaintenanceTask maintenanceTask) {
+        return maintenanceTaskService.changeEnable(maintenanceTask.getId(), maintenanceTask.getIsEnabled());
+    }
+
 
 }
diff --git a/src/main/java/com/ruoyi/device/dto/DeviceMaintenanceDto.java b/src/main/java/com/ruoyi/device/dto/DeviceMaintenanceDto.java
index f344cb3..929603a 100644
--- a/src/main/java/com/ruoyi/device/dto/DeviceMaintenanceDto.java
+++ b/src/main/java/com/ruoyi/device/dto/DeviceMaintenanceDto.java
@@ -54,7 +54,7 @@
     private String createUserName;
 
     @Schema(description = "淇濆吇鍥剧墖")
-    private List<StorageBlobDTO> storageBlobDTOs;
+    private List<StorageBlobDTO> storageBlobDTOs = new java.util.ArrayList<>();
 
 }
 
diff --git a/src/main/java/com/ruoyi/device/dto/DeviceRepairDto.java b/src/main/java/com/ruoyi/device/dto/DeviceRepairDto.java
index 12def24..75bcf72 100644
--- a/src/main/java/com/ruoyi/device/dto/DeviceRepairDto.java
+++ b/src/main/java/com/ruoyi/device/dto/DeviceRepairDto.java
@@ -5,6 +5,7 @@
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
+import java.util.ArrayList;
 import java.util.List;
 
 @Data
@@ -16,5 +17,5 @@
     @Schema(description = "缁翠慨鏃堕棿瀛楃涓�")
     private String maintenanceTimeStr;
 
-    private List<StorageBlobDTO> storageBlobDTOs;
+    private List<StorageBlobDTO> storageBlobDTOs = new ArrayList<>();
 }
diff --git a/src/main/java/com/ruoyi/device/pojo/DeviceMaintenance.java b/src/main/java/com/ruoyi/device/pojo/DeviceMaintenance.java
index f4ebc48..c8f6728 100644
--- a/src/main/java/com/ruoyi/device/pojo/DeviceMaintenance.java
+++ b/src/main/java/com/ruoyi/device/pojo/DeviceMaintenance.java
@@ -64,9 +64,20 @@
     @Schema(description = "淇濆吇缁撴灉 0 缁翠慨 1 瀹屽ソ")
     private String maintenanceResult;
 
-    @Schema(description = "鐘舵�� 0 寰呬繚鍏� 1 瀹岀粨 2 澶辫触")
+    @Schema(description = "鐘舵�� 0 寰呬繚鍏� 1 瀹岀粨 2 澶辫触 3 寰呴獙鏀�")
     private Integer status;
 
+    @Schema(description = "楠屾敹浜�")
+    private String acceptanceName;
+
+    @Schema(description = "楠屾敹鏃堕棿")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime acceptanceTime;
+
+    @Schema(description = "楠屾敹澶囨敞")
+    private String acceptanceRemark;
+
     @Schema(description = "鍒涘缓鏃堕棿")
     @TableField(fill = FieldFill.INSERT)
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
diff --git a/src/main/java/com/ruoyi/device/pojo/MaintenanceTask.java b/src/main/java/com/ruoyi/device/pojo/MaintenanceTask.java
index 0f1e7ee..e149638 100644
--- a/src/main/java/com/ruoyi/device/pojo/MaintenanceTask.java
+++ b/src/main/java/com/ruoyi/device/pojo/MaintenanceTask.java
@@ -68,6 +68,9 @@
     @Schema(description = "鏄惁婵�娲�")
     private boolean isActive;
 
+    @Schema(description = "鏄惁鍚敤 0-绂佺敤 1-鍚敤")
+    private Integer isEnabled;
+
     @Schema(description = "澶囨敞")
     @Excel(name = "澶囨敞")
     private String remarks;
diff --git a/src/main/java/com/ruoyi/device/service/IDeviceMaintenanceService.java b/src/main/java/com/ruoyi/device/service/IDeviceMaintenanceService.java
index e5a4080..41c6866 100644
--- a/src/main/java/com/ruoyi/device/service/IDeviceMaintenanceService.java
+++ b/src/main/java/com/ruoyi/device/service/IDeviceMaintenanceService.java
@@ -18,6 +18,10 @@
 
     AjaxResult updateDeviceDeviceMaintenance(DeviceMaintenanceDto deviceMaintenance);
 
+    AjaxResult confirmMaintenance(DeviceMaintenanceDto deviceMaintenanceDto);
+
+    AjaxResult approveMaintenanceAcceptance(DeviceMaintenanceDto deviceMaintenanceDto);
+
     void export(HttpServletResponse response, Long[] ids);
 
     DeviceMaintenanceVo detailById(Long id);
diff --git a/src/main/java/com/ruoyi/device/service/MaintenanceTaskService.java b/src/main/java/com/ruoyi/device/service/MaintenanceTaskService.java
index 19cb6ed..8b4a671 100644
--- a/src/main/java/com/ruoyi/device/service/MaintenanceTaskService.java
+++ b/src/main/java/com/ruoyi/device/service/MaintenanceTaskService.java
@@ -19,4 +19,6 @@
     AjaxResult updateByMaintenanceTaskId(MaintenanceTask maintenanceTask);
 
     AjaxResult delete(List<Long> ids);
+
+    AjaxResult changeEnable(Long id, Integer isEnabled);
 }
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 803450a..0190984 100644
--- a/src/main/java/com/ruoyi/device/service/impl/DeviceMaintenanceServiceImpl.java
+++ b/src/main/java/com/ruoyi/device/service/impl/DeviceMaintenanceServiceImpl.java
@@ -45,6 +45,11 @@
     private final FileUtil fileUtil;
     private final ISysNoticeService sysNoticeService;
 
+    private static final int STATUS_PENDING_MAINTENANCE = 0;
+    private static final int STATUS_COMPLETED = 1;
+    private static final int STATUS_FAILED = 2;
+    private static final int STATUS_PENDING_ACCEPTANCE = 3;
+
     @Override
     public IPage<DeviceMaintenanceDto> queryPage(Page page, DeviceMaintenanceDto deviceMaintenanceDto) {
 
@@ -81,6 +86,12 @@
             deviceMaintenance.setDeviceName(byId.getDeviceName());
             deviceMaintenance.setDeviceModel(byId.getDeviceModel());
             deviceMaintenance.setAreaId(byId.getAreaId());
+        }
+        if (deviceMaintenance.getStatus() != null
+                && deviceMaintenance.getStatus() == STATUS_COMPLETED
+                && (oldDeviceMaintenance.getStatus() == null
+                || oldDeviceMaintenance.getStatus() != STATUS_COMPLETED)) {
+            return AjaxResult.error("璇峰厛鎻愪氦楠屾敹瀹℃壒锛岄獙鏀堕�氳繃鍚庢墠鍙畬缁�");
         }
         // 澶勭悊澶囦欢浣跨敤鎯呭喌
         if (com.github.xiaoymin.knife4j.core.util.CollectionUtils.isNotEmpty(deviceMaintenance.getSparePartsUseList())) {
@@ -156,4 +167,56 @@
         vo.setStorageBlobVOs(fileUtil.getStorageBlobVOsByRecordTypeAndRecordId(RecordTypeEnum.DEVICE_MAINTENANCE, id));
         return vo;
     }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public AjaxResult confirmMaintenance(DeviceMaintenanceDto deviceMaintenanceDto) {
+        DeviceMaintenance oldDeviceMaintenance = this.getById(deviceMaintenanceDto.getId());
+        if (oldDeviceMaintenance == null) {
+            return AjaxResult.error("淇濆吇璁板綍涓嶅瓨鍦�");
+        }
+        if (oldDeviceMaintenance.getStatus() != null && oldDeviceMaintenance.getStatus() == STATUS_COMPLETED) {
+            return AjaxResult.error("璇ヤ繚鍏诲凡瀹岀粨锛屼笉鑳介噸澶嶇‘璁や繚鍏�");
+        }
+        if (oldDeviceMaintenance.getStatus() != null && oldDeviceMaintenance.getStatus() == STATUS_PENDING_ACCEPTANCE) {
+            return AjaxResult.error("璇ヤ繚鍏诲凡鎻愪氦楠屾敹瀹℃壒");
+        }
+        deviceMaintenanceDto.setStatus(STATUS_PENDING_ACCEPTANCE);
+        return updateDeviceDeviceMaintenance(deviceMaintenanceDto);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public AjaxResult approveMaintenanceAcceptance(DeviceMaintenanceDto deviceMaintenanceDto) {
+        if (deviceMaintenanceDto.getId() == null) {
+            return AjaxResult.error("淇濆吇璁板綍id涓嶈兘涓虹┖");
+        }
+        DeviceMaintenance oldDeviceMaintenance = this.getById(deviceMaintenanceDto.getId());
+        if (oldDeviceMaintenance == null) {
+            return AjaxResult.error("淇濆吇璁板綍涓嶅瓨鍦�");
+        }
+        if (oldDeviceMaintenance.getStatus() == null || oldDeviceMaintenance.getStatus() != STATUS_PENDING_ACCEPTANCE) {
+            return AjaxResult.error("璇ヤ繚鍏绘湭杩涘叆寰呴獙鏀剁姸鎬侊紝涓嶈兘瀹℃壒");
+        }
+        if (StringUtils.isBlank(deviceMaintenanceDto.getAcceptanceName())) {
+            return AjaxResult.error("楠屾敹浜轰笉鑳戒负绌�");
+        }
+        if (deviceMaintenanceDto.getAcceptanceTime() == null) {
+            return AjaxResult.error("楠屾敹鏃堕棿涓嶈兘涓虹┖");
+        }
+        if (StringUtils.isBlank(deviceMaintenanceDto.getAcceptanceRemark())) {
+            return AjaxResult.error("楠屾敹澶囨敞涓嶈兘涓虹┖");
+        }
+
+        DeviceMaintenance update = new DeviceMaintenance();
+        update.setId(deviceMaintenanceDto.getId());
+        update.setAcceptanceName(deviceMaintenanceDto.getAcceptanceName());
+        update.setAcceptanceTime(deviceMaintenanceDto.getAcceptanceTime());
+        update.setAcceptanceRemark(deviceMaintenanceDto.getAcceptanceRemark());
+        update.setStatus(STATUS_COMPLETED);
+        if (this.updateById(update)) {
+            return AjaxResult.success();
+        }
+        return AjaxResult.error("楠屾敹瀹℃壒澶辫触");
+    }
 }
diff --git a/src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskScheduler.java b/src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskScheduler.java
index ec7a8e3..6fd5a8d 100644
--- a/src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskScheduler.java
+++ b/src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskScheduler.java
@@ -160,6 +160,8 @@
                 return convertMonthlyToCron(task.getFrequencyDetail());
             case "QUARTERLY":
                 return convertQuarterlyToCron(task.getFrequencyDetail());
+            case "YEARLY":
+                return convertYearlyToCron(task.getFrequencyDetail());
             default:
                 throw new IllegalArgumentException("涓嶆敮鎸佺殑棰戠巼绫诲瀷: " + task.getFrequencyType());
         }
@@ -204,6 +206,22 @@
                 quarterStartMonth);
     }
 
+    // 姣忓勾浠诲姟杞崲
+    private String convertYearlyToCron(String frequencyDetail) {
+        String[] parts = validateAndSplit(frequencyDetail, ",", 3);
+        int month = validateMonth(parts[0]);  // 楠岃瘉鏈堜唤(1-12)
+        int day = validateDayOfMonth(parts[1]);  // 楠岃瘉鏃ユ湡
+        LocalTime time = parseTime(parts[2]);  // 瑙f瀽鏃堕棿
+
+        // Cron琛ㄨ揪寮�: 绉� 鍒� 鏃� 鏃� 鏈� 鍛�
+        // 姣忓勾鎸囧畾鏈堜唤鐨勬寚瀹氭棩鎵ц
+        return String.format("0 %d %d %d %d ?",
+                time.getMinute(),
+                time.getHour(),
+                day,
+                month);
+    }
+
     // 鏂板楠岃瘉鏈堜唤鐨勬柟娉�(1-12)
     private int validateMonth(String monthStr) {
         try {
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 1450a35..8aa02aa 100644
--- a/src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskServiceImpl.java
+++ b/src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskServiceImpl.java
@@ -147,4 +147,47 @@
         }
         return AjaxResult.success("鍒犻櫎鎴愬姛");
     }
+
+    @Override
+    public AjaxResult changeEnable(Long id, Integer isEnabled) {
+        MaintenanceTask oldTask = maintenanceTaskMapper.selectById(id);
+        if (oldTask == null) {
+            return AjaxResult.error("淇濆吇浠诲姟涓嶅瓨鍦�");
+        }
+
+        MaintenanceTask update = new MaintenanceTask();
+        update.setId(id);
+        update.setIsEnabled(isEnabled);
+        update.setActive(isEnabled != null && isEnabled == 1);
+
+        int result = maintenanceTaskMapper.updateById(update);
+        if (result > 0) {
+            try {
+                if (isEnabled != null && isEnabled == 1) {
+                    // 鍚敤锛氭仮澶嶆垨閲嶆柊璋冨害
+                    if (oldTask.getIsEnabled() != null && oldTask.getIsEnabled() == 0) {
+                        // 浠庣鐢ㄦ敼涓哄惎鐢紝閲嶆柊璁$畻涓嬫鎵ц鏃堕棿锛堝鏋滄病鏈夛級
+                        if (oldTask.getNextExecutionTime() == null || oldTask.getNextExecutionTime().isBefore(LocalDateTime.now())) {
+                            TimingTask tempTask = new TimingTask();
+                            tempTask.setFrequencyType(oldTask.getFrequencyType());
+                            tempTask.setFrequencyDetail(oldTask.getFrequencyDetail());
+                            LocalDateTime nextTime = timingTaskService.calculateFirstExecutionTime(tempTask);
+                            update.setNextExecutionTime(nextTime);
+                            maintenanceTaskMapper.updateById(update);
+                        }
+                        maintenanceTaskScheduler.scheduleMaintenanceTask(oldTask);
+                    } else {
+                        maintenanceTaskScheduler.resumeMaintenanceTask(id);
+                    }
+                } else {
+                    // 绂佺敤锛氭殏鍋滆皟搴�
+                    maintenanceTaskScheduler.pauseMaintenanceTask(id);
+                }
+            } catch (Exception e) {
+                log.error("璋冩暣淇濆吇浠诲姟璋冨害鐘舵�佸け璐�", e);
+            }
+            return AjaxResult.success("鏇存柊鎴愬姛");
+        }
+        return AjaxResult.error("鏇存柊澶辫触");
+    }
 }
diff --git a/src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskScheduleUtils.java b/src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskScheduleUtils.java
index 5c488d2..1200c31 100644
--- a/src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskScheduleUtils.java
+++ b/src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskScheduleUtils.java
@@ -33,6 +33,8 @@
                 return calculateMonthlyNextTime(frequencyDetail, currentTime);
             case "QUARTERLY":
                 return calculateQuarterlyNextTime(frequencyDetail, currentTime);
+            case "YEARLY":
+                return calculateYearlyNextTime(frequencyDetail, currentTime);
             default:
                 throw new IllegalArgumentException("涓嶆敮鎸佺殑棰戠巼绫诲瀷: " + frequencyType);
         }
@@ -105,6 +107,30 @@
         throw new IllegalArgumentException("鏃犳硶鎵惧埌涓嬩竴娆℃墽琛屾椂闂�");
     }
 
+    private static LocalDateTime calculateYearlyNextTime(String detail, LocalDateTime current) {
+        String[] parts = validateAndSplit(detail, ",", 3);
+        int month = validateMonth(parts[0]);
+        int dayOfMonth = validateDayOfMonth(parts[1]);
+        LocalTime time = parseTime(parts[2]);
+
+        for (int i = 0; i < 5; i++) {
+            int year = current.getYear() + i;
+            YearMonth targetYearMonth = YearMonth.of(year, month);
+            int adjustedDay = Math.min(dayOfMonth, targetYearMonth.lengthOfMonth());
+            LocalDateTime target = LocalDateTime.of(
+                    year,
+                    month,
+                    adjustedDay,
+                    time.getHour(),
+                    time.getMinute()
+            );
+            if (target.isAfter(current)) {
+                return target;
+            }
+        }
+        throw new IllegalArgumentException("鏃犳硶鎵惧埌涓嬩竴娆℃墽琛屾椂闂�");
+    }
+
     private static LocalTime parseTime(String timeStr) {
         try {
             return LocalTime.parse(timeStr, TIME_FORMATTER);
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 4508625..3ad8951 100644
--- a/src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskServiceImpl.java
+++ b/src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskServiceImpl.java
@@ -247,8 +247,11 @@
             // 濡傛灉鏄瘡鏈堟墽琛岋紝璁$畻涓嬩釜鏈堢殑鍏蜂綋鏃ユ湡
             return calculateMonthlyFirstExecution(task.getFrequencyDetail());
         } else if ("QUARTERLY".equals(frequencyType)) {
-            // 鑷畾涔夐鐜囷紝濡傛瘡灏忔椂銆佹瘡30鍒嗛挓绛�
-            return calculateCustomFirstExecution(task.getFrequencyDetail());
+            // 姣忓搴︽墽琛�
+            return TimingTaskScheduleUtils.calculateFirstExecutionTime("QUARTERLY", task.getFrequencyDetail());
+        } else if ("YEARLY".equals(frequencyType)) {
+            // 姣忓勾鎵ц
+            return TimingTaskScheduleUtils.calculateFirstExecutionTime("YEARLY", task.getFrequencyDetail());
         } else {
             throw new IllegalArgumentException("涓嶆敮鎸佺殑棰戠巼绫诲瀷: " + task.getFrequencyType());
         }
@@ -409,7 +412,9 @@
                 case "MONTHLY":
                     return calculateMonthlyNextTime(frequencyDetail, currentTime);
                 case "QUARTERLY":
-                    return calculateQuarterlyNextTime(frequencyDetail, currentTime);
+                    return TimingTaskScheduleUtils.calculateNextExecutionTime("QUARTERLY", frequencyDetail, currentTime);
+                case "YEARLY":
+                    return TimingTaskScheduleUtils.calculateNextExecutionTime("YEARLY", frequencyDetail, currentTime);
                 default:
                     throw new IllegalArgumentException("涓嶆敮鎸佺殑棰戠巼绫诲瀷: " + frequencyType);
             }
diff --git a/src/main/java/com/ruoyi/quality/controller/QualityInspectController.java b/src/main/java/com/ruoyi/quality/controller/QualityInspectController.java
index 676c915..9e26990 100644
--- a/src/main/java/com/ruoyi/quality/controller/QualityInspectController.java
+++ b/src/main/java/com/ruoyi/quality/controller/QualityInspectController.java
@@ -130,12 +130,33 @@
         qualityInspectService.qualityInspectExport(response, qualityInspect);
     }
 
+    @GetMapping("/export/weilong/{id}")
+    @Operation(summary = "瀵煎嚭浼熼緳妯$増妫�楠岀粨鏋�")
+    @Log(title = "瀵煎嚭浼熼緳妯$増妫�楠岀粨鏋�", businessType = BusinessType.EXPORT)
+    public void exportWeiLong(HttpServletResponse response, @PathVariable("id") Long id) {
+        qualityInspectService.exportWeiLong(response, id);
+    }
+
     /**
      * 鎻愪氦
      *
      * @param qualityInspect
      * @return
      */
+    @GetMapping("/export/baishi/{id}")
+    @Operation(summary = "瀵煎嚭鐧句簨妯$増妫�楠岀粨鏋�")
+    @Log(title = "瀵煎嚭鐧句簨妯$増妫�楠岀粨鏋�", businessType = BusinessType.EXPORT)
+    public void exportBaiShi(HttpServletResponse response, @PathVariable("id") Long id) {
+        qualityInspectService.exportBaiShi(response, id);
+    }
+
+    @GetMapping("/export/dali/{id}")
+    @Operation(summary = "瀵煎嚭杈惧埄妯$増妫�楠岀粨鏋�")
+    @Log(title = "瀵煎嚭杈惧埄妯$増妫�楠岀粨鏋�", businessType = BusinessType.EXPORT)
+    public void exportDaLi(HttpServletResponse response, @PathVariable("id") Long id) {
+        qualityInspectService.exportDaLi(response, id);
+    }
+
     @PostMapping("/submit")
     @Operation(summary = "鎻愪氦妫�楠�")
     @Log(title = "鎻愪氦妫�楠�", businessType = BusinessType.OTHER)
@@ -165,4 +186,14 @@
     public void down(HttpServletResponse response, @RequestBody QualityInspect qualityInspect) {
         qualityInspectService.down(response, qualityInspect);
     }
+
+    /**
+     * 璋冭瘯鎺ュ彛锛氬垎鏋愭ā鏉跨粨鏋�
+     */
+    @GetMapping("/analyzeTemplate")
+    @Operation(summary = "鍒嗘瀽妯℃澘缁撴瀯(璋冭瘯)")
+    public R<?> analyzeTemplate(@RequestParam String template) {
+        String templatePath = "/static/" + template + ".doc";
+        return R.ok(qualityInspectService.analyzeTemplate(templatePath));
+    }
 }
diff --git a/src/main/java/com/ruoyi/quality/service/IQualityInspectService.java b/src/main/java/com/ruoyi/quality/service/IQualityInspectService.java
index 2562995..2969972 100644
--- a/src/main/java/com/ruoyi/quality/service/IQualityInspectService.java
+++ b/src/main/java/com/ruoyi/quality/service/IQualityInspectService.java
@@ -21,6 +21,12 @@
 
     void qualityInspectExport(HttpServletResponse response, QualityInspect qualityInspect);
 
+    void exportWeiLong(HttpServletResponse response, Long id);
+
+    void exportBaiShi(HttpServletResponse response, Long id);
+
+    void exportDaLi(HttpServletResponse response, Long id);
+
     QualityInspectDto getDetailById(Integer id);
 
     int submit(QualityInspect qualityInspect);
@@ -33,4 +39,9 @@
     R batchQuickInspect(BatchQuickInspectRequest request);
 
     void down(HttpServletResponse response, QualityInspect qualityInspect);
+
+    /**
+     * 鍒嗘瀽妯℃澘缁撴瀯
+     */
+    String analyzeTemplate(String templatePath);
 }
diff --git a/src/main/java/com/ruoyi/quality/service/impl/QualityInspectServiceImpl.java b/src/main/java/com/ruoyi/quality/service/impl/QualityInspectServiceImpl.java
index effb6af..2842878 100644
--- a/src/main/java/com/ruoyi/quality/service/impl/QualityInspectServiceImpl.java
+++ b/src/main/java/com/ruoyi/quality/service/impl/QualityInspectServiceImpl.java
@@ -25,6 +25,7 @@
 import com.ruoyi.quality.pojo.QualityInspect;
 import com.ruoyi.quality.pojo.QualityInspectParam;
 import com.ruoyi.quality.pojo.QualityUnqualified;
+import com.ruoyi.quality.utils.QualityInspectTemplateExportHelper;
 import com.ruoyi.stock.pojo.StockInRecord;
 import com.ruoyi.stock.service.StockInRecordService;
 import com.ruoyi.quality.service.IQualityInspectParamService;
@@ -71,6 +72,8 @@
     private SalesLedgerProductMapper salesLedgerProductMapper;
 
     private ProcurementRecordService procurementRecordService;
+
+    private final QualityInspectTemplateExportHelper qualityInspectTemplateExportHelper;
 
     @Override
     public int add(QualityInspectDto qualityInspectDto) {
@@ -444,5 +447,24 @@
 
     }
 
+    @Override
+    public void exportWeiLong(HttpServletResponse response, Long id) {
+        qualityInspectTemplateExportHelper.exportWeiLong(response, id);
+    }
+
+    @Override
+    public void exportBaiShi(HttpServletResponse response, Long id) {
+        qualityInspectTemplateExportHelper.exportBaiShi(response, id);
+    }
+
+    @Override
+    public void exportDaLi(HttpServletResponse response, Long id) {
+        qualityInspectTemplateExportHelper.exportDaLi(response, id);
+    }
+
+    @Override
+    public String analyzeTemplate(String templatePath) {
+        return qualityInspectTemplateExportHelper.analyzeTemplate(templatePath);
+    }
 
 }
diff --git a/src/main/java/com/ruoyi/quality/utils/QualityInspectTemplateExportHelper.java b/src/main/java/com/ruoyi/quality/utils/QualityInspectTemplateExportHelper.java
new file mode 100644
index 0000000..54ad922
--- /dev/null
+++ b/src/main/java/com/ruoyi/quality/utils/QualityInspectTemplateExportHelper.java
@@ -0,0 +1,489 @@
+package com.ruoyi.quality.utils;
+
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.quality.mapper.QualityInspectMapper;
+import com.ruoyi.quality.pojo.QualityInspect;
+import com.ruoyi.quality.pojo.QualityInspectParam;
+import com.ruoyi.quality.service.IQualityInspectParamService;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.poi.hwpf.HWPFDocument;
+import org.apache.poi.hwpf.usermodel.Range;
+import org.apache.poi.hwpf.usermodel.Table;
+import org.apache.poi.hwpf.usermodel.TableCell;
+import org.apache.poi.hwpf.usermodel.TableIterator;
+import org.apache.poi.hwpf.usermodel.TableRow;
+import org.springframework.stereotype.Component;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Word template export helper for process inspection.
+ */
+@Component
+@RequiredArgsConstructor
+public class QualityInspectTemplateExportHelper {
+
+    private static final String WEILONG_TEMPLATE = "/static/浼熼緳妯$増.doc";
+    private static final String BAISHI_TEMPLATE = "/static/鐧句簨妯$増.doc";
+    private static final String DALI_TEMPLATE = "/static/杈惧埄妯$増.doc";
+
+    private final QualityInspectMapper qualityInspectMapper;
+    private final IQualityInspectParamService qualityInspectParamService;
+
+    public void exportWeiLong(HttpServletResponse response, Long inspectId) {
+        export(response, inspectId, WEILONG_TEMPLATE, "浼熼緳妯$増妫�楠岀粨鏋�");
+    }
+
+    public void exportBaiShi(HttpServletResponse response, Long inspectId) {
+        export(response, inspectId, BAISHI_TEMPLATE, "鐧句簨妯$増妫�楠岀粨鏋�");
+    }
+
+    public void exportDaLi(HttpServletResponse response, Long inspectId) {
+        export(response, inspectId, DALI_TEMPLATE, "杈惧埄妯$増妫�楠岀粨鏋�");
+    }
+
+    private void export(HttpServletResponse response, Long inspectId, String templatePath, String fileName) {
+        if (inspectId == null) {
+            throw new ServiceException("妫�楠屽崟ID涓嶈兘涓虹┖");
+        }
+
+        QualityInspect inspect = qualityInspectMapper.selectById(inspectId);
+        if (inspect == null) {
+            throw new ServiceException("妫�楠屽崟涓嶅瓨鍦�");
+        }
+
+        List<QualityInspectParam> paramList = qualityInspectParamService.list(
+                Wrappers.<QualityInspectParam>lambdaQuery()
+                        .eq(QualityInspectParam::getInspectId, inspectId)
+                        .orderByAsc(QualityInspectParam::getId));
+        Map<String, String> valueMap = buildValueMap(paramList, inspect);
+
+        try (InputStream inputStream = getClass().getResourceAsStream(templatePath)) {
+            if (inputStream == null) {
+                throw new ServiceException("妯℃澘鏂囦欢涓嶅瓨鍦細" + templatePath);
+            }
+
+            HWPFDocument document = new HWPFDocument(inputStream);
+            fillDocument(document, valueMap);
+
+            response.reset();
+            response.setContentType("application/msword");
+            response.setCharacterEncoding("UTF-8");
+            String encodedName = URLEncoder.encode(fileName, StandardCharsets.UTF_8).replace("+", "%20");
+            response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
+            response.setHeader("Content-Disposition", "attachment;filename=" + encodedName + ".doc");
+
+            try (OutputStream outputStream = response.getOutputStream()) {
+                document.write(outputStream);
+                outputStream.flush();
+            }
+        } catch (IOException e) {
+            throw new RuntimeException("瀵煎嚭澶辫触", e);
+        }
+    }
+
+    private void fillDocument(HWPFDocument document, Map<String, String> valueMap) {
+        Range range = document.getRange();
+        TableIterator iterator = new TableIterator(range);
+        while (iterator.hasNext()) {
+            Table table = iterator.next();
+            fillTable(table, valueMap);
+        }
+    }
+
+    private void fillTable(Table table, Map<String, String> valueMap) {
+        String currentGroupLabel = "";
+        // 璁板綍缁撹鍒楃殑浣嶇疆锛岄伩鍏嶅湪缁撹鍒椾笅闈㈢户缁~鍏�
+        int conclusionCellIndex = -1;
+
+        for (int rowIndex = 0; rowIndex < table.numRows(); rowIndex++) {
+            TableRow row = table.getRow(rowIndex);
+            String firstCellText = getCellText(row, 0);
+            String secondCellText = getCellText(row, 1);
+
+            if (StringUtils.isNotBlank(firstCellText)) {
+                currentGroupLabel = firstCellText;
+            }
+
+            // 鍏堝垽鏂槸鍚︿负缁撹琛�
+            String normalizedFirstCell = normalizeKey(firstCellText);
+            boolean isConclusionRow = matchesSummaryRow(normalizedFirstCell);
+
+            // 濡傛灉鏄粨璁鸿锛岀粨璁哄垪濮嬬粓鏄渶鍚庝竴鍒�
+            if (isConclusionRow) {
+                conclusionCellIndex = row.numCells() - 1;
+            }
+
+            String value = resolveValue(valueMap, currentGroupLabel, firstCellText, secondCellText, isConclusionRow);
+            if (StringUtils.isBlank(value)) {
+                continue;
+            }
+
+            // 鏌ユ壘缁撴灉鍒椾綅缃�
+            int resultCellIndex;
+            if (isConclusionRow) {
+                resultCellIndex = conclusionCellIndex;
+            } else {
+                // 鏅�氳锛氭壘绗竴涓┖鐧藉崟鍏冩牸浣滀负缁撴灉鍒楋紝浣嗚鎺掗櫎缁撹鍒�
+                resultCellIndex = findResultCellIndex(row, conclusionCellIndex);
+                if (resultCellIndex < 0) {
+                    // 涓嶄娇鐢ㄦ渶鍚庝竴鍒楋紝閬垮厤涓庣粨璁哄垪鍐茬獊
+                    int lastCellIndex = row.numCells() - 1;
+                    if (lastCellIndex > 1 && lastCellIndex != conclusionCellIndex) {
+                        resultCellIndex = lastCellIndex - 1;
+                    }
+                }
+            }
+
+            if (resultCellIndex < 0 || resultCellIndex == conclusionCellIndex && !isConclusionRow) {
+                continue;
+            }
+
+            TableCell resultCell = row.getCell(resultCellIndex);
+            String cellText = cleanCellText(resultCell.text());
+
+            // 涓ユ牸妫�鏌ワ細鍙湁绌虹櫧鎴栧崰浣嶇鎵嶅~鍏�
+            if (!isBlankLike(cellText) && !isPlaceholder(cellText)) {
+                continue;
+            }
+
+            // 浣跨敤鏇村畨鍏ㄧ殑濉厖鏂瑰紡
+            safeWriteCellText(resultCell, value);
+        }
+    }
+
+    /**
+     * 鏌ユ壘缁撴灉鍒楋紝鎺掗櫎缁撹鍒�
+     */
+    private int findResultCellIndex(TableRow row, int excludeIndex) {
+        for (int i = 1; i < row.numCells(); i++) {
+            if (i == excludeIndex) {
+                continue;
+            }
+            String cellText = cleanCellText(row.getCell(i).text());
+            if (isBlankLike(cellText) || isPlaceholder(cellText)) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    /**
+     * 瀹夊叏鍐欏叆鍗曞厓鏍兼枃鏈紝閬垮厤褰卞搷鍏朵粬琛�
+     */
+    private void safeWriteCellText(TableCell cell, String value) {
+        if (StringUtils.isBlank(value)) {
+            return;
+        }
+
+        String originalText = cell.text();
+        String cleanedOriginal = cleanCellText(originalText);
+
+        // 濡傛灉鍗曞厓鏍煎凡鏈夊唴瀹逛笖涓嶆槸鍗犱綅绗︼紝涓嶅啓鍏�
+        if (StringUtils.isNotBlank(cleanedOriginal) && !isPlaceholder(cleanedOriginal)) {
+            return;
+        }
+
+        // 鍙娇鐢╮eplaceText锛屼笉浣跨敤insertBefore
+        try {
+            if (StringUtils.isNotBlank(originalText)) {
+                cell.replaceText(originalText, value);
+            } else {
+                // 绌哄崟鍏冩牸鐩存帴璁剧疆鏂囨湰
+                cell.insertBefore(value);
+            }
+        } catch (Exception e) {
+            // 澶囩敤鏂规锛氫娇鐢╣etRange鏂瑰紡
+            try {
+//                cell.getRange().insertAfter(value);
+            } catch (Exception ignored) {}
+        }
+    }
+
+    /**
+     * 鍒ゆ柇鏄惁涓哄崰浣嶇
+     */
+    private boolean isPlaceholder(String text) {
+        if (StringUtils.isBlank(text)) {
+            return false;
+        }
+        String cleaned = text.trim();
+        // 甯歌鍗犱綅绗︽ā寮�
+        return cleaned.equals("鈥�") ||
+               cleaned.equals("-") ||
+               cleaned.equals("_") ||
+               cleaned.equals("/") ||
+               cleaned.equals("\\") ||
+               cleaned.equals("鈻�") ||
+               cleaned.equals("鈻�") ||
+               cleaned.equals("鈼�") ||
+               cleaned.equals("鈼�") ||
+               cleaned.equals("鈥�") ||
+               cleaned.equals("*") ||
+               cleaned.matches("^\\.{2,}$") || // 澶氫釜鐐�
+               cleaned.matches("^{2,}$") || // 澶氫釜澶ф嫭鍙�
+               cleaned.equalsIgnoreCase("N/A") ||
+               cleaned.equalsIgnoreCase("NA") ||
+               cleaned.equals("寰呮") ||
+               cleaned.equals("寰呭~") ||
+               cleaned.equals("绌虹櫧");
+    }
+
+    private int findResultCellIndex(TableRow row) {
+        for (int i = 1; i < row.numCells(); i++) {
+            if (isBlankLike(row.getCell(i).text())) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    private String resolveValue(Map<String, String> valueMap,
+                                String currentGroupLabel,
+                                String firstCellText,
+                                String secondCellText,
+                                boolean isConclusionRow) {
+        LinkedHashSet<String> candidates = new LinkedHashSet<>();
+        addCandidate(candidates, firstCellText);
+        addCandidate(candidates, secondCellText);
+        addCandidate(candidates, firstCellText + secondCellText);
+        if (StringUtils.isNotBlank(currentGroupLabel) && StringUtils.isNotBlank(secondCellText)) {
+            addCandidate(candidates, currentGroupLabel + secondCellText);
+        }
+        if (StringUtils.isNotBlank(currentGroupLabel)
+                && StringUtils.isNotBlank(firstCellText)
+                && StringUtils.isBlank(secondCellText)) {
+            addCandidate(candidates, currentGroupLabel);
+        }
+
+
+        // 缁撹琛屼笉濉厖锛屼繚鐣欐ā鏉垮師濮嬫暟鎹�
+        if (isConclusionRow) {
+            return null;
+        }
+
+        // 鏅�氳锛氬厛鏌ユ楠屽弬鏁板�硷紝鏈�鍚庢墠鍖归厤缁撹琛屽叧閿瘝
+        for (String candidate : candidates) {
+            String normalized = normalizeKey(candidate);
+            // 鏅�氳璺宠繃缁撹鍏抽敭璇嶅尮閰�
+            if (matchesSummaryRow(normalized)) {
+                continue;
+            }
+            String value = lookupValue(valueMap, normalized);
+            if (StringUtils.isNotBlank(value)) {
+                return value;
+            }
+        }
+
+        return null;
+    }
+
+    private boolean matchesSummaryRow(String normalizedText) {
+        if (StringUtils.isBlank(normalizedText)) {
+            return false;
+        }
+        return normalizedText.contains("璐ㄩ噺璇勫畾")
+                || normalizedText.contains("妫�楠岀粨璁�")
+                || normalizedText.contains("Gradeestimation")
+                || normalizedText.contains("Conclusion")
+                || normalizedText.contains("Evaluation")
+                || normalizedText.contains("璇勫畾")
+                || normalizedText.contains("缁撹");
+    }
+
+    private String lookupValue(Map<String, String> valueMap, String normalizedCandidate) {
+        if (StringUtils.isBlank(normalizedCandidate)) {
+            return null;
+        }
+
+        String value = valueMap.get(normalizedCandidate);
+        if (StringUtils.isNotBlank(value)) {
+            return value;
+        }
+
+        String chineseCandidate = stripEnglishLetters(normalizedCandidate);
+        value = valueMap.get(chineseCandidate);
+        if (StringUtils.isNotBlank(value)) {
+            return value;
+        }
+
+        for (Map.Entry<String, String> entry : valueMap.entrySet()) {
+            String key = entry.getKey();
+            if (StringUtils.contains(key, normalizedCandidate)
+                    || StringUtils.contains(normalizedCandidate, key)
+                    || StringUtils.contains(key, chineseCandidate)
+                    || StringUtils.contains(chineseCandidate, key)) {
+                return entry.getValue();
+            }
+        }
+        return null;
+    }
+
+    private Map<String, String> buildValueMap(List<QualityInspectParam> paramList, QualityInspect inspect) {
+        Map<String, String> valueMap = new LinkedHashMap<>();
+        for (QualityInspectParam param : paramList) {
+            String value = StringUtils.trimToNull(param.getTestValue());
+            if (StringUtils.isBlank(value)) {
+                continue;
+            }
+            putValue(valueMap, param.getParameterItem(), value);
+        }
+
+        String checkResult = StringUtils.trimToNull(inspect.getCheckResult());
+        if (StringUtils.isNotBlank(checkResult)) {
+            putValue(valueMap, "璐ㄩ噺璇勫畾", checkResult);
+            putValue(valueMap, "妫�楠岀粨鏋�", checkResult);
+            putValue(valueMap, "妫�楠岀粨璁�", checkResult);
+            putValue(valueMap, "Grade estimation", checkResult);
+            putValue(valueMap, "Test Results", checkResult);
+        }
+        return valueMap;
+    }
+
+    private void putValue(Map<String, String> valueMap, String key, String value) {
+        String normalizedKey = normalizeKey(key);
+        if (StringUtils.isBlank(normalizedKey)) {
+            return;
+        }
+        valueMap.put(normalizedKey, value);
+
+        String chineseKey = stripEnglishLetters(normalizedKey);
+        if (StringUtils.isNotBlank(chineseKey)) {
+            valueMap.putIfAbsent(chineseKey, value);
+        }
+    }
+
+    private void writeCellText(TableCell cell, String value) {
+        if (StringUtils.isBlank(value)) {
+            return;
+        }
+
+        String originalText = cell.text();
+        try {
+            cell.replaceText(originalText, value);
+        } catch (Exception ignored) {
+            // Fallback below.
+        }
+
+        String cleanedText = cleanCellText(cell.text());
+        if (!cleanedText.contains(value)) {
+            cell.insertBefore(value);
+        }
+    }
+
+    private String getCellText(TableRow row, int index) {
+        if (row.numCells() <= index) {
+            return "";
+        }
+        return cleanCellText(row.getCell(index).text());
+    }
+
+    private String cleanCellText(String text) {
+        if (text == null) {
+            return "";
+        }
+        return text.replace("\u0007", "")
+                .replace("\r", "")
+                .replace("\n", "")
+                .trim();
+    }
+
+    private boolean isBlankLike(String text) {
+        String cleaned = cleanCellText(text);
+        return StringUtils.isBlank(cleaned)
+                || "-".equals(cleaned)
+                || "_".equals(cleaned)
+                || "鈥�".equals(cleaned)
+                || "路".equals(cleaned);
+    }
+
+    private void addCandidate(LinkedHashSet<String> candidates, String text) {
+        if (StringUtils.isBlank(text)) {
+            return;
+        }
+        candidates.add(text);
+    }
+
+    private String normalizeKey(String text) {
+        String value = cleanCellText(text);
+        if (StringUtils.isBlank(value)) {
+            return "";
+        }
+        value = value.replace("\u00A0", "");
+        value = value.replaceAll("\\s+", "");
+        value = value.replace("锛�", "");
+        value = value.replace("锛�", "");
+        value = value.replace("(", "");
+        value = value.replace(")", "");
+        value = value.replace("锛�", "");
+        value = value.replace(",", "");
+        value = value.replace("銆�", "");
+        value = value.replace("锛�", "");
+        value = value.replace(":", "");
+        value = value.replace("锛�", "");
+        value = value.replace(";", "");
+        value = value.replace("銆�", "");
+        value = value.replace("鈥�", "");
+        value = value.replace("鈥�", "");
+        value = value.replace("銆�", "");
+        value = value.replace("銆�", "");
+        value = value.replace("%", "");
+        return value;
+    }
+
+    private String stripEnglishLetters(String text) {
+        if (StringUtils.isBlank(text)) {
+            return "";
+        }
+        return text.replaceAll("[A-Za-z]", "");
+    }
+
+    /**
+     * 璋冭瘯鏂规硶锛氬垎鏋愭ā鏉胯〃鏍肩粨鏋�
+     */
+    public String analyzeTemplate(String templatePath) {
+        StringBuilder sb = new StringBuilder();
+        try (InputStream inputStream = getClass().getResourceAsStream(templatePath)) {
+            if (inputStream == null) {
+                return "妯℃澘鏂囦欢涓嶅瓨鍦細" + templatePath;
+            }
+
+            HWPFDocument document = new HWPFDocument(inputStream);
+            Range range = document.getRange();
+            TableIterator iterator = new TableIterator(range);
+
+            int tableIndex = 0;
+            while (iterator.hasNext()) {
+                Table table = iterator.next();
+                sb.append("=== 琛ㄦ牸 ").append(tableIndex++).append(" ===\n");
+                sb.append("琛屾暟: ").append(table.numRows()).append("\n");
+
+                for (int rowIndex = 0; rowIndex < table.numRows(); rowIndex++) {
+                    TableRow row = table.getRow(rowIndex);
+                    sb.append("琛�").append(rowIndex).append(": ");
+                    for (int cellIndex = 0; cellIndex < row.numCells(); cellIndex++) {
+                        String cellText = cleanCellText(row.getCell(cellIndex).text());
+                        sb.append("[鍒�").append(cellIndex).append(": ").append(cellText).append("] ");
+                    }
+                    sb.append("\n");
+                }
+                sb.append("\n");
+            }
+        } catch (Exception e) {
+            sb.append("鍒嗘瀽澶辫触: ").append(e.getMessage());
+        }
+        return sb.toString();
+    }
+}
diff --git a/src/main/resources/mapper/device/DeviceMaintenanceMapper.xml b/src/main/resources/mapper/device/DeviceMaintenanceMapper.xml
index a25d13a..995c16a 100644
--- a/src/main/resources/mapper/device/DeviceMaintenanceMapper.xml
+++ b/src/main/resources/mapper/device/DeviceMaintenanceMapper.xml
@@ -13,6 +13,9 @@
         dm.maintenance_actually_time,
         dm.maintenance_result,
         dm.status,
+        dm.acceptance_name,
+        dm.acceptance_time,
+        dm.acceptance_remark,
         dm.create_time,
         dm.update_time,
         dm.create_user,
@@ -65,6 +68,9 @@
                dm.maintenance_actually_time,
                dm.maintenance_result,
                dm.status,
+               dm.acceptance_name,
+               dm.acceptance_time,
+               dm.acceptance_remark,
                dm.create_time,
                dm.update_time,
                dm.create_user,
diff --git "a/src/main/resources/static/\344\274\237\351\276\231\346\250\241\347\211\210.doc" "b/src/main/resources/static/\344\274\237\351\276\231\346\250\241\347\211\210.doc"
new file mode 100644
index 0000000..5d5eba9
--- /dev/null
+++ "b/src/main/resources/static/\344\274\237\351\276\231\346\250\241\347\211\210.doc"
Binary files differ
diff --git "a/src/main/resources/static/\347\231\276\344\272\213\346\250\241\347\211\210.doc" "b/src/main/resources/static/\347\231\276\344\272\213\346\250\241\347\211\210.doc"
new file mode 100644
index 0000000..521a62e
--- /dev/null
+++ "b/src/main/resources/static/\347\231\276\344\272\213\346\250\241\347\211\210.doc"
Binary files differ
diff --git "a/src/main/resources/static/\350\276\276\345\210\251\346\250\241\347\211\210.doc" "b/src/main/resources/static/\350\276\276\345\210\251\346\250\241\347\211\210.doc"
new file mode 100644
index 0000000..4a9e75c
--- /dev/null
+++ "b/src/main/resources/static/\350\276\276\345\210\251\346\250\241\347\211\210.doc"
Binary files differ

--
Gitblit v1.9.3