@vue-ui-kit/ant 1.5.0 → 1.7.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.
- package/README.md +426 -0
- package/README.zh.md +480 -0
- package/dist/cjs/index.js +1 -1
- package/dist/declarations/antProxy.d.ts +9 -1
- package/dist/es/index.js +1469 -1127
- package/dist/packages/components/PGrid.vue.d.ts +5 -1
- package/dist/packages/components/PromisePicker.vue.d.ts +11 -1
- package/package.json +5 -2
- package/src/declarations/antProxy.ts +9 -2
- package/src/packages/components/PFormGroup.vue +48 -12
- package/src/packages/components/PGrid.vue +42 -14
- package/src/packages/components/PromisePicker.vue +44 -5
- package/tsconfig.json +41 -0
|
@@ -17,6 +17,7 @@ declare const _default: <D = Recordable<any>, F = Recordable<any>>(__VLS_props:
|
|
|
17
17
|
selectedKeys: Array<string | number>;
|
|
18
18
|
records: D[];
|
|
19
19
|
}) => any) | undefined;
|
|
20
|
+
readonly onResetQuery?: (() => any) | undefined;
|
|
20
21
|
} & import('vue').VNodeProps & import('vue').AllowedComponentProps & import('vue').ComponentCustomProps & Readonly<{}> & Readonly<{
|
|
21
22
|
onPick?: ((data: {
|
|
22
23
|
row: D;
|
|
@@ -34,7 +35,8 @@ declare const _default: <D = Recordable<any>, F = Recordable<any>>(__VLS_props:
|
|
|
34
35
|
selectedKeys: Array<string | number>;
|
|
35
36
|
records: D[];
|
|
36
37
|
}) => any) | undefined;
|
|
37
|
-
|
|
38
|
+
onResetQuery?: (() => any) | undefined;
|
|
39
|
+
}>, never>, "onPick" | "onToolbarButtonClick" | "onToolbarToolClick" | "onResetQuery"> & PGridProps<D, F>> & import('vue').PublicProps;
|
|
38
40
|
expose(exposed: import('vue').ShallowUnwrapRef<{
|
|
39
41
|
commitProxy: {
|
|
40
42
|
query: import('lodash').DebouncedFunc<() => Promise<D[]>>;
|
|
@@ -48,6 +50,7 @@ declare const _default: <D = Recordable<any>, F = Recordable<any>>(__VLS_props:
|
|
|
48
50
|
selectedRecords: import('vue').ComputedRef<D[]>;
|
|
49
51
|
$form: import('vue').ComputedRef<any>;
|
|
50
52
|
setLoadings: (value: boolean) => void;
|
|
53
|
+
resizeTable: () => void;
|
|
51
54
|
}>): void;
|
|
52
55
|
attrs: any;
|
|
53
56
|
slots: ReturnType<() => {}>;
|
|
@@ -68,6 +71,7 @@ declare const _default: <D = Recordable<any>, F = Recordable<any>>(__VLS_props:
|
|
|
68
71
|
row: D;
|
|
69
72
|
field: string;
|
|
70
73
|
}): void;
|
|
74
|
+
(event: "resetQuery"): void;
|
|
71
75
|
} & {};
|
|
72
76
|
}>) => import('vue').VNode<import('vue').RendererNode, import('vue').RendererElement, {
|
|
73
77
|
[key: string]: any;
|
|
@@ -5,11 +5,13 @@ declare const _default: <D = Recordable<any>, F = Recordable<any>>(__VLS_props:
|
|
|
5
5
|
title: string;
|
|
6
6
|
width: string | number;
|
|
7
7
|
bodyStyle: Record<string, any>;
|
|
8
|
+
multipleAllowEmpty: boolean;
|
|
8
9
|
}> & Omit<{
|
|
9
10
|
readonly title: string;
|
|
10
11
|
readonly width: string | number;
|
|
11
12
|
readonly bodyStyle: Record<string, any>;
|
|
12
13
|
readonly gridSetting: PGridProps<D, F>;
|
|
14
|
+
readonly multipleAllowEmpty: boolean;
|
|
13
15
|
} & import('vue').VNodeProps & import('vue').AllowedComponentProps & import('vue').ComponentCustomProps & Readonly<import('vue').ExtractPropTypes<{
|
|
14
16
|
gridSetting: {
|
|
15
17
|
type: PropType<PGridProps<D, F>>;
|
|
@@ -23,15 +25,23 @@ declare const _default: <D = Recordable<any>, F = Recordable<any>>(__VLS_props:
|
|
|
23
25
|
type: PropType<string | number>;
|
|
24
26
|
default: string;
|
|
25
27
|
};
|
|
28
|
+
multipleAllowEmpty: {
|
|
29
|
+
type: BooleanConstructor;
|
|
30
|
+
default: boolean;
|
|
31
|
+
};
|
|
26
32
|
bodyStyle: {
|
|
27
33
|
type: ObjectConstructor;
|
|
28
34
|
default: () => {};
|
|
29
35
|
};
|
|
30
|
-
}>> & Readonly<{}>, "title" | "width" | "bodyStyle">, "gridSetting" | ("title" | "width" | "bodyStyle")> & {}> & import('vue').PublicProps;
|
|
36
|
+
}>> & Readonly<{}>, "title" | "width" | "bodyStyle" | "multipleAllowEmpty">, "gridSetting" | ("title" | "width" | "bodyStyle" | "multipleAllowEmpty")> & {}> & import('vue').PublicProps;
|
|
31
37
|
expose(exposed: import('vue').ShallowUnwrapRef<{
|
|
32
38
|
pick: () => Promise<{
|
|
33
39
|
row: D;
|
|
34
40
|
field?: string;
|
|
41
|
+
} | D[]>;
|
|
42
|
+
pickMultiple: () => Promise<D[] | {
|
|
43
|
+
row: D;
|
|
44
|
+
field?: string;
|
|
35
45
|
}>;
|
|
36
46
|
}>): void;
|
|
37
47
|
attrs: any;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vue-ui-kit/ant",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.0",
|
|
4
4
|
"description": "Vue3 UI Kit based on Ant Design",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -14,7 +14,10 @@
|
|
|
14
14
|
},
|
|
15
15
|
"files": [
|
|
16
16
|
"dist",
|
|
17
|
-
"src"
|
|
17
|
+
"src",
|
|
18
|
+
"README.md",
|
|
19
|
+
"README.zh.md",
|
|
20
|
+
"tsconfig.json"
|
|
18
21
|
],
|
|
19
22
|
"scripts": {
|
|
20
23
|
"dev": "vue-tsc --noEmit --skipLibCheck & vite",
|
|
@@ -4,6 +4,7 @@ import { ColProps } from 'ant-design-vue/lib/grid/Col';
|
|
|
4
4
|
import { FormProps } from 'ant-design-vue/lib/form/Form';
|
|
5
5
|
import { TableColumnType, TableProps, TooltipProps } from 'ant-design-vue';
|
|
6
6
|
import { ButtonType } from 'ant-design-vue/lib/button/buttonTypes';
|
|
7
|
+
import { ComputedRef } from 'vue';
|
|
7
8
|
|
|
8
9
|
export interface CellFuncArg<D = Recordable> {
|
|
9
10
|
row: D;
|
|
@@ -89,7 +90,7 @@ export type GroupMenuItemHandler<F = Recordable> = ({
|
|
|
89
90
|
}: {
|
|
90
91
|
index: number;
|
|
91
92
|
code: string;
|
|
92
|
-
data: Partial<F>;
|
|
93
|
+
data: Partial<F & { __index: number }>;
|
|
93
94
|
}) => void;
|
|
94
95
|
|
|
95
96
|
export interface GroupMenuItem<F = Recordable> {
|
|
@@ -105,6 +106,8 @@ export interface PFormGroupProps<F = Recordable> {
|
|
|
105
106
|
tabLabel?: string;
|
|
106
107
|
editAble?: boolean;
|
|
107
108
|
showAdd?: boolean;
|
|
109
|
+
/* 是否保持连续编号 */
|
|
110
|
+
keepSerial?: boolean;
|
|
108
111
|
itemMenus?: Array<GroupMenuItem<F>>;
|
|
109
112
|
creatItem?: ({ list }: { list?: Partial<F>[] }) => Promise<Partial<F>>;
|
|
110
113
|
max?: number;
|
|
@@ -139,7 +142,8 @@ export interface ToolbarButtonProps extends PButtonProps {
|
|
|
139
142
|
|
|
140
143
|
export interface ToolbarConfig {
|
|
141
144
|
buttons?: Array<ToolbarButtonProps>;
|
|
142
|
-
tools?: Array<{ code: string; icon: string; type?: ButtonType }>;
|
|
145
|
+
tools?: Array<{ code: string; icon: string; type?: ButtonType; disabled?: boolean }>;
|
|
146
|
+
disabled?: boolean;
|
|
143
147
|
}
|
|
144
148
|
|
|
145
149
|
export interface ResponsePathConfig<D = Recordable> {
|
|
@@ -255,10 +259,12 @@ export interface PGridInstance<D = Recordable, F = Recordable> {
|
|
|
255
259
|
passQuery: (query: Partial<F>, lazy?: boolean) => Promise<void | D[]>;
|
|
256
260
|
};
|
|
257
261
|
selectedRowKeys: string[] | number[];
|
|
262
|
+
selectedRecords: D[];
|
|
258
263
|
$table: Recordable;
|
|
259
264
|
$form: Recordable;
|
|
260
265
|
setLoadings: (value: boolean) => void;
|
|
261
266
|
setBtnLoading: (code: string, status: boolean) => void;
|
|
267
|
+
resizeTable: () => void;
|
|
262
268
|
}
|
|
263
269
|
|
|
264
270
|
export interface PFormInstance {
|
|
@@ -268,6 +274,7 @@ export interface PFormInstance {
|
|
|
268
274
|
|
|
269
275
|
export interface PromisePickerInstance<D = Recordable> {
|
|
270
276
|
pick: () => Promise<{ row: D; field?: string }>;
|
|
277
|
+
pickMultiple: () => Promise<D[]>;
|
|
271
278
|
}
|
|
272
279
|
|
|
273
280
|
export interface PFormBlockInstance {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<script lang="ts" generic="F = Recordable" setup name="PFormGroup">
|
|
2
|
-
import { computed, nextTick, PropType, ref } from 'vue';
|
|
2
|
+
import { computed, nextTick, PropType, ref, watchEffect } from 'vue';
|
|
3
3
|
import { PFormGroupProps, PFormBlockInstance } from '#/antProxy';
|
|
4
4
|
import { MoreOutlined } from '@ant-design/icons-vue';
|
|
5
|
-
import { cloneDeep, toString, isFunction, omit } from 'lodash-es';
|
|
5
|
+
import { cloneDeep, toString, isFunction, omit, maxBy, debounce } from 'lodash-es';
|
|
6
6
|
import PGroupBlock from '@/components/PGroupBlock.vue';
|
|
7
7
|
import {
|
|
8
8
|
Card as ACard,
|
|
@@ -13,10 +13,12 @@
|
|
|
13
13
|
Menu as AMenu,
|
|
14
14
|
MenuItem as AMenuItem,
|
|
15
15
|
} from 'ant-design-vue';
|
|
16
|
+
import { valued } from '@/utils/is';
|
|
17
|
+
import { MenuInfo } from 'ant-design-vue/es/menu/src/interface';
|
|
16
18
|
|
|
17
19
|
const props = defineProps<PFormGroupProps<F>>();
|
|
18
20
|
const model = defineModel({
|
|
19
|
-
type: Array as PropType<Partial<F>[]>,
|
|
21
|
+
type: Array as PropType<Partial<F & { __index: number }>[]>,
|
|
20
22
|
default: () => [],
|
|
21
23
|
});
|
|
22
24
|
const activeKey = ref(0);
|
|
@@ -24,18 +26,38 @@
|
|
|
24
26
|
const setActiveKey = (key: number) => {
|
|
25
27
|
activeKey.value = key;
|
|
26
28
|
};
|
|
27
|
-
const maxLen = props.max ?? Infinity;
|
|
29
|
+
const maxLen = computed(() => props.max ?? Infinity);
|
|
28
30
|
const handleAddItem = (idx: number) => {
|
|
29
31
|
const creator = props.creatItem ?? (() => Promise.resolve({} as Partial<F>));
|
|
30
32
|
creator({ list: model.value }).then((item) => {
|
|
31
|
-
model.value = [
|
|
33
|
+
model.value = [
|
|
34
|
+
...model.value,
|
|
35
|
+
{
|
|
36
|
+
...item,
|
|
37
|
+
__index: (maxBy(model.value, (m) => m.__index ?? -1)?.__index ?? -1) + 1,
|
|
38
|
+
} as Partial<F & { __index: number }>,
|
|
39
|
+
];
|
|
32
40
|
activeKey.value = idx;
|
|
33
41
|
});
|
|
34
42
|
};
|
|
35
|
-
const itemMenus = props.itemMenus ?? [
|
|
36
|
-
|
|
43
|
+
const itemMenus = props.itemMenus ?? [
|
|
44
|
+
{ content: '复制', code: 'copy' },
|
|
45
|
+
{ content: '删除', code: 'delete' },
|
|
46
|
+
];
|
|
47
|
+
watchEffect(() => {
|
|
48
|
+
if (!props.keepSerial) {
|
|
49
|
+
const unSortItems = model.value.filter((f) => !valued(f.__index));
|
|
50
|
+
if (unSortItems.length > 0) {
|
|
51
|
+
unSortItems.forEach((item) => {
|
|
52
|
+
// @ts-ignore
|
|
53
|
+
item.__index = (maxBy(model.value, (m) => m.__index ?? -1)?.__index ?? -1) + 1;
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
const handleMenu = ({ key }: MenuInfo, item: Partial<F & { __index: number }>, idx: number) => {
|
|
37
59
|
if (props.menuHandler && isFunction(props.menuHandler)) {
|
|
38
|
-
props.menuHandler({ code: key, data: item, index: idx });
|
|
60
|
+
props.menuHandler({ code: toString(key), data: item, index: idx });
|
|
39
61
|
} else {
|
|
40
62
|
switch (key) {
|
|
41
63
|
case 'delete':
|
|
@@ -48,11 +70,25 @@
|
|
|
48
70
|
});
|
|
49
71
|
break;
|
|
50
72
|
case 'copy':
|
|
51
|
-
model.value = [
|
|
73
|
+
model.value = [
|
|
74
|
+
...model.value,
|
|
75
|
+
cloneDeep({
|
|
76
|
+
...omit(item, ['id', '__index']),
|
|
77
|
+
__index: (maxBy(model.value, (m) => m.__index ?? -1)?.__index ?? -1) + 1,
|
|
78
|
+
}),
|
|
79
|
+
] as Partial<F & { __index: number }>[];
|
|
52
80
|
break;
|
|
53
81
|
}
|
|
54
82
|
}
|
|
55
83
|
};
|
|
84
|
+
const debounceHandleMenu = debounce(handleMenu, 100);
|
|
85
|
+
watchEffect(() => {
|
|
86
|
+
if (model.value.length === 0) {
|
|
87
|
+
activeKey.value = 0;
|
|
88
|
+
} else if (activeKey.value >= model.value.length) {
|
|
89
|
+
activeKey.value = model.value.length - 1;
|
|
90
|
+
}
|
|
91
|
+
});
|
|
56
92
|
defineExpose({
|
|
57
93
|
activeKey: computed(() => activeKey.value),
|
|
58
94
|
setActiveKey,
|
|
@@ -69,9 +105,9 @@
|
|
|
69
105
|
<template #rightExtra>
|
|
70
106
|
<slot name="rightExtra">
|
|
71
107
|
<a-button
|
|
108
|
+
v-if="showAdd && model.length < maxLen"
|
|
72
109
|
type="link"
|
|
73
110
|
@click="handleAddItem(model.length)"
|
|
74
|
-
v-if="showAdd && model.length < maxLen"
|
|
75
111
|
>
|
|
76
112
|
+ 新增
|
|
77
113
|
</a-button>
|
|
@@ -80,14 +116,14 @@
|
|
|
80
116
|
<a-tab-pane
|
|
81
117
|
v-for="(item, idx) in model"
|
|
82
118
|
:key="idx"
|
|
83
|
-
:tab="`${tabLabel} ${idx + 1}`"
|
|
119
|
+
:tab="`${tabLabel} ${keepSerial ? idx + 1 : (item.__index ?? 0) + 1}`"
|
|
84
120
|
force-render
|
|
85
121
|
>
|
|
86
122
|
<template #closeIcon>
|
|
87
123
|
<a-dropdown v-if="editAble && itemMenus?.length">
|
|
88
124
|
<MoreOutlined />
|
|
89
125
|
<template #overlay>
|
|
90
|
-
<a-menu @click="(e) =>
|
|
126
|
+
<a-menu @click="(e) => debounceHandleMenu(e, item, idx)">
|
|
91
127
|
<a-menu-item
|
|
92
128
|
v-for="menu in itemMenus.filter(
|
|
93
129
|
(f) => f.visibleMethod?.({ data: item, index: idx }) ?? true,
|
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
<script generic="D = Recordable, F = Recordable" lang="ts" name="PGrid" setup>
|
|
2
2
|
import { ColumnProps, PFormItemProps, PGridProps, ResponsePathConfig } from '#/antProxy';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
computed,
|
|
5
|
+
useAttrs,
|
|
6
|
+
ref,
|
|
7
|
+
Ref,
|
|
8
|
+
reactive,
|
|
9
|
+
onMounted,
|
|
10
|
+
watch,
|
|
11
|
+
toRefs,
|
|
12
|
+
onBeforeUnmount,
|
|
13
|
+
} from 'vue';
|
|
4
14
|
import { debounce, get, isArray, isFunction, isString, merge, omit, toNumber } from 'lodash-es';
|
|
5
15
|
import { eachTree } from '@/utils/treeHelper';
|
|
6
16
|
import { message as $message } from 'ant-design-vue';
|
|
@@ -44,6 +54,7 @@
|
|
|
44
54
|
});
|
|
45
55
|
const submitOnReset = true;
|
|
46
56
|
const boxEl = ref<HTMLDivElement>();
|
|
57
|
+
const pFormWrapper = ref<HTMLDivElement>();
|
|
47
58
|
const renderHeight = ref(500);
|
|
48
59
|
const selectedRowKeys = ref<Array<string | number>>([]);
|
|
49
60
|
const selectedCaches = ref<D[]>([]);
|
|
@@ -156,6 +167,7 @@
|
|
|
156
167
|
data: { data: D[]; code: string; selectedKeys: Array<string | number>; records: D[] },
|
|
157
168
|
): void;
|
|
158
169
|
(event: 'pick', data: { row: D; field: string }): void;
|
|
170
|
+
(event: 'resetQuery'): void;
|
|
159
171
|
}>();
|
|
160
172
|
// @ts-ignore
|
|
161
173
|
const selectedRecords = computed<D[]>(() =>
|
|
@@ -205,6 +217,7 @@
|
|
|
205
217
|
});
|
|
206
218
|
queryFormData.value = obj;
|
|
207
219
|
}
|
|
220
|
+
emit('resetQuery');
|
|
208
221
|
refreshForm();
|
|
209
222
|
}
|
|
210
223
|
|
|
@@ -377,6 +390,21 @@
|
|
|
377
390
|
},
|
|
378
391
|
{ deep: true },
|
|
379
392
|
);
|
|
393
|
+
const resizeTable = () => {
|
|
394
|
+
const pNode = boxEl.value?.parentElement;
|
|
395
|
+
const ph = pNode ? window.getComputedStyle(pNode).height : '0px';
|
|
396
|
+
const formHeight = pFormWrapper.value
|
|
397
|
+
? toNumber(window.getComputedStyle(pFormWrapper.value).height.replace('px', ''))
|
|
398
|
+
: 0;
|
|
399
|
+
|
|
400
|
+
renderHeight.value =
|
|
401
|
+
props.renderY ??
|
|
402
|
+
toNumber(ph.replace('px', '')) -
|
|
403
|
+
(props.fitHeight ?? 170) -
|
|
404
|
+
(!!props.toolbarConfig ? 30 : 0) -
|
|
405
|
+
formHeight;
|
|
406
|
+
enoughSpacing.value = toNumber(ph.replace('px', '')) > 600;
|
|
407
|
+
};
|
|
380
408
|
defineExpose({
|
|
381
409
|
commitProxy: {
|
|
382
410
|
query: debounceFetchData,
|
|
@@ -394,20 +422,16 @@
|
|
|
394
422
|
loading.table = value;
|
|
395
423
|
loading.toolbar = value;
|
|
396
424
|
},
|
|
425
|
+
resizeTable,
|
|
397
426
|
});
|
|
398
427
|
onMounted(() => {
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
const ph = pNode ? window.getComputedStyle(pNode).height : '0px';
|
|
402
|
-
renderHeight.value =
|
|
403
|
-
props.renderY ??
|
|
404
|
-
toNumber(ph.replace('px', '')) -
|
|
405
|
-
(props.fitHeight ?? 170) -
|
|
406
|
-
(!!props.toolbarConfig ? 30 : 0) -
|
|
407
|
-
Math.ceil((props.formConfig?.items?.length ?? 0) / 4) * 35;
|
|
408
|
-
enoughSpacing.value = toNumber(ph.replace('px', '')) > 600;
|
|
428
|
+
resizeTable();
|
|
429
|
+
window.addEventListener('resize', resizeTable);
|
|
409
430
|
resetQueryFormData(props.manualFetch);
|
|
410
431
|
});
|
|
432
|
+
onBeforeUnmount(() => {
|
|
433
|
+
window.removeEventListener('resize', resizeTable);
|
|
434
|
+
});
|
|
411
435
|
</script>
|
|
412
436
|
<template>
|
|
413
437
|
<div ref="boxEl" class="h-full p-wrapper flex flex-col gap-8px overflow-y-auto" v-bind="attrs">
|
|
@@ -416,6 +440,7 @@
|
|
|
416
440
|
<div
|
|
417
441
|
v-if="formConfig?.items?.some((s: PFormItemProps<F>) => s.field && s.itemRender)"
|
|
418
442
|
class="p-pane p-form-wrapper"
|
|
443
|
+
ref="pFormWrapper"
|
|
419
444
|
>
|
|
420
445
|
<a-spin :spinning="loading.form">
|
|
421
446
|
<a-form
|
|
@@ -504,7 +529,8 @@
|
|
|
504
529
|
</template>
|
|
505
530
|
<a-button
|
|
506
531
|
:type="btn.type"
|
|
507
|
-
:size="btn.size ?? '
|
|
532
|
+
:size="btn.size ?? 'middle'"
|
|
533
|
+
:disabled="toolbarConfig.disabled || btn.disabled"
|
|
508
534
|
:loading="loading.toolbar || (!!btn.code && codeLoadings[btn.code])"
|
|
509
535
|
>
|
|
510
536
|
<Icon v-if="btn.icon" :icon="btn.icon" />
|
|
@@ -515,7 +541,8 @@
|
|
|
515
541
|
<a-button
|
|
516
542
|
v-else-if="btn.code"
|
|
517
543
|
:type="btn.type"
|
|
518
|
-
:size="btn.size ?? '
|
|
544
|
+
:size="btn.size ?? 'middle'"
|
|
545
|
+
:disabled="toolbarConfig.disabled || btn.disabled"
|
|
519
546
|
:loading="loading.toolbar || (!!btn.code && codeLoadings[btn.code])"
|
|
520
547
|
@click="debounceToolBtnClick(btn.code)"
|
|
521
548
|
>
|
|
@@ -532,7 +559,8 @@
|
|
|
532
559
|
v-for="(tool, idx) in toolbarConfig.tools"
|
|
533
560
|
:key="idx"
|
|
534
561
|
:type="tool.type"
|
|
535
|
-
size="
|
|
562
|
+
:size="btn.size ?? 'middle'"
|
|
563
|
+
:disabled="toolbarConfig.disabled || tool.disabled"
|
|
536
564
|
@click="debounceToolToolClick(tool.code)"
|
|
537
565
|
:loading="loading.toolbar || (!!tool.code && codeLoadings[tool.code])"
|
|
538
566
|
>
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
<script lang="ts" setup name="PromisePicker" generic="D = Recordable, F = Recordable">
|
|
2
|
-
import { PropType, reactive, ref } from 'vue';
|
|
2
|
+
import { PropType, reactive, ref, computed } from 'vue';
|
|
3
3
|
import { PGridInstance, PGridProps } from '#/antProxy';
|
|
4
4
|
import PGrid from '@/components/PGrid.vue';
|
|
5
|
+
import { $warning } from '@/hooks/useMessage';
|
|
6
|
+
import { Button as AButton, Modal as AModal } from 'ant-design-vue';
|
|
5
7
|
|
|
6
8
|
const gridEl = ref<PGridInstance<D>>();
|
|
7
|
-
defineProps({
|
|
9
|
+
const props = defineProps({
|
|
8
10
|
gridSetting: {
|
|
9
11
|
type: Object as PropType<PGridProps<D, F>>,
|
|
10
12
|
required: true,
|
|
@@ -17,14 +19,20 @@
|
|
|
17
19
|
type: [String, Number] as PropType<string | number>,
|
|
18
20
|
default: '70%',
|
|
19
21
|
},
|
|
22
|
+
multipleAllowEmpty: {
|
|
23
|
+
type: Boolean,
|
|
24
|
+
default: false,
|
|
25
|
+
},
|
|
20
26
|
bodyStyle: {
|
|
21
27
|
type: Object,
|
|
22
28
|
default: () => ({}),
|
|
23
29
|
},
|
|
24
30
|
});
|
|
31
|
+
const isMultiple = computed(() => props.gridSetting.selectConfig?.multiple);
|
|
25
32
|
let resolvePromise: (
|
|
26
33
|
value: { row: D; field?: string } | PromiseLike<{ row: D; field?: string }>,
|
|
27
34
|
) => void;
|
|
35
|
+
let multipleResolver: (rows: D[]) => void;
|
|
28
36
|
let rejectPromise: (reason?: any) => void;
|
|
29
37
|
const visible = reactive({
|
|
30
38
|
modal: false,
|
|
@@ -34,19 +42,42 @@
|
|
|
34
42
|
rejectPromise();
|
|
35
43
|
}
|
|
36
44
|
};
|
|
45
|
+
|
|
46
|
+
const manualCancel = () => {
|
|
47
|
+
visible.modal = false;
|
|
48
|
+
if (rejectPromise) {
|
|
49
|
+
rejectPromise();
|
|
50
|
+
}
|
|
51
|
+
};
|
|
37
52
|
const selectRow = ({ row, field }: { row: D; field?: string }) => {
|
|
38
|
-
|
|
53
|
+
// 单选才关闭结束选择
|
|
54
|
+
if (resolvePromise && !isMultiple.value) {
|
|
39
55
|
visible.modal = false;
|
|
40
56
|
resolvePromise({ row, field });
|
|
41
57
|
}
|
|
42
58
|
};
|
|
59
|
+
const endMultiplePicker = () => {
|
|
60
|
+
const records = gridEl.value?.selectedRecords ?? [];
|
|
61
|
+
if (records.length === 0 && !props.multipleAllowEmpty) {
|
|
62
|
+
$warning('请选择数据');
|
|
63
|
+
} else {
|
|
64
|
+
visible.modal = false;
|
|
65
|
+
multipleResolver(records);
|
|
66
|
+
}
|
|
67
|
+
};
|
|
43
68
|
defineExpose({
|
|
44
69
|
pick: () =>
|
|
45
|
-
new Promise<{ row: D; field?: string }>((resolve, reject) => {
|
|
70
|
+
new Promise<{ row: D; field?: string } | D[]>((resolve, reject) => {
|
|
46
71
|
resolvePromise = resolve;
|
|
47
72
|
rejectPromise = reject;
|
|
48
73
|
visible.modal = true;
|
|
49
74
|
}),
|
|
75
|
+
pickMultiple: () =>
|
|
76
|
+
new Promise<{ row: D; field?: string } | D[]>((resolve, reject) => {
|
|
77
|
+
multipleResolver = resolve;
|
|
78
|
+
rejectPromise = reject;
|
|
79
|
+
visible.modal = true;
|
|
80
|
+
}),
|
|
50
81
|
});
|
|
51
82
|
</script>
|
|
52
83
|
<template>
|
|
@@ -55,10 +86,18 @@
|
|
|
55
86
|
destroy-on-close
|
|
56
87
|
:title="title"
|
|
57
88
|
:width="width"
|
|
58
|
-
:footer="null"
|
|
89
|
+
:footer="isMultiple ? undefined : null"
|
|
59
90
|
@cancel="handleCancel"
|
|
60
91
|
:body-style="bodyStyle"
|
|
61
92
|
>
|
|
62
93
|
<p-grid v-bind="gridSetting" ref="gridEl" @pick="selectRow" />
|
|
94
|
+
<template v-if="isMultiple" #footer>
|
|
95
|
+
<div class="w-full text-right p-2">
|
|
96
|
+
<span>
|
|
97
|
+
<a-button class="mr-4" @click="manualCancel"> 取消 </a-button>
|
|
98
|
+
<a-button type="primary" @click="endMultiplePicker"> 确定 </a-button>
|
|
99
|
+
</span>
|
|
100
|
+
</div>
|
|
101
|
+
</template>
|
|
63
102
|
</a-modal>
|
|
64
103
|
</template>
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "../../tsconfig.base.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"rootDir": "./src",
|
|
5
|
+
"outDir": "./dist",
|
|
6
|
+
"tsBuildInfoFile": "./dist/tsconfig.tsbuildinfo",
|
|
7
|
+
"emitDeclarationOnly": true,
|
|
8
|
+
"noImplicitAny": false,
|
|
9
|
+
"types": [
|
|
10
|
+
"vite/client",
|
|
11
|
+
"node"
|
|
12
|
+
],
|
|
13
|
+
"jsx": "preserve",
|
|
14
|
+
"jsxImportSource": "vue",
|
|
15
|
+
"paths": {
|
|
16
|
+
"@/*": [
|
|
17
|
+
"./src/packages/*"
|
|
18
|
+
],
|
|
19
|
+
"#/*": [
|
|
20
|
+
"./src/declarations/*"
|
|
21
|
+
]
|
|
22
|
+
},
|
|
23
|
+
"plugins": [
|
|
24
|
+
// Transform paths in output .js files
|
|
25
|
+
{
|
|
26
|
+
"transform": "typescript-transform-paths"
|
|
27
|
+
},
|
|
28
|
+
// Transform paths for declarations files
|
|
29
|
+
{
|
|
30
|
+
"transform": "typescript-transform-paths",
|
|
31
|
+
"afterDeclarations": true
|
|
32
|
+
}
|
|
33
|
+
]
|
|
34
|
+
},
|
|
35
|
+
"include": [
|
|
36
|
+
"src"
|
|
37
|
+
],
|
|
38
|
+
"exclude": [
|
|
39
|
+
"node_modules"
|
|
40
|
+
]
|
|
41
|
+
}
|