Newer
Older
xc-business-system / src / components / SelectByDict / index.vue
lyg on 19 Apr 2024 5 KB bug修改
<!-- 可输入配置字典的下拉选项 输入框 -->
<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,
  },
})
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 = () => {
  getDictByCode(props.dictCode).then((res) => {
    dictList.value = res.data.map((item: any) => ({ ...item, value1: item.value, value: item.name }))
  })
}
// 加载选项数据
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 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"
  >
    <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>