ZengTao
2024-10-16 3a38edcb5e9c15a9591e1e913d3583f3d437caf1
Merge remote-tracking branch '公司服务器/master'

# Conflicts:
# hangzhoumesParent/moduleService/CacheVerticalGlassModule/src/main/java/com/mes/job/PlcStorageCageTask.java
47个文件已修改
2 文件已重命名
16个文件已添加
21个文件已删除
5679 ■■■■■ 已修改文件
README.md 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UI-Project/package-lock.json 28 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UI-Project/package.json 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
UI-Project/src/lang/en.js 858 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UI-Project/src/lang/index.js 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UI-Project/src/lang/py.js 300 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UI-Project/src/lang/zh.js 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UI-Project/src/layout/MainErpView.vue 139 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UI-Project/src/router/index.js 26 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UI-Project/src/views/LoginView.vue 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UI-Project/src/views/NewPage.vue 151 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UI-Project/src/views/PurchaseReturn/purchaseReturn.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
UI-Project/src/views/Returns/return.vue 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UI-Project/src/views/Returns/returns.vue 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UI-Project/src/views/Returns/upreturns.vue 1115 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UI-Project/src/views/Slicecage/slicecage.vue 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UI-Project/src/views/UnLoadGlass/PrintCustomLabelSemi1.vue 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UI-Project/src/views/UnLoadGlass/loadmachinerack.vue 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/opcuaClient/pom.xml 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/configuration/MiloProperties.java 85 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/exception/EndPointNotFoundException.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/exception/IdentityNotFoundException.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/model/ReadWriteEntity.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/model/WriteEntity.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/pool/MiloConnectPool.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/runner/BrowseNodeRunner.java 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/runner/BrowseRunner.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/runner/ReadValuesRunner.java 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/runner/WriteValuesRunner.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/runner/subscription/SubscriptionCallback.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/runner/subscription/SubscriptionRunner.java 111 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/service/MiloService.java 553 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/utils/CustomUtil.java 114 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/utils/KeyStoreLoader.java 123 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/opcuaClient/src/main/resources/META-INF/spring.factories 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/opcuaClient/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/opcuaClient/src/main/resources/application.yml 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/pom.xml 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/servicebase/pom.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/servicebase/src/main/java/com/kangaroohy/milo/configuration/MiloAutoConfiguration.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/servicebase/src/main/java/com/kangaroohy/milo/pool/MiloConnectFactory.java 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/servicebase/src/main/java/com/mes/common/config/Const.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/servicebase/src/main/java/com/mes/pp/entity/OptimizeHeatDetail.java 116 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/servicebase/src/main/java/com/mes/pp/entity/OptimizeHeatLayout.java 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/servicebase/src/main/java/com/mes/pp/mapper/OptimizeHeatDetailMapper.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/servicebase/src/main/java/com/mes/pp/mapper/OptimizeHeatLayoutMapper.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/servicebase/src/main/java/com/mes/pp/service/OptimizeHeatDetailService.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/servicebase/src/main/java/com/mes/pp/service/OptimizeHeatLayoutService.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/servicebase/src/main/java/com/mes/pp/service/impl/OptimizeHeatDetailServiceImpl.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/servicebase/src/main/java/com/mes/pp/service/impl/OptimizeHeatLayoutServiceImpl.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/servicebase/src/main/java/com/mes/temperingglass/service/impl/TemperingGlassInfoServiceImpl.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/servicebase/src/main/java/com/mes/uppattenusage/entity/vo/UpPattenUsageVO.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/servicebase/src/main/java/com/mes/uppattenusage/mapper/UpPattenUsageMapper.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/servicebase/src/main/resources/mapper/FlowCardMapper.xml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/common/servicebase/src/main/resources/mapper/UpPattenUsageMapper.xml 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/CacheGlassModule/src/main/java/com/mes/edgstoragecage/service/EdgStorageCageDetailsService.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/CacheGlassModule/src/main/java/com/mes/edgstoragecage/service/impl/EdgStorageCageDetailsServiceImpl.java 100 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/CacheGlassModule/src/main/java/com/mes/job/CacheGlassTask.java 233 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/CacheGlassModule/src/main/java/com/mes/job/OpcCacheGlassTask.java 22 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/CacheGlassModule/src/main/java/com/mes/opccallback/CacheGlassSubscriptionCallback.java 33 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/CacheGlassModule/src/main/java/com/mes/taskcache/controller/TaskCacheController.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/CacheGlassModule/src/main/resources/application.yml 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/CacheGlassModule/src/test/java/com/mes/CacheGlassModuleApplicationTest.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/CacheVerticalGlassModule/src/main/java/com/mes/bigstorage/controller/BigStorageCageDetailsController.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/CacheVerticalGlassModule/src/main/java/com/mes/bigstorage/service/BigStorageCageDetailsService.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/CacheVerticalGlassModule/src/main/java/com/mes/bigstorage/service/impl/BigStorageCageDetailsServiceImpl.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/CacheVerticalGlassModule/src/main/java/com/mes/job/PlcStorageCageTask.java 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/CacheVerticalGlassModule/src/test/java/com/mes/CacheVerticalGlassModuleApplicationTest.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/GlassStorageModule/src/main/java/com/mes/job/RawGlassPushMessage.java 72 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/GlassStorageModule/src/main/java/com/mes/job/RawGlassTask.java 235 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/GlassStorageModule/src/main/java/com/mes/rawglassdetails/entity/RawGlassStorageDetails.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/GlassStorageModule/src/main/java/com/mes/rawglassdetails/mapper/RawGlassStorageDetailsMapper.java 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/GlassStorageModule/src/main/java/com/mes/rawglassdetails/mapper/xml/RawGlassStorageDetailsMapper.xml 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/GlassStorageModule/src/main/java/com/mes/rawglassdetails/service/RawGlassStorageDetailsService.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/GlassStorageModule/src/main/java/com/mes/rawglassdetails/service/impl/RawGlassStorageDetailsServiceImpl.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/GlassStorageModule/src/main/java/com/mes/rawglasstask/entity/RawGlassStorageTask.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/TemperingGlassModule/src/main/java/com/mes/job/TemperingTask.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/TemperingGlassModule/src/main/resources/application-dev.yml 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/TemperingGlassModule/src/main/resources/application.yml 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/TemperingGlassModule/src/main/resources/changelog/changelog.sql 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/UnLoadGlassModule/src/main/java/com/mes/downglassinfo/service/impl/DownGlassInfoServiceImpl.java 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/UnLoadGlassModule/src/main/java/com/mes/job/DownLoadCacheGlassTask.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/UnLoadGlassModule/src/main/resources/application.yml 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/moduleService/pom.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
hangzhoumesParent/readMe-OPC.md 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pom.xml 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
README.md
@@ -37,3 +37,4 @@
4.  [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目
5.  Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help)
6.  Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
UI-Project/package-lock.json
@@ -26,7 +26,7 @@
        "vue-echarts": "^6.7.3",
        "vue-i18n": "^9.10.1",
        "vue-print-nb": "^1.7.5",
        "vue-router": "^4.2.4",
        "vue-router": "^4.0.13",
        "vue3-print-nb": "^0.1.4",
        "vxe-table": "^4.5.15",
        "xe-utils": "^3.5.14",
