vue3+element-plus多个多选下拉框并搜索

发布于:2025-04-08 ⋅ 阅读:(47) ⋅ 点赞:(0)

一、下拉框组件:

<template>

  <div class="top-select">

    <div class="first-select">

      <div

        v-for="(group, index) in selectGroups"

        :key="index"

        class="item-select"

      >

        <div class="title">{{ group.title }}</div>

        <el-select

          v-model="group.checkedValues"

          multiple

          clearable

          collapse-tags

          :reserve-keyword="false"

          placeholder="全部"

          :max-collapse-tags="1"

          @visible-change="group.handleVisibleChange"

          popper-class="custom-header"

          class="select-box"

        >

          <template #header>

            <div class="header-box">

              <el-checkbox

                v-model="group.isCheckAll"

                :indeterminate="group.isIndeterminate"

                @change="group.handleCheckAll"

              >

                全部

              </el-checkbox>

              <el-input

                v-model.trim="group.searchVal"

                :maxlength="6"

                :placeholder="`请输入${group.title}`"

                clearable

                class="ipt"

              />

            </div>

          </template>

          <el-option

            v-for="item in group.filteredOptions"

            :key="item.value"

            :label="item.label"

            :value="item.value"

          />

        </el-select>

      </div>

      <el-button class="reset-btn btn" @click="resetSelect">重置</el-button>

      <el-button type="primary" class="search-btn btn" @click="searchData"

        >搜索</el-button

      >

    </div>

  </div>

</template>

<script setup lang="ts">

import { ElMessage } from 'element-plus'

import { queryIndustrySelect } from './../../monitorApi/jurisdiction/index'

import { useReportStore } from '@/store/modules/report'

const emit = defineEmits([

  'getCheckedValues',

  'seachTable',

  'resetToTop'

])

// 定义通用的全选和部分选中逻辑

const useCheckboxGroup = (options: any, title: string) => {

  const checkedValues = ref<any[]>(options.value.map((item: any) => item.value)) // 下拉框多选选中的值

  const checkedAllValues = ref<any[]>([]) // 传给后端下拉框多选选中的值

  const isCheckAll = ref(true)

  const isIndeterminate = ref(false)

  const searchVal = ref('')

  watch(checkedValues, (val) => {

    if (val.length === 0) {

      isCheckAll.value = false

      isIndeterminate.value = false

      checkedAllValues.value = []

    } else if (val.length === options.value.length) {

      isCheckAll.value = true

      isIndeterminate.value = false

      checkedAllValues.value = []

    } else {

      isIndeterminate.value = true

      checkedAllValues.value = checkedValues.value

    }

    emit('getCheckedValues', [

      selectGroups.value[0].checkedAllValues,

      selectGroups.value[1].checkedAllValues,

      selectGroups.value[2].checkedAllValues

    ])

  })

  // 点击多选框全选方法

  const handleCheckAll = (checked: boolean) => {

    isIndeterminate.value = false

    checkedValues.value = checked

      ? options.value.map((item: any) => item.value)

      : []

  }

  // 计算属性实现选项过滤

  const filteredOptions = computed(() => {

    if (!searchVal.value) return options.value

    return options.value.filter((item: any) =>

      item.label.includes(searchVal.value)

    )

  })

  // 下拉框显示/隐藏时重置搜索

  const handleVisibleChange = (visible: boolean) => {

    if (!visible) {

      searchVal.value = ''

    }

  }

  return {

    title,

    options,

    filteredOptions,

    checkedValues,

    checkedAllValues,

    isCheckAll,

    isIndeterminate,

    handleCheckAll,

    searchVal,

    handleVisibleChange

  }

}

// 初始化多选框数据

const selectGroups = ref([

  useCheckboxGroup(ref([{ value: '广东局', label: '广东局' }]), '辖区范围'),

  useCheckboxGroup(ref([]), '行业范围'),

  useCheckboxGroup(

    ref([

      { value: 'BSE', label: '北交所' },

      { value: 'SSE', label: '沪主板' },

      { value: 'STAR', label: '科创板' },

      { value: 'SZSE', label: '深主板' },

      { value: 'GEM', label: '创业板' }

    ]),

    '交易板块'

  )

])

// 获取行业下拉列表

const getIndustrySelect = () => {

  selectGroups.value[1].options = []

  queryIndustrySelect().then((res: any) => {

    if (res.code === 200) {

      res.data.forEach((item: any) => {

        let obj = {

          value: item.industryCode,

          label: item.industryName

        }

        selectGroups.value[1].options.push(obj)

        // 设置行业下拉筛选值

        if (useReportStore().topSelectObj.industryCode.length > 0) {

          selectGroups.value[1].checkedValues =

            useReportStore().topSelectObj.industryCode

          selectGroups.value[1].checkedAllValues =

            useReportStore().topSelectObj.industryCode

        } else {

          selectGroups.value[1].checkedValues =

            selectGroups.value[1].options.map((item: any) => item.value)

        }

      })

    } else {

      ElMessage({

        type: 'error',

        message: res.message

      })

    }

  })

}

