Sfoglia il codice sorgente

fix: 编译发布优化,icon优化

zhanghaijun 1 anno fa
parent
commit
9b9ee14480

+ 0 - 2
.env

@@ -24,7 +24,5 @@ VITE_OPEN_ROUTE_INFO = false
 # 锁屏加密密钥
 VITE_LOCK_ENCRYPT_KEY = s3cur3k3y4adpro
 
-# 是否启用离线图标
-VITE_APP_ICON_OFFLINE=true
 # 图标前缀-提供给icon-picker选择的图标,这里的值建议和src/utils/load-icon.ts中引入的一致
 VITE_APP_ICONIFY_PREFIX = ep,ant-design,carbon,ic,logos,lucide

+ 1 - 0
package.json

@@ -81,6 +81,7 @@
     "@commitlint/cli": "^19.4.1",
     "@commitlint/config-conventional": "^19.4.1",
     "@eslint/js": "^9.9.1",
+    "@meta2d/core": "^1.0.98",
     "@tailwindcss/vite": "^4.1.13",
     "@types/lodash-es": "^4.17.12",
     "@types/node": "^22.1.0",

+ 193 - 0
pnpm-lock.yaml

@@ -99,6 +99,9 @@ importers:
       '@eslint/js':
         specifier: ^9.9.1
         version: 9.15.0
+      '@meta2d/core':
+        specifier: ^1.0.98
+        version: 1.0.98
       '@tailwindcss/vite':
         specifier: ^4.1.13
         version: 4.1.13(vite@6.1.1(@types/node@22.10.0)(jiti@2.6.0)(lightningcss@1.30.1)(sass@1.81.0)(terser@5.36.0)(tsx@4.20.3)(yaml@2.8.0))
@@ -1090,6 +1093,9 @@ packages:
   '@lezer/yaml@1.0.3':
     resolution: {integrity: sha512-GuBLekbw9jDBDhGur82nuwkxKQ+a3W5H0GfaAthDXcAu+XdpS43VlnxA9E9hllkpSP5ellRDKjLLj7Lu9Wr6xA==}
 
+  '@meta2d/core@1.0.98':
+    resolution: {integrity: sha512-fJ7ViQDqTEsC7JTQZuG/8IwNyWINhxBUKyJ4Os/IMMzI41HDmsJWxFCM7BZu0xpy87gHDAkZoLr9/iIBlYObZg==}
+
   '@nodelib/fs.scandir@2.1.5':
     resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
     engines: {node: '>= 8'}
@@ -2044,6 +2050,9 @@ packages:
   commander@2.20.3:
     resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==}
 
+  commist@1.1.0:
+    resolution: {integrity: sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==}
+
   commitizen@4.3.1:
     resolution: {integrity: sha512-gwAPAVTy/j5YcOOebcCRIijn+mSjWJC+IYKivTu6aG8Ei/scoXgfsMRnuAk6b0GRste2J4NGxVdMN3ZpfNaVaw==}
     engines: {node: '>= 12'}
@@ -2058,6 +2067,10 @@ packages:
   concat-map@0.0.1:
     resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
 
+  concat-stream@2.0.0:
+    resolution: {integrity: sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==}
+    engines: {'0': node >= 6.0}
+
   confbox@0.1.8:
     resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==}
 
@@ -2284,6 +2297,9 @@ packages:
   downloadjs@1.4.7:
     resolution: {integrity: sha512-LN1gO7+u9xjU5oEScGFKvXhYf7Y/empUIIEAGBs1LzUq/rg5duiDrkuH5A2lQGd5jfMOb9X9usDa2oVXwJ0U/Q==}
 
+  duplexify@4.1.3:
+    resolution: {integrity: sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA==}
+
   echarts@5.6.0:
     resolution: {integrity: sha512-oTbVTsXfKuEhxftHqL5xprgLoc0k7uScAwtryCgWF6hPYFLRwOUHiFmHGCBKP5NPFNkDVopOieyUqYGH8Fa3kA==}
 
