refactor: ♻️ 布局选择组件代码优化
This commit is contained in:
@@ -1,35 +1,20 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex flex-wrap justify-around w-full h-12">
|
<div class="layout-select">
|
||||||
<el-tooltip content="左侧模式" placement="bottom">
|
<el-tooltip
|
||||||
<div
|
v-for="item in layoutOptions"
|
||||||
class="layout-item left"
|
:key="item.value"
|
||||||
:class="{ 'is-active': modelValue === LayoutEnum.LEFT }"
|
:content="item.label"
|
||||||
@click="handleLayoutChange(LayoutEnum.LEFT)"
|
placement="bottom"
|
||||||
>
|
>
|
||||||
<div />
|
|
||||||
<div />
|
|
||||||
</div>
|
|
||||||
</el-tooltip>
|
|
||||||
|
|
||||||
<el-tooltip content="顶部模式" placement="bottom">
|
|
||||||
<div
|
<div
|
||||||
class="layout-item top"
|
role="button"
|
||||||
:class="{ 'is-active': modelValue === LayoutEnum.TOP }"
|
tabindex="0"
|
||||||
@click="handleLayoutChange(LayoutEnum.TOP)"
|
:class="['layout-item', item.className, { 'is-active': modelValue === item.value }]"
|
||||||
|
@click="handleLayoutChange(item.value)"
|
||||||
|
@keydown.enter.space="handleLayoutChange(item.value)"
|
||||||
>
|
>
|
||||||
<div />
|
<div class="layout-item-part" />
|
||||||
<div />
|
<div class="layout-item-part" />
|
||||||
</div>
|
|
||||||
</el-tooltip>
|
|
||||||
|
|
||||||
<el-tooltip content="混合模式" placement="bottom">
|
|
||||||
<div
|
|
||||||
class="layout-item mix"
|
|
||||||
:class="{ 'is-active': modelValue === LayoutEnum.MIX }"
|
|
||||||
@click="handleLayoutChange(LayoutEnum.MIX)"
|
|
||||||
>
|
|
||||||
<div />
|
|
||||||
<div />
|
|
||||||
</div>
|
</div>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
</div>
|
</div>
|
||||||
@@ -38,76 +23,118 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { LayoutEnum } from "@/enums/LayoutEnum";
|
import { LayoutEnum } from "@/enums/LayoutEnum";
|
||||||
|
|
||||||
const modelValue = defineModel("modelValue", {
|
interface LayoutOption {
|
||||||
type: String,
|
value: LayoutEnum;
|
||||||
|
label: string;
|
||||||
|
className: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const layoutOptions: LayoutOption[] = [
|
||||||
|
{ value: LayoutEnum.LEFT, label: "左侧模式", className: "left" },
|
||||||
|
{ value: LayoutEnum.TOP, label: "顶部模式", className: "top" },
|
||||||
|
{ value: LayoutEnum.MIX, label: "混合模式", className: "mix" },
|
||||||
|
];
|
||||||
|
|
||||||
|
const modelValue = defineModel<LayoutEnum>("modelValue", {
|
||||||
required: true,
|
required: true,
|
||||||
default: () => "",
|
default: () => LayoutEnum.LEFT,
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
function handleLayoutChange(layout: LayoutEnum) {
|
||||||
* 变换布局
|
|
||||||
*
|
|
||||||
* @param layout
|
|
||||||
*/
|
|
||||||
function handleLayoutChange(layout: string) {
|
|
||||||
modelValue.value = layout;
|
modelValue.value = layout;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped lang="scss">
|
||||||
.layout-selector {
|
.layout-select {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
gap: 10px;
|
||||||
justify-content: space-around;
|
justify-content: space-evenly;
|
||||||
width: 100%;
|
padding: 10px 0;
|
||||||
height: 50px;
|
--layout-primary: #1b2a47;
|
||||||
|
--layout-background: #f0f2f5;
|
||||||
|
--layout-shadow: 0 0 8px rgba(0, 0, 0, 0.1);
|
||||||
|
--layout-hover: #e3f1f9;
|
||||||
}
|
}
|
||||||
|
|
||||||
.layout-item {
|
.layout-item {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 18%;
|
width: 18%;
|
||||||
height: 45px;
|
height: 50px;
|
||||||
overflow: hidden;
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
background: #f0f2f5;
|
background: var(--layout-background);
|
||||||
border-radius: 4px;
|
border-radius: 8px;
|
||||||
|
box-shadow: var(--layout-shadow);
|
||||||
|
|
||||||
&.mix div:nth-child(1),
|
transition:
|
||||||
&.top div:nth-child(1) {
|
transform 0.2s ease,
|
||||||
width: 100%;
|
border-color 0.2s ease,
|
||||||
height: 30%;
|
box-shadow 0.2s ease;
|
||||||
background: #1b2a47;
|
|
||||||
box-shadow: 0 0 1px #888;
|
&:hover {
|
||||||
|
background-color: var(--layout-hover);
|
||||||
|
transform: scale(1.02); /* 稍微放大,避免过于夸张 */
|
||||||
}
|
}
|
||||||
|
|
||||||
&.mix div:nth-child(2) {
|
&:focus-visible {
|
||||||
|
outline: 2px solid var(--el-color-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
&-part {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 0;
|
background: var(--layout-primary);
|
||||||
left: 0;
|
border-radius: 4px; /* 保持和父容器一致的圆角 */
|
||||||
width: 30%;
|
box-shadow: var(--layout-shadow);
|
||||||
height: 70%;
|
transition: all 0.3s ease;
|
||||||
background: #1b2a47;
|
|
||||||
box-shadow: 0 0 1px #888;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&.left div:nth-child(1) {
|
&.left {
|
||||||
|
.layout-item-part {
|
||||||
|
&:first-child {
|
||||||
width: 30%;
|
width: 30%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background: #1b2a47;
|
border-radius: 4px 0 0 4px; /* 左边部分圆角 */
|
||||||
}
|
}
|
||||||
|
&:last-child {
|
||||||
&.left div:nth-child(2) {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
top: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
width: 70%;
|
width: 70%;
|
||||||
height: 30%;
|
height: 30%;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
box-shadow: 0 0 1px #888;
|
border-radius: 0 4px 4px 0; /* 右边部分圆角 */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.top {
|
||||||
|
.layout-item-part:first-child {
|
||||||
|
width: 100%;
|
||||||
|
height: 30%;
|
||||||
|
border-radius: 4px 4px 0 0; /* 顶部部分圆角 */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.mix {
|
||||||
|
.layout-item-part {
|
||||||
|
&:first-child {
|
||||||
|
width: 100%;
|
||||||
|
height: 30%;
|
||||||
|
border-radius: 4px 4px 0 0; /* 顶部部分圆角 */
|
||||||
|
}
|
||||||
|
&:last-child {
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 30%;
|
||||||
|
height: 70%;
|
||||||
|
border-radius: 0 0 4px 4px; /* 底部部分圆角 */
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.layout-item.is-active {
|
.is-active {
|
||||||
|
background-color: var(--layout-hover);
|
||||||
border: 2px solid var(--el-color-primary);
|
border: 2px solid var(--el-color-primary);
|
||||||
|
transform: scale(1.05); /* 轻微放大 */
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user