态势感知平台-武汉市开源建设生态页面数据搜集与修改

This commit is contained in:
fmk1023
2026-01-12 09:20:10 +08:00
parent d63b9f32bd
commit 5f22b7d30e
2 changed files with 488 additions and 179 deletions

View File

@@ -6,17 +6,17 @@
</div>
<div class="stat-separator"></div>
<div class="stat-node">
<span class="stat-value">--</span>
<span class="stat-value">12</span>
<span class="stat-desc">武汉开源社区数量</span>
</div>
<div class="stat-separator"></div>
<div class="stat-node">
<span class="stat-value">--</span>
<span class="stat-value">70W+</span>
<span class="stat-desc">武汉开源开发者数量</span>
</div>
<div class="stat-separator"></div>
<div class="stat-node">
<span class="stat-value">200+</span>
<span class="stat-value">500+</span>
<span class="stat-desc">武汉开源项目数量</span>
</div>
</div>

View File

@@ -34,7 +34,7 @@
<div class="index-module__NV_5cW__chartsGrid">
<div class="index-module__NV_5cW__chartCard list-card">
<h3 class="chartCard__title">武汉开源项目列表</h3>
<h3 class="chartCard__title">武汉优质开源项目榜单</h3>
<div class="chartCard__container list-container"
ref="scrollContainer1"
@mouseenter="pauseScroll(1)"
@@ -57,7 +57,11 @@
<div class="source-footer">
<span class="source-label">数据来源</span>
<div class="source-content">
<svg class="source-icon" viewBox="0 0 98 96" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M48.854 0C21.839 0 0 22 0 49.217c0 21.756 13.993 40.172 33.405 46.69 2.427.49 3.316-1.059 3.316-2.362 0-1.141-.08-5.052-.08-9.127-13.59 2.934-16.42-5.867-16.42-5.867-2.184-5.704-5.42-7.17-5.42-7.17-4.448-3.015.324-3.015.324-3.015 4.934.326 7.523 5.052 7.523 5.052 4.367 7.496 11.404 5.378 14.235 4.074.404-3.178 1.699-5.378 3.074-6.6-10.839-1.141-22.243-5.378-22.243-24.283 0-5.378 1.94-9.778 5.014-13.2-.485-1.222-2.184-6.275.486-13.038 0 0 4.125-1.304 13.426 5.052a46.97 46.97 0 0 1 12.214-1.63c4.125 0 8.33.571 12.213 1.63 9.302-6.356 13.427-5.052 13.427-5.052 2.67 6.763.97 11.816.485 13.038 3.155 3.422 5.015 7.822 5.015 13.2 0 18.905-11.404 23.06-22.324 24.283 1.78 1.548 3.316 4.481 3.316 9.128 0 6.6-.08 11.897-.08 13.526 0 1.304.89 2.853 3.316 2.364 19.412-6.52 33.405-24.935 33.405-46.691C97.707 22 75.788 0 48.854 0z" fill="#333"/></svg>
<svg class="source-icon" viewBox="0 0 98 96" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd"
d="M48.854 0C21.839 0 0 22 0 49.217c0 21.756 13.993 40.172 33.405 46.69 2.427.49 3.316-1.059 3.316-2.362 0-1.141-.08-5.052-.08-9.127-13.59 2.934-16.42-5.867-16.42-5.867-2.184-5.704-5.42-7.17-5.42-7.17-4.448-3.015.324-3.015.324-3.015 4.934.326 7.523 5.052 7.523 5.052 4.367 7.496 11.404 5.378 14.235 4.074.404-3.178 1.699-5.378 3.074-6.6-10.839-1.141-22.243-5.378-22.243-24.283 0-5.378 1.94-9.778 5.014-13.2-.485-1.222-2.184-6.275.486-13.038 0 0 4.125-1.304 13.426 5.052a46.97 46.97 0 0 1 12.214-1.63c4.125 0 8.33.571 12.213 1.63 9.302-6.356 13.427-5.052 13.427-5.052 2.67 6.763.97 11.816.485 13.038 3.155 3.422 5.015 7.822 5.015 13.2 0 18.905-11.404 23.06-22.324 24.283 1.78 1.548 3.316 4.481 3.316 9.128 0 6.6-.08 11.897-.08 13.526 0 1.304.89 2.853 3.316 2.364 19.412-6.52 33.405-24.935 33.405-46.691C97.707 22 75.788 0 48.854 0z"
fill="#333" />
</svg>
<span class="source-name">GitHub</span>
</div>
</div>
@@ -72,7 +76,11 @@
<div class="source-footer">
<span class="source-label">数据来源</span>
<div class="source-content">
<svg class="source-icon" viewBox="0 0 98 96" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M48.854 0C21.839 0 0 22 0 49.217c0 21.756 13.993 40.172 33.405 46.69 2.427.49 3.316-1.059 3.316-2.362 0-1.141-.08-5.052-.08-9.127-13.59 2.934-16.42-5.867-16.42-5.867-2.184-5.704-5.42-7.17-5.42-7.17-4.448-3.015.324-3.015.324-3.015 4.934.326 7.523 5.052 7.523 5.052 4.367 7.496 11.404 5.378 14.235 4.074.404-3.178 1.699-5.378 3.074-6.6-10.839-1.141-22.243-5.378-22.243-24.283 0-5.378 1.94-9.778 5.014-13.2-.485-1.222-2.184-6.275.486-13.038 0 0 4.125-1.304 13.426 5.052a46.97 46.97 0 0 1 12.214-1.63c4.125 0 8.33.571 12.213 1.63 9.302-6.356 13.427-5.052 13.427-5.052 2.67 6.763.97 11.816.485 13.038 3.155 3.422 5.015 7.822 5.015 13.2 0 18.905-11.404 23.06-22.324 24.283 1.78 1.548 3.316 4.481 3.316 9.128 0 6.6-.08 11.897-.08 13.526 0 1.304.89 2.853 3.316 2.364 19.412-6.52 33.405-24.935 33.405-46.691C97.707 22 75.788 0 48.854 0z" fill="#333"/></svg>
<svg class="source-icon" viewBox="0 0 98 96" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd"
d="M48.854 0C21.839 0 0 22 0 49.217c0 21.756 13.993 40.172 33.405 46.69 2.427.49 3.316-1.059 3.316-2.362 0-1.141-.08-5.052-.08-9.127-13.59 2.934-16.42-5.867-16.42-5.867-2.184-5.704-5.42-7.17-5.42-7.17-4.448-3.015.324-3.015.324-3.015 4.934.326 7.523 5.052 7.523 5.052 4.367 7.496 11.404 5.378 14.235 4.074.404-3.178 1.699-5.378 3.074-6.6-10.839-1.141-22.243-5.378-22.243-24.283 0-5.378 1.94-9.778 5.014-13.2-.485-1.222-2.184-6.275.486-13.038 0 0 4.125-1.304 13.426 5.052a46.97 46.97 0 0 1 12.214-1.63c4.125 0 8.33.571 12.213 1.63 9.302-6.356 13.427-5.052 13.427-5.052 2.67 6.763.97 11.816.485 13.038 3.155 3.422 5.015 7.822 5.015 13.2 0 18.905-11.404 23.06-22.324 24.283 1.78 1.548 3.316 4.481 3.316 9.128 0 6.6-.08 11.897-.08 13.526 0 1.304.89 2.853 3.316 2.364 19.412-6.52 33.405-24.935 33.405-46.691C97.707 22 75.788 0 48.854 0z"
fill="#333" />
</svg>
<span class="source-name">GitHub</span>
</div>
</div>
@@ -147,7 +155,11 @@
</div>
<div class="dev-medal">
<svg v-if="index < 3" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="#f59e0b" stroke="none"><path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/></svg>
<svg v-if="index < 3" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24"
fill="#f59e0b" stroke="none">
<path
d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z" />
</svg>
<span v-else class="dev-score">活跃</span>
</div>
</div>
@@ -274,7 +286,14 @@
<div class="index-module__NV_5cW__actionBackground"></div>
<div class="index-module__NV_5cW__actionContent">
<div class="index-module__NV_5cW__actionIcon">
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-rocket"><path d="M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 0 0-2.91-.09z"/><path d="m12 15-3-3a22 22 0 0 1 2-3.95A12.88 12.88 0 0 1 22 2c0 2.72-.78 7.5-6 11a22.35 22.35 0 0 1-4 2z"/><path d="M9 12H4s.55-3.03 2-4c1.62-1.1 4-1 4-1s.25 2.25 1 4c.45 1.04 1 2 2 3h-5z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
class="lucide lucide-rocket">
<path d="M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 0 0-2.91-.09z" />
<path
d="m12 15-3-3a22 22 0 0 1 2-3.95A12.88 12.88 0 0 1 22 2c0 2.72-.78 7.5-6 11a22.35 22.35 0 0 1-4 2z" />
<path d="M9 12H4s.55-3.03 2-4c1.62-1.1 4-1 4-1s.25 2.25 1 4c.45 1.04 1 2 2 3h-5z" />
</svg>
</div>
<h3 class="index-module__NV_5cW__actionTitle">加入武汉开源社区</h3>
<p class="index-module__NV_5cW__actionDescription">与武汉本地开发者企业高校携手共建开源生态</p>
@@ -291,95 +310,131 @@
import { onMounted, ref, nextTick, watch, onUnmounted, computed } from 'vue';
import * as echarts from 'echarts';
import { usePageResize } from '@/utils/hooks/usePageResize';
import StatsBar from './StatsBar.vue'
import StatsBar from './StatsBar.vue';
const { widthType } = usePageResize();
// ================= 数据定义 =================
const githubProjects = ref([
{ name: 'DWSurvey', desc: '基于Vue+SpringBoot的问卷系统', stars: '3.2k' },
{ name: 'Eova', desc: '快速开发平台', stars: '2.8k' },
{ name: 'ClickVisual', desc: '日志分析平台', stars: '2.5k' },
{ name: 'Meta2d.js', desc: '2D可视化引擎', stars: '2.1k' },
{ name: 'Deepin Wine', desc: '在Linux运行Windows应用', stars: '6.5k' },
{ name: 'GoFrame', desc: 'Go语言企业级开发框架', stars: '11k' },
{ name: 'MindSpore', desc: '全场景AI计算框架(武汉所)', stars: '18k' },
{ name: 'IoTDB', desc: '物联网时序数据库', stars: '4.2k' }
{
name: 'bootstrap',
desc: 'The most popular HTML, CSS, and JavaScript framework for developing responsive, mobile first projects on the web.',
stars: '174000'
},
{
name: 'JavaGuide',
desc: 'Java 学习&面试指南Go、Python 后端面试通用,计算机基础面试总结)。准备后端技术面试,首选 JavaGuide',
stars: '153000'
},
{
name: 'cpython',
desc: 'The Python programming language',
stars: '71000'
},
{
name: 'core',
desc: '🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.',
stars: '52700'
},
{
name: 'bevy',
desc: 'A refreshingly simple data-driven game engine built in Rust',
stars: '43900'
},
{
name: 'linux-insides',
desc: 'A book-in-progress about the Linux kernel and its insides.',
stars: '31700'
},
{
name: 'podman',
desc: 'Podman: A tool for managing OCI containers and pods.',
stars: '30300'
},
{
name: 'fastai',
desc: 'The fastai deep learning library',
stars: '27800'
},
{
name: 'OI-wiki',
desc: '🌟 Wiki of OI / ICPC for everyone. (某大型游戏线上攻略,内含炫酷算术魔法)',
stars: '25200'
},
{
name: 'bilibili-API-collect',
desc: '哔哩哔哩-API收集整理【不断更新中....】',
stars: '20100'
}
]);
const activeTab = ref(0);
const excellentProjects = ref([
{ "name": "调问DWSurvey", "desc": "开源问卷表单系统", "org": "极推科技" },
{ "name": "Eova", "desc": "低代码开发平台", "org": "武汉简码" },
{ "name": "ClickVisual", "desc": "可视化日志分析告警平台", "org": "武汉初心" },
{ "name": "Meta2d.js", "desc": "2D图元可视化引擎", "org": "乐吾乐科技" },
{ "name": "Juno", "desc": "分布式微服务管理系统", "org": "武汉斗鱼" },
{ "name": "Opentalent", "desc": "开源人才评价系统", "org": "湖北大学" },
{ "name": "Fountain", "desc": "仓颉语言版 Spring 框架替代", "org": "江汉大学" },
{ "name": "deepin", "desc": "深度桌面操作系统", "org": "深之度" },
{ "name": "RustSBI", "desc": "RISC-V 安全引导程序", "org": "华中科技大学" },
{ "name": "NextDenovo", "desc": "长读长序列组装工具", "org": "武汉希望组" }
{ 'name': '调问DWSurvey', 'desc': '开源问卷表单系统', 'org': '极推科技' },
{ 'name': 'Eova', 'desc': '低代码开发平台', 'org': '武汉简码' },
{ 'name': 'ClickVisual', 'desc': '可视化日志分析告警平台', 'org': '武汉初心' },
{ 'name': 'Meta2d.js', 'desc': '2D图元可视化引擎', 'org': '乐吾乐科技' },
{ 'name': 'Juno', 'desc': '分布式微服务管理系统', 'org': '武汉斗鱼' },
{ 'name': 'Opentalent', 'desc': '开源人才评价系统', 'org': '湖北大学' },
{ 'name': 'Fountain', 'desc': '仓颉语言版 Spring 框架替代', 'org': '江汉大学' },
{ 'name': 'deepin', 'desc': '深度桌面操作系统', 'org': '深之度' },
{ 'name': 'RustSBI', 'desc': 'RISC-V 安全引导程序', 'org': '华中科技大学' },
{ 'name': 'NextDenovo', 'desc': '长读长序列组装工具', 'org': '武汉希望组' }
]);
const chinaExcellentProjects = ref([
{
"name": "Deepin 深度操作系统",
"desc": "国内领先的国产 Linux 发行版,旨在为全球用户提供美观易用、安全可靠的操作系统体验,是国产软件生态的核心。",
"org": "武汉深之度"
'name': 'Deepin 深度操作系统',
'desc': '国内领先的国产 Linux 发行版,旨在为全球用户提供美观易用、安全可靠的操作系统体验,是国产软件生态的核心。',
'org': '武汉深之度'
},
{
"name": "Jupiter 微服务治理框架",
"desc": "由斗鱼研发并开源的面向治理的微服务框架,支持多数据源、多注册中心,适用于高并发场景。",
"org": "武汉斗鱼"
'name': 'Jupiter 微服务治理框架',
'desc': '由斗鱼研发并开源的面向治理的微服务框架,支持多数据源、多注册中心,适用于高并发场景。',
'org': '武汉斗鱼'
},
{
"name": "RustSBI 安全引导程序",
"desc": "基于 Rust 语言开发的 RISC-V 指令集体系结构安全引导程序,提供更高内存安全性。",
"org": "华中科技大学"
'name': 'RustSBI 安全引导程序',
'desc': '基于 Rust 语言开发的 RISC-V 指令集体系结构安全引导程序,提供更高内存安全性。',
'org': '华中科技大学'
},
{
"name": "芯片开源 EDA 研发",
"desc": "致力于国产电子设计自动化工具开源化,解决芯片设计环节中的关键技术难题。",
"org": "华中科技大学"
'name': '芯片开源 EDA 研发',
'desc': '致力于国产电子设计自动化工具开源化,解决芯片设计环节中的关键技术难题。',
'org': '华中科技大学'
},
{
"name": "LuoJiaSET 框架与 LuoJiaSET 样本库",
"desc": "专注于智能遥感影像解译,提供海量遥感样本数据集和深度学习框架。",
"org": "武汉大学"
'name': 'LuoJiaSET 框架与 LuoJiaSET 样本库',
'desc': '专注于智能遥感影像解译,提供海量遥感样本数据集和深度学习框架。',
'org': '武汉大学'
},
{
"name": "鲲鹏安全库 (Kunpengsecl)",
"desc": "基于鲲鹏处理器的机密计算和受信任执行环境安全开发库,支撑云计算与隐私计算。",
"org": "武汉大学"
'name': '鲲鹏安全库 (Kunpengsecl)',
'desc': '基于鲲鹏处理器的机密计算和受信任执行环境安全开发库,支撑云计算与隐私计算。',
'org': '武汉大学'
},
{
"name": "柚坛工具箱 (Uotan Toolbox)",
"desc": "针对 Android 发烧友开发的图形化综合工具箱,集成刷机、系统优化等多种功能。",
"org": "武昌理工学院"
'name': '柚坛工具箱 (Uotan Toolbox)',
'desc': '针对 Android 发烧友开发的图形化综合工具箱,集成刷机、系统优化等多种功能。',
'org': '武昌理工学院'
},
{
"name": "凹语言 (Wa Language)",
"desc": "国内首个针对 WebAssembly 设计的通用编程语言,兼具 Web 灵活性与原生运行速度。",
"org": "武汉凹语言"
'name': '凹语言 (Wa Language)',
'desc': '国内首个针对 WebAssembly 设计的通用编程语言,兼具 Web 灵活性与原生运行速度。',
'org': '武汉凹语言'
},
{
"name": "OpenHIS 开源医疗系统",
"desc": "开源的医院信息系统,旨在通过标准化、模块化方式赋能基层医疗机构数字化升级。",
"org": "武汉新致新源"
'name': 'OpenHIS 开源医疗系统',
'desc': '开源的医院信息系统,旨在通过标准化、模块化方式赋能基层医疗机构数字化升级。',
'org': '武汉新致新源'
},
{
"name": "NextDenovo",
"desc": "高效且精确的长读长序列纠错和组装工具,主要用于基因组测序领域。",
"org": "武汉希望组生物科技有限公司"
'name': 'NextDenovo',
'desc': '高效且精确的长读长序列纠错和组装工具,主要用于基因组测序领域。',
'org': '武汉希望组生物科技有限公司'
}
]);
// 城市社区数量
const cityCommunityData = {
xAxis: ['北京', '上海', '深圳', '杭州', '武汉', '成都'],
data: [42, 38, 35, 28, 22, 18]
};
// 武汉知名社区数据
const wuhanCommunities = ref([
{ name: 'Deepin (深度)', type: '操作系统', slogan: '最大的国产桌面操作系统开源社区' },
@@ -397,11 +452,11 @@ let communityTimer: NodeJS.Timeout | null = null;
const switchCommunityTab = () => {
if (activeCommunityTab.value === 1) {
activeCommunityTab.value = 0
activeCommunityTab.value = 0;
nextTick(() => initCommunityRankChart());
pauseCommunityScroll();
} else {
activeCommunityTab.value = 1
activeCommunityTab.value = 1;
nextTick(() => startCommunityScroll());
}
};
@@ -429,9 +484,9 @@ const currentProjectList = computed(() => {
const switchTab = (index: number) => {
if (activeTab.value === 1) {
activeTab.value = 0
activeTab.value = 0;
} else {
activeTab.value = 1
activeTab.value = 1;
}
nextTick(() => {
if (scrollContainer2.value) scrollContainer2.value.scrollTop = 0;
@@ -442,37 +497,63 @@ const switchTab = (index: number) => {
const chartData = ref({
cityProject: {
xAxis: ['北京', '上海', '深圳', '杭州', '武汉', '成都', '广州'],
data: [12500, 11200, 9800, 8500, 6200, 5800, 5400]
xAxis: ['北京', '上海', '深圳', '杭州', '广州', '成都', '武汉', '南京', '西安', '重庆'],
data: [757259, 678614, 343417, 315406, 177003, 168300, 120827, 111593, 58678, 56564]
},
talent: {
xAxis: ['北京', '深圳', '上海', '杭州', '武汉', '南京'],
data: [45000, 38000, 36000, 28000, 22000, 15000]
xAxis: ['北京', '上海', '广州', '深圳', '成都', '杭州', '武汉', '南京', '郑州', '长沙'],
data: [2115924, 1591988, 1555240, 1163580, 894108, 830306, 791335, 733581, 553397, 487971]
},
communityRank: {
xAxis: ['Deepin', 'OpenHarmony', 'MindSpore', 'IoTDB', 'GoFrame'],
data: [95, 92, 88, 76, 72]
},
club: {
xAxis: ['北京', '武汉', '上海', '西安', '南京'],
data: [28, 24, 20, 18, 15]
xAxis: ['成都', '北京', '上海', '武汉','重庆', '深圳', '苏州', '杭州', '合肥', '青岛' ],
data: [10, 7, 5, 4, 3, 2, 2, 2, 2, 2]
},
policy: {
xAxis: ['北京', '上海', '广东', '江苏', '湖北', '浙江'],
data: [12, 10, 9, 8, 7, 6]
xAxis: [
'江苏', '北京', '浙江', '广东', '上海', '湖北', '天津',
'陕西', '河南', '云南'
// '黑龙江','安徽省', '重庆市', '宁夏回族自治区', '山东省', '湖南省'
],
data: [11, 7, 3, 3, 3, 2, 2, 2, 2, 2
// 2, 2, 1, 1, 1, 1
]
},
campus: {
xAxis: ['武汉', '北京', '成都', '深圳', '西安'],
data: [35, 32, 25, 20, 18]
xAxis: [
'南京', '武汉', '北京', '长沙', '成都', '上海', '天津', '深圳',
'济南', '广州'
// '呼和浩特', '长春', '吉林', '沈阳', '苏州', '青岛',
// '惠州', '合肥', '佛山', '南昌', '南充', '徐州', '西安', '郑州',
// '贵阳', '线上', '哈尔滨', '宜宾', '杭州', '太原', '大连', '银川',
// '西宁', '中山', '乐山', '内江', '泸州', '常德', '昌吉', '桂林',
// '福州', '常州', '库尔勒', '兰州', '温州', '鄂州', '乌鲁木齐', '日照',
// '无锡', '重庆', '东莞', '赣州'
],
data: [
20, 16, 16, 16, 11, 10, 8, 8, 7, 6
// 5, 4, 3, 3, 3, 3,
// 3, 3, 3, 3, 3, 2, 2, 2,
// 2, 2, 2, 2, 2, 2, 2, 1,
// 1, 1, 1, 1, 1, 1, 1, 1,
// 1, 1, 1, 1, 1, 1, 1, 1,
// 1, 1, 1, 1
]
},
mirrors: {
xAxis: ['清华TUNA', '中科大', '阿里', '华为', '华科HUST', '网易', '腾讯'],
data: [520, 480, 450, 420, 380, 300, 280]
xAxis: [
'上海', '北京', '西安', '重庆', '济南', '南京', '武汉', '合肥', '香港',
'长春', '成都', '深圳', '兰州', '哈尔滨', '南阳', '杭州'
],
data: [4, 4, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
}
});
// 数据定义
const developerNames = ['白纯骢', '陆红旭', '冬亮', '张继德', '蒋周奇', '张天雄', '阮文俊', '李奇', '陈鹏轩', '杨帆'];
const developerNames = ['白纯骢', '陆红旭', '冬亮', '张继德', '蒋周奇', '张天雄', '阮文俊', '李奇', '陈鹏轩', '杨帆'];
const developerScrollRef = ref<HTMLElement | null>(null);
let developerTimer: NodeJS.Timeout | null = null;
@@ -529,7 +610,9 @@ const autoScroll = (key: number) => {
}, 40);
};
const pauseScroll = (key: number) => { if (scrollTimers[key]) clearInterval(scrollTimers[key]!); };
const pauseScroll = (key: number) => {
if (scrollTimers[key]) clearInterval(scrollTimers[key]!);
};
const resumeScroll = (key: number) => autoScroll(key);
// ================= 图表初始化=================
@@ -549,7 +632,13 @@ const initCityProjectChart = () => {
yAxis: { type: 'value', name: '单位:个', splitLine: { lineStyle: { type: 'dashed', color: '#eee' } } },
series: [{
type: 'bar', data: chartData.value.cityProject.data, barWidth: '50%',
itemStyle: { borderRadius: [4, 4, 0, 0], color: new echarts.graphic.LinearGradient(0,0,0,1,[{offset:0,color:'#4F46E5'},{offset:1,color:'#818CF8'}]) }
itemStyle: {
borderRadius: [4, 4, 0, 0],
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{ offset: 0, color: '#4F46E5' }, {
offset: 1,
color: '#818CF8'
}])
}
}]
});
};
@@ -580,10 +669,21 @@ const initDeveloperChart = () => {
tooltip: { trigger: 'axis', valueFormatter: (value: any) => value + ' 贡献分' },
grid: { left: '3%', right: '5%', bottom: '15px', top: '5%', containLabel: true },
xAxis: { type: 'value', show: false }, // 隐藏x轴
yAxis: { type: 'category', data: chartData.value.developer.yAxis.reverse(), axisLine: {show: false}, axisTick: {show: false}, axisLabel: { color: '#333', fontWeight: 500 } },
yAxis: {
type: 'category',
data: chartData.value.developer.yAxis.reverse(),
axisLine: { show: false },
axisTick: { show: false },
axisLabel: { color: '#333', fontWeight: 500 }
},
series: [{
type: 'bar', data: chartData.value.developer.data.reverse(), barWidth: 16,
itemStyle: { color: new echarts.graphic.LinearGradient(1,0,0,0,[{offset:0,color:'#7C3AED'},{offset:1,color:'#C4B5FD'}]), borderRadius: [0, 8, 8, 0] },
itemStyle: {
color: new echarts.graphic.LinearGradient(1, 0, 0, 0, [{ offset: 0, color: '#7C3AED' }, {
offset: 1,
color: '#C4B5FD'
}]), borderRadius: [0, 8, 8, 0]
},
label: { show: false } // **修改点:隐藏具体分数**
}]
});
@@ -596,11 +696,15 @@ const initCommunityRankChart = () => {
myChart.setOption({
tooltip: { trigger: 'axis', valueFormatter: (val: any) => val + ' 个' },
grid: { left: '3%', right: '4%', bottom: '15px', top: '22%', containLabel: true },
xAxis: { type: 'category', data: ['北京', '上海', '深圳', '杭州', '武汉', '成都'], axisLabel: { color: '#666' } },
xAxis: {
type: 'category',
data: ['北京', '深圳', '上海', '杭州', '广州', '成都', '南京', '武汉'],
axisLabel: { color: '#666' }
},
yAxis: { type: 'value', name: '单位:个', nameTextStyle: { color: '#999' } },
series: [{
type: 'bar',
data: [42, 38, 35, 28, 22, 18],
data: [69, 35, 31, 25, 18, 15, 12, 12],
barWidth: '40%',
itemStyle: { borderRadius: [4, 4, 0, 0], color: '#3b82f6' }
}]
@@ -635,7 +739,7 @@ const initPolicyChart = () => {
myChart.setOption({
tooltip: { trigger: 'axis', valueFormatter: (value: any) => value + ' 条' },
grid: commonGrid,
xAxis: { type: 'category', data: chartData.value.policy.xAxis, axisLabel: { color: '#666' } },
xAxis: { type: 'category', data: chartData.value.policy.xAxis, axisLabel: { color: '#666', interval: 0 } },
yAxis: { type: 'value', name: '单位:条', splitLine: { lineStyle: { type: 'dashed', color: '#eee' } } },
series: [{
type: 'bar', data: chartData.value.policy.data, barWidth: '45%',
@@ -697,30 +801,49 @@ const initMirrorChart = () => {
const initCharts = () => {
nextTick(() => {
initCityProjectChart(); initTalentChart(); initDeveloperChart();
initCommunityRankChart(); initClubChart(); initPolicyChart();
initCampusChart(); initMirrorChart();
initCityProjectChart();
initTalentChart();
initDeveloperChart();
initCommunityRankChart();
initClubChart();
initPolicyChart();
initCampusChart();
initMirrorChart();
});
};
const init = () => {
nextTick(() => {
initCityProjectChart(); initTalentChart(); initDeveloperChart();
initCommunityRankChart(); initClubChart(); initPolicyChart();
initCampusChart(); initMirrorChart();
initCityProjectChart();
initTalentChart();
initDeveloperChart();
initCommunityRankChart();
initClubChart();
initPolicyChart();
initCampusChart();
initMirrorChart();
autoScroll(1); autoScroll(2);startCommunityScroll();startDeveloperScroll();
autoScroll(1);
autoScroll(2);
startCommunityScroll();
startDeveloperScroll();
});
}
};
const unInit = () => {
Object.values(scrollTimers).forEach(t => t && clearInterval(t));
pauseDeveloperScroll();
pauseCommunityScroll();
}
};
watch(widthType, () => { init() });
onMounted(() => { init() });
onUnmounted(() => { unInit() });
watch(widthType, () => {
init();
});
onMounted(() => {
init();
});
onUnmounted(() => {
unInit();
});
</script>
<style lang="scss" scoped>
@@ -770,20 +893,32 @@ onUnmounted(() => { unInit() });
}
.title-decoration {
width: 60px; height: 2px;
width: 60px;
height: 2px;
background: linear-gradient(90deg, transparent, #60a5fa);
}
.title-decoration.right {
background: linear-gradient(90deg, #60a5fa, transparent);
}
/* 标题栏图表 Icon */
.index-module__NV_5cW__sectionHeader {
display: flex; justify-content: flex-start; margin-bottom: 1.5rem;
max-width: 1400px; margin: 0 auto 1.5rem auto; padding: 0 0.5rem;
display: flex;
justify-content: flex-start;
margin-bottom: 1.5rem;
max-width: 1400px;
margin: 0 auto 1.5rem auto;
padding: 0 0.5rem;
}
.index-module__NV_5cW__sectionTitle {
display: flex; align-items: center; gap: 0.8rem; font-size: 1.4rem; font-weight: 600; color: #fff;
display: flex;
align-items: center;
gap: 0.8rem;
font-size: 1.4rem;
font-weight: 600;
color: #fff;
}
/* 网格系统 */
@@ -814,7 +949,9 @@ onUnmounted(() => { unInit() });
box-shadow: 0 20px 40px -10px rgba(0, 0, 0, 0.4);
}
.chartCard__wide { grid-column: 1 / -1; }
.chartCard__wide {
grid-column: 1 / -1;
}
.chartCard__title {
font-size: 1.05rem;
@@ -827,58 +964,144 @@ onUnmounted(() => { unInit() });
}
.chartCard__container {
width: 100%; height: 300px; position: relative;
width: 100%;
height: 300px;
position: relative;
}
/* 列表样式优化 */
.list-container {
height: 300px; overflow-y: hidden;
height: 300px;
overflow-y: hidden;
padding: 0 4px;
}
.project-list { display: flex; flex-direction: column; gap: 0.6rem; padding-bottom: 1rem; }
.project-list {
display: flex;
flex-direction: column;
gap: 0.6rem;
padding-bottom: 1rem;
}
.project-item {
display: flex; align-items: center; gap: 0.75rem; padding: 0.75rem;
background: #f8fafc; border-radius: 8px; border: 1px solid #e2e8f0;
display: flex;
align-items: center;
gap: 0.75rem;
padding: 0.75rem;
background: #f8fafc;
border-radius: 8px;
border: 1px solid #e2e8f0;
transition: all 0.2s;
}
.project-item:hover {
background: #fff; border-color: #3b82f6; box-shadow: 0 4px 12px rgba(59, 130, 246, 0.1);
background: #fff;
border-color: #3b82f6;
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.1);
}
.project-rank-wrapper {
width: 24px; display: flex; justify-content: center;
width: 24px;
display: flex;
justify-content: center;
}
.project-rank {
width: 20px; height: 20px; border-radius: 6px;
background: #cbd5e1; color: #fff;
display: flex; align-items: center; justify-content: center;
font-size: 11px; font-weight: 700;
}
/* 前三名高亮 */
.project-item:nth-child(1) .project-rank { background: linear-gradient(135deg, #fbbf24, #d97706); }
.project-item:nth-child(2) .project-rank { background: linear-gradient(135deg, #94a3b8, #64748b); }
.project-item:nth-child(3) .project-rank { background: linear-gradient(135deg, #dba789, #b07d62); }
.project-rank.rank-new { background: linear-gradient(135deg, #f43f5e, #e11d48) !important; }
.project-info { flex: 1; display: flex; flex-direction: column; gap: 2px; overflow: hidden; }
.project-name { font-size: 13px; font-weight: 700; color: #333; }
.project-desc { font-size: 11px; color: #64748b; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.project-stars { font-size: 11px; font-weight: 600; color: #f59e0b; background: #fffbeb; padding: 2px 6px; border-radius: 4px; }
.project-org-tag { font-size: 11px; color: #3b82f6; background: #eff6ff; padding: 2px 6px; border-radius: 4px; white-space: nowrap; }
.project-rank {
width: 20px;
height: 20px;
border-radius: 6px;
background: #cbd5e1;
color: #fff;
display: flex;
align-items: center;
justify-content: center;
font-size: 11px;
font-weight: 700;
}
/* 前三名高亮 */
.project-item:nth-child(1) .project-rank {
background: linear-gradient(135deg, #fbbf24, #d97706);
}
.project-item:nth-child(2) .project-rank {
background: linear-gradient(135deg, #94a3b8, #64748b);
}
.project-item:nth-child(3) .project-rank {
background: linear-gradient(135deg, #dba789, #b07d62);
}
.project-rank.rank-new {
background: linear-gradient(135deg, #f43f5e, #e11d48) !important;
}
.project-info {
flex: 1;
display: flex;
flex-direction: column;
gap: 2px;
overflow: hidden;
}
.project-name {
font-size: 13px;
font-weight: 700;
color: #333;
}
.project-desc {
font-size: 11px;
color: #64748b;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.project-stars {
font-size: 11px;
font-weight: 600;
color: #f59e0b;
background: #fffbeb;
padding: 2px 6px;
border-radius: 4px;
}
.project-org-tag {
font-size: 11px;
color: #3b82f6;
background: #eff6ff;
padding: 2px 6px;
border-radius: 4px;
white-space: nowrap;
}
/* Tabs 美化 */
.tabs-header {
display: flex; justify-content: center; gap: 4px;
background: #f1f5f9; padding: 4px; border-radius: 8px;
margin: 0 auto 0.8rem auto; width: fit-content;
display: flex;
justify-content: center;
gap: 4px;
background: #f1f5f9;
padding: 4px;
border-radius: 8px;
margin: 0 auto 0.8rem auto;
width: fit-content;
}
.tab-pill {
font-size: 12px; padding: 4px 12px; cursor: pointer; border-radius: 6px;
color: #64748b; font-weight: 500; transition: all 0.2s;
font-size: 12px;
padding: 4px 12px;
cursor: pointer;
border-radius: 6px;
color: #64748b;
font-weight: 500;
transition: all 0.2s;
}
.tab-pill.active {
background: #fff; color: #3b82f6; font-weight: 600;
background: #fff;
color: #3b82f6;
font-weight: 600;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
}
@@ -904,46 +1127,116 @@ onUnmounted(() => { unInit() });
gap: 6px;
}
.source-icon { width: 14px; height: 14px; opacity: 0.8; }
.source-logo-circle { width: 18px; height: 18px; border-radius: 50%; box-shadow: 0 1px 2px rgba(0,0,0,0.1); }
.source-logo-text { font-size: 9px; font-weight: bold; background: #333; color: #fff; padding: 0 3px; border-radius: 2px; }
.source-name { color: #475569; font-weight: 500; } /* 深一点的灰色文字 */
.source-icon {
width: 14px;
height: 14px;
opacity: 0.8;
}
.source-logo-circle {
width: 18px;
height: 18px;
border-radius: 50%;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
}
.source-logo-text {
font-size: 9px;
font-weight: bold;
background: #333;
color: #fff;
padding: 0 3px;
border-radius: 2px;
}
.source-name {
color: #475569;
font-weight: 500;
}
/* 深一点的灰色文字 */
/* 行动区域 */
.index-module__NV_5cW__actionSection {
max-width: 1400px; margin: 2rem auto 0;
text-align: center; border-radius: 24px; padding: 3rem;
max-width: 1400px;
margin: 2rem auto 0;
text-align: center;
border-radius: 24px;
padding: 3rem;
background: rgba(30, 41, 59, 0.6); /* 深色背景 */
border: 1px solid rgba(255, 255, 255, 0.1);
backdrop-filter: blur(12px);
position: relative; overflow: hidden;
position: relative;
overflow: hidden;
}
.index-module__NV_5cW__actionBackground {
position: absolute; inset: 0;
position: absolute;
inset: 0;
background: radial-gradient(circle at top right, rgba(59, 130, 246, 0.15), transparent 40%);
z-index: 1;
}
.index-module__NV_5cW__actionContent { position: relative; z-index: 2; }
.index-module__NV_5cW__actionIcon {
color: #60a5fa; background: rgba(59, 130, 246, 0.1);
border-radius: 50%; width: 3.5rem; height: 3.5rem; margin: 0 auto 1.5rem;
display: flex; justify-content: center; align-items: center;
.index-module__NV_5cW__actionContent {
position: relative;
z-index: 2;
}
.index-module__NV_5cW__actionTitle { font-size: 1.8rem; font-weight: 700; color: #fff; margin-bottom: 0.5rem; }
.index-module__NV_5cW__actionDescription { color: #cbd5e1; margin-bottom: 1.5rem; }
.index-module__NV_5cW__actionIcon {
color: #60a5fa;
background: rgba(59, 130, 246, 0.1);
border-radius: 50%;
width: 3.5rem;
height: 3.5rem;
margin: 0 auto 1.5rem;
display: flex;
justify-content: center;
align-items: center;
}
.index-module__NV_5cW__actionTitle {
font-size: 1.8rem;
font-weight: 700;
color: #fff;
margin-bottom: 0.5rem;
}
.index-module__NV_5cW__actionDescription {
color: #cbd5e1;
margin-bottom: 1.5rem;
}
.action-btn {
background: linear-gradient(135deg, #3b82f6, #6366f1);
border: none; color: white; padding: 0.8rem 2.5rem; border-radius: 50px;
font-weight: 600; cursor: pointer; font-size: 1rem;
border: none;
color: white;
padding: 0.8rem 2.5rem;
border-radius: 50px;
font-weight: 600;
cursor: pointer;
font-size: 1rem;
box-shadow: 0 4px 15px rgba(59, 130, 246, 0.4);
transition: all 0.3s;
}
.action-btn:hover { transform: translateY(-2px); box-shadow: 0 6px 20px rgba(59, 130, 246, 0.5); }
.action-btn:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(59, 130, 246, 0.5);
}
/* 工具类 */
.chart { width: 100%; height: 100%; }
.num-empty { height: 2px; width: 50%; background: #ddd; margin: 50% auto; }
.chart {
width: 100%;
height: 100%;
}
.num-empty {
height: 2px;
width: 50%;
background: #ddd;
margin: 50% auto;
}
.language-tab {
display: flex;
@@ -1125,9 +1418,21 @@ onUnmounted(() => { unInit() });
color: #94a3b8;
font-size: 14px;
}
.dev-rank.rank-1 { color: #fbbf24; font-size: 18px; }
.dev-rank.rank-2 { color: #94a3b8; font-size: 16px; }
.dev-rank.rank-3 { color: #b45309; font-size: 15px; }
.dev-rank.rank-1 {
color: #fbbf24;
font-size: 18px;
}
.dev-rank.rank-2 {
color: #94a3b8;
font-size: 16px;
}
.dev-rank.rank-3 {
color: #b45309;
font-size: 15px;
}
/* 头像占位 */
.dev-avatar {
@@ -1168,7 +1473,11 @@ onUnmounted(() => { unInit() });
}
@media (max-width: 768px) {
.main-title { font-size: 2rem; }
.index-module__NV_5cW__chartsGrid { grid-template-columns: 1fr; }
.main-title {
font-size: 2rem;
}
.index-module__NV_5cW__chartsGrid {
grid-template-columns: 1fr;
}
}
</style>