@tmagic/form 1.8.0-manmanyu.9 → 1.8.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/es/Form.vue_vue_type_script_setup_true_lang.js +88 -107
- package/dist/es/FormBox.vue_vue_type_script_setup_true_lang.js +21 -5
- package/dist/es/FormDialog.vue_vue_type_script_setup_true_lang.js +21 -5
- package/dist/es/FormDrawer.vue_vue_type_script_setup_true_lang.js +46 -12
- package/dist/es/containers/Col.vue_vue_type_script_setup_true_lang.js +6 -2
- package/dist/es/containers/Container.vue_vue_type_script_setup_true_lang.js +44 -47
- package/dist/es/containers/Fieldset.vue_vue_type_script_setup_true_lang.js +7 -1
- package/dist/es/containers/FlexLayout.vue_vue_type_script_setup_true_lang.js +5 -2
- package/dist/es/containers/FormLabel.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/containers/GroupList.vue_vue_type_script_setup_true_lang.js +59 -22
- package/dist/es/containers/GroupListItem.vue_vue_type_script_setup_true_lang.js +118 -100
- package/dist/es/containers/Panel.vue_vue_type_script_setup_true_lang.js +8 -3
- package/dist/es/containers/Row.vue_vue_type_script_setup_true_lang.js +4 -1
- package/dist/es/containers/Step.vue_vue_type_script_setup_true_lang.js +5 -2
- package/dist/es/containers/Tabs.vue_vue_type_script_setup_true_lang.js +8 -1
- package/dist/es/containers/table/ActionsColumn.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/containers/table/SortColumn.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/containers/table/Table.vue_vue_type_script_setup_true_lang.js +14 -10
- package/dist/es/containers/table/useTableColumns.js +10 -15
- package/dist/es/containers/table-group-list/TableGroupList.vue_vue_type_script_setup_true_lang.js +72 -79
- package/dist/es/containers/table-group-list/useAdd.js +26 -16
- package/dist/es/containers/table-group-list/useScrollLastItemIntoView.js +72 -0
- package/dist/es/fields/Cascader.vue_vue_type_script_setup_true_lang.js +2 -2
- package/dist/es/fields/Checkbox.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/fields/CheckboxGroup/Index.js +5 -0
- package/dist/es/fields/{CheckboxGroup.vue_vue_type_script_setup_true_lang.js → CheckboxGroup/Index.vue_vue_type_script_setup_true_lang.js} +6 -7
- package/dist/es/fields/CheckboxGroup/effect.js +8 -0
- package/dist/es/fields/ColorPicker.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/fields/Date/Index.js +5 -0
- package/dist/es/fields/{Date.vue_vue_type_script_setup_true_lang.js → Date/Index.vue_vue_type_script_setup_true_lang.js} +5 -7
- package/dist/es/fields/Date/effect.js +10 -0
- package/dist/es/fields/DateTime/Index.js +5 -0
- package/dist/es/fields/{DateTime.vue_vue_type_script_setup_true_lang.js → DateTime/Index.vue_vue_type_script_setup_true_lang.js} +5 -9
- package/dist/es/fields/DateTime/effect.js +15 -0
- package/dist/es/fields/Daterange.vue_vue_type_script_setup_true_lang.js +2 -2
- package/dist/es/fields/Display/Index.js +5 -0
- package/dist/es/fields/{Display.vue_vue_type_script_setup_true_lang.js → Display/Index.vue_vue_type_script_setup_true_lang.js} +6 -7
- package/dist/es/fields/Display/effect.js +8 -0
- package/dist/es/fields/DynamicField/Index.js +5 -0
- package/dist/es/fields/{DynamicField.vue_vue_type_script_setup_true_lang.js → DynamicField/Index.vue_vue_type_script_setup_true_lang.js} +11 -15
- package/dist/es/fields/DynamicField/effect.js +40 -0
- package/dist/es/fields/Hidden.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/fields/Link.vue_vue_type_script_setup_true_lang.js +4 -4
- package/dist/es/fields/Number.vue_vue_type_script_setup_true_lang.js +4 -2
- package/dist/es/fields/NumberRange/Index.js +5 -0
- package/dist/es/fields/{NumberRange.vue_vue_type_script_setup_true_lang.js → NumberRange/Index.vue_vue_type_script_setup_true_lang.js} +5 -6
- package/dist/es/fields/NumberRange/effect.js +8 -0
- package/dist/es/fields/RadioGroup.vue_vue_type_script_setup_true_lang.js +5 -2
- package/dist/es/fields/Select.vue_vue_type_script_setup_true_lang.js +14 -6
- package/dist/es/fields/Switch.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/fields/Text.vue_vue_type_script_setup_true_lang.js +13 -10
- package/dist/es/fields/Textarea.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/fields/Time.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/fields/Timerange.vue_vue_type_script_setup_true_lang.js +3 -3
- package/dist/es/headless.js +13 -0
- package/dist/es/index.js +19 -12
- package/dist/es/plugin.js +57 -39
- package/dist/es/schema.js +11 -2
- package/dist/es/style.css +123 -3
- package/dist/es/submitForm.js +270 -72
- package/dist/es/utils/builtInFields.js +49 -0
- package/dist/es/utils/collectFields.js +407 -0
- package/dist/es/utils/config.js +4 -8
- package/dist/es/utils/fieldInnerConfig.js +42 -0
- package/dist/es/utils/fieldValueEffects.js +80 -0
- package/dist/es/utils/form.js +154 -19
- package/dist/es/utils/formStateProxy.js +111 -0
- package/dist/es/utils/registerField.js +158 -0
- package/dist/es/utils/submitHeadless.js +54 -0
- package/dist/es/utils/tableGroupList.js +104 -0
- package/dist/es/utils/typeMatch.js +532 -0
- package/dist/es/utils/validateError.js +57 -0
- package/dist/es/utils/validateValues.js +115 -0
- package/dist/style.css +123 -3
- package/dist/themes/magic-admin.css +576 -14
- package/dist/tmagic-form-headless.umd.cjs +4515 -0
- package/dist/tmagic-form.umd.cjs +3444 -983
- package/package.json +16 -10
- package/src/Form.vue +113 -129
- package/src/FormBox.vue +16 -4
- package/src/FormDialog.vue +16 -5
- package/src/FormDrawer.vue +41 -13
- package/src/containers/Col.vue +3 -0
- package/src/containers/Container.vue +40 -45
- package/src/containers/Fieldset.vue +5 -0
- package/src/containers/FlexLayout.vue +2 -0
- package/src/containers/GroupList.vue +64 -13
- package/src/containers/GroupListItem.vue +88 -81
- package/src/containers/Panel.vue +3 -0
- package/src/containers/Row.vue +2 -0
- package/src/containers/Step.vue +2 -0
- package/src/containers/Tabs.vue +13 -0
- package/src/containers/table/ActionsColumn.vue +1 -1
- package/src/containers/table/Table.vue +5 -3
- package/src/containers/table/usePagination.ts +1 -1
- package/src/containers/table/useSortable.ts +1 -1
- package/src/containers/table/useTableColumns.ts +15 -22
- package/src/containers/table-group-list/TableGroupList.vue +46 -72
- package/src/containers/table-group-list/useAdd.ts +40 -25
- package/src/containers/table-group-list/useScrollLastItemIntoView.ts +94 -0
- package/src/fields/{CheckboxGroup.vue → CheckboxGroup/Index.vue} +3 -8
- package/src/fields/CheckboxGroup/effect.ts +27 -0
- package/src/fields/{Date.vue → Date/Index.vue} +2 -5
- package/src/fields/Date/effect.ts +29 -0
- package/src/fields/{DateTime.vue → DateTime/Index.vue} +2 -16
- package/src/fields/DateTime/effect.ts +36 -0
- package/src/fields/{Display.vue → Display/Index.vue} +3 -7
- package/src/fields/Display/effect.ts +28 -0
- package/src/fields/{DynamicField.vue → DynamicField/Index.vue} +11 -11
- package/src/fields/DynamicField/effect.ts +74 -0
- package/src/fields/Link.vue +3 -4
- package/src/fields/Number.vue +2 -1
- package/src/fields/{NumberRange.vue → NumberRange/Index.vue} +2 -6
- package/src/fields/NumberRange/effect.ts +27 -0
- package/src/fields/RadioGroup.vue +13 -1
- package/src/fields/Select.vue +13 -4
- package/src/headless.ts +78 -0
- package/src/index.ts +46 -9
- package/src/plugin.ts +68 -37
- package/src/schema.ts +13 -2
- package/src/submitForm.ts +410 -131
- package/src/theme/fieldset.scss +1 -0
- package/src/theme/form-box.scss +5 -0
- package/src/theme/form-dialog.scss +1 -1
- package/src/theme/group-list.scss +143 -2
- package/src/theme/table.scss +11 -1
- package/src/theme/themes/magic-admin/index.scss +27 -16
- package/src/utils/builtInFields.ts +69 -0
- package/src/utils/collectFields.ts +561 -0
- package/src/utils/config.ts +7 -15
- package/src/utils/fieldInnerConfig.ts +127 -0
- package/src/utils/fieldValueEffects.ts +140 -0
- package/src/utils/form.ts +230 -30
- package/src/utils/formStateProxy.ts +149 -0
- package/src/utils/registerField.ts +308 -0
- package/src/utils/submitHeadless.ts +206 -0
- package/src/utils/tableGroupList.ts +147 -0
- package/src/utils/typeMatch.ts +948 -0
- package/src/utils/validateError.ts +92 -0
- package/src/utils/validateValues.ts +177 -0
- package/types/headless.d.ts +682 -0
- package/types/index.d.ts +900 -180
- package/dist/es/_virtual/_rolldown/runtime.js +0 -27
- package/dist/es/fields/CheckboxGroup.js +0 -5
- package/dist/es/fields/Date.js +0 -5
- package/dist/es/fields/DateTime.js +0 -5
- package/dist/es/fields/Display.js +0 -5
- package/dist/es/fields/DynamicField.js +0 -5
- package/dist/es/fields/NumberRange.js +0 -5
|
@@ -14,9 +14,8 @@
|
|
|
14
14
|
<script lang="ts" setup>
|
|
15
15
|
import { TMagicDatePicker } from '@tmagic/design';
|
|
16
16
|
|
|
17
|
-
import type { DateConfig, FieldProps } from '
|
|
18
|
-
import {
|
|
19
|
-
import { useAddField } from '../utils/useAddField';
|
|
17
|
+
import type { DateConfig, FieldProps } from '@form/schema';
|
|
18
|
+
import { useAddField } from '@form/utils/useAddField';
|
|
20
19
|
|
|
21
20
|
defineOptions({
|
|
22
21
|
name: 'MFormDate',
|
|
@@ -30,8 +29,6 @@ const emit = defineEmits<{
|
|
|
30
29
|
|
|
31
30
|
useAddField(props.prop);
|
|
32
31
|
|
|
33
|
-
props.model[props.name] = datetimeFormatter(props.model[props.name], '', props.config.valueFormat || 'YYYY/MM/DD');
|
|
34
|
-
|
|
35
32
|
const changeHandler = (v: string) => {
|
|
36
33
|
emit('change', v);
|
|
37
34
|
};
|
|
@@ -0,0 +1,29 @@
|
|
|
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 { DateConfig } from '@form/schema';
|
|
20
|
+
import type { FieldMountValueEffect } from '@form/utils/fieldValueEffects';
|
|
21
|
+
import { datetimeFormatter } from '@form/utils/form';
|
|
22
|
+
|
|
23
|
+
/** 按 `valueFormat` 归一化日期值。 */
|
|
24
|
+
export const effect: FieldMountValueEffect = ({ config, model }) => {
|
|
25
|
+
if (!model) return;
|
|
26
|
+
|
|
27
|
+
const { name, valueFormat } = config as DateConfig & { name: string };
|
|
28
|
+
model[name] = datetimeFormatter(model[name], '', valueFormat || 'YYYY/MM/DD');
|
|
29
|
+
};
|
|
@@ -16,9 +16,8 @@
|
|
|
16
16
|
<script lang="ts" setup>
|
|
17
17
|
import { TMagicDatePicker } from '@tmagic/design';
|
|
18
18
|
|
|
19
|
-
import type { DateTimeConfig, FieldProps } from '
|
|
20
|
-
import {
|
|
21
|
-
import { useAddField } from '../utils/useAddField';
|
|
19
|
+
import type { DateTimeConfig, FieldProps } from '@form/schema';
|
|
20
|
+
import { useAddField } from '@form/utils/useAddField';
|
|
22
21
|
|
|
23
22
|
defineOptions({
|
|
24
23
|
name: 'MFormDateTime',
|
|
@@ -32,19 +31,6 @@ const emit = defineEmits<{
|
|
|
32
31
|
|
|
33
32
|
useAddField(props.prop);
|
|
34
33
|
|
|
35
|
-
const value = props.model?.[props.name]?.toString();
|
|
36
|
-
if (props.model) {
|
|
37
|
-
if (!value || value === 'Invalid Date') {
|
|
38
|
-
props.model[props.name] = '';
|
|
39
|
-
} else {
|
|
40
|
-
props.model[props.name] = datetimeFormatter(
|
|
41
|
-
props.model[props.name],
|
|
42
|
-
'',
|
|
43
|
-
props.config.valueFormat || 'YYYY/MM/DD HH:mm:ss',
|
|
44
|
-
);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
34
|
const changeHandler = (v: string) => {
|
|
49
35
|
emit('change', v);
|
|
50
36
|
};
|
|
@@ -0,0 +1,36 @@
|
|
|
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 { DateTimeConfig } from '@form/schema';
|
|
20
|
+
import type { FieldMountValueEffect } from '@form/utils/fieldValueEffects';
|
|
21
|
+
import { datetimeFormatter } from '@form/utils/form';
|
|
22
|
+
|
|
23
|
+
/** 按 `valueFormat` 归一化日期时间值,空值与非法值统一为空字符串。 */
|
|
24
|
+
export const effect: FieldMountValueEffect = ({ config, model }) => {
|
|
25
|
+
if (!model) return;
|
|
26
|
+
|
|
27
|
+
const { name, valueFormat } = config as DateTimeConfig & { name: string };
|
|
28
|
+
const value = model[name]?.toString();
|
|
29
|
+
|
|
30
|
+
if (!value || value === 'Invalid Date') {
|
|
31
|
+
model[name] = '';
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
model[name] = datetimeFormatter(model[name], '', valueFormat || 'YYYY/MM/DD HH:mm:ss');
|
|
36
|
+
};
|
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
<script setup lang="ts">
|
|
6
6
|
import { computed, inject } from 'vue';
|
|
7
7
|
|
|
8
|
-
import type { DisplayConfig, FieldProps, FormState } from '
|
|
9
|
-
import { filterFunction } from '
|
|
10
|
-
import { useAddField } from '
|
|
8
|
+
import type { DisplayConfig, FieldProps, FormState } from '@form/schema';
|
|
9
|
+
import { filterFunction } from '@form/utils/form';
|
|
10
|
+
import { useAddField } from '@form/utils/useAddField';
|
|
11
11
|
|
|
12
12
|
defineOptions({
|
|
13
13
|
name: 'MFormDisplay',
|
|
@@ -17,10 +17,6 @@ const props = defineProps<FieldProps<DisplayConfig>>();
|
|
|
17
17
|
|
|
18
18
|
const mForm = inject<FormState | undefined>('mForm');
|
|
19
19
|
|
|
20
|
-
if (props.config.initValue && props.model) {
|
|
21
|
-
props.model[props.name] = props.config.initValue;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
20
|
const text = computed(() => {
|
|
25
21
|
if (props.config.displayText) {
|
|
26
22
|
return filterFunction<string>(mForm, props.config.displayText, props);
|
|
@@ -0,0 +1,28 @@
|
|
|
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 { DisplayConfig } from '@form/schema';
|
|
20
|
+
import type { FieldMountValueEffect } from '@form/utils/fieldValueEffects';
|
|
21
|
+
|
|
22
|
+
/** 把 `initValue` 写入 model。 */
|
|
23
|
+
export const effect: FieldMountValueEffect = ({ config, model }) => {
|
|
24
|
+
const { initValue, name } = config as DisplayConfig & { name: string };
|
|
25
|
+
if (initValue && model) {
|
|
26
|
+
model[name] = initValue;
|
|
27
|
+
}
|
|
28
|
+
};
|
|
@@ -27,9 +27,11 @@ import { onBeforeUnmount, reactive, watch } from 'vue';
|
|
|
27
27
|
|
|
28
28
|
import { TMagicForm, TMagicFormItem, TMagicInput } from '@tmagic/design';
|
|
29
29
|
|
|
30
|
-
import type { DynamicFieldConfig, FieldProps } from '
|
|
31
|
-
import { getConfig } from '
|
|
32
|
-
import { useAddField } from '
|
|
30
|
+
import type { DynamicFieldConfig, FieldProps } from '@form/schema';
|
|
31
|
+
import { getConfig } from '@form/utils/config';
|
|
32
|
+
import { useAddField } from '@form/utils/useAddField';
|
|
33
|
+
|
|
34
|
+
import { eachDynamicField } from './effect';
|
|
33
35
|
|
|
34
36
|
defineOptions({
|
|
35
37
|
name: 'MFormDynamicField',
|
|
@@ -54,15 +56,13 @@ const changeFieldMap = async () => {
|
|
|
54
56
|
const fields = await props.config.returnFields(props.config, props.model, request);
|
|
55
57
|
fieldMap.value = {};
|
|
56
58
|
fieldLabelMap.value = {};
|
|
57
|
-
fields.
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
oldVal = v.defaultValue;
|
|
62
|
-
emit('change', oldVal, { modifyKey: v.name });
|
|
59
|
+
eachDynamicField(fields, props.model, (field, value, isDefaultApplied) => {
|
|
60
|
+
// 取了 defaultValue 的字段需要写回表单值
|
|
61
|
+
if (isDefaultApplied) {
|
|
62
|
+
emit('change', value, { modifyKey: field.name });
|
|
63
63
|
}
|
|
64
|
-
fieldMap.value[
|
|
65
|
-
fieldLabelMap.value[
|
|
64
|
+
fieldMap.value[field.name] = value;
|
|
65
|
+
fieldLabelMap.value[field.name] = field.label || '';
|
|
66
66
|
});
|
|
67
67
|
};
|
|
68
68
|
|
|
@@ -0,0 +1,74 @@
|
|
|
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 { setValueByKeyPath } from '@tmagic/utils';
|
|
20
|
+
|
|
21
|
+
import type { DynamicFieldConfig, FormValue } from '@form/schema';
|
|
22
|
+
import { getConfig } from '@form/utils/config';
|
|
23
|
+
import type { FieldMountValueEffect } from '@form/utils/fieldValueEffects';
|
|
24
|
+
|
|
25
|
+
/** `dynamic-field` 的 `returnFields` 返回的单个字段描述 */
|
|
26
|
+
type DynamicFieldItem = ReturnType<DynamicFieldConfig['returnFields']>[number];
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* 遍历动态字段列表,按「原值为空且声明了 defaultValue 则取默认值」求出每个字段当前的值。
|
|
30
|
+
*
|
|
31
|
+
* `isDefaultApplied` 为真表示该值来自 `defaultValue`,需要写回表单值
|
|
32
|
+
* (组件通过 emit change 写回,初始化写入直接写 `values`)。
|
|
33
|
+
*/
|
|
34
|
+
export const eachDynamicField = (
|
|
35
|
+
fields: DynamicFieldItem[],
|
|
36
|
+
model: FormValue | undefined,
|
|
37
|
+
onField: (_field: DynamicFieldItem, _value: any, _isDefaultApplied: boolean) => void,
|
|
38
|
+
): void => {
|
|
39
|
+
for (const field of fields) {
|
|
40
|
+
if (typeof field !== 'object' || field?.name === undefined) continue;
|
|
41
|
+
|
|
42
|
+
let value = model?.[field.name] || '';
|
|
43
|
+
let isDefaultApplied = false;
|
|
44
|
+
|
|
45
|
+
if (!value && field.defaultValue !== undefined) {
|
|
46
|
+
value = field.defaultValue;
|
|
47
|
+
isDefaultApplied = true;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
onField(field, value, isDefaultApplied);
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* 同步 `returnFields` 的 defaultValue 按 prop 写入值根对象。
|
|
56
|
+
*
|
|
57
|
+
* 该组件读取的是同级 model,但写入走 Container 的 modifyKey 分支,落在 `${prop}.${key}`,
|
|
58
|
+
* 这里保持与渲染一致(含这层不对称),避免两条链路产出不同的值。
|
|
59
|
+
* 异步 returnFields 由组件挂载后的 watch 负责,此处不等待。
|
|
60
|
+
*/
|
|
61
|
+
export const effect: FieldMountValueEffect = ({ config, model, prop, values }) => {
|
|
62
|
+
const { returnFields, dynamicKey } = config as DynamicFieldConfig;
|
|
63
|
+
if (typeof returnFields !== 'function' || !model) return;
|
|
64
|
+
if (model[dynamicKey] === '') return;
|
|
65
|
+
|
|
66
|
+
const result = returnFields(config as DynamicFieldConfig, model, getConfig<Function>('request'));
|
|
67
|
+
if (!result || typeof (result as any).then === 'function' || !Array.isArray(result)) return;
|
|
68
|
+
|
|
69
|
+
eachDynamicField(result, model, (field, value, isDefaultApplied) => {
|
|
70
|
+
if (isDefaultApplied) {
|
|
71
|
+
setValueByKeyPath(`${prop}.${field.name}`, value, values || model);
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
};
|
package/src/fields/Link.vue
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<a
|
|
3
3
|
target="_blank"
|
|
4
4
|
:href="href"
|
|
5
|
-
v-if="
|
|
5
|
+
v-if="isGlobalFlat && config.href && !disabled"
|
|
6
6
|
class="magic-admin-link"
|
|
7
7
|
:style="config.css || {}"
|
|
8
8
|
>
|
|
@@ -31,10 +31,11 @@
|
|
|
31
31
|
import { computed, inject, readonly, ref } from 'vue';
|
|
32
32
|
import { Notebook } from '@element-plus/icons-vue';
|
|
33
33
|
|
|
34
|
-
import { TMagicButton, TMagicIcon
|
|
34
|
+
import { TMagicButton, TMagicIcon } from '@tmagic/design';
|
|
35
35
|
|
|
36
36
|
import FormDialog from '../FormDialog.vue';
|
|
37
37
|
import type { FieldProps, FormState, LinkConfig } from '../schema';
|
|
38
|
+
import { isGlobalFlat } from '../utils/config';
|
|
38
39
|
import { useAddField } from '../utils/useAddField';
|
|
39
40
|
|
|
40
41
|
defineOptions({
|
|
@@ -45,8 +46,6 @@ const props = defineProps<FieldProps<LinkConfig> & { theme?: string }>();
|
|
|
45
46
|
|
|
46
47
|
const emit = defineEmits(['change']);
|
|
47
48
|
|
|
48
|
-
const displayTheme = useTheme(props);
|
|
49
|
-
|
|
50
49
|
useAddField(props.prop);
|
|
51
50
|
|
|
52
51
|
const formValue = ref({});
|
package/src/fields/Number.vue
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
v-if="model"
|
|
4
4
|
v-model="value"
|
|
5
5
|
clearable
|
|
6
|
-
controls-position="right"
|
|
6
|
+
:controls-position="isGlobalFlat ? '' : 'right'"
|
|
7
7
|
:size="size"
|
|
8
8
|
:max="config.max"
|
|
9
9
|
:min="config.min"
|
|
@@ -21,6 +21,7 @@ import { inject, ref, watch } from 'vue';
|
|
|
21
21
|
import { TMagicInputNumber } from '@tmagic/design';
|
|
22
22
|
|
|
23
23
|
import type { FieldProps, FormState, NumberConfig } from '../schema';
|
|
24
|
+
import { isGlobalFlat } from '../utils/config';
|
|
24
25
|
import { useAddField } from '../utils/useAddField';
|
|
25
26
|
|
|
26
27
|
defineOptions({
|
|
@@ -23,8 +23,8 @@ import { ref, watch } from 'vue';
|
|
|
23
23
|
|
|
24
24
|
import { TMagicInput } from '@tmagic/design';
|
|
25
25
|
|
|
26
|
-
import type { FieldProps, NumberRangeConfig } from '
|
|
27
|
-
import { useAddField } from '
|
|
26
|
+
import type { FieldProps, NumberRangeConfig } from '@form/schema';
|
|
27
|
+
import { useAddField } from '@form/utils/useAddField';
|
|
28
28
|
|
|
29
29
|
defineOptions({
|
|
30
30
|
name: 'MFormNumberRange',
|
|
@@ -53,10 +53,6 @@ watch(
|
|
|
53
53
|
|
|
54
54
|
useAddField(props.prop);
|
|
55
55
|
|
|
56
|
-
if (!Array.isArray(props.model[props.name])) {
|
|
57
|
-
props.model[props.name] = [];
|
|
58
|
-
}
|
|
59
|
-
|
|
60
56
|
const minChangeHandler = (v: string) => {
|
|
61
57
|
emit('change', [Number(v), props.model[props.name][1]]);
|
|
62
58
|
};
|
|
@@ -0,0 +1,27 @@
|
|
|
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 { FieldMountValueEffect } from '@form/utils/fieldValueEffects';
|
|
20
|
+
|
|
21
|
+
/** 值不是数组时修正为空数组。 */
|
|
22
|
+
export const effect: FieldMountValueEffect = ({ config, model }) => {
|
|
23
|
+
const { name } = config as any;
|
|
24
|
+
if (model && !Array.isArray(model[name])) {
|
|
25
|
+
model[name] = [];
|
|
26
|
+
}
|
|
27
|
+
};
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<TMagicRadioGroup
|
|
2
|
+
<TMagicRadioGroup
|
|
3
|
+
v-if="model"
|
|
4
|
+
:model-value="model[name]"
|
|
5
|
+
:size="size"
|
|
6
|
+
:disabled="disabled"
|
|
7
|
+
class="icon-{{ iconSize }}"
|
|
8
|
+
>
|
|
3
9
|
<component
|
|
4
10
|
v-for="option in config.options"
|
|
5
11
|
:is="itemComponent"
|
|
@@ -41,6 +47,9 @@ const itemComponent = computed(() => (props.config.childType === 'button' ? TMag
|
|
|
41
47
|
const emit = defineEmits(['change']);
|
|
42
48
|
|
|
43
49
|
const clickHandler = (item: string | number | boolean) => {
|
|
50
|
+
if (props.disabled) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
44
53
|
// 再次点击取消选中
|
|
45
54
|
emit('change', props.model[props.name] === item ? '' : item);
|
|
46
55
|
};
|
|
@@ -49,6 +58,9 @@ useAddField(props.prop);
|
|
|
49
58
|
|
|
50
59
|
// 这里换了设计稿里的图标,所以需要调整一下图标大小
|
|
51
60
|
const iconSize = computed(() => {
|
|
61
|
+
if (props.config.iconSize) {
|
|
62
|
+
return props.config.iconSize;
|
|
63
|
+
}
|
|
52
64
|
if (props.size === 'small') {
|
|
53
65
|
return '14';
|
|
54
66
|
}
|
package/src/fields/Select.vue
CHANGED
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
<component
|
|
58
58
|
v-for="option in options as SelectOption[]"
|
|
59
59
|
class="tmagic-design-option"
|
|
60
|
-
:key="config.valueKey ? option.value[config.valueKey] : option.value"
|
|
60
|
+
:key="config.valueKey ? option.value?.[config.valueKey] : option.value"
|
|
61
61
|
:is="optionComponent?.component || 'el-option'"
|
|
62
62
|
v-bind="
|
|
63
63
|
optionComponent?.props({
|
|
@@ -372,7 +372,12 @@ const getInitOption = async () => {
|
|
|
372
372
|
});
|
|
373
373
|
}
|
|
374
374
|
|
|
375
|
-
let initData
|
|
375
|
+
let initData: any;
|
|
376
|
+
try {
|
|
377
|
+
initData = getValueByKeyPath(initRoot || root, res);
|
|
378
|
+
} catch {
|
|
379
|
+
// 响应中不存在 initRoot/root 路径时按无数据处理
|
|
380
|
+
}
|
|
376
381
|
if (initData) {
|
|
377
382
|
if (!Array.isArray(initData)) {
|
|
378
383
|
initData = [initData];
|
|
@@ -417,8 +422,12 @@ if (typeof props.config.options === 'function') {
|
|
|
417
422
|
const v = props.model[props.name];
|
|
418
423
|
if (Array.isArray(v) ? !v.length : typeof v === 'undefined') return;
|
|
419
424
|
if (typeof v === 'undefined' || hasOption(v)) return;
|
|
420
|
-
|
|
421
|
-
|
|
425
|
+
try {
|
|
426
|
+
const data = await getInitOption();
|
|
427
|
+
setOptions(data);
|
|
428
|
+
} catch {
|
|
429
|
+
setOptions([]);
|
|
430
|
+
}
|
|
422
431
|
};
|
|
423
432
|
|
|
424
433
|
watch(
|
package/src/headless.ts
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
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
|
+
/**
|
|
20
|
+
* @fileoverview `@tmagic/form/headless`:无渲染校验入口,不加载 Vue 组件与样式。
|
|
21
|
+
*
|
|
22
|
+
* 纯 Node / CI 请从这里引入 `submitForm` / `validateForm` / `registerField`。
|
|
23
|
+
* `dialog: true` 需要 DOM,请改从 `@tmagic/form` 引入。
|
|
24
|
+
*
|
|
25
|
+
* ESM 下本入口与 `@tmagic/form` 共用同一批模块文件,字段注册表是同一份。
|
|
26
|
+
* CJS(`require`)下两者是各自独立的 UMD bundle,注册表不共享,同一进程里不要
|
|
27
|
+
* 同时 `require('@tmagic/form')` 和 `require('@tmagic/form/headless')`。
|
|
28
|
+
*
|
|
29
|
+
* @module @tmagic/form/headless
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
export * from './schema';
|
|
33
|
+
export * from './utils/form';
|
|
34
|
+
export { builtInFields } from './utils/builtInFields';
|
|
35
|
+
|
|
36
|
+
export {
|
|
37
|
+
clearFields,
|
|
38
|
+
getField as getFormField,
|
|
39
|
+
mergeFieldOptions,
|
|
40
|
+
registerBuiltInFields,
|
|
41
|
+
registerField,
|
|
42
|
+
registerFields,
|
|
43
|
+
unregisterField,
|
|
44
|
+
} from './utils/registerField';
|
|
45
|
+
export type { FieldOptions, HeadlessFieldOptions } from './utils/registerField';
|
|
46
|
+
|
|
47
|
+
export type { FieldInnerConfig, FieldInnerConfigContext, FieldInnerConfigResult } from './utils/fieldInnerConfig';
|
|
48
|
+
|
|
49
|
+
export { isLeafFieldType } from './utils/fieldValueEffects';
|
|
50
|
+
export type { FieldMountValueEffect, FieldMountValueEffectContext } from './utils/fieldValueEffects';
|
|
51
|
+
|
|
52
|
+
export {
|
|
53
|
+
applyMountValueEffects,
|
|
54
|
+
collectValidatableFields,
|
|
55
|
+
FieldInnerConfigError,
|
|
56
|
+
isFieldInnerConfigError,
|
|
57
|
+
} from './utils/collectFields';
|
|
58
|
+
export type { CollectedField } from './utils/collectFields';
|
|
59
|
+
|
|
60
|
+
export { createHeadlessFormState, validateValues } from './utils/validateValues';
|
|
61
|
+
export type { HeadlessFormStateOptions, ValidateValuesOptions, ValidateValuesResult } from './utils/validateValues';
|
|
62
|
+
|
|
63
|
+
export { formatValidateError, getTextByName } from './utils/validateError';
|
|
64
|
+
|
|
65
|
+
export {
|
|
66
|
+
clearTypeMatchRules,
|
|
67
|
+
deleteTypeMatchRule,
|
|
68
|
+
getTypeMatchRule,
|
|
69
|
+
MAX_SUGGESTION_OPTIONS,
|
|
70
|
+
optionSuggestion,
|
|
71
|
+
stringifyExampleValue,
|
|
72
|
+
validateTypeMatch,
|
|
73
|
+
} from './utils/typeMatch';
|
|
74
|
+
|
|
75
|
+
export type { TypeMatchValidateContext, TypeMatchValidator } from './utils/typeMatch';
|
|
76
|
+
|
|
77
|
+
export { submitForm, validateForm } from './utils/submitHeadless';
|
|
78
|
+
export type { SubmitFormOptions, SubmitFormResult, ValidateFormOptions } from './utils/submitHeadless';
|
package/src/index.ts
CHANGED
|
@@ -38,30 +38,67 @@ export { default as MGroupList } from './containers/table-group-list/TableGroupL
|
|
|
38
38
|
export { default as MTableGroupList } from './containers/table-group-list/TableGroupList.vue';
|
|
39
39
|
export { default as MText } from './fields/Text.vue';
|
|
40
40
|
export { default as MNumber } from './fields/Number.vue';
|
|
41
|
-
export { default as MNumberRange } from './fields/NumberRange.vue';
|
|
41
|
+
export { default as MNumberRange } from './fields/NumberRange/Index.vue';
|
|
42
42
|
export { default as MTextarea } from './fields/Textarea.vue';
|
|
43
43
|
export { default as MHidden } from './fields/Hidden.vue';
|
|
44
|
-
export { default as MDate } from './fields/Date.vue';
|
|
45
|
-
export { default as MDateTime } from './fields/DateTime.vue';
|
|
44
|
+
export { default as MDate } from './fields/Date/Index.vue';
|
|
45
|
+
export { default as MDateTime } from './fields/DateTime/Index.vue';
|
|
46
46
|
export { default as MTime } from './fields/Time.vue';
|
|
47
47
|
export { default as MCheckbox } from './fields/Checkbox.vue';
|
|
48
48
|
export { default as MSwitch } from './fields/Switch.vue';
|
|
49
49
|
export { default as MDaterange } from './fields/Daterange.vue';
|
|
50
50
|
export { default as MTimerange } from './fields/Timerange.vue';
|
|
51
51
|
export { default as MColorPicker } from './fields/ColorPicker.vue';
|
|
52
|
-
export { default as MCheckboxGroup } from './fields/CheckboxGroup.vue';
|
|
52
|
+
export { default as MCheckboxGroup } from './fields/CheckboxGroup/Index.vue';
|
|
53
53
|
export { default as MRadioGroup } from './fields/RadioGroup.vue';
|
|
54
|
-
export { default as MDisplay } from './fields/Display.vue';
|
|
54
|
+
export { default as MDisplay } from './fields/Display/Index.vue';
|
|
55
55
|
export { default as MLink } from './fields/Link.vue';
|
|
56
56
|
export { default as MSelect } from './fields/Select.vue';
|
|
57
57
|
export { default as MCascader } from './fields/Cascader.vue';
|
|
58
|
-
export { default as MDynamicField } from './fields/DynamicField.vue';
|
|
58
|
+
export { default as MDynamicField } from './fields/DynamicField/Index.vue';
|
|
59
|
+
|
|
60
|
+
export { builtInFields } from './utils/builtInFields';
|
|
59
61
|
|
|
60
62
|
export {
|
|
61
|
-
|
|
63
|
+
clearFields,
|
|
62
64
|
getField as getFormField,
|
|
63
|
-
|
|
64
|
-
|
|
65
|
+
mergeFieldOptions,
|
|
66
|
+
registerBuiltInFields,
|
|
67
|
+
registerField,
|
|
68
|
+
registerFields,
|
|
69
|
+
unregisterField,
|
|
70
|
+
} from './utils/registerField';
|
|
71
|
+
export type { FieldOptions, HeadlessFieldOptions } from './utils/registerField';
|
|
72
|
+
|
|
73
|
+
export type { FieldInnerConfig, FieldInnerConfigContext, FieldInnerConfigResult } from './utils/fieldInnerConfig';
|
|
74
|
+
|
|
75
|
+
export { isLeafFieldType } from './utils/fieldValueEffects';
|
|
76
|
+
export type { FieldMountValueEffect, FieldMountValueEffectContext } from './utils/fieldValueEffects';
|
|
77
|
+
|
|
78
|
+
export {
|
|
79
|
+
applyMountValueEffects,
|
|
80
|
+
collectValidatableFields,
|
|
81
|
+
FieldInnerConfigError,
|
|
82
|
+
isFieldInnerConfigError,
|
|
83
|
+
} from './utils/collectFields';
|
|
84
|
+
export type { CollectedField } from './utils/collectFields';
|
|
85
|
+
|
|
86
|
+
export { createHeadlessFormState, validateValues } from './utils/validateValues';
|
|
87
|
+
export type { HeadlessFormStateOptions, ValidateValuesOptions, ValidateValuesResult } from './utils/validateValues';
|
|
88
|
+
|
|
89
|
+
export { formatValidateError, getTextByName } from './utils/validateError';
|
|
90
|
+
|
|
91
|
+
export {
|
|
92
|
+
clearTypeMatchRules,
|
|
93
|
+
deleteTypeMatchRule,
|
|
94
|
+
getTypeMatchRule,
|
|
95
|
+
MAX_SUGGESTION_OPTIONS,
|
|
96
|
+
optionSuggestion,
|
|
97
|
+
stringifyExampleValue,
|
|
98
|
+
validateTypeMatch,
|
|
99
|
+
} from './utils/typeMatch';
|
|
100
|
+
|
|
101
|
+
export type { TypeMatchValidateContext, TypeMatchValidator } from './utils/typeMatch';
|
|
65
102
|
|
|
66
103
|
export type { FormInstallOptions } from './plugin';
|
|
67
104
|
|