@@ -2036,11 +2036,11 @@
      }
    },
    "node_modules/vue-router": {
      "version": "4.2.5",
      "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.2.5.tgz",
      "integrity": "sha512-DIUpKcyg4+PTQKfFPX88UWhlagBEBEfJ5A8XDXRJLUnZOvcpMF8o/dnL90vpVkGaPbjvXazV/rC1qBKrZlFugw==",
      "version": "4.0.13",
      "resolved": "https://registry.npmmirror.com/vue-router/-/vue-router-4.0.13.tgz",
      "integrity": "sha512-LmXrC+BkDRLak+d5xTMgUYraT3Nj0H/vCbP+7usGvIl9Viqd1UP6AsP0i69pSbn9O0dXK/xCdp4yPw21HqV9Jw==",
      "dependencies": {
        "@vue/devtools-api": "^6.5.0"
        "@vue/devtools-api": "^6.0.0"
      },
      "funding": {
        "url": "https://github.com/sponsors/posva"
@@ -3154,7 +3154,7 @@
        "vue-echarts": "^6.7.3",
        "vue-i18n": "^9.10.1",
        "vue-print-nb": "^1.7.5",
        "vue-router": "^4.2.4",
        "vue-router": "4.0.13",
        "vue3-print-nb": "^0.1.4",
        "vxe-table": "^4.5.15",
        "xe-utils": "^3.5.14",
@@ -4536,11 +4536,11 @@
          }
        },
        "vue-router": {
          "version": "4.2.5",
          "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.2.5.tgz",
          "integrity": "sha512-DIUpKcyg4+PTQKfFPX88UWhlagBEBEfJ5A8XDXRJLUnZOvcpMF8o/dnL90vpVkGaPbjvXazV/rC1qBKrZlFugw==",
          "version": "4.0.13",
          "resolved": "https://registry.npmmirror.com/vue-router/-/vue-router-4.0.13.tgz",
          "integrity": "sha512-LmXrC+BkDRLak+d5xTMgUYraT3Nj0H/vCbP+7usGvIl9Viqd1UP6AsP0i69pSbn9O0dXK/xCdp4yPw21HqV9Jw==",
          "requires": {
            "@vue/devtools-api": "^6.5.0"
            "@vue/devtools-api": "^6.0.0"
          }
        },
        "vue3-print-nb": {
@@ -5093,11 +5093,11 @@
      }
    },
    "vue-router": {
      "version": "4.2.5",
      "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.2.5.tgz",
      "integrity": "sha512-DIUpKcyg4+PTQKfFPX88UWhlagBEBEfJ5A8XDXRJLUnZOvcpMF8o/dnL90vpVkGaPbjvXazV/rC1qBKrZlFugw==",
      "version": "4.0.13",
      "resolved": "https://registry.npmmirror.com/vue-router/-/vue-router-4.0.13.tgz",
      "integrity": "sha512-LmXrC+BkDRLak+d5xTMgUYraT3Nj0H/vCbP+7usGvIl9Viqd1UP6AsP0i69pSbn9O0dXK/xCdp4yPw21HqV9Jw==",
      "requires": {
        "@vue/devtools-api": "^6.5.0"
        "@vue/devtools-api": "^6.0.0"
      }
    },
    "vue3-print-nb": {
UI-Project/package.json
@@ -26,7 +26,7 @@
    "vue-echarts": "^6.7.3",
    "vue-i18n": "^9.10.1",
    "vue-print-nb": "^1.7.5",
    "vue-router": "^4.2.4",
    "vue-router": "^4.0.13",
    "vue3-print-nb": "^0.1.4",
    "vxe-table": "^4.5.15",
    "xe-utils": "^3.5.14",
UI-Project/src/lang/en.js
@@ -1,300 +1,586 @@
export  default {
    "northglassMESsystem": 'Система "NorthGlass MES"' ,
      login:{
          userErr:'Введите номер счета.',
          pwErr:'Введите пароль.',
          user:'Аккаунт',
          password:'Код',
          login:'Залогин',
          loginSuccessful:'Вход в систему выполнен успешно!',
          register:'Зарегистрирова',
          namea:'Имя не может быть пустым',
          len:'Длина не должна превышать 16',
          passnull:'Пароль не может быть пустым',
          leng:'Длина пароля не должна быть меньше 6 или больше 16.',
          spwn:'Пароль подтверждения не может быть пустым',
          depass:'Два разных пароля.',
      },
      register:{
          registerSuccessful:'Регистрация успешно',
          newuserregister:'Новый реестр пользователей',
          name:'Имя:',
          inputname:'Введите имя',
          password:'Код:',
          pwErr:'Введите пароль.',
          passwordation:'Подтвердите пароль:',
          pwErration:'Пожалуйста, подтвертите пароль',
          registration:'Подтверждение о регистрации',
          false:'Отмена',
      },
      main:{
          connectErr:'Необычное подключение к серверу, попробуйте позже',
          titleFirst:"Добро пожаловать ",
          titleLast:' в систему NorthGlass MES!',
          quit:"Выход",
      },
      basicData:{
          deletemessage:'Удалить эту информацию или нет?',
          laserprinting:'Машина лазерной маркировки готова:',
          cuttingmachine:'Машина для резки готова:',
          machine:'Состояние станок загрузки в режиме онлайн:',
          machineaa:'Ручное состояние станок загрузки:',
          selectproject:"Выберите проект",
          startloading:'Начало загрузки',
          stop:'Пауза',
          yes:'подтверд',
          change:'переключа',
          projectnumber:'Номер проекта',
          glasswidth:'Ширина стекла',
          glassheight:'Высота стекла',
          coatingtypes:'Типы покрытий',
          coatingtypesa:'Типы покрытий:',
          quantity:'Количество',
          quantitya:'Количество:',
          thickness:'Толщина',
          thicknessa:'Толщина:',
          startstatus:'Статус начала операции',
          pass:'Через',
          waiting:'Ждем.',
          up:'Загрузка',
          finish:'Завершено',
          project:'инженерия',
          plselectproject:'Пожалуйста, выберите проект.',
          confirm:'подтверд',
          cancel:'Отмена',
          startfilm:'Начинать или нет?',
          whetherpause:'Пауза или нет?',
          station:'Рабочее место',
          width:'Ширина',
          widtha:'Ширина:',
          height:'Высота',
          heighta:'Высота:',
          operate:'Операция',
          add:'Добавля',
          delete:'Удал',
          addglass:'Добавить стекло',
          selectwidth:'Выбирите ширину',
          selectheight:'Выбирите высоту',
          selectcoatingtypes:'Выберите типы покрытий',
          selectthickness:'Выберите толщину',
          selectquantity:'Введите кольчество.',
          pause:'Вторая и четвертая строки должны быть выше 2700 для сохранения!',
          pausea:'Пожалуйста, убедитесь, что маркировочная и режущая машины готовы!',
          infonull:'Номер проекта не может быть пустым!',
          updatanull:'Проект не сохранились на листе загрузки!',
          glassnull:'Ошибка при обновлении стекла',
      },
      sorter:{
          gridnumber:'Ячеек сеткла',
          glassnumber:'Номер стакла',
          width:'Ширина',
          height:'Высота',
          startstatus:'Статус начала операции',
          disable:'Отключ',
          start:'Начало',
          deficiencieste:'Недостатки в отчетности',
          operate:'Операция',
          prompt:'Подсказк',
          information:'Следует ли сообщать недостающую информацию?',
          yes:'Да',
          cancel:'Отмена',
      },
      order:{
          dilapidation:'Повреждение',
          Takeaway:'Взять вручную',
      },
      searchOrder:{
        cageinformation:'Информация буфера',
        productionqueue:'Производственная очередь',
        outputglassID:'Выходное стекло ID',
        startposition:'Занять позиции',
        targetlocation:'Позиция цели',
        trips:'№ поезда',
        number:'Серийн номер',
        taskstatus:'Состояние задачи',
        filmenter:'Ожидание стеклянной вход',
        infilm:'В настоящее время',
        endtask:'Задача на конец',
        completetask:'Выполнение задания',
        intoglassid:'Входной стеклянный ID',
        line:'Линия',
        Usage:'Скорость использования',
        free:'Бесплатно (ячеек)',
        addcage:'Добавить информацию о буфере',
        glassIDa:'Стеклянный ID:',
        glassID:'Стеклянный ID',
        inglassID:'Введите стекло ID',
        pieceingrid:'Порядок расположения маленьких стеклянных пластин в клетке',
        pieceingrida:'Порядок расположения маленьких стеклянных пластин в клетке:',
        inpieceingrid:'Введите порядок расположения стеклянных листов в ячееке',
        cardnumber:'Номер карточки процесса',
        cardnumbera:'Номер карточки процесса:',
        incardnumber:'Введите номер процесса .',
        typeglass:'Тип стекла',
        typeglassa:'Тип стекла:',
        intypeglass:'Введите тип стекла',
        coatingtypes:'Типы покрытий',
        width:'Ширина',
        widtha:'Ширина:',
        inwidth:'Введите ширину',
        height:'Высота',
        heighta:'Высота:',
        inheight:'Введите высоту',
        thickness:'Толщина',
        thicknessa:'Толщина:',
        inthickness:'Введите толщину.',
        layoutID:'Чертеж ID загрузки печи для закалки',
        layoutIDa:'Чертеж ID загрузки печи для закалки:',
        inlayoutID:'Введите чертеж закалки ID',
        picturesequence:'Чертеж серийн номер загрузки печи для закалки',
        picturesequencea:'Чертеж серийн номер загрузки печи для закалки:',
        inpicturesequence:'Введите порядок чертежи закалки стекла.',
        startstatus:'Статус начала операции',
        startstatusa:'Статус начала операции:',
        instartstatus:'Введите состояние активации',
        glassgaps:'Стеклянный зазор',
        glassgapsa:'Стеклянный зазор:',
        inglassgaps:'Введите стекло зазор',
        sure:'подтверд',
        cancel:'Отмена',
        operate:'Операция',
        breakage:'Повреждение',
        delete:'Удал',
        outfilm:'Выпуск стекла',
        cagetableID:'ID буферной таблицы',
        cagenumber:'Буфер номера',
        gridnumber:'Ячеек сеткла',
        enable:'Начало',
        disable:'Отключ',
        remainingwidth:'Остаточная ширина',
        add:'Добавля',
        sheetID:'Закалка маленький стеклянный ID таблицы информации',
        processcards:'Карточка процесса',
        processcardtype:'Тип стекла карточки процесса',
        acceptshorizontal:'Умеренное принятие горизонтали',
        xcoordinates:'X-координаты',
        ycoordinates:'Y-координаты',
        rotationangle:'Угол вращения (против часовой стрелки)',
        state:'Состояние',
        takeout:'Взять',
        deletemessage:'Удалить эту информацию или нет?',
        prompt:'Подсказк',
        yes:'Да',
        accept:'Принять',
        noaccept:'Не принимать',
        filmcomplete:'Стекло готово',
        waiting:'Ждем.',
  "northglassMESsystem": "NorthGlass MES System",
    login:{
        userErr:'Please enter account number',
        pwErr:'Please input a password',
        user:'Account number',
        password:'Password',
        login:'Log on',
        loginSuccessful:'Log on was successful!',
        register:'Register',
        namea:'Name cannot be empty',
        len:'The length cannot exceed 16',
        passnull:'Password cannot be empty',
        leng:'The password length cannot be less than 6 or more than 16',
        spwn:'Confirm password cannot be empty',
        depass:'The two passwords are not the same',
    },
    register:{
        registerSuccessful:'login was successful',
        newuserregister:'New user register',
        name:'Full name:',
        inputname:'Please enter your name',
        password:'Password:',
        pwErr:'Please input a password',
        passwordation:'Confirm password:',
        pwErration:'Please confirm password',
        registration:'Registration Confirm',
        false:'Cancel',
    },
    main:{
        connectErr:'The server connection is abnormal. Please try again later',
        titleFirst:"Welcome ",
        titleLast:' to use NorthGlass MES system!',
        quit:"Exit",
    },
    basicData:{
        laserprinting:'Laser printing machine ready status:',
        cuttingmachine:'Cutting machine ready status:',
        machine:'Online status of the loading table:',
        machineaa:'Manual state of the loading table:',
        selectproject:"Select project",
        startloading:'Start loading',
        stop:'Pause',
        yes:'Confirm',
        change:'Switch',
        projectnumber:'Project number',
        glasswidth:'Glass width',
        glassheight:'Glass height',
        coatingtypes:'Coating types',
        coatingtypesa:'Coating types:',
        quantity:'Quantity',
        quantitya:'Quantity:',
        thickness:'Thickness',
        thicknessa:'Thickness:',
        startstatus:'Start status',
        pass:'Pass',
        waiting:'Waiting',
        up:'Loading',
        finish:'Completed',
        project:'Project ',
        plselectproject:'Please select project',
        confirm:'Confirm',
        cancel:'Cancel',
        startfilm:'Whether start loading?',
        whetherpause:'Whether pause?',
        station:'Station',
        width:'Width',
        widtha:'Width:',
        height:'Height',
        heighta:'Height:',
        operate:'Operate',
        add:'Increase',
        delete:'Delete',
        addglass:'Add glass',
        selectwidth:'Please select width',
        selectheight:'Please select high',
        selectcoatingtypes:'Please select the coating types',
        selectthickness:'Please select thickness',
        selectquantity:'Please enter the quantity',
        pause:'The height of the second and fourth rows must be greater than 2700 in order to save!',
        pausea:'Please confirm the ready status of marking machine and cutting machine!',
        infonull:'Project number cannot be empty!',
        updatanull:'This project has not been saved to the loading list!',
        glassnull:'An error occurred while updating the glass status',
        deletemessage:'Do you want to delete this message?',
        layoutSequence:'Serial Number',
    },
    sorter:{
        gridnumber:'Grid number',
        glassnumber:'Glass number',
        width:'Width',
        height:'Height',
        startstatus:'Start status',
        disable:'Disabled',
        start:'Enabled',
        deficiencieste:'Report deficiencies',
        updown:'Artificial filming',
        operate:'Operate',
        prompt:'Prompt',
        information:'Is the missing information reported?',
        infor:'Whether to manually download this information?',
        yes:'Yes',
        cancel:'Cancel',
    },
    order:{
        dilapidation:'Breakage',
        takeaway:'Manual removal',
        takeon:'The arrangement is complete',
    },
    searchOrder:{
        cageinformation:'Sorter information',
        productionqueue:'Production queue',
        outputglassID:'Output glass ID',
        startposition:'Start position',
        targetlocation:'Target Position',
        trips:'Train number',
        number:'Serial Number',
        taskstatus:'Task state',
        filmenter:'Waiting for input glass',
        infilm:'In progress',
        endtask:'End task',
        completetask:'Complete the task',
        intoglassid:'Input glass ID',
        line:'Wire',
        Usage:'Usage rate',
        free:'Free(pieces)',
        addcage:'Add information on sorter',
        glassIDa:'Glass ID:',
        glassID:'Glass ID',
        inglassID:'Please enter the glass ID',
        pieceingrid:'The order of small pieces within the grid',
        pieceingrida:'The order of small pieces within the grid:',
        inpieceingrid:'Please enter the order of small pieces within the grid',
        cardnumber:'Process card number',
        cardnumbera:'Process card number:',
        incardnumber:'Please enter the process card number',
        typeglass:'Glass type',
        typeglassa:'Glass type:',
        intypeglass:'Please enter the glass type',
        width:'Width',
        widtha:'Width:',
        inwidth:'Please enter width',
        height:'Height',
        heighta:'Height:',
        inheight:'Please enter height',
        coatingtypes:'Coating types',
        thickness:'Thickness',
        thicknessa:'Thickness:',
        inthickness:'Please enter the thickness',
        layoutID:'Drawing ID of loading for tempering furnace',
        layoutIDa:'Drawing ID of loading for tempering furnace:',
        inlayoutID:'Please enter the drawing ID of loading for tempering furnace',
        picturesequence:'Drawing sequence of loading for tempering furnace',
        picturesequencea:'Drawing sequence of loading for tempering furnace:',
        inpicturesequence:'Please enter the drawing sequence of loading for tempering furnace',
        startstatus:'Start status',
        startstatusa:'Start status:',
        instartstatus:'Please enter the enabled status',
        glassgaps:'Glass gap',
        glassgapsa:'Glass gap:',
        inglassgaps:'Please enter the glass gap',
        sure:'Confirm',
        cancel:'Cancel',
        operate:'Operate',
        breakage:'Breakage',
        delete:'Delete',
        outfilm:'Output glass',
        cagetableID:'Sorter table ID',
        cagenumber:'Sorter number',
        gridnumber:'Grid number',
        gridnumbera:'Grid number:',
        grid:'Please enter a grid number',
        enable:'Enabled',
        disable:'Disabled',
        remainingwidth:'Remaining width',
        add:'Add',
        sheetID:'Tempered small piece information table ID',
        processcards:'Process card',
        processcardtype:'Process card glass type',
        acceptshorizontal:'Does tempering accept horizontal placement',
        xcoordinates:'x coordinate',
        ycoordinates:'Y coordinate',
        rotationangle:'Rotation angle (counterclockwise)',
        state:'Status',
        takeout:'Take away',
        deletemessage:'Do you want to delete this message?',
        prompt:'Prompt',
        yes:'Yes',
        accept:'Accept',
        noaccept:'Not accept',
        filmcomplete:'Glass output completed',
        waiting:'Waiting',
        broke:'Is this information damaged?',
        brokeb:'Do you need to delete the message?',
        outfil:'Whether the film is released or not?',
        inputid:'Please enter the glass ID',
        search:'Search',
        tabid:'Dali film cage details table ID',
        tid:'Device ID',
        tida:'Device ID:',
        fin:'Whether or not the task was completed?',
        sureadd:'Confirm the addition',
        sureadda:'Whether to confirm the addition?',
        zailong:'In a cage',
        rengongxp:'Artificial filming',
        up:'Previous',
        down:'Next',
        now:'The current page is displayed',
        tit:'data',
        temperingqueries:'Tempering queries',
        specifytempering:'Specify a furnace',
        specifyengineerid:'Specify the project',
        projectnumber:'Project number',
        layoutnumber:'Drawing number of loading for tempering furnace',
        numberglasses:'Number of glasses',
        specifytemperinga:'Whether to specify the tempering of this information?',
        temperedswitch:'Tempered switch',
        dutyinformation:'Duty information',
        process:'Process',
        team:'Team',
        basic:'equipment',
        makesure:'Confirm the save',
        // cancel:'取消',
        temperingtotal:'Number of tempering furnaces:',
        glasstotal:'Total number of glasses:',
    },
    workOrder:{
        glassID:'Стеклянный ID',
        height:'Высота',
        width:'Ширина',
        thickness:'Толщина',
        coatingtypes:'Типы покрытий',
        productionsequence:'Последовательность производства',
        cardnumber:'Номер карточки процесса',
        operate:'Операция',
        messagedamaged:'Повреждено ли сообщение?',
        prompt:'Подсказк',
        yes:'Да',
        cancel:'Отмена',
        takemessage:'Следует ли удалять сообщение?',
        breakage:'Повреждение',
        takeout:'Взять',
        glassID:'Glass ID',
        height:'Height',
        width:'Width',
        thickness:'Thickness',
        coatingtypes:'Coating types',
        productionsequence:'Production sequence',
        cardnumber:'Process card number',
        operate:'Operate',
        messagedamaged:'Is this information damaged?',
        prompt:'Prompt',
        yes:'Yes',
        cancel:'Cancel',
        takemessage:'Do you need to delete the message?',
        breakage:'Breakage',
        takeout:'Take away',
        glasstype:'Glass type',
        line:'Wire',
        status:'Status',
    },
    processCard:{
        intofurnace:'В печь',
        beforefurnace:'До печки.',
        outfurnace:'Окончено стекло из печи для закалки',
        intofurnace:'Entering the furnace',
        beforefurnace:'Before entering the furnace',
        outfurnace:'Glass finished from tempering furnace',
        print:'Take away the print',
        printing:'print',
        projectnumber:'Please enter the project number',
        inquire:'Inquire',
        project:'Project number',
        awayprocess:'Take away the process',
        awayequipment:'Take away the equipment',
        awayteam:'Take away the crew',
        flowcard:'Process card',
        layer:'Layer number',
        temperinglayout:'Heat number',
        temperingfeed:'Preface',
        width:'Width',
        height:'Height',
        thickness:'Thickness',
        glasstakeout:'Glass take away list',
        layoutID:'Drawing ID of loading for tempering furnace',
        glassID:'Glass ID',
    },
    reportWork:{
        lowerbit:'Станция разгрузки',
        shelfnumber:'Номер стойки регистрации',
        cardnumber:'Номер карточки процесса',
        totalquantity:'Общее количество',
        beendropped:'Количество стекла разгрузки',
        state:'Состояние',
        devicenumber:'Номер оборудования.',
        startstatus:'Статус начала операции',
        enable:'Начало',
        unenable:'Не начат',
        operate:'Операция',
        bindingshelves:'Назначенная стеллажка',
        clear:'Чисто.',
        workstation:'Станция номер',
        cardnumbera:'Номер карточки процесса:',
        incardnumber:'Пожалуйста, выберите номер программы',
        clearglass:'Очистить стекло с полки',
        sure:'подтверд',
        cancel:'Отмена',
        glassinformation:'Информация стекла',
        glassID:'Стеклянный ID',
        coatingtypes:'Типы покрытий',
        thickness:'Толщина',
        width:'Ширина',
        height:'Высота',
        lowerbit:'Unloading station',
        shelfnumber:'Rack number',
        cardnumber:'Process card number',
        totalquantity:'Total quantity',
        beendropped:'Quantity of unloaded glass',
        state:'Status',
        devicenumber:'Equipment No.',
        startstatus:'Start status',
        enable:'Start',
        unenable:'Unstart',
        operate:'Operate',
        bindingshelves:'Assigned rack',
        clear:'Clear',
        workstation:'Station No.',
        shelfnumbera:'Rack number:',
        cardnumbera:'Process card number:',
        incardnumber:'Please select the process card number',
        clearglass:'Clear the glass on the shelf',
        sure:'Operate',
        cancel:'Cancel',
        glassinformation:'Glass information',
        glassID:'Glass ID',
        coatingtypes:'Coating types',
        thickness:'Thickness',
        width:'Width',
        height:'Height',
    },
    productStock:{
        addusers:'Добавьте пользователей.',
        username:'Имя пользователя.',
        usernamea:'Имя пользователя.:',
        inusername:'Введите имя пользователя',
        role:'Роль',
        rolea:'Роль:',
        inrole:'Выберите роль',
        test:'Тест',
        admin:'Администратор.',
        operate:'Операция',
        resetpassword:'Сбросить пароль',
        exit:'Редактор',
        delete:'Удал',
        prompt:'Подсказк',
        repassword:'Перезагрузка пользовательского пароля или нет?',
        yes:'Да',
        cancel:'Отмена',
        reusername:'Изменение пользователя',
        addusername:'Добавьте пользователей.',
        password:'Код:',
        sure:'подтверд',
        inpassword:'Введите пароль.',
        deusername:'Удаление пользователя или нет?',
        addusers:'Add user',
        username:'User name',
        usernamea:'User name:',
        inusername:'Enter one user name',
        role:'Role',
        rolea:'Role:',
        inrole:'Please select a role',
        test:'Test',
        admin:'Administrator',
        operate:'Operate',
        resetpassword:'Reset password',
        exit:'Edit',
        delete:'Delete',
        prompt:'Prompt',
        repassword:'Do you want to reset the user password?',
        yes:'Yes',
        cancel:'Cancel',
        reusername:'Modify Users',
        addusername:'Add user',
        password:'Password:',
        sure:'Confirm',
        inpassword:'Please input a password',
        deusername:'Do you want to delete the user?',
    },
    customer:{
        addmenu:'Добавьте меню.',
        firstmenu:'Таблица меню первой степени',
        link:'Ссылк',
        linka:'Ссылк:',
        inlink:'Введите ссылку',
        sort:'Сортировк',
        sorta:'Сортировк:',
        insort:'Введите сортировку',
        operate:'Операция',
        exit:'Редактор',
        inmenu:'Введите меню',
        delete:'Удал',
        semenu:'Таблица меню второй степени',
        menu:'Меню.:',
        sure:'подтверд',
        cancel:'Отмена',
        exmene:'Изменение меню.',
        yes:'Да',
        demenu:'Удалить меню или нет?',
        prompt:'Подсказк',
        addmenua:'Add secondary menus',
        addmenu:'Add a first-level menu',
        firstmenu:'First level menu bar',
        firstmenuname:'The name of the first-level menu:',
        link:'Link',
        inlink:'Please enter the link',
        linka:'Link:',
        sort:'Sort',
        insort:'Please enter sorting',
        sorta:'Sort:',
        operate:'Operate',
        exit:'Edit',
        delete:'Delete',
        semenu:'Secondary menu bar',
        semenuname:'Secondary menu name:',
        menu:'Menu bar:',
        inmenu:'Please enter a menu name',
        sure:'Confirm',
        cancel:'Cancel',
        exmene:'Modify the first-level menu',
        exmenea:'Modify the secondary menu',
        yes:'Yes',
        demenu:'Do you want to delete this menu?',
        prompt:'Prompt',
    },
    delivery:{
        addrole:'Добавьте роли.',
        editrole:'Изменение роли.',
        role :'Роль',
        rolea :'Роль:',
        inrole :'Введите роли.',
        operate :'Операция',
        edit :'Редактор',
        delete :'Удал',
        sure :'подтверд',
        cancel :'Отмена',
        yes:'Да',
        derole :'Удалить персонаж или нет?',
        prompt:'Подсказк',
        addrole:'Add Role',
        editrole:'Modify role',
        role :'Role',
        rolea :'Role:',
        inrole :'Please enter the role',
        operate :'Operate',
        edit :'Edit',
        delete :'Delete',
        yes:'Yes',
        sure :'Confirm',
        cancel :'Cancel',
        derole :'Do you want to delete this role',
        prompt:'Prompt',
        choice:'Menu permissions:',
        inchoice:'Please select Menu Permissions',
    },
  }
    replenish:{
        patchManagement:'Mesh management',
    },
    rework:{
        reworkManagement:'Rework management',
        addRework:"Rework added ",
    },
    role:{
        id:'ID',
        characterHomepage:'Character Home',
    },
    user:{
        userId:'User ID',
        userHomepage:'User Home',
    },
    orderBasicData:{
        order:'orders',
        orderType:'The type of order',
    },
    machine:{
        basicId:'Device number',
        basicName:'The name of the device',
        basicCategory:'The process in which it is located',
        tempering:'Steel',
    },
    report:{
        productionReport:'Production reports',
        workInProgressReport:'WIP report',
    },
    productionBasicData:{
        basicDataQuery :'Basic data query',
    },
    mainIngredient:{
        materialInformation :'Material information',
    },
    mainIngredientStock:{
        materialName :'The name of the item',
        createTime :'Return date',
    },
    large:{
        time: 'The time of the break',
        number: 'Order number',
        jobnumber: 'Job number',
        productionnumber: 'The production order number',
        cardnumber: 'Process card number',
        projectname: 'The name of the project',
        batch: 'batch',
        detailID: 'Detail ID',
        building: 'Building No',
        serialnumber: 'Order serial number',
        productname: 'Product name',
        serial: 'Process validation number',
        slicemarker: 'Frame marker (position)',
        numberpatches: 'Number of patches',
        width: 'Width',
        height: 'Height',
        shape: 'Shape',
        responsibleprocess: 'Responsible process',
        process: 'This process',
        numberfractions: 'The number of unfilled fractions',
        breakreason: 'The reason for the break',
        breaktype: 'Sub-break type',
        responsiblepersonnel: 'Responsible Personnel',
        responsiblequipment: 'Responsible Equipment',
        responsibleteam: 'Responsible team',
        area: 'Sub-broken area',
        inspector: 'Quality inspector',
        operate: 'Operate',
        mes: 'Detail',
        projectnumber: 'The project order number',
        brokeno: 'The report is broken and not filled',
        close: 'Shut down',
        orderId: 'Order ID',
        customerName: 'The name of the customer',
        project: 'The name of the project',
        are: 'are',
        quantity: 'quantity',
        warehousing: 'State',
        deliveryDate: 'Delivery time',
        notstocked: 'Not yet in stock',
        inboundstatus: 'Partial inventory status',
        allstatus: 'All in stock status',
        completedquantity: 'Completed quantity',
        scrapquantity: 'Scrap Quantity',
        method: 'Processing method',
        innumber: 'Quantity already entered',
        productstatus: 'Production status',
        right: 'normal',
        stop: 'termination',
        inquire: 'query',
        starttime :'Start Time',
        endtime :'End Time',
        loading :'In the process of uploading:',
    },
    reportmanage:{
        productiontime :'production time',
        starttime :'Start Time',
        endtime :'End Time',
        ctype :'Please select type',
        cstate :'Please select the status',
        cprocess :'Please select the process',
        all :'All',
        completed :'Completed',
        broke :'Damaged',
        takeout :'Takeout',
        dreportwork :'Unreported work',
        pendingwork :'Pending job application',
        reportwork :'Reported work',
        incise :'slicing',
        edging :'edging',
        steel :'toughened',
        inquire :'query',
        signingwork :'Reporting for work',
        reporteam :'Report work team',
        reportingequipment :'Reporting equipment',
        line :'line',
        process :'production processes',
        glassID :'Glass ID',
        projectnumber :'Project number',
        layoutID :'Tempered layout ID',
        type :'type',
        state :'state',
        processcards :'Flow Card',
        number :'Serial Number',
        layer :'storey',
        typebreakage :'Damage type',
        ptypebreakage :' Please select the type of damage',
        causebreakage :'Reason for damage',
        pcausebreakage :'Please select the reason for the damage',
        responsibleprocess :'Responsibility Process',
        responsiblepersonnel :'Responsible personnel',
        presponsiblepersonnel :'Please enter the responsible personnel',
        responsibleteam :'Responsible team',
        presponsibleteam :'Please select the responsible team',
        responsibleequipment :'Responsible equipment',
        presponsibleequipment :'Please select the responsible device',
        remark :'notes',
        premark :'Please enter a note',
    },
    film:{
        mes:'Original film storage details',
        warehousing:'store',
        operate: 'Operate',
        exit:'Edit',
        delete:'Delete',
        outbound:'Outbound',
        deviceid:'device ID',
        slot:'Grid number',
        enablestatea:'Enable tagging',
        disable:'Disable',
        start:'Enable',
        startslot:'Start workstation',
        endslot:'Target workstation',
        slotid:'Grid ID',
        width:'Width',
        widtha:'Width:',
        inwidth:'Please enter width',
        height:'Height',
        inheight:'Please enter height',
        heighta:'Height:',
        thickness:'Thickness',
        inthickness:'Please enter thickness',
        thicknessa:'Thickness:',
        films:'Films',
        infilms:'Please enter films',
        filmsa:'Films:',
        createtime:'Creation time',
        remainquantity:'Remaining Quantity',
        thickremainquantity:'Remaining quantity of original film (sheets):',
        inquantity:'Please enter the quantity',
        quantitya:'Number:',
        enableid:'Task ID',
        originateslot:'Starting grid',
        patternquantity:'Number',
        enabletype:'Task Type',
        enablestate:'Workstation status',
        finish:'Completed',
        unfinish:'Incomplete',
        dedelete:'Do you want to delete this content?',
        dedisable:'Do you want to disable this content?',
        deoutbound:'Whether to release the content of this item from the warehouse?',
        selectwarehousing:'Please select the lifting position',
        inwarehousing:'Lifting position:',
        warehousing1:'Lifting position 1',
        warehousing2:'Lifting position 2',
        starttime :'Start Time',
        endtime :'End Time',
        taskstatus :'Status',
        built :'newly built',
        execution :'In progress',
        tasktype :'Task Type',
        stocke :'store',
        dispatch :'dispatch',
        inquire :'query',
        station :'station',
    },
    Mounting:{
        previewproject :'Select Preview Project',
        loadinglinea :'Upper film line',
        loadingline :'Upper film line:',
        inloadingline :'Please select the upper film line',
        oneloadingline :'Line 1 on film',
        twoloadingline :'Line 2 on film',
        waiting :'Waiting',
        setparameters :'Set parameters',
        project :'Project number',
        projecta :'Project number:',
        width :'Width',
        height :'Height',
        thickness :'Thickness',
        projectnumber :'Project original piece number',
        state :'state',
        createtime :'Creation time',
        all :'Select All',
    }
}
UI-Project/src/lang/index.js
@@ -1,10 +1,12 @@
import { createI18n}  from 'vue-i18n'
import zh from "./zh"
import py from "./py"
import en from "./en"
let messages = {
    zh:zh,
    py:py,
    en: en
}
UI-Project/src/lang/py.js
New file
@@ -0,0 +1,300 @@
export  default {
    "northglassMESsystem": 'Система "NorthGlass MES"' ,
      login:{
          userErr:'Введите номер счета.',
          pwErr:'Введите пароль.',
          user:'Аккаунт',
          password:'Код',
          login:'Залогин',
          loginSuccessful:'Вход в систему выполнен успешно!',
          register:'Зарегистрирова',
          namea:'Имя не может быть пустым',
          len:'Длина не должна превышать 16',
          passnull:'Пароль не может быть пустым',
          leng:'Длина пароля не должна быть меньше 6 или больше 16.',
          spwn:'Пароль подтверждения не может быть пустым',
          depass:'Два разных пароля.',
      },
      register:{
          registerSuccessful:'Регистрация успешно',
          newuserregister:'Новый реестр пользователей',
          name:'Имя:',
          inputname:'Введите имя',
          password:'Код:',
          pwErr:'Введите пароль.',
          passwordation:'Подтвердите пароль:',
          pwErration:'Пожалуйста, подтвертите пароль',
          registration:'Подтверждение о регистрации',
          false:'Отмена',
      },
      main:{
          connectErr:'Необычное подключение к серверу, попробуйте позже',
          titleFirst:"Добро пожаловать ",
          titleLast:' в систему NorthGlass MES!',
          quit:"Выход",
      },
      basicData:{
          deletemessage:'Удалить эту информацию или нет?',
          laserprinting:'Машина лазерной маркировки готова:',
          cuttingmachine:'Машина для резки готова:',
          machine:'Состояние станок загрузки в режиме онлайн:',
          machineaa:'Ручное состояние станок загрузки:',
          selectproject:"Выберите проект",
          startloading:'Начало загрузки',
          stop:'Пауза',
          yes:'подтверд',
          change:'переключа',
          projectnumber:'Номер проекта',
          glasswidth:'Ширина стекла',
          glassheight:'Высота стекла',
          coatingtypes:'Типы покрытий',
          coatingtypesa:'Типы покрытий:',
          quantity:'Количество',
          quantitya:'Количество:',
          thickness:'Толщина',
          thicknessa:'Толщина:',
          startstatus:'Статус начала операции',
          pass:'Через',
          waiting:'Ждем.',
          up:'Загрузка',
          finish:'Завершено',
          project:'инженерия',
          plselectproject:'Пожалуйста, выберите проект.',
          confirm:'подтверд',
          cancel:'Отмена',
          startfilm:'Начинать или нет?',
          whetherpause:'Пауза или нет?',
          station:'Рабочее место',
          width:'Ширина',
          widtha:'Ширина:',
          height:'Высота',
          heighta:'Высота:',
          operate:'Операция',
          add:'Добавля',
          delete:'Удал',
          addglass:'Добавить стекло',
          selectwidth:'Выбирите ширину',
          selectheight:'Выбирите высоту',
          selectcoatingtypes:'Выберите типы покрытий',
          selectthickness:'Выберите толщину',
          selectquantity:'Введите кольчество.',
          pause:'Вторая и четвертая строки должны быть выше 2700 для сохранения!',
          pausea:'Пожалуйста, убедитесь, что маркировочная и режущая машины готовы!',
          infonull:'Номер проекта не может быть пустым!',
          updatanull:'Проект не сохранились на листе загрузки!',
          glassnull:'Ошибка при обновлении стекла',
      },
      sorter:{
          gridnumber:'Ячеек сеткла',
          glassnumber:'Номер стакла',
          width:'Ширина',
          height:'Высота',
          startstatus:'Статус начала операции',
          disable:'Отключ',
          start:'Начало',
          deficiencieste:'Недостатки в отчетности',
          operate:'Операция',
          prompt:'Подсказк',
          information:'Следует ли сообщать недостающую информацию?',
          yes:'Да',
          cancel:'Отмена',
      },
      order:{
          dilapidation:'Повреждение',
          Takeaway:'Взять вручную',
      },
      searchOrder:{
        cageinformation:'Информация буфера',
        productionqueue:'Производственная очередь',
        outputglassID:'Выходное стекло ID',
        startposition:'Занять позиции',
        targetlocation:'Позиция цели',
        trips:'№ поезда',
        number:'Серийн номер',
        taskstatus:'Состояние задачи',
        filmenter:'Ожидание стеклянной вход',
        infilm:'В настоящее время',
        endtask:'Задача на конец',
        completetask:'Выполнение задания',
        intoglassid:'Входной стеклянный ID',
        line:'Линия',
        Usage:'Скорость использования',
        free:'Бесплатно (ячеек)',
        addcage:'Добавить информацию о буфере',
        glassIDa:'Стеклянный ID:',
        glassID:'Стеклянный ID',
        inglassID:'Введите стекло ID',
        pieceingrid:'Порядок расположения маленьких стеклянных пластин в клетке',
        pieceingrida:'Порядок расположения маленьких стеклянных пластин в клетке:',
        inpieceingrid:'Введите порядок расположения стеклянных листов в ячееке',
        cardnumber:'Номер карточки процесса',
        cardnumbera:'Номер карточки процесса:',
        incardnumber:'Введите номер процесса .',
        typeglass:'Тип стекла',
        typeglassa:'Тип стекла:',
        intypeglass:'Введите тип стекла',
        coatingtypes:'Типы покрытий',
        width:'Ширина',
        widtha:'Ширина:',
        inwidth:'Введите ширину',
        height:'Высота',
        heighta:'Высота:',
        inheight:'Введите высоту',
        thickness:'Толщина',
        thicknessa:'Толщина:',
        inthickness:'Введите толщину.',
        layoutID:'Чертеж ID загрузки печи для закалки',
        layoutIDa:'Чертеж ID загрузки печи для закалки:',
        inlayoutID:'Введите чертеж закалки ID',
        picturesequence:'Чертеж серийн номер загрузки печи для закалки',
        picturesequencea:'Чертеж серийн номер загрузки печи для закалки:',
        inpicturesequence:'Введите порядок чертежи закалки стекла.',
        startstatus:'Статус начала операции',
        startstatusa:'Статус начала операции:',
        instartstatus:'Введите состояние активации',
        glassgaps:'Стеклянный зазор',
        glassgapsa:'Стеклянный зазор:',
        inglassgaps:'Введите стекло зазор',
        sure:'подтверд',
        cancel:'Отмена',
        operate:'Операция',
        breakage:'Повреждение',
        delete:'Удал',
        outfilm:'Выпуск стекла',
        cagetableID:'ID буферной таблицы',
        cagenumber:'Буфер номера',
        gridnumber:'Ячеек сеткла',
        enable:'Начало',
        disable:'Отключ',
        remainingwidth:'Остаточная ширина',
        add:'Добавля',
        sheetID:'Закалка маленький стеклянный ID таблицы информации',
        processcards:'Карточка процесса',
        processcardtype:'Тип стекла карточки процесса',
        acceptshorizontal:'Умеренное принятие горизонтали',
        xcoordinates:'X-координаты',
        ycoordinates:'Y-координаты',
        rotationangle:'Угол вращения (против часовой стрелки)',
        state:'Состояние',
        takeout:'Взять',
        deletemessage:'Удалить эту информацию или нет?',
        prompt:'Подсказк',
        yes:'Да',
        accept:'Принять',
        noaccept:'Не принимать',
        filmcomplete:'Стекло готово',
        waiting:'Ждем.',
    },
    workOrder:{
        glassID:'Стеклянный ID',
        height:'Высота',
        width:'Ширина',
        thickness:'Толщина',
        coatingtypes:'Типы покрытий',
        productionsequence:'Последовательность производства',
        cardnumber:'Номер карточки процесса',
        operate:'Операция',
        messagedamaged:'Повреждено ли сообщение?',
        prompt:'Подсказк',
        yes:'Да',
        cancel:'Отмена',
        takemessage:'Следует ли удалять сообщение?',
        breakage:'Повреждение',
        takeout:'Взять',
    },
    processCard:{
        intofurnace:'В печь',
        beforefurnace:'До печки.',
        outfurnace:'Окончено стекло из печи для закалки',
    },
    reportWork:{
        lowerbit:'Станция разгрузки',
        shelfnumber:'Номер стойки регистрации',
        cardnumber:'Номер карточки процесса',
        totalquantity:'Общее количество',
        beendropped:'Количество стекла разгрузки',
        state:'Состояние',
        devicenumber:'Номер оборудования.',
        startstatus:'Статус начала операции',
        enable:'Начало',
        unenable:'Не начат',
        operate:'Операция',
        bindingshelves:'Назначенная стеллажка',
        clear:'Чисто.',
        workstation:'Станция номер',
        cardnumbera:'Номер карточки процесса:',
        incardnumber:'Пожалуйста, выберите номер программы',
        clearglass:'Очистить стекло с полки',
        sure:'подтверд',
        cancel:'Отмена',
        glassinformation:'Информация стекла',
        glassID:'Стеклянный ID',
        coatingtypes:'Типы покрытий',
        thickness:'Толщина',
        width:'Ширина',
        height:'Высота',
    },
    productStock:{
        addusers:'Добавьте пользователей.',
        username:'Имя пользователя.',
        usernamea:'Имя пользователя.:',
        inusername:'Введите имя пользователя',
        role:'Роль',
        rolea:'Роль:',
        inrole:'Выберите роль',
        test:'Тест',
        admin:'Администратор.',
        operate:'Операция',
        resetpassword:'Сбросить пароль',
        exit:'Редактор',
        delete:'Удал',
        prompt:'Подсказк',
        repassword:'Перезагрузка пользовательского пароля или нет?',
        yes:'Да',
        cancel:'Отмена',
        reusername:'Изменение пользователя',
        addusername:'Добавьте пользователей.',
        password:'Код:',
        sure:'подтверд',
        inpassword:'Введите пароль.',
        deusername:'Удаление пользователя или нет?',
    },
    customer:{
        addmenu:'Добавьте меню.',
        firstmenu:'Таблица меню первой степени',
        link:'Ссылк',
        linka:'Ссылк:',
        inlink:'Введите ссылку',
        sort:'Сортировк',
        sorta:'Сортировк:',
        insort:'Введите сортировку',
        operate:'Операция',
        exit:'Редактор',
        inmenu:'Введите меню',
        delete:'Удал',
        semenu:'Таблица меню второй степени',
        menu:'Меню.:',
        sure:'подтверд',
        cancel:'Отмена',
        exmene:'Изменение меню.',
        yes:'Да',
        demenu:'Удалить меню или нет?',
        prompt:'Подсказк',
    },
    delivery:{
        addrole:'Добавьте роли.',
        editrole:'Изменение роли.',
        role :'Роль',
        rolea :'Роль:',
        inrole :'Введите роли.',
        operate :'Операция',
        edit :'Редактор',
        delete :'Удал',
        sure :'подтверд',
        cancel :'Отмена',
        yes:'Да',
        derole :'Удалить персонаж или нет?',
        prompt:'Подсказк',
    },
  }
UI-Project/src/lang/zh.js
@@ -199,26 +199,27 @@
        tid:'设备id',
        tida:'设备id:',
        fin:'是否完成任务?',
        sureadd:'确认添加',
        sureadda:'是否确认添加?',
        zailong:'在笼中',
        rengongxp:'人工下片',
        up:'上一页',
        down:'下一页',
        now:'当前页显示',
        tit:'条数据',
        temperingqueries:'钢化查询',
        specifytempering:'指定一炉',
        specifyengineerid:'指定工程',
        projectnumber:'工程号',
        layoutnumber:'钢化版图号',
        numberglasses:'玻璃数量',
        specifytemperinga:'是否指定钢化该条信息?',
        temperedswitch:'钢化开关',
        dutyinformation:'值班信息',
        process:'工序',
        team:'班组',
        basic:'设备',
        sureadd: '确认添加',
        sureadda: '是否确认添加?',
        zailong: '在笼中',
        rengongxp: '人工下片',
        up: '上一页',
        down: '下一页',
        now: '当前页显示',
        tit: '条数据',
        temperingqueries: '钢化查询',
        specifytempering: '指定一炉',
        specifyout: '指定人工出片',
        specifyengineerid: '指定工程',
        projectnumber: '工程号',
        layoutnumber: '钢化版图号',
        numberglasses: '玻璃数量',
        specifytemperinga: '是否指定钢化该条信息?',
        temperedswitch: '钢化开关',
        dutyinformation: '值班信息',
        process: '工序',
        team: '班组',
        basic: '设备',
        makesure:'确认保存',
        // cancel:'取消',
        temperingtotal:'钢化炉数:',
@@ -563,4 +564,24 @@
        inquire :'查询',
        station :'工位',
    },
    Mounting:{
        previewproject :'选择预览工程',
        loadinglinea :'上片线',
        loadingline :'上片线:',
        inloadingline :'请选择上片线',
        oneloadingline :'一号上片线',
        twoloadingline :'二号上片线',
        waiting :'等待中',
        setparameters :'设置参数',
        project :'工程号',
        projecta :'工程号:',
        width :'原片宽',
        height :'原片高',
        thickness :'原片厚',
        projectnumber :'工程原片序号',
        state :'状态',
        createtime :'创建时间',
        all :'全选',
    }
}
UI-Project/src/layout/MainErpView.vue
@@ -29,60 +29,66 @@
              })
  router.push('/login')  
}
// const quit = async () => {
//   try  {
//       store.$patch({user: null})
//     const response = await request.post('/loadGlass/sys/user/logout')
//     if (response.code === 200) {
//         console.log('登出成功');
//       } else {
//         // 处理错误情况
//         console.error('登出失败', response);
//       }
// }
// catch (error) {
//     // 处理错误
//     console.error(error);
//   }
// }
// store.createWebSocket();
// function quit() {
//   userStore.$patch({
//     user: null,
//   })
//   // router.push('/login')
//   request.get("/loadGlass/sys/user/login").then((res) => {
//     if (res.code === 200) {
//     ElMessage.success(res.msg);
//      console.log(res.data);
//     } else {
//     ElMessage.warning(res.msg);
//     // router.push("/login");
//     }
//    });
// }
  function replaceChineseWithEnglish(menuData) {  
      // 定义中俄文对照关系对象
       const translation  = {
    '上片机': 'Стол загрузки',
    '上片': 'Верхняя часть',
    '掰片/识别': 'Разлом/идентификация',
    '卧式缓存': ' Горизонтальный буфер',
    '磨边前卧式缓存': 'Горизонтальный буфер перед шлифовкой',
    '下片卧式缓存': 'Горизонтальный буфер стекла разгрузки',
    '磨边(冷加工)': 'Шлифовать края (холодная обработка)',
    '1线磨边(冷加工)': 'Шлифовать края 1 линии (холодная обработка)',
    '2线磨边(冷加工)': 'Шлифовать края 2 линии (холодная обработка)',
    '大理片笼': 'Буферная система',
    '钢化': 'Закалка',
    '钢化前': 'Перед закалки',
    '钢化后': 'После закалки',
    '下片台': 'Стол разгрузки',
    '系统管理': 'Управление системой',
    '用户管理': 'Управление пользователем',
    '权限管理': 'Управление полномочиями',
    '角色管理': 'Управление ролью',
    '可视化系统': 'Визуальная система',
    '报工管理': 'Управление отчетностью',
    '仓储中心': 'Складской центр',
    '原片仓储': 'Склад сырья',
     };
  menuData.forEach(menu => {
    menu.menuName = translation[menu.menuName] || menu.menuName;
    // if (menu.children) {
      menu.children && menu.children.forEach(submenu => {
        submenu.menuName = translation[submenu.menuName] || submenu.menuName;
      });
    // }
  });
}
function replaceChineseWithRussian(menuData) {
      // 定义中英文对照关系对象
       const translation  = {  
          '上片机': 'Стол загрузки',
          '掰片/识别': 'Разлом/идентификация',
          '卧式缓存': ' Горизонтальный буфер',
          '磨边前卧式缓存': 'Горизонтальный буфер перед шлифовкой',
          '下片卧式缓存': 'Горизонтальный буфер стекла разгрузки',
          '磨边(冷加工)': 'Шлифовать края (холодная обработка)',
          '1线磨边(冷加工)': 'Шлифовать края 1 линии (холодная обработка)',
          '2线磨边(冷加工)': 'Шлифовать края 2 линии (холодная обработка)',
          '大理片笼': 'Буферная система',
          '钢化': 'Закалка',
          '钢化前': 'Перед закалки',
          '钢化后': 'После закалки',
          '下片台': 'Стол разгрузки',
          '系统管理': 'Управление системой',
          '用户管理': 'Управление пользователем',
          '权限管理': 'Управление полномочиями',
          '角色管理': 'Управление ролью',
    '上片机': 'Loading Machine',
    '上片': 'Start showing a movie',
    '掰片/识别': 'Breaking /Identification',
    '卧式缓存': 'Horizontal cache',
    '磨边前卧式缓存': 'Horizontal buffer before edge grinding',
    '下片卧式缓存': 'Offline horizontal cache',
    '磨边(冷加工)': 'Grinding edge (cold processing)',
    '1线磨边(冷加工)': '1-line edge grinding (cold processing)',
    '2线磨边(冷加工)': '2-line edge grinding (cold processing)',
    '大理片笼': 'Dali slice cage',
    '钢化': 'Toughened',
    '钢化前': 'Before Tempering',
    '钢化后': 'After Tempering',
    '下片台': 'Next Stage',
    '系统管理': 'System Management',
    '用户管理': 'User Management',
    '权限管理': 'Rights Management',
    '角色管理': 'Roles',
    '可视化系统': 'visualization system',
    '报工管理': 'Job reporting management',
    '仓储中心': 'Storage Center',
    '原片仓储': 'Original film storage',
     };  
  menuData.forEach(menu => {  
    menu.menuName = translation[menu.menuName] || menu.menuName;  
@@ -96,32 +102,15 @@
//提取菜单模块列表
let menuList = $ref([])
// onMounted(async () => {
//   try {
//     const res = await request.get('/loadGlass/sys/menu/getMenuTree'); // 假设 request.get 返回 Promise
//     if (res.code == 200) {
//       // 使用 value 属性来修改 ref 引用的值
//       menuList.value = deepClone(res.data);
//       const language = $i18n.locale;
//       if (language === 'en') {
//         replaceChineseWithEnglish(menuList.value); // 传入 ref 的 value
//       }
//       console.log(res.data.token); // 如果 res.data 中有 token 的话
//     } else {
//       ElMessage.warning(res.msg);
//       router.push('/login');
//     }
//   } catch (error) {
//     // 处理请求错误
//     console.error('获取菜单列表时出错:', error);
//   }
// });
request.get('/loadGlass/sys/menu/getMenuTree').then((res) => {
  if (res.code == 200) {
    menuList = res.data
    console.log(language.value)
    // translateMenu(menuList.value, language.value);
      if (language.value === 'en') {
        replaceChineseWithRussian(menuList);
      }
      if (language.value === 'py') {
        replaceChineseWithEnglish(menuList);
      }
  } else {
@@ -169,7 +158,7 @@
      <el-header>
        <div style="height: 100%;width: 100%;display: flex;background-color: #fff;">
          <img src="../assets/northGlass.ico"
               alt=""
               alt=""  @click="toggleCollapse"
               style="max-width: 100%;max-height: 100%">
          <h3 style="margin: 1rem  ;font-weight: bold;width: 33vw;"> {{ $t('main.titleFirst') }}{{ userName }}{{ $t('main.titleLast') }}</h3>
          <span style="height: 70%;width: 78vw;margin-top: 1rem;">
@@ -187,11 +176,11 @@
                <SwitchButton size=""/>{{ $t('main.quit') }}
              </el-icon>
            </el-button>
            <div class="header-left">
            <!-- <div class="header-left">
              <el-button @click="toggleCollapse" style="height: 30px;">  
               <el-icon><Expand /></el-icon>
              </el-button>  
          </div>
          </div> -->
          </span>
        </div>
      </el-header>
UI-Project/src/router/index.js
@@ -3,7 +3,6 @@
// import User from '../views/sys/User.vue'
// import Role from '../views/sys/Role.vue'
// import Menu from '../views/sys/Menu.vue'
const router = createRouter({
  history: createWebHashHistory(),
  routes: [
@@ -17,6 +16,11 @@
      path: '/login',
      name: 'login',
      component: () => import('../views/LoginView.vue')
    },
    {
      path: '/new-page', // 新增的无需登录的页面
      name: 'newPage',
      component: () => import('../views/NewPage.vue')
    },
    {
      path: '/main',
@@ -68,13 +72,18 @@
        /*----------- 上片机 ----------------*/
      {
        path: 'Returns',
        name: 'Returns',
        component: () => import('../views/Returns/returns.vue'),
        name: 'return',
        component: () => import('../views/Returns/return.vue'),
        children:[
          {
            path: '/Returns/returns',
            name: 'returns',
            component: () => import('../views/Returns/returns.vue')
          },
          {
            path: '/Returns/upreturns',
            name: 'upreturns',
            component: () => import('../views/Returns/upreturns.vue')
          },
        ]
      },
@@ -302,7 +311,7 @@
        },
        {
          path: '',
          redirect: '/returns/returns'
          redirect: '/Returns/returns'
        }
      ]
    },
@@ -315,4 +324,13 @@
  ]
})
// 导航守卫
router.beforeEach((to, from, next) => {
  const isAuthenticated = !!localStorage.getItem('authToken'); // 假设这是你的登录状态检查逻辑
  if (to.matched.some(record => record.meta.requiresAuth) && !isAuthenticated) {
    next({ name: 'login' }); // 如果需要登录但未登录,则重定向到登录页面
  } else {
    next(); // 否则继续导航
  }
});
export default router
UI-Project/src/views/LoginView.vue
@@ -130,7 +130,8 @@
            placeholder=" "
            style="float: right;width: 9rem">
          <el-option value="zh"  label="中文" />
          <el-option value="en"  label="Русский язык" />
          <el-option value="py"  label="Русский язык" />
          <el-option value="en"  label="English" />
        </el-select>
        <el-form @submit.native.prevent
                 ref="ruleFormRef"
UI-Project/src/views/NewPage.vue
New file
@@ -0,0 +1,151 @@
<template>
    <div>
  <div style="display: flex;">
    <div style="margin-left: 50px;margin-top: 15px;font-size:large">工程号:</div>
<el-input v-model="current" style="margin-left: 20px;margin-top: 15px;width: 240px" placeholder="请输入工程号" @input="updateUrl"/>
      <el-button style="margin-top: 15px;margin-left: 15px;"  type="primary" @click="fetchData">查询</el-button>
    </div>
    <el-card style="flex: 1;margin-left: 10px;margin-top: 20px;margin-right: 10px;width: 1850px;" height="900" v-loading="loading">
    <div v-for="(row, rowIndex) in divsData" :key="rowIndex" class="row">
        <div v-for="(rect, colIndex) in row" :key="colIndex" class="div-container">
    <el-scrollbar height="430px" width="900px" style="background-color: #e9e9eb;">
    <div  style="position: relative;width: 100%;height: 100%;">
      <div
        v-for="(rect, index) in getAdjustedRectsForRow(rowIndex)"
      :key="index"
      class="rect"
      :style="{ position: 'absolute',
       top: `${rect.y_axis}px`,
       left: `${rect.x_axis}px`,
       width: `${rect.width}px`,
         height: `${rect.height}px`,
        backgroundColor:  '#911005'}">
     <div  class="centered-text">
    <div style="font-size: 15px;font-weight: bold;">{{ rect.process_id }}</div>
    <div style="font-size: 15px;font-weight: bold;">{{ rect.project_no }}</div>
    <div style="font-size: 30px;font-weight: bold;">{{ rect.widtha }}*{{ rect.heighta }}</div>
     </div>
      </div>
    </div>
    </el-scrollbar>
        </div>
    </div>
    </el-card>
    </div>
</template>
<script setup>
import {onMounted, ref, watch} from 'vue';
import {useRoute, useRouter} from 'vue-router';
import request from "@/utils/request"
const route = useRoute();
const router = useRouter();
const current = ref(route.query.current || '');
const adjustedRects = ref([]);
const loading = ref(false);
const adjustedRectsPerRow = ref([]);
const divsData = ref([]);
const rawData = ref([]);
onMounted(() => {
  if (route.query.current) {
    current.value = route.query.current;
         console.log(current.value);
         window.localStorage.setItem('current', current.value)
       }
     });
     onMounted(async () => {
         try {
           let current = window.localStorage.getItem('current')
             const response = await request.post(`/cacheGlass/taskCache/temperingTerritory?current=${current}`);
           if (response.code === 200) {
             rawData.value = response.data;
                   console.log(rawData.value);
                   processData(rawData.value);
           } else {
            //  ElMessage.warning(res.msg)
           }
         } catch (error) {
           // console.error('Error fetching rects :', error);
         }
       });
     watch(
       current,
       (newVal) => {
         router.replace({ query: { current: newVal } });
       },
       { immediate: true } // 使用 immediate: true 来确保在组件挂载时立即执行一次 watch 回调
     );
     const fetchData = async () => {
       try {
         const response = await request.post(`/cacheGlass/taskCache/temperingTerritory?current=${current.value}`);
         if (response.code === 200) {
            rawData.value = response.data;
            console.log(rawData.value);
            processData(rawData.value);
    }
  } catch (error) {
    console.error('Failed to fetch data:', error);
  } finally {
    loading.value = false;
  }
};
     function processData(data) {
  const groupedData = [];
  for (let i = 0; i < data.length; i += 2) {
    groupedData.push(data.slice(i, i + 2));
  }
  divsData.value = groupedData;
adjustedRectsPerRow.value = divsData.value.map(() => []);
  divsData.value.forEach((row, rowIndex) => {
    const rawRowData = rawData.value[rowIndex];
    if (rawRowData) {
adjustedRectsPerRow.value[rowIndex] = rawRowData.map(rect => {
        let adjustedWidth, adjustedHeight,newX;
        if (rect.rotate_angle  === 0) {
         newX = rect.olHeight -(rect.y_axis + rect.height);
         adjustedWidth = rect.height * (900/rect.olHeight);
         adjustedHeight = rect.width * (430/rect.olWidth);
        } else {
          newX = rect.olHeight -(rect.y_axis + rect.width);
         adjustedWidth = rect.width * (900/rect.olHeight);
         adjustedHeight = rect.height * (430/rect.olWidth);
        }
        let adjustedRect = {
          ...rect,
          // x_axis: rect.y_axis * (959.35/rect.olHeight),
          y_axis: rect.x_axis * (430/rect.olWidth),
          x_axis: newX * (900/rect.olHeight),
          // y_axis: rect.x_axis * (430/rect.olWidth),
          width: adjustedWidth,
          height: adjustedHeight,
          widtha: rect.width,
          heighta: rect.height,
        };
        return adjustedRect;
      });
    }
  });
}
// 方法用于获取当前行的adjustedRects
function getAdjustedRectsForRow(rowIndex) {
  return adjustedRectsPerRow.value[rowIndex] || [];
}
     </script>
  <style scoped>
.row {
  display: flex;
  justify-content: space-between;
  margin-bottom: 20px;
}
.div-container {
  width: 900px;
  float: left;
  background-color: #f4f4f5;
  height: 430px;
  box-sizing: border-box;
}
  </style>
UI-Project/src/views/PurchaseReturn/purchaseReturn.vue
@@ -272,7 +272,7 @@
        widtha = rect.width;
        heighta = rect.height;
      }
  if (rect.angle === 0) {
  if (rect.angle === 0) {
    adjustedWidth = widtha * scaleFactor;  
    adjustedHeight = heighta * scaleFactory;  
    // adjustedWidtha = widtha;  
UI-Project/src/views/Returns/return.vue
New file
@@ -0,0 +1,49 @@
<script setup>
import {ArrowLeftBold, ArrowRight, Search} from "@element-plus/icons-vue"
import {useRouter} from "vue-router";
let indexFlag=$ref(1)
function changeRouter(index){
  indexFlag=index
}
</script>
<template>
  <!-- <div id="main-div"> -->
    <div id="main-body">
      <router-view  />
    </div>
  <!-- </div> -->
</template>
<style scoped>
#main-div{
  width: 100%;
  height: 100%;
}
#div-title{
  height: 2%;
  width: 100%;
}
#searchButton{
  margin-top: -5px;
  margin-left: 1rem;
}
/* #searchButton1{
//margin-left: 10rem;
} */
/*main-body样式*/
#main-body{
  width: 100%;
  height: 95%;
  /* margin-top: 1%; */
}
#select{
  margin-left:0.5rem;
}
:deep(.indexTag .el-breadcrumb__inner){
  color: #5CADFE !important;
}
</style>
UI-Project/src/views/Returns/returns.vue
@@ -228,10 +228,10 @@
const requestData = {  
  state: 100  
};  
const selectgong = async (queryString: string) => {
  try  {
    const response = await request.post('/loadGlass/optimizeProject/listByState',{
@@ -559,7 +559,7 @@
      // window.location.reload() 
      blindb.value = false;
      tableData.splice([]);
      // 请求失败,显示错误消息
      ElMessage.error(response.message);
    }
@@ -613,7 +613,7 @@
const handleBindb = (row) => {
  blindb.value = true; 
};
// 删除
const handleBindRacka = (row) => {
  workstationId.value = row.workstationId;
UI-Project/src/views/Returns/upreturns.vue
New file
@@ -0,0 +1,1115 @@
<script lang="ts" setup>
import {onBeforeUnmount, onMounted, onUnmounted, reactive, ref} from "vue";
import {useRouter} from "vue-router"
import {ElMessage} from 'element-plus'
import {useI18n} from 'vue-i18n'
import {host, WebSocketHost} from '@/utils/constants'
import request from "@/utils/request"
import {closeWebSocket, initializeWebSocket} from '@/utils/WebSocketService';
const router = useRouter()
const {t} = useI18n()
const selectValuesa = reactive([]);
const dialogFormVisible = ref(false)
const blind = ref(false)
const blinda = ref(false)
const blindb = ref(false)
const add = ref(false)
const adda = ref(false)
const flake = ref(false)
const flakea = ref(false)
const flakeb = ref(false)
const flakec = ref(false)
const dialoglea = ref(false)
const tableDatax = ref([])
const user = ref('');
const projectNo = ref('');
const workstationId = ref('');
const id = ref('');
const patternHeight = ref('');
const patternWidth = ref('');
const filmsId = ref('');
const patternThickness = ref('');
const number = ref('');
const canSelectProject = ref(true);
const canStartLoading = ref(false);
const ida = ref(null);
const selectedProjectNo = ref(''); // 当前选中的工程号
const selectedProjectNoa = ref(''); // 当前选中的工程号
const selectedValue = ref(''); // 当前选中的宽
const selectedValuea = ref('');
const selectedValueb = ref('');
const selectedValuec = ref('');
// const upstatus = ref('上片机手动状态:'); // 假设这个用于显示自动/手动状态
const upstatus = ref(t('basicData.machineaa'));
const cuttingMachine = ref(''); // 假设这个用于存储后端返回的状态值(0或1)
const cuttingMachineStatusColor = ref('#911005'); // 用于动态设置i标签的背景色
const inKageWord = ref(0); // 用于存储要传递给接口的inKageWord值
const options = ref<any[]>([]); // 下拉选项列表
const selectOptions = ref<Array<any>>([]); // 下拉选选项数组
const selectOptionsa = ref<Array<any>>([]); // 下拉选选项数组
const selectOptionsb = ref<Array<any>>([]); // 下拉选选项数组
const selectOptionsc = ref<Array<any>>([]); // 下拉选选项数组
const tableDataa = ref([])
const tableData = reactive([]);
const fetchTableData = async () => {
  try {
    const response = await request.get("/loadGlass/up-patten-usage/prioritylist");
    // 检查响应状态
    if (response.code === 200) {
      // 更新表格数据
      console.log('成功获取表格数据:', response.data);
      tableData.splice(0, tableData.length, ...response.data);
      // window.localStorage.setItem('engineeringId', response.data[0].engineeringId)
      // 获取唯一值
      const uniqueWidths = new Set(response.data.map(item => item.width));
      const uniqueHeights = new Set(response.data.map(item => item.height));
      const uniqueFilmsIds = new Set(response.data.map(item => item.filmsId));
      const uniqueThicknesses = new Set(response.data.map(item => item.thickness));
      selectOptions.value = Array.from(uniqueWidths).map(width => ({
        value: width, // 假设这是你想要作为value的属性
        label: width, // 假设这是你想要显示的label
      }));
      selectOptionsa.value = Array.from(uniqueHeights).map(height => ({
        value: height,
        label: height,
      }));
      selectOptionsb.value = Array.from(uniqueFilmsIds).map(filmsId => ({
        value: filmsId,
        label: filmsId,
      }));
      selectOptionsc.value = Array.from(uniqueThicknesses).map(thickness => ({
        value: thickness,
        label: thickness,
      }));
    } else {
      ElMessage.error(response.message);
    }
  } catch (error) {
    // 处理请求失败的情况
    // ElMessage.error('获取表格数据失败,请重试');
  }
};
const handlezhiban = () => {
  dialoglea.value = true; // 打开绑定架子对话框
  fetchFlowCardId();
};
const selectproject = () => {
  dialogFormVisible.value = true;
  selectgong();
};
// 值班信息
const fetchFlowCardId = async () => {
  try {
    const response = await request.post('/loadGlass/work_assignment/selectWorkAssignment', {
      line: 2001,
      workingProcedure: '冷加工'
    })
    if (response.code == 200) {
      ElMessage.success(response.message);
      tableDatax.value = response.data;
      console.log(tableDatax.value);
      console
    } else {
      ElMessage.error(response.message);
    }
  } catch (error) {
    // 处理错误
    console.error(error);
  }
}
const handleConfirmb = async () => {
  const response = await request.post("/loadGlass/work_assignment/updateWorkAssignment", tableDatax.value)
  if (response.code === 200) {
    ElMessage.success(response.message);
    dialoglea.value = false;
  } else {
    ElMessage.error(response.message);
  }
};
onMounted(() => {
  list('');
  fetchOptions('');
  socket = initializeWebSocket(socketUrl, handleMessage);
});
onUnmounted(() => {
  if (socket) {
    closeWebSocket(socket);
  }
});
const list = async () => {
  try {
    const response = await request.get('/loadGlass/LoadGlass/list');
    if (response.code == 200) {
      tableDataa.value = response.data
      if (tableDataa.value.length === 4) {
        if (tableDataa.value[0].patternHeight > 0 && tableDataa.value[0].patternWidth > 0 && tableDataa.value[0].number > 0) {
          flake.value = true;
        }
        if (tableDataa.value[1].patternHeight > 0 && tableDataa.value[1].patternWidth > 0 && tableDataa.value[1].number > 0) {
          flakea.value = true;
        }
        if (tableDataa.value[2].patternHeight > 0 && tableDataa.value[2].patternWidth > 0 && tableDataa.value[2].number > 0) {
          flakeb.value = true;
        }
        if (tableDataa.value[3].patternHeight > 0 && tableDataa.value[3].patternWidth > 0 && tableDataa.value[3].number > 0) {
          flakec.value = true;
        }
      }
    } else {
      ElMessage.warning(response.data);
    }
  } catch (error) {
    console.error('Error fetching options:', error);
  }
};
// 假设这是您的响应处理函数
// request.get("/loadGlass/LoadGlass/list").then((res) => {
//       if (res.code == 200) {
//           tableDataa.value = res.data
//           if (tableDataa.value.length === 4) {
//           if (tableDataa.value[0].patternHeight > 0) {
//           flake.value = true;
//           }
//          if (tableDataa.value[1].patternHeight > 0) {
//           flakea.value = true;
//           }
//          if (tableDataa.value[2].patternHeight > 0) {
//           flakeb.value = true;
//           }
//          if (tableDataa.value[3].patternHeight > 0) {
//           flakec.value = true;
//           }
//            }
//           } else {
//           ElMessage.warning(res.message)
//           // router.push("/login")
//           }
//           });
//定义接收加载表头下拉数据
const titleSelectJson = ref({
  processType: [],
})
const titleSelectJsona = ref({
  processTypea: [],
})
let socket = null;
const socketUrl = `ws://${WebSocketHost}:${host}/api/loadGlass/api/talk/loadGlass`;
// 定义消息处理函数,更新 receivedData 变量
const handleMessage = (data) => {
  if (data.prioritylist != null) {
    tableData.splice(0, tableData.length, ...data.prioritylist[0]);
  }
  if (data.list != null) {
    tableDataa.value = data.list[0]
  }
  if (data.engineering) {
    if (Array.isArray(data.engineering) && data.engineering.length !== 0) {
      canSelectProject.value = false;
      canStartLoading.value = true;
    } else {
      canSelectProject.value = true;
      canStartLoading.value = false;
    }
  }
  if (data.InkageStatus) {
    if (data.InkageStatus != null) {
      const status = data.InkageStatus[0];
      cuttingMachine.value = status;
      upstatus.value = status === '1' ? t('basicData.machine') : t('basicData.machineaa');
      cuttingMachineStatusColor.value = status === '1' ? 'green' : '#911005';
      inKageWord.value = status === '1' ? 0 : 1;
    }
  }
};
const requestData = {
  state: 100
};
const selectgong = async (queryString: string) => {
  try {
    const response = await request.post('/loadGlass/optimizeProject/listByState', {
      ...requestData,
      query: queryString
    })
    if (response.code == 200) {
      titleSelectJson.value.processType = response.data;
    } else {
      ElMessage.error(response.message);
    }
  } catch (error) {
    // 处理错误
    console.error(error);
  }
}
const fetchOptions = async (queryString: string) => {
  try {
    // 发送请求到后端接口
    const response = await request.post('/loadGlass/optimizeProject/listByState', {
      ...requestData,
      query: queryString // 将查询字符串作为参数传递
    });
    if (response.code == 200) {
      // titleSelectJson.value.processType = response.data;
      console.log(response.data);
    } else {
      ElMessage.warning(response.data);
    }
  } catch (error) {
    console.error('Error fetching options:', error);
  }
};
// 处理用户输入变化的方法
const handleInputChange = async (value: string) => {
  if (value) {
    await fetchOptions(value);
  } else {
    options.value = []; // 清空选项列表
  }
};
// 处理用户输入变化的方法
const handleInputChangea = async (value: string) => {
  if (value) {
    await fetchOptionsa(value);
  } else {
    options.value = []; // 清空选项列表
  }
};
onBeforeUnmount(() => {
  closeWebSocket();
});
// 添加
const handleBindRack = (row) => {
  workstationId.value = row.workstationId; // 假设rackNumber是架号字段的属性名
  ida.value = row.id;
  add.value = true; // 打开绑定架子对话框
};
// 添加
const handleConfirm = async () => {
  // console.log('id.value:', id.value);
  if ((ida.value === 2 || ida.value === 4) && (parseInt(selectedValuea.value, 10) >= 2700)) {
    try {
      const response = await request.post('/loadGlass/LoadGlass/updateGlassMessage', {
        id: workstationId.value,
        workstationId: workstationId.value,
        patternHeight: selectedValuea.value,
        patternWidth: selectedValue.value,
        filmsId: selectedValueb.value,
        patternThickness: selectedValuec.value,
        number: number.value
      });
      // window.localStorage.setItem('workstationId', workstationId.value)
      // window.localStorage.setItem('patternHeight', selectedValuea.value)
      // window.localStorage.setItem('patternWidth', selectedValue.value)
      // window.localStorage.setItem('number', number.value)
      if (response.code == 200) {
        // 绑定成功,处理逻辑
        ElMessage.success(response.message);
        // window.location.reload()
        add.value = false;
        tableDataa.value = response.data;
        // let workstationId = window.localStorage.getItem('workstationId')
        // let patternHeight = window.localStorage.getItem('patternHeight')
        // let patternWidth = window.localStorage.getItem('patternWidth')
        // let number = window.localStorage.getItem('number')
        if (selectedValuea.value !== '0' && selectedValue.value !== '0' && number.value !== '0' && workstationId.value === '1') {
          flake.value = true
        } else if (selectedValuea.value !== '0' && selectedValue.value !== '0' && number.value !== '0' && workstationId.value === '2') {
          flakea.value = true
        } else if (selectedValuea.value !== '0' && selectedValue.value !== '0' && number.value !== '0' && workstationId.value === '3') {
          flakeb.value = true
        } else if (selectedValuea.value !== '0' && selectedValue.value !== '0' && number.value !== '0' && workstationId.value === '4') {
          flakec.value = true
        }
        //   if (patternHeight !== '0' && patternWidth !== '0' && number !== '0' && workstationId === '1') {
        //   flake.value = true
        // } else if (patternHeight !== '0' && patternWidth !== '0' && number !== '0' && workstationId === '2'){
        //   flakea.value = true
        // }else if (patternHeight !== '0' && patternWidth !== '0' && number !== '0' && workstationId === '3'){
        //   flakeb.value = true
        // }else if (patternHeight !== '0' && patternWidth !== '0' && number !== '0' && workstationId === '4'){
        //   flakec.value = true
        // }
        selectedValuea.value = '';
        selectedValue.value = '';
        selectedValueb.value = '';
        selectedValuec.value = '';
        number.value = '';
        list()
      } else {
        // 请求失败,显示错误消息
        ElMessage.error(response.message);
      }
    } catch (error) {
      // 处理请求错误
    }
  } else if (ida.value === 1 || ida.value === 3) {
    try {
      const response = await request.post('/loadGlass/LoadGlass/updateGlassMessage', {
        id: workstationId.value,
        workstationId: workstationId.value,
        patternHeight: selectedValuea.value,
        patternWidth: selectedValue.value,
        filmsId: selectedValueb.value,
        patternThickness: selectedValuec.value,
        number: number.value
      });
      if (response.code == 200) {
        // 绑定成功,处理逻辑
        ElMessage.success(response.message);
        // window.location.reload()
        add.value = false;
        tableDataa.value = response.data;
        if (selectedValuea.value !== '0' && selectedValue.value !== '0' && number.value !== '0' && workstationId.value === '1') {
          flake.value = true
        } else if (selectedValuea.value !== '0' && selectedValue.value !== '0' && number.value !== '0' && workstationId.value === '2') {
          flakea.value = true
        } else if (selectedValuea.value !== '0' && selectedValue.value !== '0' && number.value !== '0' && workstationId.value === '3') {
          flakeb.value = true
        } else if (selectedValuea.value !== '0' && selectedValue.value !== '0' && number.value !== '0' && workstationId.value === '4') {
          flakec.value = true
        }
        selectedValuea.value = '';
        selectedValue.value = '';
        selectedValueb.value = '';
        selectedValuec.value = '';
        number.value = '';
        list()
      } else {
        // 请求失败,显示错误消息
        ElMessage.error(response.message);
      }
    } catch (error) {
      // 处理请求错误
    }
  } else {
    ElMessage({
      type: 'info',
      message: t('basicData.pause'),
    })
  }
};
// 删除
const handleConfirma = async () => {
  try {
    const response = await request.post('/loadGlass/LoadGlass/updateGlassMessage', {
      workstationId: workstationId.value,
      patternHeight: 0,
      patternWidth: 0,
      filmsId: "",
      patternThickness: 0,
      number: 0
    });
    if (response.code == 200) {
      // 绑定成功,处理逻辑
      ElMessage.success(response.message);
      adda.value = false;
      tableDataa.value = response.data;
      // window.localStorage.setItem('workstationId', response.data.workstationId)
      // let workstationId = window.localStorage.getItem('workstationId')
      if (workstationId.value == '1') {
        flake.value = false
      } else if (workstationId.value == '2') {
        flakea.value = false
      } else if (workstationId.value == '3') {
        flakeb.value = false
      } else if (workstationId.value == '4') {
        flakec.value = false
      }
      list()
    } else {
      // 请求失败,显示错误消息
      ElMessage.error(response.message);
    }
  } catch (error) {
    // 处理错误
    console.error(error);
  }
};
// 选择工程确认
const handleup = async () => {
  try {
    const response = await request.post('/loadGlass/up-patten-usage/selectUpPattenUsage', {
      engineerId: selectedProjectNo.value,
    })
    window.localStorage.setItem('engineeringId', selectedProjectNo.value)
    if (response.code == 200) {
      // 绑定成功,处理逻辑
      ElMessage.success(response.message);
      // window.location.reload()
      dialogFormVisible.value = false;
      tableData.splice(0, tableData.length, ...response.data);
      selectedProjectNo.value = ''
      markingMachineStatus.value = '#911005';
      cuttingMachineStatus.value = '#911005';
      const uniqueWidths = new Set(response.data.map(item => item.width));
      const uniqueHeights = new Set(response.data.map(item => item.height));
      const uniqueFilmsIds = new Set(response.data.map(item => item.filmsId));
      const uniqueThicknesses = new Set(response.data.map(item => item.thickness));
      selectOptions.value = Array.from(uniqueWidths).map(width => ({
        value: width,
        label: width,
      }));
      selectOptionsa.value = Array.from(uniqueHeights).map(height => ({
        value: height,
        label: height,
      }));
      selectOptionsb.value = Array.from(uniqueFilmsIds).map(filmsId => ({
        value: filmsId,
        label: filmsId,
      }));
      selectOptionsc.value = Array.from(uniqueThicknesses).map(thickness => ({
        value: thickness,
        label: thickness,
      }));
    } else {
      // 请求失败,显示错误消息
      ElMessage.error(response.message);
      // ElMessage.error(response.msg);
    }
  } catch (error) {
    // 处理错误
    console.error(error);
  }
}
// 开始上片
const handle = async () => {
  if (markingMachineStatus.value === 'green' && cuttingMachineStatus.value === 'green') {
    try {
      let engineeringId = window.localStorage.getItem('engineeringId')
      const response = await request.post('/loadGlass/engineering/engineering/changeTask', {
        engineerId: engineeringId,
        state: 1,
      })
      if (response.code == 200) {
        // 绑定成功,处理逻辑
        ElMessage.success(response.message);
        // window.location.reload()
        blind.value = false;
        selectedProjectNoa.value = '';
      } else {
        // 请求失败,显示错误消息
        ElMessage.error(response.message);
      }
    } catch (error) {
      // 处理错误
      console.error(error);
    }
  } else if (markingMachineStatus.value === '#911005' || cuttingMachineStatus.value === '#911005') {
    // 提示用户打标机未就绪
    ElMessage.warning(t('basicData.pausea'));
  }
}
// 暂停
const handlea = async () => {
  try {
    let engineeringId = window.localStorage.getItem('engineeringId')
    console.log(engineeringId);
    if (engineeringId !== '') {
      const response = await request.post('/loadGlass/engineering/engineering/pauseTask', {
        engineeringId: engineeringId,
        state: 0,
      })
    if (response.code == 200) {
      ElMessage.success(response.message);
      blinda.value = false;
      // tableData.splice([]);
    } else {
      // 请求失败,显示错误消息
      ElMessage.error(response.message);
    }
  }
    else  {
      ElMessage({
        type: 'info',
        message: t('basicData.infonull'),
      })
    }
  } catch (error) {
    // 处理错误
    console.error(error);
  }
}
// 停止任务
const handleb = async () => {
  try {
    let engineeringId = window.localStorage.getItem('engineeringId')
    console.log(engineeringId);
    if (engineeringId !== '') {
      const response = await request.post('/loadGlass/engineering/engineering/pauseTask', {
        engineeringId: engineeringId,
        state: 0,
      })
      if (response.code == 200) {
        // 绑定成功,处理逻辑
        ElMessage.success(response.message);
        // window.location.reload()
        blindb.value = false;
        tableData.splice([]);
        // 请求失败,显示错误消息
        ElMessage.error(response.message);
      }
    } else {
      ElMessage({
        type: 'info',
        message: t('basicData.infonull'),
      })
    }
  } catch (error) {
    // 处理错误
    console.error(error);
  }
}
onMounted(fetchTableData);
function getStatusText(state: number) {
  switch (state) {
    case 0:
      return t('basicData.waiting');
    case 1:
      return t('basicData.up');
    case 2:
      return t('basicData.up');
    case 100:
      return t('basicData.finish');
  }
}
function getStatusType(state: number) {
  switch (state) {
    case 0:
      return 'warning';
    case 1:
      return 'primary';
    case 2:
      return 'primary';
    case 100:
      return 'success';
  }
}
// 开始上片
const handleBind = (row) => {
  blind.value = true; // 打开绑定架子对话框
};
// 暂停
const handleBinda = (row) => {
  blinda.value = true;
};
// 停止任务
const handleBindb = (row) => {
  blindb.value = true;
};
// 删除
const handleBindRacka = (row) => {
  workstationId.value = row.workstationId;
  adda.value = true;
};
// 定义一个响应式引用,用于存储颜色状态
const markingMachineStatus = ref('#911005');
const cuttingMachineStatus = ref('#911005');
// 定义一个方法来改变颜色状态
const confirmMarkingMachine = () => {
  markingMachineStatus.value = 'green';
};
const confirmCuttingMachine = () => {
  cuttingMachineStatus.value = 'green';
};
const toggleEnableState = async (row: any) => {
  // 检查 id 是否为空
  if (!row.id) {
    ElMessage.error(t('basicData.updatanull'));
    return; // 如果 id 为空,则不执行后续操作
  }
  const newState = row.state === 100 ? 0 : 100;
  try {
    // 发送请求到后端更新状态
    const response = await request.post('/loadGlass/up-patten-usage/updateGlassState', {id: row.id, state: newState});
    if (response.code === 200) {
      ElMessage.success(response.message);
      row.state = newState;
    } else {
      ElMessage.error(response.message);
    }
  } catch (error) {
    // 处理请求错误
    ElMessage.error(t('basicData.glassnull'));
  }
};
// 上片机联机状态
// const wsUrl = `ws://${WebSocketHost}:${host}/api/loadGlass/api/talk/loadGlass`;
// const ws = new WebSocket(wsUrl);
// ws.onopen = () => {
//   console.log('WebSocket连接已打开');
// };
// // 监听WebSocket的错误事件
// ws.onerror = (error) => {
//   console.error('WebSocket发生错误:', error);
// };
// // 监听WebSocket的关闭事件
// ws.onclose = (event) => {
//   if (event.wasClean) {
//     console.log('WebSocket连接已正常关闭');
//   } else {
//     console.error('WebSocket连接异常关闭');
//   }
// };
// // 监听WebSocket的消息事件
// ws.onmessage = (event) => {
//   try {
//     const data = JSON.parse(event.data.replace('<END>', '')); // 解析消息为JSON
//     if (data && Array.isArray(data.InkageStatus) && data.InkageStatus.length > 0) {
// if(data.InkageStatus!=null){
//       const status = data.InkageStatus[0];
//       cuttingMachine.value = status;
//             upstatus.value = status === '1' ? t('basicData.machine') : t('basicData.machineaa');
//       cuttingMachineStatusColor.value = status === '1' ? 'green' : '#911005';
//       inKageWord.value = status === '1' ? 0 : 1;
// }
//     } else {
//       // 处理错误情况或无效数据
//       // console.error('接收到的数据无效', data);
//     }
//   } catch (error) {
//     // console.error('解析WebSocket消息时发生错误', error);
//   }
// };
const confirmCutting = async () => {
  try {
    const response = await request.post('/loadGlass/LoadGlass/updateMesInkageLoad',
        inKageWord.value
    );
    if (response.code == 200) {
      const status = response.data.status;
      upstatus.value = status === '1' ? t('basicData.machine') : t('basicData.machineaa');
      cuttingMachineStatusColor.value = status === '1' ? 'green' : '#911005';
      // 显示成功消息
      ElMessage.success(response.message);
    } else {
      ElMessage.error(response.message || '请求失败');
    }
  } catch (error) {
    // 处理错误
    console.error('请求时发生错误', error);
    ElMessage.error('请求时发生错误');
  }
};
</script>
<template>
  <div>
    <div id="dotClass">
      <div>{{ $t('basicData.laserprinting') }}</div>
      <i :style="{ marginTop: '2px', backgroundColor: markingMachineStatus, width: '18px', height: '18px', borderRadius: '50%', display: 'block' }"></i>
      <el-button @click="confirmMarkingMachine" style="margin-left: 30px;margin-top: -3px;">{{
          $t('basicData.yes')
        }}
      </el-button>
      <div style="margin-left: 70px;">{{ $t('basicData.cuttingmachine') }}</div>
      <i :style="{ marginTop: '2px', backgroundColor: cuttingMachineStatus, width: '18px', height: '18px', borderRadius: '50%', display: 'block' }"></i>
      <el-button @click="confirmCuttingMachine" style="margin-left: 30px;margin-top: -3px;">{{
          $t('basicData.yes')
        }}
      </el-button>
      <div style="margin-left: 70px;">{{ upstatus }}</div>
      <i :style="{ marginTop: '2px', backgroundColor: cuttingMachineStatusColor, width: '18px', height: '18px', borderRadius: '50%', display: 'block' }"></i>
      <el-button @click="confirmCutting" style="margin-left: 30px;margin-top: -3px;">{{
          $t('basicData.change')
        }}
      </el-button>
    </div>
    <el-button :disabled="!canSelectProject" style="margin-top: 5px;margin-left: 15px;" type="primary"
               @click="selectproject">{{ $t('Mounting.previewproject') }}
    </el-button>
    <el-button :disabled="!canSelectProject"
               :style="{ backgroundColor: canStartLoading ? 'green' : 'initial',color: canStartLoading ? 'white' : 'black', }"
               style="margin-top: 5px;margin-left: 20px;" @click="handleBind">{{ $t('basicData.startloading') }}
    </el-button>
    <el-button style="margin-top: 5px;margin-left: 20px;" id="searchButton" type="warning" @click="handleBinda">
      {{ $t('basicData.stop') }}
    </el-button>
    <el-button style="margin-top: 5px;margin-left: 20px;" id="searchButton" type="info" @click="handlezhiban">
      {{ $t('searchOrder.dutyinformation') }}
    </el-button>
    <el-select v-model="selectValuesa[0]" clearable :placeholder="$t('film.taskstatus')"
               style="margin-top: 5px;margin-left: 20px;">
      <el-option :label="$t('film.built')" value="1"></el-option>
      <el-option :label="$t('film.execution')" value="2"></el-option>
      <el-option :label="$t('film.finish')" value="3"></el-option>
    </el-select>
    <el-select v-model="selectValuesa[1]" clearable :placeholder="$t('film.tasktype')"
               style="margin-top: 5px;margin-left: 20px;">
      <el-option :label="$t('film.stocke')" value="1"></el-option>
      <el-option :label="$t('film.outbound')" value="2"></el-option>
      <el-option :label="$t('film.dispatch')" value="3"></el-option>
    </el-select>
    <el-button type="primary" style="margin-left: 10px;" @click="selectReportData()">{{
        $t('film.inquire')
      }}
    </el-button>
    <el-card style="flex: 1;margin-left: 10px;margin-top: 15px;" v-loading="loading">
      <div style="width: 98%; height: calc(100% - 35px); overflow-y: auto;">
        <el-table
            height="350"
            ref="table"
            :header-cell-style="{background:'#F2F3F5 ',color:'#1D2129'}"
            :data="tableData"
        >
          <el-table-column prop="layoutSequence" :label="$t('basicData.layoutSequence')" width="100" align="center"/>
          <el-table-column prop="engineeringId" :label="$t('basicData.projectnumber')" width="200" align="center"/>
          <el-table-column prop="width" :label="$t('basicData.glasswidth')" align="center"/>
          <el-table-column prop="height" :label="$t('basicData.glassheight')" align="center"/>
          <el-table-column prop="filmsId" :label="$t('basicData.coatingtypes')" align="center"/>
          <el-table-column :label="$t('basicData.quantity')" align="center">
            <template #default="{ row }">
              <!-- 这里总是显示 1 -->
              <span>{{ 1 }}</span>
            </template>
          </el-table-column>
          <el-table-column prop="thickness" :label="$t('basicData.thickness')" align="center"/>
          <!-- <el-table-column
                align="center"
                label="状态"
                min-width="80"
                prop="state"
              >
              <template #default="scope">
            <el-tag :type="getStatusType(scope.row.state)">
              {{ getStatusText(scope.row.state) }}
            </el-tag>
          </template>  -->
          <el-table-column
              align="center"
              :label="$t('basicData.startstatus')"
              min-width="80"
              prop="state"
          >
            <template #default="scope">
              <el-tag
                  :type="scope.row.state === 100 ? 'success' : 'warning'"
                  @click="toggleEnableState(scope.row)"
          >
                {{ scope.row.state === 100 ? $t('basicData.pass') : $t('basicData.waiting') }}
              </el-tag>
        </template>
          </el-table-column>
    </el-table>
      </div>
    </el-card>
  <el-dialog v-model="blind" top="30vh" width="25%" :title="$t('basicData.startfilm')">
    <template #footer>
      <div id="dialog-footer">
        <el-button type="primary" @click="handle">
          {{ $t('basicData.confirm') }}
        </el-button>
        <el-button @click="blind = false">{{ $t('basicData.cancel') }}</el-button>
      </div>
    </template>
  </el-dialog>
<el-dialog v-model="dialoglea" top="15vh" width="70%" :title="$t('searchOrder.dutyinformation')">
    <el-table  ref="table" style="margin-top: 20px;height: 300px;"
        :data="tableDatax" :header-cell-style="{background:'#F2F3F5 ',color:'#1D2129'}">
          <el-table-column prop="line" fixed align="center" :label="$t('searchOrder.line')"/>
          <el-table-column prop="workProcesses" fixed align="center" :label="$t('searchOrder.process')" />
          <el-table-column prop="teamsGroupsName" align="center" :label="$t('searchOrder.team')">
        <template #default="{ row }">
          <el-input v-model="row.teamsGroupsName" autocomplete="off" min-width="150"/>
        </template>
      </el-table-column>
          <el-table-column prop="deviceName" align="center" :label="$t('searchOrder.basic')">
            <template #default="{ row }">
          <el-input v-model="row.deviceName" autocomplete="off" min-width="150"/>
        </template>
        </el-table-column>
        </el-table>
        <template #footer>
      <div id="dialog-footer">
        <el-button type="primary" @click="handleConfirm">
          {{ $t('searchOrder.add') }}
        </el-button>
        <el-button @click="dialoglea = false">{{ $t('searchOrder.cancel') }}</el-button>
      </div>
    </template>
</el-dialog>
    <el-dialog v-model="blinda" top="30vh" width="25%" :title="$t('basicData.whetherpause')">
      <template #footer>
        <div id="dialog-footer">
          <el-button type="primary" @click="handlea">
            {{ $t('basicData.confirm') }}
          </el-button>
          <el-button @click="blinda = false">{{ $t('basicData.cancel') }}</el-button>
        </div>
      </template>
    </el-dialog>
    <!-- <el-dialog v-model="blindb" top="30vh" width="25%" title="是否停止任务?" >
      <template #footer>
        <div id="dialog-footer">
          <el-button type="primary" @click="handleb">
            确认
          </el-button>
          <el-button @click="blindb = false">取消</el-button>
        </div>
      </template>
    </el-dialog> -->
    <div id="parent">
      <img src="../../assets/shangpian.png" alt=""
           style="max-width: 40%;max-height: 40%;margin-top: 20px;margin-left: 340px;">
      <div id="overlay" v-show="flake"></div>
      <div id="overlaya" v-show="flakea"></div>
      <div id="overlayb" v-show="flakeb"></div>
      <div id="overlayc" v-show="flakec"></div>
    </div>
    <div style="margin-top: -300px;margin-left: 680px;">
      <el-table :data="tableDataa" border style="width: 85%"
                :header-cell-style="{background:'#F2F3F5 ',color:'#1D2129'}"
      >
        <el-table-column prop="workstationId" align="center" :label="$t('basicData.station')" min-width="60"/>
        <el-table-column prop="patternWidth" align="center" :label="$t('basicData.width')" min-width="80"/>
        <el-table-column prop="patternHeight" align="center" :label="$t('basicData.height')" min-width="80"/>
        <el-table-column prop="filmsId" align="center" :label="$t('basicData.coatingtypes')" min-width="80"/>
        <el-table-column prop="number" align="center" :label="$t('basicData.quantity')" min-width="80"/>
        <el-table-column fixed="right" :label="$t('basicData.operate')" align="center" width="150">
          <template #default="scope">
            <el-button size="mini" type="text" plain @click="handleBindRack(scope.row)">{{
                $t('basicData.add')
              }}
            </el-button>
            <el-button size="mini" type="text" plain @click="handleBindRacka(scope.row)">{{
                $t('basicData.delete')
              }}
            </el-button>
          </template>
        </el-table-column>
      </el-table>
    </div>
    <el-dialog v-model="add" top="23vh" width="45%" :title="$t('basicData.addglass')">
      <div style="margin-left: -50px;margin-top: 10px;margin-bottom: 10px;">
        <el-form size="mini" label-width="150px">
          <el-form label-width="70px" label-position="right">
            <el-row style="margin-top: -15px;margin-bottom: -2px;">
              <el-col :span="6">
                <div id="dt" style="font-size: 15px;">
                  <div>
                    <el-form-item :label="$t('basicData.widtha')" :required="true" style="width: 14vw">
               <el-select
                      v-model="selectedValue"
                      filterable
                      clearable
                      :placeholder="$t('basicData.selectwidth')"
                      style="width: 220px"
                      @input="handleInputChangea"
                    >
                 <el-option
                    v-for="item in selectOptions"
                    :key="item.id"
                    :label="item.label"
                    :value="item.value"
                 />
               </el-select>
              </el-form-item>
              </div></div>
          </el-col>
          <el-col :span="9">
            <div id="dta" style="font-size: 15px;">
        <div>
          <el-form-item :label="$t('basicData.heighta')" :required="true" style="width: 14vw">
            <el-select
                      v-model="selectedValuea"
                      filterable
                      clearable
                      :placeholder="$t('basicData.selectheight')"
                      style="width: 220px"
                      @input="handleInputChangea"
                    >
                 <el-option
                    v-for="item in selectOptionsa"
                    :key="item.id"
                    :label="item.label"
                    :value="item.value"
                 />
               </el-select>
              </el-form-item></div>
              </div>
          </el-col>
        </el-row>
        <el-row style="margin-top: 10px;">
          <el-col :span="6">
              <div id="dt" style="font-size: 15px;">
        <div>
              <el-form-item :label="$t('basicData.coatingtypesa')"  :required="true" style="width: 14vw;">
                <el-select
                      v-model="selectedValueb"
                      filterable
                      clearable
                      :placeholder="$t('basicData.selectcoatingtypes')"
                      style="width: 220px"
                      @input="handleInputChangea"
                    >
                 <el-option
                    v-for="item in selectOptionsb"
                    :key="item.id"
                    :label="item.label"
                    :value="item.value"
                 />
               </el-select>
              </el-form-item></div></div>
          </el-col>
          <el-col :span="9">
            <div id="dta" style="font-size: 15px;">
        <div>
              <el-form-item :label="$t('basicData.thicknessa')" :required="true" style="width: 14vw">
                <el-select
                      v-model="selectedValuec"
                      filterable
                      clearable
                      :placeholder="$t('basicData.selectthickness')"
                      style="width: 220px"
                      @input="handleInputChangea"
                    >
                 <el-option
                    v-for="item in selectOptionsc"
                    :key="item.id"
                    :label="item.label"
                    :value="item.value"
                 />
               </el-select>
                <!-- <el-input v-model="patternThickness" autocomplete="off" /> -->
              </el-form-item></div></div>
          </el-col>
        </el-row>
        <el-row style="margin-top: 10px;">
          <el-col :span="6">
              <div id="dt" style="font-size: 15px;">
        <div>
              <el-form-item :label="$t('basicData.quantitya')" :required="true" style="width: 14vw;">
                <el-input :placeholder="$t('basicData.selectquantity')" v-model="number" autocomplete="off" />
              </el-form-item></div></div>
          </el-col>
        </el-row>
        </el-form>
            </el-form>
          </div>
    <template #footer>
      <div id="dialog-footer">
        <el-button type="primary" @click="handleConfirm">
          {{ $t('basicData.confirm') }}
        </el-button>
        <el-button @click="add = false">{{ $t('basicData.cancel') }}</el-button>
      </div>
    </template>
  </el-dialog>
  <el-dialog v-model="adda" top="30vh" width="25%" :title="$t('basicData.deletemessage')">
    <template #footer>
      <div id="dialog-footer">
        <el-button type="primary" @click="handleConfirma">
          {{ $t('basicData.confirm') }}
        </el-button>
        <el-button @click="adda = false">{{ $t('basicData.cancel') }}</el-button>
      </div>
    </template>
  </el-dialog>
  </div>
  <el-dialog v-model="dialogFormVisible" top="24vh" width="30%" :title="$t('basicData.project')">
    <div style="margin-left: 50px;margin-bottom: 10px;">
      <el-form-item :label="$t('basicData.projectnumber')" :required="true">
        <el-select
            v-model="selectedProjectNo"
            filterable
            clearable
            :placeholder="$t('basicData.plselectproject')"
            style="width: 220px"
            @input="handleInputChange"
        >
          <el-option
              v-for="item in titleSelectJson['processType']"
         :key="item.id"
         :label="item.projectNo"
         :value="item.projectNo"
      />
    </el-select>
              </el-form-item>
          </div>
    <template #footer>
      <div id="dialog-footer">
        <el-button type="primary" @click="handleup">
          {{ $t('basicData.confirm') }}
        </el-button>
        <el-button @click="dialogFormVisible = false">{{ $t('basicData.cancel') }}</el-button>
      </div>
    </template>
  </el-dialog>
</template>
<style scoped>
#dt { display:block; float:left;line-height: 20px;margin-left: 100px;}
#dta { display:block; float:left;line-height: 20px;margin-left: 80%;}
#dialog-footer{
  text-align: center;
  margin-top: -15px;
}
#dotClass {
  display: flex;
  margin-left: 20px;
  size: 50px;
  margin-top: 20px;
  margin-bottom: 10px;
}
#parent {
  position: relative;
  width: 1500px;
  margin-left: -300px
}
#overlayb {
  position: absolute;
  z-index: 1;
  width: 228px;
  height: 16px;
  background-color: #529b2e;
  margin-top: -303px;
  margin-left: 355px;
}
#overlayc {
  position: absolute;
  z-index: 1;
  width: 228px;
  height: 16px;
  background-color: #529b2e;
  margin-top: -303px;
  margin-left: 703px;
}
#overlay {
  position: absolute;
  z-index: 1;
  width: 228px;
  height: 16px;
  background-color: #529b2e;
  margin-top: -45px;
  margin-left: 355px;
}
#overlaya {
  position: absolute;
  z-index: 1;
  width: 228px;
  height: 16px;
  background-color: #529b2e;
  margin-top: -45px;
  margin-left: 703px;
}
</style>
UI-Project/src/views/Slicecage/slicecage.vue
@@ -1,16 +1,15 @@
<script lang="ts" setup>
import { useI18n } from 'vue-i18n'
  const { t } = useI18n()
  let language = ref(localStorage.getItem('lang') || 'zh')
