Просмотр исходного кода

Merge branch 'staffNoFix' into 'master'

用户管理fix

See merge request tian-group/skyeye-admin-fe!34
孙宏耀 2 лет назад
Родитель
Сommit
192e1a6d31
34 измененных файлов с 944 добавлено и 2180 удалено
  1. 1 1
      .env.development
  2. 1 1
      package.json
  3. 66 54
      pnpm-lock.yaml
  4. 25 0
      src/api/scene/scene.ts
  5. 23 0
      src/assets/1.svg
  6. 24 0
      src/assets/test/1-cir.svg
  7. 16 0
      src/assets/test/1-curv.svg
  8. 24 0
      src/assets/test/1-curv2.svg
  9. 23 0
      src/assets/test/1.svg
  10. 23 0
      src/assets/test/2-rect.svg
  11. 6 0
      src/assets/test/2-shine.svg
  12. 8 0
      src/assets/test/2-shining.svg
  13. 25 0
      src/assets/test/2.svg
  14. 1 0
      src/components/Table/src/Table.vue
  15. 5 0
      src/components/Table/src/props.ts
  16. 0 18
      src/hooks/useSceneInfos.ts
  17. 2 1
      src/main.ts
  18. 47 34
      src/views/map-config/mini-map/MapBase/KonvaMap.vue
  19. 2 15
      src/views/map-config/mini-map/MiniMapConfig.vue
  20. 53 27
      src/views/page-config/ConfigEdit.vue
  21. 50 15
      src/views/page-config/component/ConfigDrawer.vue
  22. 1 3
      src/views/page-config/component/ConfigFinish.vue
  23. 67 16
      src/views/page-config/component/PageMain.vue
  24. 79 59
      src/views/page-config/component/mapContainer/LabelItem.vue
  25. 119 16
      src/views/page-config/component/mapContainer/MapContainer.vue
  26. 168 0
      src/views/page-config/component/mapContainer/labelConfig.ts
  27. 0 360
      src/views/page-config/hooks/useMapEditor.ts
  28. 0 272
      src/views/page-config/hooks/useMapEditor1.ts
  29. 0 534
      src/views/page-config/shops.json
  30. 52 27
      src/views/page-config/stores/useMapEditor.ts
  31. 0 692
      src/views/page-config/tree.json
  32. 16 10
      src/views/system-config/scene-manage/CompanyDrawer.vue
  33. 6 1
      src/views/system-config/scene-manage/SceneManage.vue
  34. 11 24
      src/views/system-config/scene-manage/actionColomns.vue

+ 1 - 1
.env.development

@@ -1,5 +1,5 @@
 # 只在开发模式中被载入
-VITE_PORT = 8097
+VITE_PORT = 8092
 
 # 网站根目录
 VITE_PUBLIC_PATH = /skyeye-admin/

+ 1 - 1
package.json

@@ -45,7 +45,7 @@
     "element-resize-detector": "1.2.4",
     "fabric": "5.3.0",
     "flv.js": "1.6.2",
-    "html2canvas": "1.4.1",
+    "html2canvas": "1.0.0",
     "konva": "9.3.0",
     "lodash-es": "4.17.21",
     "mockjs": "1.1.0",

+ 66 - 54
pnpm-lock.yaml

@@ -63,8 +63,8 @@ dependencies:
     specifier: 1.6.2
     version: 1.6.2
   html2canvas:
-    specifier: 1.4.1
-    version: 1.4.1
+    specifier: 1.0.0
+    version: 1.0.0
   konva:
     specifier: 9.3.0
     version: 9.3.0
@@ -111,7 +111,7 @@ dependencies:
     specifier: 1.8.6
     version: 1.8.6(vue@3.3.4)
   vue-konva:
-    specifier: ^3.0.2
+    specifier: 3.0.2
     version: 3.0.2(konva@9.3.0)
   vue-router:
     specifier: 4.1.2
@@ -156,7 +156,7 @@ devDependencies:
     version: 5.30.7(eslint@8.20.0)(typescript@4.7.4)
   '@vitejs/plugin-vue':
     specifier: 2.3.3
-    version: 2.3.3(vite@5.0.10)(vue@3.3.4)
+    version: 2.3.3(vite@5.1.3)(vue@3.3.4)
   '@vitejs/plugin-vue-jsx':
     specifier: 1.3.10
     version: 1.3.10
@@ -232,6 +232,9 @@ devDependencies:
   sass:
     specifier: 1.53.0
     version: 1.53.0
+  simple-git:
+    specifier: 3.22.0
+    version: 3.22.0
   stylelint:
     specifier: 14.9.1
     version: 14.9.1
@@ -257,26 +260,26 @@ devDependencies:
     specifier: 4.7.4
     version: 4.7.4
   vite:
-    specifier: 5.0.10
-    version: 5.0.10(@types/node@17.0.45)(sass@1.53.0)
+    specifier: 5.1.3
+    version: 5.1.3(@types/node@17.0.45)(sass@1.53.0)
   vite-plugin-compression:
     specifier: 0.5.1
-    version: 0.5.1(vite@5.0.10)
+    version: 0.5.1(vite@5.1.3)
   vite-plugin-html:
-    specifier: 3.2.0
-    version: 3.2.0(vite@5.0.10)
+    specifier: 3.2.2
+    version: 3.2.2(vite@5.1.3)
   vite-plugin-mock:
     specifier: 2.9.6
-    version: 2.9.6(mockjs@1.1.0)(vite@5.0.10)
+    version: 2.9.6(mockjs@1.1.0)(vite@5.1.3)
   vite-plugin-style-import:
     specifier: 2.0.0
-    version: 2.0.0(vite@5.0.10)
+    version: 2.0.0(vite@5.1.3)
   vite-plugin-svg-icons:
     specifier: 2.0.1
-    version: 2.0.1(vite@5.0.10)
+    version: 2.0.1(vite@5.1.3)
   vite-plugin-vue-setup-extend:
     specifier: 0.4.0
-    version: 0.4.0(vite@5.0.10)
+    version: 0.4.0(vite@5.1.3)
   vue-eslint-parser:
     specifier: 9.0.3
     version: 9.0.3(eslint@8.20.0)
@@ -1133,6 +1136,18 @@ packages:
       '@jridgewell/sourcemap-codec': 1.4.15
     dev: true
 
+  /@kwsites/file-exists@1.1.1:
+    resolution: {integrity: sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==}
+    dependencies:
+      debug: 4.3.4
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /@kwsites/promise-deferred@1.1.1:
+    resolution: {integrity: sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==}
+    dev: true
+
   /@lukeed/csprng@1.1.0:
     resolution: {integrity: sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA==}
     engines: {node: '>=8'}
@@ -1646,14 +1661,14 @@ packages:
       - supports-color
     dev: true
 
-  /@vitejs/plugin-vue@2.3.3(vite@5.0.10)(vue@3.3.4):
+  /@vitejs/plugin-vue@2.3.3(vite@5.1.3)(vue@3.3.4):
     resolution: {integrity: sha512-SmQLDyhz+6lGJhPELsBdzXGc+AcaT8stgkbiTFGpXPe8Tl1tJaBw1A6pxDqDuRsVkD8uscrkx3hA7QDOoKYtyw==}
     engines: {node: '>=12.0.0'}
     peerDependencies:
       vite: ^2.5.10
       vue: ^3.2.25
     dependencies:
-      vite: 5.0.10(@types/node@17.0.45)(sass@1.53.0)
+      vite: 5.1.3(@types/node@17.0.45)(sass@1.53.0)
       vue: 3.3.4
     dev: true
 
@@ -2387,8 +2402,8 @@ packages:
     resolution: {integrity: sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==}
     dev: true
 
-  /base64-arraybuffer@1.0.2:
-    resolution: {integrity: sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==}
+  /base64-arraybuffer@0.2.0:
+    resolution: {integrity: sha512-7emyCsu1/xiBXgQZrscw/8KPRT44I4Yq9Pe6EGs3aPRTsWuggML1/1DTuZUuIaJPIm1FTDUVXl4x/yW8s0kQDQ==}
     engines: {node: '>= 0.6.0'}
     dev: false
 
@@ -3084,10 +3099,10 @@ packages:
     engines: {node: '>=12.22'}
     dev: true
 
-  /css-line-break@2.1.0:
-    resolution: {integrity: sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==}
+  /css-line-break@1.1.1:
+    resolution: {integrity: sha512-1feNVaM4Fyzdj4mKPIQNL2n70MmuYzAXZ1aytlROFX1JsOo070OsugwGjj7nl6jnDJWHDM8zRZswkmeYVWZJQA==}
     dependencies:
-      utrie: 1.0.2
+      base64-arraybuffer: 0.2.0
     dev: false
 
   /css-select@4.3.0:
@@ -4861,12 +4876,11 @@ packages:
     resolution: {integrity: sha512-0quDb7s97CfemeJAnW9wC0hw78MtW7NU3hqtCD75g2vFlDLt36llsYD7uB7SUzojLMP24N5IatXf7ylGXiGG9A==}
     dev: false
 
-  /html2canvas@1.4.1:
-    resolution: {integrity: sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==}
+  /html2canvas@1.0.0:
+    resolution: {integrity: sha512-0d/f2Aj1Brn+EeNWkuRdtnT13qu1NdvxhBMvts3ssme7jgPU7dtuwnm1P6cXvXmnDdUUerH5XdhveWvuLfqkew==}
     engines: {node: '>=8.0.0'}
     dependencies:
-      css-line-break: 2.1.0
-      text-segmentation: 1.0.3
+      css-line-break: 1.1.1
     dev: false
 
   /htmlparser2@3.10.1:
@@ -6543,8 +6557,8 @@ packages:
       source-map-js: 1.0.2
     dev: true
 
-  /postcss@8.4.32:
-    resolution: {integrity: sha512-D/kj5JNu6oo2EIy+XL/26JEDTlIbB8hw85G8StOE6L74RQAVVP5rej6wxCNqyMbR4RkPfqvezVbPw81Ngd6Kcw==}
+  /postcss@8.4.35:
+    resolution: {integrity: sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==}
     engines: {node: ^10 || ^12 || >=14}
     dependencies:
       nanoid: 3.3.7
@@ -7097,6 +7111,16 @@ packages:
     dev: false
     optional: true
 
+  /simple-git@3.22.0:
+    resolution: {integrity: sha512-6JujwSs0ac82jkGjMHiCnTifvf1crOiY/+tfs/Pqih6iow7VrpNKRRNdWm6RtaXpvvv/JGNYhlUtLhGFqHF+Yw==}
+    dependencies:
+      '@kwsites/file-exists': 1.1.1
+      '@kwsites/promise-deferred': 1.1.1
+      debug: 4.3.4
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
   /slash@3.0.0:
     resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==}
     engines: {node: '>=8'}
@@ -7682,12 +7706,6 @@ packages:
     engines: {node: '>=0.10'}
     dev: true
 
-  /text-segmentation@1.0.3:
-    resolution: {integrity: sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==}
-    dependencies:
-      utrie: 1.0.2
-    dev: false
-
   /text-table@0.2.0:
     resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
     dev: true
@@ -8027,12 +8045,6 @@ packages:
     engines: {node: '>= 0.4.0'}
     dev: true
 
-  /utrie@1.0.2:
-    resolution: {integrity: sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==}
-    dependencies:
-      base64-arraybuffer: 1.0.2
-    dev: false
-
   /v8-compile-cache-lib@3.0.1:
     resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==}
     dev: true
@@ -8053,7 +8065,7 @@ packages:
     engines: {node: '>= 0.8'}
     dev: true
 
-  /vite-plugin-compression@0.5.1(vite@5.0.10):
+  /vite-plugin-compression@0.5.1(vite@5.1.3):
     resolution: {integrity: sha512-5QJKBDc+gNYVqL/skgFAP81Yuzo9R+EAf19d+EtsMF/i8kFUpNi3J/H01QD3Oo8zBQn+NzoCIFkpPLynoOzaJg==}
     peerDependencies:
       vite: '>=2.0.0'
@@ -8061,13 +8073,13 @@ packages:
       chalk: 4.1.2
       debug: 4.3.4
       fs-extra: 10.1.0
-      vite: 5.0.10(@types/node@17.0.45)(sass@1.53.0)
+      vite: 5.1.3(@types/node@17.0.45)(sass@1.53.0)
     transitivePeerDependencies:
       - supports-color
     dev: true
 
-  /vite-plugin-html@3.2.0(vite@5.0.10):
-    resolution: {integrity: sha512-2VLCeDiHmV/BqqNn5h2V+4280KRgQzCFN47cst3WiNK848klESPQnzuC3okH5XHtgwHH/6s1Ho/YV6yIO0pgoQ==}
+  /vite-plugin-html@3.2.2(vite@5.1.3):
+    resolution: {integrity: sha512-vb9C9kcdzcIo/Oc3CLZVS03dL5pDlOFuhGlZYDCJ840BhWl/0nGeZWf3Qy7NlOayscY4Cm/QRgULCQkEZige5Q==}
     peerDependencies:
       vite: '>=2.0.0'
     dependencies:
@@ -8083,10 +8095,10 @@ packages:
       html-minifier-terser: 6.1.0
       node-html-parser: 5.3.3
       pathe: 0.2.0
-      vite: 5.0.10(@types/node@17.0.45)(sass@1.53.0)
+      vite: 5.1.3(@types/node@17.0.45)(sass@1.53.0)
     dev: true
 
-  /vite-plugin-mock@2.9.6(mockjs@1.1.0)(vite@5.0.10):
+  /vite-plugin-mock@2.9.6(mockjs@1.1.0)(vite@5.1.3):
     resolution: {integrity: sha512-/Rm59oPppe/ncbkSrUuAxIQihlI2YcBmnbR4ST1RA2VzM1C0tEQc1KlbQvnUGhXECAGTaQN2JyasiwXP6EtKgg==}
     engines: {node: '>=12.0.0'}
     peerDependencies:
@@ -8103,13 +8115,13 @@ packages:
       fast-glob: 3.2.12
       mockjs: 1.1.0
       path-to-regexp: 6.2.1
-      vite: 5.0.10(@types/node@17.0.45)(sass@1.53.0)
+      vite: 5.1.3(@types/node@17.0.45)(sass@1.53.0)
     transitivePeerDependencies:
       - rollup
       - supports-color
     dev: true
 
-  /vite-plugin-style-import@2.0.0(vite@5.0.10):
+  /vite-plugin-style-import@2.0.0(vite@5.1.3):
     resolution: {integrity: sha512-qtoHQae5dSUQPo/rYz/8p190VU5y19rtBaeV7ryLa/AYAU/e9CG89NrN/3+k7MR8mJy/GPIu91iJ3zk9foUOSA==}
     peerDependencies:
       vite: '>=2.0.0'
@@ -8121,10 +8133,10 @@ packages:
       fs-extra: 10.1.0
       magic-string: 0.25.9
       pathe: 0.2.0
-      vite: 5.0.10(@types/node@17.0.45)(sass@1.53.0)
+      vite: 5.1.3(@types/node@17.0.45)(sass@1.53.0)
     dev: true
 
-  /vite-plugin-svg-icons@2.0.1(vite@5.0.10):
+  /vite-plugin-svg-icons@2.0.1(vite@5.1.3):
     resolution: {integrity: sha512-6ktD+DhV6Rz3VtedYvBKKVA2eXF+sAQVaKkKLDSqGUfnhqXl3bj5PPkVTl3VexfTuZy66PmINi8Q6eFnVfRUmA==}
     peerDependencies:
       vite: '>=2.0.0'
@@ -8137,23 +8149,23 @@ packages:
       pathe: 0.2.0
       svg-baker: 1.7.0
       svgo: 2.8.0
-      vite: 5.0.10(@types/node@17.0.45)(sass@1.53.0)
+      vite: 5.1.3(@types/node@17.0.45)(sass@1.53.0)
     transitivePeerDependencies:
       - supports-color
     dev: true
 
