@yibozhang/pro-table 0.0.4 → 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.
@@ -669,8 +669,10 @@
669
669
  };
670
670
  this._loading = false;
671
671
  this._selectedTableRow = null;
672
- // 选中的行数据(用于复选框选择)
672
+ // 选中的行数据(用于复选框选择)- 保留用于兼容性
673
673
  this._selectedRows = [];
674
+ // 使用 Set 存储选中项的 ID,支持跨页选中
675
+ this._selectedRowIds = new Set();
674
676
  // 全选状态
675
677
  this._checkedAll = false;
676
678
  // 半选状态(部分选中)
@@ -1267,7 +1269,12 @@
1267
1269
  return this._selectedTableRow;
1268
1270
  };
1269
1271
  ProTableComponent.prototype.getCheckedRows = function () {
1270
- return this._selectedRows;
1272
+ if (!this.showCheckbox) {
1273
+ return [];
1274
+ }
1275
+ // 返回当前数据源中所有 checked 为 true 的项
1276
+ // 注意:如果需要获取所有页的选中项,需要遍历所有数据源或使用 _selectedRowIds
1277
+ return this.dataSource.filter(function (row) { return row.checked === true; });
1271
1278
  };
1272
1279
  // 获取指定名称的模板
1273
1280
  ProTableComponent.prototype.getTemplate = function (name) {
@@ -1314,14 +1321,16 @@
1314
1321
  return false;
1315
1322
  return this.rowDisabled ? this.rowDisabled(data) : false;
1316
1323
  };
1317
- // 检查行是否被复选框选中
1324
+ // 检查行是否被复选框选中(数据驱动模式)
1318
1325
  ProTableComponent.prototype.isRowChecked = function (data) {
1319
1326
  if (!this.showCheckbox)
1320
1327
  return false;
1321
- return this._selectedRows.some(function (row) { return JSON.stringify(row) === JSON.stringify(data); });
1328
+ // 直接读取数据对象的 checked 属性
1329
+ return data.checked === true;
1322
1330
  };
1323
- // 切换行的选中状态
1331
+ // 切换行的选中状态(数据驱动模式,保留用于兼容)
1324
1332
  ProTableComponent.prototype.toggleRowChecked = function (data, checked, event) {
1333
+ var _this = this;
1325
1334
  if (event) {
1326
1335
  event.stopPropagation(); // 阻止事件冒泡,避免触发行点击
1327
1336
  }
@@ -1329,9 +1338,21 @@
1329
1338
  if (this.isRowDisabled(data)) {
1330
1339
  return;
1331
1340
  }
1332
- var index = this._selectedRows.findIndex(function (row) { return JSON.stringify(row) === JSON.stringify(data); });
1341
+ // 直接设置数据对象的 checked 属性
1342
+ data.checked = checked;
1343
+ // 同步更新 _selectedRowIds(用于跨页选中)
1344
+ var id = this.getRowId(data);
1345
+ if (id !== undefined) {
1346
+ if (checked) {
1347
+ this._selectedRowIds.add(id);
1348
+ }
1349
+ else {
1350
+ this._selectedRowIds.delete(id);
1351
+ }
1352
+ }
1353
+ // 同步更新 _selectedRows(用于兼容性)
1354
+ var index = this._selectedRows.findIndex(function (row) { return _this.isSameRow(row, data); });
1333
1355
  if (checked) {
1334
- // 选中
1335
1356
  if (index === -1) {
1336
1357
  this._selectedRows.push(data);
1337
1358
  }
@@ -1339,19 +1360,18 @@
1339
1360
  this._selectedTableRow = data;
1340
1361
  }
1341
1362
  else {
1342
- // 取消选中
1343
1363
  if (index > -1) {
1344
1364
  this._selectedRows.splice(index, 1);
1345
1365
  }
1346
1366
  // 若当前高亮行为该行,则取消高亮
1347
1367
  if (this._selectedTableRow &&
1348
- JSON.stringify(this._selectedTableRow) === JSON.stringify(data)) {
1368
+ this.isSameRow(this._selectedTableRow, data)) {
1349
1369
  this._selectedTableRow = null;
1350
1370
  }
1351
1371
  }
1352
1372
  this.updateCheckAllStatus();
1353
1373
  };
1354
- // 更新全选状态
1374
+ // 更新全选状态(数据驱动模式)
1355
1375
  ProTableComponent.prototype.updateCheckAllStatus = function () {
1356
1376
  var _this = this;
1357
1377
  if (!this.showCheckbox || !Array.isArray(this.dataSource)) {
@@ -1361,40 +1381,122 @@
1361
1381
  }
1362
1382
  // 只计算可用的行(未禁用的行)
1363
1383
  var availableRows = this.dataSource.filter(function (row) { return !_this.isRowDisabled(row); });
1364
- var checkedCount = this._selectedRows.length;
1384
+ // 基于数据对象的 checked 属性计算
1385
+ var checkedCount = availableRows.filter(function (row) { return row.checked === true; }).length;
1365
1386
  var totalCount = availableRows.length;
1366
1387
  this._checkedAll =
1367
1388
  totalCount > 0 && checkedCount > 0 && checkedCount === totalCount;
1368
1389
  this._indeterminate = checkedCount > 0 && checkedCount < totalCount;
1369
1390
  };
1370
- // 全选/取消全选
1391
+ // 全选/取消全选(数据驱动模式)
1371
1392
  ProTableComponent.prototype.toggleCheckAll = function (checked, event) {
1372
1393
  var _this = this;
1373
1394
  if (event) {
1374
1395
  event.stopPropagation();
1375
1396
  }
1397
+ // 只处理可用的行(未禁用的行)
1398
+ var availableRows = this.dataSource.filter(function (row) { return !_this.isRowDisabled(row); });
1399
+ // 批量设置 checked 属性
1400
+ availableRows.forEach(function (row) {
1401
+ row.checked = checked;
1402
+ // 同步更新 _selectedRowIds(用于跨页选中)
1403
+ var id = _this.getRowId(row);
1404
+ if (id !== undefined) {
1405
+ if (checked) {
1406
+ _this._selectedRowIds.add(id);
1407
+ }
1408
+ else {
1409
+ _this._selectedRowIds.delete(id);
1410
+ }
1411
+ }
1412
+ });
1413
+ // 同步更新 _selectedRows(用于兼容性)
1376
1414
  if (checked) {
1377
- // 全选:只选中未禁用的行
1378
- this._selectedRows = this.dataSource.filter(function (row) { return !_this.isRowDisabled(row); });
1415
+ this._selectedRows = __spread(availableRows);
1379
1416
  // 同步设置高亮选中行为第一条可选数据
1380
- var availableRows = this._selectedRows;
1381
1417
  this._selectedTableRow =
1382
1418
  availableRows.length > 0 ? availableRows[0] : null;
1383
1419
  }
1384
1420
  else {
1385
- // 取消全选
1386
1421
  this._selectedRows = [];
1387
1422
  // 取消高亮
1388
1423
  this._selectedTableRow = null;
1389
1424
  }
1390
1425
  this.updateCheckAllStatus();
1391
1426
  };
