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>
`
})