magiccube-vue3
Version:
vue3-js版组件库
222 lines (217 loc) • 7.27 kB
JavaScript
import '../../style/permission-tree.less'
import { ref, computed, provide, inject, watchEffect, watch } from 'vue'
import * as utils from '../../utils/common'
/**
* 更新祖级的treeData,可以使用provide和inject
*/
const TreeRender = {
name: 'TreeRender',
props: {
data: Array,
currentText: [String, Number],
keyName: {
type: String,
default: 'permissionId'
}
},
setup(props, { emit, slots }) {
/**
* +- 处理
*/
const forefatherRefresh = inject('forefatherRefresh', () => { })
const handleExtend = (item) => {
item.isExtend = !item.isExtend
forefatherRefresh()
}
const extendNode = (item) => (
<div class="mc-permission-tree__panel--node--content--symbol"
onClick={() => handleExtend(item)}>
{item.isExtend ? '-' : '+'}
</div>
)
/**
* √ 处理
*/
const forefatherCheckboxClick = inject('forefatherCheckboxClick', () => { })
const handleCheck = (item) => {
forefatherCheckboxClick(item)
}
const checkboxNode = (item) => {
return (
<McCheckbox v-model={item.isChecked} onChange={() => handleCheck(item)}></McCheckbox>
)
}
/**
* text 处理
*/
const forefatherTextClick = inject('forefatherTextClick', () => { })
const handleTextClick = (item) => {
forefatherTextClick(item)
}
const textNode = (item) => (
<span class={{
'mc-permission-tree__panel--node--content--text': true,
'mc-permission-tree__panel--node--content--text-clickable': true,
'mc-permission-tree__panel--node--content--text-active': item[props.keyName] === props.currentText,
}} onClick={() => handleTextClick(item)}>
{item.permissionName}
<span style="margin-left: 8px">id:{item.permissionId}</span>
</span>
)
/**
* 编辑按钮 处理
*/
const forefatherEdit = inject('forefatherEdit', () => { })
const handleEdit = (item) => {
forefatherEdit(item)
}
const editButtonNode = (item) => (
<span class="mc-permission-tree__panel--node--content--edit" onClick={() => handleEdit(item)}>编辑</span>
)
/**
* 复制按钮 处理
*/
const copyBottuonNode = (item) => (
<span class="mc-permission-tree__panel--node--content--copy" v-copy={item.permissionKey}>复制</span>
)
/**
* 递归 处理
*/
const newPanel = (item) => (
<TreeRender data={item.children} currentText={props.currentText} />
)
/**
* liNode 处理
*/
const liNode = (item, idx) => (
<li key={idx} class="mc-permission-tree__panel--node">
<div class={{
'mc-permission-tree__panel--node--content': true,
'mc-permission-tree__panel--node--placeholder': !item.children?.length
}}>
{item.children?.length ? extendNode(item) : ''}
{checkboxNode(item)}
{textNode(item)}
{editButtonNode(item)}
{copyBottuonNode(item)}
</div>
{
item.children?.length && item.isExtend ? newPanel(item) : ''
}
</li>
)
return () => (
<ul class="mc-permission-tree__panel">
{props.data.map(liNode)}
</ul>
)
}
}
const PermissionTree = {
name: 'McPermissionTree',
props: {
data: {
type: Array,
default: () => []
},
/**
* 表示选中的条目的key值(id)的集合
*/
modelValue: {
type: Array,
default: () => []
},
keyName: {
type: String,
default: 'permissionId'
},
currentTextValue: [Number, String],
initData: Boolean
},
emits: ['trigger', 'update:modelValue', 'edit', 'update:currentTextValue'],
setup(props, { emit, slots }) {
/**
* 初始treeData
* 每次刚打开弹窗,用最初的props.data
*/
const treeData = ref([])
watchEffect(() => {
if (props.initData) {
treeData.value = utils.deepCopy(props.data)
}
})
const model = computed({
get() {
return props.modelValue
},
set(val) {
emit('update:modelValue', val)
}
})
const resetTreeData = (data, selected) => {
return data.map(item => {
const obj = {
...item,
isChecked: selected.includes(item[props.keyName]),
children: resetTreeData(item.children, selected),
}
if (obj.buttons) obj.buttons = resetTreeData(item.buttons, selected)
return obj
})
}
watch(() => props.modelValue, (n, o) => {
treeData.value = resetTreeData(treeData.value, model.value)
})
/**
* 点击+-时,item的isExtend改变,更新祖级的treeData.value
*/
const refresh = () => {
treeData.value = utils.deepCopy(treeData.value)
}
provide('forefatherRefresh', refresh)
/**
* 点击checkbox后,item的isChecked改变,需要修改model.value的值(随后会根据watch改变treeData)
*/
const checkboxClick = (item) => {
const _k = item[props.keyName]
const ary = [...model.value]
ary.includes(_k) ? ary.splice(ary.indexOf(_k), 1) : ary.push(_k)
model.value = [...ary]
}
provide('forefatherCheckboxClick', checkboxClick)
/**
* 点击文本后,会抛出点击事件;
*/
const currentText = computed({
get() {
return props.currentTextValue || ''
},
set(val) {
emit('update:currentTextValue', val)
}
})
const textClick = (item) => {
currentText.value = item[props.keyName]
emit('trigger', item)
}
provide('forefatherTextClick', textClick)
/**
* 点击编辑后,会抛出编辑事件;
*/
const handleEdit = (item) => {
emit('edit', item)
}
provide('forefatherEdit', handleEdit)
return () => (
<div class="mc-permission-tree">
<TreeRender data={treeData.value}
currentText={currentText.value} />
</div>
)
}
}
PermissionTree.install = Vue => {
Vue.component(PermissionTree.name, PermissionTree)
}
const McPermissionTree = PermissionTree
export { McPermissionTree, McPermissionTree as default }