@tmagic/form 1.2.0-beta.2 → 1.2.0-beta.3

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 (66) hide show
  1. package/dist/tmagic-form.mjs +2081 -2500
  2. package/dist/tmagic-form.mjs.map +1 -1
  3. package/dist/tmagic-form.umd.js +2104 -2524
  4. package/dist/tmagic-form.umd.js.map +1 -1
  5. package/package.json +3 -4
  6. package/src/Form.vue +116 -159
  7. package/src/FormDialog.vue +104 -126
  8. package/src/containers/Col.vue +22 -38
  9. package/src/containers/Container.vue +135 -171
  10. package/src/containers/Fieldset.vue +11 -7
  11. package/src/containers/GroupList.vue +80 -112
  12. package/src/containers/GroupListItem.vue +87 -124
  13. package/src/containers/Panel.vue +26 -49
  14. package/src/containers/Row.vue +18 -40
  15. package/src/containers/Step.vue +36 -48
  16. package/src/containers/Table.vue +437 -478
  17. package/src/containers/Tabs.vue +89 -118
  18. package/src/fields/Cascader.vue +88 -136
  19. package/src/fields/Checkbox.vue +46 -50
  20. package/src/fields/CheckboxGroup.vue +39 -35
  21. package/src/fields/ColorPicker.vue +4 -2
  22. package/src/fields/Date.vue +20 -26
  23. package/src/fields/DateTime.vue +31 -39
  24. package/src/fields/Daterange.vue +3 -2
  25. package/src/fields/DynamicField.vue +63 -77
  26. package/src/fields/Link.vue +65 -86
  27. package/src/fields/Number.vue +32 -34
  28. package/src/fields/RadioGroup.vue +23 -23
  29. package/src/fields/Select.vue +294 -310
  30. package/src/fields/SelectOptionGroups.vue +10 -5
  31. package/src/fields/SelectOptions.vue +4 -2
  32. package/src/fields/Switch.vue +46 -49
  33. package/src/fields/Text.vue +99 -107
  34. package/src/fields/Textarea.vue +32 -44
  35. package/src/fields/Time.vue +19 -30
  36. package/src/index.ts +22 -23
  37. package/src/schema.ts +45 -12
  38. package/types/Form.vue.d.ts +213 -111
  39. package/types/FormDialog.vue.d.ts +812 -155
  40. package/types/containers/Col.vue.d.ts +94 -40
  41. package/types/containers/Container.vue.d.ts +124 -65
  42. package/types/containers/GroupList.vue.d.ts +88 -53
  43. package/types/containers/GroupListItem.vue.d.ts +99 -67
  44. package/types/containers/Panel.vue.d.ts +92 -39
  45. package/types/containers/Row.vue.d.ts +94 -39
  46. package/types/containers/Step.vue.d.ts +104 -42
  47. package/types/containers/Table.vue.d.ts +157 -130
  48. package/types/containers/Tabs.vue.d.ts +95 -50
  49. package/types/fields/Cascader.vue.d.ts +97 -71
  50. package/types/fields/Checkbox.vue.d.ts +97 -56
  51. package/types/fields/CheckboxGroup.vue.d.ts +97 -53
  52. package/types/fields/Date.vue.d.ts +97 -54
  53. package/types/fields/DateTime.vue.d.ts +97 -54
  54. package/types/fields/DynamicField.vue.d.ts +97 -64
  55. package/types/fields/Link.vue.d.ts +62 -657
  56. package/types/fields/Number.vue.d.ts +101 -56
  57. package/types/fields/RadioGroup.vue.d.ts +98 -52
  58. package/types/fields/Select.vue.d.ts +99 -65
  59. package/types/fields/Switch.vue.d.ts +97 -56
  60. package/types/fields/Text.vue.d.ts +100 -57
  61. package/types/fields/Textarea.vue.d.ts +102 -60
  62. package/types/fields/Time.vue.d.ts +97 -55
  63. package/types/index.d.ts +0 -1
  64. package/types/schema.d.ts +37 -9
  65. package/src/utils/fieldProps.ts +0 -39
  66. package/types/utils/fieldProps.d.ts +0 -21
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <el-tabs
2
+ <TMagicTabs
3
3
  v-model="activeTabName"
