个人中心整体上线

This commit is contained in:
caishi 2021-05-31 17:44:30 +08:00
parent a9285f37e7
commit 1432afebfd
10 changed files with 376 additions and 49 deletions

5
package-lock.json generated
View File

@ -5075,6 +5075,11 @@
"zrender": "4.3.2" "zrender": "4.3.2"
} }
}, },
"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": { "editor.md": {
"version": "1.5.0", "version": "1.5.0",
"resolved": "https://registry.npmjs.org/editor.md/-/editor.md-1.5.0.tgz", "resolved": "https://registry.npmjs.org/editor.md/-/editor.md-1.5.0.tgz",

View File

@ -31,6 +31,7 @@
"dotenv": "4.0.0", "dotenv": "4.0.0",
"dotenv-expand": "4.2.0", "dotenv-expand": "4.2.0",
"echarts": "^4.9.0", "echarts": "^4.9.0",
"echarts-wordcloud": "^2.0.0",
"editor.md": "^1.5.0", "editor.md": "^1.5.0",
"eslint": "4.10.0", "eslint": "4.10.0",
"eslint-config-react-app": "^2.1.0", "eslint-config-react-app": "^2.1.0",

View File

@ -161,9 +161,7 @@
height: 7px; height: 7px;
margin-top: 12px; margin-top: 12px;
span{ span{
border-left: 1px solid #fff;
&:first-child{ &:first-child{
border-left: none;
border-radius: 10px 0px 0px 10px; border-radius: 10px 0px 0px 10px;
} }
&:last-child{ &:last-child{

View File

@ -4,12 +4,14 @@ import Js2WordCloud from 'js2wordcloud/dist/js2wordcloud.js'
function Cloud({data}) { function Cloud({data}) {
useEffect(()=>{ useEffect(()=>{
optionChart1(); if(data){
},[]) optionChart1(data);
}
},[data])
function optionChart1(){ function optionChart1(d){
var div = new Js2WordCloud(document.getElementById('cloud')) var div = new Js2WordCloud(document.getElementById('cloud'))
let textList=['服务', '细致', '意识', '踏实','开发', '反馈'] let textList= d.categories;
let cyList=[] let cyList=[]
for(let i=0;i<textList.length;i++){ for(let i=0;i<textList.length;i++){
cyList.push([textList[i],textList.length-i]) cyList.push([textList[i],textList.length-i])
@ -21,7 +23,7 @@ function Cloud({data}) {
maxFontSize: 21,// maxFontSize: 21,//
minFontSize: 16,// minFontSize: 16,//
tooltip: { tooltip: {
show: true show: false
}, },
list: cyList, list: cyList,
color(word, weight, fontSize, distance, theta) { // color(word, weight, fontSize, distance, theta) { //
@ -43,7 +45,7 @@ function Cloud({data}) {
}) })
} }
return( return(
<div id="cloud" style={{height:"200px"}}></div> <div id="cloud" style={{height:"120px"}}></div>
) )
} }
export default Cloud; export default Cloud;

View File

@ -3,32 +3,27 @@ import echarts from 'echarts/lib/echarts';
import 'echarts/lib/chart/pie'; import 'echarts/lib/chart/pie';
function Pie({data}) { function Pie({data}) {
useEffect(()=>{
Init();
},[])
useEffect(()=>{ useEffect(()=>{
if(data){ if(data){
Init(); Init(data);
} }
},[data]) },[data])
function Init() { function Init(d) {
var huan_val = document.getElementById("Pie"); var huan_val = document.getElementById("Pie");
var chart = echarts.init(huan_val); var chart = echarts.init(huan_val);
let option = { let option = {
color: ["#f8e367", "#99dfff", "#58c0f0", "#5ea6ff", "#ff9e48", "#bcbcbc"], color: ["#f8e367", "#5ea6ff", "#ff9e48", "#99dfff"],
title: { title: {
text: '角色定位', show:false
top:"5%",
left:"3%"
}, },
tooltip: { tooltip: {
trigger: 'item' trigger: 'item'
}, },
legend: { legend: {
top: '5%', top: '5%',
right: '3%' right: 'center'
}, },
series: [ series: [
{ {
@ -56,11 +51,10 @@ function Pie({data}) {
show: false show: false
}, },
data: [ data: [
{value: 1048, name: '搜索引擎'}, {value: d.developer && d.developer.count, name: '开发者'},
{value: 735, name: '直接访问'}, {value: d.manager && d.manager.count, name: '管理员'},
{value: 580, name: '邮件营销'}, {value: d.owner && d.owner.count, name: '创建者'},
{value: 484, name: '联盟广告'}, {value: d.reporter && d.reporter.count, name: '报告者'}
{value: 300, name: '视频广告'}
] ]
} }
] ]

View File

@ -3,54 +3,51 @@ import echarts from 'echarts/lib/echarts'
import 'echarts/lib/chart/radar'; import 'echarts/lib/chart/radar';
function Radar({data}) { function Radar({data}) {
useEffect(()=>{
Init();
},[])
useEffect(()=>{ useEffect(()=>{
if(data){ if(data){
Init(); Init(data);
} }
},[data]) },[data])
function Init() { function Init(d) {
var huan_val = document.getElementById("radar"); var huan_val = document.getElementById("radar");
var myEcharts = echarts.init(huan_val); var myEcharts = echarts.init(huan_val);
let option = { let option = {
color: ["#f8e367", "#99dfff", "#58c0f0", "#5ea6ff", "#ff9e48", "#bcbcbc"], color: ["#f8e367", "#99dfff", "#58c0f0", "#5ea6ff", "#ff9e48", "#bcbcbc"],
title: { title: {
text: '开发能力', show:false
top:"0",
left:"3%"
}, },
legend: { legend: {
data: ['预算分配', '实际开销'], data: ['个人能力(personal)', '社区平均(average)'],
top:"0", top:"3%",
right:"center" right:"center"
}, },
tooltip: {
trigger: 'item'
},
radar: { radar: {
// shape: 'circle', // shape: 'circle',
indicator: [ indicator: [
{ name: '销售', max: 6500}, { name: '影响力', max: 100},
{ name: '管理', max: 16000}, { name: '贡献度', max: 100},
{ name: '信息技术', max: 30000}, { name: '活跃度', max: 100},
{ name: '客服', max: 38000}, { name: '项目经验', max: 100},
{ name: '研发', max: 52000}, { name: '语言能力', max: 100},
{ name: '市场', max: 25000}
], ],
center:["50%","55%"] center:["50%","55%"]
}, },
series: [{ series: [{
name: '预算 vs 开销', name: '',
type: 'radar', type: 'radar',
data: [ data: [
{ {
value: [4200, 3000, 20000, 35000, 50000, 18000], value: d.user && [d.user.influence, d.user.contribution, d.user.activity, d.user.experience, d.user.language],
name: '预算分配' name: '个人能力(personal)'
}, },
{ {
value: [5000, 14000, 28000, 26000, 42000, 21000], value: d.platform && [d.platform.influence, d.platform.contribution, d.platform.activity, d.platform.experience, d.platform.language],
name: '实际开销' name: '社区平均(average)'
} }
] ]
}] }]

View File

@ -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;

View File

@ -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;
}

View File

@ -1,4 +1,4 @@
import React from 'react'; import React , {useEffect, useState} from 'react';
import './Index.scss'; import './Index.scss';
import 'echarts/lib/component/tooltip'; import 'echarts/lib/component/tooltip';
import 'echarts/lib/component/title'; import 'echarts/lib/component/title';
@ -8,13 +8,184 @@ import 'echarts/lib/component/markPoint';
import Pie from '../Echart/Pie'; import Pie from '../Echart/Pie';
import Cloud from '../Echart/Cloud'; import Cloud from '../Echart/Cloud';
import Radar from '../Echart/Radar'; 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( return(
<div> <div>
<Pie /> <div className="boxes">
<Cloud /> <FlexAJ>
<Radar /> <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> </div>
) )
} }

View File

@ -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;
}
}
}
}
}