@ebiz/designer-components 0.0.19 → 0.0.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,46 +1,47 @@
1
1
  <template>
2
2
  <div class="ebiz-tree-selector">
3
- <div class="selected-items" v-if="modelValue && modelValue.length">
4
- <div v-for="(item, index) in modelValue" :key="index" class="selected-item">
5
- <span class="item-text">{{ item.label }}</span>
6
- <span class="item-remove" @click.stop="removeItem(index)">×</span>
3
+ <div class="selected-items" v-if="modelValue && modelValue.length">
4
+ <div v-for="(item, index) in modelValue" :key="index" class="selected-item">
5
+ <span class="item-text">{{ item.label }}</span>
6
+ <span class="item-remove" @click="removeItem(index)">×</span>
7
+ </div>
7
8
  </div>
8
- </div>
9
- <t-button @click="showDialog" variant="text" theme="primary" size="small"> 添加 </t-button>
10
-
11
- <EbizDialog v-model:visible="dialogVisible" header="选择人员/部门" width="800px" placement="center" confirmBtn="确定"
12
- cancelBtn="取消" @confirm="handleConfirm" @cancel="handleCancel">
13
- <div class="selector-container">
14
- <!-- 左侧选择区域 -->
15
- <div class="left-panel">
16
- <!-- 顶部搜索区域 -->
17
- <div class="search-box">
18
- <t-input v-model="searchText" placeholder="搜索成员、部门或标签" clearable>
19
- <template #suffix-icon>
20
- <t-icon name="search"></t-icon>
21
- </template>
22
- </t-input>
23
- </div>
24
-
25
- <!-- 选项卡 -->
26
- <t-tabs v-model="activeTab" class="selector-tabs">
27
- <t-tab-panel value="organization" label="组织架构" :destroyOnHide="false">
28
-
29
- </t-tab-panel>
30
- <!-- <t-tab-panel value="department" label="部门"></t-tab-panel> -->
31
- <!-- <t-tab-panel value="position" label="岗位"></t-tab-panel> -->
32
- <t-tab-panel value="employee" label="员工"></t-tab-panel>
33
- </t-tabs>
34
-
35
- <!-- 树形结构区域 -->
36
- <div class="tree-content">
37
- <div v-if="loading" class="loading-container">
38
- <t-loading />
9
+ <t-button @click="showDialog" variant="text" theme="primary" size="small"> 添加 </t-button>
10
+
11
+ <EbizDialog attach="body" :zIndex="10000" v-model:visible="dialogVisible" header="选择人员/部门" width="800px"
12
+ placement="center" confirmBtn="确定" cancelBtn="取消" @confirm="handleConfirm" @cancel="handleCancel"
13
+ @close="handleCancel">
14
+ <div class="selector-container">
15
+ <!-- 左侧选择区域 -->
16
+ <div class="left-panel">
17
+ <!-- 顶部搜索区域 -->
18
+ <div class="search-box">
19
+ <t-input v-model="searchText" placeholder="搜索成员、部门或标签" clearable>
20
+ <template #suffix-icon>
21
+ <t-icon name="search"></t-icon>
22
+ </template>
23
+ </t-input>
39
24
  </div>
40
- <EbizTree ref="organizationTree" v-show="activeTab === 'organization'" checkable :items="organizationData"
41
- v-model="checkedNodes" v-model:expanded="expandedNodes" :disable-check="disableCheck"
42
- :keys="{ label: 'name', value: 'id', children: 'childs' }" @change="handleChange" />
43
- <!-- <EbizTree
25
+
26
+ <!-- 选项卡 -->
27
+ <t-tabs v-model="activeTab" class="selector-tabs">
28
+ <t-tab-panel value="organization" label="组织架构" :destroyOnHide="false">
29
+
30
+ </t-tab-panel>
31
+ <!-- <t-tab-panel value="department" label="部门"></t-tab-panel> -->
32
+ <!-- <t-tab-panel value="position" label="岗位"></t-tab-panel> -->
33
+ <t-tab-panel value="employee" label="员工"></t-tab-panel>
34
+ </t-tabs>
35
+
36
+ <!-- 树形结构区域 -->
37
+ <div class="tree-content">
38
+ <div v-if="loading" class="loading-container">
39
+ <t-loading />
40
+ </div>
41
+ <EbizTree ref="organizationTree" v-show="activeTab === 'organization'" checkable :items="organizationData"
42
+ v-model="checkedNodes" v-model:expanded="expandedNodes" :disable-check="disableCheck"
43
+ :keys="{ label: 'name', value: 'id', children: 'childs' }" />
44
+ <!-- <EbizTree
44
45
  v-else-if="activeTab === 'department'"
