@gingkoo/base-server 0.0.1-alpha.0 → 0.0.1-alpha.2

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.
Files changed (122) hide show
  1. package/README.md +7 -0
  2. package/app.js +36 -40
  3. package/backend/common/entity.js +55 -0
  4. package/backend/common/enum.js +247 -0
  5. package/backend/common/fss/index.js +18 -0
  6. package/backend/common/fss/routers/attachment.js +45 -0
  7. package/backend/common/fss/routers/download.js +43 -0
  8. package/backend/common/fss/routers/import_export.js +113 -0
  9. package/backend/common/fss/routers/resources.js +149 -0
  10. package/backend/common/fss/routers/upload.js +81 -0
  11. package/backend/common/fss/services/import_export.js +159 -0
  12. package/backend/common/fss/services/index.js +92 -0
  13. package/backend/common/fss/utils.js +39 -0
  14. package/backend/common/ginfo/config.js +5 -0
  15. package/backend/common/ginfo/index.js +62 -0
  16. package/backend/common/index_template.html +28 -0
  17. package/backend/common/logger/index.js +96 -0
  18. package/backend/common/mapping.js +98 -0
  19. package/backend/common/middleware/auth.js +97 -0
  20. package/backend/common/middleware/cors.js +13 -0
  21. package/backend/common/middleware/response.js +25 -0
  22. package/backend/common/page_engine.js +487 -0
  23. package/backend/common/schedule.js +45 -0
  24. package/backend/common/services/dataCombine.js +67 -0
  25. package/backend/common/services/dept.js +37 -0
  26. package/backend/common/services/dict.js +487 -0
  27. package/backend/common/services/email.js +49 -0
  28. package/backend/common/services/generalConfig.js +137 -0
  29. package/backend/common/services/login.js +18 -0
  30. package/backend/common/services/notice.js +260 -0
  31. package/backend/common/services/permission.js +500 -0
  32. package/backend/common/services/roles.js +57 -0
  33. package/backend/common/services/send-notice.js +86 -0
  34. package/backend/common/services/task.js +259 -0
  35. package/backend/common/services/user.js +673 -0
  36. package/backend/common/socket.js +18 -0
  37. package/backend/common/sse/index.js +81 -0
  38. package/backend/common/sse/router.js +30 -0
  39. package/backend/common/task.js +75 -0
  40. package/backend/common/wechat/index.js +9 -0
  41. package/backend/common/wechat/routers/auth.js +238 -0
  42. package/{modules/user/frontend → backend/common/wechat/routers}/index.html +14 -7
  43. package/backend/common/wechat/services/auth.js +209 -0
  44. package/backend/common/wechat/services/notice.js +171 -0
  45. package/backend/config/index.js +63 -0
  46. package/backend/config/path.js +3 -0
  47. package/backend/router.js +96 -0
  48. package/backend/routers/app.js +222 -0
  49. package/backend/routers/automate.js +276 -0
  50. package/backend/routers/dict.js +370 -0
  51. package/backend/routers/email.js +85 -0
  52. package/backend/routers/generalConfig.js +276 -0
  53. package/backend/routers/idm.js +245 -0
  54. package/backend/routers/module.js +357 -0
  55. package/backend/routers/notice.js +138 -0
  56. package/backend/routers/pages.js +46 -0
  57. package/backend/routers/permission.js +985 -0
  58. package/backend/routers/setting.js +184 -0
  59. package/backend/routers/team/index.js +22 -0
  60. package/backend/routers/team/routers/mapping.js +29 -0
  61. package/backend/routers/team/routers/member.js +72 -0
  62. package/backend/routers/team/routers/membermanage.js +289 -0
  63. package/backend/routers/team/routers/pages.js +47 -0
  64. package/backend/routers/team/routers/roles.js +92 -0
  65. package/backend/routers/team/routers/teaminfo.js +27 -0
  66. package/backend/routers/team/routers/usergroup.js +213 -0
  67. package/backend/routers/team/services/mapping.js +101 -0
  68. package/backend/routers/team/services/member.js +206 -0
  69. package/backend/routers/team/services/roles.js +71 -0
  70. package/backend/routers/team/services/teaminfo.js +20 -0
  71. package/backend/routers/team/services/usergroup.js +128 -0
  72. package/backend/routers/user.js +436 -0
  73. package/backend/services/automate.js +60 -0
  74. package/backend/services/config.js +14 -0
  75. package/backend/services/module.js +298 -0
  76. package/backend/services/permission.js +192 -0
  77. package/backend/services/services.js +115 -0
  78. package/backend/services/setting.js +190 -0
  79. package/backend/services/token.js +42 -0
  80. package/backend/space.js +52 -0
  81. package/backend/space_mapping.js +15 -0
  82. package/backend/utils/avatar.js +48 -0
  83. package/backend/utils/color_gen_helper.js +20 -0
  84. package/backend/utils/date.js +66 -0
  85. package/backend/utils/excel.js +446 -0
  86. package/backend/utils/fs/doc.md +64 -0
  87. package/backend/utils/fs/index.js +127 -0
  88. package/backend/utils/jwt.js +54 -0
  89. package/backend/utils/modules/sequence.js +93 -0
  90. package/backend/utils/object.js +31 -0
  91. package/backend/utils/page-query-helper/index.js +61 -0
  92. package/backend/utils/path.js +123 -0
  93. package/backend/utils/run.js +25 -0
  94. package/backend/utils/tokenize.js +82 -0
  95. package/backend/utils/typeof.js +5 -0
  96. package/backend/utils/util.js +153 -0
  97. package/backend/views/api/index.js +32 -0
  98. package/backend/views/api/index.xml +49 -0
  99. package/backend/views/dict/index.js +80 -0
  100. package/backend/views/dict/index.xml +52 -0
  101. package/backend/views/index.js +32 -0
  102. package/backend/views/members_manage/index.js +68 -0
  103. package/backend/views/members_manage/index.xml +68 -0
  104. package/backend/views/roles/index.js +17 -0
  105. package/backend/views/roles/index.xml +47 -0
  106. package/backend/views/usergroup/index.js +68 -0
  107. package/backend/views/usergroup/index.xml +65 -0
  108. package/dist/common-assets/css/index-05a08720.css +3 -0
  109. package/dist/common-assets/css/index-05a08720.css.gz +0 -0
  110. package/dist/common-assets/js/index-2e8c7128.js +762 -0
  111. package/dist/common-assets/js/index-2e8c7128.js.gz +0 -0
  112. package/dist/common-assets/js/react-cropper.es-19c27537.js +10 -0
  113. package/dist/common-assets/js/react-cropper.es-19c27537.js.gz +0 -0
  114. package/dist/common-assets/png/u9-2348c304.png +0 -0
  115. package/dist/common-assets/woff2/materialicons-83be7b2f.woff2 +0 -0
  116. package/dist/index.html +162 -0
  117. package/package.json +61 -5
  118. package/common/router.js +0 -42
  119. package/modules/user/backend/index.js +0 -19
  120. package/modules/user/backend/routers/user.js +0 -11
  121. package/modules/user/frontend/index.js +0 -1
  122. package/serve.js +0 -9
