<template>
<div
ref="select"
@mousedown="
(e) => {
e.preventDefault();
handleClickLink();
selectData.selectOpen = true;
}
"
>
<a-select
id="selectCheck"
:allowClear="allowClear"
:disabled="disabled"
dropdownClassName="select"
:maxTagCount="maxTagCount"
:mode="mode"
:placeholder="placeholder"
v-model:value="selectData.selectValue"
:options="options"
:getPopupContainer="() => $refs.select"
@change="changeSelect"
@focus="focusSelect"
@blur="blurSelect"
:open="selectData.selectOpen"
>
<template #dropdownRender>
<a-tabs
v-model:activeKey="selectData.activeKey"
tab-position="left"
@change="handleClickLink"
>
<a-tab-pane v-for="item in selectData.options" :key="item.value">
<template #tab>
<span class="left-title"> {{ item.label }}</span>
</template>
<a-checkbox-group
v-model:value="selectData.checkbox"
:options="item.children"
@change="checkboxChange"
>
</a-checkbox-group>
<div>
<a-input
v-model:value="selectData.addValue"
placeholder="请输入自定义项"
:maxlength="selectData.inputMaxlength"
v-if="selectData.add"
@click.stop="
(e) => {
e.target.focus();
}
"
@focus="focusInput"
@blur="blurInput"
/>
<a-button
type="dashed"
@click.stop="selectData.add = true"
v-if="!selectData.add"
>+ Add</a-button
>
<a-button type="primary" @click.stop="addItem" v-if="selectData.add"
>确定</a-button
>
</div>
</a-tab-pane>
</a-tabs>
</template>
</a-select>
</div>
</template>
<script>
import { reactive, onMounted, inject,watch } from "vue";
export default {
name: "",
emits: ["selectValue"],
props: {
// 是否支持清除
allowClear: {
type: Boolean,
default: false,
},
// 是否禁用
disabled: {
type: Boolean,
default: false,
},
// 最多显示多少个 tag
maxTagCount: {
type: Number,
// default: 10,
},
// 设置 Select 的模式为多选或标签
mode: {
type: String,
default: "multiple", // 'multiple' | 'tags' | 'combobox'
},
// 选择框默认文字
placeholder: {
type: String,
default: "请选择",
},
// 下拉选项
options: {
type: Array,
default: () => {
return [];
},
},
// 已选择的选项
selectValue: {
type: Array,
default: () => {
return [];
},
},
// 输入框限制位数
inputMaxlength: {
type: Number,
default: 6,
},
},
components: {},
setup(props, { emit }) {
const message = inject("$message");
//数据
const selectData = reactive({
selectValue: [],
activeKey: "",
activeKeyVal: "", // 一级菜单初始化值
options: [],
checkbox: [],
add: false,
addValue: "",
selectClass: "",
selectOpen: false,
inputMaxlength: 0,
isSelectFocus:false,
isInputFocus:false,
});
// #region 监听区间 生命周期
onMounted(async () => {
selectData.options = props.options;
selectData.activeKeyVal = selectData.options[0].value;
selectData.activeKey = selectData.activeKeyVal;
selectData.selectValue = props.selectValue;
selectData.inputMaxlength = props.inputMaxlength;
});
watch(
() => selectData.selectOpen,
(newVal, oldVal) => {
if(newVal){
selectData.add = false;
selectData.addValue = "";
selectData.activeKey = selectData.activeKeyVal;// 默认一级选中第一个
return;
}
}
);
watch(
() => selectData.activeKey,
(newVal, oldVal) => {
if(newVal !== oldVal){
selectData.add = false;
selectData.addValue = "";
return;
}
}
);
// #endregion
/**
* @description: Add
* @return {*}
*/
const addItem = () => {
let arr = [];
if (selectData.addValue) {
selectData.options.forEach((item) => {
arr.push(item.value);
item.children.forEach((it) => {
arr.push(it.value);
});
});
if (arr.indexOf(selectData.addValue) !== -1) {
message.warning("输入项重复,请重新输入");
} else {
selectData.options.forEach((item) => {
if (selectData.activeKey === item.value) {
item.children.push({
value: `${selectData.addValue}`,
label: `${selectData.addValue}`,
});
}
});
selectData.add = false;
selectData.addValue = "";
document.getElementById("selectCheck").focus();
}
} else {
message.warning("请输入自定义项");
}
};
/**
* @description: 点击一级选项
* @return {*}
*/
const handleClickLink = () => {
document.getElementById("selectCheck").focus();
selectData.checkbox = [];
selectData.options.forEach((item) => {
if (selectData.activeKey === item.value) {
item.children.forEach((it) => {
if (selectData.selectValue.indexOf(it.value) !== -1) {
selectData.checkbox.push(it.value);
}
});
}
});
};
/**
* @description: 点击二级选项
* @param {*} val 当前选中的值
* @return {*}
*/
const checkboxChange = (val) => {
selectData.add = false;
selectData.addValue = "";
document.getElementById("selectCheck").focus();
if (val.length > 0) {
selectData.options.forEach((item) => {
if (selectData.activeKey === item.value) {
item.children.forEach((it) => {
if (val.indexOf(it.value) === -1) {
if (selectData.selectValue.indexOf(it.value) !== -1) {
selectData.selectValue.splice(
selectData.selectValue.indexOf(it.value),
1
);
}
return;
}
});
return;
}
});
val.forEach((item) => {
if (selectData.selectValue.indexOf(item) === -1) {
selectData.selectValue.push(item);
return;
}
});
} else {
selectData.options.forEach((item) => {
if (item.value === selectData.activeKey) {
item.children.forEach((it) => {
if (selectData.selectValue.indexOf(it.value) !== -1) {
selectData.selectValue.splice(
selectData.selectValue.indexOf(it.value),
1
);
}
});
return;
}
});
}
};
/**
* @description: 选中 option 时
* @return {*}
*/
const changeSelect = () => {
handleClickLink();
emit("selectValue", selectData.selectValue);
};
/**
* @description: 下拉框获得焦点时回调
* @return {*}
*/
const focusSelect = () => {
selectData.isSelectFocus = true;
handleClickLink();
};
/**
* @description: 下拉框失去焦点的时回调
* @return {*}
*/
const blurSelect = () => {
emit("selectValue", selectData.selectValue);
selectData.isSelectFocus = false;
if(!selectData.isSelectFocus && !selectData.isInputFocus){
selectData.selectOpen = false;
}else{
selectData.selectOpen = true;
}
};
/**
* @description: 输入框获得焦点时回调
* @return {*}
*/
const focusInput = () => {
selectData.isInputFocus = true;
};
/**
* @description: 输入框失去焦点时回调
* @return {*}
*/
const blurInput = () => {
selectData.isInputFocus = false;
if(!selectData.isSelectFocus && !selectData.isInputFocus){
selectData.selectOpen = false;
}else{
selectData.selectOpen = true;
}
};
return {
//变量
selectData,
//事件
addItem,
checkboxChange,
handleClickLink,
changeSelect,
blurSelect,
focusSelect,
focusInput,
blurInput,
};
},
};
</script>
<style lang="less" scoped>
.ant-select {
width: 300px !important;
}
/deep/.select {
// display: block !important;
.ant-tabs {
.ant-tabs-tab {
margin: 0;
padding-right: 16px;
&::after {
display: inline-block;
content: ">";
margin-left: 30px;
}
}
.ant-tabs-ink-bar {
display: none !important;
}
.ant-tabs-left-content {
padding-left: 10px;
.ant-input {
width: 122px;
}
}
}
.ant-checkbox-group {
display: flex;
flex-direction: column;
.ant-checkbox-group-item {
margin: 8px;
}
}
.ant-btn {
margin-left: 4px;
font-size: 12px;
}
}
</style>
03-07
4937

03-10
4713

07-15