4
4
  :class="config.dynamic ? 'magic-form-dynamic-tab' : 'magic-form-tab'"
5
5
  :type="config.tabType"
@@ -10,14 +10,14 @@
10
10
  @tab-remove="onTabRemove"
11
11
  >
12
12
  <template v-for="(tab, tabIndex) in tabs">
13
- <el-tab-pane
13
+ <TMagicTabPane
14
14
  v-if="display(tab.display) && tabItems(tab).length"
15
15
  :key="tab[mForm?.keyProp || '__key'] ?? tabIndex"
16
16
  :name="filter(tab.status) || tabIndex.toString()"
17
17
  :label="filter(tab.title)"
18
18
  :lazy="tab.lazy || false"
19
19
  >
20
- <m-form-container
20
+ <Container
21
21
  v-for="item in tabItems(tab)"
22
22
  :key="item[mForm?.keyProp || '__key']"
23
23
  :config="item"
@@ -35,18 +35,22 @@
35
35
  :label-width="tab.labelWidth || labelWidth"
36
36
  :expand-more="expandMore"
37
37
  @change="changeHandler"
38
- ></m-form-container>
39
- </el-tab-pane>
38
+ ></Container>
39
+ </TMagicTabPane>
40
40
  </template>
41
- </el-tabs>
41
+ </TMagicTabs>
42
42
  </template>
43
43
 
44
- <script lang="ts">
45
- import { computed, defineComponent, inject, PropType, ref, watchEffect } from 'vue';
44
+ <script setup lang="ts">
45
+ import { computed, inject, ref, watchEffect } from 'vue';
46
46
  import { cloneDeep } from 'lodash-es';
47
47
 
48
- import { FormState, FormValue, TabConfig, TabPaneConfig } from '../schema';
49
- import { display, filterFunction } from '../utils/form';
48
+ import { TMagicTabPane, TMagicTabs } from '@tmagic/design';
49
+
50
+ import { FormState, TabConfig, TabPaneConfig } from '../schema';
51
+ import { display as displayFunc, filterFunction } from '../utils/form';
52
+
53
+ import Container from './Container.vue';
50
54
 
