@veltra/desktop 1.7.19 → 1.8.0

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.
Files changed (71) hide show
  1. package/dist/components/batch-edit/batch-edit-form.js +40 -26
  2. package/dist/components/batch-edit/batch-edit-form.js.map +1 -1
  3. package/dist/components/batch-edit/use-handlers.js +3 -3
  4. package/dist/components/batch-edit/use-handlers.js.map +1 -1
  5. package/dist/components/batch-edit/use-shortcut-key.js +4 -2
  6. package/dist/components/batch-edit/use-shortcut-key.js.map +1 -1
  7. package/dist/components/card/style2.css +0 -2
  8. package/dist/components/dropdown/dropdown.js +5 -3
  9. package/dist/components/dropdown/dropdown.js.map +1 -1
  10. package/dist/components/expression-editor/components/path-preview.js +3 -6
  11. package/dist/components/expression-editor/components/path-preview.js.map +1 -1
  12. package/dist/components/expression-editor/components/variable-picker.js +49 -12
  13. package/dist/components/expression-editor/components/variable-picker.js.map +1 -1
  14. package/dist/components/expression-editor/core/editor.js +20 -0
  15. package/dist/components/expression-editor/core/editor.js.map +1 -1
  16. package/dist/components/expression-editor/expression-editor.js +53 -18
  17. package/dist/components/expression-editor/expression-editor.js.map +1 -1
  18. package/dist/components/expression-editor/style2.css +135 -73
  19. package/dist/components/form/form.js.map +1 -1
  20. package/dist/components/form/form.vue_vue_type_script_setup_true_lang.js +0 -1
  21. package/dist/components/form/form.vue_vue_type_script_setup_true_lang.js.map +1 -1
  22. package/dist/components/form/style2.css +8 -3
  23. package/dist/components/index.d.ts +26 -26
  24. package/dist/components/index.js +52 -52
  25. package/dist/components/multi-select/multi-select.js +16 -12
  26. package/dist/components/multi-select/multi-select.js.map +1 -1
  27. package/dist/components/multi-select/style2.css +7 -0
  28. package/dist/components/multi-tree-select/multi-tree-select.js +82 -56
  29. package/dist/components/multi-tree-select/multi-tree-select.js.map +1 -1
  30. package/dist/components/multi-tree-select/style2.css +7 -0
  31. package/dist/components/select/select.js +7 -3
  32. package/dist/components/select/select.js.map +1 -1
  33. package/dist/components/select/style2.css +7 -0
  34. package/dist/components/select/use-options.js +14 -3
  35. package/dist/components/select/use-options.js.map +1 -1
  36. package/dist/components/tree-select/style2.css +7 -0
  37. package/dist/components/tree-select/tree-select.js +49 -17
  38. package/dist/components/tree-select/tree-select.js.map +1 -1
  39. package/dist/index.d.ts +1 -1
  40. package/dist/index.js +2 -2
  41. package/dist/types/dropdown.d.ts +10 -0
  42. package/dist/types/multi-tree-select.d.ts +7 -1
  43. package/dist/types/tree-select.d.ts +7 -1
  44. package/package.json +1 -1
  45. package/src/components/batch-edit/__test__/batch-edit.test.ts +112 -1
  46. package/src/components/batch-edit/batch-edit-form.vue +21 -2
  47. package/src/components/batch-edit/use-handlers.ts +6 -5
  48. package/src/components/batch-edit/use-shortcut-key.ts +5 -2
  49. package/src/components/card/style.scss +0 -2
  50. package/src/components/dropdown/dropdown.vue +9 -4
  51. package/src/components/expression-editor/components/path-preview.vue +1 -2
  52. package/src/components/expression-editor/components/variable-picker.vue +54 -13
  53. package/src/components/expression-editor/core/editor.ts +28 -0
  54. package/src/components/expression-editor/expression-editor.vue +47 -17
  55. package/src/components/expression-editor/style.scss +167 -82
  56. package/src/components/form/form.vue +0 -1
  57. package/src/components/form/style.scss +11 -4
  58. package/src/components/multi-select/multi-select.vue +11 -2
  59. package/src/components/multi-select/style.scss +6 -0
  60. package/src/components/multi-tree-select/multi-tree-select.vue +58 -9
  61. package/src/components/multi-tree-select/style.scss +6 -0
  62. package/src/components/select/__test__/select.test.ts +78 -0
  63. package/src/components/select/select.vue +13 -3
  64. package/src/components/select/style.scss +6 -0
  65. package/src/components/select/use-options.ts +25 -4
  66. package/src/components/tree-select/__test__/tree-select.test.ts +116 -0
  67. package/src/components/tree-select/style.scss +6 -0
  68. package/src/components/tree-select/tree-select.vue +63 -13
  69. package/src/types/dropdown.ts +10 -0
  70. package/src/types/multi-tree-select.ts +12 -1
  71. package/src/types/tree-select.ts +12 -1
