forked from Gitlink/forgeplus-react
merge 个人中心部分 冲突
This commit is contained in:
parent
eab68ac270
commit
a7df6da5f0
|
@ -5070,6 +5070,11 @@
|
|||
"zrender": "4.3.0"
|
||||
}
|
||||
},
|
||||
"echarts-wordcloud": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npm.taobao.org/echarts-wordcloud/download/echarts-wordcloud-2.0.0.tgz?cache=0&sync_timestamp=1610779172014&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fecharts-wordcloud%2Fdownload%2Fecharts-wordcloud-2.0.0.tgz",
|
||||
"integrity": "sha1-Uu+BeJWAH/6emd0brKt2hrLewEo="
|
||||
},
|
||||
"editor.md": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/editor.md/-/editor.md-1.5.0.tgz",
|
||||
|
|
15
package.json
15
package.json
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "forge",
|
||||
"version": "0.1.0",
|
||||
"version": "3.0.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@monaco-editor/react": "^2.3.0",
|
||||
|
@ -14,6 +14,7 @@
|
|||
"babel-jest": "20.0.3",
|
||||
"babel-loader": "7.1.2",
|
||||
"babel-plugin-syntax-dynamic-import": "^6.18.0",
|
||||
"babel-polyfill": "^6.26.0",
|
||||
"babel-preset-react-app": "^3.1.1",
|
||||
"babel-runtime": "6.26.0",
|
||||
"bizcharts": "^3.5.8",
|
||||
|
@ -29,7 +30,8 @@
|
|||
"dompurify": "^2.0.15",
|
||||
"dotenv": "4.0.0",
|
||||
"dotenv-expand": "4.2.0",
|
||||
"echarts": "^4.7.0",
|
||||
"echarts": "^4.9.0",
|
||||
"echarts-wordcloud": "^2.0.0",
|
||||
"editor.md": "^1.5.0",
|
||||
"eslint": "4.10.0",
|
||||
"eslint-config-react-app": "^2.1.0",
|
||||
|
@ -46,6 +48,7 @@
|
|||
"install": "^0.12.2",
|
||||
"jest": "20.0.4",
|
||||
"js-base64": "^2.5.2",
|
||||
"js2wordcloud": "^1.1.12",
|
||||
"katex": "^0.11.1",
|
||||
"lodash": "^4.17.15",
|
||||
"loglevel": "^1.6.8",
|
||||
|
@ -62,7 +65,7 @@
|
|||
"postcss-loader": "2.0.8",
|
||||
"promise": "8.0.1",
|
||||
"prop-types": "^15.6.1",
|
||||
"qrcode.react": "^1.0.0",
|
||||
"qrcode.react": "^1.0.1",
|
||||
"qs": "^6.9.3",
|
||||
"quill": "^1.3.7",
|
||||
"quill-delta-to-html": "^0.11.0",
|
||||
|
@ -92,6 +95,7 @@
|
|||
"react-resizable": "^1.10.1",
|
||||
"react-router": "^4.2.0",
|
||||
"react-router-dom": "^4.2.2",
|
||||
"react-slick": "^0.28.1",
|
||||
"react-split-pane": "^0.1.91",
|
||||
"react-url-query": "^1.5.0",
|
||||
"react-zmage": "^0.8.5-beta.31",
|
||||
|
@ -102,6 +106,7 @@
|
|||
"scroll-into-view": "^1.14.2",
|
||||
"showdown": "^1.9.1",
|
||||
"showdown-katex": "^0.8.0",
|
||||
"slick-carousel": "^1.8.1",
|
||||
"store": "^2.0.12",
|
||||
"style-loader": "0.19.0",
|
||||
"styled-components": "^4.4.1",
|
||||
|
@ -111,7 +116,9 @@
|
|||
"webpack-dev-server": "^3.10.3",
|
||||
"webpack-manifest-plugin": "^2.2.0",
|
||||
"whatwg-fetch": "2.0.3",
|
||||
"wrap-md-editor": "^0.2.20"
|
||||
"wrap-md-editor": "^0.2.20",
|
||||
"xterm": "4.8.1",
|
||||
"xterm-addon-fit": "0.4.0"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "node --max_old_space_size=15360 scripts/start.js",
|
||||
|
|
|
@ -129,9 +129,7 @@
|
|||
height: 7px;
|
||||
margin-top: 12px;
|
||||
span{
|
||||
border-left: 1px solid #fff;
|
||||
&:first-child{
|
||||
border-left: none;
|
||||
border-radius: 10px 0px 0px 10px;
|
||||
}
|
||||
&:last-child{
|
||||
|
|
|
@ -4,12 +4,14 @@ import Js2WordCloud from 'js2wordcloud/dist/js2wordcloud.js'
|
|||
function Cloud({data}) {
|
||||
|
||||
useEffect(()=>{
|
||||
optionChart1();
|
||||
},[])
|
||||
if(data){
|
||||
optionChart1(data);
|
||||
}
|
||||
},[data])
|
||||
|
||||
function optionChart1(){
|
||||
function optionChart1(d){
|
||||
var div = new Js2WordCloud(document.getElementById('cloud'))
|
||||
let textList=['服务', '细致', '意识', '踏实','开发', '反馈']
|
||||
let textList= d.categories;
|
||||
let cyList=[]
|
||||
for(let i=0;i<textList.length;i++){
|
||||
cyList.push([textList[i],textList.length-i])
|
||||
|
@ -21,7 +23,7 @@ function Cloud({data}) {
|
|||
maxFontSize: 21,//最大字号
|
||||
minFontSize: 16,//最小字号
|
||||
tooltip: {
|
||||
show: true
|
||||
show: false
|
||||
},
|
||||
list: cyList,
|
||||
color(word, weight, fontSize, distance, theta) { //自定义颜色、透明度
|
||||
|
@ -43,7 +45,7 @@ function Cloud({data}) {
|
|||
})
|
||||
}
|
||||
return(
|
||||
<div id="cloud" style={{height:"200px"}}></div>
|
||||
<div id="cloud" style={{height:"120px"}}></div>
|
||||
)
|
||||
}
|
||||
export default Cloud;
|
|
@ -0,0 +1,69 @@
|
|||
import React ,{ useEffect } from 'react';
|
||||
import echarts from 'echarts/lib/echarts';
|
||||
import 'echarts/lib/chart/pie';
|
||||
|
||||
function Pie({data}) {
|
||||
|
||||
useEffect(()=>{
|
||||
if(data){
|
||||
Init(data);
|
||||
}
|
||||
},[data])
|
||||
|
||||
function Init(d) {
|
||||
var huan_val = document.getElementById("Pie");
|
||||
var chart = echarts.init(huan_val);
|
||||
let option = {
|
||||
color: ["#f8e367", "#5ea6ff", "#ff9e48", "#99dfff"],
|
||||
title: {
|
||||
show:false
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'item'
|
||||
},
|
||||
legend: {
|
||||
top: '5%',
|
||||
right: 'center'
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '',
|
||||
type: 'pie',
|
||||
radius: ['40%', '70%'],
|
||||
avoidLabelOverlap: false,
|
||||
itemStyle: {
|
||||
borderRadius: 10,
|
||||
borderColor: '#fff',
|
||||
borderWidth: 2
|
||||
},
|
||||
label: {
|
||||
show: false,
|
||||
position: 'center'
|
||||
},
|
||||
emphasis: {
|
||||
label: {
|
||||
show: true,
|
||||
fontSize: '40',
|
||||
fontWeight: 'bold'
|
||||
}
|
||||
},
|
||||
labelLine: {
|
||||
show: false
|
||||
},
|
||||
data: [
|
||||
{value: d.developer && d.developer.count, name: '开发者'},
|
||||
{value: d.manager && d.manager.count, name: '管理员'},
|
||||
{value: d.owner && d.owner.count, name: '创建者'},
|
||||
{value: d.reporter && d.reporter.count, name: '报告者'}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
chart.setOption(option);
|
||||
}
|
||||
|
||||
return(
|
||||
<div id="Pie" style={{height:"400px"}}></div>
|
||||
)
|
||||
}
|
||||
export default Pie;
|
|
@ -0,0 +1,62 @@
|
|||
import React ,{ useEffect } from 'react';
|
||||
import echarts from 'echarts/lib/echarts'
|
||||
import 'echarts/lib/chart/radar';
|
||||
|
||||
function Radar({data}) {
|
||||
|
||||
useEffect(()=>{
|
||||
if(data){
|
||||
Init(data);
|
||||
}
|
||||
},[data])
|
||||
|
||||
function Init(d) {
|
||||
var huan_val = document.getElementById("radar");
|
||||
var myEcharts = echarts.init(huan_val);
|
||||
let option = {
|
||||
color: ["#f8e367", "#99dfff", "#58c0f0", "#5ea6ff", "#ff9e48", "#bcbcbc"],
|
||||
title: {
|
||||
show:false
|
||||
},
|
||||
legend: {
|
||||
data: ['个人能力(personal)', '社区平均(average)'],
|
||||
top:"3%",
|
||||
right:"center"
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'item'
|
||||
},
|
||||
radar: {
|
||||
// shape: 'circle',
|
||||
indicator: [
|
||||
{ name: '影响力', max: 100},
|
||||
{ name: '贡献度', max: 100},
|
||||
{ name: '活跃度', max: 100},
|
||||
{ name: '项目经验', max: 100},
|
||||
{ name: '语言能力', max: 100},
|
||||
],
|
||||
center:["50%","55%"]
|
||||
},
|
||||
series: [{
|
||||
name: '',
|
||||
type: 'radar',
|
||||
data: [
|
||||
{
|
||||
value: d.user && [d.user.influence, d.user.contribution, d.user.activity, d.user.experience, d.user.language],
|
||||
name: '个人能力(personal)'
|
||||
},
|
||||
{
|
||||
value: d.platform && [d.platform.influence, d.platform.contribution, d.platform.activity, d.platform.experience, d.platform.language],
|
||||
name: '社区平均(average)'
|
||||
}
|
||||
]
|
||||
}]
|
||||
};
|
||||
myEcharts.setOption(option);
|
||||
}
|
||||
|
||||
return(
|
||||
<div id="radar" style={{height:"400px"}}></div>
|
||||
)
|
||||
}
|
||||
export default Radar;
|
|
@ -0,0 +1,26 @@
|
|||
import React from 'react';
|
||||
import './style.scss';
|
||||
|
||||
|
||||
function Round({num,color,name}) {
|
||||
return(
|
||||
<div className={"annulusBasics"}>
|
||||
<div className={"centerCircle"} style={{color:`${color}`}}>
|
||||
<span><span className="score">{num}</span>分</span>
|
||||
<span>{name}</span>
|
||||
</div>
|
||||
<div className={"annulusOuter"} style={{border:`7px solid ${color}`}}></div>
|
||||
{num > 50 ?
|
||||
<div className={"leftRectangle"} style={{ transform: `rotate(${180/50 *(num - 50)}deg)` }}></div>
|
||||
:
|
||||
<div className={"leftRectangle"} ></div>
|
||||
}
|
||||
{num < 50 ?
|
||||
<div className={"rightRectangle"} style={{ transform: `rotate(${180/50 * num}deg)` }}></div>
|
||||
:
|
||||
<div className={"rightRectangle"} style={{ background: color }}></div>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
export default Round;
|
|
@ -0,0 +1,69 @@
|
|||
.annulusBasics {
|
||||
width : 74px;
|
||||
height : 74px;
|
||||
position : relative;
|
||||
overflow : hidden;
|
||||
border-radius: 50%;
|
||||
text-align : center;
|
||||
z-index : 1;
|
||||
}
|
||||
//圆环中间的白色
|
||||
.centerCircle {
|
||||
position : absolute;
|
||||
z-index : 10;
|
||||
border-radius: 50%;
|
||||
width : 60px;
|
||||
height : 60px;
|
||||
background : #fff;
|
||||
transform : translate(7px, 7px);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
line-height: 20px;
|
||||
font-size: 12px;
|
||||
.score{
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
//圆环百分比时出现圆环边框的颜色
|
||||
.annulusOuter {
|
||||
position : absolute;
|
||||
top : 0;
|
||||
left : 0;
|
||||
width : 74px;
|
||||
height : 74px;
|
||||
border : 12px solid #FF7F69;
|
||||
border-radius: 50%;
|
||||
}
|
||||
//左边遮住圆环颜色的长方形
|
||||
.leftRectangle {
|
||||
position : absolute;
|
||||
background : #EBEEF5;
|
||||
width : 37px;
|
||||
height : 74px;
|
||||
transform-origin: right;
|
||||
}
|
||||
//右边遮住圆环颜色的长方形
|
||||
.rightRectangle {
|
||||
position : absolute;
|
||||
background : #EBEEF5;
|
||||
transform-origin: left;
|
||||
left : 37px;
|
||||
width : 37px;
|
||||
height : 74px;
|
||||
transform : rotate(0deg);
|
||||
}
|
||||
//弥补hidde在移动端失效的圆环
|
||||
.repairAnnulus{
|
||||
position : absolute;
|
||||
width : 74px;
|
||||
height : 74px;
|
||||
z-index : 20;
|
||||
border-radius: 50%;
|
||||
box-sizing : content-box;
|
||||
//改外边框的时候,位置也要改下
|
||||
border : 20px solid #ffffff;
|
||||
top : -20px;
|
||||
left : -20px;
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
import React from 'react';
|
||||
import React , {useEffect, useState} from 'react';
|
||||
import './Index.scss';
|
||||
import 'echarts/lib/component/tooltip';
|
||||
import 'echarts/lib/component/title';
|
||||
|
@ -8,13 +8,184 @@ import 'echarts/lib/component/markPoint';
|
|||
import Pie from '../Echart/Pie';
|
||||
import Cloud from '../Echart/Cloud';
|
||||
import Radar from '../Echart/Radar';
|
||||
import Round from '../Echart/Round';
|
||||
import { DatePicker } from 'antd';
|
||||
import moment from 'moment';
|
||||
|
||||
import { FlexAJ } from '../../Component/layout';
|
||||
import Axios from 'axios';
|
||||
|
||||
const { RangePicker } = DatePicker;
|
||||
const dateFormat = 'YYYY-MM-DD';
|
||||
function Index(props) {
|
||||
const username = props.match.params.username;
|
||||
const [ dates, setDates] = useState(undefined);
|
||||
const [ pieData, setPieData ] = useState([]);
|
||||
const [ rDates, setRDates ] = useState(undefined);
|
||||
const [ radarData, setRadarData ] = useState([]);
|
||||
|
||||
const [ topThree , setTopThree] = useState(undefined);
|
||||
const [ percentData , setPercentData ] = useState(undefined);
|
||||
|
||||
const [ cData, setCData ] = useState(undefined);
|
||||
const [ cloudData, setCloudData ] = useState(undefined);
|
||||
|
||||
const disabledDate = current => {
|
||||
return current && current > moment().endOf('day');
|
||||
};
|
||||
|
||||
// 获取角色定位接口数据
|
||||
useEffect(()=>{
|
||||
getRoleSta();
|
||||
},[dates])
|
||||
|
||||
function getRoleSta() {
|
||||
const url = `/users/${username}/statistics/role.json`;
|
||||
Axios.get(url,{
|
||||
params:{
|
||||
start_time:dates && dates[0],
|
||||
end_time:dates && dates[1]
|
||||
}
|
||||
}).then(result=>{
|
||||
if(result && result.data){
|
||||
setPieData(result.data.role);
|
||||
}
|
||||
}).catch(error=>{})
|
||||
}
|
||||
|
||||
|
||||
// 获取开发能力接口数据
|
||||
useEffect(()=>{
|
||||
getRadarSta();
|
||||
},[rDates])
|
||||
|
||||
function getRadarSta() {
|
||||
const url = `/users/${username}/statistics/develop.json`;
|
||||
Axios.get(url,{
|
||||
params:{
|
||||
start_time:rDates && rDates[0],
|
||||
end_time:rDates && rDates[1]
|
||||
}
|
||||
}).then(result=>{
|
||||
if(result && result.data){
|
||||
setRadarData(result.data);
|
||||
let score = result.data.user && result.data.user.each_language_score;
|
||||
var sortData = []
|
||||
for (var item in score) {
|
||||
sortData.push([item, score[item]])
|
||||
}
|
||||
sortData.sort(function(a, b) {
|
||||
return b[1] - a[1];
|
||||
});
|
||||
setTopThree(sortData.slice(0,3));
|
||||
|
||||
let percent = result.data.user && result.data.user.languages_percent;
|
||||
let arr = [];
|
||||
Object.keys(percent).map((item,key)=>{
|
||||
arr.push({name:item,p:percent[item]*100,color:getColor()});
|
||||
})
|
||||
setPercentData(arr);
|
||||
}
|
||||
}).catch(error=>{})
|
||||
}
|
||||
function getColor(){
|
||||
let str = "#";
|
||||
let arr = ["1","2","3","4","4","5","6","7","8","9","a","b","c","d","e","f"];
|
||||
for(var i=0;i<6;i++){
|
||||
let num = parseInt(Math.random() * 16,0);
|
||||
str+=arr[num];
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
//用户专业定位
|
||||
useEffect(()=>{
|
||||
getCloudSta();
|
||||
},[cData])
|
||||
|
||||
function getCloudSta() {
|
||||
const url = `/users/${username}/statistics/major.json`;
|
||||
Axios.get(url,{
|
||||
params:{
|
||||
start_time:rDates && rDates[0],
|
||||
end_time:rDates && rDates[1]
|
||||
}
|
||||
}).then(result=>{
|
||||
if(result && result.data){
|
||||
setCloudData(result.data);
|
||||
}
|
||||
}).catch(error=>{})
|
||||
}
|
||||
|
||||
function Index() {
|
||||
return(
|
||||
<div>
|
||||
<Pie />
|
||||
<Cloud />
|
||||
<Radar />
|
||||
<div className="boxes">
|
||||
<FlexAJ>
|
||||
<span className="font-18">开发能力</span>
|
||||
<RangePicker
|
||||
disabledDate={disabledDate}
|
||||
onChange={(val,dateString) => {setRDates(dateString)}}
|
||||
format={dateFormat}
|
||||
/>
|
||||
</FlexAJ>
|
||||
<Radar data={radarData}/>
|
||||
{
|
||||
topThree &&
|
||||
<div className="roundBox">
|
||||
<Round num={topThree[0][1]} color="#FF7F69" name={topThree[0][0]}/>
|
||||
<Round num={topThree[1][1]} color="#99dfff" name={topThree[1][0]}/>
|
||||
<Round num={topThree[2][1]} color="#ff9e48" name={topThree[2][0]}/>
|
||||
</div>
|
||||
}
|
||||
{
|
||||
percentData &&
|
||||
<div className="pBox">
|
||||
<div class="progress">
|
||||
{
|
||||
percentData.map((i,k)=>{
|
||||
return(
|
||||
<span style={{width: `${i.p}%`, backgroundColor:`${i.color}`}}></span>
|
||||
)
|
||||
})
|
||||
}
|
||||
</div>
|
||||
<div className="progresstip">
|
||||
{
|
||||
percentData.map((i,k)=>{
|
||||
return(
|
||||
<span>
|
||||
<i class="zero" style={{backgroundColor: `${i.color}`}}></i><span>{i.name}</span>
|
||||
<span>{`${i.p}%`}</span>
|
||||
</span>
|
||||
)
|
||||
})
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div className="boxes">
|
||||
<FlexAJ>
|
||||
<span className="font-18">角色定位</span>
|
||||
<RangePicker
|
||||
disabledDate={disabledDate}
|
||||
onChange={(val,dateString) => {setDates(dateString)}}
|
||||
format={dateFormat}
|
||||
/>
|
||||
</FlexAJ>
|
||||
<Pie data={pieData}/>
|
||||
</div>
|
||||
<div className="boxes">
|
||||
<FlexAJ>
|
||||
<span className="font-18">专业定位</span>
|
||||
<RangePicker
|
||||
disabledDate={disabledDate}
|
||||
onChange={(val,dateString) => {setCData(dateString)}}
|
||||
format={dateFormat}
|
||||
/>
|
||||
</FlexAJ>
|
||||
<Cloud data={cloudData}/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
.boxes{
|
||||
padding:20px 30px;
|
||||
.roundBox{
|
||||
margin:20px auto;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
& >div{
|
||||
margin:0px 30px;
|
||||
}
|
||||
}
|
||||
.pBox{
|
||||
width: 400px;
|
||||
margin:40px auto 20px;
|
||||
.progress{
|
||||
width: 360px;
|
||||
margin:0px auto;
|
||||
display: flex;
|
||||
background-color: #fafafa;
|
||||
border-radius: 10px;
|
||||
height: 7px;
|
||||
span:first-child {
|
||||
border-radius: 10px 0px 0px 10px;
|
||||
}
|
||||
span:last-child {
|
||||
border-radius: 0px 10px 10px 0px;
|
||||
}
|
||||
}
|
||||
.progresstip {
|
||||
margin-top: 15px;
|
||||
flex-wrap: wrap;
|
||||
display: flex;
|
||||
-webkit-align-items: center;
|
||||
-webkit-box-align: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
-webkit-box-pack: justify;
|
||||
-webkit-justify-content: space-between;
|
||||
-ms-flex-pack: justify;
|
||||
justify-content: space-between;
|
||||
& > span {
|
||||
padding-left: 15px;
|
||||
position: relative;
|
||||
min-width: 33%;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
i.zero {
|
||||
display: block;
|
||||
border-radius: 50%;
|
||||
height: 8px;
|
||||
width: 8px;
|
||||
margin-top:10px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
span {
|
||||
color: #666;
|
||||
}
|
||||
span:last-child {
|
||||
color: #999;
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue