@tmagic/form 1.4.8 → 1.4.9

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.
Files changed (57) hide show
  1. package/package.json +5 -5
  2. package/src/Form.vue +201 -0
  3. package/src/FormBox.vue +120 -0
  4. package/src/FormDialog.vue +173 -0
  5. package/src/FormDrawer.vue +159 -0
  6. package/src/containers/Col.vue +52 -0
  7. package/src/containers/Container.vue +408 -0
  8. package/src/containers/Fieldset.vue +124 -0
  9. package/src/containers/GroupList.vue +139 -0
  10. package/src/containers/GroupListItem.vue +135 -0
  11. package/src/containers/Panel.vue +99 -0
  12. package/src/containers/Row.vue +54 -0
  13. package/src/containers/Step.vue +82 -0
  14. package/src/containers/Table.vue +648 -0
  15. package/src/containers/Tabs.vue +226 -0
  16. package/src/fields/Cascader.vue +131 -0
  17. package/src/fields/Checkbox.vue +58 -0
  18. package/src/fields/CheckboxGroup.vue +43 -0
  19. package/src/fields/ColorPicker.vue +30 -0
  20. package/src/fields/Date.vue +38 -0
  21. package/src/fields/DateTime.vue +47 -0
  22. package/src/fields/Daterange.vue +99 -0
  23. package/src/fields/Display.vue +21 -0
  24. package/src/fields/DynamicField.vue +90 -0
  25. package/src/fields/Hidden.vue +16 -0
  26. package/src/fields/Link.vue +86 -0
  27. package/src/fields/Number.vue +49 -0
  28. package/src/fields/NumberRange.vue +50 -0
  29. package/src/fields/RadioGroup.vue +28 -0
  30. package/src/fields/Select.vue +449 -0
  31. package/src/fields/Switch.vue +59 -0
  32. package/src/fields/Text.vue +170 -0
  33. package/src/fields/Textarea.vue +46 -0
  34. package/src/fields/Time.vue +34 -0
  35. package/src/fields/Timerange.vue +76 -0
  36. package/src/index.ts +139 -0
  37. package/src/schema.ts +757 -0
  38. package/src/shims-vue.d.ts +6 -0
  39. package/src/theme/date-time.scss +7 -0
  40. package/src/theme/fieldset.scss +28 -0
  41. package/src/theme/form-box.scss +13 -0
  42. package/src/theme/form-dialog.scss +13 -0
  43. package/src/theme/form-drawer.scss +11 -0
  44. package/src/theme/form.scss +43 -0
  45. package/src/theme/group-list.scss +23 -0
  46. package/src/theme/index.scss +14 -0
  47. package/src/theme/link.scss +3 -0
  48. package/src/theme/number-range.scss +8 -0
  49. package/src/theme/panel.scss +24 -0
  50. package/src/theme/select.scss +3 -0
  51. package/src/theme/table.scss +70 -0
  52. package/src/theme/tabs.scss +27 -0
  53. package/src/theme/text.scss +6 -0
  54. package/src/utils/config.ts +27 -0
  55. package/src/utils/containerProps.ts +50 -0
  56. package/src/utils/form.ts +268 -0
  57. package/src/utils/useAddField.ts +40 -0
