@steedos/service-ui 3.0.0-beta.99 → 3.0.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.
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
const querystring = require("querystring");
|
|
5
|
+
const odataV4Mongodb = require("@steedos/odata-v4-mongodb");
|
|
6
|
+
const filters_1 = require("@steedos/filters");
|
|
7
|
+
const auth_1 = require("@steedos/auth");
|
|
8
|
+
const moment = require("moment");
|
|
9
|
+
const json2xls = require("json2xls");
|
|
10
|
+
const objectql = require("@steedos/objectql");
|
|
11
|
+
const _ = require("lodash");
|
|
12
|
+
const objectql_1 = require("@steedos/objectql");
|
|
13
|
+
const express = require("express");
|
|
14
|
+
const router = express.Router();
|
|
15
|
+
const MAX_EXPORT = 5000;
|
|
16
|
+
const exportRecordData = function (req, res) {
|
|
17
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
18
|
+
try {
|
|
19
|
+
const userSession = req.user;
|
|
20
|
+
let userId = userSession.userId;
|
|
21
|
+
let urlParams = req.params;
|
|
22
|
+
let queryParams = req.query;
|
|
23
|
+
let filename = queryParams.filename;
|
|
24
|
+
delete queryParams.filename;
|
|
25
|
+
if (!filename) {
|
|
26
|
+
filename = "导出";
|
|
27
|
+
}
|
|
28
|
+
if (queryParams.filters) {
|
|
29
|
+
queryParams.$filter = (0, filters_1.formatFiltersToODataQuery)(JSON.parse(queryParams.filters), userSession);
|
|
30
|
+
}
|
|
31
|
+
const objectName = urlParams.objectName;
|
|
32
|
+
const collection = yield objectql.getObject(objectName);
|
|
33
|
+
if (!collection) {
|
|
34
|
+
res.status(404).send({ msg: `collection not exists: ${objectName}` });
|
|
35
|
+
}
|
|
36
|
+
removeInvalidMethod(queryParams);
|
|
37
|
+
let qs = decodeURIComponent(querystring.stringify(queryParams));
|
|
38
|
+
if (qs) {
|
|
39
|
+
var createQuery = odataV4Mongodb.createQuery(qs);
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
var createQuery = {
|
|
43
|
+
query: {},
|
|
44
|
+
sort: undefined,
|
|
45
|
+
projection: {},
|
|
46
|
+
includes: [],
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
let permissions = yield collection.getUserObjectPermission(userSession);
|
|
50
|
+
if (permissions.allowExport != true) {
|
|
51
|
+
return res
|
|
52
|
+
.status(403)
|
|
53
|
+
.send({ status: 403, error: 403, msg: `access failed` });
|
|
54
|
+
}
|
|
55
|
+
if (permissions.viewAllRecords ||
|
|
56
|
+
permissions.viewCompanyRecords ||
|
|
57
|
+
(permissions.allowRead && userId)) {
|
|
58
|
+
let entities = [];
|
|
59
|
+
let filters = queryParams.$filter || "";
|
|
60
|
+
let fields = [];
|
|
61
|
+
if (queryParams.$select) {
|
|
62
|
+
fields = _.keys(createQuery.projection);
|
|
63
|
+
}
|
|
64
|
+
if (isPlatformDriver(collection.datasource.driver)) {
|
|
65
|
+
filters = excludeDeleted(filters);
|
|
66
|
+
}
|
|
67
|
+
if (queryParams.$top !== "0") {
|
|
68
|
+
let query = {
|
|
69
|
+
filters: filters,
|
|
70
|
+
fields: fields,
|
|
71
|
+
top: Number(queryParams.$top),
|
|
72
|
+
};
|
|
73
|
+
if (Object.prototype.hasOwnProperty.call(queryParams, "$skip")) {
|
|
74
|
+
query["skip"] = Number(queryParams.$skip);
|
|
75
|
+
}
|
|
76
|
+
if (queryParams.$orderby) {
|
|
77
|
+
query["sort"] = queryParams.$orderby;
|
|
78
|
+
}
|
|
79
|
+
entities = yield collection.find(query, userSession);
|
|
80
|
+
}
|
|
81
|
+
if (entities.length > MAX_EXPORT) {
|
|
82
|
+
return res.status(403).send({
|
|
83
|
+
status: 403,
|
|
84
|
+
error: 403,
|
|
85
|
+
msg: `超出允许的导出记录数(${MAX_EXPORT}条), 请调整搜索条件后重试.`,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
if (entities) {
|
|
89
|
+
const fieldConfigs = (yield objectql
|
|
90
|
+
.getSteedosSchema()
|
|
91
|
+
.broker.call(`objectql.getRecordView`, { objectName }, { meta: { user: userSession } })).fields;
|
|
92
|
+
for (let i = 0; i < entities.length; i++) {
|
|
93
|
+
let record = entities[i];
|
|
94
|
+
delete record._id;
|
|
95
|
+
let parsedRecord = {};
|
|
96
|
+
let keys;
|
|
97
|
+
if (fields && fields.length > 0) {
|
|
98
|
+
keys = fields;
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
keys = _.keys(record);
|
|
102
|
+
}
|
|
103
|
+
for (let fieldName of keys) {
|
|
104
|
+
let fieldConfig = fieldConfigs[fieldName];
|
|
105
|
+
let fieldValue = record[fieldName];
|
|
106
|
+
if (!fieldConfig) {
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
if (fieldValue || fieldValue == false) {
|
|
110
|
+
parsedRecord = Object.assign(parsedRecord, {
|
|
111
|
+
[fieldConfig.label]: yield key2value(fieldValue, fieldConfig, userSession),
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
parsedRecord = Object.assign(parsedRecord, {
|
|
116
|
+
[fieldConfig.label]: null,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
entities[i] = parsedRecord;
|
|
121
|
+
}
|
|
122
|
+
if (_.isEmpty(entities)) {
|
|
123
|
+
entities.push({ "": "" });
|
|
124
|
+
}
|
|
125
|
+
var xls = json2xls(entities);
|
|
126
|
+
res.writeHead(200, {
|
|
127
|
+
"Content-Type": "application/octet-stream",
|
|
128
|
+
"Content-Disposition": "attachment;filename=" + encodeURI(filename + ".xlsx"),
|
|
129
|
+
"Content-Length": xls.length,
|
|
130
|
+
"Access-Control-Expose-Headers": "Content-Disposition",
|
|
131
|
+
});
|
|
132
|
+
res.end(xls, "binary");
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
res
|
|
136
|
+
.status(404)
|
|
137
|
+
.send({ code: 404, error: 404, message: "no record found" });
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
res.status(403).send({ code: 403, error: 403, message: `access failed` });
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
catch (error) {
|
|
145
|
+
let _handleError = handleError(error);
|
|
146
|
+
res.status(_handleError.statusCode).send(_handleError.body);
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
};
|
|
150
|
+
const handleError = function (e) {
|
|
151
|
+
console.log(e);
|
|
152
|
+
let body = {};
|
|
153
|
+
let error = {};
|
|
154
|
+
error["message"] = e.message;
|
|
155
|
+
let statusCode = 500;
|
|
156
|
+
if (e.error && _.isNumber(e.error)) {
|
|
157
|
+
statusCode = e.error;
|
|
158
|
+
}
|
|
159
|
+
error["code"] = statusCode;
|
|
160
|
+
error["error"] = statusCode;
|
|
161
|
+
error["details"] = e.details;
|
|
162
|
+
error["reason"] = e.reason;
|
|
163
|
+
body["error"] = error;
|
|
164
|
+
return {
|
|
165
|
+
statusCode: statusCode,
|
|
166
|
+
body: body,
|
|
167
|
+
};
|
|
168
|
+
};
|
|
169
|
+
const removeInvalidMethod = function (queryParams) {
|
|
170
|
+
if (queryParams.$filter && queryParams.$filter.indexOf("tolower(") > -1) {
|
|
171
|
+
let removeMethod = function ($1) {
|
|
172
|
+
return $1.replace("tolower(", "").replace(")", "");
|
|
173
|
+
};
|
|
174
|
+
queryParams.$filter = queryParams.$filter.replace(/tolower\(([^\)]+)\)/g, removeMethod);
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
function isPlatformDriver(driverName) {
|
|
178
|
+
if (driverName == objectql_1.SteedosDatabaseDriverType.Mongo ||
|
|
179
|
+
driverName == objectql_1.SteedosDatabaseDriverType.MeteorMongo) {
|
|
180
|
+
return true;
|
|
181
|
+
}
|
|
182
|
+
return false;
|
|
183
|
+
}
|
|
184
|
+
const excludeDeleted = function (filters) {
|
|
185
|
+
if (filters && filters.indexOf("(is_deleted eq true)") > -1) {
|
|
186
|
+
return filters;
|
|
187
|
+
}
|
|
188
|
+
return filters
|
|
189
|
+
? `(${filters}) and (is_deleted ne true)`
|
|
190
|
+
: `(is_deleted ne true)`;
|
|
191
|
+
};
|
|
192
|
+
const getOptionLabel = function (optionValue, options) {
|
|
193
|
+
let option = _.find(options, function (o) {
|
|
194
|
+
return o.value == optionValue;
|
|
195
|
+
});
|
|
196
|
+
if (option && option.label) {
|
|
197
|
+
return option.label;
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
return optionValue;
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
const key2value = function (fieldValue, fieldConfig, userSession) {
|
|
204
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
205
|
+
var _a;
|
|
206
|
+
switch (fieldConfig.type) {
|
|
207
|
+
case "boolean":
|
|
208
|
+
if (fieldValue) {
|
|
209
|
+
return t("form_field_checkbox_yes", {}, userSession.language);
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
return t("form_field_checkbox_no", {}, userSession.language);
|
|
213
|
+
}
|
|
214
|
+
case "select":
|
|
215
|
+
let options = fieldConfig.options;
|
|
216
|
+
if (fieldConfig.multiple && _.isArray(fieldValue)) {
|
|
217
|
+
for (let i = 0; i < fieldValue.length; i++) {
|
|
218
|
+
let newValue = getOptionLabel(fieldValue[i], options);
|
|
219
|
+
fieldValue[i] = newValue;
|
|
220
|
+
}
|
|
221
|
+
return fieldValue;
|
|
222
|
+
}
|
|
223
|
+
else {
|
|
224
|
+
return getOptionLabel(fieldValue, options);
|
|
225
|
+
}
|
|
226
|
+
case "master_detail":
|
|
227
|
+
case "lookup":
|
|
228
|
+
let reference_to = fieldConfig.reference_to;
|
|
229
|
+
let ref_coll;
|
|
230
|
+
let id = fieldValue;
|
|
231
|
+
if (_.isFunction(reference_to) ||
|
|
232
|
+
(fieldConfig._reference_to &&
|
|
233
|
+
fieldConfig._reference_to.startsWith("function"))) {
|
|
234
|
+
reference_to = fieldValue.o;
|
|
235
|
+
id = fieldConfig.multiple ? fieldValue.ids : fieldValue.ids[0];
|
|
236
|
+
}
|
|
237
|
+
ref_coll = yield objectql.getObject(reference_to);
|
|
238
|
+
const nameFieldKey = yield ref_coll.getNameFieldKey();
|
|
239
|
+
let reference_to_field = fieldConfig.reference_to_field;
|
|
240
|
+
let filters = [];
|
|
241
|
+
if (reference_to_field) {
|
|
242
|
+
filters[0] = reference_to_field;
|
|
243
|
+
}
|
|
244
|
+
else {
|
|
245
|
+
filters[0] = "_id";
|
|
246
|
+
}
|
|
247
|
+
if (!fieldConfig.multiple) {
|
|
248
|
+
filters[1] = "=";
|
|
249
|
+
filters[2] = id;
|
|
250
|
+
let ref_record = yield ref_coll.find({
|
|
251
|
+
filters: filters,
|
|
252
|
+
fields: [filters[0], nameFieldKey],
|
|
253
|
+
});
|
|
254
|
+
if (ref_record && ref_record.length == 1) {
|
|
255
|
+
return ref_record[0][nameFieldKey];
|
|
256
|
+
}
|
|
257
|
+
else {
|
|
258
|
+
return id;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
else {
|
|
262
|
+
filters[1] = "in";
|
|
263
|
+
filters[2] = id;
|
|
264
|
+
if (!_.isArray(id)) {
|
|
265
|
+
return id;
|
|
266
|
+
}
|
|
267
|
+
let ref_record = yield ref_coll.find({
|
|
268
|
+
filters: filters,
|
|
269
|
+
fields: [filters[0], nameFieldKey],
|
|
270
|
+
});
|
|
271
|
+
for (let i = 0; i < id.length; i++) {
|
|
272
|
+
let _record = _.find(ref_record, function (r) {
|
|
273
|
+
return r[filters[0]] == id[i];
|
|
274
|
+
});
|
|
275
|
+
if (_record) {
|
|
276
|
+
id[i] = _record[nameFieldKey];
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
return id;
|
|
280
|
+
}
|
|
281
|
+
case "date":
|
|
282
|
+
return moment(fieldValue).format("YYYY-MM-DD");
|
|
283
|
+
case "datetime":
|
|
284
|
+
return moment(fieldValue)
|
|
285
|
+
.utcOffset((_a = userSession.utcOffset) !== null && _a !== void 0 ? _a : 8)
|
|
286
|
+
.format("YYYY-MM-DD H:mm");
|
|
287
|
+
case "time":
|
|
288
|
+
return moment(fieldValue).utcOffset(0).format("HH:mm");
|
|
289
|
+
case "summary":
|
|
290
|
+
let summaryObj = yield objectql.getObject(fieldConfig.summary_object);
|
|
291
|
+
let summaryField = summaryObj.fields[fieldConfig.summary_field];
|
|
292
|
+
if (summaryField) {
|
|
293
|
+
return yield key2value(fieldValue, summaryField, userSession);
|
|
294
|
+
}
|
|
295
|
+
return fieldValue;
|
|
296
|
+
default:
|
|
297
|
+
return fieldValue;
|
|
298
|
+
}
|
|
299
|
+
});
|
|
300
|
+
};
|
|
301
|
+
router.get("/api/record/export/:objectName", auth_1.requireAuthentication, function (req, res) {
|
|
302
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
303
|
+
return yield exportRecordData(req, res);
|
|
304
|
+
});
|
|
305
|
+
});
|
|
306
|
+
exports.default = router;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@steedos/service-ui",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.1",
|
|
4
4
|
"main": "package.service.js",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"steedos"
|
|
@@ -11,15 +11,14 @@
|
|
|
11
11
|
"description": "steedos package",
|
|
12
12
|
"repository": {},
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"@steedos/auth": "3.0.
|
|
15
|
-
"@steedos/i18n": "3.0.
|
|
16
|
-
"@steedos/objectql": "3.0.
|
|
17
|
-
"express": "
|
|
14
|
+
"@steedos/auth": "3.0.1",
|
|
15
|
+
"@steedos/i18n": "3.0.1",
|
|
16
|
+
"@steedos/objectql": "3.0.1",
|
|
17
|
+
"express": "^5.1.0"
|
|
18
18
|
},
|
|
19
19
|
"license": "MIT",
|
|
20
|
-
"private": false,
|
|
21
20
|
"publishConfig": {
|
|
22
21
|
"access": "public"
|
|
23
22
|
},
|
|
24
|
-
"gitHead": "
|
|
23
|
+
"gitHead": "4bbcc1f1ba098d299f5c363e67679f001f715575"
|
|
25
24
|
}
|
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
import querystring = require("querystring");
|
|
2
|
+
import odataV4Mongodb = require("@steedos/odata-v4-mongodb");
|
|
3
|
+
import { formatFiltersToODataQuery } from "@steedos/filters";
|
|
4
|
+
import { requireAuthentication } from "@steedos/auth";
|
|
5
|
+
// const Fiber = require('fibers');
|
|
6
|
+
const moment = require("moment");
|
|
7
|
+
const json2xls = require("json2xls");
|
|
8
|
+
const objectql = require("@steedos/objectql");
|
|
9
|
+
const _ = require("lodash");
|
|
10
|
+
// export const exportExcelExpress = require('@steedos/router').staticRouter();;
|
|
11
|
+
import { SteedosDatabaseDriverType } from "@steedos/objectql";
|
|
12
|
+
const express = require("express");
|
|
13
|
+
const router = express.Router();
|
|
14
|
+
|
|
15
|
+
const MAX_EXPORT = 5000;
|
|
16
|
+
|
|
17
|
+
const exportRecordData = async function (req: any, res: any) {
|
|
18
|
+
try {
|
|
19
|
+
const userSession = req.user;
|
|
20
|
+
let userId = userSession.userId;
|
|
21
|
+
let urlParams = req.params;
|
|
22
|
+
let queryParams = req.query;
|
|
23
|
+
let filename = queryParams.filename;
|
|
24
|
+
delete queryParams.filename;
|
|
25
|
+
if (!filename) {
|
|
26
|
+
filename = "导出";
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (queryParams.filters) {
|
|
30
|
+
queryParams.$filter = formatFiltersToODataQuery(
|
|
31
|
+
JSON.parse(queryParams.filters),
|
|
32
|
+
userSession,
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const objectName = urlParams.objectName;
|
|
37
|
+
|
|
38
|
+
const collection = await objectql.getObject(objectName);
|
|
39
|
+
if (!collection) {
|
|
40
|
+
res.status(404).send({ msg: `collection not exists: ${objectName}` });
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
removeInvalidMethod(queryParams);
|
|
44
|
+
let qs = decodeURIComponent(
|
|
45
|
+
querystring.stringify(queryParams as querystring.ParsedUrlQueryInput),
|
|
46
|
+
);
|
|
47
|
+
if (qs) {
|
|
48
|
+
var createQuery = odataV4Mongodb.createQuery(qs);
|
|
49
|
+
} else {
|
|
50
|
+
var createQuery: any = {
|
|
51
|
+
query: {},
|
|
52
|
+
sort: undefined,
|
|
53
|
+
projection: {},
|
|
54
|
+
includes: [],
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
let permissions = await collection.getUserObjectPermission(userSession);
|
|
58
|
+
if (permissions.allowExport != true) {
|
|
59
|
+
return res
|
|
60
|
+
.status(403)
|
|
61
|
+
.send({ status: 403, error: 403, msg: `access failed` });
|
|
62
|
+
}
|
|
63
|
+
if (
|
|
64
|
+
permissions.viewAllRecords ||
|
|
65
|
+
permissions.viewCompanyRecords ||
|
|
66
|
+
(permissions.allowRead && userId)
|
|
67
|
+
) {
|
|
68
|
+
let entities: any[] = [];
|
|
69
|
+
let filters = (queryParams.$filter as string) || "";
|
|
70
|
+
let fields = [];
|
|
71
|
+
|
|
72
|
+
if (queryParams.$select) {
|
|
73
|
+
fields = _.keys(createQuery.projection);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (isPlatformDriver(collection.datasource.driver)) {
|
|
77
|
+
filters = excludeDeleted(filters);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (queryParams.$top !== "0") {
|
|
81
|
+
let query = {
|
|
82
|
+
filters: filters,
|
|
83
|
+
fields: fields,
|
|
84
|
+
top: Number(queryParams.$top),
|
|
85
|
+
};
|
|
86
|
+
if (Object.prototype.hasOwnProperty.call(queryParams, "$skip")) {
|
|
87
|
+
query["skip"] = Number(queryParams.$skip);
|
|
88
|
+
}
|
|
89
|
+
if (queryParams.$orderby) {
|
|
90
|
+
query["sort"] = queryParams.$orderby;
|
|
91
|
+
}
|
|
92
|
+
entities = await collection.find(query, userSession);
|
|
93
|
+
}
|
|
94
|
+
if (entities.length > MAX_EXPORT) {
|
|
95
|
+
return res.status(403).send({
|
|
96
|
+
status: 403,
|
|
97
|
+
error: 403,
|
|
98
|
+
msg: `超出允许的导出记录数(${MAX_EXPORT}条), 请调整搜索条件后重试.`,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
if (entities) {
|
|
102
|
+
const fieldConfigs = (
|
|
103
|
+
await objectql
|
|
104
|
+
.getSteedosSchema()
|
|
105
|
+
.broker.call(
|
|
106
|
+
`objectql.getRecordView`,
|
|
107
|
+
{ objectName },
|
|
108
|
+
{ meta: { user: userSession } },
|
|
109
|
+
)
|
|
110
|
+
).fields;
|
|
111
|
+
|
|
112
|
+
for (let i = 0; i < entities.length; i++) {
|
|
113
|
+
let record = entities[i];
|
|
114
|
+
delete record._id;
|
|
115
|
+
let parsedRecord = {};
|
|
116
|
+
|
|
117
|
+
let keys;
|
|
118
|
+
if (fields && fields.length > 0) {
|
|
119
|
+
keys = fields;
|
|
120
|
+
} else {
|
|
121
|
+
keys = _.keys(record);
|
|
122
|
+
}
|
|
123
|
+
for (let fieldName of keys) {
|
|
124
|
+
let fieldConfig = fieldConfigs[fieldName];
|
|
125
|
+
let fieldValue = record[fieldName];
|
|
126
|
+
|
|
127
|
+
if (!fieldConfig) {
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
if (fieldValue || fieldValue == false) {
|
|
131
|
+
// record[fieldName] = await key2value(fieldValue, fieldConfig);
|
|
132
|
+
parsedRecord = Object.assign(parsedRecord, {
|
|
133
|
+
[fieldConfig.label]: await key2value(
|
|
134
|
+
fieldValue,
|
|
135
|
+
fieldConfig,
|
|
136
|
+
userSession,
|
|
137
|
+
),
|
|
138
|
+
});
|
|
139
|
+
} else {
|
|
140
|
+
parsedRecord = Object.assign(parsedRecord, {
|
|
141
|
+
[fieldConfig.label]: null,
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
entities[i] = parsedRecord;
|
|
147
|
+
}
|
|
148
|
+
if (_.isEmpty(entities)) {
|
|
149
|
+
//生成空表格
|
|
150
|
+
entities.push({ "": "" });
|
|
151
|
+
}
|
|
152
|
+
var xls = json2xls(entities);
|
|
153
|
+
// fs.writeFileSync("test.xlsx", xls, 'binary');
|
|
154
|
+
res.writeHead(200, {
|
|
155
|
+
"Content-Type": "application/octet-stream",
|
|
156
|
+
"Content-Disposition":
|
|
157
|
+
"attachment;filename=" + encodeURI(filename + ".xlsx"),
|
|
158
|
+
"Content-Length": xls.length,
|
|
159
|
+
"Access-Control-Expose-Headers": "Content-Disposition",
|
|
160
|
+
});
|
|
161
|
+
res.end(xls, "binary");
|
|
162
|
+
} else {
|
|
163
|
+
res
|
|
164
|
+
.status(404)
|
|
165
|
+
.send({ code: 404, error: 404, message: "no record found" });
|
|
166
|
+
}
|
|
167
|
+
} else {
|
|
168
|
+
res.status(403).send({ code: 403, error: 403, message: `access failed` });
|
|
169
|
+
}
|
|
170
|
+
} catch (error) {
|
|
171
|
+
let _handleError = handleError(error);
|
|
172
|
+
res.status(_handleError.statusCode).send(_handleError.body);
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
const handleError = function (e: any) {
|
|
177
|
+
console.log(e);
|
|
178
|
+
let body = {};
|
|
179
|
+
let error = {};
|
|
180
|
+
error["message"] = e.message;
|
|
181
|
+
let statusCode = 500;
|
|
182
|
+
if (e.error && _.isNumber(e.error)) {
|
|
183
|
+
statusCode = e.error;
|
|
184
|
+
}
|
|
185
|
+
error["code"] = statusCode;
|
|
186
|
+
error["error"] = statusCode;
|
|
187
|
+
error["details"] = e.details;
|
|
188
|
+
error["reason"] = e.reason;
|
|
189
|
+
body["error"] = error;
|
|
190
|
+
return {
|
|
191
|
+
statusCode: statusCode,
|
|
192
|
+
body: body,
|
|
193
|
+
};
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
const removeInvalidMethod = function (queryParams: any) {
|
|
197
|
+
if (queryParams.$filter && queryParams.$filter.indexOf("tolower(") > -1) {
|
|
198
|
+
let removeMethod = function ($1: string) {
|
|
199
|
+
return $1.replace("tolower(", "").replace(")", "");
|
|
200
|
+
};
|
|
201
|
+
queryParams.$filter = queryParams.$filter.replace(
|
|
202
|
+
/tolower\(([^\)]+)\)/g,
|
|
203
|
+
removeMethod,
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* 判断是否是mongo或meteor-mongo驱动
|
|
210
|
+
* @param driverName 驱动名
|
|
211
|
+
* @returns
|
|
212
|
+
*/
|
|
213
|
+
function isPlatformDriver(driverName: string): boolean {
|
|
214
|
+
if (
|
|
215
|
+
driverName == SteedosDatabaseDriverType.Mongo ||
|
|
216
|
+
driverName == SteedosDatabaseDriverType.MeteorMongo
|
|
217
|
+
) {
|
|
218
|
+
return true;
|
|
219
|
+
}
|
|
220
|
+
return false;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
const excludeDeleted = function (filters: string) {
|
|
224
|
+
if (filters && filters.indexOf("(is_deleted eq true)") > -1) {
|
|
225
|
+
return filters;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
return filters
|
|
229
|
+
? `(${filters}) and (is_deleted ne true)`
|
|
230
|
+
: `(is_deleted ne true)`;
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
const getOptionLabel = function (optionValue, options) {
|
|
234
|
+
let option = _.find(options, function (o) {
|
|
235
|
+
return o.value == optionValue;
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
if (option && option.label) {
|
|
239
|
+
return option.label;
|
|
240
|
+
} else {
|
|
241
|
+
return optionValue;
|
|
242
|
+
}
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
const key2value = async function (fieldValue, fieldConfig, userSession) {
|
|
246
|
+
switch (fieldConfig.type) {
|
|
247
|
+
case "boolean":
|
|
248
|
+
if (fieldValue) {
|
|
249
|
+
return t("form_field_checkbox_yes", {}, userSession.language);
|
|
250
|
+
} else {
|
|
251
|
+
return t("form_field_checkbox_no", {}, userSession.language);
|
|
252
|
+
}
|
|
253
|
+
case "select":
|
|
254
|
+
let options = fieldConfig.options;
|
|
255
|
+
|
|
256
|
+
if (fieldConfig.multiple && _.isArray(fieldValue)) {
|
|
257
|
+
for (let i = 0; i < fieldValue.length; i++) {
|
|
258
|
+
let newValue = getOptionLabel(fieldValue[i], options);
|
|
259
|
+
fieldValue[i] = newValue;
|
|
260
|
+
}
|
|
261
|
+
return fieldValue;
|
|
262
|
+
} else {
|
|
263
|
+
return getOptionLabel(fieldValue, options);
|
|
264
|
+
}
|
|
265
|
+
case "master_detail":
|
|
266
|
+
case "lookup":
|
|
267
|
+
let reference_to = fieldConfig.reference_to;
|
|
268
|
+
let ref_coll: any;
|
|
269
|
+
let id = fieldValue;
|
|
270
|
+
// 判断reference_to是已经指定的对象名,还是通过function计算的对象名
|
|
271
|
+
if (
|
|
272
|
+
_.isFunction(reference_to) ||
|
|
273
|
+
(fieldConfig._reference_to &&
|
|
274
|
+
fieldConfig._reference_to.startsWith("function"))
|
|
275
|
+
) {
|
|
276
|
+
reference_to = fieldValue.o;
|
|
277
|
+
id = fieldConfig.multiple ? fieldValue.ids : fieldValue.ids[0];
|
|
278
|
+
}
|
|
279
|
+
ref_coll = await objectql.getObject(reference_to);
|
|
280
|
+
const nameFieldKey = await ref_coll.getNameFieldKey();
|
|
281
|
+
let reference_to_field = fieldConfig.reference_to_field;
|
|
282
|
+
let filters: any[] = [];
|
|
283
|
+
if (reference_to_field) {
|
|
284
|
+
filters[0] = reference_to_field;
|
|
285
|
+
} else {
|
|
286
|
+
filters[0] = "_id";
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
if (!fieldConfig.multiple) {
|
|
290
|
+
filters[1] = "=";
|
|
291
|
+
filters[2] = id;
|
|
292
|
+
let ref_record = await ref_coll.find({
|
|
293
|
+
filters: filters,
|
|
294
|
+
fields: [filters[0], nameFieldKey],
|
|
295
|
+
});
|
|
296
|
+
if (ref_record && ref_record.length == 1) {
|
|
297
|
+
return ref_record[0][nameFieldKey];
|
|
298
|
+
} else {
|
|
299
|
+
return id;
|
|
300
|
+
}
|
|
301
|
+
} else {
|
|
302
|
+
filters[1] = "in";
|
|
303
|
+
filters[2] = id;
|
|
304
|
+
// 如果id不是数组,则返回id
|
|
305
|
+
if (!_.isArray(id)) {
|
|
306
|
+
return id;
|
|
307
|
+
}
|
|
308
|
+
let ref_record = await ref_coll.find({
|
|
309
|
+
filters: filters,
|
|
310
|
+
fields: [filters[0], nameFieldKey],
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
for (let i = 0; i < id.length; i++) {
|
|
314
|
+
let _record = _.find(ref_record, function (r) {
|
|
315
|
+
return r[filters[0]] == id[i];
|
|
316
|
+
});
|
|
317
|
+
if (_record) {
|
|
318
|
+
id[i] = _record[nameFieldKey];
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
return id;
|
|
322
|
+
}
|
|
323
|
+
case "date":
|
|
324
|
+
return moment(fieldValue).format("YYYY-MM-DD");
|
|
325
|
+
case "datetime":
|
|
326
|
+
return moment(fieldValue)
|
|
327
|
+
.utcOffset(userSession.utcOffset ?? 8)
|
|
328
|
+
.format("YYYY-MM-DD H:mm");
|
|
329
|
+
case "time":
|
|
330
|
+
return moment(fieldValue).utcOffset(0).format("HH:mm");
|
|
331
|
+
case "summary":
|
|
332
|
+
let summaryObj = await objectql.getObject(fieldConfig.summary_object);
|
|
333
|
+
let summaryField = summaryObj.fields[fieldConfig.summary_field];
|
|
334
|
+
if (summaryField) {
|
|
335
|
+
return await key2value(fieldValue, summaryField, userSession);
|
|
336
|
+
}
|
|
337
|
+
return fieldValue;
|
|
338
|
+
default:
|
|
339
|
+
return fieldValue;
|
|
340
|
+
}
|
|
341
|
+
};
|
|
342
|
+
|
|
343
|
+
router.get(
|
|
344
|
+
"/api/record/export/:objectName",
|
|
345
|
+
requireAuthentication,
|
|
346
|
+
async function (req: any, res: any) {
|
|
347
|
+
return await exportRecordData(req, res);
|
|
348
|
+
},
|
|
349
|
+
);
|
|
350
|
+
exports.default = router;
|