You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
212 lines
5.8 KiB
212 lines
5.8 KiB
<template>
|
|
<el-autocomplete class="school-auto-complete" :value="value" :fetch-suggestions="querySearchAsync"
|
|
:placeholder="placeholder" :debounce="debounce" :loading="loading" @select="handleSelect" @input="handleInput"
|
|
@clear="handleManualClear" :clearable="clearable" :size="size" :disabled="disabled">
|
|
<!-- 自定义下拉选项 -->
|
|
<template #default="{ item }">
|
|
<div class="flex-between school-option">
|
|
<span>{{ item.name }}</span>
|
|
<img v-if="showSelectedIcon && item.id === selectedSchoolId" src="../../assets/drop-selected.svg"
|
|
alt="selected" />
|
|
</div>
|
|
</template>
|
|
</el-autocomplete>
|
|
</template>
|
|
|
|
<script>
|
|
import './index.scss'
|
|
export default {
|
|
name: 'SearchInput',
|
|
props: {
|
|
url: {
|
|
type: String,
|
|
default: ''
|
|
},
|
|
// 双向绑定的值(学校名称)
|
|
value: {
|
|
type: String,
|
|
default: ''
|
|
},
|
|
// 选中的学校ID
|
|
selectedSchoolId: {
|
|
type: [String, Number],
|
|
default: null
|
|
},
|
|
// 占位符
|
|
placeholder: {
|
|
type: String,
|
|
default: '请输入名称'
|
|
},
|
|
// 防抖延迟时间
|
|
debounce: {
|
|
type: Number,
|
|
default: 300
|
|
},
|
|
// 是否显示清空按钮
|
|
clearable: {
|
|
type: Boolean,
|
|
default: true
|
|
},
|
|
// 输入框尺寸
|
|
size: {
|
|
type: String,
|
|
default: 'medium'
|
|
},
|
|
// 是否禁用
|
|
disabled: {
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
// 是否显示选中图标
|
|
showSelectedIcon: {
|
|
type: Boolean,
|
|
default: true
|
|
}
|
|
},
|
|
|
|
data() {
|
|
return {
|
|
loading: false,
|
|
timeout: null,
|
|
lastSearchKeyword: '',
|
|
schoolList: [],
|
|
// 新增:记录最后一次有效选择
|
|
lastValidSelection: null
|
|
}
|
|
},
|
|
|
|
mounted() {
|
|
// 初始化时记录当前选择
|
|
if (this.selectedSchoolId && this.value) {
|
|
this.lastValidSelection = {
|
|
id: this.selectedSchoolId,
|
|
name: this.value
|
|
}
|
|
}
|
|
},
|
|
|
|
beforeDestroy() {
|
|
clearTimeout(this.timeout)
|
|
},
|
|
|
|
methods: {
|
|
/**
|
|
* 异步搜索学校
|
|
*/
|
|
async querySearchAsync(queryString, callback) {
|
|
const keyword = queryString.trim()
|
|
|
|
if (!keyword || keyword === this.lastSearchKeyword) {
|
|
callback([])
|
|
return
|
|
}
|
|
|
|
this.lastSearchKeyword = keyword
|
|
this.loading = true
|
|
|
|
clearTimeout(this.timeout)
|
|
this.timeout = setTimeout(async () => {
|
|
try {
|
|
const schools = await this.searchSchools(keyword)
|
|
this.schoolList = schools
|
|
callback(schools)
|
|
} catch (error) {
|
|
console.error('搜索失败:', error)
|
|
callback([])
|
|
} finally {
|
|
this.loading = false
|
|
}
|
|
}, this.debounce)
|
|
},
|
|
|
|
/**
|
|
* 搜索学校API调用
|
|
*/
|
|
async searchSchools(keyword) {
|
|
try {
|
|
const response = await this.$http('POST', this.url, {
|
|
keyword
|
|
})
|
|
|
|
if (response.status && response.data) {
|
|
return response.data
|
|
}
|
|
return []
|
|
} catch (error) {
|
|
this.$message.error('搜索列表失败')
|
|
throw error
|
|
}
|
|
},
|
|
|
|
/**
|
|
* 处理选择事件
|
|
*/
|
|
handleSelect(item) {
|
|
console.log('选中学校:', item)
|
|
|
|
// 更新记录
|
|
this.lastValidSelection = {
|
|
id: item.id,
|
|
name: item.name
|
|
}
|
|
|
|
this.$emit('select', item)
|
|
this.$emit('update:selectedSchoolId', item.id)
|
|
this.$emit('input', item.name)
|
|
this.$emit('change', item)
|
|
},
|
|
|
|
/**
|
|
* 处理输入事件 - 安全版本
|
|
*/
|
|
handleInput(value) {
|
|
console.log('输入变化:', value, '当前选中:', this.selectedSchoolId)
|
|
|
|
// 只更新显示的值
|
|
this.$emit('input', value)
|
|
|
|
// 重要:这里不自动触发清空
|
|
// 清空只会在 handleManualClear 中触发
|
|
},
|
|
handleManualClear() {
|
|
console.log('用户手动清空')
|
|
this.clearSelection()
|
|
},
|
|
clearSelection() {
|
|
console.log('执行清空操作')
|
|
this.$emit('input', '')
|
|
this.$emit('update:selectedSchoolId', null)
|
|
this.$emit('clear')
|
|
this.lastSearchKeyword = ''
|
|
this.lastValidSelection = null
|
|
},
|
|
setSelectedSchool(school) {
|
|
if (school && school.id && school.name) {
|
|
this.lastValidSelection = {
|
|
id: school.id,
|
|
name: school.name
|
|
}
|
|
this.$emit('input', school.name)
|
|
this.$emit('update:selectedSchoolId', school.id)
|
|
this.$emit('select', school)
|
|
}
|
|
},
|
|
clear() {
|
|
this.clearSelection()
|
|
},
|
|
|
|
async triggerSearch(keyword) {
|
|
return await this.searchSchools(keyword || this.value)
|
|
},
|
|
|
|
/**
|
|
* 恢复上一次的有效选择
|
|
*/
|
|
restoreLastSelection() {
|
|
if (this.lastValidSelection) {
|
|
this.setSelectedSchool(this.lastValidSelection)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</script>
|