@veltra/desktop 1.1.36 → 1.2.1

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 (129) hide show
  1. package/dist/components/auto-complete/auto-complete.js +1 -0
  2. package/dist/components/auto-complete/auto-complete.js.map +1 -1
  3. package/dist/components/batch-edit/batch-edit-form.js +12 -5
  4. package/dist/components/batch-edit/batch-edit-form.js.map +1 -1
  5. package/dist/components/batch-edit/batch-edit.js +8 -3
  6. package/dist/components/batch-edit/batch-edit.js.map +1 -1
  7. package/dist/components/batch-edit/batch-edit.vue.d.ts +40 -35
  8. package/dist/components/batch-edit/di.js.map +1 -1
  9. package/dist/components/batch-edit/use-edit.js +41 -23
  10. package/dist/components/batch-edit/use-edit.js.map +1 -1
  11. package/dist/components/cascade/cascade.js +1 -0
  12. package/dist/components/cascade/cascade.js.map +1 -1
  13. package/dist/components/checkbox/checkbox-button.js +1 -0
  14. package/dist/components/checkbox/checkbox-button.js.map +1 -1
  15. package/dist/components/checkbox/checkbox.js +1 -0
  16. package/dist/components/checkbox/checkbox.js.map +1 -1
  17. package/dist/components/checkbox-group/checkbox-group.js +1 -0
  18. package/dist/components/checkbox-group/checkbox-group.js.map +1 -1
  19. package/dist/components/code-editor/code-editor.js +2 -1
  20. package/dist/components/code-editor/code-editor.js.map +1 -1
  21. package/dist/components/condition-editor/core/evaluator.js +3 -3
  22. package/dist/components/condition-editor/core/evaluator.js.map +1 -1
  23. package/dist/components/date-picker/date-picker.js +1 -0
  24. package/dist/components/date-picker/date-picker.js.map +1 -1
  25. package/dist/components/date-range-picker/date-range-picker.js +2 -0
  26. package/dist/components/date-range-picker/date-range-picker.js.map +1 -1
  27. package/dist/components/expression-editor/expression-editor.js +1 -0
  28. package/dist/components/expression-editor/expression-editor.js.map +1 -1
  29. package/dist/components/file-picker/file-picker.js +1 -0
  30. package/dist/components/file-picker/file-picker.js.map +1 -1
  31. package/dist/components/form/form.js.map +1 -1
  32. package/dist/components/form/form.vue.d.ts +11 -19
  33. package/dist/components/form/form.vue_vue_type_script_setup_true_lang.js +24 -26
  34. package/dist/components/form/form.vue_vue_type_script_setup_true_lang.js.map +1 -1
  35. package/dist/components/form/index.d.ts +0 -3
  36. package/dist/components/form/use-form-fields.js +88 -0
  37. package/dist/components/form/use-form-fields.js.map +1 -0
  38. package/dist/components/form/use-node-interceptor.js +19 -30
  39. package/dist/components/form/use-node-interceptor.js.map +1 -1
  40. package/dist/components/form-item/form-item.js.map +1 -1
  41. package/dist/components/form-item/form-item.vue_vue_type_script_setup_true_lang.js +44 -18
  42. package/dist/components/form-item/form-item.vue_vue_type_script_setup_true_lang.js.map +1 -1
  43. package/dist/components/form-item/helper.js +4 -1
  44. package/dist/components/form-item/helper.js.map +1 -1
  45. package/dist/components/form-item/validate.js +97 -0
  46. package/dist/components/form-item/validate.js.map +1 -0
  47. package/dist/components/group-input/group-input.js +1 -0
  48. package/dist/components/group-input/group-input.js.map +1 -1
  49. package/dist/components/index.d.ts +0 -3
  50. package/dist/components/index.js +0 -7
  51. package/dist/components/input/input.vue.d.ts +4 -4
  52. package/dist/components/input/input.vue_vue_type_script_setup_true_lang.js +1 -0
  53. package/dist/components/input/input.vue_vue_type_script_setup_true_lang.js.map +1 -1
  54. package/dist/components/multi-select/multi-select.js +1 -0
  55. package/dist/components/multi-select/multi-select.js.map +1 -1
  56. package/dist/components/multi-tree-select/multi-tree-select.js +1 -0
  57. package/dist/components/multi-tree-select/multi-tree-select.js.map +1 -1
  58. package/dist/components/number-input/number-input.js +1 -0
  59. package/dist/components/number-input/number-input.js.map +1 -1
  60. package/dist/components/number-range-input/number-range-input.js +1 -0
  61. package/dist/components/number-range-input/number-range-input.js.map +1 -1
  62. package/dist/components/number-range-input/number-range-input.vue.d.ts +1 -1
  63. package/dist/components/palette/palette.js +1 -0
  64. package/dist/components/palette/palette.js.map +1 -1
  65. package/dist/components/password-input/password-input.js +1 -0
  66. package/dist/components/password-input/password-input.js.map +1 -1
  67. package/dist/components/radio/radio.js +1 -0
  68. package/dist/components/radio/radio.js.map +1 -1
  69. package/dist/components/radio-group/radio-group.js +1 -0
  70. package/dist/components/radio-group/radio-group.js.map +1 -1
  71. package/dist/components/rich-text-editor/rich-text-editor.js +3 -2
  72. package/dist/components/rich-text-editor/rich-text-editor.js.map +1 -1
  73. package/dist/components/rich-text-editor/toolbar.js +10 -7
  74. package/dist/components/rich-text-editor/toolbar.js.map +1 -1
  75. package/dist/components/select/select.js +6 -3
  76. package/dist/components/select/select.js.map +1 -1
  77. package/dist/components/slider/slider.js +15 -2
  78. package/dist/components/slider/slider.js.map +1 -1
  79. package/dist/components/switch/switch.js +1 -0
  80. package/dist/components/switch/switch.js.map +1 -1
  81. package/dist/components/tabs/tabs-horizontal.vue.d.ts +2 -2
  82. package/dist/components/tabs/tabs-vertical.vue.d.ts +2 -2
  83. package/dist/components/tabs/tabs.vue.d.ts +2 -2
  84. package/dist/components/textarea/textarea.js +1 -0
  85. package/dist/components/textarea/textarea.js.map +1 -1
  86. package/dist/components/tip/tip.vue.d.ts +3 -3
  87. package/dist/components/tree-select/tree-select.js +1 -0
  88. package/dist/components/tree-select/tree-select.js.map +1 -1
  89. package/dist/index.d.ts +3 -6
  90. package/dist/index.js +1 -4
  91. package/dist/types/batch-edit.d.ts +4 -5
  92. package/dist/types/form.d.ts +9 -48
  93. package/dist/types/index.d.ts +2 -2
  94. package/package.json +6 -6
  95. package/src/components/batch-edit/batch-edit-form.vue +20 -13
  96. package/src/components/batch-edit/batch-edit.vue +7 -8
  97. package/src/components/batch-edit/di.ts +1 -2
  98. package/src/components/batch-edit/use-edit.ts +58 -36
  99. package/src/components/date-range-picker/date-range-picker.vue +2 -0
  100. package/src/components/form/form.vue +22 -38
  101. package/src/components/form/index.ts +0 -6
  102. package/src/components/form/use-form-fields.ts +126 -0
  103. package/src/components/form/use-node-interceptor.ts +27 -56
  104. package/src/components/form-item/form-item.vue +69 -18
  105. package/src/components/form-item/helper.ts +5 -1
  106. package/src/components/form-item/validate.ts +131 -0
  107. package/src/components/rich-text-editor/rich-text-editor.vue +28 -25
  108. package/src/components/rich-text-editor/toolbar.vue +23 -19
  109. package/src/components/select/select.vue +6 -4
  110. package/src/components/slider/slider.vue +12 -2
  111. package/src/types/auto-complete.ts +1 -1
  112. package/src/types/batch-edit.ts +4 -5
  113. package/src/types/form.ts +9 -82
  114. package/src/types/radio-group.ts +1 -0
  115. package/src/types/radio.ts +1 -0
  116. package/src/types/tree-select.ts +1 -1
  117. package/dist/components/form/dynamic-form-model.d.ts +0 -73
  118. package/dist/components/form/dynamic-form-model.js +0 -184
  119. package/dist/components/form/dynamic-form-model.js.map +0 -1
  120. package/dist/components/form/form-model.d.ts +0 -73
  121. package/dist/components/form/form-model.js +0 -179
  122. package/dist/components/form/form-model.js.map +0 -1
  123. package/dist/components/form/helper.d.ts +0 -16
  124. package/dist/components/form/helper.js +0 -20
  125. package/dist/components/form/helper.js.map +0 -1
  126. package/src/components/form/__test__/form-model.test.ts +0 -190
  127. package/src/components/form/dynamic-form-model.ts +0 -258
  128. package/src/components/form/form-model.ts +0 -255
  129. package/src/components/form/helper.ts +0 -23
