于添 hai 8 meses
pai
achega
2dc5f2d6fe

+ 279 - 28
pnpm-lock.yaml

@@ -23,6 +23,24 @@ importers:
       '@chenfengyuan/vue-qrcode':
         specifier: 2.0.0
         version: 2.0.0(qrcode@1.5.1)(vue@3.2.44)
+      '@codemirror/lang-css':
+        specifier: ^6.3.1
+        version: 6.3.1
+      '@codemirror/lang-html':
+        specifier: ^6.4.9
+        version: 6.4.9
+      '@codemirror/lang-javascript':
+        specifier: ^6.2.4
+        version: 6.2.4
+      '@codemirror/lang-json':
+        specifier: ^6.0.2
+        version: 6.0.2
+      '@codemirror/lang-xml':
+        specifier: ^6.1.0
+        version: 6.1.0
+      '@codemirror/theme-one-dark':
+        specifier: ^6.1.3
+        version: 6.1.3
       '@highlightjs/vue-plugin':
         specifier: 2.1.0
         version: 2.1.0(highlight.js@11.6.0)(vue@3.2.44)
@@ -44,9 +62,9 @@ importers:
       axios:
         specifier: 1.1.3
         version: 1.1.3
-      codemirror-editor-vue3:
-        specifier: ^2.8.0
-        version: 2.8.0(codemirror@5.65.19)(diff-match-patch@1.0.5)(vue@3.2.44)
+      codemirror:
+        specifier: ^6.0.2
+        version: 6.0.2
       cropperjs:
         specifier: 1.5.12
         version: 1.5.12
@@ -87,8 +105,8 @@ importers:
         specifier: 4.17.21
         version: 4.17.21
       mavon-editor:
-        specifier: ^2.10.4
-        version: 2.10.4
+        specifier: ^3.0.1
+        version: 3.0.2
       nprogress:
         specifier: 0.2.0
         version: 0.2.0
@@ -112,7 +130,7 @@ importers:
         version: 1.1.0
       snowy-form-design:
         specifier: 1.1.9-Bata-02
-        version: 1.1.9-Bata-02(@aesoper/normal-utils@0.1.5)(@ant-design/icons-vue@6.1.0(vue@3.2.44))(@popperjs/core@2.11.8)(@vueuse/core@6.9.2(vue@3.2.44))(ant-design-vue@3.2.14(vue@3.2.44))(codemirror@5.65.19)(diff-match-patch@1.0.5)(gradient-parser@1.1.1)(lodash-es@4.17.21)(tinycolor2@1.6.0)(vue-types@4.2.1(vue@3.2.44))(vue3-angle@0.1.6(vue@3.2.44))(vue3-normal-library@0.1.6(@vue/compiler-sfc@3.2.47)(vue@3.2.44))(vue@3.2.44)
+        version: 1.1.9-Bata-02(@aesoper/normal-utils@0.1.5)(@ant-design/icons-vue@6.1.0(vue@3.2.44))(@popperjs/core@2.11.8)(@vueuse/core@6.9.2(vue@3.2.44))(ant-design-vue@3.2.14(vue@3.2.44))(codemirror@6.0.2)(diff-match-patch@1.0.5)(gradient-parser@1.1.1)(lodash-es@4.17.21)(tinycolor2@1.6.0)(vue-types@4.2.1(vue@3.2.44))(vue3-angle@0.1.6(vue@3.2.44))(vue3-normal-library@0.1.6(@vue/compiler-sfc@3.2.47)(vue@3.2.44))(vue@3.2.44)
       sortablejs:
         specifier: 1.15.0
         version: 1.15.0
@@ -128,6 +146,9 @@ importers:
       vue:
         specifier: 3.2.44
         version: 3.2.44
+      vue-codemirror:
+        specifier: ^6.1.1
+        version: 6.1.1(codemirror@6.0.2)(vue@3.2.44)
       vue-cropper:
         specifier: 1.0.5
         version: 1.0.5
@@ -476,6 +497,45 @@ packages:
       qrcode: ^1.5.0
       vue: ^3.0.0
 
+  '@codemirror/autocomplete@6.18.6':
+    resolution: {integrity: sha512-PHHBXFomUs5DF+9tCOM/UoW6XQ4R44lLNNhRaW9PKPTU0D7lIjRg3ElxaJnTwsl/oHiR93WSXDBrekhoUGCPtg==}
+
+  '@codemirror/commands@6.8.1':
+    resolution: {integrity: sha512-KlGVYufHMQzxbdQONiLyGQDUW0itrLZwq3CcY7xpv9ZLRHqzkBSoteocBHtMCoY7/Ci4xhzSrToIeLg7FxHuaw==}
+
+  '@codemirror/lang-css@6.3.1':
+    resolution: {integrity: sha512-kr5fwBGiGtmz6l0LSJIbno9QrifNMUusivHbnA1H6Dmqy4HZFte3UAICix1VuKo0lMPKQr2rqB+0BkKi/S3Ejg==}
+
+  '@codemirror/lang-html@6.4.9':
+    resolution: {integrity: sha512-aQv37pIMSlueybId/2PVSP6NPnmurFDVmZwzc7jszd2KAF8qd4VBbvNYPXWQq90WIARjsdVkPbw29pszmHws3Q==}
+
+  '@codemirror/lang-javascript@6.2.4':
+    resolution: {integrity: sha512-0WVmhp1QOqZ4Rt6GlVGwKJN3KW7Xh4H2q8ZZNGZaP6lRdxXJzmjm4FqvmOojVj6khWJHIb9sp7U/72W7xQgqAA==}
+
+  '@codemirror/lang-json@6.0.2':
+    resolution: {integrity: sha512-x2OtO+AvwEHrEwR0FyyPtfDUiloG3rnVTSZV1W8UteaLL8/MajQd8DpvUb2YVzC+/T18aSDv0H9mu+xw0EStoQ==}
+
+  '@codemirror/lang-xml@6.1.0':
+    resolution: {integrity: sha512-3z0blhicHLfwi2UgkZYRPioSgVTo9PV5GP5ducFH6FaHy0IAJRg+ixj5gTR1gnT/glAIC8xv4w2VL1LoZfs+Jg==}
+
+  '@codemirror/language@6.11.1':
+    resolution: {integrity: sha512-5kS1U7emOGV84vxC+ruBty5sUgcD0te6dyupyRVG2zaSjhTDM73LhVKUtVwiqSe6QwmEoA4SCiU8AKPFyumAWQ==}
+
+  '@codemirror/lint@6.8.5':
+    resolution: {integrity: sha512-s3n3KisH7dx3vsoeGMxsbRAgKe4O1vbrnKBClm99PU0fWxmxsx5rR2PfqQgIt+2MMJBHbiJ5rfIdLYfB9NNvsA==}
+
+  '@codemirror/search@6.5.11':
+    resolution: {integrity: sha512-KmWepDE6jUdL6n8cAAqIpRmLPBZ5ZKnicE8oGU/s3QrAVID+0VhLFrzUucVKHG5035/BSykhExDL/Xm7dHthiA==}
+
+  '@codemirror/state@6.5.2':
+    resolution: {integrity: sha512-FVqsPqtPWKVVL3dPSxy8wEF/ymIEuVzF1PK3VbUgrxXpJUSHQWWZz4JMToquRxnkw+36LTamCZG2iua2Ptq0fA==}
+
+  '@codemirror/theme-one-dark@6.1.3':
+    resolution: {integrity: sha512-NzBdIvEJmx6fjeremiGp3t/okrLPYT0d9orIc7AFun8oZcRk58aejkqhv6spnz4MLAevrKNPMQYXEWMg4s+sKA==}
+
+  '@codemirror/view@6.37.2':
+    resolution: {integrity: sha512-XD3LdgQpxQs5jhOOZ2HRVT+Rj59O4Suc7g2ULvZ+Yi8eCkickrkZ5JFuoDhs2ST1mNI5zSsNYgR3NGa4OUrbnw==}
+
   '@ctrl/tinycolor@3.6.1':
     resolution: {integrity: sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==}
     engines: {node: '>=10'}
@@ -686,6 +746,30 @@ packages:
   '@jridgewell/trace-mapping@0.3.25':
     resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==}
 
+  '@lezer/common@1.2.3':
+    resolution: {integrity: sha512-w7ojc8ejBqr2REPsWxJjrMFsA/ysDCFICn8zEOR9mrqzOu2amhITYuLD8ag6XZf0CFXDrhKqw7+tW8cX66NaDA==}
+
+  '@lezer/css@1.2.1':
+    resolution: {integrity: sha512-2F5tOqzKEKbCUNraIXc0f6HKeyKlmMWJnBB0i4XW6dJgssrZO/YlZ2pY5xgyqDleqqhiNJ3dQhbrV2aClZQMvg==}
+
+  '@lezer/highlight@1.2.1':
+    resolution: {integrity: sha512-Z5duk4RN/3zuVO7Jq0pGLJ3qynpxUVsh7IbUbGj88+uV2ApSAn6kWg2au3iJb+0Zi7kKtqffIESgNcRXWZWmSA==}
+
+  '@lezer/html@1.3.10':
+    resolution: {integrity: sha512-dqpT8nISx/p9Do3AchvYGV3qYc4/rKr3IBZxlHmpIKam56P47RSHkSF5f13Vu9hebS1jM0HmtJIwLbWz1VIY6w==}
+
+  '@lezer/javascript@1.5.1':
+    resolution: {integrity: sha512-ATOImjeVJuvgm3JQ/bpo2Tmv55HSScE2MTPnKRMRIPx2cLhHGyX2VnqpHhtIV1tVzIjZDbcWQm+NCTF40ggZVw==}
+
+  '@lezer/json@1.0.3':
+    resolution: {integrity: sha512-BP9KzdF9Y35PDpv04r0VeSTKDeox5vVr3efE7eBbx3r4s3oNLfunchejZhjArmeieBH+nVOpgIiBJpEAv8ilqQ==}
+
+  '@lezer/lr@1.4.2':
+    resolution: {integrity: sha512-pu0K1jCIdnQ12aWNaAVU5bzi7Bd1w54J3ECgANPmYLtQKP0HBj2cE/5coBD66MT10xbtIuUr7tg0Shbsvk0mDA==}
+
+  '@lezer/xml@1.0.6':
+    resolution: {integrity: sha512-CdDwirL0OEaStFue/66ZmFSeppuL6Dwjlk8qk153mSQwiSH/Dlri4GNymrNWnUmPl2Um7QfV1FO9KFUyX3Twww==}
+
   '@ljharb/resumer@0.0.1':
     resolution: {integrity: sha512-skQiAOrCfO7vRTq53cxznMpks7wS1va95UCidALlOVWqvBAzwPVErwizDwoMqNVMEn1mDq0utxZd02eIrvF1lw==}
     engines: {node: '>= 0.4'}
