fantasy-ngzorro 2.1.63 → 2.1.65

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
@@ -42,6 +42,8 @@
42
42
  | — | 2026-9-22 | `hd-tip` 支持右侧展开/收起(`showCollapse` / `[(expanded)]`),暴露 `expand` / `collapse` / `toggle` 供父组件控制其它区块 |
43
43
  | — | 2026-9-22 | `hd-form-lines` 勾选提示改为 `tableTotal` 插槽(同 hd-table),组件内不再默认渲染已选中块 |
44
44
  | — | 2026-9-22 | `hd-table` / `hd-detail-form` 字段值后支持编辑笔图标(`editable` + `edit` 回调,图标对齐 Figma) |
45
+ | — | 2026-9-24 | `hd-detail-lines`:补 `scroll.y` 后重建表格并同步表头横滚,修复列头不跟随左右滚动 |
46
+ | — | 2026-9-24 | `hd-detail-lines` / `hd-detail-lines-page`:自动或仅传 `scroll.x` 时补 `scroll.y`,修复窄屏下无法纵向滚动 |
45
47
  | — | 2026-9-22 | `hd-table` 支持 `pagination` / `frontPagination`:全量 `content` 可「不分页展示」或「前端切片分页」,列表默认仍为服务端分页 |
46
48
  | — | 2026-9-21 | hd-table 列 `color` 支持函数,按行给某一个字段标红 |
47
49
  | — | 2026-9-20 | hd-detail-form 附件图片:最多展示 4 张,超出末张蒙版 `+n`;弹窗预览支持左右翻页 |
@@ -709,7 +711,7 @@ formCols: HdOption[] = [
709
711
  | 参数 | 类型 | 默认值 | 说明 |
710
712
  | ---- | ---- | ------ | ---- |
711
713
  | lines | any[] | — | 明细数据 |
712
- | scroll | object | { x: '1px' } | 横向滚动 |
714
+ | scroll | object | 自动 | 不传则按列宽自动算横向滚动;有 `x` 时自动补 `y`(`calc(100vh - …)`),避免窄屏无法纵向滚动 |
713
715
  | showSearch | boolean | false | 行内搜索 |
714
716
  | searchFields | string[] | [] | 搜索字段,空则搜全部字段 |
715
717
  | hdFrontPagination | boolean | false | 前端分页 |
@@ -1553,13 +1553,28 @@
1553
1553
  */
1554
1554
  this.isFilterData = false;
1555
1555
  this.storeFormLinesData = []; // 缓存的总的列表数据
1556
+ // 缓存的总的列表数据
1557
+ /**
1558
+ * 控制 nz-table 重建:scroll.y 从无到有时必须重建,否则表头不跟横滚
1559
+ */
1560
+ this.showTable = true;
1561
+ this.bodyScrollListener = null;
1556
1562
  }
1557
1563
  Object.defineProperty(HdDetailLinesComponent.prototype, "effectiveScroll", {
1558
1564
  get: /**
1559
1565
  * @return {?}
1560
1566
  */
1561
1567
  function () {
1562
- return this.scroll != null ? this.scroll : this.tableScroll;
1568
+ /** @type {?} */
1569
+ var base = this.scroll != null ? this.scroll : this.tableScroll;
1570
+ if (!base) {
1571
+ return null;
1572
+ }
1573
+ // 仅有 x 无 y 时补 y,避免窄屏 / 手动传 scroll.x 时无法纵向滚动
1574
+ if (base.x && !base.y) {
1575
+ return { x: base.x, y: this.getAutoScrollY() };
1576
+ }
1577
+ return base;
1563
1578
  },
1564
1579
  enumerable: true,
1565
1580
  configurable: true
@@ -1585,6 +1600,15 @@
1585
1600
  function () {
1586
1601
  this.scheduleSyncHorizontalScroll();
1587
1602
  };
1603
+ /**
1604
+ * @return {?}
1605
+ */
1606
+ HdDetailLinesComponent.prototype.ngOnDestroy = /**
1607
+ * @return {?}
1608
+ */
1609
+ function () {
1610
+ this.unbindHeaderBodyScrollSync();
1611
+ };
1588
1612
  /**
1589
1613
  * @param {?} changes
1590
1614
  * @return {?}
@@ -1624,6 +1648,11 @@
1624
1648
  var _this = this;
1625
1649
  if (retry === void 0) { retry = 0; }
1626
1650
  if (this.scroll != null) {
1651
+ // 外部传了 scroll:首屏就带 y 时仍需绑一次兜底同步
1652
+ setTimeout((/**
1653
+ * @return {?}
1654
+ */
1655
+ function () { return _this.bindHeaderBodyScrollSync(); }));
1627
1656
  return;