45
46
  checkable
46
47
  :items="filteredData."
@@ -54,31 +55,31 @@
54
55
  v-model="checkedNodes"
55
56
  :disable-check="disableCheck"
56
57
  /> -->
57
- <EbizTree ref="employeeTree" v-show="activeTab === 'employee'" checkable :items="employeeData"
58
- :keys="{ label: 'label', value: 'bindid', children: 'childs' }" v-model="checkedUserNodes"
59
- :disable-check="disableCheck" />
58
+ <EbizTree ref="employeeTree" v-show="activeTab === 'employee'" checkable :items="employeeData"
59
+ :keys="{ label: 'label', value: 'bindid', children: 'childs' }" v-model="checkedUserNodes"
60
+ :disable-check="disableCheck" />
61
+ </div>
60
62
  </div>
61
- </div>
62
63
 
63
- <!-- 右侧已选区域 -->
64
- <div class="right-panel">
65
- <div class="selected-title">已选择的部门、成员</div>
66
- <div class="selected-count">共 {{ [...selectPreview, ...selectPreviewUser].length }} 项</div>
67
- <div class="selected-list">
68
- <div v-for="(item, index) in [...selectPreview,...selectPreviewUser]" :key="index"
69
- class="selected-list-item">
70
- <t-icon :name="getIconForType(item)" class="item-icon" />
71
- <span class="selected-label">{{ item.label }}</span>
72
- <t-icon name="close-circle" class="remove-icon" @click="removePreviewItem(item)" />
73
- </div>
74
- <div v-if="[...selectPreview, ...selectPreviewUser].length === 0" class="no-selection">
75
- <t-icon name="info-circle" />
76
- <span style="user-select: none">请在左侧选择部门或成员</span>
64
+ <!-- 右侧已选区域 -->
65
+ <div class="right-panel">
66
+ <div class="selected-title">已选择的部门、成员</div>
67
+ <div class="selected-count">共 {{ [...selectPreview, ...selectPreviewUser].length }} 项</div>
68
+ <div class="selected-list">
69
+ <div v-for="(item, index) in [...selectPreview,...selectPreviewUser]" :key="index"
70
+ class="selected-list-item">
71
+ <t-icon :name="getIconForType(item)" class="item-icon" />
72
+ <span class="selected-label">{{ item.label }}</span>
73
+ <t-icon name="close-circle" class="remove-icon" @click="removePreviewItem(item)" />
74
+ </div>
75
+ <div v-if="[...selectPreview, ...selectPreviewUser].length === 0" class="no-selection">
76
+ <t-icon name="info-circle" />
77
+ <span style="user-select: none">请在左侧选择部门或成员</span>
78
+ </div>
77
79
  </div>
78
80
  </div>
79
81
  </div>
80
- </div>
81
- </EbizDialog>
82
+ </EbizDialog>
82
83
  </div>
83
84
  </template>
84
85
 
@@ -153,7 +154,7 @@ const fetchApiData = async () => {
153
154
  '/appdata/execute/plugin?key=organizational_structure'
154
155
  )
