@tachybase/plugin-action-export 0.23.8
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/.turbo/turbo-build.log +14 -0
- package/LICENSE +201 -0
- package/README.md +9 -0
- package/README.zh-CN.md +9 -0
- package/client.d.ts +2 -0
- package/client.js +1 -0
- package/dist/client/ExportActionInitializer.d.ts +8 -0
- package/dist/client/ExportDesigner.d.ts +2 -0
- package/dist/client/ExportPluginProvider.d.ts +2 -0
- package/dist/client/index.d.ts +9 -0
- package/dist/client/index.js +14 -0
- package/dist/client/schemaSettings.d.ts +2 -0
- package/dist/client/useExportAction.d.ts +3 -0
- package/dist/client/useFields.d.ts +1 -0
- package/dist/client/useShared.d.ts +70 -0
- package/dist/externalVersion.js +13 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +39 -0
- package/dist/node_modules/node-xlsx/dist/bin/cli.cjs +95 -0
- package/dist/node_modules/node-xlsx/dist/bin/cli.d.cts +1 -0
- package/dist/node_modules/node-xlsx/dist/bin/cli.d.ts +1 -0
- package/dist/node_modules/node-xlsx/dist/bin/cli.js +37 -0
- package/dist/node_modules/node-xlsx/dist/chunk-ID6OMQGT.js +78 -0
- package/dist/node_modules/node-xlsx/dist/index.cjs +7 -0
- package/dist/node_modules/node-xlsx/dist/index.d.cts +46 -0
- package/dist/node_modules/node-xlsx/dist/index.d.ts +46 -0
- package/dist/node_modules/node-xlsx/dist/index.js +13 -0
- package/dist/node_modules/node-xlsx/node_modules/.bin/xlsx +17 -0
- package/dist/node_modules/node-xlsx/package.json +1 -0
- package/dist/server/actions/export-xlsx.d.ts +2 -0
- package/dist/server/actions/export-xlsx.js +132 -0
- package/dist/server/actions/index.d.ts +1 -0
- package/dist/server/actions/index.js +21 -0
- package/dist/server/constants.d.ts +2 -0
- package/dist/server/constants.js +30 -0
- package/dist/server/index.d.ts +10 -0
- package/dist/server/index.js +122 -0
- package/dist/server/renders/index.d.ts +10 -0
- package/dist/server/renders/index.js +159 -0
- package/dist/server/renders/renders.d.ts +21 -0
- package/dist/server/renders/renders.js +163 -0
- package/dist/server/utils/columns2Appends.d.ts +1 -0
- package/dist/server/utils/columns2Appends.js +45 -0
- package/dist/server/utils/index.d.ts +1 -0
- package/dist/server/utils/index.js +21 -0
- package/dist/swagger/index.json +21 -0
- package/package.json +35 -0
- package/server.d.ts +2 -0
- package/server.js +1 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { Sheet2JSONOpts, ParsingOptions, Range, ColInfo, RowInfo, ProtectInfo, AutoFilterInfo, AOA2SheetOpts, WritingOptions } from 'xlsx';
|
|
2
|
+
|
|
3
|
+
declare const parse: <T = any[]>(mixed: unknown, options?: Sheet2JSONOpts & ParsingOptions) => {
|
|
4
|
+
name: string;
|
|
5
|
+
data: T[];
|
|
6
|
+
}[];
|
|
7
|
+
declare const parseMetadata: (mixed: unknown, options?: ParsingOptions) => {
|
|
8
|
+
name: string;
|
|
9
|
+
data: Range | null;
|
|
10
|
+
}[];
|
|
11
|
+
type WorkSheetOptions = {
|
|
12
|
+
/** Column Info */
|
|
13
|
+
"!cols"?: ColInfo[];
|
|
14
|
+
/** Row Info */
|
|
15
|
+
"!rows"?: RowInfo[];
|
|
16
|
+
/** Merge Ranges */
|
|
17
|
+
"!merges"?: Range[];
|
|
18
|
+
/** Worksheet Protection info */
|
|
19
|
+
"!protect"?: ProtectInfo;
|
|
20
|
+
/** AutoFilter info */
|
|
21
|
+
"!autofilter"?: AutoFilterInfo;
|
|
22
|
+
};
|
|
23
|
+
type WorkSheet<T = unknown> = {
|
|
24
|
+
name: string;
|
|
25
|
+
data: T[][];
|
|
26
|
+
options: WorkSheetOptions;
|
|
27
|
+
};
|
|
28
|
+
type BuildOptions = WorkSheetOptions & {
|
|
29
|
+
parseOptions?: AOA2SheetOpts;
|
|
30
|
+
writeOptions?: WritingOptions;
|
|
31
|
+
sheetOptions?: WorkSheetOptions;
|
|
32
|
+
};
|
|
33
|
+
declare const build: (worksheets: WorkSheet[], { parseOptions, writeOptions, sheetOptions, ...otherOptions }?: BuildOptions) => Buffer;
|
|
34
|
+
declare const _default: {
|
|
35
|
+
parse: <T = any[]>(mixed: unknown, options?: Sheet2JSONOpts & ParsingOptions) => {
|
|
36
|
+
name: string;
|
|
37
|
+
data: T[];
|
|
38
|
+
}[];
|
|
39
|
+
parseMetadata: (mixed: unknown, options?: ParsingOptions) => {
|
|
40
|
+
name: string;
|
|
41
|
+
data: Range | null;
|
|
42
|
+
}[];
|
|
43
|
+
build: (worksheets: WorkSheet<unknown>[], { parseOptions, writeOptions, sheetOptions, ...otherOptions }?: BuildOptions) => Buffer;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export { type BuildOptions, type WorkSheet, type WorkSheetOptions, build, _default as default, parse, parseMetadata };
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { Sheet2JSONOpts, ParsingOptions, Range, ColInfo, RowInfo, ProtectInfo, AutoFilterInfo, AOA2SheetOpts, WritingOptions } from 'xlsx';
|
|
2
|
+
|
|
3
|
+
declare const parse: <T = any[]>(mixed: unknown, options?: Sheet2JSONOpts & ParsingOptions) => {
|
|
4
|
+
name: string;
|
|
5
|
+
data: T[];
|
|
6
|
+
}[];
|
|
7
|
+
declare const parseMetadata: (mixed: unknown, options?: ParsingOptions) => {
|
|
8
|
+
name: string;
|
|
9
|
+
data: Range | null;
|
|
10
|
+
}[];
|
|
11
|
+
type WorkSheetOptions = {
|
|
12
|
+
/** Column Info */
|
|
13
|
+
"!cols"?: ColInfo[];
|
|
14
|
+
/** Row Info */
|
|
15
|
+
"!rows"?: RowInfo[];
|
|
16
|
+
/** Merge Ranges */
|
|
17
|
+
"!merges"?: Range[];
|
|
18
|
+
/** Worksheet Protection info */
|
|
19
|
+
"!protect"?: ProtectInfo;
|
|
20
|
+
/** AutoFilter info */
|
|
21
|
+
"!autofilter"?: AutoFilterInfo;
|
|
22
|
+
};
|
|
23
|
+
type WorkSheet<T = unknown> = {
|
|
24
|
+
name: string;
|
|
25
|
+
data: T[][];
|
|
26
|
+
options: WorkSheetOptions;
|
|
27
|
+
};
|
|
28
|
+
type BuildOptions = WorkSheetOptions & {
|
|
29
|
+
parseOptions?: AOA2SheetOpts;
|
|
30
|
+
writeOptions?: WritingOptions;
|
|
31
|
+
sheetOptions?: WorkSheetOptions;
|
|
32
|
+
};
|
|
33
|
+
declare const build: (worksheets: WorkSheet[], { parseOptions, writeOptions, sheetOptions, ...otherOptions }?: BuildOptions) => Buffer;
|
|
34
|
+
declare const _default: {
|
|
35
|
+
parse: <T = any[]>(mixed: unknown, options?: Sheet2JSONOpts & ParsingOptions) => {
|
|
36
|
+
name: string;
|
|
37
|
+
data: T[];
|
|
38
|
+
}[];
|
|
39
|
+
parseMetadata: (mixed: unknown, options?: ParsingOptions) => {
|
|
40
|
+
name: string;
|
|
41
|
+
data: Range | null;
|
|
42
|
+
}[];
|
|
43
|
+
build: (worksheets: WorkSheet<unknown>[], { parseOptions, writeOptions, sheetOptions, ...otherOptions }?: BuildOptions) => Buffer;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export { type BuildOptions, type WorkSheet, type WorkSheetOptions, build, _default as default, parse, parseMetadata };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
|
3
|
+
|
|
4
|
+
case `uname` in
|
|
5
|
+
*CYGWIN*) basedir=`cygpath -w "$basedir"`;;
|
|
6
|
+
esac
|
|
7
|
+
|
|
8
|
+
if [ -z "$NODE_PATH" ]; then
|
|
9
|
+
export NODE_PATH="/Users/seal/Documents/projects/tachybase/node_modules/.pnpm/xlsx@https+++cdn.sheetjs.com+xlsx-0.20.2+xlsx-0.20.2.tgz/node_modules/xlsx/bin/node_modules:/Users/seal/Documents/projects/tachybase/node_modules/.pnpm/xlsx@https+++cdn.sheetjs.com+xlsx-0.20.2+xlsx-0.20.2.tgz/node_modules/xlsx/node_modules:/Users/seal/Documents/projects/tachybase/node_modules/.pnpm/xlsx@https+++cdn.sheetjs.com+xlsx-0.20.2+xlsx-0.20.2.tgz/node_modules:/Users/seal/Documents/projects/tachybase/node_modules/.pnpm/node_modules"
|
|
10
|
+
else
|
|
11
|
+
export NODE_PATH="/Users/seal/Documents/projects/tachybase/node_modules/.pnpm/xlsx@https+++cdn.sheetjs.com+xlsx-0.20.2+xlsx-0.20.2.tgz/node_modules/xlsx/bin/node_modules:/Users/seal/Documents/projects/tachybase/node_modules/.pnpm/xlsx@https+++cdn.sheetjs.com+xlsx-0.20.2+xlsx-0.20.2.tgz/node_modules/xlsx/node_modules:/Users/seal/Documents/projects/tachybase/node_modules/.pnpm/xlsx@https+++cdn.sheetjs.com+xlsx-0.20.2+xlsx-0.20.2.tgz/node_modules:/Users/seal/Documents/projects/tachybase/node_modules/.pnpm/node_modules:$NODE_PATH"
|
|
12
|
+
fi
|
|
13
|
+
if [ -x "$basedir/node" ]; then
|
|
14
|
+
exec "$basedir/node" "$basedir/../../../../../xlsx@https+++cdn.sheetjs.com+xlsx-0.20.2+xlsx-0.20.2.tgz/node_modules/xlsx/bin/xlsx.njs" "$@"
|
|
15
|
+
else
|
|
16
|
+
exec node "$basedir/../../../../../xlsx@https+++cdn.sheetjs.com+xlsx-0.20.2+xlsx-0.20.2.tgz/node_modules/xlsx/bin/xlsx.njs" "$@"
|
|
17
|
+
fi
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"name":"node-xlsx","author":"Olivier Louvignes <olivier@mg-crea.com>","version":"0.24.0","description":"NodeJS Excel files parser & builder","type":"module","main":"./dist/index.cjs","exports":{".":{"require":"./dist/index.cjs","import":"./dist/index.js","types":"./dist/index.d.ts"}},"bin":{"node-xlsx":"./dist/bin/cli.js"},"files":["dist"],"scripts":{"start":"npm run spec -- --watch","build":"tsup --entry src/index.ts --format cjs,esm --sourcemap --dts --clean --entry src/bin/cli.ts","lint":"eslint src/ test/","prettycheck":"prettier --check src/ test/","prettify":"prettier --write src/ test/","typecheck":"tsc --noEmit","spec":"DEBUG=node-xlsx* vitest --run","watch":"DEBUG=node-xlsx* vitest --watch","test":"npm run lint && npm run prettycheck && npm run typecheck && npm run spec","prepublishOnly":"npm run build"},"repository":"github:mgcrea/node-xlsx","license":"Apache-2.0","dependencies":{"xlsx":"https://cdn.sheetjs.com/xlsx-0.20.2/xlsx-0.20.2.tgz"},"devDependencies":{"@mgcrea/eslint-config-node":"^0.10.0","@tsconfig/node-lts":"^20.1.1","@types/node":"^20.12.7","eslint":"^8.57.0","prettier":"^3.2.5","prettier-plugin-organize-imports":"^3.2.4","tsup":"^8.0.2","typescript":"^5.4.5","vite-tsconfig-paths":"^4.3.2","vitest":"^1.5.0"},"engines":{"node":">=10.0.0"},"keywords":["excel","parser","builder","xlsx","xls"],"_lastModified":"2024-12-22T16:01:19.670Z"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
20
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
21
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
22
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
23
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
24
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
25
|
+
mod
|
|
26
|
+
));
|
|
27
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
28
|
+
var export_xlsx_exports = {};
|
|
29
|
+
__export(export_xlsx_exports, {
|
|
30
|
+
exportXlsx: () => exportXlsx
|
|
31
|
+
});
|
|
32
|
+
module.exports = __toCommonJS(export_xlsx_exports);
|
|
33
|
+
var import_utils = require("@tachybase/utils");
|
|
34
|
+
var import_node_xlsx = __toESM(require("node-xlsx"));
|
|
35
|
+
var import__ = __toESM(require(".."));
|
|
36
|
+
var import_constants = require("../constants");
|
|
37
|
+
var import_renders = __toESM(require("../renders"));
|
|
38
|
+
var import_utils2 = require("../utils");
|
|
39
|
+
async function exportXlsx(ctx, next) {
|
|
40
|
+
var _a, _b, _c;
|
|
41
|
+
const { title, filter, sort, fields, except } = ctx.action.params;
|
|
42
|
+
const { resourceName, resourceOf } = ctx.action;
|
|
43
|
+
let columns = ((_a = ctx.action.params.values) == null ? void 0 : _a.columns) || ((_b = ctx.action.params) == null ? void 0 : _b.columns);
|
|
44
|
+
if (typeof columns === "string") {
|
|
45
|
+
columns = JSON.parse(columns);
|
|
46
|
+
}
|
|
47
|
+
const repository = ctx.db.getRepository(resourceName, resourceOf);
|
|
48
|
+
const collection = repository.collection;
|
|
49
|
+
columns = columns == null ? void 0 : columns.filter((col) => {
|
|
50
|
+
var _a2;
|
|
51
|
+
return collection.hasField(col.dataIndex[0]) && ((_a2 = col == null ? void 0 : col.dataIndex) == null ? void 0 : _a2.length) > 0;
|
|
52
|
+
});
|
|
53
|
+
const appends = (0, import_utils2.columns2Appends)(columns, ctx);
|
|
54
|
+
const count = await repository.count({
|
|
55
|
+
filter,
|
|
56
|
+
context: ctx
|
|
57
|
+
});
|
|
58
|
+
if (count > import_constants.EXPORT_LENGTH_MAX) {
|
|
59
|
+
const app = ctx.app;
|
|
60
|
+
if (!((_c = app.worker) == null ? void 0 : _c.available)) {
|
|
61
|
+
ctx.throw(400, `Too many records to export: ${count} > ${import_constants.EXPORT_LENGTH_MAX}`);
|
|
62
|
+
}
|
|
63
|
+
const fileWithPath = await app.worker.callPluginMethod({
|
|
64
|
+
plugin: import__.default,
|
|
65
|
+
method: "workerExportXlsx",
|
|
66
|
+
// TODO: 这样不够优雅
|
|
67
|
+
concurrency: 1,
|
|
68
|
+
globalConcurrency: 1,
|
|
69
|
+
params: {
|
|
70
|
+
title,
|
|
71
|
+
filter,
|
|
72
|
+
sort,
|
|
73
|
+
fields,
|
|
74
|
+
except,
|
|
75
|
+
columns,
|
|
76
|
+
resourceName,
|
|
77
|
+
resourceOf,
|
|
78
|
+
appends,
|
|
79
|
+
timezone: ctx.get("X-Timezone")
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
if (!fileWithPath) {
|
|
83
|
+
ctx.throw(500, "Export failed");
|
|
84
|
+
}
|
|
85
|
+
ctx.body = {
|
|
86
|
+
filename: `/${fileWithPath}`
|
|
87
|
+
};
|
|
88
|
+
return next();
|
|
89
|
+
}
|
|
90
|
+
const data = await repository.find({
|
|
91
|
+
filter,
|
|
92
|
+
fields,
|
|
93
|
+
appends,
|
|
94
|
+
except,
|
|
95
|
+
sort,
|
|
96
|
+
context: ctx
|
|
97
|
+
});
|
|
98
|
+
const collectionFields = columns.map((col) => collection.fields.get(col.dataIndex[0]));
|
|
99
|
+
const { rows, ranges } = await (0, import_renders.default)(
|
|
100
|
+
{ columns, fields: collectionFields, data, utcOffset: ctx.get("X-Timezone") },
|
|
101
|
+
ctx.db
|
|
102
|
+
);
|
|
103
|
+
const timezone = ctx.get("x-timezone");
|
|
104
|
+
if (timezone) {
|
|
105
|
+
for (const data2 of rows) {
|
|
106
|
+
for (const key in data2) {
|
|
107
|
+
if (data2[key] instanceof Date) {
|
|
108
|
+
data2[key] = (0, import_utils.dayjs)(data2[key]).utcOffset(timezone).format("YYYY-MM-DD HH:mm:ss");
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
ctx.body = import_node_xlsx.default.build([
|
|
114
|
+
{
|
|
115
|
+
name: "Sheet 1",
|
|
116
|
+
data: rows,
|
|
117
|
+
options: {
|
|
118
|
+
"!merges": ranges
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
]);
|
|
122
|
+
ctx.set({
|
|
123
|
+
"Content-Type": "application/octet-stream",
|
|
124
|
+
// to avoid "invalid character" error in header (RFC)
|
|
125
|
+
"Content-Disposition": `attachment; filename=${encodeURI(title)}.xlsx`
|
|
126
|
+
});
|
|
127
|
+
await next();
|
|
128
|
+
}
|
|
129
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
130
|
+
0 && (module.exports = {
|
|
131
|
+
exportXlsx
|
|
132
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './export-xlsx';
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __copyProps = (to, from, except, desc) => {
|
|
6
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
7
|
+
for (let key of __getOwnPropNames(from))
|
|
8
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
9
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
10
|
+
}
|
|
11
|
+
return to;
|
|
12
|
+
};
|
|
13
|
+
var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
|
|
14
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
15
|
+
var actions_exports = {};
|
|
16
|
+
module.exports = __toCommonJS(actions_exports);
|
|
17
|
+
__reExport(actions_exports, require("./export-xlsx"), module.exports);
|
|
18
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
19
|
+
0 && (module.exports = {
|
|
20
|
+
...require("./export-xlsx")
|
|
21
|
+
});
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __export = (target, all) => {
|
|
6
|
+
for (var name in all)
|
|
7
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
8
|
+
};
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
|
+
var constants_exports = {};
|
|
19
|
+
__export(constants_exports, {
|
|
20
|
+
EXPORT_LENGTH_MAX: () => EXPORT_LENGTH_MAX,
|
|
21
|
+
EXPORT_WORKER_PAGESIZE: () => EXPORT_WORKER_PAGESIZE
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(constants_exports);
|
|
24
|
+
const EXPORT_LENGTH_MAX = +process.env.EXPORT_LENGTH_MAX || 2e3;
|
|
25
|
+
const EXPORT_WORKER_PAGESIZE = +process.env.EXPORT_WORKER_PAGESIZE || 1e3;
|
|
26
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
27
|
+
0 && (module.exports = {
|
|
28
|
+
EXPORT_LENGTH_MAX,
|
|
29
|
+
EXPORT_WORKER_PAGESIZE
|
|
30
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { InstallOptions, Plugin } from '@tachybase/server';
|
|
2
|
+
export declare class ExportPlugin extends Plugin {
|
|
3
|
+
beforeLoad(): void;
|
|
4
|
+
load(): Promise<void>;
|
|
5
|
+
install(options: InstallOptions): Promise<void>;
|
|
6
|
+
static defaultSavePath: string;
|
|
7
|
+
xlsxStorageDir(): string;
|
|
8
|
+
workerExportXlsx(params: any): Promise<string>;
|
|
9
|
+
}
|
|
10
|
+
export default ExportPlugin;
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
20
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
21
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
22
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
23
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
24
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
25
|
+
mod
|
|
26
|
+
));
|
|
27
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
28
|
+
var server_exports = {};
|
|
29
|
+
__export(server_exports, {
|
|
30
|
+
ExportPlugin: () => ExportPlugin,
|
|
31
|
+
default: () => server_default
|
|
32
|
+
});
|
|
33
|
+
module.exports = __toCommonJS(server_exports);
|
|
34
|
+
var import_fs = require("fs");
|
|
35
|
+
var import_path = __toESM(require("path"));
|
|
36
|
+
var import_server = require("@tachybase/server");
|
|
37
|
+
var import_utils = require("@tachybase/utils");
|
|
38
|
+
var import_node_xlsx = __toESM(require("node-xlsx"));
|
|
39
|
+
var import_actions = require("./actions");
|
|
40
|
+
var import_constants = require("./constants");
|
|
41
|
+
var import_renders = __toESM(require("./renders"));
|
|
42
|
+
class ExportPlugin extends import_server.Plugin {
|
|
43
|
+
beforeLoad() {
|
|
44
|
+
}
|
|
45
|
+
async load() {
|
|
46
|
+
this.app.resourcer.registerActionHandler("export", import_actions.exportXlsx);
|
|
47
|
+
this.app.acl.setAvailableAction("export", {
|
|
48
|
+
displayName: '{{t("Export")}}',
|
|
49
|
+
allowConfigureFields: true
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
async install(options) {
|
|
53
|
+
}
|
|
54
|
+
static defaultSavePath = "storage/uploads";
|
|
55
|
+
xlsxStorageDir() {
|
|
56
|
+
return import_path.default.resolve(process.cwd(), ExportPlugin.defaultSavePath);
|
|
57
|
+
}
|
|
58
|
+
async workerExportXlsx(params) {
|
|
59
|
+
const { title, filter, sort, fields, except, appends, resourceName, resourceOf, timezone } = params;
|
|
60
|
+
let columns = (params == null ? void 0 : params.columns) || (params == null ? void 0 : params.columns);
|
|
61
|
+
if (typeof columns === "string") {
|
|
62
|
+
columns = JSON.parse(columns);
|
|
63
|
+
}
|
|
64
|
+
const repository = this.db.getRepository(resourceName, resourceOf);
|
|
65
|
+
const collection = repository.collection;
|
|
66
|
+
columns = columns == null ? void 0 : columns.filter((col) => {
|
|
67
|
+
var _a;
|
|
68
|
+
return collection.hasField(col.dataIndex[0]) && ((_a = col == null ? void 0 : col.dataIndex) == null ? void 0 : _a.length) > 0;
|
|
69
|
+
});
|
|
70
|
+
let page = 1;
|
|
71
|
+
const pageSize = import_constants.EXPORT_WORKER_PAGESIZE;
|
|
72
|
+
let data = [];
|
|
73
|
+
let hasMore = true;
|
|
74
|
+
while (hasMore) {
|
|
75
|
+
const pageData = await repository.find({
|
|
76
|
+
filter,
|
|
77
|
+
fields,
|
|
78
|
+
appends,
|
|
79
|
+
except,
|
|
80
|
+
sort,
|
|
81
|
+
offset: (page - 1) * pageSize,
|
|
82
|
+
limit: pageSize
|
|
83
|
+
});
|
|
84
|
+
data = data.concat(pageData);
|
|
85
|
+
hasMore = pageData.length === pageSize;
|
|
86
|
+
page++;
|
|
87
|
+
}
|
|
88
|
+
const collectionFields = columns.map((col) => collection.fields.get(col.dataIndex[0]));
|
|
89
|
+
const { rows, ranges } = await (0, import_renders.default)({ columns, fields: collectionFields, data, utcOffset: timezone }, this.db);
|
|
90
|
+
if (timezone) {
|
|
91
|
+
for (const data2 of rows) {
|
|
92
|
+
for (const key in data2) {
|
|
93
|
+
if (data2[key] instanceof Date) {
|
|
94
|
+
data2[key] = (0, import_utils.dayjs)(data2[key]).utcOffset(timezone).format("YYYY-MM-DD HH:mm:ss");
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
const stream = import_node_xlsx.default.build([
|
|
100
|
+
{
|
|
101
|
+
name: "Sheet 1",
|
|
102
|
+
data: rows,
|
|
103
|
+
options: {
|
|
104
|
+
"!merges": ranges
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
]);
|
|
108
|
+
const savePath = this.xlsxStorageDir();
|
|
109
|
+
if (!(0, import_fs.existsSync)(savePath)) {
|
|
110
|
+
(0, import_fs.mkdirSync)(savePath, { recursive: true });
|
|
111
|
+
}
|
|
112
|
+
const fileName = `${resourceName}_${(0, import_utils.dayjs)().format("YYYYMMDDHHmm")}.xlsx`;
|
|
113
|
+
const rawFile = `${savePath}/${fileName}`;
|
|
114
|
+
(0, import_fs.writeFileSync)(rawFile, Buffer.from(stream));
|
|
115
|
+
return `${ExportPlugin.defaultSavePath}/${fileName}`;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
var server_default = ExportPlugin;
|
|
119
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
120
|
+
0 && (module.exports = {
|
|
121
|
+
ExportPlugin
|
|
122
|
+
});
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
20
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
21
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
22
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
23
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
24
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
25
|
+
mod
|
|
26
|
+
));
|
|
27
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
28
|
+
var renders_exports = {};
|
|
29
|
+
__export(renders_exports, {
|
|
30
|
+
default: () => renders_default
|
|
31
|
+
});
|
|
32
|
+
module.exports = __toCommonJS(renders_exports);
|
|
33
|
+
var renders = __toESM(require("./renders"));
|
|
34
|
+
function getInterfaceRender(name) {
|
|
35
|
+
return renders[name] || renders._;
|
|
36
|
+
}
|
|
37
|
+
function renderHeader(params) {
|
|
38
|
+
const { columns, fields, headers = [], rowIndex = 0 } = params;
|
|
39
|
+
const { colIndex = 0 } = params;
|
|
40
|
+
if (!headers[rowIndex]) {
|
|
41
|
+
headers.push([]);
|
|
42
|
+
}
|
|
43
|
+
const row = headers[rowIndex];
|
|
44
|
+
fields.forEach((field, i) => {
|
|
45
|
+
const nextColIndex = colIndex + i;
|
|
46
|
+
row.push({
|
|
47
|
+
column: columns[i],
|
|
48
|
+
field,
|
|
49
|
+
rowIndex,
|
|
50
|
+
colIndex: nextColIndex
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
Object.assign(params, { headers });
|
|
54
|
+
}
|
|
55
|
+
async function renderRows({ columns, fields, data, utcOffset }, db) {
|
|
56
|
+
return await data.reduce(async (preResult, row) => {
|
|
57
|
+
const result = await preResult;
|
|
58
|
+
const thisRow = [];
|
|
59
|
+
const rowIndex = 0;
|
|
60
|
+
let colOffset = 0;
|
|
61
|
+
for (let i = 0, iLen = fields.length; i < iLen; i++) {
|
|
62
|
+
const field = fields[i];
|
|
63
|
+
if (!thisRow[rowIndex]) {
|
|
64
|
+
thisRow.push([]);
|
|
65
|
+
}
|
|
66
|
+
const cells = thisRow[rowIndex];
|
|
67
|
+
if (field.options.interface !== "subTable") {
|
|
68
|
+
const render = getInterfaceRender(field.options.interface);
|
|
69
|
+
const value = await render(field, row, { utcOffset, db }, columns[i]);
|
|
70
|
+
cells.push({
|
|
71
|
+
value,
|
|
72
|
+
rowIndex: result.length + rowIndex,
|
|
73
|
+
colIndex: i + colOffset
|
|
74
|
+
});
|
|
75
|
+
} else {
|
|
76
|
+
const subTable = db.getTable(field.target);
|
|
77
|
+
const subFields = subTable.getOptions().fields.filter((item) => Boolean(item.__index));
|
|
78
|
+
const subTableColumns = [];
|
|
79
|
+
const subRows = await renderRows(
|
|
80
|
+
{ columns: subTableColumns, fields: subFields, data: row.get(field.name) || [], utcOffset },
|
|
81
|
+
db
|
|
82
|
+
);
|
|
83
|
+
subRows.forEach((cells2, j) => {
|
|
84
|
+
const subRowIndex = rowIndex + j;
|
|
85
|
+
if (!thisRow[subRowIndex]) {
|
|
86
|
+
thisRow.push([]);
|
|
87
|
+
}
|
|
88
|
+
const subCells = thisRow[subRowIndex];
|
|
89
|
+
subCells.push(
|
|
90
|
+
...cells2.map((cell) => ({
|
|
91
|
+
...cell,
|
|
92
|
+
rowIndex: result.length + subRowIndex,
|
|
93
|
+
colIndex: cell.colIndex + i
|
|
94
|
+
}))
|
|
95
|
+
);
|
|
96
|
+
});
|
|
97
|
+
colOffset += subFields.length;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
thisRow.forEach((cells) => {
|
|
101
|
+
cells.forEach((cell) => {
|
|
102
|
+
const relRowIndex = cell.rowIndex - result.length;
|
|
103
|
+
Object.assign(cell, {
|
|
104
|
+
rowSpan: relRowIndex >= thisRow.length - 1 || thisRow[relRowIndex + 1].find((item) => item.colIndex === cell.colIndex) ? 1 : thisRow.length - relRowIndex
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
return result.concat(thisRow);
|
|
109
|
+
}, Promise.resolve([]));
|
|
110
|
+
}
|
|
111
|
+
async function renders_default({ columns, fields, data, utcOffset }, db) {
|
|
112
|
+
const headers = [];
|
|
113
|
+
renderHeader({ columns, fields, headers });
|
|
114
|
+
const ranges = [];
|
|
115
|
+
const maxColIndex = Math.max(...headers.map((row) => row[row.length - 1].colIndex));
|
|
116
|
+
headers.forEach((row, rowIndex) => {
|
|
117
|
+
row.forEach((cell, cellIndex) => {
|
|
118
|
+
cell.rowSpan = cell.rowIndex >= headers.length - 1 || headers[cell.rowIndex + 1].find((item) => item.colIndex === cell.colIndex) ? 1 : headers.length - cell.rowIndex;
|
|
119
|
+
const nextCell = headers.slice(0, rowIndex + 1).map((r) => r.find((item) => item.colIndex > cell.colIndex)).filter((c) => Boolean(c)).reduce((min, c) => min && Math.min(min.colIndex, c.colIndex) === min.colIndex ? min : c, null);
|
|
120
|
+
cell.colSpan = nextCell ? nextCell.colIndex - cell.colIndex : maxColIndex - cell.colIndex + 1;
|
|
121
|
+
if (cell.rowSpan > 1 || cell.colSpan > 1) {
|
|
122
|
+
ranges.push({
|
|
123
|
+
s: { c: cell.colIndex, r: cell.rowIndex },
|
|
124
|
+
e: { c: cell.colIndex + cell.colSpan - 1, r: cell.rowIndex + cell.rowSpan - 1 }
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
const rows = (await renderRows({ columns, fields, data, utcOffset }, db)).map((row) => {
|
|
130
|
+
const cells = Array(maxColIndex).fill(null);
|
|
131
|
+
row.forEach((cell) => {
|
|
132
|
+
cells.splice(cell.colIndex, 1, cell.value);
|
|
133
|
+
if (cell.rowSpan > 1) {
|
|
134
|
+
ranges.push({
|
|
135
|
+
s: { c: cell.colIndex, r: cell.rowIndex + headers.length },
|
|
136
|
+
e: { c: cell.colIndex, r: cell.rowIndex + cell.rowSpan - 1 + headers.length }
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
return cells;
|
|
141
|
+
});
|
|
142
|
+
return {
|
|
143
|
+
rows: [
|
|
144
|
+
...headers.map((row) => {
|
|
145
|
+
const cells = Array(maxColIndex).fill(null);
|
|
146
|
+
row.forEach(
|
|
147
|
+
(cell) => cells.splice(
|
|
148
|
+
cell.colIndex,
|
|
149
|
+
1,
|
|
150
|
+
cell.column.title ?? cell.column.defaultTitle ?? cell.column.dataIndex[cell.column.dataIndex.length - 1]
|
|
151
|
+
)
|
|
152
|
+
);
|
|
153
|
+
return cells;
|
|
154
|
+
}),
|
|
155
|
+
...rows
|
|
156
|
+
],
|
|
157
|
+
ranges
|
|
158
|
+
};
|
|
159
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export declare function _(field: any, row: any, ctx: any, column?: any): Promise<any>;
|
|
2
|
+
export declare function datetime(field: any, row: any, { utcOffset }: {
|
|
3
|
+
utcOffset: any;
|
|
4
|
+
}): Promise<any>;
|
|
5
|
+
export declare function percent(field: any, row: any, ctx: any): Promise<string>;
|
|
6
|
+
export declare function boolean(field: any, row: any, ctx: any, column?: any): Promise<any>;
|
|
7
|
+
export declare const checkbox: typeof boolean;
|
|
8
|
+
export declare function select(field: any, row: any, { db }: {
|
|
9
|
+
db: any;
|
|
10
|
+
}, column?: any): Promise<any>;
|
|
11
|
+
export declare function multipleSelect(field: any, row: any, { db }: {
|
|
12
|
+
db: any;
|
|
13
|
+
}, column?: any): Promise<any>;
|
|
14
|
+
export declare const radio: typeof select;
|
|
15
|
+
export declare const radioGroup: typeof select;
|
|
16
|
+
export declare const checkboxes: typeof multipleSelect;
|
|
17
|
+
export declare const checkboxGroup: typeof multipleSelect;
|
|
18
|
+
export declare function subTable(field: any, row: any, ctx: any): Promise<any>;
|
|
19
|
+
export declare function linkTo(field: any, row: any, ctx: any, column?: any): Promise<any>;
|
|
20
|
+
export declare function attachment(field: any, row: any, ctx: any): Promise<any>;
|
|
21
|
+
export declare function chinaRegion(field: any, row: any, ctx: any, column?: any): Promise<string>;
|