|
|
@@ -149,10 +149,10 @@ export class TabulatorGridComponent implements OnInit, AfterViewInit, OnDestroy
|
|
149
|
149
|
|
|
150
|
150
|
// AJAX 配置
|
|
151
|
151
|
ajaxInitialLoad: true,
|
|
152
|
|
- ajaxContentType: 'json',
|
|
153
|
|
-
|
|
154
|
|
- // 设置为 false,强制 Tabulator 使用 ajaxRequestFunc
|
|
155
|
|
- ajaxURL: '/api',
|
|
|
152
|
+ ajaxContentType: 'json',
|
|
|
153
|
+
|
|
|
154
|
+ // 设置为 false,强制 Tabulator 使用 ajaxRequestFunc
|
|
|
155
|
+ ajaxURL: false,
|
|
156
|
156
|
|
|
157
|
157
|
// 分页显示配置
|
|
158
|
158
|
paginationCounter: 'rows',
|
|
|
@@ -192,7 +192,9 @@ export class TabulatorGridComponent implements OnInit, AfterViewInit, OnDestroy
|
|
192
|
192
|
const componentId = this.containerId; // 用于调试标识
|
|
193
|
193
|
defaultOptions.ajaxParams = function() {
|
|
194
|
194
|
const callTime = new Date().toISOString();
|
|
195
|
|
- console.group(`=== TabulatorGrid[${componentId}] AJAX 参数 ===`);
|
|
|
195
|
+ console.group(`🚨🚨🚨 TabulatorGrid[${componentId}] AJAX 参数函数被调用 🚨🚨🚨`);
|
|
|
196
|
+ console.log('⏰ 调用时间:', callTime);
|
|
|
197
|
+ console.log('🔍 调用堆栈:', new Error().stack);
|
|
196
|
198
|
|
|
197
|
199
|
// 这里的 this 指向 Tabulator 实例
|
|
198
|
200
|
const tabulatorInstance = this;
|
|
|
@@ -203,64 +205,159 @@ export class TabulatorGridComponent implements OnInit, AfterViewInit, OnDestroy
|
|
203
|
205
|
hasGetPageSize: typeof tabulatorInstance.getPageSize === 'function',
|
|
204
|
206
|
hasGetFilters: typeof tabulatorInstance.getFilters === 'function',
|
|
205
|
207
|
hasGetSorters: typeof tabulatorInstance.getSorters === 'function',
|
|
206
|
|
- tabulatorVersion: Tabulator.version
|
|
|
208
|
+ tabulatorVersion: Tabulator.version,
|
|
|
209
|
+ instanceMethods: Object.keys(tabulatorInstance).filter(key => typeof tabulatorInstance[key] === 'function').slice(0, 10)
|
|
|
210
|
+ });
|
|
|
211
|
+
|
|
|
212
|
+ // 验证 Tabulator 配置
|
|
|
213
|
+ console.log('⚙️ Tabulator 配置检查:', {
|
|
|
214
|
+ sortMode: tabulatorInstance.options?.sortMode || 'unknown',
|
|
|
215
|
+ filterMode: tabulatorInstance.options?.filterMode || 'unknown',
|
|
|
216
|
+ paginationMode: tabulatorInstance.options?.paginationMode || 'unknown',
|
|
|
217
|
+ ajaxURL: tabulatorInstance.options?.ajaxURL,
|
|
|
218
|
+ hasAjaxRequestFunc: !!tabulatorInstance.options?.ajaxRequestFunc
|
|
207
|
219
|
});
|
|
208
|
220
|
|
|
209
|
221
|
// 提供安全的默认值,即使 Tabulator 方法未初始化
|
|
210
|
222
|
const page = (tabulatorInstance.getPage && tabulatorInstance.getPage()) || 1;
|
|
211
|
223
|
const pageSize = (tabulatorInstance.getPageSize && tabulatorInstance.getPageSize()) || componentPaginationSize || 20;
|
|
212
|
224
|
|
|
213
|
|
- // 获取筛选器 - 传递 true 获取所有筛选器
|
|
214
|
|
- const rawFilter = (tabulatorInstance.getFilters && tabulatorInstance.getFilters(true)) || [];
|
|
215
|
|
-
|
|
216
|
|
- // 获取排序器
|
|
217
|
|
- const rawSort = (tabulatorInstance.getSorters && tabulatorInstance.getSorters()) || [];
|
|
218
|
|
-
|
|
219
|
|
- // 辅助函数:提取筛选器数据
|
|
220
|
|
- function extractFilterData(filters: any[]): any[] {
|
|
221
|
|
- if (!filters || !Array.isArray(filters)) return [];
|
|
222
|
|
- return filters.map(f => {
|
|
223
|
|
- // 提取基本属性,避免循环引用
|
|
224
|
|
- const result: any = {};
|
|
225
|
|
- if (f.field !== undefined) result.field = f.field;
|
|
226
|
|
- if (f.type !== undefined) result.type = f.type;
|
|
227
|
|
- if (f.value !== undefined) result.value = f.value;
|
|
228
|
|
- return result;
|
|
229
|
|
- });
|
|
230
|
|
- }
|
|
231
|
|
-
|
|
232
|
|
- // 辅助函数:提取排序器数据
|
|
233
|
|
- function extractSortData(sorters: any[]): any[] {
|
|
234
|
|
- if (!sorters || !Array.isArray(sorters)) return [];
|
|
235
|
|
- return sorters.map(s => {
|
|
236
|
|
- // 提取基本属性,避免循环引用
|
|
237
|
|
- const result: any = {};
|
|
238
|
|
- if (s.field !== undefined) result.field = s.field;
|
|
239
|
|
- if (s.dir !== undefined) result.dir = s.dir;
|
|
240
|
|
- return result;
|
|
241
|
|
- });
|
|
242
|
|
- }
|
|
243
|
|
-
|
|
244
|
|
- // 提取纯数据
|
|
245
|
|
- const filterData = extractFilterData(rawFilter);
|
|
246
|
|
- const sortData = extractSortData(rawSort);
|
|
247
|
|
-
|
|
248
|
|
- console.log('⏰ 调用时间:', callTime);
|
|
249
|
|
- console.log('📄 当前页码:', page);
|
|
250
|
|
- console.log('📏 每页条数:', pageSize);
|
|
251
|
|
- console.log('🔍 筛选条件:', filterData);
|
|
252
|
|
- console.log('🔢 排序条件:', sortData);
|
|
253
|
|
- console.groupEnd();
|
|
254
|
|
-
|
|
255
|
|
- const params = {
|
|
256
|
|
- page,
|
|
257
|
|
- size: pageSize,
|
|
258
|
|
- filter: filterData,
|
|
259
|
|
- sort: sortData
|
|
260
|
|
- };
|
|
|
225
|
+ // 获取筛选器 - 传递 true 获取所有筛选器
|
|
|
226
|
+ const rawFilter = (tabulatorInstance.getFilters && tabulatorInstance.getFilters(true)) || [];
|
|
|
227
|
+
|
|
|
228
|
+ // 获取排序器
|
|
|
229
|
+ const rawSort = (tabulatorInstance.getSorters && tabulatorInstance.getSorters()) || [];
|
|
|
230
|
+
|
|
|
231
|
+ // 调试原始数据
|
|
|
232
|
+ console.log('🔧 原始数据检查:', {
|
|
|
233
|
+ rawFilterType: typeof rawFilter,
|
|
|
234
|
+ rawFilterIsArray: Array.isArray(rawFilter),
|
|
|
235
|
+ rawFilterLength: Array.isArray(rawFilter) ? rawFilter.length : 'N/A',
|
|
|
236
|
+ rawSortType: typeof rawSort,
|
|
|
237
|
+ rawSortIsArray: Array.isArray(rawSort),
|
|
|
238
|
+ rawSortLength: Array.isArray(rawSort) ? rawSort.length : 'N/A',
|
|
|
239
|
+ getPageSizeResult: tabulatorInstance.getPageSize ? tabulatorInstance.getPageSize() : 'N/A',
|
|
|
240
|
+ componentPaginationSize,
|
|
|
241
|
+ finalPageSize: pageSize
|
|
|
242
|
+ });
|
|
|
243
|
+
|
|
|
244
|
+ // 安全字符串化函数,避免循环引用
|
|
|
245
|
+ function safeStringify(obj: any, space?: number): string {
|
|
|
246
|
+ const seen = new WeakSet();
|
|
|
247
|
+ return JSON.stringify(obj, (key, value) => {
|
|
|
248
|
+ if (typeof value === 'object' && value !== null) {
|
|
|
249
|
+ if (seen.has(value)) {
|
|
|
250
|
+ return '[Circular]';
|
|
|
251
|
+ }
|
|
|
252
|
+ seen.add(value);
|
|
|
253
|
+ }
|
|
|
254
|
+ return value;
|
|
|
255
|
+ }, space);
|
|
|
256
|
+ }
|
|
|
257
|
+
|
|
|
258
|
+ // 辅助函数:提取筛选器数据
|
|
|
259
|
+ function extractFilterData(filters: any[]): any[] {
|
|
|
260
|
+ if (!filters || !Array.isArray(filters)) return [];
|
|
|
261
|
+ return filters.map(f => {
|
|
|
262
|
+ // 提取基本属性,避免循环引用
|
|
|
263
|
+ const result: any = {};
|
|
|
264
|
+ if (f.field !== undefined) result.field = f.field;
|
|
|
265
|
+ if (f.type !== undefined) result.type = f.type;
|
|
|
266
|
+ if (f.value !== undefined) {
|
|
|
267
|
+ // 安全处理值,避免循环引用
|
|
|
268
|
+ if (typeof f.value === 'object' && f.value !== null) {
|
|
|
269
|
+ try {
|
|
|
270
|
+ // 尝试序列化并解析,去除循环引用
|
|
|
271
|
+ const seen = new WeakSet();
|
|
|
272
|
+ const safeValue = JSON.parse(JSON.stringify(f.value, (key, val) => {
|
|
|
273
|
+ if (typeof val === 'object' && val !== null) {
|
|
|
274
|
+ if (seen.has(val)) {
|
|
|
275
|
+ return '[Circular]';
|
|
|
276
|
+ }
|
|
|
277
|
+ seen.add(val);
|
|
|
278
|
+ }
|
|
|
279
|
+ return val;
|
|
|
280
|
+ }));
|
|
|
281
|
+ result.value = safeValue;
|
|
|
282
|
+ } catch (e) {
|
|
|
283
|
+ console.warn('筛选值包含循环引用,使用简化值:', e);
|
|
|
284
|
+ result.value = '[Complex Object]';
|
|
|
285
|
+ }
|
|
|
286
|
+ } else {
|
|
|
287
|
+ result.value = f.value;
|
|
|
288
|
+ }
|
|
|
289
|
+ }
|
|
|
290
|
+ return result;
|
|
|
291
|
+ });
|
|
|
292
|
+ }
|
|
|
293
|
+
|
|
|
294
|
+ // 辅助函数:提取排序器数据
|
|
|
295
|
+ function extractSortData(sorters: any[]): any[] {
|
|
|
296
|
+ if (!sorters || !Array.isArray(sorters)) return [];
|
|
|
297
|
+ return sorters.map(s => {
|
|
|
298
|
+ // 提取基本属性,避免循环引用
|
|
|
299
|
+ const result: any = {};
|
|
|
300
|
+ if (s.field !== undefined) {
|
|
|
301
|
+ // 安全处理字段值
|
|
|
302
|
+ if (typeof s.field === 'object' && s.field !== null) {
|
|
|
303
|
+ try {
|
|
|
304
|
+ const seen = new WeakSet();
|
|
|
305
|
+ const safeField = JSON.parse(JSON.stringify(s.field, (key, val) => {
|
|
|
306
|
+ if (typeof val === 'object' && val !== null) {
|
|
|
307
|
+ if (seen.has(val)) {
|
|
|
308
|
+ return '[Circular]';
|
|
|
309
|
+ }
|
|
|
310
|
+ seen.add(val);
|
|
|
311
|
+ }
|
|
|
312
|
+ return val;
|
|
|
313
|
+ }));
|
|
|
314
|
+ result.field = safeField;
|
|
|
315
|
+ } catch (e) {
|
|
|
316
|
+ console.warn('排序字段包含循环引用,使用简化值:', e);
|
|
|
317
|
+ result.field = '[Complex Object]';
|
|
|
318
|
+ }
|
|
|
319
|
+ } else {
|
|
|
320
|
+ result.field = s.field;
|
|
|
321
|
+ }
|
|
|
322
|
+ }
|
|
|
323
|
+ if (s.dir !== undefined) result.dir = s.dir;
|
|
|
324
|
+ return result;
|
|
|
325
|
+ });
|
|
|
326
|
+ }
|
|
261
|
327
|
|
|
262
|
|
- console.log(`🚀 TabulatorGrid[${componentId}] 返回参数:`, params);
|
|
263
|
|
- return params;
|
|
|
328
|
+ // 提取纯数据
|
|
|
329
|
+ const filterData = extractFilterData(rawFilter);
|
|
|
330
|
+ const sortData = extractSortData(rawSort);
|
|
|
331
|
+
|
|
|
332
|
+ console.log('⏰ 调用时间:', callTime);
|
|
|
333
|
+ console.log('📄 当前页码:', page);
|
|
|
334
|
+ console.log('📏 每页条数:', pageSize);
|
|
|
335
|
+ console.log('🔍 原始筛选器 (安全显示):', safeStringify(rawFilter));
|
|
|
336
|
+ console.log('🔍 处理后筛选条件:', filterData);
|
|
|
337
|
+ console.log('🔢 原始排序器 (安全显示):', safeStringify(rawSort));
|
|
|
338
|
+ console.log('🔢 处理后排序条件:', sortData);
|
|
|
339
|
+
|
|
|
340
|
+ // 验证参数完整性
|
|
|
341
|
+ console.log('✅ 参数完整性检查:', {
|
|
|
342
|
+ hasFilters: filterData.length > 0,
|
|
|
343
|
+ hasSorters: sortData.length > 0,
|
|
|
344
|
+ filterFields: filterData.map(f => f.field),
|
|
|
345
|
+ sortFields: sortData.map(s => s.field),
|
|
|
346
|
+ pageValid: page > 0,
|
|
|
347
|
+ pageSizeValid: pageSize > 0
|
|
|
348
|
+ });
|
|
|
349
|
+
|
|
|
350
|
+ console.groupEnd();
|
|
|
351
|
+
|
|
|
352
|
+ const params = {
|
|
|
353
|
+ page,
|
|
|
354
|
+ size: pageSize,
|
|
|
355
|
+ filter: filterData,
|
|
|
356
|
+ sort: sortData
|
|
|
357
|
+ };
|
|
|
358
|
+
|
|
|
359
|
+ console.log(`🚀 TabulatorGrid[${componentId}] 返回参数:`, safeStringify(params, 2));
|
|
|
360
|
+ return params;
|
|
264
|
361
|
};
|
|
265
|
362
|
|
|
266
|
363
|
// AJAX 响应处理
|
|
|
@@ -364,18 +461,53 @@ export class TabulatorGridComponent implements OnInit, AfterViewInit, OnDestroy
|
|
364
|
461
|
const dataLoadedEvent = this.dataLoaded;
|
|
365
|
462
|
const componentId = this.containerId;
|
|
366
|
463
|
|
|
367
|
|
- const ajaxFunc = (url: string, config: any, params: any): Promise<any> => {
|
|
368
|
|
- console.group(`🔍 TabulatorGrid[${componentId}] ajaxRequestFunc 被调用`);
|
|
369
|
|
- console.log('📡 请求信息:', {
|
|
370
|
|
- url,
|
|
371
|
|
- configType: typeof config,
|
|
372
|
|
- hasDataLoader: !!dataLoader
|
|
373
|
|
- });
|
|
374
|
|
- console.log('📦 请求参数:', params);
|
|
375
|
|
-
|
|
376
|
|
- // 调试:记录调用堆栈以确认函数被 Tabulator 调用
|
|
377
|
|
- console.trace('TabulatorGrid ajaxRequestFunc 调用堆栈');
|
|
378
|
|
- console.groupEnd();
|
|
|
464
|
+ const ajaxFunc = (url: string, config: any, params: any): Promise<any> => {
|
|
|
465
|
+ console.group(`🔍 TabulatorGrid[${componentId}] ajaxRequestFunc 被调用`);
|
|
|
466
|
+ console.log('📡 请求信息:', {
|
|
|
467
|
+ url,
|
|
|
468
|
+ configType: typeof config,
|
|
|
469
|
+ configKeys: config ? Object.keys(config) : [],
|
|
|
470
|
+ hasDataLoader: !!dataLoader,
|
|
|
471
|
+ ajaxURL: config?.ajaxURL,
|
|
|
472
|
+ ajaxParamsFunc: typeof config?.ajaxParams === 'function'
|
|
|
473
|
+ });
|
|
|
474
|
+
|
|
|
475
|
+ // 详细分析参数结构
|
|
|
476
|
+ console.log('📦 请求参数详情:', {
|
|
|
477
|
+ paramsType: typeof params,
|
|
|
478
|
+ isObject: params && typeof params === 'object',
|
|
|
479
|
+ keys: params ? Object.keys(params) : [],
|
|
|
480
|
+ page: params?.page,
|
|
|
481
|
+ size: params?.size,
|
|
|
482
|
+ hasFilter: 'filter' in params,
|
|
|
483
|
+ hasSort: 'sort' in params,
|
|
|
484
|
+ filterType: typeof params?.filter,
|
|
|
485
|
+ filterIsArray: Array.isArray(params?.filter),
|
|
|
486
|
+ filterLength: Array.isArray(params?.filter) ? params.filter.length : 0,
|
|
|
487
|
+ sortType: typeof params?.sort,
|
|
|
488
|
+ sortIsArray: Array.isArray(params?.sort),
|
|
|
489
|
+ sortLength: Array.isArray(params?.sort) ? params.sort.length : 0
|
|
|
490
|
+ });
|
|
|
491
|
+
|
|
|
492
|
+ // 安全输出参数,避免循环引用
|
|
|
493
|
+ const safeStringify = (obj: any, space?: number): string => {
|
|
|
494
|
+ const seen = new WeakSet();
|
|
|
495
|
+ return JSON.stringify(obj, (key, value) => {
|
|
|
496
|
+ if (typeof value === 'object' && value !== null) {
|
|
|
497
|
+ if (seen.has(value)) {
|
|
|
498
|
+ return '[Circular]';
|
|
|
499
|
+ }
|
|
|
500
|
+ seen.add(value);
|
|
|
501
|
+ }
|
|
|
502
|
+ return value;
|
|
|
503
|
+ }, space);
|
|
|
504
|
+ };
|
|
|
505
|
+
|
|
|
506
|
+ console.log('📦 原始参数值 (安全显示):', safeStringify(params, 2));
|
|
|
507
|
+
|
|
|
508
|
+ // 调试:记录调用堆栈以确认函数被 Tabulator 调用
|
|
|
509
|
+ console.trace('TabulatorGrid ajaxRequestFunc 调用堆栈');
|
|
|
510
|
+ console.groupEnd();
|
|
379
|
511
|
|
|
380
|
512
|
return new Promise((resolve, reject) => {
|
|
381
|
513
|
if (!dataLoader) {
|