1392
- // 获取选中的行数据
1427
+ // 获取选中的行数据(保留用于兼容性)
1393
1428
  ProTableComponent.prototype.getSelectedRows = function () {
1394
- return this._selectedRows;
1429
+ return this.getCheckedRows();
1430
+ };
1431
+ // 处理行 checkbox 变化事件(数据驱动模式)
1432
+ ProTableComponent.prototype.handleRowCheckedChange = function (data, checked) {
1433
+ var _this = this;
1434
+ if (this.isRowDisabled(data)) {
1435
+ return;
1436
+ }
1437
+ // 数据对象的 checked 属性已经通过双向绑定自动更新
1438
+ // 这里只需要同步更新 _selectedRowIds 和 _selectedRows
1439
+ // 同步更新 _selectedRowIds(用于跨页选中)
1440
+ var id = this.getRowId(data);
1441
+ if (id !== undefined) {
1442
+ if (checked) {
1443
+ this._selectedRowIds.add(id);
1444
+ }
1445
+ else {
1446
+ this._selectedRowIds.delete(id);
1447
+ }
1448
+ }
1449
+ // 同步更新 _selectedRows(用于兼容性)
1450
+ var index = this._selectedRows.findIndex(function (row) { return _this.isSameRow(row, data); });
1451
+ if (checked) {
1452
+ if (index === -1) {
1453
+ this._selectedRows.push(data);
1454
+ }
1455
+ // 勾选复选框时同步设置高亮选中行
1456
+ this._selectedTableRow = data;
1457
+ }
1458
+ else {
1459
+ if (index > -1) {
1460
+ this._selectedRows.splice(index, 1);
1461
+ }
1462
+ // 若当前高亮行为该行,则取消高亮
1463
+ if (this._selectedTableRow &&
1464
+ this.isSameRow(this._selectedTableRow, data)) {
1465
+ this._selectedTableRow = null;
1466
+ }
1467
+ }
1468
+ // 更新全选状态
1469
+ this.updateCheckAllStatus();
1395
1470
  };
1396
- // 清空选中的行
1471
+ // 刷新全选状态(用于其他场景)
1472
+ ProTableComponent.prototype.refreshCheckAllStatus = function () {
1473
+ this.updateCheckAllStatus();
1474
+ };
1475
+ // 获取行的唯一标识(用于跨页选中)
1476
+ ProTableComponent.prototype.getRowId = function (data) {
1477
+ var _a, _b;
1478
+ return (_b = (_a = data.id) !== null && _a !== void 0 ? _a : data.key) !== null && _b !== void 0 ? _b : undefined;
1479
+ };
1480
+ // 判断两行是否为同一行
1481
+ ProTableComponent.prototype.isSameRow = function (row1, row2) {
1482
+ var id1 = this.getRowId(row1);
1483
+ var id2 = this.getRowId(row2);
1484
+ if (id1 !== undefined && id2 !== undefined) {
1485
+ return id1 === id2;
1486
+ }
1487
+ // fallback 到 JSON 比较
1488
+ return JSON.stringify(row1) === JSON.stringify(row2);
1489
+ };
1490
+ // 清空选中的行(数据驱动模式)
1397
1491
  ProTableComponent.prototype.clearSelectedRows = function () {
1492
+ // 清空当前数据源中所有项的 checked 状态
1493
+ if (Array.isArray(this.dataSource)) {
1494
+ this.dataSource.forEach(function (row) {
1495
+ row.checked = false;
1496
+ });
1497
+ }
1498
+ // 清空选中集合
1499
+ this._selectedRowIds.clear();
1398
1500
  this._selectedRows = [];
1399
1501
  this._checkedAll = false;
1400
1502
  this._indeterminate = false;
@@ -1466,7 +1568,8 @@
1466
1568
  };
1467
1569
  ProTableComponent.prototype.handleQuery = function (afterDelete) {
1468
1570
  return __awaiter(this, void 0, void 0, function () {
1469
- var result, error_4;
1571
+ var previousDataSource, result, newDataIds_1, error_4;
1572
+ var _this = this;
1470
1573
  return __generator(this, function (_d) {
1471
1574
  switch (_d.label) {
1472
1575
  case 0:
@@ -1477,6 +1580,7 @@
1477
1580
  this._pageInfo.pageIndex > 1) {
1478
1581
  this._pageInfo.pageIndex = this._pageInfo.pageIndex - 1;
1479
1582
  }
1583
+ previousDataSource = afterDelete && this.showCheckbox ? __spread(this.dataSource) : [];
1480
1584
  this._loading = true;
1481
1585
  if (!this.request) return [3 /*break*/, 6];
1482
1586
  _d.label = 1;
@@ -1490,7 +1594,38 @@
1490
1594
  : {})))];
1491
1595
  case 2:
1492
1596
  result = _d.sent();
1493
- this.dataSource = result.data || [];
1597
+ // 自动注入 checked 字段,支持跨页选中
1598
+ if (this.showCheckbox) {
1599
+ this.dataSource = (result.data || []).map(function (item) {
1600
+ var id = _this.getRowId(item);
1601
+ // 如果数据已有 checked 属性,保留;否则根据 _selectedRowIds 判断
1602
+ var checked = item.checked !== undefined
1603
+ ? item.checked
1604
+ : id !== undefined
1605
+ ? _this._selectedRowIds.has(id)
1606
+ : false;
1607
+ return Object.assign(Object.assign({}, item), { checked: checked });
1608
+ });
1609
+ // 删除后查询:移除被删除项的选中状态
1610
+ if (afterDelete && previousDataSource.length > 0) {
1611
+ newDataIds_1 = new Set(this.dataSource.map(function (item) { return _this.getRowId(item); }));
1612
+ // 遍历之前的数据源,如果不在新数据源中,说明被删除了,需要清除其选中状态
1613
+ previousDataSource.forEach(function (oldItem) {
1614
+ var oldId = _this.getRowId(oldItem);
1615
+ if (oldId !== undefined && !newDataIds_1.has(oldId)) {
1616
+ // 被删除的项,从选中集合中移除
1617
+ _this._selectedRowIds.delete(oldId);
1618
+ // 如果数据对象还在其他地方引用,清除其选中状态
1619
+ if (oldItem.checked !== undefined) {
1620
+ oldItem.checked = false;
1621
+ }
1622
+ }
1623
+ });
1624
+ }
1625
+ }
1626
+ else {
1627
+ this.dataSource = result.data || [];
1628
+ }
1494
1629
  this.summaryData = result.summaryData || null;
1495
1630
  // 本地排序模式:拿到数据后在前端排序
1496
1631
  if (this.sortMode === "local") {
@@ -1518,9 +1653,7 @@
1518
1653
  console.warn("未提供 _request 回调函数");
1519
1654
  this._loading = false;
1520
1655
  _d.label = 7;
1521
- case 7:
1522
- this.clearSelectedRows();
1523
- return [2 /*return*/];
1656
+ case 7: return [2 /*return*/];
1524
1657
  }
1525
1658
  });
