538 lines
20 KiB
Vue
538 lines
20 KiB
Vue
<template>
|
||
<div style="display:flex;flex-direction:row;flex-wrap: nowrap">
|
||
<div style="display: flex;flex-direction:column;flex-wrap: nowrap">
|
||
<div class="PageHeader">
|
||
<br/>
|
||
<el-page-header @back="goBack" style="justify-content:left;display: flex;">
|
||
<div slot="title" style="font-size:23px;font-weight: 600;"></div>
|
||
<div slot="content" class="test" style="font-size:23px;font-weight: 600;">
|
||
<div>{{TitleWord}}</div>
|
||
</div>
|
||
</el-page-header>
|
||
</div>
|
||
<div class="PageContent" style="display: flex;flex-direction: column;flex-wrap: nowrap">
|
||
<el-card class="box-card">
|
||
<div style="display: flex;flex-direction: row;flex-wrap: nowrap;justify-content: space-between">
|
||
<el-cascader @change="FreshPage(selectedValue,1)" v-model="selectedValue" :options="options" placeholder="选择分类"
|
||
:show-all-levels="false" style="width: 10vw"></el-cascader>
|
||
<el-image fit="fill" :src="require('@/assets/svg/logo-tiobe.svg')" style="width:8vw;height: 4vh;display: flex;flex-direction: row;justify-content: flex-end"></el-image>
|
||
<el-select @change="FreshPage(selectedValue,2)" placeholder="选择年份" v-model="selectedValueByYear" style="width: 7vw" :disabled="ban">
|
||
<el-option
|
||
v-for="(n,index) in 12"
|
||
:key="index"
|
||
:label="index + 2012"
|
||
:value="index"
|
||
>
|
||
</el-option>
|
||
</el-select>
|
||
</div>
|
||
</el-card>
|
||
<el-card class="box-card" style="margin-top: 20px">
|
||
<el-switch
|
||
ref="switch"
|
||
@change="FreshPage(selectedValue,0)"
|
||
style="margin-left:75%"
|
||
v-model="value1"
|
||
:active-text=activeWord
|
||
:inactive-text=inactiveWord>
|
||
</el-switch>
|
||
|
||
<div ref="totalContent" style="margin-top:10px">
|
||
<el-row :gutter="24" style="margin-top:20px;">
|
||
<el-col :span="20" style="margin-left:10%">
|
||
<el-card shadow="always">
|
||
<span style="font-size:30px;font-weight:600">GitHub官网数据整理</span>
|
||
</el-card>
|
||
</el-col>
|
||
</el-row>
|
||
<el-table
|
||
border
|
||
class="DataForm"
|
||
:data="showData"
|
||
style="margin-top:50px;width:500px;margin-left:20%;"
|
||
:header-row-style="{height:'15px'}" :cell-style="{padding:'1px'}">
|
||
<el-table-column
|
||
prop="name"
|
||
:label=formName[0]
|
||
>
|
||
</el-table-column>
|
||
<el-table-column
|
||
prop="count"
|
||
:label=formName[1]
|
||
>
|
||
</el-table-column>
|
||
</el-table>
|
||
</div>
|
||
<!-- <el-button @click="test()"></el-button>-->
|
||
<el-row :gutter="24" style="margin-top:20px;">
|
||
<el-col :span="20" style="margin-left:10%">
|
||
<el-card shadow="always">
|
||
<span style="font-size:30px;font-weight:600">GitHub官网数据统计图</span>
|
||
</el-card>
|
||
</el-col>
|
||
</el-row>
|
||
<div ref="EChart" style="margin-left:20px;width: 700px;height:700px;margin-top:20px"></div>
|
||
</el-card>
|
||
</div>
|
||
</div>
|
||
<RightTools></RightTools>
|
||
</div>
|
||
</template>
|
||
|
||
|
||
<script>
|
||
import RightTools from "@/components/Home/RightTools.vue";
|
||
import axios from 'axios'; // 安装axios后引入
|
||
import Vue from "vue";
|
||
Vue.prototype.$axios = axios; // 将axios挂载到原型上方便使用
|
||
import * as echarts from 'echarts'
|
||
Vue.prototype.$echarts = echarts;
|
||
|
||
export default {
|
||
name: "RankingComponent",
|
||
components: {RightTools},
|
||
data(){
|
||
return{
|
||
// 标头文字:
|
||
TitleWord:'GitHub星数年度排行榜',
|
||
// 开关文本:
|
||
activeWord:'月度趋势',
|
||
inactiveWord:'年度统计',
|
||
// 禁用年份选择:
|
||
ban:false,
|
||
// echart图:
|
||
manuChart:null,
|
||
// Echart图options:
|
||
MyOption:{},
|
||
// 最后展示数据:
|
||
showData:[],
|
||
// 数据表格表头:
|
||
formName:[],
|
||
// 星数数据:
|
||
starNum:[],
|
||
// 项目拉取数:
|
||
pullNum:[],
|
||
// 推送项目数:
|
||
pushNum:[],
|
||
// 协议数:
|
||
licensesNum:[],
|
||
// 榜单分类目录:
|
||
options:[{
|
||
value: '1',
|
||
label: '编程语言',
|
||
children:[{
|
||
value:'2',
|
||
label:'星数',
|
||
}, {
|
||
value:'3',
|
||
label:'推送项目数'
|
||
},
|
||
{
|
||
value:'4',
|
||
label:'拉取项目数',
|
||
}
|
||
]
|
||
},{
|
||
value:'5',
|
||
label:'协议种类'
|
||
}
|
||
],
|
||
value1: false,
|
||
// 默认用户选择的分类
|
||
selectedValue:['1','2'],
|
||
selectedValueByYear:null,
|
||
}
|
||
},
|
||
updated(){
|
||
// history.go(0);
|
||
},
|
||
created() {
|
||
// 使用getjson读取数据
|
||
var that = this;
|
||
this.$axios.get("/gh-star-event.json").then(res => {
|
||
that.starNum = res.data;
|
||
})
|
||
this.$axios.get("/gh-push-event.json").then(res => {
|
||
that.pushNum = res.data;
|
||
})
|
||
this.$axios.get("/gh-pull-request.json").then(res => {
|
||
that.pullNum = res.data;
|
||
})
|
||
this.$axios.get("/github-licenses.json").then(res => {
|
||
that.licensesNum = res.data;
|
||
})
|
||
},
|
||
mounted() {
|
||
this.initPage();
|
||
},
|
||
methods: {
|
||
goBack() {
|
||
window.history.go(-1);
|
||
},
|
||
test(){
|
||
console.log(this.showData);
|
||
},
|
||
// 用户改变分类榜单时,刷新页面:
|
||
initPage(){
|
||
var that = this;
|
||
that.formName=['语言种类','获得星数'];
|
||
that.activeWord='月度趋势';
|
||
that.inactiveWord='年度统计';
|
||
that.ban=false;
|
||
that.showData = [];
|
||
this.manuChart = this.$echarts.init(this.$refs.EChart);
|
||
// this.getNumData(2023,false);
|
||
},
|
||
|
||
FreshPage(type,index){
|
||
var that = this;
|
||
that.ban=false;
|
||
if(index == 1) {
|
||
that.selectedValueByYear = 11;
|
||
that.value1 = false;
|
||
this.$refs.totalContent.style.display = 'block';
|
||
}
|
||
if(index == 1 || index == 2 || index == 0 && that.selectedValueByYear != null){
|
||
if(that.value1 == false && index == 0) this.$refs.totalContent.style.display = 'block';
|
||
type = type[type.length-1] - 1;
|
||
let year = that.selectedValueByYear + 2012;
|
||
if(type == 1){
|
||
// 按星数统计:
|
||
this.getNumData(year,that.value1,that.starNum);
|
||
that.formName=['语言种类','获得星数']
|
||
that.activeWord='月度趋势';
|
||
that.inactiveWord='年度统计';
|
||
that.TitleWord='GitHub星数年度排行榜';
|
||
}else if(type == 2){
|
||
this.getNumData(year,that.value1,that.pushNum);
|
||
that.formName=['语言种类','推送项目数']
|
||
that.activeWord='月度趋势';
|
||
that.inactiveWord='年度统计';
|
||
that.TitleWord='GitHub推送数年度排行榜';
|
||
}else if(type == 3){
|
||
this.getNumData(year,that.value1,that.pullNum);
|
||
that.formName=['语言种类','用户拉取项目数']
|
||
that.activeWord='月度趋势';
|
||
that.inactiveWord='年度统计';
|
||
that.TitleWord='GitHub拉取数年度排行榜';
|
||
}else if(type == 4){
|
||
this.getLiscenseData(that.value1);
|
||
that.formName=['协议种类','项目数']
|
||
that.activeWord='各协议占比';
|
||
that.inactiveWord='数据总览';
|
||
that.TitleWord='GitHub协议年度排行榜';
|
||
that.ban=true;
|
||
}
|
||
}
|
||
if(index == 0 && that.selectedValueByYear == null){
|
||
this.$message({
|
||
message: '请先选择年份!',
|
||
type: 'warning',
|
||
offset:100,
|
||
duration:500,
|
||
});
|
||
// 不让修改:
|
||
if(that.value1 == false) that.value1 = true;
|
||
if(that.value1 == true) that.value1 = false;
|
||
}
|
||
|
||
},
|
||
// 语言分类的数据:
|
||
getNumData(year,index,Mydata){
|
||
function compare(property) {
|
||
return function (a, b) {
|
||
var value1 = a[property];
|
||
var value2 = b[property];
|
||
return value2 - value1;
|
||
}
|
||
}
|
||
var that = this;
|
||
that.showData = [];
|
||
let starNum2 = Mydata.filter(item => item['year'] == year);
|
||
if(index == false){
|
||
let tmp = [];
|
||
// 按年度统计:
|
||
for(let i=0;i<starNum2.length;i++){
|
||
let tmpObj = {name:starNum2[i].name,count:starNum2[i].count};
|
||
let findSignal = tmp.findIndex(item=>item['name'] == tmpObj['name']);
|
||
if (findSignal != -1){
|
||
tmp[findSignal]['count'] = parseInt(tmp[findSignal]['count']) + parseInt(tmpObj['count']);
|
||
}else{
|
||
tmp.push(tmpObj);
|
||
}
|
||
}
|
||
that.showData = tmp.slice(0,18);
|
||
that.showData = that.showData.sort(compare('count'));
|
||
this.getRenderer();
|
||
}else{
|
||
// 按月度统计:
|
||
this.$refs.totalContent.style.display = 'none';
|
||
let quarterItems = [];
|
||
for(let i=0;i<15;i++){
|
||
// 初始化数据模板:
|
||
let tmpName = starNum2[i].name;
|
||
let tmpcount = starNum2[i].count;
|
||
let Quarter = parseInt(starNum2[i]['quarter']) - 1;
|
||
//对应该四个月的数量:
|
||
let monthCount = [0,0,0,0];
|
||
// 应该存入的对应季度数组下标:quarterItems[starNum2[i]['quarter']]
|
||
if(that.selectedValueByYear == 11){
|
||
monthCount = monthCount.fill(tmpcount);
|
||
}else{
|
||
monthCount[Quarter] = tmpcount;
|
||
}
|
||
//创建该折线数据对象:
|
||
let tmpObj = {'name':tmpName,'type':'line','data':monthCount};
|
||
quarterItems.push(tmpObj);
|
||
}
|
||
for(let j=15;j<starNum2.length;j++){
|
||
if(that.selectedValueByYear == 2023) break;
|
||
let tmpName = starNum2[j].name;
|
||
let tmpcount = starNum2[j].count;
|
||
let Quarter = parseInt(starNum2[j]['quarter']) - 1;
|
||
let LastQ = parseInt(Quarter) - 1;
|
||
let findSignal = quarterItems.findIndex(item=>item['name'] == tmpName);
|
||
if(findSignal != -1){
|
||
let p = parseInt(quarterItems[findSignal]['data'][parseInt(LastQ)]);
|
||
quarterItems[findSignal]['data'][Quarter] = p + parseInt(tmpcount);
|
||
}
|
||
}
|
||
that.showData = quarterItems;
|
||
this.getLineChart();
|
||
}
|
||
|
||
},
|
||
getLiscenseData(index){
|
||
var that = this;
|
||
that.showData = that.licensesNum;
|
||
that.showData = JSON.parse(JSON.stringify(that.showData).replace(/license/g,"name"));
|
||
that.showData = JSON.parse(JSON.stringify(that.showData).replace(/count/g,"count"))
|
||
if(index == false){
|
||
this.getRendererLiscense();
|
||
}if(index == true){
|
||
this.$refs.totalContent.style.display = 'none';
|
||
this.getPie();
|
||
}
|
||
},
|
||
// 饼图:
|
||
getPie(){
|
||
var that = this;
|
||
let tmp = that.licensesNum;
|
||
tmp = JSON.parse(JSON.stringify(tmp).replace(/license/g,"name"));
|
||
tmp = JSON.parse(JSON.stringify(tmp).replace(/count/g,"value"))
|
||
that.MyOption = {
|
||
tooltip: {
|
||
trigger: 'item', //item数据项图形触发,主要在散点图,饼图等无类目轴的图表中使用。
|
||
axisPointer: {
|
||
// 坐标轴指示器,坐标轴触发有效
|
||
type: 'shadow' // 默认为直线,可选为:'line' | 'shadow'
|
||
},
|
||
formatter: '{a} <br/>{b} 协议项目 : {c} 个 <br/>百分比 : {d}%' //{a}(系列名称),{b}(数据项名称),{c}(数值), {d}(百分比)
|
||
},
|
||
series: [{
|
||
name:'协议数据',
|
||
type: 'pie',
|
||
data: tmp,
|
||
label: {//饼图文字的显示
|
||
show: true, //默认 显示文字
|
||
formatter: function (arg) {
|
||
return arg.name + ' 项目 ' + arg.value + " 个 " +'\n'+ arg.percent + "%"
|
||
}
|
||
},
|
||
radius: 220 //饼图的半径
|
||
}],
|
||
grid: {
|
||
x: '18%',
|
||
y: 0,
|
||
x2: '10%',
|
||
y2: 0
|
||
},
|
||
dataZoom: {
|
||
yAxisIndex: [0],
|
||
type:'inside',
|
||
start: 0,
|
||
end: 100,
|
||
zoomLock:true,
|
||
}
|
||
};
|
||
that.manuChart.setOption(that.MyOption,true);
|
||
},
|
||
// 横向柱状图(协议种类):
|
||
getRendererLiscense() {
|
||
var that = this;
|
||
let name = [];
|
||
let value = [];
|
||
for(let i=0;i < that.showData.length;i++){
|
||
name.push(that.showData[i]['name']);
|
||
value.push(that.showData[i]['count']);
|
||
}
|
||
that.MyOption = {
|
||
tooltip: {
|
||
trigger: "axis"
|
||
},
|
||
xAxis: {
|
||
type: 'value',
|
||
min: 0,
|
||
axisLabel : {
|
||
show : false
|
||
},
|
||
splitLine : {
|
||
show : false
|
||
}
|
||
},
|
||
yAxis: {
|
||
type: 'category',
|
||
inverse: true,
|
||
axisTick : {
|
||
show : false
|
||
},
|
||
axisLine:{
|
||
show : false
|
||
},
|
||
data: name,
|
||
},
|
||
series: [{
|
||
name: '项目总数',
|
||
type: 'bar',
|
||
barWidth:13,
|
||
data: value,
|
||
label: {
|
||
show: true,
|
||
position: 'right'
|
||
}
|
||
}],
|
||
grid: {
|
||
x: '18%',
|
||
y: 0,
|
||
x2: '10%',
|
||
y2: 0
|
||
},
|
||
dataZoom: {
|
||
yAxisIndex: [0],
|
||
type:'inside',
|
||
start: 0,
|
||
end: 100,
|
||
zoomLock:true,
|
||
}
|
||
};
|
||
that.manuChart.setOption(that.MyOption,true);
|
||
},
|
||
// 横向柱状图(编程语言):
|
||
getRenderer() {
|
||
var that = this;
|
||
let name = [];
|
||
let value = [];
|
||
for(let i=0;i < that.showData.length;i++){
|
||
name.push(that.showData[i]['name']);
|
||
value.push(that.showData[i]['count']);
|
||
}
|
||
that.MyOption = {
|
||
tooltip: {
|
||
trigger: "axis"
|
||
},
|
||
xAxis: {
|
||
type: 'value',
|
||
min: 0,
|
||
axisLabel : {
|
||
show : false
|
||
},
|
||
splitLine : {
|
||
show : false
|
||
}
|
||
},
|
||
yAxis: {
|
||
type: 'category',
|
||
inverse: true,
|
||
axisTick : {
|
||
show : false
|
||
},
|
||
axisLine:{
|
||
show : false
|
||
},
|
||
data: name,
|
||
},
|
||
series: [{
|
||
name: '获取星数',
|
||
type: 'bar',
|
||
barWidth:13,
|
||
data: value,
|
||
label: {
|
||
show: true,
|
||
position: 'right'
|
||
}
|
||
}],
|
||
grid: {
|
||
x: '18%',
|
||
y: 0,
|
||
x2: '10%',
|
||
y2: 0
|
||
},
|
||
dataZoom: {
|
||
yAxisIndex: [0],
|
||
type:'inside',
|
||
start: 0,
|
||
end: 100,
|
||
zoomLock:true,
|
||
}
|
||
};
|
||
that.manuChart.setOption(that.MyOption,true);
|
||
},
|
||
//折线图:
|
||
getLineChart(){
|
||
var that = this;
|
||
let month = ['第一季度','第二季度','第三季度','第四季度'];
|
||
let dic = [];
|
||
for (let i = 0;i<15;i++){
|
||
dic.push(that.showData[i]['name']);
|
||
}
|
||
|
||
that.MyOption={
|
||
tooltip: {
|
||
trigger: 'axis'
|
||
},
|
||
legend: {
|
||
data: dic//图例
|
||
},
|
||
grid: {
|
||
left: '3%',
|
||
right: '4%',
|
||
top:'20%',
|
||
containLabel: true
|
||
},
|
||
|
||
// toolbox: {
|
||
// feature: {
|
||
// saveAsImage: {}
|
||
// }
|
||
// },
|
||
xAxis: {//横坐标
|
||
name: "季度",
|
||
type: 'category',
|
||
boundaryGap: false,
|
||
data: month
|
||
},
|
||
yAxis: {
|
||
name: "数量",
|
||
type: 'value'
|
||
},
|
||
//三条折线就有三种series,可以更改type以改变是否为折线
|
||
series: that.showData
|
||
};
|
||
that.manuChart.setOption(that.MyOption,true);
|
||
}
|
||
},
|
||
}
|
||
</script>
|
||
|
||
<style scoped lang="scss">
|
||
::v-deep .el-page-header__left{
|
||
left:10px;
|
||
}
|
||
::v-deep .el-page-header__content{
|
||
flex:1;
|
||
}
|
||
|
||
.el-card{
|
||
border: none;
|
||
}
|
||
</style> |