@tmagic/form 1.7.9 → 1.7.11

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.
@@ -0,0 +1,181 @@
1
+ <template>
2
+ <component
3
+ :is="displayMode === 'table' ? MFormTable : MFormGroupList"
4
+ v-bind="$attrs"
5
+ :model="model"
6
+ :name="`${name}`"
7
+ :config="currentConfig"
8
+ :disabled="disabled"
9
+ :size="size"
10
+ :is-compare="isCompare"
11
+ :last-values="lastValues"
12
+ :prop="prop"
13
+ :label-width="labelWidth"
14
+ :show-index="showIndex"
15
+ :sort-key="sortKey"
16
+ :sort="sort"
17
+ @change="onChange"
18
+ @select="onSelect"
19
+ @addDiffCount="onAddDiffCount"
20
+ >
21
+ <template #toggle-button>
22
+ <TMagicButton
23
+ v-if="config.enableToggleMode || enableToggleMode"
24
+ :icon="Grid"
25
+ size="small"
26
+ @click="toggleDisplayMode"
27
+ >
28
+ {{ displayMode === 'table' ? '展开配置' : '切换为表格' }}
29
+ </TMagicButton>
30
+ </template>
31
+
32
+ <template #add-button="{ trigger }">
33
+ <TMagicButton
34
+ v-if="addable"
35
+ :class="displayMode === 'table' ? 'm-form-table-add-button' : ''"
36
+ :size="addButtonSize"
37
+ :plain="displayMode === 'table'"
38
+ :icon="Plus"
39
+ :disabled="disabled"
40
+ v-bind="currentConfig.addButtonConfig?.props || { type: 'primary' }"
41
+ @click="trigger"
42
+ >
43
+ {{ currentConfig.addButtonConfig?.text || (displayMode === 'table' ? '新增一行' : '新增') }}
44
+ </TMagicButton>
45
+ </template>
46
+ </component>
47
+ </template>
48
+
49
+ <script setup lang="ts">
50
+ import { computed, inject, ref } from 'vue';
51
+ import { Grid, Plus } from '@element-plus/icons-vue';
52
+
53
+ import { TMagicButton } from '@tmagic/design';
54
+ import type { FormState, GroupListConfig, TableConfig } from '@tmagic/form-schema';
55
+
56
+ import type { ContainerChangeEventData } from '../schema';
57
+ import MFormTable from '../table/Table.vue';
58
+
59
+ import MFormGroupList from './GroupList.vue';
60
+
61
+ defineOptions({
62
+ name: 'MFormTableGroupList',
63
+ inheritAttrs: false,
64
+ });
65
+
66
+ const props = defineProps<{
67
+ model: any;
68
+ lastValues?: any;
69
+ isCompare?: boolean;
70
+ config: TableConfig | GroupListConfig;
71
+ name: string;
72
+ prop?: string;
73
+ labelWidth?: string;
74
+ disabled?: boolean;
75
+ size?: string;
76
+ enableToggleMode?: true;
77
+ showIndex?: boolean;
78
+ sortKey?: string;
79
+ sort?: boolean;
80
+ }>();
81
+
82
+ const emit = defineEmits(['change', 'select', 'addDiffCount']);
83
+
84
+ const mForm = inject<FormState | undefined>('mForm');
85
+
86
+ const addable = computed(() => {
87
+ const modelName = props.name || props.config.name || '';
88
+
89
+ if (!modelName) return false;
90
+
91
+ if (!props.model[modelName].length) {
92
+ return true;
93
+ }
94
+
95
+ if (typeof props.config.addable === 'function') {
96
+ return props.config.addable(mForm, {
97
+ model: props.model[modelName],
98
+ formValue: mForm?.values,
99
+ prop: props.prop,
100
+ config: props.config,
101
+ });
102
+ }
103
+
104
+ return typeof props.config.addable === 'undefined' ? true : props.config.addable;
105
+ });
106
+
107
+ const isGroupListType = (type: string | undefined) => type === 'groupList' || type === 'group-list';
108
+
109
+ const displayMode = ref<'table' | 'groupList'>(isGroupListType(props.config.type) ? 'groupList' : 'table');
110
+
111
+ const calcLabelWidth = (label: string) => {
112
+ if (!label) return '0px';
113
+ const zhLength = label.match(/[^\x00-\xff]/g)?.length || 0;
114
+ const chLength = label.length - zhLength;
115
+ return `${Math.max(chLength * 8 + zhLength * 20, 80)}px`;
116
+ };
117
+
118
+ // 当原始 config 是 table 形态时,table 模式直接透传;
119
+ // 若原始是 groupList,则基于它派生出 table 所需的 config
120
+ const tableConfig = computed<TableConfig>(() => {
121
+ if (!isGroupListType(props.config.type)) {
122
+ return props.config as TableConfig;
123
+ }
124
+
125
+ const source = props.config as GroupListConfig;
126
+ return {
127
+ ...props.config,
128
+ type: 'table',
129
+ groupItems: source.items,
130
+ items:
131
+ source.tableItems ||
132
+ (source.items as any[]).map((item: any) => ({
133
+ ...item,
134
+ label: item.label || item.text,
135
+ text: null,
136
+ })),
137
+ } as any as TableConfig;
138
+ });
139
+
140
+ // 反向派生 groupList 所需的 config
141
+ const groupListConfig = computed<GroupListConfig>(() => {
142
+ if (isGroupListType(props.config.type)) {
143
+ return props.config as GroupListConfig;
144
+ }
145
+
146
+ const source = props.config as TableConfig;
147
+ return {
148
+ ...props.config,
149
+ type: 'groupList',
150
+ tableItems: source.items,
151
+ items:
152
+ source.groupItems ||
153
+ (source.items as any[]).map((item: any) => {
154
+ const text = item.text || item.label;
155
+ return {
156
+ ...item,
157
+ text,
158
+ labelWidth: calcLabelWidth(text),
159
+ span: item.span || 12,
160
+ };
161
+ }),
162
+ } as any as GroupListConfig;
163
+ });
164
+
165
+ // 运行时类型由 displayMode 决定,`<component :is>` 无法做联合类型收窄,统一转 any 交给子组件处理
166
+ const currentConfig = computed<any>(() => (displayMode.value === 'table' ? tableConfig.value : groupListConfig.value));
167
+
168
+ // 保持原 Table/GroupList 模式下新增按钮的不同尺寸策略
169
+ const addButtonSize = computed(() => {
170
+ if (displayMode.value === 'table') return 'small';
171
+ return props.config.enableToggleMode !== false ? 'small' : 'default';
172
+ });
173
+
174
+ const toggleDisplayMode = () => {
175
+ displayMode.value = displayMode.value === 'table' ? 'groupList' : 'table';
176
+ };
177
+
178
+ const onChange = (v: any, eventData?: ContainerChangeEventData) => emit('change', v, eventData);
179
+ const onSelect = (...args: any[]) => emit('select', ...args);
180
+ const onAddDiffCount = () => emit('addDiffCount');
181
+ </script>
package/src/index.ts CHANGED
@@ -32,8 +32,9 @@ export { default as MFlexLayout } from './containers/FlexLayout.vue';
32
32
  export { default as MPanel } from './containers/Panel.vue';
