# ByCascaderPanel 级联面板选择器

基于 Element UI 的 el-cascader-panel 组件封装的级联面板选择器,支持单选/多选模式、搜索功能、聚合模式、禁用状态等功能。提供左右分栏的交互界面,左侧显示可选项目,右侧显示已选项。

# 基础用法

<template>
  <ByCascaderPanel v-model="selectedValues" :options="options" :panel-height="300" @change="handleChange" />
</template>

<script>
export default {
  data() {
    return {
      selectedValues: ['lisi', 'zhaoliu'],
      options: [
        {
          label: '技术部',
          value: 'tech',
          children: [
            {
              label: '前端组',
              value: 'frontend',
              children: [
                { label: '张三', value: 'zhangsan' },
                { label: '李四', value: 'lisi' },
                { label: '王五', value: 'wangwu' }
              ]
            },
            {
              label: '后端组',
              value: 'backend',
              children: [
                { label: '赵六', value: 'zhaoliu' },
                { label: '钱七', value: 'qianqi' }
              ]
            }
          ]
        },
        {
          label: '产品部',
          value: 'product',
          children: [
            {
              label: '产品组',
              value: 'product_group',
              children: [
                { label: '孙八', value: 'sunba' },
                { label: '周九', value: 'zhoujiu' }
              ]
            }
          ]
        }
      ]
    }
  },
  methods: {
    handleChange(data) {
      console.log('选择变化:', data)
    }
  }
}
</script>

# 单选模式

<template>
  <ByCascaderPanel
    v-model="selectedValue"
    :options="options"
    :cascader-props="singleProps"
    :panel-height="200"
    search-placeholder="请输入部门或人员名称"
    @change="handleChange"
  />
</template>

<script>
export default {
  data() {
    return {
      selectedValue: 'zhengchenggong', // 单选模式,使用单个值
      options: [
        {
          name: '明朝',
          id: 'ming_dynasty',
          children: [
            {
              name: '明朝·武将集团',
              id: 'ming_military_officials',
              children: [
                { name: '戚继光', id: 'qijiguang', status: 1 },
                { name: '郑成功', id: 'zhengchenggong', status: 1 }
              ]
            }
          ]
        }
      ],
      singleProps: {
        multiple: false,
        label: 'name',
        value: 'id',
        children: 'children'
      }
    }
  }
}
</script>

# 多选模式

<template>
  <ByCascaderPanel
    v-model="selectedValues"
    :options="options"
    :cascader-props="multipleProps"
    :panel-height="250"
    search-placeholder="请输入部门或人员名称"
    @change="handleChange"
  />
</template>

<script>
export default {
  data() {
    return {
      selectedValues: ['baijuyi', 'zhengchenggong'],
      multipleProps: {
        multiple: true,
        label: 'name',
        value: 'id',
        children: 'children'
      }
    }
  }
}
</script>

# 聚合模式

聚合模式:当父项的所有子项都被选中时,只返回父项ID,不包含子项。

<template>
  <ByCascaderPanel
    v-model="selectedValues"
    :options="options"
    :cascader-props="multipleProps"
    :aggregation-mode="true"
    :parent-node-prefix="'__parent__'"
    :panel-height="300"
    search-placeholder="请输入朝代或人物名称"
    @change="handleChange"
  />
</template>

<script>
export default {
  data() {
    return {
      selectedValues: ['baijuyi', 'zhengchenggong'],
      options: [
        {
          name: '唐朝',
          id: 'tang_dynasty',
          children: [
            {
              name: '唐朝·文官集团',
              id: 'tang_civil_officials',
              children: [
                { name: '李白', id: 'libai' },
                { name: '杜甫', id: 'dufu' },
                { name: '白居易', id: 'baijuyi' }
              ]
            }
          ]
        }
      ],
      multipleProps: {
        multiple: true,
        label: 'name',
        value: 'id',
        children: 'children'
      }
    }
  },
  methods: {
    handleChange(data) {
      console.log('聚合模式选择变化:', data)
      // 当选择"部门"下的所有子项时,聚合模式会只返回"部门"的ID,而不是所有子项ID
    }
  }
}
</script>