1526
1659
  });
@@ -1632,7 +1765,7 @@
1632
1765
  ProTableComponent.decorators = [
1633
1766
  { type: i0.Component, args: [{
1634
1767
  selector: "app-pro-table",
1635
- 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",
1768
+ 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",
1636
1769
  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}"]
1637
1770
  },] }
1638
1771
  ];
@@ -1679,6 +1812,7 @@
1679
1812
  var PageContainerComponent = /** @class */ (function () {
1680
1813
  function PageContainerComponent() {
1681
1814
  this.title = "";
1815
+ this.showHeader = true;
1682
1816
  }
1683
1817
  PageContainerComponent.prototype.ngOnInit = function () { };
1684
1818
  return PageContainerComponent;
@@ -1686,13 +1820,14 @@
1686
1820
  PageContainerComponent.decorators = [
1687
1821
  { type: i0.Component, args: [{
1688
1822
  selector: "app-page-container",
1689
- 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",
1823
+ 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",
1690
1824
  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}"]
1691
1825
  },] }
1692
1826
  ];
1693
1827
  PageContainerComponent.ctorParameters = function () { return []; };
1694
1828
  PageContainerComponent.propDecorators = {
1695
1829
  title: [{ type: i0.Input }],
1830
+ showHeader: [{ type: i0.Input }],
1696
1831
  headerTpl: [{ type: i0.ContentChild, args: ["header",] }],
1697
1832
  bodyTpl: [{ type: i0.ContentChild, args: ["body",] }]
1698
1833
  };
@@ -2324,6 +2459,7 @@
2324
2459
  this.formStore = {};
2325
2460
  this.formModifyType = "create";
2326
2461
  // ==================== 私有属性 ====================
2462
+ this.formRegisterStore = {};
2327
2463
  this.labelWidth = "120px";
2328
2464
  this.labelAlign = "right";
2329
2465
  this.labelObservers = {};
@@ -2338,6 +2474,37 @@
2338
2474
  };
2339
2475
  }
2340
2476
  // ==================== 表单创建和初始化 ====================
2477
+ // 判断是否为嵌套 FormGroup 配置
2478
+ AntdFormService.prototype.isFormGroupConfig = function (config) {
2479
+ return (typeof config === "object" &&
2480
+ config !== null &&
2481
+ "type" in config &&
2482
+ config.type === "group");
2483
+ };
2484
+ // 递归创建嵌套 FormGroup
2485
+ AntdFormService.prototype.createNestedFormGroup = function (fields, disabled) {
2486
+ var _this = this;
2487
+ var groupConfig = {};
2488
+ Object.entries(fields).forEach(function (_f) {
2489
+ var _g = __read(_f, 2), key = _g[0], fieldConfig = _g[1];
2490
+ var _a, _b, _c, _d, _e;
2491
+ if (_this.isFormGroupConfig(fieldConfig)) {
2492
+ // 递归创建嵌套的 FormGroup
2493
+ groupConfig[key] = _this.createNestedFormGroup(fieldConfig.fields, (_a = fieldConfig.disabled) !== null && _a !== void 0 ? _a : disabled);
2494
+ }
2495
+ else {
2496
+ // 创建普通 FormControl
2497
+ groupConfig[key] = [
2498
+ {
2499
+ value: fieldConfig.value,
2500
+ disabled: (_c = (_b = fieldConfig.disabled) !== null && _b !== void 0 ? _b : disabled) !== null && _c !== void 0 ? _c : false,
2501
+ },
2502
+ (_e = (_d = fieldConfig.validators) === null || _d === void 0 ? void 0 : _d.call(fieldConfig)) !== null && _e !== void 0 ? _e : [],
2503
+ ];
2504
+ }
2505
+ });
2506
+ return this.fb.group(groupConfig);
2507
+ };
2341
2508
  // 初始化表单
2342
2509
  AntdFormService.prototype.createFormGroup = function (name, config, options) {
2343
2510
  var _this = this;
@@ -2346,12 +2513,27 @@
2346
2513
  Object.entries(config).forEach(function (_f) {
2347
2514
  var _g = __read(_f, 2), key = _g[0], fieldConfig = _g[1];
2348
2515
  var _a, _b, _c;
2349
- groupConfig[key] = [
2350
- { value: fieldConfig.value, disabled: (_a = fieldConfig.disabled) !== null && _a !== void 0 ? _a : false },
2351
- (_c = (_b = fieldConfig.validators) === null || _b === void 0 ? void 0 : _b.call(fieldConfig)) !== null && _c !== void 0 ? _c : [],
2352
- ];
2353
- if (fieldConfig.errorMessages) {
2354
- _this.errorMessageStore[name][key] = fieldConfig.errorMessages;
2516
+ if (_this.isFormGroupConfig(fieldConfig)) {
2517
+ // 处理嵌套 FormGroup
2518
+ var nestedGroup = _this.createNestedFormGroup(fieldConfig.fields, fieldConfig.disabled);
2519
+ groupConfig[key] = nestedGroup;
2520
+ // 存储嵌套 FormGroup 的错误消息(如果需要)
2521
+ if (fieldConfig.errorMessages) {
2522
+ _this.errorMessageStore[name][key] = fieldConfig.errorMessages;
2523
+ }
2524
+ }
2525
+ else {
2526
+ // 处理普通字段
2527
+ groupConfig[key] = [
2528
+ {
2529
+ value: fieldConfig.value,
2530
+ disabled: (_a = fieldConfig.disabled) !== null && _a !== void 0 ? _a : false,
2531
+ },
2532
+ (_c = (_b = fieldConfig.validators) === null || _b === void 0 ? void 0 : _b.call(fieldConfig)) !== null && _c !== void 0 ? _c : [],
2533
+ ];
2534
+ if (fieldConfig.errorMessages) {
2535
+ _this.errorMessageStore[name][key] = fieldConfig.errorMessages;
2536
+ }
2355
2537
  }
2356
2538
  });
2357
2539
  if (options === null || options === void 0 ? void 0 : options.labelWidth) {
@@ -2361,6 +2543,7 @@
2361
2543
  this.labelAlign = options.labelAlign;
2362
2544
  }
2363
2545
  this.formStore[name] = this.fb.group(groupConfig);
2546
+ this.formRegisterStore[name] = true;
2364
2547
  this.setCSSVariablesToTarget(name);
2365
2548
  return this.formStore[name];
2366
2549
  };
@@ -2370,6 +2553,58 @@
2370
2553
  var _a;
2371
2554
  (_a = this.formStore[name]) === null || _a === void 0 ? void 0 : _a.reset(value);
2372
2555
  };
