1109 lines
33 KiB
Vue
1109 lines
33 KiB
Vue
|
<template>
|
|||
|
<view class="da-tree" :style="{'--theme-color': themeColor}">
|
|||
|
<scroll-view class="da-tree-scroll" :scroll-y="true" :scroll-x="false">
|
|||
|
<view
|
|||
|
class="da-tree-item"
|
|||
|
:class="{'is-show': item.show}"
|
|||
|
:style="{paddingLeft: item.level * indent + 'rpx'}"
|
|||
|
v-for="item in datalist"
|
|||
|
:key="item.key">
|
|||
|
<view
|
|||
|
v-if="item.showArrow"
|
|||
|
class="da-tree-item__icon"
|
|||
|
@click="handleExpandedChange(item)">
|
|||
|
<view :class="['da-tree-item__icon--arr','is-loading']" v-if="loadLoading && item.loading"></view>
|
|||
|
<view :class="['da-tree-item__icon--arr','is-expand', {'is-right':!item.expand}]" v-else></view>
|
|||
|
</view>
|
|||
|
<view v-else class="da-tree-item__icon"></view>
|
|||
|
<view
|
|||
|
class="da-tree-item__checkbox"
|
|||
|
:class="[`da-tree-item__checkbox--${checkboxPlacement}`,{'is--disabled': item.disabled}]"
|
|||
|
v-if="showCheckbox"
|
|||
|
@click="handleCheckChange(item)">
|
|||
|
<view class="da-tree-item__checkbox--icon da-tree-checkbox-checked" v-if="item.checkedStatus === isCheckedStatus"></view>
|
|||
|
<view class="da-tree-item__checkbox--icon da-tree-checkbox-indeterminate" v-else-if="item.checkedStatus === halfCheckedStatus"></view>
|
|||
|
<view class="da-tree-item__checkbox--icon da-tree-checkbox-outline" v-else></view>
|
|||
|
</view>
|
|||
|
<view
|
|||
|
class="da-tree-item__checkbox"
|
|||
|
:class="[`da-tree-item__checkbox--${checkboxPlacement}`,{'is--disabled': item.disabled}]"
|
|||
|
v-if="!showCheckbox && showRadioIcon"
|
|||
|
@click="handleRadioChange(item)">
|
|||
|
<view class="da-tree-item__checkbox--icon da-tree-radio-checked" v-if="item.checkedStatus === isCheckedStatus"></view>
|
|||
|
<view class="da-tree-item__checkbox--icon da-tree-radio-indeterminate" v-else-if="item.checkedStatus === halfCheckedStatus"></view>
|
|||
|
<view class="da-tree-item__checkbox--icon da-tree-radio-outline" v-else></view>
|
|||
|
</view>
|
|||
|
<view class="da-tree-item__label" :class="'da-tree-item__label--'+item.checkedStatus" @click="handleLabelClick(item)">{{ item.label }} <text class="da-tree-item__label--append" v-if="item.append">{{ item.append }}</text></view>
|
|||
|
</view>
|
|||
|
</scroll-view>
|
|||
|
</view>
|
|||
|
</template>
|
|||
|
|
|||
|
<script>
|
|||
|
import {
|
|||
|
unCheckedStatus,
|
|||
|
halfCheckedStatus,
|
|||
|
isCheckedStatus,
|
|||
|
deepClone,
|
|||
|
getAllNodeKeys,
|
|||
|
getAllNodes,
|
|||
|
logError,
|
|||
|
isArray,
|
|||
|
isString,
|
|||
|
isNumber,
|
|||
|
isFunction,
|
|||
|
} from './utils'
|
|||
|
import basicProps from './props'
|
|||
|
|
|||
|
export default {
|
|||
|
name: 'DaTree',
|
|||
|
props: basicProps,
|
|||
|
data() {
|
|||
|
return {
|
|||
|
unCheckedStatus,
|
|||
|
halfCheckedStatus,
|
|||
|
isCheckedStatus,
|
|||
|
/** 原始的树数据 */
|
|||
|
dataRef: [],
|
|||
|
/** 处理后的一维树项数据 */
|
|||
|
datalist: [],
|
|||
|
/** 处理后的以key为键值的树项数据 */
|
|||
|
datamap: {},
|
|||
|
/** 默认的展开数据 */
|
|||
|
expandedKeys: [],
|
|||
|
/** 默认的已选数据 */
|
|||
|
checkedKeys: null,
|
|||
|
/** 加载状态 */
|
|||
|
loadLoading: false,
|
|||
|
fieldMap: {
|
|||
|
value: 'value',
|
|||
|
label: 'label',
|
|||
|
children: 'children',
|
|||
|
disabled: 'disabled',
|
|||
|
append: 'append',
|
|||
|
leaf: 'leaf',
|
|||
|
sort: 'sort',
|
|||
|
},
|
|||
|
}
|
|||
|
},
|
|||
|
watch: {
|
|||
|
defaultExpandedKeys: {
|
|||
|
// deep: true,
|
|||
|
immediate: true,
|
|||
|
handler: function(v) {
|
|||
|
if (v?.length) {
|
|||
|
this.expandedKeys = v
|
|||
|
} else {
|
|||
|
this.expandedKeys = []
|
|||
|
}
|
|||
|
|
|||
|
// if (v) this.checkInitData(this.datalist)
|
|||
|
},
|
|||
|
},
|
|||
|
defaultCheckedKeys: {
|
|||
|
// deep: true,
|
|||
|
immediate: true,
|
|||
|
handler: function(v) {
|
|||
|
if (this.showCheckbox) {
|
|||
|
if (v?.length) {
|
|||
|
this.checkedKeys = v
|
|||
|
} else {
|
|||
|
this.checkedKeys = []
|
|||
|
}
|
|||
|
} else {
|
|||
|
if (v || v === 0) {
|
|||
|
this.checkedKeys = v
|
|||
|
} else {
|
|||
|
this.checkedKeys = null
|
|||
|
}
|
|||
|
}
|
|||
|
// this.checkInitData(this.datalist)
|
|||
|
},
|
|||
|
},
|
|||
|
data: {
|
|||
|
deep: true,
|
|||
|
immediate: true,
|
|||
|
handler: function(v) {
|
|||
|
this.dataRef = deepClone(v)
|
|||
|
setTimeout(() => {
|
|||
|
this.initData()
|
|||
|
}, 36)
|
|||
|
},
|
|||
|
},
|
|||
|
},
|
|||
|
methods: {
|
|||
|
/**
|
|||
|
* 初始化数据结构
|
|||
|
*/
|
|||
|
initData() {
|
|||
|
this.fieldMap = {
|
|||
|
value: this.field?.key || this.field?.value || this.valueField || 'value',
|
|||
|
label: this.field?.label || this.labelField || 'label',
|
|||
|
children: this.field?.children || this.childrenField || 'children',
|
|||
|
disabled: this.field?.disabled || this.disabledField || 'disabled',
|
|||
|
append: this.field?.append || this.appendField || 'append',
|
|||
|
leaf: this.field?.leaf || this.leafField || 'leaf',
|
|||
|
sort: this.field?.sort || this.sortField || 'sort',
|
|||
|
}
|
|||
|
|
|||
|
const data = deepClone(this.dataRef)
|
|||
|
this.datalist = []
|
|||
|
this.datamap = {}
|
|||
|
|
|||
|
// clean tree
|
|||
|
this.handleTreeData(data)
|
|||
|
// flat tree
|
|||
|
this.datalist = this.checkInitData(this.datalist)
|
|||
|
|
|||
|
console.log('init datalist', this.datalist)
|
|||
|
console.log('init datamap', this.datamap)
|
|||
|
},
|
|||
|
|
|||
|
/**
|
|||
|
* 转换为节点数据
|
|||
|
* @param data
|
|||
|
* @param parent
|
|||
|
* @param level
|
|||
|
*/
|
|||
|
handleTreeData(data = [], parent = null, level = 0, insertIndex = -1) {
|
|||
|
return data.reduce((prev, cur, index) => {
|
|||
|
const key = cur[this.fieldMap.value]
|
|||
|
const children = cur[this.fieldMap.children] || null
|
|||
|
const newItem = this.createNewItem(cur, index, parent, level)
|
|||
|
if (insertIndex > -1) {
|
|||
|
// 插入子项尾部
|
|||
|
const index = (parent.childrenKeys?.length || 0) + insertIndex + 1
|
|||
|
if (!parent?.childrenKeys?.includes(key)) {
|
|||
|
this.datamap[key] = newItem
|
|||
|
this.datalist.splice(index, 0, newItem)
|
|||
|
parent.children.push(newItem)
|
|||
|
if (newItem.parentKeys?.length) {
|
|||
|
newItem.parentKeys.forEach(k => {
|
|||
|
this.datamap[k].childrenKeys = [...this.datamap[k].childrenKeys, newItem.key]
|
|||
|
})
|
|||
|
}
|
|||
|
}
|
|||
|
} else {
|
|||
|
this.datamap[key] = newItem
|
|||
|
this.datalist.push(newItem)
|
|||
|
}
|
|||
|
|
|||
|
const hasChildren = children && children.length > 0
|
|||
|
if (hasChildren) {
|
|||
|
const childrenData = this.handleTreeData(children, newItem, level + 1)
|
|||
|
// childrenData.sort((a, b) => a.sort - b.sort)
|
|||
|
newItem.children = childrenData
|
|||
|
const childrenKeys = childrenData.reduce((p, k) => {
|
|||
|
const keys = k.childrenKeys
|
|||
|
p.push(...keys, k.key)
|
|||
|
return p
|
|||
|
}, [])
|
|||
|
newItem.childrenKeys = childrenKeys
|
|||
|
}
|
|||
|
prev.push(newItem)
|
|||
|
return prev
|
|||
|
}, [])
|
|||
|
},
|
|||
|
|
|||
|
/**
|
|||
|
* 创建节点
|
|||
|
* @param item
|
|||
|
* @param index
|
|||
|
* @param parent
|
|||
|
* @param level
|
|||
|
*/
|
|||
|
createNewItem(item, index, parent, level) {
|
|||
|
const key = item[this.fieldMap.value]
|
|||
|
const label = item[this.fieldMap.label]
|
|||
|
const sort = item[this.fieldMap.sort] || 0
|
|||
|
const children = item[this.fieldMap.children] || null
|
|||
|
const append = item[this.fieldMap.append] || null
|
|||
|
let disabled = item[this.fieldMap.disabled] || false
|
|||
|
// 优先继承父级禁用属性
|
|||
|
disabled = parent?.disabled || disabled
|
|||
|
let isLeaf = isFunction(this.isLeafFn) ? this.isLeafFn(item) : (item[this.fieldMap.leaf] || false)
|
|||
|
// const hasChildren = children && children.length > 0
|
|||
|
const isEmptyChildren = children && children.length === 0
|
|||
|
let showArrow = true
|
|||
|
// let isLeaf = !hasChildren
|
|||
|
let expand = this.defaultExpandAll || false
|
|||
|
// 是否异步加载模式
|
|||
|
const isLoadMode = this.loadMode && isFunction(this.loadApi)
|
|||
|
|
|||
|
if (!children) {
|
|||
|
expand = false
|
|||
|
if (isLoadMode) {
|
|||
|
showArrow = true
|
|||
|
} else {
|
|||
|
isLeaf = true
|
|||
|
showArrow = false
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (isEmptyChildren) {
|
|||
|
expand = false
|
|||
|
if (isLoadMode) {
|
|||
|
showArrow = true
|
|||
|
} else {
|
|||
|
isLeaf = true
|
|||
|
showArrow = false
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (isLeaf) {
|
|||
|
showArrow = false
|
|||
|
expand = false
|
|||
|
} else {
|
|||
|
showArrow = true
|
|||
|
}
|
|||
|
|
|||
|
// onlyRadioLeaf 单选只能选择末级节点
|
|||
|
if (!this.showCheckbox) {
|
|||
|
if (this.onlyRadioLeaf) {
|
|||
|
if (!isLeaf) {
|
|||
|
disabled = true
|
|||
|
} else {
|
|||
|
// 仍旧继承父类原始禁用状态
|
|||
|
disabled = parent?.originItem?.disabled || false
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (disabled) {
|
|||
|
if (isLeaf || !children || isEmptyChildren) {
|
|||
|
expand = false
|
|||
|
showArrow = false
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
const parentKey = parent ? parent.key : null
|
|||
|
const show = this.defaultExpandAll || level === 0
|
|||
|
|
|||
|
const newItem = {
|
|||
|
key,
|
|||
|
parentKey,
|
|||
|
label,
|
|||
|
append,
|
|||
|
isLeaf,
|
|||
|
showArrow,
|
|||
|
level,
|
|||
|
expand,
|
|||
|
show,
|
|||
|
sort,
|
|||
|
disabled,
|
|||
|
loaded: false,
|
|||
|
loading: false,
|
|||
|
indexs: [index],
|
|||
|
checkedStatus: unCheckedStatus,
|
|||
|
parentKeys: [],
|
|||
|
childrenKeys: [],
|
|||
|
children: [],
|
|||
|
originItem: item,
|
|||
|
}
|
|||
|
|
|||
|
if (parent) {
|
|||
|
newItem.parentKeys = [parent.key, ...parent.parentKeys]
|
|||
|
newItem.indexs = [...parent.indexs, index]
|
|||
|
}
|
|||
|
|
|||
|
return newItem
|
|||
|
},
|
|||
|
|
|||
|
/**
|
|||
|
* 处理初始化内容
|
|||
|
* @param list
|
|||
|
*/
|
|||
|
checkInitData(list) {
|
|||
|
let checkedKeyList = null
|
|||
|
let expandedKeyList = []
|
|||
|
if (this.showCheckbox) {
|
|||
|
checkedKeyList = [...new Set(this.checkedKeys || [])]
|
|||
|
expandedKeyList = this.expandChecked ? ([...(this.checkedKeys || []), ...(this.expandedKeys || [])]) : this.expandedKeys
|
|||
|
} else {
|
|||
|
checkedKeyList = this.checkedKeys || null
|
|||
|
expandedKeyList = this.expandChecked && this.checkedKeys ? ([this.checkedKeys, ...(this.expandedKeys || [])]) : this.expandedKeys
|
|||
|
}
|
|||
|
|
|||
|
this.handleCheckState(list, checkedKeyList, true)
|
|||
|
|
|||
|
// 处理初始展开
|
|||
|
expandedKeyList = [...new Set(expandedKeyList)]
|
|||
|
if (!this.defaultExpandAll) {
|
|||
|
this.handleExpandState(list, expandedKeyList, true)
|
|||
|
}
|
|||
|
|
|||
|
list.sort((a, b) => {
|
|||
|
if (a.sort === 0 && b.sort === 0) {
|
|||
|
return 0
|
|||
|
}
|
|||
|
|
|||
|
if (a.parentKey === b.parentKey) {
|
|||
|
if (a.sort - b.sort > 0) {
|
|||
|
return 1
|
|||
|
} else {
|
|||
|
return -1
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return 0
|
|||
|
})
|
|||
|
|
|||
|
return list
|
|||
|
},
|
|||
|
|
|||
|
/**
|
|||
|
* 处理选中
|
|||
|
* @param list
|
|||
|
* @param checkedKeyList
|
|||
|
*/
|
|||
|
handleCheckState(list, checkedKeyList, checked = true) {
|
|||
|
// 多选
|
|||
|
if (this.showCheckbox) {
|
|||
|
if (checkedKeyList?.length) {
|
|||
|
checkedKeyList.forEach(k => {
|
|||
|
const item = this.datamap[k]
|
|||
|
if (item) {
|
|||
|
this.checkTheChecked(item, checked)
|
|||
|
}
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// 单选
|
|||
|
for (let i = 0; i < list.length; i++) {
|
|||
|
const item = list[i]
|
|||
|
if (item.key === checkedKeyList) {
|
|||
|
// console.log('item.key === checkedKeyList', item.key, checkedKeyList)
|
|||
|
this.checkTheRadio(item, checked)
|
|||
|
break
|
|||
|
}
|
|||
|
}
|
|||
|
},
|
|||
|
|
|||
|
/**
|
|||
|
* 校验多选节点
|
|||
|
* @param item
|
|||
|
* @param checked
|
|||
|
*/
|
|||
|
checkTheChecked(item, checked = true) {
|
|||
|
const { childrenKeys, parentKeys, disabled = false } = item
|
|||
|
if (!this.checkedDisabled && disabled) return
|
|||
|
|
|||
|
// 当前
|
|||
|
item.checkedStatus = checked ? isCheckedStatus : unCheckedStatus
|
|||
|
|
|||
|
if (!this.checkStrictly) {
|
|||
|
// 子类
|
|||
|
childrenKeys.forEach(k => {
|
|||
|
const childrenItem = this.datamap[k]
|
|||
|
childrenItem.checkedStatus = (!this.checkedDisabled && childrenItem.disabled) ? childrenItem.checkedStatus : item.checkedStatus
|
|||
|
})
|
|||
|
|
|||
|
// 父类
|
|||
|
parentKeys.forEach(k => {
|
|||
|
const parentItem = this.datamap[k]
|
|||
|
parentItem.checkedStatus = this.getParentCheckedStatus(parentItem)
|
|||
|
})
|
|||
|
}
|
|||
|
},
|
|||
|
|
|||
|
/**
|
|||
|
* 校验单选节点
|
|||
|
* @param item
|
|||
|
*/
|
|||
|
checkTheRadio(item, checked) {
|
|||
|
const { parentKeys, isLeaf, disabled = false } = item
|
|||
|
if (!this.checkedDisabled && disabled) return
|
|||
|
|
|||
|
// 限制末节点选中,但当前非末节点
|
|||
|
if (this.onlyRadioLeaf && !isLeaf) {
|
|||
|
logError(`限制了末节点选中,当前[${item.label}]非末节点`)
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
if (this.datalist?.length) {
|
|||
|
this.datalist.forEach(k => {
|
|||
|
k.checkedStatus = unCheckedStatus
|
|||
|
})
|
|||
|
}
|
|||
|
console.log('000', item, parentKeys, this.datamap)
|
|||
|
|
|||
|
parentKeys.forEach(k => {
|
|||
|
console.log('kkk', k, this.datamap[k])
|
|||
|
const parentItem = this.datamap[k]
|
|||
|
parentItem.checkedStatus = checked ? this.getParentCheckedStatus(parentItem) : unCheckedStatus
|
|||
|
})
|
|||
|
|
|||
|
// 当前
|
|||
|
item.checkedStatus = checked ? isCheckedStatus : unCheckedStatus
|
|||
|
},
|
|||
|
|
|||
|
/**
|
|||
|
* 处理父节点展开
|
|||
|
* @param item
|
|||
|
* @param expand
|
|||
|
*/
|
|||
|
// handleExpandParentNode(item, expand = true) {
|
|||
|
// if (!expand) return
|
|||
|
|
|||
|
// if (item?.parentKeys?.length) {
|
|||
|
// item.parentKeys.forEach(pk => {
|
|||
|
// if (!this.datamap[pk].expand) {
|
|||
|
// this.datamap[pk].expand = true
|
|||
|
// }
|
|||
|
// })
|
|||
|
// }
|
|||
|
// },
|
|||
|
|
|||
|
/**
|
|||
|
* 处理节点展开
|
|||
|
* @param list
|
|||
|
* @param expandedKeyList
|
|||
|
* @param expand
|
|||
|
*/
|
|||
|
handleExpandState(list, expandedKeyList, expand = true) {
|
|||
|
// 收起
|
|||
|
if (expand === false) {
|
|||
|
for (let i = 0; i < list.length; i++) {
|
|||
|
const item = list[i]
|
|||
|
if (expandedKeyList?.includes(item.key)) {
|
|||
|
item.expand = false
|
|||
|
if (item.childrenKeys?.length) {
|
|||
|
item.childrenKeys.forEach(ck => {
|
|||
|
this.datamap[ck].expand = false
|
|||
|
this.datamap[ck].show = false
|
|||
|
})
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
return
|
|||
|
}
|
|||
|
// 展开
|
|||
|
for (let i = 0; i < list.length; i++) {
|
|||
|
const item = list[i]
|
|||
|
// 处理展开
|
|||
|
if (expandedKeyList?.includes(item.key)) {
|
|||
|
// 父子
|
|||
|
item.expand = true
|
|||
|
if (item.children?.length) {
|
|||
|
item.children.forEach(k => {
|
|||
|
const kItem = this.datamap[k.key]
|
|||
|
kItem.show = true
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
// 族系
|
|||
|
if (item.parentKeys?.length) {
|
|||
|
item.parentKeys.forEach(k => {
|
|||
|
const kItem = this.datamap[k]
|
|||
|
kItem.expand = true
|
|||
|
if (kItem.children?.length) {
|
|||
|
kItem.children.forEach(k => {
|
|||
|
const skItem = this.datamap[k.key]
|
|||
|
skItem.show = true
|
|||
|
})
|
|||
|
}
|
|||
|
})
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
},
|
|||
|
|
|||
|
/**
|
|||
|
* 点击选框
|
|||
|
* @param item
|
|||
|
*/
|
|||
|
handleCheckChange(item) {
|
|||
|
const { childrenKeys, parentKeys, checkedStatus, isLeaf, disabled = false } = item
|
|||
|
if (!this.showCheckbox) return
|
|||
|
if (disabled) return
|
|||
|
|
|||
|
// 当前
|
|||
|
item.checkedStatus = checkedStatus === isCheckedStatus ? unCheckedStatus : isCheckedStatus
|
|||
|
|
|||
|
// 子类
|
|||
|
if (!this.checkStrictly) {
|
|||
|
if (this.expandChecked) {
|
|||
|
item.show = true
|
|||
|
item.expand = childrenKeys?.length > 0 || isLeaf
|
|||
|
}
|
|||
|
|
|||
|
childrenKeys.forEach(k => {
|
|||
|
const childrenItem = this.datamap[k]
|
|||
|
childrenItem.checkedStatus = childrenItem.disabled ? childrenItem.checkedStatus : item.checkedStatus
|
|||
|
|
|||
|
if (this.expandChecked) {
|
|||
|
childrenItem.show = true
|
|||
|
childrenItem.expand = childrenItem?.childrenKeys?.length > 0 || childrenItem.isLeaf
|
|||
|
}
|
|||
|
})
|
|||
|
} else {
|
|||
|
if (this.expandChecked) {
|
|||
|
logError(`多选时,当 checkStrictly 为 true 时,不支持选择自动展开子节点属性(expandChecked)`)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// 父类
|
|||
|
if (!this.checkStrictly) {
|
|||
|
parentKeys.forEach(k => {
|
|||
|
const parentItem = this.datamap[k]
|
|||
|
parentItem.checkedStatus = this.getParentCheckedStatus(parentItem)
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
const hasCheckedKeys = []
|
|||
|
for (let i = 0; i < this.datalist.length; i++) {
|
|||
|
const k = this.datalist[i]
|
|||
|
if (k.checkedStatus === isCheckedStatus) {
|
|||
|
if ((this.packDisabledkey && k.disabled) || !k.disabled) {
|
|||
|
hasCheckedKeys.push(k.key)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
this.checkedKeys = [...hasCheckedKeys]
|
|||
|
|
|||
|
this.$emit('change', hasCheckedKeys, item)
|
|||
|
},
|
|||
|
|
|||
|
/**
|
|||
|
* 点击单选
|
|||
|
* @param item
|
|||
|
*/
|
|||
|
handleRadioChange(item) {
|
|||
|
const { parentKeys, checkedStatus, key, disabled = false, isLeaf } = item
|
|||
|
if (this.showCheckbox) return
|
|||
|
if (this.onlyRadioLeaf && !isLeaf) this.handleExpandedChange(item)
|
|||
|
|
|||
|
if (disabled) return
|
|||
|
|
|||
|
// 重置所有选择
|
|||
|
if (this.datalist?.length) {
|
|||
|
for (let i = 0; i < this.datalist.length; i++) {
|
|||
|
const k = this.datalist[i]
|
|||
|
k.checkedStatus = unCheckedStatus
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
parentKeys.forEach(k => {
|
|||
|
const parentItem = this.datamap[k]
|
|||
|
parentItem.checkedStatus = this.getParentCheckedStatus(parentItem)
|
|||
|
})
|
|||
|
|
|||
|
// 当前
|
|||
|
item.checkedStatus = checkedStatus === isCheckedStatus ? unCheckedStatus : isCheckedStatus
|
|||
|
|
|||
|
this.checkedKeys = key
|
|||
|
this.$emit('change', key, item)
|
|||
|
},
|
|||
|
|
|||
|
/**
|
|||
|
* 点击标签
|
|||
|
*/
|
|||
|
handleLabelClick(item) {
|
|||
|
if (this.showCheckbox) {
|
|||
|
this.handleCheckChange(item)
|
|||
|
} else {
|
|||
|
this.handleRadioChange(item)
|
|||
|
}
|
|||
|
},
|
|||
|
|
|||
|
/**
|
|||
|
* 点击展开收起
|
|||
|
* @param item
|
|||
|
*/
|
|||
|
async handleExpandedChange(item) {
|
|||
|
const { expand, loading = false, disabled } = item
|
|||
|
if (this.loadLoading && loading) return
|
|||
|
|
|||
|
this.checkExpandedChange(item)
|
|||
|
|
|||
|
// 异步
|
|||
|
item.expand = !expand
|
|||
|
|
|||
|
let currentItem = null
|
|||
|
if (!disabled) {
|
|||
|
if (!this.showCheckbox && this.onlyRadioLeaf && this.loadMode) {
|
|||
|
logError(`单选时,当 onlyRadioLeaf 为 true 时不支持动态数据`)
|
|||
|
} else {
|
|||
|
currentItem = await this.loadExpandNode(item)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
this.$emit('expand', !expand, currentItem || item || null)
|
|||
|
},
|
|||
|
|
|||
|
/**
|
|||
|
* 检查展开状态
|
|||
|
* @param item
|
|||
|
*/
|
|||
|
checkExpandedChange(item) {
|
|||
|
const { expand, childrenKeys, children = null } = item
|
|||
|
|
|||
|
if (expand) {
|
|||
|
if (childrenKeys?.length) {
|
|||
|
childrenKeys.forEach(k => {
|
|||
|
if (this.datamap[k]) {
|
|||
|
this.datamap[k].show = false
|
|||
|
this.datamap[k].expand = false
|
|||
|
}
|
|||
|
})
|
|||
|
}
|
|||
|
} else {
|
|||
|
if (children?.length) {
|
|||
|
const childrenKeys = children.map(k => k.key)
|
|||
|
childrenKeys.forEach(k => {
|
|||
|
if (this.datamap[k]) {
|
|||
|
this.datamap[k].show = true
|
|||
|
}
|
|||
|
})
|
|||
|
}
|
|||
|
}
|
|||
|
},
|
|||
|
|
|||
|
/**
|
|||
|
* 加载异步数据
|
|||
|
* @param item
|
|||
|
*/
|
|||
|
async loadExpandNode(item) {
|
|||
|
const { expand, key, loaded, children } = item
|
|||
|
if (children?.length && !this.alwaysFirstLoad) {
|
|||
|
return item
|
|||
|
}
|
|||
|
|
|||
|
if (expand && this.loadMode && !loaded) {
|
|||
|
if (isFunction(this.loadApi)) {
|
|||
|
this.expandedKeys.push(key)
|
|||
|
this.loadLoading = true
|
|||
|
item.loading = true
|
|||
|
|
|||
|
const currentNode = deepClone(item)
|
|||
|
const apiRes = await this.loadApi(currentNode)
|
|||
|
|
|||
|
// 新增子项
|
|||
|
let newChildren = [...(item.originItem?.children || []), ...(apiRes || [])]
|
|||
|
const newChildrenObj = {}
|
|||
|
newChildren = newChildren.reduce((total, next) => {
|
|||
|
newChildrenObj[next[this.fieldMap]] ? '' : newChildrenObj[next[this.fieldMap]] = true && total.push(next)
|
|||
|
return total
|
|||
|
}, [])
|
|||
|
|
|||
|
item.originItem.children = newChildren || null
|
|||
|
if (apiRes?.length) {
|
|||
|
const insertIndex = this.datalist.findIndex(k => k.key === item.key)
|
|||
|
this.handleTreeData(apiRes, item, item.level + 1, insertIndex)
|
|||
|
this.datalist = this.checkInitData(this.datalist)
|
|||
|
} else {
|
|||
|
// 加载后无数据就移除展开图标
|
|||
|
item.expand = false
|
|||
|
item.isLeaf = true
|
|||
|
item.showArrow = false
|
|||
|
}
|
|||
|
|
|||
|
this.loadLoading = false
|
|||
|
item.loading = false
|
|||
|
item.loaded = true
|
|||
|
}
|
|||
|
} else {
|
|||
|
const eki = this.expandedKeys.findIndex(k => k === key)
|
|||
|
if (eki >= 0) {
|
|||
|
this.expandedKeys.splice(eki, 1)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return item
|
|||
|
},
|
|||
|
|
|||
|
/**
|
|||
|
* 获取父类的选中状态
|
|||
|
* @param item
|
|||
|
*/
|
|||
|
getParentCheckedStatus(item) {
|
|||
|
if (!item) {
|
|||
|
return unCheckedStatus
|
|||
|
}
|
|||
|
|
|||
|
if (!this.checkedDisabled && item.disabled) {
|
|||
|
return item.checkedStatus || unCheckedStatus
|
|||
|
}
|
|||
|
|
|||
|
// 单选时,父类永远为半选
|
|||
|
if (!this.showCheckbox) {
|
|||
|
return halfCheckedStatus
|
|||
|
}
|
|||
|
|
|||
|
const { children } = item
|
|||
|
// 子类全选中
|
|||
|
const childrenCheckedAll = children.every(k => k.checkedStatus === isCheckedStatus)
|
|||
|
if (childrenCheckedAll) {
|
|||
|
return isCheckedStatus
|
|||
|
}
|
|||
|
|
|||
|
// 子类全不选中
|
|||
|
const childrenUncheckedAll = children.every(k => k.checkedStatus === unCheckedStatus)
|
|||
|
if (childrenUncheckedAll) {
|
|||
|
return unCheckedStatus
|
|||
|
}
|
|||
|
|
|||
|
return halfCheckedStatus
|
|||
|
},
|
|||
|
/**
|
|||
|
* 返回已选的 key
|
|||
|
*/
|
|||
|
getCheckedKeys() {
|
|||
|
return getAllNodeKeys(this.datalist, 'checkedStatus', isCheckedStatus, this.packDisabledkey)
|
|||
|
},
|
|||
|
/**
|
|||
|
* 根据key设置已选
|
|||
|
* @param keys 多选时为key的数组,单选时为key
|
|||
|
* @param checked 多选时为key的数组,单选时为key
|
|||
|
*/
|
|||
|
setCheckedKeys(keys, checked = true) {
|
|||
|
// 多选
|
|||
|
if (this.showCheckbox) {
|
|||
|
if (!isArray(keys)) {
|
|||
|
logError(`setCheckedKeys 第一个参数非数组,传入的是[${keys}]`)
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
const list = this.datalist
|
|||
|
|
|||
|
// 取消选择
|
|||
|
if (checked === false) {
|
|||
|
let newCheckedKeys = []
|
|||
|
for (let i = 0; i < this.checkedKeys.length; i++) {
|
|||
|
const ck = this.checkedKeys[i]
|
|||
|
if (!keys.includes(ck)) {
|
|||
|
newCheckedKeys.push(ck)
|
|||
|
}
|
|||
|
}
|
|||
|
newCheckedKeys = [...new Set(newCheckedKeys)]
|
|||
|
this.checkedKeys = newCheckedKeys
|
|||
|
this.handleCheckState(list, keys, false)
|
|||
|
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// 选择
|
|||
|
const newCheckedKeys = [...this.checkedKeys, ...keys]
|
|||
|
this.checkedKeys = [...new Set(newCheckedKeys)]
|
|||
|
this.handleCheckState(list, this.checkedKeys, true)
|
|||
|
|
|||
|
if (this.expandChecked && checked) {
|
|||
|
this.expandedKeys = [...new Set([...(this.checkedKeys || []), ...(keys || [])])]
|
|||
|
this.handleExpandState(list, keys, true)
|
|||
|
}
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// 单选
|
|||
|
// 如果为数组则拿第一个
|
|||
|
if (isArray(keys)) {
|
|||
|
keys = keys[0]
|
|||
|
}
|
|||
|
|
|||
|
if (!isString(keys) && !isNumber(keys)) {
|
|||
|
logError('setCheckedKeys 第一个参数字符串或数字,传入的是==>', keys)
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
const list = this.datalist
|
|||
|
this.checkedKeys = checked ? keys : null
|
|||
|
|
|||
|
if (this.expandChecked && checked) {
|
|||
|
this.handleExpandState(list, [keys], true)
|
|||
|
}
|
|||
|
|
|||
|
this.handleCheckState(list, keys, !!checked)
|
|||
|
},
|
|||
|
/**
|
|||
|
* 返回半选的 key
|
|||
|
*/
|
|||
|
getHalfCheckedKeys() {
|
|||
|
return getAllNodeKeys(this.datalist, 'checkedStatus', halfCheckedStatus, this.packDisabledkey)
|
|||
|
},
|
|||
|
/**
|
|||
|
* 返回未选的 key
|
|||
|
*/
|
|||
|
getUncheckedKeys() {
|
|||
|
return getAllNodeKeys(this.datalist, 'checkedStatus', unCheckedStatus, this.packDisabledkey)
|
|||
|
},
|
|||
|
/**
|
|||
|
* 返回已展开的 key
|
|||
|
*/
|
|||
|
getExpandedKeys() {
|
|||
|
return getAllNodeKeys(this.datalist, 'expand', true)
|
|||
|
},
|
|||
|
/**
|
|||
|
* 根据key展开/收起
|
|||
|
* @param keys key的数组,或字符串 all
|
|||
|
* @param expand true为展开/false为收起
|
|||
|
*/
|
|||
|
setExpandedKeys(keys, expand = true) {
|
|||
|
if (!Array.isArray(keys) && keys !== 'all') {
|
|||
|
logError('setExpandedKeys 第一个参数非数组,传入的是===>', keys)
|
|||
|
return
|
|||
|
}
|
|||
|
const list = this.datalist
|
|||
|
|
|||
|
// 展开/收起全部
|
|||
|
if (keys === 'all') {
|
|||
|
list.forEach(k => {
|
|||
|
k.expand = expand
|
|||
|
if (k.level > 0) {
|
|||
|
k.show = expand
|
|||
|
}
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// 收起
|
|||
|
if (expand === false) {
|
|||
|
const newExpandedKeys = []
|
|||
|
for (let i = 0; i < this.expandedKeys.length; i++) {
|
|||
|
const ek = this.expandedKeys[i]
|
|||
|
if (!keys.includes(ek)) {
|
|||
|
newExpandedKeys.push(ek)
|
|||
|
}
|
|||
|
}
|
|||
|
this.expandedKeys = [...new Set(newExpandedKeys)]
|
|||
|
this.handleExpandState(list, keys, false)
|
|||
|
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// 展开
|
|||
|
const newExpandedKeys = []
|
|||
|
for (let i = 0; i < list.length; i++) {
|
|||
|
if (keys.includes(list[i].key)) {
|
|||
|
newExpandedKeys.push(list[i].key)
|
|||
|
}
|
|||
|
}
|
|||
|
this.expandedKeys = [...new Set(newExpandedKeys)]
|
|||
|
this.handleExpandState(list, newExpandedKeys, true)
|
|||
|
},
|
|||
|
/**
|
|||
|
* 返回未展开的 key
|
|||
|
*/
|
|||
|
getUnexpandedKeys() {
|
|||
|
return getAllNodeKeys(this.datalist, 'expand', false)
|
|||
|
},
|
|||
|
/**
|
|||
|
* 返回已选的节点
|
|||
|
*/
|
|||
|
getCheckedNodes() {
|
|||
|
return getAllNodes(this.datalist, 'checkedStatus', isCheckedStatus, this.packDisabledkey)
|
|||
|
},
|
|||
|
/**
|
|||
|
* 返回半选的节点
|
|||
|
*/
|
|||
|
getHalfCheckedNodes() {
|
|||
|
return getAllNodes(this.datalist, 'checkedStatus', halfCheckedStatus, this.packDisabledkey)
|
|||
|
},
|
|||
|
/**
|
|||
|
* 返回未选的节点
|
|||
|
*/
|
|||
|
getUncheckedNodes() {
|
|||
|
return getAllNodes(this.datalist, 'checkedStatus', unCheckedStatus, this.packDisabledkey)
|
|||
|
},
|
|||
|
/**
|
|||
|
* 返回已展开的节点
|
|||
|
*/
|
|||
|
getExpandedNodes() {
|
|||
|
return getAllNodes(this.datalist, 'expand', true)
|
|||
|
},
|
|||
|
/**
|
|||
|
* 返回未展开的节点
|
|||
|
*/
|
|||
|
getUnexpandedNodes() {
|
|||
|
return getAllNodes(this.datalist, 'expand', false)
|
|||
|
},
|
|||
|
},
|
|||
|
}
|
|||
|
</script>
|
|||
|
|
|||
|
<style lang="scss" scoped>
|
|||
|
@font-face {
|
|||
|
font-family: 'da-tree-iconfont'; /* Project id */
|
|||
|
src: url('data:application/octet-stream;base64,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') format('truetype');
|
|||
|
}
|
|||
|
|
|||
|
.da-tree {
|
|||
|
width: 100%;
|
|||
|
height: 100%;
|
|||
|
|
|||
|
&-scroll {
|
|||
|
width: 100%;
|
|||
|
height: 100%;
|
|||
|
}
|
|||
|
|
|||
|
&-item {
|
|||
|
display: flex;
|
|||
|
align-items: center;
|
|||
|
height: 0;
|
|||
|
padding: 0;
|
|||
|
overflow: hidden;
|
|||
|
font-size: 28rpx;
|
|||
|
line-height: 1;
|
|||
|
visibility: hidden;
|
|||
|
opacity: 0;
|
|||
|
transition: opacity 0.2s linear;
|
|||
|
|
|||
|
&.is-show {
|
|||
|
height: auto;
|
|||
|
padding: 12rpx 24rpx;
|
|||
|
visibility: visible;
|
|||
|
opacity: 1;
|
|||
|
}
|
|||
|
|
|||
|
&__icon {
|
|||
|
display: flex;
|
|||
|
align-items: center;
|
|||
|
justify-content: center;
|
|||
|
width: 40rpx;
|
|||
|
height: 40rpx;
|
|||
|
overflow: hidden;
|
|||
|
|
|||
|
&--arr {
|
|||
|
position: relative;
|
|||
|
display: flex;
|
|||
|
align-items: center;
|
|||
|
justify-content: center;
|
|||
|
width: 32rpx;
|
|||
|
height: 32rpx;
|
|||
|
|
|||
|
&::after {
|
|||
|
position: relative;
|
|||
|
z-index: 1;
|
|||
|
overflow: hidden;
|
|||
|
/* stylelint-disable-next-line font-family-no-missing-generic-family-keyword */
|
|||
|
font-family: 'da-tree-iconfont' !important;
|
|||
|
font-size: 32rpx;
|
|||
|
font-style: normal;
|
|||
|
color: #999;
|
|||
|
-webkit-font-smoothing: antialiased;
|
|||
|
-moz-osx-font-smoothing: grayscale;
|
|||
|
}
|
|||
|
|
|||
|
&.is-expand {
|
|||
|
&::after {
|
|||
|
content: '\e604';
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
&.is-right {
|
|||
|
transform: rotate(-90deg);
|
|||
|
}
|
|||
|
|
|||
|
&.is-loading {
|
|||
|
animation: IconLoading 1s linear 0s infinite;
|
|||
|
|
|||
|
&::after {
|
|||
|
content: '\e7f1';
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
&__checkbox {
|
|||
|
width: 40rpx;
|
|||
|
height: 40rpx;
|
|||
|
overflow: hidden;
|
|||
|
|
|||
|
&--left {
|
|||
|
order: 0;
|
|||
|
}
|
|||
|
|
|||
|
&--right {
|
|||
|
order: 1;
|
|||
|
}
|
|||
|
|
|||
|
&--icon {
|
|||
|
position: relative;
|
|||
|
display: flex;
|
|||
|
align-items: center;
|
|||
|
justify-content: center;
|
|||
|
width: 40rpx;
|
|||
|
height: 40rpx;
|
|||
|
|
|||
|
&::after {
|
|||
|
position: relative;
|
|||
|
top: 0;
|
|||
|
left: 0;
|
|||
|
z-index: 1;
|
|||
|
overflow: hidden;
|
|||
|
/* stylelint-disable-next-line font-family-no-missing-generic-family-keyword */
|
|||
|
font-family: 'da-tree-iconfont' !important;
|
|||
|
font-size: 32rpx;
|
|||
|
font-style: normal;
|
|||
|
-webkit-font-smoothing: antialiased;
|
|||
|
-moz-osx-font-smoothing: grayscale;
|
|||
|
}
|
|||
|
|
|||
|
&.da-tree-checkbox-outline::after {
|
|||
|
color: #bbb;
|
|||
|
content: '\ead5';
|
|||
|
}
|
|||
|
|
|||
|
&.da-tree-checkbox-checked::after {
|
|||
|
color: var(--theme-color,#007aff);
|
|||
|
content: '\ead4';
|
|||
|
}
|
|||
|
|
|||
|
&.da-tree-checkbox-indeterminate::after {
|
|||
|
color: var(--theme-color,#007aff);
|
|||
|
content: '\ebce';
|
|||
|
}
|
|||
|
|
|||
|
&.da-tree-radio-outline::after {
|
|||
|
color: #bbb;
|
|||
|
content: '\ecc5';
|
|||
|
}
|
|||
|
|
|||
|
&.da-tree-radio-checked::after {
|
|||
|
color: var(--theme-color,#007aff);
|
|||
|
content: '\ecc4';
|
|||
|
}
|
|||
|
|
|||
|
&.da-tree-radio-indeterminate::after {
|
|||
|
color: var(--theme-color,#007aff);
|
|||
|
content: '\ea4f';
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
&.is--disabled {
|
|||
|
cursor: not-allowed;
|
|||
|
opacity: 0.35;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
&__label {
|
|||
|
flex: 1;
|
|||
|
margin-left: 4rpx;
|
|||
|
color: #555;
|
|||
|
|
|||
|
&--2 {
|
|||
|
color: var(--theme-color,#007aff);
|
|||
|
}
|
|||
|
|
|||
|
&--append {
|
|||
|
font-size: 60%;
|
|||
|
opacity: 0.6;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
@keyframes IconLoading {
|
|||
|
0% {
|
|||
|
transform: rotate(0deg);
|
|||
|
}
|
|||
|
|
|||
|
100% {
|
|||
|
transform: rotate(360deg);
|
|||
|
}
|
|||
|
}
|
|||
|
</style>
|