155
156
  employeeData.value = (await dataService.fetch(
156
- {keyWord:activeTab.value === 'employee' ? searchText.value : ''},
157
+ {postEnable:true, keyWord:activeTab.value === 'employee' ? searchText.value : ''},
157
158
  {},
158
159
  "/appdata/execute/plugin?key=all_active_employesse"
159
160
  )).map(i=>({
@@ -227,7 +228,6 @@ function removePreviewItem(item) {
227
228
  function removeItem(index) {
228
229
  const newValue = [...props.modelValue]
229
230
  newValue.splice(index, 1)
230
- console.log(newValue,230)
231
231
  emit('update:modelValue', newValue)
232
232
  emit('change', newValue)
233
233
  }
@@ -236,10 +236,10 @@ function removeItem(index) {
236
236
  watch(
237
237
  checkedNodes,
238
238
  (newValues) => {
239
- if (!organizationTree.value.treeRef) return
240
- selectPreview.value = newValues.map(organizationTree.value.treeRef.getItem).map((i) => ({
239
+ if (!organizationTree.value?.treeRef) return
240
+ selectPreview.value = (newValues.map(organizationTree.value.treeRef.getItem) ?? []).map((i) => ({
241
241
  label: i?.label,
242
- type: i?.data?.type || i.type,
242
+ type: i?.data?.type || i?.type,
243
243
  bindid: i?.value
244
244
  }))
245
245
  },
@@ -264,10 +264,6 @@ watch(activeTab,nVal=>{
264
264
  watch(searchText,nVal=>{
265
265
  fetchApiData()
266
266
  })
267
- // 组件挂载时,预加载数据
268
- onMounted(() => {
269
- showDialog()
270
- })
271
267
  </script>
272
268
 
273
269
  <style scoped>
@@ -1,6 +1,7 @@
1
1
  <template>
2
2
  <div>
3
- <slot name="content"></slot>
3
+ <slot></slot>
4
+ <slot v-if="$slots.content" name="content"></slot>
4
5
  </div>
5
6
  </template>
6
7
 
@@ -0,0 +1,75 @@
1
+ <template>
2
+ <div>
3
+ <div>
4
+ <div>123123123</div>
5
+ </div>
6
+ <t-descriptions v-bind="$attrs" :border="border" :colon="colon" :column="column" :layout="layout"
7
+ :item-layout="itemLayout" :size="size" :title="title" :table-layout="tableLayout"
8
+ :table-border-color="tableBorderColor">
9
+ <slot></slot>
10
+ <slot name="title"></slot>
11
+ </t-descriptions>
12
+ </div>
13
+
14
+ </template>
15
+
16
+ <script setup>
17
+ import { defineProps, defineEmits } from 'vue';
18
+ import { Descriptions as TDescriptions } from 'tdesign-vue-next';
19
+
20
+ const props = defineProps({
21
+ border: {
22
+ type: Boolean,
23
+ default: false
24
+ },
25
+ colon: {
26
+ type: Boolean,
27
+ default: false
28
+ },
29
+ column: {
30
+ type: Number,
31
+ default: 2
32
+ },
33
+ layout: {
34
+ type: String,
35
+ default: 'horizontal',
36
+ validator(val) {
37
+ return ['horizontal', 'vertical'].includes(val);
38
+ }
39
+ },
40
+ itemLayout: {
41
+ type: String,
42
+ default: 'horizontal',
43
+ validator(val) {
44
+ return ['horizontal', 'vertical'].includes(val);
45
+ }
46
+ },
47
+ size: {
48
+ type: String,
49
+ default: 'medium',
50
+ validator(val) {
51
+ return ['small', 'medium', 'large'].includes(val);
52
+ }
53
+ },
54
+ title: {
55
+ type: String,
56
+ default: ''
57
+ },
58
+ tableLayout: {
59
+ type: String,
60
+ default: 'fixed',
61
+ validator(val) {
62
+ return ['auto', 'fixed'].includes(val);
63
+ }
64
+ },
65
+ tableBorderColor: {
66
+ type: String,
67
+ default: ''
68
+ }
69
+ });
70
+
71
+ defineEmits([]);
72
+ </script>
73
+
74
+ <style scoped>
75
+ </style>
@@ -0,0 +1,51 @@
1
+ <template>
2
+ <div>
3
+ <div>123123123</div>
4
+ <t-descriptions-item v-bind="$attrs" :label="label" :span="span" :layout="layout" :className="className"
5
+ :labelClassName="labelClassName" :contentClassName="contentClassName">
6
+ <slot></slot>
7
+ </t-descriptions-item>
8
+ </div>
9
+
10
+ </template>
11
+
12
+ <script setup>
13
+ import { defineProps, defineEmits } from 'vue';
14
+ import { DescriptionsItem as TDescriptionsItem } from 'tdesign-vue-next';
15
+
16
+ const props = defineProps({
17
+ label: {
18
+ type: String,
19
+ default: ''
20
+ },
21
+ span: {
22
+ type: Number,
23
+ default: 1
24
+ },
25
+ layout: {
26
+ type: String,
27
+ default: '',
28
+ validator(val) {
29
+ if (!val) return true;
30
+ return ['horizontal', 'vertical'].includes(val);
31
+ }
32
+ },
33
+ className: {
34
+ type: String,
35
+ default: ''
36
+ },
37
+ labelClassName: {
38
+ type: String,
39
+ default: ''
40
+ },
41
+ contentClassName: {
42
+ type: String,
43
+ default: ''
44
+ }
45
+ });
46
+
47
+ defineEmits([]);
48
+ </script>
49
+
50
+ <style scoped>
51
+ </style>
@@ -1,5 +1,6 @@
1
1
  <template>
2
2
  <t-form
3
+ ref="formRef"
3
4
  :class="customClass"
4
5
  :data="data"
5
6
  :colon="colon"
@@ -30,7 +31,7 @@ export default {
30
31
  </script>
31
32
 
32
33
  <script setup>
33
- import { defineProps, defineEmits } from 'vue';
34
+ import { defineProps, defineEmits, ref, defineExpose } from 'vue';
34
35
  import { Form as TForm } from 'tdesign-vue-next';
35
36
 
36
37
  defineProps({
@@ -127,6 +128,10 @@ const handleSubmit = (e) => {
127
128
  const handleValidate = (params) => {
128
129
  emit('validate', params);
129
130
  };
131
+ const formRef = ref();
132
+ defineExpose({
133
+ formRef
134
+ })
130
135
  </script>
131
136
 
132
137
  <style lang="less" scoped>
@@ -0,0 +1,150 @@
1
+ <template>
2
+ <div class="popconfirm-example">
3
+ <h2>气泡确认框示例</h2>
4
+
5
+ <h3>1. 基础用法</h3>
6
+ <div class="example-item">
7
+ <ebiz-popconfirm content="确定要删除这条数据吗?">
8
+ <ebiz-tdesign-button>删除</ebiz-tdesign-button>
9
+ </ebiz-popconfirm>
10
+ </div>
11
+
12
+ <h3>2. 不同主题</h3>
13
+ <div class="example-item">
14
+ <ebiz-space>
15
+ <ebiz-popconfirm content="这是默认主题" theme="default">
16
+ <ebiz-tdesign-button>默认主题</ebiz-tdesign-button>
17
+ </ebiz-popconfirm>
18
+
19
+ <ebiz-popconfirm content="这是警告主题" theme="warning">
20
+ <ebiz-tdesign-button>警告主题</ebiz-tdesign-button>
21
+ </ebiz-popconfirm>
22
+
23
+ <ebiz-popconfirm content="这是危险主题" theme="danger">
24
+ <ebiz-tdesign-button>危险主题</ebiz-tdesign-button>
25
+ </ebiz-popconfirm>
26
+ </ebiz-space>
27
+ </div>
28
+
29
+ <h3>3. 不同位置</h3>
30
+ <div class="example-item">
31
+ <ebiz-space>
32
+ <ebiz-popconfirm content="这是顶部弹出" placement="top">
33
+ <ebiz-tdesign-button>顶部</ebiz-tdesign-button>
34
+ </ebiz-popconfirm>
35
+
36
+ <ebiz-popconfirm content="这是左侧弹出" placement="left">
37
+ <ebiz-tdesign-button>左侧</ebiz-tdesign-button>
38
+ </ebiz-popconfirm>
39
+
40
+ <ebiz-popconfirm content="这是右侧弹出" placement="right">
41
+ <ebiz-tdesign-button>右侧</ebiz-tdesign-button>
42
+ </ebiz-popconfirm>
43
+
44
+ <ebiz-popconfirm content="这是底部弹出" placement="bottom">
45
+ <ebiz-tdesign-button>底部</ebiz-tdesign-button>
46
+ </ebiz-popconfirm>
47
+ </ebiz-space>
48
+ </div>
49
+
50
+ <h3>4. 自定义按钮文本</h3>
51
+ <div class="example-item">
52
+ <ebiz-popconfirm
53
+ content="确定要执行此操作吗?"
54
+ confirm-btn="执行"
55
+ cancel-btn="取消执行"
56
+ >
57
+ <ebiz-tdesign-button>自定义按钮文本</ebiz-tdesign-button>
58
+ </ebiz-popconfirm>
59
+ </div>
60
+
61
+ <h3>5. 事件处理</h3>
62
+ <div class="example-item">
63
+ <ebiz-popconfirm
64
+ content="确定要继续吗?"
65
+ @confirm="handleConfirm"
66
+ @cancel="handleCancel"
67
+ >
68
+ <ebiz-tdesign-button>点击触发事件</ebiz-tdesign-button>
69
+ </ebiz-popconfirm>
70
+ </div>
71
+
72
+ <h3>6. 不同触发方式</h3>
73
+ <div class="example-item">
74
+ <ebiz-space>
75
+ <ebiz-popconfirm content="点击触发" trigger="click">
76
+ <ebiz-tdesign-button>点击触发</ebiz-tdesign-button>
77
+ </ebiz-popconfirm>
78
+
79
+ <ebiz-popconfirm content="悬浮触发" trigger="hover">
80
+ <ebiz-tdesign-button>悬浮触发</ebiz-tdesign-button>
81
+ </ebiz-popconfirm>
82
+
83
+ <ebiz-popconfirm content="获得焦点触发" trigger="focus">
84
+ <ebiz-tdesign-input placeholder="点击输入框"></ebiz-tdesign-input>
85
+ </ebiz-popconfirm>
86
+ </ebiz-space>
87
+ </div>
88
+
89
+ <h3>7. 控制显示状态</h3>
90
+ <div class="example-item">
91
+ <ebiz-tdesign-button @click="visible = !visible">
92
+ {{ visible ? '隐藏' : '显示' }}气泡确认框
93
+ </ebiz-tdesign-button>
94
+
95
+ <ebiz-popconfirm
96
+ v-model:visible="visible"
97
+ content="这是一个受控的气泡确认框"
98
+ >
99
+ <ebiz-tdesign-button style="margin-left: 16px;">
100
+ 受控组件
101
+ </ebiz-tdesign-button>
102
+ </ebiz-popconfirm>
103
+ </div>
104
+ </div>
105
+ </template>
106
+
107
+ <script setup>
108
+ import { ref } from 'vue';
109
+ import { EbizPopconfirm, EbizTdesignButton, EbizTdesignInput, EbizSpace, EbizMessage } from '../../index';
110
+
111
+ // 控制气泡确认框显示状态
112
+ const visible = ref(false);
113
+
114
+ // 确认事件处理
115
+ const handleConfirm = () => {
116
+ EbizMessage.success('确认操作');
117
+ };
118
+
119
+ // 取消事件处理
120
+ const handleCancel = () => {
121
+ EbizMessage.info('取消操作');
122
+ };
123
+ </script>
124
+
125
+ <style lang="less" scoped>
126
+ .popconfirm-example {
127
+ padding: 20px;
128
+
129
+ h2 {
130
+ margin-bottom: 24px;
131
+ font-weight: bold;
132
+ }
133
+
134
+ h3 {
135
+ margin-top: 24px;
136
+ margin-bottom: 16px;
137
+ font-weight: bold;
138
+ font-size: 16px;
139
+ border-left: 4px solid #0052d9;
140
+ padding-left: 12px;
141
+ }
142
+
143
+ .example-item {
144
+ margin-bottom: 24px;
145
+ padding: 16px;
146
+ border: 1px solid #eee;
147
+ border-radius: 6px;
148
+ }
149
+ }
150
+ </style>
package/src/index.js CHANGED
@@ -55,8 +55,17 @@ import EbizDetailBlock from './components/EbizDetailBlock.vue';
55
55
  import EbizTree from './components/EbizTree.vue';
56
56
  import EbizTreeSelector from './components/EbizTreeSelector.vue';
57
57
  import EbizTimePicker from './components/EbizTimePicker.vue';
58
+ import EbizPopconfirm from './components/EbizPopconfirm.vue';
59
+ import EbizTreeMergeTable from './components/EbizTreeMergeTable.vue';
60
+ import EbizAutoForm from './components/EbizAutoForm.vue';
58
61
  import { MessagePlugin as EbizMessage } from 'tdesign-vue-next';
59
62
 
63
+ // import EbizDescriptions from './components/EbizDescriptions.vue';
64
+ // import EbizDescriptionsItem from './components/EbizDescriptionsItem.vue'
65
+ import { Descriptions as EbizDescriptions } from 'tdesign-vue-next';
66
+ import { DescriptionsItem as EbizDescriptionsItem } from 'tdesign-vue-next';
67
+ import { DescriptionsItem as TDescriptionsItem } from 'tdesign-vue-next';
68
+
60
69
  // 导入简洁数据服务
61
70
  import dataService from "./apiService/simpleDataService";
62
71
 
@@ -165,5 +174,15 @@ export {
165
174
  EbizTree,
166
175
  EbizTreeSelector,
167
176
  // 时间选择器组件
168
- EbizTimePicker
177
+ EbizTimePicker,
178
+ // 气泡确认框组件
179
+ EbizPopconfirm,
180
+ // 树形合并表格组件
181
+ EbizTreeMergeTable,
182
+ // 自动表单组件
183
+ EbizAutoForm,
184
+ // 新增 EbizDescriptions 和 EbizDescriptionsItem
185
+ EbizDescriptions,
186
+ EbizDescriptionsItem,
187
+ TDescriptionsItem
169
188
  };
@@ -2,6 +2,7 @@ import { createRouter, createWebHistory } from 'vue-router'
2
2
  import Home from '../views/Home.vue'
3
3
  import ButtonView from '../views/Button.vue'
4
4
  import TableView from '../views/TableView.vue'
5
+ import TdesignDescriptions from '../views/TdesignDescriptions.vue'
5
6
 
6
7
  const routes = [
7
8
  {
@@ -248,7 +249,7 @@ const routes = [
248
249
  path: '/page-header',
249
250
  name: 'PageHeader',
250
251
  component: () => import('../views/PageHeaderDemo.vue'),
251
- meta: { title: 'Ebiz页面头部组件示例', icon: 'header' }
252
+ meta: { title: 'Ebiz页面头部组件示例' }
252
253
  },
253
254
  {
254
255
  path: '/table-demo',
@@ -263,17 +264,11 @@ const routes = [
263
264
  meta: { title: 'Ebiz表格排序组件示例' }
264
265
  },
265
266
  {
266
- path: '/ebiz-detail-block',
267
- name: 'EbizDetailBlock',
267
+ path: '/detail-block',
268
+ name: 'DetailBlock',
268
269
  component: () => import('../views/EbizDetailBlockDemo.vue'),
269
270
  meta: { title: 'Ebiz详情块组件示例' }
270
271
  },
271
- {
272
- path: '/tree',
273
- name: 'Tree',
274
- component: () => import('../views/TreeDemo.vue'),
275
- meta: { title: 'Ebiz树组件示例' }
276
- },
277
272
  {
278
273
  path: '/tree-demo',
279
274
  name: 'TreeDemo',
@@ -284,21 +279,31 @@ const routes = [
284
279
  path: '/tree-selector-demo',
285
280
  name: 'TreeSelectorDemo',
286
281
  component: () => import('../views/TreeSelectorDemo.vue'),
287
- meta: {
288
- title: '树形选择器'
289
- }
290
- },
291
- {
292
- path: '/tree-selector',
293
- name: 'TreeSelector',
294
- component: () => import('../views/TreeSelectorDemo.vue'),
295
- meta: { title: '树选择器组件示例' }
282
+ meta: { title: 'Ebiz树选择器组件示例' }
296
283
  },
297
284
  {
298
285
  path: '/time-picker',
299
286
  name: 'TimePicker',
300
287
  component: () => import('../views/TimePickerDemo.vue'),
301
- meta: { title: '时间选择器组件示例' }
288
+ meta: { title: 'Ebiz时间选择器组件示例' }
289
+ },
290
+ {
291
+ path: '/tdesign-descriptions',
292
+ name: 'TdesignDescriptions',
293
+ component: TdesignDescriptions,
294
+ meta: { title: 'TDesign描述列表组件示例' }
295
+ },
296
+ {
297
+ path: '/popconfirm',
298
+ name: 'Popconfirm',
299
+ component: () => import('../views/PopconfirmDemo.vue'),
300
+ meta: { title: 'Ebiz气泡确认框组件示例' }
301
+ },
302
+ {
303
+ path: '/tree-merge-table-demo',
304
+ name: 'TreeMergeTableDemo',
305
+ component: () => import('../views/TreeMergeTableDemo.vue'),
306
+ meta: { title: '树形合并表格组件示例' }
302
307
  }
303
308
  ]
304
309