2556
+ // 检测表单是否完成注册
2557
+ AntdFormService.prototype.isFormRegistered = function (name) {
2558
+ var _a;
2559
+ return (_a = this.formRegisterStore[name]) !== null && _a !== void 0 ? _a : false;
2560
+ };
2561
+ // 销毁对应的表单
2562
+ AntdFormService.prototype.destory = function (names) {
2563
+ var _this = this;
2564
+ names.forEach(function (name) {
2565
+ // 2. 清理错误消息存储
2566
+ if (_this.errorMessageStore[name]) {
2567
+ delete _this.errorMessageStore[name];
2568
+ }
2569
+ // 3. 清理表单注册标记
2570
+ if (_this.formRegisterStore[name]) {
2571
+ delete _this.formRegisterStore[name];
2572
+ }
2573
+ // 4. 清理表单组(Angular 会自动处理 FormGroup 的清理)
2574
+ if (_this.formStore[name]) {
2575
+ delete _this.formStore[name];
2576
+ }
2577
+ });
2578
+ };
2579
+ // 根据路径获取嵌套的 FormGroup
2580
+ AntdFormService.prototype.getNestedFormGroup = function (formGroup, path) {
2581
+ var e_1, _f;
2582
+ if (!path || path.trim() === "") {
2583
+ return formGroup;
2584
+ }
2585
+ var pathParts = path.split(".").filter(function (p) { return p.trim() !== ""; });
2586
+ var currentGroup = formGroup;
2587
+ try {
2588
+ for (var pathParts_1 = __values(pathParts), pathParts_1_1 = pathParts_1.next(); !pathParts_1_1.done; pathParts_1_1 = pathParts_1.next()) {
2589
+ var part = pathParts_1_1.value;
2590
+ if (!currentGroup || !(currentGroup instanceof i1.FormGroup)) {
2591
+ return null;
2592
+ }
2593
+ currentGroup = currentGroup.get(part);
2594
+ if (!currentGroup || !(currentGroup instanceof i1.FormGroup)) {
2595
+ return null;
2596
+ }
2597
+ }
2598
+ }
2599
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
2600
+ finally {
2601
+ try {
2602
+ if (pathParts_1_1 && !pathParts_1_1.done && (_f = pathParts_1.return)) _f.call(pathParts_1);
2603
+ }
2604
+ finally { if (e_1) throw e_1.error; }
2605
+ }
2606
+ return currentGroup instanceof i1.FormGroup ? currentGroup : null;
2607
+ };
2373
2608
  // 批量添加字段配置
2374
2609
  AntdFormService.prototype.addFieldsConfig = function (formName, fieldsConfig, options) {
2375
2610
  var _this = this;
@@ -2380,8 +2615,8 @@
2380
2615
  failed: [],
2381
2616
  };
2382
2617
  // 1. 验证表单是否存在
