@gingkoo/base-server 0.0.1-alpha.0 → 0.0.1-alpha.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/README.md +7 -0
- package/app.js +32 -40
- package/backend/common/entity.js +55 -0
- package/backend/common/enum.js +247 -0
- package/backend/common/fss/index.js +18 -0
- package/backend/common/fss/routers/attachment.js +45 -0
- package/backend/common/fss/routers/download.js +43 -0
- package/backend/common/fss/routers/import_export.js +113 -0
- package/backend/common/fss/routers/resources.js +149 -0
- package/backend/common/fss/routers/upload.js +81 -0
- package/backend/common/fss/services/import_export.js +159 -0
- package/backend/common/fss/services/index.js +92 -0
- package/backend/common/fss/utils.js +39 -0
- package/backend/common/ginfo/config.js +5 -0
- package/backend/common/ginfo/index.js +62 -0
- package/backend/common/index_template.html +28 -0
- package/backend/common/logger/index.js +96 -0
- package/backend/common/mapping.js +98 -0
- package/backend/common/middleware/auth.js +97 -0
- package/backend/common/middleware/cors.js +13 -0
- package/backend/common/middleware/response.js +25 -0
- package/backend/common/page_engine.js +487 -0
- package/backend/common/schedule.js +45 -0
- package/backend/common/services/dataCombine.js +67 -0
- package/backend/common/services/dept.js +37 -0
- package/backend/common/services/dict.js +487 -0
- package/backend/common/services/email.js +49 -0
- package/backend/common/services/generalConfig.js +137 -0
- package/backend/common/services/login.js +18 -0
- package/backend/common/services/notice.js +260 -0
- package/backend/common/services/permission.js +500 -0
- package/backend/common/services/roles.js +57 -0
- package/backend/common/services/send-notice.js +86 -0
- package/backend/common/services/task.js +259 -0
- package/backend/common/services/user.js +673 -0
- package/backend/common/socket.js +18 -0
- package/backend/common/sse/index.js +81 -0
- package/backend/common/sse/router.js +30 -0
- package/backend/common/task.js +75 -0
- package/backend/common/wechat/index.js +9 -0
- package/backend/common/wechat/routers/auth.js +238 -0
- package/{modules/user/frontend → backend/common/wechat/routers}/index.html +14 -7
- package/backend/common/wechat/services/auth.js +209 -0
- package/backend/common/wechat/services/notice.js +171 -0
- package/backend/config/index.js +63 -0
- package/backend/config/path.js +3 -0
- package/backend/router.js +96 -0
- package/backend/routers/app.js +222 -0
- package/backend/routers/automate.js +276 -0
- package/backend/routers/dict.js +370 -0
- package/backend/routers/email.js +85 -0
- package/backend/routers/generalConfig.js +276 -0
- package/backend/routers/idm.js +245 -0
- package/backend/routers/module.js +357 -0
- package/backend/routers/notice.js +138 -0
- package/backend/routers/pages.js +46 -0
- package/backend/routers/permission.js +985 -0
- package/backend/routers/setting.js +184 -0
- package/backend/routers/team/index.js +22 -0
- package/backend/routers/team/routers/mapping.js +29 -0
- package/backend/routers/team/routers/member.js +72 -0
- package/backend/routers/team/routers/membermanage.js +289 -0
- package/backend/routers/team/routers/pages.js +47 -0
- package/backend/routers/team/routers/roles.js +92 -0
- package/backend/routers/team/routers/teaminfo.js +27 -0
- package/backend/routers/team/routers/usergroup.js +213 -0
- package/backend/routers/team/services/mapping.js +101 -0
- package/backend/routers/team/services/member.js +206 -0
- package/backend/routers/team/services/roles.js +71 -0
- package/backend/routers/team/services/teaminfo.js +20 -0
- package/backend/routers/team/services/usergroup.js +128 -0
- package/backend/routers/user.js +436 -0
- package/backend/services/automate.js +60 -0
- package/backend/services/config.js +14 -0
- package/backend/services/module.js +298 -0
- package/backend/services/permission.js +192 -0
- package/backend/services/services.js +115 -0
- package/backend/services/setting.js +190 -0
- package/backend/services/token.js +42 -0
- package/backend/space.js +52 -0
- package/backend/space_mapping.js +15 -0
- package/backend/utils/avatar.js +48 -0
- package/backend/utils/color_gen_helper.js +20 -0
- package/backend/utils/date.js +66 -0
- package/backend/utils/excel.js +446 -0
- package/backend/utils/fs/doc.md +64 -0
- package/backend/utils/fs/index.js +127 -0
- package/backend/utils/jwt.js +54 -0
- package/backend/utils/modules/sequence.js +93 -0
- package/backend/utils/object.js +31 -0
- package/backend/utils/page-query-helper/index.js +61 -0
- package/backend/utils/path.js +123 -0
- package/backend/utils/run.js +25 -0
- package/backend/utils/tokenize.js +82 -0
- package/backend/utils/typeof.js +5 -0
- package/backend/utils/util.js +153 -0
- package/backend/views/api/index.js +32 -0
- package/backend/views/api/index.xml +49 -0
- package/backend/views/dict/index.js +80 -0
- package/backend/views/dict/index.xml +52 -0
- package/backend/views/index.js +32 -0
- package/backend/views/members_manage/index.js +68 -0
- package/backend/views/members_manage/index.xml +68 -0
- package/backend/views/roles/index.js +17 -0
- package/backend/views/roles/index.xml +47 -0
- package/backend/views/usergroup/index.js +68 -0
- package/backend/views/usergroup/index.xml +65 -0
- package/dist/assets/css/index-cc834b52.css +3 -0
- package/dist/assets/css/index-cc834b52.css.gz +0 -0
- package/dist/assets/js/index-9eef7474.js +762 -0
- package/dist/assets/js/index-9eef7474.js.gz +0 -0
- package/dist/assets/js/react-cropper.es-d3337769.js +10 -0
- package/dist/assets/js/react-cropper.es-d3337769.js.gz +0 -0
- package/dist/assets/png/u9-2348c304.png +0 -0
- package/dist/assets/woff2/materialicons-83be7b2f.woff2 +0 -0
- package/dist/index.html +162 -0
- package/package.json +60 -5
- package/common/router.js +0 -42
- package/modules/user/backend/index.js +0 -19
- package/modules/user/backend/routers/user.js +0 -11
- package/modules/user/frontend/index.js +0 -1
- package/serve.js +0 -9
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
const express = require('express');
|
|
3
|
+
const { fileExist, join, mkdirPath, saveFile } = require('../../../utils/path');
|
|
4
|
+
const config = require('../../../config/index');
|
|
5
|
+
const generateAvatar = require('../../../utils/avatar');
|
|
6
|
+
const userService = require('../../services/user');
|
|
7
|
+
const { resourcePath } = require('../utils');
|
|
8
|
+
|
|
9
|
+
var router = express.Router();
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @api {post} /fss/resources/avatar/:username 根据用户名显示 用户头像
|
|
13
|
+
* @apiVersion 1.0.0
|
|
14
|
+
* @apiGroup fss
|
|
15
|
+
*
|
|
16
|
+
* @apiQuery {string} username 用户名
|
|
17
|
+
*/
|
|
18
|
+
router.get('/avatar/:username', async function (req, res, next) {
|
|
19
|
+
let userid = req.get('X-UserId');
|
|
20
|
+
let { username } = req.params;
|
|
21
|
+
let user = await userService.getUserInfo(username === 'currentUser' ? userid : username);
|
|
22
|
+
if (user) {
|
|
23
|
+
let avatar = user?.AVATAR;
|
|
24
|
+
if (avatar) {
|
|
25
|
+
let filePath = '';
|
|
26
|
+
if (avatar.split('/').slice(-2)[0] !== 'avatars') {
|
|
27
|
+
//兼容下老版头像
|
|
28
|
+
filePath = resourcePath(userid, 'share', avatar.split('/').slice(-1)[0]);
|
|
29
|
+
} else {
|
|
30
|
+
filePath = resourcePath(userid, 'avatars', avatar.split('/').slice(-1)[0]);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (!filePath) {
|
|
34
|
+
return res.sendErr('resource not found');
|
|
35
|
+
}
|
|
36
|
+
filePath = decodeURIComponent(filePath);
|
|
37
|
+
|
|
38
|
+
let isExist = await fileExist(filePath);
|
|
39
|
+
if (isExist) {
|
|
40
|
+
var options = {
|
|
41
|
+
headers: {
|
|
42
|
+
'x-timestamp': Date.now(),
|
|
43
|
+
'x-sent': true,
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
res.sendFile(filePath, options);
|
|
48
|
+
} else {
|
|
49
|
+
res.sendErr('resource not found');
|
|
50
|
+
}
|
|
51
|
+
} else {
|
|
52
|
+
// 头像 附件存放位置
|
|
53
|
+
const attachmentPath = join(
|
|
54
|
+
config.app.home,
|
|
55
|
+
'storage',
|
|
56
|
+
global.orgid.toLowerCase(),
|
|
57
|
+
'avatars',
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
mkdirPath(attachmentPath);
|
|
61
|
+
|
|
62
|
+
let data = await generateAvatar.generate();
|
|
63
|
+
|
|
64
|
+
let localUrl = join(attachmentPath, username + '.svg');
|
|
65
|
+
await saveFile(localUrl, data);
|
|
66
|
+
|
|
67
|
+
let url = `/fss/resources/avatars/${username + '.svg'}`;
|
|
68
|
+
await userService.operTeamMember(username, {
|
|
69
|
+
AVATAR: url,
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
var options = {
|
|
73
|
+
headers: {
|
|
74
|
+
'x-timestamp': Date.now(),
|
|
75
|
+
'x-sent': true,
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
res.sendFile(localUrl, options);
|
|
80
|
+
}
|
|
81
|
+
} else {
|
|
82
|
+
res.sendErr('resource not found');
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* @api {post} /fss/resources/share/* 查看 share图片
|
|
88
|
+
* @apiGroup fss
|
|
89
|
+
*
|
|
90
|
+
*/
|
|
91
|
+
router.get('/share/*', async function (req, res, next) {
|
|
92
|
+
let userid = req.get('X-UserId');
|
|
93
|
+
let filePath = resourcePath(userid, 'share', req.path.split('/').slice(-1)[0]);
|
|
94
|
+
if (!filePath) {
|
|
95
|
+
res.sendErr('resource not found');
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
filePath = decodeURIComponent(filePath);
|
|
99
|
+
|
|
100
|
+
let isExist = await fileExist(filePath);
|
|
101
|
+
if (isExist) {
|
|
102
|
+
var options = {
|
|
103
|
+
headers: {
|
|
104
|
+
'x-timestamp': Date.now(),
|
|
105
|
+
'x-sent': true,
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
res.sendFile(filePath, options);
|
|
110
|
+
} else {
|
|
111
|
+
res.sendErr('resource not found');
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
// 图片查看 /fss/resources/share/1.png
|
|
116
|
+
// 图片头像 /fss/resources/avatar/1.png
|
|
117
|
+
/**
|
|
118
|
+
* @api {post} /fss/resources/:fileFolder/* 查看图片
|
|
119
|
+
* @apiVersion 1.0.0
|
|
120
|
+
* @apiGroup fss
|
|
121
|
+
*
|
|
122
|
+
* @apiQuery {string} fileFolder 文件存放文件夹 share | avatar
|
|
123
|
+
*/
|
|
124
|
+
router.get('/:fileFolder/*', async function (req, res, next) {
|
|
125
|
+
let userid = req.get('X-UserId');
|
|
126
|
+
let { fileFolder } = req.params;
|
|
127
|
+
let filePath = resourcePath(userid, fileFolder, req.path.split('/').slice(-1)[0]);
|
|
128
|
+
if (!filePath) {
|
|
129
|
+
res.sendErr('resource not found');
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
filePath = decodeURIComponent(filePath);
|
|
133
|
+
|
|
134
|
+
let isExist = await fileExist(filePath);
|
|
135
|
+
if (isExist) {
|
|
136
|
+
var options = {
|
|
137
|
+
headers: {
|
|
138
|
+
'x-timestamp': Date.now(),
|
|
139
|
+
'x-sent': true,
|
|
140
|
+
},
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
res.sendFile(filePath, options);
|
|
144
|
+
} else {
|
|
145
|
+
res.sendErr('resource not found');
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
module.exports = router;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
const { v4: uuidv4 } = require('uuid');
|
|
3
|
+
const express = require('express');
|
|
4
|
+
const multer = require('multer');
|
|
5
|
+
const sizeOf = require('image-size');
|
|
6
|
+
const { mkdirPath } = require('../../../utils/path');
|
|
7
|
+
const { resourcePath } = require('../utils');
|
|
8
|
+
|
|
9
|
+
var router = express.Router();
|
|
10
|
+
|
|
11
|
+
const multerUpload = multer({
|
|
12
|
+
storage: multer.diskStorage({
|
|
13
|
+
// 设置存储路径
|
|
14
|
+
destination(req, res, cb) {
|
|
15
|
+
const { fileFolder = 'share' } = req.query;
|
|
16
|
+
// 附件存放位置
|
|
17
|
+
let attachmentPath = resourcePath('', fileFolder, '');
|
|
18
|
+
let dest = mkdirPath(attachmentPath);
|
|
19
|
+
cb(null, dest);
|
|
20
|
+
},
|
|
21
|
+
// 设置存储的文件名
|
|
22
|
+
filename(req, file, cb) {
|
|
23
|
+
let fileName = file.originalname;
|
|
24
|
+
let fileNameLen = fileName.length;
|
|
25
|
+
let lastPointIndex = fileName.lastIndexOf('.');
|
|
26
|
+
let pointIndex = ~lastPointIndex ? lastPointIndex : fileNameLen;
|
|
27
|
+
let suffixLen = fileNameLen - pointIndex; // 没有后缀为 0
|
|
28
|
+
let suffixStr = fileName.slice(pointIndex); // 带.
|
|
29
|
+
|
|
30
|
+
// 去掉后缀,并限制带上后缀 不超过 56 个字符
|
|
31
|
+
fileName = fileName.slice(0, Math.min(fileNameLen, 56) - suffixLen);
|
|
32
|
+
|
|
33
|
+
function sStr() {
|
|
34
|
+
return uuidv4()
|
|
35
|
+
.replaceAll('-', '')
|
|
36
|
+
.match(/(\w{6})/g)[1];
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
cb(null, `${fileName}__${sStr()}${suffixStr}`);
|
|
40
|
+
},
|
|
41
|
+
}),
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @api {post} /fss/upload/attachment 文件上传
|
|
46
|
+
* @apiVersion 1.0.0
|
|
47
|
+
* @apiGroup fss
|
|
48
|
+
* @apiDescription 图片,文件都行
|
|
49
|
+
*
|
|
50
|
+
*/
|
|
51
|
+
router.post('/attachment', multerUpload.any(), async (req, res) => {
|
|
52
|
+
req.clearTimeout();
|
|
53
|
+
const { fileFolder = 'share' } = req.query;
|
|
54
|
+
let filesInfo = req.files.map((file) => {
|
|
55
|
+
return {
|
|
56
|
+
FILE_NAME: file['filename'],
|
|
57
|
+
FILE_TYPE: file['mimetype'],
|
|
58
|
+
path: file['path'],
|
|
59
|
+
size: file['size'],
|
|
60
|
+
};
|
|
61
|
+
})[0];
|
|
62
|
+
|
|
63
|
+
let width = 0,
|
|
64
|
+
height = 0;
|
|
65
|
+
try {
|
|
66
|
+
const dimensions = sizeOf(filesInfo['path']);
|
|
67
|
+
width = dimensions.width;
|
|
68
|
+
height = dimensions.height;
|
|
69
|
+
} catch (error) {}
|
|
70
|
+
|
|
71
|
+
res.sendOk({
|
|
72
|
+
value: `/fss/resources/${fileFolder}/${filesInfo.FILE_NAME}`,
|
|
73
|
+
width,
|
|
74
|
+
height,
|
|
75
|
+
size: filesInfo.size,
|
|
76
|
+
type: filesInfo.FILE_TYPE,
|
|
77
|
+
name: filesInfo.FILE_NAME,
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
module.exports = router;
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
const { v4: uuidv4 } = require('uuid');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const dayjs = require('dayjs');
|
|
5
|
+
const { format: timeFormat } = require('date-fns');
|
|
6
|
+
const { creatTask } = require('../../services/task');
|
|
7
|
+
const { sse, bgTaskEnum } = require('../../sse');
|
|
8
|
+
const tasks = require('../../task');
|
|
9
|
+
|
|
10
|
+
module.exports = {
|
|
11
|
+
/**
|
|
12
|
+
* 上传文件 - 插入表
|
|
13
|
+
* @param {string} USER_ID 当前登录用户
|
|
14
|
+
* @param {any[]} filesInfo 文件信息
|
|
15
|
+
* @param {object} options 参数
|
|
16
|
+
*/
|
|
17
|
+
async uploadFiles(USER_ID, filesInfo, options) {
|
|
18
|
+
let { FWD, MODULE_ID, ...rest } = options;
|
|
19
|
+
let strUUID = uuidv4().replaceAll('-', '');
|
|
20
|
+
let taskId = '';
|
|
21
|
+
|
|
22
|
+
for (let i in filesInfo) {
|
|
23
|
+
let params = {
|
|
24
|
+
ORG_ID: global.orgid,
|
|
25
|
+
REQ_ID: strUUID,
|
|
26
|
+
USER_ID,
|
|
27
|
+
STATUS: '00',
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
for (let k in filesInfo[i]) {
|
|
31
|
+
if (k in params) {
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
params[k] = filesInfo[i][k];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
let TASK_NAME = await tasks.getTaskName(MODULE_ID, FWD, rest, 'Excel文件导入');
|
|
39
|
+
|
|
40
|
+
let curDate = timeFormat(new Date(), 'yyyyMMdd');
|
|
41
|
+
let curTime = timeFormat(new Date(), 'yyyyMMddHHmmssSSSS');
|
|
42
|
+
|
|
43
|
+
let [err, taskResult] = await creatTask({
|
|
44
|
+
USER_ID,
|
|
45
|
+
FILE_NAME: params['FILE_NAME'],
|
|
46
|
+
FILE_DIR: params['UPLOAD_DIR'],
|
|
47
|
+
TASK_TYPE: 'excelImport',
|
|
48
|
+
TASK_NAME,
|
|
49
|
+
MODULE_ID: 'import',
|
|
50
|
+
TASK_SERVICE: FWD,
|
|
51
|
+
DATA_CRT_DATE: curDate,
|
|
52
|
+
DATA_CRT_TIME: curTime,
|
|
53
|
+
DATA_UPD_DATE: curDate,
|
|
54
|
+
DATA_UPD_TIME: curTime,
|
|
55
|
+
defaultDate: false,
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
if (err) {
|
|
59
|
+
return [err];
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
taskId = taskResult.TASK;
|
|
63
|
+
sse.addBgTasks(
|
|
64
|
+
{
|
|
65
|
+
USER_ID,
|
|
66
|
+
FILE_NAME: params['FILE_NAME'],
|
|
67
|
+
FILE_DIR: params['UPLOAD_DIR'],
|
|
68
|
+
TASK_TYPE: 'excelImport',
|
|
69
|
+
TASK_NAME,
|
|
70
|
+
MODULE_ID: 'import',
|
|
71
|
+
TASK_SERVICE: FWD,
|
|
72
|
+
TASK_ID: result?.TASK,
|
|
73
|
+
taskProgressStatus: bgTaskEnum.taskProgressStatus.dataLoading,
|
|
74
|
+
STATUS: 'Pending',
|
|
75
|
+
DATA_CRT_DATE: curDate,
|
|
76
|
+
DATA_CRT_TIME: curTime,
|
|
77
|
+
},
|
|
78
|
+
USER_ID,
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
let FILE_PATH = path.join(params['UPLOAD_DIR'], params['FILE_NAME']);
|
|
82
|
+
tasks.run(MODULE_ID, FWD, USER_ID, taskId, { ...rest, FILE_PATH });
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return [
|
|
86
|
+
false,
|
|
87
|
+
{
|
|
88
|
+
TASK: taskId,
|
|
89
|
+
},
|
|
90
|
+
];
|
|
91
|
+
},
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* 下载文件
|
|
95
|
+
* @param {string} USER_ID 当前登录用户
|
|
96
|
+
* @param {string} moduleId 模块id
|
|
97
|
+
* @param {object} options 参数
|
|
98
|
+
*/
|
|
99
|
+
async downloadFile(USER_ID, moduleId, options) {
|
|
100
|
+
let { FWD, ...rest } = options;
|
|
101
|
+
|
|
102
|
+
let curTime = dayjs().format('YYYYMMDDHHmmss');
|
|
103
|
+
let FILE_NAME = moduleId + '_' + curTime + '.xlsx';
|
|
104
|
+
let storageDir = path.join(config['app']['home'], 'storage');
|
|
105
|
+
let dir = path.join(global.orgid.toLowerCase(), 'users', USER_ID);
|
|
106
|
+
let FILE_DIR = path.join(storageDir, dir);
|
|
107
|
+
|
|
108
|
+
// 创建目录 - TODO.这里不应该先判断存不存在吗
|
|
109
|
+
fs.mkdirSync(FILE_DIR, { recursive: true });
|
|
110
|
+
|
|
111
|
+
let TASK_NAME = await tasks.getTaskName(MODULE_ID, FWD, rest, 'Excel文件导出');
|
|
112
|
+
|
|
113
|
+
let curDate = timeFormat(new Date(), 'yyyyMMdd');
|
|
114
|
+
let curTime1 = timeFormat(new Date(), 'yyyyMMddHHmmssSSSS');
|
|
115
|
+
|
|
116
|
+
let [err, result] = await creatTask({
|
|
117
|
+
USER_ID,
|
|
118
|
+
FILE_NAME,
|
|
119
|
+
FILE_DIR: dir, // 这里为什么不拼上 storageDir,这里不拼,那下载不也得拼吗?
|
|
120
|
+
TASK_TYPE: 'excelExport',
|
|
121
|
+
TASK_NAME,
|
|
122
|
+
MODULE_ID: moduleId,
|
|
123
|
+
TASK_SERVICE: FWD,
|
|
124
|
+
DATA_CRT_DATE: curDate,
|
|
125
|
+
DATA_CRT_TIME: curTime1,
|
|
126
|
+
DATA_UPD_DATE: curDate,
|
|
127
|
+
DATA_UPD_TIME: curTime1,
|
|
128
|
+
defaultDate: false,
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
if (err) {
|
|
132
|
+
return [err];
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// 添加后台任务
|
|
136
|
+
sse.addBgTasks(
|
|
137
|
+
{
|
|
138
|
+
USER_ID,
|
|
139
|
+
FILE_NAME,
|
|
140
|
+
FILE_DIR: dir, // 这里为什么不拼上 storageDir,这里不拼,那下载不也得拼吗?
|
|
141
|
+
TASK_TYPE: 'excelExport',
|
|
142
|
+
TASK_NAME,
|
|
143
|
+
MODULE_ID: moduleId,
|
|
144
|
+
TASK_SERVICE: FWD,
|
|
145
|
+
TASK_ID: result.TASK,
|
|
146
|
+
taskProgressStatus: bgTaskEnum.taskProgressStatus.exportOutData,
|
|
147
|
+
STATUS: 'Pending',
|
|
148
|
+
DATA_CRT_TIME: curTime1,
|
|
149
|
+
DATA_CRT_DATE: curDate,
|
|
150
|
+
},
|
|
151
|
+
USER_ID,
|
|
152
|
+
);
|
|
153
|
+
|
|
154
|
+
let FILE_PATH = path.join(FILE_DIR, FILE_NAME);
|
|
155
|
+
tasks.run(MODULE_ID, FWD, USER_ID, result.TASK, { ...rest, FILE_PATH });
|
|
156
|
+
|
|
157
|
+
return [false, result];
|
|
158
|
+
},
|
|
159
|
+
};
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
const { v4: uuidv4 } = require('uuid');
|
|
2
|
+
const { insertSqlBuilder, sqlExecutor, queryParamsBuilder } = require('@gingkoo/node-tools');
|
|
3
|
+
const entity = require('../../entity');
|
|
4
|
+
const { cleanUselessKey } = require('../../../utils/util');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* 查询附件
|
|
8
|
+
* @param {*} orgid
|
|
9
|
+
* @param {string?} OBJECT_ID 附件绑定对象id
|
|
10
|
+
* @param {string?} REF_ID 关联id
|
|
11
|
+
* @param {image | doc ?} FILE_KIND 文件类型
|
|
12
|
+
* @returns { FILE_KIND: 'image', FILE_NAME: '1102-001__440a25.png' }[]
|
|
13
|
+
*/
|
|
14
|
+
async function findAttachment({ OBJECT_ID, REF_ID, FILE_KIND }) {
|
|
15
|
+
let sql = `select * from ${entity.BASE_ATTACHMENTS} where `;
|
|
16
|
+
let filter = cleanUselessKey({
|
|
17
|
+
ORG_ID: global.orgid,
|
|
18
|
+
OBJECT_ID,
|
|
19
|
+
REF_ID,
|
|
20
|
+
FILE_KIND,
|
|
21
|
+
STATUS: '00',
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
let sqlResult = queryParamsBuilder(filter);
|
|
25
|
+
sql += sqlResult.sql;
|
|
26
|
+
let dbResult = await sqlExecutor(sql, sqlResult.params);
|
|
27
|
+
if (dbResult.error) {
|
|
28
|
+
return [];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return dbResult.results.map((v) => {
|
|
32
|
+
return { FILE_KIND: v.FILE_KIND, FILE_NAME: v.FILE_NAME };
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* 根据条件 删除附件
|
|
38
|
+
* @param {string?} DATA_ID 附件ID
|
|
39
|
+
* @param {string?} OBJECT_ID 附件绑定对象id
|
|
40
|
+
* @param {string?} REF_ID 关联id
|
|
41
|
+
* @param {string?} FILE_NAME 文件名
|
|
42
|
+
* @param {image | doc ?} FILE_KIND 文件类型
|
|
43
|
+
*/
|
|
44
|
+
async function discardAttachment({ OBJECT_ID, DATA_ID, REF_ID, FILE_NAME, FILE_KIND }) {
|
|
45
|
+
let sql = `update ${entity.BASE_ATTACHMENTS} set STATUS = '01' WHERE `;
|
|
46
|
+
let filter = cleanUselessKey({
|
|
47
|
+
ORG_ID: global.orgid,
|
|
48
|
+
OBJECT_ID,
|
|
49
|
+
DATA_ID,
|
|
50
|
+
REF_ID,
|
|
51
|
+
FILE_NAME,
|
|
52
|
+
FILE_KIND,
|
|
53
|
+
});
|
|
54
|
+
let sqlResult = queryParamsBuilder(filter);
|
|
55
|
+
sql += sqlResult.sql;
|
|
56
|
+
await sqlExecutor(sql, sqlResult.params);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* 添加附件
|
|
61
|
+
* @param {string} orgid
|
|
62
|
+
* @param {string} userid
|
|
63
|
+
* @param {object} filesInfo {FILE_NAME: 文件名, FILE_TYPE: 文件类型 也就是文件后缀}
|
|
64
|
+
* @param {string} options.MODULE_ID 模块ID project user
|
|
65
|
+
* @param {image | doc} options.FILE_KIND 文件种类
|
|
66
|
+
* @param {string} options.OBJECT_ID: 附件绑定对象id
|
|
67
|
+
* @param {string} options.REF_ID: 关联id
|
|
68
|
+
* @param {string} options.FSS_PATH: storage中的路径
|
|
69
|
+
* @param {'00' | '01'} options.STATUS: 状态 (00正常 01已删除)
|
|
70
|
+
*/
|
|
71
|
+
async function addAttachment(userid, filesInfo, options) {
|
|
72
|
+
let strUUID = uuidv4().replaceAll('-', '');
|
|
73
|
+
|
|
74
|
+
let params = Object.assign(
|
|
75
|
+
{
|
|
76
|
+
ORG_ID: global.orgid,
|
|
77
|
+
DATA_ID: strUUID,
|
|
78
|
+
USER_ID: userid,
|
|
79
|
+
},
|
|
80
|
+
filesInfo,
|
|
81
|
+
options,
|
|
82
|
+
);
|
|
83
|
+
let sqlResult = insertSqlBuilder(entity.BASE_ATTACHMENTS, params);
|
|
84
|
+
let res = await sqlExecutor(sqlResult.sql, sqlResult.params);
|
|
85
|
+
return res;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
module.exports = {
|
|
89
|
+
findAttachment,
|
|
90
|
+
addAttachment,
|
|
91
|
+
discardAttachment,
|
|
92
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const config = require('../../config/index');
|
|
3
|
+
/**
|
|
4
|
+
* 获取文件位置
|
|
5
|
+
* 一个是通过类型来 获取文件存放位置
|
|
6
|
+
* resourcePath('', fileFolder, '')
|
|
7
|
+
* 获取文件存放位置
|
|
8
|
+
* resourcePath('', fileFolder, filename)
|
|
9
|
+
* @param {*} userid 暂时没用
|
|
10
|
+
* @param {*} fileFolder //文件通过类型,判断文件存放位置
|
|
11
|
+
* @param {string} filePath //文件名称
|
|
12
|
+
* @returns
|
|
13
|
+
*/
|
|
14
|
+
function resourcePath(userid = '', fileFolder, filePath = '') {
|
|
15
|
+
let basePath = path.join(config.app.home, 'storage');
|
|
16
|
+
let fileRealPath = path.join(basePath, global.orgid.toLowerCase(), filePath);
|
|
17
|
+
|
|
18
|
+
if (fileFolder == 'users') {
|
|
19
|
+
filePath = filePath.split('/').slice(-2, -1)[0];
|
|
20
|
+
} else if (fileFolder == 'depts') {
|
|
21
|
+
} else if (fileFolder == 'groups') {
|
|
22
|
+
} else if (fileFolder == 'share') {
|
|
23
|
+
} else if (fileFolder == 'public') {
|
|
24
|
+
} else if (fileFolder == 'avatars') {
|
|
25
|
+
fileRealPath = path.join(basePath, global.orgid.toLowerCase(), 'avatars', filePath);
|
|
26
|
+
} else if (fileFolder == 'chat') {
|
|
27
|
+
fileRealPath = path.join(basePath, global.orgid.toLowerCase(), 'chat', filePath);
|
|
28
|
+
} else if (fileFolder == 'avatar') {
|
|
29
|
+
} else if (fileFolder == 'upload') {
|
|
30
|
+
fileRealPath = path.join(config.app.home, filePath);
|
|
31
|
+
} else {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
return fileRealPath;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
module.exports = {
|
|
38
|
+
resourcePath,
|
|
39
|
+
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
var httpclient = require('node-httpclient');
|
|
2
|
+
var { logger } = require('../logger/index');
|
|
3
|
+
var config = require('./config');
|
|
4
|
+
|
|
5
|
+
async function getAccessToken() {
|
|
6
|
+
url = '{host}/api/auth/gettoken?app_id={app_id}&app_key={app_key}'.format(config);
|
|
7
|
+
|
|
8
|
+
const resp = await httpclient.get(url);
|
|
9
|
+
const json_data = resp.data;
|
|
10
|
+
|
|
11
|
+
if (json_data['ret_code'] != '0') {
|
|
12
|
+
logger.error('error:{0}'.format(json_data['ret_msg']));
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const accessToken = json_data['access_token'];
|
|
17
|
+
|
|
18
|
+
return accessToken;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async function apiRequest(url_path, method, data) {
|
|
22
|
+
const accessToken = await getAccessToken();
|
|
23
|
+
const url = config['host'] + url_path;
|
|
24
|
+
|
|
25
|
+
try {
|
|
26
|
+
resp = await httpclient.ajax(url, {
|
|
27
|
+
method: method,
|
|
28
|
+
contentType: 'application/json',
|
|
29
|
+
data: data,
|
|
30
|
+
headers: {
|
|
31
|
+
Authorization: 'Bearer {0}'.format(accessToken),
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
} catch (e) {
|
|
35
|
+
console.log(e);
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
json_data = resp.data;
|
|
40
|
+
|
|
41
|
+
return json_data;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async function getUserInfo(qywxuserid) {
|
|
45
|
+
const url = '/api/users/{0}'.format(qywxuserid);
|
|
46
|
+
const ginfo_data = await apiRequest(url, 'GET', {});
|
|
47
|
+
if (ginfo_data == null || ginfo_data['ret_code'] != '0') {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const user_id = ginfo_data['data']['USER_NAME'];
|
|
52
|
+
if (user_id == null || user_id.length == 0) {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return ginfo_data['data'];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
module.exports = Ginfo = {
|
|
60
|
+
getUserInfo,
|
|
61
|
+
apiRequest,
|
|
62
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<title>{title}</title>
|
|
6
|
+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
|
7
|
+
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
|
|
8
|
+
<meta name="renderer" content="webkit" />
|
|
9
|
+
<meta name="force-rendering" content="webkit" />
|
|
10
|
+
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
|
|
11
|
+
<link rel="stylesheet" href="https://cdn.gingkoo.com/pandora/1.0.1/pandora.min.css" />
|
|
12
|
+
<link rel="stylesheet" type="text/css" href="/static/css/index.css" />
|
|
13
|
+
</head>
|
|
14
|
+
|
|
15
|
+
<body>
|
|
16
|
+
<div id="root" class="app-wrapper"></div>
|
|
17
|
+
|
|
18
|
+
<script src="https://cdn.gingkoo.com/pandora/1.0.1/pandora.min.js"></script>
|
|
19
|
+
<script>
|
|
20
|
+
let schema = '{{schema}}';
|
|
21
|
+
let props = {};
|
|
22
|
+
let env = {
|
|
23
|
+
baseURL: '',
|
|
24
|
+
};
|
|
25
|
+
Pandora.embed('#root', schema, props, env);
|
|
26
|
+
</script>
|
|
27
|
+
</body>
|
|
28
|
+
</html>
|