feat: update docs and components, fix DLQ demo bug

This commit is contained in:
sanbuphy
2026-01-18 12:21:49 +08:00
parent 26ed39e1eb
commit e41063a1cd
159 changed files with 54236 additions and 2525 deletions
@@ -0,0 +1,688 @@
<template>
<div class="backend-languages-demo">
<div class="language-grid">
<div
v-for="lang in languages"
:key="lang.name"
class="language-card"
:class="{ active: selectedLang === lang.name }"
@click="selectedLang = lang.name"
>
<div class="lang-header">
<div class="lang-icon">{{ lang.icon }}</div>
<h4>{{ lang.name }}</h4>
<div class="lang-year">{{ lang.year }}</div>
</div>
<div class="lang-tags">
<span
v-for="tag in lang.tags"
:key="tag"
class="tag"
:class="`tag-${tag.type}`"
>
{{ tag.label }}
</span>
</div>
<div class="lang-description">{{ lang.description }}</div>
<div class="lang-stats">
<div class="stat">
<span class="stat-label">性能</span>
<div class="stat-bar">
<div
class="stat-fill performance"
:style="{ width: lang.stats.performance + '%' }"
></div>
</div>
</div>
<div class="stat">
<span class="stat-label">开发效率</span>
<div class="stat-bar">
<div
class="stat-fill efficiency"
:style="{ width: lang.stats.efficiency + '%' }"
></div>
</div>
</div>
<div class="stat">
<span class="stat-label">生态</span>
<div class="stat-bar">
<div
class="stat-fill ecosystem"
:style="{ width: lang.stats.ecosystem + '%' }"
></div>
</div>
</div>
<div class="stat">
<span class="stat-label">学习曲线</span>
<div class="stat-bar">
<div
class="stat-fill learning"
:style="{ width: lang.stats.learning + '%' }"
></div>
</div>
</div>
</div>
</div>
</div>
<transition name="fade">
<div v-if="selectedLang" class="lang-detail">
<h3>{{ getLangDetail(selectedLang).title }}</h3>
<div class="detail-grid">
<div class="detail-section">
<h4>核心特点</h4>
<ul>
<li v-for="feature in getLangDetail(selectedLang).features" :key="feature">
{{ feature }}
</li>
</ul>
</div>
<div class="detail-section">
<h4>典型应用</h4>
<ul>
<li v-for="app in getLangDetail(selectedLang).applications" :key="app">
{{ app }}
</li>
</ul>
</div>
<div class="detail-section">
<h4>优劣势</h4>
<div class="pros-cons">
<div class="pros">
<strong>优势</strong>
<ul>
<li v-for="pro in getLangDetail(selectedLang).pros" :key="pro">
{{ pro }}
</li>
</ul>
</div>
<div class="cons">
<strong>劣势</strong>
<ul>
<li v-for="con in getLangDetail(selectedLang).cons" :key="con">
{{ con }}
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</transition>
</div>
</template>
<script setup>
import { ref } from 'vue'
const selectedLang = ref('Java')
const languages = [
{
name: 'Java',
icon: '☕',
year: '1995',
tags: [
{ type: 'primary', label: '企业级' },
{ type: 'success', label: '跨平台' },
{ type: 'info', label: '强类型' }
],
description: '企业级开发的霸主,Spring Boot 生态成熟',
stats: { performance: 75, efficiency: 60, ecosystem: 95, learning: 40 }
},
{
name: 'Python',
icon: '🐍',
year: '1991',
tags: [
{ type: 'primary', label: 'AI/ML' },
{ type: 'success', label: '简洁' },
{ type: 'warning', label: '动态类型' }
],
description: 'AI 与数据分析的首选语言',
stats: { performance: 30, efficiency: 95, ecosystem: 95, learning: 95 }
},
{
name: 'Go',
icon: '🐹',
year: '2009',
tags: [
{ type: 'primary', label: '云原生' },
{ type: 'success', label: '高性能' },
{ type: 'info', label: '并发' }
],
description: 'Google 出品,云原生时代的宠儿',
stats: { performance: 90, efficiency: 85, ecosystem: 75, learning: 80 }
},
{
name: 'Node.js',
icon: '💚',
year: '2009',
tags: [
{ type: 'primary', label: '全栈' },
{ type: 'success', label: 'NPM' },
{ type: 'info', label: '异步' }
],
description: 'JavaScript 运行时,前后端统一',
stats: { performance: 70, efficiency: 85, ecosystem: 95, learning: 75 }
},
{
name: 'C#',
icon: '💜',
year: '2000',
tags: [
{ type: 'primary', label: '.NET' },
{ type: 'success', label: '跨平台' },
{ type: 'info', label: 'Unity' }
],
description: '微软出品,Windows 生态王者',
stats: { performance: 80, efficiency: 70, ecosystem: 85, learning: 50 }
},
{
name: 'Rust',
icon: '🦀',
year: '2010',
tags: [
{ type: 'primary', label: '系统级' },
{ type: 'success', label: '内存安全' },
{ type: 'danger', label: '难学' }
],
description: 'Mozilla 出品,内存安全的系统语言',
stats: { performance: 95, efficiency: 40, ecosystem: 70, learning: 20 }
},
{
name: 'C++',
icon: '⚡',
year: '1985',
tags: [
{ type: 'primary', label: '高性能' },
{ type: 'success', label: '游戏' },
{ type: 'danger', label: '复杂' }
],
description: '高性能计算的基石',
stats: { performance: 98, efficiency: 35, ecosystem: 90, learning: 25 }
},
{
name: 'Ruby',
icon: '💎',
year: '1995',
tags: [
{ type: 'primary', label: 'Rails' },
{ type: 'success', label: '优雅' },
{ type: 'warning', label: '慢' }
],
description: 'Ruby on Rails,快速开发典范',
stats: { performance: 25, efficiency: 90, ecosystem: 70, learning: 85 }
}
]
const langDetails = {
Java: {
title: 'Java - 企业级开发的霸主',
features: [
'JVM (Java Virtual Machine) 实现跨平台',
'强类型系统,编译时检查',
'Spring 全家桶生态成熟',
'JIT 编译器提供接近 C++ 的性能'
],
applications: [
'大型企业系统(银行、保险、电商)',
'Android 应用开发',
'大数据处理(Hadoop、Spark',
'微服务架构(Spring Cloud'
],
pros: [
'✅ 生态极其成熟,框架完备',
'✅ 强类型,编译时检查',
'✅ 多线程模型成熟',
'✅ 跨平台,JVM 优化强大'
],
cons: [
'❌ 代码冗长,样板代码多',
'❌ 启动慢,内存占用高',
'❌ 学习曲线陡峭(Spring 全家桶)',
'❌ 版本更新快,兼容性问题'
]
},
Python: {
title: 'Python - AI 与脚本之王',
features: [
'极简语法,像读英语一样',
'AI 生态无与伦比(NumPy、PyTorch',
'快速开发,代码量少',
'丰富的科学计算库'
],
applications: [
'AI/机器学习(所有主流框架)',
'数据分析(Pandas、Jupyter',
'脚本自动化(运维、数据处理)',
'Web 开发(Django、Flask'
],
pros: [
'✅ 语法简单,学习曲线平缓',
'✅ AI 生态无与伦比',
'✅ 快速开发,代码量少',
'✅ 社区活跃,库丰富'
],
cons: [
'❌ 运行速度慢(比 Java/Go 慢 10-100 倍)',
'❌ 动态类型,运行时错误多',
'❌ GIL 限制,多线程性能差',
'❌ 打包部署复杂(依赖地狱)'
]
},
Go: {
title: 'Go - 云原生时代的宠儿',
features: [
'Goroutine (协程) 轻量级并发',
'简洁语法,25 个关键字',
'快速编译,比 Java 快 10 倍',
'单一可执行文件,无依赖'
],
applications: [
'云原生基础设施(Docker、K8s',
'微服务架构',
'DevOps 工具(Terraform、Prometheus',
'区块链(Hyperledger Fabric'
],
pros: [
'✅ 原生并发,性能接近 C++',
'✅ 简洁语法,学习曲线平缓',
'✅ 编译快,部署简单',
'✅ 单一可执行文件,无依赖'
],
cons: [
'❌ 生态不如 Java/Python 成熟',
'❌ 错误处理繁琐(if err != nil',
'❌ 泛型支持较弱(Go 1.18+ 才引入)',
'❌ 不如 Java/Python 灵活'
]
},
'Node.js': {
title: 'Node.js - 全栈工程师的利器',
features: [
'事件驱动,非阻塞 I/O',
'前后端统一语言',
'NPM 世界最大的包仓库',
'适合实时应用'
],
applications: [
'全栈 Web 应用(React + Node.js',
'实时系统(聊天应用、协作工具)',
'ServerlessAWS Lambda、Vercel',
'CLI 工具(VS Code、Webpack'
],
pros: [
'✅ 前后端统一,减少语言切换成本',
'✅ NPM 生态庞大,库丰富',
'✅ 适合 I/O 密集型应用',
'✅ 社区活跃,更新快'
],
cons: [
'❌ 单线程,CPU 密集型任务性能差',
'❌ 回调地狱(async/await 有改善)',
'❌ 动态类型,运行时错误多',
'❌ 版本兼容性问题多'
]
},
"C#": {
title: 'C# - Windows 生态的王者',
features: [
'微软 Visual Studio 极其强大',
'.NET Core 实现跨平台',
'高性能,CoreFX 优化',
'Unity 游戏开发官方语言'
],
applications: [
'Windows 应用开发',
'游戏开发(Unity 引擎)',
'Web 开发(ASP.NET Core',
'Azure 云服务'
],
pros: [
'✅ Visual Studio 极其强大',
'✅ ASP.NET Core 性能优秀',
'✅ 跨平台(.NET Core',
'✅ 游戏开发(Unity'
],
cons: [
'❌ Windows 历史包袱重',
'❌ 社区不如 Java/Python 活跃',
'❌ 学习曲线陡峭',
'❌ 开源生态相对较弱'
]
},
Rust: {
title: 'Rust - 系统级编程的未来',
features: [
'所有权系统保证内存安全',
'零成本抽象',
'编译时保证无内存泄漏',
'WebAssembly 支持'
],
applications: [
'系统编程(操作系统、数据库)',
'区块链(Solana、Polkadot',
'WebAssembly(前端高性能计算)',
'基础设施(AWS Firecracker'
],
pros: [
'✅ 内存安全,无 GC',
'✅ 性能接近 C++',
'✅ 现代化语法',
'✅ WebAssembly 支持'
],
cons: [
'❌ 学习曲线极其陡峭',
'❌ 编译时间长',
'❌ 生态不如 Go/Rust 成熟',
'❌ 开发速度慢'
]
},
'C++': {
title: 'C++ - 高性能计算的基石',
features: [
'极致性能,无语言能超越',
'底层控制,直接操作内存',
'游戏引擎标准',
'现代 C++ (11/14/17/20)'
],
applications: [
'游戏开发(Unreal Engine',
'高频交易(金融系统)',
'浏览器引擎(Chrome V8',
'AI 框架底层(PyTorch、TF'
],
pros: [
'✅ 性能极致',
'✅ 底层控制力强',
'✅ 游戏开发标准',
'✅ 生态成熟'
],
cons: [
'❌ 学习曲线极其陡峭',
'❌ 内存管理复杂(易泄漏)',
'❌ 开发效率低',
'❌ 不适合 Web 开发'
]
},
Ruby: {
title: 'Ruby - 快速开发的典范',
features: [
'Ruby on Rails 框架',
'约定优于配置',
'代码优雅',
'快速开发'
],
applications: [
'初创公司(GitHub、Airbnb',
'快速原型(MVP、黑客松)',
'Web 开发(Rails、Sinatra',
'CI/CD 脚本'
],
pros: [
'✅ Rails 框架极其成熟',
'✅ 快速开发,代码优雅',
'✅ 约定优于配置',
'✅ 社区活跃'
],
cons: [
'❌ 性能较差',
'❌ 动态类型,运行时错误多',
'❌ 多线程性能差',
'❌ 生态不如 Java/Python 广泛'
]
}
}
const getLangDetail = (name) => {
return langDetails[name] || {}
}
</script>
<style scoped>
.backend-languages-demo {
border-radius: 16px;
background: var(--vp-c-bg);
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.05);
border: 1px solid var(--vp-c-divider);
overflow: hidden;
margin: 2rem 0;
padding: 2rem;
}
.language-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 1.5rem;
margin-bottom: 2rem;
}
.language-card {
background: var(--vp-c-bg-soft);
border: 2px solid transparent;
border-radius: 12px;
padding: 1.5rem;
cursor: pointer;
transition: all 0.3s ease;
}
.language-card:hover {
transform: translateY(-5px);
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1);
}
.language-card.active {
border-color: var(--vp-c-brand);
background: var(--vp-c-bg);
}
.lang-header {
display: flex;
align-items: center;
gap: 1rem;
margin-bottom: 1rem;
}
.lang-icon {
font-size: 2.5rem;
line-height: 1;
}
.lang-header h4 {
flex: 1;
margin: 0;
font-size: 1.2rem;
color: var(--vp-c-text-1);
}
.lang-year {
font-size: 0.8rem;
color: var(--vp-c-text-3);
font-family: var(--vp-font-family-mono);
}
.lang-tags {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
margin-bottom: 1rem;
}
.tag {
padding: 0.25rem 0.75rem;
border-radius: 12px;
font-size: 0.75rem;
font-weight: 600;
}
.tag-primary {
background: #e0f2fe;
color: #0369a1;
}
.tag-success {
background: #dcfce7;
color: #15803d;
}
.tag-info {
background: #e0e7ff;
color: #4338ca;
}
.tag-warning {
background: #fef3c7;
color: #b45309;
}
.tag-danger {
background: #fee2e2;
color: #b91c1c;
}
.lang-description {
font-size: 0.9rem;
color: var(--vp-c-text-2);
margin-bottom: 1rem;
line-height: 1.5;
}
.lang-stats {
display: flex;
flex-direction: column;
gap: 0.75rem;
}
.stat {
display: flex;
align-items: center;
gap: 0.75rem;
}
.stat-label {
font-size: 0.75rem;
color: var(--vp-c-text-2);
min-width: 60px;
font-weight: 600;
}
.stat-bar {
flex: 1;
height: 8px;
background: var(--vp-c-divider);
border-radius: 4px;
overflow: hidden;
}
.stat-fill {
height: 100%;
border-radius: 4px;
transition: width 0.5s ease;
}
.stat-fill.performance {
background: linear-gradient(90deg, #fbbf24, #f59e0b);
}
.stat-fill.efficiency {
background: linear-gradient(90deg, #34d399, #10b981);
}
.stat-fill.ecosystem {
background: linear-gradient(90deg, #60a5fa, #3b82f6);
}
.stat-fill.learning {
background: linear-gradient(90deg, #f472b6, #ec4899);
}
.lang-detail {
background: var(--vp-c-bg-soft);
border-radius: 12px;
padding: 2rem;
animation: fade-in 0.3s ease;
}
.lang-detail h3 {
margin-top: 0;
margin-bottom: 1.5rem;
color: var(--vp-c-brand);
font-size: 1.5rem;
}
.detail-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 2rem;
}
.detail-section h4 {
color: var(--vp-c-text-1);
margin-bottom: 1rem;
font-size: 1.1rem;
}
.detail-section ul {
list-style: none;
padding: 0;
margin: 0;
}
.detail-section li {
padding: 0.5rem 0;
color: var(--vp-c-text-2);
font-size: 0.9rem;
line-height: 1.5;
position: relative;
padding-left: 1.5rem;
}
.detail-section li::before {
content: '▸';
position: absolute;
left: 0;
color: var(--vp-c-brand);
font-weight: bold;
}
.pros-cons {
display: flex;
flex-direction: column;
gap: 1rem;
}
.pros,
.cons {
font-size: 0.9rem;
}
.pros strong {
color: #10b981;
}
.cons strong {
color: #ef4444;
}
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.3s ease;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
@keyframes fade-in {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
</style>
@@ -0,0 +1,769 @@
<template>
<div class="concurrency-model-demo">
<div class="demo-header">
<h4>并发模型对比</h4>
<p class="subtitle">不同语言处理并发请求的方式</p>
</div>
<div class="model-grid">
<div
v-for="model in models"
:key="model.name"
class="model-card"
:class="{ active: selectedModel === model.name }"
@click="selectedModel = model.name"
>
<div class="model-icon">{{ model.icon }}</div>
<h5>{{ model.name }}</h5>
<div class="model-tag">{{ model.tag }}</div>
<div class="model-desc">{{ model.description }}</div>
</div>
</div>
<transition name="fade" mode="out-in">
<div :key="selectedModel" class="model-detail">
<div class="detail-header">
<h5>{{ getModelDetail(selectedModel).title }}</h5>
<div class="model-stats">
<div class="stat">
<span class="stat-label">并发能力</span>
<div class="stat-bar">
<div
class="stat-fill"
:style="{ width: getModelDetail(selectedModel).concurrency + '%' }"
></div>
</div>
</div>
<div class="stat">
<span class="stat-label">内存开销</span>
<div class="stat-bar">
<div
class="stat-fill memory"
:style="{ width: getModelDetail(selectedModel).memory + '%' }"
></div>
</div>
</div>
<div class="stat">
<span class="stat-label">CPU 利用率</span>
<div class="stat-bar">
<div
class="stat-fill cpu"
:style="{ width: getModelDetail(selectedModel).cpu + '%' }"
></div>
</div>
</div>
</div>
</div>
<div class="code-example">
<h6>代码示例</h6>
<pre><code>{{ getModelDetail(selectedModel).code }}</code></pre>
</div>
<div class="visualization">
<h6>并发可视化</h6>
<ConcurrencyVisualization :model="selectedModel" />
</div>
<div class="pros-cons">
<div class="pros">
<h6>优势</h6>
<ul>
<li v-for="pro in getModelDetail(selectedModel).pros" :key="pro">
{{ pro }}
</li>
</ul>
</div>
<div class="cons">
<h6>劣势</h6>
<ul>
<li v-for="con in getModelDetail(selectedModel).cons" :key="con">
{{ con }}
</li>
</ul>
</div>
</div>
</div>
</transition>
</div>
</template>
<script setup>
import { ref, defineComponent } from 'vue'
const selectedModel = ref('Goroutine')
const models = [
{
name: 'Goroutine',
icon: '🐹',
tag: 'Go',
description: '轻量级协程,百万级并发'
},
{
name: 'Thread',
icon: '🧵',
tag: 'Java',
description: '传统线程池,成熟稳定'
},
{
name: 'Async/Await',
icon: '⚡',
tag: 'Node.js',
description: '事件循环,非阻塞 I/O'
},
{
name: 'Async/Await',
icon: '🦀',
tag: 'Rust',
description: '零成本抽象,高性能'
}
]
const modelDetails = {
Goroutine: {
title: 'Go Goroutine (协程)',
concurrency: 95,
memory: 90,
cpu: 85,
code: `// Go: 启动 10 万个协程
package main
import (
"fmt"
"time"
)
func task(id int) {
fmt.Printf("Task %d\\n", id)
}
func main() {
for i := 0; i < 100000; i++ {
go task(i) // 启动协程
}
time.Sleep(time.Second)
}`,
pros: [
'✅ 轻量级:每个协程仅 2KB 栈内存',
'✅ 可创建百万级协程',
'✅ 语法简洁(go 关键字)',
'✅ 通信顺序进程(CSP)模型'
],
cons: [
'❌ 需要手动管理协程生命周期',
'❌ 错误处理繁琐(if err != nil',
'❌ 不如线程模型成熟'
]
},
Thread: {
title: 'Java Thread (线程池)',
concurrency: 70,
memory: 40,
cpu: 80,
code: `// Java: 线程池处理并发
import java.util.concurrent.*;
ExecutorService executor =
Executors.newFixedThreadPool(10);
for (int i = 0; i < 1000; i++) {
final int taskId = i;
executor.submit(() -> {
System.out.println("Task " + taskId);
});
}
executor.shutdown();`,
pros: [
'✅ 成熟稳定,企业级应用首选',
'✅ 异常处理机制完善',
'✅ 调试工具丰富(JConsole、VisualVM',
'✅ 线程池优化(ExecutorService'
],
cons: [
'❌ 线程重(1-2MB 栈内存)',
'❌ 上下文切换开销大',
'❌ 并发数受限(通常 < 10000',
'❌ 锁竞争复杂'
]
},
'Async/Await': {
title: 'Node.js Async/Await (事件循环)',
concurrency: 85,
memory: 75,
cpu: 60,
code: `// Node.js: 异步处理
const axios = require('axios');
async function fetch(id) {
const response = await axios.get(url);
console.log(\`Task \${id}\`);
}
async function main() {
const tasks = [];
for (let i = 0; i < 10000; i++) {
tasks.push(fetch(i));
}
await Promise.all(tasks);
}
main();`,
pros: [
'✅ 适合 I/O 密集型应用',
'✅ 单线程,无锁竞争',
'✅ 事件驱动,非阻塞',
'✅ 语法优雅(async/await'
],
cons: [
'❌ 单线程,CPU 密集型性能差',
'❌ 回调地狱(虽然 async/await 有改善)',
'❌ 无法利用多核 CPU(需要 Worker Threads',
'❌ 错误堆栈复杂'
]
},
RustAsync: {
title: 'Rust Async/Await (零成本抽象)',
concurrency: 90,
memory: 95,
cpu: 90,
code: `// Rust: 异步运行时(tokio
use tokio::task;
async fn task(id: u32) {
println!("Task {}", id);
}
#[tokio::main]
async fn main() {
let mut handles = vec![];
for i in 0..100_000 {
let handle = task::spawn(async move {
task(i).await;
});
handles.push(handle);
}
for handle in handles {
handle.await.unwrap();
}
}`,
pros: [
'✅ 零成本抽象(编译成状态机)',
'✅ 内存安全(编译时保证)',
'✅ 性能接近手动管理',
'✅ 无 GC,无运行时开销'
],
cons: [
'❌ 学习曲线极其陡峭',
'❌ 需要运行时(tokio、async-std',
'❌ 编译时间长',
'❌ 生态不如 Go/Node.js 成熟'
]
}
}
const getModelDetail = (model) => {
if (model === 'Async/Await') {
return selectedModel.value === 'Node.js'
? modelDetails['Async/Await']
: modelDetails.RustAsync
}
return modelDetails[model] || modelDetails.Goroutine
}
// ConcurrencyVisualization component
const ConcurrencyVisualization = defineComponent({
name: 'ConcurrencyVisualization',
props: {
model: String
},
template: `
<div class="concurrency-viz">
<div class="viz-container">
<div class="task-queue">
<div class="queue-label">任务队列</div>
<div class="queue-items">
<div
v-for="i in 20"
:key="i"
class="queue-item"
:class="{ processing: i <= activeWorkers }"
>
Task {{ i }}
</div>
</div>
</div>
<div class="workers">
<div class="workers-label">{{ workersLabel }}</div>
<div class="worker-pool">
<div
v-for="i in maxWorkers"
:key="i"
class="worker"
:class="{ active: i <= activeWorkers }"
>
{{ i <= activeWorkers ? '⚡' : '💤' }}
</div>
</div>
</div>
</div>
</div>
`,
setup(props) {
const workersLabel = computed(() => {
const labels = {
Goroutine: 'Goroutines (可无限创建)',
Thread: 'Thread Pool (固定数量)',
'Async/Await': 'Event Loop (单线程)',
RustAsync: 'Async Tasks (可无限创建)'
}
return labels[props.model] || 'Workers'
})
const maxWorkers = computed(() => {
const counts = {
Goroutine: 100,
Thread: 10,
'Async/Await': 1,
RustAsync: 100
}
return counts[props.model] || 10
})
const activeWorkers = computed(() => {
const actives = {
Goroutine: 100,
Thread: 10,
'Async/Await': 1,
RustAsync: 100
}
return actives[props.model] || 10
})
return {
workersLabel,
maxWorkers,
activeWorkers
}
}
})
</script>
<script>
import { computed, defineComponent } from 'vue'
export default {
components: {
ConcurrencyVisualization: defineComponent({
name: 'ConcurrencyVisualization',
props: {
model: String
},
template: `
<div class="concurrency-viz">
<div class="viz-container">
<div class="task-queue">
<div class="queue-label">任务队列</div>
<div class="queue-items">
<div
v-for="i in 20"
:key="i"
class="queue-item"
:class="{ processing: i <= activeWorkers }"
>
Task {{ i }}
</div>
</div>
</div>
<div class="workers">
<div class="workers-label">{{ workersLabel }}</div>
<div class="worker-pool">
<div
v-for="i in displayWorkers"
:key="i"
class="worker"
:class="{ active: i <= activeWorkers }"
>
{{ i <= activeWorkers ? '⚡' : '💤' }}
</div>
</div>
</div>
</div>
</div>
`,
setup(props) {
const workersLabel = computed(() => {
const labels = {
Goroutine: 'Goroutines (可无限创建)',
Thread: 'Thread Pool (固定数量)',
'Async/Await': 'Event Loop (单线程)',
RustAsync: 'Async Tasks (可无限创建)'
}
return labels[props.model] || 'Workers'
})
const maxWorkers = computed(() => {
const counts = {
Goroutine: 20,
Thread: 10,
'Async/Await': 1,
RustAsync: 20
}
return counts[props.model] || 10
})
const activeWorkers = computed(() => {
const actives = {
Goroutine: 20,
Thread: 10,
'Async/Await': 1,
RustAsync: 20
}
return actives[props.model] || 10
})
const displayWorkers = computed(() => {
// 限制显示数量,避免 DOM 过多
return Math.min(maxWorkers.value, 20)
})
return {
workersLabel,
maxWorkers,
activeWorkers,
displayWorkers
}
}
})
}
}
</script>
<style scoped>
.concurrency-model-demo {
background: var(--vp-c-bg);
border-radius: 12px;
padding: 2rem;
margin: 2rem 0;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.05);
border: 1px solid var(--vp-c-divider);
}
.demo-header {
text-align: center;
margin-bottom: 2rem;
}
.demo-header h4 {
margin: 0 0 0.5rem 0;
color: var(--vp-c-brand);
font-size: 1.5rem;
}
.subtitle {
margin: 0;
color: var(--vp-c-text-2);
font-size: 0.95rem;
}
.model-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1rem;
margin-bottom: 2rem;
}
.model-card {
background: var(--vp-c-bg-soft);
border: 2px solid transparent;
border-radius: 8px;
padding: 1.5rem;
cursor: pointer;
transition: all 0.3s ease;
text-align: center;
}
.model-card:hover {
transform: translateY(-3px);
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.1);
}
.model-card.active {
border-color: var(--vp-c-brand);
background: var(--vp-c-bg);
}
.model-icon {
font-size: 3rem;
margin-bottom: 0.5rem;
}
.model-card h5 {
margin: 0.5rem 0;
color: var(--vp-c-text-1);
font-size: 1.1rem;
}
.model-tag {
display: inline-block;
padding: 0.25rem 0.75rem;
background: var(--vp-c-brand);
color: white;
border-radius: 12px;
font-size: 0.75rem;
font-weight: 600;
margin-bottom: 0.5rem;
}
.model-desc {
font-size: 0.85rem;
color: var(--vp-c-text-2);
line-height: 1.4;
}
.model-detail {
background: var(--vp-c-bg-soft);
border-radius: 12px;
padding: 2rem;
animation: fade-in 0.3s ease;
}
.detail-header {
margin-bottom: 2rem;
}
.detail-header h5 {
margin: 0 0 1.5rem 0;
color: var(--vp-c-brand);
font-size: 1.3rem;
}
.model-stats {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1.5rem;
margin-bottom: 2rem;
}
.stat {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.stat-label {
font-size: 0.85rem;
font-weight: 600;
color: var(--vp-c-text-1);
}
.stat-bar {
height: 8px;
background: var(--vp-c-bg);
border-radius: 4px;
overflow: hidden;
}
.stat-fill {
height: 100%;
background: linear-gradient(90deg, var(--vp-c-brand), #8b5cf6);
transition: width 0.5s ease;
}
.stat-fill.memory {
background: linear-gradient(90deg, #f59e0b, #d97706);
}
.stat-fill.cpu {
background: linear-gradient(90deg, #10b981, #059669);
}
.code-example {
background: #1e1e1e;
border-radius: 8px;
padding: 1.5rem;
margin-bottom: 2rem;
overflow-x: auto;
}
.code-example h6 {
margin: 0 0 1rem 0;
color: #4ec9b0;
font-size: 1rem;
}
.code-example pre {
margin: 0;
}
.code-example code {
font-family: 'Monaco', 'Menlo', monospace;
font-size: 0.85rem;
line-height: 1.6;
color: #d4d4d4;
}
.visualization {
margin-bottom: 2rem;
}
.visualization h6 {
margin: 0 0 1rem 0;
color: var(--vp-c-text-1);
font-size: 1rem;
}
.concurrency-viz {
background: var(--vp-c-bg);
border-radius: 8px;
padding: 1.5rem;
border: 1px solid var(--vp-c-divider);
}
.viz-container {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 2rem;
}
.task-queue,
.workers {
display: flex;
flex-direction: column;
gap: 1rem;
}
.queue-label,
.workers-label {
font-weight: 600;
color: var(--vp-c-text-1);
font-size: 0.9rem;
}
.queue-items {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.queue-item {
padding: 0.5rem;
background: var(--vp-c-bg-soft);
border-radius: 4px;
font-size: 0.85rem;
color: var(--vp-c-text-2);
transition: all 0.3s ease;
}
.queue-item.processing {
background: #dcfce7;
color: #15803d;
font-weight: 600;
}
.worker-pool {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}
.worker {
width: 40px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
background: var(--vp-c-bg-soft);
border-radius: 8px;
font-size: 1.2rem;
transition: all 0.3s ease;
}
.worker.active {
background: #dcfce7;
animation: pulse 1.5s infinite;
}
@keyframes pulse {
0%,
100% {
transform: scale(1);
}
50% {
transform: scale(1.05);
}
}
.pros-cons {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 2rem;
}
.pros h6,
.cons h6 {
margin: 0 0 1rem 0;
font-size: 1rem;
}
.pros h6 {
color: #10b981;
}
.cons h6 {
color: #ef4444;
}
.pros ul,
.cons ul {
list-style: none;
padding: 0;
margin: 0;
}
.pros li,
.cons li {
padding: 0.5rem 0;
font-size: 0.9rem;
color: var(--vp-c-text-2);
line-height: 1.5;
}
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.3s ease;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
@keyframes fade-in {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@media (max-width: 768px) {
.model-stats {
grid-template-columns: 1fr;
}
.viz-container {
grid-template-columns: 1fr;
}
.pros-cons {
grid-template-columns: 1fr;
}
}
</style>
@@ -0,0 +1,523 @@
<template>
<div class="developer-efficiency-demo">
<div class="demo-header">
<h4>开发效率对比</h4>
<p class="subtitle">不同语言完成相同任务所需的代码量和时间</p>
</div>
<div class="task-selector">
<label>选择任务</label>
<select v-model="selectedTask" @change="updateMetrics">
<option v-for="task in tasks" :key="task.id" :value="task.id">
{{ task.name }}
</option>
</select>
</div>
<div class="metrics-grid">
<div class="metric-card">
<div class="metric-header">
<span class="metric-icon">📝</span>
<h5>代码行数</h5>
</div>
<div class="metric-chart">
<div
v-for="lang in sortedLanguages"
:key="lang.name"
class="metric-bar"
>
<div class="bar-label">{{ lang.name }}</div>
<div class="bar-container">
<div
class="bar-fill"
:style="{ width: getBarWidth(lang.lines) + '%' }"
>
<span class="bar-value">{{ lang.lines }}</span>
</div>
</div>
</div>
</div>
<div class="metric-insight">
<p>
<strong>💡 分析</strong>
{{ getTaskDetail(selectedTask).linesInsight }}
</p>
</div>
</div>
<div class="metric-card">
<div class="metric-header">
<span class="metric-icon"></span>
<h5>开发时间小时</h5>
</div>
<div class="metric-chart">
<div
v-for="lang in sortedLanguages"
:key="lang.name"
class="metric-bar"
>
<div class="bar-label">{{ lang.name }}</div>
<div class="bar-container">
<div
class="bar-fill time"
:style="{ width: getBarWidth(lang.time) + '%' }"
>
<span class="bar-value">{{ lang.time }}h</span>
</div>
</div>
</div>
</div>
<div class="metric-insight">
<p>
<strong>💡 分析</strong>
{{ getTaskDetail(selectedTask).timeInsight }}
</p>
</div>
</div>
<div class="metric-card">
<div class="metric-header">
<span class="metric-icon">🐛</span>
<h5>调试时间小时</h5>
</div>
<div class="metric-chart">
<div
v-for="lang in sortedLanguages"
:key="lang.name"
class="metric-bar"
>
<div class="bar-label">{{ lang.name }}</div>
<div class="bar-container">
<div
class="bar-fill debug"
:style="{ width: getBarWidth(lang.debug) + '%' }"
>
<span class="bar-value">{{ lang.debug }}h</span>
</div>
</div>
</div>
</div>
<div class="metric-insight">
<p>
<strong>💡 分析</strong>
{{ getTaskDetail(selectedTask).debugInsight }}
</p>
</div>
</div>
</div>
<div class="efficiency-radar">
<h5>综合效率雷达图</h5>
<div class="radar-chart">
<div class="radar-grid">
<div
v-for="lang in languages"
:key="lang.name"
class="radar-point"
:style="getRadarPosition(lang)"
>
<div class="point-label">{{ lang.name }}</div>
<div class="point-dot"></div>
</div>
</div>
</div>
<div class="radar-legend">
<div class="legend-item">
<span class="legend-dot"></span>
<span>左上代码少开发快</span>
</div>
<div class="legend-item">
<span class="legend-dot"></span>
<span>右上调试快类型安全</span>
</div>
<div class="legend-item">
<span class="legend-dot"></span>
<span>左下生态好库丰富</span>
</div>
<div class="legend-item">
<span class="legend-dot"></span>
<span>右下学习简单上手快</span>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref, computed } from 'vue'
const selectedTask = ref('rest')
const tasks = [
{ id: 'rest', name: 'REST API 服务' },
{ id: 'web', name: 'Web 应用' },
{ id: 'script', name: '数据处理脚本' },
{ id: 'micro', name: '微服务' }
]
const languages = ['Python', 'Ruby', 'Go', 'Node.js', 'Java', 'C#', 'Rust', 'C++']
const taskMetrics = {
rest: {
Python: { lines: 50, time: 4, debug: 2 },
Ruby: { lines: 45, time: 3.5, debug: 2.5 },
Go: { lines: 80, time: 5, debug: 1.5 },
'Node.js': { lines: 60, time: 4.5, debug: 2 },
Java: { lines: 150, time: 8, debug: 2 },
"C#": { lines: 120, time: 7, debug: 2 },
Rust: { lines: 100, time: 10, debug: 3 },
'C++': { lines: 180, time: 12, debug: 5 },
linesInsight:
'Python 和 Ruby 用最少的代码实现 REST API,得益于简洁的语法和强大的框架(Flask、Sinatra)。Go 虽然语法简洁,但需要显式类型声明。Java 和 C# 的样板代码最多。',
timeInsight:
'Ruby 和 Python 开发最快,适合快速迭代。Go 和 Node.js 居中,平衡了开发速度和性能。Java 和 C# 开发时间较长,但后期维护成本低。Rust 和 C++ 开发时间最长,主要受学习曲线和编译时间影响。',
debugInsight:
'Go、Java、C# 的静态类型让调试更容易,大部分错误在编译时就能发现。Python 和 Ruby 虽然开发快,但运行时错误多,调试时间长。Rust 的借用检查器虽然学习曲线陡峭,但能提前发现大量 bug。'
},
web: {
Python: { lines: 200, time: 10, debug: 5 },
Ruby: { lines: 180, time: 9, debug: 5 },
Go: { lines: 300, time: 12, debug: 4 },
'Node.js': { lines: 250, time: 11, debug: 5 },
Java: { lines: 500, time: 20, debug: 6 },
"C#": { lines: 400, time: 18, debug: 6 },
Rust: { lines: 350, time: 25, debug: 8 },
'C++': { lines: 600, time: 30, debug: 12 },
linesInsight:
'Rails 和 Django 的"约定优于配置"让 Web 开发极其高效,代码量最少。全栈的 Node.js 也表现不错。Go 需要 more boilerplate。Java 的 Spring Boot 虽然强大,但配置和样板代码较多。',
timeInsight:
'Ruby (Rails) 和 Python (Django) 是 Web 开发的效率之王,内置 ORM、模板引擎、认证等功能,开箱即用。Node.js 的全栈特性让前后端统一,减少沟通成本。Go 和 Java 需要更多配置和 boilerplate。',
debugInsight:
'静态类型语言(Go、Java、C#)在大型 Web 项目中优势明显,IDE 支持更好,重构更安全。Python 和 Ruby 在小项目中调试很快,但随着项目增长,动态类型带来的维护成本会急剧上升。'
},
script: {
Python: { lines: 20, time: 1, debug: 0.5 },
Ruby: { lines: 18, time: 1, debug: 0.5 },
Go: { lines: 40, time: 2, debug: 0.5 },
'Node.js': { lines: 25, time: 1.5, debug: 0.5 },
Java: { lines: 80, time: 4, debug: 1 },
"C#": { lines: 70, time: 3.5, debug: 1 },
Rust: { lines: 50, time: 4, debug: 1 },
'C++': { lines: 100, time: 5, debug: 2 },
linesInsight:
'Python 是脚本自动化的绝对王者,标准库丰富,第三方库如 Pandas、Requests 让数据处理极其简单。Ruby 也很优秀。其他语言对于简单脚本来说都太重量级了。',
timeInsight:
'Python 和 Ruby 是脚本任务的首选,几行代码就能完成复杂的数据处理。Node.js 在处理 JSON 数据时也很方便。编译型语言(Go、Java、C++)对于简单脚本来说 overhead 太大。',
debugInsight:
'Python 的交互式解释器(REPL)和丰富的调试工具(pdb、ipdb)让脚本调试极其高效。Ruby 的 Pry 也很强大。其他语言的编译/运行循环对于脚本开发来说太慢了。'
},
micro: {
Python: { lines: 100, time: 6, debug: 3 },
Ruby: { lines: 90, time: 5.5, debug: 3.5 },
Go: { lines: 120, time: 7, debug: 2 },
'Node.js': { lines: 110, time: 6.5, debug: 3 },
Java: { lines: 250, time: 15, debug: 4 },
"C#": { lines: 200, time: 13, debug: 4 },
Rust: { lines: 140, time: 18, debug: 5 },
'C++': { lines: 300, time: 22, debug: 8 },
linesInsight:
'Go 是微服务的理想选择,单一二进制文件 + 内置 HTTP 服务器 + 强大的标准库。Node.js 的 Express/Koa 也很轻量。Python 的 FastAPI 表现不错,但性能和并发不如 Go。',
timeInsight:
'Go 和 Node.js 在微服务开发中效率最高,启动快,部署简单。Python 和 Ruby 适合快速原型,但生产环境需要更多优化。Java 和 C# 的 Spring Cloud/.NET 虽然强大,但对于简单微服务来说太重量级。',
debugInsight:
'Go 和 Rust 的类型系统和错误处理让微服务的调试和测试更容易。Java 和 C# 的成熟工具链(JUnit、NUnit)也很有优势。Python 和 Ruby 的动态类型在分布式系统中可能带来运行时错误。'
}
}
const currentMetrics = computed(() => {
return taskMetrics[selectedTask.value]
})
const sortedLanguages = computed(() => {
return languages
.map((lang) => ({
name: lang,
...currentMetrics.value[lang]
}))
.sort((a, b) => a.lines - b.lines)
})
const getBarWidth = (value) => {
const max = Math.max(...Object.values(currentMetrics.value).flatMap((v) => [v.lines, v.time * 20, v.debug * 20]))
return (value / max) * 100
}
const getTaskDetail = (taskId) => {
return taskMetrics[taskId]
}
const getRadarPosition = (langName) => {
const metrics = currentMetrics.value[langName]
const avgLines = Object.values(currentMetrics.value).reduce((sum, v) => sum + v.lines, 0) / languages.length
const avgTime = Object.values(currentMetrics.value).reduce((sum, v) => sum + v.time, 0) / languages.length
const avgDebug = Object.values(currentMetrics.value).reduce((sum, v) => sum + v.debug, 0) / languages.length
// Normalize metrics (lower is better, so we invert)
const linesScore = 1 - metrics.lines / 300 // Max lines ~300
const timeScore = 1 - metrics.time / 30 // Max time ~30
const debugScore = 1 - metrics.debug / 12 // Max debug ~12
// Position in 2D space
// X: code efficiency (linesScore) vs ecosystem (hardcoded)
// Y: speed (timeScore) vs maintainability (debugScore)
const x = 50 + (linesScore - 0.5) * 80
const y = 50 + (timeScore - 0.5) * 80
return {
left: `${x}%`,
top: `${y}%`
}
}
const updateMetrics = () => {
// Trigger reactivity
}
</script>
<style scoped>
.developer-efficiency-demo {
background: var(--vp-c-bg);
border-radius: 12px;
padding: 2rem;
margin: 2rem 0;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.05);
border: 1px solid var(--vp-c-divider);
}
.demo-header {
text-align: center;
margin-bottom: 2rem;
}
.demo-header h4 {
margin: 0 0 0.5rem 0;
color: var(--vp-c-brand);
font-size: 1.5rem;
}
.subtitle {
margin: 0;
color: var(--vp-c-text-2);
font-size: 0.95rem;
}
.task-selector {
display: flex;
align-items: center;
justify-content: center;
gap: 1rem;
margin-bottom: 2rem;
flex-wrap: wrap;
}
.task-selector label {
font-weight: 600;
color: var(--vp-c-text-1);
}
.task-selector select {
padding: 0.5rem 1rem;
border: 1px solid var(--vp-c-divider);
border-radius: 6px;
background: var(--vp-c-bg);
color: var(--vp-c-text-1);
font-size: 0.9rem;
cursor: pointer;
}
.metrics-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 2rem;
margin-bottom: 3rem;
}
.metric-card {
background: var(--vp-c-bg-soft);
border-radius: 12px;
padding: 1.5rem;
border: 1px solid var(--vp-c-divider);
}
.metric-header {
display: flex;
align-items: center;
gap: 0.75rem;
margin-bottom: 1.5rem;
}
.metric-icon {
font-size: 2rem;
}
.metric-header h5 {
margin: 0;
color: var(--vp-c-text-1);
font-size: 1.1rem;
}
.metric-chart {
display: flex;
flex-direction: column;
gap: 0.75rem;
margin-bottom: 1.5rem;
}
.metric-bar {
display: flex;
align-items: center;
gap: 1rem;
}
.bar-label {
min-width: 70px;
font-weight: 600;
font-size: 0.85rem;
color: var(--vp-c-text-1);
}
.bar-container {
flex: 1;
height: 24px;
background: var(--vp-c-bg);
border-radius: 4px;
overflow: hidden;
}
.bar-fill {
height: 100%;
display: flex;
align-items: center;
justify-content: flex-end;
padding-right: 0.5rem;
background: linear-gradient(90deg, var(--vp-c-brand), #8b5cf6);
transition: width 0.5s ease;
color: white;
font-weight: 600;
font-size: 0.75rem;
}
.bar-fill.time {
background: linear-gradient(90deg, #10b981, #059669);
}
.bar-fill.debug {
background: linear-gradient(90deg, #f59e0b, #d97706);
}
.metric-insight {
background: var(--vp-c-bg);
border-radius: 8px;
padding: 1rem;
border-left: 3px solid var(--vp-c-brand);
}
.metric-insight p {
margin: 0;
font-size: 0.85rem;
line-height: 1.6;
color: var(--vp-c-text-2);
}
.efficiency-radar {
background: var(--vp-c-bg-soft);
border-radius: 12px;
padding: 2rem;
border: 1px solid var(--vp-c-divider);
}
.efficiency-radar h5 {
margin: 0 0 2rem 0;
text-align: center;
color: var(--vp-c-text-1);
font-size: 1.2rem;
}
.radar-chart {
position: relative;
width: 100%;
height: 400px;
background: var(--vp-c-bg);
border-radius: 8px;
margin-bottom: 1.5rem;
}
.radar-grid {
position: relative;
width: 100%;
height: 100%;
}
.radar-point {
position: absolute;
transform: translate(-50%, -50%);
cursor: pointer;
transition: all 0.3s ease;
}
.radar-point:hover {
transform: translate(-50%, -50%) scale(1.2);
}
.point-label {
position: absolute;
top: -25px;
left: 50%;
transform: translateX(-50%);
white-space: nowrap;
font-weight: 600;
font-size: 0.85rem;
color: var(--vp-c-text-1);
background: var(--vp-c-bg-soft);
padding: 0.25rem 0.5rem;
border-radius: 4px;
}
.point-dot {
width: 12px;
height: 12px;
background: var(--vp-c-brand);
border-radius: 50%;
box-shadow: 0 2px 8px rgba(59, 130, 246, 0.5);
}
.radar-legend {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1rem;
}
.legend-item {
display: flex;
align-items: center;
gap: 0.5rem;
font-size: 0.85rem;
color: var(--vp-c-text-2);
}
.legend-dot {
width: 10px;
height: 10px;
background: var(--vp-c-brand);
border-radius: 50%;
}
@media (max-width: 768px) {
.metrics-grid {
grid-template-columns: 1fr;
}
.bar-label {
min-width: 55px;
font-size: 0.75rem;
}
.efficiency-radar {
padding: 1rem;
}
.radar-chart {
height: 300px;
}
}
</style>
@@ -0,0 +1,290 @@
<template>
<div class="language-comparison-demo">
<div class="comparison-table-wrapper">
<table class="comparison-table">
<thead>
<tr>
<th>维度</th>
<th v-for="lang in languages" :key="lang.name" class="lang-col">
{{ lang.name }}
</th>
</tr>
</thead>
<tbody>
<tr v-for="dimension in dimensions" :key="dimension.key">
<td class="dimension-label">{{ dimension.label }}</td>
<td v-for="lang in languages" :key="lang.name" class="score-cell">
<div class="score-bar">
<div
class="score-fill"
:class="`score-${dimension.key}`"
:style="{ width: getScore(lang.name, dimension.key) + '%' }"
>
<span class="score-text">{{
getScore(lang.name, dimension.key)
}}</span>
</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<div class="insight-panel">
<h4>💡 洞察分析</h4>
<div class="insight-content">
<div class="insight-item">
<strong>性能王者</strong>
<span>C++ Rust 在性能方面遥遥领先但学习曲线极其陡峭</span>
</div>
<div class="insight-item">
<strong>开发效率</strong>
<span
>Python Ruby 在快速开发方面无与伦比适合原型和初创公司</span
>
</div>
<div class="insight-item">
<strong>生态成熟度</strong>
<span
>JavaPythonNode.js 拥有最成熟的生态系统库和框架丰富</span
>
</div>
<div class="insight-item">
<strong>学习曲线</strong>
<span
>PythonRubyGo 最容易上手Rust C++ 需要较长时间学习</span
>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
const languages = [
{ name: 'Java' },
{ name: 'Python' },
{ name: 'Go' },
{ name: 'Node.js' },
{ name: 'Rust' },
{ name: 'C++' }
]
const dimensions = [
{ key: 'performance', label: '性能' },
{ key: 'efficiency', label: '开发效率' },
{ key: 'ecosystem', label: '生态成熟度' },
{ key: 'learning', label: '学习曲线' },
{ key: 'concurrency', label: '并发能力' },
{ key: 'memory', label: '内存管理' }
]
const scores = {
Java: {
performance: 75,
efficiency: 60,
ecosystem: 95,
learning: 40,
concurrency: 80,
memory: 70
},
Python: {
performance: 30,
efficiency: 95,
ecosystem: 95,
learning: 95,
concurrency: 30,
memory: 40
},
Go: {
performance: 90,
efficiency: 85,
ecosystem: 75,
learning: 80,
concurrency: 95,
memory: 85
},
'Node.js': {
performance: 70,
efficiency: 85,
ecosystem: 95,
learning: 75,
concurrency: 85,
memory: 75
},
Rust: {
performance: 95,
efficiency: 40,
ecosystem: 70,
learning: 20,
concurrency: 90,
memory: 98
},
'C++': {
performance: 98,
efficiency: 35,
ecosystem: 90,
learning: 25,
concurrency: 85,
memory: 70
}
}
const getScore = (lang, dimension) => {
return scores[lang][dimension]
}
</script>
<style scoped>
.language-comparison-demo {
background: var(--vp-c-bg);
border-radius: 12px;
padding: 2rem;
margin: 2rem 0;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.05);
border: 1px solid var(--vp-c-divider);
}
.comparison-table-wrapper {
overflow-x: auto;
margin-bottom: 2rem;
}
.comparison-table {
width: 100%;
border-collapse: collapse;
min-width: 600px;
}
.comparison-table th {
background: var(--vp-c-bg-soft);
padding: 1rem;
text-align: center;
font-weight: 600;
color: var(--vp-c-text-1);
border-bottom: 2px solid var(--vp-c-divider);
}
.comparison-table th.lang-col {
color: var(--vp-c-brand);
font-size: 1.1rem;
}
.comparison-table td {
padding: 1rem;
border-bottom: 1px solid var(--vp-c-divider);
}
.dimension-label {
font-weight: 600;
color: var(--vp-c-text-1);
white-space: nowrap;
}
.score-cell {
padding: 0.75rem;
}
.score-bar {
height: 30px;
background: var(--vp-c-bg-soft);
border-radius: 6px;
overflow: hidden;
position: relative;
}
.score-fill {
height: 100%;
display: flex;
align-items: center;
justify-content: flex-end;
padding-right: 0.5rem;
transition: width 0.5s ease;
color: white;
font-weight: 600;
font-size: 0.85rem;
}
.score-performance {
background: linear-gradient(90deg, #fbbf24, #f59e0b);
}
.score-efficiency {
background: linear-gradient(90deg, #34d399, #10b981);
}
.score-ecosystem {
background: linear-gradient(90deg, #60a5fa, #3b82f6);
}
.score-learning {
background: linear-gradient(90deg, #f472b6, #ec4899);
}
.score-concurrency {
background: linear-gradient(90deg, #a78bfa, #8b5cf6);
}
.score-memory {
background: linear-gradient(90deg, #fb923c, #ea580c);
}
.score-text {
color: white;
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
}
.insight-panel {
background: var(--vp-c-bg-soft);
border-radius: 8px;
padding: 1.5rem;
border-left: 4px solid var(--vp-c-brand);
}
.insight-panel h4 {
margin-top: 0;
margin-bottom: 1rem;
color: var(--vp-c-brand);
font-size: 1.2rem;
}
.insight-content {
display: flex;
flex-direction: column;
gap: 1rem;
}
.insight-item {
display: flex;
gap: 0.5rem;
font-size: 0.95rem;
line-height: 1.6;
}
.insight-item strong {
color: var(--vp-c-text-1);
white-space: nowrap;
}
.insight-item span {
color: var(--vp-c-text-2);
}
@media (max-width: 768px) {
.comparison-table-wrapper {
font-size: 0.85rem;
}
.comparison-table th,
.comparison-table td {
padding: 0.5rem;
}
.insight-content {
font-size: 0.9rem;
}
}
</style>
@@ -0,0 +1,980 @@
<template>
<div class="language-ecosystem-demo">
<div class="demo-header">
<h4>生态系统对比</h4>
<p class="subtitle">不同语言的包管理器框架和社区活跃度</p>
</div>
<div class="ecosystem-tabs">
<button
v-for="tab in tabs"
:key="tab.id"
class="tab-btn"
:class="{ active: selectedTab === tab.id }"
@click="selectedTab = tab.id"
>
{{ tab.label }}
</button>
</div>
<transition name="fade" mode="out-in">
<div :key="selectedTab" class="tab-content">
<!-- Package Managers -->
<div v-if="selectedTab === 'packages'" class="packages-section">
<div class="packages-grid">
<div
v-for="pkg in packageManagers"
:key="pkg.name"
class="package-card"
>
<div class="pkg-header">
<span class="pkg-icon">{{ pkg.icon }}</span>
<div class="pkg-info">
<h5>{{ pkg.name }}</h5>
<span class="pkg-lang">{{ pkg.language }}</span>
</div>
</div>
<div class="pkg-stats">
<div class="stat">
<span class="stat-label">包数量</span>
<span class="stat-value">{{ formatNumber(pkg.count) }}</span>
</div>
<div class="stat">
<span class="stat-label">周下载量</span>
<span class="stat-value">{{ formatDownloads(pkg.downloads) }}</span>
</div>
</div>
<div class="pkg-command">
<code>{{ pkg.command }}</code>
</div>
<div class="pkg-features">
<div
v-for="feature in pkg.features"
:key="feature"
class="feature-tag"
>
{{ feature }}
</div>
</div>
</div>
</div>
</div>
<!-- Web Frameworks -->
<div v-else-if="selectedTab === 'frameworks'" class="frameworks-section">
<div class="frameworks-table-wrapper">
<table class="frameworks-table">
<thead>
<tr>
<th>框架</th>
<th>语言</th>
<th>性能</th>
<th>学习曲线</th>
<th>特点</th>
<th>适用场景</th>
</tr>
</thead>
<tbody>
<tr v-for="fw in frameworks" :key="fw.name">
<td class="fw-name">
<span class="fw-icon">{{ fw.icon }}</span>
{{ fw.name }}
</td>
<td>{{ fw.language }}</td>
<td>
<div class="rating-bar">
<div
class="rating-fill"
:style="{ width: fw.performance + '%' }"
></div>
</div>
</td>
<td>
<div class="rating-bar learning">
<div
class="rating-fill"
:style="{ width: fw.learning + '%' }"
></div>
</div>
</td>
<td>
<div class="tags">
<span
v-for="tag in fw.tags"
:key="tag"
class="tag"
:class="`tag-${tag.type}`"
>
{{ tag.label }}
</span>
</div>
</td>
<td>{{ fw.useCase }}</td>
</tr>
</tbody>
</table>
</div>
</div>
<!-- Community -->
<div v-else-if="selectedTab === 'community'" class="community-section">
<div class="community-metrics">
<div class="metric-card">
<div class="metric-header">
<span class="metric-icon">📦</span>
<h5>GitHub Stars</h5>
</div>
<div class="metric-chart">
<div
v-for="lang in communityStats"
:key="lang.name"
class="chart-bar"
>
<div class="bar-label">{{ lang.name }}</div>
<div class="bar-container">
<div
class="bar-fill"
:style="{ width: (lang.stars / 100) + '%' }"
>
<span class="bar-value">{{ lang.stars }}M</span>
</div>
</div>
</div>
</div>
</div>
<div class="metric-card">
<div class="metric-header">
<span class="metric-icon">💬</span>
<h5>Stack Overflow 问题</h5>
</div>
<div class="metric-chart">
<div
v-for="lang in communityStats"
:key="lang.name"
class="chart-bar"
>
<div class="bar-label">{{ lang.name }}</div>
<div class="bar-container">
<div
class="bar-fill questions"
:style="{ width: (lang.questions / 30) + '%' }"
>
<span class="bar-value">{{ lang.questions }}M</span>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="community-insights">
<h5>社区活跃度分析</h5>
<div class="insight-grid">
<div class="insight-card">
<h6>最活跃</h6>
<p>JavaScript/Node.js 社区最活跃NPM 每周新增数万个包问题响应速度最快</p>
</div>
<div class="insight-card">
<h6>最专业</h6>
<p>Java 社区最专业企业级问题讨论深入Stack Overflow 质量最高</p>
</div>
<div class="insight-card">
<h6>增长最快</h6>
<p>Rust Go 社区增长最快新一代开发者涌入问题讨论质量高</p>
</div>
<div class="insight-card">
<h6>最友好</h6>
<p>Python Ruby 社区对新手最友好问题回复耐心文档详尽</p>
</div>
</div>
</div>
</div>
<!-- Learning Resources -->
<div v-else-if="selectedTab === 'learning'" class="learning-section">
<div class="resources-grid">
<div
v-for="resource in learningResources"
:key="resource.language"
class="resource-card"
>
<div class="resource-header">
<span class="resource-icon">{{ resource.icon }}</span>
<h5>{{ resource.language }}</h5>
</div>
<div class="resource-content">
<div class="resource-section">
<h6>官方文档</h6>
<div class="doc-rating">
<span
v-for="i in 5"
:key="i"
class="star"
:class="{ filled: i <= resource.docQuality }"
>
</span>
</div>
<p class="doc-comment">{{ resource.docComment }}</p>
</div>
<div class="resource-section">
<h6>推荐书籍</h6>
<ul>
<li v-for="book in resource.books" :key="book">{{ book }}</li>
</ul>
</div>
<div class="resource-section">
<h6>在线课程</h6>
<div class="courses">
<span
v-for="course in resource.courses"
:key="course"
class="course-tag"
>
{{ course }}
</span>
</div>
</div>
<div class="resource-section">
<h6>学习曲线</h6>
<div class="learning-curve">
<div
class="curve-bar"
:style="{ width: resource.learningCurve + '%' }"
></div>
</div>
<p class="curve-label">{{ resource.curveLabel }}</p>
</div>
</div>
</div>
</div>
</div>
</div>
</transition>
</div>
</template>
<script setup>
import { ref } from 'vue'
const selectedTab = ref('packages')
const tabs = [
{ id: 'packages', label: '包管理器' },
{ id: 'frameworks', label: 'Web 框架' },
{ id: 'community', label: '社区活跃度' },
{ id: 'learning', label: '学习资源' }
]
const packageManagers = [
{
name: 'NPM',
icon: '💚',
language: 'Node.js',
count: 2000000,
downloads: '50B/week',
command: 'npm install express',
features: ['最大生态', '版本管理灵活', '依赖地狱风险']
},
{
name: 'PyPI',
icon: '🐍',
language: 'Python',
count: 500000,
downloads: '10B/week',
command: 'pip install django',
features: ['虚拟环境', '依赖管理清晰', '打包部署复杂']
},
{
name: 'Maven',
icon: '☕',
language: 'Java',
count: 300000,
downloads: '5B/week',
command: 'mvn install',
features: ['企业级', '依赖管理严格', 'XML 配置冗长']
},
{
name: 'Go Modules',
icon: '🐹',
language: 'Go',
count: 100000,
downloads: '500M/week',
command: 'go get github.com/gin-gonic/gin',
features: ['简洁', '无依赖地狱', '版本支持完善']
},
{
name: 'Cargo',
icon: '🦀',
language: 'Rust',
count: 100000,
downloads: '200M/week',
command: 'cargo add serde',
features: ['现代化', '构建工具集成', '编译时间长']
},
{
name: 'RubyGems',
icon: '💎',
language: 'Ruby',
count: 150000,
downloads: '300M/week',
command: 'gem install rails',
features: ['Bundler 管理', 'Gemfile 简洁', '版本冲突问题']
}
]
const frameworks = [
{
name: 'Express',
icon: '💚',
language: 'Node.js',
performance: 70,
learning: 90,
tags: [
{ type: 'success', label: '简洁' },
{ type: 'info', label: '灵活' }
],
useCase: '快速原型、API 服务'
},
{
name: 'Django',
icon: '🐍',
language: 'Python',
performance: 40,
learning: 85,
tags: [
{ type: 'success', label: '大而全' },
{ type: 'info', label: 'ORM' }
],
useCase: '数据驱动应用、快速开发'
},
{
name: 'Spring Boot',
icon: '☕',
language: 'Java',
performance: 75,
learning: 50,
tags: [
{ type: 'success', label: '企业级' },
{ type: 'warning', label: '复杂' }
],
useCase: '企业级应用、微服务'
},
{
name: 'Gin',
icon: '🐹',
language: 'Go',
performance: 95,
learning: 80,
tags: [
{ type: 'success', label: '高性能' },
{ type: 'info', label: '轻量' }
],
useCase: '高性能 API、微服务'
},
{
name: 'Rails',
icon: '💎',
language: 'Ruby',
performance: 35,
learning: 85,
tags: [
{ type: 'success', label: '约定优于配置' },
{ type: 'info', label: 'MVC' }
],
useCase: '初创公司、快速迭代'
},
{
name: 'Flask',
icon: '🐍',
language: 'Python',
performance: 45,
learning: 95,
tags: [
{ type: 'success', label: '轻量' },
{ type: 'info', label: '灵活' }
],
useCase: '小型项目、学习'
},
{
name: 'FastAPI',
icon: '🐍',
language: 'Python',
performance: 65,
learning: 85,
tags: [
{ type: 'success', label: '异步' },
{ type: 'info', label: '类型安全' }
],
useCase: '现代 API、异步任务'
},
{
name: 'Actix',
icon: '🦀',
language: 'Rust',
performance: 98,
learning: 30,
tags: [
{ type: 'success', label: '极致性能' },
{ type: 'danger', label: '难学' }
],
useCase: '高性能服务、系统编程'
}
]
const communityStats = [
{ name: 'JavaScript', stars: 85, questions: 28 },
{ name: 'Python', stars: 75, questions: 25 },
{ name: 'Java', stars: 65, questions: 22 },
{ name: 'Go', stars: 55, questions: 8 },
{ name: 'Rust', stars: 60, questions: 5 },
{ name: 'Ruby', stars: 40, questions: 6 },
{ name: 'C#', stars: 50, questions: 12 },
{ name: 'C++', stars: 70, questions: 18 }
]
const learningResources = [
{
language: 'Python',
icon: '🐍',
docQuality: 5,
docComment: '官方文档极其详尽,教程丰富',
books: ['Fluent Python', 'Python Cookbook'],
courses: ['Coursera', 'edX', 'Udemy'],
learningCurve: 95,
curveLabel: '最简单'
},
{
language: 'Go',
icon: '🐹',
docQuality: 5,
docComment: '官方教程优秀,A Tour of Go 经典',
books: ['The Go Programming Language', 'Go in Action'],
courses: ['Udemy', 'Coursera', '官方文档'],
learningCurve: 80,
curveLabel: '简单'
},
{
language: 'JavaScript',
icon: '💚',
docQuality: 4,
docComment: 'MDN 文档权威,但碎片化',
books: ['Eloquent JavaScript', 'You Don\'t Know JS'],
courses: ['freeCodeCamp', 'Udemy', 'Codecademy'],
learningCurve: 75,
curveLabel: '中等'
},
{
language: 'Java',
icon: '☕',
docQuality: 4,
docComment: 'Oracle 官方文档完善,但冗长',
books: ['Effective Java', 'Java Concurrency'],
courses: ['Coursera', 'Udemy', 'Oracle 官方'],
learningCurve: 40,
curveLabel: '较难'
},
{
language: 'Rust',
icon: '🦀',
docQuality: 5,
docComment: 'The Rust Book 极其详细',
books: ['The Rust Programming Language', 'Rust in Action'],
courses: ['Udemy', 'Exercism', '官方文档'],
learningCurve: 20,
curveLabel: '极难'
},
{
language: 'C#',
icon: '💜',
docQuality: 5,
docComment: 'Microsoft 文档极其详细',
books: ['C# in Depth', 'Pro C#'],
courses: ['Microsoft Learn', 'Udemy', 'Pluralsight'],
learningCurve: 50,
curveLabel: '中等'
}
]
const formatNumber = (num) => {
if (num >= 1000000) return (num / 1000000).toFixed(1) + 'M+'
if (num >= 1000) return (num / 1000).toFixed(0) + 'K+'
return num.toString()
}
const formatDownloads = (downloads) => {
return downloads
}
</script>
<style scoped>
.language-ecosystem-demo {
background: var(--vp-c-bg);
border-radius: 12px;
padding: 2rem;
margin: 2rem 0;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.05);
border: 1px solid var(--vp-c-divider);
}
.demo-header {
text-align: center;
margin-bottom: 2rem;
}
.demo-header h4 {
margin: 0 0 0.5rem 0;
color: var(--vp-c-brand);
font-size: 1.5rem;
}
.subtitle {
margin: 0;
color: var(--vp-c-text-2);
font-size: 0.95rem;
}
.ecosystem-tabs {
display: flex;
gap: 0.5rem;
margin-bottom: 2rem;
overflow-x: auto;
padding-bottom: 0.5rem;
}
.tab-btn {
padding: 0.75rem 1.5rem;
background: var(--vp-c-bg-soft);
border: 2px solid transparent;
border-radius: 8px;
color: var(--vp-c-text-1);
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
white-space: nowrap;
}
.tab-btn:hover {
border-color: var(--vp-c-brand);
}
.tab-btn.active {
background: var(--vp-c-brand);
color: white;
border-color: var(--vp-c-brand);
}
.tab-content {
animation: fade-in 0.3s ease;
}
.packages-grid,
.resources-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 1.5rem;
}
.package-card,
.resource-card {
background: var(--vp-c-bg-soft);
border-radius: 12px;
padding: 1.5rem;
border: 1px solid var(--vp-c-divider);
transition: all 0.3s ease;
}
.package-card:hover,
.resource-card:hover {
transform: translateY(-3px);
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.1);
}
.pkg-header,
.resource-header {
display: flex;
align-items: center;
gap: 1rem;
margin-bottom: 1.5rem;
}
.pkg-icon,
.resource-icon {
font-size: 2.5rem;
}
.pkg-info h5,
.resource-header h5 {
margin: 0;
color: var(--vp-c-text-1);
font-size: 1.2rem;
}
.pkg-lang {
font-size: 0.85rem;
color: var(--vp-c-text-2);
}
.pkg-stats {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1rem;
margin-bottom: 1rem;
}
.stat {
display: flex;
flex-direction: column;
gap: 0.25rem;
}
.stat-label {
font-size: 0.75rem;
color: var(--vp-c-text-2);
}
.stat-value {
font-size: 1rem;
font-weight: 600;
color: var(--vp-c-brand);
}
.pkg-command {
background: #1e1e1e;
border-radius: 6px;
padding: 0.75rem;
margin-bottom: 1rem;
}
.pkg-command code {
color: #4ec9b0;
font-family: 'Monaco', 'Menlo', monospace;
font-size: 0.85rem;
}
.pkg-features,
.courses {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}
.feature-tag,
.course-tag {
padding: 0.25rem 0.75rem;
background: var(--vp-c-bg);
border-radius: 12px;
font-size: 0.75rem;
color: var(--vp-c-text-2);
}
.frameworks-table-wrapper {
overflow-x: auto;
}
.frameworks-table {
width: 100%;
border-collapse: collapse;
}
.frameworks-table th {
background: var(--vp-c-bg-soft);
padding: 1rem;
text-align: left;
font-weight: 600;
color: var(--vp-c-text-1);
border-bottom: 2px solid var(--vp-c-divider);
}
.frameworks-table td {
padding: 1rem;
border-bottom: 1px solid var(--vp-c-divider);
}
.fw-name {
font-weight: 600;
color: var(--vp-c-text-1);
}
.fw-icon {
margin-right: 0.5rem;
}
.rating-bar {
width: 100px;
height: 8px;
background: var(--vp-c-bg);
border-radius: 4px;
overflow: hidden;
}
.rating-fill {
height: 100%;
background: linear-gradient(90deg, var(--vp-c-brand), #8b5cf6);
transition: width 0.5s ease;
}
.rating-bar.learning .rating-fill {
background: linear-gradient(90deg, #10b981, #059669);
}
.tags {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}
.tag {
padding: 0.25rem 0.75rem;
border-radius: 12px;
font-size: 0.75rem;
font-weight: 600;
}
.tag-success {
background: #dcfce7;
color: #15803d;
}
.tag-info {
background: #e0e7ff;
color: #4338ca;
}
.tag-warning {
background: #fef3c7;
color: #b45309;
}
.tag-danger {
background: #fee2e2;
color: #b91c1c;
}
.community-metrics {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 2rem;
margin-bottom: 2rem;
}
.metric-card {
background: var(--vp-c-bg-soft);
border-radius: 12px;
padding: 1.5rem;
border: 1px solid var(--vp-c-divider);
}
.metric-header {
display: flex;
align-items: center;
gap: 0.75rem;
margin-bottom: 1.5rem;
}
.metric-icon {
font-size: 2rem;
}
.metric-header h5 {
margin: 0;
color: var(--vp-c-text-1);
font-size: 1.1rem;
}
.metric-chart {
display: flex;
flex-direction: column;
gap: 0.75rem;
}
.chart-bar {
display: flex;
align-items: center;
gap: 1rem;
}
.bar-label {
min-width: 80px;
font-weight: 600;
font-size: 0.85rem;
color: var(--vp-c-text-1);
}
.bar-container {
flex: 1;
height: 24px;
background: var(--vp-c-bg);
border-radius: 4px;
overflow: hidden;
}
.bar-fill {
height: 100%;
display: flex;
align-items: center;
justify-content: flex-end;
padding-right: 0.5rem;
background: linear-gradient(90deg, var(--vp-c-brand), #8b5cf6);
color: white;
font-weight: 600;
font-size: 0.75rem;
transition: width 0.5s ease;
}
.bar-fill.questions {
background: linear-gradient(90deg, #f59e0b, #d97706);
}
.community-insights h5 {
margin: 0 0 1.5rem 0;
color: var(--vp-c-text-1);
font-size: 1.2rem;
}
.insight-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 1.5rem;
}
.insight-card {
background: var(--vp-c-bg-soft);
border-radius: 8px;
padding: 1.5rem;
border-left: 4px solid var(--vp-c-brand);
}
.insight-card h6 {
margin: 0 0 0.75rem 0;
color: var(--vp-c-brand);
font-size: 1rem;
}
.insight-card p {
margin: 0;
font-size: 0.9rem;
line-height: 1.6;
color: var(--vp-c-text-2);
}
.resource-content {
display: flex;
flex-direction: column;
gap: 1rem;
}
.resource-section h6 {
margin: 0 0 0.75rem 0;
color: var(--vp-c-text-1);
font-size: 0.95rem;
}
.doc-rating {
display: flex;
gap: 0.25rem;
margin-bottom: 0.5rem;
}
.star {
color: var(--vp-c-divider);
}
.star.filled {
color: #fbbf24;
}
.doc-comment {
margin: 0;
font-size: 0.85rem;
color: var(--vp-c-text-2);
font-style: italic;
}
.resource-section ul {
list-style: none;
padding: 0;
margin: 0;
}
.resource-section li {
padding: 0.25rem 0;
font-size: 0.85rem;
color: var(--vp-c-text-2);
position: relative;
padding-left: 1rem;
}
.resource-section li::before {
content: '▸';
position: absolute;
left: 0;
color: var(--vp-c-brand);
}
.learning-curve {
height: 8px;
background: var(--vp-c-bg);
border-radius: 4px;
overflow: hidden;
margin-bottom: 0.5rem;
}
.curve-bar {
height: 100%;
background: linear-gradient(90deg, #10b981, #059669);
transition: width 0.5s ease;
}
.curve-label {
margin: 0;
font-size: 0.85rem;
color: var(--vp-c-text-2);
}
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.3s ease;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
@keyframes fade-in {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@media (max-width: 768px) {
.ecosystem-tabs {
font-size: 0.85rem;
}
.packages-grid,
.resources-grid {
grid-template-columns: 1fr;
}
.community-metrics {
grid-template-columns: 1fr;
}
.frameworks-table {
font-size: 0.85rem;
}
.frameworks-table th,
.frameworks-table td {
padding: 0.5rem;
}
}
</style>
@@ -0,0 +1,575 @@
<template>
<div class="language-selector-demo">
<div class="selector-header">
<h4>🎯 语言选择器</h4>
<p class="subtitle">根据项目需求选择最适合的后端语言</p>
</div>
<div class="selection-flow">
<!-- Step 1: Project Type -->
<div class="step-card" :class="{ active: currentStep === 1 }">
<div class="step-number">1</div>
<h5>项目类型</h5>
<div class="options-grid">
<button
v-for="option in projectTypes"
:key="option.id"
class="option-btn"
:class="{ selected: answers.projectType === option.id }"
@click="selectProjectType(option.id)"
>
<span class="option-icon">{{ option.icon }}</span>
<span class="option-label">{{ option.label }}</span>
</button>
</div>
</div>
<!-- Step 2: Performance Requirement -->
<div
class="step-card"
:class="{ active: currentStep === 2, disabled: !answers.projectType }"
>
<div class="step-number">2</div>
<h5>性能要求</h5>
<div class="options-grid">
<button
v-for="option in performanceLevels"
:key="option.id"
class="option-btn"
:class="{ selected: answers.performance === option.id }"
@click="selectPerformance(option.id)"
>
<span class="option-icon">{{ option.icon }}</span>
<span class="option-label">{{ option.label }}</span>
<span class="option-desc">{{ option.desc }}</span>
</button>
</div>
</div>
<!-- Step 3: Team Background -->
<div
class="step-card"
:class="{
active: currentStep === 3,
disabled: !answers.performance
}"
>
<div class="step-number">3</div>
<h5>团队背景</h5>
<div class="options-grid">
<button
v-for="option in teamBackgrounds"
:key="option.id"
class="option-btn"
:class="{ selected: answers.team === option.id }"
@click="selectTeam(option.id)"
>
<span class="option-icon">{{ option.icon }}</span>
<span class="option-label">{{ option.label }}</span>
</button>
</div>
</div>
<!-- Step 4: Time to Market -->
<div
class="step-card"
:class="{ active: currentStep === 4, disabled: !answers.team }"
>
<div class="step-number">4</div>
<h5>上市时间</h5>
<div class="options-grid">
<button
v-for="option in timeConstraints"
:key="option.id"
class="option-btn"
:class="{ selected: answers.time === option.id }"
@click="selectTime(option.id)"
>
<span class="option-icon">{{ option.icon }}</span>
<span class="option-label">{{ option.label }}</span>
<span class="option-desc">{{ option.desc }}</span>
</button>
</div>
</div>
</div>
<!-- Recommendation -->
<transition name="result">
<div v-if="recommendation" class="recommendation-panel">
<h5>🎉 推荐语言</h5>
<div class="recommendation-card">
<div class="rec-language">
<span class="rec-icon">{{ recommendation.icon }}</span>
<span class="rec-name">{{ recommendation.language }}</span>
</div>
<div class="rec-reason">
<h6>选择理由</h6>
<p>{{ recommendation.reason }}</p>
</div>
<div class="rec-alternatives">
<h6>备选方案</h6>
<div class="alt-list">
<span
v-for="alt in recommendation.alternatives"
:key="alt"
class="alt-tag"
>
{{ alt }}
</span>
</div>
</div>
</div>
<button class="reset-btn" @click="reset">🔄 重新选择</button>
</div>
</transition>
</div>
</template>
<script setup>
import { ref, computed } from 'vue'
const currentStep = ref(1)
const answers = ref({
projectType: null,
performance: null,
team: null,
time: null
})
const projectTypes = [
{ id: 'web', icon: '🌐', label: 'Web 应用' },
{ id: 'api', icon: '🔌', label: 'API 服务' },
{ id: 'microservice', icon: '⚙️', label: '微服务' },
{ id: 'ai', icon: '🤖', label: 'AI/ML' },
{ id: 'game', icon: '🎮', label: '游戏' },
{ id: 'system', icon: '💻', label: '系统编程' }
]
const performanceLevels = [
{ id: 'extreme', icon: '⚡', label: '极致性能', desc: '每秒百万级请求' },
{ id: 'high', icon: '🚀', label: '高性能', desc: '每秒十万级请求' },
{ id: 'medium', icon: '📊', label: '中等性能', desc: '每秒万级请求' },
{ id: 'low', icon: '🐌', label: '性能不敏感', desc: '快速开发优先' }
]
const teamBackgrounds = [
{ id: 'frontend', icon: '💚', label: '前端团队' },
{ id: 'python', icon: '🐍', label: 'Python 背景' },
{ id: 'java', icon: '☕', label: 'Java 背景' },
{ id: 'mixed', icon: '👥', label: '混合团队' },
{ id: 'new', icon: '🆕', label: '新团队' }
]
const timeConstraints = [
{ id: 'urgent', icon: '🔥', label: '紧急', desc: '1-2 周上线' },
{ id: 'normal', icon: '📅', label: '正常', desc: '1-2 个月' },
{ id: 'flexible', icon: '🎯', label: '灵活', desc: '3 个月以上' }
]
const recommendation = computed(() => {
if (!answers.value.projectType || !answers.value.performance || !answers.value.team || !answers.value.time) {
return null
}
const { projectType, performance, team, time } = answers.value
// 决策逻辑
if (projectType === 'ai') {
return {
language: 'Python',
icon: '🐍',
reason: 'AI/ML 领域的绝对统治地位,生态无与伦比(NumPy、PyTorch、TensorFlow)。虽然性能不如 C++/Rust,但 95% 的 AI 项目都在用 Python。',
alternatives: ['C++ (模型部署)', 'Julia (科学计算)']
}
}
if (projectType === 'game') {
return {
language: 'C++',
icon: '⚡',
reason: '游戏开发的行业标准(Unreal Engine)。极致性能,底层控制力强。如果使用 Unity 引擎,则 C# 是首选。',
alternatives: ['C# (Unity)', 'Rust (独立游戏)']
}
}
if (projectType === 'system') {
if (performance === 'extreme') {
return {
language: 'Rust',
icon: '🦀',
reason: '内存安全 + 极致性能,现代化系统语言。虽然学习曲线陡峭,但编译时保证无内存泄漏,适合长期维护的基础设施。',
alternatives: ['C++ (传统选择)', 'Go (云原生)']
}
}
return {
language: 'Go',
icon: '🐹',
reason: '云原生时代的宠儿(Docker、K8s 都是 Go 写的)。简洁语法 + 原生并发 + 快速编译,非常适合系统编程和 DevOps 工具。',
alternatives: ['Rust (更安全)', 'C++ (更成熟)']
}
}
if (projectType === 'microservice') {
if (performance === 'extreme' || performance === 'high') {
return {
language: 'Go',
icon: '🐹',
reason: '云原生的首选语言。Goroutine 轻量级并发可轻松处理百万级请求,编译后的单一可执行文件部署极其简单。',
alternatives: ['Java (Spring Cloud)', 'Rust (极致性能)']
}
}
return {
language: 'Node.js',
icon: '💚',
reason: '前后端统一,减少语言切换成本。NPM 生态丰富,适合 I/O 密集型的微服务。',
alternatives: ['Go (更高性能)', 'Python (快速开发)']
}
}
if (team === 'frontend') {
return {
language: 'Node.js',
icon: '💚',
reason: '前端团队零学习成本,TypeScript 提供类型安全。全栈开发减少沟通成本,适合快速迭代和 MVP 开发。',
alternatives: ['Go (后端性能优化)', 'TypeScript (类型安全)']
}
}
if (team === 'python') {
return {
language: 'Python',
icon: '🐍',
reason: '利用团队现有技能,快速开发。Django/FastAPI 生态成熟,适合数据驱动的 Web 应用。',
alternatives: ['Go (性能提升)', 'Node.js (全栈)']
}
}
if (team === 'java') {
return {
language: 'Java',
icon: '☕',
reason: '企业级开发的最佳选择。Spring Boot 生态极其成熟,团队熟悉度高,维护成本最低。',
alternatives: ['Go (云原生)', 'Kotlin (更现代)']
}
}
if (time === 'urgent') {
if (projectType === 'web' || projectType === 'api') {
return {
language: 'Python',
icon: '🐍',
reason: '开发速度最快的语言。FastAPI/Django 让你在几天内就能搭建起完整的 Web 应用,适合快速验证想法和 MVP。',
alternatives: ['Ruby (Rails)', 'Node.js (全栈)']
}
}
}
// 默认推荐
if (performance === 'extreme') {
return {
language: 'Go',
icon: '🐹',
reason: '高性能 + 简洁语法 + 快速开发的最佳平衡点。Goroutine 并发模型让处理高并发变得简单,而不会像 Java 那么复杂。',
alternatives: ['Rust (更安全)', 'C++ (更极致)']
}
}
if (performance === 'high') {
return {
language: 'Go',
icon: '🐹',
reason: '云原生时代的高性能语言。相比 Java 更简洁,相比 Node.js 性能更好,相比 C++ 更容易维护。',
alternatives: ['Java (更成熟)', 'Node.js (更灵活)']
}
}
// Default: Node.js or Python
return {
language: 'Node.js',
icon: '💚',
reason: '前后端统一,生态庞大,适合大多数 Web 应用和 API 服务。NPM 拥有世界最大的包仓库,几乎任何功能都能找到现成的库。',
alternatives: ['Go (更高性能)', 'Python (更简单)']
}
})
const selectProjectType = (value) => {
answers.value.projectType = value
currentStep.value = 2
}
const selectPerformance = (value) => {
answers.value.performance = value
currentStep.value = 3
}
const selectTeam = (value) => {
answers.value.team = value
currentStep.value = 4
}
const selectTime = (value) => {
answers.value.time = value
currentStep.value = 5
}
const reset = () => {
answers.value = {
projectType: null,
performance: null,
team: null,
time: null
}
currentStep.value = 1
}
</script>
<style scoped>
.language-selector-demo {
background: var(--vp-c-bg);
border-radius: 12px;
padding: 2rem;
margin: 2rem 0;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.05);
border: 1px solid var(--vp-c-divider);
}
.selector-header {
text-align: center;
margin-bottom: 3rem;
}
.selector-header h4 {
margin: 0 0 0.5rem 0;
color: var(--vp-c-brand);
font-size: 1.5rem;
}
.subtitle {
margin: 0;
color: var(--vp-c-text-2);
font-size: 0.95rem;
}
.selection-flow {
display: flex;
flex-direction: column;
gap: 2rem;
}
.step-card {
background: var(--vp-c-bg-soft);
border: 2px solid var(--vp-c-divider);
border-radius: 12px;
padding: 2rem;
transition: all 0.3s ease;
}
.step-card.active {
border-color: var(--vp-c-brand);
box-shadow: 0 8px 30px rgba(59, 130, 246, 0.1);
}
.step-card.disabled {
opacity: 0.5;
pointer-events: none;
}
.step-number {
display: inline-block;
width: 32px;
height: 32px;
background: var(--vp-c-brand);
color: white;
border-radius: 50%;
text-align: center;
line-height: 32px;
font-weight: bold;
margin-bottom: 1rem;
}
.step-card h5 {
margin: 0 0 1.5rem 0;
color: var(--vp-c-text-1);
font-size: 1.2rem;
}
.options-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
gap: 1rem;
}
.option-btn {
display: flex;
flex-direction: column;
align-items: center;
gap: 0.5rem;
padding: 1.5rem 1rem;
background: var(--vp-c-bg);
border: 2px solid var(--vp-c-divider);
border-radius: 8px;
cursor: pointer;
transition: all 0.3s ease;
}
.option-btn:hover:not(.selected) {
border-color: var(--vp-c-brand);
transform: translateY(-3px);
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.15);
}
.option-btn.selected {
border-color: var(--vp-c-brand);
background: var(--vp-c-brand);
color: white;
}
.option-icon {
font-size: 2rem;
line-height: 1;
}
.option-label {
font-weight: 600;
font-size: 0.95rem;
}
.option-desc {
font-size: 0.75rem;
opacity: 0.8;
text-align: center;
}
.recommendation-panel {
margin-top: 3rem;
animation: slide-up 0.5s ease;
}
.recommendation-panel h5 {
text-align: center;
margin: 0 0 2rem 0;
color: var(--vp-c-brand);
font-size: 1.5rem;
}
.recommendation-card {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 16px;
padding: 2.5rem;
color: white;
box-shadow: 0 10px 40px rgba(102, 126, 234, 0.4);
}
.rec-language {
display: flex;
align-items: center;
justify-content: center;
gap: 1rem;
margin-bottom: 2rem;
}
.rec-icon {
font-size: 4rem;
line-height: 1;
}
.rec-name {
font-size: 2.5rem;
font-weight: bold;
}
.rec-reason,
.rec-alternatives {
background: rgba(255, 255, 255, 0.1);
border-radius: 12px;
padding: 1.5rem;
margin-bottom: 1.5rem;
backdrop-filter: blur(10px);
}
.rec-reason h6,
.rec-alternatives h6 {
margin: 0 0 1rem 0;
font-size: 1.1rem;
opacity: 0.9;
}
.rec-reason p {
margin: 0;
line-height: 1.7;
font-size: 0.95rem;
}
.alt-list {
display: flex;
flex-wrap: wrap;
gap: 0.75rem;
}
.alt-tag {
background: rgba(255, 255, 255, 0.2);
padding: 0.5rem 1rem;
border-radius: 20px;
font-size: 0.9rem;
font-weight: 600;
}
.reset-btn {
display: block;
width: 100%;
padding: 1rem;
background: white;
color: #667eea;
border: none;
border-radius: 8px;
font-size: 1rem;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
}
.reset-btn:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.15);
}
.result-enter-active,
.result-leave-active {
transition: all 0.5s ease;
}
.result-enter-from {
opacity: 0;
transform: translateY(30px);
}
.result-leave-to {
opacity: 0;
transform: translateY(-30px);
}
@keyframes slide-up {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@media (max-width: 768px) {
.options-grid {
grid-template-columns: repeat(2, 1fr);
}
.rec-name {
font-size: 2rem;
}
.rec-icon {
font-size: 3rem;
}
}
</style>
@@ -0,0 +1,386 @@
<template>
<div class="performance-benchmark-demo">
<div class="benchmark-controls">
<h4>性能基准测试</h4>
<div class="control-group">
<label>测试场景</label>
<select v-model="selectedScenario" @change="runBenchmark">
<option value="hello">Hello World (简单 HTTP)</option>
<option value="json">JSON 序列化</option>
<option value="db">数据库查询</option>
<option value="compute">CPU 密集计算</option>
</select>
</div>
<button class="run-btn" @click="runBenchmark" :disabled="isRunning">
{{ isRunning ? '测试中...' : '▶ 运行测试' }}
</button>
</div>
<div class="results-panel">
<div class="results-header">
<h5>测试结果Requests/Second</h5>
<div class="legend">
<span class="legend-item"
><span class="dot" style="background: #f59e0b"></span> 高性能</span
>
<span class="legend-item"
><span class="dot" style="background: #10b981"></span> 中等</span
>
<span class="legend-item"
><span class="dot" style="background: #6366f1"></span> 较低</span
>
</div>
</div>
<transition-group name="bar" tag="div" class="chart-container">
<div
v-for="result in sortedResults"
:key="result.language"
class="chart-bar-wrapper"
>
<div class="bar-label">{{ result.language }}</div>
<div class="bar-container">
<div
class="bar-fill"
:class="getBarClass(result.rps)"
:style="{ width: getBarWidth(result.rps) + '%' }"
>
<span class="bar-value">{{ formatRPS(result.rps) }}</span>
</div>
</div>
</div>
</transition-group>
</div>
<div class="explanation-panel">
<h5>💡 性能解释</h5>
<div class="explanation-content">
<p>{{ getCurrentExplanation() }}</p>
</div>
</div>
</div>
</template>
<script setup>
import { ref, computed } from 'vue'
const selectedScenario = ref('hello')
const isRunning = ref(false)
const benchmarkData = {
hello: {
'C++': { rps: 1500000, time: 0.5 },
Rust: { rps: 1200000, time: 0.6 },
Go: { rps: 1000000, time: 0.7 },
Java: { rps: 700000, time: 1.0 },
'Node.js': { rps: 800000, time: 0.9 },
Python: { rps: 200000, time: 2.5 },
Ruby: { rps: 150000, time: 3.0 },
PHP: { rps: 250000, time: 2.0 }
},
json: {
'C++': { rps: 800000, time: 1.0 },
Rust: { rps: 700000, time: 1.1 },
Go: { rps: 600000, time: 1.2 },
Java: { rps: 500000, time: 1.5 },
'Node.js': { rps: 450000, time: 1.6 },
Python: { rps: 150000, time: 4.0 },
Ruby: { rps: 120000, time: 5.0 },
PHP: { rps: 180000, time: 3.5 }
},
db: {
'C++': { rps: 300000, time: 2.5 },
Rust: { rps: 280000, time: 2.6 },
Go: { rps: 250000, time: 3.0 },
Java: { rps: 200000, time: 3.5 },
'Node.js': { rps: 220000, time: 3.2 },
Python: { rps: 80000, time: 8.0 },
Ruby: { rps: 70000, time: 9.0 },
PHP: { rps: 90000, time: 7.5 }
},
compute: {
'C++': { rps: 500000, time: 1.5 },
Rust: { rps: 480000, time: 1.6 },
Go: { rps: 400000, time: 2.0 },
Java: { rps: 350000, time: 2.3 },
'Node.js': { rps: 50000, time: 15.0 },
Python: { rps: 30000, time: 25.0 },
Ruby: { rps: 25000, time: 30.0 },
PHP: { rps: 35000, time: 20.0 }
}
}
const explanations = {
hello: '简单的 Hello World HTTP 响应测试。C++ 和 Rust 在这个测试中展现出接近硬件的性能优势。Go 和 Node.js 表现也很优秀,因为它们的 HTTP 栈经过高度优化。Python 和 Ruby 由于解释器开销,性能相对较低。',
json: 'JSON 序列化/反序列化测试。这个测试考验语言的 JSON 处理能力。C++ 和 Rust 依然领先,但 Node.js 的表现也不错(V8 引擎优化)。Python 的标准库 json 模块性能尚可,但比编译型语言慢很多。',
db: '模拟数据库查询(连接池 + 查询)。这个测试更接近真实应用。性能差距缩小了,因为瓶颈主要在数据库 I/O 而非语言本身。但依然能看到编译型语言(C++、Rust、Go)的优势。',
compute: 'CPU 密集型计算(斐波那契数列)。这个测试充分暴露了 Node.js 的短板:单线程 + V8 编译优化不如静态语言。Python 和 Ruby 表现最差,因为它们是解释型语言,且 GIL 限制了多线程性能。C++ 和 Rust 几乎是唯一选择。'
}
const currentResults = ref([])
const sortedResults = computed(() => {
return [...currentResults.value].sort((a, b) => b.rps - a.rps)
})
const runBenchmark = () => {
isRunning.value = true
currentResults.value = []
// 模拟测试延迟
setTimeout(() => {
const data = benchmarkData[selectedScenario.value]
currentResults.value = Object.entries(data).map(([language, stats]) => ({
language,
rps: stats.rps,
time: stats.time
}))
isRunning.value = false
}, 1000)
}
const getBarWidth = (rps) => {
const max = 1500000
return (rps / max) * 100
}
const getBarClass = (rps) => {
if (rps >= 800000) return 'bar-high'
if (rps >= 300000) return 'bar-medium'
return 'bar-low'
}
const formatRPS = (rps) => {
if (rps >= 1000000) return (rps / 1000000).toFixed(1) + 'M'
if (rps >= 1000) return (rps / 1000).toFixed(0) + 'K'
return rps.toString()
}
const getCurrentExplanation = () => {
return explanations[selectedScenario.value]
}
// 初始运行一次
runBenchmark()
</script>
<style scoped>
.performance-benchmark-demo {
background: var(--vp-c-bg);
border-radius: 12px;
padding: 2rem;
margin: 2rem 0;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.05);
border: 1px solid var(--vp-c-divider);
}
.benchmark-controls {
display: flex;
align-items: center;
gap: 1.5rem;
margin-bottom: 2rem;
flex-wrap: wrap;
}
.benchmark-controls h4 {
margin: 0;
color: var(--vp-c-brand);
font-size: 1.2rem;
}
.control-group {
display: flex;
align-items: center;
gap: 0.5rem;
}
.control-group label {
font-weight: 600;
color: var(--vp-c-text-1);
}
.control-group select {
padding: 0.5rem 1rem;
border: 1px solid var(--vp-c-divider);
border-radius: 6px;
background: var(--vp-c-bg);
color: var(--vp-c-text-1);
font-size: 0.9rem;
cursor: pointer;
}
.run-btn {
padding: 0.5rem 1.5rem;
background: var(--vp-c-brand);
color: white;
border: none;
border-radius: 6px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
}
.run-btn:hover:not(:disabled) {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.4);
}
.run-btn:disabled {
opacity: 0.6;
cursor: not-allowed;
}
.results-panel {
margin-bottom: 2rem;
}
.results-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 1.5rem;
flex-wrap: wrap;
gap: 1rem;
}
.results-header h5 {
margin: 0;
color: var(--vp-c-text-1);
font-size: 1.1rem;
}
.legend {
display: flex;
gap: 1rem;
font-size: 0.85rem;
}
.legend-item {
display: flex;
align-items: center;
gap: 0.3rem;
}
.dot {
width: 10px;
height: 10px;
border-radius: 50%;
}
.chart-container {
display: flex;
flex-direction: column;
gap: 1rem;
}
.chart-bar-wrapper {
display: flex;
align-items: center;
gap: 1rem;
}
.bar-label {
min-width: 80px;
font-weight: 600;
color: var(--vp-c-text-1);
font-size: 0.9rem;
}
.bar-container {
flex: 1;
height: 40px;
background: var(--vp-c-bg-soft);
border-radius: 8px;
overflow: hidden;
position: relative;
}
.bar-fill {
height: 100%;
display: flex;
align-items: center;
justify-content: flex-end;
padding-right: 1rem;
transition: width 0.8s ease-out;
color: white;
font-weight: 700;
font-size: 0.9rem;
}
.bar-high {
background: linear-gradient(90deg, #f59e0b, #d97706);
}
.bar-medium {
background: linear-gradient(90deg, #10b981, #059669);
}
.bar-low {
background: linear-gradient(90deg, #6366f1, #4f46e5);
}
.bar-enter-active,
.bar-leave-active {
transition: all 0.5s ease;
}
.bar-enter-from {
opacity: 0;
transform: translateX(-30px);
}
.bar-leave-to {
opacity: 0;
transform: translateX(30px);
}
.explanation-panel {
background: var(--vp-c-bg-soft);
border-radius: 8px;
padding: 1.5rem;
border-left: 4px solid var(--vp-c-brand);
}
.explanation-panel h5 {
margin-top: 0;
margin-bottom: 1rem;
color: var(--vp-c-brand);
font-size: 1.1rem;
}
.explanation-content p {
margin: 0;
color: var(--vp-c-text-2);
line-height: 1.7;
font-size: 0.95rem;
}
@media (max-width: 768px) {
.benchmark-controls {
flex-direction: column;
align-items: stretch;
}
.control-group {
flex: 1;
}
.run-btn {
width: 100%;
}
.results-header {
flex-direction: column;
align-items: flex-start;
}
.bar-label {
min-width: 60px;
font-size: 0.8rem;
}
.bar-value {
font-size: 0.8rem;
}
}
</style>
@@ -0,0 +1,471 @@
<template>
<div class="syntax-comparison-demo">
<div class="demo-header">
<h4>Hello World 语法对比</h4>
<p class="subtitle">同样的功能不同的实现方式</p>
</div>
<div class="language-selector">
<button
v-for="lang in languages"
:key="lang.name"
class="lang-btn"
:class="{ active: selectedLang === lang.name }"
@click="selectedLang = lang.name"
>
<span class="lang-icon">{{ lang.icon }}</span>
<span class="lang-name">{{ lang.name }}</span>
</button>
</div>
<transition name="fade" mode="out-in">
<div :key="selectedLang" class="code-display">
<div class="code-header">
<div class="window-controls">
<span class="control red"></span>
<span class="control yellow"></span>
<span class="control green"></span>
</div>
<div class="filename">{{ getFileName(selectedLang) }}</div>
</div>
<pre class="code-content"><code>{{ getCode(selectedLang) }}</code></pre>
<div class="code-stats">
<div class="stat-item">
<span class="stat-label">代码行数</span>
<span class="stat-value">{{ getLineCount(selectedLang) }} </span>
</div>
<div class="stat-item">
<span class="stat-label">字符数</span>
<span class="stat-value">{{ getCharCount(selectedLang) }} 字符</span>
</div>
<div class="stat-item">
<span class="stat-label">复杂度</span>
<span class="stat-value">{{ getComplexity(selectedLang) }}</span>
</div>
</div>
</div>
</transition>
<div class="analysis-panel">
<h5>💡 语法分析</h5>
<div class="analysis-content">
<p>{{ getAnalysis(selectedLang) }}</p>
</div>
</div>
<div class="complexity-chart">
<h5>代码复杂度对比</h5>
<div class="chart-bars">
<div
v-for="lang in languages"
:key="lang.name"
class="chart-bar-wrapper"
>
<div class="chart-label">{{ lang.name }}</div>
<div class="chart-bar">
<div
class="chart-fill"
:style="{ width: getComplexityWidth(lang.name) + '%' }"
></div>
</div>
<div class="chart-value">{{ getLineCount(lang.name) }} </div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
const selectedLang = ref('Python')
const languages = [
{ name: 'Python', icon: '🐍' },
{ name: 'Ruby', icon: '💎' },
{ name: 'Go', icon: '🐹' },
{ name: 'Node.js', icon: '💚' },
{ name: 'Java', icon: '☕' },
{ name: 'C#', icon: '💜' },
{ name: 'Rust', icon: '🦀' },
{ name: 'C++', icon: '⚡' }
]
const codes = {
Python: {
code: `print("Hello, World!")`,
filename: 'hello.py',
complexity: '极简'
},
Ruby: {
code: `puts "Hello, World!"`,
filename: 'hello.rb',
complexity: '极简'
},
Go: {
code: `package main
import "fmt"
func main() {
fmt.Println("Hello, World!")
}`,
filename: 'hello.go',
complexity: '简洁'
},
'Node.js': {
code: `console.log("Hello, World!");`,
filename: 'hello.js',
complexity: '极简'
},
Java: {
code: `public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}`,
filename: 'HelloWorld.java',
complexity: '冗长'
},
"C#": {
code: `using System;
class Program {
static void Main() {
Console.WriteLine("Hello, World!");
}
}`,
filename: 'Program.cs',
complexity: '冗长'
},
Rust: {
code: `fn main() {
println!("Hello, World!");
}`,
filename: 'main.rs',
complexity: '简洁'
},
'C++': {
code: `#include <iostream>
int main() {
std::cout << "Hello, World!" << std::endl;
return 0;
}`,
filename: 'hello.cpp',
complexity: '中等'
}
}
const analyses = {
Python: 'Python 的语法极其简洁,只有一行代码。这也是为什么它被称为"伪代码语言"——读起来就像英语一样自然。没有任何样板代码,直接表达意图。',
Ruby: 'Ruby 受 Perl 影响,语法非常优雅。puts 是 "put string" 的缩写,字符串不需要括号(虽然可以加)。Ruby 哲学是"程序员快乐至上"。',
Go: 'Go 的语法虽然比 Python 冗长,但非常清晰。package main、import、func main() 都是必要的显式声明,这让代码更容易理解和维护。',
'Node.js': 'Node.js 使用 JavaScript,语法简单直接。console.log() 是浏览器和 Node.js 通用的输出方式。前端开发者零学习成本。',
Java: 'Java 是典型的"仪式感"语言。class、public static void main、String[] args 都是必须的样板代码。虽然冗长,但结构清晰,适合大型项目。',
'C#': 'C# 和 Java 非常相似,同样需要 class 和 Main 方法。using System 类似 Java 的 import,但更现代一些。.NET Core 后跨平台能力大幅提升。',
Rust: 'Rust 的 fn main() 和 println! 宏看起来简洁,但 println! 后面的 ! 表示这是一个宏(不是函数)。Rust 的简洁来自于零成本抽象的设计哲学。',
'C++': 'C++ 需要 #include 头文件,std::cout 使用流操作符 <<return 0 表示程序成功退出。虽然比 C 语言简洁(printf),但依然保留了很多底层细节。'
}
const getCode = (lang) => {
return codes[lang].code
}
const getFileName = (lang) => {
return codes[lang].filename
}
const getLineCount = (lang) => {
return codes[lang].code.split('\n').length
}
const getCharCount = (lang) => {
return codes[lang].code.replace(/\s/g, '').length
}
const getComplexity = (lang) => {
return codes[lang].complexity
}
const getAnalysis = (lang) => {
return analyses[lang]
}
const getComplexityWidth = (lang) => {
const max = 10 // Java is the longest
const lines = getLineCount(lang)
return (lines / max) * 100
}
</script>
<style scoped>
.syntax-comparison-demo {
background: var(--vp-c-bg);
border-radius: 12px;
padding: 2rem;
margin: 2rem 0;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.05);
border: 1px solid var(--vp-c-divider);
}
.demo-header {
text-align: center;
margin-bottom: 2rem;
}
.demo-header h4 {
margin: 0 0 0.5rem 0;
color: var(--vp-c-brand);
font-size: 1.5rem;
}
.subtitle {
margin: 0;
color: var(--vp-c-text-2);
font-size: 0.95rem;
}
.language-selector {
display: flex;
flex-wrap: wrap;
gap: 0.75rem;
margin-bottom: 2rem;
justify-content: center;
}
.lang-btn {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.75rem 1.25rem;
border: 2px solid var(--vp-c-divider);
border-radius: 8px;
background: var(--vp-c-bg);
cursor: pointer;
transition: all 0.3s ease;
font-weight: 600;
color: var(--vp-c-text-1);
}
.lang-btn:hover {
border-color: var(--vp-c-brand);
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.2);
}
.lang-btn.active {
border-color: var(--vp-c-brand);
background: var(--vp-c-brand);
color: white;
}
.lang-icon {
font-size: 1.5rem;
line-height: 1;
}
.lang-name {
font-size: 0.95rem;
}
.code-display {
background: #1e1e1e;
border-radius: 12px;
overflow: hidden;
margin-bottom: 2rem;
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.3);
}
.code-header {
display: flex;
align-items: center;
padding: 0.8rem 1rem;
background: #2d2d2d;
border-bottom: 1px solid #3e3e3e;
}
.window-controls {
display: flex;
gap: 6px;
}
.control {
width: 12px;
height: 12px;
border-radius: 50%;
}
.control.red {
background: #ff5f56;
}
.control.yellow {
background: #ffbd2e;
}
.control.green {
background: #27c93f;
}
.filename {
flex: 1;
text-align: center;
color: #858585;
font-size: 0.85rem;
font-family: var(--vp-font-family-mono);
}
.code-content {
margin: 0;
padding: 1.5rem;
background: #1e1e1e;
color: #d4d4d4;
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
font-size: 0.9rem;
line-height: 1.6;
overflow-x: auto;
}
.code-content code {
color: #d4d4d4;
}
.code-stats {
display: flex;
gap: 2rem;
padding: 1rem 1.5rem;
background: #2d2d2d;
border-top: 1px solid #3e3e3e;
flex-wrap: wrap;
}
.stat-item {
display: flex;
gap: 0.5rem;
font-size: 0.85rem;
}
.stat-label {
color: #858585;
}
.stat-value {
color: #4ec9b0;
font-weight: 600;
font-family: var(--vp-font-family-mono);
}
.analysis-panel {
background: var(--vp-c-bg-soft);
border-radius: 8px;
padding: 1.5rem;
margin-bottom: 2rem;
border-left: 4px solid var(--vp-c-brand);
}
.analysis-panel h5 {
margin-top: 0;
margin-bottom: 1rem;
color: var(--vp-c-brand);
font-size: 1.1rem;
}
.analysis-content p {
margin: 0;
color: var(--vp-c-text-2);
line-height: 1.7;
font-size: 0.95rem;
}
.complexity-chart {
margin-top: 2rem;
}
.complexity-chart h5 {
margin-bottom: 1.5rem;
color: var(--vp-c-text-1);
font-size: 1.1rem;
}
.chart-bars {
display: flex;
flex-direction: column;
gap: 1rem;
}
.chart-bar-wrapper {
display: flex;
align-items: center;
gap: 1rem;
}
.chart-label {
min-width: 80px;
font-weight: 600;
color: var(--vp-c-text-1);
font-size: 0.9rem;
}
.chart-bar {
flex: 1;
height: 30px;
background: var(--vp-c-bg-soft);
border-radius: 6px;
overflow: hidden;
}
.chart-fill {
height: 100%;
background: linear-gradient(90deg, var(--vp-c-brand), #8b5cf6);
transition: width 0.5s ease;
}
.chart-value {
min-width: 60px;
text-align: right;
font-weight: 600;
color: var(--vp-c-text-2);
font-size: 0.85rem;
font-family: var(--vp-font-family-mono);
}
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.3s ease;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
@media (max-width: 768px) {
.language-selector {
font-size: 0.85rem;
}
.lang-btn {
padding: 0.5rem 1rem;
}
.code-stats {
flex-direction: column;
gap: 0.75rem;
}
.chart-bar-wrapper {
flex-wrap: wrap;
}
.chart-label {
min-width: 60px;
}
.chart-value {
min-width: 50px;
}
}
</style>