package/README.md CHANGED
@@ -1,2 +1,9 @@
1
1
  # base-server
2
2
 
3
+ node 基础服务
4
+
5
+ [文档](http://172.32.68.94:8080/base-server/introduce)
6
+
7
+ ## 打包
8
+
9
+ 记得改下 `/backend/config/index.js -> isProd = true`
package/app.js CHANGED
@@ -1,34 +1,28 @@
1
1
  const express = require('express');
2
- const router = require('./common/router');
3
2
  const timeout = require('connect-timeout');
4
3
  const compression = require('compression');
5
4
  const { createServer } = require('http');
6
- // const { Server } = require('socket.io');
5
+ const { Server } = require('socket.io');
7
6
  const cookieParser = require('cookie-parser');
8
7
  const xmlparser = require('express-xml-bodyparser');
9
- // const config = require('@config/index');
10
- // const { logger } = require('@common/logger/index');
11
- // const allowCors = require('@common/middleware/cors');
12
- // const response = require('@common/middleware/response');
13
- // const { createConnection } = require('@utils/sql-helper/index');
8
+ const { createConnection } = require('@gingkoo/node-tools');
14
9
 
15
- // require('@utils/array');
16
-
17
- // var Socket = require('@common/socket');
10
+ const config = require('./backend/config');
11
+ const cors = require('./backend/common/middleware/cors');
12
+ const response = require('./backend/common/middleware/response');
13
+ const router = require('./backend/router');
18
14
 
19
15
  class App {
20
- TIME_OUT = 30 * 1e3; // 超时时间
21
-
22
16
  /**
23
- * @param {string} optinos.ip 服务 host
24
- * @param {number | string} optinos.port 服务 post
25
- * @param {string} optinos.orgid 组织 id
26
- *
17
+ * @param {string} optinos.timeout 超时时间 默认 30s
18
+ * @param {(app: any, express: any) => void} optinos.beforeRoutes 在前面注册路由
19
+ * @param {(app: any, express: any) => void} optinos.afterRoutes 在后面注册路由
27
20
  */
28
21
  constructor(options = {}) {
29
22
  this.options = options;
30
23
  this.app = express();
31
24
  this.httpServer = createServer(this.app);
25
+ this.TIME_OUT = options.timeout ?? 30 * 1e3; // 超时时间
32
26
 
33
27
  this.connectDB();
34
28
  this.middleware();
@@ -40,17 +34,20 @@ class App {
40
34
 
41
35
  // 连接数据库
42
36
  connectDB() {
43
- // createConnection(config.db);
37
+ if (config.db) {
38
+ createConnection(config.db);
39
+ }
44
40
  }
45
41
 
46
42
  // 定时任务
47
43
  schedule() {
48
- // var schedule = require('@common/schedule');
44
+ const schedule = require('./backend/common/schedule');
45
+ schedule.run();
49
46
  }
50
47
 
51
48
  middleware() {
52
- // this.app.use(allowCors);
53
- // this.app.use(response);
49
+ this.app.use(cors);
50
+ this.app.use(response);
54
51
  this.app.use((req, res, next) => {
55
52
  if (~req.path.indexOf('/sse')) {
56
53
  return next();
@@ -69,35 +66,34 @@ class App {
69
66
  }
70
67
 
71
68
  routes() {
72
- this.app.use('/static', express.static('static'));
73
- // this.app.use('/assets', express.static('dist/assets'));
69
+ if (this.options.beforeRoutes) {
70
+ this.options.beforeRoutes(this.app, express);
71
+ }
74
72
  this.app.use('/', router);
73
+ if (this.options.afterRoutes) {
74
+ this.options.afterRoutes(this.app, express);
75
+ }
75
76
  }
76
77
 
77
78
  listenSocket() {
78
- // let io = new Server(this.httpServer, {
79
- // transports: ['websocket', 'polling'], // 只使用长轮询
80
- // pingTimeout: 30000,
81
- // });
82
- // new Socket(io);
79
+ let io = new Server(this.httpServer, {
80
+ transports: ['websocket', 'polling'], // 只使用长轮询
81
+ pingTimeout: 30000,
82
+ ...config.scoket.config,
83
+ });
84
+ var Socket = require('./backend/common/socket');
85
+ new Socket(io);
83
86
  }
84
87
 
85
- listen(resolve, reject) {
86
- let optinos = this.options;
87
- global.orgid = optinos.orgid;
88
-
89
- this.httpServer.listen(optinos.port, optinos.ip, () => {
90
- console.info(`server running ${optinos.port}`);
91
- if (resolve instanceof Function) {
92
- resolve('server_started');
93
- }
88
+ listen(cb) {
89
+ global.orgid = config.orgid;
90
+ this.httpServer.listen(config.port, config.ip, () => {
91
+ console.info(`server running http://${config.ip}:${config.port}`);
92
+ cb?.([false]);
94
93
  });
95
-
96
94
  this.httpServer.on('error', (err) => {
97
95
  console.error(`server error ${err}`);
98
- if (reject instanceof Function) {
99
- reject('server error');
100
- }
96
+ cb?.([true, err]);
101
97
  });
102
98
  }
103
99
  }
@@ -0,0 +1,55 @@
1
+ /**
2
+ * teams 数据库 所有实体表
3
+ */
4
+
5
+ const entity = {
6
+ // -------------- 基础模块 --------------
7
+ BASE_ATTACHMENTS: 'BASE_ATTACHMENTS', // 文件关联对象表
8
+ BASE_BG_TASK: 'BASE_BG_TASK', // 后台任务信息表
9
+ BASE_DICT_MODULE: 'BASE_DICT_MODULE', // 码表模块
10
+ BASE_DICT: 'BASE_DICT', // 码表模块下的分类
11
+ BASE_DICT_ITEMS: 'BASE_DICT_ITEMS', // 码表分类下的代码
12
+ BASE_MODULES: 'BASE_MODULES', // 模块信息表
13
+ BASE_MODULE_NAV: 'BASE_MODULE_NAV', // 模块菜单信息表
14
+ BASE_CONFIG: 'BASE_CONFIG', // 一般配置数据表
15
+ BASE_CONFIG_GROUP: 'BASE_CONFIG_GROUP', // 一般配置分组表
16
+ BASE_EMAIL_TEMPLATE: 'BASE_EMAIL_TEMPLATE', // 邮件模版
17
+ BASE_SETUP_NAV: 'BASE_SETUP_NAV', // 系统管理菜单信息
18
+ BASE_NOTIFI_MESSAGE: 'BASE_NOTIFI_MESSAGE', // 消息通知,消息记录
19
+ BASE_SEQ_CTL: 'BASE_SEQ_CTL', // 序号生成控制表
20
+ BASE_API_CONFIG: 'BASE_API_CONFIG', // API配置信息表
21
+
22
+ // -------------- 用户模块 --------------
23
+ IDM_PERMISSIONS: 'IDM_PERMISSIONS', // 权限控制表
24
+ IDM_GROUPS: 'IDM_GROUPS', // 部门分组表
25
+ IDM_GROUP_MEMBERS: 'IDM_GROUP_MEMBERS', // 部门分组成员表
26
+ IDM_ROLES: 'IDM_ROLES', // 用户角色表
27
+ IDM_ROLE_MEMBERS: 'IDM_ROLE_MEMBERS', // 角色成员表
28
+ IDM_ORGS: 'IDM_ORGS', // 机构信息表
29
+ IDM_DEPTS: 'IDM_DEPTS', // 部门表
30
+ IDM_USERS: 'IDM_USERS', // 用户信息表
31
+ IDM_USER_SECURITY_PROBLEM: 'IDM_USER_SECURITY_PROBLEM', // 用户密保表
32
+ IDM_USER_TOKEN: 'IDM_USER_TOKEN', // 用户token表
33
+ IDM_PERM_PROPS: 'IDM_PERM_PROPS', // 权限属性表
34
+ IDM_HISTORY_LOG: 'IDM_HISTORY_LOG', // 用户设备登录历史表
35
+ IDM_USER_OAUTH: 'IDM_USER_OAUTH', // 三方认证用户
36
+
37
+ // -------------- 通知模块 --------------
38
+ NOTICE_LOG: 'NOTICE_LOG', // 通知信息表
39
+ NOTICE_USER_PERMISSION: 'NOTICE_USER_PERMISSION', // 通知用户权限表
40
+ NOTICE_MODULE_ITEMS: 'NOTICE_MODULE_ITEMS', // 通知模块内容表
41
+ NOTICE_MODULES: 'NOTICE_MODULES', // 通知模块表
42
+
43
+ // -------------- 企业微信配置 --------------
44
+ WEWORK_CFG: 'WEWORK_CFG', // 企业微信配置
45
+ WEWORK_APP_CFG: 'WEWORK_APP_CFG', // 企业微信应用配置
46
+ WEWORK_MSG_RECV: 'WEWORK_MSG_RECV', // 企业微信接收消息日志
47
+ WEWORK_MSG_SEND: 'WEWORK_MSG_SEND', // 企业微信发送消息日志
48
+
49
+ // -------------- 应用网络配置 --------------
50
+ APP_NET_CFG: 'APP_NET_CFG', // 应用网络配置
51
+ APP_NET_ORG: 'APP_NET_ORG', // 应用租户网络
52
+ APP_NET_STATE: 'APP_NET_STATE', // 应用租户网络状态
53
+ };
54
+
55
+ module.exports = entity;
@@ -0,0 +1,247 @@
1
+ // fss
2
+ const FILE_TYPE = {
3
+ IMAGE: 'image',
4
+ DOC: 'doc',
5
+ };
6
+ const FILE_MODULE = {
7
+ PROJECT: 'PROJECT',
8
+ USER: 'USER',
9
+ };
10
+
11
+ // page
12
+ const PAGE_SECTION = {
13
+ add: 'BTN_ADD',
14
+ edit: 'BTN_MOD',
15
+ };
16
+
17
+ const BRANCH_STATUS = {
18
+ normal: '00',
19
+ del: '01',
20
+ // merged: '02',
21
+ };
22
+
23
+ // message
24
+ const NOT_STATUS = {
25
+ normal: '00',
26
+ notdel: '01',
27
+ };
28
+
29
+ const NOT_TYPE = {
30
+ issue_update: 'issue_update', //任务变更
31
+ };
32
+
33
+ const NOT_IS_READ = {
34
+ read: 'Y',
35
+ unread: 'N',
36
+ };
37
+
38
+ const MSG_TYPE = {
39
+ issue_update: 'issue_update', // 任务变更
40
+ issue_comments: 'issue_comment', // 任务评论
41
+ issue_docx: 'issue_docx', // 任务文件变更
42
+ issue_image: 'issue_image', // 任务图片变更
43
+ issue_connect: 'issue_connect', // 任务关联
44
+ };
45
+
46
+ const MSG_STATUS = {
47
+ normal: '00', //正常状态
48
+ fileDel: '02', //任务文件删除,
49
+ msgDel: '01', //消息删除,但select语句可以查到
50
+ };
51
+
52
+ const NOT_TITLE = {
53
+ issue: '工作项变更通知',
54
+ };
55
+
56
+ const IS_NOTICE = {
57
+ Y_NOTICE: '00',
58
+ N_NOTICE: '01',
59
+ };
60
+
61
+ const ICON_TYPE = {
62
+ fa: 'fa',
63
+ antd: 'antd',
64
+ img: 'image',
65
+ };
66
+
67
+ const NAV_MODULE_ITEM = {
68
+ issue_link: '', // 任务相关人员关联到我
69
+ project_link: '', // 项目负责人关联到我
70
+ my_issue_update: '', // 我相关的任务变更通知
71
+ issue_: '', // 任务逾期通知
72
+ // 邀请加入项目提醒
73
+ // 团队加入新成员提醒
74
+ //
75
+ };
76
+
77
+ const NAV_MODULE_TYPE = {
78
+ email: 'Email notfications', // 邮件通知
79
+ weChat: 'Enterprise WeChat notfications', // 企业微信通知
80
+ web: 'Web Site notfications', // 站内通知
81
+ // 。。。
82
+ };
83
+
84
+ const ISSUE_LINK_TYPE_ENUM = {
85
+ BUG_LINK: 'BUG_LINK', // 缺陷关联
86
+ EG_LINK: 'EG_LINK', // 用例关联
87
+ ISSUE_LINK: 'ISSUE_LINK', // 工作项关联
88
+ PLAN_LINK: 'PLAN_LINK', // 计划关联
89
+ REQUIRE_LINK: 'REQUIRE_LINK', // 需求关联
90
+ };
91
+
92
+ const REVIEW_ADVICE_STATUS = {
93
+ PASS: '通过',
94
+ NO_PASS: '不通过',
95
+ N_REVIEW: '未评审',
96
+ ADVICE: '建议',
97
+ 1: '进行中',
98
+ Done: '已完成',
99
+ Doing: '进行中',
100
+ };
101
+
102
+ const LINK_ISSUE_STATUS = {
103
+ finish: 'finish', //已完成
104
+ unfinish: 'unfinish', //未完成
105
+ };
106
+
107
+ const navTypeMapping = {
108
+ new_projects: 'new_projects', //新建的项目列表
109
+ recent_projects: 'recent_projects', //最近访问的项目列表
110
+ all_projects: 'all_projects', //所有项目列表
111
+ };
112
+
113
+ const PROJECT_LOG_TYPE = {
114
+ project: 'project',
115
+ product: 'product',
116
+ };
117
+
118
+ // 查询字典树的层级表示
119
+ const DICT_LENVEL_TYPE = {
120
+ module: 'module', //字典模块
121
+ dict: 'dict', //字典信息
122
+ };
123
+
124
+ // 团队成员
125
+ const IDM_LENVEL_TYPE = {
126
+ DEPT: 'DEPT', //部门
127
+ GROUP: 'GROUP', //用户组
128
+ };
129
+ const PROJECT_STAGE_RANGE = {
130
+ ALL_PROJECT: 'ALL_PROJECT', //应用于所有项目
131
+ };
132
+
133
+ const PROJECT_STAGE_STATUS = {
134
+ OPEN: 'OPEN', //开启
135
+ CLOSE: 'CLOSE', //关闭
136
+ };
137
+
138
+ // 任务阶段状态
139
+ const ISSUE_STAGE_STATUS = {
140
+ BACKLOG: 'Backlog', //未开始
141
+ DOING: 'Doing', //进行中
142
+ DONE: 'Done', //已完成
143
+ };
144
+
145
+ // 权限操作者类型
146
+ const OPER_TYPE = {
147
+ ROLE: 'role',
148
+ USER: 'user',
149
+ DEPT: 'dept',
150
+ GROUP: 'group',
151
+ };
152
+
153
+ const RES_KIND = {
154
+ API: 'api',
155
+ PAGE: 'page',
156
+ FILE: 'file',
157
+ };
158
+
159
+ const RES_TYPE = {
160
+ MODULE: 'module', //模块
161
+ PROJECT_NAV: 'project_nav', //项目管理导航
162
+ SYSTEM_MODULE: 'system_module', //系统模块
163
+ SYSTEM_NAV: 'system_nav', //系统导航
164
+ REQUIREMENT_NAV: 'requirement_nav', //需求导航
165
+ };
166
+
167
+ // 角色类型
168
+ const ROLE_TYPE = {
169
+ MANAGER: 'MANAGER',
170
+ PROJECT: 'PROJECT',
171
+ REQUIREMENT: 'REQUIREMENT',
172
+ };
173
+
174
+ const PERMISSION_FEATURE_KIND = {
175
+ ADD: 'add',
176
+ EDIT: 'edit',
177
+ DEL: 'del',
178
+ };
179
+
180
+ const AUTOMATE_TYPE = {
181
+ LINK_TASK_AUTOMATE: 'linkTaskAutoMate', //关联任务后触发的自动化规则
182
+ CREATE_TASK_AUTOMATE: 'createTaskAutomate', //新建任务后触发的自动化规则
183
+ UPDATE_TASK_AUTOMATE: 'updateTaskAutomate', //修改任务后触发的自动化规则
184
+ ALL_TASK_AUTOMATE: 'allTaskAutomate', //所有触发的自动化规则
185
+ };
186
+
187
+ const DEMAND_ROLE = {
188
+ DEMAND_DEV: 'DEMAND_DEV',
189
+ DEMAND_BR: 'DEMAND_BR',
190
+ DEMAND_PM: 'DEMAND_PM',
191
+ };
192
+
193
+ module.exports = {
194
+ _issue: {
195
+ ISSUE_LINK_TYPE_ENUM,
196
+ AUTOMATE_TYPE,
197
+ },
198
+ fss: {
199
+ FILE_TYPE,
200
+ FILE_MODULE,
201
+ },
202
+ page: {
203
+ PAGE_SECTION,
204
+ },
205
+ project: {
206
+ BRANCH_STATUS,
207
+ navTypeMapping,
208
+ PROJECT_LOG_TYPE,
209
+ PROJECT_STAGE_RANGE,
210
+ PROJECT_STAGE_STATUS,
211
+ ISSUE_STAGE_STATUS,
212
+ },
213
+ message: {
214
+ MSG_STATUS,
215
+ NOT_IS_READ,
216
+ MSG_TYPE,
217
+ NOT_TITLE,
218
+ NOT_STATUS,
219
+ NOT_TYPE,
220
+ },
221
+ notModule: {
222
+ IS_NOTICE,
223
+ ICON_TYPE,
224
+ NAV_MODULE_ITEM,
225
+ NAV_MODULE_TYPE,
226
+ },
227
+ linkModule: {
228
+ LINK_ISSUE_STATUS,
229
+ },
230
+ reviewModule: {
231
+ REVIEW_ADVICE_STATUS,
232
+ },
233
+ dictLevelType: {
234
+ DICT_LENVEL_TYPE,
235
+ },
236
+ idmLevelType: {
237
+ IDM_LENVEL_TYPE,
238
+ },
239
+ permission: {
240
+ OPER_TYPE,
241
+ RES_KIND,
242
+ ROLE_TYPE,
243
+ RES_TYPE,
244
+ PERMISSION_FEATURE_KIND,
245
+ DEMAND_ROLE,
246
+ },
247
+ };
@@ -0,0 +1,18 @@
1
+ 'use strict';
2
+ const express = require('express');
3
+ const { authCheck } = require('../middleware/auth');
4
+ const upload = require('./routers/upload');
5
+ const resources = require('./routers/resources');
6
+ const download = require('./routers/download');
7
+ const attachment = require('./routers/attachment');
8
+ const importExport = require('./routers/import_export');
9
+
10
+ const router = express.Router();
11
+
12
+ router.use('/upload', [authCheck], upload); // 上传附件
13
+ router.use('/resources', resources); // 查看资源
14
+ router.use('/download', [authCheck], download); // 下载文件
15
+ router.use('/attachment', [authCheck], attachment); // 查询附件列表
16
+ router.use('/import-export', [authCheck], importExport); // 导入导出
17
+
18
+ module.exports = router;
@@ -0,0 +1,45 @@
1
+ 'use strict';
2
+ const express = require('express');
3
+ const attachmentService = require('../services');
4
+
5
+ const { fss } = require('../../enum');
6
+
7
+ var router = express.Router();
8
+
9
+ /**
10
+ * @api {get} /fss/attachment 附件查询
11
+ * @apiVersion 1.0.0
12
+ * @apiGroup fss
13
+ *
14
+ * @apiQuery {String} id 附件绑定对象id
15
+ * @apiQuery {String} refId 关联id
16
+ */
17
+ router.get('/', async function (req, res) {
18
+ let { id, refId } = req.query;
19
+
20
+ if (!id && !refId) {
21
+ return res.sendOk({ IMAGES: '', FILES: '' });
22
+ }
23
+
24
+ let attachment = await attachmentService.findAttachment({ OBJECT_ID: id, REF_ID: refId });
25
+
26
+ let IMAGES = attachment
27
+ .reduce((mo, v) => {
28
+ if (v.FILE_KIND === fss.FILE_TYPE.IMAGE) mo.push(`/fss/resources/share/${v.FILE_NAME}`);
29
+ return mo;
30
+ }, [])
31
+ .join(',');
32
+
33
+ let FILES = attachment
34
+ .reduce((mo, v) => {
35
+ if (v.FILE_KIND === fss.FILE_TYPE.DOC) {
36
+ mo.push(`/fss/download/share/${v.FILE_NAME}`);
37
+ }
38
+ return mo;
39
+ }, [])
40
+ .join(',');
41
+
42
+ res.sendOk({ IMAGES, FILES });
43
+ });
44
+
45
+ module.exports = router;
@@ -0,0 +1,43 @@
1
+ 'use strict';
2
+ const express = require('express');
3
+
4
+ const { resourcePath } = require('../utils');
5
+
6
+ var router = express.Router();
7
+
8
+ // excel导出 fss/download/users/wei.wang1/issues_20220221134006.xlsx
9
+ // 附件下载 /fss/download/share/issues_20220221134006.xlsx
10
+ /**
11
+ * @api {get} /fss/download/:fileFolder/* 下载文件
12
+ * @apiVersion 1.0.0
13
+ * @apiGroup fss
14
+ *
15
+ * @apiQuery {string} fileFolder 文件存放文件夹 share | users
16
+ *
17
+ */
18
+ router.get('/:fileFolder/*', async function (req, res) {
19
+ let userid = req.get('X-UserId');
20
+ let { fileFolder } = req.params;
21
+
22
+ let filename = '';
23
+ if (fileFolder === 'share') {
24
+ filename = req.path.split('/').slice(-1)[0];
25
+ } else {
26
+ filename = req.path.substr();
27
+ }
28
+
29
+ let filePath = resourcePath(userid, fileFolder, filename);
30
+ if (!filePath) {
31
+ res.sendErr('rescource not found');
32
+ return;
33
+ }
34
+ filePath = decodeURIComponent(filePath);
35
+
36
+ res.download(filePath, (err) => {
37
+ if (err) {
38
+ res.sendErr('rescource not found');
39
+ }
40
+ });
41
+ });
42
+
43
+ module.exports = router;
@@ -0,0 +1,113 @@
1
+ 'use strict';
2
+ const express = require('express');
3
+ const path = require('path');
4
+ const multer = require('multer');
5
+ const { v4: uuidv4 } = require('uuid');
6
+ const config = require('../../../config/index');
7
+ const { mkdirPath } = require('../../../utils/path');
8
+ const importExportService = require('../services/import_export');
9
+
10
+ var router = express.Router();
11
+
12
+ // 附件存放位置
13
+ const uploadPath = path.join(config.app.home, 'upload');
14
+
15
+ const multerUpload = multer({
16
+ storage: multer.diskStorage({
17
+ destination(req, res, cb) {
18
+ let dest = mkdirPath(uploadPath);
19
+ cb(null, dest);
20
+ },
21
+ filename(req, file, cb) {
22
+ let fileName = file.originalname;
23
+ let fileNameLen = fileName.length;
24
+ let lastPointIndex = fileName.lastIndexOf('.');
25
+ let pointIndex = ~lastPointIndex ? lastPointIndex : fileNameLen;
26
+ let suffixLen = fileNameLen - pointIndex; // 没有后缀为 0
27
+ let suffixStr = fileName.slice(pointIndex); // 带.
28
+
29
+ // 去掉后缀,并限制带上后缀 不超过 56 个字符
30
+ fileName = fileName.slice(0, Math.min(fileNameLen, 56) - suffixLen);
31
+
32
+ function sStr() {
33
+ return uuidv4()
34
+ .replaceAll('-', '')
35
+ .match(/(\w{6})/g)[1];
36
+ }
37
+
38
+ cb(null, `${fileName}__${sStr()}${suffixStr}`);
39
+ },
40
+ }),
41
+ });
42
+
43
+ /**
44
+ * @api {post} /fss/import-export/excel-import/:moduleId 导入数据
45
+ * @apiGroup fss
46
+ *
47
+ * @apiParams {string} moduleId 模块id
48
+ * @apiBoby {string} FWD 上传完事之后调哪个 event (query 也行)
49
+ * @apiBoby {any} xxx 扩展参数,会原封不动传给 FWD event (query 也行)
50
+ */
51
+ router.post('/excel-import/:moduleId', multerUpload.any(), async function (req, res) {
52
+ let userid = req.get('X-UserId');
53
+
54
+ let { moduleId } = req.params;
55
+
56
+ let filesInfo = [];
57
+
58
+ for (let i in req.files) {
59
+ let file = req.files[i] || {};
60
+ let { filename, originalname, encoding, mimetype, destination, fieldname, path, size } = file;
61
+ let fileInfo = {
62
+ FILE_NAME: filename,
63
+ ORIG_NAME: originalname,
64
+ FILE_ENCODING: encoding,
65
+ MIME_TYPE: mimetype,
66
+ UPLOAD_DIR: destination,
67
+ FIELD_NAME: fieldname,
68
+ FULL_PATH: path,
69
+ FILE_SIZE: size,
70
+ MODULE_ID: moduleId,
71
+ };
72
+
73
+ filesInfo.push(fileInfo);
74
+ }
75
+
76
+ let options = {
77
+ MODULE_ID: moduleId,
78
+ ...req.query,
79
+ ...req.body,
80
+ };
81
+
82
+ let [err, result] = await importExportService.uploadFiles(userid, filesInfo, options);
83
+ if (err) {
84
+ return res.sendErr(err?.message || '上传失败');
85
+ }
86
+ res.sendOk({ TASK: result.TASK });
87
+ });
88
+
89
+ /**
90
+ * @api {post} /fss/import-export/excel-export/:moduleId 导出数据
91
+ * @apiGroup fss
92
+ *
93
+ * @apiParams {string} moduleId 模块id
94
+ * @apiBoby {string} FWD 上传完事之后调哪个 event (query 也行)
95
+ * @apiBoby {any} xxx 扩展参数,会原封不动传给 FWD event (query 也行)
96
+ */
97
+ router.post('/excel-export/:moduleId', async function (req, res) {
98
+ let userid = req.get('X-UserId');
99
+
100
+ let { moduleId } = req.params;
101
+ let options = {
102
+ ...req.query,
103
+ ...req.body,
104
+ };
105
+
106
+ let [err, result] = await importExportService.downloadFile(userid, moduleId, options);
107
+ if (err) {
108
+ return res.sendErr(err?.message || '导出失败');
109
+ }
110
+ res.sendOk({ TASK: result.TASK });
111
+ });
112
+
113
+ module.exports = router;