@@ -694,6 +778,9 @@ packages:
     resolution: {integrity: sha512-ajBvlKpWucBB17FuQYUShqpqy8GRgYEpJW0vWJbUu1CV9lWyrDCapy0lScU8T8Z6qn49sSwJB3+M+evYIdGg+A==}
     engines: {node: '>= 0.4'}
 
+  '@marijn/find-cluster-break@1.0.2':
+    resolution: {integrity: sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==}
+
   '@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1':
     resolution: {integrity: sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==}
 
@@ -1255,15 +1342,8 @@ packages:
       diff-match-patch: ^1.0.5
       vue: ^3.x
 
-  codemirror-editor-vue3@2.8.0:
-    resolution: {integrity: sha512-ebYGNhBpLmQNLguXzNyMMkn6K8v3lcS5/Ncvdn6YS4bLGEHE67MfsJIS/WV0L7I6WavUuFlY/Rs/AJKChIwSwg==}
-    peerDependencies:
-      codemirror: ^5
-      diff-match-patch: ^1.0.5
-      vue: ^3.x
-
-  codemirror@5.65.19:
-    resolution: {integrity: sha512-+aFkvqhaAVr1gferNMuN8vkTSrWIFvzlMV9I2KBLCWS2WpZ2+UAkZjlMZmEuT+gcXTi6RrGQCkWq1/bDtGqhIA==}
+  codemirror@6.0.2:
+    resolution: {integrity: sha512-VhydHotNW5w1UGK0Qj96BwSk/Zqbp9WbnyK2W/eVMv4QyF41INRGpjUhFJY7/uDNuudSc33a/PKr4iDqRduvHw==}
 
   color-convert@2.0.1:
     resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
@@ -1307,6 +1387,9 @@ packages:
   core-js@3.43.0:
     resolution: {integrity: sha512-N6wEbTTZSYOY2rYAn85CuvWWkCK6QweMn7/4Nr3w+gDBeBhk/x4EJeY6FPo4QzDoJZxVTv8U7CMvgWk6pOHHqA==}
 
+  crelt@1.0.6:
+    resolution: {integrity: sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==}
+
   cropperjs@1.5.12:
     resolution: {integrity: sha512-re7UdjE5UnwdrovyhNzZ6gathI4Rs3KGCBSc8HCIjUo5hO42CtzyblmWLj6QWVw7huHyDMfpKxhiO2II77nhDw==}
 
@@ -2360,8 +2443,8 @@ packages:
     resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
     engines: {node: '>= 0.4'}
 
-  mavon-editor@2.10.4:
-    resolution: {integrity: sha512-CFsBLkgt/KZBDg+SJYe2fyYv4zClY149PiwpH0rDAiiP4ae1XNs0GC8nBsoTeipsHcebDLN1QMkt3bUsnMDjQw==}
+  mavon-editor@3.0.2:
+    resolution: {integrity: sha512-QmmsypznEkru3Gj9u/i3OLs7uWOwrAUDyLAiQnl7bj2lvZZ++J7MPA+Al0G26cQZ8GwzyC69T5l6NQjZ2z1Nuw==}
 
   mdast-util-from-markdown@0.8.5:
     resolution: {integrity: sha512-2hkTXtYYnr+NubD/g6KGBS/0mFmBcifAsI0yIWRiRo0PjVs6SSOSOdtzbp6kSGnShDN6G5aWZpKQ2lWRy27mWQ==}
@@ -3043,6 +3126,9 @@ packages:
   strip-literal@2.1.1:
     resolution: {integrity: sha512-631UJ6O00eNGfMiWG78ck80dfBab8X6IVFB51jZK5Icd7XAs60Z5y7QdSd/wGIklnWvRbUNloVzhOKKmutxQ6Q==}
 
+  style-mod@4.1.2:
+    resolution: {integrity: sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==}
+
   supports-color@2.0.0:
     resolution: {integrity: sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==}
     engines: {node: '>=0.8.0'}
@@ -3268,6 +3354,12 @@ packages:
       terser:
         optional: true
 
+  vue-codemirror@6.1.1:
+    resolution: {integrity: sha512-rTAYo44owd282yVxKtJtnOi7ERAcXTeviwoPXjIc6K/IQYUsoDkzPvw/JDFtSP6T7Cz/2g3EHaEyeyaQCKoDMg==}
+    peerDependencies:
+      codemirror: 6.x
+      vue: 3.x
+
   vue-cropper@1.0.5:
     resolution: {integrity: sha512-D4XXdqWmMWRLOIV9LIh7/mkH6OBOMQDFbRjwntkxmAtxOtwpC9U5ZZ6lSXw5F5cbd4g8znDjk6MuCwIL+fZSrA==}
 
@@ -3358,6 +3450,9 @@ packages:
     peerDependencies:
       vue: ^3.2.31
 
+  w3c-keyname@2.2.8:
+    resolution: {integrity: sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==}
+
   warning@4.0.3:
     resolution: {integrity: sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==}
 
@@ -3905,6 +4000,103 @@ snapshots:
       qrcode: 1.5.1
       vue: 3.2.44
 
+  '@codemirror/autocomplete@6.18.6':
+    dependencies:
+      '@codemirror/language': 6.11.1
+      '@codemirror/state': 6.5.2
+      '@codemirror/view': 6.37.2
+      '@lezer/common': 1.2.3
+
+  '@codemirror/commands@6.8.1':
+    dependencies:
+      '@codemirror/language': 6.11.1
+      '@codemirror/state': 6.5.2
+      '@codemirror/view': 6.37.2
+      '@lezer/common': 1.2.3
+
+  '@codemirror/lang-css@6.3.1':
+    dependencies:
+      '@codemirror/autocomplete': 6.18.6
+      '@codemirror/language': 6.11.1
+      '@codemirror/state': 6.5.2
+      '@lezer/common': 1.2.3
+      '@lezer/css': 1.2.1
+
+  '@codemirror/lang-html@6.4.9':
+    dependencies:
+      '@codemirror/autocomplete': 6.18.6
+      '@codemirror/lang-css': 6.3.1
+      '@codemirror/lang-javascript': 6.2.4
+      '@codemirror/language': 6.11.1
+      '@codemirror/state': 6.5.2
+      '@codemirror/view': 6.37.2
+      '@lezer/common': 1.2.3
+      '@lezer/css': 1.2.1
+      '@lezer/html': 1.3.10
+
+  '@codemirror/lang-javascript@6.2.4':
+    dependencies:
+      '@codemirror/autocomplete': 6.18.6
+      '@codemirror/language': 6.11.1
+      '@codemirror/lint': 6.8.5
+      '@codemirror/state': 6.5.2
+      '@codemirror/view': 6.37.2
+      '@lezer/common': 1.2.3
+      '@lezer/javascript': 1.5.1
+
+  '@codemirror/lang-json@6.0.2':
+    dependencies:
+      '@codemirror/language': 6.11.1
+      '@lezer/json': 1.0.3
+
+  '@codemirror/lang-xml@6.1.0':
+    dependencies:
+      '@codemirror/autocomplete': 6.18.6
+      '@codemirror/language': 6.11.1
+      '@codemirror/state': 6.5.2
+      '@codemirror/view': 6.37.2
+      '@lezer/common': 1.2.3
+      '@lezer/xml': 1.0.6
+
+  '@codemirror/language@6.11.1':
+    dependencies:
+      '@codemirror/state': 6.5.2
+      '@codemirror/view': 6.37.2
+      '@lezer/common': 1.2.3
+      '@lezer/highlight': 1.2.1
+      '@lezer/lr': 1.4.2
+      style-mod: 4.1.2
+
+  '@codemirror/lint@6.8.5':
+    dependencies:
+      '@codemirror/state': 6.5.2
+      '@codemirror/view': 6.37.2
+      crelt: 1.0.6
+
+  '@codemirror/search@6.5.11':
+    dependencies:
+      '@codemirror/state': 6.5.2
+      '@codemirror/view': 6.37.2
+      crelt: 1.0.6
+
+  '@codemirror/state@6.5.2':
+    dependencies:
+      '@marijn/find-cluster-break': 1.0.2
+
+  '@codemirror/theme-one-dark@6.1.3':
+    dependencies:
+      '@codemirror/language': 6.11.1
+      '@codemirror/state': 6.5.2
+      '@codemirror/view': 6.37.2
+      '@lezer/highlight': 1.2.1
+
+  '@codemirror/view@6.37.2':
+    dependencies:
+      '@codemirror/state': 6.5.2
+      crelt: 1.0.6
+      style-mod: 4.1.2
+      w3c-keyname: 2.2.8
+
   '@ctrl/tinycolor@3.6.1': {}
 
   '@esbuild/android-arm64@0.17.19':
@@ -4056,6 +4248,46 @@ snapshots:
       '@jridgewell/resolve-uri': 3.1.2
       '@jridgewell/sourcemap-codec': 1.5.0
 
+  '@lezer/common@1.2.3': {}
+
+  '@lezer/css@1.2.1':
+    dependencies:
+      '@lezer/common': 1.2.3
+      '@lezer/highlight': 1.2.1
+      '@lezer/lr': 1.4.2
+
+  '@lezer/highlight@1.2.1':
+    dependencies:
+      '@lezer/common': 1.2.3
+
+  '@lezer/html@1.3.10':
+    dependencies:
+      '@lezer/common': 1.2.3
+      '@lezer/highlight': 1.2.1
+      '@lezer/lr': 1.4.2
+
+  '@lezer/javascript@1.5.1':
+    dependencies:
+      '@lezer/common': 1.2.3
+      '@lezer/highlight': 1.2.1
+      '@lezer/lr': 1.4.2
+
+  '@lezer/json@1.0.3':
+    dependencies:
+      '@lezer/common': 1.2.3
+      '@lezer/highlight': 1.2.1
+      '@lezer/lr': 1.4.2
+
+  '@lezer/lr@1.4.2':
+    dependencies:
+      '@lezer/common': 1.2.3
+
+  '@lezer/xml@1.0.6':
+    dependencies:
+      '@lezer/common': 1.2.3
+      '@lezer/highlight': 1.2.1
+      '@lezer/lr': 1.4.2
+
   '@ljharb/resumer@0.0.1':
     dependencies:
       '@ljharb/through': 2.3.14
