feat: 可折叠布局

This commit is contained in:
WANGFan 2025-07-05 10:53:10 +08:00
parent cef8e8dd98
commit a893345f1e
5 changed files with 143 additions and 56 deletions

37
src/components.d.ts vendored
View File

@ -5,24 +5,25 @@
// Read more: https://github.com/vuejs/core/pull/3399 // Read more: https://github.com/vuejs/core/pull/3399
export {} export {}
declare module "vue" { declare module 'vue' {
export interface GlobalComponents { export interface GlobalComponents {
RouterLink: (typeof import("vue-router"))["RouterLink"]; RouterLink: typeof import('vue-router')['RouterLink']
RouterView: (typeof import("vue-router"))["RouterView"]; RouterView: typeof import('vue-router')['RouterView']
SBarcodeDraw: (typeof import("./components/s-barcode-draw/index.vue"))["default"]; SBarcodeDraw: typeof import('./components/s-barcode-draw/index.vue')['default']
SCodeView: (typeof import("./components/s-code-view/index.vue"))["default"]; SCodeView: typeof import('./components/s-code-view/index.vue')['default']
SelectIcon: (typeof import("./components/select-icon/index.vue"))["default"]; SelectIcon: (typeof import("./components/select-icon/index.vue"))["default"]
SExternalLinkPage: (typeof import("./components/s-external-link-page/index.vue"))["default"]; SExternalLinkPage: typeof import('./components/s-external-link-page/index.vue')['default']
SFullScreen: (typeof import("./components/s-full-screen/index.vue"))["default"]; SFoldPage: typeof import('./components/s-fold-page/index.vue')['default']
SInternalLinkPage: (typeof import("./components/s-internal-link-page/index.vue"))["default"]; SFullPage: typeof import('./components/s-full-page/index.vue')['default']
SLangProvider: (typeof import("./components/s-lang-provider/index.vue"))["default"]; SInternalLinkPage: typeof import('./components/s-internal-link-page/index.vue')['default']
SMainTransition: (typeof import("./components/s-main-transition/index.vue"))["default"]; SLangProvider: typeof import('./components/s-lang-provider/index.vue')['default']
SPinyinPro: (typeof import("./components/s-pinyin-pro/index.vue"))["default"]; SMainTransition: typeof import('./components/s-main-transition/index.vue')['default']
SQrcodeDraw: (typeof import("./components/s-qrcode-draw/index.vue"))["default"]; SPinyinPro: typeof import('./components/s-pinyin-pro/index.vue')['default']
SRecorderPcm: (typeof import("./components/s-recorder-pcm/index.vue"))["default"]; SQrcodeDraw: typeof import('./components/s-qrcode-draw/index.vue')['default']
SSelectIcon: (typeof import("./components/s-select-icon/index.vue"))["default"]; SRecorderPcm: typeof import('./components/s-recorder-pcm/index.vue')['default']
SSvgAndIcon: (typeof import("./components/s-svg-and-icon/index.vue"))["default"]; SSelectIcon: typeof import('./components/s-select-icon/index.vue')['default']
SSvgIcon: (typeof import("./components/s-svg-icon/index.vue"))["default"]; SSvgAndIcon: typeof import('./components/s-svg-and-icon/index.vue')['default']
SVerifyCode: (typeof import("./components/s-verify-code/index.vue"))["default"]; SSvgIcon: typeof import('./components/s-svg-icon/index.vue')['default']
SVerifyCode: typeof import('./components/s-verify-code/index.vue')['default']
} }
} }

View File