1628
1657
  }
1629
1658
  /** @type {?} */
@@ -1644,6 +1673,27 @@
1644
1673
  }
1645
1674
  }), delay);
1646
1675
  };
1676
+ /**
1677
+ * 开启 scroll.x 后 ant-table body 会变成 overflow:scroll 容器,
1678
+ * 若不设 scroll.y,内容再高也不会表内纵向滚动,且滚轮无法冒泡到页面。
1679
+ */
1680
+ /**
1681
+ * 开启 scroll.x 后 ant-table body 会变成 overflow:scroll 容器,
1682
+ * 若不设 scroll.y,内容再高也不会表内纵向滚动,且滚轮无法冒泡到页面。
1683
+ * @private
1684
+ * @return {?}
1685
+ */
1686
+ HdDetailLinesComponent.prototype.getAutoScrollY = /**
1687
+ * 开启 scroll.x 后 ant-table body 会变成 overflow:scroll 容器,
1688
+ * 若不设 scroll.y,内容再高也不会表内纵向滚动,且滚轮无法冒泡到页面。
1689
+ * @private
1690
+ * @return {?}
1691
+ */
1692
+ function () {
1693
+ /** @type {?} */
1694
+ var offset = this.showSearch ? 320 : 280;
1695
+ return "calc(100vh - " + offset + "px)";
1696
+ };
1647
1697
  /**
1648
1698
  * @private
1649
1699
  * @return {?}
@@ -1653,6 +1703,7 @@
1653
1703
  * @return {?}
1654
1704
  */
