@tmagic/form 1.3.0-alpha.9 → 1.3.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/dist/style.css +21 -0
  2. package/dist/tmagic-form.js +716 -388
  3. package/dist/tmagic-form.js.map +1 -1
  4. package/dist/tmagic-form.umd.cjs +744 -413
  5. package/dist/tmagic-form.umd.cjs.map +1 -1
  6. package/package.json +4 -4
  7. package/src/Form.vue +12 -4
  8. package/src/FormDialog.vue +19 -5
  9. package/src/FormDrawer.vue +159 -0
  10. package/src/containers/Container.vue +11 -10
  11. package/src/containers/GroupList.vue +1 -0
  12. package/src/containers/GroupListItem.vue +8 -2
  13. package/src/containers/Table.vue +148 -150
  14. package/src/fields/Cascader.vue +2 -12
  15. package/src/fields/Checkbox.vue +2 -12
  16. package/src/fields/CheckboxGroup.vue +2 -12
  17. package/src/fields/ColorPicker.vue +5 -13
  18. package/src/fields/Date.vue +6 -14
  19. package/src/fields/DateTime.vue +7 -15
  20. package/src/fields/Daterange.vue +2 -12
  21. package/src/fields/Display.vue +2 -10
  22. package/src/fields/DynamicField.vue +3 -13
  23. package/src/fields/Hidden.vue +2 -10
  24. package/src/fields/Link.vue +2 -12
  25. package/src/fields/Number.vue +7 -14
  26. package/src/fields/NumberRange.vue +50 -0
  27. package/src/fields/RadioGroup.vue +2 -12
  28. package/src/fields/Select.vue +2 -12
  29. package/src/fields/Switch.vue +6 -14
  30. package/src/fields/Text.vue +7 -14
  31. package/src/fields/Textarea.vue +7 -14
  32. package/src/fields/Time.vue +5 -13
  33. package/src/fields/Timerange.vue +76 -0
  34. package/src/index.ts +7 -0
  35. package/src/schema.ts +23 -2
  36. package/src/theme/form-drawer.scss +11 -0
  37. package/src/theme/index.scss +2 -0
  38. package/src/theme/number-range.scss +8 -0
  39. package/src/theme/panel.scss +6 -0
  40. package/src/utils/config.ts +1 -1
  41. package/src/utils/form.ts +2 -1
  42. package/types/Form.vue.d.ts +13 -11
  43. package/types/FormDialog.vue.d.ts +30 -17
  44. package/types/FormDrawer.vue.d.ts +348 -0
  45. package/types/fields/Cascader.vue.d.ts +2 -22
  46. package/types/fields/Checkbox.vue.d.ts +2 -22
  47. package/types/fields/CheckboxGroup.vue.d.ts +2 -22
  48. package/types/fields/ColorPicker.vue.d.ts +2 -24
  49. package/types/fields/Date.vue.d.ts +2 -24
  50. package/types/fields/DateTime.vue.d.ts +2 -24
  51. package/types/fields/Daterange.vue.d.ts +2 -22
  52. package/types/fields/Display.vue.d.ts +2 -18
  53. package/types/fields/DynamicField.vue.d.ts +2 -22
  54. package/types/fields/Hidden.vue.d.ts +2 -18
  55. package/types/fields/Link.vue.d.ts +2 -22
  56. package/types/fields/Number.vue.d.ts +2 -25
  57. package/types/fields/NumberRange.vue.d.ts +12 -0
  58. package/types/fields/RadioGroup.vue.d.ts +2 -22
  59. package/types/fields/Select.vue.d.ts +2 -22
  60. package/types/fields/Switch.vue.d.ts +2 -24
  61. package/types/fields/Text.vue.d.ts +2 -25
  62. package/types/fields/Textarea.vue.d.ts +2 -25
  63. package/types/fields/Time.vue.d.ts +2 -24
  64. package/types/fields/Timerange.vue.d.ts +14 -0
  65. package/types/index.d.ts +3 -0
  66. package/types/schema.d.ts +21 -2
  67. package/types/utils/config.d.ts +1 -1
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.3.0-alpha.9",
2
+ "version": "1.3.0-beta.1",
3
3
  "name": "@tmagic/form",