@@ -0,0 +1,139 @@
1
+ <template>
2
+ <div class="m-fields-group-list">
3
+ <div v-if="config.extra" v-html="config.extra" style="color: rgba(0, 0, 0, 0.45)"></div>
4
+ <div v-if="!model[name] || !model[name].length" class="el-table__empty-block">
5
+ <span class="el-table__empty-text">暂无数据</span>
6
+ </div>
7
+
8
+ <MFieldsGroupListItem
9
+ v-else
10
+ v-for="(item, index) in model[name]"
11
+ :key="index"
12
+ :model="item"
13
+ :lastValues="getLastValues(lastValues[name], index)"
14
+ :is-compare="isCompare"
15
+ :config="config"
16
+ :prop="prop"
17
+ :index="index"
18
+ :label-width="labelWidth"
19
+ :size="size"
20
+ :disabled="disabled"
21
+ :group-model="model[name]"
22
+ @remove-item="removeHandler"
23
+ @swap-item="swapHandler"
24
+ @change="changeHandler"
25
+ @addDiffCount="onAddDiffCount()"
26
+ ></MFieldsGroupListItem>
27
+
28
+ <TMagicButton @click="addHandler" size="small" :disabled="disabled" v-if="addable">新增</TMagicButton>
29
+
30
+ <TMagicButton :icon="Grid" size="small" @click="toggleMode" v-if="config.enableToggleMode">切换为表格</TMagicButton>
31
+ </div>
32
+ </template>
33
+
34
+ <script setup lang="ts">
35
+ import { computed, inject } from 'vue';
36
+ import { Grid } from '@element-plus/icons-vue';
37
+
38
+ import { TMagicButton } from '@tmagic/design';
39
+
40
+ import { FormState, GroupListConfig } from '../schema';
41
+ import { initValue } from '../utils/form';
42
+
43
+ import MFieldsGroupListItem from './GroupListItem.vue';
44
+
45
+ defineOptions({
46
+ name: 'MFormGroupList',
47
+ });
48
+
49
+ const props = defineProps<{
50
+ model: any;
51
+ lastValues?: any;
52
+ isCompare?: boolean;
53
+ config: GroupListConfig;
54
+ name: string;
55
+ labelWidth?: string;
56
+ prop?: string;
57
+ size?: string;
58
+ disabled?: boolean;
59
+ }>();
60
+
61
+ const emit = defineEmits(['change', 'addDiffCount']);
62
+
63
+ const mForm = inject<FormState | undefined>('mForm');
64
+
65
+ const addable = computed(() => {
66
+ if (!props.name) return false;
67
+
68
+ if (typeof props.config.addable === 'function') {
69
+ return props.config.addable(mForm, {
70
+ model: props.model[props.name],
71
+ formValue: mForm?.values,
72
+ prop: props.prop,
73
+ config: props.config,
74
+ });
75
+ }
76
+
77
+ return typeof props.config.addable === 'undefined' ? true : props.config.addable;
78
+ });
79
+
80
+ const changeHandler = () => {
81
+ if (!props.name) return false;
82
+
83
+ emit('change', props.model[props.name]);
84
+ };
85
+
86
+ const addHandler = async () => {
87
+ if (!props.name) return false;
88
+
89
+ let initValues = {};
90
+
91
+ if (typeof props.config.defaultAdd === 'function') {
92
+ initValues = await props.config.defaultAdd(mForm, {
93
+ model: props.model[props.name],
94
+ formValue: mForm?.values,
95
+ prop: props.prop,
96
+ config: props.config,
97
+ });
98
+ } else if (props.config.defaultAdd) {
99
+ initValues = props.config.defaultAdd;
100
+ }
101
+
102
+ const groupValue = await initValue(mForm, {
103
+ config: props.config.items,
104
+ initValues,
105
+ });
106
+
107
+ props.model[props.name].push(groupValue);
108
+ };
109
+
110
+ const removeHandler = (index: number) => {
111
+ if (!props.name) return false;
112
+
113
+ props.model[props.name].splice(index, 1);
114
+ changeHandler();
115
+ };
116
+
117
+ const swapHandler = (idx1: number, idx2: number) => {
118
+ if (!props.name) return false;
119
+
120
+ const [currRow] = props.model[props.name].splice(idx1, 1);
121
+ props.model[props.name].splice(idx2, 0, currRow);
122
+ changeHandler();
123
+ };
124
+
125
+ const toggleMode = () => {
126
+ props.config.type = 'table';
127
+ props.config.groupItems = props.config.items;
128
+ props.config.items = (props.config.tableItems ||
129
+ props.config.items.map((item: any) => ({
130
+ ...item,
131
+ label: item.label || item.text,
132
+ text: null,
133
+ }))) as any;
134
+ };
135
+
136
+ const onAddDiffCount = () => emit('addDiffCount');
137
+
138
+ const getLastValues = (item: any, index: number) => item?.[index] || {};
139
+ </script>
@@ -0,0 +1,135 @@
1
+ <template>
2
+ <div class="m-fields-group-list-item">
3
+ <div>
4
+ <TMagicButton link :disabled="disabled" @click="expandHandler">
5
+ <TMagicIcon><CaretBottom v-if="expand" /><CaretRight v-else /></TMagicIcon>{{ title }}
6
+ </TMagicButton>
7
+
8
+ <TMagicButton
9
+ v-show="showDelete(parseInt(String(index)))"
10
+ style="color: #f56c6c"
11
+ link
12
+ :icon="Delete"
13
+ :disabled="disabled"
14
+ @click="removeHandler"
15
+ ></TMagicButton>
16
+
17
+ <template v-if="movable()">
18
+ <TMagicButton v-show="index !== 0" link :disabled="disabled" size="small" @click="changeOrder(-1)"
19
+ >上移<TMagicIcon><CaretTop /></TMagicIcon
20
+ ></TMagicButton>
21
+ <TMagicButton v-show="index !== length - 1" :disabled="disabled" link size="small" @click="changeOrder(1)"
22
+ >下移<TMagicIcon><CaretBottom /></TMagicIcon
23
+ ></TMagicButton>
24
+ </template>
25
+
26
+ <span v-if="itemExtra" v-html="itemExtra" class="m-form-tip"></span>
27
+ </div>
28
+
29
+ <Container
30
+ v-if="expand"
31
+ :config="rowConfig"
32
+ :model="model"
33
+ :lastValues="lastValues"
34
+ :is-compare="isCompare"
35
+ :labelWidth="labelWidth"
36
+ :prop="`${prop}${prop ? '.' : ''}${String(index)}`"
37
+ :size="size"
38
+ :disabled="disabled"
39
+ @change="changeHandler"
40
+ @addDiffCount="onAddDiffCount()"
41
+ ></Container>
42
+ </div>
43
+ </template>
44
+
45
+ <script setup lang="ts">
46
+ import { computed, inject, ref } from 'vue';
47
+ import { CaretBottom, CaretRight, CaretTop, Delete } from '@element-plus/icons-vue';
48
+
49
+ import { TMagicButton, TMagicIcon } from '@tmagic/design';
50
+
51
+ import { FormState, GroupListConfig } from '../schema';
52
+ import { filterFunction } from '../utils/form';
53
+
54
+ import Container from './Container.vue';
55
+
56
+ defineOptions({
57
+ name: 'MFormGroupListItem',
58
+ });
59
+
60
+ const props = defineProps<{
61
+ model: any;
62
+ lastValues: any;
63
+ isCompare?: boolean;
64
+ groupModel: any[];
65
+ config: GroupListConfig;
66
+ labelWidth?: string;
67
+ prop?: string;
68
+ size?: string;
69
+ index: number;
70
+ disabled?: boolean;
71
+ }>();
72
+
73
+ const emit = defineEmits(['swap-item', 'remove-item', 'change', 'addDiffCount']);
74
+
75
+ const mForm = inject<FormState | undefined>('mForm');
76
+ const expand = ref(props.config.expandAll || !props.index);
77
+
78
+ const rowConfig = computed(() => ({
79
+ type: 'row',
80
+ span: props.config.span || 24,
81
+ items: props.config.items,
82
+ labelWidth: props.config.labelWidth,
83
+ [mForm?.keyProp || '__key']: `${props.config[mForm?.keyProp || '__key']}${String(props.index)}`,
84
+ }));
85
+
86
+ const title = computed(() => {
87
+ if (props.config.titleKey && props.model[props.config.titleKey]) {
88
+ return props.model[props.config.titleKey];
89
+ }
90
+
91
+ if (props.config.title) {
92
+ return filterFunction(mForm, props.config.title, props);
93
+ }
94
+
95
+ const titlePrefix = props.config.titlePrefix || '组';
96
+
97
+ return `${titlePrefix} ${String(props.index + 1)}`;
98
+ });
99
+
100
+ const length = computed(() => props.groupModel?.length || 0);
101
+
102
+ const itemExtra = computed(() => filterFunction(mForm, props.config.itemExtra, props));
103
+
104
+ const removeHandler = () => emit('remove-item', props.index);
105
+
106
+ const changeHandler = () => emit('change');
107
+
108
+ const expandHandler = () => {
109
+ expand.value = !expand.value;
110
+ };
111
+
112
+ // 希望支持单行可控制是否显示删除按钮,不会影响现有逻辑
113
+ const showDelete = (index: number) => {
114
+ const deleteFunc = props.config.delete;
115
+ if (deleteFunc && typeof deleteFunc === 'function') {
116
+ return deleteFunc(props.model, index, mForm?.values);
117
+ }
118
+ return true;
119
+ };
120
+
121
+ // 调换顺序
122
+ const changeOrder = (offset = 0) => emit('swap-item', props.index, props.index + offset);
123
+
124
+ const movable = () => {
125
+ const { movable } = props.config;
126
+
127
+ // 没有设置时,默认可移动
128
+ if (movable === undefined) return true;
129
+ if (typeof movable === 'function') {
130
+ return movable(mForm, props.index || 0, props.model, props.groupModel);
131
+ }
132
+ return movable;
133
+ };
134
+ const onAddDiffCount = () => emit('addDiffCount');
135
+ </script>
@@ -0,0 +1,99 @@
1
+ <template>
2
+ <TMagicCard
3
+ v-if="items && items.length"
4
+ class="box-card m-form-panel"
5
+ :body-style="{ display: expand ? 'block' : 'none' }"
6
+ >
7
+ <template #header>
8
+ <div style="width: 100%; display: flex; align-items: center">
9
+ <TMagicButton style="padding: 0" link :icon="expand ? CaretBottom : CaretRight" @click="expand = !expand">
10
+ </TMagicButton>
11
+ <span v-if="config && config.extra" v-html="config.extra" class="m-form-tip"></span>
12
+ <slot name="header">{{ filter(config.title) }}</slot>
13
+ </div>
14
+ </template>
15
+
16
+ <div>
17
+ <slot></slot>
18
+
19
+ <div v-if="config.schematic" style="display: flex">
20
+ <div style="flex: 1">
21
+ <Container
22
+ v-for="(item, index) in items"
23
+ :key="item[mForm?.keyProp || '__key'] ?? index"
24
+ :config="item"
25
+ :model="name ? model[name] : model"
26
+ :lastValues="name ? lastValues[name] : lastValues"
27
+ :is-compare="isCompare"
28
+ :prop="prop"
29
+ :size="size"
30
+ :disabled="disabled"
31
+ :label-width="config.labelWidth || labelWidth"
32
+ @change="changeHandler"
33
+ @addDiffCount="onAddDiffCount()"
34
+ ></Container>
35
+ </div>
36
+
37
+ <img class="m-form-schematic" :src="config.schematic" />
38
+ </div>
39
+
40
+ <template v-else>
41
+ <Container
42
+ v-for="(item, index) in items"
43
+ :key="item[mForm?.keyProp || '__key'] ?? index"
44
+ :config="item"
45
+ :model="name ? model[name] : model"
46
+ :lastValues="name ? lastValues[name] : lastValues"
47
+ :is-compare="isCompare"
48
+ :prop="prop"
49
+ :size="size"
50
+ :disabled="disabled"
51
+ :label-width="config.labelWidth || labelWidth"
52
+ @change="changeHandler"
53
+ @addDiffCount="onAddDiffCount()"
54
+ ></Container>
55
+ </template>
56
+ </div>
57
+ </TMagicCard>
58
+ </template>
59
+
60
+ <script setup lang="ts">
61
+ import { computed, inject, ref } from 'vue';
62
+ import { CaretBottom, CaretRight } from '@element-plus/icons-vue';
63
+
64
+ import { TMagicButton, TMagicCard } from '@tmagic/design';
65
+
66
+ import { FormState, PanelConfig } from '../schema';
67
+ import { filterFunction } from '../utils/form';
68
+
69
+ import Container from './Container.vue';
70
+
71
+ defineOptions({
72
+ name: 'MFormPanel',
73
+ });
74
+
75
+ const props = defineProps<{
76
+ model: any;
77
+ lastValues?: any;
78
+ isCompare?: boolean;
79
+ config: PanelConfig;
80
+ name?: string;
81
+ labelWidth?: string;
82
+ prop?: string;
83
+ size?: string;
84
+ disabled?: boolean;
85
+ }>();
86
+
87
+ const emit = defineEmits(['change', 'addDiffCount']);
88
+
89
+ const mForm = inject<FormState | undefined>('mForm');
90
+
91
+ const expand = ref(props.config.expand !== false);
92
+
93
+ const items = computed(() => props.config.items);
94
+
95
+ const filter = (config: any) => filterFunction(mForm, config, props);
96
+
97
+ const changeHandler = () => emit('change', props.model);
98
+ const onAddDiffCount = () => emit('addDiffCount');
99
+ </script>
@@ -0,0 +1,54 @@
1
+ <template>
2
+ <TMagicRow :gutter="10">
3
+ <Col
4
+ v-for="(col, index) in config.items"
5
+ :key="col[mForm?.keyProp || '__key'] ?? index"
6
+ :span="col.span || config.span || 24 / config.items.length"
7
+ :config="col"
8
+ :labelWidth="config.labelWidth || labelWidth"
9
+ :expandMore="expandMore"
10
+ :model="name ? model[name] : model"
11
+ :lastValues="name ? lastValues[name] : lastValues"
12
+ :is-compare="isCompare"
13
+ :prop="prop"
14
+ :size="size"
15
+ :disabled="disabled"
16
+ @change="changeHandler"
17
+ @add-diff-count="onAddDiffCount"
18
+ />
19
+ </TMagicRow>
20
+ </template>
21
+
22
+ <script setup lang="ts">
23
+ import { inject } from 'vue';
24
+
25
+ import { TMagicRow } from '@tmagic/design';
26
+
27
+ import { FormState, RowConfig } from '../schema';
28
+
29
+ import Col from './Col.vue';
30
+
31
+ defineOptions({
32
+ name: 'MFormRow',
33
+ });
34
+
35
+ const props = defineProps<{
36
+ model: any;
37
+ lastValues?: any;
38
+ isCompare?: boolean;
39
+ config: RowConfig;
40
+ name: string;
41
+ labelWidth?: string;
42
+ prop?: string;
43
+ size?: string;
44
+ expandMore?: boolean;
45
+ disabled?: boolean;
46
+ }>();
47
+
48
+ const emit = defineEmits(['change', 'addDiffCount']);
49
+
50
+ const mForm = inject<FormState | undefined>('mForm');
51
+
52
+ const changeHandler = () => emit('change', props.name ? props.model[props.name] : props.model);
53
+ const onAddDiffCount = () => emit('addDiffCount');
54
+ </script>
@@ -0,0 +1,82 @@
1
+ <template>
2
+ <div>
3
+ <TMagicSteps :active="active" align-center :space="config.space">
4
+ <TMagicStep
5
+ v-for="(item, index) in config.items"
6
+ :key="item.__key"
7
+ :title="item.title"
8
+ :active="active"
9
+ @click="stepClick(index)"
10
+ ></TMagicStep>
11
+ </TMagicSteps>
12
+
13
+ <template v-for="(step, index) in config.items">
14
+ <template v-for="item in step.items">
15
+ <Container
16
+ v-if="item"
17
+ v-show="active - 1 === index"
18
+ :key="item[mForm?.keyProp || '__key']"
19
+ :config="item"
20
+ :model="step.name ? model[step.name] : model"
21
+ :lastValues="step.name ? lastValues[step.name] : lastValues"
22
+ :is-compare="isCompare"
23
+ :prop="`${step.name}`"
24
+ :size="size"
25
+ :disabled="disabled"
26
+ :label-width="config.labelWidth || labelWidth"
27
+ @change="changeHandler"
28
+ @addDiffCount="onAddDiffCount()"
29
+ ></Container>
30
+ </template>
31
+ </template>
32
+ </div>
33
+ </template>
34
+
35
+ <script setup lang="ts">
36
+ import { inject, ref, watchEffect } from 'vue';
37
+
38
+ import { TMagicStep, TMagicSteps } from '@tmagic/design';
39
+
40
+ import { FormState, StepConfig } from '../schema';
41
+
42
+ import Container from './Container.vue';
43
+
44
+ defineOptions({
45
+ name: 'MFormStep',
46
+ });
47
+
48
+ const props = withDefaults(
49
+ defineProps<{
50
+ model: any;
51
+ lastValues?: any;
52
+ isCompare?: boolean;
53
+ config: StepConfig;
54
+ stepActive?: number;
55
+ labelWidth?: string;
56
+ size?: string;
57
+ disabled?: boolean;
58
+ }>(),
59
+ {
60
+ stepActive: 1,
61
+ },
62
+ );
63
+
64
+ const emit = defineEmits(['change', 'addDiffCount']);
65
+
66
+ const mForm = inject<FormState | undefined>('mForm');
67
+ const active = ref(1);
68
+
69
+ watchEffect(() => {
70
+ active.value = props.stepActive;
71
+ });
72
+
73
+ const stepClick = (index: number) => {
74
+ active.value = index + 1;
75
+ mForm?.$emit('update:stepActive', active.value);
76
+ };
77
+
78
+ const changeHandler = () => {
79
+ emit('change', props.model);
80
+ };
81
+ const onAddDiffCount = () => emit('addDiffCount');
82
+ </script>