feat: align header logo with sidebar, slim footer, mixbar only in sidebar layout

- MixBar 仅左右(sidebar)布局可用,horizontal 不再渲染
- 底部 footer 高度收紧
- 顶栏 Logo 区与左侧菜单(或 MixBar+菜单)同宽;侧栏折叠仅显 Logo、展开显 Logo+标题
- 安装 sharp 使 logo.png 构建时优化(-81%)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
liuyun 2026-10-11 00:35:49 +08:00
parent 8a0f510e3a
commit 66f4a38c98
9 changed files with 385 additions and 10 deletions

View File

@ -49,6 +49,7 @@
"prettier": "3.8.4", "prettier": "3.8.4",
"rollup-plugin-visualizer": "^7.0.1", "rollup-plugin-visualizer": "^7.0.1",
"sass": "^1.101.0", "sass": "^1.101.0",
"sharp": "^0.35.5",
"terser": "^5.48.0", "terser": "^5.48.0",
"typescript": "~6.0.0", "typescript": "~6.0.0",
"unocss": "^66.7.2", "unocss": "^66.7.2",

334
pnpm-lock.yaml generated
View File

@ -248,6 +248,9 @@ importers:
sass: sass:
specifier: ^1.101.0 specifier: ^1.101.0
version: 1.101.0 version: 1.101.0
sharp:
specifier: ^0.35.5
version: 0.35.5(@types/node@24.12.2)
terser: terser:
specifier: ^5.48.0 specifier: ^5.48.0
version: 5.48.0 version: 5.48.0
@ -274,7 +277,7 @@ importers:
version: 2.5.3 version: 2.5.3
vite-plugin-image-optimizer: vite-plugin-image-optimizer:
specifier: ^2.0.3 specifier: ^2.0.3
version: 2.0.3(vite@8.0.16(@types/node@24.12.2)(jiti@2.6.1)(sass@1.101.0)(terser@5.48.0)(yaml@2.8.4)) version: 2.0.3(sharp@0.35.5(@types/node@24.12.2))(vite@8.0.16(@types/node@24.12.2)(jiti@2.6.1)(sass@1.101.0)(terser@5.48.0)(yaml@2.8.4))
vite-plugin-svg-icons: vite-plugin-svg-icons:
specifier: ^2.0.1 specifier: ^2.0.1
version: 2.0.1(supports-color@3.2.3)(vite@8.0.16(@types/node@24.12.2)(jiti@2.6.1)(sass@1.101.0)(terser@5.48.0)(yaml@2.8.4)) version: 2.0.1(supports-color@3.2.3)(vite@8.0.16(@types/node@24.12.2)(jiti@2.6.1)(sass@1.101.0)(terser@5.48.0)(yaml@2.8.4))
@ -857,6 +860,9 @@ packages:
'@emnapi/runtime@1.10.0': '@emnapi/runtime@1.10.0':
resolution: {integrity: sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==} resolution: {integrity: sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==}
'@emnapi/runtime@1.11.3':
resolution: {integrity: sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==}
'@emnapi/wasi-threads@1.2.1': '@emnapi/wasi-threads@1.2.1':
resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==} resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==}
@ -1089,6 +1095,168 @@ packages:
peerDependencies: peerDependencies:
vue: '>=3.0.0' vue: '>=3.0.0'
'@img/colour@1.1.0':
resolution: {integrity: sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==}
engines: {node: '>=18'}
'@img/sharp-darwin-arm64@0.35.5':
resolution: {integrity: sha512-QRUlFQ0WxvdWyqqG/WtI3iupfD5rBzmCHXSdPsY91sAtVtTo7Q4cb6zOccZ3gqEqkr0f1As1ehLqmEpDsRf+lg==}
engines: {node: '>=20.9.0'}
cpu: [arm64]
os: [darwin]
'@img/sharp-darwin-x64@0.35.5':
resolution: {integrity: sha512-+BR255RhDlpygUpOc/Jdt1nT6DQ3XG/ERo5wbcdOf5Q320dKtPCKPLR1LJs9VGXRaMa8l1uUa0tkCNOXiAxZUw==}
engines: {node: '>=20.9.0'}
cpu: [x64]
os: [darwin]
'@img/sharp-freebsd-wasm32@0.35.5':
resolution: {integrity: sha512-Y/z91nEZ4uIBX5X3nfTovjU9lHNKFYbL2lpHCLVNmXQK03VIZvXBBt0KxbPGp2SdGSF+2mQU4e+hQaWOt86iAw==}
engines: {node: '>=20.9.0'}
os: [freebsd]
'@img/sharp-libvips-darwin-arm64@1.3.4':
resolution: {integrity: sha512-5R89nBYiRdUlSWJxPhO+GVtaXzXSxKnRu/xqMn3KTA3L9EB9Oy/P+Nn2f2vlhPuUdy/Zusb2DarbyTpGCfEDuw==}
cpu: [arm64]
os: [darwin]
'@img/sharp-libvips-darwin-x64@1.3.4':
resolution: {integrity: sha512-iR2OKH80yi0U+dUplyh3/xdpFvps6YkCwsXenIJxqxR1v9o+xtKTGbS9H7cps+2Vxjc8B1j96p75NmTGjIhtpQ==}
cpu: [x64]
os: [darwin]
'@img/sharp-libvips-linux-arm64@1.3.4':
resolution: {integrity: sha512-Y3dgX/6lE2QhQb+Gxy0WZxfg9MEm/JBjamZpS2IklP7xIQoKN4hzAm7KcMVGtaVDt3neE9OKBC7vAfonA/Lr1A==}
cpu: [arm64]
os: [linux]
libc: [glibc]
'@img/sharp-libvips-linux-arm@1.3.4':
resolution: {integrity: sha512-LmRtTsOHuvM2+wlO2Db37dx5MiZhB0FvSunciw48YjdOkZz9KAiRbm8ujeMOA1INqmei5NapFxYEK1D1ZSidmw==}
cpu: [arm]
os: [linux]
libc: [glibc]
'@img/sharp-libvips-linux-ppc64@1.3.4':
resolution: {integrity: sha512-Le6boB8Tai0Nis+gIxIpKx68UDVVIqdR8Tin5Yf1z2LJJQLDJvCDRqRu+jC2qCoD+eIomonmOwB4smBRxfVpYQ==}
cpu: [ppc64]
os: [linux]
libc: [glibc]
'@img/sharp-libvips-linux-riscv64@1.3.4':
resolution: {integrity: sha512-aHkkIEHPRdQEegJN20MLmGtxYD9R2wQr3Cwpddnu5+YKMt6Uzax7S9h5gpZTo8wyrGuZSlfQ63OevL5mTyOC7Q==}
cpu: [riscv64]
os: [linux]
libc: [glibc]
'@img/sharp-libvips-linux-s390x@1.3.4':
resolution: {integrity: sha512-ra/mB6MikESDUO7Yg+Mi95bFBb9GsObURuhnOv3OqknjGe9sZrG8tCe9q0xSIGrtLgvgw0gKnFWcK4blSgQOuQ==}
cpu: [s390x]
os: [linux]
libc: [glibc]
'@img/sharp-libvips-linux-x64@1.3.4':
resolution: {integrity: sha512-GJ//SSXbnwSDes02umB3nDJLFcQzw8a18V8fyhqr6tV515tOEMdImjjxj1AoafMRz56F3PHgftnj1QEKSU1zkw==}
cpu: [x64]
os: [linux]
libc: [glibc]
'@img/sharp-libvips-linuxmusl-arm64@1.3.4':
resolution: {integrity: sha512-hvulFwtjUcagsis6BBxHwGFwWoNZjgYmULGVrZcyfNbjA8hKILbRxGg15/7w5HDyXHXUos/j6baAWqnCyQ2DWA==}
cpu: [arm64]
os: [linux]
libc: [musl]
'@img/sharp-libvips-linuxmusl-x64@1.3.4':
resolution: {integrity: sha512-6zXKeE/p39I1AmA3cJG35eyBGNqNddLnUXjhwBnsGjFPWqf5VKkDBEqaEkPDoTEtkxwi2vv8Tcr2mDyP4So7Fg==}
cpu: [x64]
os: [linux]
libc: [musl]
'@img/sharp-linux-arm64@0.35.5':
resolution: {integrity: sha512-LYVx5JTsOM2CBzmxreh+nl64/3H6Xb09iSLknqH47z2T2DFFxDeFLP5y4dJwe6H7uGQlHPyEEtIqyo3DYsRwdQ==}
engines: {node: '>=20.9.0'}
cpu: [arm64]
os: [linux]
libc: [glibc]
'@img/sharp-linux-arm@0.35.5':
resolution: {integrity: sha512-LEaXK2WdXVK5ykcw0buWyPMsmLLL2vpHLD6yrNSW+JGEL3BZPA4tpKN6iaMc4AxTTAoaX/sU1rOL51lcIz48ZQ==}
engines: {node: '>=20.9.0'}
cpu: [arm]
os: [linux]
libc: [glibc]
'@img/sharp-linux-ppc64@0.35.5':
resolution: {integrity: sha512-QVxAAq8evVRI9ia2vqgwrmWucn5Dfv+JdWzj75pD8omHLPSP7f8p20O8jxzjCcuCEQEOtYOZUmX1hkiZ0kdevA==}
engines: {node: '>=20.9.0'}
cpu: [ppc64]
os: [linux]
libc: [glibc]
'@img/sharp-linux-riscv64@0.35.5':
resolution: {integrity: sha512-LtdreXguaavKODPIfzJ4kffx7UNt1omwtK0rch4EBbbSTXPnxWmYSayXdLJw0fJzQ97kHt1gL/yh4tvU+nCyRQ==}
engines: {node: '>=20.9.0'}
cpu: [riscv64]
os: [linux]
libc: [glibc]
'@img/sharp-linux-s390x@0.35.5':
resolution: {integrity: sha512-UZasTOFiYzotTsGOCu42BfUzP6Tu6Do/947iRm1RsLKvlllxwGcn4RN27LibGWceix4Y+Pmw3jsnTcCQIgWjqA==}
engines: {node: '>=20.9.0'}
cpu: [s390x]
os: [linux]
libc: [glibc]
'@img/sharp-linux-x64@0.35.5':
resolution: {integrity: sha512-SxFtLTeJInhAA9Q836kux2vZNeOBQEx658qvbboZScr0wIARym3IcGmW7KpVD5sbVg0Ojy+udFQdayYIZyoNog==}
engines: {node: '>=20.9.0'}
cpu: [x64]
os: [linux]
libc: [glibc]
'@img/sharp-linuxmusl-arm64@0.35.5':
resolution: {integrity: sha512-9HbMclmI1zlNkFRs3z9/eBtDjfD0sGlrX1z6b1qwmiFY5ElDLh4BC0LPBdVp7z1DXFiKlIcznf+ZlsuZzLxQqg==}
engines: {node: '>=20.9.0'}
cpu: [arm64]
os: [linux]
libc: [musl]
'@img/sharp-linuxmusl-x64@0.35.5':
resolution: {integrity: sha512-4KOphqB035HrVdqLZfCgMzzERrQkkzOwRhl4OAkRO1YCldbaFjySXMaK534Mo0V+LndnlJk+sbUyLeU0ULyD1A==}
engines: {node: '>=20.9.0'}
cpu: [x64]
os: [linux]
libc: [musl]
'@img/sharp-wasm32@0.35.5':
resolution: {integrity: sha512-Ptsga1su4tQx+LLF1ECS9U6nz5kmrXKo6XVbtR48Ke3ZRxxgaWBu7IDtEe1quo8hiupwm6WFqxVlXaSf7IINGQ==}
engines: {node: '>=20.9.0'}
'@img/sharp-webcontainers-wasm32@0.35.5':
resolution: {integrity: sha512-hfhF/FmoQyTUkA0bIKFOtw536BQSeBMe6BF6QyWlrPxT754+TFLaZ7sKKTfvvM0yJgKgaYTwnFCIZ/GuDw5SUA==}
engines: {node: '>=20.9.0'}
cpu: [wasm32]
'@img/sharp-win32-arm64@0.35.5':
resolution: {integrity: sha512-X4t7g+7ZA5DKblCBEXGjUqqemj4vczING/5viFwAL8h4N3qYeyjwdCvRLHi4EdOUI+2Z7UFlp1VM+p/AuEtm6Q==}
engines: {node: '>=20.9.0'}
cpu: [arm64]
os: [win32]
'@img/sharp-win32-ia32@0.35.5':
resolution: {integrity: sha512-5Zm82LoBc43nhwNybZlG7Y1KO//Zhsn306fQl29ZOuStHLGTo3BWL83q3cznX0poxSAMuYL1On/BHBxkBeKr6A==}
engines: {node: ^20.9.0}
cpu: [ia32]
os: [win32]
'@img/sharp-win32-x64@0.35.5':
resolution: {integrity: sha512-x76eH0vEiHlcMQu8Y8IenntaACtddpT6W0wmXtWrnKcnKI7ME5DdgqhAD6SEWOEl1v2zDvkZDhFA9KnURwpfqg==}
engines: {node: '>=20.9.0'}
cpu: [x64]
os: [win32]
'@intlify/bundle-utils@11.2.4': '@intlify/bundle-utils@11.2.4':
resolution: {integrity: sha512-eE18yR9eM9k5n8snCkHIYp2MuVTxa19aF8z9OMyxXWv0frz2HlBZDGIPFjA38pP3OJ1IlRBXC/dW5GILeLMSCQ==} resolution: {integrity: sha512-eE18yR9eM9k5n8snCkHIYp2MuVTxa19aF8z9OMyxXWv0frz2HlBZDGIPFjA38pP3OJ1IlRBXC/dW5GILeLMSCQ==}
engines: {node: '>= 22.13'} engines: {node: '>= 22.13'}
@ -3678,6 +3846,11 @@ packages:
engines: {node: '>=10'} engines: {node: '>=10'}
hasBin: true hasBin: true
semver@7.8.5:
resolution: {integrity: sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==}
engines: {node: '>=10'}
hasBin: true
set-function-length@1.2.2: set-function-length@1.2.2:
resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
@ -3694,6 +3867,15 @@ packages:
resolution: {integrity: sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==} resolution: {integrity: sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
sharp@0.35.5:
resolution: {integrity: sha512-Ywn4OnzGukp7CDMrp08RQ50YKmuwG47brZgIVPTvBaaAfQlRlygrRqSrxdCiL9M+LlzLBiJ68IR1QqvzHyjC7g==}
engines: {node: '>=20.9.0'}
peerDependencies:
'@types/node': '*'
peerDependenciesMeta:
'@types/node':
optional: true
shebang-command@2.0.0: shebang-command@2.0.0:
resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
engines: {node: '>=8'} engines: {node: '>=8'}
@ -5033,6 +5215,11 @@ snapshots:
tslib: 2.8.1 tslib: 2.8.1
optional: true optional: true
'@emnapi/runtime@1.11.3':
dependencies:
tslib: 2.8.1
optional: true
'@emnapi/wasi-threads@1.2.1': '@emnapi/wasi-threads@1.2.1':
dependencies: dependencies:
tslib: 2.8.1 tslib: 2.8.1
@ -5191,6 +5378,112 @@ snapshots:
'@iconify/types': 2.0.0 '@iconify/types': 2.0.0
vue: 3.5.38(typescript@6.0.3) vue: 3.5.38(typescript@6.0.3)
'@img/colour@1.1.0': {}
'@img/sharp-darwin-arm64@0.35.5':
optionalDependencies:
'@img/sharp-libvips-darwin-arm64': 1.3.4
optional: true
'@img/sharp-darwin-x64@0.35.5':
optionalDependencies:
'@img/sharp-libvips-darwin-x64': 1.3.4
optional: true
'@img/sharp-freebsd-wasm32@0.35.5':
dependencies:
'@img/sharp-wasm32': 0.35.5
optional: true
'@img/sharp-libvips-darwin-arm64@1.3.4':
optional: true
'@img/sharp-libvips-darwin-x64@1.3.4':
optional: true
'@img/sharp-libvips-linux-arm64@1.3.4':
optional: true
'@img/sharp-libvips-linux-arm@1.3.4':
optional: true
'@img/sharp-libvips-linux-ppc64@1.3.4':
optional: true
'@img/sharp-libvips-linux-riscv64@1.3.4':
optional: true
'@img/sharp-libvips-linux-s390x@1.3.4':
optional: true
'@img/sharp-libvips-linux-x64@1.3.4':
optional: true
'@img/sharp-libvips-linuxmusl-arm64@1.3.4':
optional: true
'@img/sharp-libvips-linuxmusl-x64@1.3.4':
optional: true
'@img/sharp-linux-arm64@0.35.5':
optionalDependencies:
'@img/sharp-libvips-linux-arm64': 1.3.4
optional: true
'@img/sharp-linux-arm@0.35.5':
optionalDependencies:
'@img/sharp-libvips-linux-arm': 1.3.4
optional: true
'@img/sharp-linux-ppc64@0.35.5':
optionalDependencies:
'@img/sharp-libvips-linux-ppc64': 1.3.4
optional: true
'@img/sharp-linux-riscv64@0.35.5':
optionalDependencies:
'@img/sharp-libvips-linux-riscv64': 1.3.4
optional: true
'@img/sharp-linux-s390x@0.35.5':
optionalDependencies:
'@img/sharp-libvips-linux-s390x': 1.3.4
optional: true
'@img/sharp-linux-x64@0.35.5':
optionalDependencies:
'@img/sharp-libvips-linux-x64': 1.3.4
optional: true
'@img/sharp-linuxmusl-arm64@0.35.5':
optionalDependencies:
'@img/sharp-libvips-linuxmusl-arm64': 1.3.4
optional: true
'@img/sharp-linuxmusl-x64@0.35.5':
optionalDependencies:
'@img/sharp-libvips-linuxmusl-x64': 1.3.4
optional: true
'@img/sharp-wasm32@0.35.5':
dependencies:
'@emnapi/runtime': 1.11.3
optional: true
'@img/sharp-webcontainers-wasm32@0.35.5':
dependencies:
'@img/sharp-wasm32': 0.35.5
optional: true
'@img/sharp-win32-arm64@0.35.5':
optional: true
'@img/sharp-win32-ia32@0.35.5':
optional: true
'@img/sharp-win32-x64@0.35.5':
optional: true
'@intlify/bundle-utils@11.2.4(vue-i18n@11.4.6(vue@3.5.38(typescript@6.0.3)))': '@intlify/bundle-utils@11.2.4(vue-i18n@11.4.6(vue@3.5.38(typescript@6.0.3)))':
dependencies: dependencies:
'@intlify/message-compiler': 11.4.6 '@intlify/message-compiler': 11.4.6
@ -7914,6 +8207,8 @@ snapshots:
semver@7.7.4: {} semver@7.7.4: {}
semver@7.8.5: {}
set-function-length@1.2.2: set-function-length@1.2.2:
dependencies: dependencies:
define-data-property: 1.1.4 define-data-property: 1.1.4
@ -7943,6 +8238,39 @@ snapshots:
is-plain-object: 2.0.4 is-plain-object: 2.0.4
split-string: 3.1.0 split-string: 3.1.0
sharp@0.35.5(@types/node@24.12.2):
dependencies:
'@img/colour': 1.1.0
detect-libc: 2.1.2
semver: 7.8.5
optionalDependencies:
'@img/sharp-darwin-arm64': 0.35.5
'@img/sharp-darwin-x64': 0.35.5
'@img/sharp-freebsd-wasm32': 0.35.5
'@img/sharp-libvips-darwin-arm64': 1.3.4
'@img/sharp-libvips-darwin-x64': 1.3.4
'@img/sharp-libvips-linux-arm': 1.3.4
'@img/sharp-libvips-linux-arm64': 1.3.4
'@img/sharp-libvips-linux-ppc64': 1.3.4
'@img/sharp-libvips-linux-riscv64': 1.3.4
'@img/sharp-libvips-linux-s390x': 1.3.4
'@img/sharp-libvips-linux-x64': 1.3.4
'@img/sharp-libvips-linuxmusl-arm64': 1.3.4
'@img/sharp-libvips-linuxmusl-x64': 1.3.4
'@img/sharp-linux-arm': 0.35.5
'@img/sharp-linux-arm64': 0.35.5
'@img/sharp-linux-ppc64': 0.35.5
'@img/sharp-linux-riscv64': 0.35.5
'@img/sharp-linux-s390x': 0.35.5
'@img/sharp-linux-x64': 0.35.5
'@img/sharp-linuxmusl-arm64': 0.35.5
'@img/sharp-linuxmusl-x64': 0.35.5
'@img/sharp-webcontainers-wasm32': 0.35.5
'@img/sharp-win32-arm64': 0.35.5
'@img/sharp-win32-ia32': 0.35.5
'@img/sharp-win32-x64': 0.35.5
'@types/node': 24.12.2
shebang-command@2.0.0: shebang-command@2.0.0:
dependencies: dependencies:
shebang-regex: 3.0.0 shebang-regex: 3.0.0
@ -8447,11 +8775,13 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- rollup - rollup
vite-plugin-image-optimizer@2.0.3(vite@8.0.16(@types/node@24.12.2)(jiti@2.6.1)(sass@1.101.0)(terser@5.48.0)(yaml@2.8.4)): vite-plugin-image-optimizer@2.0.3(sharp@0.35.5(@types/node@24.12.2))(vite@8.0.16(@types/node@24.12.2)(jiti@2.6.1)(sass@1.101.0)(terser@5.48.0)(yaml@2.8.4)):
dependencies: dependencies:
ansi-colors: 4.1.3 ansi-colors: 4.1.3
pathe: 2.0.3 pathe: 2.0.3
vite: 8.0.16(@types/node@24.12.2)(jiti@2.6.1)(sass@1.101.0)(terser@5.48.0)(yaml@2.8.4) vite: 8.0.16(@types/node@24.12.2)(jiti@2.6.1)(sass@1.101.0)(terser@5.48.0)(yaml@2.8.4)
optionalDependencies:
sharp: 0.35.5(@types/node@24.12.2)
vite-plugin-inspect@11.3.3(supports-color@3.2.3)(vite@8.0.16(@types/node@24.12.2)(jiti@2.6.1)(sass@1.101.0)(terser@5.48.0)(yaml@2.8.4)): vite-plugin-inspect@11.3.3(supports-color@3.2.3)(vite@8.0.16(@types/node@24.12.2)(jiti@2.6.1)(sass@1.101.0)(terser@5.48.0)(yaml@2.8.4)):
dependencies: dependencies:

BIN
src/assets/images/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 KiB

View File

@ -26,7 +26,8 @@ withDefaults(
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
padding: 12px 16px; padding: 6px 16px;
line-height: 1.4;
font-size: var(--wm-font-size-xs); font-size: var(--wm-font-size-xs);
color: var(--wm-color-text-secondary); color: var(--wm-color-text-secondary);
background: var(--wm-bg-color-base); background: var(--wm-bg-color-base);

View File

@ -1,8 +1,13 @@
<template> <template>
<header class="ty-header" :class="{ 'is-fixed': fixed }"> <header class="ty-header" :class="{ 'is-fixed': fixed }">
<div class="ty-header__left"> <div class="ty-header__left">
<div class="ty-header__logo"> <div
<span class="ty-header__title">{{ title }}</span> class="ty-header__logo"
:class="{ 'is-icon': !showTitle }"
:style="logoWidth != null ? { width: `${logoWidth}px` } : undefined"
>
<img v-if="logo" class="ty-header__logo-img" :src="logo" alt="logo" />
<span v-if="showTitle" class="ty-header__title">{{ title }}</span>
</div> </div>
<button v-if="hasSidebar" class="ty-header__action" type="button" title="折叠/展开菜单" @click="emit('toggle-collapse')"> <button v-if="hasSidebar" class="ty-header__action" type="button" title="折叠/展开菜单" @click="emit('toggle-collapse')">
@ -74,6 +79,12 @@ withDefaults(
defineProps<{ defineProps<{
/** 应用标题。 */ /** 应用标题。 */
title?: string title?: string
/** Logo 图片地址。 */
logo?: string
/** 是否显示标题文字(侧栏折叠或纯图标时仅显 Logo)。 */
showTitle?: boolean
/** Logo 区宽度(px,与左侧菜单/菜单+MixBar 对齐);null 表示自适应。 */
logoWidth?: number | null
/** 是否有侧边栏(决定是否显示折叠按钮)。 */ /** 是否有侧边栏(决定是否显示折叠按钮)。 */
hasSidebar?: boolean hasSidebar?: boolean
/** 侧边栏是否折叠。 */ /** 侧边栏是否折叠。 */
@ -101,6 +112,9 @@ withDefaults(
}>(), }>(),
{ {
title: 'sysmgr', title: 'sysmgr',
logo: '',
showTitle: true,
logoWidth: null,
hasSidebar: true, hasSidebar: true,
collapsed: false, collapsed: false,
fixed: true, fixed: true,
@ -139,7 +153,7 @@ function onUserCommand(command: string): void {
display: flex; display: flex;
align-items: center; align-items: center;
height: var(--ty-header-height, 56px); height: var(--ty-header-height, 56px);
padding: 0 12px; padding: 0 12px 0 0;
background: var(--wm-bg-color-base); background: var(--wm-bg-color-base);
border-bottom: 1px solid var(--wm-border-color-light); border-bottom: 1px solid var(--wm-border-color-light);
z-index: 100; z-index: 100;
@ -158,6 +172,20 @@ function onUserCommand(command: string): void {
&__logo { &__logo {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 8px;
flex-shrink: 0;
overflow: hidden;
&.is-icon {
justify-content: center;
gap: 0;
}
}
&__logo-img {
width: 32px;
height: 32px;
flex-shrink: 0;
} }
&__title { &__title {

View File

@ -12,7 +12,7 @@
<div class="ty-setting-panel__section"> <div class="ty-setting-panel__section">
<div class="ty-setting-panel__row"> <div class="ty-setting-panel__row">
<span>MixBar</span> <span>MixBar</span>
<el-switch v-model="local.mixbar" @change="emitUpdate" /> <el-switch v-model="local.mixbar" :disabled="local.layout !== 'sidebar'" @change="emitUpdate" />
</div> </div>
<div class="ty-setting-panel__row"> <div class="ty-setting-panel__row">
<span>暗黑模式</span> <span>暗黑模式</span>

View File

@ -2,6 +2,9 @@
<div class="app-shell" :style="cssVars"> <div class="app-shell" :style="cssVars">
<ty-header <ty-header
:title="title" :title="title"
:logo="logo"
:show-title="showTitle"
:logo-width="logoWidth"
:has-sidebar="app.hasSidebar" :has-sidebar="app.hasSidebar"
:collapsed="app.sidebarCollapsed" :collapsed="app.sidebarCollapsed"
:fixed="app.headerFixed" :fixed="app.headerFixed"
@ -66,6 +69,7 @@ import { useAppStore } from '@/stores/modules/app'
import { useTabsStore } from '@/stores/modules/tabs' import { useTabsStore } from '@/stores/modules/tabs'
import { useAuthStore } from '@/stores/modules/auth' import { useAuthStore } from '@/stores/modules/auth'
import { placeholderMenus } from '@/config/menu' import { placeholderMenus } from '@/config/menu'
import logo from '@/assets/images/logo.png'
import type { LayoutSettings } from '@/config/layout' import type { LayoutSettings } from '@/config/layout'
import type { ResourceNode } from '@/types/resource' import type { ResourceNode } from '@/types/resource'
import type { BreadcrumbItem } from '@/components/ty-breadcrumb.vue' import type { BreadcrumbItem } from '@/components/ty-breadcrumb.vue'
@ -111,6 +115,17 @@ const breadcrumbs = computed<BreadcrumbItem[]>(() => {
return [{ title: top.name }] return [{ title: top.name }]
}) })
/** Logo 区宽度:与左侧菜单(或 MixBar+菜单)对齐;top 布局自适应。 */
const logoWidth = computed<number | null>(() => {
if (!app.hasSidebar) return null
const mix = app.hasMixbar ? 64 : 0
const side = app.sidebarCollapsed ? 64 : app.sidebarWidth
return mix + side
})
/** 侧栏折叠时仅显 Logo,展开时显 Logo + 标题。 */
const showTitle = computed(() => !app.hasSidebar || !app.sidebarCollapsed)
/** 侧边栏 sticky 定位(顶栏固定时往下让出顶栏高度)。 */ /** 侧边栏 sticky 定位(顶栏固定时往下让出顶栏高度)。 */
const cssVars = computed(() => ({ const cssVars = computed(() => ({
'--ty-header-height': `${HEADER_HEIGHT}px`, '--ty-header-height': `${HEADER_HEIGHT}px`,

View File

@ -25,8 +25,8 @@ export const useAppStore = defineStore(
/** 是否渲染侧边栏:horizontal / sidebar 有,top 无。 */ /** 是否渲染侧边栏:horizontal / sidebar 有,top 无。 */
const hasSidebar = computed(() => layout.value !== 'top') const hasSidebar = computed(() => layout.value !== 'top')
/** 是否渲染 MixBar。 */ /** 是否渲染 MixBar:仅左右(sidebar)布局可用。 */
const hasMixbar = computed(() => mixbar.value && hasSidebar.value) const hasMixbar = computed(() => mixbar.value && layout.value === 'sidebar')
return { return {
layout, layout,

File diff suppressed because one or more lines are too long