@@ -49,8 +49,13 @@
49
49
  <template #content>
50
50
  <!-- 菜单列表 -->
51
51
 
52
+ <div v-if="remoteLoading" :class="cls.e('loading')">
53
+ <ULoading type="dual-ring" />
54
+ </div>
52
55
  <u-tree
56
+ v-else
53
57
  v-bind="treeProps"
58
+ :data="treeData"
54
59
  :selected="model"
55
60
  @update:selected="handleSelect"
56
61
  ref="treeRef"
@@ -68,7 +73,7 @@
68
73
  </template>
69
74
 
70
75
  <script lang="ts" setup>
71
- import { dfs, o } from '@cat-kit/core'
76
+ import { debounce, dfs, o } from '@cat-kit/core'
72
77
  import { useFormFallbackProps, useUserAction } from '@veltra/compositions'
73
78
  import { ArrowDown, Close } from '@veltra/icons/normal'
74
79
  import { bem, fieldKey, FORM_EMPTY_CONTENT } from '@veltra/utils'
@@ -79,6 +84,7 @@ import type { TreeSelectProps, TreeSelectEmits, TreeExposed, InputExposed } from
79
84
  import { UDropdown } from '../dropdown'
80
85
  import { UIcon } from '../icon'
81
86
  import { UInput } from '../input'
87
+ import { ULoading } from '../loading'
82
88
  import { UTree } from '../tree'
83
89
  import type { TreeSlotsScope } from '../tree/di'
84
90
 