1655
1705
  function () {
1706
+ var _this = this;
1656
1707
  if (this.scroll != null) {
1657
1708
  return;
1658
1709
  }
@@ -1662,11 +1713,122 @@
1662
1713
  var nextScroll = resolveAutoTableScroll(this.nzTableComponent, hasData);
1663
1714
  /** @type {?} */
1664
1715
  var nextX = nextScroll ? nextScroll.x : null;
1665
- if (this.tableScroll && this.tableScroll.x === nextX) {
1716
+ // 有横向滚动时必须带 y,否则窄屏下无法纵向滚动
1717
+ /** @type {?} */
1718
+ var nextY = nextX ? this.getAutoScrollY() : null;
1719
+ /** @type {?} */
1720
+ var prevHasY = !!(this.tableScroll && this.tableScroll.y);
1721
+ /** @type {?} */
1722
+ var nextHasY = !!nextY;
1723
+ if (this.tableScroll &&
1724
+ this.tableScroll.x === nextX &&
1725
+ this.tableScroll.y === nextY) {
1726
+ return;
1727
+ }
1728
+ this.tableScroll = nextX
1729
+ ? { x: nextX, y: nextY }
1730
+ : null;
1731
+ // ng-zorro 只在 AfterViewInit 绑一次 header/body 横滚同步;
1732
+ // 运行中从无 y 变为有 y 会丢监听,表现为列头不跟着横滚 → 必须重建表格
1733
+ if (prevHasY !== nextHasY) {
1734
+ this.remountTable();
1666
1735
  return;
1667
1736
  }
1668
- this.tableScroll = nextScroll;
1669
1737
  this.cdr.markForCheck();
1738
+ setTimeout((/**
1739
+ * @return {?}
1740
+ */
1741
+ function () { return _this.bindHeaderBodyScrollSync(); }));
1742
+ };
1743
+ /** 重建 nz-table,让 header/body 滚动同步在 AfterViewInit 重新绑定 */
1744
+ /**
1745
+ * 重建 nz-table,让 header/body 滚动同步在 AfterViewInit 重新绑定
1746
+ * @private
1747
+ * @return {?}
1748
+ */
1749
+ HdDetailLinesComponent.prototype.remountTable = /**
1750
+ * 重建 nz-table,让 header/body 滚动同步在 AfterViewInit 重新绑定
1751
+ * @private
1752
+ * @return {?}
1753
+ */
1754
+ function () {
1755
+ var _this = this;
1756
+ this.unbindHeaderBodyScrollSync();
1757
+ setTimeout((/**
1758
+ * @return {?}
1759
+ */
1760
+ function () {
1761
+ _this.showTable = false;
1762
+ _this.cdr.markForCheck();
1763
+ setTimeout((/**
1764
+ * @return {?}
1765
+ */
1766
+ function () {
1767
+ _this.showTable = true;
1768
+ _this.cdr.markForCheck();
1769
+ setTimeout((/**
1770
+ * @return {?}
1771
+ */
1772
+ function () { return _this.bindHeaderBodyScrollSync(); }));
1773
+ }));
1774
+ }));
1775
+ };
1776
+ /** 表体横滚时同步表头(兜底 ng-zorro 监听丢失) */
1777
+ /**
1778
+ * 表体横滚时同步表头(兜底 ng-zorro 监听丢失)
1779
+ * @private
1780
+ * @return {?}
1781
+ */
1782
+ HdDetailLinesComponent.prototype.bindHeaderBodyScrollSync = /**
1783
+ * 表体横滚时同步表头(兜底 ng-zorro 监听丢失)
1784
+ * @private
1785
+ * @return {?}
1786
+ */
1787
+ function () {
1788
+ this.unbindHeaderBodyScrollSync();
1789
+ if (!this.nzTableComponent) {
1790
+ return;
1791
+ }
1792
+ /** @type {?} */
1793
+ var nzTable = (/** @type {?} */ (this.nzTableComponent));
1794
+ /** @type {?} */
1795
+ var header = (/** @type {?} */ (nzTable.tableHeaderNativeElement));
1796
+ /** @type {?} */
1797
+ var body = (/** @type {?} */ (nzTable.mixTableBodyNativeElement));
1798
+ if (!header || !body) {
1799
+ return;
1800
+ }
1801
+ this.bodyScrollListener = (/**
1802
+ * @return {?}
1803
+ */
1804
+ function () {
1805
+ if (header.scrollLeft !== body.scrollLeft) {
1806
+ header.scrollLeft = body.scrollLeft;
1807
+ }
1808
+ });
1809
+ body.addEventListener("scroll", this.bodyScrollListener);
1810
+ this.bodyScrollListener();
1811
+ };
1812
+ /**
1813
+ * @private
1814
+ * @return {?}
1815
+ */
1816
+ HdDetailLinesComponent.prototype.unbindHeaderBodyScrollSync = /**
1817
+ * @private
1818
+ * @return {?}
1819
+ */
1820
+ function () {
1821
+ if (!this.bodyScrollListener || !this.nzTableComponent) {
1822
+ this.bodyScrollListener = null;
1823
+ return;
1824
+ }
1825
+ /** @type {?} */
1826
+ var body = (/** @type {?} */ (((/** @type {?} */ (this.nzTableComponent)))
1827
+ .mixTableBodyNativeElement));
1828
+ if (body) {
1829
+ body.removeEventListener("scroll", this.bodyScrollListener);
1830
+ }
1831
+ this.bodyScrollListener = null;
1670
1832
  };
1671
1833
  /**
1672
1834
  * @private
@@ -2027,7 +2189,7 @@
2027
2189
  HdDetailLinesComponent.decorators = [
2028
2190
  { type: core.Component, args: [{
2029
2191
  selector: "hd-detail-lines",
2030
- template: "<ng-container>\n <hd-button-group *ngIf=\"showSearch\">\n <ng-template #buttonGroupLeft>\n <nz-input-group [nzSuffix]=\"suffixIconSearch\">\n <input type=\"text\" nz-input (keyup.enter)=\"searchLines()\" placeholder=\"\u8BF7\u8F93\u5165\u5185\u5BB9\u641C\u7D22\" style=\"width: 300px;\"\n [(ngModel)]=\"filterStr\" />\n </nz-input-group>\n <ng-template #suffixIconSearch>\n <i nz-icon nzType=\"search\" (click)=\"searchLines()\"></i>\n </ng-template>\n </ng-template>\n </hd-button-group>\n\n <hd-space *ngIf=\"showSearch\" background=\"transparent\" type=\"row\" size=\"16\"></hd-space>\n\n <nz-table #hdTable [nzScroll]=\"effectiveScroll\" class=\"hd-table-container\" nzShowSizeChanger\n [nzFrontPagination]=\"hdFrontPagination\" [nzShowQuickJumper]=\"hdFrontPagination\" [nzShowTotal]=\"tableTotalTemplate\"\n nzSize=\"middle\" [nzData]=\"displayLines\" [nzLoading]=\"tableLoading\" [(nzPageSize)]=\"tablePageSize\"\n [nzPageSizeOptions]=\"[ 10, 50, 100, 200, 500, 1000 ]\"\n (nzCurrentPageDataChange)=\"showSelected ? currentPageDataChange($event) : null\">\n <thead>\n <tr>\n <th *ngIf=\"showSelected\" nzWidth=\"40px\" nzLeft=\"0px\" nzShowCheckbox [(nzChecked)]=\"isAllDisplayDataChecked\"\n [nzIndeterminate]=\"isIndeterminate\" (nzCheckedChange)=\"checkAll($event)\"></th>\n <ng-container *ngTemplateOutlet=\"detailLineHead\"></ng-container>\n </tr>\n </thead>\n <tbody *ngIf=\"!allowDrop;else allowDropTemplate\">\n <tr *ngFor=\"let data of hdTable.data;index as i\" [class.hd-table-row-invalid]=\"isInvalidRow(data)\">\n <td *ngIf=\"showSelected\" nzWidth=\"40px\" nzLeft=\"0px\" nzShowCheckbox\n [nzChecked]=\"mapOfCheckedId[data[selectField]]\" [nzDisabled]=\"isSelectDisabled(data)\"\n (nzCheckedChange)=\"refreshStatus($event, data)\"></td>\n <ng-container *ngTemplateOutlet=\"detailLineBody;context:{$implicit: data, index: i}\"></ng-container>\n </tr>\n <!-- \u5408\u8BA1\u533A\u57DF -->\n <tr *ngIf=\"showTotal\" class=\"hd-table-total\">\n <td *ngIf=\"showSelected\"></td>\n <td>\u5408\u8BA1</td>\n <ng-container *ngFor=\"let totalOption of totalOptionList\">\n <td *ngIf=\"!totalOption.isHide\" [nzAlign]=\"totalOption.align ? totalOption.align : 'left'\">{{\n (totalOption.value || totalOption.value ===\n 0) ? (((totalOption.value % 1 === 0) && !totalOption.showDecimal ) ? totalOption.value :\n LodashRound(totalOption.value, totalOption.preserveNumber).toFixed(totalOption.preserveNumber)) : '' }} </td>\n </ng-container>\n </tr>\n </tbody>\n <ng-template #allowDropTemplate>\n <tbody cdkDropList (cdkDropListDropped)=\"drop($event)\">\n <tr *ngFor=\"let data of hdTable.data;index as i\" cdkDrag [class.hd-table-row-invalid]=\"isInvalidRow(data)\">\n <td *ngIf=\"showSelected\" nzWidth=\"40px\" nzLeft=\"0px\" nzShowCheckbox\n [nzChecked]=\"mapOfCheckedId[data[selectField]]\" [nzDisabled]=\"isSelectDisabled(data)\"\n (nzCheckedChange)=\"refreshStatus($event, data)\"></td>\n <ng-container *ngTemplateOutlet=\"detailLineBody;context:{$implicit: data, index: i}\"></ng-container>\n </tr>\n <!-- \u5408\u8BA1\u533A\u57DF -->\n <tr *ngIf=\"showTotal\" class=\"hd-table-total\">\n <td *ngIf=\"showSelected\"></td>\n <td>\u5408\u8BA1</td>\n <ng-container *ngFor=\"let totalOption of totalOptionList\">\n <td *ngIf=\"!totalOption.isHide\" [nzAlign]=\"totalOption.align ? totalOption.align : 'left'\">{{\n (totalOption.value || totalOption.value\n === 0) ? (((totalOption.value % 1 === 0) && !totalOption.showDecimal ) ? totalOption.value :\n LodashRound(totalOption.value, totalOption.preserveNumber).toFixed(totalOption.preserveNumber)) : '' }} </td>\n </ng-container>\n </tr>\n </tbody>\n </ng-template>\n <ng-template #tableTotalTemplate>\n \u5171 {{displayLines.length}} \u6761\u6570\u636E\n </ng-template>\n </nz-table>\n</ng-container>\n",
2192
+ template: "<ng-container>\n <hd-button-group *ngIf=\"showSearch\">\n <ng-template #buttonGroupLeft>\n <nz-input-group [nzSuffix]=\"suffixIconSearch\">\n <input type=\"text\" nz-input (keyup.enter)=\"searchLines()\" placeholder=\"\u8BF7\u8F93\u5165\u5185\u5BB9\u641C\u7D22\" style=\"width: 300px;\"\n [(ngModel)]=\"filterStr\" />\n </nz-input-group>\n <ng-template #suffixIconSearch>\n <i nz-icon nzType=\"search\" (click)=\"searchLines()\"></i>\n </ng-template>\n </ng-template>\n </hd-button-group>\n\n <hd-space *ngIf=\"showSearch\" background=\"transparent\" type=\"row\" size=\"16\"></hd-space>\n\n <nz-table *ngIf=\"showTable\" #hdTable [nzScroll]=\"effectiveScroll\" class=\"hd-table-container\" nzShowSizeChanger\n [nzFrontPagination]=\"hdFrontPagination\" [nzShowQuickJumper]=\"hdFrontPagination\" [nzShowTotal]=\"tableTotalTemplate\"\n nzSize=\"middle\" [nzData]=\"displayLines\" [nzLoading]=\"tableLoading\" [(nzPageSize)]=\"tablePageSize\"\n [nzPageSizeOptions]=\"[ 10, 50, 100, 200, 500, 1000 ]\"\n (nzCurrentPageDataChange)=\"showSelected ? currentPageDataChange($event) : null\">\n <thead>\n <tr>\n <th *ngIf=\"showSelected\" nzWidth=\"40px\" nzLeft=\"0px\" nzShowCheckbox [(nzChecked)]=\"isAllDisplayDataChecked\"\n [nzIndeterminate]=\"isIndeterminate\" (nzCheckedChange)=\"checkAll($event)\"></th>\n <ng-container *ngTemplateOutlet=\"detailLineHead\"></ng-container>\n </tr>\n </thead>\n <tbody *ngIf=\"!allowDrop;else allowDropTemplate\">\n <tr *ngFor=\"let data of hdTable.data;index as i\" [class.hd-table-row-invalid]=\"isInvalidRow(data)\">\n <td *ngIf=\"showSelected\" nzWidth=\"40px\" nzLeft=\"0px\" nzShowCheckbox\n [nzChecked]=\"mapOfCheckedId[data[selectField]]\" [nzDisabled]=\"isSelectDisabled(data)\"\n (nzCheckedChange)=\"refreshStatus($event, data)\"></td>\n <ng-container *ngTemplateOutlet=\"detailLineBody;context:{$implicit: data, index: i}\"></ng-container>\n </tr>\n <!-- \u5408\u8BA1\u533A\u57DF -->\n <tr *ngIf=\"showTotal\" class=\"hd-table-total\">\n <td *ngIf=\"showSelected\"></td>\n <td>\u5408\u8BA1</td>\n <ng-container *ngFor=\"let totalOption of totalOptionList\">\n <td *ngIf=\"!totalOption.isHide\" [nzAlign]=\"totalOption.align ? totalOption.align : 'left'\">{{\n (totalOption.value || totalOption.value ===\n 0) ? (((totalOption.value % 1 === 0) && !totalOption.showDecimal ) ? totalOption.value :\n LodashRound(totalOption.value, totalOption.preserveNumber).toFixed(totalOption.preserveNumber)) : '' }} </td>\n </ng-container>\n </tr>\n </tbody>\n <ng-template #allowDropTemplate>\n <tbody cdkDropList (cdkDropListDropped)=\"drop($event)\">\n <tr *ngFor=\"let data of hdTable.data;index as i\" cdkDrag [class.hd-table-row-invalid]=\"isInvalidRow(data)\">\n <td *ngIf=\"showSelected\" nzWidth=\"40px\" nzLeft=\"0px\" nzShowCheckbox\n [nzChecked]=\"mapOfCheckedId[data[selectField]]\" [nzDisabled]=\"isSelectDisabled(data)\"\n (nzCheckedChange)=\"refreshStatus($event, data)\"></td>\n <ng-container *ngTemplateOutlet=\"detailLineBody;context:{$implicit: data, index: i}\"></ng-container>\n </tr>\n <!-- \u5408\u8BA1\u533A\u57DF -->\n <tr *ngIf=\"showTotal\" class=\"hd-table-total\">\n <td *ngIf=\"showSelected\"></td>\n <td>\u5408\u8BA1</td>\n <ng-container *ngFor=\"let totalOption of totalOptionList\">\n <td *ngIf=\"!totalOption.isHide\" [nzAlign]=\"totalOption.align ? totalOption.align : 'left'\">{{\n (totalOption.value || totalOption.value\n === 0) ? (((totalOption.value % 1 === 0) && !totalOption.showDecimal ) ? totalOption.value :\n LodashRound(totalOption.value, totalOption.preserveNumber).toFixed(totalOption.preserveNumber)) : '' }} </td>\n </ng-container>\n </tr>\n </tbody>\n </ng-template>\n <ng-template #tableTotalTemplate>\n \u5171 {{displayLines.length}} \u6761\u6570\u636E\n </ng-template>\n </nz-table>\n</ng-container>\n",
2031
2193
  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-table-container ::ng-deep .ant-pagination-options-quick-jumper input{border-radius:2px;border:1px solid #d9d9d9}.hd-table-container ::ng-deep .ant-pagination-options .ant-select-selection{border-radius:2px}.hd-table-container ::ng-deep .ant-table-thead>tr>th{border-bottom:1px solid #ecf1ed}.hd-table-container ::ng-deep .ant-table-tbody>tr>td{border-bottom:1px solid #ecf1ed}.hd-table-container ::ng-deep .ant-table-tbody>tr.hd-table-row-invalid.ant-table-row-hover>td,.hd-table-container ::ng-deep .ant-table-tbody>tr.hd-table-row-invalid.ant-table-row-hover>td.ant-table-td-left-sticky,.hd-table-container ::ng-deep .ant-table-tbody>tr.hd-table-row-invalid.ant-table-row-hover>td.ant-table-td-right-sticky,.hd-table-container ::ng-deep .ant-table-tbody>tr.hd-table-row-invalid:hover>td,.hd-table-container ::ng-deep .ant-table-tbody>tr.hd-table-row-invalid:hover>td.ant-table-td-left-sticky,.hd-table-container ::ng-deep .ant-table-tbody>tr.hd-table-row-invalid:hover>td.ant-table-td-right-sticky,.hd-table-container ::ng-deep .ant-table-tbody>tr.hd-table-row-invalid>td,.hd-table-container ::ng-deep .ant-table-tbody>tr.hd-table-row-invalid>td.ant-table-td-left-sticky,.hd-table-container ::ng-deep .ant-table-tbody>tr.hd-table-row-invalid>td.ant-table-td-right-sticky{background:#f7f8fa!important;color:#868a9c!important}.hd-table-container ::ng-deep .ant-table-tbody>tr.hd-table-row-invalid .common-btn-group>a{color:#20b95d!important}.hd-table-container ::ng-deep .ant-table-tbody>tr.hd-table-row-invalid .common-btn-group>a:hover{color:#20bd62!important}.hd-table-container ::ng-deep .ant-table-tbody>tr.hd-table-row-invalid .common-btn-group .common-danger-btn:hover{color:#f05b24!important}.hd-table-container ::ng-deep .ant-table-tbody>tr.hd-table-row-invalid .hd-table-cell-value>a,.hd-table-container ::ng-deep .ant-table-tbody>tr.hd-table-row-invalid>td>a{color:#20b95d}.hd-table-container ::ng-deep .ant-table-tbody>tr.hd-table-row-invalid .common-billNumber>a{color:#3b77e3}.hd-table-container ::ng-deep .ant-table-tbody>tr.hd-table-row-invalid .hd-status-text{color:#868a9c!important}.hd-table-container ::ng-deep .hd-table-total>td{border:0!important}"]
2032
2194
  }] }
2033
2195
  ];
@@ -2162,6 +2324,16 @@
2162
2324
  HdDetailLinesComponent.prototype.isFilterData;
2163
2325
  /** @type {?} */
2164
2326
  HdDetailLinesComponent.prototype.storeFormLinesData;
2327
+ /**
2328
+ * 控制 nz-table 重建:scroll.y 从无到有时必须重建,否则表头不跟横滚
2329
+ * @type {?}
2330
+ */
2331
+ HdDetailLinesComponent.prototype.showTable;
2332
+ /**
2333
+ * @type {?}
2334
+ * @private
2335
+ */
2336
+ HdDetailLinesComponent.prototype.bodyScrollListener;
2165
2337
  /**
2166
2338
  * @type {?}
2167
2339
  * @private
@@ -2319,16 +2491,16 @@
2319
2491
  configurable: true
2320
2492
  });
2321
2493
  Object.defineProperty(HdDetailLinesPageComponent.prototype, "resolvedScroll", {
2322
- /** 虚拟滚动时保证有 scroll.y,否则 nzVirtualScroll 无效 */
2494
+ /** 虚拟滚动 / 仅有 x 时保证有 scroll.y,否则窄屏无法纵向滚动 */
2323
2495
  get: /**
2324
- * 虚拟滚动时保证有 scroll.y,否则 nzVirtualScroll 无效
2496
+ * 虚拟滚动 / 仅有 x 时保证有 scroll.y,否则窄屏无法纵向滚动
2325
2497
  * @return {?}
2326
2498
  */
2327
2499
  function () {
2328
2500
  /** @type {?} */
2329
2501
  var base = this.effectiveScroll ? __assign({}, this.effectiveScroll) : {};
2330
- if (this.useVirtualScroll && !base.y) {
2331
- base.y = "calc(100vh - 200px)";
2502
+ if ((this.useVirtualScroll || base.x) && !base.y) {
2503
+ base.y = this.getAutoScrollY();
2332
2504
  }
2333
2505
  return base;
2334
2506
  },
@@ -2546,6 +2718,25 @@
2546
2718
  }
2547
2719
  }), delay);
