@tmagic/form 1.8.0-beta.8 → 1.8.0-manmanyu.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 (72) hide show
  1. package/dist/es/Form.vue_vue_type_script_setup_true_lang.js +45 -6
  2. package/dist/es/FormBox.vue_vue_type_script_setup_true_lang.js +1 -1
  3. package/dist/es/FormDialog.vue_vue_type_script_setup_true_lang.js +13 -6
  4. package/dist/es/FormDrawer.vue_vue_type_script_setup_true_lang.js +38 -13
  5. package/dist/es/containers/Col.vue_vue_type_script_setup_true_lang.js +1 -1
  6. package/dist/es/containers/Container.vue_vue_type_script_setup_true_lang.js +22 -17
  7. package/dist/es/containers/Fieldset.vue_vue_type_script_setup_true_lang.js +1 -1
  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 +1 -1
  11. package/dist/es/containers/GroupListItem.vue_vue_type_script_setup_true_lang.js +23 -19
  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 +1 -1
  19. package/dist/es/containers/table/useTableColumns.js +5 -2
  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 +5 -2
  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 +5 -2
  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 +5 -2
  26. package/dist/es/fields/DateTime.vue_vue_type_script_setup_true_lang.js +5 -2
  27. package/dist/es/fields/Daterange.vue_vue_type_script_setup_true_lang.js +5 -2
  28. package/dist/es/fields/Display.vue_vue_type_script_setup_true_lang.js +5 -2
  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 +5 -2
  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 +17 -9
  35. package/dist/es/fields/Select.vue_vue_type_script_setup_true_lang.js +5 -2
  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 +5 -2
  41. package/dist/es/plugin.js +2 -0
  42. package/dist/es/style.css +120 -8
  43. package/dist/es/utils/form.js +2 -2
  44. package/dist/style.css +120 -8
  45. package/dist/themes/magic-admin.css +494 -0
  46. package/dist/tmagic-form.umd.cjs +1850 -1640
  47. package/package.json +5 -5
  48. package/src/Form.vue +53 -4
  49. package/src/FormDialog.vue +14 -3
  50. package/src/FormDrawer.vue +40 -12
  51. package/src/containers/Container.vue +14 -5
  52. package/src/containers/GroupListItem.vue +14 -12
  53. package/src/containers/Panel.vue +10 -3
  54. package/src/containers/table/ActionsColumn.vue +10 -4
  55. package/src/containers/table/useTableColumns.ts +8 -2
  56. package/src/containers/table-group-list/TableGroupList.vue +7 -1
  57. package/src/fields/Link.vue +17 -3
  58. package/src/fields/RadioGroup.vue +11 -5
  59. package/src/fields/Text.vue +43 -19
  60. package/src/plugin.ts +2 -0
  61. package/src/theme/container.scss +3 -0
  62. package/src/theme/fieldset.scss +50 -0
  63. package/src/theme/form.scss +6 -0
  64. package/src/theme/group-list.scss +8 -7
  65. package/src/theme/index.scss +1 -0
  66. package/src/theme/link.scss +17 -0
  67. package/src/theme/panel.scss +1 -1
  68. package/src/theme/radio-group.scss +23 -0
  69. package/src/theme/tabs.scss +2 -2
  70. package/src/theme/text.scss +38 -0
  71. package/src/theme/themes/magic-admin/index.scss +91 -0
  72. package/types/index.d.ts +46 -1
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.8.0-beta.8",
2
+ "version": "1.8.0-manmanyu.10",
3
3
  "name": "@tmagic/form",
4
4
  "type": "module",
5
5
  "sideEffects": [
@@ -50,11 +50,11 @@
50
50
  "@vue/test-utils": "^2.4.6"
51
51
  },
52
52
  "peerDependencies": {
53
- "vue": "^3.5.34",
53
+ "vue": "^3.5.38",
54
54
  "typescript": "^6.0.3",
55
- "@tmagic/design": "1.8.0-beta.8",
56
- "@tmagic/utils": "1.8.0-beta.8",
57
- "@tmagic/form-schema": "1.8.0-beta.8"
55
+ "@tmagic/design": "1.8.0-manmanyu.10",
56
+ "@tmagic/utils": "1.8.0-manmanyu.10",
57
+ "@tmagic/form-schema": "1.8.0-manmanyu.10"
58
58
  },
