feat: 新增文件管理前端页面初版

This commit is contained in:
Charles7c 2023-12-20 22:54:09 +08:00
parent 505ba49a53
commit 5d5d882c1a
50 changed files with 2004 additions and 21 deletions

View File

@ -36,6 +36,7 @@ module.exports = {
},
},
rules: {
'import/prefer-default-export': 'off',
'prettier/prettier': 1,
// Vue: Recommended rules to be closed or modify
'vue/require-default-prop': 0,

View File

@ -48,6 +48,7 @@
"pinia": "^2.1.7",
"query-string": "^8.1.0",
"sortablejs": "^1.15.0",
"v-viewer": "^1.6.4",
"vue": "^3.3.7",
"vue-codemirror": "^6.1.1",
"vue-cropper": "^1.1.1",
@ -55,7 +56,8 @@
"vue-i18n": "^9.6.5",
"vue-json-pretty": "^2.2.4",
"vue-router": "^4.2.5",
"vue3-colorpicker": "^2.2.2"
"vue3-colorpicker": "^2.2.2",
"xgplayer": "^3.0.11"
},
"devDependencies": {
"@arco-plugins/vite-vue": "^1.4.5",
@ -87,6 +89,7 @@
"prettier": "^3.0.3",
"rollup": "^4.3.0",
"rollup-plugin-visualizer": "^5.9.2",
"sass": "^1.69.5",
"stylelint": "^15.11.0",
"stylelint-config-prettier": "^9.0.5",
"stylelint-config-rational-order": "^0.1.2",

View File

@ -59,6 +59,9 @@ dependencies:
sortablejs:
specifier: ^1.15.0
version: 1.15.0
v-viewer:
specifier: ^1.6.4
version: 1.6.4
vue:
specifier: ^3.3.7
version: 3.3.7(typescript@5.2.2)
@ -83,6 +86,9 @@ dependencies:
vue3-colorpicker:
specifier: ^2.2.2
version: 2.2.2(@aesoper/normal-utils@0.1.5)(@popperjs/core@2.11.8)(@vueuse/core@10.5.0)(gradient-parser@1.0.2)(lodash-es@4.17.21)(tinycolor2@1.6.0)(vue-types@4.2.1)(vue@3.3.7)
xgplayer:
specifier: ^3.0.11
version: 3.0.11(core-js@3.34.0)
devDependencies:
'@arco-plugins/vite-vue':
@ -172,6 +178,9 @@ devDependencies:
rollup-plugin-visualizer:
specifier: ^5.9.2
version: 5.9.2(rollup@4.3.0)
sass:
specifier: ^1.69.5
version: 1.69.5
stylelint:
specifier: ^15.11.0
version: 15.11.0(typescript@5.2.2)
@ -198,7 +207,7 @@ devDependencies:
version: 0.25.2(rollup@4.3.0)(vue@3.3.7)
vite:
specifier: ^4.5.0
version: 4.5.0(@types/node@18.15.10)(less@4.2.0)
version: 4.5.0(@types/node@18.15.10)(less@4.2.0)(sass@1.69.5)
vite-plugin-compression:
specifier: ^0.5.1
version: 0.5.1(vite@4.5.0)
@ -1929,7 +1938,7 @@ packages:
'@babel/core': 7.23.2
'@babel/plugin-transform-typescript': 7.22.15(@babel/core@7.23.2)
'@vue/babel-plugin-jsx': 1.1.5(@babel/core@7.23.2)
vite: 4.5.0(@types/node@18.15.10)(less@4.2.0)
vite: 4.5.0(@types/node@18.15.10)(less@4.2.0)(sass@1.69.5)
vue: 3.3.7(typescript@5.2.2)
transitivePeerDependencies:
- supports-color
@ -1942,7 +1951,7 @@ packages:
vite: ^4.0.0
vue: ^3.2.25
dependencies:
vite: 4.5.0(@types/node@18.15.10)(less@4.2.0)
vite: 4.5.0(@types/node@18.15.10)(less@4.2.0)(sass@1.69.5)
vue: 3.3.7(typescript@5.2.2)
dev: true
@ -2230,7 +2239,7 @@ packages:
dev: true
/anymatch@3.1.3:
resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==, tarball: https://registry.npmmirror.com/anymatch/-/anymatch-3.1.3.tgz}
engines: {node: '>= 8'}
dependencies:
normalize-path: 3.0.0
@ -2501,7 +2510,7 @@ packages:
dev: true
/binary-extensions@2.2.0:
resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==}
resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==, tarball: https://registry.npmmirror.com/binary-extensions/-/binary-extensions-2.2.0.tgz}
engines: {node: '>=8'}
dev: true
@ -2540,7 +2549,7 @@ packages:
dev: true
/braces@2.3.2:
resolution: {integrity: sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==}
resolution: {integrity: sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==, tarball: https://registry.npmmirror.com/braces/-/braces-2.3.2.tgz}
engines: {node: '>=0.10.0'}
dependencies:
arr-flatten: 1.1.0
@ -2805,7 +2814,7 @@ packages:
dev: true
/chokidar@3.5.3:
resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==}
resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==, tarball: https://registry.npmmirror.com/chokidar/-/chokidar-3.5.3.tgz}
engines: {node: '>= 8.10.0'}
dependencies:
anymatch: 3.1.3
@ -3059,6 +3068,11 @@ packages:
toggle-selection: 1.0.6
dev: false
/core-js@3.34.0:
resolution: {integrity: sha512-aDdvlDder8QmY91H88GzNi9EtQi2TjvQhpCX6B1v/dAZHU1AuLgHvRh54RiOerpEhEW46Tkf+vgAViB/CWC0ag==, tarball: https://registry.npmmirror.com/core-js/-/core-js-3.34.0.tgz}
requiresBuild: true
dev: false
/core-util-is@1.0.3:
resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==}
dev: true
@ -3718,6 +3732,13 @@ packages:
d3-zoom: 3.0.0
dev: false
/d@1.0.1:
resolution: {integrity: sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==, tarball: https://registry.npmmirror.com/d/-/d-1.0.1.tgz}
dependencies:
es5-ext: 0.10.62
type: 1.2.0
dev: false
/dagre-d3@0.6.4:
resolution: {integrity: sha512-e/6jXeCP7/ptlAM48clmX4xTZc5Ek6T6kagS7Oz2HrYSdqcLZFLqpAfh7ldbZRFfxCZVyh61NEPR08UQRVxJzQ==}
dependencies:
@ -3734,6 +3755,12 @@ packages:
lodash: 4.17.21
dev: false
/danmu.js@1.1.13:
resolution: {integrity: sha512-knFd0/cB2HA4FFWiA7eB2suc5vCvoHdqio33FyyCSfP7C+1A+zQcTvnvwfxaZhrxsGj4qaQI2I8XiTqedRaVmg==, tarball: https://registry.npmmirror.com/danmu.js/-/danmu.js-1.1.13.tgz}
dependencies:
event-emitter: 0.3.5
dev: false
/dargs@7.0.0:
resolution: {integrity: sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==}
engines: {node: '>=8'}
@ -3946,6 +3973,10 @@ packages:
robust-predicates: 3.0.2
dev: false
/delegate@3.2.0:
resolution: {integrity: sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==, tarball: https://registry.npmmirror.com/delegate/-/delegate-3.2.0.tgz}
dev: false
/dir-glob@2.2.2:
resolution: {integrity: sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==}
engines: {node: '>=4'}
@ -4093,6 +4124,10 @@ packages:
pify: 3.0.0
dev: true
/downloadjs@1.4.7:
resolution: {integrity: sha512-LN1gO7+u9xjU5oEScGFKvXhYf7Y/empUIIEAGBs1LzUq/rg5duiDrkuH5A2lQGd5jfMOb9X9usDa2oVXwJ0U/Q==, tarball: https://registry.npmmirror.com/downloadjs/-/downloadjs-1.4.7.tgz}
dev: false
/duplexer3@0.1.5:
resolution: {integrity: sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==}
dev: true
@ -4287,6 +4322,31 @@ packages:
is-symbol: 1.0.4
dev: true
/es5-ext@0.10.62:
resolution: {integrity: sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==, tarball: https://registry.npmmirror.com/es5-ext/-/es5-ext-0.10.62.tgz}
engines: {node: '>=0.10'}
requiresBuild: true
dependencies:
es6-iterator: 2.0.3
es6-symbol: 3.1.3
next-tick: 1.1.0
dev: false
/es6-iterator@2.0.3:
resolution: {integrity: sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==, tarball: https://registry.npmmirror.com/es6-iterator/-/es6-iterator-2.0.3.tgz}
dependencies:
d: 1.0.1
es5-ext: 0.10.62
es6-symbol: 3.1.3
dev: false
/es6-symbol@3.1.3:
resolution: {integrity: sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==, tarball: https://registry.npmmirror.com/es6-symbol/-/es6-symbol-3.1.3.tgz}
dependencies:
d: 1.0.1
ext: 1.7.0
dev: false
/esbuild-android-64@0.14.54:
resolution: {integrity: sha512-Tz2++Aqqz0rJ7kYBfz+iqyE3QMycD4vk7LBRyWaAVFgFtQ/O8EJOnVmTOiDWYZ/uYzB4kvP+bqejYdVKzE5lAQ==, tarball: https://registry.npmmirror.com/esbuild-android-64/-/esbuild-android-64-0.14.54.tgz}
engines: {node: '>=12'}
@ -4811,6 +4871,17 @@ packages:
engines: {node: '>= 0.6'}
dev: true
/event-emitter@0.3.5:
resolution: {integrity: sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==, tarball: https://registry.npmmirror.com/event-emitter/-/event-emitter-0.3.5.tgz}
dependencies:
d: 1.0.1
es5-ext: 0.10.62
dev: false
/eventemitter3@4.0.7:
resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==, tarball: https://registry.npmmirror.com/eventemitter3/-/eventemitter3-4.0.7.tgz}
dev: false
/eventemitter3@5.0.1:
resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==}
dev: true
@ -4955,6 +5026,12 @@ packages:
sort-keys-length: 1.0.1
dev: true
/ext@1.7.0:
resolution: {integrity: sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==, tarball: https://registry.npmmirror.com/ext/-/ext-1.7.0.tgz}
dependencies:
type: 2.7.2
dev: false
/extend-shallow@2.0.1:
resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==}
engines: {node: '>=0.10.0'}
@ -5466,7 +5543,7 @@ packages:
dev: true
/glob-parent@3.1.0:
resolution: {integrity: sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==}
resolution: {integrity: sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==, tarball: https://registry.npmmirror.com/glob-parent/-/glob-parent-3.1.0.tgz}
dependencies:
is-glob: 3.1.0
path-dirname: 1.0.2
@ -5970,6 +6047,10 @@ packages:
replace-ext: 1.0.1
dev: true
/immutable@4.3.4:
resolution: {integrity: sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA==, tarball: https://registry.npmmirror.com/immutable/-/immutable-4.3.4.tgz}
dev: true
/import-fresh@2.0.0:
resolution: {integrity: sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg==}
engines: {node: '>=4'}
@ -6117,7 +6198,7 @@ packages:
dev: true
/is-binary-path@2.1.0:
resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==, tarball: https://registry.npmmirror.com/is-binary-path/-/is-binary-path-2.1.0.tgz}
engines: {node: '>=8'}
dependencies:
binary-extensions: 2.2.0
@ -6260,7 +6341,7 @@ packages:
dev: true
/is-glob@3.1.0:
resolution: {integrity: sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==}
resolution: {integrity: sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==, tarball: https://registry.npmmirror.com/is-glob/-/is-glob-3.1.0.tgz}
engines: {node: '>=0.10.0'}
dependencies:
is-extglob: 2.1.1
@ -7428,6 +7509,10 @@ packages:
dev: true
optional: true
/next-tick@1.1.0:
resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==, tarball: https://registry.npmmirror.com/next-tick/-/next-tick-1.1.0.tgz}
dev: false
/nice-try@1.0.5:
resolution: {integrity: sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==}
dev: true
@ -8459,7 +8544,7 @@ packages:
dev: true
/readdirp@3.6.0:
resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==, tarball: https://registry.npmmirror.com/readdirp/-/readdirp-3.6.0.tgz}
engines: {node: '>=8.10.0'}
dependencies:
picomatch: 2.3.1
@ -8807,6 +8892,16 @@ packages:
/safer-buffer@2.1.2:
resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
/sass@1.69.5:
resolution: {integrity: sha512-qg2+UCJibLr2LCVOt3OlPhr/dqVHWOa9XtZf2OjbLs/T4VPSJ00udtgJxH3neXZm+QqX8B+3cU7RaLqp1iVfcQ==, tarball: https://registry.npmmirror.com/sass/-/sass-1.69.5.tgz}
engines: {node: '>=14.0.0'}
hasBin: true
dependencies:
chokidar: 3.5.3
immutable: 4.3.4
source-map-js: 1.0.2
dev: true
/sax@1.2.4:
resolution: {integrity: sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==}
requiresBuild: true
@ -9023,7 +9118,7 @@ packages:
dev: false
/source-map-js@1.0.2:
resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==}
resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==, tarball: https://registry.npmmirror.com/source-map-js/-/source-map-js-1.0.2.tgz}
engines: {node: '>=0.10.0'}
/source-map-resolve@0.5.3:
@ -9723,6 +9818,11 @@ packages:
resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
dev: true
/throttle-debounce@2.3.0:
resolution: {integrity: sha512-H7oLPV0P7+jgvrk+6mwwwBDmxTaxnu9HMXmloNLXwnNO0ZxZ31Orah2n8lU1eMPvsaowP2CX+USCgyovXfdOFQ==, tarball: https://registry.npmmirror.com/throttle-debounce/-/throttle-debounce-2.3.0.tgz}
engines: {node: '>=8'}
dev: false
/through2@4.0.2:
resolution: {integrity: sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==}
dependencies:
@ -9909,6 +10009,14 @@ packages:
engines: {node: '>=10'}
dev: true
/type@1.2.0:
resolution: {integrity: sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==, tarball: https://registry.npmmirror.com/type/-/type-1.2.0.tgz}
dev: false
/type@2.7.2:
resolution: {integrity: sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==, tarball: https://registry.npmmirror.com/type/-/type-2.7.2.tgz}
dev: false
/typed-array-buffer@1.0.0:
resolution: {integrity: sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==}
engines: {node: '>= 0.4'}
@ -10173,6 +10281,14 @@ packages:
hasBin: true
dev: true
/v-viewer@1.6.4:
resolution: {integrity: sha512-LVkiUHpmsbsZXebeNXnu8krRCi5i2n07FeLFxoIVGhw8lVvTBO0ffpbDC6mLEuacCjrIh09HjIqpciwUtWE8lQ==, tarball: https://registry.npmmirror.com/v-viewer/-/v-viewer-1.6.4.tgz}
engines: {node: '>=4', npm: '>=3'}
dependencies:
throttle-debounce: 2.3.0
viewerjs: 1.11.6
dev: false
/validate-npm-package-license@3.0.4:
resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==}
dependencies:
@ -10222,6 +10338,10 @@ packages:
vfile-message: 1.1.1
dev: true
/viewerjs@1.11.6:
resolution: {integrity: sha512-TlhdSp2oEOLFXvEp4psKaeTjR5zBjTRcM/sHUN8PkV1UWuY8HKC8n7GaVdW5Xqnwdr/F1OmzLik1QwDjI4w/nw==, tarball: https://registry.npmmirror.com/viewerjs/-/viewerjs-1.11.6.tgz}
dev: false
/vite-plugin-compression@0.5.1(vite@4.5.0):
resolution: {integrity: sha512-5QJKBDc+gNYVqL/skgFAP81Yuzo9R+EAf19d+EtsMF/i8kFUpNi3J/H01QD3Oo8zBQn+NzoCIFkpPLynoOzaJg==}
peerDependencies:
@ -10230,7 +10350,7 @@ packages:
chalk: 4.1.2
debug: 4.3.4
fs-extra: 10.1.0
vite: 4.5.0(@types/node@18.15.10)(less@4.2.0)
vite: 4.5.0(@types/node@18.15.10)(less@4.2.0)(sass@1.69.5)
transitivePeerDependencies:
- supports-color
dev: true
@ -10245,7 +10365,7 @@ packages:
'@types/eslint': 8.21.3
eslint: 8.53.0
rollup: 2.79.1
vite: 4.5.0(@types/node@18.15.10)(less@4.2.0)
vite: 4.5.0(@types/node@18.15.10)(less@4.2.0)(sass@1.69.5)
dev: true
/vite-plugin-imagemin@0.6.1(vite@4.5.0):
@ -10276,7 +10396,7 @@ packages:
imagemin-webp: 6.1.0
jpegtran-bin: 6.0.1
pathe: 0.2.0
vite: 4.5.0(@types/node@18.15.10)(less@4.2.0)
vite: 4.5.0(@types/node@18.15.10)(less@4.2.0)(sass@1.69.5)
transitivePeerDependencies:
- supports-color
dev: true
@ -10294,7 +10414,7 @@ packages:
pathe: 0.2.0
svg-baker: 1.7.0
svgo: 2.8.0
vite: 4.5.0(@types/node@18.15.10)(less@4.2.0)
vite: 4.5.0(@types/node@18.15.10)(less@4.2.0)(sass@1.69.5)
transitivePeerDependencies:
- supports-color
dev: true
@ -10306,7 +10426,7 @@ packages:
svgo: 3.0.2
dev: true
/vite@4.5.0(@types/node@18.15.10)(less@4.2.0):
/vite@4.5.0(@types/node@18.15.10)(less@4.2.0)(sass@1.69.5):
resolution: {integrity: sha512-ulr8rNLA6rkyFAlVWw2q5YJ91v098AFQ2R0PRFwPzREXOUJQPtFUG0t+/ZikhaOCDqFoDhN6/v8Sq0o4araFAw==}
engines: {node: ^14.18.0 || >=16.0.0}
hasBin: true
@ -10339,6 +10459,7 @@ packages:
less: 4.2.0
postcss: 8.4.31
rollup: 3.29.4
sass: 1.69.5
optionalDependencies:
fsevents: 2.3.2
dev: true
@ -10630,6 +10751,28 @@ packages:
resolution: {integrity: sha512-GojqklwG8gpzOVEVki5KudKNoq7MbbjYZCbyWzEz7tyPA7eleiE0+ePwOWQQRb5fm86rD3S8Tc0tSFf3AOv50w==}
dev: true
/xgplayer-subtitles@3.0.11(core-js@3.34.0):
resolution: {integrity: sha512-m/fk9TeeLuwqnryHTqo5SVVS3w9A27hHe7R1HxWQlk5ZZ5H2CxAXn4dv/PU+gI61DWG3sNkjftlq5duHJtdz2g==, tarball: https://registry.npmmirror.com/xgplayer-subtitles/-/xgplayer-subtitles-3.0.11.tgz}
peerDependencies:
core-js: '>=3.12.1'
dependencies:
core-js: 3.34.0
eventemitter3: 4.0.7
dev: false
/xgplayer@3.0.11(core-js@3.34.0):
resolution: {integrity: sha512-n7qpUG46IVjcYWCFq9WLe4OQpIZvtT67lObu6RPgxbMm8IMGCscTVdbWQjRbgrlsvTVfes3zTfjyaymuS5g17g==, tarball: https://registry.npmmirror.com/xgplayer/-/xgplayer-3.0.11.tgz}
peerDependencies:
core-js: '>=3.12.1'
dependencies:
core-js: 3.34.0
danmu.js: 1.1.13
delegate: 3.2.0
downloadjs: 1.4.7
eventemitter3: 4.0.7
xgplayer-subtitles: 3.0.11(core-js@3.34.0)
dev: false
/xml-name-validator@4.0.0:
resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==}
engines: {node: '>=12'}

View File

@ -0,0 +1,24 @@
import axios from 'axios';
const BASE_URL = '/system/file';
export interface FileItem {
id: string
type: string
name: string
extendName: string
src: string | null
updateTime: string
isDir: boolean
filePath: string
[propName: string]: any // 一个 interface 中任意属性只能有一个
}
interface PageRes<T> {
records: T;
total: number;
}
export function getFileList() {
return axios.get<PageRes<FileItem[]>>(`${BASE_URL}/file`);
}

View File

Before

Width:  |  Height:  |  Size: 298 B

After

Width:  |  Height:  |  Size: 298 B

View File

@ -0,0 +1,14 @@
<svg t="1642407662269" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
p-id="19932" width="200" height="200">
<path d="M847.872 240.128v688c0 26.56-21.408 48-48 48h-576c-26.56 0-48-21.44-48-48v-832c0-26.592 21.44-48 48-48h432z"
fill="#E9EDED" p-id="19933"></path>
<path d="M160 768.128v160c0 35.456 28.544 64 64 64h576c35.456 0 64-28.544 64-64v-160H160z" fill="#4BBFEB"
p-id="19934"></path>
<path d="M847.872 240.128h-144c-26.56 0-48-21.44-48-48v-144" fill="#4BBFEB" p-id="19935"></path>
<path
d="M432.256 320.128c-35.2 0-64 28.8-64 64v32c0 18.016-14.016 32-32 32a16 16 0 0 0-15.936 12.992 16 16 0 0 0 0 0.064 16 16 0 0 0 4.736 14.56 16 16 0 0 0 2.496 1.92 16 16 0 0 0 4.448 1.92 16 16 0 0 0 3.136 0.48 16 16 0 0 0 1.12 0.064c17.984 0 32 13.984 32 32v32c0 35.2 28.8 64 64 64a16 16 0 1 0 0-32c-18.016 0-32-13.984-32-32v-32c0-19.136-8.736-36.256-22.208-48a63.68 63.68 0 0 0 22.208-48v-32c0-18.016 13.984-32 32-32a16 16 0 1 0 0-32z m157.856 0a16 16 0 0 0 1.632 32c18.016 0 32 13.984 32 32v32c0 19.168 8.736 36.224 22.208 48-13.44 11.744-22.208 28.864-22.208 48v32c0 18.016-13.984 32-32 32a16 16 0 1 0 0 32c35.2 0 64-28.8 64-64v-32c0-18.016 14.016-32 32-32a16 16 0 0 0 10.368-3.616 16 16 0 0 0 1.216-1.152 16 16 0 0 0-11.584-27.232c-17.984 0-32-13.984-32-32v-32c0-35.2-28.8-64-64-64a16 16 0 0 0-1.6 0z"
fill="#4BBFEB" p-id="19936"></path>
<path
d="M334.496 800.128a16 16 0 0 0-3.36 0.672c-41.664 3.712-75.008 37.44-75.008 79.328 0 42.08 33.696 75.904 75.616 79.296a16 16 0 0 0 4.64 0.704h32a16 16 0 1 0 0-32h-29.824c-28.544 0-50.432-21.44-50.432-48s21.888-48 50.432-48h29.568a16 16 0 1 0 0-32h-32a16 16 0 0 0-1.6 0z m128 0a16 16 0 0 0-1.984 0.384c-24.64 1.92-44.384 22.528-44.384 47.616 0 25.28 20.064 46.08 44.992 47.68a16 16 0 0 0 3.008 0.32h32c9.152 0 16 6.848 16 16 0 9.152-6.848 16-16 16h-64a16 16 0 1 0 0 32h64a16 16 0 0 0 3.296-0.384 48.096 48.096 0 0 0 44.704-47.616c0-25.152-19.84-45.888-44.576-47.68a16 16 0 0 0-3.424-0.32h-32a15.616 15.616 0 0 1-16-16c0-9.152 6.848-16 16-16h64a16 16 0 1 0 0-32h-62.88a16 16 0 0 0-1.12 0 16 16 0 0 0-1.6 0z m159.744 0a16 16 0 0 0-1.984 0.384c-24.64 1.92-44.384 22.528-44.384 47.616 0 25.28 20.096 46.08 44.992 47.68a16 16 0 0 0 3.008 0.32h32c9.152 0 16 6.848 16 16 0 9.152-6.848 16-16 16h-64a16 16 0 1 0 0 32h64a16 16 0 0 0 3.328-0.384 48.096 48.096 0 0 0 44.672-47.616c0-25.152-19.84-45.888-44.544-47.68a16 16 0 0 0-3.456-0.32h-32a15.616 15.616 0 0 1-16-16c0-9.152 6.848-16 16-16h64a16 16 0 1 0 0-32h-62.88a16 16 0 0 0-1.12 0 16 16 0 0 0-1.6 0z"
fill="#E9EDED" p-id="19937"></path>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1627885889837" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="17560" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M0 139.636364a46.545455 46.545455 0 0 1 46.545455-46.545455h354.897454a51.2 51.2 0 0 1 47.057455 31.034182L473.6 182.679273 977.454545 182.690909a46.545455 46.545455 0 0 1 46.545455 46.545455v546.909091a46.545455 46.545455 0 0 1-46.545455 46.545454H46.545455a46.545455 46.545455 0 0 1-46.545455-46.545454V139.636364z" fill="#FFA000" p-id="17561"></path><path d="M0 276.945455m46.545455 0l930.90909 0q46.545455 0 46.545455 46.545454l0 558.545455q0 46.545455-46.545455 46.545454l-930.90909 0q-46.545455 0-46.545455-46.545454l0-558.545455q0-46.545455 46.545455-46.545454Z" fill="#FFCA28" p-id="17562"></path></svg>

After

Width:  |  Height:  |  Size: 989 B

View File

@ -0,0 +1,11 @@
<svg t="1642407332637" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6055"
width="200" height="200">
<path
d="M967.111111 281.6V910.222222c0 62.577778-51.2 113.777778-113.777778 113.777778H170.666667c-62.577778 0-113.777778-51.2-113.777778-113.777778V113.777778c0-62.577778 51.2-113.777778 113.777778-113.777778h514.844444L967.111111 281.6z"
fill="#62C558" p-id="6056"></path>
<path d="M685.511111 224.711111V0L967.111111 281.6H742.4c-31.288889 0-56.888889-25.6-56.888889-56.888889"
fill="#2A8121" p-id="6057"></path>
<path
d="M682.666667 724.024889L638.691556 768 341.333333 470.670222 385.308444 426.666667zM454.087111 611.128889l44.088889 44.088889L385.422222 768 341.333333 723.911111zM682.666667 470.755556l-113.066667 113.066666-44.088889-44.088889L638.577778 426.666667z"
fill="#FFFFFF" p-id="6058"></path>
</svg>

After

Width:  |  Height:  |  Size: 894 B

View File

@ -0,0 +1,20 @@
<svg t="1642408099555" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
p-id="53361" width="200" height="200">
<path
d="M967.111111 281.6V910.222222c0 62.862222-50.915556 113.777778-113.777778 113.777778H170.666667c-62.862222 0-113.777778-50.915556-113.777778-113.777778V113.777778c0-62.862222 50.915556-113.777778 113.777778-113.777778h514.844444L967.111111 281.6z"
fill="#BABABA" p-id="53362"></path>
<path d="M685.511111 167.822222V0L967.111111 281.6H799.288889c-62.862222 0-113.777778-50.915556-113.777778-113.777778"
fill="#979797" p-id="53363"></path>
<path
d="M586.865778 521.671111a148.650667 148.650667 0 0 1-3.754667 49.265778l44.629333 22.556444a164.664889 164.664889 0 0 1-10.154666 26.254223l-4.266667 8.448a162.986667 162.986667 0 0 1-15.104 23.751111l-44.657778-22.528a149.048889 149.048889 0 0 1-37.404444 32.312889l15.587555 47.388444a192.910222 192.910222 0 0 1-62.179555 20.48l-15.587556-47.416889a148.053333 148.053333 0 0 1-49.322666-3.783111l-22.528 44.657778a163.612444 163.612444 0 0 1-26.254223-10.154667l-8.448-4.266667a158.350222 158.350222 0 0 1-23.751111-15.132444l22.528-44.600889a147.569778 147.569778 0 0 1-32.312889-37.461333l-47.416888 15.644444a195.868444 195.868444 0 0 1-12.856889-30.264889l-7.594667-31.943111 47.416889-15.616a148.650667 148.650667 0 0 1 3.754667-49.294222l-44.600889-22.528c2.190222-7.452444 4.892444-14.904889 8.078222-21.959111l8.533333-16.952889c3.84-6.769778 8.220444-13.368889 12.885334-19.569778l44.629333 22.528c10.353778-12.515556 23.04-23.608889 37.432889-32.284444l-15.587556-47.416889c9.557333-5.034667 19.626667-9.386667 30.236445-12.885333L410.737778 341.333333l15.587555 47.416889a147.370667 147.370667 0 0 1 49.322667 3.754667l22.528-44.629333c7.452444 2.190222 14.876444 4.920889 21.959111 8.106666l4.266667 2.048 8.504889 4.266667 4.181333 2.275555c6.741333 3.754667 13.368889 8.135111 19.569778 12.828445l-22.528 44.657778a147.911111 147.911111 0 0 1 32.284444 37.404444l47.416889-15.587555a195.527111 195.527111 0 0 1 20.451556 62.179555l-47.416889 15.587556z"
fill="#FFFFFF" p-id="53364"></path>
<path
d="M520.618667 508.984889a84.707556 84.707556 0 1 1-160.938667 52.963555 84.707556 84.707556 0 0 1 160.938667-52.963555"
fill="#BABABA" p-id="53365"></path>
<path
d="M742.371556 771.84c-4.864 6.826667-10.865778 12.743111-17.521778 17.436444l9.557333 23.096889c-3.896889 2.56-8.106667 4.807111-12.401778 6.656l-4.408889 1.792a79.644444 79.644444 0 0 1-13.454222 4.067556l-9.557333-23.096889c-7.992889 1.365333-16.440889 1.422222-24.746667 0l-9.557333 23.04a97.792 97.792 0 0 1-30.208-12.515556l9.557333-23.04a74.524444 74.524444 0 0 1-17.464889-17.521777l-23.096889 9.557333a82.488889 82.488889 0 0 1-6.627555-12.430222l-1.792-4.380445a80.554667 80.554667 0 0 1-4.096-13.454222l23.096889-9.557333a75.264 75.264 0 0 1 0-24.746667l-23.068445-9.557333a98.986667 98.986667 0 0 1 5.006223-15.644445l7.566222-14.592 23.04 9.557334c4.835556-6.826667 10.894222-12.743111 17.521778-17.436445l-9.557334-23.096889c3.271111-2.104889 6.741333-4.039111 10.24-5.688889l8.789334-3.612444c3.640889-1.308444 7.452444-2.389333 11.235555-3.214222l9.557333 23.096889c8.021333-1.365333 16.440889-1.422222 24.718223 0l9.585777-23.068445c5.233778 1.223111 10.496 2.844444 15.644445 5.006222l14.592 7.537778-9.585778 23.04c6.826667 4.892444 12.771556 10.894222 17.436445 17.521778l23.096888-9.528889c2.133333 3.271111 4.067556 6.712889 5.688889 10.24l0.967111 2.161778 1.792 4.380444 0.853334 2.218667c1.336889 3.640889 2.417778 7.480889 3.214222 11.264l-23.096889 9.557333c1.393778 7.964444 1.422222 16.440889 0 24.718223l23.04 9.557333a96 96 0 0 1-12.515555 30.236444l-23.04-9.557333z"
fill="#FFFFFF" p-id="53366"></path>
<path
d="M721.408 745.415111a42.382222 42.382222 0 1 1-78.250667-32.455111 42.382222 42.382222 0 0 1 78.222223 32.426667"
fill="#BABABA" p-id="53367"></path>
</svg>

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@ -0,0 +1,14 @@
<svg t="1642407647664" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
p-id="19787" width="200" height="200">
<path d="M847.872 240.128v688c0 26.56-21.408 48-48 48h-576c-26.56 0-48-21.44-48-48v-832c0-26.592 21.44-48 48-48h432z"
fill="#E9EDED" p-id="19788"></path>
<path d="M160 768.128v160c0 35.456 28.544 64 64 64h576c35.456 0 64-28.544 64-64v-160H160z" fill="#F05542"
p-id="19789"></path>
<path d="M847.872 240.128h-144c-26.56 0-48-21.44-48-48v-144" fill="#F05542" p-id="19790"></path>
<path
d="M432.736 384.064a16 16 0 0 0-10.976 4.8l-96.96 95.776a16 16 0 0 0-0.416 0.416 16 16 0 0 0 1.664 23.808l95.68 94.56a16 16 0 1 0 22.528-22.72l-85.568-84.576 85.568-84.48a16 16 0 0 0-11.52-27.584z m157.824 0a16 16 0 0 0-11.008 27.552l85.504 84.48-85.504 84.576a16 16 0 1 0 22.496 22.752l95.648-94.56a16 16 0 0 0 5.44-17.504 16 16 0 0 0-1.28-2.912 16 16 0 0 0-0.608-1.12 16 16 0 0 0-0.192-0.256 16 16 0 0 0-0.192-0.256 16 16 0 0 0-0.8-0.992 16 16 0 0 0-0.192-0.256 16 16 0 0 0-0.864-0.96 16 16 0 0 0-0.064 0l-0.64-0.544a16 16 0 0 0-0.48-0.512l-95.776-94.688a16 16 0 0 0-11.488-4.8z"
fill="#F05542" p-id="19791"></path>
<path
d="M654.88 799.744a16 16 0 0 0-11.84 6.624L608 853.312l-35.136-46.944-0.128 0.064a16 16 0 0 0-13.056-6.368 16 16 0 0 0-15.744 16.192v127.68a16 16 0 1 0 32 0v-80.128l15.936 21.248a16 16 0 0 0 28.864 4.448l19.2-25.6v80.032a16 16 0 1 0 32 0v-126.816a16 16 0 0 0-15.424-17.376 16 16 0 0 0-1.632 0z m-383.136 0.32a16 16 0 0 0-15.744 16.192V943.936a16 16 0 1 0 32 0v-47.808h64v47.808a16 16 0 1 0 32 0v-61.312a16 16 0 0 0 0-5.12v-61.248a16 16 0 0 0-16.256-16.192 16 16 0 0 0-15.744 16.192v47.872H288v-47.872a16 16 0 0 0-16.256-16.192z m192 0a16 16 0 0 0-1.6 0.064H432a16 16 0 1 0 0 32h16v111.808a16 16 0 1 0 32 0v-111.808h16a16 16 0 1 0 0-32h-30.304a16 16 0 0 0-1.92-0.064z m255.936 0a16 16 0 0 0-15.744 16.192v126.496a16 16 0 0 0 0.64 5.824 16 16 0 0 0 0 0.064 16 16 0 0 0 0.096 0.416 16 16 0 0 0 0.448 1.12 16 16 0 0 0 0.864 1.824 16 16 0 0 0 0.64 0.992 16 16 0 0 0 0.192 0.32 16 16 0 0 0 0.736 0.96 16 16 0 0 0 0.832 0.864 16 16 0 0 0 0.352 0.416 16 16 0 0 0 0.832 0.704 16 16 0 0 0 0.448 0.384 16 16 0 0 0 0.352 0.32 16 16 0 0 0 1.12 0.736 16 16 0 0 0 2.464 1.248 16 16 0 0 0 0.864 0.32 16 16 0 0 0 5.376 0.864h63.552a16 16 0 1 0 0-32h-47.808v-111.872a16 16 0 0 0-16.256-16.192z"
fill="#E9EDED" p-id="19792"></path>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -0,0 +1 @@
<svg viewBox="0 0 48 48" fill="none" stroke="currentColor" stroke-width="4"><path d="M26 33l5-6v6h-5zm0 0l-3-4-4 4h7zm11 9H11a2 2 0 01-2-2V8a2 2 0 012-2h21l7 7v27a2 2 0 01-2 2zM17 19h1v1h-1v-1z"/></svg>

After

Width:  |  Height:  |  Size: 202 B

View File

@ -1 +1,11 @@
<svg viewBox="0 0 48 48" fill="none" stroke="currentColor" stroke-width="4"><path d="M26 33l5-6v6h-5zm0 0l-3-4-4 4h7zm11 9H11a2 2 0 01-2-2V8a2 2 0 012-2h21l7 7v27a2 2 0 01-2 2zM17 19h1v1h-1v-1z"/></svg>
<svg t="1642407370336" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6354"
width="200" height="200">
<path
d="M952.888889 281.6V910.222222c0 62.862222-50.915556 113.777778-113.777778 113.777778H156.444444c-62.862222 0-113.777778-50.915556-113.777777-113.777778V113.777778c0-62.862222 50.915556-113.777778 113.777777-113.777778h514.844445L952.888889 281.6z"
fill="#85BCFF" p-id="6355"></path>
<path d="M676.664889 167.822222V0l281.6 281.6h-167.822222c-62.862222 0-113.777778-50.915556-113.777778-113.777778"
fill="#529EE0" p-id="6356"></path>
<path
d="M685.824 363.804444a53.76 53.76 0 0 1 53.731556 53.731556v307.029333a53.76 53.76 0 0 1-53.731556 53.731556H309.76a53.731556 53.731556 0 0 1-53.731556-53.76V417.564444c0-29.667556 24.035556-53.731556 53.731556-53.731555H685.795556z m-72.903111 149.674667l-138.183111 146.545778-80.583111-62.805333-92.131556 94.208v31.402666c0 11.548444 10.325333 20.906667 23.04 20.906667h345.400889c12.714667 0 23.04-9.386667 23.04-20.906667v-125.610666l-80.583111-83.740445z m-227.896889-85.532444a32.085333 32.085333 0 1 0 0 64.142222 32.085333 32.085333 0 0 0 0-64.142222z"
fill="#FFFFFF" p-id="6357"></path>
</svg>

Before

Width:  |  Height:  |  Size: 202 B

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,14 @@
<svg t="1642408007951" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
p-id="50023" width="200" height="200">
<path d="M847.872 240.128v688c0 26.56-21.408 48-48 48h-576c-26.56 0-48-21.44-48-48v-832c0-26.592 21.44-48 48-48h432z"
fill="#E9EDED" p-id="50024"></path>
<path d="M160 768.128v160c0 35.456 28.544 64 64 64h576c35.456 0 64-28.544 64-64v-160H160z" fill="#25B39E"
p-id="50025"></path>
<path d="M847.872 240.128h-144c-26.56 0-48-21.44-48-48v-144" fill="#25B39E" p-id="50026"></path>
<path
d="M432.256 320.128c-35.2 0-64 28.8-64 64v32c0 18.016-14.016 32-32 32a16 16 0 0 0-3.2 0.256 16 16 0 0 0-12.384 11.232 16 16 0 0 0-0.352 1.504 16 16 0 0 0 0 0.064 16 16 0 0 0 15.936 18.944c17.984 0 32 13.984 32 32v32c0 35.2 28.8 64 64 64a16 16 0 1 0 0-32c-18.016 0-32-13.984-32-32v-32c0-19.136-8.736-36.256-22.208-48a63.68 63.68 0 0 0 22.208-48v-32c0-18.016 13.984-32 32-32a16 16 0 1 0 0-32z m157.856 0a16 16 0 0 0 1.632 32c18.016 0 32 13.984 32 32v32c0 19.168 8.736 36.224 22.208 48-13.44 11.744-22.208 28.864-22.208 48v32c0 18.016-13.984 32-32 32a16 16 0 1 0 0 32c35.2 0 64-28.8 64-64v-32c0-18.016 14.016-32 32-32a16 16 0 0 0 10.368-3.616 16 16 0 0 0 1.216-1.152 16 16 0 0 0-11.584-27.232c-17.984 0-32-13.984-32-32v-32c0-35.2-28.8-64-64-64a16 16 0 0 0-1.6 0zM512 367.936a32 32 0 0 0-32 32 32 32 0 0 0 32 32 32 32 0 0 0 32-32 32 32 0 0 0-32-32z m0 96a32 32 0 0 0-32 32 32 32 0 0 0 16.256 27.872l-14.4 28.864a16 16 0 1 0 28.64 14.272l24-48.256a32 32 0 0 0 9.44-21.504 16 16 0 0 0 0-0.192 32 32 0 0 0 0.064-1.056 32 32 0 0 0-32-32z"
fill="#25B39E" p-id="50027"></path>
<path
d="M335.872 800a16 16 0 0 0-15.744 16.256V912c0 9.152-6.848 16-16 16a15.616 15.616 0 0 1-16-16 16 16 0 0 0-16.256-16.192 16 16 0 0 0-15.744 16.192c0 26.304 21.696 48 48 48 24.768 0 45.12-19.296 47.488-43.52a16 16 0 0 0 0.512-4.224v-96a16 16 0 0 0-16.256-16.256z m94.4 0.128a16 16 0 0 0-2.016 0.384c-24.64 1.92-44.384 22.528-44.384 47.616 0 25.28 20.096 46.08 44.992 47.68a16 16 0 0 0 3.008 0.32h32c9.152 0 16 6.848 16 16 0 9.152-6.848 16-16 16h-64a16 16 0 1 0 0 32h64a16 16 0 0 0 3.328-0.384 48.096 48.096 0 0 0 44.672-47.616c0-25.152-19.84-45.888-44.544-47.68a16 16 0 0 0-3.456-0.32h-30.88a16 16 0 0 0-1.12 0 15.616 15.616 0 0 1-16-16c0-9.152 6.848-16 16-16h64a16 16 0 1 0 0-32h-62.88a16 16 0 0 0-1.12 0 16 16 0 0 0-1.6 0z"
fill="#E9EDED" p-id="50028"></path>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -0,0 +1,14 @@
<svg t="1642407743753" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
p-id="20514" width="200" height="200">
<path d="M847.872 240.128v688c0 26.56-21.408 48-48 48h-576c-26.56 0-48-21.44-48-48v-832c0-26.592 21.44-48 48-48h432z"
fill="#E9EDED" p-id="20515"></path>
<path d="M160 768.128v160c0 35.456 28.544 64 64 64h576c35.456 0 64-28.544 64-64v-160H160z" fill="#F17F53"
p-id="20516"></path>
<path d="M847.872 240.128h-144c-26.56 0-48-21.44-48-48v-144" fill="#F17F53" p-id="20517"></path>
<path
d="M432.256 320.128c-35.2 0-64 28.8-64 64v32c0 18.016-14.016 32-32 32a16 16 0 0 0-15.936 12.992 16 16 0 0 0 0 0.064 16 16 0 0 0 4.736 14.56 16 16 0 0 0 2.496 1.92 16 16 0 0 0 4.448 1.92 16 16 0 0 0 3.136 0.48 16 16 0 0 0 1.12 0.064c17.984 0 32 13.984 32 32v32c0 35.2 28.8 64 64 64a16 16 0 1 0 0-32c-18.016 0-32-13.984-32-32v-32c0-19.136-8.736-36.256-22.208-48a63.68 63.68 0 0 0 22.208-48v-32c0-18.016 13.984-32 32-32a16 16 0 1 0 0-32z m125.856 0a16 16 0 0 0 1.632 32c18.016 0 32 13.984 32 32v32c0 19.168 8.736 36.224 22.208 48-13.44 11.744-22.208 28.864-22.208 48v32c0 18.016-13.984 32-32 32a16 16 0 1 0 0 32c35.2 0 64-28.8 64-64v-32c0-18.016 14.016-32 32-32a16 16 0 0 0 10.368-3.616 16 16 0 0 0 1.216-1.152 16 16 0 0 0-11.584-27.232c-17.984 0-32-13.984-32-32v-32c0-35.2-28.8-64-64-64a16 16 0 0 0-1.6 0zM496 384a16 16 0 0 0-16 16 16 16 0 0 0 16 16 16 16 0 0 0 16-16 16 16 0 0 0-16-16z m-0.256 63.808A16 16 0 0 0 480 464v96a16 16 0 1 0 32 0v-96a16 16 0 0 0-16.256-16.192z"
fill="#F17F53" p-id="20518"></path>
<path
d="M720.576 799.616a16 16 0 0 0-1.632 0.064 16 16 0 0 0-15.008 17.312v126.816a16 16 0 1 0 32 0v-80l66.624 88.96a16 16 0 0 0 0.064 0.096l0.448 0.576a16 16 0 0 0 28.864-9.6v-127.68a16 16 0 0 0-16.256-16.224 16 16 0 0 0-15.744 16.256v79.68l-67.136-89.6a16 16 0 0 0-12.224-6.656zM303.744 800a16 16 0 0 0-15.744 16.256V912c0 9.152-6.848 16-16 16a15.616 15.616 0 0 1-16-16 16 16 0 0 0-16.256-16.192A16 16 0 0 0 224 912c0 26.304 21.696 48 48 48 24.768 0 45.152-19.296 47.488-43.52a16 16 0 0 0 0.512-4.224v-96A16 16 0 0 0 303.744 800z m288.256 0a80.256 80.256 0 0 0-80 80c0 44 36 80 80 80s80-36 80-80-36-80-80-80z m-193.888 0.128a16 16 0 0 0-1.984 0.384c-24.64 1.92-44.384 22.528-44.384 47.616 0 25.28 20.096 46.08 44.992 47.68a16 16 0 0 0 3.008 0.32h32c9.152 0 16 6.848 16 16 0 9.152-6.848 16-16 16h-64a16 16 0 1 0 0 32h64a16 16 0 0 0 3.328-0.384 48.096 48.096 0 0 0 44.672-47.616c0-25.152-19.84-45.888-44.544-47.68a16 16 0 0 0-3.456-0.32h-30.88a16 16 0 0 0-1.12 0 15.616 15.616 0 0 1-16-16c0-9.152 6.88-16 16-16h64a16 16 0 1 0 0-32h-62.88a16 16 0 0 0-1.12 0 16 16 0 0 0-1.6 0zM592 832c26.688 0 48 21.312 48 48s-21.312 48-48 48-48-21.312-48-48 21.312-48 48-48z"
fill="#E9EDED" p-id="20519"></path>
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@ -0,0 +1,11 @@
<svg t="1642407502942" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7293"
width="200" height="200">
<path
d="M967.111111 281.6V910.222222c0 62.862222-50.915556 113.777778-113.777778 113.777778H170.666667c-62.862222 0-113.777778-50.915556-113.777778-113.777778V113.777778c0-62.862222 50.915556-113.777778 113.777778-113.777778h514.844444L967.111111 281.6z"
fill="#A15FDE" p-id="7294"></path>
<path d="M685.511111 196.266667V0L967.111111 281.6H770.844444a85.333333 85.333333 0 0 1-85.333333-85.333333"
fill="#C386F0" p-id="7295"></path>
<path
d="M669.980444 426.268444v236.999112c0 26.254222-31.857778 47.587556-71.082666 47.587555-39.253333 0-70.741333-21.333333-70.741334-47.587555 0-26.282667 31.516444-47.587556 70.741334-47.587556 14.848 0 28.728889 3.100444 40.163555 8.334222v-165.916444l-205.767111 48.497778v211.057777c0 26.254222-32.142222 47.559111-71.992889 47.559111-39.850667 0-72.305778-21.333333-72.305777-47.559111 0-26.282667 32.426667-47.587556 72.305777-47.587555a96.711111 96.711111 0 0 1 41.102223 8.647111V474.168889c0-14.222222 9.870222-26.88 23.779555-29.980445l205.795556-47.900444a30.862222 30.862222 0 0 1 38.001777 29.980444"
fill="#FFFFFF" p-id="7296"></path>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,11 @@
<svg t="1642408119178" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
p-id="53519" width="200" height="200">
<path
d="M967.111111 281.6V910.222222c0 62.862222-50.915556 113.777778-113.777778 113.777778H170.666667c-62.862222 0-113.777778-50.915556-113.777778-113.777778V113.777778c0-62.862222 50.915556-113.777778 113.777778-113.777778h514.844444L967.111111 281.6z"
fill="#BABABA" p-id="53520"></path>
<path d="M685.511111 167.822222V0L967.111111 281.6H799.288889c-62.862222 0-113.777778-50.915556-113.777778-113.777778"
fill="#979797" p-id="53521"></path>
<path
d="M733.667556 632.689778a111.104 111.104 0 0 1-110.819556 110.819555h-221.667556a111.132444 111.132444 0 0 1-110.848-110.819555 111.047111 111.047111 0 0 1 99.754667-110.279111A122.197333 122.197333 0 0 1 512 407.694222a122.197333 122.197333 0 0 1 121.912889 114.716445 111.160889 111.160889 0 0 1 99.754667 110.279111"
fill="#FFFFFF" p-id="53522"></path>
</svg>

After

Width:  |  Height:  |  Size: 992 B

View File

@ -0,0 +1 @@
<svg viewBox="0 0 48 48" fill="none" stroke="currentColor" stroke-width="4"><path d="M11 42h26a2 2 0 002-2V13.828a2 2 0 00-.586-1.414l-5.828-5.828A2 2 0 0031.172 6H11a2 2 0 00-2 2v32a2 2 0 002 2z"/><path d="M22.305 21.028c.874 1.939 3.506 6.265 4.903 8.055 1.747 2.237 3.494 2.685 4.368 2.237.873-.447 1.21-4.548-7.425-2.685-7.523 1.623-7.424 3.58-6.988 4.476.728 1.193 2.522 2.627 5.678-6.266C25.699 18.79 24.489 17 23.277 17c-1.409 0-2.538.805-.972 4.028z"/></svg>

After

Width:  |  Height:  |  Size: 466 B

View File

@ -1 +1,11 @@
<svg viewBox="0 0 48 48" fill="none" stroke="currentColor" stroke-width="4"><path d="M11 42h26a2 2 0 002-2V13.828a2 2 0 00-.586-1.414l-5.828-5.828A2 2 0 0031.172 6H11a2 2 0 00-2 2v32a2 2 0 002 2z"/><path d="M22.305 21.028c.874 1.939 3.506 6.265 4.903 8.055 1.747 2.237 3.494 2.685 4.368 2.237.873-.447 1.21-4.548-7.425-2.685-7.523 1.623-7.424 3.58-6.988 4.476.728 1.193 2.522 2.627 5.678-6.266C25.699 18.79 24.489 17 23.277 17c-1.409 0-2.538.805-.972 4.028z"/></svg>
<svg t="1642407248989" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5608"
width="200" height="200">
<path
d="M967.111111 281.6V910.222222c0 62.577778-51.2 113.777778-113.777778 113.777778H170.666667c-62.577778 0-113.777778-51.2-113.777778-113.777778V113.777778c0-62.577778 51.2-113.777778 113.777778-113.777778h514.844444L967.111111 281.6z"
fill="#D23B41" p-id="5609"></path>
<path d="M685.511111 224.711111V0L967.111111 281.6H742.4c-31.288889 0-56.888889-25.6-56.888889-56.888889"
fill="#9C171C" p-id="5610"></path>
<path
d="M680.277333 662.698667c-11.889778-1.194667-23.751111-3.640889-35.640889-9.728 10.666667-2.133333 20.110222-2.133333 30.776889-2.133334 23.751111 0 28.330667 5.774222 28.330667 9.443556-6.997333 2.417778-15.246222 3.356444-23.466667 2.417778z m-120.945777-15.530667c-25.884444 5.802667-54.556444 14.336-80.440889 23.779556v-2.446223l-2.446223 1.223111c13.084444-26.197333 25.002667-53.333333 35.640889-80.753777l0.938667 1.223111 1.194667-2.133334c13.112889 20.110222 29.866667 40.220444 47.530666 57.884445h-3.640889l1.223112 1.223111zM497.777778 417.450667c1.223111-1.223111 3.669333-1.223111 4.551111-1.223111h3.697778a96.739556 96.739556 0 0 1-1.251556 61.553777c-8.220444-18.915556-11.861333-40.220444-6.997333-60.330666zM352.142222 770.275556l-3.669333 1.223111a96.768 96.768 0 0 1 42.666667-34.417778c-9.443556 15.502222-22.556444 27.392-38.997334 33.194667z m324.494222-155.107556c-25.002667 0-49.664 3.669333-74.666666 8.248889a353.365333 353.365333 0 0 1-73.415111-94.776889c20.110222-66.417778 21.333333-111.217778 5.774222-132.551111a39.253333 39.253333 0 0 0-30.748445-15.502222c-15.246222-1.223111-29.582222 6.087111-36.579555 18.887111-21.333333 35.640889 9.443556 105.415111 23.779555 134.058666-16.782222 50.887111-36.864 99.328-63.089777 146.858667-112.412444 48.440889-114.858667 77.994667-114.858667 88.661333 0 13.084444 7.310222 26.197333 20.110222 32 4.864 3.640889 11.889778 4.835556 17.976889 4.835556 29.582222 0 64-33.194667 100.551111-98.389333 46.307556-18.887111 92.615111-34.133333 141.084445-44.8a153.941333 153.941333 0 0 0 87.722666 35.356444c20.110222 0 59.107556 0 59.107556-40.220444 1.223111-15.530667-6.997333-41.443556-62.748445-42.666667z"
fill="#FFFFFF" p-id="5611"></path>
</svg>

Before

Width:  |  Height:  |  Size: 466 B

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -0,0 +1,12 @@
<svg t="1642407349568" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6204"
width="200" height="200">
<path
d="M967.111111 281.6V910.222222c0 62.577778-51.2 113.777778-113.777778 113.777778H170.666667c-62.577778 0-113.777778-51.2-113.777778-113.777778V113.777778c0-62.577778 51.2-113.777778 113.777778-113.777778h514.844444L967.111111 281.6z"
fill="#F16C41" p-id="6205"></path>
<path d="M685.511111 224.711111V0L967.111111 281.6H742.4c-31.288889 0-56.888889-25.6-56.888889-56.888889"
fill="#CD4B29" p-id="6206"></path>
<path
d="M525.880889 648.135111a88.32 88.32 0 0 1-68.750222-32.995555 87.04 87.04 0 0 1-19.626667-55.381334c0-21.048889 7.253333-40.248889 19.626667-55.381333a88.234667 88.234667 0 0 1 68.750222-32.995556 88.490667 88.490667 0 0 1 88.376889 88.376889 88.519111 88.519111 0 0 1-88.376889 88.376889m0-235.690667c-24.945778 0-48.327111 6.087111-68.750222 17.294223a143.075556 143.075556 0 0 0-58.88 56.945777v146.119112a143.132444 143.132444 0 0 0 58.88 56.974222c20.423111 11.178667 43.804444 17.265778 68.750222 17.265778a147.342222 147.342222 0 0 0 147.285333-147.285334 147.342222 147.342222 0 0 0-147.285333-147.342222"
fill="#FFFFFF" p-id="6207"></path>
<path d="M398.222222 824.888889h58.908445V412.444444H398.222222z" fill="#FFFFFF" p-id="6208"></path>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -0,0 +1,16 @@
<svg t="1642407407406" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6649"
width="200" height="200">
<path
d="M967.111111 281.6V910.222222c0 62.862222-50.915556 113.777778-113.777778 113.777778H170.666667c-62.862222 0-113.777778-50.915556-113.777778-113.777778V113.777778c0-62.862222 50.915556-113.777778 113.777778-113.777778h514.844444L967.111111 281.6z"
fill="#FFC63A" p-id="6650"></path>
<path d="M685.511111 167.822222V0L967.111111 281.6H799.288889c-62.862222 0-113.777778-50.915556-113.777778-113.777778"
fill="#DD9F08" p-id="6651"></path>
<path
d="M436.565333 68.437333h68.437334V0h-68.437334zM505.002667 136.874667h68.437333V68.437333h-68.437333zM436.565333 205.312h68.437334V136.874667h-68.437334zM505.002667 273.749333h68.437333V205.312h-68.437333z"
fill="#FFFFFF" p-id="6652"></path>
<path d="M436.565333 342.158222h68.437334V273.720889h-68.437334zM505.002667 410.624h68.437333V342.186667h-68.437333z"
fill="#FFFFFF" p-id="6653"></path>
<path
d="M436.565333 479.032889h68.437334v-68.437333h-68.437334zM505.002667 547.470222h68.437333v-68.437333h-68.437333zM470.784 762.225778h68.437333v-68.437334h-68.437333v68.437334z m-34.218667-136.874667v136.874667c0 18.915556 15.331556 34.218667 34.218667 34.218666h68.437333c18.915556 0 34.218667-15.303111 34.218667-34.218666v-136.874667h-136.874667z"
fill="#FFFFFF" p-id="6654"></path>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -0,0 +1,11 @@
<svg t="1642407315436" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5906"
width="200" height="200">
<path
d="M967.111111 281.6V910.222222c0 62.862222-50.915556 113.777778-113.777778 113.777778H170.666667c-62.862222 0-113.777778-50.915556-113.777778-113.777778V113.777778c0-62.862222 50.915556-113.777778 113.777778-113.777778h514.844444L967.111111 281.6z"
fill="#6D9FE5" p-id="5907"></path>
<path d="M685.511111 167.822222V0L967.111111 281.6H799.288889c-62.862222 0-113.777778-50.915556-113.777778-113.777778"
fill="#4B80CB" p-id="5908"></path>
<path
d="M344.177778 485.575111h312.888889V426.666667h-312.888889zM471.153778 770.019556h58.908444v-284.444445h-58.908444z"
fill="#FFFFFF" p-id="5909"></path>
</svg>

After

Width:  |  Height:  |  Size: 785 B

View File

@ -0,0 +1 @@
<svg viewBox="0 0 48 48" fill="none" stroke="currentColor" stroke-width="4"><path d="M37 42H11a2 2 0 01-2-2V8a2 2 0 012-2h21l7 7v27a2 2 0 01-2 2z"/><path d="M22 27.796v-6l5 3-5 3z"/></svg>

After

Width:  |  Height:  |  Size: 188 B

View File

@ -1 +1,14 @@
<svg viewBox="0 0 48 48" fill="none" stroke="currentColor" stroke-width="4"><path d="M37 42H11a2 2 0 01-2-2V8a2 2 0 012-2h21l7 7v27a2 2 0 01-2 2z"/><path d="M22 27.796v-6l5 3-5 3z"/></svg>
<svg t="1642407389455" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6501"
width="200" height="200">
<path
d="M967.111111 281.6V910.222222c0 62.862222-50.915556 113.777778-113.777778 113.777778H170.666667c-62.862222 0-113.777778-50.915556-113.777778-113.777778V113.777778c0-62.862222 50.915556-113.777778 113.777778-113.777778h514.844444L967.111111 281.6z"
fill="#C386F0" p-id="6502"></path>
<path
d="M284.444444 398.222222m42.666667 0l298.666667 0q42.666667 0 42.666666 42.666667l0 234.666667q0 42.666667-42.666666 42.666666l-298.666667 0q-42.666667 0-42.666667-42.666666l0-234.666667q0-42.666667 42.666667-42.666667Z"
fill="#FFFFFF" p-id="6503"></path>
<path
d="M738.417778 457.841778a31.971556 31.971556 0 0 1 48.014222 27.676444v154.538667c0 24.632889-26.652444 40.021333-47.985778 27.704889L684.430222 636.586667V488.96z"
fill="#FFFFFF" p-id="6504"></path>
<path d="M685.511111 167.822222V0L967.111111 281.6H799.288889c-62.862222 0-113.777778-50.915556-113.777778-113.777778"
fill="#A15FDE" p-id="6505"></path>
</svg>

Before

Width:  |  Height:  |  Size: 188 B

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,13 @@
<svg t="1642407280584" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5757"
width="200" height="200">
<path
d="M967.111111 281.6V910.222222c0 62.577778-51.2 113.777778-113.777778 113.777778H170.666667c-62.577778 0-113.777778-51.2-113.777778-113.777778V113.777778c0-62.577778 51.2-113.777778 113.777778-113.777778h514.844444L967.111111 281.6z"
fill="#4F6BF6" p-id="5758"></path>
<path d="M581.262222 755.626667h59.363556L739.555556 439.04h-59.335112z" fill="#FFFFFF" p-id="5759"></path>
<path d="M685.511111 224.711111V0L967.111111 281.6H742.4c-31.288889 0-56.888889-25.6-56.888889-56.888889"
fill="#243EBB" p-id="5760"></path>
<path
d="M640.625778 755.626667h-59.363556l-98.929778-277.020445h59.335112zM442.737778 755.626667h-59.363556L284.444444 439.04h59.335112z"
fill="#FFFFFF" p-id="5761"></path>
<path d="M383.374222 755.626667h59.363556l98.929778-277.020445h-59.335112z" fill="#FFFFFF" p-id="5762"></path>
</svg>

After

Width:  |  Height:  |  Size: 995 B

View File

@ -0,0 +1 @@
<svg t="1642421944380" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="865" width="200" height="200"><path d="M97.9 376h828.4v269.2H97.9z" fill="#F95F5D" p-id="866"></path><path d="M926.3 376V161.5c0-26.6-23.8-50.3-52.1-50.3H149.9c-28.3 0-52.1 23.7-52.1 50.3V376h828.5z m0 0" fill="#55C7F7" p-id="867"></path><path d="M97.9 645.2v214.5c0 26.6 23.6 50.3 51.7 50.3h725c28.1 0 51.7-23.7 51.7-50.3V645.2H97.9z m0 0" fill="#7ECF3B" p-id="868"></path><path d="M421.8 111.2h184.9V910H421.8z" fill="#FDAF42" p-id="869"></path><path d="M606.7 457.4v112.4H413V457.4h193.7m31.1-45.9H381.9c-4.4 0-11.8 4.4-11.8 11.8v179c0 4.4 4.4 11.8 11.8 11.8h255.9c4.4 0 11.8-4.4 11.8-11.8v-179c-2.9-8.8-7.4-11.8-11.8-11.8z m0 0" fill="#FFFFFF" p-id="870"></path></svg>

After

Width:  |  Height:  |  Size: 787 B

View File

@ -0,0 +1 @@
<svg t="1684652847211" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2238" width="200" height="200"><path d="M0 0m372.363636 0l279.272728 0q372.363636 0 372.363636 372.363636l0 279.272728q0 372.363636-372.363636 372.363636l-279.272728 0q-372.363636 0-372.363636-372.363636l0-279.272728q0-372.363636 372.363636-372.363636Z" fill="#F7A647" p-id="2239"></path><path d="M232.727273 303.872C232.727273 290.327273 243.781818 279.272727 257.326545 279.272727h148.631273c5.620364 0 10.984727 2.292364 14.848 6.283637l50.897455 52.805818c1.186909 1.233455 2.210909 2.594909 3.037091 4.049454h259.874909c31.138909 0 56.657455 25.460364 56.657454 56.610909V688.058182c0 31.150545-25.518545 56.669091-56.657454 56.669091H289.396364C258.245818 744.727273 232.727273 719.208727 232.727273 688.058182V303.872zM726.702545 556.218182h-239.825454a10.216727 10.216727 0 0 0-10.205091 10.205091v25.390545c0 5.620364 4.584727 10.205091 10.205091 10.205091h239.825454a10.216727 10.216727 0 0 0 10.205091-10.205091v-25.390545a10.216727 10.216727 0 0 0-10.205091-10.205091z m-0.058181-87.691637h-239.825455a10.216727 10.216727 0 0 0-10.205091 10.205091h-0.069818v25.390546c0 5.632 4.573091 10.216727 10.205091 10.216727h239.895273a10.216727 10.216727 0 0 0 10.205091-10.216727V478.72a10.216727 10.216727 0 0 0-10.205091-10.205091z" fill="#FFFFFF" p-id="2240"></path></svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -0,0 +1,47 @@
/** @desc 文件模块-映射 */
export interface fileTypeListItem {
name: string
value: number
menuIcon: string
icon: string
}
// 文件分类
export const fileTypeList: fileTypeListItem[] = [
{ name: '全部', value: 0, menuIcon: 'menu-file', icon: 'icon-stamp' },
{ name: '图片', value: 1, menuIcon: 'file-image', icon: 'icon-file-image' },
{ name: '文档', value: 2, menuIcon: 'file-txt', icon: 'icon-file' },
{ name: '视频', value: 3, menuIcon: 'file-video', icon: 'icon-video-camera' },
{ name: '音频', value: 4, menuIcon: 'file-music', icon: 'icon-file-audio' },
{ name: '其他', value: 5, menuIcon: 'file-other', icon: 'icon-bulb' }
]
export interface FileExtendNameIconMap {
[key: string]: string
}
// 文件类型图标 Map 映射
export const fileExtendNameIconMap: FileExtendNameIconMap = {
mp3: 'file-music',
mp4: 'file-video',
dir: 'file-dir',
ppt: 'file-ppt',
doc: 'file-wps',
docx: 'file-wps',
xls: 'file-excel',
xlsx: 'file-excel',
txt: 'file-txt',
rar: 'file-rar',
zip: 'file-zip',
html: 'file-html',
css: 'file-css',
js: 'file-js',
other: 'file-other' // 未知文件
}
// 图片类型
export const imageTypeList = ['jpg', 'png', 'gif', 'jpeg']
// WPS、Office文件类型
export const officeFileType = ['ppt', 'pptx', 'doc', 'docx', 'xls', 'xlsx']

View File

@ -8,6 +8,7 @@ import localeAnnouncement from '@/views/system/announcement/locale/en-US';
import localeMessage from '@/views/system/message/locale/en-US';
import localeDict from '@/views/system/dict/locale/en-US';
import localeConfig from '@/views/system/config/locale/en-US';
import localeFile from '@/views/system/file/locale/en-US';
import localeGenerator from '@/views/tool/generator/locale/en-US';
@ -66,6 +67,7 @@ export default {
...localeMessage,
...localeDict,
...localeConfig,
...localeFile,
...localeGenerator,

View File

@ -8,6 +8,7 @@ import localeAnnouncement from '@/views/system/announcement/locale/zh-CN';
import localeMessage from '@/views/system/message/locale/zh-CN';
import localeDict from '@/views/system/dict/locale/zh-CN';
import localeConfig from '@/views/system/config/locale/zh-CN';
import localeFile from '@/views/system/file/locale/zh-CN';
import localeGenerator from '@/views/tool/generator/locale/zh-CN';
@ -66,6 +67,7 @@ export default {
...localeMessage,
...localeDict,
...localeConfig,
...localeFile,
...localeGenerator,

View File

@ -84,6 +84,15 @@ const System: AppRouteRecordRaw = {
requiresAuth: true,
},
},
{
name: 'File',
path: '/system/file',
component: () => import('@/views/system/file/index.vue'),
meta: {
locale: 'menu.system.file.list',
requiresAuth: true,
},
},
],
};

View File

@ -0,0 +1,42 @@
import { defineStore } from 'pinia';
import { ref, computed } from 'vue';
import type { FileItem } from '@/api/system/file';
type TViewMode = 'grid' | 'list';
const storeSetup = () => {
const viewMode = ref<TViewMode>('grid'); // 视图: grid宫格模式 list列表模式
const isBatchMode = ref(false); // 是否批量操作
const selectedFileList = ref<FileItem[]>([]);
const selectedFileIds = computed(() =>
selectedFileList.value.map((i) => i.id),
);
// 改变视图模式
const changeViewMode = () => {
viewMode.value = viewMode.value === 'grid' ? 'list' : 'grid';
};
// 添加选中的文件到文件勾选列表
const addSelectedFileItem = (item: FileItem) => {
if (selectedFileIds.value.includes(item.id)) {
const index = selectedFileList.value.findIndex((i) => i.id === item.id);
selectedFileList.value.splice(index, 1);
} else {
selectedFileList.value.push(item);
}
};
return {
viewMode,
isBatchMode,
selectedFileList,
selectedFileIds,
changeViewMode,
addSelectedFileItem,
};
};
export const useFileStore = defineStore('file', storeSetup, {
// persist: { storage: localStorage, paths: ['viewMode', 'selectedFileList'] },
});

View File

@ -0,0 +1,176 @@
<template>
<a-modal
v-model:visible="visible"
title="移动到"
width="90%"
modal-animation-name="el-dialog"
mask-animation-name="el-mask"
:modal-style="{ maxWidth: '500px' }"
@close="cancel"
@before-ok="save"
>
<a-form
ref="FormRef"
:model="form"
:style="{ width: '100%' }"
auto-label-width
>
<a-form-item
field="path"
label="目标路径"
:rules="[{ required: true, message: '请输入目标路径' }]"
>
<a-input v-model="form.path" placeholder="请输入" />
</a-form-item>
</a-form>
<section class="tree-box">
<a-tree
show-line
size="mini"
block-node
:data="treeData"
@select="handleClickNode"
>
<template #switcher-icon="node, { expanded }">
<GiSvgIcon
v-if="node.children && expanded"
class="switcher-icon"
name="plus-square"
:size="16"
/>
<GiSvgIcon
v-else-if="node.children && !expanded"
class="switcher-icon"
name="minus-square"
:size="16"
style="transform: rotate(0deg)"
/>
<icon-drive-file v-else :size="16" />
</template>
<template #icon>
<GiSvgIcon name="menu-zip" :size="16"></GiSvgIcon>
</template>
</a-tree>
</section>
</a-modal>
</template>
<script setup lang="ts">
import type { FormInstance, Modal, TreeInstance } from '@arco-design/web-vue';
import type { FileItem } from '@/api/system/file';
import { onMounted, reactive, ref } from 'vue';
// import GiSvgIcon from '@/components/GiSvgIcon/index.vue';
interface Props {
fileInfo: FileItem;
onClose: () => void;
}
const props = withDefaults(defineProps<Props>(), {});
const visible = ref(false);
type TForm = { path: string };
const form: TForm = reactive({ path: '/' });
const treeData = ref<object[]>([]);
treeData.value = [
{
title: '图片文件夹',
key: '0-0',
children: [
{
title: '图片文件夹1',
key: '0-0-0',
children: [
{ title: '图片文件夹1-1', key: '0-0-0-0' },
{ title: '图片文件夹1-2', key: '0-0-0-1' },
{ title: '图片文件夹1-3', key: '0-0-0-2' },
],
},
{
title: '新建文件夹',
key: '0-0-1',
},
{
title: '视频文件夹',
key: '0-0-2',
children: [
{ title: '视频文件夹1', key: '0-0-2-0' },
{ title: '视频文件夹2', key: '0-0-2-1' },
],
},
],
},
{
title: '音频文件夹',
key: '0-1',
},
{
title: '音频文件夹1',
key: '0-2',
children: [
{
title: '音频文件夹1-1',
key: '0-2-0',
children: [
{ title: '音频文件夹1-1-1', key: '0-2-0-0' },
{ title: '音频文件夹1-1-2', key: '0-2-0-1' },
],
},
],
},
];
onMounted(() => {
visible.value = true;
});
const handleClickNode: TreeInstance['onSelect'] = (selectedKeys, data) => {
form.path = `/${data.selectedNodes[0].title}`;
};
const cancel = () => {
visible.value = false;
props.onClose();
};
//
const saveApi = (): Promise<boolean> => {
return new Promise((resolve) => {
setTimeout(() => {
resolve(true);
}, 2000);
});
};
const FormRef = ref<FormInstance | null>(null);
const save: InstanceType<typeof Modal>['onBeforeOk'] = async () => {
const flag = await FormRef.value?.validate();
if (flag) return false;
return saveApi();
};
</script>
<style lang="less" scoped>
.label {
color: var(--color-text-2);
}
.switcher-icon {
fill: var(--color-text-2);
}
:deep(.arco-form-item-label-col > label) {
white-space: nowrap;
}
:deep(.arco-tree-node-switcher-icon) {
display: flex;
justify-content: center;
align-items: center;
}
.tree-box {
width: 100%;
height: 300px;
padding: 10px 16px;
box-sizing: border-box;
border: 1px solid var(--color-border);
overflow: auto;
}
</style>

View File

@ -0,0 +1,85 @@
<template>
<a-modal
v-model:visible="visible"
title="重命名"
width="90%"
modal-animation-name="el-fade"
:modal-style="{ maxWidth: '500px' }"
@close="cancel"
@before-ok="save"
>
<a-row justify="center" align="center">
<a-form
ref="FormRef"
:model="form"
auto-label-width
:style="{ width: '80%' }"
>
<a-form-item
field="name"
label="文件名称"
:rules="[{ required: true, message: '请输入文件名称' }]"
>
<a-input v-model="form.name" placeholder="请输入" allow-clear />
</a-form-item>
</a-form>
</a-row>
</a-modal>
</template>
<script setup lang="ts">
import type { FormInstance, Modal } from '@arco-design/web-vue';
import type { FileItem } from '@/api/system/file';
import { onMounted, reactive, ref } from 'vue';
interface Props {
fileInfo: FileItem;
onClose: () => void;
}
const props = withDefaults(defineProps<Props>(), {});
const visible = ref(false);
type Form = { name: string };
const form: Form = reactive({
name: '',
});
onMounted(() => {
form.name = props.fileInfo?.name || '';
visible.value = true;
});
const cancel = () => {
visible.value = false;
props.onClose();
};
//
const saveApi = (): Promise<boolean> => {
return new Promise((resolve) => {
setTimeout(() => {
resolve(true);
}, 2000)
}
);
};
const FormRef = ref<FormInstance | null>(null);
const save: InstanceType<typeof Modal>['onBeforeOk'] = async () => {
const flag = await FormRef.value?.validate();
if (flag) return false;
return saveApi();
};
</script>
<style lang="less" scoped>
.label {
color: var(--color-text-2);
}
:deep(.arco-form-item) {
margin-bottom: 0;
}
:deep(.arco-form-item-label-col > label) {
white-space: nowrap;
}
</style>

View File

@ -0,0 +1,148 @@
<template>
<transition name="slide-dynamic-origin">
<div
v-show="visible"
ref="audioRef"
class="audio-preview-wrapper"
:style="audioStyle"
>
<section style="padding: 10px 14px 14px 14px">
<div ref="audioHeadRef" class="head">
<div class="name">
<icon-music :size="16" spin />
<span
>{{ props.fileInfo?.name }}.{{ props.fileInfo?.extendName }}</span
>
</div>
<div class="close-icon" @click="close">
<icon-close :size="12" />
</div>
</div>
<!-- 音频组件 -->
<audio class="audio" :src="audioSrc" controls autoplay></audio>
</section>
</div>
</transition>
</template>
<script setup lang="ts">
import { useDraggable, useWindowSize, useElementSize } from '@vueuse/core';
import type { FileItem } from '@/api/system/file';
import { computed, onMounted, ref } from 'vue';
interface Props {
fileInfo: FileItem;
onClose: () => void;
}
const props = withDefaults(defineProps<Props>(), {});
const visible = ref(false);
const audioRef = ref<HTMLElement | null>(null);
const audioHeadRef = ref<HTMLElement | null>(null);
const audioSrc = computed(() => {
return props.fileInfo?.src || '';
});
onMounted(() => {
visible.value = true;
});
const { width: windowWidth, height: windowHeight } = useWindowSize();
const { width: boxWidth, height: boxHeight } = useElementSize(audioRef);
const axis = ref({ top: 40, left: windowWidth.value - boxWidth.value });
const obj = JSON.parse(sessionStorage.getItem('AudioDialogXY') as string);
if (obj && obj.top && obj.left) {
axis.value.top = obj.top;
axis.value.left = obj.left;
}
const { x, y } = useDraggable(audioRef, {
initialValue: { x: axis.value.left - boxWidth.value, y: axis.value.top },
});
const audioStyle = computed(() => {
let left: number | string = x.value;
let top: number | string = y.value;
if (x.value > windowWidth.value - boxWidth.value) {
left = windowWidth.value - boxWidth.value;
}
if (x.value < 0) {
left = 0;
}
if (y.value > windowHeight.value - boxHeight.value) {
top = windowHeight.value - boxHeight.value;
}
if (y.value < 0) {
top = 0;
}
sessionStorage.setItem('AudioDialogXY', JSON.stringify({ top, left }));
return {
left: `${left}px`,
top: `${top}px`,
};
});
const close = () => {
visible.value = false;
props.onClose();
};
</script>
<style lang="less" scoped>
.audio-preview-wrapper {
width: 300px;
position: fixed;
border-radius: 8px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
background: linear-gradient(to right, rgb(var(--primary-6)), rgb(var(--primary-2)));
z-index: 9999;
.head {
color: #fff;
font-size: 16px;
margin-bottom: 10px;
display: flex;
justify-content: space-between;
align-items: center;
cursor: move;
user-select: none;
&:active {
cursor: move;
}
.name {
display: flex;
align-items: center;
> span {
margin-left: 8px;
}
}
.close-icon {
width: 24px;
height: 24px;
display: flex;
justify-content: center;
align-items: center;
border-radius: 50%;
background: rgba(0, 0, 0, 0);
transition: all 0.2s;
cursor: pointer;
svg {
transition: all 0.2s;
}
&:hover {
background: rgba(0, 0, 0, 0.1);
svg {
transform: scale(1.3);
}
}
}
}
.audio {
width: 100%;
&::-webkit-media-controls-enclosure {
background: #fff;
}
}
}
</style>

View File

@ -0,0 +1,45 @@
<template>
<a-modal
v-model:visible="visible"
title="视频播放"
width="auto"
draggable
@close="close"
>
<div id="videoId"></div>
</a-modal>
</template>
<script setup lang="ts">
import Player from 'xgplayer';
import type { FileItem } from '@/api/system/file';
import { nextTick, onMounted, ref } from 'vue';
interface Props {
fileInfo: FileItem;
onClose: () => void;
}
const props = withDefaults(defineProps<Props>(), {});
const visible = ref(false);
onMounted(() => {
visible.value = true;
nextTick(() => {
// eslint-disable-next-line no-new
new Player({
id: 'videoId',
url: props.fileInfo?.src || '',
lang: 'zh-cn',
autoplay: true,
closeVideoClick: true,
videoInit: true,
});
});
});
const close = () => {
visible.value = false;
props.onClose();
};
</script>

View File

@ -0,0 +1,68 @@
import type { Component } from 'vue';
import { createApp } from 'vue';
import ArcoVueIcon from '@arco-design/web-vue/es/icon';
import ArcoVue from '@arco-design/web-vue';
import { FileItem } from '@/api/system/file';
import FileMoveModal from './FileMoveModal/index.vue';
import FileRenameModal from './FileRenameModal/index.vue';
import PreviewVideoModal from './PreviewVideoModal/index.vue';
import PreviewAudioModal from './PreviewAudioModal/index.vue';
function createModal<T extends { callback?: () => void }>(
component: Component,
options?: T,
) {
// 创建一个挂载容器
const el: HTMLElement = document.createElement('div');
// 挂载组件
document.body.appendChild(el);
// 实例化组件, createApp 第二个参数是 props
const instance = createApp(component, {
...options,
onClose: () => {
setTimeout(() => {
instance.unmount();
document.body.removeChild(el);
// options?.callback && options?.callback();
}, 350);
},
});
instance.use(ArcoVue);
instance.use(ArcoVueIcon);
instance.mount(el);
}
type TFileOptions = { fileInfo: FileItem; callback?: () => void };
/** 打开 文件移动 弹窗 */
export function openFileMoveModal(fileItem: FileItem) {
return createModal<TFileOptions>(FileMoveModal, { fileInfo: fileItem });
}
/** 打开 文件重命名 弹窗 */
export function openFileRenameModal(fileItem: FileItem) {
return createModal<TFileOptions>(FileRenameModal, { fileInfo: fileItem });
}
/** 预览 视频文件 弹窗 */
export function previewFileVideoModal(fileItem: FileItem) {
return createModal<TFileOptions>(PreviewVideoModal, { fileInfo: fileItem });
}
/** 预览 音频文件 弹窗 */
let fileAudioId = '';
export function previewFileAudioModal(fileItem: FileItem) {
if (fileAudioId) return; // 防止重复打开
fileAudioId = fileItem.id;
// eslint-disable-next-line consistent-return
return createModal<TFileOptions>(PreviewAudioModal, {
fileInfo: fileItem,
// 关闭的回调
callback: () => {
fileAudioId = '';
},
});
}

View File

@ -0,0 +1,138 @@
<template>
<div class="file-detail">
<a-row :gutter="[14, 14]" align="stretch" class="wrap">
<a-col :xs="24" :sm="24" :md="16" :lg="18" :xl="19" :xxl="19">
<div class="left">
<a-row justify="space-between">
<a-button @click="back"><icon-left /></a-button>
</a-row>
<div class="view-box">
<!-- <PreImage></PreImage>-->
</div>
</div>
</a-col>
<a-col :xs="24" :sm="24" :md="8" :lg="6" :xl="5" :xxl="5">
<div class="right">
<a-descriptions
title="文件详情"
:column="1"
size="mini"
table-layout="fixed"
layout="inline-horizontal"
>
<a-descriptions-item label="名称:">头像01</a-descriptions-item>
<a-descriptions-item label="类型:">jpg</a-descriptions-item>
<a-descriptions-item label="路径:">/</a-descriptions-item>
<a-descriptions-item label="文件大小:">256K</a-descriptions-item>
<a-descriptions-item label="创建人:">admin</a-descriptions-item>
<a-descriptions-item label="创建时间:"
>2022-05-18 15:25:08</a-descriptions-item
>
<a-descriptions-item label="文件ID"
>1511952522629615617</a-descriptions-item
>
<a-descriptions-item label="标签:">
<a-space wrap>
<a-tag size="small" color="red">头像</a-tag>
<a-tag size="small" color="orangered">图片</a-tag>
<a-tag size="small" color="purple">JPG</a-tag>
<a-tag size="small" color="blue">壁纸</a-tag>
<a-tag size="small" color="orange">4K</a-tag>
<a-tag size="small" color="green">风景</a-tag>
</a-space>
</a-descriptions-item>
<a-descriptions-item label="说明:"
>基于 v-viewer vue3
实现自定义按钮的图片预览其他功能可自行扩展</a-descriptions-item
>
</a-descriptions>
<a-row justify="end" style="margin-top: 30px">
<a-space>
<a-button>
<template #icon><icon-download :size="16" /></template>
</a-button>
<a-button>
<template #icon><icon-share-alt :size="16" /></template>
</a-button>
<a-button>
<template #icon><icon-drag-arrow :size="16" /></template>
</a-button>
<a-button>
<template #icon><icon-delete :size="16" /></template>
</a-button>
</a-space>
</a-row>
</div>
</a-col>
</a-row>
</div>
</template>
<script setup lang="ts">
import { useRouter } from 'vue-router';
// import PreImage from './PreImage.vue';
defineOptions({ name: 'FileDetail' });
const router = useRouter();
const back = () => {
router.back();
};
</script>
<style lang="less" scoped>
:deep(.arco-descriptions) {
.arco-descriptions-title {
margin-bottom: 12px;
}
.arco-descriptions-item {
display: flex;
margin-bottom: 8px;
.arco-descriptions-item-label-inline {
white-space: nowrap;
font-size: 12px;
}
.arco-descriptions-item-value-inline {
font-size: 12px;
}
}
}
.file-detail {
flex: 1;
padding: 16px;
padding-bottom: 0;
box-sizing: border-box;
overflow: hidden;
overflow-y: auto;
.wrap {
height: 100%;
}
.left,
.right {
background-color: var(--color-bg-1);
padding: 16px;
box-sizing: border-box;
overflow: hidden;
box-sizing: border-box;
}
.left {
height: 100%;
display: flex;
flex-direction: column;
.view-box {
min-height: 400px;
flex: 1;
overflow: hidden;
margin-top: $margin;
}
}
.right {
// width: 300px;
// height: fit-content;
// margin: $margin;
// margin-left: 0;
}
}
</style>

View File

@ -0,0 +1,43 @@
<template>
<a-row align="stretch" :gutter="14" class="file-manage">
<a-col
:xs="0"
:sm="8"
:md="7"
:lg="6"
:xl="5"
:xxl="4"
flex="220px"
class="h-full ov-hidden"
>
<FileAside></FileAside>
</a-col>
<a-col
:xs="24"
:sm="16"
:md="17"
:lg="18"
:xl="19"
:xxl="20"
flex="1"
class="h-full ov-hidden"
>
<FileMain></FileMain>
</a-col>
</a-row>
</template>
<script setup lang="ts">
import FileAside from './main/FileAside.vue';
import FileMain from './main/FileMain/index.vue';
defineOptions({ name: 'FileIndex' });
</script>
<style lang="less" scoped>
.file-manage {
flex: 1;
padding: 16px;
overflow: hidden;
}
</style>

View File

@ -0,0 +1,3 @@
export default {
'menu.system.file.list': 'File management',
};

View File

@ -0,0 +1,3 @@
export default {
'menu.system.file.list': '文件管理(尚在开发)',
};

View File

@ -0,0 +1,70 @@
<template>
<div>
<a-card
:title="$t('menu.system.file.list')"
:bordered="false"
:body-style="{ padding: 0 }"
>
<a-menu :default-open-keys="['0']" :selected-keys="[selectedKey]">
<a-sub-menu key="0">
<template #icon>
<icon-apps></icon-apps>
</template>
<template #title>文件类型</template>
<a-menu-item
v-for="item in fileTypeList"
:key="item.value.toString()"
>
<template #icon>
<svg-icon
:icon-class="item.menuIcon"
style="height: 28px; width: 28px"
></svg-icon>
</template>
<span>{{ item.name }}</span>
</a-menu-item>
</a-sub-menu>
</a-menu>
</a-card>
</div>
</template>
<script setup lang="ts">
import { ref, watch } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { fileTypeList, type fileTypeListItem } from '@/constant/file';
const route = useRoute();
const router = useRouter();
const selectedKey = ref('0');
//
watch(
() => route.query,
() => {
if (route.query.fileType) {
selectedKey.value = route.query.fileType as string;
}
},
{
immediate: true,
},
);
//
const onClickItem = (item: fileTypeListItem) => {
router.push({ path: '/file', query: { fileType: item.value } });
};
</script>
<style lang="less" scoped>
:deep(.arco-card) {
.arco-card-header {
border-bottom-style: dashed;
margin: 0 16px;
padding-left: 0;
padding-right: 0;
}
}
</style>

View File

@ -0,0 +1,173 @@
<template>
<div class="file-grid">
<a-grid
:cols="{ xs: 4, sm: 4, md: 5, lg: 7, xl: 8, xxl: 9 }"
:col-gap="12"
:row-gap="12"
>
<a-trigger
v-for="item in data"
:key="item.id"
trigger="contextMenu"
align-point
animation-name="slide-dynamic-origin"
auto-fit-transform-origin
position="bl"
update-at-scroll
scroll-to-close
>
<a-grid-item>
<div class="file-grid-item" @click.stop="handleClickFile(item)">
<div class="wrapper">
<div class="file-icon">
<FileImg :data="item"></FileImg>
</div>
<p class="gi_line_1 file-name">{{ getFileName(item) }}</p>
</div>
<!-- 勾选模式 -->
<section
v-show="props.isBatchMode"
class="check-mode"
:class="{ checked: props.selectedFileIds.includes(item.id) }"
@click.stop="handleCheckFile(item)"
>
<a-checkbox
class="checkbox"
:model-value="props.selectedFileIds.includes(item.id)"
@change="handleCheckFile(item)"
></a-checkbox>
</section>
</div>
</a-grid-item>
<template #content>
<FileRightMenu
:file-info="item"
@click="handleRightMenuItemClick($event, item)"
></FileRightMenu>
</template>
</a-trigger>
</a-grid>
</div>
</template>
<script setup lang="ts">
import type { FileItem } from '@/api/system/file';
import FileImg from './FileImg.vue';
import FileRightMenu from './FileRightMenu.vue';
interface Props {
data?: FileItem[];
selectedFileIds?: string[];
isBatchMode?: boolean;
}
const props = withDefaults(defineProps<Props>(), {
data: () => [], //
selectedFileIds: () => [], // id
isBatchMode: false, //
});
const emit = defineEmits(['click', 'check', 'rightMenuClick']);
//
const getFileName = (item: FileItem) => {
return `${item.name}${item.extendName ? `.${item.extendName}` : ''}`;
};
//
const handleClickFile = (item: FileItem) => {
emit('click', item);
};
//
const handleCheckFile = (item: FileItem) => {
emit('check', item);
};
//
const handleRightMenuItemClick = (mode: string, item: FileItem) => {
emit('rightMenuClick', mode, item);
};
</script>
<style lang="less" scoped>
.file-grid {
flex: 1;
margin-top: 12px;
overflow: scroll;
background: var(--color-bg-2);
}
.file-grid-item {
width: 100%;
height: 100px;
display: flex;
justify-content: center;
align-items: center;
position: relative;
cursor: pointer;
&:hover {
background: var(--color-primary-light-1);
}
&:active {
svg,
img {
transform: scale(0.9);
}
}
.check-mode {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.1);
z-index: 9;
&.checked {
background: none;
}
.checkbox {
position: absolute;
top: 5px;
left: 5px;
padding-left: 0;
}
}
.wrapper {
width: 76%;
max-width: 100px;
height: 100%;
position: relative;
overflow: hidden;
z-index: 1;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.file-icon {
width: 100%;
height: 60px;
display: flex;
justify-content: center;
overflow: hidden;
.img {
width: auto;
height: 100%;
transition: all 0.3s;
}
.svg-img {
height: 100%;
transition: all 0.3s;
}
}
.file-name {
width: 100%;
font-size: 12px;
margin-top: 8px;
padding: 0 5px;
text-align: center;
box-sizing: border-box;
}
}
}
</style>

View File

@ -0,0 +1,47 @@
<template>
<img v-if="isImage" class="img" :src="props.data.src || ''" />
<GiSvgIcon v-else size="100%" :name="getFileImg"></GiSvgIcon>
</template>
<script setup lang="ts">
import { fileExtendNameIconMap, imageTypeList } from '@/constant/file';
import type { FileItem } from '@/api/system/file';
import { computed } from 'vue';
interface Props {
data: FileItem;
}
const props = withDefaults(defineProps<Props>(), {});
//
const isImage = computed(() => {
return imageTypeList.includes(props.data.extendName.toLowerCase());
});
//
const getFileImg = computed<string>(() => {
if (props.data?.isDir) {
return fileExtendNameIconMap.dir || '';
}
if (imageTypeList.includes(props.data.extendName.toLowerCase())) {
return props.data.src || '';
}
if (
!Object.keys(fileExtendNameIconMap).includes(
props.data.extendName.toLowerCase(),
)
) {
return fileExtendNameIconMap.other || '';
}
return fileExtendNameIconMap[props.data.extendName.toLowerCase()] || '';
});
</script>
<style lang="less" scoped>
img {
width: 100%;
height: 100%;
object-fit: cover;
}
</style>

View File

@ -0,0 +1,138 @@
<template>
<div class="file-list">
<a-table
row-key="id"
:scroll="{ x: '100%', y: '100%', minWidth: 600 }"
:data="props.data"
:bordered="false"
:pagination="false"
:row-selection="isBatchMode ? rowSelection : undefined"
>
<template #columns>
<a-table-column title="名称">
<template #cell="{ record }">
<a-trigger
trigger="contextMenu"
align-point
animation-name="slide-dynamic-origin"
auto-fit-transform-origin
position="bl"
update-at-scroll
scroll-to-close
>
<div class="file-name" @click="handleRowClick(record)">
<div class="file-image">
<FileImg :data="record"></FileImg>
</div>
<span>{{ record.name }}</span>
</div>
<template #content>
<FileRightMenu
:file-info="record"
@click="handleRightMenuItemClick($event, record)"
></FileRightMenu>
</template>
</a-trigger>
</template>
</a-table-column>
<a-table-column
title="扩展名"
data-index="extendName"
:width="100"
></a-table-column>
<a-table-column
title="更改时间"
data-index="updateTime"
:width="200"
></a-table-column>
<a-table-column title="操作" :width="120" align="center">
<template #cell="{ record }">
<a-popover
trigger="click"
position="bottom"
content-class="more-option"
:content-style="{ 'padding': 0, 'margin-top': 0 }"
>
<a-button type="text"><icon-more :size="16" /></a-button>
<template #content>
<FileRightMenu
:file-info="record"
:show-class-style="false"
@click="handleRightMenuItemClick($event, record)"
></FileRightMenu>
</template>
</a-popover>
</template>
</a-table-column>
</template>
</a-table>
</div>
</template>
<script setup lang="ts">
import type { TableRowSelection } from '@arco-design/web-vue';
import type { FileItem } from '@/api/system/file';
import { reactive } from 'vue';
import FileImg from './FileImg.vue';
import FileRightMenu from './FileRightMenu.vue';
interface Props {
data?: FileItem[];
isBatchMode?: boolean;
}
const props = withDefaults(defineProps<Props>(), {
data: () => [], //
isBatchMode: false, //
});
const rowSelection: TableRowSelection = reactive({
type: 'checkbox',
showCheckedAll: true,
});
const emit = defineEmits(['click', 'rightMenuClick']);
//
const handleRowClick = (row: FileItem) => {
emit('click', row);
};
//
const handleRightMenuItemClick = (mode: string, item: FileItem) => {
emit('rightMenuClick', mode, item);
};
</script>
<style lang="scss">
.more-option {
.arco-popover-content {
margin-top: 0 !important;
}
}
</style>
<style lang="less" scoped>
:deep(.arco-table-td .arco-table-cell) {
padding-top: 0;
padding-bottom: 0;
}
.file-list {
width: 100%;
padding-top: 12px;
overflow: hidden;
.file-name {
height: 100%;
display: flex;
align-items: center;
padding-top: 6px;
padding-bottom: 6px;
cursor: pointer;
.file-image {
width: 30px;
height: 30px;
margin-right: 10px;
}
}
}
</style>

View File

@ -0,0 +1,91 @@
<template>
<GiOption :class="{ option: showClassStyle }">
<GiOptionItem @click="onClickItem('rename')">
<template #icon><GiSvgIcon name="menu-edit"></GiSvgIcon> </template>
<span>重命名</span>
</GiOptionItem>
<GiOptionItem @click="onClickItem('move')">
<template #icon><GiSvgIcon name="menu-move"></GiSvgIcon> </template>
<span>移动到</span>
</GiOptionItem>
<GiOptionItem @click="onClickItem('download')">
<template #icon><GiSvgIcon name="menu-download"></GiSvgIcon> </template>
<span>下载</span>
</GiOptionItem>
<a-popover
v-if="props.fileInfo.extendName === 'zip'"
position="right"
:content-style="{ padding: 0, overflow: 'hidden', width: '150px' }"
:arrow-style="{ display: 'none' }"
>
<GiOptionItem more>
<template #icon><GiSvgIcon name="menu-zip"></GiSvgIcon> </template>
<span>解压</span>
</GiOptionItem>
<template #content>
<GiOption>
<GiOptionItem @click="onClickItem('zip1')">
<template #icon><GiSvgIcon name="file-rar"></GiSvgIcon> </template>
<span>解压到当前目录</span>
</GiOptionItem>
<GiOptionItem @click="onClickItem('zip2')">
<template #icon><GiSvgIcon name="file-rar"></GiSvgIcon> </template>
<span>解压到其他目录</span>
</GiOptionItem>
</GiOption>
</template>
</a-popover>
<GiOptionItem @click="onClickItem('detail')">
<template #icon><GiSvgIcon name="menu-detail"></GiSvgIcon> </template>
<span>详情</span>
</GiOptionItem>
<GiOptionItem @click="onClickItem('delete')">
<template #icon><GiSvgIcon name="menu-delete"></GiSvgIcon> </template>
<span>删除</span>
</GiOptionItem>
</GiOption>
</template>
<script setup lang="ts">
import type { FileItem } from '@/api/system/file';
// import GiOption from '@/components/GiOption/index.vue';
// import GiOptionItem from '@/components/GiOptionItem/index.vue';
interface Props {
fileInfo?: FileItem;
showClassStyle?: boolean;
}
const props = withDefaults(defineProps<Props>(), {
fileInfo: () => ({
id: '',
type: '',
name: '',
extendName: '',
src: '',
updateTime: '',
isDir: false,
filePath: '',
}), //
showClassStyle: true,
});
const emit = defineEmits(['click']);
const onClickItem = (mode: string) => {
emit('click', mode);
};
</script>
<style lang="less" scoped>
.option {
box-shadow:
0 2px 4px rgba(0, 0, 0, 0.12),
0 0 6px rgba(0, 0, 0, 0.04);
border-radius: 4px;
overflow: hidden;
border: 1px solid var(--color-border-2);
box-sizing: border-box;
background: var(--color-bg-popup);
}
</style>

View File

@ -0,0 +1,213 @@
<template>
<div class="file-main">
<a-row justify="space-between" class="row-operate">
<!-- 左侧区域 -->
<a-space wrap>
<a-button type="primary" shape="round">
<template #icon><icon-upload /></template>
<template #default>上传</template>
</a-button>
<a-input-group>
<a-space>
<a-input placeholder="输入文件名称搜索" allow-clear> </a-input>
<a-button type="primary">
<template #icon><icon-search /></template>查询
</a-button>
<a-button>
<template #icon><icon-refresh /></template>重置
</a-button>
</a-space>
</a-input-group>
</a-space>
<!-- 右侧区域 -->
<a-space wrap>
<a-button
v-if="isBatchMode"
:disabled="!fileStore.selectedFileIds.length"
type="primary"
status="danger"
@click="handleMulDelete"
><template #icon><icon-delete /></template
></a-button>
<a-button type="primary" @click="isBatchMode = !isBatchMode">
<template #icon><icon-select-all /></template>
<template #default>{{
isBatchMode ? '取消批量' : '批量操作'
}}</template>
</a-button>
<a-button-group>
<a-tooltip content="视图" position="bottom">
<a-button @click="fileStore.changeViewMode">
<template #icon>
<icon-apps v-if="fileStore.viewMode === 'grid'" />
<icon-list v-else />
</template>
</a-button>
</a-tooltip>
</a-button-group>
</a-space>
</a-row>
<!-- 文件列表-宫格模式 -->
<a-spin class="file-wrap" :loading="loading">
<FileGrid
v-show="fileList.length && fileStore.viewMode == 'grid'"
:data="fileList"
:is-batch-mode="isBatchMode"
:selected-file-ids="fileStore.selectedFileIds"
@click="handleClickFile"
@check="handleCheckFile"
@rightMenuClick="handleRightMenuClick"
></FileGrid>
<!-- 文件列表-列表模式 -->
<FileList
v-show="fileList.length && fileStore.viewMode == 'list'"
:data="fileList"
:is-batch-mode="isBatchMode"
@click="handleClickFile"
@rightMenuClick="handleRightMenuClick"
></FileList>
<a-empty v-show="!fileList.length"></a-empty>
</a-spin>
</div>
</template>
<script setup lang="ts">
import { Message, Modal } from '@arco-design/web-vue';
import { api as viewerApi } from 'v-viewer';
import { fileTypeList, imageTypeList } from '@/constant/file';
import { useFileStore } from '@/store/modules/file';
import type { FileItem } from '@/api/system/file';
import { getFileList } from '@/api/system/file';
import { onBeforeRouteUpdate, useRoute, useRouter } from 'vue-router';
import { onMounted, ref } from 'vue';
import FileGrid from './FileGrid.vue';
import FileList from './FileList.vue';
import {
openFileMoveModal,
openFileRenameModal,
previewFileVideoModal,
previewFileAudioModal,
} from '../../components/index';
const route = useRoute();
const router = useRouter();
const fileStore = useFileStore();
const loading = ref(false);
//
const fileList = ref<FileItem[]>([]);
const fileType = ref('0');
//
const isBatchMode = ref(false);
fileType.value = route.query.fileType?.toString() || '0';
const getListData = async () => {
try {
loading.value = true;
isBatchMode.value = false;
// const res = await getFileList({ fileType: fileType.value });
// fileList.value = res.data;
} finally {
loading.value = false;
}
};
onMounted(() => {
getListData();
});
onBeforeRouteUpdate((to) => {
if (!to.query.fileType) return;
fileType.value = to.query.fileType?.toString();
getListData();
});
//
const handleClickFile = (item: FileItem) => {
Message.success(`点击了文件-${item.name}`);
if (imageTypeList.includes(item.extendName)) {
if (item.src) {
const imgList: string[] = fileList.value
.filter((i) => imageTypeList.includes(i.extendName))
.map((a) => a.src || '');
const index = imgList.findIndex((i) => i === item.src);
if (imgList.length) {
viewerApi({
options: {
initialViewIndex: index,
},
images: imgList,
});
}
}
}
if (item.extendName === 'mp4') {
previewFileVideoModal(item);
}
if (item.extendName === 'mp3') {
previewFileAudioModal(item);
}
};
//
const handleCheckFile = (item: FileItem) => {
fileStore.addSelectedFileItem(item);
};
//
const handleRightMenuClick = (mode: string, fileInfo: FileItem) => {
Message.success(`点击了${mode}`);
if (mode === 'delete') {
Modal.warning({
title: '提示',
content: '是否删除该文件?',
hideCancel: false,
});
}
if (mode === 'rename') {
openFileRenameModal(fileInfo);
}
if (mode === 'move') {
openFileMoveModal(fileInfo);
}
if (mode === 'detail') {
router.push({ path: '/file/detail' });
}
};
//
const handleMulDelete = () => {
Modal.warning({
title: '提示',
content: '是否确认删除?',
hideCancel: false,
});
};
</script>
<style lang="less" scoped>
.file-main {
height: 100%;
background: var(--color-bg-1);
border-radius: 2px;
display: flex;
flex-direction: column;
overflow: hidden;
.row-operate {
border-bottom: 1px dashed var(--color-border-3);
margin: 20px 16px;
}
.file-wrap {
flex: 1;
padding: 0 16px 16px;
box-sizing: border-box;
overflow: hidden;
display: flex;
flex-direction: column;
}
}
</style>

View File

@ -23,3 +23,9 @@ databaseChangeLog:
file: db/changelog/v1.3.0/continew-admin_column.sql
- include:
file: db/changelog/v1.3.0/continew-admin_data.sql
- include:
file: db/changelog/v2.2.0/continew-admin_table.sql
- include:
file: db/changelog/v2.2.0/continew-admin_column.sql
- include:
file: db/changelog/v2.2.0/continew-admin_data.sql

View File

@ -0,0 +1,2 @@
-- liquibase formatted sql

View File

@ -0,0 +1,17 @@
-- liquibase formatted sql
-- changeset Charles7c:1
-- 初始化默认菜单
INSERT IGNORE INTO `sys_menu`
(`id`, `title`, `parent_id`, `type`, `path`, `name`, `component`, `icon`, `is_external`, `is_cache`, `is_hidden`, `permission`, `sort`, `status`, `create_user`, `create_time`, `update_user`, `update_time`)
VALUES
(1090, '文件管理', 1000, 2, '/system/file', 'File', 'system/file/index', 'file', b'0', b'0', b'0', 'system:file:list', 9, 1, 1, NOW(), NULL, NULL),
(1091, '文件上传', 1090, 3, NULL, NULL, NULL, NULL, b'0', b'0', b'0', 'system:file:upload', 1, 1, 1, NOW(), NULL, NULL),
(1092, '文件修改', 1090, 3, NULL, NULL, NULL, NULL, b'0', b'0', b'0', 'system:file:update', 2, 1, 1, NOW(), NULL, NULL),
(1093, '文件删除', 1090, 3, NULL, NULL, NULL, NULL, b'0', b'0', b'0', 'system:file:delete', 3, 1, 1, NOW(), NULL, NULL),
(1094, '文件下载', 1090, 3, NULL, NULL, NULL, NULL, b'0', b'0', b'0', 'system:file:download', 4, 1, 1, NOW(), NULL, NULL),
(1100, '存储管理', 1000, 2, '/system/storage', 'Storage', 'system/storage/index', 'storage', b'0', b'0', b'1', 'system:storage:list', 10, 1, 1, NOW(), NULL, NULL),
(1101, '存储新增', 1100, 3, NULL, NULL, NULL, NULL, b'0', b'0', b'0', 'system:storage:add', 1, 1, 1, NOW(), NULL, NULL),
(1102, '存储修改', 1100, 3, NULL, NULL, NULL, NULL, b'0', b'0', b'0', 'system:storage:update', 2, 1, 1, NOW(), NULL, NULL),
(1103, '存储删除', 1100, 3, NULL, NULL, NULL, NULL, b'0', b'0', b'0', 'system:storage:delete', 3, 1, 1, NOW(), NULL, NULL),
(1104, '存储导出', 1100, 3, NULL, NULL, NULL, NULL, b'0', b'0', b'0', 'system:storage:export', 4, 1, 1, NOW(), NULL, NULL);

View File

@ -0,0 +1,44 @@
-- liquibase formatted sql
-- changeset Charles7c:1
CREATE TABLE IF NOT EXISTS `sys_file` (
`id` bigint(20) NOT NULL COMMENT 'ID',
`name` varchar(255) NOT NULL COMMENT '名称',
`size` bigint(20) NOT NULL COMMENT '大小(字节)',
`url` varchar(512) NOT NULL COMMENT 'URL',
`extension` varchar(100) DEFAULT NULL COMMENT '扩展名',
`mime_type` varchar(100) DEFAULT NULL COMMENT 'MIME类型',
`category` tinyint(1) UNSIGNED NOT NULL DEFAULT 1 COMMENT '类型1其他2图片3文档4视频5音频',
`storage_id` bigint(20) NOT NULL COMMENT '存储库ID',
`create_user` bigint(20) NOT NULL COMMENT '创建人',
`create_time` datetime NOT NULL COMMENT '创建时间',
`update_user` bigint(20) DEFAULT NULL COMMENT '修改人',
`update_time` datetime DEFAULT NULL COMMENT '修改时间',
PRIMARY KEY (`id`) USING BTREE,
INDEX `idx_category`(`category`) USING BTREE,
INDEX `idx_create_user`(`create_user`) USING BTREE,
INDEX `idx_update_user`(`update_user`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='文件表';
CREATE TABLE IF NOT EXISTS `sys_storage` (
`id` bigint(20) AUTO_INCREMENT COMMENT 'ID',
`name` varchar(100) NOT NULL COMMENT '名称',
`code` varchar(30) NOT NULL COMMENT '编码',
`access_key` varchar(255) DEFAULT NULL COMMENT 'Access Key访问密钥',
`secret_key` varchar(255) DEFAULT NULL COMMENT 'Secret Key私有访问密钥',
`endpoint` varchar(255) DEFAULT NULL COMMENT 'Endpoint终端节点',
`bucket_name` varchar(255) DEFAULT NULL COMMENT '桶名称',
`domain` varchar(255) DEFAULT NULL COMMENT '自定义域名',
`description` varchar(200) DEFAULT NULL COMMENT '描述',
`is_default` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否为默认存储',
`sort` int NOT NULL DEFAULT 999 COMMENT '排序',
`status` tinyint(1) UNSIGNED NOT NULL DEFAULT 1 COMMENT '状态1启用2禁用',
`create_user` bigint(20) NOT NULL COMMENT '创建人',
`create_time` datetime NOT NULL COMMENT '创建时间',
`update_user` bigint(20) DEFAULT NULL COMMENT '修改人',
`update_time` datetime DEFAULT NULL COMMENT '修改时间',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `uk_code`(`code`) USING BTREE,
INDEX `idx_create_user`(`create_user`) USING BTREE,
INDEX `idx_update_user`(`update_user`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='存储库表';