@vue-ui-kit/ant 1.4.0 → 1.6.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.
@@ -1,20 +1,42 @@
1
1
  import { PGridProps } from '../../declarations/antProxy';
2
2
  declare const _default: <D = Recordable<any>, F = Recordable<any>>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_Prettify<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_expose?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
3
3
  props: __VLS_Prettify<Pick<Partial<{}> & Omit<{
4
- readonly onReset?: ((...args: any[]) => any) | undefined;
5
- readonly onPick?: ((...args: any[]) => any) | undefined;
6
- readonly onQuery?: ((...args: any[]) => any) | undefined;
7
- readonly "onUpdate:tableData"?: ((...args: any[]) => any) | undefined;
8
- readonly onToolbarButtonClick?: ((...args: any[]) => any) | undefined;
9
- readonly onToolbarToolClick?: ((...args: any[]) => any) | undefined;
4
+ readonly onPick?: ((data: {
5
+ row: D;
6
+ field: string;
7
+ }) => any) | undefined;
8
+ readonly onToolbarButtonClick?: ((data: {
9
+ data: D[];
10
+ code: string;
11
+ selectedKeys: Array<string | number>;
12
+ records: D[];
13
+ }) => any) | undefined;
14
+ readonly onToolbarToolClick?: ((data: {
15
+ data: D[];
16
+ code: string;
17
+ selectedKeys: Array<string | number>;
18
+ records: D[];
19
+ }) => any) | undefined;
20
+ readonly onResetQuery?: (() => any) | undefined;
10
21
  } & import('vue').VNodeProps & import('vue').AllowedComponentProps & import('vue').ComponentCustomProps & Readonly<{}> & Readonly<{
11
- onReset?: ((...args: any[]) => any) | undefined;
12
- onPick?: ((...args: any[]) => any) | undefined;
13
- onQuery?: ((...args: any[]) => any) | undefined;
14
- "onUpdate:tableData"?: ((...args: any[]) => any) | undefined;
15
- onToolbarButtonClick?: ((...args: any[]) => any) | undefined;
16
- onToolbarToolClick?: ((...args: any[]) => any) | undefined;
17
- }>, never>, "onReset" | "onPick" | "onQuery" | "onUpdate:tableData" | "onToolbarButtonClick" | "onToolbarToolClick"> & PGridProps<D, F>> & import('vue').PublicProps;
22
+ onPick?: ((data: {
23
+ row: D;
24
+ field: string;
25
+ }) => any) | undefined;
26
+ onToolbarButtonClick?: ((data: {
27
+ data: D[];
28
+ code: string;
29
+ selectedKeys: Array<string | number>;
30
+ records: D[];
31
+ }) => any) | undefined;
32
+ onToolbarToolClick?: ((data: {
33
+ data: D[];
34
+ code: string;
35
+ selectedKeys: Array<string | number>;
36
+ records: D[];
37
+ }) => any) | undefined;
38
+ onResetQuery?: (() => any) | undefined;
39
+ }>, never>, "onPick" | "onToolbarButtonClick" | "onToolbarToolClick" | "onResetQuery"> & PGridProps<D, F>> & import('vue').PublicProps;
18
40
  expose(exposed: import('vue').ShallowUnwrapRef<{
19
41
  commitProxy: {
20
42
  query: import('lodash').DebouncedFunc<() => Promise<D[]>>;
@@ -23,13 +45,34 @@ declare const _default: <D = Recordable<any>, F = Recordable<any>>(__VLS_props:
23
45
  passQuery: (params: Partial<F>, lazy?: boolean) => Promise<void> | Promise<D[]> | undefined;
24
46
  };
25
47
  $table: import('vue').ComputedRef<any>;
26
- selectedRowKeys: import('vue').ComputedRef<string[] | number[]>;
48
+ selectedRowKeys: import('vue').ComputedRef<(string | number)[]>;
49
+ setBtnLoading: (code: string, value: boolean) => void;
50
+ selectedRecords: import('vue').ComputedRef<D[]>;
27
51
  $form: import('vue').ComputedRef<any>;
28
52
  setLoadings: (value: boolean) => void;
53
+ resizeTable: () => void;
29
54
  }>): void;
30
55
  attrs: any;
31
56
  slots: ReturnType<() => {}>;
32
- emit: ((event: "reset" | "pick" | "query" | "update:tableData" | "toolbarButtonClick" | "toolbarToolClick", ...args: any[]) => void) & {};
57
+ emit: {
58
+ (event: "toolbarButtonClick", data: {
59
+ data: D[];
60
+ code: string;
61
+ selectedKeys: Array<string | number>;
62
+ records: D[];
63
+ }): void;
64
+ (event: "toolbarToolClick", data: {
65
+ data: D[];
66
+ code: string;
67
+ selectedKeys: Array<string | number>;
68
+ records: D[];
69
+ }): void;
70
+ (event: "pick", data: {
71
+ row: D;
72
+ field: string;
73
+ }): void;
74
+ (event: "resetQuery"): void;
75
+ } & {};
33
76
  }>) => import('vue').VNode<import('vue').RendererNode, import('vue').RendererElement, {
34
77
  [key: string]: any;
35
78
  }> & {
@@ -1,2 +1,4 @@
1
1
  export declare const noValue: (val: any) => boolean;
2
2
  export declare const valued: (val: any) => boolean;
3
+ export declare const isBadValue: (val: any) => boolean;
4
+ export declare const isGoodValue: (val: any) => boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vue-ui-kit/ant",
3
- "version": "1.4.0",
3
+ "version": "1.6.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",
@@ -58,6 +58,7 @@ export interface PFormItemProps<F = Recordable> {
58
58
  itemRender?: ItemRender;
59
59
  tooltipConfig?: TooltipConfig;
60
60
  slots?: {
61
+ title?: () => any;
61
62
  default?: (
62
63
  { data, field }: ItemFuncArg<F>,
63
64
  passTrigger?: (cusFields?: string | string[]) => void,
@@ -138,7 +139,8 @@ export interface ToolbarButtonProps extends PButtonProps {
138
139
 
139
140
  export interface ToolbarConfig {
140
141
  buttons?: Array<ToolbarButtonProps>;
141
- tools?: Array<{ code: string; icon: string; type?: ButtonType }>;
142
+ tools?: Array<{ code: string; icon: string; type?: ButtonType; disabled?: boolean }>;
143
+ disabled?: boolean;
142
144
  }
143
145
 
144
146
  export interface ResponsePathConfig<D = Recordable> {
@@ -153,7 +155,7 @@ export interface ResponsePathConfig<D = Recordable> {
153
155
  | ((res: Recordable) => string | { status: string; content: string; icon?: string });
154
156
  }
155
157
 
156
- declare type HandlerMulti = (ids: string[] | number[]) => any;
158
+ declare type HandlerMulti = (ids: Array<string | number>) => any;
157
159
 
158
160
  export interface AjaxConfig<F = Recordable> {
159
161
  query: (Q: { page?: IPage; form: Partial<F> }) => Promise<Recordable>;
@@ -257,6 +259,8 @@ export interface PGridInstance<D = Recordable, F = Recordable> {
257
259
  $table: Recordable;
258
260
  $form: Recordable;
259
261
  setLoadings: (value: boolean) => void;
262
+ setBtnLoading: (code: string, status: boolean) => void;
263
+ resizeTable: () => void;
260
264
  }
261
265
 
262
266
  export interface PFormInstance {
@@ -5,7 +5,7 @@
5
5
  import { v4 as uuid_v4 } from 'uuid';
6
6
  import RenderAntItem from '@/components/RenderAntItem';
7
7
  import RenderItemSlots from '@/components/RenderItemSlots';
8
- import { valued } from '@/utils/is';
8
+ import { isGoodValue, valued } from '@/utils/is';
9
9
  import { eachTree } from '@/utils/treeHelper';
10
10
  import { defaultItemResponsive } from '@/utils/core';
11
11
  import {
@@ -39,7 +39,7 @@
39
39
  const obj: Partial<F> = {};
40
40
  eachTree(items.value, (item) => {
41
41
  if (item.field && item.itemRender) {
42
- if (valued(item.itemRender.defaultValue)) {
42
+ if (isGoodValue(item.itemRender.defaultValue)) {
43
43
  obj[item.field] = item.itemRender.defaultValue;
44
44
  } else {
45
45
  obj[item.field] = undefined;
@@ -103,6 +103,9 @@
103
103
  ])
104
104
  "
105
105
  >
106
+ <template v-if="item.slots?.title" #label>
107
+ <component :is="item.slots.title" />
108
+ </template>
106
109
  <render-item-slots
107
110
  v-if="item.slots?.default"
108
111
  :form-data="formData"
@@ -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 { computed, useAttrs, ref, Ref, reactive, onMounted, watch, toRefs } from 'vue';
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';
@@ -8,7 +18,7 @@
8
18
  import RenderTitleSlots from '@/components/RenderTitleSlots';
9
19
  import RenderDefaultSlots from '@/components/RenderDefaultSlots';
10
20
  import { v4 as uuid_v4 } from 'uuid';
11
- import { valued } from '@/utils/is';
21
+ import { isGoodValue, valued } from '@/utils/is';
12
22
  import RenderItemSlots from '@/components/RenderItemSlots';
13
23
  import { cleanCol, defaultItemResponsive, defaultLabelCol } from '@/utils/core';
14
24
  import Icon from '@/renders/Icon';
@@ -44,8 +54,10 @@
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
- const selectedRowKeys = ref<string[] | number[]>([]);
59
+ const selectedRowKeys = ref<Array<string | number>>([]);
60
+ const selectedCaches = ref<D[]>([]);
49
61
  const innerToolbarHandler = (code: string) => {
50
62
  const { ajax } = proxyConfig.value!;
51
63
  switch (code) {
@@ -69,6 +81,7 @@
69
81
  .finally(() => {
70
82
  loading.table = false;
71
83
  loading.toolbar = false;
84
+ codeLoadings.multiDelete = false;
72
85
  });
73
86
  });
74
87
  } else {
@@ -97,6 +110,21 @@
97
110
  const refreshForm = () => {
98
111
  renderFormKey.value = uuid_v4();
99
112
  };
113
+ const codeLoadings = reactive<Record<string, boolean>>(
114
+ [
115
+ ...(props.toolbarConfig?.buttons?.map((m) => m.code) ?? []).filter((f) => f),
116
+ ...(props.toolbarConfig?.tools?.map((m) => m.code) ?? []).filter((f) => f),
117
+ ].reduce(
118
+ (acc, cur) => {
119
+ acc[cur!] = false;
120
+ return acc;
121
+ },
122
+ {} as Record<string, boolean>,
123
+ ),
124
+ );
125
+ const setBtnLoading = (code: string, value: boolean) => {
126
+ codeLoadings[code] = value;
127
+ };
100
128
  const refreshTable = () => {
101
129
  renderTableKey.value = uuid_v4();
102
130
  };
@@ -129,26 +157,42 @@
129
157
  : 'bad',
130
158
  );
131
159
  const attrs = useAttrs();
132
- const emit = defineEmits([
133
- 'query',
134
- 'reset',
135
- 'update:tableData',
136
- 'toolbarButtonClick',
137
- 'toolbarToolClick',
138
- 'pick',
139
- ]);
160
+ const emit = defineEmits<{
161
+ (
162
+ event: 'toolbarButtonClick',
163
+ data: { data: D[]; code: string; selectedKeys: Array<string | number>; records: D[] },
164
+ ): void;
165
+ (
166
+ event: 'toolbarToolClick',
167
+ data: { data: D[]; code: string; selectedKeys: Array<string | number>; records: D[] },
168
+ ): void;
169
+ (event: 'pick', data: { row: D; field: string }): void;
170
+ (event: 'resetQuery'): void;
171
+ }>();
172
+ // @ts-ignore
173
+ const selectedRecords = computed<D[]>(() =>
174
+ selectedCaches.value.filter((f) =>
175
+ selectedRowKeys.value.includes(f[props.rowKey ?? 'id'] as string | number),
176
+ ),
177
+ );
140
178
  const toolBtnClick = (code: string) => {
141
179
  emit('toolbarButtonClick', {
142
180
  data: tableData.value,
143
181
  code,
144
182
  selectedKeys: selectedRowKeys.value,
183
+ records: selectedRecords.value,
145
184
  });
146
185
  innerToolbarHandler(code);
147
186
  };
148
187
  const debounceToolBtnClick = debounce(toolBtnClick, 100);
149
188
  const toolBtnMenuClick = ({ key }) => debounceToolBtnClick(key);
150
189
  const toolToolClick = (code: string) => {
151
- emit('toolbarToolClick', { data: tableData.value, code, selectedKeys: selectedRowKeys.value });
190
+ emit('toolbarToolClick', {
191
+ data: tableData.value,
192
+ code,
193
+ selectedKeys: selectedRowKeys.value,
194
+ records: selectedRecords.value,
195
+ });
152
196
  innerToolbarHandler(code);
153
197
  };
154
198
  const debounceToolToolClick = debounce(toolToolClick, 100);
@@ -164,7 +208,7 @@
164
208
  const obj: Partial<F> = {};
165
209
  eachTree(formConfig.value.items, (item) => {
166
210
  if (item.field && item.itemRender) {
167
- if (valued(item.itemRender.defaultValue)) {
211
+ if (isGoodValue(item.itemRender.defaultValue)) {
168
212
  obj[item.field] = item.itemRender.defaultValue;
169
213
  } else {
170
214
  obj[item.field] = undefined;
@@ -173,6 +217,7 @@
173
217
  });
174
218
  queryFormData.value = obj;
175
219
  }
220
+ emit('resetQuery');
176
221
  refreshForm();
177
222
  }
178
223
 
@@ -214,6 +259,7 @@
214
259
  };
215
260
  const resetPage = () => {
216
261
  pagination.page = 1;
262
+ selectedCaches.value = [];
217
263
  selectedRowKeys.value = [];
218
264
  return fetchData();
219
265
  };
@@ -309,6 +355,14 @@
309
355
  selectedRowKeys: selectedRowKeys.value,
310
356
  onChange: (selectedKeys: string[] | number[]) => {
311
357
  selectedRowKeys.value = selectedKeys;
358
+ const primaryKey = props.rowKey ?? 'id';
359
+ const cachedKeys = selectedCaches.value.map((m) => m[primaryKey]);
360
+ const newKeys = selectedKeys.filter((f) => !cachedKeys.includes(f));
361
+ const newRecords: D[] = newKeys
362
+ .map((m) => tableData.value.find((f) => f[primaryKey] === m))
363
+ .filter((f) => !!f) as D[];
364
+ // @ts-ignore
365
+ selectedCaches.value = [...selectedCaches.value, ...newRecords];
312
366
  },
313
367
  getCheckboxProps: selectConfig.value.getCheckboxProps,
314
368
  },
@@ -336,6 +390,21 @@
336
390
  },
337
391
  { deep: true },
338
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
+ };
339
408
  defineExpose({
340
409
  commitProxy: {
341
410
  query: debounceFetchData,
@@ -345,26 +414,24 @@
345
414
  },
346
415
  $table: computed(() => tableEl.value),
347
416
  selectedRowKeys: computed(() => selectedRowKeys.value),
417
+ setBtnLoading,
418
+ selectedRecords,
348
419
  $form: computed(() => formEl.value),
349
420
  setLoadings: (value: boolean) => {
350
421
  loading.form = value;
351
422
  loading.table = value;
352
423
  loading.toolbar = value;
353
424
  },
425
+ resizeTable,
354
426
  });
355
427
  onMounted(() => {
356
- /*判断本组件所在容器DOM*/
357
- const pNode = boxEl.value?.parentElement;
358
- const ph = pNode ? window.getComputedStyle(pNode).height : '0px';
359
- renderHeight.value =
360
- props.renderY ??
361
- toNumber(ph.replace('px', '')) -
362
- (props.fitHeight ?? 170) -
363
- (!!props.toolbarConfig ? 30 : 0) -
364
- Math.ceil((props.formConfig?.items?.length ?? 0) / 4) * 35;
365
- enoughSpacing.value = toNumber(ph.replace('px', '')) > 600;
428
+ resizeTable();
429
+ window.addEventListener('resize', resizeTable);
366
430
  resetQueryFormData(props.manualFetch);
367
431
  });
432
+ onBeforeUnmount(() => {
433
+ window.removeEventListener('resize', resizeTable);
434
+ });
368
435
  </script>
369
436
  <template>
370
437
  <div ref="boxEl" class="h-full p-wrapper flex flex-col gap-8px overflow-y-auto" v-bind="attrs">
@@ -373,6 +440,7 @@
373
440
  <div
374
441
  v-if="formConfig?.items?.some((s: PFormItemProps<F>) => s.field && s.itemRender)"
375
442
  class="p-pane p-form-wrapper"
443
+ ref="pFormWrapper"
376
444
  >
377
445
  <a-spin :spinning="loading.form">
378
446
  <a-form
@@ -459,7 +527,12 @@
459
527
  </a-menu-item>
460
528
  </a-menu>
461
529
  </template>
462
- <a-button :type="btn.type" :size="btn.size ?? 'small'" :loading="loading.toolbar">
530
+ <a-button
531
+ :type="btn.type"
532
+ :size="btn.size ?? 'small'"
533
+ :disabled="toolbarConfig.disabled || btn.disabled"
534
+ :loading="loading.toolbar || (!!btn.code && codeLoadings[btn.code])"
535
+ >
463
536
  <Icon v-if="btn.icon" :icon="btn.icon" />
464
537
  {{ btn.content }}
465
538
  <DownOutlined />
@@ -469,7 +542,8 @@
469
542
  v-else-if="btn.code"
470
543
  :type="btn.type"
471
544
  :size="btn.size ?? 'small'"
472
- :loading="loading.toolbar"
545
+ :disabled="toolbarConfig.disabled || btn.disabled"
546
+ :loading="loading.toolbar || (!!btn.code && codeLoadings[btn.code])"
473
547
  @click="debounceToolBtnClick(btn.code)"
474
548
  >
475
549
  <Icon v-if="btn.icon" :icon="btn.icon" />
@@ -486,8 +560,9 @@
486
560
  :key="idx"
487
561
  :type="tool.type"
488
562
  size="small"
563
+ :disabled="toolbarConfig.disabled || tool.disabled"
489
564
  @click="debounceToolToolClick(tool.code)"
490
- :loading="loading.toolbar"
565
+ :loading="loading.toolbar || (!!tool.code && codeLoadings[tool.code])"
491
566
  >
492
567
  <Icon :icon="tool.icon" />
493
568
  </a-button>
@@ -23,7 +23,7 @@ import {
23
23
  } from 'ant-design-vue';
24
24
  import { set, isFunction, merge, omit } from 'lodash-es';
25
25
  import { ButtonProps } from 'ant-design-vue/lib/button';
26
- import { noValue, valued } from '@/utils/is';
26
+ import { isBadValue, isGoodValue, noValue, valued } from '@/utils/is';
27
27
  import TableInput from '@/renders/TableInput.vue';
28
28
  import Icon from '@/renders/Icon';
29
29
  import { computed } from 'vue';
@@ -130,7 +130,7 @@ const renderBasic = (name: string) => {
130
130
  { props = {}, attrs = {}, events = {}, defaultValue }: RenderOptions,
131
131
  { data, field }: RenderFormParams,
132
132
  ) {
133
- if (valued(defaultValue) && valued(field) && noValue(data[field!])) {
133
+ if (isGoodValue(defaultValue) && valued(field) && isBadValue(data[field!])) {
134
134
  data[field!] = defaultValue;
135
135
  }
136
136
  return field ? (
@@ -151,7 +151,7 @@ const renderBasic = (name: string) => {
151
151
  { props = antDefaultProps[name] ?? {}, attrs = {}, events = {}, defaultValue }: RenderOptions,
152
152
  { data, row, field }: RenderTableParams,
153
153
  ) {
154
- if (valued(defaultValue) && valued(field) && noValue(row[field!])) {
154
+ if (isGoodValue(defaultValue) && valued(field) && isBadValue(row[field!])) {
155
155
  row[field!] = defaultValue;
156
156
  }
157
157
  return field ? (
@@ -1,2 +1,4 @@
1
1
  export const noValue = (val: any) => val === null || val === undefined || val === '';
2
2
  export const valued = (val: any) => !noValue(val);
3
+ export const isBadValue = (val: any) => val === null || val === undefined;
4
+ export const isGoodValue = (val: any) => !isBadValue(val);
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
+ }