From d6e763f57c480d5306e1209a8d8ff20e352b5c5b Mon Sep 17 00:00:00 2001 From: wuqun Date: Fri, 14 Oct 2022 14:50:28 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BA=BA=E5=91=98=E4=BF=A1=E6=81=AF=E5=AF=BC?= =?UTF-8?q?=E5=85=A5=E7=9B=B8=E5=85=B3=E4=BB=A3=E7=A0=81=E6=9A=82=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/.vscode/launch.json | 12 +++- web/client/src/layout/actions/webSocket.js | 2 +- .../sections/example/containers/example.jsx | 69 ++++++++++-------- .../containers/export-members-modal.jsx | 70 +++++++++++++++++++ web/package.json | 1 + web/routes/attachment/index.js | 61 +++++++++++++++- 6 files changed, 180 insertions(+), 35 deletions(-) create mode 100644 web/client/src/sections/example/containers/export-members-modal.jsx diff --git a/web/.vscode/launch.json b/web/.vscode/launch.json index d48243f..d4d2f5b 100644 --- a/web/.vscode/launch.json +++ b/web/.vscode/launch.json @@ -7,12 +7,20 @@ "request": "launch", "program": "${workspaceRoot}/server.js", "args": [ - "-u http://127.0.0.1:4000" + "-p 5700", + "-u http://127.0.0.1:4000", + "--apiHrUrl http://localhost:4700", + "--qnak XuDgkao6cL0HidoMAPnA5OB10Mc_Ew08mpIfRJK5", + "--qnsk yewcieZLzKZuDfig0wLZ9if9jKp2P_1jd3CMJPSa", + "--qnbkt dev-hr", + "--qndmn http://rjkwed13l.hn-bkt.clouddn.com", + // "-v 0.2.0", + // "-h 22" ], "outputCapture": "std", "env": { "NODE_ENV": "development" } - } + } ] } \ No newline at end of file diff --git a/web/client/src/layout/actions/webSocket.js b/web/client/src/layout/actions/webSocket.js index d27ee01..106186b 100644 --- a/web/client/src/layout/actions/webSocket.js +++ b/web/client/src/layout/actions/webSocket.js @@ -12,7 +12,7 @@ export function initWebSocket ({ ioUrl, token, pomsUserId }) { if (user) { user = JSON.parse(user) token = user.token - pomsUserId = user.pomsUserInfo.id + pomsUserId = user.pomsUserInfo?.id } } if (!ioUrl || !token || !pomsUserId) { diff --git a/web/client/src/sections/example/containers/example.jsx b/web/client/src/sections/example/containers/example.jsx index f138c48..95a36da 100644 --- a/web/client/src/sections/example/containers/example.jsx +++ b/web/client/src/sections/example/containers/example.jsx @@ -1,45 +1,48 @@ -import React, { useEffect } from 'react'; +import React, { useEffect, useState } from 'react'; import { connect } from 'react-redux'; -import { Spin, Card } from '@douyinfe/semi-ui'; +import { Spin, Card, Button } from '@douyinfe/semi-ui'; +import ExportMembersModal from './export-members-modal' import '../style.less' const { Meta } = Card; const Example = (props) => { const { dispatch, actions, user, loading, socket } = props - + const [exportModalVs, setExportModalVs] = useState(false); useEffect(() => { // ACTION 示例 - // dispatch(actions.example.getMembers(user.orgId)) + // dispatch(actions.example.getMembers(user.orgId)) }, []) // websocket 使用测试 -// useEffect(() => { -// console.log(socket) -// if (socket) { -// socket.on('TEST', function (msg) { -// console.info(msg); -// }); -// return () => { -// socket.off("TEST"); -// } -// } + // useEffect(() => { + // console.log(socket) + // if (socket) { + // socket.on('TEST', function (msg) { + // console.info(msg); + // }); + // return () => { + // socket.off("TEST"); + // } + // } -// }, [socket]) + // }, [socket]) return ( - +
-
- - - - - -
-
+
+ + + + + +
+
-
+

STYLE EXAMPLE

+ +
{/* { > */} + { + exportModalVs ? setExportModalVs(false)} /> : '' + }
) } -function mapStateToProps (state) { +function mapStateToProps(state) { const { auth, global, members, webSocket } = state; return { - // loading: members.isRequesting, - // user: auth.user, - // actions: global.actions, - // members: members.data, - // socket: webSocket.socket + // loading: members.isRequesting, + user: auth.user, + // actions: global.actions, + // members: members.data, + // socket: webSocket.socket }; } diff --git a/web/client/src/sections/example/containers/export-members-modal.jsx b/web/client/src/sections/example/containers/export-members-modal.jsx new file mode 100644 index 0000000..2cee319 --- /dev/null +++ b/web/client/src/sections/example/containers/export-members-modal.jsx @@ -0,0 +1,70 @@ +import React, { useEffect, useState } from 'react'; +import { Modal, Form, Button, Upload } from '@douyinfe/semi-ui'; +import { IconUpload } from '@douyinfe/semi-icons'; +import ExportJsonExcel from 'js-export-excel'; +const ExportMembersModal = (props) => { + const { onCancel, user } = props; + useEffect(() => { + + }, []); + + const handleOk = () => { + + } + + const download = () => { + dldTemplate(); + dldText("填写说明.txt", "12121212121212"); + } + + const dldTemplate = () => { + let dataTable = []; + let option = {}; + option.fileName = '人资系统人员信息导入模板'; + option.datas = [ + { + sheetData: dataTable, + sheetName: '人资系统人员信息导入模板', + sheetFilter: ['人员编号', '姓名', '证件号', '性别(男/女)', '出生年月日(例2022/02/01)', '籍贯', '婚育状态(已婚/未婚/已婚已育)', '政治面貌', '联系方式', '工作地点', '毕业院校', '学历', '专业', '毕业时间', '入职时间', '转试用期时间', '转正时间', '离职日期', '工作经验(年)', '历史工作经历与职务'], //excel文件中需显示的列数据 + sheetHeader: ['人员编号', '姓名', '证件号', '性别(男/女)', '出生年月日(例2022/02/01)', '籍贯', '婚育状态(已婚/未婚/已婚已育)', '政治面貌', '联系方式', '工作地点', '毕业院校', '学历', '专业', '毕业时间', '入职时间', '转试用期时间', '转正时间', '离职日期', '工作经验(年)', '历史工作经历与职务'], //excel文件中每列的表头名称 + } + ] + let toExcel = new ExportJsonExcel(option); //生成excel文件 + toExcel.saveExcel(); //下载excel文件 + } + + const dldText = (filename, text) => { + var element = document.createElement('a'); + element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text)); + element.setAttribute('download', filename); + + element.style.display = 'none'; + document.body.appendChild(element); + + element.click(); + document.body.removeChild(element); + } + + const action = '/_file-server/upload?type=excel&token=' + user.token; + const fileLimit = '.xls,.xlsx,.csv'; + + return ( + handleOk(null)} + onCancel={onCancel}> +
+ + + +
最大不超过200M,导入文件需与 + download()} style={{ cursor: 'pointer', color: '#0066FF' }}>导入模板 + 一致
+
+
+ ) +} + + +export default ExportMembersModal; \ No newline at end of file diff --git a/web/package.json b/web/package.json index d9ac17e..aa49743 100644 --- a/web/package.json +++ b/web/package.json @@ -63,6 +63,7 @@ "ezuikit-js": "^0.6.1", "fs-attachment": "^1.0.0", "fs-web-server-scaffold": "^1.0.6", + "js-export-excel": "^1.1.4", "koa-better-http-proxy": "^0.2.5", "koa-proxy": "^1.0.0-alpha.3", "koa-view": "^2.1.4", diff --git a/web/routes/attachment/index.js b/web/routes/attachment/index.js index 22ffbcd..d1621e0 100644 --- a/web/routes/attachment/index.js +++ b/web/routes/attachment/index.js @@ -12,7 +12,8 @@ const ext = { three: [".js"], video: [".mp4"], bpmn: [".bpmn", ".bpmn20.xml", ".zip", ".bar"], - app: [".apk"] + app: [".apk"], + excel: ['.xls', '.xlsx', '.csv'], } module.exports = { @@ -47,7 +48,65 @@ module.exports = { } } + + let upload = async function (ctx, next) { + try { + const { token } = ctx.request.query + if (token) { + const { files } = await parse(ctx.req) + const file = files[0] + const extname = path.extname(file.filename).toLowerCase() + const ftype = ctx.query.type; + if (!(FILE_TYPE[ftype] || []).includes(extname)) { + ctx.status = 400 + ctx.body = { error: '文件格式无效' } + return; + } + const fileInfo = await app.fs.attachment.upload(file, { uploadPath: ftype }) // uploadPath: 附件存放的文件夹 + ctx.status = 200; + console.log(fileInfo); + console.log('0000000000000000000000'); + + ctx.body = { uploaded: fileInfo.key } // key: `${uploadPath}/${uuid}/${filename}` + } else { + ctx.status = 403 + ctx.body = { name: 'Forbidden', message: 'token无效,禁止访问' } + } + } catch (err) { + ctx.status = 400 + ctx.body = { + name: 'BadRequest', + message: 'error happened while uploading file to qiniu.' + } + } + } + + let remove = async function (ctx, next) { + try { + const { token } = ctx.request.query + if (token) { + const { fkeys } = ctx.request.body + for (let index = 0; index < fkeys.length; index++) { + await app.fs.attachment.remove(fkeys[index]) + } + ctx.status = 200 + ctx.body = { fkeys } + } else { + ctx.status = 403 + ctx.body = { name: 'Forbidden', message: 'token无效,禁止访问' } + } + } catch (err) { + ctx.status = 400 + ctx.body = { + name: 'BadRequest', + message: 'error happened while removing file from qiniu.' + } + } + } + router.use(download); router.get('/api/root', getApiRoot); + router.post('/_file-server/upload', upload); + router.post('/_file-server/remove', remove); } };