@@ -2301,6 +2317,9 @@ packages:
   emoji-regex@8.0.0:
     resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
 
+  end-of-stream@1.4.5:
+    resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==}
+
   enhanced-resolve@5.18.3:
     resolution: {integrity: sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==}
     engines: {node: '>=10.13.0'}
@@ -2716,6 +2735,9 @@ packages:
     resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==}
     hasBin: true
 
+  help-me@3.0.0:
+    resolution: {integrity: sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==}
+
   highlight.js@11.10.0:
     resolution: {integrity: sha512-SYVnVFswQER+zu1laSya563s+F8VDGt7o35d4utbamowvUNLLMovFqwCLSocpZTz3MgaSRA1IbqRWZv97dtErQ==}
     engines: {node: '>=12.0.0'}
@@ -2928,6 +2950,9 @@ packages:
     resolution: {integrity: sha512-VXe6RjJkBPj0ohtqaO8vSWP3ZhAKo66fKrFNCll4BTcwljPLz03pCbaNKfzGP5MbrCYcbJ7v0nOYYwUzTEIdXQ==}
     hasBin: true
 
+  js-sdsl@4.3.0:
+    resolution: {integrity: sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==}
+
   js-tokens@4.0.0:
     resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
 
@@ -2996,6 +3021,10 @@ packages:
   kolorist@1.8.0:
     resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==}
 
+  leven@2.1.0:
+    resolution: {integrity: sha512-nvVPLpIHUxCUoRLrFqTgSxXJ614d8AgQoWl7zPe/2VadE8+1dpU3LBhowRuBAcuwruWtOdD8oYC9jDNJjXDPyA==}
+    engines: {node: '>=0.10.0'}
+
   levn@0.4.1:
     resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
     engines: {node: '>= 0.8.0'}
@@ -3185,6 +3214,10 @@ packages:
   lru-cache@5.1.1:
     resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
 
+  lru-cache@6.0.0:
+    resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==}
+    engines: {node: '>=10'}
+
   magic-string@0.30.14:
     resolution: {integrity: sha512-5c99P1WKTed11ZC0HMJOj6CDIue6F8ySu+bJL+85q1zBEIY8IklrJ1eiKC2NDRh3Ct3FcvmJPyQHb9erXMTJNw==}
 
@@ -3299,6 +3332,9 @@ packages:
     resolution: {integrity: sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==}
     engines: {node: '>= 18'}
 
+  mitt@2.1.0:
+    resolution: {integrity: sha512-ILj2TpLiysu2wkBbWjAmww7TkZb65aiQO+DkVdUTBpBXq+MHYiETENkKFMtsJZX1Lf4pe4QOrTSjIfUwN5lRdg==}
+
   mitt@3.0.1:
     resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==}
 
@@ -3308,6 +3344,14 @@ packages:
   mlly@1.7.4:
     resolution: {integrity: sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==}
 
+  mqtt-packet@6.10.0:
+    resolution: {integrity: sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==}
+
+  mqtt@4.3.8:
+    resolution: {integrity: sha512-2xT75uYa0kiPEF/PE0VPdavmEkoBzMT/UL9moid0rAvlCtV48qBwxD62m7Ld/4j8tSkIO1E/iqRl/S72SEOhOw==}
+    engines: {node: '>=10.0.0'}
+    hasBin: true
+
   mrmime@2.0.1:
     resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==}
     engines: {node: '>=10'}
@@ -3370,6 +3414,9 @@ packages:
   nth-check@2.1.1:
     resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==}
 
+  number-allocator@1.0.14:
+    resolution: {integrity: sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==}
+
   nypm@0.6.0:
     resolution: {integrity: sha512-mn8wBFV9G9+UFHIrq+pZ2r2zL4aPau/by3kJb3cM7+5tQHMt6HGQB8FDIeKFYp8o0D2pnH6nVsO88N4AmUxIWg==}
     engines: {node: ^14.16.0 || >=16.10.0}
