@vue-ui-kit/ant 1.0.0

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 (50) hide show
  1. package/dist/cjs/index.js +1 -0
  2. package/dist/declarations/antProxy.d.ts +239 -0
  3. package/dist/declarations/type.d.ts +1 -0
  4. package/dist/es/index.js +2471 -0
  5. package/dist/index.d.ts +12 -0
  6. package/dist/packages/components/PForm.vue.d.ts +28 -0
  7. package/dist/packages/components/PFormGroup.vue.d.ts +29 -0
  8. package/dist/packages/components/PGrid.vue.d.ts +40 -0
  9. package/dist/packages/components/PGroupBlock.vue.d.ts +16 -0
  10. package/dist/packages/components/PromisePicker.vue.d.ts +48 -0
  11. package/dist/packages/components/RenderAntCell.d.ts +10 -0
  12. package/dist/packages/components/RenderAntItem.d.ts +17 -0
  13. package/dist/packages/components/RenderDefaultSlots.d.ts +14 -0
  14. package/dist/packages/components/RenderItemSlots.d.ts +10 -0
  15. package/dist/packages/components/RenderTitleSlots.d.ts +6 -0
  16. package/dist/packages/hooks/useMessage.d.ts +8 -0
  17. package/dist/packages/renders/Icon.d.ts +4 -0
  18. package/dist/packages/renders/TableInput.vue.d.ts +44 -0
  19. package/dist/packages/store/renderStore.d.ts +59 -0
  20. package/dist/packages/utils/AFormatters.d.ts +19 -0
  21. package/dist/packages/utils/core.d.ts +8 -0
  22. package/dist/packages/utils/is.d.ts +2 -0
  23. package/dist/packages/utils/treeHelper.d.ts +19 -0
  24. package/dist/style.css +1 -0
  25. package/package.json +72 -0
  26. package/src/declarations/README.md +9 -0
  27. package/src/declarations/antProxy.ts +255 -0
  28. package/src/declarations/global.d.ts +133 -0
  29. package/src/declarations/type.ts +1 -0
  30. package/src/index.ts +25 -0
  31. package/src/packages/components/PForm.vue +108 -0
  32. package/src/packages/components/PFormGroup.vue +90 -0
  33. package/src/packages/components/PGrid.vue +472 -0
  34. package/src/packages/components/PGroupBlock.vue +12 -0
  35. package/src/packages/components/PromisePicker.vue +64 -0
  36. package/src/packages/components/RenderAntCell.tsx +29 -0
  37. package/src/packages/components/RenderAntItem.tsx +54 -0
  38. package/src/packages/components/RenderDefaultSlots.tsx +44 -0
  39. package/src/packages/components/RenderItemSlots.tsx +24 -0
  40. package/src/packages/components/RenderTitleSlots.tsx +15 -0
  41. package/src/packages/hooks/useMessage.ts +19 -0
  42. package/src/packages/renders/Icon.ts +8 -0
  43. package/src/packages/renders/TableInput.vue +107 -0
  44. package/src/packages/store/renderStore.tsx +515 -0
  45. package/src/packages/styles/index.scss +184 -0
  46. package/src/packages/styles/variables.scss +3 -0
  47. package/src/packages/utils/AFormatters.ts +64 -0
  48. package/src/packages/utils/core.ts +52 -0
  49. package/src/packages/utils/is.ts +2 -0
  50. package/src/packages/utils/treeHelper.ts +72 -0