2548
2720
  };
2721
+ /**
2722
+ * 开启 scroll.x 后 ant-table body 会变成 overflow:scroll 容器,
2723
+ * 若不设 scroll.y,窄屏下滚轮无法纵向滚动。
2724
+ */
2725
+ /**
2726
+ * 开启 scroll.x 后 ant-table body 会变成 overflow:scroll 容器,
2727
+ * 若不设 scroll.y,窄屏下滚轮无法纵向滚动。
2728
+ * @private
2729
+ * @return {?}
2730
+ */
2731
+ HdDetailLinesPageComponent.prototype.getAutoScrollY = /**
2732
+ * 开启 scroll.x 后 ant-table body 会变成 overflow:scroll 容器,
2733
+ * 若不设 scroll.y,窄屏下滚轮无法纵向滚动。
2734
+ * @private
2735
+ * @return {?}
2736
+ */
2737
+ function () {
2738
+ return "calc(100vh - 280px)";
2739
+ };
2549
2740
  /**
2550
2741
  * @private
2551
2742
  * @return {?}
@@ -2564,18 +2755,28 @@
2564
2755
  var nextScroll = resolveAutoTableScroll(this.nzTableComponent, hasData);
2565
2756
  /** @type {?} */
2566
2757
  var nextX = nextScroll ? nextScroll.x : null;
