190 lines
4.1 KiB
Vue
190 lines
4.1 KiB
Vue
<!--树形结构的多选组件,value-所选树形结构体的id的集合; text所选树形结构名字-->
|
||
<template>
|
||
<div>
|
||
<van-field
|
||
v-bind="$attrs"
|
||
readonly
|
||
clearable
|
||
@click="showPopup"
|
||
v-model="showValue"
|
||
rows="1"
|
||
autosize
|
||
type="textarea"
|
||
/>
|
||
<van-popup
|
||
v-model="show"
|
||
style="height: 60vh"
|
||
position="bottom"
|
||
safe-area-inset-bottom
|
||
:close-on-click-overlay="false"
|
||
:close-on-popstate="true"
|
||
>
|
||
<div class="popup-box">
|
||
<div class="operate">
|
||
<span @click="cancel">取消</span>
|
||
<span @click="handleOk">确认</span>
|
||
</div>
|
||
|
||
<link-menu
|
||
:data="list"
|
||
value-key="key"
|
||
label-key="title"
|
||
:value="selectedDepartTemp"
|
||
@input="selected"
|
||
:multiple="multiple"
|
||
></link-menu>
|
||
</div>
|
||
</van-popup>
|
||
</div>
|
||
</template>
|
||
|
||
<script>
|
||
import LinkMenu from './LinkMenu'
|
||
|
||
export default {
|
||
name: 'TreeSelectMultiple',
|
||
components: {
|
||
LinkMenu
|
||
},
|
||
props: {
|
||
value: {
|
||
type: [Object, Array, String],
|
||
required: true,
|
||
default: () => []
|
||
},
|
||
list: {
|
||
type: Array,
|
||
default: () => []
|
||
},
|
||
readonly: {
|
||
type: Boolean,
|
||
required: false,
|
||
default: false
|
||
},
|
||
// 是否多选 默认是true
|
||
multiple: {
|
||
type: Boolean,
|
||
required: false,
|
||
default: true
|
||
}
|
||
},
|
||
watch: {
|
||
value: {
|
||
immediate: true,
|
||
deep: true,
|
||
handler () {
|
||
this.handleInitData()
|
||
}
|
||
},
|
||
|
||
list: {
|
||
immediate: true,
|
||
deep: true,
|
||
handler () {
|
||
this.handleInitData()
|
||
}
|
||
}
|
||
},
|
||
computed: {
|
||
// 当前显示的部门名称的字符串
|
||
showValue () {
|
||
if (this.multiple) {
|
||
return this.selectedDepart.map(tt => tt.title).join(',')
|
||
} else {
|
||
return this.selectedDepart.title
|
||
}
|
||
}
|
||
},
|
||
data () {
|
||
return {
|
||
show: false, // 控制popup的显示隐藏
|
||
selectedDepart: [], // 选中的部门
|
||
selectedDepartTemp: [], // 选中的部门暂存 多选的时候是数组,单选的时候是对象
|
||
confirm: false // 是否点击了确认
|
||
}
|
||
},
|
||
methods: {
|
||
cancel () {
|
||
this.show = false
|
||
},
|
||
handleOk () {
|
||
if (this.multiple) {
|
||
this.$emit('input', this.selectedDepartTemp.map(tt => tt.key))
|
||
} else {
|
||
this.$emit('input', [this.selectedDepartTemp.key])
|
||
}
|
||
this.show = false
|
||
},
|
||
// 弹出层显示
|
||
showPopup () {
|
||
if (this.readonly) return
|
||
this.selectedDepartTemp = JSON.parse(JSON.stringify(this.selectedDepart))
|
||
this.show = true
|
||
},
|
||
selected (val) {
|
||
// 先临时转换
|
||
this.selectedDepartTemp = JSON.parse(JSON.stringify(val))
|
||
},
|
||
// 初始化数据,将id的形式转成所有对象的形式
|
||
handleInitData () {
|
||
const selectedDepart = []
|
||
this.findSelectedItemByKey(this.list, selectedDepart)
|
||
if (this.multiple) {
|
||
this.selectedDepart = [...selectedDepart]
|
||
} else {
|
||
this.selectedDepart = selectedDepart.length > 0 ? selectedDepart[0] : {}
|
||
}
|
||
},
|
||
// 循环遍历数据进行 选中的判断
|
||
findSelectedItemByKey (arr, result) {
|
||
arr.forEach(item => {
|
||
if (this.value.includes(item.key)) {
|
||
result.push(item)
|
||
}
|
||
if (item.children && item.children.length > 0) {
|
||
this.findSelectedItemByKey(item.children, result)
|
||
}
|
||
})
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style scoped lang="less">
|
||
@import '~@assets/less/common.less';
|
||
|
||
.wrap {
|
||
display: flex;
|
||
flex-direction: column;
|
||
padding: 0 @pad-base;
|
||
box-sizing: border-box;
|
||
height: 100%;
|
||
}
|
||
|
||
// 解决线上滚动条不灵敏的bug
|
||
.popup-box{
|
||
height: 100%;
|
||
position: relative;
|
||
/deep/& > .list-menu {
|
||
height: calc(100% - 0.8rem);
|
||
overflow: auto;
|
||
}
|
||
}
|
||
|
||
.operate {
|
||
padding: 0 @pad-base;
|
||
box-sizing: border-box;
|
||
font-size: 0.3rem;
|
||
font-weight: 600;
|
||
height: 0.8rem;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
}
|
||
|
||
.content {
|
||
width: 100%;
|
||
flex: 1;
|
||
}
|
||
</style>
|