@@ -113,6 +119,7 @@ const treeProps = computed(() => {
113
119
  'disabled',
114
120
  'label',
115
121
  'readonly',
122
+ 'data',
116
123
  'contentClass',
117
124
  'contentStyle',
118
125
  'minWidth',
@@ -125,11 +132,56 @@ const cls = bem('tree-select')
125
132
  const labelKey = computed(() => fieldKey(props.labelKey, 'label'))
126
133
  const valueKey = computed(() => fieldKey(props.valueKey, 'value'))
127
134
 
128
- /**过滤 */
135
+ /** 是否可搜索:显式声明或数据源为远程函数 */
136
+ const filterable = computed(() => props.filterable || typeof props.data === 'function')
137
+
138
+ /** 过滤 */
129
139
  const qs = shallowRef('')
130
- watch(qs, (qs) => {
131
- treeRef.value?.filter(qs)
132
- })
140
+
141
+ const treeRef = shallowRef<TreeExposed>()
142
+
143
+ /** 远程搜索返回的树数据 */
144
+ const remoteData = shallowRef<Record<string, any>[]>()
145
+
146
+ /** 面板渲染的树数据:data 为函数时来自远程搜索,否则为静态数据 */
147
+ const treeData = computed(() => (typeof props.data === 'function' ? remoteData.value : props.data))
148
+
149
+ const remoteLoading = shallowRef(false)
150
+ /** 远程请求序号;响应返回时序号不一致说明已有更新的请求,结果作废 */
151
+ let remoteSeq = 0
152
+
153
+ const debouncedRemoteSearch = debounce(
154
+ async (
155
+ query: string,
156
+ dataFn: (qs: string) => Promise<Record<string, any>[]> | Record<string, any>[]
157
+ ) => {
158
+ const seq = ++remoteSeq
159
+ remoteLoading.value = true
160
+ try {
161
+ const data = await dataFn(query)
162
+ // 响应到达时查询词可能已变化或已有更新的请求,过期结果直接丢弃
163
+ if (seq !== remoteSeq || query !== qs.value) return
164
+ remoteData.value = data ?? []
165
+ // 搜索结果展示完整命中路径,与本地过滤自动展开祖先的行为对齐
166
+ if (query) nextTick(() => treeRef.value?.expandAll())
167
+ } finally {
168
+ if (seq === remoteSeq) remoteLoading.value = false
169
+ }
170
+ },
171
+ 200
172
+ )
173
+
174
+ watch(
175
+ [qs, () => props.data],
176
+ ([query, data]) => {
177
+ if (typeof data === 'function') {
178
+ debouncedRemoteSearch(query, data)
179
+ return
180
+ }
181
+ treeRef.value?.filter(query)
182
+ },
183
+ { immediate: true }
184
+ )
133
185
 
134
186
  const model = defineModel<string | number>()
135
187
 
@@ -156,21 +208,21 @@ function setLabel(next?: string) {
156
208
 
157
209
  /** 触发输入框的值:查询态下承载查询串,否则展示选中标签 */
158
210
  const inputValue = computed(() => {
159
- if (props.filterable && querying.value) return qs.value
211
+ if (filterable.value && querying.value) return qs.value
160
212
  return model.value || model.value === 0 ? label.value : undefined
161
213
  })
162
214
 
163
215
  /** 查询态下已选标签降级为占位提示 */
164
216
  const inputPlaceholder = computed(() => {
165
217
  const display = model.value || model.value === 0 ? label.value : undefined
166
- if (props.filterable && querying.value && display) {
218
+ if (filterable.value && querying.value && display) {
167
219
  return display
168
220
  }
169
221
  return props.placeholder
170
222
  })
171
223
 
172
224
  function handleQueryInput(value: string) {
173
- if (!props.filterable) return
225
+ if (!filterable.value) return
174
226
  qs.value = value
175
227
  }
176
228
 
@@ -188,7 +240,7 @@ const showClear = computed(() => {
188
240
  * 非输入区域(箭头、留白)放行,维持原开合行为。
189
241
  */
190
242
  function handleTriggerClickCapture(e: MouseEvent) {
191
- if (!props.filterable || disabled.value) return
243
+ if (!filterable.value || disabled.value) return
192
244
  if (!(e.target instanceof HTMLInputElement)) return
193
245
 
194
246
  e.stopPropagation()
@@ -196,7 +248,7 @@ function handleTriggerClickCapture(e: MouseEvent) {
196
248
  }
197
249
 
198
250
  watch(dropdownVisible, (visible) => {
199
- if (visible && props.filterable) {
251
+ if (visible && filterable.value) {
200
252
  // 面板展开后进入查询态并聚焦输入框,可以立即输入查询
201
253
  querying.value = true
202
254
  nextTick(() => inputRef.value?.el?.focus())
@@ -209,8 +261,6 @@ const { formProps } = injectFormContext()
209
261
 
210
262
  const { size, disabled, readonly } = useFormFallbackProps([formProps ?? {}, props])
211
263
 
212
- const treeRef = shallowRef<TreeExposed>()
213
-
214
264
  const dropdownRef = shallowRef<InstanceType<typeof UDropdown>>()
215
265
 
216
266
  const { userAction, isUserActive } = useUserAction()
@@ -225,7 +275,7 @@ const handleClear = userAction(() => {
225
275
 
226
276
  /** 外部回显:按 data 查找 label(O(n));用户动作期内跳过 */
227
277
  watch(
228
- [() => props.data, model],
278
+ [treeData, model],
229
279
  ([data, modelVal]) => {
230
280
  if (isUserActive()) return
231
281
  if (!data?.length || modelVal === undefined || modelVal === null || modelVal === '') {
@@ -8,6 +8,16 @@ export interface DropdownProps {
8
8
  * @default 'hover'
9
9
  */
10
10
  trigger?: 'hover' | 'click' | 'custom'
11
+ /**
12
+ * 弹出方向;空间不足时仍会自动翻转
13
+ * @default 'bottom'
14
+ */
15
+ direction?: 'top' | 'bottom' | 'left' | 'right'
16
+ /**
17
+ * 弹出对齐方式
18
+ * @default 'start'
19
+ */
20
+ alignment?: 'center' | 'start' | 'end'
11
21
  /**
12
22
  * 宽度
13
23
  * @default - 跟随触发宽度
@@ -4,9 +4,20 @@ import type { CSSProperties } from 'vue'
4
4
  import type { TreeProps } from './tree'
5
5
  /** 树形多选组件组件属性 */
6
6
  export interface MultiTreeSelectProps
7
- extends FormComponentProps, Omit<TreeProps, 'selected' | 'checked' | 'selectable' | 'checkable'> {
7
+ extends
8
+ FormComponentProps,
9
+ Omit<TreeProps, 'selected' | 'checked' | 'selectable' | 'checkable' | 'data'> {
8
10
  modelValue?: (string | number)[]
9
11
 
12
+ /**
13
+ * 树数据
14
+ * @description 如果传入一个函数,那么filterable会被强制启用;
15
+ * 函数按查询词返回匹配的树,初始以空串调用一次(加载默认树)
16
+ */
17
+ data?:
18
+ | Record<string, any>[]
19
+ | ((qs: string) => Promise<Record<string, any>[]> | Record<string, any>[])
20
+
10
21
  /**自定义占位文字 */
11
22
  placeholder?: string
12
23
  /**
@@ -5,9 +5,20 @@ import type { TreeProps } from './tree'
5
5
 
6
6
  /** 树形选择器组件属性 */
7
7
  export interface TreeSelectProps
8
- extends FormComponentProps, Omit<TreeProps, 'selected' | 'checked' | 'selectable' | 'checkable'> {
8
+ extends
9
+ FormComponentProps,
10
+ Omit<TreeProps, 'selected' | 'checked' | 'selectable' | 'checkable' | 'data'> {
9
11
  modelValue?: string | number
10
12
 
13
+ /**
14
+ * 树数据
15
+ * @description 如果传入一个函数,那么filterable会被强制启用;
16
+ * 函数按查询词返回匹配的树,初始以空串调用一次(加载默认树)
17
+ */
18
+ data?:
19
+ | Record<string, any>[]
20
+ | ((qs: string) => Promise<Record<string, any>[]> | Record<string, any>[])
21
+
11
22
  /** 自定义占位文字 */
12
23
  placeholder?: string
13
24
  /**