态势感知平台-开源生态与贡献价值全景-开源项目热力图接口对接

This commit is contained in:
d266377
2026-01-29 10:56:13 +08:00
parent 2876d23502
commit 05cce185e6

View File

@@ -194,7 +194,8 @@
<span>大量开发者</span> <span>大量开发者</span>
</div> </div>
</div> </div>
<div id="heatmapChart" class="chart"></div> <div id="heatmapChart" class="chart" v-if="!loading"></div>
<div class="num-empty" v-else>加载中...</div>
</div> </div>
</div> </div>
<!-- 中国开源人才密度地图 --> <!-- 中国开源人才密度地图 -->
@@ -224,6 +225,7 @@ import VitalityWaveChart from './components/VitalityWaveChart.vue'
import StatsGlass from './components/StatsGlass.vue' import StatsGlass from './components/StatsGlass.vue'
import StarDevelopersChart from './components/StarDevelopersChart.vue' import StarDevelopersChart from './components/StarDevelopersChart.vue'
import { usePageResize } from '@/utils/hooks/usePageResize'; import { usePageResize } from '@/utils/hooks/usePageResize';
import { projectHeatMapPage2 } from '@/api/jyh/situation';
// 页面尺寸响应式 // 页面尺寸响应式
const { widthType } = usePageResize(); const { widthType } = usePageResize();
@@ -340,8 +342,6 @@ const excellentProjects = computed(() => {
})); }));
}); });
// 3. 图表数据定义 // 3. 图表数据定义
const chartData = ref({ const chartData = ref({
// 基础设施覆盖率(来自 InfrastructureCoverageRings.vue // 基础设施覆盖率(来自 InfrastructureCoverageRings.vue
@@ -390,10 +390,6 @@ const chartData = ref({
} }
}); });
// 空数据标识 // 空数据标识
const isEmpty = ref({ const isEmpty = ref({
languageTech: false languageTech: false
@@ -402,34 +398,93 @@ const isEmpty = ref({
// 语言图表Tab状态 // 语言图表Tab状态
const languageTab = ref<'mainstream' | 'emerging'>('mainstream'); const languageTab = ref<'mainstream' | 'emerging'>('mainstream');
// 定义热力图数据结构
interface HeatmapDataItem {
developer: number;
openrank: number;
org: string;
project: string;
repo: number;
}
// 开源项目热力图数据 [OpenRank, 活跃仓库数, 活跃开发者数, 项目名称, 所属组织] // 开源项目热力图数据 [OpenRank, 活跃仓库数, 活跃开发者数, 项目名称, 所属组织]
const heatmapData = ref([ const heatmapData = ref<any[]>([]);
[67538.71, 29433, 1409, 'OpenHarmony', 'Huawei'], const loading = ref(true);
[55000, 15000, 6000, 'Linux', 'Linux Foundation'],
[60000, 8000, 7000, 'Android', 'Google'], // 从API获取数据
[52000, 20000, 5500, 'Chromium', 'Google'], const fetchHeatmapData = async () => {
[38000, 16000, 4500, 'TensorFlow', 'Google'], try {
[42000, 13000, 5000, 'React', 'Meta'], loading.value = true;
[45417.67, 18000, 8629, 'Azure', 'Microsoft'], const response = await projectHeatMapPage2();
[35000, 22000, 5000, 'Kubernetes', 'CNCF'],
[21844.62, 12340, 57, 'LLM', '发芽工具'], if (response.code === 0 && response.data) {
[25241.13, 8000, 83, 'NixOS', '-'], // 转换API返回的数据格式为图表所需格式
[22961.09, 4500, 9377, 'openEuler', 'Huawei'], heatmapData.value = response.data.map((item: HeatmapDataItem) => [
[17795.41, 2792, 975, 'DataDog', 'DataDog'], item.openrank,
[25598.21, 2082, 282, '.Net', '操作系统'], item.repo,
[7405.46, 9639, 3, 'Expensify', 'Expensify'], item.developer,
[8862.2, 4625, 120, 'PaddlePaddle', 'Baidu'], item.project,
[12959.59, 2363, 1, 'Odoo', 'Odoo'], item.org
[12326.76, 881, 179, 'Rust', 'Rust Foundation'], ]);
[6778.7, 400, 479, 'CloudHarmony', '企业应用'] } else {
]); console.error('获取热力图数据失败:', response.msg || '未知错误');
// 设置默认数据
heatmapData.value = [
[67538.71, 29433, 1409, 'OpenHarmony', 'Huawei'],
[55000, 15000, 6000, 'Linux', 'Linux Foundation'],
[60000, 8000, 7000, 'Android', 'Google'],
[52000, 20000, 5500, 'Chromium', 'Google'],
[38000, 16000, 4500, 'TensorFlow', 'Google'],
[42000, 13000, 5000, 'React', 'Meta'],
[45417.67, 18000, 8629, 'Azure', 'Microsoft'],
[35000, 22000, 5000, 'Kubernetes', 'CNCF'],
[21844.62, 12340, 57, 'LLM', '发芽工具'],
[25241.13, 8000, 83, 'NixOS', '-'],
[22961.09, 4500, 9377, 'openEuler', 'Huawei'],
[17795.41, 2792, 975, 'DataDog', 'DataDog'],
[25598.21, 2082, 282, '.Net', '操作系统'],
[7405.46, 9639, 3, 'Expensify', 'Expensify'],
[8862.2, 4625, 120, 'PaddlePaddle', 'Baidu'],
[12959.59, 2363, 1, 'Odoo', 'Odoo'],
[12326.76, 881, 179, 'Rust', 'Rust Foundation'],
[6778.7, 400, 479, 'CloudHarmony', '企业应用']
];
}
} catch (error) {
console.error('获取热力图数据异常:', error);
// 设置默认数据
heatmapData.value = [
[67538.71, 29433, 1409, 'OpenHarmony', 'Huawei'],
[55000, 15000, 6000, 'Linux', 'Linux Foundation'],
[60000, 8000, 7000, 'Android', 'Google'],
[52000, 20000, 5500, 'Chromium', 'Google'],
[38000, 16000, 4500, 'TensorFlow', 'Google'],
[42000, 13000, 5000, 'React', 'Meta'],
[45417.67, 18000, 8629, 'Azure', 'Microsoft'],
[35000, 22000, 5000, 'Kubernetes', 'CNCF'],
[21844.62, 12340, 57, 'LLM', '发芽工具'],
[25241.13, 8000, 83, 'NixOS', '-'],
[22961.09, 4500, 9377, 'openEuler', 'Huawei'],
[17795.41, 2792, 975, 'DataDog', 'DataDog'],
[25598.21, 2082, 282, '.Net', '操作系统'],
[7405.46, 9639, 3, 'Expensify', 'Expensify'],
[8862.2, 4625, 120, 'PaddlePaddle', 'Baidu'],
[12959.59, 2363, 1, 'Odoo', 'Odoo'],
[12326.76, 881, 179, 'Rust', 'Rust Foundation'],
[6778.7, 400, 479, 'CloudHarmony', '企业应用']
];
} finally {
loading.value = false;
}
};
// 计算热力图统计数据 // 计算热力图统计数据
const topProject = computed(() => { const topProject = computed(() => {
const sorted = [...heatmapData.value].sort((a, b) => b[0] - a[0]); const sorted = [...heatmapData.value].sort((a, b) => b[0] - a[0]);
return { name: sorted[0][3], openrank: sorted[0][0] }; if (heatmapData.value.length > 0) {
return { name: sorted[0][3], openrank: sorted[0][0] };
}
return { name: '-', openrank: 0 };
}); });
const totalDevs = computed(() => { const totalDevs = computed(() => {
@@ -1193,6 +1248,12 @@ const initCharts = () => {
nextTick(() => initHeatmapChart()); nextTick(() => initHeatmapChart());
}; };
// 获取热力图数据并初始化图表
onMounted(async () => {
await fetchHeatmapData(); // 等待数据获取完成
nextTick(() => initHeatmapChart()); // 数据加载完成后初始化图表
});
// 页面resize时重绘图表 // 页面resize时重绘图表
watch(widthType, () => { watch(widthType, () => {
initCharts(); initCharts();
@@ -2355,6 +2416,22 @@ onMounted(() => {
rgba(236, 72, 153, 0.02) 100%); rgba(236, 72, 153, 0.02) 100%);
border: 1px solid rgba(59, 130, 246, 0.1); border: 1px solid rgba(59, 130, 246, 0.1);
position: relative; position: relative;
min-height: 400px;
}
.heatmap-container .num-empty {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
display: flex;
align-items: center;
justify-content: center;
font-size: 16px;
color: #999;
width: 100%;
height: 100%;
z-index: 1;
} }
.heatmap-legend { .heatmap-legend {