js

eleme ui el-select 远程模糊搜索例子

Vue.component('MySuperGame', { props: { // 双向绑定值 value: { type: [String, Number, Array], default: '' }, platform: { type: [String, Number], default: 0 }, // 初始默认值(用于回显) initialValu…

0 阅读

Vue.component('MySuperGame', { props: { // 双向绑定值 value: { type: [String, Number, Array], default: '' }, platform: { type: [String, Number], default: 0 }, // 初始默认值(用于回显) initialValue: { type: [String, Number, Array], default: '' }, // 是否多选 multiple: { type: Boolean, default: false }, // 防抖时间(毫秒) debounceTime: { type: Number, default: 300 }, // 是否启用缓存 enableCache: { type: Boolean, default: true }, // 自定义结果格式化函数 formatter: { type: Function, default: items => items.map(item => ({ value: item.id+'', label: item.id+'-'+item.title+'-' + item.subtitle, gameInfo: item })) } }, data() { return { localValue: this.value || this.initialValue, options: [], loading: false, searchKeyword: '', searchCache: new Map(), cancelToken: null } },

watch: {
    'platform': {
        handler(newVal, oldVal) {
            if (newVal > 0 && newVal != oldVal) {
                this.localValue = '';                   // 清空绑定值
                this.options = [];                   // 清空绑定值
            }
        },
    },
    value(newVal) {
        this.localValue = newVal
    },
    localValue(newVal) {
        this.$emit('input', newVal)
        this.$emit('change', newVal)
        let gameNode=this.options.filter(item => {
            if(item.value==newVal){
                return true
            }
        })
        if(gameNode[0]){
            this.$emit('gamechange', gameNode[0].gameInfo)
        }
    }
},

created() {
    console.log('platform',this.platform)
    // 初始化加载默认值对应的选项
    if (this.localValue) {
        this.loadInitialValues()
    }
},

methods: {
    // 防抖搜索方法
    handleSearch: _.debounce( async function  (keyword) {
        this.searchKeyword = keyword.trim()
        if (!this.searchKeyword) {
            this.options = []
            return
        }
        this.loading = true
        this.cancelPreviousRequest()
        let response = await axios.post('/topic/card/getGameNodeSearch', {key: keyword, platform: this.platform,format:0})
            .catch(error => {
                if (!axios.isCancel(error)) {
                    console.error('Remote search failed:', error)
                    this.$message.error('搜索失败,请稍后重试')
                }
            })
            .finally(() => (this.loading = false))
        const items = this.formatter(response.data.data.gameList || [])
        if (this.enableCache) {
            this.searchCache.set(this.searchKeyword, items)
        }
        this.options = items

    }, 300),

    // 取消之前的请求
    cancelPreviousRequest() {
        if (this.cancelToken) {
            this.cancelToken('取消重复请求')
        }
    },

    // 加载初始值对应的选项
    async loadInitialValues() {
        try {
            this.loading = true
            const id =  this.localValue
            const response = await axios.post(`/topic/card/getGameNodeSearch`, {key: id, format: 0, platform: this.platform})
            this.options = this.formatter(response.data.data.gameList || [])
        } catch (error) {
            console.error('初始化加载失败:', error)
        } finally {
            this.loading = false
        }
    },

    // 高亮匹配文本
    highlight(label) {
        if (!this.searchKeyword) return label
        const regex = new RegExp(`(${this.searchKeyword})`, 'gi')
        return label.replace(regex, '<span class="highlight">$1</span>')
    }
},

template: `
  <el-select
      v-model="localValue"
      filterable
      clearable
      remote
      reserve-keyword
      placeholder="请输入游戏名或游戏ID"  
      :multiple="multiple"
      :remote-method="handleSearch"
      :loading="loading"
      :loading-text="'加载中...'"
      :no-match-text="'无匹配结果'"
      :no-data-text="'暂无数据'"
  >
    <el-option
        v-for="item in options"
        :key="item.value"
        :label="item.label"
        :value="item.value"
    >
      <span v-html="highlight(item.label)"></span>
    </el-option>
  </el-select>
`

})

正在加载评论…