From 8fdbb7176fa22aa9fa841845a6892b8d28ab5518 Mon Sep 17 00:00:00 2001 From: zhouxin Date: Wed, 21 Dec 2022 14:04:24 +0800 Subject: [PATCH] =?UTF-8?q?(*)=E5=9F=B9=E8=AE=AD=E8=B5=84=E6=96=99?= =?UTF-8?q?=E5=BA=93=EF=BC=9A=E5=85=AC=E5=8F=B8=E5=9F=B9=E8=AE=AD=E8=B5=84?= =?UTF-8?q?=E6=96=99=E5=88=A0=E9=99=A4=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controllers/resourceRepository/index.js | 82 +++++++++++++++---- .../lib/routes/resourceRepository/index.js | 11 ++- .../actions/resourceRepository.js | 24 +++++- .../resourceRepository/folder-model.jsx | 6 +- .../resourceRepository/upload-modal.jsx | 51 ++++++++++++ .../containers/resourceRepository.jsx | 58 ++++++++++++- web/client/src/utils/webapi.js | 3 + 7 files changed, 212 insertions(+), 23 deletions(-) create mode 100644 web/client/src/sections/humanAffairs/components/resourceRepository/upload-modal.jsx diff --git a/api/app/lib/controllers/resourceRepository/index.js b/api/app/lib/controllers/resourceRepository/index.js index 53edb19..0f61642 100644 --- a/api/app/lib/controllers/resourceRepository/index.js +++ b/api/app/lib/controllers/resourceRepository/index.js @@ -136,24 +136,27 @@ async function getResourceFileList(ctx, next) { findObj.limit = Number(limit); findObj.offset = Number(offset); } - if (departmentName) { - const where = { - departmentName: departmentName + + if ("公司培训资料" == type) { + findObj.where = { fileName: { $not: null } }; + if (departmentName) { + findObj.where.departmentName = departmentName; } if (trainDate) { - //todo - // where.trainDate = trainDate - } - findObj.where = where; - } - if ("公司培训资料" == type) { - if (findObj.where) { - findObj.where.fileName = { $not: null }; - } else { - findObj.where = { fileName: { $not: null } }; + findObj.where.trainDate = trainDate; } rlst = await models.TrainingInformation.findAndCountAll(findObj); } else { + if (departmentName) { + const where = { + departmentName: departmentName + } + if (trainDate) { + //todo + where.trainDate = trainDate + } + findObj.where = where; + } rlst = await models.DeptTraining.findAndCountAll(findObj); } } else { @@ -246,11 +249,62 @@ async function delResourceClassify(ctx) { ctx.body = { message: err.message || '新增培训资源储备库文件夹失败' } } } +//新增公司培训资料文件 +async function postResourceFile(ctx) { + const transaction = await ctx.fs.dc.orm.transaction(); + try { + const { fileList, currentSelect } = ctx.request.body; + const { models } = ctx.fs.dc; + + const files = fileList && fileList.length && fileList.filter(f => f.fileName && f.fileType && f.fileSize && f.attachPath); + const splitArr = currentSelect.split("/"); + if (files.length && splitArr.length == 3 && "公司培训资料" == splitArr[0]) { + const dataToSave = files.map(r => { + return { + ...r, + departmentName: splitArr[1], + trainDate: splitArr[2], + updateDate: moment() + } + }); + await models.TrainingInformation.bulkCreate(dataToSave, { transaction }); + } else { + ctx.throw("新增公司培训资料文件内容不合法,请检查"); + } + + await transaction.commit(); + ctx.status = 204; + } catch (err) { + await transaction.rollback(); + ctx.status = 400; + ctx.body = { message: err.message || '新增公司培训资料文件失败' } + } +} +//删除公司培训资料文件 +async function delResourceFile(ctx) { + const transaction = await ctx.fs.dc.orm.transaction(); + try { + const { id } = ctx.params; + const { models } = ctx.fs.dc; + const old = await models.TrainingInformation.findOne({ where: { id: id } }); + if (old) { + await models.TrainingInformation.destroy({ where: { id: id }, transaction }); + } + await transaction.commit(); + ctx.status = 204; + } catch (err) { + await transaction.rollback(); + ctx.status = 400; + ctx.body = { message: err.message || '删除培训资源储备库文件夹失败' } + } +} module.exports = { getResourceClassify, getResourceFileList, postResourceClassify, putResourceClassify, - delResourceClassify + delResourceClassify, + postResourceFile, + delResourceFile } \ No newline at end of file diff --git a/api/app/lib/routes/resourceRepository/index.js b/api/app/lib/routes/resourceRepository/index.js index 61716a7..3e4a960 100644 --- a/api/app/lib/routes/resourceRepository/index.js +++ b/api/app/lib/routes/resourceRepository/index.js @@ -15,8 +15,15 @@ module.exports = function (app, router, opts) { app.fs.api.logAttr['PUT/train/trainFiles/resourceRepository/classify'] = { content: '编辑培训资源储备库文件夹', visible: true }; router.put('/train/trainFiles/resourceRepository/classify', resourceRepository.putResourceClassify); - + app.fs.api.logAttr['DELETE/train/trainFiles/resourceRepository/classify'] = { content: '删除培训资源储备库文件夹', visible: true }; router.delete('/train/trainFiles/resourceRepository/classify', resourceRepository.delResourceClassify); - + + app.fs.api.logAttr['POST/train/trainFiles/resourceRepository/file'] = { content: '新增公司培训资料文件', visible: true }; + router.post('/train/trainFiles/resourceRepository/file', resourceRepository.postResourceFile); + + app.fs.api.logAttr['DELETE/train/trainFiles/resourceRepository/file/:id'] = { content: '删除公司培训资料文件', visible: true }; + router.delete('/train/trainFiles/resourceRepository/file/:id', resourceRepository.delResourceFile); + + }; \ No newline at end of file diff --git a/web/client/src/sections/humanAffairs/actions/resourceRepository.js b/web/client/src/sections/humanAffairs/actions/resourceRepository.js index 1ecdd42..4d97d2b 100644 --- a/web/client/src/sections/humanAffairs/actions/resourceRepository.js +++ b/web/client/src/sections/humanAffairs/actions/resourceRepository.js @@ -58,4 +58,26 @@ export function delResourceClassify(query) { url: `${ApiTable.delResourceClassify}`, msg: { option: "删除" }, }); -} \ No newline at end of file +} + +export function postResourceFile(data) { + return (dispatch) => + basicAction({ + type: "post", + dispatch: dispatch, + data, + actionType: "POST_RESOURCE_FILE", + url: `${ApiTable.postResourceFile}`, + msg: { option: "上传" }, + }); +} +export function delResourceFile(id) { + return (dispatch) => + basicAction({ + type: "del", + dispatch: dispatch, + actionType: "DEL_RESOURCE_FILE", + url: ApiTable.delResourceFile.replace("{id}", id), + msg: { option: "删除" }, + }); +} diff --git a/web/client/src/sections/humanAffairs/components/resourceRepository/folder-model.jsx b/web/client/src/sections/humanAffairs/components/resourceRepository/folder-model.jsx index eaa7178..67e0e3a 100644 --- a/web/client/src/sections/humanAffairs/components/resourceRepository/folder-model.jsx +++ b/web/client/src/sections/humanAffairs/components/resourceRepository/folder-model.jsx @@ -11,7 +11,10 @@ const FolderModal = (props) => { if (val && '' == val.trim()) { return '不可以为空'; } else - if (val.length > 20) { + if (RegExp(/\//).exec(val)) { + return '不可以包含"/"特殊字符'; + } + else if (val.length > 20) { return '最大20字符'; } else { if (oldData.children) { @@ -43,7 +46,6 @@ const FolderModal = (props) => { return ''; } const handleOk = () => { - form.current.validate().then((values) => { if (!add) { values.oldDepName = departmentName; diff --git a/web/client/src/sections/humanAffairs/components/resourceRepository/upload-modal.jsx b/web/client/src/sections/humanAffairs/components/resourceRepository/upload-modal.jsx new file mode 100644 index 0000000..4638049 --- /dev/null +++ b/web/client/src/sections/humanAffairs/components/resourceRepository/upload-modal.jsx @@ -0,0 +1,51 @@ +import React, { useRef, useState } from 'react'; +import { Modal, Form, Button, Toast } from '@douyinfe/semi-ui'; +import { IconUpload } from '@douyinfe/semi-icons'; + +const ResourceUploadModal = (props) => { + const { apiRoot, user, onCancel, onOk } = props; + + const form = useRef(); + const handleOk = () => { + form.current.validate().then((values) => { + onOk(values); + }); + } + return ( +
(form.current = formApi)} + labelPosition={'left'} + labelAlign={'right'} + labelCol={{ span: 6 }} + wrapperCol={{ span: 18 }} + > + { Toast.error(`仅支持文件、压缩包类型`) }} + onSizeError={(file, fileList) => Toast.error(`${file.name} 超过200M`)} + onExceed={(fileList) => { Toast.error(`一次最多上传5个文件`) }} + rules={[{ required: true, message: '请上传文件' }]} + > + + +

支持文件类型:.doc,.docx,.xls,.xlsx,.pdf,.pptx, + 支持压缩包类型:zip、rar、7z, + 文件大小一个不能超过200M,一次最多上传5个文件。 +

+
+
+ ) +} +export default ResourceUploadModal \ No newline at end of file diff --git a/web/client/src/sections/humanAffairs/containers/resourceRepository.jsx b/web/client/src/sections/humanAffairs/containers/resourceRepository.jsx index ad87084..0550235 100644 --- a/web/client/src/sections/humanAffairs/containers/resourceRepository.jsx +++ b/web/client/src/sections/humanAffairs/containers/resourceRepository.jsx @@ -1,18 +1,24 @@ import React, { useEffect, useState, useRef } from 'react'; import { connect } from 'react-redux'; +import moment from 'moment'; import { Button, Col, Row, Input, Tree, Table, Space, Tooltip, Spin, Popconfirm } from '@douyinfe/semi-ui'; import { IconSearch, IconEditStroked, IconMinusCircleStroked, IconPlusCircleStroked } from '@douyinfe/semi-icons'; -import { getResourceClassify, getResourceFileList, postResourceClassify, putResourceClassify, delResourceClassify } from '../actions/resourceRepository'; +import { + getResourceFileList, postResourceFile, delResourceFile, + getResourceClassify, postResourceClassify, putResourceClassify, delResourceClassify +} from '../actions/resourceRepository'; import FolderModal from '../components/resourceRepository/folder-model'; +import ResourceUploadModal from '../components/resourceRepository/upload-modal'; import '../style.less'; const ResourceRepository = (props) => { - const { dispatch, clientHeight, resourceClassify, resourceFilelist, isRequesting } = props; + const { dispatch, clientHeight, apiRoot, user, resourceClassify, resourceFilelist, isRequesting } = props; const [treeData, setTreeData] = useState([]); const [currentSelect, setCurrentSelect] = useState(); const [defaultExpandedKey, setDefaultExpandedKey] = useState(); const [modelVisiable, setModelVisiable] = useState(false); const [modalData, setModalData] = useState(); + const [uploadModalVisiable, setUploadModalVisiable] = useState(false); const ref = useRef(); useEffect(() => { @@ -40,9 +46,18 @@ const ResourceRepository = (props) => { { title: '更新时间', dataIndex: 'updateDate', + render: (text) => text && moment(text).format('YYYY-MM-DD HH:mm:ss') || '-' }, { title: '操作', dataIndex: 'action', + render: (text, record) => { + return
+ + { } }); } + const handleUploadOk = (data) => { + const fileList = data.attachPath && data.attachPath.length && data.attachPath.filter(d => "success" == d.status).map(d => { + const { name, size, response } = d; + const { uploaded } = response || {}; + let index = name.lastIndexOf('.'); + return { + fileType: name.substring(index), + fileName: name.substring(0, index), + fileSize: size, + attachPath: uploaded + } + }); + dispatch(postResourceFile({ fileList, currentSelect })).then(res => { + if (res.success) { + getFile(currentSelect); + setUploadModalVisiable(false); + } + }) + + } const getFile = (e) => { const arr = e.split("/"); const query = { type: arr[0] }; @@ -187,7 +228,7 @@ const ResourceRepository = (props) => { - {currentSelect && currentSelect.includes("部门培训资料") ? null : } + {currentSelect && currentSelect.includes("部门培训资料") ? null : } 当前文件夹:{currentSelect} @@ -211,6 +252,14 @@ const ResourceRepository = (props) => { onCancel={() => { setModelVisiable(false) }} /> : null } + {uploadModalVisiable ? + { setUploadModalVisiable(false) }} + /> : null + }
) @@ -221,6 +270,7 @@ function mapStateToProps(state) { return { user: auth.user, actions: global.actions, + apiRoot: global.apiRoot, clientHeight: global.clientHeight, resourceClassify: resourceClassify.data || [], resourceFilelist: resourceFilelist.data && resourceFilelist.data, diff --git a/web/client/src/utils/webapi.js b/web/client/src/utils/webapi.js index 5e43749..51df842 100644 --- a/web/client/src/utils/webapi.js +++ b/web/client/src/utils/webapi.js @@ -54,6 +54,9 @@ export const ApiTable = { putResourceClassify: 'train/trainFiles/resourceRepository/classify', delResourceClassify: 'train/trainFiles/resourceRepository/classify', getResourceFileList: 'train/trainFiles/resourceRepository/fileList', + postResourceFile: 'train/trainFiles/resourceRepository/file', + delResourceFile: 'train/trainFiles/resourceRepository/file/{id}' + }; export const RouteTable = {