33
33
  export { default as MRow } from './containers/Row.vue';
34
34
  export { default as MTabs } from './containers/Tabs.vue';
35
- export { default as MTable } from './table/Table.vue';
36
- export { default as MGroupList } from './containers/GroupList.vue';
35
+ export { default as MTable } from './containers/TableGroupList.vue';
36
+ export { default as MGroupList } from './containers/TableGroupList.vue';
37
+ export { default as MTableGroupList } from './containers/TableGroupList.vue';
37
38
  export { default as MText } from './fields/Text.vue';
38
39
  export { default as MNumber } from './fields/Number.vue';
39
40
  export { default as MNumberRange } from './fields/NumberRange.vue';
package/src/plugin.ts CHANGED
@@ -21,10 +21,10 @@ import { type App } from 'vue';
21
21
  import Container from './containers/Container.vue';
22
22
  import Fieldset from './containers/Fieldset.vue';
23
23
  import FlexLayout from './containers/FlexLayout.vue';
24
- import GroupList from './containers/GroupList.vue';
25
24
  import Panel from './containers/Panel.vue';
26
25
  import Row from './containers/Row.vue';
27
26
  import MStep from './containers/Step.vue';
27
+ import TableGroupList from './containers/TableGroupList.vue';
28
28
  import Tabs from './containers/Tabs.vue';
