WindowNumSelect.vue 4.43 KB
<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>