import { ChangeDetectorRef, ElementRef, EventEmitter, OnDestroy, OnInit, SimpleChange, TemplateRef } from "@angular/core"; import { NzFormatBeforeDropEvent, NzFormatEmitEvent } from "ng-zorro-antd/core"; import { NzResizeEvent } from "ng-zorro-antd/resizable"; import { NzTableComponent } from "ng-zorro-antd/table"; import { Observable } from "rxjs"; import { Page } from "../model/common-type"; import { CommonSessionService } from "../service/common-session.service"; import { TotalOption } from "../hd-detail-lines/hd-detail-lines.service"; import { HdTableCellChange, HdTableColumn, OperateBtn, TableCacheOption, TreeGrid } from "./hd-table.service"; export declare class HdTableComponent implements OnInit, OnDestroy { private hostEl; private cdr; private commonSessionService; uuid: string; tableCols: Array; tableData: Page; showSelected: boolean; showOperateColWarpButton: boolean; virtualScroll: boolean; /** 手动指定行高;不传则在首屏渲染后自动测量 */ virtualItemSize: number; selectField: string; /** * 行勾选禁用字段名。定义后取当前行该字段: * 为 true 时禁用该行勾选(全选也会跳过)。 */ selectDisabledField: string; /** * 行失效字段名。定义后取当前行该字段: * 为 true 时整行背景色为 #F7F8FA。 */ rowInvalidField: string; showTableTotal: boolean; tableTotalOption: Array; /** * 合计列总数(含序号列,与 hd-detail-lines 一致); * 不传则按当前可见数据列数 + 1(序号)推算。 */ columnsNumber: number | string; sortEvent: EventEmitter<{}>; selectEvent: EventEmitter<{}>; tableSearchEvent: EventEmitter<{}>; /** 行内编辑变更(已写回行对象;previous* 供接口失败回滚) */ cellChange: EventEmitter; tableLoading: boolean; /** 是否显示分页;false 时一次展示 tableData.content 全部行 */ pagination: boolean; /** * 是否前端分页(对 content 全量切片)。 * true:翻页不触发 tableSearchEvent,适合详情全量数据; * false(默认):服务端分页,翻页触发查询(现有列表行为)。 * 与 pagination=false 同时用时以不分页为准。 */ frontPagination: boolean; tablePageIndex: number; tablePageSize: number; isFirstEntrySearch: boolean; isCrossPageSelect: boolean; tablePageIndexChange: EventEmitter; tablePageSizeChange: EventEmitter; tablePageSizeChangeEvent: EventEmitter; tableTotal: TemplateRef; tableLeftButton: TemplateRef; tableRightButton: TemplateRef; scroll: any; isAllDisplayDataChecked: boolean; isIndeterminate: boolean; listOfDisplayData: any[]; listOfAllData: any[]; listOfSelection: Array | TemplateRef; mapOfCheckedId: { [key: string]: boolean; }; mapOfCheckList: { [key: string]: any; }; tableTotalOptionList: any[]; tableCacheOption: TableCacheOption; userSession: any; tableColsCache: Array; showTable: boolean; selectColListNodes: Array; selectColListNodesCache: Array; showListNodes: boolean; isDropdownVisible: boolean; nowListNodes: Array; hideListNodes: Array; cancelNowListNodes: Array; cancelHideListNodes: Array; showDetail: boolean; localforage: any; localtionTmp: string; isFirstEntrySearchLocal: boolean; isCrossPageSelectLocal: boolean; /** 自动测量前的兜底行高,测量完成后会更新 */ measuredVirtualItemSize: number; /** 记录当前是否处于虚拟滚动模式,用于切换 pageSize 时重建表格 */ private virtualScrollActive; /** 可见列总宽,用于判断是否需要横向滚动 */ /** 列宽合计(含勾选/序号),footer 表宽与横向 scroll 共用 */ tableColWidthTotal: number; /** 数据更新后待复位纵向滚动位置 */ private pendingResetScrollTop; /** 当前排序,表格重建后用于恢复表头排序态 */ private currentSortKey; private currentSortValue; nzTableComponent: NzTableComponent; private totalFooterScrollBoundBody; private totalFooterScrollHandler; private totalFooterSyncRetry; /** 表体有竖滚条时合计 footer 才预留右侧滚动条槽 */ totalFooterNeedYGutter: boolean; /** 视口/容器尺寸变化时重算 scroll.x 与合计对齐 */ private viewportResizeTimer; private boundOnViewportResize; private hostResizeObserver; constructor(hostEl: ElementRef, cdr: ChangeDetectorRef, commonSessionService: CommonSessionService); ngOnDestroy(): void; ngOnInit(): void; ngOnChanges(changes: SimpleChange): void; /** 是否走前端分页(对 content 切片,不请求后端) */ readonly useFrontPagination: boolean; deleteHideItem(): void; sort(sort: { key: string; value: string; }): void; getColSort(col: HdTableColumn): string | null; toggleShowDetail(): void; readonly effectiveVirtualItemSize: number; /** * 纵向可用高度扣减:按钮区/合计/分页等固定占位。 * 必须与 dealScroll / presetScrollBeforeRemount 使用同一套,否则会误判「能放下」而不设 scroll.y。 */ private getScrollYMaxOffset; /** * 当前视口实际展示的行数。 * 前端分页按 pageIndex/pageSize 切片估算,避免用全量 length 误判需要纵向滚动。 */ private getVisibleRowCount; /** 当前页内容高度是否超出视口(需要表内纵向滚动) */ readonly needsVerticalScroll: boolean; /** 当前页数据能完整展示时不启用虚拟滚动,避免少量数据也出现滚动条 */ readonly useVirtualScroll: boolean; getRightSticky(col: HdTableColumn): string | null; getLeftSticky(col: HdTableColumn): string | null; /** * 序号列固定宽(含 padding,可容纳 6 位如 199995)。 * 不锁死时表体会随位数变宽(1→~64px,199995→~67px),合计行对不齐。 */ readonly lineNumberColWidth = 72; /** 开启合计时序号列的 left(勾选列占 40px) */ readonly lineNumberLeft: string; readonly lineNumberColWidthPx: string; /** * 列总宽未超出容器:无横向 scroll,表体列会被撑满,合计走 fluid(width:100%)。 * 列总宽超出:有 scroll.x,合计走固定表宽 + 横滚同步。 */ readonly isTotalFooterFluid: boolean; /** fluid → 100%;固定 → scroll.x(与表体同一套横向宽度) */ readonly totalFooterTableWidth: string; /** 当前页行号(跨页连续,从 1 开始) */ getLineNumber(index: number): number; trackByRow: (index: number, data: any) => string; /** 虚拟滚动按数组下标追踪,避免业务主键 trackBy 导致 CDK 行复用错位 */ virtualTrackByRow: (index: number) => number; trackByCol: (_index: number, col: HdTableColumn) => string; getInitLocalforage(): void; initTable(): void; /** 虚拟/普通模式切换时重建表格,避免残留滚动容器 */ applyTableScrollMode(forceRemount?: boolean): void; /** 重建前预设 scroll,保证 AfterViewInit 时 header/body 结构已正确 */ private presetScrollBeforeRemount; private afterTableRender; refreshVirtualScrollViewport(forceMeasure?: boolean): void; /** 数据刷新后将表体纵向滚动复位到顶部 */ private resetTableBodyScrollTop; /** * 数据更新后多次尝试复位。 * ng-zorro 8 + CDK 虚拟滚动会在数据刷新后异步改写 scrollTop,单次复位经常被覆盖。 */ private scheduleResetTableBodyScrollTop; private flushResetTableBodyScrollTop; /** 未手动传 virtualItemSize 时,从已渲染行测量真实高度 */ measureVirtualItemSize(force?: boolean): boolean; cancelDropdown(): void; confirmDropdown(): void; submitGrids(): void; setCols(): void; beforeDrop: (arg: NzFormatBeforeDropEvent) => Observable; moveElementNearby(arr: any, elementToMoveTitle: any, targetElementTitle: any, pos: any): any; checkAction(event: NzFormatEmitEvent): void; getHideListNodes(): Array; dealCols(): void; normalizeTableCacheOption(): void; private hasColsCache; saveTableCacheOption(): void; judgeRepeatCols(): boolean; onResize({ width }: NzResizeEvent, col: HdTableColumn): void; dealOperateBtn(): void; triggerEvent(fn: any, event: any): void; needShowConfirm(btn: OperateBtn, data: any): boolean; getBtnName(btn: OperateBtn, data: any): string; isDangerBtn(btn: OperateBtn, data: any): boolean; /** 虚拟滚动开启时使用视口最大高度 */ private getVirtualScrollY; private hasTableData; /** * 列总宽超出外层容器才启用横向 scroll。 * 以 dealScroll 累计的声明列宽为准,不用 DOM 自然测宽(内容不截断会偏大,导致列能放下也开横滚)。 */ private resolveScrollX; /** 表格渲染后按实际容器宽度校正横向 scroll(只改 x,避免触发表头结构变化) */ private syncHorizontalScroll; /** 手动把表体横向滚动同步到表头 / 合计 footer(兜底 ng-zorro 监听丢失的情况) */ private syncHeaderBodyScrollLeft; /** 取表体横向滚动容器(虚拟滚动优先 viewport) */ private getTableBodyScrollEl; private getTotalFooterScrollEl; /** 表体是否出现纵向滚动条(含滚动条槽宽) */ private bodyHasVerticalScrollbar; /** * 合计 footer 与表体联动: * - fluid(列未撑满):不横滚、不测宽,表宽 100% 与表体同比例拉伸; * - fixed(有 scroll.x):同步 scrollLeft; * - 仅当表体有竖滚条时预留右侧槽,行少无竖滚时不占位。 */ private syncTotalFooterWithBody; private syncTotalFooterScrollLeft; private bindTotalFooterScrollSync; private unbindTotalFooterScrollSync; /** * 监听窗口 / 容器宽度变化:重新判定 scroll.x(fluid↔fixed)与合计右侧竖滚槽, * 避免拉宽/缩窄屏幕后合计行宽与表体错位。 */ private bindViewportResizeSync; private unbindViewportResizeSync; private scheduleViewportScrollSync; dealScroll(): void; currentPageDataChange($event: any): void; search(reset: boolean): void; /** * 底部合计:与 hd-detail-lines 相同,使用 TotalOption(insertIndex / insertValue)。 * 开启后强制展示序号列,「合计」落在序号列下; * insertIndex 从 1 起对应可见数据列;未传 insertValue 时按该列 name 对 content 求和。 */ calculateTableTotal(): void; private getTableTotalCellMeta; /** 合计单元格展示文案(对齐 detail-lines 小数规则) */ getTableTotalCellValue(col: HdTableColumn, colIndex: number): any; getTableTotalCellAlign(col: HdTableColumn, colIndex: number): string; /** 底部「共 n 条」:非分页/前端分页用 content.length,服务端分页用 totalElements */ getTableTotalCount(): number; resetStatus(): void; refreshStatus(event?: boolean, data?: any): void; checkAll(value: boolean): void; /** 当前行是否禁用勾选 */ isSelectDisabled(data: any): boolean; /** 当前行是否失效 */ isInvalidRow(data: any): boolean; /** * 列文字颜色:color 为函数时按行计算(用于某一行某一列标红),否则整列同色。 */ resolveCellColor(col: HdTableColumn, data: any): string; /** 可点击单元格颜色:空值固定灰,否则按列 color */ getLinkCellColor(col: HdTableColumn, data: any, isEmpty: boolean): string; /** 普通文本单元格颜色:失效行统一灰,否则用列配置 color */ getPlainCellColor(col: HdTableColumn, data: any): string; judgeColEmpty(str: any): any; getStateField(col: HdTableColumn): string; /** 字段值后是否展示竖线行号 */ hasRowNo(col: HdTableColumn): boolean; /** * 行号文案。rowNo 为字段名时取行数据;为 true 时按当前页序号(跨页连续,从 1 开始)。 */ getRowNoText(col: HdTableColumn, data: any, index: number): string; /** 表头「配送单号 | 行」拆成短竖线,避免字符 | 拉满行高 */ getTitleParts(col: HdTableColumn): Array; /** 是否显示编辑笔图标(有 editType 时走行内控件,不再显示笔) */ isEditable(col: HdTableColumn, data: any): boolean; /** 点击编辑笔,回调父组件传入的 edit */ onEditClick(event: Event, col: HdTableColumn, data: any): void; /** 列是否配置了可用的行内编辑(name 必须是 string) */ hasInlineEdit(col: HdTableColumn): boolean; isEditDisabled(col: HdTableColumn, data: any): boolean; getSelectList(col: HdTableColumn, data: any): Array; getSelectOptionLabel(col: HdTableColumn, item: any): string; getInputNumberProp(col: HdTableColumn, key: "min" | "max" | "step" | "precision", fallback: number): number; /** Input / InputNumber 变更:先记旧值再写回并通知父组件 */ onCellChange(col: HdTableColumn, data: any, value: any): void; /** Select 变更:双写 value + label,并带 previous* / option */ onSelectChange(col: HdTableColumn, data: any, value: any): void; }