@vue-ui-kit/ant 1.9.4 → 2.0.1

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 (38) hide show
  1. package/dist/cjs/index.js +4 -1
  2. package/dist/declarations/antProxy.d.ts +55 -20
  3. package/dist/es/index.js +8888 -2987
  4. package/dist/index.d.ts +5 -6
  5. package/dist/packages/components/PCanvasGrid.vue.d.ts +2 -0
  6. package/dist/packages/components/PCanvasTable.vue.d.ts +136 -0
  7. package/dist/packages/components/PForm.vue.d.ts +8 -14
  8. package/dist/packages/components/PFormCol.vue.d.ts +8 -13
  9. package/dist/packages/components/PFormGroup.vue.d.ts +16 -16
  10. package/dist/packages/components/PGrid.vue.d.ts +7 -27
  11. package/dist/packages/components/PGroupBlock.vue.d.ts +5 -7
  12. package/dist/packages/components/PromisePicker.vue.d.ts +5 -7
  13. package/dist/packages/components/RenderEditCell.d.ts +10 -0
  14. package/dist/packages/renders/TableInput.vue.d.ts +7 -26
  15. package/dist/packages/store/renderStore.d.ts +10 -58
  16. package/dist/packages/utils/AFormatters.d.ts +3 -13
  17. package/dist/packages/utils/treeHelper.d.ts +7 -7
  18. package/dist/style.scss +58 -30
  19. package/package.json +2 -1
  20. package/src/declarations/antProxy.ts +75 -22
  21. package/src/index.ts +15 -2
  22. package/src/packages/components/PCanvasGrid.vue +6 -0
  23. package/src/packages/components/PCanvasTable.vue +292 -0
  24. package/src/packages/components/PForm.vue +5 -5
  25. package/src/packages/components/PFormGroup.vue +1 -1
  26. package/src/packages/components/PGrid.vue +10 -5
  27. package/src/packages/components/PGroupBlock.vue +1 -1
  28. package/src/packages/components/PromisePicker.vue +6 -1
  29. package/src/packages/components/RenderAntCell.tsx +2 -2
  30. package/src/packages/components/RenderAntItem.tsx +2 -2
  31. package/src/packages/components/RenderDefaultSlots.tsx +1 -1
  32. package/src/packages/components/RenderEditCell.tsx +36 -0
  33. package/src/packages/components/RenderItemSlots.tsx +1 -1
  34. package/src/packages/components/RenderTitleSlots.tsx +1 -1
  35. package/src/packages/renders/TableInput.vue +1 -1
  36. package/src/packages/store/renderStore.tsx +44 -18
  37. package/src/packages/styles/index.scss +59 -31
  38. package/src/packages/utils/AFormatters.ts +3 -3
package/dist/style.scss CHANGED
@@ -104,9 +104,9 @@
104
104
  z-index: 4;
105
105
  }