2383
- var formGroup = this.formStore[formName];
2384
- if (!formGroup) {
2618
+ var rootFormGroup = this.formStore[formName];
2619
+ if (!rootFormGroup) {
2385
2620
  // 如果表单不存在,所有字段都失败
2386
2621
  Object.keys(fieldsConfig).forEach(function (fieldName) {
2387
2622
  var _a;
@@ -2395,21 +2630,42 @@
2395
2630
  result.success = false;
2396
2631
  return result;
2397
2632
  }
2398
- // 2. 初始化 errorMessageStore(如果不存在)
2633
+ // 2. 获取目标 FormGroup(支持嵌套路径)
2634
+ var targetPath = options === null || options === void 0 ? void 0 : options.targetPath;
2635
+ var targetFormGroup = targetPath
2636
+ ? this.getNestedFormGroup(rootFormGroup, targetPath)
2637
+ : rootFormGroup;
2638
+ if (!targetFormGroup) {
2639
+ // 如果目标 FormGroup 不存在,所有字段都失败
2640
+ Object.keys(fieldsConfig).forEach(function (fieldName) {
2641
+ var _a;
2642
+ var error = targetPath
2643
+ ? "Target FormGroup at path \"" + targetPath + "\" not found"
2644
+ : "FormGroup not found";
2645
+ result.failed.push({
2646
+ fieldName: fieldName,
2647
+ error: error,
2648
+ });
2649
+ (_a = options === null || options === void 0 ? void 0 : options.onFieldAdded) === null || _a === void 0 ? void 0 : _a.call(options, fieldName, false, error);
2650
+ });
2651
+ result.success = false;
2652
+ return result;
2653
+ }
2654
+ // 3. 初始化 errorMessageStore(如果不存在)
2399
2655
  if (!this.errorMessageStore[formName]) {
2400
2656
  this.errorMessageStore[formName] = {};
2401
2657
  }
2402
- // 3. 批量构建控件配置
2658
+ // 4. 批量构建控件配置
2403
2659
  var controlsToAdd = {};
2404
2660
  var errorMessagesToAdd = {};
2405
- // 4. 遍历所有字段配置,进行验证和构建
2661
+ // 5. 遍历所有字段配置,进行验证和构建
2406
2662
  Object.entries(fieldsConfig).forEach(function (_f) {
2407
2663
  var _g = __read(_f, 2), fieldName = _g[0], fieldConfig = _g[1];
2408
2664
  var _a, _b, _c, _d, _e;
2409
2665
  try {
2410
- // 4.1 检查字段是否已存在
2411
- if (formGroup.get(fieldName)) {
2412
- var error = "Field \"" + fieldName + "\" already exists";
2666
+ // 5.1 检查字段是否已存在
2667
+ if (targetFormGroup.get(fieldName)) {
2668
+ var error = "Field \"" + fieldName + "\" already exists" + (targetPath ? " in \"" + targetPath + "\"" : "");
2413
2669
  result.failed.push({
2414
2670
  fieldName: fieldName,
2415
2671
  error: error,
@@ -2417,20 +2673,38 @@
2417
2673
  (_a = options === null || options === void 0 ? void 0 : options.onFieldAdded) === null || _a === void 0 ? void 0 : _a.call(options, fieldName, false, error);
2418
2674
  return;
2419
2675
  }
2420
- // 4.2 创建控件
2421
- var controlOptions = {
2422
- validators: (_c = (_b = fieldConfig.validators) === null || _b === void 0 ? void 0 : _b.call(fieldConfig)) !== null && _c !== void 0 ? _c : [],
2423
- };
2424
- var control = _this.fb.control(fieldConfig.value, controlOptions);
2425
- // 设置 disabled 状态
2426
- if (fieldConfig.disabled) {
2427
- control.disable();
2676
+ // 5.2 创建控件
2677
+ var control = void 0;
2678
+ if (_this.isFormGroupConfig(fieldConfig)) {
2679
+ // 创建嵌套 FormGroup
2680
+ control = _this.createNestedFormGroup(fieldConfig.fields, fieldConfig.disabled);
2681
+ // 存储嵌套 FormGroup 的错误消息(如果需要)
2682
+ if (fieldConfig.errorMessages) {
2683
+ var errorMessageKey = targetPath
2684
+ ? targetPath + "." + fieldName
2685
+ : fieldName;
2686
+ errorMessagesToAdd[errorMessageKey] = fieldConfig.errorMessages;
2687
+ }
2428
2688
  }
2429
- controlsToAdd[fieldName] = control;
2430
- // 存储错误消息
2431
- if (fieldConfig.errorMessages) {
2432
- errorMessagesToAdd[fieldName] = fieldConfig.errorMessages;
2689
+ else {
2690
+ // 创建普通 FormControl
2691
+ var controlOptions = {
2692
+ validators: (_c = (_b = fieldConfig.validators) === null || _b === void 0 ? void 0 : _b.call(fieldConfig)) !== null && _c !== void 0 ? _c : [],
2693
+ };
2694
+ control = _this.fb.control(fieldConfig.value, controlOptions);
2695
+ // 设置 disabled 状态
2696
+ if (fieldConfig.disabled) {
2697
+ control.disable();
2698
+ }
2699
+ // 存储错误消息
2700
+ if (fieldConfig.errorMessages) {
2701
+ var errorMessageKey = targetPath
2702
+ ? targetPath + "." + fieldName
2703
+ : fieldName;
2704
+ errorMessagesToAdd[errorMessageKey] = fieldConfig.errorMessages;
2705
+ }
2433
2706
  }
2707
+ controlsToAdd[fieldName] = control;
2434
2708
  result.added.push(fieldName);
2435
2709
  (_d = options === null || options === void 0 ? void 0 : options.onFieldAdded) === null || _d === void 0 ? void 0 : _d.call(options, fieldName, true);
2436
2710
  }
@@ -2443,20 +2717,20 @@
2443
2717
  (_e = options === null || options === void 0 ? void 0 : options.onFieldAdded) === null || _e === void 0 ? void 0 : _e.call(options, fieldName, false, errorMessage);
2444
2718
  }
2445
2719
  });
2446
- // 5. 批量添加到 FormGroup
2720
+ // 6. 批量添加到目标 FormGroup
2447
2721
  if (Object.keys(controlsToAdd).length > 0) {
2448
2722
  Object.entries(controlsToAdd).forEach(function (_f) {
2449
2723
  var _g = __read(_f, 2), fieldName = _g[0], control = _g[1];
2450
- formGroup.addControl(fieldName, control);
2724
+ targetFormGroup.addControl(fieldName, control);
2451
2725
  });
2452
- // 6. 批量存储错误消息
2726
+ // 7. 批量存储错误消息
2453
2727
  Object.entries(errorMessagesToAdd).forEach(function (_f) {
2454
2728
  var _g = __read(_f, 2), key = _g[0], messages = _g[1];
2455
2729
  _this.errorMessageStore[formName][key] = messages;
2456
2730
  });
2457
- // 7. 更新表单验证状态
2731
+ // 8. 更新表单验证状态
2458
2732
  if (options === null || options === void 0 ? void 0 : options.updateValueAndValidity) {
2459
- formGroup.updateValueAndValidity({
2733
+ targetFormGroup.updateValueAndValidity({
2460
2734
  emitEvent: (_a = options === null || options === void 0 ? void 0 : options.emitEvent) !== null && _a !== void 0 ? _a : true,
2461
2735
  });
2462
2736
  }
@@ -2587,7 +2861,7 @@
2587
2861
  // ==================== 错误消息相关 ====================
2588
2862
  // 获取字段首条错误提示
2589
2863
  AntdFormService.prototype.getFieldErrorMessage = function (name, controlName) {
2590
- var e_1, _f;
2864
+ var e_2, _f;
2591
2865
  var _a;
2592
2866
  var formGroup = this.formStore[name];
2593
2867
  if (!formGroup) {
@@ -2615,12 +2889,12 @@
2615
2889
  }
2616
2890
  }
2617
2891
  }
2618
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
2892
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
2619
2893
  finally {
2620
2894
  try {
2621
2895
  if (_h && !_h.done && (_f = _g.return)) _f.call(_g);
2622
2896
  }
2623
- finally { if (e_1) throw e_1.error; }
2897
+ finally { if (e_2) throw e_2.error; }
2624
2898
  }
2625
2899
  return "";
2626
2900
  };
@@ -2666,10 +2940,17 @@
2666
2940
  var appliedCount = 0;
2667
2941
  dom.forEach(function (item) {
2668
2942
  var target = item;
2669
- if (target.style.width !== _this.labelWidth ||
2670
- target.style.textAlign !== _this.labelAlign) {
2671
- target.style.width = _this.labelWidth;
2672
- target.style.textAlign = _this.labelAlign;
2943
+ if (target.closest(".pro-table-container")) {
2944
+ return;
2945
+ }
2946
+ var customWidth = target.getAttribute("custom-width");
2947
+ var customAlign = target.getAttribute("custom-align");
2948
+ var finalWidth = customWidth || _this.labelWidth;
2949
+ var finalTextAlign = customAlign || _this.labelAlign;
2950
+ if (target.style.width !== finalWidth ||
2951
+ target.style.textAlign !== finalTextAlign) {
2952
+ target.style.width = finalWidth;
2953
+ target.style.textAlign = finalTextAlign;
2673
2954
  appliedCount++;
2674
2955
  }
2675
2956
  });
@@ -2742,60 +3023,90 @@
2742
3023
  { type: i1.FormBuilder }
2743
3024
  ]; };
2744
3025
 
2745
- /**
2746
- * 数组型数据收集基础服务
2747
- *
2748
- * 功能:
2749
- * 1. 支持通过 ngModel 绑定对应行的数据源
2750
- * 2. 自动为数组数据添加 isEdit 和 uid 字段
2751
- * 3. 支持每个字段的自定义校验方法,返回 'success' | 'warning' | 'error'
2752
- * 4. 提供公共方法支持删除、新增、编辑等操作
2753
- */
3026
+ /** 数组型数据收集基础服务 */
2754
3027
  var ArrayFormService = /** @class */ (function () {
2755
3028
  function ArrayFormService() {
2756
3029
  this.formStore = {};
2757
3030
  }
2758
- /**
2759
- * 初始化数组数据
2760
- * 为现有数据添加 uid 和 isEdit 字段
2761
- *
2762
- * @param data 原始数据数组
2763
- * @param config 表单配置
2764
- * @returns 初始化后的数据数组
2765
- */
3031
+ /** 深度克隆值 */
3032
+ ArrayFormService.prototype.cloneValue = function (value) {
3033
+ var e_1, _c;
3034
+ var _this = this;
3035
+ if (value === null || value === undefined) {
3036
+ return value;
3037
+ }
3038
+ if (Array.isArray(value)) {
3039
+ return value.map(function (item) { return _this.cloneValue(item); });
3040
+ }
3041
+ if (typeof value === "object") {
3042
+ var cloned = {};
3043
+ try {
3044
+ for (var _d = __values(Object.keys(value)), _e = _d.next(); !_e.done; _e = _d.next()) {
3045
+ var key = _e.value;
3046
+ cloned[key] = this.cloneValue(value[key]);
3047
+ }
3048
+ }
3049
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
3050
+ finally {
3051
+ try {
3052
+ if (_e && !_e.done && (_c = _d.return)) _c.call(_d);
3053
+ }
3054
+ finally { if (e_1) throw e_1.error; }
3055
+ }
3056
+ return cloned;
3057
+ }
3058
+ return value;
3059
+ };
3060
+ /** 比较两个值是否相等 */
3061
+ ArrayFormService.prototype.isEqual = function (a, b) {
3062
+ var _this = this;
3063
+ if (a === b)
3064
+ return true;
3065
+ if (a === null || b === null)
3066
+ return a === b;
3067
+ if (a === undefined || b === undefined)
3068
+ return a === b;
3069
+ if (typeof a !== typeof b)
3070
+ return false;
3071
+ if (Array.isArray(a) && Array.isArray(b)) {
3072
+ if (a.length !== b.length)
3073
+ return false;
3074
+ return a.every(function (item, index) { return _this.isEqual(item, b[index]); });
3075
+ }
3076
+ if (typeof a === "object" && typeof b === "object") {
3077
+ var keysA = Object.keys(a);
3078
+ var keysB = Object.keys(b);
3079
+ if (keysA.length !== keysB.length)
3080
+ return false;
3081
+ return keysA.every(function (key) { return _this.isEqual(a[key], b[key]); });
3082
+ }
3083
+ return false;
3084
+ };
3085
+ /** 创建行的初始值快照 */
3086
+ ArrayFormService.prototype.createRowSnapshot = function (row, fields) {
3087
+ var _this = this;
3088
+ var snapshot = {};
3089
+ fields.forEach(function (field) {
3090
+ snapshot[field.name] = _this.cloneValue(row[field.name]);
3091
+ });
3092
+ return snapshot;
3093
+ };
3094
+ /** 初始化数组数据,添加 uid 和 isEdit 字段 */
2766
3095
  ArrayFormService.prototype.initializeData = function (data) {
2767
3096
  var _this = this;
2768
3097
  return data.map(function (item) { return _this.enrichRow(item); });
2769
3098
  };
2770
- /**
2771
- * 为单行数据添加 uid 和 isEdit 字段
2772
- *
2773
- * @param row 原始行数据
2774
- * @returns 增强后的行数据
2775
- */
3099
+ /** 为单行数据添加 uid 和 isEdit 字段 */
2776
3100
  ArrayFormService.prototype.enrichRow = function (row) {
2777
- return Object.assign(Object.assign({}, row), { uid: row.uid || uuid.v4(), isEdit: row.isEdit !== undefined ? row.isEdit : false });
3101
+ return Object.assign(Object.assign({}, row), { uid: row.uid || uuid.v4(), isEdit: row.isEdit !== undefined ? row.isEdit : false, disabled: row.disabled !== undefined ? row.disabled : false });
2778
3102
  };
2779
- /**
2780
- * 新增一行数据
2781
- *
2782
- * @param data 数据数组引用
2783
- * @param defaultValues 默认值
2784
- * @returns 新增的行数据
2785
- */
3103
+ /** 新增一行数据 */
2786
3104
  ArrayFormService.prototype.addRow = function (data, defaultValues) {
2787
- var newRow = Object.assign(Object.assign({}, defaultValues), { uid: uuid.v4(), isEdit: true, isAdd: true });
3105
+ var newRow = Object.assign(Object.assign({}, defaultValues), { uid: uuid.v4(), isEdit: true, isAdd: true, disabled: false });
2788
3106
  data.push(newRow);
2789
3107
  return newRow;
2790
3108
  };
2791
- /**
2792
- * 校验单个字段
2793
- *
2794
- * @param row 行数据
2795
- * @param fieldName 字段名
2796
- * @param config 表单配置
2797
- * @returns 校验结果
2798
- */
3109
+ /** 校验单个字段 */
2799
3110
  ArrayFormService.prototype.validateField = function (row, fieldName, config) {
2800
3111
  var fieldConfig = config.fields.find(function (f) { return f.name === fieldName; });
2801
3112
  if (!fieldConfig) {
@@ -2806,13 +3117,7 @@
2806
3117
  }
2807
3118
  return "";
2808
3119
  };
2809
- /**
2810
- * 校验整行数据
2811
- *
2812
- * @param row 行数据
2813
- * @param config 表单配置
2814
- * @returns 校验结果对象,key为字段名,value为校验结果
2815
- */
3120
+ /** 校验整行数据 */
2816
3121
  ArrayFormService.prototype.validateRow = function (row, config) {
2817
3122
  var _this = this;
2818
3123
  var results = {};
@@ -2821,13 +3126,7 @@
2821
3126
  });
2822
3127
  return results;
2823
3128
  };
2824
- /**
2825
- * 校验整个数组
2826
- *
2827
- * @param data 数据数组
2828
- * @param config 表单配置
2829
- * @returns 校验结果对象,key为行的uid,value为该行的校验结果
2830
- */
3129
+ /** 校验整个数组 */
2831
3130
  ArrayFormService.prototype.validateData = function (data, config) {
2832
3131
  var _this = this;
2833
3132
  var results = {};
@@ -2836,90 +3135,149 @@
2836
3135
  });
2837
3136
  return results;
2838
3137
  };
2839
- /**
2840
- * 注册表单到存储
2841
- * 如果表单已存在,则更新其配置
2842
- *
2843
- * @param formName 表单名称
2844
- * @param data 数据数组
2845
- * @param config 表单配置
2846
- */
3138
+ /** 注册表单到存储 */
2847
3139
  ArrayFormService.prototype.registerForm = function (formName, data, config) {
3140
+ var _this = this;
3141
+ var initializedData = this.initializeData(data);
3142
+ // 记录初始值快照
3143
+ var initialSnapshot = {};
3144
+ initializedData.forEach(function (row) {
3145
+ initialSnapshot[row.uid] = _this.createRowSnapshot(row, config.fields);
3146
+ });
2848
3147
  this.formStore[formName] = {
2849
- data: this.initializeData(data),
3148
+ data: initializedData,
2850
3149
  config: config,
2851
3150
  validationResults: {},
3151
+ initialSnapshot: initialSnapshot,
3152
+ editingSnapshot: {},
3153
+ allTouched: false,
3154
+ rowTouched: {},
2852
3155
  };
2853
3156
  // 如果配置了自动更新,立即更新一次
2854
3157
  this.autoUpdateArrayReference(formName);
2855
3158
  };
2856
- /**
2857
- * 从存储中获取表单
2858
- *
2859
- * @param formName 表单名称
2860
- * @returns 表单存储项或undefined
2861
- */
3159
+ /** 从存储中获取表单 */
2862
3160
  ArrayFormService.prototype.getForm = function (formName) {
2863
3161
  return this.formStore[formName];
2864
3162
  };
2865
- /**
2866
- * 向表单添加行
2867
- *
2868
- * @param formName 表单名称
2869
- * @param defaultValues 默认值
2870
- * @returns 新增的行数据或undefined
2871
- */
3163
+ /** 从存储中获取表单数据 */
3164
+ ArrayFormService.prototype.getFormData = function (formName) {
3165
+ var form = this.formStore[formName];
3166
+ if (!form) {
3167
+ return undefined;
3168
+ }
3169
+ return form.data.map(function (item) {
3170
+ delete item.isEdit;
3171
+ delete item.isAdd;
3172
+ delete item.uid;
3173
+ return item;
3174
+ });
3175
+ };
3176
+ /** 向表单添加行 */
2872
3177
  ArrayFormService.prototype.addRowToForm = function (formName, defaultValues) {
2873
3178
  var form = this.formStore[formName];
2874
3179
  if (!form) {
2875
3180
  return undefined;
2876
3181
  }
2877
3182
  var newRow = this.addRow(form.data, defaultValues);
3183
+ // 为新行记录初始值快照
3184
+ form.initialSnapshot[newRow.uid] = this.createRowSnapshot(newRow, form.config.fields);
2878
3185
  // 自动更新外部数组引用
2879
3186
  this.autoUpdateArrayReference(formName);
2880
3187
  return newRow;
2881
3188
  };
2882
- /**
2883
- * 校验表单
2884
- *
2885
- * @param formName 表单名称
2886
- * @returns 校验结果或undefined
2887
- */
3189
+ /** 校验表单,自动标记所有字段为已触碰 */
2888
3190
  ArrayFormService.prototype.validateForm = function (formName) {
3191
+ var e_2, _c, e_3, _d;
2889
3192
  var form = this.formStore[formName];
2890
3193
  if (!form) {
2891
- return undefined;
3194
+ return true;
2892
3195
  }
3196
+ // 标记所有字段为已触碰
3197
+ form.allTouched = true;
2893
3198
  var results = this.validateData(form.data, form.config);
2894
3199
  form.validationResults = results;
2895
- return results;
3200
+ try {
3201
+ // 检查是否有任何错误
3202
+ for (var _e = __values(Object.keys(results)), _f = _e.next(); !_f.done; _f = _e.next()) {
3203
+ var uid = _f.value;
3204
+ try {
3205
+ for (var _g = (e_3 = void 0, __values(Object.keys(results[uid]))), _h = _g.next(); !_h.done; _h = _g.next()) {
3206
+ var fieldName = _h.value;
3207
+ if (results[uid][fieldName]) {
3208
+ return false;
3209
+ }
3210
+ }
3211
+ }
3212
+ catch (e_3_1) { e_3 = { error: e_3_1 }; }
3213
+ finally {
3214
+ try {
3215
+ if (_h && !_h.done && (_d = _g.return)) _d.call(_g);
3216
+ }
3217
+ finally { if (e_3) throw e_3.error; }
3218
+ }
3219
+ }
3220
+ }
3221
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
3222
+ finally {
3223
+ try {
3224
+ if (_f && !_f.done && (_c = _e.return)) _c.call(_e);
3225
+ }
3226
+ finally { if (e_2) throw e_2.error; }
3227
+ }
3228
+ return true;
2896
3229
  };
2897
- /**
2898
- * 开启指定行的编辑模式
2899
- *
2900
- * @param row 行数据
2901
- */
2902
- ArrayFormService.prototype.enableEdit = function (row) {
3230
+ /** 开启编辑模式,保存快照用于取消恢复 */
3231
+ ArrayFormService.prototype.enableEdit = function (formName, row) {
3232
+ var form = this.formStore[formName];
3233
+ if (form && row.uid) {
3234
+ // 保存编辑前的快照
3235
+ form.editingSnapshot[row.uid] = this.createRowSnapshot(row, form.config.fields);
3236
+ }
2903
3237
  row.isEdit = true;
2904
3238
  };
2905
- /**
2906
- * 关闭指定行的编辑模式
2907
- *
2908
- * @param row 行数据
2909
- */
2910
- ArrayFormService.prototype.disableEdit = function (row) {
3239
+ /** 取消编辑,恢复到编辑前的数据 */
3240
+ ArrayFormService.prototype.disableEdit = function (formName, row) {
3241
+ var _this = this;
3242
+ var form = this.formStore[formName];
3243
+ if (form && row.uid && form.editingSnapshot[row.uid]) {
3244
+ // 恢复编辑前的数据
3245
+ var snapshot_1 = form.editingSnapshot[row.uid];
3246
+ form.config.fields.forEach(function (field) {
3247
+ row[field.name] = _this.cloneValue(snapshot_1[field.name]);
3248
+ });
3249
+ // 更新初始快照为恢复后的值,消除 touched 状态
3250
+ form.initialSnapshot[row.uid] = this.cloneValue(snapshot_1);
3251
+ // 清理编辑快照和 touched 状态
3252
+ delete form.editingSnapshot[row.uid];
3253
+ delete form.rowTouched[row.uid];
3254
+ // 清理该行的校验结果
3255
+ if (form.validationResults) {
3256
+ delete form.validationResults[row.uid];
3257
+ }
3258
+ }
2911
3259
  row.isEdit = false;
2912
3260
  };
2913
- /**
2914
- * 从表单中删除指定行
2915
- *
2916
- * @param formName 表单名称
2917
- * @param row 行的uid
2918
- * @returns 是否删除成功
2919
- */
3261
+ /** 确认编辑,保留修改后的数据 */
3262
+ ArrayFormService.prototype.confirmEdit = function (formName, row) {
3263
+ var form = this.formStore[formName];
3264
+ if (form && row.uid) {
3265
+ // 清理编辑快照(保留当前数据)
3266
+ if (form.editingSnapshot[row.uid]) {
3267
+ delete form.editingSnapshot[row.uid];
3268
+ }
3269
+ // 更新初始快照为当前值(用于后续 touched 检测)
3270
+ form.initialSnapshot[row.uid] = this.createRowSnapshot(row, form.config.fields);
3271
+ // 清除 touched 状态,基于新的 initialSnapshot 重新判断
3272
+ delete form.rowTouched[row.uid];
3273
+ }
3274
+ row.isEdit = false;
3275
+ row.isAdd = false;
3276
+ };
3277
+ /** 从表单中删除指定行 */
2920
3278
  ArrayFormService.prototype.deleteRowFromForm = function (formName, row) {
2921
3279
  var form = this.formStore[formName];
2922
- if (!form) {
3280
+ if (!form || !row.uid) {
2923
3281
  return false;
2924
3282
  }
2925
3283
  var index = form.data.findIndex(function (item) { return item.uid === row.uid; });
@@ -2927,31 +3285,44 @@
2927
3285
  return false;
2928
3286
  }
2929
3287
  form.data.splice(index, 1);
2930
- if (form.validationResults && form.validationResults[row.uid]) {
3288
+ // 清理该行的所有快照、touched 状态和校验结果
3289
+ delete form.initialSnapshot[row.uid];
3290
+ delete form.editingSnapshot[row.uid];
3291
+ delete form.rowTouched[row.uid];
3292
+ if (form.validationResults) {
2931
3293
  delete form.validationResults[row.uid];
2932
3294
  }
2933
3295
  // 自动更新外部数组引用
2934
3296
  this.autoUpdateArrayReference(formName);
2935
3297
  return true;
2936
3298
  };
2937
- /**
2938
- * 校验指定行的指定字段并返回校验结果
2939
- * 实时执行校验,用于模板中的实时校验显示
2940
- *
2941
- * @param formName 表单名称
2942
- * @param row 行数据
2943
- * @param fieldName 字段名
2944
- * @returns 校验结果
2945
- */
3299
+ /** 检测字段是否已被触碰 */
3300
+ ArrayFormService.prototype.isFieldTouched = function (form, row, fieldName) {
3301
+ var _a;
3302
+ // 整个表单已 touched(整个表单提交时)
3303
+ if (form.allTouched) {
3304
+ return true;
3305
+ }
3306
+ // 当前行已 touched(单行保存时)
3307
+ if (form.rowTouched[row.uid]) {
3308
+ return true;
3309
+ }
3310
+ // 检测当前值与初始值是否不同
3311
+ var initialValue = (_a = form.initialSnapshot[row.uid]) === null || _a === void 0 ? void 0 : _a[fieldName];
3312
+ var currentValue = row[fieldName];
3313
+ return !this.isEqual(initialValue, currentValue);
3314
+ };
3315
+ /** 校验指定行的指定字段,未修改时不显示校验状态 */
2946
3316
  ArrayFormService.prototype.validateFieldInRow = function (formName, row, fieldName) {
2947
3317
  var form = this.formStore[formName];
2948
3318
  if (!form) {
2949
- return "success";
3319
+ return "";
2950
3320
  }
2951
3321
  var fieldConfig = form.config.fields.find(function (f) { return f.name === fieldName; });
2952
3322
  if (!fieldConfig) {
2953
- return "success";
3323
+ return "";
2954
3324
  }
3325
+ // 执行校验
2955
3326
  var result = "";
2956
3327
  if (fieldConfig.validator) {
2957
3328
  result = fieldConfig.validator(row[fieldName], row, fieldName);
@@ -2964,21 +3335,36 @@
2964
3335
  form.validationResults[row.uid] = {};
2965
3336
  }
2966
3337
  form.validationResults[row.uid][fieldName] = result;
3338
+ // 如果字段未被触碰,不显示校验状态
3339
+ if (!this.isFieldTouched(form, row, fieldName)) {
3340
+ return "";
3341
+ }
2967
3342
  return result ? "error" : "success";
2968
3343
  };
2969
- /**
2970
- * 校验指定行的所有字段
2971
- *
2972
- * @param formName 表单名称
2973
- * @param row 行数据
2974
- * @returns 是否所有字段都通过校验
2975
- */
3344
+ /** 获取指定行指定字段的校验错误信息 */
3345
+ ArrayFormService.prototype.getFieldErrorMessage = function (formName, row, fieldName) {
3346
+ var _a, _b;
3347
+ var form = this.formStore[formName];
3348
+ if (!form || !row.uid) {
3349
+ return "";
3350
+ }
3351
+ // 如果字段未被触碰,不显示错误信息
3352
+ if (!this.isFieldTouched(form, row, fieldName)) {
3353
+ return "";
3354
+ }
3355
+ return ((_b = (_a = form.validationResults) === null || _a === void 0 ? void 0 : _a[row.uid]) === null || _b === void 0 ? void 0 : _b[fieldName]) || "";
3356
+ };
3357
+ /** 校验指定行的所有字段 */
2976
3358
  ArrayFormService.prototype.validateRowAllFields = function (formName, row) {
2977
3359
  var _this = this;
2978
3360
  var form = this.formStore[formName];
2979
- if (!form) {
3361
+ if (!form || !row.uid) {
2980
3362
  return true;
2981
3363
  }
3364
+ // 更新初始快照为当前值
3365
+ form.initialSnapshot[row.uid] = this.createRowSnapshot(row, form.config.fields);
3366
+ // 标记当前行为 touched(只影响当前行,不影响其他行)
3367
+ form.rowTouched[row.uid] = true;
2982
3368
  var hasError = false;
2983
3369
  form.config.fields.forEach(function (fieldConfig) {
2984
3370
  var result = _this.validateFieldInRow(formName, row, fieldConfig.name);
@@ -2988,12 +3374,7 @@
2988
3374
  });
2989
3375
  return !hasError;
2990
3376
  };
2991
- /**
2992
- * 自动更新外部数组引用(如果配置了)
2993
- * 私有方法,在数据变化时自动调用
2994
- *
2995
- * @param formName 表单名称
2996
- */
3377
+ /** 自动更新外部数组引用 */
2997
3378
  ArrayFormService.prototype.autoUpdateArrayReference = function (formName) {
2998
3379
  var form = this.formStore[formName];
2999
3380
  if (!form || !form.config.targetObject || !form.config.arrayPropertyName) {
@@ -3003,6 +3384,43 @@
3003
3384
  // 更新目标对象的数组属性为新数组引用
3004
3385
  form.config.targetObject[form.config.arrayPropertyName] = newArray;
3005
3386
  };
3387
+ /** 是否有正在编辑的行 */
3388
+ ArrayFormService.prototype.hasEditingRow = function (formName) {
3389
+ var form = this.formStore[formName];
3390
+ if (!form) {
3391
+ return false;
3392
+ }
3393
+ return form.data.some(function (item) { return item.isEdit; });
3394
+ };
3395
+ // 销毁对应的表单
3396
+ ArrayFormService.prototype.destory = function (names) {
3397
+ var _this = this;
3398
+ names.forEach(function (name) {
3399
+ if (_this.formStore[name]) {
3400
+ // 清理表单数据
3401
+ delete _this.formStore[name];
3402
+ }
3403
+ });
3404
+ };
3405
+ // 重置表单数组
3406
+ ArrayFormService.prototype.resetFormArray = function (name) {
3407
+ var form = this.formStore[name];
3408
+ if (!form) {
3409
+ return;
3410
+ }
3411
+ // 1. 清空数据数组
3412
+ form.data = [];
3413
+ // 2. 清理所有快照
3414
+ form.initialSnapshot = {};
3415
+ form.editingSnapshot = {};
3416
+ // 3. 清理校验结果
3417
+ form.validationResults = {};
3418
+ // 4. 重置 touched 状态
3419
+ form.allTouched = false;
3420
+ form.rowTouched = {};
3421
+ // 5. 如果配置了自动更新,更新外部数组引用
3422
+ this.autoUpdateArrayReference(name);
3423
+ };
3006
3424
  return ArrayFormService;
3007
3425
  }());
3008
3426
  ArrayFormService.ɵprov = i0.ɵɵdefineInjectable({ factory: function ArrayFormService_Factory() { return new ArrayFormService(); }, token: ArrayFormService, providedIn: "root" });