# 聚合模式说明

  • parentNodePrefix: 非叶子节点前缀标识,用于区分叶子节点和非叶子节点
  • 在聚合模式下,如果子项全部选中,会直接返回父项ID
  • 支持复杂的层级结构聚合,减少返回数据量

# parentNodePrefix 使用示例

<template>
  <ByCascaderPanel
    v-model="selectedValues"
    :options="options"
    :cascader-props="multipleProps"
    :aggregation-mode="true"
    :parent-node-prefix="'__parent__'"
    :panel-height="300"
    @change="handleChange"
  />
</template>

<script>
export default {
  data() {
    return {
      selectedValues: ['__parent__department1', 'employee1', 'employee2'],
      options: [
        {
          name: '技术部',
          id: 'department1', // 非叶子节点,在聚合模式下需要添加前缀
          children: [
            { name: '张三', id: 'employee1' },
            { name: '李四', id: 'employee2' }
          ]
        }
      ],
      multipleProps: {
        multiple: true,
        label: 'name',
        value: 'id',
        children: 'children'
      }
    }
  },
  methods: {
    handleChange(data) {
      console.log('聚合模式选择变化:', data)
      // 当选择技术部下的所有员工时,会返回 '__parent__department1'
      // 当只选择部分员工时,会返回具体的员工ID数组
    }
  }
}
</script>

# 禁用状态配置

<template>
  <ByCascaderPanel
    v-model="selectedValues"
    :options="options"
    disabled-field="status"
    :disabled-value="0"
    :panel-height="300"
    @change="handleChange"
  />
</template>

<script>
export default {
  data() {
    return {
      selectedValues: [],
      options: [
        {
          name: '唐朝',
          id: 'tang_dynasty',
          children: [
            {
              name: '唐朝·文官集团',
              id: 'civil_officials',
              children: [
                { name: '李白', id: 'libai', status: 1 }, // 启用
                { name: '杜甫', id: 'dufu', status: 0 }, // 禁用
                { name: '白居易', id: 'baijuyi', status: 1 } // 启用
              ]
            }
          ]
        }
      ]
    }
  }
}
</script>

# 自定义禁用判断函数

<template>
  <ByCascaderPanel
    v-model="selectedValues"
    :options="options"
    :disabled-check="customDisabledCheck"
    :panel-height="300"
    @change="handleChange"
  />
</template>

<script>
export default {
  data() {
    return {
      selectedValues: [],
      options: [
        {
          name: '技术部',
          id: 'tech',
          children: [
            {
              name: '前端组',
              id: 'frontend',
              children: [
                { name: '张三', id: 'zhangsan', role: 'admin' },
                { name: '李四', id: 'lisi', role: 'user' },
                { name: '王五', id: 'wangwu', role: 'guest' }
              ]
            }
          ]
        }
      ]
    }
  },
  methods: {
    customDisabledCheck(item) {
      // 自定义禁用逻辑:只有 role 为 'user' 的项才能选择
      return item.role !== 'user'
    }
  }
}
</script>

# 方法调用示例

<template>
  <div>
    <div class="button-group">
      <el-button @click="clearSelection">清空选择</el-button>
      <el-button @click="setDefaultSelection">设置默认选择</el-button>
      <el-button @click="getSelectedData">获取选择数据</el-button>
    </div>
    <ByCascaderPanel ref="cascaderPanel" v-model="selectedValues" :options="options" @change="handleChange" />
  </div>
</template>

<script>
export default {
  data() {
    return {
      selectedValues: [],
      options: [
        // ... 选项数据
      ]
    }
  },
  methods: {
    clearSelection() {
      this.$refs.cascaderPanel.clearSelection()
    },

    setDefaultSelection() {
      this.$refs.cascaderPanel.setValue([
        ['tech', 'frontend', 'zhangsan'],
        ['product', 'product_group', 'sunba']
      ])
    },

    getSelectedData() {
      const data = this.$refs.cascaderPanel.getSelectedData()
      this.$message.success(`已选择 ${data.count}`)
      console.log('选择数据:', data)
    }
  }
}
</script>

# API

# Props

