@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.
Files changed (91) hide show
  1. package/dist/es/Form.vue_vue_type_script_setup_true_lang.js +120 -27
  2. package/dist/es/FormBox.vue_vue_type_script_setup_true_lang.js +19 -3
  3. package/dist/es/FormDialog.vue_vue_type_script_setup_true_lang.js +30 -7
  4. package/dist/es/FormDrawer.vue_vue_type_script_setup_true_lang.js +56 -14
  5. package/dist/es/containers/Col.vue_vue_type_script_setup_true_lang.js +3 -2
  6. package/dist/es/containers/Container.vue_vue_type_script_setup_true_lang.js +51 -36
  7. package/dist/es/containers/Fieldset.vue_vue_type_script_setup_true_lang.js +5 -3
  8. package/dist/es/containers/FlexLayout.vue_vue_type_script_setup_true_lang.js +1 -1
  9. package/dist/es/containers/FormLabel.vue_vue_type_script_setup_true_lang.js +1 -1
  10. package/dist/es/containers/GroupList.vue_vue_type_script_setup_true_lang.js +7 -6
  11. package/dist/es/containers/GroupListItem.vue_vue_type_script_setup_true_lang.js +42 -32
  12. package/dist/es/containers/Panel.vue_vue_type_script_setup_true_lang.js +17 -11
  13. package/dist/es/containers/Row.vue_vue_type_script_setup_true_lang.js +1 -1
  14. package/dist/es/containers/Step.vue_vue_type_script_setup_true_lang.js +1 -1
  15. package/dist/es/containers/Tabs.vue_vue_type_script_setup_true_lang.js +1 -1
  16. package/dist/es/containers/table/ActionsColumn.vue_vue_type_script_setup_true_lang.js +14 -7
  17. package/dist/es/containers/table/SortColumn.vue_vue_type_script_setup_true_lang.js +1 -1
  18. package/dist/es/containers/table/Table.vue_vue_type_script_setup_true_lang.js +7 -5
  19. package/dist/es/containers/table/useTableColumns.js +5 -1
  20. package/dist/es/containers/table-group-list/TableGroupList.vue_vue_type_script_setup_true_lang.js +3 -2
  21. package/dist/es/fields/Cascader.vue_vue_type_script_setup_true_lang.js +6 -3
  22. package/dist/es/fields/Checkbox.vue_vue_type_script_setup_true_lang.js +5 -2
  23. package/dist/es/fields/CheckboxGroup.vue_vue_type_script_setup_true_lang.js +6 -3
  24. package/dist/es/fields/ColorPicker.vue_vue_type_script_setup_true_lang.js +5 -2
  25. package/dist/es/fields/Date.vue_vue_type_script_setup_true_lang.js +6 -3
  26. package/dist/es/fields/DateTime.vue_vue_type_script_setup_true_lang.js +6 -3
  27. package/dist/es/fields/Daterange.vue_vue_type_script_setup_true_lang.js +6 -3
  28. package/dist/es/fields/Display.vue_vue_type_script_setup_true_lang.js +6 -3
  29. package/dist/es/fields/DynamicField.vue_vue_type_script_setup_true_lang.js +5 -2
  30. package/dist/es/fields/Hidden.vue_vue_type_script_setup_true_lang.js +1 -1
  31. package/dist/es/fields/Link.vue_vue_type_script_setup_true_lang.js +30 -8
  32. package/dist/es/fields/Number.vue_vue_type_script_setup_true_lang.js +8 -3
  33. package/dist/es/fields/NumberRange.vue_vue_type_script_setup_true_lang.js +5 -2
  34. package/dist/es/fields/RadioGroup.vue_vue_type_script_setup_true_lang.js +21 -10
  35. package/dist/es/fields/Select.vue_vue_type_script_setup_true_lang.js +7 -3
  36. package/dist/es/fields/Switch.vue_vue_type_script_setup_true_lang.js +5 -2
  37. package/dist/es/fields/Text.vue_vue_type_script_setup_true_lang.js +113 -78
  38. package/dist/es/fields/Textarea.vue_vue_type_script_setup_true_lang.js +5 -2
  39. package/dist/es/fields/Time.vue_vue_type_script_setup_true_lang.js +5 -2
  40. package/dist/es/fields/Timerange.vue_vue_type_script_setup_true_lang.js +7 -4
  41. package/dist/es/index.js +5 -4
  42. package/dist/es/plugin.js +4 -0
  43. package/dist/es/schema.js +12 -1
  44. package/dist/es/style.css +133 -11
  45. package/dist/es/submitForm.js +415 -56
  46. package/dist/es/utils/config.js +4 -1
  47. package/dist/es/utils/form.js +84 -9
  48. package/dist/es/utils/typeMatch.js +487 -0
  49. package/dist/style.css +133 -11
  50. package/dist/themes/magic-admin.css +509 -0
  51. package/dist/tmagic-form.umd.cjs +1773 -399
  52. package/package.json +5 -5
  53. package/src/Form.vue +163 -30
  54. package/src/FormBox.vue +11 -0
  55. package/src/FormDialog.vue +25 -3
  56. package/src/FormDrawer.vue +51 -12
  57. package/src/containers/Col.vue +1 -0
  58. package/src/containers/Container.vue +32 -11
  59. package/src/containers/Fieldset.vue +5 -2
  60. package/src/containers/GroupList.vue +1 -1
  61. package/src/containers/GroupListItem.vue +28 -22
  62. package/src/containers/Panel.vue +10 -3
  63. package/src/containers/table/ActionsColumn.vue +10 -4
  64. package/src/containers/table/Table.vue +1 -0
  65. package/src/containers/table/useTableColumns.ts +7 -3
  66. package/src/containers/table-group-list/TableGroupList.vue +7 -1
  67. package/src/fields/Link.vue +16 -3
  68. package/src/fields/Number.vue +2 -1
  69. package/src/fields/RadioGroup.vue +24 -6
  70. package/src/fields/Text.vue +43 -19
  71. package/src/index.ts +11 -0
  72. package/src/plugin.ts +12 -0
  73. package/src/schema.ts +13 -1
  74. package/src/submitForm.ts +699 -66
  75. package/src/theme/container.scss +3 -0
  76. package/src/theme/fieldset.scss +51 -0
  77. package/src/theme/form-dialog.scss +1 -1
  78. package/src/theme/form.scss +6 -0
  79. package/src/theme/group-list.scss +19 -8
  80. package/src/theme/index.scss +1 -0
  81. package/src/theme/link.scss +17 -0
  82. package/src/theme/panel.scss +1 -1
  83. package/src/theme/radio-group.scss +23 -0
  84. package/src/theme/table.scss +11 -1
  85. package/src/theme/tabs.scss +2 -2
  86. package/src/theme/text.scss +38 -0
  87. package/src/theme/themes/magic-admin/index.scss +106 -0
  88. package/src/utils/config.ts +7 -1
  89. package/src/utils/form.ts +144 -22
  90. package/src/utils/typeMatch.ts +870 -0
  91. 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
