| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 |
- <template>
- <div class="flex flex-wrap">
- <el-select v-model="selectedValue" filterable remote reserve-keyword :placeholder="placeholder"
- :remote-method="debouncedRemoteMethod" :loading="loading" :multiple="multiple" :disabled="disabled"
- :style="{ width: width }" :multiple-limit="max" clearable>
- <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
- </el-select>
- </div>
- </template>
- <script lang="ts" setup>
- import { onMounted, ref, watch, defineProps, defineEmits, onUnmounted } from 'vue'
- import { debounce } from 'lodash-es'
- import { listUser, getUser } from "@/api/system/user"
- import { unref } from 'vue'
- interface ListItem {
- value: string
- label: string
- }
- // 定义组件属性
- const props = defineProps<{
- modelValue: string | string[]
- multiple?: boolean
- disabled?: boolean
- width?: string
- max?: number
- placeholder?: string
- }>()
- // 定义组件事件
- const emits = defineEmits(['update:modelValue'])
- const options = ref<ListItem[]>([])
- const loading = ref(false)
- const selectedValue = ref<string | string[]>(props.modelValue)
- // 根据用户ID列表获取用户信息
- const fetchUsersByIds = async (userIds: string[]) => {
- if (!userIds || userIds.length === 0) return []
- try {
- // 使用Promise.all并行获取每个用户的信息
- const userPromises = userIds.map(userId => getUser(userId))
- const userResponses = await Promise.all(userPromises)
- return userResponses.map((response: any) => ({
- value: response.data.userId,
- label: response.data.nickName
- }))
- } catch (error) {
- console.error('获取用户信息失败:', error)
- return []
- }
- }
- // 远程搜索方法
- const remoteMethod = async (query: string) => {
- if (query) {
- loading.value = true
- try {
- // 调用远程接口获取数据
- const response = await listUser({ nickName: query })
- // 假设接口返回的数据结构为 { data: [...] },根据实际情况调整
- options.value = response.rows.map((item) => ({
- value: item.userId, // 根据实际接口返回字段调整
- label: item.nickName // 根据实际接口返回字段调整
- }))
- } catch (error) {
- console.error('远程搜索出错:', error)
- } finally {
- loading.value = false
- }
- } else {
- options.value = []
- }
- }
- // 防抖处理远程搜索
- const debouncedRemoteMethod = debounce(remoteMethod, 300)
- // 标记是否正在初始化回显,避免循环更新
- const isInitializing = ref(false)
- // 监听modelValue变化,有值时执行回显逻辑
- watch(() => props.modelValue, async (newValue, oldValue) => {
- // 只有当值从无到有或值发生变化时才执行回显
- if (newValue && newValue.length > 0 && newValue !== oldValue) {
- isInitializing.value = true
- try {
- const userIds = Array.isArray(newValue) ? newValue : [newValue]
- const userOptions = await fetchUsersByIds(userIds)
- options.value = userOptions
-
- // 设置选中值,但不触发更新事件
- selectedValue.value = newValue
- } finally {
- isInitializing.value = false
- }
- }
- }, { immediate: true })
- // 监听选中值变化并触发更新事件
- watch(selectedValue, (newValue) => {
- // 只有在非初始化状态下才触发更新事件
- if (!isInitializing.value) {
- emits('update:modelValue', newValue)
- }
- })
- // 组件销毁时清空数据
- onUnmounted(() => {
- options.value = []
- selectedValue.value = props.multiple ? [] : ''
- emits('update:modelValue', selectedValue.value)
- })
- </script>
- <style scoped lang="scss">
- .flex {
- width: 100%;
- }
- </style>
|