Files
income_payments_client/src/components/jero/JTreeSelect.vue
T
2021-09-03 19:27:41 +08:00

339 lines
9.0 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div>
<a-tree-select
v-if="isAsync"
allowClear
tree-node-filter-prop="title"
:getPopupContainer="(node) => node.parentNode"
style="width: 100%"
:disabled="disabled"
:dropdownStyle="{ maxHeight: '400px', overflow: 'auto' }"
:placeholder="placeholder"
:loadData="asyncLoadTreeData"
:value="treeValue"
:treeData="treeData"
:multiple="multiple"
:show-search="!multiple"
v-bind="_attrs"
v-on="childListeners"
@change="onChange">
</a-tree-select>
<a-tree-select
v-if="!isAsync"
allowClear
tree-node-filter-prop="title"
:getPopupContainer="(node) => node.parentNode"
style="width: 100%"
:disabled="disabled"
:dropdownStyle="{ maxHeight: '400px', overflow: 'auto' }"
:placeholder="placeholder"
:value="treeValue"
:treeData="treeData"
:multiple="multiple"
:show-search="!multiple"
v-bind="_attrs"
v-on="$listeners"
@change="onChange">
</a-tree-select>
</div>
</template>
<script>
/*
* 异步树加载组件 通过传入表名 显示字段 存储字段 加载一个树控件
* <j-tree-select dict="aa_tree_test,aad,id" pid-field="pid" ></j-tree-select>
* */
import { getAction } from '@/api/manage'
export default {
name: 'JTreeSelect',
props: {
isAsync:{ // 是否采用异步方式初始化树
type:Boolean,
required:false,
default:true
},
value:{
// type: String,
required: false
},
placeholder:{
type: String,
default: '请选择',
required: false
},
dict:{
type: String,
default: '',
required: false
},
pidField:{
type: String,
default: 'pid',
required: false
},
pidValue:{
type: String,
default: '',
required: false
},
disabled:{
type:Boolean,
default:false,
required:false
},
hasChildField:{
type: String,
default: '',
required: false
},
condition:{
type:String,
default:'',
required:false
},
// 是否支持多选
multiple: {
type: Boolean,
default: false,
},
loadTriggleChange:{
type: Boolean,
default: false,
required:false
}
},
data () {
return {
treeValue: null, // 选中的数据
treeData:[],// 渲染树的数组
url:'/sys/dict/loadTreeData',
view:'/sys/dict/loadDictItem/',
tableName:'',
text:'',
code:'',
}
},
watch: {
value () {
this.loadItemByCode()
},
dict(){
this.initDictInfo()
this.loadRoot()
}
},
computed:{
_attrs() {
let attrs
attrs = { ...this.$attrs }
return attrs
},
//透传给下级组件的事件,需要排除本组件使用的change事件
childListeners() {
const vm = this
let result = Object.assign({},
this.$listeners,
)
delete result.change
return result
}
},
created(){
this.validateProp().then(()=>{
this.initDictInfo()
this.loadRoot()
this.loadItemByCode()
})
},
mounted(){
window.that = this
},
methods: {
loadItemByCode(){
if( !this.value || this.value == '0' ){
this.treeValue = null
}else{
getAction(`${this.view}${this.dict}`,{key:this.value}).then(res=>{
if(res.success){
let values = this.value.split(',')
this.treeValue = values // v-model接收的是string || string[]
//将节点名称显示在选择框上
this.treeValue = res.result[0]
this.onLoadTriggleChange(res.result[0])
}
})
}
},
onLoadTriggleChange(text){
//只有单选才会触发
if(!this.multiple && this.loadTriggleChange){
this.$emit('change', this.value,text)
}
},
initDictInfo(){ //取出父组件传过来的codetexttableName
let arr = this.dict.split(',')
this.tableName = arr[0]
this.text = arr[1]
this.code = arr[2]
},
//异步加载树节点
asyncLoadTreeData (treeNode) {
return new Promise((resolve) => {
if (treeNode.$vnode.children) {
resolve()
return
}
let pid = treeNode.$vnode.key
let param = {
pid:pid,
tableName:this.tableName,
text:this.text,
code:this.code,
pidField:this.pidField,
hasChildField:this.hasChildField,
condition:this.condition
}
getAction(this.url,param).then(res=>{
if(res.success){
for(let i of res.result){
i.value = i.key
if(i.leaf==false){
i.isLeaf=false
}else if(i.leaf==true){
i.isLeaf=true
}
}
this.addChildren(pid,res.result,this.treeData)
this.treeData = [...this.treeData]
}
resolve()
})
})
},
addChildren(pid,children,treeArray){
if(treeArray && treeArray.length>0){
for(let item of treeArray){
if(item.key == pid){ //找到当前元素所在的父节点
if(!children || children.length==0){
item.isLeaf=true
}else{
item.children = children // 搜索出来的children添加到原树子children
}
break
}else{
this.addChildren(pid,children,item.children)
}
}
}
},
/**
* 初始化树
* isAsynctrue===异步获取 false===同步获取数据 默认异步*/
loadRoot(){
if (this.isAsync){
let param = {
pid:this.pidValue,
tableName:this.tableName,
text:this.text,
code:this.code,
pidField:this.pidField,
hasChildField:this.hasChildField,
condition:this.condition
}
getAction(this.url,param).then(res=>{
if(res.success && res.result){
for(let i of res.result){
i.value = i.key
if(i.leaf==false){
i.isLeaf=false
}else if(i.leaf==true){
i.isLeaf=true
}
}
this.treeData = [...res.result]
}else{
console.log('数根节点查询结果-else',res)
}
})
}else{
//同步
let param = {
code:this.code,
pidField:this.pidField,
tableName:this.tableName,
text:this.text
}
getAction('/sys/dict/queryAllTreeData',param).then((res)=>{
if (res.success){
this.treeData = deepFor(res.result)
}
})
}
},
onChange(value){
if(!value){
/*
* 使用$listeners向上暴露事件---和$emit一起使用出现的问题:change事件会执行两遍
* 解决办法:改变选中时提交的事件名*/
this.$emit('change', '')
this.treeValue = null
} else if (value instanceof Array) {
//多选
this.$emit('change', value.join(',').toString()) //修改第一次选中时,选中为空的情况
this.treeValue = value
} else {
//单选
this.$emit('change', value)
this.treeValue = value
}
},
getCurrTreeData(){
return this.treeData
},
validateProp(){
let myCondition = this.condition
return new Promise((resolve,reject)=>{
if(!myCondition){
resolve()
}else{
try {
let test=JSON.parse(myCondition)
if(typeof test == 'object' && test){
resolve()
}else{
this.$message.error('组件JTreeSelect-condition传值有误,需要一个json字符串!')
reject()
}
} catch(e) {
this.$message.error('组件JTreeSelect-condition传值有误,需要一个json字符串!')
reject()
}
}
})
}
},
//2.2新增 在组件内定义 指定父组件调用时候的传值属性和事件类型
model: {
prop: 'value',
event: 'change'
}
}
//递归整个树,判断是否是叶子节点----同步获取数据时用到
function deepFor(source){
for(let i of source){
i.value = i.key
if(i.leaf==false){
i.isLeaf=false
}else if(i.leaf==true){
i.isLeaf=true
}
if (i.children && i.children.length > 0){
deepFor(i.children)
}
}
return source
}
</script>