cloud-web-corejs 1.1.0-dev.21 → 1.1.0-dev.22
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/package.json +1 -1
- package/src/components/excelExport/conditionExportConfig.js +112 -0
- package/src/components/excelExport/exportType.js +8 -0
- package/src/components/excelExport/index.vue +7 -1
- package/src/components/excelExport/mixins.js +410 -259
- package/src/components/xform/form-designer/form-widget/field-widget/select-export-item-button-widget.vue +2 -1
- package/src/components/xform/form-designer/form-widget/field-widget/table-export-button-widget.vue +2 -1
- package/src/components/xform/form-designer/setting-panel/property-editor/field-table-export-button/empty-number-input.vue +51 -0
- package/src/components/xform/form-designer/setting-panel/property-editor/field-table-export-button/select-export-item-button-editor.vue +27 -2
- package/src/components/xform/form-designer/setting-panel/property-editor/field-table-export-button/table-export-button-editor.vue +33 -3
- package/src/components/xform/form-designer/widget-panel/widgetsConfig.js +6 -0
- package/src/components/xform/form-render/container-item/data-table-mixin.js +3 -1
package/package.json
CHANGED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { getLogicParamValue } from "@base/api/user";
|
|
2
|
+
|
|
3
|
+
export const CONDITION_EXPORT_PARAM_CODE = "conditionExportParams";
|
|
4
|
+
export const CONDITION_EXPORT_SEARCH_COUNT_CODE
|
|
5
|
+
= "conditionExportSearchCount";
|
|
6
|
+
|
|
7
|
+
export const DEFAULT_CONDITION_EXPORT_CONFIG = Object.freeze({
|
|
8
|
+
maxQueryTotal: 300000,
|
|
9
|
+
pageSize: 1000,
|
|
10
|
+
limitFileSize: 100000,
|
|
11
|
+
searchCount: true,
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
function parsePositiveInteger(value, fallback) {
|
|
15
|
+
let text = String(value == null ? "" : value).trim();
|
|
16
|
+
if (!/^\d+$/.test(text)) return fallback;
|
|
17
|
+
let result = Number(text);
|
|
18
|
+
if (!Number.isSafeInteger(result) || result <= 0) return fallback;
|
|
19
|
+
return result;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* 解析「最大查询总数;每页查询数量;单文件最大数据量」。每一项独立回落默认值,
|
|
24
|
+
* 避免一项填错导致另外两项已生效的配置也被丢弃。
|
|
25
|
+
*/
|
|
26
|
+
export function parseConditionExportParams(rawValue) {
|
|
27
|
+
let values = typeof rawValue === "string" ? rawValue.split(";") : [];
|
|
28
|
+
return {
|
|
29
|
+
maxQueryTotal: parsePositiveInteger(
|
|
30
|
+
values[0],
|
|
31
|
+
DEFAULT_CONDITION_EXPORT_CONFIG.maxQueryTotal
|
|
32
|
+
),
|
|
33
|
+
pageSize: parsePositiveInteger(
|
|
34
|
+
values[1],
|
|
35
|
+
DEFAULT_CONDITION_EXPORT_CONFIG.pageSize
|
|
36
|
+
),
|
|
37
|
+
limitFileSize: parsePositiveInteger(
|
|
38
|
+
values[2],
|
|
39
|
+
DEFAULT_CONDITION_EXPORT_CONFIG.limitFileSize
|
|
40
|
+
),
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function parseConditionExportSearchCount(rawValue, fallback = true) {
|
|
45
|
+
if (typeof rawValue === "boolean") return rawValue;
|
|
46
|
+
if (typeof rawValue !== "string") return fallback;
|
|
47
|
+
let value = rawValue.trim().toLowerCase();
|
|
48
|
+
if (value === "true") return true;
|
|
49
|
+
if (value === "false") return false;
|
|
50
|
+
return fallback;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function readLogicParam(paramCode) {
|
|
54
|
+
return getLogicParamValue({
|
|
55
|
+
data: { paramCode },
|
|
56
|
+
modal: false,
|
|
57
|
+
failMsg: false,
|
|
58
|
+
errorMsg: false,
|
|
59
|
+
})
|
|
60
|
+
.then((res) => (res && res.type === "success" ? res.objx : ""))
|
|
61
|
+
.catch(() => "");
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** 读取两条全局逻辑参数;接口异常时静默使用内置默认值。 */
|
|
65
|
+
export function loadConditionExportConfig() {
|
|
66
|
+
return Promise.all([
|
|
67
|
+
readLogicParam(CONDITION_EXPORT_PARAM_CODE),
|
|
68
|
+
readLogicParam(CONDITION_EXPORT_SEARCH_COUNT_CODE),
|
|
69
|
+
]).then(([paramsRaw, searchCountRaw]) => ({
|
|
70
|
+
...parseConditionExportParams(paramsRaw),
|
|
71
|
+
searchCount: parseConditionExportSearchCount(searchCountRaw, true),
|
|
72
|
+
}));
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* 从导出按钮 options 取出条件导出的三项覆盖值。空值转成 null,交给
|
|
77
|
+
* resolveConditionExportConfig 回落到全局逻辑参数。
|
|
78
|
+
*/
|
|
79
|
+
export function pickConditionExportOverrides(fieldOptions = {}) {
|
|
80
|
+
return {
|
|
81
|
+
pageSize: fieldOptions.exportPageSize || null,
|
|
82
|
+
maxQueryTotal: fieldOptions.maxQueryTotal || null,
|
|
83
|
+
limitFileSize: fieldOptions.limitFileSize || null,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* 单次导出参数优先于全局逻辑参数。按钮参数与脚本参数在进入导出器前已经合并,且脚本
|
|
89
|
+
* 位于展开表达式右侧,所以这里读取到的 option 天然满足「脚本 > 按钮 > 全局」。
|
|
90
|
+
*/
|
|
91
|
+
export function resolveConditionExportConfig(globalConfig, option = {}) {
|
|
92
|
+
let base = globalConfig || DEFAULT_CONDITION_EXPORT_CONFIG;
|
|
93
|
+
let searchCountOverride
|
|
94
|
+
= option.conditionExportSearchCount !== undefined
|
|
95
|
+
? option.conditionExportSearchCount
|
|
96
|
+
: option.searchCount;
|
|
97
|
+
return {
|
|
98
|
+
maxQueryTotal: parsePositiveInteger(
|
|
99
|
+
option.maxQueryTotal,
|
|
100
|
+
base.maxQueryTotal
|
|
101
|
+
),
|
|
102
|
+
pageSize: parsePositiveInteger(option.pageSize, base.pageSize),
|
|
103
|
+
limitFileSize: parsePositiveInteger(
|
|
104
|
+
option.limitFileSize,
|
|
105
|
+
base.limitFileSize
|
|
106
|
+
),
|
|
107
|
+
searchCount: parseConditionExportSearchCount(
|
|
108
|
+
searchCountOverride,
|
|
109
|
+
base.searchCount
|
|
110
|
+
),
|
|
111
|
+
};
|
|
112
|
+
}
|
|
@@ -39,6 +39,14 @@ export function isRowExport(type) {
|
|
|
39
39
|
return type === EXPORT_TYPE.SELECTED || type === EXPORT_TYPE.CURRENT;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
/**
|
|
43
|
+
* 是否条件导出。主表条件导出的历史 type 是 null/undefined;明细条件导出有独立类型。
|
|
44
|
+
* 明细选择导出虽然也走后端分页,但不受条件导出全局上限与查总数开关影响。
|
|
45
|
+
*/
|
|
46
|
+
export function isConditionExport(type) {
|
|
47
|
+
return type == null || type === EXPORT_TYPE.ITEM_CONDITION;
|
|
48
|
+
}
|
|
49
|
+
|
|
42
50
|
/**
|
|
43
51
|
* 是否必须先勾选行:空勾选要拦截,且以勾选行 id 作为查询条件。
|
|
44
52
|
* @param {String|null} type 导出模式。
|
|
@@ -41,6 +41,12 @@
|
|
|
41
41
|
<div class="export-box">
|
|
42
42
|
<div class="tips">
|
|
43
43
|
{{ $t2("导出中,请勿关闭当前窗口", "components.excelExport.tip") }}
|
|
44
|
+
<template v-if="conditionExportMode">
|
|
45
|
+
,{{
|
|
46
|
+
$t2("导出最大数据量", "components.excelExport.maxDataSize")
|
|
47
|
+
}}:{{ conditionExportConfig.maxQueryTotal
|
|
48
|
+
}}{{ $t2("条", "components.excelExport.rowUnit") }}
|
|
49
|
+
</template>
|
|
44
50
|
</div>
|
|
45
51
|
<el-progress
|
|
46
52
|
:text-inside="true"
|
|
@@ -62,7 +68,7 @@
|
|
|
62
68
|
<div class="fl import-count">
|
|
63
69
|
<span class="f-red doneNum">{{ doneSize }}</span>
|
|
64
70
|
/
|
|
65
|
-
<span class="dataSize">{{
|
|
71
|
+
<span class="dataSize">{{ exportTotalText }}</span>
|
|
66
72
|
</div>
|
|
67
73
|
<el-button type="primary" plain class="button-sty" @click="dialogClose2">
|
|
68
74
|
<i class="el-icon-close el-icon"></i>
|
|
@@ -5,9 +5,19 @@ import { getToken } from "../../utils/auth";
|
|
|
5
5
|
import indexUtil from "../../utils/index.js";
|
|
6
6
|
import exportFieldDialog from "./exportFieldDialog.vue";
|
|
7
7
|
import { getCellValue } from "@base/components/table/util/index";
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
import {
|
|
9
|
+
isConditionExport,
|
|
10
|
+
isItemExport,
|
|
11
|
+
isRowExport,
|
|
12
|
+
requiresCheckedRows,
|
|
13
|
+
} from "./exportType";
|
|
14
|
+
import { getExportItemColumns } from "./exportItemConfigUtil";
|
|
15
|
+
import { viewKey } from "@base/utils/repeatOpen";
|
|
16
|
+
import {
|
|
17
|
+
DEFAULT_CONDITION_EXPORT_CONFIG,
|
|
18
|
+
loadConditionExportConfig,
|
|
19
|
+
resolveConditionExportConfig,
|
|
20
|
+
} from "./conditionExportConfig";
|
|
11
21
|
|
|
12
22
|
let configUtil = {
|
|
13
23
|
baseUrl: process.env.VUE_APP_BASE_API,
|
|
@@ -130,8 +140,14 @@ function getGrid(that, tableRef) {
|
|
|
130
140
|
showExportFieldDialog: false,
|
|
131
141
|
leafColumns: [],
|
|
132
142
|
columns: [],
|
|
133
|
-
queryParam: {},
|
|
134
|
-
isMinimize: false,
|
|
143
|
+
queryParam: {},
|
|
144
|
+
isMinimize: false,
|
|
145
|
+
// 条件导出在本次任务内使用的配置快照。逻辑参数只在开始时读取一次,避免中途变更
|
|
146
|
+
// 导致前后页使用不同的分页/分卷口径。
|
|
147
|
+
conditionExportMode: false,
|
|
148
|
+
conditionExportConfig: { ...DEFAULT_CONDITION_EXPORT_CONFIG },
|
|
149
|
+
// 不查总数时,处理过程中分母显示「...」;文件合并成功后才回填实际完成数。
|
|
150
|
+
totalSizeKnown: true,
|
|
135
151
|
// 定时器必须放实例上:模块级共享会导致并发导出互相清除对方的定时器
|
|
136
152
|
exportTimer: null,
|
|
137
153
|
countTimer: null,
|
|
@@ -146,9 +162,14 @@ function getGrid(that, tableRef) {
|
|
|
146
162
|
// $route.path」现查,用户在导出期间切了页签(弹框可最小化,切走完全合法)
|
|
147
163
|
// 解的就是另一把锁 —— 原页签会永久 affix,而 tagsView 的 delOthersViews /
|
|
148
164
|
// delAllViews 都保留 affix,「关闭其他」「全部关闭」也删不掉它,只能刷新页面。
|
|
149
|
-
lockedView: null,
|
|
150
|
-
};
|
|
151
|
-
},
|
|
165
|
+
lockedView: null,
|
|
166
|
+
};
|
|
167
|
+
},
|
|
168
|
+
computed: {
|
|
169
|
+
exportTotalText() {
|
|
170
|
+
return this.totalSizeKnown ? this.tTotalSize : "...";
|
|
171
|
+
},
|
|
172
|
+
},
|
|
152
173
|
created() {},
|
|
153
174
|
mounted() {
|
|
154
175
|
// this.exc();
|
|
@@ -256,13 +277,29 @@ function getGrid(that, tableRef) {
|
|
|
256
277
|
this.param.destroyComponent(loadingObj);
|
|
257
278
|
}, 0);
|
|
258
279
|
},
|
|
259
|
-
dialogPrimary2() {
|
|
280
|
+
dialogPrimary2() {
|
|
260
281
|
// this.showUserDialog=false
|
|
261
282
|
this.$emit("confirm");
|
|
262
283
|
this.$emit("close");
|
|
263
|
-
this.clearExportTimer();
|
|
264
|
-
},
|
|
265
|
-
|
|
284
|
+
this.clearExportTimer();
|
|
285
|
+
},
|
|
286
|
+
/**
|
|
287
|
+
* 读取并固化本次条件导出的全局配置。单次按钮/脚本参数已经在 option 中完成合并,
|
|
288
|
+
* resolveConditionExportConfig 会让它们覆盖同名的全局配置。
|
|
289
|
+
*/
|
|
290
|
+
prepareConditionExportConfig() {
|
|
291
|
+
this.conditionExportMode = isConditionExport(this.option.type);
|
|
292
|
+
this.totalSizeKnown = true;
|
|
293
|
+
if (!this.conditionExportMode) return Promise.resolve();
|
|
294
|
+
return loadConditionExportConfig().then((globalConfig) => {
|
|
295
|
+
this.conditionExportConfig = resolveConditionExportConfig(
|
|
296
|
+
globalConfig,
|
|
297
|
+
this.option
|
|
298
|
+
);
|
|
299
|
+
this.totalSizeKnown = this.conditionExportConfig.searchCount;
|
|
300
|
+
});
|
|
301
|
+
},
|
|
302
|
+
startProcess() {
|
|
266
303
|
this.lockMenu();
|
|
267
304
|
this.createCountTimer();
|
|
268
305
|
this.tableTarget = getGrid(this.option.vue, this.option.targetRef);
|
|
@@ -296,47 +333,62 @@ function getGrid(that, tableRef) {
|
|
|
296
333
|
this.$t1("无法确定导出服务前缀,请在导出配置中指定 prefix")
|
|
297
334
|
);
|
|
298
335
|
return;
|
|
299
|
-
}
|
|
300
|
-
this.CURRENT_PREFIX = options.prefix;
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
},
|
|
338
|
-
getExportPageSize() {
|
|
339
|
-
let
|
|
336
|
+
}
|
|
337
|
+
this.CURRENT_PREFIX = options.prefix;
|
|
338
|
+
this.title = title;
|
|
339
|
+
that.tTotalPage = 0;
|
|
340
|
+
that.tTotalSize = 0;
|
|
341
|
+
that.prepareConditionExportConfig().then(() => {
|
|
342
|
+
if (that.isExportStopped()) return;
|
|
343
|
+
// 取数走 originOption.exportAjax 时请求由 xform 侧构造,前端拿不到那个 config,
|
|
344
|
+
// 只能把令牌顺着导出参数带过去(data-table-mixin 的 exportAjax 会塞进
|
|
345
|
+
// customParam.config,最终由 formHttp 的 ...opts 透传给 axios)
|
|
346
|
+
options.cancelToken = that.getCancelToken();
|
|
347
|
+
that
|
|
348
|
+
.createExcelFile()
|
|
349
|
+
.then((resultMsg) => {
|
|
350
|
+
if (that.isExportStopped()) return;
|
|
351
|
+
if (resultMsg.type === "success") {
|
|
352
|
+
let aObj = resultMsg.objx;
|
|
353
|
+
that.uuid = aObj.uuid;
|
|
354
|
+
that.nowDate = aObj.nowDate;
|
|
355
|
+
that.ippaaapp = aObj.ippaaapp;
|
|
356
|
+
setTimeout(function () {
|
|
357
|
+
if (that.isExportStopped()) return;
|
|
358
|
+
that.handleLoopToDo();
|
|
359
|
+
}, 300);
|
|
360
|
+
} else {
|
|
361
|
+
that.abortExport();
|
|
362
|
+
that.showImportDialog = false;
|
|
363
|
+
that.showImportDialog2 = false;
|
|
364
|
+
}
|
|
365
|
+
})
|
|
366
|
+
.catch((error) => {
|
|
367
|
+
if (that.isExportStopped()) return;
|
|
368
|
+
console.error(error);
|
|
369
|
+
that.abortExport(that.$t1("创建导出文件失败,导出已中止"));
|
|
370
|
+
that.showImportDialog = false;
|
|
371
|
+
that.showImportDialog2 = false;
|
|
372
|
+
});
|
|
373
|
+
});
|
|
374
|
+
},
|
|
375
|
+
getExportPageSize() {
|
|
376
|
+
let configuredPageSize = this.conditionExportMode
|
|
377
|
+
? this.conditionExportConfig.pageSize
|
|
378
|
+
: this.option.pageSize || 1000;
|
|
379
|
+
// 条件导出的按钮/脚本值已经按优先级写进配置快照,不再用全局默认值 1000
|
|
380
|
+
// 反向封顶;非条件导出保持原有最多 1000 的行为。
|
|
381
|
+
let pageSize = this.conditionExportMode
|
|
382
|
+
? configuredPageSize
|
|
383
|
+
: Math.min(configuredPageSize, 1000);
|
|
384
|
+
if (this.conditionExportMode) {
|
|
385
|
+
// 单页本身不能突破总量或单文件上限,否则无法在页级合并时兑现硬上限。
|
|
386
|
+
pageSize = Math.min(
|
|
387
|
+
pageSize,
|
|
388
|
+
this.conditionExportConfig.maxQueryTotal,
|
|
389
|
+
this.conditionExportConfig.limitFileSize
|
|
390
|
+
);
|
|
391
|
+
}
|
|
340
392
|
let showImageAtTable = this.option.showImageAtTable || false;
|
|
341
393
|
let hasExportImage = !!this.leafColumns.find((item) => {
|
|
342
394
|
let exportType = item?.params?.exportType;
|
|
@@ -359,17 +411,19 @@ function getGrid(that, tableRef) {
|
|
|
359
411
|
}
|
|
360
412
|
return pageSize;
|
|
361
413
|
},
|
|
362
|
-
hadleMergeExcel(pPageSize) {
|
|
414
|
+
hadleMergeExcel(pPageSize) {
|
|
363
415
|
if (this.isExportStopped()) return;
|
|
364
416
|
let that = this;
|
|
365
417
|
let title = this.title;
|
|
366
418
|
let options = this.option;
|
|
367
419
|
// let pPageSize = this.getExportPageSize();
|
|
368
|
-
let limitFileSize =
|
|
420
|
+
let limitFileSize = this.conditionExportMode
|
|
421
|
+
? this.conditionExportConfig.limitFileSize
|
|
422
|
+
: options.limitFileSize || 100000;
|
|
369
423
|
let limitThreadNum = options.limitThreadNum || 5;
|
|
370
424
|
let totalPages = this.tTotalPage || 1;
|
|
371
425
|
|
|
372
|
-
let kTotalPages = parseInt(limitFileSize / pPageSize);
|
|
426
|
+
let kTotalPages = Math.max(parseInt(limitFileSize / pPageSize), 1);
|
|
373
427
|
|
|
374
428
|
let fileNum = parseInt(totalPages / kTotalPages);
|
|
375
429
|
if (totalPages % kTotalPages !== 0) {
|
|
@@ -438,20 +492,195 @@ function getGrid(that, tableRef) {
|
|
|
438
492
|
});
|
|
439
493
|
// 注意:此处不能同步 clearExportTimer,否则计时统计会在合并完成前被提前停掉
|
|
440
494
|
}
|
|
441
|
-
};
|
|
442
|
-
loopDo();
|
|
443
|
-
},
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
let
|
|
447
|
-
let
|
|
448
|
-
let
|
|
449
|
-
|
|
450
|
-
let
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
495
|
+
};
|
|
496
|
+
loopDo();
|
|
497
|
+
},
|
|
498
|
+
/** 统一组装一页条件导出的取数请求,保证两种查总数模式使用完全相同的查询条件。 */
|
|
499
|
+
async requestExportPage(pageNumber, pageSize, searchCount) {
|
|
500
|
+
let options = this.option;
|
|
501
|
+
let originOption = this.tableTarget.params.originOption;
|
|
502
|
+
let url = originOption.exportPath || originOption.path;
|
|
503
|
+
let params = this.$baseLodash.cloneDeep(this.queryParam);
|
|
504
|
+
let aParam = {
|
|
505
|
+
current: pageNumber,
|
|
506
|
+
size: pageSize,
|
|
507
|
+
nowDate: this.nowDate ?? options.nowDate,
|
|
508
|
+
searchCount,
|
|
509
|
+
};
|
|
510
|
+
let cpParam;
|
|
511
|
+
if (originOption.vform === true) {
|
|
512
|
+
params.conditions = params.conditions || {};
|
|
513
|
+
cpParam = params.conditions;
|
|
514
|
+
} else {
|
|
515
|
+
cpParam = params;
|
|
516
|
+
}
|
|
517
|
+
Object.assign(cpParam, aParam);
|
|
518
|
+
|
|
519
|
+
if (originOption.exportAjax) {
|
|
520
|
+
return originOption.exportAjax(aParam, {
|
|
521
|
+
...options,
|
|
522
|
+
exportQuerySnapshot: this.$baseLodash.cloneDeep(this.queryParam),
|
|
523
|
+
});
|
|
524
|
+
}
|
|
525
|
+
// URL 上若写死 searchCount,会与本次模式冲突;实际值统一由请求体控制。
|
|
526
|
+
let resolvedUrl = typeof url === "function" ? url() : url;
|
|
527
|
+
if (typeof resolvedUrl !== "string" || !resolvedUrl) {
|
|
528
|
+
throw new Error("无效的导出查询地址");
|
|
529
|
+
}
|
|
530
|
+
let requestUrl = resolvedUrl
|
|
531
|
+
.replace("searchCount=false", "1=1")
|
|
532
|
+
.replace("searchCount=true", "1=1");
|
|
533
|
+
let finalParams = params;
|
|
534
|
+
if (originOption.paramHandle) {
|
|
535
|
+
finalParams = originOption.paramHandle(params) || {};
|
|
536
|
+
}
|
|
537
|
+
return this.$commonHttp({
|
|
538
|
+
aes: originOption.aes || false,
|
|
539
|
+
url: requestUrl,
|
|
540
|
+
method: "post",
|
|
541
|
+
data: finalParams,
|
|
542
|
+
modal: false,
|
|
543
|
+
queryCreateInfo: originOption.queryCreateInfo,
|
|
544
|
+
addCreateInfo: originOption.addCreateInfo,
|
|
545
|
+
cancelToken: this.getCancelToken(),
|
|
546
|
+
});
|
|
547
|
+
},
|
|
548
|
+
/** 导出尚在取数/合并时最多显示 99%,100% 只由 completeExport 设置。 */
|
|
549
|
+
updateExportProgress(doneSize, progressTotal) {
|
|
550
|
+
this.doneSize = parseInt(doneSize);
|
|
551
|
+
let percentage = progressTotal > 0 ? (doneSize * 100) / progressTotal : 99;
|
|
552
|
+
if (percentage > 0 && percentage < 1) percentage = 1;
|
|
553
|
+
if (percentage >= 100) percentage = 99;
|
|
554
|
+
this.percentageNum = parseInt(percentage);
|
|
555
|
+
},
|
|
556
|
+
/**
|
|
557
|
+
* 不查询总数:每页都发 searchCount=false,以 records.length < pageSize 判定末页。
|
|
558
|
+
* 取数与写入按页串行,确保发现末页或达到最大查询总数后不会继续派发多余请求。
|
|
559
|
+
*/
|
|
560
|
+
handleLoopWithoutCount(pageSize) {
|
|
561
|
+
let that = this;
|
|
562
|
+
let maxQueryTotal = this.conditionExportConfig.maxQueryTotal;
|
|
563
|
+
let maxPages = Math.max(Math.ceil(maxQueryTotal / pageSize), 1);
|
|
564
|
+
let doneSize = 0;
|
|
565
|
+
this.tTotalPage = 0;
|
|
566
|
+
this.tTotalSize = 0;
|
|
567
|
+
this.totalSizeKnown = false;
|
|
568
|
+
|
|
569
|
+
let finish = function (lastPage) {
|
|
570
|
+
if (that.isExportStopped()) return;
|
|
571
|
+
that.tTotalPage = Math.max(lastPage, 1);
|
|
572
|
+
that.hadleMergeExcel(pageSize);
|
|
573
|
+
};
|
|
574
|
+
|
|
575
|
+
let fetchPage = function (pageNumber, retryCount = 0) {
|
|
576
|
+
if (that.isExportStopped()) return Promise.resolve(null);
|
|
577
|
+
return that
|
|
578
|
+
.requestExportPage(pageNumber, pageSize, false)
|
|
579
|
+
.then((resultMsg) => {
|
|
580
|
+
if (resultMsg && resultMsg.type === "success") return resultMsg;
|
|
581
|
+
if (retryCount < 1) {
|
|
582
|
+
return new Promise((resolve) => {
|
|
583
|
+
setTimeout(
|
|
584
|
+
() => resolve(fetchPage(pageNumber, retryCount + 1)),
|
|
585
|
+
500
|
|
586
|
+
);
|
|
587
|
+
});
|
|
588
|
+
}
|
|
589
|
+
that.abortExport();
|
|
590
|
+
return null;
|
|
591
|
+
})
|
|
592
|
+
.catch((error) => {
|
|
593
|
+
if (that.isExportStopped()) return null;
|
|
594
|
+
if (retryCount < 1) {
|
|
595
|
+
return new Promise((resolve) => {
|
|
596
|
+
setTimeout(
|
|
597
|
+
() => resolve(fetchPage(pageNumber, retryCount + 1)),
|
|
598
|
+
500
|
|
599
|
+
);
|
|
600
|
+
});
|
|
601
|
+
}
|
|
602
|
+
console.error(error);
|
|
603
|
+
that.abortExport(
|
|
604
|
+
that.$t1("第{n}页数据拉取失败,导出已中止", {
|
|
605
|
+
n: pageNumber,
|
|
606
|
+
})
|
|
607
|
+
);
|
|
608
|
+
return null;
|
|
609
|
+
});
|
|
610
|
+
};
|
|
611
|
+
|
|
612
|
+
let appendPage = function (pageNumber) {
|
|
613
|
+
fetchPage(pageNumber).then((resultMsg) => {
|
|
614
|
+
if (!resultMsg || that.isExportStopped()) return;
|
|
615
|
+
let page = resultMsg.objx || {};
|
|
616
|
+
let actualSize = Number(page.size || page.pageSize || pageSize);
|
|
617
|
+
if (!Number.isSafeInteger(actualSize) || actualSize <= 0
|
|
618
|
+
|| actualSize > pageSize || (pageNumber > 1 && actualSize !== pageSize)) {
|
|
619
|
+
that.abortExport(that.$t1("服务端分页大小发生变化,导出已中止"));
|
|
620
|
+
return;
|
|
621
|
+
}
|
|
622
|
+
pageSize = actualSize;
|
|
623
|
+
maxPages = Math.max(Math.ceil(maxQueryTotal / pageSize), 1);
|
|
624
|
+
let rawRows = Array.isArray(page.records) ? page.records : [];
|
|
625
|
+
let hasNext = rawRows.length >= pageSize;
|
|
626
|
+
|
|
627
|
+
// 整页数据需要再探测一页;探测到的空页不写入,也不参与合并。
|
|
628
|
+
if (pageNumber > 1 && rawRows.length === 0) {
|
|
629
|
+
finish(pageNumber - 1);
|
|
630
|
+
return;
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
let remaining = Math.max(maxQueryTotal - doneSize, 0);
|
|
634
|
+
let rows = rawRows.slice(0, remaining);
|
|
635
|
+
let reachedLimit = rows.length >= remaining;
|
|
636
|
+
page.current = pageNumber;
|
|
637
|
+
page.pageNumber = pageNumber;
|
|
638
|
+
page.size = pageSize;
|
|
639
|
+
page.pageSize = pageSize;
|
|
640
|
+
page.records = rows;
|
|
641
|
+
|
|
642
|
+
that
|
|
643
|
+
.addExcelData({ rows, pageNumber })
|
|
644
|
+
.then((appendResult) => {
|
|
645
|
+
if (that.isExportStopped()) return;
|
|
646
|
+
if (!appendResult || appendResult.type !== "success") {
|
|
647
|
+
if (appendResult && appendResult.type === "abort") return;
|
|
648
|
+
that.abortExport();
|
|
649
|
+
return;
|
|
650
|
+
}
|
|
651
|
+
doneSize += rows.length;
|
|
652
|
+
that.updateExportProgress(doneSize, maxQueryTotal);
|
|
653
|
+
if (reachedLimit || !hasNext || pageNumber >= maxPages) {
|
|
654
|
+
finish(pageNumber);
|
|
655
|
+
return;
|
|
656
|
+
}
|
|
657
|
+
appendPage(pageNumber + 1);
|
|
658
|
+
})
|
|
659
|
+
.catch((error) => {
|
|
660
|
+
if (that.isExportStopped()) return;
|
|
661
|
+
console.error(error);
|
|
662
|
+
that.abortExport(that.$t1("导出数据写入失败,导出已中止"));
|
|
663
|
+
});
|
|
664
|
+
});
|
|
665
|
+
};
|
|
666
|
+
|
|
667
|
+
appendPage(1);
|
|
668
|
+
},
|
|
669
|
+
handleLoopToDo() {
|
|
670
|
+
let that = this;
|
|
671
|
+
let num = 0;
|
|
672
|
+
let options = this.option;
|
|
673
|
+
|
|
674
|
+
let pPageSize = this.getExportPageSize();
|
|
675
|
+
let limitThreadNum = options.limitThreadNum || 5;
|
|
676
|
+
|
|
677
|
+
if (
|
|
678
|
+
this.conditionExportMode
|
|
679
|
+
&& this.conditionExportConfig.searchCount === false
|
|
680
|
+
) {
|
|
681
|
+
this.handleLoopWithoutCount(pPageSize);
|
|
682
|
+
return;
|
|
683
|
+
}
|
|
455
684
|
|
|
456
685
|
/**处理返回值*/
|
|
457
686
|
this.doneSize = 0;
|
|
@@ -478,39 +707,15 @@ function getGrid(that, tableRef) {
|
|
|
478
707
|
rows: resultMsg.objx.records,
|
|
479
708
|
pageNumber: pageNumber,
|
|
480
709
|
})
|
|
481
|
-
.then(function (resultMsg2) {
|
|
482
|
-
releaseWindow();
|
|
483
|
-
let data = resultMsg.objx;
|
|
484
|
-
let
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
let pageNumber = data.pageNumber || 1;
|
|
491
|
-
let k = (excedNum * 100) / totalPages;
|
|
492
|
-
if (k > 0 && k < 1) {
|
|
493
|
-
k = 1;
|
|
494
|
-
}
|
|
495
|
-
if (k > 100) k = 100;
|
|
496
|
-
let cTotal = that.tTotalSize;
|
|
497
|
-
let pageSize = data.pageSize;
|
|
498
|
-
// let datas = data.records;
|
|
499
|
-
let size = data.records.length;
|
|
500
|
-
cSize = cSize + size;
|
|
501
|
-
|
|
502
|
-
let ttNum = cSize + "/" + cTotal;
|
|
503
|
-
let percentageStr = parseInt(k) + "%";
|
|
504
|
-
|
|
505
|
-
let percentageNum = k;
|
|
506
|
-
if (percentageNum >= 100) {
|
|
507
|
-
percentageNum = 99;
|
|
508
|
-
}
|
|
509
|
-
// that.$set(that, "doneSize", parseInt(cSize));
|
|
510
|
-
// that.$set(that, "percentageNum", parseInt(percentageNum));
|
|
511
|
-
|
|
512
|
-
that.doneSize = parseInt(cSize);
|
|
513
|
-
that.percentageNum = parseInt(percentageNum);
|
|
710
|
+
.then(function (resultMsg2) {
|
|
711
|
+
releaseWindow();
|
|
712
|
+
let data = resultMsg.objx;
|
|
713
|
+
let totalPages = that.tTotalPage || 1;
|
|
714
|
+
if (resultMsg2.type === "success") {
|
|
715
|
+
excedNum++;
|
|
716
|
+
let size = data.records.length;
|
|
717
|
+
cSize = cSize + size;
|
|
718
|
+
that.updateExportProgress(cSize, that.tTotalSize);
|
|
514
719
|
|
|
515
720
|
if (totalPages === 0 || excedNum >= totalPages) {
|
|
516
721
|
that.hadleMergeExcel(data.pageSize);
|
|
@@ -605,113 +810,49 @@ function getGrid(that, tableRef) {
|
|
|
605
810
|
});
|
|
606
811
|
};
|
|
607
812
|
|
|
608
|
-
let waitReqNum = 0;
|
|
609
|
-
let
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
searchCount: flag !== 1,
|
|
652
|
-
};
|
|
653
|
-
let cpParam;
|
|
654
|
-
if (originOption.vform === true) {
|
|
655
|
-
params.conditions = params.conditions || {};
|
|
656
|
-
cpParam = params.conditions;
|
|
657
|
-
} else {
|
|
658
|
-
cpParam = params;
|
|
659
|
-
}
|
|
660
|
-
Object.assign(cpParam, aParam);
|
|
661
|
-
|
|
662
|
-
if (!originOption.exportAjax) {
|
|
663
|
-
let turl = url.replace("searchCount=false", "1=1");
|
|
664
|
-
let finaParams = params;
|
|
665
|
-
if (originOption.paramHandle) {
|
|
666
|
-
finaParams = originOption.paramHandle
|
|
667
|
-
? originOption.paramHandle(params) || {}
|
|
668
|
-
: {};
|
|
669
|
-
}
|
|
670
|
-
promise = that.$commonHttp({
|
|
671
|
-
aes: originOption.aes || false,
|
|
672
|
-
url: turl,
|
|
673
|
-
method: "post",
|
|
674
|
-
data: finaParams,
|
|
675
|
-
modal: false,
|
|
676
|
-
queryCreateInfo: originOption.queryCreateInfo,
|
|
677
|
-
addCreateInfo: originOption.addCreateInfo,
|
|
678
|
-
cancelToken: that.getCancelToken(),
|
|
679
|
-
});
|
|
680
|
-
} else {
|
|
681
|
-
promise = originOption.exportAjax(aParam, options);
|
|
682
|
-
}
|
|
683
|
-
|
|
684
|
-
promise
|
|
685
|
-
.then(function (resultMsg) {
|
|
686
|
-
if (resultMsg.type === "success") {
|
|
687
|
-
let objx = resultMsg.objx;
|
|
688
|
-
objx.pageNumber = objx.current || 1;
|
|
689
|
-
objx.totalPages = objx.pages || 1;
|
|
690
|
-
objx.pageSize = objx.size;
|
|
691
|
-
let size = objx.records.length;
|
|
692
|
-
if (flag === 0) {
|
|
693
|
-
that.tTotalPage = objx.pages;
|
|
694
|
-
// that.tTotalSize = objx.total;
|
|
695
|
-
setTimeout(function () {
|
|
696
|
-
that.$set(that, "tTotalSize", objx.total);
|
|
697
|
-
}, 0);
|
|
698
|
-
let tTotalPage = objx.pages;
|
|
699
|
-
let tTotalSize = objx.total;
|
|
700
|
-
let ttNum = 0 + "/" + objx.total;
|
|
701
|
-
|
|
702
|
-
let opNum = limitFileSize;
|
|
703
|
-
let kTotalPages = parseInt(opNum / objx.size);
|
|
704
|
-
|
|
705
|
-
let fileNum = parseInt(tTotalPage / kTotalPages);
|
|
706
|
-
if (tTotalPage % kTotalPages !== 0) {
|
|
707
|
-
fileNum = fileNum + 1;
|
|
708
|
-
}
|
|
709
|
-
if (
|
|
710
|
-
size > 0 ||
|
|
711
|
-
objx.totalPages > 0 ||
|
|
712
|
-
objx.pageNumber < objx.totalPages
|
|
713
|
-
) {
|
|
714
|
-
that.exportTimer = setInterval(function () {
|
|
813
|
+
let waitReqNum = 0;
|
|
814
|
+
let loopToDo = function (flag, pageNumber, retryCount = 0) {
|
|
815
|
+
// 取消后不再发起新页,也不再重试(重试是从 .catch 里递归回来的)
|
|
816
|
+
if (that.isExportStopped()) return;
|
|
817
|
+
let maxWaitNum = limitThreadNum;
|
|
818
|
+
if (flag !== 1) waitReqNum = 0;
|
|
819
|
+
|
|
820
|
+
that
|
|
821
|
+
.requestExportPage(pageNumber, pPageSize, flag !== 1)
|
|
822
|
+
.then(function (resultMsg) {
|
|
823
|
+
if (resultMsg.type === "success") {
|
|
824
|
+
let objx = resultMsg.objx || {};
|
|
825
|
+
objx.records = Array.isArray(objx.records) ? objx.records : [];
|
|
826
|
+
objx.pageNumber = objx.current || pageNumber;
|
|
827
|
+
objx.pageSize = objx.size || pPageSize;
|
|
828
|
+
let actualSize = Number(objx.pageSize);
|
|
829
|
+
if (!Number.isSafeInteger(actualSize) || actualSize <= 0
|
|
830
|
+
|| actualSize > pPageSize || (flag !== 0 && actualSize !== pPageSize)) {
|
|
831
|
+
that.abortExport(that.$t1("服务端分页大小发生变化,导出已中止"));
|
|
832
|
+
return;
|
|
833
|
+
}
|
|
834
|
+
pPageSize = actualSize;
|
|
835
|
+
objx.pageSize = actualSize;
|
|
836
|
+
let size = objx.records.length;
|
|
837
|
+
if (flag === 0) {
|
|
838
|
+
let rawTotal = Number(objx.total);
|
|
839
|
+
if (!Number.isFinite(rawTotal) || rawTotal < 0) {
|
|
840
|
+
rawTotal = size;
|
|
841
|
+
}
|
|
842
|
+
let exportTotal = that.conditionExportMode
|
|
843
|
+
? Math.min(
|
|
844
|
+
rawTotal,
|
|
845
|
+
that.conditionExportConfig.maxQueryTotal
|
|
846
|
+
)
|
|
847
|
+
: rawTotal;
|
|
848
|
+
that.tTotalPage = that.conditionExportMode
|
|
849
|
+
? Math.max(Math.ceil(exportTotal / pPageSize), 1)
|
|
850
|
+
: objx.pages;
|
|
851
|
+
objx.totalPages = that.tTotalPage || 1;
|
|
852
|
+
that.tTotalSize = exportTotal;
|
|
853
|
+
let tTotalPage = that.tTotalPage || 1;
|
|
854
|
+
if (tTotalPage > 1) {
|
|
855
|
+
that.exportTimer = setInterval(function () {
|
|
715
856
|
if (waitReqNum < maxWaitNum && num < tTotalPage) {
|
|
716
857
|
waitReqNum++;
|
|
717
858
|
num++;
|
|
@@ -726,9 +867,15 @@ function getGrid(that, tableRef) {
|
|
|
726
867
|
}, 100);
|
|
727
868
|
} else {
|
|
728
869
|
clearInterval(that.exportTimer);
|
|
729
|
-
that.exportTimer = null;
|
|
730
|
-
}
|
|
731
|
-
}
|
|
870
|
+
that.exportTimer = null;
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
if (that.conditionExportMode) {
|
|
874
|
+
// 总数超过有效上限时,最后一页只写允许范围内的数据。
|
|
875
|
+
let rowOffset = (pageNumber - 1) * pPageSize;
|
|
876
|
+
let allowedRows = Math.max(that.tTotalSize - rowOffset, 0);
|
|
877
|
+
objx.records = objx.records.slice(0, allowedRows);
|
|
878
|
+
}
|
|
732
879
|
// 注意:此处不再释放并发窗口。拉取完成只是这一页做完了一半,
|
|
733
880
|
// 窗口由 handleData 在上送(addExcelData)落地后释放,见那里的注释。
|
|
734
881
|
|
|
@@ -898,14 +1045,14 @@ function getGrid(that, tableRef) {
|
|
|
898
1045
|
}
|
|
899
1046
|
let cUUid = this.uuid;
|
|
900
1047
|
let ippaaapp = this.ippaaapp;
|
|
901
|
-
let url1
|
|
902
|
-
this.CURRENT_PREFIX
|
|
903
|
-
"/excel/appendExcelData?uuid="
|
|
904
|
-
cUUid
|
|
905
|
-
"&ippaaapp="
|
|
906
|
-
ippaaapp
|
|
907
|
-
"&pageNumber="
|
|
908
|
-
pageNumber;
|
|
1048
|
+
let url1
|
|
1049
|
+
= this.CURRENT_PREFIX
|
|
1050
|
+
+ "/excel/appendExcelData?uuid="
|
|
1051
|
+
+ cUUid
|
|
1052
|
+
+ "&ippaaapp="
|
|
1053
|
+
+ ippaaapp
|
|
1054
|
+
+ "&pageNumber="
|
|
1055
|
+
+ pageNumber;
|
|
909
1056
|
return this.$http({
|
|
910
1057
|
url: url1,
|
|
911
1058
|
method: "post",
|
|
@@ -919,12 +1066,12 @@ function getGrid(that, tableRef) {
|
|
|
919
1066
|
});
|
|
920
1067
|
},
|
|
921
1068
|
mergeExcel(startPage, endPage, loading) {
|
|
922
|
-
let url1
|
|
923
|
-
this.CURRENT_PREFIX
|
|
924
|
-
"/excel/mergeExcel?uuid="
|
|
925
|
-
this.uuid
|
|
926
|
-
"&ippaaapp="
|
|
927
|
-
this.ippaaapp;
|
|
1069
|
+
let url1
|
|
1070
|
+
= this.CURRENT_PREFIX
|
|
1071
|
+
+ "/excel/mergeExcel?uuid="
|
|
1072
|
+
+ this.uuid
|
|
1073
|
+
+ "&ippaaapp="
|
|
1074
|
+
+ this.ippaaapp;
|
|
928
1075
|
return this.$http({
|
|
929
1076
|
url: url1 + "&startPage=" + startPage + "&endPage=" + endPage,
|
|
930
1077
|
method: "post",
|
|
@@ -954,8 +1101,12 @@ function getGrid(that, tableRef) {
|
|
|
954
1101
|
* 合法的状态,那时页签必须能正常关闭 —— 解锁此前只挂在 beforeDestroy 上,
|
|
955
1102
|
* 用户不点「取消/确定」就永远解不开,正是「导出完成后页签关不掉」的来源。
|
|
956
1103
|
*/
|
|
957
|
-
completeExport() {
|
|
958
|
-
|
|
1104
|
+
completeExport() {
|
|
1105
|
+
if (!this.totalSizeKnown) {
|
|
1106
|
+
this.tTotalSize = this.doneSize;
|
|
1107
|
+
this.totalSizeKnown = true;
|
|
1108
|
+
}
|
|
1109
|
+
setTimeout(() => {
|
|
959
1110
|
if (this.isExportStopped()) return;
|
|
960
1111
|
this.percentageNum = parseInt(100);
|
|
961
1112
|
}, 100);
|
|
@@ -1011,10 +1162,10 @@ function getGrid(that, tableRef) {
|
|
|
1011
1162
|
return column.slots.filterVal(params);
|
|
1012
1163
|
}
|
|
1013
1164
|
let slotDefault = column.slots && column.slots.default;
|
|
1014
|
-
let hasRenderFn
|
|
1015
|
-
!!column.renderCell
|
|
1016
|
-
typeof slotDefault === "function"
|
|
1017
|
-
typeof slotDefault === "string";
|
|
1165
|
+
let hasRenderFn
|
|
1166
|
+
= !!column.renderCell
|
|
1167
|
+
|| typeof slotDefault === "function"
|
|
1168
|
+
|| typeof slotDefault === "string";
|
|
1018
1169
|
if (!hasRenderFn) {
|
|
1019
1170
|
let cellValue = params.row[column.field];
|
|
1020
1171
|
if (typeof column.formatter === "function") {
|
|
@@ -1072,8 +1223,8 @@ function getGrid(that, tableRef) {
|
|
|
1072
1223
|
// _columnIndex
|
|
1073
1224
|
};
|
|
1074
1225
|
let exportType = column.params?.exportType;
|
|
1075
|
-
let exportVal
|
|
1076
|
-
column.params && column.params.exportVal
|
|
1226
|
+
let exportVal
|
|
1227
|
+
= column.params && column.params.exportVal
|
|
1077
1228
|
? column.params.exportVal
|
|
1078
1229
|
: null;
|
|
1079
1230
|
if (exportVal) {
|
|
@@ -1089,16 +1240,16 @@ function getGrid(that, tableRef) {
|
|
|
1089
1240
|
} else if (exportType === "Number") {
|
|
1090
1241
|
resultStr = that.getExportCellValue(params);
|
|
1091
1242
|
if (
|
|
1092
|
-
resultStr !== null
|
|
1093
|
-
resultStr !== undefined
|
|
1094
|
-
resultStr !== ""
|
|
1095
|
-
!(resultStr + "").startsWith("[EXPNUM]")
|
|
1243
|
+
resultStr !== null
|
|
1244
|
+
&& resultStr !== undefined
|
|
1245
|
+
&& resultStr !== ""
|
|
1246
|
+
&& !(resultStr + "").startsWith("[EXPNUM]")
|
|
1096
1247
|
) {
|
|
1097
1248
|
resultStr = "[EXPNUM]" + resultStr;
|
|
1098
1249
|
}
|
|
1099
1250
|
} else if (
|
|
1100
|
-
exportType === "Image"
|
|
1101
|
-
(showImageAtTable && exportType === "Image2")
|
|
1251
|
+
exportType === "Image"
|
|
1252
|
+
|| (showImageAtTable && exportType === "Image2")
|
|
1102
1253
|
) {
|
|
1103
1254
|
// 取值刻意延到"确实用得上"的那条分支才做:附件的正常形态是数组,
|
|
1104
1255
|
// 那条分支会用 row[column.field] 自己拼 [EXPIMG],把取值结果整个覆盖;
|
|
@@ -1111,9 +1262,9 @@ function getGrid(that, tableRef) {
|
|
|
1111
1262
|
that.isPicture(item.extension)
|
|
1112
1263
|
);
|
|
1113
1264
|
if (items.length > 0) {
|
|
1114
|
-
resultStr
|
|
1115
|
-
"[EXPIMG]"
|
|
1116
|
-
items
|
|
1265
|
+
resultStr
|
|
1266
|
+
= "[EXPIMG]"
|
|
1267
|
+
+ items
|
|
1117
1268
|
.map((item) => {
|
|
1118
1269
|
let url = item.large || item.medium;
|
|
1119
1270
|
return item.domain + url;
|
|
@@ -1131,10 +1282,10 @@ function getGrid(that, tableRef) {
|
|
|
1131
1282
|
)
|
|
1132
1283
|
) {
|
|
1133
1284
|
if (
|
|
1134
|
-
resultStr !== null
|
|
1135
|
-
resultStr !== undefined
|
|
1136
|
-
resultStr !== ""
|
|
1137
|
-
!(resultStr + "").startsWith("[EXPIMG]")
|
|
1285
|
+
resultStr !== null
|
|
1286
|
+
&& resultStr !== undefined
|
|
1287
|
+
&& resultStr !== ""
|
|
1288
|
+
&& !(resultStr + "").startsWith("[EXPIMG]")
|
|
1138
1289
|
) {
|
|
1139
1290
|
resultStr = "[EXPIMG]" + resultStr;
|
|
1140
1291
|
}
|
|
@@ -1185,13 +1336,13 @@ function getGrid(that, tableRef) {
|
|
|
1185
1336
|
let cUUid = encodeURIComponent(row.uuid);
|
|
1186
1337
|
let ippaaapp = this.ippaaapp;
|
|
1187
1338
|
let fileName = row.title;
|
|
1188
|
-
let fileUrl
|
|
1189
|
-
configUtil.baseUrl
|
|
1190
|
-
this.CURRENT_PREFIX
|
|
1191
|
-
"/excel/download?uuid="
|
|
1192
|
-
cUUid
|
|
1193
|
-
"&ippaaapp="
|
|
1194
|
-
ippaaapp;
|
|
1339
|
+
let fileUrl
|
|
1340
|
+
= configUtil.baseUrl
|
|
1341
|
+
+ this.CURRENT_PREFIX
|
|
1342
|
+
+ "/excel/download?uuid="
|
|
1343
|
+
+ cUUid
|
|
1344
|
+
+ "&ippaaapp="
|
|
1345
|
+
+ ippaaapp;
|
|
1195
1346
|
|
|
1196
1347
|
function downLoadFile2() {
|
|
1197
1348
|
let params = {
|
|
@@ -1201,8 +1352,8 @@ function getGrid(that, tableRef) {
|
|
|
1201
1352
|
|
|
1202
1353
|
let form = document.createElement("form");
|
|
1203
1354
|
|
|
1204
|
-
let randomNum
|
|
1205
|
-
new Date().valueOf() + Math.floor(Math.random() * 1000000);
|
|
1355
|
+
let randomNum
|
|
1356
|
+
= new Date().valueOf() + Math.floor(Math.random() * 1000000);
|
|
1206
1357
|
let formId = "formId-" + randomNum;
|
|
1207
1358
|
let formName = "formName-" + randomNum;
|
|
1208
1359
|
|
|
@@ -1287,8 +1438,8 @@ function getGrid(that, tableRef) {
|
|
|
1287
1438
|
this.tableTarget = getGrid(this.option.vue, this.option.targetRef);
|
|
1288
1439
|
let that = this;
|
|
1289
1440
|
let options = this.option;
|
|
1290
|
-
let title
|
|
1291
|
-
options.title || this.$t2("导出", "components.excelExport.title");
|
|
1441
|
+
let title
|
|
1442
|
+
= options.title || this.$t2("导出", "components.excelExport.title");
|
|
1292
1443
|
if (!options.prefix && options.prefix !== "") {
|
|
1293
1444
|
let originOption = this.tableTarget.params.originOption;
|
|
1294
1445
|
let path = originOption.exportPath || originOption.path;
|
|
@@ -44,6 +44,7 @@ import i18n from "../../../utils/i18n";
|
|
|
44
44
|
import fieldMixin from "./fieldMixin";
|
|
45
45
|
import StaticContentWrapper from "./static-content-wrapper.vue";
|
|
46
46
|
import { EXPORT_TYPE } from "../../../../excelExport/exportType";
|
|
47
|
+
import { pickConditionExportOverrides } from "@base/components/excelExport/conditionExportConfig";
|
|
47
48
|
|
|
48
49
|
export default {
|
|
49
50
|
name: "select-export-item-button-widget",
|
|
@@ -101,8 +102,8 @@ export default {
|
|
|
101
102
|
let opt = {
|
|
102
103
|
title: this.field.options.exportFileName || null,
|
|
103
104
|
targetRef: this.field.options.tableRef || null,
|
|
104
|
-
pageSize: this.field.options.exportPageSize || null,
|
|
105
105
|
showImageAtTable: this.field.options.showImageAtTable || null,
|
|
106
|
+
...pickConditionExportOverrides(this.field.options),
|
|
106
107
|
// 明细导出的列 / 脚本编码 / 取数参数三项各自独立:按钮上维护了哪项就以哪项为准,
|
|
107
108
|
// 留空的那项沿用数据表格属性上那套。参数脚本原样下发,由数据表格求值(this 是
|
|
108
109
|
// 表格组件,与配在表格属性上时同义)
|
package/src/components/xform/form-designer/form-widget/field-widget/table-export-button-widget.vue
CHANGED
|
@@ -32,6 +32,7 @@ import emitter from "../../../../../components/xform/utils/emitter";
|
|
|
32
32
|
import i18n from "../../../../../components/xform/utils/i18n";
|
|
33
33
|
import fieldMixin from "../../../../../components/xform/form-designer/form-widget/field-widget/fieldMixin";
|
|
34
34
|
import StaticContentWrapper from "../../../../../components/xform/form-designer/form-widget/field-widget/static-content-wrapper.vue";
|
|
35
|
+
import { pickConditionExportOverrides } from "@base/components/excelExport/conditionExportConfig";
|
|
35
36
|
|
|
36
37
|
export default {
|
|
37
38
|
name: "table-export-button-widget",
|
|
@@ -81,8 +82,8 @@ export default {
|
|
|
81
82
|
let opt = {
|
|
82
83
|
title: this.field.options.exportFileName || null,
|
|
83
84
|
targetRef: this.field.options.tableRef || null,
|
|
84
|
-
pageSize: this.field.options.exportPageSize || null,
|
|
85
85
|
showImageAtTable: this.field.options.showImageAtTable || null,
|
|
86
|
+
...pickConditionExportOverrides(this.field.options),
|
|
86
87
|
};
|
|
87
88
|
let tableExportParam = this.handleCustomEvent(this.field.options.tableExportParam);
|
|
88
89
|
let options = { ...opt, ...tableExportParam, type: type };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<base-input-number
|
|
3
|
+
:value="innerValue"
|
|
4
|
+
v-bind="$attrs"
|
|
5
|
+
v-on="listeners"
|
|
6
|
+
@input="onInput"
|
|
7
|
+
/>
|
|
8
|
+
</template>
|
|
9
|
+
|
|
10
|
+
<script>
|
|
11
|
+
/**
|
|
12
|
+
* 未配置(null / undefined / 非正数)时显示空白,而不是 el-input-number 默认的 0。
|
|
13
|
+
* 清空后回写 null,运行时会回落到全局逻辑参数。
|
|
14
|
+
*/
|
|
15
|
+
function toDisplayNumber(value) {
|
|
16
|
+
if (value == null || value === "") return undefined;
|
|
17
|
+
let num = Number(value);
|
|
18
|
+
if (!Number.isFinite(num) || num <= 0) return undefined;
|
|
19
|
+
return num;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function toStoredNumber(value) {
|
|
23
|
+
if (value == null || value === "") return null;
|
|
24
|
+
let num = Number(value);
|
|
25
|
+
if (!Number.isFinite(num) || num <= 0) return null;
|
|
26
|
+
return num;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export default {
|
|
30
|
+
name: "empty-number-input",
|
|
31
|
+
inheritAttrs: false,
|
|
32
|
+
props: {
|
|
33
|
+
value: {},
|
|
34
|
+
},
|
|
35
|
+
computed: {
|
|
36
|
+
innerValue() {
|
|
37
|
+
return toDisplayNumber(this.value);
|
|
38
|
+
},
|
|
39
|
+
listeners() {
|
|
40
|
+
let listeners = Object.assign({}, this.$listeners);
|
|
41
|
+
delete listeners.input;
|
|
42
|
+
return listeners;
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
methods: {
|
|
46
|
+
onInput(val) {
|
|
47
|
+
this.$emit("input", toStoredNumber(val));
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
</script>
|
|
@@ -19,10 +19,29 @@
|
|
|
19
19
|
></el-switch>
|
|
20
20
|
</el-form-item>
|
|
21
21
|
<el-form-item label="导出每页查询数量" class="form-item-label-top">
|
|
22
|
-
<
|
|
22
|
+
<empty-number-input
|
|
23
23
|
v-model="optionModel.exportPageSize"
|
|
24
24
|
:max="optionModel.showImageAtTable ? 150 : 1000"
|
|
25
|
-
|
|
25
|
+
:placeholder="'默认 ' + defaultPageSize"
|
|
26
|
+
></empty-number-input>
|
|
27
|
+
</el-form-item>
|
|
28
|
+
<el-form-item label="最大查询总数" class="form-item-label-top">
|
|
29
|
+
<empty-number-input
|
|
30
|
+
v-model="optionModel.maxQueryTotal"
|
|
31
|
+
:placeholder="'默认 ' + defaultMaxQueryTotal"
|
|
32
|
+
></empty-number-input>
|
|
33
|
+
<div class="export-item-columns-tip">
|
|
34
|
+
条件导出最多拉取的行数。留空则使用全局逻辑参数(默认 {{ defaultMaxQueryTotal }})
|
|
35
|
+
</div>
|
|
36
|
+
</el-form-item>
|
|
37
|
+
<el-form-item label="每个文件最大数据量" class="form-item-label-top">
|
|
38
|
+
<empty-number-input
|
|
39
|
+
v-model="optionModel.limitFileSize"
|
|
40
|
+
:placeholder="'默认 ' + defaultLimitFileSize"
|
|
41
|
+
></empty-number-input>
|
|
42
|
+
<div class="export-item-columns-tip">
|
|
43
|
+
单个 Excel 最多行数,超出则分多个文件。留空则使用全局逻辑参数(默认 {{ defaultLimitFileSize }})
|
|
44
|
+
</div>
|
|
26
45
|
</el-form-item>
|
|
27
46
|
<el-form-item label="导出参数" label-width="150px">
|
|
28
47
|
<a
|
|
@@ -80,12 +99,15 @@
|
|
|
80
99
|
import i18n from "../../../../utils/i18n";
|
|
81
100
|
import eventMixin from "../event-handler/eventMixin";
|
|
82
101
|
import exportItemColumnsDialog from "../container-data-table/exportItemColumns-dialog.vue";
|
|
102
|
+
import { DEFAULT_CONDITION_EXPORT_CONFIG } from "@base/components/excelExport/conditionExportConfig";
|
|
103
|
+
import emptyNumberInput from "./empty-number-input.vue";
|
|
83
104
|
|
|
84
105
|
export default {
|
|
85
106
|
name: "select-export-item-button-editor",
|
|
86
107
|
mixins: [i18n, eventMixin],
|
|
87
108
|
components: {
|
|
88
109
|
exportItemColumnsDialog,
|
|
110
|
+
emptyNumberInput,
|
|
89
111
|
},
|
|
90
112
|
props: {
|
|
91
113
|
designer: Object,
|
|
@@ -98,6 +120,9 @@ export default {
|
|
|
98
120
|
// 与数据表格属性面板同一套:脚本里可直接用 dataId / formCode
|
|
99
121
|
tableConfigParams: ["dataId", "formCode"],
|
|
100
122
|
showExportItemColumnsDialog: false,
|
|
123
|
+
defaultPageSize: DEFAULT_CONDITION_EXPORT_CONFIG.pageSize,
|
|
124
|
+
defaultMaxQueryTotal: DEFAULT_CONDITION_EXPORT_CONFIG.maxQueryTotal,
|
|
125
|
+
defaultLimitFileSize: DEFAULT_CONDITION_EXPORT_CONFIG.limitFileSize,
|
|
101
126
|
};
|
|
102
127
|
},
|
|
103
128
|
methods: {
|
|
@@ -13,8 +13,23 @@
|
|
|
13
13
|
<el-switch v-model="optionModel.showImageAtTable" @change="changeShowImageAtTable"></el-switch>
|
|
14
14
|
</el-form-item>
|
|
15
15
|
<el-form-item label="导出每页查询数量" class="form-item-label-top">
|
|
16
|
-
<
|
|
17
|
-
|
|
16
|
+
<empty-number-input v-model="optionModel.exportPageSize"
|
|
17
|
+
:max="optionModel.showImageAtTable?150:1000"
|
|
18
|
+
:placeholder="'默认 ' + defaultPageSize"></empty-number-input>
|
|
19
|
+
</el-form-item>
|
|
20
|
+
<el-form-item label="最大查询总数" class="form-item-label-top">
|
|
21
|
+
<empty-number-input v-model="optionModel.maxQueryTotal"
|
|
22
|
+
:placeholder="'默认 ' + defaultMaxQueryTotal"></empty-number-input>
|
|
23
|
+
<div class="export-limit-tip">
|
|
24
|
+
条件导出最多拉取的行数。留空则使用全局逻辑参数(默认 {{ defaultMaxQueryTotal }})
|
|
25
|
+
</div>
|
|
26
|
+
</el-form-item>
|
|
27
|
+
<el-form-item label="每个文件最大数据量" class="form-item-label-top">
|
|
28
|
+
<empty-number-input v-model="optionModel.limitFileSize"
|
|
29
|
+
:placeholder="'默认 ' + defaultLimitFileSize"></empty-number-input>
|
|
30
|
+
<div class="export-limit-tip">
|
|
31
|
+
单个 Excel 最多行数,超出则分多个文件。留空则使用全局逻辑参数(默认 {{ defaultLimitFileSize }})
|
|
32
|
+
</div>
|
|
18
33
|
</el-form-item>
|
|
19
34
|
<el-form-item label="导出参数" label-width="150px">
|
|
20
35
|
<a href="javascript:void(0);" class="a-link link-oneLind"
|
|
@@ -30,10 +45,15 @@
|
|
|
30
45
|
import i18n from "../../../../../../components/xform/utils/i18n";
|
|
31
46
|
import eventMixin
|
|
32
47
|
from "../../../../../../components/xform/form-designer/setting-panel/property-editor/event-handler/eventMixin";
|
|
48
|
+
import { DEFAULT_CONDITION_EXPORT_CONFIG } from "@base/components/excelExport/conditionExportConfig";
|
|
49
|
+
import emptyNumberInput from "./empty-number-input.vue";
|
|
33
50
|
|
|
34
51
|
export default {
|
|
35
52
|
name: "table-export-button-editor",
|
|
36
53
|
mixins: [i18n, eventMixin],
|
|
54
|
+
components: {
|
|
55
|
+
emptyNumberInput,
|
|
56
|
+
},
|
|
37
57
|
props: {
|
|
38
58
|
designer: Object,
|
|
39
59
|
selectedWidget: Object,
|
|
@@ -42,6 +62,9 @@ export default {
|
|
|
42
62
|
data() {
|
|
43
63
|
return {
|
|
44
64
|
eventParams: [],
|
|
65
|
+
defaultPageSize: DEFAULT_CONDITION_EXPORT_CONFIG.pageSize,
|
|
66
|
+
defaultMaxQueryTotal: DEFAULT_CONDITION_EXPORT_CONFIG.maxQueryTotal,
|
|
67
|
+
defaultLimitFileSize: DEFAULT_CONDITION_EXPORT_CONFIG.limitFileSize,
|
|
45
68
|
};
|
|
46
69
|
},
|
|
47
70
|
methods: {
|
|
@@ -57,4 +80,11 @@ export default {
|
|
|
57
80
|
};
|
|
58
81
|
</script>
|
|
59
82
|
|
|
60
|
-
<style scoped
|
|
83
|
+
<style scoped>
|
|
84
|
+
.export-limit-tip {
|
|
85
|
+
line-height: 18px;
|
|
86
|
+
color: #909399;
|
|
87
|
+
font-size: 12px;
|
|
88
|
+
margin-top: 4px;
|
|
89
|
+
}
|
|
90
|
+
</style>
|
|
@@ -3287,6 +3287,9 @@ export const advancedFields = [
|
|
|
3287
3287
|
tableRef: "",
|
|
3288
3288
|
tableExportParam: "",
|
|
3289
3289
|
showImageAtTable: false,
|
|
3290
|
+
exportPageSize: null,
|
|
3291
|
+
maxQueryTotal: null,
|
|
3292
|
+
limitFileSize: null,
|
|
3290
3293
|
tableExportFlag: 1,
|
|
3291
3294
|
|
|
3292
3295
|
onCreated: "",
|
|
@@ -3351,6 +3354,9 @@ export const advancedFields = [
|
|
|
3351
3354
|
tableRef: "",
|
|
3352
3355
|
tableExportParam: "",
|
|
3353
3356
|
showImageAtTable: false,
|
|
3357
|
+
exportPageSize: null,
|
|
3358
|
+
maxQueryTotal: null,
|
|
3359
|
+
limitFileSize: null,
|
|
3354
3360
|
selectExportItemFlag: 1,
|
|
3355
3361
|
exportItemConditionEnabled: !1,
|
|
3356
3362
|
// 按钮级明细导出配置:三项各自独立,留空的那项沿用数据表格属性上维护的
|
|
@@ -2798,7 +2798,9 @@ modules = {
|
|
|
2798
2798
|
if (
|
|
2799
2799
|
customParam?.exportParam?.type !== EXPORT_TYPE.ITEM_SELECTED
|
|
2800
2800
|
) {
|
|
2801
|
-
formData =
|
|
2801
|
+
formData = customParam?.exportParam?.exportQuerySnapshot !== undefined
|
|
2802
|
+
? this.$baseLodash.cloneDeep(customParam.exportParam.exportQuerySnapshot)
|
|
2803
|
+
: tableOption.param ? tableOption.param() || {} : {};
|
|
2802
2804
|
}
|
|
2803
2805
|
const queryParams = Object.assign({}, formData);
|
|
2804
2806
|
|