2758
+ // 父级已指定 y(如虚拟滚动)优先保留;否则有 x 时自动补 y
2567
2759
  /** @type {?} */
2568
2760
  var currentY = this.tableScroll ? this.tableScroll.y : null;
2761
+ /** @type {?} */
2762
+ var nextY = currentY || (nextX ? this.getAutoScrollY() : null);
2763
+ /** @type {?} */
2764
+ var prevHasY = !!(this.tableScroll && this.tableScroll.y);
2765
+ /** @type {?} */
2766
+ var nextHasY = !!nextY;
2569
2767
  if (this.tableScroll &&
2570
2768
  this.tableScroll.x === nextX &&
2571
- this.tableScroll.y === currentY) {
2769
+ this.tableScroll.y === nextY) {
2770
+ return;
2771
+ }
2772
+ this.tableScroll = nextX || nextY
2773
+ ? { x: nextX, y: nextY }
2774
+ : null;
2775
+ // y 从无到有必须重建,否则表头不跟横滚
2776
+ if (prevHasY !== nextHasY) {
2777
+ this.applyTableScrollMode(true);
2572
2778
  return;
2573
2779
  }
2574
- this.tableScroll = nextScroll
2575
- ? { x: nextScroll.x, y: currentY }
2576
- : currentY
2577
- ? { y: currentY }
2578
- : null;
2579
2780
  this.cdr.markForCheck();
2580
2781
  };
2581
2782
  Object.defineProperty(HdDetailLinesPageComponent.prototype, "displayLines", {