07eafe2cff11f5795c60e05ff12d59db42781361..23182f2c951df5fa55e70e30ff70ddaf91199a2e
8 天以前 zhang
1
23182f 对比 | 目录
8 天以前 zhang
1
d35e2a 对比 | 目录
8 天以前 zhang
Merge branch 'refs/heads/rcs_master' into ctu_conveyor
af5081 对比 | 目录
8 天以前 vincentlu
#
98ddfb 对比 | 目录
8 天以前 vincentlu
#
bfd367 对比 | 目录
8 天以前 vincentlu
#
045eab 对比 | 目录
8 天以前 vincentlu
#
c70ea1 对比 | 目录
8 天以前 vincentlu
#
6aa922 对比 | 目录
8 天以前 vincentlu
#
3c65b4 对比 | 目录
8 天以前 vincentlu
#
9f658f 对比 | 目录
8 天以前 vincentlu
#
0e34b4 对比 | 目录
8 天以前 vincentlu
#
ca9d13 对比 | 目录
9 天以前 luxiaotao1123
#
d997d9 对比 | 目录
9 天以前 luxiaotao1123
#
267cb7 对比 | 目录
9 天以前 luxiaotao1123
#
b22c77 对比 | 目录
9 天以前 luxiaotao1123
#
3e6cd2 对比 | 目录
9 天以前 luxiaotao1123
#
bd4b71 对比 | 目录
2026-02-02 vincentlu
#
15b4f0 对比 | 目录
2026-02-02 vincentlu
#
827e7d 对比 | 目录
2026-02-02 vincentlu
#
d125cd 对比 | 目录
2026-02-02 vincentlu
#
5c3f2c 对比 | 目录
2026-02-02 vincentlu
#
a493cc 对比 | 目录
2026-02-02 vincentlu
#
0267cc 对比 | 目录
2026-02-02 vincentlu
#
d67321 对比 | 目录
2026-02-02 vincentlu
#
558eac 对比 | 目录
2026-02-02 vincentlu
#
264c93 对比 | 目录
2026-02-02 vincentlu
Merge remote-tracking branch 'origin/rcs_master' into rcs_master
064337 对比 | 目录
2026-02-02 vincentlu
#
6ad413 对比 | 目录
2026-02-02 vincentlu
#
a476b3 对比 | 目录
2026-02-02 vincentlu
#
1c00a6 对比 | 目录
2026-02-02 vincentlu
#
ad04df 对比 | 目录
2026-02-02 vincentlu
#
f6aec4 对比 | 目录
2026-01-30 vincentlu
#
2ea9c3 对比 | 目录
2026-01-30 vincentlu
#
3f70b7 对比 | 目录
2026-01-30 vincentlu
#
7f4dd7 对比 | 目录
2026-01-30 vincentlu
#
08dcfb 对比 | 目录
2026-01-30 vincentlu
#
e9e8c6 对比 | 目录
2026-01-30 vincentlu
#
225130 对比 | 目录
2026-02-02 vincentlu
#
53c6a3 对比 | 目录
2026-02-02 vincentlu
#
067ea0 对比 | 目录
2026-02-02 vincentlu
#
020ed9 对比 | 目录
2026-02-02 vincentlu
#
027539 对比 | 目录
2026-01-30 vincentlu
#
6773ee 对比 | 目录
2026-01-30 vincentlu
#
a0916a 对比 | 目录
2026-01-30 vincentlu
#
88cce6 对比 | 目录
2026-01-30 vincentlu
#
1a1035 对比 | 目录
2026-01-30 vincentlu
#
fb9bc1 对比 | 目录
2026-01-30 vincentlu
#
bb71a2 对比 | 目录
8个文件已删除
8 文件已重命名
49个文件已添加
56个文件已修改
4446 ■■■■ 已修改文件
component/component-Influxdb/pom.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
component/component-Influxdb/src/main/java/com/zy/component/influxdb/config/InfluxDBAutoConfiguration.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
component/component-Influxdb/src/main/java/com/zy/component/influxdb/properties/InfluxDBProperties.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
component/component-Influxdb/src/main/java/com/zy/component/influxdb/service/InfluxDBService.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
component/component-Influxdb/src/main/resources/META-INF/additional-spring-configuration-metadata.json 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
component/component-Influxdb/src/main/resources/META-INF/spring.factories 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
component/component-Influxdb/target/classes/META-INF/additional-spring-configuration-metadata.json 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
component/component-Influxdb/target/classes/META-INF/spring-configuration-metadata.json 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
component/component-Influxdb/target/classes/META-INF/spring.factories 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
component/component-Influxdb/target/classes/com/zy/component/influxdb/config/InfluxDBAutoConfiguration.class 补丁 | 查看 | 原始文档 | blame | 历史
component/component-Influxdb/target/classes/com/zy/component/influxdb/properties/InfluxDBProperties.class 补丁 | 查看 | 原始文档 | blame | 历史
component/component-Influxdb/target/classes/com/zy/component/influxdb/service/InfluxDBService.class 补丁 | 查看 | 原始文档 | blame | 历史
component/component-Influxdb/target/classes/com/zy/influxdb/base/BaseTemperature.class 补丁 | 查看 | 原始文档 | blame | 历史
component/component-Influxdb/target/classes/com/zy/influxdb/config/InfluxDBAutoConfiguration.class 补丁 | 查看 | 原始文档 | blame | 历史
component/component-Influxdb/target/classes/com/zy/influxdb/config/InfluxDBProperties.class 补丁 | 查看 | 原始文档 | blame | 历史
component/component-Influxdb/target/classes/com/zy/influxdb/service/InfluxDBService.class 补丁 | 查看 | 原始文档 | blame | 历史
component/component-Influxdb/target/component-Influxdb-1.0.0.jar 补丁 | 查看 | 原始文档 | blame | 历史
component/component-Influxdb/target/maven-archiver/pom.properties 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
component/component-Influxdb/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
component/component-Influxdb/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
component/component-Influxdb/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst 补丁 | 查看 | 原始文档 | blame | 历史
component/component-Influxdb/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst 补丁 | 查看 | 原始文档 | blame | 历史
version/db/new.sql 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
version/db/sqlIndex 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
version/doc/RCS开发进度表.xlsx 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-common/src/main/java/com/zy/acs/common/enums/ActuatorDirectionType.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-common/src/main/java/com/zy/acs/common/enums/AgvDirectionType.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-cv/src/main/java/com/zy/core/operation/handler/InOperationHandler.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-flow/package-lock.json 106 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-flow/package.json 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-flow/public/imports/code_import_template.xlsx 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-flow/src/i18n/en.js 54 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-flow/src/i18n/zh.js 56 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-flow/src/page/ResourceContent.js 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-flow/src/page/code/CodeList.jsx 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-flow/src/page/components/ImportButton.jsx 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-flow/src/page/components/ImportTxtModal.jsx 213 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-flow/src/page/components/ImportXlsxModal.jsx 191 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-flow/src/page/components/useExcelParse.js 77 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-flow/src/page/integrationRecord/IntegrationRecordCreate.jsx 207 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-flow/src/page/integrationRecord/IntegrationRecordEdit.jsx 180 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-flow/src/page/integrationRecord/IntegrationRecordList.jsx 173 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-flow/src/page/integrationRecord/IntegrationRecordPanel.jsx 129 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-flow/src/page/integrationRecord/index.jsx 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-flow/src/page/loc/LocCreate.jsx 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-flow/src/page/loc/LocEdit.jsx 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-flow/src/page/loc/LocInit.jsx 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-flow/src/page/loc/LocList.jsx 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-flow/src/page/loc/LocPanel.jsx 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-flow/src/page/loc/compDirect.js 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-flow/src/page/sta/StaCreate.jsx 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-flow/src/page/sta/StaEdit.jsx 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-flow/src/page/sta/StaList.jsx 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-flow/src/page/sta/StaPanel.jsx 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-flow/src/page/staReserve/StaReserveList.jsx 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-flow/src/page/task/TaskList.jsx 301 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-flow/src/page/task/TaskListAside.jsx 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-framework/src/main/java/com/zy/acs/framework/annotations/IntegrationAuth.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-hex/pom.xml 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-hex/src/main/java/com/zy/acs/hex/HexApplication.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-hex/src/main/java/com/zy/acs/hex/config/MessageConverterConfig.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-hex/src/main/java/com/zy/acs/hex/config/RabbitConfig.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-hex/src/main/java/com/zy/acs/hex/constant/InfluxDBConstant.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-hex/src/main/java/com/zy/acs/hex/constant/RabbitConstant.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-hex/src/main/java/com/zy/acs/hex/consumer/DownMessageListener.java 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-hex/src/main/java/com/zy/acs/hex/consumer/MessageListener.java 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-hex/src/main/java/com/zy/acs/hex/consumer/UpMessageListener.java 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-hex/src/main/java/com/zy/acs/hex/consumer/listener/AbstractListener.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-hex/src/main/java/com/zy/acs/hex/controller/TestController.java 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-hex/src/main/java/com/zy/acs/hex/domain/Device.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-hex/src/main/java/com/zy/acs/hex/utils/ReflectionUtils.java 171 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-hex/src/main/java/com/zy/acs/hex/utils/StrUtils.java 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-hex/src/main/resources/application.yml 28 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/common/CodeBuilder.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/common/config/ConveyorProperties.java 26 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/common/config/IntegrationRecordAdvice.java 84 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/common/config/UplinkProperties.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/common/constant/Constants.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/common/domain/TaskBoolDto.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/common/domain/TaskDto.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/common/utils/ExcelUtil.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/common/utils/HttpGo.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/core/HandlerController.java 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/core/domain/type/NamespaceType.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/core/integrate/conveyor/ConveyorController.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/core/integrate/conveyor/SiemensConveyorStationService.java 67 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/core/integrate/dto/OpenBusCancelParam.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/core/integrate/dto/OpenBusCancelResult.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/core/integrate/dto/OpenBusSubmitParam.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/core/integrate/dto/TaskUplinkParam.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/core/integrate/wms/OpenController.java 87 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/core/integrate/wms/TaskReportService.java 180 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/core/scheduler/AutoTestDeviationScheduler.java 149 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/core/scheduler/MaintainScheduler.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/core/scheduler/test/AutoRunRebootScheduler.java 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/core/scheduler/test/AutoRunScheduler.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/core/scheduler/test/ConveyorAutoRunScheduler.java 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/MainService.java 104 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/MapService.java 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/ValidService.java 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/manager/controller/BusController.java 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/manager/controller/CodeController.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/manager/controller/IntegrationRecordController.java 108 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/manager/controller/TaskController.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/manager/entity/IntegrationRecord.java 196 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/manager/entity/Loc.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/manager/entity/Sta.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/manager/entity/Task.java 102 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/manager/enums/IntegrationDirectionType.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/manager/enums/TaskUplinkStateType.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/manager/mapper/IntegrationRecordMapper.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/manager/service/BusService.java 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/manager/service/IntegrationRecordService.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/manager/service/TaskService.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/manager/service/impl/BusServiceImpl.java 21 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/manager/service/impl/IntegrationRecordServiceImpl.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/com/zy/acs/manager/manager/service/impl/TaskServiceImpl.java 129 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/java/integrationRecord.sql 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/resources/application.yml 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/resources/mapper/manager/IntegrationRecordMapper.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
zy-acs-manager/src/main/resources/mapper/manager/TaskMapper.xml 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
component/component-Influxdb/pom.xml
@@ -42,11 +42,6 @@
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
component/component-Influxdb/src/main/java/com/zy/component/influxdb/config/InfluxDBAutoConfiguration.java
File was renamed from component/component-Influxdb/src/main/java/com/zy/influxdb/config/InfluxDBAutoConfiguration.java
@@ -1,6 +1,7 @@
package com.zy.influxdb.config;
package com.zy.component.influxdb.config;
import com.influxdb.v3.client.InfluxDBClient;
import com.zy.component.influxdb.properties.InfluxDBProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
component/component-Influxdb/src/main/java/com/zy/component/influxdb/properties/InfluxDBProperties.java
File was renamed from component/component-Influxdb/src/main/java/com/zy/influxdb/config/InfluxDBProperties.java
@@ -1,4 +1,4 @@
package com.zy.influxdb.config;
package com.zy.component.influxdb.properties;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
component/component-Influxdb/src/main/java/com/zy/component/influxdb/service/InfluxDBService.java
File was renamed from component/component-Influxdb/src/main/java/com/zy/influxdb/service/InfluxDBService.java
@@ -1,9 +1,8 @@
package com.zy.influxdb.service;
package com.zy.component.influxdb.service;
import com.influxdb.v3.client.InfluxDBClient;
import com.influxdb.v3.client.Point;
import com.influxdb.v3.client.write.WritePrecision;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -41,7 +40,6 @@
                .setTimestamp(Instant.now().toEpochMilli(), WritePrecision.MS);
        try {
            influxDBClient.writePoint(point);
            System.out.println("Data written to the database.");
        } catch (Exception e) {
            logger.error("Failed to write data to the database.");
            e.printStackTrace();
@@ -58,6 +56,7 @@
        try {
            // æ‰§è¡ŒæŸ¥è¯¢
            Stream<Object[]> query = influxDBClient.query(sql);
            logger.info("查询数据:{}", query);
            // è½¬æ¢ä¸º Map åˆ—表(便于后续处理)
            List<Map<String, Object>> collect = query.map(record -> {
                        Map<String, Object> map = new LinkedHashMap<>();
component/component-Influxdb/src/main/resources/META-INF/additional-spring-configuration-metadata.json
New file
@@ -0,0 +1,10 @@
{
  "properties": [
    {
      "name": "influxdb3.enabled",
      "type": "java.lang.Boolean",
      "description": "Enables influxdb functionality.",
      "defaultValue": "true"
    }
  ]
}
component/component-Influxdb/src/main/resources/META-INF/spring.factories
@@ -1,2 +1 @@
com.zy.influxdb.service.InfluxDBService
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.zy.component.influxdb.service.InfluxDBService
component/component-Influxdb/target/classes/META-INF/additional-spring-configuration-metadata.json
New file
@@ -0,0 +1,10 @@
{
  "properties": [
    {
      "name": "influxdb3.enabled",
      "type": "java.lang.Boolean",
      "description": "Enables influxdb functionality.",
      "defaultValue": "true"
    }
  ]
}
component/component-Influxdb/target/classes/META-INF/spring-configuration-metadata.json
@@ -14,6 +14,12 @@
      "sourceType": "com.zy.influxdb.config.InfluxDBProperties"
    },
    {
      "name": "influxdb3.enabled",
      "type": "java.lang.Boolean",
      "description": "Enables mqtt functionality.",
      "defaultValue": "true"
    },
    {
      "name": "influxdb3.token",
      "type": "java.lang.String",
      "description": "token",
component/component-Influxdb/target/classes/META-INF/spring.factories
@@ -1,2 +1 @@
com.zy.influxdb.service.InfluxDBService
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.zy.component.influxdb.service.InfluxDBService
component/component-Influxdb/target/classes/com/zy/component/influxdb/config/InfluxDBAutoConfiguration.class
Binary files differ
component/component-Influxdb/target/classes/com/zy/component/influxdb/properties/InfluxDBProperties.class
Binary files differ
component/component-Influxdb/target/classes/com/zy/component/influxdb/service/InfluxDBService.class
Binary files differ
component/component-Influxdb/target/classes/com/zy/influxdb/base/BaseTemperature.class
Binary files differ
component/component-Influxdb/target/classes/com/zy/influxdb/config/InfluxDBAutoConfiguration.class
Binary files differ
component/component-Influxdb/target/classes/com/zy/influxdb/config/InfluxDBProperties.class
Binary files differ
component/component-Influxdb/target/classes/com/zy/influxdb/service/InfluxDBService.class
Binary files differ
component/component-Influxdb/target/component-Influxdb-1.0.0.jar
Binary files differ
component/component-Influxdb/target/maven-archiver/pom.properties
New file
@@ -0,0 +1,3 @@
artifactId=component-Influxdb
groupId=com.zy
version=1.0.0
component/component-Influxdb/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst
New file
@@ -0,0 +1,3 @@
com\zy\component\influxdb\service\InfluxDBService.class
com\zy\component\influxdb\config\InfluxDBAutoConfiguration.class
com\zy\component\influxdb\properties\InfluxDBProperties.class
component/component-Influxdb/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst
New file
@@ -0,0 +1,3 @@
D:\office\code\rcs-flow\component\component-Influxdb\src\main\java\com\zy\influxdb\config\InfluxDBProperties.java
D:\office\code\rcs-flow\component\component-Influxdb\src\main\java\com\zy\influxdb\service\InfluxDBService.java
D:\office\code\rcs-flow\component\component-Influxdb\src\main\java\com\zy\influxdb\config\InfluxDBAutoConfiguration.java
component/component-Influxdb/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst
component/component-Influxdb/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst
version/db/new.sql
@@ -29,3 +29,37 @@
alter table man_sta
    add outbound_wait int null comment '连续出库等待' after inbound_wait;
alter table man_task
    add uplink_sts varchar(64) null comment '上行状态' after empty_mk;
alter table man_task_log
    add uplink_sts varchar(64) null comment '上行状态' after empty_mk;
CREATE TABLE `man_integration_record` (
    `id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
    `uuid` VARCHAR(255) DEFAULT NULL COMMENT '编号',
    `namespace` VARCHAR(255) DEFAULT NULL COMMENT '名称空间(*)',
    `url` VARCHAR(255) DEFAULT NULL COMMENT '接口地址',
    `appkey` VARCHAR(255) DEFAULT NULL COMMENT '平台密钥',
    `caller` VARCHAR(255) DEFAULT NULL COMMENT '调用方标识',
    `direction` int(1) NOT NULL DEFAULT 0 COMMENT '方向{1:被调用,2:调用外部}',
    `timestamp` VARCHAR(64) DEFAULT NULL COMMENT '时间戳',
    `client_ip` VARCHAR(64) DEFAULT NULL COMMENT '客户端IP',
    `request` TEXT COMMENT '请求内容',
    `response` TEXT COMMENT '响应内容',
    `err` TEXT COMMENT '异常内容',
    `result` int(1) DEFAULT NULL COMMENT '结果{1:成功,0:失败}',
    `cost_ms` INT(11) DEFAULT NULL COMMENT '耗时',
    `status` int(1) DEFAULT 1 COMMENT '状态{1:正常,0:冻结}',
    `create_time` timestamp DEFAULT CURRENT_TIMESTAMP COMMENT '添加时间',
    `update_time` timestamp DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
    `memo` VARCHAR(255) DEFAULT NULL COMMENT '备注',
    PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
update man_loc set comp_direct =2  where comp_direct =0
alter table man_sta
    add act_dir int(1) null comment '货叉方向' after angle;
version/db/sqlIndex
@@ -25,6 +25,7 @@
CREATE INDEX idx_task_seq_num ON man_task(seq_num);
CREATE INDEX idx_task_agv_id ON man_task(agv_id);
CREATE INDEX idx_task_agv_id_task_sts ON man_task(agv_id, task_sts);
CREATE INDEX idx_task_task_sts_uplink_sts ON man_task(task_sts, uplink_sts);
# man_zone
CREATE INDEX idx_zone_uuid ON man_zone(uuid);
# man_agv_detail
version/doc/RCS¿ª·¢½ø¶È±í.xlsx
Binary files differ
zy-acs-common/src/main/java/com/zy/acs/common/enums/ActuatorDirectionType.java
New file
@@ -0,0 +1,30 @@
package com.zy.acs.common.enums;
import com.zy.acs.framework.exception.CoolException;
public enum ActuatorDirectionType {
    LEFT(1),
    RIGHT(2),
    FORWARD(3),
    ;
    public int val;
    ActuatorDirectionType(int val) {
        this.val = val;
    }
    public static ActuatorDirectionType fromVal(Integer val) {
        if (null == val) {
            throw new CoolException("actuator direction param val is null");
        }
        for (ActuatorDirectionType type : ActuatorDirectionType.values()) {
            if (type.val == val) {
                return type;
            }
        }
        throw new IllegalArgumentException("Invalid ActuatorDirectionType: " + val);
    }
}
zy-acs-common/src/main/java/com/zy/acs/common/enums/AgvDirectionType.java
File was deleted
zy-acs-cv/src/main/java/com/zy/core/operation/handler/InOperationHandler.java
@@ -75,10 +75,10 @@
                            if (job != null) {
                                Integer workNo = staProtocol.getWorkNo();
                                Integer targetSta = inSta.getTargetSta();
//                                staProtocol.setWorkNo(0);
//                                staProtocol.setStaNo(0);
//                                MessageQueue.offer(SlaveType.Devp, 1, new Task(2, staProtocol));
//                                Thread.sleep(1500L);
                                staProtocol.setWorkNo(0);
                                staProtocol.setStaNo(0);
                                MessageQueue.offer(SlaveType.Devp, 1, new Task(2, staProtocol));
                                Thread.sleep(1500L);
                                staProtocol.setWorkNo(workNo);
                                staProtocol.setStaNo(targetSta);
                                boolean result = MessageQueue.offer(SlaveType.Devp, 1, new Task(2, staProtocol));
zy-acs-flow/package-lock.json
@@ -24,7 +24,8 @@
        "react-router-dom": "^6.26.1",
        "react-syntax-highlighter": "^15.5.0",
        "three": "^0.155.0",
        "tweedle.js": "^2.1.0"
        "tweedle.js": "^2.1.0",
        "xlsx": "^0.18.5"
      },
      "devDependencies": {
        "@types/node": "^20.10.7",
@@ -2339,6 +2340,15 @@
        "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
      }
    },
    "node_modules/adler-32": {
      "version": "1.3.1",
      "resolved": "https://registry.npmjs.org/adler-32/-/adler-32-1.3.1.tgz",
      "integrity": "sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==",
      "license": "Apache-2.0",
      "engines": {
        "node": ">=0.8"
      }
    },
    "node_modules/ajv": {
      "version": "6.12.6",
      "resolved": "https://registry.npmmirror.com/ajv/-/ajv-6.12.6.tgz",
@@ -2702,6 +2712,19 @@
        }
      ]
    },
    "node_modules/cfb": {
      "version": "1.2.2",
      "resolved": "https://registry.npmjs.org/cfb/-/cfb-1.2.2.tgz",
      "integrity": "sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==",
      "license": "Apache-2.0",
      "dependencies": {
        "adler-32": "~1.3.0",
        "crc-32": "~1.2.0"
      },
      "engines": {
        "node": ">=0.8"
      }
    },
    "node_modules/chalk": {
      "version": "2.4.2",
      "resolved": "https://registry.npmmirror.com/chalk/-/chalk-2.4.2.tgz",
@@ -2748,6 +2771,15 @@
      "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
      "engines": {
        "node": ">=6"
      }
    },
    "node_modules/codepage": {
      "version": "1.15.0",
      "resolved": "https://registry.npmjs.org/codepage/-/codepage-1.15.0.tgz",
      "integrity": "sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==",
      "license": "Apache-2.0",
      "engines": {
        "node": ">=0.8"
      }
    },
    "node_modules/color-convert": {
@@ -2808,6 +2840,18 @@
      },
      "engines": {
        "node": ">=10"
      }
    },
    "node_modules/crc-32": {
      "version": "1.2.2",
      "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz",
      "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==",
      "license": "Apache-2.0",
      "bin": {
        "crc32": "bin/crc32.njs"
      },
      "engines": {
        "node": ">=0.8"
      }
    },
    "node_modules/cross-spawn": {
@@ -3785,6 +3829,15 @@
      "integrity": "sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==",
      "engines": {
        "node": ">=0.4.x"
      }
    },
    "node_modules/frac": {
      "version": "1.1.2",
      "resolved": "https://registry.npmjs.org/frac/-/frac-1.1.2.tgz",
      "integrity": "sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==",
      "license": "Apache-2.0",
      "engines": {
        "node": ">=0.8"
      }
    },
    "node_modules/fs.realpath": {
@@ -5982,6 +6035,18 @@
        "node": ">=6"
      }
    },
    "node_modules/ssf": {
      "version": "0.11.2",
      "resolved": "https://registry.npmjs.org/ssf/-/ssf-0.11.2.tgz",
      "integrity": "sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==",
      "license": "Apache-2.0",
      "dependencies": {
        "frac": "~1.1.2"
      },
      "engines": {
        "node": ">=0.8"
      }
    },
    "node_modules/strict-uri-encode": {
      "version": "2.0.0",
      "resolved": "https://registry.npmmirror.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz",
@@ -6552,6 +6617,24 @@
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/wmf": {
      "version": "1.0.2",
      "resolved": "https://registry.npmjs.org/wmf/-/wmf-1.0.2.tgz",
      "integrity": "sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==",
      "license": "Apache-2.0",
      "engines": {
        "node": ">=0.8"
      }
    },
    "node_modules/word": {
      "version": "0.3.0",
      "resolved": "https://registry.npmjs.org/word/-/word-0.3.0.tgz",
      "integrity": "sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA==",
      "license": "Apache-2.0",
      "engines": {
        "node": ">=0.8"
      }
    },
    "node_modules/word-wrap": {
      "version": "1.2.5",
      "resolved": "https://registry.npmmirror.com/word-wrap/-/word-wrap-1.2.5.tgz",
@@ -6567,6 +6650,27 @@
      "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
      "dev": true
    },
    "node_modules/xlsx": {
      "version": "0.18.5",
      "resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.18.5.tgz",
      "integrity": "sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==",
      "license": "Apache-2.0",
      "dependencies": {
        "adler-32": "~1.3.0",
        "cfb": "~1.2.1",
        "codepage": "~1.15.0",
        "crc-32": "~1.2.1",
        "ssf": "~0.11.2",
        "wmf": "~1.0.1",
        "word": "~0.3.0"
      },
      "bin": {
        "xlsx": "bin/xlsx.njs"
      },
      "engines": {
        "node": ">=0.8"
      }
    },
    "node_modules/xtend": {
      "version": "4.0.2",
      "resolved": "https://registry.npmmirror.com/xtend/-/xtend-4.0.2.tgz",
zy-acs-flow/package.json
@@ -28,7 +28,8 @@
    "react-router-dom": "^6.26.1",
    "react-syntax-highlighter": "^15.5.0",
    "three": "^0.155.0",
    "tweedle.js": "^2.1.0"
    "tweedle.js": "^2.1.0",
    "xlsx": "^0.18.5"
  },
  "devDependencies": {
    "@types/node": "^20.10.7",
@@ -46,4 +47,4 @@
    "vite": "^5.3.5"
  },
  "name": "cool-admin-flow"
}
}
zy-acs-flow/public/imports/code_import_template.xlsx
Binary files differ
zy-acs-flow/src/i18n/en.js
@@ -62,9 +62,9 @@
            import: {
                title: 'Import',
                stop: 'Stop import',
                msg: 'Here is a sample CSV file you can use as a template',
                msg: 'Here is a sample file you can use as a template',
                tips: 'The import is running, please do not close this tab.',
                err: 'Failed to import this file, please make sure your provided a valid CSV file.',
                err: 'Failed to import this file, please make sure your provided a valid file.',
                download: 'Download Import Template',
                result: 'Contacts import complete. Imported %{success} success, with %{error} errors',
            },
@@ -158,6 +158,7 @@
        mission: 'Mission',
        staReserve: 'Sta Reserve',
        lane: 'Lane',
        integrationRecord: 'Integration',
    },
    table: {
        field: {
@@ -288,11 +289,12 @@
                staType: "station type",
                code: "code",
                offset: "offset",
                height: "height",
                depth: "depth",
                height: "height(mm)",
                depth: "depth(mm)",
                angle: 'angle',
                inboundWait: 'inbound wait(ms)',
                outboundWait: 'outbound wait(ms)',
                actDir: 'actuator direction',
                inboundWait: 'in wait(ms)',
                outboundWait: 'out wait(ms)',
                autoing: "autoing",
                loading: "loading",
                inEnable: "in enable",
@@ -342,9 +344,9 @@
                locNo: "loc No.",
                name: "name",
                code: "code",
                compDirect: "code direct",
                compDirect: "actuator direction",
                locSts: "loc sts",
                offset: "offset",
                offset: "height",
                row: "row",
                bay: "bay",
                lev: "lev",
@@ -485,6 +487,7 @@
                destLoc: "dest loc",
                destCode: "dest code",
                emptyMk: "empty mk",
                uplinkSts: "uplink status",
                zpallet: "zpallet",
                phase: "ideal path",
                errDesc: "error",
@@ -603,6 +606,22 @@
                entryAngle: "entry angle",
                maximum: "maximum",
            },
            integrationRecord: {
                uuid: "uuid",
                namespace: "namespace",
                url: "url",
                appkey: "appkey",
                caller: "caller",
                direction: "direction",
                timestamp: "timestamp",
                clientIp: "clientIp",
                request: "request",
                response: "response",
                err: "error",
                result: "result",
                costMs: "costMs",
            },
        }
    },
    page: {
@@ -669,6 +688,13 @@
            },
            levOffset: 'lev offset',
            bottomOffset: 'bottom offset',
            enums: {
                compDirect: {
                    left: 'Left',
                    right: 'Right',
                    forward: 'Forward',
                },
            },
        },
        sta: {
            depthHint: 'Set depth to 0 to keep the default value.',
@@ -720,6 +746,18 @@
                reposition: 'clear path reposition',
            }
        },
        task: {
            enums: {
                uplinkSts: {
                    NONE: 'Unknown',
                    PENDING: 'Pending',
                    SENDING: 'Uploading',
                    SUCCESS: 'Success',
                    FAILED: 'Failed',
                    SKIPPED: 'Skipped',
                },
            },
        },
        segment: {
            enums: {
                state: {
zy-acs-flow/src/i18n/zh.js
@@ -62,9 +62,9 @@
            import: {
                title: '导入',
                stop: '停止导入',
                msg: '这是一个可以用作模板的示例 CSV æ–‡ä»¶',
                msg: '这是一个可以用作模板的示例文件',
                tips: '正在导入中,请不要关闭此窗口',
                err: '无法导入此文件,请确保您提供了有效的 CSV æ–‡ä»¶',
                err: '无法导入此文件,请确保您提供了有效的文件',
                download: '下载导入模板',
                result: '导入完成。已导入 %{success} æˆåŠŸ, å’Œ %{error} å¤±è´¥',
            },
@@ -158,6 +158,7 @@
        mission: '执行',
        staReserve: '站点预约',
        lane: '巷道管理',
        integrationRecord: '集成交互',
    },
    table: {
        field: {
@@ -288,11 +289,12 @@
                staType: "站点类型",
                code: "地面码",
                offset: "偏移量",
                height: "作业高度",
                depth: "作业深度",
                angle: '作业角度',
                inboundWait: '入库等待(毫秒)',
                outboundWait: '出库等待(毫秒)',
                height: "作业高度(mm)",
                depth: "作业深度(mm)",
                angle: '车体角度(°)',
                actDir: '货叉方向',
                inboundWait: '入库等(ms)',
                outboundWait: '出库等(ms)',
                autoing: "自动",
                loading: "载货",
                inEnable: "可入",
@@ -342,9 +344,9 @@
                locNo: "库位号",
                name: "名称",
                code: "地面码",
                compDirect: "码方向",
                compDirect: "货叉方向",
                locSts: "库位状态",
                offset: "偏移量",
                offset: "高度",
                row: "排",
                bay: "列",
                lev: "层",
@@ -485,6 +487,7 @@
                destLoc: "目标库位",
                destCode: "目标地面码",
                emptyMk: "空料箱",
                uplinkSts: "上行状态",
                zpallet: "料箱码",
                phase: "理想路径",
                errDesc: "异常描述",
@@ -603,6 +606,22 @@
                entryAngle: "车体角度",
                maximum: "承载量",
            },
            integrationRecord: {
                uuid: "编号",
                namespace: "命名空间",
                url: "接口地址",
                appkey: "密钥",
                caller: "调用方",
                direction: "方向",
                timestamp: "时间戳",
                clientIp: "客户端IP",
                request: "请求内容",
                response: "响应内容",
                err: "异常",
                result: "请求结果",
                costMs: "耗时(毫秒)",
            },
        }
    },
    page: {
@@ -669,6 +688,13 @@
            },
            levOffset: '每层高度',
            bottomOffset: '底部偏移量',
            enums: {
                compDirect: {
                    left: 'å·¦',
                    right: '右',
                    forward: '前',
                },
            },
        },
        sta: {
            depthHint: '深度设置为 0 è¡¨ç¤ºæ²¿ç”¨é»˜è®¤å€¼ã€‚',
@@ -720,6 +746,18 @@
                reposition: '清除路径重新定位',
            }
        },
        task: {
            enums: {
                uplinkSts: {
                    NONE: '未知',
                    PENDING: '待上报',
                    SENDING: '上报中',
                    SUCCESS: '成功',
                    FAILED: '失败',
                    SKIPPED: '跳过',
                },
            },
        },
        segment: {
            enums: {
                state: {
zy-acs-flow/src/page/ResourceContent.js
@@ -43,6 +43,7 @@
import mission from "./mission";
import staReserve from './staReserve';
import lane from './lane';
import integrationRecord from './integrationRecord';
const ResourceContent = (node) => {
    switch (node.component) {
@@ -124,6 +125,8 @@
            return staReserve;
        case 'lane':
            return lane;
        case 'integrationRecord':
            return integrationRecord;
        default:
            return {
                list: ListGuesser,
zy-acs-flow/src/page/code/CodeList.jsx
@@ -46,8 +46,10 @@
import ImportButton from '../components/ImportButton'
import { useCodeImport } from './useCodeImport';
import * as importTemp from './importTemp.csv?raw';
const IMPORT_TEMP_URL = `data:text/csv;name=crm_contacts_sample.csv;charset=utf-8,${encodeURIComponent(importTemp.default)}`;
// import * as importTemp from './importTemp.csv?raw';
// const IMPORT_TEMP_URL = `data:text/csv;name=crm_contacts_sample.csv;charset=utf-8,${encodeURIComponent(importTemp.default)}`;
const IMPORT_TEMP_URL = '/imports/code_import_template.xlsx';
const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({
    '& .css-1vooibu-MuiSvgIcon-root': {
@@ -126,7 +128,7 @@
                        <FilterButton />
                        <MyCreateButton onClick={() => { setCreateDialog(true) }} />
                        <SelectColumnsButton preferenceKey='code' />
                        <ImportButton importTemp={IMPORT_TEMP_URL} useCodeImport={useCodeImport} onceBatch={10} />
                        <ImportButton type="xlsx" importTemp={IMPORT_TEMP_URL} useImport={useCodeImport} onceBatch={10} />
                        <MyExportButton />
                    </TopToolbar>
                )}
zy-acs-flow/src/page/components/ImportButton.jsx
@@ -2,11 +2,18 @@
import { useState } from 'react';
import { Button } from 'react-admin';
import ImportModal from './ImportModal';
import ImportTxtModal from './ImportTxtModal';
import ImportXlsxModal from './ImportXlsxModal';
const ImportButton = (props) => {
const ImportButton = ({
    type = 'csv', // csv, txt, xlsx,
    variant = 'text',
    ...props
}) => {
    const [modalOpen, setModalOpen] = useState(false);
    const handleOpenModal = () => {
    const handleOpenModal = (e) => {
        e.stopPropagation();
        setModalOpen(true);
    };
@@ -17,12 +24,14 @@
    return (
        <>
            <Button
                variant={variant}
                startIcon={<UploadIcon />}
                label="common.action.import.title"
                onClick={handleOpenModal}
            />
            <ImportModal open={modalOpen} onClose={handleCloseModal} {...props} />
            {type === 'csv' && (<ImportModal open={modalOpen} onClose={handleCloseModal} {...props} />)}
            {type === 'txt' && (<ImportTxtModal open={modalOpen} onClose={handleCloseModal} {...props} />)}
            {type === 'xlsx' && (<ImportXlsxModal open={modalOpen} onClose={handleCloseModal} {...props} />)}
        </>
    );
};
zy-acs-flow/src/page/components/ImportTxtModal.jsx
New file
@@ -0,0 +1,213 @@
import { useEffect, useState } from 'react';
import { Box, CircularProgress, Stack, Typography } from '@mui/material';
import Alert from '@mui/material/Alert';
import Dialog from '@mui/material/Dialog';
import DialogActions from '@mui/material/DialogActions';
import DialogContent from '@mui/material/DialogContent';
import DialogTitle from '@mui/material/DialogTitle';
import MuiLink from '@mui/material/Link';
import {
    Button,
    FileField,
    FileInput,
    Form,
    Toolbar,
    useRefresh,
    useTranslate
} from 'react-admin';
import { Link } from 'react-router-dom';
import DialogCloseButton from './DialogCloseButton';
import { usePapaParse } from './usePapaParse';
const ImportTxtModal = ({ open, onClose, useImport, params, title = '', onceBatch = 10 }) => {
    const refresh = useRefresh();
    const translate = useTranslate();
    const { processBatch } = useImport();
    const { importer, parseCsv, reset } = usePapaParse({
        batchSize: onceBatch,
        processBatch,
        params,
    });
    const [file, setFile] = useState(null);
    useEffect(() => {
        if (importer.state === 'complete') {
            refresh();
        }
    }, [importer.state, refresh]);
    const handleFileChange = (file) => {
        setFile(file);
    };
    const startImport = async () => {
        if (!file) {
            return;
        }
        parseCsv(file);
    };
    const handleClose = () => {
        reset();
        onClose();
    };
    const handleReset = (e) => {
        e.preventDefault();
        reset();
    };
    return (
        <Dialog
            open={open}
            maxWidth="md"
            fullWidth
            onClick={(e) => e.stopPropagation()}
        >
            <DialogCloseButton onClose={handleClose} />
            <DialogTitle>{translate('common.action.import.title')} {title}</DialogTitle>
            <DialogContent>
                <Form>
                    <Stack spacing={2}>
                        {importer.state === 'running' && (
                            <Stack gap={2}>
                                <Alert
                                    severity="info"
                                    action={
                                        <Box
                                            sx={{
                                                display: 'flex',
                                                height: '100%',
                                                alignItems: 'center',
                                                padding: '0',
                                            }}
                                        >
                                            <CircularProgress size={20} />
                                        </Box>
                                    }
                                    sx={{
                                        alignItems: 'center',
                                        '& .MuiAlert-action': {
                                            padding: 0,
                                            marginRight: 0,
                                        },
                                    }}
                                >
                                    {translate('common.action.import.tips')}
                                </Alert>
                                <Typography variant="body2">
                                    Imported{' '}
                                    <strong>
                                        {importer.importCount} /{' '}
                                        {importer.rowCount}
                                    </strong>{' '}
                                    contacts, with{' '}
                                    <strong>{importer.errorCount}</strong>{' '}
                                    errors.
                                    {importer.remainingTime !== null && (
                                        <>
                                            {' '}
                                            Estimated remaining time:{' '}
                                            <strong>
                                                {millisecondsToTime(
                                                    importer.remainingTime
                                                )}
                                            </strong>
                                            .{' '}
                                            <MuiLink
                                                href="#"
                                                onClick={handleReset}
                                                color="error"
                                            >
                                                {translate('common.action.import.stop')}
                                            </MuiLink>
                                        </>
                                    )}
                                </Typography>
                            </Stack>
                        )}
                        {importer.state === 'error' && (
                            <Alert severity="error">
                                {translate('common.action.import.err')}
                            </Alert>
                        )}
                        {importer.state === 'complete' && (
                            <>
                                <Alert severity="success">
                                    {translate('common.action.import.result', {
                                        success: importer.importCount,
                                        error: importer.errorCount
                                    })}
                                </Alert>
                                {importer.errorMsg && (
                                    <Alert severity="error">
                                        {importer.errorMsg}
                                    </Alert>
                                )}
                            </>
                        )}
                        {importer.state === 'idle' && (
                            <>
                                <FileInput
                                    source="txt"
                                    label="Txt File"
                                    accept={{ 'text/plain': ['.txt'] }}
                                    onChange={handleFileChange}
                                >
                                    <FileField source="src" title="title" />
                                </FileInput>
                            </>
                        )}
                    </Stack>
                </Form>
            </DialogContent>
            <DialogActions
                sx={{
                    p: 0,
                    justifyContent: 'flex-start',
                }}
            >
                <Toolbar
                    sx={{
                        width: '100%',
                    }}
                >
                    {importer.state === 'idle' ? (
                        <>
                            <Button
                                label="common.action.import.title"
                                variant="contained"
                                onClick={startImport}
                                disabled={!file}
                            />
                        </>
                    ) : (
                        <Button
                            label="ra.action.close"
                            onClick={handleClose}
                            disabled={importer.state === 'running'}
                        />
                    )}
                </Toolbar>
            </DialogActions>
        </Dialog>
    );
}
function millisecondsToTime(ms) {
    var seconds = Math.floor((ms / 1000) % 60);
    var minutes = Math.floor((ms / (60 * 1000)) % 60);
    return `${minutes}m ${seconds}s`;
}
export default ImportTxtModal;
zy-acs-flow/src/page/components/ImportXlsxModal.jsx
New file
@@ -0,0 +1,191 @@
// ImportXlsxModal.jsx
import { useEffect, useState } from 'react';
import { Box, CircularProgress, Stack, Typography } from '@mui/material';
import Alert from '@mui/material/Alert';
import Dialog from '@mui/material/Dialog';
import DialogActions from '@mui/material/DialogActions';
import DialogContent from '@mui/material/DialogContent';
import DialogTitle from '@mui/material/DialogTitle';
import MuiLink from '@mui/material/Link';
import {
    Button,
    FileField,
    FileInput,
    Form,
    Toolbar,
    useRefresh,
    useTranslate,
} from 'react-admin';
import DialogCloseButton from './DialogCloseButton';
import { useExcelParse } from './useExcelParse';
const ImportXlsxModal = ({
    open,
    onClose,
    importTemp,
    useImport,
    params,
    title = '',
    onceBatch = 10,
}) => {
    const refresh = useRefresh();
    const t = useTranslate();
    const { processBatch } = useImport();
    const { importer, parseExcel, reset } = useExcelParse({
        batchSize: onceBatch,
        processBatch,
        params,
    });
    const [file, setFile] = useState(null);
    useEffect(() => {
        if (importer.state === 'complete') {
            refresh();
        }
    }, [importer.state, refresh]);
    const handleFileChange = (val) => {
        const f = Array.isArray(val) ? val[0]?.rawFile ?? val[0] : val?.rawFile ?? val;
        setFile(f || null);
    };
    const startImport = async () => {
        if (!file) return;
        parseExcel(file);
    };
    const handleClose = () => {
        reset();
        setFile(null);
        onClose();
    };
    const handleReset = (e) => {
        e.preventDefault();
        reset();
    };
    const nameMatch = importTemp?.split('/').pop() || 'import_template.xlsx';
    return (
        <Dialog open={open} maxWidth="md" fullWidth onClick={(e) => e.stopPropagation()}>
            <DialogCloseButton onClose={handleClose} />
            <DialogTitle>{t('common.action.import.title')} {title}</DialogTitle>
            <DialogContent>
                <Form>
                    <Stack spacing={2}>
                        <Alert
                            severity="info"
                            action={
                                importTemp ? (
                                    <Button
                                        component="a"
                                        label="common.action.import.download"
                                        color="info"
                                        href={importTemp}
                                        download={nameMatch}
                                    />
                                ) : null
                            }
                            sx={{
                                alignItems: 'center',
                                '& .MuiAlert-action': { p: 0, mr: 0 },
                            }}
                        >
                            {t('common.action.import.msg', { _: '这是一个可以用作模板的示例 Excel æ–‡ä»¶' })}
                        </Alert>
                        {importer.state === 'running' && (
                            <Stack gap={2}>
                                <Alert
                                    severity="info"
                                    action={
                                        <Box sx={{ display: 'flex', alignItems: 'center', p: 0 }}>
                                            <CircularProgress size={20} />
                                        </Box>
                                    }
                                    sx={{ alignItems: 'center', '& .MuiAlert-action': { p: 0, mr: 0 } }}
                                >
                                    {t('common.action.import.tips')}
                                </Alert>
                                <Typography variant="body2">
                                    Imported <strong>{importer.importCount}</strong> /{' '}
                                    <strong>{importer.rowCount}</strong> rows, with{' '}
                                    <strong>{importer.errorCount}</strong> errors.
                                    {importer.remainingTime !== null && (
                                        <>
                                            {' '}ETA: <strong>{millisecondsToTime(importer.remainingTime)}</strong>.{' '}
                                            <MuiLink href="#" onClick={handleReset} color="error">
                                                {t('common.action.import.stop')}
                                            </MuiLink>
                                        </>
                                    )}
                                </Typography>
                            </Stack>
                        )}
                        {importer.state === 'error' && (
                            <Alert severity="error">{t('common.action.import.err')}</Alert>
                        )}
                        {importer.state === 'complete' && (
                            <>
                                <Alert severity="success">
                                    {t('common.action.import.result', {
                                        success: importer.importCount,
                                        error: importer.errorCount,
                                    })}
                                </Alert>
                                {importer.errorMsg && <Alert severity="error">{importer.errorMsg}</Alert>}
                            </>
                        )}
                        {importer.state === 'idle' && (
                            <>
                                <FileInput
                                    source="xlsx"
                                    label="Excel File (.xlsx / .xls)"
                                    accept={{
                                        'application/vnd.ms-excel': ['.xls'],
                                        'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': ['.xlsx'],
                                    }}
                                    onChange={handleFileChange}
                                >
                                    <FileField source="src" title="title" />
                                </FileInput>
                            </>
                        )}
                    </Stack>
                </Form>
            </DialogContent>
            <DialogActions sx={{ p: 0, justifyContent: 'flex-start' }}>
                <Toolbar sx={{ width: '100%' }}>
                    {importer.state === 'idle' ? (
                        <Button
                            label="common.action.import.title"
                            variant="contained"
                            onClick={startImport}
                            disabled={!file}
                        />
                    ) : (
                        <Button
                            label="ra.action.close"
                            onClick={handleClose}
                            disabled={importer.state === 'running'}
                        />
                    )}
                </Toolbar>
            </DialogActions>
        </Dialog>
    );
};
function millisecondsToTime(ms) {
    const seconds = Math.floor((ms / 1000) % 60);
    const minutes = Math.floor((ms / (60 * 1000)) % 60);
    return `${minutes}m ${seconds}s`;
}
export default ImportXlsxModal;
zy-acs-flow/src/page/components/useExcelParse.js
New file
@@ -0,0 +1,77 @@
import * as XLSX from 'xlsx';
import { useCallback, useMemo, useRef, useState } from 'react';
export function useExcelParse({ batchSize = 10, processBatch, params }) {
    const importIdRef = useRef(0);
    const [importer, setImporter] = useState({ state: 'idle' });
    const reset = useCallback(() => {
        setImporter({ state: 'idle' });
        importIdRef.current += 1;
    }, []);
    const parseExcel = useCallback(async (file) => {
        if (!file) return;
        setImporter({ state: 'parsing' });
        const importId = importIdRef.current;
        try {
            const buf = await file.arrayBuffer();
            const wb = XLSX.read(buf, { type: 'array' });
            const sheet = wb.SheetNames[0];
            const rows = XLSX.utils.sheet_to_json(wb.Sheets[sheet], { defval: '' });
            setImporter({
                state: 'running',
                rowCount: rows.length,
                importCount: 0,
                errorCount: 0,
                remainingTime: null,
            });
            let totalTime = 0;
            for (let i = 0; i < rows.length; i += batchSize) {
                if (importIdRef.current !== importId) return;
                const batch = rows.slice(i, i + batchSize);
                try {
                    const start = Date.now();
                    await processBatch(batch, params);
                    totalTime += Date.now() - start;
                    const mean = totalTime / (i + batch.length);
                    setImporter((prev) =>
                        prev.state === 'running'
                            ? {
                                ...prev,
                                importCount: prev.importCount + batch.length,
                                remainingTime: mean * (rows.length - (prev.importCount + batch.length)),
                            }
                            : prev
                    );
                } catch (err) {
                    setImporter((prev) =>
                        prev.state === 'running'
                            ? {
                                ...prev,
                                errorCount: prev.errorCount + batch.length,
                                errorMsg: prev.errorMsg
                                    ? `${prev.errorMsg}\n${err?.message || String(err)}`
                                    : (err?.message || String(err)),
                            }
                            : prev
                    );
                }
            }
            setImporter((prev) =>
                prev.state === 'running' ? { ...prev, state: 'complete', remainingTime: null } : prev
            );
        } catch (error) {
            setImporter({ state: 'error', error });
        }
    }, [batchSize, processBatch, params]);
    return useMemo(() => ({ importer, parseExcel, reset }), [importer, parseExcel, reset]);
}
zy-acs-flow/src/page/integrationRecord/IntegrationRecordCreate.jsx
New file
@@ -0,0 +1,207 @@
import React, { useState, useRef, useEffect, useMemo } from "react";
import {
    CreateBase,
    useTranslate,
    TextInput,
    NumberInput,
    BooleanInput,
    DateInput,
    SaveButton,
    SelectInput,
    ReferenceInput,
    ReferenceArrayInput,
    AutocompleteInput,
    Toolbar,
    required,
    useDataProvider,
    useNotify,
    Form,
    useCreateController,
} from 'react-admin';
import {
    Dialog,
    DialogActions,
    DialogContent,
    DialogTitle,
    Stack,
    Grid,
    Box,
} from '@mui/material';
import DialogCloseButton from "../components/DialogCloseButton";
import StatusSelectInput from "../components/StatusSelectInput";
import MemoInput from "../components/MemoInput";
const IntegrationRecordCreate = (props) => {
    const { open, setOpen } = props;
    const translate = useTranslate();
    const notify = useNotify();
    const handleClose = (event, reason) => {
        if (reason !== "backdropClick") {
            setOpen(false);
        }
    };
    const handleSuccess = async (data) => {
        setOpen(false);
        notify('common.response.success');
    };
    const handleError = async (error) => {
        notify(error.message || 'common.response.fail', { type: 'error', messageArgs: { _: error.message } });
    };
    return (
        <>
            <CreateBase
                record={{}}
                transform={(data) => {
                    return data;
                }}
                mutationOptions={{ onSuccess: handleSuccess, onError: handleError }}
            >
                <Dialog
                    open={open}
                    onClose={handleClose}
                    aria-labelledby="form-dialog-title"
                    fullWidth
                    disableRestoreFocus
                    maxWidth="md"   // 'xs' | 'sm' | 'md' | 'lg' | 'xl'
                >
                    <Form>
                        <DialogTitle id="form-dialog-title" sx={{
                            position: 'sticky',
                            top: 0,
                            backgroundColor: 'background.paper',
                            zIndex: 1000
                        }}
                        >
                            {translate('create.title')}
                            <Box sx={{ position: 'absolute', top: 8, right: 8, zIndex: 1001 }}>
                                <DialogCloseButton onClose={handleClose} />
                            </Box>
                        </DialogTitle>
                        <DialogContent>
                            <Grid container rowSpacing={2} columnSpacing={2}>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <TextInput
                                        label="table.field.integrationRecord.uuid"
                                        source="uuid"
                                        parse={v => v}
                                        autoFocus
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <TextInput
                                        label="table.field.integrationRecord.namespace"
                                        source="namespace"
                                        parse={v => v}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <TextInput
                                        label="table.field.integrationRecord.url"
                                        source="url"
                                        parse={v => v}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <TextInput
                                        label="table.field.integrationRecord.appkey"
                                        source="appkey"
                                        parse={v => v}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <TextInput
                                        label="table.field.integrationRecord.caller"
                                        source="caller"
                                        parse={v => v}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <SelectInput
                                        label="table.field.integrationRecord.direction"
                                        source="direction"
                                        choices={[
                                            { id: 1, name: '被调用' },
                                            { id: 2, name: '调用外部' },
                                        ]}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <TextInput
                                        label="table.field.integrationRecord.timestamp"
                                        source="timestamp"
                                        parse={v => v}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <TextInput
                                        label="table.field.integrationRecord.clientIp"
                                        source="clientIp"
                                        parse={v => v}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <TextInput
                                        label="table.field.integrationRecord.request"
                                        source="request"
                                        parse={v => v}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <TextInput
                                        label="table.field.integrationRecord.response"
                                        source="response"
                                        parse={v => v}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <TextInput
                                        label="table.field.integrationRecord.err"
                                        source="err"
                                        parse={v => v}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <SelectInput
                                        label="table.field.integrationRecord.result"
                                        source="result"
                                        choices={[
                                            { id: 1, name: '成功' },
                                            { id: 0, name: '失败' },
                                        ]}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <NumberInput
                                        label="table.field.integrationRecord.costMs"
                                        source="costMs"
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <StatusSelectInput />
                                </Grid>
                                <Grid item xs={12} display="flex" gap={1}>
                                    <Stack direction="column" spacing={1} width={'100%'}>
                                        <MemoInput />
                                    </Stack>
                                </Grid>
                            </Grid>
                        </DialogContent>
                        <DialogActions sx={{ position: 'sticky', bottom: 0, backgroundColor: 'background.paper', zIndex: 1000 }}>
                            <Toolbar sx={{ width: '100%', justifyContent: 'space-between' }}  >
                                <SaveButton />
                            </Toolbar>
                        </DialogActions>
                    </Form>
                </Dialog>
            </CreateBase>
        </>
    )
}
export default IntegrationRecordCreate;
zy-acs-flow/src/page/integrationRecord/IntegrationRecordEdit.jsx
New file
@@ -0,0 +1,180 @@
import React, { useState, useRef, useEffect, useMemo } from "react";
import {
    Edit,
    SimpleForm,
    FormDataConsumer,
    useTranslate,
    TextInput,
    NumberInput,
    BooleanInput,
    DateInput,
    SelectInput,
    ReferenceInput,
    ReferenceArrayInput,
    AutocompleteInput,
    SaveButton,
    Toolbar,
    Labeled,
    NumberField,
    required,
    useRecordContext,
    DeleteButton,
} from 'react-admin';
import { useWatch, useFormContext } from "react-hook-form";
import { Stack, Grid, Box, Typography } from '@mui/material';
import * as Common from '@/utils/common';
import { EDIT_MODE, REFERENCE_INPUT_PAGESIZE } from '@/config/setting';
import EditBaseAside from "../components/EditBaseAside";
import CustomerTopToolBar from "../components/EditTopToolBar";
import MemoInput from "../components/MemoInput";
import StatusSelectInput from "../components/StatusSelectInput";
const FormToolbar = () => {
    const { getValues } = useFormContext();
    return (
        <Toolbar sx={{ justifyContent: 'space-between' }}>
            <SaveButton />
            <DeleteButton mutationMode="optimistic" />
        </Toolbar>
    )
}
const IntegrationRecordEdit = () => {
    const translate = useTranslate();
    return (
        <Edit
            redirect="list"
            mutationMode={EDIT_MODE}
            actions={<CustomerTopToolBar />}
            aside={<EditBaseAside />}
        >
            <SimpleForm
                shouldUnregister
                warnWhenUnsavedChanges
                toolbar={<FormToolbar />}
                mode="onTouched"
                defaultValues={{}}
            // validate={(values) => { }}
            >
                <Grid container width={{ xs: '100%', xl: '80%' }} rowSpacing={3} columnSpacing={3}>
                    <Grid item xs={12} md={8}>
                        <Typography variant="h6" gutterBottom>
                            {translate('common.edit.title.main')}
                        </Typography>
                        <Stack direction='row' gap={2}>
                            <TextInput
                                label="table.field.integrationRecord.uuid"
                                source="uuid"
                                parse={v => v}
                                autoFocus
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <TextInput
                                label="table.field.integrationRecord.namespace"
                                source="namespace"
                                parse={v => v}
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <TextInput
                                label="table.field.integrationRecord.url"
                                source="url"
                                parse={v => v}
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <TextInput
                                label="table.field.integrationRecord.appkey"
                                source="appkey"
                                parse={v => v}
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <TextInput
                                label="table.field.integrationRecord.caller"
                                source="caller"
                                parse={v => v}
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <SelectInput
                                label="table.field.integrationRecord.direction"
                                source="direction"
                                choices={[
                                    { id: 1, name: '被调用' },
                                    { id: 2, name: '调用外部' },
                                ]}
                                validate={required()}
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <TextInput
                                label="table.field.integrationRecord.timestamp"
                                source="timestamp"
                                parse={v => v}
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <TextInput
                                label="table.field.integrationRecord.clientIp"
                                source="clientIp"
                                parse={v => v}
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <TextInput
                                label="table.field.integrationRecord.request"
                                source="request"
                                parse={v => v}
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <TextInput
                                label="table.field.integrationRecord.response"
                                source="response"
                                parse={v => v}
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <TextInput
                                label="table.field.integrationRecord.err"
                                source="err"
                                parse={v => v}
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <SelectInput
                                label="table.field.integrationRecord.result"
                                source="result"
                                choices={[
                                    { id: 1, name: '成功' },
                                    { id: 0, name: '失败' },
                                ]}
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <NumberInput
                                label="table.field.integrationRecord.costMs"
                                source="costMs"
                            />
                        </Stack>
                    </Grid>
                    <Grid item xs={12} md={4}>
                        <Typography variant="h6" gutterBottom>
                            {translate('common.edit.title.common')}
                        </Typography>
                        <StatusSelectInput />
                        <Box mt="2em" />
                        <MemoInput />
                    </Grid>
                </Grid>
            </SimpleForm>
        </Edit >
    )
}
export default IntegrationRecordEdit;
zy-acs-flow/src/page/integrationRecord/IntegrationRecordList.jsx
New file
@@ -0,0 +1,173 @@
import React, { useState, useRef, useEffect, useMemo, useCallback } from "react";
import { useNavigate } from 'react-router-dom';
import {
    List,
    DatagridConfigurable,
    SearchInput,
    TopToolbar,
    SelectColumnsButton,
    EditButton,
    FilterButton,
    CreateButton,
    ExportButton,
    BulkDeleteButton,
    WrapperField,
    useRecordContext,
    useTranslate,
    useNotify,
    useListContext,
    FunctionField,
    TextField,
    NumberField,
    DateField,
    BooleanField,
    ReferenceField,
    TextInput,
    DateTimeInput,
    DateInput,
    SelectInput,
    NumberInput,
    ReferenceInput,
    ReferenceArrayInput,
    AutocompleteInput,
    DeleteButton,
} from 'react-admin';
import { Box, Typography, Card, Stack } from '@mui/material';
import { styled } from '@mui/material/styles';
import IntegrationRecordCreate from "./IntegrationRecordCreate";
import IntegrationRecordPanel from "./IntegrationRecordPanel";
import EmptyDataLoader from "../components/EmptyDataLoader";
import MyCreateButton from "../components/MyCreateButton";
import MyExportButton from '../components/MyExportButton';
import PageDrawer from "../components/PageDrawer";
import MyField from "../components/MyField";
import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting';
import * as Common from '@/utils/common';
const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({
    '& .css-1vooibu-MuiSvgIcon-root': {
        height: '.9em'
    },
    '& .RaDatagrid-row': {
        cursor: 'auto'
    },
    '& .column-name': {
    },
    '& .opt': {
        width: 200
    },
}));
const filters = [
    <SearchInput source="condition" alwaysOn />,
    <DateInput label='common.time.after' source="timeStart" alwaysOn />,
    <DateInput label='common.time.before' source="timeEnd" alwaysOn />,
    <TextInput source="uuid" label="table.field.integrationRecord.uuid" />,
    <TextInput source="namespace" label="table.field.integrationRecord.namespace" />,
    <TextInput source="url" label="table.field.integrationRecord.url" />,
    <TextInput source="appkey" label="table.field.integrationRecord.appkey" />,
    <TextInput source="caller" label="table.field.integrationRecord.caller" />,
    <SelectInput source="direction" label="table.field.integrationRecord.direction"
        choices={[
            { id: 1, name: '被调用' },
            { id: 2, name: '调用外部' },
        ]}
    />,
    <TextInput source="timestamp" label="table.field.integrationRecord.timestamp" />,
    <TextInput source="clientIp" label="table.field.integrationRecord.clientIp" />,
    <SelectInput source="result" label="table.field.integrationRecord.result"
        choices={[
            { id: 1, name: '成功' },
            { id: 0, name: '失败' },
        ]}
    />,
    <TextInput label="common.field.memo" source="memo" />,
]
const IntegrationRecordList = () => {
    const translate = useTranslate();
    const [createDialog, setCreateDialog] = useState(false);
    const [drawerVal, setDrawerVal] = useState(false);
    return (
        <Box display="flex">
            <List
                sx={{
                    flexGrow: 1,
                    transition: (theme) =>
                        theme.transitions.create(['all'], {
                            duration: theme.transitions.duration.enteringScreen,
                        }),
                    marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
                }}
                title={"menu.integrationRecord"}
                empty={<EmptyDataLoader />}
                filters={filters}
                sort={{ field: "create_time", order: "desc" }}
                actions={(
                    <TopToolbar>
                        <FilterButton />
                        <MyCreateButton onClick={() => { setCreateDialog(true) }} />
                        <SelectColumnsButton preferenceKey='integrationRecord' />
                        <MyExportButton />
                    </TopToolbar>
                )}
                perPage={DEFAULT_PAGE_SIZE}
            >
                <StyledDatagrid
                    preferenceKey='integrationRecord'
                    bulkActionButtons={() => <BulkDeleteButton mutationMode={OPERATE_MODE} />}
                    rowClick={(id, resource, record) => false}
                    expand={() => <IntegrationRecordPanel />}
                    expandSingle={true}
                    omit={['id', 'createTime', 'createBy', 'memo']}
                >
                    <NumberField source="id" />
                    <TextField source="uuid" label="table.field.integrationRecord.uuid" />
                    <TextField source="namespace" label="table.field.integrationRecord.namespace" />
                    <TextField source="url" label="table.field.integrationRecord.url" />
                    <TextField source="appkey" label="table.field.integrationRecord.appkey" />
                    <TextField source="caller" label="table.field.integrationRecord.caller" />
                    <TextField source="direction$" label="table.field.integrationRecord.direction" sortable={false} />
                    <TextField source="timestamp" label="table.field.integrationRecord.timestamp" />
                    <TextField source="clientIp" label="table.field.integrationRecord.clientIp" />
                    <TextField source="request" label="table.field.integrationRecord.request" />
                    <TextField source="response" label="table.field.integrationRecord.response" />
                    <TextField source="err" label="table.field.integrationRecord.err" />
                    <TextField source="result$" label="table.field.integrationRecord.result" sortable={false} />
                    <NumberField source="costMs" label="table.field.integrationRecord.costMs" />
                    <ReferenceField source="updateBy" label="common.field.updateBy" reference="user" link={false} sortable={false}>
                        <TextField source="nickname" />
                    </ReferenceField>
                    <DateField source="updateTime" label="common.field.updateTime" showTime />
                    <ReferenceField source="createBy" label="common.field.createBy" reference="user" link={false} sortable={false}>
                        <TextField source="nickname" />
                    </ReferenceField>
                    <DateField source="createTime" label="common.field.createTime" showTime />
                    <BooleanField source="statusBool" label="common.field.status" sortable={false} />
                    <TextField source="memo" label="common.field.memo" sortable={false} />
                    <WrapperField cellClassName="opt" label="common.field.opt">
                        <EditButton sx={{ padding: '1px', fontSize: '.75rem' }} />
                        <DeleteButton sx={{ padding: '1px', fontSize: '.75rem' }} mutationMode={OPERATE_MODE} />
                    </WrapperField>
                </StyledDatagrid>
            </List>
            <IntegrationRecordCreate
                open={createDialog}
                setOpen={setCreateDialog}
            />
            <PageDrawer
                title='IntegrationRecord Detail'
                drawerVal={drawerVal}
                setDrawerVal={setDrawerVal}
            >
            </PageDrawer>
        </Box>
    )
}
export default IntegrationRecordList;
zy-acs-flow/src/page/integrationRecord/IntegrationRecordPanel.jsx
New file
@@ -0,0 +1,129 @@
import React, { useState, useRef, useEffect, useMemo } from "react";
import { Box, Card, CardContent, Grid, Typography, Tooltip } from '@mui/material';
import {
    useTranslate,
    useRecordContext,
} from 'react-admin';
import PanelTypography from "../components/PanelTypography";
import * as Common from '@/utils/common'
const IntegrationRecordPanel = () => {
    const record = useRecordContext();
    if (!record) return null;
    const translate = useTranslate();
    return (
        <>
            <Card sx={{ width: { xs: 300, sm: 500, md: 600, lg: 800 }, margin: 'auto' }}>
                <CardContent>
                    <Grid container spacing={2}>
                        <Grid item xs={12} sx={{ display: 'flex', justifyContent: 'space-between' }}>
                            <Typography variant="h6" gutterBottom align="left" sx={{
                                maxWidth: { xs: '100px', sm: '180px', md: '260px', lg: '360px' },
                                whiteSpace: 'nowrap',
                                overflow: 'hidden',
                                textOverflow: 'ellipsis',
                            }}>
                                {Common.camelToPascalWithSpaces(translate('table.field.integrationRecord.namespace'))}: {record.namespace}
                            </Typography>
                            {/*  inherit, primary, secondary, textPrimary, textSecondary, error */}
                            <Typography variant="h6" gutterBottom align="right" >
                                ID: {record.id}
                            </Typography>
                        </Grid>
                    </Grid>
                    <Grid container spacing={2}>
                        <Grid item xs={12} container alignContent="flex-end">
                            <Typography variant="caption" color="textSecondary" sx={{ wordWrap: 'break-word', wordBreak: 'break-all' }}>
                                {Common.camelToPascalWithSpaces(translate('common.field.memo'))}:{record.memo}
                            </Typography>
                        </Grid>
                    </Grid>
                    <Box height={20}>&nbsp;</Box>
                    <Grid container spacing={2}>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.integrationRecord.uuid"
                                property={record.uuid}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.integrationRecord.namespace"
                                property={record.namespace}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.integrationRecord.url"
                                property={record.url}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.integrationRecord.appkey"
                                property={record.appkey}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.integrationRecord.caller"
                                property={record.caller}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.integrationRecord.direction"
                                property={record.direction$}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.integrationRecord.timestamp"
                                property={record.timestamp}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.integrationRecord.clientIp"
                                property={record.clientIp}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.integrationRecord.request"
                                property={record.request}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.integrationRecord.response"
                                property={record.response}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.integrationRecord.err"
                                property={record.err}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.integrationRecord.result"
                                property={record.result$}
                            />
                        </Grid>
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.integrationRecord.costMs"
                                property={record.costMs}
                            />
                        </Grid>
                    </Grid>
                </CardContent>
            </Card >
        </>
    );
};
export default IntegrationRecordPanel;
zy-acs-flow/src/page/integrationRecord/index.jsx
New file
@@ -0,0 +1,18 @@
import React, { useState, useRef, useEffect, useMemo } from "react";
import {
    ListGuesser,
    EditGuesser,
    ShowGuesser,
} from "react-admin";
import IntegrationRecordList from "./IntegrationRecordList";
import IntegrationRecordEdit from "./IntegrationRecordEdit";
export default {
    list: IntegrationRecordList,
    edit: IntegrationRecordEdit,
    show: ShowGuesser,
    recordRepresentation: (record) => {
        return `${record.namespace}`
    }
};
zy-acs-flow/src/page/loc/LocCreate.jsx
@@ -30,6 +30,7 @@
import DialogCloseButton from "../components/DialogCloseButton";
import StatusSelectInput from "../components/StatusSelectInput";
import MemoInput from "../components/MemoInput";
import { compDirectChoices } from "./compDirect";
const LocCreate = (props) => {
    const { open, setOpen } = props;
@@ -156,10 +157,7 @@
                                    <SelectInput
                                        label="table.field.loc.compDirect"
                                        source="compDirect"
                                        choices={[
                                            { id: 1, name: '大于' },
                                            { id: 0, name: '小于' },
                                        ]}
                                        choices={compDirectChoices}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
zy-acs-flow/src/page/loc/LocEdit.jsx
@@ -28,6 +28,7 @@
import CustomerTopToolBar from "../components/EditTopToolBar";
import MemoInput from "../components/MemoInput";
import StatusSelectInput from "../components/StatusSelectInput";
import { compDirectChoices } from "./compDirect";
const FormToolbar = () => {
    const { getValues } = useFormContext();
@@ -133,10 +134,7 @@
                            <SelectInput
                                label="table.field.loc.compDirect"
                                source="compDirect"
                                choices={[
                                    { id: 1, name: '大于' },
                                    { id: 0, name: '小于' },
                                ]}
                                choices={compDirectChoices}
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
zy-acs-flow/src/page/loc/LocInit.jsx
@@ -28,6 +28,7 @@
import DialogCloseButton from "../components/DialogCloseButton";
import CheckIcon from '@mui/icons-material/Check';
import request from '@/utils/request'
import { compDirectChoices } from "./compDirect";
const LocInit = (props) => {
    const { open, setOpen } = props;
@@ -166,10 +167,7 @@
                                <SelectInput
                                    label="table.field.loc.compDirect"
                                    source="compDirect"
                                    choices={[
                                        { id: 1, name: '大于' },
                                        { id: 0, name: '小于' },
                                    ]}
                                    choices={compDirectChoices}
                                />
                            </Grid>
                            <Grid item xs={6} display="flex" gap={1}>
@@ -197,4 +195,4 @@
    )
}
export default LocInit;
export default LocInit;
zy-acs-flow/src/page/loc/LocList.jsx
@@ -32,6 +32,7 @@
    DeleteButton,
    Button,
    Pagination,
    FunctionField,
} from 'react-admin';
import { Box, Typography, Card, Stack } from '@mui/material';
import { styled } from '@mui/material/styles';
@@ -49,6 +50,7 @@
import rowSx from "./rowSx";
import BulkUpdateButton from "../components/BulkUpdateButton";
import LocBulkUpdateContent from './LocBulkUpdateContent';
import { getCompDirectLabel } from './compDirect';
const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({
    '& .css-1vooibu-MuiSvgIcon-root': {
@@ -66,6 +68,7 @@
}));
const filters = [
    <SearchInput source="condition" alwaysOn />,
    <TextInput source="locNo" label="table.field.loc.locNo" alwaysOn />,
    <ReferenceInput source="locSts" label="table.field.loc.locSts" reference="locSts" alwaysOn>
        <AutocompleteInput label="table.field.loc.locSts" optionText="name" filterToQuery={(val) => ({ name: val })} />
@@ -73,8 +76,7 @@
    <NumberInput source="row" label="table.field.loc.row" alwaysOn />,
    <NumberInput source="bay" label="table.field.loc.bay" alwaysOn />,
    <NumberInput source="lev" label="table.field.loc.lev" alwaysOn />,
    <SearchInput source="condition" alwaysOn />,
    <ReferenceInput source="code" label="table.field.loc.code" reference="code" alwaysOn>
    <ReferenceInput source="code" label="table.field.loc.code" reference="code">
        <AutocompleteInput label="table.field.loc.code" optionText="data" filterToQuery={(val) => ({ data: val })} />
    </ReferenceInput>,
    <DateInput label='common.time.after' source="timeStart" />,
@@ -156,7 +158,8 @@
                    rowClick={(id, resource, record) => false}
                    expand={() => <LocPanel />}
                    expandSingle={true}
                    omit={['id', 'locType', 'uuid', 'statusBool', 'updateBy', 'createTime', 'createBy', 'memo']}
                    omit={['id', 'locType', 'uuid', 'zpallet', 'barcode'
                        , 'statusBool', 'updateBy', 'createTime', 'createBy', 'memo']}
                    rowSx={rowSx(drawerVal || null)}
                >
                    <NumberField source="id" />
@@ -170,7 +173,6 @@
                    <ReferenceField source="code" label="table.field.loc.code" reference="code" link={false} sortable={false}>
                        <TextField source="data" />
                    </ReferenceField>
                    {/* <TextField source="compDirect$" label="table.field.loc.compDirect" sortable={false} /> */}
                    <ReferenceField source="locSts" label="table.field.loc.locSts" reference="locSts" link={false} sortable={true}>
                        <TextField source="name" />
                    </ReferenceField>
@@ -178,6 +180,11 @@
                    <NumberField source="bay" label="table.field.loc.bay" />
                    <NumberField source="lev" label="table.field.loc.lev" />
                    <NumberField source="offset" label="table.field.loc.offset" />
                    <FunctionField
                        label="table.field.loc.compDirect"
                        sortable={false}
                        render={(record) => getCompDirectLabel(translate, record?.compDirect)}
                    />
                    <TextField source="barcode" label="table.field.loc.barcode" />
                    <TextField source="zpallet" label="table.field.loc.zpallet" />
                    <ReferenceField source="locType" label="table.field.loc.locType" reference="locType" link={false} sortable={false}>
zy-acs-flow/src/page/loc/LocPanel.jsx
@@ -6,6 +6,7 @@
} from 'react-admin';
import PanelTypography from "../components/PanelTypography";
import * as Common from '@/utils/common'
import { getCompDirectLabel } from "./compDirect";
const LocPanel = () => {
    const record = useRecordContext();
@@ -73,7 +74,7 @@
                        <Grid item xs={6}>
                            <PanelTypography
                                title="table.field.loc.compDirect" 
                                property={record.compDirect$}
                                property={getCompDirectLabel(translate, record.compDirect)}
                            />
                        </Grid>
                        <Grid item xs={6}>
zy-acs-flow/src/page/loc/compDirect.js
New file
@@ -0,0 +1,15 @@
export const compDirectChoices = [
    { id: 1, name: 'page.loc.enums.compDirect.left' },
    { id: 2, name: 'page.loc.enums.compDirect.right' },
    { id: 3, name: 'page.loc.enums.compDirect.forward' },
];
export const getCompDirectLabel = (translate, compDirect, fallback = '-') => {
    const choice = compDirectChoices.find((item) => item.id === compDirect);
    if (!choice) {
        return fallback;
    }
    return typeof translate === 'function'
        ? translate(choice.name, { _: fallback })
        : choice.name;
};
zy-acs-flow/src/page/sta/StaCreate.jsx
@@ -30,6 +30,7 @@
import DialogCloseButton from "../components/DialogCloseButton";
import StatusSelectInput from "../components/StatusSelectInput";
import MemoInput from "../components/MemoInput";
import { compDirectChoices } from "../loc/compDirect";
const StaCreate = (props) => {
    const { open, setOpen } = props;
@@ -152,7 +153,7 @@
                                        />
                                    </ReferenceInput>
                                </Grid>
                                <Grid item xs={4} display="flex" gap={1}>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <NumberInput
                                        label="table.field.sta.capacity"
                                        source="capacity"
@@ -166,7 +167,7 @@
                                        validate={required()}
                                    />
                                </Grid> */}
                                <Grid item xs={4} display="flex" gap={1}>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <NumberInput
                                        label="table.field.sta.height"
                                        source="height"
@@ -181,7 +182,7 @@
                                        validate={[required(), greaterThanZero]}
                                    />
                                </Grid> */}
                                <Grid item xs={4} display="flex" gap={1}>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <NumberInput
                                        label="table.field.sta.angle"
                                        source="angle"
@@ -189,6 +190,15 @@
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <SelectInput
                                        label="table.field.sta.actDir"
                                        source="actDir"
                                        choices={compDirectChoices}
                                        translateChoice
                                        validate={[required(), greaterThanZero]}
                                    />
                                </Grid>
                                <Grid item xs={6} display="flex" gap={1}>
                                    <NumberInput
                                        label="table.field.sta.inboundWait"
                                        source="inboundWait"
zy-acs-flow/src/page/sta/StaEdit.jsx
@@ -28,6 +28,7 @@
import CustomerTopToolBar from "../components/EditTopToolBar";
import MemoInput from "../components/MemoInput";
import StatusSelectInput from "../components/StatusSelectInput";
import { compDirectChoices } from "../loc/compDirect";
const FormToolbar = () => {
    const { getValues } = useFormContext();
@@ -136,27 +137,34 @@
                                validate={[required(), greaterThanZero]}
                            />
                            <NumberInput
                                label="table.field.sta.height"
                                source="height"
                                validate={[required(), greaterThanZero]}
                            />
                            {/* <NumberInput
                                label="table.field.sta.depth"
                                source="depth"
                                helperText={translate('page.sta.depthHint')}
                                validate={[required(), greaterThanZero]}
                            /> */}
                        </Stack>
                        <Stack direction='row' gap={2}>
                            <NumberInput
                                label="table.field.sta.angle"
                                source="angle"
                                validate={[required(), greaterThanZero]}
                            />
                            <SelectInput
                                label="table.field.sta.actDir"
                                source="actDir"
                                choices={compDirectChoices}
                                translateChoice
                                validate={[required(), greaterThanZero]}
                            />
                            {/* <NumberInput
                                label="table.field.sta.offset"
                                source="offset"
                                validate={required()}
                            /> */}
                            <NumberInput
                                label="table.field.sta.height"
                                source="height"
                                validate={[required(), greaterThanZero]}
                            />
                        </Stack>
                        <Stack direction='row' gap={2}>
                            {/* <NumberInput
                                label="table.field.sta.depth"
                                source="depth"
                                helperText={translate('page.sta.depthHint')}
                                validate={[required(), greaterThanZero]}
                            /> */}
                        </Stack>
                        <Stack direction='row' gap={2}>
zy-acs-flow/src/page/sta/StaList.jsx
@@ -30,6 +30,7 @@
    ReferenceArrayInput,
    AutocompleteInput,
    DeleteButton,
    FunctionField,
} from 'react-admin';
import { Box, Typography, Card, Stack } from '@mui/material';
import { styled } from '@mui/material/styles';
@@ -43,6 +44,7 @@
import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting';
import * as Common from '@/utils/common';
import rowSx from "./rowSx";
import { getCompDirectLabel } from "../loc/compDirect";
const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({
    '& .css-1vooibu-MuiSvgIcon-root': {
@@ -134,7 +136,7 @@
                    expand={() => <StaPanel />}
                    expandSingle={true}
                    rowSx={rowSx(drawerVal || null)}
                    omit={['id', 'uuid', 'name', 'offset', 'zpallet', 'depth'
                    omit={['id', 'uuid', 'name', 'offset', 'zpallet', 'depth', 'capacity'
                        , 'updateTime', 'updateBy', 'createTime', 'createBy', 'memo']}
                >
                    <NumberField source="id" />
@@ -158,11 +160,16 @@
                    <NumberField source="rsvInCnt" label="table.field.sta.rsvInCnt" />
                    <NumberField source="rsvOutCnt" label="table.field.sta.rsvOutCnt" />
                    <NumberField source="offset" label="table.field.sta.offset" />
                    <NumberField source="height" label="table.field.sta.height" />
                    <NumberField source="height" label="table.field.sta.height" sortable={false} />
                    <NumberField source="depth" label="table.field.sta.depth" />
                    <NumberField source="angle" label="table.field.sta.angle" />
                    <NumberField source="inboundWait" label="table.field.sta.inboundWait" />
                    <NumberField source="outboundWait" label="table.field.sta.outboundWait" />
                    <NumberField source="angle" label="table.field.sta.angle" sortable={false} />
                    <FunctionField
                        label="table.field.sta.actDir"
                        render={(record) => getCompDirectLabel(translate, record?.actDir)}
                        sortable={false}
                    />
                    <NumberField source="inboundWait" label="table.field.sta.inboundWait" sortable={false} />
                    <NumberField source="outboundWait" label="table.field.sta.outboundWait" sortable={false} />
                    {/* <TextField source="autoing" label="table.field.sta.autoing" />
                    <TextField source="loading" label="table.field.sta.loading" />
                    <TextField source="inEnable" label="table.field.sta.inEnable" />
zy-acs-flow/src/page/sta/StaPanel.jsx
@@ -26,6 +26,7 @@
} from 'react-admin';
import { format } from 'date-fns';
import * as Common from '@/utils/common'
import { getCompDirectLabel } from "../loc/compDirect";
const STATUS_FIELDS = [
    { key: 'autoing', labelKey: 'table.field.sta.autoing' },
@@ -38,9 +39,14 @@
    { labelKey: 'table.field.sta.zoneId', valueKey: 'zoneId$' },
    { labelKey: 'table.field.sta.staType', valueKey: 'staType$' },
    { labelKey: 'table.field.sta.code', valueKey: 'code$' },
    { labelKey: 'table.field.sta.capacity', valueKey: 'capacity' },
    // { labelKey: 'table.field.sta.capacity', valueKey: 'capacity' },
    { labelKey: 'table.field.sta.rsvInCnt', valueKey: 'rsvInCnt' },
    { labelKey: 'table.field.sta.rsvOutCnt', valueKey: 'rsvOutCnt' },
    { labelKey: 'table.field.sta.angle', valueKey: 'angle' },
    {
        labelKey: 'table.field.sta.actDir',
        getValue: (record, translate) => getCompDirectLabel(translate, record?.actDir),
    },
    // { labelKey: 'table.field.sta.offset', valueKey: 'offset' },
    { labelKey: 'table.field.sta.height', valueKey: 'height' },
    { labelKey: 'table.field.sta.depth', valueKey: 'depth' },
@@ -148,11 +154,11 @@
                    <Box height={12}>&nbsp;</Box>
                    <Grid container spacing={2}>
                        {INFO_FIELDS.map(({ labelKey, valueKey }) => (
                        {INFO_FIELDS.map(({ labelKey, valueKey, getValue }) => (
                            <Grid item xs={12} sm={6} md={4} key={labelKey}>
                                <InfoItem
                                    labelKey={labelKey}
                                    value={getRecordValue(record, valueKey)}
                                    value={getValue ? getValue(record, translate) : getRecordValue(record, valueKey)}
                                />
                            </Grid>
                        ))}
zy-acs-flow/src/page/staReserve/StaReserveList.jsx
@@ -36,7 +36,7 @@
import { styled } from '@mui/material/styles';
import StaReserveCreate from "./StaReserveCreate";
import StaReservePanel from "./StaReservePanel";
import EmptyData from "../components/EmptyData";
import EmptyDataLoader from "../components/EmptyDataLoader";
import MyCreateButton from "../components/MyCreateButton";
import MyExportButton from '../components/MyExportButton';
import PageDrawer from "../components/PageDrawer";
@@ -131,7 +131,7 @@
                    marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
                }}
                title={"menu.staReserve"}
                empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
                empty={<EmptyDataLoader />}
                filters={filters}
                sort={{ field: "create_time", order: "desc" }}
                actions={(
zy-acs-flow/src/page/task/TaskList.jsx
@@ -35,7 +35,7 @@
    useNotify,
    useRefresh,
} from 'react-admin';
import { Box, Chip, Card, Stack } from '@mui/material';
import { Box, Chip, Card, Stack, LinearProgress } from '@mui/material';
import { styled } from '@mui/material/styles';
import TaskCreate from "./TaskCreate";
import TaskPanel from "./TaskPanel";
@@ -70,6 +70,20 @@
        width: 200
    },
}));
const UPLINK_STATUS_CHOICES = [
    { id: 'NONE', name: 'page.task.enums.uplinkSts.NONE', color: 'default' },
    { id: 'PENDING', name: 'page.task.enums.uplinkSts.PENDING', color: 'warning' },
    { id: 'SENDING', name: 'page.task.enums.uplinkSts.SENDING', color: 'info' },
    { id: 'SUCCESS', name: 'page.task.enums.uplinkSts.SUCCESS', color: 'success' },
    { id: 'FAILED', name: 'page.task.enums.uplinkSts.FAILED', color: 'error' },
    { id: 'SKIPPED', name: 'page.task.enums.uplinkSts.SKIPPED', color: 'secondary' },
];
const UPLINK_STATUS_MAP = UPLINK_STATUS_CHOICES.reduce((acc, item) => {
    acc[item.id] = item;
    return acc;
}, {});
const filters = [
    // <SearchInput source="condition" alwaysOn />,
@@ -115,6 +129,7 @@
        <AutocompleteInput label="table.field.task.destCode" optionText="data" filterToQuery={(val) => ({ data: val })} />
    </ReferenceInput>,
    <TextInput source="emptyMk" label="table.field.task.emptyMk" />,
    <SelectInput source="uplinkSts" label="table.field.task.uplinkSts" choices={UPLINK_STATUS_CHOICES} />,
    <TextInput source="zpallet" label="table.field.task.zpallet" />,
    // <TextInput source="phase" label="table.field.task.phase" />,
    <TextInput source="errDesc" label="table.field.task.errDesc" />,
@@ -130,12 +145,12 @@
    />,
]
const TaskList = () => {
const TaskListContent = () => {
    const translate = useTranslate();
    const notify = useNotify();
    const refresh = useRefresh();
    const [createDialog, setCreateDialog] = useState(false);
    const [drawerVal, setDrawerVal] = useState(false);
    const { isLoading } = useListContext();
    const [taskStsByComplete, setTaskStsByComplete] = useState(null);
    const [taskStsByCancel, setTaskStsByCancel] = useState(null);
@@ -160,6 +175,7 @@
            setTaskStsByCancel(res.data.data[0]?.id);
        })
    }, []);
    const onComplete = (taskId) => {
        request.get("/task/complete/" + taskId).then(res => {
@@ -190,6 +206,163 @@
    }
    return (
        <Box sx={{ position: 'relative' }}>
            {isLoading && (
                <LinearProgress
                    sx={{
                        height: "2px",
                        position: 'absolute',
                        top: 0,
                        left: 0,
                        right: 0,
                    }}
                />
            )}
            <StyledDatagrid
                preferenceKey='task'
                bulkActionButtons={false}
                rowClick={(id, resource, record) => false}
                expand={() => <TaskPanel />}
                expandSingle={true}
                omit={['id', 'uuid', 'startTime', 'endTime', 'errTime', 'emptyMk', 'zpallet',
                    'oriSta', 'oriLoc', 'oriCode', 'destSta', 'destLoc', 'destCode', 'errDesc',
                    'updateTime', 'updateBy', 'ioTime', 'createBy', 'statusBool', 'memo']}
            >
                <NumberField source="id" />
                <TextField source="uuid" label="table.field.task.uuid" sortable={false} />
                <TextField source="seqNum" label="table.field.task.seqNum" sortable={false} />
                <ReferenceField source="busId" label="table.field.task.busId" reference="bus" link={false} sortable={false}>
                    <TextField source="busNo" />
                </ReferenceField>
                <ReferenceField source="agvId" label="table.field.task.agvId" reference="agv" link={false} sortable={false}>
                    <TextField source="uuid" />
                </ReferenceField>
                {/* <TextField source="name" label="table.field.task.name" /> */}
                <ReferenceField source="taskType" label="table.field.task.taskType" reference="taskType" link={false} sortable={false}>
                    <TextField source="name" />
                </ReferenceField>
                {/* <ReferenceField source="taskSts" label="table.field.task.taskSts" reference="taskSts" link={false} sortable={false}>
                        <TextField source="name" />
                    </ReferenceField> */}
                <ReferenceField source="taskSts" label="table.field.task.taskSts" reference="taskSts" link={false} sortable={true}>
                    <FunctionField render={record => (
                        <Chip
                            label={record.name}
                            variant="outlined"
                            size="small"
                            color={getTaskStsChipColor(record.name)}
                            sx={{ fontSize: '0.75rem' }}
                        />
                    )} />
                    {/* <TextField source="name" /> */}
                </ReferenceField>
                <DateField source="ioTime" label="table.field.task.ioTime" showTime sortable={false} />
                <DateField source="startTime" label="table.field.task.startTime" showTime sortable={false} />
                <DateField source="endTime" label="table.field.task.endTime" showTime sortable={false} />
                <DateField source="errTime" label="table.field.task.errTime" showTime sortable={false} />
                <ReferenceField source="oriSta" label="table.field.task.oriSta" reference="sta" link={false} sortable={false}>
                    <TextField source="staNo" />
                </ReferenceField>
                <ReferenceField source="oriLoc" label="table.field.task.oriLoc" reference="loc" link={false} sortable={false}>
                    <TextField source="locNo" />
                </ReferenceField>
                <ReferenceField source="oriCode" label="table.field.task.oriCode" reference="code" link={false} sortable={false}>
                    <TextField source="data" />
                </ReferenceField>
                <ReferenceField source="destSta" label="table.field.task.destSta" reference="sta" link={false} sortable={false}>
                    <TextField source="staNo" />
                </ReferenceField>
                <ReferenceField source="destLoc" label="table.field.task.destLoc" reference="loc" link={false} sortable={false}>
                    <TextField source="locNo" />
                </ReferenceField>
                <ReferenceField source="destCode" label="table.field.task.destCode" reference="code" link={false} sortable={false}>
                    <TextField source="data" />
                </ReferenceField>
                <TextField source="oriDesc" label="table.field.task.oriDesc" sortable={false} />
                <TextField source="destDesc" label="table.field.task.destDesc" sortable={false} />
                <NumberField source="priority" label="table.field.task.priority" sortable={false} />
                <FunctionField
                    label="table.field.task.uplinkSts"
                    sortable={false}
                    render={record => {
                        const meta = UPLINK_STATUS_MAP[record?.uplinkSts];
                        return (
                            <Chip
                                label={meta?.name ? translate(meta.name) : translate('common.enums.na')}
                                variant="outlined"
                                size="small"
                                color={meta?.color ?? 'default'}
                                sx={{ fontSize: '0.75rem' }}
                            />
                        );
                    }}
                />
                <TextField source="emptyMk" label="table.field.task.emptyMk" sortable={false} />
                <TextField source="zpallet" label="table.field.task.zpallet" sortable={false} />
                <TextField source="errDesc" label="table.field.task.errDesc" sortable={false} />
                <ReferenceField source="updateBy" label="common.field.updateBy" reference="user" link={false} sortable={false}>
                    <TextField source="nickname" />
                </ReferenceField>
                <DateField source="updateTime" label="common.field.updateTime" showTime />
                <ReferenceField source="createBy" label="common.field.createBy" reference="user" link={false} sortable={false}>
                    <TextField source="nickname" />
                </ReferenceField>
                <DateField source="createTime" label="common.field.createTime" showTime sortable={false} />
                <BooleanField source="statusBool" label="common.field.status" sortable={false} />
                <TextField source="memo" label="common.field.memo" sortable={false} />
                <FunctionField label="common.field.opt" cellClassName="opt" render={record => (
                    (record.taskSts !== taskStsByComplete && record.taskSts !== taskStsByCancel) && (
                        <>
                            <ConfirmButton
                                label="common.action.complete"
                                size="small"
                                color="primary"
                                startIcon={<CheckIcon />}
                                sx={{
                                    padding: '1px',
                                    fontSize: '.75rem',
                                    '& .MuiButton-startIcon': {
                                        marginRight: '2px'
                                    },
                                    mr: 1
                                }}
                                data={record.seqNum}
                                onConfirm={() => {
                                    onComplete(record.id);
                                }}
                            />
                            <ConfirmButton
                                label="ra.action.cancel"
                                size="small"
                                color="error"
                                startIcon={<ClearIcon />}
                                sx={{
                                    padding: '1px',
                                    fontSize: '.75rem',
                                    '& .MuiButton-startIcon': {
                                        marginRight: '1.5px'
                                    },
                                }}
                                data={record.seqNum}
                                onConfirm={() => {
                                    onCancel(record.id);
                                }}
                            />
                        </>
                    )
                )} />
            </StyledDatagrid>
        </Box>
    )
}
const TaskList = () => {
    const [createDialog, setCreateDialog] = useState(false);
    const [drawerVal, setDrawerVal] = useState(false);
    return (
        <Box display="flex">
            <List
                sx={{
@@ -216,125 +389,7 @@
                perPage={25}
                aside={<TaskListAside />}
            >
                <StyledDatagrid
                    preferenceKey='task'
                    bulkActionButtons={false}
                    rowClick={(id, resource, record) => false}
                    expand={() => <TaskPanel />}
                    expandSingle={true}
                    omit={['id', 'uuid', 'startTime', 'endTime', 'errTime', 'emptyMk', 'zpallet',
                        'oriSta', 'oriLoc', 'oriCode', 'destSta', 'destLoc', 'destCode', 'errDesc',
                        'updateTime', 'updateBy', 'ioTime', 'createBy', 'statusBool', 'memo']}
                >
                    <NumberField source="id" />
                    <TextField source="uuid" label="table.field.task.uuid" sortable={false} />
                    <TextField source="seqNum" label="table.field.task.seqNum" sortable={false} />
                    <ReferenceField source="busId" label="table.field.task.busId" reference="bus" link={false} sortable={false}>
                        <TextField source="busNo" />
                    </ReferenceField>
                    <ReferenceField source="agvId" label="table.field.task.agvId" reference="agv" link={false} sortable={false}>
                        <TextField source="uuid" />
                    </ReferenceField>
                    {/* <TextField source="name" label="table.field.task.name" /> */}
                    <ReferenceField source="taskType" label="table.field.task.taskType" reference="taskType" link={false} sortable={false}>
                        <TextField source="name" />
                    </ReferenceField>
                    {/* <ReferenceField source="taskSts" label="table.field.task.taskSts" reference="taskSts" link={false} sortable={false}>
                        <TextField source="name" />
                    </ReferenceField> */}
                    <ReferenceField source="taskSts" label="table.field.task.taskSts" reference="taskSts" link={false} sortable={true}>
                        <FunctionField render={record => (
                            <Chip
                                label={record.name}
                                variant="outlined"
                                size="small"
                                color={getTaskStsChipColor(record.name)}
                                sx={{ fontSize: '0.75rem' }}
                            />
                        )} />
                        {/* <TextField source="name" /> */}
                    </ReferenceField>
                    <DateField source="ioTime" label="table.field.task.ioTime" showTime sortable={false} />
                    <DateField source="startTime" label="table.field.task.startTime" showTime sortable={false} />
                    <DateField source="endTime" label="table.field.task.endTime" showTime sortable={false} />
                    <DateField source="errTime" label="table.field.task.errTime" showTime sortable={false} />
                    <ReferenceField source="oriSta" label="table.field.task.oriSta" reference="sta" link={false} sortable={false}>
                        <TextField source="staNo" />
                    </ReferenceField>
                    <ReferenceField source="oriLoc" label="table.field.task.oriLoc" reference="loc" link={false} sortable={false}>
                        <TextField source="locNo" />
                    </ReferenceField>
                    <ReferenceField source="oriCode" label="table.field.task.oriCode" reference="code" link={false} sortable={false}>
                        <TextField source="data" />
                    </ReferenceField>
                    <ReferenceField source="destSta" label="table.field.task.destSta" reference="sta" link={false} sortable={false}>
                        <TextField source="staNo" />
                    </ReferenceField>
                    <ReferenceField source="destLoc" label="table.field.task.destLoc" reference="loc" link={false} sortable={false}>
                        <TextField source="locNo" />
                    </ReferenceField>
                    <ReferenceField source="destCode" label="table.field.task.destCode" reference="code" link={false} sortable={false}>
                        <TextField source="data" />
                    </ReferenceField>
                    <TextField source="oriDesc" label="table.field.task.oriDesc" sortable={false} />
                    <TextField source="destDesc" label="table.field.task.destDesc" sortable={false} />
                    <NumberField source="priority" label="table.field.task.priority" sortable={false} />
                    <TextField source="emptyMk" label="table.field.task.emptyMk" sortable={false} />
                    <TextField source="zpallet" label="table.field.task.zpallet" sortable={false} />
                    <TextField source="errDesc" label="table.field.task.errDesc" sortable={false} />
                    <ReferenceField source="updateBy" label="common.field.updateBy" reference="user" link={false} sortable={false}>
                        <TextField source="nickname" />
                    </ReferenceField>
                    <DateField source="updateTime" label="common.field.updateTime" showTime />
                    <ReferenceField source="createBy" label="common.field.createBy" reference="user" link={false} sortable={false}>
                        <TextField source="nickname" />
                    </ReferenceField>
                    <DateField source="createTime" label="common.field.createTime" showTime sortable={false} />
                    <BooleanField source="statusBool" label="common.field.status" sortable={false} />
                    <TextField source="memo" label="common.field.memo" sortable={false} />
                    <FunctionField label="common.field.opt" cellClassName="opt" render={record => (
                        (record.taskSts !== taskStsByComplete && record.taskSts !== taskStsByCancel) && (
                            <>
                                <ConfirmButton
                                    label="common.action.complete"
                                    size="small"
                                    color="primary"
                                    startIcon={<CheckIcon />}
                                    sx={{
                                        padding: '1px',
                                        fontSize: '.75rem',
                                        '& .MuiButton-startIcon': {
                                            marginRight: '2px'
                                        },
                                        mr: 1
                                    }}
                                    data={record.seqNum}
                                    onConfirm={() => {
                                        onComplete(record.id);
                                    }}
                                />
                                <ConfirmButton
                                    label="ra.action.cancel"
                                    size="small"
                                    color="error"
                                    startIcon={<ClearIcon />}
                                    sx={{
                                        padding: '1px',
                                        fontSize: '.75rem',
                                        '& .MuiButton-startIcon': {
                                            marginRight: '1.5px'
                                        },
                                    }}
                                    data={record.seqNum}
                                    onConfirm={() => {
                                        onCancel(record.id);
                                    }}
                                />
                            </>
                        )
                    )} />
                </StyledDatagrid>
                <TaskListContent drawerVal={drawerVal} />
            </List>
            <TaskCreate
                open={createDialog}
zy-acs-flow/src/page/task/TaskListAside.jsx
@@ -51,7 +51,7 @@
                mt: 8,
                alignSelf: 'flex-start',
                border: theme[0] === 'light' && '1px solid #e0e0e3',
                width: 255
                width: 210
            }}
        >
            <CardContent>
zy-acs-framework/src/main/java/com/zy/acs/framework/annotations/IntegrationAuth.java
New file
@@ -0,0 +1,21 @@
package com.zy.acs.framework.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface IntegrationAuth {
    Auth value() default Auth.CHECK;
    String memo() default "";
    public enum Auth{
        CHECK,
        NONE
    }
}
zy-acs-hex/pom.xml
@@ -16,15 +16,22 @@
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <spring-boot.version>2.5.3</spring-boot.version>
        <fastjson.version>1.2.58</fastjson.version>
        <!-- Dependency Versions -->
        <influxdb-java.version>1.7.0</influxdb-java.version>
    </properties>
    <dependencies>
    <dependency>
        <groupId>com.zy</groupId>
        <artifactId>acs-common</artifactId>
        <version>1.0.0</version>
    </dependency>
        <dependency>
            <groupId>com.zy</groupId>
            <artifactId>acs-common</artifactId>
            <version>1.0.0</version>
        </dependency>
        <dependency>
            <groupId>com.zy</groupId>
            <artifactId>component-Influxdb</artifactId>
            <version>1.0.0</version>
        </dependency>
        <!-- SpringBoot Web -->
        <dependency>
@@ -39,10 +46,10 @@
        </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- Lombok -->
        <dependency>
zy-acs-hex/src/main/java/com/zy/acs/hex/HexApplication.java
@@ -3,7 +3,9 @@
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
@ComponentScan(basePackages = {"com.zy.component", "com.zy.acs"})
@SpringBootApplication
public class HexApplication {
zy-acs-hex/src/main/java/com/zy/acs/hex/config/MessageConverterConfig.java
File was deleted
zy-acs-hex/src/main/java/com/zy/acs/hex/config/RabbitConfig.java
New file
@@ -0,0 +1,31 @@
package com.zy.acs.hex.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Slf4j
@Configuration
public class RabbitConfig {
    @Bean
    public RabbitTemplate rabbitTemplate(CachingConnectionFactory connectionFactory) {
        RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
        rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
            if (ack) {
                log.info("消息成功发送到Exchange");
            } else {
                log.info("消息发送失败:" + cause);
            }
        });
        // ä¹Ÿå¯ä»¥è®¾ç½®è¿”回类型为mandatory,这样当消息无法路由到任何队列时,会返回给生产者一个Basic.Return。
        rabbitTemplate.setMandatory(true);
        rabbitTemplate.setReturnCallback((message, replyCode, replyText, exchange, routingKey) -> {
            log.info("消息无法路由到队列: " + replyText);
        });
        return rabbitTemplate;
    }
}
zy-acs-hex/src/main/java/com/zy/acs/hex/constant/InfluxDBConstant.java
New file
@@ -0,0 +1,28 @@
package com.zy.acs.hex.constant;
/**
 * æ—¶åºæ•°æ®åº“常量类
 *
 * @author ken
 */
public class InfluxDBConstant {
    public static final String DEVICE_MEASUREMENT = "device";
    public static final String DEVICE_MEASUREMENT_TAG_DEVICEID = "deviceId";
    public static final String DEVICE_MEASUREMENT_TAG_EVENT = "event";
    public static final String DEVICE_MEASUREMENT_TAG_TYPE = "type";
    public static class DEVICE_MEASUREMENT_TAG_TYPE_FLAG {
        public static final String DEVICE_MEASUREMENT_TAG_TYPE_UP = "up";
        public static final String DEVICE_MEASUREMENT_TAG_TYPE_DOWN = "down";
    }
}
zy-acs-hex/src/main/java/com/zy/acs/hex/constant/RabbitConstant.java
File was renamed from zy-acs-hex/src/main/java/com/zy/acs/hex/config/RabbitMQConfig.java
@@ -1,9 +1,4 @@
package com.zy.acs.hex.config;
import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
package com.zy.acs.hex.constant;
/**
@@ -11,9 +6,12 @@
 *
 * @author ken
 */
@Configuration
public class RabbitMQConfig {
public class RabbitConstant {
    public static final String DURABLE = "true";
    public static final String TOPIC_EXCHANGE_TYPE = "topic";
    // ========================== ä¸»é¢˜æ¨¡å¼ ==========================
    /**
zy-acs-hex/src/main/java/com/zy/acs/hex/consumer/DownMessageListener.java
New file
@@ -0,0 +1,42 @@
package com.zy.acs.hex.consumer;
import com.rabbitmq.client.Channel;
import com.zy.acs.hex.constant.InfluxDBConstant;
import com.zy.acs.hex.constant.RabbitConstant;
import com.zy.acs.hex.consumer.listener.AbstractListener;
import com.zy.acs.hex.domain.Device;
import com.zy.acs.hex.utils.ReflectionUtils;
import com.zy.acs.hex.utils.StrUtils;
import com.zy.component.influxdb.service.InfluxDBService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Component;
/**
 * æ¶ˆè´¹è€…
 */
@Slf4j
@Component
@RabbitListener(bindings = @QueueBinding(
        value = @Queue(name = RabbitConstant.TOPIC_QUEUE_DOWN, durable = RabbitConstant.DURABLE),
        exchange = @Exchange(name = RabbitConstant.TOPIC_EXCHANGE, type = RabbitConstant.TOPIC_EXCHANGE_TYPE),
        key = RabbitConstant.ROUTING_KEY_DOWN
))
public class DownMessageListener implements AbstractListener {
    @Autowired
    private InfluxDBService influxDBService;
    @RabbitHandler
    public void handle(Device msg, @Header(AmqpHeaders.RECEIVED_ROUTING_KEY) String routingKey, Channel channel) {
        log.info("routingKey:{},receive down message:{}", routingKey, msg);
        influxDBService.writeData(InfluxDBConstant.DEVICE_MEASUREMENT, StrUtils.getTagsByRoutingKey(routingKey), ReflectionUtils.convertBean2Map(msg));
    }
}
zy-acs-hex/src/main/java/com/zy/acs/hex/consumer/MessageListener.java
File was deleted
zy-acs-hex/src/main/java/com/zy/acs/hex/consumer/UpMessageListener.java
New file
@@ -0,0 +1,42 @@
package com.zy.acs.hex.consumer;
import com.rabbitmq.client.Channel;
import com.zy.acs.hex.constant.InfluxDBConstant;
import com.zy.acs.hex.constant.RabbitConstant;
import com.zy.acs.hex.consumer.listener.AbstractListener;
import com.zy.acs.hex.domain.Device;
import com.zy.acs.hex.utils.ReflectionUtils;
import com.zy.acs.hex.utils.StrUtils;
import com.zy.component.influxdb.service.InfluxDBService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Component;
/**
 * æ¶ˆè´¹è€…
 */
@Slf4j
@Component
@RabbitListener(bindings = @QueueBinding(
        value = @Queue(name = RabbitConstant.TOPIC_QUEUE_UP, durable = RabbitConstant.DURABLE),
        exchange = @Exchange(name = RabbitConstant.TOPIC_EXCHANGE, type = RabbitConstant.TOPIC_EXCHANGE_TYPE),
        key = RabbitConstant.ROUTING_KEY_UP
))
public class UpMessageListener implements AbstractListener {
    @Autowired
    private InfluxDBService influxDBService;
    @RabbitHandler
    public void handle(Device msg, @Header(AmqpHeaders.RECEIVED_ROUTING_KEY) String routingKey, Channel channel) {
        log.info("routingKey:{},receive up message:{}", routingKey, msg);
        influxDBService.writeData(InfluxDBConstant.DEVICE_MEASUREMENT, StrUtils.getTagsByRoutingKey(routingKey), ReflectionUtils.convertBean2Map(msg));
    }
}
zy-acs-hex/src/main/java/com/zy/acs/hex/consumer/listener/AbstractListener.java
New file
@@ -0,0 +1,10 @@
package com.zy.acs.hex.consumer.listener;
import com.rabbitmq.client.Channel;
import com.zy.acs.hex.domain.Device;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.messaging.handler.annotation.Header;
public interface AbstractListener {
    void handle(Device event, @Header(AmqpHeaders.RECEIVED_ROUTING_KEY) String routingKey, Channel channel);
}
zy-acs-hex/src/main/java/com/zy/acs/hex/controller/TestController.java
New file
@@ -0,0 +1,45 @@
package com.zy.acs.hex.controller;
import com.zy.acs.hex.constant.RabbitConstant;
import com.zy.acs.hex.domain.Device;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@Slf4j
@RequestMapping(value = "/message")
public class TestController {
    @Autowired
    private RabbitTemplate rabbitTemplate;
    /**
     * å‘送消息test1
     *
     * @return
     */
    @GetMapping(value = "/test1")
    public void sendTest1() {
        Device device = new Device();
        //device.setEvent("online");
        //device.setDeviceId("123");
        device.setProtocol("212121212121212");
        String router = RabbitConstant.ROUTING_KEY_UP.replaceFirst("\\*", "123").replaceFirst("\\*", "online");
        rabbitTemplate.convertAndSend(RabbitConstant.TOPIC_EXCHANGE, router, device);
    }
    /**
     * å‘送消息test2
     *
     * @return
     */
    @GetMapping(value = "/test2")
    public void sendTest2() {
        rabbitTemplate.convertAndSend(RabbitConstant.TOPIC_EXCHANGE, RabbitConstant.ROUTING_KEY_DOWN, "qswaqsaasas");
    }
}
zy-acs-hex/src/main/java/com/zy/acs/hex/domain/Device.java
New file
@@ -0,0 +1,10 @@
package com.zy.acs.hex.domain;
import lombok.Data;
import java.io.Serializable;
@Data
public class Device implements Serializable {
    private String protocol;
}
zy-acs-hex/src/main/java/com/zy/acs/hex/utils/ReflectionUtils.java
New file
@@ -0,0 +1,171 @@
package com.zy.acs.hex.utils;
import com.zy.acs.framework.common.Cools;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ReflectionUtils {
    /**
     * èŽ·å–ä¸€ä¸ªç±»å’Œå…¶çˆ¶ç±»çš„æ‰€æœ‰å±žæ€§
     *
     * @param clazz
     * @return
     */
    public static List<Field> findAllFieldsOfSelfAndSuperClass(Class clazz) {
        Field[] fields = null;
        List fieldList = new ArrayList();
        while (true) {
            if (clazz == null) {
                break;
            } else {
                fields = clazz.getDeclaredFields();
                for (int i = 0; i < fields.length; i++) {
                    fieldList.add(fields[i]);
                }
                clazz = clazz.getSuperclass();
            }
        }
        return fieldList;
    }
    /**
     * æŠŠä¸€ä¸ªBean对象转换成Map对象</br>
     *
     * @param obj
     * @param ignores
     * @return
     * @throws IllegalAccessException
     */
    public static Map convertBean2Map(Object obj, String[] ignores) {
        Map map = new HashMap();
        Class clazz = obj.getClass();
        List<Field> fieldList = findAllFieldsOfSelfAndSuperClass(clazz);
        Field field = null;
        try {
            for (int i = 0; i < fieldList.size(); i++) {
                field = fieldList.get(i);
                // å®šä¹‰fieldName是否在拷贝忽略的范畴内
                boolean flag = false;
                if (ignores != null && ignores.length != 0) {
                    flag = isExistOfIgnores(field.getName(), ignores);
                }
                if (!flag) {
                    Object value = getProperty(obj, field.getName());
                    if (null != value
                            && !Cools.isEmpty(value.toString())) {
                        map.put(field.getName(),
                                getProperty(obj, field.getName()));
                    }
                }
            }
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        }
        return map;
    }
    /**
     * æŠŠä¸€ä¸ªBean对象转换成Map对象</br>
     *
     * @param obj
     * @return
     */
    public static Map convertBean2Map(Object obj) {
        return convertBean2Map(obj, null);
    }
    public static Map convertBean2MapForIngoreserialVersionUID(Object obj) {
        return convertBean2Map(obj, new String[]{"serialVersionUID"});
    }
    /**
     * åˆ¤æ–­fieldName是否是ignores中排除的
     *
     * @param fieldName
     * @param ignores
     * @return
     */
    private static boolean isExistOfIgnores(String fieldName,
                                            String[] ignores) {
        boolean flag = false;
        for (String str : ignores) {
            if (str.equals(fieldName)) {
                flag = true;
                break;
            }
        }
        return flag;
    }
    public static PropertyDescriptor getPropertyDescriptor(Class clazz,
                                                           String propertyName) {
        StringBuffer sb = new StringBuffer();// æž„建一个可变字符串用来构建方法名称
        Method setMethod = null;
        Method getMethod = null;
        PropertyDescriptor pd = null;
        try {
            Field f = clazz.getDeclaredField(propertyName);// æ ¹æ®å­—段名来获取字段
            if (f != null) {
                // æž„建方法的后缀
                String methodEnd = propertyName.substring(0, 1).toUpperCase()
                        + propertyName.substring(1);
                sb.append("set" + methodEnd);// æž„建set方法
                setMethod = clazz.getDeclaredMethod(sb.toString(),
                        new Class[]{f.getType()});
                sb.delete(0, sb.length());// æ¸…空整个可变字符串
                sb.append("get" + methodEnd);// æž„建get方法
                // æž„建get æ–¹æ³•
                getMethod =
                        clazz.getDeclaredMethod(sb.toString(), new Class[]{});
                // æž„建一个属性描述器 æŠŠå¯¹åº”属性 propertyName çš„ get å’Œ set æ–¹æ³•保存到属性描述器中
                pd = new PropertyDescriptor(propertyName, getMethod, setMethod);
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return pd;
    }
    @SuppressWarnings("unchecked")
    public static void setProperty(Object obj, String propertyName,
                                   Object value) {
        Class clazz = obj.getClass();// èŽ·å–å¯¹è±¡çš„ç±»åž‹
        PropertyDescriptor pd = getPropertyDescriptor(clazz, propertyName);// èŽ·å– clazz
        // ç±»åž‹ä¸­çš„
        // propertyName
        // çš„属性描述器
        Method setMethod = pd.getWriteMethod();// ä»Žå±žæ€§æè¿°å™¨ä¸­èŽ·å– set æ–¹æ³•
        try {
            setMethod.invoke(obj, new Object[]{value});// è°ƒç”¨ set æ–¹æ³•将传入的value值保存属性中去
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    @SuppressWarnings({"unchecked", "rawtypes"})
    public static Object getProperty(Object obj, String propertyName) {
        Class clazz = obj.getClass();// èŽ·å–å¯¹è±¡çš„ç±»åž‹
        PropertyDescriptor pd = getPropertyDescriptor(clazz, propertyName);// èŽ·å– clazz
        // ç±»åž‹ä¸­çš„
        // propertyName
        // çš„属性描述器
        Method getMethod = pd.getReadMethod();// ä»Žå±žæ€§æè¿°å™¨ä¸­èŽ·å– get æ–¹æ³•
        Object value = null;
        try {
            value = getMethod.invoke(obj, new Object[]{});// è°ƒç”¨æ–¹æ³•获取方法的返回值
        } catch (Exception e) {
            e.printStackTrace();
        }
        return value;// è¿”回值
    }
}
zy-acs-hex/src/main/java/com/zy/acs/hex/utils/StrUtils.java
New file
@@ -0,0 +1,62 @@
package com.zy.acs.hex.utils;
import com.zy.acs.hex.constant.InfluxDBConstant;
import java.util.HashMap;
import java.util.Map;
public class StrUtils {
    public static Map<String, String> getTagsByRoutingKey(String routingKey) {
        // æ­£åˆ™è¡¨è¾¾å¼åŒ¹é… rcs.up. å¼€å¤´ï¼ŒåŽé¢è·Ÿç€ä¸¤ä¸ªç‰ˆæœ¬å·éƒ¨åˆ†
        String regex = "^rcs\\.up\\.(\\*|[a-zA-Z0-9]+)\\.(\\*|[a-zA-Z0-9]+)$";
        if (routingKey.matches(regex)) {
            // åˆ†å‰²å­—符串并返回版本号部分
            String[] parts = routingKey.split("\\.");
            if (parts.length == 4) {
                Map<String, String> data = new HashMap<>();
                data.put(InfluxDBConstant.DEVICE_MEASUREMENT_TAG_TYPE, parts[1]);
                data.put(InfluxDBConstant.DEVICE_MEASUREMENT_TAG_DEVICEID, parts[2]);
                data.put(InfluxDBConstant.DEVICE_MEASUREMENT_TAG_EVENT, parts[3]);
                return data;
            }
        }
        // å¦‚果格式不符合,返回空数组
        return null;
    }
    public static String getDeviceIdByRoutingKey(String routingKey) {
        // æ­£åˆ™è¡¨è¾¾å¼åŒ¹é… rcs.up. å¼€å¤´ï¼ŒåŽé¢è·Ÿç€ä¸¤ä¸ªç‰ˆæœ¬å·éƒ¨åˆ†
        String regex = "^rcs\\.up\\.(\\*|[a-zA-Z0-9]+)\\.(\\*|[a-zA-Z0-9]+)$";
        if (routingKey.matches(regex)) {
            // åˆ†å‰²å­—符串并返回版本号部分
            String[] parts = routingKey.split("\\.");
            if (parts.length == 4) {
                return parts[2];
            }
        }
        // å¦‚果格式不符合,返回空数组
        return null;
    }
    public static String getEventByRoutingKey(String routingKey) {
        // æ­£åˆ™è¡¨è¾¾å¼åŒ¹é… rcs.up. å¼€å¤´ï¼ŒåŽé¢è·Ÿç€ä¸¤ä¸ªç‰ˆæœ¬å·éƒ¨åˆ†
        String regex = "^rcs\\.up\\.(\\*|[a-zA-Z0-9]+)\\.(\\*|[a-zA-Z0-9]+)$";
        if (routingKey.matches(regex)) {
            // åˆ†å‰²å­—符串并返回版本号部分
            String[] parts = routingKey.split("\\.");
            if (parts.length == 4) {
                return parts[2];
            }
        }
        // å¦‚果格式不符合,返回空数组
        return null;
    }
    public static void main(String[] args) {
        System.out.println(StrUtils.getDeviceIdByRoutingKey("rcs.up.ds1233.2aads"));
    }
}
zy-acs-hex/src/main/resources/application.yml
@@ -1,4 +1,3 @@
spring:
  application:
    name: rcs-hex
@@ -6,22 +5,21 @@
  rabbitmq:
    host: localhost
    port: 5672
    username: admin
    password: 123456
    username: root
    password: xltys1995
    # è™šæ‹Ÿhost可以不设置,默认/
    virtual-host: /
    # ç”Ÿäº§è€…确认配置
    publisher-confirm-type: correlated
    publisher-returns: true
    # æ¶ˆè´¹è€…配置
    listener:
      simple:
        # æ‰‹åŠ¨ç¡®è®¤æ¨¡å¼
        acknowledge-mode: manual
        # æ¶ˆè´¹è€…线程数
        concurrency: 1
        # æœ€å¤§æ¶ˆè´¹è€…线程数
        max-concurrency: 5
        # æ¯æ¬¡ä»Žé˜Ÿåˆ—中获取的消息数量
        prefetch: 1
      direct:
        acknowledge-mode: manual
#    listener:
#      direct:
#    ç¡®è®¤æœºåˆ¶
#        acknowledge-mode: manual
influxdb3:
  enabled: true
  url: http://127.0.0.1:8181
  token: apiv3_Jx1SvmBMV_kikGhc4eZJQbeGmNYN7KX1GdpoR9MClkKzMxSJ0MPKM_O2Xt3o1hVyRikMmlxZ_h9zfy6ybC5Idg
  database: rcs
zy-acs-manager/src/main/java/com/zy/acs/manager/common/CodeBuilder.java
@@ -22,8 +22,8 @@
//        generator.username="sa";priority
//        generator.password="Zoneyung@zy56$";
        generator.table="man_lane";
        generator.tableDesc="Lane";
        generator.table="man_integration_record";
        generator.tableDesc="Integration Record";
        generator.packagePath="com.zy.acs.manager.manager";
        generator.build();
@@ -55,6 +55,7 @@
 * TRUNCATE man_jam;
 * TRUNCATE man_action;
 * TRUNCATE man_sta_reserve;
 * TRUNCATE man_integration_record;
 *
 * TRUNCATE man_code;
 * TRUNCATE man_code_gap;
zy-acs-manager/src/main/java/com/zy/acs/manager/common/config/ConveyorProperties.java
@@ -1,5 +1,6 @@
package com.zy.acs.manager.common.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@@ -10,6 +11,7 @@
 * è¾“送线plc系统配置
 * Created by luxiaotao on 2018/10/15
 */
@Data
@Configuration
@ConfigurationProperties(prefix = "convey-plc")
public class ConveyorProperties {
@@ -28,27 +30,9 @@
    private Integer port;
    public static String getHostName() {
        return HOST_NAME;
    }
    private String url;
    public static void setHostName(String hostName) {
        HOST_NAME = hostName;
    }
    // millisecond
    private Integer timeout = 15 * 1000;
    public String getHost() {
        return host;
    }
    public void setHost(String host) {
        this.host = host;
    }
    public Integer getPort() {
        return port;
    }
    public void setPort(Integer port) {
        this.port = port;
    }
}
zy-acs-manager/src/main/java/com/zy/acs/manager/common/config/IntegrationRecordAdvice.java
New file
@@ -0,0 +1,84 @@
package com.zy.acs.manager.common.config;
import com.alibaba.fastjson.JSON;
import com.zy.acs.framework.common.Cools;
import com.zy.acs.framework.common.R;
import com.zy.acs.manager.common.utils.IpTools;
import com.zy.acs.manager.manager.service.IntegrationRecordService;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
@Slf4j
//@ControllerAdvice
public class IntegrationRecordAdvice implements ResponseBodyAdvice<Object> {
    @Autowired
    private IntegrationRecordService integrationRecordService;
    @Override
    public boolean supports(@NotNull MethodParameter methodParameter, @NotNull Class<? extends HttpMessageConverter<?>> aClass) {
        return true;
    }
    @Override
    public Object beforeBodyWrite(Object o
            , @NotNull MethodParameter methodParameter
            , @NotNull MediaType mediaType
            , @NotNull Class<? extends HttpMessageConverter<?>> aClass
            , @NotNull ServerHttpRequest serverHttpRequest
            , @NotNull ServerHttpResponse serverHttpResponse) {
        if (serverHttpRequest instanceof ServletServerHttpRequest) {
            HttpServletRequest request = ((ServletServerHttpRequest) serverHttpRequest).getServletRequest();
            Object appAuth = request.getAttribute("appAuth");
            if (appAuth != null) {
                if (o instanceof R) {
                    String appkey = request.getHeader("appkey");
                    Object reqCache = request.getAttribute("cache");
                    if (!Cools.isEmpty(appkey)) {
                        // ä¿å­˜æŽ¥å£æ—¥å¿—
//                        apiLogService.save(
//                                String.valueOf(appAuth),
//                                request.getRequestURI(),
//                                appkey,
//                                IpTools.gainRealIp(request),
//                                reqCache==null?"": JSON.toJSONString(reqCache),
//                                JSON.toJSONString(o),
//                                String.valueOf(((R) o).get("code")).equalsIgnoreCase("200")
//                        );
                    }
                }
            }
        }
        return o;
    }
    public static String json(HttpServletRequest request) {
        try {
            BufferedReader streamReader = new BufferedReader( new InputStreamReader(request.getInputStream(), StandardCharsets.UTF_8));
            StringBuilder sb = new StringBuilder();
            String inputStr;
            while ((inputStr = streamReader.readLine()) != null) {
                sb.append(inputStr);
            }
            return sb.toString();
        } catch (Exception e) {
            log.error(e.getMessage());
            return "";
        }
    }
}
zy-acs-manager/src/main/java/com/zy/acs/manager/common/config/UplinkProperties.java
New file
@@ -0,0 +1,40 @@
package com.zy.acs.manager.common.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import java.net.InetAddress;
import java.net.UnknownHostException;
/**
 * ä¸Šæ¸¸æœåŠ¡ç³»ç»Ÿé…ç½®
 * Created by luxiaotao on 2018/10/15
 */
@Data
@Configuration
@ConfigurationProperties(prefix = "uplink")
public class UplinkProperties {
    public static String HOST_NAME;
    static {
        try {
            HOST_NAME = InetAddress.getLocalHost().getHostName();
        } catch (UnknownHostException e) {
            System.err.println("find hostname err");
        }
    }
    private Boolean enabled;
    private String host;
    private Integer port;
    private String url;
    // millisecond
    private Integer timeout = 60 * 1000;
}
zy-acs-manager/src/main/java/com/zy/acs/manager/common/constant/Constants.java
@@ -6,8 +6,14 @@
 */
public class Constants {
    public static final String UPLINK = "UPLINK";
    public static final String HANDLE = "HANDLE";
    public static final String LIMIT_ONE = "limit 1";
    public static final String RCS = "RCS";
    /**
     * é»˜è®¤æˆåŠŸç 
     */
zy-acs-manager/src/main/java/com/zy/acs/manager/common/domain/TaskBoolDto.java
New file
@@ -0,0 +1,28 @@
package com.zy.acs.manager.common.domain;
import lombok.Data;
@Data
public class TaskBoolDto {
    private String taskNo;
    private Boolean success;
    private String msg;
    public TaskBoolDto() {
    }
    public TaskBoolDto(String taskNo, Boolean success) {
        this.taskNo = taskNo;
        this.success = success;
    }
    public TaskBoolDto(String taskNo, Boolean success, String msg) {
        this.taskNo = taskNo;
        this.success = success;
        this.msg = msg;
    }
}
zy-acs-manager/src/main/java/com/zy/acs/manager/common/domain/TaskDto.java
@@ -8,7 +8,7 @@
@Data
public class TaskDto {
    private String seqNum;
    private String taskNo;
    private String oriLoc;
zy-acs-manager/src/main/java/com/zy/acs/manager/common/utils/ExcelUtil.java
@@ -2,10 +2,10 @@
import com.zy.acs.framework.common.Cools;
import io.swagger.annotations.ApiModelProperty;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@@ -24,19 +24,24 @@
    public static void build(Workbook workbook, HttpServletResponse response) {
        response.reset();
        Http.cors(response);
        response.setContentType("application/octet-stream; charset=utf-8");
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet; charset=utf-8");
        try {
            response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode("export", "UTF-8"));
            response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode("export.xlsx", "UTF-8"));
            workbook.write(response.getOutputStream());
            workbook.close();
        } catch (IOException ignore) {}
    }
    public static <T> Workbook create(List<T> list, Class<T> clz) {
        HSSFWorkbook workbook = new HSSFWorkbook();
        XSSFWorkbook workbook = new XSSFWorkbook();
        Sheet sheet = workbook.createSheet(clz.getSimpleName());
        Row header = sheet.createRow(0);
        Field[] fields = Cools.getAllFields(clz);
        int headerIdx = 0;
        for (Field field : fields) {
            if (Modifier.isFinal(field.getModifiers())
@@ -44,6 +49,7 @@
                    || Modifier.isTransient(field.getModifiers())) {
                continue;
            }
            String memo = "Undefined";
            if (field.isAnnotationPresent(ApiModelProperty.class)) {
                memo = field.getAnnotation(ApiModelProperty.class).value();
@@ -83,7 +89,7 @@
            }
        }
        for (int i = 0; i <= fields.length; i++) {
        for (int i = 0; i <= headerIdx; i++) {
            sheet.autoSizeColumn(i);
        }
zy-acs-manager/src/main/java/com/zy/acs/manager/common/utils/HttpGo.java
@@ -264,6 +264,16 @@
        }
    }
    // ======================== tools ========================
    public String buildUrl(String host, Integer port, String path) {
        return buildUrl(host, port, path, false);
    }
    public String buildUrl(String host, Integer port, String path, boolean ssl) {
        String p = (path == null) ? "" : (path.startsWith("/") ? path : ("/" + path));
        return (ssl ? "https" : "http") + "://" + host + ":" + port + p;
    }
    // ===================== Demo (main) =====================
    public static void main(String[] args) throws Exception {
zy-acs-manager/src/main/java/com/zy/acs/manager/core/HandlerController.java
@@ -9,6 +9,7 @@
import com.zy.acs.framework.common.R;
import com.zy.acs.framework.common.SnowflakeIdWorker;
import com.zy.acs.manager.common.annotation.OperationLog;
import com.zy.acs.manager.common.config.UplinkProperties;
import com.zy.acs.manager.common.domain.param.HandlerPublishParam;
import com.zy.acs.manager.common.exception.BusinessException;
import com.zy.acs.manager.core.service.*;
@@ -18,6 +19,7 @@
import com.zy.acs.manager.manager.enums.*;
import com.zy.acs.manager.manager.service.*;
import com.zy.acs.manager.system.controller.BaseController;
import com.zy.acs.manager.system.service.ConfigService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
@@ -64,7 +66,7 @@
    @Autowired
    private StaService staService;
    @Autowired
    private TrafficService trafficService;
    private UplinkProperties uplinkProperties;
    @Autowired
    private ThreadPoolRegulator threadPoolRegulator;
    @Autowired
@@ -77,6 +79,8 @@
    private StaReserveService staReserveService;
    @Autowired
    private AgvAreaDispatcher agvAreaDispatcher;
    @Autowired
    private ConfigService configService;
    @PreAuthorize("hasAuthority('manager:agv:update')")
    @OperationLog("Locate All Agv")
@@ -140,6 +144,7 @@
            return R.error();
        }
        Boolean maintainLocSts = configService.getVal("maintainLocSts", Boolean.class);
        Date now = new Date();
        Agv agv = agvService.selectByUuid(param.getAgvNo());
        AgvDetail agvDetail = agvDetailService.selectByAgvId(agv.getId());
@@ -164,13 +169,13 @@
        Task task = new Task();
        task.setAgvId(agv.getId());
        task.setUuid(String.valueOf(snowflakeIdWorker.nextId()).substring(3));
        List<Task> lastTasks = taskService.list(new LambdaQueryWrapper<Task>().orderByDesc(Task::getId));
//        List<Task> lastTasks = taskService.list(new LambdaQueryWrapper<Task>().orderByDesc(Task::getId));
//        task.setSeqNum(Utils.generateSeqNum(Cools.isEmpty(lastTasks)?null:lastTasks.get(0).getSeqNum()));
        task.setSeqNum(Base62.encode(snowflakeIdWorker.nextId()));
        task.setTaskType(param.getTaskMode().val());
        task.setTaskSts(TaskStsType.WAITING.val());
        task.setUplinkSts(uplinkProperties.getEnabled() ? TaskUplinkStateType.PENDING.toString() : TaskUplinkStateType.SKIPPED.toString());
        task.setPriority(999);
        task.setIoTime(now);
        task.setStartTime(now);
@@ -232,13 +237,15 @@
//                    throw new BusinessException("AGV " + agv.getUuid() + " failed to reach target code " + oriLoc.getCode$());
                    throw new BusinessException("AGV【" + agv.getUuid() + "】无法到达起始库位【" + oriLoc.getLocNo() + "】");
                }
                if (!oriLoc.getLocSts().equals(LocStsType.STOCK.val())) {
                    throw new BusinessException("oriLoc:" + oriLoc.getLocNo() + " ä¸æ˜¯åœ¨åº“状态");
                }
                oriLoc.setLocSts(LocStsType.PAKOUT.val());
                oriLoc.setUpdateTime(now);
                if (!locService.updateById(oriLoc)) {
                    throw new BusinessException("oriLoc:" + oriLoc.getLocNo() + " ä¿®æ”¹åº“位状态失败");
                if (maintainLocSts) {
                    if (!oriLoc.getLocSts().equals(LocStsType.STOCK.val())) {
                        throw new BusinessException("oriLoc:" + oriLoc.getLocNo() + " ä¸æ˜¯åœ¨åº“状态");
                    }
                    oriLoc.setLocSts(LocStsType.PAKOUT.val());
                    oriLoc.setUpdateTime(now);
                    if (!locService.updateById(oriLoc)) {
                        throw new BusinessException("oriLoc:" + oriLoc.getLocNo() + " ä¿®æ”¹åº“位状态失败");
                    }
                }
                // destLoc
@@ -255,13 +262,15 @@
//                    throw new BusinessException("AGV " + agv.getUuid() + " failed to reach target code " + destLoc.getCode$());
                    throw new BusinessException("AGV【" + agv.getUuid() + "】无法到达目标库位【" + destLoc.getLocNo() + "】");
                }
                if (!destLoc.getLocSts().equals(LocStsType.IDLE.val())) {
                    throw new BusinessException("destLoc:" + destLoc.getLocNo() + " ä¸æ˜¯ç©ºé—²çŠ¶æ€");
                }
                destLoc.setLocSts(LocStsType.PAKIN.val());
                destLoc.setUpdateTime(now);
                if (!locService.updateById(destLoc)) {
                    throw new BusinessException("destLoc:" + destLoc.getLocNo() + " ä¿®æ”¹åº“位状态失败");
                if (maintainLocSts) {
                    if (!destLoc.getLocSts().equals(LocStsType.IDLE.val())) {
                        throw new BusinessException("destLoc:" + destLoc.getLocNo() + " ä¸æ˜¯ç©ºé—²çŠ¶æ€");
                    }
                    destLoc.setLocSts(LocStsType.PAKIN.val());
                    destLoc.setUpdateTime(now);
                    if (!locService.updateById(destLoc)) {
                        throw new BusinessException("destLoc:" + destLoc.getLocNo() + " ä¿®æ”¹åº“位状态失败");
                    }
                }
                // task
@@ -285,13 +294,15 @@
//                    throw new BusinessException("AGV " + agv.getUuid() + " failed to reach target code " + oriLoc.getCode$());
                    throw new BusinessException("AGV【" + agv.getUuid() + "】无法到达起始库位【" + oriLoc.getLocNo() + "】");
                }
                if (!oriLoc.getLocSts().equals(LocStsType.STOCK.val())) {
                    throw new BusinessException("oriLoc:" + oriLoc.getLocNo() + " ä¸æ˜¯åœ¨åº“状态");
                }
                oriLoc.setLocSts(LocStsType.PAKOUT.val());
                oriLoc.setUpdateTime(now);
                if (!locService.updateById(oriLoc)) {
                    throw new BusinessException("oriLoc:" + oriLoc.getLocNo() + " ä¿®æ”¹åº“位状态失败");
                if (maintainLocSts) {
                    if (!oriLoc.getLocSts().equals(LocStsType.STOCK.val())) {
                        throw new BusinessException("oriLoc:" + oriLoc.getLocNo() + " ä¸æ˜¯åœ¨åº“状态");
                    }
                    oriLoc.setLocSts(LocStsType.PAKOUT.val());
                    oriLoc.setUpdateTime(now);
                    if (!locService.updateById(oriLoc)) {
                        throw new BusinessException("oriLoc:" + oriLoc.getLocNo() + " ä¿®æ”¹åº“位状态失败");
                    }
                }
                // destSta
@@ -352,13 +363,15 @@
//                    throw new BusinessException("AGV " + agv.getUuid() + " failed to reach target code " + destLoc.getCode$());
                    throw new BusinessException("AGV【" + agv.getUuid() + "】无法到达目标库位【" + destLoc.getLocNo() + "】");
                }
                if (!destLoc.getLocSts().equals(LocStsType.IDLE.val())) {
                    throw new BusinessException("destLoc:" + destLoc.getLocNo() + " ä¸æ˜¯ç©ºé—²çŠ¶æ€");
                }
                destLoc.setLocSts(LocStsType.PAKIN.val());
                destLoc.setUpdateTime(now);
                if (!locService.updateById(destLoc)) {
                    throw new BusinessException("destLoc:" + destLoc.getLocNo() + " ä¿®æ”¹åº“位状态失败");
                if (maintainLocSts) {
                    if (!destLoc.getLocSts().equals(LocStsType.IDLE.val())) {
                        throw new BusinessException("destLoc:" + destLoc.getLocNo() + " ä¸æ˜¯ç©ºé—²çŠ¶æ€");
                    }
                    destLoc.setLocSts(LocStsType.PAKIN.val());
                    destLoc.setUpdateTime(now);
                    if (!locService.updateById(destLoc)) {
                        throw new BusinessException("destLoc:" + destLoc.getLocNo() + " ä¿®æ”¹åº“位状态失败");
                    }
                }
                // task
zy-acs-manager/src/main/java/com/zy/acs/manager/core/domain/type/NamespaceType.java
New file
@@ -0,0 +1,15 @@
package com.zy.acs.manager.core.domain.type;
public enum NamespaceType {
    RCS_TASK_REPORT("任务完成上报"),
    ;
    public String name;
    NamespaceType(String name) {
        this.name = name;
    }
}
zy-acs-manager/src/main/java/com/zy/acs/manager/core/integrate/conveyor/ConveyorController.java
@@ -9,7 +9,6 @@
import com.zy.acs.manager.manager.entity.Task;
import com.zy.acs.manager.manager.enums.StatusType;
import com.zy.acs.manager.manager.service.StaService;
import com.zy.acs.manager.system.controller.BaseController;
import io.swagger.annotations.Api;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
@@ -23,7 +22,7 @@
@Api(tags = "Open Api")
@RestController
@RequestMapping("/api/open")
public class ConveyorController extends BaseController {
public class ConveyorController {
    @Autowired
    private StaService staService;
zy-acs-manager/src/main/java/com/zy/acs/manager/core/integrate/conveyor/SiemensConveyorStationService.java
@@ -3,24 +3,28 @@
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.zy.acs.framework.common.Cools;
import com.zy.acs.framework.common.SnowflakeIdWorker;
import com.zy.acs.manager.common.config.ConveyorProperties;
import com.zy.acs.manager.common.constant.Constants;
import com.zy.acs.manager.common.utils.HttpGo;
import com.zy.acs.manager.core.domain.type.NamespaceType;
import com.zy.acs.manager.core.integrate.dto.ConveyorStaDto;
import com.zy.acs.manager.core.integrate.dto.HttpResult;
import com.zy.acs.manager.manager.entity.IntegrationRecord;
import com.zy.acs.manager.manager.entity.Segment;
import com.zy.acs.manager.manager.entity.Sta;
import com.zy.acs.manager.manager.entity.Task;
import com.zy.acs.manager.manager.enums.IntegrationDirectionType;
import com.zy.acs.manager.manager.enums.StaReserveType;
import com.zy.acs.manager.manager.enums.StatusType;
import com.zy.acs.manager.manager.service.IntegrationRecordService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.time.Duration;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
@Slf4j
@Service
@@ -28,25 +32,32 @@
    @Autowired
    private ConveyorProperties conveyorProperties;
    @Autowired
    private SnowflakeIdWorker snowflakeIdWorker;
    @Autowired
    private IntegrationRecordService integrationRecordService;
    private HttpGo http;
    @PostConstruct
    public void init() {
        int timeoutSeconds = conveyorProperties.getTimeout() / 1000;
        this.http = HttpGo.builder()
                .connectTimeout(Duration.ofSeconds(8))
                .readTimeout(Duration.ofSeconds(15))
                .connectTimeout(Duration.ofSeconds(timeoutSeconds))
                .readTimeout(Duration.ofSeconds(timeoutSeconds))
//                .defaultHeader("User-Agent", "HttpGo/1.0")
                // .trustAllSsl(true) // ONLY if you really need it (self-signed internal)
//                .trustAllSsl(true) // ONLY if you really need it (self-signed internal)
                .build();
    }
    @Override
    public boolean allowAgvWork(Sta sta, Task task, Segment seg, StaReserveType type) {
        final String staNo = sta.getStaNo();
        Date now = new Date();
        // url
        String url = this.buildUrl("/cv/station/query");
        String url = this.http.buildUrl(conveyorProperties.getHost(), conveyorProperties.getPort(), conveyorProperties.getUrl());
        // headers
        Map<String, String> headers = new HashMap<>();
        // params
@@ -54,10 +65,33 @@
        List<String> list = new ArrayList<>();
        list.add(staNo);
        params.put("staNos", list);
        IntegrationRecord integrationRecord = new IntegrationRecord(
                String.valueOf(snowflakeIdWorker.nextId()).substring(3),    // ç¼–号
                NamespaceType.RCS_TASK_REPORT.name,    // åç§°ç©ºé—´
                conveyorProperties.getUrl(),    // æŽ¥å£åœ°å€
                null,    // å¹³å°å¯†é’¥
                Constants.RCS,    // è°ƒç”¨æ–¹æ ‡è¯†
                IntegrationDirectionType.OUTBOUND.value,    // æ–¹å‘[非空]
                String.valueOf(now.getTime()),    // æ—¶é—´æˆ³
                conveyorProperties.getHost(),    // å®¢æˆ·ç«¯IP
                JSON.toJSONString(params),    // è¯·æ±‚内容
                null,    // å“åº”内容
                null,    // å¼‚常内容
                0,    // ç»“æžœ
                null,    // è€—æ—¶
                StatusType.ENABLE.val,    // çŠ¶æ€
                now,    // æ·»åŠ æ—¶é—´[非空]
                now,    // ä¿®æ”¹æ—¶é—´[非空]
                null    // å¤‡æ³¨
        );
        // do request
        HttpResult<List<ConveyorStaDto>> result;
        try {
            result = postForResult(url, headers, params);
            integrationRecord.setResponse(JSON.toJSONString(result));
            Integer code = result.getCode();
            if (null == code || 200 != code) {
                return false;
@@ -94,28 +128,25 @@
                    return false;
                }
            }
            integrationRecord.setResult(1);
        } catch (Exception e) {
            log.error("Conveyor query failed, FAIL-OPEN. staNo={}, taskId={}, type={}",
                    sta.getStaNo(),
                    task.getSeqNum(),
                    type,
                    e);
            integrationRecord.setErr(e.getMessage());
            return false;
        } finally {
            integrationRecord.setCostMs((int) (System.currentTimeMillis() - now.getTime()));
            integrationRecordService.syncRecord(integrationRecord);
        }
        // ok
        return true;
    }
    private String buildUrl(String path) {
        String host = conveyorProperties.getHost();
        Integer port = conveyorProperties.getPort();
        String p = (path == null) ? "" : (path.startsWith("/") ? path : ("/" + path));
        return "http://" + host + ":" + port + p;
    }
    private HttpResult<List<ConveyorStaDto>> postForResult(String url
            , Map<String, String> headers, Map<String, Object> params) throws Exception {
    private HttpResult<List<ConveyorStaDto>> postForResult(String url, Map<String, String> headers, Map<String, Object> params) throws Exception {
        String json = JSON.toJSONString(params);
        HttpGo.HttpResponse response = this.http.postJson(url, headers, json);
zy-acs-manager/src/main/java/com/zy/acs/manager/core/integrate/dto/OpenBusCancelParam.java
New file
@@ -0,0 +1,18 @@
package com.zy.acs.manager.core.integrate.dto;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
/**
 * Created by vincent on 2023/6/12
 */
@Data
public class OpenBusCancelParam {
    private String batchNo;
    private List<String> tasks = new ArrayList<>();
}
zy-acs-manager/src/main/java/com/zy/acs/manager/core/integrate/dto/OpenBusCancelResult.java
New file
@@ -0,0 +1,19 @@
package com.zy.acs.manager.core.integrate.dto;
import com.zy.acs.manager.common.domain.TaskBoolDto;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
/**
 * Created by vincent on 2023/6/12
 */
@Data
public class OpenBusCancelResult {
    private String batchNo;
    private List<TaskBoolDto> tasks = new ArrayList<>();
}
zy-acs-manager/src/main/java/com/zy/acs/manager/core/integrate/dto/OpenBusSubmitParam.java
File was renamed from zy-acs-manager/src/main/java/com/zy/acs/manager/manager/controller/param/OpenBusSubmitParam.java
@@ -1,4 +1,4 @@
package com.zy.acs.manager.manager.controller.param;
package com.zy.acs.manager.core.integrate.dto;
import com.zy.acs.manager.common.domain.TaskDto;
import lombok.Data;
@@ -12,8 +12,8 @@
@Data
public class OpenBusSubmitParam {
    private String batch;
    private String batchNo;
    private List<TaskDto> taskList = new ArrayList<>();
    private List<TaskDto> tasks = new ArrayList<>();
}
zy-acs-manager/src/main/java/com/zy/acs/manager/core/integrate/dto/TaskUplinkParam.java
New file
@@ -0,0 +1,14 @@
package com.zy.acs.manager.core.integrate.dto;
import lombok.Data;
@Data
public class TaskUplinkParam {
    private String batchNo;
    private String taskNo;
    private Long timestamp;
}
zy-acs-manager/src/main/java/com/zy/acs/manager/core/integrate/wms/OpenController.java
@@ -1,35 +1,108 @@
package com.zy.acs.manager.core.integrate.wms;
import com.zy.acs.manager.common.annotation.OperationLog;
import com.zy.acs.framework.common.Cools;
import com.zy.acs.framework.common.R;
import com.zy.acs.manager.system.controller.BaseController;
import com.zy.acs.manager.common.annotation.OperationLog;
import com.zy.acs.manager.common.constant.Constants;
import com.zy.acs.manager.common.domain.TaskBoolDto;
import com.zy.acs.manager.core.integrate.dto.OpenBusCancelParam;
import com.zy.acs.manager.core.integrate.dto.OpenBusCancelResult;
import com.zy.acs.manager.core.integrate.dto.OpenBusSubmitParam;
import com.zy.acs.manager.core.service.MainService;
import com.zy.acs.manager.manager.controller.param.OpenBusSubmitParam;
import com.zy.acs.manager.manager.entity.Bus;
import com.zy.acs.manager.manager.entity.IntegrationRecord;
import com.zy.acs.manager.manager.entity.Task;
import com.zy.acs.manager.manager.enums.TaskStsType;
import com.zy.acs.manager.manager.service.BusService;
import com.zy.acs.manager.manager.service.TaskService;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
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;
/**
 * Created by vincent on 2023/6/12
 */
@Slf4j
@Api(tags = "Open Api")
@RestController
@RequestMapping("/api/open")
public class OpenController extends BaseController {
public class OpenController {
    @Autowired
    private MainService mainService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private BusService busService;
//    @PreAuthorize("hasAuthority('open:bus:submit')")
    @PostMapping("/bus/submit")
    @OperationLog("generate task from open api")
    public R save(@RequestBody OpenBusSubmitParam param) {
    public R submit(@RequestBody OpenBusSubmitParam param, HttpServletRequest request) {
        IntegrationRecord integrationRecord = new IntegrationRecord(
                null,    // ç¼–号
                null,    // åç§°ç©ºé—´
                null,    // æŽ¥å£åœ°å€
                null,    // å¹³å°å¯†é’¥
                null,    // è°ƒç”¨æ–¹æ ‡è¯†
                null,    // æ–¹å‘[非空]
                null,    // æ—¶é—´æˆ³
                null,    // å®¢æˆ·ç«¯IP
                null,    // è¯·æ±‚内容
                null,    // å“åº”内容
                null,    // å¼‚常内容
                null,    // ç»“æžœ
                null,    // è€—æ—¶
                null,    // çŠ¶æ€
                null,    // æ·»åŠ æ—¶é—´[非空]
                null,    // ä¿®æ”¹æ—¶é—´[非空]
                null    // å¤‡æ³¨
        );
        request.setAttribute("integrationRecord", integrationRecord);
        mainService.generateBusAndTask(param, null);
        return R.ok("generate tasks success");
    }
    @PostMapping("/task/cancel")
    @OperationLog("cancel task from open api")
    public R cancel(@RequestBody OpenBusCancelParam param) {
        if (Cools.isEmpty(param.getBatchNo())) {
            return R.error("batchNo is empty");
        }
        if (Cools.isEmpty(param.getTasks())) {
            return R.error("tasks is empty");
        }
        Bus bus = busService.selectByBusNo(param.getBatchNo());
        if (null == bus) {
            return R.error("batchNo is not exist");
        }
        OpenBusCancelResult result = new OpenBusCancelResult();
        result.setBatchNo(param.getBatchNo());
        for (String taskNo : param.getTasks()) {
            Task task = taskService.selectBySeqNum(bus.getId(), taskNo);
            if (null == task) {
                result.getTasks().add(new TaskBoolDto(taskNo, Boolean.FALSE, "task " + taskNo + " is not exist"));
                continue;
            }
            if (!task.getTaskSts().equals(TaskStsType.INIT.val())) {
                result.getTasks().add(new TaskBoolDto(taskNo, Boolean.FALSE,  "task " + taskNo + " has already been assigned"));
                continue;
            }
            Boolean cancel = false;
            try {
                cancel = taskService.cancel(task.getId(), null, Constants.UPLINK);
            } catch (Exception e) {
                log.error("failed to cancel task {}", taskNo, e);
            }
            result.getTasks().add(new TaskBoolDto(taskNo, cancel, "failed to cancel task " + taskNo));
        }
        return R.ok("cancel tasks success").add(result);
    }
}
zy-acs-manager/src/main/java/com/zy/acs/manager/core/integrate/wms/TaskReportService.java
New file
@@ -0,0 +1,180 @@
package com.zy.acs.manager.core.integrate.wms;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.zy.acs.framework.common.Cools;
import com.zy.acs.framework.common.R;
import com.zy.acs.framework.common.SnowflakeIdWorker;
import com.zy.acs.manager.common.config.UplinkProperties;
import com.zy.acs.manager.common.constant.Constants;
import com.zy.acs.manager.common.utils.HttpGo;
import com.zy.acs.manager.core.domain.type.NamespaceType;
import com.zy.acs.manager.core.integrate.dto.HttpResult;
import com.zy.acs.manager.core.integrate.dto.TaskUplinkParam;
import com.zy.acs.manager.core.service.ThreadPoolRegulator;
import com.zy.acs.manager.manager.entity.Bus;
import com.zy.acs.manager.manager.entity.IntegrationRecord;
import com.zy.acs.manager.manager.entity.Task;
import com.zy.acs.manager.manager.enums.IntegrationDirectionType;
import com.zy.acs.manager.manager.enums.StatusType;
import com.zy.acs.manager.manager.enums.TaskStsType;
import com.zy.acs.manager.manager.enums.TaskUplinkStateType;
import com.zy.acs.manager.manager.service.BusService;
import com.zy.acs.manager.manager.service.IntegrationRecordService;
import com.zy.acs.manager.manager.service.TaskService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.time.Duration;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
@Slf4j
@Service
public class TaskReportService {
    @Autowired
    private UplinkProperties uplinkProperties;
    @Autowired
    private TaskService taskService;
    @Autowired
    private ThreadPoolRegulator threadPoolRegulator;
    @Autowired
    private BusService busService;
    @Autowired
    private SnowflakeIdWorker snowflakeIdWorker;
    @Autowired
    private IntegrationRecordService integrationRecordService;
    private HttpGo http;
    @PostConstruct
    public void init() {
        int timeoutSeconds = uplinkProperties.getTimeout() / 1000;
        this.http = HttpGo.builder()
                .connectTimeout(Duration.ofSeconds(timeoutSeconds))
                .readTimeout(Duration.ofSeconds(timeoutSeconds))
//                .defaultHeader("User-Agent", "HttpGo/1.0")
//                .trustAllSsl(true) // ONLY if you really need it (self-signed internal)
                .build();
    }
    public boolean reportFinished(Task task) {
        if (Cools.isEmpty(task)) {
            return false;
        }
        if (!uplinkProperties.getEnabled()) {
            return false;
        }
        if (!task.getTaskSts().equals(TaskStsType.COMPLETE.val())) {
            return false;
        }
        TaskUplinkStateType uplinkStateType = TaskUplinkStateType.of(task.getUplinkSts());
        if (!uplinkStateType.equals(TaskUplinkStateType.PENDING)
                && !uplinkStateType.equals(TaskUplinkStateType.SENDING)
                && !uplinkStateType.equals(TaskUplinkStateType.FAILED)
        ) {
            return false;
        }
        Date now = new Date();
        // block
//        Future<R> future = threadPoolRegulator.getInstance().submit(() -> {
//            mapDataDispatcher.modifyDynamicMatrix(null, null, param.getAgvNo(), true);
//            return success();
//        });
//        System.out.println(JSON.toJSONString(future.get()));
        // non-block
        CompletableFuture<?> completableFuture = CompletableFuture.supplyAsync(() -> {
//            mapDataDispatcher.modifyDynamicMatrix(null, null, param.getAgvNo(), true);
//            avoidWaveCalculator.calcDynamicNodeByVehicle(agv, null);
            return R.ok();
        }, threadPoolRegulator.getInstance());
        // url
        String url = this.http.buildUrl(uplinkProperties.getHost(), uplinkProperties.getPort(), uplinkProperties.getUrl());
        // headers
        Map<String, String> headers = new HashMap<>();
        // params
        TaskUplinkParam param = new TaskUplinkParam();
        if (null != task.getBusId()) {
            Bus bus = busService.getById(task.getBusId());
            param.setBatchNo(bus.getBusNo());
        }
        param.setTaskNo(task.getSeqNum());
        param.setTimestamp(null == task.getEndTime() ? System.currentTimeMillis() : task.getEndTime().getTime());
        IntegrationRecord integrationRecord = new IntegrationRecord(
                String.valueOf(snowflakeIdWorker.nextId()).substring(3),    // ç¼–号
                NamespaceType.RCS_TASK_REPORT.name,    // åç§°ç©ºé—´
                uplinkProperties.getUrl(),    // æŽ¥å£åœ°å€
                null,    // å¹³å°å¯†é’¥
                Constants.RCS,    // è°ƒç”¨æ–¹æ ‡è¯†
                IntegrationDirectionType.OUTBOUND.value,    // æ–¹å‘[非空]
                String.valueOf(now.getTime()),    // æ—¶é—´æˆ³
                uplinkProperties.getHost(),    // å®¢æˆ·ç«¯IP
                JSON.toJSONString(param),    // è¯·æ±‚内容
                null,    // å“åº”内容
                null,    // å¼‚常内容
                0,    // ç»“æžœ
                null,    // è€—æ—¶
                StatusType.ENABLE.val,    // çŠ¶æ€
                now,    // æ·»åŠ æ—¶é—´[非空]
                now,    // ä¿®æ”¹æ—¶é—´[非空]
                null    // å¤‡æ³¨
        );
        HttpResult<?> result;
        try {
            result = postForResult(url, headers, param);
            integrationRecord.setResponse(JSON.toJSONString(result));
            Integer code = result.getCode();
            if (null == code || 200 != code) {
                return false;
            }
//            Object data = result.getData();
//            if (Cools.isEmpty(data)) {
//                return false;
//            }
            integrationRecord.setResult(1);
        } catch (Exception e) {
            log.error("Uplink report failed, taskId={}",
                    JSON.toJSONString(task),
                    e);
            integrationRecord.setErr(e.getMessage());
            return false;
        } finally {
            integrationRecord.setCostMs((int) (System.currentTimeMillis() - now.getTime()));
            integrationRecordService.syncRecord(integrationRecord);
        }
        return true;
    }
    private HttpResult<?> postForResult(String url, Map<String, String> headers, TaskUplinkParam param) throws Exception {
        String json = JSON.toJSONString(param);
        HttpGo.HttpResponse response = this.http.postJson(url, headers, json);
        int status = response.statusCode();
        if (status != 200) {
            throw new RuntimeException("Uplink HTTP error: status=" + status + ", body=" + response.body());
        }
        String body = response.body();
        if (Cools.isEmpty(body)) {
            throw new RuntimeException("Uplink empty response body.");
        }
        HttpResult<?> result = JSON.parseObject(body, new TypeReference<HttpResult<?>>() {});
        if (result == null) {
            throw new RuntimeException("Uplink parse HttpResult failed: body=" + body);
        }
        return result;
    }
}
zy-acs-manager/src/main/java/com/zy/acs/manager/core/scheduler/AutoTestDeviationScheduler.java
File was deleted
zy-acs-manager/src/main/java/com/zy/acs/manager/core/scheduler/MaintainScheduler.java
@@ -3,9 +3,11 @@
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zy.acs.common.enums.AgvStatusType;
import com.zy.acs.common.utils.RedisSupport;
import com.zy.acs.framework.common.Cools;
import com.zy.acs.framework.common.DateUtils;
import com.zy.acs.manager.common.config.UplinkProperties;
import com.zy.acs.manager.core.integrate.wms.TaskReportService;
import com.zy.acs.manager.core.service.MainLockWrapService;
import com.zy.acs.manager.core.service.MainService;
import com.zy.acs.manager.manager.entity.*;
import com.zy.acs.manager.manager.enums.*;
import com.zy.acs.manager.manager.service.*;
@@ -36,7 +38,7 @@
    @Autowired
    private FuncStaService funcStaService;
    @Autowired
    private MainService mainService;
    private UplinkProperties uplinkProperties;
    @Autowired
    private MainLockWrapService mainLockWrapService;
    @Autowired
@@ -47,6 +49,8 @@
    private AgvModelService agvModelService;
    @Autowired
    private SegmentService segmentService;
    @Autowired
    private TaskReportService taskReportService;
    @Scheduled(cron = "0/5 * * * * ? ")
    private synchronized void autoCharge(){
@@ -148,8 +152,30 @@
        }
    }
    @Scheduled(cron = "0/3 * * * * ? ")
    private void reportTaskToUplink() {
        if (!uplinkProperties.getEnabled()) { return; }
        List<Task> taskList = taskService.list(new LambdaQueryWrapper<Task>()
                .in(Task::getUplinkSts, TaskUplinkStateType.PENDING.toString(), TaskUplinkStateType.FAILED.toString())
                .eq(Task::getTaskSts, TaskStsType.COMPLETE.val())
                .isNotNull(Task::getBusId)
        );
        if (Cools.isEmpty(taskList)) { return; }
        for (Task task : taskList) {
            boolean finished = taskReportService.reportFinished(task);
            if (finished) {
                task.setUplinkSts(TaskUplinkStateType.SUCCESS.toString());
            } else {
                log.error("failed to report task to uplink: {}", task.getSeqNum());
                task.setUplinkSts(TaskUplinkStateType.FAILED.toString());
            }
            taskService.updateById(task);
        }
    }
    @Scheduled(cron = "0/5 * * * * ? ")
    private synchronized void releaseFuncSta(){
    private synchronized void releaseFuncSta() {
        List<FuncSta> funcStaList = funcStaService.list(new LambdaQueryWrapper<FuncSta>().eq(FuncSta::getState, FuncStaStateType.OCCUPIED.toString()));
        for (FuncSta funcSta : funcStaList) {
            boolean beIdle = funcStaService.isCanBeIdle(funcSta);
zy-acs-manager/src/main/java/com/zy/acs/manager/core/scheduler/test/AutoRunRebootScheduler.java
File was renamed from zy-acs-manager/src/main/java/com/zy/acs/manager/core/scheduler/AutoRunRebootScheduler.java
@@ -1,4 +1,4 @@
package com.zy.acs.manager.core.scheduler;
package com.zy.acs.manager.core.scheduler.test;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zy.acs.common.constant.RedisConstant;
@@ -6,10 +6,10 @@
import com.zy.acs.framework.common.Cools;
import com.zy.acs.framework.common.SnowflakeIdWorker;
import com.zy.acs.manager.common.domain.TaskDto;
import com.zy.acs.manager.core.integrate.dto.OpenBusSubmitParam;
import com.zy.acs.manager.core.service.AreaGovernService;
import com.zy.acs.manager.core.service.MainLockWrapService;
import com.zy.acs.manager.core.service.MainService;
import com.zy.acs.manager.manager.controller.param.OpenBusSubmitParam;
import com.zy.acs.manager.manager.entity.*;
import com.zy.acs.manager.manager.enums.*;
import com.zy.acs.manager.manager.service.*;
@@ -18,12 +18,11 @@
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.*;
@Slf4j
@Component
//@Component
public class AutoRunRebootScheduler {
    private static final AgvModelType DEFAULT_AGV_MODEL = AgvModelType.HEAVY_LOAD_STACKING_ROBOT;
@@ -62,6 +61,12 @@
//    @Scheduled(cron = "0/1 * * * * ? ")
    private void execute() {
        if (!configService.getVal("TaskAssignRebootMode", Boolean.class)) { return; }
        Boolean maintainLocSts = configService.getVal("maintainLocSts", Boolean.class);
        if (!maintainLocSts) {
            log.error("failed to run auto agv task, the maintainLocSts is false");
            return;
        }
        AgvModel agvModel = agvModelService.getOne(new LambdaQueryWrapper<AgvModel>().eq(AgvModel::getType, DEFAULT_AGV_MODEL.toString()));
        if (null == agvModel) { return; }
@@ -118,7 +123,7 @@
        Collections.shuffle(stockList);
        OpenBusSubmitParam param = new OpenBusSubmitParam();
        param.setBatch(String.valueOf(snowflakeIdWorker.nextId()).substring(13, 19));
        param.setBatchNo(String.valueOf(snowflakeIdWorker.nextId()).substring(13, 19));
        for (int i = 0; i < Math.min(agvModel.getBackpack(), stockList.size()) ; i++) {
            Sta stockSta = stockList.get(i);
            String staCode = codeService.getCacheById(stockSta.getCode()).getData();
@@ -156,11 +161,11 @@
            taskDto.setOriSta(stockSta.getStaNo());
            taskDto.setDestLoc(idleLoc.getLocNo());
            taskDto.setPriority(100);
            taskDto.setSeqNum(String.valueOf(snowflakeIdWorker.nextId()).substring(15, 19));
            taskDto.setTaskNo(String.valueOf(snowflakeIdWorker.nextId()).substring(15, 19));
            param.getTaskList().add(taskDto);
            param.getTasks().add(taskDto);
        }
        if (Cools.isEmpty(param.getTaskList())) { return; }
        if (Cools.isEmpty(param.getTasks())) { return; }
        mainService.generateBusAndTask(param, memo);
    }
@@ -174,7 +179,7 @@
        Collections.shuffle(idleList);
        OpenBusSubmitParam param = new OpenBusSubmitParam();
        param.setBatch(String.valueOf(snowflakeIdWorker.nextId()).substring(13, 19));
        param.setBatchNo(String.valueOf(snowflakeIdWorker.nextId()).substring(13, 19));
        for (int i = 0; i < Math.min(agvModel.getBackpack(), idleList.size()) ; i++) {
            Sta idleSta = idleList.get(i);
            String staCode = codeService.getCacheById(idleSta.getCode()).getData();
@@ -212,11 +217,11 @@
            taskDto.setOriLoc(stockLoc.getLocNo());
            taskDto.setDestSta(idleSta.getStaNo());
            taskDto.setPriority(100);
            taskDto.setSeqNum(String.valueOf(snowflakeIdWorker.nextId()).substring(15, 19));
            taskDto.setTaskNo(String.valueOf(snowflakeIdWorker.nextId()).substring(15, 19));
            param.getTaskList().add(taskDto);
            param.getTasks().add(taskDto);
        }
        if (Cools.isEmpty(param.getTaskList())) { return; }
        if (Cools.isEmpty(param.getTasks())) { return; }
        mainService.generateBusAndTask(param, memo);
    }
@@ -250,7 +255,7 @@
        Collections.shuffle(idleLocList);
        OpenBusSubmitParam param = new OpenBusSubmitParam();
        param.setBatch(String.valueOf(snowflakeIdWorker.nextId()).substring(13, 19));
        param.setBatchNo(String.valueOf(snowflakeIdWorker.nextId()).substring(13, 19));
        for (int i = 0; i < Math.min(maxCapacity, Math.min(stockLocList.size(), idleLocList.size())); i++) {
            Loc stockLoc = stockLocList.get(i);
            Loc idleLoc = idleLocList.get(i);
@@ -258,11 +263,11 @@
            TaskDto taskDto = new TaskDto();
            taskDto.setOriLoc(stockLoc.getLocNo());
            taskDto.setDestLoc(idleLoc.getLocNo());
            taskDto.setSeqNum(String.valueOf(snowflakeIdWorker.nextId()).substring(15, 19));
            taskDto.setTaskNo(String.valueOf(snowflakeIdWorker.nextId()).substring(15, 19));
            param.getTaskList().add(taskDto);
            param.getTasks().add(taskDto);
        }
        if (Cools.isEmpty(param.getTaskList())) { return; }
        if (Cools.isEmpty(param.getTasks())) { return; }
        mainService.generateBusAndTask(param, memo);
    }
zy-acs-manager/src/main/java/com/zy/acs/manager/core/scheduler/test/AutoRunScheduler.java
File was renamed from zy-acs-manager/src/main/java/com/zy/acs/manager/core/scheduler/AutoRunScheduler.java
@@ -1,4 +1,4 @@
package com.zy.acs.manager.core.scheduler;
package com.zy.acs.manager.core.scheduler.test;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zy.acs.common.constant.RedisConstant;
@@ -7,7 +7,7 @@
import com.zy.acs.framework.common.SnowflakeIdWorker;
import com.zy.acs.manager.common.domain.TaskDto;
import com.zy.acs.manager.core.service.*;
import com.zy.acs.manager.manager.controller.param.OpenBusSubmitParam;
import com.zy.acs.manager.core.integrate.dto.OpenBusSubmitParam;
import com.zy.acs.manager.manager.entity.*;
import com.zy.acs.manager.manager.enums.*;
import com.zy.acs.manager.manager.service.*;
@@ -54,6 +54,11 @@
//    @Scheduled(cron = "0/1 * * * * ? ")
    private void execute() {
        if (!configService.getVal("TaskAssignMode", Boolean.class)) { return; }
        Boolean maintainLocSts = configService.getVal("maintainLocSts", Boolean.class);
        if (!maintainLocSts) {
            log.error("failed to run auto agv task, the maintainLocSts is false");
            return;
        }
        AgvModel agvModel = agvModelService.getOne(new LambdaQueryWrapper<AgvModel>().eq(AgvModel::getType, DEFAULT_AGV_MODEL.toString()));
        if (null == agvModel) { return; }
@@ -86,7 +91,7 @@
        Collections.shuffle(stockList);
        OpenBusSubmitParam param = new OpenBusSubmitParam();
        param.setBatch(String.valueOf(snowflakeIdWorker.nextId()).substring(13, 19));
        param.setBatchNo(String.valueOf(snowflakeIdWorker.nextId()).substring(13, 19));
        for (int i = 0; i < Math.min(agvModel.getBackpack(), stockList.size()) ; i++) {
            Sta stockSta = stockList.get(i);
            String staCode = codeService.getCacheById(stockSta.getCode()).getData();
@@ -124,11 +129,11 @@
            taskDto.setOriSta(stockSta.getStaNo());
            taskDto.setDestLoc(idleLoc.getLocNo());
            taskDto.setPriority(100);
            taskDto.setSeqNum(String.valueOf(snowflakeIdWorker.nextId()).substring(15, 19));
            taskDto.setTaskNo(String.valueOf(snowflakeIdWorker.nextId()).substring(15, 19));
            param.getTaskList().add(taskDto);
            param.getTasks().add(taskDto);
        }
        if (Cools.isEmpty(param.getTaskList())) { return; }
        if (Cools.isEmpty(param.getTasks())) { return; }
        mainService.generateBusAndTask(param, memo);
    }
@@ -142,7 +147,7 @@
        Collections.shuffle(idleList);
        OpenBusSubmitParam param = new OpenBusSubmitParam();
        param.setBatch(String.valueOf(snowflakeIdWorker.nextId()).substring(13, 19));
        param.setBatchNo(String.valueOf(snowflakeIdWorker.nextId()).substring(13, 19));
        for (int i = 0; i < Math.min(agvModel.getBackpack(), idleList.size()) ; i++) {
            Sta idleSta = idleList.get(i);
            String staCode = codeService.getCacheById(idleSta.getCode()).getData();
@@ -180,11 +185,11 @@
            taskDto.setOriLoc(stockLoc.getLocNo());
            taskDto.setDestSta(idleSta.getStaNo());
            taskDto.setPriority(100);
            taskDto.setSeqNum(String.valueOf(snowflakeIdWorker.nextId()).substring(15, 19));
            taskDto.setTaskNo(String.valueOf(snowflakeIdWorker.nextId()).substring(15, 19));
            param.getTaskList().add(taskDto);
            param.getTasks().add(taskDto);
        }
        if (Cools.isEmpty(param.getTaskList())) { return; }
        if (Cools.isEmpty(param.getTasks())) { return; }
        mainService.generateBusAndTask(param, memo);
    }
@@ -218,7 +223,7 @@
        Collections.shuffle(idleLocList);
        OpenBusSubmitParam param = new OpenBusSubmitParam();
        param.setBatch(String.valueOf(snowflakeIdWorker.nextId()).substring(13, 19));
        param.setBatchNo(String.valueOf(snowflakeIdWorker.nextId()).substring(13, 19));
        for (int i = 0; i < Math.min(maxCapacity, Math.min(stockLocList.size(), idleLocList.size())); i++) {
            Loc stockLoc = stockLocList.get(i);
            Loc idleLoc = idleLocList.get(i);
@@ -226,11 +231,11 @@
            TaskDto taskDto = new TaskDto();
            taskDto.setOriLoc(stockLoc.getLocNo());
            taskDto.setDestLoc(idleLoc.getLocNo());
            taskDto.setSeqNum(String.valueOf(snowflakeIdWorker.nextId()).substring(15, 19));
            taskDto.setTaskNo(String.valueOf(snowflakeIdWorker.nextId()).substring(15, 19));
            param.getTaskList().add(taskDto);
            param.getTasks().add(taskDto);
        }
        if (Cools.isEmpty(param.getTaskList())) { return; }
        if (Cools.isEmpty(param.getTasks())) { return; }
        mainService.generateBusAndTask(param, memo);
    }
zy-acs-manager/src/main/java/com/zy/acs/manager/core/scheduler/test/ConveyorAutoRunScheduler.java
File was renamed from zy-acs-manager/src/main/java/com/zy/acs/manager/core/scheduler/ConveyorAutoRunScheduler.java
@@ -1,4 +1,4 @@
package com.zy.acs.manager.core.scheduler;
package com.zy.acs.manager.core.scheduler.test;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zy.acs.common.constant.RedisConstant;
@@ -8,7 +8,7 @@
import com.zy.acs.manager.common.domain.TaskDto;
import com.zy.acs.manager.core.service.AreaGovernService;
import com.zy.acs.manager.core.service.MainService;
import com.zy.acs.manager.manager.controller.param.OpenBusSubmitParam;
import com.zy.acs.manager.core.integrate.dto.OpenBusSubmitParam;
import com.zy.acs.manager.manager.entity.*;
import com.zy.acs.manager.manager.enums.AgvModelType;
import com.zy.acs.manager.manager.enums.BusStsType;
@@ -25,7 +25,7 @@
import java.util.*;
@Slf4j
@Component
//@Component
public class ConveyorAutoRunScheduler {
    private static final AgvModelType DEFAULT_AGV_MODEL = AgvModelType.CTU_BOX_TRANSPORT_AGV;
@@ -97,7 +97,7 @@
        Collections.shuffle(idleList);
        OpenBusSubmitParam param = new OpenBusSubmitParam();
        param.setBatch(String.valueOf(snowflakeIdWorker.nextId()).substring(13, 19));
        param.setBatchNo(String.valueOf(snowflakeIdWorker.nextId()).substring(13, 19));
        for (int i = 0; i < agvModel.getBackpack() ; i++) {
            Sta idleSta = idleList.get(i);
            String staCode = codeService.getCacheById(idleSta.getCode()).getData();
@@ -135,11 +135,11 @@
            taskDto.setOriLoc(stockLoc.getLocNo());
            taskDto.setDestSta(idleSta.getStaNo());
            taskDto.setPriority(100);
            taskDto.setSeqNum(String.valueOf(snowflakeIdWorker.nextId()).substring(15, 19));
            taskDto.setTaskNo(String.valueOf(snowflakeIdWorker.nextId()).substring(15, 19));
            param.getTaskList().add(taskDto);
            param.getTasks().add(taskDto);
        }
        if (Cools.isEmpty(param.getTaskList())) { return; }
        if (Cools.isEmpty(param.getTasks())) { return; }
        mainService.generateBusAndTask(param, memo);
    }
zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/MainService.java
@@ -23,7 +23,7 @@
import com.zy.acs.manager.core.domain.TaskPosDto;
import com.zy.acs.manager.core.integrate.conveyor.ConveyorStationService;
import com.zy.acs.manager.core.service.astart.MapDataDispatcher;
import com.zy.acs.manager.manager.controller.param.OpenBusSubmitParam;
import com.zy.acs.manager.core.integrate.dto.OpenBusSubmitParam;
import com.zy.acs.manager.manager.entity.*;
import com.zy.acs.manager.manager.enums.*;
import com.zy.acs.manager.manager.service.*;
@@ -104,11 +104,12 @@
    @Transactional
    public Bus generateBusAndTask(OpenBusSubmitParam busSubmitParam, String memo) {
        String errorMsg = busService.checkoutValid(busSubmitParam);
        Boolean maintainLocSts = configService.getVal("maintainLocSts", Boolean.class);
        if (!Cools.isEmpty(errorMsg)) {
            throw new BusinessException(errorMsg);
        }
        String batch = busSubmitParam.getBatch();
        List<TaskDto> taskDtoList = busSubmitParam.getTaskList();
        String batchNo = busSubmitParam.getBatchNo();
        List<TaskDto> taskDtoList = busSubmitParam.getTasks();
        if (Cools.isEmpty(taskDtoList)) {
            throw new BusinessException("taskList can't be empty!");
        }
@@ -123,7 +124,7 @@
        Date now = new Date();
        Bus bus = new Bus();
        bus.setUuid(String.valueOf(snowflakeIdWorker.nextId()).substring(3));
        bus.setBusNo(batch);
        bus.setBusNo(batchNo);
        bus.setStartTime(now);
        bus.setBusSts(BusStsType.RECEIVE.val());
        bus.setMemo(memo);
@@ -147,35 +148,39 @@
            Sta destSta = null;
            switch (TaskTypeType.get(task.getTaskTypeEl())) {
                case LOC_TO_LOC:
                    oriLoc = locService.getById(task.getOriLoc());
                    if (!oriLoc.getLocSts().equals(LocStsType.STOCK.val())) {
                        throw new BusinessException("oriLoc:" + task.getOriLoc$() + " is not in STOCK status");
                    }
                    oriLoc.setLocSts(LocStsType.PAKOUT.val());
                    oriLoc.setUpdateTime(now);
                    if (!locService.updateById(oriLoc)) {
                        throw new BusinessException("oriLoc:" + task.getOriLoc$() + " failed to update");
                    }
                    if (maintainLocSts) {
                        oriLoc = locService.getById(task.getOriLoc());
                        if (!oriLoc.getLocSts().equals(LocStsType.STOCK.val())) {
                            throw new BusinessException("oriLoc:" + task.getOriLoc$() + " is not in STOCK status");
                        }
                        oriLoc.setLocSts(LocStsType.PAKOUT.val());
                        oriLoc.setUpdateTime(now);
                        if (!locService.updateById(oriLoc)) {
                            throw new BusinessException("oriLoc:" + task.getOriLoc$() + " failed to update");
                        }
                    destLoc = locService.getById(task.getDestLoc());
                    if (!destLoc.getLocSts().equals(LocStsType.IDLE.val())) {
                        throw new BusinessException("destLoc:" + task.getDestLoc$() + " is not in IDLE status");
                    }
                    destLoc.setLocSts(LocStsType.PAKIN.val());
                    destLoc.setUpdateTime(now);
                    if (!locService.updateById(destLoc)) {
                        throw new BusinessException("destLoc:" + task.getDestLoc$() + " failed to update");
                        destLoc = locService.getById(task.getDestLoc());
                        if (!destLoc.getLocSts().equals(LocStsType.IDLE.val())) {
                            throw new BusinessException("destLoc:" + task.getDestLoc$() + " is not in IDLE status");
                        }
                        destLoc.setLocSts(LocStsType.PAKIN.val());
                        destLoc.setUpdateTime(now);
                        if (!locService.updateById(destLoc)) {
                            throw new BusinessException("destLoc:" + task.getDestLoc$() + " failed to update");
                        }
                    }
                    break;
                case LOC_TO_STA:
                    oriLoc = locService.getById(task.getOriLoc());
                    if (!oriLoc.getLocSts().equals(LocStsType.STOCK.val())) {
                        throw new BusinessException("oriLoc:" + task.getOriLoc$() + " is not in STOCK status");
                    }
                    oriLoc.setLocSts(LocStsType.PAKOUT.val());
                    oriLoc.setUpdateTime(now);
                    if (!locService.updateById(oriLoc)) {
                        throw new BusinessException("oriLoc:" + task.getOriLoc$() + " failed to update");
                    if (maintainLocSts) {
                        oriLoc = locService.getById(task.getOriLoc());
                        if (!oriLoc.getLocSts().equals(LocStsType.STOCK.val())) {
                            throw new BusinessException("oriLoc:" + task.getOriLoc$() + " is not in STOCK status");
                        }
                        oriLoc.setLocSts(LocStsType.PAKOUT.val());
                        oriLoc.setUpdateTime(now);
                        if (!locService.updateById(oriLoc)) {
                            throw new BusinessException("oriLoc:" + task.getOriLoc$() + " failed to update");
                        }
                    }
                    destSta = staService.getById(task.getDestSta());
@@ -189,14 +194,16 @@
                        throw new BusinessException("oriSta:" + task.getOriSta$() + " failed to reserve");
                    }
                    destLoc = locService.getById(task.getDestLoc());
                    if (!destLoc.getLocSts().equals(LocStsType.IDLE.val())) {
                        throw new BusinessException("destLoc:" + task.getDestLoc$() + " is not in IDLE status");
                    }
                    destLoc.setLocSts(LocStsType.PAKIN.val());
                    destLoc.setUpdateTime(now);
                    if (!locService.updateById(destLoc)) {
                        throw new BusinessException("destLoc:" + task.getDestLoc$() + " failed to update");
                    if (maintainLocSts) {
                        destLoc = locService.getById(task.getDestLoc());
                        if (!destLoc.getLocSts().equals(LocStsType.IDLE.val())) {
                            throw new BusinessException("destLoc:" + task.getDestLoc$() + " is not in IDLE status");
                        }
                        destLoc.setLocSts(LocStsType.PAKIN.val());
                        destLoc.setUpdateTime(now);
                        if (!locService.updateById(destLoc)) {
                            throw new BusinessException("destLoc:" + task.getDestLoc$() + " failed to update");
                        }
                    }
                    break;
                case STA_TO_STA:
@@ -791,6 +798,7 @@
            task.setPriority(taskType.equals(TaskTypeType.TO_CHARGE)?2:1);
            task.setTaskSts(TaskStsType.ASSIGN.val());
            task.setTaskType(taskType.val());
            task.setUplinkSts(TaskUplinkStateType.SKIPPED.toString());
            task.setIoTime(now);
            task.setStartTime(now);
            if (!taskService.save(task)) {
@@ -1147,7 +1155,7 @@
                }
                // ä½œä¸šç‚¹åŠ¨ä½œ
                AgvDirectionType agvDirectionType;
                ActuatorDirectionType actuatorDirectionType;
                Double staWorkDirection;
                AgvBackpackType backpackType = AgvBackpackType.query(segment.getBackpack());
                switch (Objects.requireNonNull(TaskPosDto.queryPosType(segment.getPosType()))) {
@@ -1160,7 +1168,8 @@
                        // è´§æž¶å–è´§
                        Loc oriLoc = locService.getById(task.getOriLoc());
                        // è®¡ç®—左右方向
                        agvDirectionType = mapService.calculateAgvWorkDirectionByShelf(oriLoc, lastCode);
                        actuatorDirectionType = ActuatorDirectionType.fromVal(oriLoc.getCompDirect());
//                        actuatorDirectionType = mapService.calculateAgvWorkDirectionByShelf(oriLoc, lastCode);
                        actionList.add(new Action(
                                null,    // ç¼–号
                                task.getBusId(),    // æ€»çº¿
@@ -1168,7 +1177,7 @@
                                null,    // åŠ¨ä½œå·
                                null,    // ä¼˜å…ˆçº§
                                ActionTypeType.ReadyTakeFromShelvesLoc.desc,    // åç§°
                                (double) agvDirectionType.val,    // å±žæ€§å€¼
                                (double) actuatorDirectionType.val,    // å±žæ€§å€¼
                                lastCode.getData(),    // åœ°é¢ç 
                                JSON.toJSONString(new HeightDepthDto(oriLoc.getOffset())),   // åŠ¨ä½œå‚æ•°
                                ActionTypeType.ReadyTakeFromShelvesLoc.val(),    // åŠ¨ä½œç±»åž‹
@@ -1223,7 +1232,8 @@
                        // è´§æž¶æ”¾è´§
                        Loc destLoc = locService.getById(task.getDestLoc());
                        // è®¡ç®—左右方向
                        agvDirectionType = mapService.calculateAgvWorkDirectionByShelf(destLoc, lastCode);
                        actuatorDirectionType = ActuatorDirectionType.fromVal(destLoc.getCompDirect());
//                        actuatorDirectionType = mapService.calculateAgvWorkDirectionByShelf(destLoc, lastCode);
                        actionList.add(new Action(
                                null,    // ç¼–号
                                task.getBusId(),    // æ€»çº¿
@@ -1231,7 +1241,7 @@
                                null,    // åŠ¨ä½œå·
                                 null,    // ä¼˜å…ˆçº§
                                ActionTypeType.ReadyReleaseToShelvesLoc.desc,    // åç§°
                                (double) agvDirectionType.val,    // å±žæ€§å€¼
                                (double) actuatorDirectionType.val,    // å±žæ€§å€¼
                                lastCode.getData(),    // åœ°é¢ç 
                                JSON.toJSONString(new HeightDepthDto(destLoc.getOffset())),   // åŠ¨ä½œå‚æ•°
                                ActionTypeType.ReadyReleaseToShelvesLoc.val(),    // åŠ¨ä½œç±»åž‹
@@ -1268,7 +1278,8 @@
                            lastDirection = oriStaWorkDirection;
                        }
                        // è®¡ç®—货叉工作方向
                        staWorkDirection = mapService.calculateAgvWorkDirectionByStation(oriStaWorkDirection, lastDirection);
                        actuatorDirectionType = ActuatorDirectionType.fromVal(oriSta.getActDir());
//                        staWorkDirection = mapService.calculateAgvWorkDirectionByStation(oriStaWorkDirection, lastDirection);
                        actionList.add(new Action(
                                null,    // ç¼–号
                                task.getBusId(),    // æ€»çº¿
@@ -1276,7 +1287,7 @@
                                null,    // åŠ¨ä½œå·
                                null,    // ä¼˜å…ˆçº§
                                ActionTypeType.ReadyTakeFromConveyorSta.desc,    // åç§°
                                staWorkDirection,    // å±žæ€§å€¼
                                (double) actuatorDirectionType.val,    // å±žæ€§å€¼
                                lastCode.getData(),    // åœ°é¢ç 
                                JSON.toJSONString(new HeightDepthDto(oriSta.getHeight(), Optional.ofNullable(oriSta.getDepth()).orElse((double) 0))),   // åŠ¨ä½œå‚æ•°
                                ActionTypeType.ReadyTakeFromConveyorSta.val(),    // åŠ¨ä½œç±»åž‹
@@ -1351,7 +1362,8 @@
                            ));
                        }
                        // è®¡ç®—货叉工作方向
                        staWorkDirection = mapService.calculateAgvWorkDirectionByStation(destStaWorkDirection, lastDirection);
//                        staWorkDirection = mapService.calculateAgvWorkDirectionByStation(destStaWorkDirection, lastDirection);
                        actuatorDirectionType = ActuatorDirectionType.fromVal(destSta.getActDir());
                        actionList.add(new Action(
                                null,    // ç¼–号
                                task.getBusId(),    // æ€»çº¿
@@ -1359,7 +1371,7 @@
                                null,    // åŠ¨ä½œå·
                                null,    // ä¼˜å…ˆçº§
                                ActionTypeType.ReadyReleaseToConveyorSta.desc,    // åç§°
                                staWorkDirection,    // å±žæ€§å€¼
                                (double) actuatorDirectionType.val,    // å±žæ€§å€¼
                                lastCode.getData(),    // åœ°é¢ç 
                                JSON.toJSONString(new HeightDepthDto(destSta.getHeight(), Optional.ofNullable(destSta.getDepth()).orElse((double) 0))),   // åŠ¨ä½œå‚æ•°
                                ActionTypeType.ReadyReleaseToConveyorSta.val(),    // åŠ¨ä½œç±»åž‹
zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/MapService.java
@@ -1,7 +1,7 @@
package com.zy.acs.manager.core.service;
import com.alibaba.fastjson.JSON;
import com.zy.acs.common.enums.AgvDirectionType;
import com.zy.acs.common.enums.ActuatorDirectionType;
import com.zy.acs.framework.common.Cools;
import com.zy.acs.manager.core.constant.MapDataConstant;
import com.zy.acs.manager.core.domain.DirectionDto;
@@ -158,17 +158,10 @@
        return angle;
    }
    // åæ ‡è´§æž¶é˜ˆå€¼ todo:luxiaotao
    public AgvDirectionType calculateAgvWorkDirectionByShelf(Loc loc, Code code) {
    // åæ ‡è´§æž¶é˜ˆå€¼
    public ActuatorDirectionType calculateAgvWorkDirectionByShelf(Loc loc, Code code) {
        Integer compDirect = loc.getCompDirect();
        AgvDirectionType agvDirectionType = null;
        if (compDirect == 0) {
            agvDirectionType = AgvDirectionType.RIGHT;
        }
        if (compDirect == 1) {
            agvDirectionType = AgvDirectionType.LEFT;
        }
        return agvDirectionType;
        return ActuatorDirectionType.fromVal(compDirect);
    }
    public Double getStaAngle(Sta sta, Double workDirection) {
zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/ValidService.java
@@ -3,6 +3,7 @@
import com.alibaba.fastjson.JSON;
import com.zy.acs.framework.common.Cools;
import com.zy.acs.framework.common.SnowflakeIdWorker;
import com.zy.acs.manager.common.config.UplinkProperties;
import com.zy.acs.manager.common.domain.TaskDto;
import com.zy.acs.manager.common.exception.BusinessException;
import com.zy.acs.manager.manager.entity.Code;
@@ -10,6 +11,7 @@
import com.zy.acs.manager.manager.entity.Sta;
import com.zy.acs.manager.manager.entity.Task;
import com.zy.acs.manager.manager.enums.TaskTypeType;
import com.zy.acs.manager.manager.enums.TaskUplinkStateType;
import com.zy.acs.manager.manager.service.CodeService;
import com.zy.acs.manager.manager.service.LocService;
import com.zy.acs.manager.manager.service.StaService;
@@ -36,17 +38,20 @@
    private MapService mapService;
    @Autowired
    private SnowflakeIdWorker snowflakeIdWorker;
    @Autowired
    private UplinkProperties uplinkProperties;
    public List<Task> validTaskDtoList(List<TaskDto> taskDtoList) {
        List<Task> taskList = new ArrayList<>();
        String uplinkSts = uplinkProperties.getEnabled() ? TaskUplinkStateType.PENDING.toString() : TaskUplinkStateType.SKIPPED.toString();
        for (TaskDto taskDto : taskDtoList) {
            if (Cools.isEmpty(taskDto.getSeqNum())) {
            if (Cools.isEmpty(taskDto.getTaskNo())) {
                throw new BusinessException("Task seqNum can't be empty!");
            }
            Task task = new Task();
            taskList.add(task);
            task.setUuid(String.valueOf(snowflakeIdWorker.nextId()).substring(3));
            task.setSeqNum(taskDto.getSeqNum());
            task.setSeqNum(taskDto.getTaskNo());
            task.setPriority(taskDto.getPriority());
            // ori --------------------------
@@ -140,6 +145,7 @@
                        throw new BusinessException("seqNum:" + task.getSeqNum() + " is wrong,oriLoc:" + task.getOriLoc() + " is unable to reach destLoc" + task.getDestLoc());
                    }
                    task.setPhase(JSON.toJSONString(pathList));
                    task.setUplinkSts(uplinkSts);
                    break;
                case LOC_TO_STA:
                    oriLoc = locService.getById(task.getOriLoc());
@@ -158,6 +164,7 @@
                        throw new BusinessException("seqNum:" + task.getSeqNum() + " is wrong,oriLoc:" + task.getOriLoc() + " can't move to destSta" + task.getDestSta());
                    }
                    task.setPhase(JSON.toJSONString(pathList));
                    task.setUplinkSts(uplinkSts);
                    break;
                case STA_TO_LOC:
                    oriSta = staService.getById(task.getOriSta());
@@ -176,6 +183,7 @@
                        throw new BusinessException("seqNum:" + task.getSeqNum() + " is wrong,oriSta:" + task.getOriSta() + " is unable to react destLoc" + task.getDestLoc());
                    }
                    task.setPhase(JSON.toJSONString(pathList));
                    task.setUplinkSts(uplinkSts);
                    break;
                case STA_TO_STA:
                    oriSta = staService.getById(task.getOriSta());
@@ -194,6 +202,7 @@
                        throw new BusinessException("seqNum:" + task.getSeqNum() + " is wrong,oriSta:" + task.getOriSta() + " can't move to destSta" + task.getDestSta());
                    }
                    task.setPhase(JSON.toJSONString(pathList));
                    task.setUplinkSts(uplinkSts);
                    break;
                default:
                    throw new BusinessException("seqNum:" + task.getSeqNum() + " is wrong, cause this type not exist");
zy-acs-manager/src/main/java/com/zy/acs/manager/manager/controller/BusController.java
@@ -6,12 +6,13 @@
import com.zy.acs.framework.common.Cools;
import com.zy.acs.framework.common.R;
import com.zy.acs.manager.common.annotation.OperationLog;
import com.zy.acs.manager.common.constant.Constants;
import com.zy.acs.manager.common.domain.*;
import com.zy.acs.manager.common.utils.BusinessSortService;
import com.zy.acs.manager.common.utils.ExcelUtil;
import com.zy.acs.manager.core.service.MainService;
import com.zy.acs.manager.manager.controller.param.BusCreateParam;
import com.zy.acs.manager.manager.controller.param.OpenBusSubmitParam;
import com.zy.acs.manager.core.integrate.dto.OpenBusSubmitParam;
import com.zy.acs.manager.manager.entity.Bus;
import com.zy.acs.manager.manager.entity.Task;
import com.zy.acs.manager.manager.enums.BusStsType;
@@ -94,10 +95,10 @@
    @PostMapping("/bus/save")
    public R save(@RequestBody BusCreateParam param) {
        OpenBusSubmitParam submitParam = new OpenBusSubmitParam();
        submitParam.setBatch(param.getBusNo());
        submitParam.setBatchNo(param.getBusNo());
        for (TaskIdByLongDto dto : param.getTaskList()) {
            TaskDto taskDto = new TaskDto();
            taskDto.setSeqNum(dto.getSeqNum());
            taskDto.setTaskNo(dto.getSeqNum());
            taskDto.setPriority(dto.getPriority());
            if (!Cools.isEmpty(dto.getOriSta())) {
                taskDto.setOriSta(staService.getById(dto.getOriSta()).getStaNo());
@@ -111,7 +112,7 @@
            if (!Cools.isEmpty(dto.getDestLoc())) {
                taskDto.setDestLoc(locService.getById(dto.getDestLoc()).getLocNo());
            }
            submitParam.getTaskList().add(taskDto);
            submitParam.getTasks().add(taskDto);
        }
        Bus bus = mainService.generateBusAndTask(submitParam, param.getMemo());
        return R.ok("Save Success").add(bus);
@@ -176,7 +177,7 @@
                .in(Task::getTaskSts, TaskStsType.INIT.val(), TaskStsType.WAITING.val()));
        if (!Cools.isEmpty(taskList)) {
            for (Task task : taskList) {
                taskService.cancel(task.getId(), getLoginUserId());
                taskService.cancel(task.getId(), getLoginUserId(), Constants.HANDLE);
            }
        }
        if (0 == taskService.count(new LambdaQueryWrapper<Task>().eq(Task::getBusId, bus.getId()).eq(Task::getTaskSts, TaskStsType.COMPLETE.val()))) {
zy-acs-manager/src/main/java/com/zy/acs/manager/manager/controller/CodeController.java
@@ -17,6 +17,7 @@
import com.zy.acs.manager.manager.entity.Code;
import com.zy.acs.manager.manager.entity.CodeGap;
import com.zy.acs.manager.manager.entity.Route;
import com.zy.acs.manager.manager.enums.StatusType;
import com.zy.acs.manager.manager.service.CodeGapService;
import com.zy.acs.manager.manager.service.CodeService;
import com.zy.acs.manager.manager.service.RouteService;
@@ -159,6 +160,7 @@
            code.setUuid("code".concat(code.getData()));
//            code.setCorner(0);
            code.setScale(GsonUtils.toJson(Cools.add("x", 1).add("y", 1)));
            code.setStatus(StatusType.ENABLE.val);
            code.setCreateBy(userId);
            code.setCreateTime(now);
            code.setUpdateBy(userId);
zy-acs-manager/src/main/java/com/zy/acs/manager/manager/controller/IntegrationRecordController.java
New file
@@ -0,0 +1,108 @@
package com.zy.acs.manager.manager.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zy.acs.framework.common.Cools;
import com.zy.acs.framework.common.R;
import com.zy.acs.manager.common.utils.ExcelUtil;
import com.zy.acs.manager.common.annotation.OperationLog;
import com.zy.acs.manager.common.domain.BaseParam;
import com.zy.acs.manager.common.domain.KeyValVo;
import com.zy.acs.manager.common.domain.PageParam;
import com.zy.acs.manager.manager.entity.IntegrationRecord;
import com.zy.acs.manager.manager.service.IntegrationRecordService;
import com.zy.acs.manager.system.controller.BaseController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
@RestController
@RequestMapping("/api")
public class IntegrationRecordController extends BaseController {
    @Autowired
    private IntegrationRecordService integrationRecordService;
    @PreAuthorize("hasAuthority('manager:integrationRecord:list')")
    @PostMapping("/integrationRecord/page")
    public R page(@RequestBody Map<String, Object> map) {
        BaseParam baseParam = buildParam(map, BaseParam.class);
        PageParam<IntegrationRecord, BaseParam> pageParam = new PageParam<>(baseParam, IntegrationRecord.class);
        return R.ok().add(integrationRecordService.page(pageParam, pageParam.buildWrapper(true)));
    }
    @PreAuthorize("hasAuthority('manager:integrationRecord:list')")
    @PostMapping("/integrationRecord/list")
    public R list(@RequestBody Map<String, Object> map) {
        return R.ok().add(integrationRecordService.list());
    }
    @PreAuthorize("hasAuthority('manager:integrationRecord:list')")
    @PostMapping({"/integrationRecord/many/{ids}", "/integrationRecords/many/{ids}"})
    public R many(@PathVariable Long[] ids) {
        return R.ok().add(integrationRecordService.listByIds(Arrays.asList(ids)));
    }
    @PreAuthorize("hasAuthority('manager:integrationRecord:list')")
    @GetMapping("/integrationRecord/{id}")
    public R get(@PathVariable("id") Long id) {
        return R.ok().add(integrationRecordService.getById(id));
    }
    @PreAuthorize("hasAuthority('manager:integrationRecord:save')")
    @OperationLog("Create Integration Record")
    @PostMapping("/integrationRecord/save")
    public R save(@RequestBody IntegrationRecord integrationRecord) {
        integrationRecord.setCreateTime(new Date());
        integrationRecord.setUpdateTime(new Date());
        if (!integrationRecordService.save(integrationRecord)) {
            return R.error("Save Fail");
        }
        return R.ok("Save Success").add(integrationRecord);
    }
    @PreAuthorize("hasAuthority('manager:integrationRecord:update')")
    @OperationLog("Update Integration Record")
    @PostMapping("/integrationRecord/update")
    public R update(@RequestBody IntegrationRecord integrationRecord) {
        integrationRecord.setUpdateTime(new Date());
        if (!integrationRecordService.updateById(integrationRecord)) {
            return R.error("Update Fail");
        }
        return R.ok("Update Success").add(integrationRecord);
    }
    @PreAuthorize("hasAuthority('manager:integrationRecord:remove')")
    @OperationLog("Delete Integration Record")
    @PostMapping("/integrationRecord/remove/{ids}")
    public R remove(@PathVariable Long[] ids) {
        if (!integrationRecordService.removeByIds(Arrays.asList(ids))) {
            return R.error("Delete Fail");
        }
        return R.ok("Delete Success").add(ids);
    }
    @PreAuthorize("hasAuthority('manager:integrationRecord:list')")
    @PostMapping("/integrationRecord/query")
    public R query(@RequestParam(required = false) String condition) {
        List<KeyValVo> vos = new ArrayList<>();
        LambdaQueryWrapper<IntegrationRecord> wrapper = new LambdaQueryWrapper<>();
        if (!Cools.isEmpty(condition)) {
            wrapper.like(IntegrationRecord::getNamespace, condition);
        }
        integrationRecordService.page(new Page<>(1, 30), wrapper).getRecords().forEach(
                item -> vos.add(new KeyValVo(item.getId(), item.getNamespace()))
        );
        return R.ok().add(vos);
    }
    @PreAuthorize("hasAuthority('manager:integrationRecord:list')")
    @PostMapping("/integrationRecord/export")
    public void export(@RequestBody Map<String, Object> map, HttpServletResponse response) throws Exception {
        ExcelUtil.build(ExcelUtil.create(integrationRecordService.list(), IntegrationRecord.class), response);
    }
}
zy-acs-manager/src/main/java/com/zy/acs/manager/manager/controller/TaskController.java
@@ -1,11 +1,11 @@
package com.zy.acs.manager.manager.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zy.acs.framework.common.Cools;
import com.zy.acs.framework.common.R;
import com.zy.acs.manager.common.annotation.OperationLog;
import com.zy.acs.manager.common.constant.Constants;
import com.zy.acs.manager.common.domain.BaseParam;
import com.zy.acs.manager.common.domain.KeyValVo;
import com.zy.acs.manager.common.domain.PageParam;
@@ -15,7 +15,6 @@
import com.zy.acs.manager.manager.entity.Task;
import com.zy.acs.manager.manager.service.TaskService;
import com.zy.acs.manager.system.controller.BaseController;
import com.zy.acs.manager.system.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
@@ -119,14 +118,14 @@
    @OperationLog("Complete Task")
    @GetMapping("/task/complete/{id}")
    public R complete(@PathVariable Long id) {
        return taskService.complete(id, getLoginUserId()) ? R.ok("Complete Success") : R.error("Complete Fail");
        return taskService.complete(id, getLoginUserId(), Constants.HANDLE) ? R.ok("Complete Success") : R.error("Complete Fail");
    }
    @PreAuthorize("hasAuthority('manager:task:update')")
    @OperationLog("Cancel Task")
    @GetMapping("/task/cancel/{id}")
    public R cancel(@PathVariable Long id) {
        return taskService.cancel(id, getLoginUserId()) ? R.ok("Cancel Success") : R.error("Cancel Fail");
        return taskService.cancel(id, getLoginUserId(), Constants.HANDLE) ? R.ok("Cancel Success") : R.error("Cancel Fail");
    }
}
zy-acs-manager/src/main/java/com/zy/acs/manager/manager/entity/IntegrationRecord.java
New file
@@ -0,0 +1,196 @@
package com.zy.acs.manager.manager.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.util.Date;
@Data
@TableName("man_integration_record")
public class IntegrationRecord implements Serializable {
    private static final long serialVersionUID = 1L;
    /**
     * ID
     */
    @ApiModelProperty(value= "ID")
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;
    /**
     * ç¼–号
     */
    @ApiModelProperty(value= "编号")
    private String uuid;
    /**
     * åç§°ç©ºé—´
     */
    @ApiModelProperty(value= "名称空间")
    private String namespace;
    /**
     * æŽ¥å£åœ°å€
     */
    @ApiModelProperty(value= "接口地址")
    private String url;
    /**
     * å¹³å°å¯†é’¥
     */
    @ApiModelProperty(value= "平台密钥")
    private String appkey;
    /**
     * è°ƒç”¨æ–¹æ ‡è¯†
     */
    @ApiModelProperty(value= "调用方标识")
    private String caller;
    /**
     * æ–¹å‘ 1: è¢«è°ƒç”¨  2: è°ƒç”¨å¤–部
     */
    @ApiModelProperty(value= "方向 1: è¢«è°ƒç”¨  2: è°ƒç”¨å¤–部  ")
    private Integer direction;
    /**
     * æ—¶é—´æˆ³
     */
    @ApiModelProperty(value= "时间戳")
    private String timestamp;
    /**
     * å®¢æˆ·ç«¯IP
     */
    @ApiModelProperty(value= "客户端IP")
    private String clientIp;
    /**
     * è¯·æ±‚内容
     */
    @ApiModelProperty(value= "请求内容")
    private String request;
    /**
     * å“åº”内容
     */
    @ApiModelProperty(value= "响应内容")
    private String response;
    /**
     * å¼‚常内容
     */
    @ApiModelProperty(value= "异常内容")
    private String err;
    /**
     * ç»“æžœ 1: æˆåŠŸ  0: å¤±è´¥
     */
    @ApiModelProperty(value= "结果 1: æˆåŠŸ  0: å¤±è´¥  ")
    private Integer result;
    /**
     * è€—æ—¶
     */
    @ApiModelProperty(value= "耗时")
    private Integer costMs;
    /**
     * çŠ¶æ€ 1: æ­£å¸¸  0: å†»ç»“
     */
    @ApiModelProperty(value= "状态 1: æ­£å¸¸  0: å†»ç»“  ")
    private Integer status;
    /**
     * æ·»åŠ æ—¶é—´
     */
    @ApiModelProperty(value= "添加时间")
    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
    private Date createTime;
    /**
     * ä¿®æ”¹æ—¶é—´
     */
    @ApiModelProperty(value= "修改时间")
    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
    private Date updateTime;
    /**
     * å¤‡æ³¨
     */
    @ApiModelProperty(value= "备注")
    private String memo;
    public IntegrationRecord() {}
    public IntegrationRecord(String uuid,String namespace,String url,String appkey,String caller,Integer direction,String timestamp,String clientIp,String request,String response,String err,Integer result,Integer costMs,Integer status,Date createTime,Date updateTime,String memo) {
        this.uuid = uuid;
        this.namespace = namespace;
        this.url = url;
        this.appkey = appkey;
        this.caller = caller;
        this.direction = direction;
        this.timestamp = timestamp;
        this.clientIp = clientIp;
        this.request = request;
        this.response = response;
        this.err = err;
        this.result = result;
        this.costMs = costMs;
        this.status = status;
        this.createTime = createTime;
        this.updateTime = updateTime;
        this.memo = memo;
    }
//    IntegrationRecord integrationRecord = new IntegrationRecord(
//            null,    // ç¼–号
//            null,    // åç§°ç©ºé—´
//            null,    // æŽ¥å£åœ°å€
//            null,    // å¹³å°å¯†é’¥
//            null,    // è°ƒç”¨æ–¹æ ‡è¯†
//            null,    // æ–¹å‘[非空]
//            null,    // æ—¶é—´æˆ³
//            null,    // å®¢æˆ·ç«¯IP
//            null,    // è¯·æ±‚内容
//            null,    // å“åº”内容
//            null,    // å¼‚常内容
//            null,    // ç»“æžœ
//            null,    // è€—æ—¶
//            null,    // çŠ¶æ€
//            null,    // æ·»åŠ æ—¶é—´[非空]
//            null,    // ä¿®æ”¹æ—¶é—´[非空]
//            null    // å¤‡æ³¨
//    );
    public Boolean getResultBool(){
        if (null == this.result){ return null; }
        switch (this.result){
            case 1:
                return true;
            case 0:
                return false;
            default:
                return null;
        }
    }
    public Boolean getStatusBool(){
        if (null == this.status){ return null; }
        switch (this.status){
            case 1:
                return true;
            case 0:
                return false;
            default:
                return null;
        }
    }
}
zy-acs-manager/src/main/java/com/zy/acs/manager/manager/entity/Loc.java
@@ -57,9 +57,9 @@
    private Long code;
    /**
     * æ¯”码方向阈 1:  å¤§äºŽ  0    å°äºŽ
     * æ¯”码方向阈
     */
    @ApiModelProperty(value= "比码方向阈 1:  å¤§äºŽ  0    å°äºŽ")
    @ApiModelProperty(value= "比码方向阈")
    private Integer compDirect;
    /**
zy-acs-manager/src/main/java/com/zy/acs/manager/manager/entity/Sta.java
@@ -65,6 +65,9 @@
    @ApiModelProperty(value= "作业角度")
    private String angle;
    @ApiModelProperty(value= "货叉方向")
    private Integer actDir;
    @ApiModelProperty(value= "连续入库等待(ms)")
    private Integer inboundWait;
zy-acs-manager/src/main/java/com/zy/acs/manager/manager/entity/Task.java
@@ -18,202 +18,106 @@
    private static final long serialVersionUID = 1L;
    /**
     * ID
     */
    @ApiModelProperty(value= "ID")
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;
    /**
     * ç¼–号
     */
    @ApiModelProperty(value= "编号")
    private String uuid;
    /**
     * æ€»çº¿
     */
    @ApiModelProperty(value= "总线")
    private Long busId;
    /**
     * ä»»åŠ¡å·
     */
    @ApiModelProperty(value= "任务号")
    private String seqNum;
    /**
     * ä¼˜å…ˆçº§
     */
    @ApiModelProperty(value= "优先级")
    private Integer priority;
    /**
     * åç§°
     */
    @ApiModelProperty(value= "名称")
    private String name;
    /**
     * ä»»åŠ¡è¿›åº¦
     */
    @ApiModelProperty(value= "任务进度")
    private Long taskSts;
    /**
     * ä»»åŠ¡ç±»åž‹
     */
    @ApiModelProperty(value= "任务类型")
    private Long taskType;
    /**
     * AGV
     */
    @ApiModelProperty(value= "AGV")
    private Long agvId;
    /**
     * å·¥ä½œæ—¶é—´
     */
    @ApiModelProperty(value= "工作时间")
    private Date ioTime;
    /**
     * å¼€å§‹æ—¶é—´
     */
    @ApiModelProperty(value= "开始时间")
    private Date startTime;
    /**
     * ç»“束时间
     */
    @ApiModelProperty(value= "结束时间")
    private Date endTime;
    /**
     * å¼‚常时间
     */
    @ApiModelProperty(value= "异常时间")
    private Date errTime;
    /**
     * èµ·å§‹ç«™
     */
    @ApiModelProperty(value= "起始站")
    private Long oriSta;
    /**
     * èµ·å§‹åº“位
     */
    @ApiModelProperty(value= "起始库位")
    private Long oriLoc;
    /**
     * èµ·å§‹ç 
     */
    @ApiModelProperty(value= "起始码")
    private Long oriCode;
    /**
     * èµ·å§‹å··é“哈希
     */
    @ApiModelProperty(value= "起始巷道哈希")
    private String oriLaneHash;
    /**
     * ç›®æ ‡ç«™
     */
    @ApiModelProperty(value= "目标站")
    private Long destSta;
    /**
     * ç›®æ ‡åº“位
     */
    @ApiModelProperty(value= "目标库位")
    private Long destLoc;
    /**
     * ç›®æ ‡ç 
     */
    @ApiModelProperty(value= "目标码")
    private Long destCode;
    /**
     * ç›®æ ‡å··é“哈希
     */
    @ApiModelProperty(value= "目标巷道哈希")
    private String destLaneHash;
    /**
     * ç©ºæ¿
     */
    @ApiModelProperty(value= "空板")
    private String emptyMk;
    /**
     * æ‰˜ç›˜ç 
     */
    @ApiModelProperty(value= "上行状态")
    private String uplinkSts;
    @ApiModelProperty(value= "托盘码")
    private String zpallet;
    /**
     * çŽ¯èŠ‚
     */
    @ApiModelProperty(value= "环节")
    private String phase;
    /**
     * å¼‚常描述
     */
    @ApiModelProperty(value= "异常描述")
    private String errDesc;
    /**
     * çŠ¶æ€ 1: æ­£å¸¸  0: å†»ç»“
     */
    @ApiModelProperty(value= "状态 1: æ­£å¸¸  0: å†»ç»“  ")
    private Integer status;
    /**
     * æ˜¯å¦åˆ é™¤ 1: æ˜¯  0: å¦
     */
    @ApiModelProperty(value= "是否删除 1: æ˜¯  0: å¦  ")
    private Integer deleted;
    /**
     * ç§Ÿæˆ·
     */
    @ApiModelProperty(value= "租户")
    private Long tenantId;
    /**
     * æ·»åŠ äººå‘˜
     */
    @ApiModelProperty(value= "添加人员")
    private Long createBy;
    /**
     * æ·»åŠ æ—¶é—´
     */
    @ApiModelProperty(value= "添加时间")
    private Date createTime;
    /**
     * ä¿®æ”¹äººå‘˜
     */
    @ApiModelProperty(value= "修改人员")
    private Long updateBy;
    /**
     * ä¿®æ”¹æ—¶é—´
     */
    @ApiModelProperty(value= "修改时间")
    private Date updateTime;
    /**
     * å¤‡æ³¨
     */
    @ApiModelProperty(value= "备注")
    private String memo;
zy-acs-manager/src/main/java/com/zy/acs/manager/manager/enums/IntegrationDirectionType.java
New file
@@ -0,0 +1,16 @@
package com.zy.acs.manager.manager.enums;
public enum IntegrationDirectionType {
    NONE(0),        // æœªçŸ¥
    INBOUND(1),     // æŽ¥æ”¶
    OUTBOUND(2),    // è°ƒç”¨
    ;
    public int value;
    IntegrationDirectionType(int value) {
        this.value = value;
    }
}
zy-acs-manager/src/main/java/com/zy/acs/manager/manager/enums/TaskUplinkStateType.java
New file
@@ -0,0 +1,28 @@
package com.zy.acs.manager.manager.enums;
import com.zy.acs.framework.common.Cools;
public enum TaskUplinkStateType {
    NONE,       // æœªçŸ¥
    PENDING,    // å¾…上报
    SENDING,    // ä¸ŠæŠ¥ä¸­
    SUCCESS,    // æˆåŠŸ
    FAILED,     // å¤±è´¥
    SKIPPED,    // è·³è¿‡
    ;
    public static TaskUplinkStateType of(String state) {
        if (Cools.isEmpty(state)) {
            return NONE;
        }
        for (TaskUplinkStateType type : TaskUplinkStateType.values()) {
            if (type.toString().equals(state)) {
                return type;
            }
        }
        return NONE;
    }
}
zy-acs-manager/src/main/java/com/zy/acs/manager/manager/mapper/IntegrationRecordMapper.java
New file
@@ -0,0 +1,12 @@
package com.zy.acs.manager.manager.mapper;
import com.zy.acs.manager.manager.entity.IntegrationRecord;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
@Mapper
@Repository
public interface IntegrationRecordMapper extends BaseMapper<IntegrationRecord> {
}
zy-acs-manager/src/main/java/com/zy/acs/manager/manager/service/BusService.java
@@ -1,7 +1,7 @@
package com.zy.acs.manager.manager.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.zy.acs.manager.manager.controller.param.OpenBusSubmitParam;
import com.zy.acs.manager.core.integrate.dto.OpenBusSubmitParam;
import com.zy.acs.manager.manager.entity.Bus;
import com.zy.acs.manager.manager.enums.BusStsType;
@@ -9,6 +9,8 @@
public interface BusService extends IService<Bus> {
    Bus selectByBusNo(String busNo);
    Bus selectByUuid(String uuid);
    String checkoutValid(OpenBusSubmitParam param);
zy-acs-manager/src/main/java/com/zy/acs/manager/manager/service/IntegrationRecordService.java
New file
@@ -0,0 +1,10 @@
package com.zy.acs.manager.manager.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.zy.acs.manager.manager.entity.IntegrationRecord;
public interface IntegrationRecordService extends IService<IntegrationRecord> {
    Boolean syncRecord(IntegrationRecord record);
}
zy-acs-manager/src/main/java/com/zy/acs/manager/manager/service/TaskService.java
@@ -19,7 +19,7 @@
    Task pick(TaskStsType taskStsType);
    Task selectByUuid(String uuid);
    Task selectBySeqNum(Long busId, String seqNum);
    List<Task> selectBySts(TaskStsType taskStsType);
@@ -27,9 +27,9 @@
    List<Map<String, Object>> selectStatByLastSevenDays();
    Boolean complete(Long taskId, Long userId);
    Boolean complete(Long taskId, Long userId, String from);
    Boolean cancel(Long taskId, Long userId);
    Boolean cancel(Long taskId, Long userId, String from);
    LaneDto checkoutOriginLane(Task task);
zy-acs-manager/src/main/java/com/zy/acs/manager/manager/service/impl/BusServiceImpl.java
@@ -5,8 +5,9 @@
import com.zy.acs.framework.common.BaseRes;
import com.zy.acs.framework.common.Cools;
import com.zy.acs.framework.exception.CoolException;
import com.zy.acs.manager.common.constant.Constants;
import com.zy.acs.manager.common.domain.TaskDto;
import com.zy.acs.manager.manager.controller.param.OpenBusSubmitParam;
import com.zy.acs.manager.core.integrate.dto.OpenBusSubmitParam;
import com.zy.acs.manager.manager.entity.Bus;
import com.zy.acs.manager.manager.entity.Loc;
import com.zy.acs.manager.manager.entity.Task;
@@ -33,6 +34,14 @@
    private LocService locService;
    @Override
    public Bus selectByBusNo(String busNo) {
        if (Cools.isEmpty(busNo)) {
            return null;
        }
        return this.getOne(new LambdaQueryWrapper<Bus>().eq(Bus::getBusNo, busNo).last(Constants.LIMIT_ONE));
    }
    @Override
    public Bus selectByUuid(String uuid) {
        return this.getOne(new LambdaQueryWrapper<Bus>().eq(Bus::getUuid, uuid));
    }
@@ -41,7 +50,7 @@
        if (Cools.isEmpty(param)) {
            return;
        }
        List<TaskDto> taskList = param.getTaskList();
        List<TaskDto> taskList = param.getTasks();
        if (Cools.isEmpty(taskList)) {
            return;
        }
@@ -67,7 +76,7 @@
        if (null == param) {
            return BaseRes.PARAM;
        }
        if (Cools.isEmpty(param.getBatch())) {
        if (Cools.isEmpty(param.getBatchNo())) {
            return "Batch cannot be empty!";
        }
        this.test(param);
@@ -75,7 +84,7 @@
        Set<String> oriLocNoSet = new HashSet<>();
        Set<String> destStaNoSet = new HashSet<>();
        Set<String> destLocNoSet = new HashSet<>();
        for (TaskDto dto : param.getTaskList()) {
        for (TaskDto dto : param.getTasks()) {
            if (!Cools.isEmpty(dto.getOriSta()) && !Cools.isEmpty(dto.getOriLoc())) {
                return "OriSta and OriLoc cannot exist at the same time!";
            }
@@ -119,8 +128,8 @@
                    destLocNoSet.add(dto.getDestLoc());
                }
            }
            if (Cools.isEmpty(dto.getSeqNum())) {
                dto.setSeqNum(taskService.generateSeqNum());
            if (Cools.isEmpty(dto.getTaskNo())) {
                dto.setTaskNo(taskService.generateSeqNum());
            }
        }
zy-acs-manager/src/main/java/com/zy/acs/manager/manager/service/impl/IntegrationRecordServiceImpl.java
New file
@@ -0,0 +1,38 @@
package com.zy.acs.manager.manager.service.impl;
import com.alibaba.fastjson.JSON;
import com.zy.acs.framework.common.R;
import com.zy.acs.manager.core.service.ThreadPoolRegulator;
import com.zy.acs.manager.manager.mapper.IntegrationRecordMapper;
import com.zy.acs.manager.manager.entity.IntegrationRecord;
import com.zy.acs.manager.manager.service.IntegrationRecordService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.concurrent.CompletableFuture;
@Slf4j
@Service("integrationRecordService")
public class IntegrationRecordServiceImpl extends ServiceImpl<IntegrationRecordMapper, IntegrationRecord> implements IntegrationRecordService {
    @Autowired
    private ThreadPoolRegulator threadPoolRegulator;
    @Override
    public Boolean syncRecord(IntegrationRecord record) {
        CompletableFuture<?> completableFuture = CompletableFuture.supplyAsync(() -> {
            if (!this.save(record)) {
                log.error("failed to save record {}", JSON.toJSONString(record));
            }
//            mapDataDispatcher.modifyDynamicMatrix(null, null, param.getAgvNo(), true);
//            avoidWaveCalculator.calcDynamicNodeByVehicle(agv, null);
            return R.ok();
        }, threadPoolRegulator.getInstance());
        return true;
    }
}
zy-acs-manager/src/main/java/com/zy/acs/manager/manager/service/impl/TaskServiceImpl.java
@@ -17,6 +17,7 @@
import com.zy.acs.manager.manager.enums.*;
import com.zy.acs.manager.manager.mapper.TaskMapper;
import com.zy.acs.manager.manager.service.*;
import com.zy.acs.manager.system.service.ConfigService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -50,6 +51,8 @@
    private ActionService actionService;
    @Autowired
    private TravelService travelService;
    @Autowired
    private ConfigService configService;
    @Override
    public PageResult<Task> pageRel(PageParam<Task, BaseParam> pageParam) {
@@ -68,8 +71,16 @@
    }
    @Override
    public Task selectByUuid(String uuid) {
        return this.getOne(new LambdaQueryWrapper<Task>().eq(Task::getUuid, uuid));
    public Task selectBySeqNum(Long busId, String seqNum) {
        if (Cools.isEmpty(seqNum)) {
            return null;
        }
        LambdaQueryWrapper<Task> wrapper = new LambdaQueryWrapper<>();
        if (null != busId) {
            wrapper.eq(Task::getBusId, busId);
        }
        wrapper.eq(Task::getSeqNum, seqNum);
        return this.getOne(wrapper.last(Constants.LIMIT_ONE));
    }
    @Override
@@ -100,7 +111,7 @@
    @Override
    @Transactional
    public Boolean complete(Long taskId, Long userId) {
    public Boolean complete(Long taskId, Long userId, String from) {
        Task task = this.getById(taskId);
        if (null == task) {
            return Boolean.FALSE;
@@ -112,7 +123,7 @@
        task.setTaskSts(TaskStsType.COMPLETE.val());
        task.setUpdateTime(now);
        task.setUpdateBy(userId);
        task.setMemo(Constants.HANDLE + " " + TaskStsType.COMPLETE);
        task.setMemo(from + " " + TaskStsType.COMPLETE);
        if (!this.updateById(task)) {
            throw new CoolException(BaseRes.ERROR);
        }
@@ -141,7 +152,7 @@
    @Override
    @Transactional
    public Boolean cancel(Long taskId, Long userId) {
    public Boolean cancel(Long taskId, Long userId, String from) {
        Task task = this.getById(taskId);
        if (null == task) {
            return Boolean.FALSE;
@@ -153,7 +164,7 @@
        task.setTaskSts(TaskStsType.CANCEL.val());
        task.setUpdateTime(now);
        task.setUpdateBy(userId);
        task.setMemo(Constants.HANDLE + " " + TaskStsType.CANCEL);
        task.setMemo(from + " " + TaskStsType.CANCEL);
        if (!this.updateById(task)) {
            throw new CoolException(BaseRes.ERROR);
        }
@@ -280,6 +291,7 @@
        if (!task.getTaskSts().equals(TaskStsType.COMPLETE.val())) {
            return;
        }
        Boolean maintainLocSts = configService.getVal("maintainLocSts", Boolean.class);
        Date now = new Date();
        // loc status
        Loc oriLoc = null;
@@ -288,31 +300,35 @@
        Sta destSta = null;
        switch (Objects.requireNonNull(TaskTypeType.get(task.getTaskTypeEl()))) {
            case LOC_TO_LOC:
                oriLoc = locService.getById(task.getOriLoc());
                if (oriLoc.getLocSts().equals(LocStsType.PAKOUT.val())) {
                    oriLoc.setLocSts(LocStsType.IDLE.val());
                    oriLoc.setUpdateTime(now);
                    if (!locService.updateById(oriLoc)) {
                        log.error("Loc [{}] åº“位修改状态失败", task.getOriLoc$());
                if (maintainLocSts) {
                    oriLoc = locService.getById(task.getOriLoc());
                    if (oriLoc.getLocSts().equals(LocStsType.PAKOUT.val())) {
                        oriLoc.setLocSts(LocStsType.IDLE.val());
                        oriLoc.setUpdateTime(now);
                        if (!locService.updateById(oriLoc)) {
                            log.error("Loc [{}] åº“位修改状态失败", task.getOriLoc$());
                        }
                    }
                }
                destLoc = locService.getById(task.getDestLoc());
                if (destLoc.getLocSts().equals(LocStsType.PAKIN.val())) {
                    destLoc.setLocSts(LocStsType.STOCK.val());
                    destLoc.setUpdateTime(now);
                    if (!locService.updateById(destLoc)) {
                        log.error("Loc [{}] åº“位修改状态失败", task.getDestLoc$());
                    destLoc = locService.getById(task.getDestLoc());
                    if (destLoc.getLocSts().equals(LocStsType.PAKIN.val())) {
                        destLoc.setLocSts(LocStsType.STOCK.val());
                        destLoc.setUpdateTime(now);
                        if (!locService.updateById(destLoc)) {
                            log.error("Loc [{}] åº“位修改状态失败", task.getDestLoc$());
                        }
                    }
                }
                break;
            case LOC_TO_STA:
                oriLoc = locService.getById(task.getOriLoc());
                if (oriLoc.getLocSts().equals(LocStsType.PAKOUT.val())) {
                    oriLoc.setLocSts(LocStsType.IDLE.val());
                    oriLoc.setUpdateTime(now);
                    if (!locService.updateById(oriLoc)) {
                        log.error("Loc [{}] åº“位修改状态失败", task.getOriLoc$());
                if (maintainLocSts) {
                    oriLoc = locService.getById(task.getOriLoc());
                    if (oriLoc.getLocSts().equals(LocStsType.PAKOUT.val())) {
                        oriLoc.setLocSts(LocStsType.IDLE.val());
                        oriLoc.setUpdateTime(now);
                        if (!locService.updateById(oriLoc)) {
                            log.error("Loc [{}] åº“位修改状态失败", task.getOriLoc$());
                        }
                    }
                }
@@ -323,12 +339,14 @@
                oriSta = staService.getById(task.getOriSta());
                staReserveService.confirmStaReserve(oriSta, task, 1, StaReserveType.OUT);
                destLoc = locService.getById(task.getDestLoc());
                if (destLoc.getLocSts().equals(LocStsType.PAKIN.val())) {
                    destLoc.setLocSts(LocStsType.STOCK.val());
                    destLoc.setUpdateTime(now);
                    if (!locService.updateById(destLoc)) {
                        log.error("Loc [{}] åº“位修改状态失败", task.getDestLoc$());
                if (maintainLocSts) {
                    destLoc = locService.getById(task.getDestLoc());
                    if (destLoc.getLocSts().equals(LocStsType.PAKIN.val())) {
                        destLoc.setLocSts(LocStsType.STOCK.val());
                        destLoc.setUpdateTime(now);
                        if (!locService.updateById(destLoc)) {
                            log.error("Loc [{}] åº“位修改状态失败", task.getDestLoc$());
                        }
                    }
                }
                break;
@@ -353,31 +371,36 @@
    public void maintainLocAndStaHandler(Task task, Boolean complete) {
        Loc oriLoc = null; Loc destLoc = null;
        Sta oriSta = null; Sta destSta = null;
        Boolean maintainLocSts = configService.getVal("maintainLocSts", Boolean.class);
        Date now = new Date();
        TaskTypeType typeType = TaskTypeType.get(task.getTaskTypeEl());
        switch (Objects.requireNonNull(typeType)) {
            case LOC_TO_LOC:
                oriLoc = locService.getById(task.getOriLoc());
                destLoc = locService.getById(task.getDestLoc());
                if (maintainLocSts) {
                    oriLoc = locService.getById(task.getOriLoc());
                    destLoc = locService.getById(task.getDestLoc());
                oriLoc.setLocSts(complete?LocStsType.IDLE.val():LocStsType.STOCK.val());
                oriLoc.setUpdateTime(now);
                if (!locService.updateById(oriLoc)) {
                    throw new BusinessException("Loc [" + oriLoc.getLocNo() + "] åº“位修改状态失败 ï¼ï¼ï¼");
                }
                    oriLoc.setLocSts(complete?LocStsType.IDLE.val():LocStsType.STOCK.val());
                    oriLoc.setUpdateTime(now);
                    if (!locService.updateById(oriLoc)) {
                        throw new BusinessException("Loc [" + oriLoc.getLocNo() + "] åº“位修改状态失败 ï¼ï¼ï¼");
                    }
                destLoc.setLocSts(complete?LocStsType.STOCK.val():LocStsType.IDLE.val());
                destLoc.setUpdateTime(now);
                if (!locService.updateById(destLoc)) {
                    throw new BusinessException("Loc [" + destLoc.getLocNo() + "] åº“位修改状态失败 ï¼ï¼ï¼");
                    destLoc.setLocSts(complete?LocStsType.STOCK.val():LocStsType.IDLE.val());
                    destLoc.setUpdateTime(now);
                    if (!locService.updateById(destLoc)) {
                        throw new BusinessException("Loc [" + destLoc.getLocNo() + "] åº“位修改状态失败 ï¼ï¼ï¼");
                    }
                }
                break;
            case LOC_TO_STA:
                oriLoc = locService.getById(task.getOriLoc());
                oriLoc.setLocSts(complete?LocStsType.IDLE.val():LocStsType.STOCK.val());
                oriLoc.setUpdateTime(now);
                if (!locService.updateById(oriLoc)) {
                    throw new BusinessException("Loc [" + oriLoc.getLocNo() + "] åº“位修改状态失败 ï¼ï¼ï¼");
                if (maintainLocSts) {
                    oriLoc = locService.getById(task.getOriLoc());
                    oriLoc.setLocSts(complete?LocStsType.IDLE.val():LocStsType.STOCK.val());
                    oriLoc.setUpdateTime(now);
                    if (!locService.updateById(oriLoc)) {
                        throw new BusinessException("Loc [" + oriLoc.getLocNo() + "] åº“位修改状态失败 ï¼ï¼ï¼");
                    }
                }
                destSta = staService.getById(task.getDestSta());
@@ -395,11 +418,13 @@
                    staReserveService.cancelStaReserve(oriSta, task, 1, StaReserveType.OUT);
                }
                destLoc = locService.getById(task.getDestLoc());
                destLoc.setLocSts(complete?LocStsType.STOCK.val():LocStsType.IDLE.val());
                destLoc.setUpdateTime(now);
                if (!locService.updateById(destLoc)) {
                    throw new BusinessException("Loc [" + destLoc.getLocNo() + "] åº“位修改状态失败 ï¼ï¼ï¼");
                if (maintainLocSts) {
                    destLoc = locService.getById(task.getDestLoc());
                    destLoc.setLocSts(complete?LocStsType.STOCK.val():LocStsType.IDLE.val());
                    destLoc.setUpdateTime(now);
                    if (!locService.updateById(destLoc)) {
                        throw new BusinessException("Loc [" + destLoc.getLocNo() + "] åº“位修改状态失败 ï¼ï¼ï¼");
                    }
                }
                break;
            case STA_TO_STA:
zy-acs-manager/src/main/java/integrationRecord.sql
New file
@@ -0,0 +1,7 @@
-- save integrationRecord record
-- mysql
-- SwapHorizontalCircle
insert into `sys_menu` ( `name`, `parent_id`, `route`, `component`, `type`, `sort`, `tenant_id`, `status`) values ( 'menu.integrationRecord', '0', '/manager/integrationRecord', 'integrationRecord', '0' , '5', '1' , '1');
insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Query Integration Record', '', '1', 'manager:integrationRecord:list', '0', '1', '1');
insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Delete Integration Record', '', '1', 'manager:integrationRecord:remove', '3', '1', '1');
zy-acs-manager/src/main/resources/application.yml
@@ -53,6 +53,15 @@
convey-plc:
  host: 10.10.10.222
  port: 9090
  timeout: 15000
  url: /cv/station/query
uplink:
  enabled: true
  host: 10.10.10.251
  port: 8082
  timeout: 30000
  url: /rsf-open-api/rcs/api/open/task/report
floyd:
  enable: false
zy-acs-manager/src/main/resources/mapper/manager/IntegrationRecordMapper.xml
New file
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zy.acs.manager.manager.mapper.IntegrationRecordMapper">
</mapper>
zy-acs-manager/src/main/resources/mapper/manager/TaskMapper.xml
@@ -50,6 +50,9 @@
            <if test="param.timeEnd != null">
                and a.create_time &lt; #{param.timeEnd}
            </if>
            <if test="param.uplinkSts != null">
                AND a.uplink_sts = #{param.uplinkSts}
            </if>
            <if test="param.keywords != null">
                AND (
                a.memo LIKE CONCAT('%', #{param.keywords}, '%')