@tmagic/form 1.7.14-beta.1 → 1.7.14-beta.3
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/es/Form.vue_vue_type_script_setup_true_lang.js +2 -2
- package/dist/es/FormBox.vue_vue_type_script_setup_true_lang.js +5 -2
- package/dist/es/FormDialog.vue_vue_type_script_setup_true_lang.js +5 -2
- package/dist/es/FormDrawer.vue_vue_type_script_setup_true_lang.js +5 -2
- package/dist/es/containers/Container.vue_vue_type_script_setup_true_lang.js +2 -2
- package/dist/es/containers/table-group-list/useAdd.js +1 -1
- package/dist/es/fields/Cascader.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/fields/CheckboxGroup.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/fields/Date.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/fields/DateTime.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/fields/Daterange.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/fields/Display.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/fields/Select.vue_vue_type_script_setup_true_lang.js +27 -9
- package/dist/es/fields/Text.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/fields/Timerange.vue_vue_type_script_setup_true_lang.js +2 -2
- package/dist/es/index.js +3 -2
- package/dist/es/submitForm.js +87 -0
- package/dist/es/utils/form.js +2 -2
- package/dist/tmagic-form.umd.cjs +178 -66
- package/package.json +5 -5
- package/src/FormBox.vue +3 -1
- package/src/FormDialog.vue +4 -1
- package/src/FormDrawer.vue +4 -1
- package/src/containers/table-group-list/useAdd.ts +1 -1
- package/src/fields/Select.vue +43 -8
- package/src/index.ts +1 -0
- package/src/submitForm.ts +161 -0
- package/types/index.d.ts +269 -211
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Tencent is pleased to support the open source community by making TMagicEditor available.
|
|
3
|
+
*
|
|
4
|
+
* Copyright (C) 2025 Tencent. All rights reserved.
|
|
5
|
+
*
|
|
6
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
* you may not use this file except in compliance with the License.
|
|
8
|
+
* You may obtain a copy of the License at
|
|
9
|
+
*
|
|
10
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
*
|
|
12
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
* See the License for the specific language governing permissions and
|
|
16
|
+
* limitations under the License.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import { type AppContext, type Component, createApp, defineComponent, h, nextTick, ref, watch } from 'vue';
|
|
20
|
+
|
|
21
|
+
import Form from './Form.vue';
|
|
22
|
+
import type { FormConfig, FormState } from './schema';
|
|
23
|
+
|
|
24
|
+
// #region SubmitFormOptions
|
|
25
|
+
/**
|
|
26
|
+
* submitForm 函数参数(与 Form.vue 组件 props 对齐)
|
|
27
|
+
*/
|
|
28
|
+
export interface SubmitFormOptions {
|
|
29
|
+
/** 表单配置 */
|
|
30
|
+
config: FormConfig;
|
|
31
|
+
/** 表单初始值 */
|
|
32
|
+
initValues?: Record<string, any>;
|
|
33
|
+
/** 需对比的值(开启对比模式时传入) */
|
|
34
|
+
lastValues?: Record<string, any>;
|
|
35
|
+
/** 是否开启对比模式 */
|
|
36
|
+
isCompare?: boolean;
|
|
37
|
+
parentValues?: Record<string, any>;
|
|
38
|
+
labelWidth?: string;
|
|
39
|
+
disabled?: boolean;
|
|
40
|
+
height?: string;
|
|
41
|
+
stepActive?: string | number;
|
|
42
|
+
size?: 'small' | 'default' | 'large';
|
|
43
|
+
inline?: boolean;
|
|
44
|
+
labelPosition?: string;
|
|
45
|
+
keyProp?: string;
|
|
46
|
+
popperClass?: string;
|
|
47
|
+
preventSubmitDefault?: boolean;
|
|
48
|
+
extendState?: (_state: FormState) => Record<string, any> | Promise<Record<string, any>>;
|
|
49
|
+
/** 透传给 Form.submitForm 的参数:是否直接返回原始响应式 values */
|
|
50
|
+
native?: boolean;
|
|
51
|
+
/**
|
|
52
|
+
* 父级应用上下文,用于继承全局组件、指令、provide 等。
|
|
53
|
+
* 通常通过 `app._context` 或 `getCurrentInstance()?.appContext` 获取。
|
|
54
|
+
*/
|
|
55
|
+
appContext?: AppContext | null;
|
|
56
|
+
/** 等待表单初始化的最长时间(毫秒),超时将以错误 reject。默认 10000ms */
|
|
57
|
+
timeout?: number;
|
|
58
|
+
}
|
|
59
|
+
// #endregion SubmitFormOptions
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* 以命令式方式调用 Form.vue 完成一次表单校验/提交。
|
|
63
|
+
*
|
|
64
|
+
* 类似 ElMessage 的用法:传入 props(包含 `config`/`initValues` 等),函数内部会临时挂载
|
|
65
|
+
* 一个不可见的 Form 组件实例,等待初始化完成后调用其 `submitForm` 方法,
|
|
66
|
+
* 校验通过则 resolve 表单值,校验失败则 reject 错误信息,最后自动卸载实例。
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* ```ts
|
|
70
|
+
* import { submitForm } from '@tmagic/form';
|
|
71
|
+
*
|
|
72
|
+
* try {
|
|
73
|
+
* const values = await submitForm({
|
|
74
|
+
* config: [...],
|
|
75
|
+
* initValues: { name: 'foo' },
|
|
76
|
+
* });
|
|
77
|
+
* console.log(values);
|
|
78
|
+
* } catch (e) {
|
|
79
|
+
* console.error(e);
|
|
80
|
+
* }
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
export const submitForm = (options: SubmitFormOptions): Promise<any> => {
|
|
84
|
+
const { native, appContext, timeout = 10000, ...formProps } = options;
|
|
85
|
+
|
|
86
|
+
return new Promise((resolve, reject) => {
|
|
87
|
+
const container = document.createElement('div');
|
|
88
|
+
container.style.display = 'none';
|
|
89
|
+
document.body.appendChild(container);
|
|
90
|
+
|
|
91
|
+
let cleaned = false;
|
|
92
|
+
let timer: ReturnType<typeof setTimeout> | null = null;
|
|
93
|
+
|
|
94
|
+
const wrapperComponent = defineComponent({
|
|
95
|
+
name: 'MFormSubmitWrapper',
|
|
96
|
+
setup() {
|
|
97
|
+
const formRef = ref<any>(null);
|
|
98
|
+
|
|
99
|
+
const stop = watch(
|
|
100
|
+
() => formRef.value?.initialized,
|
|
101
|
+
async (initialized) => {
|
|
102
|
+
if (!initialized) return;
|
|
103
|
+
stop();
|
|
104
|
+
|
|
105
|
+
try {
|
|
106
|
+
// 等待子组件(FormItem 等)完成首次渲染,确保 validate 能拿到所有字段
|
|
107
|
+
await nextTick();
|
|
108
|
+
const result = await formRef.value.submitForm(native);
|
|
109
|
+
resolve(result);
|
|
110
|
+
} catch (err) {
|
|
111
|
+
reject(err);
|
|
112
|
+
} finally {
|
|
113
|
+
cleanup();
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
{ flush: 'post', immediate: true },
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
return () => h(Form as Component, { ...formProps, ref: formRef });
|
|
120
|
+
},
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
const app = createApp(wrapperComponent);
|
|
124
|
+
|
|
125
|
+
// 继承父级应用上下文(components / directives / provides / config 等)
|
|
126
|
+
if (appContext) {
|
|
127
|
+
Object.assign(app._context, appContext);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const cleanup = () => {
|
|
131
|
+
if (cleaned) return;
|
|
132
|
+
cleaned = true;
|
|
133
|
+
if (timer) {
|
|
134
|
+
clearTimeout(timer);
|
|
135
|
+
timer = null;
|
|
136
|
+
}
|
|
137
|
+
try {
|
|
138
|
+
app.unmount();
|
|
139
|
+
} catch {
|
|
140
|
+
// ignore
|
|
141
|
+
}
|
|
142
|
+
container.parentNode?.removeChild(container);
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
if (timeout > 0) {
|
|
146
|
+
timer = setTimeout(() => {
|
|
147
|
+
if (!cleaned) {
|
|
148
|
+
reject(new Error(`submitForm timeout after ${timeout}ms: form is not initialized.`));
|
|
149
|
+
cleanup();
|
|
150
|
+
}
|
|
151
|
+
}, timeout);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
try {
|
|
155
|
+
app.mount(container);
|
|
156
|
+
} catch (err) {
|
|
157
|
+
reject(err);
|
|
158
|
+
cleanup();
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
};
|