@@ -4064,6 +4296,8 @@ snapshots:
     dependencies:
       call-bind: 1.0.8
 
+  '@marijn/find-cluster-break@1.0.2': {}
+
   '@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1':
     dependencies:
       eslint-scope: 5.1.1
@@ -4764,19 +4998,21 @@ snapshots:
 
   clone@2.1.2: {}
 
-  codemirror-editor-vue3@2.3.0(codemirror@5.65.19)(diff-match-patch@1.0.5)(vue@3.2.44):
+  codemirror-editor-vue3@2.3.0(codemirror@6.0.2)(diff-match-patch@1.0.5)(vue@3.2.44):
     dependencies:
-      codemirror: 5.65.19
+      codemirror: 6.0.2
       diff-match-patch: 1.0.5
       vue: 3.2.44
 
-  codemirror-editor-vue3@2.8.0(codemirror@5.65.19)(diff-match-patch@1.0.5)(vue@3.2.44):
+  codemirror@6.0.2:
     dependencies:
-      codemirror: 5.65.19
-      diff-match-patch: 1.0.5
-      vue: 3.2.44
-
-  codemirror@5.65.19: {}
+      '@codemirror/autocomplete': 6.18.6
+      '@codemirror/commands': 6.8.1
+      '@codemirror/language': 6.11.1
+      '@codemirror/lint': 6.8.5
+      '@codemirror/search': 6.5.11
+      '@codemirror/state': 6.5.2
+      '@codemirror/view': 6.37.2
 
   color-convert@2.0.1:
     dependencies:
@@ -4810,6 +5046,8 @@ snapshots:
 
   core-js@3.43.0: {}
 
+  crelt@1.0.6: {}
+
   cropperjs@1.5.12: {}
 
   cross-spawn@7.0.6:
@@ -5968,7 +6206,7 @@ snapshots:
 
   math-intrinsics@1.1.0: {}
 
-  mavon-editor@2.10.4:
+  mavon-editor@3.0.2:
     dependencies:
       xss: 1.0.15
 
@@ -6566,13 +6804,13 @@ snapshots:
     dependencies:
       babel-runtime: 6.26.0
 
-  snowy-form-design@1.1.9-Bata-02(@aesoper/normal-utils@0.1.5)(@ant-design/icons-vue@6.1.0(vue@3.2.44))(@popperjs/core@2.11.8)(@vueuse/core@6.9.2(vue@3.2.44))(ant-design-vue@3.2.14(vue@3.2.44))(codemirror@5.65.19)(diff-match-patch@1.0.5)(gradient-parser@1.1.1)(lodash-es@4.17.21)(tinycolor2@1.6.0)(vue-types@4.2.1(vue@3.2.44))(vue3-angle@0.1.6(vue@3.2.44))(vue3-normal-library@0.1.6(@vue/compiler-sfc@3.2.47)(vue@3.2.44))(vue@3.2.44):
+  snowy-form-design@1.1.9-Bata-02(@aesoper/normal-utils@0.1.5)(@ant-design/icons-vue@6.1.0(vue@3.2.44))(@popperjs/core@2.11.8)(@vueuse/core@6.9.2(vue@3.2.44))(ant-design-vue@3.2.14(vue@3.2.44))(codemirror@6.0.2)(diff-match-patch@1.0.5)(gradient-parser@1.1.1)(lodash-es@4.17.21)(tinycolor2@1.6.0)(vue-types@4.2.1(vue@3.2.44))(vue3-angle@0.1.6(vue@3.2.44))(vue3-normal-library@0.1.6(@vue/compiler-sfc@3.2.47)(vue@3.2.44))(vue@3.2.44):
     dependencies:
       '@ant-design/icons-vue': 6.1.0(vue@3.2.44)
       '@vueup/vue-quill': 1.0.0-alpha.38(vue@3.2.44)
       ant-design-vue: 3.2.14(vue@3.2.44)
       clipboard: 2.0.11
-      codemirror-editor-vue3: 2.3.0(codemirror@5.65.19)(diff-match-patch@1.0.5)(vue@3.2.44)
+      codemirror-editor-vue3: 2.3.0(codemirror@6.0.2)(diff-match-patch@1.0.5)(vue@3.2.44)
       dayjs: 1.11.7
       default-passive-events: 2.0.0
       lodash-es: 4.17.21
@@ -6689,6 +6927,8 @@ snapshots:
     dependencies:
       js-tokens: 9.0.1
 
+  style-mod@4.1.2: {}
+
   supports-color@2.0.0: {}
 
   supports-color@7.2.0:
@@ -6983,6 +7223,15 @@ snapshots:
       less: 4.1.3
       terser: 5.42.0
 
+  vue-codemirror@6.1.1(codemirror@6.0.2)(vue@3.2.44):
+    dependencies:
+      '@codemirror/commands': 6.8.1
+      '@codemirror/language': 6.11.1
+      '@codemirror/state': 6.5.2
+      '@codemirror/view': 6.37.2
+      codemirror: 6.0.2
+      vue: 3.2.44
+
   vue-cropper@1.0.5: {}
 
   vue-demi@0.13.11(vue@3.2.44):
@@ -7077,6 +7326,8 @@ snapshots:
       sortablejs: 1.14.0
       vue: 3.2.44
 
+  w3c-keyname@2.2.8: {}
+
   warning@4.0.3:
     dependencies:
       loose-envify: 1.4.0

+ 42 - 0
src/router/fullPageTool.js

@@ -0,0 +1,42 @@
+/**
+ *  Copyright [2022] [https://www.xiaonuo.vip]
+ *	Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
+ *	1.请不要删除和修改根目录下的LICENSE文件。
+ *	2.请不要删除和修改Snowy源码头部的版权声明。
+ *	3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。
+ *	4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip
+ *	5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
+ *	6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip
+ */
+const fullPageTool = {
+	//检查
+	check(to) {
+		//如果在这个列表里就设置可以全屏
+		this.fullPageList.forEach((item) => {
+			if (to.path.includes(item.path)) {
+				to.meta.fullpage = true
+			}
+		})
+	},
+	fullPageList: [
+		{
+			path: '/portal'
+		},
+		{
+			path: '/portal/resourceCenter'
+		},
+		{
+			path: '/portal/resourceDetails'
+		}
+	]
+}
+/**
+ * 路由白名单(数组形式)
+ *
+ * 如果组件像登录一样,那就简单的写一个path,即可实现放开,
+ * 如果组件不在这边的,需要手动添加组件,就像other一样,
+ * 因为没登陆你没法拿到后端给你返回的那一坨,当然就找不到component
+ *
+ * @author yubaoshan
+ */
+export default fullPageTool

+ 5 - 2
src/router/index.js

@@ -15,8 +15,10 @@ import 'nprogress/nprogress.css'
 import systemRouter from './systemRouter'
 import { afterEach, beforeEach } from './scrollBehavior'
 import whiteListRouters from './whiteList'
+import portal from './portal'
 import userRoutes from '@/config/route'
 import tool from '@/utils/tool'
+import fullPageTool from './fullPageTool'
 import { cloneDeep } from 'lodash-es'
 const modules = import.meta.glob('/src/views/**/**.vue')
 import { globalStore, searchStore } from '@/store'
