@tmagic/form 1.5.0-beta.9 → 1.5.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/{style.css → tmagic-form.css} +53 -2
- package/dist/tmagic-form.js +295 -181
- package/dist/tmagic-form.umd.cjs +294 -181
- package/package.json +10 -8
- 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 +92 -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 +32 -32
- 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 +3 -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.
|
|
2
|
+
"version": "1.5.1",
|
|
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"
|
|
@@ -45,18 +47,18 @@
|
|
|
45
47
|
"@types/lodash-es": "^4.17.4",
|
|
46
48
|
"@types/node": "^18.19.0",
|
|
47
49
|
"@types/sortablejs": "^1.15.8",
|
|
48
|
-
"@vitejs/plugin-vue": "^5.1
|
|
49
|
-
"@vue/compiler-sfc": "^3.5.
|
|
50
|
+
"@vitejs/plugin-vue": "^5.2.1",
|
|
51
|
+
"@vue/compiler-sfc": "^3.5.12",
|
|
50
52
|
"@vue/test-utils": "^2.4.6",
|
|
51
53
|
"rimraf": "^3.0.2",
|
|
52
|
-
"sass": "^1.
|
|
53
|
-
"vite": "^
|
|
54
|
+
"sass": "^1.83.0",
|
|
55
|
+
"vite": "^6.0.3"
|
|
54
56
|
},
|
|
55
57
|
"peerDependencies": {
|
|
56
|
-
"vue": "
|
|
58
|
+
"vue": ">=3.5.0",
|
|
57
59
|
"typescript": "*",
|
|
58
|
-
"@tmagic/design": "1.5.
|
|
59
|
-
"@tmagic/utils": "1.5.
|
|
60
|
+
"@tmagic/design": "1.5.1",
|
|
61
|
+
"@tmagic/utils": "1.5.1"
|
|
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,9 +37,10 @@
|
|
|
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
|
+
:label-position="config.labelPosition"
|
|
43
44
|
:rules="rule"
|
|
44
45
|
>
|
|
45
46
|
<template #label><span v-html="type === 'checkbox' ? '' : text" :title="config.labelTitle"></span></template>
|
|
@@ -93,9 +94,10 @@
|
|
|
93
94
|
<!-- 上次内容 -->
|
|
94
95
|
<TMagicFormItem
|
|
95
96
|
:style="config.tip ? 'flex: 1' : ''"
|
|
96
|
-
:class="{ hidden: `${itemLabelWidth}` === '0' || !text }"
|
|
97
|
+
:class="{ 'tmagic-form-hidden': `${itemLabelWidth}` === '0' || !text }"
|
|
97
98
|
:prop="itemProp"
|
|
98
99
|
:label-width="itemLabelWidth"
|
|
100
|
+
:label-position="config.labelPosition"
|
|
99
101
|
:rules="rule"
|
|
100
102
|
style="background: #f7dadd"
|
|
101
103
|
>
|
|
@@ -142,9 +144,10 @@
|
|
|
142
144
|
<!-- 当前内容 -->
|
|
143
145
|
<TMagicFormItem
|
|
144
146
|
:style="config.tip ? 'flex: 1' : ''"
|
|
145
|
-
:class="{ hidden: `${itemLabelWidth}` === '0' || !text }"
|
|
147
|
+
:class="{ 'tmagic-form-hidden': `${itemLabelWidth}` === '0' || !text }"
|
|
146
148
|
:prop="itemProp"
|
|
147
149
|
:label-width="itemLabelWidth"
|
|
150
|
+
:label-position="config.labelPosition"
|
|
148
151
|
:rules="rule"
|
|
149
152
|
style="background: #def7da"
|
|
150
153
|
>
|
|
@@ -191,12 +194,12 @@
|
|
|
191
194
|
</template>
|
|
192
195
|
|
|
193
196
|
<template v-else-if="items && display">
|
|
194
|
-
<template v-if="
|
|
197
|
+
<template v-if="isValidName() ? model[name] : model">
|
|
195
198
|
<Container
|
|
196
199
|
v-for="item in items"
|
|
197
200
|
:key="key(item)"
|
|
198
|
-
:model="
|
|
199
|
-
:last-values="
|
|
201
|
+
:model="isValidName() ? model[name] : model"
|
|
202
|
+
:last-values="isValidName() ? lastValues[name] || {} : lastValues"
|
|
200
203
|
:is-compare="isCompare"
|
|
201
204
|
:config="item"
|
|
202
205
|
:size="size"
|
|
@@ -220,13 +223,20 @@
|
|
|
220
223
|
</template>
|
|
221
224
|
|
|
222
225
|
<script setup lang="ts">
|
|
223
|
-
import { computed, inject, ref, watch, watchEffect } from 'vue';
|
|
226
|
+
import { computed, inject, ref, toRaw, watch, watchEffect } from 'vue';
|
|
224
227
|
import { WarningFilled } from '@element-plus/icons-vue';
|
|
225
228
|
import { isEqual } from 'lodash-es';
|
|
226
229
|
|
|
227
230
|
import { TMagicButton, TMagicFormItem, TMagicIcon, TMagicTooltip } from '@tmagic/design';
|
|
228
231
|
|
|
229
|
-
import {
|
|
232
|
+
import type {
|
|
233
|
+
ChildConfig,
|
|
234
|
+
ContainerChangeEventData,
|
|
235
|
+
ContainerCommonConfig,
|
|
236
|
+
FormState,
|
|
237
|
+
FormValue,
|
|
238
|
+
TypeFunction,
|
|
239
|
+
} from '../schema';
|
|
230
240
|
import { display as displayFunction, filterFunction, getRules } from '../utils/form';
|
|
231
241
|
|
|
232
242
|
defineOptions({
|
|
@@ -258,7 +268,10 @@ const props = withDefaults(
|
|
|
258
268
|
},
|
|
259
269
|
);
|
|
260
270
|
|
|
261
|
-
const emit = defineEmits
|
|
271
|
+
const emit = defineEmits<{
|
|
272
|
+
change: [v: any, eventData: ContainerChangeEventData];
|
|
273
|
+
addDiffCount: [];
|
|
274
|
+
}>();
|
|
262
275
|
|
|
263
276
|
const mForm = inject<FormState | undefined>('mForm');
|
|
264
277
|
|
|
@@ -285,7 +298,12 @@ const itemProp = computed(() => {
|
|
|
285
298
|
} else {
|
|
286
299
|
return props.prop;
|
|
287
300
|
}
|
|
288
|
-
|
|
301
|
+
|
|
302
|
+
if (typeof props.prop !== 'undefined' && props.prop !== '') {
|
|
303
|
+
return `${props.prop}.${n}`;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
return `${n}`;
|
|
289
307
|
});
|
|
290
308
|
|
|
291
309
|
const tagName = computed(() => `m-${items.value ? 'form' : 'fields'}-${type.value}`);
|
|
@@ -360,18 +378,6 @@ const filterHandler = (filter: any, value: FormValue | number | string) => {
|
|
|
360
378
|
return value;
|
|
361
379
|
};
|
|
362
380
|
|
|
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
381
|
const trimHandler = (trim: any, value: FormValue | number | string) => {
|
|
376
382
|
if (typeof value === 'string' && trim) {
|
|
377
383
|
return value.replace(/^\s*/, '').replace(/\s*$/, '');
|
|
@@ -381,28 +387,80 @@ const trimHandler = (trim: any, value: FormValue | number | string) => {
|
|
|
381
387
|
// 继续抛出给更高层级的组件
|
|
382
388
|
const onAddDiffCount = () => emit('addDiffCount');
|
|
383
389
|
|
|
384
|
-
const
|
|
385
|
-
|
|
386
|
-
|
|
390
|
+
const hasModifyKey = (eventDataItem: ContainerChangeEventData) =>
|
|
391
|
+
typeof eventDataItem?.modifyKey !== 'undefined' && eventDataItem.modifyKey !== '';
|
|
392
|
+
|
|
393
|
+
const isValidName = () => {
|
|
394
|
+
const valueType = typeof name.value;
|
|
395
|
+
if (valueType !== 'string' && valueType !== 'symbol' && valueType !== 'number') {
|
|
396
|
+
return false;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
if (name.value === '') {
|
|
400
|
+
return false;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
if (typeof name.value === 'number') {
|
|
404
|
+
return name.value >= 0;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
return true;
|
|
408
|
+
};
|
|
409
|
+
|
|
410
|
+
const onChangeHandler = async function (v: any, eventData: ContainerChangeEventData = {}) {
|
|
411
|
+
const { filter, onChange, trim, dynamicKey } = props.config as any;
|
|
412
|
+
let value: FormValue | number | string | any[] = toRaw(v);
|
|
413
|
+
const changeRecords = eventData.changeRecords || [];
|
|
414
|
+
const newChangeRecords = [...changeRecords];
|
|
387
415
|
|
|
388
416
|
try {
|
|
389
417
|
value = filterHandler(filter, v);
|
|
390
|
-
|
|
418
|
+
|
|
419
|
+
if (typeof onChange === 'function') {
|
|
420
|
+
value =
|
|
421
|
+
(await onChange(mForm, value, {
|
|
422
|
+
model: props.model,
|
|
423
|
+
values: mForm?.initValues,
|
|
424
|
+
formValue: mForm?.values,
|
|
425
|
+
prop: itemProp.value,
|
|
426
|
+
config: props.config,
|
|
427
|
+
changeRecords: newChangeRecords,
|
|
428
|
+
})) ?? value;
|
|
429
|
+
}
|
|
391
430
|
value = trimHandler(trim, value) ?? value;
|
|
392
431
|
} catch (e) {
|
|
393
432
|
console.error(e);
|
|
394
433
|
}
|
|
395
434
|
|
|
396
|
-
|
|
397
|
-
|
|
435
|
+
let valueProp = itemProp.value;
|
|
436
|
+
|
|
437
|
+
if (hasModifyKey(eventData)) {
|
|
438
|
+
if (dynamicKey) {
|
|
439
|
+
props.model[eventData.modifyKey!] = value;
|
|
440
|
+
} else if (isValidName()) {
|
|
441
|
+
props.model[name.value][eventData.modifyKey!] = value;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
valueProp = valueProp ? `${valueProp}.${eventData.modifyKey}` : eventData.modifyKey!;
|
|
445
|
+
|
|
446
|
+
// 需要清除掉modifyKey,不然往上层抛出后还会被认为需要修改
|
|
447
|
+
delete eventData.modifyKey;
|
|
448
|
+
} else if (isValidName() && props.model !== value && (v !== value || props.model[name.value] !== value)) {
|
|
449
|
+
// field内容下包含field-link时,model===value, 这里避免循环引用
|
|
398
450
|
// eslint-disable-next-line vue/no-mutating-props
|
|
399
|
-
props.model[name] = value;
|
|
451
|
+
props.model[name.value] = value;
|
|
400
452
|
}
|
|
401
|
-
|
|
402
|
-
if (
|
|
403
|
-
|
|
404
|
-
|
|
453
|
+
|
|
454
|
+
if (changeRecords.length === 0) {
|
|
455
|
+
newChangeRecords.push({
|
|
456
|
+
propPath: valueProp,
|
|
457
|
+
value,
|
|
458
|
+
});
|
|
405
459
|
}
|
|
406
|
-
|
|
460
|
+
|
|
461
|
+
emit('change', props.model, {
|
|
462
|
+
...eventData,
|
|
463
|
+
changeRecords: newChangeRecords,
|
|
464
|
+
});
|
|
407
465
|
};
|
|
408
466
|
</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 = () => {
|