@tmagic/form 1.4.8 → 1.4.10

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 (63) hide show
  1. package/dist/style.css +4 -0
  2. package/dist/tmagic-form.js +13 -12
  3. package/dist/tmagic-form.umd.cjs +13 -12
  4. package/package.json +5 -5
  5. package/src/Form.vue +201 -0
  6. package/src/FormBox.vue +120 -0
  7. package/src/FormDialog.vue +173 -0
  8. package/src/FormDrawer.vue +159 -0
  9. package/src/containers/Col.vue +52 -0
  10. package/src/containers/Container.vue +408 -0
  11. package/src/containers/Fieldset.vue +124 -0
  12. package/src/containers/GroupList.vue +139 -0
  13. package/src/containers/GroupListItem.vue +135 -0
  14. package/src/containers/Panel.vue +99 -0
  15. package/src/containers/Row.vue +54 -0
  16. package/src/containers/Step.vue +82 -0
  17. package/src/containers/Table.vue +648 -0
  18. package/src/containers/Tabs.vue +226 -0
  19. package/src/fields/Cascader.vue +131 -0
  20. package/src/fields/Checkbox.vue +58 -0
  21. package/src/fields/CheckboxGroup.vue +44 -0
  22. package/src/fields/ColorPicker.vue +30 -0
  23. package/src/fields/Date.vue +38 -0
  24. package/src/fields/DateTime.vue +47 -0
  25. package/src/fields/Daterange.vue +99 -0
  26. package/src/fields/Display.vue +21 -0
  27. package/src/fields/DynamicField.vue +90 -0
  28. package/src/fields/Hidden.vue +16 -0
  29. package/src/fields/Link.vue +86 -0
  30. package/src/fields/Number.vue +49 -0
  31. package/src/fields/NumberRange.vue +50 -0
  32. package/src/fields/RadioGroup.vue +28 -0
  33. package/src/fields/Select.vue +449 -0
  34. package/src/fields/Switch.vue +59 -0
  35. package/src/fields/Text.vue +170 -0
  36. package/src/fields/Textarea.vue +46 -0
  37. package/src/fields/Time.vue +34 -0
  38. package/src/fields/Timerange.vue +76 -0
  39. package/src/index.ts +139 -0
  40. package/src/schema.ts +758 -0
  41. package/src/shims-vue.d.ts +6 -0
  42. package/src/theme/container.scss +5 -0
  43. package/src/theme/date-time.scss +7 -0
  44. package/src/theme/fieldset.scss +28 -0
  45. package/src/theme/form-box.scss +13 -0
  46. package/src/theme/form-dialog.scss +13 -0
  47. package/src/theme/form-drawer.scss +11 -0
  48. package/src/theme/form.scss +43 -0
  49. package/src/theme/group-list.scss +23 -0
  50. package/src/theme/index.scss +15 -0
  51. package/src/theme/link.scss +3 -0
  52. package/src/theme/number-range.scss +8 -0
  53. package/src/theme/panel.scss +24 -0
  54. package/src/theme/select.scss +3 -0
  55. package/src/theme/table.scss +70 -0
  56. package/src/theme/tabs.scss +27 -0
  57. package/src/theme/text.scss +6 -0
  58. package/src/utils/config.ts +27 -0
  59. package/src/utils/containerProps.ts +50 -0
  60. package/src/utils/form.ts +273 -0
  61. package/src/utils/useAddField.ts +40 -0
  62. package/types/schema.d.ts +7 -5
  63. package/types/utils/form.d.ts +2 -2
