更新,工序计划

This commit is contained in:
tzy 2026-08-11 14:29:31 +08:00
parent ac596588b5
commit 5e091843b0
347 changed files with 24742 additions and 390065 deletions

8
.gitignore vendored
View File

@ -14,3 +14,11 @@ maven-wrapper.properties
**/logs/
/logs/
# IDE
.idea/
*.iml
.vscode/
# 本地文档/工具(默认不进仓库;需要单独提交时再强制 add
docs/

5
.idea/.gitignore vendored
View File

@ -1,5 +0,0 @@
# 默认忽略的文件
/shelf/
/workspace.xml
# 基于编辑器的 HTTP 客户端请求
/httpRequests/

View File

@ -1,34 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<annotationProcessing>
<profile default="true" name="Default" enabled="true" />
<profile name="Annotation profile for RuoYi-Vue-Plus" enabled="true">
<sourceOutputDir name="target/generated-sources/annotations" />
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
<outputRelativeToContentRoot value="true" />
<processorPath useClasspath="false">
<entry name="$MAVEN_REPOSITORY$/com/github/therapi/therapi-runtime-javadoc-scribe/0.15.0/therapi-runtime-javadoc-scribe-0.15.0.jar" />
<entry name="$MAVEN_REPOSITORY$/com/github/therapi/therapi-runtime-javadoc/0.15.0/therapi-runtime-javadoc-0.15.0.jar" />
<entry name="$MAVEN_REPOSITORY$/org/projectlombok/lombok/1.18.30/lombok-1.18.30.jar" />
<entry name="$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot-configuration-processor/2.7.11/spring-boot-configuration-processor-2.7.11.jar" />
<entry name="$MAVEN_REPOSITORY$/com/github/therapi/therapi-runtime-javadoc-scribe/0.15.0/therapi-runtime-javadoc-scribe-0.15.0.jar" />
<entry name="$MAVEN_REPOSITORY$/com/github/therapi/therapi-runtime-javadoc/0.15.0/therapi-runtime-javadoc-0.15.0.jar" />
<entry name="$MAVEN_REPOSITORY$/org/projectlombok/lombok/1.18.30/lombok-1.18.30.jar" />
<entry name="$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot-configuration-processor/2.7.11/spring-boot-configuration-processor-2.7.11.jar" />
</processorPath>
<module name="ruoyi-framework" />
<module name="ruoyi-oss" />
<module name="ruoyi-demo" />
<module name="ruoyi-system" />
<module name="ruoyi-job" />
<module name="ruoyi-monitor-admin" />
<module name="ruoyi-sms" />
<module name="ruoyi-common" />
<module name="ruoyi-generator" />
<module name="ruoyi-xxl-job-admin" />
<module name="ruoyi-admin" />
</profile>
</annotationProcessing>
</component>
</project>

View File

@ -1,31 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="file://$PROJECT_DIR$/ruoyi-admin/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/ruoyi-admin/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/ruoyi-common/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/ruoyi-common/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/ruoyi-demo/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/ruoyi-demo/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/ruoyi-extend/ruoyi-monitor-admin/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/ruoyi-extend/ruoyi-monitor-admin/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/ruoyi-extend/ruoyi-xxl-job-admin/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/ruoyi-extend/ruoyi-xxl-job-admin/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/ruoyi-extend/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/ruoyi-extend/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/ruoyi-framework/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/ruoyi-framework/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/ruoyi-generator/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/ruoyi-generator/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/ruoyi-job/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/ruoyi-job/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/ruoyi-oss/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/ruoyi-oss/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/ruoyi-sms/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/ruoyi-sms/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/ruoyi-system/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/ruoyi-system/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
</component>
</project>

View File

@ -1,25 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RemoteRepositoriesConfiguration">
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Central Repository" />
<option name="url" value="https://repo.maven.apache.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="public" />
<option name="name" value="aliyun nexus" />
<option name="url" value="https://maven.aliyun.com/repository/public/" />
</remote-repository>
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Maven Central repository" />
<option name="url" value="https://repo1.maven.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="jboss.community" />
<option name="name" value="JBoss Community repository" />
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
</remote-repository>
</component>
</project>

View File

@ -1,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/pom.xml" />
</list>
</option>
<option name="enabledProfiles">
<list>
<option value="dev" />
</list>
</option>
</component>
<component name="ProjectRootManager" version="2" project-jdk-name="corretto-1.8" project-jdk-type="JavaSDK" />
</project>

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,444 +0,0 @@
2026-05-18 08:34:03 [connection-pool-2-1] INFO c.d.o.a.s.n.w.WebsocketTransportConnector - [DingTalk] start websocket connection, uri=wss://wss-open-connection-union.dingtalk.com:443/connect
2026-05-18 08:34:03 [connection-pool-2-1] INFO c.d.o.a.s.n.core.DefaultSessionPool - [DingTalk] connection is established, connectionId=451fc31e-5251-11f1-8397-a2985f78c079
2026-05-18 08:43:24 [XNIO-1 task-5] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"970975bfc38c1a9acc74c573fec3aa02b216b77f","msg_signature":"970975bfc38c1a9acc74c573fec3aa02b216b77f","timestamp":"1779065001340","nonce":"5eVXd79A","encrypt":"NUUFVmiLTgmVB0EndP4sbmCVxfw9VsVqUWye/GTJHrVVYy6Y1lK8xytUwAug3WlujTvCNIGn4VmXdxMxA5ibBboZqZsqtWonuZn3LAGoDCzlldLwEw1jNbE/gLxH47lNWMIWfuTpxGr3fUCyga5CDZ6o/F3n1Vq2JhuA7tPt4ONqAYFfWaYWewNuHQFkXu02/6jOFGeVSKb+GUnORMjyPZFqbV/TTaKa/EzH0WRnqUiJrF8sxLtdjMF9UMC5QYNqk+1Nw0sjSjWxnJvyjaBgwPhNhXsQ4Y2CGupMcNw0h3QoQCxDcPDowLqF/zZv3PFKQMr0cxd5e1aJcl63pjzs6MlOIqg8patj3fLrtjD7+DfLSOpS3QIWR8v/pedaGoOXmj1AMJkN/yO2QvYADbzXk6ukz2d4jFEBy8OJNgmitI17mq7M+a7u0SDZoWWMV1Dxv51jH3YB1t4RoVmI1em4F3qjiISI7fzfkxx6l8KX3dunE7X63A51st5kl2FajKmIm8hSXP/qO85h/VyYLgeEqxTvzrbp6mCEhZnV8tfnmgq+gBfok7pDXe0Jfu39y5p6JFhUosMfDQMjE3rDXBfXXtU+eFqc0YonJ7+AsqNXAPmWyMypYBOfM3NvztLQd+gs12GcEUTz+hAh+pFx0s3QGsKbmqR2hk1NJLeMvXZt5NuPqwFCOQx98E944dLruJaxrifXgytWLcmpf4H6n0PKMxsbCuCJWVYjKT/b6FeD5SdZ3Qs+URbTwtBJeopbgubZUL4x61dG6dEEMC2grcNdZPoYSkO2JEz1tmOlSuCyOmYQqiAH9TjtBYI618py5EJ2Qo1mztMHrj8v3t7icCggQ9THoOyhZVgM9toEIkJS4bCEmw1Gd1sMhO6ofkfRzVTIdAn2cx1nstB5tZk7va8IEazfuHkYFuCbIL0GkC6gsXow0WtVqfGaU2QWI62g6m3IdmLRTkXqvIPzRzyYI4xmVy0zh7jDuOhSlbmBgsryL+I80l6df+pvf0UIApULkmGdlu/eNsyMK+UmFQaAKt0MX+m84OA3fKQkbldOslTmVE4="}
2026-05-18 08:43:24 [XNIO-1 task-5] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"qKnJo9BRRSq3GemBFc_Q_g08411778909461","eventId":"2c9565538e3b46b0b4a237002ead56cf","finishTime":1779065000000,"corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB/type/finish","EventType":"bpms_task_change","businessId":"202605161331000017243","activityName":"办理人","remark":"","actualActionerId":"03462113426124233873","agentActionerIds":[],"title":"张新怡提交的技术方案申请表","type":"finish","result":"audit","activityId":"25d1_3948","createTime":1778925260000,"processCode":"PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB","bizCategoryId":"","businessType":"","staffId":"03462113426124233873","taskId":101156217321}
2026-05-18 08:43:24 [XNIO-1 task-5] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 08:43:24 [XNIO-1 task-5] INFO c.r.c.d.w.SchemeApplicationBpmsEventHandler - 跳过方案申请表 BPMSeventType=bpms_task_change, type=finish, eventResult=audit, onInstance=true, onTask=false整单请订阅 bpms_instance_change仅任务且非 agree 时不会处理)
2026-05-18 08:43:24 [XNIO-1 task-5] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 08:43:24 [XNIO-1 task-5] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779065004374, msg_signature=42b8de361debef89d9e3f9c1310c4e04879111c4, encrypt=gUj5T88XBoYpMP16dzERFNG51JJ9Cqcl62iy3AUxr+nDx/5f3mLxGazBzp/M8tIdYRnCAUAtlKEvTlIRQRq4Pw==, nonce=7ldI5OO6FjWCDipG}
2026-05-18 08:43:32 [XNIO-1 task-5] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"0a01e86c240e730fa0a807fcd280e4af58c21f2d","msg_signature":"0a01e86c240e730fa0a807fcd280e4af58c21f2d","timestamp":"1779065001503","nonce":"WD1WK2R7","encrypt":"Tu5FRnEDir4G3rKDZqB+CwBtFayooqRyv+X4/8RYUXuhLlLf4ZuZU2XDloKHEJd5bcMl59oPU6q3bQiuKQO4aZmmn85zju3lcLsBYn481tjIdrIFj0RLV5ra52HLfd7IJGdnFHlA12G8V6GnW5Lce0skcbar4GDK+X1lzMbD7iKIwCjkUqMZgMNAE7xRQBS5nyu6WZXdnD7AZx7SlxcFSf0dSDMt5yZj0v9382hVHpoQk2jq5UY+cAXPKmjzE6MScDZR65xoKiPq6e/tTPU3W+Sd4Q7i5ddAfQYZrvE7rOCEkXckUYrVGDPxYELdh3SGKj60mfNE/n/A8HNtHKyvsu4Y8beHyNzwoNUUxNvW5xDwZ2s7ujbTil+UWY4YNXBtHwao9F2Hm6iIo8rSIPt7LMXLSLgR0Xjq6h0tBOzxOVnGc96ItVpjIvNPyjf7/sM3xyLNiEhpU6CfuWo+XlraQbbh/hDBaV8LeQjtEGaYEFXI4/Y9IW3V6KReQAJp1wm+hKFSfltN7FtBggo8Zf2Aarak83gWZrCwTQYBPjI5IstGDgjS4XpeLDu6pVWXKvUng1lJP54FqoVe2cqKUl1Qz7uMt+fvyZQdQscalTXQTFdId1VGMOHPGnatxrsLhqCjgmNRivZNJtGp7fJ6dxllc0p3bHOF7Drov8OMsNbK+wXbg3bf6dTPRi+lVObeJvhTVvBKk/bIe1qaMSTLGKTcFsMzzkL5arspAgs6Rjly0rknzauKvzVBLQcuYAoeuiniH6cFZG5V5O3FMe+hZRoK5brFnobiSqnMLcRURhHqI+uKgeuf8HqQ8rVm2bUYL7ZyTIom2gFIsAQI+hsAD2sl37fJkf1ROis7p06eWPjtyqKmZG+gRM+FToqTcOe45BCw/YsT2ZiLwADX0uYpScME5LE8Zle9RPyTrH5Mja+eHhnmEpMtd5pZXQG/CbxdS6yY3XCNftpfVZuLRiDPcadlO3X59UlYkb5vh0QJ9mlsr8KL+2Gk4Vam1QgijODWTfnj"}
2026-05-18 08:43:32 [XNIO-1 task-5] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"qKnJo9BRRSq3GemBFc_Q_g08411778909461","eventId":"964fc204bc6b4e5dbe5755eaff059ac9","corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB/type/start","EventType":"bpms_task_change","businessId":"202605161331000017243","activityName":"研发技术人员确认提交方案","actualActionerId":"01190846452221394385","agentActionerIds":[],"title":"张新怡提交的技术方案申请表","type":"start","activityId":"ffbb_66b4","createTime":1779065001000,"processCode":"PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB","bizCategoryId":"","businessType":"","staffId":"01190846452221394385","taskId":101208140285}
2026-05-18 08:43:32 [XNIO-1 task-5] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 08:43:32 [XNIO-1 task-5] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 08:43:32 [XNIO-1 task-5] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779065012881, msg_signature=ab6aceaea6c6cc4e644fb72a91320cf7130b3711, encrypt=9Tr0a9j3S9w4F7gYre7ZtcRU5AQJCw6tu3eNoC0q8/jPLiPdYItqrmvyf2oKZpSXYnEchp3G1AzUdbLhZAHSAA==, nonce=7RSNMTEXkxiTN62l}
2026-05-18 08:43:39 [XNIO-1 task-5] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"bc8af64e15d2ef492a71df3a4a6078212a08a7d7","msg_signature":"bc8af64e15d2ef492a71df3a4a6078212a08a7d7","timestamp":"1779065014134","nonce":"XY2KoIR0","encrypt":"cNPeb19i9oVYsWDsZnsgrOBeHx7okf4Yy/QbVFm/Cf5ux3pFjko7ddE/c5tfjSF+7zgQjwQPnc/vkFBPuI34Dc9NQtB/4OAgqie4v9r72TgzSbffaFi0EK4AIlRXgtVmuaYQvJx1ur6v7m7Y07BMqsc+Sb2FyCZhKxipQ8rAmFGEqbDJre9q8fq0AQzKq5LfytGAZ5tg0TFxHQCUVC3vKlkJoinXr5LDaN/zWwlidQcuMwSHosBbt9rEKHWY6OY1miUoVeUD57CcgXRPULt+OwZnmqcvV3+SwLSYpoFpyITcYpDdccVtrySfDJRZaH+nb5x1dSb667Tb18Nve+YHYIprNV9FGijbNmqHl0tRUfEzjL5XrwuJAcmOgnMsV1Df5sMQ9Eiwdywfl6CbtRiCCAjny8aOJaVBcQe0xlCMx37e5jsJMHP80+8rQoPOExtIzSc9Lr+O5aZ38tsRhR6uOAiZJHq8mrr1GZRCZSnSz4uzY2h83/7+HmEbc2i5l1kF2GgjLY2mFLTktzJxm8/ISacokHrmdAS9YTIpNup2C88GcxxrpS0zSfqI/7qSUomSp2ZU2d6yZEymJvEGjTf8h9i3/y3xhoXlEj73E0V5M6JZn6qOr3c7gvs6oBX4Ynu8j0pO9OS9SfWAp7sl23kXbQB3Z/b0WzhKWFtQR+NMukCwPetC9CLtyTIwmRGQdXn46rPvUVEyXlZ8+R7Vl1FKJ6eY9h+5c0RJxMNUXnb/PrIE4K+tjdM5dwDqQ74FfwsFpJBt3GknYI93wmg/LbNxHYbaPKnvrGZBty1dDjdeRWByJSzrKwP9mVlSlBDTAIlVwvEyDVF25ewN0XKNWTx/W/MEiOaRdrWv+YuOpfOwS5zbuk2XUeokltp7xfPUCSJ336tANl1LtPwYFMc+YwmCSbMPaffgfCdMO3YnqLTjJ9SReMgjJkzvhQZCc7HPOErFApxEAaec0NAa8QzSWwemp2cOEBjHd/AxvNlaKfIgs+PgPXZPNy9vqQsh40jInQdv"}
2026-05-18 08:43:39 [XNIO-1 task-5] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"qKnJo9BRRSq3GemBFc_Q_g08411778909461","eventId":"964fc204bc6b4e5dbe5755eaff059ac9","corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB/type/start","EventType":"bpms_task_change","businessId":"202605161331000017243","activityName":"研发技术人员确认提交方案","actualActionerId":"01190846452221394385","agentActionerIds":[],"title":"张新怡提交的技术方案申请表","type":"start","activityId":"ffbb_66b4","createTime":1779065001000,"processCode":"PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB","bizCategoryId":"","businessType":"","staffId":"01190846452221394385","taskId":101208140285}
2026-05-18 08:43:39 [XNIO-1 task-5] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 08:43:39 [XNIO-1 task-5] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 08:43:39 [XNIO-1 task-5] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779065019054, msg_signature=3951e5c0798ac44d531923db6ad4da2fbe1aa6ed, encrypt=cuXPbB+qCqLqKNssY8xetfQPEa4/vsFlfimLFBn586xmaD6bqjxsTHWvi1jVpd5h2CFChCtqgniMIqueHrPdhw==, nonce=AfUcHUQD1efB4klY}
2026-05-18 08:43:40 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"151fc508f6363c520ea6b9192cb23a73b1fd1090","msg_signature":"151fc508f6363c520ea6b9192cb23a73b1fd1090","timestamp":"1779065014023","nonce":"PxO1oGmx","encrypt":"FBKoB/nJUq8QLTEfavJwaMysmUAa0+5HacszHptfORq/bsgYOM26mx3DwhaIGzh9ttEw2fVDl2eV5FqyvjBOc14/AxIDtduB79cDsrEAA1GpEiht116dgzGBrZLfJf37C9g6j+UBhaMa5+NjplZe/mW4MoY8+mNTJLocrFENh35Jo+a97kdkjPPww5eg0tU151jpzv2OnPystg6CELg2FwS2nkj2skdpOHH7F3iOfJF2QcJZJ4nmKYfUAnLziVyKmDkj/4gklm/qWvr5vA3SxzZPLNHg5a83msGtj+9AftgXjWrWiSJsBuTzgzgaUq9essoNUJZ1ru6q3FbzGQ6UNLEa/GDJXADGXqPynjGfi5maFtd2k/k5wGsyzGv/zgrttEFTuHMlY6xOkWcQLQgarbgEGyipaDzP5ma5QXWA0mi1aXhx2rBa1YY0YoMTKkff+2pLVas9U36kb8l0XVVt8iQBo/PU9v/N3Of9nSr0r7/T5BUm/ClNCHUxF5zFjqfrzkSo3G+A9As0Irff96mnznGPrrz4/QyKDwouXgtqPuwdAzBFMvSKdKGq9IpBOYA1pqSKqG0vGtwYKwZuD0A9YaW5mzc0gARyDcWqHeC7odlUscpm0WpbBtw3o+2LPL9Jlu/slhhqGtfKlcP3hwsj/gYNLRqEv5E621Mx22JhfAv8vktDSC4WlyhB/Bs8DWZFtYe/Pv3BrFL1KxJXqaV9p97jVfyNnf3hpoM8lDe5K/K92qQTuAdPmvMDne4NYQDMzvA4BUerVIIFeuGnC3Qm9A/G8XFLFrAbJDCAyshciUZIy1qQyU11qfE9gBy4/Z+C+YVhVev9dEYH6lgAytyN3ZCpCX7IGcPFj3jv8UhF8lQASZh7lBeHp72tvCtAJWVfgP8qU3IbVJBqOlFd3dKwZjsJMu9DuXez1PZXl6Y4/6kpN3JskVtBtxh95mIH0EVGJ4s55y/fmCHO2YhTg8EwLpJJyBDbxEWiZ9f/XFjps7QxQUDSaDWwJxjDKxI7WlU1uu3T68TSt723f44TvthuS2PDEBKSmMwkTMkgApJ6xag="}
2026-05-18 08:43:40 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"qKnJo9BRRSq3GemBFc_Q_g08411778909461","eventId":"2c9565538e3b46b0b4a237002ead56cf","finishTime":1779065000000,"corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB/type/finish","EventType":"bpms_task_change","businessId":"202605161331000017243","activityName":"办理人","remark":"","actualActionerId":"03462113426124233873","agentActionerIds":[],"title":"张新怡提交的技术方案申请表","type":"finish","result":"audit","activityId":"25d1_3948","createTime":1778925260000,"processCode":"PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB","bizCategoryId":"","businessType":"","staffId":"03462113426124233873","taskId":101156217321}
2026-05-18 08:43:40 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 08:43:40 [XNIO-1 task-10] INFO c.r.c.d.w.SchemeApplicationBpmsEventHandler - 跳过方案申请表 BPMSeventType=bpms_task_change, type=finish, eventResult=audit, onInstance=true, onTask=false整单请订阅 bpms_instance_change仅任务且非 agree 时不会处理)
2026-05-18 08:43:40 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 08:43:40 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779065020651, msg_signature=99248a0fbe146e5b0c5c84a9c9f6f260cce255ad, encrypt=zhOdt6t9puYa1OqLY9Jk0yjeG4I4YarWoV8JBuzjg0P+EhHWKZAAgiEgrW+5LhRYcPxegD6Atg53dMqcexW0gw==, nonce=RlYjgrnfVKE3yBMF}
2026-05-18 08:44:07 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"53af8acaf7b0ecf05f2ac7cb31af738f95936f55","msg_signature":"53af8acaf7b0ecf05f2ac7cb31af738f95936f55","timestamp":"1779065046707","nonce":"JPEPQP6y","encrypt":"KXFNdwgUcJb0VnnmdYLW6oN4UlcKr+qqGP1AlObGmObNBxb6PupKxD0SsWcG8VHOTRtcTn9K8bnDW8pqc99SU84lV1r2WLD1pSM2UJ/WBXzpEDRIhshJTpFU6/T/RCHOmTuAhDhjT/sfMMrLCYptVrDL8kHWyq9QlBXWkXLwdpvT6p7JiQFasALEY/tC2mrWIrHMOBg3Quky+Qd+k2UvC6w+AEmvMDzotesDrG9kPoNyg8Iv9YbiYmkdBSGOghfxap4BIdBrSI+M32NTSYa3fgPDLXCBZBH9VzfVyRH+9zudsqbwH0RRwcLwi62xzGzFNIJ1bgW7/vYrWG0/XLkkLvU921h79PHNPbFifHW4pMKgs038xmIgKNs5PA43aOitVkkLVTfxsIi0b5ouL4qotirqWzdA4q9R8bXpq0TOnLXj5UExOEI7r8BAqKvipKhglvX562+RXckRsfdio+8gXLftkyP/6EOr9IZMQvqGE/6NS9z7PnPY79wXxDLYXYYF+YkKP6Bm0i+U1RTK2PrnUXy9TZ33C8L0d0qtEg4kN+jAhqSpbQWLGmYgWtkh9Py+ffkAKp0j11xDkJ5/AQ0eTNyIoNjmM3X/J577cjuwbQMwVwvzx7/Xtux2udwN5y1y659hO2aKj1vYHtEMhtkLbZQPab64hWCznXQ3yLMr2OSPzVVIdOZfivLSXVb3B5dgdrvn9yYVQLIONzffSY4NgSFqaM41GIZbpGODUJhtKfs7moxNuwZUhWT+4XNfrL02TngACXkYoXXpQ/BTo3flfqNHhbz578oQT7iBAX00gKAma6N5I+O996k2MduDhaRSYNQYUos4FYPEMJlIOWAuggtXsCTpN4pL+CVoHYxtvCCnmt/sTTf88C4PSqrw9rNMGg7nFAygHsXpDbQej71rQm/HuQy/42iQvPbsV6EKcx0MyOTgqKQx+ngviOZN8Tzx+JfdSCo8SU3hGm/mYioRBQzJJIVRGJ4v7hJTyNj66stYjUPdxukFVp0z9PKoszFAFB/OMeywx8j0WkuDzXC42CZ+B9mAvErP3T1/MCnkOF4="}
2026-05-18 08:44:07 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"qKnJo9BRRSq3GemBFc_Q_g08411778909461","eventId":"2c9565538e3b46b0b4a237002ead56cf","finishTime":1779065000000,"corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB/type/finish","EventType":"bpms_task_change","businessId":"202605161331000017243","activityName":"办理人","remark":"","actualActionerId":"03462113426124233873","agentActionerIds":[],"title":"张新怡提交的技术方案申请表","type":"finish","result":"audit","activityId":"25d1_3948","createTime":1778925260000,"processCode":"PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB","bizCategoryId":"","businessType":"","staffId":"03462113426124233873","taskId":101156217321}
2026-05-18 08:44:07 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 08:44:07 [XNIO-1 task-10] INFO c.r.c.d.w.SchemeApplicationBpmsEventHandler - 跳过方案申请表 BPMSeventType=bpms_task_change, type=finish, eventResult=audit, onInstance=true, onTask=false整单请订阅 bpms_instance_change仅任务且非 agree 时不会处理)
2026-05-18 08:44:07 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 08:44:07 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779065047037, msg_signature=cb8d08e20dd2bd53f274f44102a6d11531120db8, encrypt=mI5mn+MxHeD4hlBW8N7c7/FPWtv+3gMQw33E+UgzGSZ6Y/7yRiXCoivnNjCuQVaZ1WKEckWXa71ILEd+tD8mSA==, nonce=2kpXyq0M14ie9Nqf}
2026-05-18 08:44:07 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"508f5a217d52b8c82d50fb9644e953a71a85115a","msg_signature":"508f5a217d52b8c82d50fb9644e953a71a85115a","timestamp":"1779065046761","nonce":"ATZhGQjr","encrypt":"Ga9seFWKfbh5sLt/i2pbqz/4rJ+DOiZKnDO44rJY7X1tud0WbDSk6THp4DAyjhdRL46pR8tF5BjJwHRaJ/xZWP09J914zXC3jir0Ov+IjCyQHTmx2MEiRM6xzTnjWHWKZLneLvf+wFvpxNGUuuJ5jcPCXtpTMAK+r5o5R9qXejETFkxi758EbdnOoAVstPKUkWhKOcnEVPzKygj1aNG5LfnEAHUfiN8PtcC52x5JAHOuBTSBTGjPeEwtQjrYR4yXzGcOQE5bxeK5ZXYomsneHGpCV+lhryOP/fZOJ4Z2Gae0NUm7M4K46l8OlZStvgtvDv6qQZpQLrs3w+JxvIcQOGFfQ7/qKVrX9HlJYT7bJv7dC+S8cyiQ+mQebP14rgllmayZMe+Mi0oZFJ5HVj2M30hvFxHDdP1Mjh1htAgStuxO4Nhlj5oWhrYR/ZpWTBP5wqUKAxrvrMTdkntk2YrmHRVOdPqjlGOxNu04g1MszImbD1XoZjEoZzYjg5G+UIY1hk+lQjEBjBuyORKltplEg7jRP4FShd9X1eSP/8qVEyJsSeGqS0r5sEThmzTM+xd5Y2De52GMZ2/QtpPdf9arGTEioiq4Fs2tdN3wpeDQ5PraHS44ScrudBIsrP3PZCMzPaBxS74WKGedgjG1DYrsst1i95QSgbMM7oD4aT66tH6vNugFEr+5q4mJ8GY6dhM65CDuZ7l+H9Rkziyi3w+HB2GERnexNOCqMQ+x/aHF9ggH6KOg6VBFzbandSXDbqdXWhNH4lghvUO6RHS/KbKbLcwjBSH03oTK9AcaDpojvB9zDwpL4gDLKQ/tAnJ6wh950eEAj1l8joX4l6VDdAlihI6NjC0+Twha4LArMyrDcFjsLH/vt6XLxMT/lalf37j1nsZpqitFAEmU29ufX7vac19Ns0m5Cl8gX311tMW5UPqCVoYUCrB5ima2S/PhdZJ8cg6KQN1QmX8f7FHZ5RhrtaCjJwGuHZluPwCPEgmrCsldDio3Y/pulATxw9miG6Xb"}
2026-05-18 08:44:07 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"qKnJo9BRRSq3GemBFc_Q_g08411778909461","eventId":"964fc204bc6b4e5dbe5755eaff059ac9","corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB/type/start","EventType":"bpms_task_change","businessId":"202605161331000017243","activityName":"研发技术人员确认提交方案","actualActionerId":"01190846452221394385","agentActionerIds":[],"title":"张新怡提交的技术方案申请表","type":"start","activityId":"ffbb_66b4","createTime":1779065001000,"processCode":"PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB","bizCategoryId":"","businessType":"","staffId":"01190846452221394385","taskId":101208140285}
2026-05-18 08:44:07 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 08:44:07 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 08:44:07 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779065047056, msg_signature=19ea2bbda37a333721f38981d8664edc9aa6b204, encrypt=DazfUoxa24dOQ1soxkwY8RlMK/uxrmLy26HoOXqSau7Wl4W3YIQGw0fBkCxSVKzVHcG//r4survYNJBe5lajzw==, nonce=TH8hU2Gqqh6ZWWuA}
2026-05-18 08:45:13 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"43b599e80b6a82ec9da5b39a4c5dd211c8b20753","msg_signature":"43b599e80b6a82ec9da5b39a4c5dd211c8b20753","timestamp":"1779065112957","nonce":"WvSX71ZT","encrypt":"EYP5+5f4KID4oUN7S4SL3GO1zkDxrIoMj1uIFCUm6BXIClr1eoSJMB6bUs2610V1Yklt0P+UAkbXezxNsLSRSGG09kQ5Aw1oxB6cdPCa8A8Sd3X3a21/FY6Rz774RzFoTlSrYqtCzNnEPQwz+war8tv9mdmDSjoG8KLC4YjX9ShvORlDmHFQs695KTof1bjsacTr/8yRnwkqZe2j2yVjSKxxxdbmAJjynZTN4c6x+PmB7pmWehv1nxW1vbvG9beBcpqmuKG7iGep01Rd/tb1Py0IEOK0P/2aNmGcLp0juxdQgq0yqHGw5IRO9gasNIFE2H2cx0VIbHepXQZT+Z0OIQ5sA3JKOFDJibt+TwA7GzYU95xgBsUIniiKjvLe78/4iGhpfGXFkSVAFXDts1xwm1GyUAnFlguqzwSqhAyPhXCTVpjAk5ZVPRjgD1O4FC7upsq/Nx/Cmed+HqrqXa4gXeUX83g6/ieqqUi0SGsRoCucAvcbG4zk4humjasFOjDVobUuc7q5cEaaQk2DiCY0YRID6tXB8YkCRBSYCi0KrApivsiu0PlF8m2gBydX4kRjEQbNXb3Cq5ODvnwyhZHS4QDJrrei0vivsEyDSfsNLMxMdCMQF6Nw2ZBYdHu8cxhin7FeplrUL766k7tE0Bmxk4FVLVkOKPD1NZzIUlFHNIaICiSLiubwhNmLKGMp+8B+HDlChCJzPgjVD7/tvs3qE3r/JeaKLG5Vyu+OoOt1RtILxrNP8ZTn/mFf9H0TvlNMwqUmcL4oDoDMA8kDFr5TaSutjJPlrJ9liZym1IhRFURznIHQM2JU0X4wlKIptYy1Itn7iJFgAAdv8xiIOhADa+A4b5jm1V2gkFhjOFMFMZ1rOMcNr+VqHQuNhmVPnhZcBJkd2VIW637cWn7703FYB04ywtCa17ZsLGDPVC7lT08mKlOd5/VxwQkMs1KdudUaRx8YtW5AJ1UOMjZExrW0JQ=="}
2026-05-18 08:45:13 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"JKgCIslCQR2qzoIzZnUf7Q08411778920494","eventId":"bc5c3685bb93498a919fe06ecaae2e58","corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-FDF3F88C-ADAC-473C-ABCB-9EAAFECABE3B/type/start","EventType":"bpms_task_change","businessId":"202605161634000544911","activityName":"经营副总","actualActionerId":"1017253114780847","agentActionerIds":[],"title":"位晓峰提交的售后单","type":"start","activityId":"8d29_685e","createTime":1779065112000,"processCode":"PROC-FDF3F88C-ADAC-473C-ABCB-9EAAFECABE3B","bizCategoryId":"","businessType":"","staffId":"1017253114780847","taskId":101102815300}
2026-05-18 08:45:13 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 08:45:13 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 08:45:13 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779065113261, msg_signature=505512f6b7ad5c8129e4ff9782269ffa2307cf35, encrypt=8aDUY4z4kZH5cWfjfTiwHvLpBQJQDYjpigceCxAzaNtkaOeejha2q9kEX+tCYasbhwwnYF2/WGe7k4taZXEEVA==, nonce=1HsyEDuPygbImN9T}
2026-05-18 08:45:13 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"0cb550fd3367bcbbeaed4b5e724fb2ed0bbe2523","msg_signature":"0cb550fd3367bcbbeaed4b5e724fb2ed0bbe2523","timestamp":"1779065113095","nonce":"60fMatQl","encrypt":"J6F3oFqSbAY01+lxPB2mHN/DbUx9bvgpZKhDT8csLgK4yBR5e27CWMlUuxQpvj+7adkANu91SR/SNVy+pOgY9zSk/BqaCkl0Iwzh588VWA+56of25fbno30whaG/f8G1acI4EhsUmNgFXojgD4Dmw63QYKynCxpSAyOnaTrJksGyG2BtP2hT8XmOap9KPeXkamXZcyg4abgxMFAtlCW8cwk4XdLCx1VDk5uaOq9Wfrh485rfkD/H8pmNmQjb/SIVhSed9qMeRNCN1CNxx8fFxNU5DZKpw7+JSSptrE85ugcU4jlCZMd32N5o41VWkRovhz6GAYjF58ZrhGrHJDAHChWXQucnWngf9iYCHp35WRpD1CnAKJSMR6RW2n3Qs0Jpl3Umap3RoOq+jCzULonause2O5lJtt6kgKRWLK2cEaKkEXMYvSoGDhjo/lv/TYbcpY1mDeWbduA1hWV+ECvxWiBAyBahGpxziUUIEZ/TsHYt3nihZqO14ir0oIhqiww55TxDEN6NiYduJ8/nG+J8gTvvC1v5Rg/Dfpiwi73q4YZRcUom9I+Sqq55ee1FugtPk866hhefyWhXv9LXqRVL06HSP6mMrrn0vzNGrZE2Jo8v4yJq7fDFE76g7169XYN1KPZt97WPUWAufd8VmlzAI1atYIRNfEGXzsJ9/RQQO883W4CKBZ9eOFujsT6cOBk6Qb1qHNSAjbQE0OMgBE/uHJFHEjaJt2cOnssUHzvU6KPaH3iZAIEpjaM21G+RLq71gyAr/HRjKLXlI4FleuEaeDxd5jOXxHqclpQ1nfIMum6EnxiMapsug3D0rJSgXLU7wn9K+ZQSjPslK5eb0tkQ98d+FJwWbJVsIUmfGe16syMZjBjBRM5nyFHTIselrlnKQSOx91e+8Jxy8T9TStD94YGdWM/Gm2yvie99zqHsWtU92gW485HmXfaAS64WN9ljivdfUZODWhkFz0hZDA1hujNoQF1mkkYrmPdwUl5ZfJu5Hjm0YROxCe2phhJnNhecVK3YiP4fKTaNNZW3AkomCN434ZDqi8we5jRz8bIE2rU="}
2026-05-18 08:45:13 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"JKgCIslCQR2qzoIzZnUf7Q08411778920494","eventId":"6502eca8185f4c8195bea87a80abee2b","finishTime":1779065112000,"corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-FDF3F88C-ADAC-473C-ABCB-9EAAFECABE3B/type/finish","EventType":"bpms_task_change","businessId":"202605161634000544911","activityName":"部门领导","remark":"同意","actualActionerId":"02580952260533396432","agentActionerIds":[],"title":"位晓峰提交的售后单","type":"finish","result":"agree","activityId":"1918_5cd3","createTime":1778920495000,"processCode":"PROC-FDF3F88C-ADAC-473C-ABCB-9EAAFECABE3B","bizCategoryId":"","businessType":"","staffId":"02580952260533396432","taskId":101192164822}
2026-05-18 08:45:13 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 08:45:13 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 08:45:13 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779065113402, msg_signature=b651d7e1c4444e9adf24be61b9e0df96172aca00, encrypt=FB8dufTTc5Kc8JAkw+FHuDRbi8IMVinwZG9H9ipKIsESAGyY2fcVJwFu+Hb7MAZbWuLlEyhsycL8VFYOUhVAXw==, nonce=tBOFL9i3StEMSFED}
2026-05-18 08:45:33 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"3e58db1bac0ca405e8bbeb90ab02b80475e7b074","msg_signature":"3e58db1bac0ca405e8bbeb90ab02b80475e7b074","timestamp":"1779065132842","nonce":"bIPVo5Cq","encrypt":"YAhZ2QGV0Tcpa3cMi3KKqdLXGHOm5RxxvD0XLar1SGvV3BtoFyo+Gv4JHhD89ZA660Qgw62WSy9zaUwCWNPJnzLXKEJvfRE/8lvyQ4KSaVof6O7WmIj0AWpJZj6jt3Iy5PJ8UM2yo6zKNiiP/9jttQ1sjOCrcAHVU8sEEuh94oho5m59P/MDm9vXHyJ4HjRo9KduEnaHS8quXxyWSEO5eABICLdy3rHBr47EUczxO/Wc4xIXpn9Nu45NqsXE2Qtcedb25SSbNkCeDNlNMm+e7xT9vucXH3VwBeNeZ10rzmn8uaW+ptBZPv9H8QW9QsOk4zxEqSv0cx0E2oKvzgVJS7BW91HaqPjAaM+f3UevzFx73xFKWn/IJqHL+ZWAP4Ov4+tfedsk7n63T2xtWWlH7jk+U3PxVQe6cKrsYwH4PioAB0qnG1xTaxZyUyuZCgMzocW7yDmkyfqr5Jb/Uci8LXC9BBfcaFiXF0RdepajoNhILbt/JHCOZUZZABLUVrdnQ0Dr1E/xxn1ybdtmRWrDZ8WvIC8+VIjsBXcXEv2miSr2xwmQdh8zbwDsWRchXGTXqbjLKidSlIUpyjskgiHY8rU/j+TemEXtg/iZzujjWmiALfz8Hk1Nwud+H9SZ0fw107UHHK91K0+SR+Nykoq5N6KTva3Jf9eDO25F7fPPAW1i5f7VkjBlrRD7UjnKtjTkNbUilJxdmzZpr5yxpP0GkUvvEEfcCVVhQ94y64bIgs/W8rtUx3G6ZGvGB3HrzUBA3pkm4C4H4+bidCzfLLWLvLIf1g89OL3WjG9Hylsy88Cj7vJmPwJreICXSMx6GgzhLSo5abRmSd/y30drbLgrkaBAJA4wEHj/QpQn517/VyM/wmxdvjRHtS0Urhek4G1odkPaA1cPsxykTUxOGNmfbkV7vKyyHtzGkikbsYCcf6O1Gidl2TLF/7N/uUWknqHNsRTueTYuAOlICrhw0DKwsg=="}
2026-05-18 08:45:33 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"KAZXa5tFTaOO8AtVY2QUvw08411778920716","eventId":"949c5fa9e58945468f8ceead2d47869e","corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-FEC37380-3410-4EC8-8638-17844A89DBC6/type/start","EventType":"bpms_task_change","businessId":"202605161638000369846","activityName":"连续多级主管","actualActionerId":"1017253114780847","agentActionerIds":[],"title":"张茜提交的用印审批单","type":"start","activityId":"d4b7_f54c","createTime":1778920717000,"processCode":"PROC-FEC37380-3410-4EC8-8638-17844A89DBC6","bizCategoryId":"","businessType":"","staffId":"1017253114780847","taskId":101087267117}
2026-05-18 08:45:33 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 08:45:33 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 08:45:33 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779065133167, msg_signature=c06bcbb9e014a31fd27d4269f286df131e655587, encrypt=Dq/DFJK3WUf0+vsVxbCmA3L+CbEx7wa5rxzQ1bQR4FrCYXObdRTZiNP1pvE/MeumYK2+WPlUTFE0NzPUh/QcCw==, nonce=4MRwyxbHvZvuQCDu}
2026-05-18 08:45:33 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"5b8b4194367686cab0a63614ff83f3136be6625e","msg_signature":"5b8b4194367686cab0a63614ff83f3136be6625e","timestamp":"1779065132847","nonce":"BfBBSSlr","encrypt":"n5X5/Cqd1dsgDLH2CoAVpxEpRRv0LX9wLdfMx+qSBfkT2Jq6+w5IElUA0vX/srGcnpRA2DsoieErXDJN2VrFWocY836zFwtLkfQPr6ayOhrXn4kzVpFds4GKUF6jr1gCAr8Tb1h+ossedvBSnH9gESkn3/5D7R1xOLwULLEMKw2zq98YIroeRqB4QMpl7siPxlERho76krodZ2Nx0pFnxS/DsPCECaqACo/tXInO+Js8/HyrJ80IgSP9ctFDwOEQtcLlXiLrrobu/teI4Or89s7WcUsDe2yIAfkfvCb8yU7t3dBoDM+c8EbGPdBZkH2iuC1TvdyeAN2W+POtdbXTHxnBe5D/jE34LCVRlbqWOMte2zkMPOIzJZW/TSm4Eijg4nIhIIx+bxWo+qqQPYAgwdZDVL1eIvTaInu+fovEMAKUMlKW40VI7314xIXiZr5mzHVvMTdrRFmINOe0KFCPfjNQ0hqfRnjeEgeMSrpGiI+0LD3HB5GtZIZ92FcnjuyIPjnszwFywi3OlmGp0HAP3dLtykNS8ZJRKFOCMpoC7USpltwq2lsRIrfJgC81JMJPqci+OAGDe93QlgXeBKaMfMIR0Pv9YixAuBEpv38rB+cJswdDVQjX6afVRn+atsS2wMwas64l0Q9WGyWcNQeDALM5TojQygPGbUbaY8mpx13SSxuacHXhAJ8rajyRo21/yBC+d+9VX5HOcnT3r9/l2C3NOY6qOHxE4kfRq8+w6CHKj8uDrVIlMqdZ8PO0+mxf8Srh7UYW2W9dOP4jfN8ObzqCmlzCKUXVnXXluJsMMBv7syKhAatIPzVCc5I1iqZIzzq3R6xgp1AWh6WGzI4/wvLyBR+JykvXvOYJNW82nxEoD1STKg7xenRAz7MDH4aRiJVY4Bxm4Ol9HgmnC33Cysgk6wBfB2cysSvtrifj9WEziTWfUng2FmXkxJwC2rhf43xJGK1c1KX/dWRje2uNhReCZ0ulP0xQTqHG5yZB54t8EIQiaGAhOlCByhRQfLiie9Irh/eNs9Ebs5w/kcZG8efGkfF9Wr7E+tbw8+cYFCg="}
2026-05-18 08:45:33 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"KAZXa5tFTaOO8AtVY2QUvw08411778920716","eventId":"a5ce68c03b9b401d8c7cdb70436ad0a7","finishTime":1779065132000,"corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-FEC37380-3410-4EC8-8638-17844A89DBC6/type/finish","EventType":"bpms_task_change","businessId":"202605161638000369846","activityName":"连续多级主管","remark":"同意","actualActionerId":"02580952260533396432","agentActionerIds":[],"title":"张茜提交的用印审批单","type":"finish","result":"agree","activityId":"d4b7_f54c","createTime":1778920717000,"processCode":"PROC-FEC37380-3410-4EC8-8638-17844A89DBC6","bizCategoryId":"","businessType":"","staffId":"02580952260533396432","taskId":101087267116}
2026-05-18 08:45:33 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 08:45:33 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 08:45:33 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779065133191, msg_signature=0b0f1c566e002900c2002459999a55826722d691, encrypt=VsD9OVb6tPvudNloyIIrNkMM2Y5ieWPlTzMVJG0Nc1VqBNpW/ADoQ7yNC3Jworw4L5czHKHFXvqfBDXCtiZQ7A==, nonce=qrlBiBtlKSZjzhTK}
2026-05-18 08:45:47 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"c464e1e7e4d359f59d2a6ec89c5723dcfa7d3c35","msg_signature":"c464e1e7e4d359f59d2a6ec89c5723dcfa7d3c35","timestamp":"1779065147219","nonce":"g0yEIztf","encrypt":"oQGmkxECQoLfYUzEoBRWZu3jAxdjMPP1Rv7QuSi7AinNYLXxs2s4/+rEMdasGKVfR7IX43qgm7r+P/kOpN+xER7cqUyt78HnPN99Ct/dyH1Gm49dL6Wf29iXzANLlPdsCitJKxyQArxQXg/2W5UWpvqNyoCZU049M6r137RHO1oKcZLDkKvxCumlKlMbw1W6RiQEDV4Ihx1F9kYdbZG+7fSTBLsiV+Qgf1L76/1/q7bess+5csmlWMFzBG/U9P5vcrJKdm8baQDxleUYzkP9mz2ft4YE93kBkgaRoyzcQwB1wA9EqPqnKvvAVeGBZfD14dmoC1ZqjeQEtuBMQgT5m90zkLqYvVG4HqGJM2Dt7E2cLvdSU2tj20TY/5V2QtvHMk13BuFl76B3tuVjd83niEKSK2IjZvzstRxHQAocjew8u6VAfhTTnUkDEdmeWsvZ56fUjgZPiiXya9ZxOc3eQDE4jIk/A2BAfYU7+5+RaawfOSGIIqfZkjhk0Pajrxrmpy6ZAaE/B/e+prIbKN9lGx6KSFHxFaJlkOq5C+tBPpE3/+fQZjr0T5ZthmWuiCsHM6AhwEiWrSdKnDday2AjVYr8dm2e+D58MRizMtW2GK9RPWiaNIiccLIyQnNZstO61wmxeSMw4vY05IkEEDAP3NZDr/hSOd2PH4zzORncieFfWfD+n7CFpDlDowjWMmuZ+Ss+ky3aQHjE0P5OavmlBExeEopnSBiL7JdPu+5jLs7MK39B4fzHOzWdqXbQrFKlV9g8xhlR+wXe0oZrfjCau+zLHss0muEf+Pb4gCvNb5uG7zKDLJZ8g9uvCi3qUpMUCSv9pEKsKfkxOJR0QS40sMSJkGu1qhaYqKPuleX+R8HgBCrgdXRzDz7JbhFpvvAeNKj8hZEiebkQQp423u86zY6BeZTUD5eJ3Z6ZFk3AXmazdbkcC6s5NzVzH0KuM0Z0FBopouFAUFFer9WBFGJLXaMMakUE33uXpU7vMjaVYkHBZaH752KKdOGFbsgojSqOm1d8sMfCZggLJ7/BPsZPoZMf5KdfY4Vsf6wMrufpfDo="}
2026-05-18 08:45:47 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"zXa8jMa2QO6JJBnfFHi0zQ08411778918891","eventId":"056e633ae3974d528246939a73ea291b","finishTime":1779065147000,"corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-FEC37380-3410-4EC8-8638-17844A89DBC6/type/finish","EventType":"bpms_task_change","businessId":"202605161608000119008","activityName":"连续多级主管","remark":"同意","actualActionerId":"02580952260533396432","agentActionerIds":[],"title":"张茜提交的用印审批单","type":"finish","result":"agree","activityId":"d4b7_f54c","createTime":1778918892000,"processCode":"PROC-FEC37380-3410-4EC8-8638-17844A89DBC6","bizCategoryId":"","businessType":"","staffId":"02580952260533396432","taskId":101154557980}
2026-05-18 08:45:47 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 08:45:47 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 08:45:47 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779065147574, msg_signature=9246ee84e9c5aabe7525ead2a9c0b39ae4e7e1f9, encrypt=J+m1HvJSigaBvvS8fssPRzzPsPTRtSLxDLIRTAxm8/g1RucL2yqzl7uBnoavIK6IZeEs7fsab1mYyON7ZNR38w==, nonce=pta5GS7eDDk4alc9}
2026-05-18 08:45:47 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"48921919889340ad3ba23da6e59c4b4c75bf5854","msg_signature":"48921919889340ad3ba23da6e59c4b4c75bf5854","timestamp":"1779065147327","nonce":"SXOInfxz","encrypt":"dVrMPIoa+IB/nn3T7ef0wm+rFzvF1DmN2AL5c5PGshZT2bR3fHbGOQCy6B0ANTsGO4aVTIdMztnECI4ZQoc1U9NmOqNje9LA/f9BX9I7+HsB5HIOtytrqQsT1vkXflL6uv5qZTb/UItbBTLR5jNIszB/U7Ef500i2vxo0xV4CkyY8qyYdaRRaLcsE3+cg4VHijzUclNELNKQwt7rq8EHjewThgckcgVphT4BT5RWfkpZWBxJQqmpDNTKwmEGlAcOK+uap00l6r4L+TCjWWerB5mbfdPkJTIQnck7qFwJmufqwX1dHO/H5/IyVJWkbx3ayrVg0tD3rcAw67oYXgaP9g4l2tQc+ptTUMjbFAJ/ZedyJ5xo3MfyBCzvfQ1pk6mMP7G0T0c29g8JM8Q98J0RwoHaC2ycf4NPXBLAv49+au4e1aiqfz7+CLbsic86C0oZrA+9V0ZNAUhJGR2R1IYC8pvhIIl9+2uc7je0GyS8ULwP5g/6HVTuiOMVlyFJ3ypqm+ldYx/88pmYc6HUYY450ZssLnIQ58D4MNKygO8MU55Nk4Oh3Ch4wEWy5MTlvdb9tFVSQp8NQ4InRuRmABVeAKhZAV0MQutsOWBaJHjxTomIyAvBnUMu3RK1mJ55qwKjbhTYuL0F/N3bSZkxbGBS39uOnFNn6IntHAFN7kD2dGGk/JC2Opxl1Q7hV4wLRHgMMmyWu0/miU+7efBPgLz9bMkZM1556HXk5RCOlQyuHW0atabF6STqzuotrM7DbJCdTiB8PxOGgeTUnGhJEXa8qSt9ncWTyD3eGfR5af5oiyzta37tIAH+sqgmoKAu1+0XIAPdE0JLjgRWwC131dcacJSA0BcvM8TjJQOv7QD9MVrZzJ0AmYKFt5E+4mLEtuc23zGUuXsE9vFEZ/y6MlrNKv8hG2FOdgY9kJOLizaiGFCRiHRZgY7J+W83YknJKJPJzZoGcHoC7Gty9EkI/7qXUw=="}
2026-05-18 08:45:47 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"zXa8jMa2QO6JJBnfFHi0zQ08411778918891","eventId":"0d037e11fd954c4cb2bd6a2ba6053cfb","corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-FEC37380-3410-4EC8-8638-17844A89DBC6/type/start","EventType":"bpms_task_change","businessId":"202605161608000119008","activityName":"连续多级主管","actualActionerId":"1017253114780847","agentActionerIds":[],"title":"张茜提交的用印审批单","type":"start","activityId":"d4b7_f54c","createTime":1778918892000,"processCode":"PROC-FEC37380-3410-4EC8-8638-17844A89DBC6","bizCategoryId":"","businessType":"","staffId":"1017253114780847","taskId":101154557981}
2026-05-18 08:45:47 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 08:45:47 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 08:45:47 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779065147641, msg_signature=6314484061fdff8497f65b1d5e9bebde716cfcad, encrypt=wtMMn5d7xJnVEZ3r3lLqzM1Qz2wJ1ocB/iVWXXiSD4wG/sFzUQxRC/rBsPhHLWXcReXzNUgL+XcayqPTMjCiPg==, nonce=nRQ3eTsPE338pJN8}
2026-05-18 08:47:04 [XNIO-1 task-3] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"52df9877aeccdfe89752fdd46784be64f52a4f42","msg_signature":"52df9877aeccdfe89752fdd46784be64f52a4f42","timestamp":"1779065223916","nonce":"pkDqn4f3","encrypt":"QOpo7urUo3Ap/Leh7+YJ2cFcD9uKEbO9if9xngyepnaMufZSjFxpAHSp4+q5/qOPJuhoja6kkwXbuQJs4fNgRRz44jR8EeoGUuDblksZnxBEzyHcfal02ya6zmqhsH+la9hBPhRnE68dQBh0TJvuSGfbN2Xg9e95Ca2jkbEY4gGrCj8gm+6StN9neMm6nk/Jj9jPVjEAIqBuHKKWhDhd9x9n8KgLxhqLtglzQVm6gcELDxKkdgFDMkudAUbE0K3vDcys14VrCnMCSpAPA73secxPSfwgvUGOtZ9NWKIKHfUXpZTNxOS/4EwlC/+TXyI7AM5Y7cvTfw1eNJWs6sQzd1BgeLuzKt7LmhXc7P8kGJzyDlXdLLkVS5DsRC6BdKSk4oQrrCnHCHK0/B8hFatAaY0MqnqQct0WthJO2PAhta26IP28VLrPlL64Vj9aPLxj8k2QyW+MRFX0hDAv4sVwwnJJFAz6HZ6tgnCKSqQmgX5qrIKVbBRjXNJghIgpjoi71Zw57e1adAINq+TzmqkBXhRi4BgVqt4j6ULI7OJmt6kv7ALP/k77Hnibaynvkc3vxNPy9EWbk+WV6sN0T7bgC+K4F7CqrsgNMgrvkvnEe93AU9dSezn/2CqD2uQAJhRiNTcm6uzM0gl3dR0XKh6i12NFVfL/EkMMaspXLYjbPRWgn9D+HBimoboptL5ItjNNNrc5q5Yxb0MKx97azLcdqwSftRjhhYvty15lk3JMxz5SnNgcl1NCWRxXkWASqYfAecYeJ58mtLJimyRxwpZK/zacVfJDvZkVyJALojJ0rZiibQd2Wm8mahd+dYr29WDGtIDWCS3/+DsYu2DeoA5/bE2kBthmKEY1Knr2b+Zici213zG5ddt7jMnX/v0guR+1F8RdSTrKgaZWyhogD9hdJ95Fjy+KLX4VS/3fi7EpO8JxGt+uHB1OQOYQddkgBngyXCkgJGes19llvYdafQaNjQ=="}
2026-05-18 08:47:04 [XNIO-1 task-3] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"RywCD4-WSe6yxrpgQl1YGg08411778914559","eventId":"dd46634f896b46e7940f7922e7ddc1a6","corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-A59BAFBA-8AAC-4943-B4DA-3FC964AC47D5/type/start","EventType":"bpms_task_change","businessId":"202605161455000597391","activityName":"生产技术部长","actualActionerId":"01201038164023402380","agentActionerIds":[],"title":"位晓峰提交的售后联络单","type":"start","activityId":"b689_7c0a","createTime":1779065223000,"processCode":"PROC-A59BAFBA-8AAC-4943-B4DA-3FC964AC47D5","bizCategoryId":"","businessType":"","staffId":"01201038164023402380","taskId":101102887296}
2026-05-18 08:47:04 [XNIO-1 task-3] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 08:47:04 [XNIO-1 task-3] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 08:47:04 [XNIO-1 task-3] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779065224281, msg_signature=f41f941364bfc63ec4b274dd10827c477ade0c03, encrypt=Lfjj3SiD5U6iJAuegr4KjFksXIZTwbjR6IFMY49El+GGDj0vP8cNa+4vmGKhsmLvXEK2etFtkdKC+2Y8y6Htxg==, nonce=CMI2CQIrp2Twir8p}
2026-05-18 08:47:04 [XNIO-1 task-3] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"2ecef8a28c522ab10e13661bc48ba6d10130432c","msg_signature":"2ecef8a28c522ab10e13661bc48ba6d10130432c","timestamp":"1779065224084","nonce":"I86iOUDE","encrypt":"3iarZzmYF5E2lPCo33753FcVZUwFvMhuobSoZ8DhohcfL6QgR/Ayln1DgSEKkPE4HDdWaA+NeQIX16pMujn7fBIGbfRD0nnab1fPtb3LoXfY3m/DxhkmL6FkGN4iLWiR4YpICjN8CGEBsKz9JbBGga2uezAlCRUvwtnEs+0FYR8uJTdLUUeSDnxtjsMdAhZEiLfNeBvUkcoEdimgsfrovmoJeFpd9qDksNQ9l8cMgqDdC8i1KlQiFK8ecksBa4MZ0+fQckZjjTR5lIlLAwJLpSLMv0vh3AEHOyjNj6QhZhKYUB9UZV6Z3eCpr6bPUpc8lBcSKS2oqSg2g3OjX/JsC9SSsXywyQXBWdkQ9geHBlpgPsxQ45rtCBV9BUPJqgwRjbiTJk+noVmQA3slpSUBLqWuih10RIRIyN/3eq3C8CSgMS3udSXecyb0xFH1KtsK3mmJgbl79tZGQg2v1FTJ2HTi0uiLjHoU/LvXOcQBKYFi8iVSRD+SQ0dckdPSEU1/RfqU4CkP/CpuiBG7s7vMX/x4nU+HfwmlzLXvn+wI4oarnAElse60anGm5Mes/QramHri0iZTJz1Spp0URySOKHmkHzkw18AG5AMFOLXLB/3PoHMHFi2gDw9eNYsoU0okZUNf5sStOfi3cEQPsV2tLccoqMChEk4a9F4Xa1lWm9Ld6DLBShnfT/PX082+4/pFKTC4sDL+o5P+VGqnfXCRweqGf/V867gHNYfdq8qAZsaNx6AeBFs4FdYiz8vbYy+PgdIm/9ymOBqCaTA3+GlWMktTi/ZLyBYQfIEdaPUk2iVm0+MbnswrlnmJmn8i30RNYrEoTpbryEsegwOXZihCjm/Q1NIw2KDxpxGfg7b4QdhnMlnDbPhxWiOHiQ5AoXlyCkBDvQ8v0fUdoatgz/5xLwcg9rxsQ+dQiqRp4PgCpJ4Cj9e4Ca/66mhMyN+q7Sm6V82pm2HeDKFiYixUczXh2q66MqldzBRnJE6TIGYDEvlveNnF6Rx6iGKn2CCX7b+m2eL0NBsHLzguCUHx5Uh5om90an8yrtAfJPb2RbEd8SA="}
2026-05-18 08:47:04 [XNIO-1 task-3] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"RywCD4-WSe6yxrpgQl1YGg08411778914559","eventId":"670e81d6f0234f5a846219befe190800","finishTime":1779065223000,"corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-A59BAFBA-8AAC-4943-B4DA-3FC964AC47D5/type/finish","EventType":"bpms_task_change","businessId":"202605161455000597391","activityName":"部门领导","remark":"同意","actualActionerId":"02580952260533396432","agentActionerIds":[],"title":"位晓峰提交的售后联络单","type":"finish","result":"agree","activityId":"1918_5cd3","createTime":1778914560000,"processCode":"PROC-A59BAFBA-8AAC-4943-B4DA-3FC964AC47D5","bizCategoryId":"","businessType":"","staffId":"02580952260533396432","taskId":101190804299}
2026-05-18 08:47:04 [XNIO-1 task-3] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 08:47:04 [XNIO-1 task-3] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 08:47:04 [XNIO-1 task-3] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779065224440, msg_signature=a22124125d293d7cd10626e761bf6857b70edc75, encrypt=uBchH/FqAWQfeskoBAt7GrHvYA7w1dISMkIqrI5lyR8GHl2x/MFom3LhMIAxt4FLb/0MBOTYMeyz7vywRub4ag==, nonce=YPMYgQxpioJutSeC}
2026-05-18 08:47:25 [XNIO-1 task-3] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"fbee3ef8ba676d11d1540486cd07d804c3eee493","msg_signature":"fbee3ef8ba676d11d1540486cd07d804c3eee493","timestamp":"1779065245377","nonce":"BVjV0XJd","encrypt":"Adgsvb2N0fKZD6qiGjnC1+n0bwzzOtfGn+UDYOrmJtPUUPjVcv8ztYCGdI1Dps1NWZ/y5UHCEI8yQX4Lauu2Cp96pi8cW6WbObBqXMyhv4ES1zv5xPIrfa7cYK4vTxlIQtkSfh2Q7Ir/tyJQSmsjkOxoOgtZPyvnRWBVTsuRGEgGw0IdqClhop1WrkHPcNNBXKxPfrli21jF8ApZiyiTeO1aVrO6iAtLzLlTd/BHGeoR7iWXwq5htTYBFLYHaJPEdTBD3kt4AhMjKAtRSycA4RW7hPOS5hhxj9t7cnwNLdecsYlXPNMMGiJI2dFmkMLsQCr+o/vbulVoxA8Ft8QTocG2wAnrDoJYAt1CQytJKyT+mOnw91q1SFKXWChDfkLXqsJFl6dh/KCwlM9KlL6kGiEjGguWd5TqJngjapBecTRP8fpRyAJRa7EG0cegLFqTTVsFYHCHQgaLB8bJT2OrM/C5tiR/tukMdwnBC0w9dQT3WJB7YE4bisjIcDLu8zFi+3RJq30o09S8qdqu6LWOoE48j4xSICCjsSZSE/bWx6p5s14ZWRDmQLuZxFfk8OvMm2OzQoyz1p37pf6wDQCNu1yfJoRVJ50MvfG0rmsFlsxmJya1nu7IcmSpt2/IsL/SGqw4isfYGXPCfvm6sBsaas0bQFoipYLfcE6wQGZqTgre4xKb/yT/m8aoAp3bqSf6O+GjVKSCuUEI+H23gTNt+2MuOTZ4YAzQfaAY6jLJmRJdDo4EDR1QYY3s58I1L4S4/FhGCq3IiYu8a/kiQOYNrIR9pnNA7YUAcdPxe42PQV+xFV3NQgX1QjSHr61xfC+bmeOQw4mrqZjH/m+spjhGx1oPvMCebTlBMxZyVqMf1BRbQRGEpRj6fTJK9SsSXN1t8l6LTXRoaP5oqrz6D+aLNxBz78vy4/dJm98dPtDOdmVscj+2U2iL5er3+ij+n7n5oEBgLIiAXeHKIxsShq7qGIc+rurlqM2r39KXMUAmDFIUnaxiQ8xpqqe9dpS9leSx0Deum404bbbZbFQ98uZuDLVrc7R5otfxc+5Y7QYqRsF4uqGz/uDGlE2hnxWSyY3Epv/ELiKAuVGJkgO8YcKPww=="}
2026-05-18 08:47:25 [XNIO-1 task-3] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"HHIC0OoBT8OYiZJ4jnAMmQ08411778917283","eventId":"78489aaae61543c791400bcf2a61e3aa","finishTime":1779065245000,"corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB/type/finish","EventType":"bpms_task_change","businessId":"202605161541000233493","activityName":"工业销售总监","remark":"已确认","actualActionerId":"02580952260533396432","agentActionerIds":[],"title":"张新怡提交的技术方案申请表","type":"finish","result":"audit","activityId":"0a8f_4e19","createTime":1778917294000,"processCode":"PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB","bizCategoryId":"","businessType":"","staffId":"02580952260533396432","taskId":101086411175}
2026-05-18 08:47:25 [XNIO-1 task-3] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 08:47:25 [XNIO-1 task-3] INFO c.r.c.d.w.SchemeApplicationBpmsEventHandler - 跳过方案申请表 BPMSeventType=bpms_task_change, type=finish, eventResult=audit, onInstance=true, onTask=false整单请订阅 bpms_instance_change仅任务且非 agree 时不会处理)
2026-05-18 08:47:25 [XNIO-1 task-3] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 08:47:25 [XNIO-1 task-3] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779065245692, msg_signature=b66d57115b2cd3172f02d82ae5a8bbf9bd78b38b, encrypt=96ZH20NtOjD/q+uUzY6Y8F16flqx4t+FETuXJ6x3W3xCy4kW3mm5FC0SsFaY8ED+BZ8S6BzhmEhVu7Oz6uHlOQ==, nonce=eiO4hpwTsTNPgys9}
2026-05-18 08:47:25 [XNIO-1 task-3] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"e0ed5f51a64f00f8e02425e10323f7a27d3a7eb3","msg_signature":"e0ed5f51a64f00f8e02425e10323f7a27d3a7eb3","timestamp":"1779065245516","nonce":"Gw0x8XcO","encrypt":"Ryqkt9zbrAgHGfWIpojjy4Ne7OXme/Fbe14aDLgHNUfXA4pHj00eVIUX20qZ7+ZIYJOFKi+6r5g0YfP1UZOJVq3kwm1+ijYUA69DOVOdmgaxt4VdCCDR8KWRrMDBgrI5pMXxRUivkt9nkbIzmiKXcVDICN2jo6BjmOBNPcH6HPcRGqZrWbtVQhPpN3TuAXsr2qr+SBfXDIEm9CIUtEDQxn/CHnc619DWvcz/nmtueIn4ClXY5J0jIucBAPhGgwImBZZI68X/EXLANnwQPt6MWHlkdcHHqUPkjD6cC0da3b6zDJB0vJcgo9AKTJ0jedyVnyX+LutMFr+WF7IYX12JAn1w0tD2e7yRBso9Xrmxo9So8HU40uiBH7iqW/NBHcVaSQmrT3re1h8NHneIX4K9lP7ej9TDiLXfZjIyO+DLHG90E/Ff8XnaiPXyNFsVzdOqDuf3R/N62S37zvbkbLoSJtBxDGg6hR2sBrVEK74O2DU9AHR8icoEYXOBD4cm+usjhrCGEmr7FVpbrKmI0wG3HdtcsLOqI3vEjLYDZKLRz/0IG60wZ8YBcDCuFxhP5CfNrxFusw/JVtCv/tY4HGvZVfc4iiY9e5le6cVrZV5Dch0XMkOsNp/PzdcIqUWtMaA1yG3ZQHQ+NuJIHKWrj2Xm29Jzctxy/NXIOaAvxLFh2238E75OupXgLx2BtXatiOSy5HZYEjJXKxR0cUFT6oJWJhXl+jR5CeLHXnsO3LpTtAvuc1C+6B3GJRsvuUXEhaqUhyGTK+jB9yxWLQg8Ik+IwNfFRQ3fUSLqQuxZF5BSoHnUPs8TxOGzwGuLbqZr1l3Bfe0z1mAJDf+1cAeNHZWWCSCyGWWNPQrPjilTREX7KS8JLZ+D9hsWRVHsp/H/csSkKoZ7tMZkFSA+HgtMel4lZQOhlWrL6aHKQ4Xdm6iVbEdb9+ma6a8vYZvNTb67eOFsgeewi6qewZKQEWAXTkt8ww=="}
2026-05-18 08:47:25 [XNIO-1 task-3] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"HHIC0OoBT8OYiZJ4jnAMmQ08411778917283","eventId":"ff40bdcf73eb4aadaeadf7de1dc5ecb9","corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB/type/start","EventType":"bpms_task_change","businessId":"202605161541000233493","activityName":"总工程师","actualActionerId":"035715651324258877","agentActionerIds":[],"title":"张新怡提交的技术方案申请表","type":"start","activityId":"122b_b71f","createTime":1779065245000,"processCode":"PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB","bizCategoryId":"","businessType":"","staffId":"035715651324258877","taskId":101170493283}
2026-05-18 08:47:25 [XNIO-1 task-3] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 08:47:25 [XNIO-1 task-3] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 08:47:25 [XNIO-1 task-3] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779065245826, msg_signature=d1b231538003e524ac299a1150da1278be8cb0dd, encrypt=fj/wU1adumXsK4QTfB7Bydz3YG1LA//fN9vS07TpbV502N4rTkXMyymRqqgSQF4FbmX44KRGfr0uFuZbV2p2RA==, nonce=ONzJVmen26nunLAe}
2026-05-18 08:53:43 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"2b2c01930639ffe3abe631165e340335357e21f0","msg_signature":"2b2c01930639ffe3abe631165e340335357e21f0","timestamp":"1779065622724","nonce":"CHYinqHR","encrypt":"ZoKb79i7vnHD8Nx63/8qLYQAfmjtcIEBwkz3uebJTgB8udWAvoQzqmjufh9K0WXwTzvNpmMnI5LihvZXFhe7NuDt5X98UAwxu7Z2ah0QexEI986Y4y2vdfkm/shu5cFaaZIkfodsD0Ojf6vxjoDDIXm3zSFso/IYA/mHBbAVaJngmOOTL1ULmrxlkCFVYp7dmH8cUyGjw/8n4nEFd1KWqECfatxBgJLodIVR5FNw6yjspIscTxPO0e1X2zsHM7rpiaoUMETyEEWV0kgA3ZYctpMIRSNJwrB3FDEDKMCKK5xOgOKU8le7tsT3p5F3MTVGae/2RkL2Tf0OOFlZzTd166aikbHz0wvyR9SdQ3ZQcBdDl/dfid0ezBjVwMPggm8Ctdgyk5HR4th51/tNI8VacLb3M/ojs8dVm2r41V7vRYTLQNbu9/ZBG/XHnhxon9MAGBtk22C9WW1gwmji0tD4hESSR4wQCNXoEKENSeYJ8tTyGSSxxulhEg0z4VNM3KXU+OH+mkyewKc29t9LnzP8Jpu0Xi7oD0hji2b6/x7Bkfc4nWUCkpgrp8fWUcSzVqwjBKZWIOppUTNfqSvYDLrcFSB65z0tkjb9svVZdZCR0vI7wyiDYKVWoOwqKYjBUYyHMVweuj5Bn13GCTTiw1NokShrZWLfadERwk1COs9txBuMcnoBNie3r8e+0YM8SOBY2/ZZkwMHMN9SR2I8DAxu/uaKWjW1s+lWS0pyeN01CGOWTkpEe+Y8f1564yVYry5JWlzzZaXVwx7hiTWmvu7vqvj3uzBapVwpfnQ8gNUtwkb3J2Xan9pdRvSVY8wPXrwdQPzU7IAplfuvTKmA9ycDG/naUrRdmUKNT0X6PEli4CJK7EylRwH1f6nF/ImA47o79uhY6pxBFHhaiApL2Sjq3mwvZ1nviickqei3cBwruuaTM+5OVo5plIA/CcXckFZZeq/ghQPJyLQwW3J6YXJqoMW+0lC7dFO5NlHPSOQ/WmzuaL6wqhzMUE2f5pcN6eqD+T3R5xxEs1R8AmwX83DOg5qKYAAHRyyFBsx52HkWSkgwPXYKRm2fLfM9IjNB0GaE8GQ6em3npkyXy+/nTkotEXSgg+bhC9ThX8gHJbCbMGdvE1j8CDoEiAsX8XoFAY2KJMgmo6Y4i1CMHvZwPIFK5Qxt2A8cpNKcuNOX29ktfl8="}
2026-05-18 08:53:43 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"JKgCIslCQR2qzoIzZnUf7Q08411778920494","eventId":"13c86cb3b9c64389a74fd1b8b296975f","finishTime":1779065622000,"corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-FDF3F88C-ADAC-473C-ABCB-9EAAFECABE3B/type/finish","EventType":"bpms_task_change","businessId":"202605161634000544911","activityName":"经营副总","remark":"售后人员不知道什么原因,领导不知道原因,反正就是售后,不正常。不同意拒绝","actualActionerId":"1017253114780847","agentActionerIds":[],"title":"位晓峰提交的售后单","type":"finish","result":"refuse","activityId":"8d29_685e","createTime":1779065112000,"processCode":"PROC-FDF3F88C-ADAC-473C-ABCB-9EAAFECABE3B","bizCategoryId":"","businessType":"","staffId":"1017253114780847","taskId":101102815300}
2026-05-18 08:53:43 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 08:53:43 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 08:53:43 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779065623038, msg_signature=87948638896f6edfb996941683df41f1d7b03080, encrypt=SulxTVz3ofISPz1Sd865EdQp6vLlPU7j813LbwD4fgS4cSTuLEJf/5SLNWAtrG1hBrSZitVRVwPyF+cwC4THJg==, nonce=988oDm7M9oK5CO8J}
2026-05-18 08:54:04 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"1dd7f1de30e1b596d8f7570c2735a3071cb2597e","msg_signature":"1dd7f1de30e1b596d8f7570c2735a3071cb2597e","timestamp":"1779065644073","nonce":"qIiMFoNj","encrypt":"i/okOIKUrJ4gCEF2biocDgCf16Q/1l8a1y5AfIItvBe3aMlKNbZn+Mjeq5Exevf6EMFk9xduD3t0tGdNNMdrhV3fLhd7KHk5ANImEWXk66Xm6ONykoEBSveiRbuq9xDtkx7HVkqrDeVLqv0mP1nDn3EZWzENIHWssLQgD1+/zzTJ0xfmWGOUdGraWn0tUHImD2fKXozaBMxggBqfjeTOtTc4g/i+/fHAi5tFsv2Ofk/V2j2Kh9AjgMpZl8/jI5/tWj5pm6yY76sqVJTQ9DByklqqNVqVHXpdhE/37ByRMZDJHiu36riQ0MIwziizFVv/yVDSljZiobmsetmxT7368uVbvhokMlN7RHKnOiJv2VdaatMdh6uMmChv28y7ikMGcWRpqXJaBRh5L46tOLAFRS0B3s4PT4I5uGZLqsoGEhv4HWojL8QperQDf5DOkeN8aXZHKyGKUhRxKgCUUT0dWqvfegYiNesFYqWyGazloVnrE2e+ZKq7fcEcn4giR3HWF57HRVNiXwVlT+Jw0EL3hx/KOF+7nDifG5phO9li3Bv6GQpkDDDISVxF/Nf2F5BBzjW3yB4RotydbjYrc4kTKb1cnMwkd/1/0YJErk5/o/cp1S4Pb6NoQe8Tg/Y6XnhrH1sAGL5vFzfElF45dOVij9rftmPnlaiaT/0skHATcjvkyCxa+LLgs2LivC27bKY5RIi3I++yZQDZAJoZ3BApmgNnWsrrQfVLPnUDvkIYGhdg7rFxKGu71KY+Q3t4l+Va12NfBvup4r4Rf8V07V7XKTqoWwblTk9aCNIy2ux7+PjymOsfzrTUjqchXEMXU8PuGdAq8kRXXxJ8Zp4uYB1z3LaX7/8+f6ji+iYBEAN/i5uNMunfxdzI10okUwhO1wL+FD+b8RVf9KqX0TrQ8lVH0pjOUF4s3UufjQ3EIr9kmaVVD4B9SVhbb9IyAx/5F23jXDlisjOs2MZ9xkq9Pz9Fr2nCypPxDmsoz0XQDg8baYcyIH90LsclB6H08UVDH4fihLwbPJQqyP2IeVPLNvcuHeWEUqm9u7slbGEJmNi+0Ks="}
2026-05-18 08:54:04 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"KAZXa5tFTaOO8AtVY2QUvw08411778920716","eventId":"427d8baf727645328202f4d6c9d3a623","finishTime":1779065643000,"corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-FEC37380-3410-4EC8-8638-17844A89DBC6/type/finish","EventType":"bpms_task_change","businessId":"202605161638000369846","activityName":"连续多级主管","remark":"同意","actualActionerId":"1017253114780847","agentActionerIds":[],"title":"张茜提交的用印审批单","type":"finish","result":"agree","activityId":"d4b7_f54c","createTime":1778920717000,"processCode":"PROC-FEC37380-3410-4EC8-8638-17844A89DBC6","bizCategoryId":"","businessType":"","staffId":"1017253114780847","taskId":101087267117}
2026-05-18 08:54:04 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 08:54:04 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 08:54:04 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779065644376, msg_signature=0afb41fca17471a603ac449f9890337fa039459d, encrypt=mJb4vCZwA+DiHUtpMHkyJtYcAOaBcqUHHg0aOQ6ZjiqYH++Raxwfx+STLbvMyUnLPcTw+QBfkmO2/sKBUXzu3Q==, nonce=pTQwUg3wTIlmXwnG}
2026-05-18 08:54:29 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"1ae3a0351344a5d850b377d6b6b24c666530c02e","msg_signature":"1ae3a0351344a5d850b377d6b6b24c666530c02e","timestamp":"1779065668918","nonce":"2GSZMoJ7","encrypt":"1CPqVmjPZqYrsJzdpkR7ckxu1RzgSApWMaSnRZDKHM2cT7Uoai3p0YKP6iGtzPlVS+Hl8zGghGjcAowYYvibBuMj3OZQqAUxF3XrhJEwST7ZRQy0twOArW/J8ss7En0xH+Q4FVhKCc/u8YwqO4cZzsYqOuIyzMzaRyoQ4OyGCglqgd1U6h6Fony4kRBMvWwRceKDH5QHjJAbmAcn0y7b2W6H0mFStfDWUu96JGUQzAzX6wXloZ2ynER6TQECifCohfWkhdHfJNNeFg7AEzrGlWEpnzTb6/MaY8FkratyPQLoOSrrsXjzPXW+9o2541+hBUGhAW+Ky3CEx2FvDJ9uUVX5ORi6nNcPrP20rrt5EuQ+meKw2FfH/F5L1QqUpkhaIp+2BRqfEyIH6gTDeqcqAlvPkHihZC5n2jqIuluNXDi1BxvP/k7Js1csw2YHyvUkcu8LmomOz8KZIz7rB7mfkAXz0eZsy7iSYiVDiuFaZd4mKFjIT8jYP1kpUzGV/j3Knzl/6LLvJgX6IyrAQw5rACSHn2M0BOv/eggNXZn13GBusehcuUZe1F8EgyuIda5xVa03sudPfJCiOCBfyxHbHG/2N0hW0lXKzTfnGwlPh6g6dIalQAityiZjDzraTKAOkdkmUttl9rtKVI0el2aEzPIlCEcsGftQYM/Jtlyp3RQ4zlo5XUVMh53WeXkkfarxxuDk/KwkZGulK8TT09NIkFBqk2OA/gAPgzBnB+hi0rv/xeb4Do202Fui4tpYyyXgZ/dYPpjiSkX4Ilj7dMGCIOOo7kAjfvra3x6ZUTb3CwxGaMUsh1/+PJI/4z922bHPaq2Q0Jw+osOSTHXvM2+xCFI8stjDEeqpDLbFHsmr6NxAwyg9YJl+Jz335V1/tGPkBr0pDhlw7gJvoL2TqVfkGS5yVS2zz5sR6y/mDMHHLRylefYd5G90/BpA7kUAr+LK7zAgWl4vujfviCPx4d/gr56K4bAaFHCfuSjmZxu9Cl8o/X5ehwRbkFx5w7Gy+3/x"}
2026-05-18 08:54:29 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"9qhNpt8QQvWwUEY5nXeXZw08411778832037","eventId":"94540b39e4cc4774b8382148f2ce7d6d","corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-3E5AA98A-55E9-47B3-BA84-0D2101BB1C35/type/start","EventType":"bpms_task_change","businessId":"202605151600000374159","activityName":"质量判断整改有效性并判断被考核人","actualActionerId":"173760274129324770","agentActionerIds":[],"title":"陈志学提交的不合格评审单","type":"start","activityId":"305c_d252","createTime":1779065668000,"processCode":"PROC-3E5AA98A-55E9-47B3-BA84-0D2101BB1C35","bizCategoryId":"","businessType":"","staffId":"173760274129324770","taskId":101142674034}
2026-05-18 08:54:29 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 08:54:29 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 08:54:29 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779065669219, msg_signature=1f9e1dfa38660b8dddc97443135ee95f1a5228f8, encrypt=K2kpgIUZ5mUCT34f40hJ4PdGAHbxi9DZV05apmThq4xHNyaZ+2FslTnvGQNKmIt8ohDly/HG8BevZUQfYMg3dw==, nonce=wtcBpP5IILlRBNLH}
2026-05-18 08:54:29 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"4ee84eb25c6275a192e990c5746382d5d5c735ca","msg_signature":"4ee84eb25c6275a192e990c5746382d5d5c735ca","timestamp":"1779065668994","nonce":"WxKNQEe4","encrypt":"xYoEUNgWs3R7a+M5ou6D/A6WM1GZAhxvRqsgmYGNQw+lOIu4TauL0C5acuu++8UKf/Qj4JIUBXKbylwNRk0KdQpwRQsH/sZCLAPqQF71SM86+PHhxMMA6sbqnUBE1V90p9LOzAv3CKlgEwybM3/IL9CImRd4/ITcrgQaZ1+iBkBlLhDiqg2q2Rg3isyjBKO9lXbka+sVmF8Y7HOBiFtlwn7LIeJzIpsCkvY+bXB5aPfbiOYF3H97RTxIfhU2smwvBkxrcHF+T5XHwVAdG3vumVEgGltng9fGlzPYfO7QBhFf1+szN9lZJ0uk86xfDbDWLvjxhDzqoaBe8e6qZwbQUJGdXXcb5oXA2hcHl4oiobuNVp2ExAZAX+6ncySL+kmQHTJzfWDQrV18G71Mii3FMa2M1Ntvnq/xow+BsiCqv7Z4saI9gbADiN6MRJrBrSUI7r0x0VPgE4NHdYA4STXrgxK/qwMFFzSckWGaiSjlhbIOwXpy///+skSTZppyFnoQsGKlbrsDjesVsKNCsZvOtNGvebEeCjNGiDpeQKUfl3AtW7kivk9DM90Ihblw8aaAOeMiaO40JPF2YJwr2wXboSPTvY9sCnZ4fiV9zGnDRVzMxr01J4JIEux3gepcttVH4AerVnvRxej6pf+pO7eFD3bsFkp8xss9wr6c66z0LsNHtCVdmP7cyXol79QQscLUY3OJ1pyOFnhoHZE54UABoGy+OXS+22tL47y7a9qBtXKfxTSqB2gzvFP3SJ0dE5ttjWTFVBHttrN5RvFg8hIXU3U4siJpJgdd4f4UqIzK+t8UaDkComOgrZb2Owx6ciKl4VoeOiwAPCTdnmkVVH+m7hbuRwSQMwH+04lJzzzz/XgKOhnbwdEz71XRMsLlBDM07gdZgvyJihXjZuHY44AO/UT5u2liGVCTcKQ6pAVhl6AXvMeJ4BpDkkcF1D1oMAe3DGypSexscjpzOJ+4bHOMqcR3xXDQ9KCcb2KGm7FPjrcGlk4O3PDBazjZU76XrgdAuWzbHrtXpaaNqcTRucUtvHjKZHapF8BPjrKYhkbl1opPIYSDAhutouCMVnC8yK4KSVjOWA1C5EYNAa7EDMo8oA=="}
2026-05-18 08:54:29 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"9qhNpt8QQvWwUEY5nXeXZw08411778832037","eventId":"de92ec4846fc4f5f931542c1b2910293","finishTime":1779065668000,"corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-3E5AA98A-55E9-47B3-BA84-0D2101BB1C35/type/finish","EventType":"bpms_task_change","businessId":"202605151600000374159","activityName":"责任部门提交整改措施","remark":"已确认","actualActionerId":"010858214800672369","agentActionerIds":[],"title":"陈志学提交的不合格评审单","type":"finish","result":"audit","activityId":"679e_2fe7","createTime":1778926412000,"processCode":"PROC-3E5AA98A-55E9-47B3-BA84-0D2101BB1C35","bizCategoryId":"","businessType":"","staffId":"010858214800672369","taskId":101088555729}
2026-05-18 08:54:29 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 08:54:29 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 08:54:29 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779065669293, msg_signature=9c2cbda630fbbc25f3f2a465105de8ada8589709, encrypt=kzwRjo602CCmzMOUYovoybPSroTp8s6nlbZnQNav/Wz1QFWwsPiU41q6FQvtrdn5bpEtibTRa4sdZP4wT/cOJA==, nonce=BKLAFFWqp39M5RgI}
2026-05-18 08:54:36 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"26c8c1cab2cd75ccbc72b74bcd005dec8a29e2b8","msg_signature":"26c8c1cab2cd75ccbc72b74bcd005dec8a29e2b8","timestamp":"1779065676034","nonce":"osQ7MDHZ","encrypt":"myIB4x7nS3Cig8dBtje90/Cl3yNCLF94KDLVbnbrOHDEXlcinmSTUVdp0Zgkt04+xUExJZTYwjQwzMRbJT6AU9qEnaRE2t8SN8T2CPWQiibVd53LmAF61uQ6bj4QOdM68SpF/LeIHaVve8ouc1RzZRluqD1ZfjMTYpZ6NsDq5jM/sX6VycBCReHis+AI7DGqLvQcVs2IG1v6sNzRC0h+LlOyz/daocC3UwmNX1TP/bVB8o2kxo4MLIMvIB3+riDhsvbelehim1kiTIAOEKviUmhE/bJLapb3FFfbAZOjq/Wdrpptd4GzAO8bHAe9nH6u8UojIpGaB9mtWwow02Q6rIokVa0TnGMSJsy/ZwaaLZTAQ2OJaMlc9cqXzP0gdoghVC75o2ptpAnKSQyhqa29nAmNK6pYIFISXR9eOCDvQPUc3oS7Z1A9gCfrUqYS2GRF1MK1AbbKv6jDL+tp3uRCF7PTmUCs3Ymb64ymSR4pDcC74GEytiEWg3P7EaiO0Ifp1Iv+jACeT5C8wWBEdkvFKdkSKrnQ1xmtYem7LUDjR3Ce5v2c7bMKLICNuCQPyULdecF9o3c2RJIH2xv77XPOqmnZHeEH+aeC8JoiBYjbbrJ/f0w7oGYfWnAt3Stc6E84cs4ylw8/JS5MDjDtD2LWeTaTbtfG7aDE++KA2ICw4zrl9MZnq4RUYOXJKDGhII8SHzAgayGHs+RMypCo/yzskXc/H+bomL0tzgjMvLa+czE0dHAsgo0rj/HOnJ3Mf26xQw9BPPU8VmdMtdIPazPkYv+ptszszR63e8oj5TA4+MTymxMtIGqXHLK+IfDdFGAjeRTqpgH3dGAlU88l5Vjm4OT25/ioVRHJ5C1yrRtoKH9KIqh/BVdP4NlbxHT4PhurhebNvLgkwJyXYAInufyYMzTnft++zHtPX4te8hqbzsStm8HjiUCmDj5Ju6fYsMSNA12eUt50ozMDSCD45esF2ijW0TjI74mDnxpzukgdQDerdUPfue6Q5YqU+OZYjn+pzAVdVVeLNJdqE6fkzami3pvPu+BSO1Il3Iy1Pj/yMVI="}
2026-05-18 08:54:36 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"zXa8jMa2QO6JJBnfFHi0zQ08411778918891","eventId":"ec58f397f8ae4aefb24d964fb8175b63","finishTime":1779065675000,"corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-FEC37380-3410-4EC8-8638-17844A89DBC6/type/finish","EventType":"bpms_task_change","businessId":"202605161608000119008","activityName":"连续多级主管","remark":"同意","actualActionerId":"1017253114780847","agentActionerIds":[],"title":"张茜提交的用印审批单","type":"finish","result":"agree","activityId":"d4b7_f54c","createTime":1778918892000,"processCode":"PROC-FEC37380-3410-4EC8-8638-17844A89DBC6","bizCategoryId":"","businessType":"","staffId":"1017253114780847","taskId":101154557981}
2026-05-18 08:54:36 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 08:54:36 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 08:54:36 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779065676341, msg_signature=f5668c057606cc3add687e1751fe0a7b815317a7, encrypt=gixHPwlB/55xy/EiWjcrLgd5pcWb6wpw6eytldvDMuVC2zN1eJEvLEcApMVPmP5r/YoU3EbyAjItgbTki6G/AA==, nonce=TWnq0NhjvjAx6Zub}
2026-05-18 08:59:07 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"c7c3a36c26d029e8acce2fce406af5f1b2f80e71","msg_signature":"c7c3a36c26d029e8acce2fce406af5f1b2f80e71","timestamp":"1779065947099","nonce":"v0cORoWp","encrypt":"OsbQzle+3f5JCrxawIGnHz/tYa3BmGCCInMZcco8saENPjhhePsLin9g10c6Rj/X2QDTQuqDa4EDA7y7EmZIAtp4IfhCBySMQ+R4I1sd0qClg1EK/s/UQj3+HCErvavox8yJ//gulBQXOkgaWviHSfEpxLynmhzKXvbsRZkRhMF2+VExVxLEoyvzxqZmW3Q8p1DrlgRHRaFcQUZYzWEisaZsvJxBWql8bJbfbk9rWjZy3YbNy2ShqNE//dyu26OSHVCDpOyebUwj626UX+F1JlHDcbFzitOBscaftV77YmYZina4VUL+zattJeeKkBBF0zDYDC7D9t1/VbYlvRjP/toiYFVVwSfpO4fuNlw9sI34dVbnqeW5egSXFZ1UO9r/cfsGwyotmlhbt7/xufS1yOnGVOVEK+y5CGhWibqZg/QlIuD3VOaPFGnNbEu/W1JCHzAu710AUy9hjFJKsq/d2Q64fQTyEkctMvA6TNKVrpsS7P4GNi6PG6t4SrtQ9Ns9fw4jMYpoMorlL4z2JJyJCIfEqNihkzlTXQjJDHHdpQTBYc9ZiITj+cAV+fjHfrCVzs12uN0hhbgokwfCuKXgSEfcJD3CV1/yES6XqaRJHXyUeU2VTRSCShOQi86zus2NsOixVpHd0tHMGiqyD79XKi2ybzVjbprzJN3Aj5hN2VY539UZtLcUZq5g3IsZpyi6xlN/9JPUtJsMztmL9wrBnw1pgO/Ib3/kKvPvwe2sv1+xfIEjGwIy4Yrrr+Q+cvoyheWndZ3RwuY/kIJWQvNWXBu0TCVMjTxaiLkC96TfBAlo1NygxEtVh/Qo3EMqh1MAH9o/5G7lzmGoRWOE/Y3RtXWQugIqPJcXzjBt65kHhQB84VXvK9jXjVEuVeiQPi0VON1wIVRT7vGEzFAuHXVKGJlU74TOp06XgXK+p/kJxV9cDTTPSKtG0t+jOyJFq7NGREHjR1oBqLilnUlCOvfmHQ=="}
2026-05-18 08:59:07 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"22nH2X4WTzyyzkctrJ2LKw08411779065946","eventId":"ad1caa439040490595b91f076b45af5d","corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-FDF3F88C-ADAC-473C-ABCB-9EAAFECABE3B/type/start","EventType":"bpms_task_change","businessId":"202605180859000065828","activityName":"部门领导","actualActionerId":"02580952260533396432","agentActionerIds":[],"title":"位晓峰提交的售后单","type":"start","activityId":"1918_5cd3","createTime":1779065946000,"processCode":"PROC-FDF3F88C-ADAC-473C-ABCB-9EAAFECABE3B","bizCategoryId":"","businessType":"","staffId":"02580952260533396432","taskId":101208612829}
2026-05-18 08:59:07 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 08:59:07 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 08:59:07 [XNIO-1 task-10] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779065947422, msg_signature=f7b2bcd39c67b81f50f45204063ed91bb60fc073, encrypt=PMbMc3PQS2CK0tDfYO1qvwQXjUczZUr1W8ll5CqTMIy+6PL6RSCzfvtzfB12Cdcy1tSMfttJNZq0x81qoGjyGg==, nonce=VzB29LRvrOSs6yaF}
2026-05-18 09:08:43 [SpringApplicationShutdownHook] INFO io.undertow - stopping server: Undertow - 2.2.24.Final
2026-05-18 09:08:43 [SpringApplicationShutdownHook] INFO io.undertow.servlet - Destroying Spring FrameworkServlet 'dispatcherServlet'
2026-05-18 09:08:43 [Thread-44] INFO com.xxl.job.core.server.EmbedServer - >>>>>>>>>>> xxl-job remoting server stop.
2026-05-18 09:08:43 [xxl-job, executor ExecutorRegistryThread] INFO c.x.j.c.t.ExecutorRegistryThread - >>>>>>>>>>> xxl-job registry-remove success, registryParam:RegistryParam{registryGroup='EXECUTOR', registryKey='xxl-job-executor', registryValue='http://192.168.5.200:9101/'}, registryResult:ReturnT [code=200, msg=null, content=null]
2026-05-18 09:08:43 [xxl-job, executor ExecutorRegistryThread] INFO c.x.j.c.t.ExecutorRegistryThread - >>>>>>>>>>> xxl-job, executor registry thread destroy.
2026-05-18 09:08:43 [SpringApplicationShutdownHook] INFO com.xxl.job.core.server.EmbedServer - >>>>>>>>>>> xxl-job remoting server destroy success.
2026-05-18 09:08:43 [xxl-job, executor JobLogFileCleanThread] INFO c.x.j.c.thread.JobLogFileCleanThread - >>>>>>>>>>> xxl-job, executor JobLogFileCleanThread thread destroy.
2026-05-18 09:08:43 [xxl-job, executor TriggerCallbackThread] INFO c.x.j.c.thread.TriggerCallbackThread - >>>>>>>>>>> xxl-job, executor callback thread destroy.
2026-05-18 09:08:43 [Thread-43] INFO c.x.j.c.thread.TriggerCallbackThread - >>>>>>>>>>> xxl-job, executor retry callback thread destroy.
2026-05-18 09:08:43 [SpringApplicationShutdownHook] INFO c.r.f.manager.ShutdownManager - ====关闭后台任务任务线程池====
2026-05-18 09:08:43 [SpringApplicationShutdownHook] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource start closing ....
2026-05-18 09:08:43 [SpringApplicationShutdownHook] INFO com.zaxxer.hikari.HikariDataSource - master - Shutdown initiated...
2026-05-18 09:08:43 [SpringApplicationShutdownHook] INFO com.zaxxer.hikari.HikariDataSource - master - Shutdown completed.
2026-05-18 09:08:43 [SpringApplicationShutdownHook] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource all closed success,bye
2026-05-18 09:09:09 [background-preinit] INFO o.h.validator.internal.util.Version - HV000001: Hibernate Validator 6.2.5.Final
2026-05-18 09:09:09 [main] INFO com.ruoyi.RuoYiApplication - Starting RuoYiApplication using Java 1.8.0_482 on LAPTOP-AK2JCS84 with PID 67076 (D:\evo-k3cloud\ruoyi-admin\target\classes started by lenovo in D:\evo-k3cloud)
2026-05-18 09:09:09 [main] INFO com.ruoyi.RuoYiApplication - The following 1 profile is active: "dev"
2026-05-18 09:09:13 [main] INFO o.j.m.auto.MinidaoAutoConfiguration - ******************* init miniDao config [ begin ] ***********************
2026-05-18 09:09:13 [main] INFO o.j.m.auto.MinidaoAutoConfiguration - ------ minidao.base-package ------- org.jeecg.modules.jmreport.desreport.*
2026-05-18 09:09:13 [main] INFO o.j.m.auto.MinidaoAutoConfiguration - ******************* init miniDao config [ end ] ***********************
2026-05-18 09:09:14 [main] INFO o.j.m.f.MiniDaoClassPathMapperScanner - register minidao name is { org.jeecg.modules.jmreport.desreport.dao.JimuReportDao }
2026-05-18 09:09:14 [main] INFO o.j.m.f.MiniDaoClassPathMapperScanner - register minidao name is { org.jeecg.modules.jmreport.desreport.dao.JimuReportDataSourceDao }
2026-05-18 09:09:14 [main] INFO o.j.m.f.MiniDaoClassPathMapperScanner - register minidao name is { org.jeecg.modules.jmreport.desreport.dao.JimuReportDbDao }
2026-05-18 09:09:14 [main] INFO o.j.m.f.MiniDaoClassPathMapperScanner - register minidao name is { org.jeecg.modules.jmreport.desreport.dao.JimuReportDbFieldDao }
2026-05-18 09:09:14 [main] INFO o.j.m.f.MiniDaoClassPathMapperScanner - register minidao name is { org.jeecg.modules.jmreport.desreport.dao.JimuReportDbParamDao }
2026-05-18 09:09:14 [main] INFO o.j.m.f.MiniDaoClassPathMapperScanner - register minidao name is { org.jeecg.modules.jmreport.desreport.dao.JimuReportDictDao }
2026-05-18 09:09:14 [main] INFO o.j.m.f.MiniDaoClassPathMapperScanner - register minidao name is { org.jeecg.modules.jmreport.desreport.dao.JimuReportDictItemDao }
2026-05-18 09:09:14 [main] INFO o.j.m.f.MiniDaoClassPathMapperScanner - register minidao name is { org.jeecg.modules.jmreport.desreport.dao.JimuReportLinkDao }
2026-05-18 09:09:14 [main] INFO o.j.m.f.MiniDaoClassPathMapperScanner - register minidao name is { org.jeecg.modules.jmreport.desreport.dao.JimuReportMapDao }
2026-05-18 09:09:14 [main] INFO o.j.m.f.MiniDaoClassPathMapperScanner - register minidao name is { org.jeecg.modules.jmreport.desreport.dao.JimuReportShareDao }
2026-05-18 09:09:15 [main] INFO io.undertow.servlet - Initializing Spring embedded WebApplicationContext
2026-05-18 09:09:15 [main] INFO o.j.m.j.c.i.JimuReportConfiguration - Init JimuReport Config [ Token Interceptor & Resource Locations ]
2026-05-18 09:09:15 [main] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource detect P6SPY plugin and enabled it
2026-05-18 09:09:15 [main] INFO com.zaxxer.hikari.HikariDataSource - master - Starting...
2026-05-18 09:09:15 [main] INFO com.zaxxer.hikari.HikariDataSource - master - Start completed.
2026-05-18 09:09:15 [main] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource - add a datasource named [slave] success
2026-05-18 09:09:15 [main] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource - add a datasource named [sqlserver] success
2026-05-18 09:09:15 [main] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource - add a datasource named [master] success
2026-05-18 09:09:15 [main] INFO c.b.d.d.DynamicRoutingDataSource - dynamic-datasource initial loaded [3] datasource,primary datasource named [master]
2026-05-18 09:09:15 [main] INFO o.j.m.j.c.JmReportExecutorConfig - Init JimuReport Config [ 线程池 ]
2026-05-18 09:09:20 [main] INFO c.r.framework.config.JacksonConfig - 初始化 jackson 配置
2026-05-18 09:09:20 [main] INFO c.ruoyi.framework.config.RedisConfig - 初始化 redis 配置
2026-05-18 09:09:20 [main] INFO org.redisson.Version - Redisson 3.20.1
2026-05-18 09:09:21 [redisson-netty-2-5] INFO o.r.c.p.MasterPubSubConnectionPool - 1 connections initialized for localhost/127.0.0.1:6379
2026-05-18 09:09:21 [redisson-netty-2-4] INFO o.r.c.pool.MasterConnectionPool - 8 connections initialized for localhost/127.0.0.1:6379
2026-05-18 09:09:22 [Thread-35] INFO c.r.c.dingding.DingTalkStreamService - --------------------------------------------------
2026-05-18 09:09:22 [Thread-35] INFO c.r.c.dingding.DingTalkStreamService - 正在启动钉钉 Stream 模式事件推送服务...
2026-05-18 09:09:22 [Thread-35] INFO c.r.c.dingding.DingTalkStreamService - ClientId: dingebfrpzqko25vo8w6
2026-05-18 09:09:22 [Thread-35] INFO c.r.c.dingding.DingTalkStreamService - 钉钉 Stream 模式服务启动成功
2026-05-18 09:09:22 [Thread-35] INFO c.r.c.dingding.DingTalkStreamService - --------------------------------------------------
2026-05-18 09:09:23 [connection-pool-2-1] INFO c.d.o.a.s.n.w.WebsocketTransportConnector - [DingTalk] start websocket connection, uri=wss://wss-open-connection-union.dingtalk.com:443/connect
2026-05-18 09:09:23 [main] INFO com.ruoyi.job.config.XxlJobConfig - >>>>>>>>>>> xxl-job config init.
2026-05-18 09:09:23 [connection-pool-2-1] INFO c.d.o.a.s.n.core.DefaultSessionPool - [DingTalk] connection is established, connectionId=3493760e-5256-11f1-a582-1a02b3fe6148
2026-05-18 09:09:25 [main] INFO c.x.job.core.executor.XxlJobExecutor - >>>>>>>>>>> xxl-job register jobhandler success, name:updateMaterials, jobHandler:com.xxl.job.core.handler.impl.MethodJobHandler@6c54d0dc[class com.ruoyi.system.controller.ImMaterialController$$EnhancerBySpringCGLIB$$33481d46#updateMaterials]
2026-05-18 09:09:25 [main] INFO c.x.job.core.executor.XxlJobExecutor - >>>>>>>>>>> xxl-job register jobhandler success, name:insertJDMaterial, jobHandler:com.xxl.job.core.handler.impl.MethodJobHandler@5b5f06bb[class com.ruoyi.system.controller.ImMaterialController$$EnhancerBySpringCGLIB$$33481d46#insertJDMaterial]
2026-05-18 09:09:25 [main] INFO c.x.job.core.executor.XxlJobExecutor - >>>>>>>>>>> xxl-job register jobhandler success, name:outsourcingOrder, jobHandler:com.xxl.job.core.handler.impl.MethodJobHandler@7c74ef4a[class com.ruoyi.system.controller.ImProductionPlanProController$$EnhancerBySpringCGLIB$$d23153ee#outsourcingOrder]
2026-05-18 09:09:25 [main] INFO c.x.job.core.executor.XxlJobExecutor - >>>>>>>>>>> xxl-job register jobhandler success, name:procurementOrder, jobHandler:com.xxl.job.core.handler.impl.MethodJobHandler@54519d74[class com.ruoyi.system.controller.ImProductionPlanProController$$EnhancerBySpringCGLIB$$d23153ee#procurementOrder]
2026-05-18 09:09:25 [main] INFO c.x.job.core.executor.XxlJobExecutor - >>>>>>>>>>> xxl-job register jobhandler success, name:shengchanOrder2, jobHandler:com.xxl.job.core.handler.impl.MethodJobHandler@1ec96512[class com.ruoyi.system.controller.ImProductionPlanProController$$EnhancerBySpringCGLIB$$d23153ee#shengchanOrder2]
2026-05-18 09:09:25 [main] INFO c.x.job.core.executor.XxlJobExecutor - >>>>>>>>>>> xxl-job register jobhandler success, name:updateAssetCard, jobHandler:com.xxl.job.core.handler.impl.MethodJobHandler@3d00c2ae[class com.ruoyi.system.controller.KingdeeAssetCardController$$EnhancerBySpringCGLIB$$bcb833e#updateAssetCard]
2026-05-18 09:09:25 [main] INFO c.x.job.core.executor.XxlJobExecutor - >>>>>>>>>>> xxl-job register jobhandler success, name:getMassageForMultipleWorkCenters, jobHandler:com.xxl.job.core.handler.impl.MethodJobHandler@665574fb[class com.ruoyi.system.controller.KingdeeWorkCenterDataController$$EnhancerBySpringCGLIB$$cfd8c590#getMassageForMultipleWorkCenters]
2026-05-18 09:09:25 [main] INFO c.x.job.core.executor.XxlJobExecutor - >>>>>>>>>>> xxl-job register jobhandler success, name:getMassageDelayDate, jobHandler:com.xxl.job.core.handler.impl.MethodJobHandler@3eb7ff78[class com.ruoyi.system.controller.KingdeeWorkCenterDataController$$EnhancerBySpringCGLIB$$cfd8c590#getMassageDelayDate]
2026-05-18 09:09:25 [main] INFO c.x.job.core.executor.XxlJobExecutor - >>>>>>>>>>> xxl-job register jobhandler success, name:getKuCun, jobHandler:com.xxl.job.core.handler.impl.MethodJobHandler@6b83ec49[class com.ruoyi.system.controller.KingdeeWorkCenterDataController$$EnhancerBySpringCGLIB$$cfd8c590#getKuCun]
2026-05-18 09:09:25 [main] INFO c.x.job.core.executor.XxlJobExecutor - >>>>>>>>>>> xxl-job register jobhandler success, name:getPurchaseOrder, jobHandler:com.xxl.job.core.handler.impl.MethodJobHandler@50ad5625[class com.ruoyi.system.controller.KingdeeWorkCenterDataController$$EnhancerBySpringCGLIB$$cfd8c590#getPurchaseOrder]
2026-05-18 09:09:25 [main] INFO c.x.job.core.executor.XxlJobExecutor - >>>>>>>>>>> xxl-job register jobhandler success, name:getKuCunTo40SB, jobHandler:com.xxl.job.core.handler.impl.MethodJobHandler@1d921267[class com.ruoyi.system.controller.KingdeeWorkCenterDataController$$EnhancerBySpringCGLIB$$cfd8c590#getKuCunTo40SB]
2026-05-18 09:09:25 [main] INFO c.x.job.core.executor.XxlJobExecutor - >>>>>>>>>>> xxl-job register jobhandler success, name:getConstructionDelay, jobHandler:com.xxl.job.core.handler.impl.MethodJobHandler@1c5f6292[class com.ruoyi.system.controller.KingdeeWorkCenterDataController$$EnhancerBySpringCGLIB$$cfd8c590#getConstructionDelay]
2026-05-18 09:09:25 [main] INFO c.x.job.core.executor.XxlJobExecutor - >>>>>>>>>>> xxl-job register jobhandler success, name:getPurchaseOrder2, jobHandler:com.xxl.job.core.handler.impl.MethodJobHandler@684a34f4[class com.ruoyi.system.controller.KingdeeWorkCenterDataController$$EnhancerBySpringCGLIB$$cfd8c590#getPurchaseOrder2]
2026-05-18 09:09:25 [main] INFO c.x.job.core.executor.XxlJobExecutor - >>>>>>>>>>> xxl-job register jobhandler success, name:getProductionOrder, jobHandler:com.xxl.job.core.handler.impl.MethodJobHandler@52ec5ba6[class com.ruoyi.system.controller.KingdeeWorkCenterDataController$$EnhancerBySpringCGLIB$$cfd8c590#getProductionOrder]
2026-05-18 09:09:25 [main] INFO c.x.job.core.executor.XxlJobExecutor - >>>>>>>>>>> xxl-job register jobhandler success, name:getApplicationMessage, jobHandler:com.xxl.job.core.handler.impl.MethodJobHandler@5f606ab6[class com.ruoyi.system.controller.KingdeeWorkCenterDataController$$EnhancerBySpringCGLIB$$cfd8c590#getApplicationMessage]
2026-05-18 09:09:25 [main] INFO c.x.job.core.executor.XxlJobExecutor - >>>>>>>>>>> xxl-job register jobhandler success, name:getProcessTransferForm, jobHandler:com.xxl.job.core.handler.impl.MethodJobHandler@384cd83a[class com.ruoyi.system.controller.KingdeeWorkCenterDataController$$EnhancerBySpringCGLIB$$cfd8c590#getProcessTransferForm]
2026-05-18 09:09:25 [main] INFO c.x.job.core.executor.XxlJobExecutor - >>>>>>>>>>> xxl-job register jobhandler success, name:getUninspectedData, jobHandler:com.xxl.job.core.handler.impl.MethodJobHandler@198a653[class com.ruoyi.system.controller.KingdeeWorkCenterDataController$$EnhancerBySpringCGLIB$$cfd8c590#getUninspectedData]
2026-05-18 09:09:25 [main] INFO c.x.job.core.executor.XxlJobExecutor - >>>>>>>>>>> xxl-job register jobhandler success, name:generateDoc2, jobHandler:com.xxl.job.core.handler.impl.MethodJobHandler@3119fcad[class com.ruoyi.system.controller.WlStockDataController$$EnhancerBySpringCGLIB$$2fe52dfa#generateDoc1]
2026-05-18 09:09:25 [main] INFO c.x.job.core.executor.XxlJobExecutor - >>>>>>>>>>> xxl-job register jobhandler success, name:syncOperationPlanningJobHandler, jobHandler:com.xxl.job.core.handler.impl.MethodJobHandler@6d7005e2[class com.ruoyi.system.job.SfcOperationPlanningJob#syncOperationPlanningJobHandler]
2026-05-18 09:09:25 [main] INFO c.x.job.core.executor.XxlJobExecutor - >>>>>>>>>>> xxl-job register jobhandler success, name:demoJobHandler, jobHandler:com.xxl.job.core.handler.impl.MethodJobHandler@33a39d7e[class com.ruoyi.job.service.SampleService#demoJobHandler]
2026-05-18 09:09:25 [main] INFO c.x.job.core.executor.XxlJobExecutor - >>>>>>>>>>> xxl-job register jobhandler success, name:httpJobHandler, jobHandler:com.xxl.job.core.handler.impl.MethodJobHandler@77cd1f67[class com.ruoyi.job.service.SampleService#httpJobHandler]
2026-05-18 09:09:25 [main] INFO c.x.job.core.executor.XxlJobExecutor - >>>>>>>>>>> xxl-job register jobhandler success, name:demoJobHandler2, jobHandler:com.xxl.job.core.handler.impl.MethodJobHandler@94f79a7[class com.ruoyi.job.service.SampleService#demoJobHandler2]
2026-05-18 09:09:25 [main] INFO c.x.job.core.executor.XxlJobExecutor - >>>>>>>>>>> xxl-job register jobhandler success, name:commandJobHandler, jobHandler:com.xxl.job.core.handler.impl.MethodJobHandler@647d3279[class com.ruoyi.job.service.SampleService#commandJobHandler]
2026-05-18 09:09:25 [main] INFO c.x.job.core.executor.XxlJobExecutor - >>>>>>>>>>> xxl-job register jobhandler success, name:shardingJobHandler, jobHandler:com.xxl.job.core.handler.impl.MethodJobHandler@4b9a1be5[class com.ruoyi.job.service.SampleService#shardingJobHandler]
2026-05-18 09:09:26 [main] INFO io.undertow - starting server: Undertow - 2.2.24.Final
2026-05-18 09:09:26 [Thread-46] INFO com.xxl.job.core.server.EmbedServer - >>>>>>>>>>> xxl-job remoting server start success, nettype = class com.xxl.job.core.server.EmbedServer, port = 9101
2026-05-18 09:09:26 [main] INFO org.xnio - XNIO version 3.8.7.Final
2026-05-18 09:09:26 [main] INFO org.xnio.nio - XNIO NIO Implementation Version 3.8.7.Final
2026-05-18 09:09:26 [main] INFO org.jboss.threads - JBoss Threads version 3.1.0.Final
2026-05-18 09:09:26 [main] INFO com.ruoyi.RuoYiApplication - Started RuoYiApplication in 17.632 seconds (JVM running for 21.041)
2026-05-18 09:09:26 [main] INFO c.r.s.runner.SystemApplicationRunner - 初始化OSS配置成功
2026-05-18 09:09:26 [main] INFO c.r.s.runner.SystemApplicationRunner - 加载参数缓存数据成功
2026-05-18 09:09:26 [main] INFO c.r.s.runner.SystemApplicationRunner - 加载字典缓存数据成功
2026-05-18 09:09:27 [registrationTask1] INFO d.c.b.a.c.r.ApplicationRegistrator - Application registered itself as 08432fb0b14f
2026-05-18 09:09:27 [XNIO-1 task-1] INFO io.undertow.servlet - Initializing Spring DispatcherServlet 'dispatcherServlet'
2026-05-18 09:13:28 [XNIO-1 task-13] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"d613a1eecc0a8b7f64b9e39228490550a2cb0e39","msg_signature":"d613a1eecc0a8b7f64b9e39228490550a2cb0e39","timestamp":"1779066808573","nonce":"CBMOmOBX","encrypt":"kru77HtFgKrw8HXEK2B6nZ3NzXXLX+T4Km7vlvpItRkjWKaBYFCjpL4/c7mNxbyEZANhQpjW4XJdMRNhJ0wwBGJ9WCXRI/t+Ep5WvKvzHGEvUYe+Y6dl616nhP+p4YliAbhTdo/zyv1FTj1aENlSOXDitZmih5nvPAki2WbFlD3tnrISKBJQh4zxAoczoyvzUzn/kl6lhC0T49+sPecATuYt8/dufTr2pAvJ2rdPx4Yb3bMPwWy1YtHygdLpFdnYocNmRgQtIZT8lqPgIc4FKOmIrbNcStMjeUnXRQb/hY9N4AeVff8DH0KzQV4BthcFQ7B3VqDgf4tr6q2aAH47k2KvXRMzxVOG+TwbOFnrjynZVpoVDeav/6za10xL6JyS+eUd3giDs93ipLnnsxTykA3vinBKeETyRoMwQxLvz+QnK+2ia2szYah0LvS7e8wFKi9HzsOpmEyZzICkvs7flBTh/tnRC+Wb5NnlmPixXHYgF5hOqdP+gjWpT0p4zECCXjQQi8lEpGZJqkoDqzLGEiefoGdQG2fp18yLZk/O1PMGKZFkCR5fM+qcosMPS+yZaUyRkNc3EXl8tWkeUKCMbsgAvTkWzj8PU8KFHSAzCzdirVb7Sr13+tk4XUBEKyg3K7MOLxH/J6TLkMXWKcHOuAhqp9IkZAf//FqzpFoeCkiayBvZsPUYFQw0O0hTiaDFdj+HHFd2l4Rk0ehY5dhipau1d6hb1gBzAHAosCLPYAkUTw9v2jbDSo+nTSX0hoZZ6X/iUrAbYIUxGBO4iEyoJjLAakMXNKNQfDRQbIJ0zlu6EtRvdCwjVD08cXNcCkCDy60I5b0/FYZmrzs3qVI8Jg=="}
2026-05-18 09:13:28 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"632548b4eaf34895b9fb3aed324c2782ab46043e","msg_signature":"632548b4eaf34895b9fb3aed324c2782ab46043e","timestamp":"1779066808463","nonce":"7CMejZCz","encrypt":"XSdqn5mVA5ZrHht9bqx/qTuEQ5mcQLNFYnR1b+02ylTTliNsmdKRx3Ecv8BVyRtmUKJ8uA46PNQpYOyAXgM28zAMSFGlqVTqggAkmRoi2p2C4RPH8Q/OAVhbQ2zGade7q6d3N5X+CAAbZuj1dy9O34u1+p6ciH3M4O5B3+h6EGUmsxxzJKJMNLVyURk4wC5NxHU0bHiIDjh7Ir4W+GyWmnp954r+SRrNK/6ieTtrEN9TGyDxewC4xbdCu34d1WzIc4RkWDQm6Ge86ZzroqMLxnqHVhHKXpKj4GFdbYrQFB7vcEm61myYpVoHCA/OavPlHr900Iu4aIAv4xWgiirVhv3Nspu/14axDQN+8PGMy4OcIPmgdDgFpiY/MsdUDeNt+Sv02Y/j2ORgqCUJvP70ht5PBIfnWyvmMb512EvtANJLyZa8E6pZZMIshxMkCEErxVgT17WVzoDf+6mamik9joyNOc/qUsaaArmFi2emMa0/GReNAcVp8j5tycJNuDq51BBHSRG1UwBvScI/d5VKBe1DRAoluP3RHxTbowRTpgKcLuJsupKoDiRYnCcefPrtzvQpoJyGrGbgS2+6pizNRk8PAa3gKyORSC6CL0tsJKEn+FxXKlISx2FbS/ZZiMw7ZGVcZL9GFZTo27AmSlgga7sZk5DR/FNhizmrtqpdpFbPuuV1j5+RIW+LKH+r/yZOICNX+zbhjc6dY8nseGiBwMz46ZR1mdrttjxgIsXuxgOy/chsbRhDaV39t9ACntX8laibfICOMlcWhZazVrlF9jnMaVhvm/q5V/RRf9VMAJxYmPQ7xHYZ6vbS9muaAQncmLQPoMOpZ5sJuJd3jpAmuQ=="}
2026-05-18 09:13:28 [XNIO-1 task-13] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"yOda8XN4STGkd1FKhjUfeA08411778912977","eventId":"2dbe6eec793047288bc851e8258c9718","corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB/type/comment","EventType":"bpms_task_change","businessId":"202605161429000373885","title":"田志阳提交的技术方案申请表","type":"comment","content":"管理员后台删除","createTime":1779066808315,"processCode":"PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB","bizCategoryId":"","businessType":"","staffId":"283633411029629036"}
2026-05-18 09:13:28 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"zUFBG2SXRZSqspRumD65YA08411778912762","eventId":"10c58d08c6dd4b59b815f4028b26ded4","corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB/type/comment","EventType":"bpms_task_change","businessId":"202605161426000023614","title":"田志阳提交的技术方案申请表","type":"comment","content":"管理员后台删除","createTime":1779066808153,"processCode":"PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB","bizCategoryId":"","businessType":"","staffId":"283633411029629036"}
2026-05-18 09:13:28 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 09:13:28 [XNIO-1 task-13] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 09:13:29 [XNIO-1 task-13] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 09:13:29 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 09:13:29 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779066809043, msg_signature=05c89233a706719d0ffa504d34068020398f1003, encrypt=VECoAXl2siR0YfApd6H3ipgQQ2YRBYRU2dd7e8FIZ42auBZ0JPehjUqkwNfM4ltzQbqh+7hYp+UOhCEQOz/ZDg==, nonce=xUOZmOtk7EcJcvne}
2026-05-18 09:13:29 [XNIO-1 task-13] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779066809043, msg_signature=0fd3f9afe0ff6d53a495ff87d270ce7f61cc3aef, encrypt=aw83Tt7eqNIpuZRnr6yRk4ehjSxmY+xY5r3NLSHd+8k87dragsdju292kEvFHUnE0iLe/KFmDIviejXGeUfT+g==, nonce=l8bbUqL7NrRJ60P9}
2026-05-18 09:16:00 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"de768abf89ffa91c4840818397fa918473d08c91","msg_signature":"de768abf89ffa91c4840818397fa918473d08c91","timestamp":"1779066960606","nonce":"00YrRphr","encrypt":"J74WvfUGX6HVAh8tz9Jb2uv1qjClS+1fN6h/+q75fvSYoKIWQILTAMTM93vpUXqgcL39CX1gsayzus1/+4p4kNYM7+kjlj1DfUM23vBKT3ygs5lzu+PfNLiCDasMkEEVZnujxHTwPCepIwmyRqEVAaIQzxx4u8qa2ZSDckrVyNV26XFdJDOA1YOsiBKl3R6mdwJiTeTLXNbCJewU2QS7boDEIAvONqExbHdDYc7oyFYGCu5CFK6xG9+00fHXkDvFPTLIazfM3CE+TngyagyDksi6subeg5gExHIR9Qm60H0E72DenP3gDe1D3IcuFitrk5xGPi5oeGcPYMDjjJnXaKBYlL6rTYsk3XgR3Y0PjNWVLrQCIagfTDGIF4OifRpbMjE2k6bjVf3V2b0rMXgE7gFr7Gzgn8+Ef0xBzNDc8LbE/XKFjH3Vx2InyCVlFQUvj5rVHJIdp9suqUmWZjU8jrFZbTJzVnxLJFG5jpDnVplkA9w6runHsYPFhnoLiCI8IIVDXKK+1u1h7/TPPp6PW6YaGZY1LduFNi+ydTe5zagn3sXc9Ve2NXl8BW3hgeQQt7gHxnGQ/ECWCyE0SIgC4klSYOpBWcyVyYiWk0Ds7YbElgQTdqyI/mw+0F0W+viveU199nSluwxK6xN8/Yxlpsf6kn8gd0LXvBfBd4STOKBrviwVq//F7iHrqyKtyqLfrm9wuET+LsA0/MXv6KrtD57T1dDkInG6DauxRaLPrYznWwTrZepSH57WipEijgYwF49gF8m5PFKjEgR1jVWa1YWpajNygsT0rNOzPGbJlbLi1ksE3AC8z82q7uqwTEeRW5GuLKT93h5aIvCW3tCRnKueM4o025SL3zjYam5z5fgwdx5Wcwtrrkz7anc96h6dJU9y9A3U+qRuZDd6rjASFRibFM5cH3o4HuplnEu//LLDS/SmBs/FDQyDt/KRBak4eAUt/n3tTKzNgU9WRwqwSQ=="}
2026-05-18 09:16:00 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"T_XBf04fSpujK04zZMJXjg08411779066959","eventId":"e94970a436554d6d95aff2a0ff1c7860","corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-FEC37380-3410-4EC8-8638-17844A89DBC6/type/start","EventType":"bpms_task_change","businessId":"202605180915000597802","activityName":"连续多级主管","actualActionerId":"223241230721375124","agentActionerIds":[],"title":"郭亚曼提交的用印审批单","type":"start","activityId":"d4b7_f54c","createTime":1779066960000,"processCode":"PROC-FEC37380-3410-4EC8-8638-17844A89DBC6","bizCategoryId":"","businessType":"","staffId":"223241230721375124","taskId":101171617644}
2026-05-18 09:16:00 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 09:16:00 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 09:16:00 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779066960938, msg_signature=a24e789606ecf7cdc834b89c235dc991ab391cd2, encrypt=P4uhcdQY18l6+1q+XABswan23bydTCEnCR/jYgQvJtcLBnjhOreXaq3q8/Wrlhb64lu1Zz7jgOKb1WbSKdUnGA==, nonce=0M760ns02gUMq6he}
2026-05-18 09:16:21 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"6530c5e6db03562fbcfa79899211c91846e170c4","msg_signature":"6530c5e6db03562fbcfa79899211c91846e170c4","timestamp":"1779066981492","nonce":"YbLpCbWD","encrypt":"ts9NUjJkK5BEtzFzZybZCb9jUiKTZ3V/a48xECgEKEJEkrjzEJ51Liv+Ez3F52sRrdMvkyUR9o6BnflBFFC4G3Uv4cZ3aYIzpFHEB7vU3gFlnWXx9mmzfusF7X5V4Y1DTKv4pBFxnjpcx13N3rUwFVqyCnamNdrfdrN33fH/Qa3iHk3gEqDFZNpYxX9diQgruTfRvigNZPNqPPFFc9k3iAycRa5x+gbVosffViBGfYEhYEpTtAQFPpY29Fk6ipu9vh9JE9K9l77UWvx4uDo6fhdmUM8xKZV87W/A88V8ihdS0Wor2RojdI0/apg4oX/9ML14FfBBmqcHA1ctNVcjXDz2++yIvD/04BtrcR0N3lrOrFCoWWJHFLe9xfTfjZ2q9YBROb/P3ZC0h6lskjYxwezs7N0KcREiUj9Vexqu1p7RKWTwj46JUqu4NNaqzCk76yYC5j6Mq5WMO7Le/QCUaryI7PQD7vGY2pGAKFYTiJNstcXxZ99QB/PprBofx62ulrso1iqYVFePt3ovY2m1uc0rJCq+xUM+NuLFAiFhPUOmYRvljR74u/Bwq46mcZ1YR8ba0wKtX9dUZw/QVofup7arsnLIaiLHUwnt/XSskPalx3mJ5//7j2psOnGBCtj4DAgQ+4LpOi4if+QYUsxAgvFghydWIBqGIxa5kIuuKvGGWYvlOBJWa0sYWTW+uRK52aR7FIli4OsZQfoyypw7Ohv3GhTUzxJNzoVqUMFlzqI5d2M23DD7voWIT67wiaPN35pCawqQItXmtQn4a2d6U3ju9TCqIbktkMV7yVhjGM5vjNFnSAsQC9+5mBp511lksqK8M65LLN8rfpMZ7bA0KxHf46X9XSiyNL+liG4CFOCiThjkLlcr/Gz5WW9onkADCXmakMMbAeyp6QOuag2jgja3/1aE2ovgUa/9qa/AoKmov1UhUtP+UFz0144XqOGcin96OiK34iLrIgRqfmXSOg=="}
2026-05-18 09:16:21 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"T_XBf04fSpujK04zZMJXjg08411779066959","eventId":"641f34d6ebf3483f988d77e6c6022ddb","corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-FEC37380-3410-4EC8-8638-17844A89DBC6/type/start","EventType":"bpms_task_change","businessId":"202605180915000597802","activityName":"连续多级主管","actualActionerId":"1017253114780847","agentActionerIds":[],"title":"郭亚曼提交的用印审批单","type":"start","activityId":"d4b7_f54c","createTime":1779066960000,"processCode":"PROC-FEC37380-3410-4EC8-8638-17844A89DBC6","bizCategoryId":"","businessType":"","staffId":"1017253114780847","taskId":101171617645}
2026-05-18 09:16:21 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 09:16:21 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 09:16:21 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779066981796, msg_signature=b2a4b2230586d76c7d540dd38fbc3793f3a25366, encrypt=Va/S0mpJUo+YeHAYiY795sKMylZavNVCsqyLCVb9T6UYtqhAtc76O2UlW9ht5Sawb3SSVCYU415NsYe5yW+ciA==, nonce=fvZdndRBzcypVeRe}
2026-05-18 09:16:21 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"31e65f4bcfb710010f9bac2c91a7dbefb38ea6a1","msg_signature":"31e65f4bcfb710010f9bac2c91a7dbefb38ea6a1","timestamp":"1779066981569","nonce":"ilX4w96p","encrypt":"um3mdq457NuU7sOByV70sCPykcFNi6AhsLv4w4y+rxdG+2v/rRpVeNXXYMbsdsjShSJdYoa6HA1XMl9gLJzXEp7JiI2OYg6RtUSwL1YjeTNhvny/otsHUGjrSbrPNd0op/8AMIjLZl7NXmGY1JCw5KwOoHsOMvFDMUdfPVkhA8gJGj5tM3FWg9tNNyC10Yrd/WJ/Pt/NxAYMHQPMtB2oxuisJNarkqiK0jvTMWBeX6uFjmF7l/PkoiZ/HIg7hJKqhIqkSA+iOGFzf0j06VNrjNvXcC1b5CvapeDp0bKHakeoXY1+5tsDQXeaky/3vsH1C1Xc88D1JDJr9UbBPh5fZwhrrgZ52y8cmHKIkWesYfiUCo+hbrAaKne51MBETtBajm/TQnpNDXOmYwOelphIRX1GKIlESAkc1PLoc1RajYIdbPXhdDVptsvH6lsScjJYguJePLLVqG5frNwA+CgZSgczJ19PRk85JiBRYLy0Q1plQukfIIKnBz8L7QBQ2nVnluqU3GlbnwdoDrW6vQ/l6kofv7TTAPoA3cgmWOe/AAcIgl7ZD6ciZv2o/GJqKEZn+R0oiK7JkkELNaWFrkaTU0/p/HAmRUx0gtNXfa7y/KmfOyejJCtxJnpQHUd0cRV4lDFzJDhE6WQZQOqWa9dXSIx38629Wf+j2Bpcv+9eYIJ0p9B/5q6Isrv49ynMeX5Vum7X1tX6tll6Cuv9Edih9YJcx4kk9kIgtYH3cH8op5zSKHGfictXN27fyxjCvhygjbsl4m6ix4KKsdYSnK7ko4cEaA+nHO4mWYoyHSmi6NvtB2h2fkgdIYo7akhn7w1MfQ5RsjWFLqJN8dT/rv8QLoWPk7+/eUQdH92/oMGgr/QtPCwVONcv3KpavKNt/0zgAo1UiqoYqMz6RF1gUBlZuI2oBtlp19ar9jfcwmSpgVtccf0CuQnaHouvLYJOwMVy05W0lTFepBC5WrFYydoozJzDxCPaNKy09hkZi3jl2hSbEuk+DVZ0k3FYlrXwPulsrw4Voz30/MlX6FhMpsRfY0+a0U/wf/9q94PkaduHd5A="}
2026-05-18 09:16:21 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"T_XBf04fSpujK04zZMJXjg08411779066959","eventId":"bb2d94df682141e1b186d6dd7890a014","finishTime":1779066981000,"corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-FEC37380-3410-4EC8-8638-17844A89DBC6/type/finish","EventType":"bpms_task_change","businessId":"202605180915000597802","activityName":"连续多级主管","actualActionerId":"223241230721375124","agentActionerIds":[],"title":"郭亚曼提交的用印审批单","type":"finish","result":"agree","activityId":"d4b7_f54c","createTime":1779066960000,"processCode":"PROC-FEC37380-3410-4EC8-8638-17844A89DBC6","bizCategoryId":"","businessType":"","staffId":"223241230721375124","taskId":101171617644}
2026-05-18 09:16:21 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 09:16:21 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 09:16:21 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779066981864, msg_signature=84173f8439d351d1ed3f784b423b8e11ff523334, encrypt=vYgTZ3hb5TXnX1aZjKNKWQTHMW1Eu1PkPQBiHYtQCrvD1TjkoILA/Gm6iJ4edVsYrAx4ECk3OAiVqZlkMUCadw==, nonce=xg8fiBgv2uz5LvJI}
2026-05-18 09:17:21 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"e5aa047c984a90d36b5eb2f46f877249583829a8","msg_signature":"e5aa047c984a90d36b5eb2f46f877249583829a8","timestamp":"1779067040748","nonce":"34AM3H7o","encrypt":"eREhFZ/t61DYNCipWpe0ZIBRPR5OIadrVotty9RzzQlSL2U+SY79Umr1VwvSch3NhfkHDKwq0uPia85fm5QK8tJpFsTYgra5g4obPH0ygSBGL1QnmQsxIC01VKERxtB6/7yCVHklD3KhbLNBdcKMEz4cfEBVU2tGNAY/NKMt3Ifb5F/hC5P2yj+w+Oplf8NEKot51IG/DIUSsuoY6JHLGsBXK1K9ynsFvMZvNPc+cWDTWlVQNax+XdxQHLjZ37FKO4Ljx1yA5gt/z9y0RNigNXW9fNcc9cZlCMAzDVjsi7s5PTnBK3bYDqwuYz+4RBtJkKXg5cTCcvD+7WN22Qjx5gfB7mZApo809xXH4DO3agUCe1HluExGomu2HYrJx+cN4+mPvB/zTkFxbdTi7XJBdnPrJ76UfegPzRCGreBZKU8/HLZ1l8jwZGh8tVYjlbyQf/i7aP23Se62YUX5298yyBe3rujW96p6E3PMhrjbC3OzEtvnH7rJSqoHb2n/nQSUYC00a/kKBRL1BiMfT6QsoDax4dy5bxYuRWzwzGZdNEJY8BUMOINil7abIrIWbFqEOw/zrXuTJEQVJOz/Eb8bbPc8Ioo9F9tWT6xkVwaU8psoFeYzqW+3MbkwKn6sWese948ag1zpJ7cKrgQW4V7NlOkF4GW1g/PlrBx/KDWoSvmlpO77IifhDmVlCQeppR+ZgyT/TAdAwMh6eWajiWQWG/T8f5ThkDvwmP3UdhZVHEubNtMNHYofrDuyZpnvI0+i8IJE13oaXij5bBputKoQbef+1GISlYVui2fYquLfkQKpwSk19QErXFDjWuMUv2mZtbWbVmirbr0Jk1QWPeev6LoOxodjG/+oLfrPMsjdHgpbkRd7nQ9Ei170ZePqsRL+QhvBHcGjwMqORZdJNZ+wghaktdgqy0kni3CaaIKxZACyXUiUAdAUxOo5GFYoVcEhCPReUbO5jsTI8iWh0JCDtw=="}
2026-05-18 09:17:21 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"mSJmSHiNSNulT_2pRiVZ1Q08411779067039","eventId":"c090a273e6c94df3aa991f38775c3c7f","corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-FDF3F88C-ADAC-473C-ABCB-9EAAFECABE3B/type/start","EventType":"bpms_task_change","businessId":"202605180917000199559","activityName":"部门领导","actualActionerId":"02580952260533396432","agentActionerIds":[],"title":"位晓峰提交的售后单","type":"start","activityId":"1918_5cd3","createTime":1779067040000,"processCode":"PROC-FDF3F88C-ADAC-473C-ABCB-9EAAFECABE3B","bizCategoryId":"","businessType":"","staffId":"02580952260533396432","taskId":101143434454}
2026-05-18 09:17:21 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 09:17:21 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 09:17:21 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779067041069, msg_signature=36e2848888199fa8dda4e75d457b413d7ef6e814, encrypt=lYpJphlN/Q5fTGvFEChPphUfN6z3RIVj1aqbGs44uPSJkWDaP5jgEGs4poz4t6ERvSZpUDgZwNoAvYTKgFW+bA==, nonce=Frpio3kiPoRrrzju}
2026-05-18 09:18:01 [XNIO-1 task-13] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"18f2d1ab815106b50068fd47a55178a76c850099","msg_signature":"18f2d1ab815106b50068fd47a55178a76c850099","timestamp":"1779067081444","nonce":"6neqbdT4","encrypt":"VDBhlLGXLHB2Sm9dWs2+slyAl1j2pGfMOLhOQOS5kdmXKBLoGuzxtpCI97BFrLZvMA9RHRRGcC+fqTgsfSxBH77O5/BhGKOrICiavcijstYzEHRraAgzz9cOqOOtXVkLNuWQoDq0kyiOobmg+/CBiAHH/hCoFgL5EVkeC8V4p0GmExHyAt/4To8ACZyaRVhjlNyNlM5Zku3VVvx7DbHQvf1OV6fEdV20S6MEo3IXOZpZvBMMewDQD4KyBcHCmpsCDAM2EKA37ue82iey6S/ZZMs6HzyThzw0oukM44ZQklkqvkqkLQ9wAbATIoq6oT1CoitepuKme8Xe518kvmwcyEfHCVOQNaF92DKRQhNJ8YzlWJOAxWEmZ1+brAXO9ls0+DqmPCIWZ3xB78+Bi1HBLPJn/ai7uNWyBR2U05cPuifFdmfuNII1FXf9SzlfbE0c14SxqKBDdLaT2Eo1lHvuRXLirUW58FeahR6oNmYmnY6O0qCxukqzgKfu8Bok5jArY3UiJ0rY2AKG9gedGb4UGVEpfdD+OLGabTyQ23YPW/ETx6ZhoOHhIJKB2sRmnfqigBuBr58F4fyZNLL2Jf2yydPw4KVShQ51Lhm7IpINRKfp/ASswjYJjJ87IoRFzpvmFBxo7SXgwI1A2VfdiVEadgmVtbyEkkgEwh6N871aLuYu/2AASXktnHLNytkEuOCULOPQvqQ5RaUaSln1UTv85Ce5GdA0Poj5hXM6HyJjT03uvbGOW3+YkOWxD0ieSO3nV6Nhoyqg3EGQqx0qMf7aDOjrFIeztxPPUlo6a6WTuuFxDdEREyDXa1VmRp/u7lHBiQD0CLcc5KeThNUZi6+ejunhkK4fs0bz3/yZiRhOLYH1EQY5kM1fa9dCBqj6IBojCTJ4GOcDTUNDEGL6oiu3xhMAjZNRwqKexlCu8Ud4m2ovzXbEEhtszF+AXslJkGFb2v0KMBRJ3KP7ecoOYm8Ykg=="}
2026-05-18 09:18:01 [XNIO-1 task-13] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"gddeuwPJSviQZ0EElvuQlQ08411779067080","eventId":"40857a1cd58f430f86e4dd6d108c89bc","corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-FEC37380-3410-4EC8-8638-17844A89DBC6/type/start","EventType":"bpms_task_change","businessId":"202605180918000006850","activityName":"直接主管","actualActionerId":"176735225223967751","agentActionerIds":[],"title":"薛浩远提交的用印审批单","type":"start","activityId":"19a5_614c","createTime":1779067081000,"processCode":"PROC-FEC37380-3410-4EC8-8638-17844A89DBC6","bizCategoryId":"","businessType":"","staffId":"176735225223967751","taskId":101104191675}
2026-05-18 09:18:01 [XNIO-1 task-13] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 09:18:01 [XNIO-1 task-13] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 09:18:01 [XNIO-1 task-13] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779067081757, msg_signature=aa74302484bf47cbeef948d63318638f0bef6a6e, encrypt=bukD9pOiJyR4Kyfxd6XU8DM55Jz3pfpl6xqXV2B+5krmdvuPahhh0MDNEjN6FuxXD7APtmd1qLaMvpOiMX/bSw==, nonce=lAeteB0vqeNGu1cb}
2026-05-18 09:20:54 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"262c96163121a7ea113446558be6fe16dd26917e","msg_signature":"262c96163121a7ea113446558be6fe16dd26917e","timestamp":"1779067251234","nonce":"G8gHDeov","encrypt":"1M+UZ7dv19vVLpMFDeQDfYy8RJuXII0i+otwJHCA31SU/QyEEHkIQ4ukD3hdgerJnC0M92ke55DYDc5QcOV2f5hVA6URgvccXkuh6jvLTwY18xOA1mDMepB7Uj1cVDhILIhnrDzMweJZJx68TI5Idtir7fFBodqxYNXTNv8w5Bg294D5VRjFxUzbFCmUzb6J6PXLPImah1L1SqWzSVS5TCW3t37Xs0pvRAR86nD+5qfWyUJhQzLHdJbl1l3zQVaiMs6o1VHnPJkCQrtUpECSJAUKc+7GHLgowRENBHj2oPqSm3uGieCZaf73Txzzdtcs1KyHef2WLPsQ+MTpHXeyaHsCjLI+7q8qea5QTBXB9ES+KDdsXnMB6MD2mu53UA5YCjq1EomEhCkaAZwQgai8pDtservGpDfjgKdgOFi0mTpJVoSwg5NDS0OLaSIZdhKE+93tXDTLqHMK7qSQzuKjQwZy7zCWtPbar1PxZZ428dyM9O/+0Ja92ze5MuCJMmkHhFzKS9xrU+Ud7w+zjgmkEhdkhIZ1oCozqUPCvZ8r16ViXgK8ZvoyDmTfvhDZx9n7X0zIHul40koaTBja2Em+BMWo2KD112RnKf8rYTCdO2n1q6hqae8ghQvdZfx014pI8Vg8ofjv6F3mhZOTe2PQ365sFNx+BIT0PZcomse6vNSmokQtL9J0vQYvGqO4Q5GPMyYsBS809+miK32it1oWgRj6Dhf7DZZVqQRxJrOGV6Ikg3G9WOaKKfv8prqtS7cAkfgaWq2omXRuMybcz8Ia8RQSdrm3U5kLNFshw4UftPpxzAlP5snryRZOxEwCW0K/X5GMKrVf2zgftAtYkaJ+73RrtNLdsX+y/QVZkBR/dEleljloHlHqmwmhnQPfbN3hLHyJB4Q6pmHg5Fs0TjzvHcFpaA2kWaKBAk5qxNyfsOpaCQjF3yJ4K5iky2hs94uTOi/tnI7LjYKadGmEQNecIQ=="}
2026-05-18 09:20:54 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"gddeuwPJSviQZ0EElvuQlQ08411779067080","eventId":"b0a54bae49b7411891c291d17d24ed9c","corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-FEC37380-3410-4EC8-8638-17844A89DBC6/type/start","EventType":"bpms_task_change","businessId":"202605180918000006850","activityName":"经营副总","actualActionerId":"1017253114780847","agentActionerIds":[],"title":"薛浩远提交的用印审批单","type":"start","activityId":"53cc_22ee","createTime":1779067238000,"processCode":"PROC-FEC37380-3410-4EC8-8638-17844A89DBC6","bizCategoryId":"","businessType":"","staffId":"1017253114780847","taskId":101104291687}
2026-05-18 09:20:54 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 09:20:54 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 09:20:54 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779067254535, msg_signature=81509d43f545e547f8ed00618ace07017bf7b61d, encrypt=5EuOq6CbOFG3jwd/SCWt0haaOeEbuciEU2wk7aBF1VgIbyISXAYs7DUdu/tKucKM8gLpciJ9duaP+vhxS930jw==, nonce=31UHeKDc6Ld0OOFx}
2026-05-18 09:20:54 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"32d87d25df5af7e7ac439fde94cdddd27e8edf3f","msg_signature":"32d87d25df5af7e7ac439fde94cdddd27e8edf3f","timestamp":"1779067251272","nonce":"ovcTGUSx","encrypt":"jea2Pr4pR/QVDB6ln+Y+N8JfahT8drdxfP5TAQwGPVdOkaKzM6+51mu3AznLS8utHd+WP3m6uaXwuvJoQGTgF1Bh3LzN6aAfRsiEIJ+F4YGb3BRn713yv+qLgDg3xg2dShbkwnBXo6cjPjCt+HNjoLZ5OkVOT7CRP7dKnbbd3fspclovDUU7uqR/xddtanCxhETj98DQQkub/sagJ1Q/82EeyYvCuXRsrB560hOWF12VE44IrBvddCKZzLKT+3xcKOgZacEuF8preBCp8TJkbJbQklUdD8CG+fowEs7pRhWf2h8oItzogD4OcyyTvZfsl2LW/cNIUq767+7TN4tKkQPDZja7fZLWLFSSjd3fZ7OGGt1tBxFVAvzQtuWU/ZyuScvzsHNHLd7BvZQcznCxSEtc5e5Zssvn4D1ViTJyLw24HwhFgNrkHttW3kzl6VSxiZwwOWoAQxMbfOPXLcUDKYIPzm60byI6gchV6iwQXzF/1SwPTkbi1XqWVjw82ChNbyIXLvT9VftGaNJQ9SXff3p3oi2r28G92bA0G2zJyArdLd8LrI7C7Y20EY83ewBEfBdYrJU8tcjRQBOxH+upEXT1XBQxzPlrJ9x5gFD/4u2Zw3nImtsj7a+GA5Op/ppa0AWYS/US2zoQjdj9SAqvhI2p1Fh4NaKDoAEvW++jw/6SP4YFO/htfx3H1VL1UsWoS6/UCEFbdPdqs6Cg+Ryb/Fg/6sRhO1k8p9MgcNnG9mN1sI1g82TC8uCeEl4e3Lvyc2ynDoOTmy/Q/P5IyT5KElqREFlodhkpJw+ACPsCWskii7glOFTYfZfS34GgvGLYAHVr8Ed0Cz7IAIWDl2sbrV3kg7lL5/5zCB4HbLTJ8mDSH3mMtKoDdvuYU1v6EGD8v9brbq20OGPOisFNwCzmreWJJhchlYh5RwoBWLSBKYm5ufGfW9zuzCbpbQeQ6UdAPGdvkaryezFGM0n1kh2IiDZxIn2yqACFmwtJJRDstIF65FqT5Qfb5i0WLChVQYfM"}
2026-05-18 09:20:54 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"gddeuwPJSviQZ0EElvuQlQ08411779067080","eventId":"0905c3a6b665497da41a3150f99d87d4","finishTime":1779067238000,"corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-FEC37380-3410-4EC8-8638-17844A89DBC6/type/finish","EventType":"bpms_task_change","businessId":"202605180918000006850","activityName":"直接主管","actualActionerId":"176735225223967751","agentActionerIds":[],"title":"薛浩远提交的用印审批单","type":"finish","result":"agree","activityId":"19a5_614c","createTime":1779067081000,"processCode":"PROC-FEC37380-3410-4EC8-8638-17844A89DBC6","bizCategoryId":"","businessType":"","staffId":"176735225223967751","taskId":101104191675}
2026-05-18 09:20:54 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 09:20:54 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 09:20:54 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779067254568, msg_signature=5880f0cc6bddcbc9721166f5070bc51644e0db62, encrypt=+/88qIB3oEJ/Go15XNcWOEh3NGtTu+nPnnZRfcOnwgPtdDz1qKUnPoG9mQ7B409tlhlmlcRamFFL8t6JmwKvEA==, nonce=PkBtTU5XmpbTNuRo}
2026-05-18 09:21:24 [XNIO-1 task-15] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"79beb7d5bc4e36c0fbd34265f3d2b6c9263c3e82","msg_signature":"79beb7d5bc4e36c0fbd34265f3d2b6c9263c3e82","timestamp":"1779067283866","nonce":"h4dSHx8u","encrypt":"A6XARVAgEw96SAkv+2sAr4oFh9Oc8nX9p/wE71dHJWWdj7LUSKc+gn68oJ9duxQMRzGfs0Bh6IATm+pmT+RrOb851f2f0HLmXp18aOYRS4Izl0qrwJTaU1yQunRtedqwSGYIEvGgCWNTkEfrBKo0nkWuEKP4kmAn/zbgGaGP7MOiHZpF4l+zZuLr8F3+5UjyuJkf+EKfHh6NyY6+YdBzKFxtexBHtXsGtrnTQYRQt0teM7E06v8BqxooFsu7XfrlInu5azNBkY/2vR0lFSWWaWxlxg2ORjC95i37J9N9etWibnZcm0uhzfZgT3jjHavMELZLqzUaJGPSWGX5NdXybhW7d0D/Fm/sbJZ2ADNKALiltfGzfD4hSRMt5sg3og7RnWS+eIIBCoHs2LeELHYRyIpLc45Hf2qGCQ7dLiUrmXhVn6a/EhVnVtnnEJicbbfou/ddT3VRl6WvKkVK2fjMi9W4DgE3SlaWny+KJC/utHzJfXs4wohqHKwxzMF+V8YlFrnJ2+rdLbnlahp0OTrSjpT6wzV1TVVL4BQipqF5hHtbchdnxggOeKQ4EHcdVpIiWhp1ek9W08Xccb3rQMgwzdshoO1xqLgnLSXuT7i2EHAWfuSa+zUx2ROjosPtptPEoXbvkjI6As5s3DFMMrRZkaPVV5UEId5bd4cTYKtZ5gtjDE0hQFZTOkU1+uUXgHGqDgSdid64sAz9I6KMq0cLXjXDer2MtK0tmydVYlRZ0EvwWF0Np0sY6IXMaXus3iceN38kNrBwEq4UzHeJod4rJum7rxnzlE43R/ylw+j6ixtUPP2qi67TRTlwQqtyx6hHK7R2t7p57k8igVQAFuNFxJIZfM1OydpuGYC2TAb6oXKkIgWTh5M7qve88GQupZN+LTT0VpvPKMfVbDJjGstxpcqR0efjZ9r+wr4u0GlPnX0TE36IsL7WfLlKpwf3mcBVq3qP7MCk++m9ujV3KsaSqejTSuXUCQU2YH4AGpO5tu9CyWz99OpTME8ucOWnMFNw"}
2026-05-18 09:21:24 [XNIO-1 task-15] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"gddeuwPJSviQZ0EElvuQlQ08411779067080","eventId":"0905c3a6b665497da41a3150f99d87d4","finishTime":1779067238000,"corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-FEC37380-3410-4EC8-8638-17844A89DBC6/type/finish","EventType":"bpms_task_change","businessId":"202605180918000006850","activityName":"直接主管","actualActionerId":"176735225223967751","agentActionerIds":[],"title":"薛浩远提交的用印审批单","type":"finish","result":"agree","activityId":"19a5_614c","createTime":1779067081000,"processCode":"PROC-FEC37380-3410-4EC8-8638-17844A89DBC6","bizCategoryId":"","businessType":"","staffId":"176735225223967751","taskId":101104191675}
2026-05-18 09:21:24 [XNIO-1 task-15] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 09:21:24 [XNIO-1 task-15] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 09:21:24 [XNIO-1 task-15] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779067284173, msg_signature=95204a48785d04eacc16151d1878a733dc752134, encrypt=yyo2Jw6aMJWTOO+bcNysFULpTb/YtF9PlQRw9UJAH74BEaldtNI2a2NTJYTbJol73nzxsf1r65oRPaOu09xh/w==, nonce=krm7frOO8vMr9uHN}
2026-05-18 09:21:24 [XNIO-1 task-15] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"8a82e0e44bd62debe4164facde6b8b71356ccf0e","msg_signature":"8a82e0e44bd62debe4164facde6b8b71356ccf0e","timestamp":"1779067283949","nonce":"PwimurBf","encrypt":"akmLcPwhc1zipMYclAr9ua8GDZEQXUCY6jMCyTl3jAIm4hFbwubzhrflz3rctA8x5Vr4KkNbUYC0AT1K1dVzLiFhnDQuXWIGEfR2My2PpWWKqpn+JFbyI7kG75wRk6wc/I1MLRRMdpQc9+yOwBegs6nmcawC8mVaOkYCCXhKQFvom/KbLujkD7j26pAUE9KEPSdGhnC6y+n6S5dumiovCdmiKUYO32OzfAO8XSBebPSlFX1fdPjqWPPAbieRVsE/kKJMAg+ARQKj2YTXXKBNFcF3GDgkBsGtttsKEY9cHr3Uma6fpxBuLeHorTUAg16P82YpUkFVYVkkxKTlm2EzNAmEgzOodjU4WcjQeXhBX0VSiM5LHkHyWe9LzsXUTPCiTmTVS+IKCYoLoinBE7xikw+XLS3+ivnrS3oslICsu85OQp59dL7Ai1dvZg/AQmH5OpBAGUywhwH63gvFi3rkzBvBNO/ozUNOwdR12H+WPmtMKyZAXJFs17yAROEoUldqR/W4YRko0LLQNqlIfrRbOLB7nXmR3rRYXrg8VTSw0TsklyRbQ2vkhpcXbsYtUp7Is/p/laRvne/knhnxFlLmXGpSrdOFC1NLQ1HqV5wziIB2buKRQxcLISqBNtLaPa+5MuZ7/BeycjsZk6waWv5vdbBppU6+EZ8PbGrPgUEkqLSL+JVp859FYU9XBX+jxNCH/BKgwG1e19zu/M72rlk/NsWTmEpMtXIQWxh4L3SZXs5MDySp/e/hqobaKBjn3k/5Of+vysn90z7QdrZz6i3DUQlAbdWiklNmIqv9eJqZyaxP9uNHp3phgpxiArbmA1/o9ser8Uvh6QrHsUdpohv0KMGSrMZFvzwMCoyc95QRSs5QawEzNz/oUYegCJUzD0fe2CNvbKYfaGG1MDCKqWOpG87EcpKv+Y/BGnleitma9xjdRGJpHCl66JWihn98aMstvnnvmjOC3ATpu7bXLrSAhw=="}
2026-05-18 09:21:24 [XNIO-1 task-15] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"gddeuwPJSviQZ0EElvuQlQ08411779067080","eventId":"b0a54bae49b7411891c291d17d24ed9c","corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-FEC37380-3410-4EC8-8638-17844A89DBC6/type/start","EventType":"bpms_task_change","businessId":"202605180918000006850","activityName":"经营副总","actualActionerId":"1017253114780847","agentActionerIds":[],"title":"薛浩远提交的用印审批单","type":"start","activityId":"53cc_22ee","createTime":1779067238000,"processCode":"PROC-FEC37380-3410-4EC8-8638-17844A89DBC6","bizCategoryId":"","businessType":"","staffId":"1017253114780847","taskId":101104291687}
2026-05-18 09:21:24 [XNIO-1 task-15] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 09:21:24 [XNIO-1 task-15] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 09:21:24 [XNIO-1 task-15] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779067284284, msg_signature=1060174513b1905783b450de2a1635e1977ac428, encrypt=pY3434wnokRJGxJ8KvN6g5UJ5rLPBkwogBf/Xbpu9OZ0L0DP9OZtGm1U26wEWR3CcrgZh8cc/qQZt6i4y4xNbg==, nonce=WV40VadIIx1jKbWT}
2026-05-18 09:33:58 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"00c7089e8749e12ff92a76e3617ba29ddaa294a5","msg_signature":"00c7089e8749e12ff92a76e3617ba29ddaa294a5","timestamp":"1779068038432","nonce":"VB0SXe4w","encrypt":"iQMOsJsL0p9y0qmVG61Yc2AYK9qV33ybWiwJbeHxK4Sh4oYOrpvLLp7l0uQRLjQL4tKZwgxUDXSbuuHku2LxaeEjukwhJXdZ+ztBIh71aubzIe00kZsBeMnSmRNdcSlt0GXrKc/iKYRY8rGmePWJPGdf0rlzrrXn7+RkKvWEcuAjO0Mn85UplEz/p755M6ooalQFFbzCTq0iuw/6qX2Txe8oOxzTm4HTppag/2hXZWcEbpiZfNICTEpgCrXjCx0my2Vi+kgJ1TohPFmW05Yjq47bLUY78zzA5Ae7fnyz+lB57XJFwmVkzlSeWVkipL1SseSaDiesQZ8YSuf5jWnvpqAPf00FJSLXcSTZpk004QWICePMJ57mNvU1EXlMwQKCnzuRO97pMrgPE5k/Da52muDVbaFQzF5Xlc1SY4TD21Bsws51hDyInoHf4JkanmKwHwL8x+ew9czbMZdOTJy1nHPFZ9NNeLe8ncSmr+jeKmkaYio2fSxy8GaTN/7E8QpBogsQMH6JYX8HsLkoKWyR95mpzRCxq27Es+nusuNXitITvKkhpdiha7ZtS+aJcO5q5z+ev/zt1G9Wm2uII4OVWx/LmCuxGrIMWe5BAN0pWVqb/Jlvp5d1wULlcdNpIrG0P6GJ+tFwipCC01KbFSqyrG8UrRD1qqO+uZalS2MzahzmLqCse+hIVmHjm2VkCW4b7s7LB2Ep8zZO6/8bTGtZbRdyJSucIPP+bQfjLypGaR7wRSxg9vPE+8Z6Wz77Sl2cMo5xD4EslEGBch87yBIRj5+gnKMuJqrWt8nWQ09Hyy1Q2NGl4HNmnkJ9cDN7kOTfhKdz4sVxiW7FrHq88mfroMvOSsQu4dVq3wIoArCjLuj5SlZDOzNpR1hLZTI2ztGwuOm3ihi8lA3S7BXyAaB67fnq3L5A9M2V1S2ybttCJcY++YEx6UFXyjDt+2ZxafBRo4KADM8H56baag9F4nM2UiAtw3NVINgnIM+J6AjMcOH9ZcF3VsCrn1K7ZqEFcYerEPwJECJRaBpIlD1f/rcy9tIs/EhmYSe+FJ1BiQj9RVs="}
2026-05-18 09:33:58 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"RywCD4-WSe6yxrpgQl1YGg08411778914559","eventId":"18b267ff3d264935b88704f2622951fe","finishTime":1779068038000,"corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-A59BAFBA-8AAC-4943-B4DA-3FC964AC47D5/type/finish","EventType":"bpms_task_change","businessId":"202605161455000597391","activityName":"生产技术部长","remark":"","actualActionerId":"01201038164023402380","agentActionerIds":[],"title":"位晓峰提交的售后联络单","type":"finish","result":"agree","activityId":"b689_7c0a","createTime":1779065223000,"processCode":"PROC-A59BAFBA-8AAC-4943-B4DA-3FC964AC47D5","bizCategoryId":"","businessType":"","staffId":"01201038164023402380","taskId":101102887296}
2026-05-18 09:33:58 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 09:33:58 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 09:33:58 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779068038774, msg_signature=48eb20770cb5445821dd9acaae49e65306a3fbb0, encrypt=ZmMNQ4SpTt1Y0HTZgHb2uP4JhzVwhn1YZyCAPhX0MCepAC5pTDqih06n1b/PY9vZ7x7/h1VAGcqrLwN5gaxW5A==, nonce=sPBq3nXBDERbzrjQ}
2026-05-18 09:33:58 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"8af1a580c87d48ea0dd6589978e8b8930e5c0cfc","msg_signature":"8af1a580c87d48ea0dd6589978e8b8930e5c0cfc","timestamp":"1779068038580","nonce":"OVfazdyw","encrypt":"YTwbrOaceTAgRRY/SnDdB2wqiGYftzaWk1OulwAO+HLms9oYkArRLGPfXXpNRgjqGrt7UpVeGHmp5Y1nywGHS06m1XrcwCA0QhCSozp2PGpe9xUW3a1fepv4H0zeqaFwAnqPz6J+6drYDERxha4Zuo0TknvRaL9QS4eLPSGC+sm+XHe1/RvDcS2sOuCetBbE5kbwvrbeSDLOmahOJa2K1N8ZEU5jypgXxvL9WaaTy8xS4fjJa4aRFLX2DpWBq2R5xJ5vad61lwUMOu0tbkUvg/oqryAi0UzH4Dj44JKn+jvUULBKqOXzn/5pJO4fJpL7h9TlBkH9Fwh/yxyhoiUu9+MO+YA+qthEgeF8jK5mnYI2f1sGXCKqQc19RK0cgdgSymYLDNajW3WvGrdMqOV3DOGXi7PZdTviYccRQQTIuSQ5af6Cr3nbBXAeXVTd6ziou4mcOfntzwbLRQGPj4YmLAq/0B8g8ccy7dl+yZ5S8bqOsHE3+kZvDrJLSnpI7+TJBjbV4jr8hCAmZzwKilUNCs3b3FxHAsstNqrmvX4ETmsg/kJshwHJbv+bNVnBXuGiffR9tRbFcSCYJRkNqMz1qwTynjWf35A0kolM8VReuXeaXXNSH3AupnsrDR6SBuzaZAmajNXW0ebroiHsAtCt3X4FExjvoqlgUY3BtxV4doBkPrCBMSSFTHfXkF6wjf2nI50xnXFTSvP9B25UYoI8aXbp903H3l0Zl43Y38lV0biRzrLp+PbCJFIObpdcW4J4pfq6YbF2OtTH9wIsVLOLu+IQx8ao8++E+RoY0kklYKrrdbAc6n/ARC0VloLEPGzEiso0TOitJT8aCUVOQ6XMsAkRnS5zcBtZ+ol9LOk5xJ9lAJuNue0Bu+KdFSt8Fy9nJmucm9KHviYLgiAYyfWX9kP1cxwbTC0CpH0D73vWmRYF0H2J93BkZKb3kLP2XVY/JAc5IuC7apYoUbIWG6cQ8Q=="}
2026-05-18 09:33:58 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"RywCD4-WSe6yxrpgQl1YGg08411778914559","eventId":"b3dacc863f0f4aff9db33192bc73c90f","corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-A59BAFBA-8AAC-4943-B4DA-3FC964AC47D5/type/start","EventType":"bpms_task_change","businessId":"202605161455000597391","activityName":"副总工程师(非标)","actualActionerId":"3816683726197864","agentActionerIds":[],"title":"位晓峰提交的售后联络单","type":"start","activityId":"d81a_b76e","createTime":1779068038000,"processCode":"PROC-A59BAFBA-8AAC-4943-B4DA-3FC964AC47D5","bizCategoryId":"","businessType":"","staffId":"3816683726197864","taskId":101144070875}
2026-05-18 09:33:58 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 09:33:58 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 09:33:58 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779068038875, msg_signature=429091eef1a6ca0859bcbbd7e39ca09f095a5fa5, encrypt=PQYxENQScJIy8rbitFKYUpN8s0a8Feq/aWzu3FHcXQhnKKs66yGp/14KHNUIuWjW7V/a50rhXoktnvAEC16u9g==, nonce=28yQkBs9gIlBYNzw}
2026-05-18 09:36:01 [XNIO-1 task-13] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"bd29bcdcefcfc9b1c7d9685d5f5e199ebbf530db","msg_signature":"bd29bcdcefcfc9b1c7d9685d5f5e199ebbf530db","timestamp":"1779068161568","nonce":"Jm0fIjMk","encrypt":"HKMqjypyTMjg4e52c3hlHGZWmoFQjOzsBJ0982xacD101Sdo/+6SzwklBfAikf1xktlGdEsrJOTmsqhOTJcthg48WoZhOm0M1R4MrXXc4zmtek9b6vCKvNL5qBD3mJdH2RxvXepoY78pwKSojFZpNiUUOdLvTnIzQLPEngEY29SRpka7yZUHb8liymOJhDrcB5CwFHbYsNdETAb8nUoLJTCGS3bREdJBqnSbTTa7yavj1uXji/82nvTLLqgW+NzpbaNYdj23glp5IwzrsT3IRKCJurEHNMIjh1emDoUJAqsz2wYctYIj+BUpwIZrU9bDEap/hyQmyERiWwT6RvTVu/UTJ+9e7a/n6lR80539MrsU3+kVN5nNQpO9EA7dlynCuTFKTYe2ebuvOdieCQ4OWRH1kL2KKNEUh9Je+jkaYLurGdtduCGuGT95Y58nCFYcaUFxk0hpg1bIu/hqqtH7DCa1JLVMHTM5N//iVzlWcHmxMbhazbaXfV/r5TZAY93BEYtloHeK56tPg4fyqEZKTVNU+r3yGVc3xO6RYecSHm2i5mJvtCYAAxnHAQ6RB3HLyZdX3FsJUqrak7uHCFvchfYNz/BFtU4ILmDgmPYXwniIYbQ76N6eDlnN/ThuMC6r9KjovuyiuBKxfe1CNsGci7fyrvHqGQ0rdwtofTIFYI4Oih9DtEYuLMJ5XhR1eC29FXtUoVRHu8r8Npbb5JEJXKSPne7ZZ7R66QqJ7KWnJs/GunfKmR4WNDyuyzVQy2thcfBlBygdGGVFxlLYCbifIl+M+FqsAu61CrjcfLklFsAFWPZf4nKfmyLy0oGsTJVFLKW9BN8+VEfd5Ayq+9KTPsrDH1bDBfhc2XPdHSzlF7loF8W6EpXUAALjhdZ//Cy7Zv5WYs0Fvk9QGteV/5BA1J2azb+LFp63bI84sUGpdX1T/Z92AvMvLOYc2bWiwPJ5i+2xEzmAXDETCuONSiUczZJi9DEQ5QpdZxp3RJom5KKsquAPksILI25fKnDxWwUg"}
2026-05-18 09:36:01 [XNIO-1 task-13] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"n7TPO9MCSWSMTowwenjDNw08411779068160","eventId":"8d6efa7de0bb4a9daa97a384f8afdfaf","corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-3E5AA98A-55E9-47B3-BA84-0D2101BB1C35/type/start","EventType":"bpms_task_change","businessId":"202605180936000000713","activityName":"质量管理副科长(制程)","actualActionerId":"173760274129324770","agentActionerIds":[],"title":"师敏玲提交的不合格评审单","type":"start","activityId":"53b4_05e1","createTime":1779068161000,"processCode":"PROC-3E5AA98A-55E9-47B3-BA84-0D2101BB1C35","bizCategoryId":"","businessType":"","staffId":"173760274129324770","taskId":101172625123}
2026-05-18 09:36:01 [XNIO-1 task-13] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 09:36:01 [XNIO-1 task-13] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 09:36:01 [XNIO-1 task-13] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779068161881, msg_signature=778de7c38b18001fe4d495582d76d2ac1ab26758, encrypt=EGscNi1LyD2n7YTnomPcWIfn2CxzXopH4w9wOWviN1hEX6ZCtFz8RASwX+j88ZOifudgopBsoLvG3YQG4UFJ+g==, nonce=JP1ZfE9o7w0X1p5A}
2026-05-18 09:44:48 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"c4da823cee21a607add6bc114b652b929a450405","msg_signature":"c4da823cee21a607add6bc114b652b929a450405","timestamp":"1779068687878","nonce":"mjCyjLDu","encrypt":"mAGrd4oNl/UP5GhVYkyAF2MgbTc+XiebtuiRDW/Hrl1yW84w/GE6IKS/jaEFgPKZ/hdXmdgRhMo6CR0AyDi4yDzU1LkAOGs3GC75z6hQKyXl5qJAU2JLRtCqssGVR44FgV7x8+eX8twOC+8mYpa88rlmGVceNdJEJ3yRUmSIj1eowTM7yFq9by2gZt1ioRw22JLFFUF0Hq+UOR9svXq8K+PEw9Zgq/2aAemB2ILl6FhJLfmyTApkyJcJHSjKUCQ07SLaoBfzqrSW5raeUrDcNQK7BAjMvFI5ARCJ07dU/KlDKezHbH3QJmK7dmIPXl/h96tuzuLo8QTzd+uqL1Qp5hlvDUAMU+OgVxLdGriO9DNfUiAwwgdB+mpKkGBiAJECcN2IgHtfjIkTL+Wes3tlxKoAUgz0lqdFH8Ds0fjfKdFcTcJnCUbEV0K8duR7GrRDrTfxJ4ncGhGVRSPUEvg2zKnrzp8ttz9m/i4s3dgjaHny4vuGXtccNthY2I1A9uajuXmGCnqIT4yzY4z0Wc0uDHQo3XrIZbRHWt38BBkO63Si6CYLFUqGHxElJEFaE5F2pnmrug2bs6bHiz3MItMKjTumLwTRVnLDAxp/z/TatMUNtZrPT854EBNIm8G8u/4Hn7hRzIB+F8/KR5ZWMm0h+B9KB5pEKXtsyjVpMQoED95PogzQMohKO/hOw6orMVrustrhsaYW8j/IZIo8F5mPZe9oBU3Yh+bVI0R6+GVI5MDIDqKfucLh8QRra+a5iovErEDx0SOMKCdRTTGPNmGIawvq1iY82ovNkDPzH6Hn8D5Lf4VWwbYz3PHm0TbsT/cOeLQ61BFkoCMXUJyXtjKOaFqsP+pJIBtHX7CDLJ7VB4YZ6r7lrLZDvsqwnTp434Y1+yjTuM7h17hEeJ+O+bTbBzdNVvNeNAnC2xZwmsMneg3UC7nvQ29PJBoFII3c3Inwx7l9WVF8tmLsY2MzXvUMwpZhEplF8AWEU2Q5hBsIlNEXHz08Icj1TNc/KrQxaD+OyOxoWZZBAgeFN+gEf2i3oKFTdUOD4O1uTmDvG48RMY7XZM1VZXK+XRfhlACpeOk0X3bJHDeVEYdxuRu9GOu0gA=="}
2026-05-18 09:44:48 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"xU4uJ-I8TEutJCaj6okI6A08411778812708","eventId":"7b6e4f64cbca410d94af2156460dc4ac","corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB/type/comment","EventType":"bpms_task_change","businessId":"202605151038000287274","title":"陶佳毅提交的技术方案申请表","type":"comment","content":"当前技术要求下,杜惠斌和马杰这边无法完成当前宽度下实现客户需求。考虑到方案申请流程的变更,建议将该方案提交给总经办,由领导判定[毕敏霞](02212765235927371076)","createTime":1779068687625,"processCode":"PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB","bizCategoryId":"","businessType":"","staffId":"231850251526222856"}
2026-05-18 09:44:48 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 09:44:48 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 09:44:48 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779068688212, msg_signature=621c39eef50f73d3ff8f01ae304147bd574c0218, encrypt=iHlTuO6mLziFbh7X7V0+vgIZbeGkGqHoQH55UEukfDRVqVk1XriuExkDCs7qOMMf+hwEDjgZBmmHEpGkDh9x4w==, nonce=7maX9uadzqzhTUdL}
2026-05-18 09:46:39 [XNIO-1 task-13] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"f8087ada1ab2b7a81180592eef03ab95b78dd1e7","msg_signature":"f8087ada1ab2b7a81180592eef03ab95b78dd1e7","timestamp":"1779068798717","nonce":"bQUFx6nn","encrypt":"JSJu0D5wY6Gu6I4Hm5JjfytyZbrbQibp5+oaIKtiLDaMf+LsD2Gv7X58G1OUW3RB6iF/OTKUrYibbE6q0fhlEivOTw63aoU+vAKfFZsgEN1B+miC+oz3JsaDWhk+Ra2MWqVjH1jmoHeSAyJ5pMrP9nJWxk0L/dDiSex7uOS8q1zaF5UoXgUErAAZtRBgB1Z3z9UoPaL9aatYob8LUdt56LkWdSW/HDwgCx/2arD5/m6pEdbpIHzeWnoIrUc+OEyZHPqdqSowInPaIysk3ED93uJYOraliSbB7D4kV2bsepFlsZkqMc30msSKcomtNawZwWVrRIdQPMhstdCrffzO2vjYqTiLSW6iJRjIywFT+MnVKdz/Hu4DQ1vNbuB6as6jsbG4f/sTxqDvGGyBn4GpWMVuGNPgK4Gef0JAA7DdE9xNQ5LtX9vvZ58hL1JKjDuRnoAhaCtKtabCyQ8LI+Fm05O99oJywrjrN30lk7mwHWKnZHzdKGQdNFgKzG30r3JivsRIdssWX3ll4ziqNTJxAppz1KQf8dFvy2d5vKoxQHJ5jb5AxuVgsEFJXORbucxI+o7OxgkeqjBg02/FX8bU//tUEUOR96BDOJA2EuX8dWIcn0ey4ULgBgLNACqI0yO9JdiFi5LQeS/Z8uW8hWaRoTwhVrOwwkp0c3fOJD/gp10mi+EhDiWX6jbmg9auhr+pqJEmB8mjinW7BM2o/uePhFFga9QYlmz69Ep+0x1heu+e28o+vb1wVJfAD2dGIJ+MfPH4SnE+vGzFdCGtczS3WnMOHDiehUBtw9+HQyFXFu9X0GtpEioCOlKlbXQRN/c1GewPjixLAv9FKCZ9rZ/mvxdxhXYlWMSyNRpR5ecXCVd+3xtX99kKUeCO6eM2w3z24shnDSDhChVFywAYdfii/Ki9kzmGNWVTok3ZAv6vkoaGn6wt1T/p40ywIa8/qKronU97jQ99Tc7K7suEmHS+xQeE1auJVzTYdCeby3QejLJCNAxMadEaT2wCZmNIQg967QRjMSCnthKoLfKvw91IPRn79iUMSemLyXQPuMYHIFc="}
2026-05-18 09:46:39 [XNIO-1 task-13] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"GFB2fmehTxGfA-nBZmMRRg08411778893677","eventId":"af5ab9d071294855b9c3871995e96385","finishTime":1779068798000,"corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB/type/finish","EventType":"bpms_task_change","businessId":"202605160907000570685","activityName":"项目负责人确认时间","remark":"","actualActionerId":"283111015435457273","agentActionerIds":[],"title":"张新怡提交的技术方案申请表","type":"finish","result":"audit","activityId":"76d0_7eb3","createTime":1778912734000,"processCode":"PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB","bizCategoryId":"","businessType":"","staffId":"283111015435457273","taskId":101190348445}
2026-05-18 09:46:39 [XNIO-1 task-13] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 09:47:53 [XNIO-1 task-11] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"8d5592b92ab7d881159b10a29fe3c54a8d41f0c4","msg_signature":"8d5592b92ab7d881159b10a29fe3c54a8d41f0c4","timestamp":"1779068811328","nonce":"Q0L14cMI","encrypt":"QHkX41oVsp6QPF96CRR1yRGGEU8Xvn/FCNu1CtneMfBa42Wo+6vLtvZ3ZnkGzy4NUhi26ssmbrlZRWZsXK0PD/kpEawXMogbp79zQeWkyGGO4HnntH8JFdV/K4uz0QqKVxf/1cg37EITwyzuEvoXu5htyRCPYeiBt3ZNjcZj8RrQS9+VUMTY42r6zc0Qt0KPmwO04YtioOwi+XDzLh5kuB3YQ2D0a4UvkfwO173EB4hB/X9mVxBRVPTEPJKDky+BXQQtOAeUc2L2V/+9iJLdESgiY7alLOn6fGtDUbdbqL/w6WuftN0yREYylCTXNfvuPHY29YxLYvbZPcgontLtY2+FjvCda8lXu3olNx6DygXVdHIFC4tRCBmLoM3HjUPs9cdlTXXM0313K6vDp3MxO95Gn1AzFcQ/JZsZ6AB0jfPXXOGS2qdfVwMVISx3btB1csOn6jx3tWyK596M9XYoni1gmLDI+UAvco3CmEv9N0Ljw07AOtCzHOB363f/V0zM/c6IPptL3WtcTi2+5ujdDKEw/GxR2rnZksS0EkMmZv6JnN5yUIx+EM5MlZzd9X8vZqQ8ckuVsdT1XrvGD2UGY6mfaXNIB/fcWi18wEOfppfxjIjqUyxfjNYc+k/T6T5bdNTBUSyyBzw+BSddi+4ImRa3YX3EZnxVffig3D/A2Y41bLpRTiCGWacuXDlj1Vf0DWVfBuAOv8tw5IV8J+8fV1x3GDoaIPjKM7JIJ3WP5pYsUxCY5ILIaxxmh67XwL3LrE+tIVhM8tePjeRMemBJn3w2wZ5MjYG9YCciqnUdmXEr1UNt+hAxajMAk/cRo4INW9hjtUUDdGg4pMIaR17lpFxUFna+YxDV8CxOUP9KQIEK4v3hl50gJnm0m5SgIrr7rZBHkgP8uIRq1wBz15StZ+rtC/CYwvgW8h1+BRZ9WGN6O+Ghaqfj7r5XtDmJpdm90UHlZaKTAhysTIiRX26h39naZLFybl8bXah/aHGBSji00Vsaqs9Xs/Mm5aahsJrMHSpxFyTtsdgZXukPDWbbALRgEeShGx1RfmCGovSrr0s="}
2026-05-18 09:47:53 [XNIO-1 task-14] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"4562c86d3a89a93f5ccd23cc1df88c7843da8c0a","msg_signature":"4562c86d3a89a93f5ccd23cc1df88c7843da8c0a","timestamp":"1779068798725","nonce":"fTvamjDl","encrypt":"Y9ZBMp/i7p0RbrAP0aJjXTgy8TfNMxNPExGCmVFG0FkQmbq4nuPQ58V4A3ci8WyLPdnZ+qqDfO+jYDsP55f543G0vZbxtZKpy4bJbQm8k4pKTa5S64d7ZVtsLBmXhrvL1qR1SnLyHf/Ivj9yi7xaQfAi1YsK5ZBQxG7+01CZnBWU7KtLBIZZfKjBLg+QBhjdcrT8MBTbDCjPH8eHV6U6hcPL+Ew5h7y7iowb3SrT0iIkVCPwyn3XSpPJfH7ZG75jKgMkb7up69uPBcJ9VQW+W3/005rnmlGcmbXfpTHmURr7cbywBlWDzS51RY5RUX8oB0eqLmd1YzZw2t5eDYNHbTT85C9CDRy2knVo5kLegvzvikgFXV8ltRxPT9BTGU2YNEhUrXu+vMHErm4PJ0+ZsjDSbiUMdxua27OVsh05uUcxvcivUwmyrGgmXjmJNti34OdAVwNRWrn2zossdb1l9JlNtt/Et3V2nAp6N/5+REpk/6qlpIyCvjydU9FxspAeM4q6nHC60BhiWfn8km/w+q/k5+qEWqflFxV/PKuWSxrRgOUP0B+GQNrQPW4pPdxfZ+o72ISm03l0oUXI+XuE2QYR0W8hstS8O6xlwJmAzbXKGL2IeNEYmb4WanQRVGRUmRqiYW3ACpUHCb/5XH24mOQKFN1LRZB0Yn7dIZARlsPOpTAbNlFkRKlapygysD77idQ0T97OA3bQdykVDcYaw9WWZMgItib5ZsdT5Pn506tc+rNbOviqHr48WwRiOuS+INzbKF7qb19i5ZUmbNZwRZ2qxp3guyqGb5w9gFnFNgsCaZF7yu5OtMjEbHChCquzLHUOdOQ2nitiXg4+GqtktGwZNPGu4VOOr82+tJp08P5tBW3EzrzOkH+23ZQ4euKlq1G8sF19sBjs+oZut9Q3DGEj0qGwZygeUl8SDg9okgfMr65ktWOC83eH1sita8VbKroS2JSd+oH9P6z08kzuaA=="}
2026-05-18 09:47:53 [XNIO-1 task-11] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"GFB2fmehTxGfA-nBZmMRRg08411778893677","eventId":"af5ab9d071294855b9c3871995e96385","finishTime":1779068798000,"corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB/type/finish","EventType":"bpms_task_change","businessId":"202605160907000570685","activityName":"项目负责人确认时间","remark":"","actualActionerId":"283111015435457273","agentActionerIds":[],"title":"张新怡提交的技术方案申请表","type":"finish","result":"audit","activityId":"76d0_7eb3","createTime":1778912734000,"processCode":"PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB","bizCategoryId":"","businessType":"","staffId":"283111015435457273","taskId":101190348445}
2026-05-18 09:47:54 [XNIO-1 task-14] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"GFB2fmehTxGfA-nBZmMRRg08411778893677","eventId":"8babb5e69cad4391a5fb54bb421c57d1","corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB/type/start","EventType":"bpms_task_change","businessId":"202605160907000570685","activityName":"办理人","actualActionerId":"03462113426124233873","agentActionerIds":[],"title":"张新怡提交的技术方案申请表","type":"start","activityId":"25d1_3948","createTime":1779068798000,"processCode":"PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB","bizCategoryId":"","businessType":"","staffId":"03462113426124233873","taskId":101173037254}
2026-05-18 09:47:54 [XNIO-1 task-14] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 09:47:54 [XNIO-1 task-14] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 09:47:54 [XNIO-1 task-14] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779068874421, msg_signature=87ee2a6c56f2b149b3f5434bae4207de8ea36740, encrypt=pJ8f2hb8Zvu8/HJWP/H776+FlNKCjlElpNL6l5645gORrLQvdvQjc/UJgpVQCyZTpzJ2UGQv4HfdSzloph8efw==, nonce=OB1E8k7ffNe1IRWW}
2026-05-18 09:47:54 [XNIO-1 task-11] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 09:47:59 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"815efd81c932c988e2f886f167c693233a1a13e6","msg_signature":"815efd81c932c988e2f886f167c693233a1a13e6","timestamp":"1779068843969","nonce":"NfKtKa29","encrypt":"ETShVBA/eLfP6u8116RcjXVTro6ojyqNLaRugCnpd6PpShVmXZ24O+ShT135b6kCdfyVW1JpcZClpaDevkBgHa+T3n7T4VF1EcTBWVVqLWZYjL982jPoBSig6EdhV9FJjXB3oRu7+42uhdZBnt9cl6YUeaCnKJVXJckdVEN9DZm+w/2wriwVUNcuzAaUB+n19hXQ5mXirl9+KBmq8nbdjCLWpZ5QzMJmPj/79bFllrsC0lNYk9WHeetHxUnR7n2yP4XwEkWt/SSATEImpZgvPP/8dpkcIAgOATLuMkJAbwp2JlGBgCd3lncx491Q6KyTUHoBGm8wym17Ltp5MaTbFXFFqc5nvUahM8OekfruRAYN4gkr//JOGB+vkEJbwgxjq+5br1O0Cf/mMkMiMqBoR/Ope4H6C0vTqAyaChNGIzZRZp8DFw5g22d/+w7g7ZSUUvMMFV3exSN8ok2Cj8yjw8KrWMg7Gv2jNQwGh4vaX3u62NxakXxdtXcXKmCWa5TefCDnnBarHPbox+rkUC40eHmgmkvqmJoJMqbLD1Xrq+hbtSOdJXidU1J8wnYb0DuWRmXFgGG+253oWrmyO6Oy0K/6jqC7RZt7cCfFUjc32O2bNUegpAxM48gtnrtoy+xhkQmIlBLtP/WqWLQNogu3OSGXf43GzqiZpSHxj4jbC7yy9n8/FiRYe/LHd9LAMXBtBhP82mkAz0Xz2E2gs6nYzCjAsAF5c9xQNGczZhFD3tNCMN2oQanap3kT10EI5U7xAFIDCv1yqizYv7ycZQ/ULkGCTuBU8+wcZ1P58eoukBsSXQvDzwx3eaAYEGQjS1le20eFOBHxBquB7qfpE2jFpmzfsrKiNlHD1XGXzWOaeb5U42Er+vsdaaXUz+7TTbsKrmlfKSzm6xtwaoV/1uFXxvQ4GSRKeh6yMNnBs0tlJYCFLO/JOEQ1tncbQ2XTWAEg+JCzQa85m/W73gpyy2yQgEMLPaCJ/L/BOKtK+25Sgdyq498G6ydPfzf7Hjws5PV8WMiU7081HS/Y7Xwn9hlKAyMtoCbjGRqCoGgFdK092VI="}
2026-05-18 09:47:59 [XNIO-1 task-4] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"a488a8a0594d89c01a28cc0425498ea3b34ca516","msg_signature":"a488a8a0594d89c01a28cc0425498ea3b34ca516","timestamp":"1779068847935","nonce":"ovAQwDjn","encrypt":"WLp/z+zJTJ4rlwmbqcj5rUn3q+n9sTPfxfQS3BUxp4uctrzo3OUh6dzasVX4q+3OtVKDjI70D7LPWq2ngoYiBQfhIOxg3aKpCXRiwQ1SRVo6mRmZifch0kowTQST4Z7EYDQS6XT6HNf3orUwRmQw928YDzgkhLBQBKepLh519Dar/AS31qdkqZ/8aZZkx4OLNRn3XL3E0Jfm1Q1JDSpnyPMZdzY4rb+zx7Jw62QVfxJRN/4LHXu8q33QpoeKzOZcrAZ5tah4ThqePidg8giLA0iS+dX6uDqIsViytIpff8zTl11VDFWvRK7ixfEXhRgb6vSNRisedWpgoWyBCNY27qnJmqXEaWSeViSlVrUb3t99ZZLxPe226sukve+F8MbMC3DnbnDZRo4iSim7ioVynOO1ec2g/BSCKJbcyNJ83R9KaKxcc10ECUVWh1Oy68YhlYmdi7ovPKOcoG+AF0rgHVlf2o2Ef2OJbypj9WoYYY/VMTSTJ5WhpIjiBHB1bl4fmpRHu4z+R7wEwGsU6LBvSEEXvHZ5YvwFOOkBtblMo8F6Na8P7ja+ox7lBNV+fU6ee2uiLrtBFrk0QvaB4POirCtBaI+SOOAnpzwfRAALv6iIsI94BzOenUYcabC6KPUbLoaarBmhBNkdjA9YF6rzqvlbLRf05Tnx+lphsYOweL6x0z5xn3LycgmRTNR0ocgALUnrkdl1Tx1SBAzVzzLUXqnLbeYSqGUbSFaVwjnb0af5WOyl82hecwnvvjQBQrWof5xMP0vtz9jFrzdjCqvI00ZVlqriXnW4JHohOyO2u/BhfHv/yqvz3+4BR7h7Pr1zj5F/Z8C3Wgdlf7TZp5PkGNnsxvVUXHt/jz9gReCnxh01Z8ymj0it2riAS6OMazdHiGSEJt+tEqDOWp5xQGGeLe9hF3Jq7DP592dDl6h5OpVA6lDIFBVtSCzTRB5VmiGoecx7/REBfZhqF62w6sT5FSKji1eBvRxGEWGRBwC7R+IT6Hx3hlJXWXcGrRH/ZYRj"}
2026-05-18 09:47:59 [XNIO-1 task-14] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"2acd0a4a2777fcf0e2d83eabf8ef083dc07d7a24","msg_signature":"2acd0a4a2777fcf0e2d83eabf8ef083dc07d7a24","timestamp":"1779068847843","nonce":"MCTTM4Um","encrypt":"Wvs7hwa9GKXtkOYj6FdmUTh+7k9PU0MdDLPJALm/98XS0/URxOZoH/xPBkZXvI+zBNBO1baE6ESTWVXADNL/XPEw+ctHmdGjMqVIYIuFQ9k4tExVc7Yzex1cSxsF7tahi+PzuE4Va5N5Ewn8fkh0lg8oO2UlTkA28iom/8zauGhwkklju09Wfa7sJymQewH6xK35BKmAGG7w5JEu9t1cXKXwX+12woQ+W8mmDKsbmKpnfm9JKUNm5+6jQ0r5/QNGVLwawh7NDGQu5bE82MgDJSOMp+IGg4pMBhA3ifW8o5B2H5DPRnPHgbv41K6UgsiLrbNXfeejZjk5pG2d4TSqu9TNRMqXdLADPieMTNUlMVY1rSnBCym1NM6jGztHKCEocmlRwztWrytd1glANBwCqMlyH1iqBWk/LcyDuMRibHtSVAxZfxj+BqjzQnDunpUvKgwEStON13Cte9R4ajh0D8IOnd7bkX0IYA8G2HeQ5Kas7+7q3iq7tenq3pDbcjiDBk56xjgMJB2Uhe11NLWp2YpZ/JMkxdZolJtf66v/czlksDsj2v11yeVkIXiu3mRHFowjTAV9X7BYWjgjjr6shpV1CdsntaTIGhacDeR5n8p0w6xuCcHsVgpQKBGZqkUsOWUekaga8DlkXs3fL9v7mrRAlqqWmy6nl+lidsV6wizDYzWTfPtFAkvisDqdHzXd+eG/AoYDPkZq599obHKj8hmyF+sIzDHZ5g7i3cfyZHU9C4rsiRwMoiKrmlP8oJ9ajvHmGRwxdOtdkQxr+sfc6xVCHUT9n2WBe7uOIW6xl8BVcBydiF7LwZmMH4GVQVvSLpjy8bcKkGSnJlxalD5U3boFvQh+2iZT18mFHgxzzen6HnhrErftgbH2lXpqTH/ZGZmwZA18uMiCkh8ZyDdm8cgn+7Hq6H9AJNKTtX7Om4fdCgIrFWAX3DuqPpXGwxhxljcsNjiVJk6ouiHu5s3kOrocq3NWVPdX9rMSYr6jAwa+kaSCQQAUbTc3rwEISTriPDoFa3GAhQ79YyGPT4DTaFQZvCTpX3lNiGNLkRXBuUg="}
2026-05-18 09:47:59 [XNIO-1 task-14] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"GFB2fmehTxGfA-nBZmMRRg08411778893677","eventId":"92ad2e7f01ed4aa98d0dfa67965f2810","finishTime":1779068847000,"corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB/type/finish","EventType":"bpms_task_change","businessId":"202605160907000570685","activityName":"办理人","remark":"","actualActionerId":"03462113426124233873","agentActionerIds":[],"title":"张新怡提交的技术方案申请表","type":"finish","result":"audit","activityId":"25d1_3948","createTime":1779068798000,"processCode":"PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB","bizCategoryId":"","businessType":"","staffId":"03462113426124233873","taskId":101173037254}
2026-05-18 09:47:59 [XNIO-1 task-14] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 09:47:59 [XNIO-1 task-14] INFO c.r.c.d.w.SchemeApplicationBpmsEventHandler - 跳过方案申请表 BPMSeventType=bpms_task_change, type=finish, eventResult=audit, onInstance=true, onTask=false整单请订阅 bpms_instance_change仅任务且非 agree 时不会处理)
2026-05-18 09:47:59 [XNIO-1 task-14] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 09:47:59 [XNIO-1 task-14] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779068879311, msg_signature=b1dae080bc26798a10f9b2aa10c7e8985f67d890, encrypt=iycm70OlnodzaiVH2Y0w5koJNYkeEGnxRDKWJRwxBK+ONtbEdk14maVz303bYeDujAXrqsKB53IEwx9MZTnDdw==, nonce=jCoXV4B7hdTLUxMp}
2026-05-18 09:47:59 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"GFB2fmehTxGfA-nBZmMRRg08411778893677","eventId":"af5ab9d071294855b9c3871995e96385","finishTime":1779068798000,"corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB/type/finish","EventType":"bpms_task_change","businessId":"202605160907000570685","activityName":"项目负责人确认时间","remark":"","actualActionerId":"283111015435457273","agentActionerIds":[],"title":"张新怡提交的技术方案申请表","type":"finish","result":"audit","activityId":"76d0_7eb3","createTime":1778912734000,"processCode":"PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB","bizCategoryId":"","businessType":"","staffId":"283111015435457273","taskId":101190348445}
2026-05-18 09:47:59 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 09:47:59 [XNIO-1 task-2] INFO c.r.c.d.w.SchemeApplicationBpmsEventHandler - 跳过方案申请表 BPMSeventType=bpms_task_change, type=finish, eventResult=audit, onInstance=true, onTask=false整单请订阅 bpms_instance_change仅任务且非 agree 时不会处理)
2026-05-18 09:47:59 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 09:47:59 [XNIO-1 task-4] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"GFB2fmehTxGfA-nBZmMRRg08411778893677","eventId":"18850158dc274c70a2acac8d1f0f32bd","corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB/type/start","EventType":"bpms_task_change","businessId":"202605160907000570685","activityName":"研发技术人员确认提交方案","actualActionerId":"264325116326361164","agentActionerIds":[],"title":"张新怡提交的技术方案申请表","type":"start","activityId":"ffbb_66b4","createTime":1779068847000,"processCode":"PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB","bizCategoryId":"","businessType":"","staffId":"264325116326361164","taskId":101105511366}
2026-05-18 09:47:59 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779068879313, msg_signature=e38699704788ff586391f37b198ace8b0fbcab49, encrypt=jvMrhLWPtowbaNwc03Xa95lh0zHPOD8dKfL7QArkit89P9FZ7HFY5CtF6Vg9n+HT8zSMMHiI0MerfyX5q8xiKQ==, nonce=MOmG5RersFBI4Nl1}
2026-05-18 09:47:59 [XNIO-1 task-4] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 09:47:59 [XNIO-1 task-9] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"10dc47a5ac71099b0ded79da4b80d2fb372f6e36","msg_signature":"10dc47a5ac71099b0ded79da4b80d2fb372f6e36","timestamp":"1779068847945","nonce":"klEtB7a4","encrypt":"heGqm9h/y039L0YB166Ymz0fZEAWesnhBIRZI08NNuMis3+U6GVTTvGODF4RqPL7srLCBJ9t4aBxbaCZXkCQGvo6xHNlcn2lBpLw0debbqSzptmHKjsKK1oGTRvDyr/zwD9z96oc6wh5e5P5SiKjg2oVS5u78iLTFjIFbyC2keI4+yw6+ITSY3PqpibsXIh6SeWujp/MSK7mxhJLRQeEMxJ9mg0tFPmhNDRk80a0ntcuWZD4855Nk2DgKcOuumLSbJgRaybyT0u0jwrIXFzTWZQN38TRQn7/3ivtTj/ZZlvcUYHiPiGsjhpKSv2aYfM6Y/vyDPgnrg4svvPhSlAz67tuHsU+RGrdmMRHp1gBstabrAPtaewYLlJX2foLgg5l4Dbj+5GSnkG1gKWMnr58y5u1DZpM2VD2ybg/pKBLl4A4BM1RAKfxU7+vCE2/6ifW/3ukcQAWto/EuAk6CYqF/AzySEsCdrKgaXM59bxwD9EfrEMSlYuruq+ZWOjUTktdTsw65X6bE9izrX+sQ8IxcQqdhTiOFn00nBdoxSjNglxOgpn8qYzKRCdSfsfyH4NpwJaDn3O6qaj2mfXuyfEaPnX0Z3XxUhRHWT+PspjFPhCG5DlC/5XXhmaDDzVwK3Utsb/MMJCRP3mK4noI5gGs9NZKuje5z9K4Cn9pedB45YPH3MXTI1U/hzzJkbgKqF8/kNb+Pxs8eLrGeSUK3h+JsZr9bveY+ZLoHKuBdVDtEZIN36nKy6C7VRZcwrUNPh2o/5N4Cyt+bzN39qUdPFZOmH1IF2MllLrwCtOew79DLD4FjB2p0CKkMXOqcnJ4/Nf82g8z3vcNLd8D9cFDzd1puN+S481IvWPeG+wHh7mdncefhNfiIrm21a7EVduFzFlgLCR0cbFAJFR9AKod3ovPXHvH6bSiUPJ3EY+dvORnTNmMK9b5nZhmf/kenNdxmElHQZdEccHiL9RNcXPD8Ggov65nmhkXJ8J964fiRJcdEqOyw9mDEqK+WktcQmVDletZ"}
2026-05-18 09:47:59 [XNIO-1 task-4] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 09:47:59 [XNIO-1 task-4] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779068879314, msg_signature=970c2b2f538fd4ccccc16d7809f8e126dba03e31, encrypt=hpTIFRxYV+kshAEytLNvpNMdllXcTAhvL/p7vvnSl1flhAGu5MEL3t3tJT/a/kCm+LmYktqAUc8jn5hwkivJ0Q==, nonce=PhSFYBEVWHGXLsfi}
2026-05-18 09:47:59 [XNIO-1 task-9] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"GFB2fmehTxGfA-nBZmMRRg08411778893677","eventId":"6a76bbdef4e54e1d8a3426cb5df1a9c4","corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB/type/start","EventType":"bpms_task_change","businessId":"202605160907000570685","activityName":"研发技术人员确认提交方案","actualActionerId":"283111015435457273","agentActionerIds":[],"title":"张新怡提交的技术方案申请表","type":"start","activityId":"ffbb_66b4","createTime":1779068847000,"processCode":"PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB","bizCategoryId":"","businessType":"","staffId":"283111015435457273","taskId":101105511367}
2026-05-18 09:47:59 [XNIO-1 task-9] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 09:47:59 [XNIO-1 task-9] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 09:47:59 [XNIO-1 task-9] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779068879315, msg_signature=a6bc93d3ef3e7afa9efa13c27ac142a5bd62ac31, encrypt=J/KMVKSeZbfn02/UqnV8UROODdX69r0XNGkWggM0wivBKnMjJwpRYmmqlB+2RFvyTMaogqJv6GVU9v6EiQN25g==, nonce=SJhvVgO0lwyvRtI1}
2026-05-18 09:47:59 [XNIO-1 task-18] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"ddb4a433add562833cd89453b18f41150c14406e","msg_signature":"ddb4a433add562833cd89453b18f41150c14406e","timestamp":"1779068811329","nonce":"lWop2Q4j","encrypt":"pLu4iTB2j5FsQf23b8By6hnYTqvIDntYPcPXszB7Nu/hR0H5BZOECVMYY4SjYRii7NYl8j0zmMs4PEXhp42vkf4m5l3B70nAL3+nTkuiz6BGSzU0jWen+4a1I433uEyKDp5T48J1uU1liimBMmyXZLC7oSPNJ4dsxCPKLHGHslQ12soOz/oPnrkLMiaNvG6kePqntQ/dfekYnTQq2qCbOUIwI1WTs7NtXiKDg7C9ftFwO1uyVttTrLs1Spq/UHMejDShR1NyV4LY/KZiCBwRZUJMYiUr7V791SMRRmwozQ/U4Q85B1nRXRvclJ/6tY1r8oXJqDmbp3h7x6dfOI5D3NylAWcaJTOWSYklif+VS0SbngutMCxB0Uuiz3Ba1TNposszrEc/I6msCR4xOmbchzMpgfM9z7XeHKw6pLM0AFYYLNE7YHEv3NkICprrEati+CbPg4ZzJmh8SFYVP+AIvEijGQvlhC3JPD0kCx0pF+u2XQUAjZ2OV/eRqrgpkGAyYOmhnUkTXshDPGRmdm1ebFhy10794b1KLLJ/vsnkhouJeM2otlDobMemi4Ik3xgrzLP8O9+GSC5yDs14I4+WaDwU/OEWH3S84Cu8SphKFuSU8CaojAVFKZw1AeA5C/2VAf0tx6ajUQ4J76eFVEDrpSsiGzjQMAaR22j5XfJIlx9rwHoeXHpu/ftzBbo4tRzluwN32dXxSQswJlN4Mez27A5mYyKlp/cyUn+NezzLnDjpqP2e9PstYePh8uP+v1+6/kneCbMYLu0smqQbW4c3riWjxkaNplZqMfuPgQRmz2KkppW3mKhFXwBIWTWuaLKz1pgCFvKqaf33K4z5J87ZWIpmNioas4Oe1GefoFomMIBQlwM0UZrW2qLjcYXsZ+PhryjrzF98zlq6A5n7Ms3ZthHSgTTygV544nxCQ+xiLPCA9/2Tvu+kCzPjufKPDFYpkHY0flSHAlag4pGi7UVhHA=="}
2026-05-18 09:47:59 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"9b482b1878f281f6a6854ba721774bd9cec75801","msg_signature":"9b482b1878f281f6a6854ba721774bd9cec75801","timestamp":"1779068860606","nonce":"IrNXsXsE","encrypt":"Cy98bvaP5TeANpaTznRYxm/XlY84aMiFOEy/FgIUq5Xwr10fG8/MkoCP0gA2Tvgw1O4Z9lPFP1lMa5mZ+gBfwS5Qc6HzMCr//71GBIWxV2PyOq+asrZ4QNESSKKamergcp6ZSQc7JulejfYbYEGHHbV+xKawAkGyIy+R4OVJ9kpv1O8FVBs3+uzLXMOIdUT6hMXB718va3XIruL7kGhYkiKsXFMBCes0TTeOE2+wHi0iCEJS3xS2QVasvddZ7qGcWfURJbcKm4PTIXt1XwJ5QrYU3B+L7OAvnF5yICFwIgFE/cAOd2zQEfVpVb9iBDYA0TILUuNrnyWeywJEvoZLS4/su3VuLoydwwiYCBhVxSiwQ7giuE4gPC47vv8FBtJdSfuAaalSoTYRUeFxXrbAqCIA7GBKkCHiZrUrESsiaYlWRT3nVjYg5u+fmo6gsm4lb3eiF7IlTicLArl5Ifo5y0jSZ7tvu/yaB+s0JPvQOxvJYzcMhjzhziZ22RbdI7LNp+fwquBZbOLnTiSgzhaN2NR2hv2nzoNqniFjMHIYQNj7kkAh3PR0exhyv61tw5EWdpxOca42jMYSHL6hPeUCX5OgcrNt9JIYmXaxNixIorowpB8MosL/Tji0zjTusq5gfIvzypeHtIkMt7dxPEy8vYu5t5KfhMdh/B667ith3pFZbwOdXxvGWDLA0qDm+3BMkE3N9tkzFRNx2c//oVJ2IdE3VlKZULIF1ZOXfJiFTMFOtS6XZvg0PfhV4p4lIkcFXQ2siLMsmZnqReGq2kxr1af5bJnZnATXICK9DTwnUmW+5emt25uIap7Ds0/k8DvDvAbgeyLQkrioVQxFl+9+Nvkl3qnMlZFFPpsuR9nA3mtdc/VCpPv2sngUo5YeEIKxntz+mp0GwLj64TuHQF5ZCr8h9D8+qDP6v8Xa37g71pKoN8V+hXFWUoKk3VfzEwzSgCz0tYpcQxnX5tUpbONqKl2eWETDhs8DTJtxoK4vpt2YZizOpHeCayGXMv/PeV47"}
2026-05-18 09:47:59 [XNIO-1 task-9] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"b9f10c8f6b648550f92138c1a476bd1638f1cf38","msg_signature":"b9f10c8f6b648550f92138c1a476bd1638f1cf38","timestamp":"1779068860647","nonce":"uBr7MvMS","encrypt":"GYts0SMhvdcGbxmhZu4XhRx0XG3Ix1u7TTLPMkD/L1ZboArXgrBNN7scqFW+iwBtmctdF2VmWuyHAe2HOR8ZQU5yj8T9wiay6SZgxd+TByl0axOW/d2ORlBc3JPlbKlB9eoMICkXAwB3DVJwRPWjDiu5fvWlhFgMNvhK/ztKSZ0mSxmNbppu1wnF0CMjWQ66+/gy0cgG6dsEFhxsJVyI0SnG/p+yimj7+qLTOLFBBNOsjnZCmpupsb4/dpicaha2vskELpmPbeI+DN9ELn98KtbJgAIFcRJ9vo3JpN1DBvoDIjiQJUwiR2RrJrc68B0Ez6f+UCjtxG3WzYsGFOchdq1YzjxXgvhB8G8+7u/OeN5uFW9P1sf3KcTKFlxPXJXax+HzPHpsPyQgpuDfjcZ2c6FSJ9OC2DPeb63ccHB4RpHUhQL3UeBbLll0hWK18xQMqUdZSiVZlhEzEXeiGMb7+xq0MNU49vsLoKIYrpP3ZmR+LVrIaWKUuj45n2JfRxEXePp/EupKqp0Ony1/x8gtdpUXonw687T/nKxB3klryzVocl2NRyDa8u5a7ilfEePZP0bc7QMNaTDtXLYEPrS+pAJMKrOBW+qGe1H3cCdGSIRY5CX3Rg5R6glNqJ8PXvDqR9c5+7EmI9vUNQRebHeTrN0JnrkCUkPJtx0Ftq6dD1rJlyFz48LiMnkyftRuVhFE3CIv3dOMbOCFUXPourzEJJe1h45amvWxuDT26A/T5jJbn5t8fxTBrPn69yaT5NECiWTHkf7YKuZUsPjNlI1QS4njPyCa3ZupDh4L/umELUdBbWBUoRc1Gi+4aSIY7TxXH9K1KFNlUUQ6zevzEteIRy1syZdcZiD9DpbYbztDAbUBMrmW3+0qUU8THwEIX0r3Bentv6o1jftwbCGtxC0D4ZN7LaV1xs0F7DiqKgvGRfLFSV4Bs4lYkxBdPARyfzy+P/+/xTnRoz4oYczFMA5E60tKgINzrMsMSzQsPvy5ksTTleqqnVg8yalHX4krWwUJ"}
2026-05-18 09:47:59 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"GFB2fmehTxGfA-nBZmMRRg08411778893677","eventId":"18850158dc274c70a2acac8d1f0f32bd","corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB/type/start","EventType":"bpms_task_change","businessId":"202605160907000570685","activityName":"研发技术人员确认提交方案","actualActionerId":"264325116326361164","agentActionerIds":[],"title":"张新怡提交的技术方案申请表","type":"start","activityId":"ffbb_66b4","createTime":1779068847000,"processCode":"PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB","bizCategoryId":"","businessType":"","staffId":"264325116326361164","taskId":101105511366}
2026-05-18 09:47:59 [XNIO-1 task-9] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"GFB2fmehTxGfA-nBZmMRRg08411778893677","eventId":"6a76bbdef4e54e1d8a3426cb5df1a9c4","corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB/type/start","EventType":"bpms_task_change","businessId":"202605160907000570685","activityName":"研发技术人员确认提交方案","actualActionerId":"283111015435457273","agentActionerIds":[],"title":"张新怡提交的技术方案申请表","type":"start","activityId":"ffbb_66b4","createTime":1779068847000,"processCode":"PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB","bizCategoryId":"","businessType":"","staffId":"283111015435457273","taskId":101105511367}
2026-05-18 09:47:59 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 09:47:59 [XNIO-1 task-9] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 09:47:59 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 09:47:59 [XNIO-1 task-9] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 09:47:59 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779068879333, msg_signature=835da67538b03e61a8b66018038703e516ccf2d9, encrypt=Q1iUA5P1l7pO1E0YYEyCu4cWrNLwOeOZIT/3Tuenw6bIJrNDjzjIrDsDH9Sed/wk4xhFzqcb1SsDroxkW3UZJA==, nonce=3PPMxKvpbxQh2UGM}
2026-05-18 09:47:59 [XNIO-1 task-9] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779068879333, msg_signature=63602b1082f47d08bb74556c1a87b265c179cdf5, encrypt=NLVtMm6LCrHAlkIN/ox4FAGBxQcaFSSYYShYqR+drx6eERO7ZoLQfM8JxLOWIFGiZxuNrrMiHyspMrFRSLjC5w==, nonce=DndqMNZK61NXyVYV}
2026-05-18 09:47:59 [XNIO-1 task-18] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"GFB2fmehTxGfA-nBZmMRRg08411778893677","eventId":"8babb5e69cad4391a5fb54bb421c57d1","corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB/type/start","EventType":"bpms_task_change","businessId":"202605160907000570685","activityName":"办理人","actualActionerId":"03462113426124233873","agentActionerIds":[],"title":"张新怡提交的技术方案申请表","type":"start","activityId":"25d1_3948","createTime":1779068798000,"processCode":"PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB","bizCategoryId":"","businessType":"","staffId":"03462113426124233873","taskId":101173037254}
2026-05-18 09:47:59 [XNIO-1 task-18] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 09:47:59 [XNIO-1 task-18] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 09:47:59 [XNIO-1 task-18] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779068879335, msg_signature=e44ab598f6d1ff0c2e673fad5f3aee89f330ab47, encrypt=uACE6juJh5x70zGRcXdmjj1qnIxZwxqV6kJq+6RXWObGX27W+ZM0OQDr0iqGLP0qZFQ1sx9LKGjc6EWn9OlhOQ==, nonce=mTBOout6RL3pqjNk}
2026-05-18 09:47:59 [XNIO-1 task-13] INFO c.r.c.d.w.SchemeApplicationBpmsEventHandler - 跳过方案申请表 BPMSeventType=bpms_task_change, type=finish, eventResult=audit, onInstance=true, onTask=false整单请订阅 bpms_instance_change仅任务且非 agree 时不会处理)
2026-05-18 09:47:59 [XNIO-1 task-11] INFO c.r.c.d.w.SchemeApplicationBpmsEventHandler - 跳过方案申请表 BPMSeventType=bpms_task_change, type=finish, eventResult=audit, onInstance=true, onTask=false整单请订阅 bpms_instance_change仅任务且非 agree 时不会处理)
2026-05-18 09:47:59 [XNIO-1 task-13] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 09:47:59 [XNIO-1 task-11] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 09:47:59 [XNIO-1 task-11] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779068879339, msg_signature=9164bc5c6aac92dcc2828186c34c1d04b8213e2a, encrypt=xc9PwRrFpW4GqLOP3Ymn99LytYpoIVtsjRfmZ7kr1Uc5e4qpXC2F7NXpTtVWq+UHTa4KxJWlkx3iCOClPZGCXg==, nonce=R5wvzT1N0iRLzxzt}
2026-05-18 09:47:59 [XNIO-1 task-9] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"a7a5163074a8ac55fe276234ebbb2f59eeb3fddc","msg_signature":"a7a5163074a8ac55fe276234ebbb2f59eeb3fddc","timestamp":"1779068860545","nonce":"9PQn9Dta","encrypt":"OXymIA1KT391tSfv43vT1wcQ06CiFQQgcGzO9QuVpTDSHivJXZot5SgMc0Trb8NaWIqzBRXydXxNK+bJ5Ey7Higzjc1eBE8ZzQe49CGQfc0hlQRsGQeMcOfRw39sG0EilqIVUAiSfj7XaPSAjznKwGeFhD3BGZl3jBtbcotvYjDvS4K0x8KXZ+fr/+QFVvKenf9uEjwHEltRkCwEjOXTQIDWN7otOCmwpWmcNeBoRU82p4qr4Hb+MMuFWl3eFLBTemyEZOzBSC1OvZki7bdxe8I0H0mOGMZWn00tU6lTH/qizdG7dSGQk0vCeHB/qglQ1Gel4FPYXW2LY/aqj56RHyYR+D+COH9LXu/fBcCe9snSB2zpKzUMm/EZayrXFg/1Ls7ZyexgHcda1HGKe2Pw8WsdKS6owQLaHnsBHJeLpqq/S4XK3MG8vUx7iSsIpmmY84oqt3DgCha2EbMKGeqxKW/ZorYZnxp+lerJTQZnKW7p2lkYBlVm/9acSgPZ+Dqno59Ez9AAnnmiSTY8n3mXxvWYoJuypIMxuRmFa7zas9ypsIGtSmKynIFu1OlYWJZ4FXcX3Sc4ojHF0jvNcsObY3JKxYkA9szmpnZ+jj5liertNcXzVwuVfE0rtK7DcEVQIdNcVKJ0qROUSRX78b6qhpeOd1A3l+Kbwfa5+whdaoVnjj9YMKOv5IfZRsEot/xswho2dg3YtxdccHLX2KnRSdT4Rlwog5FpPuDWSIKX0gXkoorI0jFCLt9hwEfrDhCTQX32hZkNE0Y9yegqxoZefNIPAPxLi96J3ijApz5C5CoQ9oTe0yA8Zp2o9UH4FueFNXU66uiFW+4ih4xrGLM0GcU8A5TbKD2qYnibQUui3+WbOmDxozVAUVDjM5D7hv0CtHTDPLZ5eLYB29EcBaImcuXGp/U0EqAQMnrDmWhQMpAuZgUebOpsTf8IQYTtSvDs0+3QE+kNnQZvlCAY3SdwKydocNNeo+Ryo8Od4vv+1MzbhkpcfO7GdJyn8/qOngkvzr7ljNJiMfG8reJro8xZXAIaXnEILBIJbEvrvR8FRNc="}
2026-05-18 09:47:59 [XNIO-1 task-18] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"92846be5f2d7770afcd2f162c7a3dcd69cdfb4d8","msg_signature":"92846be5f2d7770afcd2f162c7a3dcd69cdfb4d8","timestamp":"1779068843969","nonce":"8GV7r6CF","encrypt":"nDx3ouv9uH/U44g/8mCyWCLBH8wPcTG8gLOfWRQntUaTZrhyNDF2dALbxtF5YCpseQjvRljDXHXEHmrtZKEmxoBE2hStbCCDN7YvcxQ+jxezoETTU3uvdth45Bwv7poOklj/5A1CRVsLA8y2CU06hEDjRDVDnSIfZbiOurTF8y9tyycXPDjZ9kmrebpU5UucpWyezsY+iARTGLCxXCnWjRn4xj68fQPfuCy+0Yy/jKdHB+WKAKYjs0IdJsi5zvZTFBKAkGfTUdfbriw8w+dT3bBaBOAHFtDSsup72SgupCUN4IprU30LzeCRWSiU2kjedp1ksaEQc99p86uEBxIRRuUTmn66zuTwIKeQ9zhr3UBb+DS6F3Dj2DCaWPOngAtf9ZJD4YdvY+EKLEWLrasxD26taGO2KXJ+uaYlLgT6XNnKuhE3a+dOUcpU3t8PCUPOC+Wl6CjFfTYw3mSJwfW7cWxzi5x4cyRxW5xNFuNpNh2Qqvz2xRfJEzyAv0VFEW/sLLKUtSmISMn/8M8cENM8LPNNA5qLej6RhvRNnEz6SAa/feqDONTD5MBV4YDuK2rKMSWsYNCDSMRTrfhWUQF9yolxXzFlky8HEZf5VxXVWiDLoHf92CPNAGDw63AM2ACDvmJs1DQfgRZm/HpeFq9ZXMb20/7ckL8IxZ8o0reRTD+5trleaXiPbQEZcO31+rPT1PkkBz5QoPssamsuskBe8yx6CSH+OzLKEUrvPneZdm3AJv/achLVzhRzj24p9Ch0L2HMjCP9QgUfFAe9g/BbPYWkpLMbAQxcLc5MT01tbsAVs2WpGt4JYszek29X+FhBaMkTzQBnjAC228LKa1OMrbAsoel0kYE0vywfNZB4vhc8kJkmQPT0FrjSme7GNE8SJ6WtKkDMfAJgHwalgCsdhS+XCXw4wnDKEIUs0M1SXWN69RtFhfd/pyf0QlXCus69L9kcZZVMkftFWVsqOwJgVg=="}
2026-05-18 09:47:59 [XNIO-1 task-9] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"GFB2fmehTxGfA-nBZmMRRg08411778893677","eventId":"92ad2e7f01ed4aa98d0dfa67965f2810","finishTime":1779068847000,"corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB/type/finish","EventType":"bpms_task_change","businessId":"202605160907000570685","activityName":"办理人","remark":"","actualActionerId":"03462113426124233873","agentActionerIds":[],"title":"张新怡提交的技术方案申请表","type":"finish","result":"audit","activityId":"25d1_3948","createTime":1779068798000,"processCode":"PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB","bizCategoryId":"","businessType":"","staffId":"03462113426124233873","taskId":101173037254}
2026-05-18 09:47:59 [XNIO-1 task-9] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 09:47:59 [XNIO-1 task-13] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779068879342, msg_signature=af0ff607c3693c6b10d661e77d781c24541157dc, encrypt=rbskvrjI6WkonSoDsQBmcd0noXABSxrrsMvCyctqBjNDmSU/GpmCl2jmHw8+aiQ6oJDQSgU4P1+b2lkxCFUOTQ==, nonce=vkGkQicHaIUde6Xm}
2026-05-18 09:47:59 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"4ef219a00b9917375f59c1a2cce5c2e1c4ba8ee1","msg_signature":"4ef219a00b9917375f59c1a2cce5c2e1c4ba8ee1","timestamp":"1779068870052","nonce":"lQQhFVHY","encrypt":"faXOCu/o6E3KZiIH6cYtxH5miuVXBB8Rm/TH12CTB2ag78o/vM7W4eniFc4feorE8J5WdYtazqIzSvfMXHYF6uEsDkw4Eb6KrRSi5a/PZPAQmUlACvciWKNnqxO8DIBQFPnYyk1ayQQjzQldrXlFWMIMNbtRUPhfxmq8QW7LNqP3o+FIky2fpIlLzIf+xXq+e+qGQS96hTKbmnSfImDXatSvE1AIx7b8jYryEpjvuWgq1PN8priWMP9+m5I1Jhvp1zjKov2eP0YpaI7DSMhxfnulYc66upqvvNB1KhGpd0MnME91f4N6WlJKfLjQG2vGWgZh45OYZ79uJwfPG/Ti0GOngTgTBz0swFCzBoQdLhy/BdTbKgWuOgA5mpTtLlBaGfqgfyAK0FJsT7rexGY+Z54Tfk/OqpNszY1NchMwfb/mVx+WkiU3he78BAPn9hxWL68i02Q/xUOQl4VLFKJQW7kw3Sjbuc/44P/4C1qHxNIHev7kfxqwSM2U0fc5BFC9sjdQLZA2TJ8V9cJT/3ZPIlEGYMLRB4+bidR4zvsW21+uvpbH0/F8pIEJNPwKgxVE3C04TtHOeu93n70I3dJ7RDGocBwkWAp4ICUCau/gZQpAvMOTC82a8pOGt2TcTRz2GkR1udB4UyRjCBwEYA7wd46GWfeB/axDtrLje85oYKVsnsjVG/DDDywMPWqAR8CgTtB/xbQyzBsMEMo6FR89dC1MoXVtkkUNS1Zh3jjmIwUzhZoEP9CKrm+VAwLwq4A2EdggAy1NyUaceFUZN9tGOJ/LebJfPyZeYM1NF4Khsu1ebcHYiXUrrRoSaibb81QOXlqJ4SUwEAb7nxZoRYIPfC915WQLYLNIQ5EijPXYYfFswVBN4sk0ruZzxSOx5LRwMENfjD6WVKdgZ+qy/tNAD5ZrHPE9D8hbWSeSRJeQxISStS4ZZ0eJ8LWflRWrXoRHmBuot0O5ZPZ6OVHT0gHUm2vYpqXVuj7z06Bili1+CZ7gNrjI1DktE/UmLKPEj1XJgow/Waw7LNPnYmfXuIUhnhhDvl8WCaFYlbMqh8HVL6I="}
2026-05-18 09:47:59 [XNIO-1 task-9] INFO c.r.c.d.w.SchemeApplicationBpmsEventHandler - 跳过方案申请表 BPMSeventType=bpms_task_change, type=finish, eventResult=audit, onInstance=true, onTask=false整单请订阅 bpms_instance_change仅任务且非 agree 时不会处理)
2026-05-18 09:47:59 [XNIO-1 task-9] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 09:47:59 [XNIO-1 task-18] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"GFB2fmehTxGfA-nBZmMRRg08411778893677","eventId":"8babb5e69cad4391a5fb54bb421c57d1","corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB/type/start","EventType":"bpms_task_change","businessId":"202605160907000570685","activityName":"办理人","actualActionerId":"03462113426124233873","agentActionerIds":[],"title":"张新怡提交的技术方案申请表","type":"start","activityId":"25d1_3948","createTime":1779068798000,"processCode":"PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB","bizCategoryId":"","businessType":"","staffId":"03462113426124233873","taskId":101173037254}
2026-05-18 09:47:59 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"-rq9EkhYSqy_p_bPRn446g08411778293593","eventId":"1a0434cd6583443bb6f839346a86182c","finishTime":1779068869000,"corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB/type/finish","EventType":"bpms_task_change","businessId":"202605091026000330395","activityName":"销售确认收到方案","remark":"","actualActionerId":"03462113426124233873","agentActionerIds":[],"title":"安宏生提交的技术方案申请表","type":"finish","result":"audit","activityId":"f135_c1ff","createTime":1778923843000,"processCode":"PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB","bizCategoryId":"","businessType":"","staffId":"03462113426124233873","taskId":101193056701}
2026-05-18 09:47:59 [XNIO-1 task-9] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779068879798, msg_signature=033d328f7eacf6b1335567c5207571b3e7e45f86, encrypt=8kYJ5V3RMG/PKCLOLh+8WAfLR47a4+uUPldvgzDgXjikE8IL58/z+IlTIDVokh913TgeEMs1poNT1egpMbx3uQ==, nonce=jvDthhDmIUSWXBbr}
2026-05-18 09:47:59 [XNIO-1 task-18] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 09:47:59 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 09:47:59 [XNIO-1 task-18] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 09:47:59 [XNIO-1 task-2] INFO c.r.c.d.w.SchemeApplicationBpmsEventHandler - 跳过方案申请表 BPMSeventType=bpms_task_change, type=finish, eventResult=audit, onInstance=true, onTask=false整单请订阅 bpms_instance_change仅任务且非 agree 时不会处理)
2026-05-18 09:47:59 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 09:47:59 [XNIO-1 task-2] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779068879968, msg_signature=0e0694972cef359a984dd76522dd68c5f38630bb, encrypt=tWc66WGXl/9xLnXvbKeGoRBwBDqXvS38vKGvIKow1TMbgKLJX7EOuTTT/TaT2f+Z4iRxH02DBukb677lfgqhSQ==, nonce=IBRmkZRIAKtNtZPb}
2026-05-18 09:47:59 [XNIO-1 task-18] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779068879969, msg_signature=a4f4e1a61b8faecaa519cbe4a6d288a5568e72aa, encrypt=dqJomYM7bkW+M/Ex5qoiLMmbj4tMEYhhmClo92pGWuD8/DeccDjyUTJf5ljB8Yjza42umvW9qMLlk7Ggcp8DYg==, nonce=pcSlxryAgsCU4s2E}
2026-05-18 09:48:03 [XNIO-1 task-9] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"cc319228350db2dd4083582a8216d7665244c0ca","msg_signature":"cc319228350db2dd4083582a8216d7665244c0ca","timestamp":"1779068882676","nonce":"E2VIJ1aY","encrypt":"dTzQF5wkKWyqTJoMgiqhQVffpiK2CXiVSFn9VZaf1w+aW1Cod6C2v+Ddl8TrvvEdAkhXt6wHmjKUHAU9tnloEd52ig4Zm2hcV389t0ZRm5U/CBSaiTUh5IovBR4z/mxSQeqMW58McZ4+3WQGw0WWBieAOImvbF2yASBuTjptHiWpM0B3OM+B/hG8nZmMHTbmOTG0fNeoUuuBLpwIoRxr+AFdxEVRogCzx+jinlcBZM9vU6iH5JpiCq4yTXD3re0FbytsKj5x0nsse4hRy1U8OTEdc6WxV5ijEP+9qXSYo4KjXby0KWIhLQvRG7OQ8kucucSRGj0eX4+OJTNc+WMUpPpvi8ChO7moXIgbTvFGfFvd7DEnHTYbhLLTmgaVi75cs3wAxnswGZ8xQNs9RRVOggoB/QoJZi3SDbux8qvY73G/S4wMAaVRHCqWN3kACZk6EFpoVHVcH0mxks3dLTpTCm18MFaWFI8f1cnK2rY9M+6qXoc3W1eyDjKa0DhgqBrXqnRdnQLY7MoiTS87tX5FKpULkJJicZfYfEUuQ/kY8wU4/JAYnOI5cWEHVb0h2JslkzclQZRln1s5chrJYYJY3LsSwoXw0oWjKTL0u/Id04QVNbB9+eU2m0KoLJJyZZZuZQN+hG2y5MK57sYl1WvPggbXM54aVv93rY515z7Vzq/QMbjiG5VyO1urN4/r9iRtXYjqnX2iEeqCOPYEX1SkN7L+zLLJ62SZo5odaJ6O2lUf35X3ZQHUSRB+EUSlVt32gv+LRAGi3d9imbhcOU0f+/PKPS/NmY3YvNGK9BhN0BBsRVh74Yop0DPazOJ1ye2bP+vmRzs6uNIVND09V+aCzdauCjAiqJTVByJ1JNcqCdcEtP2A4AA9KfWUSkWKtU9Gpr9e/Pek9PD167/pBwnuWCRpirrPtRwCivDPNdOwzSdcNbAjprU3NBnBqTT/NGIcNMliE6CFz1vfzQuFz1cvIGoi60+Z56bg20dtARiC5lBEw0yE7mkA8/jNNybk/YYV1wN2mNfIBdCm+aCSmY9SuABeUaXeElJziZzlkiZcJmk="}
2026-05-18 09:48:03 [XNIO-1 task-9] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"-rq9EkhYSqy_p_bPRn446g08411778293593","eventId":"1a0434cd6583443bb6f839346a86182c","finishTime":1779068869000,"corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB/type/finish","EventType":"bpms_task_change","businessId":"202605091026000330395","activityName":"销售确认收到方案","remark":"","actualActionerId":"03462113426124233873","agentActionerIds":[],"title":"安宏生提交的技术方案申请表","type":"finish","result":"audit","activityId":"f135_c1ff","createTime":1778923843000,"processCode":"PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB","bizCategoryId":"","businessType":"","staffId":"03462113426124233873","taskId":101193056701}
2026-05-18 09:48:03 [XNIO-1 task-9] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 09:48:03 [XNIO-1 task-9] INFO c.r.c.d.w.SchemeApplicationBpmsEventHandler - 跳过方案申请表 BPMSeventType=bpms_task_change, type=finish, eventResult=audit, onInstance=true, onTask=false整单请订阅 bpms_instance_change仅任务且非 agree 时不会处理)
2026-05-18 09:48:03 [XNIO-1 task-9] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 09:48:03 [XNIO-1 task-9] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779068883166, msg_signature=7bbbd846cb0055bf823a524f7dca16fb61b20ff5, encrypt=ATnndycsMpVV+6ZkyTNIwaaTKBtnv+VlZxqh/j6S+xBgalgHxxR2BvAVn1SfeP80TNLSBH8RXh2tcFd8U++PwA==, nonce=EoIHJ5LftMMXGdX2}
2026-05-18 09:48:13 [XNIO-1 task-9] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"9da92f69b07f8e9402292dafbf88a815fd16bd89","msg_signature":"9da92f69b07f8e9402292dafbf88a815fd16bd89","timestamp":"1779068893212","nonce":"oSW8CaTk","encrypt":"IEUoYEbG3T2YZayWdkniPkrcvOGSM8TiNRmJQ4XcNneIu21n6eIqBsiEygusO3UQDSfP2F8mPukNgOqNizxyunaFexFvW6d/G1bW9mAx0JadFDYXw3gL+MYaAqteLv7t2fjmmwgogDncDDm4SS23zND/5e2dtjKwl8vOzcrKpJGgoeKpN46oCMRF/SGdMPoem0iuAdnPJ8zSB6kzp1WLmT5xPCTO2z/fiNfvh3GZxMamh/s1TwJMmRSPU87/bmls/K4J6ShFcSuyc+5c6+MgZemm7kxfgklm3VPlpKX56aXc8kvSz3Cu2nUuI9p1rPa39SNka/dlygBVKeNxKC6BQrKiL/8mHIC3oSTQIptlwuIooCMzMtRKjsSBo5b3KBrBv5JYQBfdJzFFo5Icr7ef7OQbzgiWVadmO9NUUzxY3shMUdEeyOl2dXo4CfhsC4xRMd3AOYSxQM89zzBL8KNAjFNWmSNg02UDiDlbOT+dpQ3zIbu1CUpgc7NMwDsfhRrNJZMjGbe0MwV3XSX8dQvtcxXQT0PjuP5HcRhUFHKh5r5SWNPIVg5UN+Eh9lhjvtJ4ua7az4VrV/Nu3L2dDlxQe2g2tQ9avJdyhj8EwMfxw8aFcOCvS84cxMuH7swHW99JiKLOvbSbFjnWevrCAEE4WGn0k2vQ0jMvkKvmsByxXFQsW7q+JQlSFFs2vPt7VjjWovYP1+cOphkJYACBYHuhIWuvsdYtg7c6Yty8rtj93w7LBEkRT0bhwp3vxBFenrHWnpWwb1LF5PmoMJ3TClnUDbmU16vduS96663945L71mIteRTe7XuHoi0Nv4abq7ryQLuqUUImjWzAhwW8lxoeSUHSHWfyIgB6aPSU51pDL83FIxXnLvtGdTMpheYng8399RRJ6m/QK1o/3HDTyXDe/P0vH2HvfjWv7VK6eLMGOoD/KvG+ryuP3wVFiQBtiWC7RSH76Xao9ssZXIZd2CMQkOnsFUAjjXlLRSqxrMYcCI/a57WkXzHTqpDYE30UBaCT"}
2026-05-18 09:48:13 [XNIO-1 task-9] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"GFB2fmehTxGfA-nBZmMRRg08411778893677","eventId":"18850158dc274c70a2acac8d1f0f32bd","corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB/type/start","EventType":"bpms_task_change","businessId":"202605160907000570685","activityName":"研发技术人员确认提交方案","actualActionerId":"264325116326361164","agentActionerIds":[],"title":"张新怡提交的技术方案申请表","type":"start","activityId":"ffbb_66b4","createTime":1779068847000,"processCode":"PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB","bizCategoryId":"","businessType":"","staffId":"264325116326361164","taskId":101105511366}
2026-05-18 09:48:13 [XNIO-1 task-9] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 09:48:13 [XNIO-1 task-9] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 09:48:13 [XNIO-1 task-9] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779068893525, msg_signature=41b8e9b6ef8a8cd02a504e3e4bfdeb4a827f970d, encrypt=xyvpq+TrrydqN2TbRCLMGjBMukWTnHCuCDb7SBC0TY8FHOgdq7bLjQ8tUeUtZv8pKF3fLWn0sx/HmvGEtxmJMA==, nonce=XzvBzW958Zskpipy}
2026-05-18 09:48:13 [XNIO-1 task-9] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"2e40ff4cde304e25fac55cd50c19b36fd7b0fd7b","msg_signature":"2e40ff4cde304e25fac55cd50c19b36fd7b0fd7b","timestamp":"1779068893210","nonce":"LNGRmiV1","encrypt":"DGeHEHeIbXnfnQgR1PGjTeedi3I+9DK2EhvdRDx8KqLaDYpNcM48TpCXYp3tsoOld54Wi0ss8ipJl63ZEbS72k5jKTE1K6EK35zPYVotKikPWStOIsxRMZf2y11E8CepzsBNn78bJ6E55HTYc6Z3l2R6ptt8m3/ghUGlWrhBvqc94Y1v72xWduGJWWbLNZY1EnwtwGFRHMXWzgQBCt89h4Q/KdvwJNlCEcnV1DNjDt/Q29BhLilJffo1fxcywg70dLEEppBVQjCAZIvnLvpBNXs4BWud8a7W1A7TAiA/VS1CMXAAeXfKF1gwMMz5OeDxGSYl8RQ3g03+GnLb3mOm7eTusvYQRrZjqSbJcnd7zrgqQqYOQ2xU/bPRuMRlH+AViT+lWai2+vTS5AxY7sVrEjLfmJp9U+gIAwiH7COxUIG1HWjHMb3sHT6j3vbWBcjLOyVDPc0ojRCViv09uEWuaiY+Hr/4ZLO0u5WF4HeOwKOwzq9cJnHL2biFflf3HIO9hzmmgodbDvhGMre9AJ8J5n1cnH+Y8/EfQy2Mvmfc/DxTSiR3SW/AzkMESEL8ahLK/LMSIFdfpAARAsGADyqDNjjepnIzayxvTYXeWgcJpobNM1YRnK8mB0zVLCmImvN5+1Q2hDOtqMC/DUwKtOXgNxqHP0XbzPE8bqz93hRhoQzDc7l/Xx5oaqGca31hxm5msxyhve7I8CMDfFLdOnqMkiMdm5a9yWM02doXGP8aBphFf/A/z/aYvkznV8wDCEJQlZrLVQDed5BqFa92kd8zB6GoVFAI75cn/p0W90y3hAbt3uqE5KMtP13GwkDroI1hbZjkxwF8a7HxJkQCgW6WNeO+N+J9brpnWbjxTRtWbSzlUytn857EElmozefeg0m824ijiEMkrr/USMUSyVuMV0N9cD55JPbsaufS/3MDuRQF8YifijIqq1FRBQ+BrDPZwn9hLWdsHjych4bHvvLWnE998RADKm1jxP1TFlXtxVtQiFvUBAZdxKRM3F1Du3j7vxoIrCVt8RXPBC0LsHYOyCiz7VlOUScXVL38J2pUPEc="}
2026-05-18 09:48:13 [XNIO-1 task-9] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"GFB2fmehTxGfA-nBZmMRRg08411778893677","eventId":"92ad2e7f01ed4aa98d0dfa67965f2810","finishTime":1779068847000,"corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB/type/finish","EventType":"bpms_task_change","businessId":"202605160907000570685","activityName":"办理人","remark":"","actualActionerId":"03462113426124233873","agentActionerIds":[],"title":"张新怡提交的技术方案申请表","type":"finish","result":"audit","activityId":"25d1_3948","createTime":1779068798000,"processCode":"PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB","bizCategoryId":"","businessType":"","staffId":"03462113426124233873","taskId":101173037254}
2026-05-18 09:48:13 [XNIO-1 task-9] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 09:48:13 [XNIO-1 task-9] INFO c.r.c.d.w.SchemeApplicationBpmsEventHandler - 跳过方案申请表 BPMSeventType=bpms_task_change, type=finish, eventResult=audit, onInstance=true, onTask=false整单请订阅 bpms_instance_change仅任务且非 agree 时不会处理)
2026-05-18 09:48:13 [XNIO-1 task-9] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 09:48:13 [XNIO-1 task-9] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779068893547, msg_signature=877c3097e922fa841dce4f2df3872971a195344a, encrypt=i2BezQExsqZUQCAKv17NM66gRJuzOnv4UmOftRyYNoo4KfEOsp0/MeKgwmU/en0phI4u31rTCIjh6Fr8f8PHFw==, nonce=gLL3Dq6EG3bnHnRv}
2026-05-18 09:48:13 [XNIO-1 task-9] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"ee267417216ce17f014d041a134f41ab81b616b6","msg_signature":"ee267417216ce17f014d041a134f41ab81b616b6","timestamp":"1779068893286","nonce":"wn5KMFZH","encrypt":"blnDbJpd9W2X8Cs1GLDB7tlmKbg178LiWp3fWEDoXWrkJy8eq9VGMOgrU8NVA9G8yES/nFibtSldzFyg6lhlIQ5dUgKXsR8P+cqLAYIqnHj7THKFBuNY3zc/Ln//awWfCFhnmHmeSny9fdQRQl79CKqgp/9x3CnqHAyzwTOoDG4HKrdonnEADHnH6SeNWYuz0mJr6pCwKNQVYQ6MQsoO8csfanPi3N1ACddaV72+tUI2dBWkyd2VhD666M+vNtN09ChU4EDgMczpuqxNLzBitJk9XrADH/Yj9PuhTj5tkDWGTbYuvrnw5oi/qJjG2mQdFV8UR3PyB+lavmXDaqAvZRgakzr6aXT7nn43KxIn8g3ee9ZCw/kzXw/w65ToobCspheayRU2lSebeM4Wh61sAkQ7qfTxQjp7NltCrTIAY2c52l5oSZwrEq4Ctt5Qa0xCtx1AHWIDNdaO0QER/vul7K71jKDEMO3Uy4EFPPNOnRD+QpaibY9stdTyS6XtX5AfJ0W2Xi0Db4kl7nRQwluUGjKE/aI/xSiN9BXDKmvJJFsGAihX1tHFVwrf0dtIYFPgB1k02GnVE2fzgkA1E9kzomnDiFjezgMrHNXo5lRGoveYo39OODSiY+1XQg4PwMwl9ZnJkUI8niyz8FJa/RilM/4YENvo8ycqP2N1qFX0vauq5cAwmws/U9TPHP+sECoFL49mvzw7Uh/O15x0cpnnthmOjoI840MnkCC3iw7Z8hee8BwNzI9Gl6/oVVspo6hBW6f4MwCFqw6LoUO3SynIxGTwTQsHpm8iQw/BDBQANeFubghj/Gejx4pQI4rxk+v0EMD40WKH7I8VoIwljzndxTMNSQPcyOumbZfk2m2QM/aC6DSgzjKnNgp4dibs0Y0s46/czMDt2ZgezKZEJzAb9CRP6pQX/olSKvdx1b/0FgHN1iMcx1tt99Im7hz1qJes5WljsuzSEl96S8XybzNkCmxh+fMSm1J57rH0HuWHz3BuCgiOkJ2zlbG/2lfvfryZ"}
2026-05-18 09:48:13 [XNIO-1 task-9] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"GFB2fmehTxGfA-nBZmMRRg08411778893677","eventId":"6a76bbdef4e54e1d8a3426cb5df1a9c4","corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB/type/start","EventType":"bpms_task_change","businessId":"202605160907000570685","activityName":"研发技术人员确认提交方案","actualActionerId":"283111015435457273","agentActionerIds":[],"title":"张新怡提交的技术方案申请表","type":"start","activityId":"ffbb_66b4","createTime":1779068847000,"processCode":"PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB","bizCategoryId":"","businessType":"","staffId":"283111015435457273","taskId":101105511367}
2026-05-18 09:48:13 [XNIO-1 task-9] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 09:48:13 [XNIO-1 task-9] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 09:48:13 [XNIO-1 task-9] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779068893588, msg_signature=9517f1226817288a980237e615e79d2bcf3edf03, encrypt=jvSN88XIM35ozfmfrFAlmzXWgYG7w1GMXO+r2rKVMe5a2qoogojlXQtMSzzI5hTkNsog3N/e8tfbZZ6ECPqyPw==, nonce=Fi5Ws5pRRyzzoUcw}
2026-05-18 09:52:26 [XNIO-1 task-8] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"25179218391ba785f487706e99da29b4e9db4b4e","msg_signature":"25179218391ba785f487706e99da29b4e9db4b4e","timestamp":"1779069145905","nonce":"lxPyn94u","encrypt":"4A156tExFJvZdD3z4dtotjrOjHpzZWE/xTqkKqLAZ7iOnIdjzCg9FyYgSQceRdpeSWaLWJhtD/2Ldz7MqamhvOq8eIAFQucJjY1DrZqffuguojGPKG5ayzp+63q3Eupf2ztN9/9Vsi9m/XEExk5NLvGeFIc+5kgIzxVcu5jhxCaP+VWudanO2x5DZE26ESuxOXtORu0EGphyY8koV3k8cDupiGfGOYez9rgF2SxGmEJsefZIokn9e9E6XoSQIvnV3P9gwceS1bSqTZdxtrxzPX7pHzYeEUs6jtEoOUoLWljgFE2k6zXd0SIGSB97xQ3JfVFEnUSb2ul9S7xyniLBorskE7fhcanWw7GTHUSkYWjzkw0Vpo/8WjpKEKKP14IG2ScXM1yB638MIDPXGX8XHBU2uWPd0pqc5yDKo2UXAdigMleRSNA9ZDGNkPjU4OoRp1ovdjqGWd6mE7cbVTpM2BW8bAqX3/oSEClEMlTZTiWWaKLjSzHw0/N7/i7Bi3GdP+AuFzWYlJXXz92EkoKNMl9xrh5MkvarJJqkQTaQRtVhhqIiu068quczBtASrXd4qCw+VkRuaXgqGyCgVfgHqA1hICxxBhD7RyEpaXPezwssdMXN9Cbq9S1KvfcES+CPzo9bfSbrYm1U2poJoJkWkDMn9FIsLyX8P6Pa2sg0g1n69Ivl9yhD5y47oVELUesQNLBRR9G9VQFxOcoGq/HcLf2SxU4g1Z2of8WWnDxAjiHqlcjP1YIt9HUACPo6NA9k49JZDKGbH/mTK3Y71bKOOz/30VRrDpPqO77k0HEO6S6tZ3z4N1AFqxLeKBMwcMwKCzIcNnS2vRDFVBJNqp6mi528daktwfz5r9vLrMyCjuI2Px2L/QE3T83dXo5Rahsk2Lm2RHhHALu28exG07wCF3MIQdskzAd087OQoKbxbMViNgOjasK19DP2pxqgPtiPFOP1tRBR1lJznVh+586rUg=="}
2026-05-18 09:52:26 [XNIO-1 task-8] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"Jhcv53cQTNWexrH7sFpvWw08411778823288","eventId":"12698db62c074352a292f31d9a8ac3ce","corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB/type/start","EventType":"bpms_task_change","businessId":"202605151334000488937","activityName":"办理人","actualActionerId":"455108492423275705","agentActionerIds":[],"title":"安宏生提交的技术方案申请表","type":"start","activityId":"25d1_3948","createTime":1779069145000,"processCode":"PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB","bizCategoryId":"","businessType":"","staffId":"455108492423275705","taskId":101173181763}
2026-05-18 09:52:26 [XNIO-1 task-8] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 09:52:26 [XNIO-1 task-8] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 09:52:26 [XNIO-1 task-8] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779069146212, msg_signature=4d0d13172fec3030a5f63319c7ccba706cab2cc4, encrypt=Kdoa6JFkh3ADSryXwzybCuuLlwCl8Qcrb/nn/xSv9nn/aAfZBPITugOarg8k0hpJGKLeaH66jDodl4vrHGu6eQ==, nonce=fNfvBf1sUEX5acQw}
2026-05-18 09:52:26 [XNIO-1 task-8] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"786675c1546f6c74812503b137f2db861c3a9fee","msg_signature":"786675c1546f6c74812503b137f2db861c3a9fee","timestamp":"1779069146111","nonce":"pyvzZ1Ky","encrypt":"CrluvoHAXrnqaSvWJ7Mnd73wchvHLCN2bd5wBTne/WFHXhhA5AohsGtHJdrp+pZxVGc96kM6xBpFGQQN84J9ZNICmz5L+onFJwzmTsz5UOzAO5ccyX3kVQ1EIwBesYQe46B4nEWy6yG84Svnjs9YrWVH62cdrPuNEOX/3/xV5iosIHZRBxHL6l+JPLK+8dFmL26e46Rx0gKncDKvvdEXIgyIncpeo2/9TX9QsKKXE+jqdaCCOrmaz3uYEP9/zlqb1pXVr7RaN69VxpQI4WNVnkDOxIApqwdtMP9h+MLnn9r1s23POSvmuA+NB3c0VuZp/TRECO0MQA78fXe9Cn46lR0AMbInuRJlPUdgjCKbUUjxZoYIyTTsk6fz7fVKMlZenJHwOJMi/J1zwodsgcBvRIjfGvKc923FXPcxq8FOFbIRwa0frv1RsKvi9YNp9FpBlxq8E26rlWRi0tWYQL5W6dItni4gaqhzpL2v8ykD5OdxmynuhqlxQBZUS0YYWd03fZk3Yk5aexuUNsl6YvuGBRQ3I4CHlUuHDd+JXP3uN/1bOODX2cdPb9LloTVq8fMOIAf9cy3qex7MwkWl4MBGCeJw5paNgAwyIQnqMho7TUbxzFHOtNRaUdCCck2YMugJPogz2R76t9ZGdh6UR2CnZ3OlhFHRChN76vDU7yZxfsG9hd3J5EoEiCh0BQh+5Q99w/ANxO96ij41Q71FDB2JYAQati/6A1Cb2vkoFwqQQUEgCi05/hpNhwLVDbL1uY0eeBNCu1Zk3ACNtwPim2KnGU1rxLyUISRIbPq/R5ep1GGQEN8VUsmTfExmjALOwbSrIyPv31Ki5j3SM+NcMEOwtT5XSuugO+YLm9RcszXmRzh5WK2McSUlQaDrVPEVzMcT8q1QY0ohrJL/wIJz2tjoDg4lHKFMvx54pmUQCPJBneOsql8Hxwg80tZGRKws4X1ZD5yO+FVjkKwwQqBnZEnqKS3juptn6u7banKbnUDz9J78vhSAiU0NGr/lCw/697eynL+lJPx4k5qbl0dRSKX447XlOzSQS1PFFJ8XdNJUCCg="}
2026-05-18 09:52:26 [XNIO-1 task-8] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"Jhcv53cQTNWexrH7sFpvWw08411778823288","eventId":"322d4ec6b97d4e3b803bbf017adea7b6","finishTime":1779069145000,"corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB/type/finish","EventType":"bpms_task_change","businessId":"202605151334000488937","activityName":"项目负责人确认时间","remark":"","actualActionerId":"283111015435457273","agentActionerIds":[],"title":"安宏生提交的技术方案申请表","type":"finish","result":"audit","activityId":"76d0_7eb3","createTime":1778894788000,"processCode":"PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB","bizCategoryId":"","businessType":"","staffId":"283111015435457273","taskId":101120670752}
2026-05-18 09:52:26 [XNIO-1 task-8] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 09:52:26 [XNIO-1 task-8] INFO c.r.c.d.w.SchemeApplicationBpmsEventHandler - 跳过方案申请表 BPMSeventType=bpms_task_change, type=finish, eventResult=audit, onInstance=true, onTask=false整单请订阅 bpms_instance_change仅任务且非 agree 时不会处理)
2026-05-18 09:52:26 [XNIO-1 task-8] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 09:52:26 [XNIO-1 task-8] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779069146422, msg_signature=d203f73b0634dc374ef221cd5565c314681882cd, encrypt=Z5Xl9KyUhYMLqu8p2AKNFAHXH/twyaRylhnc+uWQCBFcmrGiGSLD3Xp7fZqFKUaZX0hf+7/QhVcLf7GMxEEd6w==, nonce=dS2qordNsKNiKv3C}
2026-05-18 09:55:08 [XNIO-1 task-8] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"7b6065b5435ed5dcb845eda206f98891f94b789b","msg_signature":"7b6065b5435ed5dcb845eda206f98891f94b789b","timestamp":"1779069308374","nonce":"qQ0XF5sC","encrypt":"U9/+J4q6Gi/4dQXBugxicM0gvoBr4hT7OqlI2DJ4XI6UUbAocaI3efi8ZTDbhfIh/nG/TpQ6uwP01AXFKXBaoqqKcNXxhx46rI3aoznPspCjhF5Hwag2yjwCa5XAwccYCxipDUfq1SPR1QT5ts/J1w3n8zhG8Jbqx9FgzXxgCHBZc76TzaDeS9zChsumi21WPnU8TkV2mB1RqelwKJnKmiTpn7kKlkrqsNDR3JApcc7gVC2g41srppcVuCEKOJeZVoqyWkBj5YAs2kJ9bfRIgOMzzMvx/L8wfs4NEbWknHj2cdmbQ3lwsRdA6BJiIUBaqFEbV22T63mdPt8XDBVtQiH9pHEeaFw0KNZm+Vb/ahVge0hl5u8lexQMAtwvhOqOiqlz5U3c+CdP57s5LjLfpVJtEAGmKFS3f+ftnzgButvtI5d1TD0XfCHEzVwAKcUe/toCZ/hJqklentuUFeRU34AbkNpRX9sGOqpoF9ofx5ijRSEA9iDTvyYthJfk1y2pdtwqOCKgeqPWRbgx4mWnjzDjZ7yLT6p1ep8dSnoF4srQgwoxTn4AxlqSGhCUgjCrwJyw9HYdxSIeaTP2kQKJS9c/VS2jnMc0TBM8MJQdPr1y6hnAqMjuoWjjHiJ7aOWSgHtLJGSL8K4F2pj/vqhL5PnIZxZBUNDisA+iBYlECKI5vnwskrbZfJ8Lpdpel3yhcA+KIECgdoYGiY7ErGAMVfeZRFirJNH1XHbBUIlVSaYxwXAdsrOtxOuPLT6IgdA355sEnn21UuEu/iAwmhao+mthtYlz5Z2WbsfP9YaVdkGwP0u+rUBfivYCQBjfOZOVz7hPdAMUVHh+G0qO1r/3tTY770CZrDX6Rid9kHH+U44bRgkj7NpzahruphfRIxzD/MySpWr5rPDVVUFAd7WOuNd01DblCbgBT+Ih6/p0rdHbh7VKCfZah27cCfZPpxSdKWAuJEY6JVnmfNZm6o3cRJoKZoBlNbheLtQfWrXzl6RzoJATv07Z5ap2BUvmBxxYru6scFxsmm9/RLo8Xur7f9AXn6UFvCIxSyhur6Rc9MQJgmHZu2Rkkwm1/N0GVQ0E0vrgp5QxpbMToL2J9s7wqw=="}
2026-05-18 09:55:08 [XNIO-1 task-8] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"GFB2fmehTxGfA-nBZmMRRg08411778893677","eventId":"1d301848611343f7a0fa54feba9a62a3","finishTime":1779069308000,"corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB/type/finish","EventType":"bpms_task_change","businessId":"202605160907000570685","activityName":"研发技术人员确认提交方案","remark":"已完成","actualActionerId":"264325116326361164","agentActionerIds":[],"title":"张新怡提交的技术方案申请表","type":"finish","result":"audit","activityId":"ffbb_66b4","createTime":1779068847000,"processCode":"PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB","bizCategoryId":"","businessType":"","staffId":"264325116326361164","taskId":101105511366}
2026-05-18 09:55:08 [XNIO-1 task-8] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 09:55:08 [XNIO-1 task-8] INFO c.r.c.d.w.SchemeApplicationBpmsEventHandler - 跳过方案申请表 BPMSeventType=bpms_task_change, type=finish, eventResult=audit, onInstance=true, onTask=false整单请订阅 bpms_instance_change仅任务且非 agree 时不会处理)
2026-05-18 09:55:08 [XNIO-1 task-8] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 09:55:08 [XNIO-1 task-8] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779069308676, msg_signature=45d7f40871280721e96497ee0f0796b2cff02706, encrypt=XsWSPFlfpb/LvpWzDvbzmsmPCfMZ6/y1vOnmrqtfDvoYpIukp7rMa2+ubKFEluV6Pls4Mw0UNFHdNm2JpyzKBQ==, nonce=mLxoJamn3JSUc7GH}
2026-05-18 10:09:39 [XNIO-1 task-4] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"965dbca5686125f011000e7d7ca26e3fe7222778","msg_signature":"965dbca5686125f011000e7d7ca26e3fe7222778","timestamp":"1779070178915","nonce":"I5T7Dxbm","encrypt":"zeP3BErVMQM5HDkXap/1r2ZdobBIhMSl3bRB7PfZt1aTTsiU7VPThvWR45EwP+uOq4O8eDqp4/63VcfM6DM3CdWZFwFG869+kbyiMLnkE9kV6ZH6IiSA/j+AacKCN44hyPswFFxeP4wgYvRo5Dtcym5NX5Mobzy0XF324Ri242bc7Im7mCgKfn/XQ/FInde4w1UAD7aZprck0+LB7LQo61P/3emuKg7li2HpjdC4wogcwqujgGpOZcv/scxP68i4k1YMjhjOInDiAITWUJxEkbWUSBTCiGeaQWu5u7jj+bEomxDu6jNHzTN6GrIUA2l7yNaZvVsL0b1juqSf6HDbbEAN5BB4DAnwH9wuSsVS2RcbsPqyxYdVgmFFrVAizGdefP220T/1DFdKJBp9lc35wvfZChEk+LAxklrVVY3weUcZegWJzD0eWOcuwk+SA+zXRdISRfO3V/PQQ5SsDU5DLlchq4hm2PrF5z0JXm93Jpem6EOCjMEjlF9YVbTOh4HNY2Lm6R3AJRGW13JH+TcaRqNd8+93FjMGsNaI2+LP9vkE104eh50bd0G/YzSlAm+yvuYrL1fgV0/d7/Aqp9CU27jD80u+lajc895mM7hFm44lXKd6sX6+s9fu9HpFZ+P1RXbWFeZZxB28pPwcVoNHteXpO/3PK7xUtu+xg3b9MUYxT3ysC372ViZCoX7NYkhscwyjaHEf9xJ9VoCVhIP9dsG3AbXZVVeRcSYm5zCO7wyaa5fQZrCdVW6jeLI+yroDsMmRIubMyi16DEC+J09Ek6b+uYZQ4xksy1V5aTl1QuEQoYGQT/wW7a1t+O2ndRGHuFpxmXUBzyKytfRMAwWHIbAvG7onAh9I0EoShoCtMIO8z+T5d3RX4Cs4mVoGWeZ+ZqUHoTIBjFnwlrkOlsGYABIwhfAmampZiLjI2yR63zXY8Xb7cRTf9/DxLwvhwgC9Iv+w1v8LAdADWzawr3EqxbcUGO2DgXSLw61M0OlB7MLyNIIzT2l0ICFqU2oXSMTk"}
2026-05-18 10:09:39 [XNIO-1 task-4] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"gyHkreTpRr-PZcWjpVBJYw08411779070177","eventId":"24c3fc1f79dc4285b099ddf84c8d7f97","corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-3E5AA98A-55E9-47B3-BA84-0D2101BB1C35/type/start","EventType":"bpms_task_change","businessId":"202605181009000376823","activityName":"质量管理副科长(制程)","actualActionerId":"173760274129324770","agentActionerIds":[],"title":"师敏玲提交的不合格评审单","type":"start","activityId":"53b4_05e1","createTime":1779070178000,"processCode":"PROC-3E5AA98A-55E9-47B3-BA84-0D2101BB1C35","bizCategoryId":"","businessType":"","staffId":"173760274129324770","taskId":101211684920}
2026-05-18 10:09:39 [XNIO-1 task-4] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 10:09:39 [XNIO-1 task-4] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 10:09:39 [XNIO-1 task-4] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779070179216, msg_signature=fd3343e2473f727c5ab39ca4ceb33ffaff852217, encrypt=2XQSICoX9e6eZr8/qNW1iNqjxjSkhET3jovDtFbG43Oy52SDGCbJb44GzdY9LIrbpKnO7XxL7+bOvzvz9689Dw==, nonce=BNTW8F9ds7mAHDtc}
2026-05-18 10:40:09 [XNIO-1 task-8] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"2b1174ab86e6d89902f08e11e5b0cb8a7d271f2a","msg_signature":"2b1174ab86e6d89902f08e11e5b0cb8a7d271f2a","timestamp":"1779072008955","nonce":"WdIFCUiu","encrypt":"eM4tJfTaCN1u3AZgcE2qBK4Leg6qcCB4sXkzSGogz2fqD6DTxZrKLgGtatBjMObmNA05HtjojEZWKE2rEzVk1vQtotGMkNU3duHl0m/9oz+6sJOlWsCGsFb2CQvn1Aw+02SYCg9tlxGqvui/+Ir2ts18d+ZL59Nj+7JpE6KDVhK2rsTiqX8+zCVU0m9NT+L3xHWr3hFIliRAjey0VLwQNsi0p/l6OD5Qvcmn6OpigbubCnydfkQWzmR+hWpAFBl0VoeaE8Gn3uclFfuF8sQzygfUj/BDxZEYmWPXLzWBX4eNp5grBNGO/U6WVaT3I16/5KnHWhNP6uQG+L+fP0rP4AvA9htL6g1VW5Uq2D1I7fVSnQU8gA1+LDRr+UjEQXlX4xr808R6aPGw9MnNojbKjxh3nmjduHd4Lun/ZENRQXGXK1JR5W06+ddBB5QhNWZ4N++mbK4T5NwpE7DJrzZ/aDp8J0bk+uNoh9sYC4215L+3r3FHwHYcz6p/2F5NhXIJHTIKsMuorgV6rrN/r78CLGBt/ujb8PRd3tFkKJSDORw8MaLj7xJKGH7f0QR1EQ+QogGzBUOTTByM8DEWtYqNcj33wH0KE364YDb1Zff8hX4cQOkn7OY5CGlyCczR9MzPYVKNosHCh2oV0Z3YmVnBIz9IoQIfDoqpB8bgw9p5VN2ed6h6cqEcCY646t+kCf+0ZQVngYPIYk8ibnM+tYYD8kLvT79YViueMDwpdlVrJMz892Niu7ESNOwnW5mqW2Mp+ipoLcsU9k4xPu51ms+10L8it66daseOTgfS44KN+uS/F/Kr7UhVig+qjaoLzn5osG00cW+E/7nb4FFjFu0tVmA/HhcIkpBx7bxRvKpkV4cYSCYnFjsXgNdCk/6VxUd4btAAPzvZa8tSpccZlgMVudynSH79xqtVY/Eii3YmSc/xqwj0Ab9Jt5tOpak1iRl+Q1+WiWAkwG7Iuxg1IleBSgTnklZ0Q1cSpr4c8hpv/AUZxe1m1Ygjh88cQ3Opi6u8"}
2026-05-18 10:40:09 [XNIO-1 task-8] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"RywCD4-WSe6yxrpgQl1YGg08411778914559","eventId":"d072651a182b4e0283b24e5094b72e69","corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-A59BAFBA-8AAC-4943-B4DA-3FC964AC47D5/type/comment","EventType":"bpms_task_change","businessId":"202605161455000597391","title":"位晓峰提交的售后联络单","type":"comment","content":"售后时间18-24日物料预计18日发货21日或22日到达经核算需三人才能保证及时并提前完成[南正一](223241230721375124)","createTime":1779072008698,"processCode":"PROC-A59BAFBA-8AAC-4943-B4DA-3FC964AC47D5","bizCategoryId":"","businessType":"","staffId":"03490008103620345098"}
2026-05-18 10:40:09 [XNIO-1 task-8] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 10:40:09 [XNIO-1 task-8] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 10:40:09 [XNIO-1 task-8] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779072009247, msg_signature=ad08f1965e2f6d709e7e06a3025ad2b91db13a25, encrypt=fQL73O2qKXLdpV6nMmwJrjvLlKsXc4XikopiRXqWTHibn74z6KSVgWTTeKD8PmZmlDdeRJUQdqFgBwXio9O7mQ==, nonce=6kmxMOCgtb8EcRVu}
2026-05-18 10:47:04 [XNIO-1 task-9] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"039568052a399c041a8c264e4e1007fe3300759b","msg_signature":"039568052a399c041a8c264e4e1007fe3300759b","timestamp":"1779072424161","nonce":"Hpc1jzjm","encrypt":"LXYx8WVBTEIqmUB3nCq/D3tbvTY69KhF+wxS/6i6rN/R0suZCmLJGVCCPe94e39bGC9e/l5102BdORauuR/zVrS/+4IWt6YuBJwQSJ7FBpANrYemFxcFptthHRRxjpc3ivuuyx00dLNR1N/sJguRL27whqcAHmSmpU2omlKyDWfHYIHMiXkFyJuQNksXPliBpEeJdtmW3LAlenJ/XyEyGWhoDpbZ3AB+zVbHq/1TjhP1DdvEVRn3vj5WQYKp2eugnFN5gabhFXcaToYW1nU98AshCcrIG85OWQ8LTlUUSsKYvPlKGz4c9cuQLc6o++5o9+nadLwWHmlXUvOhAuCuqNLTx2WvGFYX664TsnZMfD2go9NgHtq3S704hjHOcluSOqbMgSqiSGSpQ+/VqhmWt2ZfUI5WXdlOAMw/fIQidVFNmBM4sbE3QmXBUtPk95U1JyhOdKeZvUMWE6Qrcbe5frYbcaxlmxpqiTUxp1Nin2lLRJgE3Kv2szvPvdzYtT1pVuqUT+G0ae0KL0KZQFa6Lfg3RSiq4PD3p4OWGbewVdViQVaGPt3ZXKb6zfcdc33LPCspyfBYGpLzfDpCXC73nCvLEj29ZbOytjl0KPDo0ErjZ7VNmdM3S3yoA3/VvmGrf7t+YbJmtpYcRWbrIpcTPatwh2zKm6LPRW3hug5gK2ANAaC1PAf0Dllez1zNVsQQGzEQjIel8HjAEPR69i28nwesQf5rcRS7nzHV+khdO47onFl7NA4lJ3N86+4dLlVQlejieDbV0u1ZRR5ao+i/V6h5BRAXo86ICS0B3NUTQqOPpSfqTJ5QS9zpoyhQ/HVY+CBGJz75pdn8h2q/jmhOGZDVtMbqo24fhTxRnd/D2CR6VGg5C0T2/7HTBXCzkw44NfZkdSH6ZhHAb8Cl8Z6IjlB0TRG0Z7m6AJ2jQE1OsWusdqMi/D9iH/CxydvJ5d4n1oxGnMwH0md9VEOem0WvqpSrurv627yqkezDWn2+eXdFVU0mNJwdj+tugQuQQVIqfg9zw6QkOL2QIh2YiztRylgQSbkN3QtfsZNszNIgeg8="}
2026-05-18 10:47:04 [XNIO-1 task-9] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"HHIC0OoBT8OYiZJ4jnAMmQ08411778917283","eventId":"f79915287a4c429d88d02f8e6c0bc0dd","finishTime":1779072423000,"corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB/type/finish","EventType":"bpms_task_change","businessId":"202605161541000233493","activityName":"总工程师","remark":"","actualActionerId":"035715651324258877","agentActionerIds":[],"title":"张新怡提交的技术方案申请表","type":"finish","result":"agree","activityId":"122b_b71f","createTime":1779065245000,"processCode":"PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB","bizCategoryId":"","businessType":"","staffId":"035715651324258877","taskId":101170493283}
2026-05-18 10:47:04 [XNIO-1 task-9] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 10:47:04 [XNIO-1 task-9] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 10:47:04 [XNIO-1 task-9] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779072424451, msg_signature=86cfdc6167b03664c4380b7187bcd3fee4e9aa85, encrypt=mUOnjTBJtHoM1WfCWej4kMtiY20m47Bl7hNBKy2/ZQxIvt56N+a+6TMwhQyMD1fgnMxFVrfYciCfp34wCBr2Cw==, nonce=W6jGEgHRyaRGbpx0}
2026-05-18 10:47:57 [XNIO-1 task-4] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"eeb7c32d823b229e7998617308fb2e88af50923f","msg_signature":"eeb7c32d823b229e7998617308fb2e88af50923f","timestamp":"1779072424228","nonce":"C9b2wnjY","encrypt":"F42kI2JXEwNvg2cTSys92Jx3N2Y8bmd4+QIrhY2FOONA50K+rW0RluehXdZjukKYfQAZdgxEERovFkjCEJdqrHA8JhTBj/piCyQvdYsmUUyy7JwHqlptY98EyaUHhFL7Ucmp2dWPOM4+d+JImonRMC/SPBTK5XFjJ7l+c+uqUBxhEXWGztRtYQ4UkhmNzDhz+iiSzf/wCnyEQfGRrR30JFV7havBsQsbUBMPvz2mOc7D4y6uxt59OZbdkPCuygr9zRjC7ayyKA70zw0WfCIlNxPRq0ULo6rHVNp290rN4mUfOsmylNy4vvzXFV5hQN7bi3Ba3K0ON4SyPdMML1z4ox+2/VqUt2253J/VEgvBO7mR5YvFrbfSXIJtfcBiLv4u7DcmoTjJMUJrzSOFkll41DAjhO9LqnMmWpGOEOQ1O4bOsgy+M3h95NsFaPPElnU+2nKOBQCv7b4tjvJ8Lzr/MP3woHU8AWYgzztopqZJDDOriwX4mfZhMBxye43vR4B8p/qY+VW2V1QGKug6X+Wa0grffZmSIyXIRVfZryQhA7mZNmoV+N7xA3hHB4jk97qmFsy6doH/lhTOiD4w7HkC0PBCpsEuWYMDbQZRoUeC71xrOSAGevZmyI8jWkqhCg81sCPX5JtqIcQC5bEa5rfzarlhX3lclqky7NxGAUu3ZKBon3Qon+0FrlWvLPD4q24rHvzdmPRZntaa/pqOeq/hc9qSYWuvd//cnylsSR2Qgz1aFjy7SfRBG2wRIWa9ltRwWuhJ8+Ts7/BY+wLdrF9b9uFiM0lVl2lzvMEKXXBDrG3XzGt0vH0/gXWGrWycbnA4/I4uDuir9e58X601DZv5dDPbGpRT7/OE08/oNYR2vmLqJBrMODv6PgSoBYEOpbkBttDvQNkD4j78l90DO/rTQBZaO2u+NVHbcAkr2mDZ8uUbdODbTG3QWvnV6gceJEmyax0FbEbWDvyGsF8pQL+iEWIVxjRTvUYxW0JzeKUHECC5tIgpb2/BHHCYqQAYqudZ"}
2026-05-18 10:47:57 [XNIO-1 task-4] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"HHIC0OoBT8OYiZJ4jnAMmQ08411778917283","eventId":"6e7ab2b133884cd7b613be7f8747f55e","corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB/type/start","EventType":"bpms_task_change","businessId":"202605161541000233493","activityName":"项目负责副总工程师派工","actualActionerId":"3816683726197864","agentActionerIds":[],"title":"张新怡提交的技术方案申请表","type":"start","activityId":"7246_df51","createTime":1779072423000,"processCode":"PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB","bizCategoryId":"","businessType":"","staffId":"3816683726197864","taskId":101175493981}
2026-05-18 10:47:57 [XNIO-1 task-4] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 10:47:57 [XNIO-1 task-16] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"a29ba660a5912ec8567359ecd6e95b2e4cc9a5e8","msg_signature":"a29ba660a5912ec8567359ecd6e95b2e4cc9a5e8","timestamp":"1779072436820","nonce":"6e9KSNxD","encrypt":"+lAEGFFus+FDzLAOYJO+xHgNQ8yxR43xcttAhDJFUOzv2vDcfDUWz3FRK/FgTjq3tBf3P3RpS8mg+D2eWfB4mkDPgUqIJaYyshK46uBX2O5yL6TH4Pf1ZrWE1LI9yRi5QT860jwXMgAVHvzDBvizBz4OY6+oZsv/C13IecTEKr+CUZZ3aWOyqlz4OrfbJ3VXWi2n6yYh3LN2dFUm9aUfc293LsuRR8x5IC5caxrRceZbE/P7J3HsbgWWQpEdJfOVULu6mT/QFLkx2Kn71iJZlvTGi7+7HOipSJpWv5y/RhWiTOVh8XEVoQD2giwtXrXc7wUujJTweOjr3hyUgk3pdIjdAn3w/Dh8RkIYHsA9Duw8OqLG907BwbnCRPF4lv2/x/r+HXAT3aHWIlrqqk8poSWc6CscnE1jV/AG0UUTmDswpYikdYSywPnOlZlK9/iTR2JGSfE8Si7OSJDNnRXvPrONvR00TUEVPVEYv8IZxHUG+LzeT/XZREpLtjgQzgP5KPwwT0X4jKAsW4MfexOv60r4rnt+AT0AMdxUcX1zB+t0z2z4ad7AwIli/CvFZdEsqJMeGpuwpBWAqFEEuT3Y/aBFNdXbicpEPdBwe1KaHmFE8pBeKOCvKYYiVPsZSyyEqvqp63kkd//wG2xufEEsP4EabJ2Vk/dgRPOLg99w4Rd0Qwpo0Ahpdvwd5c2Ay/wYfrI261V4bUAuZiKwNberVStSn/mb1VYr8eu0VMdpPyY/Zpdeo8QORMgjoapSWQAJ8TH/d9/y0VZmrHg8lNZdLga8kXcIrkNrA+Ym6pf4C3G4K5+pUaEwUjAJ2bLpw5s6mjB9LEHky9wjUoFunb76wPRB9c+o0NqJ7snwF0oddVp0TMBLhguz76YfVkx1GUaBnilHWHCSJdQNzTxcD24qafZIzEcMoV9o9EDiY+lqb1lgvlG86E8Mx6lvVFvI6o48EuwyKMlxlyyZasdF+63TfSaJFN8zOS9ULb5+O1L/O7RFczMcxL+mP04ORg7axC5L"}
2026-05-18 10:47:57 [XNIO-1 task-4] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 10:47:57 [XNIO-1 task-16] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"HHIC0OoBT8OYiZJ4jnAMmQ08411778917283","eventId":"6e7ab2b133884cd7b613be7f8747f55e","corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB/type/start","EventType":"bpms_task_change","businessId":"202605161541000233493","activityName":"项目负责副总工程师派工","actualActionerId":"3816683726197864","agentActionerIds":[],"title":"张新怡提交的技术方案申请表","type":"start","activityId":"7246_df51","createTime":1779072423000,"processCode":"PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB","bizCategoryId":"","businessType":"","staffId":"3816683726197864","taskId":101175493981}
2026-05-18 10:47:57 [XNIO-1 task-4] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779072477001, msg_signature=9d26ba871da9dabca346d38253edc572d6fa61f5, encrypt=x7mIJywRw/ngmVo6ZUQQfEalHp2ZI/sGNT958CvPKLtqZEMxolBXu8hyLfVrn+XknAJ1X2SBvW8C6JDej70FyQ==, nonce=rSFr3mf5w2hEsilh}
2026-05-18 10:47:57 [XNIO-1 task-16] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 10:47:57 [XNIO-1 task-16] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 10:47:57 [XNIO-1 task-16] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779072477004, msg_signature=3679d65403927114872dc198a19de821c6b63a44, encrypt=mplUAgNW5Ypd4BPmMHs++zS79FQH73PHGcdkP+QyjhnehQhApoBK1p6nsbWU24wf4POSG9zrIBCQu6fxj/F5BQ==, nonce=Q3SUriR7sxn1ql1B}
2026-05-18 10:47:57 [XNIO-1 task-5] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"47df19e37999aaec94ed34848ac53f5ad490c11f","msg_signature":"47df19e37999aaec94ed34848ac53f5ad490c11f","timestamp":"1779072469464","nonce":"G4mkvtTI","encrypt":"RD0jOh2vQOu5Z1qsYeaMQX1s8agA51l69RzsMmeGXTHyQCFWht4DSXGgbN/XxsRit5o+UpBR/9M2iAl7Kahyh8Iv6VSrBl4yRyyivopnR10ykvooGFzCzvAL43JQsGshYDSiJnAJVb93JFscYoShRuViEExuFyMOZp4qOYjnSfwsTBD02ZBjVwXpjlZdzZogiHNsdSNdLhhH2E1ziIhLeWATDFdeDmThk0OjAJP7wooE88jQ6yqBzclzKFuSwuM4G0L5rwYfFY6pJ07vBt3vxZ4nv9Avhsupir6b3rHl3ePLgRfSHAPGbreJC0n0Fm+jiGMvS9dQcB8MYDHW9E3K+JbetePDSAZMmkvV+nyWM52sTOqyJf+iVlpz2QNllFrsQDjQMVjCYmBtscRL1bYGSnzJSYdRNu4podxqkdtTfOpIPMBJ0TABfyprrTeYUypD0v22zs/HayNJ1Ha+UPuHwuDzQ7FffNmnP9sTH/truxaft5EO/GTti5o3INwbr4u+O4eJZknqbzUFmma4qbuYusd77FmoGx1E/es8mx4dAtdMiOqkHRTW9QvRFt6FBnkLPikMvxNw7U0prlCuF/DVabz5PQyxVvLo/E2uc3M9JDT+KOUFuoJeGU5PM01MGjyEIZID6f81t5pRBbk44SEI4oTp2MTkDdi2DLuXgGPKhSO7Oq9USjdgA07GUJfochqJDWU3q9A3PouW/GfmOoxFRfsfY5LhOsq+PaN0ac/U5m3doBONBT32hM0PxDdQGCXtKVxFvRBF2Y0vk5fD9P531h+gddv3agXG1n8y3mDF4Mf/hSy8JSaJQ4O+Kzf8FoRtfg2G3QQEJrX9/zDTOgG5ACDnrqvvP9QLkw/PlI4m24dD4DbFGpCqG/nZF5ggDSRmPnaCMrSEFeR3/mI0qu2882Ri3PkkCGiv1EUkkBu2M8tjfnbaVW6VP6xdEpB6HSmnll0nWPGFEYAIlinDz6ZAnbPcZY7uFqlpFH+Alu4hO2/XEhuE5sl7XCzXJde3Z8rD"}
2026-05-18 10:47:57 [XNIO-1 task-5] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"HHIC0OoBT8OYiZJ4jnAMmQ08411778917283","eventId":"6e7ab2b133884cd7b613be7f8747f55e","corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB/type/start","EventType":"bpms_task_change","businessId":"202605161541000233493","activityName":"项目负责副总工程师派工","actualActionerId":"3816683726197864","agentActionerIds":[],"title":"张新怡提交的技术方案申请表","type":"start","activityId":"7246_df51","createTime":1779072423000,"processCode":"PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB","bizCategoryId":"","businessType":"","staffId":"3816683726197864","taskId":101175493981}
2026-05-18 10:47:57 [XNIO-1 task-5] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 10:47:57 [XNIO-1 task-5] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 10:47:57 [XNIO-1 task-5] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779072477005, msg_signature=fab0463ce6ac2c0e87ff2f42b75beb3aab0d2098, encrypt=NTMuvy5ex6Ffp+4AG7hJu8xCcJtM8WHf25nZbyqxNMsCIYdUsQ0vRLrzApjWt1ltKEd8OFufWw13mult1BZ5XQ==, nonce=IAAAFL9pL1VgrDfy}
2026-05-18 10:47:57 [scheme-bpms-HHIC0OoBT8OYiZJ4jnAMmQ08411778917283] INFO c.r.c.d.token.AccessTokenManager - 钉钉AccessToken刷新成功过期时间: 1779079577593
2026-05-18 10:47:57 [scheme-bpms-HHIC0OoBT8OYiZJ4jnAMmQ08411778917283] INFO com.aliyun.tea.TeaModel - [com.aliyun.dingtalkworkflow_1_0.models.GetProcessInstanceResponseBody.success] There are some cast events happening. expect: java.lang.String, but: java.lang.Boolean, value: true.
2026-05-18 10:47:57 [scheme-bpms-HHIC0OoBT8OYiZJ4jnAMmQ08411778917283] INFO c.r.c.d.w.SchemeApplicationBpmsEventHandler - 【方案申请表】审批详情已拉取 trigger=bpms_task_change processInstanceId=HHIC0OoBT8OYiZJ4jnAMmQ08411778917283 title=张新怡提交的技术方案申请表 instanceResult=agree status=RUNNING fields={}
2026-05-18 10:47:58 [scheme-bpms-HHIC0OoBT8OYiZJ4jnAMmQ08411778917283] INFO c.r.s.s.i.DingSchemeApplicationApprovedSinkImpl - 新增钉钉方案申请表归档 processInstanceId=HHIC0OoBT8OYiZJ4jnAMmQ08411778917283 id=6
2026-05-18 10:48:00 [XNIO-1 task-9] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"b4879f86c32754af3be1d8121ff6efd33f45b731","msg_signature":"b4879f86c32754af3be1d8121ff6efd33f45b731","timestamp":"1779072479827","nonce":"SvxWbj3Z","encrypt":"UpmWAJD6Dnshiwcz2hd/ALFDhdfscNwwOwxS9b2sF+Z3EZ273cWyh11oCV6LuXLduXdYgfpf/8DPKOn036eAhCRTSnolfEpZjp/5hc2Np2Qf+iGJI+b9W4ZsK+cgCIrYPBfb5XCGLfpmlqVVsM5QD/zORum294+2vXs9LxFclhKtM8cNTwd9eE7XCVxWBfMqu8vg7UK2QdSvaDrA1O3BKfUoxZ8Evjvlzmzi0xZVMUYD+D4cZJbyPxsk5LQrETCpVWX+i1IIXNiktzsIU6wBQfnC8uRW6gSV6ugS/1eE5if9YVkFoQzszeCe3hTX1oPO64w/FuY6EZ/VqItBz6WZbjKSqeN9GUeZZM1W/tjjmCAlNNBLfdnvaV7NzdrNdJrF6S/b8JOFr0Qr494aaGtv7zFH3kbiQN7rYU2yDEf6oGW16XMfvSCjN0XltxtBK+GJiEKSeNiEzer0eW/IF8MQloKgGhUN5hgBLt1KQ5zYya1yuil4MAZ9g3krFenkbT8dKyGRUJEqPPu93FcwNDDub2bUoRghPetWLxhFIxN2fZYaX6y1PoCCh3fXU5CHTpZiLBQOH6kku5zDcIktdUFUFhzhNI7FaIamFsjBRlEIyvo2ADGfckbCO/4xpxu/suwi0kx2TUTAG0zbYewQ46LtIPU4QSMYgsCHiJ98IF1B1nWW8ZLBA8kTRDcwzZcxT8Jr2AGrKOyc3Hte2+e0HBxfaEtToVpLwU4ymtZzfAH82yOEzCT6MkU/IhF5Q2lAIyYcu0MucZwBS4irqBP7twRxqyz+z/t0pMaI0HWXEYhzZJNu/tsMq+VZfqKKEPQiTyktbmV9eH463C86MEUpfyb1ldPlEk90xXjtL1SvaiqpXz7T66iAfxi2rr0USoeRf8f+CeQYmve2xRp0g2RbLBVjriOKw3aIWyydNtjjO5KbwsS5gix17VP/SzikKPOaH8nPYOaTB9gTP5n7MbQ79y4Bzp4oVVLXm0jGdp2hz1xzIX5p9JL/MHqakXbNpNlKhGtE3ORS4X0N/taO3vT0DF5vs5f+57YL8X5dbQUOaziuBh0="}
2026-05-18 10:48:00 [XNIO-1 task-9] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"HHIC0OoBT8OYiZJ4jnAMmQ08411778917283","eventId":"f95721059e21456da5a1cd2510dd927e","finishTime":1779072479000,"corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB/type/finish","EventType":"bpms_task_change","businessId":"202605161541000233493","activityName":"项目负责副总工程师派工","actualActionerId":"3816683726197864","agentActionerIds":[],"title":"张新怡提交的技术方案申请表","type":"finish","result":"redirect","activityId":"7246_df51","createTime":1779072423000,"processCode":"PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB","bizCategoryId":"","businessType":"","staffId":"3816683726197864","taskId":101175493981}
2026-05-18 10:48:00 [XNIO-1 task-9] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 10:48:00 [XNIO-1 task-9] INFO c.r.c.d.w.SchemeApplicationBpmsEventHandler - 跳过方案申请表 BPMSeventType=bpms_task_change, type=finish, eventResult=redirect, onInstance=true, onTask=false整单请订阅 bpms_instance_change仅任务且非 agree 时不会处理)
2026-05-18 10:48:00 [XNIO-1 task-9] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 10:48:00 [XNIO-1 task-9] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779072480140, msg_signature=e201bd66f7d54ac900bfd42e06ba1746f271cc0c, encrypt=7lj7arY1T/FhusUG/hJcNbOxrZA6Ry2DQRQubwo4vQ0o817yM2VigrGahZm75oTAy7r8rEaNBceVp62OOdYmLw==, nonce=c0iepBkJRLOi08Po}
2026-05-18 10:48:00 [XNIO-1 task-9] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"37ea659760217291c0eef264658d5145d238c85d","msg_signature":"37ea659760217291c0eef264658d5145d238c85d","timestamp":"1779072479869","nonce":"XbCfkFmp","encrypt":"A3tq2oKKJSnQfgUC/mKfNJQWG+EzpNb5QdRCMCQ8rqlF0B1YVd0TL1lguU/XX/XkzvCF3vbKkRPr+0IG+MZjA0t8ZRsXXT7i4YoYRseOu27zP2CqHZnZLrJuDBLyD51X0o+ClMBnD8UDXNyXlIDLXuANWzW3P2V0Hq0nsb34E0rvw2/NEEq47FcvpDI5D3rl0pdfIJb8ffK0DWhxaoduL5IaZXw0qQCuL7TFcO1HbChtcfqdq4OyxS0cTG07ILi6FHX+fk3sHbgDTbF+NR97W6fvlgEIgzfjPuvAEzdqfqCqqwmePkD9ZvmdQ7Ltpe4S4ixCehGfh0/Qfx0x0Ubx2eEIyfyMFk67faxubJ+Pqd3T0FkqdGzUHunjIlXp6f4O8pqg0lwHidZXVTkmHPUZLVw6pnnHvjPGPPge9cFh1czfWLFjRFILQcL5YpzJ0d9G5/a2hv6rx2I/ZxfmiICcrKljfRDP8/DVnBN6cXKRn027CpBurgy7B4Q3A9XcJem2m8+Px1tPStqO09gy3mq+NU33cIcd2SpESj6GNzydsfvzzoosZMx3HlOKf5po9gjzrMcAurdQVaSkk1PAwq05UTjcHJQwBiHWQmx7K58IZT74ctBBeIyeJs4U8bm4mR9TuGP4+r6PaLcY9XgfX/ooNZyZKUVLSD3Cshcx/IAQg4LLRRTFIWPnBXl798Jjudw0vAxVHN22n+13UYPeOtvGi80DXSUK/7fpJFW6n6h7lult9U8jNecJC9JRDJfWe4ZL7k/GzJ1saAs+vyyE6p5iTMdII5XssOLLLOD4kiUG08x84duDpCBW5JrH6LqIjIxxRBpha48m5jVyBo1yY5RxMhgvOSuVCW6cZ1htQ8MFSTXfoDyVIEWM7oLbKlS7Pxl85NMhyKMTAQHdjEwXg/rY8wF7Ww1NWmacERVShOHUaCnAU6pZaxsJ7umhB1C7fLOaOseRy48fzJbPqDOcwANDF5W67RB/FJnYR9JJwupc6gKL/S+stWno0cMAD2PZLiAJ"}
2026-05-18 10:48:00 [XNIO-1 task-9] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"HHIC0OoBT8OYiZJ4jnAMmQ08411778917283","eventId":"8068023167d148ec8b93e42df795cc3b","corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB/type/start","EventType":"bpms_task_change","businessId":"202605161541000233493","activityName":"项目负责副总工程师派工","actualActionerId":"0412414241844204","agentActionerIds":[],"title":"张新怡提交的技术方案申请表","type":"start","activityId":"7246_df51","createTime":1779072479000,"processCode":"PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB","bizCategoryId":"","businessType":"","staffId":"0412414241844204","taskId":101147114901}
2026-05-18 10:48:00 [XNIO-1 task-9] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 10:48:00 [XNIO-1 task-9] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 10:48:00 [XNIO-1 task-9] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779072480213, msg_signature=9d95cd76654784eb9308c22f6442efed55fb893a, encrypt=HShl6bg6ogXnuIANspiwCPBRBHmP97qpPUW4Lc/7j4xMp8BXybKzdUsi/qL84RU8h4joMlTtKdg8JWd/19zqEA==, nonce=lVpWTKUuRKeypkyv}
2026-05-18 10:48:39 [XNIO-1 task-19] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"9790c119cd1af61c5140b32bdbdff2c0907630ea","msg_signature":"9790c119cd1af61c5140b32bdbdff2c0907630ea","timestamp":"1779072518957","nonce":"oaR80ue9","encrypt":"i9M08Xh8DYvohsuMcpmlHVm4HdbAdgPCBOlx9/XbMJmVB63Gjkc4GjfnhivP5F9EwZeM7Wq5uu35cuFgjp+fWg18gYgkdr3oxWZp0KRXQ2muIzgku/7YoEXVt6V7f1q8T0sLoTj/VHD+0M6mWoJa6ARqRczzhCRFzT/++YzMhLtwcdekJKmWCk09yw1bVVUBcpK1n4PSX+SkUJnDwhk/+TDCSx0WqUfIjZbCY6RRWwjetZvcpksihwZPrQXkPaU3XGaleXmMHULpZmeSay8TTiXmkcnpx2hLGoRURQwbtg/ZedOCw7CnBXQvr/y7/57t8I+kFk3YwcsKJMGHSOVthBNcAZCRee0gnc1CGI4vwHYz7jw05SFRUItaVJmXPz+3NiOElzpsDxUn9/W/sIEBmEP18ScJ9pOJSrlbLrdz60byOOV1tGk7HYRRV2TsJL6Bu/bOGEEwIR9MLXl74QzQ+W7+JI7FNBMSlKaijP2Q4xsqkuXmpgO51Je9K2tnJjTO97on2S5Z4N1H48b93MplKsvasAzVP64by1Y955MfVyVD4aVa+roooUZDAFHFswUnXoCBBDWxXIndmiO105b5laIM7FnEUVDjFrElwCZigqvN10l8Usl/DAvK1RJJsdgYm9oZwqtWU3IxfUWaKry9o9AJKkb40U+LEDAl7C5iyxPgu+3gjPl8pGt2FdLmxOHctSEsXBotPt0/QAI9sSd/uPiwfsp/3JdYtZFiQ+eWBH2z2w73EQYb0Q6Psk1/wZlr+QRcyugju38H9aWz3R586PqgZ2KUfp7Pwt6+0+T83i5Nxgy89YHwAsnY1Em9JyOFOQX68RB1vXc2aN48PUWwPNjIVSTgjRIV7KMwjZngZTJVgVcD8tvRgxBvRXQz0v7SmVzxb+thxcQuc+8Zw7zYGk2mqveKSRfimrcB3wagRvSWJC23MIGjxQwnCa1ChvVOR/qIbPJVdugUUs/sGCJ7w+QEEAzliLKpMoYPxZiKn0xXYEzLVeq0IamhhlVGwxNht9K0TTHcYCQWDeY3apDckR9zBSlQSnW7mCQgUuOBUm4="}
2026-05-18 10:48:39 [XNIO-1 task-19] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"RywCD4-WSe6yxrpgQl1YGg08411778914559","eventId":"e961172ae36e4c8aba3dfcb339984e5e","finishTime":1779072518000,"corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-A59BAFBA-8AAC-4943-B4DA-3FC964AC47D5/type/finish","EventType":"bpms_task_change","businessId":"202605161455000597391","activityName":"副总工程师(非标)","actualActionerId":"3816683726197864","agentActionerIds":[],"title":"位晓峰提交的售后联络单","type":"finish","result":"redirect","activityId":"d81a_b76e","createTime":1779068038000,"processCode":"PROC-A59BAFBA-8AAC-4943-B4DA-3FC964AC47D5","bizCategoryId":"","businessType":"","staffId":"3816683726197864","taskId":101144070875}
2026-05-18 10:48:39 [XNIO-1 task-19] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 10:48:39 [XNIO-1 task-19] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 10:48:39 [XNIO-1 task-19] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779072519243, msg_signature=cc097f6a822236f3901d016486f3e10ae1849c6b, encrypt=2LOYOMDdqcyGM6ekYXQD6Kjrsd+VQHwoB/6M1pt2NOZ6CAlBFF0bKTBEvQYN4dbiKMZEPflRsbo9sr4WW/qNqg==, nonce=H8OFqwwk0TptTMNu}
2026-05-18 10:48:39 [XNIO-1 task-19] INFO c.r.w.c.dingtalk.CallbackController - 收到钉钉回调:json={"signature":"b2082f8ab72b407e2a2c00bac95d2abd6c174344","msg_signature":"b2082f8ab72b407e2a2c00bac95d2abd6c174344","timestamp":"1779072519189","nonce":"IZKeY2uQ","encrypt":"XvYWIAbcuIs+m87pWALkAFUOpOEzVt/A1P1cvZRofepQp/JnhxlLuzZSbVYq3IVxpZ+ilzIC2eBwD0XM97ujl+cZ1xEFVffP4QMxTKFxmivucEN3MrlyeGZb7kY4qWO05y+B2vXKFF4SCCl5ZenvbnDBEOoZu38R+ovh+OTItKWSojTJtVtPw1HendbugPfAv5MExOwJbu9dAVpGNPGUBseVthG+BZqOZ66MVQwxVrxPHmq4iqHCZ9IW7od34ffvwKjcckJtP6bshMRgiFArJBMr2uhLSQldUP7S3s4usqvHjdkf+bYVMMQ9HfpkallFunVR+PMlG1f2nawwWh7YtOClDyUBLjoMYKCFkcPGnOptVEr2dHtY3zJH/uaaiX6X4od9VHBs6Wqc3qE1NxwSEgDAJ0V6AJdKD//9VkJzGxtT94Vb0LMoxPhWzkWtrkLoT87f6j2V41gozUG2EIUBeZELYyzhbszShmXLSDBFBmQgDR4DuJmZ27WvVP0wFmogN+QZ+tOocacAQy8+QICr4Zj1xqHsgbGRidV0IM+dKO0hPj4iw5jco44FY4M9Wme457HFM2zA7wK2lIhJH6WYKueOki3vd+on0jK9xg1LsnM6dRrU4gtBiZr2uZBvLHgX+z3X4ditFqQOmgnUJh5ze2E/qcD3OS+d/RJWAEjAed4WQo/8+DtsvJdmwfBHsjO5OUMjfgw6kPhoxgCwoLlKcDNUFjCLUjzxQ+iWk/taFWhxEps8t2DY1eB9zBJocvrq1mR5Ji3+5elkzMMh1iQnLG7YV+olXDD/8o9xSrLkS1efPVHLIEMyvFnFYW3Zl84qZoSrOVMF0Wsk4OwzQIGCZdHrI1J87oLvX50Vngwy/aLewk6LOXPH7x76lIOxjLGgxBXZsgHqvcXyVqE4Oc6RkwxWPOaCv5h0KOBiaASfxJ3LCM8TmyGtx6/U6hkpYHz0lhhlG9jQXIJ0yZkd+6/Obg=="}
2026-05-18 10:48:39 [XNIO-1 task-19] INFO c.r.w.c.dingtalk.CallbackController - 解密后的回调内容: {"processInstanceId":"RywCD4-WSe6yxrpgQl1YGg08411778914559","eventId":"b7eb7ffcaa794311bf0ff842cd95e40a","corpId":"dinga5c6eeb2f797ecdbf5bf40eda33b7ba0","resource":"/v1.0/event/bpms_task_change/processCode/PROC-A59BAFBA-8AAC-4943-B4DA-3FC964AC47D5/type/start","EventType":"bpms_task_change","businessId":"202605161455000597391","activityName":"副总工程师(非标)","actualActionerId":"231850251526222856","agentActionerIds":[],"title":"位晓峰提交的售后联络单","type":"start","activityId":"d81a_b76e","createTime":1779072518000,"processCode":"PROC-A59BAFBA-8AAC-4943-B4DA-3FC964AC47D5","bizCategoryId":"","businessType":"","staffId":"231850251526222856","taskId":101213660295}
2026-05-18 10:48:39 [XNIO-1 task-19] INFO c.r.w.c.dingtalk.CallbackController - 事件类型: bpms_task_change
2026-05-18 10:48:39 [XNIO-1 task-19] INFO c.r.w.c.dingtalk.CallbackController - 收到事件: type=bpms_task_change
2026-05-18 10:48:39 [XNIO-1 task-19] INFO c.r.w.c.dingtalk.CallbackController - 返回加密成功响应: {timeStamp=1779072519501, msg_signature=1b1fa612dc9a6c14bd9acb057fe2d5ce3f1b36cf, encrypt=aG84HF3dTVjHH9D6/2gQpaj2BfKnHEYJLD12xvtFjLC76dZoyim16ayaGVmxACy1Cdu0UdM672+itE5o+AZSzg==, nonce=nDwSG9UKcobJYhIu}

View File

@ -99,14 +99,6 @@
<artifactId>ruoyi-oss</artifactId>
</dependency>
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>6.4.0.jre8</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>dingtalk</artifactId>
@ -161,18 +153,6 @@
<version>1.39.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-core</artifactId>
<version>1.39.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-core</artifactId>
<version>1.39.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>

View File

@ -16,11 +16,14 @@ import com.ruoyi.system.mapper.ProcessOrderProMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StreamUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@ -34,7 +37,6 @@ public class CallbackController {
private static final String TOKEN = "VDAhP9mGgALfgWioUHlVr8";
private static final String ENCODING_AES_KEY = "p9QQoHGCX1wiwSkHnLiPhcfymUCOmNum0CBuYQfFSiu";
private static final String APP_KEY = "dingebfrpzqko25vo8w6"; // Client ID
private static final String SAFETY_STOCK_ROBOT_CODE = "dingwoaeaozawfochwoo";
private final Logger bizLogger = LoggerFactory.getLogger(getClass());
@Autowired
private ProcessOrderProMapper processOrderProMapper;
@ -53,72 +55,250 @@ public class CallbackController {
@Autowired
private SchemeApplicationBpmsEventHandler schemeApplicationBpmsEventHandler;
/**
* 钉钉事件回调勿用 {@code @RequestBody}encrypt Base64 密文整段 body UTF-8 解析 JSON 会失败
*/
@PostMapping("/receive")
public Map<String, String> callBack(@RequestBody(required = false) Map<String, Object> json) {
System.out.println("【CallbackController】参数: " + JSON.toJSONString(json));
public Map<String, String> callBack(HttpServletRequest request) {
try {
bizLogger.info("收到钉钉回调:json={}", JSON.toJSONString(json));
byte[] bodyBytes = StreamUtils.copyToByteArray(request.getInputStream());
String bodyText = decodeCallbackBody(bodyBytes);
JSONObject json = parseCallbackJson(bodyText);
DingCallbackCrypto callbackCrypto = new DingCallbackCrypto(TOKEN, ENCODING_AES_KEY, APP_KEY);
// 检查是加密模式还是明文模式
if (json.containsKey("encrypt")) {
String encryptMsg = (String) json.get("encrypt");
String encryptMsg = firstNonBlank(json.getString("encrypt"), request.getParameter("encrypt"));
if (encryptMsg != null && !encryptMsg.isEmpty()) {
String msgSignature = firstNonBlank(
request.getParameter("msg_signature"),
request.getParameter("signature"),
json.getString("msg_signature"),
json.getString("signature"));
String timeStamp = firstNonBlank(
request.getParameter("timestamp"),
request.getParameter("timeStamp"),
json.getString("timestamp"),
json.getString("timeStamp"));
String nonce = firstNonBlank(request.getParameter("nonce"), json.getString("nonce"));
String msgSignature1 = json.get("msg_signature").toString();
String timeStamp1 = json.get("timestamp").toString();
String nonce1 = json.get("nonce").toString();
// 1. 解密
String decryptMsg = callbackCrypto.getDecryptMsg(msgSignature1, timeStamp1, nonce1, encryptMsg);
bizLogger.info("解密后的回调内容: {}", decryptMsg);
byte[] plainUtf8 = callbackCrypto.getDecryptPlainUtf8(msgSignature, timeStamp, nonce, encryptMsg);
String decryptMsg = new String(plainUtf8, StandardCharsets.UTF_8);
JSONObject eventJson = JSON.parseObject(decryptMsg);
processEvent(eventJson);
// 3.返回加密 success
Map<String, String> successMap = callbackCrypto.getEncryptedMap("success");
bizLogger.info("返回加密成功响应: {}", successMap);
return successMap;
} else {
// 明文模式
bizLogger.info("收到明文消息,直接处理");
JSONObject eventJson = new JSONObject(json);
processEvent(eventJson);
// 返回简单成功响应
Map<String, String> result = new java.util.HashMap<>();
result.put("message", "success");
return result;
return callbackCrypto.getEncryptedMap("success");
}
processEvent(json);
Map<String, String> result = new HashMap<>();
result.put("message", "success");
return result;
} catch (Exception e) {
e.printStackTrace();
bizLogger.error("回调处理异常", e);
// 返回错误信息以便调试
Map<String, String> errorMap = new java.util.HashMap<>();
Map<String, String> errorMap = new HashMap<>();
errorMap.put("error", e.getMessage());
return errorMap;
}
}
private void updateProcessOrderProStatus(String outTrackId, Long status) {
private static JSONObject parseCallbackJson(String bodyText) {
if (bodyText == null || bodyText.isEmpty()) {
return new JSONObject();
}
String trimmed = bodyText.trim();
if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
return JSON.parseObject(trimmed);
}
JSONObject wrap = new JSONObject();
wrap.put("encrypt", trimmed);
return wrap;
}
/**
* 解码回调 body明文机器人消息多为 UTF-8 GBK加密模式外层仅 ASCII+Base64UTF-8 失败时用 ISO-8859-1 保字节
*/
private static String decodeCallbackBody(byte[] bytes) {
if (bytes == null || bytes.length == 0) {
return "";
}
int start = 0;
if (bytes.length >= 3 && (bytes[0] & 0xFF) == 0xEF && (bytes[1] & 0xFF) == 0xBB && (bytes[2] & 0xFF) == 0xBF) {
start = 3;
}
byte[] payload = java.util.Arrays.copyOfRange(bytes, start, bytes.length);
String utf8 = new String(payload, StandardCharsets.UTF_8).trim();
if (!utf8.startsWith("{")) {
return new String(payload, StandardCharsets.ISO_8859_1);
}
JSONObject utf8Json;
try {
utf8Json = JSON.parseObject(utf8);
} catch (Exception e) {
String gbkOnFail = new String(payload, Charset.forName("GBK")).trim();
if (gbkOnFail.startsWith("{")) {
try {
JSON.parseObject(gbkOnFail);
return gbkOnFail;
} catch (Exception ignored) {
// fall through
}
}
return new String(payload, StandardCharsets.ISO_8859_1);
}
if (utf8Json.containsKey("encrypt")) {
return utf8;
}
String gbk = new String(payload, Charset.forName("GBK")).trim();
try {
JSONObject gbkJson = JSON.parseObject(gbk);
if (hasChineseInRobotPayload(gbkJson) && !hasChineseInRobotPayload(utf8Json)) {
return gbk;
}
} catch (Exception ignored) {
// keep utf8
}
return utf8;
}
private static boolean hasChineseInRobotPayload(JSONObject json) {
if (json == null) {
return false;
}
if (containsCjk(json.getString("senderNick"))) {
return true;
}
if (containsCjk(json.getString("conversationTitle"))) {
return true;
}
JSONObject text = json.getJSONObject("text");
if (text != null && containsCjk(text.getString("content"))) {
return true;
}
return false;
}
private static boolean containsCjk(String s) {
if (s == null || s.isEmpty()) {
return false;
}
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c >= '\u4e00' && c <= '\u9fff') {
return true;
}
}
return false;
}
private static String extractRobotText(JSONObject eventJson) {
if (eventJson == null || !eventJson.containsKey("text")) {
return null;
}
JSONObject text = eventJson.getJSONObject("text");
if (text == null) {
return null;
}
String content = normalizeRobotText(text.getString("content"));
if (content == null) {
return null;
}
return content.replaceFirst("^@[^\\s]+\\s*", "").trim();
}
private static String normalizeRobotText(String content) {
if (content == null) {
return null;
}
content = content.trim();
if (containsCjk(content)) {
return content;
}
String gbk = recoverGbkFromLatin1Misread(content);
if (gbk != null && containsCjk(gbk)) {
return gbk;
}
String utf8 = recoverUtf8FromLatin1Misread(content);
if (utf8 != null && containsCjk(utf8)) {
return utf8;
}
return content;
}
private static boolean textContains(String text, String keyword) {
if (text == null || keyword == null || keyword.isEmpty()) {
return false;
}
String normalized = normalizeRobotText(text);
if (normalized != null && normalized.contains(keyword)) {
return true;
}
return text.contains(keyword);
}
/** GBK 字节被误按 ISO-8859-1 解码时:°²È«¿â´æ → 安全库存 */
private static String recoverGbkFromLatin1Misread(String garbled) {
if (garbled == null || garbled.isEmpty()) {
return garbled;
}
try {
String fixed = new String(garbled.getBytes(StandardCharsets.ISO_8859_1), Charset.forName("GBK"));
return fixed.contains("\uFFFD") ? garbled : fixed;
} catch (Exception e) {
return garbled;
}
}
/** UTF-8 被误按 Latin-1 解码时的乱码修复 */
private static String recoverUtf8FromLatin1Misread(String garbled) {
if (garbled == null || garbled.isEmpty()) {
return garbled;
}
try {
String utf8 = new String(garbled.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
return utf8.contains("\uFFFD") ? garbled : utf8;
} catch (Exception e) {
return garbled;
}
}
private static String firstNonBlank(String... values) {
if (values == null) {
return null;
}
for (String v : values) {
if (v != null && !v.trim().isEmpty()) {
return v.trim();
}
}
return null;
}
/**
* 更新工艺审核结果
*
* @param outTrackId 审核卡片 id
* @param routeStatus 工艺审核1已审核 / 2已拒绝
* @param bomStatus 项目状态8工艺审核完成 / 9工艺审核拒绝
*/
private void updateProcessOrderProStatus(String outTrackId, Long routeStatus, Long bomStatus) {
try {
// 根据 notificationCardId 查询
ProcessOrderPro order = processOrderProMapper.selectOne(new LambdaQueryWrapper<ProcessOrderPro>().eq(ProcessOrderPro::getAuditCardId, outTrackId));
if (order != null) {
ProcessOrderPro update = new ProcessOrderPro();
update.setId(order.getId());
update.setRouteStatus(status);
update.setBomStatus(8L);
update.setRouteStatus(routeStatus);
update.setBomStatus(bomStatus);
update.setUpdateBy("DingDing");
processOrderProMapper.updateById(update);
bizLogger.info("更新 ProcessOrderPro 状态成功: id={}, status={}", order.getId(), status);
bizLogger.info("更新 ProcessOrderPro 状态成功: id={}, routeStatus={}, bomStatus={}",
order.getId(), routeStatus, bomStatus);
// 如果审核通过假设 status 1L 表示通过给配置的人发消息
if (status != null && status == 1L) {
// 审核通过通知可上传金蝶
if (routeStatus != null && routeStatus == 1L) {
sendAuditCompleteNotification(order);
}
} else {
@ -196,12 +376,12 @@ public class CallbackController {
// 根据 action 更新状态
if ("agree".equals(action)) {
cardDataMap.put("status", "agree");
// 更新数据库状态
updateProcessOrderProStatus(outTrackId, 1L); // 1 通过
// routeStatus=1 已审核bomStatus=8 工艺审核完成
updateProcessOrderProStatus(outTrackId, 1L, 8L);
} else if ("reject".equals(action)) {
cardDataMap.put("status", "reject");
// 更新数据库状态
updateProcessOrderProStatus(outTrackId, 2L); // 0 未通过
// routeStatus=2 已拒绝bomStatus=9 工艺审核拒绝
updateProcessOrderProStatus(outTrackId, 2L, 9L);
}
// 调用 DingUtil 更新卡片
@ -219,28 +399,23 @@ public class CallbackController {
if (eventType == null && eventJson.containsKey("msgId")) {
eventType = "robot_message";
}
bizLogger.info("事件类型: {}", eventType);
//只处理技术方案表同意场景
schemeApplicationBpmsEventHandler.handleEventPayload(eventType, eventJson.toJSONString());
// 4. 根据EventType分类处理
if ("check_url".equals(eventType)) {
bizLogger.info("测试回调url的正确性");
} else if ("user_add_org".equals(eventType)) {
bizLogger.info("发生了:" + eventType + "事件");
} else if ("bpms_instance_change".equals(eventType)) {
// 处理审批实例状态变更钉钉OA审批
bizLogger.info("收到审批状态变更事件: {}", eventJson.toJSONString());
} else {
// 其他事件包括机器人消息
bizLogger.info("收到事件: type={}", eventType);
if (eventJson.containsKey("text")) {
String content = eventJson.getJSONObject("text").getString("content");
bizLogger.info("机器人收到文本消息: {}", content);
// 4. 根据EventType分类处理审批/URL校验等不打 INFO避免刷屏
if ("check_url".equals(eventType) || "user_add_org".equals(eventType)
|| "bpms_instance_change".equals(eventType) || "bpms_task_change".equals(eventType)) {
return;
}
// 其他事件包括机器人消息
if (eventJson.containsKey("text")) {
String content = extractRobotText(eventJson);
bizLogger.info("机器人收到文本消息: content={} conversationTitle={} robotCode={}",
content, eventJson.getString("conversationTitle"), eventJson.getString("robotCode"));
boolean isHandled = false;
// 如果内容包含 "你好"则回复 "你好"
if (content != null && content.trim().contains("你好")) {
if (textContains(content, "你好")) {
isHandled = true;
String conversationId = eventJson.getString("conversationId");
// 获取发送者ID如果为空则使用默认ID
@ -255,18 +430,16 @@ public class CallbackController {
String targetAppSecret = dingTalkProperties.getAppSecret();
// 如果是安全库存机器人
if (SAFETY_STOCK_ROBOT_CODE.equals(incomingRobotCode) || (dingTalkProperties.getSafetyStockAppKey() != null && dingTalkProperties.getSafetyStockAppKey().equals(incomingRobotCode))) {
if (dingTalkProperties.getSafetyStockRobotCode().equals(incomingRobotCode) || (dingTalkProperties.getSafetyStockAppKey() != null && dingTalkProperties.getSafetyStockAppKey().equals(incomingRobotCode))) {
// 使用安全库存机器人的配置
targetAppKey = dingTalkProperties.getSafetyStockAppKey();
targetAppSecret = dingTalkProperties.getSafetyStockAppSecret();
// 兜底如果配置为空使用常量
if (targetAppKey == null || targetAppKey.isEmpty()) {
targetAppKey = SAFETY_STOCK_ROBOT_CODE;
targetAppKey = dingTalkProperties.getSafetyStockRobotCode();
}
}
String accessToken = DingUtil.getAccessToken(targetAppKey, targetAppSecret);
// 统一使用企业机器人发送群消息 (不再使用 Webhook)
// 构造回复内容尝试 @ 用户
String replyContent = "你好 @" + senderId;
@ -281,7 +454,7 @@ public class CallbackController {
}
// 如果内容包含 "安全库存"则调用 KingdeeWorkCenterDataController 发送安全库存
if (content != null && content.contains("安全库存")) {
if (textContains(content, "安全库存")) {
isHandled = true;
String sessionWebhook = null; // 不再使用 webhook
String senderId = eventJson.getString("senderStaffId");
@ -290,7 +463,7 @@ public class CallbackController {
// 异步调用以避免阻塞回调
new Thread(() -> {
try {
kingdeeWorkCenterDataController.sendKuCunData(conversationId, sessionWebhook, senderId, SAFETY_STOCK_ROBOT_CODE);
kingdeeWorkCenterDataController.sendKuCunData(conversationId, sessionWebhook, senderId, dingTalkProperties.getSafetyStockRobotCode());
bizLogger.info("已触发发送安全库存");
} catch (Exception e) {
bizLogger.error("触发安全库存发送失败", e);
@ -299,14 +472,14 @@ public class CallbackController {
}
// 延期
if (content != null && content.contains("延期")) {
if (textContains(content, "延期")) {
isHandled = true;
String sessionWebhook = null; // 不再使用 webhook
String senderId = eventJson.getString("senderStaffId");
String conversationId = eventJson.getString("conversationId");
new Thread(() -> {
try {
kingdeeWorkCenterDataController.sendMassageDelayDate(conversationId, sessionWebhook, senderId, SAFETY_STOCK_ROBOT_CODE);
kingdeeWorkCenterDataController.sendMassageDelayDate(conversationId, sessionWebhook, senderId, dingTalkProperties.getSafetyStockRobotCode());
} catch (Exception e) {
bizLogger.error("触发延期发送失败", e);
}
@ -314,14 +487,14 @@ public class CallbackController {
}
// 预警
if (content != null && content.contains("预警")) {
if (textContains(content, "预警")) {
isHandled = true;
String sessionWebhook = null; // 不再使用 webhook
String senderId = eventJson.getString("senderStaffId");
String conversationId = eventJson.getString("conversationId");
new Thread(() -> {
try {
kingdeeWorkCenterDataController.sendMassageForMultipleWorkCenters(conversationId, sessionWebhook, senderId, SAFETY_STOCK_ROBOT_CODE);
kingdeeWorkCenterDataController.sendMassageForMultipleWorkCenters(conversationId, sessionWebhook, senderId, dingTalkProperties.getSafetyStockRobotCode());
} catch (Exception e) {
bizLogger.error("触发预警发送失败", e);
}
@ -329,44 +502,96 @@ public class CallbackController {
}
// 采购 采购申请
if (content != null && (content.contains("采购") || content.contains("采购申请"))) {
if (textContains(content, "采购") || textContains(content, "采购申请")) {
isHandled = true;
String sessionWebhook = null; // 不再使用 webhook
String senderId = eventJson.getString("senderStaffId");
String conversationId = eventJson.getString("conversationId");
new Thread(() -> {
try {
kingdeeWorkCenterDataController.sendPurchaseOrder2(conversationId, sessionWebhook, senderId, SAFETY_STOCK_ROBOT_CODE);
kingdeeWorkCenterDataController.sendPurchaseOrder2(conversationId, sessionWebhook, senderId, dingTalkProperties.getSafetyStockRobotCode());
} catch (Exception e) {
bizLogger.error("触发采购发送失败", e);
}
}).start();
}
// 工序汇报 未入库
if (content != null && (content.contains("工序汇报") || content.contains("未入库"))) {
// 工序汇报未质检
if (textContains(content, "汇报未质检")) {
isHandled = true;
String sessionWebhook = null; // 不再使用 webhook
String senderId = eventJson.getString("senderStaffId");
String conversationId = eventJson.getString("conversationId");
new Thread(() -> {
try {
kingdeeWorkCenterDataController.sendProductionOrder(conversationId, sessionWebhook, senderId, SAFETY_STOCK_ROBOT_CODE);
kingdeeWorkCenterDataController.sendProcessReportNotInspected(
conversationId, sessionWebhook, senderId, dingTalkProperties.getSafetyStockRobotCode());
} catch (Exception e) {
bizLogger.error("触发未入库发送失败", e);
bizLogger.error("触发汇报未质检发送失败", e);
}
}).start();
}
// 质检未入库
if (textContains(content, "质检未入库")) {
isHandled = true;
String sessionWebhook = null; // 不再使用 webhook
String senderId = eventJson.getString("senderStaffId");
String conversationId = eventJson.getString("conversationId");
new Thread(() -> {
try {
kingdeeWorkCenterDataController.sendProcessReportNotStockedIn(
conversationId, sessionWebhook, senderId, dingTalkProperties.getSafetyStockRobotCode());
} catch (Exception e) {
bizLogger.error("触发质检未入库发送失败", e);
}
}).start();
}
// 已转入未转出 / 转入但部分转出
if (textContains(content, "已转入未转出") || textContains(content, "转入但部分转出")
|| textContains(content, "转入未转出") || textContains(content, "部分转出")) {
isHandled = true;
String sessionWebhook = null;
String senderId = eventJson.getString("senderStaffId");
String conversationId = eventJson.getString("conversationId");
new Thread(() -> {
try {
kingdeeWorkCenterDataController.sendMassageTransInPendingOut(
conversationId, sessionWebhook, senderId, dingTalkProperties.getSafetyStockRobotCode());
bizLogger.info("已触发已转入未转出/部分转出数据发送");
} catch (Exception e) {
bizLogger.error("触发已转入未转出数据发送失败", e);
}
}).start();
}
// 开工未转入
if (textContains(content, "开工未转入") || textContains(content, "开工未转")) {
isHandled = true;
String sessionWebhook = null;
String senderId = eventJson.getString("senderStaffId");
String conversationId = eventJson.getString("conversationId");
new Thread(() -> {
try {
kingdeeWorkCenterDataController.sendMassageStartedNotTransIn(
conversationId, sessionWebhook, senderId, dingTalkProperties.getSafetyStockRobotCode());
bizLogger.info("已触发开工未转入数据发送");
} catch (Exception e) {
bizLogger.error("触发开工未转入数据发送失败", e);
}
}).start();
}
// 未及时转移
if (content != null && content.contains("未及时转移")) {
if (textContains(content, "未及时转移")) {
isHandled = true;
String sessionWebhook = null; // 不再使用 webhook
String senderId = eventJson.getString("senderStaffId");
String conversationId = eventJson.getString("conversationId");
new Thread(() -> {
try {
kingdeeWorkCenterDataController.sendProcessTransferForm(conversationId, sessionWebhook, senderId, SAFETY_STOCK_ROBOT_CODE);
kingdeeWorkCenterDataController.sendProcessTransferForm(conversationId, sessionWebhook, senderId, dingTalkProperties.getSafetyStockRobotCode());
} catch (Exception e) {
bizLogger.error("触发未及时转移发送失败", e);
}
@ -380,7 +605,7 @@ public class CallbackController {
String conversationId = eventJson.getString("conversationId");
if (conversationId != null && !conversationId.isEmpty()) {
String helpContent = "您好,我是数据提醒机器人。收到您的消息,但不知道你在讲什么?。\n" + "目前支持以下业务指令,请直接回复关键词:\n" + "1. 安全库存\n" + "2. 延期\n" + "3. 预警\n" + "4. 采购 / 采购申请\n" + "5. 工序汇报 / 未入库\n" + "6. 未及时转移";
String helpContent = "您好,我是数据提醒机器人。收到您的消息,但不知道你在讲什么?。\n" + "目前支持以下业务指令,请直接回复关键词:\n" + "1. 安全库存\n" + "2. 延期\n" + "3. 预警\n" + "4. 采购 / 采购申请\n" + "5. 工序汇报未质检 / 质检未入库\n" + "6. 未及时转移\n" + "7. 已转入未转出 / 转入但部分转出 / 部分转出\n" + "8. 开工未转入 / 开工未转";
// 使用回调中的 sessionWebhook 直接回复 (这是最标准的回调回复方式)
if (sessionWebhook != null && !sessionWebhook.isEmpty()) {
@ -393,7 +618,6 @@ public class CallbackController {
}
}
}
}
}
@Autowired
@ -406,13 +630,13 @@ public class CallbackController {
if (eventJson.containsKey("robotCode")) {
String robotCode = eventJson.getString("robotCode");
// 如果是安全库存机器人
if (SAFETY_STOCK_ROBOT_CODE.equals(robotCode) ||
if (dingTalkProperties.getSafetyStockRobotCode().equals(robotCode) ||
(dingTalkProperties.getSafetyStockAppKey() != null && dingTalkProperties.getSafetyStockAppKey().equals(robotCode))) {
String appKey = dingTalkProperties.getSafetyStockAppKey();
String appSecret = dingTalkProperties.getSafetyStockAppSecret();
// 兜底如果配置为空使用常量
if (appKey == null || appKey.isEmpty()) {
appKey = SAFETY_STOCK_ROBOT_CODE;
appKey = dingTalkProperties.getSafetyStockRobotCode();
}
// 动态获取 Token
bizLogger.info("使用安全库存机器人Token: robotCode={}", robotCode);

View File

@ -1,19 +1,17 @@
package com.ruoyi.web.controller.system;
import cn.dev33.satoken.annotation.SaIgnore;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.service.SysLoginService;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
@RequiredArgsConstructor
@ -23,16 +21,18 @@ public class PlmAuthController {
private final SysLoginService loginService;
/**
* PLM 获取本系统 Sa-Token支持 JSON 体或表单/query 参数避免客户端未带 Content-Type 导致 415
*/
@SaIgnore
@PostMapping(value = "/token", consumes = MediaType.APPLICATION_JSON_VALUE)
public R<Map<String, Object>> token(@RequestBody PlmTokenRequest body) {
if (body == null || StringUtils.isBlank(body.getAppKey()) || StringUtils.isBlank(body.getAppSecret())) {
@PostMapping("/token")
public R<Map<String, Object>> token(@RequestBody(required = false) PlmTokenRequest body,@RequestParam(required = false) String appKey, @RequestParam(required = false) String appSecret) {
String key = body != null && StringUtils.isNotBlank(body.getAppKey()) ? body.getAppKey() : appKey;
String secret = body != null && StringUtils.isNotBlank(body.getAppSecret()) ? body.getAppSecret() : appSecret;
if (StringUtils.isBlank(key) || StringUtils.isBlank(secret)) {
return R.fail("appKey/appSecret不能为空");
}
String token = loginService.plmToken(body.getAppKey(), body.getAppSecret());
Map<String, Object> data = new HashMap<>(2);
data.put(Constants.TOKEN, token);
return R.ok(data);
return R.ok(loginService.plmToken(key, secret));
}
@Data

View File

@ -50,8 +50,8 @@ spring:
# jdbc 所有参数配置参考 https://lionli.blog.csdn.net/article/details/122018562
# rewriteBatchedStatements=true 批处理优化 大幅提升批量插入更新删除性能(对数据库有性能损耗 使用批量操作应考虑性能问题)
# 本机双实例5.7 常用 33068.0 常用其它端口(示例 3307内网库另见下行注释
#url: jdbc:mysql://localhost:3306/item_retrieval-evo?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
#url: jdbc:mysql://localhost:3307/item_retrieval-evo?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
#url: jdbc:mysql://localhost:3306/item_\retrieval-evo?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
#url: jdbc:mysql://192.168.5.121:3306/item_retrieval-evo-test?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
url: jdbc:mysql://192.168.5.121:3306/item_retrieval-evo?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
username: root
password: root
@ -62,7 +62,8 @@ spring:
driverClassName: com.mysql.cj.jdbc.Driver
#url: jdbc:mysql://localhost:3306/item_retrieval_salve?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
#url: jdbc:mysql://localhost:3307/item_retrieval_salve?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
url: jdbc:mysql://192.168.5.121:3306/item_retrieval_salve?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
#url: jdbc:mysql://192.168.5.121:3306/item_retrieval_salve-test?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
url: jdbc:mysql://192.168.5.121:3306/item_retrieval-evo?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
username: root
password: root
sqlserver:
@ -161,3 +162,8 @@ sms:
signName: 测试
# 腾讯专用
sdkAppId:
--- # PLM 方案申请推送(开发环境可覆盖 base-url须含端口与 /api/
plm:
sale-plan:
base-url: http://192.168.5.20:8081/api/

View File

@ -1,6 +1,11 @@
--- # 临时文件存储位置 避免临时文件被系统清理报错
spring.servlet.multipart.location: /ruoyi/server/temp
--- # 图纸 DWG 上传暂存(应用服务器本地,非电子档案 E: 盘)
app:
drawing:
upload-staging-dir: /ruoyi/server/temp/dwg-upload
--- # 监控中心配置
spring.boot.admin.client:
# 增加客户端开关
@ -62,7 +67,7 @@ spring:
type: com.zaxxer.hikari.HikariDataSource
driverClassName: com.mysql.cj.jdbc.Driver
#url: jdbc:mysql://localhost:3306/item_retrieval_salve?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true
url: jdbc:mysql://192.168.5.121:3306/item_retrieval_salve?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true
url: jdbc:mysql://192.168.5.121:3306/item_retrieval-evo?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true
username: root
password: root
sqlserver:

View File

@ -63,6 +63,8 @@ user:
spring:
application:
name: ${ruoyi.name}
config:
import: optional:classpath:plm-pdf-mark.yml
http:
connect-timeout: 10000
read-timeout: 20000
@ -70,6 +72,7 @@ spring:
messages:
# 国际化资源文件路径
basename: i18n/messages
encoding: UTF-8
profiles:
active: '@profiles.active@'
# 文件上传
@ -104,9 +107,9 @@ sa-token:
# token名称 (同时也是cookie名称)
token-name: Authorization
# token有效期 设为一天 (必定过期) 单位: 秒
timeout: 986400
timeout: 86400
# token临时有效期 (指定时间无操作就过期) 单位: 秒
activity-timeout: 99999
activity-timeout: 86400
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
is-concurrent: true
# 在多人登录同一账号时是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
@ -156,6 +159,9 @@ security:
- /system/operationPlanningMain/sync
- /system/operationPlanningMain/cascadeList
- /system/operationPlanningMain/queryFromK3
- /system/route/push/**
- /DataBoard/ProduceKanBan/**
- /system/workCenterData/produceDataKanban
# MyBatisPlus配置
# https://baomidou.com/config/
@ -296,17 +302,102 @@ management:
logfile:
external-file: ./logs/sys-console.log
dingtalk:
#钉钉应用Key
app-key: dingebfrpzqko25vo8w6
#钉钉应用Secret
app-secret: M_hoza71hmEqsbbeXM-7MBg67EINqi9C6mKj4zWKQysXN-68GCYYc5DZoV0hXVvk
#钉钉机器人Code
robot-code: dingebfrpzqko25vo8w6
#安全库存应用Key
safety-stock-app-key: dingwoaeaozawfochwoo
#安全库存应用Secret
safety-stock-app-secret: rGrAQ7cReWeYzIK5j71l8d2qOLgUTyc-qnlacQcl3n0dKG3M8bgbbaSoc9AbKeUy
#安全库存机器人ID
safety-stock-agent-id: 35823003
#安全库存开放会话ID
open-conversation-id: ciddXVuhDM6kJZPJ3o+RcOBqQ==
# 信息发送机器人(项目进度 / 延期全工段汇总多Sheet 私发AppSecret 须填钉钉开放平台该应用密钥
info-send-app-key: ding9bhxctsmq5jsf8pk
info-send-app-secret: OBhuwZzf31kcVqqVwODtu59Aqmql21gc301V06Y8URdjZy_YmBJ47-AZ4nnLZVVm
info-send-robot-code: ding9bhxctsmq5jsf8pk
info-send-user-ids: "665416234832653417,283633411029629036,0754423610937470"
#项目卡片模板ID
project-card-template-id: 2b7bd7ab-0a20-43f2-902c-71198a8dd6a1.schema
#工艺审核互动卡片模板ID
route-card-template-id: 58244f90-b92d-4ab9-b619-8e83cef67d0c.schema
#工艺审核互动卡片回调路由Key
callback-route-key: update_route_status2
notify-user-id: 0754423610937470
route-approval-id: 01201038164023402380
plan-user-id: 313514580637707245,192530665123549546
sync-k3-notify-user-ids: 313514580637707245,351225426738742993,192530665123549546
# 出图完成通知(钉钉 userId/staffId多人逗号分隔以 0 开头的须加引号)
notify-user-id: "173769650335444471,0108392663561185496,283633411029629036"
# 工艺审核互动卡片
route-approval-id: "01201038164023402380"
# 工艺计划推送用户
plan-user-id: "313514580637707245,02256761642526333139,192530665123549546,01201038164023402380"
# 同步K3通知用户
sync-k3-notify-user-ids: "313514580637707245,02256761642526333139,192530665123549546"
#技术方案申请流程编码
scheme-application-process-code: PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB
#技术方案申请流程同意后是否推送PLM
scheme-bpms-on-instance-agree: true
#技术方案申请流程任务同意后是否推送PLM
scheme-bpms-on-task-agree: false
#技术方案申请流程任务同意后推送PLM显示名称
scheme-bpms-plm-push-task-show-names: 总工程师
#技术方案申请流程同意后推送PLM是否显示总工程师意见
scheme-bpms-plm-push-on-chief-opinion-filled: true
# 图纸档案 FTP同机 14.218,下载 21 / 上传 80228022 登录根目录=电子档案/1.标准图纸存放文件夹)
app:
drawing:
# DWG 上传在应用服务器上的暂存目录(须可写);实际上传目标走 FTP 8022
upload-staging-dir: D:/file/dwg-upload
# 工艺计划表落盘目录(手动上传 / PLM 导出共用;下按生产令号分子目录)
plan-excel:
base-dir: D:/file/plan-excel
ftp:
download:
host: 192.168.14.218
port: 21
username: admin
password: hbyt2025
upload:
host: 192.168.14.218
port: 8022
username: admin
password: hbyt2025
# PLM 对接(/plm/token 鉴权、PDF 图纸接收、钉钉方案申请推送等)
plm:
pdf:
base-dir: D:/plm/pdf
separator: '_'
# 左栏标注坐标见独立配置 plm-pdf-mark.yml按 A4/A3/A3横/A2 等图幅匹配)
auth:
# 与 PLM 调用 /plm/token 时传入的 appKey、appSecret 一致
app-key: plm
app-secret: change-me-plm-secret
# 本系统 sys_user.user_name须已存在且可登录用于签发 Sa-Token
username: plm_bot
# 钉钉技术方案申请表 → PLM sales/saleplanapplyform出站
sale-plan:
enabled: true
# 须含 /api/,与 PLM 一致POST {base-url}Login → http://host:8081/api/Login
base-url: http://192.168.5.20:8081/api/
login-path: Login
submit-path: sales/saleplanapplyform
username: 钉钉
password: "123"
token-header: Authorization
token-prefix: "Bearer "
# 副总工程师姓名→工号见代码 DingSchemeDeputyChiefNameMapzpdfzgcs
# 钉钉附件grantProcessInstanceForDownloadFile → multipart/form-data files 直传 PLM
attachments-enabled: true
attachment-field: files
max-attachment-files: 20
# 单附件上限 100MB
max-attachment-bytes-per-file: 104857600
read-timeout-ms: 600000
ding-attachment-download-timeout-ms: 600000
# 库内 DDAttachment 常为空时,推送前再从钉钉 getProcessInstance 拉附件
refresh-attachments-from-ding-on-push: true
log-payload-max-chars: 8000

View File

@ -1,9 +1,8 @@
#??ID-PROD
#ID-PROD
X-KDApi-AcctID = 69d0e0f3a5801e
X-KDApi-UserName = Administrator
#??IDID
#IDID
X-KDApi-AppID = 288012_Rc0C0zCG2lga0/Vs2Y4pzYSL6hQcWOko
# ??
X-KDApi-AppSec = 8a76cd746fa24636b2c65ef9f313c640
X-KDApi-ServerUrl =http://192.168.5.8/K3Cloud/
X-KDApi-LCID = 2052

View File

@ -0,0 +1,172 @@
# PLM PDF 左栏标注坐标(伊特图框:本批数量 / 单台数量 / 发图时间 / 生产令号)
# 修改后重启生效。坐标为相对页宽/页高的比例,原点在 PDF 左下角。
#
# 匹配规则:首页 MediaBox 宽高与 width-pt、height-pt 相差不超过 tolerance-pt
# allow-swap: true 时横竖互换也可匹配。
# 列表顺序优先:加长/横版专用项在前,避免被竖版 allow-swap 误命中。
# 未命中任何项时使用 default-format。
# 注意A4 / A3 / A3_LANDSCAPE / A2 / A2_LANDSCAPE 为已目视调好的坐标,请勿改动 ratio。
#
# 样本文件 ↔ 配置 id 对应关系(调试样本 / _mark_debug
# 1-A0.pdf → A0_LANDSCAPE
# 2-A0-plus.pdf → A0_PLUS_LANDSCAPE
# 3-A1.pdf → A1_LANDSCAPE
# 4-A1-PLUS.pdf → A1_PLUS_0_5_LANDSCAPE
# 5-A2.pdf → A2_LANDSCAPE
# 6-A2-PLUS.pdf → A2_PLUS_0_5_LANDSCAPE
# 7-A3.pdf → A3_LANDSCAPE
# 8-A3-plus.pdf → A3_PLUS_0_5_LANDSCAPE
# 9-A3x2.pdf → A3_PLUS_1_LANDSCAPE
# 10-A4.pdf → A4
plm:
pdf:
mark:
rotation: 90
font-size: 10
default-format: A4
formats:
# --- A0+ 横 5057 × 2384样本 2-A0-plus.pdf ---
- id: A0_PLUS_LANDSCAPE
width-pt: 5057.00
height-pt: 2384.00
tolerance-pt: 4
allow-swap: false
x-ratio: 0.0376
batch-qty-y-ratio: 0.23
unit-qty-y-ratio: 0.18
issue-time-y-ratio: 0.115
order-no-y-ratio: 0.067
# --- A0 横 3370 × 2384样本 1-A0.pdf ---
- id: A0_LANDSCAPE
width-pt: 3370.00
height-pt: 2384.00
tolerance-pt: 4
allow-swap: false
x-ratio: 0.043
batch-qty-y-ratio: 0.23
unit-qty-y-ratio: 0.18
issue-time-y-ratio: 0.13
order-no-y-ratio: 0.06
# --- A1+0.5 横 3571.65 × 1683.78|样本 4-A1-PLUS.pdf ---
- id: A1_PLUS_0_5_LANDSCAPE
width-pt: 3571.65
height-pt: 1683.78
tolerance-pt: 4
allow-swap: false
x-ratio: 0.0433
batch-qty-y-ratio: 0.33
unit-qty-y-ratio: 0.25
issue-time-y-ratio: 0.15
order-no-y-ratio: 0.08
# --- A2+0.5 横 2525.67 × 1190.55|样本 6-A2-PLUS.pdf ---
- id: A2_PLUS_0_5_LANDSCAPE
width-pt: 2525.67
height-pt: 1190.55
tolerance-pt: 4
allow-swap: false
x-ratio: 0.047
batch-qty-y-ratio: 0.45
unit-qty-y-ratio: 0.34
issue-time-y-ratio: 0.22
order-no-y-ratio: 0.11
# --- A3+1 横 2381.10 × 841.89|样本 9-A3x2.pdf ---
- id: A3_PLUS_1_LANDSCAPE
width-pt: 2381.10
height-pt: 841.89
tolerance-pt: 4
allow-swap: false
x-ratio: 0.052
batch-qty-y-ratio: 0.60
unit-qty-y-ratio: 0.47
issue-time-y-ratio: 0.28
order-no-y-ratio: 0.11
# --- A1 横 2381.10 × 1683.78|样本 3-A1.pdf ---
- id: A1_LANDSCAPE
width-pt: 2381.10
height-pt: 1683.78
tolerance-pt: 4
allow-swap: false
x-ratio: 0.0491
batch-qty-y-ratio: 0.33
unit-qty-y-ratio: 0.24
issue-time-y-ratio: 0.15
order-no-y-ratio: 0.07
# --- A3+0.5 横 1785.83 × 841.89|样本 8-A3-plus.pdf ---
- id: A3_PLUS_0_5_LANDSCAPE
width-pt: 1785.83
height-pt: 841.89
tolerance-pt: 4
allow-swap: false
x-ratio: 0.057
batch-qty-y-ratio: 0.60
unit-qty-y-ratio: 0.44
issue-time-y-ratio: 0.28
order-no-y-ratio: 0.12
# --- A2 横 1683.78 × 1190.55|样本 5-A2.pdf须在 A2 竖版之前)---
- id: A2_LANDSCAPE
width-pt: 1683.78
height-pt: 1190.55
tolerance-pt: 6
allow-swap: false
x-ratio: 0.059
batch-qty-y-ratio: 0.437
unit-qty-y-ratio: 0.34
issue-time-y-ratio: 0.21
order-no-y-ratio: 0.11
# --- A3 横 1190.55 × 841.89|样本 7-A3.pdf须在 A3 竖版之前)---
- id: A3_LANDSCAPE
width-pt: 1190.55
height-pt: 841.89
tolerance-pt: 4
allow-swap: false
x-ratio: 0.074
batch-qty-y-ratio: 0.60
unit-qty-y-ratio: 0.47
issue-time-y-ratio: 0.28
order-no-y-ratio: 0.10
# --- A4 竖 595.28 × 841.89|样本 10-A4.pdf ---
- id: A4
width-pt: 595.28
height-pt: 841.89
tolerance-pt: 4
x-ratio: 0.12
batch-qty-y-ratio: 0.60
unit-qty-y-ratio: 0.44
issue-time-y-ratio: 0.27
order-no-y-ratio: 0.11
font-size: 10
# --- A3 竖 841.89 × 1190.55(无对应横版样本时备用)---
- id: A3
width-pt: 841.89
height-pt: 1190.55
tolerance-pt: 4
allow-swap: false
x-ratio: 0.05
batch-qty-y-ratio: 0.62
unit-qty-y-ratio: 0.45
issue-time-y-ratio: 0.27
order-no-y-ratio: 0.1
# --- A2 竖 1190.55 × 1683.78(无对应横版样本时备用)---
- id: A2
width-pt: 1190.55
height-pt: 1683.78
tolerance-pt: 6
allow-swap: false
x-ratio: 0.038
batch-qty-y-ratio: 0.45
unit-qty-y-ratio: 0.32
issue-time-y-ratio: 0.18
order-no-y-ratio: 0.06

View File

@ -1,21 +1,7 @@
package com.ruoyi;
import com.ruoyi.common.utils.FtpUtil;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
@SpringBootTest(classes=RuoYiApplication.class)
@SpringBootTest(classes = RuoYiApplication.class)
public class RuoYiTestApplication {
@Test
public void asfsrfsf() throws FileNotFoundException {
FtpUtil.uploadFile("192.168.5.18", 8022, "admin", "hbyt2025", "", "test11/111111111/222222", "33333.dwg", new FileInputStream(new File("D:\\dwg\\111111111111111.dwg")));
}
}

View File

@ -118,6 +118,18 @@
<artifactId>hutool-extra</artifactId>
</dependency>
<!-- PLM 图纸压缩包rar / 7z / tar.gz 等 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>1.26.1</version>
</dependency>
<dependency>
<groupId>com.github.junrar</groupId>
<artifactId>junrar</artifactId>
<version>7.5.5</version>
</dependency>
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>jakarta.mail</artifactId>

View File

@ -44,6 +44,81 @@ public class DingTalkProperties {
*/
private String safetyStockAgentId;
/**
* 安全库存机器人所在群可选未配置时主动推送仍用 {@link #openConversationId}
*/
private String safetyStockOpenConversationId;
/**
* 信息发送机器人 AppKey名称信息发送用于项目进度私发等
*/
private String infoSendAppKey;
/**
* 信息发送机器人 AppSecret
*/
private String infoSendAppSecret;
/**
* 信息发送机器人 Code通常与 AppKey 相同
*/
private String infoSendRobotCode;
/**
* 信息发送机器人私发接收人 StaffId逗号分隔项目进度延期全工段汇总等
*/
private String infoSendUserIds;
/**
* 定时/主动群推送默认 robotCode {@link #openConversationId} 对应
*/
public String getDefaultAlertPushRobotCode() {
if (robotCode != null && !robotCode.isEmpty()) {
return robotCode.trim();
}
return getSafetyStockRobotCode();
}
public boolean isSafetyStockRobot(String code) {
if (code == null || code.isEmpty()) {
return false;
}
String c = code.trim();
return c.equals(getSafetyStockRobotCode())
|| (safetyStockAppKey != null && c.equals(safetyStockAppKey.trim()));
}
public boolean isInfoSendRobot(String code) {
if (code == null || code.isEmpty()) {
return false;
}
String c = code.trim();
return c.equals(getInfoSendRobotCode())
|| (infoSendAppKey != null && c.equals(infoSendAppKey.trim()));
}
/** 信息发送机器人 robotCode默认 ding9bhxctsmq5jsf8pk */
public String getInfoSendRobotCode() {
if (infoSendRobotCode != null && !infoSendRobotCode.isEmpty()) {
return infoSendRobotCode.trim();
}
if (infoSendAppKey != null && !infoSendAppKey.isEmpty()) {
return infoSendAppKey.trim();
}
return "ding9bhxctsmq5jsf8pk";
}
/**
* 安全库存/数据提醒机器人 robotCode {@link #safetyStockAppKey} 同值供群关键词回调使用
* 注意主动推送到 {@link #openConversationId} 时默认应使用 {@link #robotCode}二者所在群可能不同
*/
public String getSafetyStockRobotCode() {
if (safetyStockAppKey != null && !safetyStockAppKey.isEmpty()) {
return safetyStockAppKey.trim();
}
return "dingwoaeaozawfochwoo";
}
/**
* 群会话 ID
*/
@ -65,7 +140,7 @@ public class DingTalkProperties {
/**
* 接收工艺表格个人用户ID
* 接收工艺表格个人用户ID多个用逗号分隔
*/
private String notifyUserId;
/**
@ -86,7 +161,7 @@ public class DingTalkProperties {
/**
* 技术方案申请表 OA 模板 processCode PROC-xxx为空则不处理 BPMS 审批事件
*/
private String schemeApplicationProcessCode = "";
private String schemeApplicationProcessCode = "PROC-81A79B4D-F0EA-4353-9A91-68FD7E3BCEBB";
/**
* 是否在 bpms_instance_change 整单结束且 result=agree 时拉取审批详情推荐
@ -98,6 +173,17 @@ public class DingTalkProperties {
*/
private boolean schemeBpmsOnTaskAgree = false;
/**
* 任务同意时触发入库与 PLM 的审批节点 showName逗号分隔 operationRecords.showName 匹配默认总工程师
* 审批节点名不在表单 component 列表里须与钉钉审批流节点名称一致
*/
private String schemeBpmsPlmPushTaskShowNames = "总工程师";
/**
* 任务同意且表单技术总工意见已有内容时也可触发 PLM不依赖节点 showName 是否叫总工程师
*/
private boolean schemeBpmsPlmPushOnChiefOpinionFilled = true;
/**
* 拉取详情后日志中输出的控件名称逗号分隔为空则输出全部非空表单字段
*/

View File

@ -0,0 +1,42 @@
package com.ruoyi.common.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 图纸 FTP同一台 192.168.14.218下载 21 端口上传 8022 端口登录根目录为电子档案
*/
@Data
@Component
@ConfigurationProperties(prefix = "app.ftp")
public class DrawingFtpProperties {
/** PDF/DWG 等从出图库下载(端口 21 */
private Endpoint download = Endpoint.forDownload();
/** 图纸上传到电子档案(端口 8022登录根目录已是 1.标准图纸存放文件夹) */
private Endpoint upload = Endpoint.forUpload();
@Data
public static class Endpoint {
private String host = "192.168.14.218";
private int port = 21;
private String username = "admin";
private String password = "hbyt2025";
static Endpoint forDownload() {
Endpoint e = new Endpoint();
e.setHost("192.168.14.218");
e.setPort(21);
return e;
}
static Endpoint forUpload() {
Endpoint e = new Endpoint();
e.setHost("192.168.14.218");
e.setPort(8022);
return e;
}
}
}

View File

@ -0,0 +1,57 @@
package com.ruoyi.common.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
/**
* PLM PDF 左栏标注坐标配置 classpath:plm-pdf-mark.yml
*/
@Data
@Component
@ConfigurationProperties(prefix = "plm.pdf.mark")
public class PlmPdfMarkProperties {
/** 逆时针旋转角,伊特左栏竖排一般为 90 */
private float rotation = 90f;
/** 默认字号(各图幅 font-size 为 0 时使用) */
private int fontSize = 10;
/** 未匹配到任何图幅时使用的 format id */
private String defaultFormat = "A4";
/** 按 PDF 首页宽高pt匹配列表顺序优先先配更具体的尺寸 */
private List<FormatProfile> formats = new ArrayList<>();
@Data
public static class FormatProfile {
/** 图幅标识,日志与 default-format 引用 */
private String id;
/** 参考页宽pt与 PDF MediaBox 一致 */
private float widthPt;
/** 参考页高pt */
private float heightPt;
/** 宽高允许偏差pt */
private float tolerancePt = 4f;
/** 是否允许宽高互换后匹配(横竖版) */
private boolean allowSwap = true;
private float xRatio = 0.048f;
private float batchQtyYRatio = 0.69f;
private float unitQtyYRatio = 0.52f;
private float issueTimeYRatio = 0.35f;
private float orderNoYRatio = 0.18f;
/** 0 表示使用全局 font-size */
private int fontSize = 0;
}
}

View File

@ -0,0 +1,62 @@
package com.ruoyi.common.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 钉钉方案申请 PLM 售前方案申请单sales/saleplanapplyform对接配置
*/
@Data
@Component
@ConfigurationProperties(prefix = "plm.sale-plan")
public class PlmSalePlanProperties {
/** 是否启用推送 */
private boolean enabled = false;
private String baseUrl = "http://192.168.5.20:8081/api/";
/** 登录接口相对路径(请求体 UserName、Password */
private String loginPath = "Login";
/** 提交接口相对路径 */
private String submitPath = "sales/saleplanapplyform";
private String username = "钉钉";
private String password = "123";
/** 提交时 Token 请求头名 */
private String tokenHeader = "Authorization";
/** Token 前缀,如 Bearer */
private String tokenPrefix = "Bearer ";
/** 连接超时(毫秒) */
private int connectTimeoutMs = 15000;
/** 读取超时(毫秒);大附件 multipart 上传 PLM 建议 ≥300000 */
private int readTimeoutMs = 600_000;
/** 是否下载钉钉附件并以 multipart files 直传 PLM */
private boolean attachmentsEnabled = true;
/** PLM multipart 附件字段名 */
private String attachmentField = "files";
private int maxAttachmentFiles = 20;
/** 单附件最大字节数,默认 100MB支持 STEP 等大文件) */
private int maxAttachmentBytesPerFile = 100 * 1024 * 1024;
/** 钉钉 OSS 单文件下载超时(毫秒) */
private int dingAttachmentDownloadTimeoutMs = 600_000;
/** 库内 wf/form 无 fileId 时,推送前是否再调 getProcessInstance 拉附件 */
private boolean refreshAttachmentsFromDingOnPush = true;
/** 推送日志中摘要最大长度 */
private int logPayloadMaxChars = 8000;
}

View File

@ -0,0 +1,32 @@
package com.ruoyi.common.convert;
/**
* Excel 文本空值归一化将空串及常见占位文本视为 null
*/
final class ExcelNullableText {
private ExcelNullableText() {
}
static String normalize(String value) {
if (value == null) {
return null;
}
String str = value.trim();
if (str.isEmpty()) {
return null;
}
String lower = str.toLowerCase();
if ("null".equals(lower)
|| "nul".equals(lower)
|| "undefined".equals(lower)
|| "nan".equals(lower)
|| "n/a".equals(lower)
|| "-".equals(str)
|| "--".equals(str)
|| "/".equals(str)) {
return null;
}
return str;
}
}

View File

@ -0,0 +1,51 @@
package com.ruoyi.common.convert;
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.data.ReadCellData;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
/**
* EasyExcel Double 空值安全转换空单元格/空字符串返回 null不抛异常
*/
public class NullableDoubleConverter implements Converter<Double> {
@Override
public Class<Double> supportJavaTypeKey() {
return Double.class;
}
@Override
public Double convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
if (cellData == null || cellData.getType() == null || cellData.getType() == CellDataTypeEnum.EMPTY) {
return null;
}
switch (cellData.getType()) {
case NUMBER:
return cellData.getNumberValue() == null ? null : cellData.getNumberValue().doubleValue();
case STRING:
String str = ExcelNullableText.normalize(cellData.getStringValue());
if (str == null) {
return null;
}
try {
return Double.valueOf(str);
} catch (NumberFormatException e) {
return null;
}
case BOOLEAN:
return cellData.getBooleanValue() == null ? null : (cellData.getBooleanValue() ? 1D : 0D);
default:
return null;
}
}
@Override
public WriteCellData<?> convertToExcelData(Double value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
return value == null ? new WriteCellData<>("") : new WriteCellData<>(String.valueOf(value));
}
}

View File

@ -0,0 +1,51 @@
package com.ruoyi.common.convert;
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.data.ReadCellData;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
/**
* EasyExcel Long 空值安全转换空单元格/空字符串返回 null不抛异常
*/
public class NullableLongConverter implements Converter<Long> {
@Override
public Class<Long> supportJavaTypeKey() {
return Long.class;
}
@Override
public Long convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
if (cellData == null || cellData.getType() == null || cellData.getType() == CellDataTypeEnum.EMPTY) {
return null;
}
switch (cellData.getType()) {
case NUMBER:
return cellData.getNumberValue() == null ? null : cellData.getNumberValue().longValue();
case STRING:
String str = ExcelNullableText.normalize(cellData.getStringValue());
if (str == null) {
return null;
}
try {
return (long) Double.parseDouble(str);
} catch (NumberFormatException e) {
return null;
}
case BOOLEAN:
return cellData.getBooleanValue() == null ? null : (cellData.getBooleanValue() ? 1L : 0L);
default:
return null;
}
}
@Override
public WriteCellData<?> convertToExcelData(Long value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
return value == null ? new WriteCellData<>("") : new WriteCellData<>(String.valueOf(value));
}
}

View File

@ -105,14 +105,19 @@ public class DingCallbackCrypto {
*/
public String getDecryptMsg(String msgSignature, String timeStamp, String nonce, String encryptMsg)
throws DingTalkEncryptException {
//校验签名
return new String(getDecryptPlainUtf8(msgSignature, timeStamp, nonce, encryptMsg), CHARSET);
}
/**
* 验签后返回解密明文的 UTF-8 字节避免中间 String 与外层 body 解码互相污染
*/
public byte[] getDecryptPlainUtf8(String msgSignature, String timeStamp, String nonce, String encryptMsg)
throws DingTalkEncryptException {
String signature = getSignature(token, timeStamp, nonce, encryptMsg);
if (!signature.equals(msgSignature)) {
throw new DingTalkEncryptException(DingTalkEncryptException.COMPUTE_SIGNATURE_ERROR);
}
// 解密
String result = decrypt(encryptMsg);
return result;
return decryptPlainUtf8Bytes(encryptMsg);
}
/*
@ -152,43 +157,35 @@ public class DingCallbackCrypto {
* @param text 需要解密的密文
* @return 解密得到的明文
*/
private String decrypt(String text) throws DingTalkEncryptException {
private byte[] decryptPlainUtf8Bytes(String text) throws DingTalkEncryptException {
byte[] originalArr;
try {
// 设置解密模式为AES的CBC模式
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
SecretKeySpec keySpec = new SecretKeySpec(aesKey, "AES");
IvParameterSpec iv = new IvParameterSpec(Arrays.copyOfRange(aesKey, 0, 16));
cipher.init(Cipher.DECRYPT_MODE, keySpec, iv);
// 使用BASE64对密文进行解码
byte[] encrypted = Base64.decodeBase64(text);
// 解密
originalArr = cipher.doFinal(encrypted);
} catch (Exception e) {
throw new DingTalkEncryptException(DingTalkEncryptException.COMPUTE_DECRYPT_TEXT_ERROR);
}
String plainText;
byte[] plainTextBytes;
String fromCorpid;
try {
// 去除补位字符
byte[] bytes = PKCS7Padding.removePaddingBytes(originalArr);
// 分离16位随机字符串,网络字节序和corpId
byte[] networkOrder = Arrays.copyOfRange(bytes, 16, 20);
int plainTextLegth = Utils.bytes2int(networkOrder);
plainText = new String(Arrays.copyOfRange(bytes, 20, 20 + plainTextLegth), CHARSET);
plainTextBytes = Arrays.copyOfRange(bytes, 20, 20 + plainTextLegth);
fromCorpid = new String(Arrays.copyOfRange(bytes, 20 + plainTextLegth, bytes.length), CHARSET);
} catch (Exception e) {
throw new DingTalkEncryptException(DingTalkEncryptException.COMPUTE_DECRYPT_TEXT_LENGTH_ERROR);
}
// corpid不相同的情况
if (!fromCorpid.equals(corpId)) {
System.out.println("DingCallbackCrypto 校验失败: 传入的 corpId=" + corpId + ", 解密得到的 fromCorpid=" + fromCorpid);
// 暂时注释掉抛出异常以便调试或者您根据控制台输出修正配置
// throw new DingTalkEncryptException(DingTalkEncryptException.COMPUTE_DECRYPT_TEXT_CORPID_ERROR);
}
return plainText;
return plainTextBytes;
}
/**

View File

@ -14,6 +14,9 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@ -120,7 +123,21 @@ public class RobotGroupService {
* @param text Markdown内容
* @return success
*/
/**
* 支持逗号分隔多个 userId plan-user-idsync-k3-notify-user-ids 配置一致
*/
public String sendMarkdownToUser(String userId, String title, String text) {
List<String> userIds = parseUserIds(userId);
if (userIds.isEmpty()) {
throw new DingException("接收人 userId 为空");
}
for (String uid : userIds) {
sendMarkdownToSingleUser(uid, title, text);
}
return "success";
}
private void sendMarkdownToSingleUser(String userId, String title, String text) {
try {
Config config = new Config();
config.protocol = "https";
@ -142,9 +159,8 @@ public class RobotGroupService {
client.batchSendOTOWithOptions(request, headers, new RuntimeOptions());
log.info("机器人个人Markdown消息发送成功, userId: {}, title: {}", userId, title);
return "success";
} catch (Exception e) {
log.error("机器人个人Markdown消息发送失败", e);
log.error("机器人个人Markdown消息发送失败, userId={}", userId, e);
throw new DingException("机器人个人Markdown消息发送失败", e);
}
}
@ -158,6 +174,17 @@ public class RobotGroupService {
* @return success
*/
public String sendFileToUser(String userId, String mediaId, String fileName) {
List<String> userIds = parseUserIds(userId);
if (userIds.isEmpty()) {
throw new DingException("接收人 userId 为空");
}
for (String uid : userIds) {
sendFileToSingleUser(uid, mediaId, fileName);
}
return "success";
}
private void sendFileToSingleUser(String userId, String mediaId, String fileName) {
try {
Config config = new Config();
config.protocol = "https";
@ -178,13 +205,26 @@ public class RobotGroupService {
client.batchSendOTOWithOptions(request, headers, new com.aliyun.teautil.models.RuntimeOptions());
log.info("机器人个人文件发送成功, userId: {}, fileName: {}", userId, fileName);
return "success";
} catch (Exception e) {
log.error("机器人个人文件发送失败", e);
log.error("机器人个人文件发送失败, userId={}", userId, e);
throw new DingException("机器人个人文件发送失败", e);
}
}
/** 解析逗号分隔的钉钉 userId / staffId 列表。 */
static List<String> parseUserIds(String userIdsCsv) {
if (!StringUtils.hasText(userIdsCsv)) {
return Collections.emptyList();
}
List<String> result = new ArrayList<>();
for (String part : userIdsCsv.split(",")) {
if (StringUtils.hasText(part)) {
result.add(part.trim());
}
}
return result;
}
/**
* 发送文本消息到群
*

View File

@ -5,6 +5,8 @@ import com.aliyun.dingtalkim_1_0.models.SendInteractiveCardHeaders;
import com.aliyun.dingtalkim_1_0.models.SendInteractiveCardRequest;
import com.aliyun.dingtalkoauth2_1_0.models.GetAccessTokenRequest;
import com.aliyun.dingtalkoauth2_1_0.models.GetAccessTokenResponse;
import com.aliyun.dingtalkrobot_1_0.models.BatchSendOTOHeaders;
import com.aliyun.dingtalkrobot_1_0.models.BatchSendOTORequest;
import com.aliyun.dingtalkrobot_1_0.models.OrgGroupSendHeaders;
import com.aliyun.dingtalkrobot_1_0.models.OrgGroupSendRequest;
import com.aliyun.dingtalkrobot_1_0.models.OrgGroupSendResponse;
@ -24,6 +26,7 @@ import org.apache.commons.codec.binary.Base64;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
@ -934,6 +937,74 @@ public class DingUtil {
}
}
/**
* 机器人单聊批量发送 MarkdownBatchSendOTO最多 20 /
*/
public static void batchSendOtoMarkdown(String accessToken, String robotCode, List<String> userIds,
String title, String text) {
if (userIds == null || userIds.isEmpty()) {
return;
}
try {
Map<String, Object> msgParamMap = new HashMap<>();
msgParamMap.put("title", title == null ? "" : title);
msgParamMap.put("text", text == null ? "" : text);
String msgParam = OBJECT_MAPPER.writeValueAsString(msgParamMap);
batchSendOto(accessToken, robotCode, userIds, "sampleMarkdown", msgParam);
} catch (JsonProcessingException e) {
throw new RuntimeException("构建单聊 Markdown 参数失败", e);
}
}
/**
* 机器人单聊批量发送文件BatchSendOTO最多 20 /
*/
public static void batchSendOtoFile(String accessToken, String robotCode, List<String> userIds,
String mediaId, String fileName, String fileType) {
if (userIds == null || userIds.isEmpty()) {
return;
}
try {
Map<String, Object> msgParamMap = new HashMap<>();
msgParamMap.put("mediaId", mediaId);
msgParamMap.put("fileName", fileName);
if (fileType != null && !fileType.isEmpty()) {
msgParamMap.put("fileType", fileType);
}
String msgParam = OBJECT_MAPPER.writeValueAsString(msgParamMap);
batchSendOto(accessToken, robotCode, userIds, "sampleFile", msgParam);
} catch (JsonProcessingException e) {
throw new RuntimeException("构建单聊文件参数失败", e);
}
}
private static void batchSendOto(String accessToken, String robotCode, List<String> userIds,
String msgKey, String msgParam) {
try {
com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config();
config.protocol = "https";
config.regionId = "central";
com.aliyun.dingtalkrobot_1_0.Client client = new com.aliyun.dingtalkrobot_1_0.Client(config);
BatchSendOTOHeaders headers = new BatchSendOTOHeaders();
headers.xAcsDingtalkAccessToken = accessToken;
for (int i = 0; i < userIds.size(); i += 20) {
List<String> batch = userIds.subList(i, Math.min(i + 20, userIds.size()));
BatchSendOTORequest request = new BatchSendOTORequest()
.setRobotCode(robotCode)
.setUserIds(new ArrayList<>(batch))
.setMsgKey(msgKey)
.setMsgParam(msgParam);
client.batchSendOTOWithOptions(request, headers, new com.aliyun.teautil.models.RuntimeOptions());
}
} catch (com.aliyun.tea.TeaException err) {
throw new RuntimeException(err);
} catch (Exception e) {
throw new RuntimeException("机器人单聊发送失败", e);
}
}
/**
* 使用 Token 初始化账号 ClientOA 审批 / workflow
*/

View File

@ -0,0 +1,19 @@
package com.ruoyi.common.dingding.workflow;
import lombok.Builder;
import lombok.Data;
/**
* 钉钉审批表单附件来自 DDAttachment 控件 value 中的 fileId
*/
@Data
@Builder
public class DingSchemeAttachmentRef {
private String componentId;
private String fileId;
private Long spaceId;
private String fileName;
private String fileType;
private Long fileSize;
}

View File

@ -0,0 +1,177 @@
package com.ruoyi.common.dingding.workflow;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.aliyun.dingtalkworkflow_1_0.models.AddApproveDentryAuthHeaders;
import com.aliyun.dingtalkworkflow_1_0.models.AddApproveDentryAuthRequest;
import com.aliyun.dingtalkworkflow_1_0.models.AddApproveDentryAuthRequest.AddApproveDentryAuthRequestFileInfos;
import com.aliyun.dingtalkworkflow_1_0.models.GrantProcessInstanceForDownloadFileHeaders;
import com.aliyun.dingtalkworkflow_1_0.models.GrantProcessInstanceForDownloadFileRequest;
import com.aliyun.dingtalkworkflow_1_0.models.GrantProcessInstanceForDownloadFileResponse;
import com.aliyun.dingtalkworkflow_1_0.models.GrantProcessInstanceForDownloadFileResponseBody;
import com.aliyun.dingtalkworkflow_1_0.models.GrantProcessInstanceForDownloadFileResponseBody.GrantProcessInstanceForDownloadFileResponseBodyResult;
import com.aliyun.teautil.models.RuntimeOptions;
import com.ruoyi.common.config.PlmSalePlanProperties;
import com.ruoyi.common.dingding.token.AccessTokenManager;
import com.ruoyi.common.dingding.util.DingUtil;
import com.ruoyi.common.exception.ServiceException;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
/**
* 钉钉审批附件 {@code addApproveDentryAuth} 授权 {@code grantProcessInstanceForDownloadFile} 取链
* 最后用原始 URL GET不可 RestTemplate 重编码否则 OSS SignatureDoesNotMatch
*/
@Component
@RequiredArgsConstructor
public class DingWorkflowAttachmentClient {
private static final Logger log = LoggerFactory.getLogger(DingWorkflowAttachmentClient.class);
private static final int AUTH_BATCH_SIZE = 10;
private final AccessTokenManager accessTokenManager;
private final PlmSalePlanProperties plmSalePlanProperties;
public List<DownloadedAttachment> downloadAll(String processInstanceId, String userId,
List<DingSchemeAttachmentRef> refs) {
if (StrUtil.isBlank(processInstanceId) || refs == null || refs.isEmpty()) {
return new ArrayList<>();
}
if (StrUtil.isBlank(userId)) {
throw new ServiceException("下载钉钉附件缺少 userId请使用审批发起人 originatorUserId");
}
List<DownloadedAttachment> out = new ArrayList<>(refs.size());
try {
com.aliyun.dingtalkworkflow_1_0.Client client = DingUtil.createWorkflowClient();
String token = accessTokenManager.getAccessToken();
RuntimeOptions runtime = new RuntimeOptions();
for (int i = 0; i < refs.size(); i += AUTH_BATCH_SIZE) {
List<DingSchemeAttachmentRef> batch = refs.subList(i, Math.min(i + AUTH_BATCH_SIZE, refs.size()));
addApproveDentryAuth(client, token, userId, batch, runtime);
}
GrantProcessInstanceForDownloadFileHeaders grantHeaders = new GrantProcessInstanceForDownloadFileHeaders();
grantHeaders.xAcsDingtalkAccessToken = token;
for (DingSchemeAttachmentRef ref : refs) {
if (StrUtil.isBlank(ref.getFileId())) {
continue;
}
GrantProcessInstanceForDownloadFileRequest request = new GrantProcessInstanceForDownloadFileRequest()
.setProcessInstanceId(processInstanceId)
.setFileId(ref.getFileId());
GrantProcessInstanceForDownloadFileResponse response =
client.grantProcessInstanceForDownloadFileWithOptions(request, grantHeaders, runtime);
String downloadUri = extractDownloadUri(response, ref.getFileId());
byte[] bytes = fetchPresignedUrlBytes(downloadUri, plmSalePlanProperties.getDingAttachmentDownloadTimeoutMs());
out.add(new DownloadedAttachment(ref, bytes));
log.info("钉钉附件已下载 processInstanceId={} fileId={} fileName={} bytes={}",
processInstanceId, ref.getFileId(), ref.getFileName(), bytes.length);
}
} catch (ServiceException ex) {
throw ex;
} catch (Exception ex) {
throw new ServiceException("钉钉附件下载异常: " + ex.getMessage());
}
return out;
}
private static void addApproveDentryAuth(com.aliyun.dingtalkworkflow_1_0.Client client, String token, String userId,
List<DingSchemeAttachmentRef> batch, RuntimeOptions runtime) throws Exception {
List<AddApproveDentryAuthRequestFileInfos> fileInfos = new ArrayList<>();
for (DingSchemeAttachmentRef ref : batch) {
if (ref.getSpaceId() == null || StrUtil.isBlank(ref.getFileId())) {
continue;
}
AddApproveDentryAuthRequestFileInfos info = new AddApproveDentryAuthRequestFileInfos();
info.setFileId(ref.getFileId());
info.setSpaceId(ref.getSpaceId());
fileInfos.add(info);
}
if (fileInfos.isEmpty()) {
return;
}
AddApproveDentryAuthRequest authRequest = new AddApproveDentryAuthRequest();
authRequest.setUserId(userId);
authRequest.setFileInfos(fileInfos);
AddApproveDentryAuthHeaders authHeaders = new AddApproveDentryAuthHeaders();
authHeaders.xAcsDingtalkAccessToken = token;
client.addApproveDentryAuthWithOptions(authRequest, authHeaders, runtime);
}
private static String extractDownloadUri(GrantProcessInstanceForDownloadFileResponse response, String fileId) {
GrantProcessInstanceForDownloadFileResponseBody body = response != null ? response.getBody() : null;
if (body != null && Boolean.FALSE.equals(body.getSuccess())) {
throw new ServiceException("钉钉附件授权失败 fileId=" + fileId);
}
GrantProcessInstanceForDownloadFileResponseBodyResult result = body != null ? body.getResult() : null;
if (result == null || StrUtil.isBlank(result.getDownloadUri())) {
throw new ServiceException("钉钉未返回附件下载地址 fileId=" + fileId);
}
return result.getDownloadUri().trim();
}
/**
* OSS 预签名 URL必须原样 GET保留 Expires/OSSAccessKeyId/Signature query且不加额外请求头
*/
private static byte[] fetchPresignedUrlBytes(String downloadUri, int timeoutMs) {
int timeout = timeoutMs > 0 ? timeoutMs : 600_000;
HttpResponse resp = HttpRequest.get(downloadUri)
.timeout(timeout)
.setFollowRedirects(true)
.disableCache()
.execute();
if (!resp.isOk()) {
String err = StrUtil.sub(resp.body(), 0, 800);
log.warn("OSS 附件下载失败 status={} urlHost={} err={}",
resp.getStatus(), hostOf(downloadUri), err);
throw new ServiceException("附件下载 HTTP " + resp.getStatus() + ": " + err);
}
byte[] body = resp.bodyBytes();
if (body == null || body.length == 0) {
throw new ServiceException("附件下载内容为空");
}
return body;
}
private static String hostOf(String url) {
try {
int start = url.indexOf("://");
if (start < 0) {
return url;
}
int hostStart = start + 3;
int hostEnd = url.indexOf('/', hostStart);
return hostEnd < 0 ? url.substring(hostStart) : url.substring(hostStart, hostEnd);
} catch (Exception ex) {
return "?";
}
}
public static final class DownloadedAttachment {
private final DingSchemeAttachmentRef ref;
private final byte[] content;
public DownloadedAttachment(DingSchemeAttachmentRef ref, byte[] content) {
this.ref = ref;
this.content = content;
}
public DingSchemeAttachmentRef getRef() {
return ref;
}
public byte[] getContent() {
return content;
}
}
}

View File

@ -37,27 +37,35 @@ import java.util.stream.Collectors;
* 建议在钉钉侧将订阅范围限定到对应 {@link DingTalkProperties#getSchemeApplicationProcessCode()}
* <p>
* {@code bpms_instance_change}{@code type=finish} 后即拉取详情是否同意以 {@code getProcessInstance().result} 为准避免事件体里 result 与详情不一致导致误跳过
* {@code bpms_task_change} {@code scheme-bpms-on-task-agree=true} 且事件 {@code result=agree}单节点若为 audit 等不会处理请改用实例结束事件
* {@code bpms_task_change}拉详情后若整单已 {@code COMPLETED} {@code result=agree} 则入库并推 PLM末节点同意时常仅有 task 事件 instance 事件
* 或节点名/showName 匹配 {@link DingTalkProperties#getSchemeBpmsPlmPushTaskShowNames()}
* 技术总工意见已填 {@code scheme-bpms-on-task-agree=true}
*/
@Component
public class SchemeApplicationBpmsEventHandler {
private static final Logger log = LoggerFactory.getLogger(SchemeApplicationBpmsEventHandler.class);
/** 表单「技术总工意见」控件 id审批节点名不在 formComponentValues 里) */
private static final String CHIEF_ENGINEER_OPINION_COMPONENT_ID = "TextareaField_GO981AG879K0";
/** 同一 processInstanceId 同时只跑一个拉详情+入库,避免 Stream/HTTP 重复回调并发 insert */
private static final ConcurrentHashMap<String, Boolean> PROCESSING = new ConcurrentHashMap<>();
private final DingTalkProperties properties;
private final AccessTokenManager accessTokenManager;
private final List<SchemeApplicationApprovedSink> schemeApplicationApprovedSinks;
private final List<SchemeApplicationPlmPushSink> schemeApplicationPlmPushSinks;
public SchemeApplicationBpmsEventHandler(
DingTalkProperties properties,
AccessTokenManager accessTokenManager,
@Autowired(required = false) List<SchemeApplicationApprovedSink> schemeApplicationApprovedSinks) {
@Autowired(required = false) List<SchemeApplicationApprovedSink> schemeApplicationApprovedSinks,
@Autowired(required = false) List<SchemeApplicationPlmPushSink> schemeApplicationPlmPushSinks) {
this.properties = properties;
this.accessTokenManager = accessTokenManager;
this.schemeApplicationApprovedSinks = schemeApplicationApprovedSinks != null ? schemeApplicationApprovedSinks : Collections.emptyList();
this.schemeApplicationPlmPushSinks = schemeApplicationPlmPushSinks != null ? schemeApplicationPlmPushSinks : Collections.emptyList();
}
/**
@ -86,13 +94,15 @@ public class SchemeApplicationBpmsEventHandler {
}
String eventResult = event.getStr("result");
// 整单事件里 result 可能与详情不一致甚至为空只要收到实例结束即拉详情最终以 getProcessInstance.result 为准
boolean instanceFinish = eventResult.equals("agree");
// 单任务仍以事件 result=agree 为准节点上常为 agree若为 audit 等需开 scheme-bpms-on-task-agree 并扩展白名单
// boolean taskAgree = properties.isSchemeBpmsOnTaskAgree() && "bpms_task_change".equals(eventType) && "agree".equalsIgnoreCase(eventResult);
if (!instanceFinish ) {
log.info("跳过方案申请表 BPMSeventType={}, type=finish, eventResult={}, onInstance={}, onTask={}(整单请订阅 bpms_instance_change仅任务且非 agree 时不会处理)",
eventType, eventResult, properties.isSchemeBpmsOnInstanceAgree(), properties.isSchemeBpmsOnTaskAgree());
boolean isInstanceChange = "bpms_instance_change".equals(eventType);
boolean isTaskChange = "bpms_task_change".equals(eventType);
// 整单结束事件收到 type=finish 即拉详情是否同意以 getProcessInstance.result 为准
boolean instanceFinish = isInstanceChange && properties.isSchemeBpmsOnInstanceAgree();
// 单任务同意先放行拉详情是否在 pullAndDispatch 入库由整单状态/节点名/技术总工意见等二次判断
boolean taskFinishAgree = isTaskChange && "agree".equalsIgnoreCase(eventResult);
if (!instanceFinish && !taskFinishAgree) {
log.info("跳过方案申请表 BPMSeventType={}, type=finish, eventResult={}(仅处理 instance_finish 或 task_finish+agree",
eventType, eventResult);
return;
}
@ -108,16 +118,23 @@ public class SchemeApplicationBpmsEventHandler {
}
final String finalEventType = eventType;
final String finalEventResult = eventResult;
final String taskStaffId = event.getStr("staffId");
final String activityName = event.getStr("activityName");
new Thread(() -> {
try {
pullAndDispatch(processInstanceId, finalEventType, finalEventResult);
pullAndDispatch(processInstanceId, finalEventType, finalEventResult, taskStaffId, activityName);
} finally {
PROCESSING.remove(processInstanceId);
}
}, "scheme-bpms-" + processInstanceId).start();
}
private void pullAndDispatch(String processInstanceId, String triggerEventType, String eventResult) {
private void pullAndDispatch(
String processInstanceId,
String triggerEventType,
String eventResult,
String taskStaffId,
String activityName) {
try {
com.aliyun.dingtalkworkflow_1_0.Client client = DingUtil.createWorkflowClient();
GetProcessInstanceHeaders headers = new GetProcessInstanceHeaders();
@ -132,12 +149,21 @@ public class SchemeApplicationBpmsEventHandler {
return;
}
if (properties.isSchemeBpmsOnInstanceAgree() && "bpms_instance_change".equals(triggerEventType)) {
if ("bpms_instance_change".equals(triggerEventType)) {
if (!"agree".equalsIgnoreCase(inst.getResult())) {
log.info("整单审批未同意,跳过入库 processInstanceId={} eventResult={} instanceResult={} status={}",
processInstanceId, eventResult, inst.getResult(), inst.getStatus());
return;
}
} else if ("bpms_task_change".equals(triggerEventType)) {
if (!shouldProcessTaskAgree(inst, taskStaffId, activityName)) {
log.info("任务同意但未到 PLM 触发条件,跳过 processInstanceId={} activityName={} staffId={} "
+ "instanceResult={} status={} onTaskAgree={} showNames={} chiefOpinionFilled={}",
processInstanceId, activityName, taskStaffId, inst.getResult(), inst.getStatus(),
properties.isSchemeBpmsOnTaskAgree(), properties.getSchemeBpmsPlmPushTaskShowNames(),
properties.isSchemeBpmsPlmPushOnChiefOpinionFilled());
return;
}
}
Map<String, String> formMap = toFormFieldMap(inst.getFormComponentValues());
@ -153,6 +179,7 @@ public class SchemeApplicationBpmsEventHandler {
SchemeApplicationApprovedPayload payload = buildPayload(inst, processInstanceId, triggerEventType);
notifySinks(payload);
notifyPlmPush(processInstanceId);
} catch (Exception e) {
log.error("拉取方案申请表审批实例失败 processInstanceId={}", processInstanceId, e);
}
@ -191,6 +218,87 @@ public class SchemeApplicationBpmsEventHandler {
}
}
/**
* 单任务同意时是否入库并推 PLM末节点同意且整单已结束或命中配置节点名或技术总工意见已填等
*/
private boolean shouldProcessTaskAgree(
GetProcessInstanceResponseBodyResult inst,
String taskStaffId,
String activityName) {
if (properties.isSchemeBpmsOnTaskAgree()) {
return true;
}
if (isInstanceCompletedAgree(inst)) {
return true;
}
if (properties.isSchemeBpmsPlmPushOnChiefOpinionFilled()
&& hasChiefEngineerOpinion(inst.getFormComponentValues())) {
return true;
}
return matchesConfiguredTaskShowNames(activityName);
}
/** 整单已结束且结果为同意(末节点 task_finish 回调时 instance 事件可能未订阅或晚到)。 */
private static boolean isInstanceCompletedAgree(GetProcessInstanceResponseBodyResult inst) {
if (inst == null || !"agree".equalsIgnoreCase(inst.getResult())) {
return false;
}
String status = StrUtil.nullToEmpty(inst.getStatus()).trim().toUpperCase();
return "COMPLETED".equals(status);
}
/** 回调 {@code activityName} 与配置节点名匹配SDK operationRecords 无 showName 字段)。 */
private boolean matchesConfiguredTaskShowNames(String activityName) {
Set<String> wanted = parseCommaSeparatedNames(properties.getSchemeBpmsPlmPushTaskShowNames());
if (wanted.isEmpty() || StrUtil.isBlank(activityName)) {
return false;
}
return wanted.contains(activityName.trim());
}
private static boolean hasChiefEngineerOpinion(
List<GetProcessInstanceResponseBodyResultFormComponentValues> formValues) {
if (CollUtil.isEmpty(formValues)) {
return false;
}
for (GetProcessInstanceResponseBodyResultFormComponentValues c : formValues) {
if (c == null) {
continue;
}
if (CHIEF_ENGINEER_OPINION_COMPONENT_ID.equals(c.getId()) && StrUtil.isNotBlank(c.getValue())) {
return true;
}
}
return false;
}
private static Set<String> parseCommaSeparatedNames(String cfg) {
if (StrUtil.isBlank(cfg)) {
return Collections.emptySet();
}
Set<String> names = new LinkedHashSet<>();
for (String part : cfg.split(",")) {
if (StrUtil.isNotBlank(part)) {
names.add(part.trim());
}
}
return names;
}
/** 入库完成后推送 PLM须在 {@link #notifySinks} 之后调用)。 */
private void notifyPlmPush(String processInstanceId) {
if (schemeApplicationPlmPushSinks.isEmpty()) {
return;
}
for (SchemeApplicationPlmPushSink sink : schemeApplicationPlmPushSinks) {
try {
sink.pushToPlm(processInstanceId);
} catch (Exception ex) {
log.error("SchemeApplicationPlmPushSink 执行失败: {}", sink.getClass().getName(), ex);
}
}
}
private static Date parseDingDateTime(String iso) {
if (StrUtil.isBlank(iso)) {
return null;

View File

@ -0,0 +1,12 @@
package com.ruoyi.common.dingding.workflow;
/**
* 技术方案申请表审批归档成功后推送 PLM {@link SchemeApplicationBpmsEventHandler} 触发
*/
public interface SchemeApplicationPlmPushSink {
/**
* @param processInstanceId 钉钉审批实例 ID须已写入 ding_scheme_application
*/
void pushToPlm(String processInstanceId);
}

View File

@ -1,5 +1,6 @@
package com.ruoyi.common.poi;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.CellCopyPolicy;
import org.apache.poi.ss.usermodel.Workbook;
@ -50,6 +51,60 @@ public class ExcelTemplateProc {
saveExportFile(workbook, exportFilePathAndName);
}
/**
* 同一模板多 Sheet 导出 sheetConfigs 顺序复制模板页并分别填充Sheet 名取自 sheetName通常为工段名
*/
public static void doExportExcelByTemplateProcMultiSheet(String templateFileName,
String exportFilePathAndName,
List<SheetExportConfig> sheetConfigs) throws IOException {
if (sheetConfigs == null || sheetConfigs.isEmpty()) {
throw new IllegalArgumentException("sheetConfigs 不能为空");
}
InputStream inputStream = openTemplateInputStream(templateFileName);
XSSFWorkbook workbook;
try {
workbook = new XSSFWorkbook(inputStream);
} finally {
inputStream.close();
}
while (workbook.getNumberOfSheets() > 1) {
workbook.removeSheetAt(workbook.getNumberOfSheets() - 1);
}
for (int i = 1; i < sheetConfigs.size(); i++) {
workbook.cloneSheet(0);
}
for (int i = 0; i < sheetConfigs.size(); i++) {
SheetExportConfig config = sheetConfigs.get(i);
XSSFSheet sheet = workbook.getSheetAt(i);
workbook.setSheetName(i, sanitizeSheetName(config.getSheetName()));
dealSheetDataByTemplate(sheet, config.getStaticDataMap(), config.getDynamicDataMappingList());
}
saveExportFile(workbook, exportFilePathAndName);
}
private static InputStream openTemplateInputStream(String templateFileName) throws IOException {
if (templateFileName.startsWith("/") || templateFileName.contains(":")) {
return Files.newInputStream(new File(templateFileName).toPath());
}
ClassPathResource resource = new ClassPathResource(templateFileName);
return resource.getInputStream();
}
private static String sanitizeSheetName(String name) {
if (name == null || name.isEmpty()) {
return "Sheet";
}
String sanitized = name.replaceAll("[\\\\/*?:\\[\\]]", "");
return sanitized.length() > 31 ? sanitized.substring(0, 31) : sanitized;
}
@Data
public static class SheetExportConfig {
private String sheetName;
private Map<String, Object> staticDataMap;
private List<DynamicDataMapping> dynamicDataMappingList;
}
/**
* @param workbook
* @param excelFilePath
@ -139,18 +194,6 @@ public class ExcelTemplateProc {
continue; // 跳过空行
}
// 添加调试信息检查每一行是否有静态数据占位符
if (row.getFirstCellNum() != -1 && row.getLastCellNum() != -1) {
for (int j = row.getFirstCellNum(); j < row.getLastCellNum(); j++) {
XSSFCell cell = row.getCell(j);
if (cell != null) {
String cellValue = cell.getStringCellValue();
if (cellValue != null && cellValue.contains("{{") && !cellValue.contains(".")) {
System.out.println("发现静态数据占位符: 行" + i + ", 列" + j + ", 内容: " + cellValue);
}
}
}
}
// 先处理静态数据再处理动态数据
dealTemplateDataRow(row, null, staticDataMap);
@ -233,11 +276,6 @@ public class ExcelTemplateProc {
String replacementValue = entry.getValue() == null ? "" : entry.getValue().toString();
cellValue = cellValue.replace(cellTemplateStr, replacementValue);
flag = true;
// 添加静态数据替换的调试信息
if (dataPrefix == null || dataPrefix.isEmpty()) {
System.out.println("静态数据替换: " + cellTemplateStr + " -> " + replacementValue);
System.out.println("替换后内容: " + cellValue);
}
}
}
if (flag) {

View File

@ -1,104 +0,0 @@
package com.ruoyi.common.utils;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class FTPDownload {
private FTPClient ftpClient;
public FTPDownload() {
ftpClient = new FTPClient();
}
/**
* 连接到FTP服务器
*/
public void connect(String ftpHost, String ftpUserName, String ftpPassword, int ftpPort) {
try {
ftpClient.connect(ftpHost, ftpPort);
ftpClient.login(ftpUserName, ftpPassword);
ftpClient.enterLocalPassiveMode(); // 设置被动模式
System.out.println("FTP连接成功!");
} catch (IOException e) {
System.out.println("FTP连接失败!");
e.printStackTrace();
}
}
/**
* 列出远程目录中的文件
* @param remoteDir 远程目录路径
* @return FTPFile列表
* @throws IOException
*/
public FTPFile[] listFiles(String remoteDir) throws IOException {
return ftpClient.listFiles(remoteDir);
}
/**
* 下载文件
* @param remoteFile 远程文件路径
* @param localFile 本地保存路径
* @throws IOException
*/
public void downloadFile(String remoteFile, String localFile) throws IOException {
try (OutputStream os = new FileOutputStream(localFile)) {
ftpClient.retrieveFile(remoteFile, os);
System.out.println("文件下载成功: " + remoteFile);
} catch (IOException e) {
System.out.println("文件下载失败: " + remoteFile);
e.printStackTrace();
}
}
/**
* 下载整个目录中的所有文件
* @param remoteDir 远程目录路径
* @param localDir 本地保存目录
*/
public void downloadFilesInDirectory(String remoteDir, String localDir) {
try {
FTPFile[] files = listFiles(remoteDir);
for (FTPFile file : files) {
String remoteFilePath = remoteDir + "/" + file.getName();
String localFilePath = localDir + "/" + file.getName();
if (file.isFile()) {
downloadFile(remoteFilePath, localFilePath);
} else if (file.isDirectory()) {
// 递归下载文件夹
File localFolder = new File(localFilePath);
if (!localFolder.exists()) {
localFolder.mkdirs(); // 创建本地文件夹
}
downloadFilesInDirectory(remoteFilePath, localFilePath); // 递归下载子文件夹
}
}
} catch (IOException e) {
System.out.println("列出文件失败: " + remoteDir);
e.printStackTrace();
}
}
public static void main(String[] args) {
FTPDownload ftpDownload = new FTPDownload();
String ftpHost = "192.168.5.18"; // FTP服务器IP
String ftpUserName = "admin"; // FTP用户名
String ftpPassword = "hbyt2025"; // FTP密码
int ftpPort = 21; // FTP端口默认21
String remoteDir = "/FB-25-039-FS-01/FS25040.03.0-PDF"; // 远程目录
String localDir = "F:/FB-25-039-FS-01"; // 本地保存目录
// 连接到FTP服务器
ftpDownload.connect(ftpHost, ftpUserName, ftpPassword, ftpPort);
// 下载文件
ftpDownload.downloadFilesInDirectory(remoteDir, localDir);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,44 @@
package com.ruoyi.common.utils;
/**
* 金蝶物料存货类别(FCategoryID.FNumber) 取值规则
*/
public final class KingdeeMaterialCategoryHelper {
/** 半成品 */
public static final String SEMI_FINISHED = "007";
/** 原材料 */
public static final String RAW_MATERIAL = "006";
/** 产成品(父级物料默认) */
public static final String FINISHED_PRODUCT = "CHLB05_SYS";
private KingdeeMaterialCategoryHelper() {
}
/**
* BOM 子件 / 明细物料自制(2)委外(3)编码含 -MP 007外购(1) 006
*/
public static String resolveChildCategoryFNumber(String erpClsId, String materialCode) {
if (containsMp(materialCode)) {
return SEMI_FINISHED;
}
if ("2".equals(erpClsId) || "3".equals(erpClsId)) {
return SEMI_FINISHED;
}
return RAW_MATERIAL;
}
/**
* BOM 父级物料 -MP 007否则产成品 CHLB05_SYS
*/
public static String resolveParentCategoryFNumber(String fNumber, String partNumber) {
if (containsMp(fNumber) || containsMp(partNumber)) {
return SEMI_FINISHED;
}
return FINISHED_PRODUCT;
}
public static boolean containsMp(String materialCode) {
return materialCode != null && materialCode.contains("-MP");
}
}

View File

@ -0,0 +1,130 @@
package com.ruoyi.common.utils;
import com.ruoyi.common.exception.ServiceException;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
* 工艺路线工段 金蝶加工车间FDepartmentId.FNumber与金蝶一致
* <pre>
* WC000001 机一工段 006 机加车间
* WC000002 机二工段 006 机加车间
* WC000004 装一工段 007 装配车间
* WC000005 装二工段 007 装配车间
* WC000006 电钳工段 007 装配车间
* WC000007 下料工段 006 机加车间
* WC000008 委外中心 006 机加车间
* WC000010 下料工段 018 铆焊车间
* WC000011 焊接工段 018 铆焊车间
* </pre>
*/
public final class KingdeeRouteDepartmentHelper {
/** 机加车间 */
public static final String DEPT_MACHINE = "006";
/** 装配车间 */
public static final String DEPT_ASSEMBLY = "007";
/** 铆焊车间 */
public static final String DEPT_RIVET_WELD = "018";
/** 006 机加车间 */
private static final Set<String> MACHINE_WORKSHOP = setOf(
"机一工段", "机二工段", "机加委外");
/** 007 装配车间 */
private static final Set<String> ASSEMBLY_WORKSHOP = setOf(
"装一工段", "装二工段", "电钳工段","装配委外");
/** 018 铆焊车间 */
private static final Set<String> RIVET_WELD_WORKSHOP = setOf(
"下料工段", "焊接工段","铆焊委外");
public static final List<String> ALLOWED_WORK_CENTERS;
static {
LinkedHashSet<String> all = new LinkedHashSet<>();
all.addAll(MACHINE_WORKSHOP);
all.addAll(ASSEMBLY_WORKSHOP);
all.addAll(RIVET_WELD_WORKSHOP);
ALLOWED_WORK_CENTERS = Collections.unmodifiableList(Arrays.asList(all.toArray(new String[0])));
}
private KingdeeRouteDepartmentHelper() {
}
/**
* @param workCenter 工段名称 trim
* @return 金蝶部门编码 FDepartmentId.FNumber
*/
public static String resolveDepartmentFNumber(String workCenter) {
String wc = normalize(workCenter);
if (wc == null) {
throw new ServiceException("工作中心(工段)不能为空");
}
if (MACHINE_WORKSHOP.contains(wc)) {
return DEPT_MACHINE;
}
if (ASSEMBLY_WORKSHOP.contains(wc)) {
return DEPT_ASSEMBLY;
}
if (RIVET_WELD_WORKSHOP.contains(wc)) {
return DEPT_RIVET_WELD;
}
throw new ServiceException("不支持的工作中心「" + wc + "」,仅允许:"
+ String.join("", ALLOWED_WORK_CENTERS));
}
public static String normalize(String workCenter) {
if (workCenter == null) {
return null;
}
String s = workCenter.trim();
return s.isEmpty() ? null : s;
}
/** 金蝶部门编码 → 加工车间名称(用于校验提示) */
public static String departmentLabel(String deptFNumber) {
if (DEPT_MACHINE.equals(deptFNumber)) {
return "机加车间";
}
if (DEPT_ASSEMBLY.equals(deptFNumber)) {
return "装配车间";
}
if (DEPT_RIVET_WELD.equals(deptFNumber)) {
return "铆焊车间";
}
return deptFNumber != null ? deptFNumber : "";
}
/**
* 车间兼容分组机加(006)装配(007)视为同一组可同物料混用
* 铆焊(018)单独成组不得与机加/装配混用
*/
public static String workshopCompatibilityGroup(String deptFNumber) {
if (DEPT_MACHINE.equals(deptFNumber) || DEPT_ASSEMBLY.equals(deptFNumber)) {
return "MACHINE_ASSEMBLY";
}
return deptFNumber;
}
/**
* 同一物料下的加工车间是否冲突
* 仅机加+装配 不冲突含铆焊且同时含其他车间 冲突
*/
public static boolean hasIncompatibleWorkshops(Set<String> deptFNumbers) {
if (deptFNumbers == null || deptFNumbers.size() <= 1) {
return false;
}
LinkedHashSet<String> groups = new LinkedHashSet<>();
for (String dept : deptFNumbers) {
groups.add(workshopCompatibilityGroup(dept));
}
return groups.size() > 1;
}
private static Set<String> setOf(String... items) {
return Arrays.stream(items).collect(Collectors.toCollection(LinkedHashSet::new));
}
}

View File

@ -4,8 +4,11 @@ import com.ruoyi.common.utils.spring.SpringUtils;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.springframework.context.MessageSource;
import org.springframework.context.NoSuchMessageException;
import org.springframework.context.i18n.LocaleContextHolder;
import java.util.Locale;
/**
* 获取i18n资源文件
*
@ -24,6 +27,11 @@ public class MessageUtils {
* @return 获取国际化翻译值
*/
public static String message(String code, Object... args) {
return MESSAGE_SOURCE.getMessage(code, args, LocaleContextHolder.getLocale());
Locale locale = LocaleContextHolder.getLocale();
try {
return MESSAGE_SOURCE.getMessage(code, args, locale);
} catch (NoSuchMessageException ex) {
return MESSAGE_SOURCE.getMessage(code, args, code, locale);
}
}
}

View File

@ -0,0 +1,22 @@
package com.ruoyi.common.utils;
import lombok.Getter;
/**
* PLM PDF 左栏标注落点 {@link PlmPdfMarkPlacementResolver} 解析
*/
@Getter
public class PlmPdfMarkPlacement {
private final String formatId;
private final float markX;
private final float[] markY;
private final int fontSize;
public PlmPdfMarkPlacement(String formatId, float markX, float[] markY, int fontSize) {
this.formatId = formatId;
this.markX = markX;
this.markY = markY;
this.fontSize = fontSize;
}
}

View File

@ -0,0 +1,112 @@
package com.ruoyi.common.utils;
import com.ruoyi.common.config.PlmPdfMarkProperties;
import com.ruoyi.common.config.PlmPdfMarkProperties.FormatProfile;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* PDF 首页尺寸匹配 plm-pdf-mark.yml 中的图幅配置
*/
@Slf4j
@Component
@RequiredArgsConstructor
public class PlmPdfMarkPlacementResolver {
private final PlmPdfMarkProperties properties;
public float rotation() {
return properties.getRotation();
}
public PlmPdfMarkPlacement resolve(float width, float height) {
FormatProfile profile = findMatchingProfile(width, height);
if (profile == null) {
profile = findById(properties.getDefaultFormat());
if (profile != null) {
log.warn("[PLM PDF 标注] 未匹配图幅 {}x{}pt回退 default-format={}",
width, height, profile.getId());
}
}
if (profile == null && !properties.getFormats().isEmpty()) {
profile = properties.getFormats().get(0);
log.warn("[PLM PDF 标注] 未匹配图幅 {}x{}pt回退列表首项 id={}",
width, height, profile.getId());
}
if (profile == null) {
log.warn("[PLM PDF 标注] 无图幅配置,使用内置 A4 默认比例 page={}x{}", width, height);
return buildPlacement("A4_FALLBACK", width, height, fallbackA4Profile());
}
return buildPlacement(profile.getId(), width, height, profile);
}
private PlmPdfMarkPlacement buildPlacement(String formatId, float width, float height, FormatProfile profile) {
int fontSize = profile.getFontSize() > 0 ? profile.getFontSize() : properties.getFontSize();
return new PlmPdfMarkPlacement(
formatId,
width * profile.getXRatio(),
new float[]{
height * profile.getBatchQtyYRatio(),
height * profile.getUnitQtyYRatio(),
height * profile.getIssueTimeYRatio(),
height * profile.getOrderNoYRatio()
},
fontSize
);
}
private FormatProfile findMatchingProfile(float width, float height) {
List<FormatProfile> formats = properties.getFormats();
if (formats == null || formats.isEmpty()) {
return null;
}
for (FormatProfile profile : formats) {
if (profile == null || profile.getId() == null) {
continue;
}
if (matches(width, height, profile)) {
return profile;
}
}
return null;
}
private FormatProfile findById(String id) {
if (id == null || id.trim().isEmpty()) {
return null;
}
String target = id.trim();
for (FormatProfile profile : properties.getFormats()) {
if (profile != null && target.equalsIgnoreCase(profile.getId())) {
return profile;
}
}
return null;
}
private static boolean matches(float width, float height, FormatProfile profile) {
float tol = profile.getTolerancePt() > 0 ? profile.getTolerancePt() : 4f;
if (nearPair(width, height, profile.getWidthPt(), profile.getHeightPt(), tol)) {
return true;
}
return profile.isAllowSwap()
&& nearPair(width, height, profile.getHeightPt(), profile.getWidthPt(), tol);
}
private static boolean nearPair(float w, float h, float refW, float refH, float tol) {
return Math.abs(w - refW) <= tol && Math.abs(h - refH) <= tol;
}
private static FormatProfile fallbackA4Profile() {
FormatProfile p = new FormatProfile();
p.setXRatio(0.048f);
p.setBatchQtyYRatio(0.69f);
p.setUnitQtyYRatio(0.52f);
p.setIssueTimeYRatio(0.35f);
p.setOrderNoYRatio(0.18f);
return p;
}
}

View File

@ -11,6 +11,8 @@ import org.apache.pdfbox.multipdf.PDFMergerUtility;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.List;
import java.util.Map;
@ -114,16 +116,62 @@ public class PDFDocHelper {
* @return void
*/
private static void addDeptReview(PdfContentByte content, Map<String, Object> review,float pswX,float pswY) {
addDeptReview(content, review, pswX, pswY, 0);
}
private static void addDeptReview(PdfContentByte content, Map<String, Object> review, float pswX, float pswY, float rotation) {
if (Integer.parseInt(String.valueOf(review.get("type"))) == 1) {
content.setColorFill(BaseColor.BLACK);
} else {
content.setColorFill(BaseColor.RED);
}
// 设置水印位置和内容
String result = (String) review.get("result");
System.out.println("水印内容:" + result);
System.out.println("打印位置坐标:" + pswX + "," + pswY);
content.showTextAligned(Element.ALIGN_LEFT, result, pswX, pswY, 0);
content.showTextAligned(Element.ALIGN_LEFT, result, pswX, pswY, rotation);
}
/**
* PDF 1 页指定位置叠加文字无图章经临时文件替换原文件
*/
public static void stampTextFirstPage(String pdfPath, List<Map<String, ?>> reviews, float[] pswX, float[] pswY, int fontSize)
throws IOException, DocumentException {
stampTextFirstPage(pdfPath, reviews, pswX, pswY, fontSize, 0);
}
/**
* PDF 1 页指定位置叠加文字无图章经临时文件替换原文件
*
* @param rotation 逆时针旋转角度伊特左栏竖排一般为 90
*/
public static void stampTextFirstPage(String pdfPath, List<Map<String, ?>> reviews, float[] pswX, float[] pswY,
int fontSize, float rotation) throws IOException, DocumentException {
if (reviews == null || reviews.isEmpty()) {
return;
}
if (pswX == null || pswY == null || pswX.length < reviews.size() || pswY.length < reviews.size()) {
throw new IllegalArgumentException("reviews 与坐标数组长度不一致");
}
File src = new File(pdfPath);
File temp = new File(src.getParentFile(), "_plm_stamp_" + src.getName());
PdfReader reader = new PdfReader(pdfPath);
FileOutputStream fout = new FileOutputStream(temp);
PdfStamper stp = new PdfStamper(reader, fout);
try {
PdfContentByte content = stp.getOverContent(1);
content.beginText();
content.setFontAndSize(getBaseFont(), fontSize > 0 ? fontSize : 10);
for (int t = 0; t < reviews.size(); t++) {
Map<String, Object> review = (Map<String, Object>) reviews.get(t);
addDeptReview(content, review, pswX[t], pswY[t], rotation);
}
content.endText();
} finally {
stp.close();
fout.close();
reader.close();
}
Files.move(temp.toPath(), src.toPath(), StandardCopyOption.REPLACE_EXISTING);
}
/**

View File

@ -0,0 +1,321 @@
package com.ruoyi.common.utils.file;
import com.github.junrar.Archive;
import com.github.junrar.rarfile.FileHeader;
import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry;
import org.apache.commons.compress.archivers.sevenz.SevenZFile;
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.Enumeration;
import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
/**
* zip / rar / 7z / tar.gz 等压缩包中读取 PDF / DWG
*/
public final class PlmPdfArchiveExtractor {
public static final String SUPPORTED_HINT = "zip、rar、7z、tar、tar.gz、tgz、tar.bz2、gz单 PDF/DWG";
@FunctionalInterface
public interface PdfEntryWriter {
void writeTo(Path target) throws IOException;
}
/** 持有底层压缩包句柄,用完须 close */
public static final class PdfArchiveSession implements AutoCloseable {
private final Map<String, PdfEntryWriter> entryWriters;
private final Closeable resource;
private PdfArchiveSession(Map<String, PdfEntryWriter> entryWriters, Closeable resource) {
this.entryWriters = entryWriters;
this.resource = resource;
}
/** PDF + DWG 条目写入器key 为压缩包内相对路径) */
public Map<String, PdfEntryWriter> getPdfWriters() {
return entryWriters;
}
public Map<String, PdfEntryWriter> getEntryWriters() {
return entryWriters;
}
@Override
public void close() throws IOException {
if (resource != null) {
resource.close();
}
}
}
private PlmPdfArchiveExtractor() {
}
public static PdfArchiveSession open(Path archiveFile, String originalName) throws IOException {
String type = detectArchiveType(originalName);
if (type == null) {
throw new IOException("不支持的压缩格式,仅支持: " + SUPPORTED_HINT);
}
switch (type) {
case "zip":
return openZip(archiveFile);
case "rar":
return openRar(archiveFile);
case "7z":
return open7z(archiveFile);
case "tar":
return openTar(archiveFile, false, false);
case "tar.gz":
return openTar(archiveFile, true, false);
case "tar.bz2":
return openTar(archiveFile, false, true);
case "gz":
return openGzipSingle(archiveFile, originalName);
default:
throw new IOException("不支持的压缩格式: " + type);
}
}
public static String detectArchiveType(String originalName) {
if (originalName == null) {
return null;
}
String lower = originalName.trim().toLowerCase(Locale.ROOT);
if (lower.endsWith(".tar.gz") || lower.endsWith(".tgz")) {
return "tar.gz";
}
if (lower.endsWith(".tar.bz2") || lower.endsWith(".tbz2")) {
return "tar.bz2";
}
if (lower.endsWith(".zip")) {
return "zip";
}
if (lower.endsWith(".rar")) {
return "rar";
}
if (lower.endsWith(".7z")) {
return "7z";
}
if (lower.endsWith(".tar")) {
return "tar";
}
if (lower.endsWith(".gz")) {
return "gz";
}
return null;
}
public static String tempFileSuffix(String originalName) {
String type = detectArchiveType(originalName);
if (type == null) {
return ".bin";
}
switch (type) {
case "tar.gz":
return ".tar.gz";
case "tar.bz2":
return ".tar.bz2";
case "gz":
return ".gz";
default:
return "." + type;
}
}
private static PdfArchiveSession openZip(Path file) throws IOException {
ZipFile zf = new ZipFile(file.toFile());
Map<String, PdfEntryWriter> map = new LinkedHashMap<>();
try {
Enumeration<? extends ZipEntry> entries = zf.entries();
while (entries.hasMoreElements()) {
ZipEntry ze = entries.nextElement();
if (ze == null || ze.isDirectory()) {
continue;
}
String name = normalizeEntryName(ze.getName());
if (!isPdfOrDwg(name)) {
continue;
}
putOnce(map, name, target -> {
try (InputStream in = zf.getInputStream(ze)) {
Files.copy(in, target, StandardCopyOption.REPLACE_EXISTING);
}
});
}
} catch (IOException e) {
zf.close();
throw e;
}
return new PdfArchiveSession(map, zf);
}
private static PdfArchiveSession openRar(Path file) throws IOException {
try {
Archive archive = new Archive(file.toFile());
Map<String, PdfEntryWriter> map = new LinkedHashMap<>();
for (FileHeader fh : archive.getFileHeaders()) {
if (fh == null || fh.isDirectory()) {
continue;
}
String name = normalizeEntryName(fh.getFileName());
if (!isPdfOrDwg(name)) {
continue;
}
putOnce(map, name, target -> {
try (InputStream in = archive.getInputStream(fh)) {
Files.copy(in, target, StandardCopyOption.REPLACE_EXISTING);
}
});
}
return new PdfArchiveSession(map, archive);
} catch (Exception e) {
throw new IOException("解压 RAR 失败: " + e.getMessage(), e);
}
}
private static PdfArchiveSession open7z(Path file) throws IOException {
SevenZFile sz = SevenZFile.builder().setPath(file).get();
Map<String, PdfEntryWriter> map = new LinkedHashMap<>();
try {
SevenZArchiveEntry entry;
while ((entry = sz.getNextEntry()) != null) {
if (entry.isDirectory()) {
continue;
}
String name = normalizeEntryName(entry.getName());
if (!isPdfOrDwg(name)) {
continue;
}
byte[] data = read7zEntry(sz);
putOnce(map, name, target -> Files.write(target, data));
}
} catch (IOException e) {
sz.close();
throw e;
}
return new PdfArchiveSession(map, sz);
}
private static byte[] read7zEntry(SevenZFile sz) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[8192];
int n;
while ((n = sz.read(buffer)) > 0) {
baos.write(buffer, 0, n);
}
return baos.toByteArray();
}
private static PdfArchiveSession openTar(Path file, boolean gzip, boolean bzip2) throws IOException {
InputStream raw = Files.newInputStream(file);
InputStream compressed = raw;
if (gzip) {
compressed = new GzipCompressorInputStream(raw);
} else if (bzip2) {
compressed = new BZip2CompressorInputStream(raw);
}
TarArchiveInputStream tar = new TarArchiveInputStream(compressed);
Map<String, PdfEntryWriter> map = new LinkedHashMap<>();
try {
collectTarEntries(map, tar);
} catch (IOException e) {
tar.close();
throw e;
}
return new PdfArchiveSession(map, (Closeable) tar::close);
}
private static void collectTarEntries(Map<String, PdfEntryWriter> map, TarArchiveInputStream tar)
throws IOException {
ArchiveEntry entry;
while ((entry = tar.getNextEntry()) != null) {
if (entry.isDirectory()) {
continue;
}
String name = normalizeEntryName(entry.getName());
if (!isPdfOrDwg(name)) {
continue;
}
byte[] data = readAll(tar);
putOnce(map, name, target -> Files.write(target, data));
}
}
private static PdfArchiveSession openGzipSingle(Path file, String originalName) throws IOException {
String entryName = normalizeEntryName(fileNameOnly(originalName));
String lower = entryName.toLowerCase(Locale.ROOT);
if (!isPdfOrDwg(entryName)) {
// 单文件 gzip无法从内容判断时默认按 PDF 命名
if (!lower.endsWith(".pdf") && !lower.endsWith(".dwg")) {
entryName = entryName + ".pdf";
}
}
Map<String, PdfEntryWriter> map = new LinkedHashMap<>();
String finalName = entryName;
map.put(finalName, target -> {
try (InputStream in = new GzipCompressorInputStream(Files.newInputStream(file))) {
Files.copy(in, target, StandardCopyOption.REPLACE_EXISTING);
}
});
return new PdfArchiveSession(map, null);
}
private static byte[] readAll(InputStream in) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buf = new byte[8192];
int n;
while ((n = in.read(buf)) != -1) {
baos.write(buf, 0, n);
}
return baos.toByteArray();
}
private static void putOnce(Map<String, PdfEntryWriter> map, String name, PdfEntryWriter writer) throws IOException {
if (map.containsKey(name)) {
throw new IOException("压缩包内存在重复图纸路径: " + name);
}
map.put(name, writer);
}
private static boolean isPdfOrDwg(String name) {
if (name == null) {
return false;
}
String lower = name.toLowerCase(Locale.ROOT);
return lower.endsWith(".pdf") || lower.endsWith(".dwg");
}
public static String normalizeEntryName(String entryName) {
String s = entryName == null ? "" : entryName.trim().replace('\\', '/');
while (s.startsWith("/")) {
s = s.substring(1);
}
while (s.startsWith("./")) {
s = s.substring(2);
}
if (s.contains("..")) {
throw new IllegalArgumentException("非法压缩包路径: " + entryName);
}
return s;
}
private static String fileNameOnly(String path) {
String s = path == null ? "" : path.replace('\\', '/');
int i = s.lastIndexOf('/');
return i >= 0 ? s.substring(i + 1) : s;
}
}

View File

@ -39,7 +39,7 @@ public class SmbUtil {
}
// 定位到远程目标子目录
SmbFile remoteDir = new SmbFile("smb://192.168.5.18/2025/" + targetFolder + "/", cifs);
SmbFile remoteDir = new SmbFile("smb://192.168.14.218/2025/" + targetFolder + "/", cifs);
if (!remoteDir.exists() || !remoteDir.isDirectory()) {
System.err.println("远程目录不存在: " + remoteDir.getCanonicalPath());
@ -84,7 +84,7 @@ public class SmbUtil {
}
// 定位到远程目标子目录
SmbFile remoteDir = new SmbFile("smb://192.168.5.18/2026/" + targetFolder + "/", cifs);
SmbFile remoteDir = new SmbFile("smb://192.168.14.218/2026/" + targetFolder + "/", cifs);
if (!remoteDir.exists() || !remoteDir.isDirectory()) {
System.err.println("远程目录不存在或不是一个目录: " + remoteDir.getCanonicalPath());

View File

@ -0,0 +1,7 @@
package com.ruoyi.common.utils;
/**
* Maven Surefire 默认 profile=dev 时只运行带 {@code @Category(Dev.class)} 的测试
*/
public interface Dev {
}

View File

@ -1,30 +0,0 @@
package com.ruoyi.common.utils;
import com.ruoyi.common.core.domain.R;
import org.junit.Test;
public class FtpDownloadTest {
@Test
public void testDownload() {
String host = "192.168.5.18";
int port = 21; // 使用21端口测试下载根据你之前代F码的默认行为一般下载用21
String username = "admin";
String password = "hbyt2025";
// 你的实际测试路径
String remoteDir = "/2026/QB-26-072-XCL"; // 你想测试下载的 FTP 目录
String localDir = "D:\\file\\test_download"; // 本地存放目录
System.out.println("开始测试下载 FTP 目录: " + remoteDir);
// 调用 FtpUtil 下载文件
R<String> result = FtpUtil.downloadFtpDirectoryFiles(
host, username, password, port, remoteDir, localDir, null
);
System.out.println("下载结果 Code: " + result.getCode());
System.out.println("下载结果 Msg: " + result.getMsg());
System.out.println("下载结果 Data: " + result.getData());
}
}

View File

@ -0,0 +1,444 @@
package com.ruoyi.common.utils;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfReader;
import com.ruoyi.common.config.PlmPdfMarkProperties;
import com.ruoyi.common.config.PlmPdfMarkProperties.FormatProfile;
import com.ruoyi.common.utils.file.PDFDocHelper;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.yaml.snakeyaml.Yaml;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
/**
* PLM PDF 左栏标注坐标调试工具配合 plm-pdf-mark.yml
* <p>
* <b>适配规则</b>
* <ol>
* <li> PDF 首页 {@code getPageSizeWithRotation(1)} 的宽高pt为准 yml {@code width-pt}/{@code height-pt} 比较</li>
* <li>偏差在 {@code tolerance-pt} 内视为命中{@code allow-swap: true} 时允许横竖互换匹配</li>
* <li>横版专用项 A3_LANDSCAPE应设 {@code allow-swap: false}且写在竖版同尺寸项之前或之后均可但须 tolerance 足够区分</li>
* <li>加长图幅A3+0.5A2+0.5 尺寸与标准 A 系不同须单独增加 format {@code id} 建议与文件名一致</li>
* <li>坐标均为相对页宽/高的比例0~1原点在左下角四条文字自上而下本批数量单台数量发图时间生产令号</li>
* <li>调试流程先跑 {@link #scanAndMatchReport()} 看匹配结果 再跑 {@link #stampPreview()} 目视核对 微调 ratio 后重复</li>
* </ol>
* <p>
* <b>样本文件 plm-pdf-mark.yml 配置 id 对应关系</b>样本目录下原文件 {@code _mark_debug/*_marked.pdf}
* <pre>
* 1-A0.pdf A0_LANDSCAPE
* 2-A0-plus.pdf A0_PLUS_LANDSCAPE
* 3-A1.pdf A1_LANDSCAPE
* 4-A1-PLUS.pdf A1_PLUS_0_5_LANDSCAPE
* 5-A2.pdf A2_LANDSCAPE
* 6-A2-PLUS.pdf A2_PLUS_0_5_LANDSCAPE
* 7-A3.pdf A3_LANDSCAPE
* 8-A3-plus.pdf A3_PLUS_0_5_LANDSCAPE
* 9-A3x2.pdf A3_PLUS_1_LANDSCAPE
* 10-A4.pdf A4
* </pre>
* <p>
* 默认样本目录见 {@link #SAMPLE_DIR}输出目录{@code _mark_debug}
*/
@Category(Dev.class)
public class PlmPdfMarkDebugTest {
public static void main(String[] args) throws Exception {
if (args.length > 0 && "stamp".equalsIgnoreCase(args[0])) {
new PlmPdfMarkDebugTest().stampPreview();
} else {
new PlmPdfMarkDebugTest().scanAndMatchReport();
}
}
/** 钟铃样本 PDF 目录,可按本机路径修改 */
private static final String SAMPLE_DIR = "D:\\新建文件夹\\新建文件夹(2)";
/** 标注预览输出子目录(不覆盖原文件) */
private static final String OUTPUT_SUBDIR = "_mark_debug";
/** 可用 -Dplm.pdf.mark.yml=绝对路径 覆盖 */
private static final String MARK_YML_PROP = "plm.pdf.mark.yml";
private static final String[] MARK_YML_CANDIDATES = {
"ruoyi-admin/src/main/resources/plm-pdf-mark.yml",
"../ruoyi-admin/src/main/resources/plm-pdf-mark.yml",
"evo-k3cloud/ruoyi-admin/src/main/resources/plm-pdf-mark.yml"
};
private static final String[] LABELS = {"本批99", "单台9", "2026/06/26", "CP-TEST-001"};
/**
* 扫描样本目录下所有 PDF打印页尺寸旋转匹配到的 format id绝对坐标
* 未命中时会给出建议的 yml 片段width/height 取实测值
*/
@Test
public void scanAndMatchReport() throws Exception {
PlmPdfMarkProperties props = loadMarkProperties();
PlmPdfMarkPlacementResolver resolver = new PlmPdfMarkPlacementResolver(props);
File dir = new File(SAMPLE_DIR);
if (!dir.isDirectory()) {
throw new IllegalStateException("样本目录不存在: " + SAMPLE_DIR);
}
File[] pdfs = dir.listFiles(f -> f.isFile() && f.getName().toLowerCase(Locale.ROOT).endsWith(".pdf"));
if (pdfs == null || pdfs.length == 0) {
throw new IllegalStateException("目录下无 PDF: " + SAMPLE_DIR);
}
Arrays.sort(pdfs, (a, b) -> a.getName().compareToIgnoreCase(b.getName()));
System.out.println("=== PLM PDF 图幅扫描 ===");
File ymlFile = resolveMarkYmlFile();
System.out.println("配置: " + ymlFile.getAbsolutePath());
System.out.println("样本: " + SAMPLE_DIR);
System.out.println("rotation=" + props.getRotation() + ", default-format=" + props.getDefaultFormat());
System.out.println();
for (File pdf : pdfs) {
PageInfo page = readFirstPage(pdf);
PlmPdfMarkPlacement placement = resolver.resolve(page.width, page.height);
FormatProfile matchedProfile = findExactProfile(props, page.width, page.height);
boolean direct = matchedProfile != null && directMatch(page.width, page.height, matchedProfile);
String matchMode = matchedProfile == null ? "FALLBACK"
: (direct ? "DIRECT" : "SWAP");
System.out.println("--- " + pdf.getName() + " ---");
System.out.printf(Locale.ROOT, " page=%.2f x %.2f pt, rotation=%d%n",
page.width, page.height, page.rotation);
System.out.printf(Locale.ROOT, " matched=%s (%s)%n",
placement.getFormatId(), matchMode);
if ("SWAP".equals(matchMode)) {
System.out.println(" >>> 注意: 通过 allow-swap 横竖互换命中,请将专用横版项排在竖版项之前并设 allow-swap: false");
}
System.out.printf(Locale.ROOT, " markX=%.2f, markY=[%.2f, %.2f, %.2f, %.2f], fontSize=%d%n",
placement.getMarkX(),
placement.getMarkY()[0], placement.getMarkY()[1],
placement.getMarkY()[2], placement.getMarkY()[3],
placement.getFontSize());
if (matchedProfile == null) {
System.out.println(" >>> 建议新增 yml 项(复制后微调 ratio:");
System.out.print(suggestYamlSnippet(pdf.getName(), page.width, page.height, props));
}
System.out.println();
}
}
/**
* 按当前 yml 配置对样本 PDF 打测试字输出到 {@code _mark_debug} 目录供目视核对
*/
@Test
public void stampPreview() throws Exception {
PlmPdfMarkProperties props = loadMarkProperties();
PlmPdfMarkPlacementResolver resolver = new PlmPdfMarkPlacementResolver(props);
File inDir = new File(SAMPLE_DIR);
File outDir = new File(inDir, OUTPUT_SUBDIR);
if (outDir.exists()) {
File[] old = outDir.listFiles();
if (old != null) {
for (File f : old) {
if (!f.delete()) {
System.out.println(" 警告: 无法删除旧文件 " + f.getName() + "(若被 PDF 阅读器占用请关闭后重试)");
}
}
}
} else if (!outDir.mkdirs()) {
throw new IllegalStateException("无法创建输出目录: " + outDir.getAbsolutePath());
}
File[] pdfs = inDir.listFiles(f -> f.isFile() && f.getName().toLowerCase(Locale.ROOT).endsWith(".pdf"));
if (pdfs == null || pdfs.length == 0) {
throw new IllegalStateException("目录下无 PDF: " + SAMPLE_DIR);
}
System.out.println("=== PLM PDF 标注预览 ===");
System.out.println("输出: " + outDir.getAbsolutePath());
for (File pdf : pdfs) {
PageInfo page = readFirstPage(pdf);
PlmPdfMarkPlacement placement = resolver.resolve(page.width, page.height);
float markX = placement.getMarkX();
float[] markY = placement.getMarkY();
float[] markXArr = {markX, markX, markX, markX};
File outFile = new File(outDir, stripPdfExt(pdf.getName()) + "_marked.pdf");
Files.copy(pdf.toPath(), outFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
List<Map<String, ?>> reviews = buildTestReviews();
PDFDocHelper.stampTextFirstPage(outFile.getAbsolutePath(), reviews, markXArr, markY,
placement.getFontSize(), props.getRotation());
System.out.printf(Locale.ROOT, " %s -> %s [%s, %.0fx%.0f]%n",
pdf.getName(), outFile.getName(), placement.getFormatId(), page.width, page.height);
}
System.out.println("完成,请打开 _mark_debug 目录目视核对四条文字是否对齐图框左栏。");
}
// --- helpers ---
private static PageInfo readFirstPage(File pdf) throws Exception {
PdfReader reader = new PdfReader(pdf.getAbsolutePath());
try {
Rectangle pageSize = reader.getPageSizeWithRotation(1);
return new PageInfo(pageSize.getWidth(), pageSize.getHeight(), reader.getPageRotation(1));
} finally {
reader.close();
}
}
private static FormatProfile findExactProfile(PlmPdfMarkProperties props, float w, float h) {
if (props.getFormats() == null) {
return null;
}
for (FormatProfile p : props.getFormats()) {
if (p == null || p.getId() == null) {
continue;
}
float tol = p.getTolerancePt() > 0 ? p.getTolerancePt() : 4f;
if (near(w, h, p.getWidthPt(), p.getHeightPt(), tol)) {
return p;
}
if (p.isAllowSwap() && near(w, h, p.getHeightPt(), p.getWidthPt(), tol)) {
return p;
}
}
return null;
}
private static boolean near(float w, float h, float rw, float rh, float tol) {
return Math.abs(w - rw) <= tol && Math.abs(h - rh) <= tol;
}
private static String suggestYamlSnippet(String fileName, float w, float h, PlmPdfMarkProperties props) {
FormatProfile seed = findNearestSeed(w, h, props);
String id = suggestId(fileName, w, h);
return String.format(Locale.ROOT,
" - id: %s%n" +
" width-pt: %.2f%n" +
" height-pt: %.2f%n" +
" tolerance-pt: 4%n" +
" allow-swap: false%n" +
" x-ratio: %.3f%n" +
" batch-qty-y-ratio: %.2f%n" +
" unit-qty-y-ratio: %.2f%n" +
" issue-time-y-ratio: %.2f%n" +
" order-no-y-ratio: %.2f%n",
id, w, h,
seed.getXRatio(), seed.getBatchQtyYRatio(), seed.getUnitQtyYRatio(),
seed.getIssueTimeYRatio(), seed.getOrderNoYRatio());
}
private static FormatProfile findNearestSeed(float w, float h, PlmPdfMarkProperties props) {
FormatProfile best = null;
double bestDist = Double.MAX_VALUE;
for (FormatProfile p : props.getFormats()) {
if (p == null) {
continue;
}
double d1 = dist(w, h, p.getWidthPt(), p.getHeightPt());
double d2 = dist(w, h, p.getHeightPt(), p.getWidthPt());
double d = Math.min(d1, d2);
if (d < bestDist) {
bestDist = d;
best = p;
}
}
return best != null ? best : props.getFormats().get(0);
}
private static double dist(float w, float h, float rw, float rh) {
return Math.hypot(w - rw, h - rh);
}
private static boolean directMatch(float w, float h, FormatProfile p) {
float tol = p.getTolerancePt() > 0 ? p.getTolerancePt() : 4f;
return near(w, h, p.getWidthPt(), p.getHeightPt(), tol);
}
private static String suggestId(String fileName, float w, float h) {
String upper = stripPdfExt(fileName).toUpperCase(Locale.ROOT);
if (upper.contains("A1+0.5") || upper.contains("A10.5")) {
return "A1_PLUS_0_5_LANDSCAPE";
}
if (upper.contains("A1")) {
return "A1_LANDSCAPE";
}
if (upper.contains("A2+0.5") || upper.contains("A20.5")) {
return "A2_PLUS_0_5_LANDSCAPE";
}
if (upper.contains("A2")) {
return "A2_LANDSCAPE";
}
if (upper.contains("A3+1") || upper.contains("A31")) {
return "A3_PLUS_1_LANDSCAPE";
}
if (upper.contains("A3+0.5") || upper.contains("A30.5")) {
return "A3_PLUS_0_5_LANDSCAPE";
}
if (upper.contains("A3")) {
return w > h ? "A3_LANDSCAPE" : "A3";
}
if (upper.contains("A4")) {
return "A4";
}
return (w > h ? "CUSTOM_LANDSCAPE" : "CUSTOM") + "_" + Math.round(w) + "x" + Math.round(h);
}
private static String stripPdfExt(String name) {
int dot = name.lastIndexOf('.');
return dot > 0 ? name.substring(0, dot) : name;
}
private static List<Map<String, ?>> buildTestReviews() {
List<Map<String, ?>> reviews = new ArrayList<>(4);
for (String label : LABELS) {
Map<String, Object> m = new HashMap<>(2);
m.put("type", 1);
m.put("result", label);
reviews.add(m);
}
return reviews;
}
@SuppressWarnings("unchecked")
static PlmPdfMarkProperties loadMarkProperties() throws Exception {
File ymlFile = resolveMarkYmlFile();
try (InputStream in = new FileInputStream(ymlFile)) {
Map<String, Object> root = new Yaml().load(in);
Map<String, Object> mark = (Map<String, Object>) ((Map<String, Object>) ((Map<String, Object>)
root.get("plm")).get("pdf")).get("mark");
return parseMarkProperties(mark);
}
}
/** 兼容 IDEA 工作目录为项目根或 ruoyi-common 模块目录 */
private static File resolveMarkYmlFile() {
String override = System.getProperty(MARK_YML_PROP);
if (override != null && !override.trim().isEmpty()) {
File f = new File(override.trim());
if (f.isFile()) {
return f;
}
throw new IllegalStateException("系统属性 " + MARK_YML_PROP + " 指向的文件不存在: " + f.getAbsolutePath());
}
File userDir = new File(System.getProperty("user.dir", "."));
List<File> tried = new ArrayList<>();
for (String rel : MARK_YML_CANDIDATES) {
File f = new File(userDir, rel);
tried.add(f);
if (f.isFile()) {
return f;
}
}
File walk = userDir;
for (int i = 0; i < 6 && walk != null; i++) {
File f = new File(walk, "ruoyi-admin/src/main/resources/plm-pdf-mark.yml");
tried.add(f);
if (f.isFile()) {
return f;
}
walk = walk.getParentFile();
}
StringBuilder msg = new StringBuilder("找不到 plm-pdf-mark.yml已尝试:");
for (File f : tried) {
msg.append("\n ").append(f.getAbsolutePath());
}
msg.append("\n可通过 -D").append(MARK_YML_PROP).append("=绝对路径 指定");
throw new IllegalStateException(msg.toString());
}
@SuppressWarnings("unchecked")
private static PlmPdfMarkProperties parseMarkProperties(Map<String, Object> mark) {
PlmPdfMarkProperties props = new PlmPdfMarkProperties();
props.setRotation(floatVal(mark.get("rotation"), 90f));
props.setFontSize(intVal(mark.get("font-size"), 10));
props.setDefaultFormat(strVal(mark.get("default-format"), "A4"));
List<Map<String, Object>> formats = (List<Map<String, Object>>) mark.get("formats");
if (formats != null) {
List<FormatProfile> list = new ArrayList<>(formats.size());
for (Map<String, Object> item : formats) {
list.add(parseFormatProfile(item));
}
props.setFormats(list);
}
return props;
}
private static FormatProfile parseFormatProfile(Map<String, Object> item) {
FormatProfile p = new FormatProfile();
p.setId(strVal(item.get("id"), null));
p.setWidthPt(floatVal(item.get("width-pt"), 0f));
p.setHeightPt(floatVal(item.get("height-pt"), 0f));
p.setTolerancePt(floatVal(item.get("tolerance-pt"), 4f));
p.setAllowSwap(boolVal(item.get("allow-swap"), true));
p.setXRatio(floatVal(item.get("x-ratio"), 0.048f));
p.setBatchQtyYRatio(floatVal(item.get("batch-qty-y-ratio"), 0.69f));
p.setUnitQtyYRatio(floatVal(item.get("unit-qty-y-ratio"), 0.52f));
p.setIssueTimeYRatio(floatVal(item.get("issue-time-y-ratio"), 0.35f));
p.setOrderNoYRatio(floatVal(item.get("order-no-y-ratio"), 0.18f));
p.setFontSize(intVal(item.get("font-size"), 0));
return p;
}
private static String strVal(Object v, String def) {
return v == null ? def : String.valueOf(v).trim();
}
private static float floatVal(Object v, float def) {
if (v == null) {
return def;
}
if (v instanceof Number) {
return ((Number) v).floatValue();
}
return Float.parseFloat(String.valueOf(v));
}
private static int intVal(Object v, int def) {
if (v == null) {
return def;
}
if (v instanceof Number) {
return ((Number) v).intValue();
}
return Integer.parseInt(String.valueOf(v));
}
private static boolean boolVal(Object v, boolean def) {
if (v == null) {
return def;
}
if (v instanceof Boolean) {
return (Boolean) v;
}
return Boolean.parseBoolean(String.valueOf(v));
}
private static final class PageInfo {
final float width;
final float height;
final int rotation;
PageInfo(float width, float height, int rotation) {
this.width = width;
this.height = height;
this.rotation = rotation;
}
}
}

View File

@ -15,8 +15,8 @@ spring:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
#url: jdbc:mysql://localhost:3306/item_retrieval-evo?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
url: jdbc:mysql://localhost:3307/item_retrieval-evo?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
#url: jdbc:mysql://192.168.5.121:3306/item_retrieval-evo?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
#url: jdbc:mysql://localhost:3307/item_retrieval-evo?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
url: jdbc:mysql://192.168.5.121:3306/item_retrieval-evo?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
username: root
password: root
hikari:

View File

@ -14,7 +14,7 @@ spring:
datasource:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/item_retrieval-evo?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai
url: jdbc:mysql://192.168.5.121:3306/item_retrieval-evo?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai
username: root
password: root
hikari:

View File

@ -12,6 +12,7 @@ import com.ruoyi.common.utils.StreamUtils;
import lombok.extern.slf4j.Slf4j;
import org.mybatis.spring.MyBatisSystemException;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.validation.BindException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
@ -73,6 +74,21 @@ public class GlobalExceptionHandler {
return R.fail(e.getMessage());
}
/**
* 数据完整性约束异常非空外键等
*/
@ExceptionHandler(DataIntegrityViolationException.class)
public R<Void> handleDataIntegrityViolationException(DataIntegrityViolationException e, HttpServletRequest request) {
String requestURI = request.getRequestURI();
log.error("请求地址'{}',数据完整性约束异常", requestURI, e);
Throwable cause = e.getMostSpecificCause();
String detail = cause != null ? cause.getMessage() : e.getMessage();
if (detail != null && (detail.contains("1048") || detail.contains("cannot be null") || detail.contains("不能为null"))) {
return R.fail("数据保存失败存在必填字段为空请检查Excel中名称、数量等列是否填写完整");
}
return R.fail("数据保存失败,请检查导入数据是否完整且符合格式要求");
}
/**
* 主键或UNIQUE索引数据重复异常
*/

View File

@ -27,10 +27,6 @@
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-s3</artifactId>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId>
</dependency>
</dependencies>

View File

@ -0,0 +1,60 @@
package com.ruoyi.system.constant;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* 钉钉指定/项目负责副总工程师姓名 PLM {@code zpdfzgcs} 工号写死在代码勿放 yml
*/
public final class DingSchemeDeputyChiefNameMap {
private DingSchemeDeputyChiefNameMap() {
}
/** 姓名未命中时的默认工号 */
public static final String DEFAULT_EMP_NO = "00496";
/** 「是否为机械标品」=是 时固定推送工号(毕敏霞) */
public static final String MECHANICAL_STANDARD_EMP_NO = "00026";
private static final Map<String, String> NAME_TO_EMP_NO;
static {
Map<String, String> m = new LinkedHashMap<>();
m.put("李德山", "00496");
m.put("杜惠斌", "00059");
// 马杰钉钉指定副总 PLM 接收人毕敏霞 00026
m.put("马杰", "00026");
NAME_TO_EMP_NO = Collections.unmodifiableMap(m);
}
public static Map<String, String> all() {
return NAME_TO_EMP_NO;
}
public static String empNoOf(String displayName) {
if (displayName == null || displayName.isEmpty()) {
return null;
}
for (String part : splitNames(displayName)) {
String empNo = NAME_TO_EMP_NO.get(part);
if (empNo != null) {
return empNo;
}
}
return null;
}
private static String[] splitNames(String displayName) {
String normalized = displayName.replace('', ',').trim();
if (!normalized.contains(",")) {
return new String[]{normalized};
}
String[] parts = normalized.split(",");
for (int i = 0; i < parts.length; i++) {
parts[i] = parts[i].trim();
}
return parts;
}
}

View File

@ -0,0 +1,95 @@
package com.ruoyi.system.constant;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* 钉钉技术方案申请表 {@code form_label_map} 标准对照控件 id 中文标题
* {@link DingSchemeFormWideColumns#ORDERED_IDS} 键集合一致
*/
public final class DingSchemeFormLabelMap {
private DingSchemeFormLabelMap() {
}
private static final Map<String, String> LABELS = build();
public static Map<String, String> labels() {
return LABELS;
}
public static String labelOf(String componentId) {
return LABELS.get(componentId);
}
private static Map<String, String> build() {
Map<String, String> m = new LinkedHashMap<>();
m.put("TextField_1BBYI1OFDJA80", "方案申请编号");
m.put("TextField_FRLYG3CQ3CG0", "概述名称");
m.put("InnerContactField_9DSIOI7Y7AO0", "填表人");
m.put("DDDateField_1BHYQ7T5N5TS0", "填表日期");
m.put("DDDateField_YYD1HAMKFXS0", "需求日期");
m.put("DDSelectField_1VS1BX17O9MO0", "有无前期对接工程师");
m.put("InnerContactField_U886PC45AO00", "前期对接工程师");
m.put("TextField_1HXMC0VO5TCW0", "客户全称");
m.put("TextField_QBMQQBNCTA80", "联系人及电话");
m.put("DDSelectField_845RKMRCBNC", "项目分类");
m.put("DDSelectField_1XTHOHPHULNK0", "产品名称");
m.put("TextField_1EIAVY538AM80", "产品应用领域");
m.put("ColumnLayout_N0ZDGQT4UJ40", "分栏");
m.put("DDSelectField_JDD37MSAU7K0", "刚性链类型");
m.put("TextField_7KHHS2KML4G0", "台面尺寸");
m.put("TextField_1CTQW75A6XK00", "台面尺寸/外形轮廓");
m.put("TextField_6JT3ARDIUY40", "外形尺寸(长宽高)");
m.put("TextField_1JWDW5KVN95S0", "基坑深度");
m.put("TextField_17ONU2GWWQQK0", "行程");
m.put("TextField_2E68TAT1P2B", "速度单位m/s或mm/s");
m.put("TextField_1D66PIGUHPEO0", "负载单位kg");
m.put("DDSelectField_12J1O9KUMFK00", "驱动方式");
m.put("DDSelectField_1QQEC44I00G00", "限位方式");
m.put("TextField_1FVHYJIFC9340", "最低高度");
m.put("DDSelectField_1CTHXMP1W6000", "有无偏载");
m.put("DDSelectField_1J17P5TOEU0W0", "设备形式");
m.put("TextField_23GWUBGROXWG0", "动载");
m.put("TextField_SIM35ICCGOW0", "静载");
m.put("TextField_1X4ISVYJ2E000", "电源电压");
m.put("TextField_F05H5U3N9NC0", "电压频率是否特殊");
m.put("TextField_J84FK4ALUOG0", "减速器要求");
m.put("TextField_3IXTW5EOSTK0", "导向形式");
m.put("DDSelectField_4JP6PT1HB480", "有无脚轮");
m.put("TextField_1ED24R0QOG4G0", "卷筒直径");
m.put("TextField_IR0XM2QFI4G0", "吊点数");
m.put("TextField_MWLXHEAJYDS0", "额定载荷");
m.put("TextField_GZISO77XGU80", "杆体自重/总载荷");
m.put("DDSelectField_1XGOO6QI7YE80", "有无载荷传感器");
m.put("TextField_V3UBXSM0V400", "箱体形式");
m.put("TextField_1N6AOCMUFXXC0", "出轴方式/方向");
m.put("TextField_5B1TRAUGUP80", "地脚板位置");
m.put("TextField_G2N28LNPOKO0", "行走速度");
m.put("DDSelectField_Y8AKWL5T20G0", "是否带升降");
m.put("TextField_1X0CJO3BBELC0", "升降高度");
m.put("TextField_1DCKMEARM96O0", "升降速度");
m.put("DDSelectField_1UNDZ9DNXIN4", "导航方式");
m.put("TextField_CO3RY4XTL800", "电机减速机种类");
m.put("TextField_QZAR20YC9DC0", "旋转速度");
m.put("TextField_1N728V92Z1LS0", "使用频率");
m.put("TextareaField_9MIMABZEHW40", "使用环境");
m.put("TextareaField_1WLKQPZU8UF40", "电控要求");
m.put("TextareaField_1BXA83S0L9Q80", "安装位置(如有纵/横剖图可附件说明)");
m.put("TextareaField_15N86B1OM9R40", "其他特殊要求");
m.put("TextareaField_ZCRQZCLP3800", "方案补充说明");
m.put("ColumnLayout_PV2QMZXXVCW0", "分栏");
m.put("DDAttachment_XJYUB17OFGW0", "附件");
m.put("TextareaField_GO981AG879K0", "技术总工意见");
m.put("DDSelectField_8DWKMBIUJ4S0", "是否为机械标品");
m.put("InnerContactField_1GEJYHX8RFQ80", "指定副总工程师");
m.put("InnerContactField_1YBPCOGCMBTS0", "指派项目工程师");
m.put("DDDateField_15JD56QBNOF40", "预计方案完成日期");
m.put("TextareaField_193R557BONZ40", "项目工程师意见");
m.put("TextareaField_1DVKJWXCBJ4W0", "任务详情");
m.put("DDDateField_LKZDJVPWIHC0", "方案提交日期");
m.put("DDSelectField_JZ9OQZY1A000", "是否收到方案");
return Collections.unmodifiableMap(m);
}
}

View File

@ -8,8 +8,8 @@ import java.util.Locale;
import java.util.Set;
/**
* event.json formComponentValues(146-843) gen-ding-scheme-wide.mjs IDS 一致
* 表单宽数据写入 {@code wf_values_json}JSON key 为钉钉控件 id原始大小写 {@code form_label_map} key 一致
* 当前钉钉模板 {@link DingSchemeFormLabelMap} / form_label_map 一致
* 表单宽数据写入 {@code wf_values_json}key=控件 id form_label_map key 一致
*/
public final class DingSchemeFormWideColumns {
@ -30,106 +30,60 @@ public final class DingSchemeFormWideColumns {
"DDSelectField_1XTHOHPHULNK0",
"TextField_1EIAVY538AM80",
"ColumnLayout_N0ZDGQT4UJ40",
"TextareaField_GO981AG879K0",
"InnerContactField_1TXM18E414740",
"InnerContactField_SHOIEPZ1X8W0",
"DDDateField_1107GY4FF5R40",
"TextareaField_1JNZ7QFU4GLC0",
"ColumnLayout_5UK9OEEPNQG0",
"TextNote_14QFWOA0NXUK",
"DDSelectField_JDD37MSAU7K0",
"TextField_7KHHS2KML4G0",
"TextField_17ONU2GWWQQK0",
"TextField_1D66PIGUHPEO0",
"TextField_2E68TAT1P2B",
"TextField_1FVHYJIFC9340",
"DDSelectField_12J1O9KUMFK00",
"DDSelectField_1CTHXMP1W6000",
"DDSelectField_1QQEC44I00G00",
"TextField_1X4ISVYJ2E000",
"TextareaField_9MIMABZEHW40",
"TextField_1N728V92Z1LS0",
"DDSelectField_4JP6PT1HB480",
"TextareaField_1WLKQPZU8UF40",
"TextareaField_ZCRQZCLP3800",
"ColumnLayout_704TMWHBUK00",
"DDAttachment_XJYUB17OFGW0",
"TextNote_1S3AH8USXUU80",
"TextNote_1S2UFGJ55CDC0",
"TextField_1JWDW5KVN95S0",
"TextField_1CTQW75A6XK00",
"TextField_6JT3ARDIUY40",
"TextField_1JWDW5KVN95S0",
"TextField_17ONU2GWWQQK0",
"TextField_2E68TAT1P2B",
"TextField_1D66PIGUHPEO0",
"DDSelectField_12J1O9KUMFK00",
"DDSelectField_1QQEC44I00G00",
"TextField_1FVHYJIFC9340",
"DDSelectField_1CTHXMP1W6000",
"DDSelectField_1J17P5TOEU0W0",
"TextField_23GWUBGROXWG0",
"TextField_SIM35ICCGOW0",
"TextField_18UFLIYK2G0W",
"TextField_EEO52079YWG0",
"TextField_17J58EEU17DS0",
"TextField_1X4ISVYJ2E000",
"TextField_F05H5U3N9NC0",
"TextField_J84FK4ALUOG0",
"TextField_3IXTW5EOSTK0",
"ColumnLayout_OWD8CAEIPCW0",
"DDAttachment_ZVUJAK8ZRVK0",
"TextNote_196NEZF2GKQO0",
"TextareaField_1BXA83S0L9Q80",
"DDSelectField_1J17P5TOEU0W0",
"DDSelectField_4JP6PT1HB480",
"TextField_1ED24R0QOG4G0",
"TextField_62OWJDX5J780",
"TextField_W509DMUVT0W0",
"TextField_IR0XM2QFI4G0",
"TextField_MWLXHEAJYDS0",
"TextField_GZISO77XGU80",
"DDSelectField_1XGOO6QI7YE80",
"TextareaField_15N86B1OM9R40",
"ColumnLayout_13OIS5R5G4G00",
"DDAttachment_Y0KM7E71JY80",
"TextNote_65FUYS6PMOG0",
"TextField_1WOIAN7UXMXS0",
"TextField_1B349K9H85FK0",
"TextField_V3UBXSM0V400",
"TextField_1N6AOCMUFXXC0",
"TextField_5B1TRAUGUP80",
"DDSelectField_R805UL353UO0",
"TextField_210LMWSH8CCG0",
"TextareaField_6JU2QSEND4G0",
"ColumnLayout_1OBP4JCUUC1S0",
"DDAttachment_1OQ414MMSQE80",
"TextNote_7USWEJCWOHO0",
"TextField_10A0OELOA9CW0",
"TextField_1F35DOLS3GJK0",
"TextField_G2N28LNPOKO0",
"DDSelectField_Y8AKWL5T20G0",
"TextField_1X0CJO3BBELC0",
"TextField_1DCKMEARM96O0",
"TextareaField_8ZYS78VXXKG0",
"DDSelectField_1UNDZ9DNXIN4",
"TextareaField_902TJ8AC3BO0",
"ColumnLayout_1V6324DSHDMO0",
"DDAttachment_19GLQ5UABT9C0",
"TextNote_1JGD3A0EBOU80",
"DDSelectField_JDD37MSAU7K0",
"TextField_1ODO49P4QIOW0",
"TextField_15YXLN28VYWW0",
"TextField_N3EEZETOMLS0",
"TextField_MZLNE0WXSYO0",
"DDSelectField_1D1NY47OPRY80",
"TextField_CO3RY4XTL800",
"TextField_1LJRN85YYW680",
"TextareaField_1W3YXGM2WVWG0",
"ColumnLayout_FVVK6OHVSMO0",
"DDAttachment_NISKKTWA4LC0",
"TextNote_18NMSNM15JLS0",
"TextField_YON75A1BPDS0",
"TextField_1LA4D1ZNJCO00",
"TextField_QZAR20YC9DC0",
"TextField_W5VDI6TJE0W0",
"DDSelectField_JQFNCPP9Q8G0",
"TextField_X7WT90RW88W0",
"TextareaField_XVWU129IDG00",
"TextField_21CFZH9VCESG0",
"TextareaField_20MIUBGWHAYO0",
"ColumnLayout_7E01AAY4TUO0",
"DDAttachment_PVHB9480IPS0",
"TextareaField_I623WTCGKBK0",
"DDDateField_1QY4LG6SI9FK0",
"DDSelectField_W8ZTK2TQHHS0"
"TextField_1N728V92Z1LS0",
"TextareaField_9MIMABZEHW40",
"TextareaField_1WLKQPZU8UF40",
"TextareaField_1BXA83S0L9Q80",
"TextareaField_15N86B1OM9R40",
"TextareaField_ZCRQZCLP3800",
"ColumnLayout_PV2QMZXXVCW0",
"DDAttachment_XJYUB17OFGW0",
"TextareaField_GO981AG879K0",
"DDSelectField_8DWKMBIUJ4S0",
"InnerContactField_1GEJYHX8RFQ80",
"ColumnLayout_1P00KI5NCBKW0",
"InnerContactField_1YBPCOGCMBTS0",
"DDDateField_15JD56QBNOF40",
"TextareaField_193R557BONZ40",
"ColumnLayout_1C721C2ID5PC0",
"TextareaField_1DVKJWXCBJ4W0",
"DDDateField_LKZDJVPWIHC0",
"DDSelectField_JZ9OQZY1A000"
));
private static final Set<String> ID_SET = new HashSet<>(ORDERED_IDS);
@ -138,12 +92,10 @@ public final class DingSchemeFormWideColumns {
return componentId != null && ID_SET.contains(componentId);
}
/** JSON 中的控件 id key与钉钉一致 */
public static String jsonKey(String componentId) {
return componentId;
}
/** 兼容旧「列名」思路wf_ + id 小写,仅用于文档/SQL 排查,不再建物理列 */
public static String legacyPhysicalColumnName(String componentId) {
return "wf_" + componentId.toLowerCase(Locale.ROOT);
}

View File

@ -0,0 +1,195 @@
package com.ruoyi.system.constant;
/**
* 钉钉控件 id{@link DingSchemeFormLabelMap} PLM {@code sales/saleplanapplyform} 字段
* 仅包含当前 form_label_map 中存在的控件注释为钉钉中文标题
* <p>
* 刚性链类型 PLM {@code gxllx}string多选逗号拼接
* 指派的副总工程师 PLM {@code zpdfzgcs}string 工号按钉钉姓名映射 {@link DingSchemeDeputyChiefNameMap}
* </p>
*/
public final class DingSchemePlmFieldIds {
private DingSchemePlmFieldIds() {
}
/** 方案申请编号 → fasqbh */
public static final String SCHEME_APPLY_NO = "TextField_1BBYI1OFDJA80";
/** 概述名称 → gsmc */
public static final String OVERVIEW_NAME = "TextField_FRLYG3CQ3CG0";
/** 填表人 → tbr */
public static final String FILLER = "InnerContactField_9DSIOI7Y7AO0";
/** 填表日期 → tbrq */
public static final String FILL_DATE = "DDDateField_1BHYQ7T5N5TS0";
/** 需求日期 → xqrq */
public static final String NEED_DATE = "DDDateField_YYD1HAMKFXS0";
/** 有无前期对接工程师 */
public static final String HAS_EARLY_ENGINEER = "DDSelectField_1VS1BX17O9MO0";
/** 前期对接工程师 → qqdjgcs多选姓名逗号拼接 */
public static final String EARLY_ENGINEER = "InnerContactField_U886PC45AO00";
/** 客户全称 → khgsqc */
public static final String CUSTOMER = "TextField_1HXMC0VO5TCW0";
/** 联系人及电话 → lxrjdh */
public static final String CONTACT = "TextField_QBMQQBNCTA80";
/** 项目分类 */
public static final String PROJECT_CATEGORY = "DDSelectField_845RKMRCBNC";
/** 产品名称 → cpmc */
public static final String PRODUCT_NAME = "DDSelectField_1XTHOHPHULNK0";
/** 产品应用领域 → cpyyly */
public static final String PRODUCT_DOMAIN = "TextField_1EIAVY538AM80";
/** 分栏 */
public static final String COLUMN_LAYOUT_MAIN = "ColumnLayout_N0ZDGQT4UJ40";
/** 刚性链类型 → gxllx */
public static final String RIGID_CHAIN_TYPE = "DDSelectField_JDD37MSAU7K0";
/** 台面尺寸 → tmcc */
public static final String TABLE_SIZE = "TextField_7KHHS2KML4G0";
/** 台面尺寸/外形轮廓 → tmccwxlk */
public static final String TABLE_OUTLINE = "TextField_1CTQW75A6XK00";
/** 外形尺寸(长宽高) → wxcc */
public static final String OUTLINE_SIZE = "TextField_6JT3ARDIUY40";
/** 基坑深度 → jksd */
public static final String PIT_DEPTH = "TextField_1JWDW5KVN95S0";
/** 行程 → xc */
public static final String STROKE = "TextField_17ONU2GWWQQK0";
/** 速度单位m/s或mm/s → sd */
public static final String SPEED = "TextField_2E68TAT1P2B";
/** 负载单位kg → fz */
public static final String LOAD = "TextField_1D66PIGUHPEO0";
/** 驱动方式 → qdfs */
public static final String DRIVE_MODE = "DDSelectField_12J1O9KUMFK00";
/** 限位方式 → xwfs */
public static final String LIMIT_MODE = "DDSelectField_1QQEC44I00G00";
/** 最低高度 → zdgd */
public static final String MIN_HEIGHT = "TextField_1FVHYJIFC9340";
/** 有无偏载 → ywpz */
public static final String ECCENTRIC_LOAD = "DDSelectField_1CTHXMP1W6000";
/** 设备形式 → sbxs */
public static final String DEVICE_FORM = "DDSelectField_1J17P5TOEU0W0";
/** 动载 → dz */
public static final String DYNAMIC_LOAD = "TextField_23GWUBGROXWG0";
/** 静载 → jz */
public static final String STATIC_LOAD = "TextField_SIM35ICCGOW0";
/** 电源电压 → dydy */
public static final String VOLTAGE = "TextField_1X4ISVYJ2E000";
/** 电压频率是否特殊 → dyplsfts */
public static final String VOLTAGE_FREQ_SPECIAL = "TextField_F05H5U3N9NC0";
/** 减速器要求 → jsqyq */
public static final String REDUCER_REQ = "TextField_J84FK4ALUOG0";
/** 导向形式 → dxxs */
public static final String GUIDE_FORM = "TextField_3IXTW5EOSTK0";
/** 有无脚轮 → ywjl */
public static final String CASTERS = "DDSelectField_4JP6PT1HB480";
/** 卷筒直径 → jtzj */
public static final String DRUM_DIAMETER = "TextField_1ED24R0QOG4G0";
/** 吊点数 → dds */
public static final String LIFT_POINTS = "TextField_IR0XM2QFI4G0";
/** 额定载荷 → edzh */
public static final String RATED_LOAD = "TextField_MWLXHEAJYDS0";
/** 杆体自重/总载荷 → gtzz */
public static final String ROD_WEIGHT = "TextField_GZISO77XGU80";
/** 有无载荷传感器 → ywzhcgq */
public static final String LOAD_SENSOR = "DDSelectField_1XGOO6QI7YE80";
/** 箱体形式 → xtxs */
public static final String BOX_FORM = "TextField_V3UBXSM0V400";
/** 出轴方式/方向 → czfsfx */
public static final String SHAFT_MODE = "TextField_1N6AOCMUFXXC0";
/** 地脚板位置 → djbwz */
public static final String FOOT_PLATE_POS = "TextField_5B1TRAUGUP80";
/** 行走速度 → xingzsd */
public static final String TRAVEL_SPEED = "TextField_G2N28LNPOKO0";
/** 是否带升降 → sfdjs */
public static final String WITH_LIFT = "DDSelectField_Y8AKWL5T20G0";
/** 升降高度 → sjgd */
public static final String LIFT_HEIGHT = "TextField_1X0CJO3BBELC0";
/** 升降速度 → sjsd */
public static final String LIFT_SPEED = "TextField_1DCKMEARM96O0";
/** 导航方式 → dhfs */
public static final String NAV_MODE = "DDSelectField_1UNDZ9DNXIN4";
/** 电机减速机种类 → djjsjzl */
public static final String MOTOR_REDUCER_TYPE = "TextField_CO3RY4XTL800";
/** 旋转速度 → xuanzsd */
public static final String ROTATE_SPEED = "TextField_QZAR20YC9DC0";
/** 使用频率 → sypl */
public static final String FREQ = "TextField_1N728V92Z1LS0";
/** 使用环境 → syhj */
public static final String ENV = "TextareaField_9MIMABZEHW40";
/** 电控要求 → dkyq */
public static final String ELECTRIC_REQ = "TextareaField_1WLKQPZU8UF40";
/** 安装位置(如有纵/横剖图可附件说明) → azwz */
public static final String INSTALL_POS = "TextareaField_1BXA83S0L9Q80";
/** 其他特殊要求 → qttsyq */
public static final String OTHER_SPECIAL = "TextareaField_15N86B1OM9R40";
/** 方案补充说明 → fapcsm */
public static final String SCHEME_NOTE = "TextareaField_ZCRQZCLP3800";
/** 分栏 */
public static final String COLUMN_LAYOUT_ATTACH = "ColumnLayout_PV2QMZXXVCW0";
/** 附件 */
public static final String ATTACHMENT_MAIN = "DDAttachment_XJYUB17OFGW0";
/** 技术总工意见 → jszgyj */
public static final String CHIEF_ENGINEER_OPINION = "TextareaField_GO981AG879K0";
/** 是否为机械标品(是 → zpdfzgcs 固定 00026 */
public static final String MECHANICAL_STANDARD_PRODUCT = "DDSelectField_8DWKMBIUJ4S0";
/** 项目负责副总工程师 / 指定副总工程师 → zpdfzgcs姓名映射工号 */
public static final String ASSIGNED_DEPUTY_CHIEF = "InnerContactField_1GEJYHX8RFQ80";
/** 旧版表单控件 id兼容历史 wf_values_json */
public static final String ASSIGNED_DEPUTY_CHIEF_LEGACY = "InnerContactField_1TXM18E414740";
}

View File

@ -0,0 +1,25 @@
package com.ruoyi.system.constant;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* PLM {@code sales/saleplanapplyform} 全部表单字段名
* 非必填字段也必须传参无值时传空字符串 {@code ""}不能缺 key 或传 null
*/
public final class DingSchemePlmFormKeys {
private DingSchemePlmFormKeys() {
}
public static final List<String> ALL = Collections.unmodifiableList(Arrays.asList(
"fasqbh", "mc", "gsmc", "tbr", "tbrq", "xqrq", "khgsqc", "lxrjdh",
"cpmc", "cpyyly", "tmcc", "xc", "zdgd", "qdfs", "ywpz", "xwfs",
"dydy", "syhj", "sypl", "ywjl", "dkyq", "fapcsm", "jksd", "dz", "jz",
"dyplsfts", "jsqyq", "dxxs", "azwz", "sbxs", "jtzj", "dds", "edzh",
"gtzz", "ywzhcgq", "xtxs", "czfsfx", "djbwz", "sfdjs", "sjgd", "sjsd",
"dhfs", "gxllx", "djjsjzl", "sd", "tsxc", "tssd", "tmccwxlk", "wxcc",
"fz", "xingzsd", "xuanzsd", "jszgyj", "zpdfzgcs", "qqdjgcs", "qttsyq"
));
}

View File

@ -0,0 +1,20 @@
package com.ruoyi.system.constant;
/**
* 项目令号 {@code process_order_pro.source} 来源
*/
public final class ProcessOrderProSource {
/** 页面/接口手工新增 */
public static final String MANUAL = "手动";
/** PLM 等外部系统同步 */
public static final String PLM = "PLM";
private ProcessOrderProSource() {
}
public static boolean isValid(String source) {
return MANUAL.equals(source) || PLM.equals(source);
}
}

View File

@ -0,0 +1,28 @@
package com.ruoyi.system.constant;
/**
* 采购订单审批待办钉钉提醒审批人姓名与 StaffId 映射写死在代码中
*/
public final class PurchaseOrderApproverNotifyConstants {
private PurchaseOrderApproverNotifyConstants() {
}
/** 刘冉 钉钉 StaffId */
public static final String LIU_RAN_STAFF_ID = "010858214800672369";
/** 张敏 钉钉 StaffId */
public static final String ZHANG_MIN_STAFF_ID = "1017253114780847";
/** 默认抄送(任务执行汇总,用于确认推送是否成功) */
public static final String DEFAULT_NOTIFY_STAFF_ID = "283633411029629036";
/** 工作流当前审批人姓名匹配:刘冉 */
public static final String LIU_RAN_NAME = "刘冉";
/** 工作流当前审批人姓名匹配:张敏(金蝶工作流中的真实姓名) */
public static final String ZHANG_MIN_NAME = "张敏";
/** 钉钉推送展示称呼:张总 */
public static final String ZHANG_MIN_DISPLAY_NAME = "张总";
}

View File

@ -0,0 +1,114 @@
package com.ruoyi.system.controller;
import cn.dev33.satoken.annotation.SaIgnore;
import com.alibaba.fastjson.JSON;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.dto.productionorder.AssemblyBomReceiveItemDTO;
import com.ruoyi.system.domain.dto.productionorder.AssemblyBomReceiveSummary;
import com.ruoyi.system.service.IPlmReceiveLogService;
import com.ruoyi.system.service.IProductionOrderService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* PLM 总装配 BOM 推送接收入口POST JSON 数组
*/
@Slf4j
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/system/plm")
public class AssemblyBomReceiveController extends BaseController {
private static final String API_PATH = "/system/plm/assemblyBomReceive";
private final IProductionOrderService productionOrderService;
private final IPlmReceiveLogService plmReceiveLogService;
/**
* 接收总装配 BOM 行列表按生产令号全量替换写入 production_order并同步 bom_detailsbomType=0
* <p>
* POST /system/plm/assemblyBomReceive<br>
* Content-Type: application/json; charset=UTF-8
*/
@SaIgnore
@Log(title = "总装配BOM推送接收", businessType = BusinessType.OTHER)
@PostMapping("/assemblyBomReceive")
public R<AssemblyBomReceiveSummary> receive(@Valid @RequestBody List<AssemblyBomReceiveItemDTO> body) {
String payloadJson = JSON.toJSONString(body);
String orderNo = resolveOrderNo(body);
String clientIp = resolveClientIp();
try {
AssemblyBomReceiveSummary summary = productionOrderService.receiveAssemblyBom(body);
Map<String, Object> summaryMap = new LinkedHashMap<>();
summaryMap.put("productionOrderNo", summary.getProductionOrderNo());
summaryMap.put("lineCount", summary.getLineCount());
summaryMap.put("insertedCount", summary.getInsertedCount());
summaryMap.put("replaced", summary.isReplaced());
plmReceiveLogService.record(
IPlmReceiveLogService.BIZ_ASSEMBLY_BOM,
API_PATH,
summary.getProductionOrderNo(),
payloadJson,
JSON.toJSONString(summaryMap),
summary.getLineCount(),
summary.getInsertedCount(),
summary.isReplaced(),
IPlmReceiveLogService.STATUS_SUCCESS,
null,
clientIp
);
return R.ok("接收成功", summary);
} catch (Exception e) {
plmReceiveLogService.record(
IPlmReceiveLogService.BIZ_ASSEMBLY_BOM,
API_PATH,
orderNo,
payloadJson,
null,
body == null ? 0 : body.size(),
null,
null,
IPlmReceiveLogService.STATUS_FAIL,
e.getMessage(),
clientIp
);
throw e;
}
}
private static String resolveOrderNo(List<AssemblyBomReceiveItemDTO> body) {
if (body == null) {
return null;
}
for (AssemblyBomReceiveItemDTO item : body) {
if (item != null && StringUtils.isNotBlank(item.getProductionOrderNo())) {
return item.getProductionOrderNo().trim();
}
}
return null;
}
private static String resolveClientIp() {
try {
return ServletUtils.getClientIP();
} catch (Exception ignored) {
return null;
}
}
}

View File

@ -29,9 +29,11 @@ import com.ruoyi.common.config.DingTalkProperties;
import com.ruoyi.common.dingding.util.DingUtil;
import com.ruoyi.common.utils.JdUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.system.constant.ProcessOrderProSource;
import com.ruoyi.system.domain.BomDetails;
import com.ruoyi.system.domain.MaterialProperties;
import com.ruoyi.system.domain.ProcessOrderPro;
import com.ruoyi.system.domain.ProductionOrder;
import com.ruoyi.system.domain.bo.BomDetailsBo;
import com.ruoyi.system.domain.vo.BomDetailsVo;
import com.ruoyi.system.domain.vo.ElectricalMaterialBomVO;
@ -84,7 +86,7 @@ public class BomDetailsController extends BaseController {
private final IProcessOrderProService iProcessOrderProService;
private final IProductionOrderService iProductionOrderService;
private final IProductionOrderService iProductionOrderService;
private final ProcessOrderProMapper processOrderProMapper;
@ -107,15 +109,18 @@ public class BomDetailsController extends BaseController {
List<BomDetailsVo> topLevelList = new ArrayList<>();
List<BomDetailsVo> rows = bomDetailsVoTableDataInfo.getRows();
for (BomDetailsVo bomDetailsVo : rows) {
String parentCodeAndName = String.format("%s_%s", bomDetailsVo.getFName(), bomDetailsVo.getFNumber());
String assemblyCode = resolveAssemblyCode(bomDetailsVo);
String parentCodeAndName = String.format("%s_%s", bomDetailsVo.getFName(), assemblyCode);
BomDetailsVo parent = bomMap.get(parentCodeAndName);
if (parent == null) {
parent = new BomDetailsVo();
parent.setId(generateUniqueParentId(bomDetailsVo.getId()));
// parent.setUnitWeight(bomDetailsVo.getUnitWeight());
parent.setParentCodeAndName(parentCodeAndName);
parent.setFNumber(bomDetailsVo.getFNumber());
parent.setFNumber(assemblyCode);
parent.setFName(bomDetailsVo.getFName());
parent.setPartdiagramCode(bomDetailsVo.getPartdiagramCode());
parent.setPartdiagramName(bomDetailsVo.getPartdiagramName());
parent.setUnitWeight(bomDetailsVo.getUnitWeight());
parent.setStats(bomDetailsVo.getStats());
parent.setMaterial(bomDetailsVo.getMaterial());
@ -142,21 +147,90 @@ public class BomDetailsController extends BaseController {
return originalId + 1000;
}
/** 总成物料编码:优先 f_number其次 partdiagram_code装备 BOM 导入常缺 f_number */
private String resolveAssemblyCode(BomDetailsVo vo) {
if (vo == null) {
return "";
}
if (StringUtils.isNotBlank(vo.getFNumber())) {
return vo.getFNumber().trim();
}
if (StringUtils.isNotBlank(vo.getPartdiagramCode())) {
return vo.getPartdiagramCode().trim();
}
return "";
}
private void normalizeAssemblyFNumber(List<BomDetails> bomDetails, String assemblyCode) {
if (bomDetails == null || bomDetails.isEmpty() || StringUtils.isBlank(assemblyCode)) {
return;
}
for (BomDetails row : bomDetails) {
if (StringUtils.isBlank(row.getFNumber())) {
row.setFNumber(assemblyCode);
}
}
}
/**
* 父级物料 f_number 建档仅使用 bom_details.dan_zhong不再查其它表
*/
private void writeKingdeeParentDanZhong(JsonObject model, BomDetails row, String scene) {
if (row == null || StringUtils.isBlank(row.getFNumber())) {
log.info("[金蝶单重上传] {} | 父级 | FNumber=空 | F_HBYT_DZ=未写入 | 来源=无", scene);
return;
}
String fNumber = row.getFNumber().trim();
String fName = row.getFName() != null ? row.getFName() : "";
Double dz = row.getDanZhong();
String source = dz != null ? "bom_details.dan_zhong" : "";
log.info("[金蝶单重上传] {} | 父级 | FNumber={} | FName={} | F_HBYT_DZ={} | 来源={}",
scene, fNumber, fName, dz != null ? dz : "未写入", source);
if (dz != null) {
model.addProperty("F_HBYT_DZ", dz);
}
}
/**
* 子项物料 part_number 建档仅使用 bom_details.single_weghit不再查其它表
*/
private void writeKingdeeChildDanZhong(JsonObject model, BomDetails row, String scene) {
if (row == null || StringUtils.isBlank(row.getPartNumber())) {
log.info("[金蝶单重上传] {} | 子项 | FNumber=空 | F_HBYT_DZ=未写入 | 来源=无", scene);
return;
}
String partNumber = row.getPartNumber().trim();
String name = row.getName() != null ? row.getName() : "";
Double dz = row.getSingleWeghit();
String source = dz != null ? "bom_details.single_weghit" : "";
log.info("[金蝶单重上传] {} | 子项 | FNumber={} | FName={} | F_HBYT_DZ={} | 来源={}",
scene, partNumber, name, dz != null ? dz : "未写入", source);
if (dz != null) {
model.addProperty("F_HBYT_DZ", dz);
}
}
private BomDetailsVo createChildVo(BomDetailsVo bomDetailsVo) {
BomDetailsVo child = null;
child = new BomDetailsVo();
BomDetailsVo child = new BomDetailsVo();
child.setId(bomDetailsVo.getId());
child.setTotalWeight(bomDetailsVo.getTotalWeight());
child.setFNumber(resolveAssemblyCode(bomDetailsVo));
child.setFName(bomDetailsVo.getFName());
child.setPartNumber(bomDetailsVo.getPartNumber());
child.setName(bomDetailsVo.getName());
child.setPartdiagramCode(bomDetailsVo.getPartdiagramCode());
child.setPartdiagramName(bomDetailsVo.getPartdiagramName());
child.setQuantity(bomDetailsVo.getQuantity());
child.setDenominator(bomDetailsVo.getDenominator());
child.setStats(bomDetailsVo.getStats());
child.setMaterial(bomDetailsVo.getMaterial());
child.setRemarks(bomDetailsVo.getRemarks());
// child.setTotalWeight(bomDetailsVo.getTotalWeight());
child.setWareHouse(bomDetailsVo.getWareHouse());
child.setUnitWeight(bomDetailsVo.getUnitWeight());
// 其他必要的字段赋值
child.setDanZhong(bomDetailsVo.getDanZhong());
child.setSingleWeghit(bomDetailsVo.getSingleWeghit());
child.setBomType(bomDetailsVo.getBomType());
child.setStateImportance(bomDetailsVo.getStateImportance());
child.setRemarks(bomDetailsVo.getRemarks());
return child;
}
@ -331,9 +405,7 @@ public class BomDetailsController extends BaseController {
* @return
*/
public static String determineState(BomDetails stats) {
if (stats == null || stats.getStats().equals("外购") || stats.getFName().startsWith("009") ||
stats.getFName().startsWith("AA") || stats.getFName().startsWith("AB")
|| stats.getFName().startsWith("AC")) {
if (stats == null || stats.getStats().equals("外购") || stats.getFName().startsWith("009") || stats.getFName().startsWith("AA") || stats.getFName().startsWith("AB") || stats.getFName().startsWith("AC")) {
return "1";
} else if (stats.getStats().equals("自制")) {
return "2";
@ -343,6 +415,28 @@ public class BomDetailsController extends BaseController {
return "1";
}
/**
* 是否走生产物料建档与总装一致
* <ul>
* <li>bomType=0 总装 生产建档</li>
* <li>PLM 项目 / PLM 推送的材料 BOMbomType=1 生产建档 stats 写自制/外购</li>
* <li>仅非 PLM 的电气 Excel BOMbomType=1 电气建档</li>
* </ul>
*/
private static boolean useProductionMaterialSave(BomDetails material, ProcessOrderPro project) {
if (material == null) {
return true;
}
if ("0".equals(material.getBomType())) {
return true;
}
if (project != null && ProcessOrderProSource.PLM.equals(project.getSource())) {
return true;
}
return "PLM".equalsIgnoreCase(material.getCreateBy())
|| "PLM".equalsIgnoreCase(material.getUpdateBy());
}
/* 触发金蝶物料清单按钮 */
@Log(title = "金蝶物料清单更新")
@SaCheckPermission("system:details:updateMaterial")
@ -376,22 +470,41 @@ public class BomDetailsController extends BaseController {
@SaCheckPermission("system:details:updateFBMaterial")
@PostMapping("/updateFBMaterial")
public R updateFBMaterial(@RequestBody List<Map<String, String>> bomDetailParams) {
if (bomDetailParams == null || bomDetailParams.isEmpty()) {
return R.fail("请先选择要上传的物料");
}
List<BomDetails> bomDetailsList = new ArrayList<>();
List<KindegeeLogDTO> logDTOS = new ArrayList<>();
List<String> failedMaterials = new ArrayList<>(); // 用于跟踪处理失败的物料
String totalWeight = "";
// 遍历前端传来的数据
for (Map<String, String> param : bomDetailParams) {
String fnumber = param.get("fnumber"); // 物料编码
String groupName = param.get("groupName"); // 物料编码
String fnumber = param.get("fnumber"); // 总成物料编码父项图号
String fname = param.get("fname"); // 总成名称父项名称
String groupName = param.get("groupName"); // 上传分组
totalWeight = param.get("totalWeight"); // 生产令号
// 根据物料编码和生产令号查询
List<BomDetails> bomDetails = iBomDetailsService.selectByFNumberAndTotalWeight(fnumber, totalWeight);
log.info("处理物料编码: {}, 生产令号: {}", fnumber, totalWeight);
List<BomDetails> bomDetails = null;
if (StringUtils.isNotBlank(fnumber)) {
bomDetails = iBomDetailsService.selectByFNumberAndTotalWeight(fnumber, totalWeight);
}
if (bomDetails != null && !bomDetails.isEmpty()) {
String assemblyCode = StringUtils.isNotBlank(fnumber) ? fnumber : resolveAssemblyCode(BeanUtil.toBean(bomDetails.get(0), BomDetailsVo.class));
normalizeAssemblyFNumber(bomDetails, assemblyCode);
if (StringUtils.isBlank(fnumber)) {
fnumber = assemblyCode;
}
}
log.info("处理物料编码: {}, 总成名称: {}, 生产令号: {}", fnumber, fname, totalWeight);
if (bomDetails != null && !bomDetails.isEmpty()) {
//TODO 处理父级物料
ProcessOrderPro bo = iProcessOrderProService.selectByProjectNumber(totalWeight);
if (bo == null) {
log.error("未找到生产令号对应的项目, 令号: {}", totalWeight);
failedMaterials.add(fnumber);
continue;
}
// 第一步处理所有物料的保存
for (BomDetails material : bomDetails) {
// 获取工艺表中的非委外工时
@ -404,33 +517,19 @@ public class BomDetailsController extends BaseController {
continue;
}
String state = determineState(material);
//判断bom类型是生产还是电气
if (material.getBomType().equals("0")) {
try {
int result = loadMaterialPreservation(material, state, fbWorkTime);
if (result == 1) {
material.setUnitWeight("新增成功");
} else {
failedMaterials.add(material.getPartNumber());
}
// 更新物料状态
iBomDetailsService.updateByBo(BeanUtil.toBean(material, BomDetailsBo.class));
} catch (Exception e) {
failedMaterials.add(material.getPartNumber());
}
} else {
try {
int result = loadMaterialToDQ(material, state);
if (result == 1) {
material.setUnitWeight("新增成功");
} else {
failedMaterials.add(material.getPartNumber());
}
// 更新物料状态
iBomDetailsService.updateByBo(BeanUtil.toBean(material, BomDetailsBo.class));
} catch (Exception e) {
// 总装(bomType=0) PLM 工艺材料BOM(bomType=1)均走生产建档仅非 PLM 的电气 BOM 走电气建档
try {
int result = useProductionMaterialSave(material, bo)
? loadMaterialPreservation(material, state, fbWorkTime)
: loadMaterialToDQ(material, state);
if (result == 1) {
material.setUnitWeight("新增成功");
} else {
failedMaterials.add(material.getPartNumber());
}
iBomDetailsService.updateByBo(BeanUtil.toBean(material, BomDetailsBo.class));
} catch (Exception e) {
failedMaterials.add(material.getPartNumber());
}
} else {
@ -476,8 +575,14 @@ public class BomDetailsController extends BaseController {
}
}
}
if (StringUtils.isBlank(totalWeight)) {
return R.fail("生产令号不能为空");
}
//更新项目进度
ProcessOrderPro processOrderProBo = iProcessOrderProService.selectByProjectNumber(totalWeight);
if (processOrderProBo == null) {
return R.fail("未找到生产令号对应的项目: " + totalWeight);
}
processOrderProBo.setDrawingType(JSONUtil.toJsonStr(logDTOS));
processOrderProBo.setBomStatus(2L);
processOrderProMapper.updateById(processOrderProBo);
@ -835,6 +940,9 @@ public class BomDetailsController extends BaseController {
JsonArray fTreeEntity = new JsonArray();
model.add("FTreeEntity", fTreeEntity);
List<JsonObject> fTreeEntityList = new ArrayList<>();
// PLM 总装production_order.prtType=伊特 Excel 备注伊特同口径 FSupplyType=C采购
String orderNo = bo != null ? bo.getProductionOrderNo() : bomDetails1.getTotalWeight();
Set<String> yiteDrawingNos = loadYiteDrawingNosFromProductionOrder(orderNo);
for (BomDetails details : bomlist) {
if (bomlist.isEmpty()) {
return null;
@ -855,8 +963,10 @@ public class BomDetailsController extends BaseController {
if (iProcessRouteService.isAnTuDingGou(partNumber)) {
supplyType = "C";
}
// 检查是否为伊特
else if ("伊特".equals(remarks)) {
// 伊特Excel 备注 / 材质含伊特 / PLM prtType=伊特
else if (isYiteText(remarks)
|| isYiteText(details.getMaterial())
|| yiteDrawingNos.contains(partNumber)) {
supplyType = "C";
}
}
@ -912,6 +1022,33 @@ public class BomDetailsController extends BaseController {
}
}
/**
* production_order 收集 prtType/备注/材质为伊特的子项图号PLM 总装推送口径
*/
private Set<String> loadYiteDrawingNosFromProductionOrder(String productionOrderNo) {
Set<String> result = new HashSet<>();
if (StringUtils.isBlank(productionOrderNo)) {
return result;
}
List<ProductionOrder> orders = iProductionOrderService.selectByProCode(productionOrderNo);
if (orders == null || orders.isEmpty()) {
return result;
}
for (ProductionOrder order : orders) {
if (order == null || StringUtils.isBlank(order.getDrawingNo())) {
continue;
}
if (isYiteText(order.getPrtType()) || isYiteText(order.getRemark()) || isYiteText(order.getMaterial())) {
result.add(order.getDrawingNo().trim());
}
}
return result;
}
private static boolean isYiteText(String text) {
return StringUtils.isNotBlank(text) && ("伊特".equals(text.trim()) || text.contains("伊特"));
}
/*
* 父级物料保存接口
* 单位 是台
@ -935,20 +1072,7 @@ public class BomDetailsController extends BaseController {
JsonObject FSVRIAssistant = new JsonObject();
FSVRIAssistant.addProperty("FNumber", materialProperties.getMaterialAttributeId());
model.add("F_SVRI_Assistant", FSVRIAssistant);
// 单重 Excel 批量匹配逻辑一致production_order.drawing_no process_route.material_code图号用物料编码 partNumber库中未查到则为 null
Double dz = iProductionOrderService.resolveSingleWeightByMaterialCode(bomDetails.getPartNumber());
if (dz == null) {
if (bomDetails.getDanZhong() != null && bomDetails.getSingleWeghit() != null) {
dz = bomDetails.getSingleWeghit();
} else if (bomDetails.getDanZhong() != null) {
dz = bomDetails.getDanZhong();
} else if (bomDetails.getSingleWeghit() != null) {
dz = bomDetails.getSingleWeghit();
}
}
if (dz != null) {
model.addProperty("F_HBYT_DZ", dz);
}
writeKingdeeParentDanZhong(model, bomDetails, "父级物料建档");
// 创建FMaterialGroup对象并加入Model
JsonObject fMaterialGroup = new JsonObject();
fMaterialGroup.addProperty("FNumber", "XM-100");
@ -1140,20 +1264,7 @@ public class BomDetailsController extends BaseController {
model.add("FMaterialGroup", fMaterialGroup);
model.addProperty("FIsHandleReserve", true);
// 单重 Excel 批量匹配逻辑一致production_order.drawing_no process_route.material_code图号用物料编码 partNumber库中未查到则为 null
Double dz = iProductionOrderService.resolveSingleWeightByMaterialCode(bomDetail.getPartNumber());
if (dz == null) {
if (bomDetail.getDanZhong() != null && bomDetail.getSingleWeghit() != null) {
dz = bomDetail.getSingleWeghit();
} else if (bomDetail.getDanZhong() != null) {
dz = bomDetail.getDanZhong();
} else if (bomDetail.getSingleWeghit() != null) {
dz = bomDetail.getSingleWeghit();
}
}
if (dz != null) {
model.addProperty("F_HBYT_DZ", dz);
}
writeKingdeeParentDanZhong(model, bomDetail, "FB父级物料建档");
// 创建SubHeadEntity对象并加入Model
JsonObject subHeadEntity = new JsonObject();
model.add("SubHeadEntity", subHeadEntity);
@ -1551,21 +1662,9 @@ public class BomDetailsController extends BaseController {
json.add("Model", model);
model.addProperty("FMATERIALID", 0);
// 单重 Excel 批量匹配逻辑一致production_order.drawing_no process_route.material_code图号用物料编码 partNumber库中未查到则为 null
Double dz = iProductionOrderService.resolveSingleWeightByMaterialCode(bomDetails1.getPartNumber());
if (dz == null) {
if (bomDetails1.getDanZhong() != null && bomDetails1.getSingleWeghit() != null) {
dz = bomDetails1.getSingleWeghit();
} else if (bomDetails1.getDanZhong() != null) {
dz = bomDetails1.getDanZhong();
} else if (bomDetails1.getSingleWeghit() != null) {
dz = bomDetails1.getSingleWeghit();
}
}
if (dz != null) {
model.addProperty("F_HBYT_DZ", dz);
}
model.addProperty("FSpecification", bomDetails1.getRemarks());
writeKingdeeChildDanZhong(model, bomDetails1, "子项物料建档");
// 规格存材质与电气建档 loadMaterialToDQ 一致原先误用 remarksPLM remarks 常为单位
model.addProperty("FSpecification", bomDetails1.getMaterial());
model.addProperty("FNumber", bomDetails1.getPartNumber());
model.addProperty("FName", bomDetails1.getName());
model.addProperty("F_HBYT_ZYCD", bomDetails1.getStateImportance() != null ? bomDetails1.getStateImportance() : "");
@ -1575,7 +1674,7 @@ public class BomDetailsController extends BaseController {
FSVRIAssistant.addProperty("FNumber", materialProperties.getMaterialAttributeId());
model.add("F_SVRI_Assistant", FSVRIAssistant);
} else {
// 没写材料为默认为空
// 字典未命中时默认成品(17)
JsonObject FSVRIAssistant = new JsonObject();
FSVRIAssistant.addProperty("FNumber", "17");
model.add("F_SVRI_Assistant", FSVRIAssistant);
@ -1858,6 +1957,7 @@ public class BomDetailsController extends BaseController {
model.addProperty("FMATERIALID", 0);
model.addProperty("FSpecification", bomDetails1.getMaterial());// 规格 为存入的材质字段
model.addProperty("F_HBYT_PP", bomDetails1.getWareHouse());// 品牌 为存入的仓库字段
writeKingdeeChildDanZhong(model, bomDetails1, "电气子项物料建档");
model.addProperty("FNumber", bomDetails1.getPartNumber());
model.addProperty("FName", bomDetails1.getName());
MaterialProperties materialProperties = iMaterialPropertiesService.selectByAttribute(bomDetails1.getMaterial());
@ -1866,7 +1966,7 @@ public class BomDetailsController extends BaseController {
FSVRIAssistant.addProperty("FNumber", materialProperties.getMaterialAttributeId());
model.add("F_SVRI_Assistant", FSVRIAssistant);
} else {
// 没写材料为默认为空
// 字典未命中时默认成品(17)
JsonObject FSVRIAssistant = new JsonObject();
FSVRIAssistant.addProperty("FNumber", "17");
model.add("F_SVRI_Assistant", FSVRIAssistant);
@ -1881,15 +1981,17 @@ public class BomDetailsController extends BaseController {
// 创建SubHeadEntity对象并加入Model
JsonObject subHeadEntity = new JsonObject();
model.add("SubHeadEntity", subHeadEntity);
if (bomDetails1.getWareHouse().contains("伊特")) {
subHeadEntity.addProperty("FErpClsID", "2");
// 与生产建档一致 determineState 结果写物料属性1外购/2自制/3委外不再仅凭仓库含伊特默认外购
String erpClsId = StringUtils.isNotBlank(states) ? states : "1";
if (StringUtils.isNotBlank(bomDetails1.getWareHouse()) && bomDetails1.getWareHouse().contains("伊特")) {
erpClsId = "2";
}
subHeadEntity.addProperty("FErpClsID", "1");
subHeadEntity.addProperty("FErpClsID", erpClsId);
subHeadEntity.addProperty("FFeatureItem", "1");
// 创建FCategoryID对象并加入SubHeadEntity
JsonObject fCategoryID = new JsonObject();
if (states.equals("2") || states.equals("3")) {
if (erpClsId.equals("2") || erpClsId.equals("3")) {
fCategoryID.addProperty("FNumber", "007");
} else {
fCategoryID.addProperty("FNumber", "006");
@ -2318,14 +2420,15 @@ public class BomDetailsController extends BaseController {
bomDetails.setName(bomVO.getDrawingName());
bomDetails.setMaterial(bomVO.getModel());
bomDetails.setWareHouse(bomVO.getBrand());
if(bomVO.getBrand().contains("伊特")){
String brand = bomVO.getBrand();
if (brand != null && brand.contains("伊特")) {
bomDetails.setStats("自制");
} else {
bomDetails.setStats("外购");
}
bomDetails.setStats("外购");
bomDetails.setQuantity(bomVO.getQuantity() == null ? null : bomVO.getQuantity().toString());
bomDetails.setRemarks(bomVO.getUnit());
bomDetails.setUpdateTime(new Date());
bomDetails.setQuantity(String.valueOf(bomVO.getQuantity()));
bomDetails.setDenominator(1.0);
bomDetails.setBomType("1");
list.add(bomDetails);

View File

@ -18,6 +18,7 @@ import com.ruoyi.common.core.validate.AddGroup;
import com.ruoyi.common.core.validate.EditGroup;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.JdUtils;
import com.ruoyi.common.utils.KingdeeMaterialCategoryHelper;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.system.domain.BomDetails;
import com.ruoyi.system.domain.BomVariable;
@ -425,7 +426,8 @@ public class BomVariableController extends BaseController {
}
// 创建FCategoryID对象并加入SubHeadEntity
JsonObject fCategoryID = new JsonObject();
fCategoryID.addProperty("FNumber", "007");
fCategoryID.addProperty("FNumber", KingdeeMaterialCategoryHelper.resolveChildCategoryFNumber(
states, partNumber));
subHeadEntity.add("FCategoryID", fCategoryID);
// 创建FTaxRateId对象并加入SubHeadEntity

View File

@ -0,0 +1,69 @@
package com.ruoyi.system.controller;
import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.annotation.SaCheckPermission;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.system.domain.bo.DingSchemeApplicationBo;
import com.ruoyi.system.domain.vo.DingSchemeApplicationDetailVo;
import com.ruoyi.system.domain.vo.DingSchemeApplicationVo;
import com.ruoyi.system.service.IDingSchemeApplicationPlmPushService;
import com.ruoyi.system.service.IDingSchemeApplicationService;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.constraints.NotNull;
/**
* 钉钉技术方案申请归档 查询与 PLM 推送管理
*/
@Validated
@RestController
@RequiredArgsConstructor
@RequestMapping("/system/ding/scheme")
public class DingSchemeApplicationController extends BaseController {
private final IDingSchemeApplicationService dingSchemeApplicationService;
private final IDingSchemeApplicationPlmPushService plmPushService;
/**
* 分页查询技术方案申请归档
*/
@SaCheckPermission("system:dingSchemeApplication:list")
@GetMapping("/list")
public TableDataInfo<DingSchemeApplicationVo> list(DingSchemeApplicationBo bo, PageQuery pageQuery) {
return dingSchemeApplicationService.queryPageList(bo, pageQuery);
}
/**
* 技术方案申请详情 formLabelMapwfValuesJson
*/
@SaCheckPermission("system:dingSchemeApplication:query")
@GetMapping("/{id}")
public R<DingSchemeApplicationDetailVo> getInfo(@NotNull(message = "主键不能为空") @PathVariable Long id) {
return R.ok(dingSchemeApplicationService.queryDetail(id));
}
/**
* 手动推送 PLM
*/
@SaCheckLogin
@PostMapping("/{id}/push-plm")
public R<Void> pushPlm(@PathVariable Long id, @RequestParam(defaultValue = "false") boolean force) {
try {
boolean pushed = plmPushService.pushById(id, force);
return pushed ? R.ok() : R.fail("未执行推送(已成功、未启用或记录不存在)");
} catch (ServiceException ex) {
return R.fail(ex.getMessage());
}
}
}

View File

@ -22,13 +22,18 @@ import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.excel.ExcelResult;
import com.ruoyi.common.utils.JdUtils;
import com.ruoyi.system.domain.BomDetails;
import com.ruoyi.system.domain.EleMaterials;
import com.ruoyi.system.domain.ImMaterial;
import com.ruoyi.system.domain.MaterialProperties;
import com.ruoyi.system.domain.PartCost;
import com.ruoyi.system.domain.ProcessRoute;
import com.ruoyi.system.domain.dto.*;
import com.ruoyi.system.domain.vo.ExcelVo;
import com.ruoyi.system.mapper.BomDetailsMapper;
import com.ruoyi.system.mapper.ImMaterialMapper;
import com.ruoyi.system.mapper.PartCostMapper;
import com.ruoyi.system.mapper.ProcessRouteMapper;
import com.ruoyi.system.runner.JdUtil;
import lombok.RequiredArgsConstructor;
import javax.servlet.http.HttpServletResponse;
@ -47,9 +52,11 @@ import com.ruoyi.common.core.validate.AddGroup;
import com.ruoyi.common.core.validate.EditGroup;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.system.domain.MaterialProperties;
import com.ruoyi.system.domain.vo.EleMaterialsVo;
import com.ruoyi.system.domain.bo.EleMaterialsBo;
import com.ruoyi.system.service.IEleMaterialsService;
import com.ruoyi.system.service.IMaterialPropertiesService;
import com.ruoyi.common.core.page.TableDataInfo;
import org.springframework.web.multipart.MultipartFile;
@ -69,6 +76,9 @@ public class EleMaterialsController extends BaseController {
private final ImMaterialMapper materialMapper;
private static final Logger log = LoggerFactory.getLogger(EleMaterialsController.class);
private final PartCostMapper partCostMapper;
private final IMaterialPropertiesService iMaterialPropertiesService;
private final BomDetailsMapper bomDetailsMapper;
private final ProcessRouteMapper processRouteMapper;
/**
* 查询电器物料管理列表
@ -557,6 +567,183 @@ public class EleMaterialsController extends BaseController {
return R.ok("更新成功");
}
/**
* Excel 批量更新金蝶物料材质规格 + 材质辅助资料
* Excel 只需物料编码物料名称可选材质从本地库匹配
* bom_details.part_number material找不到再查 process_route.material_code material
*/
@Log(title = "更新物料材质", businessType = BusinessType.IMPORT)
@SaCheckPermission("system:route:updateDanzhong")
@PostMapping(value = "/updateCaizhi", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public R<String> updateCaizhi(@RequestParam("file") MultipartFile file) throws Exception {
String originalFilename = file.getOriginalFilename();
log.info("更新材质,读取文件: {}", originalFilename);
ExcelResult<JdCaiZhi> result = ExcelUtil.importExcelSheet1(file.getInputStream(), JdCaiZhi.class, true);
List<JdCaiZhi> list = result.getList();
if (list == null || list.isEmpty()) {
return R.fail("Excel 无有效数据");
}
List<String> codes = list.stream()
.filter(Objects::nonNull)
.map(JdCaiZhi::getMaterialCode)
.filter(StringUtils::isNotBlank)
.map(String::trim)
.distinct()
.collect(Collectors.toList());
if (codes.isEmpty()) {
return R.fail("Excel 无有效物料编码");
}
Map<String, String> codeToMaterial = resolveMaterialFromDb(codes);
long totalRows = 0;
long submitted = 0;
long skippedBlank = 0;
long skippedNoDbMaterial = 0;
long skippedNoDict = 0;
int failedTasks = 0;
List<String> notFoundCodes = Collections.synchronizedList(new ArrayList<>());
List<String> noDbMaterials = new ArrayList<>();
List<String> noDictMaterials = Collections.synchronizedList(new ArrayList<>());
ExecutorService executor = Executors.newFixedThreadPool(10);
List<Future<Void>> futures = new ArrayList<>();
try {
for (JdCaiZhi row : list) {
totalRows++;
if (row == null || StringUtils.isBlank(row.getMaterialCode())) {
skippedBlank++;
continue;
}
final String materialCode = row.getMaterialCode().trim();
String materialFromDb = codeToMaterial.get(materialCode);
if (StringUtils.isBlank(materialFromDb)) {
skippedNoDbMaterial++;
noDbMaterials.add(materialCode);
log.warn("本地库未匹配到材质,跳过: {}", materialCode);
continue;
}
final String materialName = materialFromDb.trim();
MaterialProperties props = iMaterialPropertiesService.selectByAttribute(materialName);
final String attributeId;
if (props != null && StringUtils.isNotBlank(props.getMaterialAttributeId())) {
attributeId = props.getMaterialAttributeId();
} else {
attributeId = "17";
skippedNoDict++;
noDictMaterials.add(materialCode + "(" + materialName + ")");
log.warn("材质字典未命中默认成品17: code={}, material={}", materialCode, materialName);
}
futures.add(executor.submit(() -> {
List<JdEntryVmi> entryID = JdUtil.getEntryID2(materialCode);
if (entryID == null || entryID.isEmpty()) {
notFoundCodes.add(materialCode);
log.warn("金蝶未查到物料编码: {}", materialCode);
return null;
}
for (JdEntryVmi jdEntryVmi : entryID) {
int fmaterialid = jdEntryVmi.getFMATERIALID();
log.info("开始更新材质 code={}, fmaterialid={}, attributeId={}, material={}",
materialCode, fmaterialid, attributeId, materialName);
JdUtil.updateCaizhi(fmaterialid, attributeId, materialName);
}
return null;
}));
submitted++;
}
for (Future<Void> future : futures) {
try {
future.get();
} catch (ExecutionException e) {
failedTasks++;
log.error("更新物料材质任务异常: {}", e.getCause() != null ? e.getCause().getMessage() : e.getMessage(), e);
}
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
log.error("更新物料材质被中断", e);
return R.fail("任务被中断");
} finally {
executor.shutdown();
try {
if (!executor.awaitTermination(60, TimeUnit.MINUTES)) {
executor.shutdownNow();
}
} catch (InterruptedException e) {
executor.shutdownNow();
Thread.currentThread().interrupt();
}
}
String summary = String.format(
"扫描行=%d, 提交=%d, 跳过空编码=%d, 库中无材质=%d, 字典未命中默认17=%d, 金蝶未找到=%d, 失败任务=%d",
totalRows, submitted, skippedBlank, skippedNoDbMaterial, skippedNoDict, notFoundCodes.size(), failedTasks);
log.info("updateCaizhi 完成: {}, 库中无材质样例={}, 未找到编码样例={}, 未命中字典样例={}",
summary,
noDbMaterials.stream().limit(20).collect(Collectors.toList()),
notFoundCodes.stream().limit(20).collect(Collectors.toList()),
noDictMaterials.stream().limit(20).collect(Collectors.toList()));
if (failedTasks > 0) {
return R.fail("部分失败: " + summary);
}
return R.ok(summary);
}
/**
* 按物料编码从本地库解析材质优先 bom_details其次 process_route
*/
private Map<String, String> resolveMaterialFromDb(List<String> codes) {
Map<String, String> map = new HashMap<>();
if (codes == null || codes.isEmpty()) {
return map;
}
final int batchSize = 500;
for (int i = 0; i < codes.size(); i += batchSize) {
List<String> batch = codes.subList(i, Math.min(i + batchSize, codes.size()));
List<BomDetails> bomRows = bomDetailsMapper.selectList(
Wrappers.<BomDetails>lambdaQuery()
.in(BomDetails::getPartNumber, batch)
.isNotNull(BomDetails::getMaterial)
.ne(BomDetails::getMaterial, "")
.select(BomDetails::getPartNumber, BomDetails::getMaterial, BomDetails::getId)
.orderByDesc(BomDetails::getId));
for (BomDetails row : bomRows) {
if (row == null || StringUtils.isBlank(row.getPartNumber()) || StringUtils.isBlank(row.getMaterial())) {
continue;
}
map.putIfAbsent(row.getPartNumber().trim(), row.getMaterial().trim());
}
List<String> missing = batch.stream()
.filter(c -> !map.containsKey(c))
.collect(Collectors.toList());
if (missing.isEmpty()) {
continue;
}
List<ProcessRoute> routeRows = processRouteMapper.selectList(
Wrappers.<ProcessRoute>lambdaQuery()
.in(ProcessRoute::getMaterialCode, missing)
.isNotNull(ProcessRoute::getMaterial)
.ne(ProcessRoute::getMaterial, "")
.select(ProcessRoute::getMaterialCode, ProcessRoute::getMaterial, ProcessRoute::getId)
.orderByDesc(ProcessRoute::getId));
for (ProcessRoute row : routeRows) {
if (row == null || StringUtils.isBlank(row.getMaterialCode()) || StringUtils.isBlank(row.getMaterial())) {
continue;
}
map.putIfAbsent(row.getMaterialCode().trim(), row.getMaterial().trim());
}
}
return map;
}
@Log(title = "更新VMI仓位", businessType = BusinessType.IMPORT)
@SaCheckPermission("system:route:updaDateCangwei")

View File

@ -0,0 +1,111 @@
package com.ruoyi.system.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.vo.KingdeeMaterialDocHubVo;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.system.domain.dto.ProcessReportDTO;
import com.ruoyi.system.domain.dto.SubcontractOperationTransferRowDTO;
import com.ruoyi.system.domain.vo.MaterialDocHubBoardVo;
import com.ruoyi.system.domain.vo.MaterialDocHubDetailVo;
import com.ruoyi.system.domain.vo.MaterialDocHubProjectVo;
import com.ruoyi.system.service.IKingdeeMaterialDocHubService;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* 金蝶生产单据整合按生产令号从总装配 BOM 出发聚合库存MO/PO工序计划汇报入库委外
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/system/kingdee/materialDocHub")
public class KingdeeMaterialDocHubController {
private final IKingdeeMaterialDocHubService kingdeeMaterialDocHubService;
/**
* 按生产令号查询整合数据BOM 主轴
* <p>示例{@code GET /system/kingdee/materialDocHub/query?sclh=QB-26-106-LT}</p>
*/
@SaCheckPermission("system:mssql:query")
@GetMapping("/query")
public R<KingdeeMaterialDocHubVo> query(@RequestParam("sclh") String sclh) {
if (StringUtils.isBlank(sclh)) {
throw new ServiceException("生产令号不能为空");
}
return R.ok(kingdeeMaterialDocHubService.queryBySclh(sclh.trim()));
}
/**
* 工序计划看板分页默认每页 20最大 100令号可选
*/
@SaCheckPermission("system:mssql:query")
@GetMapping("/board/page")
public TableDataInfo<MaterialDocHubProjectVo> boardPage(
@RequestParam(value = "sclh", required = false) String sclh,
PageQuery pageQuery) {
if (pageQuery.getPageSize() == null) {
pageQuery.setPageSize(20);
}
return kingdeeMaterialDocHubService.queryBoardPage(
StringUtils.isNotBlank(sclh) ? sclh.trim() : null, pageQuery);
}
/**
* 展开工单仅工序计划按工序号排序
*/
@SaCheckPermission("system:mssql:query")
@GetMapping("/board/detail")
public R<MaterialDocHubDetailVo> boardDetail(
@RequestParam("moBillNo") String moBillNo,
@RequestParam("materialNumber") String materialNumber) {
return R.ok(kingdeeMaterialDocHubService.queryBoardDetail(moBillNo, materialNumber));
}
/** 按需加载:工序汇报 */
@SaCheckPermission("system:mssql:query")
@GetMapping("/board/reports")
public R<List<ProcessReportDTO>> boardReports(
@RequestParam("moBillNo") String moBillNo,
@RequestParam(value = "materialNumber", required = false) String materialNumber,
@RequestParam(value = "operNumber", required = false) String operNumber) {
return R.ok(kingdeeMaterialDocHubService.queryBoardReports(moBillNo, materialNumber, operNumber));
}
/** 按需加载:入库点质检与生产入库 */
@SaCheckPermission("system:mssql:query")
@GetMapping("/board/instockQc")
public R<List<ProcessReportDTO>> boardInstockQc(
@RequestParam("moBillNo") String moBillNo,
@RequestParam(value = "materialNumber", required = false) String materialNumber,
@RequestParam(value = "operNumber", required = false) String operNumber) {
return R.ok(kingdeeMaterialDocHubService.queryBoardInstockQc(moBillNo, materialNumber, operNumber));
}
/** 按需加载:委外 C/G */
@SaCheckPermission("system:mssql:query")
@GetMapping("/board/subcontract")
public R<List<SubcontractOperationTransferRowDTO>> boardSubcontract(
@RequestParam("moBillNo") String moBillNo) {
return R.ok(kingdeeMaterialDocHubService.queryBoardSubcontract(moBillNo));
}
/**
* @deprecated 全量查询易超时请使用 /board/page
*/
@SaCheckPermission("system:mssql:query")
@GetMapping("/board")
public R<MaterialDocHubBoardVo> board(@RequestParam(value = "sclh", required = false) String sclh) {
throw new ServiceException("请使用分页接口 /board/page");
}
}

View File

@ -32,4 +32,10 @@ public class KingdeeOrderTraceController {
KingdeeOrderTraceVo data = mssqlQueryService.queryOrderTrace(bo);
return R.ok(data);
}
@SaCheckPermission("system:mssql:query")
@GetMapping("/all")
public R<KingdeeOrderTraceVo> all() {
return R.ok(mssqlQueryService.queryOrderTraceAll());
}
}

View File

@ -0,0 +1,106 @@
package com.ruoyi.system.controller;
import cn.dev33.satoken.annotation.SaCheckLogin;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.bo.Nd3CustomKitBo;
import com.ruoyi.system.domain.vo.nd3.Nd3PhasedProductProjectVo;
import com.ruoyi.system.domain.vo.nd3.Nd3PhasedProductReportVo;
import com.ruoyi.system.service.INd3PhasedProductService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
/**
* 专项 ND3 项目阶段性产品报表接口
* <ul>
* <li>{@code /search}按物料号/令号关键字检索</li>
* <li>{@code /report}生产令号物料编码至少填一项可直接输入物料号查 BOM 及指标</li>
* </ul>
*/
@RestController
@RequiredArgsConstructor
@RequestMapping("/system/nd3/phased-product")
public class Nd3PhasedProductController {
private final INd3PhasedProductService nd3PhasedProductService;
/**
* 检索支持物料编码金蝶 BOM 父项 ND3 生产令号
*/
@SaCheckLogin
@GetMapping("/search")
public R<List<Nd3PhasedProductProjectVo>> search(@RequestParam String keyword) {
if (StringUtils.isBlank(keyword)) {
return R.fail("请输入物料编码或生产令号");
}
return R.ok(nd3PhasedProductService.searchProjects(keyword.trim()));
}
/**
* 报表{@code materialCode} {@code productionOrderNo} 至少填一项
* 仅物料号时按金蝶 BOM 展开子项发货/在途表头为全项目合计下钻仍按令号汇总
*/
@SaCheckLogin
@GetMapping("/report")
public R<Nd3PhasedProductReportVo> report(
@RequestParam(required = false) String productionOrderNo,
@RequestParam(required = false) String materialCode,
@RequestParam(required = false) Integer inputQty) {
if (StringUtils.isBlank(productionOrderNo) && StringUtils.isBlank(materialCode)) {
return R.fail("请填写物料编码或生产令号");
}
return R.ok(nd3PhasedProductService.buildReport(
StringUtils.isNotBlank(productionOrderNo) ? productionOrderNo.trim() : null,
StringUtils.isNotBlank(materialCode) ? materialCode.trim() : null,
inputQty));
}
/**
* 多主产品联合齐套试算各父项分别输入投单量子项按物料合并并展示各父项单台用量
*/
@SaCheckLogin
@PostMapping("/custom-kit")
public R<Nd3PhasedProductReportVo> customKit(@RequestBody Nd3CustomKitBo bo) {
if (bo == null || bo.getParents() == null || bo.getParents().isEmpty()) {
return R.fail("请至少填写一个主产品及投单量");
}
boolean hasValid = bo.getParents().stream()
.anyMatch(p -> p != null
&& StringUtils.isNotBlank(p.getMaterialCode())
&& p.getInputQty() != null
&& p.getInputQty() > 0);
if (!hasValid) {
return R.fail("请填写主产品编码及大于 0 的投单量");
}
return R.ok(nd3PhasedProductService.buildCustomKitReport(bo));
}
/**
* 多主产品联合齐套试算导出 Excel
*/
@SaCheckLogin
@PostMapping("/custom-kit/export")
public void exportCustomKit(@RequestBody Nd3CustomKitBo bo, HttpServletResponse response) {
if (bo == null || bo.getParents() == null || bo.getParents().isEmpty()) {
throw new ServiceException("请至少填写一个主产品及投单量");
}
boolean hasValid = bo.getParents().stream()
.anyMatch(p -> p != null
&& StringUtils.isNotBlank(p.getMaterialCode())
&& p.getInputQty() != null
&& p.getInputQty() > 0);
if (!hasValid) {
throw new ServiceException("请填写主产品编码及大于 0 的投单量");
}
nd3PhasedProductService.exportCustomKitReport(bo, response);
}
}

View File

@ -3,6 +3,7 @@ package com.ruoyi.system.controller;
import java.util.List;
import java.util.Arrays;
import cn.dev33.satoken.annotation.SaIgnore;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.RequiredArgsConstructor;
import javax.servlet.http.HttpServletResponse;
@ -108,9 +109,12 @@ public class PartCostController extends BaseController {
/**
* 在金蝶获取成本价
* 在金蝶获取成本价支持 XXL-JOB 定时同步
* JobHandler: getObtainPartData
*/
@SaCheckPermission("system:cost:getObtainPartData")
// @SaCheckPermission("system:cost:getObtainPartData")
@SaIgnore
@XxlJob("getObtainPartData")
@Log(title = "在金蝶获取成本价", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/getObtainPartData")

View File

@ -0,0 +1,105 @@
package com.ruoyi.system.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.system.domain.bo.PlmPdfZipPushBo;
import com.ruoyi.system.domain.vo.PlmPdfZipPushDetailVo;
import com.ruoyi.system.domain.vo.PlmPdfZipPushVo;
import com.ruoyi.system.service.IPlmPdfZipPushService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotNull;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
/**
* PLM PDF 压缩包推送记录
*/
@Slf4j
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/system/plmPdfZipPush")
public class PlmPdfZipPushController extends BaseController {
private final IPlmPdfZipPushService plmPdfZipPushService;
/**
* 分页查询推送记录
*/
@SaCheckPermission("system:plmPdfZipPush:list")
@GetMapping("/list")
public TableDataInfo<PlmPdfZipPushVo> list(PlmPdfZipPushBo bo, PageQuery pageQuery) {
return plmPdfZipPushService.queryPageList(bo, pageQuery);
}
/**
* 下载推送明细中的 PLM DWG校验项目是否允许下载图纸
*/
@SaCheckPermission("system:plmPdfZipPush:query")
@Log(title = "下载PLM DWG图纸", businessType = BusinessType.OTHER)
@GetMapping("/downloadDwgItem/{itemId}")
public void downloadDwgItem(@NotNull(message = "明细ID不能为空") @PathVariable Long itemId,
HttpServletResponse response) {
try {
File file = plmPdfZipPushService.resolveDownloadableDwgFile(itemId);
response.setContentType("application/octet-stream");
response.setCharacterEncoding("utf-8");
String fileName = URLEncoder.encode(file.getName(), "UTF-8").replaceAll("\\+", "%20");
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName);
response.setContentLengthLong(file.length());
try (FileInputStream fis = new FileInputStream(file);
OutputStream os = response.getOutputStream()) {
byte[] buffer = new byte[8192];
int length;
while ((length = fis.read(buffer)) > 0) {
os.write(buffer, 0, length);
}
os.flush();
}
} catch (ServiceException e) {
writeJsonFail(response, e.getMessage());
} catch (Exception e) {
log.error("下载PLM DWG失败 itemId={}", itemId, e);
writeJsonFail(response, "下载失败: " + e.getMessage());
}
}
/**
* 推送记录详情 manifest JSON 与明细
*/
@SaCheckPermission("system:plmPdfZipPush:query")
@GetMapping("/{id}")
public R<PlmPdfZipPushDetailVo> getInfo(@NotNull(message = "主键不能为空") @PathVariable Long id) {
return R.ok(plmPdfZipPushService.queryDetail(id));
}
private void writeJsonFail(HttpServletResponse response, String msg) {
try {
if (!response.isCommitted()) {
response.reset();
}
response.setContentType("application/json;charset=utf-8");
response.getWriter().write(JSONObject.toJSONString(R.fail(msg)));
} catch (IOException ex) {
log.error("写入错误响应失败", ex);
}
}
}

View File

@ -0,0 +1,124 @@
package com.ruoyi.system.controller;
import cn.dev33.satoken.annotation.SaIgnore;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.system.domain.bo.ProcessOrderProBo;
import com.ruoyi.system.domain.vo.ProcessOrderProVo;
import com.ruoyi.system.domain.vo.plm.PlmProductionOrderVo;
import com.ruoyi.system.service.IProcessOrderProService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
/**
* PLM 查询生产令号清单
* <p>
* GET /system/plm/productionOrders
*/
@Slf4j
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/system/plm")
public class PlmProductionOrderController extends BaseController {
private final IProcessOrderProService processOrderProService;
/**
* 分页查询生产令号清单有哪些生产令号
* <p>
* 可选筛选productionOrderNo模糊productionName模糊source手动/PLM
* bomStatus项目状态 2=工艺待审核6=开始生产routeStatus工艺审核状态<br>
* 分页pageNumpageSize默认按创建时间倒序
*/
@SaIgnore
@GetMapping("/productionOrders")
public TableDataInfo<PlmProductionOrderVo> productionOrders(ProcessOrderProBo bo, PageQuery pageQuery) {
TableDataInfo<ProcessOrderProVo> page = processOrderProService.queryPageList(bo, pageQuery);
List<ProcessOrderProVo> rows = page.getRows();
List<PlmProductionOrderVo> mapped = rows == null ? Collections.emptyList()
: rows.stream().map(this::toPlmVo).collect(Collectors.toList());
TableDataInfo<PlmProductionOrderVo> result = new TableDataInfo<>(mapped, page.getTotal());
result.setCode(page.getCode());
result.setMsg(page.getMsg());
return result;
}
private PlmProductionOrderVo toPlmVo(ProcessOrderProVo src) {
PlmProductionOrderVo vo = new PlmProductionOrderVo();
vo.setId(src.getId());
vo.setProductionOrderNo(src.getProductionOrderNo());
vo.setProductionName(src.getProductionName());
vo.setSource(src.getSource());
vo.setQuantity(src.getQuantity());
vo.setUnit(src.getUnit());
vo.setNeedProcess(src.getNeedProcess());
vo.setBomStatus(src.getBomStatus());
vo.setBomStatusLabel(resolveBomStatusLabel(src.getBomStatus()));
vo.setRouteStatus(src.getRouteStatus());
vo.setRouteStatusLabel(resolveRouteStatusLabel(src.getRouteStatus()));
vo.setPlanStartTime(src.getPlanStartTime());
vo.setPlanEndTime(src.getPlanEndTime());
vo.setCreateTime(src.getCreateTime());
return vo;
}
/**
* 项目状态0方案设计完成 2工艺待审核 6开始生产 8工艺审核完成 9工艺审核拒绝
*/
private static String resolveBomStatusLabel(Long status) {
if (status == null) {
return null;
}
switch (status.intValue()) {
case 0:
return "方案设计完成";
case 1:
return "设计出图完成";
case 2:
return "工艺待审核";
case 3:
return "已推送BOM";
case 4:
return "已推送工艺";
case 5:
return "已核算MRP";
case 6:
return "开始生产";
case 7:
return "生产完成";
case 8:
return "工艺审核完成";
case 9:
return "工艺审核拒绝";
default:
return String.valueOf(status);
}
}
/** 工艺审核0未审核 1已审核 2已拒绝 */
private static String resolveRouteStatusLabel(Long status) {
if (status == null) {
return null;
}
switch (status.intValue()) {
case 0:
return "未审核";
case 1:
return "已审核";
case 2:
return "已拒绝";
default:
return String.valueOf(status);
}
}
}

View File

@ -0,0 +1,74 @@
package com.ruoyi.system.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.bo.PlmReceiveLogBo;
import com.ruoyi.system.domain.vo.PlmReceiveLogVo;
import com.ruoyi.system.service.IPlmReceiveLogService;
import com.ruoyi.system.service.IProductionOrderService;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.constraints.NotNull;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* PLM 总装 BOM / 工艺路线接收留痕
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/system/plmReceiveLog")
public class PlmReceiveLogController extends BaseController {
private final IPlmReceiveLogService plmReceiveLogService;
private final IProductionOrderService productionOrderService;
@SaCheckPermission("system:plmReceiveLog:list")
@GetMapping("/list")
public TableDataInfo<PlmReceiveLogVo> list(PlmReceiveLogBo bo, PageQuery pageQuery) {
return plmReceiveLogService.queryPageList(bo, pageQuery);
}
@SaCheckPermission("system:plmReceiveLog:query")
@GetMapping("/{id}")
public R<PlmReceiveLogVo> getInfo(@NotNull(message = "主键不能为空") @PathVariable Long id) {
return R.ok(plmReceiveLogService.queryDetail(id));
}
/**
* 按留痕记录的生产令号 production_order 总装行手动同步到 bom_detailsbomType=0
*/
@SaCheckPermission("system:plmReceiveLog:syncBomDetails")
@Log(title = "PLM接收留痕-同步bom_details", businessType = BusinessType.UPDATE)
@PostMapping("/{id}/syncBomDetails")
public R<Map<String, Object>> syncBomDetails(@NotNull(message = "主键不能为空") @PathVariable Long id) {
PlmReceiveLogVo logVo = plmReceiveLogService.queryDetail(id);
if (logVo == null) {
throw new ServiceException("接收记录不存在");
}
if (StringUtils.isBlank(logVo.getProductionOrderNo())) {
throw new ServiceException("该记录无生产令号,无法同步 bom_details");
}
String orderNo = logVo.getProductionOrderNo().trim();
int count = productionOrderService.syncAssemblyBomDetailsByOrderNo(orderNo);
Map<String, Object> data = new LinkedHashMap<>();
data.put("productionOrderNo", orderNo);
data.put("savedCount", count);
data.put("bizType", logVo.getBizType());
return R.ok("已同步 " + count + " 条总装行到 bom_details", data);
}
}

View File

@ -13,7 +13,9 @@ import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.ruoyi.common.excel.DefaultExcelListener;
import com.ruoyi.common.config.DrawingFtpProperties;
import com.ruoyi.common.exception.ServiceException;
import cn.hutool.core.bean.BeanUtil;
import com.ruoyi.common.utils.FtpUtil;
import com.ruoyi.common.utils.HttpUtils;
import com.ruoyi.common.utils.StringUtils;
@ -21,7 +23,11 @@ import com.ruoyi.common.utils.VersionComparator;
import com.ruoyi.common.utils.file.SmbUtil;
import com.ruoyi.common.poi.ExcelTemplateProc;
import com.ruoyi.common.poi.DynamicDataMapping;
import com.ruoyi.system.constant.ProcessOrderProSource;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.domain.bo.KingdeeOrderReceiveBatchBo;
import com.ruoyi.system.domain.dto.KingdeePrdMoDTO;
import com.ruoyi.system.domain.dto.KingdeePurchaseOrderDTO;
import com.ruoyi.system.domain.dto.MaterialUseDTO;
import com.ruoyi.system.domain.dto.ProcessRouteDTO;
import com.ruoyi.system.domain.ProcessRouteExcelDTO1;
@ -45,6 +51,7 @@ import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.annotation.SaIgnore;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
@ -76,14 +83,23 @@ import shade.com.alibaba.fastjson2.JSONObject;
@RequestMapping("/system/orderPro")
public class ProcessOrderProController extends BaseController {
private final IProcessOrderProService iProcessOrderProService;
private final KingdeeOrderReceiveService kingdeeOrderReceiveService;
@Autowired
private final IMrpResultCheckService iMrpResultCheckService;
private final ProcessOrderProMapper processOrderProMapper;
private final IImMaterialService imMaterialService;
private final ISafetyStockService safetyStockService;
private final IProcessRouteService processRouteService;
private final IProductionOrderService productionOrderService;
private final SafetyStockMapper stockMapper;
private final FigureSaveMapper figureSaveMapper;
private final DrawingFtpProperties drawingFtpProperties;
private final IPlmPdfZipPushService plmPdfZipPushService;
private final IDrawingWorkloadService drawingWorkloadService;
/** 出图 Excel 在 FTP 上的盘符根路径,与 SMB F:\2026\令号 一致 */
@Value("${app.drawing.base-path:F:}")
private String drawingBasePath;
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy年MM月dd日");
@ -111,7 +127,10 @@ public class ProcessOrderProController extends BaseController {
@PostMapping("/export")
public void export(ProcessOrderProBo bo, HttpServletResponse response) {
List<ProcessOrderProVo> list = iProcessOrderProService.queryList(bo);
ExcelUtil.exportExcel(list, "项目令号", ProcessOrderProVo.class, response);
List<ProcessOrderProExportVo> exportList = list.stream()
.map(ProcessOrderProExportVo::from)
.collect(java.util.stream.Collectors.toList());
ExcelUtil.exportExcel(exportList, "项目令号", ProcessOrderProExportVo.class, response);
}
/**
@ -249,7 +268,7 @@ public class ProcessOrderProController extends BaseController {
}
@GetMapping("/getstate")
public R<JSONObject> getPlotState() {
String result = HttpUtils.sendGet("http://192.168.5.18:9000/getstate", "UTF-8");
String result = HttpUtils.sendGet("http://192.168.14.218:9000/getstate", "UTF-8");
if (StringUtils.isBlank(result)) {
return R.ok("操作成功", null);
}
@ -293,12 +312,15 @@ public class ProcessOrderProController extends BaseController {
/**
* 下载PDF并生成zip包
* <p>业务失败时返回 HTTP 200 + application/json blob 下载约定一致便于前端解析 msg
* 避免 axios 4xx 走错误拦截器只提示系统接口400异常</p>
*/
@SaCheckPermission("system:orderPro:uploadPDF")
@Log(title = "下载PDF", businessType = BusinessType.UPDATE)
@CrossOrigin(origins = "*", allowedHeaders = "*", exposedHeaders = {"Content-Disposition", "Content-Length"})
@GetMapping("/uploadPDF")
public void uploadPDF(@RequestParam Long id, HttpServletResponse response) {
log.info("下载PDF ZIP 请求: id={}", id);
try {
// CORS headers for all responses (success and error)
response.setHeader("Access-Control-Allow-Origin", "*");
@ -306,9 +328,8 @@ public class ProcessOrderProController extends BaseController {
// 调用service方法获取文件路径
R<String> result = iProcessOrderProService.uploadPDF(id);
if (result.getCode() != 200) {
response.setStatus(HttpStatus.BAD_REQUEST.value());
response.setContentType("application/json;charset=UTF-8");
response.getWriter().write("{\"code\":" + result.getCode() + ",\"msg\":\"" + result.getMsg() + "\"}");
log.warn("下载PDF ZIP 生成失败: id={}, code={}, msg={}", id, result.getCode(), result.getMsg());
writePdfDownloadJson(response, result);
return;
}
@ -317,12 +338,12 @@ public class ProcessOrderProController extends BaseController {
// 检查文件是否存在
if (!file.exists()) {
response.setStatus(HttpStatus.NOT_FOUND.value());
response.setContentType("application/json;charset=UTF-8");
response.getWriter().write("{\"code\":404,\"msg\":\"文件不存在\"}");
log.warn("下载PDF ZIP 文件不存在: id={}, path={}", id, filePath);
writePdfDownloadJson(response, R.fail("PDF文件不存在请稍后重试"));
return;
}
log.info("下载PDF ZIP 开始输出: id={}, path={}, size={}", id, filePath, file.length());
// 设置响应头
response.setContentType("application/zip");
response.setHeader("Content-Disposition", "attachment; filename=\"" + URLEncoder.encode(file.getName(), "UTF-8") + "\"");
@ -339,18 +360,35 @@ public class ProcessOrderProController extends BaseController {
}
os.flush();
}
log.info("下载PDF ZIP 输出完成: id={}, file={}", id, file.getName());
} catch (Exception e) {
if (response.isCommitted()) {
// 响应已开始写出多为客户端超时/关闭页面导致连接中断ZIP 通常已在服务端生成
log.warn("客户端已断开连接PDF/ZIP 可能已在服务端生成: id={}, {}", id, e.getMessage());
return;
}
log.error("下载PDF文件失败", e);
try {
response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
response.getWriter().write("下载失败: " + e.getMessage());
writePdfDownloadJson(response, R.fail("PDF下载失败请稍后重试"));
} catch (IOException ex) {
log.error("写入错误响应失败", ex);
}
}
}
/**
* blob 下载场景下统一写出 JSON 错误体HTTP 200 + application/jsonmsg 安全转义
*/
private void writePdfDownloadJson(HttpServletResponse response, R<?> body) throws IOException {
response.setStatus(HttpServletResponse.SC_OK);
response.setContentType("application/json;charset=UTF-8");
response.setCharacterEncoding("UTF-8");
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Expose-Headers", "Content-Disposition, Content-Length");
response.getWriter().write(JSONObject.toJSONString(body));
}
/**
* 下载ZIP包
*/
@ -394,11 +432,17 @@ public class ProcessOrderProController extends BaseController {
}
} catch (Exception e) {
if (response.isCommitted()) {
log.warn("客户端已断开连接ZIP 可能已在服务端生成: id={}, {}", id, e.getMessage());
return;
}
log.error("下载ZIP包失败", e);
try {
response.setContentType("text/html;charset=utf-8");
response.getWriter().write("下载失败: " + e.getMessage());
response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
response.setContentType("application/json;charset=UTF-8");
response.getWriter().write("{\"code\":500,\"msg\":\"下载失败\"}");
} catch (IOException ex) {
ex.printStackTrace();
log.error("写入错误响应失败", ex);
}
}
}
@ -489,7 +533,7 @@ public class ProcessOrderProController extends BaseController {
existingVmi.setQuantity(currentQuantity + itemQuantity);
Integer currentBatchQuantity = existingVmi.getBatchQuantity() != null ? existingVmi.getBatchQuantity() : 0;
Integer itemBatchQuantity = item.getBatchQuantity() != null ? Integer.parseInt(item.getBatchQuantity()) : 0;
Integer itemBatchQuantity = parseBatchQuantityAsIntOrZero(item.getBatchQuantity());
existingVmi.setBatchQuantity(currentBatchQuantity + itemBatchQuantity);
found = true;
break;
@ -1093,17 +1137,8 @@ public class ProcessOrderProController extends BaseController {
map.put("parentDrawingNo", item.getParentDrawingNo());
map.put("batchQuantity", item.getBatchQuantity());
// 为了兼容模板也提供数字格式的batchQuantity
Integer batchQuantityInt = null;
if (item.getBatchQuantity() != null && !item.getBatchQuantity().isEmpty()) {
try {
batchQuantityInt = Integer.valueOf(item.getBatchQuantity());
} catch (NumberFormatException e) {
// 如果转换失败保持原值
map.put("batchQuantityInt", null);
}
}
map.put("batchQuantityInt", batchQuantityInt);
// 为了兼容模板也提供数字格式的batchQuantity兼容 "32.0"
map.put("batchQuantityInt", parseBatchQuantityAsInt(item.getBatchQuantity()));
map.put("mainProducts", item.getMainPart());
map.put("mainProductsName", item.getMainName());
@ -1112,6 +1147,25 @@ public class ProcessOrderProController extends BaseController {
return mapList;
}
/**
* 批次数量转 Integer兼容 "32" / "32.0"PLM 常把 Double 存成带小数点的字符串
*/
private static Integer parseBatchQuantityAsInt(String batchQuantity) {
if (StringUtils.isBlank(batchQuantity)) {
return null;
}
try {
return (int) Double.parseDouble(batchQuantity.trim());
} catch (NumberFormatException e) {
return null;
}
}
private static int parseBatchQuantityAsIntOrZero(String batchQuantity) {
Integer v = parseBatchQuantityAsInt(batchQuantity);
return v != null ? v : 0;
}
/**
* 转换BOM数据为Map列表用于模板
*/
@ -1147,7 +1201,7 @@ public class ProcessOrderProController extends BaseController {
vmiData.setUnitWeight(item.getSingleWeight() != null ? BigDecimal.valueOf(item.getSingleWeight()) : null);
vmiData.setTotalWeight(item.getTotalWeight() != null ? BigDecimal.valueOf(item.getTotalWeight()) : null);
vmiData.setRemark(item.getRemark());
vmiData.setBatchQuantity(item.getBatchQuantity() != null ? Integer.valueOf(item.getBatchQuantity()) : null);
vmiData.setBatchQuantity(parseBatchQuantityAsInt(item.getBatchQuantity()));
return vmiData;
}
@ -1164,7 +1218,7 @@ public class ProcessOrderProController extends BaseController {
elecData.setUnitWeight(item.getSingleWeight() != null ? BigDecimal.valueOf(item.getSingleWeight()) : null);
elecData.setTotalWeight(item.getTotalWeight() != null ? BigDecimal.valueOf(item.getTotalWeight()) : null);
elecData.setRemark(item.getRemark());
elecData.setBatchQuantity(item.getBatchQuantity() != null ? Integer.valueOf(item.getBatchQuantity()) : null);
elecData.setBatchQuantity(parseBatchQuantityAsInt(item.getBatchQuantity()));
return elecData;
}
@ -1181,7 +1235,7 @@ public class ProcessOrderProController extends BaseController {
supplierData.setUnitWeight(item.getSingleWeight() != null ? BigDecimal.valueOf(item.getSingleWeight()) : null);
supplierData.setTotalWeight(item.getTotalWeight() != null ? BigDecimal.valueOf(item.getTotalWeight()) : null);
supplierData.setRemark(item.getRemark());
supplierData.setBatchQuantity(item.getBatchQuantity() != null ? Integer.valueOf(item.getBatchQuantity()) : null);
supplierData.setBatchQuantity(parseBatchQuantityAsInt(item.getBatchQuantity()));
return supplierData;
}
@ -1198,7 +1252,7 @@ public class ProcessOrderProController extends BaseController {
evoData.setUnitWeight(item.getSingleWeight() != null ? BigDecimal.valueOf(item.getSingleWeight()) : null);
evoData.setTotalWeight(item.getTotalWeight() != null ? BigDecimal.valueOf(item.getTotalWeight()) : null);
evoData.setRemark(item.getRemark());
evoData.setBatchQuantity(item.getBatchQuantity() != null ? Integer.valueOf(item.getBatchQuantity()) : null);
evoData.setBatchQuantity(parseBatchQuantityAsInt(item.getBatchQuantity()));
return evoData;
}
@ -1527,7 +1581,7 @@ public class ProcessOrderProController extends BaseController {
existingVmi.setQuantity(currentQuantity + itemQuantity);
Integer currentBatchQuantity = existingVmi.getBatchQuantity() != null ? existingVmi.getBatchQuantity() : 0;
Integer itemBatchQuantity = item.getBatchQuantity() != null ? Integer.parseInt(item.getBatchQuantity()) : 0;
Integer itemBatchQuantity = parseBatchQuantityAsIntOrZero(item.getBatchQuantity());
existingVmi.setBatchQuantity(currentBatchQuantity + itemBatchQuantity);
found = true;
break;
@ -1972,26 +2026,59 @@ public class ProcessOrderProController extends BaseController {
public String generateRoute3Excel(Long id, boolean isDrawing) throws Exception {
ProcessOrderPro orderPro = processOrderProMapper.selectById(id);
// 下载Excel文件
// 1. 解析年份
// PLM 来源装配 BOM / 工艺表从库读取不依赖 FTP 汇总表
if (ProcessOrderProSource.PLM.equals(orderPro.getSource())) {
return generateRoute3ExcelFromPlm(orderPro, isDrawing);
}
String productionCode = orderPro.getProductionOrderNo();
String year = ProductionOrderNoUtils.extractYear(productionCode);
// 2. 构建FTP路径和本地路径
String ftpPath = "/" + year + "/" + productionCode;
String localPath = "D:\\file\\";
String expectedSummaryName = productionCode + "汇总表.xlsx";
String remoteSummaryName = expectedSummaryName;
// 3. 下载文件 (下载汇总表.xlsx RawDataTable.xlsx)
FtpUtil.downloadFtpDirectoryFiles("192.168.5.18", "admin", "hbyt2025", 21, ftpPath, localPath, "汇总表.xlsx");
FtpUtil.downloadFtpDirectoryFiles("192.168.5.18", "admin", "hbyt2025", 21, ftpPath, localPath, "RawDataTable.xlsx");
String ftpPath = FtpUtil.buildDrawingExcelRemoteDir(drawingBasePath, year, productionCode);
log.info("工艺计划表 FTP 下载路径: {} (basePath={})", ftpPath, drawingBasePath);
// 构建文件路径
String excelName = "D:\\file\\" + orderPro.getProductionOrderNo() + "汇总表.xlsx";
String rawDataFile = "D:\\file\\" + "RawDataTable.xlsx";
R<String> summaryResult = FtpUtil.downloadFtpFile(
drawingFtpProperties, ftpPath, localPath, remoteSummaryName, expectedSummaryName);
if (R.isError(summaryResult)) {
log.warn("汇总表单文件下载失败: {},尝试目录扫描", summaryResult.getMsg());
summaryResult = FtpUtil.downloadFtpDirectoryFiles(
drawingFtpProperties, ftpPath, localPath, remoteSummaryName);
}
if (R.isError(summaryResult)) {
String fallbackPath = FtpUtil.buildDrawingExcelRemoteDir("", year, productionCode);
if (!fallbackPath.equals(ftpPath)) {
log.info("尝试无盘符 FTP 路径: {}", fallbackPath);
summaryResult = FtpUtil.downloadFtpFile(
drawingFtpProperties, fallbackPath, localPath, remoteSummaryName, expectedSummaryName);
if (R.isError(summaryResult)) {
summaryResult = FtpUtil.downloadFtpDirectoryFiles(
drawingFtpProperties, fallbackPath, localPath, remoteSummaryName);
}
if (R.isSuccess(summaryResult)) {
ftpPath = fallbackPath;
}
}
}
R<String> rawResult = FtpUtil.downloadFtpFile(
drawingFtpProperties, ftpPath, localPath, "RawDataTable.xlsx", "RawDataTable.xlsx");
if (R.isError(rawResult)) {
log.warn("RawDataTable 单文件下载失败: {},尝试目录扫描", rawResult.getMsg());
rawResult = FtpUtil.downloadFtpDirectoryFiles(
drawingFtpProperties, ftpPath, localPath, "RawDataTable.xlsx");
}
if (R.isError(rawResult)) {
log.warn("RawDataTable 下载: {}", rawResult.getMsg());
}
String excelName = localPath + expectedSummaryName;
String rawDataFile = localPath + "RawDataTable.xlsx";
File file = new File(excelName);
if (!file.exists() || file.length() == 0) {
// 如果文件不存在或为空下载失败抛出业务异常
throw new ServiceException("项目 " + orderPro.getProductionOrderNo() + " 汇总表下载失败或不存在");
throw new ServiceException("项目 " + productionCode + " 汇总表下载失败或不存在FTP路径="
+ ftpPath + ",远程文件名=" + remoteSummaryName + "" + summaryResult.getMsg());
}
// 1. 读取第一个sheet的数据list
List<ProductionOrderVo> allDataList = readExcelWithPOI(excelName,orderPro.getProductionOrderNo());
@ -2295,15 +2382,7 @@ public class ProcessOrderProController extends BaseController {
// 合并本批数量 (batchQuantity)
Integer currentBatch = existingElec.getBatchQuantity() != null ? existingElec.getBatchQuantity() : 0;
Integer itemBatch = 0;
try {
if (item.getBatchQuantity() != null) {
itemBatch = Integer.valueOf(item.getBatchQuantity().toString());
}
} catch (NumberFormatException e) {
// 转换失败忽略
}
existingElec.setBatchQuantity(currentBatch + itemBatch);
existingElec.setBatchQuantity(currentBatch + parseBatchQuantityAsIntOrZero(item.getBatchQuantity()));
found = true;
break;
@ -2408,6 +2487,241 @@ public class ProcessOrderProController extends BaseController {
return outputPath;
}
/**
* PLM 来源下载工艺计划表装配 BOM 总装配材料BOM工艺路线 工艺及生产计划表
* 并按规则拆出 VMI/机电件/甲供件/伊特明细不导出基础 BOM 其余明细 sheet 无数据也保留
* 无工艺推送时用装配 BOM 行占位一物料一行不走 FTP
*/
private String generateRoute3ExcelFromPlm(ProcessOrderPro orderPro, boolean isDrawing) throws Exception {
String productionCode = orderPro.getProductionOrderNo();
List<ProductionOrder> orders = productionOrderService.selectByProCode(productionCode);
if (orders == null || orders.isEmpty()) {
throw new ServiceException("PLM 项目 " + productionCode + " 未找到装配 BOM请先接收 PLM 推送");
}
List<ProductionOrderVo> allDataList = BeanUtil.copyToList(orders, ProductionOrderVo.class);
List<ProcessRoute> routeList = processRouteService.selectByProjectNumber(productionCode);
if (routeList == null) {
routeList = new ArrayList<>();
}
if (routeList.isEmpty()) {
for (ProductionOrderVo vo : allDataList) {
if (vo == null || StringUtils.isBlank(vo.getDrawingNo())) {
continue;
}
ProcessRoute row = new ProcessRoute();
row.setRouteDescription(productionCode);
row.setMaterialCode(vo.getDrawingNo());
row.setMaterialName(vo.getDrawingName());
row.setMaterial(vo.getMaterial());
row.setDiscWeight(vo.getSingleWeight());
row.setUnitQuantity(vo.getQuantity());
if (StringUtils.isNotBlank(vo.getBatchQuantity())) {
try {
row.setBatchQuantity(Long.valueOf(vo.getBatchQuantity().trim()));
} catch (NumberFormatException ignored) {
// ignore
}
}
routeList.add(row);
}
}
// 分类VMI / 机电件 / 甲供件 / 伊特不灌基础 BOM
BomClassifyResult classified = classifyAssemblyBomDetails(allDataList);
String templatePath = "jpg/生产及工艺计划模版.xlsx";
String safeOrderNo = sanitizeFileNameSegment(productionCode);
String outputPath = isDrawing
? ("D:/file/" + safeOrderNo + "工艺表.xlsx")
: ("D:/file/" + safeOrderNo + "生产及工艺计划表.xlsx");
Map<String, Object> staticDataMap = new HashMap<>();
staticDataMap.put("productionOrderNo", productionCode);
staticDataMap.put("productionName", orderPro.getProductionName());
List<DynamicDataMapping> dynamicDataMappingList = new ArrayList<>();
dynamicDataMappingList.addAll(DynamicDataMapping.createOneDataList(
"ProductionOrder", convertProductionOrderToMapList(allDataList, productionCode)));
if (!classified.vmiList.isEmpty()) {
dynamicDataMappingList.addAll(DynamicDataMapping.createOneDataList(
"VMIDataVO", convertVMIDataToMapList(classified.vmiList)));
}
if (!classified.elecOutList.isEmpty()) {
dynamicDataMappingList.addAll(DynamicDataMapping.createOneDataList(
"ElecOutDataVO", convertElecOutDataToMapList(classified.elecOutList)));
}
if (!classified.supplierList.isEmpty()) {
dynamicDataMappingList.addAll(DynamicDataMapping.createOneDataList(
"SupProvidDataVO", convertSupProvidDataToMapList(classified.supplierList)));
}
if (!classified.evoProductsList.isEmpty()) {
dynamicDataMappingList.addAll(DynamicDataMapping.createOneDataList(
"EVOProductsDataVO", convertEVOProductsDataToMapList(classified.evoProductsList)));
}
// 刻意不添加 BomDataVO PLM 不导出基础 BOM
if (!routeList.isEmpty()) {
dynamicDataMappingList.addAll(DynamicDataMapping.createOneDataList(
"RouteBomData", convertRouteBomToMapList(routeList, Collections.emptyList())));
}
log.info("PLM 工艺计划导出 productionCode={} assemblyBom={} routeRows={} vmi={} elec={} supplier={} evo={}",
productionCode, allDataList.size(), routeList.size(),
classified.vmiList.size(), classified.elecOutList.size(),
classified.supplierList.size(), classified.evoProductsList.size());
ExcelTemplateProc.doExportExcelByTemplateProc(templatePath, outputPath, staticDataMap, dynamicDataMappingList);
// PLM 不导出基础 BOM 其余明细 sheet 即使无数据也保留
removeExcelSheetsByName(outputPath, Collections.singletonList("基础BOM表"));
return outputPath;
}
/** 装配 BOM 分类结果VMI / 机电件 / 甲供件 / 伊特) */
private static final class BomClassifyResult {
private final List<VMIDataVO> vmiList = new ArrayList<>();
private final List<ElecOutDataVO> elecOutList = new ArrayList<>();
private final List<SupProvidDataVO> supplierList = new ArrayList<>();
private final List<EVOProductsDataVO> evoProductsList = new ArrayList<>();
}
/**
* 总装 BOM 明细分类与非 PLM 导出一致
* 1) 物料主数据 classificationName=true VMI
* 2) 图号两空格/指定前缀 备注|零件类型含外购 机电件安全库存除外
* 3) 备注|零件类型含甲供件 甲供件
* 4) 备注|零件类型含伊特 伊特产品
*/
private BomClassifyResult classifyAssemblyBomDetails(List<ProductionOrderVo> allDataList) {
BomClassifyResult result = new BomClassifyResult();
if (allDataList == null || allDataList.isEmpty()) {
return result;
}
for (ProductionOrderVo item : allDataList) {
if (item == null) {
continue;
}
String materialCode = item.getDrawingNo();
String remark = item.getRemark();
String prtType = item.getPrtType();
String categoryText = joinCategoryText(remark, prtType);
if (materialCode == null) {
continue;
}
String drawingNo = item.getDrawingNo();
String drawingName = item.getDrawingName();
if (drawingName != null) {
ImMaterial material = imMaterialService.selectByCodeAndName(drawingNo, drawingName);
if (material != null && "true".equals(material.getClassificationName())) {
mergeOrAddVmi(result.vmiList, item);
continue;
}
}
if (isElecOutMaterialCode(materialCode) || categoryTextContains(categoryText, "外购")) {
Boolean isSafeStock = safetyStockService.isSafeCode(materialCode.trim());
if (!Boolean.TRUE.equals(isSafeStock)) {
mergeOrAddElec(result.elecOutList, item);
}
continue;
}
if (categoryTextContains(categoryText, "甲供件")) {
result.supplierList.add(convertToSupProvidDataVO(item));
continue;
}
if (categoryTextContains(categoryText, "伊特")) {
result.evoProductsList.add(convertToEVOProductsDataVO(item));
}
}
return result;
}
private static String joinCategoryText(String remark, String prtType) {
if (StringUtils.isBlank(remark) && StringUtils.isBlank(prtType)) {
return "";
}
if (StringUtils.isBlank(remark)) {
return prtType;
}
if (StringUtils.isBlank(prtType)) {
return remark;
}
return remark + " " + prtType;
}
private static boolean categoryTextContains(String text, String keyword) {
return text != null && keyword != null && text.contains(keyword);
}
private static boolean isElecOutMaterialCode(String materialCode) {
return materialCode.startsWith(" ")
|| materialCode.startsWith("009301") || materialCode.startsWith("009999")
|| materialCode.startsWith("017003") || materialCode.startsWith("017002")
|| materialCode.startsWith("009001") || materialCode.startsWith("009081");
}
private void mergeOrAddVmi(List<VMIDataVO> vmiList, ProductionOrderVo item) {
String drawingNo = item.getDrawingNo();
for (VMIDataVO existing : vmiList) {
if (drawingNo != null && drawingNo.equals(existing.getDrawingNo())) {
Integer currentQuantity = existing.getQuantity() != null ? existing.getQuantity() : 0;
Integer itemQuantity = item.getQuantity() != null ? item.getQuantity().intValue() : 0;
existing.setQuantity(currentQuantity + itemQuantity);
Integer currentBatch = existing.getBatchQuantity() != null ? existing.getBatchQuantity() : 0;
existing.setBatchQuantity(currentBatch + parseBatchQuantityAsIntOrZero(item.getBatchQuantity()));
return;
}
}
vmiList.add(convertToVMIDataVO(item));
}
private void mergeOrAddElec(List<ElecOutDataVO> elecOutList, ProductionOrderVo item) {
for (ElecOutDataVO existing : elecOutList) {
if (item.getDrawingNo() != null && item.getDrawingNo().equals(existing.getDrawingNo())) {
Double currentQuantity = existing.getQuantity() != null ? existing.getQuantity() : 0.0;
Double itemQuantity = item.getQuantity() != null ? item.getQuantity() : 0.0;
existing.setQuantity(currentQuantity + itemQuantity);
Integer currentBatch = existing.getBatchQuantity() != null ? existing.getBatchQuantity() : 0;
existing.setBatchQuantity(currentBatch + parseBatchQuantityAsIntOrZero(item.getBatchQuantity()));
return;
}
}
elecOutList.add(convertToElecOutDataVO(item));
}
/** 按名称删除导出 Excel 中的 sheet从后往前删避免索引错位 */
private void removeExcelSheetsByName(String excelPath, List<String> sheetNames) {
if (StringUtils.isBlank(excelPath) || sheetNames == null || sheetNames.isEmpty()) {
return;
}
File file = new File(excelPath);
if (!file.exists()) {
return;
}
Set<String> toRemove = sheetNames.stream()
.filter(StringUtils::isNotBlank)
.collect(Collectors.toSet());
if (toRemove.isEmpty()) {
return;
}
try (FileInputStream fis = new FileInputStream(file);
XSSFWorkbook workbook = new XSSFWorkbook(fis)) {
for (int i = workbook.getNumberOfSheets() - 1; i >= 0; i--) {
String name = workbook.getSheetName(i);
if (toRemove.contains(name)) {
workbook.removeSheetAt(i);
}
}
try (FileOutputStream fos = new FileOutputStream(file)) {
workbook.write(fos);
}
} catch (Exception e) {
log.warn("删除空 sheet 失败 path={} sheets={} err={}", excelPath, toRemove, e.getMessage());
}
}
@ -2490,4 +2804,151 @@ public class ProcessOrderProController extends BaseController {
}
}
/**
* 下载项目 PLM 本地 DWG 图纸打包 ZIP校验是否允许下载项目图纸
*/
@SaCheckPermission("system:orderPro:downloadZip")
@Log(title = "下载PLM DWG图纸", businessType = BusinessType.OTHER)
@GetMapping("/downloadPlmDwg/{id}")
public void downloadPlmDwg(@PathVariable("id") Long id, HttpServletResponse response) {
try {
ProcessOrderProVo orderPro = iProcessOrderProService.queryById(id);
if (orderPro == null) {
writeJsonFail(response, "项目不存在");
return;
}
if (StringUtils.isBlank(orderPro.getProductionOrderNo())) {
writeJsonFail(response, "项目未配置生产令号");
return;
}
List<File> dwgFiles = plmPdfZipPushService.listDownloadableDwgFiles(orderPro.getProductionOrderNo());
String zipName = orderPro.getProductionOrderNo().trim() + "_PLM_DWG.zip";
String encoded = URLEncoder.encode(zipName, "UTF-8").replaceAll("\\+", "%20");
response.setContentType("application/zip");
response.setCharacterEncoding("utf-8");
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + encoded);
try (java.util.zip.ZipOutputStream zos = new java.util.zip.ZipOutputStream(response.getOutputStream())) {
Set<String> usedNames = new HashSet<>();
byte[] buffer = new byte[8192];
for (File file : dwgFiles) {
if (file == null || !file.isFile()) {
continue;
}
String entryName = uniqueZipEntryName(file.getName(), usedNames);
zos.putNextEntry(new java.util.zip.ZipEntry(entryName));
try (FileInputStream fis = new FileInputStream(file)) {
int len;
while ((len = fis.read(buffer)) > 0) {
zos.write(buffer, 0, len);
}
}
zos.closeEntry();
}
zos.finish();
}
} catch (ServiceException e) {
writeJsonFail(response, e.getMessage());
} catch (Exception e) {
log.error("下载PLM DWG失败 id={}", id, e);
writeJsonFail(response, "下载失败: " + e.getMessage());
}
}
private static String uniqueZipEntryName(String name, Set<String> usedNames) {
String base = name == null ? "unnamed.dwg" : name;
if (usedNames.add(base)) {
return base;
}
int dot = base.lastIndexOf('.');
String prefix = dot > 0 ? base.substring(0, dot) : base;
String suffix = dot > 0 ? base.substring(dot) : "";
int i = 2;
String candidate;
do {
candidate = prefix + "_" + i + suffix;
i++;
} while (!usedNames.add(candidate));
return candidate;
}
private void writeJsonFail(HttpServletResponse response, String msg) {
try {
if (!response.isCommitted()) {
response.reset();
}
response.setContentType("application/json;charset=utf-8");
response.getWriter().write(JSONObject.toJSONString(R.fail(msg)));
} catch (IOException ex) {
log.error("写入错误响应失败", ex);
}
}
/**
* FTP 读取{令号}图纸数量统计表.xlsx解析 Sheet1/Sheet2 入库并返回
*/
@SaCheckPermission("system:orderPro:drawingWorkload")
@Log(title = "读取图纸工作量", businessType = BusinessType.OTHER)
@PostMapping("/drawingWorkload/sync/{id}")
public R<DrawingWorkloadVo> syncDrawingWorkload(@NotNull(message = "项目id不能为空") @PathVariable Long id) {
return R.ok(drawingWorkloadService.syncFromFtp(id));
}
/**
* 查询已入库的图纸工作量含明细
*/
@SaCheckPermission("system:orderPro:drawingWorkload")
@GetMapping("/drawingWorkload/{id}")
public R<DrawingWorkloadVo> getDrawingWorkload(@NotNull(message = "项目id不能为空") @PathVariable Long id) {
DrawingWorkloadVo vo = drawingWorkloadService.getByOrderProId(id);
if (vo == null) {
return R.fail("尚未读取图纸工作量,请先点击「读取图纸工作量」");
}
return R.ok(vo);
}
/**
* 接收金蝶推送的生产/采购订单并入库支持多个生产令号
*/
@SaIgnore
@Log(title = "接收金蝶订单", businessType = BusinessType.INSERT)
@PostMapping("/kingdee/receive")
public R<Void> receiveKingdeeOrders(@Validated @RequestBody KingdeeOrderReceiveBatchBo bo) {
kingdeeOrderReceiveService.saveBatch(bo);
return R.ok();
}
/**
* 按项目 id 查询金蝶生产订单实时
*/
@SaCheckPermission("system:orderPro:list")
@GetMapping("/kingdee/prdMo/{id}")
public R<List<KingdeePrdMoDTO>> getKingdeePrdMo(@NotNull(message = "项目id不能为空") @PathVariable Long id) {
String productionOrderNo = resolveProductionOrderNoById(id);
List<KingdeePrdMoDTO> list = JdUtil.getKingdeePrdMoByProductionOrderNo(productionOrderNo);
return R.ok(list);
}
/**
* 按项目 id 查询金蝶采购订单
*/
@SaCheckPermission("system:orderPro:list")
@GetMapping("/kingdee/purchaseOrder/{id}")
public R<List<KingdeePurchaseOrderDTO>> getKingdeePurchaseOrder(@NotNull(message = "项目id不能为空") @PathVariable Long id) {
String productionOrderNo = resolveProductionOrderNoById(id);
List<KingdeePurchaseOrderDTO> list = JdUtil.getKingdeePurchaseOrderByProductionOrderNo(productionOrderNo);
return R.ok(list);
}
private String resolveProductionOrderNoById(Long id) {
ProcessOrderProVo orderPro = iProcessOrderProService.queryById(id);
if (orderPro == null) {
throw new ServiceException("项目不存在");
}
if (StringUtils.isBlank(orderPro.getProductionOrderNo())) {
throw new ServiceException("项目未配置生产令号");
}
return orderPro.getProductionOrderNo().trim();
}
}

View File

@ -8,6 +8,7 @@ import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.annotation.RepeatSubmit;
import com.ruoyi.common.config.DrawingFtpProperties;
import com.ruoyi.common.config.DingTalkProperties;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.PageQuery;
@ -23,6 +24,7 @@ import com.ruoyi.common.excel.ExcelResult;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.helper.LoginHelper;
import com.ruoyi.common.utils.FtpUtil;
import com.ruoyi.common.utils.KingdeeRouteDepartmentHelper;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.SmbUtil;
import com.ruoyi.common.utils.poi.ExcelUtil;
@ -84,6 +86,7 @@ public class ProcessRouteController extends BaseController {
private final OperationReportWorkshopUpdateService operationReportWorkshopUpdateService;
private final IBomDetailsService iBomDetailsService;
private final ProcessOrderProMapper proMapper;
private final DrawingFtpProperties drawingFtpProperties;
private final IImMaterialService materialService;
@Autowired
BomDetailsMapper bomDetailsMapper;
@ -95,6 +98,8 @@ public class ProcessRouteController extends BaseController {
private ISysOssService iSysOssService;
@Autowired
private IProcessOrderProService processOrderProService;
/** 计划表落盘 + 按 plan-user-id 推送(与 PLM 导出共用) */
private final ProcessPlanExcelPushService processPlanExcelPushService;
@Autowired
private ISysUserService userService;
@ -309,7 +314,6 @@ public class ProcessRouteController extends BaseController {
}
//读取file的所有的物料编码
try {
if (file.exists()) {
// 读取Excel的sheet6 从第三行开始 读取到第4列 无数据的跳过
DefaultExcelListener<ProcessRoute> listener = new DefaultExcelListener<>(true);
@ -418,21 +422,25 @@ public class ProcessRouteController extends BaseController {
if (!route.isEmpty()) {
return R.fail("项目 " + productionOrderNo + "已导入过工艺 ,请先清空再上传");
}
String workCenterError = validateImportWorkCenters(list1);
if (workCenterError != null) {
return R.fail("生产工艺计划表工段校验失败:\n" + workCenterError);
}
if (iProcessRouteService.saveData(list1, list)) {
// 保存临时文件用于发送给指定用户
File tempFile = null;
// 计划表落到服务器固定目录app.plan-excel.base-dir/令号/保留不删
File savedPlanFile = null;
try {
String tempDirPath = "D:/file/";
File tempDir = new File(tempDirPath);
if (!tempDir.exists()) {
tempDir.mkdirs();
File dir = new File(processPlanExcelPushService.getPlanExcelBaseDir(), productionOrderNo);
if (!dir.exists() && !dir.mkdirs()) {
log.warn("创建计划表目录失败: {}", dir.getAbsolutePath());
}
tempFile = new File(tempDirPath + System.currentTimeMillis() + "_" + originalFilename);
file.transferTo(tempFile);
savedPlanFile = new File(dir, originalFilename);
file.transferTo(savedPlanFile);
log.info("上传的工艺计划表已落盘: {}", savedPlanFile.getAbsolutePath());
} catch (Exception e) {
log.error("保存上传临时文件失败", e);
log.error("保存上传的工艺计划表失败", e);
}
final File uploadFile = tempFile;
final File uploadFile = savedPlanFile;
// 获取当前登录用户昵称需要在异步线程前获取
String currentUserNickName = "未知用户";
@ -448,38 +456,11 @@ public class ProcessRouteController extends BaseController {
log.warn("获取当前登录用户昵称失败", e);
}
// 异步发送钉钉卡片和文件
// 异步 plan-user-id 发文件 + 发工艺审核卡片落盘文件保留
String finalNickName = currentUserNickName;
CompletableFuture.runAsync(() -> {
try {
if (uploadFile != null && uploadFile.exists()) {
String planUserIds = dingTalkProperties.getPlanUserId();
if (StringUtils.isNotBlank(planUserIds)) {
String mediaId = mediaService.uploadMedia("file", uploadFile.getAbsolutePath());
// 支持多人推送假设多个 userId 以逗号分隔
String[] userIds = planUserIds.split(",");
for (String userId : userIds) {
String cleanUserId = userId.trim();
if (StringUtils.isNotBlank(cleanUserId)) {
try {
robotGroupService.sendFileToUser(cleanUserId, mediaId, originalFilename);
log.info("上传的工艺计划表已成功发送给用户: {}", cleanUserId);
} catch (Exception e) {
log.error("发送文件给用户 {} 异常", cleanUserId, e);
}
}
}
} else {
log.warn("未配置钉钉工艺计划接收人(planUserId),跳过发送文件");
}
}
} catch (Exception e) {
log.error("发送文件给工艺计划接收人异常", e);
} finally {
if (uploadFile != null && uploadFile.exists()) {
uploadFile.delete();
}
}
// PLM 导出推送同一套接收人
processPlanExcelPushService.sendToPlanUsers(uploadFile, originalFilename);
try {
ProcessOrderPro order = processOrderProService.selectByProjectNumber(productionOrderNo);
@ -497,7 +478,7 @@ public class ProcessRouteController extends BaseController {
String outTrackId = "audit-card-" + System.currentTimeMillis();
// 调用发送给工艺负责人的方法 createAndDeliverCardToUser
DingUtil.createAndDeliverCardToUser(
DingUtil.createAndDeliverCardToUser(
accessToken,
dingTalkProperties.getRouteCardTemplateId(),
Collections.singletonList(dingTalkProperties.getRouteApprovalId()),
@ -571,6 +552,13 @@ public class ProcessRouteController extends BaseController {
return iProcessRouteService.pushRouteBom(rooteProdet, groupName);
}
@Log(title = "审核通过(发送钉钉通知,不推送金蝶)")
@SaCheckPermission("system:route:approveRoute")
@PostMapping("/approveRoute")
public R<Void> approveRoute(@RequestParam String rooteProdet) {
return processOrderProService.approveRoute(rooteProdet);
}
/**
* 查询项目列表
*/
@ -656,12 +644,12 @@ public class ProcessRouteController extends BaseController {
@SaCheckPermission("system:route:updateProcessPlan")
@PostMapping("/updateProcessPlanByWorkshopCustom")
public R<List<Model>> updateProcessPlanByWorkshopCustom(
@RequestParam String departmentCompare,
@RequestParam String departmentNumber,
@RequestParam String productCompare,
@RequestParam String productFilterValue) throws Exception {
@RequestParam String departmentCompare,
@RequestParam String departmentNumber,
@RequestParam String productCompare,
@RequestParam String productFilterValue) throws Exception {
return R.ok(operationPlanningWorkshopUpdateService.updateProcessPlanByWorkshopFilter(
departmentCompare, departmentNumber, productCompare, productFilterValue));
departmentCompare, departmentNumber, productCompare, productFilterValue));
}
@Log(title = "按车间物料更新工序汇报单(默认条件)")
@ -676,7 +664,7 @@ public class ProcessRouteController extends BaseController {
@PostMapping("/updateOperationReportByWorkshopCustom")
public R<List<Model>> updateOperationReportByWorkshopCustom() throws Exception {
return R.ok(operationReportWorkshopUpdateService.updateOperationReportByWorkshopFilter(
"67", "007", "17", "-MP"));
"67", "007", "17", "-MP"));
}
/**
@ -1036,15 +1024,10 @@ public class ProcessRouteController extends BaseController {
// 下载Excel模板 (切换为FTP方式)
// SmbUtil.downloadExcelFiles(rooteProdet);
String ftpHost = "192.168.5.18";
String ftpUser = "admin";
String ftpPass = "hbyt2025";
int ftpPort = 21;
String localDir = "D:\\file";
// 假设远程目录结构与SMB一致 /2026/{rooteProdet}
String remoteDir = "/2026/" + rooteProdet;
R<String> ftpResult = FtpUtil.downloadFtpDirectoryFiles(ftpHost, ftpUser, ftpPass, ftpPort, remoteDir, localDir);
R<String> ftpResult = FtpUtil.downloadFtpDirectoryFiles(drawingFtpProperties, remoteDir, localDir);
if (R.isError(ftpResult)) {
log.error("FTP下载失败: {}", ftpResult.getMsg());
} else {
@ -1109,4 +1092,106 @@ public class ProcessRouteController extends BaseController {
List<String> list = iProcessRouteService.updateCgOrders(rooteProdet, cangKuNum);
return R.ok(list);
}
/**
* 导入前校验工作中心加工车间工段合法
* 同一物料下机加(006)与装配(007)可混用铆焊(018)不得与其他车间混用
*/
private static String validateImportWorkCenters(List<ProcessRouteVo> list) {
if (list == null || list.isEmpty()) {
return null;
}
StringBuilder sb = new StringBuilder();
validateImportWorkCenterPerRow(list, sb);
validateImportMaterialSingleWorkshop(list, sb);
return sb.length() == 0 ? null : sb.toString();
}
/**
* 逐行工段非空且在允许列表内
*/
private static void validateImportWorkCenterPerRow(List<ProcessRouteVo> list, StringBuilder sb) {
int seq = 0;
for (ProcessRouteVo vo : list) {
if (vo == null) {
continue;
}
Long processNo = vo.getProcessNo();
String workCenter = vo.getWorkCenter();
boolean hasProcess = processNo != null;
boolean hasWorkCenter = StringUtils.isNotBlank(workCenter);
if (!hasProcess && !hasWorkCenter) {
continue;
}
seq++;
if (!hasWorkCenter) {
appendWorkCenterError(sb, seq, processNo, vo.getMaterialCode(), "工作中心不能为空");
continue;
}
try {
String dept = KingdeeRouteDepartmentHelper.resolveDepartmentFNumber(workCenter);
log.debug("工段校验通过 第{}条工艺 processNo={} workCenter={} dept={}",
seq, processNo, KingdeeRouteDepartmentHelper.normalize(workCenter), dept);
} catch (ServiceException e) {
appendWorkCenterError(sb, seq, processNo, vo.getMaterialCode(), e.getMessage());
}
}
}
/**
* 同一物料编码下机加(006)与装配(007)允许混用铆焊(018)不得与机加/装配混用
*/
private static void validateImportMaterialSingleWorkshop(List<ProcessRouteVo> list, StringBuilder sb) {
Map<String, LinkedHashSet<String>> materialToDepts = new LinkedHashMap<>();
Map<String, LinkedHashSet<String>> materialToWorkCenters = new LinkedHashMap<>();
for (ProcessRouteVo vo : list) {
if (vo == null || vo.getProcessNo() == null || StringUtils.isBlank(vo.getWorkCenter())) {
continue;
}
String materialCode = StringUtils.trim(vo.getMaterialCode());
if (StringUtils.isBlank(materialCode)) {
continue;
}
String workCenter = KingdeeRouteDepartmentHelper.normalize(vo.getWorkCenter());
String dept;
try {
dept = KingdeeRouteDepartmentHelper.resolveDepartmentFNumber(workCenter);
} catch (ServiceException e) {
continue;
}
materialToDepts.computeIfAbsent(materialCode, k -> new LinkedHashSet<>()).add(dept);
materialToWorkCenters.computeIfAbsent(materialCode, k -> new LinkedHashSet<>()).add(workCenter);
}
for (Map.Entry<String, LinkedHashSet<String>> entry : materialToDepts.entrySet()) {
if (!KingdeeRouteDepartmentHelper.hasIncompatibleWorkshops(entry.getValue())) {
continue;
}
String materialCode = entry.getKey();
String deptDesc = entry.getValue().stream()
.map(d -> KingdeeRouteDepartmentHelper.departmentLabel(d) + "(" + d + ")")
.collect(Collectors.joining(""));
String wcDesc = String.join("", materialToWorkCenters.getOrDefault(materialCode, new LinkedHashSet<>()));
if (sb.length() > 0) {
sb.append('\n');
}
sb.append("物料 ").append(materialCode)
.append(" 的工艺路线存在不兼容的加工车间(").append(deptDesc)
.append("),涉及工段:").append(wcDesc)
.append(";机加与装配可同物料混用,铆焊车间不得与其他车间混用");
}
}
private static void appendWorkCenterError(StringBuilder sb, int seq, Long processNo, String materialCode, String msg) {
if (sb.length() > 0) {
sb.append('\n');
}
sb.append("").append(seq).append("条工艺");
if (processNo != null) {
sb.append(" 工序号=").append(processNo);
}
if (StringUtils.isNotBlank(materialCode)) {
sb.append(" 物料=").append(materialCode);
}
sb.append("").append(msg);
}
}

View File

@ -0,0 +1,165 @@
package com.ruoyi.system.controller;
import cn.dev33.satoken.annotation.SaIgnore;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.system.domain.ProcessOrderPro;
import com.ruoyi.system.domain.bo.plm.PlmProcessRoutePushBo;
import com.ruoyi.system.domain.bo.plm.PlmProcessRoutePushNormalizer;
import com.ruoyi.system.mapper.ProcessOrderProMapper;
import com.ruoyi.system.service.IPlmProcessRoutePushService;
import com.ruoyi.system.service.IPlmReceiveLogService;
import com.ruoyi.system.service.ProcessPlanExcelPushService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.File;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
/**
* PLM 系统推送完整工艺信息接收入口POST JSON英文键名
*
* @see PlmProcessRoutePushBo
*/
@Slf4j
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/system/plm")
public class ProcessRoutePushReceiveController extends BaseController {
private static final String API_PATH = "/system/plm/routReceive";
private final IPlmProcessRoutePushService plmProcessRoutePushService;
private final IPlmReceiveLogService plmReceiveLogService;
private final ProcessOrderProMapper processOrderProMapper;
/** 导出计划表落盘 + 按 plan-user-id 推送(与手动上传一致) */
private final ProcessPlanExcelPushService processPlanExcelPushService;
/**
* 接收一个生产令号下的物料材料 BOM工艺路线及工步数据
* <p>
* POST /system/plm/routReceive<br>
* Content-Type: application/json; charset=UTF-8
*/
@SaIgnore
@Log(title = "PLM工艺信息推送接收", businessType = BusinessType.OTHER)
@PostMapping("/routReceive")
public R<PlmProcessRoutePushNormalizer.PlmProcessRoutePushSummary> receive(
@Validated @RequestBody PlmProcessRoutePushBo body) {
String payloadJson = JSON.toJSONString(body);
String orderNo = body == null ? null : body.getProductionOrder();
String clientIp = resolveClientIp();
try {
PlmProcessRoutePushNormalizer.normalize(body);
PlmProcessRoutePushNormalizer.PlmProcessRoutePushSummary summary = plmProcessRoutePushService.persist(body);
log.info("收到 PLM 工艺推送 productionOrder={} materialCount={} processCount={} stepCount={} bomLineCount={} savedBom={} savedRoute={}",
summary.getProductionOrder(), summary.getMaterialCount(),
summary.getProcessCount(), summary.getStepCount(), summary.getBomLineCount(),
summary.getSavedBomCount(), summary.getSavedRouteCount());
log.info("PLM 工艺推送完整 JSON:\n{}", JSON.toJSONString(body, SerializerFeature.PrettyFormat));
Map<String, Object> summaryMap = new LinkedHashMap<>();
summaryMap.put("productionOrder", summary.getProductionOrder());
summaryMap.put("materialCount", summary.getMaterialCount());
summaryMap.put("bomLineCount", summary.getBomLineCount());
summaryMap.put("processCount", summary.getProcessCount());
summaryMap.put("stepCount", summary.getStepCount());
summaryMap.put("savedBomCount", summary.getSavedBomCount());
summaryMap.put("savedMaterialBomCount", summary.getSavedMaterialBomCount());
summaryMap.put("savedRouteCount", summary.getSavedRouteCount());
int saved = summary.getSavedBomCount() + summary.getSavedMaterialBomCount() + summary.getSavedRouteCount();
plmReceiveLogService.record(
IPlmReceiveLogService.BIZ_PROCESS_ROUTE,
API_PATH,
summary.getProductionOrder(),
payloadJson,
JSON.toJSONString(summaryMap),
summary.getMaterialCount(),
saved,
Boolean.TRUE,
IPlmReceiveLogService.STATUS_SUCCESS,
null,
clientIp
);
// 入库成功后异步导出工艺计划表 落盘 推送给 plan-user-id与手动上传同一套用户
final String productionOrder = summary.getProductionOrder();
CompletableFuture.runAsync(() -> exportAndPushPlanExcel(productionOrder));
return R.ok("接收成功", summary);
} catch (Exception e) {
Integer lineCount = null;
if (body != null && body.getMaterialList() != null) {
lineCount = body.getMaterialList().size();
}
plmReceiveLogService.record(
IPlmReceiveLogService.BIZ_PROCESS_ROUTE,
API_PATH,
orderNo,
payloadJson,
null,
lineCount,
null,
null,
IPlmReceiveLogService.STATUS_FAIL,
e.getMessage(),
clientIp
);
throw e;
}
}
/**
* PLM 工艺入库后按模板导出计划表存到 app.plan-excel.base-dir再按 plan-user-id 推送
*/
private void exportAndPushPlanExcel(String productionOrder) {
try {
ProcessOrderPro order = processOrderProMapper.selectByProjectNumber(productionOrder);
if (order == null || order.getId() == null) {
log.warn("PLM 导出计划表跳过:项目不存在 productionOrder={}", productionOrder);
return;
}
// 复用现有导出PLM 来源会走 generateRoute3ExcelFromPlm
ProcessOrderProController controller = SpringUtils.getBean(ProcessOrderProController.class);
String generatedPath = controller.generateRoute3Excel(order.getId(), true);
File generated = new File(generatedPath);
if (!generated.exists() || generated.length() <= 0) {
log.warn("PLM 导出计划表失败:文件为空 path={}", generatedPath);
return;
}
// 落到固定目录再推送临时生成文件可删
File saved = processPlanExcelPushService.savePlanExcel(productionOrder, generated, generated.getName());
File toSend = saved != null ? saved : generated;
processPlanExcelPushService.sendToPlanUsers(toSend, toSend.getName());
if (saved != null && generated.exists() && !generated.getAbsolutePath().equals(saved.getAbsolutePath())) {
if (!generated.delete()) {
log.warn("删除临时计划表失败: {}", generated.getAbsolutePath());
}
}
} catch (Exception e) {
log.error("PLM 工艺推送后导出/推送计划表失败 productionOrder={}", productionOrder, e);
}
}
private static String resolveClientIp() {
try {
return ServletUtils.getClientIP();
} catch (Exception ignored) {
return null;
}
}
}

View File

@ -0,0 +1,39 @@
package com.ruoyi.system.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.system.domain.vo.PurchaseOrderApprovalQueryVo;
import com.ruoyi.system.runner.JdUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* 金蝶采购订单查询
*/
@RequiredArgsConstructor
@RestController
@RequestMapping("/system/purchaseOrder")
public class PurchaseOrderController extends BaseController {
/**
* 采购订单审批状态分类审批中B重新审批D
*
* @param productionOrderNo 生产令号可选模糊匹配 F_UCHN_Text2
* @param materialCode 物料编码可选精确匹配
*/
@SaCheckPermission("system:workCenterData:list")
@GetMapping("/approval")
public R<PurchaseOrderApprovalQueryVo> approvalQuery(
@RequestParam(required = false) String productionOrderNo,
@RequestParam(required = false) String materialCode) {
try {
return R.ok(JdUtil.getPurchaseOrderApprovalGrouped(productionOrderNo, materialCode));
} catch (Exception e) {
return R.fail("查询采购订单审批数据失败:" + e.getMessage());
}
}
}

View File

@ -0,0 +1,27 @@
package com.ruoyi.system.controller;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.system.domain.dto.ratio.RatioBuildCapacityDTO;
import com.ruoyi.system.service.IRatioBuildCapacityService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.math.BigDecimal;
@RequiredArgsConstructor
@RestController
@RequestMapping("/system/ratio")
public class RatioBuildCapacityController {
private final IRatioBuildCapacityService ratioBuildCapacityService;
@GetMapping("/buildCapacity")
public R<RatioBuildCapacityDTO> buildCapacity(@RequestParam("ratioValue") BigDecimal ratioValue,
@RequestParam("qty") Integer qty) {
return R.ok(ratioBuildCapacityService.queryByRatio(ratioValue, qty));
}
}

View File

@ -23,8 +23,6 @@ import com.ruoyi.system.domain.bo.SfcOperationPlanningMainBo;
import com.ruoyi.system.service.ISfcOperationPlanningMainService;
import com.ruoyi.common.core.page.TableDataInfo;
import cn.dev33.satoken.annotation.SaIgnore;
import com.ruoyi.system.domain.dto.OperationPlanResultDTO;
import com.ruoyi.system.domain.dto.OperationPlanningUpdateOperatorsReq;
@ -71,6 +69,27 @@ public class SfcOperationPlanningMainController extends BaseController {
return iSfcOperationPlanningMainService.queryCascadePageList(bo, pageQuery);
}
/**
* 导出工序进度按生产令号分 Sheet过滤已完工/已关闭
*/
@SaCheckPermission("system:operationPlanningMain:export")
@Log(title = "工序计划进度导出", businessType = BusinessType.EXPORT)
@PostMapping("/exportCascadeProgress")
public void exportCascadeProgress(SfcOperationPlanningMainBo bo, HttpServletResponse response) {
iSfcOperationPlanningMainService.exportCascadeProgress(bo, response);
}
/**
* 项目进度推送生成进度 Excel信息发送机器人私发给配置人员
* <p>接收人见 dingtalk.info-send-user-ids机器人 ding9bhxctsmq5jsf8pk
*/
@SaCheckPermission("system:operationPlanningMain:export")
@Log(title = "项目进度推送", businessType = BusinessType.OTHER)
@PostMapping("/pushCascadeProgress")
public R<String> pushCascadeProgress(SfcOperationPlanningMainBo bo) {
return iSfcOperationPlanningMainService.pushCascadeProgress(bo);
}
@SaCheckPermission("system:operationPlanningMain:updateOperators")
@Log(title = "工序作业人员/设备更新", businessType = BusinessType.UPDATE)
@PutMapping("/updateOperators")

View File

@ -0,0 +1,95 @@
package com.ruoyi.system.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.annotation.RepeatSubmit;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.validate.AddGroup;
import com.ruoyi.common.core.validate.EditGroup;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.system.domain.bo.WorkAlertPushConfigBo;
import com.ruoyi.system.domain.vo.WorkAlertPushConfigVo;
import com.ruoyi.system.service.IWorkAlertPushConfigService;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
/**
* 预警钉钉定时推送配置
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/system/workAlertPushConfig")
public class WorkAlertPushConfigController extends BaseController {
private final IWorkAlertPushConfigService workAlertPushConfigService;
@SaCheckPermission("system:workAlertPushConfig:list")
@GetMapping("/list")
public TableDataInfo<WorkAlertPushConfigVo> list(WorkAlertPushConfigBo bo, PageQuery pageQuery) {
return workAlertPushConfigService.queryPageList(bo, pageQuery);
}
@SaCheckPermission("system:workAlertPushConfig:export")
@Log(title = "预警推送配置", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(WorkAlertPushConfigBo bo, HttpServletResponse response) {
List<WorkAlertPushConfigVo> list = workAlertPushConfigService.queryList(bo);
ExcelUtil.exportExcel(list, "预警推送配置", WorkAlertPushConfigVo.class, response);
}
@SaCheckPermission("system:workAlertPushConfig:query")
@GetMapping("/{id}")
public R<WorkAlertPushConfigVo> getInfo(@NotNull @PathVariable Long id) {
return R.ok(workAlertPushConfigService.queryById(id));
}
@SaCheckPermission("system:workAlertPushConfig:list")
@GetMapping("/pushTypes")
public R<List<Map<String, String>>> pushTypes() {
return R.ok(workAlertPushConfigService.listPushTypeOptions());
}
@SaCheckPermission("system:workAlertPushConfig:add")
@Log(title = "预警推送配置", businessType = BusinessType.INSERT)
@RepeatSubmit
@PostMapping
public R<Void> add(@Validated(AddGroup.class) @RequestBody WorkAlertPushConfigBo bo) {
return toAjax(workAlertPushConfigService.insertByBo(bo));
}
@SaCheckPermission("system:workAlertPushConfig:edit")
@Log(title = "预警推送配置", businessType = BusinessType.UPDATE)
@RepeatSubmit
@PutMapping
public R<Void> edit(@Validated(EditGroup.class) @RequestBody WorkAlertPushConfigBo bo) {
return toAjax(workAlertPushConfigService.updateByBo(bo));
}
@SaCheckPermission("system:workAlertPushConfig:remove")
@Log(title = "预警推送配置", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty @PathVariable Long[] ids) {
return toAjax(workAlertPushConfigService.deleteWithValidByIds(Arrays.asList(ids), true));
}
@SaCheckPermission("system:workAlertPushConfig:trigger")
@Log(title = "预警推送配置", businessType = BusinessType.OTHER)
@PostMapping("/trigger/{id}")
public R<Void> trigger(@NotNull @PathVariable Long id) {
workAlertPushConfigService.triggerPush(id);
return R.ok();
}
}

View File

@ -105,7 +105,7 @@ public class BomDetails extends BaseEntity {
/**
* 子项单重
*/
private Double singleWeghit;
private Double singleWeghit;
/**
*bom类型
*/

View File

@ -0,0 +1,50 @@
package com.ruoyi.system.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.ruoyi.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.Date;
/**
* 项目图纸工作量汇总Sheet1
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("drawing_workload")
public class DrawingWorkload extends BaseEntity {
private static final long serialVersionUID = 1L;
@TableId(type = IdType.AUTO)
private Long id;
/** 项目令号ID */
private Long orderProId;
/** 生产令号 */
private String productionOrderNo;
private Integer a4Count;
private Integer a3Count;
private Integer a3HalfCount;
private Integer a3Plus1Count;
private Integer a2Count;
private Integer a2HalfCount;
private Integer a1Count;
private Integer a1HalfCount;
private Integer a0Count;
private Integer a0HalfCount;
/** 等效A4图纸总数量 */
private Integer equivalentA4Total;
/** 明细行数 */
private Integer itemCount;
/** 最近同步时间 */
private Date syncTime;
}

View File

@ -0,0 +1,38 @@
package com.ruoyi.system.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
/**
* 项目图纸工作量明细Sheet2
*/
@Data
@TableName("drawing_workload_item")
public class DrawingWorkloadItem {
@TableId(type = IdType.AUTO)
private Long id;
/** 汇总ID */
private Long workloadId;
/** 图号 */
private String drawingNo;
/** 名称 */
private String drawingName;
/** 图框名称 */
private String frameName;
/** 图纸幅面 */
private String paperSize;
/** 等效A4图纸数量 */
private Integer equivalentA4;
/** 行序 */
private Integer sortNo;
}

View File

@ -0,0 +1,31 @@
package com.ruoyi.system.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
@Data
@TableName("kingdee_prd_mo")
public class KingdeePrdMo {
@TableId(type = IdType.AUTO)
private Long id;
private String productionOrderNo;
private String billNo;
private String routingNumber;
private String workshopName;
private String materialCode;
private String materialName;
private BigDecimal qty;
private String materialProperty;
private String unitName;
private String planStartDate;
private String planFinishDate;
private String pickMtrlStatus;
private Date receiveTime;
}

View File

@ -0,0 +1,29 @@
package com.ruoyi.system.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
@Data
@TableName("kingdee_purchase_order")
public class KingdeePurchaseOrder {
@TableId(type = IdType.AUTO)
private Long id;
private String productionOrderNo;
private String billNo;
private String materialCode;
private String materialName;
private BigDecimal qty;
private String orderDate;
private String deliveryDate;
private BigDecimal remainStockInQty;
private String mrpCloseStatus;
private String supplierName;
private Date receiveTime;
}

View File

@ -0,0 +1,23 @@
package com.ruoyi.system.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.util.Date;
@Data
@TableName("plm_pdf_zip_push")
public class PlmPdfZipPush {
@TableId(type = IdType.AUTO)
private Long id;
private String productionOrderNo;
private String archiveName;
private String manifestJson;
private String savedDir;
private Integer itemCount;
private Date receiveTime;
}

View File

@ -0,0 +1,33 @@
package com.ruoyi.system.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
@Data
@TableName("plm_pdf_zip_push_item")
public class PlmPdfZipPushItem {
@TableId(type = IdType.AUTO)
private Long id;
private Long pushId;
private String pdfPath;
/** 压缩包内/原始 DWG 路径 */
private String dwgPath;
private String materialCode;
private String materialName;
/** 单台数量 */
private java.math.BigDecimal unitQty;
/** 本批数量 */
private java.math.BigDecimal batchQty;
/** 是否变更图纸PLM: IsDrawingChanaged */
private Boolean isDrawingChanged;
private String savedFileName;
private String savedPath;
/** DWG 落盘文件名 */
private String savedDwgFileName;
/** DWG 落盘完整路径 */
private String savedDwgPath;
}

View File

@ -0,0 +1,50 @@
package com.ruoyi.system.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.util.Date;
/**
* PLM 总装配 BOM / 工艺路线推送接收留痕
*/
@Data
@TableName("plm_receive_log")
public class PlmReceiveLog {
@TableId(type = IdType.AUTO)
private Long id;
/** ASSEMBLY_BOM / PROCESS_ROUTE */
private String bizType;
private String apiPath;
private String productionOrderNo;
/** 完整请求 JSON */
private String payloadJson;
private String payloadSha256;
private Integer payloadSize;
private String summaryJson;
private Integer lineCount;
private Integer savedCount;
private Boolean replaced;
/** SUCCESS / FAIL */
private String status;
private String errorMsg;
private String clientIp;
private Date receiveTime;
}

View File

@ -37,6 +37,10 @@ public class ProcessOrderPro extends BaseEntity {
* 是否可以下载
*/
private Integer isDownload;
/**
* 是否做工艺0否 1是
*/
private Integer needProcess;
/**
* 延期天数
*/
@ -85,7 +89,7 @@ public class ProcessOrderPro extends BaseEntity {
private String drawingPath;
/**
* 项目状态(0方案设计完成,1设计出图完成,2,工艺待审核 3 已推送BOM,4已推送工艺,5已核算MRP, 6开始生产,7生产完成,8 工艺审核完成 )
* 项目状态(0方案设计完成,1设计出图完成,2工艺待审核,3已推送BOM,4已推送工艺,5已核算MRP,6开始生产,7生产完成,8工艺审核完成,9工艺审核拒绝)
*/
private Long bomStatus;
/**
@ -142,4 +146,19 @@ public class ProcessOrderPro extends BaseEntity {
*/
private Integer routePlanSendCount;
/**
* 来源{@link com.ruoyi.system.constant.ProcessOrderProSource#MANUAL} / {@link com.ruoyi.system.constant.ProcessOrderProSource#PLM}
*/
private String source;
/**
* 金蝶生产订单状态0待建 1已建金蝶推送接收后置1
*/
private Integer needKingdeePrdMo;
/**
* 金蝶采购订单状态0待建 1已建金蝶推送接收后置1
*/
private Integer needKingdeePurchaseOrder;
}

View File

@ -1,6 +1,8 @@
package com.ruoyi.system.domain;
import com.alibaba.excel.annotation.ExcelProperty;
import com.ruoyi.common.convert.NullableDoubleConverter;
import com.ruoyi.common.convert.NullableLongConverter;
import lombok.Data;
import java.util.Date;
@ -16,7 +18,7 @@ public class ProcessRouteExcelDTO1 {
@ExcelProperty(index = 2)
private String material;
@ExcelProperty(index = 3)
@ExcelProperty(index = 3, converter = NullableDoubleConverter.class)
private Double discWeight;
@ExcelProperty(index = 4)
@ -28,7 +30,7 @@ public class ProcessRouteExcelDTO1 {
@ExcelProperty(index = 6)
private String bomMaterial;
@ExcelProperty(index = 7)
@ExcelProperty(index = 7, converter = NullableDoubleConverter.class)
private Double bomDanZhong;
@ExcelProperty(index = 8)
@ -37,7 +39,7 @@ public class ProcessRouteExcelDTO1 {
@ExcelProperty(index = 9)
private String bomUnit;
@ExcelProperty(index = 10)
@ExcelProperty(index = 10, converter = NullableLongConverter.class)
private Long processNo;
@ExcelProperty(index = 11)
@ -52,16 +54,16 @@ public class ProcessRouteExcelDTO1 {
@ExcelProperty(index = 14)
private String processControl;
@ExcelProperty(index = 15)
@ExcelProperty(index = 15, converter = NullableDoubleConverter.class)
private Double activityDuration;
@ExcelProperty(index = 16)
private String activityUnit;
@ExcelProperty(index = 17)
@ExcelProperty(index = 17, converter = NullableDoubleConverter.class)
private Double unitQuantity;
@ExcelProperty(index = 18)
@ExcelProperty(index = 18, converter = NullableLongConverter.class)
private Long batchQuantity;
@ExcelProperty(index = 19)

View File

@ -1,81 +1,86 @@
package com.ruoyi.system.domain;
import com.baomidou.mybatisplus.annotation.*;
import com.ruoyi.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.math.BigDecimal;
/**
* 生产订单对象 production_order
*
* @author 田志阳
* @date 2024-10-20
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("production_order")
public class ProductionOrder extends BaseEntity {
private static final long serialVersionUID=1L;
/**
* ID
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 生产令号
*/
private String productionOrderNo;
/**
* 生产图号
*/
private String drawingNo;
/**
* 生产名称
*/
private String drawingName;
/**
* 生产数量
*/
private Double quantity;
/**
* 生产材料
*/
private String material;
/**
* 单重kg
*/
private Double singleWeight;
/**
* 总重kg
*/
private Double totalWeight;
/**
* 备注
*/
private String remark;
/**
* 部件名称
*/
private String parentPart;
/**
* 部件图号
*/
private String parentDrawingNo;
/**
* 主产品名称
*/
private String mainName;
/**
* 主产品图号
*/
private String mainPart;
/**
* 批次数量
*/
private String batchQuantity;
}
package com.ruoyi.system.domain;
import com.baomidou.mybatisplus.annotation.*;
import com.ruoyi.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.math.BigDecimal;
/**
* 生产订单对象 production_order
*
* @author 田志阳
* @date 2024-10-20
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("production_order")
public class ProductionOrder extends BaseEntity {
private static final long serialVersionUID=1L;
/**
* ID
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 生产令号
*/
private String productionOrderNo;
/**
* 生产图号
*/
private String drawingNo;
/**
* 生产名称
*/
private String drawingName;
/**
* 单台数量
*/
private Double quantity;
/**
* 生产材料
*/
private String material;
/**
* 单重kg
*/
private Double singleWeight;
/**
* 总重kg
*/
private Double totalWeight;
/**
* 备注
*/
private String remark;
/**
* 部件名称
*/
private String parentPart;
/**
* 部件图号
*/
private String parentDrawingNo;
/**
* 主产品名称
*/
private String mainName;
/**
* 主产品图号
*/
private String mainPart;
/**
* 批次数量
*/
private String batchQuantity;
/**
* 零件类型标准件/自制件/外购件等
*/
private String prtType;
}

View File

@ -0,0 +1,32 @@
package com.ruoyi.system.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.ruoyi.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("ratio_accessory")
public class RatioAccessory extends BaseEntity {
@TableId(value = "id", type = IdType.AUTO)
private Long id;
private Long ratioConfigId;
private String materialCode;
private String materialName;
private String danzhong;
private String canzhi;
private String partCategory;
private Integer status;
}

View File

@ -0,0 +1,28 @@
package com.ruoyi.system.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.ruoyi.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.math.BigDecimal;
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("ratio_config")
public class RatioConfig extends BaseEntity {
@TableId(value = "id", type = IdType.AUTO)
private Long id;
private BigDecimal ratioValue;
private BigDecimal maxTorqueNm;
private Integer status;
private String remark;
}

View File

@ -0,0 +1,59 @@
package com.ruoyi.system.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.Date;
/**
* 预警钉钉定时推送配置 work_alert_push_config
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("work_alert_push_config")
public class WorkAlertPushConfig extends BaseEntity {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/** 推送任务编码 */
private String pushCode;
/** 推送名称 */
private String pushName;
/** 每日推送时间 HH:mm */
private String pushTime;
/** 钉钉用户 StaffId逗号分隔 */
private String dingUserIds;
/** 分对象接收人 JSON如 {"机一工段":"staffId1,staffId2"} */
private String recipientRules;
/** 群会话 ID */
private String openConversationId;
/** 机器人 Code */
private String robotCode;
/** 是否启用 0否 1是 */
private String enabled;
/** 上次推送日期 */
@JsonFormat(pattern = "yyyy-MM-dd")
private Date lastPushDate;
/** 排序 */
private Integer sortOrder;
/** 备注 */
private String remark;
}

View File

@ -0,0 +1,21 @@
package com.ruoyi.system.domain.bo;
import com.ruoyi.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 钉钉技术方案申请归档查询条件
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class DingSchemeApplicationBo extends BaseEntity {
private Long id;
private String schemeApplyNo;
private String overviewName;
private String fillerName;
private String customerFullName;
private String productName;
private String plmPushStatus;
}

View File

@ -0,0 +1,18 @@
package com.ruoyi.system.domain.bo;
import lombok.Data;
import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;
import java.util.List;
/**
* 金蝶批量推送多个生产令号下的生产/采购订单
*/
@Data
public class KingdeeOrderReceiveBatchBo {
@NotEmpty(message = "订单列表不能为空")
@Valid
private List<KingdeeOrderReceiveBo> items;
}

View File

@ -0,0 +1,22 @@
package com.ruoyi.system.domain.bo;
import com.ruoyi.system.domain.dto.KingdeePrdMoDTO;
import com.ruoyi.system.domain.dto.KingdeePurchaseOrderDTO;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import java.util.List;
/**
* 金蝶推送一个生产令号下的生产订单 + 采购订单
*/
@Data
public class KingdeeOrderReceiveBo {
@NotBlank(message = "生产令号不能为空")
private String productionOrderNo;
private List<KingdeePrdMoDTO> prdMoList;
private List<KingdeePurchaseOrderDTO> purchaseOrderList;
}

View File

@ -129,4 +129,19 @@ public class KingdeeWorkCenterDataBo extends BaseEntity {
*/
private BigDecimal FScrapQty;
/** 上一序工序号(工艺路线) */
private String prevOperNumber;
/** 上一序工序名称 */
private String prevProcessName;
/** 上一序工作中心 */
private String prevWorkCenter;
/** 查路线使用的物料编码(-MP 物料为去后缀后编码) */
private String prevRouteMaterialCode;
/** 上一序状态:未质检 / 质检未入库 / 上一序未转出 等 */
private String prevOperStatus;
}

Some files were not shown because too many files have changed in this diff Show More