@vue-ui-kit/ant 2.3.9 → 2.4.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vue-ui-kit/ant",
3
- "version": "2.3.9",
3
+ "version": "2.4.1",
4
4
  "description": "Vue3 UI Kit based on Ant Design",
5
5
  "type": "module",
6
6
  "main": "./dist/cjs/index.js",
@@ -75,11 +75,13 @@ export interface PFormItemProps<F extends Recordable = Recordable> {
75
75
  }
76
76
 
77
77
  export interface PFormProps<F extends Recordable = Recordable> extends FormProps {
78
+ name?: string;
78
79
  items: PFormItemProps<F>[];
79
80
  customReset?: () => void;
80
81
  }
81
82
 
82
83
  export interface PBlockProps<F extends Recordable = Recordable> {
84
+ name?: string;
83
85
  getFormSetting: (data: Partial<F>) => PFormProps<Partial<F>>;
84
86
  source: Partial<F>;
85
87
  }
@@ -114,6 +116,7 @@ export interface GroupMenuItem<F extends Recordable = Recordable> {
114
116
  }
115
117
 
116
118
  export interface PFormGroupProps<F extends Recordable = Recordable> {
119
+ name?: string;
117
120
  getFormSetting: (data: Partial<F>) => PFormProps<Partial<F>>;
118
121
  title?: string;
119
122
  tabLabel?: string;
@@ -5,18 +5,18 @@
5
5
  name="PCanvasGrid"
6
6
  >
7
7
  import PCanvasTable from './PCanvasTable.vue';
8
- import { computed, useAttrs, ref, Ref, reactive, onMounted, toRefs, onBeforeUnmount } from 'vue';
9
8
  import {
10
- debounce,
11
- get,
12
- isBoolean,
13
- isFunction,
14
- isObject,
15
- isString,
16
- omit,
17
- toNumber,
18
- uniq,
19
- } from 'xe-utils';
9
+ computed,
10
+ useAttrs,
11
+ ref,
12
+ Ref,
13
+ reactive,
14
+ onMounted,
15
+ toRefs,
16
+ onBeforeUnmount,
17
+ watch,
18
+ } from 'vue';
19
+ import { debounce, get, isBoolean, isFunction, isObject, isString, omit, uniq } from 'xe-utils';
20
20
  import {
21
21
  CanvasColumnProps,
22
22
  PCanvasGridProps,
@@ -109,6 +109,7 @@
109
109
  const canvasTableRef = ref<PCanvasTableInstance<D>>();
110
110
  const boxEl = ref<HTMLDivElement>();
111
111
  const pFormWrapper = ref<HTMLDivElement>();
112
+ const tableWrapperEl = ref<HTMLDivElement>();
112
113
  const renderHeight = ref(500);
113
114
  /* 分页时缓存的跨页选择数据,风险:数据可能会更新导致串页,读取计算的时候要去重 */
114
115
  const pageSelections = ref<{
@@ -375,34 +376,42 @@
375
376
  pageSelections.value = {};
376
377
  return resetQueryFormData();
377
378
  };
379
+ let resizeRaf: number | null = null;
378
380
  const resizeTable = () => {
379
- const pNode = boxEl.value?.parentElement;
380
- const ph = pNode ? window.getComputedStyle(pNode).height : '0px';
381
- const formOriginHeight = pFormWrapper.value
382
- ? window.getComputedStyle(pFormWrapper.value).height
383
- : '0px';
384
- const formHeight = formOriginHeight.includes('px')
385
- ? toNumber(formOriginHeight.replace('px', ''))
386
- : 0;
387
- const showCountHeight = staticConfig.value?.showCount ? 22 : 0;
388
- renderHeight.value =
389
- toNumber(ph.replace('px', '')) -
390
- props.fitHeight -
391
- (props.toolbarConfig ? 30 : 0) -
392
- formHeight -
393
- showCountHeight;
381
+ if (resizeRaf) cancelAnimationFrame(resizeRaf);
382
+ resizeRaf = requestAnimationFrame(() => {
383
+ resizeRaf = null;
384
+ if (!tableWrapperEl.value) return;
385
+ const rect = tableWrapperEl.value.getBoundingClientRect();
386
+ renderHeight.value = Math.max(window.innerHeight - rect.top - props.fitHeight, 100);
387
+ });
394
388
  };
389
+
390
+ // 监听表单区域高度变化(响应式布局换行/收起时自动重算)
391
+ let formWrapperResizeObserver: ResizeObserver | null = null;
392
+ watch(
393
+ pFormWrapper,
394
+ (el) => {
395
+ formWrapperResizeObserver?.disconnect();
396
+ formWrapperResizeObserver = null;
397
+ if (!el) return;
398
+ formWrapperResizeObserver = new ResizeObserver(() => resizeTable());
399
+ formWrapperResizeObserver.observe(el);
400
+ },
401
+ { immediate: true },
402
+ );
403
+
395
404
  let observer: MutationObserver;
405
+ let boxElResizeObserver: ResizeObserver | null = null;
396
406
  onMounted(() => {
397
407
  resizeTable();
398
408
  window.addEventListener('resize', resizeTable);
399
- // 还需要在组件根节点由不可见转为可见时重新计算高度(display:none等样式控制时)
409
+ // 组件根节点由不可见转为可见时重新计算(display:none 切换场景)
400
410
  observer = new MutationObserver((mutations) => {
401
411
  mutations.forEach((mutation) => {
402
412
  if (mutation.type === 'attributes' && mutation.attributeName === 'style') {
403
413
  const el = mutation.target as HTMLElement;
404
- const style = window.getComputedStyle(el);
405
- if (style.display !== 'none') {
414
+ if (window.getComputedStyle(el).display !== 'none') {
406
415
  resizeTable();
407
416
  }
408
417
  }
@@ -410,12 +419,23 @@
410
419
  });
411
420
  if (boxEl.value) {
412
421
  observer.observe(boxEl.value, { attributes: true, attributeFilter: ['style'] });
422
+ // 往上观察多级祖先:父容器可能是内容撑开的,真正因外部兄弟变化而 resize
423
+ // 的元素可能在更高层(如 flex 容器)。观察多层确保能感知到
424
+ boxElResizeObserver = new ResizeObserver(() => resizeTable());
425
+ let ancestor: Element | null = boxEl.value.parentElement;
426
+ for (let i = 0; i < 5 && ancestor && ancestor !== document.body; i++) {
427
+ boxElResizeObserver.observe(ancestor);
428
+ ancestor = ancestor.parentElement;
429
+ }
413
430
  }
414
431
  resetQueryFormData(props.manualFetch);
415
432
  });
416
433
  onBeforeUnmount(() => {
434
+ if (resizeRaf) cancelAnimationFrame(resizeRaf);
417
435
  window.removeEventListener('resize', resizeTable);
418
436
  observer.disconnect();
437
+ formWrapperResizeObserver?.disconnect();
438
+ boxElResizeObserver?.disconnect();
419
439
  });
420
440
  defineExpose({
421
441
  commitProxy: {
@@ -534,7 +554,7 @@
534
554
  </template>
535
555
  </span>
536
556
  </div>
537
- <div :class="`p-pane flex-1 h-0 p-inner-scroll`">
557
+ <div ref="tableWrapperEl" :class="`p-pane flex-1 h-0 p-inner-scroll`">
538
558
  <div
539
559
  v-if="staticConfig?.selectable && staticConfig.showCount"
540
560
  class="w-full text-slate-5 pl-4"
@@ -75,7 +75,14 @@
75
75
  v-if="items.some((s: PFormItemProps<F>) => (s.field && s.itemRender) || s.slots?.default)"
76
76
  class="p-pane p-wrapper"
77
77
  >
78
- <a-form :key="renderFormKey" ref="formEl" :model="formData" v-bind="fc" @submit="handleSubmit">
78
+ <a-form
79
+ :name="name"
80
+ :key="renderFormKey"
81
+ ref="formEl"
82
+ :model="formData"
83
+ v-bind="fc"
84
+ @submit="handleSubmit"
85
+ >
79
86
  <a-row :gutter="[6, 12]">
80
87
  <p-form-col
81
88
  v-for="(item, idx) in items"
@@ -310,6 +310,7 @@
310
310
  ref="blockInstance"
311
311
  :key="idx"
312
312
  :source="item"
313
+ :name="name ? `${name}_${idx}` : undefined"
313
314
  :get-form-setting="getFormSetting"
314
315
  @focus.capture="debounceHandleBlockFocus(idx)"
315
316
  @click.capture="debounceHandleBlockFocus(idx)"
@@ -26,7 +26,6 @@
26
26
  isString,
27
27
  merge,
28
28
  omit,
29
- toNumber,
30
29
  } from 'xe-utils';
31
30
  import { eachTree } from '@/utils/treeHelper';
32
31
  import { message as $message } from 'ant-design-vue';
@@ -86,6 +85,7 @@
86
85
  };
87
86
  const boxEl = ref<HTMLDivElement>();
88
87
  const pFormWrapper = ref<HTMLDivElement>();
88
+ const tableWrapperEl = ref<HTMLDivElement>();
89
89
  const renderHeight = ref(500);
90
90
  const selectedRowKeys = ref<Array<string | number>>([]);
91
91
  const selectedCaches = ref<D[]>([]);
@@ -423,25 +423,32 @@
423
423
  },
424
424
  { deep: true },
425
425
  );
426
+ let resizeRaf: number | null = null;
426
427
  const resizeTable = () => {
427
- const pNode = boxEl.value?.parentElement;
428
- const ph = pNode ? window.getComputedStyle(pNode).height : '0px';
429
- const formOriginHeight = pFormWrapper.value
430
- ? window.getComputedStyle(pFormWrapper.value).height
431
- : '0px';
432
- const formHeight = formOriginHeight.includes('px')
433
- ? toNumber(formOriginHeight.replace('px', ''))
434
- : 0;
435
- const showCountHeight = selectConfig.value?.showCount ? 22 : 0;
436
- renderHeight.value =
437
- props.renderY ??
438
- toNumber(ph.replace('px', '')) -
439
- props.fitHeight -
440
- (props.toolbarConfig ? 30 : 0) -
441
- formHeight -
442
- showCountHeight;
443
- enoughSpacing.value = toNumber(ph.replace('px', '')) > 600;
428
+ if (resizeRaf) cancelAnimationFrame(resizeRaf);
429
+ resizeRaf = requestAnimationFrame(() => {
430
+ resizeRaf = null;
431
+ if (!tableWrapperEl.value) return;
432
+ const rect = tableWrapperEl.value.getBoundingClientRect();
433
+ renderHeight.value =
434
+ props.renderY ?? Math.max(window.innerHeight - rect.top - props.fitHeight, 100);
435
+ enoughSpacing.value = window.innerHeight > 600;
436
+ });
444
437
  };
438
+
439
+ // 监听表单区域高度变化(响应式布局换行/收起时自动重算)
440
+ let formWrapperResizeObserver: ResizeObserver | null = null;
441
+ watch(
442
+ pFormWrapper,
443
+ (el) => {
444
+ formWrapperResizeObserver?.disconnect();
445
+ formWrapperResizeObserver = null;
446
+ if (!el) return;
447
+ formWrapperResizeObserver = new ResizeObserver(() => resizeTable());
448
+ formWrapperResizeObserver.observe(el);
449
+ },
450
+ { immediate: true },
451
+ );
445
452
  defineExpose({
446
453
  commitProxy: {
447
454
  query: debounceFetchData,
@@ -461,16 +468,16 @@
461
468
  });
462
469
 
463
470
  let observer: MutationObserver;
471
+ let boxElResizeObserver: ResizeObserver | null = null;
464
472
  onMounted(() => {
465
473
  resizeTable();
466
474
  window.addEventListener('resize', resizeTable);
467
- // 还需要在组件根节点由不可见转为可见时重新计算高度(display:none等样式控制时)
475
+ // 组件根节点由不可见转为可见时重新计算(display:none 切换场景)
468
476
  observer = new MutationObserver((mutations) => {
469
477
  mutations.forEach((mutation) => {
470
478
  if (mutation.type === 'attributes' && mutation.attributeName === 'style') {
471
479
  const el = mutation.target as HTMLElement;
472
- const style = window.getComputedStyle(el);
473
- if (style.display !== 'none') {
480
+ if (window.getComputedStyle(el).display !== 'none') {
474
481
  resizeTable();
475
482
  }
476
483
  }
@@ -479,6 +486,14 @@
479
486
 
480
487
  if (boxEl.value) {
481
488
  observer.observe(boxEl.value, { attributes: true, attributeFilter: ['style'] });
489
+ // 往上观察多级祖先:父容器可能是内容撑开的,真正因外部兄弟变化而 resize
490
+ // 的元素可能在更高层(如 flex 容器)。观察多层确保能感知到
491
+ boxElResizeObserver = new ResizeObserver(() => resizeTable());
492
+ let ancestor: Element | null = boxEl.value.parentElement;
493
+ for (let i = 0; i < 5 && ancestor && ancestor !== document.body; i++) {
494
+ boxElResizeObserver.observe(ancestor);
495
+ ancestor = ancestor.parentElement;
496
+ }
482
497
  }
483
498
  resetQueryFormData(props.manualFetch);
484
499
  });
@@ -504,8 +519,11 @@
504
519
  ...c,
505
520
  }));
506
521
  onBeforeUnmount(() => {
522
+ if (resizeRaf) cancelAnimationFrame(resizeRaf);
507
523
  window.removeEventListener('resize', resizeTable);
508
524
  observer.disconnect();
525
+ formWrapperResizeObserver?.disconnect();
526
+ boxElResizeObserver?.disconnect();
509
527
  });
510
528
  </script>
511
529
  <template>
@@ -519,6 +537,7 @@
519
537
  >
520
538
  <a-spin :spinning="loading.form">
521
539
  <a-form
540
+ :name="formConfig?.name"
522
541
  :key="renderFormKey"
523
542
  ref="formEl"
524
543
  :model="queryFormData"
@@ -619,7 +638,10 @@
619
638
  </template>
620
639
  </span>
621
640
  </div>
622
- <div :class="`p-pane flex-1 ${enoughSpacing ? 'h-0' : ''} p-${scrollMode ?? 'inner'}-scroll`">
641
+ <div
642
+ ref="tableWrapperEl"
643
+ :class="`p-pane flex-1 ${enoughSpacing ? 'h-0' : ''} p-${scrollMode ?? 'inner'}-scroll`"
644
+ >
623
645
  <div
624
646
  v-if="selectConfig?.multiple && selectConfig.showCount"
625
647
  class="w-full text-slate-5 pl-4"
@@ -13,5 +13,5 @@
13
13
  });
14
14
  </script>
15
15
  <template>
16
- <p-form ref="formEl" v-bind="formSetting" :data="source!" />
16
+ <p-form :name="name" ref="formEl" v-bind="formSetting" :data="source!" />
17
17
  </template>