参数 说明 类型 默认值
value / v-model 已选值 Array / Number / String []
options 级联数据源 Array []
cascaderProps 级联面板配置 Object { multiple: true, label: 'label', value: 'value', children: 'children' }
panelHeight 面板高度(px) Number / String 300
searchPlaceholder 搜索占位符 String '请输入名称搜索'
disabledField 禁用字段名(只针对叶子节点) String 'disabled'
disabledValue 禁用值(只针对叶子节点) String / Number / Boolean true
disabledCheck 自定义禁用判断函数 Function null
showSelectAll 是否显示全选按钮 Boolean true
aggregationMode 是否聚合模式 Boolean false
parentNodePrefix 非叶子节点前缀标识(聚合模式下用于标识非叶子节点) String 'parent'

# cascaderProps 配置

参数 说明 类型 默认值
multiple 是否多选 Boolean true
label 指定选项的标签为选项对象的某个属性值 String 'label'
value 指定选项的值为选项对象的某个属性值 String 'value'
children 指定选项的子选项为选项对象的某个属性值 String 'children'

# Events

事件名 说明 参数
change 选择变化时触发 data: { valuesPath: Array, values: Array/String, items: Array, count: Number }
input v-model 绑定值变化时触发 value: Array/String

# Methods

方法名 说明 参数
setValue 设置选择值 values: Array/String
clearSelection 清空选择 -
getSelectedData 获取选中的数据 -

# getSelectedData 返回值

参数 说明 类型
valuesPath 路径数组(聚合模式下已聚合) Array
values 外部value(单选时返回单个值,多选时返回数组) Array/String
items 已选项列表 Array
count 已选项数量 Number

# 数据格式

# 基础数据格式

const options = [
  {
    label: '技术部', // 显示文本
    value: 'tech', // 选项值
    disabled: false, // 是否禁用(可选)
    children: [
      // 子选项
      {
        label: '前端组',
        value: 'frontend',
        children: [
          { label: '张三', value: 'zhangsan' },
          { label: '李四', value: 'lisi' }
        ]
      }
    ]
  }
]

# 自定义字段数据格式

const options = [
  {
    name: '技术部', // 自定义显示字段
    id: 'tech', // 自定义值字段
    status: 1, // 自定义禁用字段
    children: [
      {
        name: '前端组',
        id: 'frontend',
        status: 1,
        children: [
          { name: '张三', id: 'zhangsan', status: 1 },
          { name: '李四', id: 'lisi', status: 0 } // status为0表示禁用
        ]
      }
    ]
  }
]

# 聚合模式数据格式

在聚合模式下,非叶子节点需要添加前缀标识以避免ID冲突:

const options = [
  {
    name: '技术部',
    id: 'tech', // 非叶子节点,在聚合模式下需要添加前缀
    children: [
      {
        name: '前端组',
        id: 'frontend', // 非叶子节点,在聚合模式下需要添加前缀
        children: [
          { name: '张三', id: 'zhangsan' }, // 叶子节点,不需要前缀
          { name: '李四', id: 'lisi' } // 叶子节点,不需要前缀
        ]
      }
    ]
  }
]

// 在聚合模式下,选择值可能包含前缀:
const selectedValues = [
  '__parent__tech', // 表示选择了整个技术部
  '__parent__frontend', // 表示选择了整个前端组
  'zhangsan', // 表示只选择了张三
  'lisi' // 表示只选择了李四
]

# 功能特性

# 1. 搜索功能

  • 支持按名称搜索,实时过滤选项
  • 搜索结果会展开所有匹配的路径
  • 搜索模式下支持选择操作
  • 搜索无结果时显示空状态

# 2. 全选功能

  • 多选模式下支持全选/取消全选
  • 聚合模式下智能判断是否全选
  • 全选时只选择所有可选的叶子节点

# 3. 聚合模式

  • 当父项的所有子项都被选中时,只返回父项ID
  • 减少返回数据量,优化性能
  • 支持复杂的层级结构聚合
  • 通过 parentNodePrefix 属性区分叶子节点和非叶子节点
  • 在聚合模式下,非叶子节点需要添加前缀标识以避免ID冲突

# 4. 禁用状态

  • 支持字段级别的禁用配置
  • 支持自定义禁用判断函数
  • 禁用项不可选择,但会显示在列表中
最后更新时间: 9/16/2025, 9:21:04 AM