layui/src/module/tree/TreeEntity.vue
2021-10-14 16:37:17 +08:00

172 lines
4.1 KiB
Vue

<script lang="ts">
export default {
name: 'LayTreeEntity',
}
</script>
<script setup lang="ts">
import LayIcon from '../icon'
import LayCheckbox from '../checkbox'
import { TreeNode } from '/@src/module/tree/tree.type'
type EventType = 'icon' | 'node'
interface TreeEntityProps {
node: TreeNode
showCheckbox?: boolean,
updateCheckedByNode: (node: TreeNode) => void
}
interface EmitEvent {
(e: 'node-click', node: TreeNode, type: EventType): void
}
const props = withDefaults(defineProps<TreeEntityProps>(), {
showCheckbox: false,
})
const emit = defineEmits<EmitEvent>()
/**
* 是否设置短线
* @param node
*/
const renderLineShort = (node: TreeNode): boolean => {
return (
// 没有下一个节点
(node._nextSibling === null &&
node._parentNode &&
// 外层最后一个
(node._parentNode._nextSibling === null ||
//上一层父级有延伸线
(node._parentNode._nextSibling &&
!node._parentNode._nextSibling.children))) as boolean
)
}
/**
* 展开收起 icon样式
* @param node
*/
const nodeIconType = (node: TreeNode): string => {
return !node.spread ? 'layui-icon-addition' : 'layui-icon-subtraction'
}
/**
* 节点Icon点击
* @param node
*/
function handleIconClick(node: TreeNode) {
emit('node-click', node, 'icon')
}
/**
* 节点点击
* @param node
*/
function handleNodeClick(node: TreeNode) {
emit('node-click', node, 'node')
}
/**
* 递归emit事件
* @param node
* @param type
*/
function innerClick(node: TreeNode, type: EventType) {
emit('node-click', node, type)
}
/**
* checkbox click
* @param arg
* @param node
*/
function handleCheckboxChange (arg: { checked: boolean, value: string }, node: TreeNode) {
props.updateCheckedByNode(node)
}
</script>
<template>
<template v-if="node.children && node.children.length > 0">
<div
class="layui-tree-set"
:class="{
'layui-tree-setLineShort': renderLineShort(node),
'layui-tree-setHide': !node.parentId,
}"
>
<div class="layui-tree-entry">
<div class="layui-tree-main">
<span class="layui-tree-iconClick layui-tree-icon">
<LayIcon
:type="nodeIconType(node)"
@click.prevent.stop="handleIconClick(node, 'icon')"
/>
</span>
<LayCheckbox
v-if="showCheckbox"
name="name"
skin="primary"
v-model:checked="node._checked"
@change="(args) => { handleCheckboxChange(args, node) }"
>
<!-- {{ node.title }} || {{node.id}}-->
</LayCheckbox>
<span
class="layui-tree-txt"
@click.prevent.stop="handleNodeClick(node, 'node')"
>
{{ node.title }}
</span>
</div>
</div>
<div
v-show="node.spread"
class="layui-tree-pack layui-tree-showLine"
style="display: block"
>
<LayTreeEntity
v-for="(item, index) in node.children"
:key="index"
:node="item"
:show-checkbox="showCheckbox"
@node-click="innerClick"
:updateCheckedByNode="updateCheckedByNode"
/>
</div>
</div>
</template>
<template v-else>
<div
class="layui-tree-set"
:class="{
'layui-tree-setLineShort': renderLineShort(node),
}"
>
<div class="layui-tree-entry">
<div class="layui-tree-main">
<span class="layui-tree-iconClick">
<LayIcon
type="layui-icon-file"
@click.prevent.stop="handleIconClick(node, 'icon')"
/>
</span>
<LayCheckbox
v-if="showCheckbox"
name="name"
skin="primary"
label="1"
v-model:checked="node._checked"
@change="(args) => { handleCheckboxChange(args, node) }"
>
</LayCheckbox>
<span
class="layui-tree-txt"
@click.prevent.stop="handleNodeClick(node, 'node')"
>
{{ node.title }}
</span>
</div>
</div>
</div>
</template>
</template>
<style scoped lang="less"></style>