- <MHidden v-if="type === 'hidden'" :name="`${name}`" :prop="itemProp" :model="model"></MHidden>
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 style="text-align: center" v-if="config.expand && type !== 'fieldset'">
224
- <TMagicButton type="primary" size="small" :disabled="false" link @click="expandHandler">{{
225
- expand ? '收起配置' : '展开更多配置'
226
- }}</TMagicButton>
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
- const curValue = name.value ? props.model[name.value] : props.model;
311
- const lastValue = name.value ? props.lastValues[name.value] : props.lastValues;
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="config.legend"></span><span v-if="config.extra" v-html="config.extra" class="m-form-tip"></span
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="config.legend"></span>
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">暂无数据</span>
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><CaretBottom v-if="expand" /><CaretRight v-else /></TMagicIcon><span v-html="title"></span>
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
- <TMagicButton
10
- v-if="!isCompare"
11
- v-show="showDelete"
12
- type="danger"
13
- size="small"
14
- link
15
- :icon="Delete"
16
- :disabled="disabled"
17
- @click="removeHandler"
18
- ></TMagicButton>
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="small"
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="small"
38
+ size="default"
36
39
  :disabled="disabled"
37
- :icon="CaretTop"
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="small"
47
+ size="default"
45
48
  :disabled="disabled"
46
- :icon="CaretBottom"
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 { CaretBottom, CaretRight, CaretTop, Delete, DocumentCopy, Position } from '@element-plus/icons-vue';
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
- return props.model[props.config.titleKey];
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) {
@@ -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 style="padding: 0" link :icon="expand ? CaretBottom : CaretRight" @click="expand = !expand">
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 { CaretBottom, CaretRight } from '@element-plus/icons-vue';
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
- ></TMagicButton>
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
- ></TMagicButton>
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');
@@ -27,6 +27,7 @@
27
27
  :key="updateKey"
28
28
  @select="selectHandle"
29
29
  @sort-change="sortChangeHandler"
30
+ :empty-text="`暂无${config.titlePrefix || ''}数据`"
30
31
  ></TMagicTable>
31
32
  </TMagicTooltip>
32
33
 
@@ -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 : 'left';
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
- {{ currentConfig.addButtonConfig?.text || (displayMode === 'table' ? '新增一行' : '新增') }}
45
+ {{
46
+ currentConfig.addButtonConfig?.text ||
47
+ (displayMode === 'table'
48
+ ? `新增一行${groupListConfig.titlePrefix || ''}`
49
+ : `新增${groupListConfig.titlePrefix || ''}`)
50
+ }}
45
51
  </TMagicButton>
46
52
  </template>
47
53
  </component>
@@ -1,5 +1,16 @@
1
1
  <template>
2
- <a v-if="config.href && !disabled" target="_blank" :href="href" :style="config.css || {}">{{ displayText }}</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
 
@@ -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 v-if="model" :model-value="model[name]" :size="size" :disabled="disabled">
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 v-if="option.icon" :size="iconSize"><component :is="option.icon"></component></TMagicIcon>
13
- <span v-if="option.text">{{ option.text }}</span>
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 '12';
65
+ return '14';
48
66
  }
49
67
  if (props.size === 'large') {
50
68
  return '16';
51
69
  }
52
- return '14';
70
+ return '16';
53
71
  });
54
72
  </script>
@@ -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: #409eff"
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
- if (typeof props.config.append === 'string') {
109
+ const { append } = props.config;
110
+
111
+ // 字符串形态:纯文本 append。
112
+ if (typeof append === 'string') {
84
113
  return {
85
114
  type: 'text',
86
- text: props.config.append,
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
- return props.config.append;
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;