@nocobase/plugin-action-export 1.5.0-beta.9 → 1.5.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/dist/externalVersion.js +6 -6
- package/dist/locale/zh-CN.json +3 -3
- package/dist/node_modules/xlsx/package.json +1 -1
- package/dist/server/actions/export-xlsx.d.ts +1 -1
- package/dist/server/actions/export-xlsx.js +5 -2
- package/dist/server/index.d.ts +2 -0
- package/dist/server/index.js +8 -2
- package/dist/server/services/base-exporter.d.ts +40 -0
- package/dist/server/{xlsx-exporter.js → services/base-exporter.js} +46 -71
- package/dist/server/{xlsx-exporter.d.ts → services/xlsx-exporter.d.ts} +13 -27
- package/dist/server/services/xlsx-exporter.js +113 -0
- package/package.json +2 -2
package/dist/externalVersion.js
CHANGED
|
@@ -10,16 +10,16 @@
|
|
|
10
10
|
module.exports = {
|
|
11
11
|
"@formily/react": "2.3.0",
|
|
12
12
|
"@formily/shared": "2.3.2",
|
|
13
|
-
"@nocobase/client": "1.5.
|
|
13
|
+
"@nocobase/client": "1.5.1",
|
|
14
14
|
"react": "18.2.0",
|
|
15
15
|
"@formily/antd-v5": "1.1.9",
|
|
16
16
|
"react-i18next": "11.18.6",
|
|
17
17
|
"lodash": "4.17.21",
|
|
18
18
|
"file-saver": "2.0.5",
|
|
19
19
|
"antd": "5.12.8",
|
|
20
|
-
"@nocobase/server": "1.5.
|
|
21
|
-
"@nocobase/
|
|
22
|
-
"@nocobase/database": "1.5.
|
|
23
|
-
"
|
|
24
|
-
"
|
|
20
|
+
"@nocobase/server": "1.5.1",
|
|
21
|
+
"@nocobase/actions": "1.5.1",
|
|
22
|
+
"@nocobase/database": "1.5.1",
|
|
23
|
+
"async-mutex": "0.5.0",
|
|
24
|
+
"@nocobase/data-source-manager": "1.5.1"
|
|
25
25
|
};
|
package/dist/locale/zh-CN.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
|
-
"Export warning": "
|
|
3
|
-
"Start export": "
|
|
4
|
-
"another export action is running, please try again later.": "
|
|
2
|
+
"Export warning": "每次最多导出记录 {{limit}} 行数据,超出的将被忽略。",
|
|
3
|
+
"Start export": "开始导出记录",
|
|
4
|
+
"another export action is running, please try again later.": "另一导出记录任务正在运行,请稍后重试。",
|
|
5
5
|
"True": "是",
|
|
6
6
|
"False": "否"
|
|
7
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"xlsx","version":"0.20.2","author":"sheetjs","description":"SheetJS Spreadsheet data parser and writer","keywords":["excel","xls","xlsx","xlsb","xlsm","ods","csv","dbf","dif","sylk","office","spreadsheet"],"bin":{"xlsx":"./bin/xlsx.njs"},"main":"xlsx.js","module":"xlsx.mjs","unpkg":"dist/xlsx.full.min.js","jsdelivr":"dist/xlsx.full.min.js","types":"types/index.d.ts","exports":{".":{"import":"./xlsx.mjs","require":"./xlsx.js","types":"./types/index.d.ts"},"./xlsx.mjs":{"import":"./xlsx.mjs","types":"./types/index.d.ts"},"./xlsx.js":{"require":"./xlsx.js","types":"./types/index.d.ts"},"./dist/xlsx.core.min":{"import":"./dist/xlsx.core.min.js","require":"./dist/xlsx.core.min.js","types":"./types/index.d.ts"},"./dist/xlsx.core.min.js":{"import":"./dist/xlsx.core.min.js","require":"./dist/xlsx.core.min.js","types":"./types/index.d.ts"},"./dist/xlsx.full.min":{"import":"./dist/xlsx.full.min.js","require":"./dist/xlsx.full.min.js","types":"./types/index.d.ts"},"./dist/xlsx.full.min.js":{"import":"./dist/xlsx.full.min.js","require":"./dist/xlsx.full.min.js","types":"./types/index.d.ts"},"./dist/xlsx.mini.min":{"import":"./dist/xlsx.mini.min.js","require":"./dist/xlsx.mini.min.js","types":"./types/index.d.ts"},"./dist/xlsx.mini.min.js":{"import":"./dist/xlsx.mini.min.js","require":"./dist/xlsx.mini.min.js","types":"./types/index.d.ts"},"./dist/xlsx.zahl":{"import":"./dist/xlsx.zahl.mjs","require":"./dist/xlsx.zahl.js","types":"./dist/zahl.d.ts"},"./dist/xlsx.zahl.mjs":{"import":"./dist/xlsx.zahl.mjs","types":"./dist/zahl.d.ts"},"./dist/xlsx.zahl.js":{"require":"./dist/xlsx.zahl.js","types":"./dist/zahl.d.ts"},"./dist/cpexcel":{"import":"./dist/cpexcel.full.mjs","require":"./dist/cpexcel.js","types":"./dist/cpexcel.d.ts"},"./dist/cpexcel.js":{"require":"./dist/cpexcel.js","types":"./dist/cpexcel.d.ts"},"./dist/cpexcel.full":{"import":"./dist/cpexcel.full.mjs","require":"./dist/cpexcel.js","types":"./dist/cpexcel.d.ts"},"./dist/cpexcel.full.mjs":{"import":"./dist/cpexcel.full.mjs","types":"./dist/cpexcel.d.ts"}},"browser":{"buffer":false,"crypto":false,"stream":false,"process":false,"fs":false},"sideEffects":false,"dependencies":{},"devDependencies":{"@sheetjs/uglify-js":"~2.7.3","@types/node":"^8.5.9","acorn":"7.4.1","adler-32":"~1.3.1","alex":"8.1.1","blanket":"~1.2.3","cfb":"~1.2.2","codepage":"~1.15.0","commander":"~2.17.1","crc-32":"~1.2.2","dtslint":"^0.1.2","eslint":"7.23.0","eslint-plugin-html":"^6.1.2","eslint-plugin-json":"^2.1.2","exit-on-epipe":"~1.0.1","fflate":"^0.7.1","jsdom":"~11.1.0","markdown-spellcheck":"^1.3.1","mocha":"~2.5.3","sinon":"^1.17.7","ssf":"~0.11.2","typescript":"2.2.0","wmf":"~1.0.1","word":"~0.3.0"},"repository":{"type":"git","url":"https://git.sheetjs.com/SheetJS/sheetjs"},"scripts":{"pretest":"npm run lint","test":"npm run tests-only","pretest-only":"git submodule init && git submodule update","tests-only":"make travis","build":"make","lint":"make fullint","dtslint":"dtslint types"},"config":{"blanket":{"pattern":"xlsx.js"}},"alex":{"allow":["chinese","special","simple","just","crash","wtf","holes"]},"homepage":"https://sheetjs.com/","files":["CHANGELOG.md","LICENSE","README.md","bower.json","package.json","xlsx.js","xlsx.mjs","xlsxworker.js","bin/xlsx.njs","dist/LICENSE","dist/*.mjs","dist/*.js","dist/*.map","dist/*.d.ts","types/index.d.ts","types/tsconfig.json"],"bugs":{"url":"https://git.sheetjs.com/SheetJS/sheetjs/issues"},"license":"Apache-2.0","engines":{"node":">=0.8"},"_lastModified":"
|
|
1
|
+
{"name":"xlsx","version":"0.20.2","author":"sheetjs","description":"SheetJS Spreadsheet data parser and writer","keywords":["excel","xls","xlsx","xlsb","xlsm","ods","csv","dbf","dif","sylk","office","spreadsheet"],"bin":{"xlsx":"./bin/xlsx.njs"},"main":"xlsx.js","module":"xlsx.mjs","unpkg":"dist/xlsx.full.min.js","jsdelivr":"dist/xlsx.full.min.js","types":"types/index.d.ts","exports":{".":{"import":"./xlsx.mjs","require":"./xlsx.js","types":"./types/index.d.ts"},"./xlsx.mjs":{"import":"./xlsx.mjs","types":"./types/index.d.ts"},"./xlsx.js":{"require":"./xlsx.js","types":"./types/index.d.ts"},"./dist/xlsx.core.min":{"import":"./dist/xlsx.core.min.js","require":"./dist/xlsx.core.min.js","types":"./types/index.d.ts"},"./dist/xlsx.core.min.js":{"import":"./dist/xlsx.core.min.js","require":"./dist/xlsx.core.min.js","types":"./types/index.d.ts"},"./dist/xlsx.full.min":{"import":"./dist/xlsx.full.min.js","require":"./dist/xlsx.full.min.js","types":"./types/index.d.ts"},"./dist/xlsx.full.min.js":{"import":"./dist/xlsx.full.min.js","require":"./dist/xlsx.full.min.js","types":"./types/index.d.ts"},"./dist/xlsx.mini.min":{"import":"./dist/xlsx.mini.min.js","require":"./dist/xlsx.mini.min.js","types":"./types/index.d.ts"},"./dist/xlsx.mini.min.js":{"import":"./dist/xlsx.mini.min.js","require":"./dist/xlsx.mini.min.js","types":"./types/index.d.ts"},"./dist/xlsx.zahl":{"import":"./dist/xlsx.zahl.mjs","require":"./dist/xlsx.zahl.js","types":"./dist/zahl.d.ts"},"./dist/xlsx.zahl.mjs":{"import":"./dist/xlsx.zahl.mjs","types":"./dist/zahl.d.ts"},"./dist/xlsx.zahl.js":{"require":"./dist/xlsx.zahl.js","types":"./dist/zahl.d.ts"},"./dist/cpexcel":{"import":"./dist/cpexcel.full.mjs","require":"./dist/cpexcel.js","types":"./dist/cpexcel.d.ts"},"./dist/cpexcel.js":{"require":"./dist/cpexcel.js","types":"./dist/cpexcel.d.ts"},"./dist/cpexcel.full":{"import":"./dist/cpexcel.full.mjs","require":"./dist/cpexcel.js","types":"./dist/cpexcel.d.ts"},"./dist/cpexcel.full.mjs":{"import":"./dist/cpexcel.full.mjs","types":"./dist/cpexcel.d.ts"}},"browser":{"buffer":false,"crypto":false,"stream":false,"process":false,"fs":false},"sideEffects":false,"dependencies":{},"devDependencies":{"@sheetjs/uglify-js":"~2.7.3","@types/node":"^8.5.9","acorn":"7.4.1","adler-32":"~1.3.1","alex":"8.1.1","blanket":"~1.2.3","cfb":"~1.2.2","codepage":"~1.15.0","commander":"~2.17.1","crc-32":"~1.2.2","dtslint":"^0.1.2","eslint":"7.23.0","eslint-plugin-html":"^6.1.2","eslint-plugin-json":"^2.1.2","exit-on-epipe":"~1.0.1","fflate":"^0.7.1","jsdom":"~11.1.0","markdown-spellcheck":"^1.3.1","mocha":"~2.5.3","sinon":"^1.17.7","ssf":"~0.11.2","typescript":"2.2.0","wmf":"~1.0.1","word":"~0.3.0"},"repository":{"type":"git","url":"https://git.sheetjs.com/SheetJS/sheetjs"},"scripts":{"pretest":"npm run lint","test":"npm run tests-only","pretest-only":"git submodule init && git submodule update","tests-only":"make travis","build":"make","lint":"make fullint","dtslint":"dtslint types"},"config":{"blanket":{"pattern":"xlsx.js"}},"alex":{"allow":["chinese","special","simple","just","crash","wtf","holes"]},"homepage":"https://sheetjs.com/","files":["CHANGELOG.md","LICENSE","README.md","bower.json","package.json","xlsx.js","xlsx.mjs","xlsxworker.js","bin/xlsx.njs","dist/LICENSE","dist/*.mjs","dist/*.js","dist/*.map","dist/*.d.ts","types/index.d.ts","types/tsconfig.json"],"bugs":{"url":"https://git.sheetjs.com/SheetJS/sheetjs/issues"},"license":"Apache-2.0","engines":{"node":">=0.8"},"_lastModified":"2025-02-06T03:44:14.483Z"}
|
|
@@ -7,4 +7,4 @@
|
|
|
7
7
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
8
|
*/
|
|
9
9
|
import { Context, Next } from '@nocobase/actions';
|
|
10
|
-
export declare function exportXlsx(ctx: Context, next: Next): Promise<
|
|
10
|
+
export declare function exportXlsx(ctx: Context, next: Next): Promise<any>;
|
|
@@ -39,7 +39,7 @@ __export(export_xlsx_exports, {
|
|
|
39
39
|
exportXlsx: () => exportXlsx
|
|
40
40
|
});
|
|
41
41
|
module.exports = __toCommonJS(export_xlsx_exports);
|
|
42
|
-
var import_xlsx_exporter =
|
|
42
|
+
var import_xlsx_exporter = require("../services/xlsx-exporter");
|
|
43
43
|
var import_xlsx = __toESM(require("xlsx"));
|
|
44
44
|
var import_async_mutex = require("async-mutex");
|
|
45
45
|
const mutex = new import_async_mutex.Mutex();
|
|
@@ -53,7 +53,7 @@ async function exportXlsxAction(ctx, next) {
|
|
|
53
53
|
const repository = ctx.getCurrentRepository();
|
|
54
54
|
const dataSource = ctx.dataSource;
|
|
55
55
|
const collection = repository.collection;
|
|
56
|
-
const xlsxExporter = new import_xlsx_exporter.
|
|
56
|
+
const xlsxExporter = new import_xlsx_exporter.XlsxExporter({
|
|
57
57
|
collectionManager: dataSource.collectionManager,
|
|
58
58
|
collection,
|
|
59
59
|
repository,
|
|
@@ -73,6 +73,9 @@ async function exportXlsxAction(ctx, next) {
|
|
|
73
73
|
});
|
|
74
74
|
}
|
|
75
75
|
async function exportXlsx(ctx, next) {
|
|
76
|
+
if (ctx.exportHandled) {
|
|
77
|
+
return await next();
|
|
78
|
+
}
|
|
76
79
|
if (mutex.isLocked()) {
|
|
77
80
|
throw new Error(
|
|
78
81
|
ctx.t(`another export action is running, please try again later.`, {
|
package/dist/server/index.d.ts
CHANGED
package/dist/server/index.js
CHANGED
|
@@ -23,6 +23,7 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
23
23
|
}
|
|
24
24
|
return to;
|
|
25
25
|
};
|
|
26
|
+
var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
|
|
26
27
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
27
28
|
var server_exports = {};
|
|
28
29
|
__export(server_exports, {
|
|
@@ -32,6 +33,8 @@ __export(server_exports, {
|
|
|
32
33
|
module.exports = __toCommonJS(server_exports);
|
|
33
34
|
var import_server = require("@nocobase/server");
|
|
34
35
|
var import_actions = require("./actions");
|
|
36
|
+
__reExport(server_exports, require("./services/base-exporter"), module.exports);
|
|
37
|
+
__reExport(server_exports, require("./services/xlsx-exporter"), module.exports);
|
|
35
38
|
class PluginActionExportServer extends import_server.Plugin {
|
|
36
39
|
beforeLoad() {
|
|
37
40
|
this.app.on("afterInstall", async () => {
|
|
@@ -64,7 +67,8 @@ class PluginActionExportServer extends import_server.Plugin {
|
|
|
64
67
|
dataSource.resourceManager.registerActionHandler("export", import_actions.exportXlsx);
|
|
65
68
|
dataSource.acl.setAvailableAction("export", {
|
|
66
69
|
displayName: '{{t("Export")}}',
|
|
67
|
-
allowConfigureFields: true
|
|
70
|
+
allowConfigureFields: true,
|
|
71
|
+
aliases: ["export", "exportAttachments"]
|
|
68
72
|
});
|
|
69
73
|
});
|
|
70
74
|
}
|
|
@@ -72,5 +76,7 @@ class PluginActionExportServer extends import_server.Plugin {
|
|
|
72
76
|
var server_default = PluginActionExportServer;
|
|
73
77
|
// Annotate the CommonJS export names for ESM import in node:
|
|
74
78
|
0 && (module.exports = {
|
|
75
|
-
PluginActionExportServer
|
|
79
|
+
PluginActionExportServer,
|
|
80
|
+
...require("./services/base-exporter"),
|
|
81
|
+
...require("./services/xlsx-exporter")
|
|
76
82
|
});
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { FindOptions, ICollection, ICollectionManager, IField, IModel } from '@nocobase/data-source-manager';
|
|
3
|
+
import EventEmitter from 'events';
|
|
4
|
+
export type ExportOptions = {
|
|
5
|
+
collectionManager: ICollectionManager;
|
|
6
|
+
collection: ICollection;
|
|
7
|
+
repository?: any;
|
|
8
|
+
fields: Array<Array<string>>;
|
|
9
|
+
findOptions?: FindOptions;
|
|
10
|
+
chunkSize?: number;
|
|
11
|
+
limit?: number;
|
|
12
|
+
};
|
|
13
|
+
declare abstract class BaseExporter<T extends ExportOptions = ExportOptions> extends EventEmitter {
|
|
14
|
+
protected options: T;
|
|
15
|
+
/**
|
|
16
|
+
* You can adjust the maximum number of exported rows based on business needs and system
|
|
17
|
+
* available resources. However, please note that you need to fully understand the risks
|
|
18
|
+
* after the modification. Increasing the maximum number of rows that can be exported may
|
|
19
|
+
* increase system resource usage, leading to increased processing delays for other
|
|
20
|
+
* requests, or even server processes being recycled by the operating system.
|
|
21
|
+
*
|
|
22
|
+
* 您可以根据业务需求和系统可用资源等参数,调整最大导出数量的限制。但请注意,您需要充分了解修改之后的风险,
|
|
23
|
+
* 增加最大可导出的行数可能会导致系统资源占用率升高,导致其他请求处理延迟增加、无法处理、甚至
|
|
24
|
+
* 服务端进程被操作系统回收等问题。
|
|
25
|
+
*/
|
|
26
|
+
protected limit: number;
|
|
27
|
+
protected constructor(options: T);
|
|
28
|
+
abstract init(ctx?: any): Promise<void>;
|
|
29
|
+
abstract finalize(): Promise<any>;
|
|
30
|
+
abstract handleRow(row: any, ctx?: any): Promise<void>;
|
|
31
|
+
run(ctx?: any): Promise<any>;
|
|
32
|
+
protected getAppendOptionsFromFields(): string[];
|
|
33
|
+
protected getFindOptions(): any;
|
|
34
|
+
protected findFieldByDataIndex(dataIndex: Array<string>): IField;
|
|
35
|
+
protected renderRawValue(value: any): any;
|
|
36
|
+
protected getFieldRenderer(field?: IField, ctx?: any): (value: any) => any;
|
|
37
|
+
protected formatValue(rowData: IModel, dataIndex: Array<string>, ctx?: any): any;
|
|
38
|
+
generateOutputPath(prefix?: string, ext?: string, destination?: string): string;
|
|
39
|
+
}
|
|
40
|
+
export { BaseExporter };
|
|
@@ -34,17 +34,20 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
34
34
|
mod
|
|
35
35
|
));
|
|
36
36
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
37
|
-
var
|
|
38
|
-
__export(
|
|
39
|
-
|
|
37
|
+
var base_exporter_exports = {};
|
|
38
|
+
__export(base_exporter_exports, {
|
|
39
|
+
BaseExporter: () => BaseExporter
|
|
40
40
|
});
|
|
41
|
-
module.exports = __toCommonJS(
|
|
42
|
-
var
|
|
43
|
-
var import_deep_get = require("
|
|
44
|
-
var
|
|
45
|
-
|
|
41
|
+
module.exports = __toCommonJS(base_exporter_exports);
|
|
42
|
+
var import_events = __toESM(require("events"));
|
|
43
|
+
var import_deep_get = require("../utils/deep-get");
|
|
44
|
+
var import_path = __toESM(require("path"));
|
|
45
|
+
var import_os = __toESM(require("os"));
|
|
46
|
+
class BaseExporter extends import_events.default {
|
|
46
47
|
constructor(options) {
|
|
48
|
+
super();
|
|
47
49
|
this.options = options;
|
|
50
|
+
this.limit = options.limit ?? (process.env["EXPORT_LIMIT"] ? parseInt(process.env["EXPORT_LIMIT"]) : 2e3);
|
|
48
51
|
}
|
|
49
52
|
/**
|
|
50
53
|
* You can adjust the maximum number of exported rows based on business needs and system
|
|
@@ -57,68 +60,46 @@ class XlsxExporter {
|
|
|
57
60
|
* 增加最大可导出的行数可能会导致系统资源占用率升高,导致其他请求处理延迟增加、无法处理、甚至
|
|
58
61
|
* 服务端进程被操作系统回收等问题。
|
|
59
62
|
*/
|
|
60
|
-
limit
|
|
63
|
+
limit;
|
|
61
64
|
async run(ctx) {
|
|
62
|
-
|
|
63
|
-
const
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
origin: "A1"
|
|
67
|
-
});
|
|
68
|
-
let startRowNumber = 2;
|
|
65
|
+
await this.init(ctx);
|
|
66
|
+
const { collection, chunkSize, repository } = this.options;
|
|
67
|
+
const total = await (repository || collection.repository).count(this.getFindOptions());
|
|
68
|
+
let current = 0;
|
|
69
69
|
await (repository || collection.repository).chunk({
|
|
70
70
|
...this.getFindOptions(),
|
|
71
71
|
chunkSize: chunkSize || 200,
|
|
72
72
|
callback: async (rows, options) => {
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
|
|
73
|
+
for (const row of rows) {
|
|
74
|
+
await this.handleRow(row, ctx);
|
|
75
|
+
current += 1;
|
|
76
|
+
this.emit("progress", {
|
|
77
|
+
total,
|
|
78
|
+
current
|
|
76
79
|
});
|
|
77
|
-
});
|
|
78
|
-
import_xlsx.default.utils.sheet_add_aoa(worksheet, chunkData, {
|
|
79
|
-
origin: `A${startRowNumber}`
|
|
80
|
-
});
|
|
81
|
-
startRowNumber += rows.length;
|
|
82
|
-
await new Promise((resolve) => {
|
|
83
|
-
setTimeout(resolve, 50);
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
});
|
|
87
|
-
for (const col of columns) {
|
|
88
|
-
const field = this.findFieldByDataIndex(col.dataIndex);
|
|
89
|
-
if (field instanceof import_database.NumberField) {
|
|
90
|
-
const colIndex = columns.indexOf(col);
|
|
91
|
-
const cellRange = import_xlsx.default.utils.decode_range(worksheet["!ref"]);
|
|
92
|
-
for (let r = 1; r <= cellRange.e.r; r++) {
|
|
93
|
-
const cell = worksheet[import_xlsx.default.utils.encode_cell({ c: colIndex, r })];
|
|
94
|
-
if (cell && isNumeric(cell.v)) {
|
|
95
|
-
cell.t = "n";
|
|
96
|
-
}
|
|
97
80
|
}
|
|
98
81
|
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
return workbook;
|
|
82
|
+
});
|
|
83
|
+
return this.finalize();
|
|
102
84
|
}
|
|
103
|
-
|
|
104
|
-
return this.options.
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
const field = this.options.collection.getField(col.dataIndex[0]);
|
|
109
|
-
if (!field) {
|
|
110
|
-
throw new Error(`Field "${col.dataIndex[0]}" not found: , please check the columns configuration.`);
|
|
85
|
+
getAppendOptionsFromFields() {
|
|
86
|
+
return this.options.fields.map((field) => {
|
|
87
|
+
const fieldInstance = this.options.collection.getField(field[0]);
|
|
88
|
+
if (!fieldInstance) {
|
|
89
|
+
throw new Error(`Field "${field[0]}" not found: , please check the fields configuration.`);
|
|
111
90
|
}
|
|
112
|
-
if (
|
|
113
|
-
return
|
|
91
|
+
if (fieldInstance.isRelationField()) {
|
|
92
|
+
return field.join(".");
|
|
114
93
|
}
|
|
115
94
|
return null;
|
|
116
95
|
}).filter(Boolean);
|
|
117
96
|
}
|
|
118
97
|
getFindOptions() {
|
|
119
98
|
const { findOptions = {} } = this.options;
|
|
120
|
-
|
|
121
|
-
|
|
99
|
+
if (this.limit) {
|
|
100
|
+
findOptions.limit = this.limit;
|
|
101
|
+
}
|
|
102
|
+
const appendOptions = this.getAppendOptionsFromFields();
|
|
122
103
|
if (appendOptions.length) {
|
|
123
104
|
return {
|
|
124
105
|
...findOptions,
|
|
@@ -142,15 +123,6 @@ class XlsxExporter {
|
|
|
142
123
|
}
|
|
143
124
|
return currentField;
|
|
144
125
|
}
|
|
145
|
-
renderHeaders() {
|
|
146
|
-
return this.options.columns.map((col) => {
|
|
147
|
-
const field = this.findFieldByDataIndex(col.dataIndex);
|
|
148
|
-
if (col.title) {
|
|
149
|
-
return col.title;
|
|
150
|
-
}
|
|
151
|
-
return (field == null ? void 0 : field.options.title) || col.defaultTitle;
|
|
152
|
-
});
|
|
153
|
-
}
|
|
154
126
|
renderRawValue(value) {
|
|
155
127
|
if (typeof value === "object" && value !== null) {
|
|
156
128
|
return JSON.stringify(value);
|
|
@@ -163,11 +135,10 @@ class XlsxExporter {
|
|
|
163
135
|
if (!InterfaceClass) {
|
|
164
136
|
return this.renderRawValue;
|
|
165
137
|
}
|
|
166
|
-
const
|
|
167
|
-
return (value) =>
|
|
138
|
+
const fieldInterface = new InterfaceClass(field == null ? void 0 : field.options);
|
|
139
|
+
return (value) => fieldInterface.toString(value, ctx);
|
|
168
140
|
}
|
|
169
|
-
|
|
170
|
-
const { dataIndex } = column;
|
|
141
|
+
formatValue(rowData, dataIndex, ctx) {
|
|
171
142
|
rowData = rowData.toJSON();
|
|
172
143
|
const value = rowData[dataIndex[0]];
|
|
173
144
|
const field = this.findFieldByDataIndex(dataIndex);
|
|
@@ -181,8 +152,12 @@ class XlsxExporter {
|
|
|
181
152
|
}
|
|
182
153
|
return render(value);
|
|
183
154
|
}
|
|
155
|
+
generateOutputPath(prefix = "export", ext = "", destination = import_os.default.tmpdir()) {
|
|
156
|
+
const fileName = `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2)}${ext}`;
|
|
157
|
+
return import_path.default.join(destination, fileName);
|
|
158
|
+
}
|
|
184
159
|
}
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
160
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
161
|
+
0 && (module.exports = {
|
|
162
|
+
BaseExporter
|
|
163
|
+
});
|
|
@@ -1,28 +1,16 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* This file is part of the NocoBase (R) project.
|
|
3
|
-
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
-
* Authors: NocoBase Team.
|
|
5
|
-
*
|
|
6
|
-
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
-
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
-
*/
|
|
9
|
-
import { FindOptions, ICollection, ICollectionManager } from '@nocobase/data-source-manager';
|
|
10
1
|
import XLSX from 'xlsx';
|
|
2
|
+
import { BaseExporter, ExportOptions } from './base-exporter';
|
|
11
3
|
type ExportColumn = {
|
|
12
4
|
dataIndex: Array<string>;
|
|
13
5
|
title?: string;
|
|
14
6
|
defaultTitle: string;
|
|
15
7
|
};
|
|
16
|
-
type
|
|
17
|
-
collectionManager: ICollectionManager;
|
|
18
|
-
collection: ICollection;
|
|
19
|
-
repository?: any;
|
|
8
|
+
type XlsxExportOptions = Omit<ExportOptions, 'fields'> & {
|
|
20
9
|
columns: Array<ExportColumn>;
|
|
21
|
-
findOptions?: FindOptions;
|
|
22
|
-
chunkSize?: number;
|
|
23
10
|
};
|
|
24
|
-
declare class XlsxExporter {
|
|
25
|
-
|
|
11
|
+
export declare class XlsxExporter extends BaseExporter<XlsxExportOptions & {
|
|
12
|
+
fields: Array<Array<string>>;
|
|
13
|
+
}> {
|
|
26
14
|
/**
|
|
27
15
|
* You can adjust the maximum number of exported rows based on business needs and system
|
|
28
16
|
* available resources. However, please note that you need to fully understand the risks
|
|
@@ -34,15 +22,13 @@ declare class XlsxExporter {
|
|
|
34
22
|
* 增加最大可导出的行数可能会导致系统资源占用率升高,导致其他请求处理延迟增加、无法处理、甚至
|
|
35
23
|
* 服务端进程被操作系统回收等问题。
|
|
36
24
|
*/
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
25
|
+
private workbook;
|
|
26
|
+
private worksheet;
|
|
27
|
+
private startRowNumber;
|
|
28
|
+
constructor(options: XlsxExportOptions);
|
|
29
|
+
init(ctx?: any): Promise<void>;
|
|
30
|
+
handleRow(row: any, ctx?: any): Promise<void>;
|
|
31
|
+
finalize(): Promise<XLSX.WorkBook>;
|
|
43
32
|
private renderHeaders;
|
|
44
|
-
private renderRawValue;
|
|
45
|
-
private getFieldRenderer;
|
|
46
|
-
private renderCellValue;
|
|
47
33
|
}
|
|
48
|
-
export
|
|
34
|
+
export {};
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
var __create = Object.create;
|
|
11
|
+
var __defProp = Object.defineProperty;
|
|
12
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
13
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
14
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
15
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
16
|
+
var __export = (target, all) => {
|
|
17
|
+
for (var name in all)
|
|
18
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
19
|
+
};
|
|
20
|
+
var __copyProps = (to, from, except, desc) => {
|
|
21
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
22
|
+
for (let key of __getOwnPropNames(from))
|
|
23
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
24
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
25
|
+
}
|
|
26
|
+
return to;
|
|
27
|
+
};
|
|
28
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
29
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
30
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
31
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
32
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
33
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
34
|
+
mod
|
|
35
|
+
));
|
|
36
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
37
|
+
var xlsx_exporter_exports = {};
|
|
38
|
+
__export(xlsx_exporter_exports, {
|
|
39
|
+
XlsxExporter: () => XlsxExporter
|
|
40
|
+
});
|
|
41
|
+
module.exports = __toCommonJS(xlsx_exporter_exports);
|
|
42
|
+
var import_xlsx = __toESM(require("xlsx"));
|
|
43
|
+
var import_base_exporter = require("./base-exporter");
|
|
44
|
+
var import_database = require("@nocobase/database");
|
|
45
|
+
class XlsxExporter extends import_base_exporter.BaseExporter {
|
|
46
|
+
/**
|
|
47
|
+
* You can adjust the maximum number of exported rows based on business needs and system
|
|
48
|
+
* available resources. However, please note that you need to fully understand the risks
|
|
49
|
+
* after the modification. Increasing the maximum number of rows that can be exported may
|
|
50
|
+
* increase system resource usage, leading to increased processing delays for other
|
|
51
|
+
* requests, or even server processes being recycled by the operating system.
|
|
52
|
+
*
|
|
53
|
+
* 您可以根据业务需求和系统可用资源等参数,调整最大导出数量的限制。但请注意,您需要充分了解修改之后的风险,
|
|
54
|
+
* 增加最大可导出的行数可能会导致系统资源占用率升高,导致其他请求处理延迟增加、无法处理、甚至
|
|
55
|
+
* 服务端进程被操作系统回收等问题。
|
|
56
|
+
*/
|
|
57
|
+
workbook;
|
|
58
|
+
worksheet;
|
|
59
|
+
startRowNumber;
|
|
60
|
+
constructor(options) {
|
|
61
|
+
const fields = options.columns.map((col) => col.dataIndex);
|
|
62
|
+
super({ ...options, fields });
|
|
63
|
+
}
|
|
64
|
+
async init(ctx) {
|
|
65
|
+
this.workbook = import_xlsx.default.utils.book_new();
|
|
66
|
+
this.worksheet = import_xlsx.default.utils.sheet_new();
|
|
67
|
+
import_xlsx.default.utils.sheet_add_aoa(this.worksheet, [this.renderHeaders(this.options.columns)], {
|
|
68
|
+
origin: "A1"
|
|
69
|
+
});
|
|
70
|
+
this.startRowNumber = 2;
|
|
71
|
+
}
|
|
72
|
+
async handleRow(row, ctx) {
|
|
73
|
+
const rowData = [
|
|
74
|
+
this.options.columns.map((col) => {
|
|
75
|
+
return this.formatValue(row, col.dataIndex, ctx);
|
|
76
|
+
})
|
|
77
|
+
];
|
|
78
|
+
import_xlsx.default.utils.sheet_add_aoa(this.worksheet, rowData, {
|
|
79
|
+
origin: `A${this.startRowNumber}`
|
|
80
|
+
});
|
|
81
|
+
this.startRowNumber += 1;
|
|
82
|
+
}
|
|
83
|
+
async finalize() {
|
|
84
|
+
for (const col of this.options.columns) {
|
|
85
|
+
const fieldInstance = this.findFieldByDataIndex(col.dataIndex);
|
|
86
|
+
if (fieldInstance instanceof import_database.NumberField) {
|
|
87
|
+
const colIndex = this.options.columns.indexOf(col);
|
|
88
|
+
const cellRange = import_xlsx.default.utils.decode_range(this.worksheet["!ref"]);
|
|
89
|
+
for (let r = 1; r <= cellRange.e.r; r++) {
|
|
90
|
+
const cell = this.worksheet[import_xlsx.default.utils.encode_cell({ c: colIndex, r })];
|
|
91
|
+
if (cell && isNumeric(cell.v)) {
|
|
92
|
+
cell.t = "n";
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
import_xlsx.default.utils.book_append_sheet(this.workbook, this.worksheet, "Data");
|
|
98
|
+
return this.workbook;
|
|
99
|
+
}
|
|
100
|
+
renderHeaders(columns) {
|
|
101
|
+
return columns.map((col) => {
|
|
102
|
+
const fieldInstance = this.findFieldByDataIndex(col.dataIndex);
|
|
103
|
+
return col.title || (fieldInstance == null ? void 0 : fieldInstance.options.title) || col.defaultTitle;
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
function isNumeric(n) {
|
|
108
|
+
return !isNaN(parseFloat(n)) && isFinite(n);
|
|
109
|
+
}
|
|
110
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
111
|
+
0 && (module.exports = {
|
|
112
|
+
XlsxExporter
|
|
113
|
+
});
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"displayName.zh-CN": "操作:导出记录",
|
|
5
5
|
"description": "Export filtered records to excel, you can configure which fields to export.",
|
|
6
6
|
"description.zh-CN": "导出筛选后的记录到 Excel 中,可以配置导出哪些字段。",
|
|
7
|
-
"version": "1.5.
|
|
7
|
+
"version": "1.5.1",
|
|
8
8
|
"license": "AGPL-3.0",
|
|
9
9
|
"main": "./dist/server/index.js",
|
|
10
10
|
"homepage": "https://docs.nocobase.com/handbook/action-export",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"@nocobase/test": "1.x",
|
|
30
30
|
"@nocobase/utils": "1.x"
|
|
31
31
|
},
|
|
32
|
-
"gitHead": "
|
|
32
|
+
"gitHead": "b16a0ff226482d0de847656ea26fd621b1d685cf",
|
|
33
33
|
"keywords": [
|
|
34
34
|
"Actions"
|
|
35
35
|
]
|