@@ -1,5 +1,5 @@
1
1
  import { o } from '@cat-kit/core'
2
- import { bem, type BEM, type FormComponentProps } from '@veltra/utils'
2
+ import { bem, type BEM, type FormComponentProps, type FormFieldItem } from '@veltra/utils'
3
3
 
4
4
  /**
5
5
  * 获取表单项的属性
@@ -16,3 +16,7 @@ export function getFormItemProps(
16
16
  }
17
17
 
18
18
  export const formItemCls: BEM<'form-item'> = bem('form-item')
19
+
20
+ export function defineField(field: FormFieldItem) {
21
+ return field
22
+ }
@@ -0,0 +1,131 @@
1
+ import { isEmpty, o } from '@cat-kit/core'
2
+ import type { PresetRule, Undef, ValidateRule } from '@veltra/utils'
3
+
4
+ const presetRules: Record<PresetRule, (value: string) => string | undefined> = {
5
+ email(v) {
6
+ const re = /^([\w_-]+)@([\w-]+[.]?)*[\w]+\.[a-zA-Z]{2,10}$/
7
+ if (!re.test(v)) {
8
+ return '邮箱格式不正确'
9
+ }
10
+ },
11
+ phone(v) {
12
+ const re = /^\d{11}$/
13
+ if (!re.test(v)) {
14
+ return '手机号格式不正确'
15
+ }
16
+ },
17
+ num(v) {
18
+ const re = /^\d+$/
19
+ if (!re.test(v)) {
20
+ return '数字格式不正确'
21
+ }
22
+ },
23
+ url(v) {
24
+ const re = /^(ftp|https?):\/\/([\w_-]+)\.([\w-]+[.]?)*[\w]+\.[a-zA-Z]{2,10}(.*)/
25
+ if (!re.test(v)) {
26
+ return '链接格式不正确'
27
+ }
28
+ },
29
+
30
+ idCard(v) {
31
+ const re = /^(\d{6})(\d{4})(\d{2})(\d{2})(\d{3})([0-9]|X)$/
32
+ if (!re.test(v)) {
33
+ return '身份证格式不正确'
34
+ }
35
+ }
36
+ }
37
+
38
+ /** 预设规则 */
39
+ const ruleTypes = {
40
+ required(value: any, required: ValidateRule['required']): Undef<string> {
41
+ if (required === false) return
42
+
43
+ const errMsg = typeof required === 'string' ? required : '该项不能为空'
44
+ if (isEmpty(value)) return errMsg
45
+
46
+ if (Array.isArray(value) && !value.length) return errMsg
47
+ if (typeof value === 'string' && !value) return errMsg
48
+ },
49
+ min(value: any, rule: ValidateRule['min']): Undef<string> {
50
+ if (isEmpty(value)) return
51
+ let _rule = Array.isArray(rule) ? rule[0] : rule!
52
+ let errMsg = Array.isArray(rule) ? rule[1] : `该项必须大于等于${_rule}`
53
+ if (typeof value !== 'number') return `${value}不是一个数字`
54
+ if (value < _rule) return errMsg
55
+ },
56
+ max(value: any, rule: ValidateRule['max']): Undef<string> {
57
+ if (isEmpty(value)) return
58
+ let _rule = Array.isArray(rule) ? rule[0] : rule!
59
+ let errMsg = Array.isArray(rule) ? rule[1] : `该项必须小于等于${_rule}`
60
+ if (typeof value !== 'number') return `${value}不是一个数字`
61
+ if (value > _rule) return errMsg
62
+ },
63
+
64
+ minLen(value: any, rule: ValidateRule['minLen']): Undef<string> {
65
+ if (isEmpty(value)) return
66
+ let _rule = Array.isArray(rule) ? rule[0] : rule!
67
+ let errMsg = Array.isArray(rule) ? rule[1] : `该项长度必须大于等于${_rule}`
68
+ if (!Array.isArray(value) && typeof value !== 'string') return `${value}不是一个字符串或数组`
69
+ if (value.length < _rule) return errMsg
70
+ },
71
+ maxLen(value: any, rule: ValidateRule['maxLen']): Undef<string> {
72
+ if (isEmpty(value)) return
73
+ let _rule = Array.isArray(rule) ? rule[0] : rule!
74
+ let errMsg = Array.isArray(rule) ? rule[1] : `该项长度必须小于等于:${_rule}`
75
+ if (!Array.isArray(value) && typeof value !== 'string') return `${value}不是一个字符串或数组`
76
+ if (value.length > _rule) return errMsg
77
+ },
78
+ match(value: any, rule: ValidateRule['match']): Undef<string> {
79
+ if (isEmpty(value) || value === '') return
80
+ if (typeof rule === 'string') {
81
+ if (!rule) return
82
+ rule = new RegExp(rule)
83
+ }
84
+ let _rule = Array.isArray(rule) ? rule[0] : rule!
85
+ let errMsg = Array.isArray(rule) ? rule[1] : `该项不匹配正则:${_rule}`
86
+ if (typeof value !== 'string') return `${value}不是一个字符串`
87
+ if (!_rule.test(value)) return errMsg
88
+ },
89
+ preset(value: any, rule: ValidateRule['preset']): Undef<string> {
90
+ if (isEmpty(value) || value === '' || !rule) return
91
+ if (typeof value !== 'string') return `${value}不是一个字符串`
92
+ const ruleValidator = presetRules[rule]
93
+ return ruleValidator(value)
94
+ }
95
+ }
96
+
97
+ export async function validateField(
98
+ formData: Record<string, any>,
99
+ field: string,
100
+ rules: ValidateRule
101
+ ): Promise<Undef<string>> {
102
+ const value = o(formData).get(field)
103
+
104
+ if (!rules) return
105
+
106
+ const { validator, required, ...normalRules } = rules
107
+
108
+ // 必填要先去校验
109
+ if (required) {
110
+ const err = ruleTypes.required(value, required)
111
+ if (err) return err
112
+ }
113
+
114
+ // 校验规则
115
+ for (const ruleKey in normalRules) {
116
+ const validate = ruleTypes[ruleKey as keyof typeof ruleTypes]
117
+ if (!validate) continue
118
+
119
+ const err = validate(value, normalRules[ruleKey])
120
+
121
+ if (err) return err
122
+ }
123
+
124
+ // 自定义校验最火校验
125
+ if (validator) {
126
+ const err = await validator(value, formData)
127
+ if (err) return err
128
+ }
129
+
130
+ return
131
+ }
@@ -152,30 +152,33 @@ function initEditor() {
152
152
  // Listen for content changes
153
153
  cleanupFns.push(
154
154
  editorInstance.registerUpdateListener(({ editorState }) => {
155
- editorState.read(() => {
156
- const root = $getRoot()
157
- const textContent = root.getTextContent()
158
- showPlaceholder.value = textContent.trim().length === 0
159
-
160
- if (isComposing) return
161
-
162
- let value: string
163
- if (props.format === 'json') {
164
- value = JSON.stringify(editorState.toJSON())
165
- } else {
166
- value = $generateHtmlFromNodes(editorInstance)
167
- }
168
-
169
- // Avoid circular updates: only emit if content really changed
170
- if (value !== model.value) {
171
- isComposing = true
172
- model.value = value
173
- // Use microtask to reset after Vue processes the update
174
- queueMicrotask(() => {
175
- isComposing = false
176
- })
177
- }
178
- })
155
+ editorState.read(
156
+ () => {
157
+ const root = $getRoot()
158
+ const textContent = root.getTextContent()
159
+ showPlaceholder.value = textContent.trim().length === 0
160
+
161
+ if (isComposing) return
162
+
163
+ let value: string
164
+ if (props.format === 'json') {
165
+ value = JSON.stringify(editorState.toJSON())
166
+ } else {
167
+ value = $generateHtmlFromNodes(editorInstance)
168
+ }
169
+
170
+ // Avoid circular updates: only emit if content really changed
171
+ if (value !== model.value) {
172
+ isComposing = true
173
+ model.value = value
174
+ // Use microtask to reset after Vue processes the update
175
+ queueMicrotask(() => {
176
+ isComposing = false
177
+ })
178
+ }
179
+ },
180
+ { editor: editorInstance }
181
+ )
179
182
  })
180
183
  )
181
184
 
@@ -229,7 +232,7 @@ watch(model, (newVal) => {
229
232
  const editorInstance = editor.value
230
233
 
231
234
  // Compare current content to avoid circular updates
232
- editorInstance.getEditorState().read(() => {
235
+ editorInstance.read(() => {
233
236
  let currentValue: string
234
237
  if (props.format === 'json') {
235
238
  currentValue = JSON.stringify(editorInstance.getEditorState().toJSON())
@@ -84,12 +84,15 @@ let cleanupListener: (() => void) | null = null
84
84
  function setupListener(editorInstance: LexicalEditor) {
85
85
  cleanupListener?.()
86
86
  cleanupListener = editorInstance.registerUpdateListener(({ editorState }) => {
87
- editorState.read(() => {
88
- const selection = $getSelection()
89
- if (!$isRangeSelection(selection)) return
87
+ editorState.read(
88
+ () => {
89
+ const selection = $getSelection()
90
+ if (!$isRangeSelection(selection)) return
90
91
 
91
- updateToolbarState(selection)
92
- })
92
+ updateToolbarState(selection)
93
+ },
94
+ { editor: editorInstance }
95
+ )
93
96
  })
94
97
  }
95
98
 
@@ -235,24 +238,25 @@ function onHeadingChange(event: Event) {
235
238
  }
236
239
 
237
240
  function toggleLink(editorInstance: LexicalEditor) {
238
- editorInstance.getEditorState().read(() => {
241
+ let shouldRemoveLink = false
242
+
243
+ editorInstance.read(() => {
239
244
  const selection = $getSelection()
240
245
  if (!$isRangeSelection(selection)) return
241
246
 
242
- const anchorNode = selection.anchor.getNode()
243
- const parent = anchorNode.getParent()
244
-
245
- if ($isLinkNode(parent)) {
246
- // Remove link
247
- editorInstance.dispatchCommand(TOGGLE_LINK_COMMAND, null)
248
- } else {
249
- // Insert link with prompt
250
- const url = prompt('请输入链接地址:', 'https://')
251
- if (url && url !== 'https://') {
252
- editorInstance.dispatchCommand(TOGGLE_LINK_COMMAND, url)
253
- }
254
- }
247
+ const parent = selection.anchor.getNode().getParent()
248
+ shouldRemoveLink = $isLinkNode(parent)
255
249
  })
250
+
251
+ if (shouldRemoveLink) {
252
+ editorInstance.dispatchCommand(TOGGLE_LINK_COMMAND, null)
253
+ return
254
+ }
255
+
256
+ const url = prompt('请输入链接地址:', 'https://')
257
+ if (url && url !== 'https://') {
258
+ editorInstance.dispatchCommand(TOGGLE_LINK_COMMAND, url)
259
+ }
256
260
  }
257
261
 
258
262
  function getTitle(item: ToolbarItem): string {
@@ -209,14 +209,16 @@ watch(
209
209
 
210
210
  if (!options?.length) return
211
211
 
212
- if (modelValue !== undefined) {
213
- const { valueKey } = props
214
- currentIndex.value = options.findIndex((option) => o(option).get(valueKey) === modelValue)
212
+ const { valueKey, labelKey } = props
215
213
 
216
- selected.value = options[currentIndex.value]
214
+ if (modelValue !== undefined && modelValue !== null && modelValue !== '') {
215
+ currentIndex.value = options.findIndex((option) => o(option).get(valueKey) === modelValue)
216
+ selected.value = currentIndex.value >= 0 ? options[currentIndex.value] : undefined
217
+ label.value = selected.value ? o(selected.value).get(labelKey) : undefined
217
218
  } else {
218
219
  currentIndex.value = -1
219
220
  selected.value = undefined
221
+ label.value = undefined
220
222
  }
221
223
  },
222
224
  { immediate: true }
@@ -113,10 +113,20 @@ const ticks = computed(() => {
113
113
  watch(
114
114
  [offset1, offset2],
115
115
  userAction((v) => {
116
+ if (sliderSize.value === 0) return
117
+
116
118
  if (props.range) {
117
- emit('update:modelValue', v.map(sliderOffset2Value).toSorted() as T)
119
+ const next = v.map(sliderOffset2Value).toSorted((a, b) => a - b) as [number, number]
120
+ const current = props.modelValue as [number, number] | undefined
121
+ if (current) {
122
+ const [a, b] = [...current].sort((x, y) => x - y)
123
+ if (next[0] === a && next[1] === b) return
124
+ }
125
+ emit('update:modelValue', next as T)
118
126
  } else {
119
- emit('update:modelValue', sliderOffset2Value(v[0]) as T)
127
+ const next = sliderOffset2Value(v[0])
128
+ if (next === props.modelValue) return
129
+ emit('update:modelValue', next as T)
120
130
  }
121
131
  })
122
132
  )
@@ -1,4 +1,4 @@
1
- import type { FormComponentProps, DeconstructValue } from '@veltra/utils'
1
+ import type { DeconstructValue, FormComponentProps } from '@veltra/utils'
2
2
 
3
3
  /** 自动补全组件组件属性 */
4
4
  export interface AutoCompleteProps extends FormComponentProps {
@@ -1,7 +1,6 @@
1
1
  import type { DeconstructValue } from '@veltra/utils'
2
2
 
3
3
  import type { ActionProps } from './action'
4
- import type { IFormModel } from './form'
5
4
  import type { TableColumn, TableEmits, TableProps, TableRow } from './table'
6
5
 
7
6
  /** 批量编辑列 */
@@ -20,12 +19,12 @@ export interface BatchEditColumn extends TableColumn {
20
19
  export type BatchEditFeature = 'create' | 'update' | 'copy' | 'delete' | 'view' | 'createChild'
21
20
 
22
21
  /** 批量编辑组件属性 */
23
- export interface BatchEditProps<Model extends IFormModel = IFormModel> extends TableProps {
22
+ export interface BatchEditProps extends TableProps {
24
23
  /**
25
- * 表单模型
26
- * @description 该模型优先级要大于列配置
24
+ * 表单数据
25
+ * @description 与右侧 UForm 绑定的 reactive 对象
27
26
  */
28
- model?: Model
27
+ model?: Record<string, any>
29
28
  /** 表格标题 */
30
29
  title?: string
31
30
  /**
package/src/types/form.ts CHANGED
@@ -1,93 +1,16 @@
1
- import type { ComponentProps, DeconstructValue, ValidateRule } from '@veltra/utils'
1
+ import type { ComponentProps, DeconstructValue } from '@veltra/utils'
2
2
  import type { ShallowRef } from 'vue'
3
3
 
4
- import type { NestedFieldMarker } from '../components/form/helper'
5
-
6
- export interface FormModelItem<Val = any> extends ValidateRule {
7
- /** 模型值 */
8
- value?: Val
9
- }
10
-
11
- export type FormModelField = FormModelItem | NestedFieldMarker
12
-
13
- // 最终暴露的 ModelData 类型
14
- export type ModelData<Fields extends Record<string, any>> = {
15
- [key in keyof Fields]: Fields[key] extends NestedFieldMarker<infer SubFields>
16
- ? ModelData<SubFields>
17
- : Fields[key] extends FormModelItem
18
- ? Fields[key]['value'] extends () => infer T
19
- ? T
20
- : Fields[key]['value']
21
- : never
22
- }
23
-
24
- // 获取所有的扁平路径 Union(如 'name' | 'contact.email')
25
- export type AllKeys<Fields extends Record<string, any>> = {
26
- [K in keyof Fields]: K extends string
27
- ? Fields[K] extends NestedFieldMarker<infer SubFields>
28
- ? `${K}.${AllKeys<SubFields>}`
29
- : K
30
- : never
31
- }[keyof Fields]
32
-
33
- export type ModelRules<Fields extends Record<string, FormModelItem>> = {
34
- [key in keyof Fields]: Omit<Fields[key], 'value'>
35
- }
36
-
37
- export interface DataSettingConfig {
38
- /**
39
- * 是否校验
40
- * @default true
41
- */
42
- validate?: boolean
43
- }
44
-
45
- export type IFormModel<Fields extends Record<string, any> = Record<string, any>> = {
46
- /** 表单数据 */
47
- readonly data: ModelData<Fields>
48
- /** 字段校验规则 */
49
- readonly fields: Fields
50
- /**
51
- * 字段键
52
- */
53
- readonly allKeys: string[]
54
- /** 需要校验的key */
55
- formKeys: Map<number, string[]>
56
- /** 错误 */
57
- readonly errors: Map<string, string[] | undefined>
58
- /**
59
- * 字段校验
60
- * @param fields 字段, 如果不传入时将会使用keyFields来进行校验
61
- */
62
- validate: (fields?: string | string[]) => Promise<boolean>
63
- /** 重置数据 */
64
- resetData(fields?: string | string[]): void
65
-
66
- /**
67
- * 设置数据
68
- * @param formData 表单值
69
- * @param options 配置
70
- */
71
- setData(formData: Partial<Record<string, any>>, config?: DataSettingConfig): void
72
- /** 清除校验 */
73
- clearValidate(): void
74
- /** 监听值变更 */
75
- onChange(cb: (field: string, val: any) => void): void
76
- /** 关闭监听值变更 */
77
- offChange(cb: (field: string, val: any) => void): void
78
- }
79
-
80
4
  /** 表单组件属性 */
81
- export interface FormProps<Model extends IFormModel = IFormModel> extends ComponentProps {
5
+ export interface FormProps extends ComponentProps {
82
6
  /**
83
7
  * 自定义表单列数
84
8
  * - 默认根据尺寸断点自动排列
85
9
  */
86
10
  cols?: number
87
- /** 是否显示初始数据 */
88
- showInitialData?: boolean
89
- /** 表单数据模型 */
90
- model: Model
11
+ /** 表单数据 */
12
+ model?: Record<string, any>
13
+ // showModified?: boolean
91
14
  /** 表单项label宽度 */
92
15
  labelWidth?: string | number
93
16
  /** 是否不显示tips */
@@ -100,6 +23,10 @@ export interface FormProps<Model extends IFormModel = IFormModel> extends Compon
100
23
 
101
24
  export interface _FormExposed {
102
25
  el: ShallowRef<HTMLElement | null | undefined>
26
+ validate: (keys?: string[]) => Promise<boolean>
27
+ clearValidate: () => void
28
+ /** 将 model 恢复为最近一次 props.model 引用变更时的快照,并清除校验 */
29
+ reset: () => void
103
30
  }
104
31
 
105
32
  export type FormExposed = DeconstructValue<_FormExposed>
@@ -1,4 +1,5 @@
1
1
  import type { DeconstructValue, FormComponentProps } from '@veltra/utils'
2
+
2
3
  /** 单选框默认父组件组件属性 */
3
4
  export interface RadioGroupProps extends FormComponentProps {
4
5
  /** 值 */
@@ -1,4 +1,5 @@
1
1
  import type { DeconstructValue, FormComponentProps } from '@veltra/utils'
2
+
2
3
  /** 单选框组件属性 */
3
4
  export interface RadioProps extends FormComponentProps {
4
5
  /** 单选框值 */
@@ -1,4 +1,4 @@
1
- import type { FormComponentProps, DeconstructValue } from '@veltra/utils'
1
+ import type { DeconstructValue, FormComponentProps } from '@veltra/utils'
2
2
  import type { CSSProperties } from 'vue'
3
3
 
4
4
  import type { TreeProps } from './tree'
@@ -1,73 +0,0 @@
1
- import { DataSettingConfig, FormModelField } from "../../types/form.js";
2
- //#region src/components/form/dynamic-form-model.d.ts
3
- /**
4
- * 动态表单模型
5
- */
6
- declare class DynamicFormModel {
7
- /** 表单数据 */
8
- private _data;
9
- set data(v: Record<string, any>);
10
- get data(): Record<string, any>;
11
- /** 表单规则 */
12
- readonly fields: Record<string, FormModelField>;
13
- private flatFields;
14
- private validator;
15
- /**
16
- * 不同表单对应的key
17
- */
18
- formKeys: Map<number, string[]>;
19
- readonly errors: Map<string, string[] | undefined>;
20
- /**
21
- * 是否在表单值更新时校验
22
- */
23
- private validateOnFieldChange;
24
- private modelChangeCallback;
25
- private _allKeys;
26
- /** 所有的键 */
27
- get allKeys(): string[];
28
- private updateFlatFields;
29
- private getAllKeys;
30
- /** 初始数据 */
31
- readonly initialData: Record<string, any>;
32
- /**
33
- * 变更前的值
34
- */
35
- private readonly oldData;
36
- constructor(fields?: Record<string, FormModelField>);
37
- private watchData;
38
- append(fields: Record<string, FormModelField>): void;
39
- /**
40
- * 添加字段
41
- * @param field 字段
42
- * @param item 字段配置项
43
- */
44
- add(field: string, item: FormModelField): void;
45
- /**
46
- * 移除字段
47
- * @param field 字段
48
- */
49
- delete(field: string): void;
50
- /**
51
- * 监听值变更
52
- * @param cb 回调
53
- */
54
- onChange(cb: (field: string, val: any) => void): void;
55
- offChange(cb: (field: string, val: any) => void): void;
56
- validate(fields?: string | string[]): Promise<boolean>;
57
- private getValidateFields;
58
- /**
59
- * 重置数据
60
- * @param fields 需要重置的字段
61
- */
62
- resetData(keys?: string | string[]): void;
63
- /**
64
- * 设置值
65
- * @param formData 表单值
66
- * @param options 配置
67
- */
68
- setData(formData: Record<string, any>, config?: DataSettingConfig): void;
69
- clearValidate(): void;
70
- }
71
- //#endregion
72
- export { DynamicFormModel };
73
- //# sourceMappingURL=dynamic-form-model.d.ts.map