// 重置

const resetSelect = () => {

  selectGroups.value[0].checkedValues = selectGroups.value[0].options.map(

    (item: any) => item.value

  ) // 多选框选中的值

  selectGroups.value[1].checkedValues = selectGroups.value[1].options.map(

    (item: any) => item.value

  ) // 行业筛选的值

  selectGroups.value[2].checkedValues = selectGroups.value[2].options.map(

    (item: any) => item.value

  ) // 多选框选中的值

  selectGroups.value[0].checkedAllValues = [] // 传给后端多选框选中的值

  selectGroups.value[1].checkedAllValues = [] // 传给后端多选框选中的值

  selectGroups.value[2].checkedAllValues = [] // 传给后端多选框选中的值

  emit('resetToTop') // 条件重置页面置顶

}

// 搜索

const searchData = () => {

  emit('seachTable')

}

onMounted(() => {

  getIndustrySelect()

})

onUnmounted(() => {

  let obj = {

    exchangeCode: [], // 多选框选中的值

    industryCode: [], // 多选框选中的值

    area: [] // 多选框选中的值

  }

  useReportStore().setTopSelect(obj)

})

</script>

<style lang="less">

.el-select-dropdown__header {

  padding: 5px 10px;

  .header-box {

    display: flex;

    align-items: center;

    justify-content: space-between;

    .ipt {

      width: 120px;

      height: 28px;

    }

  }

}

.el-checkbox__label {

  font-size: 12px;

}

</style>

<style lang="less" scoped>

.top-select {

  display: flex;

  flex-wrap: wrap;

  .first-select {

    margin-bottom: 10px;

  }

  .first-select,

  .second-select {

    display: flex;

    align-items: center;

    .item-select {

      display: flex;

      align-items: center;

      margin-right: 28px;

      .title {

        margin-right: 10px;

        font-size: 14px;

        color: #333333;

      }

      .select-box {

        width: 205px;

      }

      .select-box1 {

        width: 175px;

      }

    }

    .date-select {

      margin-right: 30px;

    }

    .account-select {

      margin-right: 0 !important;

      margin-left: 28px;

    }

    .edit-box {

      margin-right: 0 !important;

    }

    .btn {

      width: 52px;

      border-radius: 4px;

      font-size: 12px;

      margin-left: 10px;

      display: flex;

      justify-content: center;

      align-items: center;

      cursor: pointer;

    }

    .reset-btn {

      height: 28px;

      color: #3a5bb7;

      border: 1px solid #3a5bb7;

    }

    .search-btn {

      height: 30px;

    }

  }

}

</style>

二、下拉框使用组件:

<template>

      <!-- 筛选板块 -->

      <div class="select-box">

        <div class="content">

          <topSelect

            @getCheckedValues="getCheckedValues"

            @seachTable="seachTable"

            @resetToTop="resetToTop"

          ></topSelect>

        </div>

      </div>

</template>

<script setup lang="ts">

import topSelect from './topSelect.vue'

import { useReportStore } from '@/store/modules/report'

const seleceObj = ref<any>({

  exchangeCode: [], // 多选框选中的值

  industryCode: [], // 多选框选中的值

  area: [] // 多选框选中的值

})

// 获取多选框选中的值

const getCheckedValues = (data: any) => {

  seleceObj.value.exchangeCode = data[2]

  seleceObj.value.industryCode = data[1]

  seleceObj.value.area = data[0]

}

// 搜索

const seachTable = () => {

  let selectTopObj = JSON.parse(JSON.stringify(seleceObj.value))

  let obj = {

    exchangeCode: selectTopObj.exchangeCode, // 多选框选中的值

    industryCode: selectTopObj.industryCode, // 多选框选中的值

    area: selectTopObj.area // 多选框选中的值

  }

  useReportStore().setTopSelect(obj)

}

// 重置置顶

const resetToTop = () => {

  seleceObj.value = {

    exchangeCode: [], // 多选框选中的值

    industryCode: [], // 多选框选中的值

    area: [] // 多选框选中的值

  }

  useReportStore().setTopSelect(seleceObj.value)

}

</script>

<style scoped lang="less">

    .select-box {

      background-color: #fff;

      width: 100%;

      margin-bottom: 10px;

      display: flex;

      justify-content: center;

      .content {

        width: 1450px;

        height: 100%;

        display: flex;

        margin: 10px 0;

      }

    }

</style>

三、store中report文件方法:

import { ref } from 'vue'

import store from '@/store'

import { defineStore } from 'pinia'

export const useReportStore = defineStore('report', () => {

  const topSelectObj = ref({

    exchangeCode: [], // 多选框选中的值

    industryCode: [], // 多选框选中的值

    area: [] // 多选框选中的值

  }) // 筛选条件

  // 存储筛选条件

  const setTopSelect = (data: any) => {

    topSelectObj.value = data

  }

  return {

    topSelectObj,

    setTopSelect

  }

})

/** 在 setup 外使用 */

export function useReportStoreHook() {

  return useReportStore(store)

}


网站公告

今日签到

点亮在社区的每一天
去签到