@@ -3672,9 +3719,15 @@ packages:
     resolution: {integrity: sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==}
     engines: {node: '>=6'}
 
+  process-nextick-args@2.0.1:
+    resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==}
+
   proxy-from-env@1.1.0:
     resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
 
+  pump@3.0.3:
+    resolution: {integrity: sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==}
+
   punycode.js@2.3.1:
     resolution: {integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==}
     engines: {node: '>=6'}
@@ -3712,6 +3765,9 @@ packages:
   regenerator-runtime@0.14.1:
     resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==}
 
+  reinterval@1.1.0:
+    resolution: {integrity: sha512-QIRet3SYrGp0HUHO88jVskiG6seqUGC5iAG7AwI/BV4ypGcuqk9Du6YQBUOUqm9c8pw1eyLoIaONifRua1lsEQ==}
+
   require-directory@2.1.1:
     resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
     engines: {node: '>=0.10.0'}
@@ -3876,6 +3932,9 @@ packages:
     resolution: {integrity: sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==}
     engines: {node: '>=0.10.0'}
 
+  split2@3.2.2:
+    resolution: {integrity: sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==}
+
   split2@4.2.0:
     resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==}
     engines: {node: '>= 10.x'}
@@ -3890,6 +3949,9 @@ packages:
   std-env@3.9.0:
     resolution: {integrity: sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==}
 
+  stream-shift@1.0.3:
+    resolution: {integrity: sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==}
+
   string-argv@0.3.2:
     resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==}
     engines: {node: '>=0.6.19'}
@@ -4105,6 +4167,9 @@ packages:
   type@2.7.3:
     resolution: {integrity: sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==}
 
+  typedarray@0.0.6:
+    resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==}
+
   typescript-eslint@8.16.0:
     resolution: {integrity: sha512-wDkVmlY6O2do4V+lZd0GtRfbtXbeD0q9WygwXXSJnC1xorE8eqyC2L1tJimqpSeFrOzRlYtWnUp/uzgHQOgfBQ==}
     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -4383,6 +4448,18 @@ packages:
     resolution: {integrity: sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==}
     engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
 
+  ws@7.5.10:
+    resolution: {integrity: sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==}
+    engines: {node: '>=8.3.0'}
+    peerDependencies:
+      bufferutil: ^4.0.1
+      utf-8-validate: ^5.0.2
+    peerDependenciesMeta:
+      bufferutil:
+        optional: true
+      utf-8-validate:
+        optional: true
+
   xgplayer-subtitles@3.0.20:
     resolution: {integrity: sha512-I1bjsIY+aKOrhYQspLdneOkYg+Vf4cJVGPnDSFnNebnxXl9Mhz5SEpWGzYizMYxL9UvsQ9pgjeEY0o4hkwM+kQ==}
     peerDependencies:
@@ -4407,6 +4484,10 @@ packages:
     engines: {node: '>= 0.10.0'}
     hasBin: true
 
+  xtend@4.0.2:
+    resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==}
+    engines: {node: '>=0.4'}
+
   y18n@5.0.8:
     resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
     engines: {node: '>=10'}
@@ -4414,6 +4495,9 @@ packages:
   yallist@3.1.1:
     resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
 
+  yallist@4.0.0:
+    resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
+
   yallist@5.0.0:
     resolution: {integrity: sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==}
     engines: {node: '>=18'}
@@ -5528,6 +5612,15 @@ snapshots:
       '@lezer/highlight': 1.2.1
       '@lezer/lr': 1.4.2
 
+  '@meta2d/core@1.0.98':
+    dependencies:
+      mitt: 2.1.0
+      mqtt: 4.3.8
+    transitivePeerDependencies:
+      - bufferutil
+      - supports-color
+      - utf-8-validate
+
   '@nodelib/fs.scandir@2.1.5':
     dependencies:
       '@nodelib/fs.stat': 2.0.5
@@ -6583,6 +6676,11 @@ snapshots:
 
   commander@2.20.3: {}
 
