WindowNumSelect.vue
4.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
<template>
<el-select
v-model="selected"
placeholder="分屏模式"
size="mini"
style="width: 130px; margin-right: 10px;"
@change="handleChange"
>
<!-- 自定义下拉选项的模板 -->
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value"
class="layout-option"
>
<!-- 左侧文字 -->
<span class="option-label">{{ item.label }}</span>
<!-- 右侧图标 (纯CSS Grid绘制,所见即所得) -->
<div class="layout-icon" :style="getIconContainerStyle(item.value)">
<!-- 根据布局数量生成对应的小方块 -->
<div
v-for="(block, i) in getIconBlocks(item.value)"
:key="i"
class="icon-block"
:style="block.style"
></div>
</div>
</el-option>
</el-select>
</template>
<script>
export default {
name: "WindowNumSelect",
props: {
// 接收父组件 v-model 传来的值
value: {
type: String,
default: '4'
}
},
data() {
return {
selected: this.value,
// 定义所有支持的分屏模式
options: [
{ value: '1', label: '单屏' },
{ value: '4', label: '四分屏' },
{ value: '9', label: '九分屏' },
{ value: '16', label: '十六分屏' },
{ value: '25', label: '二十五分屏' }, // 新增
{ value: '36', label: '三十六分屏' }, // 新增
{ value: '1+5', label: '1+5模式' },
{ value: '1+7', label: '1+7模式' },
{ value: '1+9', label: '1+9模式' }, // 新增
{ value: '1+11', label: '1+11模式' } // 新增
]
};
},
watch: {
value(val) {
this.selected = val;
}
},
methods: {
handleChange(val) {
this.$emit('input', val); // 触发 v-model 更新
this.$emit('change', val);
},
/**
* 生成图标容器的 Grid 样式
*/
getIconContainerStyle(mode) {
const grids = {
'1': { rows: 1, cols: 1 },
'4': { rows: 2, cols: 2 },
'9': { rows: 3, cols: 3 },
'16': { rows: 4, cols: 4 },
'25': { rows: 5, cols: 5 }, // 新增 5x5
'36': { rows: 6, cols: 6 }, // 新增 6x6
'1+5': { rows: 3, cols: 3 },
'1+7': { rows: 4, cols: 4 },
'1+9': { rows: 5, cols: 5 }, // 新增
'1+11': { rows: 6, cols: 6 } // 新增
};
const config = grids[mode] || grids['4'];
return {
display: 'grid',
gridTemplateColumns: `repeat(${config.cols}, 1fr)`,
gridTemplateRows: `repeat(${config.rows}, 1fr)`
};
},
/**
* 生成图标内部的小方块样式
*/
getIconBlocks(mode) {
// 1. 标准均匀网格
if (['1', '4', '9', '16', '25', '36'].includes(mode)) {
return Array(Number(mode)).fill({ style: {} });
}
// 2. 异形网格配置
const irregularConfig = {
'1+5': { total: 5, span: 2 },
'1+7': { total: 7, span: 3 },
'1+9': { total: 9, span: 4 }, // 5x5网格,主图占4x4
'1+11': { total: 11, span: 5 } // 6x6网格,主图占5x5
};
if (irregularConfig[mode]) {
const { total, span } = irregularConfig[mode];
const blocks = [];
// 添加大块
blocks.push({
style: {
gridColumn: `span ${span}`,
gridRow: `span ${span}`,
backgroundColor: '#409EFF'
}
});
// 添加剩余小块
for(let i = 0; i < total; i++) blocks.push({ style: {} });
return blocks;
}
return [];
}
}
};
</script>
<style scoped>
.layout-option {
display: flex;
align-items: center;
justify-content: space-between;
padding-right: 10px; /* 给图标留点空间 */
}
.option-label {
font-size: 13px;
color: #333;
}
/* 图标容器 */
.layout-icon {
width: 20px;
height: 20px;
gap: 1px; /* 网格间距 */
background-color: transparent;
pointer-events: none; /* 纯展示 */
}
/* 图标内部的小方块 */
.icon-block {
background-color: #909399; /* 默认灰色 */
border-radius: 1px;
}
/* 选中状态下,让图标变色 (Element UI 的选中类名是 selected) */
.layout-option.selected .option-label {
color: #409EFF;
font-weight: bold;
}
.layout-option.selected .icon-block {
background-color: #409EFF; /* 选中变蓝 */
}
/* 悬停时的颜色变化 */
.layout-option:hover .icon-block {
background-color: #66b1ff;
}
</style>