⚔ refactor(pulldownSelecter): 优化并修复部分一直bug

This commit is contained in:
喵你个汪呀 2025-08-18 18:52:37 +08:00
parent 33aa826fc1
commit f28f128625

View File

@ -91,7 +91,7 @@ const props = defineProps({
*/ */
labelFormat: { labelFormat: {
type: Function, type: Function,
default: (item: any) => {}, default: (item: any) => undefined,
}, },
/** /**
* 默认查询条件值绑定的属性名 * 默认查询条件值绑定的属性名
@ -231,7 +231,7 @@ const resetQuery = () => {
}; };
// //
const remoteMethod = debounce((query) => { const remoteMethod = debounce((query: any) => {
if (query) { if (query) {
state.loading = true; state.loading = true;
if (typeof query === 'string') { if (typeof query === 'string') {
@ -258,37 +258,42 @@ const handleQuery = () => {
// //
const handleChange = (row: any) => { const handleChange = (row: any) => {
state.tableQuery = Object.assign(state.tableQuery, props.queryParams); state.tableQuery = Object.assign(state.tableQuery, props.queryParams);
state.defaultOptions = props.defaultOptions ?? [];
state.defaultOptions.push(row);
//
if (props.multiple && !state.selectedValues) state.selectedValues = []; if (props.multiple && !state.selectedValues) state.selectedValues = [];
// ,
if (typeof row[props.valueProp] === 'string') row[props.valueProp] = row[props.valueProp]?.trim(); if (typeof row[props.valueProp] === 'string') row[props.valueProp] = row[props.valueProp]?.trim();
setDefaultOptions([row]);
//
state.selectedValues = props.multiple ? Array.from(new Set([...state.selectedValues, row[props.valueProp]])) : row[props.valueProp]; state.selectedValues = props.multiple ? Array.from(new Set([...state.selectedValues, row[props.valueProp]])) : row[props.valueProp];
emit('update:modelValue', state.selectedValues);
emit('change', state.selectedValues, row); //
if (!props.multiple || state.selectedValues) selectRef.value?.blur(); if (!props.multiple || state.selectedValues) selectRef.value?.blur();
tableRef.value?.setCurrentRow(row); tableRef.value?.setCurrentRow(row);
emit('update:modelValue', state.selectedValues);
emit('change', state.selectedValues, row);
}; };
watch( //
() => props.modelValue, const selectVisibleChange = (visible: boolean) => {
(val: any) => { if (visible) {
state.selectedValues = val; state.tableQuery[props.keywordProp] = undefined;
}, handleQuery();
{ immediate: true } }
); };
watch( //
() => props.defaultOptions,
(val: any) => {
state.defaultOptions = val;
},
{ immediate: true }
);
//
const setDefaultOptions = (options: any[]) => { const setDefaultOptions = (options: any[]) => {
state.defaultOptions = options; const list = [] as any[];
for(const item of [...options ?? [], ...state.defaultOptions]) {
const value = item?.[props.valueProp];
const label = props.labelFormat?.(item) || item?.[props.labelProp];
if (value && label) list.push({ [props.valueProp]: value, [props.labelProp]: label })
}
state.defaultOptions = Array.from(new Set(list));
}; };
// //
@ -314,6 +319,9 @@ const setValue = (option: any | any[], row: any) => {
emit('change', state.selectedValues, row); emit('change', state.selectedValues, row);
}; };
watch(() => props.modelValue, (val: any) => state.selectedValues = val, { immediate: true });
watch(() => props.defaultOptions, (val: any) => setDefaultOptions(val), { immediate: true });
defineExpose({ defineExpose({
setValue, setValue,
handleQuery, handleQuery,
@ -324,32 +332,26 @@ defineExpose({
<template> <template>
<el-select <el-select
v-model="state.selectedValues" v-model="state.selectedValues"
:clearable="clearable" :clearable="clearable"
:multiple="multiple" :multiple="multiple"
:disabled="disabled" :disabled="disabled"
:placeholder="placeholder" :placeholder="placeholder"
:allow-create="allowCreate" :allow-create="allowCreate"
:remote-method="remoteMethod" :remote-method="remoteMethod"
:default-first-option="allowCreate" :default-first-option="allowCreate"
@visible-change="(val: boolean) => (val ? handleQuery() : null)" @visible-change="selectVisibleChange"
popper-class="popper-class" popper-class="popper-class"
ref="selectRef" ref="selectRef"
remote-show-suffix remote-show-suffix
filterable filterable
remote remote
> >
<!-- 隐藏的选项用于占位 --> <!-- 隐藏的选项用于占位 -->
<el-option style="width: 0; height: 0" /> <el-option style="width: 0; height: 0" />
<!-- 默认选项用于回显数据 --> <!-- 默认选项用于回显数据 -->
<el-option <el-option v-for="item in state.defaultOptions ?? []" :key="item[valueProp]" :label="labelFormat(item) || item[labelProp]" :value="item[valueProp]" style="width: 0; height: 0" />
v-for="item in (state.defaultOptions ?? []).filter((e) => !state.tableData?.items?.find((e2) => e2[valueProp] === e[valueProp]))"
:key="item[valueProp]"
:label="labelFormat(item) || item[labelProp]"
:value="item[valueProp]"
style="width: 0; height: 0"
/>
<!-- 下拉框内容区域 --> <!-- 下拉框内容区域 -->
<div class="w100" v-loading="state.loading"> <div class="w100" v-loading="state.loading">
@ -367,12 +369,12 @@ defineExpose({
<!-- 数据表格 --> <!-- 数据表格 -->
<el-table <el-table
ref="tableRef" ref="tableRef"
@row-click="handleChange" @row-click="handleChange"
:data="state.tableData?.items ?? []" :data="state.tableData?.items ?? []"
:height="`calc(${dropdownHeight} - 175px${$slots.queryForm ? ' - 35px' : ''})`" :height="`calc(${dropdownHeight} - 175px${$slots.queryForm ? ' - 35px' : ''}${state.tableQuery[keywordProp] && allowCreate ? ' - 35px' : ''})`"
:style="{ width: dropdownWidth }" :style="{ width: dropdownWidth }"
highlight-current-row highlight-current-row
> >
<template #empty><el-empty :image-size="25" /></template> <template #empty><el-empty :image-size="25" /></template>
<slot name="columns"></slot> <slot name="columns"></slot>
@ -380,17 +382,17 @@ defineExpose({
<!-- 分页组件 --> <!-- 分页组件 -->
<el-pagination <el-pagination
v-if="props.pagination" v-if="props.pagination"
:disabled="state.loading" :disabled="state.loading"
:currentPage="state.tableQuery.page" :currentPage="state.tableQuery.page"
:page-size="state.tableQuery.pageSize" :page-size="state.tableQuery.pageSize"
:total="state.tableData.total" :total="state.tableData.total"
:pager-count="4" :pager-count="4"
@size-change="handleSizeChange" @size-change="handleSizeChange"
@current-change="handleCurrentChange" @current-change="handleCurrentChange"
layout="prev, pager, next" layout="prev, pager, next"
size="small" size="small"
background background
/> />
</div> </div>
</el-select> </el-select>
@ -407,4 +409,4 @@ defineExpose({
.popper-class { .popper-class {
min-width: 400px !important; min-width: 400px !important;
} }
</style> </style>