支持单选 和多选同时存在
一封装下拉框组件
<template><div ref="dropdownRef" class="drop_down" id="d1" v-click-outside="closeOrder"><divclass="cascade-input"@click="toggleDropdown":class="{ 'is-active': isDropdownVisible }"@mouseenter="mouseShowDelete"@mouseleave="noShowDelete"><span class="cascade_choose">{{ inputValue == "" ? "请选择" : inputValue }}</span><el-icon:class="{ 'is-rotate': isDropdownVisible }"class="down"v-if="!(inputValue != '' && isShowDelete)"><ArrowDown/></el-icon><el-icon v-if="inputValue != '' && isShowDelete" @click.stop="deleteInput"><CircleClose/></el-icon></div><div class="cascade-dropdown" v-if="isDropdownVisible"><div style="display: flex"><!-- 一级菜单 --><ul><liclass="cascade_item"v-for="(item, index) in cascadeType":key="index"@click="chooseType(item.field)":class="{ active: chooseTypeIndex == item.field }"><span class="cascade_item_name">{{ item.name }}</span><span class="cascade_item_name"><el-icon><ArrowRight /></el-icon></span></li></ul><!-- 二级菜单 --><div class="choose" v-show="isShowTwoMenu"><!-- 必选非必选 --><div class="choose_header"><ul><listyle="cursor: pointer"v-for="(item, index) in MustList"@click="changeMustTab(item.id)":key="index":class="{ 'is-must': isMust == item.id }">{{ item.name }}</li></ul></div><div class="choose_content"><!-- 系统字段 --><ul><template v-for="item in secondList" :key="item.id"><liv-if="!item.subImportField"style="cursor: pointer"@click="changeItem(item, true)":class="{'is-choose': isChooseIds.includes(item.id),disabled: item.disabled && !isChooseIds.includes(item.id)}">{{ item.name }}</li><template v-if="item.subImportField?.length > 0"><span class="links">以下联系方式至少选一种</span><liv-for="i in item.subImportField":key="i.id"style="cursor: pointer"@click="changeItem(i, false)":class="{'is-choose_list': isChooseIds.includes(i.id),disabled: i.disabled && !isChooseIds.includes(i.id)}">{{ i.name }}</li></template></template></ul></div><div class="choose_footer" @click="openCustomFields"> 新增自定义字段 </div></div></div></div></div><el-icon size="24" color="#52C41A" style="margin-left: 10px" v-if="inputValue != ''"><CircleCheckFilled/></el-icon><customFields ref="customFieldsRef" :visible="dialogVisible" @closeDialog="closeDialog" />
</template>
<script setup lang="ts">
import { ArrowDown, ArrowRight, CircleClose, CircleCheckFilled } from "@element-plus/icons-vue"
import { ClickOutside as vClickOutside } from "element-plus"
import customFields from "./customFields.vue"const props = defineProps({importType: {type: String,default: ""},code: {type: String,default: ""},customerSystemFields: {type: Array,default: () => []},contactSystemFields: {type: Array,default: () => []},customerNoMustFields: {type: Array,default: () => []},contactNoMustFields: {type: Array,default: () => []},followSystemFields: {type: Array,default: () => []},followNoMustFields: {type: Array,default: () => []},userSelectList: {type: Array,default: () => []}
})
const cascadeType = ref<any>([])
watch(() => props.importType,(nV: any, oV: any) => {console.log("props.importType1", nV)if (props.importType == "1") {cascadeType.value = [{field: "1",name: "客户"},{field: "2",name: "联系人"}]} else if (props.importType == "2") {cascadeType.value = [{field: "1",name: "客户"},{field: "2",name: "联系人"},{field: "3",name: "跟进记录"}]}},{immediate: true}
)/*** 切换*/
const isDropdownVisible = ref(false)//切换下拉框
const toggleDropdown = () => {isDropdownVisible.value = !isDropdownVisible.valueif (!isDropdownVisible.value && inputValue.value === "") {isShowTwoMenu.value = falsechooseTypeIndex.value = null}//回显选中数据,并跳转到指定位置if (isDropdownVisible.value) {if (inputValue.value) {chooseTypeIndex.value = selectImportType.valueisMust.value = tabType.valuegetSecondListByTab(tabType.value, selectImportType.value)elScrollIntoView()}}
}// 滚动到选中位置
const elScrollIntoView = async () => {await nextTick()const element =document.querySelectorAll(".is-choose_list")[0] || document.querySelectorAll(".is-choose")[0]if (element) {element.scrollIntoView({ block: "end" })}
}const closeOrder = () => {emit("updateSelectFields", props.code, isChooseItem.value)isDropdownVisible.value = false
}//切换类型
const chooseTypeIndex = ref<any>(null)
//展示二级菜单
const isShowTwoMenu = ref(false)const secondList = ref<any>([])
const chooseType = (field: any) => {chooseTypeIndex.value = fieldisShowTwoMenu.value = trueisMust.value = "1"// 获取二级菜单数据 必须数据getSecondList(field)
}// 获取二级菜单数据 必须数据
const getSecondList = (type: any) => {switch (type) {case "1":secondList.value = props.customerSystemFields || []breakcase "2":secondList.value = props.contactSystemFields || []breakcase "3":secondList.value = props.followSystemFields || []break}
}// 是不是展示删除按钮
const isShowDelete = ref(false)
const mouseShowDelete = () => {isShowDelete.value = true
}
const noShowDelete = () => {isShowDelete.value = false
}//删除input数据
const deleteInput = () => {inputValue.value = ""isChooseIds.value = []isChooseItem.value = []emit("updateSelectFields", props.code, isChooseItem.value)isDropdownVisible.value = false
}//展示input结果
const inputValue = ref("")
const emit = defineEmits(["updateSelectFields"])/*** 单选*/const isChooseItem = ref<any>([])
const isChooseIds = ref<any>([])
//选中的一级菜单
const selectImportType = ref("")
const tabType = ref("")
const changeItem = (item: any, flag: boolean) => {if (flag) {//单选//禁用不允许点击if (item.disabled) {return}isChooseItem.value = [{ id: item.id, name: item.name, flag: flag }]} else {//多选//禁用不允许点击if (item.disabled && !isChooseIds.value.includes(item.id)) {return}//排除单选isChooseItem.value = isChooseItem.value.filter((e: any) => !e.flag)let ids = isChooseItem.value.map((j: any) => j.id)//点击可以多选if (ids.includes(item.id)) {isChooseItem.value = isChooseItem.value.filter((j: any) => j.id !== item.id)} else {isChooseItem.value.push({ id: item.id, name: item.name, flag: flag })}}emit("updateSelectFields", props.code, isChooseItem.value)//回显数据位置selectImportType.value = item.importTypetabType.value = isMust.value//回显input数据inputValue.value = ""if (isChooseItem.value.length > 0) {let list: any = []isChooseItem.value.forEach((e: any) => list.push(e.name))isChooseIds.value = isChooseItem.value.map((i: any) => i.id)inputValue.value = list.join(",")} else {inputValue.value = ""isChooseIds.value = []}//单选选择后直接关闭弹框if (flag) {isDropdownVisible.value = false}
}/*** 多选*/
// const isChooseItemList = ref<any>([])
// const changeItemList = (item: any) => {
// //禁用
// if (item.disabled) {
// return
// }
// //多选清除单选选项
// if (isChooseItem.value != "") {
// isChooseItem.value = ""
// }
// emit("updateSelectFields", item.id, false)
// //多选
// if (isChooseItemList.value.includes(item.id)) {
// isChooseItemList.value = isChooseItemList.value.filter((j: any) => j !== item.id)
// } else {
// isChooseItemList.value.push(item.id)
// }
// //回显input数据
// if (isChooseItemList.value.length > 0) {
// let list: any = []
// secondList.value.forEach((item: any) => {
// if (item.subImportField?.length > 0) {
// item.subImportField.forEach((i: any) => {
// if (isChooseItemList.value.includes(i.id)) {
// list.push(i.name)
// }
// })
// }
// })
// inputValue.value = list.join(",")
// } else {
// inputValue.value = ""
// }
// }// 切换必须非必选
const isMust = ref<any>("1")
const MustList = ref([{name: "必须",id: "1"},{name: "非必须",id: "2"}
])
const changeMustTab = (id) => {isMust.value = idgetSecondListByTab(id, chooseTypeIndex.value)
}const getSecondListByTab = (id, chooseTypeIndex) => {if (chooseTypeIndex == "1") {switch (id) {case "1":secondList.value = props.customerSystemFieldsbreakcase "2":secondList.value = props.customerNoMustFieldsbreak}} else if (chooseTypeIndex == "2") {switch (id) {case "1":secondList.value = props.contactSystemFieldsbreakcase "2":secondList.value = props.contactNoMustFieldsbreak}} else if (chooseTypeIndex == "3") {switch (id) {case "1":secondList.value = props.followSystemFieldsbreakcase "2":secondList.value = props.followNoMustFieldsbreak}}
}// 打开自定义弹框
const dialogVisible = ref(false)
const openCustomFields = () => {dialogVisible.value = true
}
const closeDialog = () => {dialogVisible.value = false
}
</script>
<style scoped lang="scss">
.drop_down {position: relative;width: 80%;.cascade-input {height: 40px;padding: 0px 12px;border: 1px solid #ccc;border-radius: 4px;cursor: pointer;user-select: none;display: flex;justify-content: space-between;align-items: center;position: relative;.cascade_choose {color: #333333;font-size: 16px;font-weight: 400;}}.cascade-input.is-active {border-color: #409eff;}.down {transition: all 0.4s;}.is-rotate {transform: rotate(180deg);}.cascade-dropdown {position: absolute;top: 40px;left: 0px;z-index: 99;display: inline-block;box-shadow: 0 2px 9px 0 #c8c9cc80;height: 291px;background: #fff;border-radius: 2px;border: 1px solid #ebedf0;border-radius: 4px;margin-top: 4px;.active {background: #f7f8fa;}.cascade_item {width: 240px;height: 36px;display: flex;justify-content: space-between;align-items: center;padding: 0px 12px;cursor: pointer;.cascade_item_name {color: #323233;font-size: 14px;font-weight: 400;}}.choose {width: 240px;height: 291px;border-left: 1px solid #dcdfe6;position: relative;display: flex;flex-direction: column;.choose_header {width: 100%;ul {display: flex;height: 36px;line-height: 36px;border-bottom: 1px solid #dedede;box-sizing: border-box;padding-left: 10px;li {margin-right: 20px;color: #323233;font-size: 14px;font-weight: 500;&:hover {cursor: pointer;}}}.is-must {color: #477fff;border-bottom: 1px solid #477fff;}}.choose_content {// padding-left: 12px;flex: 1;overflow: auto;margin-bottom: 40px;ul {li {height: 32px;line-height: 32px;padding-left: 12px;}.is-choose {background: #f7f8fa;color: black !important;}.is-choose_list {background: #f7f8fa;color: black !important;}.disabled {color: #bebebe;cursor: not-allowed !important;}}.links {color: #477fff;font-size: 12px;font-family: "苹方";padding: 5px 0px 5px 12px;}}.choose_footer {position: absolute;left: 0;bottom: 0;width: 92%;height: 40px;line-height: 40px;text-align: center;border-top: 1px solid #dcdfe6;color: #477fff;font-size: 14px;font-weight: 400;margin: 0px 10px;}}}
}
</style>
二 使用
<table border width="100%" class="match_table"><thead><tr class="match_tr match_thead"><td class="march_th_left">Excel 字段</td><td class="march_th_right">系统字段</td></tr></thead><tbody><tr v-for="item in excelFields" :key="item.code" class="match_tr"><td class="march_th_left"> {{ item.name }}</td><td class="march_th_right"><fieldSelect:importType="props.importType":customerSystemFields="customerSystemFields":customerNoMustFields="customerNoMustFields":contactSystemFields="contactSystemFields":contactNoMustFields="contactNoMustFields":followSystemFields="followSystemFields":followNoMustFields="followNoMustFields"@update-select-fields="updateSelectFields":code="item.code"/></td></tr></tbody></table>const updateSelectFields = (code, value) => {userSelectList.value = []everySelectList.value[code] = valuefor (let key in everySelectList.value) {let list = everySelectList.value[key]userSelectList.value = Array.from(new Set([...userSelectList.value, ...list]))}let data = userSelectList.value.map((e: any) => {return e.id})updateMatchs(everySelectList.value)// 更新系统字段数据禁用let allFieldsif (props.importType == "1") {allFields = [...customerSystemFields.value,...customerNoMustFields.value,...contactSystemFields.value,...contactNoMustFields.value]} else if (props.importType == "2") {allFields = [...customerSystemFields.value,...customerNoMustFields.value,...contactSystemFields.value,...contactNoMustFields.value,...followSystemFields.value,...followNoMustFields.value]}// if (ismust == 1) {allFields.forEach((item) => {if (item.subImportField) {item.subImportField.forEach((item1) => {if (data.includes(item1.id)) {item1.disabled = true} else {item1.disabled = false}})} else {if (data.includes(item.id)) {item.disabled = true} else {item.disabled = false}}})// } else {contactSystemFields.value.forEach((item) => {if (data.includes(item.id)) {item.disabled = true} else {item.disabled = false}})// }
}const getSystemFields = () => {//客户customerSystemFields.value = [{name: "称谓",id: 21,importType: "1"},{name: "生日",id: 22,importType: "1"},{name: "生日",id: 221,importType: "1"},{name: "生日",id: 222,importType: "1"},{name: "生日",id: 223,importType: "1"},{name: "生日",id: 224,importType: "1"},{name: "生日",id: 225,importType: "1"},{name: "联系方式",id: 23,subImportField: [{name: "邮箱",id: 24,importType: "1"},{name: "手机",id: 25,importType: "1"},{name: "电话",id: 26,importType: "1"},{name: "电话",id: 27,importType: "1"},{name: "电话",id: 28,importType: "1"},{name: "电话",id: 29,importType: "1"},{name: "电话",id: 30,importType: "1"}]}]customerNoMustFields.value = [{name: "域名",id: 31,importType: "1"},{name: "意向客户",id: 32,importType: "1"}]contactSystemFields.value = [{name: "传真",id: 11,importType: "2"},{name: "职务",id: 12,importType: "2"}]contactNoMustFields.value = [{name: "部门",id: 41,importType: "2"},{name: "职务",id: 42,importType: "2"}]followSystemFields.value = [{name: "跟进时间",id: 51,importType: "3"},{name: "跟进方式",id: 52,importType: "3"}]followNoMustFields.value = [{name: "跟进状态",id: 61,importType: "3"}]
}