@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.
- package/dist/components/auto-complete/auto-complete.js +1 -0
- package/dist/components/auto-complete/auto-complete.js.map +1 -1
- package/dist/components/batch-edit/batch-edit-form.js +12 -5
- package/dist/components/batch-edit/batch-edit-form.js.map +1 -1
- package/dist/components/batch-edit/batch-edit.js +8 -3
- package/dist/components/batch-edit/batch-edit.js.map +1 -1
- package/dist/components/batch-edit/batch-edit.vue.d.ts +40 -35
- package/dist/components/batch-edit/di.js.map +1 -1
- package/dist/components/batch-edit/use-edit.js +41 -23
- package/dist/components/batch-edit/use-edit.js.map +1 -1
- package/dist/components/cascade/cascade.js +1 -0
- package/dist/components/cascade/cascade.js.map +1 -1
- package/dist/components/checkbox/checkbox-button.js +1 -0
- package/dist/components/checkbox/checkbox-button.js.map +1 -1
- package/dist/components/checkbox/checkbox.js +1 -0
- package/dist/components/checkbox/checkbox.js.map +1 -1
- package/dist/components/checkbox-group/checkbox-group.js +1 -0
- package/dist/components/checkbox-group/checkbox-group.js.map +1 -1
- package/dist/components/code-editor/code-editor.js +2 -1
- package/dist/components/code-editor/code-editor.js.map +1 -1
- package/dist/components/condition-editor/core/evaluator.js +3 -3
- package/dist/components/condition-editor/core/evaluator.js.map +1 -1
- package/dist/components/date-picker/date-picker.js +1 -0
- package/dist/components/date-picker/date-picker.js.map +1 -1
- package/dist/components/date-range-picker/date-range-picker.js +2 -0
- package/dist/components/date-range-picker/date-range-picker.js.map +1 -1
- package/dist/components/expression-editor/expression-editor.js +1 -0
- package/dist/components/expression-editor/expression-editor.js.map +1 -1
- package/dist/components/file-picker/file-picker.js +1 -0
- package/dist/components/file-picker/file-picker.js.map +1 -1
- package/dist/components/form/form.js.map +1 -1
- package/dist/components/form/form.vue.d.ts +11 -19
- package/dist/components/form/form.vue_vue_type_script_setup_true_lang.js +24 -26
- package/dist/components/form/form.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/form/index.d.ts +0 -3
- package/dist/components/form/use-form-fields.js +88 -0
- package/dist/components/form/use-form-fields.js.map +1 -0
- package/dist/components/form/use-node-interceptor.js +19 -30
- package/dist/components/form/use-node-interceptor.js.map +1 -1
- package/dist/components/form-item/form-item.js.map +1 -1
- package/dist/components/form-item/form-item.vue_vue_type_script_setup_true_lang.js +44 -18
- package/dist/components/form-item/form-item.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/form-item/helper.js +4 -1
- package/dist/components/form-item/helper.js.map +1 -1
- package/dist/components/form-item/validate.js +97 -0
- package/dist/components/form-item/validate.js.map +1 -0
- package/dist/components/group-input/group-input.js +1 -0
- package/dist/components/group-input/group-input.js.map +1 -1
- package/dist/components/index.d.ts +0 -3
- package/dist/components/index.js +0 -7
- package/dist/components/input/input.vue.d.ts +4 -4
- package/dist/components/input/input.vue_vue_type_script_setup_true_lang.js +1 -0
- package/dist/components/input/input.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/multi-select/multi-select.js +1 -0
- package/dist/components/multi-select/multi-select.js.map +1 -1
- package/dist/components/multi-tree-select/multi-tree-select.js +1 -0
- package/dist/components/multi-tree-select/multi-tree-select.js.map +1 -1
- package/dist/components/number-input/number-input.js +1 -0
- package/dist/components/number-input/number-input.js.map +1 -1
- package/dist/components/number-range-input/number-range-input.js +1 -0
- package/dist/components/number-range-input/number-range-input.js.map +1 -1
- package/dist/components/number-range-input/number-range-input.vue.d.ts +1 -1
- package/dist/components/palette/palette.js +1 -0
- package/dist/components/palette/palette.js.map +1 -1
- package/dist/components/password-input/password-input.js +1 -0
- package/dist/components/password-input/password-input.js.map +1 -1
- package/dist/components/radio/radio.js +1 -0
- package/dist/components/radio/radio.js.map +1 -1
- package/dist/components/radio-group/radio-group.js +1 -0
- package/dist/components/radio-group/radio-group.js.map +1 -1
- package/dist/components/rich-text-editor/rich-text-editor.js +3 -2
- package/dist/components/rich-text-editor/rich-text-editor.js.map +1 -1
- package/dist/components/rich-text-editor/toolbar.js +10 -7
- package/dist/components/rich-text-editor/toolbar.js.map +1 -1
- package/dist/components/select/select.js +6 -3
- package/dist/components/select/select.js.map +1 -1
- package/dist/components/slider/slider.js +15 -2
- package/dist/components/slider/slider.js.map +1 -1
- package/dist/components/switch/switch.js +1 -0
- package/dist/components/switch/switch.js.map +1 -1
- package/dist/components/tabs/tabs-horizontal.vue.d.ts +2 -2
- package/dist/components/tabs/tabs-vertical.vue.d.ts +2 -2
- package/dist/components/tabs/tabs.vue.d.ts +2 -2
- package/dist/components/textarea/textarea.js +1 -0
- package/dist/components/textarea/textarea.js.map +1 -1
- package/dist/components/tip/tip.vue.d.ts +3 -3
- package/dist/components/tree-select/tree-select.js +1 -0
- package/dist/components/tree-select/tree-select.js.map +1 -1
- package/dist/index.d.ts +3 -6
- package/dist/index.js +1 -4
- package/dist/types/batch-edit.d.ts +4 -5
- package/dist/types/form.d.ts +9 -48
- package/dist/types/index.d.ts +2 -2
- package/package.json +6 -6
- package/src/components/batch-edit/batch-edit-form.vue +20 -13
- package/src/components/batch-edit/batch-edit.vue +7 -8
- package/src/components/batch-edit/di.ts +1 -2
- package/src/components/batch-edit/use-edit.ts +58 -36
- package/src/components/date-range-picker/date-range-picker.vue +2 -0
- package/src/components/form/form.vue +22 -38
- package/src/components/form/index.ts +0 -6
- package/src/components/form/use-form-fields.ts +126 -0
- package/src/components/form/use-node-interceptor.ts +27 -56
- package/src/components/form-item/form-item.vue +69 -18
- package/src/components/form-item/helper.ts +5 -1
- package/src/components/form-item/validate.ts +131 -0
- package/src/components/rich-text-editor/rich-text-editor.vue +28 -25
- package/src/components/rich-text-editor/toolbar.vue +23 -19
- package/src/components/select/select.vue +6 -4
- package/src/components/slider/slider.vue +12 -2
- package/src/types/auto-complete.ts +1 -1
- package/src/types/batch-edit.ts +4 -5
- package/src/types/form.ts +9 -82
- package/src/types/radio-group.ts +1 -0
- package/src/types/radio.ts +1 -0
- package/src/types/tree-select.ts +1 -1
- package/dist/components/form/dynamic-form-model.d.ts +0 -73
- package/dist/components/form/dynamic-form-model.js +0 -184
- package/dist/components/form/dynamic-form-model.js.map +0 -1
- package/dist/components/form/form-model.d.ts +0 -73
- package/dist/components/form/form-model.js +0 -179
- package/dist/components/form/form-model.js.map +0 -1
- package/dist/components/form/helper.d.ts +0 -16
- package/dist/components/form/helper.js +0 -20
- package/dist/components/form/helper.js.map +0 -1
- package/src/components/form/__test__/form-model.test.ts +0 -190
- package/src/components/form/dynamic-form-model.ts +0 -258
- package/src/components/form/form-model.ts +0 -255
- 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
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
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.
|
|
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
|
-
|
|
89
|
-
|
|
87
|
+
editorState.read(
|
|
88
|
+
() => {
|
|
89
|
+
const selection = $getSelection()
|
|
90
|
+
if (!$isRangeSelection(selection)) return
|
|
90
91
|
|
|
91
|
-
|
|
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
|
-
|
|
241
|
+
let shouldRemoveLink = false
|
|
242
|
+
|
|
243
|
+
editorInstance.read(() => {
|
|
239
244
|
const selection = $getSelection()
|
|
240
245
|
if (!$isRangeSelection(selection)) return
|
|
241
246
|
|
|
242
|
-
const
|
|
243
|
-
|
|
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
|
-
|
|
213
|
-
const { valueKey } = props
|
|
214
|
-
currentIndex.value = options.findIndex((option) => o(option).get(valueKey) === modelValue)
|
|
212
|
+
const { valueKey, labelKey } = props
|
|
215
213
|
|
|
216
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
)
|
package/src/types/batch-edit.ts
CHANGED
|
@@ -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
|
|
22
|
+
export interface BatchEditProps extends TableProps {
|
|
24
23
|
/**
|
|
25
|
-
*
|
|
26
|
-
* @description
|
|
24
|
+
* 表单数据
|
|
25
|
+
* @description 与右侧 UForm 绑定的 reactive 对象
|
|
27
26
|
*/
|
|
28
|
-
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
|
|
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
|
|
5
|
+
export interface FormProps extends ComponentProps {
|
|
82
6
|
/**
|
|
83
7
|
* 自定义表单列数
|
|
84
8
|
* - 默认根据尺寸断点自动排列
|
|
85
9
|
*/
|
|
86
10
|
cols?: number
|
|
87
|
-
/**
|
|
88
|
-
|
|
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>
|
package/src/types/radio-group.ts
CHANGED
package/src/types/radio.ts
CHANGED
package/src/types/tree-select.ts
CHANGED
|
@@ -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
|