-  /vite-plugin-vue-setup-extend@0.4.0(vite@5.0.10):
+  /vite-plugin-vue-setup-extend@0.4.0(vite@5.1.3):
     resolution: {integrity: sha512-WMbjPCui75fboFoUTHhdbXzu4Y/bJMv5N9QT9a7do3wNMNHHqrk+Tn2jrSJU0LS5fGl/EG+FEDBYVUeWIkDqXQ==}
     peerDependencies:
       vite: '>=2.0.0'
     dependencies:
       '@vue/compiler-sfc': 3.3.4
       magic-string: 0.25.9
-      vite: 5.0.10(@types/node@17.0.45)(sass@1.53.0)
+      vite: 5.1.3(@types/node@17.0.45)(sass@1.53.0)
     dev: true
 
-  /vite@5.0.10(@types/node@17.0.45)(sass@1.53.0):
-    resolution: {integrity: sha512-2P8J7WWgmc355HUMlFrwofacvr98DAjoE52BfdbwQtyLH06XKwaL/FMnmKM2crF0iX4MpmMKoDlNCB1ok7zHCw==}
+  /vite@5.1.3(@types/node@17.0.45)(sass@1.53.0):
+    resolution: {integrity: sha512-UfmUD36DKkqhi/F75RrxvPpry+9+tTkrXfMNZD+SboZqBCMsxKtO52XeGzzuh7ioz+Eo/SYDBbdb0Z7vgcDJew==}
     engines: {node: ^18.0.0 || >=20.0.0}
     hasBin: true
     peerDependencies:
@@ -8182,7 +8194,7 @@ packages:
     dependencies:
       '@types/node': 17.0.45
       esbuild: 0.19.10
-      postcss: 8.4.32
+      postcss: 8.4.35
       rollup: 4.9.1
       sass: 1.53.0
     optionalDependencies:

+ 25 - 0
src/api/scene/scene.ts

@@ -240,3 +240,28 @@ export const getCompanyLayoutApi = (params: { companyId: number; labelId: number
     params,
   });
 };
+
+// /** 查询公司主页配置 */
+// export const getCompanyLayoutApi = (params: { companyId: number; labelId: number }) => {
+//   return http.request({
+//     url: '/homepageConfig/getCompanyLayoutByCompanyLabel',
+//     method: 'get',
+//     params,
+//   });
+// };
+
+/** 查询所有公司主页配置 */
+export const getCompanyLayoutList = () => {
+  return http.request({
+    url: '/homepageConfig/getCompanyLayoutList',
+    method: 'get',
+  });
+};
+
+/** 删除公司主页配置 */
+export const delCompanyLayout = (params: number) => {
+  return http.request({
+    url: `/homepageConfig/deleteCompanyLayout?layoutId=${params}`,
+    method: 'delete',
+  });
+};

Разница между файлами не показана из-за своего большого размера
+ 23 - 0
src/assets/1.svg


Разница между файлами не показана из-за своего большого размера
+ 24 - 0
src/assets/test/1-cir.svg


Разница между файлами не показана из-за своего большого размера
+ 16 - 0
src/assets/test/1-curv.svg


Разница между файлами не показана из-за своего большого размера
+ 24 - 0
src/assets/test/1-curv2.svg


Разница между файлами не показана из-за своего большого размера
+ 23 - 0
src/assets/test/1.svg


+ 23 - 0
src/assets/test/2-rect.svg

@@ -0,0 +1,23 @@
+<svg width="160" height="38" fill="currentColor" xmlns="http://www.w3.org/2000/svg"
+    xmlns:xlink="http://www.w3.org/1999/xlink">
+    <defs>
+        <linearGradient x1="100%" y1="51.673%" x2="0%" y2="48.327%" id="prefix__a">
+            <stop stop-color="currentColor" offset="0%" />
+            <stop stop-color="currentColor" stop-opacity=".5" offset="100%" />
+        </linearGradient>
+    </defs>
+    <g transform="translate(0 1)" fill="none" fill-rule="evenodd">
+        <g transform="translate(8.27 23.337)" fill-rule="nonzero">
+            <path stroke="currentColor" stroke-width=".5" d="M.664.476l3.984 2.857h80.56L89.191.476h52.674" />
+            <circle fill="currentColor" cx=".664" cy=".476" r="1" />
+            <path fill="currentColor" d="M102.471.476H92.069v1h10.402z" />
+            <path fill="currentColor" d="M85.207 3.333H4.647v1h80.56z" />
+        </g>
+        <path d="M13.426 14.448l-10.62 5.32V9.129l10.62 5.32z" stroke="currentColor" stroke-width=".5" />
+        <path fill="currentColor" d="M10.175 14.448l-6.349 3.18v-6.36z" />
+        <path d="M146.904 14.448l10.62 5.32V9.129l-10.62 5.32z" stroke="currentColor" stroke-width=".5" />
+        <path fill="currentColor" d="M150.155 14.448l6.349 3.18v-6.36z" />
+        <path d="M159.428.25v28.705H5.179L.25 24.36V2.315L3.428.25h156z" stroke-opacity=".498" stroke="#FFFFFF"
+            stroke-width=".5" fill-opacity=".7" fill="url(#prefix__a)" transform="translate(0 -.154)" />
+    </g>
+</svg>

Разница между файлами не показана из-за своего большого размера
+ 6 - 0
src/assets/test/2-shine.svg


Разница между файлами не показана из-за своего большого размера
+ 8 - 0
src/assets/test/2-shining.svg


Разница между файлами не показана из-за своего большого размера
+ 25 - 0
src/assets/test/2.svg


+ 1 - 0
src/components/Table/src/Table.vue

@@ -87,6 +87,7 @@
         v-bind="getBindValues"
         v-loading="tableLoading"
         @sort-change="sortChange"
+        :expand-row-keys="$props.expendRow"
       >
         <template v-for="item in getTableColumns" :key="item.key">
           <el-table-column

+ 5 - 0
src/components/Table/src/props.ts

@@ -36,6 +36,11 @@ export const basicProps = {
     default: () => [],
     required: true,
   },
+  expendRow: {
+    type: [Array],
+    default: () => [],
+    // required: true,
+  },
   request: {
     type: Function as PropType<(...arg: any[]) => Promise<any>>,
     default: null,

+ 0 - 18
src/hooks/useSceneInfos.ts

@@ -60,24 +60,6 @@ export function useSceneInfos() {
 
   const getCameraList = (workshop: number) => {
     return getCamerasByWorkSpace({ workshopId: workshop }).then((res) => {
-      res[0]?.cameraList?.push(
-        {
-          name: 'C204',
-          code: 'C204',
-          cameraIp: '192.168.1.203',
-          remark: '',
-          status: 0,
-          pushstreamIp: 'http://192.168.1.138:8080/live/C203.flv',
-        },
-        {
-          name: 'C205',
-          code: 'C205',
-          cameraIp: '192.168.1.203',
-          remark: '',
-          status: 0,
-          pushstreamIp: 'http://192.168.1.138:8080/live/C203.flv',
-        },
-      );
       return res;
     });
   };

+ 2 - 1
src/main.ts

@@ -8,11 +8,12 @@ import VueKonva from 'vue-konva';
 
 import { createApp } from 'vue';
 import App from './App.vue';
-import VueKonva from 'vue-konva';
+// import VueKonva from 'vue-konva';
 import router, { setupRouter } from './router';
 import { setupStore } from '@/store';
 import 'virtual:svg-icons-register';
 import { setupElement, setupDirectives, setupCustomComponents } from '@/plugins';
+// import VueKonva from 'vue-konva';
 
 async function bootstrap() {
   const app = createApp(App);

+ 47 - 34
src/views/map-config/mini-map/MapBase/KonvaMap.vue

@@ -6,6 +6,7 @@
         <v-group
           v-for="camera in cameras"
           :key="camera.id"
+          :id="camera.id"
           :config="camera.groupConfig"
           @click="handleCameraClick(camera)"
           @mouseover="(e) => handleMouseOver(e)"
@@ -42,6 +43,7 @@
   import cameraImgSrc from '@/assets/camera/cameraImg.png';
   import favoritesImgSrc from '@/assets/camera/favorites.png';
   import { TipPositionEnum, camerasGroupType } from '../type';
+  import { cloneDeep } from 'lodash-es';
 
   const globSetting = useGlobSetting();
 
@@ -91,7 +93,12 @@
     backgroundSize: 'cover',
   });
 
-  const transformerConfig = ref({ keepRatio: true, rotateAnchorOffset: 30 });
+  //待修改
+  const transformerConfig = ref({
+    keepRatio: true,
+    rotateAnchorOffset: 30,
+    enabledAnchors: ['top-left', 'top-right', 'bottom-left', 'bottom-right'],
+  });
 
   //背景大小变换
   const resizeContainer = (width, height) => {
@@ -195,8 +202,6 @@
   const addCamera = (id: string) => {
     const existingCamera = cameras.value.find((camera) => camera.id === id);
     if (existingCamera) return;
-    // const camImg = new Image();
-    // camImg.src = cameraImgSrc;
     const config = {
       width: 52,
       height: 37,
@@ -235,6 +240,12 @@
         item.isDefault = false;
       }
     });
+    const transformerNode = transformer.value.getNode();
+    const stage = transformerNode.getStage();
+    transformerNode.nodes([]);
+    const cameraNode = stage.findOne('#' + defaultCameraId.value);
+    // 将变换器附加到点击的相机
+    transformerNode.nodes([cameraNode]);
     defaultShow.value = false;
   };
 
@@ -254,41 +265,44 @@
     { immediate: true, deep: true },
   );
 
