@tmagic/form 1.5.0-beta.9 → 1.5.0
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/style.css +53 -2
- package/dist/tmagic-form.js +271 -151
- package/dist/tmagic-form.umd.cjs +271 -152
- package/package.json +8 -6
- package/src/Form.vue +29 -8
- package/src/FormBox.vue +11 -5
- package/src/FormDialog.vue +6 -4
- package/src/FormDrawer.vue +6 -4
- package/src/containers/Col.vue +6 -3
- package/src/containers/Container.vue +89 -34
- package/src/containers/Fieldset.vue +13 -12
- package/src/containers/GroupList.vue +26 -10
- package/src/containers/GroupListItem.vue +4 -2
- package/src/containers/Panel.vue +8 -3
- package/src/containers/Row.vue +8 -3
- package/src/containers/Step.vue +9 -4
- package/src/containers/Table.vue +15 -3
- package/src/containers/Tabs.vue +35 -20
- package/src/fields/DateTime.vue +2 -2
- package/src/fields/DynamicField.vue +4 -2
- package/src/fields/Text.vue +71 -36
- package/src/index.ts +2 -2
- package/src/schema.ts +30 -16
- package/src/theme/form.scss +2 -2
- package/src/theme/text.scss +56 -0
- package/types/index.d.ts +433 -657
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.5.0
|
|
2
|
+
"version": "1.5.0",
|
|
3
3
|
"name": "@tmagic/form",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": [
|
|
@@ -32,11 +32,13 @@
|
|
|
32
32
|
"node": ">=18"
|
|
33
33
|
},
|
|
34
34
|
"repository": {
|
|
35
|
+
"directory": "packages/form",
|
|
35
36
|
"type": "git",
|
|
36
37
|
"url": "https://github.com/Tencent/tmagic-editor.git"
|
|
37
38
|
},
|
|
38
39
|
"dependencies": {
|
|
39
40
|
"@element-plus/icons-vue": "^2.3.1",
|
|
41
|
+
"@popperjs/core": "^2.11.8",
|
|
40
42
|
"dayjs": "^1.11.11",
|
|
41
43
|
"lodash-es": "^4.17.21",
|
|
42
44
|
"sortablejs": "^1.15.2"
|
|
@@ -46,17 +48,17 @@
|
|
|
46
48
|
"@types/node": "^18.19.0",
|
|
47
49
|
"@types/sortablejs": "^1.15.8",
|
|
48
50
|
"@vitejs/plugin-vue": "^5.1.3",
|
|
49
|
-
"@vue/compiler-sfc": "^3.5.
|
|
51
|
+
"@vue/compiler-sfc": "^3.5.12",
|
|
50
52
|
"@vue/test-utils": "^2.4.6",
|
|
51
53
|
"rimraf": "^3.0.2",
|
|
52
54
|
"sass": "^1.78.0",
|
|
53
|
-
"vite": "^5.4.
|
|
55
|
+
"vite": "^5.4.10"
|
|
54
56
|
},
|
|
55
57
|
"peerDependencies": {
|
|
56
|
-
"vue": "
|
|
58
|
+
"vue": ">=3.5.0",
|
|
57
59
|
"typescript": "*",
|
|
58
|
-
"@tmagic/design": "1.5.0
|
|
59
|
-
"@tmagic/utils": "1.5.0
|
|
60
|
+
"@tmagic/design": "1.5.0",
|
|
61
|
+
"@tmagic/utils": "1.5.0"
|
|
60
62
|
},
|
|
61
63
|
"peerDependenciesMeta": {
|
|
62
64
|
"typescript": {
|
package/src/Form.vue
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
:style="`height: ${height}`"
|
|
8
8
|
:inline="inline"
|
|
9
9
|
:label-position="labelPosition"
|
|
10
|
+
@submit="submitHandler"
|
|
10
11
|
>
|
|
11
12
|
<template v-if="initialized && Array.isArray(config)">
|
|
12
13
|
<Container
|
|
@@ -27,15 +28,15 @@
|
|
|
27
28
|
</template>
|
|
28
29
|
|
|
29
30
|
<script setup lang="ts">
|
|
30
|
-
import { provide, reactive, ref, toRaw, watch, watchEffect } from 'vue';
|
|
31
|
+
import { provide, reactive, ref, shallowRef, toRaw, watch, watchEffect } from 'vue';
|
|
31
32
|
import { cloneDeep, isEqual } from 'lodash-es';
|
|
32
33
|
|
|
33
|
-
import { TMagicForm } from '@tmagic/design';
|
|
34
|
+
import { TMagicForm, tMagicMessage, tMagicMessageBox } from '@tmagic/design';
|
|
34
35
|
|
|
35
36
|
import Container from './containers/Container.vue';
|
|
36
37
|
import { getConfig } from './utils/config';
|
|
37
38
|
import { initValue } from './utils/form';
|
|
38
|
-
import type { FormConfig, FormState, FormValue, ValidateError } from './schema';
|
|
39
|
+
import type { ChangeRecord, ContainerChangeEventData, FormConfig, FormState, FormValue, ValidateError } from './schema';
|
|
39
40
|
|
|
40
41
|
defineOptions({
|
|
41
42
|
name: 'MForm',
|
|
@@ -61,6 +62,7 @@ const props = withDefaults(
|
|
|
61
62
|
labelPosition?: string;
|
|
62
63
|
keyProp?: string;
|
|
63
64
|
popperClass?: string;
|
|
65
|
+
preventSubmitDefault?: boolean;
|
|
64
66
|
extendState?: (state: FormState) => Record<string, any> | Promise<Record<string, any>>;
|
|
65
67
|
}>(),
|
|
66
68
|
{
|
|
@@ -79,7 +81,7 @@ const props = withDefaults(
|
|
|
79
81
|
},
|
|
80
82
|
);
|
|
81
83
|
|
|
82
|
-
const emit = defineEmits(['change', 'error', 'field-input', 'field-change']);
|
|
84
|
+
const emit = defineEmits(['change', 'error', 'field-input', 'field-change', 'update:stepActive']);
|
|
83
85
|
|
|
84
86
|
const tMagicForm = ref<InstanceType<typeof TMagicForm>>();
|
|
85
87
|
const initialized = ref(false);
|
|
@@ -104,11 +106,13 @@ const formState: FormState = reactive<FormState>({
|
|
|
104
106
|
setField: (prop: string, field: any) => fields.set(prop, field),
|
|
105
107
|
getField: (prop: string) => fields.get(prop),
|
|
106
108
|
deleteField: (prop: string) => fields.delete(prop),
|
|
109
|
+
$messageBox: tMagicMessageBox,
|
|
110
|
+
$message: tMagicMessage,
|
|
107
111
|
post: (options: any) => {
|
|
108
112
|
if (requestFuc) {
|
|
109
113
|
return requestFuc({
|
|
110
|
-
...options,
|
|
111
114
|
method: 'POST',
|
|
115
|
+
...options,
|
|
112
116
|
});
|
|
113
117
|
}
|
|
114
118
|
},
|
|
@@ -133,9 +137,13 @@ watchEffect(async () => {
|
|
|
133
137
|
|
|
134
138
|
provide('mForm', formState);
|
|
135
139
|
|
|
140
|
+
const changeRecords = shallowRef<ChangeRecord[]>([]);
|
|
141
|
+
|
|
136
142
|
watch(
|
|
137
143
|
[() => props.config, () => props.initValues],
|
|
138
144
|
([config], [preConfig]) => {
|
|
145
|
+
changeRecords.value = [];
|
|
146
|
+
|
|
139
147
|
if (!isEqual(toRaw(config), toRaw(preConfig))) {
|
|
140
148
|
initialized.value = false;
|
|
141
149
|
}
|
|
@@ -163,8 +171,17 @@ watch(
|
|
|
163
171
|
{ immediate: true },
|
|
164
172
|
);
|
|
165
173
|
|
|
166
|
-
const changeHandler = () => {
|
|
167
|
-
|
|
174
|
+
const changeHandler = (v: FormValue, eventData: ContainerChangeEventData) => {
|
|
175
|
+
if (eventData.changeRecords?.length) {
|
|
176
|
+
changeRecords.value.push(...eventData.changeRecords);
|
|
177
|
+
}
|
|
178
|
+
emit('change', values.value, eventData);
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
const submitHandler = (e: SubmitEvent) => {
|
|
182
|
+
if (props.preventSubmitDefault) {
|
|
183
|
+
e.preventDefault();
|
|
184
|
+
}
|
|
168
185
|
};
|
|
169
186
|
|
|
170
187
|
defineExpose({
|
|
@@ -172,10 +189,14 @@ defineExpose({
|
|
|
172
189
|
lastValuesProcessed,
|
|
173
190
|
formState,
|
|
174
191
|
initialized,
|
|
192
|
+
changeRecords,
|
|
175
193
|
|
|
176
194
|
changeHandler,
|
|
177
195
|
|
|
178
|
-
resetForm: () =>
|
|
196
|
+
resetForm: () => {
|
|
197
|
+
tMagicForm.value?.resetFields();
|
|
198
|
+
changeRecords.value = [];
|
|
199
|
+
},
|
|
179
200
|
|
|
180
201
|
submitForm: async (native?: boolean): Promise<any> => {
|
|
181
202
|
try {
|
package/src/FormBox.vue
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
:label-width="labelWidth"
|
|
13
13
|
:label-position="labelPosition"
|
|
14
14
|
:inline="inline"
|
|
15
|
+
:prevent-submit-default="preventSubmitDefault"
|
|
15
16
|
@change="changeHandler"
|
|
16
17
|
></Form>
|
|
17
18
|
<slot></slot>
|
|
@@ -39,7 +40,7 @@ import { computed, ref, watchEffect } from 'vue';
|
|
|
39
40
|
import { TMagicButton, TMagicScrollbar } from '@tmagic/design';
|
|
40
41
|
|
|
41
42
|
import Form from './Form.vue';
|
|
42
|
-
import type { FormConfig } from './schema';
|
|
43
|
+
import type { ContainerChangeEventData, FormConfig, FormValue } from './schema';
|
|
43
44
|
|
|
44
45
|
defineOptions({
|
|
45
46
|
name: 'MFormBox',
|
|
@@ -58,6 +59,7 @@ const props = withDefaults(
|
|
|
58
59
|
confirmText?: string;
|
|
59
60
|
inline?: boolean;
|
|
60
61
|
labelPosition?: string;
|
|
62
|
+
preventSubmitDefault?: boolean;
|
|
61
63
|
}>(),
|
|
62
64
|
{
|
|
63
65
|
config: () => [],
|
|
@@ -66,7 +68,11 @@ const props = withDefaults(
|
|
|
66
68
|
},
|
|
67
69
|
);
|
|
68
70
|
|
|
69
|
-
const emit = defineEmits
|
|
71
|
+
const emit = defineEmits<{
|
|
72
|
+
change: [v: any, eventData: ContainerChangeEventData];
|
|
73
|
+
submit: [v: any, eventData: ContainerChangeEventData];
|
|
74
|
+
error: [e: any];
|
|
75
|
+
}>();
|
|
70
76
|
|
|
71
77
|
const footerHeight = 60;
|
|
72
78
|
|
|
@@ -96,14 +102,14 @@ watchEffect(() => {
|
|
|
96
102
|
const submitHandler = async () => {
|
|
97
103
|
try {
|
|
98
104
|
const values = await form.value?.submitForm();
|
|
99
|
-
emit('submit', values);
|
|
105
|
+
emit('submit', values, { changeRecords: form.value?.changeRecords });
|
|
100
106
|
} catch (e) {
|
|
101
107
|
emit('error', e);
|
|
102
108
|
}
|
|
103
109
|
};
|
|
104
110
|
|
|
105
|
-
const changeHandler = (value:
|
|
106
|
-
emit('change', value);
|
|
111
|
+
const changeHandler = (value: FormValue, eventData: ContainerChangeEventData) => {
|
|
112
|
+
emit('change', value, eventData);
|
|
107
113
|
};
|
|
108
114
|
|
|
109
115
|
const show = () => {};
|
package/src/FormDialog.vue
CHANGED
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
:label-width="labelWidth"
|
|
28
28
|
:label-position="labelPosition"
|
|
29
29
|
:inline="inline"
|
|
30
|
+
:prevent-submit-default="preventSubmitDefault"
|
|
30
31
|
@change="changeHandler"
|
|
31
32
|
></Form>
|
|
32
33
|
<slot></slot>
|
|
@@ -64,7 +65,7 @@ import { computed, ref } from 'vue';
|
|
|
64
65
|
import { TMagicButton, TMagicCol, TMagicDialog, TMagicRow } from '@tmagic/design';
|
|
65
66
|
|
|
66
67
|
import Form from './Form.vue';
|
|
67
|
-
import { FormConfig, StepConfig } from './schema';
|
|
68
|
+
import { ContainerChangeEventData, FormConfig, FormValue, StepConfig } from './schema';
|
|
68
69
|
|
|
69
70
|
defineOptions({
|
|
70
71
|
name: 'MFormDialog',
|
|
@@ -85,6 +86,7 @@ const props = withDefaults(
|
|
|
85
86
|
zIndex?: number;
|
|
86
87
|
size?: 'small' | 'default' | 'large';
|
|
87
88
|
confirmText?: string;
|
|
89
|
+
preventSubmitDefault?: boolean;
|
|
88
90
|
}>(),
|
|
89
91
|
{
|
|
90
92
|
config: () => [],
|
|
@@ -130,7 +132,7 @@ const closeHandler = () => {
|
|
|
130
132
|
const save = async () => {
|
|
131
133
|
try {
|
|
132
134
|
const values = await form.value?.submitForm();
|
|
133
|
-
emit('submit', values);
|
|
135
|
+
emit('submit', values, { changeRecords: form.value?.changeRecords });
|
|
134
136
|
} catch (e) {
|
|
135
137
|
emit('error', e);
|
|
136
138
|
}
|
|
@@ -144,8 +146,8 @@ const nextStep = () => {
|
|
|
144
146
|
stepActive.value += 1;
|
|
145
147
|
};
|
|
146
148
|
|
|
147
|
-
const changeHandler = (value:
|
|
148
|
-
emit('change', value);
|
|
149
|
+
const changeHandler = (value: FormValue, eventData: ContainerChangeEventData) => {
|
|
150
|
+
emit('change', value, eventData);
|
|
149
151
|
};
|
|
150
152
|
|
|
151
153
|
const show = () => {
|
package/src/FormDrawer.vue
CHANGED
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
:label-width="labelWidth"
|
|
28
28
|
:label-position="labelPosition"
|
|
29
29
|
:inline="inline"
|
|
30
|
+
:prevent-submit-default="preventSubmitDefault"
|
|
30
31
|
@change="changeHandler"
|
|
31
32
|
></Form>
|
|
32
33
|
<slot></slot>
|
|
@@ -58,7 +59,7 @@ import { ref, watchEffect } from 'vue';
|
|
|
58
59
|
import { TMagicButton, TMagicCol, TMagicDrawer, TMagicRow } from '@tmagic/design';
|
|
59
60
|
|
|
60
61
|
import Form from './Form.vue';
|
|
61
|
-
import type { FormConfig } from './schema';
|
|
62
|
+
import type { ContainerChangeEventData, FormConfig, FormValue } from './schema';
|
|
62
63
|
|
|
63
64
|
defineOptions({
|
|
64
65
|
name: 'MFormDialog',
|
|
@@ -79,6 +80,7 @@ withDefaults(
|
|
|
79
80
|
confirmText?: string;
|
|
80
81
|
inline?: boolean;
|
|
81
82
|
labelPosition?: string;
|
|
83
|
+
preventSubmitDefault?: boolean;
|
|
82
84
|
/** 关闭前的回调,会暂停 Drawer 的关闭; done 是个 function type 接受一个 boolean 参数, 执行 done 使用 true 参数或不提供参数将会终止关闭 */
|
|
83
85
|
beforeClose?: (done: (cancel?: boolean) => void) => void;
|
|
84
86
|
}>(),
|
|
@@ -108,14 +110,14 @@ watchEffect(() => {
|
|
|
108
110
|
const submitHandler = async () => {
|
|
109
111
|
try {
|
|
110
112
|
const values = await form.value?.submitForm();
|
|
111
|
-
emit('submit', values);
|
|
113
|
+
emit('submit', values, { changeRecords: form.value?.changeRecords });
|
|
112
114
|
} catch (e) {
|
|
113
115
|
emit('error', e);
|
|
114
116
|
}
|
|
115
117
|
};
|
|
116
118
|
|
|
117
|
-
const changeHandler = (value:
|
|
118
|
-
emit('change', value);
|
|
119
|
+
const changeHandler = (value: FormValue, eventData: ContainerChangeEventData) => {
|
|
120
|
+
emit('change', value, eventData);
|
|
119
121
|
};
|
|
120
122
|
|
|
121
123
|
const openHandler = () => {
|
package/src/containers/Col.vue
CHANGED
|
@@ -21,7 +21,7 @@ import { computed, inject } from 'vue';
|
|
|
21
21
|
|
|
22
22
|
import { TMagicCol } from '@tmagic/design';
|
|
23
23
|
|
|
24
|
-
import { ChildConfig, FormState } from '../schema';
|
|
24
|
+
import type { ChildConfig, ContainerChangeEventData, FormState } from '../schema';
|
|
25
25
|
import { display as displayFunction } from '../utils/form';
|
|
26
26
|
|
|
27
27
|
import Container from './Container.vue';
|
|
@@ -43,10 +43,13 @@ const props = defineProps<{
|
|
|
43
43
|
disabled?: boolean;
|
|
44
44
|
}>();
|
|
45
45
|
|
|
46
|
-
const emit = defineEmits
|
|
46
|
+
const emit = defineEmits<{
|
|
47
|
+
change: [v: any, eventData: ContainerChangeEventData];
|
|
48
|
+
addDiffCount: [];
|
|
49
|
+
}>();
|
|
47
50
|
|
|
48
51
|
const mForm = inject<FormState | undefined>('mForm');
|
|
49
52
|
const display = computed(() => displayFunction(mForm, props.config.display, props));
|
|
50
|
-
const changeHandler = () => emit('change',
|
|
53
|
+
const changeHandler = (v: any, eventData: ContainerChangeEventData) => emit('change', v, eventData);
|
|
51
54
|
const onAddDiffCount = () => emit('addDiffCount');
|
|
52
55
|
</script>
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
<template v-else-if="type && display && !showDiff">
|
|
38
38
|
<TMagicFormItem
|
|
39
39
|
:style="config.tip ? 'flex: 1' : ''"
|
|
40
|
-
:class="{ hidden: `${itemLabelWidth}` === '0' || !text }"
|
|
40
|
+
:class="{ 'tmagic-form-hidden': `${itemLabelWidth}` === '0' || !text }"
|
|
41
41
|
:prop="itemProp"
|
|
42
42
|
:label-width="itemLabelWidth"
|
|
43
43
|
:rules="rule"
|
|
@@ -93,7 +93,7 @@
|
|
|
93
93
|
<!-- 上次内容 -->
|
|
94
94
|
<TMagicFormItem
|
|
95
95
|
:style="config.tip ? 'flex: 1' : ''"
|
|
96
|
-
:class="{ hidden: `${itemLabelWidth}` === '0' || !text }"
|
|
96
|
+
:class="{ 'tmagic-form-hidden': `${itemLabelWidth}` === '0' || !text }"
|
|
97
97
|
:prop="itemProp"
|
|
98
98
|
:label-width="itemLabelWidth"
|
|
99
99
|
:rules="rule"
|
|
@@ -142,7 +142,7 @@
|
|
|
142
142
|
<!-- 当前内容 -->
|
|
143
143
|
<TMagicFormItem
|
|
144
144
|
:style="config.tip ? 'flex: 1' : ''"
|
|
145
|
-
:class="{ hidden: `${itemLabelWidth}` === '0' || !text }"
|
|
145
|
+
:class="{ 'tmagic-form-hidden': `${itemLabelWidth}` === '0' || !text }"
|
|
146
146
|
:prop="itemProp"
|
|
147
147
|
:label-width="itemLabelWidth"
|
|
148
148
|
:rules="rule"
|
|
@@ -191,12 +191,12 @@
|
|
|
191
191
|
</template>
|
|
192
192
|
|
|
193
193
|
<template v-else-if="items && display">
|
|
194
|
-
<template v-if="
|
|
194
|
+
<template v-if="isValidName() ? model[name] : model">
|
|
195
195
|
<Container
|
|
196
196
|
v-for="item in items"
|
|
197
197
|
:key="key(item)"
|
|
198
|
-
:model="
|
|
199
|
-
:last-values="
|
|
198
|
+
:model="isValidName() ? model[name] : model"
|
|
199
|
+
:last-values="isValidName() ? lastValues[name] || {} : lastValues"
|
|
200
200
|
:is-compare="isCompare"
|
|
201
201
|
:config="item"
|
|
202
202
|
:size="size"
|
|
@@ -220,13 +220,20 @@
|
|
|
220
220
|
</template>
|
|
221
221
|
|
|
222
222
|
<script setup lang="ts">
|
|
223
|
-
import { computed, inject, ref, watch, watchEffect } from 'vue';
|
|
223
|
+
import { computed, inject, ref, toRaw, watch, watchEffect } from 'vue';
|
|
224
224
|
import { WarningFilled } from '@element-plus/icons-vue';
|
|
225
225
|
import { isEqual } from 'lodash-es';
|
|
226
226
|
|
|
227
227
|
import { TMagicButton, TMagicFormItem, TMagicIcon, TMagicTooltip } from '@tmagic/design';
|
|
228
228
|
|
|
229
|
-
import {
|
|
229
|
+
import type {
|
|
230
|
+
ChildConfig,
|
|
231
|
+
ContainerChangeEventData,
|
|
232
|
+
ContainerCommonConfig,
|
|
233
|
+
FormState,
|
|
234
|
+
FormValue,
|
|
235
|
+
TypeFunction,
|
|
236
|
+
} from '../schema';
|
|
230
237
|
import { display as displayFunction, filterFunction, getRules } from '../utils/form';
|
|
231
238
|
|
|
232
239
|
defineOptions({
|
|
@@ -258,7 +265,10 @@ const props = withDefaults(
|
|
|
258
265
|
},
|
|
259
266
|
);
|
|
260
267
|
|
|
261
|
-
const emit = defineEmits
|
|
268
|
+
const emit = defineEmits<{
|
|
269
|
+
change: [v: any, eventData: ContainerChangeEventData];
|
|
270
|
+
addDiffCount: [];
|
|
271
|
+
}>();
|
|
262
272
|
|
|
263
273
|
const mForm = inject<FormState | undefined>('mForm');
|
|
264
274
|
|
|
@@ -285,7 +295,12 @@ const itemProp = computed(() => {
|
|
|
285
295
|
} else {
|
|
286
296
|
return props.prop;
|
|
287
297
|
}
|
|
288
|
-
|
|
298
|
+
|
|
299
|
+
if (typeof props.prop !== 'undefined' && props.prop !== '') {
|
|
300
|
+
return `${props.prop}.${n}`;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
return `${n}`;
|
|
289
304
|
});
|
|
290
305
|
|
|
291
306
|
const tagName = computed(() => `m-${items.value ? 'form' : 'fields'}-${type.value}`);
|
|
@@ -360,18 +375,6 @@ const filterHandler = (filter: any, value: FormValue | number | string) => {
|
|
|
360
375
|
return value;
|
|
361
376
|
};
|
|
362
377
|
|
|
363
|
-
const changeHandler = (onChange: any, value: FormValue | number | string) => {
|
|
364
|
-
if (typeof onChange === 'function') {
|
|
365
|
-
return onChange(mForm, value, {
|
|
366
|
-
model: props.model,
|
|
367
|
-
values: mForm?.initValues,
|
|
368
|
-
formValue: mForm?.values,
|
|
369
|
-
prop: itemProp.value,
|
|
370
|
-
config: props.config,
|
|
371
|
-
});
|
|
372
|
-
}
|
|
373
|
-
};
|
|
374
|
-
|
|
375
378
|
const trimHandler = (trim: any, value: FormValue | number | string) => {
|
|
376
379
|
if (typeof value === 'string' && trim) {
|
|
377
380
|
return value.replace(/^\s*/, '').replace(/\s*$/, '');
|
|
@@ -381,28 +384,80 @@ const trimHandler = (trim: any, value: FormValue | number | string) => {
|
|
|
381
384
|
// 继续抛出给更高层级的组件
|
|
382
385
|
const onAddDiffCount = () => emit('addDiffCount');
|
|
383
386
|
|
|
384
|
-
const
|
|
385
|
-
|
|
386
|
-
|
|
387
|
+
const hasModifyKey = (eventDataItem: ContainerChangeEventData) =>
|
|
388
|
+
typeof eventDataItem?.modifyKey !== 'undefined' && eventDataItem.modifyKey !== '';
|
|
389
|
+
|
|
390
|
+
const isValidName = () => {
|
|
391
|
+
const valueType = typeof name.value;
|
|
392
|
+
if (valueType !== 'string' && valueType !== 'symbol' && valueType !== 'number') {
|
|
393
|
+
return false;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
if (name.value === '') {
|
|
397
|
+
return false;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
if (typeof name.value === 'number') {
|
|
401
|
+
return name.value >= 0;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
return true;
|
|
405
|
+
};
|
|
406
|
+
|
|
407
|
+
const onChangeHandler = async function (v: any, eventData: ContainerChangeEventData = {}) {
|
|
408
|
+
const { filter, onChange, trim, dynamicKey } = props.config as any;
|
|
409
|
+
let value: FormValue | number | string | any[] = toRaw(v);
|
|
410
|
+
const changeRecords = eventData.changeRecords || [];
|
|
411
|
+
const newChangeRecords = [...changeRecords];
|
|
387
412
|
|
|
388
413
|
try {
|
|
389
414
|
value = filterHandler(filter, v);
|
|
390
|
-
|
|
415
|
+
|
|
416
|
+
if (typeof onChange === 'function') {
|
|
417
|
+
value =
|
|
418
|
+
(await onChange(mForm, value, {
|
|
419
|
+
model: props.model,
|
|
420
|
+
values: mForm?.initValues,
|
|
421
|
+
formValue: mForm?.values,
|
|
422
|
+
prop: itemProp.value,
|
|
423
|
+
config: props.config,
|
|
424
|
+
changeRecords: newChangeRecords,
|
|
425
|
+
})) ?? value;
|
|
426
|
+
}
|
|
391
427
|
value = trimHandler(trim, value) ?? value;
|
|
392
428
|
} catch (e) {
|
|
393
429
|
console.error(e);
|
|
394
430
|
}
|
|
395
431
|
|
|
396
|
-
|
|
397
|
-
|
|
432
|
+
let valueProp = itemProp.value;
|
|
433
|
+
|
|
434
|
+
if (hasModifyKey(eventData)) {
|
|
435
|
+
if (dynamicKey) {
|
|
436
|
+
props.model[eventData.modifyKey!] = value;
|
|
437
|
+
} else if (isValidName()) {
|
|
438
|
+
props.model[name.value][eventData.modifyKey!] = value;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
valueProp = valueProp ? `${valueProp}.${eventData.modifyKey}` : eventData.modifyKey!;
|
|
442
|
+
|
|
443
|
+
// 需要清除掉modifyKey,不然往上层抛出后还会被认为需要修改
|
|
444
|
+
delete eventData.modifyKey;
|
|
445
|
+
} else if (isValidName() && props.model !== value && (v !== value || props.model[name.value] !== value)) {
|
|
446
|
+
// field内容下包含field-link时,model===value, 这里避免循环引用
|
|
398
447
|
// eslint-disable-next-line vue/no-mutating-props
|
|
399
|
-
props.model[name] = value;
|
|
448
|
+
props.model[name.value] = value;
|
|
400
449
|
}
|
|
401
|
-
|
|
402
|
-
if (
|
|
403
|
-
|
|
404
|
-
|
|
450
|
+
|
|
451
|
+
if (changeRecords.length === 0) {
|
|
452
|
+
newChangeRecords.push({
|
|
453
|
+
propPath: valueProp,
|
|
454
|
+
value,
|
|
455
|
+
});
|
|
405
456
|
}
|
|
406
|
-
|
|
457
|
+
|
|
458
|
+
emit('change', props.model, {
|
|
459
|
+
...eventData,
|
|
460
|
+
changeRecords: newChangeRecords,
|
|
461
|
+
});
|
|
407
462
|
};
|
|
408
463
|
</script>
|
|
@@ -1,16 +1,12 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<fieldset
|
|
3
|
-
v-if="name ? model[name] : model"
|
|
4
|
-
class="m-fieldset"
|
|
5
|
-
:style="show ? 'padding: 15px 15px 0 5px;' : 'border: 0'"
|
|
6
|
-
>
|
|
2
|
+
<fieldset v-if="name ? model[name] : model" class="m-fieldset" :style="show ? 'padding: 15px' : 'border: 0'">
|
|
7
3
|
<component v-if="name && config.checkbox" :is="!show ? 'div' : 'legend'">
|
|
8
4
|
<TMagicCheckbox
|
|
9
5
|
v-model="model[name].value"
|
|
10
6
|
:prop="`${prop}${prop ? '.' : ''}${config.name}.value`"
|
|
11
7
|
:true-value="1"
|
|
12
8
|
:false-value="0"
|
|
13
|
-
@update:modelValue="
|
|
9
|
+
@update:modelValue="valueChangeHandler"
|
|
14
10
|
><span v-html="config.legend"></span><span v-if="config.extra" v-html="config.extra" class="m-form-tip"></span
|
|
15
11
|
></TMagicCheckbox>
|
|
16
12
|
</component>
|
|
@@ -33,7 +29,7 @@
|
|
|
33
29
|
:disabled="disabled"
|
|
34
30
|
:labelWidth="lWidth"
|
|
35
31
|
:size="size"
|
|
36
|
-
@change="
|
|
32
|
+
@change="changeHandler"
|
|
37
33
|
@add-diff-count="onAddDiffCount()"
|
|
38
34
|
></Container>
|
|
39
35
|
</div>
|
|
@@ -54,7 +50,7 @@
|
|
|
54
50
|
:labelWidth="lWidth"
|
|
55
51
|
:size="size"
|
|
56
52
|
:disabled="disabled"
|
|
57
|
-
@change="
|
|
53
|
+
@change="changeHandler"
|
|
58
54
|
@addDiffCount="onAddDiffCount()"
|
|
59
55
|
></Container>
|
|
60
56
|
</template>
|
|
@@ -66,7 +62,7 @@ import { computed, inject } from 'vue';
|
|
|
66
62
|
|
|
67
63
|
import { TMagicCheckbox } from '@tmagic/design';
|
|
68
64
|
|
|
69
|
-
import { FieldsetConfig, FormState } from '../schema';
|
|
65
|
+
import { ContainerChangeEventData, FieldsetConfig, FormState } from '../schema';
|
|
70
66
|
|
|
71
67
|
import Container from './Container.vue';
|
|
72
68
|
|
|
@@ -94,7 +90,10 @@ const props = withDefaults(
|
|
|
94
90
|
},
|
|
95
91
|
);
|
|
96
92
|
|
|
97
|
-
const emit = defineEmits
|
|
93
|
+
const emit = defineEmits<{
|
|
94
|
+
change: [v: any, eventData: ContainerChangeEventData];
|
|
95
|
+
addDiffCount: [];
|
|
96
|
+
}>();
|
|
98
97
|
|
|
99
98
|
const mForm = inject<FormState | undefined>('mForm');
|
|
100
99
|
|
|
@@ -114,10 +113,12 @@ const lWidth = computed(() => {
|
|
|
114
113
|
return props.config.labelWidth || props.labelWidth || (props.config.text ? undefined : '0');
|
|
115
114
|
});
|
|
116
115
|
|
|
117
|
-
const
|
|
118
|
-
emit('change',
|
|
116
|
+
const valueChangeHandler = (value: number | boolean) => {
|
|
117
|
+
emit('change', value, { modifyKey: 'value' });
|
|
119
118
|
};
|
|
120
119
|
|
|
120
|
+
const changeHandler = (v: any, eventData: ContainerChangeEventData) => emit('change', v, eventData);
|
|
121
|
+
|
|
121
122
|
const key = (item: any, index: number) => item[mForm?.keyProp || '__key'] ?? index;
|
|
122
123
|
|
|
123
124
|
const onAddDiffCount = () => emit('addDiffCount');
|
|
@@ -25,7 +25,14 @@
|
|
|
25
25
|
@addDiffCount="onAddDiffCount()"
|
|
26
26
|
></MFieldsGroupListItem>
|
|
27
27
|
|
|
28
|
-
<TMagicButton
|
|
28
|
+
<TMagicButton
|
|
29
|
+
v-if="addable"
|
|
30
|
+
type="primary"
|
|
31
|
+
:size="config.enableToggleMode ? 'small' : 'default'"
|
|
32
|
+
:disabled="disabled"
|
|
33
|
+
@click="addHandler"
|
|
34
|
+
>新增</TMagicButton
|
|
35
|
+
>
|
|
29
36
|
|
|
30
37
|
<TMagicButton :icon="Grid" size="small" @click="toggleMode" v-if="config.enableToggleMode">切换为表格</TMagicButton>
|
|
31
38
|
</div>
|
|
@@ -37,7 +44,7 @@ import { Grid } from '@element-plus/icons-vue';
|
|
|
37
44
|
|
|
38
45
|
import { TMagicButton } from '@tmagic/design';
|
|
39
46
|
|
|
40
|
-
import { FormState, GroupListConfig } from '../schema';
|
|
47
|
+
import type { ContainerChangeEventData, FormState, GroupListConfig } from '../schema';
|
|
41
48
|
import { initValue } from '../utils/form';
|
|
42
49
|
|
|
43
50
|
import MFieldsGroupListItem from './GroupListItem.vue';
|
|
@@ -58,7 +65,10 @@ const props = defineProps<{
|
|
|
58
65
|
disabled?: boolean;
|
|
59
66
|
}>();
|
|
60
67
|
|
|
61
|
-
const emit = defineEmits
|
|
68
|
+
const emit = defineEmits<{
|
|
69
|
+
change: [v: any, eventData?: ContainerChangeEventData];
|
|
70
|
+
addDiffCount: [];
|
|
71
|
+
}>();
|
|
62
72
|
|
|
63
73
|
const mForm = inject<FormState | undefined>('mForm');
|
|
64
74
|
|
|
@@ -77,10 +87,8 @@ const addable = computed(() => {
|
|
|
77
87
|
return typeof props.config.addable === 'undefined' ? true : props.config.addable;
|
|
78
88
|
});
|
|
79
89
|
|
|
80
|
-
const changeHandler = () => {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
emit('change', props.model[props.name]);
|
|
90
|
+
const changeHandler = (v: any, eventData: ContainerChangeEventData) => {
|
|
91
|
+
emit('change', props.model, eventData);
|
|
84
92
|
};
|
|
85
93
|
|
|
86
94
|
const addHandler = async () => {
|
|
@@ -105,14 +113,22 @@ const addHandler = async () => {
|
|
|
105
113
|
});
|
|
106
114
|
|
|
107
115
|
props.model[props.name].push(groupValue);
|
|
108
|
-
|
|
116
|
+
|
|
117
|
+
emit('change', props.model[props.name], {
|
|
118
|
+
changeRecords: [
|
|
119
|
+
{
|
|
120
|
+
propPath: `${props.prop}.${props.model[props.name].length - 1}`,
|
|
121
|
+
value: groupValue,
|
|
122
|
+
},
|
|
123
|
+
],
|
|
124
|
+
});
|
|
109
125
|
};
|
|
110
126
|
|
|
111
127
|
const removeHandler = (index: number) => {
|
|
112
128
|
if (!props.name) return false;
|
|
113
129
|
|
|
114
130
|
props.model[props.name].splice(index, 1);
|
|
115
|
-
|
|
131
|
+
emit('change', props.model[props.name]);
|
|
116
132
|
};
|
|
117
133
|
|
|
118
134
|
const swapHandler = (idx1: number, idx2: number) => {
|
|
@@ -120,7 +136,7 @@ const swapHandler = (idx1: number, idx2: number) => {
|
|
|
120
136
|
|
|
121
137
|
const [currRow] = props.model[props.name].splice(idx1, 1);
|
|
122
138
|
props.model[props.name].splice(idx2, 0, currRow);
|
|
123
|
-
|
|
139
|
+
emit('change', props.model[props.name]);
|
|
124
140
|
};
|
|
125
141
|
|
|
126
142
|
const toggleMode = () => {
|