feat(tree): add tree component and wip workspace
This commit is contained in:
parent
393ff8c9e0
commit
7dbb3b0353
56
docs/docs/zh-CN/components/tree.md
Normal file
56
docs/docs/zh-CN/components/tree.md
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
::: demo
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<lay-tree
|
||||||
|
:data="data"
|
||||||
|
>
|
||||||
|
</lay-tree>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
const data = ref([{
|
||||||
|
title: '江西'
|
||||||
|
,id: 1
|
||||||
|
,children: [{
|
||||||
|
title: '南昌'
|
||||||
|
,id: 1000
|
||||||
|
,children: [{
|
||||||
|
title: '青山湖区'
|
||||||
|
,id: 10001
|
||||||
|
},{
|
||||||
|
title: '高新区'
|
||||||
|
,id: 10002
|
||||||
|
}]
|
||||||
|
},{
|
||||||
|
title: '九江'
|
||||||
|
,id: 1001
|
||||||
|
},{
|
||||||
|
title: '赣州'
|
||||||
|
,id: 1002
|
||||||
|
}]
|
||||||
|
},{
|
||||||
|
title: '广西'
|
||||||
|
,id: 2
|
||||||
|
,children: [{
|
||||||
|
title: '南宁'
|
||||||
|
,id: 2000
|
||||||
|
},{
|
||||||
|
title: '桂林'
|
||||||
|
,id: 2001
|
||||||
|
}]
|
||||||
|
},{
|
||||||
|
title: '陕西'
|
||||||
|
,id: 3
|
||||||
|
,children: [{
|
||||||
|
title: '西安'
|
||||||
|
,id: 3000
|
||||||
|
},{
|
||||||
|
title: '延安'
|
||||||
|
,id: 3001
|
||||||
|
}]
|
||||||
|
}])
|
||||||
|
</script>
|
||||||
|
|
||||||
|
:::
|
@ -18,14 +18,10 @@
|
|||||||
style="margin-top: 0px; margin-bottom: 0px"
|
style="margin-top: 0px; margin-bottom: 0px"
|
||||||
>
|
>
|
||||||
<li class="layui-nav-item">
|
<li class="layui-nav-item">
|
||||||
<a href="https://gitee.com/layui-vue/layui-vue-sample">
|
<a href="https://gitee.com/layui-vue/layui-vue-sample"> 案例 </a>
|
||||||
案例
|
|
||||||
</a>
|
|
||||||
</li>
|
</li>
|
||||||
<li class="layui-nav-item">
|
<li class="layui-nav-item">
|
||||||
<a href="https://gitee.com/layui-vue/layui-vue">
|
<a href="https://gitee.com/layui-vue/layui-vue"> 仓库 </a>
|
||||||
仓库
|
|
||||||
</a>
|
|
||||||
</li>
|
</li>
|
||||||
<li class="layui-nav-item">
|
<li class="layui-nav-item">
|
||||||
<a
|
<a
|
||||||
@ -37,11 +33,16 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</lay-header>
|
</lay-header>
|
||||||
<lay-side>
|
<lay-side>
|
||||||
<ul class="layui-menu layui-menu-lg layui-menu-docs" style="padding:6px">
|
<ul
|
||||||
|
class="layui-menu layui-menu-lg layui-menu-docs"
|
||||||
|
style="padding: 6px"
|
||||||
|
>
|
||||||
<li
|
<li
|
||||||
:key="menu"
|
:key="menu"
|
||||||
v-for="menu in menus"
|
v-for="menu in menus"
|
||||||
:class="[currentPath === menu.path ? 'layui-menu-item-checked2' : '']"
|
:class="[
|
||||||
|
currentPath === menu.path ? 'layui-menu-item-checked2' : '',
|
||||||
|
]"
|
||||||
@click="handleClick(menu)"
|
@click="handleClick(menu)"
|
||||||
>
|
>
|
||||||
<div class="layui-menu-body-title">
|
<div class="layui-menu-body-title">
|
||||||
@ -70,7 +71,7 @@ export default {
|
|||||||
setup() {
|
setup() {
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const currentPath = ref("hahaha")
|
const currentPath = ref('hahaha')
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => route.path,
|
() => route.path,
|
||||||
@ -247,12 +248,19 @@ export default {
|
|||||||
title: '选项卡',
|
title: '选项卡',
|
||||||
subTitle: 'tab',
|
subTitle: 'tab',
|
||||||
path: '/zh-CN/components/tab',
|
path: '/zh-CN/components/tab',
|
||||||
},{
|
},
|
||||||
|
{
|
||||||
id: 29,
|
id: 29,
|
||||||
title: '图标选择',
|
title: '图标选择',
|
||||||
subTitle: 'iconPicker',
|
subTitle: 'iconPicker',
|
||||||
path: '/zh-CN/components/iconPicker',
|
path: '/zh-CN/components/iconPicker',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: 30,
|
||||||
|
title: '树形组件',
|
||||||
|
subTitle: 'tree',
|
||||||
|
path: '/zh-CN/components/tree',
|
||||||
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
const selected = ref(1)
|
const selected = ref(1)
|
||||||
@ -284,4 +292,4 @@ export default {
|
|||||||
.layui-menu-docs .layui-menu-body-title .layui-font-gray {
|
.layui-menu-docs .layui-menu-body-title .layui-font-gray {
|
||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -148,7 +148,11 @@ const zhCN = [
|
|||||||
path: '/zh-CN/components/iconPicker',
|
path: '/zh-CN/components/iconPicker',
|
||||||
component: () => import('../../docs/zh-CN/components/iconPicker.md'),
|
component: () => import('../../docs/zh-CN/components/iconPicker.md'),
|
||||||
meta: { title: '图标选择' },
|
meta: { title: '图标选择' },
|
||||||
}
|
}, {
|
||||||
|
path: '/zh-CN/components/tree',
|
||||||
|
component: () => import('../../docs/zh-CN/components/tree.md'),
|
||||||
|
meta: { title: '树形组件' }
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
55
src/index.ts
55
src/index.ts
@ -1,7 +1,7 @@
|
|||||||
import type { App } from 'vue'
|
import type { App } from 'vue'
|
||||||
import type { IDefineComponent, InstallOptions } from './module/type/index'
|
import type { IDefineComponent, InstallOptions } from './module/type/index'
|
||||||
|
|
||||||
import "./css/layui.css"
|
import './css/layui.css'
|
||||||
import LayAvatar from './module/avatar/index'
|
import LayAvatar from './module/avatar/index'
|
||||||
import LayRadio from './module/radio/index'
|
import LayRadio from './module/radio/index'
|
||||||
import LayButton from './module/button/index'
|
import LayButton from './module/button/index'
|
||||||
@ -10,27 +10,27 @@ import LayButtonGroup from './module/buttonGroup/index'
|
|||||||
import LayIcon from './module/icon/index'
|
import LayIcon from './module/icon/index'
|
||||||
import LayIconPicker from './module/iconPicker/index'
|
import LayIconPicker from './module/iconPicker/index'
|
||||||
import LayCard from './module/card/index'
|
import LayCard from './module/card/index'
|
||||||
import LayLayout from "./module/layout/index"
|
import LayLayout from './module/layout/index'
|
||||||
import LaySide from "./module/side/index"
|
import LaySide from './module/side/index'
|
||||||
import LayBody from "./module/body/index"
|
import LayBody from './module/body/index'
|
||||||
import LayHeader from "./module/header/index"
|
import LayHeader from './module/header/index'
|
||||||
import LayFooter from "./module/footer/index"
|
import LayFooter from './module/footer/index'
|
||||||
import LayLogo from "./module/logo/index"
|
import LayLogo from './module/logo/index'
|
||||||
import LayPanel from "./module/panel/index"
|
import LayPanel from './module/panel/index'
|
||||||
import LayProgress from "./module/progress/index"
|
import LayProgress from './module/progress/index'
|
||||||
import LayCol from "./module/col/index"
|
import LayCol from './module/col/index'
|
||||||
import LayRow from "./module/row/index"
|
import LayRow from './module/row/index'
|
||||||
import LayInput from "./module/input/index"
|
import LayInput from './module/input/index'
|
||||||
import LayBadge from "./module/badge/index"
|
import LayBadge from './module/badge/index'
|
||||||
import LayBlock from "./module/block/index"
|
import LayBlock from './module/block/index'
|
||||||
import LayLine from "./module/line/index"
|
import LayLine from './module/line/index'
|
||||||
import LayTimeline from "./module/timeline/index"
|
import LayTimeline from './module/timeline/index'
|
||||||
import LayTimelineItem from "./module/timelineItem/index"
|
import LayTimelineItem from './module/timelineItem/index'
|
||||||
import LayTextarea from "./module/textarea/index"
|
import LayTextarea from './module/textarea/index'
|
||||||
import LaySwitch from "./module/switch/index"
|
import LaySwitch from './module/switch/index'
|
||||||
import LayCollapse from "./module/collapse/index"
|
import LayCollapse from './module/collapse/index'
|
||||||
import LayCollapseItem from "./module/collapseItem/index"
|
import LayCollapseItem from './module/collapseItem/index'
|
||||||
import LayContainer from "./module/container/index"
|
import LayContainer from './module/container/index'
|
||||||
import LayMenu from './module/menu/index'
|
import LayMenu from './module/menu/index'
|
||||||
import LayMenuItem from './module/menuItem/index'
|
import LayMenuItem from './module/menuItem/index'
|
||||||
import LayMenuChildItem from './module/menuChildItem/index'
|
import LayMenuChildItem from './module/menuChildItem/index'
|
||||||
@ -49,6 +49,7 @@ import LayDropdown from './module/dropdown/index'
|
|||||||
import LayDropdownItem from './module/dropdownItem/index'
|
import LayDropdownItem from './module/dropdownItem/index'
|
||||||
import LayTab from './module/tab/index'
|
import LayTab from './module/tab/index'
|
||||||
import LayTabItem from './module/tabItem/index'
|
import LayTabItem from './module/tabItem/index'
|
||||||
|
import LayTree from './module/tree/index'
|
||||||
|
|
||||||
const components: Record<string, IDefineComponent> = {
|
const components: Record<string, IDefineComponent> = {
|
||||||
LayRadio,
|
LayRadio,
|
||||||
@ -97,11 +98,12 @@ const components: Record<string, IDefineComponent> = {
|
|||||||
LayDropdownItem,
|
LayDropdownItem,
|
||||||
LayTab,
|
LayTab,
|
||||||
LayTabItem,
|
LayTabItem,
|
||||||
LayIconPicker
|
LayIconPicker,
|
||||||
|
LayTree
|
||||||
}
|
}
|
||||||
|
|
||||||
const install = (app: App, options?: InstallOptions): void => {
|
const install = (app: App, options?: InstallOptions): void => {
|
||||||
const _options = options;
|
const _options = options
|
||||||
app.config.globalProperties.$PROOPTIONS = _options
|
app.config.globalProperties.$PROOPTIONS = _options
|
||||||
|
|
||||||
for (const key in components) {
|
for (const key in components) {
|
||||||
@ -110,7 +112,7 @@ const install = (app: App, options?: InstallOptions): void => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("document Site : http://layui-vue.pearadmin.com")
|
console.log('document Site : http://layui-vue.pearadmin.com')
|
||||||
|
|
||||||
export {
|
export {
|
||||||
LayRadio,
|
LayRadio,
|
||||||
@ -122,7 +124,7 @@ export {
|
|||||||
LayBody,
|
LayBody,
|
||||||
LayFooter,
|
LayFooter,
|
||||||
LayLogo,
|
LayLogo,
|
||||||
LayPanel,
|
LayPanel,
|
||||||
LayCard,
|
LayCard,
|
||||||
LayProgress,
|
LayProgress,
|
||||||
LayButtonGroup,
|
LayButtonGroup,
|
||||||
@ -160,6 +162,7 @@ export {
|
|||||||
LayTab,
|
LayTab,
|
||||||
LayTabItem,
|
LayTabItem,
|
||||||
LayIconPicker,
|
LayIconPicker,
|
||||||
|
LayTree,
|
||||||
install,
|
install,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
9
src/module/tree/index.ts
Normal file
9
src/module/tree/index.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import type { App } from 'vue'
|
||||||
|
import Component from './index.vue'
|
||||||
|
import type { IDefineComponent } from '../type/index'
|
||||||
|
|
||||||
|
Component.install = (app: App) => {
|
||||||
|
app.component(Component.name || 'LayTree', Component)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Component as IDefineComponent
|
287
src/module/tree/index.vue
Normal file
287
src/module/tree/index.vue
Normal file
@ -0,0 +1,287 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { VNode, VNodeChild } from 'vue'
|
||||||
|
|
||||||
|
interface TreeData {
|
||||||
|
/**
|
||||||
|
* 节点唯一索引值,用于对指定节点进行各类操作
|
||||||
|
*/
|
||||||
|
id: string | number
|
||||||
|
/**
|
||||||
|
* 节点标题
|
||||||
|
*/
|
||||||
|
title: string | (() => string)
|
||||||
|
/**
|
||||||
|
* 节点字段名
|
||||||
|
*/
|
||||||
|
field: string | (() => string)
|
||||||
|
/**
|
||||||
|
* 子节点。支持设定选项同父节点
|
||||||
|
*/
|
||||||
|
children: TreeData[]
|
||||||
|
/**
|
||||||
|
* 点击节点弹出新窗口对应的 url。需开启 isJump 参数
|
||||||
|
*/
|
||||||
|
href: string | URL
|
||||||
|
/**
|
||||||
|
* 节点是否初始展开,默认 false
|
||||||
|
*/
|
||||||
|
spread: boolean
|
||||||
|
/**
|
||||||
|
* 节点是否初始为选中状态(如果开启复选框的话),默认 false
|
||||||
|
*/
|
||||||
|
checked: boolean
|
||||||
|
/**
|
||||||
|
* 节点是否为禁用状态。默认 false
|
||||||
|
*/
|
||||||
|
disabled: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
type EditAction = 'add' | 'update' | 'del'
|
||||||
|
|
||||||
|
type EditType = boolean | EditAction[]
|
||||||
|
|
||||||
|
interface TreeProps {
|
||||||
|
/**
|
||||||
|
* 数据源
|
||||||
|
*/
|
||||||
|
data?: TreeData
|
||||||
|
/**
|
||||||
|
* 是否显示复选框 默认 false
|
||||||
|
*/
|
||||||
|
showCheckbox?: boolean
|
||||||
|
/**
|
||||||
|
* 是否开启节点的操作图标。默认 false。
|
||||||
|
若为 true,则默认显示“改删”图标
|
||||||
|
若为 数组,则可自由配置操作图标的显示状态和顺序,目前支持的操作图标有:add、update、del,如:
|
||||||
|
edit: ['add', 'update', 'del']
|
||||||
|
*/
|
||||||
|
edit?: EditType
|
||||||
|
/**
|
||||||
|
* 是否开启手风琴模式,默认 false
|
||||||
|
*/
|
||||||
|
accordion?: boolean
|
||||||
|
/**
|
||||||
|
* 是否仅允许节点左侧图标控制展开收缩。默认 false(即点击节点本身也可控制)。若为 true,则只能通过节点左侧图标来展开收缩
|
||||||
|
*/
|
||||||
|
onlyIconControl?: boolean
|
||||||
|
/**
|
||||||
|
* 是否允许点击节点时弹出新窗口跳转。默认 false,若开启,需在节点数据中设定 link 参数(值为 url 格式
|
||||||
|
*/
|
||||||
|
isJump?: boolean
|
||||||
|
/**
|
||||||
|
* 是否开启连接线。默认 true,若设为 false,则节点左侧出现三角图标。
|
||||||
|
*/
|
||||||
|
showLine?: boolean
|
||||||
|
/**
|
||||||
|
* 自定义各类默认文本,目前支持以下设定:
|
||||||
|
*/
|
||||||
|
text?: {
|
||||||
|
/**
|
||||||
|
* 节点默认名称
|
||||||
|
*/
|
||||||
|
defaultNodeName?: () => string | string
|
||||||
|
/**
|
||||||
|
* 数据为空时的提示文本
|
||||||
|
*/
|
||||||
|
none?: () => string | string | VNode | Element
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface TreeNode {
|
||||||
|
/**
|
||||||
|
* 当前点击的节点数据
|
||||||
|
*/
|
||||||
|
data: TreeData
|
||||||
|
/**
|
||||||
|
* 节点的展开状态
|
||||||
|
*/
|
||||||
|
state: 'open' | 'close' | 'normal'
|
||||||
|
/**
|
||||||
|
* 当前节点元素
|
||||||
|
*/
|
||||||
|
elem: Element | VNode | VNodeChild
|
||||||
|
}
|
||||||
|
|
||||||
|
interface TreeEmits {
|
||||||
|
/**
|
||||||
|
* 节点被点击后触发
|
||||||
|
* @param e 事件
|
||||||
|
* @param treeNode
|
||||||
|
*/
|
||||||
|
(e: 'on-click', treeNode: TreeNode): void
|
||||||
|
/**
|
||||||
|
* 点击复选框时触发
|
||||||
|
* @param e 事件
|
||||||
|
* @param treeNode
|
||||||
|
*/
|
||||||
|
(e: 'on-check', treeNode: TreeNode): void
|
||||||
|
/**
|
||||||
|
* 操作节点的回调
|
||||||
|
* @param e 事件
|
||||||
|
* @param treeNode
|
||||||
|
*/
|
||||||
|
(e: 'on-operate', treeNode: TreeNode): void
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<TreeProps>(), {
|
||||||
|
showCheckbox: false,
|
||||||
|
accordion: false,
|
||||||
|
onlyIconControl: false,
|
||||||
|
isJump: false,
|
||||||
|
showLine: true,
|
||||||
|
edit: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
console.log(props)
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<script lang="ts">
|
||||||
|
export default {
|
||||||
|
name: 'LayTree',
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<div id="test1" class="demo-tree demo-tree-box">
|
||||||
|
<div class="layui-tree layui-tree-line" lay-filter="LAY-tree-2">
|
||||||
|
<div
|
||||||
|
data-id="1"
|
||||||
|
class="layui-tree-set layui-tree-setHide layui-tree-spread"
|
||||||
|
>
|
||||||
|
<div class="layui-tree-entry">
|
||||||
|
<div class="layui-tree-main">
|
||||||
|
<span class="layui-tree-iconClick layui-tree-icon"
|
||||||
|
><i class="layui-icon layui-icon-subtraction"></i></span
|
||||||
|
><span class="layui-tree-txt">江西</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="layui-tree-pack layui-tree-lineExtend layui-tree-showLine"
|
||||||
|
style="display: block"
|
||||||
|
>
|
||||||
|
<div data-id="1000" class="layui-tree-set layui-tree-spread">
|
||||||
|
<div class="layui-tree-entry">
|
||||||
|
<div class="layui-tree-main">
|
||||||
|
<span class="layui-tree-iconClick layui-tree-icon"
|
||||||
|
><i class="layui-icon layui-icon-subtraction"></i></span
|
||||||
|
><span class="layui-tree-txt">南昌</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="layui-tree-pack layui-tree-lineExtend layui-tree-showLine"
|
||||||
|
style="display: block"
|
||||||
|
>
|
||||||
|
<div data-id="10001" class="layui-tree-set">
|
||||||
|
<div class="layui-tree-entry">
|
||||||
|
<div class="layui-tree-main">
|
||||||
|
<span class="layui-tree-iconClick"
|
||||||
|
><i class="layui-icon layui-icon-file"></i></span
|
||||||
|
><span class="layui-tree-txt">青山湖区</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
data-id="10002"
|
||||||
|
class="layui-tree-set layui-tree-setLineShort"
|
||||||
|
>
|
||||||
|
<div class="layui-tree-entry">
|
||||||
|
<div class="layui-tree-main">
|
||||||
|
<span class="layui-tree-iconClick"
|
||||||
|
><i class="layui-icon layui-icon-file"></i></span
|
||||||
|
><span class="layui-tree-txt">高新区</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div data-id="1001" class="layui-tree-set">
|
||||||
|
<div class="layui-tree-entry">
|
||||||
|
<div class="layui-tree-main">
|
||||||
|
<span class="layui-tree-iconClick"
|
||||||
|
><i class="layui-icon layui-icon-file"></i></span
|
||||||
|
><span class="layui-tree-txt">九江</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div data-id="1002" class="layui-tree-set">
|
||||||
|
<div class="layui-tree-entry">
|
||||||
|
<div class="layui-tree-main">
|
||||||
|
<span class="layui-tree-iconClick"
|
||||||
|
><i class="layui-icon layui-icon-file"></i></span
|
||||||
|
><span class="layui-tree-txt">赣州</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
data-id="2"
|
||||||
|
class="layui-tree-set layui-tree-setHide layui-tree-spread"
|
||||||
|
>
|
||||||
|
<div class="layui-tree-entry">
|
||||||
|
<div class="layui-tree-main">
|
||||||
|
<span class="layui-tree-iconClick layui-tree-icon"
|
||||||
|
><i class="layui-icon layui-icon-subtraction"></i></span
|
||||||
|
><span class="layui-tree-txt">广西</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="layui-tree-pack layui-tree-lineExtend layui-tree-showLine"
|
||||||
|
style="display: block"
|
||||||
|
>
|
||||||
|
<div data-id="2000" class="layui-tree-set">
|
||||||
|
<div class="layui-tree-entry">
|
||||||
|
<div class="layui-tree-main">
|
||||||
|
<span class="layui-tree-iconClick"
|
||||||
|
><i class="layui-icon layui-icon-file"></i></span
|
||||||
|
><span class="layui-tree-txt">南宁</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div data-id="2001" class="layui-tree-set">
|
||||||
|
<div class="layui-tree-entry">
|
||||||
|
<div class="layui-tree-main">
|
||||||
|
<span class="layui-tree-iconClick"
|
||||||
|
><i class="layui-icon layui-icon-file"></i></span
|
||||||
|
><span class="layui-tree-txt">桂林</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
data-id="3"
|
||||||
|
class="layui-tree-set layui-tree-setHide layui-tree-setLineShort"
|
||||||
|
>
|
||||||
|
<div class="layui-tree-entry">
|
||||||
|
<div class="layui-tree-main">
|
||||||
|
<span class="layui-tree-iconClick layui-tree-icon"
|
||||||
|
><i class="layui-icon layui-icon-addition"></i></span
|
||||||
|
><span class="layui-tree-txt">陕西</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="layui-tree-pack layui-tree-lineExtend">
|
||||||
|
<div data-id="3000" class="layui-tree-set">
|
||||||
|
<div class="layui-tree-entry">
|
||||||
|
<div class="layui-tree-main">
|
||||||
|
<span class="layui-tree-iconClick"
|
||||||
|
><i class="layui-icon layui-icon-file"></i></span
|
||||||
|
><span class="layui-tree-txt">西安</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div data-id="3001" class="layui-tree-set layui-tree-setLineShort">
|
||||||
|
<div class="layui-tree-entry">
|
||||||
|
<div class="layui-tree-main">
|
||||||
|
<span class="layui-tree-iconClick"
|
||||||
|
><i class="layui-icon layui-icon-file"></i></span
|
||||||
|
><span class="layui-tree-txt">延安</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<style scoped></style>
|
14
src/module/tree/props.ts
Normal file
14
src/module/tree/props.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { TreeEmits, TreeProps } from '/@src/module/tree/type'
|
||||||
|
|
||||||
|
export const treeProps = withDefaults(defineProps<TreeProps>(), {
|
||||||
|
showCheckbox: false,
|
||||||
|
accordion: false,
|
||||||
|
onlyIconControl: false,
|
||||||
|
isJump: false,
|
||||||
|
showLine: true,
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-ignore
|
||||||
|
edit: true
|
||||||
|
})
|
||||||
|
|
||||||
|
export const emit = defineEmits<TreeEmits>()
|
140
src/module/tree/type.ts
Normal file
140
src/module/tree/type.ts
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
/**
|
||||||
|
* defineProps 暂不支付外部导入的复杂类型,这里备用后续迁移。
|
||||||
|
* 暂时 在index.vue内部单独实现一份
|
||||||
|
*/
|
||||||
|
import { VNode, VNodeChild } from 'vue'
|
||||||
|
|
||||||
|
export interface TreeData {
|
||||||
|
/**
|
||||||
|
* 节点唯一索引值,用于对指定节点进行各类操作
|
||||||
|
*/
|
||||||
|
id: () => (string | number) | string | number
|
||||||
|
/**
|
||||||
|
* 节点标题
|
||||||
|
*/
|
||||||
|
title: (() => string) | string
|
||||||
|
/**
|
||||||
|
* 节点字段名
|
||||||
|
*/
|
||||||
|
field: (() => string) | string
|
||||||
|
/**
|
||||||
|
* 子节点。支持设定选项同父节点
|
||||||
|
*/
|
||||||
|
children: TreeData[]
|
||||||
|
/**
|
||||||
|
* 点击节点弹出新窗口对应的 url。需开启 isJump 参数
|
||||||
|
*/
|
||||||
|
href: string | URL
|
||||||
|
/**
|
||||||
|
* 节点是否初始展开,默认 false
|
||||||
|
*/
|
||||||
|
spread: boolean
|
||||||
|
/**
|
||||||
|
* 节点是否初始为选中状态(如果开启复选框的话),默认 false
|
||||||
|
*/
|
||||||
|
checked: boolean
|
||||||
|
/**
|
||||||
|
* 节点是否为禁用状态。默认 false
|
||||||
|
*/
|
||||||
|
disabled: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
type EditAction = 'add' | 'update' | 'del'
|
||||||
|
|
||||||
|
type EditType = boolean | EditAction[]
|
||||||
|
|
||||||
|
export interface TreeProps {
|
||||||
|
/**
|
||||||
|
* 数据源
|
||||||
|
*/
|
||||||
|
data?: TreeData
|
||||||
|
/**
|
||||||
|
* 是否显示复选框 默认 false
|
||||||
|
*/
|
||||||
|
showCheckbox?: boolean
|
||||||
|
/**
|
||||||
|
* 是否开启节点的操作图标。默认 false。
|
||||||
|
若为 true,则默认显示“改删”图标
|
||||||
|
若为 数组,则可自由配置操作图标的显示状态和顺序,目前支持的操作图标有:add、update、del,如:
|
||||||
|
edit: ['add', 'update', 'del']
|
||||||
|
*/
|
||||||
|
edit?: EditType
|
||||||
|
/**
|
||||||
|
* 是否开启手风琴模式,默认 false
|
||||||
|
*/
|
||||||
|
accordion?: boolean
|
||||||
|
/**
|
||||||
|
* 是否仅允许节点左侧图标控制展开收缩。默认 false(即点击节点本身也可控制)。若为 true,则只能通过节点左侧图标来展开收缩
|
||||||
|
*/
|
||||||
|
onlyIconControl?: boolean
|
||||||
|
/**
|
||||||
|
* 是否允许点击节点时弹出新窗口跳转。默认 false,若开启,需在节点数据中设定 link 参数(值为 url 格式
|
||||||
|
*/
|
||||||
|
isJump?: boolean
|
||||||
|
/**
|
||||||
|
* 是否开启连接线。默认 true,若设为 false,则节点左侧出现三角图标。
|
||||||
|
*/
|
||||||
|
showLine?: boolean
|
||||||
|
/**
|
||||||
|
* 自定义各类默认文本,目前支持以下设定:
|
||||||
|
*/
|
||||||
|
text?: {
|
||||||
|
/**
|
||||||
|
* 节点默认名称
|
||||||
|
*/
|
||||||
|
defaultNodeName?: () => string | string
|
||||||
|
/**
|
||||||
|
* 数据为空时的提示文本
|
||||||
|
*/
|
||||||
|
none?: () => string | string | VNode | Element
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TreeNode {
|
||||||
|
/**
|
||||||
|
* 当前点击的节点数据
|
||||||
|
*/
|
||||||
|
data: TreeData
|
||||||
|
/**
|
||||||
|
* 节点的展开状态
|
||||||
|
*/
|
||||||
|
state: 'open' | 'close' | 'normal'
|
||||||
|
/**
|
||||||
|
* 当前节点元素
|
||||||
|
*/
|
||||||
|
elem: Element | VNode | VNodeChild
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TreeEmits {
|
||||||
|
/**
|
||||||
|
* 节点被点击后触发
|
||||||
|
* @param e 事件
|
||||||
|
* @param treeNode
|
||||||
|
*/
|
||||||
|
(e: 'on-click', treeNode: TreeNode): void
|
||||||
|
/**
|
||||||
|
* 点击复选框时触发
|
||||||
|
* @param e 事件
|
||||||
|
* @param treeNode
|
||||||
|
*/
|
||||||
|
(e: 'on-check', treeNode: TreeNode): void
|
||||||
|
/**
|
||||||
|
* 操作节点的回调
|
||||||
|
* @param e 事件
|
||||||
|
* @param treeNode
|
||||||
|
*/
|
||||||
|
(e: 'on-operate', treeNode: TreeNode): void
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export interface TreeExpose {
|
||||||
|
/**
|
||||||
|
* 返回选中的节点数据
|
||||||
|
* 一般来说,v-model就够使了,但不排除需要直接获取其值的时候,此时通过该方法获取
|
||||||
|
* eg: treeRef.getChecked()
|
||||||
|
*/
|
||||||
|
getChecked: () => TreeData
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置节点勾选 setChecked 变为v-model控制
|
||||||
|
// 实例重载 reload 变为v-model控制
|
Loading…
Reference in New Issue
Block a user