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.
367 lines
10 KiB
367 lines
10 KiB
/* eslint-disable react-hooks/exhaustive-deps */
|
|
import React, { useState, useEffect, useRef } from 'react';
|
|
import { connect } from 'react-redux';
|
|
import { Spin, Table } from 'antd';
|
|
import classnames from 'classnames/bind';
|
|
import { push } from 'react-router-redux';
|
|
import moment from 'moment';
|
|
import request from 'superagent';
|
|
import ProTable from '@ant-design/pro-table';
|
|
import { Scroller } from '$components';
|
|
import {
|
|
getPeople, getWait, postKeySearch,
|
|
} from '../actions/profile';
|
|
import styles from './index.less';
|
|
|
|
const schedule = require('node-schedule');
|
|
|
|
const CX = classnames.bind(styles);
|
|
|
|
const topImg = '/assets/images/top.png';
|
|
const pointImg = '/assets/images/point.png';
|
|
|
|
function Management(props) {
|
|
const { dispatch, user } = props;
|
|
const [name, setName] = useState();// 名字查询
|
|
const [ajob, setAjob] = useState();// 岗位查询
|
|
const [projectData, setProjectData] = useState([]);
|
|
const [peopleData, setPeopleData] = useState([]);
|
|
const [waitData, setWaitData] = useState([]);
|
|
const ref = useRef();
|
|
|
|
function getOngoingProjects() {
|
|
request.get('/ongoing/projects').then((res) => {
|
|
setProjectData(res?.body?.projects);
|
|
});
|
|
}
|
|
|
|
useEffect(() => {
|
|
getOngoingProjects();
|
|
|
|
schedule.scheduleJob('0 0 7,18 * * ?', () => { // 每天 7时、18时 定时更新
|
|
getOngoingProjects();
|
|
});
|
|
|
|
dispatch(getPeople()).then((res) => {
|
|
setPeopleData(res?.payload.data?.projects);
|
|
});
|
|
dispatch(getWait()).then((res) => {
|
|
setWaitData(res?.payload.data?.projects);
|
|
});
|
|
}, []);
|
|
const projectCol = [
|
|
{
|
|
title: '执行ID',
|
|
dataIndex: 'execution_id',
|
|
key: 'execution_id',
|
|
align: 'center',
|
|
},
|
|
{
|
|
title: '项目名称',
|
|
dataIndex: 'name_project',
|
|
key: 'name_project',
|
|
align: 'center',
|
|
},
|
|
{
|
|
title: '投入人力',
|
|
dataIndex: 'part_people',
|
|
key: 'part_people',
|
|
align: 'center',
|
|
render: (dom, record) => (
|
|
<div>
|
|
{record.part_people.map((i, index) => (record.part_people.length == 1 ? <span>{i.name_people}</span> : (
|
|
<span>
|
|
{i.name_people}
|
|
{index < record.part_people.length - 1 ? '、' : ''}
|
|
</span>
|
|
)))}
|
|
</div>
|
|
),
|
|
},
|
|
{
|
|
title: '构建时间',
|
|
dataIndex: 'build_time',
|
|
key: 'build_time',
|
|
align: 'center',
|
|
defaultSortOrder: 'ascend',
|
|
// sortOrder:'descend' ,
|
|
sorter: {
|
|
compare: (a, b) => {
|
|
const one = moment(a.build_time).format('YYYYMMDD');
|
|
const two = moment(b.build_time).format('YYYYMMDD');
|
|
return one - two;
|
|
},
|
|
},
|
|
render: (dom, record) => <>{record.build_time ? moment(record.build_time).format('YYYY-MM-DD') : '待定'}</>,
|
|
},
|
|
{
|
|
title: '发布时间',
|
|
dataIndex: 'publish_time',
|
|
key: 'publish_time',
|
|
align: 'center',
|
|
render: (dom, record) => moment(record.publish_time).format('YYYY-MM-DD'),
|
|
},
|
|
{
|
|
title: '进度',
|
|
dataIndex: 'progress',
|
|
key: 'progress',
|
|
align: 'center',
|
|
},
|
|
{
|
|
title: '状态',
|
|
dataIndex: 'deferred_payment',
|
|
key: 'deferred_payment',
|
|
align: 'center',
|
|
render: (dom, record) => (
|
|
<>
|
|
{
|
|
record.publish_time && moment().isAfter(moment(record.publish_time))
|
|
? <div style={{ color: '#fb3838' }}>已延期</div> : <div style={{ color: '#23d96e' }}>未延期</div>
|
|
}
|
|
</>
|
|
),
|
|
},
|
|
];
|
|
|
|
const peopleCol = [
|
|
{
|
|
title: '人员姓名',
|
|
dataIndex: 'name_people',
|
|
key: 'name_people',
|
|
ellipsis: true,
|
|
hideInSearch: true,
|
|
width: 100,
|
|
render: (dom, record) => record.name_people,
|
|
|
|
}, {
|
|
title: '岗位',
|
|
key: 'post_people',
|
|
dataIndex: 'post_people',
|
|
valueType: 'select',
|
|
initialValue: null,
|
|
fieldProps: {
|
|
onChange: (value, cs) => {
|
|
setAjob(value);
|
|
},
|
|
options: [
|
|
{
|
|
label: '全部岗位',
|
|
value: null,
|
|
},
|
|
{
|
|
label: '研发',
|
|
value: '研发',
|
|
},
|
|
{
|
|
label: '测试',
|
|
value: '测试',
|
|
},
|
|
{
|
|
label: 'UI',
|
|
value: 'UI',
|
|
},
|
|
],
|
|
},
|
|
render: (dom, record) => record.post_people,
|
|
},
|
|
{
|
|
title: '周一',
|
|
key: 'md',
|
|
dataIndex: 'md',
|
|
hideInSearch: true,
|
|
render: (dom, record) => <div>{record.md == 'undefined' ? '--' : record.md}</div>,
|
|
},
|
|
{
|
|
title: '周二',
|
|
key: 'td',
|
|
dataIndex: 'td',
|
|
hideInSearch: true,
|
|
render: (dom, record) => <div>{record.td == 'undefined' ? '--' : record.td}</div>,
|
|
},
|
|
{
|
|
title: '周三',
|
|
key: 'wd',
|
|
dataIndex: 'wd',
|
|
hideInSearch: true,
|
|
render: (dom, record) => <div>{record.wd == 'undefined' ? '--' : record.wd}</div>,
|
|
},
|
|
{
|
|
title: '周四',
|
|
key: 'thd ',
|
|
dataIndex: 'thd ',
|
|
hideInSearch: true,
|
|
render: (dom, record) => <div>{record.thd == 'undefined' ? '--' : record.thd}</div>,
|
|
},
|
|
{
|
|
title: '周五',
|
|
key: 'fd',
|
|
dataIndex: 'fd',
|
|
hideInSearch: true,
|
|
render: (dom, record) => <div>{record.fd == 'undefined' ? '--' : record.fd}</div>,
|
|
},
|
|
{
|
|
title: '周六',
|
|
key: 'sd',
|
|
dataIndex: 'sd',
|
|
hideInSearch: true,
|
|
render: (dom, record) => <div>{record.sd == 'undefined' ? '--' : record.sd}</div>,
|
|
},
|
|
{
|
|
title: '周日',
|
|
key: 'ssd',
|
|
dataIndex: 'ssd',
|
|
hideInSearch: true,
|
|
render: (dom, record) => <div>{record.ssd == 'undefined' ? '--' : record.ssd}</div>,
|
|
},
|
|
{
|
|
title: '关键字搜索',
|
|
key: 'direction',
|
|
hideInTable: true,
|
|
dataIndex: 'direction',
|
|
order: 6,
|
|
fieldProps: {
|
|
onChange: (value, cs) => {
|
|
setName(value.target.value);
|
|
},
|
|
placeholder: '请输入关键字进行搜索',
|
|
getPopupContainer: (triggerNode) => triggerNode.parentNode,
|
|
},
|
|
},
|
|
];
|
|
|
|
const waitCol = [
|
|
{
|
|
title: '项目',
|
|
dataIndex: 'name_project',
|
|
key: 'name_project',
|
|
align: 'center',
|
|
},
|
|
{
|
|
title: '需求来源',
|
|
dataIndex: 'from_project',
|
|
key: 'from_project',
|
|
align: 'center',
|
|
},
|
|
{
|
|
title: '对接人',
|
|
dataIndex: 'contacts',
|
|
key: 'contacts',
|
|
align: 'center',
|
|
}, {
|
|
title: '评估工时',
|
|
dataIndex: 'consum_time',
|
|
key: 'consum_time',
|
|
align: 'center',
|
|
},
|
|
{
|
|
title: '处理进度',
|
|
dataIndex: 'progress',
|
|
key: 'progress',
|
|
align: 'center',
|
|
},
|
|
|
|
];
|
|
|
|
return (
|
|
<>
|
|
<div className={CX('index')}>
|
|
<img className={CX('index-img')} src={topImg} />
|
|
<div className={CX('index-main')}>
|
|
<div className={CX('index-main-box')}>
|
|
<img className={CX('index-main-box-point')} src={pointImg} />
|
|
<div className={CX('index-main-box-title')}>本月在研项目</div>
|
|
<div className={CX('index-main-box-en')}>/Research project this week</div>
|
|
<Spin spinning={false}>
|
|
<Table dataSource={projectData} columns={projectCol} size="small" pagination={false} scroll={{ y: '32vh' }} />
|
|
</Spin>
|
|
</div>
|
|
|
|
<div className={CX('index-main-box')}>
|
|
<img className={CX('index-main-box-point')} src={pointImg} />
|
|
<div className={CX('index-main-box-title')}>待研发项目</div>
|
|
<div className={CX('index-main-box-en')}>/Project to be developed</div>
|
|
<Table dataSource={waitData} columns={waitCol} size="small" pagination={false} scroll={{ y: '32vh' }} />
|
|
</div>
|
|
</div>
|
|
<div
|
|
className={CX('index-main-box')}
|
|
style={{
|
|
width: '90%', margin: '0 auto', marginTop: '2.8rem', height: '42.5vh',
|
|
}}
|
|
>
|
|
<img className={CX('index-main-box-point')} src={pointImg} />
|
|
<div className={CX('index-main-box-title')}>人员情况</div>
|
|
<div className={CX('index-main-box-en')}>/Information on Personnel</div>
|
|
{/* <Scroller containerId={"article-container-query"} height={"80%"}> */}
|
|
<ProTable
|
|
options={false}
|
|
actionRef={ref}
|
|
dataSource={peopleData}
|
|
columns={peopleCol}
|
|
size="small"
|
|
pagination={false}
|
|
scroll={{ y: '20vh' }}
|
|
request={async () => {
|
|
if (name || ajob) {
|
|
const query = {
|
|
value1: name,
|
|
value2: ajob,
|
|
};
|
|
const res = await dispatch(postKeySearch(query));
|
|
setPeopleData(res?.payload.data.projects);
|
|
return {
|
|
...res,
|
|
// total: res.payload.data.data ? res.payload.data.total : 0,
|
|
};
|
|
}
|
|
const res = await dispatch(getPeople());
|
|
setPeopleData(res?.payload.data.projects);
|
|
return {
|
|
...res,
|
|
// total: res.payload.data.data ? res.payload.data.total : 0,
|
|
};
|
|
}}
|
|
onReset={(v) => {
|
|
setName(null);
|
|
setAjob(null);
|
|
}}
|
|
/>
|
|
{/* </Scroller> */}
|
|
</div>
|
|
</div>
|
|
|
|
<a
|
|
style={{
|
|
fontSize: '16px',
|
|
position: 'absolute',
|
|
color: '#000',
|
|
right: '40px',
|
|
top: '20px',
|
|
zIndex: 10000,
|
|
}}
|
|
onClick={() => {
|
|
if (
|
|
user
|
|
&& user.authorized
|
|
&& JSON.parse(sessionStorage.getItem('user'))
|
|
) {
|
|
dispatch(push('/article'));
|
|
} else {
|
|
dispatch(push('/login'));
|
|
}
|
|
}}
|
|
>
|
|
进入后台
|
|
</a>
|
|
</>
|
|
);
|
|
}
|
|
function mapStateToProps(state) {
|
|
const { auth, global } = state;
|
|
return {
|
|
// loding: party.isRequesting,
|
|
// user: auth.user,
|
|
// actions: global.actions,
|
|
};
|
|
}
|
|
export default connect(mapStateToProps)(Management);
|
|
|