vue3 el-cascader 实现 一级单选 ,二级多选,只能选择三个

实现效果如下
image

思路是
1.选择一个时,取出一级选中值code,首先把一级中code不是选中code的置灰,实现一级单选
2.当选择二级时,选中数组长度大于等于三,则把当前二级数据(不是选中的)置灰,其他不置灰

代码如下

<template>
  <div class="productCategory">
    <el-cascader
      v-model="selectedList"
      :options="options"
      :props="props"
      collapse-tags
      collapse-tags-tooltip
      clearable
      @change="change"
      :teleported="false"
    />
  </div>
</template>
<script lang="ts" setup>
import type { CascaderProps } from "element-plus";
import { onMounted, ref } from "vue";
import { categoryQueryAPI } from "@/api/material";
import { splitArray } from "@/utils/index";
import { isEmpty } from "@/utils/types";
//选中值 二维数组
const selectedList = ref([]);
//数据源
const options = ref([]);
//配置
const props: CascaderProps = {
  multiple: true,
  value: "code",
  label: "title",
  children: "subList",
  leaf: "leaf"
};

onMounted(() => {
  getCategoryAllList();
});

//这里是后端返回的树形结果是三级,我根据实际业务去掉了最后一级
const removeTreeDataWithLevel = (data, limited = 1) =>
  data.map(({ subList, ...rest }) => ({
    ...rest,
    ...(limited === 2
      ? {}
      : { subList: removeTreeDataWithLevel(subList, limited + 1) })
  }));

const change = (val: any) => {
  const newList = val.flat(Infinity);
  const selectedList = splitArray(newList, 2);
  const selectedLeve0Index = newList.length > 0 ? newList[0] : "";
  setDisabled(selectedLeve0Index, selectedList);
};

const setDisabled = (selectedLeve0Index: string, selectedList: any) => {
  let leve2 = selectedList.map((item: any) => {
    return item[1];
  });
  options.value.forEach((item) => {
    item.disabled = false;
    if (!isEmpty(selectedLeve0Index)) {
      if (item.code !== selectedLeve0Index) {
        item.disabled = true;
      }
      if (item.code == selectedLeve0Index) {
        item.subList.forEach((sitem) => {
          sitem.disabled =
            selectedList.length >= 3 && !leve2.includes(sitem.code)
              ? true
              : false;
        });
      }
    }
  });
};

const getCategoryAllList = async () => {
  const res = await categoryQueryAPI({ module: 1 });
  if (res) {
    options.value = removeTreeDataWithLevel(res.data);
  }
};
</script>
<style lang="less">
.productCategory {
  .el-cascader-panel {
    .el-scrollbar:first-child {
      .el-checkbox {
        display: none;
      }
    }
  }
}

.productCategory {
  .el-cascader {
    width: 100% !important;
  }
}
</style>

辅助代码如下

/**
 * 数组的数据格式转换拆分-----一维转二维
 * @param {Object} arr 源数组
 * @param {Object} len 二维中一维的长度
 */
export function  splitArray(arr, len) {
  let arrLen = arr.length;
  let result = [];
  for (let i = 0; i < arrLen; i += len) {
    result.push(arr.slice(i, i + len));
  }
  return result;
}

/**
 * 数据非空验证
 * @desc 验证数据是否为 null undefined [] {} ''
 * @param data
 * @return {boolean}
 */
export function isEmpty(data) {
  if (data === null) return true
  if (data === undefined) return true
  if (Object.prototype.toString.call(data) === '[object Array]') return data.length === 0
  if (Object.prototype.toString.call(data) === '[object Object]') return Object.keys(data).length === 0
  if (typeof data === 'string') return data.trim() === ''
  return false
}
posted @ 2023-01-31 15:50  火龙果呀  阅读(5269)  评论(0)    收藏  举报