51
55
  const getActive = (mForm: FormState | undefined, props: any, activeTabName: string) => {
52
56
  const { config, model, prop } = props;
@@ -59,7 +63,7 @@ const getActive = (mForm: FormState | undefined, props: any, activeTabName: stri
59
63
  return '0';
60
64
  };
61
65
 
62
- const tabClickHandler = (mForm: FormState | undefined, tab: any, props: any) => {
66
+ const tabClick = (mForm: FormState | undefined, tab: any, props: any) => {
63
67
  const { config, model, prop } = props;
64
68
 
65
69
  // 兼容vue2的element-ui
@@ -75,123 +79,90 @@ const tabClickHandler = (mForm: FormState | undefined, tab: any, props: any) =>
75
79
  }
76
80
  };
77
81
 
78
- const Tab = defineComponent({
79
- name: 'm-form-tab',
80
-
81
- props: {
82
- labelWidth: String,
83
- expandMore: Boolean,
84
-
85
- model: {
86
- type: Object,
87
- default: () => ({}),
88
- },
89
-
90
- config: {
91
- type: Object as PropType<TabConfig>,
92
- default: () => ({}),
93
- },
82
+ const props = defineProps<{
83
+ model: any;
84
+ config: TabConfig;
85
+ name: string;
86
+ size?: string;
87
+ labelWidth?: string;
88
+ prop?: string;
89
+ expandMore?: boolean;
90
+ }>();
91
+
92
+ const emit = defineEmits(['change']);
93
+
94
+ const mForm = inject<FormState | undefined>('mForm');
95
+ const activeTabName = ref(getActive(mForm, props, ''));
96
+
97
+ const tabs = computed(() => {
98
+ if (props.config.dynamic) {
99
+ if (!props.config.name) throw new Error('dynamic tab 必须配置name');
100
+ return props.model[props.config.name] || [];
101
+ }
102
+ return props.config.items;
103
+ });
94
104
 
95
- prop: String,
105
+ const filter = (config: any) => filterFunction(mForm, config, props);
96
106
 
97
- name: String,
107
+ watchEffect(() => {
108
+ if (typeof props.config.activeChange === 'function') {
109
+ props.config.activeChange(mForm, activeTabName.value, {
110
+ model: props.model,
111
+ prop: props.prop,
112
+ });
113
+ }
114
+ });
98
115
 
99
- size: String,
100
- },
116
+ const tabItems = (tab: TabPaneConfig) => (props.config.dynamic ? props.config.items : tab.items);
101
117
 
102
- emits: {
103
- change(values: FormValue) {
104
- return values;
105
- },
106
- },
118
+ const tabClickHandler = (tab: any) => tabClick(mForm, tab, props);
107
119
 
108
- setup(props, { emit }) {
109
- const mForm = inject<FormState | undefined>('mForm');
110
- const activeTabName = ref(getActive(mForm, props, ''));
120
+ const onTabAdd = () => {
121
+ if (!props.config.name) throw new Error('dynamic tab 必须配置name');
111
122
 
112
- const tabs = computed(() => {
113
- if (props.config.dynamic) {
114
- if (!props.config.name) throw new Error('dynamic tab 必须配置name');
115
- return props.model[props.config.name] || [];
116
- }
117
- return props.config.items;
123
+ if (typeof props.config.onTabAdd === 'function') {
124
+ props.config.onTabAdd(mForm, {
125
+ model: props.model,
126
+ prop: props.prop,
127
+ config: props.config,
118
128
  });
129
+ } else if (tabs.value.length > 0) {
130
+ const newObj = cloneDeep(tabs.value[0]);
131
+ newObj.title = `标签${tabs.value.length + 1}`;
132
+ props.model[props.config.name].push(newObj);
133
+ }
134
+ emit('change', props.model);
135
+ mForm?.$emit('field-change', props.prop, props.model[props.config.name]);
136
+ };
119
137
 
120
- const filter = (config: any) => filterFunction(mForm, config, props);
138
+ const onTabRemove = (tabName: string) => {
139
+ if (!props.config.name) throw new Error('dynamic tab 必须配置name');
121
140
 
122
- watchEffect(() => {
123
- if (typeof props.config.activeChange === 'function') {
124
- props.config.activeChange(mForm, activeTabName.value, {
125
- model: props.model,
126
- prop: props.prop,
127
- });
128
- }
141
+ if (typeof props.config.onTabRemove === 'function') {
142
+ props.config.onTabRemove(mForm, tabName, {
143
+ model: props.model,
144
+ prop: props.prop,
145
+ config: props.config,
129
146
  });
147
+ } else {
148
+ props.model[props.config.name].splice(+tabName, 1);
149
+
150
+ // 防止删除后没有选中的问题
151
+ if (tabName < activeTabName.value || activeTabName.value >= props.model[props.config.name].length) {
152
+ activeTabName.value = (+activeTabName.value - 1).toString();
153
+ tabClick(mForm, { name: activeTabName.value }, props);
154
+ }
155
+ }
156
+ emit('change', props.model);
157
+ mForm?.$emit('field-change', props.prop, props.model[props.config.name]);
158
+ };
130
159
 
131
- return {
132
- mForm,
133
-
134
- activeTabName,
135
-
136
- tabs,
137
-
138
- filter,
139
-
140
- tabItems: (tab: TabPaneConfig) => (props.config.dynamic ? props.config.items : tab.items),
141
-
142
- tabClickHandler: (tab: any) => tabClickHandler(mForm, tab, props),
143
-
144
- onTabAdd: () => {
145
- if (!props.config.name) throw new Error('dynamic tab 必须配置name');
146
-
147
- if (typeof props.config.onTabAdd === 'function') {
148
- props.config.onTabAdd(mForm, {
149
- model: props.model,
150
- prop: props.prop,
151
- config: props.config,
152
- });
153
- } else if (tabs.value.length > 0) {
154
- const newObj = cloneDeep(tabs.value[0]);
155
- newObj.title = `标签${tabs.value.length + 1}`;
156
- props.model[props.config.name].push(newObj);
157
- }
158
- emit('change', props.model);
159
- mForm?.$emit('field-change', props.prop, props.model[props.config.name]);
160
- },
161
-
162
- onTabRemove: (tabName: string) => {
163
- if (!props.config.name) throw new Error('dynamic tab 必须配置name');
164
-
165
- if (typeof props.config.onTabRemove === 'function') {
166
- props.config.onTabRemove(mForm, tabName, {
167
- model: props.model,
168
- prop: props.prop,
169
- config: props.config,
170
- });
171
- } else {
172
- props.model[props.config.name].splice(+tabName, 1);
173
-
174
- // 防止删除后没有选中的问题
175
- if (tabName < activeTabName.value || activeTabName.value >= props.model[props.config.name].length) {
176
- activeTabName.value = (+activeTabName.value - 1).toString();
177
- tabClickHandler(mForm, { name: activeTabName.value }, props);
178
- }
179
- }
180
- emit('change', props.model);
181
- mForm?.$emit('field-change', props.prop, props.model[props.config.name]);
182
- },
183
-
184
- display: (displayConfig: any) => display(mForm, displayConfig, props),
185
-
186
- changeHandler: () => {
187
- emit('change', props.model);
188
- if (typeof props.config.onChange === 'function') {
189
- props.config.onChange(mForm, { model: props.model, prop: props.prop, config: props.config });
190
- }
191
- },
192
- };
193
- },
194
- });
160
+ const display = (displayConfig: any) => displayFunc(mForm, displayConfig, props);
195
161
 
196
- export default Tab;
162
+ const changeHandler = () => {
163
+ emit('change', props.model);
164
+ if (typeof props.config.onChange === 'function') {
165
+ props.config.onChange(mForm, { model: props.model, prop: props.prop, config: props.config });
166
+ }
167
+ };
197
168
  </script>
@@ -1,146 +1,98 @@
1
1
  <template>
2
- <div class="m-cascader" style="width: 100%">
3
- <el-cascader
4
- v-model="model[name]"
5
- ref="cascader"
6
- style="width: 100%"
7
- clearable
8
- filterable
9
- :size="size"
10
- :placeholder="config.placeholder"
11
- :disabled="disabled"
12
- :options="options"
13
- :props="{ multiple: config.multiple }"
14
- @change="changeHandler"
15
- ></el-cascader>
16
- </div>
2
+ <TMagicCascader
3
+ v-model="model[name]"
4
+ ref="tMagicCascader"
5
+ style="width: 100%"
6
+ clearable
7
+ filterable
8
+ :size="size"
9
+ :placeholder="config.placeholder"
10
+ :disabled="disabled"
11
+ :options="options"
12
+ :props="{ multiple: config.multiple }"
13
+ @change="changeHandler"
14
+ ></TMagicCascader>
17
15
  </template>
18
16
 
19
- <script lang="ts">
20
- import {
21
- ComponentInternalInstance,
22
- computed,
23
- defineComponent,
24
- getCurrentInstance,
25
- inject,
26
- PropType,
27
- ref,
28
- watchEffect,
29
- } from 'vue';
17
+ <script setup lang="ts">
18
+ import { inject, ref, watchEffect } from 'vue';
19
+
20
+ import { TMagicCascader } from '@tmagic/design';
30
21
 
31
22
  import { CascaderConfig, FormState } from '../schema';
32
23
  import { getConfig } from '../utils/config';
33
- import fieldProps from '../utils/fieldProps';
34
24
  import { useAddField } from '../utils/useAddField';
35
25
 
36
- export default defineComponent({
37
- name: 'm-fields-cascader',
38
-
39
- props: {
40
- ...fieldProps,
41
- config: {
42
- type: Object as PropType<CascaderConfig>,
43
- required: true,
44
- },
45
- },
46
-
47
- emits: ['change'],
48
-
49
- setup(props, { emit }) {
50
- const mForm = inject<FormState | null>('mForm');
51
- const vm = getCurrentInstance() as ComponentInternalInstance;
52
-
53
- useAddField(props.prop);
54
-
55
- const requestFunc = getConfig('request') as Function;
56
-
57
- const cascader = ref<any>();
58
- const dialog = ref<any>();
59
-
60
- const options = Array.isArray(props.config.options) ? ref(props.config.options) : ref([]);
61
- const remoteData = ref<any>(null);
62
-
63
- const setRemoteOptions = async function () {
64
- const { config } = props;
65
- const { option } = config;
66
- if (!option) return;
67
- let { body } = option;
68
-
69
- const postOptions: Record<string, any> = {
70
- url: option.url,
71
- cache: option.cache,
72
- timeout: option.timeout,
73
- data: {},
74
- };
75
-
76
- if (body && mForm) {
77
- if (typeof body === 'function' && props.model && mForm) {
78
- body = body(mForm, {
79
- model: props.model,
80
- formValue: mForm.values,
81
- formValues: mForm.values,
82
- config: props.config,
83
- });
84
- }
85
- postOptions.data = body;
86
- }
87
-
88
- const res = await requestFunc(postOptions);
89
-
90
- remoteData.value = res[option.root];
91
- if (remoteData.value && typeof option?.item === 'function') {
92
- options.value = option.item(res[option.root]);
93
- }
94
- };
95
-
96
- // 初始化
97
- if (typeof props.config.options === 'function' && props.model && mForm) {
98
- watchEffect(
99
- () =>
100
- (options.value = (props.config.options as Function)(vm, { model: props.model, formValues: mForm.values })),
101
- );
102
- } else if (!props.config.options || !props.config.options.length || props.config.remote) {
103
- Promise.resolve(setRemoteOptions());
26
+ const props = defineProps<{
27
+ config: CascaderConfig;
28
+ model: any;
29
+ initValues?: any;
30
+ values?: any;
31
+ name: string;
32
+ prop: string;
33
+ disabled?: boolean;
34
+ size: 'mini' | 'small' | 'medium';
35
+ }>();
36
+
37
+ const emit = defineEmits(['change']);
38
+
39
+ const mForm = inject<FormState | null>('mForm');
40
+
41
+ useAddField(props.prop);
42
+
43
+ const requestFunc = getConfig('request') as Function;
44
+
45
+ const tMagicCascader = ref<InstanceType<typeof TMagicCascader>>();
46
+
47
+ const options = Array.isArray(props.config.options) ? ref(props.config.options) : ref([]);
48
+ const remoteData = ref<any>(null);
49
+
50
+ const setRemoteOptions = async function () {
51
+ const { config } = props;
52
+ const { option } = config;
53
+ if (!option) return;
54
+ let { body } = option;
55
+
56
+ const postOptions: Record<string, any> = {
57
+ url: option.url,
58
+ cache: option.cache,
59
+ timeout: option.timeout,
60
+ data: {},
61
+ };
62
+
63
+ if (body && mForm) {
64
+ if (typeof body === 'function' && props.model && mForm) {
65
+ body = body(mForm, {
66
+ model: props.model,
67
+ formValue: mForm.values,
68
+ formValues: mForm.values,
69
+ config: props.config,
70
+ });
104
71
  }
105
-
106
- const action = computed(() => {
107
- if (props.config.add?.action.method === 'post') {
108
- return (options: any) =>
109
- requestFunc({
110
- ...props.config?.add?.action.body,
111
- ...options,
112
- });
113
- }
114
- return null;
115
- });
116
-
117
- return {
118
- options,
119
- remoteData,
120
- addButtonStyle: {
121
- top: 0,
122
- left: 0,
123
- width: 'auto',
124
- },
125
- dialogVisible: false,
126
- cascader,
127
- dialog,
128
- action,
129
- setRemoteOptions,
130
- changeHandler: (value: any) => {
131
- if (!cascader.value) return;
132
- cascader.value.query = '';
133
- cascader.value.previousQuery = null;
134
- emit('change', value);
135
- },
136
- addHandler: () => {
137
- if (!dialog.value) return;
138
- dialog.value.dialogVisible = true;
139
- },
140
- editAfterAction: () => {
141
- setRemoteOptions();
142
- },
143
- };
144
- },
145
- });
72
+ postOptions.data = body;
73
+ }
74
+
75
+ const res = await requestFunc(postOptions);
76
+
77
+ remoteData.value = res[option.root];
78
+ if (remoteData.value && typeof option?.item === 'function') {
79
+ options.value = option.item(res[option.root]);
80
+ }
81
+ };
82
+
83
+ // 初始化
84
+ if (typeof props.config.options === 'function' && props.model && mForm) {
85
+ watchEffect(
86
+ () => (options.value = (props.config.options as Function)(mForm, { model: props.model, formValues: mForm.values })),
87
+ );
88
+ } else if (!props.config.options || !props.config.options.length || props.config.remote) {
89
+ Promise.resolve(setRemoteOptions());
90
+ }
91
+
92
+ const changeHandler = (value: any) => {
93
+ if (!tMagicCascader.value) return;
94
+ tMagicCascader.value.setQuery('');
95
+ tMagicCascader.value.setPreviousQuery(null);
96
+ emit('change', value);
97
+ };
146
98
  </script>
@@ -1,67 +1,63 @@
1
1
  <template>
2
- <el-checkbox
2
+ <TMagicCheckbox
3
3
  v-model="model[name]"
4
4
  :size="size"
5
5
  :trueLabel="activeValue"
6
6
  :falseLabel="inactiveValue"
7
7
  :disabled="disabled"
8
- :label="config.text"
9
8
  @change="changeHandler"
10
- ></el-checkbox>
9
+ >{{ config.text }}</TMagicCheckbox
10
+ >
11
11
  </template>
12
12
 
13
- <script lang="ts">
14
- import { computed, defineComponent, PropType } from 'vue';
13
+ <script setup lang="ts">
14
+ import { computed } from 'vue';
15
+
16
+ import { TMagicCheckbox } from '@tmagic/design';
15
17
 
16
18
  import { CheckboxConfig } from '../schema';
17
- import fieldProps from '../utils/fieldProps';
18
19
  import { useAddField } from '../utils/useAddField';
19
20
 
20
- export default defineComponent({
21
- name: 'm-fields-checkbox',
22
-
23
- props: {
24
- ...fieldProps,
25
- config: {
26
- type: Object as PropType<CheckboxConfig>,
27
- required: true,
28
- },
29
- },
30
-
31
- emits: ['change', 'input'],
32
-
33
- setup(props, { emit }) {
34
- useAddField(props.prop);
35
-
36
- return {
37
- activeValue: computed(() => {
38
- if (typeof props.config.activeValue === 'undefined') {
39
- if (props.config.filter === 'number') {
40
- return 1;
41
- }
42
- } else {
43
- return props.config.activeValue;
44
- }
45
-
46
- return undefined;
47
- }),
48
-
49
- inactiveValue: computed(() => {
50
- if (typeof props.config.inactiveValue === 'undefined') {
51
- if (props.config.filter === 'number') {
52
- return 0;
53
- }
54
- } else {
55
- return props.config.inactiveValue;
56
- }
21
+ const props = defineProps<{
22
+ config: CheckboxConfig;
23
+ model: any;
24
+ initValues?: any;
25
+ values?: any;
26
+ name: string;
27
+ prop: string;
28
+ disabled?: boolean;
29
+ size: 'mini' | 'small' | 'medium';
30
+ }>();
31
+
32
+ const emit = defineEmits(['change']);
33
+
34
+ useAddField(props.prop);
35
+
36
+ const activeValue = computed(() => {
37
+ if (typeof props.config.activeValue === 'undefined') {
38
+ if (props.config.filter === 'number') {
39
+ return 1;
40
+ }
41
+ } else {
42
+ return props.config.activeValue;
43
+ }
44
+
45
+ return undefined;
46
+ });
57
47
 
58
- return undefined;
59
- }),
48
+ const inactiveValue = computed(() => {
49
+ if (typeof props.config.inactiveValue === 'undefined') {
50
+ if (props.config.filter === 'number') {
51
+ return 0;
52
+ }
53
+ } else {
54
+ return props.config.inactiveValue;
55
+ }
60
56
 
61
- changeHandler(value: number | boolean) {
62
- emit('change', value);
63
- },
64
- };
65
- },
57
+ return undefined;
66
58
  });
59
+
60
+ const changeHandler = (value: number | boolean) => {
61
+ emit('change', value);
62
+ };
67
63
  </script>