import {Search} from "@element-plus/icons-vue";
import {useI18n} from 'vue-i18n'
import {useRouter} from "vue-router"
const router = useRouter()
import request from "@/utils/request"
import { WebSocketHost ,host} from '@/utils/constants'
import { ref, onMounted , onBeforeUnmount, reactive, computed,onUnmounted } from "vue";
import { initializeWebSocket, closeWebSocket } from '@/utils/WebSocketService';
import { ElMessage, ElMessageBox } from 'element-plus'
import { tr } from "element-plus/es/locale";
import {host, WebSocketHost} from '@/utils/constants'
import {computed, onBeforeUnmount, onMounted, onUnmounted, reactive, ref} from "vue";
import {closeWebSocket, initializeWebSocket} from '@/utils/WebSocketService';
import {ElMessage, ElMessageBox} from 'element-plus'
const {t} = useI18n()
let language = ref(localStorage.getItem('lang') || 'zh')
const router = useRouter()
const dialogFormVisible = ref(false)
const dialoglea = ref(false)
const dialogFormVisiblea = ref(false)
@@ -362,21 +361,22 @@
  }  
}; 
 // 指定钢化
 const brokee = async(row) => {
const brokee = async (row, temperingFeedSequence) => {
  try {
    const confirmResult = await ElMessageBox.confirm(
      t('searchOrder.specifytemperinga'),
      t('searchOrder.prompt'),
      {
        confirmButtonText: t('searchOrder.yes'),
        cancelButtonText: t('searchOrder.cancel'),
        type: 'warning',
      }
    const confirmResult = await ElMessageBox.confirm(
        t('searchOrder.specifytemperinga'),
        t('searchOrder.prompt'),
        {
          confirmButtonText: t('searchOrder.yes'),
          cancelButtonText: t('searchOrder.cancel'),
          type: 'warning',
        }
    ); 
    if (confirmResult === 'confirm') {  
      const response = await request.post("/cacheVerticalGlass/bigStorageCageDetails/TemperingGlass",{
        engineerId: row.engineer_id,
        temperingLayoutId: row.tempering_layout_id,
        temperingFeedSequence: temperingFeedSequence
    });
    if (response.code === 200) {
      ElMessage.success(response.message);
@@ -386,7 +386,8 @@
    }  
  } catch (error) {  
    console.error('发生错误:', error);  
  }
  }
  handleganghua();
}; 
 // 指定工程
 const brokek = async(row) => {  
@@ -1561,10 +1562,18 @@
          <el-table-column prop="count4" align="center" :label="$t('破损/拿走数量')" min-width="150" />
          <el-table-column fixed="right" :label="$t('searchOrder.operate')" align="center" width="250">
            <template #default="scope">
              <el-button size="mini" type="text" plain @click="brokee(scope.row)">{{ $t('searchOrder.specifytempering') }}</el-button>
              <el-button size="mini" type="text" plain @click="brokek(scope.row)">{{ $t('searchOrder.specifyengineerid') }}</el-button>
              <el-button size="mini" type="text" plain @click="brokee(scope.row,1)">
                {{ $t('searchOrder.specifytempering') }}
              </el-button>
              <el-button size="mini" type="text" plain @click="brokee(scope.row,0)">{{
                  $t('searchOrder.specifyout')
                }}
              </el-button>
              <el-button size="mini" type="text" plain @click="brokek(scope.row)">{{
                  $t('searchOrder.specifyengineerid')
                }}
              </el-button>
            </template>
        </el-table-column>
        </el-table>
</el-dialog>
UI-Project/src/views/UnLoadGlass/PrintCustomLabelSemi1.vue
@@ -1,8 +1,7 @@
<script setup>
import request from "@/utils/request"
import {ElDatePicker, ElMessage} from "element-plus"
import {nextTick, onMounted, onUnmounted, reactive, ref, watch} from "vue"
import {Search} from "@element-plus/icons-vue"
import {ElMessage} from "element-plus"
import {onMounted, ref} from "vue"
// import {useRouter} from 'vue-router'
// import {changeFilterEvent, filterChanged} from "@/hook"
// import {useI18n} from 'vue-i18n'
@@ -36,14 +35,15 @@
let props = defineProps({
  printFlowCardId: null,
  printLayer: null,
  printGlassId: null,
})
onMounted(async () => {
  console.log(props.printFlowCardId,props.printLayer)
  const response = await request.post('/unLoadGlass/downGlassInfo/downGlassLabelPrint',{
        flowCardId:props.printFlowCardId,
        layer:props.printLayer
    });
  const response = await request.post('/unLoadGlass/downGlassInfo/downGlassLabelPrint', {
    flowCardId: props.printFlowCardId,
    layer: props.printLayer,
    glassId: props.printGlassId
  });
        if (response.code == 200) {
          console.log("lastList.value",response.data)
          lastList.value=response.data;
UI-Project/src/views/UnLoadGlass/loadmachinerack.vue
@@ -1,18 +1,14 @@
<script setup>
import { onBeforeUnmount, onMounted, onUnmounted, reactive, ref } from "vue";
import { useRouter } from "vue-router"
import { useI18n } from 'vue-i18n'
import { ElMessage } from 'element-plus'
import {onBeforeUnmount, onMounted, onUnmounted, reactive, ref} from "vue";
import {useRouter} from "vue-router"
import {useI18n} from 'vue-i18n'
import {ElMessage} from 'element-plus'
import request from "@/utils/request";
import { closeWebSocket, initializeWebSocket } from '@/utils/WebSocketService';
import { host, WebSocketHost } from '@/utils/constants'
import PrintFlow from "@/views/UnLoadGlass/PrintFlow.vue";
import Landingindication from "./Landingindication.vue";
import Landingindicationtwo from "./Landingindicationtwo.vue";
import PrintLabel from "@/views/UnLoadGlass/PrintCustomLabelSemi1.vue";
import {closeWebSocket, initializeWebSocket} from '@/utils/WebSocketService';
import {host, WebSocketHost} from '@/utils/constants'
const router = useRouter()
const { t } = useI18n()
const {t} = useI18n()
let language = ref(localStorage.getItem('lang') || 'zh')
const printLoading = ref(true)
const fullFlowCard = ref('')
@@ -44,6 +40,7 @@
const dialogTableVisible1 = ref(false)
const printFlowCardId = ref('')
const printLayer = ref('')
const printGlassId = ref('')
const now = new Date();
const timeRange = ref([])
const browser = ref(false)
@@ -234,6 +231,9 @@
      scanGlass.value.width = height;
      scanGlass.value.height = width;
    }
    if (autoPrint.value == true && browser.value == true) {
      open1(scanGlass);
    }
  }
  //自动打印
@@ -338,6 +338,7 @@
  printFlowCardId.value = row.flowCardId;
  printLayer.value = row.layer
  printGlassId.value = row.glassId
  dialogTableVisible1.value = true;
  setTimeout(() => {
    printFlowCard1();
@@ -536,6 +537,9 @@
              </div>
              <div style="font-size: 50px; text-align: center;position: absolute;top:0px;left:170px;">
                <div>人工下片当前玻璃信息</div>
                <div>
                  <el-button type="primary" @click="open1(takeGlass)">打印标签</el-button>
                </div>
                <div>{{ takeGlass.flowCardId }}</div>
                <div>{{ takeGlass.layer }}</div>
                <div>{{ takeGlass.glassId }}</div>
@@ -551,6 +555,9 @@
              </div>
              <div style="font-size: 50px; text-align: center;position: absolute;top:0px;left:200px;">
                <div>扫码枪当前玻璃信息</div>
                <div>
                  <el-button type="primary" @click="open1(scanGlass)">打印标签</el-button>
                </div>
                <div>{{ scanGlass.flowCardId }}</div>
                <div>{{ scanGlass.layer }}</div>
                <div>{{ scanGlass.glassId }}</div>
@@ -622,7 +629,8 @@
      style="width: 100%;height: 100%" />
  </el-dialog>
  <el-dialog id="sizePrintCalrd1" v-model="dialogTableVisible1" destroy-on-close>
    <print-label id="printFlowCard" :printFlowCardId="printFlowCardId" :printLayer="printLayer" style="" />
    <print-label id="printFlowCard" :printFlowCardId="printFlowCardId" :printLayer="printLayer"
                 :printGlassId="printGlassId" style=""/>
  </el-dialog>
</template>
hangzhoumesParent/common/opcuaClient/pom.xml
File was deleted
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/configuration/MiloProperties.java
File was deleted
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/exception/EndPointNotFoundException.java
File was deleted
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/exception/IdentityNotFoundException.java
File was deleted
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/model/ReadWriteEntity.java
File was deleted
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/model/WriteEntity.java
File was deleted
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/pool/MiloConnectPool.java
File was deleted
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/runner/BrowseNodeRunner.java
File was deleted
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/runner/BrowseRunner.java
File was deleted
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/runner/ReadValuesRunner.java
File was deleted
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/runner/WriteValuesRunner.java
File was deleted
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/runner/subscription/SubscriptionCallback.java
File was deleted
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/runner/subscription/SubscriptionRunner.java
File was deleted
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/service/MiloService.java
File was deleted
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/utils/CustomUtil.java
File was deleted
hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/utils/KeyStoreLoader.java
File was deleted
hangzhoumesParent/common/opcuaClient/src/main/resources/META-INF/spring.factories
File was deleted
hangzhoumesParent/common/opcuaClient/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
File was deleted
hangzhoumesParent/common/opcuaClient/src/main/resources/application.yml
File was deleted
hangzhoumesParent/common/pom.xml
@@ -15,7 +15,6 @@
    <modules>
        <module>servicebase</module>
        <module>springsecurity</module>
        <module>opcuaClient</module>
    </modules>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
hangzhoumesParent/common/servicebase/pom.xml
@@ -38,6 +38,13 @@
            <artifactId>sdk-server</artifactId>
            <version>0.6.8</version>
        </dependency>
        <dependency>
            <groupId>com.kangaroohy</groupId>
            <artifactId>milo-spring-boot-starter</artifactId>
            <version>3.0.6.12</version>
        </dependency>
    </dependencies>
</project>
hangzhoumesParent/common/servicebase/src/main/java/com/kangaroohy/milo/configuration/MiloAutoConfiguration.java
File was renamed from hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/configuration/MiloAutoConfiguration.java
@@ -1,8 +1,8 @@
package com.mes.milo.configuration;
package com.kangaroohy.milo.configuration;
import com.mes.milo.pool.MiloConnectFactory;
import com.mes.milo.pool.MiloConnectPool;
import com.mes.milo.service.MiloService;
import com.kangaroohy.milo.pool.MiloConnectFactory;
import com.kangaroohy.milo.pool.MiloConnectPool;
import com.kangaroohy.milo.service.MiloService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig;
import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
hangzhoumesParent/common/servicebase/src/main/java/com/kangaroohy/milo/pool/MiloConnectFactory.java
File was renamed from hangzhoumesParent/common/opcuaClient/src/main/java/com/mes/milo/pool/MiloConnectFactory.java
@@ -1,9 +1,9 @@
package com.mes.milo.pool;
package com.kangaroohy.milo.pool;
import com.mes.milo.configuration.MiloProperties;
import com.mes.milo.exception.EndPointNotFoundException;
import com.mes.milo.exception.IdentityNotFoundException;
import com.mes.milo.utils.CustomUtil;
import com.kangaroohy.milo.configuration.MiloProperties;
import com.kangaroohy.milo.exception.EndPointNotFoundException;
import com.kangaroohy.milo.exception.IdentityNotFoundException;
import com.kangaroohy.milo.utils.CustomUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.pool2.KeyedPooledObjectFactory;
import org.apache.commons.pool2.PooledObject;
hangzhoumesParent/common/servicebase/src/main/java/com/mes/common/config/Const.java
@@ -180,4 +180,23 @@
    public static final Integer UNLOAD_GLASS_OUT = 1;
    public static final Integer UNLOAD_GLASS_DOWN = 2;
    /**
     * 原片仓储任务类型
     * 进片任务1
     * 出片任务2
     */
    public static final Integer RAW_GLASS_TASK_TYPE_IN = 1;
    public static final Integer RAW_GLASS_TASK_TYPE_OUT = 2;
    public static final Integer RAW_GLASS_TASK_TYPE_DISPATCH = 3;
    /**
     * 原片仓储任务类型
     * 进片任务1
     * 出片任务2
     */
    public static final Integer ENGINEERING_NEW = 0;
    public static final Integer ENGINEERING_RUNNING = 1;
}
hangzhoumesParent/common/servicebase/src/main/java/com/mes/pp/entity/OptimizeHeatDetail.java
New file
@@ -0,0 +1,116 @@
package com.mes.pp.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
/**
 * <p>
 *
 * </p>
 *
 * @author zhoush
 * @since 2024-04-16
 */
@Data
@EqualsAndHashCode(callSuper = false)
public class OptimizeHeatDetail implements Serializable {
    private static final long serialVersionUID = 1L;
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;
    /**
     * 工程号
     */
    private String projectNo;
    /**
     * 流程卡号
     */
    private String processId;
    /**
     * 补片状态:补片1,0非补片;2024.0409新增
     */
    private Integer patchState;
    /**
     * 层
     */
    private Integer layer;
    /**
     * 订单内排序
     */
    private Integer orderSort;
    /**
     * 版图编号
     */
    private Integer layoutId;
    /**
     * 版图内排序
     */
    private Integer sort;
    /**
     * 小片编号
     */
    private Integer glassId;
    /**
     * 小片宽
     */
    private double width;
    /**
     * 小片高
     */
    private double height;
    /**
     * 配片宽
     */
    private double pairWidth;
    /**
     * 配片高
     */
    private double pairHeight;
    /**
     * x坐标
     */
    private double xAxis;
    /**
     * y坐标
     */
    private double yAxis;
    /**
     * 旋转角度(逆时针)
     */
    private double rotateAngle;
    /**
     * 创建人
     */
    private String creater;
    /**
     * 创建时间
     */
    private Data createTime;
    /**
     * 修改时间
     */
    private Data updateTime;
    @TableField("intRemark")
    private Integer intRemark;
    @TableField("strRemark")
    private String strRemark;
}
hangzhoumesParent/common/servicebase/src/main/java/com/mes/pp/entity/OptimizeHeatLayout.java
New file
@@ -0,0 +1,70 @@
package com.mes.pp.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.util.Date;
/**
 * <p>
 *
 * </p>
 *
 * @author zhoush
 * @since 2024-04-16
 */
@Data
@EqualsAndHashCode(callSuper = false)
public class OptimizeHeatLayout implements Serializable {
    private static final long serialVersionUID = 1L;
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;
    /**
     * 工程号
     */
    private String projectNo;
    /**
     * 版图Id
     */
    private Integer layoutId;
    /**
     * 玻璃数量
     */
    private Integer glassQty;
    /**
     * 版图玻璃面积
     */
    private double glassArea;
    /**
     * 装载率
     */
    private double layoutRate;
    /**
     * 创建人
     */
    private Integer creater;
    /**
     * 创建时间
     */
    private Date createTime;
    @TableField("intRemark")
    private Integer intRemark;
    @TableField("strRemark")
    private String strRemark;
}
hangzhoumesParent/common/servicebase/src/main/java/com/mes/pp/mapper/OptimizeHeatDetailMapper.java
New file
@@ -0,0 +1,19 @@
package com.mes.pp.mapper;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.github.yulichang.base.MPJBaseMapper;
import com.mes.pp.entity.OptimizeDetail;
import com.mes.pp.entity.OptimizeHeatDetail;
/**
 * <p>
 * Mapper 接口
 * </p>
 *
 * @author zhoush
 * @since 2024-04-16
 */
@DS("pp")
public interface OptimizeHeatDetailMapper extends MPJBaseMapper<OptimizeHeatDetail> {
}
hangzhoumesParent/common/servicebase/src/main/java/com/mes/pp/mapper/OptimizeHeatLayoutMapper.java
New file
@@ -0,0 +1,19 @@
package com.mes.pp.mapper;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.github.yulichang.base.MPJBaseMapper;
import com.mes.pp.entity.OptimizeDetail;
import com.mes.pp.entity.OptimizeHeatLayout;
/**
 * <p>
 * Mapper 接口
 * </p>
 *
 * @author zhoush
 * @since 2024-04-16
 */
@DS("pp")
public interface OptimizeHeatLayoutMapper extends MPJBaseMapper<OptimizeHeatLayout> {
}
hangzhoumesParent/common/servicebase/src/main/java/com/mes/pp/service/OptimizeHeatDetailService.java
New file
@@ -0,0 +1,17 @@
package com.mes.pp.service;
import com.github.yulichang.base.MPJBaseService;
import com.mes.pp.entity.OptimizeDetail;
import com.mes.pp.entity.OptimizeHeatDetail;
/**
 * <p>
 * 服务类
 * </p>
 *
 * @author zhoush
 * @since 2024-04-16
 */
public interface OptimizeHeatDetailService extends MPJBaseService<OptimizeHeatDetail> {
}
hangzhoumesParent/common/servicebase/src/main/java/com/mes/pp/service/OptimizeHeatLayoutService.java
New file
@@ -0,0 +1,17 @@
package com.mes.pp.service;
import com.github.yulichang.base.MPJBaseService;
import com.mes.pp.entity.OptimizeDetail;
import com.mes.pp.entity.OptimizeHeatLayout;
/**
 * <p>
 * 服务类
 * </p>
 *
 * @author zhoush
 * @since 2024-04-16
 */
public interface OptimizeHeatLayoutService extends MPJBaseService<OptimizeHeatLayout> {
}
hangzhoumesParent/common/servicebase/src/main/java/com/mes/pp/service/impl/OptimizeHeatDetailServiceImpl.java
New file
@@ -0,0 +1,25 @@
package com.mes.pp.service.impl;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.github.yulichang.base.MPJBaseServiceImpl;
import com.mes.pp.entity.OptimizeDetail;
import com.mes.pp.entity.OptimizeHeatDetail;
import com.mes.pp.mapper.OptimizeDetailMapper;
import com.mes.pp.mapper.OptimizeHeatDetailMapper;
import com.mes.pp.service.OptimizeDetailService;
import com.mes.pp.service.OptimizeHeatDetailService;
import org.springframework.stereotype.Service;
/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author zhoush
 * @since 2024-04-16
 */
@Service
@DS("pp")
public class OptimizeHeatDetailServiceImpl extends MPJBaseServiceImpl<OptimizeHeatDetailMapper, OptimizeHeatDetail> implements OptimizeHeatDetailService {
}
hangzhoumesParent/common/servicebase/src/main/java/com/mes/pp/service/impl/OptimizeHeatLayoutServiceImpl.java
New file
@@ -0,0 +1,25 @@
package com.mes.pp.service.impl;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.github.yulichang.base.MPJBaseServiceImpl;
import com.mes.pp.entity.OptimizeDetail;
import com.mes.pp.entity.OptimizeHeatLayout;
import com.mes.pp.mapper.OptimizeDetailMapper;
import com.mes.pp.mapper.OptimizeHeatLayoutMapper;
import com.mes.pp.service.OptimizeDetailService;
import com.mes.pp.service.OptimizeHeatLayoutService;
import org.springframework.stereotype.Service;
/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author zhoush
 * @since 2024-04-16
 */
@Service
@DS("pp")
public class OptimizeHeatLayoutServiceImpl extends MPJBaseServiceImpl<OptimizeHeatLayoutMapper, OptimizeHeatLayout> implements OptimizeHeatLayoutService {
}
hangzhoumesParent/common/servicebase/src/main/java/com/mes/temperingglass/service/impl/TemperingGlassInfoServiceImpl.java
@@ -2,12 +2,12 @@
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.yulichang.base.MPJBaseServiceImpl;
import com.mes.temperingglass.entity.TemperingGlassInfo;
import com.mes.temperingglass.mapper.TemperingGlassInfoMapper;
import com.mes.temperingglass.service.TemperingGlassInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.github.yulichang.base.MPJBaseServiceImpl;
import java.util.List;
@@ -29,7 +29,7 @@
    public List<TemperingGlassInfo> selectWaitingGlass() {
        //获取等待进炉中的玻璃信息
        QueryWrapper<TemperingGlassInfo> wrapper = new QueryWrapper<>();
        wrapper.select("Top 1 *").in("state",1,0);
        wrapper.select("Top 1 *").in("state", 1, 0, -1);
        TemperingGlassInfo glass=temperingMapper.selectOne(wrapper);
        if(glass!=null) {
            QueryWrapper<TemperingGlassInfo> glassinfo = new QueryWrapper<>();
hangzhoumesParent/common/servicebase/src/main/java/com/mes/uppattenusage/entity/vo/UpPattenUsageVO.java
New file
@@ -0,0 +1,14 @@
package com.mes.uppattenusage.entity.vo;
import com.mes.uppattenusage.entity.UpPattenUsage;
import lombok.Data;
/**
 * @Author : zhoush
 * @Date: 2024/10/12 15:43
 * @Description:
 */
@Data
public class UpPattenUsageVO extends UpPattenUsage {
    private String groupNumber;
}
hangzhoumesParent/common/servicebase/src/main/java/com/mes/uppattenusage/mapper/UpPattenUsageMapper.java
@@ -2,7 +2,10 @@
import com.github.yulichang.base.MPJBaseMapper;
import com.mes.uppattenusage.entity.UpPattenUsage;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.mes.uppattenusage.entity.vo.UpPattenUsageVO;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
 * <p>
@@ -14,4 +17,5 @@
 */
public interface UpPattenUsageMapper extends MPJBaseMapper<UpPattenUsage> {
    List<UpPattenUsageVO> queryRawGlassByEngineeringId(@Param("engineeringId") String engineerId);
}
hangzhoumesParent/common/servicebase/src/main/resources/mapper/FlowCardMapper.xml
@@ -27,7 +27,7 @@
        on pd.prod_id = od.product_id and pd.glass_sort = ogd.technology_number
        where fc.process_id = #{processId}
        <if test="technologyNumber != 0">
            and a.layer = #{technologyNumber}
            and fc.technology_number = #{technologyNumber}
        </if>
        <if test="technologyNumber != 0">
            and position(fc.technology_number in #{technologyNumber})
hangzhoumesParent/common/servicebase/src/main/resources/mapper/UpPattenUsageMapper.xml
New file
@@ -0,0 +1,32 @@
<?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.mes.uppattenusage.mapper.UpPattenUsageMapper">
    <resultMap id="baseMap" type="com.mes.uppattenusage.entity.vo.UpPattenUsageVO">
        <result column="id" property="id"/>
        <result column="engineering_id" property="engineeringId"/>
        <result column="films_id" property="filmsId"/>
        <result column="width" property="width"/>
        <result column="height" property="height"/>
        <result column="thickness" property="thickness"/>
        <result column="layout_sequence" property="layoutSequence"/>
        <result column="state" property="state"/>
        <result column="group_number" property="groupNumber"/>
    </resultMap>
    <select id="queryRawGlassByEngineeringId" resultType="com.mes.uppattenusage.entity.vo.UpPattenUsageVO">
        SET @prev_width := NULL;
        SET @prev_height := NULL;
        SET @counter := 0;
        SELECT t.*,
               @counter := IF(@prev_width = width and @prev_height = height, @counter, @counter + 1) AS group_number,
               @prev_width := width,
               @prev_height := height
        FROM up_patten_usage t
        where t.engineering_id = #{engineeringId}
          and t.state = 0
        ORDER BY t.layout_sequence
    </select>
</mapper>
hangzhoumesParent/moduleService/CacheGlassModule/src/main/java/com/mes/edgstoragecage/service/EdgStorageCageDetailsService.java
@@ -31,6 +31,12 @@
     * @return
     */
    List<List<Map<String, Object>>> selectCurrentCutTerritory(String current);
    /**
     * 获取 工程下的钢化版图
     * @param current
     * @return
     */
    List<List<Map<String, Object>>> selectTemperingTerritory(String current);
    /**
     * 查询笼内版图差值范围内的  此尺寸玻璃  如无则按照 钢化版图序号 以及玻璃序号
@@ -64,4 +70,12 @@
     * @return
     */
    String edgReportStatus(IdentWornRequest request);
    /**
     * 进片  扫码ID验证重复
     *
     * @param glassId
     * @return
     */
    boolean inToVerify(String glassId);
}
hangzhoumesParent/moduleService/CacheGlassModule/src/main/java/com/mes/edgstoragecage/service/impl/EdgStorageCageDetailsServiceImpl.java
@@ -8,7 +8,6 @@
import com.github.yulichang.query.MPJLambdaQueryWrapper;
import com.github.yulichang.toolkit.JoinWrappers;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.mes.common.config.Const;
import com.mes.damage.entity.Damage;
import com.mes.damage.mapper.DamageMapper;
import com.mes.damage.service.DamageService;
@@ -24,9 +23,9 @@
import com.mes.engineering.mapper.EngineeringMapper;
import com.mes.glassinfo.entity.GlassInfo;
import com.mes.glassinfo.mapper.GlassInfoMapper;
import com.mes.pp.entity.OptimizeDetail;
import com.mes.pp.entity.OptimizeLayout;
import com.mes.pp.entity.*;
import com.mes.pp.mapper.OptimizeDetailMapper;
import com.mes.pp.mapper.OptimizeHeatDetailMapper;
import com.mes.taskcache.entity.TaskCache;
import com.mes.taskcache.service.TaskCacheService;
import com.mes.uppattenusage.entity.UpPattenUsage;
@@ -62,6 +61,9 @@
    @Autowired
    OptimizeDetailMapper optimizeDetailMapper;
    @Autowired
    OptimizeHeatDetailMapper optimizeHeatDetailMapper;
    @Autowired
    EdgStorageCageMapper edgStorageCageMapper;
@@ -299,6 +301,72 @@
    }
    /**
     * 获取 工程下的钢化版图
     *
     * @param current
     * @return
     */
    @Override
    public List<List<Map<String, Object>>> selectTemperingTerritory(String current) {
        //此工程的所有优化数据
        List<Map<String, Object>> resultCutTerritory=optimizeHeatDetailMapper.selectJoinMaps(JoinWrappers.lambda(OptimizeHeatDetail.class)
                .selectAll(OptimizeHeatDetail.class)
                .selectAs(OptimizeProject::getLoadWidth, "olWidth")
                .selectAs(OptimizeProject::getLoadLength, "olHeight")
                .leftJoin(OptimizeHeatLayout.class, on -> on
                        .eq(OptimizeHeatLayout::getProjectNo, OptimizeHeatDetail::getProjectNo)
                        .eq(OptimizeHeatLayout::getLayoutId, OptimizeHeatDetail::getLayoutId))
                .leftJoin(OptimizeProject.class, on -> on
                        .eq(OptimizeProject::getProjectNo, OptimizeHeatLayout::getProjectNo))
                .eq(OptimizeHeatDetail::getProjectNo, current)
        );
        Map<String, List<Map<String, Object>>> groupBy = resultCutTerritory.stream().collect(Collectors.groupingBy(item -> item.get("layout_id").toString()));
//        List<List<Map<String, Object>>> Result=groupBy.values().stream().collect(Collectors.toList());
        List<List<Map<String, Object>>> result = new ArrayList<>();
        for (int i = 1; i <= groupBy.keySet().size(); i++) {
            String key = i + "";
            if (key != null) {
                result.add(groupBy.get(key));
            }
        }
        return result;
    }
    /**
     * 获取 工程下的钢化版图
     *
     * @param current
     * @return
     */
    @Override
    public List<List<Map<String, Object>>> selectTemperingTerritory(String current) {
        //此工程的所有优化数据
        List<Map<String, Object>> resultCutTerritory = optimizeHeatDetailMapper.selectJoinMaps(JoinWrappers.lambda(OptimizeHeatDetail.class)
                .selectAll(OptimizeHeatDetail.class)
                .selectAs(OptimizeProject::getLoadWidth, "olWidth")
                .selectAs(OptimizeProject::getLoadLength, "olHeight")
                .leftJoin(OptimizeHeatLayout.class, on -> on
                        .eq(OptimizeHeatLayout::getProjectNo, OptimizeHeatDetail::getProjectNo)
                        .eq(OptimizeHeatLayout::getLayoutId, OptimizeHeatDetail::getLayoutId))
                .leftJoin(OptimizeProject.class, on -> on
                        .eq(OptimizeProject::getProjectNo, OptimizeHeatLayout::getProjectNo))
                .eq(OptimizeHeatDetail::getProjectNo, current)
        );
        Map<String, List<Map<String, Object>>> groupBy = resultCutTerritory.stream().collect(Collectors.groupingBy(item -> item.get("layout_id").toString()));
//        List<List<Map<String, Object>>> Result=groupBy.values().stream().collect(Collectors.toList());
        List<List<Map<String, Object>>> result = new ArrayList<>();
        for (int i = 1; i <= groupBy.keySet().size(); i++) {
            String key = i + "";
            if (key != null) {
                result.add(groupBy.get(key));
            }
        }
        return result;
    }
    /**
     * 查询笼内版图差值范围内的  此尺寸玻璃  如无则按照 钢化版图序号 以及玻璃序号
     *
     * @param glassId
@@ -431,4 +499,30 @@
                .set(EdgGlassTaskInfo::getStatus, request.getState()).eq(EdgGlassTaskInfo::getGlassId, request.getGlassId()));
        return "success";
    }
    /**
     * 进片  扫码ID验证重复
     *
     * @param glassId
     * @return
     */
    @Override
    public boolean inToVerify(String glassId){
        List<EdgStorageCageDetails> listEdgStorageCageDetails = baseMapper.selectList(new LambdaQueryWrapper<EdgStorageCageDetails>()
                .eq(EdgStorageCageDetails::getGlassId, glassId)
        );
        if (listEdgStorageCageDetails.isEmpty()) {
            //说明此玻璃没有进过理片
            return true;
        }else{
            List<Damage> damage=damageMapper.selectList(new LambdaQueryWrapper<Damage>()
                    .eq(Damage::getGlassId, glassId)
                    .and(wrapper->wrapper.eq(Damage::getType, 8).or().eq(Damage::getType, 9))
            );
            if(!damage.isEmpty()){
                return true;
            }
        }
        return false;
    }
}
hangzhoumesParent/moduleService/CacheGlassModule/src/main/java/com/mes/job/CacheGlassTask.java
@@ -80,6 +80,12 @@
    @Value("${mes.max.secondLength}")
    private String secondLength;
    @Value("${mes.cache.cacheWidth}")
    private double cacheWidth;
    @Value("${mes.cache.cacheHeight}")
    private double cacheHeight;
    @Value("${mes.min.one.firstLength}")
    private String minOneFirstLength;
@@ -94,7 +100,7 @@
    public static String engineerId = "";
    @Scheduled(fixedDelay = 1000)
    //@Scheduled(fixedDelay = 1000)
    public void plcHomeEdgTask() {
        Date startDate = new Date();
        log.info("本次任务开始执行时间:{}", startDate);
@@ -124,8 +130,9 @@
            log.info("2、获取到的请求字不为0,将确认字不为0,直接结束");
            return;
        }
        if ("1".equals(taskRequestTypeValue)) {
            log.info("2、进片请求,且确认字为0,执行进片任务");
        boolean result = edgStorageCageDetailsService.inToVerify(glassIdeValue);
        if ("1".equals(taskRequestTypeValue) && result) {
            log.info("2、进片请求,且确认字为0,执行进片任务,扫码重复ID验证【有重复=false,无重复=true】:{}", result);
            inTo(glassIdeValue, confirmationWrodAddress, currentSlot);
        } else if ("2".equals(taskRequestTypeValue)) {
            //09空闲 :1      10空闲 :2        都空闲:3    其他0
@@ -137,8 +144,8 @@
            //加笼子里面是否有玻璃,有先出,无玻璃先进
            boolean outFlase = outTo(Integer.parseInt(out08Glassstate),
                    Integer.parseInt(out10Glassstate), confirmationWrodAddress, glassIdeValue, Integer.parseInt(currentSlot));
            log.info("出片任务是否完成:{},且玻璃id:{}不为空则执行进片任务", outFlase, glassIdeValue);
            if (!outFlase && StringUtils.isNotBlank(glassIdeValue)) {
            log.info("出片任务是否完成:{},且玻璃id:{}不为空则执行进片任务,扫码重复ID验证【有重复=false,无重复=true】:{}", outFlase, glassIdeValue, result);
            if (!outFlase && StringUtils.isNotBlank(glassIdeValue) && result) {
                inTo(glassIdeValue, confirmationWrodAddress, currentSlot);
            }
        }
@@ -164,9 +171,9 @@
                Damage damage = new Damage();
                damage.setGlassId(e.getGlassId());
                damage.setLine(e.getEndCell());
                damage.setWorkingProcedure("冷加工");
                damage.setWorkingProcedure("磨边");
                damage.setRemark("磨边前卧式理片");
                damage.setStatus(0);
                damage.setStatus(1);
                damage.setType(e.getTaskStatus());
                return damage;
            }).collect(Collectors.toList());
@@ -186,14 +193,28 @@
     */
    public void inTo(String glassId, String confirmationWrodAddress, String currentSlot) {
        log.info("1、按照玻璃id:{}获取玻璃小片信息,当前格子为:{}", glassId, currentSlot);
        GlassInfo feedGlassInfo = glassInfoService.getOne(
                new LambdaQueryWrapper<GlassInfo>()
                        .eq(GlassInfo::getGlassId, glassId)
        );
        if (Math.max(feedGlassInfo.getWidth(), feedGlassInfo.getHeight()) > cacheWidth || Math.min(feedGlassInfo.getWidth(), feedGlassInfo.getHeight()) > cacheHeight) {
            log.info("1.1、玻璃超过卧式理片最大尺寸:{}", feedGlassInfo);
            return;
        }
        //添加进片任务  查找空格
        EdgStorageCage nearestEmpty = edgStorageCageService.selectNearestEmpty(Integer.parseInt(currentSlot), Boolean.FALSE);
        Assert.isTrue(null != nearestEmpty, "格子已满");
        log.info("2、查询卧式理片笼里面的空格:{}", nearestEmpty);
        //查询玻璃并进行交换
        GlassInfo glassInfo = queryAndChangeGlass(glassId);
        //查询玻璃信息
        GlassInfo glassInfo = glassInfoService.getOne(new LambdaQueryWrapper<GlassInfo>().eq(GlassInfo::getGlassId, glassId));
        if (glassInfo == null) {
            return;
        }
        if ((glassInfo.getWidth() < Double.parseDouble(minTwoFirstLength) && glassInfo.getHeight() < Double.parseDouble(minTwoSecondLength)) || (glassInfo.getWidth() < Double.parseDouble(minTwoSecondLength) && glassInfo.getHeight() < Double.parseDouble(minTwoFirstLength))) {
            log.info("3、玻璃信息不符合进入理片笼最小尺寸,玻璃信息为{}", glassInfo);
            return;
        }
        log.info("4、将玻璃信息插入卧式理片笼,当前玻璃信息:{}", glassInfo);
@@ -219,15 +240,10 @@
     * @param glassId
     * @return
     */
    public GlassInfo queryAndChangeGlass(String glassId) {
    public String queryAndChangeGlass(String glassId) {
        GlassInfo glassInfo = glassInfoService.getOne(new LambdaQueryWrapper<GlassInfo>().eq(GlassInfo::getGlassId, glassId));
//                .inSql(GlassInfo::getEngineerId, "select engineer_id from engineering where state = 1"));
        Assert.isFalse(null == glassInfo, "玻璃信息不存在");
        if ((glassInfo.getWidth() < Double.parseDouble(minTwoFirstLength) && glassInfo.getHeight() < Double.parseDouble(minTwoSecondLength)) || (glassInfo.getWidth() < Double.parseDouble(minTwoSecondLength) && glassInfo.getHeight() < Double.parseDouble(minTwoFirstLength))) {
            log.info("3、玻璃信息不符合进入理片笼最小尺寸,玻璃信息为{}", glassInfo);
            return null;
        }
        //按照玻璃尺寸
        Assert.isFalse(null == glassInfo, "玻璃信息不存在");        //按照玻璃尺寸
        LambdaQueryWrapper<GlassInfo> queryWrapper = new LambdaQueryWrapper<GlassInfo>()
                .eq(GlassInfo::getWidth, glassInfo.getWidth())
                .eq(GlassInfo::getHeight, glassInfo.getHeight())
@@ -249,9 +265,41 @@
            glassInfo.setGlassId(swapGlassId);
            glassInfoService.updateById(swapGlassInfo);
            glassInfoService.updateById(glassInfo);
            return swapGlassInfo;
            return swapGlassId;
        }
        return glassInfo;
        return "";
    }
    /**
     * 查询卧式理片玻璃并进行交换
     *
     * @param glassId
     * @return
     */
    public void queryEdgAndChangeGlass(String glassId, String swapGlassId) {
        if (StringUtils.isBlank(swapGlassId)) {
            log.info("当前出笼玻璃不存在需要替换的玻璃");
            return;
        }
        //获取待出笼的玻璃
        EdgStorageCageDetails glassInfo = edgStorageCageDetailsService.getOne(new LambdaQueryWrapper<EdgStorageCageDetails>()
                .eq(EdgStorageCageDetails::getGlassId, glassId).eq(EdgStorageCageDetails::getState, Const.GLASS_STATE_IN));
//        获取待出笼的玻璃需要替换的玻璃信息
        EdgStorageCageDetails swapGlassDetailInfo = edgStorageCageDetailsService.getOne(new LambdaQueryWrapper<EdgStorageCageDetails>()
                .eq(EdgStorageCageDetails::getGlassId, swapGlassId).eq(EdgStorageCageDetails::getState, Const.GLASS_STATE_IN));
//      玻璃小片表中玻璃已经替换,更新卧理笼内现有的准备出笼的玻璃信息,
        if (null == swapGlassDetailInfo) {
            //需要替换的玻璃为存进卧理,仅需更新当前需要出笼的玻璃信息即可
            edgStorageCageDetailsService.update(new LambdaUpdateWrapper<EdgStorageCageDetails>()
                    .eq(EdgStorageCageDetails::getGlassId, glassId).set(EdgStorageCageDetails::getGlassId, swapGlassId));
        } else {
            //需要替换的玻璃都在卧理内,按照玻璃id对调玻璃信息:对调玻璃id即可
            edgStorageCageDetailsService.update(new LambdaUpdateWrapper<EdgStorageCageDetails>()
                    .eq(EdgStorageCageDetails::getId, glassInfo.getId()).set(EdgStorageCageDetails::getGlassId, swapGlassId));
            edgStorageCageDetailsService.update(new LambdaUpdateWrapper<EdgStorageCageDetails>()
                    .eq(EdgStorageCageDetails::getId, swapGlassDetailInfo.getId()).set(EdgStorageCageDetails::getGlassId, glassId));
        }
    }
    /**
@@ -636,7 +684,6 @@
                details.setSlot(nearestEmpty.getSlot());
                details.setState(Const.GLASS_STATE_OUT);
                edgStorageCageDetailsService.save(details);
                boolean taskCacheStatus = saveTaskCache(glassInfo.getGlassId(), nearestEmpty.getSlot(), endcell, Const.GLASS_CACHE_TYPE_THROUGH);
                log.info("6、添加出片任务是否完成:{}", taskCacheStatus);
            } else {
@@ -653,7 +700,153 @@
            log.info("7、添加出片玻璃尺寸信息到磨边前玻璃表是否完成:{}", glassSizeStatus);
            S7object.getinstance().plccontrol.writeWord(confirmationWrodAddress, 1);
            log.info("8、发送确认字已完成");
            Damage damage=new Damage();
            Damage damage = new Damage();
            damage.setGlassId(glassInfo.getGlassId());
            damage.setWorkingProcedure("切割");
            damage.setLine(1001);
            damage.setType(1);
            damage.setRemark("过卧式理片");
            damageService.insertDamage(damage);
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }
    /**
     * 保存出片任务相关信息
     *
     * @param glassInfo
     * @param endcell
     * @param confirmationWrodAddress
     * @param glassId
     * @return
     */
    private boolean saveOutGlassMessageBySlot(EdgStorageCageDetails glassInfo, int endcell, String confirmationWrodAddress, String glassId, Integer currentSlot) {
        if (glassInfo != null) {
            log.info("4、添加出片任务,玻璃id:{},任务类型:{},起始位置:{},结束位置:{}", glassInfo.getGlassId(),
                    2, glassInfo.getSlot(), endcell);
            if (glassInfo.getGlassId().equals(glassId)) {
                log.info("5、直通任务,将玻璃信息插入卧式理片笼,当前玻璃信息:{}", glassInfo);
                EdgStorageCageDetails details = new EdgStorageCageDetails();
                //玻璃信息替换
                String glassIdChange = queryAndChangeGlass(glassId);
                if (StringUtils.isBlank(glassIdChange)) {
                    BeanUtils.copyProperties(glassInfo, details);
                } else {
                    GlassInfo one = glassInfoService.getOne(new LambdaQueryWrapper<GlassInfo>().eq(GlassInfo::getGlassId, glassId));
                    BeanUtils.copyProperties(glassInfo, details);
                }
                EdgStorageCage nearestEmpty = edgStorageCageService.selectNearestEmpty(currentSlot, Boolean.TRUE);
                Assert.isTrue(null != nearestEmpty, "格子已满,无法执行直通任务");
                log.info("3、查询卧式理片笼里面的空格:{}", nearestEmpty);
                details.setSlot(nearestEmpty.getSlot());
                details.setState(Const.GLASS_STATE_OUT);
                edgStorageCageDetailsService.save(details);
                boolean taskCacheStatus = saveTaskCache(glassInfo.getGlassId(), nearestEmpty.getSlot(), endcell, Const.GLASS_CACHE_TYPE_THROUGH);
                log.info("6、添加出片任务是否完成:{}", taskCacheStatus);
            } else {
                log.info("5、非直通任务,将玻璃信息插入卧式理片笼,当前玻璃信息:{}", glassInfo);
                if (endcell != currentSlot) {
                    EdgStorageCageDetails currentGlass = edgStorageCageDetailsService.getOne(new LambdaQueryWrapper<EdgStorageCageDetails>()
                            .eq(EdgStorageCageDetails::getState, Const.GLASS_STATE_IN)
                            .eq(EdgStorageCageDetails::getSlot, currentSlot).eq(EdgStorageCageDetails::getWidth, glassInfo.getWidth())
                            .eq(EdgStorageCageDetails::getHeight, glassInfo.getHeight()).eq(EdgStorageCageDetails::getThickness, glassInfo.getThickness())
                    );
                    if (null != currentGlass) {
                        glassInfo = currentGlass;
                        endcell = currentSlot;
                    }
                }
                //玻璃信息替换
                String glassIdChange = queryAndChangeGlass(glassInfo.getGlassId());
                //处理在卧理内的玻璃信息:笼内的数据处理
                queryEdgAndChangeGlass(glassInfo.getGlassId(), glassIdChange);
                LambdaUpdateWrapper<EdgStorageCageDetails> wrapper = new LambdaUpdateWrapper<>();
                wrapper.eq(EdgStorageCageDetails::getGlassId, glassInfo.getGlassId()).set(EdgStorageCageDetails::getState, Const.GLASS_STATE_OUT);
                edgStorageCageDetailsService.update(wrapper);
                log.info("5、更新出片玻璃的状态为{}", Const.GLASS_STATE_OUT);
                boolean taskCacheStatus = saveTaskCache(glassInfo.getGlassId(), glassInfo.getSlot(), endcell, Const.GLASS_CACHE_TYPE_OUT);
                log.info("6、添加出片任务是否完成:{}", taskCacheStatus);
            }
            boolean glassSizeStatus = saveGlassSize(glassInfo, endcell);
            log.info("7、添加出片玻璃尺寸信息到磨边前玻璃表是否完成:{}", glassSizeStatus);
            S7object.getinstance().plccontrol.writeWord(confirmationWrodAddress, 1);
            log.info("8、发送确认字已完成");
            Damage damage = new Damage();
            damage.setGlassId(glassInfo.getGlassId());
            damage.setWorkingProcedure("切割");
            damage.setLine(1001);
            damage.setType(1);
            damage.setRemark("过卧式理片");
            damageService.insertDamage(damage);
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }
    /**
     * 保存出片任务相关信息
     *
     * @param glassInfo
     * @param endcell
     * @param confirmationWrodAddress
     * @param glassId
     * @return
     */
    private boolean saveOutGlassMessageBySlot(EdgStorageCageDetails glassInfo, int endcell, String confirmationWrodAddress, String glassId, Integer currentSlot) {
        if (glassInfo != null) {
            log.info("4、添加出片任务,玻璃id:{},任务类型:{},起始位置:{},结束位置:{}", glassInfo.getGlassId(),
                    2, glassInfo.getSlot(), endcell);
            if (glassInfo.getGlassId().equals(glassId)) {
                log.info("5、直通任务,将玻璃信息插入卧式理片笼,当前玻璃信息:{}", glassInfo);
                EdgStorageCageDetails details = new EdgStorageCageDetails();
                //玻璃信息替换
                String glassIdChange = queryAndChangeGlass(glassId);
                if (StringUtils.isBlank(glassIdChange)) {
                    BeanUtils.copyProperties(glassInfo, details);
                } else {
                    GlassInfo one = glassInfoService.getOne(new LambdaQueryWrapper<GlassInfo>().eq(GlassInfo::getGlassId, glassId));
                    BeanUtils.copyProperties(glassInfo, details);
                }
                EdgStorageCage nearestEmpty = edgStorageCageService.selectNearestEmpty(currentSlot, Boolean.TRUE);
                Assert.isTrue(null != nearestEmpty, "格子已满,无法执行直通任务");
                log.info("3、查询卧式理片笼里面的空格:{}", nearestEmpty);
                details.setSlot(nearestEmpty.getSlot());
                details.setState(Const.GLASS_STATE_OUT);
                edgStorageCageDetailsService.save(details);
                boolean taskCacheStatus = saveTaskCache(glassInfo.getGlassId(), nearestEmpty.getSlot(), endcell, Const.GLASS_CACHE_TYPE_THROUGH);
                log.info("6、添加出片任务是否完成:{}", taskCacheStatus);
            } else {
                log.info("5、非直通任务,将玻璃信息插入卧式理片笼,当前玻璃信息:{}", glassInfo);
                if (endcell != currentSlot) {
                    EdgStorageCageDetails currentGlass = edgStorageCageDetailsService.getOne(new LambdaQueryWrapper<EdgStorageCageDetails>()
                            .eq(EdgStorageCageDetails::getState, Const.GLASS_STATE_IN)
                            .eq(EdgStorageCageDetails::getSlot, currentSlot).eq(EdgStorageCageDetails::getWidth, glassInfo.getWidth())
                            .eq(EdgStorageCageDetails::getHeight, glassInfo.getHeight()).eq(EdgStorageCageDetails::getThickness, glassInfo.getThickness())
                    );
                    if (null != currentGlass) {
                        glassInfo = currentGlass;
                        endcell = currentSlot;
                    }
                }
                //玻璃信息替换
                String glassIdChange = queryAndChangeGlass(glassInfo.getGlassId());
                //处理在卧理内的玻璃信息:笼内的数据处理
                queryEdgAndChangeGlass(glassInfo.getGlassId(), glassIdChange);
                LambdaUpdateWrapper<EdgStorageCageDetails> wrapper = new LambdaUpdateWrapper<>();
                wrapper.eq(EdgStorageCageDetails::getGlassId, glassInfo.getGlassId()).set(EdgStorageCageDetails::getState, Const.GLASS_STATE_OUT);
                edgStorageCageDetailsService.update(wrapper);
                log.info("5、更新出片玻璃的状态为{}", Const.GLASS_STATE_OUT);
                boolean taskCacheStatus = saveTaskCache(glassInfo.getGlassId(), glassInfo.getSlot(), endcell, Const.GLASS_CACHE_TYPE_OUT);
                log.info("6、添加出片任务是否完成:{}", taskCacheStatus);
            }
            boolean glassSizeStatus = saveGlassSize(glassInfo, endcell);
            log.info("7、添加出片玻璃尺寸信息到磨边前玻璃表是否完成:{}", glassSizeStatus);
            S7object.getinstance().plccontrol.writeWord(confirmationWrodAddress, 1);
            log.info("8、发送确认字已完成");
            Damage damage = new Damage();
            damage.setGlassId(glassInfo.getGlassId());
            damage.setWorkingProcedure("切割");
            damage.setLine(1001);
hangzhoumesParent/moduleService/CacheGlassModule/src/main/java/com/mes/job/OpcCacheGlassTask.java
@@ -1,7 +1,5 @@
package com.mes.job;
import com.mes.milo.runner.subscription.SubscriptionCallback;
import com.mes.milo.service.MiloService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
@@ -18,14 +16,14 @@
@Slf4j
public class OpcCacheGlassTask {
    @Autowired
    MiloService miloService;
    @Autowired
    SubscriptionCallback cacheGlassSubscriptionCallback;
    @Scheduled(fixedDelay = Long.MAX_VALUE)
    public void startOpcTask() throws Exception {
        miloService.subscriptionFromOpcUa(Arrays.asList("my.device.x1", "my.device.x2"), cacheGlassSubscriptionCallback);
    }
//    @Autowired
//    MiloService miloService;
//
//    @Autowired
//    SubscriptionCallback cacheGlassSubscriptionCallback;
//
//    @Scheduled(fixedDelay = Long.MAX_VALUE)
//    public void startOpcTask() throws Exception {
//        miloService.subscriptionFromOpcUa(Arrays.asList("my.device.x1", "my.device.x2"), cacheGlassSubscriptionCallback);
//    }
}
hangzhoumesParent/moduleService/CacheGlassModule/src/main/java/com/mes/opccallback/CacheGlassSubscriptionCallback.java
@@ -1,8 +1,5 @@
package com.mes.opccallback;
import com.mes.milo.model.ReadWriteEntity;
import com.mes.milo.runner.subscription.SubscriptionCallback;
import com.mes.milo.service.MiloService;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.milo.opcua.sdk.client.subscriptions.ManagedDataItem;
import org.eclipse.milo.opcua.stack.core.types.builtin.DataValue;
@@ -16,20 +13,20 @@
 */
@Service
@Slf4j
public class CacheGlassSubscriptionCallback implements SubscriptionCallback {
public class CacheGlassSubscriptionCallback  {
    @Autowired
    MiloService miloService;
    @Override
    public void onSubscribe(ManagedDataItem dataItem, DataValue value) {
        try {
            log.info("{}___________{}" + dataItem, value);
            ReadWriteEntity readWriteEntity = miloService.readFromOpcUa("my.device.x1");
            log.info("{}___________{}" + readWriteEntity);
        } catch (Exception e) {
        }
    }
//    @Autowired
//    MiloService miloService;
//
//    @Override
//    public void onSubscribe(ManagedDataItem dataItem, DataValue value) {
//        try {
//            log.info("{}___________{}" + dataItem, value);
//            ReadWriteEntity readWriteEntity = miloService.readFromOpcUa("my.device.x1");
//            log.info("{}___________{}" + readWriteEntity);
//        } catch (Exception e) {
//
//        }
//
//    }
}
hangzhoumesParent/moduleService/CacheGlassModule/src/main/java/com/mes/taskcache/controller/TaskCacheController.java
@@ -32,6 +32,14 @@
    @Autowired
    private TaskCacheService taskCacheService;
    @ApiOperation("查询钢化版图信息-根据 工程号   参数(工程号)")
    @PostMapping("/temperingTerritory")
    @ResponseBody
    public Result temperingTerritory(String current) {
        List<List<Map<String, Object>>> h = edgStorageCageDetailsService.selectTemperingTerritory(current);
        return Result.build(200, "成功", h);
    }
    @ApiOperation("查询切割版图信息-根据 工程号   参数(工程号)")
    @PostMapping("/cutTerritory")
    @ResponseBody
hangzhoumesParent/moduleService/CacheGlassModule/src/main/resources/application.yml
@@ -3,7 +3,7 @@
spring:
  profiles:
    active: dev
    active: cz
  application:
    name: cacheGlass
  liquibase:
@@ -15,6 +15,9 @@
mes:
  threshold: 3
  ratio: 10
  cache: # 卧式理片最大尺寸
    cacheWidth: 4000
    cacheHeight:3000
  max: # 第二条线的最大尺寸信息
    firstLength: 3500
    secondLength: 2500
hangzhoumesParent/moduleService/CacheGlassModule/src/test/java/com/mes/CacheGlassModuleApplicationTest.java
@@ -143,6 +143,12 @@
    }
    @Test
    public void testEngineerTerritory() {
        List<List<Map<String, Object>>> map = edgStorageCageDetailsService.selectTemperingTerritory("P24052203");
        log.info("钢化工程版图信息:{}", Arrays.asList(map));
    }
    @Test
    public void testidentWorn() {
        Map<String, Object> arguments=new HashMap<>();
        arguments.put("glassId","NG24051802A002-1-4-2-4");//玻璃ID
@@ -152,6 +158,11 @@
//        edgStorageCageDetailsService.identWorn(arguments);
        log.info("识别台【破损/拿走】:{}", 1);
    }
    @Test
    public void testInToVerify() {
        boolean result=edgStorageCageDetailsService.inToVerify("P24060405|30|1");
        log.info("是否存在重复ID 》允许进片:{}", result);
    }
    @Test
    public void testPpOptimizeDetail() {
hangzhoumesParent/moduleService/CacheVerticalGlassModule/src/main/java/com/mes/bigstorage/controller/BigStorageCageDetailsController.java
@@ -3,7 +3,6 @@
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.mes.bigstorage.entity.BigStorageCageDetails;
import com.mes.bigstorage.service.BigStorageCageDetailsService;
import com.mes.bigstorage.service.BigStorageCageService;
@@ -92,7 +91,8 @@
    @ApiOperation("指定钢化")
    @PostMapping("/TemperingGlass")
    public Result temperingGlass(@RequestBody BigStorageCageDetails bigStorageCageDetails) {
        boolean result = bigStorageCageDetailsService.temperingGlass(bigStorageCageDetails.getTemperingLayoutId().toString(), bigStorageCageDetails.getEngineerId());
        boolean result = bigStorageCageDetailsService
                .temperingGlass(bigStorageCageDetails.getTemperingLayoutId().toString(), bigStorageCageDetails.getEngineerId(), bigStorageCageDetails.getTemperingFeedSequence().toString());
        if (result == true) {
            return Result.build(200, "指定钢化成功", 1);
        } else {
hangzhoumesParent/moduleService/CacheVerticalGlassModule/src/main/java/com/mes/bigstorage/service/BigStorageCageDetailsService.java
@@ -69,7 +69,7 @@
     */
    List<SlotSequenceDTO> queryGlassMaxAndMin(String engineerId, Integer temperingLayoutId);
    boolean temperingGlass(String temperingLayoutId, String engineerId);
    boolean temperingGlass(String temperingLayoutId, String engineerId, String temperingFeedSequence);
    List<Map<String, Object>> selectTemperingGlass();
hangzhoumesParent/moduleService/CacheVerticalGlassModule/src/main/java/com/mes/bigstorage/service/impl/BigStorageCageDetailsServiceImpl.java
@@ -2,7 +2,6 @@
import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.github.yulichang.base.MPJBaseServiceImpl;
import com.github.yulichang.toolkit.JoinWrappers;
@@ -27,6 +26,7 @@
import com.mes.glassinfo.entity.GlassInfo;
import com.mes.glassinfo.mapper.GlassInfoMapper;
import com.mes.glassinfo.service.GlassInfoService;
import com.mes.job.PlcStorageCageTask;
import com.mes.temperingglass.entity.TemperingGlassInfo;
import com.mes.temperingglass.mapper.TemperingGlassInfoMapper;
import com.mes.temperingglass.service.TemperingGlassInfoService;
@@ -70,6 +70,9 @@
    @Resource
    private TemperingGlassInfoService temperingGlassInfoService;
    @Resource
    private PlcStorageCageTask plcStorageCageTask;
    @Resource
    private DamageService damageService;
@@ -188,7 +191,7 @@
        LambdaQueryWrapper<BigStorageCageDetails> bigStorageCageDetailsWrapper = new LambdaQueryWrapper<>();
        bigStorageCageDetailsWrapper
                .eq(BigStorageCageDetails::getGlassId, glassId)
                .eq(BigStorageCageDetails::getState,Const.GLASS_STATE_IN);
                .eq(BigStorageCageDetails::getState, Const.GLASS_STATE_IN);
        BigStorageCageDetails bigStorageCageDetails = baseMapper.selectOne(bigStorageCageDetailsWrapper);
        if (temperingGlassInfo != null) {
@@ -221,7 +224,7 @@
    @Override
    public List<BigStorageCageDetails> selectBigStorageCageDetails(String glassId) {
        LambdaQueryWrapper<GlassInfo> glassInfoWrapper = new LambdaQueryWrapper<>();
        List<BigStorageCageDetails> bigStorageCageDetailsList=new ArrayList<>();
        List<BigStorageCageDetails> bigStorageCageDetailsList = new ArrayList<>();
        glassInfoWrapper.eq(GlassInfo::getGlassId, glassId);
        GlassInfo glassInfo = glassInfoMapper.selectOne(glassInfoWrapper);
        BigStorageCageDetails bigStorageCageDetails = new BigStorageCageDetails();
@@ -276,8 +279,8 @@
                .gt(BigStorageCage::getRemainWidth, Math.max(glassInfo.getWidth(), glassInfo.getHeight()))
                .last("limit 1");
        if (glassInfo.getTemperingLayoutId() == 0) {
            wrapper.eq(BigStorageCageDetails::getFlowCardId,glassInfo.getFlowCardId())
                    .eq(BigStorageCageDetails::getLayer,glassInfo.getLayer());
            wrapper.eq(BigStorageCageDetails::getFlowCardId, glassInfo.getFlowCardId())
                    .eq(BigStorageCageDetails::getLayer, glassInfo.getLayer());
//            wrapper.eq(BigStorageCageDetails::getWidth, glassInfo.getWidth()).eq(BigStorageCageDetails::getHeight, glassInfo.getHeight());
        } else {
            wrapper.eq(BigStorageCageDetails::getTemperingFeedSequence, glassInfo.getTemperingFeedSequence() + 1);
@@ -363,7 +366,7 @@
    }
    @Override
    public boolean temperingGlass(String temperingLayoutId, String engineerId) {
    public boolean temperingGlass(String temperingLayoutId, String engineerId, String temperingFeedSequence) {
        LambdaQueryWrapper<TemperingGlassInfo> temperingGlassInfoLambdaQueryWrapper = new LambdaQueryWrapper<>();
        temperingGlassInfoLambdaQueryWrapper
                .eq(TemperingGlassInfo::getState, Const.TEMPERING_NEW);
@@ -380,7 +383,13 @@
                    .in(BigStorageCageDetails::getState, Const.GLASS_STATE_IN)
                    .orderBy(Boolean.TRUE, sequenceOrder, GlassInfo::getTemperingFeedSequence));
            if (CollectionUtils.isNotEmpty(temperingGlassInfos)) {
                temperingGlassInfoService.saveBatch(temperingGlassInfos);
                if ("0".equals(temperingFeedSequence)) {
                    if (CollectionUtils.isNotEmpty(temperingGlassInfos)) {
                        plcStorageCageTask.computeOutMoreGlassInfo(temperingGlassInfos, Boolean.FALSE, "");
                    }
                } else {
                    temperingGlassInfoService.saveBatch(temperingGlassInfos);
                }
                return true;
            }
        }
@@ -406,7 +415,7 @@
    }
    @Override
    public void appointEngineerId(String engineerId){
    public void appointEngineerId(String engineerId) {
        redisUtil.setCacheObject("temperingengineerId", engineerId);
    }
}
hangzhoumesParent/moduleService/CacheVerticalGlassModule/src/main/java/com/mes/job/PlcStorageCageTask.java
@@ -575,30 +575,53 @@
     * 确认字清空
     */
//    @Scheduled(fixedDelay = 300)
//    public void confirmClear() {
//        PlcParameterObject plcParameterObject = S7object.getinstance().PlcMesObject;
//        String d01ToMES = plcParameterObject.getPlcParameter("D01ToMES").getValue();
//        String d04ToMES = plcParameterObject.getPlcParameter("D04ToMES").getValue();
//        String mesD01Address = plcParameterObject.getPlcParameter("MESToD01").getAddress();
//        String mesD04Address = plcParameterObject.getPlcParameter("MESToD04").getAddress();
//        String d03ToMES = plcParameterObject.getPlcParameter("D03ToMES").getValue();
//        String d05ToMES = plcParameterObject.getPlcParameter("D05ToMES").getValue();
//        String mesD03Address = plcParameterObject.getPlcParameter("MESToD03").getAddress();
//        String mesD05Address = plcParameterObject.getPlcParameter("MESToD05").getAddress();
//        if(!REQUEST_WORD.equals(d01ToMES)){
//            S7object.getinstance().plccontrol.writeWord(mesD01Address, 0);
//        }
//        if(!REQUEST_WORD.equals(d04ToMES)){
//            S7object.getinstance().plccontrol.writeWord(mesD04Address, 0);
//        }
//        if (!REQUEST_WORD.equals(d03ToMES)) {
//            S7object.getinstance().plccontrol.writeWord(mesD03Address, 0);
//        }
//        if (!REQUEST_WORD.equals(d05ToMES)) {
//            S7object.getinstance().plccontrol.writeWord(mesD05Address, 0);
//        }
//    }
    /**
     * 进片状态修改
     */
//    @Scheduled(fixedDelay = 300)
    public void feedStatusUpdate() {
        List<String> glassIds1=null;
        List<String> glassIds2=null;
        List<BigStorageCageFeedTask> bigStorageCageFeedTasks1=bigStorageCageFeedTaskService.list(
                new LambdaQueryWrapper<BigStorageCageFeedTask>()
                .eq(BigStorageCageFeedTask::getTaskState,1)
                .eq(BigStorageCageFeedTask::getLine,Const.ARTIFICIAL_OUT_TARGET_POSITION)
        );
        List<BigStorageCageFeedTask> bigStorageCageFeedTasks2=bigStorageCageFeedTaskService.list(
                new LambdaQueryWrapper<BigStorageCageFeedTask>()
                        .eq(BigStorageCageFeedTask::getTaskState,1)
                        .eq(BigStorageCageFeedTask::getLine,Const.TEMPERING_OUT_TARGET_POSITION)
        );
//        if(CollectionUtils.isNotEmpty(bigStorageCageFeedTasks1)){
//
//        }
//        if(CollectionUtils.isNotEmpty(bigStorageCageFeedTasks1)){
//
//        }
    }
//    public void feedStatusUpdate() {
//        List<String> glassIds1=null;
//        List<String> glassIds2=null;
//        List<BigStorageCageFeedTask> bigStorageCageFeedTasks1=bigStorageCageFeedTaskService.list(
//                new LambdaQueryWrapper<BigStorageCageFeedTask>()
//                .eq(BigStorageCageFeedTask::getTaskState,1)
//                .eq(BigStorageCageFeedTask::getLine,Const.ARTIFICIAL_OUT_TARGET_POSITION)
//        );
//        List<BigStorageCageFeedTask> bigStorageCageFeedTasks2=bigStorageCageFeedTaskService.list(
//                new LambdaQueryWrapper<BigStorageCageFeedTask>()
//                        .eq(BigStorageCageFeedTask::getTaskState,1)
//                        .eq(BigStorageCageFeedTask::getLine,Const.TEMPERING_OUT_TARGET_POSITION)
//        );
////        if(CollectionUtils.isNotEmpty(bigStorageCageFeedTasks1)){
////
////        }
////        if(CollectionUtils.isNotEmpty(bigStorageCageFeedTasks1)){
////
////        }
//    }
    /**
     * 按照玻璃id判断玻璃状态及卧转立是否可直接启动
@@ -623,8 +646,8 @@
                );
                EdgGlassTaskInfo edgGlassTaskInfo = new EdgGlassTaskInfo();
                BeanUtils.copyProperties(glassInfo, edgGlassTaskInfo);
                edgGlassTaskInfo.setWidth((int)glassInfo.getWidth());
                edgGlassTaskInfo.setHeight((int)glassInfo.getHeight());
                edgGlassTaskInfo.setWidth((int) glassInfo.getWidth());
                edgGlassTaskInfo.setHeight((int) glassInfo.getHeight());
                edgGlassTaskInfoList.add(edgGlassTaskInfo);
                log.info("在玻璃信息表中获取玻璃信息{}", edgGlassTaskInfoList);
            }
hangzhoumesParent/moduleService/CacheVerticalGlassModule/src/test/java/com/mes/CacheVerticalGlassModuleApplicationTest.java
@@ -2,13 +2,11 @@
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mes.bigstorage.entity.BigStorageCage;
import com.mes.bigstorage.service.BigStorageCageDetailsService;
import com.mes.bigstorage.service.BigStorageCageService;
import com.mes.bigstoragetask.mapper.BigStorageCageFeedTaskMapper;
import com.mes.common.config.Const;
import com.mes.damage.entity.Damage;
import com.mes.damage.service.DamageService;
@@ -17,7 +15,6 @@
import com.mes.job.PlcStorageCageTask;
import com.mes.pp.entity.ReportingWork;
import com.mes.pp.entity.ReportingWorkDetail;
import com.mes.temperingglass.entity.TemperingGlassInfo;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -32,7 +29,9 @@
import java.net.URL;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
 * @Author : zhoush
@@ -173,7 +172,7 @@
        Damage damage=new Damage();
        damage.setGlassId("P24060403|3|6");
        damage.setLine(2001);
        damage.setWorkingProcedure("冷加工");
        damage.setWorkingProcedure("磨边");
        damage.setRemark("");
        damage.setStatus(2);
        damageService.insertDamage(damage);
hangzhoumesParent/moduleService/GlassStorageModule/src/main/java/com/mes/job/RawGlassPushMessage.java
@@ -2,10 +2,7 @@
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.mes.rawglassdetails.entity.RawGlassStorageDetails;
import com.mes.rawglassdetails.service.RawGlassStorageDetailsService;
import com.mes.rawglassstation.service.RawGlassStorageStationService;
import com.mes.rawglasstask.entity.RawGlassStorageTask;
import com.mes.rawglasstask.service.RawGlassStorageTaskService;
@@ -16,7 +13,6 @@
import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;
/**
 * @author wangfei
@@ -25,56 +21,26 @@
@Component
public class RawGlassPushMessage {
  @Resource private RawGlassStorageStationService rawGlassStorageStationService;
    @Resource
    private RawGlassStorageStationService rawGlassStorageStationService;
  @Resource private RawGlassStorageTaskService rawGlassStorageTaskService;
    @Resource
    private RawGlassStorageTaskService rawGlassStorageTaskService;
  @Resource private RawGlassStorageDetailsService rawGlassStorageDetailsService;
  @Scheduled(fixedDelay = 2000)
  public void sendRawGlassMessage() {
    log.info("发送任务信息和架子信息");
    JSONObject jsonObject = new JSONObject();
    List<RawGlassStorageDetails> rawStationDetailsList =
        rawGlassStorageStationService.listRawGlassDetails();
    List<RawGlassStorageTask> tasks = rawGlassStorageTaskService.listRawGlassTask();
    jsonObject.append("rawStationDetailsList", rawStationDetailsList);
    jsonObject.append("tasks", tasks);
//    log.info("获取到的工位详情及任务信息为:{}", jsonObject);
    List<WebSocketServer> sendwServer = WebSocketServer.sessionMap.get("rawGlass");
    if (CollectionUtil.isNotEmpty(sendwServer)) {
      sendwServer.stream().forEach(e->{
        e.sendMessage(String.valueOf(jsonObject));
      });
    @Scheduled(fixedDelay = 2000)
    public void sendRawGlassMessage() {
        log.info("发送任务信息和架子信息");
        JSONObject jsonObject = new JSONObject();
        List<RawGlassStorageDetails> rawStationDetailsList =
                rawGlassStorageStationService.listRawGlassDetails();
        List<RawGlassStorageTask> tasks = rawGlassStorageTaskService.listRawGlassTask();
        jsonObject.append("rawStationDetailsList", rawStationDetailsList);
        jsonObject.append("tasks", tasks);
        List<WebSocketServer> sendwServer = WebSocketServer.sessionMap.get("rawGlass");
        if (CollectionUtil.isNotEmpty(sendwServer)) {
            sendwServer.stream().forEach(e -> {
                e.sendMessage(String.valueOf(jsonObject));
            });
        }
    }
  }
  /** todo:入库任务:吊装位有玻璃,先去工位表查询空格子,生成入库任务从吊装位到目标格子 */
//  @Scheduled(fixedDelay = 1000)
//  public void sendRawGlassMessage() {
////    List<RawGlassStorageDetails> rawGlassStorageDetailsList = rawGlassStorageDetailsService.List(new RawGlassStorageDetails())
//    Wrapper<RawGlassStorageDetails> queryWrapper = null;
//    List<RawGlassStorageDetails> detailsList = rawGlassStorageDetailsService.list(null);
//    queryWrapper.eq(RawGlassStorageDetails::getState, 100);
//  if(detailsList.size() >0){
//    //查找格子表details空格子
//    List<String> slotIds = detailsList.stream()
//            .map(RawGlassStorageDetails::getSlotId)
//            .collect(Collectors.toList());
//    list(new LambdaQueryWrapper<RawGlassStorageTask>()
//            .in(CollectionUtil.isNotEmpty(request.getState()), RawGlassStorageTask::getState, request.getState())
//            .in(CollectionUtil.isNotEmpty(request.getSlotId()), RawGlassStorageTask::getSlotId, request.getSlotId())
//            .orderByDesc(RawGlassStorageTask::getCreateTime));
//  }if(slotIds.size()>0){
//      //生成入库任务
//    }
//
//  }
  /** todo:出库任务:1、点出库,立马生成出片任务 2、点出库修改工位详情内的状态为待出库,定时任务扫描生成出库任务 */
  /** todo:原片调度:1、查询工程原片表,按照顺序将原片放入上片1号位,后续原片放上片2号位,出现尺寸替换,判断原上片位是否有玻璃,有 先出后进,无 直接进片 */
}
hangzhoumesParent/moduleService/GlassStorageModule/src/main/java/com/mes/job/RawGlassTask.java
New file
@@ -0,0 +1,235 @@
package com.mes.job;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.kangaroohy.milo.model.ReadWriteEntity;
import com.kangaroohy.milo.service.MiloService;
import com.mes.common.config.Const;
import com.mes.engineering.entity.Engineering;
import com.mes.engineering.mapper.EngineeringMapper;
import com.mes.rawglassdetails.entity.RawGlassStorageDetails;
import com.mes.rawglassdetails.service.RawGlassStorageDetailsService;
import com.mes.rawglassstation.entity.RawGlassStorageStation;
import com.mes.rawglassstation.service.RawGlassStorageStationService;
import com.mes.rawglasstask.entity.RawGlassStorageTask;
import com.mes.rawglasstask.service.RawGlassStorageTaskService;
import com.mes.uppattenusage.entity.vo.UpPattenUsageVO;
import com.mes.uppattenusage.mapper.UpPattenUsageMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
 * @Author : zhoush
 * @Date: 2024/10/11 16:13
 * @Description:
 */
@Slf4j
@Component
public class RawGlassTask {
    @Autowired
    private RawGlassStorageStationService rawGlassStorageStationService;
    @Autowired
    private RawGlassStorageDetailsService rawGlassStorageDetailsService;
    @Autowired
    private RawGlassStorageTaskService rawGlassStorageTaskService;
    @Resource
    private EngineeringMapper engineeringMapper;
    @Resource
    private UpPattenUsageMapper upPattenUsageMapper;
    @Autowired
    private MiloService miloService;
    private static final List<String> liftingStation = Arrays.asList("1", "2");
    private static final List<String> loadGlassStation = Arrays.asList("3", "4", "5", "6");
    /**
     * 入库任务:吊装位有玻璃,先去工位表查询空格子,生成入库任务从吊装位到目标格子
     *
     * @throws Exception
     */
    @Scheduled(fixedDelay = 1000)
    public void warehouseTask() throws Exception {
        ReadWriteEntity entity = miloService.readFromOpcUa("rawglass.device.request");
        String value = entity.getValueString();
        if (!"1".equals(value)) {
            log.info("大车忙碌");
            return;
        }
        List<RawGlassStorageDetails> rawGlassList = rawGlassStorageDetailsService.list(new LambdaQueryWrapper<RawGlassStorageDetails>()
                .eq(RawGlassStorageDetails::getState, Const.GLASS_STATE_IN)
                .inSql(RawGlassStorageDetails::getSlotId, "select slot from raw_glass_storage_station where enable_state = 1 and slot in (1,2)"));
        if (CollectionUtil.isEmpty(rawGlassList)) {
            log.info("吊装位被禁用或没有玻璃");
            return;
        }
        //查询工位信息是否有
        List<RawGlassStorageStation> stationList = rawGlassStorageStationService.list(new LambdaQueryWrapper<RawGlassStorageStation>().notInSql(RawGlassStorageStation::getSlot, "select slot_id from raw_glass_storage_details where state = '100'")
                .eq(RawGlassStorageStation::getEnableState, Const.SLOT_ON));
        if (CollectionUtil.isEmpty(stationList)) {
            log.info("没有空的工位");
            return;
        }
        //生成进笼任务
        generateTask(rawGlassList.get(0).getSlotId(), stationList.get(0).getSlot(),
                rawGlassList.get(0).getRemainQuantity(), Const.RAW_GLASS_TASK_TYPE_IN);
        //生成工位任务,将吊装位的玻璃状态改位进笼中
    }
    /**
     * 出库任务:1、点出库,立马生成出片任务 2、点出库修改工位详情内的状态为待出库,定时任务扫描生成出库任务
     */
    @Scheduled(fixedDelay = 1000)
    public void outboundTask() throws Exception {
        ReadWriteEntity entity = miloService.readFromOpcUa("rawglass.device.request");
        String value = entity.getValueString();
        if (!"2".equals(value)) {
            log.info("大车忙碌");
            return;
        }
        List<RawGlassStorageDetails> rawGlassList = rawGlassStorageDetailsService.list(new LambdaQueryWrapper<RawGlassStorageDetails>()
                .eq(RawGlassStorageDetails::getState, Const.GLASS_STATE_OUT_ING)
                .inSql(RawGlassStorageDetails::getSlotId, "select slot from raw_glass_storage_station where enable_state = 1 and slot not in (1,2)"));
        if (CollectionUtil.isEmpty(rawGlassList)) {
            log.info("系统没有需要出库的原片信息");
            return;
        }
        List<Integer> emptyLeftingList = rawGlassStorageDetailsService.listBySlotState(liftingStation, Arrays.asList(Const.GLASS_STATE_IN));
        if (CollectionUtil.isEmpty(emptyLeftingList)) {
            log.info("吊装位当前都有原片,结束出片任务");
        }
        //生成出库任务
        generateTask(rawGlassList.get(0).getSlotId(), emptyLeftingList.get(0),
                rawGlassList.get(0).getRemainQuantity(), Const.RAW_GLASS_TASK_TYPE_OUT);
    }
    /**
     * 原片调度:1、查询工程原片表,按照顺序将原片放入上片1号位,后续原片放上片2号位,出现尺寸替换,判断原上片位是否有玻璃,有 先出后进,无 直接进片
     */
    @Scheduled(fixedDelay = 1000)
    public void rawGlassDispatchTask() throws Exception {
        ReadWriteEntity entity = miloService.readFromOpcUa("rawglass.device.request");
        String value = entity.getValueString();
        if (!"2".equals(value)) {
            log.info("大车忙碌");
            return;
        }
        //查询当前系统正在执行的订单
        Engineering engineering = engineeringMapper.selectOne(new LambdaQueryWrapper<Engineering>().eq(Engineering::getState, Const.ENGINEERING_RUNNING).last("order by id limit 1"));
        if (null == engineering) {
            log.info("没有正在执行的工程");
            return;
        }
        //当前尺寸需要上片的数量
        List<UpPattenUsageVO> pattenUsageList = upPattenUsageMapper.queryRawGlassByEngineeringId(engineering.getEngineerId());
        if (CollectionUtils.isEmpty(pattenUsageList)) {
            log.info("正在执行的工程原片无可上片的原片信息");
            return;
        }
        Map<String, List<UpPattenUsageVO>> upListMap = pattenUsageList.stream()
                .collect(Collectors.groupingBy(UpPattenUsageVO::getGroupNumber));
        //todo:按照工程号按照工程下未完成的尺寸的顺序,当1号上片位架子上的当前尺寸玻璃少于3片且2号上片位无原片玻璃,则将去调度玻璃去2号上片位,
        //todo:当一号上片位架子上的玻璃位空或者当前尺寸用完时时,将2号(有玻璃)上片位调度到1号上片位
        //1、查询4个上片的原片详情
        List<RawGlassStorageDetails> rawGlassDetailsList = rawGlassStorageDetailsService.list(new LambdaQueryWrapper<RawGlassStorageDetails>()
                .eq(RawGlassStorageDetails::getState, Const.GLASS_STATE_IN).in(RawGlassStorageDetails::getSlotId, loadGlassStation));
        if (CollectionUtils.isEmpty(rawGlassDetailsList)) {
            //表示1上片位没有原片,直接找原片放入对应的上片位
            List<UpPattenUsageVO> upPattenUsage01VOS = upListMap.get("1");
            UpPattenUsageVO usageVO = upPattenUsage01VOS.get(0);
            RawGlassStorageDetails details = rawGlassStorageDetailsService.getOne(new LambdaQueryWrapper<RawGlassStorageDetails>()
                    .eq(RawGlassStorageDetails::getFilmsId, usageVO.getFilmsId())
                    .eq(RawGlassStorageDetails::getPatternWidth, usageVO.getWidth())
                    .eq(RawGlassStorageDetails::getPatternHeight, usageVO.getHeight())
                    .eq(RawGlassStorageDetails::getPatternThickness, usageVO.getThickness())
                    .gt(RawGlassStorageDetails::getRemainQuantity, upPattenUsage01VOS.size())
                    .orderByAsc(RawGlassStorageDetails::getRemainQuantity)
                    .last("limit 1")
            );
            generateTask(details.getSlotId(), 1, details.getRemainQuantity(), Const.RAW_GLASS_TASK_TYPE_DISPATCH);
            //结束调度任务
        }
        Map<Integer, List<RawGlassStorageDetails>> listMap = rawGlassDetailsList.stream().collect(Collectors.groupingBy(RawGlassStorageDetails::getSlotId));
        RawGlassStorageDetails rawGlass03Details = listMap.get(3).get(0);
        RawGlassStorageDetails rawGlass04Details = listMap.get(4).get(0);
//        RawGlassStorageDetails rawGlass05Details = listMap.get(5).get(0);
//        RawGlassStorageDetails rawGlass06Details = listMap.get(6).get(0);
        //todo:上片1号位2种清空方式:方式一:原片用完  方式二:当前尺寸用完
        if (null == rawGlass03Details) {
            if (null == rawGlass04Details) {
                //表示1上片位没有原片,直接找原片放入对应的上片位
                List<UpPattenUsageVO> upPattenUsage01VOS = upListMap.get("1");
                UpPattenUsageVO usageVO = upPattenUsage01VOS.get(0);
                RawGlassStorageDetails details = rawGlassStorageDetailsService.getOne(new LambdaQueryWrapper<RawGlassStorageDetails>()
                        .eq(RawGlassStorageDetails::getFilmsId, usageVO.getFilmsId())
                        .eq(RawGlassStorageDetails::getPatternWidth, usageVO.getWidth())
                        .eq(RawGlassStorageDetails::getPatternHeight, usageVO.getHeight())
                        .eq(RawGlassStorageDetails::getPatternThickness, usageVO.getThickness())
                        .gt(RawGlassStorageDetails::getRemainQuantity, upPattenUsage01VOS.size())
                        .orderByAsc(RawGlassStorageDetails::getRemainQuantity)
                        .last("limit 1")
                );
                generateTask(details.getSlotId(), 1, details.getRemainQuantity(), Const.RAW_GLASS_TASK_TYPE_DISPATCH);
                //结束调度任务
            } else {
                //将2号上片位的原片放入1号上片位
                generateTask(2, 1, rawGlass04Details.getRemainQuantity(), Const.RAW_GLASS_TASK_TYPE_DISPATCH);
                //结束调度任务
            }
        } else {
            if (null == rawGlass04Details) {
                List<UpPattenUsageVO> upPattenUsage01VOS = upListMap.get("2");
                if (CollectionUtils.isEmpty(upPattenUsage01VOS)) {
                    return;
                }
                UpPattenUsageVO usageVO = upPattenUsage01VOS.get(0);
                RawGlassStorageDetails details = rawGlassStorageDetailsService.getOne(new LambdaQueryWrapper<RawGlassStorageDetails>()
                        .eq(RawGlassStorageDetails::getFilmsId, usageVO.getFilmsId())
                        .eq(RawGlassStorageDetails::getPatternWidth, usageVO.getWidth())
                        .eq(RawGlassStorageDetails::getPatternHeight, usageVO.getHeight())
                        .eq(RawGlassStorageDetails::getPatternThickness, usageVO.getThickness())
                        .gt(RawGlassStorageDetails::getRemainQuantity, upPattenUsage01VOS.size())
                        .orderByAsc(RawGlassStorageDetails::getRemainQuantity)
                        .last("limit 1")
                );
                generateTask(details.getSlotId(), 2, details.getRemainQuantity(), Const.RAW_GLASS_TASK_TYPE_DISPATCH);
            }
        }
    }
    /**
     * 生成原片仓储任务
     *
     * @param startSlot
     * @param endSlot
     * @param patternQuantity
     * @param taskType
     * @return
     */
    private boolean generateTask(int startSlot, int endSlot, Integer patternQuantity, int taskType) {
        RawGlassStorageTask task = RawGlassStorageTask.builder()
                .originateSlot(startSlot)
                .endSlot(endSlot)
                .patternQuantity(patternQuantity)
                .taskType(taskType)
                .createTime(new Date()).build();
        return rawGlassStorageTaskService.save(task);
    }
}
hangzhoumesParent/moduleService/GlassStorageModule/src/main/java/com/mes/rawglassdetails/entity/RawGlassStorageDetails.java
@@ -33,7 +33,7 @@
    /**
     * 格子id
     */
    private String slotId;
    private Integer slotId;
    /**
     * 原片宽
@@ -63,7 +63,7 @@
    /**
     * 剩余数量
     */
    private String remainQuantity;
    private Integer remainQuantity;
    /**
hangzhoumesParent/moduleService/GlassStorageModule/src/main/java/com/mes/rawglassdetails/mapper/RawGlassStorageDetailsMapper.java
@@ -1,11 +1,14 @@
package com.mes.rawglassdetails.mapper;
import com.mes.rawglassdetails.entity.RawGlassStorageDetails;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.mes.rawglassdetails.entity.RawGlassStorageDetails;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
 * <p>
 *  Mapper 接口
 * Mapper 接口
 * </p>
 *
 * @author wf
@@ -13,4 +16,12 @@
 */
public interface RawGlassStorageDetailsMapper extends BaseMapper<RawGlassStorageDetails> {
    /**
     * 按照吊装位和详情表状态查询空闲的吊装位
     *
     * @param liftingStation
     * @param state
     * @return
     */
    List<Integer> listBySlotState(@Param("leftingStation") List<String> liftingStation, @Param("state") List<Integer> state);
}
hangzhoumesParent/moduleService/GlassStorageModule/src/main/java/com/mes/rawglassdetails/mapper/xml/RawGlassStorageDetailsMapper.xml
@@ -1,5 +1,19 @@
<?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="glassdetails.mapper.RawGlassStorageDetailsMapper">
<mapper namespace="com.mes.rawglassdetails.mapper.RawGlassStorageDetailsMapper">
    <select id="listBySlotState" resultType="java.lang.Integer">
        select t.slot
        from raw_glass_storage_station t
        inner JOIN raw_glass_storage_details t1
        on t.slot = t1.slot_id and t.enable_state = 1
        and t.slot in
        <foreach collection="leftingStation" item="item" open='(' close=')' separator=','>
            #{item}
        </foreach>
        and t1.state not in
        <foreach collection="state" item="item" open='(' close=')' separator=','>
            #{item}
        </foreach>
    </select>
</mapper>
hangzhoumesParent/moduleService/GlassStorageModule/src/main/java/com/mes/rawglassdetails/service/RawGlassStorageDetailsService.java
@@ -1,10 +1,8 @@
package com.mes.rawglassdetails.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.mes.entity.request.GeneralRequest;
import com.mes.rawglassdetails.entity.RawGlassStorageDetails;
import com.mes.rawglassdetails.entity.request.RawGlassRequest;
import com.mes.userinfo.entity.vo.SysUserVO;
import java.util.List;
@@ -39,4 +37,6 @@
    String deleteWarehousing(Long slotId);
    String outWarehousing(Long slotId);
    List<Integer> listBySlotState(List<String> liftingStation, List<Integer> state);
}
hangzhoumesParent/moduleService/GlassStorageModule/src/main/java/com/mes/rawglassdetails/service/impl/RawGlassStorageDetailsServiceImpl.java
@@ -8,8 +8,6 @@
import com.mes.rawglassdetails.entity.request.RawGlassRequest;
import com.mes.rawglassdetails.mapper.RawGlassStorageDetailsMapper;
import com.mes.rawglassdetails.service.RawGlassStorageDetailsService;
import com.mes.rawglassstation.entity.RawGlassStorageStation;
import com.mes.userinfo.entity.vo.SysUserVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
@@ -24,8 +22,8 @@
@Service
@Slf4j
public class RawGlassStorageDetailsServiceImpl extends ServiceImpl<RawGlassStorageDetailsMapper, RawGlassStorageDetails> implements RawGlassStorageDetailsService {
  @Override
  public boolean deleteRawGlassStorageDetails(String device_id) {
    @Override
    public boolean deleteRawGlassStorageDetails(String device_id) {
        QueryWrapper<RawGlassStorageDetails> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("device_id", device_id);
        return remove(queryWrapper);//remove才是删除,delete得用另外的依赖,默认方法是remove返回bool
@@ -60,17 +58,24 @@
                        .eq(RawGlassStorageDetails::getSlotId, request.getSlotId()));
        return "success";
    }
    @Override
    public String deleteWarehousing(Long slotId) {
        update(new LambdaUpdateWrapper<RawGlassStorageDetails>().eq(RawGlassStorageDetails::getSlotId, slotId)
                .set(RawGlassStorageDetails::getState,Const.GLASS_STATE_OUT));
                .set(RawGlassStorageDetails::getState, Const.GLASS_STATE_OUT));
        return "success";
    }
    @Override
    public String outWarehousing(Long slotId) {
        update(new LambdaUpdateWrapper<RawGlassStorageDetails>().eq(RawGlassStorageDetails::getSlotId, slotId)
                .set(RawGlassStorageDetails::getState,Const.GLASS_STATE_OUT_ING));
                .set(RawGlassStorageDetails::getState, Const.GLASS_STATE_OUT_ING));
        return "success";
    }
    @Override
    public List<Integer> listBySlotState(List<String> liftingStation, List<Integer> state) {
        return baseMapper.listBySlotState(liftingStation, state);
    }
}
hangzhoumesParent/moduleService/GlassStorageModule/src/main/java/com/mes/rawglasstask/entity/RawGlassStorageTask.java
@@ -2,20 +2,23 @@
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.util.Date;
/**
 * <p>
 *
 *
 * </p>
 *
 * @author wf
 * @since 2024-09-10
 */
@Data
@Builder
@EqualsAndHashCode(callSuper = false)
public class RawGlassStorageTask implements Serializable {
@@ -38,7 +41,7 @@
    /**
     * 原片数量
     */
    private String patternQuantity;
    private Integer patternQuantity;
    /**
     * 任务类型
@@ -53,7 +56,7 @@
    /**
     * 创建时间
     */
    private String createTime;
    private Date createTime;
}
hangzhoumesParent/moduleService/TemperingGlassModule/src/main/java/com/mes/job/TemperingTask.java
@@ -152,7 +152,7 @@
                damage.setLine(Const.TEMPERING_OUT_TARGET_POSITION);
                damage.setWorkingProcedure("钢化");
                damage.setRemark("钢化");
                damage.setStatus(0);
                damage.setStatus(1);
                damage.setType(e.getState());
                return damage;
            }).collect(Collectors.toList());
hangzhoumesParent/moduleService/TemperingGlassModule/src/main/resources/application-dev.yml
@@ -34,4 +34,6 @@
    database: 0
    host: 127.0.0.1
    port: 6379
    password: 123456
    password: 123456
  liquibase:
    change-log: classpath:changelog/changelogBase.xml
hangzhoumesParent/moduleService/TemperingGlassModule/src/main/resources/application.yml
@@ -2,16 +2,25 @@
  port: 8084
spring:
  profiles:
    active: cz
    active: dev
  application:
    name: temperingGlass
  liquibase:
    enabled: false
    change-log: classpath:changelog/changelog.sql
    enabled: true
mybatis-plus:
  mapper-locations: classpath*:mapper/*.xml
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
mes:
  width: 2800
  height: 5000
  height: 5000
kangaroohy:
  milo:
    enabled: false
    primary: default
    config:
      default:
        endpoint: opc.tcp://10.153.19.150:49320
        security-policy: basic256sha256
        username: admin
        password: 1qaz2wsx3edc4rfv
hangzhoumesParent/moduleService/TemperingGlassModule/src/main/resources/changelog/changelog.sql
@@ -153,56 +153,61 @@
-- rollback DELETE FROM sys_dict_data WHERE dict_type in ('白玻', '单银', '双银');
-- changeset wangfei:20240918001
-- changeset zsh:20240918001
-- preconditions onFail:CONTINUE onError:CONTINUE
-- precondition-sql-check expectedResult:0 SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'raw_glass_storage_details' and table_schema = 'hangzhoumes';
CREATE TABLE raw_glass_storage_details
(
    id                bigint       NOT NULL AUTO_INCREMENT,
    device_id         int          NULL DEFAULT NULL COMMENT '设备id',
    slot_id           varchar(255) NULL DEFAULT NULL COMMENT '格子id',
    slot              int          NULL DEFAULT NULL COMMENT '格子id',
    pattern_width     double(8, 2) NULL DEFAULT NULL COMMENT '原片宽',
    pattern_height    double(8, 2) NULL DEFAULT NULL COMMENT '原片高',
    pattern_thickness double(8, 2) NULL DEFAULT NULL COMMENT '原片厚度',
    films_id          varchar(255) NULL DEFAULT NULL COMMENT '膜系',
    films_id          varchar(64)  NULL DEFAULT NULL COMMENT '膜系',
    create_time       datetime     NOT NULL COMMENT '创建时间',
    remain_quantity   varchar(255) NULL DEFAULT NULL COMMENT '剩余数量',
    remain_quantity   int          NULL DEFAULT NULL COMMENT '剩余数量',
    state             int          NULL DEFAULT NULL COMMENT '状态',
    PRIMARY KEY (id) USING BTREE
);
-- rollback DROP TABLE raw_glass_storage_details;
-- changeset wangfei:20240918002
-- changeset zsh:20240918002
-- preconditions onFail:CONTINUE onError:CONTINUE
-- precondition-sql-check expectedResult:0 SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'raw_glass_storage_station' and table_schema = 'hangzhoumes';
CREATE TABLE raw_glass_storage_station
(
    id           bigint NOT NULL AUTO_INCREMENT,
    device_id    int NULL DEFAULT NULL COMMENT '设备id',
    slot         int NULL DEFAULT NULL COMMENT '栅格号',
    id           bigint       NOT NULL AUTO_INCREMENT,
    device_id    int          NULL DEFAULT NULL COMMENT '设备id',
    slot         int          NULL DEFAULT NULL COMMENT '栅格号',
    enable_state varchar(255) NULL DEFAULT NULL COMMENT '启用标记',
    start_slot   int NULL DEFAULT NULL COMMENT '开始工位',
    end_slot     int NULL DEFAULT NULL COMMENT '目标工位',
    PRIMARY KEY (id) USING BTREE
    PRIMARY KEY (id)
);
-- rollback DROP TABLE raw_glass_storage_station;
-- changeset wangfei:20240918003
-- changeset zsh:20240918003
-- preconditions onFail:CONTINUE onError:CONTINUE
-- precondition-sql-check expectedResult:0 SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'raw_glass_storage_task' and table_schema = 'hangzhoumes';
CREATE TABLE raw_glass_storage_task
(
    id               bigint NOT NULL AUTO_INCREMENT,
    enable_id        int NULL DEFAULT NULL COMMENT '任务ID',
    originate_slot   int NULL DEFAULT NULL COMMENT '起始格子',
    end_slot         int NULL DEFAULT NULL COMMENT '目标格子',
    pattern_quantity varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '原片数量',
    enable_type      int NULL DEFAULT NULL COMMENT '任务类型',
    enable_state     int NULL DEFAULT NULL COMMENT '任务状态',
    id               bigint   NOT NULL AUTO_INCREMENT,
    start_slot       int      NULL DEFAULT NULL COMMENT '起始格子',
    end_slot         int      NULL DEFAULT NULL COMMENT '目标格子',
    pattern_quantity int      NULL DEFAULT NULL COMMENT '原片数量',
    enable_type      int      NULL DEFAULT NULL COMMENT '任务类型',
    enable_state     int      NULL DEFAULT NULL COMMENT '任务状态',
    create_time      datetime NULL DEFAULT NULL COMMENT '创建时间',
    PRIMARY KEY (id) USING BTREE
);
-- rollback DROP TABLE raw_glass_storage_task;
-- changeset zsh:20241015001
-- preconditions onFail:CONTINUE onError:CONTINUE
-- precondition-sql-check expectedResult:0 SELECT count(0) FROM information_schema.columns WHERE table_schema = 'hangzhoumes' AND table_name = 'engineering' AND column_name = 'station_cell';
ALTER TABLE engineering
    ADD COLUMN station_cell varchar(20);
hangzhoumesParent/moduleService/UnLoadGlassModule/src/main/java/com/mes/downglassinfo/service/impl/DownGlassInfoServiceImpl.java
@@ -1,6 +1,5 @@
package com.mes.downglassinfo.service.impl;
import cn.smallbun.screw.core.util.CollectionUtils;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
@@ -19,6 +18,7 @@
import com.mes.downworkstation.entity.dto.DownGlassInfoDTO;
import com.mes.downworkstation.service.DownWorkstationService;
import com.mes.glassinfo.entity.GlassInfo;
import com.mes.glassinfo.service.GlassInfoService;
import com.mes.job.DownLoadCacheGlassTask;
import com.mes.pp.service.FlowCardService;
import lombok.extern.slf4j.Slf4j;
@@ -31,7 +31,6 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Slf4j
@Service
@@ -52,6 +51,9 @@
    @Autowired
    FlowCardService flowCardService;
    @Autowired
    GlassInfoService glassInfoService;
    /**
     * 根据流程卡号查询最大序号
@@ -224,8 +226,15 @@
    @Override
    public List<Map<String, Object>> downGlassLabelPrint(DownGlassInfo downGlassInfo) {
        List<Map<String, Object>> resultList = baseMapper.downGlassLabelPrint(downGlassInfo.getFlowCardId(), downGlassInfo.getLayer());
        List<Map<String, Object>> resultList = null;
        if (downGlassInfo.getGlassId() != null) {
            resultList = glassInfoService.listMaps(
                    new LambdaQueryWrapper<GlassInfo>()
                            .eq(GlassInfo::getGlassId, downGlassInfo.getGlassId())
            );
        } else {
            resultList = baseMapper.downGlassLabelPrint(downGlassInfo.getFlowCardId(), downGlassInfo.getLayer());
        }
        log.info("MES落架数据:{}", resultList);
        //获取ERP标签所需的信息
        List<Map<String, Object>> labelInfo;
hangzhoumesParent/moduleService/UnLoadGlassModule/src/main/java/com/mes/job/DownLoadCacheGlassTask.java
@@ -30,7 +30,6 @@
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@@ -93,7 +92,6 @@
        String confirmationWrodValue = plcParameterObject.getPlcParameter("confirmationWord").getValue();
        String confirmationWrodAddress = plcParameterObject.getPlcParameter("confirmationWord").getAddress();
        String currentSlot = plcParameterObject.getPlcParameter("currentCell").getValue();
        log.info("1、获取到的请求字为:{},获取到的扫描ID为:{},获取到的确认字为:{},获取到的出片状态分别为:g06:{}、g08:{}、g11:{}、g13:{},当前格子号为:{}",
                requestWord, glassIdeValue, confirmationWrodValue, out06Glassstate, out08Glassstate, out11Glassstate, out13Glassstate, currentSlot);
@@ -169,9 +167,9 @@
                Damage damage = new Damage();
                damage.setGlassId(e.getGlassId());
                damage.setLine(Const.TEMPERING_OUT_TARGET_POSITION);
                damage.setWorkingProcedure("下片");
                damage.setWorkingProcedure("钢化");
                damage.setRemark("下片");
                damage.setStatus(0);
                damage.setStatus(1);
                damage.setType(e.getTaskStatus());
                return damage;
            }).collect(Collectors.toList());
hangzhoumesParent/moduleService/UnLoadGlassModule/src/main/resources/application.yml
File was deleted
hangzhoumesParent/moduleService/pom.xml
@@ -55,11 +55,6 @@
            <groupId>com.mes</groupId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <artifactId>opcuaClient</artifactId>
            <groupId>com.mes</groupId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <!--开发者工具-->
        <!--        <dependency>-->
hangzhoumesParent/readMe-OPC.md
New file
@@ -0,0 +1,6 @@
3.1.1.0.6.13 读值支持返回更多信息 #PR16 3.1.0.6.13 升级到最新版本 0.6.13 修改订阅监听callback参数以获取更多信息,具有破坏性!!!#PR15 3.0.6.12 升级到最新版本 0.6.12
连接池配置优化 #gitee I86XSX 3.0.5 支持配置是否启用组件:kangaroohy.milo.enabled=true 3.0.4 支持配置多个 opc ua 服务器,调用方法时可手动指定需要访问的服务器 批量读值方法优化
升级milo依赖到 0.6.10 3.0.3 ID支持字符串表示法:ns=<命名空间索引>;<标识符类型>=<标识符>
3.0.2 订阅时 支持指定订阅时间间隙,默认 1000ms 3.0.1 endpoint 支持外网穿透类的地址 新增点位订阅方法,订阅断掉自动重连 外网穿透类地址如: 内网地址为:opc.tcp://192.168.68.128:
49320 外网地址为:opc.tcp://opc.kangaroohy.com:59320 3.0.0 适配 spring boot 3.x,也可在spring boot 2.x中使用 基于 eclipse milo 最新版本 0.6.9
支持连接池配置
pom.xml
File was deleted