增加基于文件系统的路由支持

This commit is contained in:
hooray 2022-02-25 14:24:51 +08:00
parent 35fd8f69ab
commit 7904ab66e8
65 changed files with 1148 additions and 83 deletions

View File

@ -65,9 +65,11 @@
"vite-plugin-compression": "^0.5.1",
"vite-plugin-html": "^3.0.6",
"vite-plugin-mock": "^2.9.6",
"vite-plugin-pages": "^0.20.2",
"vite-plugin-restart": "^0.1.1",
"vite-plugin-spritesmith": "^0.1.1",
"vite-plugin-svg-icons": "^2.0.1",
"vite-plugin-vue-layouts": "^0.6.0",
"vite-plugin-vue-setup-extend": "^0.4.0",
"vue-eslint-parser": "^8.2.0"
}

View File

@ -45,9 +45,11 @@ specifiers:
vite-plugin-compression: ^0.5.1
vite-plugin-html: ^3.0.6
vite-plugin-mock: ^2.9.6
vite-plugin-pages: ^0.20.2
vite-plugin-restart: ^0.1.1
vite-plugin-spritesmith: ^0.1.1
vite-plugin-svg-icons: ^2.0.1
vite-plugin-vue-layouts: ^0.6.0
vite-plugin-vue-setup-extend: ^0.4.0
vue: ^3.2.31
vue-eslint-parser: ^8.2.0
@ -102,9 +104,11 @@ devDependencies:
vite-plugin-compression: 0.5.1_vite@2.8.2
vite-plugin-html: 3.0.6_vite@2.8.2
vite-plugin-mock: 2.9.6_mockjs@1.1.0+vite@2.8.2
vite-plugin-pages: 0.20.2_225319ba269c7341e620f4355a031650
vite-plugin-restart: 0.1.1_vite@2.8.2
vite-plugin-spritesmith: 0.1.1
vite-plugin-svg-icons: 2.0.1_vite@2.8.2
vite-plugin-vue-layouts: 0.6.0_0509afcdf03496209baa96a2baefec6c
vite-plugin-vue-setup-extend: 0.4.0_vite@2.8.2
vue-eslint-parser: 8.2.0_eslint@8.9.0
@ -467,7 +471,7 @@ packages:
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dependencies:
ajv: 6.12.6
debug: 4.3.2
debug: 4.3.3
espree: 9.3.1
globals: 13.11.0
ignore: 4.0.6
@ -484,7 +488,7 @@ packages:
engines: {node: '>=10.10.0'}
dependencies:
'@humanwhocodes/object-schema': 1.2.1
debug: 4.3.2
debug: 4.3.3
minimatch: 3.0.4
transitivePeerDependencies:
- supports-color
@ -519,12 +523,12 @@ packages:
dev: true
/@nodelib/fs.stat/2.0.5:
resolution: {integrity: sha1-W9Jir5Tp0lvR5xsF3u1Eh2oiLos=, tarball: '@nodelib/fs.stat/download/@nodelib/fs.stat-2.0.5.tgz'}
resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==}
engines: {node: '>= 8'}
dev: true
/@nodelib/fs.walk/1.2.8:
resolution: {integrity: sha1-6Vc36LtnRt3t9pxVaVNJTxlv5po=, tarball: '@nodelib/fs.walk/download/@nodelib/fs.walk-1.2.8.tgz'}
resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
engines: {node: '>= 8'}
dependencies:
'@nodelib/fs.scandir': 2.1.5
@ -1029,6 +1033,11 @@ packages:
hasBin: true
dev: true
/available-typed-arrays/1.0.5:
resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==}
engines: {node: '>= 0.4'}
dev: true
/aws-sign2/0.7.0:
resolution: {integrity: sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=, tarball: aws-sign2/download/aws-sign2-0.7.0.tgz}
dev: true
@ -1194,7 +1203,7 @@ packages:
dev: true
/call-bind/1.0.2:
resolution: {integrity: sha1-sdTonmiBGcPJqQOtMKuy9qkZvjw=, tarball: call-bind/download/call-bind-1.0.2.tgz}
resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==}
dependencies:
function-bind: 1.1.1
get-intrinsic: 1.1.1
@ -1705,6 +1714,26 @@ packages:
engines: {node: '>=0.10'}
dev: true
/deep-equal/2.0.5:
resolution: {integrity: sha512-nPiRgmbAtm1a3JsnLCf6/SLfXcjyN5v8L1TXzdCmHrXJ4hx+gW/w1YCcn7z8gJtSiDArZCgYtbao3QqLm/N1Sw==}
dependencies:
call-bind: 1.0.2
es-get-iterator: 1.1.2
get-intrinsic: 1.1.1
is-arguments: 1.1.1
is-date-object: 1.0.5
is-regex: 1.1.4
isarray: 2.0.5
object-is: 1.1.5
object-keys: 1.1.1
object.assign: 4.1.2
regexp.prototype.flags: 1.4.1
side-channel: 1.0.4
which-boxed-primitive: 1.0.2
which-collection: 1.0.1
which-typed-array: 1.1.7
dev: true
/deep-is/0.1.4:
resolution: {integrity: sha1-pvLc5hL63S7x9Rm3NVHxfoUZmDE=, tarball: deep-is/download/deep-is-0.1.4.tgz}
dev: true
@ -1720,6 +1749,13 @@ packages:
clone: 1.0.4
dev: true
/define-properties/1.1.3:
resolution: {integrity: sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==}
engines: {node: '>= 0.4'}
dependencies:
object-keys: 1.1.1
dev: true
/define-property/0.2.5:
resolution: {integrity: sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==}
engines: {node: '>=0.10.0'}
@ -1937,6 +1973,54 @@ packages:
is-arrayish: 0.2.1
dev: true
/es-abstract/1.19.1:
resolution: {integrity: sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==}
engines: {node: '>= 0.4'}
dependencies:
call-bind: 1.0.2
es-to-primitive: 1.2.1
function-bind: 1.1.1
get-intrinsic: 1.1.1
get-symbol-description: 1.0.0
has: 1.0.3
has-symbols: 1.0.2
internal-slot: 1.0.3
is-callable: 1.2.4
is-negative-zero: 2.0.2
is-regex: 1.1.4
is-shared-array-buffer: 1.0.1
is-string: 1.0.7
is-weakref: 1.0.2
object-inspect: 1.12.0
object-keys: 1.1.1
object.assign: 4.1.2
string.prototype.trimend: 1.0.4
string.prototype.trimstart: 1.0.4
unbox-primitive: 1.0.1
dev: true
/es-get-iterator/1.1.2:
resolution: {integrity: sha512-+DTO8GYwbMCwbywjimwZMHp8AuYXOS2JZFWoi2AlPOS3ebnII9w/NLpNZtA7A0YLaVDw+O7KFCeoIV7OPvM7hQ==}
dependencies:
call-bind: 1.0.2
get-intrinsic: 1.1.1
has-symbols: 1.0.2
is-arguments: 1.1.1
is-map: 2.0.2
is-set: 2.0.2
is-string: 1.0.7
isarray: 2.0.5
dev: true
/es-to-primitive/1.2.1:
resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==}
engines: {node: '>= 0.4'}
dependencies:
is-callable: 1.2.4
is-date-object: 1.0.5
is-symbol: 1.0.4
dev: true
/esbuild-android-arm64/0.14.21:
resolution: {integrity: sha512-Bqgld1TY0wZv8TqiQmVxQFgYzz8ZmyzT7clXBDZFkOOdRybzsnj8AZuK1pwcLVA7Ya6XncHgJqIao7NFd3s0RQ==}
engines: {node: '>=12'}
@ -2408,7 +2492,7 @@ packages:
dev: true
/fast-glob/3.2.11:
resolution: {integrity: sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==, tarball: fast-glob/download/fast-glob-3.2.11.tgz}
resolution: {integrity: sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==}
engines: {node: '>=8.6.0'}
dependencies:
'@nodelib/fs.stat': 2.0.5
@ -2442,7 +2526,7 @@ packages:
dev: true
/fastq/1.13.0:
resolution: {integrity: sha1-YWdg+Ip1Jr38WWt8q4wYk4w2uYw=, tarball: fastq/download/fastq-1.13.0.tgz}
resolution: {integrity: sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==}
dependencies:
reusify: 1.0.4
dev: true
@ -2569,6 +2653,10 @@ packages:
for-in: 1.0.2
dev: true
/foreach/2.0.5:
resolution: {integrity: sha512-ZBbtRiapkZYLsqoPyZOR+uPfto0GRMNQN1GwzZtZt7iZvPPbDDQV0JF5Hx4o/QFQ5c0vyuoZ98T8RSBbopzWtA==}
dev: true
/forever-agent/0.6.1:
resolution: {integrity: sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=, tarball: forever-agent/download/forever-agent-0.6.1.tgz}
dev: true
@ -2629,7 +2717,7 @@ packages:
dev: true
/get-intrinsic/1.1.1:
resolution: {integrity: sha1-FfWfN2+FXERpY5SPDSTNNje0q8Y=, tarball: get-intrinsic/download/get-intrinsic-1.1.1.tgz}
resolution: {integrity: sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==}
dependencies:
function-bind: 1.1.1
has: 1.0.3
@ -2661,6 +2749,14 @@ packages:
engines: {node: '>=10'}
dev: true
/get-symbol-description/1.0.0:
resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==}
engines: {node: '>= 0.4'}
dependencies:
call-bind: 1.0.2
get-intrinsic: 1.1.1
dev: true
/get-value/2.0.6:
resolution: {integrity: sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==}
engines: {node: '>=0.10.0'}
@ -2680,7 +2776,7 @@ packages:
dev: true
/glob-parent/5.1.2:
resolution: {integrity: sha1-hpgyxYA0/mikCTwX3BXoNA2EAcQ=, tarball: glob-parent/download/glob-parent-5.1.2.tgz}
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
engines: {node: '>= 6'}
dependencies:
is-glob: 4.0.3
@ -2848,6 +2944,10 @@ packages:
ansi-regex: 2.1.1
dev: true
/has-bigints/1.0.1:
resolution: {integrity: sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==}
dev: true
/has-flag/1.0.0:
resolution: {integrity: sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA==}
engines: {node: '>=0.10.0'}
@ -2864,9 +2964,16 @@ packages:
dev: true
/has-symbols/1.0.2:
resolution: {integrity: sha1-Fl0wcMADCXUqEjakeTMeOsVvFCM=, tarball: has-symbols/download/has-symbols-1.0.2.tgz}
resolution: {integrity: sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==}
engines: {node: '>= 0.4'}
/has-tostringtag/1.0.0:
resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==}
engines: {node: '>= 0.4'}
dependencies:
has-symbols: 1.0.2
dev: true
/has-value/0.3.1:
resolution: {integrity: sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q==}
engines: {node: '>=0.10.0'}
@ -3131,6 +3238,15 @@ packages:
through: 2.3.8
dev: true
/internal-slot/1.0.3:
resolution: {integrity: sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==}
engines: {node: '>= 0.4'}
dependencies:
get-intrinsic: 1.1.1
has: 1.0.3
side-channel: 1.0.4
dev: true
/interpret/2.2.0:
resolution: {integrity: sha1-GnigtZZcQKVBbQB61vUK0nxBffk=, tarball: interpret/download/interpret-2.2.0.tgz}
engines: {node: '>= 0.10'}
@ -3162,10 +3278,24 @@ packages:
kind-of: 6.0.3
dev: true
/is-arguments/1.1.1:
resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==}
engines: {node: '>= 0.4'}
dependencies:
call-bind: 1.0.2
has-tostringtag: 1.0.0
dev: true
/is-arrayish/0.2.1:
resolution: {integrity: sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=, tarball: is-arrayish/download/is-arrayish-0.2.1.tgz}
dev: true
/is-bigint/1.0.4:
resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==}
dependencies:
has-bigints: 1.0.1
dev: true
/is-binary-path/2.1.0:
resolution: {integrity: sha1-6h9/O4DwZCNug0cPhsCcJU+0Wwk=, tarball: is-binary-path/download/is-binary-path-2.1.0.tgz}
engines: {node: '>=8'}
@ -3173,10 +3303,23 @@ packages:
binary-extensions: 2.2.0
dev: true
/is-boolean-object/1.1.2:
resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==}
engines: {node: '>= 0.4'}
dependencies:
call-bind: 1.0.2
has-tostringtag: 1.0.0
dev: true
/is-buffer/1.1.6:
resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==}
dev: true
/is-callable/1.2.4:
resolution: {integrity: sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==}
engines: {node: '>= 0.4'}
dev: true
/is-core-module/2.8.1:
resolution: {integrity: sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==}
dependencies:
@ -3197,6 +3340,13 @@ packages:
kind-of: 6.0.3
dev: true
/is-date-object/1.0.5:
resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==}
engines: {node: '>= 0.4'}
dependencies:
has-tostringtag: 1.0.0
dev: true
/is-descriptor/0.1.6:
resolution: {integrity: sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==}
engines: {node: '>=0.10.0'}
@ -3259,10 +3409,26 @@ packages:
engines: {node: '>=12'}
dev: true
/is-map/2.0.2:
resolution: {integrity: sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==}
dev: true
/is-module/1.0.0:
resolution: {integrity: sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=, tarball: is-module/download/is-module-1.0.0.tgz}
dev: true
/is-negative-zero/2.0.2:
resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==}
engines: {node: '>= 0.4'}
dev: true
/is-number-object/1.0.6:
resolution: {integrity: sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==}
engines: {node: '>= 0.4'}
dependencies:
has-tostringtag: 1.0.0
dev: true
/is-number/3.0.0:
resolution: {integrity: sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==}
engines: {node: '>=0.10.0'}
@ -3302,6 +3468,14 @@ packages:
engines: {node: '>=0.10.0'}
dev: true
/is-regex/1.1.4:
resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==}
engines: {node: '>= 0.4'}
dependencies:
call-bind: 1.0.2
has-tostringtag: 1.0.0
dev: true
/is-regexp/2.1.0:
resolution: {integrity: sha1-zXNKVoZOI7lWv058ZsOWpMCyLC0=, tarball: is-regexp/download/is-regexp-2.1.0.tgz}
engines: {node: '>=6'}
@ -3314,11 +3488,44 @@ packages:
is-unc-path: 1.0.0
dev: true
/is-set/2.0.2:
resolution: {integrity: sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==}
dev: true
/is-shared-array-buffer/1.0.1:
resolution: {integrity: sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==}
dev: true
/is-stream/2.0.1:
resolution: {integrity: sha1-+sHj1TuXrVqdCunO8jifWBClwHc=, tarball: is-stream/download/is-stream-2.0.1.tgz}
engines: {node: '>=8'}
dev: true
/is-string/1.0.7:
resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==}
engines: {node: '>= 0.4'}
dependencies:
has-tostringtag: 1.0.0
dev: true
/is-symbol/1.0.4:
resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==}
engines: {node: '>= 0.4'}
dependencies:
has-symbols: 1.0.2
dev: true
/is-typed-array/1.1.8:
resolution: {integrity: sha512-HqH41TNZq2fgtGT8WHVFVJhBVGuY3AnP3Q36K8JKXUxSxRgk/d+7NjmwG2vo2mYmXK8UYZKu0qH8bVP5gEisjA==}
engines: {node: '>= 0.4'}
dependencies:
available-typed-arrays: 1.0.5
call-bind: 1.0.2
es-abstract: 1.19.1
foreach: 2.0.5
has-tostringtag: 1.0.0
dev: true
/is-typedarray/1.0.0:
resolution: {integrity: sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=, tarball: is-typedarray/download/is-typedarray-1.0.0.tgz}
dev: true
@ -3344,6 +3551,23 @@ packages:
resolution: {integrity: sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=, tarball: is-utf8/download/is-utf8-0.2.1.tgz}
dev: true
/is-weakmap/2.0.1:
resolution: {integrity: sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==}
dev: true
/is-weakref/1.0.2:
resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==}
dependencies:
call-bind: 1.0.2
dev: true
/is-weakset/2.0.2:
resolution: {integrity: sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==}
dependencies:
call-bind: 1.0.2
get-intrinsic: 1.1.1
dev: true
/is-windows/1.0.2:
resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==}
engines: {node: '>=0.10.0'}
@ -3354,7 +3578,11 @@ packages:
dev: true
/isarray/1.0.0:
resolution: {integrity: sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=, tarball: isarray/download/isarray-1.0.0.tgz}
resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==}
dev: true
/isarray/2.0.5:
resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==}
dev: true
/isbinaryfile/4.0.8:
@ -3605,7 +3833,7 @@ packages:
dev: true
/local-pkg/0.4.1:
resolution: {integrity: sha512-lL87ytIGP2FU5PWwNDo0w3WhIo2gopIAxPg9RxDYF7m4rr5ahuZxP22xnJHIvaLTe4Z9P6uKKY2UHiwyB4pcrw==, tarball: local-pkg/download/local-pkg-0.4.1.tgz}
resolution: {integrity: sha512-lL87ytIGP2FU5PWwNDo0w3WhIo2gopIAxPg9RxDYF7m4rr5ahuZxP22xnJHIvaLTe4Z9P6uKKY2UHiwyB4pcrw==}
engines: {node: '>=14'}
dev: true
@ -3769,12 +3997,12 @@ packages:
dev: true
/merge2/1.4.1:
resolution: {integrity: sha1-Q2iJL4hekHRVpv19xVwMnUBJkK4=, tarball: merge2/download/merge2-1.4.1.tgz}
resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
engines: {node: '>= 8'}
dev: true
/micromatch/3.1.0:
resolution: {integrity: sha1-UQLU6vILaZfWAI46z+HESj+oFeI=, tarball: micromatch/download/micromatch-3.1.0.tgz}
resolution: {integrity: sha512-3StSelAE+hnRvMs8IdVW7Uhk8CVed5tp+kLLGlBP6WiRAXS21GPGu/Nat4WNPXj2Eoc24B02SaeoyozPMfj0/g==}
engines: {node: '>=0.10.0'}
dependencies:
arr-diff: 4.0.0
@ -3838,7 +4066,7 @@ packages:
dev: true
/minimist/1.2.5:
resolution: {integrity: sha1-Z9ZgFLZqaoqqDAg8X9WN9OTpdgI=, tarball: minimist/download/minimist-1.2.5.tgz}
resolution: {integrity: sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==}
dev: true
/mitt/3.0.0:
@ -3867,11 +4095,11 @@ packages:
dev: false
/ms/2.0.0:
resolution: {integrity: sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=, tarball: ms/download/ms-2.0.0.tgz}
resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==}
dev: true
/ms/2.1.2:
resolution: {integrity: sha1-0J0fNXtEP0kzgqjrPM0YOHKuYAk=, tarball: ms/download/ms-2.1.2.tgz}
resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
dev: true
/ms/2.1.3:
@ -4058,6 +4286,19 @@ packages:
/object-inspect/1.12.0:
resolution: {integrity: sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==, tarball: object-inspect/download/object-inspect-1.12.0.tgz}
/object-is/1.1.5:
resolution: {integrity: sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==}
engines: {node: '>= 0.4'}
dependencies:
call-bind: 1.0.2
define-properties: 1.1.3
dev: true
/object-keys/1.1.1:
resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==}
engines: {node: '>= 0.4'}
dev: true
/object-visit/1.0.1:
resolution: {integrity: sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA==}
engines: {node: '>=0.10.0'}
@ -4065,6 +4306,16 @@ packages:
isobject: 3.0.1
dev: true
/object.assign/4.1.2:
resolution: {integrity: sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==}
engines: {node: '>= 0.4'}
dependencies:
call-bind: 1.0.2
define-properties: 1.1.3
has-symbols: 1.0.2
object-keys: 1.1.1
dev: true
/object.defaults/1.1.0:
resolution: {integrity: sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=, tarball: object.defaults/download/object.defaults-1.1.0.tgz}
engines: {node: '>=0.10.0'}
@ -4554,7 +4805,7 @@ packages:
dev: true
/queue-microtask/1.2.3:
resolution: {integrity: sha1-SSkii7xyTfrEPg77BYyve2z7YkM=, tarball: queue-microtask/download/queue-microtask-1.2.3.tgz}
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
dev: true
/quick-lru/4.0.1:
@ -4661,6 +4912,14 @@ packages:
safe-regex: 1.1.0
dev: true
/regexp.prototype.flags/1.4.1:
resolution: {integrity: sha512-pMR7hBVUUGI7PMA37m2ofIdQCsomVnas+Jn5UPGAHQ+/LlwKm/aTLJHdasmHRzlfeZwHiAOaRSo2rbBDm3nNUQ==}
engines: {node: '>= 0.4'}
dependencies:
call-bind: 1.0.2
define-properties: 1.1.3
dev: true
/regexpp/3.2.0:
resolution: {integrity: sha1-BCWido2PI7rXDKS5BGH6LxIT4bI=, tarball: regexpp/download/regexpp-3.2.0.tgz}
engines: {node: '>=8'}
@ -4788,7 +5047,7 @@ packages:
dev: true
/reusify/1.0.4:
resolution: {integrity: sha1-kNo4Kx4SbvwCFG6QhFqI2xKSXXY=, tarball: reusify/download/reusify-1.0.4.tgz}
resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==}
engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
dev: true
@ -4817,7 +5076,7 @@ packages:
dev: true
/run-parallel/1.2.0:
resolution: {integrity: sha1-ZtE2jae9+SHrnZW9GpIp5/IaQ+4=, tarball: run-parallel/download/run-parallel-1.2.0.tgz}
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
dependencies:
queue-microtask: 1.2.3
dev: true
@ -4926,7 +5185,7 @@ packages:
dev: true
/side-channel/1.0.4:
resolution: {integrity: sha1-785cj9wQTudRslxY1CkAEfpeos8=, tarball: side-channel/download/side-channel-1.0.4.tgz}
resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==}
dependencies:
call-bind: 1.0.2
get-intrinsic: 1.1.1
@ -5188,6 +5447,20 @@ packages:
strip-ansi: 7.0.1
dev: true
/string.prototype.trimend/1.0.4:
resolution: {integrity: sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==}
dependencies:
call-bind: 1.0.2
define-properties: 1.1.3
dev: true
/string.prototype.trimstart/1.0.4:
resolution: {integrity: sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==}
dependencies:
call-bind: 1.0.2
define-properties: 1.1.3
dev: true
/string_decoder/0.10.31:
resolution: {integrity: sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==}
dev: true
@ -5640,6 +5913,15 @@ packages:
dev: true
optional: true
/unbox-primitive/1.0.1:
resolution: {integrity: sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==}
dependencies:
function-bind: 1.1.1
has-bigints: 1.0.1
has-symbols: 1.0.2
which-boxed-primitive: 1.0.2
dev: true
/unc-path-regex/0.1.2:
resolution: {integrity: sha1-5z3T17DXxe2G+6xrCufYxqadUPo=, tarball: unc-path-regex/download/unc-path-regex-0.1.2.tgz}
engines: {node: '>=0.10.0'}
@ -5939,6 +6221,27 @@ packages:
- supports-color
dev: true
/vite-plugin-pages/0.20.2_225319ba269c7341e620f4355a031650:
resolution: {integrity: sha512-A/N6Pez9sMzt7ZEfd1H7P9tmP6LrZwXMexV8xSiRahnUeNw+gz0W2dsPLJDZBvcixDZqoK8ggKdmyxgVBuTAfg==}
peerDependencies:
'@vue/compiler-sfc': '>=3'
vite: '>=2'
peerDependenciesMeta:
'@vue/compiler-sfc':
optional: true
dependencies:
'@vue/compiler-sfc': 3.2.31
debug: 4.3.3
deep-equal: 2.0.5
fast-glob: 3.2.11
json5: 2.2.0
local-pkg: 0.4.1
vite: 2.8.2_sass@1.49.7
yaml: 2.0.0-10
transitivePeerDependencies:
- supports-color
dev: true
/vite-plugin-restart/0.1.1_vite@2.8.2:
resolution: {integrity: sha512-kBxOqRrdbjVmC0PiT2KNXZogpgqA2epMkny//VjWnOS2k9NV/vXA7PYgf8/1lmBCZsC+iMj1C1ODuAR/9Sig4A==, tarball: vite-plugin-restart/download/vite-plugin-restart-0.1.1.tgz}
peerDependencies:
@ -5977,6 +6280,23 @@ packages:
- supports-color
dev: true
/vite-plugin-vue-layouts/0.6.0_0509afcdf03496209baa96a2baefec6c:
resolution: {integrity: sha512-7QX7o/NpCfs+hyXphwYfmPqAEQ6qd4uXsvI0VsovjGT2eCoEE5dMdP6L+uqqNWY4uqv7oCvtinecZmbzZv/9Rg==}
peerDependencies:
vite: ^2.5.0
vue: ^2.6.12 || ^3.2.4
vue-router: ^3.5.1 || ^ 4.0.11
dependencies:
'@vue/compiler-sfc': 3.2.31
debug: 4.3.3
fast-glob: 3.2.11
vite: 2.8.2_sass@1.49.7
vue: 3.2.31
vue-router: 4.0.12_vue@3.2.31
transitivePeerDependencies:
- supports-color
dev: true
/vite-plugin-vue-setup-extend/0.4.0_vite@2.8.2:
resolution: {integrity: sha512-WMbjPCui75fboFoUTHhdbXzu4Y/bJMv5N9QT9a7do3wNMNHHqrk+Tn2jrSJU0LS5fGl/EG+FEDBYVUeWIkDqXQ==, tarball: vite-plugin-vue-setup-extend/download/vite-plugin-vue-setup-extend-0.4.0.tgz}
peerDependencies:
@ -6074,6 +6394,37 @@ packages:
resolution: {integrity: sha1-zVl8bVHVpey0c+6hmDpY+ooX3tk=, tarball: webpack-virtual-modules/download/webpack-virtual-modules-0.4.3.tgz?cache=0&sync_timestamp=1632822714135&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fwebpack-virtual-modules%2Fdownload%2Fwebpack-virtual-modules-0.4.3.tgz}
dev: true
/which-boxed-primitive/1.0.2:
resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==}
dependencies:
is-bigint: 1.0.4
is-boolean-object: 1.1.2
is-number-object: 1.0.6
is-string: 1.0.7
is-symbol: 1.0.4
dev: true
/which-collection/1.0.1:
resolution: {integrity: sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==}
dependencies:
is-map: 2.0.2
is-set: 2.0.2
is-weakmap: 2.0.1
is-weakset: 2.0.2
dev: true
/which-typed-array/1.1.7:
resolution: {integrity: sha512-vjxaB4nfDqwKI0ws7wZpxIlde1XrLX5uB0ZjpfshgmapJMD7jJWhZI+yToJTqaFByF0eNBcYxbjmCzoRP7CfEw==}
engines: {node: '>= 0.4'}
dependencies:
available-typed-arrays: 1.0.5
call-bind: 1.0.2
es-abstract: 1.19.1
foreach: 2.0.5
has-tostringtag: 1.0.0
is-typed-array: 1.1.8
dev: true
/which/1.3.1:
resolution: {integrity: sha1-pFBD1U9YBTFtqNYvn1CRjT2nCwo=, tarball: which/download/which-1.3.1.tgz}
hasBin: true
@ -6153,6 +6504,11 @@ packages:
engines: {node: '>= 6'}
dev: true
/yaml/2.0.0-10:
resolution: {integrity: sha512-FHV8s5ODFFQXX/enJEU2EkanNl1UDBUz8oa4k5Qo/sR+Iq7VmhCDkRMb0/mjJCNeAWQ31W8WV6PYStDE4d9EIw==}
engines: {node: '>= 12'}
dev: true
/yargs-parser/20.2.9:
resolution: {integrity: sha1-LrfcOwKJcY/ClfNidThFxBoMlO4=, tarball: yargs-parser/download/yargs-parser-20.2.9.tgz?cache=0&sync_timestamp=1634135116887&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fyargs-parser%2Fdownload%2Fyargs-parser-20.2.9.tgz}
engines: {node: '>=10'}

