neo-cmp-cli 1.13.17 → 1.13.19
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 +23 -3
- package/dist/index2.js +1 -1
- package/dist/neo/env.js +1 -1
- package/dist/neo/pushCmp.js +1 -1
- package/dist/package.json.js +1 -1
- package/package.json +3 -2
- package/template/asset-manage-template/docs/README.md +1 -232
- package/template/echarts-custom-cmp-template/package.json +1 -1
- package/template/neo-bi-cmps/package.json +1 -1
- package/template/neo-bi-cmps/src/components/filterBar__c/common.scss +1 -1
- package/template/neo-bi-cmps/src/components/filterBar__c/index.tsx +18 -10
- package/template/neo-bi-cmps/src/components/filterBar__c/model.ts +8 -2
- package/template/neo-bi-cmps/src/components/targetNumber__c/model.ts +1 -1
- package/template/neo-bi-cmps/src/utils/common.ts +18 -20
- package/template/neo-bi-cmps/src/utils/filter2chartFilter.ts +4 -6
- package/template/neo-bi-cmps/src/utils/pipelineFunnel.ts +4 -2
- package/template/neo-bi-cmps/src/utils/simpleTable.tsx +21 -16
- package/template/neo-custom-cmp-template/docs/README.md +0 -231
- package/template/neo-custom-cmp-template/package.json +1 -1
- package/template/neo-h5-cmps/src/components/entityList__c/index.tsx +1 -2
- package/template/neo-h5-cmps/src/components/entityTabs__c/index.tsx +1 -1
- package/template/neo-h5-cmps/src/components/globalSearchInput__c/index.tsx +1 -1
- package/template/neo-h5-cmps/src/components/openChatPageBtn__c/index.tsx +1 -2
- package/template/neo-pipeline-cmps/neo.config.js +11 -0
- package/template/neo-pipeline-cmps/src/assets/css/common.scss +16 -16
- package/template/neo-pipeline-cmps/src/assets/css/mixin.scss +5 -5
- package/template/neo-pipeline-cmps/src/components/filterBar__c/README.md +9 -9
- package/template/neo-pipeline-cmps/src/components/filterBar__c/common.scss +5 -5
- package/template/neo-pipeline-cmps/src/components/filterBar__c/index.tsx +47 -46
- package/template/neo-pipeline-cmps/src/components/filterBar__c/model.ts +22 -12
- package/template/neo-pipeline-cmps/src/components/filterBar__c/style.scss +1 -1
- package/template/neo-pipeline-cmps/src/components/pipelineFunnel__c/README.md +17 -17
- package/template/neo-pipeline-cmps/src/components/pipelineFunnel__c/index.tsx +24 -22
- package/template/neo-pipeline-cmps/src/components/pipelineFunnel__c/model.ts +31 -18
- package/template/neo-pipeline-cmps/src/components/pipelineFunnel__c/reset.scss +4 -0
- package/template/neo-pipeline-cmps/src/components/showHealthResult__c/index.tsx +33 -26
- package/template/neo-pipeline-cmps/src/components/showHealthResult__c/model.ts +9 -9
- package/template/neo-pipeline-cmps/src/components/simpleTable__c/README.md +53 -54
- package/template/neo-pipeline-cmps/src/components/simpleTable__c/common.scss +5 -5
- package/template/neo-pipeline-cmps/src/components/simpleTable__c/index.tsx +70 -68
- package/template/neo-pipeline-cmps/src/components/simpleTable__c/model.ts +41 -41
- package/template/neo-pipeline-cmps/src/components/simpleTable__c/style.scss +2 -3
- package/template/neo-pipeline-cmps/src/components/stageSwitch__c/README.md +15 -15
- package/template/neo-pipeline-cmps/src/components/stageSwitch__c/index.tsx +35 -33
- package/template/neo-pipeline-cmps/src/components/stageSwitch__c/model.ts +29 -16
- package/template/neo-pipeline-cmps/src/components/stageTimeChart__c/README.md +18 -18
- package/template/neo-pipeline-cmps/src/components/stageTimeChart__c/index.tsx +20 -20
- package/template/neo-pipeline-cmps/src/components/stageTimeChart__c/model.ts +34 -19
- package/template/neo-pipeline-cmps/src/utils/common.ts +14 -14
- package/template/neo-pipeline-cmps/src/utils/filter2chartFilter.ts +21 -23
- package/template/neo-pipeline-cmps/src/utils/filterBar.ts +14 -14
- package/template/neo-pipeline-cmps/src/utils/pipelineFunnel.ts +5 -5
- package/template/neo-pipeline-cmps/src/utils/queryByCustomSQL.ts +26 -22
- package/template/neo-pipeline-cmps/src/utils/requestDebounce.ts +3 -3
- package/template/neo-pipeline-cmps/src/utils/simpleTable.tsx +31 -26
- package/template/neo-pipeline-cmps/src/utils/stageSwitch.ts +1 -1
- package/template/neo-pipeline-cmps/src/utils/stageTimeChart.ts +5 -5
- package/template/neo-pipeline-cmps/src/utils/targetNumber.ts +2 -2
- package/template/neo-web-entity-grid/src/components/createForm__c/index.tsx +271 -259
- package/template/neo-web-entity-grid/src/components/createForm__c/model.ts +17 -3
- package/template/neo-web-entity-grid/src/components/createForm__c/resetAntd.scss +0 -1
- package/template/neo-web-entity-grid/src/components/createForm__c/style.scss +1 -1
- package/template/neo-web-entity-grid/src/components/entityGrid2__c/index.tsx +5 -1
- package/template/neo-web-entity-grid/src/components/entityGrid2__c/model.ts +4 -3
- package/template/neo-web-entity-grid/src/components/entityGrid3__c/index.tsx +1 -1
- package/template/neo-web-entity-grid/src/components/searchForm__c/index.tsx +4 -3
- package/template/neo-web-entity-grid/src/components/searchForm__c/model.ts +9 -4
- package/template/neo-web-entity-grid/src/components/searchForm__c/style.scss +2 -1
- package/template/neo-web-form/package.json +1 -1
- package/template/neo-web-form/src/components/batchAddTable__c/index.tsx +179 -59
- package/template/neo-web-form/src/components/batchAddTable__c/model.ts +12 -14
- package/template/neo-web-form/src/components/listSummary__c/index.tsx +6 -5
- package/template/react-custom-cmp-template/package.json +1 -1
- package/template/asset-manage-template/src/utils/axiosFetcher.ts +0 -37
- package/template/asset-manage-template/src/utils/queryObjectData.ts +0 -112
- package/template/asset-manage-template/src/utils/xobjects.ts +0 -162
- package/template/neo-custom-cmp-template/src/utils/axiosFetcher.ts +0 -37
- package/template/neo-custom-cmp-template/src/utils/queryObjectData.ts +0 -112
- package/template/neo-custom-cmp-template/src/utils/xobjects.ts +0 -162
- package/template/neo-h5-cmps/src/utils/axiosFetcher.ts +0 -37
- package/template/neo-h5-cmps/src/utils/queryObjectData.ts +0 -112
- package/template/neo-h5-cmps/src/utils/xobjects.ts +0 -167
- package/template/neo-order-cmps/src/utils/axiosFetcher.ts +0 -37
- package/template/neo-order-cmps/src/utils/queryObjectData.ts +0 -112
- package/template/neo-order-cmps/src/utils/xobjects.ts +0 -162
- package/template/neo-web-entity-grid/src/utils/axiosFetcher.ts +0 -37
- package/template/neo-web-entity-grid/src/utils/queryObjectData.ts +0 -112
- package/template/neo-web-entity-grid/src/utils/xobjects.ts +0 -167
- package/template/neo-web-form/src/utils/axiosFetcher.ts +0 -37
- package/template/neo-web-form/src/utils/queryObjectData.ts +0 -112
- package/template/neo-web-form/src/utils/xobjects.ts +0 -167
|
@@ -67,14 +67,15 @@ export class NeoEntityGridModel {
|
|
|
67
67
|
apiKey: 'handleCustomSearchEvent',
|
|
68
68
|
label: '更新筛选条件',
|
|
69
69
|
helpTextKey: '更新自定义筛选条件',
|
|
70
|
-
funcInParams: [
|
|
70
|
+
funcInParams: [
|
|
71
|
+
// 定义组件函数入参
|
|
71
72
|
{
|
|
72
73
|
apiKey: 'eventData',
|
|
73
74
|
label: '自定义筛选条件',
|
|
74
75
|
type: 'Array',
|
|
75
|
-
required: true
|
|
76
|
+
required: true,
|
|
76
77
|
},
|
|
77
|
-
]
|
|
78
|
+
],
|
|
78
79
|
},
|
|
79
80
|
];
|
|
80
81
|
|
|
@@ -61,7 +61,7 @@ export default class NeoEntityGridCmp extends React.PureComponent<NeoEntityGridP
|
|
|
61
61
|
objectApiKey={objectApiKey || 'account'}
|
|
62
62
|
pattern={'pickView'} // Picker 列表(选择器)
|
|
63
63
|
referData={referData}
|
|
64
|
-
selectionMode={selectionMode ??
|
|
64
|
+
selectionMode={selectionMode ?? 'single'} // 多选模式
|
|
65
65
|
shouldCloseDialog={restProps.shouldCloseDialog ?? true}
|
|
66
66
|
onRowSelected={(data: any, event: any) => {
|
|
67
67
|
const selectedIds = data.map(({ data }: any) => data.id);
|
|
@@ -335,10 +335,11 @@ export default class SearchForm extends React.PureComponent<
|
|
|
335
335
|
const payload: CustomQueryPayload = {
|
|
336
336
|
xObjectApiKey, // 冗余数据
|
|
337
337
|
conditions, // 冗余数据
|
|
338
|
-
data: {
|
|
338
|
+
data: {
|
|
339
|
+
// 事件动作的入参数据
|
|
339
340
|
xObjectApiKey,
|
|
340
|
-
conditions
|
|
341
|
-
}
|
|
341
|
+
conditions,
|
|
342
|
+
},
|
|
342
343
|
};
|
|
343
344
|
|
|
344
345
|
this.onQuery(payload);
|
|
@@ -66,10 +66,15 @@ export class SearchFormModel {
|
|
|
66
66
|
label: '点击查询后',
|
|
67
67
|
helpText:
|
|
68
68
|
'点击「查询」后触发;事件参数为 { xObjectApiKey, conditions },conditions 每项含 apiKey、type(1 等于 / 3 包含)、value',
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
69
|
+
// 定义事件触发时接收到的事件数据格式
|
|
70
|
+
eventParams: [
|
|
71
|
+
{
|
|
72
|
+
apiKey: 'eventParam',
|
|
73
|
+
children: [{ apiKey: 'data', label: '当前表单数据', type: 'Object' }],
|
|
74
|
+
label: '事件入参',
|
|
75
|
+
type: 'Object',
|
|
76
|
+
},
|
|
77
|
+
],
|
|
73
78
|
},
|
|
74
79
|
];
|
|
75
80
|
|
|
@@ -189,7 +189,8 @@
|
|
|
189
189
|
font-weight: 400;
|
|
190
190
|
min-width: auto;
|
|
191
191
|
margin-left: 10px;
|
|
192
|
-
transition: border-color 0.2s ease, background 0.2s ease,
|
|
192
|
+
transition: border-color 0.2s ease, background 0.2s ease,
|
|
193
|
+
box-shadow 0.2s ease;
|
|
193
194
|
|
|
194
195
|
&:first-child {
|
|
195
196
|
margin-left: 0;
|
|
@@ -83,6 +83,14 @@ interface BatchAddTableState {
|
|
|
83
83
|
entityTypeList: any[];
|
|
84
84
|
submitting: boolean;
|
|
85
85
|
modalVisible: boolean;
|
|
86
|
+
/** Excel 导入 loading 状态 */
|
|
87
|
+
importLoading: boolean;
|
|
88
|
+
/** 导入进度信息 */
|
|
89
|
+
importProgress: { current: number; total: number } | null;
|
|
90
|
+
/** 当前页码 */
|
|
91
|
+
currentPage: number;
|
|
92
|
+
/** 每页条数 */
|
|
93
|
+
pageSize: number;
|
|
86
94
|
}
|
|
87
95
|
|
|
88
96
|
let rowKeySeed = 0;
|
|
@@ -145,6 +153,10 @@ export default class BatchAddTable extends React.PureComponent<
|
|
|
145
153
|
entityTypeList: [],
|
|
146
154
|
submitting: false,
|
|
147
155
|
modalVisible: false,
|
|
156
|
+
importLoading: false,
|
|
157
|
+
importProgress: null,
|
|
158
|
+
currentPage: 1,
|
|
159
|
+
pageSize: 100,
|
|
148
160
|
};
|
|
149
161
|
this.loadFieldList = this.loadFieldList.bind(this);
|
|
150
162
|
this.getEntityTypeList = this.getEntityTypeList.bind(this);
|
|
@@ -279,9 +291,14 @@ export default class BatchAddTable extends React.PureComponent<
|
|
|
279
291
|
message.warning('暂无可用字段');
|
|
280
292
|
return;
|
|
281
293
|
}
|
|
282
|
-
this.
|
|
283
|
-
|
|
284
|
-
|
|
294
|
+
const { rows, pageSize } = this.state;
|
|
295
|
+
const newRows = [...rows, emptyRowForFields(visible)];
|
|
296
|
+
// 计算新增后的最后一页页码
|
|
297
|
+
const lastPage = Math.ceil(newRows.length / pageSize);
|
|
298
|
+
this.setState({
|
|
299
|
+
rows: newRows,
|
|
300
|
+
currentPage: lastPage,
|
|
301
|
+
});
|
|
285
302
|
}
|
|
286
303
|
|
|
287
304
|
handleCellChange(rowKey: string, apiKey: string, value: any) {
|
|
@@ -315,17 +332,11 @@ export default class BatchAddTable extends React.PureComponent<
|
|
|
315
332
|
(it) => it.id === raw || String(it.id) === s,
|
|
316
333
|
);
|
|
317
334
|
if (byId) return byId.id;
|
|
318
|
-
const byLabel = entityTypeList.find(
|
|
319
|
-
(it) => String(it.label).trim() === s,
|
|
320
|
-
);
|
|
335
|
+
const byLabel = entityTypeList.find((it) => String(it.label).trim() === s);
|
|
321
336
|
return byLabel ? byLabel.id : raw;
|
|
322
337
|
}
|
|
323
338
|
|
|
324
|
-
parseImportedCell(
|
|
325
|
-
field: FieldInfo,
|
|
326
|
-
raw: any,
|
|
327
|
-
entityTypeList: any[],
|
|
328
|
-
): any {
|
|
339
|
+
parseImportedCell(field: FieldInfo, raw: any, entityTypeList: any[]): any {
|
|
329
340
|
if (raw === undefined || raw === null || raw === '') return undefined;
|
|
330
341
|
if (raw instanceof Date) {
|
|
331
342
|
if (
|
|
@@ -413,72 +424,132 @@ export default class BatchAddTable extends React.PureComponent<
|
|
|
413
424
|
const ws = XLSX.utils.aoa_to_sheet([headers]); // 将标题行转换为工作表
|
|
414
425
|
const wb = XLSX.utils.book_new(); // 创建新的工作簿
|
|
415
426
|
XLSX.utils.book_append_sheet(wb, ws, '导入模板'); // 将工作表添加到工作簿
|
|
416
|
-
const name = `${
|
|
427
|
+
const name = `${
|
|
428
|
+
this.props.xObjectDataApi?.xObjectApiKey || 'data'
|
|
429
|
+
}_导入模板.xlsx`; // 生成文件名
|
|
417
430
|
XLSX.writeFile(wb, name); // 将工作簿写入文件
|
|
418
431
|
message.success('模板已下载');
|
|
419
432
|
}
|
|
420
433
|
|
|
434
|
+
/**
|
|
435
|
+
* 分批处理导入数据,避免大数据量阻塞 UI
|
|
436
|
+
*/
|
|
437
|
+
private async processImportData(
|
|
438
|
+
rowsAoA: any[][],
|
|
439
|
+
fields: FieldInfo[],
|
|
440
|
+
colMap: Record<string, number>,
|
|
441
|
+
entityTypeList: any[],
|
|
442
|
+
onProgress: (current: number, total: number) => void,
|
|
443
|
+
): Promise<RowRecord[]> {
|
|
444
|
+
const newRows: RowRecord[] = [];
|
|
445
|
+
const total = rowsAoA.length - 1; // 排除表头
|
|
446
|
+
const batchSize = 100; // 每批处理 100 行
|
|
447
|
+
|
|
448
|
+
for (let r = 1; r < rowsAoA.length; r++) {
|
|
449
|
+
const line = rowsAoA[r];
|
|
450
|
+
if (!line || !line.some((c) => c !== '' && c != null)) continue;
|
|
451
|
+
|
|
452
|
+
const row: RowRecord = { _rowKey: nextRowKey() };
|
|
453
|
+
fields.forEach((f) => {
|
|
454
|
+
const idx = colMap[f.apiKey];
|
|
455
|
+
const raw = idx !== undefined ? line[idx] : undefined;
|
|
456
|
+
row[f.apiKey] = this.parseImportedCell(f, raw, entityTypeList);
|
|
457
|
+
});
|
|
458
|
+
newRows.push(row);
|
|
459
|
+
|
|
460
|
+
// 每处理 batchSize 行,让出主线程并更新进度
|
|
461
|
+
if (r % batchSize === 0) {
|
|
462
|
+
onProgress(r - 1, total);
|
|
463
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
onProgress(total, total);
|
|
468
|
+
return newRows;
|
|
469
|
+
}
|
|
470
|
+
|
|
421
471
|
handleImportBeforeUpload(file: File) {
|
|
422
472
|
const fields = this.getVisibleFields();
|
|
423
473
|
if (!fields.length) {
|
|
424
474
|
message.warning('暂无可用字段');
|
|
425
475
|
return false;
|
|
426
476
|
}
|
|
477
|
+
|
|
478
|
+
// 设置导入 loading 状态
|
|
479
|
+
this.setState({
|
|
480
|
+
importLoading: true,
|
|
481
|
+
importProgress: { current: 0, total: 0 },
|
|
482
|
+
});
|
|
483
|
+
|
|
427
484
|
const reader = new FileReader();
|
|
428
|
-
reader.onload = (e) => {
|
|
485
|
+
reader.onload = async (e) => {
|
|
429
486
|
try {
|
|
430
|
-
const data = new Uint8Array(e.target?.result as ArrayBuffer);
|
|
431
|
-
const wb = XLSX.read(data, { type: 'array', cellDates: true });
|
|
432
|
-
const sheetName = wb.SheetNames[0];
|
|
487
|
+
const data = new Uint8Array(e.target?.result as ArrayBuffer);
|
|
488
|
+
const wb = XLSX.read(data, { type: 'array', cellDates: true });
|
|
489
|
+
const sheetName = wb.SheetNames[0];
|
|
433
490
|
if (!sheetName) {
|
|
434
491
|
message.error('Excel 中未找到工作表');
|
|
492
|
+
this.setState({ importLoading: false, importProgress: null });
|
|
435
493
|
return;
|
|
436
494
|
}
|
|
437
|
-
const sheet = wb.Sheets[sheetName];
|
|
438
|
-
const rowsAoA: any[][] = XLSX.utils.sheet_to_json(sheet, {
|
|
439
|
-
header: 1,
|
|
440
|
-
raw: true,
|
|
441
|
-
defval: '',
|
|
442
|
-
}) as any[][];
|
|
495
|
+
const sheet = wb.Sheets[sheetName];
|
|
496
|
+
const rowsAoA: any[][] = XLSX.utils.sheet_to_json(sheet, {
|
|
497
|
+
header: 1,
|
|
498
|
+
raw: true,
|
|
499
|
+
defval: '',
|
|
500
|
+
}) as any[][];
|
|
443
501
|
if (!rowsAoA.length) {
|
|
444
502
|
message.error('Excel 内容为空');
|
|
503
|
+
this.setState({ importLoading: false, importProgress: null });
|
|
445
504
|
return;
|
|
446
505
|
}
|
|
447
506
|
const headerRow = rowsAoA[0] || [];
|
|
448
|
-
const colMap = this.buildHeaderIndexMap(headerRow, fields);
|
|
449
|
-
const missing = fields.filter((f) => colMap[f.apiKey] === undefined);
|
|
507
|
+
const colMap = this.buildHeaderIndexMap(headerRow, fields);
|
|
508
|
+
const missing = fields.filter((f) => colMap[f.apiKey] === undefined);
|
|
450
509
|
if (missing.length) {
|
|
451
510
|
message.error(
|
|
452
511
|
`表头无法匹配字段:${missing.map((m) => m.label).join('、')}`,
|
|
453
512
|
);
|
|
513
|
+
this.setState({ importLoading: false, importProgress: null });
|
|
454
514
|
return;
|
|
455
515
|
}
|
|
456
516
|
const { entityTypeList } = this.state;
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
|
|
517
|
+
|
|
518
|
+
// 使用分批处理解析数据
|
|
519
|
+
const newRows = await this.processImportData(
|
|
520
|
+
rowsAoA,
|
|
521
|
+
fields,
|
|
522
|
+
colMap,
|
|
523
|
+
entityTypeList,
|
|
524
|
+
(current, total) => {
|
|
525
|
+
this.setState({ importProgress: { current, total } });
|
|
526
|
+
},
|
|
527
|
+
);
|
|
528
|
+
|
|
469
529
|
if (!newRows.length) {
|
|
470
530
|
message.warning('未解析到有效数据行');
|
|
531
|
+
this.setState({ importLoading: false, importProgress: null });
|
|
471
532
|
return;
|
|
472
533
|
}
|
|
534
|
+
|
|
473
535
|
this.setState((prev) => ({
|
|
474
536
|
rows: [...prev.rows, ...newRows],
|
|
537
|
+
importLoading: false,
|
|
538
|
+
importProgress: null,
|
|
539
|
+
// 导入完成后跳转到第一页,展示新导入的数据
|
|
540
|
+
currentPage: 1,
|
|
475
541
|
}));
|
|
476
542
|
message.success(`已导入 ${newRows.length} 行`);
|
|
477
543
|
} catch (err) {
|
|
478
544
|
console.error(err);
|
|
479
545
|
message.error('解析 Excel 失败');
|
|
546
|
+
this.setState({ importLoading: false, importProgress: null });
|
|
480
547
|
}
|
|
481
548
|
};
|
|
549
|
+
reader.onerror = () => {
|
|
550
|
+
message.error('读取文件失败');
|
|
551
|
+
this.setState({ importLoading: false, importProgress: null });
|
|
552
|
+
};
|
|
482
553
|
reader.readAsArrayBuffer(file);
|
|
483
554
|
return false;
|
|
484
555
|
}
|
|
@@ -556,7 +627,13 @@ export default class BatchAddTable extends React.PureComponent<
|
|
|
556
627
|
const cloned = this.cloneRowRecord(record, fields);
|
|
557
628
|
const newRows = [...this.state.rows];
|
|
558
629
|
newRows.splice(idx + 1, 0, cloned);
|
|
559
|
-
|
|
630
|
+
// 计算复制行所在的页码
|
|
631
|
+
const { pageSize, currentPage } = this.state;
|
|
632
|
+
const copiedRowIndex = idx + 1;
|
|
633
|
+
const copiedRowPage = Math.floor(copiedRowIndex / pageSize) + 1;
|
|
634
|
+
// 如果复制的行不在当前页,跳转到复制的行所在页
|
|
635
|
+
const newPage = copiedRowPage !== currentPage ? copiedRowPage : currentPage;
|
|
636
|
+
this.setState({ rows: newRows, currentPage: newPage });
|
|
560
637
|
message.success('已在本行下方复制一行');
|
|
561
638
|
}
|
|
562
639
|
|
|
@@ -566,10 +643,22 @@ export default class BatchAddTable extends React.PureComponent<
|
|
|
566
643
|
if (newRows.length === 0 && fields.length) {
|
|
567
644
|
newRows.push(emptyRowForFields(fields));
|
|
568
645
|
}
|
|
569
|
-
|
|
646
|
+
// 删除后重新计算当前页码,避免当前页超出范围
|
|
647
|
+
const { pageSize, currentPage } = this.state;
|
|
648
|
+
const totalPages = Math.ceil(newRows.length / pageSize) || 1;
|
|
649
|
+
const newCurrentPage = Math.min(currentPage, totalPages);
|
|
650
|
+
this.setState({ rows: newRows, currentPage: newCurrentPage });
|
|
570
651
|
message.success('已删除该行');
|
|
571
652
|
}
|
|
572
653
|
|
|
654
|
+
/** 分页变化处理 */
|
|
655
|
+
handlePageChange = (page: number, pageSize?: number) => {
|
|
656
|
+
this.setState({
|
|
657
|
+
currentPage: page,
|
|
658
|
+
...(pageSize ? { pageSize } : {}),
|
|
659
|
+
} as BatchAddTableState);
|
|
660
|
+
};
|
|
661
|
+
|
|
573
662
|
openModal() {
|
|
574
663
|
this.setState({ modalVisible: true });
|
|
575
664
|
}
|
|
@@ -682,11 +771,7 @@ export default class BatchAddTable extends React.PureComponent<
|
|
|
682
771
|
style={{ minWidth: 140 }}
|
|
683
772
|
>
|
|
684
773
|
{entityTypeList.map((item) => (
|
|
685
|
-
<Option
|
|
686
|
-
key={item.apiKey}
|
|
687
|
-
value={item.id}
|
|
688
|
-
disabled={!item.active}
|
|
689
|
-
>
|
|
774
|
+
<Option key={item.apiKey} value={item.id} disabled={!item.active}>
|
|
690
775
|
{item.label}
|
|
691
776
|
</Option>
|
|
692
777
|
))}
|
|
@@ -819,7 +904,17 @@ export default class BatchAddTable extends React.PureComponent<
|
|
|
819
904
|
}
|
|
820
905
|
|
|
821
906
|
render() {
|
|
822
|
-
const {
|
|
907
|
+
const {
|
|
908
|
+
loading,
|
|
909
|
+
error,
|
|
910
|
+
rows,
|
|
911
|
+
submitting,
|
|
912
|
+
title,
|
|
913
|
+
importLoading,
|
|
914
|
+
importProgress,
|
|
915
|
+
currentPage,
|
|
916
|
+
pageSize,
|
|
917
|
+
} = this.state;
|
|
823
918
|
const { tableTitle, className, data } = this.props;
|
|
824
919
|
const curAmisData = data || {};
|
|
825
920
|
const systemInfo = curAmisData.__NeoSystemInfo || {};
|
|
@@ -876,12 +971,15 @@ export default class BatchAddTable extends React.PureComponent<
|
|
|
876
971
|
),
|
|
877
972
|
});
|
|
878
973
|
|
|
879
|
-
|
|
880
|
-
|
|
974
|
+
// 计算分页数据
|
|
975
|
+
const startIndex = (currentPage - 1) * pageSize;
|
|
976
|
+
const endIndex = startIndex + pageSize;
|
|
977
|
+
const paginatedRows = rows.slice(startIndex, endIndex);
|
|
978
|
+
|
|
979
|
+
const displayTitle = tableTitle || title || '批量新增数据';
|
|
881
980
|
const batchImportButtonTitle =
|
|
882
981
|
this.props.batchImportButtonTitle ?? '批量导入';
|
|
883
|
-
const batchImportButtonAlign =
|
|
884
|
-
this.props.batchImportButtonAlign ?? 'right';
|
|
982
|
+
const batchImportButtonAlign = this.props.batchImportButtonAlign ?? 'right';
|
|
885
983
|
|
|
886
984
|
const showModalFooter = !error && !!xObjectApiKey && fields.length > 0;
|
|
887
985
|
|
|
@@ -967,14 +1065,16 @@ export default class BatchAddTable extends React.PureComponent<
|
|
|
967
1065
|
accept=".xlsx,.xls"
|
|
968
1066
|
showUploadList={false}
|
|
969
1067
|
beforeUpload={this.handleImportBeforeUpload}
|
|
1068
|
+
disabled={importLoading}
|
|
970
1069
|
>
|
|
971
1070
|
<Button
|
|
972
1071
|
size="small"
|
|
973
1072
|
className="batch-add-modal-toolbar-btn"
|
|
974
1073
|
icon={<UploadOutlined />}
|
|
975
|
-
|
|
1074
|
+
loading={importLoading}
|
|
1075
|
+
disabled={!xObjectApiKey || !fields.length || importLoading}
|
|
976
1076
|
>
|
|
977
|
-
Excel 导入
|
|
1077
|
+
{importLoading ? '导入中...' : 'Excel 导入'}
|
|
978
1078
|
</Button>
|
|
979
1079
|
</Upload>
|
|
980
1080
|
</Space>
|
|
@@ -1008,15 +1108,35 @@ export default class BatchAddTable extends React.PureComponent<
|
|
|
1008
1108
|
/>
|
|
1009
1109
|
) : (
|
|
1010
1110
|
<div className="table-wrap">
|
|
1011
|
-
<
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
size="
|
|
1019
|
-
|
|
1111
|
+
<Spin
|
|
1112
|
+
spinning={importLoading}
|
|
1113
|
+
tip={
|
|
1114
|
+
importProgress
|
|
1115
|
+
? `正在加载导入数据... (${importProgress.current}/${importProgress.total})`
|
|
1116
|
+
: '正在加载导入数据...'
|
|
1117
|
+
}
|
|
1118
|
+
size="large"
|
|
1119
|
+
>
|
|
1120
|
+
<Table
|
|
1121
|
+
rowKey="_rowKey"
|
|
1122
|
+
columns={columns as any}
|
|
1123
|
+
dataSource={paginatedRows}
|
|
1124
|
+
pagination={{
|
|
1125
|
+
current: currentPage,
|
|
1126
|
+
pageSize: pageSize,
|
|
1127
|
+
total: rows.length,
|
|
1128
|
+
showSizeChanger: true,
|
|
1129
|
+
showQuickJumper: true,
|
|
1130
|
+
pageSizeOptions: ['50', '100', '200', '500'],
|
|
1131
|
+
showTotal: (total) => `共 ${total} 条`,
|
|
1132
|
+
onChange: this.handlePageChange,
|
|
1133
|
+
onShowSizeChange: this.handlePageChange,
|
|
1134
|
+
}}
|
|
1135
|
+
scroll={{ x: 'max-content', y: 'calc(100vh - 400px)' }}
|
|
1136
|
+
bordered
|
|
1137
|
+
size="small"
|
|
1138
|
+
/>
|
|
1139
|
+
</Spin>
|
|
1020
1140
|
</div>
|
|
1021
1141
|
)}
|
|
1022
1142
|
</Spin>
|
|
@@ -21,7 +21,7 @@ export class BatchAddTableModel {
|
|
|
21
21
|
batchImportButtonTitle: '批量导入',
|
|
22
22
|
batchImportButtonAlign: 'right',
|
|
23
23
|
xObjectDataApi: {
|
|
24
|
-
xObjectApiKey: 'opportunityProduct',
|
|
24
|
+
xObjectApiKey: 'opportunityProduct', // 商机明细
|
|
25
25
|
fields: [],
|
|
26
26
|
},
|
|
27
27
|
};
|
|
@@ -31,19 +31,17 @@ export class BatchAddTableModel {
|
|
|
31
31
|
apiKey: 'onSubmit',
|
|
32
32
|
label: '点击提交',
|
|
33
33
|
helpText: '点击提交按钮时触发,事件参数包含当前表格中所有行数据',
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
{
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
eventParams:
|
|
46
|
-
'[{"apiKey":"eventParam","children":[{"apiKey":"xObjectApiKey","label":"实体 API Key","type":"String"},{"apiKey":"rows","label":"表格数据列表","type":"Array"}],"label":"事件入参","type":"Object"}]',
|
|
34
|
+
eventParams: [
|
|
35
|
+
{
|
|
36
|
+
apiKey: 'eventParam',
|
|
37
|
+
children: [
|
|
38
|
+
{ apiKey: 'xObjectApiKey', label: '实体 API Key', type: 'String' },
|
|
39
|
+
{ apiKey: 'rows', label: '表格数据列表', type: 'Array' },
|
|
40
|
+
],
|
|
41
|
+
label: '事件入参',
|
|
42
|
+
type: 'Object',
|
|
43
|
+
},
|
|
44
|
+
],
|
|
47
45
|
},
|
|
48
46
|
];
|
|
49
47
|
|
|
@@ -29,7 +29,9 @@ interface ListSummaryState {
|
|
|
29
29
|
listData: any[];
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
function getFirstFieldApiKey(
|
|
32
|
+
function getFirstFieldApiKey(
|
|
33
|
+
desc?: FieldDescItem[] | null,
|
|
34
|
+
): string | undefined {
|
|
33
35
|
if (!desc || !Array.isArray(desc) || desc.length === 0) return undefined;
|
|
34
36
|
const first = desc[0];
|
|
35
37
|
return first?.value;
|
|
@@ -84,12 +86,11 @@ class ListSummary extends BaseCmp<ListSummaryProps, ListSummaryState> {
|
|
|
84
86
|
|
|
85
87
|
const hasRows = Array.isArray(listData) && listData.length > 0;
|
|
86
88
|
const totalQty = hasRows && qtyKey ? sumField(listData, qtyKey) : 0;
|
|
87
|
-
const totalAmount =
|
|
89
|
+
const totalAmount =
|
|
90
|
+
hasRows && amountKey ? sumField(listData, amountKey) : 0;
|
|
88
91
|
|
|
89
92
|
const qtyDisplay =
|
|
90
|
-
!hasRows || !qtyKey
|
|
91
|
-
? '0'
|
|
92
|
-
: totalQty.toLocaleString('zh-CN');
|
|
93
|
+
!hasRows || !qtyKey ? '0' : totalQty.toLocaleString('zh-CN');
|
|
93
94
|
|
|
94
95
|
const amountDisplay =
|
|
95
96
|
!hasRows || !amountKey
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import axios from 'axios'; // https://www.axios-http.cn/docs/intro
|
|
2
|
-
|
|
3
|
-
// 创建基于 axios 的 fetcher 函数
|
|
4
|
-
const axiosFetcher = async (options: any) => {
|
|
5
|
-
try {
|
|
6
|
-
const config = {
|
|
7
|
-
...options,
|
|
8
|
-
method: options?.method || 'GET',
|
|
9
|
-
data: options?.data || {},
|
|
10
|
-
headers: {
|
|
11
|
-
'Content-Type': 'application/json',
|
|
12
|
-
...options?.headers,
|
|
13
|
-
},
|
|
14
|
-
timeout: options?.timeout || 30000,
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
if (config?.method === 'GET') {
|
|
18
|
-
config.params = options?.data || {};
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const response = await axios(config);
|
|
22
|
-
return response?.data || {};
|
|
23
|
-
} catch (error) {
|
|
24
|
-
if (error.response) {
|
|
25
|
-
// 请求成功发出且服务器也响应了状态码,但状态代码超出了 2xx 的范围
|
|
26
|
-
console.error('接口请求报错 / 接口服务异常:', error.message);
|
|
27
|
-
} else if (error.request) {
|
|
28
|
-
// 请求已经成功发起,但没有收到响应
|
|
29
|
-
console.error('接口请求报错 / 接口未正常响应:', error.message);
|
|
30
|
-
} else {
|
|
31
|
-
console.error('接口请求报错:', error, ',请求参数:', options);
|
|
32
|
-
}
|
|
33
|
-
throw error;
|
|
34
|
-
}
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
export default axiosFetcher;
|