diff --git a/src/forge/Component/Radar.jsx b/src/forge/Component/Radar.jsx
new file mode 100644
index 000000000..0f085c255
--- /dev/null
+++ b/src/forge/Component/Radar.jsx
@@ -0,0 +1,100 @@
+import React, { useEffect, useState } from 'react';
+import echarts from 'echarts/lib/echarts'
+import 'echarts/lib/chart/radar';
+import { Popover } from 'antd';
+import axios from 'axios';
+
+
+const radarChartOption = {
+ color: ["#f8e367", "#99dfff"],
+ title: {
+ show: true
+ },
+ legend: {
+ show: false
+ },
+ tooltip: {
+ trigger: 'item',
+ },
+ radar: {
+ indicator: [
+ { name: '影响力', max: 100 },
+ { name: '活跃度', max: 100 },
+ { name: '开发度', max: 100 },
+ { name: '健康度', max: 100 },
+ { name: '流行度', max: 100 },
+ ],
+ center: ["50%", "55%"]
+ },
+ series: [{
+ name: '',
+ type: 'radar'
+ }]
+};
+
+function Radar({ fullName }) {
+ const [score, setScore] = useState(undefined);
+ useEffect(() => {
+ let url = `/${fullName}/score.json`;
+ axios.get(url).then(response => {
+ if ('updated_at' in response.data) {
+ setScore(response.data);
+ const properties = ['influence', 'community', 'vitality', 'health', 'trend'];
+ const scoreList = properties.map(property => Number((response.data[`${property}_norm_score`] * 100).toFixed(2)));
+ var radarContainer = document.getElementById("radar");
+ var myEcharts = echarts.init(radarContainer);
+ radarChartOption.series[0].data = [{
+ value: scoreList,
+ name: '项目得分'
+ }];
+ myEcharts.setOption(radarChartOption);
+ }
+ });
+ }, [])
+
+ return (
+
+
+
+
+
项目画像
+
+ {score &&
+
+
+ - 影响力 :
+ 与star、fork等社交指标相关
+ - 活跃度 :
+ 与issue、pr响应率相关
+ - 流行度 :
+ 与近期讨论度相关
+ - 开发度 :
+ 与近期代码提交数相关
+ - 健康度 :
+ 与贡献者人数相关
+
+ 更新于 {score['updated_at']}
+ } title="维度说明" trigger="hover" placement="bottomRight" overlayStyle={{ width: '270px' }}>
+
+
+ }
+
+
+
+ {score ? : 预计将于一周后更新数据
}
+
+
+ )
+}
+export default Radar;
\ No newline at end of file
diff --git a/src/forge/Main/CoderDepot.jsx b/src/forge/Main/CoderDepot.jsx
index b41a161eb..11884dbee 100644
--- a/src/forge/Main/CoderDepot.jsx
+++ b/src/forge/Main/CoderDepot.jsx
@@ -15,6 +15,7 @@ import ReadMe from './CoderDepotReadme';
import CoderRootFileDetail from './CoderRootFileDetail';
import './Index.scss';
import Releases from '../Component/Releases';
+import Radar from '../Component/Radar';
import Contributors from '../Component/Contributors';
import LanguagePower from '../Component/LanguagePower';
import DrawerPanel from '../Component/DrawerPanel';
@@ -646,6 +647,8 @@ function CoderDepot(props){
/>
}
+ {/* 项目画像 */}
+ {!projectDetail.private && }
{/* 贡献者 */}
{mirror_status ===0 && }
{/* 语言 */}
diff --git a/src/forge/Main/projecthome/Index.jsx b/src/forge/Main/projecthome/Index.jsx
index 1fc10cfa2..c2b0cab36 100644
--- a/src/forge/Main/projecthome/Index.jsx
+++ b/src/forge/Main/projecthome/Index.jsx
@@ -10,6 +10,8 @@ import more from '../img/index/more.png';
import axios from 'axios';
import { getImageUrl } from 'educoder';
import Nodata from '../../Nodata';
+import TopIcon from '../img/index/hotAuthor.png';
+import TopProjectSelect from './TopProjectSelect'
const { Search } = Input;
@@ -28,8 +30,10 @@ function Index() {
},[])
useEffect(()=>{
- setIsSpin(true);
- getProject();
+ if(cateID != -1){
+ setIsSpin(true);
+ getProject();
+ }
},[cateID, search])
function getCate() {
@@ -58,6 +62,10 @@ function Index() {
}).catch(error=>{})
}
+ const handleTopProjectData = (data) => {
+ setProjectsList(data);
+ };
+
function searchFun(value){
setSearch(value);
}
@@ -70,6 +78,7 @@ function Index() {
+ {cateID == -1 && }
{
diff --git a/src/forge/Main/projecthome/TopProjectSelect.jsx b/src/forge/Main/projecthome/TopProjectSelect.jsx
new file mode 100644
index 000000000..544a35ca2
--- /dev/null
+++ b/src/forge/Main/projecthome/TopProjectSelect.jsx
@@ -0,0 +1,76 @@
+import React, { useEffect, useState } from 'react';
+import axios from 'axios';
+import { Radio, Select } from 'antd';
+
+const { Option } = Select
+
+function TopProjectSelect(props) {
+ const [interval, setInterval] = useState(0);
+ const [periodList, setPeriodList] = useState([]);
+ const [selectedPeriod, setSelectedPeriod] = useState("暂无数据");
+ const onChangeInterval = (e) => {
+ setInterval(e.target.value);
+ getTopProjects(0, e.target.value);
+ };
+
+ const onChangePeriod = (value) => {
+ console.log(value);
+ setSelectedPeriod(value);
+ getTopProjects(value, interval);
+ };
+
+ function getTopProjects(period, time_interval) {
+ let url = `/projects/top.json`;
+ axios.get(url, {
+ params: {
+ period: period,
+ time_interval: time_interval
+ }
+ }).then(result => {
+ if (result && result.data) {
+ if (period == 0) {
+ var period_info = result.data.period_info
+ var optionsData = period_info.reverse().map((item) => ({
+ value: item.period,
+ label: `第${item.period}期(${item.updated_at})`,
+ }));
+ setPeriodList(optionsData)
+ console.log(optionsData)
+ if (optionsData) {
+ setSelectedPeriod(optionsData[0].value)
+ getTopProjects(optionsData[0].value, time_interval)
+ }
+
+ } else {
+ props.onData(result.data.projects);
+ }
+ }
+
+ }).catch(error => { })
+ }
+
+ useEffect(() => {
+ getTopProjects(0, 0)
+ }, [])
+
+ return (
+
+
+ 时间跨度:
+ 每周
+ 每月
+ 季度
+ 年度
+
+
+
+
+ )
+}
+export default TopProjectSelect;
\ No newline at end of file