Ant Design Vue Select 选择器 全选 功能
Vue.js的组件库Ant Design Vue Select 选择器没有全选功能,如下图所示:
在项目中,我们自己实现了全选和清空功能,如下所示:
代码如下所示:
<!--
=========================================================
* 参数配置 - 风力发电 - 曲线图
* 猴王软件学院 - 大强
* 2025-3-23
=========================================================
-->
<template>
<div>
<div class="flex-container">
<div class="flex-item">
<a-select
id="a-select-scene"
:options="options_scene"
mode="combobox"
style="width: 200px; height:50px;"
@change="proChange_scene"
showArrow="true"
placeholder="请选择场景"
v-model="selected_scene"
>
</a-select>
</div>
<div class="flex-item">
<a-select
id="a-select-node"
:options="options_node"
mode="multiple"
style="width: 200px; height:50px;"
@change="proChange_node"
showArrow="true"
v-model:value="selected_node"
>
<template #dropdownRender="{ menuNode: menu }">
<div>
<a-button @click="allSelectedFun" type="primary" style="margin-right: 10px;">全选</a-button>
<a-button @click="clearFun">清空</a-button>
<a-divider style="margin: 5px 0;" />
<v-nodes :vnodes="menu" />
</div>
</template>
</a-select>
<div class="my-ant-select-selection-placeholder">请选择节点</div>
</div>
<div class="flex-item">
<a-select
id="a-select-power"
:options="options_power"
mode="combobox"
style="width: 200px; height:50px;"
@change="proChange_power"
showArrow="true"
placeholder="请选择功率"
v-model="selected_power"
>
</a-select>
</div>
<div class="flex-item">
<a-button type="primary" preIcon="ant-design:search-outlined" @click="searchChart">查看</a-button>
</div>
</div>
<div ref="chartRef" :style="{ height, width }"></div>
</div>
</template>
<script lang="ts">
import {defineComponent, PropType, ref, Ref, reactive, watchEffect, unref, onMounted} from 'vue';
import {useECharts} from '/@/hooks/web/useECharts';
import {cloneDeep} from 'lodash-es';
import {Select} from "ant-design-vue";
import {initDictOptions} from "@/utils/dict";
export default defineComponent({
name: 'LineMulti',
components: {Select,
VNodes: (_, { attrs }) => {
return attrs.vnodes;
},
},
props: {
chartData: {
type: Array,
default: () => [],
required: true,
},
option: {
type: Object,
default: () => ({}),
},
type: {
type: String as PropType<string>,
default: 'line',
},
width: {
type: String as PropType<string>,
default: '100%',
},
height: {
type: String as PropType<string>,
default: 'calc(100vh - 78px)',
},
},
emits: ['click'],
setup(props, {emit}) {
const chartRef = ref<HTMLDivElement | null>(null);
const {setOptions, getInstance} = useECharts(chartRef as Ref<HTMLDivElement>);
const option = reactive({
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow',
label: {
show: true,
backgroundColor: '#333',
},
},
},
legend: {
top: 30,
},
grid: {
top: 60,
},
xAxis: {
name: '时间(小时)',
type: 'category',
data: [],
},
yAxis: {
name: '功率(万千瓦)',
type: 'value',
},
series: [],
});
// 功率
let options_power = ref<any>([]);
let selected_power = ref('');
// 场景
let options_scene = ref<any>([]);
let selected_scene = ref('');
// 节点
let options_node = ref<any>([]);
// let selected_node = ref('');
let selected_node = ref([]);
/**
* 功率改变函数
* @param val
*/
function proChange_power(val) {
selected_power.value = val;
}
/**
* 场景改变函数
* @param val
*/
function proChange_scene(val) {
selected_scene.value = val;
}
/**
* 节点改变函数
* @param val
*/
function proChange_node(val) {
selected_node.value = val;
}
// 全选函数
function allSelectedFun() {
options_node.value.forEach((item) => {
let index = selected_node.value.indexOf(item.value);
if (index == -1) {
selected_node.value.push(item.value);
}
});
};
// 清空函数
function clearFun() {
selected_node.value.splice(0, selected_node.value.length);
};
/**
* 查看图表
*/
function searchChart() {
if (selected_scene.value == '') {
alert("请选择场景!")
return
}
if (selected_node.value == '') {
alert("请选择节点!")
return
}
if (selected_power.value == '') {
alert("请选择功率!")
return
}
if (props.option) {
Object.assign(option, cloneDeep(props.option));
}
//节点
let nodeArr = Array.from(new Set(props.chartData.map((item) => item.nodeName)));
//轴数据
let xAxisData = Array.from(new Set(props.chartData.map((item) => item.index)));
let seriesData = [];
nodeArr.forEach((node) => {
selected_node.value.forEach((value) => {
if (node === value) {
let obj: any = {name: node, type: props.type};
// update-begin-author:liusq date:2023-7-12 for: [issues/613] LineMulti 在数据不对齐时,横坐标计算错误
let data = [];
xAxisData.forEach((x) => {
let dataArr = props.chartData.filter((item) =>
x == item.index && // 索引
selected_power.value == item.power && // 功率
selected_scene.value == item.scene && // 场景
node == item.nodeName // 节点
);
if (dataArr && dataArr.length > 0) {
data.push(dataArr[0].value);
} else {
data.push(null);
}
});
// update-end-author:liusq date:2023-7-12 for: [issues/613] LineMulti 在数据不对齐时,横坐标计算错误
//data数据
obj['data'] = data;
seriesData.push(obj);
}
});
});
option.series = seriesData;
option.xAxis.data = xAxisData;
// option.legend.show = false;
option.legend.selector = [
{
// 全选
type: 'all',
// 可以是任意你喜欢的标题
title: '全选'
},
{
// 反选
type: 'inverse',
// 可以是任意你喜欢的标题
title: '反选'
}
];
option.legend.selectedMode = false;
option.legend.orient = 'vertical';
option.legend.right = '0px';
// option.legend.top = '-50px';
console.log('option', option);
setOptions(option);
getInstance()?.off('click', onClick);
getInstance()?.on('click', onClick);
}
function onClick(params) {
emit('click', params);
}
/**
* 初始化字典选项
*/
async function initDictConfig() {
options_power.value = await initDictOptions('power');
options_scene.value = await initDictOptions('scene');
options_node.value = await initDictOptions('node');
}
onMounted(() => {
//初始化字典选项
initDictConfig();
});
return {
options_power, options_scene, options_node,
selected_power, selected_scene, selected_node,
proChange_power, proChange_scene, proChange_node, chartRef, searchChart,
allSelectedFun, clearFun
};
},
});
</script>
<style>
.flex-container {
display: -webkit-flex;
display: flex;
}
.flex-item {
width: 210px;
}
.ant-select-multiple .ant-select-selection-overflow-item {
flex: none;
align-self: center;
max-width: 100%;
display: none;
}
.my-ant-select-selection-placeholder {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
flex: 1;
color: rgba(0, 0, 0, 0.65);
pointer-events: none;
margin-top: -45px;
margin-left: 20px;
position: relative;
}
</style>