+  commist@1.1.0:
+    dependencies:
+      leven: 2.1.0
+      minimist: 1.2.8
+
   commitizen@4.3.1(@types/node@22.10.0)(typescript@5.6.3):
     dependencies:
       cachedir: 2.3.0
@@ -6612,6 +6710,13 @@ snapshots:
 
   concat-map@0.0.1: {}
 
+  concat-stream@2.0.0:
+    dependencies:
+      buffer-from: 1.1.2
+      inherits: 2.0.4
+      readable-stream: 3.6.2
+      typedarray: 0.0.6
+
   confbox@0.1.8: {}
 
   confbox@0.2.2: {}
@@ -6804,6 +6909,13 @@ snapshots:
 
   downloadjs@1.4.7: {}
 
+  duplexify@4.1.3:
+    dependencies:
+      end-of-stream: 1.4.5
+      inherits: 2.0.4
+      readable-stream: 3.6.2
+      stream-shift: 1.0.3
+
   echarts@5.6.0:
     dependencies:
       tslib: 2.3.0
@@ -6836,6 +6948,10 @@ snapshots:
 
   emoji-regex@8.0.0: {}
 
+  end-of-stream@1.4.5:
+    dependencies:
+      once: 1.4.0
+
   enhanced-resolve@5.18.3:
     dependencies:
       graceful-fs: 4.2.11
@@ -7351,6 +7467,11 @@ snapshots:
 
   he@1.2.0: {}
 
+  help-me@3.0.0:
+    dependencies:
+      glob: 7.2.3
+      readable-stream: 3.6.2
+
   highlight.js@11.10.0: {}
 
   homedir-polyfill@1.0.3:
@@ -7510,6 +7631,8 @@ snapshots:
 
   jiti@2.6.0: {}
 
+  js-sdsl@4.3.0: {}
+
   js-tokens@4.0.0: {}
 
   js-tokens@9.0.1: {}
@@ -7560,6 +7683,8 @@ snapshots:
 
   kolorist@1.8.0: {}
 
+  leven@2.1.0: {}
+
   levn@0.4.1:
     dependencies:
       prelude-ls: 1.2.1
@@ -7726,6 +7851,10 @@ snapshots:
     dependencies:
       yallist: 3.1.1
 
+  lru-cache@6.0.0:
+    dependencies:
+      yallist: 4.0.0
+
   magic-string@0.30.14:
     dependencies:
       '@jridgewell/sourcemap-codec': 1.5.0
@@ -7836,6 +7965,8 @@ snapshots:
     dependencies:
       minipass: 7.1.2
 
+  mitt@2.1.0: {}
+
   mitt@3.0.1: {}
 
   mlly@1.7.3:
@@ -7852,6 +7983,38 @@ snapshots:
       pkg-types: 1.3.1
       ufo: 1.6.1
 
+  mqtt-packet@6.10.0:
+    dependencies:
+      bl: 4.1.0
+      debug: 4.4.1
+      process-nextick-args: 2.0.1
+    transitivePeerDependencies:
+      - supports-color
+
+  mqtt@4.3.8:
+    dependencies:
+      commist: 1.1.0
+      concat-stream: 2.0.0
+      debug: 4.4.1
+      duplexify: 4.1.3
+      help-me: 3.0.0
+      inherits: 2.0.4
+      lru-cache: 6.0.0
+      minimist: 1.2.8
+      mqtt-packet: 6.10.0
+      number-allocator: 1.0.14
+      pump: 3.0.3
+      readable-stream: 3.6.2
+      reinterval: 1.1.0
+      rfdc: 1.4.1
+      split2: 3.2.2
+      ws: 7.5.10
+      xtend: 4.0.2
+    transitivePeerDependencies:
+      - bufferutil
+      - supports-color
+      - utf-8-validate
+
   mrmime@2.0.1: {}
 
   ms@2.1.3: {}
@@ -7896,6 +8059,13 @@ snapshots:
     dependencies:
       boolbase: 1.0.0
 
