@yibozhang/pro-table 0.0.5 → 0.0.6

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.
@@ -181,8 +181,10 @@ class ProTableComponent {
181
181
  };
182
182
  this._loading = false;
183
183
  this._selectedTableRow = null;
184
- // 选中的行数据(用于复选框选择)
184
+ // 选中的行数据(用于复选框选择)- 保留用于兼容性
185
185
  this._selectedRows = [];
186
+ // 使用 Set 存储选中项的 ID,支持跨页选中
187
+ this._selectedRowIds = new Set();
186
188
  // 全选状态
187
189
  this._checkedAll = false;
188
190
  // 半选状态(部分选中)
@@ -705,7 +707,12 @@ class ProTableComponent {
705
707
  return this._selectedTableRow;
706
708
  }
707
709
  getCheckedRows() {
708
- return this._selectedRows;
710
+ if (!this.showCheckbox) {
711
+ return [];
712
+ }
713
+ // 返回当前数据源中所有 checked 为 true 的项
714
+ // 注意:如果需要获取所有页的选中项,需要遍历所有数据源或使用 _selectedRowIds
715
+ return this.dataSource.filter((row) => row.checked === true);
709
716
  }
710
717
  // 获取指定名称的模板
711
718
  getTemplate(name) {
@@ -752,13 +759,14 @@ class ProTableComponent {
752
759
  return false;
753
760
  return this.rowDisabled ? this.rowDisabled(data) : false;
754
761
  }
755
- // 检查行是否被复选框选中
762
+ // 检查行是否被复选框选中(数据驱动模式)
756
763
  isRowChecked(data) {
757
764
  if (!this.showCheckbox)
758
765
  return false;
759
- return this._selectedRows.some((row) => JSON.stringify(row) === JSON.stringify(data));
766
+ // 直接读取数据对象的 checked 属性
767
+ return data.checked === true;
760
768
  }
761
- // 切换行的选中状态
769
+ // 切换行的选中状态(数据驱动模式,保留用于兼容)
762
770
  toggleRowChecked(data, checked, event) {
763
771
  if (event) {
764
772
  event.stopPropagation(); // 阻止事件冒泡,避免触发行点击
@@ -767,9 +775,21 @@ class ProTableComponent {
767
775
  if (this.isRowDisabled(data)) {
768
776
  return;
769
777
  }
770
- const index = this._selectedRows.findIndex((row) => JSON.stringify(row) === JSON.stringify(data));
778
+ // 直接设置数据对象的 checked 属性
779
+ data.checked = checked;
780
+ // 同步更新 _selectedRowIds(用于跨页选中)
781
+ const id = this.getRowId(data);
782
+ if (id !== undefined) {
783
+ if (checked) {
784
+ this._selectedRowIds.add(id);
785
+ }
786
+ else {
787
+ this._selectedRowIds.delete(id);
788
+ }
789
+ }
790
+ // 同步更新 _selectedRows(用于兼容性)
791
+ const index = this._selectedRows.findIndex((row) => this.isSameRow(row, data));
771
792
  if (checked) {
772
- // 选中
773
793
  if (index === -1) {
774
794
  this._selectedRows.push(data);
775
795
  }
@@ -777,19 +797,18 @@ class ProTableComponent {
777
797
  this._selectedTableRow = data;
778
798
  }
779
799
  else {
780
- // 取消选中
781
800
  if (index > -1) {
782
801
  this._selectedRows.splice(index, 1);
783
802
  }
784
803
  // 若当前高亮行为该行,则取消高亮
785
804
  if (this._selectedTableRow &&
786
- JSON.stringify(this._selectedTableRow) === JSON.stringify(data)) {
805
+ this.isSameRow(this._selectedTableRow, data)) {
787
806
  this._selectedTableRow = null;
788
807
  }
789
808
  }
790
809
  this.updateCheckAllStatus();
791
810
  }
792
- // 更新全选状态
811
+ // 更新全选状态(数据驱动模式)
793
812
  updateCheckAllStatus() {
794
813
  if (!this.showCheckbox || !Array.isArray(this.dataSource)) {
795
814
  this._checkedAll = false;
@@ -798,39 +817,120 @@ class ProTableComponent {
798
817
  }
799
818
  // 只计算可用的行(未禁用的行)
800
819
  const availableRows = this.dataSource.filter((row) => !this.isRowDisabled(row));
801
- const checkedCount = this._selectedRows.length;
820
+ // 基于数据对象的 checked 属性计算
821
+ const checkedCount = availableRows.filter((row) => row.checked === true).length;
802
822
  const totalCount = availableRows.length;
803
823
  this._checkedAll =
804
824
  totalCount > 0 && checkedCount > 0 && checkedCount === totalCount;
805
825
  this._indeterminate = checkedCount > 0 && checkedCount < totalCount;
806
826
  }
807
- // 全选/取消全选
827
+ // 全选/取消全选(数据驱动模式)
808
828
  toggleCheckAll(checked, event) {
809
829
  if (event) {
810
830
  event.stopPropagation();
811
831
  }
832
+ // 只处理可用的行(未禁用的行)
833
+ const availableRows = this.dataSource.filter((row) => !this.isRowDisabled(row));
834
+ // 批量设置 checked 属性
835
+ availableRows.forEach((row) => {
836
+ row.checked = checked;
837
+ // 同步更新 _selectedRowIds(用于跨页选中)
838
+ const id = this.getRowId(row);
839
+ if (id !== undefined) {
840
+ if (checked) {
841
+ this._selectedRowIds.add(id);
842
+ }
843
+ else {
844
+ this._selectedRowIds.delete(id);
845
+ }
846
+ }
847
+ });
848
+ // 同步更新 _selectedRows(用于兼容性)
812
849
  if (checked) {
813
- // 全选:只选中未禁用的行
814
- this._selectedRows = this.dataSource.filter((row) => !this.isRowDisabled(row));
850
+ this._selectedRows = [...availableRows];
815
851
  // 同步设置高亮选中行为第一条可选数据
816
- const availableRows = this._selectedRows;
817
852
  this._selectedTableRow =
818
853
  availableRows.length > 0 ? availableRows[0] : null;
819
854
  }
820
855
  else {
821
- // 取消全选
822
856
  this._selectedRows = [];
823
857
  // 取消高亮
824
858
  this._selectedTableRow = null;
825
859
  }
826
860
  this.updateCheckAllStatus();
827
861
  }
828
- // 获取选中的行数据
862
+ // 获取选中的行数据(保留用于兼容性)
829
863
  getSelectedRows() {
830
- return this._selectedRows;
864
+ return this.getCheckedRows();
831
865
  }
832
- // 清空选中的行
866
+ // 处理行 checkbox 变化事件(数据驱动模式)
867
+ handleRowCheckedChange(data, checked) {
868
+ if (this.isRowDisabled(data)) {
869
+ return;
870
+ }
871
+ // 数据对象的 checked 属性已经通过双向绑定自动更新
872
+ // 这里只需要同步更新 _selectedRowIds 和 _selectedRows
873
+ // 同步更新 _selectedRowIds(用于跨页选中)
874
+ const id = this.getRowId(data);
875
+ if (id !== undefined) {
876
+ if (checked) {
877
+ this._selectedRowIds.add(id);
878
+ }
879
+ else {
880
+ this._selectedRowIds.delete(id);
881
+ }
882
+ }
883
+ // 同步更新 _selectedRows(用于兼容性)
884
+ const index = this._selectedRows.findIndex((row) => this.isSameRow(row, data));
885
+ if (checked) {
886
+ if (index === -1) {
887
+ this._selectedRows.push(data);
888
+ }
889
+ // 勾选复选框时同步设置高亮选中行
890
+ this._selectedTableRow = data;
891
+ }
892
+ else {
893
+ if (index > -1) {
894
+ this._selectedRows.splice(index, 1);
895
+ }
896
+ // 若当前高亮行为该行,则取消高亮
897
+ if (this._selectedTableRow &&
898
+ this.isSameRow(this._selectedTableRow, data)) {
899
+ this._selectedTableRow = null;
900
+ }
901
+ }
902
+ // 更新全选状态
903
+ this.updateCheckAllStatus();
904
+ }
905
+ // 刷新全选状态(用于其他场景)
906
+ refreshCheckAllStatus() {
907
+ this.updateCheckAllStatus();
908
+ }
909
+ // 获取行的唯一标识(用于跨页选中)
910
+ getRowId(data) {
911
+ var _a, _b;
912
+ return (_b = (_a = data.id) !== null && _a !== void 0 ? _a : data.key) !== null && _b !== void 0 ? _b : undefined;
913
+ }
914
+ // 判断两行是否为同一行
915
+ isSameRow(row1, row2) {
916
+ const id1 = this.getRowId(row1);
917
+ const id2 = this.getRowId(row2);
918
+ if (id1 !== undefined && id2 !== undefined) {
919
+ return id1 === id2;
920
+ }
921
+ // fallback 到 JSON 比较
922
+ return JSON.stringify(row1) === JSON.stringify(row2);
923
+ }
924
+ // 清空选中的行(数据驱动模式)
833
925
  clearSelectedRows() {
926
+ // 清空当前数据源中所有项的 checked 状态
927
+ if (Array.isArray(this.dataSource)) {
928
+ this.dataSource.forEach((row) => {
929
+ row.checked = false;
930
+ });
931
+ }
932
+ // 清空选中集合
933
+ this._selectedRowIds.clear();
834
934
  this._selectedRows = [];
835
935
  this._checkedAll = false;
836
936
  this._indeterminate = false;
@@ -907,6 +1007,8 @@ class ProTableComponent {
907
1007
  this._pageInfo.pageIndex > 1) {
908
1008
  this._pageInfo.pageIndex = this._pageInfo.pageIndex - 1;
909
1009
  }
1010
+ // 保存删除前的数据源(用于删除后查询时移除被删除项的选中状态)
1011
+ const previousDataSource = afterDelete && this.showCheckbox ? [...this.dataSource] : [];
910
1012
  this._loading = true;
911
1013
  if (this.request) {
912
1014
  try {
@@ -916,7 +1018,38 @@ class ProTableComponent {
916
1018
  } }, (this.sortMode === "server"
917
1019
  ? { sort: this.buildServerSortPayload() }
918
1020
  : {})));
919
- this.dataSource = result.data || [];
1021
+ // 自动注入 checked 字段,支持跨页选中
1022
+ if (this.showCheckbox) {
1023
+ this.dataSource = (result.data || []).map((item) => {
1024
+ const id = this.getRowId(item);
1025
+ // 如果数据已有 checked 属性,保留;否则根据 _selectedRowIds 判断
1026
+ const checked = item.checked !== undefined
1027
+ ? item.checked
1028
+ : id !== undefined
1029
+ ? this._selectedRowIds.has(id)
1030
+ : false;
1031
+ return Object.assign(Object.assign({}, item), { checked: checked });
1032
+ });
1033
+ // 删除后查询:移除被删除项的选中状态
1034
+ if (afterDelete && previousDataSource.length > 0) {
1035
+ const newDataIds = new Set(this.dataSource.map((item) => this.getRowId(item)));
1036
+ // 遍历之前的数据源,如果不在新数据源中,说明被删除了,需要清除其选中状态
1037
+ previousDataSource.forEach((oldItem) => {
1038
+ const oldId = this.getRowId(oldItem);
1039
+ if (oldId !== undefined && !newDataIds.has(oldId)) {
1040
+ // 被删除的项,从选中集合中移除
1041
+ this._selectedRowIds.delete(oldId);
1042
+ // 如果数据对象还在其他地方引用,清除其选中状态
1043
+ if (oldItem.checked !== undefined) {
1044
+ oldItem.checked = false;
1045
+ }
1046
+ }
1047
+ });
1048
+ }
1049
+ }
1050
+ else {
1051
+ this.dataSource = result.data || [];
1052
+ }
920
1053
  this.summaryData = result.summaryData || null;
921
1054
  // 本地排序模式:拿到数据后在前端排序
922
1055
  if (this.sortMode === "local") {
@@ -937,15 +1070,13 @@ class ProTableComponent {
937
1070
  finally {
938
1071
  this._loading = false;
939
1072
  this._selectedTableRow = null;
940
- // 清空选中行(可选,根据业务需求决定是否保留跨页选中)
941
- // this.clearSelectedRows();
942
1073
  }
943
1074
  }
944
1075
  else {
945
1076
  console.warn("未提供 _request 回调函数");
946
1077
  this._loading = false;
947
1078
  }
948
- this.clearSelectedRows();
1079
+ // 不再调用 clearSelectedRows(),保留跨页选中状态
949
1080
  });
950
1081
  }
951
1082
  // 触发列排序变更
@@ -1052,7 +1183,7 @@ class ProTableComponent {
1052
1183
  ProTableComponent.decorators = [
1053
1184
  { type: Component, args: [{
1054
1185
  selector: "app-pro-table",
1055
- template: "<app-page-container [title]=\"title\">\r\n <ng-template #header>\r\n <app-table-search-bar\r\n *ngIf=\"showSearchBar\"\r\n [labelWidth]=\"labelWidth\"\r\n [labelAlign]=\"labelAlign\"\r\n >\r\n <ng-template #leftContent>\r\n <nz-form-item\r\n *ngFor=\"let column of _searchFiledColumns\"\r\n [ngClass]=\"getFormItemClassName(column)\"\r\n >\r\n <nz-form-label *ngIf=\"!getFieldProps(column).hideLabel\" nzNoColon>\r\n <!-- \u68C0\u67E5\u662F\u5426\u6709\u81EA\u5B9A\u4E49label\u6A21\u677F -->\r\n <ng-container\r\n *ngIf=\"\r\n column.customLabelRender &&\r\n getLabelTemplate(column.customLabelRender);\r\n else defaultLabel\r\n \"\r\n >\r\n <ng-container\r\n [ngTemplateOutlet]=\"getLabelTemplate(column.customLabelRender)\"\r\n [ngTemplateOutletContext]=\"{\r\n $implicit: column,\r\n column: column,\r\n fieldProps: getFieldProps(column)\r\n }\"\r\n >\r\n </ng-container>\r\n </ng-container>\r\n <ng-template #defaultLabel>\r\n {{ getFieldProps(column).label || column.title }}\r\n </ng-template>\r\n </nz-form-label>\r\n <nz-form-control *ngIf=\"column.valueType === 'input'\">\r\n <input\r\n nz-input\r\n [name]=\"getFieldProps(column).name || column.prop\"\r\n [placeholder]=\"getFieldProps(column).placeHolder\"\r\n [disabled]=\"getFieldProps(column).disabled\"\r\n [(ngModel)]=\"\r\n _searchParams[getFieldProps(column).name || column.prop]\r\n \"\r\n />\r\n </nz-form-control>\r\n <nz-form-control *ngIf=\"column.valueType === 'inputPlate'\">\r\n <app-plate-input\r\n [name]=\"getFieldProps(column).name || column.prop\"\r\n [(ngModel)]=\"\r\n _searchParams[getFieldProps(column).name || column.prop]\r\n \"\r\n ></app-plate-input>\r\n </nz-form-control>\r\n <nz-form-control *ngIf=\"column.valueType === 'select'\">\r\n <nz-select\r\n [(ngModel)]=\"\r\n _searchParams[getFieldProps(column).name || column.prop]\r\n \"\r\n [nzAllowClear]=\"getFieldProps(column).allowClear\"\r\n [nzPlaceHolder]=\"getFieldProps(column).placeHolder\"\r\n [name]=\"getFieldProps(column).name || column.prop\"\r\n [nzOptions]=\"getFieldProps(column).options\"\r\n [nzDisabled]=\"getFieldProps(column).disabled\"\r\n >\r\n </nz-select>\r\n </nz-form-control>\r\n <nz-form-control *ngIf=\"column.valueType === 'selectMultiple'\">\r\n <nz-select\r\n [(ngModel)]=\"\r\n _searchParams[getFieldProps(column).name || column.prop]\r\n \"\r\n [nzAllowClear]=\"getFieldProps(column).allowClear\"\r\n [nzPlaceHolder]=\"getFieldProps(column).placeHolder\"\r\n [name]=\"getFieldProps(column).name || column.prop\"\r\n [nzOptions]=\"getFieldProps(column).options\"\r\n [nzDisabled]=\"getFieldProps(column).disabled\"\r\n nzMode=\"multiple\"\r\n >\r\n </nz-select>\r\n </nz-form-control>\r\n <nz-form-control *ngIf=\"column.valueType === 'date'\">\r\n <nz-date-picker\r\n [nzShowTime]=\"getFieldProps(column).showTime\"\r\n [nzFormat]=\"getFieldProps(column).format\"\r\n [nzPlaceHolder]=\"getFieldProps(column).placeHolder\"\r\n [nzAllowClear]=\"getFieldProps(column).allowClear\"\r\n [nzDisabled]=\"getFieldProps(column).disabled\"\r\n [(ngModel)]=\"\r\n _searchParams[getFieldProps(column).name || column.prop]\r\n \"\r\n [nzMode]=\"getFieldProps(column).mode\"\r\n ></nz-date-picker>\r\n </nz-form-control>\r\n <nz-form-control *ngIf=\"column.valueType === 'checkbox'\">\r\n <nz-checkbox-group\r\n [class]=\"\r\n getFieldProps(column).noStyle\r\n ? 'pro-table-checkboxgroup-nostyle'\r\n : ''\r\n \"\r\n [(ngModel)]=\"getFieldProps(column).options\"\r\n [nzDisabled]=\"getFieldProps(column).disabled\"\r\n (ngModelChange)=\"\r\n handleFieldCheckBoxChange(\r\n $event,\r\n getFieldProps(column).name || column.prop\r\n )\r\n \"\r\n ></nz-checkbox-group>\r\n </nz-form-control>\r\n <nz-form-control *ngIf=\"column.valueType === 'autoComplete'\">\r\n <input\r\n nz-input\r\n [(ngModel)]=\"\r\n _searchParams[getFieldProps(column)?.name || column.prop]\r\n \"\r\n (input)=\"handleAutoCompleteInput($event, column)\"\r\n [nzAutocomplete]=\"auto\"\r\n [disabled]=\"getFieldProps(column)?.disabled\"\r\n [placeholder]=\"getFieldProps(column)?.placeHolder\"\r\n />\r\n <nz-autocomplete\r\n [nzBackfill]=\"getFieldProps(column).backFill\"\r\n [nzDefaultActiveFirstOption]=\"\r\n getFieldProps(column).defaultActiveFirstOption\r\n \"\r\n [nzWidth]=\"getFieldProps(column).width\"\r\n #auto\r\n >\r\n <nz-auto-option\r\n *ngFor=\"let option of getAutoCompleteDataSource(column)\"\r\n [nzValue]=\"\r\n getFieldProps(column).returnFullData ? option : option.value\r\n \"\r\n [nzLabel]=\"option.label\"\r\n [nzDisabled]=\"option.disabled\"\r\n >\r\n {{ option.label }}\r\n </nz-auto-option>\r\n </nz-autocomplete>\r\n </nz-form-control>\r\n <nz-form-control *ngIf=\"column.valueType === 'custom'\">\r\n <app-dynamic-search-field\r\n [component]=\"getFieldProps(column).component\"\r\n [value]=\"_searchParams[getFieldProps(column).name || column.prop]\"\r\n [props]=\"getFieldProps(column)\"\r\n (valueChange)=\"\r\n setFieldValue(getFieldProps(column).name || column.prop, $event)\r\n \"\r\n ></app-dynamic-search-field>\r\n </nz-form-control>\r\n <nz-form-control *ngIf=\"column.valueType === 'inputNumber'\">\r\n <nz-input-number\r\n [style.width]=\"'100%'\"\r\n [(ngModel)]=\"\r\n _searchParams[getFieldProps(column).name || column.prop]\r\n \"\r\n [nzPlaceHolder]=\"getFieldProps(column).placeHolder\"\r\n [nzDisabled]=\"getFieldProps(column).disabled\"\r\n [nzFormatter]=\"getFieldProps(column).formatterPercent\"\r\n [nzParser]=\"getFieldProps(column).parserPercent\"\r\n ></nz-input-number>\r\n </nz-form-control>\r\n </nz-form-item>\r\n </ng-template>\r\n <ng-template #actionTextBtn>\r\n <nz-space [nzSize]=\"4\">\r\n <nz-space-item *ngIf=\"showSearchBtn\">\r\n <button nz-button nzType=\"primary\" (click)=\"handleSearch()\">\r\n {{ confirmBtnText }}\r\n </button>\r\n </nz-space-item>\r\n <nz-space-item *ngIf=\"showClearBtn\">\r\n <button nz-button (click)=\"handleResetForm()\">\r\n {{ clearBtnText }}\r\n </button>\r\n </nz-space-item>\r\n </nz-space>\r\n </ng-template>\r\n <ng-template #actionImgBtn>\r\n <nz-space>\r\n <ng-container *ngTemplateOutlet=\"imgActionBarTpl\"></ng-container>\r\n <nz-space-item class=\"setting-space-item\" *ngIf=\"showColumnSetting\">\r\n <app-colmuns-setting\r\n [columns]=\"columns\"\r\n [selectedColumns]=\"_serverColumns\"\r\n [tableName]=\"tableName\"\r\n (afterConfirm)=\"handleColumnsSettingConfirm()\"\r\n ></app-colmuns-setting>\r\n </nz-space-item>\r\n </nz-space>\r\n </ng-template>\r\n </app-table-search-bar>\r\n </ng-template>\r\n <ng-template #body>\r\n <div class=\"mb-12\">\r\n <ng-container *ngIf=\"showActionBar\">\r\n <ng-container *ngTemplateOutlet=\"actionBarTpl\"></ng-container>\r\n </ng-container>\r\n </div>\r\n <ng-container *ngIf=\"customTableRender\">\r\n <ng-container *ngTemplateOutlet=\"customTableRender\"></ng-container>\r\n </ng-container>\r\n <nz-table\r\n *ngIf=\"!customTableRender\"\r\n #basicTable\r\n nzSize=\"small\"\r\n nzShowSizeChanger\r\n [nzBordered]=\"bordered\"\r\n [nzOuterBordered]=\"outerBordered\"\r\n [nzData]=\"dataSource\"\r\n [nzPageIndex]=\"_pageInfo.pageIndex\"\r\n [nzPageSize]=\"_pageInfo.pageSize\"\r\n [nzTotal]=\"_pageInfo.total\"\r\n [nzPageSizeOptions]=\"_pageInfo.pageSizeOptions\"\r\n [nzShowPagination]=\"showPagination\"\r\n [nzShowTotal]=\"totalTemplate\"\r\n [nzLoading]=\"_loading\"\r\n [nzFrontPagination]=\"frontPagination\"\r\n [nzScroll]=\"scroll\"\r\n (nzPageIndexChange)=\"handlePageIndexChange($event)\"\r\n (nzPageSizeChange)=\"handlePageSizeChange($event)\"\r\n >\r\n <thead>\r\n <tr>\r\n <!-- \u590D\u9009\u6846\u5217\uFF08\u5F53 showCheckbox=true \u65F6\u663E\u793A\uFF09 -->\r\n <th\r\n *ngIf=\"showCheckbox\"\r\n [nzWidth]=\"'50px'\"\r\n [nzAlign]=\"'center'\"\r\n style=\"text-align: center\"\r\n >\r\n <label\r\n nz-checkbox\r\n [(ngModel)]=\"_checkedAll\"\r\n [nzIndeterminate]=\"_indeterminate\"\r\n (ngModelChange)=\"toggleCheckAll($event)\"\r\n (click)=\"$event.stopPropagation()\"\r\n ></label>\r\n </th>\r\n <th\r\n *ngFor=\"let column of _columns\"\r\n [nzWidth]=\"column.width\"\r\n [nzAlign]=\"column.align\"\r\n [nzLeft]=\"column.fixedLeft\"\r\n [nzRight]=\"column.fixedRight\"\r\n [nzShowSort]=\"!!column.sorter\"\r\n [nzSortOrder]=\"getSortOrder(column.prop)\"\r\n (nzSortOrderChange)=\"onSortChange(column.prop, $event)\"\r\n >\r\n {{ column.title }}\r\n </th>\r\n </tr>\r\n </thead>\r\n\r\n <tbody>\r\n <tr\r\n style=\"cursor: pointer\"\r\n *ngFor=\"let data; let i = index; of: basicTable.data\"\r\n [ngClass]=\"{\r\n 'ant-table-custom-row-selected': !!getTableRowChecked(data),\r\n 'ant-table-custom-row-even': i % 2 === 0,\r\n 'ant-table-custom-row-odd': i % 2 !== 0\r\n }\"\r\n (click)=\"handleTableRowClick(data)\"\r\n (dblclick)=\"handleTableRowDbClick(data)\"\r\n >\r\n <!-- \u590D\u9009\u6846\u5217\uFF08\u5F53 showCheckbox=true \u65F6\u663E\u793A\uFF09 -->\r\n <td\r\n *ngIf=\"showCheckbox\"\r\n [nzAlign]=\"'center'\"\r\n style=\"text-align: center\"\r\n (click)=\"$event.stopPropagation()\"\r\n >\r\n <label\r\n nz-checkbox\r\n [ngModel]=\"isRowChecked(data)\"\r\n [nzDisabled]=\"isRowDisabled(data)\"\r\n (ngModelChange)=\"toggleRowChecked(data, $event)\"\r\n ></label>\r\n </td>\r\n <td\r\n *ngFor=\"let column of _columns\"\r\n [nzLeft]=\"column.fixedLeft\"\r\n [nzRight]=\"column.fixedRight\"\r\n [nzAlign]=\"column.align\"\r\n class=\"pro-ellipsis\"\r\n [title]=\"data[column.prop]\"\r\n >\r\n <!-- \u68C0\u67E5\u662F\u5426\u6709\u81EA\u5B9A\u4E49\u6A21\u677F -->\r\n <ng-container\r\n *ngIf=\"\r\n column.customRender && getTemplate(column.customRender);\r\n let template\r\n \"\r\n >\r\n <ng-template\r\n [ngTemplateOutlet]=\"template\"\r\n [ngTemplateOutletContext]=\"{\r\n $implicit: data,\r\n data: data,\r\n column: column,\r\n index: i,\r\n pageInfo: _pageInfo\r\n }\"\r\n >\r\n </ng-template>\r\n </ng-container>\r\n\r\n <!-- \u9ED8\u8BA4\u6E32\u67D3\u903B\u8F91 -->\r\n <ng-container\r\n *ngIf=\"!column.customRender || !getTemplate(column.customRender)\"\r\n >\r\n {{ data[column.prop] }}\r\n </ng-container>\r\n </td>\r\n </tr>\r\n <tr *ngIf=\"summaryData && _pageInfo.total > 0\">\r\n <!-- \u6C47\u603B\u884C\u7684\u590D\u9009\u6846\u5217\uFF08\u5F53 showCheckbox=true \u65F6\u663E\u793A\uFF0C\u4F46\u4E3A\u7A7A\uFF09 -->\r\n <td\r\n *ngIf=\"showCheckbox\"\r\n style=\"font-weight: bold; border-right: 1px solid #e8e8e8\"\r\n ></td>\r\n <td\r\n *ngFor=\"let column; let i = index; of: _columns\"\r\n [nzLeft]=\"column.fixedLeft\"\r\n [nzRight]=\"column.fixedRight\"\r\n style=\"font-weight: bold; border-right: 1px solid #e8e8e8\"\r\n [nzAlign]=\"column.align\"\r\n >\r\n <span *ngIf=\"i === 0\">\u603B\u8BA1</span>\r\n <ng-container *ngIf=\"i !== 0 && column.summary\">\r\n {{\r\n column.summary?.format\r\n ? column.summary?.format(\r\n summaryData[column.summary?.name || column.prop]\r\n )\r\n : summaryData[column.summary?.name || column.prop]\r\n }}\r\n </ng-container>\r\n </td>\r\n </tr>\r\n </tbody>\r\n <ng-template #totalTemplate let-total\r\n >\u5171 {{ _pageInfo.total }} \u6761\u8BB0\u5F55</ng-template\r\n >\r\n </nz-table>\r\n </ng-template>\r\n</app-page-container>\r\n",
1186
+ template: "<app-page-container\r\n [title]=\"title\"\r\n [showHeader]=\"showSearchBar\"\r\n ngClass=\"pro-table-container\"\r\n>\r\n <ng-template #header>\r\n <app-table-search-bar\r\n *ngIf=\"showSearchBar\"\r\n [labelWidth]=\"labelWidth\"\r\n [labelAlign]=\"labelAlign\"\r\n >\r\n <ng-template #leftContent>\r\n <nz-form-item\r\n *ngFor=\"let column of _searchFiledColumns\"\r\n [ngClass]=\"getFormItemClassName(column)\"\r\n >\r\n <nz-form-label *ngIf=\"!getFieldProps(column).hideLabel\" nzNoColon>\r\n <!-- \u68C0\u67E5\u662F\u5426\u6709\u81EA\u5B9A\u4E49label\u6A21\u677F -->\r\n <ng-container\r\n *ngIf=\"\r\n column.customLabelRender &&\r\n getLabelTemplate(column.customLabelRender);\r\n else defaultLabel\r\n \"\r\n >\r\n <ng-container\r\n [ngTemplateOutlet]=\"getLabelTemplate(column.customLabelRender)\"\r\n [ngTemplateOutletContext]=\"{\r\n $implicit: column,\r\n column: column,\r\n fieldProps: getFieldProps(column)\r\n }\"\r\n >\r\n </ng-container>\r\n </ng-container>\r\n <ng-template #defaultLabel>\r\n {{ getFieldProps(column).label || column.title }}\r\n </ng-template>\r\n </nz-form-label>\r\n <nz-form-control *ngIf=\"column.valueType === 'input'\">\r\n <input\r\n nz-input\r\n [name]=\"getFieldProps(column).name || column.prop\"\r\n [placeholder]=\"getFieldProps(column).placeHolder\"\r\n [disabled]=\"getFieldProps(column).disabled\"\r\n [(ngModel)]=\"\r\n _searchParams[getFieldProps(column).name || column.prop]\r\n \"\r\n />\r\n </nz-form-control>\r\n <nz-form-control *ngIf=\"column.valueType === 'inputPlate'\">\r\n <app-plate-input\r\n [name]=\"getFieldProps(column).name || column.prop\"\r\n [(ngModel)]=\"\r\n _searchParams[getFieldProps(column).name || column.prop]\r\n \"\r\n ></app-plate-input>\r\n </nz-form-control>\r\n <nz-form-control *ngIf=\"column.valueType === 'select'\">\r\n <nz-select\r\n [(ngModel)]=\"\r\n _searchParams[getFieldProps(column).name || column.prop]\r\n \"\r\n [nzAllowClear]=\"getFieldProps(column).allowClear\"\r\n [nzPlaceHolder]=\"getFieldProps(column).placeHolder\"\r\n [name]=\"getFieldProps(column).name || column.prop\"\r\n [nzOptions]=\"getFieldProps(column).options\"\r\n [nzDisabled]=\"getFieldProps(column).disabled\"\r\n >\r\n </nz-select>\r\n </nz-form-control>\r\n <nz-form-control *ngIf=\"column.valueType === 'selectMultiple'\">\r\n <nz-select\r\n [(ngModel)]=\"\r\n _searchParams[getFieldProps(column).name || column.prop]\r\n \"\r\n [nzAllowClear]=\"getFieldProps(column).allowClear\"\r\n [nzPlaceHolder]=\"getFieldProps(column).placeHolder\"\r\n [name]=\"getFieldProps(column).name || column.prop\"\r\n [nzOptions]=\"getFieldProps(column).options\"\r\n [nzDisabled]=\"getFieldProps(column).disabled\"\r\n nzMode=\"multiple\"\r\n >\r\n </nz-select>\r\n </nz-form-control>\r\n <nz-form-control *ngIf=\"column.valueType === 'date'\">\r\n <nz-date-picker\r\n [nzShowTime]=\"getFieldProps(column).showTime\"\r\n [nzFormat]=\"getFieldProps(column).format\"\r\n [nzPlaceHolder]=\"getFieldProps(column).placeHolder\"\r\n [nzAllowClear]=\"getFieldProps(column).allowClear\"\r\n [nzDisabled]=\"getFieldProps(column).disabled\"\r\n [(ngModel)]=\"\r\n _searchParams[getFieldProps(column).name || column.prop]\r\n \"\r\n [nzMode]=\"getFieldProps(column).mode\"\r\n ></nz-date-picker>\r\n </nz-form-control>\r\n <nz-form-control *ngIf=\"column.valueType === 'checkbox'\">\r\n <nz-checkbox-group\r\n [class]=\"\r\n getFieldProps(column).noStyle\r\n ? 'pro-table-checkboxgroup-nostyle'\r\n : ''\r\n \"\r\n [(ngModel)]=\"getFieldProps(column).options\"\r\n [nzDisabled]=\"getFieldProps(column).disabled\"\r\n (ngModelChange)=\"\r\n handleFieldCheckBoxChange(\r\n $event,\r\n getFieldProps(column).name || column.prop\r\n )\r\n \"\r\n ></nz-checkbox-group>\r\n </nz-form-control>\r\n <nz-form-control *ngIf=\"column.valueType === 'autoComplete'\">\r\n <input\r\n nz-input\r\n [(ngModel)]=\"\r\n _searchParams[getFieldProps(column)?.name || column.prop]\r\n \"\r\n (input)=\"handleAutoCompleteInput($event, column)\"\r\n [nzAutocomplete]=\"auto\"\r\n [disabled]=\"getFieldProps(column)?.disabled\"\r\n [placeholder]=\"getFieldProps(column)?.placeHolder\"\r\n />\r\n <nz-autocomplete\r\n [nzBackfill]=\"getFieldProps(column).backFill\"\r\n [nzDefaultActiveFirstOption]=\"\r\n getFieldProps(column).defaultActiveFirstOption\r\n \"\r\n [nzWidth]=\"getFieldProps(column).width\"\r\n #auto\r\n >\r\n <nz-auto-option\r\n *ngFor=\"let option of getAutoCompleteDataSource(column)\"\r\n [nzValue]=\"\r\n getFieldProps(column).returnFullData ? option : option.value\r\n \"\r\n [nzLabel]=\"option.label\"\r\n [nzDisabled]=\"option.disabled\"\r\n >\r\n {{ option.label }}\r\n </nz-auto-option>\r\n </nz-autocomplete>\r\n </nz-form-control>\r\n <nz-form-control *ngIf=\"column.valueType === 'custom'\">\r\n <app-dynamic-search-field\r\n [component]=\"getFieldProps(column).component\"\r\n [value]=\"_searchParams[getFieldProps(column).name || column.prop]\"\r\n [props]=\"getFieldProps(column)\"\r\n (valueChange)=\"\r\n setFieldValue(getFieldProps(column).name || column.prop, $event)\r\n \"\r\n ></app-dynamic-search-field>\r\n </nz-form-control>\r\n <nz-form-control *ngIf=\"column.valueType === 'inputNumber'\">\r\n <nz-input-number\r\n [style.width]=\"'100%'\"\r\n [(ngModel)]=\"\r\n _searchParams[getFieldProps(column).name || column.prop]\r\n \"\r\n [nzPlaceHolder]=\"getFieldProps(column).placeHolder\"\r\n [nzDisabled]=\"getFieldProps(column).disabled\"\r\n [nzFormatter]=\"getFieldProps(column).formatterPercent\"\r\n [nzParser]=\"getFieldProps(column).parserPercent\"\r\n ></nz-input-number>\r\n </nz-form-control>\r\n </nz-form-item>\r\n </ng-template>\r\n <ng-template #actionTextBtn>\r\n <nz-space [nzSize]=\"4\">\r\n <nz-space-item *ngIf=\"showSearchBtn\">\r\n <button nz-button nzType=\"primary\" (click)=\"handleSearch()\">\r\n {{ confirmBtnText }}\r\n </button>\r\n </nz-space-item>\r\n <nz-space-item *ngIf=\"showClearBtn\">\r\n <button nz-button (click)=\"handleResetForm()\">\r\n {{ clearBtnText }}\r\n </button>\r\n </nz-space-item>\r\n </nz-space>\r\n </ng-template>\r\n <ng-template #actionImgBtn>\r\n <nz-space>\r\n <ng-container *ngTemplateOutlet=\"imgActionBarTpl\"></ng-container>\r\n <nz-space-item class=\"setting-space-item\" *ngIf=\"showColumnSetting\">\r\n <app-colmuns-setting\r\n [columns]=\"columns\"\r\n [selectedColumns]=\"_serverColumns\"\r\n [tableName]=\"tableName\"\r\n (afterConfirm)=\"handleColumnsSettingConfirm()\"\r\n ></app-colmuns-setting>\r\n </nz-space-item>\r\n </nz-space>\r\n </ng-template>\r\n </app-table-search-bar>\r\n </ng-template>\r\n\r\n <ng-template #body>\r\n <div class=\"mb-12\">\r\n <ng-container *ngIf=\"showActionBar\">\r\n <ng-container *ngTemplateOutlet=\"actionBarTpl\"></ng-container>\r\n </ng-container>\r\n </div>\r\n <ng-container *ngIf=\"customTableRender\">\r\n <ng-container *ngTemplateOutlet=\"customTableRender\"></ng-container>\r\n </ng-container>\r\n <nz-table\r\n *ngIf=\"!customTableRender\"\r\n #dynamicTable\r\n nzSize=\"small\"\r\n nzShowSizeChanger\r\n [nzBordered]=\"bordered\"\r\n [nzOuterBordered]=\"outerBordered\"\r\n [nzData]=\"dataSource\"\r\n [nzPageIndex]=\"_pageInfo.pageIndex\"\r\n [nzPageSize]=\"_pageInfo.pageSize\"\r\n [nzTotal]=\"_pageInfo.total\"\r\n [nzPageSizeOptions]=\"_pageInfo.pageSizeOptions\"\r\n [nzShowPagination]=\"showPagination\"\r\n [nzShowTotal]=\"totalTemplate\"\r\n [nzLoading]=\"_loading\"\r\n [nzFrontPagination]=\"frontPagination\"\r\n [nzScroll]=\"scroll\"\r\n (nzPageIndexChange)=\"handlePageIndexChange($event)\"\r\n (nzPageSizeChange)=\"handlePageSizeChange($event)\"\r\n >\r\n <thead>\r\n <tr>\r\n <!-- \u590D\u9009\u6846\u5217\uFF08\u5F53 showCheckbox=true \u65F6\u663E\u793A\uFF09 -->\r\n <th\r\n *ngIf=\"showCheckbox\"\r\n [nzWidth]=\"'50px'\"\r\n [nzAlign]=\"'center'\"\r\n style=\"text-align: center\"\r\n [(nzChecked)]=\"_checkedAll\"\r\n [nzIndeterminate]=\"_indeterminate\"\r\n (nzCheckedChange)=\"toggleCheckAll($event)\"\r\n (click)=\"$event.stopPropagation()\"\r\n ></th>\r\n <th\r\n *ngFor=\"let column of _columns\"\r\n [nzWidth]=\"column.width\"\r\n [nzAlign]=\"column.align\"\r\n [nzLeft]=\"column.fixedLeft\"\r\n [nzRight]=\"column.fixedRight\"\r\n [nzShowSort]=\"!!column.sorter\"\r\n [nzSortOrder]=\"getSortOrder(column.prop)\"\r\n (nzSortOrderChange)=\"onSortChange(column.prop, $event)\"\r\n >\r\n {{ column.title }}\r\n </th>\r\n </tr>\r\n </thead>\r\n\r\n <tbody>\r\n <tr\r\n style=\"cursor: pointer\"\r\n *ngFor=\"let data; let i = index; of: dynamicTable.data\"\r\n [ngClass]=\"{\r\n 'ant-table-custom-row-selected': !!getTableRowChecked(data),\r\n 'ant-table-custom-row-even': i % 2 === 0,\r\n 'ant-table-custom-row-odd': i % 2 !== 0\r\n }\"\r\n (click)=\"handleTableRowClick(data)\"\r\n (dblclick)=\"handleTableRowDbClick(data)\"\r\n >\r\n <!-- \u590D\u9009\u6846\u5217\uFF08\u5F53 showCheckbox=true \u65F6\u663E\u793A\uFF09 -->\r\n <td\r\n *ngIf=\"showCheckbox\"\r\n [nzAlign]=\"'center'\"\r\n style=\"text-align: center\"\r\n [(nzChecked)]=\"data.checked\"\r\n [nzDisabled]=\"isRowDisabled(data)\"\r\n (nzCheckedChange)=\"handleRowCheckedChange(data, $event)\"\r\n (click)=\"$event.stopPropagation()\"\r\n ></td>\r\n <td\r\n *ngFor=\"let column of _columns\"\r\n [nzLeft]=\"column.fixedLeft\"\r\n [nzRight]=\"column.fixedRight\"\r\n [nzAlign]=\"column.align\"\r\n class=\"pro-ellipsis\"\r\n [title]=\"data[column.prop]\"\r\n >\r\n <!-- \u68C0\u67E5\u662F\u5426\u6709\u81EA\u5B9A\u4E49\u6A21\u677F -->\r\n <ng-container\r\n *ngIf=\"\r\n column.customRender && getTemplate(column.customRender);\r\n let template\r\n \"\r\n >\r\n <ng-template\r\n [ngTemplateOutlet]=\"template\"\r\n [ngTemplateOutletContext]=\"{\r\n $implicit: data,\r\n data: data,\r\n column: column,\r\n index: i,\r\n pageInfo: _pageInfo\r\n }\"\r\n >\r\n </ng-template>\r\n </ng-container>\r\n\r\n <!-- \u9ED8\u8BA4\u6E32\u67D3\u903B\u8F91 -->\r\n <ng-container\r\n *ngIf=\"!column.customRender || !getTemplate(column.customRender)\"\r\n >\r\n {{ data[column.prop] }}\r\n </ng-container>\r\n </td>\r\n </tr>\r\n <tr *ngIf=\"summaryData && _pageInfo.total > 0\">\r\n <!-- \u6C47\u603B\u884C\u7684\u590D\u9009\u6846\u5217\uFF08\u5F53 showCheckbox=true \u65F6\u663E\u793A\uFF0C\u4F46\u4E3A\u7A7A\uFF09 -->\r\n <td\r\n *ngIf=\"showCheckbox\"\r\n style=\"font-weight: bold; border-right: 1px solid #e8e8e8\"\r\n ></td>\r\n <td\r\n *ngFor=\"let column; let i = index; of: _columns\"\r\n [nzLeft]=\"column.fixedLeft\"\r\n [nzRight]=\"column.fixedRight\"\r\n style=\"font-weight: bold; border-right: 1px solid #e8e8e8\"\r\n [nzAlign]=\"column.align\"\r\n >\r\n <span *ngIf=\"i === 0\">\u603B\u8BA1</span>\r\n <ng-container *ngIf=\"i !== 0 && column.summary\">\r\n {{\r\n column.summary?.format\r\n ? column.summary?.format(\r\n summaryData[column.summary?.name || column.prop]\r\n )\r\n : summaryData[column.summary?.name || column.prop]\r\n }}\r\n </ng-container>\r\n </td>\r\n </tr>\r\n </tbody>\r\n <ng-template #totalTemplate let-total\r\n >\u5171 {{ _pageInfo.total }} \u6761\u8BB0\u5F55</ng-template\r\n >\r\n </nz-table>\r\n </ng-template>\r\n</app-page-container>\r\n",
1056
1187
  styles: [".pro-ellipsis{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}::ng-deep .setting-space-item{margin-right:0!important}::ng-deep .pro-table-checkboxgroup-nostyle{white-space:nowrap}::ng-deep .ant-table-bordered .ant-table-container .ant-table-content .ant-table-body table{border-collapse:separate;border-spacing:0}::ng-deep .ant-table-bordered .ant-table-container .ant-table-content .ant-table-body .ant-table-tbody>tr>td{border-right:1px solid #e8e8e8!important}::ng-deep .ant-table-bordered .ant-table-container .ant-table-content .ant-table-body .ant-table-thead>tr>th{border-bottom:1px solid #e8e8e8!important;border-right:1px solid #e8e8e8!important;white-space:nowrap}::ng-deep .ant-table-bordered .ant-table-container .ant-table-content .ant-table-body .ant-table-tbody>tr>td:first-child,::ng-deep .ant-table-bordered .ant-table-container .ant-table-content .ant-table-body .ant-table-thead>tr>th:first-child{border-left:none!important}::ng-deep .ant-table-bordered .ant-table-container .ant-table-content .ant-table-body .ant-table-cell-fix-left,::ng-deep .ant-table-bordered .ant-table-container .ant-table-content .ant-table-body .ant-table-cell-fix-right,::ng-deep .ant-table-bordered .ant-table-container .ant-table-content .ant-table-header .ant-table-thead>tr>th.ant-table-cell-fix-left,::ng-deep .ant-table-bordered .ant-table-container .ant-table-content .ant-table-header .ant-table-thead>tr>th.ant-table-cell-fix-right{border-bottom:1px solid #e8e8e8!important;border-right:1px solid #e8e8e8!important}::ng-deep .ant-table-bordered .ant-table-container .ant-table-content .ant-table-header .ant-table-thead>tr>th{border-top:1px solid #e8e8e8!important}::ng-deep .ant-table-bordered .ant-table-container .ant-table-content .ant-table-body .ant-table-tbody>tr>td:last-child,::ng-deep .ant-table-bordered .ant-table-container .ant-table-content .ant-table-body .ant-table-thead>tr>th:last-child{border-right:1px solid #e8e8e8!important}::ng-deep .ant-table-bordered .ant-table-container .ant-table-content .ant-table-body .ant-table-tbody>tr:last-child>td{border-bottom:1px solid #e8e8e8!important}::ng-deep .table-search-bar-left .ant-form-item{margin-bottom:8px}"]
1057
1188
  },] }
1058
1189
  ];
@@ -1099,19 +1230,21 @@ ProTableComponent.propDecorators = {
1099
1230
  class PageContainerComponent {
1100
1231
  constructor() {
1101
1232
  this.title = "";
1233
+ this.showHeader = true;
1102
1234
  }
1103
1235
  ngOnInit() { }
1104
1236
  }
1105
1237
  PageContainerComponent.decorators = [
1106
1238
  { type: Component, args: [{
1107
1239
  selector: "app-page-container",
1108
- template: "<nz-card\r\n [nzBorderless]=\"true\"\r\n [nzBodyStyle]=\"{ padding: '10px', width: '100%' }\"\r\n>\r\n <div class=\"page-container-title\" *ngIf=\"title\">{{ title }}</div>\r\n <div class=\"page-container-header\">\r\n <ng-container *ngTemplateOutlet=\"headerTpl\"></ng-container>\r\n </div>\r\n <div class=\"page-container-body\">\r\n <ng-container *ngTemplateOutlet=\"bodyTpl\"></ng-container>\r\n </div>\r\n</nz-card>\r\n",
1240
+ template: "<nz-card\r\n [nzBorderless]=\"true\"\r\n [nzBodyStyle]=\"{ padding: '10px', width: '100%' }\"\r\n>\r\n <div class=\"page-container-title\" *ngIf=\"title\">{{ title }}</div>\r\n <div class=\"page-container-header\" *ngIf=\"showHeader\">\r\n <ng-container *ngTemplateOutlet=\"headerTpl\"></ng-container>\r\n </div>\r\n <div class=\"page-container-body\">\r\n <ng-container *ngTemplateOutlet=\"bodyTpl\"></ng-container>\r\n </div>\r\n</nz-card>\r\n",
1109
1241
  styles: [".page-container-title{border-left:3px solid #096dd9;color:#1d1d1d;font-size:16px;margin-bottom:16px;padding-left:10px}.page-container-body,.page-container-header{box-sizing:border-box;padding:7px}"]
1110
1242
  },] }
1111
1243
  ];
1112
1244
  PageContainerComponent.ctorParameters = () => [];
1113
1245
  PageContainerComponent.propDecorators = {
1114
1246
  title: [{ type: Input }],
1247
+ showHeader: [{ type: Input }],
1115
1248
  headerTpl: [{ type: ContentChild, args: ["header",] }],
1116
1249
  bodyTpl: [{ type: ContentChild, args: ["body",] }]
1117
1250
  };
@@ -1718,6 +1851,7 @@ class AntdFormService {
1718
1851
  this.formStore = {};
1719
1852
  this.formModifyType = "create";
1720
1853
  // ==================== 私有属性 ====================
1854
+ this.formRegisterStore = {};
1721
1855
  this.labelWidth = "120px";
1722
1856
  this.labelAlign = "right";
1723
1857
  this.labelObservers = {};
@@ -1732,18 +1866,62 @@ class AntdFormService {
1732
1866
  };
1733
1867
  }
1734
1868
  // ==================== 表单创建和初始化 ====================
1869
+ // 判断是否为嵌套 FormGroup 配置
1870
+ isFormGroupConfig(config) {
1871
+ return (typeof config === "object" &&
1872
+ config !== null &&
1873
+ "type" in config &&
1874
+ config.type === "group");
1875
+ }
1876
+ // 递归创建嵌套 FormGroup
1877
+ createNestedFormGroup(fields, disabled) {
1878
+ const groupConfig = {};
1879
+ Object.entries(fields).forEach(([key, fieldConfig]) => {
1880
+ var _a, _b, _c, _d, _e;
1881
+ if (this.isFormGroupConfig(fieldConfig)) {
1882
+ // 递归创建嵌套的 FormGroup
1883
+ groupConfig[key] = this.createNestedFormGroup(fieldConfig.fields, (_a = fieldConfig.disabled) !== null && _a !== void 0 ? _a : disabled);
1884
+ }
1885
+ else {
1886
+ // 创建普通 FormControl
1887
+ groupConfig[key] = [
1888
+ {
1889
+ value: fieldConfig.value,
1890
+ disabled: (_c = (_b = fieldConfig.disabled) !== null && _b !== void 0 ? _b : disabled) !== null && _c !== void 0 ? _c : false,
1891
+ },
1892
+ (_e = (_d = fieldConfig.validators) === null || _d === void 0 ? void 0 : _d.call(fieldConfig)) !== null && _e !== void 0 ? _e : [],
1893
+ ];
1894
+ }
1895
+ });
1896
+ return this.fb.group(groupConfig);
1897
+ }
1735
1898
  // 初始化表单
1736
1899
  createFormGroup(name, config, options) {
1737
1900
  const groupConfig = {};
1738
1901
  this.errorMessageStore[name] = {};
1739
1902
  Object.entries(config).forEach(([key, fieldConfig]) => {
1740
1903
  var _a, _b, _c;
1741
- groupConfig[key] = [
1742
- { value: fieldConfig.value, disabled: (_a = fieldConfig.disabled) !== null && _a !== void 0 ? _a : false },
1743
- (_c = (_b = fieldConfig.validators) === null || _b === void 0 ? void 0 : _b.call(fieldConfig)) !== null && _c !== void 0 ? _c : [],
1744
- ];
1745
- if (fieldConfig.errorMessages) {
1746
- this.errorMessageStore[name][key] = fieldConfig.errorMessages;
1904
+ if (this.isFormGroupConfig(fieldConfig)) {
1905
+ // 处理嵌套 FormGroup
1906
+ const nestedGroup = this.createNestedFormGroup(fieldConfig.fields, fieldConfig.disabled);
1907
+ groupConfig[key] = nestedGroup;
1908
+ // 存储嵌套 FormGroup 的错误消息(如果需要)
1909
+ if (fieldConfig.errorMessages) {
1910
+ this.errorMessageStore[name][key] = fieldConfig.errorMessages;
1911
+ }
1912
+ }
1913
+ else {
1914
+ // 处理普通字段
1915
+ groupConfig[key] = [
1916
+ {
1917
+ value: fieldConfig.value,
1918
+ disabled: (_a = fieldConfig.disabled) !== null && _a !== void 0 ? _a : false,
1919
+ },
1920
+ (_c = (_b = fieldConfig.validators) === null || _b === void 0 ? void 0 : _b.call(fieldConfig)) !== null && _c !== void 0 ? _c : [],
1921
+ ];
1922
+ if (fieldConfig.errorMessages) {
1923
+ this.errorMessageStore[name][key] = fieldConfig.errorMessages;
1924
+ }
1747
1925
  }
1748
1926
  });
1749
1927
  if (options === null || options === void 0 ? void 0 : options.labelWidth) {
@@ -1753,6 +1931,7 @@ class AntdFormService {
1753
1931
  this.labelAlign = options.labelAlign;
1754
1932
  }
1755
1933
  this.formStore[name] = this.fb.group(groupConfig);
1934
+ this.formRegisterStore[name] = true;
1756
1935
  this.setCSSVariablesToTarget(name);
1757
1936
  return this.formStore[name];
1758
1937
  }
@@ -1762,6 +1941,46 @@ class AntdFormService {
1762
1941
  var _a;
1763
1942
  (_a = this.formStore[name]) === null || _a === void 0 ? void 0 : _a.reset(value);
1764
1943
  }
1944
+ // 检测表单是否完成注册
1945
+ isFormRegistered(name) {
1946
+ var _a;
1947
+ return (_a = this.formRegisterStore[name]) !== null && _a !== void 0 ? _a : false;
1948
+ }
1949
+ // 销毁对应的表单
1950
+ destory(names) {
1951
+ names.forEach((name) => {
1952
+ // 2. 清理错误消息存储
1953
+ if (this.errorMessageStore[name]) {
1954
+ delete this.errorMessageStore[name];
1955
+ }
1956
+ // 3. 清理表单注册标记
1957
+ if (this.formRegisterStore[name]) {
1958
+ delete this.formRegisterStore[name];
1959
+ }
1960
+ // 4. 清理表单组(Angular 会自动处理 FormGroup 的清理)
1961
+ if (this.formStore[name]) {
1962
+ delete this.formStore[name];
1963
+ }
1964
+ });
1965
+ }
1966
+ // 根据路径获取嵌套的 FormGroup
1967
+ getNestedFormGroup(formGroup, path) {
1968
+ if (!path || path.trim() === "") {
1969
+ return formGroup;
1970
+ }
1971
+ const pathParts = path.split(".").filter((p) => p.trim() !== "");
1972
+ let currentGroup = formGroup;
1973
+ for (const part of pathParts) {
1974
+ if (!currentGroup || !(currentGroup instanceof FormGroup)) {
1975
+ return null;
1976
+ }
1977
+ currentGroup = currentGroup.get(part);
1978
+ if (!currentGroup || !(currentGroup instanceof FormGroup)) {
1979
+ return null;
1980
+ }
1981
+ }
1982
+ return currentGroup instanceof FormGroup ? currentGroup : null;
1983
+ }
1765
1984
  // 批量添加字段配置
1766
1985
  addFieldsConfig(formName, fieldsConfig, options) {
1767
1986
  var _a;
@@ -1771,8 +1990,8 @@ class AntdFormService {
1771
1990
  failed: [],
1772
1991
  };
1773
1992
  // 1. 验证表单是否存在
1774
- const formGroup = this.formStore[formName];
1775
- if (!formGroup) {
1993
+ const rootFormGroup = this.formStore[formName];
1994
+ if (!rootFormGroup) {
1776
1995
  // 如果表单不存在,所有字段都失败
1777
1996
  Object.keys(fieldsConfig).forEach((fieldName) => {
1778
1997
  var _a;
@@ -1786,20 +2005,41 @@ class AntdFormService {
1786
2005
  result.success = false;
1787
2006
  return result;
1788
2007
  }
1789
- // 2. 初始化 errorMessageStore(如果不存在)
2008
+ // 2. 获取目标 FormGroup(支持嵌套路径)
2009
+ const targetPath = options === null || options === void 0 ? void 0 : options.targetPath;
2010
+ const targetFormGroup = targetPath
2011
+ ? this.getNestedFormGroup(rootFormGroup, targetPath)
2012
+ : rootFormGroup;
2013
+ if (!targetFormGroup) {
2014
+ // 如果目标 FormGroup 不存在,所有字段都失败
2015
+ Object.keys(fieldsConfig).forEach((fieldName) => {
2016
+ var _a;
2017
+ const error = targetPath
2018
+ ? `Target FormGroup at path "${targetPath}" not found`
2019
+ : `FormGroup not found`;
2020
+ result.failed.push({
2021
+ fieldName,
2022
+ error,
2023
+ });
2024
+ (_a = options === null || options === void 0 ? void 0 : options.onFieldAdded) === null || _a === void 0 ? void 0 : _a.call(options, fieldName, false, error);
2025
+ });
2026
+ result.success = false;
2027
+ return result;
2028
+ }
2029
+ // 3. 初始化 errorMessageStore(如果不存在)
1790
2030
  if (!this.errorMessageStore[formName]) {
1791
2031
  this.errorMessageStore[formName] = {};
1792
2032
  }
1793
- // 3. 批量构建控件配置
2033
+ // 4. 批量构建控件配置
1794
2034
  const controlsToAdd = {};
1795
2035
  const errorMessagesToAdd = {};
1796
- // 4. 遍历所有字段配置,进行验证和构建
2036
+ // 5. 遍历所有字段配置,进行验证和构建
1797
2037
  Object.entries(fieldsConfig).forEach(([fieldName, fieldConfig]) => {
1798
2038
  var _a, _b, _c, _d, _e;
1799
2039
  try {
1800
- // 4.1 检查字段是否已存在
1801
- if (formGroup.get(fieldName)) {
1802
- const error = `Field "${fieldName}" already exists`;
2040
+ // 5.1 检查字段是否已存在
2041
+ if (targetFormGroup.get(fieldName)) {
2042
+ const error = `Field "${fieldName}" already exists${targetPath ? ` in "${targetPath}"` : ""}`;
1803
2043
  result.failed.push({
1804
2044
  fieldName,
1805
2045
  error,
@@ -1807,20 +2047,38 @@ class AntdFormService {
1807
2047
  (_a = options === null || options === void 0 ? void 0 : options.onFieldAdded) === null || _a === void 0 ? void 0 : _a.call(options, fieldName, false, error);
1808
2048
  return;
1809
2049
  }
1810
- // 4.2 创建控件
1811
- const controlOptions = {
1812
- validators: (_c = (_b = fieldConfig.validators) === null || _b === void 0 ? void 0 : _b.call(fieldConfig)) !== null && _c !== void 0 ? _c : [],
1813
- };
1814
- const control = this.fb.control(fieldConfig.value, controlOptions);
1815
- // 设置 disabled 状态
1816
- if (fieldConfig.disabled) {
1817
- control.disable();
2050
+ // 5.2 创建控件
2051
+ let control;
2052
+ if (this.isFormGroupConfig(fieldConfig)) {
2053
+ // 创建嵌套 FormGroup
2054
+ control = this.createNestedFormGroup(fieldConfig.fields, fieldConfig.disabled);
2055
+ // 存储嵌套 FormGroup 的错误消息(如果需要)
2056
+ if (fieldConfig.errorMessages) {
2057
+ const errorMessageKey = targetPath
2058
+ ? `${targetPath}.${fieldName}`
2059
+ : fieldName;
2060
+ errorMessagesToAdd[errorMessageKey] = fieldConfig.errorMessages;
2061
+ }
1818
2062
  }
1819
- controlsToAdd[fieldName] = control;
1820
- // 存储错误消息
1821
- if (fieldConfig.errorMessages) {
1822
- errorMessagesToAdd[fieldName] = fieldConfig.errorMessages;
2063
+ else {
2064
+ // 创建普通 FormControl
2065
+ const controlOptions = {
2066
+ validators: (_c = (_b = fieldConfig.validators) === null || _b === void 0 ? void 0 : _b.call(fieldConfig)) !== null && _c !== void 0 ? _c : [],
2067
+ };
2068
+ control = this.fb.control(fieldConfig.value, controlOptions);
2069
+ // 设置 disabled 状态
2070
+ if (fieldConfig.disabled) {
2071
+ control.disable();
2072
+ }
2073
+ // 存储错误消息
2074
+ if (fieldConfig.errorMessages) {
2075
+ const errorMessageKey = targetPath
2076
+ ? `${targetPath}.${fieldName}`
2077
+ : fieldName;
2078
+ errorMessagesToAdd[errorMessageKey] = fieldConfig.errorMessages;
2079
+ }
1823
2080
  }
2081
+ controlsToAdd[fieldName] = control;
1824
2082
  result.added.push(fieldName);
1825
2083
  (_d = options === null || options === void 0 ? void 0 : options.onFieldAdded) === null || _d === void 0 ? void 0 : _d.call(options, fieldName, true);
1826
2084
  }
@@ -1833,18 +2091,18 @@ class AntdFormService {
1833
2091
  (_e = options === null || options === void 0 ? void 0 : options.onFieldAdded) === null || _e === void 0 ? void 0 : _e.call(options, fieldName, false, errorMessage);
1834
2092
  }
1835
2093
  });
1836
- // 5. 批量添加到 FormGroup
2094
+ // 6. 批量添加到目标 FormGroup
1837
2095
  if (Object.keys(controlsToAdd).length > 0) {
1838
2096
  Object.entries(controlsToAdd).forEach(([fieldName, control]) => {
1839
- formGroup.addControl(fieldName, control);
2097
+ targetFormGroup.addControl(fieldName, control);
1840
2098
  });
1841
- // 6. 批量存储错误消息
2099
+ // 7. 批量存储错误消息
1842
2100
  Object.entries(errorMessagesToAdd).forEach(([key, messages]) => {
1843
2101
  this.errorMessageStore[formName][key] = messages;
1844
2102
  });
1845
- // 7. 更新表单验证状态
2103
+ // 8. 更新表单验证状态
1846
2104
  if (options === null || options === void 0 ? void 0 : options.updateValueAndValidity) {
1847
- formGroup.updateValueAndValidity({
2105
+ targetFormGroup.updateValueAndValidity({
1848
2106
  emitEvent: (_a = options === null || options === void 0 ? void 0 : options.emitEvent) !== null && _a !== void 0 ? _a : true,
1849
2107
  });
1850
2108
  }
@@ -2040,10 +2298,17 @@ class AntdFormService {
2040
2298
  let appliedCount = 0;
2041
2299
  dom.forEach((item) => {
2042
2300
  const target = item;
2043
- if (target.style.width !== this.labelWidth ||
2044
- target.style.textAlign !== this.labelAlign) {
2045
- target.style.width = this.labelWidth;
2046
- target.style.textAlign = this.labelAlign;
2301
+ if (target.closest(".pro-table-container")) {
2302
+ return;
2303
+ }
2304
+ const customWidth = target.getAttribute("custom-width");
2305
+ const customAlign = target.getAttribute("custom-align");
2306
+ const finalWidth = customWidth || this.labelWidth;
2307
+ const finalTextAlign = customAlign || this.labelAlign;
2308
+ if (target.style.width !== finalWidth ||
2309
+ target.style.textAlign !== finalTextAlign) {
2310
+ target.style.width = finalWidth;
2311
+ target.style.textAlign = finalTextAlign;
2047
2312
  appliedCount++;
2048
2313
  }
2049
2314
  });
@@ -2441,6 +2706,34 @@ class ArrayFormService {
2441
2706
  }
2442
2707
  return form.data.some((item) => item.isEdit);
2443
2708
  }
2709
+ // 销毁对应的表单
2710
+ destory(names) {
2711
+ names.forEach((name) => {
2712
+ if (this.formStore[name]) {
2713
+ // 清理表单数据
2714
+ delete this.formStore[name];
2715
+ }
2716
+ });
2717
+ }
2718
+ // 重置表单数组
2719
+ resetFormArray(name) {
2720
+ const form = this.formStore[name];
2721
+ if (!form) {
2722
+ return;
2723
+ }
2724
+ // 1. 清空数据数组
2725
+ form.data = [];
2726
+ // 2. 清理所有快照
2727
+ form.initialSnapshot = {};
2728
+ form.editingSnapshot = {};
2729
+ // 3. 清理校验结果
2730
+ form.validationResults = {};
2731
+ // 4. 重置 touched 状态
2732
+ form.allTouched = false;
2733
+ form.rowTouched = {};
2734
+ // 5. 如果配置了自动更新,更新外部数组引用
2735
+ this.autoUpdateArrayReference(name);
2736
+ }
2444
2737
  }
2445
2738
  ArrayFormService.ɵprov = ɵɵdefineInjectable({ factory: function ArrayFormService_Factory() { return new ArrayFormService(); }, token: ArrayFormService, providedIn: "root" });
2446
2739
  ArrayFormService.decorators = [