wui-components-v2 1.1.69 → 1.1.71
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.
- package/api/core/index.ts +74 -74
- package/api/feishu.ts +20 -20
- package/api/index.ts +4 -4
- package/api/login.ts +51 -51
- package/api/menu.ts +45 -45
- package/api/page.ts +114 -114
- package/api/sys.ts +12 -12
- package/api/tree.ts +28 -28
- package/components/action-popup/action-popup.vue +116 -116
- package/components/add-address-list/add-address-list.vue +187 -187
- package/components/add-address-page/add-address-page.vue +77 -77
- package/components/add-address-page/config.ts +297 -297
- package/components/audio-play/audio-play.vue +220 -220
- package/components/batch-upload-file/batch-upload-file.vue +75 -75
- package/components/card-botom-buttons/card-botom-buttons.vue +279 -279
- package/components/custom-date-picker/custom-date-picker.vue +106 -106
- package/components/custom-select-picker/custom-select-picker.vue +95 -95
- package/components/demo-block/demo-block.vue +63 -63
- package/components/demo-card/demo-card.vue +44 -44
- package/components/detail-popup/detail-popup.vue +99 -99
- package/components/evaluation-page/evaluation-page.vue +196 -196
- package/components/fold-card/fold-card.vue +171 -171
- package/components/form-control/form-control.vue +661 -661
- package/components/global-loading/GlobalLoading.md +366 -366
- package/components/global-loading/global-loading.vue +55 -55
- package/components/global-message/GlobalMessage.md +570 -570
- package/components/global-message/global-message.vue +68 -68
- package/components/global-toast/GlobalToast.md +261 -261
- package/components/global-toast/global-toast.vue +56 -56
- package/components/label-value/label-value.vue +144 -144
- package/components/label-value/open-value-more.vue +56 -56
- package/components/list-top-buttons/list-top-buttons.vue +19 -19
- package/components/loading/loading.vue +5 -5
- package/components/login-form/login-form.vue +126 -126
- package/components/login-form-box/login-form-box.vue +65 -65
- package/components/mulselect-picker/mulselect-picker.vue +86 -86
- package/components/phone-login-form/phone-login-form.vue +204 -204
- package/components/privacy-popup/privacy-popup.vue +191 -191
- package/components/product-card/product-card.vue +201 -201
- package/components/scan-input/scan-input.vue +406 -406
- package/components/search/search.vue +128 -128
- package/components/select-col-picker/select-col-picker.vue +168 -168
- package/components/tab-search/tab-search.vue +73 -73
- package/components/tree-select/components/TreeNode.vue +200 -200
- package/components/tree-select/components/index.vue +471 -471
- package/components/tree-select/components/tree-select.vue +56 -56
- package/components/tree-select/index.vue +93 -93
- package/components/user-choose/user-choose.vue +169 -151
- package/components/video-play/video-play.vue +56 -56
- package/components/wui-auto-update-component/wui-auto-update-component.vue +132 -132
- package/components/wui-default/wui-default.vue +49 -49
- package/components/wui-details-page/wui-details-page.vue +147 -147
- package/components/wui-edit-page/wui-edit-page-copy.vue +757 -757
- package/components/wui-edit-page/wui-edit-page.vue +793 -793
- package/components/wui-enume-select-control/wui-enume-select-control.vue +92 -92
- package/components/wui-list/wui-list.vue +235 -235
- package/components/wui-login/wui-login.vue +43 -43
- package/components/wui-login1/wui-login.vue +41 -41
- package/components/wui-menus/wui-menus-top.vue +137 -137
- package/components/wui-menus/wui-menus-top1.vue +8 -8
- package/components/wui-menus/wui-menus.vue +247 -247
- package/components/wui-menus1/components/banner-carousel.vue +320 -320
- package/components/wui-menus1/components/navbar.vue +43 -43
- package/components/wui-menus1/components/quick-panel.vue +55 -55
- package/components/wui-menus1/components/search-bar.vue +49 -49
- package/components/wui-menus1/components/section-menus.vue +208 -208
- package/components/wui-menus1/wui-menus-top.vue +718 -718
- package/components/wui-menus1/wui-menus-top1.vue +398 -398
- package/components/wui-menus1/wui-menus.vue +564 -564
- package/components/wui-notify-info/notify-handle.vue +53 -53
- package/components/wui-notify-info/wui-notify-info.vue +280 -280
- package/components/wui-scan-binding-sensor/wui-scan-binding-sensor.vue +75 -75
- package/components/wui-search-history-babbar/components/SearchBar.vue +70 -70
- package/components/wui-search-history-babbar/wui-search-history-babbar.vue +204 -204
- package/components/wui-select-list/wui-select-list.vue +310 -310
- package/components/wui-select-popup/wui-select-popup.vue +613 -612
- package/components/wui-system-settings/wui-system-settings.vue +144 -144
- package/components/wui-tabbar/wui-tabbar.vue +106 -106
- package/components/wui-tree-page/components/tree-item.vue +238 -238
- package/components/wui-tree-page/wui-tree-page.vue +297 -297
- package/components/wui-update-component/wui-update-component.vue +221 -221
- package/components/wui-user/wui-user.vue +202 -202
- package/composables/types/theme.ts +65 -65
- package/composables/types/user.ts +5 -5
- package/composables/useColorGenerator.ts +221 -221
- package/composables/useCompanyFieldFilter.ts +91 -91
- package/composables/useEnumes.ts +43 -43
- package/composables/useEventBus.ts +37 -37
- package/composables/useGlobalLoading.ts +47 -47
- package/composables/useGlobalMessage.ts +53 -53
- package/composables/useGlobalToast.ts +63 -63
- package/composables/useLocale.ts +54 -54
- package/composables/useManualTheme.ts +179 -179
- package/composables/useMenus.ts +193 -193
- package/composables/useSectionMenus.ts +120 -120
- package/composables/useTabbar.ts +50 -50
- package/composables/useTheme.ts +74 -74
- package/composables/useUser.ts +24 -24
- package/index.d.ts +90 -90
- package/index.ts +83 -83
- package/package.json +24 -24
- package/static/iconfont/iconfont.css +63 -63
- package/store/language.ts +151 -151
- package/store/manualThemeStore.ts +143 -143
- package/store/persist.ts +41 -41
- package/store/themeStore.ts +74 -74
- package/store/userStore.ts +22 -22
- package/styles/dark-mode.css +523 -523
- package/styles/dark-mode.min.css +1 -1
- package/styles/dark-mode.scss +498 -498
- package/type.ts +154 -154
- package/utils/control-tree.ts +353 -353
- package/utils/control-type-supportor.ts +148 -148
- package/utils/eventBus.ts +36 -36
- package/utils/idata-scan.ts +99 -99
- package/utils/index.ts +979 -979
- package/utils/rsaEncrypt.ts +10 -10
|
@@ -1,297 +1,297 @@
|
|
|
1
|
-
<script lang="ts" setup>
|
|
2
|
-
import { computed, defineOptions, onMounted, onUnmounted, ref } from 'vue'
|
|
3
|
-
import { onLoad } from '@dcloudio/uni-app'
|
|
4
|
-
import { useDialog } from '@wot-ui/ui'
|
|
5
|
-
import { useGlobalLoading } from '../../composables/useGlobalLoading'
|
|
6
|
-
import { useGlobalToast } from '../../composables/useGlobalToast'
|
|
7
|
-
import ListTopButtons from '../list-top-buttons/list-top-buttons.vue'
|
|
8
|
-
import { useTreeControlInit } from '../../utils/control-tree'
|
|
9
|
-
import type { TreeNode, nodeType } from '../../utils/control-tree'
|
|
10
|
-
import { generateHighResolutionID } from '../../utils/index'
|
|
11
|
-
import { treeNodeDeleteApi } from '../../api/tree'
|
|
12
|
-
import treeItem from './components/tree-item.vue'
|
|
13
|
-
|
|
14
|
-
defineOptions({
|
|
15
|
-
name: 'WuiTreePage',
|
|
16
|
-
})
|
|
17
|
-
// --- 数据定义 ---
|
|
18
|
-
const searchText = ref('')
|
|
19
|
-
const sourceId = ref('')
|
|
20
|
-
const pageTitle = ref('')
|
|
21
|
-
const mainCode = ref('')
|
|
22
|
-
const addEvent = generateHighResolutionID()// 全局事件名称
|
|
23
|
-
const Zpaging = ref<any>(null)
|
|
24
|
-
const dialog = useDialog()
|
|
25
|
-
const parentId = ref('')
|
|
26
|
-
const parentNodeType = ref<nodeType>('root')
|
|
27
|
-
const targetNodeType = ref<nodeType>('root')
|
|
28
|
-
const { loading } = useGlobalLoading()
|
|
29
|
-
const { success, error } = useGlobalToast()
|
|
30
|
-
|
|
31
|
-
onLoad((option: any) => {
|
|
32
|
-
console.log(option)
|
|
33
|
-
sourceId.value = option.sourceId
|
|
34
|
-
pageTitle.value = option.title
|
|
35
|
-
mainCode.value = option.mainCode || ''
|
|
36
|
-
uni.setNavigationBarTitle({
|
|
37
|
-
title: option.title,
|
|
38
|
-
})
|
|
39
|
-
})
|
|
40
|
-
|
|
41
|
-
const { treeConfig, treeData, findTreeNodeandExpand, getTreeRootData } = useTreeControlInit(sourceId.value, Zpaging)
|
|
42
|
-
|
|
43
|
-
onMounted(async () => {
|
|
44
|
-
// 监听添加成功的事件
|
|
45
|
-
uni.$on(addEvent, async (e) => {
|
|
46
|
-
console.log(e)
|
|
47
|
-
// findTreeNodeandAppend(parentId.value, treeData.value, [{
|
|
48
|
-
// id: e.entityCode,
|
|
49
|
-
// parentId: parentId.value,
|
|
50
|
-
// label: e.data[targetNodeType.value === 'branch' && treeConfig.value.branchLTmplConfig ? treeConfig.value.branchLTmplConfig.primaryColumn.sourceId : targetNodeType.value === 'leaf' && treeConfig.value.leafLTmplConfig? treeConfig.value.leafLTmplConfig.primaryColumn.sourceId : treeConfig.value.rootLTmplConfig.primaryColumn.sourceId],
|
|
51
|
-
// expanded: false,
|
|
52
|
-
// type: targetNodeType.value,
|
|
53
|
-
// loading: false,
|
|
54
|
-
// children: null,
|
|
55
|
-
// }], parentNodeType.value)
|
|
56
|
-
findTreeNodeandExpand({
|
|
57
|
-
id: parentId.value,
|
|
58
|
-
type: parentNodeType.value,
|
|
59
|
-
parentId: '',
|
|
60
|
-
label: '',
|
|
61
|
-
expanded: false,
|
|
62
|
-
loading: false,
|
|
63
|
-
}, treeData.value, 'add')
|
|
64
|
-
// Zpaging.value.reload()
|
|
65
|
-
})
|
|
66
|
-
})
|
|
67
|
-
// 在组件卸载时解绑全局事件
|
|
68
|
-
onUnmounted(() => {
|
|
69
|
-
console.log(`${pageTitle.value}页面卸载`)
|
|
70
|
-
uni.$off(addEvent)
|
|
71
|
-
})
|
|
72
|
-
|
|
73
|
-
function toggleExpand(node: TreeNode) {
|
|
74
|
-
// 展开节点
|
|
75
|
-
findTreeNodeandExpand(node, treeData.value)
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// 添加分支节点
|
|
79
|
-
function handleAddBranch(parentNode: TreeNode) {
|
|
80
|
-
console.log('添加子节点:', parentNode)
|
|
81
|
-
parentId.value = parentNode.id
|
|
82
|
-
parentNodeType.value = parentNode.type
|
|
83
|
-
targetNodeType.value = 'branch'
|
|
84
|
-
uni.navigateTo({
|
|
85
|
-
url: `/pages/edit-page/index?sourceId=${treeConfig.value.branchRatmplId}&title=${pageTitle.value}&mainCode=${parentNode.id}&addEvent=${addEvent}`,
|
|
86
|
-
})
|
|
87
|
-
}
|
|
88
|
-
// 添加叶子节点
|
|
89
|
-
function handleAddLeaf(parentNode: TreeNode) {
|
|
90
|
-
console.log('添加叶子节点:', parentNode)
|
|
91
|
-
parentId.value = parentNode.id
|
|
92
|
-
parentNodeType.value = parentNode.type
|
|
93
|
-
targetNodeType.value = 'leaf'
|
|
94
|
-
uni.navigateTo({
|
|
95
|
-
url: `/pages/edit-page/index?sourceId=${treeConfig.value.leafRatmplId}&title=${pageTitle.value}&mainCode=${parentNode.id}&addEvent=${addEvent}`,
|
|
96
|
-
})
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// 处理更新节点
|
|
100
|
-
function handleUpdate(targetNode: TreeNode) {
|
|
101
|
-
let sourceId = null
|
|
102
|
-
if (targetNode.type === 'leaf') {
|
|
103
|
-
sourceId = treeConfig.value.leafRatmplId
|
|
104
|
-
}
|
|
105
|
-
else if (targetNode.type === 'branch') {
|
|
106
|
-
sourceId = treeConfig.value.branchRatmplId
|
|
107
|
-
}
|
|
108
|
-
else {
|
|
109
|
-
sourceId = treeConfig.value.rootGtmplId
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
uni.navigateTo({
|
|
113
|
-
url: `/pages/edit-page/index?sourceId=${sourceId}&title=${pageTitle.value}&id=${targetNode.id}&mainCode=${targetNode.parentId}&addEvent=${addEvent}`,
|
|
114
|
-
})
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// 过滤后的树形数据
|
|
118
|
-
const filteredTreeData = computed<TreeNode[]>(() => {
|
|
119
|
-
if (!searchText.value) {
|
|
120
|
-
return treeData.value
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
const keyword = searchText.value.toLowerCase()
|
|
124
|
-
|
|
125
|
-
// 过滤节点的递归函数
|
|
126
|
-
const filterNodes = (nodes: TreeNode[]): TreeNode[] => {
|
|
127
|
-
return nodes
|
|
128
|
-
.map((node) => {
|
|
129
|
-
// 复制节点,避免修改原数据
|
|
130
|
-
const newNode = { ...node }
|
|
131
|
-
|
|
132
|
-
// 如果有子节点,递归过滤
|
|
133
|
-
// if (newNode.children && newNode.children.length > 0) {
|
|
134
|
-
// newNode.children = filterNodes(newNode.children)
|
|
135
|
-
// }
|
|
136
|
-
|
|
137
|
-
// 节点名称包含关键词,或者有符合条件的子节点,则保留该节点
|
|
138
|
-
const nodeNameMatch = newNode.label.toLowerCase().includes(keyword)
|
|
139
|
-
// const hasMatchingChildren = newNode.children && newNode.children.length > 0
|
|
140
|
-
|
|
141
|
-
// return nodeNameMatch || hasMatchingChildren ? newNode : null
|
|
142
|
-
return nodeNameMatch ? newNode : null
|
|
143
|
-
})
|
|
144
|
-
.filter(Boolean) as TreeNode[]
|
|
145
|
-
}
|
|
146
|
-
console.log('filterNodes:', filterNodes(treeData.value))
|
|
147
|
-
|
|
148
|
-
return filterNodes(treeData.value)
|
|
149
|
-
})
|
|
150
|
-
// 删除节点
|
|
151
|
-
function handleRemove(targetNode: TreeNode) {
|
|
152
|
-
let sourceId = treeConfig.value.rootGtmplId
|
|
153
|
-
if (targetNode.type === 'leaf') {
|
|
154
|
-
sourceId = treeConfig.value.leafRatmplId || ''
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
if (targetNode.type === 'branch') {
|
|
158
|
-
sourceId = treeConfig.value.branchRatmplId || ''
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
dialog
|
|
162
|
-
.confirm({
|
|
163
|
-
msg: `确定要删除 "${targetNode.label}" 及其子节点吗?`,
|
|
164
|
-
title: '提示',
|
|
165
|
-
beforeConfirm: async () => {
|
|
166
|
-
loading('删除中...')
|
|
167
|
-
try {
|
|
168
|
-
// const res = await editPageConfig(sourceId || '', targetNode.id)
|
|
169
|
-
// const res1 = await editPageDataSave(sourceId || '', targetNode.id, {}, '', res.dtmplConfig.actions[0].id)
|
|
170
|
-
const res1 = await treeNodeDeleteApi(sourceId, targetNode.id)
|
|
171
|
-
if (res1.status === 'success') {
|
|
172
|
-
success('删除成功')
|
|
173
|
-
removeNodeRecursively(filteredTreeData.value, targetNode.id)
|
|
174
|
-
return true
|
|
175
|
-
}
|
|
176
|
-
else {
|
|
177
|
-
error('删除失败')
|
|
178
|
-
return false
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
catch (error1) {
|
|
182
|
-
error('删除失败')
|
|
183
|
-
console.log(error1)
|
|
184
|
-
return false
|
|
185
|
-
}
|
|
186
|
-
},
|
|
187
|
-
})
|
|
188
|
-
.then(() => { })
|
|
189
|
-
.catch((error) => {
|
|
190
|
-
console.log(error)
|
|
191
|
-
})
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
// 递归删除逻辑
|
|
195
|
-
function removeNodeRecursively(list: TreeNode[], idToRemove: string): boolean {
|
|
196
|
-
for (let i = 0; i < list.length; i++) {
|
|
197
|
-
if (list[i].id === idToRemove) {
|
|
198
|
-
list.splice(i, 1)
|
|
199
|
-
return true
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
const children = list[i].children
|
|
203
|
-
if (Array.isArray(children) && children.length > 0) {
|
|
204
|
-
const deleted = removeNodeRecursively(children, idToRemove)
|
|
205
|
-
if (deleted)
|
|
206
|
-
return true
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
return false
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
// --- 搜索逻辑 ---
|
|
213
|
-
/*
|
|
214
|
-
搜索策略:
|
|
215
|
-
1. 遍历树。
|
|
216
|
-
2. 如果节点名称包含关键字,标记高亮(通过prop传给子组件)。
|
|
217
|
-
3. 如果节点包含关键字,或者其子孙节点包含关键字,则该节点必须展开 (expanded = true)。
|
|
218
|
-
*/
|
|
219
|
-
function handleSearch() {
|
|
220
|
-
const keyword = searchText.value.trim().toLowerCase()
|
|
221
|
-
|
|
222
|
-
if (!keyword)
|
|
223
|
-
return
|
|
224
|
-
|
|
225
|
-
// 定义递归搜索函数
|
|
226
|
-
const traverseAndExpand = (nodes: TreeNode[]) => {
|
|
227
|
-
let hasMatchInLevel = false
|
|
228
|
-
|
|
229
|
-
nodes.forEach((node) => {
|
|
230
|
-
// 检查当前节点是否匹配
|
|
231
|
-
const isSelfMatch = node.label.toLowerCase().includes(keyword)
|
|
232
|
-
|
|
233
|
-
// 递归检查子节点
|
|
234
|
-
let hasChildMatch = false
|
|
235
|
-
if (node.children && node.children.length > 0) {
|
|
236
|
-
hasChildMatch = traverseAndExpand(node.children)
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
// 核心逻辑:如果自己匹配,或子节点有匹配,则当前路径应激活/展开
|
|
240
|
-
if (isSelfMatch || hasChildMatch) {
|
|
241
|
-
// node.expanded = true;
|
|
242
|
-
hasMatchInLevel = true
|
|
243
|
-
}
|
|
244
|
-
else {
|
|
245
|
-
// 如果不是搜索状态,可以选择收起,这里为了体验保留原状或强制收起均可
|
|
246
|
-
// node.expanded = false; // 取消注释则未匹配路径会自动收起
|
|
247
|
-
}
|
|
248
|
-
})
|
|
249
|
-
|
|
250
|
-
return hasMatchInLevel
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
traverseAndExpand(treeData.value)
|
|
254
|
-
}
|
|
255
|
-
</script>
|
|
256
|
-
|
|
257
|
-
<template>
|
|
258
|
-
<z-paging
|
|
259
|
-
v-if="treeConfig.id" ref="Zpaging" v-model="filteredTreeData" :auto-show-system-loading="true"
|
|
260
|
-
:loading-more-enabled="false" :show-loading-more-when-reload="false"
|
|
261
|
-
:to-bottom-loading-more-enabled="false" @query="() => { getTreeRootData(treeConfig.id) }"
|
|
262
|
-
>
|
|
263
|
-
<template #top>
|
|
264
|
-
<wd-search v-model="searchText" hide-cancel @change="handleSearch" />
|
|
265
|
-
<view>
|
|
266
|
-
<ListTopButtons
|
|
267
|
-
:add-event="addEvent" :main-code="mainCode" :buttons="treeConfig.rootLTmplConfig.buttons"
|
|
268
|
-
:source-id="treeConfig.rootGtmplId" :page-title="pageTitle" page-type="列表"
|
|
269
|
-
/>
|
|
270
|
-
</view>
|
|
271
|
-
</template>
|
|
272
|
-
<view class="container">
|
|
273
|
-
<!-- 树形内容 -->
|
|
274
|
-
<view class="tree-container">
|
|
275
|
-
<tree-item
|
|
276
|
-
v-for="item in filteredTreeData" :key="item.id" :node="item" :search-keyword="searchText"
|
|
277
|
-
:leaf-ratmpl-id="treeConfig.leafRatmplId" @add-leaf="handleAddLeaf" @add-branch="handleAddBranch"
|
|
278
|
-
@remove="handleRemove" @update="handleUpdate" @toggle-expand="toggleExpand"
|
|
279
|
-
/>
|
|
280
|
-
</view>
|
|
281
|
-
</view>
|
|
282
|
-
<wd-dialog />
|
|
283
|
-
</z-paging>
|
|
284
|
-
</template>
|
|
285
|
-
|
|
286
|
-
<style>
|
|
287
|
-
.container {
|
|
288
|
-
display: flex;
|
|
289
|
-
flex-direction: column;
|
|
290
|
-
/* height: 100vh; */
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
.tree-container {
|
|
294
|
-
flex: 1;
|
|
295
|
-
overflow: hidden;
|
|
296
|
-
}
|
|
297
|
-
</style>
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import { computed, defineOptions, onMounted, onUnmounted, ref } from 'vue'
|
|
3
|
+
import { onLoad } from '@dcloudio/uni-app'
|
|
4
|
+
import { useDialog } from '@wot-ui/ui'
|
|
5
|
+
import { useGlobalLoading } from '../../composables/useGlobalLoading'
|
|
6
|
+
import { useGlobalToast } from '../../composables/useGlobalToast'
|
|
7
|
+
import ListTopButtons from '../list-top-buttons/list-top-buttons.vue'
|
|
8
|
+
import { useTreeControlInit } from '../../utils/control-tree'
|
|
9
|
+
import type { TreeNode, nodeType } from '../../utils/control-tree'
|
|
10
|
+
import { generateHighResolutionID } from '../../utils/index'
|
|
11
|
+
import { treeNodeDeleteApi } from '../../api/tree'
|
|
12
|
+
import treeItem from './components/tree-item.vue'
|
|
13
|
+
|
|
14
|
+
defineOptions({
|
|
15
|
+
name: 'WuiTreePage',
|
|
16
|
+
})
|
|
17
|
+
// --- 数据定义 ---
|
|
18
|
+
const searchText = ref('')
|
|
19
|
+
const sourceId = ref('')
|
|
20
|
+
const pageTitle = ref('')
|
|
21
|
+
const mainCode = ref('')
|
|
22
|
+
const addEvent = generateHighResolutionID()// 全局事件名称
|
|
23
|
+
const Zpaging = ref<any>(null)
|
|
24
|
+
const dialog = useDialog()
|
|
25
|
+
const parentId = ref('')
|
|
26
|
+
const parentNodeType = ref<nodeType>('root')
|
|
27
|
+
const targetNodeType = ref<nodeType>('root')
|
|
28
|
+
const { loading } = useGlobalLoading()
|
|
29
|
+
const { success, error } = useGlobalToast()
|
|
30
|
+
|
|
31
|
+
onLoad((option: any) => {
|
|
32
|
+
console.log(option)
|
|
33
|
+
sourceId.value = option.sourceId
|
|
34
|
+
pageTitle.value = option.title
|
|
35
|
+
mainCode.value = option.mainCode || ''
|
|
36
|
+
uni.setNavigationBarTitle({
|
|
37
|
+
title: option.title,
|
|
38
|
+
})
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
const { treeConfig, treeData, findTreeNodeandExpand, getTreeRootData } = useTreeControlInit(sourceId.value, Zpaging)
|
|
42
|
+
|
|
43
|
+
onMounted(async () => {
|
|
44
|
+
// 监听添加成功的事件
|
|
45
|
+
uni.$on(addEvent, async (e) => {
|
|
46
|
+
console.log(e)
|
|
47
|
+
// findTreeNodeandAppend(parentId.value, treeData.value, [{
|
|
48
|
+
// id: e.entityCode,
|
|
49
|
+
// parentId: parentId.value,
|
|
50
|
+
// label: e.data[targetNodeType.value === 'branch' && treeConfig.value.branchLTmplConfig ? treeConfig.value.branchLTmplConfig.primaryColumn.sourceId : targetNodeType.value === 'leaf' && treeConfig.value.leafLTmplConfig? treeConfig.value.leafLTmplConfig.primaryColumn.sourceId : treeConfig.value.rootLTmplConfig.primaryColumn.sourceId],
|
|
51
|
+
// expanded: false,
|
|
52
|
+
// type: targetNodeType.value,
|
|
53
|
+
// loading: false,
|
|
54
|
+
// children: null,
|
|
55
|
+
// }], parentNodeType.value)
|
|
56
|
+
findTreeNodeandExpand({
|
|
57
|
+
id: parentId.value,
|
|
58
|
+
type: parentNodeType.value,
|
|
59
|
+
parentId: '',
|
|
60
|
+
label: '',
|
|
61
|
+
expanded: false,
|
|
62
|
+
loading: false,
|
|
63
|
+
}, treeData.value, 'add')
|
|
64
|
+
// Zpaging.value.reload()
|
|
65
|
+
})
|
|
66
|
+
})
|
|
67
|
+
// 在组件卸载时解绑全局事件
|
|
68
|
+
onUnmounted(() => {
|
|
69
|
+
console.log(`${pageTitle.value}页面卸载`)
|
|
70
|
+
uni.$off(addEvent)
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
function toggleExpand(node: TreeNode) {
|
|
74
|
+
// 展开节点
|
|
75
|
+
findTreeNodeandExpand(node, treeData.value)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// 添加分支节点
|
|
79
|
+
function handleAddBranch(parentNode: TreeNode) {
|
|
80
|
+
console.log('添加子节点:', parentNode)
|
|
81
|
+
parentId.value = parentNode.id
|
|
82
|
+
parentNodeType.value = parentNode.type
|
|
83
|
+
targetNodeType.value = 'branch'
|
|
84
|
+
uni.navigateTo({
|
|
85
|
+
url: `/pages/edit-page/index?sourceId=${treeConfig.value.branchRatmplId}&title=${pageTitle.value}&mainCode=${parentNode.id}&addEvent=${addEvent}`,
|
|
86
|
+
})
|
|
87
|
+
}
|
|
88
|
+
// 添加叶子节点
|
|
89
|
+
function handleAddLeaf(parentNode: TreeNode) {
|
|
90
|
+
console.log('添加叶子节点:', parentNode)
|
|
91
|
+
parentId.value = parentNode.id
|
|
92
|
+
parentNodeType.value = parentNode.type
|
|
93
|
+
targetNodeType.value = 'leaf'
|
|
94
|
+
uni.navigateTo({
|
|
95
|
+
url: `/pages/edit-page/index?sourceId=${treeConfig.value.leafRatmplId}&title=${pageTitle.value}&mainCode=${parentNode.id}&addEvent=${addEvent}`,
|
|
96
|
+
})
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// 处理更新节点
|
|
100
|
+
function handleUpdate(targetNode: TreeNode) {
|
|
101
|
+
let sourceId = null
|
|
102
|
+
if (targetNode.type === 'leaf') {
|
|
103
|
+
sourceId = treeConfig.value.leafRatmplId
|
|
104
|
+
}
|
|
105
|
+
else if (targetNode.type === 'branch') {
|
|
106
|
+
sourceId = treeConfig.value.branchRatmplId
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
sourceId = treeConfig.value.rootGtmplId
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
uni.navigateTo({
|
|
113
|
+
url: `/pages/edit-page/index?sourceId=${sourceId}&title=${pageTitle.value}&id=${targetNode.id}&mainCode=${targetNode.parentId}&addEvent=${addEvent}`,
|
|
114
|
+
})
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// 过滤后的树形数据
|
|
118
|
+
const filteredTreeData = computed<TreeNode[]>(() => {
|
|
119
|
+
if (!searchText.value) {
|
|
120
|
+
return treeData.value
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const keyword = searchText.value.toLowerCase()
|
|
124
|
+
|
|
125
|
+
// 过滤节点的递归函数
|
|
126
|
+
const filterNodes = (nodes: TreeNode[]): TreeNode[] => {
|
|
127
|
+
return nodes
|
|
128
|
+
.map((node) => {
|
|
129
|
+
// 复制节点,避免修改原数据
|
|
130
|
+
const newNode = { ...node }
|
|
131
|
+
|
|
132
|
+
// 如果有子节点,递归过滤
|
|
133
|
+
// if (newNode.children && newNode.children.length > 0) {
|
|
134
|
+
// newNode.children = filterNodes(newNode.children)
|
|
135
|
+
// }
|
|
136
|
+
|
|
137
|
+
// 节点名称包含关键词,或者有符合条件的子节点,则保留该节点
|
|
138
|
+
const nodeNameMatch = newNode.label.toLowerCase().includes(keyword)
|
|
139
|
+
// const hasMatchingChildren = newNode.children && newNode.children.length > 0
|
|
140
|
+
|
|
141
|
+
// return nodeNameMatch || hasMatchingChildren ? newNode : null
|
|
142
|
+
return nodeNameMatch ? newNode : null
|
|
143
|
+
})
|
|
144
|
+
.filter(Boolean) as TreeNode[]
|
|
145
|
+
}
|
|
146
|
+
console.log('filterNodes:', filterNodes(treeData.value))
|
|
147
|
+
|
|
148
|
+
return filterNodes(treeData.value)
|
|
149
|
+
})
|
|
150
|
+
// 删除节点
|
|
151
|
+
function handleRemove(targetNode: TreeNode) {
|
|
152
|
+
let sourceId = treeConfig.value.rootGtmplId
|
|
153
|
+
if (targetNode.type === 'leaf') {
|
|
154
|
+
sourceId = treeConfig.value.leafRatmplId || ''
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (targetNode.type === 'branch') {
|
|
158
|
+
sourceId = treeConfig.value.branchRatmplId || ''
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
dialog
|
|
162
|
+
.confirm({
|
|
163
|
+
msg: `确定要删除 "${targetNode.label}" 及其子节点吗?`,
|
|
164
|
+
title: '提示',
|
|
165
|
+
beforeConfirm: async () => {
|
|
166
|
+
loading('删除中...')
|
|
167
|
+
try {
|
|
168
|
+
// const res = await editPageConfig(sourceId || '', targetNode.id)
|
|
169
|
+
// const res1 = await editPageDataSave(sourceId || '', targetNode.id, {}, '', res.dtmplConfig.actions[0].id)
|
|
170
|
+
const res1 = await treeNodeDeleteApi(sourceId, targetNode.id)
|
|
171
|
+
if (res1.status === 'success') {
|
|
172
|
+
success('删除成功')
|
|
173
|
+
removeNodeRecursively(filteredTreeData.value, targetNode.id)
|
|
174
|
+
return true
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
error('删除失败')
|
|
178
|
+
return false
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
catch (error1) {
|
|
182
|
+
error('删除失败')
|
|
183
|
+
console.log(error1)
|
|
184
|
+
return false
|
|
185
|
+
}
|
|
186
|
+
},
|
|
187
|
+
})
|
|
188
|
+
.then(() => { })
|
|
189
|
+
.catch((error) => {
|
|
190
|
+
console.log(error)
|
|
191
|
+
})
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// 递归删除逻辑
|
|
195
|
+
function removeNodeRecursively(list: TreeNode[], idToRemove: string): boolean {
|
|
196
|
+
for (let i = 0; i < list.length; i++) {
|
|
197
|
+
if (list[i].id === idToRemove) {
|
|
198
|
+
list.splice(i, 1)
|
|
199
|
+
return true
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const children = list[i].children
|
|
203
|
+
if (Array.isArray(children) && children.length > 0) {
|
|
204
|
+
const deleted = removeNodeRecursively(children, idToRemove)
|
|
205
|
+
if (deleted)
|
|
206
|
+
return true
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
return false
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// --- 搜索逻辑 ---
|
|
213
|
+
/*
|
|
214
|
+
搜索策略:
|
|
215
|
+
1. 遍历树。
|
|
216
|
+
2. 如果节点名称包含关键字,标记高亮(通过prop传给子组件)。
|
|
217
|
+
3. 如果节点包含关键字,或者其子孙节点包含关键字,则该节点必须展开 (expanded = true)。
|
|
218
|
+
*/
|
|
219
|
+
function handleSearch() {
|
|
220
|
+
const keyword = searchText.value.trim().toLowerCase()
|
|
221
|
+
|
|
222
|
+
if (!keyword)
|
|
223
|
+
return
|
|
224
|
+
|
|
225
|
+
// 定义递归搜索函数
|
|
226
|
+
const traverseAndExpand = (nodes: TreeNode[]) => {
|
|
227
|
+
let hasMatchInLevel = false
|
|
228
|
+
|
|
229
|
+
nodes.forEach((node) => {
|
|
230
|
+
// 检查当前节点是否匹配
|
|
231
|
+
const isSelfMatch = node.label.toLowerCase().includes(keyword)
|
|
232
|
+
|
|
233
|
+
// 递归检查子节点
|
|
234
|
+
let hasChildMatch = false
|
|
235
|
+
if (node.children && node.children.length > 0) {
|
|
236
|
+
hasChildMatch = traverseAndExpand(node.children)
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// 核心逻辑:如果自己匹配,或子节点有匹配,则当前路径应激活/展开
|
|
240
|
+
if (isSelfMatch || hasChildMatch) {
|
|
241
|
+
// node.expanded = true;
|
|
242
|
+
hasMatchInLevel = true
|
|
243
|
+
}
|
|
244
|
+
else {
|
|
245
|
+
// 如果不是搜索状态,可以选择收起,这里为了体验保留原状或强制收起均可
|
|
246
|
+
// node.expanded = false; // 取消注释则未匹配路径会自动收起
|
|
247
|
+
}
|
|
248
|
+
})
|
|
249
|
+
|
|
250
|
+
return hasMatchInLevel
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
traverseAndExpand(treeData.value)
|
|
254
|
+
}
|
|
255
|
+
</script>
|
|
256
|
+
|
|
257
|
+
<template>
|
|
258
|
+
<z-paging
|
|
259
|
+
v-if="treeConfig.id" ref="Zpaging" v-model="filteredTreeData" :auto-show-system-loading="true"
|
|
260
|
+
:loading-more-enabled="false" :show-loading-more-when-reload="false"
|
|
261
|
+
:to-bottom-loading-more-enabled="false" @query="() => { getTreeRootData(treeConfig.id) }"
|
|
262
|
+
>
|
|
263
|
+
<template #top>
|
|
264
|
+
<wd-search v-model="searchText" hide-cancel @change="handleSearch" />
|
|
265
|
+
<view>
|
|
266
|
+
<ListTopButtons
|
|
267
|
+
:add-event="addEvent" :main-code="mainCode" :buttons="treeConfig.rootLTmplConfig.buttons"
|
|
268
|
+
:source-id="treeConfig.rootGtmplId" :page-title="pageTitle" page-type="列表"
|
|
269
|
+
/>
|
|
270
|
+
</view>
|
|
271
|
+
</template>
|
|
272
|
+
<view class="container">
|
|
273
|
+
<!-- 树形内容 -->
|
|
274
|
+
<view class="tree-container">
|
|
275
|
+
<tree-item
|
|
276
|
+
v-for="item in filteredTreeData" :key="item.id" :node="item" :search-keyword="searchText"
|
|
277
|
+
:leaf-ratmpl-id="treeConfig.leafRatmplId" @add-leaf="handleAddLeaf" @add-branch="handleAddBranch"
|
|
278
|
+
@remove="handleRemove" @update="handleUpdate" @toggle-expand="toggleExpand"
|
|
279
|
+
/>
|
|
280
|
+
</view>
|
|
281
|
+
</view>
|
|
282
|
+
<wd-dialog />
|
|
283
|
+
</z-paging>
|
|
284
|
+
</template>
|
|
285
|
+
|
|
286
|
+
<style>
|
|
287
|
+
.container {
|
|
288
|
+
display: flex;
|
|
289
|
+
flex-direction: column;
|
|
290
|
+
/* height: 100vh; */
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
.tree-container {
|
|
294
|
+
flex: 1;
|
|
295
|
+
overflow: hidden;
|
|
296
|
+
}
|
|
297
|
+
</style>
|