+  number-allocator@1.0.14:
+    dependencies:
+      debug: 4.4.1
+      js-sdsl: 4.3.0
+    transitivePeerDependencies:
+      - supports-color
+
   nypm@0.6.0:
     dependencies:
       citty: 0.1.6
@@ -8131,8 +8301,15 @@ snapshots:
 
   prismjs@1.29.0: {}
 
+  process-nextick-args@2.0.1: {}
+
   proxy-from-env@1.1.0: {}
 
+  pump@3.0.3:
+    dependencies:
+      end-of-stream: 1.4.5
+      once: 1.4.0
+
   punycode.js@2.3.1: {}
 
   punycode@2.3.1: {}
@@ -8164,6 +8341,8 @@ snapshots:
 
   regenerator-runtime@0.14.1: {}
 
+  reinterval@1.1.0: {}
+
   require-directory@2.1.1: {}
 
   require-from-string@2.0.2: {}
@@ -8323,6 +8502,10 @@ snapshots:
 
   speakingurl@14.0.1: {}
 
+  split2@3.2.2:
+    dependencies:
+      readable-stream: 3.6.2
+
   split2@4.2.0: {}
 
   ssf@0.11.2:
@@ -8333,6 +8516,8 @@ snapshots:
 
   std-env@3.9.0: {}
 
+  stream-shift@1.0.3: {}
+
   string-argv@0.3.2: {}
 
   string-width@4.2.3:
@@ -8578,6 +8763,8 @@ snapshots:
 
   type@2.7.3: {}
 
+  typedarray@0.0.6: {}
+
   typescript-eslint@8.16.0(eslint@9.15.0(jiti@2.6.0))(typescript@5.6.3):
     dependencies:
       '@typescript-eslint/eslint-plugin': 8.16.0(@typescript-eslint/parser@8.16.0(eslint@9.15.0(jiti@2.6.0))(typescript@5.6.3))(eslint@9.15.0(jiti@2.6.0))(typescript@5.6.3)
@@ -8899,6 +9086,8 @@ snapshots:
       imurmurhash: 0.1.4
       signal-exit: 4.1.0
 
+  ws@7.5.10: {}
+
   xgplayer-subtitles@3.0.20(core-js@3.39.0):
     dependencies:
       core-js: 3.39.0
@@ -8930,10 +9119,14 @@ snapshots:
       commander: 2.20.3
       cssfilter: 0.0.10
 
+  xtend@4.0.2: {}
+
   y18n@5.0.8: {}
 
   yallist@3.1.1: {}
 
+  yallist@4.0.0: {}
+
   yallist@5.0.0: {}
 
   yaml@2.8.0: {}

+ 1 - 2
src/api/auth.api.ts

