diff --git a/src/views/liswork/work/components/DictInput.vue b/src/views/liswork/work/components/DictInput.vue index ab6569c..541f47c 100644 --- a/src/views/liswork/work/components/DictInput.vue +++ b/src/views/liswork/work/components/DictInput.vue @@ -9,6 +9,7 @@ @clear="handleClear" @dblclick="handleDblClick" > +<<<<<<< HEAD @@ -51,6 +52,55 @@ +======= + + + + + + + + + + + + + + + +>>>>>>> e1f19883e37f969d4e8ada6a3137ba399ebfc6df @@ -59,6 +109,7 @@ import { ref, computed, watch, onMounted } from 'vue'; import { Loading, ArrowDown } from '@element-plus/icons-vue'; +<<<<<<< HEAD import { getFirstLetter } from '@/api/pinyin.js'; // 引入拼音处理工具 // 组件参数 const props = defineProps({ @@ -89,6 +140,64 @@ const displayValue = computed({ return labelValue.value || tempValue.value || props.modelValue || ''; }, set(newValue) { +======= +// 组件参数(Vue3 语法) +const props = defineProps({ + modelValue: { // 双向绑定的原始值 + type: [String, Number], + default: '' + }, + dictType: { // 字典类型 + type: String, + required: true + }, + placeholder: { + type: String, + default: '请输入或双击选择' + }, + clearable: { + type: Boolean, + default: true + }, + disabled: { + type: Boolean, + default: false + }, + fetchDict: { // 获取字典的方法(需返回 Promise) + type: Function, + required: true + }, + dialogTitle: { + type: String, + default: '选择字典项' + } +}); + +// 组件事件(Vue3 语法) +const emit = defineEmits([ + 'update:modelValue', // 同步原始值 + 'update:labelValue', // 同步标签值 + 'select' // 选中事件 +]); + +// 内部状态(Vue3 ref 响应式) +const tempValue = ref(''); // 临时输入值 +const labelValue = ref(''); // 映射后的标签 +const dictData = ref([]); // 完整字典数据 +const filteredDictData = ref([]); // 过滤后的字典数据 +const isDictLoading = ref(true); // 字典加载状态 +const dialogVisible = ref(false); // 弹窗显示状态 +const searchKey = ref(''); // 搜索关键词 + +// 显示值计算(Vue3 computed) +const displayValue = computed({ + get() { + // 优先显示标签,无则显示原始值 + return labelValue.value || tempValue.value || props.modelValue || ''; + }, + set(newValue) { + // 用户输入时更新临时值,并清除旧标签 +>>>>>>> e1f19883e37f969d4e8ada6a3137ba399ebfc6df tempValue.value = newValue; if (labelValue.value && newValue !== labelValue.value) { labelValue.value = ''; @@ -97,6 +206,7 @@ const displayValue = computed({ } }); +<<<<<<< HEAD // 加载字典数据(并添加简拼字段) @@ -111,6 +221,16 @@ const loadDictData = async () => { })); filteredDictData.value = [...dictData.value]; +======= +// 加载字典数据 +const loadDictData = async () => { + try { + isDictLoading.value = true; + // 调用父组件传入的字典获取方法 + const data = await props.fetchDict(props.dictType); + dictData.value = data || []; + filteredDictData.value = [...dictData.value]; // 初始化过滤数据 +>>>>>>> e1f19883e37f969d4e8ada6a3137ba399ebfc6df } catch (error) { console.error(`加载${props.dictType}字典失败:`, error); dictData.value = []; @@ -120,6 +240,7 @@ const loadDictData = async () => { } }; +<<<<<<< HEAD // 核心搜索逻辑(支持模糊搜索+简拼搜索) const filterDictData = () => { const key = searchKey.value.trim().toLowerCase(); @@ -139,11 +260,28 @@ const filterDictData = () => { // 满足任一条件即匹配 return matchLabel || matchValue || matchPinyin; }); +======= +// 过滤字典数据(搜索功能) +const filterDictData = () => { + if (!searchKey.value) { + filteredDictData.value = [...dictData.value]; + return; + } + const key = searchKey.value.toLowerCase(); + filteredDictData.value = dictData.value.filter(item => + item.label.toLowerCase().includes(key) || + String(item.value).toLowerCase().includes(key) + ); +>>>>>>> e1f19883e37f969d4e8ada6a3137ba399ebfc6df }; // 双击事件处理 const handleDblClick = () => { if (!props.disabled && !isDictLoading.value) { +<<<<<<< HEAD +======= + console.log('双击触发弹窗'); +>>>>>>> e1f19883e37f969d4e8ada6a3137ba399ebfc6df dialogVisible.value = true; } }; @@ -152,13 +290,19 @@ const handleDblClick = () => { const openDictSelector = () => { if (!props.disabled && !isDictLoading.value) { dialogVisible.value = true; +<<<<<<< HEAD searchKey.value = ''; filterDictData(); +======= + searchKey.value = ''; // 重置搜索 + filterDictData(); // 重置过滤 +>>>>>>> e1f19883e37f969d4e8ada6a3137ba399ebfc6df } }; // 选择字典项 const selectItem = (item) => { +<<<<<<< HEAD emit('update:modelValue', item.value); emit('update:labelValue', item.label); emit('select', item); @@ -172,10 +316,60 @@ const handleBlur = () => { /* ... */ }; const handleClear = () => { /* ... */ }; +======= + // 同步原始值和标签值到父组件 + emit('update:modelValue', item.value); + emit('update:labelValue', item.label); + emit('select', item); // 触发选中事件 + + // 更新内部状态 + tempValue.value = item.value; + labelValue.value = item.label; + + // 关闭弹窗 + dialogVisible.value = false; +}; + +// 失焦时自动映射 +const handleBlur = () => { + const value = tempValue.value.trim() || props.modelValue; + if (!value) { + emit('update:modelValue', ''); + emit('update:labelValue', ''); + labelValue.value = ''; + tempValue.value = ''; + return; + } + + // 查找匹配的字典项 + const matched = dictData.value.find( + item => String(item.value) === String(value) + ); + + if (matched) { + emit('update:labelValue', matched.label); + labelValue.value = matched.label; + } else { + emit('update:labelValue', value); // 无匹配时用原始值 + labelValue.value = value; + } +}; + +// 清空输入 +const handleClear = () => { + tempValue.value = ''; + labelValue.value = ''; + emit('update:modelValue', ''); + emit('update:labelValue', ''); +}; + +// 关闭弹窗 +>>>>>>> e1f19883e37f969d4e8ada6a3137ba399ebfc6df const handleDialogClose = () => { dialogVisible.value = false; }; +<<<<<<< HEAD // 监听初始值变化 watch(() => props.modelValue, (newVal) => { tempValue.value = newVal || ''; @@ -185,6 +379,26 @@ watch(() => props.modelValue, (newVal) => { emit('update:labelValue', labelValue.value); } }, {immediate: true}); +======= +// 监听父组件传入的初始值 +watch( + () => props.modelValue, + (newVal) => { + if (newVal === tempValue.value) return; // 避免重复更新 + tempValue.value = newVal || ''; + + // 初始值自动映射标签 + if (newVal && !isDictLoading.value) { + const matched = dictData.value.find( + item => String(item.value) === String(newVal) + ); + labelValue.value = matched?.label || newVal; + emit('update:labelValue', labelValue.value); + } + }, + { immediate: true } // 初始化时执行一次 +); +>>>>>>> e1f19883e37f969d4e8ada6a3137ba399ebfc6df // 组件挂载时加载字典 onMounted(async () => { @@ -193,7 +407,10 @@ onMounted(async () => {