@@ -90,6 +92,7 @@ router.beforeEach(async (to, from, next) => {
 			// 有token的时候才保存登录之前要访问的页面
 			tool.data.set('LAST_VIEWS_PATH', to.fullPath)
 		}
+		fullPageTool.check(to)
 	}
 	if (!token) {
 		next({
@@ -109,7 +112,7 @@ router.beforeEach(async (to, from, next) => {
 			apiMenu[0] = cloneDeep(userRoutes.module[0])
 		}
 		const childrenApiMenu = apiMenu[0].children
-		apiMenu[0].children = [...childrenApiMenu ? childrenApiMenu : [], ...userRoutes.menu]
+		apiMenu[0].children = [...(childrenApiMenu ? childrenApiMenu : []), ...userRoutes.menu]
 		let menuRouter = filterAsyncRouter(apiMenu)
 		menuRouter = flatAsyncRoutes(menuRouter)
 		menuRouter.forEach((item) => {
@@ -148,7 +151,7 @@ router.getMenu = () => {
 		apiMenu[0] = cloneDeep(userRoutes.module[0])
 	}
 	const childrenApiMenu = apiMenu[0].children
-	apiMenu[0].children = [...childrenApiMenu ? childrenApiMenu : [], ...userRoutes.menu]
+	apiMenu[0].children = [...(childrenApiMenu ? childrenApiMenu : []), ...userRoutes.menu]
 	return filterUrl(apiMenu)
 }
 

+ 39 - 0
src/router/portal.js

@@ -0,0 +1,39 @@
+/**
+ *  Copyright [2022] [https://www.xiaonuo.vip]
+ *	Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
+ *	1.请不要删除和修改根目录下的LICENSE文件。
+ *	2.请不要删除和修改Snowy源码头部的版权声明。
+ *	3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。
+ *	4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip
+ *	5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
+ *	6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip
+ */
+const portal = [
+	{
+		name: 'portal',
+		path: '/portal',
+		components: () => import('@/portal/index.vue'),
+		children: [
+			{
+				name: 'resourceCenter',
+				path: '/portal/resourceCenter',
+				component: () => import('@/resourceCenter/index.vue')
+			},
+			{
+				name: 'resourceDetails',
+				path: '/portal/resourceDetails',
+				component: () => import('@/resourceDetails/index.vue')
+			}
+		]
+	}
+]
+/**
+ * 路由白名单(数组形式)
+ *
+ * 如果组件像登录一样,那就简单的写一个path,即可实现放开,
+ * 如果组件不在这边的,需要手动添加组件,就像other一样,
+ * 因为没登陆你没法拿到后端给你返回的那一坨,当然就找不到component
+ *
+ * @author yubaoshan
+ */
+export default portal

+ 0 - 1
src/views/myResources/index.vue

@@ -428,7 +428,6 @@
 	// 上传资源模态框
 	const uploadModalVisible = ref(false)
 
-
 	// 显示上传模态框
 	const showUploadModal = () => {
 		uploadModalVisible.value = true

+ 32 - 0
src/views/portal/components/BreadCrumb.vue

@@ -0,0 +1,32 @@
+<template>
+	<div style="margin-top: 10px; margin-bottom: 10px">
+		<a-breadcrumb>
+			<a-breadcrumb-item
+				v-for="(item, index) in list"
+				:key="index"
+				style="cursor: pointer"
+				@click="handleItem(index)"
+				>{{ item }}</a-breadcrumb-item
+			>
+		</a-breadcrumb>
+	</div>
+</template>
+
+<script setup>
+	import { ref } from 'vue'
+	const list = ref(['首页', '资源中心'])
+	const selectedCourse = ref('all')
+
+	const handleItem = (index) => {
+		console.log('点了第几个了', index)
+	}
+</script>
+
+<style scoped>
+	.filter-bar {
+		padding: 20px;
+	}
+	.filter-group {
+		margin-bottom: 10px;
+	}
+</style>

+ 31 - 0
src/views/portal/components/Footer.vue

@@ -0,0 +1,31 @@
+<template>
+	<footer class="footer">
+		<div class="footer-links">
+			<a href="#">网站首页</a>
+			<a href="#">帮助中心</a>
+			<a href="#">联系我们</a>
+			<a href="#">招聘信息</a>
+			<a href="#">客户服务</a>
+		</div>
+		<div class="footer-info">Copyright © www.AxureUX.com, All Rights Reserved.</div>
+	</footer>
+</template>
+
+<script setup></script>
+
+<style scoped>
+	.footer {
+		padding: 20px;
+		text-align: center;
+		background-color: #f8f8f8;
+		border-top: 1px solid #eaeaea;
+	}
+	.footer-links a {
+		margin: 0 10px;
+		color: #999;
+	}
+	.footer-info {
+		margin-top: 10px;
+		color: #666;
+	}
+</style>

+ 74 - 0
src/views/portal/components/Header.vue

@@ -0,0 +1,74 @@
+<template>
+	<div>
+		<div style="display: flex; width: 100vw; justify-content: space-between; align-items: center">
+			<div style="display: flex; padding-left: 10%">
+				<div style="width: 120px; height: 55px; background-color: brown" />
+				<a-menu v-model:selectedKeys="current" mode="horizontal" theme="light" style="line-height: 55px">
+					<a-menu-item style="margin-left: 10px; margin-right: 10px" key="1">首页</a-menu-item>
+					<a-menu-item style="margin-left: 10px; margin-right: 10px" key="resourceCenter">资源中心</a-menu-item>
+					<a-menu-item style="margin-left: 10px; margin-right: 10px" key="resourceDetails">资源管理</a-menu-item>
+				</a-menu>
+			</div>
+
+			<div class="header-right">
+				<!-- <a-input-search placeholder="输入关键词搜索" style="width: 200px" /> -->
+				<div style="display: flex">
+					<SearchOutlined :style="{ fontSize: '16px', color: '#00000083' }" />
+					<div style="width: 5px"></div>
+					<span style="font-size: 12px; color: #00000083">搜索</span>
+				</div>
+				<div style="width: 20px"></div>
+				<div style="display: flex">
+					<UserOutlined :style="{ fontSize: '16px', color: '#00000083' }" />
+					<div style="width: 5px"></div>
+					<span style="font-size: 12px; color: #00000083">登录</span>
+				</div>
+				<div style="width: 20px"></div>
+				<div style="display: flex">
+					<span style="font-size: 12px; color: #00000083">注册</span>
+				</div>
+				<!-- <a-button type="primary">登录</a-button>
+				<a-button>注册</a-button> -->
+			</div>
+		</div>
+		<div class="line" style=""></div>
+	</div>
+</template>
+
+<script setup>
+	import { ref } from 'vue'
+	const current = ref(['2']) // 默认选中“资源中心”
+
+	const emit = defineEmits(['onChangeCurrent'])
+
+	watch(
+		() => current.value,
+		(newVal, oldVal) => {
+			console.log('新的是', newVal, '旧的是', oldVal)
+			if (newVal != oldVal) {
+				emit('onChangeCurrent', newVal)
+			}
+		}
+	)
+</script>
+
+<style scoped>
+	.header {
+		display: flex;
+		align-items: center;
+		justify-content: space-between;
+		padding: 0 50px;
+	}
+	.header-right {
+		display: flex;
+		align-items: center;
+
+		margin-right: 20%;
+	}
+
+	.line {
+		width: 100%;
+		height: 0.25px;
+		background-color: #00000013;
+	}
+</style>

+ 42 - 0
src/views/portal/index.vue

@@ -0,0 +1,42 @@
+<template>
+	<div style="overflow-y: auto">
+		<a-layout>
+			<Header @onChangeCurrent="onChangeCurrent" />
+			<div style="width: 71%; margin-left: 10%">
+				<BreadCrumb />
+				<ResourceCenter v-if="indexType == 'resourceCenter'" />
+				<ResourceDetails v-if="indexType == 'resourceDetails'" />
+			</div>
+		</a-layout>
+		<Footer />
+	</div>
+</template>
+
+<script setup>
+	import Header from './components/Header.vue'
+	import BreadCrumb from './components/BreadCrumb.vue'
+	import Footer from './components/Footer.vue'
+	import ResourceCenter from '@/views/resourceCenter/index.vue'
+	import ResourceDetails from '@/views/resourceDetails/index.vue'
+
+	const indexType = ref('resourceDetails')
+
+	const onChangeCurrent = (current) => {
+		indexType.value = current
+	}
+
+	const handlerItemSidebar = (item) => {
+		// emit('handlerItemSidebar', item)
+	}
+
+	const handlerItemCorrelation = (item) => {
+		// emit('handlerItemSidebar', item)
+	}
+</script>
+
+<style scoped>
+	.content {
+		/* padding-left: 10%;
+		padding-right: 30%; */
+	}
+</style>

+ 257 - 0
src/views/resourceCenter/components/ComplexChoices.vue

@@ -0,0 +1,257 @@
+<template>
+	<div class="filter-bar">
+		<!-- 所选院系 -->
+		<div class="filter-group">
+			<span class="filter-group-title">所选院系:</span>
+			<!-- <a-radio-group v-model:value="selectedDept" >
+				<a-radio-button v-for="dept in selectedDepts" :key="dept" :value="dept">{{ dept }}</a-radio-button>
+			</a-radio-group> -->
+			<MyRadioButtonGroup ref="Dept" v-model="selectedDept" @change="handleSelectedDept">
+				<MyRadioButton
+					v-for="(item, index) in selectedDepts"
+					:key="index"
+					:value="item"
+					:label="item"
+					:index="index"
+				></MyRadioButton>
+			</MyRadioButtonGroup>
+		</div>
+		<div style="height: 10px"></div>
+		<div class="line"></div>
+		<div style="height: 10px"></div>
+		<!-- 所属课程 -->
+		<div class="filter-group">
+			<span class="filter-group-title">所选课程:</span>
+			<!-- <a-radio-group v-model:value="selectedCourse" @change="handleSelectedCourses">
+				<a-radio-button v-for="dept in selectedCourses" :key="dept" :value="dept">{{ dept }}</a-radio-button>
+				其他课程选项
+			</a-radio-group> -->
+			<MyRadioButtonGroup ref="Course" v-model="selectedCourse" @change="handleSelectedCourses">
+				<MyRadioButton
+					v-for="(item, index) in selectedCourses"
+					:key="index"
+					:value="item"
+					:label="item"
+					:index="index"
+				></MyRadioButton>
+			</MyRadioButtonGroup>
+		</div>
+		<div style="height: 10px"></div>
+		<div class="line"></div>
+		<div style="height: 10px"></div>
+		<!-- 课程类型和课件格式(联动单选) -->
+		<div class="filter-group">
+			<span class="filter-group-title">课程类型:</span>
+			<!-- <a-radio-group v-model:value="selectedType" @change="handleTypeChange">
+				<a-radio-button v-for="dept in selectedTypes" :key="dept" :value="dept">{{ dept }}</a-radio-button>
+			</a-radio-group> -->
+
+			<MyRadioButtonGroup ref="Type" v-model="selectedType" @change="handleTypeChange">
+				<MyRadioButton
+					v-for="(item, index) in selectedTypes"
+					:key="index"
+					:value="item"
+					:label="item"
+					:index="index"
+				></MyRadioButton>
+			</MyRadioButtonGroup>
+		</div>
+		<div style="height: 10px"></div>
+		<div class="line"></div>
+		<div style="height: 10px"></div>
+		<div class="filter-group">
+			<span class="filter-group-title">课件格式:</span>
+			<!-- <a-radio-group v-model:value="selectedFormat" @change="handleFormatChange">
+				<a-radio-button v-for="dept in selectedFormats" :key="dept" :value="dept">{{ dept }}</a-radio-button>
+			</a-radio-group> -->
+
+			<MyRadioButtonGroup ref="Format" v-model="selectedFormat" @change="handleFormatChange">
+				<MyRadioButton
+					v-for="(item, index) in selectedFormats"
+					:key="item"
+					:value="item"
+					:label="item"
+					:index="index"
+				></MyRadioButton>
+			</MyRadioButtonGroup>
+		</div>
+		<div style="height: 10px"></div>
+		<div class="line"></div>
+		<div style="height: 10px"></div>
+		<!-- 已选条件 -->
+		<div class="filter-group">
+			<span class="filter-group-title">已选条件:</span>
+			<a-tag v-for="tag in selectedTags" :key="tag" closable @close="handleTagClose(tag)">
+				{{ tag }}
+			</a-tag>
+
+			<span v-if="selectedTags.length > 0" class="clean" @click="handleClean">清除筛选</span>
+		</div>
+	</div>
+</template>
+
+<script setup>
+	import { ref, computed } from 'vue'
+	import MyRadioButtonGroup from '../components/MyRadioButtonGroup.vue'
+	import MyRadioButton from '../components/MyRadioButton.vue'
+
+	const selectedDept = ref('')
+	const selectedCourse = ref('')
+	const selectedType = ref('')
+	const selectedFormat = ref('')
+	const Dept = ref(null)
+	const Course = ref(null)
+	const Type = ref(null)
+	const Format = ref(null)
+
+	const selectedTags = ref([])
+	const selectedTagKeys = ref([])
+
+	const selectedDepts = ref([
+		'全部',
+		'航空理论系',
+		'军事理论系',
+		'政治工作系',
+		'机务工程系',
+		'航空机务系',
+		'航空理论系1',
+		'军事理论系1',
+		'政治工作系1',
+		'机务工程系1',
+		'航空机务系1',
+		'航空理论系2',
+		'军事理论系2',
+		'政治工作系2',
+		'机务工程系2',
+		'航空机务系2',
+		'航空理论系3'
+	])
+	const selectedCourses = ref([
+		'全部',
+		'初级飞行训练',
+		'高级飞行训练',
+		'实弹训练',
+		'低空战术飞行',
+		'跨区转场训练',
+		'空气动力学',
+		'航空气象学',
+		'航空电子设备',
+		'飞机结构与系统',
+		'空军作战指挥',
+		'战场态势感知',
+		'模拟对抗训练',
+		'军队政治工作',
+		'军事理论',
+		'战斗精神培育',
+		'机型改装训练',
+		'应急程序训练'
+	])
+	const selectedTypes = ref(['全部', '热门资源', '名师资源', '必修', '选修'])
+	const selectedFormats = ref(['全部', 'ppt', 'word', 'excel', 'pdf', 'mp4', 'zip', 'rar'])
+
+	const handleSelectedDept = (e) => {
+		updateSelectedTags()
+	}
+	const handleSelectedCourses = (e) => {
+		updateSelectedTags()
+	}
+	// 处理课程类型选择变化
+	const handleTypeChange = (e) => {
+		// selectedFormat.value = undefined // 选择课程类型时,重置课件格式
+		updateSelectedTags()
+	}
+
+	// 处理课件格式选择变化
+	const handleFormatChange = (e) => {
+		// selectedType.value = undefined // 选择课件格式时,重置课程类型
+		updateSelectedTags()
+	}
+
+	// 更新已选条件
+	const updateSelectedTags = () => {
+		selectedTags.value = []
+		selectedTagKeys.value = []
+		// selectedTags.value = [
+		// 	...(selectedDept.value !== '全部' ? { key: 'Dept', list: [selectedDept.value] } : []),
+		// 	...(selectedCourse.value !== '全部' ? { key: 'Course', list: [selectedCourse.value] } : []),
+		// 	...(selectedType.value !== '全部' ? { key: 'Type', list: [selectedType.value] } : []),
+		// 	...(selectedFormat.value !== '全部' ? { key: 'Format', list: [selectedFormat.value] } : [])
+		// ]
+		if (selectedDept.value !== '全部') {
+			selectedTags.value.push(...[selectedDept.value])
+			selectedTagKeys.value.push('Dept')
+		}
+		if (selectedCourse.value !== '全部') {
+			selectedTags.value.push(...[selectedCourse.value])
+			selectedTagKeys.value.push('Course')
+		}
+		if (selectedType.value !== '全部') {
+			selectedTags.value.push(...[selectedType.value])
+			selectedTagKeys.value.push('Type')
+		}
+		if (selectedFormat.value !== '全部') {
+			selectedTags.value.push(...[selectedFormat.value])
+			selectedTagKeys.value.push('Format')
+		}
+		console.log('筛选条件', selectedTags.value, selectedTagKeys.value)
+	}
+
+	// 删除已选条件
+	const handleTagClose = (tag) => {
+		if (tag === selectedDept.value) {
+			selectedDept.value = '全部'
+		} else if (tag === selectedCourse.value) {
+			selectedCourse.value = '全部'
+		} else if (tag === selectedType.value) {
+			selectedType.value = '全部'
+		} else if (tag === selectedFormat.value) {
+			selectedFormat.value = '全部'
+		}
+		updateSelectedTags()
+	}
+	const handleClean = () => {
+		selectedTags.value = []
+		selectedDept.value = '全部'
+		selectedCourse.value = '全部'
+		selectedType.value = '全部'
+		selectedFormat.value = '全部'
+
+		Dept.value.setClean()
+		Course.value.setClean()
+		Type.value.setClean()
+		Format.value.setClean()
+		updateSelectedTags()
+	}
+
+	onMounted(() => {
+		// 初始化已选条件
+		handleClean()
+	})
+</script>
+
+<style scoped>
+	.filter-bar {
+		border: 1px solid #00000011; /* 灰色细边框 */
+		padding: 20px;
+	}
+
+	.filter-group {
+		display: flex;
+	}
+	.filter-group-title {
+		color: rgba(0, 0, 0, 0.521);
+		font-size: 12px;
+		min-width: 80px;
+		margin-top: 10px;
+	}
+
+	.line {
+		width: 100%;
+		height: 0.25px;
+		background-color: #00000013;
+	}
+	.clean {
+		color: rgb(133, 183, 224);
+		cursor: pointer;
+	}
+</style>

+ 82 - 0
src/views/resourceCenter/components/Correlation.vue

@@ -0,0 +1,82 @@
+<template>
+	<div>
+		<div class="recommend-container">
+			<h3>相关课程</h3>
+			<div v-for="(item, index) in recommendations" :key="index" class="recommend-item" @click="handlerItem(item)">
+				<div class="item"></div>
+				<div style="display: flex; flex-direction: column; justify-content: space-between; margin-left: 10px">
+					<span style="font-weight: bold; font-size: 12px; margin-top: 5px">{{ item.title }}</span>
+					<div style="display: flex; justify-content: center; align-items: space-between">
+						<div style="display: flex; justify-content: center; align-items: center">
+							<FieldTimeOutlined />
+							<div style="width: 5px"></div>
+							<span style="font-size: 12px">{{ item.time }}</span>
+						</div>
+						<div style="width: 20px"></div>
+						<div style="display: flex; justify-content: center; align-items: center">
+							<EyeOutlined />
+							<div style="width: 5px"></div>
+							<span style="font-size: 12px">{{ item.look }}</span>
+						</div>
+					</div>
+				</div>
+			</div>
+		</div>
+	</div>
+</template>
+
+<script setup>
+	const emit = defineEmits(['handlerItem'])
+	const recommendations = [
+		{ id: '1', title: '资源名称', time: '05-22', look: '10000' },
+		{ id: '2', title: '资源名称', time: '05-22', look: '10000' },
+		{ id: '3', title: '资源名称', time: '05-22', look: '10000' },
+		{ id: '4', title: '资源名称', time: '05-22', look: '10000' },
+		{ id: '5', title: '资源名称', time: '05-22', look: '10000' },
+		{ id: '6', title: '资源名称', time: '05-22', look: '10000' }
+		// 更多数据...
+	]
+	const handlerItem = (item) => {
+		emit('handlerItem', item)
+	}
+</script>
+<style scoped>
+	.recommend-container {
+		display: flex;
+		flex-direction: column;
+		border: 1px solid #e8e8e8;
+		margin-bottom: 10px;
+		border-radius: 4px;
+		padding: 10px;
+	}
+
+	.recommend-item {
+		display: flex;
+		cursor: pointer;
+		margin-bottom: 10px;
+	}
+
+	.recommend-avatar {
+		margin-right: 15px;
+	}
+
+	.recommend-content {
+		flex: 1;
+	}
+
+	.recommend-title {
+		font-size: 16px;
+		color: #1890ff;
+		margin-bottom: 5px;
+	}
+
+	.recommend-description {
+		font-size: 14px;
+		color: #666;
+	}
+	.item {
+		width: 100px;
+		height: 70px;
+		background-color: rgba(5, 5, 5, 0.219);
+	}
+</style>

+ 62 - 0
src/views/resourceCenter/components/Header.vue

@@ -0,0 +1,62 @@
+<template>
+	<div>
+		<div style="display: flex; width: 100vw; justify-content: space-between; align-items: center">
+			<div style="display: flex; padding-left: 10%">
+				<div style="width: 120px; height: 55px; background-color: brown" />
+				<a-menu v-model:selectedKeys="current" mode="horizontal" theme="light" style="line-height: 55px">
+					<a-menu-item style="margin-left: 10px; margin-right: 10px" key="1">首页</a-menu-item>
+					<a-menu-item style="margin-left: 10px; margin-right: 10px" key="2">资源中心</a-menu-item>
+					<a-menu-item style="margin-left: 10px; margin-right: 10px" key="3">资源管理</a-menu-item>
+				</a-menu>
+			</div>
+
+			<div class="header-right">
+				<!-- <a-input-search placeholder="输入关键词搜索" style="width: 200px" /> -->
+				<div style="display: flex">
+					<SearchOutlined :style="{ fontSize: '16px', color: '#00000083' }" />
+					<div style="width: 5px"></div>
+					<span style="font-size: 12px; color: #00000083">搜索</span>
+				</div>
+				<div style="width: 20px"></div>
+				<div style="display: flex">
+					<UserOutlined :style="{ fontSize: '16px', color: '#00000083' }" />
+					<div style="width: 5px"></div>
+					<span style="font-size: 12px; color: #00000083">登录</span>
+				</div>
+				<div style="width: 20px"></div>
+				<div style="display: flex">
+					<span style="font-size: 12px; color: #00000083">注册</span>
+				</div>
+				<!-- <a-button type="primary">登录</a-button>
+				<a-button>注册</a-button> -->
+			</div>
+		</div>
+		<div class="line" style=""></div>
+	</div>
+</template>
+
+<script setup>
+	import { ref } from 'vue'
+	const current = ref(['2']) // 默认选中“资源中心”
+</script>
+
+<style scoped>
+	.header {
+		display: flex;
+		align-items: center;
+		justify-content: space-between;
+		padding: 0 50px;
+	}
+	.header-right {
+		display: flex;
+		align-items: center;
+
+		margin-right: 20%;
+	}
+
+	.line {
+		width: 100%;
+		height: 0.25px;
+		background-color: #00000013;
+	}
+</style>

+ 117 - 0
src/views/resourceCenter/components/MyRadioButton.vue

@@ -0,0 +1,117 @@
+<template>
+	<div class="my-radio-button" :class="{ active: isActive }" @click="handleClick">
+		<span style="font-size: 12px">{{ label }}</span>
+	</div>
+</template>
+
+<script setup>
+	import { ref, inject } from 'vue'
+	// 注入来自父组件的数据
+	const group = inject('MyRadioGroupContext')
+	const clickType = ref('noClickType')
+	const title = ref('')
+	// 判断是否是当前选中项
+	// const isActive = computed(() => props.value === group.value)
+	const isActive = ref(false)
+
+	const props = defineProps({
+		value: {
+			required: true
+		},
+		label: {
+			type: String,
+			default: ''
+		},
+		index: {
+			type: Number
+		}
+	})
+	// 监听 group.value 的变化
+	watch(
+		() => group.value.value,
+		(newVal, oldVal) => {
+			console.log('group.value changed:', newVal, oldVal)
+			isActive.value = newVal === props.value
+		}
+	)
+
+	const setData = (data) => {
+		title.value = data
+	}
+	const getData = (data) => {
+		return title.value
+	}
+	const setClick = () => {
+		clickType.value = 'clickType'
+	}
+	const setNoClick = () => {
+		clickType.value = 'noClickType'
+	}
+
+	const handleClick = () => {
+		console.log(
+			'点击了 子布局',
+			' isActive.value ',
+			isActive.value,
+			' props.value ',
+			props.value,
+			' group.value ',
+			group.value
+		)
+		if (!isActive.value) {
+			group.changeValue(props.value)
+		}
+	}
+
+	onMounted(() => {
+		if (props.index == 0) {
+			isActive.value = true
+		}
+	})
+</script>
+
+<style scoped>
+	.clickType {
+		border-radius: 20px;
+		background: rgb(45, 130, 226);
+		display: flex;
+		align-items: center;
+		justify-content: center;
+		min-height: 50px;
+		min-width: 100px;
+	}
+	.clickType span {
+		color: white;
+	}
+	.noClickType {
+		display: flex;
+		align-items: center;
+		justify-content: center;
+		min-height: 50px;
+		min-width: 100px;
+	}
+	.noClickType span {
+		color: black;
+	}
+	.my-radio-button {
+		min-width: 100px;
+		display: flex;
+		justify-content: center;
+		align-items: center;
+		height: 30px;
+		margin: 1px;
+		border: 1px solid #ffffff00;
+		border-radius: 5px;
+		/* border: 1px solid #d9d9d9; */
+		/* border-radius: 4px; */
+		cursor: pointer;
+		transition: all 0.2s ease;
+	}
+	.my-radio-button.active {
+		background-color: #1890ff;
+		color: white;
+		border-color: #1890ff;
+		border: 1px solid #d9d9d9;
+		border-radius: 30px;
+	}
+</style>

+ 53 - 0
src/views/resourceCenter/components/MyRadioButtonGroup.vue

@@ -0,0 +1,53 @@
+<template>
+	<div class="my-radio-group">
+		<slot></slot>
+	</div>
+</template>
+
+<script setup>
+	import { ref, provide } from 'vue'
+
+	const props = defineProps({
+		modelValue: [String, Number, Boolean, Object, Array, null]
+	})
+
+	const emit = defineEmits(['update:modelValue'])
+	// 使用 ref 来包装 value 以确保响应性
+	const valueRef = ref(props.modelValue)
+
+	// 监听 group.value 的变化
+	watch(
+		() => valueRef.value,
+		(newVal, oldVal) => {
+			console.log('选择的右边胡麻:', newVal, oldVal)
+		}
+	)
+
+	// 提供给子组件的上下文
+	const groupContext = {
+		value: valueRef,
+		changeValue: (value) => {
+			console.log('点击了吗父布局', props.modelValue)
+			valueRef.value = value // 修改 ref 的值
+			// 改为通过 emit 更新值
+			emit('update:modelValue', value)
+			emit('change', value)
+		}
+	}
+	provide('MyRadioGroupContext', groupContext)
+
+	const setClean = () => {
+		valueRef.value = '全部'
+	}
+
+	defineExpose({
+		setClean
+	})
+</script>
+
+<style scoped>
+	.my-radio-group {
+		display: flex;
+		flex-wrap: wrap;
+	}
+</style>

+ 119 - 0
src/views/resourceCenter/components/ResourceList.vue

@@ -0,0 +1,119 @@
+<template>
+	<div class="resource-list">
+		<div class="list-header">
+			<div style="display: flex">
+				<div style="display: flex; justify-content: center; align-items: center">
+					<div class="line"></div>
+					<span style="font-weight: bold">共计 {{ total }} 个资源</span>
+				</div>
+				<div style="width: 20px"></div>
+				<TabSwitcher @selectTab="selectTab" />
+			</div>
+
+			<a-input-search placeholder="输入资源关键词" style="width: 200px" @search="onSearch" />
+		</div>
+		<a-row :gutter="[16, 16]">
+			<a-col :span="8" v-for="(item, index) in resources" :key="index">
+				<div style="border-radius: 10px 10px 5px 5px; border: 1px solid #dcdcdc">
+					<div style="display: flex">
+						<div class="resource" @click="handleItem(item)">
+							<PlayCircleOutlined :style="{ fontSize: '40px', color: 'white' }" />
+						</div>
+					</div>
+					<div style="display: flex; flex-direction: column; padding: 5px 10px">
+						<span style="font-size: 16px; font-weight: bold">{{ item.title }}</span>
+						<span style="font-size: 12px">{{ item.description }}</span>
+						<span style="font-size: 12px">{{ item.name }}</span>
+						<div style="display: flex; justify-content: space-between">
+							<div style="display: flex; justify-content: center; align-items: center">
+								<FieldTimeOutlined />
+								<div style="width: 5px"></div>
+								<span style="font-size: 12px">{{ item.time }}</span>
+							</div>
+
+							<div style="display: flex; justify-content: center; align-items: center">
+								<EyeOutlined />
+								<div style="width: 5px"></div>
+								<span style="font-size: 12px">{{ item.look }}</span>
+							</div>
+						</div>
+					</div>
+
+					<!-- <a-card-meta :title="item.title">
+						<template #description>
+							<p>{{ item.description }}</p>
+						</template>
+					</a-card-meta> -->
+				</div>
+			</a-col>
+		</a-row>
+
+		<div style="height: 20px"></div>
+		<div style="display: flex; width: 100%; align-items: center; justify-content: center">
+			<a-pagination v-model:current="currentPage" :total="total" show-size-changer />
+		</div>
+		<div style="height: 20px"></div>
+	</div>
+</template>
+
+<script setup>
+	import { ref } from 'vue'
+	import TabSwitcher from './TabSwitcher.vue'
+	const total = ref(1024)
+	const tabKey = ref('new')
+	const currentPage = ref(1)
+	const resources = [
+		{ id: 1, title: '学术交流英语', description: '来源学校', name: '姓名', time: '05-22 10:49', look: 10000 },
+		{ id: 2, title: '学术交流英语', description: '来源学校', name: '姓名', time: '05-22 10:49', look: 10000 },
+		{ id: 3, title: '学术交流英语', description: '来源学校', name: '姓名', time: '05-22 10:49', look: 10000 },
+		{ id: 4, title: '学术交流英语', description: '来源学校', name: '姓名', time: '05-22 10:49', look: 10000 },
+		{ id: 5, title: '学术交流英语', description: '来源学校', name: '姓名', time: '05-22 10:49', look: 10000 },
+		{ id: 6, title: '学术交流英语', description: '来源学校', name: '姓名', time: '05-22 10:49', look: 10000 },
+		{ id: 7, title: '学术交流英语', description: '来源学校', name: '姓名', time: '05-22 10:49', look: 10000 },
+		{ id: 8, title: '学术交流英语', description: '来源学校', name: '姓名', time: '05-22 10:49', look: 10000 },
+		{ id: 9, title: '学术交流英语', description: '来源学校', name: '姓名', time: '05-22 10:49', look: 10000 },
+		{ id: 10, title: '学术交流英语', description: '来源学校', name: '姓名', time: '05-22 10:49', look: 10000 },
+		{ id: 11, title: '学术交流英语', description: '来源学校', name: '姓名', time: '05-22 10:49', look: 10000 },
+		{ id: 12, title: '学术交流英语', description: '来源学校', name: '姓名', time: '05-22 10:49', look: 10000 }
+		// 更多数据...
+	]
+
+	const selectTab = (key) => {
+		console.log('现在是点了tab', key)
+	}
+	const handleItem = (item) => {
+		console.log('点了看教材的条目了', item)
+	}
+	const onSearch = (value) => {
+		console.log('搜索了', value)
+	}
+</script>
+
+<style scoped>
+	.list-header {
+		display: flex;
+		align-items: center;
+		justify-content: space-between;
+		margin-bottom: 20px;
+	}
+	.line {
+		width: 6px;
+		height: 15px;
+		background-color: rgb(0, 140, 255);
+		margin-right: 5px;
+	}
+
+	.resource {
+		width: 100%;
+		height: 150px;
+		background: #00000011;
+		border-radius: 10px 10px 0 0;
+		display: flex;
+		justify-content: center;
+		align-items: center;
+		cursor: pointer;
+	}
+	.resource:hover {
+		background: #0000008c;
+	}
+</style>

+ 85 - 0
src/views/resourceCenter/components/SidebarRecommend.vue

@@ -0,0 +1,85 @@
+<template>
+	<div>
+		<div class="recommend-container">
+			<h3>资源推荐</h3>
+			<div v-for="(item, index) in recommendations" :key="index" class="recommend-item" @click="handlerItem(item)">
+				<div class="item"></div>
+				<div style="display: flex; flex-direction: column; justify-content: space-between; margin-left: 10px">
+					<span style="font-weight: bold; font-size: 12px; margin-top: 5px">{{ item.title }}</span>
+					<div style="display: flex; justify-content: center; align-items: space-between">
+						<div style="display: flex; justify-content: center; align-items: center">
+							<FieldTimeOutlined />
+							<div style="width: 5px"></div>
+							<span style="font-size: 12px">{{ item.time }}</span>
+						</div>
+						<div style="width: 20px"></div>
+						<div style="display: flex; justify-content: center; align-items: center">
+							<EyeOutlined />
+							<div style="width: 5px"></div>
+							<span style="font-size: 12px">{{ item.look }}</span>
+						</div>
+					</div>
+				</div>
+			</div>
+		</div>
+	</div>
+</template>
+
+<script setup>
+	const emit = defineEmits(['handlerItem'])
+
+	const recommendations = [
+		{ id: '1', title: '资源名称', time: '05-22', look: '10000' },
+		{ id: '2', title: '资源名称', time: '05-22', look: '10000' },
+		{ id: '3', title: '资源名称', time: '05-22', look: '10000' },
+		{ id: '4', title: '资源名称', time: '05-22', look: '10000' },
+		{ id: '5', title: '资源名称', time: '05-22', look: '10000' },
+		{ id: '6', title: '资源名称', time: '05-22', look: '10000' }
+		// 更多数据...
+	]
+
+	const handlerItem = (item) => {
+		emit('handlerItem', item)
+	}
+</script>
+<style scoped>
+	.recommend-container {
+		display: flex;
+		flex-direction: column;
+		border: 1px solid #e8e8e8;
+		margin-bottom: 10px;
+		border-radius: 4px;
+		padding: 10px;
+	}
+
+	.recommend-item {
+		display: flex;
+
+		margin-bottom: 10px;
+		cursor: pointer;
+	}
+
+	.recommend-avatar {
+		margin-right: 15px;
+	}
+
+	.recommend-content {
+		flex: 1;
+	}
+
+	.recommend-title {
+		font-size: 16px;
+		color: #1890ff;
+		margin-bottom: 5px;
+	}
+
+	.recommend-description {
+		font-size: 14px;
+		color: #666;
+	}
+	.item {
+		width: 100px;
+		height: 70px;
+		background-color: rgba(5, 5, 5, 0.219);
+	}
+</style>

+ 43 - 0
src/views/resourceCenter/components/TabSwitcher.vue

@@ -0,0 +1,43 @@
+<template>
+	<div class="tab-switcher">
+		<div :class="{ active: selectedTab === 'latest' }" @click="selectTab('latest')">最新</div>
+		<div :class="{ active: selectedTab === 'hot' }" @click="selectTab('hot')">热门</div>
+	</div>
+</template>
+
+<script setup>
+	import { ref } from 'vue'
+	const emit = defineEmits(['selectTab'])
+	const selectedTab = ref('latest')
+
+	const selectTab = (tab) => {
+		if (selectedTab.value != tab) {
+			selectedTab.value = tab
+			emit('selectTab', tab)
+		}
+	}
+</script>
+
+<style scoped>
+	.tab-switcher {
+		display: flex;
+		border-radius: 20px;
+		border: 1px solid #1e90ff;
+		overflow: hidden;
+	}
+
+	.tab-switcher div {
+		padding: 2px 20px;
+		background-color: #f5f5f5;
+
+		cursor: pointer;
+	}
+
+	.tab-switcher div.active {
+		background-color: #1e90ff;
+		color: white;
+	}
+
+	.tab-switcher div:not(:last-child) {
+	}
+</style>

+ 37 - 0
src/views/resourceCenter/index.vue

@@ -0,0 +1,37 @@
+<template>
+	<div>
+		<ComplexChoices />
+		<div style="height: 20px"></div>
+		<a-row :gutter="16">
+			<a-col :span="18">
+				<ResourceList />
+			</a-col>
+			<a-col :span="6">
+				<SidebarRecommend @handlerItem="handlerItemSidebar" />
+				<Correlation @handlerItem="handlerItemCorrelation" />
+			</a-col>
+		</a-row>
+	</div>
+</template>
+
+<script setup>
+	import ComplexChoices from './components/ComplexChoices.vue'
+	import ResourceList from './components/ResourceList.vue'
+	import SidebarRecommend from './components/SidebarRecommend.vue'
+	import Correlation from './components/Correlation.vue'
+
+	const handlerItemSidebar = (item) => {
+		// emit('handlerItemSidebar', item)
+	}
+
+	const handlerItemCorrelation = (item) => {
+		// emit('handlerItemSidebar', item)
+	}
+</script>
+
+<style scoped>
+	.content {
+		padding-left: 10%;
+		padding-right: 30%;
+	}
+</style>

+ 43 - 0
src/views/resourceDetails/components/ListUnpublishedView.vue

@@ -0,0 +1,43 @@
+<template>
+	<div>
+		<QueryUnpublishedView />
+	</div>
+</template>
+
+<script setup>
+	import { ref } from 'vue'
+	import QueryUnpublishedView from './QueryUnpublishedView.vue'
+	const emit = defineEmits(['selectTab'])
+	const selectedTab = ref('latest')
+
+	const selectTab = (tab) => {
+		if (selectedTab.value != tab) {
+			selectedTab.value = tab
+			emit('selectTab', tab)
+		}
+	}
+</script>
+
+<style scoped>
+	.tab-switcher {
+		display: flex;
+		border-radius: 20px;
+		border: 1px solid #1e90ff;
+		overflow: hidden;
+	}
+
+	.tab-switcher div {
+		padding: 2px 20px;
+		background-color: #f5f5f5;
+
+		cursor: pointer;
+	}
+
+	.tab-switcher div.active {
+		background-color: #1e90ff;
+		color: white;
+	}
+
+	.tab-switcher div:not(:last-child) {
+	}
+</style>

+ 76 - 0
src/views/resourceDetails/components/QueryUnpublishedView.vue

@@ -0,0 +1,76 @@
+<template>
+	<div style="display: flex; justify-content: space-between">
+		<a-form :model="formState">
+			<a-form-item>
+				<a-input v-model:value="formState.name" placeholder="请输入资源名称" style="width: 200px; margin-right: 20px" />
+				<a-button type="primary" @click="onSubmit" :loading="iconLoading">
+					<template #icon> <SearchOutlined /> </template>
+					提交
+				</a-button>
+				<a-button style="margin-left: 10px" @click="reset">
+					<template #icon>
+						<RedoOutlined />
+					</template>
+					重置
+				</a-button>
+			</a-form-item>
+		</a-form>
+		<a-button type="primary" style="margin-left: 10px" @click="reset">
+			<template #icon> <PlusOutlined /> </template>
+			上传资源
+		</a-button>
+	</div>
+</template>
+
+<script setup>
+	import { ref } from 'vue'
+	import { Form } from 'ant-design-vue'
+	const emit = defineEmits(['selectTab'])
+	const iconLoading = ref(false)
+
+	const useForm = Form.useForm
+	const formState = reactive({
+		name: ''
+	})
+	const rulesRef = reactive({})
+	const { resetFields, validate, validateInfos } = useForm(formState, rulesRef)
+	const onSubmit = () => {
+		iconLoading.value = true
+		validate()
+			.then(() => {
+				iconLoading.value = false
+				console.log(toRaw(formState))
+			})
+			.catch((err) => {
+				console.log('error', err)
+				iconLoading.value = false
+			})
+	}
+	const reset = () => {
+		resetFields()
+	}
+</script>
+
+<style scoped>
+	.tab-switcher {
+		display: flex;
+		border-radius: 20px;
+		border: 1px solid #1e90ff;
+		overflow: hidden;
+	}
+
+	.tab-switcher div {
+		padding: 2px 20px;
+		background-color: #f5f5f5;
+
+		cursor: pointer;
+	}
+
+	.tab-switcher div.active {
+		background-color: #1e90ff;
+		color: white;
+	}
+
+	.tab-switcher div:not(:last-child) {
+	}
+</style>

+ 36 - 0
src/views/resourceDetails/index.vue

@@ -0,0 +1,36 @@
+<template>
+	<div class="content">
+		<a-tabs v-model:activeKey="activeKey" type="card">
+			<a-tab-pane key="1" tab="未发布">
+				<ListUnpublishedView />
+			</a-tab-pane>
+			<a-tab-pane key="2" tab="待审核">
+				<!-- <ListUnpublishedView /> -->
+			</a-tab-pane>
+			<a-tab-pane key="3" tab="已发布">
+				<!-- <ListUnpublishedView /> -->
+			</a-tab-pane>
+			<a-tab-pane key="4" tab="回收站">
+				<!-- <ListUnpublishedView /> -->
+			</a-tab-pane>
+		</a-tabs>
+	</div>
+</template>
+
+<script setup>
+	import ListUnpublishedView from './components/ListUnpublishedView.vue'
+
+	const handlerItemSidebar = (item) => {
+		// emit('handlerItemSidebar', item)
+	}
+
+	const handlerItemCorrelation = (item) => {
+		// emit('handlerItemSidebar', item)
+	}
+</script>
+
+<style scoped>
+	.content {
+		border: 1px solid #00000011; /* 灰色细边框 */
+	}
+</style>

+ 226 - 226
src/views/resourceOverview/index.vue

@@ -77,259 +77,259 @@
 	</div>
 </template>
 
-  <script setup>
-import * as echarts from 'echarts'
-import { ref, onMounted } from 'vue'
-import resourceOverviewApi from '@/api/resourceOverview.js'
-// import { ARow, ACol, ASelect, ASelectOption, AInputSearch, AButton } from 'ant-design-vue'
-
-// 响应式数据
-const totalCapacity = ref(20)
-const usedCapacity = ref(2) //已使用内容
-const availableCapacity = ref(18) //可用内存
-const resourceTotal = ref(36) //资源总量
-const resourceStats = ref([
-	{ width: '44%', color: '#5470c6' },
-	{ width: '6%', color: '#91cc75' },
-	{ width: '25%', color: '#fac858' },
-	{ width: '25%', color: '#c4ccd3' }
-])
-const resourceLabels = ref([
-	{ text: '视频:16', color: '#5470c6' },
-	{ text: '音频:0', color: '#f04864' },
-	{ text: '图片:2', color: '#91cc75' },
-	{ text: '文档:9', color: '#fac858' },
-	{ text: '其他:9', color: '#c4ccd3' }
-])
-// const historyList = ref([
-// 	{ date: '2024-09-24 16:12:24', file: '现代教育技术应用-6.mp4' },
-// 	{ date: '2024-09-24 13:38:52', file: '怎样写出较高水平的学术文章.mp4' },
-// 	{ date: '2024-09-23 16:44:14', file: 'etl.yml' },
-// 	{ date: '2024-09-23 13:53:59', file: '学术论文书写套路.mp4' },
-// 	{ date: '2024-09-23 13:53:55', file: '怎样找到值得研究的问题.mp4' },
-// 	{ date: '2024-09-21 14:56:16', file: '第一讲 当代艺术概况.pptx' },
-// 	{ date: '2024-09-21 14:08:57', file: '论文汇总.xlsx' },
-// 	{ date: '2024-09-20 12:03:35', file: '现代教育技术应用-6-字幕.srt' }
-// ])
-const historyList = ref([])
-
-// 搜索相关数据
-const selectedOption = ref('all')
-const searchKeyword = ref('')
-
-// 方法
-const applyExpansion = () => {
-	console.log('申请扩容')
-}
-// 方法
-const getLists = () => {
-	resourceOverviewApi
-		.getList({ type: 'upload' })
-		.then((res) => {
-			console.log(res, '资源概括数据')
-			historyList.value = res.data
-		})
-		.catch((err) => {
-			console.log(err)
-		})
-}
-//存储空间数据
-const getQueryList = () => {
-	resourceOverviewApi
-		.queryList()
-		.then((res) => {
-			console.log(res, '存储空间数据')
-			resourceTotal.value = res.totalSize
-			availableCapacity.value = res.remainStorageSize
-			usedCapacity.value = Number(res.totalFileSize)
-			totalCapacity.value = res.totalStorageSize
-			initChart()
-		})
-		.catch((err) => {
-			console.log(err)
-		})
-}
-
-const handleSearch = () => {
-	console.log('搜索:', selectedOption.value, searchKeyword.value)
-	// 这里可以添加实际的搜索逻辑
-}
-
-// 生命周期钩子
-onMounted(() => {
-	getQueryList()
-	getLists()
-})
-
-// 图表初始化
-const initChart = () => {
-	const chartDom = document.getElementById('storage-chart')
-	const myChart = echarts.init(chartDom)
-	const option = {
-		series: [
-			{
-				type: 'pie',
-				radius: ['40%', '70%'],
-				avoidLabelOverlap: false,
-				itemStyle: {
-					borderRadius: 10,
-					borderColor: '#fff',
-					borderWidth: 2
-				},
-				label: {
-					show: false,
-					position: 'center'
-				},
-				emphasis: {
-					label: {
-						show: true,
-						fontSize: '15',
-						fontWeight: 'bold'
-					}
-				},
-				labelLine: {
-					show: false
-				},
-				data: [
-					{ value: usedCapacity.value, name: '已使用' },
-					{ value: availableCapacity.value, name: '可用容量' }
-				]
-			}
-		]
+<script setup>
+	import * as echarts from 'echarts'
+	import { ref, onMounted } from 'vue'
+	import resourceOverviewApi from '@/api/resourceOverview.js'
+	// import { ARow, ACol, ASelect, ASelectOption, AInputSearch, AButton } from 'ant-design-vue'
+
+	// 响应式数据
+	const totalCapacity = ref(20)
+	const usedCapacity = ref(2) //已使用内容
+	const availableCapacity = ref(18) //可用内存
+	const resourceTotal = ref(36) //资源总量
+	const resourceStats = ref([
+		{ width: '44%', color: '#5470c6' },
+		{ width: '6%', color: '#91cc75' },
+		{ width: '25%', color: '#fac858' },
+		{ width: '25%', color: '#c4ccd3' }
+	])
+	const resourceLabels = ref([
+		{ text: '视频:16', color: '#5470c6' },
+		{ text: '音频:0', color: '#f04864' },
+		{ text: '图片:2', color: '#91cc75' },
+		{ text: '文档:9', color: '#fac858' },
+		{ text: '其他:9', color: '#c4ccd3' }
+	])
+	// const historyList = ref([
+	// 	{ date: '2024-09-24 16:12:24', file: '现代教育技术应用-6.mp4' },
+	// 	{ date: '2024-09-24 13:38:52', file: '怎样写出较高水平的学术文章.mp4' },
+	// 	{ date: '2024-09-23 16:44:14', file: 'etl.yml' },
+	// 	{ date: '2024-09-23 13:53:59', file: '学术论文书写套路.mp4' },
+	// 	{ date: '2024-09-23 13:53:55', file: '怎样找到值得研究的问题.mp4' },
+	// 	{ date: '2024-09-21 14:56:16', file: '第一讲 当代艺术概况.pptx' },
+	// 	{ date: '2024-09-21 14:08:57', file: '论文汇总.xlsx' },
+	// 	{ date: '2024-09-20 12:03:35', file: '现代教育技术应用-6-字幕.srt' }
+	// ])
+	const historyList = ref([])
+
+	// 搜索相关数据
+	const selectedOption = ref('all')
+	const searchKeyword = ref('')
+
+	// 方法
+	const applyExpansion = () => {
+		console.log('申请扩容')
+	}
+	// 方法
+	const getLists = () => {
+		resourceOverviewApi
+			.getList({ type: 'upload' })
+			.then((res) => {
+				console.log(res, '资源概括数据')
+				historyList.value = res.data
+			})
+			.catch((err) => {
+				console.log(err)
+			})
+	}
+	//存储空间数据
+	const getQueryList = () => {
+		resourceOverviewApi
+			.queryList()
+			.then((res) => {
+				console.log(res, '存储空间数据')
+				resourceTotal.value = res.totalSize
+				availableCapacity.value = res.remainStorageSize
+				usedCapacity.value = Number(res.totalFileSize)
+				totalCapacity.value = res.totalStorageSize
+				initChart()
+			})
+			.catch((err) => {
+				console.log(err)
+			})
+	}
+
+	const handleSearch = () => {
+		console.log('搜索:', selectedOption.value, searchKeyword.value)
+		// 这里可以添加实际的搜索逻辑
 	}
 
-	myChart.setOption(option)
-}
+	// 生命周期钩子
+	onMounted(() => {
+		getQueryList()
+		getLists()
+	})
+
+	// 图表初始化
+	const initChart = () => {
+		const chartDom = document.getElementById('storage-chart')
+		const myChart = echarts.init(chartDom)
+		const option = {
+			series: [
+				{
+					type: 'pie',
+					radius: ['40%', '70%'],
+					avoidLabelOverlap: false,
+					itemStyle: {
+						borderRadius: 10,
+						borderColor: '#fff',
+						borderWidth: 2
+					},
+					label: {
+						show: false,
+						position: 'center'
+					},
+					emphasis: {
+						label: {
+							show: true,
+							fontSize: '15',
+							fontWeight: 'bold'
+						}
+					},
+					labelLine: {
+						show: false
+					},
+					data: [
+						{ value: usedCapacity.value, name: '已使用' },
+						{ value: availableCapacity.value, name: '可用容量' }
+					]
+				}
+			]
+		}
+
+		myChart.setOption(option)
+	}
 </script>
 <style scoped>
-.dashboard-container {
-	display: flex;
-	flex-direction: column;
-}
-
-.left-content {
-	padding: 40px 60px;
-	box-sizing: border-box;
-}
-.right-content {
-	padding: 40px;
-	box-sizing: border-box;
-}
-
-.storage-space {
-	display: flex;
-	align-items: center;
-}
-
-#storage-chart {
-	margin-right: 20px;
-}
-
-.storage-info {
-	display: flex;
-	flex-direction: column;
-}
-
-.resource-total {
-	margin-top: 20px;
-}
-
-.resource-stats {
-	display: flex;
-	height: 20px;
-}
-
-.resource-stats > div {
-	height: 100%;
-}
-
-.resource-labels {
-	display: flex;
-	margin-top: 10px;
-}
-
-.resource-labels > span {
-	margin-right: 20px;
-}
-
-.history-list {
-	list-style: none;
-	padding: 0;
-}
-
-.history-list li {
-	position: relative;
-	padding-left: 20px;
-	margin-bottom: 15px;
-}
-
-.history-list li::before {
-	content: '';
-	position: absolute;
-	left: 0;
-	top: 8px;
-	width: 8px;
-	height: 8px;
-	background-color: #ccc;
-	border-radius: 50%;
-}
-
-.history-time {
-	color: #999;
-	margin-right: 10px;
-}
-
-.history-file {
-	font-size: 14px;
-}
-.fonsize28 {
-	font-size: 28px;
-}
-.marginright5 {
-	margin-right: 5px;
-}
-
-/* 响应式调整 */
-@media (max-width: 768px) {
-	.left-content,
+	.dashboard-container {
+		display: flex;
+		flex-direction: column;
+	}
+
+	.left-content {
+		padding: 40px 60px;
+		box-sizing: border-box;
+	}
 	.right-content {
-		padding: 20px;
+		padding: 40px;
+		box-sizing: border-box;
 	}
 
 	.storage-space {
-		flex-direction: column;
-		align-items: flex-start;
+		display: flex;
+		align-items: center;
 	}
 
 	#storage-chart {
-		width: 150px;
-		height: 150px;
-		margin-bottom: 10px;
+		margin-right: 20px;
+	}
+
+	.storage-info {
+		display: flex;
+		flex-direction: column;
 	}
 
-	.storage-info p {
-		margin: 5px 0;
+	.resource-total {
+		margin-top: 20px;
 	}
 
 	.resource-stats {
-		height: 15px;
+		display: flex;
+		height: 20px;
+	}
+
+	.resource-stats > div {
+		height: 100%;
+	}
+
+	.resource-labels {
+		display: flex;
+		margin-top: 10px;
 	}
 
 	.resource-labels > span {
-		margin-right: 10px;
+		margin-right: 20px;
+	}
+
+	.history-list {
+		list-style: none;
+		padding: 0;
 	}
 
 	.history-list li {
-		padding-left: 15px;
-		margin-bottom: 10px;
+		position: relative;
+		padding-left: 20px;
+		margin-bottom: 15px;
+	}
+
+	.history-list li::before {
+		content: '';
+		position: absolute;
+		left: 0;
+		top: 8px;
+		width: 8px;
+		height: 8px;
+		background-color: #ccc;
+		border-radius: 50%;
 	}
 
 	.history-time {
-		font-size: 12px;
+		color: #999;
+		margin-right: 10px;
 	}
 
 	.history-file {
-		font-size: 13px;
+		font-size: 14px;
+	}
+	.fonsize28 {
+		font-size: 28px;
+	}
+	.marginright5 {
+		margin-right: 5px;
+	}
+
+	/* 响应式调整 */
+	@media (max-width: 768px) {
+		.left-content,
+		.right-content {
+			padding: 20px;
+		}
+
+		.storage-space {
+			flex-direction: column;
+			align-items: flex-start;
+		}
+
+		#storage-chart {
+			width: 150px;
+			height: 150px;
+			margin-bottom: 10px;
+		}
+
+		.storage-info p {
+			margin: 5px 0;
+		}
+
+		.resource-stats {
+			height: 15px;
+		}
+
+		.resource-labels > span {
+			margin-right: 10px;
+		}
+
+		.history-list li {
+			padding-left: 15px;
+			margin-bottom: 10px;
+		}
+
+		.history-time {
+			font-size: 12px;
+		}
+
+		.history-file {
+			font-size: 13px;
+		}
 	}
-}
 </style>