29
29
  import Cascader from './fields/Cascader.vue';
30
30
  import Checkbox from './fields/Checkbox.vue';
@@ -46,7 +46,6 @@ import Text from './fields/Text.vue';
46
46
  import Textarea from './fields/Textarea.vue';
47
47
  import Time from './fields/Time.vue';
48
48
  import Timerange from './fields/Timerange.vue';
49
- import Table from './table/Table.vue';
50
49
  import { setConfig } from './utils/config';
51
50
  import Form from './Form.vue';
52
51
  import FormDialog from './FormDialog.vue';
@@ -70,11 +69,11 @@ export default {
70
69
  app.component('m-form-dialog', FormDialog);
71
70
  app.component('m-form-container', Container);
72
71
  app.component('m-form-fieldset', Fieldset);
73
- app.component('m-form-group-list', GroupList);
72
+ app.component('m-form-group-list', TableGroupList);
74
73
  app.component('m-form-panel', Panel);
75
74
  app.component('m-form-row', Row);
76
75
  app.component('m-form-step', MStep);
77
- app.component('m-form-table', Table);
76
+ app.component('m-form-table', TableGroupList);
78
77
  app.component('m-form-tab', Tabs);
79
78
  app.component('m-form-flex-layout', FlexLayout);
80
79
  app.component('m-fields-text', Text);
@@ -4,7 +4,7 @@
4
4
  v-bind="$attrs"
5
5
  class="m-fields-table-wrap"
6
6
  :class="{ fixed: isFullscreen }"
7
- :style="isFullscreen ? `z-index: ${nextZIndex()}` : ''"
7
+ :style="isFullscreen ? `z-index: ${fullscreenZIndex}` : ''"
8
8
  >
9
9
  <div class="m-fields-table" :class="{ 'm-fields-table-item-extra': config.itemExtra }">
10
10
  <span v-if="config.extra" style="color: rgba(0, 0, 0, 0.45)" v-html="config.extra"></span>
@@ -34,13 +34,7 @@
34
34
 
35
35
  <div style="display: flex; justify-content: space-between; margin: 10px 0">
36
36
  <div style="display: flex">
37
- <TMagicButton
38
- :icon="Grid"
39
- size="small"
40
- @click="toggleMode"
41
- v-if="enableToggleMode && config.enableToggleMode !== false && !isFullscreen"
42
- >展开配置</TMagicButton
43
- >
37
+ <slot name="toggle-button" v-if="!isFullscreen"></slot>
44
38
  <TMagicButton
45
39
  :icon="FullScreen"
46
40
  size="small"
@@ -64,17 +58,7 @@
64
58
  >清空</TMagicButton
65
59
  >
66
60
  </div>
67
- <TMagicButton
68
- v-if="addable"
69
- class="m-form-table-add-button"
70
- size="small"
71
- plain
72
- :icon="Plus"
73
- v-bind="config.addButtonConfig?.props || { type: 'primary' }"
74
- :disabled="disabled"
75
- @click="newHandler()"
76
- >{{ config.addButtonConfig?.text || '新增一行' }}</TMagicButton
77
- >
61
+ <slot name="add-button" :trigger="newHandler"></slot>
78
62
  </div>
79
63
 
80
64
  <div class="bottom" style="text-align: right" v-if="config.pagination">
@@ -96,8 +80,8 @@
96
80
  </template>
97
81
 
98
82
  <script setup lang="ts">
99
- import { computed, ref, useTemplateRef } from 'vue';
100
- import { FullScreen, Grid, Plus } from '@element-plus/icons-vue';
83
+ import { computed, ref, useTemplateRef, watch } from 'vue';
84
+ import { FullScreen } from '@element-plus/icons-vue';
101
85
 
102
86
  import { TMagicButton, TMagicPagination, TMagicTable, TMagicTooltip, TMagicUpload, useZIndex } from '@tmagic/design';
103
87
 
@@ -120,7 +104,6 @@ defineOptions({
120
104
  const props = withDefaults(defineProps<TableProps>(), {
121
105
  prop: '',
122
106
  sortKey: '',
123
- enableToggleMode: true,
124
107
  showIndex: true,
125
108
  lastValues: () => ({}),
126
109
  isCompare: false,
@@ -138,42 +121,24 @@ const { pageSize, currentPage, paginationData, handleSizeChange, handleCurrentCh
138
121
 
139
122
  const { nextZIndex } = useZIndex();
140
123
  const updateKey = ref(1);
124
+ const fullscreenZIndex = ref(nextZIndex());
141
125
 
142
- const { addable, newHandler } = useAdd(props, emit);
126
+ const { newHandler } = useAdd(props, emit);
143
127
  const { columns } = useTableColumns(props, emit, currentPage, pageSize, modelName);
144
128
  useSortable(props, emit, tMagicTableRef, modelName, updateKey);
145
129
  const { isFullscreen, toggleFullscreen } = useFullscreen();
130
+
131
+ watch(isFullscreen, (value) => {
132
+ if (value) {
133
+ fullscreenZIndex.value = nextZIndex();
134
+ }
135
+ });
136
+
146
137
  const { importable, excelHandler, clearHandler } = useImport(props, emit, newHandler);
147
138
  const { selectHandle, toggleRowSelection } = useSelection(props, emit, tMagicTableRef);
148
139
 
149
140
  const data = computed(() => (props.config.pagination ? paginationData.value : props.model[modelName.value]));
150
141
 
151
- const toggleMode = () => {
152
- const calcLabelWidth = (label: string) => {
153
- if (!label) return '0px';
154
- const zhLength = label.match(/[^\x00-\xff]/g)?.length || 0;
155
- const chLength = label.length - zhLength;
156
- return `${Math.max(chLength * 8 + zhLength * 20, 80)}px`;
157
- };
158
-
159
- // 切换为groupList的形式
160
- props.config.type = 'groupList';
161
- props.config.enableToggleMode = true;
162
- props.config.tableItems = props.config.items;
163
- props.config.items =
164
- props.config.groupItems ||
165
- props.config.items.map((item: any) => {
166
- const text = item.text || item.label;
167
- const labelWidth = calcLabelWidth(text);
168
- return {
169
- ...item,
170
- text,
171
- labelWidth,
172
- span: item.span || 12,
173
- };
174
- });
175
- };
176
-
177
142
  const sortChangeHandler = (sortOptions: SortProp) => {
178
143
  const modelName = props.name || props.config.name || '';
179
144
  sortChange(props.model[modelName], sortOptions);
package/src/table/type.ts CHANGED
@@ -13,6 +13,5 @@ export interface TableProps {
13
13
  sortKey?: string;
14
14
  text?: string;
15
15
  size?: string;
16
- enableToggleMode?: boolean;
17
16
  showIndex?: boolean;
18
17
  }
@@ -1,4 +1,4 @@
1
- import { computed, inject } from 'vue';
1
+ import { inject } from 'vue';
2
2
 
3
3
  import { tMagicMessage } from '@tmagic/design';
4
4
  import type { FormConfig, FormState } from '@tmagic/form-schema';
@@ -13,21 +13,6 @@ export const useAdd = (
13
13
  ) => {
14
14
  const mForm = inject<FormState | undefined>('mForm');
15
15
 
16
- const addable = computed(() => {
17
- const modelName = props.name || props.config.name || '';
18
- if (!props.model[modelName].length) {
19
- return true;
20
- }
21
- if (typeof props.config.addable === 'function') {
22
- return props.config.addable(mForm, {
23
- model: props.model[modelName],
24
- formValue: mForm?.values,
25
- prop: props.prop,
26
- });
27
- }
28
- return typeof props.config.addable === 'undefined' ? true : props.config.addable;
29
- });
30
-
31
16
  const newHandler = async (row?: any) => {
32
17
  const modelName = props.name || props.config.name || '';
33
18
 
@@ -37,7 +22,7 @@ export const useAdd = (
37
22
  }
38
23
 
39
24
  if (typeof props.config.beforeAddRow === 'function') {
40
- const beforeCheckRes = props.config.beforeAddRow(mForm, {
25
+ const beforeCheckRes = await props.config.beforeAddRow(mForm, {
41
26
  model: props.model[modelName],
42
27
  formValue: mForm?.values,
43
28
  prop: props.prop,
@@ -106,7 +91,6 @@ export const useAdd = (
106
91
  };
107
92
 
108
93
  return {
109
- addable,
110
94
  newHandler,
111
95
  };
112
96
  };