@@ -0,0 +1,226 @@
1
+ <template>
2
+ <component
3
+ v-model="activeTabName"
4
+ v-bind="
5
+ tabsComponent?.props({
6
+ type: config.tabType,
7
+ editable: config.editable || false,
8
+ tabPosition: config.tabPosition || 'top',
9
+ }) || {}
10
+ "
11
+ :is="tabsComponent?.component || 'el-tabs'"
12
+ :class="`tmagic-design-tabs ${config.dynamic ? 'magic-form-dynamic-tab' : 'magic-form-tab'}`"
13
+ @tab-click="tabClickHandler"
14
+ @tab-add="onTabAdd"
15
+ @tab-remove="onTabRemove"
16
+ >
17
+ <component
18
+ v-for="(tab, tabIndex) in tabs"
19
+ :is="tabPaneComponent?.component || 'el-tab-pane'"
20
+ :key="tab[mForm?.keyProp || '__key'] ?? tabIndex"
21
+ v-bind="
22
+ tabPaneComponent?.props({ name: filter(tab.status) || tabIndex.toString(), lazy: tab.lazy || false }) || {}
23
+ "
24
+ >
25
+ <template #label>
26
+ <span>
27
+ {{ filter(tab.title)
28
+ }}<TMagicBadge
29
+ :hidden="!diffCount[tabIndex]"
30
+ :value="diffCount[tabIndex]"
31
+ class="diff-count-badge"
32
+ ></TMagicBadge>
33
+ </span>
34
+ </template>
35
+ <Container
36
+ v-for="item in tabItems(tab)"
37
+ :key="item[mForm?.keyProp || '__key']"
38
+ :config="item"
39
+ :disabled="disabled"
40
+ :model="
41
+ config.dynamic
42
+ ? (name ? model[name] : model)[tabIndex]
43
+ : tab.name
44
+ ? (name ? model[name] : model)[tab.name]
45
+ : name
46
+ ? model[name]
47
+ : model
48
+ "
49
+ :last-values="
50
+ isEmpty(lastValues)
51
+ ? {}
52
+ : config.dynamic
53
+ ? (name ? lastValues[name] : lastValues)[tabIndex]
54
+ : tab.name
55
+ ? (name ? lastValues[name] : lastValues)[tab.name]
56
+ : name
57
+ ? lastValues[name]
58
+ : lastValues
59
+ "
60
+ :is-compare="isCompare"
61
+ :prop="config.dynamic ? `${prop}${prop ? '.' : ''}${String(tabIndex)}` : prop"
62
+ :size="size"
63
+ :label-width="tab.labelWidth || labelWidth"
64
+ :expand-more="expandMore"
65
+ @change="changeHandler"
66
+ @addDiffCount="onAddDiffCount(tabIndex)"
67
+ ></Container>
68
+ </component>
69
+ </component>
70
+ </template>
71
+
72
+ <script setup lang="ts">
73
+ import { computed, inject, ref, watchEffect } from 'vue';
74
+ import { cloneDeep, isEmpty } from 'lodash-es';
75
+
76
+ import { getConfig, TMagicBadge } from '@tmagic/design';
77
+
78
+ import { FormState, TabConfig, TabPaneConfig } from '../schema';
79
+ import { display as displayFunc, filterFunction } from '../utils/form';
80
+
81
+ import Container from './Container.vue';
82
+
83
+ defineOptions({
84
+ name: 'MFormTabs',
85
+ });
86
+
87
+ type DiffCount = {
88
+ [tabIndex: number]: number;
89
+ };
90
+
91
+ const tabPaneComponent = getConfig('components')?.tabPane;
92
+ const tabsComponent = getConfig('components')?.tabs;
93
+
94
+ const getActive = (mForm: FormState | undefined, props: any, activeTabName: string) => {
95
+ const { config, model, prop } = props;
96
+ const { active } = config;
97
+
98
+ if (typeof active === 'function') return active(mForm, { model, formValue: mForm?.values, prop });
99
+ if (+activeTabName >= props.config.items.length) return '0';
100
+ if (typeof active !== 'undefined') return active;
101
+
102
+ return '0';
103
+ };
104
+
105
+ const tabClick = (mForm: FormState | undefined, tab: any, props: any) => {
106
+ const { config, model, prop } = props;
107
+
108
+ // 兼容vue2的element-ui
109
+ tab.name = tab.paneName;
110
+
111
+ if (typeof config.onTabClick === 'function') {
112
+ config.onTabClick(mForm, tab, { model, formValue: mForm?.values, prop, config });
113
+ }
114
+
115
+ const tabConfig = config.items.find((item: TabPaneConfig) => tab.name === item.status);
116
+ if (tabConfig && typeof tabConfig.onTabClick === 'function') {
117
+ tabConfig.onTabClick(mForm, tab, { model, formValue: mForm?.values, prop, config });
118
+ }
119
+ };
120
+
121
+ const props = withDefaults(
122
+ defineProps<{
123
+ model: any;
124
+ lastValues?: any;
125
+ isCompare?: boolean;
126
+ config: TabConfig;
127
+ name: string;
128
+ size?: string;
129
+ labelWidth?: string;
130
+ prop?: string;
131
+ expandMore?: boolean;
132
+ disabled?: boolean;
133
+ }>(),
134
+ {
135
+ lastValues: () => ({}),
136
+ isCompare: false,
137
+ },
138
+ );
139
+
140
+ const emit = defineEmits(['change', 'addDiffCount']);
141
+
142
+ const mForm = inject<FormState | undefined>('mForm');
143
+ const activeTabName = ref(getActive(mForm, props, ''));
144
+ const diffCount = ref<DiffCount>({});
145
+
146
+ const tabs = computed(() => {
147
+ if (props.config.dynamic) {
148
+ if (!props.config.name) throw new Error('dynamic tab 必须配置name');
149
+ return props.model[props.config.name] || [];
150
+ }
151
+ return props.config.items.filter((item) => displayFunc(mForm, item.display, props));
152
+ });
153
+
154
+ const filter = (config: any) => filterFunction(mForm, config, props);
155
+
156
+ watchEffect(() => {
157
+ if (typeof props.config.activeChange === 'function') {
158
+ props.config.activeChange(mForm, activeTabName.value, {
159
+ model: props.model,
160
+ prop: props.prop,
161
+ });
162
+ }
163
+ });
164
+
165
+ const tabItems = (tab: TabPaneConfig) => (props.config.dynamic ? props.config.items : tab.items);
166
+
167
+ const tabClickHandler = (tab: any) => tabClick(mForm, tab, props);
168
+
169
+ const onTabAdd = () => {
170
+ if (!props.config.name) throw new Error('dynamic tab 必须配置name');
171
+
172
+ if (typeof props.config.onTabAdd === 'function') {
173
+ props.config.onTabAdd(mForm, {
174
+ model: props.model,
175
+ prop: props.prop,
176
+ config: props.config,
177
+ });
178
+ } else if (tabs.value.length > 0) {
179
+ const newObj = cloneDeep(tabs.value[0]);
180
+ newObj.title = `标签${tabs.value.length + 1}`;
181
+ props.model[props.config.name].push(newObj);
182
+ }
183
+ emit('change', props.model);
184
+ mForm?.$emit('field-change', props.prop, props.model[props.config.name]);
185
+ };
186
+
187
+ const onTabRemove = (tabName: string) => {
188
+ if (!props.config.name) throw new Error('dynamic tab 必须配置name');
189
+
190
+ if (typeof props.config.onTabRemove === 'function') {
191
+ props.config.onTabRemove(mForm, tabName, {
192
+ model: props.model,
193
+ prop: props.prop,
194
+ config: props.config,
195
+ });
196
+ } else {
197
+ props.model[props.config.name].splice(+tabName, 1);
198
+
199
+ // 防止删除后没有选中的问题
200
+ if (tabName < activeTabName.value || activeTabName.value >= props.model[props.config.name].length) {
201
+ activeTabName.value = (+activeTabName.value - 1).toString();
202
+ tabClick(mForm, { name: activeTabName.value }, props);
203
+ }
204
+ }
205
+ emit('change', props.model);
206
+ mForm?.$emit('field-change', props.prop, props.model[props.config.name]);
207
+ };
208
+
209
+ const changeHandler = () => {
210
+ emit('change', props.model);
211
+ if (typeof props.config.onChange === 'function') {
212
+ props.config.onChange(mForm, { model: props.model, prop: props.prop, config: props.config });
213
+ }
214
+ };
215
+
216
+ // 在tabs组件中收集事件触发次数,即该tab下的差异数
217
+ const onAddDiffCount = (tabIndex: number) => {
218
+ if (!diffCount.value[tabIndex]) {
219
+ diffCount.value[tabIndex] = 1;
220
+ } else {
221
+ diffCount.value[tabIndex] += 1;
222
+ }
223
+ // 继续抛出给更高层级的组件
224
+ emit('addDiffCount');
225
+ };
226
+ </script>
@@ -0,0 +1,131 @@
1
+ <template>
2
+ <TMagicCascader
3
+ v-model="value"
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
+ :popper-class="config.popperClass"
13
+ :props="{
14
+ multiple: config.multiple ?? false,
15
+ emitPath: config.emitPath ?? true,
16
+ checkStrictly: checkStrictly ?? false,
17
+ }"
18
+ @change="changeHandler"
19
+ ></TMagicCascader>
20
+ </template>
21
+
22
+ <script setup lang="ts">
23
+ import { computed, inject, ref, watchEffect } from 'vue';
24
+
25
+ import { TMagicCascader } from '@tmagic/design';
26
+
27
+ import type { CascaderConfig, CascaderOption, FieldProps, FormState } from '../schema';
28
+ import { getConfig } from '../utils/config';
29
+ import { filterFunction } from '../utils/form';
30
+ import { useAddField } from '../utils/useAddField';
31
+
32
+ defineOptions({
33
+ name: 'MFormCascader',
34
+ });
35
+
36
+ const props = defineProps<FieldProps<CascaderConfig>>();
37
+
38
+ const emit = defineEmits(['change']);
39
+
40
+ const mForm = inject<FormState | undefined>('mForm');
41
+
42
+ useAddField(props.prop);
43
+
44
+ const requestFunc = getConfig('request') as Function;
45
+
46
+ const tMagicCascader = ref<InstanceType<typeof TMagicCascader>>();
47
+
48
+ const options = ref<CascaderOption[]>([]);
49
+ const remoteData = ref<any>(null);
50
+
51
+ const checkStrictly = computed(() => filterFunction(mForm, props.config.checkStrictly, props));
52
+ const valueSeparator = computed(() => filterFunction<string>(mForm, props.config.valueSeparator, props));
53
+
54
+ const value = computed({
55
+ get() {
56
+ if (typeof props.model[props.name] === 'string' && valueSeparator.value) {
57
+ return props.model[props.name].split(valueSeparator.value);
58
+ }
59
+ return props.model[props.name];
60
+ },
61
+ set(value) {
62
+ let result = value;
63
+ if (valueSeparator.value) {
64
+ result = value.join(valueSeparator.value);
65
+ }
66
+ props.model[props.name] = result;
67
+ },
68
+ });
69
+
70
+ const setRemoteOptions = async function () {
71
+ const { config } = props;
72
+ const { option } = config;
73
+ if (!option) return;
74
+ let { body } = option;
75
+
76
+ const postOptions: Record<string, any> = {
77
+ url: option.url,
78
+ cache: option.cache,
79
+ timeout: option.timeout,
80
+ data: {},
81
+ };
82
+
83
+ if (body && mForm) {
84
+ if (typeof body === 'function' && props.model && mForm) {
85
+ body = body(mForm, {
86
+ model: props.model,
87
+ formValue: mForm.values,
88
+ formValues: mForm.values,
89
+ config: props.config,
90
+ });
91
+ }
92
+ postOptions.data = body;
93
+ }
94
+
95
+ const res = await requestFunc(postOptions);
96
+
97
+ remoteData.value = res[option.root];
98
+ if (remoteData.value && typeof option?.item === 'function') {
99
+ options.value = option.item(res[option.root]);
100
+ }
101
+ };
102
+
103
+ // 初始化
104
+ if (typeof props.config.options === 'function' && props.model && mForm) {
105
+ watchEffect(() => {
106
+ typeof props.config.options === 'function' &&
107
+ Promise.resolve(
108
+ props.config.options(mForm, {
109
+ model: props.model,
110
+ prop: props.prop,
111
+ formValue: mForm?.values,
112
+ }),
113
+ ).then((data) => {
114
+ options.value = data;
115
+ });
116
+ });
117
+ } else if (!props.config.options?.length || props.config.remote) {
118
+ Promise.resolve(setRemoteOptions());
119
+ } else if (Array.isArray(props.config.options)) {
120
+ watchEffect(() => {
121
+ options.value = props.config.options as CascaderOption[];
122
+ });
123
+ }
124
+
125
+ const changeHandler = () => {
126
+ if (!tMagicCascader.value) return;
127
+ tMagicCascader.value.setQuery('');
128
+ tMagicCascader.value.setPreviousQuery(null);
129
+ emit('change', props.model[props.name]);
130
+ };
131
+ </script>
@@ -0,0 +1,58 @@
1
+ <template>
2
+ <TMagicCheckbox
3
+ v-model="model[name]"
4
+ :size="size"
5
+ :trueValue="activeValue"
6
+ :falseValue="inactiveValue"
7
+ :disabled="disabled"
8
+ @change="changeHandler"
9
+ >{{ config.text }}</TMagicCheckbox
10
+ >
11
+ </template>
12
+
13
+ <script setup lang="ts">
14
+ import { computed } from 'vue';
15
+
16
+ import { TMagicCheckbox } from '@tmagic/design';
17
+
18
+ import type { CheckboxConfig, FieldProps } from '../schema';
19
+ import { useAddField } from '../utils/useAddField';
20
+
21
+ defineOptions({
22
+ name: 'MFormCheckbox',
23
+ });
24
+
25
+ const props = defineProps<FieldProps<CheckboxConfig>>();
26
+
27
+ const emit = defineEmits(['change']);
28
+
29
+ useAddField(props.prop);
30
+
31
+ const activeValue = computed(() => {
32
+ if (typeof props.config.activeValue === 'undefined') {
33
+ if (props.config.filter === 'number') {
34
+ return 1;
35
+ }
36
+ } else {
37
+ return props.config.activeValue;
38
+ }
39
+
40
+ return undefined;
41
+ });
42
+
43
+ const inactiveValue = computed(() => {
44
+ if (typeof props.config.inactiveValue === 'undefined') {
45
+ if (props.config.filter === 'number') {
46
+ return 0;
47
+ }
48
+ } else {
49
+ return props.config.inactiveValue;
50
+ }
51
+
52
+ return undefined;
53
+ });
54
+
55
+ const changeHandler = (value: number | boolean) => {
56
+ emit('change', value);
57
+ };
58
+ </script>
@@ -0,0 +1,44 @@
1
+ <template>
2
+ <TMagicCheckboxGroup v-model="model[name]" :size="size" :disabled="disabled" @change="changeHandler">
3
+ <TMagicCheckbox v-for="option in options" :value="option.value" :key="option.value" :disabled="option.disabled"
4
+ >{{ option.text }}
5
+ </TMagicCheckbox>
6
+ </TMagicCheckboxGroup>
7
+ </template>
8
+
9
+ <script lang="ts" setup>
10
+ import { computed, inject } from 'vue';
11
+
12
+ import { TMagicCheckbox, TMagicCheckboxGroup } from '@tmagic/design';
13
+
14
+ import type { CheckboxGroupConfig, CheckboxGroupOption, FieldProps, FormState } from '../schema';
15
+ import { filterFunction } from '../utils/form';
16
+ import { useAddField } from '../utils/useAddField';
17
+
18
+ defineOptions({
19
+ name: 'MFormCheckGroup',
20
+ });
21
+
22
+ const props = defineProps<FieldProps<CheckboxGroupConfig>>();
23
+
24
+ const emit = defineEmits(['change']);
25
+
26
+ useAddField(props.prop);
27
+
28
+ // 初始化选项
29
+ if (props.model && !props.model[props.name]) {
30
+ props.model[props.name] = [];
31
+ }
32
+
33
+ const changeHandler = (v: Array<string | number | boolean>) => {
34
+ emit('change', v);
35
+ };
36
+
37
+ const mForm = inject<FormState | undefined>('mForm');
38
+ const options = computed(() => {
39
+ if (Array.isArray(props.config.options)) return props.config.options;
40
+ if (typeof props.config.options === 'function')
41
+ return filterFunction<CheckboxGroupOption[]>(mForm, props.config.options, props) || [];
42
+ return [];
43
+ });
44
+ </script>
@@ -0,0 +1,30 @@
1
+ <template>
2
+ <TMagicColorPicker
3
+ v-model="model[name]"
4
+ :size="size"
5
+ :disabled="disabled"
6
+ :showAlpha="true"
7
+ @change="changeHandler"
8
+ ></TMagicColorPicker>
9
+ </template>
10
+
11
+ <script lang="ts" setup>
12
+ import { TMagicColorPicker } from '@tmagic/design';
13
+
14
+ import type { ColorPickConfig, FieldProps } from '../schema';
15
+ import { useAddField } from '../utils/useAddField';
16
+
17
+ defineOptions({
18
+ name: 'MFormColorPicker',
19
+ });
20
+
21
+ const props = defineProps<FieldProps<ColorPickConfig>>();
22
+
23
+ const emit = defineEmits<{
24
+ change: [value: string];
25
+ }>();
26
+
27
+ useAddField(props.prop);
28
+
29
+ const changeHandler = (value: string) => emit('change', value);
30
+ </script>
@@ -0,0 +1,38 @@
1
+ <template>
2
+ <TMagicDatePicker
3
+ v-model="model[name]"
4
+ type="date"
5
+ :size="size"
6
+ :placeholder="config.placeholder"
7
+ :disabled="disabled"
8
+ :format="config.format"
9
+ :value-format="config.valueFormat || 'YYYY/MM/DD HH:mm:ss'"
10
+ @change="changeHandler"
11
+ ></TMagicDatePicker>
12
+ </template>
13
+
14
+ <script lang="ts" setup>
15
+ import { TMagicDatePicker } from '@tmagic/design';
16
+ import { datetimeFormatter } from '@tmagic/utils';
17
+
18
+ import type { DateConfig, FieldProps } from '../schema';
19
+ import { useAddField } from '../utils/useAddField';
20
+
21
+ defineOptions({
22
+ name: 'MFormDate',
23
+ });
24
+
25
+ const props = defineProps<FieldProps<DateConfig>>();
26
+
27
+ const emit = defineEmits<{
28
+ change: [value: string];
29
+ }>();
30
+
31
+ useAddField(props.prop);
32
+
33
+ props.model[props.name] = datetimeFormatter(props.model[props.name], '');
34
+
35
+ const changeHandler = (v: string) => {
36
+ emit('change', v);
37
+ };
38
+ </script>
@@ -0,0 +1,47 @@
1
+ <template>
2
+ <TMagicDatePicker
3
+ v-model="model[name]"
4
+ popper-class="magic-datetime-picker-popper"
5
+ type="datetime"
6
+ :size="size"
7
+ :placeholder="config.placeholder"
8
+ :disabled="disabled"
9
+ :format="config.format || 'YYYY/MM/DD HH:mm:ss'"
10
+ :value-format="config.valueFormat || 'YYYY/MM/DD HH:mm:ss'"
11
+ :default-time="config.defaultTime"
12
+ @change="changeHandler"
13
+ ></TMagicDatePicker>
14
+ </template>
15
+
16
+ <script lang="ts" setup>
17
+ import { TMagicDatePicker } from '@tmagic/design';
18
+ import { datetimeFormatter } from '@tmagic/utils';
19
+
20
+ import type { DateTimeConfig, FieldProps } from '../schema';
21
+ import { useAddField } from '../utils/useAddField';
22
+
23
+ defineOptions({
24
+ name: 'MFormDateTime',
25
+ });
26
+
27
+ const props = defineProps<FieldProps<DateTimeConfig>>();
28
+
29
+ const emit = defineEmits<{
30
+ change: [value: string];
31
+ }>();
32
+
33
+ useAddField(props.prop);
34
+
35
+ const value = props.model?.[props.name].toString();
36
+ if (props.model) {
37
+ if (value === 'Invalid Date') {
38
+ props.model[props.name] = '';
39
+ } else {
40
+ props.model[props.name] = datetimeFormatter(props.model[props.name], '', props.config.valueFormat);
41
+ }
42
+ }
43
+
44
+ const changeHandler = (v: string) => {
45
+ emit('change', v);
46
+ };
47
+ </script>
@@ -0,0 +1,99 @@
1
+ <template>
2
+ <TMagicDatePicker
3
+ v-model="value"
4
+ type="datetimerange"
5
+ range-separator="-"
6
+ start-placeholder="开始日期"
7
+ end-placeholder="结束日期"
8
+ :size="size"
9
+ :unlink-panels="true"
10
+ :disabled="disabled"
11
+ :default-time="config.defaultTime"
12
+ @change="changeHandler"
13
+ ></TMagicDatePicker>
14
+ </template>
15
+
16
+ <script lang="ts" setup>
17
+ import { ref, watch } from 'vue';
18
+
19
+ import { TMagicDatePicker } from '@tmagic/design';
20
+ import { datetimeFormatter } from '@tmagic/utils';
21
+
22
+ import type { DaterangeConfig, FieldProps } from '../schema';
23
+ import { useAddField } from '../utils/useAddField';
24
+
25
+ defineOptions({
26
+ name: 'MFormDateRange',
27
+ });
28
+
29
+ const props = defineProps<FieldProps<DaterangeConfig>>();
30
+
31
+ const emit = defineEmits(['change']);
32
+
33
+ useAddField(props.prop);
34
+
35
+ // eslint-disable-next-line vue/no-setup-props-destructure
36
+ const { names } = props.config;
37
+ const value = ref<(Date | undefined)[] | null>([]);
38
+
39
+ if (props.model !== undefined) {
40
+ if (names?.length) {
41
+ watch(
42
+ [() => props.model[names[0]], () => props.model[names[1]]],
43
+ ([start, end], [preStart, preEnd]) => {
44
+ if (!value.value) {
45
+ value.value = [];
46
+ }
47
+ if (!start || !end) value.value = [];
48
+ if (start !== preStart) value.value[0] = new Date(start);
49
+ if (end !== preEnd) value.value[1] = new Date(end);
50
+ },
51
+ {
52
+ immediate: true,
53
+ },
54
+ );
55
+ } else if (props.name && props.model[props.name]) {
56
+ watch(
57
+ () => props.model[props.name],
58
+ (start, preStart) => {
59
+ if (start !== preStart) value.value = start.map((item: string) => (item ? new Date(item) : undefined));
60
+ },
61
+ {
62
+ immediate: true,
63
+ },
64
+ );
65
+ }
66
+ }
67
+
68
+ const setValue = (v: Date[] | Date) => {
69
+ names?.forEach((item, index) => {
70
+ if (!props.model) {
71
+ return;
72
+ }
73
+ if (Array.isArray(v)) {
74
+ props.model[item] = datetimeFormatter(v[index]?.toString(), '');
75
+ } else {
76
+ props.model[item] = undefined;
77
+ }
78
+ });
79
+ };
80
+
81
+ const changeHandler = (v: Date[]) => {
82
+ const value = v || [];
83
+
84
+ if (props.name) {
85
+ emit(
86
+ 'change',
87
+ value.map((item?: Date) => {
88
+ if (item) return datetimeFormatter(item, '');
89
+ return undefined;
90
+ }),
91
+ );
92
+ } else {
93
+ if (names?.length) {
94
+ setValue(value);
95
+ }
96
+ emit('change', value);
97
+ }
98
+ };
99
+ </script>
@@ -0,0 +1,21 @@
1
+ <template>
2
+ <span v-if="model">{{ model[name] }}</span>
3
+ </template>
4
+
5
+ <script setup lang="ts">
6
+ import type { DisplayConfig, FieldProps } from '../schema';
7
+ import { useAddField } from '../utils/useAddField';
8
+
9
+ defineOptions({
10
+ name: 'MFormDisplay',
11
+ });
12
+
13
+ const props = defineProps<FieldProps<DisplayConfig>>();
14
+
15
+ if (props.config.initValue && props.model) {
16
+ // eslint-disable-next-line vue/no-setup-props-destructure
17
+ props.model[props.name] = props.config.initValue;
18
+ }
19
+
20
+ useAddField(props.prop);
21
+ </script>