@tmagic/form 1.8.0-beta.7 → 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.
- package/dist/es/Form.vue_vue_type_script_setup_true_lang.js +45 -6
- package/dist/es/FormBox.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/FormDialog.vue_vue_type_script_setup_true_lang.js +13 -6
- package/dist/es/FormDrawer.vue_vue_type_script_setup_true_lang.js +38 -13
- package/dist/es/containers/Col.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/containers/Container.vue_vue_type_script_setup_true_lang.js +22 -17
- package/dist/es/containers/Fieldset.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/containers/FlexLayout.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/containers/FormLabel.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/containers/GroupList.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/containers/GroupListItem.vue_vue_type_script_setup_true_lang.js +23 -19
- package/dist/es/containers/Panel.vue_vue_type_script_setup_true_lang.js +17 -11
- package/dist/es/containers/Row.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/containers/Step.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/containers/Tabs.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/containers/table/ActionsColumn.vue_vue_type_script_setup_true_lang.js +14 -7
- package/dist/es/containers/table/SortColumn.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/containers/table/Table.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/containers/table/useTableColumns.js +5 -2
- package/dist/es/containers/table-group-list/TableGroupList.vue_vue_type_script_setup_true_lang.js +3 -2
- package/dist/es/fields/Cascader.vue_vue_type_script_setup_true_lang.js +5 -2
- package/dist/es/fields/Checkbox.vue_vue_type_script_setup_true_lang.js +5 -2
- package/dist/es/fields/CheckboxGroup.vue_vue_type_script_setup_true_lang.js +5 -2
- package/dist/es/fields/ColorPicker.vue_vue_type_script_setup_true_lang.js +5 -2
- package/dist/es/fields/Date.vue_vue_type_script_setup_true_lang.js +5 -2
- package/dist/es/fields/DateTime.vue_vue_type_script_setup_true_lang.js +5 -2
- package/dist/es/fields/Daterange.vue_vue_type_script_setup_true_lang.js +5 -2
- package/dist/es/fields/Display.vue_vue_type_script_setup_true_lang.js +5 -2
- package/dist/es/fields/DynamicField.vue_vue_type_script_setup_true_lang.js +5 -2
- package/dist/es/fields/Hidden.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/fields/Link.vue_vue_type_script_setup_true_lang.js +30 -8
- package/dist/es/fields/Number.vue_vue_type_script_setup_true_lang.js +5 -2
- package/dist/es/fields/NumberRange.vue_vue_type_script_setup_true_lang.js +5 -2
- package/dist/es/fields/RadioGroup.vue_vue_type_script_setup_true_lang.js +17 -9
- package/dist/es/fields/Select.vue_vue_type_script_setup_true_lang.js +5 -2
- package/dist/es/fields/Switch.vue_vue_type_script_setup_true_lang.js +5 -2
- package/dist/es/fields/Text.vue_vue_type_script_setup_true_lang.js +113 -78
- package/dist/es/fields/Textarea.vue_vue_type_script_setup_true_lang.js +5 -2
- package/dist/es/fields/Time.vue_vue_type_script_setup_true_lang.js +5 -2
- package/dist/es/fields/Timerange.vue_vue_type_script_setup_true_lang.js +5 -2
- package/dist/es/plugin.js +2 -0
- package/dist/es/style.css +120 -8
- package/dist/es/utils/form.js +2 -2
- package/dist/style.css +120 -8
- package/dist/themes/magic-admin.css +494 -0
- package/dist/tmagic-form.umd.cjs +1850 -1640
- package/package.json +5 -5
- package/src/Form.vue +53 -4
- package/src/FormDialog.vue +14 -3
- package/src/FormDrawer.vue +40 -12
- package/src/containers/Container.vue +14 -5
- package/src/containers/GroupListItem.vue +14 -12
- package/src/containers/Panel.vue +10 -3
- package/src/containers/table/ActionsColumn.vue +10 -4
- package/src/containers/table/useTableColumns.ts +8 -2
- package/src/containers/table-group-list/TableGroupList.vue +7 -1
- package/src/fields/Link.vue +17 -3
- package/src/fields/RadioGroup.vue +11 -5
- package/src/fields/Text.vue +43 -19
- package/src/plugin.ts +2 -0
- package/src/theme/container.scss +3 -0
- package/src/theme/fieldset.scss +50 -0
- package/src/theme/form.scss +6 -0
- package/src/theme/group-list.scss +8 -7
- package/src/theme/index.scss +1 -0
- package/src/theme/link.scss +17 -0
- package/src/theme/panel.scss +1 -1
- package/src/theme/radio-group.scss +23 -0
- package/src/theme/tabs.scss +2 -2
- package/src/theme/text.scss +38 -0
- package/src/theme/themes/magic-admin/index.scss +91 -0
- package/types/index.d.ts +46 -1
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.8.0-
|
|
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.
|
|
53
|
+
"vue": "^3.5.38",
|
|
54
54
|
"typescript": "^6.0.3",
|
|
55
|
-
"@tmagic/
|
|
56
|
-
"@tmagic/
|
|
57
|
-
"@tmagic/form-schema": "1.8.0-
|
|
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="
|
|
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
|
-
|
|
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, {
|
package/src/FormDialog.vue
CHANGED
|
@@ -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>>();
|
package/src/FormDrawer.vue
CHANGED
|
@@ -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="
|
|
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="
|
|
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: '
|
|
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
|
|
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
|
-
|
|
155
|
+
dialogVisible.value = true;
|
|
145
156
|
};
|
|
146
157
|
|
|
147
158
|
const hide = () => {
|
|
148
|
-
|
|
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
|
|
224
|
-
<TMagicButton
|
|
225
|
-
|
|
226
|
-
|
|
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><
|
|
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
|
-
|
|
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="
|
|
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="
|
|
37
|
+
size="default"
|
|
36
38
|
:disabled="disabled"
|
|
37
|
-
:icon="
|
|
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="
|
|
46
|
+
size="default"
|
|
45
47
|
:disabled="disabled"
|
|
46
|
-
:icon="
|
|
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 {
|
|
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
|
|
package/src/containers/Panel.vue
CHANGED
|
@@ -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
|
|
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 {
|
|
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
|
-
|
|
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
|
-
|
|
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 :
|
|
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
|
-
{{
|
|
45
|
+
{{
|
|
46
|
+
currentConfig.addButtonConfig?.text ||
|
|
47
|
+
(displayMode === 'table'
|
|
48
|
+
? `新增一行${groupListConfig.titlePrefix || ''}`
|
|
49
|
+
: `新增${groupListConfig.titlePrefix || ''}`)
|
|
50
|
+
}}
|
|
45
51
|
</TMagicButton>
|
|
46
52
|
</template>
|
|
47
53
|
</component>
|
package/src/fields/Link.vue
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<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
|
|
13
|
-
|
|
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 '
|
|
53
|
+
return '14';
|
|
48
54
|
}
|
|
49
55
|
if (props.size === 'large') {
|
|
50
56
|
return '16';
|
|
51
57
|
}
|
|
52
|
-
return '
|
|
58
|
+
return '16';
|
|
53
59
|
});
|
|
54
60
|
</script>
|