59
59
  "peerDependenciesMeta": {
60
60
  "typescript": {
package/src/Form.vue CHANGED
@@ -1,6 +1,10 @@
1
1
  <template>
2
2
  <TMagicForm
3
- class="m-form"
3
+ :class="[
4
+ 'm-form',
5
+ effectiveTheme ? `m-form--${effectiveTheme}` : '',
6
+ effectiveTheme ? `m-theme--${effectiveTheme}` : '',
7
+ ]"
4
8
  ref="tMagicForm"
5
9
  :model="values"
6
10
  :label-width="labelWidth"
@@ -32,10 +36,10 @@
32
36
  </template>
33
37
 
34
38
  <script setup lang="ts">
35
- import { provide, reactive, ref, shallowRef, toRaw, useTemplateRef, watch, watchEffect } from 'vue';
39
+ import { computed, inject, provide, reactive, ref, shallowRef, toRaw, useTemplateRef, watch, watchEffect } from 'vue';
36
40
  import { cloneDeep, isEqual } from 'lodash-es';
37
41
 
38
- import { TMagicForm, tMagicMessage, tMagicMessageBox } from '@tmagic/design';
42
+ import { M_THEME_KEY, TMagicForm, tMagicMessage, tMagicMessageBox } from '@tmagic/design';
39
43
  import { setValueByKeyPath } from '@tmagic/utils';
40
44
 
41
45
  import Container from './containers/Container.vue';
@@ -107,6 +111,15 @@ const props = withDefaults(
107
111
  * 通过 provide 下发,对整棵表单的所有层级 Container 生效,只需在 MForm 这一层传一次。
108
112
  */
109
113
  selfDiffFieldTypes?: string[] | ((_defaultTypes: string[]) => string[]);
114
+ /**
115
+ * 主题名称:对应 `packages/form/src/theme/themes/<theme>/index.scss` 的目录名。
116
+ *
117
+ * 设置后会在表单根元素上追加 `m-form--<theme>` 修饰类,配合按需引入
118
+ * `@tmagic/form/dist/themes/<theme>.css` 即可启用主题样式。
119
+ *
120
+ * 例如:`<MForm theme="magic-admin" />` + `import '@tmagic/form/dist/themes/magic-admin.css'`。
121
+ */
122
+ theme?: string;
110
123
  }>(),
111
124
  {
112
125
  config: () => [],
@@ -134,6 +147,27 @@ const fields = new Map<string, any>();
134
147
 
135
148
  const requestFuc = getConfig('request') as Function;
136
149
 
150
+ /**
151
+ * 当前表单生效的主题名称:
152
+ * - 优先用本组件自己的 `props.theme`;
153
+ * - 没设置时回退到最近祖先 `<MEditor>` / `<MForm>` provide 的主题,便于内嵌于编辑器
154
+ * 时自动跟随外层主题,无需在每个 `MForm` 上重复传 `theme`。
155
+ *
156
+ * 同时把合并后的值再 provide 出去(见下方 `provide(M_THEME_KEY, ...)`),让 form 子树
157
+ * 里再嵌套的 portal 组件(`TMagicPopover` 等)依然能拿到非空主题。
158
+ */
159
+ const ancestorTheme = inject(M_THEME_KEY, null);
160
+ const effectiveTheme = computed(() => props.theme || ancestorTheme?.value || '');
161
+
162
+ /**
163
+ * 拼到 `formState.popperClass` 上的主题修饰类(仅 `m-theme--<theme>`,
164
+ * 不带 `m-form` / `m-editor` 前缀,因为 Element Plus 弹层节点本身既不是 form 也不是 editor)。
165
+ *
166
+ * 这条类会随所有读 `mForm.popperClass` 的字段(Select / DateTime / Cascader 等)下发到
167
+ * Element Plus 的 `popper-class`,让 portal 节点也命中 `m-theme--<theme>` 上的 CSS 变量。
168
+ */
169
+ const themeClass = computed(() => (effectiveTheme.value ? `m-theme--${effectiveTheme.value}` : ''));
170
+
137
171
  /**
138
172
  * formState 实现说明:
139
173
  *
@@ -150,13 +184,21 @@ const requestFuc = getConfig('request') as Function;
150
184
  * 把最新值刷进 formState。
151
185
  * - accessor 描述符(`{ get stage() { return ... } }`)按原样写入,调用方可以控制
152
186
  * 读时求值,每次读取都会重新执行 getter。
187
+ *
188
+ * 4. `popperClass` 会自动拼接 `themeClass`:调用方传入的 `popperClass` + 当前主题
189
+ * 修饰类(含祖先 `<MEditor>` provide 的主题)。这样所有透传到 Element Plus 弹层
190
+ * `popper-class` 的字段(Select / DateTime / Cascader 等)能自带主题作用域。
153
191
  */
154
192
  const formState: FormState = reactive<FormState>({
155
193
  get keyProp() {
156
194
  return props.keyProp;
157
195
  },
158
196
  get popperClass() {
159
- return props.popperClass;
197
+ const userClass = props.popperClass ?? '';
198
+ const tc = themeClass.value;
199
+ if (!userClass) return tc;
200
+ if (!tc) return userClass;
201
+ return `${userClass} ${tc}`;
160
202
  },
161
203
  get config() {
162
204
  return props.config;
@@ -243,6 +285,13 @@ watchEffect(async (onCleanup) => {
243
285
 
244
286
  provide('mForm', formState);
245
287
 
288
+ /**
289
+ * 把生效主题(自身或祖先)再 provide 出去,供 form 子树内含 `Teleport` 的组件
290
+ * (如 `TMagicPopover`)在传送目标上挂 `m-theme--<theme>` 类。
291
+ * 详见 `@tmagic/design/theme.ts`。
292
+ */
293
+ provide(M_THEME_KEY, effectiveTheme);
294
+
246
295
  // 对比相关配置单独通过 provide 下发,所有层级的 Container 通过 inject 获取,无需逐层透传 prop。
247
296
  // 用 getter 对象保证读取时回到最新的 props 值,维持响应式。
248
297
  provide(FORM_DIFF_CONFIG_KEY, {
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <TMagicDialog
3
3
  v-model="dialogVisible"
4
- class="m-form-dialog"
4
+ :class="['m-form-dialog', effectiveTheme ? `m-theme--${effectiveTheme}` : '']"
5
5
  top="20px"
6
6
  append-to-body
7
7
  :title="title"
@@ -32,6 +32,7 @@
32
32
  :inline="inline"
33
33
  :prevent-submit-default="preventSubmitDefault"
34
34
  :extend-state="extendState"
35
+ :theme="effectiveTheme"
35
36
  @change="changeHandler"
36
37
  ></Form>
37
38
  <slot></slot>
@@ -64,9 +65,9 @@
64
65
  </template>
65
66
 
66
67
  <script setup lang="ts">
67
- import { computed, ref } from 'vue';
68
+ import { computed, inject, provide, ref } from 'vue';
68
69
 
69
- import { TMagicButton, TMagicCol, TMagicDialog, TMagicRow } from '@tmagic/design';
70
+ import { M_THEME_KEY, TMagicButton, TMagicCol, TMagicDialog, TMagicRow } from '@tmagic/design';
70
71
 
71
72
  import Form from './Form.vue';
72
73
  import { ContainerChangeEventData, FormConfig, FormState, FormValue, StepConfig } from './schema';
@@ -98,6 +99,12 @@ const props = withDefaults(
98
99
  showCancel?: boolean;
99
100
  /** 透传给内部 `MForm`,用于扩展 `formState`(如注入 `$message` / `$store` 等) */
100
101
  extendState?: (_state: FormState) => Record<string, any> | Promise<Record<string, any>>;
102
+ /**
103
+ * 主题名。优先级:传入 `theme` prop > 祖先 `provide(M_THEME_KEY)` > 空串。
104
+ * 计算结果会再次 `provide` 出去,使得 Dialog 被 Teleport 到 body 后,内部子树
105
+ * (包括 `MForm` 以及更深的 popover / dropdown)仍能拿到主题。
106
+ */
107
+ theme?: string;
101
108
  }>(),
102
109
  {
103
110
  config: () => [],
@@ -111,6 +118,10 @@ const props = withDefaults(
111
118
  },
112
119
  );
113
120
 
121
+ const ancestorTheme = inject(M_THEME_KEY, null);
122
+ const effectiveTheme = computed(() => props.theme || ancestorTheme?.value || '');
123
+ provide(M_THEME_KEY, effectiveTheme);
124
+
114
125
  const emit = defineEmits(['close', 'submit', 'error', 'change']);
115
126
 
116
127
  const form = ref<InstanceType<typeof Form>>();
@@ -1,8 +1,8 @@
1
1
  <template>
2
2
  <TMagicDrawer
3
- class="m-form-drawer"
3
+ :class="['m-form-drawer', effectiveTheme ? `m-theme--${effectiveTheme}` : '']"
4
4
  ref="drawer"
5
- v-model="visible"
5
+ v-model="dialogVisible"
6
6
  :title="title"
7
7
  :close-on-press-escape="closeOnPressEscape"
8
8
  :append-to-body="true"
@@ -16,7 +16,7 @@
16
16
  @close="closeHandler"
17
17
  @closed="closedHandler"
18
18
  >
19
- <div v-if="visible" ref="drawerBody" class="m-drawer-body">
19
+ <div v-if="dialogVisible" ref="drawerBody" class="m-drawer-body">
20
20
  <Form
21
21
  ref="form"
22
22
  :size="size"
@@ -29,6 +29,7 @@
29
29
  :inline="inline"
30
30
  :prevent-submit-default="preventSubmitDefault"
31
31
  :extend-state="extendState"
32
+ :theme="effectiveTheme"
32
33
  @change="changeHandler"
33
34
  ></Form>
34
35
  <slot></slot>
@@ -55,18 +56,18 @@
55
56
  </template>
56
57
 
57
58
  <script setup lang="ts">
58
- import { ref, watchEffect } from 'vue';
59
+ import { computed, inject, provide, ref, watchEffect } from 'vue';
59
60
 
60
- import { TMagicButton, TMagicCol, TMagicDrawer, TMagicRow } from '@tmagic/design';
61
+ import { M_THEME_KEY, TMagicButton, TMagicCol, TMagicDrawer, TMagicRow } from '@tmagic/design';
61
62
 
62
63
  import Form from './Form.vue';
63
64
  import type { ContainerChangeEventData, FormConfig, FormState, FormValue } from './schema';
64
65
 
65
66
  defineOptions({
66
- name: 'MFormDialog',
67
+ name: 'MFormDrawer',
67
68
  });
68
69
 
69
- withDefaults(
70
+ const props = withDefaults(
70
71
  defineProps<{
71
72
  config?: FormConfig;
72
73
  values?: Object;
@@ -86,6 +87,12 @@ withDefaults(
86
87
  beforeClose?: (_done: (_cancel?: boolean) => void) => void;
87
88
  /** 透传给内部 `MForm`,用于扩展 `formState`(如注入 `$message` / `$store` 等) */
88
89
  extendState?: (_state: FormState) => Record<string, any> | Promise<Record<string, any>>;
90
+ /**
91
+ * 主题名。优先级:传入 `theme` prop > 祖先 `provide(M_THEME_KEY)` > 空串。
92
+ * 计算结果会再次 `provide` 出去,使得 Drawer 被 Teleport 到 body 后,内部子树
93
+ * (包括 `MForm` 以及更深的 popover / dropdown)仍能拿到主题。
94
+ */
95
+ theme?: string;
89
96
  }>(),
90
97
  {
91
98
  closeOnPressEscape: true,
@@ -95,12 +102,16 @@ withDefaults(
95
102
  },
96
103
  );
97
104
 
105
+ const ancestorTheme = inject(M_THEME_KEY, null);
106
+ const effectiveTheme = computed(() => props.theme || ancestorTheme?.value || '');
107
+ provide(M_THEME_KEY, effectiveTheme);
108
+
98
109
  const emit = defineEmits(['close', 'closed', 'submit', 'error', 'change', 'open', 'opened']);
99
110
 
100
111
  const drawer = ref<InstanceType<typeof TMagicDrawer>>();
101
112
  const form = ref<InstanceType<typeof Form>>();
102
113
  const drawerBody = ref<HTMLDivElement>();
103
- const visible = ref(false);
114
+ const dialogVisible = ref(false);
104
115
  const saveFetch = ref(false);
105
116
  const bodyHeight = ref(0);
106
117
 
@@ -141,25 +152,42 @@ const closedHandler = () => {
141
152
  };
142
153
 
143
154
  const show = () => {
144
- visible.value = true;
155
+ dialogVisible.value = true;
145
156
  };
146
157
 
147
158
  const hide = () => {
148
- visible.value = false;
159
+ dialogVisible.value = false;
160
+ };
161
+ const close = () => {
162
+ dialogVisible.value = false;
163
+ };
164
+ const cancel = () => {
165
+ hide();
149
166
  };
150
-
151
167
  /** 用于关闭 Drawer, 该方法会调用传入的 before-close 方法 */
152
168
  const handleClose = () => {
153
169
  drawer.value?.handleClose();
154
170
  };
155
171
 
172
+ const save = async () => {
173
+ try {
174
+ const changeRecords = [...(form.value?.changeRecords || [])];
175
+ const values = await form.value?.submitForm();
176
+ emit('submit', values, { changeRecords });
177
+ } catch (e) {
178
+ emit('error', e);
179
+ }
180
+ };
181
+
156
182
  defineExpose({
157
183
  form,
158
184
  saveFetch,
159
185
  bodyHeight,
160
-
186
+ close,
161
187
  show,
162
188
  hide,
189
+ save,
190
+ cancel,
163
191
  handleClose,
164
192
  });
165
193
  </script>
@@ -33,6 +33,9 @@
33
33
  :label-title="config.labelTitle"
34
34
  :text="text"
35
35
  ></FormLabel>
36
+ <span class="m-form-tip m-form-title-extra" v-if="config.titleExtra && config.labelPosition === 'top'">
37
+ {{ config.titleExtra }}</span
38
+ >
36
39
  </slot>
37
40
  </template>
38
41
 
@@ -220,17 +223,23 @@
220
223
  </template>
221
224
  </template>
222
225
 
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>
226
+ <div class="m-form-container-expand" v-if="config.expand && type !== 'fieldset'">
227
+ <TMagicButton
228
+ type="primary"
229
+ size="small"
230
+ :disabled="false"
231
+ link
232
+ @click="expandHandler"
233
+ :icon="expand ? ArrowUp : ArrowDown"
234
+ >{{ expand ? '收起配置' : '展开更多配置' }}</TMagicButton
235
+ >
227
236
  </div>
228
237
  </div>
229
238
  </template>
230
239
 
231
240
  <script setup lang="ts">
232
241
  import { computed, inject, readonly, ref, toRaw, watch, watchEffect } from 'vue';
233
- import { WarningFilled } from '@element-plus/icons-vue';
242
+ import { ArrowDown, ArrowUp, WarningFilled } from '@element-plus/icons-vue';
234
243
  import { isEqual } from 'lodash-es';
235
244
 
236
245
  import { TMagicButton, TMagicFormItem, TMagicIcon, TMagicTooltip } from '@tmagic/design';
@@ -1,17 +1,19 @@
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
+ <span v-html="title"></span>
10
+
9
11
  <TMagicButton
10
12
  v-if="!isCompare"
11
13
  v-show="showDelete"
12
- type="danger"
13
- size="small"
14
+ size="default"
14
15
  link
16
+ class="delete-button"
15
17
  :icon="Delete"
16
18
  :disabled="disabled"
17
19
  @click="removeHandler"
@@ -20,7 +22,7 @@
20
22
  <TMagicButton
21
23
  v-if="copyable && !isCompare"
22
24
  link
23
- size="small"
25
+ size="default"
24
26
  type="primary"
25
27
  :icon="DocumentCopy"
26
28
  :disabled="disabled"
@@ -32,18 +34,18 @@
32
34
  <TMagicButton
33
35
  v-show="index !== 0"
34
36
  link
35
- size="small"
37
+ size="default"
36
38
  :disabled="disabled"
37
- :icon="CaretTop"
39
+ :icon="Top"
38
40
  @click="changeOrder(-1)"
39
41
  >上移</TMagicButton
40
42
  >
41
43
  <TMagicButton
42
44
  v-show="index !== length - 1"
43
45
  link
44
- size="small"
46
+ size="default"
45
47
  :disabled="disabled"
46
- :icon="CaretBottom"
48
+ :icon="Bottom"
47
49
  @click="changeOrder(1)"
48
50
  >下移</TMagicButton
49
51
  >
@@ -107,7 +109,7 @@
107
109
 
108
110
  <script setup lang="ts">
109
111
  import { computed, inject, ref } from 'vue';
110
- import { CaretBottom, CaretRight, CaretTop, Delete, DocumentCopy, Position } from '@element-plus/icons-vue';
112
+ import { ArrowDown, ArrowRight, Bottom, Delete, DocumentCopy, Position, Top } from '@element-plus/icons-vue';
111
113
 
112
114
  import { TMagicButton, TMagicCard, TMagicIcon, TMagicInputNumber, TMagicPopover } from '@tmagic/design';
113
115
 
@@ -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');
@@ -2,7 +2,7 @@ import { computed, h, inject, type Ref } from 'vue';
2
2
  import { WarningFilled } from '@element-plus/icons-vue';
3
3
  import { cloneDeep } from 'lodash-es';
4
4
 
5
- import { type TableColumnOptions, TMagicIcon, TMagicTooltip } from '@tmagic/design';
5
+ import { isMagicAdminTheme, type TableColumnOptions, TMagicIcon, TMagicTooltip } from '@tmagic/design';
6
6
  import type { FormItemConfig, FormState, TableColumnConfig } from '@tmagic/form-schema';
7
7
 
8
8
  import type { ContainerChangeEventData } from '../../schema';
@@ -21,6 +21,9 @@ export const useTableColumns = (
21
21
  modelName: Ref<string | number>,
22
22
  ) => {
23
23
  const mForm = inject<FormState | undefined>('mForm');
24
+ // magic-admin 主题下「操作列」默认固定在右侧;其它主题保持原默认「左侧」。
25
+ // 调用方仍可通过 `config.fixed`('left' | 'right' | false)显式覆盖。
26
+ const isMagicAdmin = isMagicAdminTheme();
24
27
 
25
28
  const display = (fuc: any) => displayFunc(mForm, fuc, props);
26
29
 
@@ -111,8 +114,9 @@ export const useTableColumns = (
111
114
  },
112
115
  });
113
116
  }
117
+ const defaultFixed: 'left' | 'right' = isMagicAdmin.value ? 'right' : 'left';
114
118
 
115
- let actionFixed: 'left' | 'right' | undefined = props.config.fixed === false ? undefined : 'left';
119
+ let actionFixed: 'left' | 'right' | undefined = props.config.fixed === false ? undefined : defaultFixed;
116
120
 
117
121
  if (typeof props.config.fixed === 'string' && ['left', 'right'].includes(props.config.fixed)) {
118
122
  actionFixed = props.config.fixed;
@@ -122,12 +126,14 @@ export const useTableColumns = (
122
126
  props: {
123
127
  label: '操作',
124
128
  fixed: actionFixed,
129
+
125
130
  width: props.config.operateColWidth ?? (props.config.dropSortHandle && props.config.dropSort ? 132 : 112),
126
131
  align: 'center',
127
132
  },
128
133
  cell: ({ row, $index }: any) =>
129
134
  h(ActionsColumn, {
130
135
  row,
136
+ flat: props.config.flat,
131
137
  index: $index,
132
138
  model: props.model,
133
139
  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="isMagicAdmin && 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,8 +29,9 @@
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 { isMagicAdminTheme, TMagicButton, TMagicIcon } from '@tmagic/design';
23
35
 
24
36
  import FormDialog from '../FormDialog.vue';
25
37
  import type { FieldProps, FormState, LinkConfig } from '../schema';
@@ -29,10 +41,12 @@ defineOptions({
29
41
  name: 'MFormLink',
30
42
  });
31
43
 
32
- const props = defineProps<FieldProps<LinkConfig>>();
44
+ const props = defineProps<FieldProps<LinkConfig> & { theme?: string }>();
33
45
 
34
46
  const emit = defineEmits(['change']);
35
47
 
48
+ const isMagicAdmin = isMagicAdminTheme(props);
49
+
36
50
  useAddField(props.prop);
37
51
 
38
52
  const formValue = ref({});
@@ -8,9 +8,14 @@
8
8
  @click="clickHandler(option.value)"
9
9
  >
10
10
  <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>
11
+ <div class="m-fields-radio-group__option">
12
+ <TMagicIcon
13
+ v-if="option.icon"
14
+ :size="iconSize"
15
+ :class="{ 'm-fields-radio-group__icon_with_text': !!option.text }"
16
+ ><component :is="option.icon"></component
17
+ ></TMagicIcon>
18
+ <span v-if="option.text" class="m-fields-radio-group__text">{{ option.text }}</span>
14
19
  </div>
15
20
  </TMagicTooltip>
16
21
  </component>
@@ -42,13 +47,14 @@ const clickHandler = (item: string | number | boolean) => {
42
47
 
43
48
  useAddField(props.prop);
44
49
 
50
+ // 这里换了设计稿里的图标,所以需要调整一下图标大小
45
51
  const iconSize = computed(() => {
46
52
  if (props.size === 'small') {
47
- return '12';
53
+ return '14';
48
54
  }
49
55
  if (props.size === 'large') {
50
56
  return '16';
51
57
  }
52
- return '14';
58
+ return '16';
53
59
  });
54
60
  </script>