@@ -0,0 +1,255 @@
1
+ import type { Rule } from 'ant-design-vue/lib/form';
2
+ import { ButtonProps } from 'ant-design-vue/lib/button';
3
+ import { ColProps } from 'ant-design-vue/lib/grid/Col';
4
+ import { FormProps } from 'ant-design-vue/lib/form/Form';
5
+ import { TableColumnType, TableProps } from 'ant-design-vue';
6
+ import { ButtonType } from 'ant-design-vue/lib/button/buttonTypes';
7
+
8
+ export interface CellFuncArg<D = Recordable> {
9
+ row: D;
10
+ column: ColumnProps<D>;
11
+ rowIndex: number;
12
+ cellValue: any;
13
+ }
14
+
15
+ export interface ItemFuncArg<F = Recordable> {
16
+ data: F;
17
+ field?: string;
18
+ }
19
+
20
+ export interface ItemRender {
21
+ name: string;
22
+ defaultValue?: any;
23
+ props?: Recordable;
24
+ options?: IOption[];
25
+ children?: Recordable[];
26
+ events?: { [key: string]: (...args: any[]) => any };
27
+ }
28
+
29
+ export interface CellRender {
30
+ name: string;
31
+ props?: Recordable;
32
+ children?: Recordable[];
33
+ }
34
+
35
+ export interface Responsive {
36
+ xxs?: number;
37
+ xs?: number;
38
+ sm?: number;
39
+ md?: number;
40
+ lg?: number;
41
+ xl?: number;
42
+ xxl?: number;
43
+ }
44
+
45
+ export interface PFormItemProps<F = Recordable> {
46
+ field?: string;
47
+ title?: string;
48
+ span?: number;
49
+ align?: 'left' | 'right' | 'center';
50
+ col?: ColProps;
51
+ rule?: Rule[];
52
+ itemRender?: ItemRender;
53
+ slots?: {
54
+ default?: (
55
+ { data, field }: ItemFuncArg<F>,
56
+ passTrigger?: (cusFields?: string | string[]) => void,
57
+ ) => any;
58
+ };
59
+ }
60
+
61
+ export interface PFormProps<F = Recordable> extends FormProps {
62
+ items: PFormItemProps<F>[];
63
+ customReset?: () => void;
64
+ }
65
+
66
+ export interface PBlockProps<F = Recordable> {
67
+ getFormSetting: (data: Partial<F>) => PFormProps<Partial<F>>;
68
+ source: Partial<F>;
69
+ }
70
+
71
+ export interface PromisePickerProps<D = Recordable, F = Recordable> {
72
+ gridSetting: PGridProps<D, F>;
73
+ title?: string;
74
+ width?: string | number;
75
+ }
76
+
77
+ export type GroupMenuItemHandler<F = Recordable> = ({
78
+ index,
79
+ data,
80
+ code,
81
+ }: {
82
+ index: number;
83
+ code: string;
84
+ data: Partial<F>;
85
+ }) => void;
86
+
87
+ export interface GroupMenuItem<F = Recordable> {
88
+ content: string;
89
+ icon?: string;
90
+ code: string;
91
+ visibleMethod?: ({ data, index }: { data: Partial<F>; index: number }) => boolean;
92
+ }
93
+
94
+ export interface PFormGroupProps<F = Recordable> {
95
+ getFormSetting: (data: Partial<F>) => PFormProps<Partial<F>>;
96
+ title?: string;
97
+ tabLabel?: string;
98
+ editAble?: boolean;
99
+ showAdd?: boolean;
100
+ itemMenus?: Array<GroupMenuItem<F>>;
101
+ creatItem?: ({ list }: { list?: Partial<F>[] }) => Promise<Partial<F>>;
102
+ max?: number;
103
+ menuHandler?: GroupMenuItemHandler<F>;
104
+ }
105
+
106
+ export interface ColumnProps<D = Recordable> extends Omit<TableColumnType, 'slots'> {
107
+ field?: string;
108
+ children?: ColumnProps<D>[];
109
+ formatter?:
110
+ | string
111
+ | [string, ...Array<any>]
112
+ | ((arg: PartialByKeys<CellFuncArg<D>, 'cellValue'>) => any);
113
+ slots?: {
114
+ default?: ({ row, column, rowIndex }: PartialByKeys<CellFuncArg<D>, 'cellValue'>) => any;
115
+ title?: ({ column }: { column: ColumnProps<D> }) => any;
116
+ };
117
+ cellRender?: CellRender;
118
+ }
119
+
120
+ export interface PButtonProps extends ButtonProps {
121
+ content?: string;
122
+ icon?: string;
123
+ type?: ButtonType;
124
+ }
125
+
126
+ export interface ToolbarButtonProps extends PButtonProps {
127
+ code: string;
128
+ }
129
+
130
+ export interface ToolbarConfig {
131
+ buttons?: Array<ToolbarButtonProps>;
132
+ tools?: Array<{ code: string; icon: string; type?: ButtonType }>;
133
+ }
134
+
135
+ export interface ResponsePathConfig<D = Recordable> {
136
+ /*非分页取值路径*/
137
+ list?: string | ((res: Recordable) => D[]);
138
+ /*分页取值路径*/
139
+ result?: string | ((res: Recordable) => D[]);
140
+ total?: string | ((res: Recordable) => D[]);
141
+ /*提示信息取值路径*/
142
+ message?:
143
+ | string
144
+ | ((res: Recordable) => string | { status: string; content: string; icon?: string });
145
+ }
146
+
147
+ declare type HandlerMulti = (ids: string[] | number[]) => any;
148
+
149
+ export interface AjaxConfig<F = Recordable> {
150
+ query: (Q: { page?: IPage; form: Partial<F> }) => Promise<Recordable>;
151
+ multiDelete?: HandlerMulti;
152
+ }
153
+
154
+ export interface ProxyConfig<D = Recordable, F = Recordable> {
155
+ // 结果集 取值路径
156
+ response?: ResponsePathConfig<D>;
157
+ ajax: AjaxConfig<F>;
158
+ }
159
+
160
+ export interface PageConfig {
161
+ pageSizes?: number[];
162
+ pageSize?: number;
163
+ }
164
+
165
+ export interface SelectConfig {
166
+ multiple?: boolean;
167
+ }
168
+
169
+ export type PGridProps<D = Recordable, F = Recordable> = {
170
+ selectConfig?: SelectConfig;
171
+ rowKey?: string;
172
+ manualFetch?: boolean;
173
+ formConfig?: PFormProps<F>;
174
+ columns: ColumnProps<D>[];
175
+ toolbarConfig?: ToolbarConfig;
176
+ pageConfig?: PageConfig;
177
+ proxyConfig?: ProxyConfig<D, F>;
178
+ tableConfig?: TableProps<D>;
179
+ scrollMode?: 'outer' | 'inner';
180
+ };
181
+
182
+ export interface RenderOptions {
183
+ /**
184
+ * 渲染器名称
185
+ */
186
+ name?: string;
187
+ /**
188
+ * 目标组件渲染的参数
189
+ */
190
+ props?: { [key: string]: any };
191
+ /**
192
+ * 目标组件渲染的属性
193
+ */
194
+ attrs?: { [key: string]: any };
195
+ /**
196
+ * 目标组件渲染的事件
197
+ */
198
+ events?: { [key: string]: (...args: any[]) => any };
199
+ /**
200
+ * 多目标渲染
201
+ */
202
+ children?: any[];
203
+ /**
204
+ * 选项
205
+ */
206
+ options?: IOption[];
207
+ /**
208
+ * 默认值
209
+ */
210
+ defaultValue?: any;
211
+ /**
212
+ * 校验触发器
213
+ * @param cusFields field或者field数组
214
+ */
215
+ handleTrigger?: (cusFields?: string | string[]) => void;
216
+ }
217
+
218
+ export interface RenderFormParams<F = Recordable> {
219
+ data: F;
220
+ field?: string;
221
+ }
222
+
223
+ export interface RenderTableParams<D = Recordable> {
224
+ data?: D[];
225
+ row: D;
226
+ rowIndex?: number;
227
+ field?: string;
228
+ title?: string;
229
+ }
230
+
231
+ export interface PGridInstance<D = Recordable, F = Recordable> {
232
+ commitProxy: {
233
+ query: () => Promise<D[]>;
234
+ reload: () => Promise<D[]>;
235
+ reloadPage: () => Promise<D[]>;
236
+ passQuery: (query: Partial<F>) => Promise<D[]>;
237
+ };
238
+ selectedRowKeys: string[] | number[];
239
+ $table: Recordable;
240
+ $form: Recordable;
241
+ }
242
+
243
+ export interface PFormInstance {
244
+ reset: () => void;
245
+ $form: Recordable;
246
+ }
247
+
248
+ export interface PromisePickerInstance<D = Recordable> {
249
+ pick: () => Promise<{ row: D; field?: string }>;
250
+ }
251
+
252
+ export interface PFormGroupInstance<F = Recordable> {
253
+ activeKey: number;
254
+ setActiveKey: (activeKey: number) => void;
255
+ }
@@ -0,0 +1,133 @@
1
+ //<editor-fold desc="👇全局类型补丁,不需要引用👇">
2
+ declare type Recordable<T = any> = Record<string, T>;
3
+ type PartialByKeys<T, K extends keyof T = keyof T> = Omit<T, K & keyof T> &
4
+ Partial<Pick<T, K & keyof T>> extends infer U
5
+ ? { [K in keyof U]: U[K] }
6
+ : never;
7
+ type DeepPick<T extends Record<string, any>, U extends string> = (
8
+ U extends string
9
+ ? U extends `${infer F}.${infer R}`
10
+ ? (arg: {
11
+ [K in F]: DeepPick<T[F], R>;
12
+ }) => void
13
+ : U extends keyof T
14
+ ? (arg: Pick<T, U>) => void
15
+ : (arg: unknown) => void
16
+ : never
17
+ ) extends (arg: infer Z) => void
18
+ ? Z
19
+ : never;
20
+
21
+ //选项类型
22
+ interface IOption<T = any> {
23
+ value: T;
24
+ label: string;
25
+ color?: string;
26
+ }
27
+
28
+ interface OptionGroup<T> {
29
+ label?: string;
30
+ options: IOption<T>[];
31
+ }
32
+
33
+ //树形结构类型
34
+ type ITreeAble<T, U = void> = U extends void
35
+ ? T & { children?: ITreeAble<T>[] }
36
+ : U extends string
37
+ ? T & { [key in U]?: ITreeAble<T, U>[] }
38
+ : T;
39
+
40
+ declare type WrapID<T extends Recordable> = {
41
+ readonly id: string | number;
42
+ } & { [K in keyof T]: T[K] };
43
+
44
+ declare type TimeoutHandle = ReturnType<typeof window.setTimeout>;
45
+ declare type IntervalHandle = ReturnType<typeof window.setInterval>;
46
+
47
+ declare type GrowToSize<T, N extends number, A extends T[]> = A['length'] extends N
48
+ ? A
49
+ : GrowToSize<T, N, [...A, T]>;
50
+
51
+ declare type FixedArray<T, N extends number> = GrowToSize<T, N, []>;
52
+
53
+ interface IPage {
54
+ /**
55
+ * 第几页
56
+ */
57
+ page: number;
58
+ /**
59
+ * 一页显示的数量
60
+ */
61
+ size: number;
62
+ }
63
+
64
+ interface WrapList<T> {
65
+ /**
66
+ * 列表
67
+ */
68
+ list: T[];
69
+ }
70
+
71
+ interface WrapPage<T> {
72
+ /**
73
+ * 列表
74
+ */
75
+ list: T[];
76
+ /**
77
+ * 当前页码
78
+ */
79
+ page: number;
80
+ /**
81
+ * 总页数
82
+ */
83
+ pages?: string[];
84
+ /**
85
+ * 每页数量
86
+ */
87
+ size: number;
88
+ /**
89
+ * 总数量
90
+ */
91
+ total: number;
92
+ }
93
+
94
+ interface ISchema {
95
+ id: number;
96
+ /**
97
+ * 操作人
98
+ */
99
+ operator?: string;
100
+ /**
101
+ * 创建人
102
+ */
103
+ create_by?: string;
104
+ /**
105
+ * 更新人
106
+ */
107
+ update_by?: string;
108
+ /**
109
+ * 更新时间
110
+ */
111
+ update_time?: number;
112
+ /**
113
+ * 创建时间
114
+ */
115
+ create_time?: number;
116
+ /**
117
+ * 创建人
118
+ */
119
+ creator?: string;
120
+ }
121
+
122
+ declare module '*.vue' {
123
+ import type { DefineComponent } from 'vue'
124
+
125
+ // biome-ignore lint/complexity/noBannedTypes: reason
126
+ const component: DefineComponent<{}, {}, any>
127
+ export default component
128
+ }
129
+ declare module '*.png';
130
+ declare module '*.svg';
131
+ declare module '*.jpeg';
132
+ declare module '*.jpg';
133
+ //</editor-fold>
@@ -0,0 +1 @@
1
+ export type Recordable<T = any> = Record<string, T>;
package/src/index.ts ADDED
@@ -0,0 +1,25 @@
1
+ import { App } from 'vue';
2
+ import PForm from '@/components/PForm.vue';
3
+ import PGrid from '@/components/PGrid.vue';
4
+ import PFormGroup from '@/components/PFormGroup.vue';
5
+ import PGroupBlock from '@/components/PGroupBlock.vue';
6
+ import PromisePicker from '@/components/PromisePicker.vue';
7
+ import { addFormatter } from '@/utils/AFormatters';
8
+ import { addRender } from '@/store/renderStore';
9
+ import * as utils from '@/utils/core';
10
+
11
+ export default {
12
+ install(app: App) {
13
+ app.component('PForm', PForm);
14
+ app.component('PGrid', PGrid);
15
+ // @ts-ignore
16
+ app.component('PFormGroup', PFormGroup);
17
+ app.component('PGroupBlock', PGroupBlock);
18
+ app.component('PromisePicker', PromisePicker);
19
+ },
20
+ addFormatter,
21
+ addRender,
22
+ };
23
+
24
+ export * from '#/antProxy';
25
+ export * from '@/utils/core';
@@ -0,0 +1,108 @@
1
+ <script generic="F = Recordable" lang="ts" name="PForm" setup>
2
+ import { PFormItemProps, PFormProps } from '#/antProxy';
3
+ import { computed, onMounted, ref, toRefs, watch } from 'vue';
4
+ import { debounce, omit } from 'lodash-es';
5
+ import { v4 as uuid_v4 } from 'uuid';
6
+ import RenderAntItem from '@/components/RenderAntItem';
7
+ import RenderItemSlots from '@/components/RenderItemSlots';
8
+ import { valued } from '@/utils/is';
9
+ import { eachTree } from '@/utils/treeHelper';
10
+ import { defaultItemResponsive } from '@/utils/core';
11
+ import { Form as AForm, Row as ARow, Col as ACol, FormItem as AFormItem } from 'ant-design-vue';
12
+
13
+ const props = defineProps<PFormProps<F> & { data: F }>();
14
+ const emit = defineEmits(['apply', 'reset']);
15
+ const { items, data: formData } = toRefs(props);
16
+
17
+ function handleSubmit() {
18
+ emit('apply', formData.value);
19
+ }
20
+
21
+ const formEl = ref();
22
+ const renderFormKey = ref(uuid_v4());
23
+ const resetForm = () => {
24
+ renderFormKey.value = uuid_v4();
25
+ };
26
+ const debounceResetForm = debounce(resetForm, 100);
27
+ watch(() => items.value, debounceResetForm, { deep: true });
28
+ const resetFormData = () => {
29
+ if (props.customReset) {
30
+ props.customReset();
31
+ } else {
32
+ const obj: Partial<F> = {};
33
+ eachTree(items.value, (item) => {
34
+ if (item.field && item.itemRender) {
35
+ if (valued(item.itemRender.defaultValue)) {
36
+ obj[item.field] = item.itemRender.defaultValue;
37
+ } else {
38
+ obj[item.field] = undefined;
39
+ }
40
+ }
41
+ });
42
+ Object.assign(formData.value, obj);
43
+ }
44
+ };
45
+ // omit({labelCol:defaultLabelCol,...props},['items','data','model'])
46
+ const fc = computed(() => ({
47
+ ...omit(props, ['items', 'data', 'model', 'labelCol', 'wrapperCol']),
48
+ labelCol: props.labelCol ?? { span: 6 },
49
+ wrapperCol: props.wrapperCol ?? { span: 16 },
50
+ }));
51
+ const validateField = (fields?: string | string[]) => {
52
+ if (fields) {
53
+ formEl.value?.validateFields(fields);
54
+ }
55
+ };
56
+ const handleTrigger = (cusFields?: string | string[]) => {
57
+ validateField(cusFields);
58
+ };
59
+ defineExpose({
60
+ reset: resetForm,
61
+ $form: computed(() => formEl.value),
62
+ });
63
+ onMounted(() => {
64
+ resetForm();
65
+ });
66
+ </script>
67
+ <template>
68
+ <div
69
+ v-if="items.some((s: PFormItemProps<F>) => s.field && s.itemRender)"
70
+ class="p-pane p-wrapper"
71
+ >
72
+ <a-form :key="renderFormKey" ref="formEl" :model="formData" v-bind="fc" @submit="handleSubmit">
73
+ <a-row :gutter="[6, 12]">
74
+ <a-col
75
+ v-for="(item, idx) in items"
76
+ :key="'_col_' + idx"
77
+ v-bind="item.col ?? (item.span ? { span: item.span } : defaultItemResponsive)"
78
+ >
79
+ <a-form-item
80
+ :key="'_item_' + idx"
81
+ :label="item.title"
82
+ :name="item.field"
83
+ :wrapper-col="item.wrapperCol ?? (item.title ? undefined : { span: 24 })"
84
+ colon
85
+ :class="`p-content-align-${item.align ?? 'left'}`"
86
+ v-bind="omit(item, ['field', 'title', 'span', 'col', 'wrapperCol', 'itemRender'])"
87
+ >
88
+ <render-item-slots
89
+ v-if="item.slots?.default"
90
+ :form-data="formData"
91
+ :item="item"
92
+ :pass-trigger="handleTrigger"
93
+ />
94
+ <render-ant-item
95
+ v-else-if="item.itemRender?.name"
96
+ :key="'_re_' + idx"
97
+ :default-handler="{ reset: resetFormData }"
98
+ :item-render="item.itemRender"
99
+ @trigger="handleTrigger"
100
+ :render-form-params="{ data: formData, field: item.field }"
101
+ />
102
+ <span v-else></span>
103
+ </a-form-item>
104
+ </a-col>
105
+ </a-row>
106
+ </a-form>
107
+ </div>
108
+ </template>
@@ -0,0 +1,90 @@
1
+ <script lang="ts" generic="F = Recordable" setup name="PFormGroup">
2
+ import { computed, PropType, ref } from 'vue';
3
+ import { PFormGroupProps } from '#/antProxy';
4
+ import { MoreOutlined } from '@ant-design/icons-vue';
5
+ import { cloneDeep, toString, isFunction, omit } from 'lodash-es';
6
+ import PGroupBlock from '@/components/PGroupBlock.vue';
7
+ import {
8
+ Card as ACard,
9
+ Tabs as ATabs,
10
+ TabPane as ATabPane,
11
+ Button as AButton,
12
+ Dropdown as ADropdown,
13
+ Menu as AMenu,
14
+ MenuItem as AMenuItem,
15
+ } from 'ant-design-vue';
16
+
17
+ const props = defineProps<PFormGroupProps<F>>();
18
+ const model = defineModel({
19
+ type: Array as PropType<Partial<F>[]>,
20
+ default: () => [],
21
+ });
22
+ const activeKey = ref(0);
23
+ const setActiveKey = (key: number) => {
24
+ activeKey.value = key;
25
+ };
26
+ const maxLen = props.max ?? Infinity;
27
+ const handleAddItem = (idx: number) => {
28
+ const creator = props.creatItem ?? (() => Promise.resolve({} as Partial<F>));
29
+ creator({ list: model.value }).then((item) => {
30
+ model.value = [...model.value, item];
31
+ activeKey.value = idx;
32
+ });
33
+ };
34
+ const itemMenus = props.itemMenus ?? [{ content: '删除', code: 'delete' }];
35
+ const handleMenu = (key: string, item: Partial<F>, idx: number) => {
36
+ if (props.menuHandler && isFunction(props.menuHandler)) {
37
+ props.menuHandler({ code: key, data: item, index: idx });
38
+ } else {
39
+ switch (key) {
40
+ case 'delete':
41
+ model.value = model.value.filter((_, i) => i !== idx);
42
+ break;
43
+ case 'copy':
44
+ model.value = [...model.value, cloneDeep(omit(item, ['id']))];
45
+ break;
46
+ }
47
+ }
48
+ };
49
+ defineExpose({
50
+ activeKey: computed(() => activeKey.value),
51
+ setActiveKey,
52
+ });
53
+ </script>
54
+ <template>
55
+ <a-card :title="title" size="small">
56
+ <a-tabs type="editable-card" v-model:activeKey="activeKey" hide-add>
57
+ <template #rightExtra>
58
+ <slot name="rightExtra">
59
+ <a-button
60
+ type="link"
61
+ @click="handleAddItem(model.length)"
62
+ v-if="showAdd && model.length < maxLen"
63
+ >
64
+ + 新增
65
+ </a-button>
66
+ </slot>
67
+ </template>
68
+ <a-tab-pane v-for="(item, idx) in model" :key="idx" :tab="`${tabLabel} ${idx + 1}`">
69
+ <template #closeIcon>
70
+ <a-dropdown v-if="editAble && itemMenus?.length">
71
+ <MoreOutlined />
72
+ <template #overlay>
73
+ <a-menu @click="(e) => handleMenu(toString(e.key), item, idx)">
74
+ <a-menu-item
75
+ v-for="menu in itemMenus.filter(
76
+ (f) => f.visibleMethod?.({ data: item, index: idx }) ?? true,
77
+ )"
78
+ :key="menu.code"
79
+ >
80
+ <div>{{ menu.content }}</div>
81
+ </a-menu-item>
82
+ </a-menu>
83
+ </template>
84
+ </a-dropdown>
85
+ </template>
86
+ <p-group-block :key="idx" :source="item" :get-form-setting="getFormSetting" />
87
+ </a-tab-pane>
88
+ </a-tabs>
89
+ </a-card>
90
+ </template>