@yibozhang/pro-table 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -0
- package/bundles/yibozhang-pro-table.umd.js +3110 -0
- package/bundles/yibozhang-pro-table.umd.js.map +1 -0
- package/bundles/yibozhang-pro-table.umd.min.js +2 -0
- package/bundles/yibozhang-pro-table.umd.min.js.map +1 -0
- package/esm2015/lib/components/colmuns-setting/colmuns-setting.component.js +158 -0
- package/esm2015/lib/components/dynamic-search-field/dynamic-search-field.component.js +101 -0
- package/esm2015/lib/constants.js +89 -0
- package/esm2015/lib/page-container/page-container.component.js +21 -0
- package/esm2015/lib/page-container/page-container.module.js +25 -0
- package/esm2015/lib/page-public/antd-form.js +734 -0
- package/esm2015/lib/plate-input/plate-input.component.js +155 -0
- package/esm2015/lib/plate-input/plate-input.module.js +26 -0
- package/esm2015/lib/plate-input/plate-prefix-load.service.js +41 -0
- package/esm2015/lib/pro-table.component.js +983 -0
- package/esm2015/lib/pro-table.module.js +73 -0
- package/esm2015/lib/table-search-bar/table-search-bar-module.js +27 -0
- package/esm2015/lib/table-search-bar/table-search-bar.component.js +51 -0
- package/esm2015/lib/tokens.js +4 -0
- package/esm2015/lib/type.js +2 -0
- package/esm2015/public-api.js +12 -0
- package/esm2015/yibozhang-pro-table.js +13 -0
- package/fesm2015/yibozhang-pro-table.js +2448 -0
- package/fesm2015/yibozhang-pro-table.js.map +1 -0
- package/lib/components/colmuns-setting/colmuns-setting.component.d.ts +35 -0
- package/lib/components/colmuns-setting/colmuns-setting.component.d.ts.map +1 -0
- package/lib/components/dynamic-search-field/dynamic-search-field.component.d.ts +22 -0
- package/lib/components/dynamic-search-field/dynamic-search-field.component.d.ts.map +1 -0
- package/lib/constants.d.ts +20 -0
- package/lib/constants.d.ts.map +1 -0
- package/lib/page-container/page-container.component.d.ts +9 -0
- package/lib/page-container/page-container.component.d.ts.map +1 -0
- package/lib/page-container/page-container.module.d.ts +3 -0
- package/lib/page-container/page-container.module.d.ts.map +1 -0
- package/lib/page-public/antd-form.d.ts +99 -0
- package/lib/page-public/antd-form.d.ts.map +1 -0
- package/lib/plate-input/plate-input.component.d.ts +31 -0
- package/lib/plate-input/plate-input.component.d.ts.map +1 -0
- package/lib/plate-input/plate-input.module.d.ts +3 -0
- package/lib/plate-input/plate-input.module.d.ts.map +1 -0
- package/lib/plate-input/plate-prefix-load.service.d.ts +13 -0
- package/lib/plate-input/plate-prefix-load.service.d.ts.map +1 -0
- package/lib/pro-table.component.d.ts +122 -0
- package/lib/pro-table.component.d.ts.map +1 -0
- package/lib/pro-table.module.d.ts +3 -0
- package/lib/pro-table.module.d.ts.map +1 -0
- package/lib/table-search-bar/table-search-bar-module.d.ts +3 -0
- package/lib/table-search-bar/table-search-bar-module.d.ts.map +1 -0
- package/lib/table-search-bar/table-search-bar.component.d.ts +15 -0
- package/lib/table-search-bar/table-search-bar.component.d.ts.map +1 -0
- package/lib/tokens.d.ts +36 -0
- package/lib/tokens.d.ts.map +1 -0
- package/lib/type.d.ts +226 -0
- package/lib/type.d.ts.map +1 -0
- package/package.json +40 -0
- package/public-api.d.ts +9 -0
- package/public-api.d.ts.map +1 -0
- package/src/lib/styles/custom-antd.less +114 -0
- package/src/lib/styles/margin.css +90 -0
- package/src/lib/styles/theme.less +42 -0
- package/yibozhang-pro-table.d.ts +13 -0
- package/yibozhang-pro-table.d.ts.map +1 -0
- package/yibozhang-pro-table.metadata.json +1 -0
|
@@ -0,0 +1,2448 @@
|
|
|
1
|
+
import { __awaiter, __rest } from 'tslib';
|
|
2
|
+
import { InjectionToken, EventEmitter, Component, Optional, Inject, Input, Output, ContentChild, ContentChildren, TemplateRef, NgModule, forwardRef, ChangeDetectorRef, ElementRef, ViewChild, ComponentFactoryResolver, ViewContainerRef, Injectable, ɵɵdefineInjectable, ɵɵinject } from '@angular/core';
|
|
3
|
+
import { isEqual, hasIn, cloneDeep, isNil, debounce } from 'lodash-es';
|
|
4
|
+
import { isObservable } from 'rxjs';
|
|
5
|
+
import { DragDropModule } from '@angular/cdk/drag-drop';
|
|
6
|
+
import { CommonModule } from '@angular/common';
|
|
7
|
+
import { HttpClientModule, HttpClient } from '@angular/common/http';
|
|
8
|
+
import { FormsModule, ReactiveFormsModule, NG_VALUE_ACCESSOR, FormArray, FormGroup, FormBuilder } from '@angular/forms';
|
|
9
|
+
import { RouterModule } from '@angular/router';
|
|
10
|
+
import { NzButtonModule } from 'ng-zorro-antd/button';
|
|
11
|
+
import { NzCheckboxModule } from 'ng-zorro-antd/checkbox';
|
|
12
|
+
import { NzDatePickerModule } from 'ng-zorro-antd/date-picker';
|
|
13
|
+
import { NzFormModule } from 'ng-zorro-antd/form';
|
|
14
|
+
import { NzGridModule } from 'ng-zorro-antd/grid';
|
|
15
|
+
import { NzIconModule } from 'ng-zorro-antd/icon';
|
|
16
|
+
import { NzInputModule } from 'ng-zorro-antd/input';
|
|
17
|
+
import { NzModalModule } from 'ng-zorro-antd/modal';
|
|
18
|
+
import { NzPopoverModule } from 'ng-zorro-antd/popover';
|
|
19
|
+
import { NzSelectModule } from 'ng-zorro-antd/select';
|
|
20
|
+
import { NzSpaceModule } from 'ng-zorro-antd/space';
|
|
21
|
+
import { NzTableModule } from 'ng-zorro-antd/table';
|
|
22
|
+
import { NzTypographyModule } from 'ng-zorro-antd/typography';
|
|
23
|
+
import { NzCardModule } from 'ng-zorro-antd/card';
|
|
24
|
+
import Sortable from 'sortablejs';
|
|
25
|
+
import { NzAutocompleteModule } from 'ng-zorro-antd/auto-complete';
|
|
26
|
+
import { NzInputNumberModule } from 'ng-zorro-antd/input-number';
|
|
27
|
+
import { NzToolTipModule } from 'ng-zorro-antd/tooltip';
|
|
28
|
+
import { debounceTime, distinctUntilChanged } from 'rxjs/operators';
|
|
29
|
+
|
|
30
|
+
const ɵ0 = () => [], ɵ1 = (value) => `${value}`, ɵ2 = (value) => value;
|
|
31
|
+
const PRO_TABLE_DEFAULT_PROPS = {
|
|
32
|
+
input: {
|
|
33
|
+
name: "",
|
|
34
|
+
placeHolder: "",
|
|
35
|
+
disabled: false,
|
|
36
|
+
label: "",
|
|
37
|
+
value: "",
|
|
38
|
+
},
|
|
39
|
+
select: {
|
|
40
|
+
name: "",
|
|
41
|
+
options: [],
|
|
42
|
+
disabled: false,
|
|
43
|
+
label: "",
|
|
44
|
+
value: "",
|
|
45
|
+
allowClear: true,
|
|
46
|
+
placeHolder: "",
|
|
47
|
+
},
|
|
48
|
+
selectMultiple: {
|
|
49
|
+
name: "",
|
|
50
|
+
options: [],
|
|
51
|
+
disabled: false,
|
|
52
|
+
label: "",
|
|
53
|
+
value: [],
|
|
54
|
+
allowClear: true,
|
|
55
|
+
placeHolder: "请选择",
|
|
56
|
+
},
|
|
57
|
+
inputPlate: {
|
|
58
|
+
name: "",
|
|
59
|
+
label: "",
|
|
60
|
+
value: "",
|
|
61
|
+
},
|
|
62
|
+
checkbox: {
|
|
63
|
+
name: "",
|
|
64
|
+
options: [],
|
|
65
|
+
disabled: false,
|
|
66
|
+
label: "",
|
|
67
|
+
value: [],
|
|
68
|
+
noStyle: false,
|
|
69
|
+
},
|
|
70
|
+
date: {
|
|
71
|
+
name: "",
|
|
72
|
+
disabled: false,
|
|
73
|
+
label: "",
|
|
74
|
+
value: "",
|
|
75
|
+
allowClear: true,
|
|
76
|
+
placeHolder: "请选择",
|
|
77
|
+
showTime: false,
|
|
78
|
+
format: "yyyy-MM-dd",
|
|
79
|
+
mode: "date",
|
|
80
|
+
},
|
|
81
|
+
autoComplete: {
|
|
82
|
+
name: "",
|
|
83
|
+
disabled: false,
|
|
84
|
+
placeHolder: "请输入",
|
|
85
|
+
label: "",
|
|
86
|
+
value: "",
|
|
87
|
+
dataSource: ɵ0,
|
|
88
|
+
backFill: false,
|
|
89
|
+
defaultActiveFirstOption: false,
|
|
90
|
+
returnFullData: false,
|
|
91
|
+
},
|
|
92
|
+
inputNumber: {
|
|
93
|
+
name: "",
|
|
94
|
+
disabled: false,
|
|
95
|
+
label: "",
|
|
96
|
+
value: "",
|
|
97
|
+
placeHolder: "请输入",
|
|
98
|
+
min: 0,
|
|
99
|
+
max: 100,
|
|
100
|
+
precision: 0,
|
|
101
|
+
formatterPercent: ɵ1,
|
|
102
|
+
parserPercent: ɵ2,
|
|
103
|
+
},
|
|
104
|
+
custom: {
|
|
105
|
+
name: "",
|
|
106
|
+
value: null,
|
|
107
|
+
label: "",
|
|
108
|
+
},
|
|
109
|
+
};
|
|
110
|
+
const PRO_TABLE_DEFAULT_COLUMN = {
|
|
111
|
+
width: "",
|
|
112
|
+
align: "left",
|
|
113
|
+
fixedLeft: false,
|
|
114
|
+
fixedRight: false,
|
|
115
|
+
auxiliaryColumn: false,
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
const PRO_TABLE_COLUMN_REMOTE = new InjectionToken("PRO_TABLE_COLUMN_REMOTE");
|
|
119
|
+
const PLATE_PREFIX_LOAD_SERVICE = new InjectionToken("PLATE_PREFIX_LOAD_SERVICE");
|
|
120
|
+
|
|
121
|
+
class ProTableComponent {
|
|
122
|
+
constructor(columnRemote) {
|
|
123
|
+
this.columnRemote = columnRemote;
|
|
124
|
+
this.showSearchBtn = true;
|
|
125
|
+
this.showClearBtn = true;
|
|
126
|
+
this.title = null;
|
|
127
|
+
this.tableName = "";
|
|
128
|
+
this.multiRow = false;
|
|
129
|
+
this.columns = [];
|
|
130
|
+
this.showSearchBar = true;
|
|
131
|
+
this.showActionBar = true;
|
|
132
|
+
this.confirmBtnText = "查询";
|
|
133
|
+
this.clearBtnText = "清空";
|
|
134
|
+
this.labelWidth = "90px";
|
|
135
|
+
this.labelAlign = "right";
|
|
136
|
+
this.dataSource = [];
|
|
137
|
+
this.bordered = true;
|
|
138
|
+
this.outerBordered = true;
|
|
139
|
+
this.showPagination = true;
|
|
140
|
+
this.frontPagination = false;
|
|
141
|
+
this.scroll = null;
|
|
142
|
+
this.summaryData = null;
|
|
143
|
+
// 排序模式:local 本地排序;server 在线排序(提交给接口)
|
|
144
|
+
this.sortMode = "local";
|
|
145
|
+
this.showColumnSetting = false;
|
|
146
|
+
// 是否开启多列排序(默认单列)
|
|
147
|
+
this.multipleSort = false;
|
|
148
|
+
this.showCheckbox = false;
|
|
149
|
+
// 判断行是否禁用的函数
|
|
150
|
+
this.rowDisabled = () => false;
|
|
151
|
+
// 是否自动触发请求
|
|
152
|
+
this.autoTriggerRequest = true;
|
|
153
|
+
this.onRowClick = new EventEmitter();
|
|
154
|
+
this.onRowDbClick = new EventEmitter();
|
|
155
|
+
this.onValuesChange = new EventEmitter();
|
|
156
|
+
this.onResetFormBeforeReload = new EventEmitter();
|
|
157
|
+
this._savedSearchParams = {};
|
|
158
|
+
// 存储模板映射关系 - 通过字符串名称映射到模板引用
|
|
159
|
+
this.templateMap = new Map();
|
|
160
|
+
// 存储所有自定义模板的引用
|
|
161
|
+
this.customTemplates = new Map();
|
|
162
|
+
// 记录各列排序状态:'ascend' | 'descend' | null
|
|
163
|
+
this._sortMap = {};
|
|
164
|
+
// 记录多列排序的优先级(后设置的优先)
|
|
165
|
+
this._sortPriority = [];
|
|
166
|
+
// 存储每个 autoComplete 字段的防抖函数
|
|
167
|
+
this._autoCompleteDebounceMap = new Map();
|
|
168
|
+
// 仅在初始化时运行列配置预检查,避免后续调用重复触发
|
|
169
|
+
this._preCheckDone = false;
|
|
170
|
+
this._columns = [];
|
|
171
|
+
// 筛选表单数据存储
|
|
172
|
+
this._searchParams = {};
|
|
173
|
+
// 筛选表单list渲染数据
|
|
174
|
+
this._searchFiledColumns = [];
|
|
175
|
+
this._pageInfo = {
|
|
176
|
+
pageIndex: 1,
|
|
177
|
+
pageSize: 15,
|
|
178
|
+
total: 100,
|
|
179
|
+
pageSizeOptions: [10, 15, 20, 50, 100, 500, 1000],
|
|
180
|
+
};
|
|
181
|
+
this._loading = false;
|
|
182
|
+
this._selectedTableRow = null;
|
|
183
|
+
// 选中的行数据(用于复选框选择)
|
|
184
|
+
this._selectedRows = [];
|
|
185
|
+
// 全选状态
|
|
186
|
+
this._checkedAll = false;
|
|
187
|
+
// 半选状态(部分选中)
|
|
188
|
+
this._indeterminate = false;
|
|
189
|
+
// 远程columns
|
|
190
|
+
this._serverColumns = [];
|
|
191
|
+
// 存储 autoComplete 字段的数据源
|
|
192
|
+
this._autoCompleteDataSources = {};
|
|
193
|
+
}
|
|
194
|
+
fetchRemoteColumns() {
|
|
195
|
+
var _a;
|
|
196
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
197
|
+
if (!((_a = this.columnRemote) === null || _a === void 0 ? void 0 : _a.getCol) || !this.tableName) {
|
|
198
|
+
return null;
|
|
199
|
+
}
|
|
200
|
+
try {
|
|
201
|
+
const res = yield this.columnRemote.getCol(this.tableName, this.multiRow);
|
|
202
|
+
return res;
|
|
203
|
+
}
|
|
204
|
+
catch (error) {
|
|
205
|
+
return null;
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
persistRemoteColumns(columns) {
|
|
210
|
+
var _a;
|
|
211
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
212
|
+
if (!((_a = this.columnRemote) === null || _a === void 0 ? void 0 : _a.setCol) || !this.tableName) {
|
|
213
|
+
return null;
|
|
214
|
+
}
|
|
215
|
+
try {
|
|
216
|
+
const result = this.columnRemote.setCol(this.tableName, columns, this.multiRow);
|
|
217
|
+
if (result && isObservable(result)) {
|
|
218
|
+
return yield result.toPromise();
|
|
219
|
+
}
|
|
220
|
+
return result;
|
|
221
|
+
}
|
|
222
|
+
catch (error) {
|
|
223
|
+
return null;
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
ngOnInit() {
|
|
228
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
229
|
+
this._searchParams = {};
|
|
230
|
+
this.formateInnerColumns(this.columns);
|
|
231
|
+
yield this.setSearchParams(this.columns);
|
|
232
|
+
// 使用 Proxy 包装 _searchParams,拦截表单项值变化并向外发出事件
|
|
233
|
+
this._searchParams = this.createSearchParamsProxy(this._searchParams);
|
|
234
|
+
if (this.autoTriggerRequest) {
|
|
235
|
+
this.handleQuery();
|
|
236
|
+
}
|
|
237
|
+
this.queryDynamicColumns();
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
ngAfterContentInit() {
|
|
241
|
+
// 自动注册所有自定义模板
|
|
242
|
+
this.autoRegisterTemplates();
|
|
243
|
+
}
|
|
244
|
+
preCheckServerColumns() {
|
|
245
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
246
|
+
const res = yield this.fetchRemoteColumns();
|
|
247
|
+
if (!res)
|
|
248
|
+
return false;
|
|
249
|
+
const initColumns = this.columns
|
|
250
|
+
.filter((col) => !col.auxiliaryColumn)
|
|
251
|
+
.map((column) => {
|
|
252
|
+
return {
|
|
253
|
+
field: column.prop,
|
|
254
|
+
isShow: !column.hideInTable,
|
|
255
|
+
header: column.title,
|
|
256
|
+
sortName: column.sortName || null,
|
|
257
|
+
};
|
|
258
|
+
});
|
|
259
|
+
if (res.code === 0) {
|
|
260
|
+
if (!isEqual(res.data.tabColumn, initColumns)) {
|
|
261
|
+
const initRes = yield this.persistRemoteColumns(initColumns);
|
|
262
|
+
if (initRes) {
|
|
263
|
+
this.queryDynamicColumns();
|
|
264
|
+
}
|
|
265
|
+
return false;
|
|
266
|
+
}
|
|
267
|
+
else {
|
|
268
|
+
console.log("一致");
|
|
269
|
+
return true;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
else {
|
|
273
|
+
return false;
|
|
274
|
+
}
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
queryDynamicColumns() {
|
|
278
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
279
|
+
if (!this.tableName || !this.columnRemote)
|
|
280
|
+
return;
|
|
281
|
+
if (!this._preCheckDone) {
|
|
282
|
+
const checkResult = yield this.preCheckServerColumns();
|
|
283
|
+
this._preCheckDone = true;
|
|
284
|
+
if (!checkResult)
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
const res = yield this.fetchRemoteColumns();
|
|
288
|
+
if (!res)
|
|
289
|
+
return;
|
|
290
|
+
if (res.code === 0) {
|
|
291
|
+
const _tabColumn = res.data.tabColumn.map((item) => {
|
|
292
|
+
return {
|
|
293
|
+
title: item.header,
|
|
294
|
+
prop: item.field,
|
|
295
|
+
sortName: item.sortName,
|
|
296
|
+
hideInTable: !item.isShow,
|
|
297
|
+
};
|
|
298
|
+
});
|
|
299
|
+
this._serverColumns = _tabColumn;
|
|
300
|
+
this.updateTableColumns(_tabColumn);
|
|
301
|
+
}
|
|
302
|
+
else if (res.code === 10) {
|
|
303
|
+
// 如果未设置接口返回,需要默认调用一次修改函数初始化数据
|
|
304
|
+
const initColumns = this.columns
|
|
305
|
+
.filter((col) => !col.auxiliaryColumn)
|
|
306
|
+
.map((column) => {
|
|
307
|
+
return {
|
|
308
|
+
field: column.prop,
|
|
309
|
+
isShow: true,
|
|
310
|
+
header: column.title,
|
|
311
|
+
sortName: column.sortName || null,
|
|
312
|
+
};
|
|
313
|
+
});
|
|
314
|
+
// 调用修改接口初始化数据
|
|
315
|
+
const initRes = yield this.persistRemoteColumns(initColumns);
|
|
316
|
+
if (initRes) {
|
|
317
|
+
this.queryDynamicColumns();
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
formateInnerColumns(columns) {
|
|
323
|
+
this._columns = columns
|
|
324
|
+
.filter((item) => !item.hideInTable)
|
|
325
|
+
.map((item) => {
|
|
326
|
+
return Object.assign(Object.assign({}, PRO_TABLE_DEFAULT_COLUMN), item);
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
// 自动注册模板的方法
|
|
330
|
+
autoRegisterTemplates() {
|
|
331
|
+
// 获取所有需要自定义模板的列
|
|
332
|
+
const columnsWithCustomRender = this._columns.filter((col) => col.customRender);
|
|
333
|
+
if (columnsWithCustomRender.length > 0) {
|
|
334
|
+
// 尝试从ContentChildren中查找对应的模板
|
|
335
|
+
columnsWithCustomRender.forEach((column) => {
|
|
336
|
+
const templateName = column.customRender;
|
|
337
|
+
const template = this.findTemplateByName(templateName);
|
|
338
|
+
if (template) {
|
|
339
|
+
this.customTemplates.set(templateName, template);
|
|
340
|
+
}
|
|
341
|
+
else {
|
|
342
|
+
}
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
// 获取所有需要自定义label模板的列(使用原始columns,确保顺序正确)
|
|
346
|
+
const columnsWithCustomLabel = this.columns.filter((col) => col.customLabelRender);
|
|
347
|
+
if (columnsWithCustomLabel.length > 0) {
|
|
348
|
+
// 尝试从ContentChildren中查找对应的label模板
|
|
349
|
+
columnsWithCustomLabel.forEach((column) => {
|
|
350
|
+
const templateName = column.customLabelRender;
|
|
351
|
+
const template = this.findLabelTemplateByName(templateName, columnsWithCustomLabel);
|
|
352
|
+
if (template) {
|
|
353
|
+
this.customTemplates.set(templateName, template);
|
|
354
|
+
}
|
|
355
|
+
else {
|
|
356
|
+
}
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
// 根据名称查找模板
|
|
361
|
+
findTemplateByName(templateName) {
|
|
362
|
+
return this.getTemplateFromContent(templateName);
|
|
363
|
+
}
|
|
364
|
+
// 从ContentChildren中查找指定名称的模板
|
|
365
|
+
getTemplateFromContent(templateName) {
|
|
366
|
+
const customRenderColumns = this._columns.filter((col) => col.customRender);
|
|
367
|
+
const templateIndex = customRenderColumns.findIndex((col) => col.customRender === templateName);
|
|
368
|
+
if (templateIndex >= 0) {
|
|
369
|
+
// 获取所有模板,并过滤掉特殊模板(actionBar和ImgActionBar)
|
|
370
|
+
// 这样可以避免因为特殊模板的位置导致索引计算错误
|
|
371
|
+
const templates = this.allTemplates.toArray();
|
|
372
|
+
const customTemplates = templates.filter((tpl) => tpl !== this.actionBarTpl && tpl !== this.imgActionBarTpl);
|
|
373
|
+
if (templateIndex < customTemplates.length) {
|
|
374
|
+
const template = customTemplates[templateIndex];
|
|
375
|
+
return template;
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
console.warn(`未找到模板 ${templateName}`);
|
|
379
|
+
return null;
|
|
380
|
+
}
|
|
381
|
+
// 根据名称查找label模板
|
|
382
|
+
findLabelTemplateByName(templateName, customLabelColumns) {
|
|
383
|
+
const templateIndex = customLabelColumns.findIndex((col) => col.customLabelRender === templateName);
|
|
384
|
+
if (templateIndex >= 0) {
|
|
385
|
+
// 获取所有模板,并过滤掉特殊模板(actionBar和ImgActionBar)
|
|
386
|
+
const templates = this.allTemplates.toArray();
|
|
387
|
+
const customTemplates = templates.filter((tpl) => tpl !== this.actionBarTpl && tpl !== this.imgActionBarTpl);
|
|
388
|
+
// 计算label模板的索引:需要跳过所有的customRender模板
|
|
389
|
+
const customRenderColumns = this._columns.filter((col) => col.customRender);
|
|
390
|
+
const labelTemplateIndex = customRenderColumns.length + templateIndex;
|
|
391
|
+
if (labelTemplateIndex < customTemplates.length) {
|
|
392
|
+
const template = customTemplates[labelTemplateIndex];
|
|
393
|
+
return template;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
console.warn(`未找到label模板 ${templateName}`);
|
|
397
|
+
return null;
|
|
398
|
+
}
|
|
399
|
+
// 设置筛选表单默认属性
|
|
400
|
+
setSearchFormDefaultProp(columns) {
|
|
401
|
+
columns.forEach((item) => {
|
|
402
|
+
if (item.valueType) {
|
|
403
|
+
if (item.fieldProps) {
|
|
404
|
+
item.fieldProps = Object.assign(Object.assign({}, PRO_TABLE_DEFAULT_PROPS[item.valueType]), item.fieldProps);
|
|
405
|
+
}
|
|
406
|
+
else {
|
|
407
|
+
item.fieldProps = Object.assign({}, PRO_TABLE_DEFAULT_PROPS[item.valueType]);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
});
|
|
411
|
+
}
|
|
412
|
+
// 动态设置Options
|
|
413
|
+
setSelectRequest(columns) {
|
|
414
|
+
columns.map((item) => __awaiter(this, void 0, void 0, function* () {
|
|
415
|
+
var _a, _b;
|
|
416
|
+
if (item.fieldProps && hasIn(item.fieldProps, "request")) {
|
|
417
|
+
try {
|
|
418
|
+
const options = yield ((_b = (_a = item.fieldProps).request) === null || _b === void 0 ? void 0 : _b.call(_a));
|
|
419
|
+
item.fieldProps.options = options;
|
|
420
|
+
}
|
|
421
|
+
catch (error) {
|
|
422
|
+
item.fieldProps.options = [];
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
}));
|
|
426
|
+
}
|
|
427
|
+
setSearchParams(columns) {
|
|
428
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
429
|
+
this._searchFiledColumns = [];
|
|
430
|
+
columns
|
|
431
|
+
.filter((item) => {
|
|
432
|
+
const flag = !item.hideInSearch && item.valueType;
|
|
433
|
+
if (flag) {
|
|
434
|
+
this._searchFiledColumns.push(cloneDeep(item));
|
|
435
|
+
}
|
|
436
|
+
return flag;
|
|
437
|
+
})
|
|
438
|
+
.forEach((column) => {
|
|
439
|
+
var _a, _b, _c;
|
|
440
|
+
const key = ((_a = column.fieldProps) === null || _a === void 0 ? void 0 : _a.name) || column.prop;
|
|
441
|
+
let defaultValue = PRO_TABLE_DEFAULT_PROPS[column.valueType].value;
|
|
442
|
+
// 对于checkbox类型,从options中找出checked为true的项作为默认值
|
|
443
|
+
if (column.valueType === "checkbox") {
|
|
444
|
+
const checkedValues = (((_b = column.fieldProps) === null || _b === void 0 ? void 0 : _b.options) || [])
|
|
445
|
+
.filter((opt) => opt.checked)
|
|
446
|
+
.map((opt) => opt.value);
|
|
447
|
+
this._searchParams[key] =
|
|
448
|
+
checkedValues.length > 0 ? checkedValues : defaultValue;
|
|
449
|
+
}
|
|
450
|
+
else {
|
|
451
|
+
this._searchParams[key] = ((_c = column.fieldProps) === null || _c === void 0 ? void 0 : _c.value) || defaultValue;
|
|
452
|
+
}
|
|
453
|
+
// 初始化 autoComplete 数据源
|
|
454
|
+
if (column.valueType === "autoComplete") {
|
|
455
|
+
this._autoCompleteDataSources[key] = [];
|
|
456
|
+
}
|
|
457
|
+
});
|
|
458
|
+
// 根据列的 order 字段进行排序,未设置 order 的放在最后
|
|
459
|
+
this._searchFiledColumns.sort((a, b) => {
|
|
460
|
+
const aOrder = isNil(a === null || a === void 0 ? void 0 : a.order) ? Number.MAX_SAFE_INTEGER : a.order;
|
|
461
|
+
const bOrder = isNil(b === null || b === void 0 ? void 0 : b.order) ? Number.MAX_SAFE_INTEGER : b.order;
|
|
462
|
+
if (aOrder === bOrder)
|
|
463
|
+
return 0;
|
|
464
|
+
return aOrder - bOrder;
|
|
465
|
+
});
|
|
466
|
+
this.setSearchFormDefaultProp(this._searchFiledColumns);
|
|
467
|
+
// 并发加载所有需要异步获取的选项
|
|
468
|
+
this.setSelectRequest(this._searchFiledColumns);
|
|
469
|
+
});
|
|
470
|
+
}
|
|
471
|
+
updateTableColumns(injectColumns) {
|
|
472
|
+
// 1. 使用最原始的columns作为数据源,确保辅助列完全不受影响
|
|
473
|
+
const originalColumns = cloneDeep(this.columns);
|
|
474
|
+
// 2. 处理字段映射(如果提供了fields参数)
|
|
475
|
+
let processedInjectColumns = injectColumns;
|
|
476
|
+
// 3. 分离辅助列和非辅助列(使用原始数据)
|
|
477
|
+
const nonAuxiliaryColumns = originalColumns.filter((col) => !col.auxiliaryColumn);
|
|
478
|
+
// 4. 按照injectColumns的顺序重新排列非辅助列
|
|
479
|
+
const reorderedNonAuxiliaryColumns = [];
|
|
480
|
+
const remainingNonAuxiliaryColumns = [...nonAuxiliaryColumns]; // 复制一份用于查找和移除
|
|
481
|
+
processedInjectColumns.forEach((injectCol) => {
|
|
482
|
+
// 查找非辅助列中对应的下标
|
|
483
|
+
const existingColIndex = remainingNonAuxiliaryColumns.findIndex((col) => col.prop === injectCol.prop);
|
|
484
|
+
if (existingColIndex !== -1) {
|
|
485
|
+
// 如果找到相同列,用injectColumns中的属性覆盖原始columns中的属性
|
|
486
|
+
const existingCol = remainingNonAuxiliaryColumns[existingColIndex];
|
|
487
|
+
const updatedCol = Object.assign(Object.assign({}, existingCol), injectCol);
|
|
488
|
+
reorderedNonAuxiliaryColumns.push(updatedCol);
|
|
489
|
+
// 从剩余数组中移除,避免重复
|
|
490
|
+
remainingNonAuxiliaryColumns.splice(existingColIndex, 1);
|
|
491
|
+
}
|
|
492
|
+
else {
|
|
493
|
+
// 如果没找到对应的列,直接添加injectColumns中的列
|
|
494
|
+
reorderedNonAuxiliaryColumns.push(injectCol);
|
|
495
|
+
}
|
|
496
|
+
});
|
|
497
|
+
// 5. 处理剩余的原始columns中的非辅助列(在injectColumns中未出现的列)
|
|
498
|
+
// 这些列应该被隐藏(设置hideInTable为true)
|
|
499
|
+
remainingNonAuxiliaryColumns.forEach((remainingCol) => {
|
|
500
|
+
const hiddenCol = Object.assign(Object.assign({}, remainingCol), { hideInTable: true });
|
|
501
|
+
reorderedNonAuxiliaryColumns.push(hiddenCol);
|
|
502
|
+
});
|
|
503
|
+
// 6. 按照原始columns的顺序重新组合:保持辅助列的原始位置和属性
|
|
504
|
+
const finalColumns = [];
|
|
505
|
+
let nonAuxiliaryIndex = 0;
|
|
506
|
+
let auxiliaryIndex = 0;
|
|
507
|
+
originalColumns.forEach((originalCol) => {
|
|
508
|
+
if (originalCol.auxiliaryColumn) {
|
|
509
|
+
// 如果是辅助列,使用原始列数据,完全不进行任何修改
|
|
510
|
+
finalColumns.push(originalCol);
|
|
511
|
+
auxiliaryIndex++;
|
|
512
|
+
}
|
|
513
|
+
else {
|
|
514
|
+
// 如果是非辅助列,使用重新排序后的列,但保留原始列的所有属性
|
|
515
|
+
const reorderedCol = reorderedNonAuxiliaryColumns[nonAuxiliaryIndex];
|
|
516
|
+
if (reorderedCol) {
|
|
517
|
+
// 合并原始列和重新排序后的列,确保保留所有原始属性
|
|
518
|
+
const mergedCol = Object.assign(Object.assign({}, originalCol), reorderedCol);
|
|
519
|
+
finalColumns.push(mergedCol);
|
|
520
|
+
}
|
|
521
|
+
else {
|
|
522
|
+
// 如果重新排序后的列不存在,使用原始列
|
|
523
|
+
finalColumns.push(originalCol);
|
|
524
|
+
}
|
|
525
|
+
nonAuxiliaryIndex++;
|
|
526
|
+
}
|
|
527
|
+
});
|
|
528
|
+
this.formateInnerColumns(finalColumns);
|
|
529
|
+
}
|
|
530
|
+
// 通过 Proxy 监听 _searchParams 的属性变更
|
|
531
|
+
createSearchParamsProxy(target) {
|
|
532
|
+
const self = this;
|
|
533
|
+
const handler = {
|
|
534
|
+
set(obj, prop, value) {
|
|
535
|
+
const key = String(prop);
|
|
536
|
+
const oldVal = obj[key];
|
|
537
|
+
if (oldVal === value) {
|
|
538
|
+
obj[key] = value;
|
|
539
|
+
return true;
|
|
540
|
+
}
|
|
541
|
+
obj[key] = value;
|
|
542
|
+
try {
|
|
543
|
+
self.onValuesChange.emit({
|
|
544
|
+
key,
|
|
545
|
+
value,
|
|
546
|
+
params: self.getSearchParams(),
|
|
547
|
+
});
|
|
548
|
+
}
|
|
549
|
+
catch (e) { }
|
|
550
|
+
return true;
|
|
551
|
+
},
|
|
552
|
+
};
|
|
553
|
+
return new Proxy(target, handler);
|
|
554
|
+
}
|
|
555
|
+
clearEmptySearchParams() {
|
|
556
|
+
const cloneSearchParams = cloneDeep(this._searchParams);
|
|
557
|
+
return cloneSearchParams;
|
|
558
|
+
}
|
|
559
|
+
buildServerSortPayload() {
|
|
560
|
+
// 构建激活排序集合(按优先级从低到高,末尾优先)
|
|
561
|
+
const activeKeys = this._sortPriority.filter((k) => !!this._sortMap[k]);
|
|
562
|
+
if (activeKeys.length === 0)
|
|
563
|
+
return null;
|
|
564
|
+
const sorts = activeKeys.map((field) => {
|
|
565
|
+
// 查找对应的列配置,优先使用sortName字段
|
|
566
|
+
const column = this._columns.find((col) => col.prop === field);
|
|
567
|
+
const sortField = (column === null || column === void 0 ? void 0 : column.sortName) || field;
|
|
568
|
+
return {
|
|
569
|
+
field: sortField,
|
|
570
|
+
order: this._sortMap[field],
|
|
571
|
+
};
|
|
572
|
+
});
|
|
573
|
+
if (this.multipleSort) {
|
|
574
|
+
return sorts; // 以数组形式提交多列排序
|
|
575
|
+
}
|
|
576
|
+
const [first] = sorts;
|
|
577
|
+
return first; // 兼容单列结构 { field, order }
|
|
578
|
+
}
|
|
579
|
+
sortDataSourceInPlace() {
|
|
580
|
+
if (!Array.isArray(this.dataSource) || this.dataSource.length === 0)
|
|
581
|
+
return;
|
|
582
|
+
const activeKeys = this._sortPriority.filter((k) => !!this._sortMap[k]);
|
|
583
|
+
if (activeKeys.length === 0)
|
|
584
|
+
return;
|
|
585
|
+
// 复制一份优先级,从前到后优先级从低到高(最后设置的字段优先)
|
|
586
|
+
const keysInPriority = [...activeKeys];
|
|
587
|
+
this.dataSource.sort((a, b) => {
|
|
588
|
+
for (let i = keysInPriority.length - 1; i >= 0; i--) {
|
|
589
|
+
const field = keysInPriority[i];
|
|
590
|
+
const order = this._sortMap[field];
|
|
591
|
+
const av = a === null || a === void 0 ? void 0 : a[field];
|
|
592
|
+
const bv = b === null || b === void 0 ? void 0 : b[field];
|
|
593
|
+
const cmp = this.compareValues(av, bv);
|
|
594
|
+
if (cmp !== 0)
|
|
595
|
+
return order === "ascend" ? cmp : -cmp;
|
|
596
|
+
}
|
|
597
|
+
return 0;
|
|
598
|
+
});
|
|
599
|
+
}
|
|
600
|
+
compareValues(aVal, bVal) {
|
|
601
|
+
if (aVal == null && bVal == null)
|
|
602
|
+
return 0;
|
|
603
|
+
if (aVal == null)
|
|
604
|
+
return -1;
|
|
605
|
+
if (bVal == null)
|
|
606
|
+
return 1;
|
|
607
|
+
if (aVal instanceof Date && bVal instanceof Date) {
|
|
608
|
+
return aVal.getTime() - bVal.getTime();
|
|
609
|
+
}
|
|
610
|
+
if (typeof aVal === "boolean" && typeof bVal === "boolean") {
|
|
611
|
+
return aVal === bVal ? 0 : aVal ? 1 : -1;
|
|
612
|
+
}
|
|
613
|
+
if (typeof aVal === "number" && typeof bVal === "number") {
|
|
614
|
+
return aVal - bVal;
|
|
615
|
+
}
|
|
616
|
+
if (typeof aVal === "string" && typeof bVal === "string") {
|
|
617
|
+
return aVal.localeCompare(bVal);
|
|
618
|
+
}
|
|
619
|
+
const aNum = Number(aVal);
|
|
620
|
+
const bNum = Number(bVal);
|
|
621
|
+
if (!isNaN(aNum) && !isNaN(bNum))
|
|
622
|
+
return aNum - bNum;
|
|
623
|
+
return String(aVal).localeCompare(String(bVal));
|
|
624
|
+
}
|
|
625
|
+
// 执行 autoComplete 数据源查询(实际执行逻辑)
|
|
626
|
+
executeAutoCompleteDataSource(event, column) {
|
|
627
|
+
var _a;
|
|
628
|
+
const fieldKey = ((_a = column.fieldProps) === null || _a === void 0 ? void 0 : _a.name) || column.prop;
|
|
629
|
+
if (column.fieldProps.dataSource &&
|
|
630
|
+
typeof column.fieldProps.dataSource ===
|
|
631
|
+
"function") {
|
|
632
|
+
try {
|
|
633
|
+
const result = column.fieldProps.dataSource(event);
|
|
634
|
+
// 如果返回的是 Promise,处理异步结果
|
|
635
|
+
if (result instanceof Promise) {
|
|
636
|
+
result
|
|
637
|
+
.then((data) => {
|
|
638
|
+
this._autoCompleteDataSources[fieldKey] = data || [];
|
|
639
|
+
})
|
|
640
|
+
.catch((error) => {
|
|
641
|
+
console.error("AutoComplete dataSource error:", error);
|
|
642
|
+
this._autoCompleteDataSources[fieldKey] = [];
|
|
643
|
+
});
|
|
644
|
+
}
|
|
645
|
+
else {
|
|
646
|
+
// 同步返回结果
|
|
647
|
+
this._autoCompleteDataSources[fieldKey] = result || [];
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
catch (error) {
|
|
651
|
+
console.error("AutoComplete dataSource error:", error);
|
|
652
|
+
this._autoCompleteDataSources[fieldKey] = [];
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
getSearchParams(options) {
|
|
657
|
+
const { useSaved = false } = options || {};
|
|
658
|
+
const rawParams = useSaved ? this._savedSearchParams : this._searchParams;
|
|
659
|
+
const params = cloneDeep(rawParams || {});
|
|
660
|
+
return Object.assign({ params, pageInfo: {
|
|
661
|
+
pageIndex: this._pageInfo.pageIndex,
|
|
662
|
+
pageSize: this._pageInfo.pageSize,
|
|
663
|
+
} }, (this.sortMode === "server"
|
|
664
|
+
? { sort: this.buildServerSortPayload() }
|
|
665
|
+
: {}));
|
|
666
|
+
}
|
|
667
|
+
reload(afterDelete) {
|
|
668
|
+
this.handleQuery(afterDelete);
|
|
669
|
+
}
|
|
670
|
+
setFieldsValue(fields) {
|
|
671
|
+
Object.keys(fields).forEach((k) => {
|
|
672
|
+
this._searchParams[k] = fields[k]; // 保留 Proxy,逐项赋值触发拦截
|
|
673
|
+
});
|
|
674
|
+
}
|
|
675
|
+
setFieldValue(key, value) {
|
|
676
|
+
this._searchParams[key] = value;
|
|
677
|
+
}
|
|
678
|
+
clearSelectedRow() {
|
|
679
|
+
this._selectedTableRow = null;
|
|
680
|
+
}
|
|
681
|
+
setColumns(columns, options) {
|
|
682
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
683
|
+
// 更新 columns 输入属性
|
|
684
|
+
this.columns = cloneDeep(columns);
|
|
685
|
+
// 重新格式化内部列
|
|
686
|
+
this.formateInnerColumns(this.columns);
|
|
687
|
+
// 重新设置搜索参数(异步操作)
|
|
688
|
+
// 先清空旧的搜索参数,避免旧数据残留
|
|
689
|
+
this._searchParams = {};
|
|
690
|
+
yield this.setSearchParams(this.columns);
|
|
691
|
+
// 重新创建 Proxy,确保表单项值变化能正常触发事件
|
|
692
|
+
this._searchParams = this.createSearchParamsProxy(this._searchParams);
|
|
693
|
+
// 重新注册模板(如果组件已经初始化完成)
|
|
694
|
+
if (this.allTemplates) {
|
|
695
|
+
this.autoRegisterTemplates();
|
|
696
|
+
}
|
|
697
|
+
// 如果设置了 reload 选项为 true,则重新查询数据
|
|
698
|
+
if ((options === null || options === void 0 ? void 0 : options.reload) === true) {
|
|
699
|
+
this.handleQuery();
|
|
700
|
+
}
|
|
701
|
+
});
|
|
702
|
+
}
|
|
703
|
+
getSelectedRowData() {
|
|
704
|
+
return this._selectedTableRow;
|
|
705
|
+
}
|
|
706
|
+
getCheckedRows() {
|
|
707
|
+
return this._selectedRows;
|
|
708
|
+
}
|
|
709
|
+
// 获取指定名称的模板
|
|
710
|
+
getTemplate(name) {
|
|
711
|
+
if (!name)
|
|
712
|
+
return null;
|
|
713
|
+
try {
|
|
714
|
+
// 首先从自定义模板中查找
|
|
715
|
+
const customTemplate = this.customTemplates.get(name);
|
|
716
|
+
if (customTemplate) {
|
|
717
|
+
return customTemplate;
|
|
718
|
+
}
|
|
719
|
+
// 然后从通用模板映射中查找
|
|
720
|
+
const template = this.templateMap.get(name);
|
|
721
|
+
if (template) {
|
|
722
|
+
return template;
|
|
723
|
+
}
|
|
724
|
+
return null;
|
|
725
|
+
}
|
|
726
|
+
catch (error) {
|
|
727
|
+
return null;
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
getToolTipTextValue(column, data) {
|
|
731
|
+
const key = column.customRender && this.getTemplate(column.customRender)
|
|
732
|
+
? ""
|
|
733
|
+
: column.ellipsis
|
|
734
|
+
? column.prop
|
|
735
|
+
: "";
|
|
736
|
+
return !key ? "" : data[key];
|
|
737
|
+
}
|
|
738
|
+
getTableRowChecked(data) {
|
|
739
|
+
// 启用复选框时:行高亮应与复选框选中状态一致(支持多选)
|
|
740
|
+
if (this.showCheckbox) {
|
|
741
|
+
return this.isRowChecked(data);
|
|
742
|
+
}
|
|
743
|
+
// 未启用复选框时:仍然使用单选行高亮
|
|
744
|
+
if (!this._selectedTableRow)
|
|
745
|
+
return false;
|
|
746
|
+
return JSON.stringify(this._selectedTableRow) === JSON.stringify(data);
|
|
747
|
+
}
|
|
748
|
+
// 检查行是否被禁用
|
|
749
|
+
isRowDisabled(data) {
|
|
750
|
+
if (!this.showCheckbox)
|
|
751
|
+
return false;
|
|
752
|
+
return this.rowDisabled ? this.rowDisabled(data) : false;
|
|
753
|
+
}
|
|
754
|
+
// 检查行是否被复选框选中
|
|
755
|
+
isRowChecked(data) {
|
|
756
|
+
if (!this.showCheckbox)
|
|
757
|
+
return false;
|
|
758
|
+
return this._selectedRows.some((row) => JSON.stringify(row) === JSON.stringify(data));
|
|
759
|
+
}
|
|
760
|
+
// 切换行的选中状态
|
|
761
|
+
toggleRowChecked(data, checked, event) {
|
|
762
|
+
if (event) {
|
|
763
|
+
event.stopPropagation(); // 阻止事件冒泡,避免触发行点击
|
|
764
|
+
}
|
|
765
|
+
// 如果行被禁用,不允许切换选中状态
|
|
766
|
+
if (this.isRowDisabled(data)) {
|
|
767
|
+
return;
|
|
768
|
+
}
|
|
769
|
+
const index = this._selectedRows.findIndex((row) => JSON.stringify(row) === JSON.stringify(data));
|
|
770
|
+
if (checked) {
|
|
771
|
+
// 选中
|
|
772
|
+
if (index === -1) {
|
|
773
|
+
this._selectedRows.push(data);
|
|
774
|
+
}
|
|
775
|
+
// 勾选复选框时同步设置高亮选中行
|
|
776
|
+
this._selectedTableRow = data;
|
|
777
|
+
}
|
|
778
|
+
else {
|
|
779
|
+
// 取消选中
|
|
780
|
+
if (index > -1) {
|
|
781
|
+
this._selectedRows.splice(index, 1);
|
|
782
|
+
}
|
|
783
|
+
// 若当前高亮行为该行,则取消高亮
|
|
784
|
+
if (this._selectedTableRow &&
|
|
785
|
+
JSON.stringify(this._selectedTableRow) === JSON.stringify(data)) {
|
|
786
|
+
this._selectedTableRow = null;
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
this.updateCheckAllStatus();
|
|
790
|
+
}
|
|
791
|
+
// 更新全选状态
|
|
792
|
+
updateCheckAllStatus() {
|
|
793
|
+
if (!this.showCheckbox || !Array.isArray(this.dataSource)) {
|
|
794
|
+
this._checkedAll = false;
|
|
795
|
+
this._indeterminate = false;
|
|
796
|
+
return;
|
|
797
|
+
}
|
|
798
|
+
// 只计算可用的行(未禁用的行)
|
|
799
|
+
const availableRows = this.dataSource.filter((row) => !this.isRowDisabled(row));
|
|
800
|
+
const checkedCount = this._selectedRows.length;
|
|
801
|
+
const totalCount = availableRows.length;
|
|
802
|
+
this._checkedAll =
|
|
803
|
+
totalCount > 0 && checkedCount > 0 && checkedCount === totalCount;
|
|
804
|
+
this._indeterminate = checkedCount > 0 && checkedCount < totalCount;
|
|
805
|
+
}
|
|
806
|
+
// 全选/取消全选
|
|
807
|
+
toggleCheckAll(checked, event) {
|
|
808
|
+
if (event) {
|
|
809
|
+
event.stopPropagation();
|
|
810
|
+
}
|
|
811
|
+
if (checked) {
|
|
812
|
+
// 全选:只选中未禁用的行
|
|
813
|
+
this._selectedRows = this.dataSource.filter((row) => !this.isRowDisabled(row));
|
|
814
|
+
// 同步设置高亮选中行为第一条可选数据
|
|
815
|
+
const availableRows = this._selectedRows;
|
|
816
|
+
this._selectedTableRow =
|
|
817
|
+
availableRows.length > 0 ? availableRows[0] : null;
|
|
818
|
+
}
|
|
819
|
+
else {
|
|
820
|
+
// 取消全选
|
|
821
|
+
this._selectedRows = [];
|
|
822
|
+
// 取消高亮
|
|
823
|
+
this._selectedTableRow = null;
|
|
824
|
+
}
|
|
825
|
+
this.updateCheckAllStatus();
|
|
826
|
+
}
|
|
827
|
+
// 获取选中的行数据
|
|
828
|
+
getSelectedRows() {
|
|
829
|
+
return this._selectedRows;
|
|
830
|
+
}
|
|
831
|
+
// 清空选中的行
|
|
832
|
+
clearSelectedRows() {
|
|
833
|
+
this._selectedRows = [];
|
|
834
|
+
this._checkedAll = false;
|
|
835
|
+
this._indeterminate = false;
|
|
836
|
+
this._selectedTableRow = null;
|
|
837
|
+
}
|
|
838
|
+
handleFieldCheckBoxChange(checkBoxOptions, key) {
|
|
839
|
+
this.setFieldsValue({
|
|
840
|
+
[key]: checkBoxOptions
|
|
841
|
+
.filter((item) => item.checked)
|
|
842
|
+
.map((item) => item.value),
|
|
843
|
+
});
|
|
844
|
+
}
|
|
845
|
+
handleSearch() {
|
|
846
|
+
this._savedSearchParams = this.clearEmptySearchParams();
|
|
847
|
+
this._pageInfo.pageIndex = 1;
|
|
848
|
+
this.handleQuery();
|
|
849
|
+
}
|
|
850
|
+
handleResetForm() {
|
|
851
|
+
Object.keys(this._searchParams).forEach((key) => {
|
|
852
|
+
const targetColumn = this._searchFiledColumns.find((item) => {
|
|
853
|
+
var _a;
|
|
854
|
+
return (((_a = item.fieldProps) === null || _a === void 0 ? void 0 : _a.name) || item.prop) === key;
|
|
855
|
+
});
|
|
856
|
+
// 对于checkbox类型,需要特殊处理默认值
|
|
857
|
+
if ((targetColumn === null || targetColumn === void 0 ? void 0 : targetColumn.valueType) === "checkbox") {
|
|
858
|
+
// 从原始columns配置中获取初始配置,以确保使用正确的默认值
|
|
859
|
+
const originalColumn = this.columns.find((item) => {
|
|
860
|
+
var _a;
|
|
861
|
+
return (((_a = item.fieldProps) === null || _a === void 0 ? void 0 : _a.name) || item.prop) === key;
|
|
862
|
+
});
|
|
863
|
+
// 从原始options中找出checked为true的项作为默认值
|
|
864
|
+
const originalFieldProps = originalColumn === null || originalColumn === void 0 ? void 0 : originalColumn.fieldProps;
|
|
865
|
+
const checkedValues = ((originalFieldProps === null || originalFieldProps === void 0 ? void 0 : originalFieldProps.options) || [])
|
|
866
|
+
.filter((opt) => opt.checked)
|
|
867
|
+
.map((opt) => opt.value);
|
|
868
|
+
const defaultValue = checkedValues.length > 0
|
|
869
|
+
? checkedValues
|
|
870
|
+
: PRO_TABLE_DEFAULT_PROPS[targetColumn.valueType].value;
|
|
871
|
+
this._searchParams[key] = defaultValue;
|
|
872
|
+
// 根据默认值恢复options的checked状态,使用原始options的结构
|
|
873
|
+
const defaultValues = Array.isArray(defaultValue) ? defaultValue : [];
|
|
874
|
+
const originalOptions = (originalFieldProps === null || originalFieldProps === void 0 ? void 0 : originalFieldProps.options) || [];
|
|
875
|
+
const targetFieldProps = targetColumn.fieldProps;
|
|
876
|
+
targetFieldProps.options = originalOptions.map((item) => {
|
|
877
|
+
return Object.assign(Object.assign({}, item), { checked: defaultValues.includes(item.value) });
|
|
878
|
+
});
|
|
879
|
+
}
|
|
880
|
+
else {
|
|
881
|
+
this._searchParams[key] = (targetColumn === null || targetColumn === void 0 ? void 0 : targetColumn.fieldProps) ? (targetColumn === null || targetColumn === void 0 ? void 0 : targetColumn.fieldProps.value) ||
|
|
882
|
+
PRO_TABLE_DEFAULT_PROPS[targetColumn.valueType].value
|
|
883
|
+
: PRO_TABLE_DEFAULT_PROPS[targetColumn.valueType].value;
|
|
884
|
+
}
|
|
885
|
+
});
|
|
886
|
+
this._savedSearchParams = {};
|
|
887
|
+
this._pageInfo.pageIndex = 1;
|
|
888
|
+
this.onResetFormBeforeReload.emit();
|
|
889
|
+
this.handleQuery();
|
|
890
|
+
}
|
|
891
|
+
handlePageIndexChange(pageIndex) {
|
|
892
|
+
this._pageInfo.pageIndex = pageIndex;
|
|
893
|
+
this.handleQuery();
|
|
894
|
+
}
|
|
895
|
+
handlePageSizeChange(pageSize) {
|
|
896
|
+
this._pageInfo.pageSize = pageSize;
|
|
897
|
+
this._pageInfo.pageIndex = 1;
|
|
898
|
+
this.handleQuery();
|
|
899
|
+
}
|
|
900
|
+
handleQuery(afterDelete) {
|
|
901
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
902
|
+
// 删除后刷新且当前页仅剩一条记录时,若不在第一页则先回退一页
|
|
903
|
+
if (afterDelete &&
|
|
904
|
+
Array.isArray(this.dataSource) &&
|
|
905
|
+
this.dataSource.length === 1 &&
|
|
906
|
+
this._pageInfo.pageIndex > 1) {
|
|
907
|
+
this._pageInfo.pageIndex = this._pageInfo.pageIndex - 1;
|
|
908
|
+
}
|
|
909
|
+
this._loading = true;
|
|
910
|
+
if (this.request) {
|
|
911
|
+
try {
|
|
912
|
+
const result = yield this.request(Object.assign({ params: this.clearEmptySearchParams(), pageInfo: {
|
|
913
|
+
pageIndex: this._pageInfo.pageIndex,
|
|
914
|
+
pageSize: this._pageInfo.pageSize,
|
|
915
|
+
} }, (this.sortMode === "server"
|
|
916
|
+
? { sort: this.buildServerSortPayload() }
|
|
917
|
+
: {})));
|
|
918
|
+
this.dataSource = result.data || [];
|
|
919
|
+
this.summaryData = result.summaryData || null;
|
|
920
|
+
// 本地排序模式:拿到数据后在前端排序
|
|
921
|
+
if (this.sortMode === "local") {
|
|
922
|
+
this.sortDataSourceInPlace();
|
|
923
|
+
}
|
|
924
|
+
this._pageInfo.total = result.total || 0;
|
|
925
|
+
// 更新全选状态
|
|
926
|
+
if (this.showCheckbox) {
|
|
927
|
+
this.updateCheckAllStatus();
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
catch (error) {
|
|
931
|
+
console.error("查询失败:", error);
|
|
932
|
+
this.dataSource = [];
|
|
933
|
+
this._pageInfo.total = 0;
|
|
934
|
+
this.summaryData = null;
|
|
935
|
+
}
|
|
936
|
+
finally {
|
|
937
|
+
this._loading = false;
|
|
938
|
+
this._selectedTableRow = null;
|
|
939
|
+
// 清空选中行(可选,根据业务需求决定是否保留跨页选中)
|
|
940
|
+
// this.clearSelectedRows();
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
else {
|
|
944
|
+
console.warn("未提供 _request 回调函数");
|
|
945
|
+
this._loading = false;
|
|
946
|
+
}
|
|
947
|
+
this.clearSelectedRows();
|
|
948
|
+
});
|
|
949
|
+
}
|
|
950
|
+
// 触发列排序变更
|
|
951
|
+
onSortChange(sortKey, sortOrder) {
|
|
952
|
+
// 单列排序:重置其它列;多列排序:保留其它列
|
|
953
|
+
if (!this.multipleSort) {
|
|
954
|
+
Object.keys(this._sortMap).forEach((key) => {
|
|
955
|
+
if (key !== sortKey)
|
|
956
|
+
this._sortMap[key] = null;
|
|
957
|
+
});
|
|
958
|
+
}
|
|
959
|
+
this._sortMap[sortKey] = sortOrder;
|
|
960
|
+
// 维护优先级队列:有序列且非空 -> 置于末尾;为空 -> 移除
|
|
961
|
+
this._sortPriority = this._sortPriority.filter((k) => k !== sortKey);
|
|
962
|
+
if (sortOrder) {
|
|
963
|
+
this._sortPriority.push(sortKey);
|
|
964
|
+
}
|
|
965
|
+
if (this.sortMode === "local") {
|
|
966
|
+
this.sortDataSourceInPlace();
|
|
967
|
+
}
|
|
968
|
+
else {
|
|
969
|
+
// 在线排序:重新请求
|
|
970
|
+
this.handleQuery();
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
getSortOrder(sortKey) {
|
|
974
|
+
return this._sortMap[sortKey] || null;
|
|
975
|
+
}
|
|
976
|
+
handleTableRowClick(data) {
|
|
977
|
+
this._selectedTableRow = data;
|
|
978
|
+
// 如果开启了复选框,点击行时只选中点击行(如果行未被禁用)
|
|
979
|
+
if (this.showCheckbox && !this.isRowDisabled(data)) {
|
|
980
|
+
// 先清空所有选中行
|
|
981
|
+
this._selectedRows = [];
|
|
982
|
+
// 只选中当前点击的行
|
|
983
|
+
this.toggleRowChecked(data, true);
|
|
984
|
+
}
|
|
985
|
+
this.onRowClick.emit(this._selectedTableRow);
|
|
986
|
+
}
|
|
987
|
+
handleTableRowDbClick(data) {
|
|
988
|
+
this._selectedTableRow = data;
|
|
989
|
+
this.onRowDbClick.emit(this._selectedTableRow);
|
|
990
|
+
}
|
|
991
|
+
handleColumnsSettingConfirm() {
|
|
992
|
+
this.queryDynamicColumns();
|
|
993
|
+
}
|
|
994
|
+
// 处理 autoComplete 输入事件(带防抖)
|
|
995
|
+
handleAutoCompleteInput(event, column) {
|
|
996
|
+
var _a;
|
|
997
|
+
const fieldKey = ((_a = column.fieldProps) === null || _a === void 0 ? void 0 : _a.name) || column.prop;
|
|
998
|
+
// 如果该字段还没有防抖函数,创建一个
|
|
999
|
+
if (!this._autoCompleteDebounceMap.has(fieldKey)) {
|
|
1000
|
+
const debouncedFn = debounce((evt) => {
|
|
1001
|
+
// 重新查找对应的 column,确保使用最新的配置
|
|
1002
|
+
const currentColumn = this._searchFiledColumns.find((col) => { var _a; return (((_a = col.fieldProps) === null || _a === void 0 ? void 0 : _a.name) || col.prop) === fieldKey; });
|
|
1003
|
+
if (currentColumn) {
|
|
1004
|
+
this.executeAutoCompleteDataSource(evt, currentColumn);
|
|
1005
|
+
}
|
|
1006
|
+
}, 300); // 300ms 防抖延迟
|
|
1007
|
+
this._autoCompleteDebounceMap.set(fieldKey, debouncedFn);
|
|
1008
|
+
}
|
|
1009
|
+
// 调用防抖函数
|
|
1010
|
+
const debouncedFn = this._autoCompleteDebounceMap.get(fieldKey);
|
|
1011
|
+
if (debouncedFn) {
|
|
1012
|
+
debouncedFn(event);
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
1015
|
+
// 获取 autoComplete 的数据源
|
|
1016
|
+
getAutoCompleteDataSource(column) {
|
|
1017
|
+
var _a;
|
|
1018
|
+
const fieldKey = ((_a = column.fieldProps) === null || _a === void 0 ? void 0 : _a.name) || column.prop;
|
|
1019
|
+
return this._autoCompleteDataSources[fieldKey] || [];
|
|
1020
|
+
}
|
|
1021
|
+
getFieldProps(column) {
|
|
1022
|
+
return column.fieldProps;
|
|
1023
|
+
}
|
|
1024
|
+
// 获取指定名称的label模板
|
|
1025
|
+
getLabelTemplate(name) {
|
|
1026
|
+
if (!name)
|
|
1027
|
+
return null;
|
|
1028
|
+
try {
|
|
1029
|
+
// 首先从自定义模板中查找
|
|
1030
|
+
const customTemplate = this.customTemplates.get(name);
|
|
1031
|
+
if (customTemplate) {
|
|
1032
|
+
return customTemplate;
|
|
1033
|
+
}
|
|
1034
|
+
// 然后从通用模板映射中查找
|
|
1035
|
+
const template = this.templateMap.get(name);
|
|
1036
|
+
if (template) {
|
|
1037
|
+
return template;
|
|
1038
|
+
}
|
|
1039
|
+
return null;
|
|
1040
|
+
}
|
|
1041
|
+
catch (error) {
|
|
1042
|
+
return null;
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
1045
|
+
// 获取 form-item 的动态类名
|
|
1046
|
+
getFormItemClassName(column) {
|
|
1047
|
+
const fieldName = this.getFieldProps(column).name || column.prop;
|
|
1048
|
+
return `pro-table-${fieldName}-form-item`;
|
|
1049
|
+
}
|
|
1050
|
+
}
|
|
1051
|
+
ProTableComponent.decorators = [
|
|
1052
|
+
{ type: Component, args: [{
|
|
1053
|
+
selector: "app-pro-table",
|
|
1054
|
+
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",
|
|
1055
|
+
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}"]
|
|
1056
|
+
},] }
|
|
1057
|
+
];
|
|
1058
|
+
ProTableComponent.ctorParameters = () => [
|
|
1059
|
+
{ type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [PRO_TABLE_COLUMN_REMOTE,] }] }
|
|
1060
|
+
];
|
|
1061
|
+
ProTableComponent.propDecorators = {
|
|
1062
|
+
showSearchBtn: [{ type: Input }],
|
|
1063
|
+
showClearBtn: [{ type: Input }],
|
|
1064
|
+
title: [{ type: Input }],
|
|
1065
|
+
tableName: [{ type: Input }],
|
|
1066
|
+
multiRow: [{ type: Input }],
|
|
1067
|
+
columns: [{ type: Input }],
|
|
1068
|
+
showSearchBar: [{ type: Input }],
|
|
1069
|
+
showActionBar: [{ type: Input }],
|
|
1070
|
+
confirmBtnText: [{ type: Input }],
|
|
1071
|
+
clearBtnText: [{ type: Input }],
|
|
1072
|
+
labelWidth: [{ type: Input }],
|
|
1073
|
+
labelAlign: [{ type: Input }],
|
|
1074
|
+
dataSource: [{ type: Input }],
|
|
1075
|
+
bordered: [{ type: Input }],
|
|
1076
|
+
outerBordered: [{ type: Input }],
|
|
1077
|
+
showPagination: [{ type: Input }],
|
|
1078
|
+
frontPagination: [{ type: Input }],
|
|
1079
|
+
scroll: [{ type: Input }],
|
|
1080
|
+
request: [{ type: Input }],
|
|
1081
|
+
summaryData: [{ type: Input }],
|
|
1082
|
+
sortMode: [{ type: Input }],
|
|
1083
|
+
showColumnSetting: [{ type: Input }],
|
|
1084
|
+
multipleSort: [{ type: Input }],
|
|
1085
|
+
showCheckbox: [{ type: Input }],
|
|
1086
|
+
rowDisabled: [{ type: Input }],
|
|
1087
|
+
autoTriggerRequest: [{ type: Input }],
|
|
1088
|
+
customTableRender: [{ type: Input }],
|
|
1089
|
+
onRowClick: [{ type: Output }],
|
|
1090
|
+
onRowDbClick: [{ type: Output }],
|
|
1091
|
+
onValuesChange: [{ type: Output }],
|
|
1092
|
+
onResetFormBeforeReload: [{ type: Output }],
|
|
1093
|
+
actionBarTpl: [{ type: ContentChild, args: ["actionBar",] }],
|
|
1094
|
+
imgActionBarTpl: [{ type: ContentChild, args: ["ImgActionBar",] }],
|
|
1095
|
+
allTemplates: [{ type: ContentChildren, args: [TemplateRef,] }]
|
|
1096
|
+
};
|
|
1097
|
+
|
|
1098
|
+
class PageContainerComponent {
|
|
1099
|
+
constructor() {
|
|
1100
|
+
this.title = "";
|
|
1101
|
+
}
|
|
1102
|
+
ngOnInit() { }
|
|
1103
|
+
}
|
|
1104
|
+
PageContainerComponent.decorators = [
|
|
1105
|
+
{ type: Component, args: [{
|
|
1106
|
+
selector: "app-page-container",
|
|
1107
|
+
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",
|
|
1108
|
+
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}"]
|
|
1109
|
+
},] }
|
|
1110
|
+
];
|
|
1111
|
+
PageContainerComponent.ctorParameters = () => [];
|
|
1112
|
+
PageContainerComponent.propDecorators = {
|
|
1113
|
+
title: [{ type: Input }],
|
|
1114
|
+
headerTpl: [{ type: ContentChild, args: ["header",] }],
|
|
1115
|
+
bodyTpl: [{ type: ContentChild, args: ["body",] }]
|
|
1116
|
+
};
|
|
1117
|
+
|
|
1118
|
+
class PageContainerModule {
|
|
1119
|
+
}
|
|
1120
|
+
PageContainerModule.decorators = [
|
|
1121
|
+
{ type: NgModule, args: [{
|
|
1122
|
+
imports: [
|
|
1123
|
+
CommonModule,
|
|
1124
|
+
FormsModule,
|
|
1125
|
+
HttpClientModule,
|
|
1126
|
+
RouterModule,
|
|
1127
|
+
NzCardModule,
|
|
1128
|
+
ReactiveFormsModule,
|
|
1129
|
+
],
|
|
1130
|
+
declarations: [PageContainerComponent],
|
|
1131
|
+
providers: [],
|
|
1132
|
+
exports: [PageContainerComponent],
|
|
1133
|
+
},] }
|
|
1134
|
+
];
|
|
1135
|
+
|
|
1136
|
+
class PlateInputComponent {
|
|
1137
|
+
constructor(cdr, elementRef, platePrefixLoadService) {
|
|
1138
|
+
this.cdr = cdr;
|
|
1139
|
+
this.elementRef = elementRef;
|
|
1140
|
+
this.platePrefixLoadService = platePrefixLoadService;
|
|
1141
|
+
this.nzPopoverVisible = false;
|
|
1142
|
+
this.platePrefix = "";
|
|
1143
|
+
this.plateSuffix = "";
|
|
1144
|
+
this.platePrefixOptions = [];
|
|
1145
|
+
this.disabled = false;
|
|
1146
|
+
this.onChange = (value) => { };
|
|
1147
|
+
this.onTouched = () => { };
|
|
1148
|
+
}
|
|
1149
|
+
ngOnInit() {
|
|
1150
|
+
if (this.platePrefixLoadService) {
|
|
1151
|
+
// 使用注入的全局服务加载车牌前缀选项
|
|
1152
|
+
this.platePrefixLoadService
|
|
1153
|
+
.loadPrefixOptions()
|
|
1154
|
+
.then((data) => {
|
|
1155
|
+
this.platePrefixOptions = data;
|
|
1156
|
+
})
|
|
1157
|
+
.catch(() => {
|
|
1158
|
+
this.platePrefixOptions = [];
|
|
1159
|
+
});
|
|
1160
|
+
}
|
|
1161
|
+
else {
|
|
1162
|
+
// 如果没有注入服务,则保持空数组
|
|
1163
|
+
this.platePrefixOptions = [];
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1166
|
+
handlePlatePrefix(value) {
|
|
1167
|
+
this.platePrefix = value;
|
|
1168
|
+
this.emitValue();
|
|
1169
|
+
this.nzPopoverVisible = false;
|
|
1170
|
+
this.removeClickOutsideListener();
|
|
1171
|
+
}
|
|
1172
|
+
writeValue(value) {
|
|
1173
|
+
if (value) {
|
|
1174
|
+
this.platePrefix = value.split("")[0];
|
|
1175
|
+
this.plateSuffix = value
|
|
1176
|
+
.split("")
|
|
1177
|
+
.filter((item, index) => index > 0)
|
|
1178
|
+
.join("");
|
|
1179
|
+
}
|
|
1180
|
+
else {
|
|
1181
|
+
this.platePrefix = "";
|
|
1182
|
+
this.plateSuffix = "";
|
|
1183
|
+
}
|
|
1184
|
+
}
|
|
1185
|
+
registerOnChange(fn) {
|
|
1186
|
+
this.onChange = fn;
|
|
1187
|
+
}
|
|
1188
|
+
registerOnTouched(fn) {
|
|
1189
|
+
this.onTouched = fn;
|
|
1190
|
+
}
|
|
1191
|
+
setDisabledState(isDisabled) {
|
|
1192
|
+
const previousDisabled = this.disabled;
|
|
1193
|
+
this.disabled = isDisabled;
|
|
1194
|
+
// 如果禁用状态改变,关闭 popover 并移除监听器
|
|
1195
|
+
if (previousDisabled !== isDisabled) {
|
|
1196
|
+
this.nzPopoverVisible = false;
|
|
1197
|
+
this.removeClickOutsideListener();
|
|
1198
|
+
// 强制变更检测
|
|
1199
|
+
this.cdr.detectChanges();
|
|
1200
|
+
}
|
|
1201
|
+
}
|
|
1202
|
+
handlePrefixClick(event) {
|
|
1203
|
+
if (this.disabled) {
|
|
1204
|
+
event.preventDefault();
|
|
1205
|
+
event.stopPropagation();
|
|
1206
|
+
this.nzPopoverVisible = false;
|
|
1207
|
+
return;
|
|
1208
|
+
}
|
|
1209
|
+
// 手动切换 popover 的显示/隐藏状态
|
|
1210
|
+
this.nzPopoverVisible = !this.nzPopoverVisible;
|
|
1211
|
+
// 如果打开了 popover,添加文档点击监听器
|
|
1212
|
+
if (this.nzPopoverVisible) {
|
|
1213
|
+
setTimeout(() => {
|
|
1214
|
+
this.attachClickOutsideListener();
|
|
1215
|
+
}, 0);
|
|
1216
|
+
}
|
|
1217
|
+
else {
|
|
1218
|
+
this.removeClickOutsideListener();
|
|
1219
|
+
}
|
|
1220
|
+
event.stopPropagation(); // 阻止事件冒泡
|
|
1221
|
+
}
|
|
1222
|
+
attachClickOutsideListener() {
|
|
1223
|
+
if (this.clickOutsideHandler) {
|
|
1224
|
+
return;
|
|
1225
|
+
}
|
|
1226
|
+
this.clickOutsideHandler = (event) => {
|
|
1227
|
+
const nativeElement = this.elementRef.nativeElement;
|
|
1228
|
+
const target = event.target;
|
|
1229
|
+
// 检查是否点击在 popover 内容区域内
|
|
1230
|
+
const popoverContent = document.querySelector('.plate-input-popover');
|
|
1231
|
+
const clickedInPopover = popoverContent && popoverContent.contains(target);
|
|
1232
|
+
// 检查是否点击在组件内部(前缀按钮)
|
|
1233
|
+
const clickedInComponent = nativeElement.contains(target);
|
|
1234
|
+
// 如果点击既不在组件内部,也不在 popover 内容区域,则关闭 popover
|
|
1235
|
+
if (!clickedInComponent && !clickedInPopover) {
|
|
1236
|
+
this.nzPopoverVisible = false;
|
|
1237
|
+
this.removeClickOutsideListener();
|
|
1238
|
+
this.cdr.detectChanges();
|
|
1239
|
+
}
|
|
1240
|
+
};
|
|
1241
|
+
// 使用捕获阶段,确保在其他事件处理之前执行
|
|
1242
|
+
document.addEventListener('click', this.clickOutsideHandler, true);
|
|
1243
|
+
}
|
|
1244
|
+
removeClickOutsideListener() {
|
|
1245
|
+
if (this.clickOutsideHandler) {
|
|
1246
|
+
document.removeEventListener('click', this.clickOutsideHandler, true);
|
|
1247
|
+
this.clickOutsideHandler = undefined;
|
|
1248
|
+
}
|
|
1249
|
+
}
|
|
1250
|
+
ngOnDestroy() {
|
|
1251
|
+
this.removeClickOutsideListener();
|
|
1252
|
+
}
|
|
1253
|
+
emitValue() {
|
|
1254
|
+
const fullPlate = this.platePrefix + this.plateSuffix;
|
|
1255
|
+
this.onChange(fullPlate);
|
|
1256
|
+
}
|
|
1257
|
+
onBlur() {
|
|
1258
|
+
this.onTouched();
|
|
1259
|
+
}
|
|
1260
|
+
handleAntdPlateSuffixBlur(event) {
|
|
1261
|
+
if (this.disabled)
|
|
1262
|
+
return;
|
|
1263
|
+
const value = event.target.value.toUpperCase();
|
|
1264
|
+
this.plateSuffix = value;
|
|
1265
|
+
this.emitValue();
|
|
1266
|
+
}
|
|
1267
|
+
}
|
|
1268
|
+
PlateInputComponent.decorators = [
|
|
1269
|
+
{ type: Component, args: [{
|
|
1270
|
+
selector: "app-plate-input",
|
|
1271
|
+
template: "<div\r\n class=\"plate-antd-input-container\"\r\n [class.plate-antd-input-disabled]=\"disabled\"\r\n>\r\n <div\r\n class=\"plate-input-prefix\"\r\n [class.plate-input-prefix-disabled]=\"disabled\"\r\n nz-popover\r\n nzPopoverPlacement=\"bottom\"\r\n nzPopoverOverlayClassName=\"plate-input-popover\"\r\n [(nzPopoverVisible)]=\"nzPopoverVisible\"\r\n [nzPopoverTrigger]=\"'manual'\"\r\n [nzPopoverContent]=\"contentTemplate\"\r\n (click)=\"handlePrefixClick($event)\"\r\n >\r\n {{ platePrefix | uppercase }}\r\n <i\r\n class=\"plate-input-icon-down\"\r\n [nzRotate]=\"nzPopoverVisible ? 180 : 0\"\r\n nz-icon\r\n nzType=\"down\"\r\n nzTheme=\"outline\"\r\n ></i>\r\n </div>\r\n <ng-template #contentTemplate>\r\n <div nz-row style=\"height: 100%\">\r\n <div\r\n nz-col\r\n nzSpan=\"4\"\r\n *ngFor=\"let item of platePrefixOptions\"\r\n class=\"plate-input-popover-item\"\r\n (click)=\"!disabled && handlePlatePrefix(item.value)\"\r\n [ngClass]=\"{\r\n 'plate-input-popover-item-active': item.value === platePrefix,\r\n 'plate-input-popover-item-default': item.value !== platePrefix\r\n }\"\r\n >\r\n <div class=\"plate-input-popover-item-label\">\r\n {{ item.label }}\r\n </div>\r\n </div>\r\n </div>\r\n </ng-template>\r\n <input\r\n class=\"plate-input-suffix\"\r\n type=\"text\"\r\n nz-input\r\n style=\"width: 75%\"\r\n [value]=\"plateSuffix | uppercase\"\r\n [disabled]=\"disabled\"\r\n (blur)=\"!disabled && handleAntdPlateSuffixBlur($event)\"\r\n />\r\n</div>\r\n",
|
|
1272
|
+
providers: [
|
|
1273
|
+
{
|
|
1274
|
+
provide: NG_VALUE_ACCESSOR,
|
|
1275
|
+
useExisting: forwardRef(() => PlateInputComponent),
|
|
1276
|
+
multi: true,
|
|
1277
|
+
},
|
|
1278
|
+
],
|
|
1279
|
+
styles: ["::ng-deep .plate-input-popover{box-sizing:border-box;padding:5px 0}::ng-deep .plate-input-popover .ant-popover-inner-content{height:264px;padding:0;width:387px}::ng-deep .plate-input-popover .ant-popover-inner-content .plate-input-popover-item{box-sizing:border-box;cursor:pointer;height:42px;padding:6px 12px}::ng-deep .plate-input-popover .ant-popover-inner-content .plate-input-popover-item .plate-input-popover-item-label{align-items:center;border:1px solid #ccc;display:flex;height:100%;justify-content:center;width:100%}::ng-deep .plate-input-popover .ant-popover-inner-content .plate-input-popover-item-default:hover{background-color:#eaeaea}::ng-deep .plate-input-popover .ant-popover-inner-content .plate-input-popover-item-active{background-color:#096dd9;color:#fff}::ng-deep .plate-input-prefix:hover:after{background-color:transparent;content:\"\";height:100%;position:absolute;right:0;top:0;width:1px;z-index:2}::ng-deep .plate-antd-input-container{display:flex;flex-wrap:nowrap;width:100%}::ng-deep .plate-antd-input-container .plate-input-prefix{align-items:center;border:1px solid #d9d9d9;border-radius:2px;cursor:pointer;display:flex;justify-content:center;min-height:32px;position:relative;text-align:center;width:60px}::ng-deep .plate-antd-input-container .plate-input-prefix .plate-input-icon-down{font-size:10px;position:absolute;right:5px;top:50%;transform:translateY(-50%)}::ng-deep .plate-antd-input-container .plate-input-prefix:hover:not(.plate-input-prefix-disabled){border-color:#40a9ff}::ng-deep .plate-antd-input-container .plate-input-prefix-disabled{background-color:#f5f5f5;border-color:#d9d9d9;color:rgba(0,0,0,.25);cursor:not-allowed}::ng-deep .plate-antd-input-container .plate-input-suffix{width:calc(100% - 60px)}"]
|
|
1280
|
+
},] }
|
|
1281
|
+
];
|
|
1282
|
+
PlateInputComponent.ctorParameters = () => [
|
|
1283
|
+
{ type: ChangeDetectorRef },
|
|
1284
|
+
{ type: ElementRef },
|
|
1285
|
+
{ type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [PLATE_PREFIX_LOAD_SERVICE,] }] }
|
|
1286
|
+
];
|
|
1287
|
+
|
|
1288
|
+
class PlateInputModule {
|
|
1289
|
+
}
|
|
1290
|
+
PlateInputModule.decorators = [
|
|
1291
|
+
{ type: NgModule, args: [{
|
|
1292
|
+
imports: [
|
|
1293
|
+
CommonModule,
|
|
1294
|
+
FormsModule,
|
|
1295
|
+
NzGridModule,
|
|
1296
|
+
NzInputModule,
|
|
1297
|
+
NzPopoverModule,
|
|
1298
|
+
NzIconModule,
|
|
1299
|
+
],
|
|
1300
|
+
declarations: [PlateInputComponent],
|
|
1301
|
+
providers: [],
|
|
1302
|
+
exports: [PlateInputComponent],
|
|
1303
|
+
},] }
|
|
1304
|
+
];
|
|
1305
|
+
|
|
1306
|
+
class TableSearchBarComponent {
|
|
1307
|
+
constructor() {
|
|
1308
|
+
this.leftColSpan = 21;
|
|
1309
|
+
this.rightColSpan = 3;
|
|
1310
|
+
this.labelWidth = "90px";
|
|
1311
|
+
this.labelAlign = "right";
|
|
1312
|
+
}
|
|
1313
|
+
ngOnInit() {
|
|
1314
|
+
this.setCSSVariablesToTarget();
|
|
1315
|
+
}
|
|
1316
|
+
ngAfterViewInit() {
|
|
1317
|
+
this.setCSSVariablesToTarget();
|
|
1318
|
+
}
|
|
1319
|
+
setCSSVariablesToTarget() {
|
|
1320
|
+
// setTimeout(() => {
|
|
1321
|
+
// const leftElement = document.querySelectorAll(".table-search-bar-left");
|
|
1322
|
+
// console.log('leftElement',leftElement);
|
|
1323
|
+
// if (leftElement.length > 0) {
|
|
1324
|
+
// leftElement.forEach((element) => {
|
|
1325
|
+
// (element as HTMLElement).style.setProperty(
|
|
1326
|
+
// "--label-width",
|
|
1327
|
+
// this.labelWidth
|
|
1328
|
+
// );
|
|
1329
|
+
// (element as HTMLElement).style.setProperty(
|
|
1330
|
+
// "--label-align",
|
|
1331
|
+
// this.labelAlign
|
|
1332
|
+
// );
|
|
1333
|
+
// });
|
|
1334
|
+
// }
|
|
1335
|
+
// });
|
|
1336
|
+
}
|
|
1337
|
+
}
|
|
1338
|
+
TableSearchBarComponent.decorators = [
|
|
1339
|
+
{ type: Component, args: [{
|
|
1340
|
+
selector: "app-table-search-bar",
|
|
1341
|
+
template: "<div class=\"table-search-bar\">\r\n <div class=\"table-search-bar-left\" style=\"--label-width: {{ labelWidth }}; --label-align: {{ labelAlign }};\">\r\n <ng-container *ngTemplateOutlet=\"leftContentTpl\"></ng-container>\r\n </div>\r\n <div class=\"table-search-bar-right\">\r\n <nz-space nzDirection=\"vertical\" nzAlign=\"end\">\r\n <nz-space-item>\r\n <ng-container *ngTemplateOutlet=\"actionTextBtnTpl\"></ng-container>\r\n </nz-space-item>\r\n <nz-space-item>\r\n <ng-container *ngTemplateOutlet=\"actionImgBtnTpl\"></ng-container>\r\n </nz-space-item>\r\n </nz-space>\r\n <!-- <ng-container *ngTemplateOutlet=\"rightContentTpl\"></ng-container> -->\r\n </div>\r\n</div>\r\n",
|
|
1342
|
+
styles: ["::ng-deep .table-search-bar{align-items:flex-start;display:flex;flex-wrap:wrap;gap:16px;width:100%}::ng-deep .table-search-bar-left{display:flex;flex:1;flex-wrap:wrap;gap:0 normal;min-width:0}::ng-deep .table-search-bar-left ::ng-deep .ant-form-item{flex-shrink:0;flex-wrap:nowrap;width:250px}::ng-deep .table-search-bar-left ::ng-deep .ant-form-item .ant-form-item-label{flex-shrink:0;text-align:var(--label-align);width:var(--label-width)}::ng-deep .table-search-bar-left ::ng-deep .ant-form-item .ant-form-item-label label:after{content:\"\"}::ng-deep .table-search-bar-left ::ng-deep .ant-form-item .ant-picker{width:100%}::ng-deep .table-search-bar-right{align-items:flex-start;display:flex;flex-shrink:0}"]
|
|
1343
|
+
},] }
|
|
1344
|
+
];
|
|
1345
|
+
TableSearchBarComponent.ctorParameters = () => [];
|
|
1346
|
+
TableSearchBarComponent.propDecorators = {
|
|
1347
|
+
leftColSpan: [{ type: Input }],
|
|
1348
|
+
rightColSpan: [{ type: Input }],
|
|
1349
|
+
labelWidth: [{ type: Input }],
|
|
1350
|
+
labelAlign: [{ type: Input }],
|
|
1351
|
+
leftContentTpl: [{ type: ContentChild, args: ["leftContent",] }],
|
|
1352
|
+
actionTextBtnTpl: [{ type: ContentChild, args: ["actionTextBtn",] }],
|
|
1353
|
+
actionImgBtnTpl: [{ type: ContentChild, args: ["actionImgBtn",] }]
|
|
1354
|
+
};
|
|
1355
|
+
|
|
1356
|
+
class TableSearchBarModule {
|
|
1357
|
+
}
|
|
1358
|
+
TableSearchBarModule.decorators = [
|
|
1359
|
+
{ type: NgModule, args: [{
|
|
1360
|
+
imports: [
|
|
1361
|
+
CommonModule,
|
|
1362
|
+
FormsModule,
|
|
1363
|
+
HttpClientModule,
|
|
1364
|
+
RouterModule,
|
|
1365
|
+
NzGridModule,
|
|
1366
|
+
ReactiveFormsModule,
|
|
1367
|
+
NzSpaceModule,
|
|
1368
|
+
],
|
|
1369
|
+
declarations: [TableSearchBarComponent],
|
|
1370
|
+
providers: [],
|
|
1371
|
+
exports: [TableSearchBarComponent],
|
|
1372
|
+
},] }
|
|
1373
|
+
];
|
|
1374
|
+
|
|
1375
|
+
class ColmunsSettingComponent {
|
|
1376
|
+
constructor(columnRemote) {
|
|
1377
|
+
this.columnRemote = columnRemote;
|
|
1378
|
+
this.columns = [];
|
|
1379
|
+
this.selectedColumns = [];
|
|
1380
|
+
this.afterConfirm = new EventEmitter();
|
|
1381
|
+
this.modalVisible = false;
|
|
1382
|
+
this.options = [];
|
|
1383
|
+
this.sortableInstance = null;
|
|
1384
|
+
}
|
|
1385
|
+
ngOnInit() { }
|
|
1386
|
+
ngAfterViewInit() {
|
|
1387
|
+
this.initSortable();
|
|
1388
|
+
}
|
|
1389
|
+
ngOnDestroy() {
|
|
1390
|
+
if (this.sortableInstance) {
|
|
1391
|
+
this.sortableInstance.destroy();
|
|
1392
|
+
}
|
|
1393
|
+
}
|
|
1394
|
+
initSortable() {
|
|
1395
|
+
// 先销毁已存在的实例
|
|
1396
|
+
if (this.sortableInstance) {
|
|
1397
|
+
this.sortableInstance.destroy();
|
|
1398
|
+
this.sortableInstance = null;
|
|
1399
|
+
}
|
|
1400
|
+
if (this.sortableContainer && this.sortableContainer.nativeElement) {
|
|
1401
|
+
this.sortableInstance = new Sortable(this.sortableContainer.nativeElement, {
|
|
1402
|
+
animation: 150,
|
|
1403
|
+
ghostClass: "sortable-ghost",
|
|
1404
|
+
chosenClass: "sortable-chosen",
|
|
1405
|
+
dragClass: "sortable-drag",
|
|
1406
|
+
handle: ".sort-list-item",
|
|
1407
|
+
onEnd: (evt) => {
|
|
1408
|
+
this.onSortEnd(evt);
|
|
1409
|
+
},
|
|
1410
|
+
});
|
|
1411
|
+
}
|
|
1412
|
+
}
|
|
1413
|
+
onSortEnd(evt) {
|
|
1414
|
+
const { oldIndex, newIndex } = evt;
|
|
1415
|
+
if (oldIndex !== newIndex) {
|
|
1416
|
+
// 创建新的数组来避免直接修改输入属性
|
|
1417
|
+
const newSelectedColumns = [...this.selectedColumns];
|
|
1418
|
+
const movedItem = newSelectedColumns.splice(oldIndex, 1)[0];
|
|
1419
|
+
newSelectedColumns.splice(newIndex, 0, movedItem);
|
|
1420
|
+
// 更新 selectedColumns
|
|
1421
|
+
this.selectedColumns = newSelectedColumns;
|
|
1422
|
+
}
|
|
1423
|
+
}
|
|
1424
|
+
trackByColumn(index, item) {
|
|
1425
|
+
return item.prop || index.toString();
|
|
1426
|
+
}
|
|
1427
|
+
/**
|
|
1428
|
+
* 同步 options 数组的 checked 状态与 selectedColumns
|
|
1429
|
+
*/
|
|
1430
|
+
syncOptionsWithSelectedColumns() {
|
|
1431
|
+
const selectedProps = this.selectedColumns.map((col) => col.prop);
|
|
1432
|
+
this.options.forEach((option) => {
|
|
1433
|
+
option.checked = selectedProps.includes(option.value);
|
|
1434
|
+
});
|
|
1435
|
+
}
|
|
1436
|
+
handleModalVisible() {
|
|
1437
|
+
this.options = this.columns
|
|
1438
|
+
.filter((item) => !item.auxiliaryColumn)
|
|
1439
|
+
.map((item) => {
|
|
1440
|
+
return {
|
|
1441
|
+
label: item.title,
|
|
1442
|
+
value: item.prop,
|
|
1443
|
+
checked: item.hideInTable ? false : true,
|
|
1444
|
+
sortName: item.sortName || null,
|
|
1445
|
+
};
|
|
1446
|
+
});
|
|
1447
|
+
// 同步 options 的 checked 状态与当前 selectedColumns
|
|
1448
|
+
this.syncOptionsWithSelectedColumns();
|
|
1449
|
+
this.modalVisible = true;
|
|
1450
|
+
// 模态框打开后重新初始化排序
|
|
1451
|
+
setTimeout(() => {
|
|
1452
|
+
this.initSortable();
|
|
1453
|
+
}, 100);
|
|
1454
|
+
}
|
|
1455
|
+
handleModalClose() {
|
|
1456
|
+
this.modalVisible = false;
|
|
1457
|
+
if (this.sortableInstance) {
|
|
1458
|
+
this.sortableInstance.destroy();
|
|
1459
|
+
this.sortableInstance = null;
|
|
1460
|
+
}
|
|
1461
|
+
}
|
|
1462
|
+
handleSelectRemove(key) {
|
|
1463
|
+
this.selectedColumns = this.selectedColumns.filter((item) => item.prop !== key);
|
|
1464
|
+
// 使用同步方法确保所有状态一致
|
|
1465
|
+
this.syncOptionsWithSelectedColumns();
|
|
1466
|
+
}
|
|
1467
|
+
handleCheckBoxChange(value, record) {
|
|
1468
|
+
if (!value) {
|
|
1469
|
+
this.handleSelectRemove(record.value);
|
|
1470
|
+
}
|
|
1471
|
+
else {
|
|
1472
|
+
this.selectedColumns.push({
|
|
1473
|
+
title: record.label,
|
|
1474
|
+
prop: record.value,
|
|
1475
|
+
sortName: record.sortName,
|
|
1476
|
+
hideInTable: false,
|
|
1477
|
+
});
|
|
1478
|
+
// 添加项目后同步状态
|
|
1479
|
+
this.syncOptionsWithSelectedColumns();
|
|
1480
|
+
}
|
|
1481
|
+
}
|
|
1482
|
+
handleConfirm() {
|
|
1483
|
+
var _a;
|
|
1484
|
+
if (!((_a = this.columnRemote) === null || _a === void 0 ? void 0 : _a.setCol) || !this.tableName) {
|
|
1485
|
+
this.modalVisible = false;
|
|
1486
|
+
this.afterConfirm.emit();
|
|
1487
|
+
return;
|
|
1488
|
+
}
|
|
1489
|
+
const payload = this.selectedColumns.map((column) => {
|
|
1490
|
+
return {
|
|
1491
|
+
field: column.prop,
|
|
1492
|
+
isShow: column.hideInTable ? false : true,
|
|
1493
|
+
header: column.title,
|
|
1494
|
+
sortName: column.sortName || null,
|
|
1495
|
+
};
|
|
1496
|
+
});
|
|
1497
|
+
const result = this.columnRemote.setCol(this.tableName, payload);
|
|
1498
|
+
const done = (res) => {
|
|
1499
|
+
this.modalVisible = false;
|
|
1500
|
+
this.afterConfirm.emit();
|
|
1501
|
+
};
|
|
1502
|
+
if (result && isObservable(result)) {
|
|
1503
|
+
result.subscribe(done, () => done(null));
|
|
1504
|
+
}
|
|
1505
|
+
else {
|
|
1506
|
+
Promise.resolve(result).finally(() => done(null));
|
|
1507
|
+
}
|
|
1508
|
+
}
|
|
1509
|
+
}
|
|
1510
|
+
ColmunsSettingComponent.decorators = [
|
|
1511
|
+
{ type: Component, args: [{
|
|
1512
|
+
selector: "app-colmuns-setting",
|
|
1513
|
+
template: "<div class=\"action-pic-btn\" (click)=\"handleModalVisible()\" title=\"\u5217\u8BBE\u7F6E\">\r\n <i nz-icon nzType=\"setting\" nzTheme=\"outline\"></i>\r\n</div>\r\n\r\n<nz-modal\r\n [(nzVisible)]=\"modalVisible\"\r\n [nzWidth]=\"820\"\r\n [nzTitle]=\"modalTitle\"\r\n (nzOnCancel)=\"handleModalClose()\"\r\n [nzContent]=\"modalBody\"\r\n [nzBodyStyle]=\"{ padding: '12px' }\"\r\n (nzOnOk)=\"handleConfirm()\"\r\n [nzWrapClassName]=\"'draggable-modal'\"\r\n>\r\n <ng-template #modalTitle>\r\n <div\r\n class=\"modal-drag-handle\"\r\n cdkDrag\r\n [cdkDragRootElement]=\"'.draggable-modal .ant-modal'\"\r\n cdkDragHandle\r\n [cdkDragBoundary]=\"'.draggable-modal'\"\r\n >\r\n <span>\u8BBE\u7F6E\u663E\u793A\u5B57\u6BB5</span>\r\n </div>\r\n </ng-template>\r\n <ng-template #modalBody>\r\n <div class=\"modal-body\">\r\n <div class=\"check-box-list\">\r\n <div class=\"mb-12\">\u53EF\u9009\u5B57\u6BB5</div>\r\n <nz-checkbox-wrapper style=\"width: 100%\">\r\n <div nz-row [nzGutter]=\"[24, 24]\">\r\n <div nz-col nzSpan=\"6\" *ngFor=\"let item of options\">\r\n <label\r\n nz-checkbox\r\n nzValue=\"item.value\"\r\n [ngModel]=\"item.checked\"\r\n (ngModelChange)=\"handleCheckBoxChange($event, item)\"\r\n >{{ item.label }}</label\r\n >\r\n </div>\r\n </div>\r\n </nz-checkbox-wrapper>\r\n </div>\r\n <div class=\"sort-list\">\r\n <div nz-typography class=\"mb-4\">\u5F53\u524D\u5DF2\u7ECF\u9009\u5B9A\u7684\u5B57\u6BB5</div>\r\n <div\r\n nz-typography\r\n nzType=\"secondary\"\r\n class=\"mb-4\"\r\n [style.fontSize]=\"'12px'\"\r\n >\r\n \u63D0\u793A\uFF1A\u53EF\u62D6\u52A8\u6392\u5E8F\r\n </div>\r\n <div #sortableContainer class=\"sortable-container\">\r\n <div\r\n class=\"sort-list-item mb-12\"\r\n *ngFor=\"let item of selectedColumns; trackBy: trackByColumn\"\r\n >\r\n {{ item.title }}\r\n <a\r\n href=\"javascript:void(0)\"\r\n class=\"fieldd-remove\"\r\n title=\"\u5220\u9664\"\r\n (click)=\"handleSelectRemove(item.prop)\"\r\n >\u00D7</a\r\n >\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </ng-template>\r\n</nz-modal>\r\n",
|
|
1514
|
+
styles: [".action-pic-btn{align-items:center;cursor:pointer;display:inline-flex;height:32px;justify-content:center;width:32px}.modal-body{display:flex;height:600px;width:100%}.modal-body .check-box-list{height:100%;width:calc(100% - 200px)}.modal-body .sort-list{border-left:1px solid #e3e3e3;box-sizing:border-box;height:100%;overflow-y:auto;padding-left:12px;padding-right:12px;width:200px}.modal-body .sort-list .sortable-container{min-height:100px}.modal-body .sort-list .sort-list-item{-moz-user-select:none;-webkit-user-select:none;align-items:center;cursor:move;display:flex;justify-content:space-between;user-select:none}.modal-body .sort-list .sort-list-item a{font-size:18px}.modal-drag-handle{-moz-user-select:none;-webkit-user-select:none;cursor:move;user-select:none;width:100%}"]
|
|
1515
|
+
},] }
|
|
1516
|
+
];
|
|
1517
|
+
ColmunsSettingComponent.ctorParameters = () => [
|
|
1518
|
+
{ type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [PRO_TABLE_COLUMN_REMOTE,] }] }
|
|
1519
|
+
];
|
|
1520
|
+
ColmunsSettingComponent.propDecorators = {
|
|
1521
|
+
columns: [{ type: Input }],
|
|
1522
|
+
selectedColumns: [{ type: Input }],
|
|
1523
|
+
tableName: [{ type: Input }],
|
|
1524
|
+
afterConfirm: [{ type: Output }],
|
|
1525
|
+
sortableContainer: [{ type: ViewChild, args: ["sortableContainer", { static: false },] }]
|
|
1526
|
+
};
|
|
1527
|
+
|
|
1528
|
+
class DynamicSearchFieldComponent {
|
|
1529
|
+
constructor(cfr) {
|
|
1530
|
+
this.cfr = cfr;
|
|
1531
|
+
this.component = null;
|
|
1532
|
+
this.props = null;
|
|
1533
|
+
this.valueChange = new EventEmitter();
|
|
1534
|
+
this.cmpRef = null;
|
|
1535
|
+
this.isCva = false;
|
|
1536
|
+
this.cvaOnChange = null;
|
|
1537
|
+
}
|
|
1538
|
+
ngOnInit() {
|
|
1539
|
+
this.render();
|
|
1540
|
+
}
|
|
1541
|
+
ngOnChanges(changes) {
|
|
1542
|
+
if (changes.component && !changes.component.firstChange) {
|
|
1543
|
+
this.destroy();
|
|
1544
|
+
this.render();
|
|
1545
|
+
return;
|
|
1546
|
+
}
|
|
1547
|
+
if (this.cmpRef) {
|
|
1548
|
+
if (changes.value && !changes.value.firstChange) {
|
|
1549
|
+
if (this.isCva) {
|
|
1550
|
+
if (typeof this.cmpRef.instance.writeValue === 'function') {
|
|
1551
|
+
this.cmpRef.instance.writeValue(this.value);
|
|
1552
|
+
}
|
|
1553
|
+
}
|
|
1554
|
+
else if ('value' in this.cmpRef.instance) {
|
|
1555
|
+
this.cmpRef.instance.value = this.value;
|
|
1556
|
+
}
|
|
1557
|
+
}
|
|
1558
|
+
if (changes.props && !changes.props.firstChange) {
|
|
1559
|
+
this.applyProps();
|
|
1560
|
+
}
|
|
1561
|
+
}
|
|
1562
|
+
}
|
|
1563
|
+
render() {
|
|
1564
|
+
if (!this.component)
|
|
1565
|
+
return;
|
|
1566
|
+
const factory = this.cfr.resolveComponentFactory(this.component);
|
|
1567
|
+
this.vc.clear();
|
|
1568
|
+
this.cmpRef = this.vc.createComponent(factory);
|
|
1569
|
+
this.isCva = typeof this.cmpRef.instance.registerOnChange === 'function' && typeof this.cmpRef.instance.writeValue === 'function';
|
|
1570
|
+
if (this.isCva) {
|
|
1571
|
+
this.cmpRef.instance.writeValue(this.value);
|
|
1572
|
+
this.cmpRef.instance.registerOnChange((v) => {
|
|
1573
|
+
this.valueChange.emit(v);
|
|
1574
|
+
});
|
|
1575
|
+
}
|
|
1576
|
+
else {
|
|
1577
|
+
if ('value' in this.cmpRef.instance) {
|
|
1578
|
+
this.cmpRef.instance.value = this.value;
|
|
1579
|
+
}
|
|
1580
|
+
if ('valueChange' in this.cmpRef.instance && this.cmpRef.instance.valueChange && typeof this.cmpRef.instance.valueChange.subscribe === 'function') {
|
|
1581
|
+
this.cmpRef.instance.valueChange.subscribe((v) => {
|
|
1582
|
+
this.valueChange.emit(v);
|
|
1583
|
+
});
|
|
1584
|
+
}
|
|
1585
|
+
}
|
|
1586
|
+
this.applyProps();
|
|
1587
|
+
}
|
|
1588
|
+
applyProps() {
|
|
1589
|
+
const p = this.props || {};
|
|
1590
|
+
const extra = p.componentProps || {};
|
|
1591
|
+
Object.keys(extra).forEach((k) => {
|
|
1592
|
+
try {
|
|
1593
|
+
this.cmpRef.instance[k] = extra[k];
|
|
1594
|
+
}
|
|
1595
|
+
catch (_a) { }
|
|
1596
|
+
});
|
|
1597
|
+
}
|
|
1598
|
+
destroy() {
|
|
1599
|
+
if (this.cmpRef) {
|
|
1600
|
+
try {
|
|
1601
|
+
this.cmpRef.destroy();
|
|
1602
|
+
}
|
|
1603
|
+
catch (_a) { }
|
|
1604
|
+
this.cmpRef = null;
|
|
1605
|
+
}
|
|
1606
|
+
}
|
|
1607
|
+
ngOnDestroy() {
|
|
1608
|
+
this.destroy();
|
|
1609
|
+
}
|
|
1610
|
+
}
|
|
1611
|
+
DynamicSearchFieldComponent.decorators = [
|
|
1612
|
+
{ type: Component, args: [{
|
|
1613
|
+
selector: 'app-dynamic-search-field',
|
|
1614
|
+
template: `<ng-template #vc></ng-template>`
|
|
1615
|
+
},] }
|
|
1616
|
+
];
|
|
1617
|
+
DynamicSearchFieldComponent.ctorParameters = () => [
|
|
1618
|
+
{ type: ComponentFactoryResolver }
|
|
1619
|
+
];
|
|
1620
|
+
DynamicSearchFieldComponent.propDecorators = {
|
|
1621
|
+
component: [{ type: Input }],
|
|
1622
|
+
value: [{ type: Input }],
|
|
1623
|
+
props: [{ type: Input }],
|
|
1624
|
+
valueChange: [{ type: Output }],
|
|
1625
|
+
vc: [{ type: ViewChild, args: ['vc', { read: ViewContainerRef, static: true },] }]
|
|
1626
|
+
};
|
|
1627
|
+
|
|
1628
|
+
class ProTableModule {
|
|
1629
|
+
}
|
|
1630
|
+
ProTableModule.decorators = [
|
|
1631
|
+
{ type: NgModule, args: [{
|
|
1632
|
+
imports: [
|
|
1633
|
+
CommonModule,
|
|
1634
|
+
FormsModule,
|
|
1635
|
+
HttpClientModule,
|
|
1636
|
+
RouterModule,
|
|
1637
|
+
NzFormModule,
|
|
1638
|
+
NzSelectModule,
|
|
1639
|
+
NzSpaceModule,
|
|
1640
|
+
NzGridModule,
|
|
1641
|
+
NzInputModule,
|
|
1642
|
+
ReactiveFormsModule,
|
|
1643
|
+
NzPopoverModule,
|
|
1644
|
+
NzIconModule,
|
|
1645
|
+
NzButtonModule,
|
|
1646
|
+
PageContainerModule,
|
|
1647
|
+
TableSearchBarModule,
|
|
1648
|
+
NzTableModule,
|
|
1649
|
+
PlateInputModule,
|
|
1650
|
+
NzDatePickerModule,
|
|
1651
|
+
NzModalModule,
|
|
1652
|
+
NzCheckboxModule,
|
|
1653
|
+
NzTypographyModule,
|
|
1654
|
+
DragDropModule,
|
|
1655
|
+
NzCheckboxModule,
|
|
1656
|
+
NzAutocompleteModule,
|
|
1657
|
+
NzInputNumberModule,
|
|
1658
|
+
NzToolTipModule,
|
|
1659
|
+
],
|
|
1660
|
+
declarations: [ProTableComponent, ColmunsSettingComponent, DynamicSearchFieldComponent],
|
|
1661
|
+
providers: [
|
|
1662
|
+
{
|
|
1663
|
+
// 默认不提供远程列服务,宿主可覆盖注入
|
|
1664
|
+
provide: PRO_TABLE_COLUMN_REMOTE,
|
|
1665
|
+
useValue: null,
|
|
1666
|
+
},
|
|
1667
|
+
],
|
|
1668
|
+
exports: [ProTableComponent],
|
|
1669
|
+
},] }
|
|
1670
|
+
];
|
|
1671
|
+
|
|
1672
|
+
/**
|
|
1673
|
+
* 默认的车牌前缀加载服务实现
|
|
1674
|
+
* 使用 HttpClient 调用 API 获取车牌前缀选项
|
|
1675
|
+
*/
|
|
1676
|
+
class DefaultPlatePrefixLoadService {
|
|
1677
|
+
constructor(http) {
|
|
1678
|
+
this.http = http;
|
|
1679
|
+
this.defaultApiUrl = "/PlateFirstWord/GetPlateFirstWord";
|
|
1680
|
+
}
|
|
1681
|
+
loadPrefixOptions() {
|
|
1682
|
+
return this.http
|
|
1683
|
+
.post(this.defaultApiUrl, { dictCode: "PlateFirstWord" })
|
|
1684
|
+
.toPromise()
|
|
1685
|
+
.then((list) => {
|
|
1686
|
+
const options = [];
|
|
1687
|
+
// 添加空选项(与旧版保持一致)
|
|
1688
|
+
options.push({ label: "", value: "" });
|
|
1689
|
+
// 转换数据格式
|
|
1690
|
+
for (let i = 0; i < list.length; i++) {
|
|
1691
|
+
options.push({
|
|
1692
|
+
label: list[i],
|
|
1693
|
+
value: list[i],
|
|
1694
|
+
});
|
|
1695
|
+
}
|
|
1696
|
+
return options;
|
|
1697
|
+
})
|
|
1698
|
+
.catch(() => {
|
|
1699
|
+
// 发生错误时返回空数组
|
|
1700
|
+
return [];
|
|
1701
|
+
});
|
|
1702
|
+
}
|
|
1703
|
+
}
|
|
1704
|
+
DefaultPlatePrefixLoadService.decorators = [
|
|
1705
|
+
{ type: Injectable }
|
|
1706
|
+
];
|
|
1707
|
+
DefaultPlatePrefixLoadService.ctorParameters = () => [
|
|
1708
|
+
{ type: HttpClient }
|
|
1709
|
+
];
|
|
1710
|
+
|
|
1711
|
+
// ==================== 服务类 ====================
|
|
1712
|
+
class AntdFormService {
|
|
1713
|
+
// ==================== 构造函数 ====================
|
|
1714
|
+
constructor(fb) {
|
|
1715
|
+
this.fb = fb;
|
|
1716
|
+
// ==================== 公共属性 ====================
|
|
1717
|
+
this.formStore = {};
|
|
1718
|
+
this.formModifyType = "create";
|
|
1719
|
+
// ==================== 私有属性 ====================
|
|
1720
|
+
this.labelWidth = "120px";
|
|
1721
|
+
this.labelAlign = "right";
|
|
1722
|
+
this.labelObservers = {};
|
|
1723
|
+
this.errorMessageStore = {};
|
|
1724
|
+
this.formArrayConfigStore = {};
|
|
1725
|
+
this.INTERNAL_ID_FIELD = "__formItemId";
|
|
1726
|
+
this.classPrefix = "ant-form-";
|
|
1727
|
+
this.defaultErrorMessages = {
|
|
1728
|
+
required: "该字段为必填项",
|
|
1729
|
+
minlength: "输入长度不足",
|
|
1730
|
+
maxlength: "输入长度超限",
|
|
1731
|
+
email: "请输入合法的邮箱地址",
|
|
1732
|
+
pattern: "输入格式不正确",
|
|
1733
|
+
};
|
|
1734
|
+
}
|
|
1735
|
+
// ==================== 表单创建和初始化 ====================
|
|
1736
|
+
// 初始化表单(支持 FormArray)
|
|
1737
|
+
createFormGroup(name, config, options) {
|
|
1738
|
+
const groupConfig = {};
|
|
1739
|
+
this.errorMessageStore[name] = {};
|
|
1740
|
+
Object.entries(config).forEach(([key, field]) => {
|
|
1741
|
+
var _a, _b, _c;
|
|
1742
|
+
if (this.isFormArrayConfig(field)) {
|
|
1743
|
+
// FormArray 配置处理
|
|
1744
|
+
if (!this.formArrayConfigStore[name]) {
|
|
1745
|
+
this.formArrayConfigStore[name] = {};
|
|
1746
|
+
}
|
|
1747
|
+
this.formArrayConfigStore[name][key] = {
|
|
1748
|
+
itemConfig: field.itemConfig,
|
|
1749
|
+
uniqueIdField: field.uniqueIdField,
|
|
1750
|
+
};
|
|
1751
|
+
const formArray = this.createFormArrayFromConfig(name, key, field.itemConfig, field.initialItems || [], field.uniqueIdField);
|
|
1752
|
+
groupConfig[key] = formArray;
|
|
1753
|
+
// 存储 FormArray 字段的错误消息配置,格式:arrayName[].fieldName
|
|
1754
|
+
if (field.errorMessages) {
|
|
1755
|
+
Object.entries(field.errorMessages).forEach(([fieldName, errorMessages]) => {
|
|
1756
|
+
const errorMessageKey = `${key}[].${fieldName}`;
|
|
1757
|
+
this.errorMessageStore[name][errorMessageKey] = errorMessages;
|
|
1758
|
+
});
|
|
1759
|
+
}
|
|
1760
|
+
}
|
|
1761
|
+
else {
|
|
1762
|
+
// 普通字段配置
|
|
1763
|
+
const fieldConfig = field;
|
|
1764
|
+
groupConfig[key] = [
|
|
1765
|
+
{ value: fieldConfig.value, disabled: (_a = fieldConfig.disabled) !== null && _a !== void 0 ? _a : false },
|
|
1766
|
+
(_c = (_b = fieldConfig.validators) === null || _b === void 0 ? void 0 : _b.call(fieldConfig)) !== null && _c !== void 0 ? _c : [],
|
|
1767
|
+
];
|
|
1768
|
+
if (fieldConfig.errorMessages) {
|
|
1769
|
+
this.errorMessageStore[name][key] = fieldConfig.errorMessages;
|
|
1770
|
+
}
|
|
1771
|
+
}
|
|
1772
|
+
});
|
|
1773
|
+
if (options === null || options === void 0 ? void 0 : options.labelWidth) {
|
|
1774
|
+
this.labelWidth = options.labelWidth;
|
|
1775
|
+
}
|
|
1776
|
+
if (options === null || options === void 0 ? void 0 : options.labelAlign) {
|
|
1777
|
+
this.labelAlign = options.labelAlign;
|
|
1778
|
+
}
|
|
1779
|
+
this.formStore[name] = this.fb.group(groupConfig);
|
|
1780
|
+
this.setCSSVariablesToTarget(name);
|
|
1781
|
+
return this.formStore[name];
|
|
1782
|
+
}
|
|
1783
|
+
// ==================== 表单操作 ====================
|
|
1784
|
+
// 重置表单
|
|
1785
|
+
resetFormGroup(name, value) {
|
|
1786
|
+
var _a;
|
|
1787
|
+
(_a = this.formStore[name]) === null || _a === void 0 ? void 0 : _a.reset(value);
|
|
1788
|
+
}
|
|
1789
|
+
// 批量添加字段配置
|
|
1790
|
+
addFieldsConfig(formName, fieldsConfig, options) {
|
|
1791
|
+
var _a;
|
|
1792
|
+
const result = {
|
|
1793
|
+
success: true,
|
|
1794
|
+
added: [],
|
|
1795
|
+
failed: [],
|
|
1796
|
+
};
|
|
1797
|
+
// 1. 验证表单是否存在
|
|
1798
|
+
const formGroup = this.formStore[formName];
|
|
1799
|
+
if (!formGroup) {
|
|
1800
|
+
// 如果表单不存在,所有字段都失败
|
|
1801
|
+
Object.keys(fieldsConfig).forEach((fieldName) => {
|
|
1802
|
+
var _a;
|
|
1803
|
+
const error = `Form "${formName}" not found`;
|
|
1804
|
+
result.failed.push({
|
|
1805
|
+
fieldName,
|
|
1806
|
+
error,
|
|
1807
|
+
});
|
|
1808
|
+
(_a = options === null || options === void 0 ? void 0 : options.onFieldAdded) === null || _a === void 0 ? void 0 : _a.call(options, fieldName, false, error);
|
|
1809
|
+
});
|
|
1810
|
+
result.success = false;
|
|
1811
|
+
return result;
|
|
1812
|
+
}
|
|
1813
|
+
// 2. 初始化 errorMessageStore 和 formArrayConfigStore(如果不存在)
|
|
1814
|
+
if (!this.errorMessageStore[formName]) {
|
|
1815
|
+
this.errorMessageStore[formName] = {};
|
|
1816
|
+
}
|
|
1817
|
+
if (!this.formArrayConfigStore[formName]) {
|
|
1818
|
+
this.formArrayConfigStore[formName] = {};
|
|
1819
|
+
}
|
|
1820
|
+
// 3. 批量构建控件配置
|
|
1821
|
+
const controlsToAdd = {};
|
|
1822
|
+
const errorMessagesToAdd = {};
|
|
1823
|
+
const formArrayConfigsToAdd = {};
|
|
1824
|
+
// 4. 遍历所有字段配置,进行验证和构建
|
|
1825
|
+
Object.entries(fieldsConfig).forEach(([fieldName, fieldConfig]) => {
|
|
1826
|
+
var _a, _b, _c, _d, _e;
|
|
1827
|
+
try {
|
|
1828
|
+
// 4.1 检查字段是否已存在
|
|
1829
|
+
if (formGroup.get(fieldName)) {
|
|
1830
|
+
const error = `Field "${fieldName}" already exists`;
|
|
1831
|
+
result.failed.push({
|
|
1832
|
+
fieldName,
|
|
1833
|
+
error,
|
|
1834
|
+
});
|
|
1835
|
+
(_a = options === null || options === void 0 ? void 0 : options.onFieldAdded) === null || _a === void 0 ? void 0 : _a.call(options, fieldName, false, error);
|
|
1836
|
+
return;
|
|
1837
|
+
}
|
|
1838
|
+
// 4.2 根据字段类型创建控件
|
|
1839
|
+
if (this.isFormArrayConfig(fieldConfig)) {
|
|
1840
|
+
// FormArray 处理
|
|
1841
|
+
const formArray = this.createFormArrayFromConfig(formName, fieldName, fieldConfig.itemConfig, fieldConfig.initialItems || [], fieldConfig.uniqueIdField);
|
|
1842
|
+
controlsToAdd[fieldName] = formArray;
|
|
1843
|
+
// 存储 FormArray 配置
|
|
1844
|
+
formArrayConfigsToAdd[fieldName] = {
|
|
1845
|
+
itemConfig: fieldConfig.itemConfig,
|
|
1846
|
+
uniqueIdField: fieldConfig.uniqueIdField,
|
|
1847
|
+
};
|
|
1848
|
+
// 存储错误消息
|
|
1849
|
+
if (fieldConfig.errorMessages) {
|
|
1850
|
+
Object.entries(fieldConfig.errorMessages).forEach(([itemFieldName, errorMessages]) => {
|
|
1851
|
+
const errorMessageKey = `${fieldName}[].${itemFieldName}`;
|
|
1852
|
+
errorMessagesToAdd[errorMessageKey] = errorMessages;
|
|
1853
|
+
});
|
|
1854
|
+
}
|
|
1855
|
+
}
|
|
1856
|
+
else {
|
|
1857
|
+
// 普通字段处理
|
|
1858
|
+
const fieldConfigTyped = fieldConfig;
|
|
1859
|
+
const controlOptions = {
|
|
1860
|
+
validators: (_c = (_b = fieldConfigTyped.validators) === null || _b === void 0 ? void 0 : _b.call(fieldConfigTyped)) !== null && _c !== void 0 ? _c : [],
|
|
1861
|
+
};
|
|
1862
|
+
const control = this.fb.control(fieldConfigTyped.value, controlOptions);
|
|
1863
|
+
// 设置 disabled 状态
|
|
1864
|
+
if (fieldConfigTyped.disabled) {
|
|
1865
|
+
control.disable();
|
|
1866
|
+
}
|
|
1867
|
+
controlsToAdd[fieldName] = control;
|
|
1868
|
+
// 存储错误消息
|
|
1869
|
+
if (fieldConfigTyped.errorMessages) {
|
|
1870
|
+
errorMessagesToAdd[fieldName] = fieldConfigTyped.errorMessages;
|
|
1871
|
+
}
|
|
1872
|
+
}
|
|
1873
|
+
result.added.push(fieldName);
|
|
1874
|
+
(_d = options === null || options === void 0 ? void 0 : options.onFieldAdded) === null || _d === void 0 ? void 0 : _d.call(options, fieldName, true);
|
|
1875
|
+
}
|
|
1876
|
+
catch (error) {
|
|
1877
|
+
const errorMessage = (error === null || error === void 0 ? void 0 : error.message) || (error === null || error === void 0 ? void 0 : error.toString()) || "Unknown error";
|
|
1878
|
+
result.failed.push({
|
|
1879
|
+
fieldName,
|
|
1880
|
+
error: errorMessage,
|
|
1881
|
+
});
|
|
1882
|
+
(_e = options === null || options === void 0 ? void 0 : options.onFieldAdded) === null || _e === void 0 ? void 0 : _e.call(options, fieldName, false, errorMessage);
|
|
1883
|
+
}
|
|
1884
|
+
});
|
|
1885
|
+
// 5. 批量添加到 FormGroup
|
|
1886
|
+
if (Object.keys(controlsToAdd).length > 0) {
|
|
1887
|
+
Object.entries(controlsToAdd).forEach(([fieldName, control]) => {
|
|
1888
|
+
formGroup.addControl(fieldName, control);
|
|
1889
|
+
});
|
|
1890
|
+
// 6. 批量存储错误消息
|
|
1891
|
+
Object.entries(errorMessagesToAdd).forEach(([key, messages]) => {
|
|
1892
|
+
this.errorMessageStore[formName][key] = messages;
|
|
1893
|
+
});
|
|
1894
|
+
// 7. 批量存储 FormArray 配置
|
|
1895
|
+
Object.entries(formArrayConfigsToAdd).forEach(([fieldName, config]) => {
|
|
1896
|
+
this.formArrayConfigStore[formName][fieldName] = config;
|
|
1897
|
+
});
|
|
1898
|
+
// 8. 更新表单验证状态
|
|
1899
|
+
if (options === null || options === void 0 ? void 0 : options.updateValueAndValidity) {
|
|
1900
|
+
formGroup.updateValueAndValidity({
|
|
1901
|
+
emitEvent: (_a = options === null || options === void 0 ? void 0 : options.emitEvent) !== null && _a !== void 0 ? _a : true,
|
|
1902
|
+
});
|
|
1903
|
+
}
|
|
1904
|
+
}
|
|
1905
|
+
// 9. 判断整体是否成功
|
|
1906
|
+
result.success = result.failed.length === 0;
|
|
1907
|
+
return result;
|
|
1908
|
+
}
|
|
1909
|
+
// 批量删除字段配置
|
|
1910
|
+
removeFieldsConfig(formName, fieldNames, options) {
|
|
1911
|
+
const result = {
|
|
1912
|
+
success: true,
|
|
1913
|
+
removed: [],
|
|
1914
|
+
failed: [],
|
|
1915
|
+
};
|
|
1916
|
+
// 1. 验证表单是否存在
|
|
1917
|
+
const formGroup = this.formStore[formName];
|
|
1918
|
+
if (!formGroup) {
|
|
1919
|
+
fieldNames.forEach((fieldName) => {
|
|
1920
|
+
var _a;
|
|
1921
|
+
const error = `Form "${formName}" not found`;
|
|
1922
|
+
result.failed.push({
|
|
1923
|
+
fieldName,
|
|
1924
|
+
error,
|
|
1925
|
+
});
|
|
1926
|
+
(_a = options === null || options === void 0 ? void 0 : options.onFieldRemoved) === null || _a === void 0 ? void 0 : _a.call(options, fieldName, false, error);
|
|
1927
|
+
});
|
|
1928
|
+
result.success = false;
|
|
1929
|
+
return result;
|
|
1930
|
+
}
|
|
1931
|
+
// 2. 批量收集需要清理的信息
|
|
1932
|
+
const fieldsToRemove = [];
|
|
1933
|
+
const errorMessageKeysToRemove = [];
|
|
1934
|
+
const formArrayFields = [];
|
|
1935
|
+
// 3. 验证每个字段并收集信息
|
|
1936
|
+
fieldNames.forEach((fieldName) => {
|
|
1937
|
+
var _a;
|
|
1938
|
+
const control = formGroup.get(fieldName);
|
|
1939
|
+
if (!control) {
|
|
1940
|
+
const error = `Field "${fieldName}" not found`;
|
|
1941
|
+
result.failed.push({
|
|
1942
|
+
fieldName,
|
|
1943
|
+
error,
|
|
1944
|
+
});
|
|
1945
|
+
(_a = options === null || options === void 0 ? void 0 : options.onFieldRemoved) === null || _a === void 0 ? void 0 : _a.call(options, fieldName, false, error);
|
|
1946
|
+
return;
|
|
1947
|
+
}
|
|
1948
|
+
// 判断是否是 FormArray
|
|
1949
|
+
if (control instanceof FormArray) {
|
|
1950
|
+
formArrayFields.push(fieldName);
|
|
1951
|
+
// 收集 FormArray 相关的错误消息键(格式:arrayName[].fieldName)
|
|
1952
|
+
if (this.errorMessageStore[formName]) {
|
|
1953
|
+
Object.keys(this.errorMessageStore[formName]).forEach((key) => {
|
|
1954
|
+
if (key.startsWith(`${fieldName}[].`)) {
|
|
1955
|
+
errorMessageKeysToRemove.push(key);
|
|
1956
|
+
}
|
|
1957
|
+
});
|
|
1958
|
+
}
|
|
1959
|
+
}
|
|
1960
|
+
else {
|
|
1961
|
+
// 普通字段的错误消息键
|
|
1962
|
+
errorMessageKeysToRemove.push(fieldName);
|
|
1963
|
+
}
|
|
1964
|
+
fieldsToRemove.push(fieldName);
|
|
1965
|
+
});
|
|
1966
|
+
// 4. 批量执行删除操作
|
|
1967
|
+
try {
|
|
1968
|
+
// 4.1 从 FormGroup 中移除控件
|
|
1969
|
+
fieldsToRemove.forEach((fieldName) => {
|
|
1970
|
+
var _a;
|
|
1971
|
+
formGroup.removeControl(fieldName);
|
|
1972
|
+
result.removed.push(fieldName);
|
|
1973
|
+
(_a = options === null || options === void 0 ? void 0 : options.onFieldRemoved) === null || _a === void 0 ? void 0 : _a.call(options, fieldName, true);
|
|
1974
|
+
});
|
|
1975
|
+
// 4.2 批量删除错误消息
|
|
1976
|
+
if (this.errorMessageStore[formName]) {
|
|
1977
|
+
errorMessageKeysToRemove.forEach((key) => {
|
|
1978
|
+
delete this.errorMessageStore[formName][key];
|
|
1979
|
+
});
|
|
1980
|
+
}
|
|
1981
|
+
// 4.3 批量删除 FormArray 配置
|
|
1982
|
+
if (this.formArrayConfigStore[formName]) {
|
|
1983
|
+
formArrayFields.forEach((fieldName) => {
|
|
1984
|
+
delete this.formArrayConfigStore[formName][fieldName];
|
|
1985
|
+
});
|
|
1986
|
+
}
|
|
1987
|
+
}
|
|
1988
|
+
catch (error) {
|
|
1989
|
+
// 如果批量删除过程中出错,标记为失败
|
|
1990
|
+
fieldsToRemove.forEach((fieldName) => {
|
|
1991
|
+
var _a;
|
|
1992
|
+
if (!result.removed.includes(fieldName)) {
|
|
1993
|
+
const errorMessage = (error === null || error === void 0 ? void 0 : error.message) || (error === null || error === void 0 ? void 0 : error.toString()) || "Failed to remove field";
|
|
1994
|
+
result.failed.push({
|
|
1995
|
+
fieldName,
|
|
1996
|
+
error: errorMessage,
|
|
1997
|
+
});
|
|
1998
|
+
(_a = options === null || options === void 0 ? void 0 : options.onFieldRemoved) === null || _a === void 0 ? void 0 : _a.call(options, fieldName, false, errorMessage);
|
|
1999
|
+
}
|
|
2000
|
+
});
|
|
2001
|
+
}
|
|
2002
|
+
// 5. 判断整体是否成功
|
|
2003
|
+
result.success = result.failed.length === 0;
|
|
2004
|
+
return result;
|
|
2005
|
+
}
|
|
2006
|
+
// 局部赋值(支持 FormArray 的智能更新,统一根据 action 字段判断操作类型)
|
|
2007
|
+
patchFormValues(name, values, options) {
|
|
2008
|
+
var _a;
|
|
2009
|
+
const formGroup = this.formStore[name];
|
|
2010
|
+
if (!formGroup) {
|
|
2011
|
+
console.warn(`[AntdFormService] patchFormValues: form "${name}" not found.`);
|
|
2012
|
+
return;
|
|
2013
|
+
}
|
|
2014
|
+
const processedValues = {};
|
|
2015
|
+
Object.entries(values).forEach(([key, value]) => {
|
|
2016
|
+
const control = formGroup.get(key);
|
|
2017
|
+
// 检测是否是 FormArray
|
|
2018
|
+
if (control instanceof FormArray && Array.isArray(value)) {
|
|
2019
|
+
this.patchFormArray(name, key, value);
|
|
2020
|
+
return;
|
|
2021
|
+
}
|
|
2022
|
+
// 普通字段,直接加入
|
|
2023
|
+
processedValues[key] = value;
|
|
2024
|
+
});
|
|
2025
|
+
// 处理普通字段
|
|
2026
|
+
if (Object.keys(processedValues).length > 0) {
|
|
2027
|
+
formGroup.patchValue(processedValues, {
|
|
2028
|
+
emitEvent: (_a = options === null || options === void 0 ? void 0 : options.emitEvent) !== null && _a !== void 0 ? _a : true,
|
|
2029
|
+
});
|
|
2030
|
+
}
|
|
2031
|
+
}
|
|
2032
|
+
// 表单校验(自动过滤内部字段)
|
|
2033
|
+
validateForm(name, options) {
|
|
2034
|
+
var _a, _b;
|
|
2035
|
+
if (this.formStore[name].valid) {
|
|
2036
|
+
const rawValue = this.formStore[name].getRawValue();
|
|
2037
|
+
return this.excludeInternalFields(rawValue);
|
|
2038
|
+
}
|
|
2039
|
+
else {
|
|
2040
|
+
// 递归校验所有控件,包括 FormArray 中的项
|
|
2041
|
+
this.markAllControlsAsDirty(this.formStore[name], (_a = options === null || options === void 0 ? void 0 : options.emitEvent) !== null && _a !== void 0 ? _a : true, (_b = options === null || options === void 0 ? void 0 : options.onlySelf) !== null && _b !== void 0 ? _b : false);
|
|
2042
|
+
return false;
|
|
2043
|
+
}
|
|
2044
|
+
}
|
|
2045
|
+
// 递归标记所有无效控件为 dirty(包括 FormArray 中的项)
|
|
2046
|
+
markAllControlsAsDirty(control, emitEvent, onlySelf) {
|
|
2047
|
+
if (control.invalid) {
|
|
2048
|
+
control.markAsDirty();
|
|
2049
|
+
control.updateValueAndValidity({
|
|
2050
|
+
emitEvent,
|
|
2051
|
+
onlySelf,
|
|
2052
|
+
});
|
|
2053
|
+
}
|
|
2054
|
+
// 如果是 FormGroup,递归处理所有子控件
|
|
2055
|
+
if (control instanceof FormGroup) {
|
|
2056
|
+
Object.values(control.controls).forEach((childControl) => {
|
|
2057
|
+
this.markAllControlsAsDirty(childControl, emitEvent, onlySelf);
|
|
2058
|
+
});
|
|
2059
|
+
}
|
|
2060
|
+
// 如果是 FormArray,递归处理数组中的每一项
|
|
2061
|
+
if (control instanceof FormArray) {
|
|
2062
|
+
control.controls.forEach((childControl) => {
|
|
2063
|
+
this.markAllControlsAsDirty(childControl, emitEvent, onlySelf);
|
|
2064
|
+
});
|
|
2065
|
+
}
|
|
2066
|
+
}
|
|
2067
|
+
// ==================== 错误消息相关 ====================
|
|
2068
|
+
// 获取字段首条错误提示,支持普通字段和 FormArray 字段(格式:arrayName.index.fieldName)
|
|
2069
|
+
getFieldErrorMessage(name, controlName) {
|
|
2070
|
+
var _a;
|
|
2071
|
+
const formGroup = this.formStore[name];
|
|
2072
|
+
if (!formGroup) {
|
|
2073
|
+
console.warn(`[AntdFormService] getFieldErrorMessage: form "${name}" not found.`);
|
|
2074
|
+
return "";
|
|
2075
|
+
}
|
|
2076
|
+
const control = formGroup.get(controlName);
|
|
2077
|
+
if (!control) {
|
|
2078
|
+
console.warn(`[AntdFormService] getFieldErrorMessage: control "${controlName}" not found in form "${name}".`);
|
|
2079
|
+
return "";
|
|
2080
|
+
}
|
|
2081
|
+
if (!control.errors) {
|
|
2082
|
+
return "";
|
|
2083
|
+
}
|
|
2084
|
+
// 解析 controlName,支持 FormArray 格式:arrayName.index.fieldName
|
|
2085
|
+
let errorMessageKey = controlName;
|
|
2086
|
+
const arrayMatch = controlName.match(/^(.+)\.(\d+)\.(.+)$/);
|
|
2087
|
+
if (arrayMatch) {
|
|
2088
|
+
// FormArray 格式:arrayName.index.fieldName -> 使用 arrayName[].fieldName 作为 key
|
|
2089
|
+
const [, arrayName, , fieldName] = arrayMatch;
|
|
2090
|
+
errorMessageKey = `${arrayName}[].${fieldName}`;
|
|
2091
|
+
}
|
|
2092
|
+
// 从 errorMessageStore 获取错误消息配置
|
|
2093
|
+
const errorMessages = (_a = this.errorMessageStore[name]) === null || _a === void 0 ? void 0 : _a[errorMessageKey];
|
|
2094
|
+
const mergedMessages = Object.assign(Object.assign({}, this.defaultErrorMessages), (errorMessages !== null && errorMessages !== void 0 ? errorMessages : {}));
|
|
2095
|
+
for (const errorKey of Object.keys(control.errors)) {
|
|
2096
|
+
const message = mergedMessages[errorKey];
|
|
2097
|
+
if (message) {
|
|
2098
|
+
// 不再支持函数形式,只返回字符串
|
|
2099
|
+
return typeof message === "string" ? message : "";
|
|
2100
|
+
}
|
|
2101
|
+
}
|
|
2102
|
+
return "";
|
|
2103
|
+
}
|
|
2104
|
+
// ==================== 监听相关 ====================
|
|
2105
|
+
// 监听表单所有字段变更
|
|
2106
|
+
watchFormChanges(name, handler, options) {
|
|
2107
|
+
const formGroup = this.formStore[name];
|
|
2108
|
+
if (!formGroup) {
|
|
2109
|
+
console.warn(`[AntdFormService] watchFormChanges: form "${name}" not found.`);
|
|
2110
|
+
return undefined;
|
|
2111
|
+
}
|
|
2112
|
+
return this.setupValueChangeSubscription(formGroup, handler, options);
|
|
2113
|
+
}
|
|
2114
|
+
// 监听指定字段变更
|
|
2115
|
+
watchFieldChanges(name, controlName, handler, options) {
|
|
2116
|
+
const formGroup = this.formStore[name];
|
|
2117
|
+
if (!formGroup) {
|
|
2118
|
+
console.warn(`[AntdFormService] watchFieldChanges: form "${name}" not found.`);
|
|
2119
|
+
return undefined;
|
|
2120
|
+
}
|
|
2121
|
+
const control = formGroup.get(controlName);
|
|
2122
|
+
if (!control) {
|
|
2123
|
+
console.warn(`[AntdFormService] watchFieldChanges: control "${controlName}" not found in form "${name}".`);
|
|
2124
|
+
return undefined;
|
|
2125
|
+
}
|
|
2126
|
+
return this.setupValueChangeSubscription(control, handler, options);
|
|
2127
|
+
}
|
|
2128
|
+
// ==================== 工具方法 ====================
|
|
2129
|
+
// 获取表单类名
|
|
2130
|
+
getFormClassName(name) {
|
|
2131
|
+
return `${this.classPrefix}${name}`;
|
|
2132
|
+
}
|
|
2133
|
+
// 设置 CSS 变量到目标元素(支持持久化监听动态添加的元素)
|
|
2134
|
+
setCSSVariablesToTarget(name) {
|
|
2135
|
+
const selector = `.${this.getFormClassName(name)} .ant-form-item-label`;
|
|
2136
|
+
const formContainerSelector = `.${this.getFormClassName(name)}`;
|
|
2137
|
+
const applyStyles = () => {
|
|
2138
|
+
const dom = document.querySelectorAll(selector);
|
|
2139
|
+
if (!dom.length) {
|
|
2140
|
+
return false;
|
|
2141
|
+
}
|
|
2142
|
+
let appliedCount = 0;
|
|
2143
|
+
dom.forEach((item) => {
|
|
2144
|
+
const target = item;
|
|
2145
|
+
if (target.style.width !== this.labelWidth ||
|
|
2146
|
+
target.style.textAlign !== this.labelAlign) {
|
|
2147
|
+
target.style.width = this.labelWidth;
|
|
2148
|
+
target.style.textAlign = this.labelAlign;
|
|
2149
|
+
appliedCount++;
|
|
2150
|
+
}
|
|
2151
|
+
});
|
|
2152
|
+
return appliedCount > 0;
|
|
2153
|
+
};
|
|
2154
|
+
if (this.labelObservers[name]) {
|
|
2155
|
+
return;
|
|
2156
|
+
}
|
|
2157
|
+
let timeout = null;
|
|
2158
|
+
const observer = new MutationObserver(() => {
|
|
2159
|
+
cancelAnimationFrame(timeout);
|
|
2160
|
+
timeout = requestAnimationFrame(() => {
|
|
2161
|
+
setTimeout(() => {
|
|
2162
|
+
applyStyles();
|
|
2163
|
+
}, 0);
|
|
2164
|
+
});
|
|
2165
|
+
});
|
|
2166
|
+
const formContainer = document.querySelector(formContainerSelector);
|
|
2167
|
+
observer.observe(formContainer || document.body, {
|
|
2168
|
+
childList: true,
|
|
2169
|
+
subtree: true,
|
|
2170
|
+
attributes: true,
|
|
2171
|
+
});
|
|
2172
|
+
this.labelObservers[name] = observer;
|
|
2173
|
+
}
|
|
2174
|
+
// ==================== 私有方法 ====================
|
|
2175
|
+
// 获取 FormArray
|
|
2176
|
+
getFormArray(formName, arrayName) {
|
|
2177
|
+
const formGroup = this.formStore[formName];
|
|
2178
|
+
if (!formGroup) {
|
|
2179
|
+
console.warn(`[AntdFormService] getFormArray: form "${formName}" not found.`);
|
|
2180
|
+
return null;
|
|
2181
|
+
}
|
|
2182
|
+
const control = formGroup.get(arrayName);
|
|
2183
|
+
if (!control || !(control instanceof FormArray)) {
|
|
2184
|
+
console.warn(`[AntdFormService] getFormArray: array "${arrayName}" not found in form "${formName}".`);
|
|
2185
|
+
return null;
|
|
2186
|
+
}
|
|
2187
|
+
return control;
|
|
2188
|
+
}
|
|
2189
|
+
// 判断是否是 FormArray 配置
|
|
2190
|
+
isFormArrayConfig(field) {
|
|
2191
|
+
return field.type === "array";
|
|
2192
|
+
}
|
|
2193
|
+
// 从配置创建 FormArray
|
|
2194
|
+
createFormArrayFromConfig(formName, arrayName, itemConfig, initialItems, uniqueIdField) {
|
|
2195
|
+
const formArray = this.fb.array([]);
|
|
2196
|
+
initialItems.forEach((item) => {
|
|
2197
|
+
const itemGroup = this.createItemFormGroup(itemConfig, item, uniqueIdField);
|
|
2198
|
+
formArray.push(itemGroup);
|
|
2199
|
+
});
|
|
2200
|
+
return formArray;
|
|
2201
|
+
}
|
|
2202
|
+
// 生成内部ID(使用业务唯一字段或生成临时ID)
|
|
2203
|
+
generateInternalId(itemData, uniqueIdField) {
|
|
2204
|
+
// 优先使用业务唯一字段
|
|
2205
|
+
if (uniqueIdField && (itemData === null || itemData === void 0 ? void 0 : itemData[uniqueIdField]) !== undefined) {
|
|
2206
|
+
const businessId = itemData[uniqueIdField];
|
|
2207
|
+
if (businessId !== null &&
|
|
2208
|
+
businessId !== undefined &&
|
|
2209
|
+
businessId !== "") {
|
|
2210
|
+
return `business-${uniqueIdField}-${businessId}`;
|
|
2211
|
+
}
|
|
2212
|
+
}
|
|
2213
|
+
// 如果没有业务ID,生成临时ID(用于新添加的项)
|
|
2214
|
+
return `temp-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
2215
|
+
}
|
|
2216
|
+
// 创建单个项的 FormGroup
|
|
2217
|
+
createItemFormGroup(itemConfig, itemData, uniqueIdField) {
|
|
2218
|
+
const groupConfig = {};
|
|
2219
|
+
// 添加内部ID字段
|
|
2220
|
+
const itemId = this.generateInternalId(itemData, uniqueIdField);
|
|
2221
|
+
groupConfig[this.INTERNAL_ID_FIELD] = [
|
|
2222
|
+
{ value: itemId, disabled: true },
|
|
2223
|
+
[],
|
|
2224
|
+
];
|
|
2225
|
+
// 添加业务字段
|
|
2226
|
+
Object.entries(itemConfig).forEach(([key, field]) => {
|
|
2227
|
+
var _a, _b, _c;
|
|
2228
|
+
// itemConfig 中的字段应该是 FieldConfig,不应该包含 FormArrayConfig
|
|
2229
|
+
if (this.isFormArrayConfig(field)) {
|
|
2230
|
+
console.warn(`[AntdFormService] createItemFormGroup: FormArrayConfig is not allowed in itemConfig. Skipping field "${key}".`);
|
|
2231
|
+
return;
|
|
2232
|
+
}
|
|
2233
|
+
const fieldConfig = field;
|
|
2234
|
+
const value = (itemData === null || itemData === void 0 ? void 0 : itemData[key]) !== undefined ? itemData[key] : fieldConfig.value;
|
|
2235
|
+
groupConfig[key] = [
|
|
2236
|
+
{ value: value, disabled: (_a = fieldConfig.disabled) !== null && _a !== void 0 ? _a : false },
|
|
2237
|
+
(_c = (_b = fieldConfig.validators) === null || _b === void 0 ? void 0 : _b.call(fieldConfig)) !== null && _c !== void 0 ? _c : [],
|
|
2238
|
+
];
|
|
2239
|
+
});
|
|
2240
|
+
return this.fb.group(groupConfig);
|
|
2241
|
+
}
|
|
2242
|
+
// 通过业务唯一字段查找内部ID
|
|
2243
|
+
findFormArrayItemIdByBusinessField(formName, arrayName, uniqueIdField, businessIdValue) {
|
|
2244
|
+
const formArray = this.getFormArray(formName, arrayName);
|
|
2245
|
+
if (!formArray)
|
|
2246
|
+
return null;
|
|
2247
|
+
for (let i = 0; i < formArray.length; i++) {
|
|
2248
|
+
const item = formArray.at(i);
|
|
2249
|
+
const itemValue = item.getRawValue();
|
|
2250
|
+
const internalId = itemValue[this.INTERNAL_ID_FIELD];
|
|
2251
|
+
// 检查内部ID是否匹配业务ID
|
|
2252
|
+
if (internalId && internalId.startsWith(`business-${uniqueIdField}-`)) {
|
|
2253
|
+
const idInInternalId = internalId.replace(`business-${uniqueIdField}-`, "");
|
|
2254
|
+
if (String(idInInternalId) === String(businessIdValue)) {
|
|
2255
|
+
return internalId;
|
|
2256
|
+
}
|
|
2257
|
+
}
|
|
2258
|
+
// 也检查当前业务字段值是否匹配(处理业务ID更新的情况)
|
|
2259
|
+
if (itemValue[uniqueIdField] === businessIdValue) {
|
|
2260
|
+
return internalId;
|
|
2261
|
+
}
|
|
2262
|
+
}
|
|
2263
|
+
return null;
|
|
2264
|
+
}
|
|
2265
|
+
// 通过内部ID查找项
|
|
2266
|
+
findFormArrayItemById(formName, arrayName, itemId) {
|
|
2267
|
+
var _a;
|
|
2268
|
+
const formArray = this.getFormArray(formName, arrayName);
|
|
2269
|
+
if (!formArray)
|
|
2270
|
+
return null;
|
|
2271
|
+
for (let i = 0; i < formArray.length; i++) {
|
|
2272
|
+
const item = formArray.at(i);
|
|
2273
|
+
const id = (_a = item.get(this.INTERNAL_ID_FIELD)) === null || _a === void 0 ? void 0 : _a.value;
|
|
2274
|
+
if (id === itemId) {
|
|
2275
|
+
return { index: i, formGroup: item };
|
|
2276
|
+
}
|
|
2277
|
+
}
|
|
2278
|
+
return null;
|
|
2279
|
+
}
|
|
2280
|
+
// 获取操作类型(必须明确指定 action 字段)
|
|
2281
|
+
getOperationType(itemData) {
|
|
2282
|
+
if (!itemData || typeof itemData !== "object")
|
|
2283
|
+
return null;
|
|
2284
|
+
const action = itemData.action;
|
|
2285
|
+
if (action === "delete" || action === "update" || action === "create") {
|
|
2286
|
+
return action;
|
|
2287
|
+
}
|
|
2288
|
+
return null;
|
|
2289
|
+
}
|
|
2290
|
+
// 过滤操作字段(action 字段不保存到表单中)
|
|
2291
|
+
filterOperationFields(itemData) {
|
|
2292
|
+
if (!itemData || typeof itemData !== "object")
|
|
2293
|
+
return itemData;
|
|
2294
|
+
const filtered = {};
|
|
2295
|
+
Object.entries(itemData).forEach(([key, value]) => {
|
|
2296
|
+
if (key !== "action") {
|
|
2297
|
+
filtered[key] = value;
|
|
2298
|
+
}
|
|
2299
|
+
});
|
|
2300
|
+
return filtered;
|
|
2301
|
+
}
|
|
2302
|
+
// 处理 FormArray 的更新(统一根据 action 字段判断操作类型)
|
|
2303
|
+
patchFormArray(formName, arrayName, newValues) {
|
|
2304
|
+
var _a;
|
|
2305
|
+
const formArray = this.getFormArray(formName, arrayName);
|
|
2306
|
+
if (!formArray) {
|
|
2307
|
+
console.warn(`[AntdFormService] patchFormArray: array "${arrayName}" not found in form "${formName}".`);
|
|
2308
|
+
return;
|
|
2309
|
+
}
|
|
2310
|
+
const config = (_a = this.formArrayConfigStore[formName]) === null || _a === void 0 ? void 0 : _a[arrayName];
|
|
2311
|
+
if (!config) {
|
|
2312
|
+
console.warn(`[AntdFormService] patchFormArray: config not found for array "${arrayName}" in form "${formName}".`);
|
|
2313
|
+
return;
|
|
2314
|
+
}
|
|
2315
|
+
const { itemConfig, uniqueIdField } = config;
|
|
2316
|
+
// 统一根据 action 字段判断操作类型
|
|
2317
|
+
const itemsToDelete = new Set();
|
|
2318
|
+
const itemsToUpdate = new Map();
|
|
2319
|
+
const itemsToAdd = [];
|
|
2320
|
+
newValues.forEach((itemData) => {
|
|
2321
|
+
if (!itemData || typeof itemData !== "object")
|
|
2322
|
+
return;
|
|
2323
|
+
const operationType = this.getOperationType(itemData);
|
|
2324
|
+
if (!operationType) {
|
|
2325
|
+
console.warn(`[AntdFormService] patchFormArray: Item missing required "action" field. Skipping.`, itemData);
|
|
2326
|
+
return;
|
|
2327
|
+
}
|
|
2328
|
+
// 删除操作
|
|
2329
|
+
if (operationType === "delete") {
|
|
2330
|
+
if (uniqueIdField && itemData[uniqueIdField] !== undefined) {
|
|
2331
|
+
const businessId = itemData[uniqueIdField];
|
|
2332
|
+
const internalId = this.findFormArrayItemIdByBusinessField(formName, arrayName, uniqueIdField, businessId);
|
|
2333
|
+
if (internalId) {
|
|
2334
|
+
itemsToDelete.add(internalId);
|
|
2335
|
+
}
|
|
2336
|
+
else {
|
|
2337
|
+
console.warn(`[AntdFormService] patchFormArray: Cannot delete item with ${uniqueIdField}=${businessId}, item not found.`);
|
|
2338
|
+
}
|
|
2339
|
+
}
|
|
2340
|
+
else {
|
|
2341
|
+
console.warn(`[AntdFormService] patchFormArray: Cannot delete item, missing required uniqueIdField "${uniqueIdField}".`);
|
|
2342
|
+
}
|
|
2343
|
+
return;
|
|
2344
|
+
}
|
|
2345
|
+
// 更新操作
|
|
2346
|
+
if (operationType === "update") {
|
|
2347
|
+
if (uniqueIdField && itemData[uniqueIdField] !== undefined) {
|
|
2348
|
+
const businessId = itemData[uniqueIdField];
|
|
2349
|
+
const internalId = this.findFormArrayItemIdByBusinessField(formName, arrayName, uniqueIdField, businessId);
|
|
2350
|
+
if (internalId) {
|
|
2351
|
+
const filteredData = this.filterOperationFields(itemData);
|
|
2352
|
+
itemsToUpdate.set(internalId, filteredData);
|
|
2353
|
+
}
|
|
2354
|
+
else {
|
|
2355
|
+
console.warn(`[AntdFormService] patchFormArray: Cannot update item with ${uniqueIdField}=${businessId}, item not found. Skipping.`);
|
|
2356
|
+
}
|
|
2357
|
+
}
|
|
2358
|
+
else {
|
|
2359
|
+
console.warn(`[AntdFormService] patchFormArray: Cannot update item, missing required uniqueIdField "${uniqueIdField}". Skipping.`);
|
|
2360
|
+
}
|
|
2361
|
+
return;
|
|
2362
|
+
}
|
|
2363
|
+
// 创建操作
|
|
2364
|
+
if (operationType === "create") {
|
|
2365
|
+
const filteredData = this.filterOperationFields(itemData);
|
|
2366
|
+
itemsToAdd.push(filteredData);
|
|
2367
|
+
}
|
|
2368
|
+
});
|
|
2369
|
+
// 执行删除(需要从后往前删除,避免索引变化)
|
|
2370
|
+
const deleteIndices = [];
|
|
2371
|
+
itemsToDelete.forEach((itemId) => {
|
|
2372
|
+
const found = this.findFormArrayItemById(formName, arrayName, itemId);
|
|
2373
|
+
if (found) {
|
|
2374
|
+
deleteIndices.push(found.index);
|
|
2375
|
+
}
|
|
2376
|
+
});
|
|
2377
|
+
deleteIndices
|
|
2378
|
+
.sort((a, b) => b - a)
|
|
2379
|
+
.forEach((index) => {
|
|
2380
|
+
formArray.removeAt(index);
|
|
2381
|
+
});
|
|
2382
|
+
// 执行更新
|
|
2383
|
+
itemsToUpdate.forEach((itemData, itemId) => {
|
|
2384
|
+
const found = this.findFormArrayItemById(formName, arrayName, itemId);
|
|
2385
|
+
if (found) {
|
|
2386
|
+
const _a = itemData, _b = this.INTERNAL_ID_FIELD, _ = _a[_b], dataToUpdate = __rest(_a, [typeof _b === "symbol" ? _b : _b + ""]);
|
|
2387
|
+
found.formGroup.patchValue(dataToUpdate);
|
|
2388
|
+
}
|
|
2389
|
+
});
|
|
2390
|
+
// 执行添加
|
|
2391
|
+
itemsToAdd.forEach((itemData) => {
|
|
2392
|
+
const newItem = this.createItemFormGroup(itemConfig, itemData, uniqueIdField);
|
|
2393
|
+
formArray.push(newItem);
|
|
2394
|
+
});
|
|
2395
|
+
}
|
|
2396
|
+
// 过滤内部字段(递归处理对象和数组)
|
|
2397
|
+
excludeInternalFields(value) {
|
|
2398
|
+
if (value === null || value === undefined) {
|
|
2399
|
+
return value;
|
|
2400
|
+
}
|
|
2401
|
+
if (Array.isArray(value)) {
|
|
2402
|
+
return value.map((item) => this.excludeInternalFields(item));
|
|
2403
|
+
}
|
|
2404
|
+
if (typeof value !== "object") {
|
|
2405
|
+
return value;
|
|
2406
|
+
}
|
|
2407
|
+
const filtered = {};
|
|
2408
|
+
Object.entries(value).forEach(([key, val]) => {
|
|
2409
|
+
// 过滤以 __ 开头的内部字段和 action 字段
|
|
2410
|
+
if (!key.startsWith("__") && key !== "action") {
|
|
2411
|
+
filtered[key] = this.excludeInternalFields(val);
|
|
2412
|
+
}
|
|
2413
|
+
});
|
|
2414
|
+
return filtered;
|
|
2415
|
+
}
|
|
2416
|
+
// 设置值变更订阅
|
|
2417
|
+
setupValueChangeSubscription(target, handler, options) {
|
|
2418
|
+
let valueChanges$ = target.valueChanges;
|
|
2419
|
+
if ((options === null || options === void 0 ? void 0 : options.debounce) != null) {
|
|
2420
|
+
valueChanges$ = valueChanges$.pipe(debounceTime(options.debounce));
|
|
2421
|
+
}
|
|
2422
|
+
if ((options === null || options === void 0 ? void 0 : options.distinctUntilChanged) !== false) {
|
|
2423
|
+
valueChanges$ = valueChanges$.pipe(distinctUntilChanged());
|
|
2424
|
+
}
|
|
2425
|
+
if (options === null || options === void 0 ? void 0 : options.emitInitial) {
|
|
2426
|
+
handler(target.value);
|
|
2427
|
+
}
|
|
2428
|
+
return valueChanges$.subscribe(handler);
|
|
2429
|
+
}
|
|
2430
|
+
}
|
|
2431
|
+
AntdFormService.ɵprov = ɵɵdefineInjectable({ factory: function AntdFormService_Factory() { return new AntdFormService(ɵɵinject(FormBuilder)); }, token: AntdFormService, providedIn: "root" });
|
|
2432
|
+
AntdFormService.decorators = [
|
|
2433
|
+
{ type: Injectable, args: [{ providedIn: "root" },] }
|
|
2434
|
+
];
|
|
2435
|
+
AntdFormService.ctorParameters = () => [
|
|
2436
|
+
{ type: FormBuilder }
|
|
2437
|
+
];
|
|
2438
|
+
|
|
2439
|
+
/*
|
|
2440
|
+
* Public API Surface of pro-table
|
|
2441
|
+
*/
|
|
2442
|
+
|
|
2443
|
+
/**
|
|
2444
|
+
* Generated bundle index. Do not edit.
|
|
2445
|
+
*/
|
|
2446
|
+
|
|
2447
|
+
export { AntdFormService, DefaultPlatePrefixLoadService, PLATE_PREFIX_LOAD_SERVICE, PRO_TABLE_COLUMN_REMOTE, PRO_TABLE_DEFAULT_COLUMN, PRO_TABLE_DEFAULT_PROPS, ProTableComponent, ProTableModule, ɵ0, ɵ1, ɵ2, PageContainerModule as ɵa, PageContainerComponent as ɵb, TableSearchBarModule as ɵc, TableSearchBarComponent as ɵd, PlateInputModule as ɵe, PlateInputComponent as ɵf, ColmunsSettingComponent as ɵg, DynamicSearchFieldComponent as ɵh };
|
|
2448
|
+
//# sourceMappingURL=yibozhang-pro-table.js.map
|