@tmagic/form 1.8.0-beta.2 → 1.8.0-beta.21
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 +120 -27
- package/dist/es/FormBox.vue_vue_type_script_setup_true_lang.js +19 -3
- package/dist/es/FormDialog.vue_vue_type_script_setup_true_lang.js +30 -7
- package/dist/es/FormDrawer.vue_vue_type_script_setup_true_lang.js +56 -14
- package/dist/es/containers/Col.vue_vue_type_script_setup_true_lang.js +3 -2
- package/dist/es/containers/Container.vue_vue_type_script_setup_true_lang.js +51 -36
- package/dist/es/containers/Fieldset.vue_vue_type_script_setup_true_lang.js +5 -3
- package/dist/es/containers/FlexLayout.vue_vue_type_script_setup_true_lang.js +1 -1
- 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 +7 -6
- package/dist/es/containers/GroupListItem.vue_vue_type_script_setup_true_lang.js +42 -32
- package/dist/es/containers/Panel.vue_vue_type_script_setup_true_lang.js +17 -11
- package/dist/es/containers/Row.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/containers/Step.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/containers/Tabs.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/containers/table/ActionsColumn.vue_vue_type_script_setup_true_lang.js +14 -7
- 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 +7 -5
- package/dist/es/containers/table/useTableColumns.js +5 -1
- package/dist/es/containers/table-group-list/TableGroupList.vue_vue_type_script_setup_true_lang.js +3 -2
- package/dist/es/fields/Cascader.vue_vue_type_script_setup_true_lang.js +6 -3
- package/dist/es/fields/Checkbox.vue_vue_type_script_setup_true_lang.js +5 -2
- package/dist/es/fields/CheckboxGroup.vue_vue_type_script_setup_true_lang.js +6 -3
- package/dist/es/fields/ColorPicker.vue_vue_type_script_setup_true_lang.js +5 -2
- package/dist/es/fields/Date.vue_vue_type_script_setup_true_lang.js +6 -3
- package/dist/es/fields/DateTime.vue_vue_type_script_setup_true_lang.js +6 -3
- package/dist/es/fields/Daterange.vue_vue_type_script_setup_true_lang.js +6 -3
- package/dist/es/fields/Display.vue_vue_type_script_setup_true_lang.js +6 -3
- package/dist/es/fields/DynamicField.vue_vue_type_script_setup_true_lang.js +5 -2
- 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 +30 -8
- package/dist/es/fields/Number.vue_vue_type_script_setup_true_lang.js +8 -3
- package/dist/es/fields/NumberRange.vue_vue_type_script_setup_true_lang.js +5 -2
- package/dist/es/fields/RadioGroup.vue_vue_type_script_setup_true_lang.js +21 -10
- package/dist/es/fields/Select.vue_vue_type_script_setup_true_lang.js +7 -3
- package/dist/es/fields/Switch.vue_vue_type_script_setup_true_lang.js +5 -2
- package/dist/es/fields/Text.vue_vue_type_script_setup_true_lang.js +113 -78
- package/dist/es/fields/Textarea.vue_vue_type_script_setup_true_lang.js +5 -2
- package/dist/es/fields/Time.vue_vue_type_script_setup_true_lang.js +5 -2
- package/dist/es/fields/Timerange.vue_vue_type_script_setup_true_lang.js +7 -4
- package/dist/es/index.js +5 -4
- package/dist/es/plugin.js +4 -0
- package/dist/es/schema.js +12 -1
- package/dist/es/style.css +133 -11
- package/dist/es/submitForm.js +415 -56
- package/dist/es/utils/config.js +4 -1
- package/dist/es/utils/form.js +84 -9
- package/dist/es/utils/typeMatch.js +487 -0
- package/dist/style.css +133 -11
- package/dist/themes/magic-admin.css +509 -0
- package/dist/tmagic-form.umd.cjs +1773 -399
- package/package.json +5 -5
- package/src/Form.vue +163 -30
- package/src/FormBox.vue +11 -0
- package/src/FormDialog.vue +25 -3
- package/src/FormDrawer.vue +51 -12
- package/src/containers/Col.vue +1 -0
- package/src/containers/Container.vue +32 -11
- package/src/containers/Fieldset.vue +5 -2
- package/src/containers/GroupList.vue +1 -1
- package/src/containers/GroupListItem.vue +28 -22
- package/src/containers/Panel.vue +10 -3
- package/src/containers/table/ActionsColumn.vue +10 -4
- package/src/containers/table/Table.vue +1 -0
- package/src/containers/table/useTableColumns.ts +7 -3
- package/src/containers/table-group-list/TableGroupList.vue +7 -1
- package/src/fields/Link.vue +16 -3
- package/src/fields/Number.vue +2 -1
- package/src/fields/RadioGroup.vue +24 -6
- package/src/fields/Text.vue +43 -19
- package/src/index.ts +11 -0
- package/src/plugin.ts +12 -0
- package/src/schema.ts +13 -1
- package/src/submitForm.ts +699 -66
- package/src/theme/container.scss +3 -0
- package/src/theme/fieldset.scss +51 -0
- package/src/theme/form-dialog.scss +1 -1
- package/src/theme/form.scss +6 -0
- package/src/theme/group-list.scss +19 -8
- package/src/theme/index.scss +1 -0
- package/src/theme/link.scss +17 -0
- package/src/theme/panel.scss +1 -1
- package/src/theme/radio-group.scss +23 -0
- package/src/theme/table.scss +11 -1
- package/src/theme/tabs.scss +2 -2
- package/src/theme/text.scss +38 -0
- package/src/theme/themes/magic-admin/index.scss +106 -0
- package/src/utils/config.ts +7 -1
- package/src/utils/form.ts +144 -22
- package/src/utils/typeMatch.ts +870 -0
- package/types/index.d.ts +408 -21
|
@@ -5,7 +5,9 @@
|
|
|
5
5
|
:class="`m-form-container m-container-${type || ''} ${config.className || ''}${config.tip ? ' has-tip' : ''}`"
|
|
6
6
|
:style="config.style"
|
|
7
7
|
>
|
|
8
|
-
<
|
|
8
|
+
<TMagicFormItem v-if="type === 'hidden'" v-bind="formItemProps" style="display: none">
|
|
9
|
+
<MHidden :name="`${name}`" :prop="itemProp" :model="model"></MHidden>
|
|
10
|
+
</TMagicFormItem>
|
|
9
11
|
|
|
10
12
|
<component
|
|
11
13
|
v-else-if="items && !text && type && display"
|
|
@@ -33,6 +35,9 @@
|
|
|
33
35
|
:label-title="config.labelTitle"
|
|
34
36
|
:text="text"
|
|
35
37
|
></FormLabel>
|
|
38
|
+
<span class="m-form-tip m-form-title-extra" v-if="config.titleExtra && config.labelPosition === 'top'">
|
|
39
|
+
{{ config.titleExtra }}</span
|
|
40
|
+
>
|
|
36
41
|
</slot>
|
|
37
42
|
</template>
|
|
38
43
|
|
|
@@ -220,17 +225,23 @@
|
|
|
220
225
|
</template>
|
|
221
226
|
</template>
|
|
222
227
|
|
|
223
|
-
<div
|
|
224
|
-
<TMagicButton
|
|
225
|
-
|
|
226
|
-
|
|
228
|
+
<div class="m-form-container-expand" v-if="config.expand && type !== 'fieldset'">
|
|
229
|
+
<TMagicButton
|
|
230
|
+
type="primary"
|
|
231
|
+
size="small"
|
|
232
|
+
:disabled="false"
|
|
233
|
+
link
|
|
234
|
+
@click="expandHandler"
|
|
235
|
+
:icon="expand ? ArrowUp : ArrowDown"
|
|
236
|
+
>{{ expand ? '收起配置' : '展开更多配置' }}</TMagicButton
|
|
237
|
+
>
|
|
227
238
|
</div>
|
|
228
239
|
</div>
|
|
229
240
|
</template>
|
|
230
241
|
|
|
231
242
|
<script setup lang="ts">
|
|
232
|
-
import { computed, inject, readonly, ref, toRaw, watch, watchEffect } from 'vue';
|
|
233
|
-
import { WarningFilled } from '@element-plus/icons-vue';
|
|
243
|
+
import { computed, inject, provide, readonly, ref, toRaw, watch, watchEffect } from 'vue';
|
|
244
|
+
import { ArrowDown, ArrowUp, WarningFilled } from '@element-plus/icons-vue';
|
|
234
245
|
import { isEqual } from 'lodash-es';
|
|
235
246
|
|
|
236
247
|
import { TMagicButton, TMagicFormItem, TMagicIcon, TMagicTooltip } from '@tmagic/design';
|
|
@@ -249,7 +260,7 @@ import type {
|
|
|
249
260
|
FormValue,
|
|
250
261
|
ToolTipConfigType,
|
|
251
262
|
} from '../schema';
|
|
252
|
-
import { FORM_DIFF_CONFIG_KEY } from '../schema';
|
|
263
|
+
import { FORM_DIFF_CONFIG_KEY, FORM_TYPE_MATCH_VALID_KEY } from '../schema';
|
|
253
264
|
import { getField } from '../utils/config';
|
|
254
265
|
import { createObjectProp, display as displayFunction, filterFunction, getRules } from '../utils/form';
|
|
255
266
|
|
|
@@ -276,6 +287,8 @@ const props = withDefaults(
|
|
|
276
287
|
size?: string;
|
|
277
288
|
/** 是否开启对比模式 */
|
|
278
289
|
isCompare?: boolean;
|
|
290
|
+
/** 是否在行容器中 */
|
|
291
|
+
isInRow?: boolean;
|
|
279
292
|
}>(),
|
|
280
293
|
{
|
|
281
294
|
prop: '',
|
|
@@ -296,6 +309,8 @@ const mForm = inject<FormState | undefined>('mForm');
|
|
|
296
309
|
// 对比相关配置由 MForm 通过 provide 下发,这里直接 inject,无需逐层透传 prop。
|
|
297
310
|
const diffConfig = inject<FormDiffConfig>(FORM_DIFF_CONFIG_KEY, {});
|
|
298
311
|
|
|
312
|
+
const typeMatchValid = inject(FORM_TYPE_MATCH_VALID_KEY);
|
|
313
|
+
|
|
299
314
|
const expand = ref(false);
|
|
300
315
|
|
|
301
316
|
const name = computed(() => props.config.name || '');
|
|
@@ -307,8 +322,10 @@ const name = computed(() => props.config.name || '');
|
|
|
307
322
|
// 便于业务侧自定义"语义上相等"的特殊场景(例如空字符串与空 hook 结构)。
|
|
308
323
|
const showDiff = computed(() => {
|
|
309
324
|
if (!props.isCompare) return false;
|
|
310
|
-
|
|
311
|
-
|
|
325
|
+
if (!name.value) return false;
|
|
326
|
+
|
|
327
|
+
const curValue = props.model[name.value];
|
|
328
|
+
const lastValue = props.lastValues[name.value];
|
|
312
329
|
|
|
313
330
|
const customShowDiff = diffConfig.showDiff;
|
|
314
331
|
if (typeof customShowDiff === 'function') {
|
|
@@ -409,7 +426,7 @@ const tooltip = computed(() => {
|
|
|
409
426
|
};
|
|
410
427
|
});
|
|
411
428
|
|
|
412
|
-
const rule = computed(() => getRules(mForm, props.config.rules, props));
|
|
429
|
+
const rule = computed(() => getRules(mForm, props.config.rules, props, typeMatchValid));
|
|
413
430
|
|
|
414
431
|
const display = computed((): boolean => {
|
|
415
432
|
const value = displayFunction(mForm, props.config.display, props);
|
|
@@ -434,8 +451,10 @@ const formItemProps = computed(() => ({
|
|
|
434
451
|
prop: itemProp.value,
|
|
435
452
|
labelWidth: itemLabelWidth.value,
|
|
436
453
|
labelPosition: props.config.labelPosition,
|
|
454
|
+
|
|
437
455
|
rules: rule.value,
|
|
438
456
|
extra: filterFunction(mForm, props.config.extra, props),
|
|
457
|
+
extraTips: props.config.extraTips,
|
|
439
458
|
}));
|
|
440
459
|
|
|
441
460
|
const itemLabelWidth = computed(() => props.config.labelWidth ?? props.labelWidth);
|
|
@@ -459,6 +478,8 @@ watch(
|
|
|
459
478
|
},
|
|
460
479
|
);
|
|
461
480
|
|
|
481
|
+
provide('isInRow', props.isInRow ?? false);
|
|
482
|
+
|
|
462
483
|
const expandHandler = () => (expand.value = !expand.value);
|
|
463
484
|
|
|
464
485
|
const key = (config: any) => config[mForm?.keyProps];
|
|
@@ -7,11 +7,11 @@
|
|
|
7
7
|
:true-value="checkboxTrueValue"
|
|
8
8
|
:false-value="checkboxFalseValue"
|
|
9
9
|
@update:modelValue="valueChangeHandler"
|
|
10
|
-
><span v-html="
|
|
10
|
+
><span v-html="legend"></span><span v-if="config.extra" v-html="config.extra" class="m-form-tip"></span
|
|
11
11
|
></TMagicCheckbox>
|
|
12
12
|
</component>
|
|
13
13
|
<legend v-else>
|
|
14
|
-
<span v-html="
|
|
14
|
+
<span v-html="legend"></span>
|
|
15
15
|
<span v-if="config.extra" v-html="config.extra" class="m-form-tip"></span>
|
|
16
16
|
</legend>
|
|
17
17
|
|
|
@@ -63,6 +63,7 @@ import { computed, inject } from 'vue';
|
|
|
63
63
|
import { TMagicCheckbox } from '@tmagic/design';
|
|
64
64
|
|
|
65
65
|
import { ContainerChangeEventData, FieldsetConfig, FormState } from '../schema';
|
|
66
|
+
import { filterFunction } from '../utils/form';
|
|
66
67
|
|
|
67
68
|
import Container from './Container.vue';
|
|
68
69
|
|
|
@@ -99,6 +100,8 @@ const mForm = inject<FormState | undefined>('mForm');
|
|
|
99
100
|
|
|
100
101
|
const name = computed(() => props.config.name || '');
|
|
101
102
|
|
|
103
|
+
const legend = computed(() => filterFunction<string>(mForm, props.config.legend, props));
|
|
104
|
+
|
|
102
105
|
const checkboxName = computed(() => {
|
|
103
106
|
if (typeof props.config.checkbox === 'object' && typeof props.config.checkbox.name === 'string') {
|
|
104
107
|
return props.config.checkbox.name;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<div class="m-fields-group-list">
|
|
3
3
|
<div v-if="config.extra" v-html="config.extra" style="color: rgba(0, 0, 0, 0.45)"></div>
|
|
4
4
|
<div v-if="!model[name] || !model[name].length" class="el-table__empty-block">
|
|
5
|
-
<span class="el-table__empty-text t-table__empty"
|
|
5
|
+
<span class="el-table__empty-text t-table__empty">暂无{{ config.titlePrefix || '' }}数据</span>
|
|
6
6
|
</div>
|
|
7
7
|
|
|
8
8
|
<MFieldsGroupListItem
|
|
@@ -1,26 +1,29 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<TMagicCard class="m-fields-group-list-item" :body-style="{ display: expand ? 'block' : 'none' }">
|
|
2
|
+
<TMagicCard class="m-fields-group-list-item" :flat="config.flat" :body-style="{ display: expand ? 'block' : 'none' }">
|
|
3
3
|
<template #header>
|
|
4
|
-
<div>
|
|
5
|
-
<TMagicButton link :disabled="disabled" @click="expandHandler">
|
|
6
|
-
<TMagicIcon><
|
|
4
|
+
<div class="m-fields-group-list-item-header">
|
|
5
|
+
<TMagicButton link :disabled="disabled" @click="expandHandler" class="expand-button">
|
|
6
|
+
<TMagicIcon><ArrowDown v-if="expand" /><ArrowRight v-else /></TMagicIcon>
|
|
7
7
|
</TMagicButton>
|
|
8
8
|
|
|
9
|
-
<
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
9
|
+
<span v-html="title"></span>
|
|
10
|
+
<TMagicTooltip :content="`删除 ${title}`">
|
|
11
|
+
<TMagicButton
|
|
12
|
+
v-if="!isCompare"
|
|
13
|
+
v-show="showDelete"
|
|
14
|
+
size="default"
|
|
15
|
+
link
|
|
16
|
+
class="delete-button"
|
|
17
|
+
:icon="Delete"
|
|
18
|
+
:disabled="disabled"
|
|
19
|
+
@click="removeHandler"
|
|
20
|
+
></TMagicButton>
|
|
21
|
+
</TMagicTooltip>
|
|
19
22
|
|
|
20
23
|
<TMagicButton
|
|
21
24
|
v-if="copyable && !isCompare"
|
|
22
25
|
link
|
|
23
|
-
size="
|
|
26
|
+
size="default"
|
|
24
27
|
type="primary"
|
|
25
28
|
:icon="DocumentCopy"
|
|
26
29
|
:disabled="disabled"
|
|
@@ -32,18 +35,18 @@
|
|
|
32
35
|
<TMagicButton
|
|
33
36
|
v-show="index !== 0"
|
|
34
37
|
link
|
|
35
|
-
size="
|
|
38
|
+
size="default"
|
|
36
39
|
:disabled="disabled"
|
|
37
|
-
:icon="
|
|
40
|
+
:icon="Top"
|
|
38
41
|
@click="changeOrder(-1)"
|
|
39
42
|
>上移</TMagicButton
|
|
40
43
|
>
|
|
41
44
|
<TMagicButton
|
|
42
45
|
v-show="index !== length - 1"
|
|
43
46
|
link
|
|
44
|
-
size="
|
|
47
|
+
size="default"
|
|
45
48
|
:disabled="disabled"
|
|
46
|
-
:icon="
|
|
49
|
+
:icon="Bottom"
|
|
47
50
|
@click="changeOrder(1)"
|
|
48
51
|
>下移</TMagicButton
|
|
49
52
|
>
|
|
@@ -107,9 +110,9 @@
|
|
|
107
110
|
|
|
108
111
|
<script setup lang="ts">
|
|
109
112
|
import { computed, inject, ref } from 'vue';
|
|
110
|
-
import {
|
|
113
|
+
import { ArrowDown, ArrowRight, Bottom, Delete, DocumentCopy, Position, Top } from '@element-plus/icons-vue';
|
|
111
114
|
|
|
112
|
-
import { TMagicButton, TMagicCard, TMagicIcon, TMagicInputNumber, TMagicPopover } from '@tmagic/design';
|
|
115
|
+
import { TMagicButton, TMagicCard, TMagicIcon, TMagicInputNumber, TMagicPopover, TMagicTooltip } from '@tmagic/design';
|
|
113
116
|
|
|
114
117
|
import type { ContainerChangeEventData, FormState, GroupListConfig } from '../schema';
|
|
115
118
|
import { filterFunction } from '../utils/form';
|
|
@@ -152,7 +155,10 @@ const rowConfig = computed(() => ({
|
|
|
152
155
|
|
|
153
156
|
const title = computed(() => {
|
|
154
157
|
if (props.config.titleKey && props.model[props.config.titleKey]) {
|
|
155
|
-
|
|
158
|
+
const { titlePrefix } = props.config;
|
|
159
|
+
return titlePrefix
|
|
160
|
+
? `${titlePrefix} ${String(props.index + 1)}: ${props.model[props.config.titleKey]}`
|
|
161
|
+
: `${props.model[props.config.titleKey]}`;
|
|
156
162
|
}
|
|
157
163
|
|
|
158
164
|
if (props.config.title) {
|
package/src/containers/Panel.vue
CHANGED
|
@@ -3,10 +3,17 @@
|
|
|
3
3
|
v-if="items && items.length"
|
|
4
4
|
class="box-card m-form-panel"
|
|
5
5
|
:body-style="{ display: expand ? 'block' : 'none' }"
|
|
6
|
+
:flat="config.flat"
|
|
6
7
|
>
|
|
7
8
|
<template #header>
|
|
8
9
|
<div style="width: 100%; display: flex; align-items: center">
|
|
9
|
-
<TMagicButton
|
|
10
|
+
<TMagicButton
|
|
11
|
+
style="padding: 0; margin-right: 10px"
|
|
12
|
+
link
|
|
13
|
+
:icon="expand ? ArrowDown : ArrowRight"
|
|
14
|
+
@click="expand = !expand"
|
|
15
|
+
v-if="!hideExpand"
|
|
16
|
+
>
|
|
10
17
|
</TMagicButton>
|
|
11
18
|
<slot name="header">
|
|
12
19
|
<span style="cursor: pointer" @click="expand = !expand">{{ filter(config.title) }}</span>
|
|
@@ -62,7 +69,7 @@
|
|
|
62
69
|
|
|
63
70
|
<script setup lang="ts">
|
|
64
71
|
import { computed, inject, ref } from 'vue';
|
|
65
|
-
import {
|
|
72
|
+
import { ArrowDown, ArrowRight } from '@element-plus/icons-vue';
|
|
66
73
|
|
|
67
74
|
import { TMagicButton, TMagicCard } from '@tmagic/design';
|
|
68
75
|
|
|
@@ -85,6 +92,7 @@ const props = defineProps<{
|
|
|
85
92
|
prop?: string;
|
|
86
93
|
size?: string;
|
|
87
94
|
disabled?: boolean;
|
|
95
|
+
hideExpand?: boolean;
|
|
88
96
|
}>();
|
|
89
97
|
|
|
90
98
|
const emit = defineEmits<{
|
|
@@ -107,7 +115,6 @@ const onAddDiffCount = () => emit('addDiffCount');
|
|
|
107
115
|
|
|
108
116
|
defineExpose({
|
|
109
117
|
getExpand: () => expand.value,
|
|
110
|
-
|
|
111
118
|
setExpand: (v: boolean) => {
|
|
112
119
|
expand.value = v;
|
|
113
120
|
},
|
|
@@ -9,15 +9,18 @@
|
|
|
9
9
|
>
|
|
10
10
|
</TMagicButton>
|
|
11
11
|
</TMagicTooltip>
|
|
12
|
+
|
|
12
13
|
<TMagicButton
|
|
13
14
|
v-show="showDelete(index + 1 + currentPage * pageSize - 1)"
|
|
14
15
|
size="small"
|
|
15
16
|
type="danger"
|
|
16
17
|
link
|
|
17
18
|
title="删除"
|
|
18
|
-
:icon="config.deleteActionButtonIcon || Delete"
|
|
19
|
+
:icon="flat ? undefined : config.deleteActionButtonIcon || Delete"
|
|
19
20
|
@click="removeHandler(index + 1 + currentPage * pageSize - 1)"
|
|
20
|
-
|
|
21
|
+
>
|
|
22
|
+
<template v-if="flat">删除</template>
|
|
23
|
+
</TMagicButton>
|
|
21
24
|
|
|
22
25
|
<TMagicButton
|
|
23
26
|
v-if="copyable(index + 1 + currentPage * pageSize - 1)"
|
|
@@ -25,10 +28,12 @@
|
|
|
25
28
|
size="small"
|
|
26
29
|
type="primary"
|
|
27
30
|
title="复制"
|
|
28
|
-
:icon="config.copyActionButtonIcon || DocumentCopy"
|
|
31
|
+
:icon="flat ? undefined : config.copyActionButtonIcon || DocumentCopy"
|
|
29
32
|
:disabled="disabled"
|
|
30
33
|
@click="copyHandler(index + 1 + currentPage * pageSize - 1)"
|
|
31
|
-
|
|
34
|
+
>
|
|
35
|
+
<template v-if="flat">复制</template>
|
|
36
|
+
</TMagicButton>
|
|
32
37
|
</template>
|
|
33
38
|
|
|
34
39
|
<script setup lang="ts">
|
|
@@ -53,6 +58,7 @@ const props = defineProps<{
|
|
|
53
58
|
row: any;
|
|
54
59
|
prop?: string;
|
|
55
60
|
sortKey?: string;
|
|
61
|
+
flat?: boolean;
|
|
56
62
|
}>();
|
|
57
63
|
|
|
58
64
|
const mForm = inject<FormState | undefined>('mForm');
|
|
@@ -6,6 +6,7 @@ import { type TableColumnOptions, TMagicIcon, TMagicTooltip } from '@tmagic/desi
|
|
|
6
6
|
import type { FormItemConfig, FormState, TableColumnConfig } from '@tmagic/form-schema';
|
|
7
7
|
|
|
8
8
|
import type { ContainerChangeEventData } from '../../schema';
|
|
9
|
+
import { isGlobalFlat } from '../../utils/config';
|
|
9
10
|
import { display as displayFunc, getDataByPage, sortArray } from '../../utils/form';
|
|
10
11
|
import Container from '../Container.vue';
|
|
11
12
|
|
|
@@ -111,23 +112,26 @@ export const useTableColumns = (
|
|
|
111
112
|
},
|
|
112
113
|
});
|
|
113
114
|
}
|
|
114
|
-
|
|
115
|
-
let actionFixed: 'left' | 'right' | undefined = props.config.fixed === false ? undefined :
|
|
116
|
-
|
|
115
|
+
const defaultFixed: 'left' | 'right' = isGlobalFlat.value ? 'right' : 'left';
|
|
116
|
+
let actionFixed: 'left' | 'right' | undefined = props.config.fixed === false ? undefined : defaultFixed;
|
|
117
117
|
if (typeof props.config.fixed === 'string' && ['left', 'right'].includes(props.config.fixed)) {
|
|
118
118
|
actionFixed = props.config.fixed;
|
|
119
119
|
}
|
|
120
120
|
|
|
121
|
+
const actionFlat = props.config.flat === undefined && isGlobalFlat.value ? true : props.config.flat;
|
|
122
|
+
|
|
121
123
|
const actionColumn = {
|
|
122
124
|
props: {
|
|
123
125
|
label: '操作',
|
|
124
126
|
fixed: actionFixed,
|
|
127
|
+
|
|
125
128
|
width: props.config.operateColWidth ?? (props.config.dropSortHandle && props.config.dropSort ? 132 : 112),
|
|
126
129
|
align: 'center',
|
|
127
130
|
},
|
|
128
131
|
cell: ({ row, $index }: any) =>
|
|
129
132
|
h(ActionsColumn, {
|
|
130
133
|
row,
|
|
134
|
+
flat: actionFlat,
|
|
131
135
|
index: $index,
|
|
132
136
|
model: props.model,
|
|
133
137
|
config: props.config,
|
|
@@ -37,11 +37,17 @@
|
|
|
37
37
|
:size="addButtonSize"
|
|
38
38
|
:plain="displayMode === 'table'"
|
|
39
39
|
:icon="Plus"
|
|
40
|
+
text
|
|
40
41
|
:disabled="disabled"
|
|
41
42
|
v-bind="currentConfig.addButtonConfig?.props || { type: 'primary' }"
|
|
42
43
|
@click="newHandler"
|
|
43
44
|
>
|
|
44
|
-
{{
|
|
45
|
+
{{
|
|
46
|
+
currentConfig.addButtonConfig?.text ||
|
|
47
|
+
(displayMode === 'table'
|
|
48
|
+
? `新增一行${groupListConfig.titlePrefix || ''}`
|
|
49
|
+
: `新增${groupListConfig.titlePrefix || ''}`)
|
|
50
|
+
}}
|
|
45
51
|
</TMagicButton>
|
|
46
52
|
</template>
|
|
47
53
|
</component>
|
package/src/fields/Link.vue
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<a
|
|
2
|
+
<a
|
|
3
|
+
target="_blank"
|
|
4
|
+
:href="href"
|
|
5
|
+
v-if="isGlobalFlat && config.href && !disabled"
|
|
6
|
+
class="magic-admin-link"
|
|
7
|
+
:style="config.css || {}"
|
|
8
|
+
>
|
|
9
|
+
<TMagicButton link type="primary">
|
|
10
|
+
<TMagicIcon><Notebook /></TMagicIcon>{{ displayText }}
|
|
11
|
+
</TMagicButton>
|
|
12
|
+
</a>
|
|
13
|
+
<a v-else-if="config.href && !disabled" target="_blank" :href="href" :style="config.css || {}">{{ displayText }}</a>
|
|
3
14
|
<span v-else-if="config.href && disabled" :style="config.disabledCss || {}">{{ displayText }}</span>
|
|
4
15
|
<div v-else class="m-fields-link">
|
|
5
16
|
<TMagicButton link type="primary" @click="editHandler">点击编辑</TMagicButton>
|
|
@@ -18,18 +29,20 @@
|
|
|
18
29
|
|
|
19
30
|
<script lang="ts" setup>
|
|
20
31
|
import { computed, inject, readonly, ref } from 'vue';
|
|
32
|
+
import { Notebook } from '@element-plus/icons-vue';
|
|
21
33
|
|
|
22
|
-
import { TMagicButton } from '@tmagic/design';
|
|
34
|
+
import { TMagicButton, TMagicIcon } from '@tmagic/design';
|
|
23
35
|
|
|
24
36
|
import FormDialog from '../FormDialog.vue';
|
|
25
37
|
import type { FieldProps, FormState, LinkConfig } from '../schema';
|
|
38
|
+
import { isGlobalFlat } from '../utils/config';
|
|
26
39
|
import { useAddField } from '../utils/useAddField';
|
|
27
40
|
|
|
28
41
|
defineOptions({
|
|
29
42
|
name: 'MFormLink',
|
|
30
43
|
});
|
|
31
44
|
|
|
32
|
-
const props = defineProps<FieldProps<LinkConfig
|
|
45
|
+
const props = defineProps<FieldProps<LinkConfig> & { theme?: string }>();
|
|
33
46
|
|
|
34
47
|
const emit = defineEmits(['change']);
|
|
35
48
|
|
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({
|
|
@@ -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"
|
|
@@ -8,9 +14,14 @@
|
|
|
8
14
|
@click="clickHandler(option.value)"
|
|
9
15
|
>
|
|
10
16
|
<TMagicTooltip :disabled="!Boolean(option.tooltip)" placement="top-start" :content="option.tooltip">
|
|
11
|
-
<div>
|
|
12
|
-
<TMagicIcon
|
|
13
|
-
|
|
17
|
+
<div class="m-fields-radio-group__option">
|
|
18
|
+
<TMagicIcon
|
|
19
|
+
v-if="option.icon"
|
|
20
|
+
:size="iconSize"
|
|
21
|
+
:class="{ 'm-fields-radio-group__icon_with_text': !!option.text }"
|
|
22
|
+
><component :is="option.icon"></component
|
|
23
|
+
></TMagicIcon>
|
|
24
|
+
<span v-if="option.text" class="m-fields-radio-group__text">{{ option.text }}</span>
|
|
14
25
|
</div>
|
|
15
26
|
</TMagicTooltip>
|
|
16
27
|
</component>
|
|
@@ -36,19 +47,26 @@ const itemComponent = computed(() => (props.config.childType === 'button' ? TMag
|
|
|
36
47
|
const emit = defineEmits(['change']);
|
|
37
48
|
|
|
38
49
|
const clickHandler = (item: string | number | boolean) => {
|
|
50
|
+
if (props.disabled) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
39
53
|
// 再次点击取消选中
|
|
40
54
|
emit('change', props.model[props.name] === item ? '' : item);
|
|
41
55
|
};
|
|
42
56
|
|
|
43
57
|
useAddField(props.prop);
|
|
44
58
|
|
|
59
|
+
// 这里换了设计稿里的图标,所以需要调整一下图标大小
|
|
45
60
|
const iconSize = computed(() => {
|
|
61
|
+
if (props.config.iconSize) {
|
|
62
|
+
return props.config.iconSize;
|
|
63
|
+
}
|
|
46
64
|
if (props.size === 'small') {
|
|
47
|
-
return '
|
|
65
|
+
return '14';
|
|
48
66
|
}
|
|
49
67
|
if (props.size === 'large') {
|
|
50
68
|
return '16';
|
|
51
69
|
}
|
|
52
|
-
return '
|
|
70
|
+
return '16';
|
|
53
71
|
});
|
|
54
72
|
</script>
|
package/src/fields/Text.vue
CHANGED
|
@@ -1,6 +1,31 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="m-fields-text">
|
|
2
|
+
<div :class="['m-fields-text', { 'm-fields-text--static': config.static }]">
|
|
3
|
+
<div v-if="config.disabled"></div>
|
|
4
|
+
<!-- 新增静态展示文本样式 -->
|
|
5
|
+
<template v-if="config.static">
|
|
6
|
+
<span v-if="config.prepend" class="m-fields-text__prepend">{{ config.prepend }}</span>
|
|
7
|
+
<span class="m-fields-text__value">{{ value }}</span>
|
|
8
|
+
<template v-if="appendConfig">
|
|
9
|
+
<TMagicButton
|
|
10
|
+
v-if="appendConfig.type === 'button'"
|
|
11
|
+
style="color: #0056ea"
|
|
12
|
+
:size="size"
|
|
13
|
+
@click.prevent="buttonClickHandler"
|
|
14
|
+
>
|
|
15
|
+
{{ appendConfig.text }}
|
|
16
|
+
</TMagicButton>
|
|
17
|
+
<img
|
|
18
|
+
v-else-if="appendConfig.type === 'icon'"
|
|
19
|
+
class="m-fields-text__icon"
|
|
20
|
+
:src="appendConfig.text"
|
|
21
|
+
@click="buttonClickHandler"
|
|
22
|
+
/>
|
|
23
|
+
<span v-else>{{ appendConfig.text }}</span>
|
|
24
|
+
</template>
|
|
25
|
+
</template>
|
|
26
|
+
|
|
3
27
|
<TMagicInput
|
|
28
|
+
v-else
|
|
4
29
|
v-model="value"
|
|
5
30
|
ref="input"
|
|
6
31
|
:clearable="config.clearable ?? true"
|
|
@@ -17,17 +42,18 @@
|
|
|
17
42
|
<template #append v-if="appendConfig">
|
|
18
43
|
<TMagicButton
|
|
19
44
|
v-if="appendConfig.type === 'button'"
|
|
20
|
-
style="color: #
|
|
45
|
+
style="color: #0056ea"
|
|
21
46
|
:size="size"
|
|
22
47
|
@click.prevent="buttonClickHandler"
|
|
23
48
|
>
|
|
24
49
|
{{ appendConfig.text }}
|
|
25
50
|
</TMagicButton>
|
|
51
|
+
<img v-else-if="appendConfig.type === 'icon'" :src="appendConfig.text" @click="buttonClickHandler" />
|
|
26
52
|
<span v-else>{{ appendConfig.text }}</span>
|
|
27
53
|
</template>
|
|
28
54
|
</TMagicInput>
|
|
29
55
|
|
|
30
|
-
<Teleport to="body">
|
|
56
|
+
<Teleport to="body" v-if="!config.static">
|
|
31
57
|
<div v-if="popoverVisible" class="tmagic-form-text-popper m-form-item__content" ref="popoverEl">
|
|
32
58
|
<div class="m-form-validate__warning">输入内容前后有空格,是否移除空格?</div>
|
|
33
59
|
<div style="display: flex; justify-content: flex-end">
|
|
@@ -80,28 +106,26 @@ watch(
|
|
|
80
106
|
);
|
|
81
107
|
|
|
82
108
|
const appendConfig = computed(() => {
|
|
83
|
-
|
|
109
|
+
const { append } = props.config;
|
|
110
|
+
|
|
111
|
+
// 字符串形态:纯文本 append。
|
|
112
|
+
if (typeof append === 'string') {
|
|
84
113
|
return {
|
|
85
114
|
type: 'text',
|
|
86
|
-
text:
|
|
115
|
+
text: append,
|
|
87
116
|
handler: undefined,
|
|
88
117
|
};
|
|
89
118
|
}
|
|
90
|
-
if (typeof props.config.append === 'object') {
|
|
91
|
-
if (typeof props.config.append?.handler === 'function') {
|
|
92
|
-
return {
|
|
93
|
-
type: 'button',
|
|
94
|
-
text: props.config.append.text,
|
|
95
|
-
handler: props.config.append.handler,
|
|
96
|
-
};
|
|
97
|
-
}
|
|
98
|
-
if (props.config.append) {
|
|
99
|
-
if (props.config.append.value === 0) {
|
|
100
|
-
return false;
|
|
101
|
-
}
|
|
102
119
|
|
|
103
|
-
|
|
104
|
-
|
|
120
|
+
// 对象形态:按 schema 定义,`type` 可为 `'button' | 'icon'`,`handler` 可选。
|
|
121
|
+
//
|
|
122
|
+
// 旧逻辑里只要带 handler 就强制覆盖为 `type: 'button'`,导致 schema 中显式传入的
|
|
123
|
+
// `type: 'icon'` 在到达模板前被抹掉(参见 `@editor/utils/props.ts` 中 ID 字段
|
|
124
|
+
// 的复制按钮配置)。这里直接返回原对象,模板按 `type` 分支渲染 button / icon / text。
|
|
125
|
+
if (typeof append === 'object' && append) {
|
|
126
|
+
// `value === 0` 沿用旧约定:作为「隐藏 append」的开关。
|
|
127
|
+
if (append.value === 0) return false;
|
|
128
|
+
return append;
|
|
105
129
|
}
|
|
106
130
|
|
|
107
131
|
return false;
|
package/src/index.ts
CHANGED
|
@@ -63,6 +63,17 @@ export {
|
|
|
63
63
|
registerField as registerFormField,
|
|
64
64
|
} from './utils/config';
|
|
65
65
|
|
|
66
|
+
export {
|
|
67
|
+
clearTypeMatchRules,
|
|
68
|
+
deleteTypeMatchRule,
|
|
69
|
+
getTypeMatchRule,
|
|
70
|
+
registerTypeMatchRule,
|
|
71
|
+
registerTypeMatchRules,
|
|
72
|
+
validateTypeMatch,
|
|
73
|
+
} from './utils/typeMatch';
|
|
74
|
+
|
|
75
|
+
export type { TypeMatchValidateContext, TypeMatchValidator } from './utils/typeMatch';
|
|
76
|
+
|
|
66
77
|
export type { FormInstallOptions } from './plugin';
|
|
67
78
|
|
|
68
79
|
export const createForm = <T extends [] = []>(config: FormConfig | T) => config;
|