<!-- 可输入配置字典的下拉选项 输入框 --> <script lang="ts" setup name="SelectByDict"> import { CircleClose } from '@element-plus/icons-vue' import { getDictAllList, getDictByCode, updateDict } from '@/api/system/dict' // ------------------定义props、 emit------------------- const props = defineProps({ // 数据绑定 modelValue: { type: [Number, String], default: '', }, // 输入 // 是否禁用 disabled: { type: Boolean, default: false, }, placeholder: { type: String, default: '请输入', }, // 字典纸对应code dictCode: { type: String, required: true, }, // 字典数组,传递了就不用组件内接口获取 // dictData: { // type: Array, // default: () => ([]), // }, // isData: { // type: Boolean, // default: false, // }, }) const emit = defineEmits(['update:modelValue', 'getDictValue', 'changeValue']) const checkItem = ref({}) // 选中的选项 const input = ref() // 输入框组件 // -------------------------定义数据-------------------- const value = computed({ get() { return props.modelValue }, set(value) { emit('update:modelValue', value) }, }) // 点击选项 const handleSelect = (item: LinkItem) => { console.log('点击选项', item) checkItem.value = item } // 字典列表 const dictList = ref<{ name: string;id: string;value: string }[]>([]) // 获取字典列表 const fetchDict = () => { // if (props.dictData.length) { // dictList.value = props.dictData // } // else if (props.isData) { // dictList.value = props.dictData // } // else { getDictByCode(props.dictCode).then((res) => { dictList.value = res.data.map((item: any) => ({ ...item, value1: item.value, value: item.name })) // console.log(dictList.value, 'dictList.value') }) // } } // watch(() => props.dictData, (newVal) => { // if (newVal.length && props.isData) { // dictList.value = props.dictData.map((item: any) => ({ ...item, value1: item.value, value: item.name })) // console.log(dictList.value, 'dictList.value-custom') // } // }) // 加载选项数据 const querySearch = (queryString: string, cb) => { const results = queryString ? dictList.value.filter(item => item.name.includes(queryString)) : dictList.value cb(results) } // 数据转换, 字典详情转换为中间带冒号的 function arrayToString(arr: any[]) { let detailArray = '' const detailList = arr detailList.forEach((detail, index) => { detailArray += `${detail.value}:${detail.name}:${detail.num}` if (index !== (detailList.length - 1)) { detailArray += ';' } }) return detailArray } // 字典详情字符串转数组 function stringToArray(data: string) { const detailArr = data.split(';') const arr = [] for (const detail of detailArr) { const detailItem = detail.split(':') const item = { value: detailItem[0], name: detailItem[1], num: parseInt(detailItem[2]), } arr.push(item) } return arr } const changeValue = (val: any) => { emit('changeValue', val) } // 更新字典 const updateDictFun = () => { if (value.value) { const inputValue = value.value // 先判断字典中是否存在该值 const data = dictList.value.filter(item => item.name === inputValue).length console.log() if (!data) { console.log(inputValue, '该值不存在添加字典') emit('changeValue', inputValue) // 在字典中添加该值 getDictAllList().then((res) => { const currentDict = res.data.filter(item => item.code === props.dictCode)[0] // 整理数据 const formData = { dictId: currentDict.id, dictCode: currentDict.code, dictName: currentDict.name, dictTips: currentDict.tips, dictValues: currentDict.detail, } const dict = stringToArray(formData.dictValues) // 在原来数据中插入新的数据 dict.push({ value: dict.map(item => item.value).every(item => !isNaN(item)) ? String(Math.max(...dict.map(item => Number(item.value))) + 1) : String(Math.ceil(Math.random() * 1000)), name: inputValue, num: dict[dict.length - 1].num + 1, }) formData.dictValues = arrayToString(JSON.parse(JSON.stringify(dict))) // 调用更新接口 updateDict(formData).then(() => { // 更新字典列表 dictList.value = dict.map((item: any) => ({ ...item, value1: item.value, value: item.name })) // 发送 绑定的value (可用可不用) emit('getDictValue', dictList.value.filter(item => item.name === inputValue)[0].value1) }).catch(() => { emit('getDictValue', inputValue) }) }).catch(() => { emit('getDictValue', inputValue) }) } else { console.log(inputValue, '该值存在') emit('changeValue', inputValue) // 发送 绑定的value (可用可不用) emit('getDictValue', dictList.value.filter(item => item.name === inputValue)[0].value1) // setTimeout(() => { // input.value.blur() // }) } } } // -------------------------钩子-------------------- onMounted(() => { if (props.dictCode) { fetchDict() } }) // defineExpose({ // clearMulti, initColumnsState, // }) </script> <template> <el-autocomplete ref="input" v-model.trim="value" clearable :fetch-suggestions="querySearch" :disabled="props.disabled" popper-class="my-autocomplete" :placeholder="props.placeholder" style="width: 100%;" @select="handleSelect" @blur="updateDictFun" @change="changeValue" > <template #default="{ item }"> <div class="value"> <div>{{ item.name }}</div> <div /> <!-- <div style="height: 34px;line-height: 40px;"> <el-icon style="font-size: 18px;"> <circle-close /> </el-icon> </div> --> </div> </template> </el-autocomplete> </template> <style scoped lang="scss"> .value { display: flex; justify-content: space-between; line-height: 34px; } </style>