@veltra/desktop 1.3.7 → 1.3.9

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.
@@ -63,13 +63,13 @@
63
63
  </u-dropdown>
64
64
 
65
65
  <template v-else>
66
- {{ text || label || FORM_EMPTY_CONTENT }}
66
+ {{ label || FORM_EMPTY_CONTENT }}
67
67
  </template>
68
68
  </template>
69
69
 
70
70
  <script lang="ts" setup>
71
71
  import { dfs, o } from '@cat-kit/core'
72
- import { useFormFallbackProps } from '@veltra/compositions'
72
+ import { useFormFallbackProps, useUserAction } from '@veltra/compositions'
73
73
  import { ArrowDown, Close } from '@veltra/icons/normal'
74
74
  import { bem, fieldKey, FORM_EMPTY_CONTENT } from '@veltra/utils'
75
75
  import { injectFormContext } from '@veltra/utils'
@@ -133,6 +133,7 @@ watch(qs, (qs) => {
133
133
 
134
134
  const model = defineModel<string | number>()
135
135
 
136
+ /** 内部展示文案,仅由 data 推导;通过 update:text 单向通知父级 */
136
137
  const label = shallowRef<string>()
137
138
 
138
139
  const dropdownVisible = shallowRef(false)
@@ -146,15 +147,22 @@ const querying = shallowRef(false)
146
147
 
147
148
  const inputRef = useTemplateRef<InputExposed>('inputRef')
148
149
 
150
+ /** 更新内部文案;值变化时单向 emit update:text */
151
+ function setLabel(next?: string) {
152
+ if (label.value === next) return
153
+ label.value = next
154
+ emit('update:text', next)
155
+ }
156
+
149
157
  /** 触发输入框的值:查询态下承载查询串,否则展示选中标签 */
150
158
  const inputValue = computed(() => {
151
159
  if (props.filterable && querying.value) return qs.value
152
- return props.text ?? (model.value ? label.value : undefined)
160
+ return model.value || model.value === 0 ? label.value : undefined
153
161
  })
154
162
 
155
163
  /** 查询态下已选标签降级为占位提示 */
156
164
  const inputPlaceholder = computed(() => {
157
- const display = props.text ?? (model.value ? label.value : undefined)
165
+ const display = model.value || model.value === 0 ? label.value : undefined
158
166
  if (props.filterable && querying.value && display) {
159
167
  return display
160
168
  }
@@ -171,7 +179,7 @@ const hovered = shallowRef(false)
171
179
  /** 悬停且存在选中值时展示清除按钮(替代下拉箭头) */
172
180
  const showClear = computed(() => {
173
181
  if (!props.clearable || disabled.value || !hovered.value) return false
174
- return !!(props.text ?? (model.value ? label.value : undefined))
182
+ return !!(model.value || model.value === 0 ? label.value : undefined)
175
183
  })
176
184
 
177
185
  /**
@@ -205,34 +213,35 @@ const treeRef = shallowRef<TreeExposed>()
205
213
 
206
214
  const dropdownRef = shallowRef<InstanceType<typeof UDropdown>>()
207
215
 
208
- /**清空 */
209
- const handleClear = () => {
216
+ const { userAction, isUserActive } = useUserAction()
217
+
218
+ /** 清空 */
219
+ const handleClear = userAction(() => {
210
220
  model.value = ''
211
- label.value = undefined
221
+ setLabel(undefined)
212
222
  emit('clear')
213
223
  emit('change', undefined)
214
- emit('update:text', '')
215
- }
224
+ })
216
225
 
217
- let changedByEvent = false
226
+ /** 外部回显:按 data 查找 label(O(n));用户动作期内跳过 */
218
227
  watch(
219
228
  [() => props.data, model],
220
- ([data, model]) => {
221
- if (changedByEvent) return
222
- if (!data?.length || model === undefined) {
223
- label.value = undefined
224
- model = undefined
229
+ ([data, modelVal]) => {
230
+ if (isUserActive()) return
231
+ if (!data?.length || modelVal === undefined || modelVal === null || modelVal === '') {
232
+ setLabel(undefined)
225
233
  return
226
234
  }
227
235
 
228
- let founded = false
236
+ let nextLabel: string | undefined
229
237
  const childrenKey = props.childrenKey ?? 'children'
230
238
  data.some((item) => {
239
+ let founded = false
231
240
  dfs(
232
241
  item,
233
242
  (v) => {
234
- if (v[valueKey.value] === model) {
235
- label.value = v[labelKey.value]
243
+ if (v[valueKey.value] === modelVal) {
244
+ nextLabel = v[labelKey.value]
236
245
  founded = true
237
246
  return true
238
247
  }
@@ -242,32 +251,29 @@ watch(
242
251
 
243
252
  return founded
244
253
  })
254
+ setLabel(nextLabel)
245
255
  },
246
256
  { immediate: true }
247
257
  )
248
258
 
249
- const handleSelect = (selected?: string | number, selectedData?: Record<string, any>) => {
250
- changedByEvent = true
251
- nextTick(() => {
252
- changedByEvent = false
253
- })
259
+ /** 用户选择:O(1) 写入值与文案,跳过 data 回显查找 */
260
+ const handleSelect = userAction(
261
+ (selected?: string | number, selectedData?: Record<string, any>) => {
262
+ model.value = selected ?? ''
254
263
 
255
- model.value = selected ?? ''
264
+ if (selectedData) {
265
+ setLabel(o(selectedData).get(labelKey.value))
266
+ } else {
267
+ setLabel(undefined)
268
+ }
256
269
 
257
- if (selectedData) {
258
- label.value = o(selectedData).get(labelKey.value)
259
- } else {
260
- label.value = ''
270
+ emit('change', selectedData)
271
+ // 立即退出查询态,输入框同步恢复显示选中标签
272
+ querying.value = false
273
+ qs.value = ''
274
+ dropdownRef.value?.close()
261
275
  }
262
-
263
- emit('change', selectedData)
264
- emit('update:text', label.value)
265
- // 立即退出查询态,输入框同步恢复显示选中标签
266
- querying.value = false
267
- qs.value = ''
268
- dropdownRef.value?.close()
269
- }
270
-
276
+ )
271
277
  const handleDropdownVisible = (visible: boolean) => {
272
278
  if (!visible) {
273
279
  qs.value = ''
@@ -5,8 +5,6 @@ import type { CSSProperties, ShallowRef } from 'vue'
5
5
  export interface SelectProps extends FormComponentProps {
6
6
  /** 绑定值 */
7
7
  modelValue?: any
8
- /** 文本内容 */
9
- text?: string
10
8
  /**
11
9
  * 列表选项
12
10
  * @description 如果传入一个函数,那么filterable会被强制启用
@@ -55,8 +53,11 @@ export interface SelectProps extends FormComponentProps {
55
53
  }
56
54
 
57
55
  export interface SelectEmits {
58
- /** 触发更新label事件 */
59
- (e: 'update:label', label?: string): void
56
+ /**
57
+ * 选中项文案变化(单向通知,用于同步父级冗余字段)
58
+ * @description 展示始终由 options 推导,请用 `@update:text` 而非 `v-model:text`
59
+ */
60
+ (e: 'update:text', text?: string): void
60
61
  (e: 'update:modelValue', modelValue?: any): void
61
62
  (e: 'change', option?: Record<string, any>): void
62
63
  }
@@ -29,9 +29,6 @@ export interface TreeSelectProps
29
29
  */
30
30
  width?: string
31
31
 
32
- /** 显示文本 */
33
- text?: string
34
-
35
32
  /** 内容容器样式 */
36
33
  contentStyle?: CSSProperties | string
37
34
 
@@ -44,6 +41,10 @@ export interface TreeSelectEmits {
44
41
  (e: 'clear'): void
45
42
  (e: 'update:modelValue', value?: string | number): void
46
43
  (e: 'change', selectedData?: Record<string, any>): void
44
+ /**
45
+ * 选中项文案变化(单向通知,用于同步父级冗余字段)
46
+ * @description 展示始终由 data 推导,请用 `@update:text` 而非 `v-model:text`
47
+ */
47
48
  (e: 'update:text', text?: string): void
48
49
  }
49
50