forked from Gitlink/forgeplus-react
修改iframe及左侧菜单代码
This commit is contained in:
parent
dfcecc1f2d
commit
c3ce2cc6a0
|
@ -0,0 +1,152 @@
|
|||
import React, { useEffect } from 'react';
|
||||
import * as echarts from 'echarts';
|
||||
|
||||
let fontSizeText = 16;
|
||||
let clientWidth = document.body.clientWidth;
|
||||
if (clientWidth < 1000) {
|
||||
fontSizeText = 16
|
||||
} else if (clientWidth >= 1000 && clientWidth <= 2000) {
|
||||
fontSizeText = 14 + (clientWidth - 1000) / 500;
|
||||
} else if (clientWidth > 2000) {
|
||||
fontSizeText = 16 + (clientWidth - 2000) / 500;
|
||||
} else if (clientWidth > 3000) {
|
||||
fontSizeText = 18 + (clientWidth - 3000) / 2000;
|
||||
}
|
||||
let fontSizeTitle = 1.25 * fontSizeText;
|
||||
|
||||
|
||||
export default ({ id,className, title, xData, yData }) => {
|
||||
|
||||
useEffect(() => {
|
||||
let newEchartBar = document.getElementById(id) && echarts.init(document.getElementById(id));
|
||||
let textColor = "#7988a5";
|
||||
let normalColor = "#e8e8ed";
|
||||
|
||||
let option = {
|
||||
grid: {
|
||||
left: "3%",
|
||||
top: "15%",
|
||||
right: "8%",
|
||||
bottom: 0,
|
||||
containLabel: true
|
||||
},
|
||||
title: {
|
||||
text: title,
|
||||
fontSize: fontSizeTitle,
|
||||
position: 'inside',
|
||||
textStyle: {
|
||||
color: textColor
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
trigger: "axis",
|
||||
axisPointer: {
|
||||
type: "shadow",
|
||||
textStyle: {
|
||||
color: "#fff"
|
||||
}
|
||||
},
|
||||
},
|
||||
xAxis: [{
|
||||
type: "category",
|
||||
data: xData,
|
||||
axisPointer: {
|
||||
type: "shadow"
|
||||
},
|
||||
axisLabel: {
|
||||
textStyle: {
|
||||
color: textColor,
|
||||
fontSize: .75 * fontSizeText
|
||||
},
|
||||
interval: 0,
|
||||
rotate: 40
|
||||
},
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
color: normalColor
|
||||
}
|
||||
},
|
||||
axisTick: {
|
||||
show: false
|
||||
},
|
||||
splitLine: {
|
||||
show: false
|
||||
}
|
||||
}],
|
||||
yAxis: [{
|
||||
type: "value",
|
||||
minInterval: 1,
|
||||
nameTextStyle: {
|
||||
color: textColor,
|
||||
fontSize: fontSizeText
|
||||
},
|
||||
axisLabel: {
|
||||
formatter: "{value}",
|
||||
textStyle: {
|
||||
color: textColor,
|
||||
fontSize: fontSizeText
|
||||
}
|
||||
},
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
color: normalColor
|
||||
}
|
||||
},
|
||||
axisTick: {
|
||||
show: false
|
||||
},
|
||||
splitLine: {
|
||||
lineStyle: {
|
||||
color: normalColor
|
||||
}
|
||||
},
|
||||
}],
|
||||
series: [{
|
||||
type: "bar",
|
||||
data: yData,
|
||||
barWidth: "60%",
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: {
|
||||
type: "linear",
|
||||
x: 0,
|
||||
y: 0,
|
||||
x2: 0,
|
||||
y2: 1,
|
||||
colorStops: [{
|
||||
offset: 0,
|
||||
color: "#deeefe"
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
color: "#2c8bff"
|
||||
}
|
||||
],
|
||||
globalCoord: false
|
||||
}
|
||||
}
|
||||
},
|
||||
label: {
|
||||
show: true,
|
||||
// position: ['-20%', -1.2 * fontSizeText],
|
||||
position: "top",
|
||||
// color: "#2c8bff",
|
||||
color: '#555',
|
||||
fontSize: fontSizeText,
|
||||
formatter: function (params) {
|
||||
// var percent = 0;
|
||||
// percent = ((params.value / allStaff.num) * 100).toFixed(0);
|
||||
return params.value || ''
|
||||
// + '\n' + percent + '%';
|
||||
},
|
||||
}
|
||||
}]
|
||||
};
|
||||
newEchartBar && newEchartBar.setOption(option);
|
||||
}, [id, title, xData, yData])
|
||||
|
||||
return (
|
||||
<div id={id} key={id} className={className} style={{minHeight:"20vh"}}>
|
||||
</div>
|
||||
)
|
||||
}
|
|
@ -0,0 +1,198 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import * as echarts from 'echarts';
|
||||
|
||||
|
||||
let fontSizeText = 16;
|
||||
let clientWidth = document.body.clientWidth;
|
||||
if (clientWidth < 1000) {
|
||||
fontSizeText = 16
|
||||
} else if (clientWidth >= 1000 && clientWidth <= 2000) {
|
||||
fontSizeText = 14 + (clientWidth - 1000) / 500;
|
||||
} else if (clientWidth > 2000) {
|
||||
fontSizeText = 16 + (clientWidth - 2000) / 500;
|
||||
} else if (clientWidth > 3000) {
|
||||
fontSizeText = 18 + (clientWidth - 3000) / 2000;
|
||||
}
|
||||
|
||||
const colorList = ["#27e8b4", '#77b4fd', '#ffd55f', '#ac90ef', '#9E87FF'];
|
||||
|
||||
export default ({ id = "uid", className, title, xData, seriesArr }) => {
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
let newEchartBar = document.getElementById(id) && echarts.init(document.getElementById(id));
|
||||
let option = {
|
||||
backgroundColor: '#fff',
|
||||
legend: {
|
||||
icon: 'circle',
|
||||
top: '5%',
|
||||
itemWidth: 6,
|
||||
itemGap: 20,
|
||||
textStyle: {
|
||||
color: '#556677'
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
lineStyle: {
|
||||
color: "#DCE2E8"
|
||||
}
|
||||
},
|
||||
backgroundColor: '#fff',
|
||||
textStyle: {
|
||||
color: '#5c6c7c'
|
||||
},
|
||||
padding: [10, 10],
|
||||
extraCssText: 'box-shadow: 1px 0 2px 0 rgba(163,163,163,0.5)'
|
||||
},
|
||||
grid: {
|
||||
top: '15%'
|
||||
},
|
||||
xAxis: [{
|
||||
type: 'category',
|
||||
data: xData,
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
color: '#DCE2E8'
|
||||
}
|
||||
},
|
||||
axisTick: {
|
||||
show: false
|
||||
},
|
||||
axisLabel: {
|
||||
// interval: 0,
|
||||
textStyle: {
|
||||
color: '#556677'
|
||||
},
|
||||
// 默认x轴字体大小
|
||||
fontSize: 0.75*fontSizeText,
|
||||
// margin:文字到x轴的距离
|
||||
margin: fontSizeText,
|
||||
rotate: 40
|
||||
},
|
||||
axisPointer: {
|
||||
label: {
|
||||
padding: [0, 0, 10, 0],
|
||||
/*
|
||||
除了padding[0]建议必须是0之外,其他三项可随意设置
|
||||
和CSSpadding相同,[上,右,下,左]
|
||||
如果需要下边线超出文字,设左右padding即可,注:左右padding最好相同
|
||||
padding[2]的10:
|
||||
10 = 文字距下边线的距离 + 下边线的宽度
|
||||
如:UI图中文字距下边线距离为7 下边线宽度为2
|
||||
则padding: [0, 0, 9, 0]
|
||||
*/
|
||||
// 这里的margin和axisLabel的margin要一致!
|
||||
margin: fontSizeText,
|
||||
// 移入时的字体大小
|
||||
fontSize: 0.75*fontSizeText,
|
||||
backgroundColor: {
|
||||
type: 'linear',
|
||||
x: 0,
|
||||
y: 0,
|
||||
x2: 0,
|
||||
y2: 1,
|
||||
colorStops: [{
|
||||
offset: 0,
|
||||
color: '#fff' // 0% 处的颜色
|
||||
}, {
|
||||
// offset: 0.9,
|
||||
offset: 0.86,
|
||||
//0.86 = (文字 + 文字距下边线的距离)/(文字 + 文字距下边线的距离 + 下边线的宽度)
|
||||
color: '#fff' // 0% 处的颜色
|
||||
}, {
|
||||
offset: 0.86,
|
||||
color: '#33c0cd' // 0% 处的颜色
|
||||
}, {
|
||||
offset: 1,
|
||||
color: '#33c0cd' // 100% 处的颜色
|
||||
}],
|
||||
global: false // 缺省为 false
|
||||
}
|
||||
}
|
||||
},
|
||||
boundaryGap: false
|
||||
}],
|
||||
yAxis: [{
|
||||
name: "(个)",
|
||||
minInterval: 1,
|
||||
type: 'value',
|
||||
axisTick: {
|
||||
show: false
|
||||
},
|
||||
axisLine: {
|
||||
show: false,
|
||||
lineStyle: {
|
||||
color: '#556677'
|
||||
}
|
||||
},
|
||||
axisLabel: {
|
||||
textStyle: {
|
||||
color: '#556677'
|
||||
}
|
||||
},
|
||||
splitLine: {
|
||||
lineStyle: {
|
||||
color: '#e8e8ed'
|
||||
}
|
||||
}
|
||||
}],
|
||||
series: [],
|
||||
};
|
||||
|
||||
for (let i = 0; i < seriesArr.length; i++) {
|
||||
if (seriesArr[i].data) {
|
||||
option.series.push({
|
||||
name: seriesArr[i].name,
|
||||
type: 'line',
|
||||
data: seriesArr[i].data,
|
||||
symbolSize: 1,
|
||||
symbol: 'circle',
|
||||
smooth: true,
|
||||
yAxisIndex: 0,
|
||||
showSymbol: false,
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: colorList[i],
|
||||
borderColor: colorList[i]
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
if(seriesArr[i].name=='新增代码数'&&seriesArr[i].data){
|
||||
option.yAxis.push({
|
||||
name: "(行)",
|
||||
type: 'value',
|
||||
position: 'right',
|
||||
axisTick: {
|
||||
show: false
|
||||
},
|
||||
axisLabel: {
|
||||
textStyle: {
|
||||
color: '#556677'
|
||||
},
|
||||
formatter: '{value}'
|
||||
},
|
||||
axisLine: {
|
||||
show: false,
|
||||
lineStyle: {
|
||||
color: '#556677'
|
||||
}
|
||||
},
|
||||
splitLine: {
|
||||
show: false
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
newEchartBar && newEchartBar.setOption(option);
|
||||
}, [xData,seriesArr])
|
||||
|
||||
return (
|
||||
<div id={id} key={id} className={className} style={{ minHeight: "400px" }}>
|
||||
</div>
|
||||
)
|
||||
}
|
|
@ -10,6 +10,49 @@
|
|||
*/
|
||||
|
||||
export default [
|
||||
{
|
||||
key: "statistics",
|
||||
title: "概览",
|
||||
location: "",
|
||||
icon: "icon-yonghuguanli",
|
||||
target: "_self",
|
||||
urltype: "self",
|
||||
children: [
|
||||
{
|
||||
key: "global",
|
||||
title: "全局统计",
|
||||
location: "/managements/statistics/global",
|
||||
menustatus: "Y",
|
||||
parentKey: "statistics",
|
||||
icon: "",
|
||||
target: "",
|
||||
urltype: "self",
|
||||
children: [],
|
||||
},
|
||||
// {
|
||||
// key: "member",
|
||||
// title: "成员工作统计",
|
||||
// location: "/managements/statistics/member",
|
||||
// menustatus: "Y",
|
||||
// parentKey: "statistics",
|
||||
// icon: "",
|
||||
// target: "",
|
||||
// urltype: "self",
|
||||
// children: [],
|
||||
// },
|
||||
// {
|
||||
// key: "activity",
|
||||
// title: "项目活跃度统计",
|
||||
// location: "/managements/statistics/activity",
|
||||
// menustatus: "Y",
|
||||
// parentKey: "statistics",
|
||||
// icon: "",
|
||||
// target: "",
|
||||
// urltype: "self",
|
||||
// children: [],
|
||||
// },
|
||||
],
|
||||
},
|
||||
{
|
||||
key: "task",
|
||||
title: "创客空间",
|
||||
|
@ -396,4 +439,26 @@ export default [
|
|||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
key: "settings",
|
||||
title: "网站配置",
|
||||
location: "",
|
||||
icon: "icon-yonghuguanli",
|
||||
target: "",
|
||||
urltype: "current_main_site_url",
|
||||
children: [
|
||||
{
|
||||
key: "platform_communicates",
|
||||
title: "社区动态管理",
|
||||
location: "/managements/admins/platform_communicates",
|
||||
menustatus: "Y",
|
||||
parentKey: "settings",
|
||||
icon: "",
|
||||
target: "",
|
||||
urltype: "current_main_site_url",
|
||||
params:'layout=none',
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
|
|
@ -9,11 +9,13 @@ const titleObj = {};
|
|||
const locationObj = {};
|
||||
const parentKeyObj = {};
|
||||
const allRouter = [];
|
||||
const rootSubmenuKeys =[];
|
||||
function titleFun(menus) {
|
||||
menus.forEach(i => {
|
||||
titleObj[i.key] = i.title;
|
||||
locationObj[i.location] = i;
|
||||
i.location && allRouter.push(i.location);
|
||||
!i.parentKey && rootSubmenuKeys.push(i.key);
|
||||
if (Array.isArray(i.children) && i.children.length > 0) {
|
||||
titleFun(i.children);
|
||||
i.parentKey && (parentKeyObj[i.key] = i.parentKey);
|
||||
|
@ -31,7 +33,13 @@ export default (props) => {
|
|||
|
||||
let initCurrent = locationObj[pathname] ? [locationObj[pathname].key] : [];
|
||||
let initKeyPath = locationObj[pathname] ? [locationObj[pathname].parentKey, locationObj[pathname].key] : [];
|
||||
|
||||
const defaultOpenKeys = [];
|
||||
const myKey = pathname && locationObj[pathname] && locationObj[pathname].parentKey;
|
||||
defaultOpenKeys.push(myKey ? myKey : "task");
|
||||
parentKeyObj[myKey]&&defaultOpenKeys.push(parentKeyObj[myKey]);
|
||||
|
||||
const [openKeys, setOpenKeys] =useState(defaultOpenKeys);
|
||||
const [current, setCurrent] = useState(initCurrent);
|
||||
const [keyPath, setKeyPath] = useState(initKeyPath);
|
||||
const [acitve, setActive] = useState(locationObj[pathname] || {});
|
||||
|
@ -84,6 +92,16 @@ export default (props) => {
|
|||
}
|
||||
}
|
||||
|
||||
function onOpenChange(newOpenKeys){
|
||||
const latestOpenKey = newOpenKeys.find(key=>openKeys.indexOf(key) === -1);
|
||||
if(rootSubmenuKeys.indexOf(latestOpenKey) === -1){
|
||||
setOpenKeys(newOpenKeys);
|
||||
}else{
|
||||
setOpenKeys(latestOpenKey?[latestOpenKey]:[]);
|
||||
}
|
||||
console.log(newOpenKeys);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
// 添加路由监听函数
|
||||
history.listen(historyLocation => {
|
||||
|
@ -95,19 +113,16 @@ export default (props) => {
|
|||
})
|
||||
}, [history]);
|
||||
|
||||
const defaultOpenKeys = [];
|
||||
const myKey = pathname && locationObj[pathname] && locationObj[pathname].parentKey;
|
||||
defaultOpenKeys.push(myKey ? myKey : "task");
|
||||
defaultOpenKeys.push(parentKeyObj[myKey]);
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<div className="layouts">
|
||||
<Menu
|
||||
mode="inline"
|
||||
defaultOpenKeys={defaultOpenKeys}
|
||||
// defaultOpenKeys={defaultOpenKeys}
|
||||
selectedKeys={current}
|
||||
onClick={handleClick}
|
||||
onOpenChange={onOpenChange}
|
||||
openKeys={openKeys}
|
||||
>
|
||||
{getMenuList(urlConfig)}
|
||||
</Menu>
|
||||
|
@ -115,7 +130,7 @@ export default (props) => {
|
|||
<div className="managements">
|
||||
<div className="head-title">{head(keyPath)}</div>
|
||||
{acitve.urltype == "self" ? children :
|
||||
<iframe id="iframe" className="iframe-item" src={`${setting[acitve.urltype] + acitve.location}?${acitve.params}`} onLoad={iframeLoad}></iframe>
|
||||
<iframe id="iframe" className="iframe-item" src={`${setting[acitve.urltype]}${acitve.location.startsWith('/managements')?acitve.location.replace(/\/managements/,""):acitve.location}?${acitve.params}`} onLoad={iframeLoad}></iframe>
|
||||
}
|
||||
</div>
|
||||
</Fragment>
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import React, { useEffect, useState } from "react";
|
||||
|
||||
import { Route, Switch } from "react-router-dom";
|
||||
import { withRouter } from "react-router";
|
||||
import { SnackbarHOC } from "educoder";
|
||||
|
@ -11,6 +10,12 @@ import { ImageLayerOfCommentHOC } from "../modules/page/layers/ImageLayerOfComme
|
|||
import Layouts from "./components/layouts";
|
||||
import './index.scss';
|
||||
|
||||
// 概览
|
||||
const Statistics = Loadable({
|
||||
loader: () => import("./statistics/"),
|
||||
loading: Loading,
|
||||
});
|
||||
|
||||
{/* 任务管理审核 */ }
|
||||
const TaskManage = Loadable({
|
||||
loader: () => import("../military/task/taskManage"),
|
||||
|
@ -93,23 +98,8 @@ const CompetitionList = Loadable({
|
|||
});
|
||||
|
||||
// 公告管理
|
||||
const NoticeList = Loadable({
|
||||
loader: () => import("./notice/noticeList"),
|
||||
loading: Loading,
|
||||
});
|
||||
// 公告管理详情
|
||||
const NoticeDetail = Loadable({
|
||||
loader: () => import("./notice/noticeDetail"),
|
||||
loading: Loading,
|
||||
});
|
||||
// 公告管理编辑
|
||||
const NoticeEdit = Loadable({
|
||||
loader: () => import("./notice/noticeEdit"),
|
||||
loading: Loading,
|
||||
});
|
||||
// 公告reader
|
||||
const NoticeReader = Loadable({
|
||||
loader: () => import("./notice/noticeReader"),
|
||||
const NoticeManage = Loadable({
|
||||
loader: () => import("./notice"),
|
||||
loading: Loading,
|
||||
});
|
||||
|
||||
|
@ -136,6 +126,15 @@ const Managements = (propsF) => {
|
|||
<div className="newMain clearfix">
|
||||
<Layouts {...propsF} >
|
||||
<Switch {...propsF}>
|
||||
|
||||
{/* 概览 */}
|
||||
<Route
|
||||
path="/managements/statistics"
|
||||
render={(props) => (
|
||||
<Statistics {...propsF} {...props} />
|
||||
)}
|
||||
></Route>
|
||||
|
||||
{/* 任务管理审核 */}
|
||||
<Route
|
||||
path="/managements/task/taskManage/:publishMode"
|
||||
|
@ -208,8 +207,6 @@ const Managements = (propsF) => {
|
|||
)}
|
||||
></Route>
|
||||
|
||||
|
||||
|
||||
{/* 专家审核 */}
|
||||
<Route
|
||||
path="/managements/expert/register"
|
||||
|
@ -274,39 +271,11 @@ const Managements = (propsF) => {
|
|||
)}
|
||||
></Route>
|
||||
|
||||
{/* 公告列表 */}
|
||||
{/* 公告管理 */}
|
||||
<Route
|
||||
path="/managements/notice/list/:isChecked"
|
||||
path="/managements/notice"
|
||||
render={(props) => (
|
||||
<NoticeList {...propsF} {...props} />
|
||||
)}
|
||||
></Route>
|
||||
{/* 公告详情 */}
|
||||
<Route
|
||||
path="/managements/notice/detail/:noticeId"
|
||||
render={(props) => (
|
||||
<NoticeDetail {...propsF} {...props} />
|
||||
)}
|
||||
></Route>
|
||||
{/* 公告编辑 */}
|
||||
<Route
|
||||
path="/managements/notice/edit/:noticeId"
|
||||
render={(props) => (
|
||||
<NoticeEdit {...propsF} {...props} />
|
||||
)}
|
||||
></Route>
|
||||
{/* 公告新增 */}
|
||||
<Route
|
||||
path="/managements/notice/edit"
|
||||
render={(props) => (
|
||||
<NoticeEdit {...propsF} {...props} />
|
||||
)}
|
||||
></Route>
|
||||
{/* 公告预览 */}
|
||||
<Route
|
||||
path="/managements/notice/reader/:noticeId"
|
||||
render={(props) => (
|
||||
<NoticeReader {...propsF} {...props} />
|
||||
<NoticeManage {...propsF} {...props} />
|
||||
)}
|
||||
></Route>
|
||||
</Switch>
|
||||
|
|
|
@ -3,6 +3,9 @@
|
|||
padding:0 1.875rem 1.6rem;
|
||||
background: #f6f9fe;
|
||||
min-height: 80vh;
|
||||
.content{
|
||||
margin-top:1rem;
|
||||
}
|
||||
}
|
||||
.management-content-head{
|
||||
background-color: #fff;
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
import React from "react";
|
||||
import { Route, Switch } from "react-router-dom";
|
||||
import Loadable from "react-loadable";
|
||||
import Loading from "../../Loading";
|
||||
|
||||
// 公告管理
|
||||
const NoticeList = Loadable({
|
||||
loader: () => import("./noticeList"),
|
||||
loading: Loading,
|
||||
});
|
||||
// 公告管理详情
|
||||
const NoticeDetail = Loadable({
|
||||
loader: () => import("./noticeDetail"),
|
||||
loading: Loading,
|
||||
});
|
||||
// 公告管理编辑
|
||||
const NoticeEdit = Loadable({
|
||||
loader: () => import("./noticeEdit"),
|
||||
loading: Loading,
|
||||
});
|
||||
// 公告reader
|
||||
const NoticeReader = Loadable({
|
||||
loader: () => import("./noticeReader"),
|
||||
loading: Loading,
|
||||
});
|
||||
|
||||
export default (propsF)=>{
|
||||
return (
|
||||
<Switch {...propsF}>
|
||||
{/* 公告列表 */}
|
||||
<Route
|
||||
path="/managements/notice/list/:isChecked"
|
||||
render={(props) => (
|
||||
<NoticeList {...propsF} {...props} />
|
||||
)}
|
||||
></Route>
|
||||
{/* 公告详情 */}
|
||||
<Route
|
||||
path="/managements/notice/detail/:noticeId"
|
||||
render={(props) => (
|
||||
<NoticeDetail {...propsF} {...props} />
|
||||
)}
|
||||
></Route>
|
||||
{/* 公告编辑 */}
|
||||
<Route
|
||||
path="/managements/notice/edit/:noticeId"
|
||||
render={(props) => (
|
||||
<NoticeEdit {...propsF} {...props} />
|
||||
)}
|
||||
></Route>
|
||||
{/* 公告新增 */}
|
||||
<Route
|
||||
path="/managements/notice/edit"
|
||||
render={(props) => (
|
||||
<NoticeEdit {...propsF} {...props} />
|
||||
)}
|
||||
></Route>
|
||||
{/* 公告预览 */}
|
||||
<Route
|
||||
path="/managements/notice/reader/:noticeId"
|
||||
render={(props) => (
|
||||
<NoticeReader {...propsF} {...props} />
|
||||
)}
|
||||
></Route>
|
||||
</Switch>
|
||||
)
|
||||
}
|
|
@ -0,0 +1,175 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import { Table, Pagination, notification, Input } from 'antd';
|
||||
import { paramToUrl } from '../../common/utils';
|
||||
import fetch from 'military/notice/fetch';
|
||||
|
||||
|
||||
const { Search } = Input;
|
||||
|
||||
export default function Activity(props) {
|
||||
|
||||
const [curPage, setCurPage] = useState(1);
|
||||
const [total, setTotal] = useState(0);
|
||||
const [orderBy, setOrderBy] = useState('');
|
||||
const [dataList, setDataList] = useState([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [projectName, setProjectName] = useState('');
|
||||
|
||||
useEffect(() => {
|
||||
// 获取table数据
|
||||
let params = {
|
||||
orderBy,
|
||||
curPage,
|
||||
projectName,
|
||||
pageSize: 10,
|
||||
};
|
||||
let url = encodeURI(paramToUrl('/api/ProjectActivityData/', params));
|
||||
setLoading(true);
|
||||
fetch({
|
||||
url,
|
||||
method: 'get',
|
||||
}).then(res => {
|
||||
if (res.code === '1') {
|
||||
setDataList(res.data.rows);
|
||||
setTotal(res.data.total);
|
||||
} else {
|
||||
setDataList([]);
|
||||
setTotal(0);
|
||||
notification.open({
|
||||
message: "错误",
|
||||
description: res.message,
|
||||
});
|
||||
}
|
||||
setLoading(false);
|
||||
});
|
||||
}, [curPage, orderBy, projectName]);
|
||||
|
||||
|
||||
|
||||
|
||||
function handleTableChange(pagination, filters, sorter) {
|
||||
if (sorter.order) {
|
||||
if (sorter.order === 'ascend') {
|
||||
setOrderBy(sorter.field + 'Asc');
|
||||
} else {
|
||||
setOrderBy(sorter.field + 'Desc');
|
||||
}
|
||||
} else {
|
||||
setOrderBy('');
|
||||
}
|
||||
}
|
||||
|
||||
function onCell(record) {
|
||||
return {
|
||||
onClick: event => { onCellClick(record) }, // 点击
|
||||
}
|
||||
}
|
||||
|
||||
function onCellClick(record) {
|
||||
|
||||
let url = encodeURI(paramToUrl('/api/ProjectActivityData/getUrl', { projectId: record.projectId }));
|
||||
fetch({
|
||||
url,
|
||||
method: 'get',
|
||||
}).then(res => {
|
||||
if (res.code === '1') {
|
||||
window.open(res.data);
|
||||
} else {
|
||||
notification.open({
|
||||
message: "错误",
|
||||
description: res.message,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: '项目名',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
className: 'link',
|
||||
onCell,
|
||||
},
|
||||
{
|
||||
title: '活跃度',
|
||||
key: 'activityScore',
|
||||
dataIndex: 'activityScore',
|
||||
sorter: true,
|
||||
},
|
||||
{
|
||||
title: '浏览数',
|
||||
key: 'visits',
|
||||
dataIndex: 'visits',
|
||||
sorter: true,
|
||||
},
|
||||
{
|
||||
title: '点赞数',
|
||||
key: 'praisesCount',
|
||||
dataIndex: 'praisesCount',
|
||||
sorter: true,
|
||||
},
|
||||
{
|
||||
title: '关注数',
|
||||
key: 'watchersCount',
|
||||
dataIndex: 'watchersCount',
|
||||
sorter: true,
|
||||
},
|
||||
{
|
||||
title: '任务数',
|
||||
key: 'issuesCount',
|
||||
dataIndex: 'issuesCount',
|
||||
sorter: true,
|
||||
},
|
||||
{
|
||||
title: 'PR数',
|
||||
key: 'pullRequestsCount',
|
||||
dataIndex: 'pullRequestsCount',
|
||||
sorter: true,
|
||||
},
|
||||
{
|
||||
title: '版本数',
|
||||
key: 'versionsCount',
|
||||
dataIndex: 'versionsCount',
|
||||
sorter: true,
|
||||
},
|
||||
];
|
||||
|
||||
function searchFun(val) {
|
||||
setProjectName(val);
|
||||
setCurPage(1);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="content">
|
||||
<Search
|
||||
style={{ width: '300px', margin: '1em' }}
|
||||
placeholder="请输入项目关键字"
|
||||
enterButton="搜索"
|
||||
size="large"
|
||||
onSearch={searchFun}
|
||||
className="global-search"
|
||||
maxLength={20}
|
||||
/>
|
||||
|
||||
<div className="table-detail">
|
||||
<Table
|
||||
loading={loading}
|
||||
rowKey={(row) => row.id}
|
||||
dataSource={dataList}
|
||||
columns={columns}
|
||||
pagination={false}
|
||||
onChange={handleTableChange} //预留的排序
|
||||
/>
|
||||
|
||||
{dataList.length > 0 &&
|
||||
<Pagination
|
||||
onChange={(page) => { setCurPage(page) }}
|
||||
current={curPage}
|
||||
total={total}
|
||||
/>}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,134 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import { Icon, Col, Row, Tabs, notification } from 'antd';
|
||||
import EchartBar from '../../components/EchartBar';
|
||||
import fetch from 'military/notice/fetch';
|
||||
import './index.scss';
|
||||
const { TabPane } = Tabs;
|
||||
|
||||
let length = 13;
|
||||
let nowMonth = new Date().getMonth() + 1;
|
||||
let year = new Date().getFullYear() - 1;
|
||||
let monthArr = [];
|
||||
if (nowMonth === 13) {
|
||||
nowMonth = 1
|
||||
}
|
||||
for (let i = 0; i < length; i++) {
|
||||
monthArr.push(year + '.' + nowMonth);
|
||||
nowMonth++;
|
||||
if (nowMonth === 13) {
|
||||
nowMonth = 1;
|
||||
year++;
|
||||
}
|
||||
}
|
||||
|
||||
export default function Global(props){
|
||||
const [type, setType] = useState(1);
|
||||
const [totalProjects, setTotalProjects] = useState(0);
|
||||
const [totalMembers, setTotalMembers] = useState(0);
|
||||
const [newAddedProjects, setNewAddedProjects] = useState([]);
|
||||
const [newAddedMembers, setNewAddedMembers] = useState([]);
|
||||
const [newCodeSubmissionTimes, setNewCodeSubmissionTimes] = useState([]);
|
||||
const [taskCompletion, setTaskCompletion] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
fetch({
|
||||
url: '/api/GlobalResourcesData/',
|
||||
method: 'get',
|
||||
}).then(res => {
|
||||
if (res.code === '1') {
|
||||
const data = res.data;
|
||||
setTotalProjects(data.totalProjects);
|
||||
setTotalMembers(data.totalMembers);
|
||||
setNewAddedProjects(data.newAddedProjects);
|
||||
setNewAddedMembers(data.newAddedMembers);
|
||||
setNewCodeSubmissionTimes(data.newCodeSubmissionTimes);
|
||||
setTaskCompletion(data.taskCompletion);
|
||||
} else {
|
||||
notification.open({
|
||||
message: "错误",
|
||||
description: res.message,
|
||||
});
|
||||
}
|
||||
});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
|
||||
<div className="content">
|
||||
<Row>
|
||||
<Col className="box-item" xs={12} lg={6}>
|
||||
<Icon type="folder" />
|
||||
<div>
|
||||
<p className="box-item-tit">项目总数</p>
|
||||
<p className="box-item-num">{totalProjects}</p>
|
||||
<p className="box-item-describe">当前项目总数</p>
|
||||
</div>
|
||||
</Col>
|
||||
<Col className="box-item" xs={12} lg={6}>
|
||||
<Icon type="user" />
|
||||
<div>
|
||||
<p className="box-item-tit">用户总数</p>
|
||||
<p className="box-item-num">{totalMembers}</p>
|
||||
<p className="box-item-describe">当前用户总数</p>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Tabs defaultActiveKey="1" onChange={(key) => { setType(key) }}>
|
||||
<TabPane tab="开源统计" key="1">
|
||||
<Row>
|
||||
<Col xs={24} lg={12}>
|
||||
<EchartBar
|
||||
id="newAddedProjects"
|
||||
className="echart-box"
|
||||
title="新项目统计"
|
||||
xData={monthArr}
|
||||
yData={newAddedProjects}
|
||||
/>
|
||||
</Col>
|
||||
|
||||
<Col xs={24} lg={12}>
|
||||
<EchartBar
|
||||
id="newAddedMembers"
|
||||
className="echart-box"
|
||||
title="新用户统计"
|
||||
xData={monthArr}
|
||||
yData={newAddedMembers}
|
||||
/>
|
||||
</Col>
|
||||
|
||||
<Col xs={24} lg={12}>
|
||||
<EchartBar
|
||||
id="newCodeSubmissionTimes"
|
||||
className="echart-box"
|
||||
title="代码提交次数"
|
||||
xData={monthArr}
|
||||
yData={newCodeSubmissionTimes}
|
||||
/>
|
||||
</Col>
|
||||
|
||||
<Col xs={24} lg={12}>
|
||||
<EchartBar
|
||||
id="taskCompletion"
|
||||
className="echart-box"
|
||||
title="任务完成量"
|
||||
xData={monthArr}
|
||||
yData={taskCompletion}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
</TabPane>
|
||||
|
||||
{/* <TabPane tab="众包统计任务" key="2">
|
||||
|
||||
</TabPane>
|
||||
|
||||
<TabPane tab="其他" key="4">
|
||||
|
||||
</TabPane> */}
|
||||
|
||||
</Tabs>
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
.box-item{
|
||||
display: flex;
|
||||
max-width: 300px;
|
||||
justify-content: space-around;
|
||||
margin: .75em;
|
||||
padding: .5em;
|
||||
background: #fff;
|
||||
border-radius: .5em;
|
||||
box-shadow: 0 1px 1px #d9d9d9;
|
||||
|
||||
.anticon{
|
||||
font-size: 4em;
|
||||
color: #1890ff;
|
||||
}
|
||||
|
||||
.box-item-num{
|
||||
font-size: 2em;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.box-item-describe{
|
||||
font-size: .9em;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
.ant-tabs-bar{
|
||||
border: 0;
|
||||
}
|
||||
.ant-tabs-tabpane {
|
||||
min-height: 25vh;
|
||||
}
|
||||
.ant-tabs-tab-active {
|
||||
color: #000;
|
||||
font-weight: 600;
|
||||
}
|
||||
.ant-tabs-nav .ant-tabs-tab:hover {
|
||||
color: #000;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.echart-box{
|
||||
height: 300px;
|
||||
margin: .75em;
|
||||
padding: 1em;
|
||||
border-radius: .5em;
|
||||
background: #fff;
|
||||
border:1px solid #d9d9d9;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
import React from "react";
|
||||
import { Route, Switch } from "react-router-dom";
|
||||
import Loadable from "react-loadable";
|
||||
import Loading from "../../Loading";
|
||||
|
||||
// 全局统计
|
||||
const Global = Loadable({
|
||||
loader: () => import("./global"),
|
||||
loading: Loading,
|
||||
});
|
||||
// 成员工作统计
|
||||
const Member = Loadable({
|
||||
loader: () => import("./member"),
|
||||
loading: Loading,
|
||||
});
|
||||
// 项目活跃度统计
|
||||
const Activity = Loadable({
|
||||
loader: () => import("./activity"),
|
||||
loading: Loading,
|
||||
});
|
||||
|
||||
|
||||
export default (propsF)=>{
|
||||
return (
|
||||
<Switch {...propsF}>
|
||||
{/* 全局统计 */}
|
||||
<Route
|
||||
path="/managements/statistics/global"
|
||||
render={(props) => (
|
||||
<Global {...propsF} {...props} />
|
||||
)}
|
||||
></Route>
|
||||
{/* 成员工作统计 */}
|
||||
<Route
|
||||
path="/managements/statistics/member"
|
||||
render={(props) => (
|
||||
<Member {...propsF} {...props} />
|
||||
)}
|
||||
></Route>
|
||||
{/* 活跃度统计 */}
|
||||
<Route
|
||||
path="/managements/statistics/activity"
|
||||
render={(props) => (
|
||||
<Activity {...propsF} {...props} />
|
||||
)}
|
||||
></Route>
|
||||
</Switch>
|
||||
)
|
||||
}
|
|
@ -0,0 +1,280 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import { Col, Row, Select, Button, DatePicker, notification } from 'antd';
|
||||
import moment from 'moment';
|
||||
import EchartLine from '../../components/EchartLine';
|
||||
import { beforeDayArr, paramToUrl } from '../../common/utils';
|
||||
import TableDetail from './table-detail';
|
||||
import fetch from 'military/notice/fetch';
|
||||
import './index.scss';
|
||||
|
||||
const { Option } = Select;
|
||||
const ButtonGroup = Button.Group;
|
||||
const { RangePicker } = DatePicker;
|
||||
|
||||
const monthArr = beforeDayArr();
|
||||
const nowDate = moment(new Date()).format('YYYY-MM-DD');
|
||||
const weekAgo = moment(new Date().setDate(new Date().getDate() - 6)).format('YYYY-MM-DD');
|
||||
console.log(weekAgo);
|
||||
const monthAgo = moment(new Date().setDate(new Date().getDate() - 30)).format('YYYY-MM-DD');
|
||||
const threeMonthAgo = moment(new Date().setDate(new Date().getDate() - 90)).format('YYYY-MM-DD');
|
||||
|
||||
export default function Member(props) {
|
||||
|
||||
const [member, setMember] = useState(undefined);
|
||||
const [memberList, setMemberList] = useState([]);
|
||||
const [timeType, setTimeType] = useState(2);
|
||||
const [dayNum, setDayNum] = useState(30);
|
||||
const [timeArr, setTimeArr] = useState(monthArr);
|
||||
const [startTime, setStartTime] = useState(monthAgo); //初始化为当前时间
|
||||
const [endTime, setEndTime] = useState(nowDate);
|
||||
|
||||
const [newTask, setNewTask] = useState(null);
|
||||
const [completedTask, setCompletedTask] = useState(null);
|
||||
const [newPrNum, setNewPrNum] = useState(null);
|
||||
const [newCommitNum, setNewCommitNum] = useState(null);
|
||||
const [newCodeNum, setNewCodeNum] = useState(null);
|
||||
|
||||
|
||||
|
||||
// 获取总体折线图数据
|
||||
function getAllDataLine() {
|
||||
let params = {
|
||||
startTime,
|
||||
endTime,
|
||||
}
|
||||
let url = encodeURI(paramToUrl('/api/DeveloperData/total', params));
|
||||
fetch({
|
||||
url,
|
||||
method: 'get',
|
||||
}).then(res => {
|
||||
if (res.code === '1') {
|
||||
const data = res.data;
|
||||
setNewTask(data.newTask);
|
||||
setCompletedTask(data.completedTask);
|
||||
setNewPrNum(data.newPrNum);
|
||||
setNewCommitNum(data.newCommitNum);
|
||||
setNewCodeNum(data.newCodeNum);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 获取单个成员的数据
|
||||
function getPersonData() {
|
||||
let params = {
|
||||
startTime,
|
||||
endTime,
|
||||
curPage: 1,
|
||||
pageSize: 31,
|
||||
userId: member.key,
|
||||
userName:member.login,
|
||||
};
|
||||
if (timeType == 1) {
|
||||
params.pageSize = 7;
|
||||
} else if (timeType == 3) {
|
||||
params.pageSize = 91;
|
||||
} else if (timeType == 0) {
|
||||
params.pageSize = dayNum;
|
||||
}
|
||||
let url = encodeURI(paramToUrl('/api/DeveloperData/detail/search', params));
|
||||
fetch({
|
||||
url,
|
||||
method: 'get',
|
||||
}).then(res => {
|
||||
let newTask = [];
|
||||
let completedTask = [];
|
||||
let newPrNum = [];
|
||||
let newCommitNum = [];
|
||||
let newCodeNum = [];
|
||||
|
||||
if (res.code === '1' && res.data.rows) {
|
||||
if (res.data.rows.length) {
|
||||
for (const item of res.data.rows) {
|
||||
newTask.unshift(item.newTask);
|
||||
completedTask.unshift(item.completedTask);
|
||||
newPrNum.unshift(item.newPrNum);
|
||||
newCommitNum.unshift(item.newCommitNum);
|
||||
newCodeNum.unshift(item.newCodeNum);
|
||||
}
|
||||
} else {
|
||||
newCodeNum.fill(0, 0,);
|
||||
}
|
||||
} else {
|
||||
notification.open({
|
||||
message: "错误",
|
||||
description: res.message,
|
||||
});
|
||||
}
|
||||
setNewTask(newTask);
|
||||
setCompletedTask(completedTask);
|
||||
setNewPrNum(newPrNum);
|
||||
setNewCommitNum(newCommitNum);
|
||||
setNewCodeNum(newCodeNum);
|
||||
});
|
||||
}
|
||||
|
||||
function onSearch(value) {
|
||||
if (value) {
|
||||
getMemberList(value);
|
||||
}
|
||||
}
|
||||
|
||||
// 获取成员数据
|
||||
let timeout;
|
||||
function getMemberList(value) {
|
||||
if (timeout) {
|
||||
clearTimeout(timeout);
|
||||
timeout = null;
|
||||
}
|
||||
function fake() {
|
||||
fetch({
|
||||
url: '/api/DeveloperData/detail/searchInput?userName=' + value,
|
||||
method: 'get',
|
||||
}).then(res => {
|
||||
if (res.code === '1') {
|
||||
setMemberList(res.data);
|
||||
} else {
|
||||
notification.open({
|
||||
message: "错误",
|
||||
description: res.message,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
timeout = setTimeout(fake, 1000);
|
||||
}
|
||||
|
||||
|
||||
function searchInTime(timeType) {
|
||||
setTimeType(timeType);
|
||||
if (timeType === 1) {
|
||||
setTimeArr(beforeDayArr(7));
|
||||
setStartTime(weekAgo);
|
||||
setEndTime(nowDate);
|
||||
|
||||
} else if (timeType === 2) {
|
||||
setTimeArr(monthArr);
|
||||
setStartTime(monthAgo);
|
||||
setEndTime(nowDate);
|
||||
} else if (timeType === 3) {
|
||||
setTimeArr(beforeDayArr(91));
|
||||
setStartTime(threeMonthAgo);
|
||||
setEndTime(nowDate);
|
||||
}
|
||||
}
|
||||
|
||||
function changeDate(dates, dateStrings) {
|
||||
if (dateStrings && dateStrings[0]) {
|
||||
setStartTime(dateStrings[0]);
|
||||
setEndTime(dateStrings[1]);
|
||||
let dayNum = (dates[1] - dates[0]) / 86400000 + 1;
|
||||
setTimeArr(beforeDayArr(dayNum, new Date(dates[1])));
|
||||
setTimeType(0);
|
||||
setDayNum(dayNum);
|
||||
} else {
|
||||
setTimeType(2);
|
||||
setTimeArr(monthArr);
|
||||
setStartTime(monthAgo);
|
||||
setEndTime(nowDate);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
if (member) {
|
||||
getPersonData();
|
||||
} else {
|
||||
getAllDataLine();
|
||||
}
|
||||
}, [startTime, endTime, member]);
|
||||
|
||||
function changeMember(val){
|
||||
if(val){
|
||||
for(const item of memberList){
|
||||
if(val.key==item.id){
|
||||
val.login=item.login
|
||||
}
|
||||
}
|
||||
}
|
||||
setMember(val);
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
<div className="content">
|
||||
<Row className="search-box">
|
||||
<Col xs={24} sm={12} lg={10} >
|
||||
<Select
|
||||
showSearch
|
||||
value={member}
|
||||
placeholder={'请选择成员或输入成员查询'}
|
||||
defaultActiveFirstOption={false}
|
||||
filterOption={false}
|
||||
onSearch={onSearch}
|
||||
onChange={(val) => { changeMember(val) }}
|
||||
notFoundContent={null}
|
||||
allowClear={true}
|
||||
labelInValue
|
||||
>
|
||||
{
|
||||
memberList.map(d => <Option key={d.id}>{d.nickname || d.login}</Option>)
|
||||
}
|
||||
</Select>
|
||||
</Col>
|
||||
|
||||
|
||||
<Col xs={24} sm={12} lg={14} className="choose-time">
|
||||
<ButtonGroup>
|
||||
<Button type={timeType === 1 ? "primary" : ""} onClick={() => { searchInTime(1) }}>
|
||||
近1周
|
||||
</Button>
|
||||
<Button type={timeType === 2 ? "primary" : ""} onClick={() => { searchInTime(2) }}>
|
||||
近1月
|
||||
</Button>
|
||||
<Button type={timeType === 3 ? "primary" : ""} onClick={() => { searchInTime(3) }}>
|
||||
近3月
|
||||
</Button>
|
||||
</ButtonGroup>
|
||||
|
||||
<div className="custom-time">
|
||||
<div className="time-label">自定义时间段</div>
|
||||
<RangePicker
|
||||
placeholder={['--/--', '--/--']}
|
||||
onChange={changeDate}
|
||||
/>
|
||||
</div>
|
||||
</Col>
|
||||
|
||||
</Row>
|
||||
|
||||
<EchartLine
|
||||
id="memberStatistics"
|
||||
xData={timeArr}
|
||||
seriesArr={
|
||||
[{
|
||||
name: '新增任务数',
|
||||
data: newTask
|
||||
}, {
|
||||
name: '完成任务数',
|
||||
data: completedTask
|
||||
}, {
|
||||
name: '新增PR数',
|
||||
data: newPrNum
|
||||
}, {
|
||||
name: '新增提交数',
|
||||
data: newCommitNum
|
||||
}, {
|
||||
name: '新增代码数',
|
||||
data: newCodeNum
|
||||
}]
|
||||
}
|
||||
/>
|
||||
|
||||
<h4 className="mt20">详情列表</h4>
|
||||
<TableDetail
|
||||
member={member}
|
||||
startTime={startTime}
|
||||
endTime={endTime}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
.search-box {
|
||||
margin-bottom: .75rem;
|
||||
.ant-select {
|
||||
min-width: 280px;
|
||||
}
|
||||
|
||||
.ant-btn:active, .ant-btn.active{
|
||||
color: #fff;
|
||||
background-color: #096dd9;
|
||||
border-color: #096dd9;
|
||||
}
|
||||
|
||||
.choose-time{
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
.ant-btn-group{
|
||||
margin-right: 10px;
|
||||
}
|
||||
.custom-time{
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
}
|
||||
.ant-calendar-picker{
|
||||
max-width: 250px;
|
||||
}
|
||||
.time-label{
|
||||
background: #fafbfc;
|
||||
line-height: 30px;
|
||||
padding: 0 10px;
|
||||
border: 1px solid #d9d9d9;
|
||||
border-right: 0;
|
||||
border-top-left-radius: 4px;
|
||||
border-bottom-left-radius: 4px;
|
||||
|
||||
}
|
||||
.ant-calendar-picker-input{
|
||||
text-align: left;
|
||||
border-top-left-radius: 0px;
|
||||
border-bottom-left-radius: 0px;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,175 @@
|
|||
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Table, Pagination, notification } from 'antd';
|
||||
import { paramToUrl } from '../../common/utils';
|
||||
import fetch from 'military/notice/fetch';
|
||||
|
||||
|
||||
export default ({ member, startTime, endTime }) => {
|
||||
|
||||
const [curPage, setCurPage] = useState(1);
|
||||
const [total, setTotal] = useState(0);
|
||||
const [orderBy, setOrderBy] = useState('');
|
||||
const [dataList, setDataList] = useState([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
getTableData();
|
||||
}, [member, startTime, endTime, orderBy, curPage]);
|
||||
|
||||
// 获取table数据
|
||||
function getTableData() {
|
||||
let params = {
|
||||
startTime,
|
||||
endTime,
|
||||
orderBy,
|
||||
curPage,
|
||||
pageSize: 10,
|
||||
};
|
||||
setLoading(true);
|
||||
let url;
|
||||
if (member) {
|
||||
// 获取单人数据
|
||||
params = {
|
||||
...params,
|
||||
userId: member.key,
|
||||
userName: member.login,
|
||||
};
|
||||
url = encodeURI(paramToUrl('/api/DeveloperData/detail/search', params));
|
||||
} else {
|
||||
// 获取总体数据
|
||||
url = encodeURI(paramToUrl('/api/DeveloperData/detail', params));
|
||||
}
|
||||
fetch({
|
||||
url,
|
||||
method: 'get',
|
||||
data: params
|
||||
}).then(res => {
|
||||
if (res.code === '1') {
|
||||
setDataList(res.data.rows);
|
||||
setTotal(res.data.total);
|
||||
} else {
|
||||
setDataList([]);
|
||||
setTotal(0);
|
||||
notification.open({
|
||||
message: "错误",
|
||||
description: res.message,
|
||||
});
|
||||
}
|
||||
setLoading(false);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function handleTableChange(pagination, filters, sorter) {
|
||||
if (sorter.order) {
|
||||
if (sorter.order === 'ascend') {
|
||||
setOrderBy(sorter.field + 'Asc');
|
||||
setCurPage(1);
|
||||
} else {
|
||||
setOrderBy(sorter.field + 'Desc');
|
||||
setCurPage(1);
|
||||
}
|
||||
} else {
|
||||
setOrderBy('');
|
||||
setCurPage(1);
|
||||
}
|
||||
}
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: '成员姓名',
|
||||
dataIndex: 'nickName',
|
||||
key: 'nickName',
|
||||
width: '20%',
|
||||
className: 'link',
|
||||
onCell,
|
||||
render: (text, record) => {
|
||||
return (text || record.userName)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '新增任务数',
|
||||
key: 'newTask',
|
||||
dataIndex: 'newTask',
|
||||
sorter: true,
|
||||
},
|
||||
{
|
||||
title: '完成任务数',
|
||||
key: 'completedTask',
|
||||
dataIndex: 'completedTask',
|
||||
sorter: true,
|
||||
},
|
||||
{
|
||||
title: '新增PR数',
|
||||
key: 'newPrNum',
|
||||
dataIndex: 'newPrNum',
|
||||
sorter: true,
|
||||
},
|
||||
{
|
||||
title: '新增提交数',
|
||||
key: 'newCommitNum',
|
||||
dataIndex: 'newCommitNum',
|
||||
sorter: true,
|
||||
},
|
||||
// {
|
||||
// title: '新增代码',
|
||||
// key: 'newCodeNum',
|
||||
// dataIndex: 'newCodeNum',
|
||||
// },
|
||||
];
|
||||
|
||||
function onCell(record) {
|
||||
return {
|
||||
onClick: event => { onCellClick(record) }, // 点击
|
||||
}
|
||||
}
|
||||
|
||||
function onCellClick(record) {
|
||||
|
||||
let url = encodeURI(paramToUrl('/api/DeveloperData/getUrl', { login: record.userName }));
|
||||
fetch({
|
||||
url,
|
||||
method: 'get',
|
||||
}).then(res => {
|
||||
if (res.code === '1') {
|
||||
window.open(res.data);
|
||||
} else {
|
||||
notification.open({
|
||||
message: "错误",
|
||||
description: res.message,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (member) {
|
||||
columns.splice(0, 1, {
|
||||
title: '日期',
|
||||
dataIndex: 'date',
|
||||
key: 'date',
|
||||
width: '20%',
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="table-detail">
|
||||
<Table
|
||||
loading={loading}
|
||||
rowKey={(row, i) => row.id || i}
|
||||
dataSource={dataList}
|
||||
columns={columns}
|
||||
pagination={false}
|
||||
onChange={handleTableChange}
|
||||
/>
|
||||
|
||||
{dataList.length > 0 &&
|
||||
<Pagination
|
||||
onChange={(page) => { setCurPage(page) }}
|
||||
current={curPage}
|
||||
total={total}
|
||||
loading={loading}
|
||||
/>}
|
||||
</div>
|
||||
)
|
||||
}
|
Loading…
Reference in New Issue