上面这个是效果图,写的有点丑,凑合看吧,
下面这个是我当时的目标图(是华为控制台里的)
不多啰嗦,直接代码展示
<template>
<div class="SearchRow">
<!-- 已输入好的部分 -->
<div class="selectTagCss"v-if="selectedTagList.length > 0">
<el-tag
v-for=" item in selectedTagList"
:key="item.value"
closable
type="info"
@close="handleClose(item)"
>{{ item.label + ':' + item.text }}</el-tag>
</div>
<!-- 正在选择的部分 -->
<div class="currentSelectCss" v-if="currentSelectTag.label">
{{ currentSelectTag.label + ':' }}
</div>
<!-- 输入框 -->
<!-- @focus="showOptions" -->
<div class="inputAndOption" >
<input
v-model="inputValue"
class="input-text"
ref="inputRef"
@keyup="handleKeyup"
@blur="submitInput"
@click="showOptions"
placeholder="添加筛选条件"
></input>
<el-tooltip v-if="selectedTagList.length > 0 || currentSelectTag.label" content="清空" placement="top" effect="light">
<div @click="clearTags" class="clearTagCss">✖</div>
</el-tooltip>
<div class="optionsCSS" v-if="optionVisible && !currentSelectTag.label && !inputValue">
<option
v-for="item in options"
:key="item.value"
@click="selectField(item)"
>
{{ item.label }}
</option>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { reactive, onMounted, ref, toRefs, getCurrentInstance } from 'vue';
import { Search, Plus, Select } from '@element-plus/icons-vue';
const { proxy } = getCurrentInstance();
// 控制下拉框显隐
const optionVisible = ref(false);
// 输入框的内容
const inputValue = ref('');
// 已选择好的数组
const selectedTagList = ref([]);
const currentSelectTag = ref({});
const options = ref([
{ value: 'regulationName', label: '法规名称' },
{ value: 'code', label: '编号' },
]);
// 切换显示和隐藏
function showOptions() {
// optionVisible.value = true;
optionVisible.value = !optionVisible.value;
}
// 隐藏下拉框
function HiddenOptions() {
optionVisible.value = false
}
// 点击选择的字段
function selectField(item) {
currentSelectTag.value = item;
proxy.$refs.inputRef.focus()
HiddenOptions();
}
// 输入框的按键
function handleKeyup(e){
// 检查是否是退格键(Backspace 或 Delete)
if (e.key === 'Backspace' || e.key === 'Delete' || e.keyCode === 8) {
currentSelectTag.value = {}
}
// 如果你想监听回车键,可以在这里加入 @keyup.enter 的处理逻辑
if (e.key === 'Enter') {
submitInput();
}
}
// 删掉标签
function handleClose(item){
selectedTagList.value = selectedTagList.value.filter(e => e.value != item.value)
proxy.$refs.inputRef.focus()
}
// 清空所有标签
function clearTags(){
currentSelectTag.value = {}
selectedTagList.value = []
proxy.$refs.inputRef.focus()
}
// 回车
function submitInput() {
if(!inputValue.value) return
// 如果没选中,说明是查默认的,比如第一条
if(!currentSelectTag.value.value){
selectedTagList.value = selectedTagList.value.filter(e => e.value != options.value[0].value)
selectedTagList.value.push({
value: options.value[0].value,
label: options.value[0].label,
text: inputValue.value
})
}else{
selectedTagList.value = selectedTagList.value.filter(e => e.value != currentSelectTag.value.value)
selectedTagList.value.push({
value: currentSelectTag.value.value,
label: currentSelectTag.value.label,
text: inputValue.value
})
}
inputValue.value = ''
currentSelectTag.value = {}
HiddenOptions()
}
</script>
<style lang="scss" scoped>
.SearchRow {
display: flex;
width: 380px;
border: 1px solid;
border-radius: 15px;
height: 22px;
padding: 5px;
float: left;
// overflow: hidden;
.selectTagCss{
white-space: nowrap;
margin-right: 10px;
height: 100%;
line-height: 100%;
.el-tag{
margin-left: 5px;
}
}
.currentSelectCss{
white-space: nowrap;
margin-top: 2px;
}
.inputAndOption{
position: relative;
z-index: 10000;
flex-grow: 1; // 占剩余部分的宽度
display: flex;
}
.input-text{
height: 100%;
border: none; /* 清除边框 */
outline: none; /* 清除在获得焦点时可能显示的外轮廓线 */
font-size: 16px;
width: 100%;
}
.clearTagCss{
cursor: pointer;
text-align: center;
width: 20px;
}
.optionsCSS{
position: absolute;
// width: 100%;
width: calc(100% - 10px);
background: #fff;
top: 28px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1), 0 8px 16px rgba(0, 0, 0, 0.1);
border-radius: 5px;
padding: 5px;
option{
padding: 5px 0 5px 5px;
}
option:hover{
background: #dfdfdf;
cursor: pointer;
}
}
}
</style>
我是写成了一个公共组件,还没写完,自己再把options换成prop里传过来的就可以了,每次submitInput的时候 把选择的selectedTagList 字段和text 返回给父级 就ok啦。父级拿到就直接掉接口