fantasy-ngzorro 2.1.60 → 2.1.62

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 CHANGED
@@ -37,6 +37,9 @@
37
37
  | — | 2026-5-20 | 补充 hd-table、hd-detail-lines-page 等组件;完善公共子类型(SelectOption、FormItem 等)文档 |
38
38
  | — | 2026-9-18 | `hd-form-lines` 选中回显(nzHide)认 `showLabelAndValue`,与下拉 `[value]label` 一致(对齐 `hd-form`) |
39
39
  | — | 2026-9-18 | `hd-detail-lines-page` 对齐 `hd-table` 支持虚拟滚动(`virtualScroll` / `virtualItemSize`);千行勾选时减少 DOM 卡顿 |
40
+ | — | 2026-9-20 | hd-detail-form 附件图片:最多展示 4 张,超出末张蒙版 `+n`;弹窗预览支持左右翻页 |
41
+ | — | 2026-9-20 | hd-detail-form 附件图片点击弹窗预览大图(不再 `window.open`) |
42
+ | — | 2026-9-20 | hd-detail-form 支持附件图片字段(`HdDetailFormFieldType.Accessory`,Figma 48×48 缩略图横排,不复用 hd-accessory-list) |
40
43
  | — | 2026-9-17 | hd-table / hd-detail-lines / hd-detail-lines-page 支持 `selectDisabledField` / `rowInvalidField`:按行字段控制勾选禁用、失效行样式 |
41
44
  | — | 2026-9-14 | 新增 `hd-accessory-list` 附件列表组件(分组 name + accessoryList,点击下载/查看) |
42
45
  | — | 2026-6-23 | hd-table 状态列支持 `stateField` 自定义取值字段、`isState` 按列名取值;hd-form Input 支持 `prefix` / `prefixIcon`;hd-detail-lines-page 支持 `isCrossPageSelect` 跨页勾选开关 |
@@ -578,14 +581,27 @@ this.hdFormLines.batchFillSelected({ remark: '批量备注' }); // 批量填充
578
581
  ### 示例
579
582
 
580
583
  ```html
581
- <hd-detail-form [formCols]="formCols"></hd-detail-form>
584
+ <hd-detail-form [formCols]="formCols" (imageClick)="onDetailFormImageClick($event)"></hd-detail-form>
582
585
  ```
583
586
 
584
587
  ```typescript
588
+ import { HdDetailFormFieldType, HdOption } from 'fantasy-ngzorro';
589
+
585
590
  formCols: HdOption[] = [
586
591
  { label: '收货单号', value: '202111030001' },
587
592
  { label: '地址', value: '江苏/南京市/玄武区 某某路', width: 2 },
588
- { label: '备注', value: '...' }
593
+ { label: '备注', value: '...' },
594
+ // 附件图片:label + 图片地址列表(Figma 48×48 缩略图横排)
595
+ {
596
+ label: '食品经营许可证',
597
+ type: HdDetailFormFieldType.Accessory,
598
+ width: 2,
599
+ value: [
600
+ { name: '正面', path: 'https://oss.xxx.com/a.png' },
601
+ { name: '背面', path: 'https://oss.xxx.com/b.png' },
602
+ 'https://oss.xxx.com/c.png', // 也支持纯地址字符串
603
+ ],
604
+ },
589
605
  ];
590
606
  ```
591
607
 
