@vue-ui-kit/ant 1.9.3 → 2.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.
- package/dist/cjs/index.js +4 -1
- package/dist/declarations/antProxy.d.ts +58 -20
- package/dist/es/index.js +8857 -2969
- package/dist/index.d.ts +5 -6
- package/dist/packages/components/PCanvasGrid.vue.d.ts +2 -0
- package/dist/packages/components/PCanvasTable.vue.d.ts +134 -0
- package/dist/packages/components/PForm.vue.d.ts +8 -14
- package/dist/packages/components/PFormCol.vue.d.ts +8 -13
- package/dist/packages/components/PFormGroup.vue.d.ts +16 -16
- package/dist/packages/components/PGrid.vue.d.ts +7 -27
- package/dist/packages/components/PGroupBlock.vue.d.ts +5 -7
- package/dist/packages/components/PromisePicker.vue.d.ts +8 -43
- package/dist/packages/components/RenderEditCell.d.ts +10 -0
- package/dist/packages/renders/TableInput.vue.d.ts +7 -26
- package/dist/packages/store/renderStore.d.ts +10 -58
- package/dist/packages/utils/AFormatters.d.ts +3 -13
- package/dist/packages/utils/treeHelper.d.ts +7 -7
- package/dist/style.scss +59 -35
- package/package.json +2 -1
- package/src/declarations/antProxy.ts +78 -22
- package/src/index.ts +15 -2
- package/src/packages/components/PCanvasGrid.vue +6 -0
- package/src/packages/components/PCanvasTable.vue +286 -0
- package/src/packages/components/PForm.vue +5 -5
- package/src/packages/components/PFormGroup.vue +1 -1
- package/src/packages/components/PGrid.vue +10 -5
- package/src/packages/components/PGroupBlock.vue +1 -1
- package/src/packages/components/PromisePicker.vue +19 -29
- package/src/packages/components/RenderAntCell.tsx +2 -2
- package/src/packages/components/RenderAntItem.tsx +2 -2
- package/src/packages/components/RenderDefaultSlots.tsx +1 -1
- package/src/packages/components/RenderEditCell.tsx +36 -0
- package/src/packages/components/RenderItemSlots.tsx +1 -1
- package/src/packages/components/RenderTitleSlots.tsx +1 -1
- package/src/packages/renders/TableInput.vue +1 -1
- package/src/packages/store/renderStore.tsx +44 -18
- package/src/packages/styles/index.scss +59 -31
- package/src/packages/utils/AFormatters.ts +3 -3
package/dist/style.scss
CHANGED
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
:root {
|
|
3
|
-
--p-theme-bg: #fff;
|
|
4
|
-
}
|
|
5
|
-
|
|
1
|
+
@use 'variables';
|
|
6
2
|
|
|
7
3
|
.p-pane {
|
|
8
4
|
background-color: var(--p-theme-bg);
|
|
@@ -104,9 +100,9 @@
|
|
|
104
100
|
z-index: 4;
|
|
105
101
|
}
|
|
106
102
|
.p-error-hang-out {
|
|
107
|
-
.ant-input-affix-wrapper-status-error:not(
|
|
108
|
-
.ant-input-affix-wrapper-
|
|
109
|
-
)
|
|
103
|
+
.ant-input-affix-wrapper-status-error:not(.ant-input-affix-wrapper-disabled):not(
|
|
104
|
+
.ant-input-affix-wrapper-borderless
|
|
105
|
+
).ant-input-affix-wrapper {
|
|
110
106
|
border-color: #d9d9d9 !important;
|
|
111
107
|
|
|
112
108
|
&:focus {
|
|
@@ -126,7 +122,9 @@
|
|
|
126
122
|
transform: translateY(-10px);
|
|
127
123
|
max-height: 0;
|
|
128
124
|
overflow: hidden;
|
|
129
|
-
transition:
|
|
125
|
+
transition:
|
|
126
|
+
opacity 0.3s ease-out 0.3s,
|
|
127
|
+
transform 0.3s ease-out 0.3s,
|
|
130
128
|
max-height 0.3s ease-out 0.3s;
|
|
131
129
|
}
|
|
132
130
|
.ant-form-item-has-error .ant-form-item-explain-error {
|
|
@@ -238,25 +236,25 @@
|
|
|
238
236
|
}
|
|
239
237
|
}
|
|
240
238
|
}
|
|
241
|
-
.p-error-group-tab{
|
|
242
|
-
position:relative;
|
|
239
|
+
.p-error-group-tab {
|
|
240
|
+
position: relative;
|
|
243
241
|
overflow: visible;
|
|
244
|
-
color
|
|
245
|
-
&:after{
|
|
246
|
-
content:'🏷️';
|
|
247
|
-
position:absolute;
|
|
248
|
-
top
|
|
249
|
-
right:0;
|
|
250
|
-
width:1em;
|
|
251
|
-
height:1em;
|
|
252
|
-
font-size:0.8em;
|
|
242
|
+
color: #f5222d !important;
|
|
243
|
+
&:after {
|
|
244
|
+
content: '🏷️';
|
|
245
|
+
position: absolute;
|
|
246
|
+
top: -1em;
|
|
247
|
+
right: 0;
|
|
248
|
+
width: 1em;
|
|
249
|
+
height: 1em;
|
|
250
|
+
font-size: 0.8em;
|
|
253
251
|
animation: heartbeat 2s infinite;
|
|
254
252
|
}
|
|
255
253
|
}
|
|
256
254
|
.p-error-hang-out {
|
|
257
|
-
.ant-input-affix-wrapper-status-error:not(
|
|
258
|
-
.ant-input-affix-wrapper-
|
|
259
|
-
)
|
|
255
|
+
.ant-input-affix-wrapper-status-error:not(.ant-input-affix-wrapper-disabled):not(
|
|
256
|
+
.ant-input-affix-wrapper-borderless
|
|
257
|
+
).ant-input-affix-wrapper {
|
|
260
258
|
border-color: #d9d9d9 !important;
|
|
261
259
|
|
|
262
260
|
&:focus {
|
|
@@ -276,6 +274,10 @@
|
|
|
276
274
|
}
|
|
277
275
|
//endregion
|
|
278
276
|
|
|
277
|
+
/* #region EVirtTable */
|
|
278
|
+
|
|
279
|
+
/* #endregion */
|
|
280
|
+
|
|
279
281
|
@each $align in right center {
|
|
280
282
|
/**/
|
|
281
283
|
.p-content-align-#{$align}.ant-form-item .ant-form-item-control-input-content {
|
|
@@ -291,15 +293,37 @@
|
|
|
291
293
|
}
|
|
292
294
|
|
|
293
295
|
@keyframes heartbeat {
|
|
294
|
-
0%
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
}
|
|
296
|
+
0% {
|
|
297
|
+
transform: scale(1);
|
|
298
|
+
}
|
|
299
|
+
6% {
|
|
300
|
+
transform: scale(1.22);
|
|
301
|
+
}
|
|
302
|
+
12% {
|
|
303
|
+
transform: scale(1);
|
|
304
|
+
}
|
|
305
|
+
18% {
|
|
306
|
+
transform: scale(1.18);
|
|
307
|
+
}
|
|
308
|
+
24% {
|
|
309
|
+
transform: scale(1);
|
|
310
|
+
}
|
|
311
|
+
48% {
|
|
312
|
+
transform: scale(1);
|
|
313
|
+
} // 长停顿
|
|
314
|
+
54% {
|
|
315
|
+
transform: scale(1.22);
|
|
316
|
+
}
|
|
317
|
+
60% {
|
|
318
|
+
transform: scale(1);
|
|
319
|
+
}
|
|
320
|
+
66% {
|
|
321
|
+
transform: scale(1.18);
|
|
322
|
+
}
|
|
323
|
+
72% {
|
|
324
|
+
transform: scale(1);
|
|
325
|
+
}
|
|
326
|
+
100% {
|
|
327
|
+
transform: scale(1);
|
|
328
|
+
} // 长停顿
|
|
329
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vue-ui-kit/ant",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Vue3 UI Kit based on Ant Design",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/cjs/index.js",
|
|
@@ -48,6 +48,7 @@
|
|
|
48
48
|
"email": "adoin@qq.com"
|
|
49
49
|
},
|
|
50
50
|
"dependencies": {
|
|
51
|
+
"e-virt-table": "^1.2.20",
|
|
51
52
|
"uuid": "^10.0.0",
|
|
52
53
|
"xe-utils": "^3.7.6"
|
|
53
54
|
},
|
|
@@ -4,15 +4,17 @@ 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 type { ConfigType, Column as EVirtColumn } from 'e-virt-table';
|
|
7
8
|
|
|
8
|
-
export interface CellFuncArg<D = Recordable> {
|
|
9
|
+
export interface CellFuncArg<D extends Recordable = Recordable> {
|
|
9
10
|
row: D;
|
|
10
|
-
column
|
|
11
|
+
column?: ColumnProps<D>;
|
|
11
12
|
rowIndex: number;
|
|
12
13
|
cellValue: any;
|
|
13
14
|
}
|
|
14
|
-
|
|
15
|
-
export
|
|
15
|
+
export type FormatterFunc = (c: CellFuncArg, ...args: any[]) => any;
|
|
16
|
+
export type PFormatter = Record<string, FormatterFunc>;
|
|
17
|
+
export interface ItemFuncArg<F extends Recordable = Recordable> {
|
|
16
18
|
data: F;
|
|
17
19
|
field?: string;
|
|
18
20
|
}
|
|
@@ -48,7 +50,7 @@ export interface TooltipConfig extends TooltipProps {
|
|
|
48
50
|
title: TooltipProps['title'] | (() => any);
|
|
49
51
|
}
|
|
50
52
|
|
|
51
|
-
export interface PFormItemProps<F = Recordable> {
|
|
53
|
+
export interface PFormItemProps<F extends Recordable = Recordable> {
|
|
52
54
|
field?: string;
|
|
53
55
|
title?: string;
|
|
54
56
|
span?: number;
|
|
@@ -72,23 +74,29 @@ export interface PFormItemProps<F = Recordable> {
|
|
|
72
74
|
};
|
|
73
75
|
}
|
|
74
76
|
|
|
75
|
-
export interface PFormProps<F = Recordable> extends FormProps {
|
|
77
|
+
export interface PFormProps<F extends Recordable = Recordable> extends FormProps {
|
|
76
78
|
items: PFormItemProps<F>[];
|
|
77
79
|
customReset?: () => void;
|
|
78
80
|
}
|
|
79
81
|
|
|
80
|
-
export interface PBlockProps<F = Recordable> {
|
|
82
|
+
export interface PBlockProps<F extends Recordable = Recordable> {
|
|
81
83
|
getFormSetting: (data: Partial<F>) => PFormProps<Partial<F>>;
|
|
82
84
|
source: Partial<F>;
|
|
83
85
|
}
|
|
84
86
|
|
|
85
|
-
export interface PromisePickerProps<
|
|
87
|
+
export interface PromisePickerProps<
|
|
88
|
+
D extends Recordable = Recordable,
|
|
89
|
+
F extends Recordable = Recordable,
|
|
90
|
+
> {
|
|
86
91
|
gridSetting: PGridProps<D, F>;
|
|
87
92
|
title?: string;
|
|
88
93
|
width?: string | number;
|
|
94
|
+
multipleAllowEmpty?: boolean;
|
|
95
|
+
bodyStyle?: Recordable;
|
|
96
|
+
beforePick?: (rowOrRows: D | Array<D>) => Promise<void>;
|
|
89
97
|
}
|
|
90
98
|
|
|
91
|
-
export type GroupMenuItemHandler<F = Recordable> = ({
|
|
99
|
+
export type GroupMenuItemHandler<F extends Recordable = Recordable> = ({
|
|
92
100
|
index,
|
|
93
101
|
data,
|
|
94
102
|
code,
|
|
@@ -98,14 +106,14 @@ export type GroupMenuItemHandler<F = Recordable> = ({
|
|
|
98
106
|
data: Partial<F & { __index: number }>;
|
|
99
107
|
}) => void;
|
|
100
108
|
|
|
101
|
-
export interface GroupMenuItem<F = Recordable> {
|
|
109
|
+
export interface GroupMenuItem<F extends Recordable = Recordable> {
|
|
102
110
|
content: string;
|
|
103
111
|
icon?: string;
|
|
104
112
|
code: string;
|
|
105
113
|
visibleMethod?: ({ data, index }: { data: Partial<F>; index: number }) => boolean;
|
|
106
114
|
}
|
|
107
115
|
|
|
108
|
-
export interface PFormGroupProps<F = Recordable> {
|
|
116
|
+
export interface PFormGroupProps<F extends Recordable = Recordable> {
|
|
109
117
|
getFormSetting: (data: Partial<F>) => PFormProps<Partial<F>>;
|
|
110
118
|
title?: string;
|
|
111
119
|
tabLabel?: string;
|
|
@@ -122,7 +130,8 @@ export interface PFormGroupProps<F = Recordable> {
|
|
|
122
130
|
menuHandler?: GroupMenuItemHandler<F>;
|
|
123
131
|
}
|
|
124
132
|
|
|
125
|
-
export interface ColumnProps<D
|
|
133
|
+
export interface ColumnProps<D extends Recordable = Recordable>
|
|
134
|
+
extends Omit<TableColumnType, 'slots'> {
|
|
126
135
|
field?: string;
|
|
127
136
|
children?: ColumnProps<D>[];
|
|
128
137
|
formatter?:
|
|
@@ -160,7 +169,7 @@ export interface ToolbarConfig {
|
|
|
160
169
|
disabled?: boolean;
|
|
161
170
|
}
|
|
162
171
|
|
|
163
|
-
export interface ResponsePathConfig<D = Recordable> {
|
|
172
|
+
export interface ResponsePathConfig<D extends Recordable = Recordable> {
|
|
164
173
|
/*非分页取值路径*/
|
|
165
174
|
list?: string | ((res: Recordable) => D[]);
|
|
166
175
|
/*分页取值路径*/
|
|
@@ -174,12 +183,12 @@ export interface ResponsePathConfig<D = Recordable> {
|
|
|
174
183
|
|
|
175
184
|
export type HandlerMultiDel = (ids: Array<string | number>) => any;
|
|
176
185
|
|
|
177
|
-
export interface AjaxConfig<F = Recordable> {
|
|
186
|
+
export interface AjaxConfig<F extends Recordable = Recordable> {
|
|
178
187
|
query: (Q: { page?: IPage; form: Partial<F> }) => Promise<Recordable>;
|
|
179
188
|
multiDelete?: HandlerMultiDel;
|
|
180
189
|
}
|
|
181
190
|
|
|
182
|
-
export interface ProxyConfig<D = Recordable, F = Recordable> {
|
|
191
|
+
export interface ProxyConfig<D extends Recordable = Recordable, F extends Recordable = Recordable> {
|
|
183
192
|
// 结果集 取值路径
|
|
184
193
|
response?: ResponsePathConfig<D>;
|
|
185
194
|
ajax: AjaxConfig<F>;
|
|
@@ -188,15 +197,17 @@ export interface ProxyConfig<D = Recordable, F = Recordable> {
|
|
|
188
197
|
export interface PageConfig {
|
|
189
198
|
pageSizes?: number[];
|
|
190
199
|
pageSize?: number;
|
|
200
|
+
showSizeChanger?: boolean;
|
|
201
|
+
showQuickJumper?: boolean;
|
|
191
202
|
}
|
|
192
203
|
|
|
193
|
-
export interface SelectConfig<D = Recordable> {
|
|
204
|
+
export interface SelectConfig<D extends Recordable = Recordable> {
|
|
194
205
|
multiple?: boolean;
|
|
195
206
|
showCount?: boolean;
|
|
196
207
|
getCheckboxProps?: (record: D) => { disabled?: boolean };
|
|
197
208
|
}
|
|
198
209
|
|
|
199
|
-
export type PGridProps<D = Recordable, F = Recordable> = {
|
|
210
|
+
export type PGridProps<D extends Recordable = Recordable, F extends Recordable = Recordable> = {
|
|
200
211
|
selectConfig?: SelectConfig<D>;
|
|
201
212
|
rowKey?: string;
|
|
202
213
|
manualFetch?: boolean;
|
|
@@ -262,20 +273,65 @@ export interface RenderOptions {
|
|
|
262
273
|
handleDelayTrigger?: (cusFields?: string | string[], time?: number) => void;
|
|
263
274
|
}
|
|
264
275
|
|
|
265
|
-
export interface RenderFormParams<F = Recordable> {
|
|
276
|
+
export interface RenderFormParams<F extends Recordable = Recordable> {
|
|
266
277
|
data: F;
|
|
267
278
|
field?: string;
|
|
268
279
|
}
|
|
269
280
|
|
|
270
|
-
export interface RenderTableParams<D = Recordable> {
|
|
281
|
+
export interface RenderTableParams<D extends Recordable = Recordable> {
|
|
271
282
|
data?: D[];
|
|
272
283
|
row: D;
|
|
273
284
|
rowIndex?: number;
|
|
274
285
|
field?: string;
|
|
275
286
|
title?: string;
|
|
276
287
|
}
|
|
277
|
-
|
|
278
|
-
|
|
288
|
+
export interface CanvasColumnProps<T extends Recordable = Recordable>
|
|
289
|
+
extends Omit<EVirtColumn, 'children' | 'formatter' | 'key'> {
|
|
290
|
+
key?: string;
|
|
291
|
+
field?: string;
|
|
292
|
+
children?: CanvasColumnProps<T>[];
|
|
293
|
+
formatter?:
|
|
294
|
+
| string
|
|
295
|
+
| [string, ...Array<any>]
|
|
296
|
+
| ((arg: PartialByKeys<CellFuncArg<T>, 'cellValue'>) => any);
|
|
297
|
+
slots?: {
|
|
298
|
+
default?: ({
|
|
299
|
+
row,
|
|
300
|
+
column,
|
|
301
|
+
rowIndex,
|
|
302
|
+
}: {
|
|
303
|
+
row: T;
|
|
304
|
+
column: CanvasColumnProps<T>;
|
|
305
|
+
rowIndex: number;
|
|
306
|
+
}) => any;
|
|
307
|
+
edit?: ({
|
|
308
|
+
row,
|
|
309
|
+
column,
|
|
310
|
+
rowIndex,
|
|
311
|
+
}: {
|
|
312
|
+
row: T;
|
|
313
|
+
column: CanvasColumnProps<T>;
|
|
314
|
+
rowIndex: number;
|
|
315
|
+
}) => any;
|
|
316
|
+
title?: ({ column }: { column: CanvasColumnProps<T> }) => any;
|
|
317
|
+
};
|
|
318
|
+
cellRender?: CellRender;
|
|
319
|
+
editRender?: CellRender;
|
|
320
|
+
}
|
|
321
|
+
export interface CanvasTableProps<
|
|
322
|
+
T extends Recordable = Recordable,
|
|
323
|
+
B extends Recordable = Recordable,
|
|
324
|
+
> {
|
|
325
|
+
columns: CanvasColumnProps<T>[];
|
|
326
|
+
data: T[];
|
|
327
|
+
config: ConfigType;
|
|
328
|
+
footerData?: B[];
|
|
329
|
+
loading?: boolean;
|
|
330
|
+
}
|
|
331
|
+
export interface PGridInstance<
|
|
332
|
+
D extends Recordable = Recordable,
|
|
333
|
+
F extends Recordable = Recordable,
|
|
334
|
+
> {
|
|
279
335
|
commitProxy: {
|
|
280
336
|
query: () => Promise<D[]>;
|
|
281
337
|
reload: () => Promise<D[]>;
|
|
@@ -297,7 +353,7 @@ export interface PFormInstance {
|
|
|
297
353
|
$form: Recordable;
|
|
298
354
|
}
|
|
299
355
|
|
|
300
|
-
export interface PromisePickerInstance<D = Recordable> {
|
|
356
|
+
export interface PromisePickerInstance<D extends Recordable = Recordable> {
|
|
301
357
|
pick: () => Promise<{ row: D; field?: string }>;
|
|
302
358
|
pickMultiple: () => Promise<D[]>;
|
|
303
359
|
grid: PGridInstance<D>;
|
package/src/index.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { App } from 'vue';
|
|
2
2
|
import PForm from '@/components/PForm.vue';
|
|
3
3
|
import PGrid from '@/components/PGrid.vue';
|
|
4
|
+
import PCanvasTable from '@/components/PCanvasTable.vue';
|
|
5
|
+
import PCanvasGrid from '@/components/PCanvasGrid.vue';
|
|
4
6
|
import PFormGroup from '@/components/PFormGroup.vue';
|
|
5
7
|
import PGroupBlock from '@/components/PGroupBlock.vue';
|
|
6
8
|
import PromisePicker from '@/components/PromisePicker.vue';
|
|
@@ -19,7 +21,8 @@ export default {
|
|
|
19
21
|
install(app: App) {
|
|
20
22
|
app.component('PForm', PForm);
|
|
21
23
|
app.component('PGrid', PGrid);
|
|
22
|
-
|
|
24
|
+
app.component('PCanvasTable', PCanvasTable);
|
|
25
|
+
app.component('PCanvasGrid', PCanvasGrid);
|
|
23
26
|
app.component('PFormGroup', PFormGroup);
|
|
24
27
|
app.component('PGroupBlock', PGroupBlock);
|
|
25
28
|
app.component('PromisePicker', PromisePicker);
|
|
@@ -37,4 +40,14 @@ export * from '@/utils/core';
|
|
|
37
40
|
export { setup, setUIKitConfig, getUIKitConfig, resetUIKitConfig, type UIKitConfig };
|
|
38
41
|
|
|
39
42
|
// 直接导出组件,使用户可以直接导入使用
|
|
40
|
-
export {
|
|
43
|
+
export {
|
|
44
|
+
PForm,
|
|
45
|
+
PGrid,
|
|
46
|
+
PCanvasTable,
|
|
47
|
+
PCanvasGrid,
|
|
48
|
+
PFormGroup,
|
|
49
|
+
PGroupBlock,
|
|
50
|
+
PromisePicker,
|
|
51
|
+
addFormatter,
|
|
52
|
+
addRender,
|
|
53
|
+
};
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
<script
|
|
2
|
+
lang="ts"
|
|
3
|
+
setup
|
|
4
|
+
generic="T extends Recordable = Recordable, B extends Recordable = Recordable"
|
|
5
|
+
>
|
|
6
|
+
import Cell from 'e-virt-table/dist/lib/Cell';
|
|
7
|
+
import type CellType from 'e-virt-table/dist/lib/Cell';
|
|
8
|
+
import EVirtTable from 'e-virt-table';
|
|
9
|
+
import type {
|
|
10
|
+
Column as EVirtColumn,
|
|
11
|
+
CellParams,
|
|
12
|
+
OverlayerContainer,
|
|
13
|
+
FormatterMethod,
|
|
14
|
+
} from 'e-virt-table';
|
|
15
|
+
import { ref, onMounted, computed, useAttrs, watch } from 'vue';
|
|
16
|
+
import { EventCallback } from 'e-virt-table/dist/lib/EventBus';
|
|
17
|
+
import { isArray, isEqual, isFunction, isString, omit } from 'xe-utils';
|
|
18
|
+
import renderStore from '@/store/renderStore';
|
|
19
|
+
import RenderEditCell from './RenderEditCell';
|
|
20
|
+
import type { CanvasColumnProps, CanvasTableProps, FormatterFunc, CellRender } from '#/antProxy';
|
|
21
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
22
|
+
import { antFormatters } from '@/utils/AFormatters';
|
|
23
|
+
|
|
24
|
+
const emit = defineEmits<{
|
|
25
|
+
(e: 'change', value: any[]): void; // 需要默认实现change,不能动态绑定
|
|
26
|
+
(e: 'ready', value: EVirtTable): void;
|
|
27
|
+
}>();
|
|
28
|
+
const defaultConfig = {
|
|
29
|
+
DISABLED: true,
|
|
30
|
+
};
|
|
31
|
+
const props = defineProps<CanvasTableProps<T, B>>();
|
|
32
|
+
let eVirtTable: EVirtTable | null = null;
|
|
33
|
+
const attrs = useAttrs();
|
|
34
|
+
const eVirtTableRef = ref(null);
|
|
35
|
+
const eVirtTableEditorRef = ref(null);
|
|
36
|
+
const eVirtTableEmptyRef = ref(null);
|
|
37
|
+
const eVirtTableOverlayerRef = ref(null);
|
|
38
|
+
const editorCell = ref<Cell>();
|
|
39
|
+
const editorType = ref<string>('text');
|
|
40
|
+
const overlayerView = ref<OverlayerContainer>();
|
|
41
|
+
const cacheEditorSlotColumns: Record<string, CanvasColumnProps<T>> = {};
|
|
42
|
+
const cacheEditorRenders: Record<string, CellRender> = {};
|
|
43
|
+
// 编辑器样式
|
|
44
|
+
const editorStyle = computed(() => {
|
|
45
|
+
const cell = editorCell.value;
|
|
46
|
+
if (!cell) {
|
|
47
|
+
return {};
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
width: `${cell.width}px`,
|
|
51
|
+
height: `${cell.height}px`,
|
|
52
|
+
};
|
|
53
|
+
});
|
|
54
|
+
const getFormatter = (name: string) => antFormatters[name] || (({ cellValue }) => cellValue);
|
|
55
|
+
const getCellRender = (name: string) => renderStore.renders[name]?.renderDefault;
|
|
56
|
+
const transferFormatter =
|
|
57
|
+
(formatter: FormatterFunc, ...restArgs: any[]): FormatterMethod =>
|
|
58
|
+
({ row, rowIndex, value }) =>
|
|
59
|
+
formatter(
|
|
60
|
+
{
|
|
61
|
+
row,
|
|
62
|
+
rowIndex,
|
|
63
|
+
cellValue: value,
|
|
64
|
+
},
|
|
65
|
+
...restArgs,
|
|
66
|
+
);
|
|
67
|
+
// 将复杂的三元运算符拆分成函数
|
|
68
|
+
const getRenderFunction = (column: CanvasColumnProps<T>) => {
|
|
69
|
+
if (column.slots?.default && isFunction(column.slots?.default)) {
|
|
70
|
+
return (cell: CellParams) =>
|
|
71
|
+
column.slots?.default?.({
|
|
72
|
+
row: cell.row,
|
|
73
|
+
column: column,
|
|
74
|
+
rowIndex: cell.rowIndex,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (column.slots?.default && isString(column.slots?.default)) {
|
|
79
|
+
return `slot:${column.slots?.default}`;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (column.cellRender && column.cellRender.name) {
|
|
83
|
+
return (cell: CellParams) =>
|
|
84
|
+
getCellRender(column.cellRender!.name)?.(
|
|
85
|
+
column.cellRender!,
|
|
86
|
+
{
|
|
87
|
+
data: props.data,
|
|
88
|
+
row: cell.row,
|
|
89
|
+
rowIndex: cell.rowIndex,
|
|
90
|
+
field: column.field || cell.column.key,
|
|
91
|
+
title: cell.column?.title ?? '',
|
|
92
|
+
},
|
|
93
|
+
{},
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return undefined;
|
|
98
|
+
};
|
|
99
|
+
const parseToEVirtColumn = (column: CanvasColumnProps<T>): EVirtColumn => {
|
|
100
|
+
if (column.slots?.edit && (column.field || column.key) && isFunction(column.slots?.edit)) {
|
|
101
|
+
cacheEditorSlotColumns[`__slot:${column.field || column.key}`] = column;
|
|
102
|
+
} else if (column.editRender?.name && (column.field || column.key)) {
|
|
103
|
+
cacheEditorRenders[column.field! || column.key!] = column.editRender;
|
|
104
|
+
}
|
|
105
|
+
return {
|
|
106
|
+
...omit(column, ['formatter']),
|
|
107
|
+
key: column.key || column.field || uuidv4(),
|
|
108
|
+
formatter: isString(column.formatter)
|
|
109
|
+
? transferFormatter(getFormatter(column.formatter as string))
|
|
110
|
+
: isArray(column.formatter) && isString(column.formatter[0])
|
|
111
|
+
? transferFormatter(getFormatter(column.formatter[0]), ...column.formatter.slice(1))
|
|
112
|
+
: isFunction(column.formatter)
|
|
113
|
+
? transferFormatter(column.formatter as FormatterFunc)
|
|
114
|
+
: undefined,
|
|
115
|
+
editorType:
|
|
116
|
+
column.editorType ??
|
|
117
|
+
(column.slots?.edit && (column.field || column.key) && isFunction(column.slots?.edit)
|
|
118
|
+
? `__slot:${column.field || column.key}`
|
|
119
|
+
: column.editRender?.name
|
|
120
|
+
? column.editRender.name
|
|
121
|
+
: undefined),
|
|
122
|
+
render: getRenderFunction(column),
|
|
123
|
+
children: column.children?.map((child) => parseToEVirtColumn(child)),
|
|
124
|
+
};
|
|
125
|
+
};
|
|
126
|
+
onMounted(() => {
|
|
127
|
+
if (!eVirtTableRef.value) {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
eVirtTable = new EVirtTable(eVirtTableRef.value, {
|
|
131
|
+
config: {
|
|
132
|
+
...defaultConfig,
|
|
133
|
+
...props.config,
|
|
134
|
+
},
|
|
135
|
+
columns: props.columns.map((col) => parseToEVirtColumn(col)),
|
|
136
|
+
data: props.data,
|
|
137
|
+
emptyElement: eVirtTableEmptyRef.value || undefined,
|
|
138
|
+
overlayerElement: eVirtTableOverlayerRef.value || undefined,
|
|
139
|
+
editorElement: eVirtTableEditorRef.value || undefined,
|
|
140
|
+
});
|
|
141
|
+
// 动态绑定事件
|
|
142
|
+
Object.keys(attrs).forEach((key) => {
|
|
143
|
+
const func = attrs[key];
|
|
144
|
+
if (typeof func === 'function' && key.startsWith('on')) {
|
|
145
|
+
const _eventName = key.charAt(2).toLowerCase() + key.slice(3); // 去掉 'on' 前缀 只将 'on' 后第一个字母转换为小写
|
|
146
|
+
eVirtTable?.on(_eventName, func as EventCallback);
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
eVirtTable.on('change', (value) => {
|
|
150
|
+
emit('change', value);
|
|
151
|
+
});
|
|
152
|
+
eVirtTable.on('overlayerChange', (overlayer: OverlayerContainer) => {
|
|
153
|
+
overlayerView.value = overlayer;
|
|
154
|
+
});
|
|
155
|
+
eVirtTable.on('startEdit', (cell) => {
|
|
156
|
+
editorCell.value = cell;
|
|
157
|
+
editorType.value = cell.editorType;
|
|
158
|
+
// 内部已经处理了文本类型的编辑
|
|
159
|
+
if (editorType.value === 'text') {
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
eVirtTable.on('doneEdit', () => {
|
|
164
|
+
editorType.value = 'text';
|
|
165
|
+
});
|
|
166
|
+
emit('ready', eVirtTable);
|
|
167
|
+
});
|
|
168
|
+
function saveCellValue(value) {
|
|
169
|
+
if (!eVirtTable || !editorCell.value) {
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
const { rowKey, key } = editorCell.value;
|
|
173
|
+
eVirtTable?.setItemValueByEditor(rowKey, key, value);
|
|
174
|
+
}
|
|
175
|
+
watch(
|
|
176
|
+
props.data,
|
|
177
|
+
(newValue) => {
|
|
178
|
+
eVirtTable?.loadData(newValue);
|
|
179
|
+
},
|
|
180
|
+
{ deep: true },
|
|
181
|
+
);
|
|
182
|
+
watch(
|
|
183
|
+
() => props.columns,
|
|
184
|
+
(newValue, oldValue) => {
|
|
185
|
+
if (!isEqual(newValue, oldValue)) {
|
|
186
|
+
eVirtTable?.loadColumns(newValue.map((col) => parseToEVirtColumn(col)));
|
|
187
|
+
}
|
|
188
|
+
},
|
|
189
|
+
{ deep: true },
|
|
190
|
+
);
|
|
191
|
+
watch(
|
|
192
|
+
() => props.config,
|
|
193
|
+
(newValue) => {
|
|
194
|
+
eVirtTable?.loadConfig(newValue);
|
|
195
|
+
},
|
|
196
|
+
{ deep: true },
|
|
197
|
+
);
|
|
198
|
+
watch(
|
|
199
|
+
() => props.footerData,
|
|
200
|
+
(newValue) => {
|
|
201
|
+
eVirtTable?.loadFooterData(newValue || []);
|
|
202
|
+
},
|
|
203
|
+
{ deep: true },
|
|
204
|
+
);
|
|
205
|
+
const getPopupContainer = () => {
|
|
206
|
+
return document.body;
|
|
207
|
+
};
|
|
208
|
+
</script>
|
|
209
|
+
<template>
|
|
210
|
+
<a-spin :spinning="loading">
|
|
211
|
+
<div ref="eVirtTableRef">
|
|
212
|
+
<div ref="eVirtTableEditorRef">
|
|
213
|
+
<!-- 插槽编辑器 -->
|
|
214
|
+
<component
|
|
215
|
+
v-if="editorType.startsWith('__slot:')"
|
|
216
|
+
:is="
|
|
217
|
+
cacheEditorSlotColumns[editorType]!.slots!.edit!({
|
|
218
|
+
row: editorCell!.row,
|
|
219
|
+
column: cacheEditorSlotColumns[editorType],
|
|
220
|
+
rowIndex: editorCell!.rowIndex,
|
|
221
|
+
})
|
|
222
|
+
"
|
|
223
|
+
:bordered="false"
|
|
224
|
+
:style="editorStyle"
|
|
225
|
+
class="ev-editor-wrapper"
|
|
226
|
+
:get-popup-container="getPopupContainer"
|
|
227
|
+
v-model:value="editorCell!.value"
|
|
228
|
+
:cell="editorCell"
|
|
229
|
+
@blur="saveCellValue"
|
|
230
|
+
>
|
|
231
|
+
</component>
|
|
232
|
+
<!-- 自定义编辑器 -->
|
|
233
|
+
<render-edit-cell
|
|
234
|
+
v-else-if="renderStore.renders[editorType]?.renderEdit"
|
|
235
|
+
:cell-render="cacheEditorRenders[editorCell!.key]"
|
|
236
|
+
class="ev-editor-wrapper"
|
|
237
|
+
:style="editorStyle"
|
|
238
|
+
:render-table-params="{
|
|
239
|
+
data: props.data,
|
|
240
|
+
row: editorCell?.row,
|
|
241
|
+
rowIndex: editorCell?.rowIndex ?? -1,
|
|
242
|
+
field: editorCell?.key ?? '',
|
|
243
|
+
title: editorCell?.column?.title ?? '',
|
|
244
|
+
}"
|
|
245
|
+
:bordered="false"
|
|
246
|
+
:get-popup-container="getPopupContainer"
|
|
247
|
+
@blur="saveCellValue"
|
|
248
|
+
/>
|
|
249
|
+
</div>
|
|
250
|
+
<div ref="eVirtTableEmptyRef">
|
|
251
|
+
<slot name="empty">
|
|
252
|
+
<!-- 自定义空数据 -->
|
|
253
|
+
<a-empty description="空数据" />
|
|
254
|
+
</slot>
|
|
255
|
+
</div>
|
|
256
|
+
<div ref="eVirtTableOverlayerRef">
|
|
257
|
+
<!-- 自定覆盖层 -->
|
|
258
|
+
<div
|
|
259
|
+
:class="wrapper.class"
|
|
260
|
+
v-for="wrapper in overlayerView?.views || []"
|
|
261
|
+
:style="wrapper.style"
|
|
262
|
+
:key="wrapper.type"
|
|
263
|
+
>
|
|
264
|
+
<div :style="view.style" v-for="view in wrapper.views" :key="view.key">
|
|
265
|
+
<div
|
|
266
|
+
class="cell"
|
|
267
|
+
v-for="cell in view.cells"
|
|
268
|
+
:key="`${cell.rowKey}_${cell.key}`"
|
|
269
|
+
:style="cell.style"
|
|
270
|
+
>
|
|
271
|
+
<component
|
|
272
|
+
v-if="typeof cell.render === 'function'"
|
|
273
|
+
:is="cell.render(cell)"
|
|
274
|
+
></component>
|
|
275
|
+
<template
|
|
276
|
+
v-else-if="typeof cell.render === 'string' && cell.render.startsWith('slot:')"
|
|
277
|
+
>
|
|
278
|
+
<slot :name="cell.render.replace('slot:', '')" v-bind="cell" :cell="cell"></slot>
|
|
279
|
+
</template>
|
|
280
|
+
</div>
|
|
281
|
+
</div>
|
|
282
|
+
</div>
|
|
283
|
+
</div>
|
|
284
|
+
</div>
|
|
285
|
+
</a-spin>
|
|
286
|
+
</template>
|