@@ -11,8 +11,7 @@ interface LoginResponse {
 
 export class AuthService {
   // 登录
-  static login = (params: LoginParams) =>
-    request.post<LoginResponse>({ url: '/auth/login', params })
+  static login = (params: LoginParams) => request.post<LoginResponse>({ url: '/auth/login', params })
   // 退出登录
   static logout = () => request.post({ url: '/auth/logout' })
 }

BIN
src/assets/img/favicon.ico


+ 100 - 0
src/components/business/meta2d/Meta2dView.vue

@@ -0,0 +1,100 @@
+<template>
+  <div class="meta2d-container" ref="container"></div>
+</template>
+
+<script lang="ts" setup>
+  import { onMounted, onUnmounted } from 'vue'
+  import { Meta2d, Pen } from '@meta2d/core'
+  // import { Meta2d, Pen, register, registerAnchors, registerCanvasDraw } from '@meta2d/core'
+  // import { flowPens, flowAnchors } from '@meta2d/flow-diagram'
+  // import { activityDiagram, activityDiagramByCtx } from '@meta2d/activity-diagram'
+  // import { classPens } from '@meta2d/class-diagram'
+  // import { sequencePens, sequencePensbyCtx } from '@meta2d/sequence-diagram'
+  // import { register as registerEcharts } from '@meta2d/chart-diagram'
+  // import { formPens } from '@meta2d/form-diagram'
+  // import { chartsPens } from '@meta2d/le5le-charts'
+  // import { ftaPens, ftaPensbyCtx, ftaAnchors } from '@meta2d/fta-diagram'
+  import { useSelection } from './selections'
+
+  // Props 接收外部数据
+  interface Meta2dProps {
+    data?: any // 初始拓扑图数据
+    preview?: boolean // 是否只读
+  }
+  const props = defineProps<Meta2dProps>()
+
+  // 组件内部引用
+  const container = ref<HTMLDivElement | null>(null)
+  const meta2dRef = ref<Meta2d | null>(null)
+  const { select } = useSelection()
+
+  const active = (pens?: Pen[]) => select(pens)
+
+  const inactive = () => select()
+
+  // 初始化拓扑图
+  const initMeta2d = () => {
+    if (!container.value) return
+
+    meta2dRef.value = new Meta2d(container.value, { rule: true })
+    const meta2d = meta2dRef.value
+
+    // 按需注册图形库
+    // 以下为自带基础图形库
+    // register(flowPens())
+    // registerAnchors(flowAnchors())
+    // register(activityDiagram())
+    // registerCanvasDraw(activityDiagramByCtx())
+    // register(classPens())
+    // register(sequencePens())
+    // registerCanvasDraw(sequencePensbyCtx())
+    // registerEcharts()
+    // registerCanvasDraw(formPens())
+    // registerCanvasDraw(chartsPens())
+    // register(ftaPens())
+    // registerCanvasDraw(ftaPensbyCtx())
+    // registerAnchors(ftaAnchors())
+
+    // 打开数据
+    let data = props.data || {}
+    if (props.preview) data.locked = 1
+    meta2d.open(data)
+
+    // 节点点击事件
+    meta2d.on('active', (event) => {
+      console.log('触发active事件', event)
+      active(event)
+    })
+    meta2d.on('inactive', (event) => {
+      console.log('触发inactive事件', event)
+      inactive()
+    })
+  }
+
+  // 支持外部更新数据
+  watch(
+    () => props.data,
+    (val) => {
+      if (meta2dRef.value && val) {
+        meta2dRef.value.open(val)
+      }
+    },
+    { deep: true }
+  )
+
+  onMounted(() => nextTick(initMeta2d))
+
+  onUnmounted(() => {
+    meta2dRef.value?.destroy()
+    meta2dRef.value = null
+  })
+</script>
+
+<style scoped>
+  .meta2d-container {
+    z-index: 1;
+    width: 100%;
+    height: calc(100vh - 120px);
+    border: 1px solid #ddd;
+  }
+</style>

+ 31 - 0
src/components/business/meta2d/selections.ts

@@ -0,0 +1,31 @@
+import { Pen } from '@meta2d/core'
+import { reactive } from 'vue'
+
+export enum SelectionMode {
+  File, // 选中画布
+  Pen // 选中单个图元
+}
+
+// 响应式存储当前选中状态
+export const selections = reactive<{ mode: SelectionMode; pen?: Pen }>({
+  mode: SelectionMode.File,
+  pen: undefined
+})
+
+export const useSelection = () => {
+  const select = (pens?: Pen[]) => {
+    if (!pens || pens.length !== 1) {
+      selections.mode = SelectionMode.File
+      selections.pen = undefined
+      return
+    }
+
+    selections.mode = SelectionMode.Pen
+    selections.pen = pens[0]
+  }
+
+  return {
+    selections,
+    select
+  }
+}

+ 4 - 28
src/components/core/base/art-icon-selector/index.vue

@@ -74,7 +74,6 @@
   import { extractIconClasses, type IconfontType } from '@/utils/constants'
   import { Icon } from '@/components/icon'
   import { listIcons } from '@iconify/vue'
-  import { fetchIconsData } from './icons'
 
   defineOptions({ name: 'ArtIconSelector' })
   const searchText = ref('')
@@ -91,34 +90,11 @@
     return iconifyMap[activeTab.value]
   })
   onMounted(() => {
-    // 离线模式下,已存缓存了所有图标
-    if (import.meta.env.VITE_APP_ICON_OFFLINE === 'true') {
-      iconifyPrefixs.forEach((prefix: any) => {
-        const icons = listIcons('', prefix)
-        iconifyMap[prefix] = icons
-      })
-    } else {
-      // 在线模式下,根据当前激活的tab加载图标
-      if (iconifyPrefixs.includes(activeTab.value)) {
-        fetchIconsData(activeTab.value).then((res) => {
-          iconifyMap[activeTab.value] = res
-        })
-      }
-    }
+    iconifyPrefixs.forEach((prefix: any) => {
+      const icons = listIcons('', prefix)
+      iconifyMap[prefix] = icons
+    })
   })