106
106
  .p-error-hang-out {
107
- .ant-input-affix-wrapper-status-error:not(
108
- .ant-input-affix-wrapper-disabled
109
- ):not(.ant-input-affix-wrapper-borderless).ant-input-affix-wrapper {
107
+ .ant-input-affix-wrapper-status-error:not(.ant-input-affix-wrapper-disabled):not(
108
+ .ant-input-affix-wrapper-borderless
109
+ ).ant-input-affix-wrapper {
110
110
  border-color: #d9d9d9 !important;
111
111
 
112
112
  &:focus {
@@ -126,7 +126,9 @@
126
126
  transform: translateY(-10px);
127
127
  max-height: 0;
128
128
  overflow: hidden;
129
- transition: opacity 0.3s ease-out 0.3s, transform 0.3s ease-out 0.3s,
129
+ transition:
130
+ opacity 0.3s ease-out 0.3s,
131
+ transform 0.3s ease-out 0.3s,
130
132
  max-height 0.3s ease-out 0.3s;
131
133
  }
132
134
  .ant-form-item-has-error .ant-form-item-explain-error {
@@ -238,25 +240,25 @@
238
240
  }
239
241
  }
240
242
  }
241
- .p-error-group-tab{
242
- position:relative;
243
+ .p-error-group-tab {
244
+ position: relative;
243
245
  overflow: visible;
244
- color:#f5222d!important;
245
- &:after{
246
- content:'🏷️';
247
- position:absolute;
248
- top:-1em;
249
- right:0;
250
- width:1em;
251
- height:1em;
252
- font-size:0.8em;
246
+ color: #f5222d !important;
247
+ &:after {
248
+ content: '🏷️';
249
+ position: absolute;
250
+ top: -1em;
251
+ right: 0;
252
+ width: 1em;
253
+ height: 1em;
254
+ font-size: 0.8em;
253
255
  animation: heartbeat 2s infinite;
254
256
  }
255
257
  }
256
258
  .p-error-hang-out {
257
- .ant-input-affix-wrapper-status-error:not(
258
- .ant-input-affix-wrapper-disabled
259
- ):not(.ant-input-affix-wrapper-borderless).ant-input-affix-wrapper {
259
+ .ant-input-affix-wrapper-status-error:not(.ant-input-affix-wrapper-disabled):not(
260
+ .ant-input-affix-wrapper-borderless
261
+ ).ant-input-affix-wrapper {
260
262
  border-color: #d9d9d9 !important;
261
263
 
262
264
  &:focus {
@@ -276,6 +278,10 @@
276
278
  }
277
279
  //endregion
278
280
 
281
+ /* #region EVirtTable */
282
+
283
+ /* #endregion */
284
+
279
285
  @each $align in right center {
280
286
  /**/
281
287
  .p-content-align-#{$align}.ant-form-item .ant-form-item-control-input-content {
@@ -291,15 +297,37 @@
291
297
  }
292
298
 
293
299
  @keyframes heartbeat {
294
- 0% { transform: scale(1); }
295
- 6% { transform: scale(1.22); }
296
- 12% { transform: scale(1); }
297
- 18% { transform: scale(1.18); }
298
- 24% { transform: scale(1); }
299
- 48% { transform: scale(1); } // 长停顿
300
- 54% { transform: scale(1.22); }
301
- 60% { transform: scale(1); }
302
- 66% { transform: scale(1.18); }
303
- 72% { transform: scale(1); }
304
- 100% { transform: scale(1); } // 长停顿
305
- }
300
+ 0% {
301
+ transform: scale(1);
302
+ }
303
+ 6% {
304
+ transform: scale(1.22);
305
+ }
306
+ 12% {
307
+ transform: scale(1);
308
+ }
309
+ 18% {
310
+ transform: scale(1.18);
311
+ }
312
+ 24% {
313
+ transform: scale(1);
314
+ }
315
+ 48% {
316
+ transform: scale(1);
317
+ } // 长停顿
318
+ 54% {
319
+ transform: scale(1.22);
320
+ }
321
+ 60% {
322
+ transform: scale(1);
323
+ }
324
+ 66% {
325
+ transform: scale(1.18);
326
+ }
327
+ 72% {
328
+ transform: scale(1);
329
+ }
330
+ 100% {
331
+ transform: scale(1);
332
+ } // 长停顿
333
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vue-ui-kit/ant",
3
- "version": "1.9.4",
3
+ "version": "2.0.1",
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: ColumnProps<D>;
11
+ column?: ColumnProps<D>;
11
12
  rowIndex: number;
12
13
  cellValue: any;
13
14
  }
14
-
15
- export interface ItemFuncArg<F = Recordable> {
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,17 +74,20 @@ 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<D = Recordable, F = Recordable> {
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;
@@ -91,7 +96,7 @@ export interface PromisePickerProps<D = Recordable, F = Recordable> {
91
96
  beforePick?: (rowOrRows: D | Array<D>) => Promise<void>;
92
97
  }
93
98
 
94
- export type GroupMenuItemHandler<F = Recordable> = ({
99
+ export type GroupMenuItemHandler<F extends Recordable = Recordable> = ({
95
100
  index,
96
101
  data,
97
102
  code,
@@ -101,14 +106,14 @@ export type GroupMenuItemHandler<F = Recordable> = ({
101
106
  data: Partial<F & { __index: number }>;
102
107
  }) => void;
103
108
 
104
- export interface GroupMenuItem<F = Recordable> {
109
+ export interface GroupMenuItem<F extends Recordable = Recordable> {
105
110
  content: string;
106
111
  icon?: string;
107
112
  code: string;
108
113
  visibleMethod?: ({ data, index }: { data: Partial<F>; index: number }) => boolean;
109
114
  }
110
115
 
111
- export interface PFormGroupProps<F = Recordable> {
116
+ export interface PFormGroupProps<F extends Recordable = Recordable> {
112
117
  getFormSetting: (data: Partial<F>) => PFormProps<Partial<F>>;
113
118
  title?: string;
114
119
  tabLabel?: string;
@@ -125,7 +130,8 @@ export interface PFormGroupProps<F = Recordable> {
125
130
  menuHandler?: GroupMenuItemHandler<F>;
126
131
  }
127
132
 
128
- export interface ColumnProps<D = Recordable> extends Omit<TableColumnType, 'slots'> {
133
+ export interface ColumnProps<D extends Recordable = Recordable>
134
+ extends Omit<TableColumnType, 'slots'> {
129
135
  field?: string;
130
136
  children?: ColumnProps<D>[];
131
137
  formatter?:
@@ -163,7 +169,7 @@ export interface ToolbarConfig {
163
169
  disabled?: boolean;
164
170
  }
165
171
 
166
- export interface ResponsePathConfig<D = Recordable> {
172
+ export interface ResponsePathConfig<D extends Recordable = Recordable> {
167
173
  /*非分页取值路径*/
168
174
  list?: string | ((res: Recordable) => D[]);
169
175
  /*分页取值路径*/
@@ -177,12 +183,12 @@ export interface ResponsePathConfig<D = Recordable> {
177
183
 
178
184
  export type HandlerMultiDel = (ids: Array<string | number>) => any;
179
185
 
180
- export interface AjaxConfig<F = Recordable> {
186
+ export interface AjaxConfig<F extends Recordable = Recordable> {
181
187
  query: (Q: { page?: IPage; form: Partial<F> }) => Promise<Recordable>;
182
188
  multiDelete?: HandlerMultiDel;
183
189
  }
184
190
 
185
- export interface ProxyConfig<D = Recordable, F = Recordable> {
191
+ export interface ProxyConfig<D extends Recordable = Recordable, F extends Recordable = Recordable> {
186
192
  // 结果集 取值路径
187
193
  response?: ResponsePathConfig<D>;
188
194
  ajax: AjaxConfig<F>;
@@ -191,15 +197,17 @@ export interface ProxyConfig<D = Recordable, F = Recordable> {
191
197
  export interface PageConfig {
192
198
  pageSizes?: number[];
193
199
  pageSize?: number;
200
+ showSizeChanger?: boolean;
201
+ showQuickJumper?: boolean;
194
202
  }
195
203
 
196
- export interface SelectConfig<D = Recordable> {
204
+ export interface SelectConfig<D extends Recordable = Recordable> {
197
205
  multiple?: boolean;
198
206
  showCount?: boolean;
199
207
  getCheckboxProps?: (record: D) => { disabled?: boolean };
200
208
  }
201
209
 
202
- export type PGridProps<D = Recordable, F = Recordable> = {
210
+ export type PGridProps<D extends Recordable = Recordable, F extends Recordable = Recordable> = {
203
211
  selectConfig?: SelectConfig<D>;
204
212
  rowKey?: string;
205
213
  manualFetch?: boolean;
@@ -265,20 +273,65 @@ export interface RenderOptions {
265
273
  handleDelayTrigger?: (cusFields?: string | string[], time?: number) => void;
266
274
  }
267
275
 
268
- export interface RenderFormParams<F = Recordable> {
276
+ export interface RenderFormParams<F extends Recordable = Recordable> {
269
277
  data: F;
270
278
  field?: string;
271
279
  }
272
280
 
273
- export interface RenderTableParams<D = Recordable> {
281
+ export interface RenderTableParams<D extends Recordable = Recordable> {
274
282
  data?: D[];
275
283
  row: D;
276
284
  rowIndex?: number;
277
285
  field?: string;
278
286
  title?: string;
279
287
  }
280
-
281
- export interface PGridInstance<D = Recordable, F = Recordable> {
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
+ > {
282
335
  commitProxy: {
283
336
  query: () => Promise<D[]>;
284
337
  reload: () => Promise<D[]>;
@@ -300,7 +353,7 @@ export interface PFormInstance {
300
353
  $form: Recordable;
301
354
  }
302
355
 
303
- export interface PromisePickerInstance<D = Recordable> {
356
+ export interface PromisePickerInstance<D extends Recordable = Recordable> {
304
357
  pick: () => Promise<{ row: D; field?: string }>;
305
358
  pickMultiple: () => Promise<D[]>;
306
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
- // @ts-ignore
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 { PForm, PGrid, PFormGroup, PGroupBlock, PromisePicker, addFormatter, addRender };
43
+ export {
44
+ PForm,
45
+ PGrid,
46
+ PCanvasTable,
47
+ PCanvasGrid,
48
+ PFormGroup,
49
+ PGroupBlock,
50
+ PromisePicker,
51
+ addFormatter,
52
+ addRender,
53
+ };
@@ -0,0 +1,6 @@
1
+ <script lang="ts" setup>
2
+ import PCanvasTable from './PCanvasTable.vue';
3
+ </script>
4
+ <template>
5
+ <div>todo</div>
6
+ </template>
@@ -0,0 +1,292 @@
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
+ eVirtTable.on('selectionChange', (selection) => {
167
+ console.log('selection', selection);
168
+ });
169
+ emit('ready', eVirtTable);
170
+ });
171
+ function saveCellValue(value) {
172
+ if (!eVirtTable || !editorCell.value) {
173
+ return;
174
+ }
175
+ const { rowKey, key } = editorCell.value;
176
+ eVirtTable?.setItemValueByEditor(rowKey, key, value);
177
+ }
178
+ const getPopupContainer = () => {
179
+ return document.body;
180
+ };
181
+ watch(
182
+ props.data,
183
+ (newValue) => {
184
+ eVirtTable?.loadData(newValue);
185
+ },
186
+ { deep: true },
187
+ );
188
+ watch(
189
+ () => props.columns,
190
+ (newValue, oldValue) => {
191
+ if (!isEqual(newValue, oldValue)) {
192
+ eVirtTable?.loadColumns(newValue.map((col) => parseToEVirtColumn(col)));
193
+ }
194
+ },
195
+ { deep: true },
196
+ );
197
+ watch(
198
+ () => props.config,
199
+ (newValue) => {
200
+ eVirtTable?.loadConfig(newValue);
201
+ },
202
+ { deep: true },
203
+ );
204
+ watch(
205
+ () => props.footerData,
206
+ (newValue) => {
207
+ eVirtTable?.loadFooterData(newValue || []);
208
+ },
209
+ { deep: true },
210
+ );
211
+ defineExpose({
212
+ $table: eVirtTable,
213
+ });
214
+ </script>
215
+ <template>
216
+ <a-spin :spinning="loading">
217
+ <div ref="eVirtTableRef">
218
+ <div ref="eVirtTableEditorRef">
219
+ <!-- 插槽编辑器 -->
220
+ <component
221
+ v-if="editorType.startsWith('__slot:')"
222
+ :is="
223
+ cacheEditorSlotColumns[editorType]!.slots!.edit!({
224
+ row: editorCell!.row,
225
+ column: cacheEditorSlotColumns[editorType],
226
+ rowIndex: editorCell!.rowIndex,
227
+ })
228
+ "
229
+ :bordered="false"
230
+ :style="editorStyle"
231
+ class="ev-editor-wrapper"
232
+ :get-popup-container="getPopupContainer"
233
+ v-model:value="editorCell!.value"
234
+ :cell="editorCell"
235
+ @blur="saveCellValue"
236
+ >
237
+ </component>
238
+ <!-- 自定义编辑器 -->
239
+ <render-edit-cell
240
+ v-else-if="renderStore.renders[editorType]?.renderEdit"
241
+ :cell-render="cacheEditorRenders[editorCell!.key]"
242
+ class="ev-editor-wrapper"
243
+ :style="editorStyle"
244
+ :render-table-params="{
245
+ data: props.data,
246
+ row: editorCell?.row,
247
+ rowIndex: editorCell?.rowIndex ?? -1,
248
+ field: editorCell?.key ?? '',
249
+ title: editorCell?.column?.title ?? '',
250
+ }"
251
+ :bordered="false"
252
+ :get-popup-container="getPopupContainer"
253
+ @blur="saveCellValue"
254
+ />
255
+ </div>
256
+ <div ref="eVirtTableEmptyRef">
257
+ <slot name="empty">
258
+ <!-- 自定义空数据 -->
259
+ <a-empty description="空数据" />
260
+ </slot>
261
+ </div>
262
+ <div ref="eVirtTableOverlayerRef">
263
+ <!-- 自定覆盖层 -->
264
+ <div
265
+ :class="wrapper.class"
266
+ v-for="wrapper in overlayerView?.views || []"
267
+ :style="wrapper.style"
268
+ :key="wrapper.type"
269
+ >
270
+ <div :style="view.style" v-for="view in wrapper.views" :key="view.key">
271
+ <div
272
+ class="cell"
273
+ v-for="cell in view.cells"
274
+ :key="`${cell.rowKey}_${cell.key}`"
275
+ :style="cell.style"
276
+ >
277
+ <component
278
+ v-if="typeof cell.render === 'function'"
279
+ :is="cell.render(cell)"
280
+ ></component>
281
+ <template
282
+ v-else-if="typeof cell.render === 'string' && cell.render.startsWith('slot:')"
283
+ >
284
+ <slot :name="cell.render.replace('slot:', '')" v-bind="cell" :cell="cell"></slot>
285
+ </template>
286
+ </div>
287
+ </div>
288
+ </div>
289
+ </div>
290
+ </div>
291
+ </a-spin>
292
+ </template>