@veltra/desktop 1.0.8 → 1.0.10
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/dist/components/action/action-group.vue.d.ts +2 -2
- package/dist/components/action/action.vue.d.ts +3 -3
- package/dist/components/auto-complete/auto-complete.vue.d.ts +1 -1
- package/dist/components/batch-edit/batch-edit.js.map +1 -1
- package/dist/components/batch-edit/batch-edit.vue.d.ts +2 -2
- package/dist/components/batch-edit/use-edit.js.map +1 -1
- package/dist/components/button/button.js.map +1 -1
- package/dist/components/button/button.vue.d.ts +1 -1
- package/dist/components/cascade/cascade.js +15 -13
- package/dist/components/cascade/cascade.js.map +1 -1
- package/dist/components/cascade/cascade.vue.d.ts +7 -7
- package/dist/components/cascade/node.js.map +1 -1
- package/dist/components/cascade/use-check.js +3 -2
- package/dist/components/cascade/use-check.js.map +1 -1
- package/dist/components/cascade/use-select.js +3 -3
- package/dist/components/cascade/use-select.js.map +1 -1
- package/dist/components/checkbox-group/checkbox-group.js.map +1 -1
- package/dist/components/checkbox-group/checkbox-group.vue.d.ts +2 -2
- package/dist/components/date-panel/date-panel.js.map +1 -1
- package/dist/components/date-panel/date-panel.vue.d.ts +1 -1
- package/dist/components/date-picker/date-picker.js +9 -9
- package/dist/components/date-picker/date-picker.js.map +1 -1
- package/dist/components/date-picker/date-picker.vue.d.ts +1 -1
- package/dist/components/date-range-picker/date-range-picker.js +9 -9
- package/dist/components/date-range-picker/date-range-picker.js.map +1 -1
- package/dist/components/date-range-picker/date-range-picker.vue.d.ts +1 -1
- package/dist/components/drawer/drawer.js.map +1 -1
- package/dist/components/empty/empty.vue.d.ts +1 -1
- package/dist/components/expression-editor/expression-editor.js.map +1 -1
- package/dist/components/expression-editor/internal/editor-runtime/create-runtime.js.map +1 -1
- package/dist/components/expression-editor/internal/features/commands/register-command-packs.js.map +1 -1
- package/dist/components/expression-editor/internal/features/insertion/insertion-service.js.map +1 -1
- package/dist/components/expression-editor/use-decorators.js.map +1 -1
- package/dist/components/expression-editor/use-expression-drag-drop.js.map +1 -1
- package/dist/components/file-picker/file-picker.js.map +1 -1
- package/dist/components/file-picker/file-picker.vue.d.ts +1 -1
- package/dist/components/file-picker/helper.js +19 -7
- package/dist/components/file-picker/helper.js.map +1 -1
- package/dist/components/file-viewer/file-viewer.js +294 -0
- package/dist/components/file-viewer/file-viewer.js.map +1 -0
- package/dist/components/file-viewer/file-viewer.vue.d.ts +42 -0
- package/dist/components/file-viewer/helper.js +185 -0
- package/dist/components/file-viewer/helper.js.map +1 -0
- package/dist/components/file-viewer/index.d.ts +1 -0
- package/dist/components/file-viewer/previewers/docx-previewer.js +76 -0
- package/dist/components/file-viewer/previewers/docx-previewer.js.map +1 -0
- package/dist/components/file-viewer/previewers/image-previewer.js +64 -0
- package/dist/components/file-viewer/previewers/image-previewer.js.map +1 -0
- package/dist/components/file-viewer/previewers/pdf-previewer.js +90 -0
- package/dist/components/file-viewer/previewers/pdf-previewer.js.map +1 -0
- package/dist/components/file-viewer/previewers/sheet-previewer.js +175 -0
- package/dist/components/file-viewer/previewers/sheet-previewer.js.map +1 -0
- package/dist/components/file-viewer/previewers/text-previewer.js +74 -0
- package/dist/components/file-viewer/previewers/text-previewer.js.map +1 -0
- package/dist/components/file-viewer/previewers/video-previewer.js +62 -0
- package/dist/components/file-viewer/previewers/video-previewer.js.map +1 -0
- package/dist/components/file-viewer/style.d.ts +1 -0
- package/dist/components/file-viewer/style.js +4 -0
- package/dist/components/file-viewer/style2.css +445 -0
- package/dist/components/form/form-model.js +2 -1
- package/dist/components/form/form-model.js.map +1 -1
- package/dist/components/grid/grid.js.map +1 -1
- package/dist/components/grid/use-responsive.js.map +1 -1
- package/dist/components/grid-input/grid-input.vue.d.ts +1 -1
- package/dist/components/index.d.ts +12 -9
- package/dist/components/input/input.vue.d.ts +3 -3
- package/dist/components/list/list.js.map +1 -1
- package/dist/components/loading/directive.js.map +1 -1
- package/dist/components/menu/menu-item.js.map +1 -1
- package/dist/components/message/message2.js.map +1 -1
- package/dist/components/multi-select/multi-select-option.js +14 -10
- package/dist/components/multi-select/multi-select-option.js.map +1 -1
- package/dist/components/multi-select/multi-select.js +16 -19
- package/dist/components/multi-select/multi-select.js.map +1 -1
- package/dist/components/multi-select/multi-select.vue.d.ts +4 -4
- package/dist/components/multi-tree-select/multi-tree-select.vue.d.ts +7 -7
- package/dist/components/notification/index.js.map +1 -1
- package/dist/components/notification/notification.vue.d.ts +1 -1
- package/dist/components/number-input/number-input.js.map +1 -1
- package/dist/components/number-input/number-input.vue.d.ts +1 -1
- package/dist/components/number-range-input/number-range-input.vue.d.ts +1 -1
- package/dist/components/palette/color-transform.js.map +1 -1
- package/dist/components/palette/di.js.map +1 -1
- package/dist/components/palette/palette-alpha.js +7 -10
- package/dist/components/palette/palette-alpha.js.map +1 -1
- package/dist/components/palette/palette-hue.js +5 -7
- package/dist/components/palette/palette-hue.js.map +1 -1
- package/dist/components/palette/palette-sv.js +8 -10
- package/dist/components/palette/palette-sv.js.map +1 -1
- package/dist/components/palette/palette.js +22 -24
- package/dist/components/palette/palette.js.map +1 -1
- package/dist/components/password-input/password-input.vue.d.ts +1 -1
- package/dist/components/pop-confirm/pop-confirm.vue.d.ts +2 -2
- package/dist/components/progress/progress.js +1 -1
- package/dist/components/progress/progress.js.map +1 -1
- package/dist/components/progress-nodes/progress-nodes.js.map +1 -1
- package/dist/components/radio-group/radio-group.vue.d.ts +2 -2
- package/dist/components/rich-text-editor/rich-text-editor.js.map +1 -1
- package/dist/components/rich-text-editor/rich-text-editor.vue.d.ts +1 -1
- package/dist/components/rich-text-editor/toolbar.js.map +1 -1
- package/dist/components/scroll/scroll.js.map +1 -1
- package/dist/components/select/select.js +14 -12
- package/dist/components/select/select.js.map +1 -1
- package/dist/components/select/select.vue.d.ts +3 -3
- package/dist/components/slider/slider-thumb.js +10 -13
- package/dist/components/slider/slider-thumb.js.map +1 -1
- package/dist/components/slider/slider.js +12 -15
- package/dist/components/slider/slider.js.map +1 -1
- package/dist/components/table/di.js.map +1 -1
- package/dist/components/table/node/row.d.ts +10 -1
- package/dist/components/table/node/row.js +9 -0
- package/dist/components/table/node/row.js.map +1 -1
- package/dist/components/table/table-body.js +25 -26
- package/dist/components/table/table-body.js.map +1 -1
- package/dist/components/table/table-cell.js +16 -9
- package/dist/components/table/table-cell.js.map +1 -1
- package/dist/components/table/table-row.js +77 -19
- package/dist/components/table/table-row.js.map +1 -1
- package/dist/components/table/table.js +75 -34
- package/dist/components/table/table.js.map +1 -1
- package/dist/components/table/table.vue.d.ts +2 -2
- package/dist/components/table/use-columns.js +4 -0
- package/dist/components/table/use-columns.js.map +1 -1
- package/dist/components/table/use-fixed-columns.js +27 -8
- package/dist/components/table/use-fixed-columns.js.map +1 -1
- package/dist/components/table/use-rows.js +2 -2
- package/dist/components/table/use-rows.js.map +1 -1
- package/dist/components/table/use-table.js +50 -3
- package/dist/components/table/use-table.js.map +1 -1
- package/dist/components/tabs/index.d.ts +3 -1
- package/dist/components/tabs/style2.css +170 -107
- package/dist/components/tabs/tabs-horizontal.js +133 -0
- package/dist/components/tabs/tabs-horizontal.js.map +1 -0
- package/dist/components/tabs/tabs-horizontal.vue.d.ts +40 -0
- package/dist/components/tabs/tabs-vertical.js +89 -0
- package/dist/components/tabs/tabs-vertical.js.map +1 -0
- package/dist/components/tabs/tabs-vertical.vue.d.ts +38 -0
- package/dist/components/tabs/tabs.js +75 -105
- package/dist/components/tabs/tabs.js.map +1 -1
- package/dist/components/tabs/tabs.vue.d.ts +9 -23
- package/dist/components/tabs/use-tabs-bar.js +105 -0
- package/dist/components/tabs/use-tabs-bar.js.map +1 -0
- package/dist/components/text/text.js.map +1 -1
- package/dist/components/textarea/textarea.js.map +1 -1
- package/dist/components/textarea/textarea.vue.d.ts +4 -4
- package/dist/components/theme/theme.js.map +1 -1
- package/dist/components/tip/tip.vue.d.ts +1 -1
- package/dist/components/tree/style2.css +45 -23
- package/dist/components/tree/tree-node.js +50 -35
- package/dist/components/tree/tree-node.js.map +1 -1
- package/dist/components/tree/tree-node2.js.map +1 -1
- package/dist/components/tree/tree.js +27 -20
- package/dist/components/tree/tree.js.map +1 -1
- package/dist/components/tree/tree.vue.d.ts +5 -5
- package/dist/components/tree/use-check.js +52 -14
- package/dist/components/tree/use-check.js.map +1 -1
- package/dist/components/tree/use-tree-nodes.js +51 -24
- package/dist/components/tree/use-tree-nodes.js.map +1 -1
- package/dist/components/tree-select/tree-select.vue.d.ts +7 -7
- package/dist/index.d.ts +57 -53
- package/dist/index.js +51 -48
- package/dist/types/file-viewer.d.ts +71 -0
- package/dist/types/index.d.ts +3 -2
- package/dist/types/tabs.d.ts +106 -14
- package/dist/types/tree.d.ts +6 -1
- package/package.json +32 -31
- package/src/components/cascade/cascade.vue +18 -18
- package/src/components/cascade/node.ts +4 -1
- package/src/components/cascade/use-check.ts +5 -4
- package/src/components/cascade/use-select.ts +4 -5
- package/src/components/date-picker/date-picker.vue +10 -9
- package/src/components/date-range-picker/date-range-picker.vue +12 -12
- package/src/components/file-picker/helper.ts +21 -10
- package/src/components/file-viewer/file-viewer.vue +311 -0
- package/src/components/file-viewer/helper.ts +193 -0
- package/src/components/file-viewer/index.ts +1 -0
- package/src/components/file-viewer/previewers/docx-previewer.vue +78 -0
- package/src/components/file-viewer/previewers/image-previewer.vue +64 -0
- package/src/components/file-viewer/previewers/pdf-previewer.vue +90 -0
- package/src/components/file-viewer/previewers/sheet-previewer.vue +210 -0
- package/src/components/file-viewer/previewers/text-previewer.vue +76 -0
- package/src/components/file-viewer/previewers/video-previewer.vue +72 -0
- package/src/components/file-viewer/style.scss +504 -0
- package/src/components/file-viewer/style.ts +4 -0
- package/src/components/index.ts +2 -0
- package/src/components/multi-select/multi-select-option.vue +16 -3
- package/src/components/multi-select/multi-select.vue +17 -9
- package/src/components/palette/di.ts +5 -3
- package/src/components/palette/palette-alpha.vue +7 -10
- package/src/components/palette/palette-hue.vue +5 -7
- package/src/components/palette/palette-sv.vue +12 -14
- package/src/components/palette/palette.vue +19 -21
- package/src/components/progress/progress.vue +1 -1
- package/src/components/select/select.vue +21 -19
- package/src/components/slider/slider-thumb.vue +11 -14
- package/src/components/slider/slider.vue +15 -15
- package/src/components/table/di.ts +58 -43
- package/src/components/table/node/row.ts +10 -1
- package/src/components/table/table-body.vue +28 -33
- package/src/components/table/table-cell.vue +17 -9
- package/src/components/table/table-row.tsx +83 -17
- package/src/components/table/table.vue +72 -45
- package/src/components/table/use-fixed-columns.ts +46 -12
- package/src/components/table/use-rows.ts +14 -3
- package/src/components/table/use-table.ts +27 -3
- package/src/components/tabs/index.ts +2 -0
- package/src/components/tabs/style.scss +219 -133
- package/src/components/tabs/tabs-horizontal.vue +128 -0
- package/src/components/tabs/tabs-vertical.vue +77 -0
- package/src/components/tabs/tabs.vue +56 -127
- package/src/components/tabs/use-tabs-bar.ts +119 -0
- package/src/components/tree/style.scss +74 -29
- package/src/components/tree/tree-node.vue +10 -4
- package/src/components/tree/tree.vue +39 -12
- package/src/components/tree/use-check.ts +79 -23
- package/src/components/tree/use-tree-nodes.ts +85 -34
- package/src/types/file-viewer.ts +69 -0
- package/src/types/index.ts +1 -0
- package/src/types/tabs.ts +113 -19
- package/src/types/tree.ts +6 -1
|
@@ -16,12 +16,36 @@ interface UseCheckReturned {
|
|
|
16
16
|
toggleCheck: (node: TreeNode, check: boolean, ctrlKey?: boolean) => void
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
/**
|
|
20
|
+
* 展开目标节点的所有祖先。返回是否发生了实际展开。
|
|
21
|
+
*/
|
|
22
|
+
function expandAncestors(node: TreeNode): boolean {
|
|
23
|
+
let changed = false
|
|
24
|
+
node.bubbleSet((n) => {
|
|
25
|
+
if (n.parent) {
|
|
26
|
+
if (n.parent.expanded) return false
|
|
27
|
+
n.parent.expanded = true
|
|
28
|
+
changed = true
|
|
29
|
+
}
|
|
30
|
+
})
|
|
31
|
+
return changed
|
|
32
|
+
}
|
|
33
|
+
|
|
19
34
|
export function useCheck(options: Options): UseCheckReturned {
|
|
20
35
|
const { emit, props, nodeDict, getFlattedNodes } = options
|
|
21
36
|
|
|
22
37
|
const checkedData = new Set<Record<string, any>>()
|
|
23
38
|
|
|
24
|
-
|
|
39
|
+
/**
|
|
40
|
+
* 上一次回显使用的 value 集合(仅限 props.checked)。
|
|
41
|
+
* 用于在相同 `nodeDict` 下走差集回显,避免每次全量清空再重建。
|
|
42
|
+
*/
|
|
43
|
+
let lastCheckedSet = new Set<unknown>()
|
|
44
|
+
/** 最近一次参与差集比较的 nodeDict 引用;引用变化时视为整棵树重建。 */
|
|
45
|
+
let lastDict: Map<any, TreeNode> | null = null
|
|
46
|
+
|
|
47
|
+
function checkNode(node: TreeNode): void {
|
|
48
|
+
if (node.checked) return
|
|
25
49
|
node.checked = true
|
|
26
50
|
if (node.parent) {
|
|
27
51
|
node.parent.childrenCheckCount++
|
|
@@ -29,7 +53,8 @@ export function useCheck(options: Options): UseCheckReturned {
|
|
|
29
53
|
checkedData.add(node.data)
|
|
30
54
|
}
|
|
31
55
|
|
|
32
|
-
function uncheckNode(node: TreeNode) {
|
|
56
|
+
function uncheckNode(node: TreeNode): void {
|
|
57
|
+
if (!node.checked) return
|
|
33
58
|
node.checked = false
|
|
34
59
|
if (node.parent) {
|
|
35
60
|
node.parent.childrenCheckCount--
|
|
@@ -45,27 +70,56 @@ export function useCheck(options: Options): UseCheckReturned {
|
|
|
45
70
|
// 回显
|
|
46
71
|
watch(
|
|
47
72
|
[() => props.checked, nodeDict],
|
|
48
|
-
([c,
|
|
73
|
+
([c, dict]) => {
|
|
49
74
|
// 事件已经触发模型变更了,所以不再进行下面的计算
|
|
50
75
|
if (checkedByEvent || !props.checkable) return
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
76
|
+
if (!dict.size) return
|
|
77
|
+
|
|
78
|
+
const nextSet = new Set<unknown>(c ?? [])
|
|
79
|
+
|
|
80
|
+
// 森林重建(dict 引用变化)→ 走全量清空重建路径,
|
|
81
|
+
// 因为所有 TreeNode 实例都是新的,上一轮缓存的 lastCheckedSet 失效。
|
|
82
|
+
const dictChanged = dict !== lastDict
|
|
83
|
+
if (dictChanged) {
|
|
84
|
+
checkedData.clear()
|
|
85
|
+
lastCheckedSet = new Set()
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
let mutated = false
|
|
89
|
+
|
|
90
|
+
// 取消:上一轮有但本轮没有的 value
|
|
91
|
+
for (const v of lastCheckedSet) {
|
|
92
|
+
if (!nextSet.has(v)) {
|
|
93
|
+
const node = dict.get(v)
|
|
94
|
+
if (node) {
|
|
95
|
+
uncheckNode(node)
|
|
96
|
+
mutated = true
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// 新增:本轮有但上一轮没有的 value
|
|
102
|
+
let ancestorsExpanded = false
|
|
103
|
+
for (const v of nextSet) {
|
|
104
|
+
if (!lastCheckedSet.has(v) || dictChanged) {
|
|
105
|
+
const node = dict.get(v)
|
|
106
|
+
if (node) {
|
|
107
|
+
checkNode(node)
|
|
108
|
+
mutated = true
|
|
109
|
+
if (expandAncestors(node)) {
|
|
110
|
+
ancestorsExpanded = true
|
|
63
111
|
}
|
|
64
|
-
}
|
|
112
|
+
}
|
|
65
113
|
}
|
|
66
|
-
}
|
|
114
|
+
}
|
|
67
115
|
|
|
68
|
-
|
|
116
|
+
lastCheckedSet = nextSet
|
|
117
|
+
lastDict = dict
|
|
118
|
+
|
|
119
|
+
// 只在真实发生变化时才触发扁平化,避免空转。
|
|
120
|
+
if (mutated || ancestorsExpanded) {
|
|
121
|
+
getFlattedNodes()
|
|
122
|
+
}
|
|
69
123
|
},
|
|
70
124
|
{ immediate: true }
|
|
71
125
|
)
|
|
@@ -134,11 +188,13 @@ export function useCheck(options: Options): UseCheckReturned {
|
|
|
134
188
|
|
|
135
189
|
const checkedArr = Array.from(checkedData)
|
|
136
190
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
)
|
|
191
|
+
const valueKey = props.valueKey!
|
|
192
|
+
const nextValues = checkedArr.map((item) => o(item).get(valueKey) as unknown)
|
|
193
|
+
|
|
194
|
+
// 与外部 checked 保持差集缓存同步,避免下一次 watch 回调把刚勾选的值又误判为“新增”。
|
|
195
|
+
lastCheckedSet = new Set(nextValues)
|
|
196
|
+
|
|
197
|
+
emit('update:checked', nextValues as any[], checkedArr)
|
|
142
198
|
|
|
143
199
|
nextTick(() => {
|
|
144
200
|
checkedByEvent = false
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Forest } from '@cat-kit/core'
|
|
2
|
-
import { computed, shallowRef, type ShallowRef, type ComputedRef } from 'vue'
|
|
2
|
+
import { computed, shallowRef, triggerRef, watch, type ShallowRef, type ComputedRef } from 'vue'
|
|
3
3
|
|
|
4
4
|
import type { TreeProps } from '../../types'
|
|
5
5
|
import { TreeNode } from './tree-node'
|
|
@@ -13,12 +13,29 @@ interface UseTreeNodesReturned {
|
|
|
13
13
|
forest: ComputedRef<Forest<Record<string, unknown>, any>>
|
|
14
14
|
getFlattedNodes: () => void
|
|
15
15
|
nodeDict: ComputedRef<Map<string | number, TreeNode>>
|
|
16
|
+
/** 强制刷新 `nodes` 的订阅者(供字段级别变化但列表引用不变时手动触发)。 */
|
|
17
|
+
triggerNodes: () => void
|
|
16
18
|
}
|
|
19
|
+
|
|
17
20
|
export function useTreeNodes(options: Options): UseTreeNodesReturned {
|
|
18
21
|
const { props } = options
|
|
19
22
|
|
|
20
|
-
|
|
21
|
-
|
|
23
|
+
// forest / nodeDict 保持为 shallowRef 而非 computed:
|
|
24
|
+
// - computed 会因为任一 prop 变化(尤其是内联 disabledNode 函数)而整棵重建,
|
|
25
|
+
// 丢失 expanded/checked/visible 等运行时状态;
|
|
26
|
+
// - 显式 watch 仅在真正影响结构的输入变化时才重建,行为可控、可测量。
|
|
27
|
+
const forestRef = shallowRef<Forest<Record<string, unknown>, any>>(
|
|
28
|
+
new Forest<Record<string, unknown>, any>({
|
|
29
|
+
data: [],
|
|
30
|
+
childrenKey: props.childrenKey ?? 'children'
|
|
31
|
+
})
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
const nodeDictRef = shallowRef<Map<string | number, TreeNode>>(new Map())
|
|
35
|
+
|
|
36
|
+
const nodes = shallowRef<TreeNode[]>([])
|
|
37
|
+
|
|
38
|
+
function buildForest(): Forest<Record<string, unknown>, any> {
|
|
22
39
|
const { disabledNode, expandAll = false, valueKey, labelKey } = props
|
|
23
40
|
const childrenKey = props.childrenKey ?? 'children'
|
|
24
41
|
|
|
@@ -26,9 +43,8 @@ export function useTreeNodes(options: Options): UseTreeNodesReturned {
|
|
|
26
43
|
data: Record<string, any>,
|
|
27
44
|
index: number,
|
|
28
45
|
depth: number,
|
|
29
|
-
_f: Forest<Record<string, unknown>, any>,
|
|
30
46
|
parent?: TreeNode
|
|
31
|
-
) {
|
|
47
|
+
): TreeNode {
|
|
32
48
|
const node = new TreeNode({
|
|
33
49
|
data,
|
|
34
50
|
index,
|
|
@@ -42,47 +58,82 @@ export function useTreeNodes(options: Options): UseTreeNodesReturned {
|
|
|
42
58
|
}
|
|
43
59
|
|
|
44
60
|
return new Forest<Record<string, unknown>, any>({
|
|
45
|
-
data: props.data
|
|
61
|
+
data: (props.data ?? []) as Record<string, unknown>[],
|
|
46
62
|
childrenKey,
|
|
47
63
|
createNode: disabledNode
|
|
48
|
-
? (data, index, depth,
|
|
49
|
-
const node = createNode(
|
|
50
|
-
data as Record<string, any>,
|
|
51
|
-
index,
|
|
52
|
-
depth,
|
|
53
|
-
f,
|
|
54
|
-
parent as TreeNode
|
|
55
|
-
)
|
|
64
|
+
? (data, index, depth, _f, parent) => {
|
|
65
|
+
const node = createNode(data as Record<string, any>, index, depth, parent as TreeNode)
|
|
56
66
|
if (data) {
|
|
57
|
-
node.disabled = disabledNode(data, node) ?? false
|
|
67
|
+
node.disabled = disabledNode(data as Record<string, any>, node) ?? false
|
|
58
68
|
}
|
|
59
69
|
return node
|
|
60
70
|
}
|
|
61
|
-
: (data, index, depth,
|
|
62
|
-
createNode(data as Record<string, any>, index, depth,
|
|
71
|
+
: (data, index, depth, _f, parent) =>
|
|
72
|
+
createNode(data as Record<string, any>, index, depth, parent as TreeNode)
|
|
63
73
|
})
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/** 碾平后的节点 */
|
|
67
|
-
const nodes = shallowRef<TreeNode[]>([])
|
|
74
|
+
}
|
|
68
75
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
const nodeDict = computed(() => {
|
|
73
|
-
const dict = new Map<string | number, TreeNode>()
|
|
76
|
+
function rebuildForest(): void {
|
|
77
|
+
const nextForest = buildForest()
|
|
78
|
+
const nextDict = new Map<string | number, TreeNode>()
|
|
74
79
|
|
|
75
|
-
|
|
76
|
-
|
|
80
|
+
// 构建森林的同时一次 DFS 同步填充字典,
|
|
81
|
+
// 避免旧版 “forest computed → nodeDict computed” 两次完整遍历。
|
|
82
|
+
nextForest.dfs((node) => {
|
|
83
|
+
nextDict.set(node.key, node)
|
|
77
84
|
})
|
|
78
85
|
|
|
79
|
-
|
|
80
|
-
|
|
86
|
+
forestRef.value = nextForest
|
|
87
|
+
nodeDictRef.value = nextDict
|
|
88
|
+
|
|
89
|
+
getFlattedNodes()
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** 按展开与可见性扁平化:仅一次 DFS。 */
|
|
93
|
+
function getFlattedNodes(): void {
|
|
94
|
+
const result: TreeNode[] = []
|
|
95
|
+
const roots = forestRef.value.roots as TreeNode[]
|
|
96
|
+
|
|
97
|
+
const stack: TreeNode[] = []
|
|
98
|
+
for (let i = roots.length - 1; i >= 0; i--) {
|
|
99
|
+
stack.push(roots[i]!)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
while (stack.length) {
|
|
103
|
+
const node = stack.pop()!
|
|
104
|
+
if (!node.visible) continue
|
|
105
|
+
result.push(node)
|
|
106
|
+
if (node.expanded && node.children && node.children.length) {
|
|
107
|
+
for (let i = node.children.length - 1; i >= 0; i--) {
|
|
108
|
+
stack.push(node.children[i]!)
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
nodes.value = result
|
|
114
|
+
}
|
|
81
115
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
nodes.value = forest.value.flattenVisible((n) => n.expanded).filter((n) => n.visible)
|
|
116
|
+
function triggerNodes(): void {
|
|
117
|
+
triggerRef(nodes)
|
|
85
118
|
}
|
|
86
119
|
|
|
87
|
-
|
|
120
|
+
watch(
|
|
121
|
+
[
|
|
122
|
+
() => props.data,
|
|
123
|
+
() => props.disabledNode,
|
|
124
|
+
() => props.childrenKey,
|
|
125
|
+
() => props.valueKey,
|
|
126
|
+
() => props.labelKey,
|
|
127
|
+
() => props.expandAll
|
|
128
|
+
],
|
|
129
|
+
() => {
|
|
130
|
+
rebuildForest()
|
|
131
|
+
},
|
|
132
|
+
{ immediate: true }
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
const forest = computed(() => forestRef.value)
|
|
136
|
+
const nodeDict = computed(() => nodeDictRef.value)
|
|
137
|
+
|
|
138
|
+
return { nodes, forest, getFlattedNodes, nodeDict, triggerNodes }
|
|
88
139
|
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type { DeconstructValue } from '@veltra/utils'
|
|
2
|
+
import type { ShallowRef } from 'vue'
|
|
3
|
+
|
|
4
|
+
/** 预览器类别:xlsx 与 csv 归一为 sheet */
|
|
5
|
+
export type FileViewerKind = 'image' | 'video' | 'pdf' | 'sheet' | 'docx' | 'text'
|
|
6
|
+
|
|
7
|
+
/** 单个预览文件定义 */
|
|
8
|
+
export interface FileViewerItem {
|
|
9
|
+
/** 唯一 id;未提供时组件内部按索引生成 */
|
|
10
|
+
id?: string
|
|
11
|
+
/** 展示名(通常为原始文件名) */
|
|
12
|
+
name: string
|
|
13
|
+
/**
|
|
14
|
+
* 文件源:
|
|
15
|
+
* - string: URL(支持 http(s):、blob:、data:)
|
|
16
|
+
* - File / Blob / ArrayBuffer / Uint8Array: 二进制原始数据
|
|
17
|
+
*/
|
|
18
|
+
src: string | File | Blob | ArrayBuffer | Uint8Array
|
|
19
|
+
/** 类型;缺省时根据 name 后缀推断 */
|
|
20
|
+
kind?: FileViewerKind
|
|
21
|
+
/** MIME type,仅用于原生 <video> / <img> / 下载时的类型提示 */
|
|
22
|
+
mime?: string
|
|
23
|
+
/** 文件大小(字节),可选,仅用于侧栏展示 */
|
|
24
|
+
size?: number
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** 文件预览组件属性 */
|
|
28
|
+
export interface FileViewerProps {
|
|
29
|
+
/** 待预览的文件列表 */
|
|
30
|
+
files: FileViewerItem[]
|
|
31
|
+
/** 当前激活文件 id(配合 v-model) */
|
|
32
|
+
modelValue?: string
|
|
33
|
+
/** 侧栏宽度(CSS length 或 false 隐藏侧栏),默认 280px */
|
|
34
|
+
sidebarWidth?: string | number | false
|
|
35
|
+
/** sheet 场景单文件最大渲染行数,默认 50000;0 表示不截断 */
|
|
36
|
+
sheetMaxRows?: number
|
|
37
|
+
/** 是否显示下载按钮,默认 true */
|
|
38
|
+
downloadable?: boolean
|
|
39
|
+
/**
|
|
40
|
+
* 全屏模态模式开关(支持 v-model:open)。
|
|
41
|
+
*
|
|
42
|
+
* - `undefined`(缺省):内嵌模式,组件在原位置渲染
|
|
43
|
+
* - `true` / `false`:进入模态模式,Teleport 到 body,按本值控制显隐
|
|
44
|
+
*/
|
|
45
|
+
open?: boolean
|
|
46
|
+
/** 模态模式下点击背景是否关闭,默认 true */
|
|
47
|
+
closeOnClickBackdrop?: boolean
|
|
48
|
+
/** 模态模式下按 ESC 是否关闭,默认 true */
|
|
49
|
+
closeOnEsc?: boolean
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** 文件预览组件事件 */
|
|
53
|
+
export interface FileViewerEmits {
|
|
54
|
+
(e: 'update:modelValue', id: string): void
|
|
55
|
+
(e: 'update:open', value: boolean): void
|
|
56
|
+
(e: 'change', file: FileViewerItem): void
|
|
57
|
+
(e: 'error', err: { file: FileViewerItem; error: unknown }): void
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** 文件预览组件暴露的属性和方法(组件内部使用) */
|
|
61
|
+
export interface _FileViewerExposed {
|
|
62
|
+
activeId: ShallowRef<string | undefined>
|
|
63
|
+
activate: (id: string) => void
|
|
64
|
+
next: () => void
|
|
65
|
+
prev: () => void
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** 文件预览组件暴露的属性和方法(组件外部使用, 引用的值会被自动解构) */
|
|
69
|
+
export type FileViewerExposed = DeconstructValue<_FileViewerExposed>
|
package/src/types/index.ts
CHANGED
package/src/types/tabs.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ComponentProps } from '@veltra/utils'
|
|
1
|
+
import type { ComponentProps, ComponentSize } from '@veltra/utils'
|
|
2
2
|
|
|
3
3
|
export type TabItem = {
|
|
4
4
|
/**
|
|
@@ -12,44 +12,138 @@ export type TabItem = {
|
|
|
12
12
|
key: string
|
|
13
13
|
/** 是否禁用 */
|
|
14
14
|
disabled?: boolean
|
|
15
|
+
/**
|
|
16
|
+
* 单个标签是否可关闭
|
|
17
|
+
* @description 未显式设置时,沿用组件级 `closable` 属性
|
|
18
|
+
*/
|
|
19
|
+
closable?: boolean
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** 水平标签栏(top/bottom)属性 */
|
|
23
|
+
export interface TabsHorizontalProps {
|
|
24
|
+
/** 组件尺寸 */
|
|
25
|
+
size?: ComponentSize
|
|
26
|
+
/** 当前激活的标签 key */
|
|
27
|
+
modelValue?: string
|
|
28
|
+
/** 标签项 */
|
|
29
|
+
items: TabItem[]
|
|
30
|
+
/**
|
|
31
|
+
* 是否可关闭
|
|
32
|
+
* @description 作为所有 TabItem 未显式 `closable` 时的默认值;禁用项不显示关闭按钮
|
|
33
|
+
* @default false
|
|
34
|
+
*/
|
|
35
|
+
closable?: boolean
|
|
36
|
+
/**
|
|
37
|
+
* 是否填充父容器宽度
|
|
38
|
+
* @description 开启时 header 容器占满父容器宽度,背景完整铺开;tab-item 自身宽度保持不变
|
|
39
|
+
* @default false
|
|
40
|
+
*/
|
|
41
|
+
block?: boolean
|
|
42
|
+
/**
|
|
43
|
+
* 是否开启圆角胶囊风格
|
|
44
|
+
* @default false
|
|
45
|
+
*/
|
|
46
|
+
rounded?: boolean
|
|
47
|
+
/**
|
|
48
|
+
* 位置
|
|
49
|
+
* @default 'top'
|
|
50
|
+
*/
|
|
51
|
+
position?: 'top' | 'bottom'
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** 垂直标签栏(left/right)属性 */
|
|
55
|
+
export interface TabsVerticalProps {
|
|
56
|
+
/** 组件尺寸 */
|
|
57
|
+
size?: ComponentSize
|
|
58
|
+
/** 当前激活的标签 key */
|
|
59
|
+
modelValue?: string
|
|
60
|
+
/** 标签项 */
|
|
61
|
+
items: TabItem[]
|
|
62
|
+
/**
|
|
63
|
+
* 是否可关闭
|
|
64
|
+
* @description 作为所有 TabItem 未显式 `closable` 时的默认值;禁用项不显示关闭按钮
|
|
65
|
+
* @default false
|
|
66
|
+
*/
|
|
67
|
+
closable?: boolean
|
|
68
|
+
/**
|
|
69
|
+
* 是否开启圆角胶囊风格
|
|
70
|
+
* @default false
|
|
71
|
+
*/
|
|
72
|
+
rounded?: boolean
|
|
73
|
+
/**
|
|
74
|
+
* 位置
|
|
75
|
+
* @default 'left'
|
|
76
|
+
*/
|
|
77
|
+
position?: 'left' | 'right'
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** 水平标签栏事件 */
|
|
81
|
+
export interface TabsHorizontalEmits {
|
|
82
|
+
(e: 'update:modelValue', value: string): void
|
|
83
|
+
(e: 'click', item: TabItem, index: number): void
|
|
84
|
+
(e: 'close', item: TabItem, index: number): void
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** 垂直标签栏事件 */
|
|
88
|
+
export interface TabsVerticalEmits {
|
|
89
|
+
(e: 'update:modelValue', value: string): void
|
|
90
|
+
(e: 'click', item: TabItem, index: number): void
|
|
91
|
+
(e: 'close', item: TabItem, index: number): void
|
|
15
92
|
}
|
|
16
93
|
|
|
17
94
|
/** 标签页组件组件属性 */
|
|
18
95
|
export interface TabsProps extends ComponentProps {
|
|
96
|
+
/** 当前激活的标签 key */
|
|
19
97
|
modelValue?: string
|
|
20
98
|
/** 标签项 */
|
|
21
99
|
items: TabItem[]
|
|
100
|
+
/**
|
|
101
|
+
* 是否可关闭
|
|
102
|
+
* @description 作为所有 TabItem 未显式 `closable` 时的默认值;禁用项不显示关闭按钮
|
|
103
|
+
* @default false
|
|
104
|
+
*/
|
|
105
|
+
closable?: boolean
|
|
106
|
+
/**
|
|
107
|
+
* 是否填充父容器宽度(仅在 position=top/bottom 时生效)
|
|
108
|
+
* @description 开启时 header 容器占满父容器宽度,背景完整铺开;tab-item 自身宽度保持不变
|
|
109
|
+
* @default false
|
|
110
|
+
*/
|
|
111
|
+
block?: boolean
|
|
112
|
+
/**
|
|
113
|
+
* 是否开启圆角胶囊风格
|
|
114
|
+
* @default false
|
|
115
|
+
*/
|
|
116
|
+
rounded?: boolean
|
|
22
117
|
/** 显示位置 */
|
|
23
118
|
position?: 'left' | 'right' | 'top' | 'bottom'
|
|
24
|
-
/** 是否可以动态编辑 */
|
|
25
|
-
editable?: boolean
|
|
26
119
|
/**
|
|
27
120
|
* 是否保活
|
|
28
121
|
* @default false
|
|
29
122
|
*/
|
|
30
123
|
keepAlive?: boolean
|
|
31
|
-
/** 是否允许拖拽排序 */
|
|
32
|
-
// sortable?: boolean
|
|
33
|
-
// beforeLeave?: (
|
|
34
|
-
// prev: string | number,
|
|
35
|
-
// next: string | number
|
|
36
|
-
// ) => void | boolean | Promise<void | boolean>
|
|
37
124
|
}
|
|
38
125
|
|
|
39
126
|
/** 标签页组件组件定义的事件 */
|
|
40
127
|
export interface TabsEmits {
|
|
41
|
-
(e: 'update:modelValue', value: string
|
|
42
|
-
(e: 'update:items', items: TabItem[]): void
|
|
43
|
-
(e: 'update:active', active: string | number): void
|
|
44
|
-
(e: 'delete', item: TabItem, index: number): void
|
|
45
|
-
(e: 'create'): void
|
|
128
|
+
(e: 'update:modelValue', value: string): void
|
|
46
129
|
(e: 'click', item: TabItem, index: number): void
|
|
130
|
+
(e: 'close', item: TabItem, index: number): void
|
|
47
131
|
}
|
|
48
132
|
|
|
49
|
-
/**
|
|
133
|
+
/** 标签页组件暴露的属性和方法(组件内部使用) */
|
|
50
134
|
export interface _TabsExposed {}
|
|
51
135
|
|
|
52
|
-
/**
|
|
53
|
-
export interface TabsExposed {
|
|
54
|
-
|
|
55
|
-
|
|
136
|
+
/** 标签页组件暴露的属性和方法(组件外部使用, 引用的值会被自动解构) */
|
|
137
|
+
export interface TabsExposed {}
|
|
138
|
+
|
|
139
|
+
/** 水平标签栏暴露的属性和方法(组件内部使用) */
|
|
140
|
+
export interface _TabsHorizontalExposed {}
|
|
141
|
+
|
|
142
|
+
/** 水平标签栏暴露的属性和方法(组件外部使用) */
|
|
143
|
+
export interface TabsHorizontalExposed {}
|
|
144
|
+
|
|
145
|
+
/** 垂直标签栏暴露的属性和方法(组件内部使用) */
|
|
146
|
+
export interface _TabsVerticalExposed {}
|
|
147
|
+
|
|
148
|
+
/** 垂直标签栏暴露的属性和方法(组件外部使用) */
|
|
149
|
+
export interface TabsVerticalExposed {}
|
package/src/types/tree.ts
CHANGED
|
@@ -76,7 +76,12 @@ export interface TreeEmit {
|
|
|
76
76
|
|
|
77
77
|
export interface TreeNodeProps {
|
|
78
78
|
node: TreeNode
|
|
79
|
-
|
|
79
|
+
/**
|
|
80
|
+
* 虚拟项索引:对应 `nodes` 数组中的绝对位置。
|
|
81
|
+
* 需要传入以便在节点卸载时正确通知 `Virtualizer` 解绑,避免 size=0 的脏测量。
|
|
82
|
+
*/
|
|
83
|
+
index?: number
|
|
84
|
+
measureElement?: (index: number, el: Element | null) => void
|
|
80
85
|
}
|
|
81
86
|
|
|
82
87
|
/** 树组件暴露的属性和方法(组件内部使用) */
|