@ -0,0 +1,79 @@
<template>
<a-layout class="layout" id="s-fold-page">
<a-layout-sider ref="siderContent" class="layout-sider" :collapsed-width="12" :width="width" :collapsed="collapsed">
<div class="packup-btn" @click="collapsed = !collapsed">
<icon-left v-if="!collapsed" />
<icon-right v-else />
</div>
<div
v-show="!collapsed"
:style="{
padding: siderPadding
}"
>
<slot name="sider"> </slot>
</div>
</a-layout-sider>
<a-layout-content>
<div class="content">
<slot name="content"> </slot>
</div>
</a-layout-content>
</a-layout>
</template>
<script setup lang="ts">
const width = defineModel("width", {
type: Number,
default: 200
});
const collapsed = ref<boolean>(false);
const siderPadding = computed(() => (collapsed.value ? "0px" : "12px"));
</script>
<style lang="scss" scoped>
.layout {
box-sizing: border-box;
height: 100%;
overflow: hidden;
.layout-sider {
position: relative;
border-right: 1px solid $color-border-2;
.packup-btn {
position: absolute;
top: 50%;
right: calc(-24px / 2);
display: flex;
align-items: center;
justify-content: center;
width: 24px;
height: 24px;
color: $color-text-2;
background: $color-bg-white;
border-radius: 50%;
box-shadow:
inset 0 0 0 1px $color-border-2,
0 0 10px 0 rgb(0 0 0 / 5%);
box-shadow:
inset 0 0 0 1px $color-border-2,
0 0 10px 0 rgb(0 0 0 / 5%);
box-shadow:
inset 0 0 0 1px $color-border-2,
0 0 10px 0 rgb(0 0 0 / 5%);
transform: translateY(-50%);
transition: all 0.1s;
&:hover {
transform: translateY(-50%) scale(1.1);
}
}
}
.content {
box-sizing: border-box;
height: 100%;
padding: 12px;
}
}
:deep(.arco-layout-sider-light) {
box-shadow: unset;
}
</style>

View File

@ -0,0 +1,21 @@
<template>
<div class="container">
<s-fold-page>
<template #sider>
<div>左侧</div>
</template>
<template #content>
<div>右侧</div>
</template>
</s-fold-page>
</div>
</template>
<script setup lang="ts"></script>
<style lang="scss" scoped>
.container {
height: 100%;
border: 1px solid $color-border-2;
}
</style>

View File

@ -1,50 +1,36 @@
<template> <template>
<s-full-screen> <s-full-page>
<a-layout class="layout"> <s-fold-page v-model:width="siderWidth">
<a-layout-sider class="layout-sider" :collapsed-width="12" :collapsed="collapsed"> <template #sider>
<div class="packup-btn" @click="collapsed = !collapsed"> <a-menu :style="{ width: '100%', height: '100%' }" :selected-keys="[currentMenu]">
<icon-left v-if="!collapsed" /> <a-menu-item v-for="item in menuData" :key="item.id">{{ item.title }}</a-menu-item>
<icon-right v-else /> </a-menu>
</template>
<template #content>
<div class="content">
<FoldPage v-if="currentMenu == 1" />
</div> </div>
<div v-show="!collapsed">sider</div> </template>
</a-layout-sider> </s-fold-page>
<a-layout-content>Content</a-layout-content> </s-full-page>
</a-layout>
</s-full-screen>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
const collapsed = ref<boolean>(false); import FoldPage from "@/views/component/common-layouts/fold-page.vue";
interface MenuData {
id: number;
title: string;
}
const siderWidth = ref<number>(250);
const menuData = ref<MenuData[]>([{ id: 1, title: "可折叠布局" }]);
const currentMenu = ref<number>(1);
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.layout { .content {
height: 100%; height: 100%;
box-shadow: $shadow-border-1;
.layout-sider {
position: relative;
border-right: 1px solid cyan;
.packup-btn {
position: absolute;
top: 50%;
right: calc(-24px / 2);
display: flex;
align-items: center;
justify-content: center;
width: 24px;
height: 24px;
background: $color-bg-white;
border-radius: 50%;
box-shadow: inset 0 0 0 1px $color-border-2;
transform: translateY(-50%);
transition: all 0.1s;
&:hover {
transform: translateY(-50%) scale(1.1);
}
}
}
} }
:deep(.arco-layout-sider-light) { :deep(.arco-menu-vertical .arco-menu-inner) {
box-shadow: unset; padding: 0;
} }
</style> </style>