Browse Source

Merge branch 'professional2' of http://git.mydig.net/Sagoo-Cloud/sagoo-admin-ui into professional2

Xiahai 1 year ago
parent
commit
2427760bba
93 changed files with 1126 additions and 6724 deletions
  1. 14 0
      .env.golocal
  2. 4 1
      README.md
  3. 0 3655
      package-lock.json
  4. 2 0
      package.json
  5. 10 11
      src/api/alarm/index.ts
  6. 46 34
      src/api/datahub/index.ts
  7. 18 18
      src/api/device/index.ts
  8. 1 1
      src/api/ota/index.ts
  9. 31 0
      src/components/copy/index.vue
  10. 11 10
      src/components/devantd/index.vue
  11. 1 1
      src/components/noticeBar/index.vue
  12. 1 1
      src/components/upload-wrapper/index.vue
  13. 1 1
      src/components/upload/index.vue
  14. 1 1
      src/components/vue3cron/vue3cron.vue
  15. 2 2
      src/layout/lockScreen/index.vue
  16. 2 2
      src/layout/navBars/breadcrumb/breadcrumb.vue
  17. 2 2
      src/layout/navBars/breadcrumb/search.vue
  18. 1 1
      src/layout/navBars/breadcrumb/setings.vue
  19. 3 3
      src/layout/navBars/breadcrumb/user.vue
  20. 1 1
      src/layout/navBars/breadcrumb/userNews.vue
  21. 1 1
      src/layout/navBars/tagsView/tagsView.vue
  22. 2 2
      src/layout/navMenu/horizontal.vue
  23. 2 0
      src/main.ts
  24. 12 0
      src/utils/copy.ts
  25. 1 1
      src/views/iot/alarm/log/component/detail.vue
  26. 1 1
      src/views/iot/alarm/log/component/edit.vue
  27. 29 37
      src/views/iot/alarm/setting/component/edit.vue
  28. 0 80
      src/views/iot/alarm/setting/component/level.vue
  29. 12 28
      src/views/iot/alarm/setting/index.vue
  30. 2 2
      src/views/iot/device-tree/tree/index.vue
  31. 4 4
      src/views/iot/device/channel/component/detail.vue
  32. 5 3
      src/views/iot/device/channel/component/taskDialog.vue
  33. 17 17
      src/views/iot/device/instance/component/edit.vue
  34. 18 25
      src/views/iot/device/instance/component/excel.vue
  35. 3 3
      src/views/iot/device/instance/component/function.vue
  36. 6 32
      src/views/iot/device/instance/component/list.vue
  37. 4 4
      src/views/iot/device/instance/component/map.vue
  38. 1 2
      src/views/iot/device/instance/component/setAttr.vue
  39. 13 910
      src/views/iot/device/instance/component/subDevice.vue
  40. 19 17
      src/views/iot/device/instance/component/subDeviceMutipleBind.vue
  41. 1 1
      src/views/iot/device/instance/component/tag.vue
  42. 77 131
      src/views/iot/device/instance/detail.vue
  43. 33 27
      src/views/iot/device/instance/index.vue
  44. 3 3
      src/views/iot/device/product/component/dataParse.vue
  45. 7 7
      src/views/iot/device/product/component/editAttr.vue
  46. 59 46
      src/views/iot/device/product/component/editEvent.vue
  47. 60 63
      src/views/iot/device/product/component/editFun.vue
  48. 30 30
      src/views/iot/device/product/component/editOption.vue
  49. 42 33
      src/views/iot/device/product/component/editPro.vue
  50. 48 46
      src/views/iot/device/product/component/editTab.vue
  51. 10 10
      src/views/iot/device/product/component/typeItem.vue
  52. 50 46
      src/views/iot/device/product/detail.vue
  53. 17 14
      src/views/iot/device/product/index.vue
  54. 3 3
      src/views/iot/device/template/component/dataAreaDialog.vue
  55. 5 7
      src/views/iot/device/template/component/deviceTemplateDialog.vue
  56. 2 2
      src/views/iot/device/template/component/edit.vue
  57. 8 10
      src/views/iot/device/template/component/importFile.vue
  58. 0 876
      src/views/iot/device/template/detail.vue
  59. 8 10
      src/views/iot/ice104/device/component/edit.vue
  60. 8 13
      src/views/iot/ice104/device/component/editDeviceForm.vue
  61. 2 2
      src/views/iot/iotCard/dashboard.vue
  62. 1 1
      src/views/iot/iotCard/index/detail.vue
  63. 130 72
      src/views/iot/iotmanager/dashboard.vue
  64. 2 1
      src/views/iot/network/server/component/list.vue
  65. 5 5
      src/views/iot/network/server/create.vue
  66. 5 5
      src/views/iot/network/server/edit.vue
  67. 1 5
      src/views/iot/network/tunnel/component/list.vue
  68. 4 4
      src/views/iot/network/tunnel/create.vue
  69. 8 8
      src/views/iot/network/tunnel/edit.vue
  70. 47 67
      src/views/iot/ota-update/data/index.vue
  71. 8 8
      src/views/iot/ota-update/module/component/edit.vue
  72. 8 7
      src/views/iot/ota-update/module/index.vue
  73. 20 113
      src/views/iot/ota-update/update/component/check.vue
  74. 23 29
      src/views/iot/ota-update/update/component/deviceBind.vue
  75. 16 20
      src/views/iot/ota-update/update/component/edit.vue
  76. 22 40
      src/views/iot/ota-update/update/component/productBind.vue
  77. 0 1
      src/views/iot/ota-update/update/detail.vue
  78. 1 1
      src/views/iot/ota-update/update/index.vue
  79. 1 1
      src/views/iot/property/dossier/edit.vue
  80. 1 3
      src/views/iot/scene/list/index.vue
  81. 7 7
      src/views/iot/scene/manage/component/actionType/deviceOut.vue
  82. 8 8
      src/views/iot/scene/manage/component/sceneItem.vue
  83. 1 1
      src/views/login/component/scan.vue
  84. 2 2
      src/views/personal/index.vue
  85. 7 7
      src/views/system/assess/totalIndex/component/addItem.vue
  86. 3 3
      src/views/system/assess/totalIndex/component/addSign.vue
  87. 1 1
      src/views/system/assess/totalIndex/component/detailItem.vue
  88. 5 5
      src/views/system/assess/totalIndex/component/editItem.vue
  89. 1 1
      src/views/system/assess/totalIndex/component/setTask.vue
  90. 1 1
      src/views/system/assess/totalIndex/index.vue
  91. 2 2
      src/views/system/basicConfig/index.vue
  92. 1 1
      src/views/system/manage/blacklist/index.vue
  93. 7 0
      yarn.lock

+ 14 - 0
.env.golocal

@@ -0,0 +1,14 @@
+# 基础服务路径
+VITE_SERVER_URL = '/'
+# 基础接口路径
+VITE_API_URL = '/api/v1'
+# 指数管理页面用到的
+VITE_ASSESS_URL = '/assess/v1'
+# 大屏前端
+VITE_SCREEN_URL = '/plugin/screen/'
+# 组态图前端
+VITE_TOPO_URL = '/plugin/topo/'
+# modbus服务
+VITE_MODBUS_API = '/modbus'
+# ice104协议网关服务
+VITE_ICE104_API = '/ice104'

+ 4 - 1
README.md

@@ -15,6 +15,9 @@
 
 | 为默认环境配置,不可修改,会导致线上使用异常
 
+**.env.golocal**
+|为go直接运行环境配置,不可修改,会导致go直接运行异常
+
 **.env.development**
 
 | 开发环境配置,可在此配置开发环境,开发使用时会覆盖默认配置
@@ -24,4 +27,4 @@
 | 可在本地添加此文件进行配置,会覆盖默认配置及【.env.development】的配置,并且git会忽略这个文件,不会对其他的开发者的环境造成影响
 
 
-<el-form :model="params" inline ref="queryRef" @submit.prevent @keyup.enter="queryList">
+<el-form :model="params" inline ref="queryRef" @submit.prevent @keyup.enter="queryList">

+ 0 - 3655
package-lock.json

@@ -1,3655 +0,0 @@
-{
-  "name": "vue-next-admin",
-  "version": "2.0.2",
-  "lockfileVersion": 1,
-  "requires": true,
-  "dependencies": {
-    "@antv/adjust": {
-      "version": "0.2.5",
-      "resolved": "https://registry.npmjs.org/@antv/adjust/-/adjust-0.2.5.tgz",
-      "integrity": "sha512-MfWZOkD9CqXRES6MBGRNe27Q577a72EIwyMnE29wIlPliFvJfWwsrONddpGU7lilMpVKecS3WAzOoip3RfPTRQ==",
-      "requires": {
-        "@antv/util": "~2.0.0",
-        "tslib": "^1.10.0"
-      },
-      "dependencies": {
-        "tslib": {
-          "version": "1.14.1",
-          "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
-          "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
-        }
-      }
-    },
-    "@antv/attr": {
-      "version": "0.3.3",
-      "resolved": "https://registry.npmjs.org/@antv/attr/-/attr-0.3.3.tgz",
-      "integrity": "sha512-7iSSRhYzZ7pYXZKTL1ECGhTdKVHPQx1Vj7yYVTAiyLMsWsLUAoMf0m6dT6msTs0SdrXHRbjzXavVXxRj/wZZJA==",
-      "requires": {
-        "@antv/color-util": "^2.0.1",
-        "@antv/util": "~2.0.0",
-        "tslib": "^1.10.0"
-      },
-      "dependencies": {
-        "tslib": {
-          "version": "1.14.1",
-          "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
-          "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
-        }
-      }
-    },
-    "@antv/color-util": {
-      "version": "2.0.6",
-      "resolved": "https://registry.npmjs.org/@antv/color-util/-/color-util-2.0.6.tgz",
-      "integrity": "sha512-KnPEaAH+XNJMjax9U35W67nzPI+QQ2x27pYlzmSIWrbj4/k8PGrARXfzDTjwoozHJY8qG62Z+Ww6Alhu2FctXQ==",
-      "requires": {
-        "@antv/util": "^2.0.9",
-        "tslib": "^2.0.3"
-      }
-    },
-    "@antv/component": {
-      "version": "0.8.32",
-      "resolved": "https://registry.npmjs.org/@antv/component/-/component-0.8.32.tgz",
-      "integrity": "sha512-KyQcI4rVfY6VBfkgFMebcvw5CQEJOykuTq+v1nFzJ283Pt3YiFZNAfHnKVj7oXtWMGLNI3/yGfrlPPvFmV5EeA==",
-      "requires": {
-        "@antv/color-util": "^2.0.3",
-        "@antv/dom-util": "~2.0.1",
-        "@antv/g-base": "^0.5.9",
-        "@antv/matrix-util": "^3.1.0-beta.1",
-        "@antv/path-util": "~2.0.7",
-        "@antv/scale": "~0.3.1",
-        "@antv/util": "~2.0.0",
-        "fecha": "~4.2.0",
-        "tslib": "^2.0.3"
-      }
-    },
-    "@antv/coord": {
-      "version": "0.3.1",
-      "resolved": "https://registry.npmjs.org/@antv/coord/-/coord-0.3.1.tgz",
-      "integrity": "sha512-rFE94C8Xzbx4xmZnHh2AnlB3Qm1n5x0VT3OROy257IH6Rm4cuzv1+tZaUBATviwZd99S+rOY9telw/+6C9GbRw==",
-      "requires": {
-        "@antv/matrix-util": "^3.1.0-beta.2",
-        "@antv/util": "~2.0.12",
-        "tslib": "^2.1.0"
-      }
-    },
-    "@antv/dom-util": {
-      "version": "2.0.4",
-      "resolved": "https://registry.npmjs.org/@antv/dom-util/-/dom-util-2.0.4.tgz",
-      "integrity": "sha512-2shXUl504fKwt82T3GkuT4Uoc6p9qjCKnJ8gXGLSW4T1W37dqf9AV28aCfoVPHp2BUXpSsB+PAJX2rG/jLHsLQ==",
-      "requires": {
-        "tslib": "^2.0.3"
-      }
-    },
-    "@antv/event-emitter": {
-      "version": "0.1.3",
-      "resolved": "https://registry.npmjs.org/@antv/event-emitter/-/event-emitter-0.1.3.tgz",
-      "integrity": "sha512-4ddpsiHN9Pd4UIlWuKVK1C4IiZIdbwQvy9i7DUSI3xNJ89FPUFt8lxDYj8GzzfdllV0NkJTRxnG+FvLk0llidg=="
-    },
-    "@antv/g-base": {
-      "version": "0.5.11",
-      "resolved": "https://registry.npmjs.org/@antv/g-base/-/g-base-0.5.11.tgz",
-      "integrity": "sha512-10Hkq7XksVCqxZZrPkd6HTU9tb/+2meCVEMy/edhS4I/sokhcgC9m3fQP5bE8rA3EVKwELE7MJHZ98BEpVFqvQ==",
-      "requires": {
-        "@antv/event-emitter": "^0.1.1",
-        "@antv/g-math": "^0.1.6",
-        "@antv/matrix-util": "^3.1.0-beta.1",
-        "@antv/path-util": "~2.0.5",
-        "@antv/util": "~2.0.13",
-        "@types/d3-timer": "^2.0.0",
-        "d3-ease": "^1.0.5",
-        "d3-interpolate": "^1.3.2",
-        "d3-timer": "^1.0.9",
-        "detect-browser": "^5.1.0",
-        "tslib": "^2.0.3"
-      }
-    },
-    "@antv/g-canvas": {
-      "version": "0.5.12",
-      "resolved": "https://registry.npmjs.org/@antv/g-canvas/-/g-canvas-0.5.12.tgz",
-      "integrity": "sha512-iJ/muwwqCCNONVlPIzv/7OL5iLguaKRj2BxNMytUO3TWwamM+kHkiyYEOkS0dPn9h/hBsHYlLUluSVz2Fp6/bw==",
-      "requires": {
-        "@antv/g-base": "^0.5.3",
-        "@antv/g-math": "^0.1.6",
-        "@antv/matrix-util": "^3.1.0-beta.1",
-        "@antv/path-util": "~2.0.5",
-        "@antv/util": "~2.0.0",
-        "gl-matrix": "^3.0.0",
-        "tslib": "^2.0.3"
-      }
-    },
-    "@antv/g-math": {
-      "version": "0.1.7",
-      "resolved": "https://registry.npmjs.org/@antv/g-math/-/g-math-0.1.7.tgz",
-      "integrity": "sha512-xGyXaloD1ynfp7gS4VuV+MjSptZIwHvLHr8ekXJSFAeWPYLu84yOW2wOZHDdp1bzDAIuRv6xDBW58YGHrWsFcA==",
-      "requires": {
-        "@antv/util": "~2.0.0",
-        "gl-matrix": "^3.0.0"
-      }
-    },
-    "@antv/g-svg": {
-      "version": "0.5.6",
-      "resolved": "https://registry.npmjs.org/@antv/g-svg/-/g-svg-0.5.6.tgz",
-      "integrity": "sha512-Xve1EUGk4HMbl2nq4ozR4QLh6GyoZ8Xw/+9kHYI4B5P2lIUQU95MuRsaLFfW5NNpZDx85ZeH97tqEmC9L96E7A==",
-      "requires": {
-        "@antv/g-base": "^0.5.3",
-        "@antv/g-math": "^0.1.6",
-        "@antv/util": "~2.0.0",
-        "detect-browser": "^5.0.0",
-        "tslib": "^2.0.3"
-      }
-    },
-    "@antv/g2": {
-      "version": "4.2.8",
-      "resolved": "https://registry.npmjs.org/@antv/g2/-/g2-4.2.8.tgz",
-      "integrity": "sha512-V2ntdehdCTCjSdkDxC1/kafii/2MZ2dhLd/auMoE6viwIvyy5CKkd7qa9krxJ4IIR5RH9v5uoRV8q2Bzd0OD2Q==",
-      "requires": {
-        "@antv/adjust": "^0.2.1",
-        "@antv/attr": "^0.3.1",
-        "@antv/color-util": "^2.0.2",
-        "@antv/component": "^0.8.27",
-        "@antv/coord": "^0.3.0",
-        "@antv/dom-util": "^2.0.2",
-        "@antv/event-emitter": "~0.1.0",
-        "@antv/g-base": "~0.5.6",
-        "@antv/g-canvas": "~0.5.10",
-        "@antv/g-svg": "~0.5.6",
-        "@antv/matrix-util": "^3.1.0-beta.3",
-        "@antv/path-util": "^2.0.15",
-        "@antv/scale": "^0.3.14",
-        "@antv/util": "~2.0.5",
-        "tslib": "^2.0.0"
-      }
-    },
-    "@antv/g2plot": {
-      "version": "2.4.20",
-      "resolved": "https://registry.npmjs.org/@antv/g2plot/-/g2plot-2.4.20.tgz",
-      "integrity": "sha512-MHFTe3zdEHy/5VHdG9LmX9jQy9NdZm31olQjhE65eGpxhX5N1ibyo+qO247I9Jazb4sLD5LNWYPtPHofUOUaNg==",
-      "requires": {
-        "@antv/event-emitter": "^0.1.2",
-        "@antv/g2": "^4.1.26",
-        "@antv/util": "^2.0.17",
-        "d3-hierarchy": "^2.0.0",
-        "d3-regression": "^1.3.5",
-        "fmin": "^0.0.2",
-        "pdfast": "^0.2.0",
-        "size-sensor": "^1.0.1",
-        "tslib": "^2.0.3"
-      }
-    },
-    "@antv/matrix-util": {
-      "version": "3.1.0-beta.3",
-      "resolved": "https://registry.npmjs.org/@antv/matrix-util/-/matrix-util-3.1.0-beta.3.tgz",
-      "integrity": "sha512-W2R6Za3A6CmG51Y/4jZUM/tFgYSq7vTqJL1VD9dKrvwxS4sE0ZcXINtkp55CdyBwJ6Cwm8pfoRpnD4FnHahN0A==",
-      "requires": {
-        "@antv/util": "^2.0.9",
-        "gl-matrix": "^3.4.3",
-        "tslib": "^2.0.3"
-      }
-    },
-    "@antv/path-util": {
-      "version": "2.0.15",
-      "resolved": "https://registry.npmjs.org/@antv/path-util/-/path-util-2.0.15.tgz",
-      "integrity": "sha512-R2VLZ5C8PLPtr3VciNyxtjKqJ0XlANzpFb5sE9GE61UQqSRuSVSzIakMxjEPrpqbgc+s+y8i+fmc89Snu7qbNw==",
-      "requires": {
-        "@antv/matrix-util": "^3.0.4",
-        "@antv/util": "^2.0.9",
-        "tslib": "^2.0.3"
-      },
-      "dependencies": {
-        "@antv/matrix-util": {
-          "version": "3.0.4",
-          "resolved": "https://registry.npmjs.org/@antv/matrix-util/-/matrix-util-3.0.4.tgz",
-          "integrity": "sha512-BAPyu6dUliHcQ7fm9hZSGKqkwcjEDVLVAstlHULLvcMZvANHeLXgHEgV7JqcAV/GIhIz8aZChIlzM1ZboiXpYQ==",
-          "requires": {
-            "@antv/util": "^2.0.9",
-            "gl-matrix": "^3.3.0",
-            "tslib": "^2.0.3"
-          }
-        }
-      }
-    },
-    "@antv/scale": {
-      "version": "0.3.18",
-      "resolved": "https://registry.npmjs.org/@antv/scale/-/scale-0.3.18.tgz",
-      "integrity": "sha512-GHwE6Lo7S/Q5fgaLPaCsW+CH+3zl4aXpnN1skOiEY0Ue9/u+s2EySv6aDXYkAqs//i0uilMDD/0/4n8caX9U9w==",
-      "requires": {
-        "@antv/util": "~2.0.3",
-        "fecha": "~4.2.0",
-        "tslib": "^2.0.0"
-      }
-    },
-    "@antv/util": {
-      "version": "2.0.17",
-      "resolved": "https://registry.npmjs.org/@antv/util/-/util-2.0.17.tgz",
-      "integrity": "sha512-o6I9hi5CIUvLGDhth0RxNSFDRwXeywmt6ExR4+RmVAzIi48ps6HUy+svxOCayvrPBN37uE6TAc2KDofRo0nK9Q==",
-      "requires": {
-        "csstype": "^3.0.8",
-        "tslib": "^2.0.3"
-      }
-    },
-    "@babel/parser": {
-      "version": "7.18.11",
-      "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.18.11.tgz",
-      "integrity": "sha512-9JKn5vN+hDt0Hdqn1PiJ2guflwP+B6Ga8qbDuoF0PzzVhrzsKIJo8yGqVk6CmMHiMei9w1C1Bp9IMJSIK+HPIQ=="
-    },
-    "@babel/runtime": {
-      "version": "7.18.9",
-      "resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.18.9.tgz",
-      "integrity": "sha512-lkqXDcvlFT5rvEjiu6+QYO+1GXrEHRo2LOtS7E4GtX5ESIZOgepqsZBVIj6Pv+a6zqsya9VCgiK1KAK4BvJDAw==",
-      "requires": {
-        "regenerator-runtime": "^0.13.4"
-      }
-    },
-    "@babel/runtime-corejs3": {
-      "version": "7.18.9",
-      "resolved": "https://registry.npmmirror.com/@babel/runtime-corejs3/-/runtime-corejs3-7.18.9.tgz",
-      "integrity": "sha512-qZEWeccZCrHA2Au4/X05QW5CMdm4VjUDCrGq5gf1ZDcM4hRqreKrtwAn7yci9zfgAS9apvnsFXiGBHBAxZdK9A==",
-      "requires": {
-        "core-js-pure": "^3.20.2",
-        "regenerator-runtime": "^0.13.4"
-      }
-    },
-    "@codemirror/commands": {
-      "version": "6.1.0",
-      "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.1.0.tgz",
-      "integrity": "sha512-qCj2YqmbBjj0P1iumnlL5lBqZvJPzT+t2UvgjcaXErp5ZvMqFRVgQyrEfdXX6SX5UcvcHKBjXqno+MkUp0aYvQ==",
-      "requires": {
-        "@codemirror/language": "^6.0.0",
-        "@codemirror/state": "^6.0.0",
-        "@codemirror/view": "^6.0.0",
-        "@lezer/common": "^1.0.0"
-      }
-    },
-    "@codemirror/language": {
-      "version": "6.2.1",
-      "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.2.1.tgz",
-      "integrity": "sha512-MC3svxuvIj0MRpFlGHxLS6vPyIdbTr2KKPEW46kCoCXw2ktb4NTkpkPBI/lSP/FoNXLCBJ0mrnUi1OoZxtpW1Q==",
-      "requires": {
-        "@codemirror/state": "^6.0.0",
-        "@codemirror/view": "^6.0.0",
-        "@lezer/common": "^1.0.0",
-        "@lezer/highlight": "^1.0.0",
-        "@lezer/lr": "^1.0.0",
-        "style-mod": "^4.0.0"
-      }
-    },
-    "@codemirror/state": {
-      "version": "6.1.1",
-      "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.1.1.tgz",
-      "integrity": "sha512-2s+aXsxmAwnR3Rd+JDHPG/1lw0YsA9PEwl7Re88gHJHGfxyfEzKBmsN4rr53RyPIR4lzbbhJX0DCq0WlqlBIRw=="
-    },
-    "@codemirror/view": {
-      "version": "6.2.2",
-      "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.2.2.tgz",
-      "integrity": "sha512-RwtFlBM/+xnv95urH1D8bVsX3KYLZGygGyZG2TZoXW2Q/GMrI+AuUXh7jBE1M38IOX3YnLTlp6RdgCx3Xo2jVA==",
-      "requires": {
-        "@codemirror/state": "^6.0.0",
-        "style-mod": "^4.0.0",
-        "w3c-keyname": "^2.2.4"
-      }
-    },
-    "@ctrl/tinycolor": {
-      "version": "3.6.1",
-      "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz",
-      "integrity": "sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA=="
-    },
-    "@element-plus/icons": {
-      "version": "0.0.11",
-      "resolved": "https://registry.npmmirror.com/@element-plus/icons/-/icons-0.0.11.tgz",
-      "integrity": "sha512-iKQXSxXu131Ai+I9Ymtcof9WId7kaXvB1+WRfAfpQCW7UiAMYgdNDqb/u0hgTo2Yq3MwC4MWJnNuTBEpG8r7+A=="
-    },
-    "@element-plus/icons-vue": {
-      "version": "2.0.9",
-      "resolved": "https://registry.npmmirror.com/@element-plus/icons-vue/-/icons-vue-2.0.9.tgz",
-      "integrity": "sha512-okdrwiVeKBmW41Hkl0eMrXDjzJwhQMuKiBOu17rOszqM+LS/yBYpNQNV5Jvoh06Wc+89fMmb/uhzf8NZuDuUaQ=="
-    },
-    "@esbuild/linux-loong64": {
-      "version": "0.14.54",
-      "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.14.54.tgz",
-      "integrity": "sha512-bZBrLAIX1kpWelV0XemxBZllyRmM6vgFQQG2GdNb+r3Fkp0FOh1NJSvekXDs7jq70k4euu1cryLMfU+mTXlEpw==",
-      "dev": true,
-      "optional": true
-    },
-    "@eslint/eslintrc": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmmirror.com/@eslint/eslintrc/-/eslintrc-1.3.0.tgz",
-      "integrity": "sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw==",
-      "dev": true,
-      "requires": {
-        "ajv": "^6.12.4",
-        "debug": "^4.3.2",
-        "espree": "^9.3.2",
-        "globals": "^13.15.0",
-        "ignore": "^5.2.0",
-        "import-fresh": "^3.2.1",
-        "js-yaml": "^4.1.0",
-        "minimatch": "^3.1.2",
-        "strip-json-comments": "^3.1.1"
-      }
-    },
-    "@floating-ui/core": {
-      "version": "1.5.0",
-      "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.5.0.tgz",
-      "integrity": "sha512-kK1h4m36DQ0UHGj5Ah4db7R0rHemTqqO0QLvUqi1/mUUp3LuAWbWxdxSIf/XsnH9VS6rRVPLJCncjRzUvyCLXg==",
-      "requires": {
-        "@floating-ui/utils": "^0.1.3"
-      }
-    },
-    "@floating-ui/dom": {
-      "version": "1.5.3",
-      "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.5.3.tgz",
-      "integrity": "sha512-ClAbQnEqJAKCJOEbbLo5IUlZHkNszqhuxS4fHAVxRPXPya6Ysf2G8KypnYcOTpx6I8xcgF9bbHb6g/2KpbV8qA==",
-      "requires": {
-        "@floating-ui/core": "^1.4.2",
-        "@floating-ui/utils": "^0.1.3"
-      }
-    },
-    "@floating-ui/utils": {
-      "version": "0.1.6",
-      "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.1.6.tgz",
-      "integrity": "sha512-OfX7E2oUDYxtBvsuS4e/jSn4Q9Qb6DzgeYtsAdkPZ47znpoNsMgZw0+tVijiv3uGNR6dgNlty6r9rzIzHjtd/A=="
-    },
-    "@humanwhocodes/config-array": {
-      "version": "0.10.4",
-      "resolved": "https://registry.npmmirror.com/@humanwhocodes/config-array/-/config-array-0.10.4.tgz",
-      "integrity": "sha512-mXAIHxZT3Vcpg83opl1wGlVZ9xydbfZO3r5YfRSH6Gpp2J/PfdBP0wbDa2sO6/qRbcalpoevVyW6A/fI6LfeMw==",
-      "dev": true,
-      "requires": {
-        "@humanwhocodes/object-schema": "^1.2.1",
-        "debug": "^4.1.1",
-        "minimatch": "^3.0.4"
-      }
-    },
-    "@humanwhocodes/gitignore-to-minimatch": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmmirror.com/@humanwhocodes/gitignore-to-minimatch/-/gitignore-to-minimatch-1.0.2.tgz",
-      "integrity": "sha512-rSqmMJDdLFUsyxR6FMtD00nfQKKLFb1kv+qBbOVKqErvloEIJLo5bDTJTQNTYgeyp78JsA7u/NPi5jT1GR/MuA==",
-      "dev": true
-    },
-    "@humanwhocodes/object-schema": {
-      "version": "1.2.1",
-      "resolved": "https://registry.npmmirror.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz",
-      "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
-      "dev": true
-    },
-    "@interactjs/actions": {
-      "version": "1.10.17",
-      "resolved": "https://registry.npmmirror.com/@interactjs/actions/-/actions-1.10.17.tgz",
-      "integrity": "sha512-wyB1ZqpaZy5gmz6VDqK9KWh98xKnFgL7VyLvxHODFi9V0IYX4HJAAOBlhtfze0D1R1f1cY+gqPDK+dLaHMlE+w==",
-      "requires": {
-        "@interactjs/interact": "1.10.17"
-      }
-    },
-    "@interactjs/auto-scroll": {
-      "version": "1.10.17",
-      "resolved": "https://registry.npmmirror.com/@interactjs/auto-scroll/-/auto-scroll-1.10.17.tgz",
-      "integrity": "sha512-IQcW7N3xOaoL8RnAGOGMk0Y2gue7L4S3BT6Id4VBBu8so163DtLiZVW6jXu9rKVntzbluaAeqNZlfAVyu3kIWg==",
-      "requires": {
-        "@interactjs/interact": "1.10.17"
-      }
-    },
-    "@interactjs/auto-start": {
-      "version": "1.10.17",
-      "resolved": "https://registry.npmmirror.com/@interactjs/auto-start/-/auto-start-1.10.17.tgz",
-      "integrity": "sha512-qYVxhAbYnwxjD/NLEegUoAST7WASJ4VmWNjsyWRx/js5Op+I4E2zteARIeZGgrutcGIXMCcQzhCMgE3PjOpbpw==",
-      "requires": {
-        "@interactjs/interact": "1.10.17"
-      }
-    },
-    "@interactjs/core": {
-      "version": "1.10.17",
-      "resolved": "https://registry.npmmirror.com/@interactjs/core/-/core-1.10.17.tgz",
-      "integrity": "sha512-rL9w+83HDRuXub8Ezqs+97CYLl/ne7bLT/sAeduUWaxYhsW9iOqBoob9JnkkCZOaOsYizWI1EWy0+fNc5ibtLQ=="
-    },
-    "@interactjs/dev-tools": {
-      "version": "1.10.17",
-      "resolved": "https://registry.npmmirror.com/@interactjs/dev-tools/-/dev-tools-1.10.17.tgz",
-      "integrity": "sha512-Oi9nEw3FfSwkNmW+V0WwdHqvzEkVHc24mH1v5EjRn60sqgrGLK9nTQ+NSuqcnUY8GxC3TkyuxnsOodxiadIRmA==",
-      "requires": {
-        "@interactjs/interact": "1.10.17"
-      }
-    },
-    "@interactjs/inertia": {
-      "version": "1.10.17",
-      "resolved": "https://registry.npmmirror.com/@interactjs/inertia/-/inertia-1.10.17.tgz",
-      "integrity": "sha512-41vbYUjZIDCKt2/yhmjPrEW5+0uoL/hldFsll9pkvnLhmm12Xk0VXOlmR2zXKAmsTK3fJlKMyBYUX92qHLkyVQ==",
-      "requires": {
-        "@interactjs/interact": "1.10.17",
-        "@interactjs/offset": "1.10.17"
-      }
-    },
-    "@interactjs/interact": {
-      "version": "1.10.17",
-      "resolved": "https://registry.npmmirror.com/@interactjs/interact/-/interact-1.10.17.tgz",
-      "integrity": "sha512-NyKsf8EFudvdahBjPz1Gt5QnynVwa/2LUfBc2/w8QOnOBiyzUm0HLloJSaB8a50QbQkSWN243/Lgpd8GTMQvuQ==",
-      "requires": {
-        "@interactjs/core": "1.10.17",
-        "@interactjs/types": "1.10.17",
-        "@interactjs/utils": "1.10.17"
-      }
-    },
-    "@interactjs/interactjs": {
-      "version": "1.10.17",
-      "resolved": "https://registry.npmmirror.com/@interactjs/interactjs/-/interactjs-1.10.17.tgz",
-      "integrity": "sha512-hHmiukARbZhiM12zNKx0yQlFVl4C+NMeYNAYh6Mf9U3ZziQ47C+JEW8Gr7Zr/MxfNZyPu5nLKCpVQjh/JvBO9g==",
-      "requires": {
-        "@interactjs/actions": "1.10.17",
-        "@interactjs/auto-scroll": "1.10.17",
-        "@interactjs/auto-start": "1.10.17",
-        "@interactjs/core": "1.10.17",
-        "@interactjs/dev-tools": "1.10.17",
-        "@interactjs/inertia": "1.10.17",
-        "@interactjs/interact": "1.10.17",
-        "@interactjs/modifiers": "1.10.17",
-        "@interactjs/offset": "1.10.17",
-        "@interactjs/pointer-events": "1.10.17",
-        "@interactjs/reflow": "1.10.17",
-        "@interactjs/utils": "1.10.17"
-      }
-    },
-    "@interactjs/modifiers": {
-      "version": "1.10.17",
-      "resolved": "https://registry.npmmirror.com/@interactjs/modifiers/-/modifiers-1.10.17.tgz",
-      "integrity": "sha512-Dxw8kv9VBIxnhNvQncR6CKAGMzKXczLvuAUIdSPFYtyerX/XiDulJUqhR+jVKNp/WjF1DvdBxWo0kGGLbM84LQ==",
-      "requires": {
-        "@interactjs/interact": "1.10.17",
-        "@interactjs/snappers": "1.10.17"
-      }
-    },
-    "@interactjs/offset": {
-      "version": "1.10.17",
-      "resolved": "https://registry.npmmirror.com/@interactjs/offset/-/offset-1.10.17.tgz",
-      "integrity": "sha512-wWBnIQWgLrmJNTBbd/FdxHxAJjiXl/5ND8Jbw2DuP9gIGDxhFSdEt62Fgqimn9ICb8v8ycvSLObEmcvJF/8hQQ==",
-      "requires": {
-        "@interactjs/interact": "1.10.17"
-      }
-    },
-    "@interactjs/pointer-events": {
-      "version": "1.10.17",
-      "resolved": "https://registry.npmmirror.com/@interactjs/pointer-events/-/pointer-events-1.10.17.tgz",
-      "integrity": "sha512-VsfluouEKb8QRGyH6jQATCW+QdAd/3dkENS7rj2m+EcVUhz2Ob5mpMRopjALi4pwltMowqTfuJ4LtwMSX2G29A==",
-      "requires": {
-        "@interactjs/interact": "1.10.17"
-      }
-    },
-    "@interactjs/reflow": {
-      "version": "1.10.17",
-      "resolved": "https://registry.npmmirror.com/@interactjs/reflow/-/reflow-1.10.17.tgz",
-      "integrity": "sha512-ncpWP5k93FRQptEhjzPZsbuRRajd4rkW17lDavCrEjrDi/LHnYekWGqZTaFzfJ80n1x8xUm9ujDjxCTylNqEIA==",
-      "requires": {
-        "@interactjs/interact": "1.10.17"
-      }
-    },
-    "@interactjs/snappers": {
-      "version": "1.10.17",
-      "resolved": "https://registry.npmmirror.com/@interactjs/snappers/-/snappers-1.10.17.tgz",
-      "integrity": "sha512-m753DGsNOts797e3zDT6wqELoc+BlpIC1w+TyMyISRxU6n1RlS8Q6LHBGgwAgV79LHLaahv/a5haFF9H1VG0FQ==",
-      "requires": {
-        "@interactjs/interact": "1.10.17"
-      }
-    },
-    "@interactjs/types": {
-      "version": "1.10.17",
-      "resolved": "https://registry.npmmirror.com/@interactjs/types/-/types-1.10.17.tgz",
-      "integrity": "sha512-X2JpoM7xUw0p9Me0tMaI0HNfcF/Hd07ZZlzpnpEMpGerUZOLoyeThrV9P+CrBHxZrluWJrigJbcdqXliFd0YMA=="
-    },
-    "@interactjs/utils": {
-      "version": "1.10.17",
-      "resolved": "https://registry.npmmirror.com/@interactjs/utils/-/utils-1.10.17.tgz",
-      "integrity": "sha512-sZAW08CkqgvqRjUIaLRjScjObcCzN9D75yekLA21EClYAZIhi4A+GEt2z/WqOCOksTaEPLYmQyhkpXcboc0LhQ=="
-    },
-    "@intlify/core-base": {
-      "version": "9.1.10",
-      "resolved": "https://registry.npmmirror.com/@intlify/core-base/-/core-base-9.1.10.tgz",
-      "integrity": "sha512-So9CNUavB/IsZ+zBmk2Cv6McQp6vc2wbGi1S0XQmJ8Vz+UFcNn9MFXAe9gY67PreIHrbLsLxDD0cwo1qsxM1Nw==",
-      "requires": {
-        "@intlify/devtools-if": "9.1.10",
-        "@intlify/message-compiler": "9.1.10",
-        "@intlify/message-resolver": "9.1.10",
-        "@intlify/runtime": "9.1.10",
-        "@intlify/shared": "9.1.10",
-        "@intlify/vue-devtools": "9.1.10"
-      }
-    },
-    "@intlify/devtools-if": {
-      "version": "9.1.10",
-      "resolved": "https://registry.npmmirror.com/@intlify/devtools-if/-/devtools-if-9.1.10.tgz",
-      "integrity": "sha512-SHaKoYu6sog3+Q8js1y3oXLywuogbH1sKuc7NSYkN3GElvXSBaMoCzW+we0ZSFqj/6c7vTNLg9nQ6rxhKqYwnQ==",
-      "requires": {
-        "@intlify/shared": "9.1.10"
-      }
-    },
-    "@intlify/message-compiler": {
-      "version": "9.1.10",
-      "resolved": "https://registry.npmmirror.com/@intlify/message-compiler/-/message-compiler-9.1.10.tgz",
-      "integrity": "sha512-+JiJpXff/XTb0EadYwdxOyRTB0hXNd4n1HaJ/a4yuV960uRmPXaklJsedW0LNdcptd/hYUZtCkI7Lc9J5C1gxg==",
-      "requires": {
-        "@intlify/message-resolver": "9.1.10",
-        "@intlify/shared": "9.1.10",
-        "source-map": "0.6.1"
-      }
-    },
-    "@intlify/message-resolver": {
-      "version": "9.1.10",
-      "resolved": "https://registry.npmmirror.com/@intlify/message-resolver/-/message-resolver-9.1.10.tgz",
-      "integrity": "sha512-5YixMG/M05m0cn9+gOzd4EZQTFRUu8RGhzxJbR1DWN21x/Z3bJ8QpDYj6hC4FwBj5uKsRfKpJQ3Xqg98KWoA+w=="
-    },
-    "@intlify/runtime": {
-      "version": "9.1.10",
-      "resolved": "https://registry.npmmirror.com/@intlify/runtime/-/runtime-9.1.10.tgz",
-      "integrity": "sha512-7QsuByNzpe3Gfmhwq6hzgXcMPpxz8Zxb/XFI6s9lQdPLPe5Lgw4U1ovRPZTOs6Y2hwitR3j/HD8BJNGWpJnOFA==",
-      "requires": {
-        "@intlify/message-compiler": "9.1.10",
-        "@intlify/message-resolver": "9.1.10",
-        "@intlify/shared": "9.1.10"
-      }
-    },
-    "@intlify/shared": {
-      "version": "9.1.10",
-      "resolved": "https://registry.npmmirror.com/@intlify/shared/-/shared-9.1.10.tgz",
-      "integrity": "sha512-Om54xJeo1Vw+K1+wHYyXngE8cAbrxZHpWjYzMR9wCkqbhGtRV5VLhVc214Ze2YatPrWlS2WSMOWXR8JktX/IgA=="
-    },
-    "@intlify/vue-devtools": {
-      "version": "9.1.10",
-      "resolved": "https://registry.npmmirror.com/@intlify/vue-devtools/-/vue-devtools-9.1.10.tgz",
-      "integrity": "sha512-5l3qYARVbkWAkagLu1XbDUWRJSL8br1Dj60wgMaKB0+HswVsrR6LloYZTg7ozyvM621V6+zsmwzbQxbVQyrytQ==",
-      "requires": {
-        "@intlify/message-resolver": "9.1.10",
-        "@intlify/runtime": "9.1.10",
-        "@intlify/shared": "9.1.10"
-      }
-    },
-    "@lezer/common": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.0.1.tgz",
-      "integrity": "sha512-8TR5++Q/F//tpDsLd5zkrvEX5xxeemafEaek7mUp7Y+bI8cKQXdSqhzTOBaOogETcMOVr0pT3BBPXp13477ciw=="
-    },
-    "@lezer/highlight": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.0.0.tgz",
-      "integrity": "sha512-nsCnNtim90UKsB5YxoX65v3GEIw3iCHw9RM2DtdgkiqAbKh9pCdvi8AWNwkYf10Lu6fxNhXPpkpHbW6mihhvJA==",
-      "requires": {
-        "@lezer/common": "^1.0.0"
-      }
-    },
-    "@lezer/lr": {
-      "version": "1.2.3",
-      "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.2.3.tgz",
-      "integrity": "sha512-qpB7rBzH8f6Mzjv2AVZRahcm+2Cf7nbIH++uXbvVOL1yIRvVWQ3HAM/saeBLCyz/togB7LGo76qdJYL1uKQlqA==",
-      "requires": {
-        "@lezer/common": "^1.0.0"
-      }
-    },
-    "@nodelib/fs.scandir": {
-      "version": "2.1.5",
-      "resolved": "https://registry.npmmirror.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
-      "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
-      "dev": true,
-      "requires": {
-        "@nodelib/fs.stat": "2.0.5",
-        "run-parallel": "^1.1.9"
-      }
-    },
-    "@nodelib/fs.stat": {
-      "version": "2.0.5",
-      "resolved": "https://registry.npmmirror.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
-      "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
-      "dev": true
-    },
-    "@nodelib/fs.walk": {
-      "version": "1.2.8",
-      "resolved": "https://registry.npmmirror.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
-      "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
-      "dev": true,
-      "requires": {
-        "@nodelib/fs.scandir": "2.1.5",
-        "fastq": "^1.6.0"
-      }
-    },
-    "@types/d3-timer": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-2.0.1.tgz",
-      "integrity": "sha512-TF8aoF5cHcLO7W7403blM7L1T+6NF3XMyN3fxyUolq2uOcFeicG/khQg/dGxiCJWoAcmYulYN7LYSRKO54IXaA=="
-    },
-    "@types/json-schema": {
-      "version": "7.0.11",
-      "resolved": "https://registry.npmmirror.com/@types/json-schema/-/json-schema-7.0.11.tgz",
-      "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==",
-      "dev": true
-    },
-    "@types/lodash": {
-      "version": "4.14.200",
-      "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.200.tgz",
-      "integrity": "sha512-YI/M/4HRImtNf3pJgbF+W6FrXovqj+T+/HpENLTooK9PnkacBsDpeP3IpHab40CClUfhNmdM2WTNP2sa2dni5Q=="
-    },
-    "@types/lodash-es": {
-      "version": "4.17.10",
-      "resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.10.tgz",
-      "integrity": "sha512-YJP+w/2khSBwbUSFdGsSqmDvmnN3cCKoPOL7Zjle6s30ZtemkkqhjVfFqGwPN7ASil5VyjE2GtyU/yqYY6mC0A==",
-      "requires": {
-        "@types/lodash": "*"
-      }
-    },
-    "@types/node": {
-      "version": "17.0.45",
-      "resolved": "https://registry.npmmirror.com/@types/node/-/node-17.0.45.tgz",
-      "integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==",
-      "dev": true
-    },
-    "@types/nprogress": {
-      "version": "0.2.0",
-      "resolved": "https://registry.npmmirror.com/@types/nprogress/-/nprogress-0.2.0.tgz",
-      "integrity": "sha512-1cYJrqq9GezNFPsWTZpFut/d4CjpZqA0vhqDUPFWYKF1oIyBz5qnoYMzR+0C/T96t3ebLAC1SSnwrVOm5/j74A==",
-      "dev": true
-    },
-    "@types/sortablejs": {
-      "version": "1.13.0",
-      "resolved": "https://registry.npmmirror.com/@types/sortablejs/-/sortablejs-1.13.0.tgz",
-      "integrity": "sha512-C3064MH72iEfeGCYEGCt7FCxXoAXaMPG0QPnstcxvPmbl54erpISu06d++FY37Smja64iWy5L8wOyHHBghWbJQ==",
-      "dev": true
-    },
-    "@types/web-bluetooth": {
-      "version": "0.0.16",
-      "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz",
-      "integrity": "sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ=="
-    },
-    "@typescript-eslint/eslint-plugin": {
-      "version": "5.33.0",
-      "resolved": "https://registry.npmmirror.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.33.0.tgz",
-      "integrity": "sha512-jHvZNSW2WZ31OPJ3enhLrEKvAZNyAFWZ6rx9tUwaessTc4sx9KmgMNhVcqVAl1ETnT5rU5fpXTLmY9YvC1DCNg==",
-      "dev": true,
-      "requires": {
-        "@typescript-eslint/scope-manager": "5.33.0",
-        "@typescript-eslint/type-utils": "5.33.0",
-        "@typescript-eslint/utils": "5.33.0",
-        "debug": "^4.3.4",
-        "functional-red-black-tree": "^1.0.1",
-        "ignore": "^5.2.0",
-        "regexpp": "^3.2.0",
-        "semver": "^7.3.7",
-        "tsutils": "^3.21.0"
-      }
-    },
-    "@typescript-eslint/parser": {
-      "version": "5.33.0",
-      "resolved": "https://registry.npmmirror.com/@typescript-eslint/parser/-/parser-5.33.0.tgz",
-      "integrity": "sha512-cgM5cJrWmrDV2KpvlcSkelTBASAs1mgqq+IUGKJvFxWrapHpaRy5EXPQz9YaKF3nZ8KY18ILTiVpUtbIac86/w==",
-      "dev": true,
-      "requires": {
-        "@typescript-eslint/scope-manager": "5.33.0",
-        "@typescript-eslint/types": "5.33.0",
-        "@typescript-eslint/typescript-estree": "5.33.0",
-        "debug": "^4.3.4"
-      }
-    },
-    "@typescript-eslint/scope-manager": {
-      "version": "5.33.0",
-      "resolved": "https://registry.npmmirror.com/@typescript-eslint/scope-manager/-/scope-manager-5.33.0.tgz",
-      "integrity": "sha512-/Jta8yMNpXYpRDl8EwF/M8It2A9sFJTubDo0ATZefGXmOqlaBffEw0ZbkbQ7TNDK6q55NPHFshGBPAZvZkE8Pw==",
-      "dev": true,
-      "requires": {
-        "@typescript-eslint/types": "5.33.0",
-        "@typescript-eslint/visitor-keys": "5.33.0"
-      }
-    },
-    "@typescript-eslint/type-utils": {
-      "version": "5.33.0",
-      "resolved": "https://registry.npmmirror.com/@typescript-eslint/type-utils/-/type-utils-5.33.0.tgz",
-      "integrity": "sha512-2zB8uEn7hEH2pBeyk3NpzX1p3lF9dKrEbnXq1F7YkpZ6hlyqb2yZujqgRGqXgRBTHWIUG3NGx/WeZk224UKlIA==",
-      "dev": true,
-      "requires": {
-        "@typescript-eslint/utils": "5.33.0",
-        "debug": "^4.3.4",
-        "tsutils": "^3.21.0"
-      }
-    },
-    "@typescript-eslint/types": {
-      "version": "5.33.0",
-      "resolved": "https://registry.npmmirror.com/@typescript-eslint/types/-/types-5.33.0.tgz",
-      "integrity": "sha512-nIMt96JngB4MYFYXpZ/3ZNU4GWPNdBbcB5w2rDOCpXOVUkhtNlG2mmm8uXhubhidRZdwMaMBap7Uk8SZMU/ppw==",
-      "dev": true
-    },
-    "@typescript-eslint/typescript-estree": {
-      "version": "5.33.0",
-      "resolved": "https://registry.npmmirror.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.33.0.tgz",
-      "integrity": "sha512-tqq3MRLlggkJKJUrzM6wltk8NckKyyorCSGMq4eVkyL5sDYzJJcMgZATqmF8fLdsWrW7OjjIZ1m9v81vKcaqwQ==",
-      "dev": true,
-      "requires": {
-        "@typescript-eslint/types": "5.33.0",
-        "@typescript-eslint/visitor-keys": "5.33.0",
-        "debug": "^4.3.4",
-        "globby": "^11.1.0",
-        "is-glob": "^4.0.3",
-        "semver": "^7.3.7",
-        "tsutils": "^3.21.0"
-      }
-    },
-    "@typescript-eslint/utils": {
-      "version": "5.33.0",
-      "resolved": "https://registry.npmmirror.com/@typescript-eslint/utils/-/utils-5.33.0.tgz",
-      "integrity": "sha512-JxOAnXt9oZjXLIiXb5ZIcZXiwVHCkqZgof0O8KPgz7C7y0HS42gi75PdPlqh1Tf109M0fyUw45Ao6JLo7S5AHw==",
-      "dev": true,
-      "requires": {
-        "@types/json-schema": "^7.0.9",
-        "@typescript-eslint/scope-manager": "5.33.0",
-        "@typescript-eslint/types": "5.33.0",
-        "@typescript-eslint/typescript-estree": "5.33.0",
-        "eslint-scope": "^5.1.1",
-        "eslint-utils": "^3.0.0"
-      }
-    },
-    "@typescript-eslint/visitor-keys": {
-      "version": "5.33.0",
-      "resolved": "https://registry.npmmirror.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.33.0.tgz",
-      "integrity": "sha512-/XsqCzD4t+Y9p5wd9HZiptuGKBlaZO5showwqODii5C0nZawxWLF+Q6k5wYHBrQv96h6GYKyqqMHCSTqta8Kiw==",
-      "dev": true,
-      "requires": {
-        "@typescript-eslint/types": "5.33.0",
-        "eslint-visitor-keys": "^3.3.0"
-      }
-    },
-    "@vitejs/plugin-vue": {
-      "version": "2.3.4",
-      "resolved": "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-2.3.4.tgz",
-      "integrity": "sha512-IfFNbtkbIm36O9KB8QodlwwYvTEsJb4Lll4c2IwB3VHc2gie2mSPtSzL0eYay7X2jd/2WX02FjSGTWR6OPr/zg==",
-      "dev": true
-    },
-    "@vue/compiler-core": {
-      "version": "3.2.37",
-      "resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.2.37.tgz",
-      "integrity": "sha512-81KhEjo7YAOh0vQJoSmAD68wLfYqJvoiD4ulyedzF+OEk/bk6/hx3fTNVfuzugIIaTrOx4PGx6pAiBRe5e9Zmg==",
-      "requires": {
-        "@babel/parser": "^7.16.4",
-        "@vue/shared": "3.2.37",
-        "estree-walker": "^2.0.2",
-        "source-map": "^0.6.1"
-      }
-    },
-    "@vue/compiler-dom": {
-      "version": "3.2.37",
-      "resolved": "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.2.37.tgz",
-      "integrity": "sha512-yxJLH167fucHKxaqXpYk7x8z7mMEnXOw3G2q62FTkmsvNxu4FQSu5+3UMb+L7fjKa26DEzhrmCxAgFLLIzVfqQ==",
-      "requires": {
-        "@vue/compiler-core": "3.2.37",
-        "@vue/shared": "3.2.37"
-      }
-    },
-    "@vue/compiler-sfc": {
-      "version": "3.2.37",
-      "resolved": "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.2.37.tgz",
-      "integrity": "sha512-+7i/2+9LYlpqDv+KTtWhOZH+pa8/HnX/905MdVmAcI/mPQOBwkHHIzrsEsucyOIZQYMkXUiTkmZq5am/NyXKkg==",
-      "requires": {
-        "@babel/parser": "^7.16.4",
-        "@vue/compiler-core": "3.2.37",
-        "@vue/compiler-dom": "3.2.37",
-        "@vue/compiler-ssr": "3.2.37",
-        "@vue/reactivity-transform": "3.2.37",
-        "@vue/shared": "3.2.37",
-        "estree-walker": "^2.0.2",
-        "magic-string": "^0.25.7",
-        "postcss": "^8.1.10",
-        "source-map": "^0.6.1"
-      }
-    },
-    "@vue/compiler-ssr": {
-      "version": "3.2.37",
-      "resolved": "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.2.37.tgz",
-      "integrity": "sha512-7mQJD7HdXxQjktmsWp/J67lThEIcxLemz1Vb5I6rYJHR5vI+lON3nPGOH3ubmbvYGt8xEUaAr1j7/tIFWiEOqw==",
-      "requires": {
-        "@vue/compiler-dom": "3.2.37",
-        "@vue/shared": "3.2.37"
-      }
-    },
-    "@vue/devtools-api": {
-      "version": "6.2.1",
-      "resolved": "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-6.2.1.tgz",
-      "integrity": "sha512-OEgAMeQXvCoJ+1x8WyQuVZzFo0wcyCmUR3baRVLmKBo1LmYZWMlRiXlux5jd0fqVJu6PfDbOrZItVqUEzLobeQ=="
-    },
-    "@vue/reactivity": {
-      "version": "3.2.37",
-      "resolved": "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.2.37.tgz",
-      "integrity": "sha512-/7WRafBOshOc6m3F7plwzPeCu/RCVv9uMpOwa/5PiY1Zz+WLVRWiy0MYKwmg19KBdGtFWsmZ4cD+LOdVPcs52A==",
-      "requires": {
-        "@vue/shared": "3.2.37"
-      }
-    },
-    "@vue/reactivity-transform": {
-      "version": "3.2.37",
-      "resolved": "https://registry.npmmirror.com/@vue/reactivity-transform/-/reactivity-transform-3.2.37.tgz",
-      "integrity": "sha512-IWopkKEb+8qpu/1eMKVeXrK0NLw9HicGviJzhJDEyfxTR9e1WtpnnbYkJWurX6WwoFP0sz10xQg8yL8lgskAZg==",
-      "requires": {
-        "@babel/parser": "^7.16.4",
-        "@vue/compiler-core": "3.2.37",
-        "@vue/shared": "3.2.37",
-        "estree-walker": "^2.0.2",
-        "magic-string": "^0.25.7"
-      }
-    },
-    "@vue/runtime-core": {
-      "version": "3.2.37",
-      "resolved": "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.2.37.tgz",
-      "integrity": "sha512-JPcd9kFyEdXLl/i0ClS7lwgcs0QpUAWj+SKX2ZC3ANKi1U4DOtiEr6cRqFXsPwY5u1L9fAjkinIdB8Rz3FoYNQ==",
-      "requires": {
-        "@vue/reactivity": "3.2.37",
-        "@vue/shared": "3.2.37"
-      }
-    },
-    "@vue/runtime-dom": {
-      "version": "3.2.37",
-      "resolved": "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.2.37.tgz",
-      "integrity": "sha512-HimKdh9BepShW6YozwRKAYjYQWg9mQn63RGEiSswMbW+ssIht1MILYlVGkAGGQbkhSh31PCdoUcfiu4apXJoPw==",
-      "requires": {
-        "@vue/runtime-core": "3.2.37",
-        "@vue/shared": "3.2.37",
-        "csstype": "^2.6.8"
-      },
-      "dependencies": {
-        "csstype": {
-          "version": "2.6.20",
-          "resolved": "https://registry.npmmirror.com/csstype/-/csstype-2.6.20.tgz",
-          "integrity": "sha512-/WwNkdXfckNgw6S5R125rrW8ez139lBHWouiBvX8dfMFtcn6V81REDqnH7+CRpRipfYlyU1CmOnOxrmGcFOjeA=="
-        }
-      }
-    },
-    "@vue/server-renderer": {
-      "version": "3.2.37",
-      "resolved": "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.2.37.tgz",
-      "integrity": "sha512-kLITEJvaYgZQ2h47hIzPh2K3jG8c1zCVbp/o/bzQOyvzaKiCquKS7AaioPI28GNxIsE/zSx+EwWYsNxDCX95MA==",
-      "requires": {
-        "@vue/compiler-ssr": "3.2.37",
-        "@vue/shared": "3.2.37"
-      }
-    },
-    "@vue/shared": {
-      "version": "3.2.37",
-      "resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.2.37.tgz",
-      "integrity": "sha512-4rSJemR2NQIo9Klm1vabqWjD8rs/ZaJSzMxkMNeJS6lHiUjjUeYFbooN19NgFjztubEKh3WlZUeOLVdbbUWHsw=="
-    },
-    "@vueuse/core": {
-      "version": "9.13.0",
-      "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-9.13.0.tgz",
-      "integrity": "sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==",
-      "requires": {
-        "@types/web-bluetooth": "^0.0.16",
-        "@vueuse/metadata": "9.13.0",
-        "@vueuse/shared": "9.13.0",
-        "vue-demi": "*"
-      }
-    },
-    "@vueuse/metadata": {
-      "version": "9.13.0",
-      "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-9.13.0.tgz",
-      "integrity": "sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ=="
-    },
-    "@vueuse/shared": {
-      "version": "9.13.0",
-      "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-9.13.0.tgz",
-      "integrity": "sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==",
-      "requires": {
-        "vue-demi": "*"
-      }
-    },
-    "acorn": {
-      "version": "8.8.0",
-      "resolved": "https://registry.npmmirror.com/acorn/-/acorn-8.8.0.tgz",
-      "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==",
-      "dev": true
-    },
-    "acorn-jsx": {
-      "version": "5.3.2",
-      "resolved": "https://registry.npmmirror.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
-      "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
-      "dev": true
-    },
-    "adler-32": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmmirror.com/adler-32/-/adler-32-1.2.0.tgz",
-      "integrity": "sha512-/vUqU/UY4MVeFsg+SsK6c+/05RZXIHZMGJA+PX5JyWI0ZRcBpupnRuPLU/NXXoFwMYCPCoxIfElM2eS+DUXCqQ==",
-      "requires": {
-        "exit-on-epipe": "~1.0.1",
-        "printj": "~1.1.0"
-      }
-    },
-    "ajv": {
-      "version": "6.12.6",
-      "resolved": "https://registry.npmmirror.com/ajv/-/ajv-6.12.6.tgz",
-      "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
-      "dev": true,
-      "requires": {
-        "fast-deep-equal": "^3.1.1",
-        "fast-json-stable-stringify": "^2.0.0",
-        "json-schema-traverse": "^0.4.1",
-        "uri-js": "^4.2.2"
-      }
-    },
-    "align-text": {
-      "version": "0.1.4",
-      "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz",
-      "integrity": "sha512-GrTZLRpmp6wIC2ztrWW9MjjTgSKccffgFagbNDOX95/dcjEcYZibYTeaOntySQLcdw1ztBoFkviiUvTMbb9MYg==",
-      "requires": {
-        "kind-of": "^3.0.2",
-        "longest": "^1.0.1",
-        "repeat-string": "^1.5.2"
-      }
-    },
-    "amdefine": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
-      "integrity": "sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg=="
-    },
-    "ansi-regex": {
-      "version": "5.0.1",
-      "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz",
-      "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
-      "dev": true
-    },
-    "ansi-styles": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz",
-      "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
-      "dev": true,
-      "requires": {
-        "color-convert": "^2.0.1"
-      }
-    },
-    "anymatch": {
-      "version": "3.1.2",
-      "resolved": "https://registry.npmmirror.com/anymatch/-/anymatch-3.1.2.tgz",
-      "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
-      "dev": true,
-      "requires": {
-        "normalize-path": "^3.0.0",
-        "picomatch": "^2.0.4"
-      }
-    },
-    "argparse": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmmirror.com/argparse/-/argparse-2.0.1.tgz",
-      "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
-      "dev": true
-    },
-    "array-union": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmmirror.com/array-union/-/array-union-2.1.0.tgz",
-      "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
-      "dev": true
-    },
-    "async-validator": {
-      "version": "4.2.5",
-      "resolved": "https://registry.npmjs.org/async-validator/-/async-validator-4.2.5.tgz",
-      "integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg=="
-    },
-    "axios": {
-      "version": "0.26.1",
-      "resolved": "https://registry.npmmirror.com/axios/-/axios-0.26.1.tgz",
-      "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==",
-      "requires": {
-        "follow-redirects": "^1.14.8"
-      }
-    },
-    "balanced-match": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz",
-      "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
-    },
-    "batch-processor": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmmirror.com/batch-processor/-/batch-processor-1.0.0.tgz",
-      "integrity": "sha512-xoLQD8gmmR32MeuBHgH0Tzd5PuSZx71ZsbhVxOCRbgktZEPe4SQy7s9Z50uPp0F/f7iw2XmkHN2xkgbMfckMDA=="
-    },
-    "binary-extensions": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmmirror.com/binary-extensions/-/binary-extensions-2.2.0.tgz",
-      "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
-      "dev": true
-    },
-    "bmaplib.curveline": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmmirror.com/bmaplib.curveline/-/bmaplib.curveline-1.0.0.tgz",
-      "integrity": "sha512-9wcFMVhiYxNPqpvsLDAADn3qDhNzXp2mA6VyHSHg2XOAgSooC7ZiujdFhy0sp+0QYjTfJ/MjmLuNoUg2HHxH4Q=="
-    },
-    "bmaplib.distancetool": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmmirror.com/bmaplib.distancetool/-/bmaplib.distancetool-1.0.2.tgz",
-      "integrity": "sha512-EvxMnQRH6xM036zx5OLPyTg5tMCTbFBuGTTHOtExLy2/T0X6v5Va0YE7c3IPm/a/Eo5V/ynYpOLOLZbRY8ccyA=="
-    },
-    "bmaplib.heatmap": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmmirror.com/bmaplib.heatmap/-/bmaplib.heatmap-1.0.4.tgz",
-      "integrity": "sha512-rmhqUARBpUSJ9jXzUI2j7dIOqnc38bqubkx/8a349U2qtw/ulLUwyzRD535OrA8G7w5cz4aPKm6/rNvUAarg/Q=="
-    },
-    "bmaplib.lushu": {
-      "version": "1.0.7",
-      "resolved": "https://registry.npmmirror.com/bmaplib.lushu/-/bmaplib.lushu-1.0.7.tgz",
-      "integrity": "sha512-LVvgpESPii6xGxyjnQjq8u+ic4NjvhdCPV/RiSS/PGTUdZKeTDS7prSpleJLZH3ES0+oc0gYn8bw0LtPYUSz2w=="
-    },
-    "bmaplib.markerclusterer": {
-      "version": "1.0.13",
-      "resolved": "https://registry.npmmirror.com/bmaplib.markerclusterer/-/bmaplib.markerclusterer-1.0.13.tgz",
-      "integrity": "sha512-VrLyWSiuDEVNi0yUfwOhFQ6z1oEEHS4w36GNu3iASu6p52QIx9uAXMUkuSCHReNR0bj2Cp9SA1dSx5RpojXajQ==",
-      "requires": {
-        "bmaplib.texticonoverlay": "^1.0.2"
-      }
-    },
-    "bmaplib.texticonoverlay": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmmirror.com/bmaplib.texticonoverlay/-/bmaplib.texticonoverlay-1.0.2.tgz",
-      "integrity": "sha512-4ZTWr4ZP3B6qEWput5Tut16CfZgII38YwM3bpyb4gFTQyORlKYryFp9WHWrwZZaHlOyYDAXG9SX0hka43jTADg=="
-    },
-    "boolbase": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmmirror.com/boolbase/-/boolbase-1.0.0.tgz",
-      "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
-      "dev": true
-    },
-    "brace-expansion": {
-      "version": "1.1.11",
-      "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.11.tgz",
-      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
-      "requires": {
-        "balanced-match": "^1.0.0",
-        "concat-map": "0.0.1"
-      }
-    },
-    "braces": {
-      "version": "3.0.2",
-      "resolved": "https://registry.npmmirror.com/braces/-/braces-3.0.2.tgz",
-      "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
-      "dev": true,
-      "requires": {
-        "fill-range": "^7.0.1"
-      }
-    },
-    "call-bind": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
-      "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
-      "requires": {
-        "function-bind": "^1.1.1",
-        "get-intrinsic": "^1.0.2"
-      }
-    },
-    "callsites": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmmirror.com/callsites/-/callsites-3.1.0.tgz",
-      "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
-      "dev": true
-    },
-    "camelcase": {
-      "version": "1.2.1",
-      "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz",
-      "integrity": "sha512-wzLkDa4K/mzI1OSITC+DUyjgIl/ETNHE9QvYgy6J6Jvqyyz4C0Xfd+lQhb19sX2jMpZV4IssUn0VDVmglV+s4g=="
-    },
-    "center-align": {
-      "version": "0.1.3",
-      "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz",
-      "integrity": "sha512-Baz3aNe2gd2LP2qk5U+sDk/m4oSuwSDcBfayTCTBoWpfIGO5XFxPmjILQII4NGiZjD6DoDI6kf7gKaxkf7s3VQ==",
-      "requires": {
-        "align-text": "^0.1.3",
-        "lazy-cache": "^1.0.3"
-      }
-    },
-    "cfb": {
-      "version": "1.2.2",
-      "resolved": "https://registry.npmmirror.com/cfb/-/cfb-1.2.2.tgz",
-      "integrity": "sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==",
-      "requires": {
-        "adler-32": "~1.3.0",
-        "crc-32": "~1.2.0"
-      },
-      "dependencies": {
-        "adler-32": {
-          "version": "1.3.1",
-          "resolved": "https://registry.npmmirror.com/adler-32/-/adler-32-1.3.1.tgz",
-          "integrity": "sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A=="
-        }
-      }
-    },
-    "chalk": {
-      "version": "4.1.2",
-      "resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz",
-      "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
-      "dev": true,
-      "requires": {
-        "ansi-styles": "^4.1.0",
-        "supports-color": "^7.1.0"
-      }
-    },
-    "chokidar": {
-      "version": "3.5.3",
-      "resolved": "https://registry.npmmirror.com/chokidar/-/chokidar-3.5.3.tgz",
-      "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
-      "dev": true,
-      "requires": {
-        "anymatch": "~3.1.2",
-        "braces": "~3.0.2",
-        "fsevents": "~2.3.2",
-        "glob-parent": "~5.1.2",
-        "is-binary-path": "~2.1.0",
-        "is-glob": "~4.0.1",
-        "normalize-path": "~3.0.0",
-        "readdirp": "~3.6.0"
-      }
-    },
-    "claygl": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmmirror.com/claygl/-/claygl-1.3.0.tgz",
-      "integrity": "sha512-+gGtJjT6SSHD2l2yC3MCubW/sCV40tZuSs5opdtn79vFSGUgp/lH139RNEQ6Jy078/L0aV8odCw8RSrUcMfLaQ=="
-    },
-    "clipboard": {
-      "version": "2.0.11",
-      "resolved": "https://registry.npmmirror.com/clipboard/-/clipboard-2.0.11.tgz",
-      "integrity": "sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==",
-      "requires": {
-        "good-listener": "^1.2.2",
-        "select": "^1.1.2",
-        "tiny-emitter": "^2.0.0"
-      }
-    },
-    "cliui": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz",
-      "integrity": "sha512-GIOYRizG+TGoc7Wgc1LiOTLare95R3mzKgoln+Q/lE4ceiYH19gUpl0l0Ffq4lJDEf3FxujMe6IBfOCs7pfqNA==",
-      "requires": {
-        "center-align": "^0.1.1",
-        "right-align": "^0.1.1",
-        "wordwrap": "0.0.2"
-      }
-    },
-    "codemirror": {
-      "version": "5.65.9",
-      "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.65.9.tgz",
-      "integrity": "sha512-19Jox5sAKpusTDgqgKB5dawPpQcY+ipQK7xoEI+MVucEF9qqFaXpeqY1KaoyGBso/wHQoDa4HMMxMjdsS3Zzzw=="
-    },
-    "codepage": {
-      "version": "1.14.0",
-      "resolved": "https://registry.npmmirror.com/codepage/-/codepage-1.14.0.tgz",
-      "integrity": "sha512-iz3zJLhlrg37/gYRWgEPkaFTtzmnEv1h+r7NgZum2lFElYQPi0/5bnmuDfODHxfp0INEfnRqyfyeIJDbb7ahRw==",
-      "requires": {
-        "commander": "~2.14.1",
-        "exit-on-epipe": "~1.0.1"
-      },
-      "dependencies": {
-        "commander": {
-          "version": "2.14.1",
-          "resolved": "https://registry.npmmirror.com/commander/-/commander-2.14.1.tgz",
-          "integrity": "sha512-+YR16o3rK53SmWHU3rEM3tPAh2rwb1yPcQX5irVn7mb0gXbwuCCrnkbV5+PBfETdfg1vui07nM6PCG1zndcjQw=="
-        }
-      }
-    },
-    "color-convert": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz",
-      "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
-      "dev": true,
-      "requires": {
-        "color-name": "~1.1.4"
-      }
-    },
-    "color-name": {
-      "version": "1.1.4",
-      "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz",
-      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
-      "dev": true
-    },
-    "commander": {
-      "version": "2.17.1",
-      "resolved": "https://registry.npmmirror.com/commander/-/commander-2.17.1.tgz",
-      "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg=="
-    },
-    "concat-map": {
-      "version": "0.0.1",
-      "resolved": "https://registry.npmmirror.com/concat-map/-/concat-map-0.0.1.tgz",
-      "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
-    },
-    "contour_plot": {
-      "version": "0.0.1",
-      "resolved": "https://registry.npmjs.org/contour_plot/-/contour_plot-0.0.1.tgz",
-      "integrity": "sha512-Nil2HI76Xux6sVGORvhSS8v66m+/h5CwFkBJDO+U5vWaMdNC0yXNCsGDPbzPhvqOEU5koebhdEvD372LI+IyLw=="
-    },
-    "core-js": {
-      "version": "3.26.1",
-      "resolved": "https://registry.npmmirror.com/core-js/-/core-js-3.26.1.tgz",
-      "integrity": "sha512-21491RRQVzUn0GGM9Z1Jrpr6PNPxPi+Za8OM9q4tksTSnlbXXGKK1nXNg/QvwFYettXvSX6zWKCtHHfjN4puyA=="
-    },
-    "core-js-pure": {
-      "version": "3.24.1",
-      "resolved": "https://registry.npmmirror.com/core-js-pure/-/core-js-pure-3.24.1.tgz",
-      "integrity": "sha512-r1nJk41QLLPyozHUUPmILCEMtMw24NG4oWK6RbsDdjzQgg9ZvrUsPBj1MnG0wXXp1DCDU6j+wUvEmBSrtRbLXg=="
-    },
-    "countup.js": {
-      "version": "2.3.2",
-      "resolved": "https://registry.npmmirror.com/countup.js/-/countup.js-2.3.2.tgz",
-      "integrity": "sha512-dQ7F/CmKGjaO6cDfhtEXwsKVlXIpJ89dFs8PvkaZH9jBVJ2Z8GU4iwG/qP7MgY8qwr+1skbwR6qecWWQLUzB8Q=="
-    },
-    "crc-32": {
-      "version": "1.2.2",
-      "resolved": "https://registry.npmmirror.com/crc-32/-/crc-32-1.2.2.tgz",
-      "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ=="
-    },
-    "cropperjs": {
-      "version": "1.5.12",
-      "resolved": "https://registry.npmmirror.com/cropperjs/-/cropperjs-1.5.12.tgz",
-      "integrity": "sha512-re7UdjE5UnwdrovyhNzZ6gathI4Rs3KGCBSc8HCIjUo5hO42CtzyblmWLj6QWVw7huHyDMfpKxhiO2II77nhDw=="
-    },
-    "cross-spawn": {
-      "version": "7.0.3",
-      "resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.3.tgz",
-      "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
-      "dev": true,
-      "requires": {
-        "path-key": "^3.1.0",
-        "shebang-command": "^2.0.0",
-        "which": "^2.0.1"
-      }
-    },
-    "cssesc": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmmirror.com/cssesc/-/cssesc-3.0.0.tgz",
-      "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
-      "dev": true
-    },
-    "csstype": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmmirror.com/csstype/-/csstype-3.1.0.tgz",
-      "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA=="
-    },
-    "d3-color": {
-      "version": "1.4.1",
-      "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-1.4.1.tgz",
-      "integrity": "sha512-p2sTHSLCJI2QKunbGb7ocOh7DgTAn8IrLx21QRc/BSnodXM4sv6aLQlnfpvehFMLZEfBc6g9pH9SWQccFYfJ9Q=="
-    },
-    "d3-ease": {
-      "version": "1.0.7",
-      "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-1.0.7.tgz",
-      "integrity": "sha512-lx14ZPYkhNx0s/2HX5sLFUI3mbasHjSSpwO/KaaNACweVwxUruKyWVcb293wMv1RqTPZyZ8kSZ2NogUZNcLOFQ=="
-    },
-    "d3-hierarchy": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-2.0.0.tgz",
-      "integrity": "sha512-SwIdqM3HxQX2214EG9GTjgmCc/mbSx4mQBn+DuEETubhOw6/U3fmnji4uCVrmzOydMHSO1nZle5gh6HB/wdOzw=="
-    },
-    "d3-interpolate": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-1.4.0.tgz",
-      "integrity": "sha512-V9znK0zc3jOPV4VD2zZn0sDhZU3WAE2bmlxdIwwQPPzPjvyLkd8B3JUVdS1IDUFDkWZ72c9qnv1GK2ZagTZ8EA==",
-      "requires": {
-        "d3-color": "1"
-      }
-    },
-    "d3-regression": {
-      "version": "1.3.10",
-      "resolved": "https://registry.npmjs.org/d3-regression/-/d3-regression-1.3.10.tgz",
-      "integrity": "sha512-PF8GWEL70cHHWpx2jUQXc68r1pyPHIA+St16muk/XRokETzlegj5LriNKg7o4LR0TySug4nHYPJNNRz/W+/Niw=="
-    },
-    "d3-timer": {
-      "version": "1.0.10",
-      "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-1.0.10.tgz",
-      "integrity": "sha512-B1JDm0XDaQC+uvo4DT79H0XmBskgS3l6Ve+1SBCfxgmtIb1AVrPIoqd+nPSv+loMX8szQ0sVUhGngL7D5QPiXw=="
-    },
-    "dayjs": {
-      "version": "1.11.8",
-      "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.8.tgz",
-      "integrity": "sha512-LcgxzFoWMEPO7ggRv1Y2N31hUf2R0Vj7fuy/m+Bg1K8rr+KAs1AEy4y9jd5DXe8pbHgX+srkHNS7TH6Q6ZhYeQ=="
-    },
-    "debug": {
-      "version": "4.3.4",
-      "resolved": "https://registry.npmmirror.com/debug/-/debug-4.3.4.tgz",
-      "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
-      "dev": true,
-      "requires": {
-        "ms": "2.1.2"
-      }
-    },
-    "decamelize": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
-      "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA=="
-    },
-    "deep-equal": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz",
-      "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==",
-      "requires": {
-        "is-arguments": "^1.0.4",
-        "is-date-object": "^1.0.1",
-        "is-regex": "^1.0.4",
-        "object-is": "^1.0.1",
-        "object-keys": "^1.1.1",
-        "regexp.prototype.flags": "^1.2.0"
-      }
-    },
-    "deep-is": {
-      "version": "0.1.4",
-      "resolved": "https://registry.npmmirror.com/deep-is/-/deep-is-0.1.4.tgz",
-      "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
-      "dev": true
-    },
-    "define-properties": {
-      "version": "1.1.4",
-      "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz",
-      "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==",
-      "requires": {
-        "has-property-descriptors": "^1.0.0",
-        "object-keys": "^1.1.1"
-      }
-    },
-    "defined": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz",
-      "integrity": "sha512-Y2caI5+ZwS5c3RiNDJ6u53VhQHv+hHKwhkI1iHvceKUHw9Df6EK2zRLfjejRgMuCuxK7PfSWIMwWecceVvThjQ=="
-    },
-    "delegate": {
-      "version": "3.2.0",
-      "resolved": "https://registry.npmmirror.com/delegate/-/delegate-3.2.0.tgz",
-      "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw=="
-    },
-    "detect-browser": {
-      "version": "5.3.0",
-      "resolved": "https://registry.npmjs.org/detect-browser/-/detect-browser-5.3.0.tgz",
-      "integrity": "sha512-53rsFbGdwMwlF7qvCt0ypLM5V5/Mbl0szB7GPN8y9NCcbknYOeVVXdrXEq+90IwAfrrzt6Hd+u2E2ntakICU8w=="
-    },
-    "dir-glob": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmmirror.com/dir-glob/-/dir-glob-3.0.1.tgz",
-      "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
-      "dev": true,
-      "requires": {
-        "path-type": "^4.0.0"
-      }
-    },
-    "doctrine": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmmirror.com/doctrine/-/doctrine-3.0.0.tgz",
-      "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
-      "dev": true,
-      "requires": {
-        "esutils": "^2.0.2"
-      }
-    },
-    "dotenv": {
-      "version": "16.0.1",
-      "resolved": "https://registry.npmmirror.com/dotenv/-/dotenv-16.0.1.tgz",
-      "integrity": "sha512-1K6hR6wtk2FviQ4kEiSjFiH5rpzEVi8WW0x96aztHVMhEspNpc4DVOUTEHtEva5VThQ8IaBX1Pe4gSzpVVUsKQ==",
-      "dev": true
-    },
-    "dotignore": {
-      "version": "0.1.2",
-      "resolved": "https://registry.npmjs.org/dotignore/-/dotignore-0.1.2.tgz",
-      "integrity": "sha512-UGGGWfSauusaVJC+8fgV+NVvBXkCTmVv7sk6nojDZZvuOUNGUy0Zk4UpHQD6EDjS0jpBwcACvH4eofvyzBcRDw==",
-      "requires": {
-        "minimatch": "^3.0.4"
-      }
-    },
-    "downloadjs": {
-      "version": "1.4.7",
-      "resolved": "https://registry.npmmirror.com/downloadjs/-/downloadjs-1.4.7.tgz",
-      "integrity": "sha512-LN1gO7+u9xjU5oEScGFKvXhYf7Y/empUIIEAGBs1LzUq/rg5duiDrkuH5A2lQGd5jfMOb9X9usDa2oVXwJ0U/Q=="
-    },
-    "echarts": {
-      "version": "5.3.3",
-      "resolved": "https://registry.npmmirror.com/echarts/-/echarts-5.3.3.tgz",
-      "integrity": "sha512-BRw2serInRwO5SIwRviZ6Xgm5Lb7irgz+sLiFMmy/HOaf4SQ+7oYqxKzRHAKp4xHQ05AuHw1xvoQWJjDQq/FGw==",
-      "requires": {
-        "tslib": "2.3.0",
-        "zrender": "5.3.2"
-      },
-      "dependencies": {
-        "tslib": {
-          "version": "2.3.0",
-          "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.3.0.tgz",
-          "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg=="
-        }
-      }
-    },
-    "echarts-gl": {
-      "version": "2.0.9",
-      "resolved": "https://registry.npmmirror.com/echarts-gl/-/echarts-gl-2.0.9.tgz",
-      "integrity": "sha512-oKeMdkkkpJGWOzjgZUsF41DOh6cMsyrGGXimbjK2l6Xeq/dBQu4ShG2w2Dzrs/1bD27b2pLTGSaUzouY191gzA==",
-      "requires": {
-        "claygl": "^1.2.1",
-        "zrender": "^5.1.1"
-      }
-    },
-    "echarts-wordcloud": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmmirror.com/echarts-wordcloud/-/echarts-wordcloud-2.0.0.tgz",
-      "integrity": "sha512-K7l6pTklqdW7ZWzT/1CS0KhBSINr/cd7c5N1fVMzZMwLQHEwT7x+nivK7g5hkVh7WNcAv4Dn6/ZS5zMKRozC1g=="
-    },
-    "element-plus": {
-      "version": "2.2.28",
-      "resolved": "https://registry.npmjs.org/element-plus/-/element-plus-2.2.28.tgz",
-      "integrity": "sha512-BsxF7iEaBydmRfw1Tt++EO9jRBjbtJr7ZRIrnEwz4J3Cwa1IzHCNCcx3ZwcYTlJq9CYFxv94JnbNr1EbkTou3A==",
-      "requires": {
-        "@ctrl/tinycolor": "^3.4.1",
-        "@element-plus/icons-vue": "^2.0.6",
-        "@floating-ui/dom": "^1.0.1",
-        "@popperjs/core": "npm:@sxzz/popperjs-es@^2.11.7",
-        "@types/lodash": "^4.14.182",
-        "@types/lodash-es": "^4.17.6",
-        "@vueuse/core": "^9.1.0",
-        "async-validator": "^4.2.5",
-        "dayjs": "^1.11.3",
-        "escape-html": "^1.0.3",
-        "lodash": "^4.17.21",
-        "lodash-es": "^4.17.21",
-        "lodash-unified": "^1.0.2",
-        "memoize-one": "^6.0.0",
-        "normalize-wheel-es": "^1.2.0"
-      },
-      "dependencies": {
-        "@popperjs/core": {
-          "version": "npm:@sxzz/popperjs-es@2.11.7",
-          "resolved": "https://registry.npmjs.org/@sxzz/popperjs-es/-/popperjs-es-2.11.7.tgz",
-          "integrity": "sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ=="
-        }
-      }
-    },
-    "element-resize-detector": {
-      "version": "1.2.4",
-      "resolved": "https://registry.npmmirror.com/element-resize-detector/-/element-resize-detector-1.2.4.tgz",
-      "integrity": "sha512-Fl5Ftk6WwXE0wqCgNoseKWndjzZlDCwuPTcoVZfCP9R3EHQF8qUtr3YUPNETegRBOKqQKPW3n4kiIWngGi8tKg==",
-      "requires": {
-        "batch-processor": "1.0.0"
-      }
-    },
-    "es-abstract": {
-      "version": "1.20.3",
-      "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.3.tgz",
-      "integrity": "sha512-AyrnaKVpMzljIdwjzrj+LxGmj8ik2LckwXacHqrJJ/jxz6dDDBcZ7I7nlHM0FvEW8MfbWJwOd+yT2XzYW49Frw==",
-      "requires": {
-        "call-bind": "^1.0.2",
-        "es-to-primitive": "^1.2.1",
-        "function-bind": "^1.1.1",
-        "function.prototype.name": "^1.1.5",
-        "get-intrinsic": "^1.1.3",
-        "get-symbol-description": "^1.0.0",
-        "has": "^1.0.3",
-        "has-property-descriptors": "^1.0.0",
-        "has-symbols": "^1.0.3",
-        "internal-slot": "^1.0.3",
-        "is-callable": "^1.2.6",
-        "is-negative-zero": "^2.0.2",
-        "is-regex": "^1.1.4",
-        "is-shared-array-buffer": "^1.0.2",
-        "is-string": "^1.0.7",
-        "is-weakref": "^1.0.2",
-        "object-inspect": "^1.12.2",
-        "object-keys": "^1.1.1",
-        "object.assign": "^4.1.4",
-        "regexp.prototype.flags": "^1.4.3",
-        "safe-regex-test": "^1.0.0",
-        "string.prototype.trimend": "^1.0.5",
-        "string.prototype.trimstart": "^1.0.5",
-        "unbox-primitive": "^1.0.2"
-      }
-    },
-    "es-to-primitive": {
-      "version": "1.2.1",
-      "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
-      "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
-      "requires": {
-        "is-callable": "^1.1.4",
-        "is-date-object": "^1.0.1",
-        "is-symbol": "^1.0.2"
-      }
-    },
-    "esbuild": {
-      "version": "0.14.54",
-      "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.54.tgz",
-      "integrity": "sha512-Cy9llcy8DvET5uznocPyqL3BFRrFXSVqbgpMJ9Wz8oVjZlh/zUSNbPRbov0VX7VxN2JH1Oa0uNxZ7eLRb62pJA==",
-      "dev": true,
-      "requires": {
-        "@esbuild/linux-loong64": "0.14.54",
-        "esbuild-android-64": "0.14.54",
-        "esbuild-android-arm64": "0.14.54",
-        "esbuild-darwin-64": "0.14.54",
-        "esbuild-darwin-arm64": "0.14.54",
-        "esbuild-freebsd-64": "0.14.54",
-        "esbuild-freebsd-arm64": "0.14.54",
-        "esbuild-linux-32": "0.14.54",
-        "esbuild-linux-64": "0.14.54",
-        "esbuild-linux-arm": "0.14.54",
-        "esbuild-linux-arm64": "0.14.54",
-        "esbuild-linux-mips64le": "0.14.54",
-        "esbuild-linux-ppc64le": "0.14.54",
-        "esbuild-linux-riscv64": "0.14.54",
-        "esbuild-linux-s390x": "0.14.54",
-        "esbuild-netbsd-64": "0.14.54",
-        "esbuild-openbsd-64": "0.14.54",
-        "esbuild-sunos-64": "0.14.54",
-        "esbuild-windows-32": "0.14.54",
-        "esbuild-windows-64": "0.14.54",
-        "esbuild-windows-arm64": "0.14.54"
-      }
-    },
-    "esbuild-android-64": {
-      "version": "0.14.54",
-      "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.54.tgz",
-      "integrity": "sha512-Tz2++Aqqz0rJ7kYBfz+iqyE3QMycD4vk7LBRyWaAVFgFtQ/O8EJOnVmTOiDWYZ/uYzB4kvP+bqejYdVKzE5lAQ==",
-      "dev": true,
-      "optional": true
-    },
-    "esbuild-android-arm64": {
-      "version": "0.14.54",
-      "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.54.tgz",
-      "integrity": "sha512-F9E+/QDi9sSkLaClO8SOV6etqPd+5DgJje1F9lOWoNncDdOBL2YF59IhsWATSt0TLZbYCf3pNlTHvVV5VfHdvg==",
-      "dev": true,
-      "optional": true
-    },
-    "esbuild-darwin-64": {
-      "version": "0.14.54",
-      "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.54.tgz",
-      "integrity": "sha512-jtdKWV3nBviOd5v4hOpkVmpxsBy90CGzebpbO9beiqUYVMBtSc0AL9zGftFuBon7PNDcdvNCEuQqw2x0wP9yug==",
-      "dev": true,
-      "optional": true
-    },
-    "esbuild-darwin-arm64": {
-      "version": "0.14.54",
-      "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.54.tgz",
-      "integrity": "sha512-OPafJHD2oUPyvJMrsCvDGkRrVCar5aVyHfWGQzY1dWnzErjrDuSETxwA2HSsyg2jORLY8yBfzc1MIpUkXlctmw==",
-      "dev": true,
-      "optional": true
-    },
-    "esbuild-freebsd-64": {
-      "version": "0.14.54",
-      "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.54.tgz",
-      "integrity": "sha512-OKwd4gmwHqOTp4mOGZKe/XUlbDJ4Q9TjX0hMPIDBUWWu/kwhBAudJdBoxnjNf9ocIB6GN6CPowYpR/hRCbSYAg==",
-      "dev": true,
-      "optional": true
-    },
-    "esbuild-freebsd-arm64": {
-      "version": "0.14.54",
-      "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.54.tgz",
-      "integrity": "sha512-sFwueGr7OvIFiQT6WeG0jRLjkjdqWWSrfbVwZp8iMP+8UHEHRBvlaxL6IuKNDwAozNUmbb8nIMXa7oAOARGs1Q==",
-      "dev": true,
-      "optional": true
-    },
-    "esbuild-linux-32": {
-      "version": "0.14.54",
-      "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.54.tgz",
-      "integrity": "sha512-1ZuY+JDI//WmklKlBgJnglpUL1owm2OX+8E1syCD6UAxcMM/XoWd76OHSjl/0MR0LisSAXDqgjT3uJqT67O3qw==",
-      "dev": true,
-      "optional": true
-    },
-    "esbuild-linux-64": {
-      "version": "0.14.54",
-      "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.54.tgz",
-      "integrity": "sha512-EgjAgH5HwTbtNsTqQOXWApBaPVdDn7XcK+/PtJwZLT1UmpLoznPd8c5CxqsH2dQK3j05YsB3L17T8vE7cp4cCg==",
-      "dev": true,
-      "optional": true
-    },
-    "esbuild-linux-arm": {
-      "version": "0.14.54",
-      "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.54.tgz",
-      "integrity": "sha512-qqz/SjemQhVMTnvcLGoLOdFpCYbz4v4fUo+TfsWG+1aOu70/80RV6bgNpR2JCrppV2moUQkww+6bWxXRL9YMGw==",
-      "dev": true,
-      "optional": true
-    },
-    "esbuild-linux-arm64": {
-      "version": "0.14.54",
-      "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.54.tgz",
-      "integrity": "sha512-WL71L+0Rwv+Gv/HTmxTEmpv0UgmxYa5ftZILVi2QmZBgX3q7+tDeOQNqGtdXSdsL8TQi1vIaVFHUPDe0O0kdig==",
-      "dev": true,
-      "optional": true
-    },
-    "esbuild-linux-mips64le": {
-      "version": "0.14.54",
-      "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.54.tgz",
-      "integrity": "sha512-qTHGQB8D1etd0u1+sB6p0ikLKRVuCWhYQhAHRPkO+OF3I/iSlTKNNS0Lh2Oc0g0UFGguaFZZiPJdJey3AGpAlw==",
-      "dev": true,
-      "optional": true
-    },
-    "esbuild-linux-ppc64le": {
-      "version": "0.14.54",
-      "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.54.tgz",
-      "integrity": "sha512-j3OMlzHiqwZBDPRCDFKcx595XVfOfOnv68Ax3U4UKZ3MTYQB5Yz3X1mn5GnodEVYzhtZgxEBidLWeIs8FDSfrQ==",
-      "dev": true,
-      "optional": true
-    },
-    "esbuild-linux-riscv64": {
-      "version": "0.14.54",
-      "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.54.tgz",
-      "integrity": "sha512-y7Vt7Wl9dkOGZjxQZnDAqqn+XOqFD7IMWiewY5SPlNlzMX39ocPQlOaoxvT4FllA5viyV26/QzHtvTjVNOxHZg==",
-      "dev": true,
-      "optional": true
-    },
-    "esbuild-linux-s390x": {
-      "version": "0.14.54",
-      "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.54.tgz",
-      "integrity": "sha512-zaHpW9dziAsi7lRcyV4r8dhfG1qBidQWUXweUjnw+lliChJqQr+6XD71K41oEIC3Mx1KStovEmlzm+MkGZHnHA==",
-      "dev": true,
-      "optional": true
-    },
-    "esbuild-netbsd-64": {
-      "version": "0.14.54",
-      "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.54.tgz",
-      "integrity": "sha512-PR01lmIMnfJTgeU9VJTDY9ZerDWVFIUzAtJuDHwwceppW7cQWjBBqP48NdeRtoP04/AtO9a7w3viI+PIDr6d+w==",
-      "dev": true,
-      "optional": true
-    },
-    "esbuild-openbsd-64": {
-      "version": "0.14.54",
-      "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.54.tgz",
-      "integrity": "sha512-Qyk7ikT2o7Wu76UsvvDS5q0amJvmRzDyVlL0qf5VLsLchjCa1+IAvd8kTBgUxD7VBUUVgItLkk609ZHUc1oCaw==",
-      "dev": true,
-      "optional": true
-    },
-    "esbuild-sunos-64": {
-      "version": "0.14.54",
-      "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.54.tgz",
-      "integrity": "sha512-28GZ24KmMSeKi5ueWzMcco6EBHStL3B6ubM7M51RmPwXQGLe0teBGJocmWhgwccA1GeFXqxzILIxXpHbl9Q/Kw==",
-      "dev": true,
-      "optional": true
-    },
-    "esbuild-windows-32": {
-      "version": "0.14.54",
-      "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.54.tgz",
-      "integrity": "sha512-T+rdZW19ql9MjS7pixmZYVObd9G7kcaZo+sETqNH4RCkuuYSuv9AGHUVnPoP9hhuE1WM1ZimHz1CIBHBboLU7w==",
-      "dev": true,
-      "optional": true
-    },
-    "esbuild-windows-64": {
-      "version": "0.14.54",
-      "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.54.tgz",
-      "integrity": "sha512-AoHTRBUuYwXtZhjXZbA1pGfTo8cJo3vZIcWGLiUcTNgHpJJMC1rVA44ZereBHMJtotyN71S8Qw0npiCIkW96cQ==",
-      "dev": true,
-      "optional": true
-    },
-    "esbuild-windows-arm64": {
-      "version": "0.14.54",
-      "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.54.tgz",
-      "integrity": "sha512-M0kuUvXhot1zOISQGXwWn6YtS+Y/1RT9WrVIOywZnJHo3jCDyewAc79aKNQWFCQm+xNHVTq9h8dZKvygoXQQRg==",
-      "dev": true,
-      "optional": true
-    },
-    "escape-html": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
-      "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
-    },
-    "escape-string-regexp": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
-      "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
-      "dev": true
-    },
-    "eslint": {
-      "version": "8.22.0",
-      "resolved": "https://registry.npmmirror.com/eslint/-/eslint-8.22.0.tgz",
-      "integrity": "sha512-ci4t0sz6vSRKdmkOGmprBo6fmI4PrphDFMy5JEq/fNS0gQkJM3rLmrqcp8ipMcdobH3KtUP40KniAE9W19S4wA==",
-      "dev": true,
-      "requires": {
-        "@eslint/eslintrc": "^1.3.0",
-        "@humanwhocodes/config-array": "^0.10.4",
-        "@humanwhocodes/gitignore-to-minimatch": "^1.0.2",
-        "ajv": "^6.10.0",
-        "chalk": "^4.0.0",
-        "cross-spawn": "^7.0.2",
-        "debug": "^4.3.2",
-        "doctrine": "^3.0.0",
-        "escape-string-regexp": "^4.0.0",
-        "eslint-scope": "^7.1.1",
-        "eslint-utils": "^3.0.0",
-        "eslint-visitor-keys": "^3.3.0",
-        "espree": "^9.3.3",
-        "esquery": "^1.4.0",
-        "esutils": "^2.0.2",
-        "fast-deep-equal": "^3.1.3",
-        "file-entry-cache": "^6.0.1",
-        "find-up": "^5.0.0",
-        "functional-red-black-tree": "^1.0.1",
-        "glob-parent": "^6.0.1",
-        "globals": "^13.15.0",
-        "globby": "^11.1.0",
-        "grapheme-splitter": "^1.0.4",
-        "ignore": "^5.2.0",
-        "import-fresh": "^3.0.0",
-        "imurmurhash": "^0.1.4",
-        "is-glob": "^4.0.0",
-        "js-yaml": "^4.1.0",
-        "json-stable-stringify-without-jsonify": "^1.0.1",
-        "levn": "^0.4.1",
-        "lodash.merge": "^4.6.2",
-        "minimatch": "^3.1.2",
-        "natural-compare": "^1.4.0",
-        "optionator": "^0.9.1",
-        "regexpp": "^3.2.0",
-        "strip-ansi": "^6.0.1",
-        "strip-json-comments": "^3.1.0",
-        "text-table": "^0.2.0",
-        "v8-compile-cache": "^2.0.3"
-      },
-      "dependencies": {
-        "eslint-scope": {
-          "version": "7.1.1",
-          "resolved": "https://registry.npmmirror.com/eslint-scope/-/eslint-scope-7.1.1.tgz",
-          "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==",
-          "dev": true,
-          "requires": {
-            "esrecurse": "^4.3.0",
-            "estraverse": "^5.2.0"
-          }
-        },
-        "estraverse": {
-          "version": "5.3.0",
-          "resolved": "https://registry.npmmirror.com/estraverse/-/estraverse-5.3.0.tgz",
-          "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
-          "dev": true
-        },
-        "glob-parent": {
-          "version": "6.0.2",
-          "resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-6.0.2.tgz",
-          "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
-          "dev": true,
-          "requires": {
-            "is-glob": "^4.0.3"
-          }
-        }
-      }
-    },
-    "eslint-plugin-vue": {
-      "version": "8.7.1",
-      "resolved": "https://registry.npmmirror.com/eslint-plugin-vue/-/eslint-plugin-vue-8.7.1.tgz",
-      "integrity": "sha512-28sbtm4l4cOzoO1LtzQPxfxhQABararUb1JtqusQqObJpWX2e/gmVyeYVfepizPFne0Q5cILkYGiBoV36L12Wg==",
-      "dev": true,
-      "requires": {
-        "eslint-utils": "^3.0.0",
-        "natural-compare": "^1.4.0",
-        "nth-check": "^2.0.1",
-        "postcss-selector-parser": "^6.0.9",
-        "semver": "^7.3.5",
-        "vue-eslint-parser": "^8.0.1"
-      }
-    },
-    "eslint-scope": {
-      "version": "5.1.1",
-      "resolved": "https://registry.npmmirror.com/eslint-scope/-/eslint-scope-5.1.1.tgz",
-      "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
-      "dev": true,
-      "requires": {
-        "esrecurse": "^4.3.0",
-        "estraverse": "^4.1.1"
-      }
-    },
-    "eslint-utils": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmmirror.com/eslint-utils/-/eslint-utils-3.0.0.tgz",
-      "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==",
-      "dev": true,
-      "requires": {
-        "eslint-visitor-keys": "^2.0.0"
-      },
-      "dependencies": {
-        "eslint-visitor-keys": {
-          "version": "2.1.0",
-          "resolved": "https://registry.npmmirror.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz",
-          "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==",
-          "dev": true
-        }
-      }
-    },
-    "eslint-visitor-keys": {
-      "version": "3.3.0",
-      "resolved": "https://registry.npmmirror.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz",
-      "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==",
-      "dev": true
-    },
-    "espree": {
-      "version": "9.3.3",
-      "resolved": "https://registry.npmmirror.com/espree/-/espree-9.3.3.tgz",
-      "integrity": "sha512-ORs1Rt/uQTqUKjDdGCyrtYxbazf5umATSf/K4qxjmZHORR6HJk+2s/2Pqe+Kk49HHINC/xNIrGfgh8sZcll0ng==",
-      "dev": true,
-      "requires": {
-        "acorn": "^8.8.0",
-        "acorn-jsx": "^5.3.2",
-        "eslint-visitor-keys": "^3.3.0"
-      }
-    },
-    "esquery": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmmirror.com/esquery/-/esquery-1.4.0.tgz",
-      "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==",
-      "dev": true,
-      "requires": {
-        "estraverse": "^5.1.0"
-      },
-      "dependencies": {
-        "estraverse": {
-          "version": "5.3.0",
-          "resolved": "https://registry.npmmirror.com/estraverse/-/estraverse-5.3.0.tgz",
-          "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
-          "dev": true
-        }
-      }
-    },
-    "esrecurse": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmmirror.com/esrecurse/-/esrecurse-4.3.0.tgz",
-      "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
-      "dev": true,
-      "requires": {
-        "estraverse": "^5.2.0"
-      },
-      "dependencies": {
-        "estraverse": {
-          "version": "5.3.0",
-          "resolved": "https://registry.npmmirror.com/estraverse/-/estraverse-5.3.0.tgz",
-          "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
-          "dev": true
-        }
-      }
-    },
-    "estraverse": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmmirror.com/estraverse/-/estraverse-4.3.0.tgz",
-      "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
-      "dev": true
-    },
-    "estree-walker": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmmirror.com/estree-walker/-/estree-walker-2.0.2.tgz",
-      "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
-    },
-    "esutils": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmmirror.com/esutils/-/esutils-2.0.3.tgz",
-      "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
-      "dev": true
-    },
-    "event-source-polyfill": {
-      "version": "1.0.31",
-      "resolved": "https://registry.npmjs.org/event-source-polyfill/-/event-source-polyfill-1.0.31.tgz",
-      "integrity": "sha512-4IJSItgS/41IxN5UVAVuAyczwZF7ZIEsM1XAoUzIHA6A+xzusEZUutdXz2Nr+MQPLxfTiCvqE79/C8HT8fKFvA=="
-    },
-    "exit-on-epipe": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmmirror.com/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz",
-      "integrity": "sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw=="
-    },
-    "fast-deep-equal": {
-      "version": "3.1.3",
-      "resolved": "https://registry.npmmirror.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
-      "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
-      "dev": true
-    },
-    "fast-glob": {
-      "version": "3.2.11",
-      "resolved": "https://registry.npmmirror.com/fast-glob/-/fast-glob-3.2.11.tgz",
-      "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==",
-      "dev": true,
-      "requires": {
-        "@nodelib/fs.stat": "^2.0.2",
-        "@nodelib/fs.walk": "^1.2.3",
-        "glob-parent": "^5.1.2",
-        "merge2": "^1.3.0",
-        "micromatch": "^4.0.4"
-      }
-    },
-    "fast-json-stable-stringify": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmmirror.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
-      "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
-      "dev": true
-    },
-    "fast-levenshtein": {
-      "version": "2.0.6",
-      "resolved": "https://registry.npmmirror.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
-      "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
-      "dev": true
-    },
-    "fastq": {
-      "version": "1.13.0",
-      "resolved": "https://registry.npmmirror.com/fastq/-/fastq-1.13.0.tgz",
-      "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==",
-      "dev": true,
-      "requires": {
-        "reusify": "^1.0.4"
-      }
-    },
-    "fecha": {
-      "version": "4.2.3",
-      "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz",
-      "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw=="
-    },
-    "fflate": {
-      "version": "0.3.11",
-      "resolved": "https://registry.npmmirror.com/fflate/-/fflate-0.3.11.tgz",
-      "integrity": "sha512-Rr5QlUeGN1mbOHlaqcSYMKVpPbgLy0AWT/W0EHxA6NGI12yO1jpoui2zBBvU2G824ltM6Ut8BFgfHSBGfkmS0A=="
-    },
-    "file-entry-cache": {
-      "version": "6.0.1",
-      "resolved": "https://registry.npmmirror.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
-      "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
-      "dev": true,
-      "requires": {
-        "flat-cache": "^3.0.4"
-      }
-    },
-    "fill-range": {
-      "version": "7.0.1",
-      "resolved": "https://registry.npmmirror.com/fill-range/-/fill-range-7.0.1.tgz",
-      "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
-      "dev": true,
-      "requires": {
-        "to-regex-range": "^5.0.1"
-      }
-    },
-    "find-up": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmmirror.com/find-up/-/find-up-5.0.0.tgz",
-      "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
-      "dev": true,
-      "requires": {
-        "locate-path": "^6.0.0",
-        "path-exists": "^4.0.0"
-      }
-    },
-    "flat-cache": {
-      "version": "3.0.4",
-      "resolved": "https://registry.npmmirror.com/flat-cache/-/flat-cache-3.0.4.tgz",
-      "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==",
-      "dev": true,
-      "requires": {
-        "flatted": "^3.1.0",
-        "rimraf": "^3.0.2"
-      }
-    },
-    "flatted": {
-      "version": "3.2.6",
-      "resolved": "https://registry.npmmirror.com/flatted/-/flatted-3.2.6.tgz",
-      "integrity": "sha512-0sQoMh9s0BYsm+12Huy/rkKxVu4R1+r96YX5cG44rHV0pQ6iC3Q+mkoMFaGWObMFYQxCVT+ssG1ksneA2MI9KQ==",
-      "dev": true
-    },
-    "fmin": {
-      "version": "0.0.2",
-      "resolved": "https://registry.npmjs.org/fmin/-/fmin-0.0.2.tgz",
-      "integrity": "sha512-sSi6DzInhl9d8yqssDfGZejChO8d2bAGIpysPsvYsxFe898z89XhCZg6CPNV3nhUhFefeC/AXZK2bAJxlBjN6A==",
-      "requires": {
-        "contour_plot": "^0.0.1",
-        "json2module": "^0.0.3",
-        "rollup": "^0.25.8",
-        "tape": "^4.5.1",
-        "uglify-js": "^2.6.2"
-      },
-      "dependencies": {
-        "ansi-regex": {
-          "version": "2.1.1",
-          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
-          "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA=="
-        },
-        "ansi-styles": {
-          "version": "2.2.1",
-          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
-          "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA=="
-        },
-        "chalk": {
-          "version": "1.1.3",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
-          "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==",
-          "requires": {
-            "ansi-styles": "^2.2.1",
-            "escape-string-regexp": "^1.0.2",
-            "has-ansi": "^2.0.0",
-            "strip-ansi": "^3.0.0",
-            "supports-color": "^2.0.0"
-          }
-        },
-        "escape-string-regexp": {
-          "version": "1.0.5",
-          "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
-          "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="
-        },
-        "rollup": {
-          "version": "0.25.8",
-          "resolved": "https://registry.npmjs.org/rollup/-/rollup-0.25.8.tgz",
-          "integrity": "sha512-a2S4Bh3bgrdO4BhKr2E4nZkjTvrJ2m2bWjMTzVYtoqSCn0HnuxosXnaJUHrMEziOWr3CzL9GjilQQKcyCQpJoA==",
-          "requires": {
-            "chalk": "^1.1.1",
-            "minimist": "^1.2.0",
-            "source-map-support": "^0.3.2"
-          }
-        },
-        "strip-ansi": {
-          "version": "3.0.1",
-          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
-          "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==",
-          "requires": {
-            "ansi-regex": "^2.0.0"
-          }
-        },
-        "supports-color": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
-          "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g=="
-        }
-      }
-    },
-    "follow-redirects": {
-      "version": "1.15.1",
-      "resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.1.tgz",
-      "integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA=="
-    },
-    "for-each": {
-      "version": "0.3.3",
-      "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
-      "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
-      "requires": {
-        "is-callable": "^1.1.3"
-      }
-    },
-    "frac": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmmirror.com/frac/-/frac-1.1.2.tgz",
-      "integrity": "sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA=="
-    },
-    "fs-extra": {
-      "version": "10.1.0",
-      "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
-      "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
-      "dev": true,
-      "requires": {
-        "graceful-fs": "^4.2.0",
-        "jsonfile": "^6.0.1",
-        "universalify": "^2.0.0"
-      }
-    },
-    "fs.realpath": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmmirror.com/fs.realpath/-/fs.realpath-1.0.0.tgz",
-      "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
-    },
-    "fsevents": {
-      "version": "2.3.2",
-      "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.2.tgz",
-      "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
-      "dev": true,
-      "optional": true
-    },
-    "function-bind": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.1.tgz",
-      "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
-    },
-    "function.prototype.name": {
-      "version": "1.1.5",
-      "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz",
-      "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==",
-      "requires": {
-        "call-bind": "^1.0.2",
-        "define-properties": "^1.1.3",
-        "es-abstract": "^1.19.0",
-        "functions-have-names": "^1.2.2"
-      }
-    },
-    "functional-red-black-tree": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmmirror.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
-      "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==",
-      "dev": true
-    },
-    "functions-have-names": {
-      "version": "1.2.3",
-      "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
-      "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ=="
-    },
-    "get-intrinsic": {
-      "version": "1.1.3",
-      "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz",
-      "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==",
-      "requires": {
-        "function-bind": "^1.1.1",
-        "has": "^1.0.3",
-        "has-symbols": "^1.0.3"
-      }
-    },
-    "get-symbol-description": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz",
-      "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==",
-      "requires": {
-        "call-bind": "^1.0.2",
-        "get-intrinsic": "^1.1.1"
-      }
-    },
-    "gl-matrix": {
-      "version": "3.4.3",
-      "resolved": "https://registry.npmjs.org/gl-matrix/-/gl-matrix-3.4.3.tgz",
-      "integrity": "sha512-wcCp8vu8FT22BnvKVPjXa/ICBWRq/zjFfdofZy1WSpQZpphblv12/bOQLBC1rMM7SGOFS9ltVmKOHil5+Ml7gA=="
-    },
-    "glob": {
-      "version": "7.2.3",
-      "resolved": "https://registry.npmmirror.com/glob/-/glob-7.2.3.tgz",
-      "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
-      "requires": {
-        "fs.realpath": "^1.0.0",
-        "inflight": "^1.0.4",
-        "inherits": "2",
-        "minimatch": "^3.1.1",
-        "once": "^1.3.0",
-        "path-is-absolute": "^1.0.0"
-      }
-    },
-    "glob-parent": {
-      "version": "5.1.2",
-      "resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz",
-      "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
-      "dev": true,
-      "requires": {
-        "is-glob": "^4.0.1"
-      }
-    },
-    "globals": {
-      "version": "13.17.0",
-      "resolved": "https://registry.npmmirror.com/globals/-/globals-13.17.0.tgz",
-      "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==",
-      "dev": true,
-      "requires": {
-        "type-fest": "^0.20.2"
-      }
-    },
-    "globby": {
-      "version": "11.1.0",
-      "resolved": "https://registry.npmmirror.com/globby/-/globby-11.1.0.tgz",
-      "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
-      "dev": true,
-      "requires": {
-        "array-union": "^2.1.0",
-        "dir-glob": "^3.0.1",
-        "fast-glob": "^3.2.9",
-        "ignore": "^5.2.0",
-        "merge2": "^1.4.1",
-        "slash": "^3.0.0"
-      }
-    },
-    "good-listener": {
-      "version": "1.2.2",
-      "resolved": "https://registry.npmmirror.com/good-listener/-/good-listener-1.2.2.tgz",
-      "integrity": "sha512-goW1b+d9q/HIwbVYZzZ6SsTr4IgE+WA44A0GmPIQstuOrgsFcT7VEJ48nmr9GaRtNu0XTKacFLGnBPAM6Afouw==",
-      "requires": {
-        "delegate": "^3.1.2"
-      }
-    },
-    "graceful-fs": {
-      "version": "4.2.11",
-      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
-      "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
-      "dev": true
-    },
-    "grapheme-splitter": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmmirror.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz",
-      "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==",
-      "dev": true
-    },
-    "has": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmmirror.com/has/-/has-1.0.3.tgz",
-      "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
-      "requires": {
-        "function-bind": "^1.1.1"
-      }
-    },
-    "has-ansi": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
-      "integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==",
-      "requires": {
-        "ansi-regex": "^2.0.0"
-      },
-      "dependencies": {
-        "ansi-regex": {
-          "version": "2.1.1",
-          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
-          "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA=="
-        }
-      }
-    },
-    "has-bigints": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz",
-      "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ=="
-    },
-    "has-flag": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz",
-      "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
-      "dev": true
-    },
-    "has-property-descriptors": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz",
-      "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==",
-      "requires": {
-        "get-intrinsic": "^1.1.1"
-      }
-    },
-    "has-symbols": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
-      "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A=="
-    },
-    "has-tostringtag": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
-      "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
-      "requires": {
-        "has-symbols": "^1.0.2"
-      }
-    },
-    "ignore": {
-      "version": "5.2.0",
-      "resolved": "https://registry.npmmirror.com/ignore/-/ignore-5.2.0.tgz",
-      "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==",
-      "dev": true
-    },
-    "immutable": {
-      "version": "4.1.0",
-      "resolved": "https://registry.npmmirror.com/immutable/-/immutable-4.1.0.tgz",
-      "integrity": "sha512-oNkuqVTA8jqG1Q6c+UglTOD1xhC1BtjKI7XkCXRkZHrN5m18/XsnUp8Q89GkQO/z+0WjonSvl0FLhDYftp46nQ==",
-      "dev": true
-    },
-    "import-fresh": {
-      "version": "3.3.0",
-      "resolved": "https://registry.npmmirror.com/import-fresh/-/import-fresh-3.3.0.tgz",
-      "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
-      "dev": true,
-      "requires": {
-        "parent-module": "^1.0.0",
-        "resolve-from": "^4.0.0"
-      }
-    },
-    "imurmurhash": {
-      "version": "0.1.4",
-      "resolved": "https://registry.npmmirror.com/imurmurhash/-/imurmurhash-0.1.4.tgz",
-      "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
-      "dev": true
-    },
-    "inflight": {
-      "version": "1.0.6",
-      "resolved": "https://registry.npmmirror.com/inflight/-/inflight-1.0.6.tgz",
-      "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
-      "requires": {
-        "once": "^1.3.0",
-        "wrappy": "1"
-      }
-    },
-    "inherits": {
-      "version": "2.0.4",
-      "resolved": "https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz",
-      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
-    },
-    "internal-slot": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz",
-      "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==",
-      "requires": {
-        "get-intrinsic": "^1.1.0",
-        "has": "^1.0.3",
-        "side-channel": "^1.0.4"
-      }
-    },
-    "is-arguments": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz",
-      "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==",
-      "requires": {
-        "call-bind": "^1.0.2",
-        "has-tostringtag": "^1.0.0"
-      }
-    },
-    "is-bigint": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
-      "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==",
-      "requires": {
-        "has-bigints": "^1.0.1"
-      }
-    },
-    "is-binary-path": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmmirror.com/is-binary-path/-/is-binary-path-2.1.0.tgz",
-      "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
-      "dev": true,
-      "requires": {
-        "binary-extensions": "^2.0.0"
-      }
-    },
-    "is-boolean-object": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
-      "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==",
-      "requires": {
-        "call-bind": "^1.0.2",
-        "has-tostringtag": "^1.0.0"
-      }
-    },
-    "is-buffer": {
-      "version": "1.1.6",
-      "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
-      "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
-    },
-    "is-callable": {
-      "version": "1.2.7",
-      "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
-      "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA=="
-    },
-    "is-core-module": {
-      "version": "2.10.0",
-      "resolved": "https://registry.npmmirror.com/is-core-module/-/is-core-module-2.10.0.tgz",
-      "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==",
-      "requires": {
-        "has": "^1.0.3"
-      }
-    },
-    "is-date-object": {
-      "version": "1.0.5",
-      "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz",
-      "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==",
-      "requires": {
-        "has-tostringtag": "^1.0.0"
-      }
-    },
-    "is-extglob": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz",
-      "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
-      "dev": true
-    },
-    "is-glob": {
-      "version": "4.0.3",
-      "resolved": "https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz",
-      "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
-      "dev": true,
-      "requires": {
-        "is-extglob": "^2.1.1"
-      }
-    },
-    "is-negative-zero": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz",
-      "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA=="
-    },
-    "is-number": {
-      "version": "7.0.0",
-      "resolved": "https://registry.npmmirror.com/is-number/-/is-number-7.0.0.tgz",
-      "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
-      "dev": true
-    },
-    "is-number-object": {
-      "version": "1.0.7",
-      "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz",
-      "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==",
-      "requires": {
-        "has-tostringtag": "^1.0.0"
-      }
-    },
-    "is-regex": {
-      "version": "1.1.4",
-      "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
-      "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
-      "requires": {
-        "call-bind": "^1.0.2",
-        "has-tostringtag": "^1.0.0"
-      }
-    },
-    "is-shared-array-buffer": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz",
-      "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==",
-      "requires": {
-        "call-bind": "^1.0.2"
-      }
-    },
-    "is-string": {
-      "version": "1.0.7",
-      "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz",
-      "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==",
-      "requires": {
-        "has-tostringtag": "^1.0.0"
-      }
-    },
-    "is-symbol": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz",
-      "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
-      "requires": {
-        "has-symbols": "^1.0.2"
-      }
-    },
-    "is-weakref": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz",
-      "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==",
-      "requires": {
-        "call-bind": "^1.0.2"
-      }
-    },
-    "isexe": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmmirror.com/isexe/-/isexe-2.0.0.tgz",
-      "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
-      "dev": true
-    },
-    "js-yaml": {
-      "version": "4.1.0",
-      "resolved": "https://registry.npmmirror.com/js-yaml/-/js-yaml-4.1.0.tgz",
-      "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
-      "dev": true,
-      "requires": {
-        "argparse": "^2.0.1"
-      }
-    },
-    "jsencrypt": {
-      "version": "3.3.2",
-      "resolved": "https://registry.npmjs.org/jsencrypt/-/jsencrypt-3.3.2.tgz",
-      "integrity": "sha512-arQR1R1ESGdAxY7ZheWr12wCaF2yF47v5qpB76TtV64H1pyGudk9Hvw8Y9tb/FiTIaaTRUyaSnm5T/Y53Ghm/A=="
-    },
-    "json-schema-traverse": {
-      "version": "0.4.1",
-      "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
-      "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
-      "dev": true
-    },
-    "json-stable-stringify-without-jsonify": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmmirror.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
-      "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
-      "dev": true
-    },
-    "json2module": {
-      "version": "0.0.3",
-      "resolved": "https://registry.npmjs.org/json2module/-/json2module-0.0.3.tgz",
-      "integrity": "sha512-qYGxqrRrt4GbB8IEOy1jJGypkNsjWoIMlZt4bAsmUScCA507Hbc2p1JOhBzqn45u3PWafUgH2OnzyNU7udO/GA==",
-      "requires": {
-        "rw": "^1.3.2"
-      }
-    },
-    "jsonfile": {
-      "version": "6.1.0",
-      "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
-      "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
-      "dev": true,
-      "requires": {
-        "graceful-fs": "^4.1.6",
-        "universalify": "^2.0.0"
-      }
-    },
-    "jsplumb": {
-      "version": "2.15.6",
-      "resolved": "https://registry.npmmirror.com/jsplumb/-/jsplumb-2.15.6.tgz",
-      "integrity": "sha512-sIpbpz5eMVM+vV+MQzFCidlaa1RsknrQs6LOTKYDjYUDdTAi2AN2bFi94TxB33TifcIsRNV1jebcaxg0tCoPzg=="
-    },
-    "kind-of": {
-      "version": "3.2.2",
-      "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-      "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==",
-      "requires": {
-        "is-buffer": "^1.1.5"
-      }
-    },
-    "klona": {
-      "version": "2.0.5",
-      "resolved": "https://registry.npmmirror.com/klona/-/klona-2.0.5.tgz",
-      "integrity": "sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ==",
-      "dev": true
-    },
-    "lazy-cache": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz",
-      "integrity": "sha512-RE2g0b5VGZsOCFOCgP7omTRYFqydmZkBwl5oNnQ1lDYC57uyO9KqNnNVxT7COSHTxrRCWVcAVOcbjk+tvh/rgQ=="
-    },
-    "levn": {
-      "version": "0.4.1",
-      "resolved": "https://registry.npmmirror.com/levn/-/levn-0.4.1.tgz",
-      "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
-      "dev": true,
-      "requires": {
-        "prelude-ls": "^1.2.1",
-        "type-check": "~0.4.0"
-      }
-    },
-    "locate-path": {
-      "version": "6.0.0",
-      "resolved": "https://registry.npmmirror.com/locate-path/-/locate-path-6.0.0.tgz",
-      "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
-      "dev": true,
-      "requires": {
-        "p-locate": "^5.0.0"
-      }
-    },
-    "lodash": {
-      "version": "4.17.21",
-      "resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz",
-      "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
-    },
-    "lodash-es": {
-      "version": "4.17.21",
-      "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
-      "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
-    },
-    "lodash-unified": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/lodash-unified/-/lodash-unified-1.0.3.tgz",
-      "integrity": "sha512-WK9qSozxXOD7ZJQlpSqOT+om2ZfcT4yO+03FuzAHD0wF6S0l0090LRPDx3vhTTLZ8cFKpBn+IOcVXK6qOcIlfQ=="
-    },
-    "lodash.merge": {
-      "version": "4.6.2",
-      "resolved": "https://registry.npmmirror.com/lodash.merge/-/lodash.merge-4.6.2.tgz",
-      "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
-      "dev": true
-    },
-    "longest": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz",
-      "integrity": "sha512-k+yt5n3l48JU4k8ftnKG6V7u32wyH2NfKzeMto9F/QRE0amxy/LayxwlvjjkZEIzqR+19IrtFO8p5kB9QaYUFg=="
-    },
-    "lru-cache": {
-      "version": "6.0.0",
-      "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-6.0.0.tgz",
-      "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
-      "dev": true,
-      "requires": {
-        "yallist": "^4.0.0"
-      }
-    },
-    "magic-string": {
-      "version": "0.25.9",
-      "resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.25.9.tgz",
-      "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==",
-      "requires": {
-        "sourcemap-codec": "^1.4.8"
-      }
-    },
-    "memoize-one": {
-      "version": "6.0.0",
-      "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz",
-      "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw=="
-    },
-    "merge2": {
-      "version": "1.4.1",
-      "resolved": "https://registry.npmmirror.com/merge2/-/merge2-1.4.1.tgz",
-      "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
-      "dev": true
-    },
-    "micromatch": {
-      "version": "4.0.5",
-      "resolved": "https://registry.npmmirror.com/micromatch/-/micromatch-4.0.5.tgz",
-      "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
-      "dev": true,
-      "requires": {
-        "braces": "^3.0.2",
-        "picomatch": "^2.3.1"
-      }
-    },
-    "minimatch": {
-      "version": "3.1.2",
-      "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.2.tgz",
-      "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
-      "requires": {
-        "brace-expansion": "^1.1.7"
-      }
-    },
-    "minimist": {
-      "version": "1.2.6",
-      "resolved": "https://registry.npmmirror.com/minimist/-/minimist-1.2.6.tgz",
-      "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q=="
-    },
-    "mitt": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmmirror.com/mitt/-/mitt-3.0.0.tgz",
-      "integrity": "sha512-7dX2/10ITVyqh4aOSVI9gdape+t9l2/8QxHrFmUXu4EEUpdlxl6RudZUPZoc+zuY2hk1j7XxVroIVIan/pD/SQ=="
-    },
-    "ms": {
-      "version": "2.1.2",
-      "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.2.tgz",
-      "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
-      "dev": true
-    },
-    "nanoid": {
-      "version": "3.3.4",
-      "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.4.tgz",
-      "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw=="
-    },
-    "natural-compare": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmmirror.com/natural-compare/-/natural-compare-1.4.0.tgz",
-      "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
-      "dev": true
-    },
-    "neo-async": {
-      "version": "2.6.2",
-      "resolved": "https://registry.npmmirror.com/neo-async/-/neo-async-2.6.2.tgz",
-      "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
-      "dev": true
-    },
-    "normalize-path": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmmirror.com/normalize-path/-/normalize-path-3.0.0.tgz",
-      "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
-      "dev": true
-    },
-    "normalize-wheel": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmmirror.com/normalize-wheel/-/normalize-wheel-1.0.1.tgz",
-      "integrity": "sha512-1OnlAPZ3zgrk8B91HyRj+eVv+kS5u+Z0SCsak6Xil/kmgEia50ga7zfkumayonZrImffAxPU/5WcyGhzetHNPA=="
-    },
-    "normalize-wheel-es": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/normalize-wheel-es/-/normalize-wheel-es-1.2.0.tgz",
-      "integrity": "sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw=="
-    },
-    "nprogress": {
-      "version": "0.2.0",
-      "resolved": "https://registry.npmmirror.com/nprogress/-/nprogress-0.2.0.tgz",
-      "integrity": "sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA=="
-    },
-    "nth-check": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmmirror.com/nth-check/-/nth-check-2.1.1.tgz",
-      "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
-      "dev": true,
-      "requires": {
-        "boolbase": "^1.0.0"
-      }
-    },
-    "object-inspect": {
-      "version": "1.12.2",
-      "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz",
-      "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ=="
-    },
-    "object-is": {
-      "version": "1.1.5",
-      "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz",
-      "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==",
-      "requires": {
-        "call-bind": "^1.0.2",
-        "define-properties": "^1.1.3"
-      }
-    },
-    "object-keys": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
-      "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="
-    },
-    "object.assign": {
-      "version": "4.1.4",
-      "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz",
-      "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==",
-      "requires": {
-        "call-bind": "^1.0.2",
-        "define-properties": "^1.1.4",
-        "has-symbols": "^1.0.3",
-        "object-keys": "^1.1.1"
-      }
-    },
-    "once": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmmirror.com/once/-/once-1.4.0.tgz",
-      "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
-      "requires": {
-        "wrappy": "1"
-      }
-    },
-    "optionator": {
-      "version": "0.9.1",
-      "resolved": "https://registry.npmmirror.com/optionator/-/optionator-0.9.1.tgz",
-      "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==",
-      "dev": true,
-      "requires": {
-        "deep-is": "^0.1.3",
-        "fast-levenshtein": "^2.0.6",
-        "levn": "^0.4.1",
-        "prelude-ls": "^1.2.1",
-        "type-check": "^0.4.0",
-        "word-wrap": "^1.2.3"
-      }
-    },
-    "p-limit": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmmirror.com/p-limit/-/p-limit-3.1.0.tgz",
-      "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
-      "dev": true,
-      "requires": {
-        "yocto-queue": "^0.1.0"
-      }
-    },
-    "p-locate": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmmirror.com/p-locate/-/p-locate-5.0.0.tgz",
-      "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
-      "dev": true,
-      "requires": {
-        "p-limit": "^3.0.2"
-      }
-    },
-    "pako": {
-      "version": "1.0.11",
-      "resolved": "https://registry.npmmirror.com/pako/-/pako-1.0.11.tgz",
-      "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw=="
-    },
-    "parent-module": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmmirror.com/parent-module/-/parent-module-1.0.1.tgz",
-      "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
-      "dev": true,
-      "requires": {
-        "callsites": "^3.0.0"
-      }
-    },
-    "path-exists": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmmirror.com/path-exists/-/path-exists-4.0.0.tgz",
-      "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
-      "dev": true
-    },
-    "path-is-absolute": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmmirror.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
-      "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="
-    },
-    "path-key": {
-      "version": "3.1.1",
-      "resolved": "https://registry.npmmirror.com/path-key/-/path-key-3.1.1.tgz",
-      "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
-      "dev": true
-    },
-    "path-parse": {
-      "version": "1.0.7",
-      "resolved": "https://registry.npmmirror.com/path-parse/-/path-parse-1.0.7.tgz",
-      "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
-    },
-    "path-type": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmmirror.com/path-type/-/path-type-4.0.0.tgz",
-      "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
-      "dev": true
-    },
-    "pdfast": {
-      "version": "0.2.0",
-      "resolved": "https://registry.npmjs.org/pdfast/-/pdfast-0.2.0.tgz",
-      "integrity": "sha512-cq6TTu6qKSFUHwEahi68k/kqN2mfepjkGrG9Un70cgdRRKLKY6Rf8P8uvP2NvZktaQZNF3YE7agEkLj0vGK9bA=="
-    },
-    "picocolors": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.0.0.tgz",
-      "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="
-    },
-    "picomatch": {
-      "version": "2.3.1",
-      "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.1.tgz",
-      "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
-      "dev": true
-    },
-    "postcss": {
-      "version": "8.4.16",
-      "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.4.16.tgz",
-      "integrity": "sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==",
-      "requires": {
-        "nanoid": "^3.3.4",
-        "picocolors": "^1.0.0",
-        "source-map-js": "^1.0.2"
-      }
-    },
-    "postcss-selector-parser": {
-      "version": "6.0.10",
-      "resolved": "https://registry.npmmirror.com/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz",
-      "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==",
-      "dev": true,
-      "requires": {
-        "cssesc": "^3.0.0",
-        "util-deprecate": "^1.0.2"
-      }
-    },
-    "prelude-ls": {
-      "version": "1.2.1",
-      "resolved": "https://registry.npmmirror.com/prelude-ls/-/prelude-ls-1.2.1.tgz",
-      "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
-      "dev": true
-    },
-    "prettier": {
-      "version": "2.7.1",
-      "resolved": "https://registry.npmmirror.com/prettier/-/prettier-2.7.1.tgz",
-      "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==",
-      "dev": true
-    },
-    "print-js": {
-      "version": "1.6.0",
-      "resolved": "https://registry.npmmirror.com/print-js/-/print-js-1.6.0.tgz",
-      "integrity": "sha512-BfnOIzSKbqGRtO4o0rnj/K3681BSd2QUrsIZy/+WdCIugjIswjmx3lDEZpXB2ruGf9d4b3YNINri81+J0FsBWg=="
-    },
-    "printj": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmmirror.com/printj/-/printj-1.1.2.tgz",
-      "integrity": "sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ=="
-    },
-    "punycode": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmmirror.com/punycode/-/punycode-2.1.1.tgz",
-      "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
-      "dev": true
-    },
-    "qrcodejs2-fixes": {
-      "version": "0.0.2",
-      "resolved": "https://registry.npmmirror.com/qrcodejs2-fixes/-/qrcodejs2-fixes-0.0.2.tgz",
-      "integrity": "sha512-wMUXYMOixAEJlLnjk5MbLiFaz0gQObWYm/TIFWB5+j7sTY5gPyr09Cx1EpcLYbsgfFdN3wHjrKAhZofTuCBGhg=="
-    },
-    "queue-microtask": {
-      "version": "1.2.3",
-      "resolved": "https://registry.npmmirror.com/queue-microtask/-/queue-microtask-1.2.3.tgz",
-      "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
-      "dev": true
-    },
-    "readdirp": {
-      "version": "3.6.0",
-      "resolved": "https://registry.npmmirror.com/readdirp/-/readdirp-3.6.0.tgz",
-      "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
-      "dev": true,
-      "requires": {
-        "picomatch": "^2.2.1"
-      }
-    },
-    "regenerator-runtime": {
-      "version": "0.13.9",
-      "resolved": "https://registry.npmmirror.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz",
-      "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA=="
-    },
-    "regexp.prototype.flags": {
-      "version": "1.4.3",
-      "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz",
-      "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==",
-      "requires": {
-        "call-bind": "^1.0.2",
-        "define-properties": "^1.1.3",
-        "functions-have-names": "^1.2.2"
-      }
-    },
-    "regexpp": {
-      "version": "3.2.0",
-      "resolved": "https://registry.npmmirror.com/regexpp/-/regexpp-3.2.0.tgz",
-      "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==",
-      "dev": true
-    },
-    "repeat-string": {
-      "version": "1.6.1",
-      "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
-      "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w=="
-    },
-    "resize-observer-polyfill": {
-      "version": "1.5.1",
-      "resolved": "https://registry.npmmirror.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz",
-      "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg=="
-    },
-    "resolve": {
-      "version": "1.22.1",
-      "resolved": "https://registry.npmmirror.com/resolve/-/resolve-1.22.1.tgz",
-      "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==",
-      "requires": {
-        "is-core-module": "^2.9.0",
-        "path-parse": "^1.0.7",
-        "supports-preserve-symlinks-flag": "^1.0.0"
-      }
-    },
-    "resolve-from": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmmirror.com/resolve-from/-/resolve-from-4.0.0.tgz",
-      "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
-      "dev": true
-    },
-    "resumer": {
-      "version": "0.0.0",
-      "resolved": "https://registry.npmjs.org/resumer/-/resumer-0.0.0.tgz",
-      "integrity": "sha512-Fn9X8rX8yYF4m81rZCK/5VmrmsSbqS/i3rDLl6ZZHAXgC2nTAx3dhwG8q8odP/RmdLa2YrybDJaAMg+X1ajY3w==",
-      "requires": {
-        "through": "~2.3.4"
-      }
-    },
-    "reusify": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmmirror.com/reusify/-/reusify-1.0.4.tgz",
-      "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
-      "dev": true
-    },
-    "right-align": {
-      "version": "0.1.3",
-      "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz",
-      "integrity": "sha512-yqINtL/G7vs2v+dFIZmFUDbnVyFUJFKd6gK22Kgo6R4jfJGFtisKyncWDDULgjfqf4ASQuIQyjJ7XZ+3aWpsAg==",
-      "requires": {
-        "align-text": "^0.1.1"
-      }
-    },
-    "rimraf": {
-      "version": "3.0.2",
-      "resolved": "https://registry.npmmirror.com/rimraf/-/rimraf-3.0.2.tgz",
-      "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
-      "dev": true,
-      "requires": {
-        "glob": "^7.1.3"
-      }
-    },
-    "rollup": {
-      "version": "2.77.3",
-      "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.77.3.tgz",
-      "integrity": "sha512-/qxNTG7FbmefJWoeeYJFbHehJ2HNWnjkAFRKzWN/45eNBBF/r8lo992CwcJXEzyVxs5FmfId+vTSTQDb+bxA+g==",
-      "dev": true,
-      "requires": {
-        "fsevents": "~2.3.2"
-      }
-    },
-    "run-parallel": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmmirror.com/run-parallel/-/run-parallel-1.2.0.tgz",
-      "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
-      "dev": true,
-      "requires": {
-        "queue-microtask": "^1.2.2"
-      }
-    },
-    "rw": {
-      "version": "1.3.3",
-      "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz",
-      "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ=="
-    },
-    "safe-regex-test": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz",
-      "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==",
-      "requires": {
-        "call-bind": "^1.0.2",
-        "get-intrinsic": "^1.1.3",
-        "is-regex": "^1.1.4"
-      }
-    },
-    "sass": {
-      "version": "1.54.4",
-      "resolved": "https://registry.npmmirror.com/sass/-/sass-1.54.4.tgz",
-      "integrity": "sha512-3tmF16yvnBwtlPrNBHw/H907j8MlOX8aTBnlNX1yrKx24RKcJGPyLhFUwkoKBKesR3unP93/2z14Ll8NicwQUA==",
-      "dev": true,
-      "requires": {
-        "chokidar": ">=3.0.0 <4.0.0",
-        "immutable": "^4.0.0",
-        "source-map-js": ">=0.6.2 <2.0.0"
-      }
-    },
-    "sass-loader": {
-      "version": "12.6.0",
-      "resolved": "https://registry.npmmirror.com/sass-loader/-/sass-loader-12.6.0.tgz",
-      "integrity": "sha512-oLTaH0YCtX4cfnJZxKSLAyglED0naiYfNG1iXfU5w1LNZ+ukoA5DtyDIN5zmKVZwYNJP4KRc5Y3hkWga+7tYfA==",
-      "dev": true,
-      "requires": {
-        "klona": "^2.0.4",
-        "neo-async": "^2.6.2"
-      }
-    },
-    "screenfull": {
-      "version": "6.0.2",
-      "resolved": "https://registry.npmmirror.com/screenfull/-/screenfull-6.0.2.tgz",
-      "integrity": "sha512-AQdy8s4WhNvUZ6P8F6PB21tSPIYKniic+Ogx0AacBMjKP1GUHN2E9URxQHtCusiwxudnCKkdy4GrHXPPJSkCCw=="
-    },
-    "select": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmmirror.com/select/-/select-1.1.2.tgz",
-      "integrity": "sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA=="
-    },
-    "semver": {
-      "version": "7.3.7",
-      "resolved": "https://registry.npmmirror.com/semver/-/semver-7.3.7.tgz",
-      "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
-      "dev": true,
-      "requires": {
-        "lru-cache": "^6.0.0"
-      }
-    },
-    "shebang-command": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmmirror.com/shebang-command/-/shebang-command-2.0.0.tgz",
-      "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
-      "dev": true,
-      "requires": {
-        "shebang-regex": "^3.0.0"
-      }
-    },
-    "shebang-regex": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmmirror.com/shebang-regex/-/shebang-regex-3.0.0.tgz",
-      "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
-      "dev": true
-    },
-    "side-channel": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
-      "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
-      "requires": {
-        "call-bind": "^1.0.0",
-        "get-intrinsic": "^1.0.2",
-        "object-inspect": "^1.9.0"
-      }
-    },
-    "size-sensor": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/size-sensor/-/size-sensor-1.0.1.tgz",
-      "integrity": "sha512-QTy7MnuugCFXIedXRpUSk9gUnyNiaxIdxGfUjr8xxXOqIB3QvBUYP9+b51oCg2C4dnhaeNk/h57TxjbvoJrJUA=="
-    },
-    "slash": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmmirror.com/slash/-/slash-3.0.0.tgz",
-      "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
-      "dev": true
-    },
-    "sortablejs": {
-      "version": "1.15.0",
-      "resolved": "https://registry.npmmirror.com/sortablejs/-/sortablejs-1.15.0.tgz",
-      "integrity": "sha512-bv9qgVMjUMf89wAvM6AxVvS/4MX3sPeN0+agqShejLU5z5GX4C75ow1O2e5k4L6XItUyAK3gH6AxSbXrOM5e8w=="
-    },
-    "source-map": {
-      "version": "0.6.1",
-      "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz",
-      "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
-    },
-    "source-map-js": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.0.2.tgz",
-      "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw=="
-    },
-    "source-map-support": {
-      "version": "0.3.3",
-      "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.3.3.tgz",
-      "integrity": "sha512-9O4+y9n64RewmFoKUZ/5Tx9IHIcXM6Q+RTSw6ehnqybUz4a7iwR3Eaw80uLtqqQ5D0C+5H03D4KKGo9PdP33Gg==",
-      "requires": {
-        "source-map": "0.1.32"
-      },
-      "dependencies": {
-        "source-map": {
-          "version": "0.1.32",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.32.tgz",
-          "integrity": "sha512-htQyLrrRLkQ87Zfrir4/yN+vAUd6DNjVayEjTSHXu29AYQJw57I4/xEL/M6p6E/woPNJwvZt6rVlzc7gFEJccQ==",
-          "requires": {
-            "amdefine": ">=0.0.4"
-          }
-        }
-      }
-    },
-    "sourcemap-codec": {
-      "version": "1.4.8",
-      "resolved": "https://registry.npmmirror.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
-      "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA=="
-    },
-    "splitpanes": {
-      "version": "3.1.1",
-      "resolved": "https://registry.npmmirror.com/splitpanes/-/splitpanes-3.1.1.tgz",
-      "integrity": "sha512-VUkxDJfIGSvTM/fm/+OSrx8ha9URwE/9B8FPvfzoBuAxVELIHBWpsfnJXIXv77zVwuex//QQL4kTU9SDBPeHjA=="
-    },
-    "ssf": {
-      "version": "0.11.2",
-      "resolved": "https://registry.npmmirror.com/ssf/-/ssf-0.11.2.tgz",
-      "integrity": "sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==",
-      "requires": {
-        "frac": "~1.1.2"
-      }
-    },
-    "string.prototype.trim": {
-      "version": "1.2.6",
-      "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.6.tgz",
-      "integrity": "sha512-8lMR2m+U0VJTPp6JjvJTtGyc4FIGq9CdRt7O9p6T0e6K4vjU+OP+SQJpbe/SBmRcCUIvNUnjsbmY6lnMp8MhsQ==",
-      "requires": {
-        "call-bind": "^1.0.2",
-        "define-properties": "^1.1.4",
-        "es-abstract": "^1.19.5"
-      }
-    },
-    "string.prototype.trimend": {
-      "version": "1.0.5",
-      "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz",
-      "integrity": "sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==",
-      "requires": {
-        "call-bind": "^1.0.2",
-        "define-properties": "^1.1.4",
-        "es-abstract": "^1.19.5"
-      }
-    },
-    "string.prototype.trimstart": {
-      "version": "1.0.5",
-      "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz",
-      "integrity": "sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==",
-      "requires": {
-        "call-bind": "^1.0.2",
-        "define-properties": "^1.1.4",
-        "es-abstract": "^1.19.5"
-      }
-    },
-    "strip-ansi": {
-      "version": "6.0.1",
-      "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz",
-      "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
-      "dev": true,
-      "requires": {
-        "ansi-regex": "^5.0.1"
-      }
-    },
-    "strip-json-comments": {
-      "version": "3.1.1",
-      "resolved": "https://registry.npmmirror.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
-      "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
-      "dev": true
-    },
-    "style-mod": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.0.0.tgz",
-      "integrity": "sha512-OPhtyEjyyN9x3nhPsu76f52yUGXiZcgvsrFVtvTkyGRQJ0XK+GPc6ov1z+lRpbeabka+MYEQxOYRnt5nF30aMw=="
-    },
-    "supports-color": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz",
-      "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
-      "dev": true,
-      "requires": {
-        "has-flag": "^4.0.0"
-      }
-    },
-    "supports-preserve-symlinks-flag": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmmirror.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
-      "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="
-    },
-    "tape": {
-      "version": "4.16.1",
-      "resolved": "https://registry.npmjs.org/tape/-/tape-4.16.1.tgz",
-      "integrity": "sha512-U4DWOikL5gBYUrlzx+J0oaRedm2vKLFbtA/+BRAXboGWpXO7bMP8ddxlq3Cse2bvXFQ0jZMOj6kk3546mvCdFg==",
-      "requires": {
-        "call-bind": "~1.0.2",
-        "deep-equal": "~1.1.1",
-        "defined": "~1.0.0",
-        "dotignore": "~0.1.2",
-        "for-each": "~0.3.3",
-        "glob": "~7.2.3",
-        "has": "~1.0.3",
-        "inherits": "~2.0.4",
-        "is-regex": "~1.1.4",
-        "minimist": "~1.2.6",
-        "object-inspect": "~1.12.2",
-        "resolve": "~1.22.1",
-        "resumer": "~0.0.0",
-        "string.prototype.trim": "~1.2.6",
-        "through": "~2.3.8"
-      }
-    },
-    "text-table": {
-      "version": "0.2.0",
-      "resolved": "https://registry.npmmirror.com/text-table/-/text-table-0.2.0.tgz",
-      "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
-      "dev": true
-    },
-    "through": {
-      "version": "2.3.8",
-      "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
-      "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg=="
-    },
-    "tiny-emitter": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmmirror.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
-      "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q=="
-    },
-    "to-regex-range": {
-      "version": "5.0.1",
-      "resolved": "https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz",
-      "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
-      "dev": true,
-      "requires": {
-        "is-number": "^7.0.0"
-      }
-    },
-    "tslib": {
-      "version": "2.4.0",
-      "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.4.0.tgz",
-      "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ=="
-    },
-    "tsutils": {
-      "version": "3.21.0",
-      "resolved": "https://registry.npmmirror.com/tsutils/-/tsutils-3.21.0.tgz",
-      "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==",
-      "dev": true,
-      "requires": {
-        "tslib": "^1.8.1"
-      },
-      "dependencies": {
-        "tslib": {
-          "version": "1.14.1",
-          "resolved": "https://registry.npmmirror.com/tslib/-/tslib-1.14.1.tgz",
-          "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
-          "dev": true
-        }
-      }
-    },
-    "type-check": {
-      "version": "0.4.0",
-      "resolved": "https://registry.npmmirror.com/type-check/-/type-check-0.4.0.tgz",
-      "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
-      "dev": true,
-      "requires": {
-        "prelude-ls": "^1.2.1"
-      }
-    },
-    "type-fest": {
-      "version": "0.20.2",
-      "resolved": "https://registry.npmmirror.com/type-fest/-/type-fest-0.20.2.tgz",
-      "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
-      "dev": true
-    },
-    "typescript": {
-      "version": "4.7.4",
-      "resolved": "https://registry.npmmirror.com/typescript/-/typescript-4.7.4.tgz",
-      "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==",
-      "dev": true
-    },
-    "uglify-js": {
-      "version": "2.8.29",
-      "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz",
-      "integrity": "sha512-qLq/4y2pjcU3vhlhseXGGJ7VbFO4pBANu0kwl8VCa9KEI0V8VfZIx2Fy3w01iSTA/pGwKZSmu/+I4etLNDdt5w==",
-      "requires": {
-        "source-map": "~0.5.1",
-        "uglify-to-browserify": "~1.0.0",
-        "yargs": "~3.10.0"
-      },
-      "dependencies": {
-        "source-map": {
-          "version": "0.5.7",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
-          "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ=="
-        }
-      }
-    },
-    "uglify-to-browserify": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz",
-      "integrity": "sha512-vb2s1lYx2xBtUgy+ta+b2J/GLVUR+wmpINwHePmPRhOsIVCG2wDzKJ0n14GslH1BifsqVzSOwQhRaCAsZ/nI4Q==",
-      "optional": true
-    },
-    "unbox-primitive": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
-      "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==",
-      "requires": {
-        "call-bind": "^1.0.2",
-        "has-bigints": "^1.0.2",
-        "has-symbols": "^1.0.3",
-        "which-boxed-primitive": "^1.0.2"
-      }
-    },
-    "universalify": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
-      "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
-      "dev": true
-    },
-    "uri-js": {
-      "version": "4.4.1",
-      "resolved": "https://registry.npmmirror.com/uri-js/-/uri-js-4.4.1.tgz",
-      "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
-      "dev": true,
-      "requires": {
-        "punycode": "^2.1.0"
-      }
-    },
-    "util-deprecate": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz",
-      "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
-      "dev": true
-    },
-    "uuid": {
-      "version": "9.0.0",
-      "resolved": "https://registry.npmmirror.com/uuid/-/uuid-9.0.0.tgz",
-      "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg=="
-    },
-    "v8-compile-cache": {
-      "version": "2.3.0",
-      "resolved": "https://registry.npmmirror.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz",
-      "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==",
-      "dev": true
-    },
-    "vform3-builds": {
-      "version": "3.0.8",
-      "resolved": "https://registry.npmjs.org/vform3-builds/-/vform3-builds-3.0.8.tgz",
-      "integrity": "sha512-ipfwAlFcZ87/asYmeYBqAtwXlq7pB4WRpwGsF2dW310GUmy8RrIm5sRklntTi4m6xuZCXwhkOFXkHokTOCkCpg=="
-    },
-    "vite": {
-      "version": "2.9.16",
-      "resolved": "https://registry.npmjs.org/vite/-/vite-2.9.16.tgz",
-      "integrity": "sha512-X+6q8KPyeuBvTQV8AVSnKDvXoBMnTx8zxh54sOwmmuOdxkjMmEJXH2UEchA+vTMps1xw9vL64uwJOWryULg7nA==",
-      "dev": true,
-      "requires": {
-        "esbuild": "^0.14.27",
-        "fsevents": "~2.3.2",
-        "postcss": "^8.4.13",
-        "resolve": "^1.22.0",
-        "rollup": ">=2.59.0 <2.78.0"
-      }
-    },
-    "vite-plugin-compression": {
-      "version": "0.5.1",
-      "resolved": "https://registry.npmjs.org/vite-plugin-compression/-/vite-plugin-compression-0.5.1.tgz",
-      "integrity": "sha512-5QJKBDc+gNYVqL/skgFAP81Yuzo9R+EAf19d+EtsMF/i8kFUpNi3J/H01QD3Oo8zBQn+NzoCIFkpPLynoOzaJg==",
-      "dev": true,
-      "requires": {
-        "chalk": "^4.1.2",
-        "debug": "^4.3.3",
-        "fs-extra": "^10.0.0"
-      }
-    },
-    "vue": {
-      "version": "3.2.37",
-      "resolved": "https://registry.npmmirror.com/vue/-/vue-3.2.37.tgz",
-      "integrity": "sha512-bOKEZxrm8Eh+fveCqS1/NkG/n6aMidsI6hahas7pa0w/l7jkbssJVsRhVDs07IdDq7h9KHswZOgItnwJAgtVtQ==",
-      "requires": {
-        "@vue/compiler-dom": "3.2.37",
-        "@vue/compiler-sfc": "3.2.37",
-        "@vue/runtime-dom": "3.2.37",
-        "@vue/server-renderer": "3.2.37",
-        "@vue/shared": "3.2.37"
-      }
-    },
-    "vue-baidu-map-3x": {
-      "version": "1.0.18",
-      "resolved": "https://registry.npmmirror.com/vue-baidu-map-3x/-/vue-baidu-map-3x-1.0.18.tgz",
-      "integrity": "sha512-02KmFBLZ7xr/rmolRTo2tXw/uN3C0sYCag0D4RENkzggB2kHlKSijf+HLiedgNRDogfeS9IQkwo8zOhYIHga9A==",
-      "requires": {
-        "bmaplib.curveline": "^1.0.0",
-        "bmaplib.distancetool": "^1.0.2",
-        "bmaplib.heatmap": "^1.0.4",
-        "bmaplib.lushu": "^1.0.7",
-        "bmaplib.markerclusterer": "^1.0.13",
-        "tiny-emitter": "^2.1.0",
-        "vue": "^3.2.25",
-        "vue-router": "^4.0.14"
-      }
-    },
-    "vue-clipboard3": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmmirror.com/vue-clipboard3/-/vue-clipboard3-1.0.1.tgz",
-      "integrity": "sha512-iJ2vrizowfA73W3pcxMAKhYSvfekJrQ3FhbveVe9esS1Vfu+xW3Fgc0UKE8N4Q6DyRtcAoNlef8txmD8tK8dIg==",
-      "requires": {
-        "clipboard": "^2.0.6"
-      }
-    },
-    "vue-codemirror": {
-      "version": "6.1.1",
-      "resolved": "https://registry.npmjs.org/vue-codemirror/-/vue-codemirror-6.1.1.tgz",
-      "integrity": "sha512-rTAYo44owd282yVxKtJtnOi7ERAcXTeviwoPXjIc6K/IQYUsoDkzPvw/JDFtSP6T7Cz/2g3EHaEyeyaQCKoDMg==",
-      "requires": {
-        "@codemirror/commands": "6.x",
-        "@codemirror/language": "6.x",
-        "@codemirror/state": "6.x",
-        "@codemirror/view": "6.x"
-      }
-    },
-    "vue-demi": {
-      "version": "0.14.6",
-      "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.6.tgz",
-      "integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w=="
-    },
-    "vue-eslint-parser": {
-      "version": "8.3.0",
-      "resolved": "https://registry.npmmirror.com/vue-eslint-parser/-/vue-eslint-parser-8.3.0.tgz",
-      "integrity": "sha512-dzHGG3+sYwSf6zFBa0Gi9ZDshD7+ad14DGOdTLjruRVgZXe2J+DcZ9iUhyR48z5g1PqRa20yt3Njna/veLJL/g==",
-      "dev": true,
-      "requires": {
-        "debug": "^4.3.2",
-        "eslint-scope": "^7.0.0",
-        "eslint-visitor-keys": "^3.1.0",
-        "espree": "^9.0.0",
-        "esquery": "^1.4.0",
-        "lodash": "^4.17.21",
-        "semver": "^7.3.5"
-      },
-      "dependencies": {
-        "eslint-scope": {
-          "version": "7.1.1",
-          "resolved": "https://registry.npmmirror.com/eslint-scope/-/eslint-scope-7.1.1.tgz",
-          "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==",
-          "dev": true,
-          "requires": {
-            "esrecurse": "^4.3.0",
-            "estraverse": "^5.2.0"
-          },
-          "dependencies": {
-            "esrecurse": {
-              "version": "4.3.0",
-              "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
-              "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
-              "dev": true,
-              "requires": {
-                "estraverse": "^5.2.0"
-              }
-            },
-            "estraverse": {
-              "version": "5.3.0",
-              "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
-              "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
-              "dev": true
-            }
-          }
-        }
-      }
-    },
-    "vue-grid-layout": {
-      "version": "3.0.0-beta1",
-      "resolved": "https://registry.npmmirror.com/vue-grid-layout/-/vue-grid-layout-3.0.0-beta1.tgz",
-      "integrity": "sha512-MsW0yfYNtnAO/uDhfZvkP6effxSJxvhAFbIL37x6Rn3vW9xf0WHVefKaSbQMLpSq3mXnR6ut0pg2Cd5lqIIZzg==",
-      "requires": {
-        "@interactjs/actions": "^1.10.2",
-        "@interactjs/auto-start": "^1.10.2",
-        "@interactjs/dev-tools": "^1.10.2",
-        "@interactjs/interactjs": "^1.10.2",
-        "@interactjs/modifiers": "^1.10.2",
-        "element-resize-detector": "^1.2.1",
-        "mitt": "^2.1.0"
-      },
-      "dependencies": {
-        "mitt": {
-          "version": "2.1.0",
-          "resolved": "https://registry.npmmirror.com/mitt/-/mitt-2.1.0.tgz",
-          "integrity": "sha512-ILj2TpLiysu2wkBbWjAmww7TkZb65aiQO+DkVdUTBpBXq+MHYiETENkKFMtsJZX1Lf4pe4QOrTSjIfUwN5lRdg=="
-        }
-      }
-    },
-    "vue-i18n": {
-      "version": "9.1.10",
-      "resolved": "https://registry.npmmirror.com/vue-i18n/-/vue-i18n-9.1.10.tgz",
-      "integrity": "sha512-jpr7gV5KPk4n+sSPdpZT8Qx3XzTcNDWffRlHV/cT2NUyEf+sEgTTmLvnBAibjOFJ0zsUyZlVTAWH5DDnYep+1g==",
-      "requires": {
-        "@intlify/core-base": "9.1.10",
-        "@intlify/shared": "9.1.10",
-        "@intlify/vue-devtools": "9.1.10",
-        "@vue/devtools-api": "^6.0.0-beta.7"
-      }
-    },
-    "vue-router": {
-      "version": "4.1.3",
-      "resolved": "https://registry.npmmirror.com/vue-router/-/vue-router-4.1.3.tgz",
-      "integrity": "sha512-XvK81bcYglKiayT7/vYAg/f36ExPC4t90R/HIpzrZ5x+17BOWptXLCrEPufGgZeuq68ww4ekSIMBZY1qdUdfjA==",
-      "requires": {
-        "@vue/devtools-api": "^6.1.4"
-      }
-    },
-    "vue3-cron": {
-      "version": "1.1.8",
-      "resolved": "https://registry.npmmirror.com/vue3-cron/-/vue3-cron-1.1.8.tgz",
-      "integrity": "sha512-r6SBXnIASHponz3vXuh9vVHYYsGEbtUljSzJAdAAEBkh5wtg0zj/yks8979cKPmQsU46p79c/sxOxUs5KCa/Lw==",
-      "requires": {
-        "core-js": "^3.6.5",
-        "element-plus": "^1.0.2-beta.28",
-        "vue": "^3.0.0"
-      },
-      "dependencies": {
-        "@popperjs/core": {
-          "version": "2.11.6",
-          "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.6.tgz",
-          "integrity": "sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw=="
-        },
-        "async-validator": {
-          "version": "3.5.2",
-          "resolved": "https://registry.npmmirror.com/async-validator/-/async-validator-3.5.2.tgz",
-          "integrity": "sha512-8eLCg00W9pIRZSB781UUX/H6Oskmm8xloZfr09lz5bikRpBVDlJ3hRVuxxP1SxcwsEYfJ4IU8Q19Y8/893r3rQ=="
-        },
-        "element-plus": {
-          "version": "1.0.2-beta.71",
-          "resolved": "https://registry.npmmirror.com/element-plus/-/element-plus-1.0.2-beta.71.tgz",
-          "integrity": "sha512-tlfbRORIav8gJcIpjZI5F6aJIVHIaDuGO6/vKu43lgYq4JS2JPNRTjvrSE2p4f5xLfaFNfOWjCS3sybXLfMg8g==",
-          "requires": {
-            "@element-plus/icons": "^0.0.11",
-            "@popperjs/core": "^2.4.4",
-            "async-validator": "^3.4.0",
-            "dayjs": "1.x",
-            "lodash": "^4.17.20",
-            "mitt": "^2.1.0",
-            "normalize-wheel": "^1.0.1",
-            "resize-observer-polyfill": "^1.5.1"
-          }
-        },
-        "mitt": {
-          "version": "2.1.0",
-          "resolved": "https://registry.npmmirror.com/mitt/-/mitt-2.1.0.tgz",
-          "integrity": "sha512-ILj2TpLiysu2wkBbWjAmww7TkZb65aiQO+DkVdUTBpBXq+MHYiETENkKFMtsJZX1Lf4pe4QOrTSjIfUwN5lRdg=="
-        }
-      }
-    },
-    "vue3-json-viewer": {
-      "version": "2.2.2",
-      "resolved": "https://registry.npmjs.org/vue3-json-viewer/-/vue3-json-viewer-2.2.2.tgz",
-      "integrity": "sha512-56l3XDGggnpwEqZieXsSMhNT4NhtO6d7zuSAxHo4i0UVxymyY2jRb7UMQOU1ztChKALZCAzX7DlgrsnEhxu77A==",
-      "requires": {
-        "clipboard": "^2.0.10"
-      }
-    },
-    "vuex": {
-      "version": "4.0.2",
-      "resolved": "https://registry.npmmirror.com/vuex/-/vuex-4.0.2.tgz",
-      "integrity": "sha512-M6r8uxELjZIK8kTKDGgZTYX/ahzblnzC4isU1tpmEuOIIKmV+TRdc+H4s8ds2NuZ7wpUTdGRzJRtoj+lI+pc0Q==",
-      "requires": {
-        "@vue/devtools-api": "^6.0.0-beta.11"
-      }
-    },
-    "w3c-keyname": {
-      "version": "2.2.6",
-      "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.6.tgz",
-      "integrity": "sha512-f+fciywl1SJEniZHD6H+kUO8gOnwIr7f4ijKA6+ZvJFjeGi1r4PDLl53Ayud9O/rk64RqgoQine0feoeOU0kXg=="
-    },
-    "wangeditor": {
-      "version": "4.7.15",
-      "resolved": "https://registry.npmmirror.com/wangeditor/-/wangeditor-4.7.15.tgz",
-      "integrity": "sha512-aPTdREd8BxXVyJ5MI+LU83FQ7u1EPd341iXIorRNYSOvoimNoZ4nPg+yn3FGbB93/owEa6buLw8wdhYnMCJQLg==",
-      "requires": {
-        "@babel/runtime": "^7.11.2",
-        "@babel/runtime-corejs3": "^7.11.2",
-        "tslib": "^2.1.0"
-      }
-    },
-    "which": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmmirror.com/which/-/which-2.0.2.tgz",
-      "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
-      "dev": true,
-      "requires": {
-        "isexe": "^2.0.0"
-      }
-    },
-    "which-boxed-primitive": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
-      "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
-      "requires": {
-        "is-bigint": "^1.0.1",
-        "is-boolean-object": "^1.1.0",
-        "is-number-object": "^1.0.4",
-        "is-string": "^1.0.5",
-        "is-symbol": "^1.0.3"
-      }
-    },
-    "window-size": {
-      "version": "0.1.0",
-      "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz",
-      "integrity": "sha512-1pTPQDKTdd61ozlKGNCjhNRd+KPmgLSGa3mZTHoOliaGcESD8G1PXhh7c1fgiPjVbNVfgy2Faw4BI8/m0cC8Mg=="
-    },
-    "wmf": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmmirror.com/wmf/-/wmf-1.0.2.tgz",
-      "integrity": "sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw=="
-    },
-    "word": {
-      "version": "0.3.0",
-      "resolved": "https://registry.npmmirror.com/word/-/word-0.3.0.tgz",
-      "integrity": "sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA=="
-    },
-    "word-wrap": {
-      "version": "1.2.3",
-      "resolved": "https://registry.npmmirror.com/word-wrap/-/word-wrap-1.2.3.tgz",
-      "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
-      "dev": true
-    },
-    "wordwrap": {
-      "version": "0.0.2",
-      "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz",
-      "integrity": "sha512-xSBsCeh+g+dinoBv3GAOWM4LcVVO68wLXRanibtBSdUvkGWQRGeE9P7IwU9EmDDi4jA6L44lz15CGMwdw9N5+Q=="
-    },
-    "wrappy": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmmirror.com/wrappy/-/wrappy-1.0.2.tgz",
-      "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
-    },
-    "xlsx-with-styles": {
-      "version": "0.17.2",
-      "resolved": "https://registry.npmmirror.com/xlsx-with-styles/-/xlsx-with-styles-0.17.2.tgz",
-      "integrity": "sha512-7lrfG6DmIuZI1yjebQFIQzKrR/ZBXEYiQVAuEl/wqB45X8Izr0epynfOMi/Oo5Z8TSM5VoO2bCtOGy4wRnii3A==",
-      "requires": {
-        "adler-32": "~1.2.0",
-        "cfb": "^1.1.4",
-        "codepage": "~1.14.0",
-        "commander": "~2.17.1",
-        "crc-32": "~1.2.0",
-        "exit-on-epipe": "~1.0.1",
-        "fflate": "^0.3.8",
-        "ssf": "~0.11.2",
-        "wmf": "~1.0.1",
-        "word": "~0.3.0"
-      }
-    },
-    "yallist": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz",
-      "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
-      "dev": true
-    },
-    "yargs": {
-      "version": "3.10.0",
-      "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz",
-      "integrity": "sha512-QFzUah88GAGy9lyDKGBqZdkYApt63rCXYBGYnEP4xDJPXNqXXnBDACnbrXnViV6jRSqAePwrATi2i8mfYm4L1A==",
-      "requires": {
-        "camelcase": "^1.0.2",
-        "cliui": "^2.1.0",
-        "decamelize": "^1.0.0",
-        "window-size": "0.1.0"
-      }
-    },
-    "yocto-queue": {
-      "version": "0.1.0",
-      "resolved": "https://registry.npmmirror.com/yocto-queue/-/yocto-queue-0.1.0.tgz",
-      "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
-      "dev": true
-    },
-    "zrender": {
-      "version": "5.3.2",
-      "resolved": "https://registry.npmmirror.com/zrender/-/zrender-5.3.2.tgz",
-      "integrity": "sha512-8IiYdfwHj2rx0UeIGZGGU4WEVSDEdeVCaIg/fomejg1Xu6OifAL1GVzIPHg2D+MyUkbNgPWji90t0a8IDk+39w==",
-      "requires": {
-        "tslib": "2.3.0"
-      },
-      "dependencies": {
-        "tslib": {
-          "version": "2.3.0",
-          "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.3.0.tgz",
-          "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg=="
-        }
-      }
-    }
-  }
-}

+ 2 - 0
package.json

@@ -7,6 +7,7 @@
   "scripts": {
     "dev": "vite --force",
     "build": "vite build",
+    "build:golocal": "vite build --mode golocal",
     "build:open": "vite build --mode open",
     "build:test": "vite build --mode test",
     "deploy:zip": "npm run build && npm run zipAndUpload && npm run unzip && npm run success",
@@ -53,6 +54,7 @@
     "vue-grid-layout": "^3.0.0-beta1",
     "vue-i18n": "9.1.10",
     "vue-router": "^4.0.13",
+    "vue3-clipboard": "^1.0.0",
     "vue3-cron": "^1.1.8",
     "vue3-json-viewer": "^2.2.2",
     "vuex": "^4.0.2",

+ 10 - 11
src/api/alarm/index.ts

@@ -2,11 +2,10 @@ import { get, post, del, put } from '/@/utils/request';
 
 export default {
   common: {
-    levelall: (id: number) => get('/alarm/level/all', { id }),
-    trigger_type: (productKey: number) => get('/alarm/rule/trigger_type', { productKey }),
-    trigger_param: (productKey: number) => get('/alarm/rule/trigger_param', { productKey }),
+    trigger_type: (productKey: string) => get('/alarm/rule/trigger_type', { productKey }),
+    trigger_param: (productKey: string) => get('/alarm/rule/trigger_param', { productKey }),
     trigger_params: (params: object) => get('/alarm/rule/trigger_param', params),
-    operator: (productKey: number) => get('/alarm/rule/operator', { productKey }),
+    operator: (productKey?: string) => get('/alarm/rule/operator', { productKey }),
     getList: (params: object) => get('/alarm/rule/list', params),
     add: (data: object) => post('/alarm/rule/add', data),
     delete: (id: number) => del('/alarm/rule/del', { id }),
@@ -15,11 +14,11 @@ export default {
     deploy: (data: object) => post('/alarm/rule/deploy', data),
     undeploy: (data: object) => post('/alarm/rule/undeploy', data),
     level_edit: (data: object) => put('/alarm/level/edit', data),
-    level_all: (productKey: number) => get('/alarm/level/all', { productKey }),
-    },
-    log: {
-      getList: (params: object) => get('/alarm/log/list', params),
-      detail: (id: number) => get('/alarm/log/detail', { id }),
-      handle: (data: object) => post('/alarm/log/handle', data),
-      },
+    level_all: (productKey: string) => get('/alarm/level/all', { productKey }),
+  },
+  log: {
+    getList: (params: object) => get('/alarm/log/list', params),
+    detail: (id: number) => get('/alarm/log/detail', { id }),
+    handle: (data: object) => post('/alarm/log/handle', data),
+  },
 }

+ 46 - 34
src/api/datahub/index.ts

@@ -2,32 +2,32 @@ import { get, post, del, put, file } from '/@/utils/request';
 
 export default {
 
-  common: {
-    getList: (params: object) => get('/source/search', params),
-    add: (data: object) => post('/source/api/add', data),
-    delete: (ids: number) => del('/source/del', { ids }),
-    edit: (data: object) => put('/source/api/edit', data),
-    detail: (sourceId: number) => get('/source/detail', { sourceId }),
-    deploy: (data: object) => post('/source/deploy', data),
-    undeploy: (data: object) => post('/source/undeploy', data),  
-    api: (sourceId: number) => get('/source/api/get', { sourceId }),
-    devadd: (data: object) => post('/source/device/add', data),
-    devedit: (data: object) => put('/source/device/edit', data),
-    devapi: (sourceId: number) => get('/source/device/get', { sourceId }),
-    getdevList: (params: object) => get('/product/device/list', params),
-    getdata: (params: object) => get('/source/getdata', params),
-    getLists: (params: object) => get('/source/list', params),
-    copy: (params: object) => post('/source/copy', params),
+   common: {
+      getList: (params: object) => get('/source/search', params),
+      add: (data: object) => post('/source/api/add', data),
+      delete: (ids: number) => del('/source/del', { ids }),
+      edit: (data: object) => put('/source/api/edit', data),
+      detail: (sourceId: number) => get('/source/detail', { sourceId }),
+      deploy: (data: object) => post('/source/deploy', data),
+      undeploy: (data: object) => post('/source/undeploy', data),
+      api: (sourceId: number) => get('/source/api/get', { sourceId }),
+      devadd: (data: object) => post('/source/device/add', data),
+      devedit: (data: object) => put('/source/device/edit', data),
+      devapi: (sourceId: number) => get('/source/device/get', { sourceId }),
+      getdevList: (params: object) => get('/product/device/list', params),
+      getdata: (params: object) => get('/source/getdata', params),
+      getLists: (params: object) => get('/source/list', params),
+      copy: (params: object) => post('/source/copy', params),
 
-    dbadd: (data: object) => post('/source/db/add', data),
-    dbedit: (data: object) => put('/source/db/edit', data),
-    getfields: (sourceId: number) => get('/source/db/fields', { sourceId }),
+      dbadd: (data: object) => post('/source/db/add', data),
+      dbedit: (data: object) => put('/source/db/edit', data),
+      getfields: (sourceId: number) => get('/source/db/fields', { sourceId }),
 
-    devdb: (sourceId: number) => get('/source/db/get', { sourceId }),
+      devdb: (sourceId: number) => get('/source/db/get', { sourceId }),
 
-    },
-   
-   node:{
+   },
+
+   node: {
       getList: (params: object) => get('/source/node/list', params),
       add: (data: object) => post('/source/node/add', data),
       delete: (nodeId: number) => del('/source/node/del', { nodeId }),
@@ -35,34 +35,34 @@ export default {
       getpropertyList: (params: object) => get('/product/tsl/property/all', params),
    },
 
-   template:{
+   template: {
       getList: (params: object) => get('/source/template/search', params),
       add: (data: object) => post('/source/template/add', data),
       delete: (ids: number) => del('/source/template/del', { ids }),
       edit: (data: object) => put('/source/template/edit', data),
       detail: (id: string) => get('/source/template/detail', { id }),
       allList: (params: object) => get('/source/template/list', params), // 获取所有已发布列表
-      getdata: (params: object) => get('/source/template/getdata',  params ),
-      getDictData: (params: object) => get('/common/dict/data/getDictData',  params ),
-      cityTree: (params: object) => get('/common/city/tree',  params ),
+      getdata: (params: object) => get('/source/template/getdata', params),
+      getDictData: (params: object) => get('/common/dict/data/getDictData', params),
+      cityTree: (params: object) => get('/common/city/tree', params),
       copy: (params: object) => post('/source/template/copy', params),
       relation_check: (id: number) => get('/source/template/relation_check', { id }),
       source_list: (id: number) => get('/source/template/source_list', { id }),
       aggregate_from: (id: number) => get('/source/template/aggregate_from', { id }),
       relation: (data: object) => post('/source/template/relation', data),
       aggregate: (data: object) => post('/source/template/aggregate', data),
-   } ,
+   },
 
-   tnode:{
+   tnode: {
       getList: (params: object) => get('/source/template/node/list', params),
       add: (data: object) => post('/source/template/node/add', data),
       delete: (id: number) => del('/source/template/node/del', { id }),
       edit: (data: object) => put('/source/template/node/edit', data),
       deploy: (data: object) => post('/source/template/deploy', data),
-      undeploy: (data: object) => post('/source/template/undeploy', data),  
+      undeploy: (data: object) => post('/source/template/undeploy', data),
    },
-  
-   weather:{
+
+   weather: {
       getCityWeatherList: () => get('/envirotronics/weather/cityWeatherList'),
       getWhichCityWeather: (params: object) => get('/envirotronics/weather/getInfoById', params),
       getTemperatureEchartById: (params: object) => get('/envirotronics/weather/getTemperatureEchartById', params),
@@ -70,17 +70,29 @@ export default {
       getCityWeatherHistory: (params: object) => get('/envirotronics/weather/GetCityWeatherHistory', params),
       getCityWeatherHistoryExport: (params: object) => file('/envirotronics/weather/GetCityWeatherHistoryExport', params),
    },
-   statistics:{
+   statistics: {
       getStatisticsChartData: (params: object) => get('/statistics/bar/chart/data', params),
       getStatisticsLineChartData: (params: object) => get('/statistics/broken/line/data', params),
       getStatisticsTotalData: (params: object) => get('/statistics/city/data', params),
       getStatisticsPieData: (params: object) => get('/statistics/tempering/ratio/data', params),
       getStatisticsOverview: (params: object) => get('/statistics/overview', params),
    },
-   iotManage:{
+   iotManage: {
       getOverviewData: () => get('/thing/overview'),
       getAlarmList: (params: object) => get('/alarm/log/list', params),
       getAlarmDetail: (id: number) => get('/alarm/log/detail', { id }),
       getAlarmHandle: (data: object) => post('/alarm/log/handle', data),
+      // 设备消息总量本年统计
+      deviceDataTotalCount: (dateType: 'year' | 'month' | 'day') => get('/analysis/deviceDataTotalCount', { dateType }),
+      // 设备在线离线及总数统计
+      deviceOnlineOfflineCount: () => get('/analysis/deviceOnlineOfflineCount'),
+      // 本年度每月设备消息量统计 
+      deviceDataCount: (dateType: 'year' | 'month') => get('/analysis/deviceDataCount', { dateType }),
+      // 按年度每月设备告警数统计
+      deviceAlertCountByYearMonth: (year = '2023') => get('/analysis/deviceAlertCountByYearMonth', { year }),
+      // 按告警级别统计
+      deviceAlarmLevelCount: (dateType: 'year' | 'month' | 'day', date: string) => get('/analysis/deviceAlarmLevelCount', { dateType, date }),
+      // 产品数量统计
+      productCount: () => get('/analysis/productCount'),
    }
 }

+ 18 - 18
src/api/device/index.ts

@@ -10,24 +10,24 @@ export default {
   product: {
     // 设备属性设置
     propertySet: (data: object) => post('/product/property/set', data),
-    // 获取设备接入信息 /product/?id=35
-    connect_intro: (id: string) => get('/product/connect_intro', { id }),
+    // 获取设备接入信息
+    connect_intro: (productKey: string) => get('/product/connect_intro', { productKey }),
     getList: (params: object) => get('/product/page_list', params),
-    getLists: (params: object) => get('/product/list', params),
+    getLists: (params?: object) => get('/product/list', params),
     add: (data: object) => post('/product/add', data),
-    delete: (ids: number) => del('/product/del', { ids }),
+    delete: (keys: string[]) => del('/product/del', { keys }),
     edit: (data: object) => put('/product/edit', data),
-    detail: (id: number) => get('/product/detail', { id }),
+    detail: (productKey: string | string[]) => get('/product/detail', { productKey }),
     message_protocol_list: (params: object) => get('/product/protocol/message_protocol_list', params),
     trunsport_protocol_list: (params: object) => get('/product/protocol/trunsport_protocol_list', params),
     getDataType: (params: object) => get('/product/tsl/data_type', params),
-    deploy: (data: object) => post('/product/deploy', data),
-    undeploy: (data: object) => post('/product/undeploy', data),
+    deploy: (productKey: any) => post('/product/deploy', { productKey }),
+    undeploy: (productKey: any) => post('/product/undeploy', { productKey }),
     event: (data: object) => get('/product/tsl/event/all', data),
     getSubList: () => get('/product/sub_list'),
     export: (params: object) => file('/product/tsl/export', params),
 
-    deleteSubDevice: (id: number) => del('/product/device/del_sub', { id }),
+    deleteSubDevice: (deviceKey: number) => del('/product/device/del_sub', { deviceKey }),
     // 获取插件通信方式类型
     getTypesAll: (data: object) => get('/system/plugins/getTypesAll', data),
     // 脚本更新
@@ -43,16 +43,16 @@ export default {
     getList: (params: object) => get('/product/device/page_list', params),
     add: (data: object) => post('/product/device/add', data),
     edit: (data: object) => put('/product/device/edit', data),
-    del: (ids: number) => del('/product/device/del', { ids }),
-    detail: (id: number) => get('/product/device/detail', { id }),
+    del: (keys: string[]) => del('/product/device/del', { keys }),
+    detail: (deviceKey: any) => get('/product/device/detail', { deviceKey }),
     getLogList: (params: object) => get('/product/log/search', params),
     getlogcate: (params: object) => get('/product/log/type', params),
     getrun_status: (params: object) => get('/product/device/run_status', params),
     getLogDetail: (params: object) => get('/product/device/property/list', params),
     devonline: (data: object) => post('/product/device/online', data),
     devoffline: (data: object) => post('/product/device/offline', data),
-    devdeploy: (data: object) => post('/product/device/deploy', data),
-    devundeploy: (data: object) => post('/product/device/undeploy', data),
+    devdeploy: (deviceKey: string) => post('/product/device/deploy', { deviceKey }),
+    devundeploy: (deviceKey: string) => post('/product/device/undeploy', { deviceKey }),
   },
   dept: {
     getList: (params: object) => get('/system/dept/tree', params),
@@ -66,23 +66,23 @@ export default {
     property: (params: object) => get('/product/tsl/property/list', params),
     propertyadd: (data: object) => post('/product/tsl/property/add', data),
     propertyedit: (data: object) => put('/product/tsl/property/edit', data),
-    propertydel: (productId: number, key: string) => del('/product/tsl/property/del', { productId, key }),
+    propertydel: (productKey: string, key: string) => del('/product/tsl/property/del', { productKey, key }),
 
     function: (params: object) => get('/product/tsl/function/list', params),
     functionadd: (data: object) => post('/product/tsl/function/add', data),
     functionedit: (data: object) => put('/product/tsl/function/edit', data),
-    functiondel: (productId: number, key: string) => del('/product/tsl/function/del', { productId, key }),
+    functiondel: (productKey: string, key: string) => del('/product/tsl/function/del', { productKey, key }),
 
 
     event: (params: object) => get('/product/tsl/event/list', params),
     eventadd: (data: object) => post('/product/tsl/event/add', data),
     eventedit: (data: object) => put('/product/tsl/event/edit', data),
-    eventdel: (productId: number, key: string) => del('/product/tsl/event/del', { productId, key }),
+    eventdel: (productKey: string, key: string) => del('/product/tsl/event/del', { productKey, key }),
 
     tag: (params: object) => get('/product/tsl/tag/list', params),
     tagadd: (data: object) => post('/product/tsl/tag/add', data),
     tagedit: (data: object) => put('/product/tsl/tag/edit', data),
-    tagdel: (productId: number, key: string) => del('/product/tsl/tag/del', { productId, key }),
+    tagdel: (productKey: string, key: string) => del('/product/tsl/tag/del', { productKey, key }),
   },
   tree: {
     getList: (params: object) => get('/product/device_tree/list', params),
@@ -105,14 +105,14 @@ export default {
     import: (data: object) => post('/product/device/import', data),
     export: (data: object) => file('/product/device/export', data),
   },
-  dev_asset:{
+  dev_asset: {
     getList: (params: object) => get('/product/dev_asset/list', params),
     add: (params: object) => post('/product/dev_asset/add', params),
     edit: (params: object) => put('/product/dev_asset/edit', params),
     detail: (params: object) => get('/product/dev_asset/get', params),
     delete: (params: object) => del('/product/dev_asset/delete', params),
   },
-  dev_asset_metadata:{
+  dev_asset_metadata: {
     getList: (params: object) => get('/product/dev_asset_metadata/list', params),
     add: (params: object) => post('/product/dev_asset_metadata/add', params),
     edit: (params: object) => put('/product/dev_asset_metadata/edit', params),

+ 1 - 1
src/api/ota/index.ts

@@ -12,7 +12,7 @@ export default {
   module: {
     getSubList: () => get('/product/list'),
     getList: (data: any) => get('/operate/ota_module/list', data),
-    del: (ids: number) => del('/operate/ota_module/delete', {ids}),
+    del: (ids: number[]) => del('/operate/ota_module/delete', {ids}),
     add: (data: any) => post('/operate/ota_module/add', data),
     edit: (data: any) => put('/operate/ota_module/edit', data),
     detail: (id: number) => get('/operate/ota_module/get', {id}),

+ 31 - 0
src/components/copy/index.vue

@@ -0,0 +1,31 @@
+<template>
+	<div class="text-copy-part">
+		<div class="text-part-text">{{ text }}</div>
+		<el-tooltip effect="dark" content="复制" placement="top">
+			<el-icon color="#409eff" @click="copy(text)"><ele-CopyDocument /></el-icon>
+		</el-tooltip>
+	</div>
+</template>
+
+<script lang="ts" setup>
+import copy from '/@/utils/copy.ts'
+defineProps({ text: String })
+</script>
+  
+<style lang="scss" scoped>
+.text-copy-part {
+	display: flex;
+	align-items: center;
+
+	.text-part-text {
+		overflow: hidden;
+		white-space: nowrap;
+		text-overflow: ellipsis;
+	}
+
+	.el-icon {
+		cursor: pointer;
+		margin-left: 4px;
+	}
+}
+</style>

+ 11 - 10
src/components/devantd/index.vue

@@ -4,34 +4,35 @@
 
 <script lang="ts" setup>
 import { TinyArea } from '@antv/g2plot';
-import { onMounted } from 'vue';
+import { onMounted, watch } from 'vue';
+
+let tinyArea: any = null
 
 const props = defineProps({
 	json: {
 		type: Object,
 		required: true,
 	},
-	antdid:{
+	antdid: {
 		type: String,
 		required: true,
 	}
 });
 
+// 数据更新之后更新图形
+watch(() => props.json, (data) => {
+	tinyArea && tinyArea.changeData(data.reverse());
+})
+
 onMounted(() => {
-	const tinyArea = new TinyArea(props.antdid, {
+	tinyArea = new TinyArea(props.antdid, {
 		height: 40,
 		autoFit: true,
-		data: props.json,
+		data: props.json.reverse(),
 		smooth: true,
 		areaStyle: {
 			fill: '#873bf4',
 		},
-	// 	tooltip: {
-	// 		customContent: (title, data) => {
-	// 			console.log(title,data);
-	// 		//return "<div>"+data2[index]+"</div><div>"+
-	// 	}
-    // },
 	});
 
 	tinyArea.render();

+ 1 - 1
src/components/noticeBar/index.vue

@@ -171,7 +171,7 @@ export default defineComponent({
 			.notice-bar-warp-slot {
 				width: 100%;
 				white-space: nowrap;
-				::v-deep(.el-carousel__item) {
+				:deep(.el-carousel__item) {
 					display: flex;
 					align-items: center;
 				}

+ 1 - 1
src/components/upload-wrapper/index.vue

@@ -54,7 +54,7 @@ const beforeAvatarUpload: UploadProps['beforeUpload'] = (rawFile) => {
 </script>
 
 <style scoped>
-.hide ::v-deep(.el-upload-list) {
+.hide :deep(.el-upload-list) {
   display: none;
 }
 

+ 1 - 1
src/components/upload/index.vue

@@ -153,7 +153,7 @@ const beforeAvatarUpload: UploadProps['beforeUpload'] = (rawFile) => {
 </script>
 
 <style scoped>
-.hide ::v-deep(.el-upload--picture-card) {
+.hide :deep(.el-upload--picture-card) {
 	display: none;
 }
 

+ 1 - 1
src/components/vue3cron/vue3cron.vue

@@ -573,7 +573,7 @@ export default defineComponent({
   }
 });
 </script>
-<style >
+<style lang="scss" scoped>
 .vue3-cron-div {
 
   .el-input-number__decrease,

+ 2 - 2
src/layout/lockScreen/index.vue

@@ -357,11 +357,11 @@ export default defineComponent({
 		}
 	}
 }
-::v-deep(.el-input-group__append) {
+:deep(.el-input-group__append) {
 	background: var(--el-color-white);
 	padding: 0px 15px;
 }
-::v-deep(.el-input__inner) {
+:deep(.el-input__inner) {
 	border-right-color: var(--el-border-color-extra-light);
 	&:hover {
 		border-color: var(--el-border-color-extra-light);

+ 2 - 2
src/layout/navBars/breadcrumb/breadcrumb.vue

@@ -134,11 +134,11 @@ export default defineComponent({
 		font-size: 14px;
 		margin-right: 5px;
 	}
-	::v-deep(.el-breadcrumb__separator) {
+	:deep(.el-breadcrumb__separator) {
 		opacity: 0.7;
 		color: var(--next-bg-topBarColor);
 	}
-	::v-deep(.el-breadcrumb__inner a, .el-breadcrumb__inner.is-link) {
+	:deep(.el-breadcrumb__inner a, .el-breadcrumb__inner.is-link) {
 		font-weight: unset !important;
 		color: var(--next-bg-topBarColor);
 		&:hover {

+ 2 - 2
src/layout/navBars/breadcrumb/search.vue

@@ -118,12 +118,12 @@ export default defineComponent({
 
 <style scoped lang="scss">
 .layout-search-dialog {
-	::v-deep(.el-dialog) {
+	:deep(.el-dialog) {
 		box-shadow: unset !important;
 		border-radius: 0 !important;
 		background: rgba(0, 0, 0, 0.5);
 	}
-	::v-deep(.el-autocomplete) {
+	:deep(.el-autocomplete) {
 		width: 560px;
 		position: absolute;
 		top: 100px;

+ 1 - 1
src/layout/navBars/breadcrumb/setings.vue

@@ -602,7 +602,7 @@ export default defineComponent({
 	height: calc(100vh - 50px);
 	padding: 0 15px;
 
-	::v-deep(.el-scrollbar__view) {
+	:deep(.el-scrollbar__view) {
 		overflow-x: hidden !important;
 	}
 

+ 3 - 3
src/layout/navBars/breadcrumb/user.vue

@@ -302,18 +302,18 @@ export default defineComponent({
     }
   }
 
-  ::v-deep(.el-dropdown) {
+  :deep(.el-dropdown) {
     color: var(--next-bg-topBarColor);
   }
 
-  ::v-deep(.el-badge) {
+  :deep(.el-badge) {
     height: 40px;
     line-height: 40px;
     display: flex;
     align-items: center;
   }
 
-  ::v-deep(.el-badge__content.is-fixed) {
+  :deep(.el-badge__content.is-fixed) {
     top: 12px;
   }
 }

+ 1 - 1
src/layout/navBars/breadcrumb/userNews.vue

@@ -121,7 +121,7 @@ const onGoToGiteeClick = () => {
 			opacity: 1;
 		}
 	}
-	::v-deep(.el-empty__description p) {
+	:deep(.el-empty__description p) {
 		font-size: 13px;
 	}
 }

+ 1 - 1
src/layout/navBars/tagsView/tagsView.vue

@@ -557,7 +557,7 @@ export default defineComponent({
 	border-bottom: 1px solid var(--next-border-color-light);
 	position: relative;
 	z-index: 4;
-	::v-deep(.el-scrollbar__wrap) {
+	:deep(.el-scrollbar__wrap) {
 		overflow-x: auto !important;
 	}
 	&-ul {

+ 2 - 2
src/layout/navMenu/horizontal.vue

@@ -135,10 +135,10 @@ export default defineComponent({
 	flex: 1;
 	overflow: hidden;
 	margin-right: 30px;
-	::v-deep(.el-scrollbar__bar.is-vertical) {
+	:deep(.el-scrollbar__bar.is-vertical) {
 		display: none;
 	}
-	::v-deep(a) {
+	:deep(a) {
 		width: 100%;
 	}
 	.el-menu.el-menu--horizontal {

+ 2 - 0
src/main.ts

@@ -17,6 +17,7 @@ import { getUpFileUrl, handleTree, selectDictLabel } from "/@/utils/common";
 import { useDict } from "/@/api/common/dict/data";
 // 分页组件
 import pagination from '/@/components/pagination/index.vue'
+import copy from '/@/components/copy/index.vue'
 // 引入百度地图组件
 // import BaiduMap from 'vue-baidu-map-3x'
 
@@ -32,6 +33,7 @@ directive(app);
 other.elSvg(app);
 
 app.component('pagination', pagination)
+app.component('copy', copy)
 app.use(router)
   .use(store, key)
   .use(ElementPlus, { i18n: i18n.global.t })

+ 12 - 0
src/utils/copy.ts

@@ -0,0 +1,12 @@
+import { copyText } from 'vue3-clipboard'
+import { ElMessage } from 'element-plus'
+
+export default function copy(text: string) {
+  copyText(text || '', undefined, (error: Error) => {
+    if (error) {
+      ElMessage.warning(`复制失败: ${error} !`);
+    } else {
+      ElMessage.success(`复制成功!`);
+    }
+  });
+}

+ 1 - 1
src/views/iot/alarm/log/component/detail.vue

@@ -24,7 +24,7 @@
           {{ ruleForm.createdAt }}
         </el-form-item>
         <el-form-item label="告警数据">
-          <JsonViewer style="width:100%;" :value="jsonData" boxed sort theme="jv-dark" @click="onKeyclick" />
+          <JsonViewer style="width:100%;" :value="jsonData" boxed sort theme="jv-dark" />
         </el-form-item>
 
         <el-form-item label="处理意见">

+ 1 - 1
src/views/iot/alarm/log/component/edit.vue

@@ -56,7 +56,7 @@ export default defineComponent({
 		});
 
 		// 打开弹窗
-		const openDialog = (row: RuleFormState | null) => {
+		const openDialog = (row: any) => {
 			resetForm();
 			api.log.detail(row.id).then((res: any) => {
 				state.ruleForm.id = res.data.id;

+ 29 - 37
src/views/iot/alarm/setting/component/edit.vue

@@ -8,7 +8,7 @@
 
 				<el-form-item label="告警级别" prop="level">
 					<el-radio-group v-model="ruleForm.level">
-						<el-radio :label="item.level" v-for="item in levelData" :key="item.level">{{ item.name }}</el-radio>
+						<el-radio :label="Number(item.value)" v-for="item in alarm_type" :key="item.value">{{ item.label }}</el-radio>
 					</el-radio-group>
 				</el-form-item>
 
@@ -41,11 +41,11 @@
 					<el-select v-model="ruleForm.eventKey" filterable placeholder="请选择事件" @change="eventTypeChange">
 						<el-option v-for="item in eventList" :key="item.key" :label="item.name" :value="item.key"></el-option>
 					</el-select>
-				
+
 				</el-form-item>
 
 
-				<div v-if="ruleForm.triggerType>2" >
+				<div v-if="ruleForm.triggerType > 2">
 					<el-divider content-position="left">触发条件</el-divider>
 					<div class="box-content">
 						<div v-for="(item, index) in requestParams" :key="index">
@@ -197,10 +197,11 @@ interface RuleFormState {
 	eventKey: string;
 	productKey: string;
 	deviceKey: string;
-	triggerCondition: any;
+	triggerCondition: any[];
 	action: any;
 }
 interface DicState {
+	id: number;
 	isShowDialog: boolean;
 	ruleForm: RuleFormState;
 	rules: any;
@@ -209,9 +210,7 @@ interface DicState {
 	typeData: any;
 	triData: any;
 	operData: any;
-	levelData: any;
 	requestParams: any;
-	triggerCondition: any;
 	action: any;
 	tempData: any;
 	sendGatewayData: any;
@@ -228,7 +227,8 @@ export default defineComponent({
 		const formRef = ref<HTMLElement | null>(null);
 		const { proxy } = getCurrentInstance() as any;
 
-		const { notice_send_gateway } = proxy.useDict('notice_send_gateway');
+		const { notice_send_gateway, alarm_type } = proxy.useDict('notice_send_gateway', 'alarm_type');
+
 		const state = reactive<DicState>({
 			id: 0,
 			isShowDialog: false,
@@ -312,11 +312,10 @@ export default defineComponent({
 			if (row) {
 				setType(true);
 
-
 				alarm.common.detail(row.id).then((res: any) => {
-					
+
 					state.requestParams = res.data.condition.triggerCondition;
-					let product_key=res.data.productKey;
+					let product_key = res.data.productKey;
 					res.data.performAction.action.forEach(function (value: { sendGateway: any; noticeConfig: number; }, index: string | number) {
 						notice.config.getList({ sendGateway: value.sendGateway }).then((res: any) => {
 							state.sendGatewayData[index] = res.Data;
@@ -334,21 +333,18 @@ export default defineComponent({
 							return { phone: p };
 						});
 					});
-					iotapi.product.event({key:res.data.productKey}).then((ress: any) => {
+					iotapi.product.event({ productKey: res.data.productKey }).then((ress: any) => {
 						state.eventList = ress || []
-						state.ruleForm.eventKey=row.eventKey
+						state.ruleForm.eventKey = row.eventKey
 					})
 					state.ruleForm = res.data;
 
-					if(product_key){
+					if (product_key) {
 						alarm.common.trigger_type(product_key).then((res: any) => {
 							state.typeData = res.list || [];
 						});
-						
 					}
 				});
-
-			
 			}
 			state.isShowDialog = true;
 		};
@@ -358,10 +354,7 @@ export default defineComponent({
 			iotapi.product.getLists({ status: 1 }).then((res: any) => {
 				state.productData = res.product || [];
 			});
-			alarm.common.levelall('').then((res: any) => {
-				state.levelData = res.list || [];
-			});
-			alarm.common.operator('').then((res: any) => {
+			alarm.common.operator().then((res: any) => {
 				state.operData = res.list || [];
 			});
 		};
@@ -399,6 +392,7 @@ export default defineComponent({
 				triggerType: 1,
 				level: '',
 				productKey: '',
+				eventKey: '',
 				deviceKey: '',
 				action: [
 					{
@@ -436,12 +430,12 @@ export default defineComponent({
 			gettriData()
 		};
 
-		watch(() => state.ruleForm.productKey, (key) => {
-			if (!key) return
+		watch(() => state.ruleForm.productKey, (productKey) => {
+			if (!productKey) return
 			// 切换产品时候重新获取事件列表,清空之前选中的事件
 			state.ruleForm.eventKey = ''
 
-			iotapi.product.event({ key }).then((res: any) => {
+			iotapi.product.event({ productKey }).then((res: any) => {
 				state.eventList = res || []
 			})
 		})
@@ -537,22 +531,16 @@ export default defineComponent({
 			});
 		};
 
-		const setType = (notResetDeviceKey: boolean) => {
+		const setType = (notResetDeviceKey?: boolean) => {
 			!notResetDeviceKey && (state.ruleForm.deviceKey = '')
-			let product_id = 0;
-			state.productData.forEach((item: { key: string; id: number; }) => {
-				if (item.key == state.ruleForm.productKey) {
-					product_id = item.id;
-				}
-			});
 
-			api.common.getdevList({ productId: product_id }).then((res: any) => {
+			api.common.getdevList({ productKey: state.ruleForm.deviceKey }).then((res: any) => {
 				state.sourceData = res.device;
 			});
 			alarm.common.trigger_type(state.ruleForm.productKey).then((res: any) => {
-						state.typeData = res.list || [];
-					});
-		
+				state.typeData = res.list || [];
+			});
+
 			gettriData();
 
 		};
@@ -583,7 +571,8 @@ export default defineComponent({
 			const triggerType = state.ruleForm.triggerType
 			const form = {
 				productKey: state.ruleForm.productKey,
-				triggerType
+				triggerType,
+				eventKey: ''
 			}
 
 			// 如果是事件上报,需要传eventKey参数
@@ -612,6 +601,7 @@ export default defineComponent({
 		};
 
 		return {
+			alarm_type,
 			getRadio,
 			gettriData,
 			getTem,
@@ -639,7 +629,8 @@ export default defineComponent({
 	},
 });
 </script>
-<style scoped>
+<style scoped lang="scss">
+
 .inline {
 	display: inline-flex;
 }
@@ -682,5 +673,6 @@ export default defineComponent({
 
 .jv-node {
 	margin-left: 25px;
-}</style>
+}
+</style>
  

+ 0 - 80
src/views/iot/alarm/setting/component/level.vue

@@ -1,80 +0,0 @@
-<template>
-	<div class="system-edit-dept-container">
-		<el-dialog title="设置告警级别" v-model="isShowDialog" width="769px">
-			<el-form ref="formRef" :model="ruleForm" :rules="rules" label-width="90px">
-				<el-row :gutter="35">
-					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20" v-for="(item, index) in levelData" :key="index">
-						<el-form-item :label="'级别' + item.level" prop="name" required>
-							<el-input v-model.trim="item.name" placeholder="请输入告警级别名称"></el-input>
-						</el-form-item>
-					</el-col>
-				</el-row>
-			</el-form>
-			<template #footer>
-				<span class="dialog-footer">
-					<el-button @click="onCancel">取 消</el-button>
-					<el-button type="primary" @click="onSubmit">设置</el-button>
-				</span>
-			</template>
-		</el-dialog>
-	</div>
-</template>
-
-<script lang="ts">
-import { reactive, toRefs, defineComponent, ref } from 'vue';
-import api from '/@/api/alarm';
-import { ElMessage } from 'element-plus';
-
-interface RuleFormState {
-	level: number;
-	name: string;
-}
-interface DeptSate {
-	isShowDialog: boolean;
-	levelData: RuleFormState[];
-}
-
-export default defineComponent({
-	name: 'level',
-	setup() {
-		const formRef = ref<HTMLElement | null>(null);
-		const state = reactive<DeptSate>({
-			isShowDialog: false,
-			levelData: [],
-		});
-
-		// 打开弹窗
-		const openDialog = () => {
-			api.common.level_all(1).then((res: any) => {
-				state.levelData = res.list || [];
-			});
-
-			state.isShowDialog = true;
-		};
-		// 关闭弹窗
-		const closeDialog = () => {
-			state.isShowDialog = false;
-		};
-		// 取消
-		const onCancel = () => {
-			closeDialog();
-		};
-		// 新增
-		const onSubmit = () => {
-			api.common.level_edit({ list: state.levelData }).then(() => {
-				ElMessage.success('修改成功');
-				closeDialog(); // 关闭弹窗
-			});
-		};
-
-		return {
-			openDialog,
-			closeDialog,
-			onCancel,
-			onSubmit,
-			formRef,
-			...toRefs(state),
-		};
-	},
-});
-</script>

+ 12 - 28
src/views/iot/alarm/setting/index.vue

@@ -8,12 +8,6 @@
 					</el-icon>
 					新增告警
 				</el-button>
-				<el-button type="primary" @click="onOpenLevel" v-auth="'level'">
-					<el-icon>
-						<ele-Setting />
-					</el-icon>
-					级别设置
-				</el-button>
 			</el-form-item>
 		</el-form>
 		<el-divider class="my-5" />
@@ -98,7 +92,6 @@
 		</el-row>
 		<pagination v-show="tableData.total > 0" :total="tableData.total" v-model:page="tableData.param.pageNum" v-model:limit="tableData.param.pageSize" @pagination="dataList" />
 		<EditDic ref="editDicRef" @dataList="dataList" />
-		<LevelDic ref="levelDicRef" @dataList="dataList" />
 	</div>
 </template>
 
@@ -106,35 +99,34 @@
 import { toRefs, reactive, onMounted, ref, defineComponent } from 'vue';
 import { ElMessageBox, ElMessage, FormInstance } from 'element-plus';
 import EditDic from './component/edit.vue';
-import LevelDic from './component/level.vue';
 import alarm from '/@/api/alarm';
 
 // 定义接口来定义对象的类型
 interface TableDataRow {
 	id: number;
+	status: number;
 	name: string;
 	key: string;
 	createBy: string;
 }
 interface TableDataState {
-	ids: number[];
 	tableData: {
-		data: Array<TableDataRow>;
+		data: any[];
 		total: number;
 		loading: boolean;
 		param: {
 			pageNum: number;
 			pageSize: number;
 			name: string;
-			level: number;
-			triggerType: number;
+			level: string;
+			triggerType: string;
 		};
 	};
 }
 
 export default defineComponent({
 	name: 'setlist',
-	components: { EditDic, LevelDic },
+	components: { EditDic },
 
 	setup() {
 		const addDicRef = ref();
@@ -174,9 +166,6 @@ export default defineComponent({
 		const onOpenAdd = () => {
 			editDicRef.value.openDialog();
 		};
-		const onOpenLevel = () => {
-			levelDicRef.value.openDialog();
-		};
 		// 打开修改模型弹窗
 		const onOpenEdit = (row: TableDataRow) => {
 			editDicRef.value.openDialog({ ...row });
@@ -187,24 +176,19 @@ export default defineComponent({
 		};
 		const onRowDel = (row?: TableDataRow) => {
 			let msg = '你确定要删除所选数据?';
-			let ids: number[] = [];
-			if (row) {
-				msg = `此操作将永久删除告警:“${row.name}”,是否继续?`;
-				ids = row.id;
-			} else {
-				ids = state.ids;
-			}
-			if (ids.length === 0) {
+			let ids: number[] | number = [];
+			if (!row?.id) {
 				ElMessage.error('请选择要删除的数据。');
 				return;
 			}
+			msg = `此操作将永久删除告警:“${row.name}”,是否继续?`;
 			ElMessageBox.confirm(msg, '提示', {
 				confirmButtonText: '确认',
 				cancelButtonText: '取消',
 				type: 'warning',
 			})
 				.then(() => {
-					alarm.common.delete(ids).then(() => {
+					alarm.common.delete(row.id).then(() => {
 						ElMessage.success('删除成功');
 						dataList();
 					});
@@ -221,8 +205,8 @@ export default defineComponent({
 			formEl.resetFields();
 			dataList();
 		};
-		const onActionStatus = (item: TableDataRow[]) => {
-			if (item.status == 0) {
+		const onActionStatus = (item: TableDataRow) => {
+			if (item.status === 0) {
 				alarm.common.deploy({ id: item.id }).then(() => {
 					dataList();
 				});
@@ -241,7 +225,6 @@ export default defineComponent({
 			queryRef,
 			levelDicRef,
 			onOpenRecord,
-			onOpenLevel,
 			onOpenAdd,
 			onOpenEdit,
 			onRowDel,
@@ -253,6 +236,7 @@ export default defineComponent({
 });
 </script>
 <style scoped lang="scss">
+
 .el-button.is-text:not(.is-disabled).is-has-bg {
 	background-color: var(--next-border-color-light);
 }

+ 2 - 2
src/views/iot/device-tree/tree/index.vue

@@ -377,11 +377,11 @@ export default defineComponent({
 </script>
 
 <style scoped lang="scss">
-.el-card ::v-deep(.el-card__body) {
+.el-card :deep(.el-card__body) {
   height: 100%;
 }
 
-.el-tree ::v-deep(.el-tree-node__label) {
+.el-tree :deep(.el-tree-node__label) {
   width: 100%;
   overflow: hidden;
   display: block;

+ 4 - 4
src/views/iot/device/channel/component/detail.vue

@@ -42,13 +42,13 @@
 						<el-table-column label="操作" align="center" width="200">
 							<template #default="{ row, $index }">
 								<el-button type="primary" size="small" @click="handleUpdate(row)"> 详情 </el-button>
-								<el-button v-if="row.status != 'deleted'" size="small" type="danger" @click="handleDelete(row, $index)"> 删除 </el-button>
+								<el-button v-if="row.status != 'deleted'" size="small" type="danger" @click="handleDelete(row)"> 删除 </el-button>
 							</template>
 						</el-table-column>
 					</el-table>
 
 					<pagination v-if="total > 0" :total="total" v-model:page="listQuery.page" v-model:limit="listQuery.size" @pagination="getList()" />
-					<TaskDialog ref="taskDialog" :formatOptions="formatOptions" @finish="getList(1)" />
+					<TaskDialog ref="taskDialog" :formatOptions="formatOptions" @finish="getList()" />
 				</el-tab-pane>
 				<el-tab-pane label="通道码流" name="3">
 					<div>
@@ -65,7 +65,7 @@
 </template>
 
 <script lang="ts">
-import { ElMessage } from 'element-plus';
+import { ElMessage, ElMessageBox } from 'element-plus';
 import api from '/@/api/device/modbus';
 import getOrigin from '/@/utils/origin';
 import TaskDialog from './taskDialog.vue';
@@ -168,7 +168,7 @@ export default {
 				});
 		},
 		handleDelete(row: any) {
-			this.$confirm('是否确认删除任务名称为"' + row.Job.title + '"的数据项?', '警告', {
+			ElMessageBox.confirm('是否确认删除任务名称为"' + row.Job.title + '"的数据项?', '警告', {
 				confirmButtonText: '确定',
 				cancelButtonText: '取消',
 				type: 'warning',

+ 5 - 3
src/views/iot/device/channel/component/taskDialog.vue

@@ -29,6 +29,7 @@
 </template>
 
 <script lang="ts">
+import { PropType } from 'vue';
 import api from '/@/api/device/modbus';
 import { ElMessage } from 'element-plus';
 
@@ -37,6 +38,7 @@ export default {
 	props: {
 		formatOptions: {
 			default: () => [],
+			type: Array as PropType<any[]>
 		},
 	},
 	data() {
@@ -57,17 +59,17 @@ export default {
 			},
 			dialogVisible: false,
 			listLoading: false,
-			dialogStatus: '',
+			dialogStatus: 'update' as 'update' | 'create',
 			textMap: {
 				update: '任务详情',
 				create: '添加任务',
 			},
-			templateOptions: '',
+			templateOptions: [] as any[],
 		};
 	},
 
 	methods: {
-		openDialog({ dialogStatus, row, deviceNumber }) {
+		openDialog({ dialogStatus, row, deviceNumber }: any) {
 			this.dialogStatus = dialogStatus;
 			this.temp.deviceNumber = deviceNumber;
 			if (row) {

+ 17 - 17
src/views/iot/device/instance/component/edit.vue

@@ -8,9 +8,9 @@
         <el-form-item label="设备名称" prop="name">
           <el-input v-model="ruleForm.name" placeholder="请输入设备名称" />
         </el-form-item>
-        <el-form-item label="所属产品" prop="productId">
-          <el-select v-model="ruleForm.productId" @change="productIdChange" :disabled="ruleForm.id" placeholder="请选择所属产品" class="w100">
-            <el-option v-for="item in productData" :key="item.id" :label="item.name" :value="item.id" />
+        <el-form-item label="所属产品" prop="productKey">
+          <el-select v-model="ruleForm.productKey" @change="productKeyChange" :disabled="ruleForm.id" placeholder="请选择所属产品" class="w100">
+            <el-option v-for="item in productData" :key="item.id" :label="item.name" :value="item.key" />
           </el-select>
         </el-form-item>
         <el-form-item label="设备坐标" prop="lng">
@@ -66,13 +66,13 @@
           <el-input v-model="intro" type="textarea" placeholder="请输入设备说明"></el-input>
         </el-form-item>
         <el-form-item label="设备图片">
-<!--					<upload-vue :imgs="phone" @set-imgs="setImgsPhone" :limit="deviceImgLimit"></upload-vue>-->
+          <!--					<upload-vue :imgs="phone" @set-imgs="setImgsPhone" :limit="deviceImgLimit"></upload-vue>-->
           <uploadVue :img="phone" @set-imgs="setImgsPhone"></uploadVue>
-				</el-form-item>
+        </el-form-item>
         <el-form-item label="证书图片">
-<!--					<upload-vue :imgs="certificate" @set-imgs="setImgsCertificate" :limit="deviceImgLimit"></upload-vue>-->
+          <!--					<upload-vue :imgs="certificate" @set-imgs="setImgsCertificate" :limit="deviceImgLimit"></upload-vue>-->
           <uploadVue :img="certificate" @set-imgs="setImgsCertificate"></uploadVue>
-				</el-form-item>
+        </el-form-item>
       </el-form>
       <template #footer>
         <span class="dialog-footer">
@@ -90,7 +90,7 @@
 import { reactive, toRefs, defineComponent, ref, unref, nextTick, onMounted } from 'vue';
 import api from '/@/api/device';
 import apiSystem from '/@/api/system';
-import {ElMessage, UploadProps} from "element-plus";
+import { ElMessage, UploadProps } from "element-plus";
 import tagVue from './tag.vue';
 import Map from './map.vue';
 import UploadVue from '/@/components/upload/index.vue';
@@ -101,7 +101,7 @@ interface RuleFormState {
   key: string;
   name: string;
   version: string;
-  productId: number | string;
+  productKey: string | string;
   tags: Tag[];
   lng: string;
   lat: string;
@@ -119,7 +119,7 @@ const form: RuleFormState = {
   id: 0,
   key: '',
   name: '',
-  productId: '',
+  productKey: '',
   tags: [],
   lng: '',
   lat: '',
@@ -163,7 +163,7 @@ export default defineComponent({
     const formRef = ref<HTMLElement | null>(null);
     const tagRef = ref<HTMLElement | null>(null);
     const mapRef = ref();
-    const certList = ref([])
+    const certList = ref<any[]>([])
     const state = reactive<DicState>({
       isShowDialog: false,
       product: {},
@@ -178,7 +178,7 @@ export default defineComponent({
         key: [
           { required: true, message: "设备标识不能为空", trigger: "blur" }
         ],
-        productId: [{ required: true, message: '所属产品不能为空', trigger: 'blur' }],
+        productKey: [{ required: true, message: '所属产品不能为空', trigger: 'blur' }],
       },
       deviceImgLimit: 0,
       certificateLimit: 0,
@@ -218,7 +218,7 @@ export default defineComponent({
         state.phone = row.extensionInfo ? JSON.parse(row.extensionInfo).phone : [];
         state.certificate = row.extensionInfo ? JSON.parse(row.extensionInfo).certificate : [];
         state.intro = row.extensionInfo ? JSON.parse(row.extensionInfo).intro : "";
-        productIdChange(row.productId as number)
+        productKeyChange(row.productKey as string)
       }
       state.isShowDialog = true;
     };
@@ -301,8 +301,8 @@ export default defineComponent({
     }
 
     // 所属产品变化的时候,更新产品详情
-    const productIdChange = (productId: number) => {
-      api.product.detail(productId).then((res: any) => {
+    const productKeyChange = (productKey: string) => {
+      api.product.detail(productKey).then((res: any) => {
         const { authType, authUser, authPasswd, accessToken, certificateId } = res.data
         state.product = res.data
         state.ruleForm.authType = authType
@@ -314,7 +314,7 @@ export default defineComponent({
     }
 
     //回调地图选点
-    const updateMap=(data:any)=>{
+    const updateMap = (data: any) => {
       state.ruleForm.lng = data.lng;
       state.ruleForm.lat = data.lat;
       state.ruleForm.address = data.address;
@@ -322,7 +322,7 @@ export default defineComponent({
 
     return {
       certList,
-      productIdChange,
+      productKeyChange,
       tagRef,
       selectMap,
       mapRef,

+ 18 - 25
src/views/iot/device/instance/component/excel.vue

@@ -3,16 +3,14 @@
     <el-dialog :title="(open_type === 'upload' ? '导入' : '导出') + '设备'" v-model="isShowDialog" width="769px">
       <el-form :model="ruleForm" ref="formRef" :rules="rules" label-width="110px">
 
-        <el-form-item label="所属产品" prop="productId">
-          <el-select v-model="ruleForm.productId" placeholder="请选择所属产品" class="w100">
-            <el-option v-for="item in productData" :key="item.id" :label="item.name" :value="item.id" />
+        <el-form-item label="所属产品" prop="productKey">
+          <el-select v-model="ruleForm.productKey" placeholder="请选择所属产品" class="w100">
+            <el-option v-for="item in productData" :key="item.key" :label="item.name" :value="item.key" />
           </el-select>
         </el-form-item>
 
         <el-form-item label="导入文件" prop="path" v-if="open_type === 'upload'">
-          <el-upload accept="xls,xlsx,csv" :show-file-list="true" 
-  :data="{ productId:ruleForm.productId }"  :limit="1" :headers="headers" :action="uploadUrl"
-            :on-success="updateImg" :before-upload="beforeAvatarUpload">
+          <el-upload accept="xls,xlsx,csv" :show-file-list="true" :data="{ productKey: ruleForm.productKey }" :limit="1" :headers="headers" :action="uploadUrl" :on-success="updateImg" :before-upload="beforeAvatarUpload">
             <el-button>
               <el-icon> <ele-Upload /> </el-icon>
               上传文件
@@ -21,10 +19,10 @@
           <div>{{ ruleForm.path }}</div>
         </el-form-item>
         <el-form-item label="样表下载" v-if="open_type === 'upload'">
-          <el-button  @click="down" type="primary" text="primary">
-              <el-icon> <ele-Download /> </el-icon>
-              下载文件
-            </el-button>
+          <el-button @click="down" type="primary" text="primary">
+            <el-icon> <ele-Download /> </el-icon>
+            下载文件
+          </el-button>
         </el-form-item>
       </el-form>
       <template #footer>
@@ -41,18 +39,18 @@
 <script lang="ts">
 import { reactive, toRefs, defineComponent, ref, unref, nextTick } from 'vue';
 import api from '/@/api/device';
-import { ElMessage,UploadProps } from "element-plus";
+import { ElMessage, UploadProps } from "element-plus";
 import downloadFile from '/@/utils/download';
 import getOrigin from '/@/utils/origin';
 
 
 interface RuleFormState {
-  productId: number | string;
+  productKey: number | string;
   path: string;
 }
 
 const form: RuleFormState = {
-  productId: '',
+  productKey: '',
   path: '',
 }
 
@@ -62,7 +60,6 @@ interface DicState {
   ruleForm: RuleFormState;
   rules: {}
   open_type: string;
-  sproductId: number;
 }
 
 
@@ -76,7 +73,6 @@ export default defineComponent({
     const formRef = ref<HTMLElement | null>(null);
     const tagRef = ref<HTMLElement | null>(null);
     const state = reactive<DicState>({
-      sproductId:0,
       isShowDialog: false,
       open_type: '',
       productData: [], // 分类数据
@@ -84,13 +80,13 @@ export default defineComponent({
         ...form
       },
       rules: {
-        productId: [{ required: true, message: '所属产品不能为空', trigger: 'blur' }],
+        productKey: [{ required: true, message: '所属产品不能为空', trigger: 'blur' }],
       }
     });
 
 
     const beforeAvatarUpload: UploadProps['beforeUpload'] = (rawFile) => {
-      if (!state.ruleForm.productId) {
+      if (!state.ruleForm.productKey) {
         ElMessage.error('请先选择所属产品!');
         return false;
       }
@@ -104,8 +100,8 @@ export default defineComponent({
     const updateImg = (res: any) => {
       if (res.code === 0) {
         ElMessage.success('导入成功');
-       closeDialog(); // 关闭弹窗
-       emit('typeList')
+        closeDialog(); // 关闭弹窗
+        emit('typeList')
 
       } else {
         ElMessage.error(res.message);
@@ -153,13 +149,10 @@ export default defineComponent({
               ElMessage.success('导入成功');
               closeDialog(); // 关闭弹窗
             });
-
-
           } else {
-            const selectedProduct = state.productData.find((item) => item.id === state.ruleForm.productId);
+            const selectedProduct = state.productData.find((item) => item.key === state.ruleForm.productKey);
             if (selectedProduct) {
-
-              api.device.export({ productId: state.ruleForm.productId }).then((res: any) => downloadFile(res, selectedProduct.name + "-" + getCurrentTime() + ".xlsx"))
+              api.device.export({ productKey: state.ruleForm.productKey }).then((res: any) => downloadFile(res, selectedProduct.name + "-" + getCurrentTime() + ".xlsx"))
               closeDialog(); // 关闭弹窗
             }
 
@@ -168,7 +161,7 @@ export default defineComponent({
         }
       });
     };
-    const down=()=>{
+    const down = () => {
       const fileURL = '/deviceImportExample.xlsx';
       // 创建下载链接
       const link = document.createElement('a');

+ 3 - 3
src/views/iot/device/instance/component/function.vue

@@ -54,7 +54,7 @@ getData()
 
 function getData() {
 	loading.value = true
-	api.tabDeviceFucntion.getList({ key: props.productKey }).then((res: IListItem[]) => {
+	api.tabDeviceFucntion.getList({ productKey: props.productKey }).then((res: IListItem[]) => {
 		if (!res) return
 		res.forEach((item) => (item.result = ''))
 		list.value = res
@@ -118,11 +118,11 @@ function clear(row: IListItem) {
 		flex: 2;
 	}
 
-	::v-deep(.el-textarea__inner) {
+	:deep(.el-textarea__inner) {
 		height: 100%;
 	}
 
-	::v-deep(.el-select) {
+	:deep(.el-select) {
 		width: 100%;
 	}
 }

+ 6 - 32
src/views/iot/device/instance/component/list.vue

@@ -27,43 +27,15 @@
 </template>
 
 <script lang="ts">
-import { reactive, toRefs, defineComponent, ref, unref } from 'vue';
+import { reactive, toRefs, defineComponent, ref } from 'vue';
 import { Close } from '@element-plus/icons-vue';
-
 import api from '/@/api/device';
-import { ElMessage } from 'element-plus';
-
-interface DicState {
-	isShowDialog: boolean;
-}
-
-// 定义接口来定义对象的类型
-interface TableDataRow {
-	id: number;
-	name: string;
-	key: string;
-
-	createBy: string;
-}
-interface TableDataState {
-	ids: number[];
-	tableData: {
-		data: Array<TableDataRow>;
-		total: number;
-		loading: boolean;
-		param: {
-			pageNum: number;
-			pageSize: number;
-      deviceKey: string;
-		};
-	};
-}
 
 export default defineComponent({
 	name: 'deviceEditPro',
 	setup(prop, { emit }) {
 		const formRef = ref<HTMLElement | null>(null);
-		const state = reactive<DicState>({
+		const state = reactive({
 			isShowDialog: false,
 			dialogFullScreen: false,
 			tableData: {
@@ -73,13 +45,13 @@ export default defineComponent({
 				param: {
 					pageNum: 1,
 					pageSize: 10,
-          deviceKey: '',
+					deviceKey: '',
 					propertyKey: '',
 				},
 			},
 		});
 		// 打开弹窗
-		const openDialog = (row: RuleFormState | null, deviceKey) => {
+		const openDialog = (row: any, deviceKey: string) => {
 			resetForm();
 			if (row) {
 				state.tableData.param.deviceKey = deviceKey;
@@ -107,6 +79,8 @@ export default defineComponent({
 				param: {
 					pageNum: 1,
 					pageSize: 10,
+					deviceKey: '',
+					propertyKey: '',
 				},
 			}
 		};

+ 4 - 4
src/views/iot/device/instance/component/map.vue

@@ -62,7 +62,7 @@ const openDialog = (row: any) => {
     const { BMapGL: theBMapGL, centerPoint } = await initMap()
 
     BMapGL = theBMapGL
-    
+
     map = new BMapGL.Map(mapContainer.value!);
 
     // 如果添加了经纬度则进入地图后还原上次地址
@@ -132,7 +132,7 @@ const setAddressByCoordinate = (lng: string | number, lat: string | number) => {
   // 创建地理编码实例, 并配置参数获取乡镇级数据
   const myGeo = new BMapGL.Geocoder({ extensions_town: true });
   // 根据坐标得到地址描述
-  myGeo.getLocation(new BMapGL.Point(lng, lat), function (result) {
+  myGeo.getLocation(new BMapGL.Point(lng, lat), function (result: any) {
     if (result) {
       address.value = result.content.poi_desc;
       if (oldAddress.value) {
@@ -141,7 +141,7 @@ const setAddressByCoordinate = (lng: string | number, lat: string | number) => {
     }
   });
 
-  // TODO旧查询经纬度方法
+  // 旧查询经纬度方法
   // const point = new BMapGL.Point(lng, lat);
   // const geocoder = new BMapGL.Geocoder();
   // geocoder.getPoint(point, (pointResult: any) => {
@@ -175,7 +175,7 @@ const searchByCoordinate = () => {
 const searchByKeyword = (keyword?: string) => {
   if (keyword) {
     const localSearch = new BMapGL.LocalSearch(map);
-    localSearch.setSearchCompleteCallback((searchResult) => {
+    localSearch.setSearchCompleteCallback((searchResult: any) => {
       if (searchResult) {
         const poi = searchResult.getPoi(0);
         if (poi) {

+ 1 - 2
src/views/iot/device/instance/component/setAttr.vue

@@ -53,7 +53,6 @@ const loading = ref(false)
 const typeData = ref<any[]>([])
 
 const form = {
-
   "key": "",
   "name": "",
   "accessMode": 0,
@@ -65,7 +64,7 @@ const form = {
   "value": ""
 }
 
-const data = reactive({
+const data = reactive<any>({
   ...form
 })
 

+ 13 - 910
src/views/iot/device/instance/component/subDevice.vue

@@ -1,920 +1,23 @@
 <template>
-	<div class="system-dic-container">
-		<el-dialog title="子设备详情" v-model="isShowSubDeviceDialog" width="80%">
-			<div class="content">
-				<div class="cont_box">
-					<div class="title">设备:{{ detail.name }}</div>
-					<div class="pro-status"><span :class="developer_status == 2 ? 'on' : 'off'"></span>{{ developer_status == 2 ? '在线' : '离线' }}</div>
-
-					<!-- <div class="pro-option" @click="CkOption">{{ developer_status == 2 ? '下线' : '上线' }}</div> -->
-				</div>
-			</div>
-
-			<div class="content-box">
-				<el-tabs v-model="activeName" @tab-click="handleClick">
-					<el-tab-pane label="运行状态" name="3">
-						<div style="display: flex; padding: 10px; flex-wrap: wrap">
-							<div class="ant-card">
-								<div class="ant-card-body">
-									<div class="cardflex">
-										<div>设备状态</div>
-										<div @click="getrunData()" style="cursor: pointer">
-											<el-icon style="font-size: 18px">
-												<ele-Refresh />
-											</el-icon>
-										</div>
-									</div>
-
-									<div class="statusname" v-if="areaData.status == 0">未启用</div>
-									<div class="statusname" v-if="areaData.status == 1">离线</div>
-									<div class="statusname" v-if="areaData.status == 2">在线</div>
-									<div class="cardflex comtest">
-										<div>数据时间</div>
-										<div>{{ areaData.lastOnlineTime || '未启用' }}</div>
-									</div>
-								</div>
-							</div>
-
-							<div class="ant-card" v-for="(item, index) in areaData.properties" :key="index">
-								<div class="ant-card-body">
-									<div class="cardflex">
-										<div>{{ item.name }}</div>
-										<div style="cursor: pointer">
-											<el-icon style="font-size: 18px" @click="getrunData()">
-												<ele-Refresh />
-											</el-icon>
-											<el-icon style="font-size: 18px; margin-left: 10px" @click="onOpenListDetail(item)">
-												<ele-Expand />
-											</el-icon>
-										</div>
-									</div>
-
-									<div class="statusname">{{ item.value }}{{ item.unit }}</div>
-									<div>
-										<devantd :json="item.list" :antdid="item.key" v-if="item.type == 'int' || item.type == 'float'" />
-									</div>
-								</div>
-							</div>
-						</div>
-					</el-tab-pane>
-					<el-tab-pane label="设备信息" name="1">
-						<div class="pro-box">
-							<div class="protitle">设备信息</div>
-							<div>
-								<el-button type="primary" v-auth="'edit'" @click="onOpenEditDic(detail)">编辑</el-button>
-							</div>
-						</div>
-
-						<div class="ant-descriptions-view">
-							<table>
-								<tbody>
-									<tr class="ant-descriptions-row">
-										<th class="ant-descriptions-item-label ant-descriptions-item-colon">设备标识</th>
-										<td class="ant-descriptions-item-content" colspan="1">{{ detail.key }}</td>
-										<th class="ant-descriptions-item-label ant-descriptions-item-colon">设备名称</th>
-										<td class="ant-descriptions-item-content" colspan="1">{{ detail.name }}</td>
-										<th class="ant-descriptions-item-label ant-descriptions-item-colon">所属产品</th>
-										<td class="ant-descriptions-item-content" colspan="1">{{ detail.productName }}</td>
-									</tr>
-									<tr class="ant-descriptions-row">
-										<th class="ant-descriptions-item-label ant-descriptions-item-colon">消息协议</th>
-										<td class="ant-descriptions-item-content" colspan="1">{{ prodetail.messageProtocol }}</td>
-										<th class="ant-descriptions-item-label ant-descriptions-item-colon">链接协议</th>
-										<td class="ant-descriptions-item-content" colspan="1">{{ prodetail.transportProtocol }}</td>
-										<th class="ant-descriptions-item-label ant-descriptions-item-colon">设备类型</th>
-										<td class="ant-descriptions-item-content" colspan="1">{{ prodetail.deviceType }}</td>
-									</tr>
-									<tr class="ant-descriptions-row">
-										<th class="ant-descriptions-item-label ant-descriptions-item-colon">固件版本</th>
-										<td class="ant-descriptions-item-content" colspan="1">{{ prodetail.version }}</td>
-										<th class="ant-descriptions-item-label ant-descriptions-item-colon">注册时间</th>
-										<td class="ant-descriptions-item-content" colspan="1">{{ detail.updatedAt }}</td>
-										<th class="ant-descriptions-item-label ant-descriptions-item-colon">最后上线时间</th>
-										<td class="ant-descriptions-item-content" colspan="1">{{ detail.lastOnlineTime || '' }}</td>
-									</tr>
-									<tr class="ant-descriptions-row">
-										<th class="ant-descriptions-item-label ant-descriptions-item-colon">说明</th>
-										<td class="ant-descriptions-item-content" colspan="5">{{ detail.desc }}</td>
-									</tr>
-								</tbody>
-							</table>
-						</div>
-					</el-tab-pane>
-					<el-tab-pane label="物模型" name="2">
-						<div class="wu-box">
-							<el-tabs type="border-card" v-model="activetab" @tab-click="wuhandleClick">
-								<el-tab-pane label="属性定义" name="attr">
-									<div class="wu-title">
-										<div class="title">属性定义</div>
-										<div>
-											<el-button type="primary" @click="onOpenEditAttr()">添加</el-button>
-										</div>
-									</div>
-
-									<el-table style="width: 100%" :data="tableData.data" v-if="activetab == 'attr'">
-										<el-table-column label="属性标识" align="center" prop="key" />
-										<el-table-column label="属性名称" prop="name" show-overflow-tooltip />
-										<el-table-column prop="valueType" label="数据类型" width="100" align="center">
-											<template #default="scope">
-												<span>{{ scope.row.valueType?.type }}</span>
-											</template>
-										</el-table-column>
-										<el-table-column prop="decimals" label="精度" width="60" align="center">
-											<template #default="scope">
-												<span>{{ scope.row.valueType.decimals }}</span>
-											</template>
-										</el-table-column>
-										<el-table-column prop="unit" label="单位" width="60" align="center">
-											<template #default="scope">
-												<span>{{ scope.row.valueType.unit }}</span>
-											</template>
-										</el-table-column>
-										<el-table-column prop="accessMode" label="是否只读" width="120" align="center">
-											<template #default="scope">
-												<el-tag type="info" size="small" v-if="scope.row.accessMode">只读</el-tag>
-												<el-tag type="success" size="small" v-else>读写</el-tag>
-											</template>
-										</el-table-column>
-										<el-table-column label="说明" prop="desc" show-overflow-tooltip />
-										<el-table-column label="操作" width="300" align="center" fixed="right">
-											<template #default="scope">
-												<el-button size="small" text type="warning" @click="onEditAttr(scope.row)">修改</el-button>
-												<el-button size="small" text type="danger" @click="onRowDel(scope.row.key, 'attr')">删除</el-button>
-											</template>
-										</el-table-column>
-									</el-table>
-								</el-tab-pane>
-								<el-tab-pane label="功能定义" name="fun">
-									<div class="wu-title">
-										<div class="title">功能定义</div>
-										<div>
-											<el-button type="primary" @click="onOpenEditFun()">添加</el-button>
-										</div>
-									</div>
-
-									<el-table style="width: 100%" :data="tableData.data" v-if="activetab == 'fun'">
-										<el-table-column label="功能标识" align="center" prop="key" />
-										<el-table-column label="名称" prop="name" show-overflow-tooltip />
-
-										<el-table-column label="描述" prop="desc" show-overflow-tooltip />
-										<el-table-column label="操作" width="300" align="center" fixed="right">
-											<template #default="scope">
-												<el-button size="small" text type="warning" @click="onEditFun(scope.row)">修改</el-button>
-												<el-button size="small" text type="danger" @click="onRowDel(scope.row.key, 'fun')">删除</el-button>
-											</template>
-										</el-table-column>
-									</el-table>
-								</el-tab-pane>
-								<el-tab-pane label="事件定义" name="event">
-									<div class="wu-title">
-										<div class="title">事件定义</div>
-										<div>
-											<el-button size="small" type="primary" @click="onOpenEditEvent()">添加</el-button>
-										</div>
-									</div>
-
-									<el-table style="width: 100%" :data="tableData.data" v-if="activetab == 'event'">
-										<el-table-column label="事件标识" align="center" prop="key" />
-										<el-table-column label="名称" prop="name" show-overflow-tooltip />
-										<el-table-column prop="level" label="事件级别" width="120" align="center">
-											<template #default="scope">
-												<el-tag type="primary" size="small" v-if="scope.row.level == 0">普通</el-tag>
-												<el-tag type="warning" size="small" v-if="scope.row.level == 1">警告</el-tag>
-												<el-tag type="danger" size="small" v-if="scope.row.level == 2">紧急</el-tag>
-											</template>
-										</el-table-column>
-										<el-table-column label="描述" prop="desc" show-overflow-tooltip />
-
-										<el-table-column label="操作" width="300" align="center" fixed="right">
-											<template #default="scope">
-												<el-button size="small" text type="warning" @click="onEditEvent(scope.row)">修改</el-button>
-												<el-button size="small" text type="danger" @click="onRowDel(scope.row.key, 'event')">删除</el-button>
-											</template>
-										</el-table-column>
-									</el-table>
-								</el-tab-pane>
-								<el-tab-pane label="标签定义" name="tab">
-									<div class="wu-title">
-										<div class="title">标签定义</div>
-										<div>
-											<el-button type="primary" @click="onOpenEditTab()">添加</el-button>
-										</div>
-									</div>
-
-									<el-table style="width: 100%" :data="tableData.data" v-if="activetab == 'tab'">
-										<el-table-column label="属性标识" align="center" prop="key" />
-										<el-table-column label="属性名称" prop="name" show-overflow-tooltip />
-										<el-table-column prop="valueType" label="数据类型" width="120" align="center">
-											<template #default="scope">
-												<span>{{ scope.row.valueType.type }}</span>
-											</template>
-										</el-table-column>
-										<el-table-column prop="accessMode" label="是否只读" width="120" align="center">
-											<template #default="scope">
-												<el-tag type="info" size="small" v-if="scope.row.accessMode">只读</el-tag>
-												<el-tag type="success" size="small" v-else>读写</el-tag>
-											</template>
-										</el-table-column>
-										<el-table-column label="描述" prop="desc" show-overflow-tooltip />
-										<el-table-column label="操作" width="300" align="center" fixed="right">
-											<template #default="scope">
-												<el-button size="small" text type="warning" @click="onEditTag(scope.row)">修改</el-button>
-												<el-button size="small" text type="danger" @click="onRowDel(scope.row.key, 'tab')">删除</el-button>
-											</template>
-										</el-table-column>
-									</el-table>
-								</el-tab-pane>
-							</el-tabs>
-							<pagination
-								v-show="tableData.total > 0"
-								:total="tableData.total"
-								v-model:page="tableData.param.pageNum"
-								v-model:limit="tableData.param.pageSize"
-								@pagination="getList()"
-							/>
-						</div>
-					</el-tab-pane>
-					<el-tab-pane label="设备功能" name="5">
-						<functionCom :device-key="detail.key" :product-key="prodetail.key" v-if="detail.key && prodetail.key"></functionCom>
-					</el-tab-pane>
-					<el-tab-pane label="日志管理" name="4">
-						<div class="system-user-search mb15">
-							<el-form :model="logtableData.param" ref="queryRef" inline label-width="68px">
-								<el-form-item label="日志类型" prop="types">
-									<el-select v-model="logtableData.param.types" placeholder="日志类型" clearable>
-										<el-option v-for="item in logTypeData" :key="item" :label="item" :value="item" />
-									</el-select>
-								</el-form-item>
-
-								<el-form-item label="创建时间" prop="dateRange">
-									<el-date-picker
-										v-model="logtableData.param.dateRange"
-										size="default"
-										value-format="YYYY-MM-DD"
-										type="daterange"
-										range-separator="-"
-										start-placeholder="开始日期"
-										end-placeholder="结束日期"
-									></el-date-picker>
-								</el-form-item>
-								<el-form-item>
-									<el-button type="primary" class="ml10" @click="getlog">
-										<el-icon>
-											<ele-Search />
-										</el-icon>
-										查询
-									</el-button>
-									<el-button @click="resetQuery(queryRef)">
-										<el-icon>
-											<ele-Refresh />
-										</el-icon>
-										重置
-									</el-button>
-								</el-form-item>
-							</el-form>
-						</div>
-						<el-table style="width: 100%" :data="logtableData.data">
-							<el-table-column label="类型" align="center" prop="type" />
-							<el-table-column label="时间" prop="ts" show-overflow-tooltip />
-
-							<el-table-column label="内容" prop="content" show-overflow-tooltip />
-							<el-table-column label="操作" width="300" align="center" fixed="right">
-								<template #default="scope">
-									<el-button size="small" text type="warning" @click="onLogDetail(scope.row)">查看</el-button>
-								</template>
-							</el-table-column>
-						</el-table>
-
-						<pagination
-							v-show="logtableData.total > 0"
-							:total="logtableData.total"
-							v-model:page="logtableData.param.pageNum"
-							v-model:limit="logtableData.param.pageSize"
-							@pagination="getlog"
-						/>
-					</el-tab-pane>
-				</el-tabs>
-			</div>
-		</el-dialog>
-
-		<EditDic ref="editDicRef" @typeList="typeList" />
-		<EditAttr ref="editAttrRef" @typeList="getproperty" />
-		<EditFun ref="editFunRef" @typeList="getfunction" />
-		<EditEvent ref="editEventRef" @typeList="getevent" />
-		<EditTab ref="editTabRef" @typeList="gettab" />
-		<ListDic ref="listDicRef" />
-
-		<el-dialog v-model="dialogVisible" title="返回Json数据" width="30%">
-			<JsonViewer :value="jsonData" boxed sort theme="jv-dark" @click="onKeyclick" />
-
-			<template #footer>
-				<span class="dialog-footer">
-					<el-button @click="dialogVisible = false">关闭</el-button>
-				</span>
-			</template>
-		</el-dialog>
-	</div>
+	<el-dialog title="子设备详情" v-model="showDialog" fullscreen width="80%">
+		<DetailVue :deviceKey="deviceKey" v-if="showDialog"></DetailVue>
+	</el-dialog>
 </template>
-<script lang="ts">
-import { toRefs, reactive, onMounted, ref, defineComponent } from 'vue'
-import { ElMessageBox, ElMessage, FormInstance } from 'element-plus'
-import functionCom from './function.vue'
-
-import 'vue3-json-viewer/dist/index.css'
-
-import EditDic from '../../product/component/editPro.vue'
-import EditAttr from '../../product/component/editAttr.vue'
-import EditFun from '../../product/component/editFun.vue'
-import EditEvent from '../../product/component/editEvent.vue'
-import EditTab from '../../product/component/editTab.vue'
-import devantd from '/@/components/devantd/index.vue'
-import ListDic from './list.vue'
-
-import { useRoute } from 'vue-router'
+<script lang="ts" setup>
+import { ref } from 'vue';
+import DetailVue from '../detail.vue';
 
-import api from '/@/api/device'
+const showDialog = ref(false)
+const deviceKey = ref('')
 
-interface TableDataState {
-	ids: number[]
-	deviceIds: number[]
-    detail: object[]
-    isShowSubDeviceDialog: boolean
-	deviceTableData: {
-		data: []
-		total: number
-		loading: boolean
-		param: {
-			pageNum: number
-			pageSize: number
-			gatewayKey: string
-			// status: string;
-			dateRange: string[]
-		}
-	}
-	tableData: {
-		data: []
-		total: number
-		loading: boolean
-		param: {
-			pageNum: number
-			pageSize: number
-			name: string
-			deviceType: string
-			status: string
-			dateRange: string[]
-		}
-	}
-	logtableData: {
-		data: []
-		total: number
-		loading: boolean
-		param: {
-			pageNum: number
-			pageSize: number
-			name: string
-			deviceType: string
-			status: string
-			dateRange: string[]
-		}
-	}
+function openDialog(row: any) {
+	deviceKey.value = row.key
+	showDialog.value = true
 }
-export default defineComponent({
-	name: 'deviceEditPro',
-	components: { EditDic, EditAttr, EditFun, EditEvent, EditTab, devantd, ListDic, functionCom },
-
-	setup(prop, context) {
-		const route = useRoute()
-		const editDicRef = ref()
-		const editAttrRef = ref()
-		const editFunRef = ref()
-		const listDicRef = ref()
-		const editEventRef = ref()
-		const editTabRef = ref()
-		const state = reactive<TableDataState>({
-			deviceIds: [],
-			areaData: [],
-			isShowDialog: false,
-			dialogVisible: false,
-            isShowSubDeviceDialog: false,
-			logTypeData: [],
-			jsonData: '',
-			activeName: '3', // 分类数据
-			activetab: 'attr', // 分类数据
-			detail: [],
-			prodetail: [],
-			product_id: 0,
-			developer_status: 0,
-			deviceTableData: {
-				data: [],
-				total: 0,
-				loading: false,
-				param: {
-					pageNum: 1,
-					gatewayKey: '',
-					pageSize: 10,
-					dateRange: [],
-				},
-			},
-			tableData: {
-				data: [],
-				total: 0,
-				loading: false,
-				param: {
-					pageNum: 1,
-					productId: 0,
-					pageSize: 10,
-					status: '',
-					dateRange: [],
-				},
-			},
-			logtableData: {
-				data: [],
-				total: 0,
-				loading: false,
-				param: {
-					pageNum: 1,
-					productId: 0,
-					pageSize: 10,
-					status: '',
-					dateRange: [],
-				},
-			},
-		})
-
-		const getDeviceTableData = () => {
-			state.deviceTableData.param.gatewayKey = state.detail.key
-			api.device.getList(state.deviceTableData.param).then((res: any) => {
-				state.deviceTableData.data = res.list
-				state.deviceTableData.total = res.Total
-			})
-		}
-
-		// 多选框选中数据
-		const handleSelectionChange = (selection: any[]) => {
-			state.deviceIds = selection.map((item) => item.id)
-		}
-		// 打开弹窗
-		const openDialog = (row: any | null) => {
-			if (row) {
-                const ids = row.id;
-                api.instance.detail(ids).then((res: any) => {
-                    state.detail = res.data;
-                    state.developer_status = res.data.status;
-                    state.tableData.param.productId = res.data.product.id;
-                    state.product_id = res.data.product.id;
-                    getrunData();
-                    api.product.detail(res.data.product.id).then((productRes: any) => {
-                        state.prodetail = productRes.data;
-                    });
-                    //第一次加载
-                    api.model.property(state.tableData.param).then((modelRes: any) => {
-                        state.tableData.data = modelRes.Data;
-                        state.tableData.total = modelRes.Total;
-                    });
-                    getDeviceTableData()
-                });
-			}
-			  state.isShowSubDeviceDialog = true;
-		}
-
-		const onLogDetail = (row: TableDataRow) => {
-			state.jsonData = JSON.parse(row.content)
-			state.dialogVisible = true
-		}
-
-		//编辑属性
-		const onEditAttr = (row: TableDataRow) => {
-			editAttrRef.value.openDialog(row, state.product_id)
-		}
-
-		//编辑功能
-		const onEditFun = (row: TableDataRow) => {
-			editFunRef.value.openDialog(row, state.product_id)
-		}
-
-		//编辑事件
-		const onEditEvent = (row: TableDataRow) => {
-			editEventRef.value.openDialog(row, state.product_id)
-		}
-
-		//编辑标签
-		const onEditTag = (row: TableDataRow) => {
-			editTabRef.value.openDialog(row, state.product_id)
-		}
-
-		//打开添加属性弹窗
-		const onOpenEditAttr = () => {
-			editAttrRef.value.openDialog({ product_id: state.product_id, id: 0, accessMode: 0 })
-		}
-
-		//打开添加功能弹窗
-		const onOpenEditFun = () => {
-			editFunRef.value.openDialog({ product_id: state.product_id, id: 0 })
-		}
-		//打开添加事件弹窗
-		const onOpenEditEvent = () => {
-			editEventRef.value.openDialog({ product_id: state.product_id, id: 0, level: 0 })
-		}
-
-		//打开添加事件弹窗
-		const onOpenEditTab = () => {
-			editTabRef.value.openDialog({ product_id: state.product_id, id: 0, accessMode: 0 })
-		}
-
-		//查看日志列表
-		const onOpenListDetail = (row: TableDataRow) => {
-			listDicRef.value.openDialog(row, state.detail.id)
-		}
-
-		// 打开修改产品弹窗
-		const onOpenEditDic = (row: TableDataRow) => {
-			editDicRef.value.openDialog(row)
-		}
-
-		// 删除产品
-		const onRowDel = (key, type) => {
-			let msg = `此操作将永久删除该数据,是否继续?`
-
-			if (key.length === 0) {
-				ElMessage.error('请选择要删除的数据。')
-				return
-			}
-			ElMessageBox.confirm(msg, '提示', {
-				confirmButtonText: '确认',
-				cancelButtonText: '取消',
-				type: 'warning',
-			})
-				.then(() => {
-					if (type == 'attr') {
-						api.model.propertydel(state.product_id, key).then(() => {
-							ElMessage.success('删除成功')
-							getproperty()
-						})
-					}
-					if (type == 'fun') {
-						api.model.functiondel(state.product_id, key).then(() => {
-							ElMessage.success('删除成功')
-							getfunction()
-						})
-					}
-					if (type == 'event') {
-						api.model.eventdel(state.product_id, key).then(() => {
-							ElMessage.success('删除成功')
-							getevent()
-						})
-					}
-					if (type == 'tab') {
-						api.model.tagdel(state.product_id, key).then(() => {
-							ElMessage.success('删除成功')
-							tagdel()
-						})
-					}
-				})
-				.catch(() => {})
-		}
-
-		//根据不同类型获取列表
-		const getList = () => {
-			switch (state.activetab) {
-				case 'attr':
-					getproperty()
-					break
-				case 'fun':
-					getfunction()
-					break
-				case 'event':
-					getevent()
-					break
-				case 'tab':
-					gettab()
-					break
-			}
-		}
-
-		const getproperty = () => {
-			api.model.property(state.tableData.param).then((res: any) => {
-				state.tableData.data = res.Data
-				state.tableData.total = res.Total
-			})
-		}
-
-		const getfunction = () => {
-			api.model.function(state.tableData.param).then((res: any) => {
-				state.tableData.data = res.Data
-				state.tableData.total = res.Total
-			})
-		}
-		const getevent = () => {
-			api.model.event(state.tableData.param).then((res: any) => {
-				state.tableData.data = res.Data
-				state.tableData.total = res.Total
-			})
-		}
-
-		const gettab = () => {
-			api.model.tag(state.tableData.param).then((res: any) => {
-				state.tableData.data = res.Data
-				state.tableData.total = res.Total
-			})
-		}
-
-		const wuhandleClick = (tab: TabsPaneContext) => {
-			state.activetab = tab.props.name
-			switch (tab.props.name) {
-				case 'attr':
-					getproperty()
-					break
-				case 'fun':
-					getfunction()
-					break
-				case 'event':
-					getevent()
-					break
-				case 'tab':
-					gettab()
-					break
-			}
-		}
 
-		const handleClick = (tab: TabsPaneContext, event: Event) => {
-			if (tab.props.name == 4) {
-				//获取日志
-				getlog()
-				getlogtype()
-			} else if (tab.props.name == 2) {
-				getList()
-			} else if (tab.props.name == 3) {
-				getrunData()
-			}
-		}
+defineExpose({ openDialog })
 
-		const getrunData = () => {
-			api.instance.getrun_status({ id: state.detail.id }).then((res: any) => {
-				state.areaData = res
-				let properties = state.areaData.properties || []
-
-				var temp = new Array()
-
-				properties.forEach(function (item, index) {
-					let datalist = item.list || []
-					temp[index] = []
-					var temps = new Array()
-					datalist.forEach(function (a, b) {
-						if (b < 15) {
-							temps.push(a)
-						}
-					})
-					temp[index]['name'] = item.name
-					temp[index]['key'] = item.key
-					temp[index]['type'] = item.type
-					temp[index]['unit'] = item.unit
-					temp[index]['value'] = item.value
-					temp[index]['list'] = temps
-				})
-
-				state.areaData.properties = temp
-			})
-		}
-
-		const getlogtype = () => {
-			api.instance.getlogcate({}).then((res: any) => {
-				state.logTypeData = res.list
-			})
-		}
-
-		const getlog = () => {
-			state.logtableData.param.deviceKey = state.detail.key
-			api.instance.getLogList(state.logtableData.param).then((res: any) => {
-				state.logtableData.data = res.list
-				state.logtableData.total = res.Total
-			})
-		}
-
-		const CkOption = () => {
-			if (state.developer_status == 2) {
-				api.instance.devoffline({ id: state.detail.id }).then((res: any) => {
-					ElMessage.success('操作成功')
-					state.developer_status = 1
-				})
-			} else {
-				api.instance.devonline({ id: state.detail.id }).then((res: any) => {
-					ElMessage.success('操作成功')
-					state.developer_status = 2
-				})
-			}
-		}
-		const tinyAreas = () => {
-			var data = state.data
-
-			const tinyArea = new TinyArea('container', {
-				height: 60,
-				autoFit: false,
-				data,
-				smooth: true,
-				areaStyle: {
-					fill: '#d6e3fd',
-				},
-			})
-			tinyArea.render()
-		}
-		return {
-			tinyAreas,
-			editDicRef,
-			editAttrRef,
-			listDicRef,
-			editFunRef,
-			editEventRef,
-			editTabRef,
-			onOpenListDetail,
-			getrunData,
-			getlog,
-			getlogtype,
-			onLogDetail,
-			CkOption,
-			onRowDel,
-			onEditFun,
-			onEditEvent,
-			onEditTag,
-			onEditAttr,
-			getList,
-			getproperty,
-			getDeviceTableData,
-			handleSelectionChange,
-			getfunction,
-			getevent,
-			gettab,
-			wuhandleClick,
-            openDialog,
-			onOpenEditTab,
-			onOpenEditEvent,
-			onOpenEditAttr,
-			onOpenEditFun,
-			onOpenEditDic,
-			handleClick,
-			...toRefs(state),
-		}
-	},
-})
 </script>
-  <style scoped>
-.content {
-	width: 100%;
-	padding: 20px;
-}
-.content-box {
-	width: 100%;
-	padding: 20px;
-}
-.cont_box {
-	display: flex;
-}
-.cont_box .title {
-	font-size: 24px;
-}
-.cont_box .pro-status {
-	line-height: 40px;
-	margin-left: 30px;
-}
-.cont_box .pro-status .on {
-	background: #52c41a;
-}
-.cont_box .pro-status .off {
-	background: #c41a1a;
-}
-.cont_box .pro-status span {
-	position: relative;
-	top: -1px;
-	display: inline-block;
-	width: 6px;
-	height: 6px;
-	vertical-align: middle;
-	border-radius: 50%;
-	margin-right: 5px;
-}
-.cont_box .pro-option {
-	line-height: 40px;
-	margin-left: 10px;
-	color: #1890ff;
-	cursor: pointer;
-}
-.content-box .pro-box {
-	display: flex;
-	padding: 10px;
-	justify-content: space-between;
-}
-.content-box .pro-box .protitle {
-	font-size: 18px;
-	font-weight: bold;
-	line-height: 35px;
-}
-.content-box .pro-box .buttonedit {
-	border: 0px;
-	color: #1890ff;
-}
-table {
-	border-collapse: collapse;
-	text-indent: initial;
-	border-spacing: 2px;
-}
-tbody {
-	box-sizing: border-box;
-	display: table-row-group;
-	vertical-align: middle;
-	border-color: inherit;
-}
-
-tr {
-	display: table-row;
-	vertical-align: inherit;
-	border-color: inherit;
-}
-.ant-descriptions-view {
-	width: 100%;
-	overflow: hidden;
-	border-radius: 4px;
-}
-.ant-descriptions-view {
-	border: 1px solid #e8e8e8;
-}
-.ant-descriptions-view table {
-	width: 100%;
-	table-layout: fixed;
-}
-.ant-descriptions-view > table {
-	table-layout: auto;
-}
-.ant-descriptions-row {
-	border-bottom: 1px solid #e8e8e8;
-}
-.ant-descriptions-item-label {
-	color: rgba(0, 0, 0, 0.85);
-	font-weight: 400;
-	font-size: 14px;
-	line-height: 1.5;
-}
-.ant-descriptions-item-label {
-	padding: 16px 24px;
-	border-right: 1px solid #e8e8e8;
-}
-.ant-descriptions-item-label {
-	background-color: #fafafa;
-}
-.ant-descriptions-item-content {
-	padding: 16px 24px;
-	border-right: 1px solid #e8e8e8;
-	display: table-cell;
-	color: rgba(0, 0, 0, 0.65);
-	font-size: 14px;
-	line-height: 1.5;
-}
-.wu-box {
-	border: #e8e8e8 solid 1px;
-	padding: 20px;
-	width: 100%;
-}
-.wu-box .wu-title {
-	display: flex;
-	flex-direction: row;
-	justify-content: space-between;
-	padding: 20px;
-	border-bottom: #e8e8e8 1px solid;
-}
-.wu-box .wu-title .title {
-	font-size: 18px;
-}
-.ant-card {
-	box-sizing: border-box;
-	margin: 10px;
-	width: 23.2%;
-	font-size: 14px;
-	font-variant: tabular-nums;
-	border: 1px solid var(--next-border-color-light);
-
-	line-height: 1.5;
-	list-style: none;
-	font-feature-settings: 'tnum';
-	position: relative;
-	border-radius: 2px;
-	transition: all 0.3s;
-}
-.ant-card-body {
-	padding: 24px;
-	zoom: 1;
-}
-.cardflex {
-	display: flex;
-	justify-content: space-between;
-}
-.statusname {
-	font-size: 30px;
-	margin-top: 10px;
-	margin-bottom: 15px;
-}
-.comtest {
-	margin-top: 20px;
-	height: 30px;
-	line-height: 30px;
-}
-</style>
+<style scoped></style>
 
 

+ 19 - 17
src/views/iot/device/instance/component/subDeviceMutipleBind.vue

@@ -2,9 +2,9 @@
 	<div class="mutiple-bind-dialog-wrap">
 		<el-dialog title="批量绑定子设备" v-model="isShowDialog" width="90%">
 			<el-form :model="ruleForm" ref="formRef" :rules="rules" size="small" label-width="110px">
-				<el-form-item label="所属产品" prop="productId">
-					<el-select @change="handleChange" v-model="ruleForm.productId" placeholder="请选择所属产品" style="width: 300px;">
-						<el-option v-for="item in productData" :key="item.id" :label="item.name" :value="item.id" />
+				<el-form-item label="所属产品" prop="productKey">
+					<el-select @change="handleChange" v-model="ruleForm.productKey" placeholder="请选择所属产品" style="width: 300px;">
+						<el-option v-for="item in productData" :key="item.key" :label="item.name" :value="item.key" />
 					</el-select>
 					<el-button style="margin-left: 20px;" :disabled="!deviceKeyList.length" v-auth="'mutipleBind'" type="primary" @click="confirmBind()">批量绑定</el-button>
 
@@ -12,7 +12,11 @@
 			</el-form>
 			<el-table :data="tableData.data" style="width: 100%" @selection-change="handleSelectionChange" v-loading="tableData.loading">
 				<el-table-column type="selection" width="55" align="center" />
-				<el-table-column label="标识" prop="key" width="130" show-overflow-tooltip v-col="'key'" />
+				<el-table-column label="标识" prop="key" width="130" show-overflow-tooltip v-col="'key'">
+					<template #default="{ row }">
+						<copy :text="row.key"></copy>
+					</template>
+				</el-table-column>
 				<el-table-column label="设备名称" prop="name" show-overflow-tooltip v-col="'name'" />
 				<el-table-column label="产品名称" prop="productName" show-overflow-tooltip v-col="'productName'" />
 
@@ -54,13 +58,13 @@ interface TableDataState {
 		param: {
 			pageNum: number
 			pageSize: number
-			productId: number
+			productKey: number
 			status: string
 			dateRange: string[]
 		}
 	},
 	ruleForm: {
-		productId: string | number
+		productKey: string | number
 	},
 	rules: {}
 }
@@ -81,21 +85,21 @@ export default defineComponent({
 				param: {
 					pageNum: 1,
 					pageSize: 10,
-					productId: 0,
+					productKey: 0,
 					status: '',
 					dateRange: [],
 				},
 			},
 			ruleForm: {
-				productId: ''
+				productKey: ''
 			},
 			rules: {
-				productId: [{ required: true, message: '所属产品不能为空', trigger: 'blur' }],
+				productKey: [{ required: true, message: '所属产品不能为空', trigger: 'blur' }],
 			}
 		})
 
 		const getDeviceList = () => {
-			if (!state.ruleForm.productId) {
+			if (!state.ruleForm.productKey) {
 				state.tableData.data = [];
 				state.tableData.total = 0;
 				return;
@@ -103,21 +107,19 @@ export default defineComponent({
 
 			state.tableData.loading = true;
 			api.device.getSubList({
-				"productId": state.ruleForm.productId,
+				"productKey": state.ruleForm.productKey,
 				"pageSize": state.tableData.param.pageSize,
 				"pageNum": state.tableData.param.pageNum
 			}).then((res: any) => {
 				state.tableData.data = res.device;
 				state.tableData.total = res.Total;
 			}).finally(() => (state.tableData.loading = false));
-
 		};
 
 		const getProductList = () => {
 			api.product.getSubList().then((res: any) => {
-				let productDataList = res.product
-				state.productData = productDataList;
-				state.ruleForm.productId = state.productData[0].id
+				state.productData = res.product;
+				state.ruleForm.productKey = res.product[0].key
 				getDeviceList()
 				state.isShowDialog = true;
 			});
@@ -156,8 +158,8 @@ export default defineComponent({
 				})
 		};
 
-		const handleChange = (productId: number) => {
-			state.ruleForm.productId = productId;
+		const handleChange = (productKey: number) => {
+			state.ruleForm.productKey = productKey;
 			getDeviceList()
 		}
 

+ 1 - 1
src/views/iot/device/instance/component/tag.vue

@@ -23,7 +23,7 @@
 <script lang="ts" setup>
 import { reactive, ref, getCurrentInstance } from 'vue';
 
-const { proxy } = getCurrentInstance()
+const { proxy } = getCurrentInstance() as any
 
 interface Tag {
   key: string;

+ 77 - 131
src/views/iot/device/instance/detail.vue

@@ -1,17 +1,14 @@
 <template>
   <div class="page bg page-full">
     <div class="content">
-      <div class="cont_box">
+      <div class="cont_box" style="align-items: center;">
         <div class="title">设备:{{ detail.name }}</div>
-        <div class="pro-status"><span :class="developer_status == 2 ? 'on' : 'off'"></span>{{ developer_status == 2 ? '在线'
-          : '离线' }}</div>
-        <!-- <div class="pro-option" @click="CkOption">{{ developer_status == 2 ? '下线' : '上线' }}</div> -->
+        <el-tag :type="developer_status == 2 ? 'success' : 'danger'" style="margin-left: 20px;">{{ developer_status == 2 ? '在线' : '离线' }}</el-tag>
       </div>
     </div>
 
     <div class="content-box page-full-part page-full">
       <el-tabs v-model="activeName" @tab-click="handleClick">
-
         <el-tab-pane label="运行状态" name="3">
           <div style=" display: flex;flex-wrap: wrap;">
             <div class="ant-card">
@@ -78,10 +75,12 @@
           </div>
 
           <el-descriptions class="margin-top" :column="3" border>
-            <el-descriptions-item label="设备标识">{{ detail.key }}</el-descriptions-item>
+            <el-descriptions-item label="设备标识">
+              <copy :text="detail.key"></copy>
+            </el-descriptions-item>
             <el-descriptions-item label="设备名称">{{ detail.name }}</el-descriptions-item>
             <el-descriptions-item label="所属产品">
-              <router-link :to="'/iotmanager/device/product/detail/' + prodetail.id" class="link-type">{{
+              <router-link :to="'/iotmanager/device/product/detail/' + prodetail.key" class="link-type">{{
                 detail.productName }} </router-link>
             </el-descriptions-item>
             <el-descriptions-item label="消息协议">{{ prodetail.messageProtocol }}</el-descriptions-item>
@@ -241,7 +240,6 @@
                   <el-option v-for="item in logTypeData" :key="item" :label="item" :value="item" />
                 </el-select>
               </el-form-item>
-
               <el-form-item label="创建时间" prop="dateRange">
                 <el-date-picker v-model="logtableData.param.dateRange" value-format="YYYY-MM-DD" type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker>
               </el-form-item>
@@ -284,10 +282,13 @@
                 <el-button v-auth="'cancleMutipleBind'" :disabled="!deviceKeyList.length" type="primary" @click="mutipleUnbind()">批量解绑</el-button>
               </div>
             </div>
-
             <el-table :data="deviceTableData.data" style="width: 100%" @selection-change="handleSelectionChange" v-loading="deviceTableData.loading">
               <el-table-column type="selection" width="55" align="center" />
-              <el-table-column label="标识" prop="key" width="130" show-overflow-tooltip />
+              <el-table-column label="标识" prop="key" width="130" show-overflow-tooltip>
+                <template #default="{ row }">
+                  <copy :text="row.key"></copy>
+                </template>
+              </el-table-column>
               <el-table-column label="设备名称" prop="name" show-overflow-tooltip />
               <el-table-column label="产品名称" prop="productName" show-overflow-tooltip />
 
@@ -314,38 +315,6 @@
         </el-tab-pane>
         <el-tab-pane label="设备档案" name="7" v-if="deviceAssetData">
           <el-form label-width="110px">
-
-            <!--            <FromData :DataList="Datalist" v-if="Datalist && Datalist.length > 0" disable="true"></FromData>-->
-            <!--            <div class="pro-box">-->
-            <!--              <div class="protitle">设备档案</div>-->
-            <!--              <div>-->
-            <!--                <el-button type="primary" v-auth="'edit'" @click="onOpenEditAsset">编辑</el-button>-->
-            <!--              </div>-->
-            <!--            </div>-->
-
-            <!--            <div class="ant-descriptions-view">-->
-            <!--              <table>-->
-            <!--                <tbody>-->
-            <!--                <tr class="ant-descriptions-row" v-for="(item, index) in dataList" :key="index">-->
-            <!--                  <th class="ant-descriptions-item-label ant-descriptions-item-colon">{{ item.title }}</th>-->
-            <!--                  <td class="ant-descriptions-item-content" colspan="1">-->
-            <!--                    <view v-if="item.types === 'file'">-->
-            <!--                      <img :src="deviceAssetMetadata[item.name]" class="avatar" />-->
-            <!--                    </view>-->
-            <!--                    <view v-else>-->
-            <!--                      <view v-if="item.pattern">-->
-            <!--                        <el-link :href="deviceAssetMetadata[item.name]" type="primary" target="_blank">{{ deviceAssetMetadata[item.name] }}</el-link>-->
-            <!--                      </view>-->
-            <!--                      <view v-else>-->
-            <!--                        {{ deviceAssetMetadata[item.name] }}-->
-            <!--                      </view>-->
-            <!--                    </view>-->
-            <!--                  </td>-->
-            <!--                </tr>-->
-            <!--                </tbody>-->
-            <!--              </table>-->
-            <!--            </div>-->
-
             <div class="pro-box">
               <div class="protitle">设备档案</div>
               <div>
@@ -370,12 +339,8 @@
                 </el-descriptions-item>
               </view>
             </el-descriptions>
-
           </el-form>
         </el-tab-pane>
-
-
-
       </el-tabs>
     </div>
     <EditDic ref="editDicRef" @typeList="initData" />
@@ -392,7 +357,7 @@
     <EditAssetRef ref="editAssetRef" @getList="getDeviceAssetMetadata"></EditAssetRef>
 
     <el-dialog v-model="dialogVisible" title="日志数据内容" width="30%">
-      <JsonViewer :value="jsonData" boxed sort theme="jv-dark" @click="onKeyclick" />
+      <JsonViewer :value="jsonData" boxed sort theme="jv-dark" />
 
       <template #footer>
         <span class="dialog-footer">
@@ -403,12 +368,11 @@
   </div>
 </template>
 <script lang="ts">
-import { toRefs, reactive, onMounted, ref, defineComponent, nextTick } from 'vue';
+import { toRefs, reactive, onMounted, ref, defineComponent, nextTick, onUnmounted } from 'vue';
 import { ElMessageBox, ElMessage, FormInstance } from 'element-plus';
 import functionCom from './component/function.vue';
 import 'vue3-json-viewer/dist/index.css';
 import EditDic from './component/edit.vue';
-// import EditDic from '../product/component/editPro.vue';
 import EditAttr from '../product/component/editAttr.vue';
 import EditFun from '../product/component/editFun.vue';
 import EditEvent from '../product/component/editEvent.vue';
@@ -426,23 +390,22 @@ import EditAssetRef from "/@/views/iot/property/dossier/edit.vue";
 import { useRoute } from 'vue-router';
 
 interface TableDataState {
+  isShowDialog: boolean;
+  dialogVisible: boolean;
   phone: any[];
   certificate: any[];
+  logTypeData: any[];
+  prodetail: any;
+  areaData: any;
+  activetab: string;
+  activeName: string;
+  productKey: string;
+  jsonData: string;
   intro: string;
-  ids: number[];
+  developer_status: number;
   detail: any;
   deviceKeyList: string[];
-  deviceTableData: {
-    data: [];
-    total: number;
-    loading: boolean;
-    param: {
-      pageNum: number;
-      pageSize: number;
-      gatewayKey: string;
-      dateRange: string[];
-    };
-  };
+  deviceTableData: any;
   tableData: {
     data: [];
     total: number;
@@ -454,27 +417,28 @@ interface TableDataState {
       deviceType: string;
       status: string;
       dateRange: string[];
-    };
+    } | any;
   };
   logtableData: {
     data: [];
     total: number;
     loading: boolean;
-    param: {
-      pageNum: number;
-      pageSize: number;
-      name: string;
-      deviceType: string;
-      status: string;
-      dateRange: string[];
-    };
+    param: any;
   };
 }
 export default defineComponent({
   name: 'deviceEditPro',
   components: { EditAssetRef, FromData, SubDeviceMutipleBind, SubDevice, EditDic, EditAttr, EditFun, EditEvent, EditTab, devantd, ListDic, functionCom, setAttr },
 
-  setup(prop, context) {
+  props: {
+    deviceKey: String
+  },
+  setup(props, context) {
+
+    let timer: any
+
+    onUnmounted(() => clearInterval(timer))
+
     const logqueryRef = ref();
 
     // 属性列表,查询保留小数位使用
@@ -494,7 +458,7 @@ export default defineComponent({
     const editAssetRef = ref();
     const dataList = ref();
     const deviceAssetData = ref();
-    const deviceAssetMetadata = ref({});
+    const deviceAssetMetadata = ref<any>({});
     const state = reactive<TableDataState>({
       certificate: [],
       phone: [],
@@ -509,7 +473,7 @@ export default defineComponent({
       activetab: 'attr', // 分类数据
       detail: {},
       prodetail: [],
-      product_id: 0,
+      productKey: '',
       developer_status: 0,
       deviceTableData: {
         data: [],
@@ -528,7 +492,7 @@ export default defineComponent({
         loading: false,
         param: {
           pageNum: 1,
-          productId: 0,
+          productKey: '',
           pageSize: 10,
           status: '',
           dateRange: [],
@@ -540,7 +504,7 @@ export default defineComponent({
         loading: false,
         param: {
           pageNum: 1,
-          productId: 0,
+          productKey: '',
           pageSize: 10,
           status: '',
           dateRange: [],
@@ -553,14 +517,13 @@ export default defineComponent({
     });
 
     function initData() {
-
-      const ids = route.params && route.params.id;
-      api.instance.detail(ids).then((res: any) => {
+      // 如果是嵌入的就是子设备,看子设备详情,否则看页面参数
+      api.instance.detail(props.deviceKey || route.params?.id).then((res: any) => {
         state.detail = res.data;
         state.developer_status = res.data.status;
-        state.tableData.param.productId = res.data.product.id;
-        state.product_id = res.data.product.id;
-        api.product.detail(res.data.product.id).then((res: any) => {
+        state.tableData.param.productKey = res.data.product.key;
+        state.productKey = res.data.product.key;
+        api.product.detail(res.data.product.key).then((res: any) => {
           state.prodetail = res.data;
         });
 
@@ -570,7 +533,7 @@ export default defineComponent({
         state.intro = intro
 
         //加载全部属性
-        datahub.node.getpropertyList({ key: state.detail.product.key }).then((re: any) => {
+        datahub.node.getpropertyList({ productKey: state.detail.product.key }).then((re: any) => {
           array_list.value = re;
           re.forEach((item: any) => propertyMap.set(item.key, item?.valueType));
         });
@@ -580,6 +543,8 @@ export default defineComponent({
 
         getrunData();
 
+        timer = setInterval(getrunData, 3000)
+
         getDeviceTableData()
       });
     }
@@ -591,7 +556,7 @@ export default defineComponent({
         api.dev_asset.detail({ deviceKey: state.detail.key }).then((resde: any) => {
           // 存储设备档案信息
           deviceAssetData.value = resde;
-          const newArray = resde.data.map(obj => {
+          const newArray = (resde?.data || []).map((obj: any) => {
             const { name, value, ...rest } = obj;
             const newObj = { name, value, ...rest };
             newObj[name] = value ? value : '';
@@ -672,7 +637,7 @@ export default defineComponent({
 
     };
 
-    const onLogDetail = (row: TableDataRow) => {
+    const onLogDetail = (row: any) => {
       state.jsonData = JSON.parse(row.content);
       state.dialogVisible = true;
     };
@@ -683,51 +648,51 @@ export default defineComponent({
 
 
     //编辑属性
-    const onEditAttr = (row: TableDataRow) => {
-      editAttrRef.value.openDialog(row, state.product_id);
+    const onEditAttr = (row: any) => {
+      editAttrRef.value.openDialog(row, state.productKey);
     };
 
     //编辑功能
-    const onEditFun = (row: TableDataRow) => {
-      editFunRef.value.openDialog(row, state.product_id);
+    const onEditFun = (row: any) => {
+      editFunRef.value.openDialog(row, state.productKey);
     };
 
     //编辑事件
-    const onEditEvent = (row: TableDataRow) => {
-      editEventRef.value.openDialog(row, state.product_id);
+    const onEditEvent = (row: any) => {
+      editEventRef.value.openDialog(row, state.productKey);
     };
 
     //编辑标签
-    const onEditTag = (row: TableDataRow) => {
-      editTabRef.value.openDialog(row, state.product_id);
+    const onEditTag = (row: any) => {
+      editTabRef.value.openDialog(row, state.productKey);
     };
 
     //打开添加属性弹窗
     const onOpenEditAttr = () => {
-      editAttrRef.value.openDialog({ product_id: state.product_id, id: 0, accessMode: 0 });
+      editAttrRef.value.openDialog({ productKey: state.productKey, id: 0, accessMode: 0 });
     };
 
     //打开添加功能弹窗
     const onOpenEditFun = () => {
-      editFunRef.value.openDialog({ product_id: state.product_id, id: 0 });
+      editFunRef.value.openDialog({ productKey: state.productKey, id: 0 });
     };
     //打开添加事件弹窗
     const onOpenEditEvent = () => {
-      editEventRef.value.openDialog({ product_id: state.product_id, id: 0, level: 0 });
+      editEventRef.value.openDialog({ productKey: state.productKey, id: 0, level: 0 });
     };
 
     //打开添加事件弹窗
     const onOpenEditTab = () => {
-      editTabRef.value.openDialog({ product_id: state.product_id, id: 0, accessMode: 0 });
+      editTabRef.value.openDialog({ productKey: state.productKey, id: 0, accessMode: 0 });
     };
 
     //查看日志列表
-    const onOpenListDetail = (row: TableDataRow) => {
+    const onOpenListDetail = (row: any) => {
       listDicRef.value.openDialog(row, state.detail.key);
     };
 
     // 打开修改产品弹窗
-    const onOpenEditDic = (row: TableDataRow) => {
+    const onOpenEditDic = (row: any) => {
       editDicRef.value.openDialog(row);
     };
 
@@ -737,7 +702,7 @@ export default defineComponent({
     };
 
     // 删除产品
-    const onRowDel = (key, type) => {
+    const onRowDel = (key: string, type: string) => {
       let msg = `此操作将永久删除该数据,是否继续?`;
 
       if (key.length === 0) {
@@ -751,27 +716,27 @@ export default defineComponent({
       })
         .then(() => {
           if (type == 'attr') {
-            api.model.propertydel(state.product_id, key).then(() => {
+            api.model.propertydel(state.productKey, key).then(() => {
               ElMessage.success('删除成功');
               getproperty();
             });
           }
           if (type == 'fun') {
-            api.model.functiondel(state.product_id, key).then(() => {
+            api.model.functiondel(state.productKey, key).then(() => {
               ElMessage.success('删除成功');
               getfunction();
             });
           }
           if (type == 'event') {
-            api.model.eventdel(state.product_id, key).then(() => {
+            api.model.eventdel(state.productKey, key).then(() => {
               ElMessage.success('删除成功');
               getevent();
             });
           }
           if (type == 'tab') {
-            api.model.tagdel(state.product_id, key).then(() => {
+            api.model.tagdel(state.productKey, key).then(() => {
               ElMessage.success('删除成功');
-              tagdel();
+              gettab();
             });
           }
         })
@@ -825,7 +790,7 @@ export default defineComponent({
       });
     };
 
-    const wuhandleClick = (tab: TabsPaneContext) => {
+    const wuhandleClick = (tab: any) => {
       state.activetab = tab.props.name;
       switch (tab.props.name) {
         case 'attr':
@@ -843,7 +808,7 @@ export default defineComponent({
       }
     };
 
-    const handleClick = (tab: TabsPaneContext, event: Event) => {
+    const handleClick = (tab: any, event: Event) => {
       if (tab.props.name == 4) {
         //获取日志
         getlog();
@@ -874,8 +839,8 @@ export default defineComponent({
         return value;
       }
     }
-    const getStatusText = (name, value) => {
-      let data = array_list.value;
+    const getStatusText = (name: any, value: string) => {
+      let data = array_list.value as any;
       for (let i = 0; i < data.length; i++) {
         const field = data[i];
         if (field.valueType.type === "object") {
@@ -883,7 +848,7 @@ export default defineComponent({
             const property = field.valueType.properties[j];
             if (property.key === name) {
               if (property.valueType.type === "enum") {
-                const element = property.valueType.elements.find((element) => element.value === value);
+                const element = property.valueType.elements.find((element: any) => element.value === value);
                 if (element) {
                   return `${property.name}: ${element.text}`;
                 } else {
@@ -896,7 +861,7 @@ export default defineComponent({
           }
         } else if (field.key === name) {
           if (field.valueType.type === "enum") {
-            const element = field.valueType.elements.find((element) => element.value === value);
+            const element = field.valueType.elements.find((element: any) => element.value === value);
             if (element) {
               return `${field.name}: ${element.text}`;
             }
@@ -918,13 +883,13 @@ export default defineComponent({
 
         var temp = new Array();
 
-        properties.forEach(function (item, index) {
+        properties.forEach(function (item: any, index: number) {
 
           let datalist = item.list || [];
           temp[index] = [];
           var temps = new Array();
 
-          datalist.forEach(function (a, b) {
+          datalist.forEach(function (a: any, b: number) {
             if (b < 15) {
               temps.push(a);
             }
@@ -933,10 +898,6 @@ export default defineComponent({
             item.value = JSON.parse(item.value);
           }
 
-
-
-
-
           temp[index]['name'] = item.name
           temp[index]['key'] = item.key
           temp[index]['type'] = item.type
@@ -982,20 +943,6 @@ export default defineComponent({
         });
       }
     };
-    const tinyAreas = () => {
-      var data = state.data;
-
-      const tinyArea = new TinyArea('container', {
-        height: 60,
-        autoFit: false,
-        data,
-        smooth: true,
-        areaStyle: {
-          fill: '#d6e3fd',
-        },
-      });
-      tinyArea.render();
-    }
     const onlineTimeoutUpdate = () => {
       if (!state.detail.onlineTimeout) return ElMessage('请先输入设备超时时间')
       api.device.updateOnlineTimeout({ id: state.detail.id, onlineTimeout: state.detail.onlineTimeout }).then(() => {
@@ -1014,7 +961,6 @@ export default defineComponent({
       getValueText,
       onlineTimeoutUpdate,
       setAttr,
-      tinyAreas,
       setAttrRef,
       editDicRef,
       editAttrRef,

+ 33 - 27
src/views/iot/device/instance/index.vue

@@ -9,9 +9,9 @@
           <el-form-item label="标识" prop="key">
             <el-input v-model="tableData.param.key" placeholder="请输入设备标识" clearable style="width: 165px" @keyup.enter.native="typeList" />
           </el-form-item>
-          <el-form-item label="所属产品" prop="productId">
-            <el-select v-model="tableData.param.productId" style="width: 140px" filterable placeholder="请选择产品">
-              <el-option v-for="item in productData" :key="item.id" :label="item.name" :value="item.id.toString()" value-key="id"> </el-option>
+          <el-form-item label="所属产品" prop="productKey">
+            <el-select v-model="tableData.param.productKey" style="width: 140px" filterable placeholder="请选择产品">
+              <el-option v-for="item in productData" :key="item.key" :label="item.name" :value="item.key" value-key="id"> </el-option>
             </el-select>
           </el-form-item>
 
@@ -99,7 +99,11 @@
       </div>
       <el-table :data="tableData.data" style="width: 100%" @selection-change="handleSelectionChange" v-loading="tableData.loading">
         <el-table-column type="selection" width="55" align="center" />
-        <el-table-column label="标识" prop="key" min-width="150" show-overflow-tooltip v-col="'key'" />
+        <el-table-column label="标识" prop="key" min-width="150" show-overflow-tooltip v-col="'key'">
+          <template #default="{ row }">
+            <copy :text="row.key"></copy>
+          </template>
+        </el-table-column>
         <el-table-column label="设备名称" prop="name" min-width="160" show-overflow-tooltip v-col="'name'" />
         <el-table-column label="设备类型" prop="product.deviceType" min-width="120" align="center" show-overflow-tooltip v-col="'deviceType'" />
         <el-table-column label="产品名称" prop="productName" min-width="120" align="center" show-overflow-tooltip v-col="'productName'" />
@@ -115,7 +119,7 @@
 
         <el-table-column label="操作" width="180" align="center" fixed="right">
           <template #default="scope">
-            <router-link :to="'/iotmanager/device/instance/' + scope.row.id" class="link-type" style="padding-right: 12px;font-size: 12px;color: #409eff;" v-auth="'detail'">
+            <router-link :to="'/iotmanager/device/instance/' + scope.row.key" class="link-type" style="padding-right: 12px;font-size: 12px;color: #409eff;" v-auth="'detail'">
               <span>详情</span>
             </router-link>
             <el-button size="small" text type="warning" @click="onOpenEditDic(scope.row)" v-auth="'edit'">修改</el-button>
@@ -151,7 +155,7 @@ interface TableDataRow {
   createBy: string;
 }
 interface TableDataState {
-  ids: number[];
+  keys: string[];
   productData: Array<TableDataRow>;
   tableData: {
     data: Array<TableDataRow>;
@@ -162,7 +166,7 @@ interface TableDataState {
       pageSize: number;
       name: string;
       key: string;
-      productId: string;
+      productKey: string;
       status: string;
       dateRange: string[];
     };
@@ -180,7 +184,7 @@ export default defineComponent({
     const queryRef = ref();
     const batchLoading = ref(false);
     const state = reactive<TableDataState>({
-      ids: [],
+      keys: [],
       productData: [],
       tableData: {
         data: [],
@@ -191,6 +195,7 @@ export default defineComponent({
           pageSize: 10,
           name: '',
           key: '',
+          productKey: '',
           status: '',
           dateRange: [],
         },
@@ -234,13 +239,13 @@ export default defineComponent({
 
     //批量启用
     const setDeviceStatus1 = (row?: TableDataRow) => {
-      let ids: number[] = [];
+      let keys: string[] = [];
       if (row) {
-        ids = [row.id];
+        keys = [row.key];
       } else {
-        ids = state.ids;
+        keys = state.keys;
       }
-      if (ids.length === 0) {
+      if (keys.length === 0) {
         ElMessage.error('请选择要操作的数据。');
         return;
       }
@@ -251,7 +256,7 @@ export default defineComponent({
       })
         .then(() => {
           batchLoading.value = true
-          api.device.setDeviceStatus({ ids: ids, status: 1 }).then(() => {
+          api.device.setDeviceStatus({ ids: keys, status: 1 }).then(() => {
             ElMessage.success('启用成功');
             typeList();
           }).finally(() => batchLoading.value = false)
@@ -261,13 +266,13 @@ export default defineComponent({
 
     //批量禁用
     const setDeviceStatus0 = (row?: TableDataRow) => {
-      let ids: number[] = [];
+      let keys: string[] = [];
       if (row) {
-        ids = [row.id];
+        keys = [row.key];
       } else {
-        ids = state.ids;
+        keys = state.keys;
       }
-      if (ids.length === 0) {
+      if (keys.length === 0) {
         ElMessage.error('请选择要操作的数据。');
         return;
       }
@@ -278,7 +283,7 @@ export default defineComponent({
       })
         .then(() => {
           batchLoading.value = true
-          api.device.setDeviceStatus({ ids: ids, status: 0 }).then(() => {
+          api.device.setDeviceStatus({ ids: keys, status: 0 }).then(() => {
             ElMessage.success('禁用成功');
             typeList();
           }).finally(() => batchLoading.value = false)
@@ -288,14 +293,14 @@ export default defineComponent({
     // 删除产品
     const onRowDel = (row?: TableDataRow) => {
       let msg = '你确定要删除所选数据?';
-      let ids: number[] = [];
+      let keys: string[] = [];
       if (row) {
         msg = `此操作将永久删除设备:“${row.name}”,是否继续?`;
-        ids = [row.id];
+        keys = [row.key];
       } else {
-        ids = state.ids;
+        keys = state.keys;
       }
-      if (ids.length === 0) {
+      if (keys.length === 0) {
         ElMessage.error('请选择要删除的数据。');
         return;
       }
@@ -305,7 +310,7 @@ export default defineComponent({
         type: 'warning',
       })
         .then(() => {
-          api.instance.del(ids).then(() => {
+          api.instance.del(keys).then(() => {
             ElMessage.success('删除成功');
             typeList();
           });
@@ -324,16 +329,17 @@ export default defineComponent({
     };
     // 多选框选中数据
     const handleSelectionChange = (selection: TableDataRow[]) => {
-      state.ids = selection.map((item) => item.id);
+      state.keys = selection.map((item) => item.key);
     };
-    const onActionStatus = (item: TableDataRow[]) => {
+
+    const onActionStatus = (item: TableDataRow) => {
       if (item.status == 0) {
-        api.instance.devdeploy({ id: item.id }).then((res: any) => {
+        api.instance.devdeploy(item.key).then((res: any) => {
           typeList();
           ElMessage.success(res.message || '操作成功');
         });
       } else {
-        api.instance.devundeploy({ id: item.id }).then((res: any) => {
+        api.instance.devundeploy(item.key).then((res: any) => {
           typeList();
           ElMessage.success(res.message || '操作成功');
         });

+ 3 - 3
src/views/iot/device/product/component/dataParse.vue

@@ -51,7 +51,7 @@ function saveCode() {
 
 function toSave(data: string) {
 	api.product.script({
-		id: route.params.id,
+		key: route.params.id,
 		scriptInfo: data
 	}).then(() => {
 		ElMessage.success('保存成功')
@@ -84,13 +84,13 @@ function mock() {
 }
 </script>
 <style lang="scss" scoped>
-::v-deep(.CodeMirror) {
+:deep(.CodeMirror) {
 	height: calc(100vh - 320px);
 }
 
 .input,
 .output {
-	::v-deep(.el-textarea__inner) {
+	:deep(.el-textarea__inner) {
 		height: calc(50vh - 170px);
 	}
 }

+ 7 - 7
src/views/iot/device/product/component/editAttr.vue

@@ -199,7 +199,7 @@ import { validateNoSpace } from '/@/utils/validator';
 
 interface RuleFormState {
 	id: number;
-	productId: number;
+	productKey: string;
 	name: string;
 	dictType: string;
 	valueType: Object;
@@ -224,7 +224,7 @@ export default defineComponent({
 			typeData: [], //
 			type: '',
 			types: '',
-			productId: 0,
+			productKey: '',
 			valueType: {
 				type: '',
 				maxLength: '',
@@ -248,7 +248,7 @@ export default defineComponent({
 
 			ruleForm: {
 				id: 0,
-				productId: 0,
+				productKey: '',
 				name: '',
 				key: '',
 				transportProtocol: '',
@@ -273,7 +273,7 @@ export default defineComponent({
 		});
 
 		// 打开弹窗
-		const openDialog = (row: RuleFormState | null, productId: number | null) => {
+		const openDialog = (row: RuleFormState | null, productKey: string | null) => {
 			resetForm();
 
 			api.product.getDataType({ status: -1 }).then((res: any) => {
@@ -293,7 +293,7 @@ export default defineComponent({
 			if (row.valueType) {
 				state.ruleForm = row;
 
-				state.productId = productId;
+				state.productKey = productKey;
 				state.valueType = row.valueType;
 				state.ruleForm.valueType.type = row.valueType.type;
 				state.ruleForm.type = row.valueType.type;
@@ -377,7 +377,7 @@ export default defineComponent({
 		}
 
 		const addJson = () => {
-			editOptionRef.value.openDialog({ product_id: 0, id: 0 });
+			editOptionRef.value.openDialog({ productKey: '', id: 0 });
 		};
 		const getOptionData = (data) => {
 			state.jsondata.push(data);
@@ -425,7 +425,7 @@ export default defineComponent({
 						}
 
 						state.ruleForm.valueType = state.valueType;
-						state.ruleForm.productId = state.productId
+						state.ruleForm.productKey = state.productKey
 						api.model.propertyedit(state.ruleForm).then(() => {
 							ElMessage.success('属性定义类型修改成功');
 							closeDialog(); // 关闭弹窗

+ 59 - 46
src/views/iot/device/product/component/editEvent.vue

@@ -24,7 +24,7 @@
 							<div>参数名称:{{ item.name }}</div>
 							<div>数据类型:{{ item.valueType.type }}</div>
 							<div class="jsonoption">
-								<el-link type="primary"  @click="editjson(index, 'fun')">编辑</el-link>
+								<el-link type="primary" @click="editjson(index, 'fun')">编辑</el-link>
 								<el-link type="primary" @click="deljson(index, 'fun')">删除</el-link>
 							</div>
 						</div>
@@ -32,7 +32,9 @@
 
 					<div style="display: block; width: 100%">
 						<div class="input-options" @click="addJson('fun')">
-							<el-icon><Plus /></el-icon>
+							<el-icon>
+								<Plus />
+							</el-icon>
 							<div>添加参数</div>
 						</div>
 					</div>
@@ -59,25 +61,42 @@ import api from '/@/api/device';
 import { Plus, Minus, Right } from '@element-plus/icons-vue';
 import EditOption from './editOption.vue';
 import { validateNoSpace } from '/@/utils/validator';
-
-import { ElMessage, UploadProps } from 'element-plus';
+import { ElMessage } from 'element-plus';
 
 interface RuleFormState {
-	id: number;
-	productId: number;
-	level: number;
+	id?: number;
+	productKey: string;
+	level: number | null;
+	key: string;
+	type: string;
 	name: string;
-	dictType: string;
-	inputs: Object;
-	outputs: Object [];
+	outputs: any[];
 	status: number;
 	desc: string;
 }
 interface DicState {
 	isShowDialog: boolean;
 	ruleForm: RuleFormState;
-	typeData: RuleFormState[];
-	rules: {};
+	type: string;
+	types: string;
+	productKey: string;
+	typeData: any[];
+	jsondata: any[];
+	enumdata: any[];
+	outputsdata: any[];
+	elementType: any;
+	rules: any;
+}
+
+const form = {
+	productKey: '',
+	type: '',
+	name: '',
+	level: null,
+	key: '',
+	status: 1,
+	outputs: [],
+	desc: '',
 }
 
 export default defineComponent({
@@ -91,7 +110,7 @@ export default defineComponent({
 			typeData: [], //
 			type: '',
 			types: '',
-			productId: 0,
+			productKey: '',
 			elementType: {
 				type: '',
 				maxLength: '',
@@ -102,33 +121,26 @@ export default defineComponent({
 					value: '',
 				},
 			],
-
 			jsondata: [],
 			outputsdata: [],
-
-			ruleForm: {
-				productId: 0,
-				name: '',
-				key: '',
-				outputs: [],
-				desc: '',
-			},
+			ruleForm: JSON.parse(JSON.stringify(form)),
 			rules: {
-				name: [ { required: true, message: '事件定义名称不能为空', trigger: 'blur' },
-        				{ max: 32, message: '事件定义名称不能超过32个字符', trigger: 'blur' },
-						{ validator: validateNoSpace, message: '事件定义名称不能包含空格', trigger: 'blur' }
-					],
+				name: [
+					{ required: true, message: '事件定义名称不能为空', trigger: 'blur' },
+					{ max: 32, message: '事件定义名称不能超过32个字符', trigger: 'blur' },
+					{ validator: validateNoSpace, message: '事件定义名称不能包含空格', trigger: 'blur' }
+				],
 				key: [{ required: true, message: '事件定义标识不能为空', trigger: 'blur' }],
 				type: [{ required: true, message: '请选择数据类型', trigger: 'blur' }],
 			},
 		});
 
 		// 打开弹窗
-		const openDialog = (row: RuleFormState | null, productId: number | null) => {
+		const openDialog = (row: RuleFormState, productKey: string) => {
 			resetForm();
 
 			api.product.getDataType({ status: -1 }).then((res: any) => {
-				const datat = Object.values(res.dataType);
+				const datat: any[] = Object.values(res.dataType);
 				datat.forEach((item, index) => {
 					if (index == 0) {
 						datat[index]['label'] = '基础类型';
@@ -144,29 +156,24 @@ export default defineComponent({
 			state.ruleForm = row;
 			if (row.outputs) {
 				state.ruleForm = row;
-				state.productId = productId;
+				state.productKey = productKey;
 				state.outputsdata = row.outputs;
 			}
 			state.isShowDialog = true;
 		};
 		const resetForm = () => {
-			state.ruleForm = {
-				name: '',
-				key: '',
-				status: 1,
-				desc: '',
-			};
+			state.ruleForm = JSON.parse(JSON.stringify(form))
 			state.type = '';
 			state.types = '';
 			state.outputsdata = [];
 			state.elementType = [];
 		};
 
-		const seletChange = (val) => {
+		const seletChange = (val: string) => {
 			state.type = val;
 			state.ruleForm.type = val;
 		};
-		const seletChanges = (val) => {
+		const seletChanges = (val: string) => {
 			state.types = val;
 		};
 
@@ -176,18 +183,18 @@ export default defineComponent({
 				value: '',
 			});
 		};
-		const delEnum = (index) => {
+		const delEnum = (index: number) => {
 			state.enumdata.splice(index, 1);
 		};
 
-		const deljson = (index, type) => {
+		const deljson = (index: number, type: string) => {
 			if (type == 'fun') {
 				state.outputsdata.splice(index, 1);
 			} else {
 				state.jsondata.splice(index, 1);
 			}
 		};
-		const editjson=(index,type)=>{
+		const editjson = (index: number, type: string) => {
 			if (type == 'fun') {
 				editOptionRef.value.openDialog(state.outputsdata[index]);
 			} else {
@@ -196,10 +203,10 @@ export default defineComponent({
 			}
 		}
 
-		const addJson = (type) => {
-			editOptionRef.value.openDialog({ product_id: 0, id: 0, type_data: type });
+		const addJson = (type: string) => {
+			editOptionRef.value.openDialog({ productKey: '', id: 0, type_data: type });
 		};
-		const getOptionData = (data, type_data) => {
+		const getOptionData = (data: any, type_data: any) => {
 			if (type_data == 'fun') {
 				state.outputsdata.push(data);
 			} else {
@@ -225,7 +232,7 @@ export default defineComponent({
 					const theApi = state.ruleForm.id !== 0 ? api.model.eventedit : api.model.eventadd;
 
 					if (state.ruleForm.id !== 0) {
-						state.ruleForm.productId = state.productId;
+						state.ruleForm.productKey = state.productKey;
 					}
 
 					theApi(state.ruleForm).then(() => {
@@ -264,35 +271,41 @@ export default defineComponent({
 	justify-content: space-between;
 	margin-top: 10px;
 }
+
 .input-option {
 	line-height: 30px;
 	padding-top: 5px;
 	width: 140px;
 }
+
 .input-option i {
 	margin: 0px 5px;
 	border: 1px solid #c3c3c3;
 	font-size: 16px;
 }
+
 .input-options {
 	display: flex;
 	align-items: center;
 	color: #409eff;
 	cursor: pointer;
 }
+
 .jslist {
 	width: 100%;
 	border: 1px solid #e8e8e8;
 	padding: 10px;
 	margin-bottom: 10px;
 }
+
 .jsonlist {
 	display: flex;
 	flex-direction: row;
 	justify-content: space-between;
 }
-.jsonoption {
-}
+
+.jsonoption {}
+
 .jsonoption a {
 	margin: 0px 10px;
 }

+ 60 - 63
src/views/iot/device/product/component/editFun.vue

@@ -16,7 +16,7 @@
 							<div>参数名称:{{ item.name }}</div>
 							<div>数据类型:{{ item.valueType.type }}</div>
 							<div class="jsonoption">
-								<el-link type="primary"  @click="editjson(index, 'fun')">编辑</el-link>
+								<el-link type="primary" @click="editjson(index, 'fun')">编辑</el-link>
 								<el-link type="primary" @click="deljson(index, 'fun')">删除</el-link>
 							</div>
 						</div>
@@ -39,7 +39,7 @@
 							<div>参数名称:{{ item.name }}</div>
 							<div>数据类型:{{ item.valueType.type }}</div>
 							<div class="jsonoption">
-								<el-link type="primary" @click="editjsonOut(index, 'fun')">编辑</el-link>
+								<el-link type="primary" @click="editjsonOut(index)">编辑</el-link>
 								<el-link type="primary" @click="deljsonOut(index, 'fun')">删除</el-link>
 							</div>
 						</div>
@@ -66,8 +66,8 @@
 				</span>
 			</template>
 		</el-dialog>
-		<EditOption ref="editOptionRef" key="editOptionRef" @typeList="getOptionData"  @editTypeList="editOptionDataOut" />
-		<EditOption ref="editOptionOutRef" key="editOptionOutRef" @typeList="getOptionDataOut"  @editTypeList="editOptionDataOut"/>
+		<EditOption ref="editOptionRef" key="editOptionRef" @typeList="getOptionData" />
+		<EditOption ref="editOptionOutRef" key="editOptionOutRef" @typeList="getOptionDataOut" />
 	</div>
 </template>
 
@@ -78,26 +78,53 @@ import { Plus, Minus, Right } from '@element-plus/icons-vue';
 import EditOption from './editOption.vue';
 import { validateNoSpace } from '/@/utils/validator';
 
-import { ElMessage, UploadProps } from 'element-plus';
+import { ElMessage } from 'element-plus';
 
 interface RuleFormState {
-	id: number;
-	productId: number;
+	id?: number;
+	key: string;
+	productKey: string;
 	name: string;
+	type: string;
 	dictType: string;
 	valueType: Object;
-	inputs: Object;
-	output: Object;
+	inputs: any;
+	outputs: any;
 	status: number;
 	desc: string;
 }
 interface DicState {
 	isShowDialog: boolean;
+	productKey: string;
+	type: string;
+	types: string;
 	ruleForm: RuleFormState;
-	typeData: RuleFormState[];
+	typeData: any[];
+	inputsdata: any[];
+	outputsdata: any[];
+	jsondata: any[];
+	elementType: any;
+	enumdata: any;
+	valueType: any;
 	rules: {};
 }
 
+const form = {
+	productKey: '',
+	type: '',
+	name: '',
+	key: '',
+	status: 1,
+	dictType: '',
+	inputs: [],
+	outputs: [],
+	valueType: {
+		type: '',
+		maxLength: '',
+	},
+	desc: '',
+}
+
 export default defineComponent({
 	name: 'deviceEditPro',
 	components: { Plus, Minus, Right, EditOption },
@@ -110,7 +137,7 @@ export default defineComponent({
 			typeData: [], //
 			type: '',
 			types: '',
-			productId: 0,
+			productKey: '',
 			valueType: {
 				type: '',
 				maxLength: '',
@@ -129,56 +156,32 @@ export default defineComponent({
 					value: '',
 				},
 			],
-
 			jsondata: [],
 			inputsdata: [],
 			outputsdata: [],
-
-			ruleForm: {
-				productId: 0,
-				name: '',
-				key: '',
-				inputs: [],
-				outputs: [],
-				valueType: {
-					type: '',
-					maxLength: '',
-				},
-
-				desc: '',
-			},
+			ruleForm: JSON.parse(JSON.stringify(form)),
 			rules: {
-				name: [ { required: true, message: '功能定义名称不能为空', trigger: 'blur' },
-        				{ max: 32, message: '功能定义名称不能超过32个字符', trigger: 'blur' },
-						{ validator: validateNoSpace, message: '功能定义名称不能包含空格', trigger: 'blur' }
-					],
+				name: [{ required: true, message: '功能定义名称不能为空', trigger: 'blur' },
+				{ max: 32, message: '功能定义名称不能超过32个字符', trigger: 'blur' },
+				{ validator: validateNoSpace, message: '功能定义名称不能包含空格', trigger: 'blur' }
+				],
 				key: [{ required: true, message: '功能定义标识不能为空', trigger: 'blur' }],
 				type: [{ required: true, message: '请选择数据类型', trigger: 'blur' }],
 			},
 		});
 
 		// 打开弹窗
-		const openDialog = (row: RuleFormState | null, productId: number | null) => {
+		const openDialog = (row: RuleFormState, productKey: string) => {
 			resetForm();
 			state.ruleForm = row;
-			state.productId = productId;
+			state.productKey = productKey;
 			state.inputsdata = row.inputs || [];
 			state.outputsdata = row.outputs || [];
 			state.isShowDialog = true;
 
 		};
 		const resetForm = () => {
-			state.ruleForm = {
-				name: '',
-				key: '',
-				status: 1,
-				valueType: {
-					type: '',
-					maxLength: '',
-				},
-
-				desc: '',
-			};
+			state.ruleForm = JSON.parse(JSON.stringify(form))
 			state.type = '';
 			state.types = '';
 			state.inputsdata = [];
@@ -187,12 +190,12 @@ export default defineComponent({
 			state.valueType = {};
 		};
 
-		const seletChange = (val) => {
+		const seletChange = (val: string) => {
 			state.type = val;
 			state.ruleForm.type = val;
 
 		};
-		const seletChanges = (val) => {
+		const seletChanges = (val: string) => {
 			state.types = val;
 		};
 
@@ -202,11 +205,11 @@ export default defineComponent({
 				value: '',
 			});
 		};
-		const delEnum = (index) => {
+		const delEnum = (index: number) => {
 			state.enumdata.splice(index, 1);
 		};
 
-		const editjson=(index,type)=>{
+		const editjson = (index: number, type: string) => {
 			if (type == 'fun') {
 				editOptionRef.value.openDialog(state.inputsdata[index]);
 			} else {
@@ -215,7 +218,7 @@ export default defineComponent({
 			}
 		}
 
-		const deljson = (index, type) => {
+		const deljson = (index: number, type: string) => {
 			if (type == 'fun') {
 				state.inputsdata.splice(index, 1);
 			} else {
@@ -223,7 +226,7 @@ export default defineComponent({
 			}
 		};
 
-		const deljsonOut = (index, type) => {
+		const deljsonOut = (index: number, type: string) => {
 			if (type == 'fun') {
 				state.outputsdata.splice(index, 1);
 			} else {
@@ -231,37 +234,32 @@ export default defineComponent({
 			}
 		};
 
-		const editjsonOut=(index,type)=>{
+		const editjsonOut = (index: number) => {
 			editOptionOutRef.value.openDialog(state.outputsdata[index]);
 		}
 
-		const addJson = (type) => {
-			editOptionRef.value.openDialog({ product_id: 0, id: 0, type_data: type });
+		const addJson = (type: string) => {
+			editOptionRef.value.openDialog({ productKey: '', id: 0, type_data: type });
 		};
 
-		const addJsonOut = (type) => {
-			editOptionOutRef.value.openDialog({ product_id: 0, id: 0, type_data: type });
+		const addJsonOut = (type: string) => {
+			editOptionOutRef.value.openDialog({ productKey: '', id: 0, type_data: type });
 		};
 
-		const getOptionData = (data, type_data) => {
+		const getOptionData = (data: any, type_data: any) => {
 			if (type_data == 'fun') {
 				state.inputsdata.push(data);
 			} else {
 				state.jsondata.push(data);
 			}
 		};
-		const getOptionDataOut = (data, type_data) => {
-
+		const getOptionDataOut = (data: any, type_data: any) => {
 			if (type_data == 'fun') {
 				state.outputsdata.push(data);
 			} else {
 				state.outputsdata.push(data);
 			}
-
-			
 		};
-		const editOptionDataOut =(data,type_data)=>{
-		}
 		// 关闭弹窗
 		const closeDialog = () => {
 			state.isShowDialog = false;
@@ -279,7 +277,7 @@ export default defineComponent({
 					state.ruleForm.inputs = state.inputsdata;
 					state.ruleForm.outputs = state.outputsdata;
 					if (state.ruleForm.id !== 0) {
-						state.ruleForm.productId = state.productId;
+						state.ruleForm.productKey = state.productKey;
 						api.model.functionedit(state.ruleForm).then(() => {
 							ElMessage.success('功能定义类型修改成功');
 							closeDialog(); // 关闭弹窗
@@ -299,7 +297,6 @@ export default defineComponent({
 		return {
 			editOptionRef,
 			editOptionOutRef,
-			editOptionDataOut,
 			getOptionData,
 			getOptionDataOut,
 			openDialog,

+ 30 - 30
src/views/iot/device/product/component/editOption.vue

@@ -3,7 +3,7 @@
 		<el-dialog :title="(typeof ruleForm.valueType !== 'undefined' ? '修改' : '添加') + '参数'" v-model="isShowDialog" width="769px">
 			<el-form :model="ruleForm" ref="formRef" :rules="rules" label-width="120px">
 				<el-form-item label="参数标识" prop="key">
-					<el-input v-model="ruleForm.key" placeholder="请输入参数标识"  />
+					<el-input v-model="ruleForm.key" placeholder="请输入参数标识" />
 				</el-form-item>
 				<el-form-item label="参数名称" prop="name">
 					<el-input v-model="ruleForm.name" placeholder="请输入参数名称" />
@@ -12,7 +12,6 @@
 				<el-form-item label="数据类型" prop="type">
 					<el-select v-model="valueType.type" placeholder="请选择数据类型" @change="seletChange">
 						<el-option-group v-for="group in typeData" :key="group.label" :label="group.label">
-							<!-- <el-option v-for="item in group.options" :key="item.type" :label="item.title" :value="item.type" :disabled="item.type == 'object'" /> -->
 							<el-option v-for="item in group.options" :key="item.type" :label="item.title" :value="item.type" />
 						</el-option-group>
 					</el-select>
@@ -24,7 +23,6 @@
 						<el-select v-model="elementType.type" placeholder="请选择元素类型" @change="seletChanges">
 							<el-option-group v-for="group in typeData" :key="group.label" :label="group.label">
 								<el-option v-for="item in group.options" :key="item.type" :label="item.title" :value="item.type" :disabled="['array', 'enum'].includes(item.type)" />
-								<!-- <el-option v-for="item in group.options" :key="item.type" :label="item.title" :value="item.type" :disabled="['array', 'object', 'enum', 'date'].includes(item.type)" /> -->
 							</el-option-group>
 						</el-select>
 					</el-form-item>
@@ -53,10 +51,15 @@ import { Plus, Minus, Right } from '@element-plus/icons-vue';
 import { ElMessage } from 'element-plus';
 import { validateNoSpace } from '/@/utils/validator';
 
-interface RuleFormState {
-	id: number;
-	name: string;
-	desc: string;
+interface stateType {
+	isShowDialog: boolean
+	rules: any
+	ruleForm: any
+	valueType: any
+	typeData: any
+	elementType: any
+	type: string
+	[key: string]: any
 }
 
 const valueTypeBase = {
@@ -98,7 +101,7 @@ export default defineComponent({
 	setup(prop, { emit }) {
 		const formRef = ref<HTMLElement | null>(null);
 
-		const state = reactive<any>({
+		const state = reactive<stateType>({
 			isShowDialog: false,
 			typeData: [], //
 			type: '',
@@ -112,7 +115,6 @@ export default defineComponent({
 					'value': '',
 				},
 			],
-
 			ruleForm: {
 				id: 0,
 				name: '',
@@ -120,27 +122,27 @@ export default defineComponent({
 				transportProtocol: '',
 				accessMode: '0',
 				status: 1,
-				valueType: {
-				},
+				valueType: {},
 				desc: '',
 			},
 			rules: {
-				name: [ { required: true, message: '参数名称不能为空', trigger: 'blur' },
-        				{ max: 32, message: '参数名称不能超过32个字符', trigger: 'blur' },
-						{ validator: validateNoSpace, message: '参数名称不能包含空格', trigger: 'blur' }
-					],
+				name: [
+					{ required: true, message: '参数名称不能为空', trigger: 'blur' },
+					{ max: 32, message: '参数名称不能超过32个字符', trigger: 'blur' },
+					{ validator: validateNoSpace, message: '参数名称不能包含空格', trigger: 'blur' }
+				],
 				key: [{ required: true, message: '参数标识不能为空', trigger: 'blur' }],
 				accessMode: [{ required: true, message: '请选择是否只读', trigger: 'blur' }],
 			},
 		});
 
 		// 打开弹窗
-		const openDialog = (row: RuleFormState | null,type='add') => {
+		const openDialog = (row?: any) => {
 			resetForm();
 
 			api.product.getDataType({ status: -1 }).then((res: any) => {
 				const datat: any = Object.values(res.dataType);
-				datat.forEach((item, index) => {
+				datat.forEach((item: any, index: number) => {
 					if (index == 0) {
 						datat[index]['label'] = '基础类型';
 						datat[index]['options'] = item;
@@ -153,17 +155,16 @@ export default defineComponent({
 			});
 
 			if (row) {
-
 				if (typeof row.valueType !== 'undefined') {
-					state.type=row.valueType.type;
+					state.type = row.valueType.type;
 
-					if (typeof row.valueType.elementType !== 'undefined')state.elementType=row.valueType.elementType;
-					if (typeof row.valueType.elements !== 'undefined')state.enumdata=row.valueType.elements;
-					if (typeof row.valueType.properties !== 'undefined')state.properties=row.valueType.properties;
-					if (typeof row.valueType.type !== 'undefined')state.valueType.type=row.valueType.type;
+					if (typeof row.valueType.elementType !== 'undefined') state.elementType = row.valueType.elementType;
+					if (typeof row.valueType.elements !== 'undefined') state.enumdata = row.valueType.elements;
+					if (typeof row.valueType.properties !== 'undefined') state.properties = row.valueType.properties;
+					if (typeof row.valueType.type !== 'undefined') state.valueType.type = row.valueType.type;
 
 					const fieldCount = Object.keys(row.valueType).length;
-					if(fieldCount>1)state.valueType=row.valueType;
+					if (fieldCount > 1) state.valueType = row.valueType;
 				}
 
 				state.ruleForm = row;
@@ -183,11 +184,11 @@ export default defineComponent({
 			state.elementType = JSON.parse(JSON.stringify(valueType));
 		};
 
-		const seletChange = (val) => {
+		const seletChange = (val: string) => {
 
 			state.type = val;
 		};
-		const seletChanges = (val) => {
+		const seletChanges = (val: string) => {
 			state.types = val;
 		};
 
@@ -197,7 +198,7 @@ export default defineComponent({
 				'value': '',
 			});
 		};
-		const delEnum = (index) => {
+		const delEnum = (index: number) => {
 			state.enumdata.splice(index, 1);
 		}
 
@@ -217,7 +218,7 @@ export default defineComponent({
 				if (valid) {
 					if (typeof state.ruleForm.valueType !== 'undefined') {
 						//修改
-				
+
 						if (state.type == 'array') {
 							state.valueType.elementType = state.elementType;
 						}
@@ -228,12 +229,11 @@ export default defineComponent({
 						emit('editTypeList', state.ruleForm, state.ruleForm.type_data);
 					} else {
 						// //添加
-				
+
 						if (state.type == 'array') {
 							state.valueType.elementType = state.elementType;
 						}
 
-
 						state.ruleForm.valueType = state.valueType;
 						ElMessage.success('参数类型添加成功');
 						closeDialog(); // 关闭弹窗

+ 42 - 33
src/views/iot/device/product/component/editPro.vue

@@ -20,8 +20,8 @@
 						</template>
 					</el-cascader>
 
-          <!-- 添加产品分类 -->
-          <el-button type="success" @click="onOpenAddCategory()" style="margin-left: 5px;">添加产品分类</el-button>
+					<!-- 添加产品分类 -->
+					<el-button type="success" @click="onOpenAddCategory()" style="margin-left: 5px;">添加产品分类</el-button>
 				</el-form-item>
 
 				<el-form-item label="消息协议" prop="messageProtocol">
@@ -96,7 +96,7 @@
 				</span>
 			</template>
 		</el-dialog>
-    <EditCategory ref="editCategoryRef" @getCateList="getCategoryList" />
+		<EditCategory ref="editCategoryRef" @getCateList="getCategoryList" />
 	</div>
 </template>
 
@@ -118,9 +118,11 @@ interface RuleFormState {
 	transportProtocol: string
 	deviceType: string
 	name: string
-	authType: string
+	key: string
+	authType: number| null
 	status: number
 	desc: string
+	icon: string
 	authUser: string
 	authPasswd: string
 	accessToken: string
@@ -129,24 +131,28 @@ interface RuleFormState {
 interface DicState {
 	isShowDialog: boolean
 	ruleForm: RuleFormState
-	cateData: RuleFormState[]
-	deptData: RuleFormState[]
-	messageData: RuleFormState[]
-	tranData: RuleFormState[]
-	rules: {},
+	cateData: any[]
+	deptData: any[]
+	messageData: any[]
+	network_protocols: any[]
+	tranData: any[]
+	rules: {}
 	imageUrl: string
+	singleImg: string
 }
 
 const form = {
 	id: 0,
 	name: '',
+	key: '',
 	categoryId: '',
 	messageProtocol: '',
 	transportProtocol: '',
 	deviceType: '设备',
 	status: 1,
 	desc: '',
-	authType: '',
+	icon: '',
+	authType: null,
 	authUser: '',
 	authPasswd: '',
 	accessToken: '',
@@ -156,7 +162,7 @@ const form = {
 
 export default defineComponent({
 	name: 'deviceEditPro',
-	components: {EditCategory, uploadVue },
+	components: { EditCategory, uploadVue },
 	setup(prop, { emit }) {
 		const formRef = ref<HTMLElement | null>(null)
 		const baseURL: string | undefined | boolean = getOrigin(import.meta.env.VITE_API_URL)
@@ -164,11 +170,11 @@ export default defineComponent({
 		const { proxy } = getCurrentInstance() as any
 		const { network_server_type } = proxy.useDict('network_server_type')
 
-		const certList = ref([])
+		const certList = ref<any[]>([])
 		const submitLoading = ref(false)
-    const editCategoryRef = ref();
+		const editCategoryRef = ref();
 
-		const state = reactive<DicState | any>({
+		const state = reactive<DicState>({
 			isShowDialog: false,
 			cateData: [], // 分类数据
 			deptData: [], //
@@ -181,12 +187,15 @@ export default defineComponent({
 				...form
 			},
 			rules: {
-				name: [{ required: true, message: '产品名称不能为空', trigger: 'change' },
-				{ max: 32, message: '产品名称不能超过32个字符', trigger: 'change' },
-				{ validator: validateNoSpace, message: '产品名称不能包含空格', trigger: 'change' }
+				name: [
+					{ required: true, message: '产品名称不能为空', trigger: 'change' },
+					{ max: 32, message: '产品名称不能超过32个字符', trigger: 'change' },
+					{ validator: validateNoSpace, message: '产品名称不能包含空格', trigger: 'change' }
+				],
+				key: [
+					{ required: true, message: '产品标识不能为空', trigger: 'change' },
+					{ validator: validateNoSpace, message: '产品标识不能包含空格', trigger: 'change' }
 				],
-				key: [{ required: true, message: '产品标识不能为空', trigger: 'change' },
-				{ validator: validateNoSpace, message: '产品标识不能包含空格', trigger: 'change' }],
 				messageProtocol: [{ required: true, message: '消息协议不能为空', trigger: 'change' }],
 				transportProtocol: [{ required: true, message: '接入方式不能为空', trigger: 'change' }],
 				categoryId: [{ required: true, message: '产品分类不能为空', trigger: 'change' }],
@@ -200,7 +209,7 @@ export default defineComponent({
 		}
 
 		// 打开弹窗
-		const openDialog = (row: RuleFormState | null) => {
+		const openDialog = (row?: any) => {
 			resetForm()
 			api.category.getList({ status: 1 }).then((res: any) => {
 				state.cateData = res.category || []
@@ -285,31 +294,31 @@ export default defineComponent({
 				}
 			})
 		}
-    // 打开新增产品分类弹窗
-    const onOpenAddCategory = () => {
-      editCategoryRef.value.openDialog();
-    };
-    // 获取产品分类列表
-    const getCategoryList = () => {
-      api.category.getList({ status: 1 }).then((res: any) => {
-        state.cateData = res.category || []
-      })
-    }
+		// 打开新增产品分类弹窗
+		const onOpenAddCategory = () => {
+			editCategoryRef.value.openDialog();
+		};
+		// 获取产品分类列表
+		const getCategoryList = () => {
+			api.category.getList({ status: 1 }).then((res: any) => {
+				state.cateData = res.category || []
+			})
+		}
 
 		return {
 			transportProtocolChange,
 			submitLoading,
 			certList,
 			openDialog,
-      onOpenAddCategory,
+			onOpenAddCategory,
 			handleAvatarSuccess,
 			closeDialog,
 			onCancel,
 			onSubmit,
 			network_server_type,
-      getCategoryList,
+			getCategoryList,
 			formRef,
-      editCategoryRef,
+			editCategoryRef,
 			...toRefs(state),
 		}
 	},

+ 48 - 46
src/views/iot/device/product/component/editTab.vue

@@ -197,21 +197,48 @@ import { ElMessage } from 'element-plus';
 
 interface RuleFormState {
 	id: number;
-	productId: number;
+	productKey: string;
 	accessMode: number;
 	name: string;
+	key: string;
+	type: string;
+	transportProtocol: string;
 	dictType: string;
-	valueType: Object;
+	valueType: any;
 	status: number;
 	desc: string;
 }
 interface DicState {
 	isShowDialog: boolean;
+	productKey: string;
+	type: string;
+	types: string;
+	valueType: any;
+	elementType: any;
 	ruleForm: RuleFormState;
-	typeData: RuleFormState[];
+	jsondata: any;
+	typeData: any[];
+	enumdata: any[];
 	rules: {};
 }
 
+const ruleForm = {
+	id: 0,
+	productKey: '',
+	name: '',
+	dictType: '',
+	type: '',
+	key: '',
+	transportProtocol: '',
+	accessMode: 1,
+	status: 1,
+	valueType: {
+		type: '',
+		maxLength: '',
+	},
+	desc: '',
+}
+
 export default defineComponent({
 	name: 'deviceEditPro',
 	components: { Plus, Minus, Right, EditOption },
@@ -223,7 +250,7 @@ export default defineComponent({
 			typeData: [], //
 			type: '',
 			types: '',
-			productId: 0,
+			productKey: '',
 			valueType: {
 				type: '',
 				maxLength: '',
@@ -245,26 +272,13 @@ export default defineComponent({
 
 			jsondata: [],
 
-			ruleForm: {
-				id: 0,
-				productId: 0,
-				name: '',
-				key: '',
-				transportProtocol: '',
-				accessMode: 1,
-				status: 1,
-				valueType: {
-					type: '',
-					maxLength: '',
-				},
-
-				desc: '',
-			},
+			ruleForm: JSON.parse(JSON.stringify(ruleForm)),
 			rules: {
-				name: [ { required: true, message: '标签定义名称不能为空', trigger: 'blur' },
-        				{ max: 32, message: '标签定义名称不能超过32个字符', trigger: 'blur' },
-						{ validator: validateNoSpace, message: '标签定义名称不能包含空格', trigger: 'blur' }
-					],
+				name: [
+					{ required: true, message: '标签定义名称不能为空', trigger: 'blur' },
+					{ max: 32, message: '标签定义名称不能超过32个字符', trigger: 'blur' },
+					{ validator: validateNoSpace, message: '标签定义名称不能包含空格', trigger: 'blur' }
+				],
 				key: [{ required: true, message: '标签定义标识不能为空', trigger: 'blur' }],
 				accessMode: [{ required: true, message: '请选择是否只读', trigger: 'blur' }],
 				type: [{ required: true, message: '请选择数据类型', trigger: 'blur' }],
@@ -272,11 +286,11 @@ export default defineComponent({
 		});
 
 		// 打开弹窗
-		const openDialog = (row: RuleFormState | null, productId: number | null) => {
+		const openDialog = (row: RuleFormState, productKey: string) => {
 			resetForm();
 
 			api.product.getDataType({ status: -1 }).then((res: any) => {
-				const datat = Object.values(res.dataType);
+				const datat = Object.values(res.dataType) as any[];
 				datat.forEach((item, index) => {
 					if (index == 0) {
 						datat[index]['label'] = '基础类型';
@@ -293,7 +307,7 @@ export default defineComponent({
 			if (row.valueType) {
 				state.ruleForm = row;
 
-				state.productId = productId;
+				state.productKey = productKey;
 				state.valueType = row.valueType;
 				state.ruleForm.valueType.type = row.valueType.type;
 				state.ruleForm.type = row.valueType.type;
@@ -323,19 +337,7 @@ export default defineComponent({
 			state.isShowDialog = true;
 		};
 		const resetForm = () => {
-			state.ruleForm = {
-				name: '',
-				key: '',
-				transportProtocol: '',
-				accessMode: 1,
-				status: 1,
-				valueType: {
-					type: '',
-					maxLength: '',
-				},
-
-				desc: '',
-			};
+			state.ruleForm = JSON.parse(JSON.stringify(ruleForm))
 			state.type = '';
 			state.types = '';
 			state.valueType = {};
@@ -347,12 +349,12 @@ export default defineComponent({
 			},];
 		};
 
-		const seletChange = (val) => {
+		const seletChange = (val: string) => {
 			state.type = val;
 			state.ruleForm.type = val;
 
 		};
-		const seletChanges = (val) => {
+		const seletChanges = (val: string) => {
 			state.types = val;
 		};
 
@@ -362,18 +364,18 @@ export default defineComponent({
 				value: '',
 			});
 		};
-		const delEnum = (index) => {
+		const delEnum = (index: number) => {
 			state.enumdata.splice(index, 1);
 		};
 
-		const deljson = (index) => {
+		const deljson = (index: number) => {
 			state.jsondata.splice(index, 1);
 		};
 
 		const addJson = () => {
-			editOptionRef.value.openDialog({ product_id: 0, id: 0 });
+			editOptionRef.value.openDialog({ productKey: '', id: 0 });
 		};
-		const getOptionData = (data) => {
+		const getOptionData = (data: any) => {
 			state.jsondata.push(data);
 		};
 		// 关闭弹窗
@@ -418,7 +420,7 @@ export default defineComponent({
 							}
 						}
 						state.ruleForm.valueType = state.valueType;
-						state.ruleForm.productId = state.productId;
+						state.ruleForm.productKey = state.productKey;
 
 						api.model.tagedit(state.ruleForm).then(() => {
 							ElMessage.success('标签定义类型修改成功');

+ 10 - 10
src/views/iot/device/product/component/typeItem.vue

@@ -83,16 +83,16 @@ import { Plus, Minus, Right } from '@element-plus/icons-vue';
 import TypeItem from './typeItem.vue';
 
 interface IValyeType {
-  type: string;
-  min?: string;
-  max?: string;
-  unit?: string;
-  decimals?: string;
-  trueText?: string;
-  falseText?: string;
-  trueValue?: string;
-  falseValue?: string;
-  maxLength?: string;
+  type: string | null;
+  min?: string | null;
+  max?: string | null;
+  unit?: string | null;
+  decimals?: string | null;
+  trueText?: string | null;
+  falseText?: string | null;
+  trueValue?: string | null;
+  falseValue?: string | null;
+  maxLength?: string | null;
   elements: { text: string, value: string }[];
   elementType?: IValyeType;
   properties: { key: string, name: string, desc: string, valueType: IValyeType }[];

+ 50 - 46
src/views/iot/device/product/detail.vue

@@ -1,12 +1,10 @@
 <template>
 	<div class="page bg page-full">
 		<div class="content">
-			<div class="cont_box">
+			<div class="cont_box" style="align-items: center;">
 				<div class="title">产品:{{ detail.name }}</div>
-				<div class="pro-status"><span :class="developer_status == 1 ? 'on' : 'off'"></span>{{ developer_status == 1
-					? '已发布' : '未发布' }}</div>
-				<div class="pro-option" @click="CkOption" v-auth="'startOrStop'"> {{ developer_status == 1 ? '停用' : '启用' }}
-				</div>
+				<!-- <el-tag :type="developer_status == 1 ? 'success' : 'danger'" style="margin:0 20px;">{{ developer_status == 1 ? '已发布' : '未发布' }}</el-tag> -->
+				<el-switch v-auth="'startOrStop'" style="margin:0 20px;" v-model="developer_status" inline-prompt :active-value="1" :inactive-value="0" active-text="启用" inactive-text="停用" @change="CkOption"></el-switch>
 			</div>
 		</div>
 
@@ -18,7 +16,7 @@
 				</div>
 
 				<el-descriptions class="margin-top" :column="3" border>
-					<el-descriptions-item label="产品标识">{{ detail.key }}</el-descriptions-item>
+					<el-descriptions-item label="产品标识"><copy :text="detail.key"></copy></el-descriptions-item>
 					<el-descriptions-item label="产品分类">{{ detail.categoryName }}</el-descriptions-item>
 					<el-descriptions-item label="设备类型">{{ detail.deviceType }}</el-descriptions-item>
 					<el-descriptions-item label="产品图片">
@@ -159,7 +157,7 @@
 				</el-tabs>
 				<div class="import">
 					<div class="row_bet">
-						<el-upload accept="json" :show-file-list="false" :limit="1" :data="{ key: detail.key }" :headers="headers" :action="uploadUrl" :on-success="updateImg">
+						<el-upload accept="json" :show-file-list="false" :limit="1" :data="{ productKey: detail.key }" :headers="headers" :action="uploadUrl" :on-success="updateImg">
 							<el-button size="small">
 								<el-icon> <ele-Upload /> </el-icon>
 								导入物模型
@@ -172,9 +170,7 @@
 							导出物模型
 						</el-button>
 					</div>
-
 				</div>
-
 				<pagination v-show="tableData.total > 0" :total="tableData.total" v-model:page="tableData.param.pageNum" v-model:limit="tableData.param.pageSize" @pagination="getList()" />
 			</el-tab-pane>
 			<el-tab-pane label="设备接入" name="3">
@@ -185,7 +181,7 @@
 				</dataParse>
 			</el-tab-pane>
 		</el-tabs>
-		<EditDic ref="editDicRef" @typeList="typeList" />
+		<EditDic ref="editDicRef" @typeList="productDetail" />
 		<EditAttr ref="editAttrRef" @typeList="getproperty" />
 		<EditFun ref="editFunRef" @typeList="getfunction" />
 		<EditEvent ref="editEventRef" @typeList="getevent" />
@@ -212,10 +208,12 @@ import { useRoute } from 'vue-router';
 
 import api from '/@/api/device';
 
-
 interface TableDataState {
-	ids: number[];
+	isShowDialog: boolean;
 	detail: any;
+	developer_status: number;
+	activeName: string;
+	activetab: string;
 	tableData: {
 		data: [];
 		total: number;
@@ -224,10 +222,11 @@ interface TableDataState {
 			pageNum: number;
 			pageSize: number;
 			name: string;
+			productKey: string | string[];
 			deviceType: string;
 			status: string;
 			dateRange: string[];
-		};
+		} | any;
 	};
 }
 export default defineComponent({
@@ -258,7 +257,7 @@ export default defineComponent({
 				loading: false,
 				param: {
 					pageNum: 1,
-					productId: route.params && route.params.id,
+					productKey: route.params?.id,
 					pageSize: 10,
 					status: '',
 					dateRange: [],
@@ -267,12 +266,7 @@ export default defineComponent({
 		});
 
 		onMounted(() => {
-			const ids = route.params && route.params.id;
-			api.product.detail(ids).then((res: any) => {
-				state.detail = res.data;
-				state.developer_status = res.data.status
-			});
-
+			productDetail()
 			//第一次加载
 			api.model.property(state.tableData.param).then((res: any) => {
 				state.tableData.data = res.Data;
@@ -280,54 +274,63 @@ export default defineComponent({
 			});
 		});
 
+		function productDetail() {
+			const productKey = route.params?.id;
+			api.product.detail(productKey).then((res: any) => {
+				state.detail = res.data;
+				state.developer_status = res.data.status
+			});
+		}
+
+
 		//编辑属性
-		const onEditAttr = (row: TableDataRow) => {
+		const onEditAttr = (row: any) => {
 			editAttrRef.value.openDialog(row, route.params.id);
 		};
 
 		//编辑功能
-		const onEditFun = (row: TableDataRow) => {
+		const onEditFun = (row: any) => {
 			editFunRef.value.openDialog(row, route.params.id);
 		}
 
 
 		//编辑事件
-		const onEditEvent = (row: TableDataRow) => {
+		const onEditEvent = (row: any) => {
 			editEventRef.value.openDialog(row, route.params.id);
 		}
 
 		//编辑标签
-		const onEditTag = (row: TableDataRow) => {
+		const onEditTag = (row: any) => {
 			editTabRef.value.openDialog(row, route.params.id);
 		}
 
 		//打开添加属性弹窗
 		const onOpenEditAttr = () => {
-			editAttrRef.value.openDialog({ product_id: route.params.id, id: 0, accessMode: 1 });
+			editAttrRef.value.openDialog({ productKey: route.params.id, id: 0, accessMode: 1 });
 		};
 
 		//打开添加功能弹窗
 		const onOpenEditFun = () => {
-			editFunRef.value.openDialog({ product_id: route.params.id, id: 0 });
+			editFunRef.value.openDialog({ productKey: route.params.id, id: 0 });
 		};
 		//打开添加事件弹窗
 		const onOpenEditEvent = () => {
-			editEventRef.value.openDialog({ product_id: route.params.id, id: 0, level: 0 });
+			editEventRef.value.openDialog({ productKey: route.params.id, id: 0, level: 0 });
 		};
 
 		//打开添加事件弹窗
 		const onOpenEditTab = () => {
-			editTabRef.value.openDialog({ product_id: route.params.id, id: 0, accessMode: 1 });
+			editTabRef.value.openDialog({ productKey: route.params.id, id: 0, accessMode: 1 });
 		};
 
 		// 打开修改产品弹窗
-		const onOpenEditDic = (row: TableDataRow) => {
+		const onOpenEditDic = (row: any) => {
 			editDicRef.value.openDialog(row);
 		};
 
 
 		// 删除产品
-		const onRowDel = (key, type) => {
+		const onRowDel = (key: string, type: string) => {
 			let msg = `此操作将永久删除该数据,是否继续?`;
 
 			if (key.length === 0) {
@@ -340,28 +343,29 @@ export default defineComponent({
 				type: 'warning',
 			})
 				.then(() => {
+					const productKey = route.params?.id as string
 					if (type == 'attr') {
-						api.model.propertydel(route.params.id, key).then(() => {
+						api.model.propertydel(productKey, key).then(() => {
 							ElMessage.success('删除成功');
 							getproperty();
 						});
 					}
 					if (type == 'fun') {
-						api.model.functiondel(route.params.id, key).then(() => {
+						api.model.functiondel(productKey, key).then(() => {
 							ElMessage.success('删除成功');
 							getfunction();
 						});
 					}
 					if (type == 'event') {
-						api.model.eventdel(route.params.id, key).then(() => {
+						api.model.eventdel(productKey, key).then(() => {
 							ElMessage.success('删除成功');
 							getevent();
 						});
 					}
 					if (type == 'tab') {
-						api.model.tagdel(route.params.id, key).then(() => {
+						api.model.tagdel(productKey, key).then(() => {
 							ElMessage.success('删除成功');
-							tagdel();
+							gettab();
 						});
 					}
 				})
@@ -414,7 +418,7 @@ export default defineComponent({
 			});
 		};
 
-		const wuhandleClick = (tab: TabsPaneContext) => {
+		const wuhandleClick = (tab: any) => {
 			state.activetab = tab.props.name;
 			switch (tab.props.name) {
 				case 'attr':
@@ -432,32 +436,31 @@ export default defineComponent({
 			}
 		};
 
-		const handleClick = (tab: TabsPaneContext, event: Event) => {
+		const handleClick = (tab: any, event: Event) => {
 		};
 
 		const updateScript = (scriptInfo: string) => {
 			state.detail.scriptInfo = scriptInfo
 		};
 
-		const CkOption = () => {
-
-			if (state.developer_status == 1) {
-				api.product.undeploy({ id: route.params.id }).then((res: any) => {
+		const CkOption = (developer_status: number) => {
+			if (developer_status == 0) {
+				api.product.undeploy(route.params.id).then((res: any) => {
 					ElMessage.success('操作成功');
 					state.developer_status = 0;
-				});
+				}).catch(() => state.developer_status = 1)
 			} else {
-				api.product.deploy({ id: route.params.id }).then((res: any) => {
+				api.product.deploy(route.params.id).then((res: any) => {
 					ElMessage.success('操作成功');
 					state.developer_status = 1;
-				});
+				}).catch(() => state.developer_status = 0)
 			}
 		}
 
 		// 导出
 		const onRowExport = () => {
 
-			api.product.export({ key: state.detail.key }).then((res: any) => downloadFile(res, "TSL-" + state.detail.key + "-" + getCurrentTime() + ".json"))
+			api.product.export({ productKey: state.detail.key }).then((res: any) => downloadFile(res, "TSL-" + state.detail.key + "-" + getCurrentTime() + ".json"))
 		};
 
 
@@ -472,7 +475,7 @@ export default defineComponent({
 		}
 		const updateImg = (res: any) => {
 			if (res.code === 0) {
-				getList("attr");
+				getList();
 				ElMessage.success('物模型导入成功');
 			} else {
 				ElMessage.error(res.message);
@@ -506,6 +509,7 @@ export default defineComponent({
 			wuhandleClick,
 			onOpenEditTab,
 			onOpenEditEvent,
+			productDetail,
 			onOpenEditAttr,
 			onOpenEditFun,
 			onOpenEditDic,

+ 17 - 14
src/views/iot/device/product/index.vue

@@ -36,7 +36,7 @@
             </el-icon>
             新增产品
           </el-button>
-          <el-button type="info" class="ml10" @click="onRowDel(null)" v-auth="'del'">
+          <el-button type="info" class="ml10" @click="onRowDel()" v-auth="'del'">
             <el-icon>
               <ele-Delete />
             </el-icon>
@@ -46,7 +46,9 @@
       </el-form>
       <el-table :data="tableData.data" style="width: 100%" @selection-change="handleSelectionChange" v-loading="tableData.loading">
         <el-table-column type="selection" width="55" align="center" />
-        <el-table-column label="标识" prop="key" min-width="130" show-overflow-tooltip v-col="'key'" />
+        <el-table-column label="标识" prop="key" min-width="130" show-overflow-tooltip v-col="'key'">
+          <template #default="{ row }"><copy :text="row.key"></copy></template>
+        </el-table-column>
         <el-table-column label="名称" prop="name" min-width="160" show-overflow-tooltip v-col="'name'" />
         <el-table-column label="分类" prop="categoryName" align="center" width="140" show-overflow-tooltip v-col="'categoryName'" />
         <el-table-column label="消息协议" prop="messageProtocol" align="center" min-width="150" show-overflow-tooltip v-col="'messageProtocol'" />
@@ -60,7 +62,7 @@
         </el-table-column>
         <el-table-column label="操作" width="130" align="center" fixed="right">
           <template #default="scope">
-            <router-link :to="'/iotmanager/device/product/detail/' + scope.row.id" class="link-type" style="padding-right: 12px;font-size: 12px;color: #409eff;">
+            <router-link :to="'/iotmanager/device/product/detail/' + scope.row.key" class="link-type" style="padding-right: 12px;font-size: 12px;color: #409eff;">
               <span>详情</span>
             </router-link>
             <el-button size="small" text type="warning" @click="onOpenEditDic(scope.row)" v-auth="'edit'">修改</el-button>
@@ -83,6 +85,7 @@ import api from '/@/api/device';
 // 定义接口来定义对象的类型
 interface TableDataRow {
   id: number;
+  key: string;
   name: string;
   deviceType: string;
   status: number;
@@ -90,7 +93,7 @@ interface TableDataRow {
   createBy: string;
 }
 interface TableDataState {
-  ids: number[];
+  keys: string[];
   tableData: {
     data: Array<TableDataRow>;
     total: number;
@@ -114,7 +117,7 @@ export default defineComponent({
     const editDicRef = ref();
     const queryRef = ref();
     const state = reactive<TableDataState>({
-      ids: [],
+      keys: [],
       tableData: {
         data: [],
         total: 0,
@@ -122,9 +125,9 @@ export default defineComponent({
         param: {
           pageNum: 1,
           pageSize: 10,
-          dictName: '',
-          dictType: '',
           status: '',
+          name: '',
+          deviceType: '',
           dateRange: [],
         },
       },
@@ -149,16 +152,16 @@ export default defineComponent({
       editDicRef.value.openDialog(row);
     };
     // 删除产品
-    const onRowDel = (row: TableDataRow) => {
+    const onRowDel = (row?: TableDataRow) => {
       let msg = '你确定要删除所选数据?';
-      let ids: number[] = [];
+      let keys: string[] = [];
       if (row) {
         msg = `此操作将永久删除产品:“${row.name}”,是否继续?`;
-        ids = [row.id];
+        keys = [row.key];
       } else {
-        ids = state.ids;
+        keys = state.keys;
       }
-      if (ids.length === 0) {
+      if (keys.length === 0) {
         ElMessage.error('请选择要删除的数据。');
         return;
       }
@@ -168,7 +171,7 @@ export default defineComponent({
         type: 'warning',
       })
         .then(() => {
-          api.product.delete(ids).then(() => {
+          api.product.delete(keys).then(() => {
             ElMessage.success('删除成功');
             typeList();
           });
@@ -187,7 +190,7 @@ export default defineComponent({
     };
     // 多选框选中数据
     const handleSelectionChange = (selection: TableDataRow[]) => {
-      state.ids = selection.map((item) => item.id);
+      state.keys = selection.map((item) => item.key);
     };
     return {
       addDicRef,

+ 3 - 3
src/views/iot/device/template/component/dataAreaDialog.vue

@@ -42,7 +42,7 @@
 			</el-table-column>
 			<el-table-column label="操作" align="center" width="180px">
 				<template #default="{ row, $index }">
-					<el-button type="primary" size="small" @click="handleSubmit(row, $index)"> 保存 </el-button>
+					<el-button type="primary" size="small" @click="handleSubmit(row)"> 保存 </el-button>
 					<el-button type="danger" size="small" @click="handleDelete(row, $index)"> 删除 </el-button>
 				</template>
 			</el-table-column>
@@ -52,7 +52,7 @@
 
 <script lang="ts">
 import api from '/@/api/device/modbus';
-import { ElMessage } from 'element-plus';
+import { ElMessage, ElMessageBox } from 'element-plus';
 
 export default {
 	props: {
@@ -99,7 +99,7 @@ export default {
 			});
 		},
 		handleDelete(row: any, index: number) {
-			this.$confirm('是否确认删除数据区名称为"' + row.name + '"的数据项?', '警告', {
+			ElMessageBox.confirm('是否确认删除数据区名称为"' + row.name + '"的数据项?', '警告', {
 				confirmButtonText: '确定',
 				cancelButtonText: '取消',
 				type: 'warning',

+ 5 - 7
src/views/iot/device/template/component/deviceTemplateDialog.vue

@@ -108,7 +108,7 @@ import api from '/@/api/device/modbus';
 export default {
 	props: {
 		templateNumber: String,
-		mode: String,
+		mode: Number,
 	},
 	data() {
 		return {
@@ -120,7 +120,7 @@ export default {
 				page: 1,
 				size: 20,
 				template_number: '',
-			},
+			} as any,
 			temp: {
 				title: '',
 				unit: '',
@@ -198,7 +198,7 @@ export default {
 			// this.listQuery.page = 1
 			this.getList();
 		},
-		handleDelete(row) {
+		handleDelete(row: any) {
 			this.$confirm('是否确认删除变量名称为"' + row.title + '"的数据项?', '警告', {
 				confirmButtonText: '确定',
 				cancelButtonText: '取消',
@@ -309,9 +309,7 @@ export default {
 	margin: 10px;
 }
 
-::v-deep {
-	.el-form-item__label {
-		text-align: right;
-	}
+:deep(.el-form-item__label) {
+	text-align: right;
 }
 </style>

+ 2 - 2
src/views/iot/device/template/component/edit.vue

@@ -55,7 +55,7 @@ export default {
 				mode: [{ required: true, message: '请选择模式', trigger: 'change' }],
 			},
 			dialogVisible: false,
-			dialogStatus: '',
+			dialogStatus: 'update' as 'update' | 'create',
 			textMap: {
 				update: '模板详情',
 				create: '添加模板',
@@ -72,7 +72,7 @@ export default {
 	},
 
 	methods: {
-		open(dialogStatus: string, row: any) {
+		open(dialogStatus: 'update' | 'create', row: any) {
 			this.dialogStatus = dialogStatus;
 			this.tabsKey = Date.now();
 			this.dialogVisible = true;

+ 8 - 10
src/views/iot/device/template/component/importFile.vue

@@ -123,20 +123,17 @@ export default {
 				});
 		},
 	},
-
-	mounted() {},
 };
 </script>
 
 <style lang="scss" scoped>
-::v-deep {
-	.import-dialog {
-		.el-dialog {
-			width: 575px !important;
-			height: auto;
-		}
+:deep(.import-dialog) {
+	.el-dialog {
+		width: 575px !important;
+		height: auto;
 	}
 }
+
 .title {
 	// color: #000;
 	font-size: 16px;
@@ -156,6 +153,7 @@ export default {
 	padding: 10px;
 	margin-bottom: 20px;
 	border: 2px dashed #ccc;
+
 	img {
 		margin-right: 10px;
 	}
@@ -175,8 +173,8 @@ export default {
 	cursor: pointer;
 	margin-bottom: 20px;
 	padding: 5px 10px;
+
 	&:hover {
 		background-color: #f5f7fa;
 	}
-}
-</style>
+}</style>

+ 0 - 876
src/views/iot/device/template/detail.vue

@@ -1,876 +0,0 @@
-<template>
-	<div class="system-dic-container">
-		<div class="content">
-			<div class="cont_box">
-				<div class="title">设备:{{ detail.name }}</div>
-				<div class="pro-status"><span :class="developer_status == 2 ? 'on' : 'off'"></span>{{ developer_status == 2 ? '在线' : '离线' }}</div>
-
-				<!-- <div class="pro-option" @click="CkOption">{{ developer_status == 2 ? '下线' : '上线' }}</div> -->
-			</div>
-		</div>
-
-		<div class="content-box">
-			<el-tabs v-model="activeName" @tab-click="handleClick">
-				<el-tab-pane label="运行状态" name="3">
-					<div style="display: flex; padding: 10px; flex-wrap: wrap">
-						<div class="ant-card">
-							<div class="ant-card-body">
-								<div class="cardflex">
-									<div>设备状态</div>
-									<div @click="getrunData()" style="cursor: pointer">
-										<el-icon style="font-size: 18px">
-											<ele-Refresh />
-										</el-icon>
-									</div>
-								</div>
-
-								<div class="statusname" v-if="areaData.status == 0">未启用</div>
-								<div class="statusname" v-if="areaData.status == 1">离线</div>
-								<div class="statusname" v-if="areaData.status == 2">在线</div>
-								<div class="cardflex comtest">
-									<div>数据时间</div>
-									<div>{{ areaData.lastOnlineTime || '未启用' }}</div>
-								</div>
-							</div>
-						</div>
-
-						<div class="ant-card" v-for="(item, index) in areaData.properties" :key="index">
-							<div class="ant-card-body">
-								<div class="cardflex">
-									<div>{{ item.name }}</div>
-									<div style="cursor: pointer">
-										<el-icon style="font-size: 18px" @click="getrunData()">
-											<ele-Refresh />
-										</el-icon>
-										<el-icon style="font-size: 18px; margin-left: 10px" @click="onOpenListDetail(item)">
-											<ele-Expand />
-										</el-icon>
-									</div>
-								</div>
-
-								<div class="statusname">{{ item.value }}{{ item.unit }}</div>
-								<div>
-									<devantd :json="item.list" :antdid="item.key" v-if="item.type == 'int' || item.type == 'float'" />
-								</div>
-							</div>
-						</div>
-					</div>
-				</el-tab-pane>
-				<el-tab-pane label="设备信息" name="1">
-					<div class="pro-box">
-						<div class="protitle">设备信息</div>
-						<div>
-							<el-button type="primary" v-auth="'edit'" @click="onOpenEditDic(detail)">编辑</el-button>
-						</div>
-					</div>
-					<div class="ant-descriptions-view">
-						<table>
-							<tbody>
-								<tr class="ant-descriptions-row">
-									<th class="ant-descriptions-item-label ant-descriptions-item-colon">设备标识</th>
-									<td class="ant-descriptions-item-content" colspan="1">{{ detail.key }}</td>
-									<th class="ant-descriptions-item-label ant-descriptions-item-colon">设备名称</th>
-									<td class="ant-descriptions-item-content" colspan="1">{{ detail.name }}</td>
-									<th class="ant-descriptions-item-label ant-descriptions-item-colon">所属产品</th>
-									<td class="ant-descriptions-item-content" colspan="1">{{ detail.productName }}</td>
-								</tr>
-								<tr class="ant-descriptions-row">
-									<th class="ant-descriptions-item-label ant-descriptions-item-colon">消息协议</th>
-									<td class="ant-descriptions-item-content" colspan="1">{{ prodetail.messageProtocol }}</td>
-									<th class="ant-descriptions-item-label ant-descriptions-item-colon">链接协议</th>
-									<td class="ant-descriptions-item-content" colspan="1">{{ prodetail.transportProtocol }}</td>
-									<th class="ant-descriptions-item-label ant-descriptions-item-colon">设备类型</th>
-									<td class="ant-descriptions-item-content" colspan="1">{{ prodetail.deviceType }}</td>
-								</tr>
-								<tr class="ant-descriptions-row">
-									<th class="ant-descriptions-item-label ant-descriptions-item-colon">固件版本</th>
-									<td class="ant-descriptions-item-content" colspan="1">{{ prodetail.version }}</td>
-									<th class="ant-descriptions-item-label ant-descriptions-item-colon">注册时间</th>
-									<td class="ant-descriptions-item-content" colspan="1">{{ detail.updatedAt }}</td>
-									<th class="ant-descriptions-item-label ant-descriptions-item-colon">最后上线时间</th>
-									<td class="ant-descriptions-item-content" colspan="1">{{ detail.lastOnlineTime || '' }}</td>
-								</tr>
-								<tr class="ant-descriptions-row">
-									<th class="ant-descriptions-item-label ant-descriptions-item-colon">说明</th>
-									<td class="ant-descriptions-item-content" colspan="5">{{ detail.desc }}</td>
-								</tr>
-							</tbody>
-						</table>
-					</div>
-				</el-tab-pane>
-				<el-tab-pane label="物模型" name="2">
-					<div class="wu-box">
-						<el-tabs type="border-card" v-model="activetab" @tab-click="wuhandleClick">
-							<el-tab-pane label="属性定义" name="attr">
-								<div class="wu-title">
-									<div class="title">属性定义</div>
-									<div>
-										<el-button type="primary" @click="onOpenEditAttr()">添加</el-button>
-									</div>
-								</div>
-
-								<el-table style="width: 100%" :data="tableData.data" v-if="activetab == 'attr'">
-									<el-table-column label="属性标识" align="center" prop="key" />
-									<el-table-column label="属性名称" prop="name" show-overflow-tooltip />
-									<el-table-column prop="valueType" label="数据类型" width="100" align="center">
-										<template #default="scope">
-											<span>{{ scope.row.valueType.type }}</span>
-										</template>
-									</el-table-column>
-									<el-table-column prop="decimals" label="精度" width="60" align="center">
-										<template #default="scope">
-											<span>{{ scope.row.valueType.decimals }}</span>
-										</template>
-									</el-table-column>
-									<el-table-column prop="unit" label="单位" width="60" align="center">
-										<template #default="scope">
-											<span>{{ scope.row.valueType.unit }}</span>
-										</template>
-									</el-table-column>
-									<el-table-column prop="accessMode" label="是否只读" width="120" align="center">
-										<template #default="scope">
-											<el-tag type="info" size="small" v-if="scope.row.accessMode">只读</el-tag>
-											<el-tag type="success" size="small" v-else>读写</el-tag>
-										</template>
-									</el-table-column>
-									<el-table-column label="说明" prop="desc" show-overflow-tooltip />
-									<el-table-column label="操作" width="300" align="center" fixed="right">
-										<template #default="scope">
-											<el-button size="small" text type="warning" @click="onEditAttr(scope.row)">修改</el-button>
-											<el-button size="small" text type="danger" @click="onRowDel(scope.row.key, 'attr')">删除</el-button>
-										</template>
-									</el-table-column>
-								</el-table>
-							</el-tab-pane>
-							<el-tab-pane label="功能定义" name="fun">
-								<div class="wu-title">
-									<div class="title">功能定义</div>
-									<div>
-										<el-button type="primary" @click="onOpenEditFun()">添加</el-button>
-									</div>
-								</div>
-
-								<el-table style="width: 100%" :data="tableData.data" v-if="activetab == 'fun'">
-									<el-table-column label="功能标识" align="center" prop="key" />
-									<el-table-column label="名称" prop="name" show-overflow-tooltip />
-
-									<el-table-column label="描述" prop="desc" show-overflow-tooltip />
-									<el-table-column label="操作" width="300" align="center" fixed="right">
-										<template #default="scope">
-											<el-button size="small" text type="warning" @click="onEditFun(scope.row)">修改</el-button>
-											<el-button size="small" text type="danger" @click="onRowDel(scope.row.key, 'fun')">删除</el-button>
-										</template>
-									</el-table-column>
-								</el-table>
-							</el-tab-pane>
-							<el-tab-pane label="事件定义" name="event">
-								<div class="wu-title">
-									<div class="title">事件定义</div>
-									<div>
-										<el-button type="primary" @click="onOpenEditEvent()">添加</el-button>
-									</div>
-								</div>
-
-								<el-table style="width: 100%" :data="tableData.data" v-if="activetab == 'event'">
-									<el-table-column label="事件标识" align="center" prop="key" />
-									<el-table-column label="名称" prop="name" show-overflow-tooltip />
-									<el-table-column prop="level" label="事件级别" width="120" align="center">
-										<template #default="scope">
-											<el-tag type="primary" size="small" v-if="scope.row.level == 0">普通</el-tag>
-											<el-tag type="warning" size="small" v-if="scope.row.level == 1">警告</el-tag>
-											<el-tag type="danger" size="small" v-if="scope.row.level == 2">紧急</el-tag>
-										</template>
-									</el-table-column>
-									<el-table-column label="描述" prop="desc" show-overflow-tooltip />
-
-									<el-table-column label="操作" width="300" align="center" fixed="right">
-										<template #default="scope">
-											<el-button size="small" text type="warning" @click="onEditEvent(scope.row)">修改</el-button>
-											<el-button size="small" text type="danger" @click="onRowDel(scope.row.key, 'event')">删除</el-button>
-										</template>
-									</el-table-column>
-								</el-table>
-							</el-tab-pane>
-							<el-tab-pane label="标签定义" name="tab">
-								<div class="wu-title">
-									<div class="title">标签定义</div>
-									<div>
-										<el-button type="primary" @click="onOpenEditTab()">添加</el-button>
-									</div>
-								</div>
-
-								<el-table style="width: 100%" :data="tableData.data" v-if="activetab == 'tab'">
-									<el-table-column label="属性标识" align="center" prop="key" />
-									<el-table-column label="属性名称" prop="name" show-overflow-tooltip />
-									<el-table-column prop="valueType" label="数据类型" width="120" align="center">
-										<template #default="scope">
-											<span>{{ scope.row.valueType.type }}</span>
-										</template>
-									</el-table-column>
-									<el-table-column prop="accessMode" label="是否只读" width="120" align="center">
-										<template #default="scope">
-											<el-tag type="info" size="small" v-if="scope.row.accessMode">只读</el-tag>
-											<el-tag type="success" size="small" v-else>读写</el-tag>
-										</template>
-									</el-table-column>
-									<el-table-column label="描述" prop="desc" show-overflow-tooltip />
-									<el-table-column label="操作" width="300" align="center" fixed="right">
-										<template #default="scope">
-											<el-button size="small" text type="warning" @click="onEditTag(scope.row)">修改</el-button>
-											<el-button size="small" text type="danger" @click="onRowDel(scope.row.key, 'tab')">删除</el-button>
-										</template>
-									</el-table-column>
-								</el-table>
-							</el-tab-pane>
-						</el-tabs>
-						<pagination v-show="tableData.total > 0" :total="tableData.total" v-model:page="tableData.param.pageNum" v-model:limit="tableData.param.pageSize" @pagination="getList()" />
-					</div>
-				</el-tab-pane>
-
-				<el-tab-pane label="日志管理" name="4">
-					<div class="system-user-search mb15">
-						<el-form :model="logtableData.param" ref="queryRef" inline label-width="68px">
-							<el-form-item label="日志类型" prop="types">
-								<el-select v-model="logtableData.param.types" placeholder="日志类型" clearable>
-									<el-option v-for="item in logTypeData" :key="item" :label="item" :value="item" />
-								</el-select>
-							</el-form-item>
-
-							<el-form-item label="创建时间" prop="dateRange">
-								<el-date-picker v-model="logtableData.param.dateRange" value-format="YYYY-MM-DD" type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker>
-							</el-form-item>
-							<el-form-item>
-								<el-button type="primary" class="ml10" @click="getlog">
-									<el-icon>
-										<ele-Search />
-									</el-icon>
-									查询
-								</el-button>
-								<el-button @click="resetQuery(queryRef)">
-									<el-icon>
-										<ele-Refresh />
-									</el-icon>
-									重置
-								</el-button>
-							</el-form-item>
-						</el-form>
-					</div>
-					<el-table style="width: 100%" :data="logtableData.data">
-						<el-table-column label="类型" align="center" prop="type" />
-						<el-table-column label="时间" prop="ts" show-overflow-tooltip />
-
-						<el-table-column label="内容" prop="content" show-overflow-tooltip />
-						<el-table-column label="操作" width="300" align="center" fixed="right">
-							<template #default="scope">
-								<el-button size="small" text type="warning" @click="onLogDetail(scope.row)">查看</el-button>
-							</template>
-						</el-table-column>
-					</el-table>
-
-					<pagination v-show="logtableData.total > 0" :total="logtableData.total" v-model:page="logtableData.param.pageNum" v-model:limit="logtableData.param.pageSize" @pagination="getlog" />
-				</el-tab-pane>
-			</el-tabs>
-		</div>
-		<EditDic ref="editDicRef" @typeList="typeList" />
-		<EditAttr ref="editAttrRef" @typeList="getproperty" />
-		<EditFun ref="editFunRef" @typeList="getfunction" />
-		<EditEvent ref="editEventRef" @typeList="getevent" />
-		<EditTab ref="editTabRef" @typeList="gettab" />
-		<ListDic ref="listDicRef" />
-
-		<el-dialog v-model="dialogVisible" title="返回Json数据" width="30%">
-			<JsonViewer :value="jsonData" boxed sort theme="jv-dark" @click="onKeyclick" />
-
-			<template #footer>
-				<span class="dialog-footer">
-					<el-button @click="dialogVisible = false">关闭</el-button>
-				</span>
-			</template>
-		</el-dialog>
-	</div>
-</template>
-<script lang="ts">
-import { toRefs, reactive, onMounted, ref, defineComponent } from 'vue';
-import { ElMessageBox, ElMessage, FormInstance } from 'element-plus';
-
-import 'vue3-json-viewer/dist/index.css';
-
-import EditDic from '../product/component/editPro.vue';
-import EditAttr from '../product/component/editAttr.vue';
-import EditFun from '../product/component/editFun.vue';
-import EditEvent from '../product/component/editEvent.vue';
-import EditTab from '../product/component/editTab.vue';
-import devantd from '/@/components/devantd/index.vue';
-import ListDic from './component/list.vue';
-
-import { useRoute } from 'vue-router';
-
-import api from '/@/api/device';
-
-interface TableDataState {
-	ids: number[];
-	tableData: {
-		data: [];
-		total: number;
-		loading: boolean;
-		param: {
-			pageNum: number;
-			pageSize: number;
-			name: string;
-			deviceType: string;
-			status: string;
-			dateRange: string[];
-		};
-	};
-	logtableData: {
-		data: [];
-		total: number;
-		loading: boolean;
-		param: {
-			pageNum: number;
-			pageSize: number;
-			name: string;
-			deviceType: string;
-			status: string;
-			dateRange: string[];
-		};
-	};
-}
-export default defineComponent({
-	name: 'deviceEditPro',
-	components: { EditDic, EditAttr, EditFun, EditEvent, EditTab, devantd, ListDic },
-
-	setup(prop, context) {
-		const route = useRoute();
-		const editDicRef = ref();
-		const editAttrRef = ref();
-		const editFunRef = ref();
-		const listDicRef = ref();
-		const editEventRef = ref();
-		const editTabRef = ref();
-		const state = reactive<TableDataState>({
-			areaData: [],
-			isShowDialog: false,
-			dialogVisible: false,
-			logTypeData: [],
-			jsonData: '',
-			activeName: '3', // 分类数据
-			activetab: 'attr', // 分类数据
-			detail: [],
-			prodetail: [],
-			product_id: 0,
-			developer_status: 0,
-			tableData: {
-				data: [],
-				total: 0,
-				loading: false,
-				param: {
-					pageNum: 1,
-					productId: 0,
-					pageSize: 10,
-					status: '',
-					dateRange: [],
-				},
-			},
-			logtableData: {
-				data: [],
-				total: 0,
-				loading: false,
-				param: {
-					pageNum: 1,
-					productId: 0,
-					pageSize: 10,
-					status: '',
-					dateRange: [],
-				},
-			},
-		});
-
-		onMounted(() => {
-			const ids = route.params && route.params.id;
-			api.instance.detail(ids).then((res: any) => {
-				state.detail = res.data;
-				state.developer_status = res.data.status;
-				state.tableData.param.productId = res.data.product.id;
-				state.product_id = res.data.product.id;
-				getrunData();
-				api.product.detail(res.data.product.id).then((res: any) => {
-					state.prodetail = res.data;
-				});
-
-				//第一次加载
-				api.model.property(state.tableData.param).then((res: any) => {
-					state.tableData.data = res.Data;
-					state.tableData.total = res.Total;
-				});
-			});
-		});
-
-		const onLogDetail = (row: TableDataRow) => {
-			state.jsonData = JSON.parse(row.content);
-			state.dialogVisible = true;
-		};
-
-		//编辑属性
-		const onEditAttr = (row: TableDataRow) => {
-			editAttrRef.value.openDialog(row, state.product_id);
-		};
-
-		//编辑功能
-		const onEditFun = (row: TableDataRow) => {
-			editFunRef.value.openDialog(row, state.product_id);
-		};
-
-		//编辑事件
-		const onEditEvent = (row: TableDataRow) => {
-			editEventRef.value.openDialog(row, state.product_id);
-		};
-
-		//编辑标签
-		const onEditTag = (row: TableDataRow) => {
-			editTabRef.value.openDialog(row, state.product_id);
-		};
-
-		//打开添加属性弹窗
-		const onOpenEditAttr = () => {
-			editAttrRef.value.openDialog({ product_id: state.product_id, id: 0, accessMode: 0 });
-		};
-
-		//打开添加功能弹窗
-		const onOpenEditFun = () => {
-			editFunRef.value.openDialog({ product_id: state.product_id, id: 0 });
-		};
-		//打开添加事件弹窗
-		const onOpenEditEvent = () => {
-			editEventRef.value.openDialog({ product_id: state.product_id, id: 0, level: 0 });
-		};
-
-		//打开添加事件弹窗
-		const onOpenEditTab = () => {
-			editTabRef.value.openDialog({ product_id: state.product_id, id: 0, accessMode: 0 });
-		};
-
-		//查看日志列表
-		const onOpenListDetail = (row: TableDataRow) => {
-			listDicRef.value.openDialog(row, state.detail.id);
-		};
-
-		// 打开修改产品弹窗
-		const onOpenEditDic = (row: TableDataRow) => {
-			editDicRef.value.openDialog(row);
-		};
-
-		// 删除产品
-		const onRowDel = (key, type) => {
-			let msg = `此操作将永久删除该数据,是否继续?`;
-
-			if (key.length === 0) {
-				ElMessage.error('请选择要删除的数据。');
-				return;
-			}
-			ElMessageBox.confirm(msg, '提示', {
-				confirmButtonText: '确认',
-				cancelButtonText: '取消',
-				type: 'warning',
-			})
-				.then(() => {
-					if (type == 'attr') {
-						api.model.propertydel(state.product_id, key).then(() => {
-							ElMessage.success('删除成功');
-							getproperty();
-						});
-					}
-					if (type == 'fun') {
-						api.model.functiondel(state.product_id, key).then(() => {
-							ElMessage.success('删除成功');
-							getfunction();
-						});
-					}
-					if (type == 'event') {
-						api.model.eventdel(state.product_id, key).then(() => {
-							ElMessage.success('删除成功');
-							getevent();
-						});
-					}
-					if (type == 'tab') {
-						api.model.tagdel(state.product_id, key).then(() => {
-							ElMessage.success('删除成功');
-							tagdel();
-						});
-					}
-				})
-				.catch(() => { });
-		};
-
-		//根据不同类型获取列表
-		const getList = () => {
-			switch (state.activetab) {
-				case 'attr':
-					getproperty();
-					break;
-				case 'fun':
-					getfunction();
-					break;
-				case 'event':
-					getevent();
-					break;
-				case 'tab':
-					gettab();
-					break;
-			}
-		};
-
-		const getproperty = () => {
-			api.model.property(state.tableData.param).then((res: any) => {
-				state.tableData.data = res.Data;
-				state.tableData.total = res.Total;
-			});
-		};
-
-		const getfunction = () => {
-			api.model.function(state.tableData.param).then((res: any) => {
-				state.tableData.data = res.Data;
-				state.tableData.total = res.Total;
-			});
-		};
-		const getevent = () => {
-			api.model.event(state.tableData.param).then((res: any) => {
-				state.tableData.data = res.Data;
-				state.tableData.total = res.Total;
-			});
-		};
-
-		const gettab = () => {
-			api.model.tag(state.tableData.param).then((res: any) => {
-				state.tableData.data = res.Data;
-				state.tableData.total = res.Total;
-			});
-		};
-
-		const wuhandleClick = (tab: TabsPaneContext) => {
-			state.activetab = tab.props.name;
-			switch (tab.props.name) {
-				case 'attr':
-					getproperty();
-					break;
-				case 'fun':
-					getfunction();
-					break;
-				case 'event':
-					getevent();
-					break;
-				case 'tab':
-					gettab();
-					break;
-			}
-		};
-
-		const handleClick = (tab: TabsPaneContext, event: Event) => {
-			if (tab.props.name == 4) {
-				//获取日志
-				getlog();
-				getlogtype();
-			} else if (tab.props.name == 2) {
-				getList();
-			} else if (tab.props.name == 3) {
-				getrunData();
-			}
-		};
-
-		const getrunData = () => {
-			api.instance.getrun_status({ deviceKey: state.detail.key }).then((res: any) => {
-				state.areaData = res;
-				let properties = state.areaData.properties || [];
-
-				var temp = new Array();
-
-				properties.forEach(function (item, index) {
-					let datalist = item.list || [];
-					temp[index] = [];
-					var temps = new Array();
-					datalist.forEach(function (a, b) {
-						if (b < 15) {
-							temps.push(a);
-						}
-					});
-					temp[index]['name'] = item.name;
-					temp[index]['key'] = item.key;
-					temp[index]['type'] = item.type;
-					temp[index]['unit'] = item.unit;
-					temp[index]['value'] = item.value;
-					temp[index]['list'] = temps;
-				});
-
-				state.areaData.properties = temp;
-			});
-		};
-
-		const getlogtype = () => {
-			api.instance.getlogcate({}).then((res: any) => {
-				state.logTypeData = res.list;
-			});
-		};
-
-		const getlog = () => {
-			state.logtableData.param.deviceKey = state.detail.key;
-			api.instance.getLogList(state.logtableData.param).then((res: any) => {
-				state.logtableData.data = res.list;
-				state.logtableData.total = res.Total;
-			});
-		};
-
-		const CkOption = () => {
-			if (state.developer_status == 2) {
-				api.instance.devoffline({ deviceKey: state.detail.key }).then((res: any) => {
-					ElMessage.success('操作成功');
-					state.developer_status = 1;
-				});
-			} else {
-				api.instance.devonline({ deviceKey: state.detail.key }).then((res: any) => {
-					ElMessage.success('操作成功');
-					state.developer_status = 2;
-				});
-			}
-		};
-		const tinyAreas = () => {
-			var data = state.data;
-
-			const tinyArea = new TinyArea('container', {
-				height: 60,
-				autoFit: false,
-				data,
-				smooth: true,
-				areaStyle: {
-					fill: '#d6e3fd',
-				},
-			});
-			tinyArea.render();
-		};
-		return {
-			tinyAreas,
-			editDicRef,
-			editAttrRef,
-			listDicRef,
-			editFunRef,
-			editEventRef,
-			editTabRef,
-			onOpenListDetail,
-			getrunData,
-			getlog,
-			getlogtype,
-			onLogDetail,
-			CkOption,
-			onRowDel,
-			onEditFun,
-			onEditEvent,
-			onEditTag,
-			onEditAttr,
-			getList,
-			getproperty,
-			getfunction,
-			getevent,
-			gettab,
-			wuhandleClick,
-			onOpenEditTab,
-			onOpenEditEvent,
-			onOpenEditAttr,
-			onOpenEditFun,
-			onOpenEditDic,
-			handleClick,
-			...toRefs(state),
-		};
-	},
-});
-</script>
-<style scoped>
-.content {
-	background: #fff;
-	width: 100%;
-	padding: 20px;
-}
-
-.content-box {
-	background: #fff;
-	width: 100%;
-	padding: 20px;
-	margin-top: 20px;
-}
-
-.cont_box {
-	display: flex;
-}
-
-.cont_box .title {
-	font-size: 24px;
-}
-
-.cont_box .pro-status {
-	line-height: 40px;
-	margin-left: 30px;
-}
-
-.cont_box .pro-status .on {
-	background: #52c41a;
-}
-
-.cont_box .pro-status .off {
-	background: #c41a1a;
-}
-
-.cont_box .pro-status span {
-	position: relative;
-	top: -1px;
-	display: inline-block;
-	width: 6px;
-	height: 6px;
-	vertical-align: middle;
-	border-radius: 50%;
-	margin-right: 5px;
-}
-
-.cont_box .pro-option {
-	line-height: 40px;
-	margin-left: 10px;
-	color: #1890ff;
-	cursor: pointer;
-}
-
-.content-box .pro-box {
-	display: flex;
-	padding: 10px;
-	justify-content: space-between;
-}
-
-.content-box .pro-box .protitle {
-	font-size: 18px;
-	font-weight: bold;
-	line-height: 35px;
-}
-
-.content-box .pro-box .buttonedit {
-	border: 0px;
-	color: #1890ff;
-}
-
-table {
-	border-collapse: collapse;
-	text-indent: initial;
-	border-spacing: 2px;
-}
-
-tbody {
-	box-sizing: border-box;
-	display: table-row-group;
-	vertical-align: middle;
-	border-color: inherit;
-}
-
-tr {
-	display: table-row;
-	vertical-align: inherit;
-	border-color: inherit;
-}
-
-.ant-descriptions-view {
-	width: 100%;
-	overflow: hidden;
-	border-radius: 4px;
-}
-
-.ant-descriptions-view {
-	border: 1px solid #e8e8e8;
-}
-
-.ant-descriptions-view table {
-	width: 100%;
-	table-layout: fixed;
-}
-
-.ant-descriptions-view>table {
-	table-layout: auto;
-}
-
-.ant-descriptions-row {
-	border-bottom: 1px solid #e8e8e8;
-}
-
-.ant-descriptions-item-label {
-	color: rgba(0, 0, 0, 0.85);
-	font-weight: 400;
-	font-size: 14px;
-	line-height: 1.5;
-}
-
-.ant-descriptions-item-label {
-	padding: 16px 24px;
-	border-right: 1px solid #e8e8e8;
-}
-
-.ant-descriptions-item-label {
-	background-color: #fafafa;
-}
-
-.ant-descriptions-item-content {
-	padding: 16px 24px;
-	border-right: 1px solid #e8e8e8;
-	display: table-cell;
-	color: rgba(0, 0, 0, 0.65);
-	font-size: 14px;
-	line-height: 1.5;
-}
-
-.wu-box {
-	border: #e8e8e8 solid 1px;
-	padding: 20px;
-	width: 100%;
-}
-
-.wu-box .wu-title {
-	display: flex;
-	flex-direction: row;
-	justify-content: space-between;
-	padding: 20px;
-	border-bottom: #e8e8e8 1px solid;
-}
-
-.wu-box .wu-title .title {
-	font-size: 18px;
-}
-
-.ant-card {
-	box-sizing: border-box;
-	margin: 10px;
-	width: 23.2%;
-	font-size: 14px;
-	font-variant: tabular-nums;
-	border: 1px solid var(--next-border-color-light);
-
-	line-height: 1.5;
-	list-style: none;
-	font-feature-settings: 'tnum';
-	position: relative;
-	border-radius: 2px;
-	transition: all 0.3s;
-}
-
-.ant-card-body {
-	padding: 24px;
-	zoom: 1;
-}
-
-.cardflex {
-	display: flex;
-	justify-content: space-between;
-}
-
-.statusname {
-	font-size: 30px;
-	margin-top: 10px;
-	margin-bottom: 15px;
-}
-
-.comtest {
-	margin-top: 20px;
-	height: 30px;
-	line-height: 30px;
-}</style>

+ 8 - 10
src/views/iot/ice104/device/component/edit.vue

@@ -36,20 +36,19 @@
 	</el-dialog>
 </template>
 <script lang="ts" setup>
-import { computed, reactive, ref, onMounted } from 'vue';
+import { computed, ref, onMounted } from 'vue';
 import api from '/@/api/ice104/index';
-import { useI18n } from 'vue-i18n';
 import { ElMessage } from 'element-plus';
 import { useSearch } from '/@/hooks/useCommonIce104';
 import apiDevice from '/@/api/device';
 
-const { params, tableData, getList, loading } = useSearch(api.template.getAll, 'data', { title: '', status: 1 });
+const { tableData, getList } = useSearch(api.template.getAll, 'data', { title: '', status: 1 });
 getList();
 
 const dialogVisible = ref(false);
 const btnLoading = ref(false);
-const productList = ref([]);
-const deviceList = ref([]);
+const productList = ref<any[]>([]);
+const deviceList = ref<any[]>([]);
 const emit = defineEmits(['updateList']);
 const formRef = ref();
 const ruleForm = ref({
@@ -95,14 +94,13 @@ const submitData = async () => {
 	})
 }
 
-const handleProductChange = (data: any) => {
+const handleProductChange = (productKey: string) => {
 	ruleForm.value.deviceKey = "";
-	let findItem: any = productList.value.find((v: any) => v.key === data);
-	getDeviceList(findItem.id)
+	getDeviceList(productKey)
 }
 
-const getDeviceList = (id: number) => {
-	apiDevice.device.allList({ productId: id }).then((res: any) => {
+const getDeviceList = (productKey: string) => {
+	apiDevice.device.allList({ productKey }).then((res: any) => {
 		deviceList.value = res.device
 	})
 }

+ 8 - 13
src/views/iot/ice104/device/component/editDeviceForm.vue

@@ -18,7 +18,7 @@
 			</el-select>
 		</el-form-item>
 		<el-form-item label="产品key">
-			<el-select @change="(val) => handleProductChange(val, true)" v-model="ruleForm.productKey" placeholder="请选择产品key" class="width100">
+			<el-select @change="(val: string) => handleProductChange(val, true)" v-model="ruleForm.productKey" placeholder="请选择产品key" class="width100">
 				<el-option :label="item.name" :value="item.key" v-for="(item, index) in productList" :key="index" />
 			</el-select>
 		</el-form-item>
@@ -43,8 +43,8 @@ const { params, tableData, getList, loading } = useSearch(api.template.getAll, '
 getList();
 
 const btnLoading = ref(false);
-const productList = ref([]);
-const deviceList = ref([]);
+const productList = ref<any[]>([]);
+const deviceList = ref<any[]>([]);
 const emit = defineEmits(['updateList']);
 const formRef = ref();
 const ruleForm = ref({
@@ -80,22 +80,17 @@ const submitData = async () => {
 	})
 }
 
-const handleProductChange = (data: any, isClear: boolean) => {
-	if (isClear) {
-		ruleForm.value.deviceKey = "";
-	}
-	let findItem: any = productList.value.find((v: any) => v.key === data);
-	if (!findItem) return;
-	getDeviceList(findItem.id)
+const handleProductChange = (productKey: string, isClear: boolean) => {
+	if (isClear) ruleForm.value.deviceKey = ""
+	getDeviceList(productKey)
 }
 
-const getDeviceList = (id: number) => {
-	apiDevice.device.allList({ productId: id }).then((res: any) => {
+const getDeviceList = (productKey: string) => {
+	apiDevice.device.allList({ productKey }).then((res: any) => {
 		deviceList.value = res.device
 	})
 }
 
-
 const open = async (row: any) => {
 	if (row && row.number.toString()) {
 		ruleForm.value = row;

+ 2 - 2
src/views/iot/iotCard/dashboard.vue

@@ -610,7 +610,7 @@ watch(
       justify-content: space-between;
       align-items: center;
       margin-bottom: 16px;
-      ::v-deep .el-date-editor.el-input__wrapper {
+      :deep(.el-date-editor.el-input__wrapper) {
         width: 360px!important;
         margin-left: 12px;
       }
@@ -629,7 +629,7 @@ watch(
       justify-content: space-between;
       align-items: center;
       margin-bottom: 16px;
-      ::v-deep .el-date-editor.el-input__wrapper {
+      :deep(.el-date-editor.el-input__wrapper) {
         max-width: 220px!important;
       }
     }

+ 1 - 1
src/views/iot/iotCard/index/detail.vue

@@ -659,7 +659,7 @@ watch(
       justify-content: space-between;
       align-items: center;
       margin-bottom: 16px;
-      ::v-deep .el-date-editor.el-input__wrapper {
+      :deep(.el-date-editor.el-input__wrapper) {
         width: 360px!important;
         margin-left: 12px;
       }

+ 130 - 72
src/views/iot/iotmanager/dashboard.vue

@@ -6,12 +6,10 @@
 					<div>{{ v.num3 }}</div>
 					<div class="flex-margin flex w100" :class="` home-one-animation${k}`">
 						<div class="flex-auto">
-
 							<span class="font30">{{ v.allnum }}</span>
 						</div>
 						<div class="home-card-item-icon flex">
 							<img :src="'/imgs/' + v.icoimg" class="icoimg">
-
 						</div>
 					</div>
 					<div class="flex" style="font-weight: bold;">
@@ -81,12 +79,13 @@
 </template>
 
 <script lang="ts">
-import { toRefs, reactive, defineComponent, onMounted, ref, watch, nextTick, onActivated } from 'vue';
+import { toRefs, reactive, defineComponent, onMounted, ref, watch, nextTick, onActivated, getCurrentInstance, onUnmounted } from 'vue';
 import * as echarts from 'echarts';
-import { useRouter } from 'vue-router';
+import { useRouter, useRoute } from 'vue-router';
 import { useStore } from '/@/store/index';
 
 import api from '/@/api/datahub';
+import dayjs from 'dayjs';
 
 import EditDic from '../alarm/log/component/edit.vue';
 import DetailDic from '../alarm/log/component/detail.vue';
@@ -102,6 +101,32 @@ export default defineComponent({
 	name: 'home',
 	components: { EditDic, DetailDic },
 	setup() {
+
+		let timer1: any
+		let timer2: any
+
+		onUnmounted(() => {
+			clearInterval(timer1)
+			clearInterval(timer2)
+		})
+
+		const { proxy } = getCurrentInstance() as any;
+		const { alarm_type } = proxy.useDict('alarm_type');
+		const alarmTypeMap: any = {}
+
+		// 监听告警类型是否获取成功
+		watch(() => alarm_type.value, (list) => {
+			if (!list.length) return
+			list.forEach((item: any) => {
+				alarmTypeMap[item.value] = item.label
+			});
+
+			getChartData()
+
+		}, {
+			immediate: true
+		})
+
 		const editDicRef = ref();
 		const detailRef = ref();
 		const homeLineRef = ref();
@@ -124,9 +149,9 @@ export default defineComponent({
 			},
 			homeOne: [
 				{
-					allnum: '0',
-					num1: '0',
-					num2: '0',
+					allnum: 0,
+					num1: 0,
+					num2: 0,
 					num3: '产品',
 					num4: 'icon-zidingyibuju',
 					color1: '#6690F9',
@@ -140,47 +165,47 @@ export default defineComponent({
 
 				},
 				{
-					allnum: '0',
-					num1: '0',
-					num2: '0',
-					num3: '设备',
+					allnum: 0,
+					num1: 0,
+					num2: 0,
+					num3: '在线设备',
 					num4: 'icon-putong',
 					color1: '#FF6462',
 					color2: '--next-color-primary-lighter',
 					color3: '--el-color-primary',
 					icoimg: 'index_device.svg',
-					title1: '在线',
-					title2: '离线',
+					title1: '启用',
+					title2: '停用',
 					title1_bgcolor: '#3cd357',
 					title2_bgcolor: '#c1bbbb',
 				},
 				{
-					allnum: '0',
-					num1: '0',
-					num2: '0',
+					allnum: 0,
+					num1: 0,
+					num2: 0,
 					num3: '设备消息',
 					num4: 'icon-shidu',
 					color1: '#6690F9',
 					color2: '--el-color-success-lighter',
 					color3: '--el-color-success',
 					icoimg: 'index_sensor.svg',
-					title1: '总量',
+					title1: '本月',
 					title2: '今日',
 					title1_bgcolor: '#c1bbbb',
 					title2_bgcolor: '#18f3ff',
 				},
 				{
-					allnum: '0',
-					num1: '0',
-					num2: '0',
+					allnum: 0,
+					num1: 0,
+					num2: 0,
 					num3: '设备告警',
 					num4: 'icon-zaosheng',
 					color1: '#6690F9',
 					color2: '--el-color-warning-lighter',
 					color3: '--el-color-warning',
 					icoimg: 'index_alarm.svg',
-					title1: '总量',
-					title2: '新增',
+					title1: '本月',
+					title2: '今日',
 					title1_bgcolor: '#c1bbbb',
 					title2_bgcolor: '#ff1818',
 				},
@@ -191,7 +216,7 @@ export default defineComponent({
 				bgColor: '',
 				color: '#303133',
 			},
-			lineChartXAxisDat: [],
+			lineChartXAxisData: [],
 			lineChartMsgTotalData: [],
 			lineChartAlarmTotalData: [],
 			pieChartLegend: [],
@@ -209,7 +234,7 @@ export default defineComponent({
 					x: 'left',
 					textStyle: { fontSize: '15', color: state.charts.color },
 				},
-				grid: { top: 70, right: 20, bottom: 30, left: 30 },
+				grid: { top: 70, right: 20, bottom: 30, left: 50 },
 				tooltip: { trigger: 'axis' },
 				legend: { data: ['消息量', '预警量'], right: 0 },
 				xAxis: {
@@ -389,55 +414,76 @@ export default defineComponent({
 		const initEchartsResize = () => {
 			window.addEventListener('resize', initEchartsResizeFun);
 		};
-		const getOverviewData = () => {
-			api.iotManage.getOverviewData().then((res: any) => {
-				const { overview, device, alarmLevel } = res;
-				// overview
-				// "deviceTotal": 8, //设备总量
-				// "deviceOffline": 4, //离线设备数量
-				// "productTotal": 6, //产品总量
-				// "productAdded": 0, //今日产品增量
-				// "msgTotal": 107246, //设备消息总量
-				// "msgAdded": 7391, //今日设备消息增量
-				// "alarmTotal": 43, //设备报警总量
-				// "alarmAdded": 0 //今日设备报警增量
-				state.homeOne[0].allnum = overview.productTotal;
-				state.homeOne[0].num1 = `${overview.productActivation}`;
-				state.homeOne[0].num2 = `${overview.productDeactivation}`;
-				state.homeOne[1].allnum = overview.deviceTotal;
-				state.homeOne[1].num1 = `${overview.deviceTotal - overview.deviceOffline}`;
-				state.homeOne[1].num2 = `${overview.deviceOffline}`;
-				state.homeOne[2].allnum = overview.msgTotal;
-				state.homeOne[2].num1 = overview.msgTotal;
-				state.homeOne[2].num2 = `${overview.msgAdded}`;
-				state.homeOne[3].allnum = overview.alarmTotal;
-				state.homeOne[3].num1 = overview.alarmTotal;
-				state.homeOne[3].num2 = `${overview.alarmAdded}`;
-
-				// device
-				// msgTotal 设备消息量月度统计
-				// alarmTotal 设备告警量月度统计
-				state.lineChartMsgTotalData = [];
-				state.lineChartAlarmTotalData = [];
-				state.lineChartXAxisData = Object.keys(device.msgTotal).map((item: any) => {
-					state.lineChartMsgTotalData.push(device.msgTotal[item]);
-					state.lineChartAlarmTotalData.push(device.alarmTotal[item]);
-					return `${item}月`
-				})
-
-				// alarmLevel
-				// "level": 4, //级别
-				// "name": "一般", //级别名称
-				// "num": 43, //该级别日志数量
-				// "ratio": 100 //该级别日志数量占比(百分比)
-				state.pieChartLegend = [];
-				state.pieChartLevel = [];
-				alarmLevel && alarmLevel.map((item: any) => {
-					state.pieChartLegend.push(item.name)
-					state.pieChartData.push(item.ratio)
-					state.pieChartLevel.push(item.level)
-				})
+
+		// 定时获取设备,在线信息,告警数量更新
+		function getLoopData() {
+			// 产品数量
+			api.iotManage.productCount().then((res: any) => {
+				state.homeOne[0].allnum = res.total;
+				state.homeOne[0].num1 = res.enable
+				state.homeOne[0].num2 = res.disable
+			})
+
+			api.iotManage.deviceDataTotalCount('year').then((res: any) => {
+				state.homeOne[2].allnum = res.number;
+			})
+			api.iotManage.deviceDataTotalCount('month').then((res: any) => {
+				state.homeOne[2].num1 = res.number;
+			})
+			api.iotManage.deviceDataTotalCount('day').then((res: any) => {
+				state.homeOne[2].num2 = res.number;
+			})
+			api.iotManage.deviceOnlineOfflineCount().then((res: any) => {
+				// console.log(res)
+				state.homeOne[1].allnum = res.online;
+				state.homeOne[1].num1 = res.total - res.disable
+				state.homeOne[1].num2 = res.disable
+			})
+
+			// 按告警级别统计
+			api.iotManage.deviceAlarmLevelCount('year', dayjs().format('YYYY')).then((res: any) => {
+				const list = (res.data || [])
+				const total = list.reduce((a: any, b: any) => a + b.Value, 0)
+				state.homeOne[3].allnum = total;
 			})
+			api.iotManage.deviceAlarmLevelCount('month', dayjs().format('M')).then((res: any) => {
+				const total = (res.data || []).reduce((a: any, b: any) => a + b.Value, 0)
+				state.homeOne[3].num1 = total;
+			})
+			api.iotManage.deviceAlarmLevelCount('day', dayjs().format('D')).then((res: any) => {
+				const total = (res.data || []).reduce((a: any, b: any) => a + b.Value, 0)
+				state.homeOne[3].num2 = total;
+			})
+		}
+
+		// 获取告警告警数量和消息数量绘图
+		function getChartData() {
+			// 获取年度消息,年度告警数量
+			Promise.all([api.iotManage.deviceDataCount('year'), api.iotManage.deviceAlertCountByYearMonth(dayjs().format('YYYY'))]).then(([msg, alarm]: any) => {
+				const msgArr = msg?.data || []
+				const alarmArr = alarm?.data || []
+				// console.log(alarmArr)
+				state.lineChartMsgTotalData = msgArr.map((item: any) => item.Value)
+				state.lineChartXAxisData = msgArr.map((item: any) => item.Title)
+				state.lineChartAlarmTotalData = alarmArr.map((item: any) => item.Value)
+			})
+			// 按告警级别统计 绘制饼图
+			api.iotManage.deviceAlarmLevelCount('year', dayjs().format('YYYY')).then((res: any) => {
+				const list = (res.data || []).sort((a: any, b: any) => b.Title - a.Title)
+				state.pieChartLegend = list.map((item: any) => alarmTypeMap[item.Title])
+				state.pieChartLevel = list.map((item: any) => item.Title)
+				state.pieChartData = list.map((item: any) => item.Value)
+			})
+		}
+
+		// 每隔3秒更新数据
+		timer1 = setInterval(getLoopData, 3000)
+
+		// 每隔一分钟秒更新图形
+		timer2 = setInterval(getChartData, 60000)
+
+		const getOverviewData = () => {
+			getLoopData()
 		};
 		const getAlarmList = () => {
 			api.iotManage.getAlarmList(state.tableData.param).then((res: any) => {
@@ -507,6 +553,18 @@ export default defineComponent({
 				immediate: true,
 			}
 		);
+		watch(
+			() => state.lineChartMsgTotalData,
+			() => {
+				initLineChart();
+			}
+		);
+		watch(
+			() => state.pieChartData,
+			() => {
+				initPieChart();
+			}
+		);
 		return {
 			homeLineRef,
 			homePieRef,

+ 2 - 1
src/views/iot/network/server/component/list.vue

@@ -178,8 +178,9 @@ export default defineComponent({
 </script>
 
 <style lang="scss" scoped>
-::v-deep div.more-opearte-wrap {
+:deep(div.more-opearte-wrap) {
   flex-direction: row;
   background-color: pink;
+  // padding: 4px!important;
 }
 </style>

+ 5 - 5
src/views/iot/network/server/create.vue

@@ -363,7 +363,7 @@ export default defineComponent({
 }
 </style>
 <style lang="scss" scoped>
-::v-deep .el-collapse-item__header {
+:deep(.el-collapse-item__header) {
   position: relative;
   padding-left: 20px;
 
@@ -376,16 +376,16 @@ export default defineComponent({
   }
 }
 
-::v-deep .el-input,
-::v-deep .el-input-number {
+:deep(.el-input),
+:deep(.el-input-number) {
   width: 500px;
 }
 
-::v-deep .params {
+:deep(.params) {
   width: 600px;
 }
 
-::v-deep .flex-column {
+:deep(.flex-column) {
   display: flex;
   flex-direction: column;
 

+ 5 - 5
src/views/iot/network/server/edit.vue

@@ -375,7 +375,7 @@ export default defineComponent({
 });
 </script>
 <style lang="scss" scoped>
-::v-deep .el-collapse-item__header {
+:deep(.el-collapse-item__header) {
   position: relative;
   padding-left: 20px;
 
@@ -388,16 +388,16 @@ export default defineComponent({
   }
 }
 
-::v-deep .el-input,
-::v-deep .el-input-number {
+:deep(.el-input),
+:deep(.el-input-number) {
   width: 500px;
 }
 
-::v-deep .params {
+:deep(.params) {
   width: 600px;
 }
 
-::v-deep .flex-column {
+:deep(.flex-column) {
   display: flex;
   flex-direction: column;
 

+ 1 - 5
src/views/iot/network/tunnel/component/list.vue

@@ -172,12 +172,8 @@ export default defineComponent({
 </script>
 
 <style lang="scss" scoped>
-::v-deep div.more-opearte-wrap {
+:deep(div.more-opearte-wrap) {
   flex-direction: row;
   background-color: pink;
-
-  // padding: 4px!important;
-  div {}
-
 }
 </style>

+ 4 - 4
src/views/iot/network/tunnel/create.vue

@@ -264,7 +264,7 @@ export default defineComponent({
 }
 </style>
 <style lang="scss" scoped>
-::v-deep .el-collapse-item__header {
+:deep(.el-collapse-item__header) {
   position: relative;
   padding-left: 20px;
 
@@ -277,12 +277,12 @@ export default defineComponent({
   }
 }
 
-::v-deep .el-input,
-::v-deep .el-input-number {
+:deep(.el-input),
+:deep(.el-input-number) {
   width: 500px;
 }
 
-::v-deep .params {
+:deep(.params) {
   width: 600px;
 }
 </style>

+ 8 - 8
src/views/iot/network/tunnel/edit.vue

@@ -256,9 +256,9 @@ export default defineComponent({
 }
 </style>
 <style lang="scss" scoped>
-::v-deep .el-collapse-item__header {
-  position: relative;
-  padding-left: 20px;
+:deep(.el-collapse-item__header) {
+    position: relative;
+    padding-left: 20px;
 
   .el-collapse-item__arrow {
     margin: 0 !important;
@@ -269,13 +269,13 @@ export default defineComponent({
   }
 }
 
-::v-deep .el-input,
-::v-deep .el-input-number {
-  width: 500px;
+:deep(.el-input),
+:deep(.el-input-number) {
+    width: 500px;
 }
 
-::v-deep .params {
-  width: 600px;
+:deep(.params) {
+    width: 600px;
 }
 </style>
 

+ 47 - 67
src/views/iot/ota-update/data/index.vue

@@ -1,58 +1,54 @@
 <template>
 	<el-card shadow="nover">
 		<el-tabs v-model="activeTab">
-				<el-tab-pane label="版本分布" name="tab1">
-					<div class="flex">
-						<el-form-item label="所属产品" prop="productId">
-							<el-select v-model="productId" filterable placeholder="请选择产品">
-								<el-option v-for="item in productData" :key="item.id" :label="item.name" :value="item.id.toString()" value-key="id">
-								</el-option>
-							</el-select>
-						</el-form-item>
-						<el-form-item label="所属模块" prop="productId" class="ml10">
-							<el-select v-model="productId" filterable placeholder="请选择所属模块">
-								<el-option v-for="item in productData" :key="item.id" :label="item.name" :value="item.id.toString()" value-key="id">
-								</el-option>
-							</el-select>
-						</el-form-item>
-					</div>
-					<div >
-						<el-row>
+			<el-tab-pane label="版本分布" name="tab1">
+				<div class="flex">
+					<el-form-item label="所属产品" prop="productKey">
+						<el-select v-model="productKey" filterable placeholder="请选择产品">
+							<el-option v-for="item in productData" :key="item.id" :label="item.name" :value="item.key" value-key="id">
+							</el-option>
+						</el-select>
+					</el-form-item>
+					<el-form-item label="所属模块" prop="productKey" class="ml10">
+						<el-select v-model="productKey" filterable placeholder="请选择所属模块">
+							<el-option v-for="item in productData" :key="item.id" :label="item.name" :value="item.key" value-key="id">
+							</el-option>
+						</el-select>
+					</el-form-item>
+				</div>
+				<div>
+					<el-row>
 						<el-col :span="12">
 							<div class="data-box">
 								<div class="title">版本分布</div>
 								<div style="height: 100%" ref="pieRef"></div>
-
 							</div>
 						</el-col>
 						<el-col :span="12">
 							<div class="data-box">
 								<div class="title">版本占比</div>
-
 							</div>
-
 						</el-col>
 					</el-row>
-
-					</div>
-				</el-tab-pane>
-				<el-tab-pane label="成功率分布" name="tab2">
-					<div class="flex">
-						<el-form-item label="所属产品" prop="productId">
-							<el-select v-model="productId" filterable placeholder="请选择产品">
-								<el-option v-for="item in productData" :key="item.id" :label="item.name" :value="item.id.toString()" value-key="id">
-								</el-option>
-							</el-select>
-						</el-form-item>
-						<el-form-item label="所属模块" prop="productId" class="ml10">
-							<el-select v-model="productId" filterable placeholder="请选择所属模块">
-								<el-option v-for="item in productData" :key="item.id" :label="item.name" :value="item.id.toString()" value-key="id">
-								</el-option>
-							</el-select>
-						</el-form-item>
-					</div>
-					<div >
-						<el-row>
+				</div>
+			</el-tab-pane>
+			<el-tab-pane label="成功率分布" name="tab2">
+				<div class="flex">
+					<el-form-item label="所属产品" prop="productKey">
+						<el-select v-model="productKey" filterable placeholder="请选择产品">
+							<el-option v-for="item in productData" :key="item.id" :label="item.name" :value="item.key" value-key="id">
+							</el-option>
+						</el-select>
+					</el-form-item>
+					<el-form-item label="所属模块" prop="productKey" class="ml10">
+						<el-select v-model="productKey" filterable placeholder="请选择所属模块">
+							<el-option v-for="item in productData" :key="item.id" :label="item.name" :value="item.key" value-key="id">
+							</el-option>
+						</el-select>
+					</el-form-item>
+				</div>
+				<div>
+					<el-row>
 						<el-col :span="12">
 							<div class="data-box">
 								<div class="title">升级成功率目标版本1.0</div>
@@ -61,9 +57,7 @@
 						<el-col :span="12">
 							<div class="data-box">
 								<div class="title">源版本总分布(包含成功/失败)</div>
-
 							</div>
-
 						</el-col>
 					</el-row>
 					<el-row>
@@ -75,9 +69,7 @@
 						<el-col :span="12">
 							<div class="data-box">
 								<div class="title">失败源版本分布</div>
-
 							</div>
-
 						</el-col>
 					</el-row>
 					<el-row>
@@ -86,40 +78,28 @@
 								<div class="title">失败原因分布</div>
 							</div>
 						</el-col>
-						
 					</el-row>
-					</div>
-				</el-tab-pane>
-			
-			</el-tabs>
-
-	
-
+				</div>
+			</el-tab-pane>
+		</el-tabs>
 	</el-card>
 </template>
   
 <script lang="ts" setup>
-import * as echarts from 'echarts';
-
-import api from '/@/api/ota';
-import { ElMessageBox, ElMessage, FormInstance } from 'element-plus';
 import { ref } from 'vue';
-import { useRouter } from 'vue-router';
-
-const router = useRouter();
-const activeTab=ref('tab1');
-const homePieRef = ref();
-
-
 
+const activeTab = ref('tab1')
+const productKey = ref('')
+const productData = ref<any[]>([])
 </script>
 <style scoped lang="scss">
-.data-box{
-    padding: 10px;
-    border: 1px solid #eee;
+.data-box {
+	padding: 10px;
+	border: 1px solid #eee;
 	margin: 10px;
 	min-height: 300px;
-	.title{
+
+	.title {
 		margin-left: 10px;
 	}
 

+ 8 - 8
src/views/iot/ota-update/module/component/edit.vue

@@ -2,9 +2,9 @@
 	<div class="ota-edit-module-container">
 		<el-dialog :title="(ruleForm.id!==0?'修改':'添加')+'模块'" v-model="isShowDialog" width="769px">
 			<el-form :model="ruleForm" ref="formRef" :rules="rules" label-width="90px">
-				<el-form-item label="所属产品" prop="productId">
-					<el-select v-model="ruleForm.productId" filterable placeholder="请选择产品">
-						<el-option v-for="item in productData" :key="item.name" :label="item.name" :value="item.id.toString()" />
+				<el-form-item label="所属产品" prop="productKey">
+					<el-select v-model="ruleForm.productKey" filterable placeholder="请选择产品">
+						<el-option v-for="item in productData" :key="item.key" :label="item.name" :value="item.key" />
 					</el-select>
 				</el-form-item>
 				<el-form-item label="模块名称" prop="name">
@@ -35,13 +35,13 @@ interface RuleFormState {
   id: number;
   name: string;
   nameAs: string;
-  productId: '';
+  productKey: '';
   describe: string;
 }
 interface ModuleState {
   isShowDialog: boolean;
   ruleForm: RuleFormState;
-  productData: [],
+  productData: any[],
   rules: {};
 }
 
@@ -55,12 +55,12 @@ export default defineComponent({
         id: 0,
         name: '',
         nameAs: '',
-        productId: '',
+        productKey: '',
 		    describe: '',
       },
 	    productData: [],
       rules: {
-        productId: [{ required: true, message: '产品不能为空', trigger: 'blur' }],
+        productKey: [{ required: true, message: '产品不能为空', trigger: 'blur' }],
         name: [{ required: true, message: '模块名称不能为空', trigger: 'blur' }],
         nameAs: [{ required: true, message: '模块别名不能为空', trigger: 'blur' }],
       },
@@ -89,7 +89,7 @@ export default defineComponent({
         id: 0,
         name: '',
         nameAs: '',
-        productId: '',
+        productKey: '',
         describe: '',
       };
     };

+ 8 - 7
src/views/iot/ota-update/module/index.vue

@@ -5,9 +5,9 @@
         <el-form-item label="模块名称" prop="name">
           <el-input v-model="tableData.param.name" placeholder="请输入模块名称" clearable style="width: 200px;" />
         </el-form-item>
-        <el-form-item label="所属产品" prop="productId">
-          <el-select v-model="tableData.param.productId" clearable filterable placeholder="请选择产品">
-            <el-option v-for="item in productData" :key="item.id" :label="item.name" :value="item.id.toString()" value-key="id"> </el-option>
+        <el-form-item label="所属产品" prop="productKey">
+          <el-select v-model="tableData.param.productKey" clearable filterable placeholder="请选择产品">
+            <el-option v-for="item in productData" :key="item.key" :label="item.name" :value="item.key" value-key="id"> </el-option>
           </el-select>
         </el-form-item>
         <el-form-item>
@@ -38,7 +38,7 @@
         <el-table-column label="模块别名" v-col="'nameAs'" prop="nameAs" show-overflow-tooltip />
         <el-table-column label="所属产品" v-col="'ProductName'" align="center" show-overflow-tooltip>
           <template #default="scope">
-            <router-link :to="'/iotmanager/device/product/detail/' + scope.row.productId" class="link-type">
+            <router-link :to="'/iotmanager/device/product/detail/' + scope.row.productKey" class="link-type">
               <span>{{ scope.row.ProductName }}</span>
             </router-link>
           </template>
@@ -74,6 +74,7 @@ interface TableDataRow {
 }
 interface TableDataState {
   ids: number[];
+  productData: any[];
   tableData: {
     data: Array<TableDataRow>;
     total: number;
@@ -82,7 +83,7 @@ interface TableDataState {
       pageNum: number;
       pageSize: number;
       keyWord: string;
-      productId: string;
+      productKey: string;
       dateRange: string[];
     };
   };
@@ -108,7 +109,7 @@ export default defineComponent({
           pageNum: 1,
           pageSize: 10,
           keyWord: '',
-          productId: '',
+          productKey: '',
         },
       },
       productData: [],
@@ -121,7 +122,7 @@ export default defineComponent({
     const initTableData = () => {
       moduleList();
     };
-    const getList = (pageNum: number) => {
+    const getList = (pageNum?: number) => {
       typeof pageNum === 'number' && (state.tableData.param.pageNum = pageNum)
       state.tableData.loading = true;
       api.module

+ 20 - 113
src/views/iot/ota-update/update/component/check.vue

@@ -1,12 +1,4 @@
 <template>
-  <!-- <el-dialog
-    class="api-edit"
-    v-model="showDialog"
-    :title="`${formData.id ? '编辑批次' : '新增批次'}`"
-    width="768px"
-    :close-on-click-modal="false"
-    :close-on-press-escape="false">
-    <el-form ref="formRef" :model="formData" :rules="ruleForm" label-width="160px"> -->
   <div class="ota-edit-module-container">
     <el-dialog :title="'操作升级包'" v-model="isShowDialog" width="769px">
       <el-form :model="ruleForm" ref="formRef" :rules="rules" label-width="160px">
@@ -21,10 +13,6 @@
           <el-input v-model="ruleForm.name" placeholder="请输入批次名称" />
         </el-form-item>
 
-        <!--        <el-form-item label="待升级版本号" prop="waitVersion">-->
-        <!--          <el-input v-model="ruleForm.waitVersion" placeholder="请输入待升级版本号" />-->
-        <!--        </el-form-item>-->
-
         <el-form-item label="协议方式" prop="method">
           <el-radio-group v-model="ruleForm.method" @change="getMethod">
             <el-radio label="1">http</el-radio>
@@ -34,9 +22,6 @@
         </el-form-item>
 
         <el-form-item label="所属设备" prop="devices" v-if="deviceShow">
-<!--          <el-select v-model="ruleForm.devices" filterable multiple placeholder="请选择设备" class="width100">-->
-<!--            <el-option v-for="item in productData" :key="item.id" :label="item.name" :value="item.id.toString()" />-->
-<!--          </el-select>-->
 
           <!-- 回显已选设备 -->
           <template v-if="deviceNameShow">
@@ -61,10 +46,10 @@
         </el-form-item>
       </el-form>
       <template #footer>
-				<span class="dialog-footer">
-				<el-button @click="onCancel">取 消</el-button>
-				<el-button type="primary" @click="onSubmit">{{ruleForm.id!==0?'修 改':'添 加'}}</el-button>
-				</span>
+        <span class="dialog-footer">
+          <el-button @click="onCancel">取 消</el-button>
+          <el-button type="primary" @click="onSubmit">{{ ruleForm.id !== 0 ? '修 改' : '添 加' }}</el-button>
+        </span>
       </template>
     </el-dialog>
 
@@ -74,11 +59,10 @@
 </template>
 
 <script lang="ts">
-import { reactive, toRefs, defineComponent, onMounted, ref, unref} from 'vue';
+import { reactive, toRefs, defineComponent, onMounted, ref, unref } from 'vue';
 import { ElMessage } from 'element-plus';
 import api from '/@/api/ota';
 import rule from "/@/api/rule";
-import Device from "/@/views/iot/device/instance/index.vue";
 import DeviceBind from "/@/views/iot/ota-update/update/component/deviceBind.vue";
 
 interface RuleFormState {
@@ -86,13 +70,13 @@ interface RuleFormState {
   name: string;
   waitVersion: string;
   method: string;
-  devices: [];
+  devices: string[];
   stratege: string;
   devOtaFirmwareId: number;
   push: string;
   pushDisabled: boolean,
   types: string;
-  productId: string;
+  productKey: string;
 }
 interface UpdateState {
   isShowDialog: boolean;
@@ -106,7 +90,7 @@ interface UpdateState {
 
 export default defineComponent({
   name: 'otaEditUpdateData',
-  components: {DeviceBind},
+  components: { DeviceBind },
   computed: {
     rule() {
       return rule
@@ -128,7 +112,7 @@ export default defineComponent({
         push: '2',
         pushDisabled: true,
         types: "1",
-        productId: '',
+        productKey: '',
       },
       productData: [],
       rules: {
@@ -137,7 +121,7 @@ export default defineComponent({
         stratege: [{ required: true, message: '升级方式不能为空', trigger: 'blur' }],
         push: [{ required: true, message: '推送方式不能为空', trigger: 'blur' }],
         types: [{ required: true, message: '类型不能为空', trigger: 'blur' }],
-        devices: [{ required: true, message: '所属设备不能为空', trigger: 'blue'}],
+        devices: [{ required: true, message: '所属设备不能为空', trigger: 'blue' }],
       },
       deviceShow: false, // 所属设备是否显示
       deviceNameShow: false, // 回显设备名称状态
@@ -145,7 +129,6 @@ export default defineComponent({
     });
     // 页面加载时
     onMounted(() => {
-      // getProductList();
       getFormType();
     });
     // 获取操作升级包类型
@@ -153,8 +136,7 @@ export default defineComponent({
       // 如果是验证类型,设备信息必填项
       if (state.ruleForm.types === "1") {
         state.deviceShow = true;
-      } else { // 如果是升级类型,设备可选可不选
-        delete (state.rules.devices);
+      } else {
         state.deviceShow = false;
       }
     };
@@ -162,23 +144,18 @@ export default defineComponent({
     const getMethod = () => {
       // 如果是http、https协议则主动推送为否
       // if (state.ruleForm.method === '1') {
-        state.ruleForm.push = '2';
-        state.ruleForm.pushDisabled = true;
+      state.ruleForm.push = '2';
+      state.ruleForm.pushDisabled = true;
       // }
       // if (state.ruleForm.method === '2') {
       //   state.ruleForm.push = '2';
       //   state.ruleForm.pushDisabled = true;
       // }
-      if (state.ruleForm.method === '3'){
+      if (state.ruleForm.method === '3') {
         state.ruleForm.pushDisabled = false;
         state.ruleForm.push = '1';
       }
     };
-    const getProductList = () => {
-      api.batch.getDeviceList({ productId: state.ruleForm.productId}).then((res: any) => {
-        state.productData = res.device
-      })
-    }
     // 打开弹窗
     const openDialog = (row: RuleFormState | null) => {
       resetForm();
@@ -186,7 +163,7 @@ export default defineComponent({
       state.deviceNameShow = false;
       if (row) {
         state.ruleForm.devOtaFirmwareId = row.id;
-        state.ruleForm.productId = row.productId;
+        state.ruleForm.productKey = row.productKey;
       }
       state.isShowDialog = true;
 
@@ -206,7 +183,7 @@ export default defineComponent({
         push: '2',
         pushDisabled: true,
         types: "1",
-        productId: '',
+        productKey: '',
       };
     };
     // 关闭弹窗
@@ -225,6 +202,7 @@ export default defineComponent({
       if (!formWrap) return;
       formWrap.validate((valid: boolean) => {
         if (valid) {
+          // 如果是升级类型,设备可选可不选
           if (state.ruleForm.id !== 0) {
             //修改
             api.batch.edit(state.ruleForm).then(() => {
@@ -244,14 +222,14 @@ export default defineComponent({
       });
     };
     // 获取设备列表
-    const getDeviceTableData = (deviceIdList: any, deviceNameList: any) => {
-      state.ruleForm.devices = deviceIdList;
+    const getDeviceTableData = (deviceKeyList: any, deviceNameList: any) => {
+      state.ruleForm.devices = deviceKeyList;
       state.deviceNameList = deviceNameList;
       state.deviceNameShow = true;
     };
     // 打开设备列表
     const onOpenDevice = () => {
-      deviceRef.value.openDialog(state.ruleForm.devices, state.ruleForm.productId);
+      deviceRef.value.openDialog(state.ruleForm.devices, state.ruleForm.productKey);
     };
     return {
       deviceRef,
@@ -269,77 +247,6 @@ export default defineComponent({
   },
 });
 
-
-// import { ref, reactive, nextTick } from 'vue'
-// import api from '/@/api/ota'
-// import { ruleRequired } from '/@/utils/validator'
-// import { ElMessage } from 'element-plus'
-
-
-// const emit = defineEmits(['getList'])
-
-// const showDialog = ref(false)
-// const formRef = ref()
-
-// const productData = ref([
-// 	{
-// 		id: '',
-// 		name: '',
-// 	},
-// ])
-// const baseForm = {
-// 	id: undefined,
-// 	method: '1',
-// 	push: '1',
-// 	name: '',
-// 	devices: '',
-// 	stratege: '1',
-// 	waitVersion: '',
-// 	devOtaFirmwareId: '',
-// 	productId:'',
-// }
-
-// const formData = reactive({
-// 	...baseForm,
-// })
-
-// const ruleForm = {
-// 	method: [ruleRequired('请选择批次类型')],
-// 	name: [ruleRequired('批次名称不能为空')],
-// 	productId: [ruleRequired('请选择所属产品')],
-// 	devices: [ruleRequired('请选择批次模块')],
-// 	stratege: [ruleRequired('批次版本号不能为空')],
-// 	waitVersion: [ruleRequired('升级后版本号不能为空')],
-// }
-
-
-// const onSubmit = async () => {
-// 	await formRef.value.validate()
-
-// 	const theApi = formData.id ? api.batch.edit : api.batch.add
-// 	await theApi(formData)
-// 	ElMessage.success('操作成功')
-// 	resetForm()
-// 	showDialog.value = false
-// 	emit('getList')
-// }
-
-// const resetForm = async () => {
-// 	Object.assign(formData, { ...baseForm })
-// 	formRef.value && formRef.value.resetFields()
-// }
-
-// const open = async (row: any) => {
-// 	resetForm()
-// 	showDialog.value = true
-// 	nextTick(() => {
-// 		Object.assign(formData, { ...row })
-// 		getProductList()
-
-// 	})
-// }
-
-// defineExpose({ open })
 </script>
 
 <style lang="scss" scoped>

+ 23 - 29
src/views/iot/ota-update/update/component/deviceBind.vue

@@ -11,7 +11,11 @@
       </el-form>
       <el-table ref="multipleTable" :data="tableData.data" style="width: 100%" @selection-change="handleSelectionChange" v-loading="tableData.loading">
         <el-table-column type="selection" width="55" align="center" />
-        <el-table-column label="标识" prop="key" width="130" show-overflow-tooltip v-col="'key'" />
+        <el-table-column label="标识" prop="key" width="130" show-overflow-tooltip v-col="'key'">
+          <template #default="{ row }">
+            <copy :text="row.key"></copy>
+          </template>
+        </el-table-column>
         <el-table-column label="设备名称" prop="name" show-overflow-tooltip v-col="'name'" />
         <el-table-column label="产品名称" prop="productName" show-overflow-tooltip v-col="'productName'" />
 
@@ -34,20 +38,14 @@
 <script lang="ts">
 import { toRefs, reactive, defineComponent, nextTick, getCurrentInstance } from 'vue'
 import { ElMessageBox, ElMessage } from 'element-plus'
-
-import 'vue3-json-viewer/dist/index.css'
-
-import { useRoute } from 'vue-router'
-
 import api from '/@/api/device'
 
 interface TableDataState {
   isShowDialog: boolean,
   productData: object[],
   deviceKeyList: string[];
-  deviceIdList: string[];
   deviceNameList: string[];
-  checkIdList: string[];
+  checkKeyList: string[];
   tableData: {
     data: []
     total: number
@@ -56,11 +54,11 @@ interface TableDataState {
       pageNum: number
       pageSize: number
       name: string
-      productId: number
+      productKey: string
     }
   },
   ruleForm: {
-    productId: string | number
+    productKey: string
   },
   rules: {}
 }
@@ -69,14 +67,12 @@ export default defineComponent({
 
   setup(prop, { emit }) {
     const { proxy } = getCurrentInstance() as any;
-    const route = useRoute()
     const state = reactive<TableDataState>({
       deviceKeyList: [],
-      deviceIdList: [],
       deviceNameList: [],
       isShowDialog: false,
       productData: [],
-      checkIdList: [],
+      checkKeyList: [],
       tableData: {
         data: [],
         total: 0,
@@ -85,19 +81,19 @@ export default defineComponent({
           pageNum: 1,
           pageSize: 10,
           name: '',
-          productId: 0,
+          productKey: '',
         },
       },
       ruleForm: {
-        productId: ''
+        productKey: ''
       },
       rules: {
-        productId: [{ required: true, message: '所属产品不能为空', trigger: 'blur' }],
+        productKey: [{ required: true, message: '所属产品不能为空', trigger: 'blur' }],
       }
     })
 
     const getDeviceList = () => {
-      // if (!state.ruleForm.productId) {
+      // if (!state.ruleForm.productKey) {
       //   state.tableData.data = [];
       //   state.tableData.total = 0;
       //   return;
@@ -114,23 +110,21 @@ export default defineComponent({
 
     const getProductList = () => {
       api.product.getSubList().then((res: any) => {
-        let productDataList = res.product
-        state.productData = productDataList;
-        state.ruleForm.productId = state.productData[0].id
+        state.productData = res.product;
+        state.ruleForm.productKey = res.product[0].key
         getDeviceList()
       });
     };
 
-    const openDialog = (checkIdData: any, productId: any) => {
-      state.checkIdList = checkIdData;
-      state.tableData.param.productId = productId;
+    const openDialog = (checkKeyList: string[], productKey: any) => {
+      state.checkKeyList = checkKeyList;
+      state.tableData.param.productKey = productKey;
       getDeviceList()
     };
 
     // 多选框选中数据
     const handleSelectionChange = (selection: any[]) => {
       state.deviceKeyList = selection.map((item) => item.key);
-      state.deviceIdList = selection.map((item) => item.id);
       state.deviceNameList = selection.map((item) => item.name);
     };
 
@@ -145,20 +139,20 @@ export default defineComponent({
         cancelButtonText: '取消',
         type: 'warning',
       }).then(() => {
-        emit('bindSuccess', state.deviceIdList, state.deviceNameList)
+        emit('bindSuccess', state.deviceKeyList, state.deviceNameList)
         state.isShowDialog = false;
       })
     };
 
-    const handleChange = (productId: number) => {
-      state.ruleForm.productId = productId;
+    const handleChange = (productKey: string) => {
+      state.ruleForm.productKey = productKey;
       getDeviceList()
     }
 
     const changeSelect = () => {
       nextTick(() => {
-        state.tableData.data.forEach((item) => {
-          if (state.checkIdList.includes(item.id)) {
+        state.tableData.data.forEach((item: any) => {
+          if (state.checkKeyList.includes(item.key)) {
             proxy.$refs.multipleTable.toggleRowSelection(item, true);
           }
         })

+ 16 - 20
src/views/iot/ota-update/update/component/edit.vue

@@ -13,11 +13,7 @@
           <el-input v-model.trim="ruleForm.name" placeholder="请输入升级包名称" />
         </el-form-item>
 
-        <el-form-item label="所属产品" prop="productId">
-          <!--          <el-select v-model="ruleForm.productId" placeholder="请选择产品" @change="selectChange">-->
-          <!--            <el-option v-for="item in productData" :key="item.id" :label="item.name" :value="item.id.toString()" />-->
-          <!--          </el-select>-->
-
+        <el-form-item label="所属产品" prop="productKey">
           <!-- 回显已选产品 -->
           <template v-if="productNameShow">
             <el-tag style="margin-right: 10px;">{{ productName }}</el-tag>
@@ -107,7 +103,7 @@ interface RuleFormState {
   id: number;
   types: string;
   name: string;
-  productId: '';
+  productKey: string;
   module: string;
   version: string;
   waitVersion: string;
@@ -162,7 +158,7 @@ export default defineComponent({
         id: 0,
         types: '1',
         name: '',
-        productId: '',
+        productKey: '',
         module: '',
         version: '',
         waitVersion: '',
@@ -181,7 +177,7 @@ export default defineComponent({
       rules: {
         types: [{ required: true, message: '升级包类型不能为空', trigger: 'change' }],
         name: [{ required: true, message: '升级包名称不能为空', trigger: 'change' }],
-        productId: [{ required: true, message: '所属产品不能为空', trigger: 'change' }],
+        productKey: [{ required: true, message: '所属产品不能为空', trigger: 'change' }],
         module: [{ required: true, message: '升级包模块不能为空', trigger: 'change' }],
         version: [
           { required: true, message: '升级包版本号不能为空', trigger: 'change' },
@@ -205,10 +201,10 @@ export default defineComponent({
           const data: RuleFormState = res;
           state.ruleForm = data;
         });
-        selectChange(row.productId);
+        selectChange(row.productKey);
         state.ruleForm = row;
         // 获取产品名称
-        apiProduct.product.detail(state.ruleForm.productId).then((res: any) => {
+        apiProduct.product.detail(state.ruleForm.productKey).then((res: any) => {
           if (res.data) {
             state.productNameShow = true;
             state.productName = res.data.name;
@@ -225,7 +221,7 @@ export default defineComponent({
       state.productNameShow = false;
 
       // 获取上传格式
-      apiSystem.getInfoByKey({ ConfigKey: 'sys.uploadFile.fileType' }).then((res: any) => {
+      apiSystem.getInfoByKey('sys.uploadFile.fileType').then((res: any) => {
         if (res.data) {
           let fileType = res.data.configValue.split(",");
           for (let i = 0; i < fileType.length; i++) {
@@ -240,7 +236,7 @@ export default defineComponent({
         id: 0,
         types: '1',
         name: '',
-        productId: '',
+        productKey: '',
         module: '',
         version: '',
         waitVersion: '',
@@ -267,15 +263,15 @@ export default defineComponent({
         ElMessage.error(res.message);
       }
     };
-    const selectChange = (val: Number) => {
+    const selectChange = (val: string) => {
       getModuleList(val);
     };
-    const getModuleList = (productID: Number) => {
+    const getModuleList = (productKey?: string) => {
       state.ruleForm.module = '';
-      if (!productID) {
-        productID = Number(state.ruleForm.productId)
+      if (!productKey) {
+        productKey = state.ruleForm.productKey
       }
-      api.module.getList({ productID: productID }).then((res: any) => {
+      api.module.getList({ productKey }).then((res: any) => {
         state.moduleData = res.Data;
       });
     };
@@ -325,9 +321,9 @@ export default defineComponent({
       productRef.value.openDialog();
     }
     // 获取产品回显数据
-    const getProductTableData = (deviceIdList: any, deviceNameList: any) => {
-      state.ruleForm.productId = deviceIdList[0];
-      selectChange(deviceIdList[0]);
+    const getProductTableData = (productKeyList: any, deviceNameList: any) => {
+      state.ruleForm.productKey = productKeyList[0];
+      selectChange(productKeyList[0]);
       state.productName = deviceNameList[0];
       state.productNameShow = true;
     }

+ 22 - 40
src/views/iot/ota-update/update/component/productBind.vue

@@ -1,54 +1,43 @@
 <template>
   <div class="mutiple-bind-dialog-wrap">
-    <el-dialog title="选择产品" v-model="isShowDialog" width="90%">
-      <el-form ref="formRef" size="small" label-width="110px">
-        <el-form-item label="设备名称" prop="name">
-          <el-input v-model="tableData.param.name" placeholder="请输入产品名称" clearable style="width: 240px" @keyup.enter.native="getProductList" />
-          <el-button style="margin-left: 20px;" type="primary" @click="getProductList()">查询</el-button>
-
-          <el-button style="margin-left: 20px;" :disabled="!deviceKeyList.length" type="danger" @click="confirmBind()">确定选择</el-button>
+    <el-dialog title="选择产品" v-model="isShowDialog" width="700px">
+      <el-form ref="formRef">
+        <el-form-item label="" prop="name">
+          <el-input v-model="tableData.param.name" placeholder="请输入产品标识或名称" clearable style="width: 240px" @keyup.enter.native="getProductList" />
+          <el-button style="margin-left: 20px;" type="primary" @click="getProductList()"><el-icon><ele-Search /></el-icon>查询</el-button>
+          <el-button style="margin-left: 20px;" :disabled="!deviceKeyList.length" type="danger" @click="confirmBind()"><el-icon><ele-Finished /></el-icon>确定选择</el-button>
         </el-form-item>
       </el-form>
       <el-table ref="productTable" :data="tableData.data" style="width: 100%" @selection-change="handleSelectionChange" @select-all="selectAll" v-loading="tableData.loading">
         <el-table-column type="selection" width="55" align="center" />
-        <el-table-column label="标识" prop="key" show-overflow-tooltip v-col="'key'" />
-        <el-table-column label="名称" prop="name" show-overflow-tooltip v-col="'name'" />
-        <el-table-column label="分类" prop="categoryName" show-overflow-tooltip v-col="'categoryName'" />
-        <el-table-column label="消息协议" prop="messageProtocol" show-overflow-tooltip v-col="'messageProtocol'" />
-        <el-table-column label="接入方式" prop="transportProtocol" show-overflow-tooltip v-col="'transportProtocol'" />
-        <el-table-column label="类型" prop="deviceType" show-overflow-tooltip v-col="'deviceType'" />
-
-        <el-table-column prop="status" label="状态" width="100" align="center" v-col="'status'">
-          <template #default="scope">
-            <el-tag type="success" size="small" v-if="scope.row.status">已发布</el-tag>
-            <el-tag type="info" size="small" v-else>未发布</el-tag>
+        <el-table-column label="标识" prop="key" show-overflow-tooltip v-col="'key'">
+          <template #default="{ row }">
+            <copy :text="row.key"></copy>
           </template>
         </el-table-column>
-
+        <el-table-column label="名称" prop="name" show-overflow-tooltip v-col="'name'" />
       </el-table>
       <pagination v-show="tableData.total > 0" :total="tableData.total" v-model:page="tableData.param.pageNum" v-model:limit="tableData.param.pageSize" @pagination="getProductList" />
-
     </el-dialog>
   </div>
 </template>
 <script lang="ts">
 import { toRefs, reactive, defineComponent, nextTick, getCurrentInstance, ref } from 'vue'
 import { ElMessageBox, ElMessage } from 'element-plus'
-import 'vue3-json-viewer/dist/index.css'
 import api from '/@/api/device'
 
 interface TableDataState {
   isShowDialog: boolean,
   productData: object[],
   deviceKeyList: string[];
-  deviceIdList: string[];
   deviceNameList: string[];
-  checkIdList: string[];
+  checkKeyList: string[];
   tableData: {
     data: []
     total: number
     loading: boolean
     param: {
+      status: number
       pageNum: number
       pageSize: number
       name: string
@@ -63,16 +52,16 @@ export default defineComponent({
     const productTable = ref();
     const state = reactive<TableDataState>({
       deviceKeyList: [],
-      deviceIdList: [],
       deviceNameList: [],
       isShowDialog: false,
       productData: [],
-      checkIdList: [],
+      checkKeyList: [],
       tableData: {
         data: [],
         total: 0,
         loading: false,
         param: {
+          status: 1,
           pageNum: 1,
           pageSize: 10,
           name: '',
@@ -91,15 +80,14 @@ export default defineComponent({
       }).finally(() => (state.tableData.loading = false));
     };
 
-    const openDialog = (checkIdData: any) => {
-      state.checkIdList = checkIdData;
+    const openDialog = (checkKeyList: string[]) => {
+      state.checkKeyList = checkKeyList;
       getProductList()
     };
 
     // 多选框选中数据
     const handleSelectionChange = (selection: any[]) => {
       state.deviceKeyList = selection.map((item) => item.key);
-      state.deviceIdList = selection.map((item) => item.id);
       state.deviceNameList = selection.map((item) => item.name);
 
       if (selection.length > 1) {
@@ -109,19 +97,13 @@ export default defineComponent({
     };
 
     const confirmBind = () => {
-      let msg = '是否确定选择产品?';
       if (state.deviceKeyList.length === 0) {
         ElMessage.error('请选择要确定绑定的数据。');
         return;
       }
-      ElMessageBox.confirm(msg, '提示', {
-        confirmButtonText: '确认',
-        cancelButtonText: '取消',
-        type: 'warning',
-      }).then(() => {
-        emit('bindSuccess', state.deviceIdList, state.deviceNameList)
-        state.isShowDialog = false;
-      })
+
+      emit('bindSuccess', state.deviceKeyList, state.deviceNameList)
+      state.isShowDialog = false;
     };
 
     const handleChange = () => {
@@ -130,9 +112,9 @@ export default defineComponent({
 
     const changeSelect = () => {
       nextTick(() => {
-        state.tableData.data.forEach((item) => {
-          if (state.checkIdList) {
-            if (state.checkIdList.includes(item.id)) {
+        state.tableData.data.forEach((item: any) => {
+          if (state.checkKeyList) {
+            if (state.checkKeyList.includes(item.key)) {
               proxy.$refs.multipleTable.toggleRowSelection(item, true);
             }
           }

+ 0 - 1
src/views/iot/ota-update/update/detail.vue

@@ -50,7 +50,6 @@ export default defineComponent({
         are: '',
         moduleName: '',
         checkres: 0,
-        productId: 0,
       },
     });
     const getDetail = () => {

+ 1 - 1
src/views/iot/ota-update/update/index.vue

@@ -37,7 +37,7 @@
         </el-table-column>
         <el-table-column label="所属产品" v-col="'productName'" align="center" show-overflow-tooltip>
           <template #default="scope">
-            <router-link :to="'/iotmanager/device/product/detail/' + scope.row.productId" class="link-type">
+            <router-link :to="'/iotmanager/device/product/detail/' + scope.row.productKey" class="link-type">
               <span>{{ scope.row.productName }}</span>
             </router-link>
           </template>

+ 1 - 1
src/views/iot/property/dossier/edit.vue

@@ -192,7 +192,7 @@ const open = async (row: any, productInfo: any) => {
         }
       }
       //根据产品ID获取设备列表
-      api.device.allList({ productId: productInfo.id }).then((resd: any) => {
+      api.device.allList({ productKey: productInfo.key }).then((resd: any) => {
         deviceList.value = resd.device || [];
       });
     })

+ 1 - 3
src/views/iot/scene/list/index.vue

@@ -51,15 +51,13 @@
 <script lang="ts" setup>
 import api from '/@/api/scene';
 import { useSearch } from '/@/hooks/useCommon';
-import { ElMessageBox, ElMessage, FormInstance } from 'element-plus';
+import { ElMessageBox, ElMessage } from 'element-plus';
 import { ref } from 'vue';
 const queryRef = ref();
 const { params, tableData, getList, loading } = useSearch<any[]>(api.log.getList, 'data', { keyWord: '' });
 getList();
 
-
 const view = (row: any) => {
-
 };
 
 const del = (row: any) => {

+ 7 - 7
src/views/iot/scene/manage/component/actionType/deviceOut.vue

@@ -142,18 +142,18 @@ const selectAction=(val:string)=>{
 const getAction = (val: string) => {
   switch (val) {
     case 'functionCall':
-      product.tabDeviceFucntion.getList({ key: productKey.value }).then((res: any) => {
+      product.tabDeviceFucntion.getList({ productKey: productKey.value }).then((res: any) => {
         functionCallList.value = res
       })
       break;
     case 'getProperties':
-      datahub.node.getpropertyList({ key: productKey.value }).then((re: any) => {
+      datahub.node.getpropertyList({ productKey: productKey.value }).then((re: any) => {
         propertyCallList.value = re;
       });
 
       break;
     case 'setProperties':
-      datahub.node.getpropertyList({ key: productKey.value }).then((re: any) => {
+      datahub.node.getpropertyList({ productKey: productKey.value }).then((re: any) => {
         propertyCallList.value = re;
       });
       break;
@@ -185,8 +185,8 @@ const saveData = () => {
   emit('SetSaveData', newdata);
 }
 
-const getDeviceList = (_id: any) => {
-  product.device.allList({ productId: _id }).then((res: any) => {
+const getDeviceList = (productKey: any) => {
+  product.device.allList({ productKey }).then((res: any) => {
     deviceListData.value = res.device
   })
 }
@@ -197,7 +197,7 @@ const seletChange = (val: string) => {
   if (info) {
     // 重置 deviceKey 的值
     fromData.value.deviceKey = '';
-    getDeviceList(info.id)
+    getDeviceList(info.key)
   }
   saveData();
 }
@@ -208,7 +208,7 @@ onMounted(() => {
     productKey.value = infoc.productKey;
     let info = props.sourceData?.find((pro: testIValueType) => pro.key === infoc.productKey);
     if (info) {
-       getDeviceList(info.id)
+       getDeviceList(info.key)
     }
   }
 

+ 8 - 8
src/views/iot/scene/manage/component/sceneItem.vue

@@ -159,13 +159,13 @@ const seletChange = (index: number, val: string) => {
       'operator': '',
       'value': ''
     }]];
-    getDeviceList(info.id)
+    getDeviceList(info.key)
   }
   EditPen(index);
 }
-const getDeviceList = (_id: any) => {
-  product.device.allList({ productId: _id }).then((res: any) => {
-    deviceListData.value = res.device
+const getDeviceList = (productKey: any) => {
+  product.device.allList({ productKey }).then((res: any) => {
+    deviceListData.value = res.device || []
   })
 }
 const getSelectcolumns=(index: number, val: string) => {
@@ -183,18 +183,18 @@ const getSelectcolumns=(index: number, val: string) => {
 const getAction = (val: string) => {
   switch (val) {
     case 'functionCall':
-      product.tabDeviceFucntion.getList({ key: product_key }).then((res: any) => {
+      product.tabDeviceFucntion.getList({ product_key }).then((res: any) => {
         functionCallList.value = res
       })
       break;
     case 'readAttribute':
-      datahub.node.getpropertyList({ key: product_key }).then((re: any) => {
+      datahub.node.getpropertyList({ product_key }).then((re: any) => {
         propertyCallList.value = re;
       });
 
       break;
     case 'modifyAttribute':
-      datahub.node.getpropertyList({ key: product_key }).then((re: any) => {
+      datahub.node.getpropertyList({ product_key }).then((re: any) => {
         propertyCallList.value = re;
       });
       break;
@@ -268,7 +268,7 @@ const intScenel=()=>{
           let info = props.sourceData?.find((pro: { key: any; }) => pro.key === val.productKey);
 
           if (info) {
-            getDeviceList(info.id)
+            getDeviceList(info.key)
           }
       }
       if(val.triggerType){

+ 1 - 1
src/views/login/component/scan.vue

@@ -46,7 +46,7 @@ export default defineComponent({
 	text-align: center;
 	@extend .login-scan-animation;
 	animation-delay: 0.1s;
-	::v-deep(img) {
+	:deep(img) {
 		margin: auto;
 	}
 	.login-msg {

+ 2 - 2
src/views/personal/index.vue

@@ -180,7 +180,7 @@ const dateChange = (e: any) => {
 		align-items: center;
 
 		.personal-user-left {
-			::v-deep(.el-upload) {
+			:deep(.el-upload) {
 				height: 100%;
 				display: flex;
 				flex-direction: column;
@@ -234,7 +234,7 @@ const dateChange = (e: any) => {
 				.personal-item-value-edit {
 					width: 220px;
 
-					::v-deep(.el-input__wrapper) {
+					:deep(.el-input__wrapper) {
 						width: 100%;
 					}
 				}

+ 7 - 7
src/views/system/assess/totalIndex/component/addItem.vue

@@ -39,8 +39,8 @@
 					</template>
 				</el-table-column>
 			</el-table>
-			<el-pagination @size-change="onHandleSizeChange" @current-change="onHandleCurrentChange" class="mt15" :pager-count="5" :page-sizes="[10, 20, 30, 50, 100, 200, 300, 500]" v-model:current-page="tableData.param.pageNum" background v-model:page-size="tableData.param.pageSize"
-				layout="total, sizes, prev, pager, next, jumper" :total="tableData.total">
+			<el-pagination @size-change="onHandleSizeChange" @current-change="onHandleCurrentChange" class="mt15" :pager-count="5" :page-sizes="[10, 20, 30, 50, 100, 200, 300, 500]" v-model:current-page="tableData.param.pageNum" background
+				v-model:page-size="tableData.param.pageSize" layout="total, sizes, prev, pager, next, jumper" :total="tableData.total">
 			</el-pagination>
 
 			<template #footer>
@@ -237,7 +237,7 @@ export default defineComponent({
 </script>
 
 <style lang="scss" scoped>
-::v-deep .el-form {
+:deep(.el-form) {
 
 	// display: flex;
 	// justify-self: center;
@@ -248,17 +248,17 @@ export default defineComponent({
 		margin: 8px auto;
 	}
 
-	::v-deep .el-input__inner,
-	::v-deep .el-textarea__inner {
+	:deep(.el-input__inner),
+	:deep(.el-textarea__inner) {
 		width: 400px;
 		// flex-grow: 0;
 	}
 
-	::v-deep .el-input__inner {
+	:deep(.el-input__inner) {
 		padding: 1px 10px;
 	}
 
-	::v-deep .el-input__wrapper {
+	:deep(.el-input__wrapper) {
 		flex-grow: 0;
 		padding: 0
 	}

+ 3 - 3
src/views/system/assess/totalIndex/component/addSign.vue

@@ -198,7 +198,7 @@ export default defineComponent({
 </script>
 
 <style lang="scss" scoped>
-::v-deep .has-symbol > .el-form-item__content {
+:deep(.has-symbol) > .el-form-item__content {
 	position: relative;
 	.symbol {
 		position: absolute;
@@ -241,14 +241,14 @@ export default defineComponent({
 				}
 
 			}
-			::v-deep .el-input {
+			:deep(.el-input) {
 				width: 100px;
 				height: 28px;
 			}
 		}
 	}
 }
-::v-deep  .el-dialog__body {
+:deep(.el-dialog__body) {
 	border-top: 1px var(--el-border-color) var(--el-border-style);
 }
 </style>

+ 1 - 1
src/views/system/assess/totalIndex/component/detailItem.vue

@@ -146,7 +146,7 @@ export default defineComponent({
 </script>
 
 <style lang="scss" scoped>
-::v-deep .el-dialog__body {
+:deep(.el-dialog__body) {
 	border-top: 1px var(--el-border-color) var(--el-border-style);
 }
 .table-wrap {

+ 5 - 5
src/views/system/assess/totalIndex/component/editItem.vue

@@ -254,7 +254,7 @@ export default defineComponent({
 </script>
 
 <style lang="scss" scoped>
-::v-deep .el-form {
+:deep(.el-form) {
 
 	// display: flex;
 	// justify-self: center;
@@ -265,17 +265,17 @@ export default defineComponent({
 		margin: 8px auto;
 	}
 
-	::v-deep .el-input__inner,
-	::v-deep .el-textarea__inner {
+	:deep(.el-input__inner),
+	:deep(.el-textarea__inner) {
 		width: 400px;
 		// flex-grow: 0;
 	}
 
-	::v-deep .el-input__inner {
+	:deep(.el-input__inner) {
 		padding: 1px 10px;
 	}
 
-	::v-deep .el-input__wrapper {
+	:deep(.el-input__wrapper) {
 		flex-grow: 0;
 		padding: 0
 	}

+ 1 - 1
src/views/system/assess/totalIndex/component/setTask.vue

@@ -306,7 +306,7 @@ export default defineComponent({
 
 <style lang="scss" scoped>
 .inline-row {
-	::v-deep .el-form-item__content {
+	:deep(.el-form-item__content) {
 		display: flex;
 
 		.el-input {

+ 1 - 1
src/views/system/assess/totalIndex/index.vue

@@ -173,7 +173,7 @@ export default defineComponent({
 </script>
 
 <style lang="scss" scoped>
-::v-deep .el-dialog__body {
+:deep(.el-dialog__body) {
   border-top: 1px var(--el-border-color) var(--el-border-style);
 }
 </style>

+ 2 - 2
src/views/system/basicConfig/index.vue

@@ -44,7 +44,7 @@ function menuChange(index: string) {
 		flex: 1;
 	}
 
-	.el-card ::v-deep(.el-card__body) {
+	.el-card :deep(.el-card__body) {
 		flex: 1;
 		height: 100%;
 		overflow-y: auto;
@@ -54,7 +54,7 @@ function menuChange(index: string) {
 	.el-menu {
 		width: 200px;
 
-		::v-deep(.el-menu-item) {
+		:deep(.el-menu-item) {
 			height: 40px !important;
 			line-height: 40px !important;
 		}

+ 1 - 1
src/views/system/manage/blacklist/index.vue

@@ -55,7 +55,7 @@
         <el-table-column v-col="'createdAt'" prop="createdAt" label="创建时间" align="center" width="180"></el-table-column>
         <el-table-column v-col="'handle'" label="操作" width="150" align="center" fixed="right">
           <template #default="scope">
-            <!-- <router-link :to="'/iotmanager/device/product/detail/' + scope.row.id" class="link-type" style="padding-right: 12px;font-size: 12px;color: #409eff;">
+            <!-- <router-link :to="'/iotmanager/device/product/detail/' + scope.row.key" class="link-type" style="padding-right: 12px;font-size: 12px;color: #409eff;">
               <span>详情</span>
             </router-link> -->
             <el-button size="small" text type="warning" @click="onOpenEditDic(scope.row)" v-auth="'edit'">编辑</el-button>

+ 7 - 0
yarn.lock

@@ -2991,6 +2991,13 @@ vue-router@^4.0.13, vue-router@^4.0.14:
   dependencies:
     "@vue/devtools-api" "^6.1.4"
 
+vue3-clipboard@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.npmmirror.com/vue3-clipboard/-/vue3-clipboard-1.0.0.tgz#f7d17a00bce6579ba866df825541563b272610f2"
+  integrity sha512-GUqKh1oO79xDpq0z+cCv/NDVTpcJGNDzeNgT3PmTdTp/WJh3gcTrDqIYKycKhzMFOtIFJ7hO/+usgyWtT+fNhA==
+  dependencies:
+    clipboard "^2.0.6"
+
 vue3-cron@^1.1.8:
   version "1.1.8"
   resolved "https://registry.npmmirror.com/vue3-cron/-/vue3-cron-1.1.8.tgz"