+  const clearBg = () => {
+    bgImg.src = null as any as string;
+  };
+
   //添加背景
   const addBg = (imgBg) => {
-    bgImgUrl.value = imgBg;
-    if (!bgImgUrl.value) {
-      bgImg.src = null as any as string;
-      return;
-    }
-    bgImg.src = urlJoin(globSetting.imgUrl!, imgBg) as string;
-    bgImg.onload = () => {
-      bgConfig.value.width = bgImg.width;
-      bgConfig.value.height = bgImg.height;
-      resizeContainer(bgImg.width, bgImg.height);
-    };
+    return new Promise((resolve) => {
+      bgImgUrl.value = imgBg;
+      bgImg.src = urlJoin(globSetting.imgUrl!, imgBg) as string;
+      bgImg.onload = () => {
+        bgConfig.value.width = bgImg.width;
+        bgConfig.value.height = bgImg.height;
+        resizeContainer(bgImg.width, bgImg.height);
+        resolve(null);
+      };
+    });
   };
 
   //保存布局
   const saveLayout = () => {
     const stage = transformer.value.getNode().getStage();
     const groups = stage.find('.group');
-    const camerasList = groups.map((item, index) => {
-      cameras.value[index].groupConfig.x = Math.round(item.attrs.x | 0);
-      cameras.value[index].groupConfig.y = Math.round(item.attrs.y | 0);
-      cameras.value[index].groupConfig.rotation = Number((item.attrs.rotation | 0).toFixed(2));
-      cameras.value[index].groupConfig.scaleX = Number((item.attrs.scaleX | 1).toFixed(1));
-      cameras.value[index].groupConfig.scaleY = Number((item.attrs.scaleY | 1).toFixed(1));
-      cameras.value[index].config.url = cameraImgSrc;
-      return cameras.value[index];
+    const tempList = cloneDeep(cameras.value);
+    const camerasLists = tempList.map((item, index) => {
+      item.groupConfig.x = groups[index].attrs.x;
+      item.groupConfig.y = groups[index].attrs.y;
+      item.groupConfig.rotation = groups[index].attrs.rotation || 0;
+      item.groupConfig.scaleX = groups[index].attrs.scaleX || 1;
+      item.groupConfig.scaleY = groups[index].attrs.scaleY || 1;
+      item.config.url = cameraImgSrc;
+      return item;
     });
-    cameras.value = camerasList;
     const layout = {
       stageConfig: stageConfig.value,
       bgConfig: bgConfig.value,
       bgImgUrl: bgImgUrl.value,
       defaultCameraId: defaultCameraId.value,
-      cameraList: cameras.value,
+      cameraList: camerasLists,
     };
     return JSON.stringify(layout);
   };
@@ -315,7 +329,7 @@
   //重置
   const resetMap = () => {
     bgImgUrl.value = null;
-    addBg('');
+    clearBg();
     cameras.value = [];
     lastClickedGroupId.value = null;
     defaultCameraId.value = '';
@@ -323,16 +337,15 @@
 
   /** 导入布局json */
   const createMap = (layout) => {
-    addBg(layout.bgImgUrl);
-    stageConfig.value = layout.stageConfig;
-    // const camImg = new Image();
-    // camImg.src = cameraImgSrc;
-    defaultCameraId.value = layout.defaultCameraId;
-    layout.cameraList = layout.cameraList?.map((item) => {
-      item.config.image = camImg;
-      return item;
+    addBg(layout.bgImgUrl).then((_res) => {
+      stageConfig.value = layout.stageConfig;
+      defaultCameraId.value = layout.defaultCameraId;
+      layout.cameraList = layout.cameraList?.map((item) => {
+        item.config.image = camImg;
+        return item;
+      });
+      cameras.value = layout.cameraList;
     });
-    cameras.value = layout.cameraList;
   };
 
   defineExpose({ addBg, createMap, resetMap, addCamera, resizeContainer, saveLayout });

+ 2 - 15
src/views/map-config/mini-map/MiniMapConfig.vue

@@ -1,5 +1,5 @@
 <template>
-  <div class="page" @click="handleWholeClick">
+  <div class="page">
     <div class="page-head flex items-center">
       <el-icon size="20"><ArrowLeft /></el-icon>
       <div class="head-opt flex-1 flex justify-between items-center">
@@ -26,9 +26,7 @@
             name="file"
             :data="{ workshopId: selectedShopDetail?.id }"
           >
-            <el-button style="font-size: 12px" :icon="Refresh" :disabled="!hasBg">
-              替换照片
-            </el-button>
+            <el-button :icon="Refresh" :disabled="!hasBg"> 替换照片 </el-button>
           </el-upload>
 
           <el-button
@@ -144,7 +142,6 @@
     camerasAdded.value = camerasList.map((item) => {
       return item.id;
     });
-    // console.log('camerasAdded.value', camerasAdded.value);
   };
 
   /** 判断相机是否已经添加 */
@@ -158,7 +155,6 @@
   };
 
   const handleAvatarSuccess = (e) => {
-    //自己的
     imgUrlBg.value = e.data;
     konvaMap.value.addBg(imgUrlBg.value);
     hasBg.value = true;
@@ -181,12 +177,6 @@
     });
   };
 
-  const handleWholeClick = (e) => {
-    // if (e.button === 0) {
-    //   mapEditor.destoryOptBlock();
-    // }
-  };
-
   onMounted(() => {
     getScenesTree({ level: 2, valueKey: 'code', labelKey: 'name', disabled: true });
     konvaMap.value.resizeContainer(
@@ -212,12 +202,9 @@
       return;
     }
     konvaMap.value.addCamera(cameraId);
-    // mapEditor.addCamera(cameraId);
-    // konvaMap.value.addCamera(cameraId);
   };
 
   const handleSave = () => {
-    // const layout = mapEditor.toJson();
     const layout = konvaMap.value.saveLayout();
     updateMinMapViewLayoutApi({ layout, targetId: String(selectedShopDetail.value?.id) }).then(
       (res) => {

+ 53 - 27
src/views/page-config/ConfigEdit.vue

@@ -4,7 +4,7 @@
       <el-icon size="20"><ArrowLeft /></el-icon>
       <div class="head-opt flex-1 flex justify-between items-center">
         <div>
-          <span>场景:</span>
+          <!-- <span>场景:</span> -->
           <el-select
             v-model="selectedCompany"
             class="m-2"
@@ -20,7 +20,7 @@
             />
           </el-select>
         </div>
-        <div v-if="selectedCompany" style="display: flex; margin-top: 8px">
+        <div v-if="selectedCompany" style="display: flex">
           <div class="label-workshop">选择标签:</div>
           <div>
             <el-radio-group
@@ -50,9 +50,7 @@
             name="file"
             :data="{ companyId: selectedCompany, labelId: label, deleteFileName: bgImg }"
           >
-            <el-button style="font-size: 12px" :icon="Refresh" :disabled="!hasBg">
-              替换照片
-            </el-button>
+            <el-button :icon="Refresh" :disabled="!hasBg"> 替换照片 </el-button>
           </el-upload>
 
           <el-button
@@ -87,7 +85,7 @@
             class="camera-item flex justify-start items-center"
             :class="{
               isAdded: isAddedShop(item.id),
-              isActive: item.id === activeShop.id,
+              isActive: item.id === Number(activeShopId),
             }"
             @click="handleAddShop(item)"
           >
@@ -97,7 +95,7 @@
       </div>
       <div ref="drawContainer" id="drawContainer" class="draw-container">
         <div id="shopEditContainer" v-moveable:1>
-          <MapContainer />
+          <MapContainer ref="mapContainerRef" @on-open="openConfig" />
         </div>
         <el-upload
           v-if="!hasBg"
@@ -131,12 +129,15 @@
       >
         <el-icon class="left-icon" size="16px"><ArrowLeftBold /></el-icon>
         <el-icon style="margin-top: 7px" size="16px"><ArrowLeftBold /></el-icon>
-        <!-- <el-icon class="left-icon"><DArrowLeft /></el-icon> -->
       </div>
-      <!-- <img src="~@/assets/icons/slide.png" alt="" class="dialog-btn" /> -->
     </el-tooltip>
 
-    <ConfigDialog ref="configDrawer" @on-close="onClose" class="drawer-position" />
+    <ConfigDialog
+      ref="configDrawer"
+      @on-close="onClose"
+      @transformer-change="transformChange"
+      class="drawer-position"
+    />
 
     <ConfigFinish
       :visible="visibleResult"
@@ -152,10 +153,10 @@
   import ConfigFinish from './component/ConfigFinish.vue';
   import { storeToRefs } from 'pinia';
   import { ElMessage, ElInput } from 'element-plus';
-  import { onBeforeUnmount, onMounted, ref } from 'vue';
+  import { onBeforeUnmount, onMounted, ref, watch } from 'vue';
   import { WorkShopInfoItem } from '@/api/scene/scene';
   import { computed } from 'vue';
-  import { Search, Refresh } from '@element-plus/icons-vue';
+  import { Search, Refresh, ArrowLeftBold, ArrowLeft } from '@element-plus/icons-vue';
   import usePageConfig from './usePageConfig';
   import MapContainer from './component/mapContainer/MapContainer.vue';
   import useMapEditor, { LabelPositionEnum } from './stores/useMapEditor';
@@ -164,8 +165,8 @@
   import { useRouter } from 'vue-router';
 
   const mapEditor = useMapEditor();
-  const { bgImg, addedShops, activeShop } = storeToRefs(mapEditor);
-  const { addShop, addBg, toJson, resetMap, createMap, deleteShop } = mapEditor;
+  const { bgImg, addedShops, activeShopId, showShops } = storeToRefs(mapEditor);
+  const { addShop, addBg, calcLayout, resetMap, createMap, deleteShop } = mapEditor;
 
   const router = useRouter();
 
@@ -173,6 +174,7 @@
   const { selectedCompany, scenesInfos, label, labelList, shopList, layoutId } = pageConfig;
 
   const drawContainer = ref<HTMLDivElement>();
+  const mapContainerRef = ref();
 
   const searchKey = ref('');
   // 是否已有背景图
@@ -199,6 +201,18 @@
     leftShow.value = val;
   };
 
+  const transformChange = () => {
+    mapContainerRef.value.updateLayoutTransformer();
+  };
+
+  watch(
+    () => showShops,
+    () => {
+      transformChange();
+    },
+    { deep: true },
+  );
+
   const shadow = ref(false);
   const shadowAdd = () => {
     shadow.value = true;
@@ -212,6 +226,10 @@
     configDrawer.value.openDialog();
   };
 
+  const openConfig = () => {
+    configDrawer.value.openDialog();
+  };
+
   //总体的保存,将整个数据传过去
   const visibleResult = ref(false);
   const configStatus = ref(true);
@@ -222,24 +240,26 @@
 
   const handleAvatarSuccess = (e) => {
     bgImg.value = e.data;
-    addBg();
     hasBg.value = true;
+    addBg();
   };
 
   const changeShop = () => {
+    hasBg.value = false;
     resetMap();
     getShopContent();
-    hasBg.value = false;
   };
 
   const getShopContent = () => {
     getCompanyLayoutApi({ companyId: selectedCompany.value || 2, labelId: label.value || 1 }).then(
       (res) => {
         if (!res) {
+          layoutId.value = undefined;
           return;
         }
         layoutId.value = res.id;
         const layoutJSON = res.layout ? safeParse(res.layout) : null;
+
         if (!layoutJSON) {
           return;
         }
@@ -259,6 +279,7 @@
     // 删除键
     if (e.keyCode === 46 || e.code === 'Delete') {
       deleteShop();
+      configDrawer.value.closeDialog();
     }
   };
 
@@ -266,7 +287,9 @@
     const routerParams = router.currentRoute.value.query;
     if (routerParams.companyId) {
       selectedCompany.value = Number(routerParams.companyId);
-      console.log(selectedCompany.value);
+    }
+    if (routerParams.labelId) {
+      label.value = Number(routerParams.labelId);
     }
 
     window.addEventListener('keydown', handleKeyDown);
@@ -283,6 +306,10 @@
   });
 
   const handleAddShop = (shop: WorkShopInfoItem) => {
+    //如果已经存在车间,则禁止加入
+    const existingCamera = addedShops.value.find((item) => item.id === shop.id);
+    if (existingCamera) return;
+    // activeShopId.value = shop.id;
     if (!hasBg.value) {
       ElMessage.warning({
         message: '请先添加背景图片',
@@ -291,9 +318,10 @@
     }
     const shopNode = {
       ...shop,
-      x: 20,
-      y: 20,
-      scale: 1,
+      x: 50,
+      y: 50,
+      scaleX: 1,
+      scaleY: 1,
       bgColor: 'rgba(58, 170, 209, 1)',
       fontSize: 14,
       fontColor: '#ffffff',
@@ -304,7 +332,8 @@
   };
 
   const handleSave = () => {
-    const layout = toJson();
+    const json = mapContainerRef.value?.getLayout();
+    const layout = calcLayout(json);
     const param = {
       layout,
       targetId: selectedCompany.value || 2,
@@ -312,14 +341,11 @@
     };
     if (!layoutId.value) {
       uploadCompanyLayout(param).then((res) => {
-        console.log('uploadCompanyLayout', res);
         layoutId.value = res;
         ElMessage.success('保存成功');
       });
     } else {
-      updateCompanyLayout({ ...param, id: layoutId.value }).then((res) => {
-        console.log('updateCompanyLayout', res);
-        layoutId.value = res;
+      updateCompanyLayout({ ...param, id: layoutId.value }).then((_res) => {
         ElMessage.success('更新成功');
       });
     }
@@ -469,8 +495,8 @@
 
   .feedback-position {
     position: absolute;
-    left: 460px;
-    top: 150px;
+    left: 760px;
+    top: 250px;
     z-index: 9999;
   }
 

+ 50 - 15
src/views/page-config/component/ConfigDrawer.vue

@@ -28,8 +28,8 @@
             list-type="picture-card"
             :action="
               editShop.thumbnail
-                ? '/api/homepageConfig/updateWorkshopPicture'
-                : '/api/homepageConfig/uploadWorkshopPicture'
+                ? '/skyeye-admin-api/homepageConfig/updateWorkshopPicture'
+                : '/skyeye-admin-api/homepageConfig/uploadWorkshopPicture'
             "
             :show-file-list="false"
             :with-credentials="true"
@@ -37,7 +37,7 @@
             :on-success="handleAvatarSuccess"
             :data="
               editShop.thumbnail
-                ? { workshopId: editShop.id, deleteFileName: editShop.thumbnail }
+                ? { workshopId: editShop.id, deleteFileName: thumbnailChange }
                 : { workshopId: editShop.id }
             "
           >
@@ -100,11 +100,30 @@
           </div>
           <hr />
           <div>
+            <!-- //这里要变选值 -->
             <div class="content-title"><div class="uploader-title">布局</div> </div>
             <div class="layout-set">
-              <img src="~@/assets/icons/layout-left.png" alt="" style="margin-right: 19px" />
-              <img src="~@/assets/icons/layout-right.png" alt="" style="margin-right: 17px" />
-              <img src="~@/assets/icons/layout-top.png" alt="" />
+              <img
+                src="~@/assets/icons/layout-left.png"
+                alt=""
+                @click="posAdj(LabelPositionEnum.LEFT)"
+                style="margin-right: 19px; cursor: pointer"
+                :class="{ active: editShop.posType === LabelPositionEnum.LEFT }"
+              />
+              <img
+                src="~@/assets/icons/layout-right.png"
+                alt=""
+                @click="posAdj(LabelPositionEnum.RIGHT)"
+                style="margin-right: 17px; cursor: pointer"
+                :class="{ active: editShop.posType === LabelPositionEnum.RIGHT }"
+              />
+              <img
+                src="~@/assets/icons/layout-top.png"
+                alt=""
+                style="cursor: pointer"
+                @click="posAdj(LabelPositionEnum.TOP)"
+                :class="{ active: editShop.posType === LabelPositionEnum.TOP }"
+              />
             </div>
           </div>
         </div>
@@ -118,24 +137,30 @@
   import { Plus, RefreshRight } from '@element-plus/icons-vue';
   import { ElMessage } from 'element-plus';
   import { colorRGB2Hex } from '@/utils';
-  import useMapEditor, { MapWorkShopInfoItem } from '../stores/useMapEditor';
+  import useMapEditor, { LabelPositionEnum, MapWorkShopInfoItem } from '../stores/useMapEditor';
   import { storeToRefs } from 'pinia';
   import { cloneDeep } from 'lodash-es';
   import { useGlobSetting } from '@/hooks/setting';
   import urlJoin from 'url-join';
 
   const mapEditor = useMapEditor();
-  const { addedShops, showShops, activeShop } = storeToRefs(mapEditor);
+  const { addedShops, showShops, activeShopId } = storeToRefs(mapEditor);
 
   const globSetting = useGlobSetting();
 
-  const editShop = computed(
-    () =>
-      showShops.value.find((item) => item.id === activeShop.value.id) ||
-      ({} as MapWorkShopInfoItem),
-  );
+  const editShop = computed(() => {
+    const val =
+      showShops.value.find((item) => {
+        return item.id === Number(activeShopId.value);
+      }) || ({} as MapWorkShopInfoItem);
+    return val;
+  });
+
+  const thumbnailChange = computed(() => {
+    return editShop.value.thumbnail?.replace(globSetting.imgUrl!, '');
+  });
 
-  const emit = defineEmits(['onClose', 'saveConfig']);
+  const emit = defineEmits(['onClose', 'transformerChange']);
 
   const showColor = computed(() => colorRGB2Hex(editShop.value!.bgColor));
   const dialogTableVisible = ref(false);
@@ -162,13 +187,19 @@
     emit('onClose', true);
   };
 
+  const posAdj = (pos: LabelPositionEnum) => {
+    editShop.value.posType = pos;
+    emit('transformerChange');
+  };
+
   const fontSizeList = Array.from({ length: 11 }, (_, index) => index + 10);
 
   const saveWorkshopConfig = () => {
     addedShops.value = cloneDeep(showShops.value);
+    closeDialog();
   };
 
-  defineExpose({ openDialog });
+  defineExpose({ openDialog, closeDialog });
 </script>
 
 <style lang="scss" scoped>
@@ -315,4 +346,8 @@
     left: 105px;
     bottom: 35px;
   }
+
+  .active {
+    background-color: #cbcdce;
+  }
 </style>

+ 1 - 3
src/views/page-config/component/ConfigFinish.vue

@@ -17,9 +17,7 @@
   </div>
 </template>
 <script lang="ts" setup>
-  import { ref } from 'vue';
-  import { Close, Plus, RefreshRight } from '@element-plus/icons-vue';
-  import { ElMessage } from 'element-plus';
+  import { Close } from '@element-plus/icons-vue';
   import { useRouter } from 'vue-router';
   const router = useRouter();
 

+ 67 - 16
src/views/page-config/component/PageMain.vue

@@ -11,13 +11,20 @@
       </div>
 
       <div
-        v-for="item in picList"
+        v-for="item in companyLayoutList"
         :key="item.id"
         class="content-show"
+        :class="{ 'content-active': item.id === IconId }"
         @mouseover="showDeleteIcon(item)"
         @mouseleave="hideDeleteIcon(item)"
+        @click="handleClick(item)"
       >
-        <div class="pic-box"><img src="" alt="图片" class="content-pic" /></div>
+        <div class="pic-box"
+          ><img
+            :src="globSetting.imgUrl! +(item.layout as any).bgInfo.img"
+            alt="图片"
+            class="content-pic"
+        /></div>
 
         <div class="pic-word">
           <img src="~@/assets/icons/file.png" alt="" />
@@ -26,41 +33,79 @@
             v-show="item.id === IconId"
             src="~@/assets/icons/del.png"
             alt=""
-            @click="deleteItem(item)"
+            @click.stop="deleteItem(item)"
             class="del-icon"
           />
-          <!-- <el-icon v-show="item.id === IconId" @click="deleteItem(item)" class="del-icon"
-            ><Delete
-          /></el-icon> -->
         </div>
-      </div>
-    </div></div
-  >
+      </div> </div
+  ></div>
 </template>
 <script lang="ts" setup>
-  import { ref } from 'vue';
-  import { picList } from '../constant';
+  import { ref, onMounted } from 'vue';
   import { useRouter } from 'vue-router';
+  import { useGlobSetting } from '@/hooks/setting';
   import { Plus } from '@element-plus/icons-vue';
+  import { getCompanyLayoutList, delCompanyLayout } from '@/api/scene/scene';
+
+  const globSetting = useGlobSetting();
+  interface companyLayoutType {
+    createdAt: string;
+    id: number;
+    isDelete: number;
+    labelId: number;
+    layout: string;
+    name: string;
+    status: number;
+    targetId: number;
+    updatedAt: string;
+    version: string;
+    viewType: number;
+  }
+  const companyLayoutList = ref<companyLayoutType[]>([]);
+
+  onMounted(() => {
+    getCompanyLayoutList().then((res) => {
+      companyLayoutList.value = res;
+      companyLayoutList.value = companyLayoutList.value.map((item) => {
+        item.layout = JSON.parse(item.layout);
+        return item;
+      });
+    });
+  });
+
   const router = useRouter();
 
-  // const pageAdd = ref<boolean>(true);
   const handleAddPage = () => {
     router.push('/page-config/config');
   };
 
-  const IconId = ref('');
+  const IconId = ref<number>();
   const showDeleteIcon = (item) => {
     IconId.value = item.id;
   };
 
   const hideDeleteIcon = (_item) => {
-    IconId.value = '';
+    IconId.value = undefined;
+  };
+
+  const handleClick = (item) => {
+    router.push({
+      path: '/page-config/config',
+      query: { companyId: item.targetId, labelId: item.labelId },
+    });
   };
 
   const deleteItem = (item) => {
     // 处理删除逻辑
-    console.log(item);
+    delCompanyLayout(item.id).then(() => {
+      getCompanyLayoutList().then((res) => {
+        companyLayoutList.value = res;
+        companyLayoutList.value = companyLayoutList.value.map((item) => {
+          item.layout = JSON.parse(item.layout);
+          return item;
+        });
+      });
+    });
   };
 
   // const label = ref('');
@@ -93,7 +138,7 @@
     height: 104px;
     background: rgba(255, 255, 255, 0.04);
     border-radius: 5px;
-    border: 1px solid rgba(0, 0, 0, 0.15);
+    border: 1px dashed rgba(0, 0, 0, 0.15);
     // text-align: center;
     margin-left: 56px;
     margin-top: 43px;
@@ -127,6 +172,12 @@
     margin-left: 26px;
     border: 1px solid #e8ecf2;
     margin-bottom: 24px;
+    cursor: pointer;
+    border-radius: 5px;
+  }
+
+  .content-active {
+    box-shadow: 0px 1px 10px 1px rgba(24, 144, 255, 0.5);
   }
 
   .pic-box {

+ 79 - 59
src/views/page-config/component/mapContainer/LabelItem.vue

@@ -1,71 +1,91 @@
 <template>
-  <div class="flex">
-    <SvgIcon icon-name="posPoint" :color="props.shop.bgColor" class="test-icon" />
-    <img
-      v-if="showThumbnail && props.shop.thumbnail"
-      class="hover-img"
-      :src="props.shop.thumbnail"
-      :alt="props.shop.name"
-    />
-    <div class="pos-rect">
-      <SvgIcon icon-name="posRect" :color="props.shop.bgColor" class="test-icon1" />
-      <span
-        class="label-name"
-        :style="{ fontSize: `${props.shop.fontSize}px`, color: props.shop.fontColor }"
-        >{{ props.shop.name }}</span
-      >
-    </div>
-  </div>
+  <v-image ref="pointRef" :config="getPointCurvConfig(props.shop.posType, curvImage)" />
+  <v-image :config="getCirConfig(props.shop.posType, cirImage)" />
+  <v-image ref="rectRef" :config="getRectCurConfig(props.shop.posType, rectImage)" />
+  <v-text :config="getTextConfig(props.shop)" />
+  <v-image :config="shineConfig(props.shop.posType, shineImage)" />
 </template>
 
 <script setup lang="ts">
-  import { computed } from 'vue';
-  import { SvgIcon } from '@/components/SvgIcon';
+  import { ref, onMounted, nextTick, watch } from 'vue';
+  import rectBlock from '@/assets/test/2-rect.svg';
+  import pointCurv from '@/assets/test/1-curv2.svg';
+  import shine from '@/assets/test/2-shining.svg';
+  import circle from '@/assets/test/1-cir.svg';
+  import Konva from 'konva';
   import { MapWorkShopInfoItem } from '../../stores/useMapEditor';
+  import {
+    getRGBANum,
+    getPointCurvConfig,
+    getCirConfig,
+    getRectCurConfig,
+    getTextConfig,
+    shineConfig,
+  } from './labelConfig';
 
-  const props = defineProps<{ shop: MapWorkShopInfoItem; show: boolean }>();
+  const props = defineProps<{ shop: MapWorkShopInfoItem }>();
 
-  const showThumbnail = computed(() => props.show);
-</script>
+  const curvImage = ref<HTMLImageElement>(new Image());
+  const rectImage = ref<HTMLImageElement>(new Image());
+  const shineImage = ref<HTMLImageElement>(new Image());
+  const cirImage = ref<HTMLImageElement>(new Image());
+  const rectRef = ref<Konva.Image>();
+  const pointRef = ref<Konva.Image>();
+
+  const nodeUpdateFilter = (node: Konva.Node) => {
+    node.cache();
+    const rgba = getRGBANum(props.shop.bgColor);
+    node.red(rgba[0]);
+    node.green(rgba[1]);
+    node.blue(rgba[2]);
+    node.alpha(rgba[3]);
+  };
+
+  watch(
+    () => props.shop,
+    () => {
+      nextTick(() => {
+        nodeUpdateFilter(pointRef.value!.getNode());
+        nodeUpdateFilter(rectRef.value!.getNode());
+      });
+    },
+    { deep: true },
+  );
 
-<style scoped>
-  .label-name {
-    position: absolute;
-    font-family: TRENDS;
-    margin-bottom: 10px;
-  }
+  onMounted(() => {
+    const svgImg = new Image();
+    svgImg.onload = () => {
+      curvImage.value = svgImg;
+      nextTick(() => {
+        nodeUpdateFilter(pointRef.value?.getNode());
+      });
+    };
+    svgImg.src = pointCurv;
 
-  .test-icon {
-    width: 40.2px;
-    height: 48px;
-    margin-right: 15px;
-  }
+    const rectImg = new Image();
+    rectImg.onload = () => {
+      rectImage.value = rectImg;
+      nextTick(() => {
+        nodeUpdateFilter(rectRef.value?.getNode());
+      });
+    };
+    rectImg.src = rectBlock;
 
-  .hover-img {
-    position: absolute;
-    bottom: 0;
-    left: 0;
-    width: 81px;
-    height: 98px;
-    z-index: 10;
-    transform: translateX(-40%);
-  }
+    const shineImg = new Image();
+    shineImg.onload = () => {
+      shineImage.value = shineImg;
+    };
+    shineImg.src = shine;
 
-  .pos-rect {
-    position: relative;
-    width: 241.5px;
-    height: 55.5px;
-    display: flex;
-    justify-content: center;
-    align-items: center;
-  }
+    const cirImg = new Image();
+    cirImg.onload = () => {
+      cirImage.value = cirImg;
+    };
+    cirImg.src = circle;
+
+    rectRef.value?.getNode().filters([Konva.Filters.RGBA]);
+    pointRef.value?.getNode().filters([Konva.Filters.RGBA]);
+  });
+</script>
 
-  .test-icon1 {
-    position: absolute;
-    top: 0;
-    left: 0;
-    width: 100%;
-    height: 100%;
-    object-fit: fill;
-  }
-</style>
+<style scoped></style>

+ 119 - 16
src/views/page-config/component/mapContainer/MapContainer.vue

@@ -1,29 +1,132 @@
 <template>
-  <div
-    :style="{
-      position: 'relative',
-      width: `${mapWidth}px`,
-      height: `${mapHeight}px`,
-      background: `url(${getRealImgUrl()})`,
-    }"
-  >
-    <Transformer v-for="item in showShops" :key="item.id" :shop="item" />
+  <div>
+    <v-stage
+      ref="stageRef"
+      :config="stageSize"
+      @mousedown="handleStageMouseDown"
+      @touchstart="handleStageMouseDown"
+    >
+      <v-layer ref="layerRef">
+        <v-image :config="bgConfig" />
+        <v-group
+          v-for="item in showShops"
+          :key="item.id"
+          :config="getGroupConfig(item)"
+          @dblclick="handleClick"
+        >
+          <LabelItem :shop="item" />
+        </v-group>
+        <v-transformer ref="transformerRef" :config="transformerConfig" />
+      </v-layer>
+    </v-stage>
   </div>
 </template>
 
 <script setup lang="ts">
+  import { computed, ref, watch, nextTick } from 'vue';
+  import LabelItem from './LabelItem.vue';
   import { storeToRefs } from 'pinia';
-  import Transformer from './Transformer.vue';
-  import useMapEditor from '../../stores/useMapEditor';
-  import { useGlobSetting } from '@/hooks/setting';
-  import urlJoin from 'url-join';
+  import useMapEditor, { MapWorkShopInfoItem } from '../../stores/useMapEditor';
+  import Konva from 'konva';
 
   const mapEditor = useMapEditor();
-  const { mapWidth, mapHeight, bgImg, showShops } = storeToRefs(mapEditor);
+  const { showShops, bgImage, activeShopId } = storeToRefs(mapEditor);
 
-  const globSetting = useGlobSetting();
+  const emit = defineEmits(['onOpen']);
 
-  const getRealImgUrl = () => urlJoin(globSetting.imgUrl!, bgImg.value);
+  const stageRef = ref<Konva.Stage>();
+  const layerRef = ref<Konva.Layer>();
+  const transformerRef = ref<Konva.Transformer>();
+
+  const stageSize = computed(() => {
+    return {
+      width: 1920,
+      height: 1080,
+    };
+  });
+
+  const bgConfig = computed(() => {
+    return {
+      width: 1920,
+      height: 1080,
+      image: bgImage.value,
+      name: 'bg',
+    };
+  });
+
+  const getGroupConfig = (shop: MapWorkShopInfoItem) => {
+    return {
+      x: shop.x,
+      y: shop.y,
+      scaleX: shop.scaleX,
+      scaleY: shop.scaleY,
+      id: shop.id + '',
+      draggable: true,
+      name: 'group',
+    };
+  };
+
+  const transformerConfig = {
+    keepRatio: true,
+    rotateEnabled: false,
+    enabledAnchors: ['top-left', 'top-right', 'bottom-left', 'bottom-right'],
+  };
+
+  const handleStageMouseDown = (e) => {
+    if (e.target.attrs.name === 'bg') {
+      activeShopId.value = -1;
+      updateTransformer();
+    }
+
+    if (e.target.parent.attrs.name === 'group') {
+      if (e.target.parent.id() === activeShopId.value) {
+        return;
+      }
+      activeShopId.value = e.target.parent.id();
+      updateTransformer();
+    }
+  };
+
+  const updateTransformer = () => {
+    const transformerNode = transformerRef.value!.getNode();
+    const layer = layerRef.value!.getNode().getLayer();
+    if (activeShopId.value! >= 0) {
+      const selectedNode = layer.findOne('#' + activeShopId.value);
+      (transformerNode as Konva.Transformer).nodes([selectedNode!]);
+    } else {
+      (transformerNode as Konva.Transformer).nodes([]);
+    }
+  };
+
+  const updateLayoutTransformer = () => {
+    const transformerNode = transformerRef.value!.getNode();
+    const layer = layerRef.value!.getNode().getLayer();
+    (transformerNode as Konva.Transformer).nodes([]);
+    const selectedNode = layer.findOne('#' + activeShopId.value);
+    if (selectedNode) {
+      nextTick(() => {
+        (transformerNode as Konva.Transformer)?.nodes([selectedNode!]);
+      });
+    }
+  };
+
+  const handleClick = () => {
+    emit('onOpen');
+  };
+
+  watch(activeShopId, () => {
+    nextTick(() => {
+      updateTransformer();
+    });
+  });
+
+  const getLayout = () => {
+    const json = stageRef.value?.getStage().toJSON();
+
+    return json;
+  };
+
+  defineExpose({ getLayout, updateLayoutTransformer });
 </script>
 
 <style scoped></style>

+ 168 - 0
src/views/page-config/component/mapContainer/labelConfig.ts

@@ -0,0 +1,168 @@
+import { LabelPositionEnum } from '../../stores/useMapEditor';
+
+export const getRGBANum = (color: string) => {
+  if (!color) return [0, 0, 0, 0];
+  const pattern = /\((\d+),\s*(\d+),\s*(\d+),\s*(\d+(\.\d+)?)\)$/;
+  const array = color.match(pattern);
+  return [
+    Number(array![1]) || 0,
+    Number(array![2]) || 0,
+    Number(array![3]) || 0,
+    Number(array![4]) || 0,
+  ];
+};
+
+export const getPointCurvConfig = (posType: LabelPositionEnum, image: any) => {
+  if (posType === LabelPositionEnum.LEFT) {
+    return {
+      x: 0,
+      y: 0,
+      width: 32,
+      height: 39,
+      image: image,
+    };
+  } else if (posType === LabelPositionEnum.RIGHT) {
+    return {
+      x: 183,
+      y: 0,
+      width: 32,
+      height: 39,
+      image: image,
+    };
+  } else {
+    return {
+      x: 65,
+      y: 35,
+      width: 32,
+      height: 39,
+      image: image,
+    };
+  }
+};
+
+export const getCirConfig = (posType: LabelPositionEnum, image: any) => {
+  if (posType === LabelPositionEnum.LEFT) {
+    return {
+      x: 0,
+      y: 0,
+      width: 32,
+      height: 32,
+      image: image,
+    };
+  } else if (posType === LabelPositionEnum.RIGHT) {
+    return {
+      x: 183,
+      y: 0,
+      width: 32,
+      height: 32,
+      image: image,
+    };
+  } else {
+    return {
+      x: 65,
+      y: 35,
+      width: 32,
+      height: 32,
+      image: image,
+    };
+  }
+};
+
+export const getRectCurConfig = (posType: LabelPositionEnum, image: any) => {
+  if (posType === LabelPositionEnum.LEFT) {
+    return {
+      x: 53,
+      y: 0,
+      width: 160,
+      height: 38,
+      image: image,
+    };
+  } else if (posType === LabelPositionEnum.RIGHT) {
+    return {
+      x: 0,
+      y: 0,
+      width: 160,
+      height: 38,
+      image: image,
+    };
+  } else {
+    return {
+      x: 0,
+      y: 0,
+      width: 160,
+      height: 38,
+      image: image,
+    };
+  }
+};
+
+export const getTextConfig = (shop: any) => {
+  if (shop.posType === LabelPositionEnum.LEFT) {
+    return {
+      x: 53,
+      y: 0,
+      text: shop.name,
+      fontSize: shop.fontSize,
+      fontFamily: 'TRENDS',
+      fill: shop.fontColor,
+      width: 160,
+      height: 32,
+      align: 'center',
+      verticalAlign: 'middle',
+    };
+  } else if (shop.posType === LabelPositionEnum.RIGHT) {
+    return {
+      x: 0,
+      y: 0,
+      text: shop.name,
+      fontSize: shop.fontSize,
+      fontFamily: 'TRENDS',
+      fill: shop.fontColor,
+      width: 160,
+      height: 32,
+      align: 'center',
+      verticalAlign: 'middle',
+    };
+  } else {
+    return {
+      x: 0,
+      y: 0,
+      text: shop.name,
+      fontSize: shop.fontSize,
+      fontFamily: 'TRENDS',
+      fill: shop.fontColor,
+      width: 160,
+      height: 32,
+      align: 'center',
+      verticalAlign: 'middle',
+    };
+  }
+};
+
+export const shineConfig = (posType: LabelPositionEnum, image: any) => {
+  if (posType === LabelPositionEnum.LEFT) {
+    return {
+      x: 77,
+      y: 0,
+      width: 107,
+      height: 38,
+      image: image,
+    };
+  } else if (posType === LabelPositionEnum.RIGHT) {
+    return {
+      x: 25,
+      y: 0,
+      width: 107,
+      height: 38,
+      image: image,
+    };
+  } else {
+    return {
+      x: 25,
+      y: 0,
+      width: 107,
+      height: 38,
+      image: image,
+    };
+  }
+};

+ 0 - 360
src/views/page-config/hooks/useMapEditor.ts

@@ -1,360 +0,0 @@
-import { computed, h, onBeforeUnmount, onMounted, ref, render } from 'vue';
-import Konva from 'konva';
-import cameraImg from '@/assets/camera/cameraImg.png';
-import OptBar from '../components/CameraOptBar.vue';
-import DefaultTip from '../components/DefaultTip.vue';
-import { ElMessage } from 'element-plus';
-import { useGlobSetting } from '@/hooks/setting';
-import urlJoin from 'url-join';
-import { WorkShopInfoItem } from '@/api/scene/scene';
-import LabelItem from '../component/LabelItem.vue';
-import { SvgIcon } from '@/components/SvgIcon';
-import html2canvas from 'html2canvas';
-import { Canvg } from 'canvg';
-
-interface MapEditorOption {
-  onShopStyle?: (shop: WorkShopInfoItem) => void;
-}
-
-export function useMapEditor(opt: MapEditorOption) {
-  let initWidth; // 默认宽度
-  let initHeight; // 默认高度
-  let stage: Konva.Stage | null = null;
-  let layer: Konva.Layer | null = null;
-  const addedShops = ref<number[]>([]); // 已添加车间列表
-  const activeGroup = ref<Konva.Group | null>(null); // transformer激活的车间
-  let optBlock: HTMLDivElement | null = null; // 鼠标右击弹出的选项组
-  let isTransform = false; // 是否在变换中
-  const activeShopId = computed(() => activeGroup.value?.id()); // 当前选中车间ID
-  const bgImgUrl = ref<string>('');
-
-  const globSetting = useGlobSetting();
-
-  /** 容器初始化 */
-  const initContainer = (opt: Konva.StageConfig) => {
-    initWidth = opt.width || 0;
-    initHeight = opt.height || 0;
-    stage = new Konva.Stage(opt);
-    stage.on('click tap', handleStageClick);
-    layer = new Konva.Layer();
-    stage.add(layer);
-  };
-
-  /** 更换背景图时根据图片大小重置容器宽高 */
-  const resizeContainer = (width, height) => {
-    const newWidth = width > initWidth ? width : initWidth;
-    const newHeight = height > initHeight ? height : initHeight;
-    stage?.width(newWidth);
-    stage?.height(newHeight);
-  };
-
-  /** 添加背景 */
-  const addBg = () => {
-    // const imgUrl = urlJoin(globSetting.imgUrl!, bgImgUrl.value);
-    const imgUrl = bgImgUrl.value;
-    const bgNode = layer?.find('#bgImg')[0] as Konva.Image;
-    const bgImg = new Image();
-    bgImg.onload = () => {
-      // 判断是否已有背景
-      if (!bgNode) {
-        const mapBg = new Konva.Image({
-          x: 0,
-          y: 0,
-          image: bgImg,
-          width: bgImg.width,
-          height: bgImg.height,
-          id: 'bgImg',
-        });
-        layer?.add(mapBg);
-        mapBg.moveToBottom();
-      } else {
-        bgNode.width(bgImg.width);
-        bgNode.height(bgImg.height);
-        bgNode.image(bgImg);
-      }
-      resizeContainer(bgImg.width, bgImg.height);
-      layer?.batchDraw();
-    };
-    bgImg.src = imgUrl;
-  };
-
-  /** 变更需要激活transform的车间 */
-  const attachTransformer = (group: Konva.Group): Konva.Transformer => {
-    activeGroup.value = group;
-    stage!.find('Transformer')[0]?.destroy(); // 清除现有transformer
-    const id = group.id();
-    const tr = new Konva.Transformer({
-      keepRatio: true,
-      rotateAnchorOffset: 30,
-      rotateEnabled: false,
-      enabledAnchors: ['top-left', 'top-right', 'bottom-left', 'bottom-right'],
-      id: 'tr_' + id,
-    });
-    tr.nodes([group]);
-    layer?.add(tr);
-    layer?.draw();
-
-    group.on('dragstart', handleDragStart);
-    group.on('dragstart', handleDragEnd);
-
-    return tr;
-  };
-
-  /** 添加车间 */
-  const addShop = (shop: WorkShopInfoItem) => {
-    const group = new Konva.Group({
-      x: 100,
-      y: 100,
-      id: shop.id + '',
-      draggable: true,
-      name: 'group',
-    });
-    // Konva.Image.fromURL(point, (imageNode) => {
-    //   group.add(imageNode),
-    //     imageNode.setAttrs({
-    //       fill: 'red',
-    //     });
-    // });
-
-    const testImg = new Konva.Image({
-      width: 27,
-      height: 32,
-      image: undefined,
-    });
-    group?.add(testImg);
-    const dv = document.createElement('div');
-    dv.setAttribute('id', 'labelItem');
-    dv.setAttribute('style', `position: absolute; left: 0px; top: 0px;`);
-    const label = h(SvgIcon, {
-      iconName: 'posPoint',
-      color: '#ef684d',
-      style: { width: '27px', height: '32px' },
-    });
-    render(label, dv);
-    const labelSvg = dv.querySelector('svg');
-    const labelSvgStr = new XMLSerializer().serializeToString(labelSvg!);
-    const canvas = document.createElement('canvas') as HTMLCanvasElement;
-    const ctx = canvas.getContext('2d');
-    Canvg.from(ctx!, labelSvgStr).then(() => {
-      console.log('0-0-0-0-0-');
-
-      const ahref = document.createElement('a');
-      ahref.href = canvas.toDataURL('image/png');
-      ahref.download = 'exportPng';
-      ahref.click();
-
-      const parentEl = document.getElementById('drawContainer') as HTMLDivElement;
-      parentEl.append(canvas);
-      const test = new Konva.Image({
-        x: 10,
-        y: 10,
-        width: 27,
-        height: 32,
-        image: canvas,
-        name: 'image',
-      });
-      layer?.add(test);
-      test.moveToTop();
-      layer?.draw();
-    });
-
-    //     const test = new konva.Image({
-    //       x: 10,
-    //       y: 10,
-    //       width: 27,
-    //       height: 32,
-    //       image: canvas,
-    //       name: 'image',
-    //     });
-    //     layer.add(test);
-    //     test.moveToTop();
-    //     layer.draw();
-    //   },
-    // });
-
-    // const labelImg = new Image();
-    // const svgUrl = new Blob([labelSvgStr], { type: 'image/svg+xml;charset=utf-8' });
-    // const DOMURL = self.URL || self.webkitURL || self;
-    // const labelUrl = DOMURL.createObjectURL(svgUrl);
-    // console.log(labelSvgStr);
-
-    // labelImg.onload = () => {
-    //   const labelPoint = new Konva.Image({
-    //     width: 27,
-    //     height: 32,
-    //     image: labelImg,
-    //     name: 'image',
-    //   });
-    //   layer?.add(labelPoint);
-    //   layer?.batchDraw();
-    // };
-    // labelImg.src = labelUrl;
-
-    // parentEl.append(dv);
-    // html2canvas(dv, { backgroundColor: 'transparent' }).then((canvas) => {
-    //   console.log(canvas);
-
-    //   testImg.image(canvas);
-    //   layer?.batchDraw();
-    // });
-
-    const shopName = new Konva.Text({
-      text: shop.name,
-      fontSize: 14,
-      fontFamily: 'TRENDS',
-      fill: '#FFFFFF',
-    });
-    group.add(shopName);
-    const w = shopName.width();
-    const th = shopName.height();
-    const markCir = new Konva.Circle({
-      x: th / 2 + 3,
-      y: th / 2 + 3,
-      radius: th / 2 + 3,
-      fill: 'blue',
-    });
-    group.add(markCir);
-    shopName.moveUp();
-    const markRect = new Konva.Rect({
-      x: th + 20,
-      y: 0,
-      width: w + 10,
-      height: th + 6,
-      fill: 'blue',
-    });
-    group.add(markRect);
-    shopName.x(th + 25);
-    shopName.y(5);
-    shopName.moveUp();
-
-    testImg.moveToTop();
-
-    layer?.add(group);
-    attachTransformer(group); // 添加的车间默认激活transformer
-
-    opt.onShopStyle && opt.onShopStyle(shop);
-    addedShops.value.push(shop.id);
-  };
-
-  /** 创建右键选项组 */
-  const createOptBlock = (node: Konva.Group, x: number, y: number) => {};
-
-  /** 删除右键选项组 */
-  const destoryOptBlock = () => {
-    optBlock?.remove();
-    optBlock = null;
-  };
-
-  /** 删除车间 */
-  const deleteShop = () => {
-    const index = addedShops.value.findIndex((item) => item === activeGroup.value?.id());
-    index >= 0 && addedShops.value.splice(index, 1);
-    activeGroup.value?.destroy();
-    stage!.find('Transformer')[0]?.destroy();
-    layer?.draw();
-  };
-
-  /** 鼠标悬浮事件 */
-  const handleMouseOver = (e) => {
-    // 禁用浏览器默认鼠标事件
-    document.oncontextmenu = () => {
-      return false;
-    };
-  };
-
-  /** 鼠标离开事件 */
-  const handleMouseLeave = () => {
-    // 恢复浏览器默认事件
-    document.oncontextmenu = () => {
-      return true;
-    };
-  };
-
-  /** 开始拖拽事件 */
-  const handleDragStart = () => {
-    isTransform = true;
-    destoryOptBlock();
-  };
-
-  /** 结束拖拽事件 */
-  const handleDragEnd = () => {
-    isTransform = false;
-  };
-
-  /** 全局点击事件 */
-  const handleStageClick = (e) => {
-    // 点击舞台取消现有激活的transformer
-    if (e.target === stage) {
-      stage!.find('Transformer')[0].destroy();
-      layer!.draw();
-      return;
-    }
-
-    // 判断点击对象是否为车间
-    if (!e.target.hasName('image')) {
-      return;
-    }
-    const parent = e.target.parent;
-    if (!parent.hasName('group')) {
-      return;
-    }
-    const group = e.target.parent;
-    attachTransformer(group);
-    // 判断是否为右键点击
-    if (e.evt.button === 2) {
-      createOptBlock(group, e.evt.offsetX + 20, e.evt.offsetY);
-    }
-  };
-
-  /** 键盘点击事件 */
-  const handleKeyDown = (e) => {
-    // 删除键
-    if (e.keyCode === 46 || e.code === 'Delete') {
-      deleteShop();
-    }
-  };
-
-  // 基础监听事件绑定
-  const bindBaseEvt = (node: Konva.Node) => {
-    // node.on('transform', handleDragStart);
-    // node.on('transformend', handleDragEnd);
-    node.on('mouseover', handleMouseOver);
-    node.on('mouseleave', handleMouseLeave);
-  };
-
-  /** 输出布局json */
-  const toJson = () => {
-    const json = stage!.toJSON();
-    const layout = {
-      bgImg: bgImgUrl.value,
-      shopLis: [],
-    };
-
-    return JSON.stringify(layout);
-  };
-
-  /** 导入布局json */
-  const createMap = (json) => {};
-
-  onMounted(() => {
-    window.addEventListener('keydown', handleKeyDown);
-  });
-
-  onBeforeUnmount(() => {
-    window.removeEventListener('keydown', handleKeyDown);
-  });
-
-  return {
-    activeShopId,
-    addedShops,
-    bgImgUrl,
-    initContainer,
-    addBg,
-    addShop,
-    destoryOptBlock,
-    toJson,
-    createMap,
-  };
-}
-
-export default useMapEditor;

+ 0 - 272
src/views/page-config/hooks/useMapEditor1.ts

@@ -1,272 +0,0 @@
-import { computed, h, onBeforeUnmount, onMounted, ref, render } from 'vue';
-import Konva from 'konva';
-import cameraImg from '@/assets/camera/cameraImg.png';
-import OptBar from '../components/CameraOptBar.vue';
-import DefaultTip from '../components/DefaultTip.vue';
-import { ElMessage } from 'element-plus';
-import { useGlobSetting } from '@/hooks/setting';
-import urlJoin from 'url-join';
-import { WorkShopInfoItem } from '@/api/scene/scene';
-import point from '@/assets/icons/posPoint.svg';
-
-interface MapEditorOption {
-  onShopStyle?: (shop: WorkShopInfoItem) => void;
-}
-
-export function useMapEditor(opt: MapEditorOption) {
-  let initWidth; // 默认宽度
-  let initHeight; // 默认高度
-  let stage: Konva.Stage | null = null;
-  let layer: Konva.Layer | null = null;
-  const addedShops = ref<number[]>([]); // 已添加车间列表
-  const activeGroup = ref<Konva.Group | null>(null); // transformer激活的车间
-  let optBlock: HTMLDivElement | null = null; // 鼠标右击弹出的选项组
-  let isTransform = false; // 是否在变换中
-  const activeShopId = computed(() => activeGroup.value?.id()); // 当前选中车间ID
-  const bgImgUrl = ref<string>('');
-
-  const globSetting = useGlobSetting();
-
-  /** 容器初始化 */
-  const initContainer = (opt: Konva.StageConfig) => {
-    initWidth = opt.width || 0;
-    initHeight = opt.height || 0;
-    stage = new Konva.Stage(opt);
-    stage.on('click tap', handleStageClick);
-    layer = new Konva.Layer();
-    stage.add(layer);
-  };
-
-  /** 更换背景图时根据图片大小重置容器宽高 */
-  const resizeContainer = (width, height) => {
-    const newWidth = width > initWidth ? width : initWidth;
-    const newHeight = height > initHeight ? height : initHeight;
-    stage?.width(newWidth);
-    stage?.height(newHeight);
-  };
-
-  /** 添加背景 */
-  const addBg = () => {
-    // const imgUrl = urlJoin(globSetting.imgUrl!, bgImgUrl.value);
-    const imgUrl = bgImgUrl.value;
-    const bgNode = layer?.find('#bgImg')[0] as Konva.Image;
-    const bgImg = new Image();
-    bgImg.onload = () => {
-      // 判断是否已有背景
-      if (!bgNode) {
-        const mapBg = new Konva.Image({
-          x: 0,
-          y: 0,
-          image: bgImg,
-          width: bgImg.width,
-          height: bgImg.height,
-          id: 'bgImg',
-        });
-        layer?.add(mapBg);
-        mapBg.moveToBottom();
-      } else {
-        bgNode.width(bgImg.width);
-        bgNode.height(bgImg.height);
-        bgNode.image(bgImg);
-      }
-      resizeContainer(bgImg.width, bgImg.height);
-      layer?.batchDraw();
-    };
-    bgImg.src = imgUrl;
-  };
-
-  /** 变更需要激活transform的车间 */
-  const attachTransformer = (group: Konva.Group): Konva.Transformer => {
-    activeGroup.value = group;
-    stage!.find('Transformer')[0]?.destroy(); // 清除现有transformer
-    const id = group.id();
-    const tr = new Konva.Transformer({
-      keepRatio: true,
-      rotateAnchorOffset: 30,
-      rotateEnabled: false,
-      enabledAnchors: ['top-left', 'top-right', 'bottom-left', 'bottom-right'],
-      id: 'tr_' + id,
-    });
-    tr.nodes([group]);
-    layer?.add(tr);
-    layer?.draw();
-
-    group.on('dragstart', handleDragStart);
-    group.on('dragstart', handleDragEnd);
-
-    return tr;
-  };
-
-  /** 添加车间 */
-  const addShop = (shop: WorkShopInfoItem) => {
-    const group = new Konva.Group({
-      x: 100,
-      y: 100,
-      id: shop.id + '',
-      draggable: true,
-      name: 'group',
-    });
-    // Konva.Image.fromURL(point, (imageNode) => {
-    //   group.add(imageNode),
-    //     imageNode.setAttrs({
-    //       fill: 'red',
-    //     });
-    // });
-
-    const shopName = new Konva.Text({
-      text: shop.name,
-      fontSize: 14,
-      fontFamily: 'TRENDS',
-      fill: '#FFFFFF',
-    });
-    group.add(shopName);
-    const w = shopName.width();
-    const h = shopName.height();
-    const markCir = new Konva.Circle({
-      x: h / 2 + 3,
-      y: h / 2 + 3,
-      radius: h / 2 + 3,
-      fill: 'blue',
-    });
-    group.add(markCir);
-    shopName.moveUp();
-    const markRect = new Konva.Rect({
-      x: h + 20,
-      y: 0,
-      width: w + 10,
-      height: h + 6,
-      fill: 'blue',
-    });
-    group.add(markRect);
-    shopName.x(h + 25);
-    shopName.y(5);
-    shopName.moveUp();
-    layer?.add(group);
-    attachTransformer(group); // 添加的车间默认激活transformer
-
-    opt.onShopStyle && opt.onShopStyle(shop);
-    addedShops.value.push(shop.id);
-  };
-
-  /** 创建右键选项组 */
-  const createOptBlock = (node: Konva.Group, x: number, y: number) => {};
-
-  /** 删除右键选项组 */
-  const destoryOptBlock = () => {
-    optBlock?.remove();
-    optBlock = null;
-  };
-
-  /** 删除车间 */
-  const deleteShop = () => {
-    const index = addedShops.value.findIndex((item) => item === activeGroup.value?.id());
-    index >= 0 && addedShops.value.splice(index, 1);
-    activeGroup.value?.destroy();
-    stage!.find('Transformer')[0]?.destroy();
-    layer?.draw();
-  };
-
-  /** 鼠标悬浮事件 */
-  const handleMouseOver = (e) => {
-    // 禁用浏览器默认鼠标事件
-    document.oncontextmenu = () => {
-      return false;
-    };
-  };
-
-  /** 鼠标离开事件 */
-  const handleMouseLeave = () => {
-    // 恢复浏览器默认事件
-    document.oncontextmenu = () => {
-      return true;
-    };
-  };
-
-  /** 开始拖拽事件 */
-  const handleDragStart = () => {
-    isTransform = true;
-    destoryOptBlock();
-  };
-
-  /** 结束拖拽事件 */
-  const handleDragEnd = () => {
-    isTransform = false;
-  };
-
-  /** 全局点击事件 */
-  const handleStageClick = (e) => {
-    // 点击舞台取消现有激活的transformer
-    if (e.target === stage) {
-      stage!.find('Transformer')[0].destroy();
-      layer!.draw();
-      return;
-    }
-
-    // 判断点击对象是否为车间
-    if (!e.target.hasName('image')) {
-      return;
-    }
-    const parent = e.target.parent;
-    if (!parent.hasName('group')) {
-      return;
-    }
-    const group = e.target.parent;
-    attachTransformer(group);
-    // 判断是否为右键点击
-    if (e.evt.button === 2) {
-      createOptBlock(group, e.evt.offsetX + 20, e.evt.offsetY);
-    }
-  };
-
-  /** 键盘点击事件 */
-  const handleKeyDown = (e) => {
-    // 删除键
-    if (e.keyCode === 46 || e.code === 'Delete') {
-      deleteShop();
-    }
-  };
-
-  // 基础监听事件绑定
-  const bindBaseEvt = (node: Konva.Node) => {
-    // node.on('transform', handleDragStart);
-    // node.on('transformend', handleDragEnd);
-    node.on('mouseover', handleMouseOver);
-    node.on('mouseleave', handleMouseLeave);
-  };
-
-  /** 输出布局json */
-  const toJson = () => {
-    const json = stage!.toJSON();
-    const layout = {
-      bgImg: bgImgUrl.value,
-      shopLis: [],
-    };
-
-    return JSON.stringify(layout);
-  };
-
-  /** 导入布局json */
-  const createMap = (json) => {};
-
-  onMounted(() => {
-    window.addEventListener('keydown', handleKeyDown);
-  });
-
-  onBeforeUnmount(() => {
-    window.removeEventListener('keydown', handleKeyDown);
-  });
-
-  return {
-    activeShopId,
-    addedShops,
-    bgImgUrl,
-    initContainer,
-    addBg,
-    addShop,
-    destoryOptBlock,
-    toJson,
-    createMap,
-  };
-}
-
-export default useMapEditor;

+ 0 - 534
src/views/page-config/shops.json

@@ -1,534 +0,0 @@
-[
-  {
-    "id": 16,
-    "companyId": 6,
-    "sceneLabelId": 2,
-    "name": "硝盐槽",
-    "code": "nitrate tank",
-    "remark": "",
-    "status": 0,
-    "createdAt": "2023-12-11 12:04:17",
-    "updatedAt": "2023-12-11 14:00:40",
-    "isDeleted": 0,
-    "serial": 0,
-    "labelName": "安全管控",
-    "workshopModule": {
-      "id": 2,
-      "name": "厂房",
-      "code": "2",
-      "remark": "",
-      "status": 0,
-      "createdAt": "2023-12-22 11:44:06",
-      "updatedAt": "2023-12-22 11:44:06",
-      "isDeleted": 0
-    },
-    "children": []
-  },
-  {
-    "id": 17,
-    "companyId": 6,
-    "sceneLabelId": 2,
-    "name": "化学品库房",
-    "code": "cw",
-    "remark": "",
-    "status": 0,
-    "createdAt": "2023-12-11 12:04:42",
-    "updatedAt": "2023-12-11 12:04:42",
-    "isDeleted": 0,
-    "serial": 0,
-    "labelName": "安全管控",
-    "workshopModule": {
-      "id": 2,
-      "name": "厂房",
-      "code": "2",
-      "remark": "",
-      "status": 0,
-      "createdAt": "2023-12-22 11:44:06",
-      "updatedAt": "2023-12-22 11:44:06",
-      "isDeleted": 0
-    },
-    "children": []
-  },
-  {
-    "id": 18,
-    "companyId": 3,
-    "sceneLabelId": 2,
-    "name": "燃油实验室",
-    "code": "sfy-FL",
-    "remark": "",
-    "status": 0,
-    "createdAt": "2023-12-11 13:41:37",
-    "updatedAt": "2023-12-11 13:41:37",
-    "isDeleted": 0,
-    "serial": 0,
-    "labelName": "安全管控",
-    "workshopModule": {
-      "id": 1,
-      "name": "危险点",
-      "code": "1",
-      "remark": "",
-      "status": 0,
-      "createdAt": "2023-12-22 11:43:54",
-      "updatedAt": "2023-12-22 11:43:54",
-      "isDeleted": 0
-    },
-    "children": []
-  },
-  {
-    "id": 19,
-    "companyId": 5,
-    "sceneLabelId": 2,
-    "name": "配电站",
-    "code": "kf-substation",
-    "remark": "",
-    "status": 0,
-    "createdAt": "2023-12-26 11:09:22",
-    "updatedAt": "2023-12-26 11:09:22",
-    "isDeleted": 0,
-    "serial": 0,
-    "labelName": "安全管控",
-    "workshopModule": {
-      "id": 1,
-      "name": "危险点",
-      "code": "1",
-      "remark": "",
-      "status": 0,
-      "createdAt": "2023-12-22 11:43:54",
-      "updatedAt": "2023-12-22 11:43:54",
-      "isDeleted": 0
-    },
-    "children": []
-  },
-  {
-    "id": 20,
-    "companyId": 5,
-    "sceneLabelId": 2,
-    "name": "气瓶间",
-    "code": "kf-gcr",
-    "remark": "",
-    "status": 0,
-    "createdAt": "2023-12-26 11:09:59",
-    "updatedAt": "2023-12-26 11:09:59",
-    "isDeleted": 0,
-    "serial": 0,
-    "labelName": "安全管控",
-    "workshopModule": {
-      "id": 2,
-      "name": "厂房",
-      "code": "2",
-      "remark": "",
-      "status": 0,
-      "createdAt": "2023-12-22 11:44:06",
-      "updatedAt": "2023-12-22 11:44:06",
-      "isDeleted": 0
-    },
-    "children": []
-  },
-  {
-    "id": 21,
-    "companyId": 5,
-    "sceneLabelId": 2,
-    "name": "柴油发电机",
-    "code": "kf-dg",
-    "remark": "",
-    "status": 0,
-    "createdAt": "2023-12-26 11:10:19",
-    "updatedAt": "2023-12-26 11:10:19",
-    "isDeleted": 0,
-    "serial": 0,
-    "labelName": "安全管控",
-    "workshopModule": {
-      "id": 2,
-      "name": "厂房",
-      "code": "2",
-      "remark": "",
-      "status": 0,
-      "createdAt": "2023-12-22 11:44:06",
-      "updatedAt": "2023-12-22 11:44:06",
-      "isDeleted": 0
-    },
-    "children": []
-  },
-  {
-    "id": 22,
-    "companyId": 5,
-    "sceneLabelId": 2,
-    "name": "运行支持指挥中心",
-    "code": "kf-qrh",
-    "remark": "",
-    "status": 0,
-    "createdAt": "2023-12-26 11:10:40",
-    "updatedAt": "2024-01-16 15:01:28",
-    "isDeleted": 0,
-    "serial": 0,
-    "labelName": "安全管控",
-    "workshopModule": {
-      "id": 2,
-      "name": "厂房",
-      "code": "2",
-      "remark": "",
-      "status": 0,
-      "createdAt": "2023-12-22 11:44:06",
-      "updatedAt": "2023-12-22 11:44:06",
-      "isDeleted": 0
-    },
-    "children": []
-  },
-  {
-    "id": 23,
-    "companyId": 5,
-    "sceneLabelId": 2,
-    "name": "C919飞行模拟机",
-    "code": "kf-sl",
-    "remark": "",
-    "status": 0,
-    "createdAt": "2023-12-26 11:11:00",
-    "updatedAt": "2024-01-17 08:51:47",
-    "isDeleted": 0,
-    "serial": 0,
-    "labelName": "安全管控",
-    "workshopModule": {
-      "id": 2,
-      "name": "厂房",
-      "code": "2",
-      "remark": "",
-      "status": 0,
-      "createdAt": "2023-12-22 11:44:06",
-      "updatedAt": "2023-12-22 11:44:06",
-      "isDeleted": 0
-    },
-    "children": []
-  },
-  {
-    "id": 1,
-    "companyId": 2,
-    "sceneLabelId": 1,
-    "name": "ARJ21部装车间",
-    "code": "C12",
-    "remark": "",
-    "status": 0,
-    "createdAt": "2023-10-13 09:48:58",
-    "updatedAt": "2024-01-16 15:00:46",
-    "isDeleted": 0,
-    "serial": 0,
-    "labelName": "生产安全",
-    "workshopModule": {
-      "id": 2,
-      "name": "厂房",
-      "code": "2",
-      "remark": "",
-      "status": 0,
-      "createdAt": "2023-12-22 11:44:06",
-      "updatedAt": "2023-12-22 11:44:06",
-      "isDeleted": 0
-    },
-    "children": [
-      {
-        "id": 2,
-        "workshopId": 1,
-        "name": "西侧200室内气密试验区",
-        "code": "C12-W200test",
-        "remark": "",
-        "principal": "",
-        "status": 0,
-        "createdAt": "2023-12-27 14:07:15",
-        "updatedAt": "2024-01-05 09:05:52",
-        "isDeleted": 0,
-        "serial": 0
-      },
-      {
-        "id": 1,
-        "workshopId": 1,
-        "name": "东侧200室内气密试验区",
-        "code": "C12-E200test",
-        "remark": "",
-        "principal": "",
-        "status": 0,
-        "createdAt": "2023-12-27 14:06:46",
-        "updatedAt": "2024-01-05 09:05:52",
-        "isDeleted": 0,
-        "serial": 1
-      }
-    ]
-  },
-  {
-    "id": 3,
-    "companyId": 2,
-    "sceneLabelId": 1,
-    "name": "C919部装车间",
-    "code": "C02",
-    "remark": "",
-    "status": 0,
-    "createdAt": "2023-10-13 09:50:31",
-    "updatedAt": "2024-01-16 15:00:52",
-    "isDeleted": 0,
-    "serial": 0,
-    "labelName": "生产安全",
-    "workshopModule": {
-      "id": 2,
-      "name": "厂房",
-      "code": "2",
-      "remark": "",
-      "status": 0,
-      "createdAt": "2023-12-22 11:44:06",
-      "updatedAt": "2023-12-22 11:44:06",
-      "isDeleted": 0
-    },
-    "children": []
-  },
-  {
-    "id": 6,
-    "companyId": 2,
-    "sceneLabelId": 1,
-    "name": "胶接车间",
-    "code": "B16",
-    "remark": "",
-    "status": 0,
-    "createdAt": "2023-10-13 09:51:42",
-    "updatedAt": "2024-01-16 15:00:57",
-    "isDeleted": 0,
-    "serial": 0,
-    "labelName": "生产安全",
-    "workshopModule": {
-      "id": 2,
-      "name": "厂房",
-      "code": "2",
-      "remark": "",
-      "status": 0,
-      "createdAt": "2023-12-22 11:44:06",
-      "updatedAt": "2023-12-22 11:44:06",
-      "isDeleted": 0
-    },
-    "children": []
-  },
-  {
-    "id": 7,
-    "companyId": 2,
-    "sceneLabelId": 1,
-    "name": "复材车间",
-    "code": "B01",
-    "remark": "",
-    "status": 0,
-    "createdAt": "2023-10-13 09:52:02",
-    "updatedAt": "2024-01-16 15:00:59",
-    "isDeleted": 0,
-    "serial": 0,
-    "labelName": "生产安全",
-    "workshopModule": null,
-    "children": []
-  },
-  {
-    "id": 8,
-    "companyId": 2,
-    "sceneLabelId": 1,
-    "name": "工装中心",
-    "code": "B04",
-    "remark": "",
-    "status": 0,
-    "createdAt": "2023-10-13 09:53:01",
-    "updatedAt": "2023-10-13 09:53:01",
-    "isDeleted": 0,
-    "serial": 0,
-    "labelName": "生产安全",
-    "workshopModule": null,
-    "children": []
-  },
-  {
-    "id": 9,
-    "companyId": 2,
-    "sceneLabelId": 2,
-    "name": "B16热压罐",
-    "code": "B16autoclave",
-    "remark": "",
-    "status": 0,
-    "createdAt": "2023-10-13 10:22:20",
-    "updatedAt": "2023-10-19 19:12:27",
-    "isDeleted": 0,
-    "serial": 0,
-    "labelName": "安全管控",
-    "workshopModule": null,
-    "children": []
-  },
-  {
-    "id": 10,
-    "companyId": 2,
-    "sceneLabelId": 2,
-    "name": "B01热压罐",
-    "code": "B01autoclave",
-    "remark": "",
-    "status": 0,
-    "createdAt": "2023-10-13 10:22:39",
-    "updatedAt": "2023-10-13 10:22:39",
-    "isDeleted": 0,
-    "serial": 0,
-    "labelName": "安全管控",
-    "workshopModule": null,
-    "children": []
-  },
-  {
-    "id": 11,
-    "companyId": 2,
-    "sceneLabelId": 2,
-    "name": "110KV变电站",
-    "code": "110KVsubstation",
-    "remark": "",
-    "status": 0,
-    "createdAt": "2023-10-13 10:23:02",
-    "updatedAt": "2023-10-13 10:23:02",
-    "isDeleted": 0,
-    "serial": 0,
-    "labelName": "安全管控",
-    "workshopModule": null,
-    "children": []
-  },
-  {
-    "id": 12,
-    "companyId": 2,
-    "sceneLabelId": 2,
-    "name": "2011锅炉房",
-    "code": "2011boiler",
-    "remark": "",
-    "status": 0,
-    "createdAt": "2023-10-13 10:23:20",
-    "updatedAt": "2023-10-13 10:23:20",
-    "isDeleted": 0,
-    "serial": 0,
-    "labelName": "安全管控",
-    "workshopModule": {
-      "id": 1,
-      "name": "危险点",
-      "code": "1",
-      "remark": "",
-      "status": 0,
-      "createdAt": "2023-12-22 11:43:54",
-      "updatedAt": "2023-12-22 11:43:54",
-      "isDeleted": 0
-    },
-    "children": []
-  },
-  {
-    "id": 13,
-    "companyId": 2,
-    "sceneLabelId": 2,
-    "name": "2001a锅炉房",
-    "code": "2001aboiler",
-    "remark": "",
-    "status": 0,
-    "createdAt": "2023-10-13 10:23:36",
-    "updatedAt": "2023-10-13 10:23:36",
-    "isDeleted": 0,
-    "serial": 0,
-    "labelName": "安全管控",
-    "workshopModule": {
-      "id": 1,
-      "name": "危险点",
-      "code": "1",
-      "remark": "",
-      "status": 0,
-      "createdAt": "2023-12-22 11:43:54",
-      "updatedAt": "2023-12-22 11:43:54",
-      "isDeleted": 0
-    },
-    "children": []
-  },
-  {
-    "id": 15,
-    "companyId": 2,
-    "sceneLabelId": 2,
-    "name": "增材实验室",
-    "code": "sf-additive_lab",
-    "remark": "",
-    "status": 0,
-    "createdAt": "2023-12-11 13:40:33",
-    "updatedAt": "2023-12-11 13:40:33",
-    "isDeleted": 0,
-    "serial": 0,
-    "labelName": "安全管控",
-    "workshopModule": {
-      "id": 1,
-      "name": "危险点",
-      "code": "1",
-      "remark": "",
-      "status": 0,
-      "createdAt": "2023-12-22 11:43:54",
-      "updatedAt": "2023-12-22 11:43:54",
-      "isDeleted": 0
-    },
-    "children": []
-  },
-  {
-    "id": 2,
-    "companyId": 2,
-    "sceneLabelId": 1,
-    "name": "ARJ21总装车间",
-    "code": "C11",
-    "remark": "",
-    "status": 0,
-    "createdAt": "2023-10-13 09:49:31",
-    "updatedAt": "2024-01-16 15:00:48",
-    "isDeleted": 0,
-    "serial": 1,
-    "labelName": "生产安全",
-    "workshopModule": {
-      "id": 2,
-      "name": "厂房",
-      "code": "2",
-      "remark": "",
-      "status": 0,
-      "createdAt": "2023-12-22 11:44:06",
-      "updatedAt": "2023-12-22 11:44:06",
-      "isDeleted": 0
-    },
-    "children": []
-  },
-  {
-    "id": 4,
-    "companyId": 2,
-    "sceneLabelId": 1,
-    "name": "C919总装车间",
-    "code": "C01",
-    "remark": "",
-    "status": 0,
-    "createdAt": "2023-10-13 09:50:53",
-    "updatedAt": "2024-01-16 15:00:54",
-    "isDeleted": 0,
-    "serial": 1,
-    "labelName": "生产安全",
-    "workshopModule": {
-      "id": 2,
-      "name": "厂房",
-      "code": "2",
-      "remark": "",
-      "status": 0,
-      "createdAt": "2023-12-22 11:44:06",
-      "updatedAt": "2023-12-22 11:44:06",
-      "isDeleted": 0
-    },
-    "children": []
-  },
-  {
-    "id": 5,
-    "companyId": 2,
-    "sceneLabelId": 1,
-    "name": "维修交付中心",
-    "code": "repair",
-    "remark": "",
-    "status": 0,
-    "createdAt": "2023-10-13 09:51:22",
-    "updatedAt": "2024-01-16 15:00:55",
-    "isDeleted": 0,
-    "serial": 2,
-    "labelName": "生产安全",
-    "workshopModule": {
-      "id": 2,
-      "name": "厂房",
-      "code": "2",
-      "remark": "",
-      "status": 0,
-      "createdAt": "2023-12-22 11:44:06",
-      "updatedAt": "2023-12-22 11:44:06",
-      "isDeleted": 0
-    },
-    "children": []
-  }
-]

+ 52 - 27
src/views/page-config/stores/useMapEditor.ts

@@ -3,7 +3,10 @@ import { defineStore } from 'pinia';
 import { WorkShopInfoItem } from '@/api/scene/scene';
 import { cloneDeep } from 'lodash-es';
 import { useGlobSetting } from '@/hooks/setting';
+import safeParse from '@/utils/safeParse';
 import urlJoin from 'url-join';
+import { resolve } from 'path';
+// import emptyImg from '@/assets/images/table/table-empty.png';
 
 export enum LabelPositionEnum {
   LEFT = 'left',
@@ -14,7 +17,9 @@ export enum LabelPositionEnum {
 export type EditStyle = {
   x: number;
   y: number;
-  scale: number;
+  // scale: number;
+  scaleX: number;
+  scaleY: number;
   thumbnail?: string;
   bgColor: string;
   fontSize: number;
@@ -32,38 +37,54 @@ export const useMapEditor = defineStore('home-map-ediotr', () => {
   const mapHeight = ref(0);
   const addedShops = ref<MapWorkShopInfoItem[]>([]);
   const showShops = ref<MapWorkShopInfoItem[]>([]);
-  const activeShop = ref<MapWorkShopInfoItem>({} as MapWorkShopInfoItem);
+  const activeShopId = ref<number>();
+
+  /** konva elements refs */
+  const bgImage = ref<HTMLImageElement>(new Image());
+
+  const clearBg = () => {
+    bgImage.value.src = '';
+  };
 
   const addBg = () => {
-    const imgUrl = urlJoin(globSetting.imgUrl!, bgImg.value);
-    console.log(imgUrl);
+    return new Promise((resolve) => {
+      const imgUrl = urlJoin(globSetting.imgUrl!, bgImg.value);
 
-    const img = new Image();
-    img.onload = () => {
-      mapWidth.value = img.width;
-      mapHeight.value = img.height;
-    };
-    img.src = imgUrl;
+      const tempImg = new Image();
+      tempImg.onload = () => {
+        mapWidth.value = tempImg.width;
+        mapHeight.value = tempImg.height;
+        bgImage.value = tempImg;
+      };
+      tempImg.src = imgUrl;
+      resolve(null);
+    });
   };
 
   const addShop = (shop: MapWorkShopInfoItem) => {
-    activeShop.value = shop;
+    activeShopId.value = shop.id;
     addedShops.value.push(cloneDeep(shop));
     showShops.value.push(cloneDeep(shop));
   };
 
-  const toJson = () => {
+  const calcLayout = (json: string) => {
+    const mapJson = safeParse(json);
+    const mapData = mapJson.children[0].children.filter((item) => item.className === 'Group');
+
+    const shopListAdded = addedShops.value.map((item, index) => {
+      item.x = mapData[index].attrs.x;
+      item.y = mapData[index].attrs.y;
+      item.scaleX = mapData[index].attrs.scaleX || 1;
+      item.scaleY = mapData[index].attrs.scaleY || 1;
+      return item;
+    });
     const layout = {
       bgInfo: {
         width: mapWidth.value,
         height: mapHeight.value,
         img: bgImg.value,
       },
-      shopList: addedShops.value.map((shop) => {
-        const temp = cloneDeep(shop) as any;
-        delete temp.children;
-        return temp;
-      }),
+      shopList: shopListAdded,
     };
 
     return JSON.stringify(layout);
@@ -71,16 +92,18 @@ export const useMapEditor = defineStore('home-map-ediotr', () => {
 
   const createMap = (layout) => {
     bgImg.value = layout.bgInfo.img;
-    mapWidth.value = layout.bgInfo.width;
-    mapHeight.value = layout.bgInfo.height;
-    addedShops.value = cloneDeep(layout.shopList);
-    showShops.value = cloneDeep(layout.shopList);
+    addBg().then(() => {
+      mapWidth.value = layout.bgInfo.width;
+      mapHeight.value = layout.bgInfo.height;
+      addedShops.value = cloneDeep(layout.shopList);
+      showShops.value = cloneDeep(layout.shopList);
+    });
   };
 
   const deleteShop = () => {
-    addedShops.value = addedShops.value.filter((item) => item.id !== activeShop.value.id);
-    showShops.value = showShops.value.filter((item) => item.id !== activeShop.value.id);
-    activeShop.value = {} as MapWorkShopInfoItem;
+    addedShops.value = addedShops.value.filter((item) => item.id !== Number(activeShopId.value));
+    showShops.value = showShops.value.filter((item) => item.id !== Number(activeShopId.value));
+    activeShopId.value = undefined;
   };
 
   const resetMap = () => {
@@ -89,7 +112,8 @@ export const useMapEditor = defineStore('home-map-ediotr', () => {
     mapHeight.value = 0;
     addedShops.value = [];
     showShops.value = [];
-    activeShop.value = {} as MapWorkShopInfoItem;
+    activeShopId.value = undefined;
+    clearBg();
   };
 
   return {
@@ -98,10 +122,11 @@ export const useMapEditor = defineStore('home-map-ediotr', () => {
     mapHeight,
     addedShops,
     showShops,
-    activeShop,
+    activeShopId,
+    bgImage,
     addShop,
     addBg,
-    toJson,
+    calcLayout,
     createMap,
     deleteShop,
     resetMap,

+ 0 - 692
src/views/page-config/tree.json

@@ -1,692 +0,0 @@
-[
-  {
-    "id": 1,
-    "parentId": 0,
-    "name": "商飞公司",
-    "code": "COMAC",
-    "remark": "",
-    "status": 0,
-    "createdAt": "2023-10-10 19:53:58",
-    "updatedAt": "2024-01-02 15:25:01",
-    "serial": 0,
-    "isDeleted": 0,
-    "children": [],
-    "labelList": [
-      {
-        "id": 2,
-        "name": "安全管控",
-        "code": "2",
-        "remark": "",
-        "status": 0,
-        "createdAt": "2023-12-27 13:49:28",
-        "updatedAt": "2024-01-16 15:00:28",
-        "isDeleted": 0
-      }
-    ],
-    "moduleList": [
-      {
-        "id": 1,
-        "name": "生产安全模板",
-        "code": "12",
-        "remark": "32437857",
-        "status": 0,
-        "createdAt": "2023-12-22 11:43:05",
-        "updatedAt": "2024-01-04 14:37:40",
-        "isDeleted": 0
-      }
-    ]
-  },
-  {
-    "id": 6,
-    "parentId": 1,
-    "name": "上飞公司大场基地",
-    "code": "shangfeidachang",
-    "remark": "",
-    "status": 0,
-    "createdAt": "2023-12-11 09:07:53",
-    "updatedAt": "2023-12-11 09:07:53",
-    "serial": 0,
-    "isDeleted": 0,
-    "children": [
-      {
-        "id": 16,
-        "companyId": 6,
-        "sceneLabelId": 2,
-        "name": "硝盐槽",
-        "code": "nitrate tank",
-        "remark": "",
-        "status": 0,
-        "createdAt": "2023-12-11 12:04:17",
-        "updatedAt": "2023-12-11 14:00:40",
-        "isDeleted": 0,
-        "serial": 0,
-        "labelName": "安全管控",
-        "workshopModule": {
-          "id": 2,
-          "name": "厂房",
-          "code": "2",
-          "remark": "",
-          "status": 0,
-          "createdAt": "2023-12-22 11:44:06",
-          "updatedAt": "2023-12-22 11:44:06",
-          "isDeleted": 0
-        },
-        "children": []
-      },
-      {
-        "id": 17,
-        "companyId": 6,
-        "sceneLabelId": 2,
-        "name": "化学品库房",
-        "code": "cw",
-        "remark": "",
-        "status": 0,
-        "createdAt": "2023-12-11 12:04:42",
-        "updatedAt": "2023-12-11 12:04:42",
-        "isDeleted": 0,
-        "serial": 0,
-        "labelName": "安全管控",
-        "workshopModule": {
-          "id": 2,
-          "name": "厂房",
-          "code": "2",
-          "remark": "",
-          "status": 0,
-          "createdAt": "2023-12-22 11:44:06",
-          "updatedAt": "2023-12-22 11:44:06",
-          "isDeleted": 0
-        },
-        "children": []
-      }
-    ],
-    "labelList": [],
-    "moduleList": []
-  },
-  {
-    "id": 3,
-    "parentId": 1,
-    "name": "上飞院",
-    "code": "shangfeiyuan",
-    "remark": "",
-    "status": 0,
-    "createdAt": "2023-10-13 09:42:50",
-    "updatedAt": "2024-01-02 15:25:01",
-    "serial": 1,
-    "isDeleted": 0,
-    "children": [
-      {
-        "id": 18,
-        "companyId": 3,
-        "sceneLabelId": 2,
-        "name": "燃油实验室",
-        "code": "sfy-FL",
-        "remark": "",
-        "status": 0,
-        "createdAt": "2023-12-11 13:41:37",
-        "updatedAt": "2023-12-11 13:41:37",
-        "isDeleted": 0,
-        "serial": 0,
-        "labelName": "安全管控",
-        "workshopModule": {
-          "id": 1,
-          "name": "危险点",
-          "code": "1",
-          "remark": "",
-          "status": 0,
-          "createdAt": "2023-12-22 11:43:54",
-          "updatedAt": "2023-12-22 11:43:54",
-          "isDeleted": 0
-        },
-        "children": []
-      }
-    ],
-    "labelList": [],
-    "moduleList": []
-  },
-  {
-    "id": 4,
-    "parentId": 1,
-    "name": "北研中心",
-    "code": "beiyan",
-    "remark": "",
-    "status": 0,
-    "createdAt": "2023-10-13 09:43:09",
-    "updatedAt": "2024-01-02 15:25:01",
-    "serial": 2,
-    "isDeleted": 0,
-    "children": [],
-    "labelList": [],
-    "moduleList": []
-  },
-  {
-    "id": 5,
-    "parentId": 1,
-    "name": "客服中心",
-    "code": "kefu",
-    "remark": "",
-    "status": 1,
-    "createdAt": "2023-10-17 16:56:33",
-    "updatedAt": "2024-01-02 19:22:12",
-    "serial": 3,
-    "isDeleted": 0,
-    "children": [
-      {
-        "id": 19,
-        "companyId": 5,
-        "sceneLabelId": 2,
-        "name": "配电站",
-        "code": "kf-substation",
-        "remark": "",
-        "status": 0,
-        "createdAt": "2023-12-26 11:09:22",
-        "updatedAt": "2023-12-26 11:09:22",
-        "isDeleted": 0,
-        "serial": 0,
-        "labelName": "安全管控",
-        "workshopModule": {
-          "id": 1,
-          "name": "危险点",
-          "code": "1",
-          "remark": "",
-          "status": 0,
-          "createdAt": "2023-12-22 11:43:54",
-          "updatedAt": "2023-12-22 11:43:54",
-          "isDeleted": 0
-        },
-        "children": []
-      },
-      {
-        "id": 20,
-        "companyId": 5,
-        "sceneLabelId": 2,
-        "name": "气瓶间",
-        "code": "kf-gcr",
-        "remark": "",
-        "status": 0,
-        "createdAt": "2023-12-26 11:09:59",
-        "updatedAt": "2023-12-26 11:09:59",
-        "isDeleted": 0,
-        "serial": 0,
-        "labelName": "安全管控",
-        "workshopModule": {
-          "id": 2,
-          "name": "厂房",
-          "code": "2",
-          "remark": "",
-          "status": 0,
-          "createdAt": "2023-12-22 11:44:06",
-          "updatedAt": "2023-12-22 11:44:06",
-          "isDeleted": 0
-        },
-        "children": []
-      },
-      {
-        "id": 21,
-        "companyId": 5,
-        "sceneLabelId": 2,
-        "name": "柴油发电机",
-        "code": "kf-dg",
-        "remark": "",
-        "status": 0,
-        "createdAt": "2023-12-26 11:10:19",
-        "updatedAt": "2023-12-26 11:10:19",
-        "isDeleted": 0,
-        "serial": 0,
-        "labelName": "安全管控",
-        "workshopModule": {
-          "id": 2,
-          "name": "厂房",
-          "code": "2",
-          "remark": "",
-          "status": 0,
-          "createdAt": "2023-12-22 11:44:06",
-          "updatedAt": "2023-12-22 11:44:06",
-          "isDeleted": 0
-        },
-        "children": []
-      },
-      {
-        "id": 22,
-        "companyId": 5,
-        "sceneLabelId": 2,
-        "name": "运行支持指挥中心",
-        "code": "kf-qrh",
-        "remark": "",
-        "status": 0,
-        "createdAt": "2023-12-26 11:10:40",
-        "updatedAt": "2024-01-16 15:01:28",
-        "isDeleted": 0,
-        "serial": 0,
-        "labelName": "安全管控",
-        "workshopModule": {
-          "id": 2,
-          "name": "厂房",
-          "code": "2",
-          "remark": "",
-          "status": 0,
-          "createdAt": "2023-12-22 11:44:06",
-          "updatedAt": "2023-12-22 11:44:06",
-          "isDeleted": 0
-        },
-        "children": []
-      },
-      {
-        "id": 23,
-        "companyId": 5,
-        "sceneLabelId": 2,
-        "name": "C919飞行模拟机",
-        "code": "kf-sl",
-        "remark": "",
-        "status": 0,
-        "createdAt": "2023-12-26 11:11:00",
-        "updatedAt": "2024-01-17 08:51:47",
-        "isDeleted": 0,
-        "serial": 0,
-        "labelName": "安全管控",
-        "workshopModule": {
-          "id": 2,
-          "name": "厂房",
-          "code": "2",
-          "remark": "",
-          "status": 0,
-          "createdAt": "2023-12-22 11:44:06",
-          "updatedAt": "2023-12-22 11:44:06",
-          "isDeleted": 0
-        },
-        "children": []
-      }
-    ],
-    "labelList": [],
-    "moduleList": []
-  },
-  {
-    "id": 2,
-    "parentId": 1,
-    "name": "上飞厂",
-    "code": "shangfei",
-    "remark": "",
-    "status": 0,
-    "createdAt": "2023-10-13 09:42:21",
-    "updatedAt": "2024-01-02 19:22:12",
-    "serial": 4,
-    "isDeleted": 0,
-    "children": [
-      {
-        "id": 1,
-        "companyId": 2,
-        "sceneLabelId": 1,
-        "name": "ARJ21部装车间",
-        "code": "C12",
-        "remark": "",
-        "status": 0,
-        "createdAt": "2023-10-13 09:48:58",
-        "updatedAt": "2024-01-16 15:00:46",
-        "isDeleted": 0,
-        "serial": 0,
-        "labelName": "生产安全",
-        "workshopModule": {
-          "id": 2,
-          "name": "厂房",
-          "code": "2",
-          "remark": "",
-          "status": 0,
-          "createdAt": "2023-12-22 11:44:06",
-          "updatedAt": "2023-12-22 11:44:06",
-          "isDeleted": 0
-        },
-        "children": [
-          {
-            "id": 2,
-            "workshopId": 1,
-            "name": "西侧200室内气密试验区",
-            "code": "C12-W200test",
-            "remark": "",
-            "principal": "",
-            "status": 0,
-            "createdAt": "2023-12-27 14:07:15",
-            "updatedAt": "2024-01-05 09:05:52",
-            "isDeleted": 0,
-            "serial": 0
-          },
-          {
-            "id": 1,
-            "workshopId": 1,
-            "name": "东侧200室内气密试验区",
-            "code": "C12-E200test",
-            "remark": "",
-            "principal": "",
-            "status": 0,
-            "createdAt": "2023-12-27 14:06:46",
-            "updatedAt": "2024-01-05 09:05:52",
-            "isDeleted": 0,
-            "serial": 1
-          }
-        ]
-      },
-      {
-        "id": 3,
-        "companyId": 2,
-        "sceneLabelId": 1,
-        "name": "C919部装车间",
-        "code": "C02",
-        "remark": "",
-        "status": 0,
-        "createdAt": "2023-10-13 09:50:31",
-        "updatedAt": "2024-01-16 15:00:52",
-        "isDeleted": 0,
-        "serial": 0,
-        "labelName": "生产安全",
-        "workshopModule": {
-          "id": 2,
-          "name": "厂房",
-          "code": "2",
-          "remark": "",
-          "status": 0,
-          "createdAt": "2023-12-22 11:44:06",
-          "updatedAt": "2023-12-22 11:44:06",
-          "isDeleted": 0
-        },
-        "children": []
-      },
-      {
-        "id": 6,
-        "companyId": 2,
-        "sceneLabelId": 1,
-        "name": "胶接车间",
-        "code": "B16",
-        "remark": "",
-        "status": 0,
-        "createdAt": "2023-10-13 09:51:42",
-        "updatedAt": "2024-01-16 15:00:57",
-        "isDeleted": 0,
-        "serial": 0,
-        "labelName": "生产安全",
-        "workshopModule": {
-          "id": 2,
-          "name": "厂房",
-          "code": "2",
-          "remark": "",
-          "status": 0,
-          "createdAt": "2023-12-22 11:44:06",
-          "updatedAt": "2023-12-22 11:44:06",
-          "isDeleted": 0
-        },
-        "children": []
-      },
-      {
-        "id": 7,
-        "companyId": 2,
-        "sceneLabelId": 1,
-        "name": "复材车间",
-        "code": "B01",
-        "remark": "",
-        "status": 0,
-        "createdAt": "2023-10-13 09:52:02",
-        "updatedAt": "2024-01-16 15:00:59",
-        "isDeleted": 0,
-        "serial": 0,
-        "labelName": "生产安全",
-        "workshopModule": null,
-        "children": []
-      },
-      {
-        "id": 8,
-        "companyId": 2,
-        "sceneLabelId": 1,
-        "name": "工装中心",
-        "code": "B04",
-        "remark": "",
-        "status": 0,
-        "createdAt": "2023-10-13 09:53:01",
-        "updatedAt": "2023-10-13 09:53:01",
-        "isDeleted": 0,
-        "serial": 0,
-        "labelName": "生产安全",
-        "workshopModule": null,
-        "children": []
-      },
-      {
-        "id": 9,
-        "companyId": 2,
-        "sceneLabelId": 2,
-        "name": "B16热压罐",
-        "code": "B16autoclave",
-        "remark": "",
-        "status": 0,
-        "createdAt": "2023-10-13 10:22:20",
-        "updatedAt": "2023-10-19 19:12:27",
-        "isDeleted": 0,
-        "serial": 0,
-        "labelName": "安全管控",
-        "workshopModule": null,
-        "children": []
-      },
-      {
-        "id": 10,
-        "companyId": 2,
-        "sceneLabelId": 2,
-        "name": "B01热压罐",
-        "code": "B01autoclave",
-        "remark": "",
-        "status": 0,
-        "createdAt": "2023-10-13 10:22:39",
-        "updatedAt": "2023-10-13 10:22:39",
-        "isDeleted": 0,
-        "serial": 0,
-        "labelName": "安全管控",
-        "workshopModule": null,
-        "children": []
-      },
-      {
-        "id": 11,
-        "companyId": 2,
-        "sceneLabelId": 2,
-        "name": "110KV变电站",
-        "code": "110KVsubstation",
-        "remark": "",
-        "status": 0,
-        "createdAt": "2023-10-13 10:23:02",
-        "updatedAt": "2023-10-13 10:23:02",
-        "isDeleted": 0,
-        "serial": 0,
-        "labelName": "安全管控",
-        "workshopModule": null,
-        "children": []
-      },
-      {
-        "id": 12,
-        "companyId": 2,
-        "sceneLabelId": 2,
-        "name": "2011锅炉房",
-        "code": "2011boiler",
-        "remark": "",
-        "status": 0,
-        "createdAt": "2023-10-13 10:23:20",
-        "updatedAt": "2023-10-13 10:23:20",
-        "isDeleted": 0,
-        "serial": 0,
-        "labelName": "安全管控",
-        "workshopModule": {
-          "id": 1,
-          "name": "危险点",
-          "code": "1",
-          "remark": "",
-          "status": 0,
-          "createdAt": "2023-12-22 11:43:54",
-          "updatedAt": "2023-12-22 11:43:54",
-          "isDeleted": 0
-        },
-        "children": []
-      },
-      {
-        "id": 13,
-        "companyId": 2,
-        "sceneLabelId": 2,
-        "name": "2001a锅炉房",
-        "code": "2001aboiler",
-        "remark": "",
-        "status": 0,
-        "createdAt": "2023-10-13 10:23:36",
-        "updatedAt": "2023-10-13 10:23:36",
-        "isDeleted": 0,
-        "serial": 0,
-        "labelName": "安全管控",
-        "workshopModule": {
-          "id": 1,
-          "name": "危险点",
-          "code": "1",
-          "remark": "",
-          "status": 0,
-          "createdAt": "2023-12-22 11:43:54",
-          "updatedAt": "2023-12-22 11:43:54",
-          "isDeleted": 0
-        },
-        "children": []
-      },
-      {
-        "id": 15,
-        "companyId": 2,
-        "sceneLabelId": 2,
-        "name": "增材实验室",
-        "code": "sf-additive_lab",
-        "remark": "",
-        "status": 0,
-        "createdAt": "2023-12-11 13:40:33",
-        "updatedAt": "2023-12-11 13:40:33",
-        "isDeleted": 0,
-        "serial": 0,
-        "labelName": "安全管控",
-        "workshopModule": {
-          "id": 1,
-          "name": "危险点",
-          "code": "1",
-          "remark": "",
-          "status": 0,
-          "createdAt": "2023-12-22 11:43:54",
-          "updatedAt": "2023-12-22 11:43:54",
-          "isDeleted": 0
-        },
-        "children": []
-      },
-      {
-        "id": 2,
-        "companyId": 2,
-        "sceneLabelId": 1,
-        "name": "ARJ21总装车间",
-        "code": "C11",
-        "remark": "",
-        "status": 0,
-        "createdAt": "2023-10-13 09:49:31",
-        "updatedAt": "2024-01-16 15:00:48",
-        "isDeleted": 0,
-        "serial": 1,
-        "labelName": "生产安全",
-        "workshopModule": {
-          "id": 2,
-          "name": "厂房",
-          "code": "2",
-          "remark": "",
-          "status": 0,
-          "createdAt": "2023-12-22 11:44:06",
-          "updatedAt": "2023-12-22 11:44:06",
-          "isDeleted": 0
-        },
-        "children": []
-      },
-      {
-        "id": 4,
-        "companyId": 2,
-        "sceneLabelId": 1,
-        "name": "C919总装车间",
-        "code": "C01",
-        "remark": "",
-        "status": 0,
-        "createdAt": "2023-10-13 09:50:53",
-        "updatedAt": "2024-01-16 15:00:54",
-        "isDeleted": 0,
-        "serial": 1,
-        "labelName": "生产安全",
-        "workshopModule": {
-          "id": 2,
-          "name": "厂房",
-          "code": "2",
-          "remark": "",
-          "status": 0,
-          "createdAt": "2023-12-22 11:44:06",
-          "updatedAt": "2023-12-22 11:44:06",
-          "isDeleted": 0
-        },
-        "children": []
-      },
-      {
-        "id": 5,
-        "companyId": 2,
-        "sceneLabelId": 1,
-        "name": "维修交付中心",
-        "code": "repair",
-        "remark": "",
-        "status": 0,
-        "createdAt": "2023-10-13 09:51:22",
-        "updatedAt": "2024-01-16 15:00:55",
-        "isDeleted": 0,
-        "serial": 2,
-        "labelName": "生产安全",
-        "workshopModule": {
-          "id": 2,
-          "name": "厂房",
-          "code": "2",
-          "remark": "",
-          "status": 0,
-          "createdAt": "2023-12-22 11:44:06",
-          "updatedAt": "2023-12-22 11:44:06",
-          "isDeleted": 0
-        },
-        "children": []
-      }
-    ],
-    "labelList": [
-      {
-        "id": 1,
-        "name": "生产安全",
-        "code": "1",
-        "remark": "11",
-        "status": 0,
-        "createdAt": "2023-12-22 11:42:52",
-        "updatedAt": "2024-01-16 15:00:11",
-        "isDeleted": 0
-      },
-      {
-        "id": 2,
-        "name": "安全管控",
-        "code": "2",
-        "remark": "",
-        "status": 0,
-        "createdAt": "2023-12-27 13:49:28",
-        "updatedAt": "2024-01-16 15:00:28",
-        "isDeleted": 0
-      }
-    ],
-    "moduleList": [
-      {
-        "id": 1,
-        "name": "生产安全模板",
-        "code": "12",
-        "remark": "32437857",
-        "status": 0,
-        "createdAt": "2023-12-22 11:43:05",
-        "updatedAt": "2024-01-04 14:37:40",
-        "isDeleted": 0
-      },
-      {
-        "id": 1,
-        "name": "生产安全模板",
-        "code": "12",
-        "remark": "32437857",
-        "status": 0,
-        "createdAt": "2023-12-22 11:43:05",
-        "updatedAt": "2024-01-04 14:37:40",
-        "isDeleted": 0
-      }
-    ]
-  }
-]

+ 16 - 10
src/views/system-config/scene-manage/CompanyDrawer.vue

@@ -100,7 +100,7 @@
   } from '@/api/scene/secene-templet';
   import { ENABLED } from './constant';
   import type { FormInstance, FormRules } from 'element-plus';
-  import { ElMessageBox } from 'element-plus';
+  import { ElMessage, ElMessageBox } from 'element-plus';
   import { CirclePlus } from '@element-plus/icons-vue';
   import { addCompany, editCompany } from '@/api/scene/sceneOperate';
 
@@ -201,17 +201,23 @@
 
   //删除场景&模板
   const deleScene = (index) => {
-    ElMessageBox.confirm('请确认是否关闭该场景?', '状态关闭', {
-      confirmButtonText: '确认',
-      cancelButtonText: '取消',
-      type: 'warning',
-    })
-      .then(() => {
-        ruleForm.selectItems!.splice(index, 1);
+    if (ruleForm.selectItems!.length > 1) {
+      ElMessageBox.confirm('请确认是否关闭该场景?', '状态关闭', {
+        confirmButtonText: '确认',
+        cancelButtonText: '取消',
+        type: 'warning',
       })
-      .catch(() => {
-        console.log('取消删除物件');
+        .then(() => {
+          ruleForm.selectItems!.splice(index, 1);
+        })
+        .catch(() => {
+          console.log('取消删除物件');
+        });
+    } else {
+      ElMessage.warning({
+        message: '无法删除',
       });
+    }
   };
   //添加新公司的提交
   const newCompanyAdd = (formEl: FormInstance | undefined) => {

+ 6 - 1
src/views/system-config/scene-manage/SceneManage.vue

@@ -6,6 +6,7 @@
         :data-source="tableData"
         :row-key="(row) => row.name"
         :action-column="actionColumn"
+        :expend-row="expendRowKeys"
         :tableSetting="{
           width: 200,
           size: false,
@@ -110,6 +111,7 @@
   const { tableData, getSceneDetail } = useSceneList;
   const useSceneTempleteDetail = useSceneTemplete();
   const { sceneList, templateList, workshopTemplateList } = useSceneTempleteDetail;
+  const expendRowKeys = ref(['']);
 
   const showDrawer = ref<DrawerType | null>(null);
 
@@ -218,7 +220,10 @@
     editedItem.value = { ...row }; // 将当前行的内容拷贝到 editedItem 中,以便编辑
     //得出当前的数据的层级
     level.value = findItemLevel(tableData.value, row.id, row.name);
-
+    if ((expendRowKeys.value[0] = row.name)) {
+      expendRowKeys.value[0] = '';
+    }
+    expendRowKeys.value[0] = row.name;
     if (level.value === DATA_LEVEL.company) {
       showDrawer.value = DrawerType.workshop;
       detail.value = {

+ 11 - 24
src/views/system-config/scene-manage/actionColomns.vue

@@ -12,30 +12,10 @@
       <div @click="changeAdd" class="wordStyle" style="margin-right: 7px">添加下一级</div></div
     >
     <div style="width: 1px; height: 14px; color: #e9e9e9; margin-right: 14px">|</div>
-    <img
-      src="../../../assets/icons/edit.png"
-      @click="changeEdit"
-      style="margin-right: 10px; cursor: pointer"
-      alt=""
-    />
-    <img
-      src="../../../assets/icons/delete.png"
-      @click="changeDelete"
-      style="margin-right: 10px; cursor: pointer"
-      alt=""
-    />
-    <img
-      src="../../../assets/icons/up.png"
-      @click="changeUp"
-      style="margin-right: 10px; cursor: pointer"
-      alt=""
-    />
-    <img
-      src="../../../assets/icons/down.png"
-      @click="changeDown"
-      style="margin-right: 10px; cursor: pointer"
-      alt=""
-    />
+    <img src="../../../assets/icons/edit.png" @click="changeEdit" class="action-img" alt="" />
+    <img src="../../../assets/icons/delete.png" @click="changeDelete" class="action-img" alt="" />
+    <img src="../../../assets/icons/up.png" @click="changeUp" class="action-img" alt="" />
+    <img src="../../../assets/icons/down.png" @click="changeDown" class="action-img" alt="" />
   </div>
 </template>
 
@@ -107,4 +87,11 @@
     --el-button-hover-bg-color: #f68888;
     --el-button-active-bg-color: #c35353;
   }
+
+  .action-img {
+    margin-right: 10px;
+    cursor: pointer;
+    height: 16px;
+    margin-top: 5px;
+  }
 </style>