4
4
  "type": "module",
5
5
  "sideEffects": [
@@ -36,8 +36,8 @@
36
36
  },
37
37
  "dependencies": {
38
38
  "@element-plus/icons-vue": "^2.0.9",
39
- "@tmagic/design": "1.3.0-alpha.9",
40
- "@tmagic/utils": "1.3.0-alpha.9",
39
+ "@tmagic/design": "1.3.0-beta.1",
40
+ "@tmagic/utils": "1.3.0-beta.1",
41
41
  "lodash-es": "^4.17.21",
42
42
  "sortablejs": "^1.14.0",
43
43
  "vue": "^3.3.4"
@@ -56,7 +56,7 @@
56
56
  "rimraf": "^3.0.2",
57
57
  "sass": "^1.35.1",
58
58
  "typescript": "^5.0.4",
59
- "vite": "^4.3.8",
59
+ "vite": "^4.4.4",
60
60
  "vue-tsc": "^1.6.5"
61
61
  }
62
62
  }
package/src/Form.vue CHANGED
@@ -47,12 +47,12 @@ const props = withDefaults(
47
47
  /** 表单配置 */
48
48
  config: FormConfig;
49
49
  /** 表单值 */
50
- initValues: Object;
50
+ initValues: Record<string, any>;
51
51
  /** 需对比的值(开启对比模式时传入) */
52
- lastValues?: Object;
52
+ lastValues?: Record<string, any>;
53
53
  /** 是否开启对比模式 */
54
54
  isCompare?: boolean;
55
- parentValues?: Object;
55
+ parentValues?: Record<string, any>;
56
56
  labelWidth?: string;
57
57
  disabled?: boolean;
58
58
  height?: string;
@@ -62,6 +62,7 @@ const props = withDefaults(
62
62
  labelPosition?: string;
63
63
  keyProp?: string;
64
64
  popperClass?: string;
65
+ extendState?: (state: FormState) => Record<string, any> | Promise<Record<string, any>>;
65
66
  }>(),
66
67
  {
67
68
  config: () => [],
@@ -114,7 +115,7 @@ const formState: FormState = reactive<FormState>({
114
115
  },
115
116
  });
116
117
 
117
- watchEffect(() => {
118
+ watchEffect(async () => {
118
119
  formState.initValues = props.initValues;
119
120
  formState.lastValues = props.lastValues;
120
121
  formState.isCompare = props.isCompare;
@@ -122,6 +123,13 @@ watchEffect(() => {
122
123
  formState.keyProp = props.keyProp;
123
124
  formState.popperClass = props.popperClass;
124
125
  formState.parentValues = props.parentValues;
126
+
127
+ if (typeof props.extendState === 'function') {
128
+ const state = (await props.extendState(formState)) || {};
129
+ Object.entries(state).forEach(([key, value]) => {
130
+ formState[key] = value;
131
+ });
132
+ }
125
133
  });
126
134
 
127
135
  provide('mForm', formState);
@@ -25,6 +25,8 @@
25
25
  :init-values="values"
26
26
  :parent-values="parentValues"
27
27
  :label-width="labelWidth"
28
+ :label-position="labelPosition"
29
+ :inline="inline"
28
30
  @change="changeHandler"
29
31
  ></Form>
30
32
  <slot></slot>
@@ -46,7 +48,7 @@
46
48
  <TMagicButton v-if="hasStep && stepCount > stepActive" type="info" size="small" @click="nextStep"
47
49
  >下一步</TMagicButton
48
50
  >
49
- <TMagicButton v-else type="primary" size="small" :loading="saveFetch" @click="save">{{
51
+ <TMagicButton v-else type="primary" size="small" :disabled="disabled" :loading="saveFetch" @click="save">{{
50
52
  confirmText
51
53
  }}</TMagicButton>
52
54
  </slot>
@@ -78,6 +80,8 @@ const props = withDefaults(
78
80
  fullscreen?: boolean;
79
81
  disabled?: boolean;
80
82
  title?: string;
83
+ inline?: boolean;
84
+ labelPosition?: string;
81
85
  zIndex?: number;
82
86
  size?: 'small' | 'default' | 'large';
83
87
  confirmText?: string;
@@ -118,10 +122,6 @@ const hasStep = computed(() => {
118
122
  return false;
119
123
  });
120
124
 
121
- const cancel = () => {
122
- dialogVisible.value = false;
123
- };
124
-
125
125
  const closeHandler = () => {
126
126
  stepActive.value = 1;
127
127
  emit('close');
@@ -148,6 +148,18 @@ const changeHandler = (value: any) => {
148
148
  emit('change', value);
149
149
  };
150
150
 
151
+ const show = () => {
152
+ dialogVisible.value = true;
153
+ };
154
+
155
+ const hide = () => {
156
+ dialogVisible.value = false;
157
+ };
158
+
159
+ const cancel = () => {
160
+ hide();
161
+ };
162
+
151
163
  defineExpose({
152
164
  form,
153
165
  saveFetch,
@@ -155,5 +167,7 @@ defineExpose({
155
167
 
156
168
  cancel,
157
169
  save,
170
+ show,
171
+ hide,
158
172
  });
159
173
  </script>
@@ -0,0 +1,159 @@
1
+ <template>
2
+ <TMagicDrawer
3
+ class="m-form-drawer"
4
+ ref="drawer"
5
+ v-model="visible"
6
+ :title="title"
7
+ :close-on-press-escape="closeOnPressEscape"
8
+ :append-to-body="true"
9
+ :show-close="true"
10
+ :close-on-click-modal="true"
11
+ :size="width"
12
+ :zIndex="zIndex"
13
+ :before-close="beforeClose"
14
+ @open="openHandler"
15
+ @opened="openedHandler"
16
+ @close="closeHandler"
17
+ @closed="closedHandler"
18
+ >
19
+ <div v-if="visible" ref="drawerBody" class="m-drawer-body">
20
+ <Form
21
+ ref="form"
22
+ :size="size"
23
+ :disabled="disabled"
24
+ :config="config"
25
+ :init-values="values"
26
+ :parent-values="parentValues"
27
+ :label-width="labelWidth"
28
+ :label-position="labelPosition"
29
+ :inline="inline"
30
+ @change="changeHandler"
31
+ ></Form>
32
+ <slot></slot>
33
+ </div>
34
+
35
+ <template #footer>
36
+ <TMagicRow class="dialog-footer">
37
+ <TMagicCol :span="12" style="text-align: left">
38
+ <div style="min-height: 1px">
39
+ <slot name="left"></slot>
40
+ </div>
41
+ </TMagicCol>
42
+ <TMagicCol :span="12">
43
+ <slot name="footer">
44
+ <TMagicButton @click="handleClose">关闭</TMagicButton>
45
+ <TMagicButton type="primary" :disabled="disabled" :loading="saveFetch" @click="submitHandler">{{
46
+ confirmText
47
+ }}</TMagicButton>
48
+ </slot>
49
+ </TMagicCol>
50
+ </TMagicRow>
51
+ </template>
52
+ </TMagicDrawer>
53
+ </template>
54
+
55
+ <script setup lang="ts">
56
+ import { ref, watchEffect } from 'vue';
57
+
58
+ import { TMagicButton, TMagicCol, TMagicDrawer, TMagicRow } from '@tmagic/design';
59
+
60
+ import Form from './Form.vue';
61
+ import type { FormConfig } from './schema';
62
+
63
+ defineOptions({
64
+ name: 'MFormDialog',
65
+ });
66
+
67
+ withDefaults(
68
+ defineProps<{
69
+ config?: FormConfig;
70
+ values?: Object;
71
+ parentValues?: Object;
72
+ width?: string | number;
73
+ labelWidth?: string;
74
+ disabled?: boolean;
75
+ closeOnPressEscape?: boolean;
76
+ title?: string;
77
+ zIndex?: number;
78
+ size?: 'small' | 'default' | 'large';
79
+ confirmText?: string;
80
+ inline?: boolean;
81
+ labelPosition?: string;
82
+ /** 关闭前的回调,会暂停 Drawer 的关闭; done 是个 function type 接受一个 boolean 参数, 执行 done 使用 true 参数或不提供参数将会终止关闭 */
83
+ beforeClose?: (done: (cancel?: boolean) => void) => void;
84
+ }>(),
85
+ {
86
+ closeOnPressEscape: true,
87
+ config: () => [],
88
+ values: () => ({}),
89
+ confirmText: '确定',
90
+ },
91
+ );
92
+
93
+ const emit = defineEmits(['close', 'closed', 'submit', 'error', 'change', 'open', 'opened']);
94
+
95
+ const drawer = ref<InstanceType<typeof TMagicDrawer>>();
96
+ const form = ref<InstanceType<typeof Form>>();
97
+ const drawerBody = ref<HTMLDivElement>();
98
+ const visible = ref(false);
99
+ const saveFetch = ref(false);
100
+ const bodyHeight = ref(0);
101
+
102
+ watchEffect(() => {
103
+ if (drawerBody.value) {
104
+ bodyHeight.value = drawerBody.value.clientHeight;
105
+ }
106
+ });
107
+
108
+ const submitHandler = async () => {
109
+ try {
110
+ const values = await form.value?.submitForm();
111
+ emit('submit', values);
112
+ } catch (e) {
113
+ emit('error', e);
114
+ }
115
+ };
116
+
117
+ const changeHandler = (value: any) => {
118
+ emit('change', value);
119
+ };
120
+
121
+ const openHandler = () => {
122
+ emit('open');
123
+ };
124
+
125
+ const openedHandler = () => {
126
+ emit('opened');
127
+ };
128
+
129
+ const closeHandler = () => {
130
+ emit('close');
131
+ };
132
+
133
+ const closedHandler = () => {
134
+ emit('closed');
135
+ };
136
+
137
+ const show = () => {
138
+ visible.value = true;
139
+ };
140
+
141
+ const hide = () => {
142
+ visible.value = false;
143
+ };
144
+
145
+ /** 用于关闭 Drawer, 该方法会调用传入的 before-close 方法 */
146
+ const handleClose = () => {
147
+ drawer.value?.handleClose();
148
+ };
149
+
150
+ defineExpose({
151
+ form,
152
+ saveFetch,
153
+ bodyHeight,
154
+
155
+ show,
156
+ hide,
157
+ handleClose,
158
+ });
159
+ </script>
@@ -2,8 +2,7 @@
2
2
  <div
3
3
  v-if="config"
4
4
  :style="config.tip ? 'display: flex;align-items: baseline;' : ''"
5
- :class="config.className"
6
- class="m-form-container"
5
+ :class="`m-form-container m-container-${type || ''} ${config.className || ''}`"
7
6
  >
8
7
  <m-fields-hidden
9
8
  v-if="type === 'hidden'"
@@ -15,7 +14,7 @@
15
14
  ></m-fields-hidden>
16
15
 
17
16
  <component
18
- v-else-if="items && !config.text && type && display"
17
+ v-else-if="items && !text && type && display"
19
18
  :key="key(config)"
20
19
  :size="size"
21
20
  :is="tagName"
@@ -36,12 +35,12 @@
36
35
  <template v-else-if="type && display && !showDiff">
37
36
  <TMagicFormItem
38
37
  :style="config.tip ? 'flex: 1' : ''"
39
- :class="{ hidden: `${itemLabelWidth}` === '0' || !config.text }"
38
+ :class="{ hidden: `${itemLabelWidth}` === '0' || !text }"
40
39
  :prop="itemProp"
41
40
  :label-width="itemLabelWidth"
42
41
  :rules="rule"
43
42
  >
44
- <template #label><span v-html="type === 'checkbox' ? '' : config.text"></span></template>
43
+ <template #label><span v-html="type === 'checkbox' ? '' : text"></span></template>
45
44
  <TMagicTooltip v-if="tooltip">
46
45
  <component
47
46
  :key="key(config)"
@@ -92,13 +91,13 @@
92
91
  <!-- 上次内容 -->
93
92
  <TMagicFormItem
94
93
  :style="config.tip ? 'flex: 1' : ''"
95
- :class="{ hidden: `${itemLabelWidth}` === '0' || !config.text }"
94
+ :class="{ hidden: `${itemLabelWidth}` === '0' || !text }"
96
95
  :prop="itemProp"
97
96
  :label-width="itemLabelWidth"
98
97
  :rules="rule"
99
98
  style="background: #f7dadd"
100
99
  >
101
- <template #label><span v-html="type === 'checkbox' ? '' : config.text"></span></template>
100
+ <template #label><span v-html="type === 'checkbox' ? '' : text"></span></template>
102
101
  <TMagicTooltip v-if="tooltip">
103
102
  <component
104
103
  :key="key(config)"
@@ -141,13 +140,13 @@
141
140
  <!-- 当前内容 -->
142
141
  <TMagicFormItem
143
142
  :style="config.tip ? 'flex: 1' : ''"
144
- :class="{ hidden: `${itemLabelWidth}` === '0' || !config.text }"
143
+ :class="{ hidden: `${itemLabelWidth}` === '0' || !text }"
145
144
  :prop="itemProp"
146
145
  :label-width="itemLabelWidth"
147
146
  :rules="rule"
148
147
  style="background: #def7da"
149
148
  >
150
- <template #label><span v-html="type === 'checkbox' ? '' : config.text"></span></template>
149
+ <template #label><span v-html="type === 'checkbox' ? '' : text"></span></template>
151
150
  <TMagicTooltip v-if="tooltip">
152
151
  <component
153
152
  :key="key(config)"
@@ -295,6 +294,8 @@ const tagName = computed(() => {
295
294
 
296
295
  const disabled = computed(() => props.disabled || filterFunction(mForm, props.config.disabled, props));
297
296
 
297
+ const text = computed(() => filterFunction(mForm, props.config.text, props));
298
+
298
299
  const tooltip = computed(() => filterFunction(mForm, props.config.tooltip, props));
299
300
 
300
301
  const extra = computed(() => filterFunction(mForm, props.config.extra, props));
@@ -332,7 +333,7 @@ watch(
332
333
  showDiff,
333
334
  (showDiff) => {
334
335
  if (type.value === 'hidden') return;
335
- if (items.value && !props.config.text && type.value && display.value) return;
336
+ if (items.value && !text.value && type.value && display.value) return;
336
337
  if (display.value && showDiff && type.value) {
337
338
  emit('addDiffCount');
338
339
  }
@@ -132,6 +132,7 @@ const toggleMode = () => {
132
132
  text: null,
133
133
  }))) as any;
134
134
  };
135
+
135
136
  const onAddDiffCount = () => emit('addDiffCount');
136
137
 
137
138
  const getLastValues = (item: any, index: number) => item?.[index] || {};
@@ -88,7 +88,13 @@ const title = computed(() => {
88
88
  return props.model[props.config.titleKey];
89
89
  }
90
90
 
91
- return `组 ${String(props.index)}`;
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)}`;
92
98
  });
93
99
 
94
100
  const length = computed(() => props.groupModel?.length || 0);
@@ -113,7 +119,7 @@ const showDelete = (index: number) => {
113
119
  };
114
120
 
115
121
  // 调换顺序
116
- const changeOrder = (offset = 0) => emit('swap-item', props.index, `${String(props.index)}${offset}`);
122
+ const changeOrder = (offset = 0) => emit('swap-item', props.index, props.index + offset);
117
123
 
118
124
  const movable = () => {
119
125
  const { movable } = props.config;