@@ -593,6 +609,16 @@ formCols: HdOption[] = [
593
609
  | ---- | ---- | ------ | ---- |
594
610
  | formCols | HdOption[] | — | 展示字段,见 [HdOption](#hdoption键值展示项) |
595
611
  | nzColumn | number \| object | `4` | 一行列数,默认固定 4 列 |
612
+ | imageClick | EventEmitter | — | 附件图片点击回调 `{ image, path, index }`(`type=accessory` 时) |
613
+
614
+ 附件字段 `type: HdDetailFormFieldType.Accessory`(或 `'accessory'`):
615
+
616
+ - 对齐 Figma `items/description-cell`「图片」:标签 + **48×48** 缩略图横排(间距 6px,边框 `#E5E6EB`,圆角 4px);标签与首图顶对齐
617
+ - `value` 支持:图片地址 `string` / `string[]`,或 `{ name?, path?/url? }[]`
618
+ - 最多直接展示 **4** 张;超出时第 4 张蒙版显示 `+n`(n 为剩余张数)
619
+ - 点击缩略图弹窗预览大图(支持左右翻页),并触发 `imageClick`
620
+ - 无图时展示 `<空>`
621
+ - **不使用** `hd-accessory-list`(文件列表样式请用独立附件列表组件)
596
622
 
597
623
  ---
598
624
 
@@ -904,7 +930,8 @@ selectOption: {
904
930
  | 参数 | 类型 | 说明 |
905
931
  | ---- | ---- | ---- |
906
932
  | label | string | 标签 |
907
- | value | any | |
933
+ | value | any | 值;附件类型时为图片地址 `string` / `string[]` 或 `{ name?, path?/url? }[]` |
934
+ | type | string / HdDetailFormFieldType | 字段类型,默认文本;`accessory` 为附件图片缩略图 |
908
935
  | width | number | 占据列数,默认 1,最大 4;未传按 1 |
909
936
  | color | string | 文字颜色 |
910
937
  | hide | boolean | 是否隐藏 |
@@ -437,6 +437,49 @@
437
437
  * @fileoverview added by tsickle
438
438
  * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
439
439
  */
440
+ /** @enum {string} */
441
+ var HdDetailFormFieldType = {
442
+ /** 普通文本(默认) */
443
+ Text: "text",
444
+ /** 附件图片(描述项内横排缩略图) */
445
+ Accessory: "accessory",
446
+ };
447
+ /**
448
+ * 附件图片项(path 为图片地址)
449
+ * @record
450
+ */
451
+ function HdDetailFormImage() { }
452
+ if (false) {
453
+ /** @type {?|undefined} */
454
+ HdDetailFormImage.prototype.name;
455
+ /** @type {?|undefined} */
456
+ HdDetailFormImage.prototype.path;
457
+ /** @type {?|undefined} */
458
+ HdDetailFormImage.prototype.url;
459
+ }
460
+ var HdDetailFormService = /** @class */ (function () {
461
+ function HdDetailFormService() {
462
+ }
463
+ HdDetailFormService.decorators = [
464
+ { type: core.Injectable, args: [{
465
+ providedIn: "root",
466
+ },] }
467
+ ];
468
+ /** @nocollapse */
469
+ HdDetailFormService.ctorParameters = function () { return []; };
470
+ /** @nocollapse */ HdDetailFormService.ngInjectableDef = core.ɵɵdefineInjectable({ factory: function HdDetailFormService_Factory() { return new HdDetailFormService(); }, token: HdDetailFormService, providedIn: "root" });
471
+ return HdDetailFormService;
472
+ }());
473
+
474
+ /**
475
+ * @fileoverview added by tsickle
476
+ * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
477
+ */
478
+ /**
479
+ * 附件缩略图最多直接展示张数,超出末张蒙版 +n
480
+ * @type {?}
481
+ */
482
+ var MAX_VISIBLE_IMAGES = 4;
440
483
  var HdDetailFormComponent = /** @class */ (function () {
441
484
  function HdDetailFormComponent() {
442
485
  this.formCols = new Array();
@@ -444,7 +487,48 @@
444
487
  * 一行列数,默认固定 4 列(不再按屏幕宽度自适应)
445
488
  */
446
489
  this.nzColumn = 4;
490
+ /**
491
+ * 附件图片点击回调
492
+ */
493
+ this.imageClick = new core.EventEmitter();
494
+ this.HdDetailFormFieldType = HdDetailFormFieldType;
495
+ /**
496
+ * 大图预览
497
+ */
498
+ this.previewVisible = false;
499
+ this.previewImagePath = "";
500
+ this.previewTitle = "图片预览";
501
+ /**
502
+ * 当前预览所属字段的图片列表(用于翻页)
503
+ */
504
+ this.previewImages = [];
505
+ this.previewIndex = 0;
506
+ /**
507
+ * 附件字段图片缓存(避免模板里反复 getImageList 导致 *ngFor 重建、点击丢失)
508
+ */
509
+ this.imageListCache = new Map();
510
+ this.displayListCache = new Map();
447
511
  }
512
+ Object.defineProperty(HdDetailFormComponent.prototype, "canPreviewPrev", {
513
+ get: /**
514
+ * @return {?}
515
+ */
516
+ function () {
517
+ return this.previewIndex > 0;
518
+ },
519
+ enumerable: true,
520
+ configurable: true
521
+ });
522
+ Object.defineProperty(HdDetailFormComponent.prototype, "canPreviewNext", {
523
+ get: /**
524
+ * @return {?}
525
+ */
526
+ function () {
527
+ return this.previewIndex < this.previewImages.length - 1;
528
+ },
529
+ enumerable: true,
530
+ configurable: true
531
+ });
448
532
  /**
449
533
  * @return {?}
450
534
  */
@@ -453,13 +537,13 @@
453
537
  */
454
538
  function () {
455
539
  if (this.formCols && this.formCols.length > 0) {
456
- // 剔除掉formCols里面不需要显示的内容
457
540
  this.formCols = this.formCols.filter((/**
458
541
  * @param {?} item
459
542
  * @return {?}
460
543
  */
461
544
  function (item) { return !item.hide; }));
462
545
  }
546
+ this.refreshImageCache();
463
547
  };
464
548
  /**
465
549
  * @param {?} changes
@@ -470,16 +554,295 @@
470
554
  * @return {?}
471
555
  */
472
556
  function (changes) {
473
- if (changes['formCols'] && JSON.stringify(changes['formCols'].currentValue) !== JSON.stringify(changes['formCols'].previousValue)) {
557
+ if (changes["formCols"] &&
558
+ JSON.stringify(changes["formCols"].currentValue) !==
559
+ JSON.stringify(changes["formCols"].previousValue)) {
474
560
  if (this.formCols && this.formCols.length > 0) {
475
- // 剔除掉formCols里面不需要显示的内容
476
561
  this.formCols = this.formCols.filter((/**
477
562
  * @param {?} item
478
563
  * @return {?}
479
564
  */
480
565
  function (item) { return !item.hide; }));
481
566
  }
567
+ this.refreshImageCache();
568
+ }
569
+ };
570
+ /**
571
+ * @param {?} col
572
+ * @return {?}
573
+ */
574
+ HdDetailFormComponent.prototype.isAccessory = /**
575
+ * @param {?} col
576
+ * @return {?}
577
+ */
578
+ function (col) {
579
+ return !!(col &&
580
+ (col.type === HdDetailFormFieldType.Accessory || col.type === "accessory"));
581
+ };
582
+ /**
583
+ * @private
584
+ * @return {?}
585
+ */
586
+ HdDetailFormComponent.prototype.refreshImageCache = /**
587
+ * @private
588
+ * @return {?}
589
+ */
590
+ function () {
591
+ var _this = this;
592
+ this.imageListCache.clear();
593
+ this.displayListCache.clear();
594
+ (this.formCols || []).forEach((/**
595
+ * @param {?} col
596
+ * @return {?}
597
+ */
598
+ function (col) {
599
+ if (_this.isAccessory(col)) {
600
+ _this.imageListCache.set(col, _this.parseImageList(col));
601
+ }
602
+ }));
603
+ };
604
+ /**
605
+ * 解析附件图片列表。value 支持:
606
+ * - string / string[](图片地址)
607
+ * - { name?, path? / url? }[]
608
+ */
609
+ /**
610
+ * 解析附件图片列表。value 支持:
611
+ * - string / string[](图片地址)
612
+ * - { name?, path? / url? }[]
613
+ * @private
614
+ * @param {?} col
615
+ * @return {?}
616
+ */
617
+ HdDetailFormComponent.prototype.parseImageList = /**
618
+ * 解析附件图片列表。value 支持:
619
+ * - string / string[](图片地址)
620
+ * - { name?, path? / url? }[]
621
+ * @private
622
+ * @param {?} col
623
+ * @return {?}
624
+ */
625
+ function (col) {
626
+ /** @type {?} */
627
+ var value = col && col.value;
628
+ if (value == null || value === "") {
629
+ return [];
630
+ }
631
+ /** @type {?} */
632
+ var list = Array.isArray(value) ? value : [value];
633
+ /** @type {?} */
634
+ var result = [];
635
+ list.forEach((/**
636
+ * @param {?} item
637
+ * @return {?}
638
+ */
639
+ function (item) {
640
+ if (item == null || item === "") {
641
+ return;
642
+ }
643
+ if (typeof item === "string") {
644
+ result.push({ path: item });
645
+ return;
646
+ }
647
+ /** @type {?} */
648
+ var path = item.path || item.url || item.address || "";
649
+ if (!path) {
650
+ return;
651
+ }
652
+ result.push({
653
+ name: item.name || item.fileName,
654
+ path: String(path),
655
+ });
656
+ }));
657
+ return result;
658
+ };
659
+ /**
660
+ * @param {?} col
661
+ * @return {?}
662
+ */
663
+ HdDetailFormComponent.prototype.getImageList = /**
664
+ * @param {?} col
665
+ * @return {?}
666
+ */
667
+ function (col) {
668
+ if (!this.imageListCache.has(col)) {
669
+ this.imageListCache.set(col, this.parseImageList(col));
670
+ }
671
+ return this.imageListCache.get(col) || [];
672
+ };
673
+ /**
674
+ * @param {?} col
675
+ * @return {?}
676
+ */
677
+ HdDetailFormComponent.prototype.hasImages = /**
678
+ * @param {?} col
679
+ * @return {?}
680
+ */
681
+ function (col) {
682
+ return this.getImageList(col).length > 0;
683
+ };
684
+ /** 实际渲染的缩略图(最多 4 张) */
685
+ /**
686
+ * 实际渲染的缩略图(最多 4 张)
687
+ * @param {?} col
688
+ * @return {?}
689
+ */
690
+ HdDetailFormComponent.prototype.getDisplayImages = /**
691
+ * 实际渲染的缩略图(最多 4 张)
692
+ * @param {?} col
693
+ * @return {?}
694
+ */
695
+ function (col) {
696
+ if (this.displayListCache.has(col)) {
697
+ return this.displayListCache.get(col);
698
+ }
699
+ /** @type {?} */
700
+ var display = this.getImageList(col).slice(0, MAX_VISIBLE_IMAGES);
701
+ this.displayListCache.set(col, display);
702
+ return display;
703
+ };
704
+ /** 未展示张数(末张蒙版 +n) */
705
+ /**
706
+ * 未展示张数(末张蒙版 +n)
707
+ * @param {?} col
708
+ * @return {?}
709
+ */
710
+ HdDetailFormComponent.prototype.getMoreCount = /**
711
+ * 未展示张数(末张蒙版 +n)
712
+ * @param {?} col
713
+ * @return {?}
714
+ */
715
+ function (col) {
716
+ /** @type {?} */
717
+ var total = this.getImageList(col).length;
718
+ return total > MAX_VISIBLE_IMAGES ? total - MAX_VISIBLE_IMAGES : 0;
719
+ };
720
+ /**
721
+ * @param {?} image
722
+ * @return {?}
723
+ */
724
+ HdDetailFormComponent.prototype.getImagePath = /**
725
+ * @param {?} image
726
+ * @return {?}
727
+ */
728
+ function (image) {
729
+ return (image && (image.path || image.url)) || "";
730
+ };
731
+ /**
732
+ * @param {?} index
733
+ * @param {?} image
734
+ * @return {?}
735
+ */
736
+ HdDetailFormComponent.prototype.trackByImage = /**
737
+ * @param {?} index
738
+ * @param {?} image
739
+ * @return {?}
740
+ */
741
+ function (index, image) {
742
+ return (image && (image.path || image.url)) || String(index);
743
+ };
744
+ /**
745
+ * @param {?} col
746
+ * @param {?} image
747
+ * @param {?} index
748
+ * @param {?=} event
749
+ * @return {?}
750
+ */
751
+ HdDetailFormComponent.prototype.onImageClick = /**
752
+ * @param {?} col
753
+ * @param {?} image
754
+ * @param {?} index
755
+ * @param {?=} event
756
+ * @return {?}
757
+ */
758
+ function (col, image, index, event) {
759
+ var _this = this;
760
+ if (event) {
761
+ event.preventDefault();
762
+ event.stopPropagation();
763
+ }
764
+ /** @type {?} */
765
+ var path = this.getImagePath(image);
766
+ this.imageClick.emit({ image: image, path: path, index: index });
767
+ if (!path) {
768
+ return;
482
769
  }
770
+ this.previewImages = this.getImageList(col).slice();
771
+ this.previewIndex = index >= 0 ? index : 0;
772
+ this.applyPreviewImage();
773
+ setTimeout((/**
774
+ * @return {?}
775
+ */
776
+ function () {
777
+ _this.previewVisible = true;
778
+ }));
779
+ };
780
+ /**
781
+ * @param {?=} event
782
+ * @return {?}
783
+ */
784
+ HdDetailFormComponent.prototype.previewPrev = /**
785
+ * @param {?=} event
786
+ * @return {?}
787
+ */
788
+ function (event) {
789
+ if (event) {
790
+ event.preventDefault();
791
+ event.stopPropagation();
792
+ }
793
+ if (!this.canPreviewPrev) {
794
+ return;
795
+ }
796
+ this.previewIndex -= 1;
797
+ this.applyPreviewImage();
798
+ };
799
+ /**
800
+ * @param {?=} event
801
+ * @return {?}
802
+ */
803
+ HdDetailFormComponent.prototype.previewNext = /**
804
+ * @param {?=} event
805
+ * @return {?}
806
+ */
807
+ function (event) {
808
+ if (event) {
809
+ event.preventDefault();
810
+ event.stopPropagation();
811
+ }
812
+ if (!this.canPreviewNext) {
813
+ return;
814
+ }
815
+ this.previewIndex += 1;
816
+ this.applyPreviewImage();
817
+ };
818
+ /**
819
+ * @private
820
+ * @return {?}
821
+ */
822
+ HdDetailFormComponent.prototype.applyPreviewImage = /**
823
+ * @private
824
+ * @return {?}
825
+ */
826
+ function () {
827
+ /** @type {?} */
828
+ var image = this.previewImages[this.previewIndex];
829
+ /** @type {?} */
830
+ var path = this.getImagePath(image);
831
+ this.previewImagePath = path;
832
+ this.previewTitle =
833
+ (image && image.name) || "图片" + (this.previewIndex + 1);
834
+ };
835
+ /**
836
+ * @return {?}
837
+ */
838
+ HdDetailFormComponent.prototype.closePreview = /**
839
+ * @return {?}
840
+ */
841
+ function () {
842
+ this.previewVisible = false;
843
+ this.previewImages = [];
844
+ this.previewIndex = 0;
845
+ this.previewImagePath = "";
483
846
  };
484
847
  /** HdOption.width:默认 1,最大 4 */
485
848
  /**
@@ -515,16 +878,17 @@
515
878
  };
516
879
  HdDetailFormComponent.decorators = [
517
880
  { type: core.Component, args: [{
518
- selector: 'hd-detail-form',
519
- template: "<nz-content class=\"hd-detail-form-container\">\n <nz-descriptions [nzColumn]=\"nzColumn\">\n <ng-container *ngFor=\"let col of formCols\">\n <nz-descriptions-item *ngIf=\"!col.click\" [nzTitle]=\"col.label\" [nzSpan]=\"getColSpan(col)\">\n <span [ngStyle]=\"{'color': col?.color ? col.color : null}\">{{(col.value === '0' || col.value === 0 || col.value\n )? col.value : '&lt;\u7A7A&gt;'}}</span>\n </nz-descriptions-item>\n <nz-descriptions-item *ngIf=\"col.click\" [nzTitle]=\"col.label\" [nzSpan]=\"getColSpan(col)\">\n <span [ngStyle]=\"{'color': col?.color ? col.color : null}\" *ngIf=\"col.clickText\">\n {{(col.value === '0' || col.value === 0 || col.value\n )? col.value : '&lt;\u7A7A&gt;'}}\n <a (click)=\"triggerEvent(col.click || null)\">&nbsp;&nbsp;&nbsp;&nbsp;{{ col.clickText }}</a>\n <a *ngIf=\"col.clickText1\" (click)=\"triggerEvent(col.click1 || null)\">&nbsp;&nbsp;&nbsp;&nbsp;{{ col.clickText1 }}</a>\n </span>\n <span [ngStyle]=\"{'color': col?.color ? col.color : null}\" *ngIf=\"!col.clickText\">\n <a (click)=\"triggerEvent(col.click || null)\">{{(col.value === '0' || col.value === 0 || col.value\n )? col.value : '&lt;\u7A7A&gt;'}}</a>\n <a *ngIf=\"col.clickText1\" (click)=\"triggerEvent(col.click1 || null)\">&nbsp;&nbsp;&nbsp;&nbsp;{{ col.clickText1 }}</a>\n </span>\n </nz-descriptions-item>\n </ng-container>\n </nz-descriptions>\n</nz-content>\n",
520
- styles: ["::ng-deep .common-btn-group>a{font-size:14px;font-weight:400;color:#20b95d!important;white-space:nowrap}::ng-deep .common-btn-group .common-danger-btn:hover{color:#f05b24!important}::ng-deep .common-btn-group>a:hover{color:#20bd62!important}::ng-deep .common-btn-group>a:not(:last-child)::after{content:'';margin:0 2px}::ng-deep .common-billNumber>a{color:#3b77e3}button{box-shadow:unset;text-shadow:unset}::ng-deep .ant-form-item-label>label{color:#4b504e;font-size:14px}::ng-deep .ant-input-number-input{height:32px}::ng-deep .ant-input-number{height:32px}textarea.ant-input{height:auto;min-height:32px}::ng-deep .ant-select-selection--multiple{min-height:32px}::ng-deep .ant-select-selection__rendered>ul>li{height:26px!important;margin-top:3px!important;line-height:26px!important}::ng-deep .ant-advanced-search-form .ant-form-item{margin-bottom:0!important}::ng-deep .ant-select-selection--single{height:32px!important}::ng-deep .ant-input{height:32px}::ng-deep .ant-input[disabled]:hover{border-color:#d9d9d9!important}::ng-deep .ant-select-selection__rendered{line-height:32px!important}::ng-deep .ant-calendar-range-picker-input{text-align:left!important}::ng-deep .ant-calendar-picker{width:100%!important}::ng-deep .ant-row{margin-right:0!important;margin-left:0!important}::ng-deep .ant-col-6{padding-left:12px;padding-right:12px}::ng-deep .ant-col-12{padding-left:12px;padding-right:12px}::ng-deep .ant-col-18{padding-left:12px;padding-right:12px}::ng-deep .ant-col-24{padding-left:12px;padding-right:12px}::ng-deep .ant-alert-info{background-color:#f5f8f6;border:1px solid #cfe3d4}::ng-deep .hd-table-container .ant-table-td-left-sticky,::ng-deep .hd-table-container .ant-table-td-right-sticky,::ng-deep .hd-table-container .ant-table-th-left-sticky,::ng-deep .hd-table-container .ant-table-th-right-sticky{z-index:2;transform:translateZ(0)}::ng-deep .hd-table-container .ant-table-thead>tr>th.ant-table-th-left-sticky,::ng-deep .hd-table-container .ant-table-thead>tr>th.ant-table-th-right-sticky{background:#f5f8f6!important}::ng-deep .hd-table-container .ant-table-tbody>tr>td.ant-table-td-left-sticky,::ng-deep .hd-table-container .ant-table-tbody>tr>td.ant-table-td-right-sticky{background:#fff}::ng-deep .hd-table-container .ant-table-tbody>tr.ant-table-row-hover>td.ant-table-td-left-sticky,::ng-deep .hd-table-container .ant-table-tbody>tr.ant-table-row-hover>td.ant-table-td-right-sticky,::ng-deep .hd-table-container .ant-table-tbody>tr:hover>td.ant-table-td-left-sticky,::ng-deep .hd-table-container .ant-table-tbody>tr:hover>td.ant-table-td-right-sticky{background:#ecf8f1!important}::ng-deep .hd-table-container .ant-table-scroll-position-left .ant-table-td-right-sticky,::ng-deep .hd-table-container .ant-table-scroll-position-left .ant-table-th-right-sticky,::ng-deep .hd-table-container .ant-table-scroll-position-middle .ant-table-td-right-sticky,::ng-deep .hd-table-container .ant-table-scroll-position-middle .ant-table-th-right-sticky,::ng-deep .hd-table-container .ant-table-scroll-position-right .ant-table-td-right-sticky,::ng-deep .hd-table-container .ant-table-scroll-position-right .ant-table-th-right-sticky{box-shadow:none!important}::ng-deep .hd-table-container .ant-table-fixed-right{right:0!important}:host ::ng-deep th{background:#f5f8f6!important;font-weight:700!important;white-space:nowrap;font-size:14px;font-family:PingFangSC-Medium,PingFang SC;color:#2a3634;padding:8px!important;box-sizing:border-box}:host ::ng-deep td{font-weight:400;font-style:normal;font-size:14px;color:#2a3634;text-align:left;white-space:nowrap;padding:8px!important;box-sizing:border-box}::ng-deep .ant-pagination-options{display:inline-flex;align-items:center}::ng-deep .ant-pagination-options .ant-select,::ng-deep .ant-pagination-options .ant-select-selection--single{min-width:100px}::ng-deep .ant-pagination-options-size-changer.ant-select{min-width:100px}::ng-deep .ant-time-picker{width:100%}::ng-deep .cdk-overlay-pane .hd-cascader-menus.ant-cascader-menus>.ant-cascader-menu:only-child{width:-webkit-max-content!important;width:-moz-max-content!important;width:max-content!important;min-width:var(--hd-cascader-menu-min-width,auto);max-width:560px}::ng-deep .cdk-overlay-pane .hd-cascader-menus.ant-cascader-menus>.ant-cascader-menu:only-child .ant-cascader-menu-item{white-space:nowrap}.ant-input-number-disabled,.ant-input[disabled],.ant-select-disabled{color:#4b504e}.hd-detail-form-container{font-size:14px}.hd-detail-form-container ::ng-deep td.ant-descriptions-item{vertical-align:top;padding-top:6px!important;padding-bottom:6px!important;padding-left:0!important;font-size:14px}.hd-detail-form-container ::ng-deep .ant-descriptions-item-label{color:#4b504e;font-size:14px}.hd-detail-form-container ::ng-deep .ant-descriptions-item-content{word-break:break-all;color:rgba(0,0,0,.85);font-weight:400;font-size:14px}.hd-detail-form-container ::ng-deep a{font-size:14px}.hd-detail-form-container ::ng-deep td{white-space:unset!important}"]
881
+ selector: "hd-detail-form",
882
+ template: "<nz-content class=\"hd-detail-form-container\">\n <nz-descriptions [nzColumn]=\"nzColumn\">\n <ng-container *ngFor=\"let col of formCols\">\n <!-- \u9644\u4EF6\u56FE\u7247\uFF1A\u6700\u591A\u5C55\u793A 4 \u5F20\uFF0C\u8D85\u51FA\u672B\u5F20\u8499\u7248 +n -->\n <nz-descriptions-item *ngIf=\"isAccessory(col)\" [nzTitle]=\"col.label\" [nzSpan]=\"getColSpan(col)\">\n <div class=\"hd-detail-form-images\" *ngIf=\"hasImages(col)\">\n <div class=\"hd-detail-form-image-item\"\n *ngFor=\"let image of getDisplayImages(col); let i = index; trackBy: trackByImage\"\n (click)=\"onImageClick(col, image, i, $event)\">\n <img class=\"hd-detail-form-image\"\n [src]=\"getImagePath(image)\"\n [alt]=\"image.name || ('\u56FE\u7247' + (i + 1))\"\n [attr.title]=\"image.name || ('\u56FE\u7247' + (i + 1))\" />\n <span class=\"hd-detail-form-image-mask\"\n *ngIf=\"getMoreCount(col) > 0 && i === getDisplayImages(col).length - 1\">\n +{{ getMoreCount(col) }}\n </span>\n </div>\n </div>\n <span *ngIf=\"!hasImages(col)\">&lt;\u7A7A&gt;</span>\n </nz-descriptions-item>\n <!-- \u666E\u901A\u6587\u672C -->\n <nz-descriptions-item *ngIf=\"!isAccessory(col) && !col.click\" [nzTitle]=\"col.label\" [nzSpan]=\"getColSpan(col)\">\n <span [ngStyle]=\"{'color': col?.color ? col.color : null}\">{{(col.value === '0' || col.value === 0 || col.value\n )? col.value : '&lt;\u7A7A&gt;'}}</span>\n </nz-descriptions-item>\n <!-- \u53EF\u70B9\u51FB -->\n <nz-descriptions-item *ngIf=\"!isAccessory(col) && col.click\" [nzTitle]=\"col.label\" [nzSpan]=\"getColSpan(col)\">\n <span [ngStyle]=\"{'color': col?.color ? col.color : null}\" *ngIf=\"col.clickText\">\n {{(col.value === '0' || col.value === 0 || col.value\n )? col.value : '&lt;\u7A7A&gt;'}}\n <a (click)=\"triggerEvent(col.click || null)\">&nbsp;&nbsp;&nbsp;&nbsp;{{ col.clickText }}</a>\n <a *ngIf=\"col.clickText1\" (click)=\"triggerEvent(col.click1 || null)\">&nbsp;&nbsp;&nbsp;&nbsp;{{ col.clickText1\n }}</a>\n </span>\n <span [ngStyle]=\"{'color': col?.color ? col.color : null}\" *ngIf=\"!col.clickText\">\n <a (click)=\"triggerEvent(col.click || null)\">{{(col.value === '0' || col.value === 0 || col.value\n )? col.value : '&lt;\u7A7A&gt;'}}</a>\n <a *ngIf=\"col.clickText1\" (click)=\"triggerEvent(col.click1 || null)\">&nbsp;&nbsp;&nbsp;&nbsp;{{ col.clickText1\n }}</a>\n </span>\n </nz-descriptions-item>\n </ng-container>\n </nz-descriptions>\n</nz-content>\n\n<nz-modal [(nzVisible)]=\"previewVisible\" [nzTitle]=\"previewTitle\" [nzFooter]=\"null\" [nzWidth]=\"960\"\n [nzContent]=\"previewModalContent\" (nzOnCancel)=\"closePreview()\">\n</nz-modal>\n<ng-template #previewModalContent>\n <div class=\"hd-detail-form-preview\">\n <button type=\"button\" class=\"hd-detail-form-preview-nav hd-detail-form-preview-nav--prev\"\n *ngIf=\"previewImages.length > 1\" [disabled]=\"!canPreviewPrev\" (click)=\"previewPrev($event)\"\n title=\"\u4E0A\u4E00\u5F20\">\n <i nz-icon nzType=\"left\" nzTheme=\"outline\"></i>\n </button>\n <div class=\"hd-detail-form-preview-body\">\n <img *ngIf=\"previewImagePath\" [src]=\"previewImagePath\" [alt]=\"previewTitle\" />\n <div class=\"hd-detail-form-preview-index\" *ngIf=\"previewImages.length > 1\">\n {{ previewIndex + 1 }} / {{ previewImages.length }}\n </div>\n </div>\n <button type=\"button\" class=\"hd-detail-form-preview-nav hd-detail-form-preview-nav--next\"\n *ngIf=\"previewImages.length > 1\" [disabled]=\"!canPreviewNext\" (click)=\"previewNext($event)\"\n title=\"\u4E0B\u4E00\u5F20\">\n <i nz-icon nzType=\"right\" nzTheme=\"outline\"></i>\n </button>\n </div>\n</ng-template>\n",
883
+ styles: ["::ng-deep .common-btn-group>a{font-size:14px;font-weight:400;color:#20b95d!important;white-space:nowrap}::ng-deep .common-btn-group .common-danger-btn:hover{color:#f05b24!important}::ng-deep .common-btn-group>a:hover{color:#20bd62!important}::ng-deep .common-btn-group>a:not(:last-child)::after{content:'';margin:0 2px}::ng-deep .common-billNumber>a{color:#3b77e3}button{box-shadow:unset;text-shadow:unset}::ng-deep .ant-form-item-label>label{color:#4b504e;font-size:14px}::ng-deep .ant-input-number-input{height:32px}::ng-deep .ant-input-number{height:32px}textarea.ant-input{height:auto;min-height:32px}::ng-deep .ant-select-selection--multiple{min-height:32px}::ng-deep .ant-select-selection__rendered>ul>li{height:26px!important;margin-top:3px!important;line-height:26px!important}::ng-deep .ant-advanced-search-form .ant-form-item{margin-bottom:0!important}::ng-deep .ant-select-selection--single{height:32px!important}::ng-deep .ant-input{height:32px}::ng-deep .ant-input[disabled]:hover{border-color:#d9d9d9!important}::ng-deep .ant-select-selection__rendered{line-height:32px!important}::ng-deep .ant-calendar-range-picker-input{text-align:left!important}::ng-deep .ant-calendar-picker{width:100%!important}::ng-deep .ant-row{margin-right:0!important;margin-left:0!important}::ng-deep .ant-col-6{padding-left:12px;padding-right:12px}::ng-deep .ant-col-12{padding-left:12px;padding-right:12px}::ng-deep .ant-col-18{padding-left:12px;padding-right:12px}::ng-deep .ant-col-24{padding-left:12px;padding-right:12px}::ng-deep .ant-alert-info{background-color:#f5f8f6;border:1px solid #cfe3d4}::ng-deep .hd-table-container .ant-table-td-left-sticky,::ng-deep .hd-table-container .ant-table-td-right-sticky,::ng-deep .hd-table-container .ant-table-th-left-sticky,::ng-deep .hd-table-container .ant-table-th-right-sticky{z-index:2;transform:translateZ(0)}::ng-deep .hd-table-container .ant-table-thead>tr>th.ant-table-th-left-sticky,::ng-deep .hd-table-container .ant-table-thead>tr>th.ant-table-th-right-sticky{background:#f5f8f6!important}::ng-deep .hd-table-container .ant-table-tbody>tr>td.ant-table-td-left-sticky,::ng-deep .hd-table-container .ant-table-tbody>tr>td.ant-table-td-right-sticky{background:#fff}::ng-deep .hd-table-container .ant-table-tbody>tr.ant-table-row-hover>td.ant-table-td-left-sticky,::ng-deep .hd-table-container .ant-table-tbody>tr.ant-table-row-hover>td.ant-table-td-right-sticky,::ng-deep .hd-table-container .ant-table-tbody>tr:hover>td.ant-table-td-left-sticky,::ng-deep .hd-table-container .ant-table-tbody>tr:hover>td.ant-table-td-right-sticky{background:#ecf8f1!important}::ng-deep .hd-table-container .ant-table-scroll-position-left .ant-table-td-right-sticky,::ng-deep .hd-table-container .ant-table-scroll-position-left .ant-table-th-right-sticky,::ng-deep .hd-table-container .ant-table-scroll-position-middle .ant-table-td-right-sticky,::ng-deep .hd-table-container .ant-table-scroll-position-middle .ant-table-th-right-sticky,::ng-deep .hd-table-container .ant-table-scroll-position-right .ant-table-td-right-sticky,::ng-deep .hd-table-container .ant-table-scroll-position-right .ant-table-th-right-sticky{box-shadow:none!important}::ng-deep .hd-table-container .ant-table-fixed-right{right:0!important}:host ::ng-deep th{background:#f5f8f6!important;font-weight:700!important;white-space:nowrap;font-size:14px;font-family:PingFangSC-Medium,PingFang SC;color:#2a3634;padding:8px!important;box-sizing:border-box}:host ::ng-deep td{font-weight:400;font-style:normal;font-size:14px;color:#2a3634;text-align:left;white-space:nowrap;padding:8px!important;box-sizing:border-box}::ng-deep .ant-pagination-options{display:inline-flex;align-items:center}::ng-deep .ant-pagination-options .ant-select,::ng-deep .ant-pagination-options .ant-select-selection--single{min-width:100px}::ng-deep .ant-pagination-options-size-changer.ant-select{min-width:100px}::ng-deep .ant-time-picker{width:100%}::ng-deep .cdk-overlay-pane .hd-cascader-menus.ant-cascader-menus>.ant-cascader-menu:only-child{width:-webkit-max-content!important;width:-moz-max-content!important;width:max-content!important;min-width:var(--hd-cascader-menu-min-width,auto);max-width:560px}::ng-deep .cdk-overlay-pane .hd-cascader-menus.ant-cascader-menus>.ant-cascader-menu:only-child .ant-cascader-menu-item{white-space:nowrap}.ant-input-number-disabled,.ant-input[disabled],.ant-select-disabled{color:#4b504e}.hd-detail-form-container{font-size:14px}.hd-detail-form-container ::ng-deep td.ant-descriptions-item{vertical-align:top;padding-top:6px!important;padding-bottom:6px!important;padding-left:0!important;font-size:14px}.hd-detail-form-container ::ng-deep .ant-descriptions-item>span{vertical-align:top}.hd-detail-form-container ::ng-deep .ant-descriptions-item-label{color:#4b504e;font-size:14px;line-height:22px;padding-top:1px;vertical-align:top}.hd-detail-form-container ::ng-deep .ant-descriptions-item-content{word-break:break-all;color:rgba(0,0,0,.85);font-weight:400;font-size:14px;vertical-align:top;line-height:22px}.hd-detail-form-container ::ng-deep a{font-size:14px}.hd-detail-form-container ::ng-deep td{white-space:unset!important}.hd-detail-form-container .hd-detail-form-images{display:flex;flex-wrap:nowrap;align-items:flex-start;gap:6px}.hd-detail-form-container .hd-detail-form-image-item{position:relative;flex-shrink:0;box-sizing:border-box;width:48px;height:48px;overflow:hidden;border:1px solid #e5e6eb;border-radius:4px;cursor:pointer}.hd-detail-form-container .hd-detail-form-image-item:hover{border-color:#20b95d}.hd-detail-form-container .hd-detail-form-image{display:block;width:100%;height:100%;-o-object-fit:cover;object-fit:cover}.hd-detail-form-container .hd-detail-form-image-mask{position:absolute;top:0;right:0;bottom:0;left:0;display:flex;align-items:center;justify-content:center;background:rgba(0,0,0,.45);color:#fff;font-size:14px;line-height:22px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;pointer-events:none}.hd-detail-form-preview{position:relative;display:flex;align-items:center;justify-content:center;min-height:200px;max-height:70vh}.hd-detail-form-preview .hd-detail-form-preview-body{flex:1;min-width:0;text-align:center;max-height:70vh;overflow:auto}.hd-detail-form-preview img{display:inline-block;max-width:100%;max-height:calc(70vh - 32px);-o-object-fit:contain;object-fit:contain}.hd-detail-form-preview .hd-detail-form-preview-index{margin-top:8px;color:#4b504e;font-size:14px;line-height:22px}.hd-detail-form-preview .hd-detail-form-preview-nav{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;width:40px;height:40px;margin:0 8px;padding:0;border:1px solid #e5e6eb;border-radius:50%;background:#fff;color:rgba(0,0,0,.85);cursor:pointer;outline:0}.hd-detail-form-preview .hd-detail-form-preview-nav i{font-size:16px}.hd-detail-form-preview .hd-detail-form-preview-nav:hover:not(:disabled){border-color:#20b95d;color:#20b95d}.hd-detail-form-preview .hd-detail-form-preview-nav:disabled{color:#c9cdd4;cursor:not-allowed;background:#f7f8fa}"]
521
884
  }] }
522
885
  ];
523
886
  /** @nocollapse */
524
887
  HdDetailFormComponent.ctorParameters = function () { return []; };
525
888
  HdDetailFormComponent.propDecorators = {
526
889
  formCols: [{ type: core.Input }],
527
- nzColumn: [{ type: core.Input }]
890
+ nzColumn: [{ type: core.Input }],
891
+ imageClick: [{ type: core.Output }]
528
892
  };
529
893
  return HdDetailFormComponent;
530
894
  }());
@@ -536,6 +900,40 @@
536
900
  * @type {?}
537
901
  */
538
902
  HdDetailFormComponent.prototype.nzColumn;
903
+ /**
904
+ * 附件图片点击回调
905
+ * @type {?}
906
+ */
907
+ HdDetailFormComponent.prototype.imageClick;
908
+ /** @type {?} */
909
+ HdDetailFormComponent.prototype.HdDetailFormFieldType;
910
+ /**
911
+ * 大图预览
912
+ * @type {?}
913
+ */
914
+ HdDetailFormComponent.prototype.previewVisible;
915
+ /** @type {?} */
916
+ HdDetailFormComponent.prototype.previewImagePath;
917
+ /** @type {?} */
918
+ HdDetailFormComponent.prototype.previewTitle;
919
+ /**
920
+ * 当前预览所属字段的图片列表(用于翻页)
921
+ * @type {?}
922
+ */
923
+ HdDetailFormComponent.prototype.previewImages;
924
+ /** @type {?} */
925
+ HdDetailFormComponent.prototype.previewIndex;
926
+ /**
927
+ * 附件字段图片缓存(避免模板里反复 getImageList 导致 *ngFor 重建、点击丢失)
928
+ * @type {?}
929
+ * @private
930
+ */
931
+ HdDetailFormComponent.prototype.imageListCache;
932
+ /**
933
+ * @type {?}
934
+ * @private
935
+ */
936
+ HdDetailFormComponent.prototype.displayListCache;
539
937
  }
540
938
 
541
939
  /**
@@ -547,12 +945,9 @@
547
945
  }
548
946
  HdDetailFormModule.decorators = [
549
947
  { type: core.NgModule, args: [{
550
- imports: [
551
- common.CommonModule,
552
- ngZorroAntd.NgZorroAntdModule
553
- ],
948
+ imports: [common.CommonModule, ngZorroAntd.NgZorroAntdModule],
554
949
  exports: [HdDetailFormComponent],
555
- declarations: [HdDetailFormComponent]
950
+ declarations: [HdDetailFormComponent],
556
951
  },] }
557
952
  ];
558
953
  return HdDetailFormModule;
@@ -727,6 +1122,12 @@
727
1122
  * @type {?}
728
1123
  */
729
1124
  HdOption.prototype.width;
1125
+ /**
1126
+ * 字段类型,默认文本。
1127
+ * `accessory`:附件图片,value 为图片地址 string / string[] 或 { name?, path?/url? }[]
1128
+ * @type {?}
1129
+ */
1130
+ HdOption.prototype.type;
730
1131
  /** @type {?} */
731
1132
  HdOption.prototype.clickText;
732
1133
  /** @type {?} */
@@ -1984,19 +2385,25 @@
1984
2385
  this.virtualScrollActive !== useVirtual;
1985
2386
  this.virtualScrollActive = useVirtual;
1986
2387
  if (forceRemount || modeChanged) {
1987
- this.showTable = false;
1988
- this.cdr.markForCheck();
2388
+ // 延后销毁/重建,避免当前 CD 周期内 ngIf 变更触发 ExpressionChanged
1989
2389
  setTimeout((/**
1990
2390
  * @return {?}
1991
2391
  */
1992
2392
  function () {
1993
- _this.showTable = true;
2393
+ _this.showTable = false;
1994
2394
  _this.cdr.markForCheck();
1995
2395
  setTimeout((/**
1996
2396
  * @return {?}
1997
2397
  */
1998
2398
  function () {
1999
- _this.afterTableRender(useVirtual);
2399
+ _this.showTable = true;
2400
+ _this.cdr.markForCheck();
2401
+ setTimeout((/**
2402
+ * @return {?}
2403
+ */
2404
+ function () {
2405
+ _this.afterTableRender(useVirtual);
2406
+ }));
2000
2407
  }));
2001
2408
  }));
2002
2409
  return;
@@ -10910,24 +11317,6 @@
10910
11317
  TableTotalOption.prototype.insertName;
10911
11318
  }
10912
11319
 
10913
- /**
10914
- * @fileoverview added by tsickle
10915
- * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
10916
- */
10917
- var HdDetailFormService = /** @class */ (function () {
10918
- function HdDetailFormService() {
10919
- }
10920
- HdDetailFormService.decorators = [
10921
- { type: core.Injectable, args: [{
10922
- providedIn: 'root'
10923
- },] }
10924
- ];
10925
- /** @nocollapse */
10926
- HdDetailFormService.ctorParameters = function () { return []; };
10927
- /** @nocollapse */ HdDetailFormService.ngInjectableDef = core.ɵɵdefineInjectable({ factory: function HdDetailFormService_Factory() { return new HdDetailFormService(); }, token: HdDetailFormService, providedIn: "root" });
10928
- return HdDetailFormService;
10929
- }());
10930
-
10931
11320
  /**
10932
11321
  * @fileoverview added by tsickle
10933
11322
  * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
@@ -11381,6 +11770,7 @@
11381
11770
  exports.HdAccessoryListComponent = HdAccessoryListComponent;
11382
11771
  exports.HdButtonService = HdButtonService;
11383
11772
  exports.HdCurrentTableComponent = HdCurrentTableComponent;
11773
+ exports.HdDetailFormFieldType = HdDetailFormFieldType;
11384
11774
  exports.HdDetailFormService = HdDetailFormService;
11385
11775
  exports.HdFilterService = HdFilterService;
11386
11776
  exports.HdFormLinesService = HdFormLinesService;