人力资源
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

364 lines
17 KiB

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, Pagination, DatePicker } from '@douyinfe/semi-ui';
import { IconSearch, IconEditStroked, IconMinusCircleStroked, IconPlusCircleStroked } from '@douyinfe/semi-icons';
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 { isAuthorized } from '$utils'
import '../style.less';
const ResourceRepository = (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 [paginationQuery, setPaginatioQuery] = useState({ limit: 10, page: 0 }); //页码信息
const [keyword, setKeyword] = useState();//文件名称过滤
const [dataRange, setDataRange] = useState();//更新时间过滤
const ref = useRef();
useEffect(() => {
getClassify();
}, [])
const style = {
width: 260,
height: clientHeight - 294,
border: '1px solid var(--semi-color-border)'
};
const columns = [
{
title: '文件类型',
dataIndex: 'fileType',
},
{
title: '文件名称',
dataIndex: 'fileName',
},
{
title: '大小',
dataIndex: 'fileSize',
},
{
title: '更新时间',
dataIndex: 'updateDate',
render: (text) => text && moment(text).format('YYYY-MM-DD HH:mm:ss') || '-'
}, {
title: '操作',
dataIndex: 'action',
render: (text, record) => {
return <div style={{ color: "#1890FF" }}>
<Space>
{
isAuthorized('DOWNLOADTRAININGMATERIALS') ? <a href={'/_file-server/' + record.attachPath + '?filename=' + encodeURIComponent(record.fileName + record.fileType)}>下载</a> : ''
}
{
isAuthorized('DELETETRAININGMATERIALS')?currentSelect.includes("公司培训资料") &&
<Popconfirm
style={{ minWidth: "max-content" }}
title="提示"
content="确认删除该文件?"
onConfirm={() => { handleDelFile(record.id) }}
position={"leftBottom"}
>
<a style={{ cursor: 'pointer' }}>删除</a>
</Popconfirm>:''
}
</Space>
</div>
}
}
];
const renderLabel = (label, data) => {
const child = data.children ? true : false;
const key = data.key.split('/');
return (<div>
<Tooltip content={label}><span >{label.length > 7 ? label.substring(0, 7) + '...' : label}</span></Tooltip>
{true == data.operation ?
<span className='tree-icon'>
<IconEditStroked size='default' onClick={() => handleFolderClick(child ? '编辑' : '编辑子', !child, key[1], key[2] || undefined)} />
<Popconfirm
title="确定是否要删除?"
content="该文件夹下的所有子文件/附件将永久删除,请慎重!"
onConfirm={() => handleDel(data.key)}
// onCancel={onCancel}
>
<IconMinusCircleStroked size='default' />
</Popconfirm>
{child ?
<IconPlusCircleStroked
size='default'
onClick={() => handleFolderClick('新建子', true, label, undefined)}
/> : ''}
</span>
: ''}
</div>)
};
const handleFolderClick = (title, childFolder, departmentName, trainDate) => {
setModelVisiable(true);
setModalData({ title, childFolder, departmentName, trainDate });
}
const handleSelect = (e) => {
setCurrentSelect(e);
setPaginatioQuery({ limit: 10, page: 0 });
setKeyword(null);
setDataRange(null);
getFile(e, { limit: 10, page: 0 }, { restSearch: true });
}
const handleDataToSave = (add, body) => {
setDefaultExpandedKey([]);
if (add) {
dispatch(postResourceClassify(body)).then(res => {
if (res.success) {
getClassify();
setModelVisiable(false);
}
});
} else {
dispatch(putResourceClassify(body)).then(res => {
if (res.success) {
getClassify();
setModelVisiable(false);
}
});
}
}
const handleDelFile = (id) => {
dispatch(delResourceFile(id)).then(res => {
if (res.success) {
getFile(currentSelect, { limit: 10, page: 0 }, { restSearch: true });
}
})
}
const handleDel = (key) => {
const arr = key.split('/');
const query = {
departmentName: arr[1]
}
if (arr.length == 3) {
query.trainDate = arr[2];
}
dispatch(delResourceClassify(query)).then(res => {
if (res.success) {
getClassify();
setModelVisiable(false);
}
});
}
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 handleSearch = () => {
setPaginatioQuery({ limit: 10, page: 0 });
getFile(null, { limit: 10, page: 0 });
}
const getFile = (e, pagination, opt) => {
const arr = e ? e.split("/") : currentSelect.split("/");
const query = pagination ? { ...pagination, type: arr[0] } : { ...paginationQuery, type: arr[0] };
if (opt && opt.restSearch) {
//选中树节点重置
setPaginatioQuery({ limit: 10, page: 0 });
setKeyword(null);
setDataRange(null);
} else {
if (keyword) { query.keyword = keyword; }
if (dataRange) {
query.startTime = moment(dataRange[0]).format('YYYY-MM-DD HH:mm:ss');
query.endTime = moment(dataRange[1]).format('YYYY-MM-DD HH:mm:ss');
}
}
if (arr[1]) { query.departmentName = arr[1]; }
if (arr[2]) { query.trainDate = arr[2]; }
dispatch(getResourceFileList(query));
}
const getClassify = () => {
dispatch(getResourceClassify()).then(res => {
const { success, payload } = res;
if (success) {
let defaultKey = "";
if (payload.data.length) {
if (payload.data[0].children && payload.data[0].children.length) {
defaultKey = payload.data[0].children[0].key;
setDefaultExpandedKey([payload.data[0].key, payload.data[0].children[0].key]);
} else {
defaultKey = payload.data[0].key;
setDefaultExpandedKey([payload.data[0].key]);
}
}
setCurrentSelect(defaultKey);
setTreeData(payload.data);
getFile(defaultKey);
}
});
}
return (
<>
<div style={{ padding: '0px 12px' }}>
<div style={{ display: 'flex' }}>
<div style={{ color: 'rgba(0,0,0,0.45)', fontSize: 14 }}>培训</div>
<div style={{ color: 'rgba(0,0,0,0.45)', fontSize: 14, margin: '0px 8px' }}>/</div>
<div style={{ color: 'rgba(0,0,0,0.45)', fontSize: 14 }}>培训档案</div>
<div style={{ color: '#033C9A', fontSize: 14, margin: '0px 8px' }}>/</div>
<div style={{ color: '#033C9A', fontSize: 14 }}>培训资源储存库</div>
</div>
<div style={{ background: '#FFFFFF', boxShadow: '0px 0px 12px 2px rgba(220,222,224,0.2)', borderRadius: 2, padding: '20px', marginTop: 12 }}>
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
<div style={{ display: 'flex', alignItems: 'baseline' }}>
<div style={{ width: 0, height: 20, borderLeft: '3px solid #0F7EFB', borderTop: '3px solid transparent', borderBottom: '3px solid transparent' }}></div>
<div style={{ fontFamily: "YouSheBiaoTiHei", fontSize: 24, color: '#033C9A', marginLeft: 8 }}>培训资源储存库</div>
<div style={{ marginLeft: 6, fontSize: 12, color: '#969799', fontFamily: "DINExp", }}>RESOURCE REPOSITORY</div>
</div>
</div>
<Spin spinning={isRequesting}>
<Row className='resourceRepository'>
{/* 左侧 */}
<Col className='left' span={6}>
{
isAuthorized('FOLDERMANAGEMENT') ? <Button theme='solid' type='primary' onClick={() => handleFolderClick("新建", false)}>新建文件夹</Button> : ''
}
<Button theme='solid' type='primary' onClick={() => handleFolderClick("新建", false)}>新建文件夹</Button>
<br />
<Input suffix={<IconSearch />} showClear onChange={v => ref.current.search(v)} placeholder="请输入"></Input>
<Tree
ref={ref}
defaultExpandAll={true}
treeData={treeData}
style={style}
value={[currentSelect]}
expandedKeys={defaultExpandedKey}
filterTreeNode={true}
searchRender={false}
directory={true}
showFilteredOnly={true}
renderLabel={renderLabel}
onExpand={(e) => setDefaultExpandedKey(e)}
onSelect={handleSelect}
/>
</Col>
{/* 右侧内容 */}
<Col span={18} className='right'>
<Row> <span className="path-lable"><strong>当前文件夹{currentSelect}</strong></span></Row>
<Row className='search'>
<Space>
{isAuthorized('UPLOADTRAININGMATERIALS') ? currentSelect && currentSelect.includes("公司培训资料") && currentSelect.split("/").length == 3 ?
<Button theme='solid' type='primary' onClick={() => { setUploadModalVisiable(true) }} >上传文件</Button>
: null : ''}
<span className='search-label'>关键字</span>
<Input
style={{ width: 160 }}
// suffix={<IconSearch />}
showClear
placeholder="文件名称"
value={keyword}
onChange={(value) => { setKeyword(value) }}
></Input>
<span className='search-label'>更新时间范围</span>
<DatePicker
style={{ width: 350 }}
value={dataRange}
type="dateTimeRange"
density="compact"
onChange={(data) => { setDataRange(data) }}
onClear={() => { setDataRange(null) }}
/>
<Button theme='solid' type='primary' style={{ width: 80, borderRadius: 2, height: 32, background: '#DBECFF', color: '#005ABD' }}
onClick={() => handleSearch()}
>查询</Button>
</Space>
</Row>
<Table
columns={columns}
dataSource={resourceFilelist && resourceFilelist.rows || []}
pagination={false} />
<div style={{
display: "flex",
justifyContent: "space-between",
padding: "20px 20px",
}}>
<div></div>
<div style={{ display: 'flex', }}>
<span style={{ lineHeight: "30px", fontSize: 13, color: 'rgba(0,90,189,0.8)' }}>
{resourceFilelist && resourceFilelist.count}条信息
</span>
<Pagination
total={resourceFilelist && resourceFilelist.count}
showSizeChanger
currentPage={paginationQuery.page + 1}
pageSizeOpts={[10, 20, 30, 40]}
onChange={(currentPage, pageSize) => {
setPaginatioQuery({ limit: pageSize, page: currentPage - 1 });
getFile(currentSelect, { limit: pageSize, page: currentPage - 1 });
}}
/>
</div>
</div>
</Col>
</Row>
</Spin>
</div>
{modelVisiable ?
<FolderModal
oldData={resourceClassify && resourceClassify.find(r => '公司培训资料' == r.label)}
modalData={modalData}
onOk={handleDataToSave}
onCancel={() => { setModelVisiable(false) }}
/> : null
}
{uploadModalVisiable ?
<ResourceUploadModal
apiRoot={apiRoot}
user={user}
onOk={handleUploadOk}
onCancel={() => { setUploadModalVisiable(false) }}
/> : null
}
</div>
</>
)
}
function mapStateToProps(state) {
const { auth, global, resourceClassify, resourceFilelist } = state;
return {
user: auth.user,
actions: global.actions,
apiRoot: global.apiRoot,
clientHeight: global.clientHeight,
resourceClassify: resourceClassify.data || [],
resourceFilelist: resourceFilelist.data && resourceFilelist.data,
isRequesting: resourceClassify.isRequesting || resourceFilelist.isRequesting
};
}
export default connect(mapStateToProps)(ResourceRepository);