View File

@ -47,17 +47,17 @@ function handleCopy() {
<el-alert title="应用配置可实时预览效果,但仅是临时生效,要想真正作用于项目,可以点击下方的“复制配置”按钮,将配置粘贴到 src/settings.custom.json 中即可,或者也可在 src/settings.js 中直接修改默认配置。同时建议在生产环境隐藏应用配置功能。" type="error" :closable="false" />
<el-divider v-if="settingsStore.mode === 'pc'">导航栏模式</el-divider>
<div v-if="settingsStore.mode === 'pc'" class="menu-mode">
<el-tooltip content="侧边栏模式(含主导航)" placement="top" :show-after="500" :append-to-body="false">
<el-tooltip content="侧边栏模式(含主导航)" placement="top" :show-after="500" append-to=".container">
<div class="mode mode-side" :class="{'active': settings.menu.menuMode === 'side'}" @click="settings.menu.menuMode = 'side'">
<svg-icon name="el-icon-check" />
</div>
</el-tooltip>
<el-tooltip content="顶部模式" placement="top" :show-after="500" :append-to-body="false">
<el-tooltip content="顶部模式" placement="top" :show-after="500" append-to=".container">
<div class="mode mode-head" :class="{'active': settings.menu.menuMode === 'head'}" @click="settings.menu.menuMode = 'head'">
<svg-icon name="el-icon-check" />
</div>
</el-tooltip>
<el-tooltip content="侧边栏模式(不含主导航)" placement="top" :show-after="500" :append-to-body="false">
<el-tooltip content="侧边栏模式(不含主导航)" placement="top" :show-after="500" append-to=".container">
<div class="mode mode-single" :class="{'active': settings.menu.menuMode === 'single'}" @click="settings.menu.menuMode = 'single'">
<svg-icon name="el-icon-check" />
</div>
@ -71,7 +71,7 @@ function handleCopy() {
<div class="setting-item">
<div class="label">
切换跳转
<el-tooltip content="开启该功能后,切换侧边栏时,页面自动跳转至该侧边栏导航下第一个路由地址" placement="top" :append-to-body="false">
<el-tooltip content="开启该功能后,切换侧边栏时,页面自动跳转至该侧边栏导航下第一个路由地址" placement="top" append-to=".container">
<svg-icon name="el-icon-question-filled" />
</el-tooltip>
</div>
@ -80,7 +80,7 @@ function handleCopy() {
<div class="setting-item">
<div class="label">
保持展开一个
<el-tooltip content="开启该功能后,侧边栏只保持一个子菜单的展开" placement="top" :append-to-body="false">
<el-tooltip content="开启该功能后,侧边栏只保持一个子菜单的展开" placement="top" append-to=".container">
<svg-icon name="el-icon-question-filled" />
</el-tooltip>
</div>
@ -102,7 +102,7 @@ function handleCopy() {
<div class="setting-item">
<div class="label">
导航栏搜索
<el-tooltip content="对导航栏进行快捷搜索" placement="top" :append-to-body="false">
<el-tooltip content="对导航栏进行快捷搜索" placement="top" append-to=".container">
<svg-icon name="el-icon-question-filled" />
</el-tooltip>
</div>
@ -111,7 +111,7 @@ function handleCopy() {
<div v-if="settingsStore.mode === 'pc'" class="setting-item">
<div class="label">
全屏
<el-tooltip content="该功能使用场景极少,用户习惯于通过窗口“最大化”功能来扩大显示区域,以显示更多内容,并且使用 F11 键也可以进入全屏效果" placement="top" :append-to-body="false">
<el-tooltip content="该功能使用场景极少,用户习惯于通过窗口“最大化”功能来扩大显示区域,以显示更多内容,并且使用 F11 键也可以进入全屏效果" placement="top" append-to=".container">
<svg-icon name="el-icon-question-filled" />
</el-tooltip>
</div>
@ -120,7 +120,7 @@ function handleCopy() {
<div class="setting-item">
<div class="label">
页面刷新
<el-tooltip content="开启时会阻止原生 F5 键刷新功能,并采用框架提供的刷新模式进行页面刷新" placement="top" :append-to-body="false">
<el-tooltip content="开启时会阻止原生 F5 键刷新功能,并采用框架提供的刷新模式进行页面刷新" placement="top" append-to=".container">
<svg-icon name="el-icon-question-filled" />
</el-tooltip>
</div>
@ -147,7 +147,7 @@ function handleCopy() {
<div class="setting-item">
<div class="label">
是否开启
<el-tooltip content="该功能开启时,登录成功默认进入控制台页面,反之则默认进入导航栏里第一个导航页面" placement="top" :append-to-body="false">
<el-tooltip content="该功能开启时,登录成功默认进入控制台页面,反之则默认进入导航栏里第一个导航页面" placement="top" append-to=".container">
<svg-icon name="el-icon-question-filled" />
</el-tooltip>
</div>
@ -161,7 +161,7 @@ function handleCopy() {
<div class="setting-item">
<div class="label">
组件尺寸
<el-tooltip content="全局设置 Element Plus 组件的默认尺寸大小" placement="top" :append-to-body="false">
<el-tooltip content="全局设置 Element Plus 组件的默认尺寸大小" placement="top" append-to=".container">
<svg-icon name="el-icon-question-filled" />
</el-tooltip>
</div>
@ -175,14 +175,10 @@ function handleCopy() {
<div class="label">是否启用权限</div>
<el-switch v-model="settings.app.enablePermission" />
</div>
<div class="setting-item">
<div class="label">是否开启后端返回路由数据</div>
<el-switch v-model="settings.app.enableBackendReturnRoute" />
</div>
<div class="setting-item">
<div class="label">
载入进度条
<el-tooltip content="该功能开启时,跳转路由会看到页面顶部有进度条" placement="top" :append-to-body="false">
<el-tooltip content="该功能开启时,跳转路由会看到页面顶部有进度条" placement="top" append-to=".container">
<svg-icon name="el-icon-question-filled" />
</el-tooltip>
</div>
@ -191,7 +187,7 @@ function handleCopy() {
<div class="setting-item">
<div class="label">
动态标题
<el-tooltip content="该功能开启时,页面标题会显示当前路由标题,格式为“页面标题 - 网站名称”;关闭时则显示网站名称,网站名称在项目根目录下 .env.* 文件里配置" placement="top" :append-to-body="false">
<el-tooltip content="该功能开启时,页面标题会显示当前路由标题,格式为“页面标题 - 网站名称”;关闭时则显示网站名称,网站名称在项目根目录下 .env.* 文件里配置" placement="top" append-to=".container">
<svg-icon name="el-icon-question-filled" />
</el-tooltip>
</div>

View File

@ -7,6 +7,8 @@ import { useSettingsStore } from '@/store/modules/settings'
const settingsStore = useSettingsStore()
import { useRouteStore } from '@/store/modules/route'
const routeStore = useRouteStore()
import { useMenuStore } from '@/store/modules/menu'
const menuStore = useMenuStore()
const isShow = ref(false)
const searchInput = ref('')
@ -68,9 +70,15 @@ onMounted(() => {
isShow.value = true
}
})
routeStore.routes.map(item => {
getSourceList(item.children)
})
if (settingsStore.app.routeBaseOn !== 'filesystem') {
routeStore.routes.map(item => {
getSourceList(item.children)
})
} else {
menuStore.menus.map(item => {
getSourceList(item.children)
})
}
})
function hasChildren(item) {

View File

@ -30,8 +30,8 @@ function onSidebarScroll(e) {
}"
>
<transition-group name="sub-sidebar">
<template v-for="route in menuStore.sidebarMenus">
<SidebarItem v-if="route.meta.sidebar !== false" :key="route.path" :item="route" :base-path="route.path" />
<template v-for="(route, index) in menuStore.sidebarMenus">
<SidebarItem v-if="route.meta.sidebar !== false" :key="route.path || index" :item="route" :base-path="route.path" />
</template>
</transition-group>
</el-menu>

View File

@ -57,7 +57,7 @@ function pathCompile(path) {
<div v-if="enableSidebarCollapse" class="sidebar-collapse" :class="{'is-collapse': settingsStore.menu.subMenuCollapse}" @click="settingsStore.toggleSidebarCollapse()">
<svg-icon name="toolbar-collapse" />
</div>
<el-breadcrumb v-if="settingsStore.topbar.enableBreadcrumb && settingsStore.mode === 'pc'" separator-class="el-icon-arrow-right">
<el-breadcrumb v-if="settingsStore.topbar.enableBreadcrumb && settingsStore.mode === 'pc' && settingsStore.app.routeBaseOn !== 'filesystem'" separator-class="el-icon-arrow-right">
<transition-group name="breadcrumb">
<el-breadcrumb-item v-for="(item, index) in breadcrumbList" :key="item.path" :to="index < breadcrumbList.length - 1 ? pathCompile(item.path) : ''">
{{ item.title }}

15
src/menu/index.js Normal file
View File

@ -0,0 +1,15 @@
import MultilevelMenuExample from './modules/multilevel.menu.example'
const menu = [
{
meta: {
title: '演示',
icon: 'sidebar-default'
},
children: [
MultilevelMenuExample
]
}
]
export default menu

View File

@ -0,0 +1,46 @@
export default {
meta: {
title: '多级导航',
icon: 'sidebar-menu'
},
children: [
{
path: '/multilevel_menu_example/page',
meta: {
title: '导航1'
}
},
{
meta: {
title: '导航2'
},
children: [
{
path: '/multilevel_menu_example/level2/page',
meta: {
title: '导航2-1'
}
},
{
meta: {
title: '导航2-2'
},
children: [
{
path: '/multilevel_menu_example/level2/level3/page1',
meta: {
title: '导航2-2-1'
}
},
{
path: '/multilevel_menu_example/level2/level3/page2',
meta: {
title: '导航2-2-2'
}
}
]
}
]
}
]
}

68
src/mock/menu.js Normal file
View File

@ -0,0 +1,68 @@
export default [
{
url: '/mock/menu/list',
method: 'get',
response: () => {
return {
error: '',
status: 1,
data: [
{
meta: {
title: '演示',
icon: 'sidebar-default'
},
children: [
{
meta: {
title: '多级导航',
icon: 'sidebar-menu'
},
children: [
{
path: '/multilevel_menu_example/page',
meta: {
title: '导航1'
}
},
{
meta: {
title: '导航2'
},
children: [
{
path: '/multilevel_menu_example/level2/page',
meta: {
title: '导航2-1'
}
},
{
meta: {
title: '导航2-2'
},
children: [
{
path: '/multilevel_menu_example/level2/level3/page1',
meta: {
title: '导航2-2-1'
}
},
{
path: '/multilevel_menu_example/level2/level3/page2',
meta: {
title: '导航2-2-2'
}
}
]
}
]
}
]
}
]
}
]
}
}
}
]

View File

@ -10,7 +10,7 @@ import { useNProgress } from '@vueuse/integrations/useNProgress'
const { isLoading } = useNProgress()
// 固定路由
const constantRoutes = [
let constantRoutes = [
{
path: '/login',
name: 'login',
@ -81,7 +81,7 @@ import EcologyExample from './modules/ecology.example'
import CooperationExample from './modules/cooperation.example'
// 动态路由(异步路由、导航栏路由)
const asyncRoutes = [
let asyncRoutes = [
{
meta: {
title: '演示',
@ -129,13 +129,26 @@ const asyncRoutes = [
]
const lastRoute = {
path: '/:pathMatch(.*)*',
component: () => import('@/views/404.vue'),
path: '/:all(.*)*',
name: 'notFound',
component: () => import('@/views/[...all].vue'),
meta: {
title: '找不到页面'
}
}
import { setupLayouts } from 'virtual:generated-layouts'
import generatedRoutes from 'virtual:generated-pages'
if (useSettingsOutsideStore().app.routeBaseOn === 'filesystem') {
constantRoutes = generatedRoutes.filter(item => {
return item.meta?.enabled !== false && item.meta?.constant === true
})
asyncRoutes = setupLayouts(generatedRoutes.filter(item => {
return item.meta?.enabled !== false && item.meta?.constant !== true && item.meta?.layout !== false
}))
}
const router = createRouter({
history: createWebHashHistory(),
routes: constantRoutes
@ -184,10 +197,24 @@ router.beforeEach(async(to, from, next) => {
next()
}
} else {
if (!settingsOutsideStore.app.enableBackendReturnRoute) {
await routeOutsideStore.generateRoutesAtFront(asyncRoutes)
} else {
await routeOutsideStore.generateRoutesAtBack()
switch (settingsOutsideStore.app.routeBaseOn) {
case 'frontend':
await routeOutsideStore.generateRoutesAtFront(asyncRoutes)
break
case 'backend':
await routeOutsideStore.generateRoutesAtBack()
break
case 'filesystem':
await routeOutsideStore.generateRoutesAtFilesystem(asyncRoutes)
switch (settingsOutsideStore.menu.baseOn) {
case 'frontend':
await menuOutsideStore.generateMenusAtFront()
break
case 'backend':
await menuOutsideStore.generateMenusAtBack()
break
}
break
}
let removeRoutes = []
routeOutsideStore.flatRoutes.forEach(route => {
@ -195,7 +222,12 @@ router.beforeEach(async(to, from, next) => {
removeRoutes.push(router.addRoute(route))
}
})
removeRoutes.push(router.addRoute(lastRoute))
if (settingsOutsideStore.app.routeBaseOn === 'filesystem') {
const otherRoutes = generatedRoutes.filter(item => item.meta?.constant !== true && item.meta?.layout === false)
otherRoutes.length && removeRoutes.push(router.addRoute(...otherRoutes))
} else {
removeRoutes.push(router.addRoute(lastRoute))
}
// 记录的 accessRoutes 路由数据,在登出时会使用到,不使用 router.removeRoute 是考虑配置的路由可能不一定有设置 name ,则通过调用 router.addRoute() 返回的回调进行删除
routeOutsideStore.setCurrentRemoveRoutes(removeRoutes)
next({ ...to, replace: true })

View File

@ -10,12 +10,17 @@ let globalSettings = {
* 4鉴权函数this.$auth()this.$authAll()
*/
enablePermission: false,
// 是否开启后端返回路由数据
enableBackendReturnRoute: false,
// 是否开启载入进度条
enableProgress: true,
// 是否开启动态标题
enableDynamicTitle: false
enableDynamicTitle: false,
/**
* 路由数据来源
* frontend 前端
* backend 后端
* filesystem 文件系统
*/
routeBaseOn: 'frontend'
},
// 控制台
dashboard: {
@ -31,6 +36,12 @@ let globalSettings = {
},
// 导航栏
menu: {
/**
* 数据来源 app.routeBaseOn filesystem 时生效
* frontend 前端
* backend 后端
*/
baseOn: 'frontend',
/**
* 导航栏模式
* side 侧边栏模式含主导航

View File

@ -1,9 +1,12 @@
import { defineStore } from 'pinia'
import { piniaStore } from '@/store'
import { resolveRoutePath } from '@/util'
import { deepClone, resolveRoutePath } from '@/util'
import path from 'path-browserify'
import api from '@/api'
import menu from '@/menu'
import { useSettingsStore } from './settings'
import { useUserStore } from './user'
import { useRouteStore } from './route'
function getDeepestPath(routes, rootPath = '') {
@ -29,28 +32,67 @@ function getDeepestPath(routes, rootPath = '') {
return retnPath
}
function hasPermission(permissions, route) {
let isAuth = false
if (route.meta && route.meta.auth) {
isAuth = permissions.some(auth => {
if (typeof route.meta.auth == 'string') {
return route.meta.auth === auth
} else {
return route.meta.auth.some(routeAuth => {
return routeAuth === auth
})
}
})
} else {
isAuth = true
}
return isAuth
}
function filterAsyncMenus(menus, permissions) {
const res = []
menus.forEach(menu => {
let tmpMenu = deepClone(menu)
if (hasPermission(permissions, tmpMenu)) {
if (tmpMenu.children) {
tmpMenu.children = filterAsyncMenus(tmpMenu.children, permissions)
tmpMenu.children.length && res.push(tmpMenu)
} else {
res.push(tmpMenu)
}
}
})
return res
}
export const useMenuStore = defineStore(
// 唯一ID
'menu',
{
state: () => ({
menus: [],
actived: 0
}),
getters: {
// 完整导航数据
allMenus() {
const settingsStore = useSettingsStore()
const routeStore = useRouteStore()
let routes
if (settingsStore.menu.menuMode === 'single') {
routes = [{ children: [] }]
routeStore.routes.map(item => {
routes[0].children.push(...item.children)
})
let menus
if (settingsStore.app.routeBaseOn !== 'filesystem') {
const routeStore = useRouteStore()
if (settingsStore.menu.menuMode === 'single') {
menus = [{ children: [] }]
routeStore.routes.map(item => {
menus[0].children.push(...item.children)
})
} else {
menus = routeStore.routes
}
} else {
routes = routeStore.routes
menus = this.menus
}
return routes
return menus
},
// 次导航数据
sidebarMenus() {
@ -61,18 +103,60 @@ export const useMenuStore = defineStore(
return this.allMenus.length > 0 ? getDeepestPath(this.sidebarMenus[0]) : '/'
},
defaultOpenedPaths() {
const routeStore = useRouteStore()
const settingsStore = useSettingsStore()
let defaultOpenedPaths = []
routeStore.routes.map(item => {
item.meta.defaultOpened && defaultOpenedPaths.push(item.path)
item.children && item.children.map(child => {
child.meta.defaultOpened && defaultOpenedPaths.push(path.resolve(item.path, child.path))
if (settingsStore.app.routeBaseOn !== 'filesystem') {
const routeStore = useRouteStore()
routeStore.routes.map(item => {
item.meta.defaultOpened && defaultOpenedPaths.push(item.path)
item.children && item.children.map(child => {
child.meta.defaultOpened && defaultOpenedPaths.push(path.resolve(item.path, child.path))
})
})
})
}
return defaultOpenedPaths
}
},
actions: {
// 生成导航(前端生成)
generateMenusAtFront() {
// eslint-disable-next-line no-async-promise-executor
return new Promise(async resolve => {
const settingsStore = useSettingsStore()
const userStore = useUserStore()
let accessedMenus
// 如果权限功能开启,则需要对导航数据进行筛选过滤
if (settingsStore.app.enablePermission) {
const permissions = await userStore.getPermissions()
accessedMenus = filterAsyncMenus(menu, permissions)
} else {
accessedMenus = deepClone(menu)
}
this.menus = accessedMenus.filter(item => item.children.length != 0)
resolve()
})
},
// 生成导航(后端生成)
generateMenusAtBack() {
return new Promise(resolve => {
api.get('menu/list', {
baseURL: '/mock/'
}).then(async res => {
const settingsStore = useSettingsStore()
const userStore = useUserStore()
let accessedMenus
// 如果权限功能开启,则需要对导航数据进行筛选过滤
if (settingsStore.app.enablePermission) {
const permissions = await userStore.getPermissions()
accessedMenus = filterAsyncMenus(res.data, permissions)
} else {
accessedMenus = deepClone(res.data)
}
this.menus = accessedMenus.filter(item => item.children.length != 0)
resolve()
})
})
},
// 切换主导航
setActived(data) {
if (typeof data === 'number') {

View File

@ -130,19 +130,26 @@ export const useRouteStore = defineStore(
getters: {
// 扁平化路由(将三级及以上路由数据拍平成二级)
flatRoutes: state => {
const settingsStore = useSettingsStore()
let routes = []
if (state.routes) {
state.routes.map(item => {
routes.push(...deepClone(item.children))
})
routes.map(item => {
if (item.children) {
item.children = flatAsyncRoutes(item.children, [{
path: item.path,
title: item.meta.title
}], item.path)
}
})
if (settingsStore.app.routeBaseOn !== 'filesystem') {
state.routes.map(item => {
routes.push(...deepClone(item.children))
})
routes.map(item => {
if (item.children) {
item.children = flatAsyncRoutes(item.children, [{
path: item.path,
title: item.meta.title
}], item.path)
}
})
} else {
state.routes.map(item => {
routes.push(deepClone(item))
})
}
}
return routes
}
@ -192,6 +199,26 @@ export const useRouteStore = defineStore(
})
})
},
// 根据权限动态生成路由(文件系统生成)
generateRoutesAtFilesystem(asyncRoutes) {
// eslint-disable-next-line no-async-promise-executor
return new Promise(async resolve => {
const settingsStore = useSettingsStore()
const userStore = useUserStore()
let accessedRoutes
// 如果权限功能开启,则需要对路由数据进行筛选过滤
if (settingsStore.app.enablePermission) {
const permissions = await userStore.getPermissions()
accessedRoutes = filterAsyncRoutes(asyncRoutes, permissions)
} else {
accessedRoutes = deepClone(asyncRoutes)
}
// 设置 routes 数据
this.isGenerate = true
this.routes = accessedRoutes.filter(item => item.children.length != 0)
resolve()
})
},
// 记录 accessRoutes 路由,用于登出时删除路由
setCurrentRemoveRoutes(routes) {
this.currentRemoveRoutes = routes

View File

@ -1,3 +1,13 @@
<route>
{
name: 'notFound',
meta: {
title: "找不到页面",
layout: false
}
}
</route>
<script setup>
import { onBeforeRouteLeave } from 'vue-router'
const router = useRouter()

View File

@ -1,3 +1,11 @@
<route>
{
meta: {
enabled: false
}
}
</route>
<template>
<div>
<page-main>

View File

@ -1,3 +1,11 @@
<route>
{
meta: {
enabled: false
}
}
</route>
<template>
<div>
<page-main>

View File

@ -1,3 +1,11 @@
<route>
{
meta: {
enabled: false
}
}
</route>
<template>
<page-main>
<router-link :to="{name: 'breadcrumbExampleDetail1'}">查看详情页</router-link>

View File

@ -1,3 +1,11 @@
<route>
{
meta: {
enabled: false
}
}
</route>
<template>
<page-main>
<router-link :to="{name: 'breadcrumbExampleDetail2'}">查看详情页</router-link>

View File

@ -1,3 +1,11 @@
<route>
{
meta: {
enabled: false
}
}
</route>
<script setup>
import Alert from './components/alert.vue'
import { Search, Edit, Check, Message, Star, Delete, Share, ArrowLeft } from '@element-plus/icons-vue'

View File

@ -1,3 +1,11 @@
<route>
{
meta: {
enabled: false
}
}
</route>
<script>
import Alert from './components/alert.vue'

View File

@ -1,3 +1,11 @@
<route>
{
meta: {
enabled: false
}
}
</route>
<script>
import Alert from './components/alert.vue'

View File

@ -1,3 +1,11 @@
<route>
{
meta: {
enabled: false
}
}
</route>
<script>
import Alert from './components/alert.vue'

View File

@ -1,3 +1,11 @@
<route>
{
meta: {
enabled: false
}
}
</route>
<script setup>
import Alert from './components/alert.vue'
import { Search } from '@element-plus/icons-vue'

View File

@ -1,3 +1,11 @@
<route>
{
meta: {
enabled: false
}
}
</route>
<script>
import Alert from './components/alert.vue'

View File

@ -1,3 +1,11 @@
<route>
{
meta: {
enabled: false
}
}
</route>
<script>
import Alert from './components/alert.vue'

View File

@ -1,3 +1,11 @@
<route>
{
meta: {
enabled: false
}
}
</route>
<script setup>
import Alert from './components/alert.vue'
import { Edit } from '@element-plus/icons-vue'

View File

@ -1,3 +1,11 @@
<route>
{
meta: {
enabled: false
}
}
</route>
<script>
import Alert from './components/alert.vue'

View File

@ -1,3 +1,11 @@
<route>
{
meta: {
enabled: false
}
}
</route>
<script>
import Alert from './components/alert.vue'

View File

@ -1,3 +1,11 @@
<route>
{
meta: {
enabled: false
}
}
</route>
<script>
import Alert from './components/alert.vue'

View File

@ -1,3 +1,11 @@
<route>
{
meta: {
enabled: false
}
}
</route>
<script>
import Alert from './components/alert.vue'

View File

@ -1,3 +1,11 @@
<route>
{
meta: {
enabled: false
}
}
</route>
<script>
import Alert from './components/alert.vue'

View File

@ -1,3 +1,11 @@
<route>
{
meta: {
enabled: false
}
}
</route>
<script>
import Alert from './components/alert.vue'

View File

@ -1,3 +1,11 @@
<route>
{
meta: {
enabled: false
}
}
</route>
<script>
export default {
data() {

View File

@ -1,3 +1,11 @@
<route>
{
meta: {
enabled: false
}
}
</route>
<script>
export default {
name: 'ComponentExampleArea',

View File

@ -1,3 +1,11 @@
<route>
{
meta: {
enabled: false
}
}
</route>
<script>
export default {
name: 'ComponentExampleBatchactionbar',

View File

@ -1,3 +1,11 @@
<route>
{
meta: {
enabled: false
}
}
</route>
<script setup>
import { mavonEditor } from 'mavon-editor'
import 'mavon-editor/dist/css/index.css'

View File

@ -1,3 +1,11 @@
<route>
{
meta: {
enabled: false
}
}
</route>
<script>
export default {
props: {},

View File

@ -1,3 +1,11 @@
<route>
{
meta: {
enabled: false
}
}
</route>
<template>
<div>
<page-header title="页头" content="PageHeader" />

View File

@ -1,3 +1,11 @@
<route>
{
meta: {
enabled: false
}
}
</route>
<template>
<div>
<page-header title="内容块" content="PageMain" />

View File

@ -1,3 +1,11 @@
<route>
{
meta: {
enabled: false
}
}
</route>
<script>
export default {
data() {

View File

@ -1,3 +1,11 @@
<route>
{
meta: {
enabled: false
}
}
</route>
<script>
export default {
data() {

View File

@ -1,3 +1,11 @@
<route>
{
meta: {
enabled: false
}
}
</route>
<script>
export default {
name: 'ComponentExampleTableHeightAdaption',

View File

@ -1,3 +1,11 @@
<route>
{
meta: {
enabled: false
}
}
</route>
<template>
<div>
<page-header title="趋势符号">

View File

@ -1,3 +1,11 @@
<route>
{
meta: {
enabled: false
}
}
</route>
<script>
export default {
data() {

View File

@ -1,3 +1,12 @@
<route>
{
name: 'dashboard',
meta: {
title: "控制台"
}
}
</route>
<script setup>
const locationOrigin = location.origin

View File

@ -1,3 +1,11 @@
<route>
{
meta: {
enabled: false
}
}
</route>
<template>
<page-main>
<el-button @click="$router.go(-1)">返回</el-button>

View File

@ -1,3 +1,11 @@
<route>
{
meta: {
enabled: false
}
}
</route>
<script setup name="TabExampleNested1">
import { useKeepAliveStore } from '@/store/modules/keepAlive'
const keepAliveStore = useKeepAliveStore()

View File

@ -1,3 +1,11 @@
<route>
{
meta: {
enabled: false
}
}
</route>
<script setup name="TabExampleNested2">
import { useKeepAliveStore } from '@/store/modules/keepAlive'
const keepAliveStore = useKeepAliveStore()

View File

@ -1,3 +1,11 @@
<route>
{
meta: {
enabled: false
}
}
</route>
<script>
export default {
name: 'TabExampleNestedTest',

View File

@ -1,3 +1,11 @@
<route>
{
meta: {
enabled: false
}
}
</route>
<script>
export default {
name: 'TabExampleNestedTest2',

View File

@ -1,3 +1,11 @@
<route>
{
meta: {
enabled: false
}
}
</route>
<script setup name="KeepAliveExamplePage">
import { onBeforeRouteLeave } from 'vue-router'

View File

@ -1,3 +1,13 @@
<route>
{
meta: {
title: "登录",
constant: true,
layout: false
}
}
</route>
<script setup name="Login">
const { proxy } = getCurrentInstance()
const route = useRoute(), router = useRouter()

View File

@ -1,3 +1,11 @@
<route>
{
meta: {
enabled: false
}
}
</route>
<script setup>
const { proxy } = getCurrentInstance()

View File

@ -1,3 +1,11 @@
<route>
{
meta: {
title: '导航2-2-1'
}
}
</route>
<template>
<div>
<page-main>

View File

@ -1,3 +1,11 @@
<route>
{
meta: {
title: '导航2-2-2'
}
}
</route>
<template>
<div>
<page-main>

View File

@ -1,3 +1,11 @@
<route>
{
meta: {
title: '导航2-1'
}
}
</route>
<template>
<div>
<page-main>

View File

@ -1,3 +1,11 @@
<route>
{
meta: {
title: '导航1'
}
}
</route>
<template>
<div>
<page-main>

View File

@ -1,3 +1,11 @@
<route>
{
meta: {
enabled: false
}
}
</route>
<script setup>
const { proxy } = getCurrentInstance()

View File

@ -1,3 +1,11 @@
<route>
{
meta: {
title: "修改密码"
}
}
</route>
<script setup name="PersonalEditPassword">
const route = useRoute(), router = useRouter()
const { proxy } = getCurrentInstance()

View File

@ -1,3 +1,12 @@
<route>
{
meta: {
title: "个人设置",
cache: "personal-edit.password"
}
}
</route>
<script setup name="PersonalSetting">
const router = useRouter()
const { proxy } = getCurrentInstance()
@ -26,7 +35,6 @@ function editPassword() {
<template>
<div>
<!-- 页面Setting -->
<page-main>
<el-tabs tab-position="left" style="height: 600px;">
<el-tab-pane label="基本设置" class="basic">

View File

@ -1,3 +1,12 @@
<route>
{
meta: {
constant: true,
layout: false
}
}
</route>
<script setup>
const router = useRouter()

View File

@ -1,3 +1,11 @@
<route>
{
meta: {
enabled: false
}
}
</route>
<template>
<div>
<page-header title="即将推出 Vue3 版本视频教程,尽请期待" />

View File

@ -8,6 +8,8 @@ import createComponents from './components'
import createSetupExtend from './setup-extend'
import createSvgIcon from './svg-icon'
import createMock from './mock'
import createLayouts from './layouts'
import createPages from './pages'
import createCompression from './compression'
import createSpritesmith from './spritesmith'
import createBanner from './banner'
@ -22,6 +24,8 @@ export default function createVitePlugins(viteEnv, isBuild = false) {
vitePlugins.push(createSetupExtend())
vitePlugins.push(createSvgIcon(isBuild))
vitePlugins.push(createMock())
vitePlugins.push(createLayouts())
vitePlugins.push(createPages())
isBuild && vitePlugins.push(...createCompression(viteEnv))
vitePlugins.push(...createSpritesmith(isBuild))
vitePlugins.push(createBanner())

8
vite/plugins/layouts.js Normal file
View File

@ -0,0 +1,8 @@
import Layouts from 'vite-plugin-vue-layouts'
export default function createPages() {
return Layouts({
layoutsDirs: 'src/layout',
defaultLayout: 'index'
})
}

10
vite/plugins/pages.js Normal file
View File

@ -0,0 +1,10 @@
import Pages from 'vite-plugin-pages'
export default function createPages() {
return Pages({
dirs: 'src/views',
exclude: [
'**/components/**/*.vue'
]
})
}