-  watchDebounced(
-    () => activeTab.value,
-    () => {
-      // 在线模式下,根据当前激活的tab加载图标
-      if (import.meta.env.VITE_APP_ICON_OFFLINE === 'false') {
-        if (iconifyPrefixs.includes(activeTab.value)) {
-          fetchIconsData(activeTab.value).then((res) => {
-            iconifyMap[activeTab.value] = res
-          })
-        }
-      }
-    }
-  )
 
   // 过滤后的图标列表(搜索功能)
   const filteredIconifyList = computed<string[]>(() => {

+ 0 - 4
src/main.ts

@@ -17,10 +17,6 @@ import * as ElementPlusIconsVue from '@element-plus/icons-vue'
 import { setupGlobDirectives } from './directives'
 import { setupErrorHandle } from './utils/sys/error-handle'
 import language from './locales'
-if ((import.meta as any).env.VITE_APP_ICON_OFFLINE === 'true') {
-  // 加载图标
-  await import('@/utils/load-icon');
-}
 
 document.addEventListener(
   'touchstart',

+ 0 - 13
src/utils/load-icon.ts

@@ -1,13 +0,0 @@
-import { addCollection } from '@iconify/vue'
-import AntDesignIcons from '@iconify/json/json/ant-design.json'
-import CarbonIcons from '@iconify/json/json/carbon.json'
-import IcIcons from '@iconify/json/json/ic.json'
-import LogosIcons from '@iconify/json/json/logos.json'
-import LucideIcons from '@iconify/json/json/lucide.json'
-import EP from '@iconify/json/json/ep.json'
-addCollection(AntDesignIcons)
-addCollection(LucideIcons)
-addCollection(CarbonIcons)
-addCollection(IcIcons as any)
-addCollection(LogosIcons as any)
-addCollection(EP)

+ 3 - 16
src/utils/tool.ts

@@ -46,12 +46,7 @@ export const getRelativeTime = (dateString: string): string => {
  * @param childrenKey 子节点字段名,默认为'children'
  * @returns 包含当前节点及所有子节点ID的数组
  */
-export const getTreeNodeAndChildrenIds = (
-  data: any[],
-  id: any,
-  idKey = 'id',
-  childrenKey = 'children'
-): any[] => {
+export const getTreeNodeAndChildrenIds = (data: any[], id: any, idKey = 'id', childrenKey = 'children'): any[] => {
   const result: any[] = []
 
   const traverse = (nodes: any[]) => {
@@ -95,11 +90,7 @@ export const getTreeLeafNodes = (data: any[], childrenKey = 'children'): any[] =
 
     for (const node of nodes) {
       // 如果节点没有子节点或者子节点为空数组,则为叶子节点
-      if (
-        !node[childrenKey] ||
-        !Array.isArray(node[childrenKey]) ||
-        node[childrenKey].length === 0
-      ) {
+      if (!node[childrenKey] || !Array.isArray(node[childrenKey]) || node[childrenKey].length === 0) {
         result.push(node)
       } else {
         // 递归查找子节点
@@ -127,11 +118,7 @@ export const getTreeLeafNodeIds = (data: any[], idKey = 'id', childrenKey = 'chi
 
     for (const node of nodes) {
       // 如果节点没有子节点或者子节点为空数组,则为叶子节点
-      if (
-        !node[childrenKey] ||
-        !Array.isArray(node[childrenKey]) ||
-        node[childrenKey].length === 0
-      ) {
+      if (!node[childrenKey] || !Array.isArray(node[childrenKey]) || node[childrenKey].length === 0) {
         result.push(node[idKey])
       } else {
         // 递归查找子节点

+ 3 - 20
src/views/article/publish/index.vue

@@ -5,20 +5,11 @@
         <!-- 文章标题、类型 -->
         <ElRow :gutter="10">
           <ElCol :span="18">
-            <ElInput
-              v-model.trim="articleName"
-              placeholder="请输入文章标题(最多100个字符)"
-              maxlength="100"
-            />
+            <ElInput v-model.trim="articleName" placeholder="请输入文章标题(最多100个字符)" maxlength="100" />
           </ElCol>
           <ElCol :span="6">
             <ElSelect v-model="articleType" placeholder="请选择文章类型" filterable>
-              <ElOption
-                v-for="item in articleTypes"
-                :key="item.id"
-                :label="item.name"
-                :value="item.id"
-              />
+              <ElOption v-for="item in articleTypes" :key="item.id" :label="item.name" :value="item.id" />
             </ElSelect>
           </ElCol>
         </ElRow>
@@ -32,15 +23,7 @@
           <ElForm>
             <ElFormItem label="封面">
               <div class="el-top upload-container">
-                <ElUpload
-                  class="cover-uploader"
-                  :action="uploadImageUrl"
-                  :headers="uploadHeaders"
-                  :show-file-list="false"
-                  :on-success="onSuccess"
-                  :on-error="onError"
-                  :before-upload="beforeUpload"
-                >
+                <ElUpload class="cover-uploader" :action="uploadImageUrl" :headers="uploadHeaders" :show-file-list="false" :on-success="onSuccess" :on-error="onError" :before-upload="beforeUpload">
                   <div v-if="!cover" class="upload-placeholder">
                     <ElIcon class="upload-icon"><Plus /></ElIcon>
                     <div class="upload-text">点击上传封面</div>

+ 1 - 1
src/views/train/monitor/course.vue

@@ -3,7 +3,7 @@
 @creationTime: 2025-09-23
 -->
 <template>
-  <div class="app-container w-full art-full-height">
+  <div class="app-container art-full-height w-full">
     <div class="header">
       <el-button type="primary" @click="publish" round>发布</el-button>
     </div>

+ 9 - 8
src/views/train/monitor/device.vue

@@ -1,17 +1,18 @@
 <!--
-@description: 设备监控
-@creationTime: 2025-09-23
+@description: 设备视图
+@creationTime: 2025-09-17
 -->
-
 <template>
-  <div>设备监控</div>
+  <div class="art-full-height w-full">
+    <Meta2dView :data="data" :preview="true" />
+  </div>
 </template>
 
 <script lang="ts" setup>
-  defineOptions({ name: '设备监控' })
-  /* ------------------------ 导入 与 引用 ----------------------------------- */
-  /* ------------------------ 函数 与 方法 ----------------------------------- */
-  /* ------------------------- 生命周期 -------------------------------------- */
+  import Meta2dView from '@/components/business/meta2d/Meta2dView.vue'
+  defineOptions({ name: 'Device' })
+
+  import data from './data/data.json'
 </script>
 
 <style lang="scss" scoped></style>

+ 1 - 1
src/views/train/plan/index.vue

@@ -13,7 +13,7 @@
         <i class="iconfont-sys clear-icon" @click.stop="clearIcon">&#xe83a;</i>
       </div>
     </div>
-    <div class="flex gap-4 mt-4 items-center">
+    <div class="mt-4 flex items-center gap-4">
       <i class="iconfont-sys">&#xe83a;</i>
       <Icon :icon="'svg:download'" />
       <Icon :icon="'svg:gitee'" />