diff --git a/.gitignore b/.gitignore index 26f8dcc..441b227 100644 --- a/.gitignore +++ b/.gitignore @@ -4,9 +4,15 @@ tools/* docs/.vitepress/dist docs/.vitepress/cache temp/* +docs/zh-cn/appendix-old-backup*/ +docs/zh-cn/appendix-dirs-backup*/ CLAUDE.md MULTI_LANGUAGE_PLAN.md .trae scripts/collapse_code_blocks.py .gitignore scripts/verify.sh +REFACTORING_PLAN.md +.gitignore +.gitignore +REFACTORING_REPORT.md diff --git a/README.md b/README.md index c82008d..1e3acab 100644 --- a/README.md +++ b/README.md @@ -209,7 +209,7 @@ Easy-Vibe 通过以下几个阶段,带你从 0 到 1: | 章节 | 关键内容 | 状态 | | :------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------- | :--- | -| [高级一:MCP 与 ClaudeCode Skills](docs/zh-cn/stage-3/core-skills/3.1-mcp-claudecode-skills/) | 通过 MCP 与 Skills 扩展 IDE 能力,把外部服务接成工具 | 🚧 | +| [高级一:MCP 与 Claude Code Skills](docs/zh-cn/stage-3/core-skills/3.1-mcp-claude-code-skills/) | 通过 MCP 与 Skills 扩展 IDE 能力,把外部服务接成工具 | 🚧 | | [高级二:如何让 Coding Tools 长时间工作](docs/zh-cn/stage-3/core-skills/3.2-long-running-tasks/) | 设计和配置长时间运行的任务,让 Coding Tools 更稳定可靠 | 🚧 | | [高级三:多平台开发:如何构建微信小程序](docs/zh-cn/stage-3/cross-platform/3.3-wechat-miniprogram/) | 了解微信小程序生态,从官方模板到上线完成一个前端小程序 | ✅ | | [高级四:多平台开发:如何构建微信小程序-包含后端](docs/zh-cn/stage-3/cross-platform/3.4-wechat-miniprogram-backend/) | 在小程序中接入数据库与后端逻辑,打通完整业务闭环 | 🚧 | diff --git a/docs-readme/ar-SA/README.md b/docs-readme/ar-SA/README.md index 5cc1b6d..7097a59 100644 --- a/docs-readme/ar-SA/README.md +++ b/docs-readme/ar-SA/README.md @@ -140,7 +140,7 @@ | الفصل | المحتوى الرئيسي | الحالة | | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------- | :----- | -| [المتقدم 1: MCP ومهارات ClaudeCode](docs/stage-3/core-skills/3.1-mcp-claudecode-skills/) : توسيع قدرات IDE من خلال MCP والمهارات، توصيل الخدمات الخارجية كأدوات | 🚧 | +| [المتقدم 1: MCP ومهارات ClaudeCode](docs/stage-3/core-skills/3.1-mcp-claude-code-skills/) : توسيع قدرات IDE من خلال MCP والمهارات، توصيل الخدمات الخارجية كأدوات | 🚧 | | [المتقدم 2: كيفية جعل Coding Tools تعمل لفترة طويلة](docs/stage-3/core-skills/3.2-long-running-tasks/) : تصميم وتكوين المهام طويلة التشغيل، جعل Coding Tools أكثر استقرارًا وموثوقية | 🚧 | | [المتقدم 3: التطوير متعدد المنصات: كيفية بناء برامج WeChat المصغرة](docs/stage-3/cross-platform/3.3-wechat-miniprogram/) : فهم نظام البرامج المصغرة WeChat، إكمال برنامج مصغر للواجهة الأمامية من القالب الرسمي إلى الإطلاق | ✅ | | [المتقدم 4: التطوير متعدد المنصات: كيفية بناء برامج WeChat المصغرة - بما في ذلك الخلفية](docs/stage-3/cross-platform/3.4-wechat-miniprogram-backend/) : دمج قاعدة البيانات ومنطق الواجهة الخلفية في البرامج المصغرة، تحقيق دورة نشاط كاملة | 🚧 | diff --git a/docs-readme/de-DE/README.md b/docs-readme/de-DE/README.md index 818b985..ae49a81 100644 --- a/docs-readme/de-DE/README.md +++ b/docs-readme/de-DE/README.md @@ -140,7 +140,7 @@ Wir glauben, dass durch die Beherrschung von Vibe Coding in Kombination mit syst | Kapitel | Schlüsselinhalt | Status | | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------- | :----- | -| [Fortgeschritten 1: MCP und ClaudeCode Skills](docs/zh-cn/stage-3/core-skills/3.1-mcp-claudecode-skills/) : IDE-Fähigkeiten durch MCP und Skills erweitern, externe Dienste als Tools anschließen | 🚧 | +| [Fortgeschritten 1: MCP und Claude Code Skills](docs/zh-cn/stage-3/core-skills/3.1-mcp-claude-code-skills/) : IDE-Fähigkeiten durch MCP und Skills erweitern, externe Dienste als Tools anschließen | 🚧 | | [Fortgeschritten 2: Coding Tools lange laufen lassen](docs/zh-cn/stage-3/core-skills/3.2-long-running-tasks/) : Lang laufende Aufgaben entwerfen und konfigurieren, Coding Tools stabiler und zuverlässiger machen | 🚧 | | [Fortgeschritten 3: Plattformübergreifende Entwicklung: WeChat-Miniprogramme erstellen](docs/zh-cn/stage-3/cross-platform/3.3-wechat-miniprogram/) : WeChat-Miniprogramm-Ökosystem verstehen, Frontend-Miniprogramm von offizieller Vorlage bis zum Start completed | ✅ | | [Fortgeschritten 4: Plattformübergreifende Entwicklung: WeChat-Miniprogramme erstellen - Mit Backend](docs/zh-cn/stage-3/cross-platform/3.4-wechat-miniprogram-backend/) : Datenbank und Backend-Logik in Miniprogramme integrieren, vollständigen Geschäftskreislauf realisieren | 🚧 | diff --git a/docs-readme/en-US/README.md b/docs-readme/en-US/README.md index 547cac4..4a56c55 100644 --- a/docs-readme/en-US/README.md +++ b/docs-readme/en-US/README.md @@ -143,7 +143,7 @@ We believe that by mastering Vibe Coding combined with systematic training, one | Chapter | Key Content | Status | | :-------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------- | :----- | -| [Advanced 1: MCP and ClaudeCode Skills](docs/zh-cn/stage-3/core-skills/3.1-mcp-claudecode-skills/) | Extend IDE capabilities through MCP and Skills, integrate external services as tools | 🚧 | +| [Advanced 1: MCP and Claude Code Skills](docs/zh-cn/stage-3/core-skills/3.1-mcp-claude-code-skills/) | Extend IDE capabilities through MCP and Skills, integrate external services as tools | 🚧 | | [Advanced 2: Making Coding Tools Work for Long Periods](docs/zh-cn/stage-3/core-skills/3.2-long-running-tasks/) | Design and configure long-running tasks, make Coding Tools more stable and reliable | 🚧 | | [Advanced 3: Multi-Platform Development: Building WeChat Mini Programs](docs/zh-cn/stage-3/cross-platform/3.3-wechat-miniprogram/) | Understand WeChat mini program ecosystem, complete a frontend mini program from official template to launch | ✅ | | [Advanced 4: Multi-Platform Development: Building WeChat Mini Programs - With Backend](docs/zh-cn/stage-3/cross-platform/3.4-wechat-miniprogram-backend/) | Integrate databases and backend logic in mini programs, complete business loops | 🚧 | diff --git a/docs-readme/es-ES/README.md b/docs-readme/es-ES/README.md index 37aeb20..2dc404c 100644 --- a/docs-readme/es-ES/README.md +++ b/docs-readme/es-ES/README.md @@ -140,7 +140,7 @@ Creemos que al dominar Vibe Coding y combinarlo con entrenamiento sistemático, | Capítulo | Contenido clave | Estado | | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------- | :----- | -| [Avanzado 1: MCP y ClaudeCode Skills](docs/zh-cn/stage-3/core-skills/3.1-mcp-claudecode-skills/) | Extender capacidades del IDE a través de MCP y Skills, conectar servicios externos como herramientas | 🚧 | +| [Avanzado 1: MCP y Claude Code Skills](docs/zh-cn/stage-3/core-skills/3.1-mcp-claude-code-skills/) | Extender capacidades del IDE a través de MCP y Skills, conectar servicios externos como herramientas | 🚧 | | [Avanzado 2: Cómo hacer que Coding Tools funcione durante mucho tiempo](docs/zh-cn/stage-3/core-skills/3.2-long-running-tasks/) | Diseñar y configurar tareas de ejecución prolongada, hacer Coding Tools más estable y confiable | 🚧 | | [Avanzado 3: Desarrollo multiplataforma: Cómo construir mini programas de WeChat](docs/zh-cn/stage-3/cross-platform/3.3-wechat-miniprogram/) | Entender el ecosistema de mini programas de WeChat, completar un mini programa frontend desde plantilla oficial hasta lanzamiento | ✅ | | [Avanzado 4: Desarrollo multiplataforma: Cómo construir mini programas de WeChat - Incluyendo backend](docs/zh-cn/stage-3/cross-platform/3.4-wechat-miniprogram-backend/) | Integrar base de datos y lógica backend en mini programas,实现 ciclo completo de negocio | 🚧 | diff --git a/docs-readme/fr-FR/README.md b/docs-readme/fr-FR/README.md index e7db06a..75d7d6c 100644 --- a/docs-readme/fr-FR/README.md +++ b/docs-readme/fr-FR/README.md @@ -140,7 +140,7 @@ Nous croyons qu'en maîtrisant Vibe Coding et en le combinant avec un entraînem | Chapitre | Contenu clé | Statut | | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :---------- | :----- | -| [Avancé 1 : MCP et ClaudeCode Skills](docs/zh-cn/stage-3/core-skills/3.1-mcp-claudecode-skills/) : Étendre les capacités de l'IDE via MCP et Skills, connecter des services externes comme outils | 🚧 | +| [Avancé 1 : MCP et Claude Code Skills](docs/zh-cn/stage-3/core-skills/3.1-mcp-claude-code-skills/) : Étendre les capacités de l'IDE via MCP et Skills, connecter des services externes comme outils | 🚧 | | [Avancé 2 : Comment faire fonctionner Coding Tools longtemps](docs/zh-cn/stage-3/core-skills/3.2-long-running-tasks/) : Concevoir et configurer des tâches à longue exécution, rendre Coding Tools plus stable et fiable | 🚧 | | [Avancé 3 : Développement multiplateforme : Comment construire des mini-programmes WeChat](docs/zh-cn/stage-3/cross-platform/3.3-wechat-miniprogram/) : Comprendre l'écosystème des mini-programmes WeChat, compléter un mini-programme frontend du modèle officiel au lancement | ✅ | | [Avancé 4 : Développement multiplateforme : Comment construire des mini-programmes WeChat - Y compris backend](docs/zh-cn/stage-3/cross-platform/3.4-wechat-miniprogram-backend/) : Intégrer une base de données et une logique backend dans les mini-programmes, réaliser un cycle d'activité complet | 🚧 | diff --git a/docs-readme/ja-JP/README.md b/docs-readme/ja-JP/README.md index 2e3cdbd..427eda6 100644 --- a/docs-readme/ja-JP/README.md +++ b/docs-readme/ja-JP/README.md @@ -140,7 +140,7 @@ AI でコードを書こうとしてエラーが続き、諦めかけたくな | 章 | 主要内容 | 状態 | | :---------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------- | :--- | -| [上級一:MCP と ClaudeCode Skills](docs/zh-cn/stage-3/core-skills/3.1-mcp-claudecode-skills/) | MCP と Skills を通じて IDE 能力を拡張し、外部サービスをツールとして接続 | 🚧 | +| [上級一:MCP と Claude Code Skills](docs/zh-cn/stage-3/core-skills/3.1-mcp-claude-code-skills/) | MCP と Skills を通じて IDE 能力を拡張し、外部サービスをツールとして接続 | 🚧 | | [上級二:Coding Tools を長時間動作させる方法](docs/zh-cn/stage-3/core-skills/3.2-long-running-tasks/) | 長時間動作するタスクを設計・設定し、Coding Tools をより安定して信頼性の高いものに | 🚧 | | [上級三:マルチプラットフォーム開発:WeChat ミニプログラムの構築方法](docs/zh-cn/stage-3/cross-platform/3.3-wechat-miniprogram/) | WeChat ミニプログラムのエコシステムを理解し、公式テンプレートからリリースまでフロントエンドミニプログラムを完成 | ✅ | | [上級四:マルチプラットフォーム開発:WeChat ミニプログラムの構築方法 - バックエンド含む](docs/zh-cn/stage-3/cross-platform/3.4-wechat-miniprogram-backend/) | ミニプログラムにデータベースとバックエンドロジックを統合し、完全な業務クローズドループを実現 | 🚧 | diff --git a/docs-readme/ko-KR/README.md b/docs-readme/ko-KR/README.md index 08c6e73..3d62f52 100644 --- a/docs-readme/ko-KR/README.md +++ b/docs-readme/ko-KR/README.md @@ -140,7 +140,7 @@ AI로 코드를 작성하려고 할 때 오류가 계속 발생하고, 포기하 | 장 | 주요 내용 | 상태 | | :--------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------- | :--- | -| [고급 1: MCP와 ClaudeCode Skills](docs/zh-cn/stage-3/core-skills/3.1-mcp-claudecode-skills/) | MCP와 Skills를 통해 IDE 능력 확장, 외부 서비스를 도구로 연결 | 🚧 | +| [고급 1: MCP와 Claude Code Skills](docs/zh-cn/stage-3/core-skills/3.1-mcp-claude-code-skills/) | MCP와 Skills를 통해 IDE 능력 확장, 외부 서비스를 도구로 연결 | 🚧 | | [고급 2: Coding Tools를 장시간 작동시키는 방법](docs/zh-cn/stage-3/core-skills/3.2-long-running-tasks/) | 장시간 실행되는 작업 설계 및 구성, Coding Tools를 더 안정적이고 신뢰할 수 있게 | 🚧 | | [고급 3: 멀티플랫폼 개발: 위챗 미니 프로그램 구축 방법](docs/zh-cn/stage-3/cross-platform/3.3-wechat-miniprogram/) | 위챗 미니 프로그램 생태계 이해, 공식 템플릿부터 출시까지 프론트엔드 미니 프로그램 완성 | ✅ | | [고급 4: 멀티플랫폼 개발: 위챗 미니 프로그램 구축 방법 - 백엔드 포함](docs/zh-cn/stage-3/cross-platform/3.4-wechat-miniprogram-backend/) | 미니 프로그램에 데이터베이스와 백엔드 로직 통합, 완전한 비즈니스 폐루프 실현 | 🚧 | diff --git a/docs-readme/vi-VN/README.md b/docs-readme/vi-VN/README.md index 1c1ca28..256bde4 100644 --- a/docs-readme/vi-VN/README.md +++ b/docs-readme/vi-VN/README.md @@ -140,7 +140,7 @@ Chúng tôi tin rằng thông qua việc làm chủ Vibe Coding kết hợp vớ | Chương | Nội dung chính | Trạng thái | | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------- | :--------- | -| [Cao cấp 1: MCP và ClaudeCode Skills](docs/stage-3/core-skills/3.1-mcp-claudecode-skills/) : Mở rộng khả năng IDE qua MCP và Skills, kết nối dịch vụ bên ngoài như công cụ | 🚧 | +| [Cao cấp 1: MCP và Claude Code Skills](docs/stage-3/core-skills/3.1-mcp-claude-code-skills/) : Mở rộng khả năng IDE qua MCP và Skills, kết nối dịch vụ bên ngoài như công cụ | 🚧 | | [Cao cấp 2: Cách để Coding Tools hoạt động lâu](docs/stage-3/core-skills/3.2-long-running-tasks/) : Thiết kế và cấu hình nhiệm vụ chạy dài, làm Coding Tools ổn định và đáng tin cậy hơn | 🚧 | | [Cao cấp 3: Phát triển đa nền tảng: Cách xây dựng chương trình nhỏ WeChat](docs/stage-3/cross-platform/3.3-wechat-miniprogram/) : Hiểu hệ sinh thái chương trình nhỏ WeChat, hoàn thành chương trình nhỏ frontend từ mẫu chính thức đến phát hành | ✅ | | [Cao cấp 4: Phát triển đa nền tảng: Cách xây dựng chương trình nhỏ WeChat - Bao gồm backend](docs/stage-3/cross-platform/3.4-wechat-miniprogram-backend/) : Tích hợp cơ sở dữ liệu và logic backend vào chương trình nhỏ, thực hiện vòng tuần hoàn hoạt động hoàn chỉnh | 🚧 | diff --git a/docs-readme/zh-TW/README.md b/docs-readme/zh-TW/README.md index 933ea46..9709b27 100644 --- a/docs-readme/zh-TW/README.md +++ b/docs-readme/zh-TW/README.md @@ -140,7 +140,7 @@ | 章节 | 關鍵內容 | 狀態 | | :---------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------- | :--- | -| [高級一:MCP 與 ClaudeCode Skills](../docs/zh-cn/stage-3/core-skills/3.1-mcp-claudecode-skills/) | 通過 MCP 與 Skills 擴展 IDE 能力,把外部服務接成工具 | 🚧 | +| [高級一:MCP 與 Claude Code Skills](../docs/zh-cn/stage-3/core-skills/3.1-mcp-claude-code-skills/) | 通過 MCP 與 Skills 擴展 IDE 能力,把外部服務接成工具 | 🚧 | | [高級二:如何讓 Coding Tools 長時間工作](../docs/zh-cn/stage-3/core-skills/3.2-long-running-tasks/) | 設計和配置長時間運行的任務,讓 Coding Tools 更穩定可靠 | 🚧 | | [高級三:多平台開發:如何建構微信小程式](../docs/zh-cn/stage-3/cross-platform/3.3-wechat-miniprogram/) | 了解微信小程式生態,從官方模板到上線完成一個前端小程式 | ✅ | | [高級四:多平台開發:如何建構微信小程式-包含後端](../docs/zh-cn/stage-3/cross-platform/3.4-wechat-miniprogram-backend/) | 在小程式中接入數據庫與後端邏輯,打通完整業務閉環 | 🚧 | diff --git a/docs/.vitepress/config.mjs b/docs/.vitepress/config.mjs index b41667e..1176f95 100644 --- a/docs/.vitepress/config.mjs +++ b/docs/.vitepress/config.mjs @@ -344,7 +344,7 @@ export default defineConfig({ text: '高级开发', link: '/zh-cn/stage-3/intro' }, - { text: '附录', link: '/zh-cn/appendix/intro' } + { text: '附录', link: '/zh-cn/appendix/index' } ], sidebar: { '/zh-cn/stage-0/': productManagerSidebar, @@ -445,8 +445,8 @@ export default defineConfig({ collapsed: false, items: [ { - text: '高级一:MCP 与 ClaudeCode Skills', - link: '/zh-cn/stage-3/core-skills/3.1-mcp-claudecode-skills/' + text: '高级一:MCP 与 Claude Code Skills', + link: '/zh-cn/stage-3/core-skills/3.1-mcp-claude-code-skills/' }, { text: '高级二:如何让 Coding Tools 长时间工作', @@ -570,152 +570,156 @@ export default defineConfig({ ], '/zh-cn/appendix/': [ { - text: '人工智能基础', + text: '一、计算机是怎么回事', collapsed: false, items: [ - { - text: '提示词工程', - link: '/zh-cn/appendix/prompt-engineering' - }, - { - text: '人工智能进化史', - link: '/zh-cn/appendix/ai-evolution' - }, - { text: '大语言模型', link: '/zh-cn/appendix/llm-intro' }, - { text: '多模态大模型', link: '/zh-cn/appendix/vlm-intro' }, - { - text: 'AI 绘画原理', - link: '/zh-cn/appendix/image-gen-intro' - }, - { text: 'AI 音频模型', link: '/zh-cn/appendix/audio-intro' }, - { - text: '上下文工程', - link: '/zh-cn/appendix/context-engineering' - }, - { text: 'Agent 智能体', link: '/zh-cn/appendix/agent-intro' }, - { - text: 'AI 能力词典', - link: '/zh-cn/appendix/ai-capability-dictionary' - } + { text: '从晶体管到 CPU', link: '/zh-cn/appendix/1-computer-fundamentals/transistor-to-cpu' }, + { text: '操作系统(进程 / 内存 / 文件系统)', link: '/zh-cn/appendix/1-computer-fundamentals/operating-systems' }, + { text: '数据的编码、存储与传输', link: '/zh-cn/appendix/1-computer-fundamentals/data-encoding-storage' }, + { text: '网络:两台电脑如何对话', link: '/zh-cn/appendix/1-computer-fundamentals/computer-networks' }, + { text: '数据结构', link: '/zh-cn/appendix/1-computer-fundamentals/data-structures' }, + { text: '算法思维入门', link: '/zh-cn/appendix/1-computer-fundamentals/algorithm-thinking' }, + { text: '编程语言图谱', link: '/zh-cn/appendix/1-computer-fundamentals/programming-languages' }, + { text: '类型系统与编译原理入门', link: '/zh-cn/appendix/1-computer-fundamentals/type-systems-compilers' } ] }, { - text: '前端开发', + text: '二、开发环境与工具', collapsed: false, items: [ - { - text: 'HTML/CSS/JS 基础', - link: '/zh-cn/appendix/web-basics' - }, - { - text: '前端进化史', - link: '/zh-cn/appendix/frontend-evolution' - }, - { - text: '前端性能优化', - link: '/zh-cn/appendix/frontend-performance' - }, - { - text: 'Canvas 2D 入门', - link: '/zh-cn/appendix/canvas-intro' - }, - { - text: 'URL 到浏览器显示', - link: '/zh-cn/appendix/url-to-browser' - }, - { - text: '浏览器调试器', - link: '/zh-cn/appendix/browser-devtools' - }, - { - text: '浏览器渲染原理', - link: '/zh-cn/appendix/browser-rendering-pipeline' - }, - { - text: '前端路由原理', - link: '/zh-cn/appendix/frontend-routing' - }, - { - text: '组件状态管理', - link: '/zh-cn/appendix/component-state-management' - }, - { - text: '前端工程化', - link: '/zh-cn/appendix/frontend-engineering' - } + { text: '集成开发环境 (IDE) 基础', link: '/zh-cn/appendix/2-development-tools/ide-basics' }, + { text: '命令行与 Shell 脚本', link: '/zh-cn/appendix/2-development-tools/command-line-shell' }, + { text: '编辑器与 AI 编程助手', link: '/zh-cn/appendix/2-development-tools/editors-and-ai' }, + { text: 'Git:代码的时光机', link: '/zh-cn/appendix/2-development-tools/git-version-control' }, + { text: '环境变量与 PATH', link: '/zh-cn/appendix/2-development-tools/environment-path' }, + { text: '端口与 localhost', link: '/zh-cn/appendix/2-development-tools/ports-localhost' }, + { text: 'SSH 与密钥认证', link: '/zh-cn/appendix/2-development-tools/ssh-authentication' }, + { text: '包管理器(npm / pip / cargo)', link: '/zh-cn/appendix/2-development-tools/package-managers' }, + { text: '调试的艺术', link: '/zh-cn/appendix/2-development-tools/debugging-art/' }, + { text: '正则表达式', link: '/zh-cn/appendix/2-development-tools/regex' } ] }, { - text: '后端开发', + text: '三、浏览器与前端', collapsed: false, items: [ - { - text: '后端进化史', - link: '/zh-cn/appendix/backend-evolution' - }, - { - text: '后端分层架构', - link: '/zh-cn/appendix/backend-layered-architecture' - }, - { - text: '后端编程语言', - link: '/zh-cn/appendix/backend-languages' - }, - { - text: '并发编程模型', - link: '/zh-cn/appendix/concurrency-models' - }, - { - text: '接口设计规范', - link: '/zh-cn/appendix/api-design' - }, - { text: '数据库原理', link: '/zh-cn/appendix/database-intro' }, - { text: '系统缓存设计', link: '/zh-cn/appendix/cache-design' }, - { text: '消息队列设计', link: '/zh-cn/appendix/queue-design' }, - { text: '鉴权原理与实战', link: '/zh-cn/appendix/auth-design' }, - { - text: '网关与反向代理', - link: '/zh-cn/appendix/gateway-proxy' - }, - { - text: '负载均衡策略', - link: '/zh-cn/appendix/load-balancing' - }, - { text: '埋点设计', link: '/zh-cn/appendix/tracking-design' }, - { text: '线上运维', link: '/zh-cn/appendix/operations' } + { text: 'JavaScript 语言深入', link: '/zh-cn/appendix/3-browser-and-frontend/javascript-deep-dive' }, + { text: 'TypeScript:给 JS 加上类型系统', link: '/zh-cn/appendix/3-browser-and-frontend/typescript' }, + { text: '前端框架对比(React / Vue / Svelte / Angular)', link: '/zh-cn/appendix/3-browser-and-frontend/frontend-frameworks' }, + { text: '浏览器是一个操作系统', link: '/zh-cn/appendix/3-browser-and-frontend/browser-as-os' }, + { text: '浏览器渲染管道', link: '/zh-cn/appendix/3-browser-and-frontend/browser-as-os-rendering' }, + { text: 'HTML / CSS 布局体系', link: '/zh-cn/appendix/3-browser-and-frontend/html-css-layout' }, + { text: 'JavaScript 运行时', link: '/zh-cn/appendix/3-browser-and-frontend/javascript-runtime' }, + { text: '前端框架的本质', link: '/zh-cn/appendix/3-browser-and-frontend/frontend-framework-nature' }, + { text: '状态管理哲学', link: '/zh-cn/appendix/3-browser-and-frontend/state-management' }, + { text: '路由与导航', link: '/zh-cn/appendix/3-browser-and-frontend/routing-navigation' }, + { text: '图形与动画(Canvas / SVG / WebGL)', link: '/zh-cn/appendix/3-browser-and-frontend/graphics-animation' }, + { text: '实时通信(WebSocket / SSE)', link: '/zh-cn/appendix/3-browser-and-frontend/realtime-communication' }, + { text: '网页性能的度量与优化', link: '/zh-cn/appendix/3-browser-and-frontend/web-performance' }, + { text: '前端工程化全貌', link: '/zh-cn/appendix/3-browser-and-frontend/frontend-engineering' }, + { text: '无障碍与国际化', link: '/zh-cn/appendix/3-browser-and-frontend/a11n-i18n' } ] }, { - text: '云计算与服务', + text: '四、服务器与后端', collapsed: false, items: [ - { - text: '云服务基础', - link: '/zh-cn/appendix/cloud-services' - }, - { - text: 'IAM 权限管理', - link: '/zh-cn/appendix/cloud-iam' - }, - { - text: '对象存储与 CDN', - link: '/zh-cn/appendix/cloud-storage-cdn' - } + { text: '后端语言对比(Node.js / Go / Java / Rust)', link: '/zh-cn/appendix/4-server-and-backend/backend-languages' }, + { text: '客户端语言对比(Swift / Kotlin / Dart)', link: '/zh-cn/appendix/4-server-and-backend/client-languages' }, + { text: '跨平台方案对比(React Native / Flutter / Electron / Tauri)', link: '/zh-cn/appendix/4-server-and-backend/cross-platform' }, + { text: 'HTTP 协议', link: '/zh-cn/appendix/4-server-and-backend/http-protocol' }, + { text: '一个请求的完整旅程', link: '/zh-cn/appendix/4-server-and-backend/request-journey' }, + { text: 'Web 框架的本质', link: '/zh-cn/appendix/4-server-and-backend/web-frameworks' }, + { text: 'API 设计哲学(REST / GraphQL / gRPC)', link: '/zh-cn/appendix/4-server-and-backend/api-design' }, + { text: 'API 入门', link: '/zh-cn/appendix/4-server-and-backend/api-intro' }, + { text: '序列化与数据格式', link: '/zh-cn/appendix/4-server-and-backend/serialization' }, + { text: '认证与授权体系', link: '/zh-cn/appendix/4-server-and-backend/auth-authorization' }, + { text: '并发、异步与多线程', link: '/zh-cn/appendix/4-server-and-backend/concurrency-async' }, + { text: '缓存的层次与策略', link: '/zh-cn/appendix/4-server-and-backend/caching' }, + { text: '消息队列与事件驱动', link: '/zh-cn/appendix/4-server-and-backend/message-queues' }, + { text: '异步任务队列与生产消费模型', link: '/zh-cn/appendix/4-server-and-backend/async-task-queues' }, + { text: '限流与背压控制', link: '/zh-cn/appendix/4-server-and-backend/rate-limiting-backpressure' }, + { text: '搜索引擎原理', link: '/zh-cn/appendix/4-server-and-backend/search-engines' }, + { text: '文件存储与对象存储', link: '/zh-cn/appendix/4-server-and-backend/file-storage' }, + { text: '后端分层架构', link: '/zh-cn/appendix/4-server-and-backend/backend-layered-architecture' } ] }, { - text: '通用技能', + text: '五、数据', collapsed: false, items: [ - { text: 'API 入门', link: '/zh-cn/appendix/api-intro' }, - { text: 'IDE 原理', link: '/zh-cn/appendix/ide-intro' }, - { text: '终端入门', link: '/zh-cn/appendix/terminal-intro' }, - { text: 'Git 详细介绍', link: '/zh-cn/appendix/git-intro' }, - { - text: '计算机网络', - link: '/zh-cn/appendix/computer-networks' - }, - { text: '部署与上线', link: '/zh-cn/appendix/deployment' } + { text: 'SQL', link: '/zh-cn/appendix/5-data/sql' }, + { text: '数据库原理(索引 / 事务 / 查询优化)', link: '/zh-cn/appendix/5-data/database-fundamentals' }, + { text: '数据模型全景(文档 / 图 / 时序 / 向量)', link: '/zh-cn/appendix/5-data/data-models' }, + { text: '数据埋点与用户行为采集', link: '/zh-cn/appendix/5-data/data-tracking' }, + { text: '数据分析基础(统计 / 指标 / 漏斗)', link: '/zh-cn/appendix/5-data/data-analysis' }, + { text: 'A/B 测试与实验驱动', link: '/zh-cn/appendix/5-data/ab-testing' }, + { text: '数据可视化与仪表盘', link: '/zh-cn/appendix/5-data/data-visualization' }, + { text: '数据治理与数据质量', link: '/zh-cn/appendix/5-data/data-governance' } + ] + }, + { + text: '六、架构与系统设计', + collapsed: false, + items: [ + { text: '从单体到微服务的演进', link: '/zh-cn/appendix/6-architecture-and-system-design/monolith-to-microservices' }, + { text: '分布式系统的挑战', link: '/zh-cn/appendix/6-architecture-and-system-design/distributed-systems' }, + { text: '高可用与容灾', link: '/zh-cn/appendix/6-architecture-and-system-design/high-availability' }, + { text: '系统设计方法论', link: '/zh-cn/appendix/6-architecture-and-system-design/system-design-methodology' } + ] + }, + { + text: '七、基础设施与运维', + collapsed: false, + items: [ + { text: 'Linux 基础', link: '/zh-cn/appendix/7-infrastructure-and-operations/linux-basics' }, + { text: 'Docker 容器化', link: '/zh-cn/appendix/7-infrastructure-and-operations/docker-containers' }, + { text: 'Kubernetes 编排', link: '/zh-cn/appendix/7-infrastructure-and-operations/kubernetes' }, + { text: 'CI / CD 自动化', link: '/zh-cn/appendix/7-infrastructure-and-operations/ci-cd' }, + { text: '域名、DNS 与 HTTPS', link: '/zh-cn/appendix/7-infrastructure-and-operations/dns-https' }, + { text: '负载均衡与网关', link: '/zh-cn/appendix/7-infrastructure-and-operations/load-balancing-gateway' }, + { text: '网关与反向代理', link: '/zh-cn/appendix/7-infrastructure-and-operations/gateway-proxy' }, + { text: '云平台实战', link: '/zh-cn/appendix/7-infrastructure-and-operations/cloud-platforms' }, + { text: 'IAM 权限管理', link: '/zh-cn/appendix/7-infrastructure-and-operations/cloud-iam' }, + { text: '对象存储与 CDN', link: '/zh-cn/appendix/7-infrastructure-and-operations/cloud-storage-cdn' }, + { text: '基础设施即代码', link: '/zh-cn/appendix/7-infrastructure-and-operations/infrastructure-as-code' }, + { text: '监控、日志与告警', link: '/zh-cn/appendix/7-infrastructure-and-operations/monitoring-logging' }, + { text: '故障排查与应急响应', link: '/zh-cn/appendix/7-infrastructure-and-operations/incident-response' } + ] + }, + { + text: '八、人工智能', + collapsed: false, + items: [ + { text: 'AI 简史与核心概念', link: '/zh-cn/appendix/8-artificial-intelligence/ai-history' }, + { text: '神经网络与深度学习', link: '/zh-cn/appendix/8-artificial-intelligence/neural-networks' }, + { text: 'Transformer 与注意力机制', link: '/zh-cn/appendix/8-artificial-intelligence/transformer-attention' }, + { text: '大语言模型的工作原理', link: '/zh-cn/appendix/8-artificial-intelligence/llm-principles' }, + { text: '提示词工程', link: '/zh-cn/appendix/8-artificial-intelligence/prompt-engineering' }, + { text: '上下文工程', link: '/zh-cn/appendix/8-artificial-intelligence/context-engineering' }, + { text: '多模态模型(视觉 / 音频 / 视频)', link: '/zh-cn/appendix/8-artificial-intelligence/multimodal-models' }, + { text: '图像生成原理', link: '/zh-cn/appendix/8-artificial-intelligence/image-generation' }, + { text: '语音合成与识别', link: '/zh-cn/appendix/8-artificial-intelligence/speech-synthesis-recognition' }, + { text: 'Embedding 与向量检索', link: '/zh-cn/appendix/8-artificial-intelligence/embedding-vector-retrieval' }, + { text: 'RAG 架构', link: '/zh-cn/appendix/8-artificial-intelligence/rag' }, + { text: 'AI Agent 与工具调用', link: '/zh-cn/appendix/8-artificial-intelligence/ai-agents' }, + { text: 'AI 协议(MCP 等)', link: '/zh-cn/appendix/8-artificial-intelligence/ai-protocols' }, + { text: '模型微调与部署', link: '/zh-cn/appendix/8-artificial-intelligence/model-finetuning-deployment' }, + { text: 'AI 原生应用设计', link: '/zh-cn/appendix/8-artificial-intelligence/ai-native-app-design' }, + { text: 'AI 能力词典', link: '/zh-cn/appendix/8-artificial-intelligence/ai-capability-dictionary' } + ] + }, + { + text: '九、工程素养', + collapsed: false, + items: [ + { text: '代码质量与重构', link: '/zh-cn/appendix/9-engineering-excellence/code-quality-refactoring' }, + { text: '测试策略', link: '/zh-cn/appendix/9-engineering-excellence/testing-strategies' }, + { text: '设计模式', link: '/zh-cn/appendix/9-engineering-excellence/design-patterns' }, + { text: '安全思维与攻防基础', link: '/zh-cn/appendix/9-engineering-excellence/security-thinking' }, + { text: '技术文档写作', link: '/zh-cn/appendix/9-engineering-excellence/technical-writing' }, + { text: '开源协作', link: '/zh-cn/appendix/9-engineering-excellence/open-source-collaboration' }, + { text: '技术选型方法论', link: '/zh-cn/appendix/9-engineering-excellence/technology-selection' } ] } ] diff --git a/docs/.vitepress/theme/Layout.vue b/docs/.vitepress/theme/Layout.vue index a9c6c0f..006483f 100644 --- a/docs/.vitepress/theme/Layout.vue +++ b/docs/.vitepress/theme/Layout.vue @@ -86,7 +86,6 @@ onMounted(() => { applyLineHeight(savedLineHeight) isHydrated.value = true - // 初始化 outline 自动滚动功能 initOutlineAutoScroll() }) @@ -95,7 +94,34 @@ onMounted(() => { // 当页面滚动时,自动滚动 outline 让当前激活项保持在可视区域 // ============================================ function initOutlineAutoScroll() { - // 使用 MutationObserver 监听 outline 的变化 + const outlineSelectors = [ + '.VPDocAsideOutline', + '.VPTableOfContents', + '.vitepress-doc-sidebar', + '.sidebar-outline', + 'aside' + ] + + const sidebarSelectors = [ + '.VPSidebar', + '.VPDocSidebar', + '.vitepress-doc-sidebar' + ] + + let outlineContainer = null + for (const selector of outlineSelectors) { + outlineContainer = document.querySelector(selector) + if (outlineContainer) break + } + + if (!outlineContainer) return + + let sidebarContainer = null + for (const selector of sidebarSelectors) { + sidebarContainer = document.querySelector(selector) + if (sidebarContainer) break + } + const observer = new MutationObserver((mutations) => { for (const mutation of mutations) { if (mutation.type === 'attributes' && mutation.attributeName === 'class') { @@ -107,7 +133,17 @@ function initOutlineAutoScroll() { } }) - // 开始监听 + const sidebarObserver = new MutationObserver((mutations) => { + for (const mutation of mutations) { + if (mutation.type === 'attributes' && mutation.attributeName === 'class') { + const target = mutation.target + if (target.classList.contains('is-active')) { + scrollSidebarToActiveItem(target) + } + } + } + }) + const startObserving = () => { const outlineContainer = document.querySelector('.VPDocAsideOutline') if (outlineContainer) { @@ -116,32 +152,48 @@ function initOutlineAutoScroll() { subtree: true, attributeFilter: ['class'] }) + + const existingActive = outlineContainer.querySelector('.active') + if (existingActive) { + scrollOutlineToActiveItem(existingActive) + } + } + + if (sidebarContainer) { + sidebarObserver.observe(sidebarContainer, { + attributes: true, + subtree: true, + attributeFilter: ['class'] + }) + + const existingSidebarActive = sidebarContainer.querySelector('.is-active') + if (existingSidebarActive) { + scrollSidebarToActiveItem(existingSidebarActive) + } } } - // 页面加载完成后开始监听 if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', startObserving) } else { startObserving() } - // 同时监听路由变化(VitePress 是 SPA) const originalPushState = history.pushState const originalReplaceState = history.replaceState history.pushState = function (...args) { originalPushState.apply(this, args) - setTimeout(startObserving, 100) + setTimeout(startObserving, 300) } history.replaceState = function (...args) { originalReplaceState.apply(this, args) - setTimeout(startObserving, 100) + setTimeout(startObserving, 300) } window.addEventListener('popstate', () => { - setTimeout(startObserving, 100) + setTimeout(startObserving, 300) }) } @@ -172,6 +224,32 @@ function scrollOutlineToActiveItem(activeLink) { } } +// 滚动侧边栏让当前激活项保持在可视区域中心 +function scrollSidebarToActiveItem(activeItem) { + const sidebarContainer = document.querySelector('.VPSidebar') || document.querySelector('.VPDocSidebar') + if (!sidebarContainer || !activeItem) return + + const targetElement = activeItem.querySelector('.item') || activeItem.querySelector('a') || activeItem + + const containerRect = sidebarContainer.getBoundingClientRect() + const targetRect = targetElement.getBoundingClientRect() + + const targetTop = targetRect.top - containerRect.top + sidebarContainer.scrollTop + const targetHeight = targetRect.height + const targetCenterY = targetTop + targetHeight / 2 + + const isInside = targetRect.top >= containerRect.top - 20 && + targetRect.bottom <= containerRect.bottom + 20 + + if (!isInside) { + const targetScrollTop = targetCenterY - containerRect.height / 2 + sidebarContainer.scrollTo({ + top: targetScrollTop, + behavior: 'smooth' + }) + } +} + watch(fontSize, (next) => { if (!isHydrated.value) return const normalized = clampFontSize(next) diff --git a/docs/.vitepress/theme/components/appendix/agent-intro/AgentArchitectureDemo.vue b/docs/.vitepress/theme/components/appendix/agent-intro/AgentArchitectureDemo.vue index aa00cfd..4921341 100644 --- a/docs/.vitepress/theme/components/appendix/agent-intro/AgentArchitectureDemo.vue +++ b/docs/.vitepress/theme/components/appendix/agent-intro/AgentArchitectureDemo.vue @@ -156,7 +156,7 @@ const current = ref(modules[0]) .icon { width: 28px; height: 28px; - border-radius: 8px; + border-radius: 6px; display: grid; place-items: center; background: var(--vp-c-bg-soft); diff --git a/docs/.vitepress/theme/components/appendix/agent-intro/AgentMemoryDemo.vue b/docs/.vitepress/theme/components/appendix/agent-intro/AgentMemoryDemo.vue index 499d374..4d50d8d 100644 --- a/docs/.vitepress/theme/components/appendix/agent-intro/AgentMemoryDemo.vue +++ b/docs/.vitepress/theme/components/appendix/agent-intro/AgentMemoryDemo.vue @@ -261,7 +261,7 @@ const wait = (ms) => new Promise(r => setTimeout(r, ms)) padding: 12px; min-height: 120px; max-height: 160px; - overflow-y: auto; + } .msg-row { @@ -421,7 +421,7 @@ const wait = (ms) => new Promise(r => setTimeout(r, ms)) gap: 8px; padding: 10px 14px; background: #dcfce7; - border-radius: 8px; + border-radius: 6px; margin-bottom: 16px; font-size: 12px; color: #166534; @@ -433,7 +433,7 @@ const wait = (ms) => new Promise(r => setTimeout(r, ms)) gap: 8px; padding: 10px 14px; background: var(--vp-c-brand-soft); - border-radius: 8px; + border-radius: 6px; font-size: 12px; color: var(--vp-c-text-1); } diff --git a/docs/.vitepress/theme/components/appendix/agent-intro/AgentMemoryPrinciple.vue b/docs/.vitepress/theme/components/appendix/agent-intro/AgentMemoryPrinciple.vue index a1a158f..52b4477 100644 --- a/docs/.vitepress/theme/components/appendix/agent-intro/AgentMemoryPrinciple.vue +++ b/docs/.vitepress/theme/components/appendix/agent-intro/AgentMemoryPrinciple.vue @@ -588,7 +588,7 @@ const truncate = (str, len) => str?.length > len ? str.slice(0, len) + '...' : s /* 对话区 */ .chat-area { background: var(--vp-c-bg-soft); - border-radius: 8px; + border-radius: 6px; padding: 12px; margin-bottom: 16px; } @@ -613,7 +613,7 @@ const truncate = (str, len) => str?.length > len ? str.slice(0, len) + '...' : s .messages { max-height: 200px; - overflow-y: auto; + display: flex; flex-direction: column; gap: 10px; @@ -732,7 +732,7 @@ const truncate = (str, len) => str?.length > len ? str.slice(0, len) + '...' : s .memory-panel { background: var(--vp-c-bg-soft); border: 2px solid var(--vp-c-divider); - border-radius: 8px; + border-radius: 6px; overflow: hidden; cursor: pointer; transition: all 0.3s; @@ -778,7 +778,7 @@ const truncate = (str, len) => str?.length > len ? str.slice(0, len) + '...' : s padding: 10px; min-height: 80px; max-height: 120px; - overflow-y: auto; + } .empty { @@ -1060,7 +1060,7 @@ const truncate = (str, len) => str?.length > len ? str.slice(0, len) + '...' : s gap: 12px; padding: 12px; background: var(--vp-c-bg-soft); - border-radius: 8px; + border-radius: 6px; } .practice-icon { diff --git a/docs/.vitepress/theme/components/appendix/agent-intro/AgentMultiToolPrinciple.vue b/docs/.vitepress/theme/components/appendix/agent-intro/AgentMultiToolPrinciple.vue index 283dfe8..875714a 100644 --- a/docs/.vitepress/theme/components/appendix/agent-intro/AgentMultiToolPrinciple.vue +++ b/docs/.vitepress/theme/components/appendix/agent-intro/AgentMultiToolPrinciple.vue @@ -435,7 +435,7 @@ const truncate = (str, len) => str.length > len ? str.slice(0, len) + '...' : st .phase { margin-bottom: 12px; border: 1px solid var(--vp-c-divider); - border-radius: 8px; + border-radius: 6px; overflow: hidden; opacity: 0.5; transition: all 0.3s; @@ -525,7 +525,7 @@ const truncate = (str, len) => str.length > len ? str.slice(0, len) + '...' : st gap: 12px; padding: 12px; background: var(--vp-c-bg-soft); - border-radius: 8px; + border-radius: 6px; border: 2px solid transparent; transition: all 0.3s; position: relative; @@ -685,7 +685,7 @@ const truncate = (str, len) => str.length > len ? str.slice(0, len) + '...' : st .final-output { padding: 12px; background: #dcfce7; - border-radius: 8px; + border-radius: 6px; } .output-bubble { @@ -704,7 +704,7 @@ const truncate = (str, len) => str.length > len ? str.slice(0, len) + '...' : st .control-btn { padding: 10px 24px; - border-radius: 8px; + border-radius: 6px; font-size: 14px; cursor: pointer; transition: all 0.2s; @@ -762,7 +762,7 @@ const truncate = (str, len) => str.length > len ? str.slice(0, len) + '...' : st .explanation-card { background: var(--vp-c-bg); border: 1px solid var(--vp-c-divider); - border-radius: 8px; + border-radius: 6px; padding: 14px; text-align: center; } @@ -788,7 +788,7 @@ const truncate = (str, len) => str.length > len ? str.slice(0, len) + '...' : st .comparison-section { background: var(--vp-c-bg); border: 1px solid var(--vp-c-divider); - border-radius: 8px; + border-radius: 6px; padding: 14px; } diff --git a/docs/.vitepress/theme/components/appendix/agent-intro/AgentPlanningDemo.vue b/docs/.vitepress/theme/components/appendix/agent-intro/AgentPlanningDemo.vue index c50cfbd..ef91e13 100644 --- a/docs/.vitepress/theme/components/appendix/agent-intro/AgentPlanningDemo.vue +++ b/docs/.vitepress/theme/components/appendix/agent-intro/AgentPlanningDemo.vue @@ -304,7 +304,7 @@ reset() .goal-bar { background: var(--vp-c-brand-soft); border-left: 3px solid var(--vp-c-brand); - border-radius: 8px; + border-radius: 6px; padding: 10px 14px; margin-bottom: 16px; font-size: 14px; @@ -403,7 +403,7 @@ reset() .log-box, .thought-box { background: var(--vp-c-bg); border: 1px solid var(--vp-c-divider); - border-radius: 8px; + border-radius: 6px; overflow: hidden; } @@ -431,7 +431,7 @@ reset() padding: 10px 12px; min-height: 100px; max-height: 140px; - overflow-y: auto; + } .empty { @@ -534,7 +534,7 @@ reset() gap: 8px; padding: 10px 14px; background: var(--vp-c-brand-soft); - border-radius: 8px; + border-radius: 6px; font-size: 12px; color: var(--vp-c-text-1); } diff --git a/docs/.vitepress/theme/components/appendix/agent-intro/AgentQuickStartDemo.vue b/docs/.vitepress/theme/components/appendix/agent-intro/AgentQuickStartDemo.vue index 1bf2ef5..7d76427 100644 --- a/docs/.vitepress/theme/components/appendix/agent-intro/AgentQuickStartDemo.vue +++ b/docs/.vitepress/theme/components/appendix/agent-intro/AgentQuickStartDemo.vue @@ -476,7 +476,7 @@ const wait = (ms) => new Promise(r => setTimeout(r, ms)) .thinking-section { margin-bottom: 10px; border: 1px solid var(--vp-c-divider); - border-radius: 8px; + border-radius: 6px; overflow: hidden; } @@ -516,7 +516,7 @@ const wait = (ms) => new Promise(r => setTimeout(r, ms)) .tools-section { margin-bottom: 10px; border: 1px solid var(--vp-c-divider); - border-radius: 8px; + border-radius: 6px; overflow: hidden; } @@ -530,7 +530,7 @@ const wait = (ms) => new Promise(r => setTimeout(r, ms)) gap: 10px; padding: 10px; background: var(--vp-c-bg-soft); - border-radius: 8px; + border-radius: 6px; margin-bottom: 8px; border: 1px solid var(--vp-c-divider); transition: all 0.3s; @@ -603,7 +603,7 @@ const wait = (ms) => new Promise(r => setTimeout(r, ms)) padding: 12px; background: #dcfce7; border: 1px solid #86efac; - border-radius: 8px; + border-radius: 6px; } .response-header { @@ -628,7 +628,7 @@ const wait = (ms) => new Promise(r => setTimeout(r, ms)) background: var(--vp-c-brand); color: white; border: none; - border-radius: 8px; + border-radius: 6px; font-size: 13px; cursor: pointer; transition: background 0.2s; @@ -651,7 +651,7 @@ const wait = (ms) => new Promise(r => setTimeout(r, ms)) margin-top: 16px; padding: 12px 16px; background: var(--vp-c-brand-soft); - border-radius: 8px; + border-radius: 6px; font-size: 13px; } diff --git a/docs/.vitepress/theme/components/appendix/agent-intro/AgentTaskFlowDemo.vue b/docs/.vitepress/theme/components/appendix/agent-intro/AgentTaskFlowDemo.vue index 3f9fcb2..054f46e 100644 --- a/docs/.vitepress/theme/components/appendix/agent-intro/AgentTaskFlowDemo.vue +++ b/docs/.vitepress/theme/components/appendix/agent-intro/AgentTaskFlowDemo.vue @@ -163,7 +163,7 @@ const steps = [ .n { width: 26px; height: 26px; - border-radius: 8px; + border-radius: 6px; display: grid; place-items: center; background: var(--vp-c-bg-soft); diff --git a/docs/.vitepress/theme/components/appendix/agent-intro/AgentToolUseDemo.vue b/docs/.vitepress/theme/components/appendix/agent-intro/AgentToolUseDemo.vue index 1f8f292..79092a4 100644 --- a/docs/.vitepress/theme/components/appendix/agent-intro/AgentToolUseDemo.vue +++ b/docs/.vitepress/theme/components/appendix/agent-intro/AgentToolUseDemo.vue @@ -266,7 +266,7 @@ const reset = () => { currentStep.value = 0 } .user-input-bar { background: var(--vp-c-bg); border: 1px solid var(--vp-c-divider); - border-radius: 8px; + border-radius: 6px; padding: 10px 14px; margin-bottom: 16px; font-size: 14px; @@ -460,7 +460,7 @@ const reset = () => { currentStep.value = 0 } .final-result { background: var(--vp-c-brand-soft); border-left: 3px solid var(--vp-c-brand); - border-radius: 8px; + border-radius: 6px; padding: 12px 14px; margin-bottom: 16px; font-size: 13px; @@ -513,7 +513,7 @@ const reset = () => { currentStep.value = 0 } gap: 8px; padding: 10px 14px; background: var(--vp-c-brand-soft); - border-radius: 8px; + border-radius: 6px; font-size: 12px; color: var(--vp-c-text-1); } diff --git a/docs/.vitepress/theme/components/appendix/agent-intro/AgentWorkflowDemo.vue b/docs/.vitepress/theme/components/appendix/agent-intro/AgentWorkflowDemo.vue index d818a38..c53fe8e 100644 --- a/docs/.vitepress/theme/components/appendix/agent-intro/AgentWorkflowDemo.vue +++ b/docs/.vitepress/theme/components/appendix/agent-intro/AgentWorkflowDemo.vue @@ -179,7 +179,7 @@ const reset = () => { .icon { width: 28px; height: 28px; - border-radius: 8px; + border-radius: 6px; display: grid; place-items: center; background: var(--vp-c-bg-soft); diff --git a/docs/.vitepress/theme/components/appendix/ai-history/AttentionMechanismDemo.vue b/docs/.vitepress/theme/components/appendix/ai-history/AttentionMechanismDemo.vue index ab687d4..2dbf367 100644 --- a/docs/.vitepress/theme/components/appendix/ai-history/AttentionMechanismDemo.vue +++ b/docs/.vitepress/theme/components/appendix/ai-history/AttentionMechanismDemo.vue @@ -140,7 +140,7 @@ const getInsight = (index) => { margin-bottom: 24px; padding: 16px; background-color: var(--vp-c-bg-alt); - border-radius: 8px; + border-radius: 6px; } .word-token { diff --git a/docs/.vitepress/theme/components/appendix/ai-history/BackpropagationDemo.vue b/docs/.vitepress/theme/components/appendix/ai-history/BackpropagationDemo.vue index cb2ede9..98e9331 100644 --- a/docs/.vitepress/theme/components/appendix/ai-history/BackpropagationDemo.vue +++ b/docs/.vitepress/theme/components/appendix/ai-history/BackpropagationDemo.vue @@ -234,7 +234,7 @@ onMounted(() => { display: flex; justify-content: center; background-color: var(--vp-c-bg-alt); - border-radius: 8px; + border-radius: 6px; padding: 10px; } diff --git a/docs/.vitepress/theme/components/appendix/ai-history/CombinatorialExplosionDemo.vue b/docs/.vitepress/theme/components/appendix/ai-history/CombinatorialExplosionDemo.vue index 714fb26..87a6aa2 100644 --- a/docs/.vitepress/theme/components/appendix/ai-history/CombinatorialExplosionDemo.vue +++ b/docs/.vitepress/theme/components/appendix/ai-history/CombinatorialExplosionDemo.vue @@ -213,7 +213,7 @@ watch([featureCount, valuesPerFeature], () => { text-align: center; background-color: var(--vp-c-bg-alt); padding: 16px; - border-radius: 8px; + border-radius: 6px; } .formula-suffix { @@ -234,7 +234,7 @@ watch([featureCount, valuesPerFeature], () => { width: 50px; height: 50px; border: 2px solid; - border-radius: 8px; + border-radius: 6px; display: flex; flex-direction: column; align-items: center; diff --git a/docs/.vitepress/theme/components/appendix/ai-history/DiscriminativeVsGenerativeDemo.vue b/docs/.vitepress/theme/components/appendix/ai-history/DiscriminativeVsGenerativeDemo.vue index 3d4d34f..ebf6b9c 100644 --- a/docs/.vitepress/theme/components/appendix/ai-history/DiscriminativeVsGenerativeDemo.vue +++ b/docs/.vitepress/theme/components/appendix/ai-history/DiscriminativeVsGenerativeDemo.vue @@ -208,7 +208,7 @@ const mode = ref('discriminative') gap: 10px; background-color: var(--vp-c-bg); padding: 16px; - border-radius: 8px; + border-radius: 6px; } .io-box { diff --git a/docs/.vitepress/theme/components/appendix/ai-history/GPTEvolutionDemo.vue b/docs/.vitepress/theme/components/appendix/ai-history/GPTEvolutionDemo.vue index 080f914..0c65092 100644 --- a/docs/.vitepress/theme/components/appendix/ai-history/GPTEvolutionDemo.vue +++ b/docs/.vitepress/theme/components/appendix/ai-history/GPTEvolutionDemo.vue @@ -149,7 +149,7 @@ const handleTabClick = (tab) => { } .main-card { - border-radius: 8px; + border-radius: 6px; } .card-header { diff --git a/docs/.vitepress/theme/components/appendix/ai-history/NeuralNetworkVisualizationDemo.vue b/docs/.vitepress/theme/components/appendix/ai-history/NeuralNetworkVisualizationDemo.vue index 2c2e9af..6095a26 100644 --- a/docs/.vitepress/theme/components/appendix/ai-history/NeuralNetworkVisualizationDemo.vue +++ b/docs/.vitepress/theme/components/appendix/ai-history/NeuralNetworkVisualizationDemo.vue @@ -334,7 +334,7 @@ const isConnectionFocus = (c) => { display: flex; justify-content: center; background-color: var(--vp-c-bg-alt); - border-radius: 8px; + border-radius: 6px; padding: 10px; } diff --git a/docs/.vitepress/theme/components/appendix/ai-history/RuleBasedVsLearningDemo.vue b/docs/.vitepress/theme/components/appendix/ai-history/RuleBasedVsLearningDemo.vue index 8296d1e..7253124 100644 --- a/docs/.vitepress/theme/components/appendix/ai-history/RuleBasedVsLearningDemo.vue +++ b/docs/.vitepress/theme/components/appendix/ai-history/RuleBasedVsLearningDemo.vue @@ -274,7 +274,7 @@ const train = () => { .result-box { background-color: var(--vp-c-bg-alt); padding: 12px; - border-radius: 8px; + border-radius: 6px; border: 1px solid var(--vp-c-divider); text-align: center; } diff --git a/docs/.vitepress/theme/components/appendix/api-design/DocumentationDemo.vue b/docs/.vitepress/theme/components/appendix/api-design/DocumentationDemo.vue index ea59c4f..bb459eb 100644 --- a/docs/.vitepress/theme/components/appendix/api-design/DocumentationDemo.vue +++ b/docs/.vitepress/theme/components/appendix/api-design/DocumentationDemo.vue @@ -1,50 +1,496 @@ + diff --git a/docs/.vitepress/theme/components/appendix/api-design/ErrorHandlingDemo.vue b/docs/.vitepress/theme/components/appendix/api-design/ErrorHandlingDemo.vue index ecc0d11..320b2e5 100644 --- a/docs/.vitepress/theme/components/appendix/api-design/ErrorHandlingDemo.vue +++ b/docs/.vitepress/theme/components/appendix/api-design/ErrorHandlingDemo.vue @@ -1,97 +1,379 @@ + + + diff --git a/docs/.vitepress/theme/components/appendix/api-design/HttpMethodsDemo.vue b/docs/.vitepress/theme/components/appendix/api-design/HttpMethodsDemo.vue index 895009a..b3490d2 100644 --- a/docs/.vitepress/theme/components/appendix/api-design/HttpMethodsDemo.vue +++ b/docs/.vitepress/theme/components/appendix/api-design/HttpMethodsDemo.vue @@ -268,7 +268,7 @@ const currentMethod = computed(() => .method-detail { background: var(--vp-c-bg); border: 1px solid var(--vp-c-divider); - border-radius: 8px; + border-radius: 6px; padding: 20px; } @@ -306,7 +306,7 @@ const currentMethod = computed(() => align-items: center; padding: 12px; background: var(--vp-c-bg-soft); - border-radius: 8px; + border-radius: 6px; border: 1px solid var(--vp-c-divider); opacity: 0.6; transition: all 0.2s ease; @@ -361,7 +361,7 @@ const currentMethod = computed(() => .example-item { background: var(--vp-c-bg-soft); border: 1px solid var(--vp-c-divider); - border-radius: 8px; + border-radius: 6px; padding: 12px; margin-bottom: 12px; } diff --git a/docs/.vitepress/theme/components/appendix/api-design/RequestStructureDemo.vue b/docs/.vitepress/theme/components/appendix/api-design/RequestStructureDemo.vue index b934ffd..6bd4578 100644 --- a/docs/.vitepress/theme/components/appendix/api-design/RequestStructureDemo.vue +++ b/docs/.vitepress/theme/components/appendix/api-design/RequestStructureDemo.vue @@ -48,7 +48,7 @@ diff --git a/docs/.vitepress/theme/components/appendix/api-design/RestfulDesignDemo.vue b/docs/.vitepress/theme/components/appendix/api-design/RestfulDesignDemo.vue index 0a7f26f..89dbfb7 100644 --- a/docs/.vitepress/theme/components/appendix/api-design/RestfulDesignDemo.vue +++ b/docs/.vitepress/theme/components/appendix/api-design/RestfulDesignDemo.vue @@ -194,9 +194,9 @@ const activePrinciple = computed(() => .restful-design-demo { border: 1px solid var(--vp-c-divider); background: var(--vp-c-bg-soft); - border-radius: 8px; + border-radius: 6px; padding: 1.5rem; - margin: 1rem 0; + margin: 0.5rem 0; } .header { @@ -225,8 +225,8 @@ const activePrinciple = computed(() => .principle-card { background: var(--vp-c-bg); border: 1px solid var(--vp-c-divider); - border-radius: 8px; - padding: 1rem; + border-radius: 6px; + padding: 0.75rem; cursor: pointer; transition: all 0.2s; text-align: center; @@ -260,7 +260,7 @@ const activePrinciple = computed(() => .detail-panel { background: var(--vp-c-bg); border: 1px solid var(--vp-c-divider); - border-radius: 8px; + border-radius: 6px; padding: 1.25rem; } diff --git a/docs/.vitepress/theme/components/appendix/api-design/StatusCodeDemo.vue b/docs/.vitepress/theme/components/appendix/api-design/StatusCodeDemo.vue index 043490f..37a39ff 100644 --- a/docs/.vitepress/theme/components/appendix/api-design/StatusCodeDemo.vue +++ b/docs/.vitepress/theme/components/appendix/api-design/StatusCodeDemo.vue @@ -417,7 +417,7 @@ function toggleExpand(number) { align-items: center; padding: 12px 20px; border: 1px solid var(--vp-c-divider); - border-radius: 8px; + border-radius: 6px; background: var(--vp-c-bg); cursor: pointer; transition: all 0.2s ease; @@ -465,7 +465,7 @@ function toggleExpand(number) { .status-card { background: var(--vp-c-bg); border: 1px solid var(--vp-c-divider); - border-radius: 8px; + border-radius: 6px; overflow: hidden; cursor: pointer; transition: all 0.2s ease; diff --git a/docs/.vitepress/theme/components/appendix/api-design/VersioningStrategyDemo.vue b/docs/.vitepress/theme/components/appendix/api-design/VersioningStrategyDemo.vue index cdce418..233fbe5 100644 --- a/docs/.vitepress/theme/components/appendix/api-design/VersioningStrategyDemo.vue +++ b/docs/.vitepress/theme/components/appendix/api-design/VersioningStrategyDemo.vue @@ -1,50 +1,413 @@ + diff --git a/docs/.vitepress/theme/components/appendix/api-intro/ApiConceptDemo.vue b/docs/.vitepress/theme/components/appendix/api-intro/ApiConceptDemo.vue index c5bf6e7..5cc2ad4 100644 --- a/docs/.vitepress/theme/components/appendix/api-intro/ApiConceptDemo.vue +++ b/docs/.vitepress/theme/components/appendix/api-intro/ApiConceptDemo.vue @@ -250,7 +250,7 @@ function sendRequest() { background: var(--vp-c-brand); color: white; border: none; - border-radius: 8px; + border-radius: 6px; font-weight: 600; cursor: pointer; transition: opacity 0.2s; @@ -303,7 +303,7 @@ function sendRequest() { font-family: monospace; font-size: 12px; overflow-x: auto; - overflow-y: auto; + max-height: 200px; margin: 0; } diff --git a/docs/.vitepress/theme/components/appendix/api-intro/ApiDocumentDemo.vue b/docs/.vitepress/theme/components/appendix/api-intro/ApiDocumentDemo.vue index 1412d1f..ea6765d 100644 --- a/docs/.vitepress/theme/components/appendix/api-intro/ApiDocumentDemo.vue +++ b/docs/.vitepress/theme/components/appendix/api-intro/ApiDocumentDemo.vue @@ -150,7 +150,7 @@ const isHuman = ref(false) .api-doc { background: #1e293b; - border-radius: 8px; + border-radius: 6px; padding: 20px; color: #e2e8f0; font-family: monospace; diff --git a/docs/.vitepress/theme/components/appendix/api-intro/ApiMethodDemo.vue b/docs/.vitepress/theme/components/appendix/api-intro/ApiMethodDemo.vue index 8e8d121..fa1b1ed 100644 --- a/docs/.vitepress/theme/components/appendix/api-intro/ApiMethodDemo.vue +++ b/docs/.vitepress/theme/components/appendix/api-intro/ApiMethodDemo.vue @@ -237,7 +237,7 @@ .method-examples { background: var(--vp-c-bg-soft); padding: 12px; - border-radius: 8px; + border-radius: 6px; margin-bottom: 12px; } @@ -249,7 +249,7 @@ .method-tip { padding: 10px 12px; - border-radius: 8px; + border-radius: 6px; font-size: 12px; line-height: 1.5; } @@ -339,7 +339,7 @@ tr:last-child td { .tips { background: var(--vp-c-bg); padding: 16px; - border-radius: 8px; + border-radius: 6px; font-size: 14px; line-height: 1.8; color: var(--vp-c-text-2); diff --git a/docs/.vitepress/theme/components/appendix/api-intro/ApiPlayground.vue b/docs/.vitepress/theme/components/appendix/api-intro/ApiPlayground.vue index c4c7d00..94666b8 100644 --- a/docs/.vitepress/theme/components/appendix/api-intro/ApiPlayground.vue +++ b/docs/.vitepress/theme/components/appendix/api-intro/ApiPlayground.vue @@ -345,7 +345,7 @@ function sendRequest() { background: var(--vp-c-brand); color: white; border: none; - border-radius: 8px; + border-radius: 6px; font-weight: 600; cursor: pointer; margin-top: 8px; @@ -415,7 +415,7 @@ function sendRequest() { padding: 12px; margin-bottom: 12px; overflow-x: auto; - overflow-y: auto; + max-height: 180px; } diff --git a/docs/.vitepress/theme/components/appendix/api-intro/ApiQuickStartDemo.vue b/docs/.vitepress/theme/components/appendix/api-intro/ApiQuickStartDemo.vue index b658cd6..51c6743 100644 --- a/docs/.vitepress/theme/components/appendix/api-intro/ApiQuickStartDemo.vue +++ b/docs/.vitepress/theme/components/appendix/api-intro/ApiQuickStartDemo.vue @@ -143,7 +143,7 @@ function callApi() { .response-card { background: var(--vp-c-bg); border: 1px solid var(--vp-c-divider); - border-radius: 8px; + border-radius: 6px; padding: 16px; animation: slideUp 0.3s ease-out; } diff --git a/docs/.vitepress/theme/components/appendix/api-intro/RealWorldApiDemo.vue b/docs/.vitepress/theme/components/appendix/api-intro/RealWorldApiDemo.vue index a5e7df2..b58e803 100644 --- a/docs/.vitepress/theme/components/appendix/api-intro/RealWorldApiDemo.vue +++ b/docs/.vitepress/theme/components/appendix/api-intro/RealWorldApiDemo.vue @@ -349,7 +349,7 @@ async function runDemo() { background: #1e293b; color: #e2e8f0; padding: 12px; - border-radius: 8px; + border-radius: 6px; font-family: 'Monaco', 'Menlo', monospace; font-size: 12px; line-height: 1.6; @@ -371,7 +371,7 @@ async function runDemo() { .summary { background: var(--vp-c-bg-soft); padding: 16px; - border-radius: 8px; + border-radius: 6px; font-size: 14px; line-height: 1.8; } @@ -443,7 +443,7 @@ async function runDemo() { .result-body { background: #f0fdf4; border: 2px solid #86efac; - border-radius: 8px; + border-radius: 6px; padding: 16px; font-size: 14px; line-height: 1.6; diff --git a/docs/.vitepress/theme/components/appendix/api-intro/RequestResponseFlow.vue b/docs/.vitepress/theme/components/appendix/api-intro/RequestResponseFlow.vue index 765326e..0360b84 100644 --- a/docs/.vitepress/theme/components/appendix/api-intro/RequestResponseFlow.vue +++ b/docs/.vitepress/theme/components/appendix/api-intro/RequestResponseFlow.vue @@ -163,7 +163,7 @@ function send() { padding: 10px 20px; font-size: 14px; font-weight: bold; - border-radius: 8px; + border-radius: 6px; cursor: pointer; transition: all 0.2s; } @@ -183,7 +183,7 @@ function send() { .result-box { padding: 12px 16px; - border-radius: 8px; + border-radius: 6px; font-size: 14px; font-weight: 500; } diff --git a/docs/.vitepress/theme/components/appendix/audio-intro/ASRvsTTSDemo.vue b/docs/.vitepress/theme/components/appendix/audio-intro/ASRvsTTSDemo.vue index 3ef382a..bd2f89b 100644 --- a/docs/.vitepress/theme/components/appendix/audio-intro/ASRvsTTSDemo.vue +++ b/docs/.vitepress/theme/components/appendix/audio-intro/ASRvsTTSDemo.vue @@ -378,7 +378,7 @@ onMounted(() => { .flow-section { background: var(--vp-c-bg); - border-radius: 8px; + border-radius: 6px; padding: 20px; } @@ -418,7 +418,7 @@ onMounted(() => { padding: 16px; background: var(--vp-c-bg-soft); border: 2px solid var(--vp-c-divider); - border-radius: 8px; + border-radius: 6px; cursor: pointer; display: flex; align-items: center; @@ -458,14 +458,14 @@ onMounted(() => { padding: 12px; background: var(--vp-c-bg-soft); border: 1px dashed var(--vp-c-divider); - border-radius: 8px; + border-radius: 6px; cursor: pointer; color: var(--vp-c-text-2); } .audio-preview { background: var(--vp-c-bg-soft); - border-radius: 8px; + border-radius: 6px; padding: 12px; } @@ -479,7 +479,7 @@ onMounted(() => { background: var(--vp-c-brand); color: white; border: none; - border-radius: 8px; + border-radius: 6px; cursor: pointer; font-weight: 500; display: flex; @@ -512,7 +512,7 @@ onMounted(() => { .result-box { background: var(--vp-c-bg-soft); - border-radius: 8px; + border-radius: 6px; padding: 16px; border: 1px solid var(--vp-c-divider); } @@ -540,7 +540,7 @@ textarea { width: 100%; padding: 12px; border: 1px solid var(--vp-c-divider); - border-radius: 8px; + border-radius: 6px; background: var(--vp-c-bg-soft); font-size: 14px; resize: vertical; @@ -654,7 +654,7 @@ textarea { .comparison-section { background: var(--vp-c-bg); - border-radius: 8px; + border-radius: 6px; padding: 20px; margin-bottom: 20px; } @@ -673,7 +673,7 @@ textarea { .comp-card { background: var(--vp-c-bg-soft); - border-radius: 8px; + border-radius: 6px; padding: 20px; text-align: center; } @@ -705,7 +705,7 @@ textarea { .pipeline-comparison { background: var(--vp-c-bg); - border-radius: 8px; + border-radius: 6px; padding: 20px; margin-bottom: 20px; } @@ -724,7 +724,7 @@ textarea { .pipeline { background: var(--vp-c-bg-soft); - border-radius: 8px; + border-radius: 6px; padding: 16px; } @@ -761,7 +761,7 @@ textarea { gap: 12px; padding: 16px; background: var(--vp-c-bg-mute); - border-radius: 8px; + border-radius: 6px; font-size: 13px; line-height: 1.6; } diff --git a/docs/.vitepress/theme/components/appendix/audio-intro/AudioQuickStartDemo.vue b/docs/.vitepress/theme/components/appendix/audio-intro/AudioQuickStartDemo.vue index d0c8d94..2ae3040 100644 --- a/docs/.vitepress/theme/components/appendix/audio-intro/AudioQuickStartDemo.vue +++ b/docs/.vitepress/theme/components/appendix/audio-intro/AudioQuickStartDemo.vue @@ -462,7 +462,7 @@ onUnmounted(() => { width: 100%; padding: 12px; border: 1px solid var(--vp-c-divider); - border-radius: 8px; + border-radius: 6px; font-size: 14px; resize: vertical; background: var(--vp-c-bg); @@ -504,7 +504,7 @@ onUnmounted(() => { .action-btn { padding: 12px 24px; border: none; - border-radius: 8px; + border-radius: 6px; background: var(--vp-c-bg-mute); cursor: pointer; font-size: 14px; @@ -557,7 +557,7 @@ onUnmounted(() => { width: 100%; padding: 16px; background: var(--vp-c-bg-soft); - border-radius: 8px; + border-radius: 6px; } .result-label { @@ -592,7 +592,7 @@ onUnmounted(() => { gap: 12px; padding: 16px; background: var(--vp-c-bg-soft); - border-radius: 8px; + border-radius: 6px; opacity: 0.5; transition: all 0.2s; } @@ -692,7 +692,7 @@ onUnmounted(() => { .embedding-viz { padding: 16px; background: var(--vp-c-bg-soft); - border-radius: 8px; + border-radius: 6px; } .viz-title { @@ -720,7 +720,7 @@ onUnmounted(() => { .waveform-container { padding: 16px; background: var(--vp-c-bg-soft); - border-radius: 8px; + border-radius: 6px; } .waveform-container canvas { @@ -777,7 +777,7 @@ onUnmounted(() => { gap: 8px; padding: 12px; background: var(--vp-c-bg); - border-radius: 8px; + border-radius: 6px; font-size: 13px; } diff --git a/docs/.vitepress/theme/components/appendix/audio-intro/AudioTokenizationDemo.vue b/docs/.vitepress/theme/components/appendix/audio-intro/AudioTokenizationDemo.vue index caa5dea..755cff7 100644 --- a/docs/.vitepress/theme/components/appendix/audio-intro/AudioTokenizationDemo.vue +++ b/docs/.vitepress/theme/components/appendix/audio-intro/AudioTokenizationDemo.vue @@ -334,7 +334,7 @@ onMounted(() => { diff --git a/docs/.vitepress/theme/components/appendix/backend-evolution/DeploymentFlowDemo.vue b/docs/.vitepress/theme/components/appendix/backend-evolution/DeploymentFlowDemo.vue index cec6cca..3f1e105 100644 --- a/docs/.vitepress/theme/components/appendix/backend-evolution/DeploymentFlowDemo.vue +++ b/docs/.vitepress/theme/components/appendix/backend-evolution/DeploymentFlowDemo.vue @@ -96,10 +96,10 @@ const steps = [ diff --git a/docs/.vitepress/theme/components/appendix/backend-evolution/KubernetesDemo.vue b/docs/.vitepress/theme/components/appendix/backend-evolution/KubernetesDemo.vue index 58dd14b..b7e6947 100644 --- a/docs/.vitepress/theme/components/appendix/backend-evolution/KubernetesDemo.vue +++ b/docs/.vitepress/theme/components/appendix/backend-evolution/KubernetesDemo.vue @@ -240,10 +240,10 @@ const resetCluster = () => { diff --git a/docs/.vitepress/theme/components/appendix/backend-evolution/MonolithReleaseRiskDemo.vue b/docs/.vitepress/theme/components/appendix/backend-evolution/MonolithReleaseRiskDemo.vue index cb8f4a2..90b1f0b 100644 --- a/docs/.vitepress/theme/components/appendix/backend-evolution/MonolithReleaseRiskDemo.vue +++ b/docs/.vitepress/theme/components/appendix/backend-evolution/MonolithReleaseRiskDemo.vue @@ -159,7 +159,7 @@ const deployRelease = () => { .module-btn { border: 1px solid var(--vp-c-divider); - border-radius: 8px; + border-radius: 6px; background: var(--vp-c-bg); padding: 0.5rem; font-size: 0.9rem; @@ -186,7 +186,7 @@ const deployRelease = () => { .risk-meter { background: var(--vp-c-bg); border-radius: 10px; - padding: 1rem; + padding: 0.75rem; border: 1px solid var(--vp-c-divider); } @@ -217,7 +217,7 @@ const deployRelease = () => { margin-top: 1rem; width: 100%; border: none; - border-radius: 8px; + border-radius: 6px; padding: 0.6rem; background: var(--vp-c-brand); color: #fff; @@ -229,7 +229,7 @@ const deployRelease = () => { margin-top: 0.75rem; font-size: 0.9rem; padding: 0.5rem 0.75rem; - border-radius: 8px; + border-radius: 6px; background: var(--vp-c-bg); border: 1px dashed var(--vp-c-divider); } diff --git a/docs/.vitepress/theme/components/appendix/backend-evolution/MonolithVsMicroserviceDemo.vue b/docs/.vitepress/theme/components/appendix/backend-evolution/MonolithVsMicroserviceDemo.vue index d8cd060..a906c21 100644 --- a/docs/.vitepress/theme/components/appendix/backend-evolution/MonolithVsMicroserviceDemo.vue +++ b/docs/.vitepress/theme/components/appendix/backend-evolution/MonolithVsMicroserviceDemo.vue @@ -79,10 +79,10 @@ const reset = () => { diff --git a/docs/.vitepress/theme/components/appendix/backend-evolution/ScalingStrategyDemo.vue b/docs/.vitepress/theme/components/appendix/backend-evolution/ScalingStrategyDemo.vue index 79d3457..a2a8381 100644 --- a/docs/.vitepress/theme/components/appendix/backend-evolution/ScalingStrategyDemo.vue +++ b/docs/.vitepress/theme/components/appendix/backend-evolution/ScalingStrategyDemo.vue @@ -62,10 +62,10 @@ const comparisonData = [ diff --git a/docs/.vitepress/theme/components/appendix/backend-languages/BackendLanguagesDemo.vue b/docs/.vitepress/theme/components/appendix/backend-languages/BackendLanguagesDemo.vue index 7c1d50b..d2c3020 100644 --- a/docs/.vitepress/theme/components/appendix/backend-languages/BackendLanguagesDemo.vue +++ b/docs/.vitepress/theme/components/appendix/backend-languages/BackendLanguagesDemo.vue @@ -230,12 +230,12 @@ const getCurrentLang = () => { diff --git a/docs/.vitepress/theme/components/appendix/canvas-intro/CanvasBasicsDemo.vue b/docs/.vitepress/theme/components/appendix/canvas-intro/CanvasBasicsDemo.vue index 0539726..66c49e3 100644 --- a/docs/.vitepress/theme/components/appendix/canvas-intro/CanvasBasicsDemo.vue +++ b/docs/.vitepress/theme/components/appendix/canvas-intro/CanvasBasicsDemo.vue @@ -13,85 +13,89 @@ --> @@ -101,8 +105,8 @@ import { ref, computed, watch, onMounted } from 'vue' const canvasRef = ref(null) const currentShape = ref('rect') -const fillColor = ref('#3498db') -const strokeColor = ref('#2c3e50') +const fillColor = ref('#3b82f6') +const strokeColor = ref('#1e293b') const strokeWidth = ref(2) const rectSize = ref(100) const circleRadius = ref(50) @@ -231,145 +235,193 @@ onMounted(() => { diff --git a/docs/.vitepress/theme/components/appendix/canvas-intro/CoordinateSystemDemo.vue b/docs/.vitepress/theme/components/appendix/canvas-intro/CoordinateSystemDemo.vue index d2f7259..d0582fd 100644 --- a/docs/.vitepress/theme/components/appendix/canvas-intro/CoordinateSystemDemo.vue +++ b/docs/.vitepress/theme/components/appendix/canvas-intro/CoordinateSystemDemo.vue @@ -272,117 +272,140 @@ onMounted(() => { diff --git a/docs/.vitepress/theme/components/appendix/canvas-intro/EventHandlingDemo.vue b/docs/.vitepress/theme/components/appendix/canvas-intro/EventHandlingDemo.vue index fdef10f..4d94f93 100644 --- a/docs/.vitepress/theme/components/appendix/canvas-intro/EventHandlingDemo.vue +++ b/docs/.vitepress/theme/components/appendix/canvas-intro/EventHandlingDemo.vue @@ -491,14 +491,15 @@ onMounted(() => { diff --git a/docs/.vitepress/theme/components/appendix/canvas-intro/ParticleSystemDemo.vue b/docs/.vitepress/theme/components/appendix/canvas-intro/ParticleSystemDemo.vue index 44a002d..a6f982b 100644 --- a/docs/.vitepress/theme/components/appendix/canvas-intro/ParticleSystemDemo.vue +++ b/docs/.vitepress/theme/components/appendix/canvas-intro/ParticleSystemDemo.vue @@ -378,14 +378,15 @@ onUnmounted(() => { diff --git a/docs/.vitepress/theme/components/appendix/canvas-intro/PerformanceDemo.vue b/docs/.vitepress/theme/components/appendix/canvas-intro/PerformanceDemo.vue index 324f11f..f94292c 100644 --- a/docs/.vitepress/theme/components/appendix/canvas-intro/PerformanceDemo.vue +++ b/docs/.vitepress/theme/components/appendix/canvas-intro/PerformanceDemo.vue @@ -553,14 +553,15 @@ onUnmounted(() => { diff --git a/docs/.vitepress/theme/components/appendix/cloud-iam/AccessKeyManagementDemo.vue b/docs/.vitepress/theme/components/appendix/cloud-iam/AccessKeyManagementDemo.vue index dfba066..09a716e 100644 --- a/docs/.vitepress/theme/components/appendix/cloud-iam/AccessKeyManagementDemo.vue +++ b/docs/.vitepress/theme/components/appendix/cloud-iam/AccessKeyManagementDemo.vue @@ -1,94 +1,50 @@ @@ -96,102 +52,52 @@ @@ -199,278 +105,154 @@ function deleteKey() { .access-key-management-demo { border: 1px solid var(--vp-c-divider); background: var(--vp-c-bg-soft); - border-radius: 8px; - padding: 1.5rem; - margin: 1rem 0; - max-height: 600px; - overflow-y: auto; + border-radius: 6px; + padding: 0.75rem; + margin: 0.5rem 0; } .demo-header { - margin-bottom: 1rem; + display: flex; + align-items: center; + gap: 0.5rem; + margin-bottom: 0.75rem; } -.demo-header h4 { - margin: 0 0 0.5rem 0; - font-weight: 800; - color: var(--vp-c-text-1); -} +.demo-header .icon { font-size: 1.25rem; } +.demo-header .title { font-weight: bold; font-size: 1rem; } +.demo-header .subtitle { color: var(--vp-c-text-2); font-size: 0.85rem; margin-left: 0.5rem; } -.intro-text { - margin: 0; - color: var(--vp-c-text-2); - font-size: 0.9rem; -} - -.demo-content { - margin-bottom: 1rem; -} - -.lifecycle-container { +.main-area { display: grid; grid-template-columns: 1fr auto; - gap: 1.25rem; - margin-bottom: 1.25rem; + gap: 0.75rem; + margin-bottom: 0.75rem; +} + +@media (max-width: 640px) { + .main-area { grid-template-columns: 1fr; } } -/* AK/SK Card */ .aksk-card { background: var(--vp-c-bg); border: 1px solid var(--vp-c-divider); - border-radius: 8px; - padding: 1.25rem; + border-radius: 6px; + padding: 0.75rem; } .card-header { display: flex; justify-content: space-between; align-items: center; - margin-bottom: 1rem; - padding-bottom: 0.75rem; + margin-bottom: 0.5rem; + padding-bottom: 0.4rem; border-bottom: 1px solid var(--vp-c-divider); } .status-badge { - padding: 0.25rem 0.75rem; - border-radius: 4px; - font-size: 0.75rem; - font-weight: 600; - text-transform: uppercase; -} - -.status-badge.active { - background: var(--vp-c-brand-soft); - color: var(--vp-c-brand-1); -} - -.status-badge.inactive { - background: rgba(var(--vp-c-brand-delta-rgb), 0.15); - color: var(--vp-c-brand-delta); -} - -.age-indicator { - font-size: 0.75rem; - color: var(--vp-c-text-3); -} - -.credentials-display { - display: flex; - flex-direction: column; - gap: 0.75rem; - margin-bottom: 1rem; -} - -.credential-row { - display: flex; - flex-direction: column; - gap: 0.25rem; -} - -.credential-row .label { + padding: 0.15rem 0.5rem; + border-radius: 3px; font-size: 0.7rem; - color: var(--vp-c-text-3); - text-transform: uppercase; + font-weight: 600; } -.value-container { +.status-badge.active { background: var(--vp-c-brand-soft); color: var(--vp-c-brand-1); } +.status-badge.inactive { background: rgba(239, 68, 68, 0.15); color: #dc2626; } + +.age { font-size: 0.7rem; color: var(--vp-c-text-3); } + +.credentials { display: flex; flex-direction: column; gap: 0.4rem; margin-bottom: 0.5rem; } + +.cred-row { display: flex; align-items: center; - gap: 0.5rem; + gap: 0.4rem; } -.value { +.cred-row .label { font-size: 0.7rem; color: var(--vp-c-text-3); min-width: 80px; } +.cred-row .value { flex: 1; - padding: 0.5rem 0.75rem; + padding: 0.3rem 0.5rem; background: var(--vp-c-bg-alt); border: 1px solid var(--vp-c-divider); - border-radius: 6px; + border-radius: 4px; font-family: var(--vp-font-family-mono); - font-size: 0.8rem; - word-break: break-all; + font-size: 0.7rem; color: var(--vp-c-text-1); } -.icon-btn { - padding: 0.5rem; +.toggle-btn { + padding: 0.25rem; background: var(--vp-c-bg); border: 1px solid var(--vp-c-divider); - border-radius: 6px; + border-radius: 4px; cursor: pointer; - font-size: 1rem; - transition: background 0.2s; + font-size: 0.85rem; } -.icon-btn:hover { - background: var(--vp-c-bg-alt); -} - -.usage-stats { +.stats { display: flex; gap: 1rem; - padding-top: 0.75rem; + padding-top: 0.4rem; border-top: 1px solid var(--vp-c-divider); } -.stat-item { - display: flex; - flex-direction: column; - gap: 0.125rem; -} +.stat { display: flex; flex-direction: column; } +.stat .v { font-size: 0.9rem; font-weight: 700; color: var(--vp-c-brand-1); } +.stat .l { font-size: 0.65rem; color: var(--vp-c-text-3); } -.stat-value { - font-size: 1.2rem; - font-weight: 700; - color: var(--vp-c-brand-1); -} +.action-panel { display: flex; flex-direction: column; gap: 0.4rem; } -.stat-label { - font-size: 0.7rem; - color: var(--vp-c-text-3); -} - -/* Action Panel */ -.action-panel { - display: flex; - flex-direction: column; - gap: 0.75rem; -} - -.action-btn { - display: flex; - align-items: center; - gap: 0.625rem; - padding: 0.875rem 1.125rem; +.btn { + padding: 0.5rem 0.75rem; border: 1px solid var(--vp-c-divider); - border-radius: 6px; + border-radius: 4px; cursor: pointer; - transition: all 0.2s ease; - font-size: 0.9rem; + font-size: 0.8rem; font-weight: 500; background: var(--vp-c-bg); color: var(--vp-c-text-1); + text-align: left; } -.action-btn:disabled { - opacity: 0.5; - cursor: not-allowed; -} +.btn:disabled { opacity: 0.5; cursor: not-allowed; } +.btn.primary { background: var(--vp-c-brand); border-color: var(--vp-c-brand); color: #fff; } +.btn.warning { background: rgba(234, 179, 8, 0.1); border-color: #eab308; color: #ca8a04; } +.btn.danger { background: rgba(239, 68, 68, 0.1); border-color: #dc2626; color: #dc2626; } -.action-btn.primary { - background: var(--vp-c-brand); - border-color: var(--vp-c-brand); - color: var(--vp-c-bg); -} - -.action-btn.primary:hover:not(:disabled) { - transform: translateY(-2px); - box-shadow: 0 4px 12px rgba(var(--vp-c-brand-rgb), 0.3); -} - -.action-btn.warning { - background: rgba(var(--vp-c-brand-delta-rgb), 0.1); - border-color: var(--vp-c-brand-delta); - color: var(--vp-c-brand-delta); -} - -.action-btn.warning:hover:not(:disabled) { - transform: translateY(-2px); - box-shadow: 0 4px 12px rgba(var(--vp-c-brand-delta-rgb), 0.2); -} - -.action-btn.danger { - background: rgba(var(--vp-c-brand-delta-rgb), 0.15); - border-color: var(--vp-c-brand-delta); - color: var(--vp-c-brand-delta); -} - -.action-btn.danger:hover { - transform: translateY(-2px); - box-shadow: 0 4px 12px rgba(var(--vp-c-brand-delta-rgb), 0.2); -} - -.btn-icon { - font-size: 1.2rem; -} - -/* Rotation Progress */ -.rotation-progress { +.rotation-bar { background: var(--vp-c-bg); border: 1px solid var(--vp-c-divider); - border-radius: 8px; - padding: 1.25rem; - margin-top: 1.25rem; -} - -.progress-bar { - height: 8px; - background: var(--vp-c-bg-alt); - border-radius: 4px; - overflow: hidden; + border-radius: 6px; + padding: 0.6rem; margin-bottom: 0.75rem; } -.progress-fill { +.bar { + height: 6px; + background: var(--vp-c-bg-alt); + border-radius: 3px; + overflow: hidden; + margin-bottom: 0.4rem; +} + +.fill { height: 100%; background: var(--vp-c-brand); - border-radius: 4px; - transition: width 0.3s ease; + transition: width 0.2s; } -.progress-text { - display: block; - text-align: center; - font-size: 0.9rem; - color: var(--vp-c-text-2); -} +.text { display: block; text-align: center; font-size: 0.8rem; color: var(--vp-c-text-2); } .info-box { - padding: 0.75rem; background: var(--vp-c-bg-alt); - border: 1px solid var(--vp-c-divider); - border-left: 4px solid var(--vp-c-brand); + padding: 0.6rem; border-radius: 6px; - font-size: 0.9rem; - line-height: 1.6; + font-size: 0.85rem; color: var(--vp-c-text-2); + display: flex; + gap: 0.25rem; } -.info-box strong { - color: var(--vp-c-text-1); -} - -@media (max-width: 768px) { - .lifecycle-container { - grid-template-columns: 1fr; - } - - .action-panel { - flex-direction: row; - flex-wrap: wrap; - } - - .action-btn { - flex: 1; - min-width: 140px; - } -} +.info-box .icon { flex-shrink: 0; } +.info-box strong { color: var(--vp-c-text-1); } diff --git a/docs/.vitepress/theme/components/appendix/cloud-iam/BestPracticesDemo.vue b/docs/.vitepress/theme/components/appendix/cloud-iam/BestPracticesDemo.vue index 592d7e5..3c79702 100644 --- a/docs/.vitepress/theme/components/appendix/cloud-iam/BestPracticesDemo.vue +++ b/docs/.vitepress/theme/components/appendix/cloud-iam/BestPracticesDemo.vue @@ -1,58 +1,36 @@ @@ -67,187 +45,41 @@ const bestPractices = [ icon: '👑', title: '根账号保护', priority: 'p0', - priorityText: 'P0 - 最高优先级', - color: 'rgba(var(--vp-c-brand-delta-rgb), 0.15)', - description: '根账号是云服务的所有者,拥有所有权限。必须实施最高级别的保护措施。', - checklist: [ - '启用 MFA(推荐硬件 MFA 设备)', - '创建 IAM 管理员用户用于日常操作', - '删除或锁定根账号的访问密钥', - '配置根账号使用告警', - '设置账号恢复联系信息' - ], - code: `# AWS CLI - 创建管理员用户并禁用根账号 AK -aws iam create-user --user-name AdminUser -aws iam attach-user-policy --user-name AdminUser \ - --policy-arn arn:aws:iam::aws:policy/AdministratorAccess - -# 删除根账号访问密钥(必须使用根账号登录控制台操作)`, - tools: ['硬件 MFA (YubiKey)', '虚拟 MFA (Google Authenticator)', 'AWS IAM', '阿里云 RAM'] + priorityText: 'P0', + description: '根账号是云服务的所有者,必须实施最高级别的保护。', + checklist: ['启用 MFA', '创建 IAM 管理员用户', '删除根账号访问密钥'] }, { icon: '👤', title: '用户权限最小化', priority: 'p0', - priorityText: 'P0 - 最高优先级', - color: 'rgba(var(--vp-c-brand-rgb), 0.1)', + priorityText: 'P0', description: '遵循最小权限原则,只授予用户完成工作所需的最低权限。', - checklist: [ - '避免使用 AdministratorAccess 等全权限策略', - '使用 IAM 用户组批量管理权限', - '定期审查和删除未使用的 IAM 用户', - '为不同角色创建细粒度的自定义策略', - '使用 IAM Access Analyzer 识别过度宽松的权限' - ], - code: `{ - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Action": [ - "s3:GetObject", - "s3:PutObject", - "s3:ListBucket" - ], - "Resource": [ - "arn:aws:s3:::my-bucket", - "arn:aws:s3:::my-bucket/*" - ], - "Condition": { - "StringEquals": { - "aws:RequestedRegion": "ap-northeast-1" - } - } - } - ] -}`, - tools: ['IAM Policy Simulator', 'IAM Access Analyzer', 'AWS CloudTrail', 'AWS Config'] + checklist: ['避免全权限策略', '使用用户组管理', '定期审查用户'] }, { icon: '🎭', title: '优先使用 IAM 角色', priority: 'p1', - priorityText: 'P1 - 高优先级', - color: 'var(--vp-c-brand-soft)', - description: 'IAM 角色没有长期凭证,通过临时凭证访问,大大降低凭证泄露风险。', - checklist: [ - 'EC2 实例使用实例角色(Instance Profile)', - 'Lambda 函数使用执行角色', - 'ECS 任务使用任务角色', - '跨账号访问使用角色扮演(AssumeRole)', - 'CI/CD 流水线使用 OIDC 联邦身份' - ], - code: `import boto3 - -# EC2 实例自动使用附加的实例角色 -# 无需提供任何凭证 -s3 = boto3.client('s3') - -# 跨账号角色扮演 -sts = boto3.client('sts') -assumed_role = sts.assume_role( - RoleArn='arn:aws:iam::123456789012:role/CrossAccountRole', - RoleSessionName='MyApplication', - DurationSeconds=3600 -) - -# 使用临时凭证 -temp_creds = assumed_role['Credentials'] -s3_cross = boto3.client( - 's3', - aws_access_key_id=temp_creds['AccessKeyId'], - aws_secret_access_key=temp_creds['SecretAccessKey'], - aws_session_token=temp_creds['SessionToken'] -)`, - tools: ['IAM Roles', 'AWS STS', 'EC2 Instance Profiles', 'Lambda Execution Roles'] + priorityText: 'P1', + description: 'IAM 角色没有长期凭证,通过临时凭证访问,降低泄露风险。', + checklist: ['EC2 使用实例角色', 'Lambda 使用执行角色', '跨账号用 AssumeRole'] }, { icon: '🔑', title: '访问密钥安全管理', priority: 'p1', - priorityText: 'P1 - 高优先级', - color: 'rgba(var(--vp-c-brand-rgb), 0.1)', - description: '如果必须使用访问密钥(AK/SK),需要实施严格的安全管理措施。', - checklist: [ - '绝不将 AK/SK 硬编码在代码或配置文件中', - '使用环境变量或密钥管理服务(如 AWS Secrets Manager)', - '每 90 天轮换一次访问密钥', - '定期审查和删除未使用的访问密钥', - '启用 CloudTrail 记录所有 AK/SK 的使用情况' - ], - code: `# ❌ 错误做法 - 硬编码凭证 -import boto3 - -s3 = boto3.client( - 's3', - aws_access_key_id='AKIAIOSFODNN7EXAMPLE', - aws_secret_access_key='wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY' -) - -# ✅ 正确做法 - 使用环境变量 -import boto3 -import os - -s3 = boto3.client( - 's3', - aws_access_key_id=os.environ.get('AWS_ACCESS_KEY_ID'), - aws_secret_access_key=os.environ.get('AWS_SECRET_ACCESS_KEY') -) - -# ✅ 正确做法 - 使用 AWS Secrets Manager -import boto3 -import json - -secrets_client = boto3.client('secretsmanager') -secret_value = secrets_client.get_secret_value(SecretId='my-app/credentials') -credentials = json.loads(secret_value['SecretString']) - -s3 = boto3.client( - 's3', - aws_access_key_id=credentials['access_key_id'], - aws_secret_access_key=credentials['secret_access_key'] -)`, - tools: ['AWS Secrets Manager', 'HashiCorp Vault', 'Azure Key Vault', 'GCP Secret Manager'] + priorityText: 'P1', + description: '如果必须使用 AK/SK,需要实施严格的安全管理措施。', + checklist: ['不硬编码凭证', '使用密钥管理服务', '定期轮换密钥'] }, { icon: '📊', title: '监控与审计', priority: 'p2', - priorityText: 'P2 - 中优先级', - color: 'var(--vp-c-bg-alt)', - description: '建立全面的监控和审计机制,及时发现和响应安全事件。', - checklist: [ - '启用 CloudTrail 记录所有 API 调用', - '配置关键操作的实时告警(根账号使用、策略变更等)', - '使用 IAM Access Analyzer 持续分析权限', - '定期审查 IAM 用户和权限配置', - '将日志存储到独立的审计账号,防止篡改' - ], - code: `# AWS CloudTrail 配置示例 -aws cloudtrail create-trail \ - --name OrganizationTrail \ - --s3-bucket-name my-cloudtrail-bucket \ - --is-organization-trail \ - --enable-log-file-validation \ - --is-multi-region-trail - -# CloudWatch 告警配置 - 根账号使用 -aws cloudwatch put-metric-alarm \ - --alarm-name RootAccountUsageAlarm \ - --alarm-description "Alert when root account is used" \ - --metric-name RootAccountUsage \ - --namespace CloudTrailMetrics \ - --statistic Sum \ - --period 300 \ - --evaluation-periods 1 \ - --threshold 1 \ - --comparison-operator GreaterThanOrEqualToThreshold - -# IAM Access Analyzer 创建分析器 -aws accessanalyzer create-analyzer \ - --analyzer-name MyOrgAnalyzer \ - --type ORGANIZATION`, - tools: ['AWS CloudTrail', 'AWS CloudWatch', 'IAM Access Analyzer', 'AWS Config', 'AWS Security Hub'] + priorityText: 'P2', + description: '建立全面的监控和审计机制,及时发现安全事件。', + checklist: ['启用 CloudTrail', '配置关键操作告警', '定期审查权限'] } ] @@ -260,236 +92,102 @@ function toggleCard(index) { .best-practices-demo { border: 1px solid var(--vp-c-divider); background: var(--vp-c-bg-soft); - border-radius: 8px; - padding: 1.5rem; - margin: 1rem 0; - max-height: 600px; - overflow-y: auto; + border-radius: 6px; + padding: 0.75rem; + margin: 0.5rem 0; } .demo-header { - margin-bottom: 1rem; + display: flex; + align-items: center; + gap: 0.5rem; + margin-bottom: 0.75rem; } -.demo-header h4 { - margin: 0 0 0.5rem 0; - font-weight: 800; - color: var(--vp-c-text-1); +.demo-header .icon { font-size: 1.25rem; } +.demo-header .title { font-weight: bold; font-size: 1rem; } +.demo-header .subtitle { color: var(--vp-c-text-2); font-size: 0.85rem; margin-left: 0.5rem; } + +.practices-list { + display: flex; + flex-direction: column; + gap: 0.4rem; + margin-bottom: 0.75rem; } -.intro-text { - margin: 0; - color: var(--vp-c-text-2); - font-size: 0.9rem; -} - -.demo-content { - margin-bottom: 1rem; -} - -.practices-grid { - display: grid; - gap: 1rem; -} - -.practice-card { +.practice-item { background: var(--vp-c-bg); border: 1px solid var(--vp-c-divider); - border-radius: 8px; - padding: 1.25rem; + border-radius: 6px; cursor: pointer; - transition: all 0.2s ease; + transition: all 0.2s; } -.practice-card:hover { - border-color: var(--vp-c-brand); - transform: translateY(-2px); -} - -.practice-card.expanded { +.practice-item:hover { border-color: var(--vp-c-brand); } +.practice-item.active { border-color: var(--vp-c-brand); background: var(--vp-c-bg-alt); } -.card-header { +.item-header { display: flex; align-items: center; - gap: 1rem; + gap: 0.5rem; + padding: 0.6rem; } -.icon-wrapper { - width: 48px; - height: 48px; - border-radius: 8px; - display: flex; - align-items: center; - justify-content: center; - font-size: 1.5rem; - flex-shrink: 0; -} +.item-icon { font-size: 1rem; } +.item-title { font-weight: 600; font-size: 0.85rem; flex: 1; } -.title-wrapper { - flex: 1; -} - -.title-wrapper h5 { - margin: 0 0 0.25rem 0; - font-size: 1.1rem; +.item-priority { + font-size: 0.65rem; font-weight: 700; - color: var(--vp-c-text-1); + padding: 0.15rem 0.4rem; + border-radius: 3px; } -.priority { - padding: 0.125rem 0.5rem; - border-radius: 4px; - font-size: 0.7rem; - font-weight: 600; - text-transform: uppercase; -} +.item-priority.p0 { background: var(--vp-c-danger); color: #fff; } +.item-priority.p1 { background: var(--vp-c-warning); color: #fff; } +.item-priority.p2 { background: var(--vp-c-brand-soft); color: var(--vp-c-brand-1); } -.priority.p0 { - background: rgba(var(--vp-c-brand-delta-rgb), 0.15); - color: var(--vp-c-brand-delta); -} - -.priority.p1 { - background: rgba(var(--vp-c-brand-rgb), 0.1); - color: var(--vp-c-brand); -} - -.priority.p2 { - background: var(--vp-c-brand-soft); - color: var(--vp-c-brand-1); -} - -.expand-icon { - font-size: 1.5rem; - font-weight: 300; - color: var(--vp-c-text-3); -} - -.card-body { - margin-top: 1.25rem; - padding-top: 1.25rem; +.item-body { + padding: 0 0.6rem 0.6rem; border-top: 1px solid var(--vp-c-divider); + margin-top: 0; + padding-top: 0.5rem; } -.description { - font-size: 0.95rem; - line-height: 1.6; - margin-bottom: 1rem; - color: var(--vp-c-text-2); -} - -.checklist { - margin-bottom: 1.25rem; -} - -.checklist h6 { - margin: 0 0 0.75rem 0; - font-size: 0.9rem; - font-weight: 700; - color: var(--vp-c-brand-1); -} - -.checklist ul { - list-style: none; - padding: 0; - margin: 0; -} - -.checklist li { - padding: 0.375rem 0; - padding-left: 1.5rem; - position: relative; - font-size: 0.9rem; - color: var(--vp-c-text-2); -} - -.checklist li:before { - content: '☐'; - position: absolute; - left: 0; - color: var(--vp-c-brand); -} - -.code-example { - margin-bottom: 1.25rem; -} - -.code-example h6 { - margin: 0 0 0.75rem 0; - font-size: 0.9rem; - font-weight: 700; - color: var(--vp-c-brand-1); -} - -.code-example pre { - background: var(--vp-c-bg); - border: 1px solid var(--vp-c-divider); - border-radius: 6px; - padding: 0.75rem; - overflow-x: auto; - margin: 0; -} - -.code-example code { - color: var(--vp-c-text-2); - font-family: var(--vp-font-family-mono); +.item-desc { font-size: 0.8rem; - line-height: 1.5; + color: var(--vp-c-text-2); + margin: 0 0 0.5rem; + line-height: 1.4; } -.tools h6 { - margin: 0 0 0.75rem 0; - font-size: 0.9rem; - font-weight: 700; - color: var(--vp-c-brand-1); -} - -.tool-tags { +.item-checks { display: flex; flex-wrap: wrap; - gap: 0.5rem; + gap: 0.3rem; } -.tool-tag { - padding: 0.25rem 0.75rem; +.check-tag { + font-size: 0.7rem; + padding: 0.15rem 0.4rem; background: var(--vp-c-brand-soft); color: var(--vp-c-brand-1); - border-radius: 4px; - font-size: 0.8rem; - font-weight: 500; + border-radius: 3px; } .info-box { - padding: 0.75rem; background: var(--vp-c-bg-alt); - border: 1px solid var(--vp-c-divider); - border-left: 4px solid var(--vp-c-brand); + padding: 0.6rem; border-radius: 6px; - font-size: 0.9rem; - line-height: 1.6; + font-size: 0.85rem; color: var(--vp-c-text-2); + display: flex; + gap: 0.25rem; } -.info-box strong { - color: var(--vp-c-text-1); -} - -@media (max-width: 768px) { - .card-header { - flex-wrap: wrap; - } - - .icon-wrapper { - width: 40px; - height: 40px; - font-size: 1.2rem; - } - - .title-wrapper h5 { - font-size: 1rem; - } -} +.info-box .icon { flex-shrink: 0; } +.info-box strong { color: var(--vp-c-text-1); } diff --git a/docs/.vitepress/theme/components/appendix/cloud-iam/CrossAccountAccessDemo.vue b/docs/.vitepress/theme/components/appendix/cloud-iam/CrossAccountAccessDemo.vue index 3ebf2e5..df8eead 100644 --- a/docs/.vitepress/theme/components/appendix/cloud-iam/CrossAccountAccessDemo.vue +++ b/docs/.vitepress/theme/components/appendix/cloud-iam/CrossAccountAccessDemo.vue @@ -1,230 +1,175 @@ diff --git a/docs/.vitepress/theme/components/appendix/cloud-iam/IAMStructure.vue b/docs/.vitepress/theme/components/appendix/cloud-iam/IAMStructure.vue index 37d1c1b..2423984 100644 --- a/docs/.vitepress/theme/components/appendix/cloud-iam/IAMStructure.vue +++ b/docs/.vitepress/theme/components/appendix/cloud-iam/IAMStructure.vue @@ -1,35 +1,42 @@ @@ -44,61 +51,36 @@ const layers = [ icon: '👑', name: '根账号', shortDesc: '最高权限', - description: '云账号的所有者,拥有全部资源的完全控制权限。建议仅用于初始设置,日常操作使用子账号。', - examples: [ - '创建/删除 IAM 用户', - '管理账单和支付方式', - '关闭账号', - '恢复已删除资源' - ] + description: '云账号的所有者,拥有全部资源的完全控制权限。建议仅用于初始设置。', + examples: ['创建/删除 IAM 用户', '管理账单和支付方式'] }, { icon: '👤', name: 'IAM 用户', shortDesc: '个人身份', - description: '为具体人员(如员工)创建的长期凭证,用于日常登录和操作云服务。', - examples: [ - '开发人员账号', - '运维人员账号', - '只读审计账号', - 'API 调用账号' - ] + description: '为具体人员创建的长期凭证,用于日常登录和操作云服务。', + examples: ['开发人员账号', '运维人员账号'] }, { icon: '👥', name: '用户组', shortDesc: '批量管理', description: '将多个用户归为一组,统一分配权限,简化管理。', - examples: [ - '开发组(开发权限)', - '运维组(运维权限)', - '财务组(账单权限)', - '审计组(只读权限)' - ] + examples: ['开发组', '运维组'] }, { icon: '🎭', name: '角色', shortDesc: '临时授权', description: '一种临时身份,可以被切换或赋予其他账号/服务,具有时效性更安全。', - examples: [ - '跨账号访问角色', - '服务角色(如 Lambda)', - '临时运维角色', - '第三方登录角色' - ] + examples: ['跨账号访问角色', '服务角色'] }, { icon: '📋', name: '策略', shortDesc: '权限规则', description: '定义"谁可以对什么资源执行什么操作"的规则文档,以 JSON 格式编写。', - examples: [ - '允许访问 S3 存储桶', - '禁止删除 EC2 实例', - '只允许查看 RDS', - '允许特定时间段访问' - ] + examples: ['允许访问 S3', '禁止删除 EC2'] } ] @@ -112,23 +94,45 @@ function selectLayer(index) { diff --git a/docs/.vitepress/theme/components/appendix/cloud-iam/IamRamComparisonDemo.vue b/docs/.vitepress/theme/components/appendix/cloud-iam/IamRamComparisonDemo.vue index 2ef8488..f346765 100644 --- a/docs/.vitepress/theme/components/appendix/cloud-iam/IamRamComparisonDemo.vue +++ b/docs/.vitepress/theme/components/appendix/cloud-iam/IamRamComparisonDemo.vue @@ -1,86 +1,61 @@ @@ -88,311 +63,153 @@ diff --git a/docs/.vitepress/theme/components/appendix/cloud-iam/IdentityProviderDemo.vue b/docs/.vitepress/theme/components/appendix/cloud-iam/IdentityProviderDemo.vue index c39a2c8..0740bfe 100644 --- a/docs/.vitepress/theme/components/appendix/cloud-iam/IdentityProviderDemo.vue +++ b/docs/.vitepress/theme/components/appendix/cloud-iam/IdentityProviderDemo.vue @@ -1,44 +1,37 @@ @@ -49,356 +42,140 @@ import { ref, computed } from 'vue' const currentStep = ref(0) const steps = [ - { title: '用户访问应用', desc: '用户尝试访问企业应用' }, - { title: '重定向到 IdP', desc: '应用将用户重定向到身份提供商' }, - { title: '用户登录认证', desc: '用户在 IdP 输入企业账号密码' }, - { title: '颁发 SAML 令牌', desc: 'IdP 验证成功后颁发 SAML Assertion' }, - { title: '返回应用', desc: '携带令牌返回企业应用' }, - { title: '换取云凭证', desc: '应用使用令牌换取云临时凭证' }, - { title: '访问云资源', desc: '使用临时凭证访问云资源' } + { title: '访问应用' }, + { title: '重定向 IdP' }, + { title: '用户登录' }, + { title: '颁发令牌' }, + { title: '返回应用' }, + { title: '换取凭证' }, + { title: '访问资源' } ] const stepDetails = [ - { - title: '用户访问企业应用', - detail: '用户打开浏览器,访问企业内部的业务系统(如 CRM、ERP 等)。此时用户尚未登录,应用检测到用户没有有效的会话。', - flow: [ - { from: { name: '用户', type: 'user' }, action: '访问 →', to: { name: '企业应用', type: 'app' } } - ] - }, - { - title: '应用重定向到 IdP', - detail: '应用发现用户未登录,生成 SAML Request,将用户浏览器重定向到企业的身份提供商(IdP,如 Azure AD、Okta 等)。', - code: `// SAML Request 示例 - - - https://app.example.com - -`, - flow: [ - { from: { name: '企业应用', type: 'app' }, action: '重定向 →', to: { name: 'IdP', type: 'idp' } } - ] - }, - { - title: '用户在 IdP 登录', - detail: '用户在 IdP 的登录页面输入企业账号和密码。IdP 验证用户身份,可能还需要进行 MFA 多因素认证。', - flow: [ - { from: { name: '用户', type: 'user' }, action: '登录 →', to: { name: 'IdP', type: 'idp' } } - ] - }, - { - title: 'IdP 颁发 SAML Assertion', - detail: '用户认证成功后,IdP 生成包含用户身份和属性的 SAML Assertion(断言),并使用 IdP 的私钥签名。', - code: ` - - - - - user@example.com - - - - - Admin - - - -`, - flow: [ - { from: { name: 'IdP', type: 'idp' }, action: '颁发令牌 →', to: { name: '用户浏览器', type: 'user' } } - ] - }, - { - title: '返回企业应用', - detail: 'IdP 通过浏览器将 SAML Response POST 到企业应用。应用验证 SAML 断言的签名,确认用户身份,建立用户会话。', - flow: [ - { from: { name: '用户浏览器', type: 'user' }, action: 'POST 令牌 →', to: { name: '企业应用', type: 'app' } } - ] - }, - { - title: '换取云临时凭证', - detail: '企业应用使用 SAML Assertion 向云厂商的 STS 服务请求临时安全凭证。云服务验证 SAML 断言后,颁发临时 AK/SK/Token。', - code: `# Python 示例:使用 SAML 换取 AWS 临时凭证 -import boto3 - -# 创建 STS 客户端 -sts = boto3.client('sts') - -# 使用 SAML 断言请求临时凭证 -response = sts.assume_role_with_saml( - RoleArn='arn:aws:iam::123456789012:role/SAML-Role', - PrincipalArn='arn:aws:iam::123456789012:saml-provider/Okta', - SAMLAssertion='VGhpcyBpcyBhIHRlc3QgU0FNTCBhc3NlcnRpb24=', - DurationSeconds=3600 -) - -# 获取临时凭证 -credentials = response['Credentials'] -print(f"Access Key: {credentials['AccessKeyId']}") -print(f"Secret Key: {credentials['SecretAccessKey']}") -print(f"Session Token: {credentials['SessionToken']}")`, - flow: [ - { from: { name: '企业应用', type: 'app' }, action: 'AssumeRole →', to: { name: '云 STS', type: 'cloud' } } - ] - }, - { - title: '访问云资源', - detail: '企业应用使用获取到的临时凭证,调用云服务的 API 访问资源(如 S3、EC2、数据库等)。临时凭证有过期时间,到期后需要重新获取。', - flow: [ - { from: { name: '企业应用', type: 'app' }, action: '访问资源 →', to: { name: '云服务', type: 'cloud' } } - ] - } + { title: '用户访问企业应用', detail: '用户打开浏览器访问企业业务系统,应用检测到用户没有有效会话。', flow: [{ from: { name: '用户' }, action: '访问 →', to: { name: '企业应用' } }] }, + { title: '应用重定向到 IdP', detail: '应用生成 SAML Request,将用户重定向到企业身份提供商。', flow: [{ from: { name: '应用' }, action: '重定向 →', to: { name: 'IdP' } }] }, + { title: '用户在 IdP 登录', detail: '用户在 IdP 登录页面输入企业账号密码,可能需要 MFA 认证。', flow: [{ from: { name: '用户' }, action: '登录 →', to: { name: 'IdP' } }] }, + { title: 'IdP 颁发 SAML 令牌', detail: '用户认证成功后,IdP 生成包含用户身份的 SAML Assertion。', flow: [{ from: { name: 'IdP' }, action: '颁发 →', to: { name: '令牌' } }] }, + { title: '返回企业应用', detail: 'IdP 通过浏览器将 SAML Response POST 到企业应用。', flow: [{ from: { name: '浏览器' }, action: 'POST →', to: { name: '应用' } }] }, + { title: '换取云临时凭证', detail: '应用使用 SAML 向云 STS 服务请求临时安全凭证。', flow: [{ from: { name: '应用' }, action: 'AssumeRole →', to: { name: '云 STS' } }] }, + { title: '访问云资源', detail: '应用使用临时凭证调用云服务 API 访问资源。', flow: [{ from: { name: '应用' }, action: '访问 →', to: { name: '云服务' } }] } ] -const currentStepData = computed(() => { - if (currentStep.value === null) return null - return stepDetails[currentStep.value] -}) - -function goToStep(index) { - currentStep.value = index -} +const currentStepData = computed(() => stepDetails[currentStep.value]) diff --git a/docs/.vitepress/theme/components/appendix/cloud-iam/MfaSecurityDemo.vue b/docs/.vitepress/theme/components/appendix/cloud-iam/MfaSecurityDemo.vue index b1d6cdb..50c118c 100644 --- a/docs/.vitepress/theme/components/appendix/cloud-iam/MfaSecurityDemo.vue +++ b/docs/.vitepress/theme/components/appendix/cloud-iam/MfaSecurityDemo.vue @@ -1,98 +1,82 @@ diff --git a/docs/.vitepress/theme/components/appendix/cloud-iam/PermissionHierarchyDemo.vue b/docs/.vitepress/theme/components/appendix/cloud-iam/PermissionHierarchyDemo.vue index ab956fc..5595d73 100644 --- a/docs/.vitepress/theme/components/appendix/cloud-iam/PermissionHierarchyDemo.vue +++ b/docs/.vitepress/theme/components/appendix/cloud-iam/PermissionHierarchyDemo.vue @@ -1,12 +1,13 @@ @@ -74,71 +54,42 @@ const selectedLevel = ref(0) const hierarchyLevels = [ { icon: '👑', - name: '根账号 (Root)', + name: '根账号', scope: '全账号最高权限', - scenario: '账号所有者,拥有云服务的所有权限', - permissions: [ - { name: '完全管理权限', type: 'full' }, - { name: '账单管理', type: 'billing' }, - { name: '组织架构管理', type: 'org' }, - { name: '关闭账号', type: 'critical' }, - { name: '恢复已删除资源', type: 'admin' } - ] + scenario: '账号所有者,拥有所有权限', + permissions: [{ name: '完全管理' }, { name: '账单管理' }, { name: '关闭账号' }] }, { icon: '👤', name: 'IAM 管理员', scope: 'IAM 全权限', scenario: '管理所有 IAM 用户、角色、策略', - permissions: [ - { name: '创建/删除用户', type: 'user' }, - { name: '创建/删除角色', type: 'role' }, - { name: '管理策略', type: 'policy' }, - { name: '查看凭证报告', type: 'audit' } - ] + permissions: [{ name: '创建/删除用户' }, { name: '管理策略' }, { name: '查看凭证' }] }, { icon: '👥', - name: '普通 IAM 用户', + name: '普通用户', scope: '受限权限', - scenario: '日常开发人员,只能访问特定资源', - permissions: [ - { name: '只读访问 EC2', type: 'read' }, - { name: '读写指定 S3 桶', type: 'limited' }, - { name: '查看 CloudWatch 日志', type: 'read' }, - { name: '无法创建 IAM 资源', type: 'deny' } - ] + scenario: '日常开发,只能访问特定资源', + permissions: [{ name: '只读 EC2' }, { name: '读写 S3' }, { name: '查看日志' }] }, { icon: '🎭', - name: '临时角色 (Role)', + name: '临时角色', scope: '按策略定义', - scenario: '跨账号访问、服务角色、临时授权', - permissions: [ - { name: '临时凭证 (1-12小时)', type: 'temp' }, - { name: '按信任策略授权', type: 'conditional' }, - { name: '可跨账号使用', type: 'cross' }, - { name: '无长期凭证', type: 'secure' } - ] + scenario: '跨账号访问、临时授权', + permissions: [{ name: '临时凭证' }, { name: '跨账号' }, { name: '无长期凭证' }] }, { icon: '🔑', - name: '服务账号 / 应用', - scope: 'API 访问权限', - scenario: '应用程序、CI/CD 流水线、自动化脚本', - permissions: [ - { name: 'AK/SK 或临时凭证', type: 'api' }, - { name: '特定服务 API 权限', type: 'service' }, - { name: '无控制台访问', type: 'programmatic' }, - { name: '建议定期轮换密钥', type: 'security' } - ] + name: '服务账号', + scope: 'API 访问', + scenario: '应用程序、CI/CD 流水线', + permissions: [{ name: 'AK/SK' }, { name: '特定 API' }, { name: '定期轮换' }] } ] -const selectedLevelData = computed(() => { - if (selectedLevel.value === null) return null - return hierarchyLevels[selectedLevel.value] -}) +const selectedLevelData = computed(() => hierarchyLevels[selectedLevel.value]) function selectLevel(index) { selectedLevel.value = index @@ -149,248 +100,102 @@ function selectLevel(index) { .permission-hierarchy-demo { border: 1px solid var(--vp-c-divider); background: var(--vp-c-bg-soft); - border-radius: 8px; - padding: 1.5rem; - margin: 1rem 0; - max-height: 600px; - overflow-y: auto; + border-radius: 6px; + padding: 0.75rem; + margin: 0.5rem 0; } .demo-header { - margin-bottom: 1rem; -} - -.demo-header h4 { - margin: 0 0 0.5rem 0; - font-weight: 800; - color: var(--vp-c-text-1); -} - -.intro-text { - margin: 0; - color: var(--vp-c-text-2); - font-size: 0.9rem; -} - -.demo-content { - margin-bottom: 1rem; -} - -.hierarchy-container { display: flex; - flex-direction: column; + align-items: center; gap: 0.5rem; - margin-bottom: 1.5rem; + margin-bottom: 0.75rem; } +.demo-header .icon { font-size: 1.25rem; } +.demo-header .title { font-weight: bold; font-size: 1rem; } +.demo-header .subtitle { color: var(--vp-c-text-2); font-size: 0.85rem; margin-left: 0.5rem; } + +.main-area { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 0.75rem; + margin-bottom: 0.75rem; +} + +@media (max-width: 640px) { + .main-area { grid-template-columns: 1fr; } +} + +.levels-list { display: flex; flex-direction: column; gap: 0.4rem; } + .level-row { display: flex; align-items: center; - gap: 0.75rem; - padding: 0.75rem 1rem; + gap: 0.5rem; + padding: 0.5rem; background: var(--vp-c-bg); border: 1px solid var(--vp-c-divider); border-radius: 6px; cursor: pointer; - transition: all 0.2s ease; + transition: all 0.2s; } -.level-row:hover, -.level-row.active { - background: var(--vp-c-bg-alt); - border-color: var(--vp-c-brand); - transform: translateX(4px); -} +.level-row:hover { border-color: var(--vp-c-brand); } +.level-row.active { border-color: var(--vp-c-brand); background: var(--vp-c-brand-soft); } -.level-icon { - font-size: 1.6rem; - width: 40px; - height: 40px; - display: flex; - align-items: center; - justify-content: center; - background: var(--vp-c-bg-alt); - border: 1px solid var(--vp-c-divider); - border-radius: 6px; -} +.level-icon { font-size: 1.25rem; } -.level-content { - display: flex; - flex-direction: column; - flex: 1; -} - -.level-name { - font-weight: 600; - font-size: 0.95rem; - color: var(--vp-c-text-1); -} - -.level-scope { - font-size: 0.75rem; - color: var(--vp-c-text-3); -} - -.permission-badges { - display: flex; - gap: 0.25rem; - flex-wrap: wrap; - justify-content: flex-end; - max-width: 150px; -} - -.badge { - padding: 0.125rem 0.5rem; - background: var(--vp-c-bg-alt); - border: 1px solid var(--vp-c-divider); - border-radius: 4px; - font-size: 0.65rem; - white-space: nowrap; - color: var(--vp-c-text-2); -} - -.badge.more { - background: var(--vp-c-brand-soft); - border-color: var(--vp-c-brand); - color: var(--vp-c-brand-1); -} +.level-info { display: flex; flex-direction: column; } +.level-name { font-weight: 600; font-size: 0.85rem; color: var(--vp-c-text-1); } +.level-scope { font-size: 0.7rem; color: var(--vp-c-text-2); } .detail-panel { background: var(--vp-c-bg); border: 1px solid var(--vp-c-divider); - border-radius: 8px; - padding: 1rem; + border-radius: 6px; + padding: 0.75rem; } -.detail-panel h5 { - margin: 0 0 1rem 0; - font-size: 1.1rem; - font-weight: 700; +.detail-title { + font-weight: 600; + font-size: 0.9rem; color: var(--vp-c-brand-1); - padding-bottom: 0.5rem; + margin-bottom: 0.5rem; + padding-bottom: 0.4rem; border-bottom: 1px solid var(--vp-c-divider); } -.detail-section { - margin-bottom: 0.75rem; +.detail-row { display: flex; - align-items: flex-start; - gap: 0.5rem; + gap: 0.3rem; + margin-bottom: 0.3rem; + font-size: 0.8rem; } -.detail-section .label { - font-weight: 600; - color: var(--vp-c-text-2); - min-width: 80px; - font-size: 0.85rem; -} +.detail-row .label { color: var(--vp-c-text-2); } +.detail-row .value { color: var(--vp-c-text-1); } -.detail-section .value { - color: var(--vp-c-text-1); - font-size: 0.9rem; - flex: 1; -} - -.permissions-grid { - display: flex; - flex-wrap: wrap; - gap: 0.375rem; - flex: 1; -} +.perms-list { display: flex; flex-wrap: wrap; gap: 0.3rem; margin-top: 0.5rem; } .perm-tag { - padding: 0.25rem 0.625rem; - border-radius: 4px; font-size: 0.7rem; - font-weight: 500; -} - -.perm-tag.full { - background: rgba(var(--vp-c-brand-delta-rgb), 0.15); - color: var(--vp-c-brand-delta); -} - -.perm-tag.read, -.perm-tag.user, -.perm-tag.readonly { + padding: 0.15rem 0.4rem; background: var(--vp-c-brand-soft); color: var(--vp-c-brand-1); -} - -.perm-tag.limited, -.perm-tag.role { - background: rgba(var(--vp-c-brand-rgb), 0.1); - color: var(--vp-c-brand); -} - -.perm-tag.deny, -.perm-tag.critical { - background: rgba(var(--vp-c-brand-delta-rgb), 0.15); - color: var(--vp-c-brand-delta); -} - -.perm-tag.temp, -.perm-tag.conditional, -.perm-tag.service { - background: var(--vp-c-bg-soft); - border: 1px solid var(--vp-c-divider); - color: var(--vp-c-text-1); -} - -.perm-tag.admin, -.perm-tag.org, -.perm-tag.billing { - background: rgba(var(--vp-c-brand-rgb), 0.15); - color: var(--vp-c-brand); -} - -.perm-tag.api, -.perm-tag.programmatic, -.perm-tag.security { - background: var(--vp-c-bg-alt); - border: 1px solid var(--vp-c-divider); - color: var(--vp-c-text-2); -} - -.perm-tag.cross, -.perm-tag.secure, -.perm-tag.audit, -.perm-tag.policy { - background: var(--vp-c-bg-soft); - border: 1px solid var(--vp-c-divider); - color: var(--vp-c-text-2); + border-radius: 3px; } .info-box { - padding: 0.75rem; background: var(--vp-c-bg-alt); - border: 1px solid var(--vp-c-divider); - border-left: 4px solid var(--vp-c-brand); + padding: 0.6rem; border-radius: 6px; - font-size: 0.9rem; - line-height: 1.6; + font-size: 0.85rem; color: var(--vp-c-text-2); + display: flex; + gap: 0.25rem; } -.info-box strong { - color: var(--vp-c-text-1); -} - -@media (max-width: 768px) { - .level-row { - flex-wrap: wrap; - } - - .permission-badges { - width: 100%; - justify-content: flex-start; - max-width: none; - margin-top: 0.5rem; - } - - .detail-section { - flex-direction: column; - gap: 0.25rem; - } -} +.info-box .icon { flex-shrink: 0; } +.info-box strong { color: var(--vp-c-text-1); } diff --git a/docs/.vitepress/theme/components/appendix/cloud-iam/PolicyEditorDemo.vue b/docs/.vitepress/theme/components/appendix/cloud-iam/PolicyEditorDemo.vue index dc9d157..e1a7d0c 100644 --- a/docs/.vitepress/theme/components/appendix/cloud-iam/PolicyEditorDemo.vue +++ b/docs/.vitepress/theme/components/appendix/cloud-iam/PolicyEditorDemo.vue @@ -1,5 +1,11 @@ @@ -87,10 +98,10 @@ const effectList = computed(() => { diff --git a/docs/.vitepress/theme/components/appendix/cloud-services/ApiCallDemo.vue b/docs/.vitepress/theme/components/appendix/cloud-services/ApiCallDemo.vue index 3833b91..a566f58 100644 --- a/docs/.vitepress/theme/components/appendix/cloud-services/ApiCallDemo.vue +++ b/docs/.vitepress/theme/components/appendix/cloud-services/ApiCallDemo.vue @@ -103,10 +103,10 @@ function reset() { diff --git a/docs/.vitepress/theme/components/appendix/cloud-storage-cdn/CachePolicyDemo.vue b/docs/.vitepress/theme/components/appendix/cloud-storage-cdn/CachePolicyDemo.vue index 5894f0d..964f51c 100644 --- a/docs/.vitepress/theme/components/appendix/cloud-storage-cdn/CachePolicyDemo.vue +++ b/docs/.vitepress/theme/components/appendix/cloud-storage-cdn/CachePolicyDemo.vue @@ -1,14 +1,20 @@ @@ -22,7 +28,7 @@ const description = ref('展示CDN和对象存储的缓存策略配置,包括 diff --git a/docs/.vitepress/theme/components/appendix/cloud-storage-cdn/EdgeNodeDistributionDemo.vue b/docs/.vitepress/theme/components/appendix/cloud-storage-cdn/EdgeNodeDistributionDemo.vue index 423a5c2..45c0c01 100644 --- a/docs/.vitepress/theme/components/appendix/cloud-storage-cdn/EdgeNodeDistributionDemo.vue +++ b/docs/.vitepress/theme/components/appendix/cloud-storage-cdn/EdgeNodeDistributionDemo.vue @@ -22,7 +22,7 @@ const description = ref('展示CDN边缘节点在全球的分布情况和调度 diff --git a/docs/.vitepress/theme/components/appendix/cloud-storage-cdn/ObjectStorageDemo.vue b/docs/.vitepress/theme/components/appendix/cloud-storage-cdn/ObjectStorageDemo.vue index 38ca274..595c1c9 100644 --- a/docs/.vitepress/theme/components/appendix/cloud-storage-cdn/ObjectStorageDemo.vue +++ b/docs/.vitepress/theme/components/appendix/cloud-storage-cdn/ObjectStorageDemo.vue @@ -1,12 +1,9 @@ - @@ -262,83 +230,79 @@ const getFileIcon = (type) => { .object-storage-demo { border: 1px solid var(--vp-c-divider); background: var(--vp-c-bg-soft); - border-radius: 12px; - padding: 1.5rem; - margin: 1.5rem 0; - font-family: var(--vp-font-family-base); + border-radius: 6px; + padding: 0.75rem; + margin: 0.5rem 0; } -.header { - margin-bottom: 1.5rem; +.demo-header { + display: flex; + align-items: center; + gap: 0.4rem; + margin-bottom: 0.5rem; } -.title { - font-weight: 700; - font-size: 1.2rem; - margin-bottom: 0.25rem; -} - -.subtitle { - color: var(--vp-c-text-2); - font-size: 0.9rem; -} +.demo-header .icon { font-size: 1rem; } +.demo-header .title { font-weight: bold; font-size: 0.9rem; } +.demo-header .subtitle { color: var(--vp-c-text-2); font-size: 0.75rem; margin-left: 0.4rem; } .storage-architecture { - display: flex; - flex-direction: column; - gap: 0.75rem; + display: grid; + grid-template-columns: 1fr 1fr; + grid-template-rows: auto auto; + gap: 0.4rem; } .account-layer { - background: linear-gradient(135deg, #e0e7ff, #c7d2fe); - padding: 1rem; - border-radius: 10px; + background: var(--vp-c-brand-soft); + padding: 0.5rem; + border-radius: 6px; text-align: center; - border: 2px solid #6366f1; + border: 2px solid var(--vp-c-brand); + grid-column: 1 / -1; } .account-icon { - font-size: 2rem; - margin-bottom: 0.25rem; + font-size: 1.2rem; + margin-bottom: 0.15rem; } .account-name { font-weight: 600; - font-size: 0.95rem; - color: #4338ca; + font-size: 0.8rem; + color: var(--vp-c-brand-1); + margin-bottom: 0.1rem; } .account-desc { - font-size: 0.75rem; - color: #6366f1; - margin-top: 0.25rem; + font-size: 0.65rem; + color: var(--vp-c-text-2); + margin-top: 0.1rem; } .connector { - text-align: center; - color: var(--vp-c-text-3); - font-size: 1.25rem; + display: none; } .buckets-container { background: var(--vp-c-bg); border: 2px solid var(--vp-c-divider); - border-radius: 10px; - padding: 1rem; + border-radius: 6px; + padding: 0.5rem; } .section-title { display: flex; align-items: center; - gap: 0.5rem; + gap: 0.3rem; font-weight: 600; - font-size: 0.9rem; - margin-bottom: 0.75rem; + font-size: 0.75rem; + margin-bottom: 0.4rem; color: var(--vp-c-text-1); } .section-desc { - font-size: 0.75rem; + font-size: 0.6rem; font-weight: normal; color: var(--vp-c-text-2); margin-left: auto; @@ -346,17 +310,16 @@ const getFileIcon = (type) => { .buckets-row { display: flex; - gap: 0.75rem; - flex-wrap: wrap; + gap: 0.4rem; } .bucket-card { flex: 1; - min-width: 140px; + min-width: 80px; background: var(--vp-c-bg-soft); - border: 2px solid var(--vp-c-divider); - border-radius: 8px; - padding: 0.75rem; + border: 1px solid var(--vp-c-divider); + border-radius: 4px; + padding: 0.35rem; text-align: center; cursor: pointer; transition: all 0.2s; @@ -364,67 +327,64 @@ const getFileIcon = (type) => { .bucket-card:hover { border-color: var(--vp-c-brand); - transform: translateY(-2px); + transform: translateY(-1px); } .bucket-card.active { border-color: var(--vp-c-brand); background: var(--vp-c-brand-soft); - box-shadow: 0 0 0 3px var(--vp-c-brand-dimm); + box-shadow: 0 0 2px var(--vp-c-brand-dimm); } -.bucket-icon { - font-size: 1.75rem; - margin-bottom: 0.25rem; -} +.bucket-icon { font-size: 1.1rem; margin-bottom: 0.1rem; } .bucket-name { font-weight: 600; - font-size: 0.8rem; + font-size: 0.65rem; color: var(--vp-c-text-1); word-break: break-all; } .bucket-meta { - font-size: 0.7rem; + font-size: 0.55rem; color: var(--vp-c-text-2); - margin-top: 0.25rem; + margin-top: 0.1rem; } .bucket-size { - font-size: 0.75rem; + font-size: 0.6rem; color: var(--vp-c-brand); font-weight: 600; - margin-top: 0.25rem; + margin-top: 0.1rem; } .objects-container { background: var(--vp-c-bg); border: 2px solid var(--vp-c-divider); - border-radius: 10px; - padding: 1rem; - min-height: 150px; + border-radius: 6px; + padding: 0.5rem; + min-height: 80px; } .objects-list { display: flex; flex-direction: column; - gap: 0.5rem; + gap: 0.25rem; } .object-item { display: flex; align-items: center; - gap: 0.75rem; - padding: 0.5rem 0.75rem; + gap: 0.3rem; + padding: 0.3rem 0.4rem; background: var(--vp-c-bg-soft); - border-radius: 6px; + border-radius: 3px; cursor: pointer; transition: all 0.2s; } .object-item:hover { - background: var(--vp-c-bg-mute); + background: var(--vp-c-bg-alt); } .object-item.selected { @@ -432,9 +392,7 @@ const getFileIcon = (type) => { border: 1px solid var(--vp-c-brand); } -.object-icon { - font-size: 1.25rem; -} +.object-icon { font-size: 0.85rem; } .object-info { flex: 1; @@ -442,7 +400,7 @@ const getFileIcon = (type) => { } .object-key { - font-size: 0.8rem; + font-size: 0.65rem; font-weight: 600; color: var(--vp-c-text-1); white-space: nowrap; @@ -451,67 +409,63 @@ const getFileIcon = (type) => { } .object-meta { - font-size: 0.7rem; + font-size: 0.55rem; color: var(--vp-c-text-2); } .object-arrow { color: var(--vp-c-text-3); + font-size: 0.7rem; } -.objects-placeholder { +.objects-placeholder, +.metadata-placeholder { text-align: center; - padding: 2rem; + padding: 0.75rem; color: var(--vp-c-text-2); - font-size: 0.9rem; + font-size: 0.7rem; } .metadata-container { background: var(--vp-c-bg); border: 2px solid var(--vp-c-divider); - border-radius: 10px; - padding: 1rem; - min-height: 150px; + border-radius: 6px; + padding: 0.5rem; + min-height: 80px; } .metadata-content { display: grid; grid-template-columns: 1fr 1fr; - gap: 1rem; -} - -@media (max-width: 768px) { - .metadata-content { - grid-template-columns: 1fr; - } + gap: 0.4rem; } .metadata-section { background: var(--vp-c-bg-soft); - border-radius: 8px; - padding: 0.75rem; + border-radius: 4px; + padding: 0.35rem; } .metadata-section-title { font-weight: 600; - font-size: 0.85rem; + font-size: 0.65rem; color: var(--vp-c-brand); - margin-bottom: 0.5rem; - padding-bottom: 0.5rem; + margin-bottom: 0.25rem; + padding-bottom: 0.25rem; border-bottom: 1px solid var(--vp-c-divider); } .metadata-list { display: flex; flex-direction: column; - gap: 0.4rem; + gap: 0.15rem; } .metadata-item { display: flex; flex-direction: column; - gap: 0.1rem; - font-size: 0.75rem; + gap: 0; + font-size: 0.6rem; } .metadata-key { @@ -525,66 +479,17 @@ const getFileIcon = (type) => { word-break: break-all; } -.metadata-placeholder { - text-align: center; - padding: 2rem; - color: var(--vp-c-text-2); - font-size: 0.9rem; -} - -.architecture-summary { - background: var(--vp-c-bg); - border-radius: 10px; - padding: 1.25rem; - margin-top: 1.5rem; - border: 1px solid var(--vp-c-divider); -} - -.summary-title { - font-weight: 700; - font-size: 1rem; - margin-bottom: 1rem; - color: var(--vp-c-text-1); -} - -.summary-grid { - display: grid; - grid-template-columns: repeat(2, 1fr); - gap: 1rem; -} - -@media (max-width: 640px) { - .summary-grid { - grid-template-columns: 1fr; - } -} - -.summary-item { - display: flex; - gap: 0.75rem; - padding: 0.75rem; - background: var(--vp-c-bg-soft); - border-radius: 8px; -} - -.summary-icon { - font-size: 1.5rem; -} - -.summary-text { - display: flex; - flex-direction: column; - gap: 0.25rem; -} - -.summary-text strong { - font-size: 0.9rem; - color: var(--vp-c-text-1); -} - -.summary-text span { +.info-box { + background: var(--vp-c-bg-alt); + padding: 0.5rem; + border-radius: 4px; font-size: 0.75rem; color: var(--vp-c-text-2); - line-height: 1.4; + margin-top: 0.5rem; + display: flex; + gap: 0.2rem; + grid-column: 1 / -1; } + +.info-box .icon { flex-shrink: 0; } diff --git a/docs/.vitepress/theme/components/appendix/cloud-storage-cdn/TrafficSchedulingDemo.vue b/docs/.vitepress/theme/components/appendix/cloud-storage-cdn/TrafficSchedulingDemo.vue index 6da61e1..a22c918 100644 --- a/docs/.vitepress/theme/components/appendix/cloud-storage-cdn/TrafficSchedulingDemo.vue +++ b/docs/.vitepress/theme/components/appendix/cloud-storage-cdn/TrafficSchedulingDemo.vue @@ -1,14 +1,20 @@ @@ -20,31 +26,58 @@ const description = ref('展示CDN的智能流量调度机制,包括负载均 diff --git a/docs/.vitepress/theme/components/appendix/cloud-storage-cdn/UploadProcessDemo.vue b/docs/.vitepress/theme/components/appendix/cloud-storage-cdn/UploadProcessDemo.vue index f353d49..b724044 100644 --- a/docs/.vitepress/theme/components/appendix/cloud-storage-cdn/UploadProcessDemo.vue +++ b/docs/.vitepress/theme/components/appendix/cloud-storage-cdn/UploadProcessDemo.vue @@ -4,9 +4,10 @@ --> @@ -312,7 +318,7 @@ const resetDemo = () => { background: var(--vp-c-bg); border: 2px solid var(--vp-c-divider); border-radius: 10px; - padding: 1rem; + padding: 0.75rem; text-align: center; cursor: pointer; transition: all 0.2s; @@ -386,7 +392,7 @@ const resetDemo = () => { gap: 0.75rem; padding: 0.75rem; background: var(--vp-c-bg-soft); - border-radius: 8px; + border-radius: 6px; border-left: 3px solid var(--vp-c-divider); transition: all 0.3s; } diff --git a/docs/.vitepress/theme/components/appendix/cloud-topology/AvailabilityZoneDemo.vue b/docs/.vitepress/theme/components/appendix/cloud-topology/AvailabilityZoneDemo.vue index 4a60407..b15b252 100644 --- a/docs/.vitepress/theme/components/appendix/cloud-topology/AvailabilityZoneDemo.vue +++ b/docs/.vitepress/theme/components/appendix/cloud-topology/AvailabilityZoneDemo.vue @@ -232,7 +232,7 @@ const getAzStatusText = (az) => { .availability-zone-demo { padding: 20px; background: #f5f7fa; - border-radius: 8px; + border-radius: 6px; } .control-panel { @@ -243,7 +243,7 @@ const getAzStatusText = (az) => { margin-bottom: 20px; padding: 16px; background: white; - border-radius: 8px; + border-radius: 6px; } .architecture-container { @@ -284,7 +284,7 @@ const getAzStatusText = (az) => { gap: 6px; padding: 12px 16px; background: #f5f7fa; - border-radius: 8px; + border-radius: 6px; min-width: 80px; } @@ -507,7 +507,7 @@ const getAzStatusText = (az) => { margin-top: 20px; padding: 16px; background: white; - border-radius: 8px; + border-radius: 6px; box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1); } diff --git a/docs/.vitepress/theme/components/appendix/cloud-topology/ComputeTopologyDemo.vue b/docs/.vitepress/theme/components/appendix/cloud-topology/ComputeTopologyDemo.vue index 3d3ded7..2e87017 100644 --- a/docs/.vitepress/theme/components/appendix/cloud-topology/ComputeTopologyDemo.vue +++ b/docs/.vitepress/theme/components/appendix/cloud-topology/ComputeTopologyDemo.vue @@ -309,7 +309,7 @@ const backendServices = [ .compute-topology-demo { padding: 20px; background: #f5f7fa; - border-radius: 8px; + border-radius: 6px; } .control-panel { @@ -319,7 +319,7 @@ const backendServices = [ margin-bottom: 20px; padding: 16px; background: white; - border-radius: 8px; + border-radius: 6px; flex-wrap: wrap; gap: 12px; } @@ -355,7 +355,7 @@ const backendServices = [ .server-rack { background: #f5f7fa; - border-radius: 8px; + border-radius: 6px; padding: 12px; } @@ -406,7 +406,7 @@ const backendServices = [ .hypervisor { background: #f5f7fa; - border-radius: 8px; + border-radius: 6px; padding: 12px; } @@ -507,7 +507,7 @@ const backendServices = [ .control-plane { background: #f0f9ff; border: 1px solid #bae6fd; - border-radius: 8px; + border-radius: 6px; padding: 12px; } @@ -564,7 +564,7 @@ const backendServices = [ .node { background: #f8fafc; border: 1px solid #e2e8f0; - border-radius: 8px; + border-radius: 6px; padding: 12px; } @@ -636,7 +636,7 @@ const backendServices = [ .functions-section, .backend-section { background: #fafafa; - border-radius: 8px; + border-radius: 6px; padding: 12px; } @@ -685,7 +685,7 @@ const backendServices = [ .function-card { background: white; border: 1px solid #e4e7ed; - border-radius: 8px; + border-radius: 6px; padding: 12px; } @@ -752,7 +752,7 @@ const backendServices = [ margin-top: 20px; padding: 16px; background: white; - border-radius: 8px; + border-radius: 6px; box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1); } diff --git a/docs/.vitepress/theme/components/appendix/cloud-topology/DisasterRecoveryDemo.vue b/docs/.vitepress/theme/components/appendix/cloud-topology/DisasterRecoveryDemo.vue index 6026493..81900b2 100644 --- a/docs/.vitepress/theme/components/appendix/cloud-topology/DisasterRecoveryDemo.vue +++ b/docs/.vitepress/theme/components/appendix/cloud-topology/DisasterRecoveryDemo.vue @@ -291,7 +291,7 @@ const drComparisonData = [ .disaster-recovery-demo { padding: 20px; background: #f5f7fa; - border-radius: 8px; + border-radius: 6px; } .control-panel { @@ -301,7 +301,7 @@ const drComparisonData = [ margin-bottom: 20px; padding: 16px; background: white; - border-radius: 8px; + border-radius: 6px; flex-wrap: wrap; gap: 12px; } @@ -386,7 +386,7 @@ const drComparisonData = [ /* AZ Block */ .az-block { background: #f5f7fa; - border-radius: 8px; + border-radius: 6px; padding: 12px; border-left: 4px solid #409eff; transition: all 0.3s; @@ -530,7 +530,7 @@ const drComparisonData = [ gap: 12px; padding: 16px; background: #f5f7fa; - border-radius: 8px; + border-radius: 6px; } .link-group { @@ -711,7 +711,7 @@ const drComparisonData = [ .explanation-card { background: white; - border-radius: 8px; + border-radius: 6px; padding: 16px; } diff --git a/docs/.vitepress/theme/components/appendix/cloud-topology/NetworkFlowDemo.vue b/docs/.vitepress/theme/components/appendix/cloud-topology/NetworkFlowDemo.vue index 2f0a4df..dabd252 100644 --- a/docs/.vitepress/theme/components/appendix/cloud-topology/NetworkFlowDemo.vue +++ b/docs/.vitepress/theme/components/appendix/cloud-topology/NetworkFlowDemo.vue @@ -211,7 +211,7 @@ const subnets = [ .network-flow-demo { padding: 20px; background: #f5f7fa; - border-radius: 8px; + border-radius: 6px; } .control-panel { @@ -221,7 +221,7 @@ const subnets = [ margin-bottom: 20px; padding: 16px; background: white; - border-radius: 8px; + border-radius: 6px; flex-wrap: wrap; gap: 12px; } @@ -273,7 +273,7 @@ const subnets = [ gap: 6px; padding: 12px 16px; background: #f5f7fa; - border-radius: 8px; + border-radius: 6px; min-width: 80px; } @@ -401,7 +401,7 @@ const subnets = [ gap: 6px; padding: 12px; background: #f5f7fa; - border-radius: 8px; + border-radius: 6px; min-width: 100px; border: 2px solid transparent; transition: all 0.3s; @@ -475,7 +475,7 @@ const subnets = [ .subnet { background: #f5f7fa; - border-radius: 8px; + border-radius: 6px; padding: 12px; border-left: 4px solid; } @@ -586,7 +586,7 @@ const subnets = [ margin-top: 20px; padding: 16px; background: white; - border-radius: 8px; + border-radius: 6px; box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1); } diff --git a/docs/.vitepress/theme/components/appendix/cloud-topology/ResourceTopologyDemo.vue b/docs/.vitepress/theme/components/appendix/cloud-topology/ResourceTopologyDemo.vue index b75ebee..a3a4eb1 100644 --- a/docs/.vitepress/theme/components/appendix/cloud-topology/ResourceTopologyDemo.vue +++ b/docs/.vitepress/theme/components/appendix/cloud-topology/ResourceTopologyDemo.vue @@ -168,7 +168,7 @@ const selectRegion = (id) => { .resource-topology-demo { padding: 20px; background: #f5f7fa; - border-radius: 8px; + border-radius: 6px; } .controls { @@ -218,7 +218,7 @@ const selectRegion = (id) => { align-items: center; padding: 16px; border: 2px solid #e4e7ed; - border-radius: 8px; + border-radius: 6px; cursor: pointer; transition: all 0.3s; } @@ -254,7 +254,7 @@ const selectRegion = (id) => { .region-card { padding: 12px; border: 2px solid #e4e7ed; - border-radius: 8px; + border-radius: 6px; cursor: pointer; transition: all 0.3s; } @@ -304,7 +304,7 @@ const selectRegion = (id) => { .resource-category { padding: 16px; border: 2px solid #e4e7ed; - border-radius: 8px; + border-radius: 6px; transition: all 0.3s; } @@ -357,7 +357,7 @@ const selectRegion = (id) => { margin-top: 20px; padding: 16px; background: #f0f9eb; - border-radius: 8px; + border-radius: 6px; border-left: 4px solid #67c23a; } diff --git a/docs/.vitepress/theme/components/appendix/cloud-topology/StorageTopologyDemo.vue b/docs/.vitepress/theme/components/appendix/cloud-topology/StorageTopologyDemo.vue index 89180be..082a198 100644 --- a/docs/.vitepress/theme/components/appendix/cloud-topology/StorageTopologyDemo.vue +++ b/docs/.vitepress/theme/components/appendix/cloud-topology/StorageTopologyDemo.vue @@ -297,7 +297,7 @@ const comparisonData = [ .storage-topology-demo { padding: 20px; background: #f5f7fa; - border-radius: 8px; + border-radius: 6px; } .control-panel { @@ -307,7 +307,7 @@ const comparisonData = [ margin-bottom: 20px; padding: 16px; background: white; - border-radius: 8px; + border-radius: 6px; flex-wrap: wrap; gap: 12px; } @@ -344,7 +344,7 @@ const comparisonData = [ .method-card { background: #f5f7fa; - border-radius: 8px; + border-radius: 6px; padding: 16px; text-align: center; position: relative; @@ -382,7 +382,7 @@ const comparisonData = [ background: #333; color: white; padding: 10px 14px; - border-radius: 8px; + border-radius: 6px; font-size: 12px; z-index: 10; margin-bottom: 8px; @@ -398,7 +398,7 @@ const comparisonData = [ .gateway-card { background: #f5f7fa; - border-radius: 8px; + border-radius: 6px; padding: 12px; border-left: 4px solid; } diff --git a/docs/.vitepress/theme/components/appendix/cloud-topology/SubnetDesignDemo.vue b/docs/.vitepress/theme/components/appendix/cloud-topology/SubnetDesignDemo.vue index 1806776..ae89f87 100644 --- a/docs/.vitepress/theme/components/appendix/cloud-topology/SubnetDesignDemo.vue +++ b/docs/.vitepress/theme/components/appendix/cloud-topology/SubnetDesignDemo.vue @@ -202,7 +202,7 @@ const selectSubnet = (index) => { .subnet-design-demo { padding: 20px; background: #f5f7fa; - border-radius: 8px; + border-radius: 6px; } .control-panel { @@ -213,7 +213,7 @@ const selectSubnet = (index) => { margin-bottom: 20px; padding: 16px; background: white; - border-radius: 8px; + border-radius: 6px; } .panel-section { @@ -278,7 +278,7 @@ const selectSubnet = (index) => { .subnet-cell { background: #f5f7fa; - border-radius: 8px; + border-radius: 6px; padding: 12px; border: 2px solid transparent; cursor: pointer; @@ -356,7 +356,7 @@ const selectSubnet = (index) => { background: #333; color: white; padding: 10px 14px; - border-radius: 8px; + border-radius: 6px; font-size: 12px; z-index: 10; margin-bottom: 8px; @@ -373,7 +373,7 @@ const selectSubnet = (index) => { /* Calculation Panel */ .calculation-panel { background: white; - border-radius: 8px; + border-radius: 6px; padding: 20px; margin-bottom: 20px; } @@ -447,7 +447,7 @@ const selectSubnet = (index) => { /* Tips Panel */ .tips-panel { background: #f0f9eb; - border-radius: 8px; + border-radius: 6px; padding: 20px; border-left: 4px solid #67c23a; } diff --git a/docs/.vitepress/theme/components/appendix/cloud-topology/VpcArchitectureDemo.vue b/docs/.vitepress/theme/components/appendix/cloud-topology/VpcArchitectureDemo.vue index 8054208..3610288 100644 --- a/docs/.vitepress/theme/components/appendix/cloud-topology/VpcArchitectureDemo.vue +++ b/docs/.vitepress/theme/components/appendix/cloud-topology/VpcArchitectureDemo.vue @@ -186,7 +186,7 @@ const borderDevices = [ .vpc-architecture-demo { padding: 20px; background: #f5f7fa; - border-radius: 8px; + border-radius: 6px; } .control-panel { @@ -287,7 +287,7 @@ const borderDevices = [ gap: 6px; padding: 12px 16px; background: white; - border-radius: 8px; + border-radius: 6px; border: 2px solid #e0e0e0; cursor: pointer; transition: all 0.3s; @@ -404,7 +404,7 @@ const borderDevices = [ /* AZ Container */ .az-container { background: #f5f7fa; - border-radius: 8px; + border-radius: 6px; padding: 12px; } diff --git a/docs/.vitepress/theme/components/appendix/component-state-management/ComponentHierarchyDemo.vue b/docs/.vitepress/theme/components/appendix/component-state-management/ComponentHierarchyDemo.vue index cd9e955..596a627 100644 --- a/docs/.vitepress/theme/components/appendix/component-state-management/ComponentHierarchyDemo.vue +++ b/docs/.vitepress/theme/components/appendix/component-state-management/ComponentHierarchyDemo.vue @@ -194,12 +194,12 @@ const selectNode = (nodeId) => { diff --git a/docs/.vitepress/theme/components/appendix/computer-fundamentals/AlgorithmDemo.vue b/docs/.vitepress/theme/components/appendix/computer-fundamentals/AlgorithmDemo.vue new file mode 100644 index 0000000..de2b34c --- /dev/null +++ b/docs/.vitepress/theme/components/appendix/computer-fundamentals/AlgorithmDemo.vue @@ -0,0 +1,535 @@ + + + + + diff --git a/docs/.vitepress/theme/components/appendix/computer-fundamentals/CompilerDemo.vue b/docs/.vitepress/theme/components/appendix/computer-fundamentals/CompilerDemo.vue new file mode 100644 index 0000000..aa380ea --- /dev/null +++ b/docs/.vitepress/theme/components/appendix/computer-fundamentals/CompilerDemo.vue @@ -0,0 +1,598 @@ + + + + + diff --git a/docs/.vitepress/theme/components/appendix/computer-fundamentals/CpuArchitectureDemo.vue b/docs/.vitepress/theme/components/appendix/computer-fundamentals/CpuArchitectureDemo.vue new file mode 100644 index 0000000..b1d3dc2 --- /dev/null +++ b/docs/.vitepress/theme/components/appendix/computer-fundamentals/CpuArchitectureDemo.vue @@ -0,0 +1,245 @@ + + + + + diff --git a/docs/.vitepress/theme/components/appendix/computer-fundamentals/DataStructureDemo.vue b/docs/.vitepress/theme/components/appendix/computer-fundamentals/DataStructureDemo.vue new file mode 100644 index 0000000..7b35040 --- /dev/null +++ b/docs/.vitepress/theme/components/appendix/computer-fundamentals/DataStructureDemo.vue @@ -0,0 +1,529 @@ + + + + + diff --git a/docs/.vitepress/theme/components/appendix/computer-fundamentals/EncodingDemo.vue b/docs/.vitepress/theme/components/appendix/computer-fundamentals/EncodingDemo.vue new file mode 100644 index 0000000..a82176c --- /dev/null +++ b/docs/.vitepress/theme/components/appendix/computer-fundamentals/EncodingDemo.vue @@ -0,0 +1,265 @@ + + + + + diff --git a/docs/.vitepress/theme/components/appendix/computer-fundamentals/FilesystemDemo.vue b/docs/.vitepress/theme/components/appendix/computer-fundamentals/FilesystemDemo.vue new file mode 100644 index 0000000..0920868 --- /dev/null +++ b/docs/.vitepress/theme/components/appendix/computer-fundamentals/FilesystemDemo.vue @@ -0,0 +1,292 @@ + + + + + diff --git a/docs/.vitepress/theme/components/appendix/computer-fundamentals/LanguageMapDemo.vue b/docs/.vitepress/theme/components/appendix/computer-fundamentals/LanguageMapDemo.vue new file mode 100644 index 0000000..2711c7f --- /dev/null +++ b/docs/.vitepress/theme/components/appendix/computer-fundamentals/LanguageMapDemo.vue @@ -0,0 +1,404 @@ + + + + + diff --git a/docs/.vitepress/theme/components/appendix/computer-fundamentals/LogicGateDemo.vue b/docs/.vitepress/theme/components/appendix/computer-fundamentals/LogicGateDemo.vue new file mode 100644 index 0000000..f198b86 --- /dev/null +++ b/docs/.vitepress/theme/components/appendix/computer-fundamentals/LogicGateDemo.vue @@ -0,0 +1,374 @@ + + + + + diff --git a/docs/.vitepress/theme/components/appendix/computer-fundamentals/MemoryDemo.vue b/docs/.vitepress/theme/components/appendix/computer-fundamentals/MemoryDemo.vue new file mode 100644 index 0000000..39369c9 --- /dev/null +++ b/docs/.vitepress/theme/components/appendix/computer-fundamentals/MemoryDemo.vue @@ -0,0 +1,282 @@ + + + + + diff --git a/docs/.vitepress/theme/components/appendix/computer-fundamentals/NetworkLayers.vue b/docs/.vitepress/theme/components/appendix/computer-fundamentals/NetworkLayers.vue new file mode 100644 index 0000000..6e21a92 --- /dev/null +++ b/docs/.vitepress/theme/components/appendix/computer-fundamentals/NetworkLayers.vue @@ -0,0 +1,361 @@ + + + + + diff --git a/docs/.vitepress/theme/components/appendix/computer-fundamentals/ProcessDemo.vue b/docs/.vitepress/theme/components/appendix/computer-fundamentals/ProcessDemo.vue new file mode 100644 index 0000000..44f6ff2 --- /dev/null +++ b/docs/.vitepress/theme/components/appendix/computer-fundamentals/ProcessDemo.vue @@ -0,0 +1,261 @@ + + + + + diff --git a/docs/.vitepress/theme/components/appendix/computer-fundamentals/StorageDemo.vue b/docs/.vitepress/theme/components/appendix/computer-fundamentals/StorageDemo.vue new file mode 100644 index 0000000..d0c689d --- /dev/null +++ b/docs/.vitepress/theme/components/appendix/computer-fundamentals/StorageDemo.vue @@ -0,0 +1,246 @@ + + + + + diff --git a/docs/.vitepress/theme/components/appendix/computer-fundamentals/SubnetCalculator.vue b/docs/.vitepress/theme/components/appendix/computer-fundamentals/SubnetCalculator.vue new file mode 100644 index 0000000..55e5f48 --- /dev/null +++ b/docs/.vitepress/theme/components/appendix/computer-fundamentals/SubnetCalculator.vue @@ -0,0 +1,432 @@ + + + + + diff --git a/docs/.vitepress/theme/components/appendix/computer-fundamentals/TcpUdpComparison.vue b/docs/.vitepress/theme/components/appendix/computer-fundamentals/TcpUdpComparison.vue new file mode 100644 index 0000000..e009723 --- /dev/null +++ b/docs/.vitepress/theme/components/appendix/computer-fundamentals/TcpUdpComparison.vue @@ -0,0 +1,584 @@ + + + + + diff --git a/docs/.vitepress/theme/components/appendix/computer-fundamentals/TransistorDemo.vue b/docs/.vitepress/theme/components/appendix/computer-fundamentals/TransistorDemo.vue new file mode 100644 index 0000000..6804ff6 --- /dev/null +++ b/docs/.vitepress/theme/components/appendix/computer-fundamentals/TransistorDemo.vue @@ -0,0 +1,201 @@ + + + + + diff --git a/docs/.vitepress/theme/components/appendix/computer-fundamentals/TransmissionDemo.vue b/docs/.vitepress/theme/components/appendix/computer-fundamentals/TransmissionDemo.vue new file mode 100644 index 0000000..a109f74 --- /dev/null +++ b/docs/.vitepress/theme/components/appendix/computer-fundamentals/TransmissionDemo.vue @@ -0,0 +1,345 @@ + + + + + diff --git a/docs/.vitepress/theme/components/appendix/computer-fundamentals/TypeSystemDemo.vue b/docs/.vitepress/theme/components/appendix/computer-fundamentals/TypeSystemDemo.vue new file mode 100644 index 0000000..26e703c --- /dev/null +++ b/docs/.vitepress/theme/components/appendix/computer-fundamentals/TypeSystemDemo.vue @@ -0,0 +1,481 @@ + + + + + diff --git a/docs/.vitepress/theme/components/appendix/concurrency-models/AsyncAwaitDemo.vue b/docs/.vitepress/theme/components/appendix/concurrency-models/AsyncAwaitDemo.vue index 24de9e6..ed8fd2d 100644 --- a/docs/.vitepress/theme/components/appendix/concurrency-models/AsyncAwaitDemo.vue +++ b/docs/.vitepress/theme/components/appendix/concurrency-models/AsyncAwaitDemo.vue @@ -201,7 +201,7 @@ generateTasks() .demo-container { padding: 20px; background: #f5f7fa; - border-radius: 8px; + border-radius: 6px; } h4 { @@ -229,7 +229,7 @@ h4 { .code-block { background: #282c34; - border-radius: 8px; + border-radius: 6px; overflow: hidden; } @@ -273,7 +273,7 @@ h4 { .timeline-container { background: white; - border-radius: 8px; + border-radius: 6px; padding: 16px; margin-bottom: 16px; } @@ -363,7 +363,7 @@ h4 { .stat-card { background: white; - border-radius: 8px; + border-radius: 6px; padding: 12px; text-align: center; } diff --git a/docs/.vitepress/theme/components/appendix/concurrency-models/ConcurrentVsParallelDemo.vue b/docs/.vitepress/theme/components/appendix/concurrency-models/ConcurrentVsParallelDemo.vue index 2169abe..a9f7e13 100644 --- a/docs/.vitepress/theme/components/appendix/concurrency-models/ConcurrentVsParallelDemo.vue +++ b/docs/.vitepress/theme/components/appendix/concurrency-models/ConcurrentVsParallelDemo.vue @@ -211,7 +211,7 @@ function reset() { .demo-container { padding: 20px; background: #f5f7fa; - border-radius: 8px; + border-radius: 6px; } h4 { @@ -236,7 +236,7 @@ h4 { .section { background: white; - border-radius: 8px; + border-radius: 6px; padding: 16px; } @@ -260,7 +260,7 @@ h4 { .cpu-core { background: #f5f7fa; border: 2px solid #e4e7ed; - border-radius: 8px; + border-radius: 6px; padding: 16px; text-align: center; transition: all 0.3s; @@ -354,7 +354,7 @@ h4 { .comparison-table { background: white; - border-radius: 8px; + border-radius: 6px; padding: 20px; } @@ -377,7 +377,7 @@ h4 { .comparison-item { background: #f5f7fa; - border-radius: 8px; + border-radius: 6px; padding: 16px; } @@ -412,7 +412,7 @@ h4 { .need-table { background: #f5f7fa; - border-radius: 8px; + border-radius: 6px; padding: 16px; } diff --git a/docs/.vitepress/theme/components/appendix/concurrency-models/CoroutineLightweightDemo.vue b/docs/.vitepress/theme/components/appendix/concurrency-models/CoroutineLightweightDemo.vue index 5c5a649..260b8fc 100644 --- a/docs/.vitepress/theme/components/appendix/concurrency-models/CoroutineLightweightDemo.vue +++ b/docs/.vitepress/theme/components/appendix/concurrency-models/CoroutineLightweightDemo.vue @@ -253,7 +253,7 @@ function stateText(state) { .demo-container { padding: 20px; background: #f5f7fa; - border-radius: 8px; + border-radius: 6px; } h4 { @@ -284,7 +284,7 @@ h4 { .comparison-column { background: white; - border-radius: 8px; + border-radius: 6px; padding: 16px; } diff --git a/docs/.vitepress/theme/components/appendix/concurrency-models/EventLoopDemo.vue b/docs/.vitepress/theme/components/appendix/concurrency-models/EventLoopDemo.vue index f19fe2e..ce85f7d 100644 --- a/docs/.vitepress/theme/components/appendix/concurrency-models/EventLoopDemo.vue +++ b/docs/.vitepress/theme/components/appendix/concurrency-models/EventLoopDemo.vue @@ -230,7 +230,7 @@ function reset() { .demo-container { padding: 20px; background: #f5f7fa; - border-radius: 8px; + border-radius: 6px; } h4 { @@ -255,7 +255,7 @@ h4 { .section { background: white; - border-radius: 8px; + border-radius: 6px; padding: 16px; } diff --git a/docs/.vitepress/theme/components/appendix/concurrency-models/GoroutineGreenThreadDemo.vue b/docs/.vitepress/theme/components/appendix/concurrency-models/GoroutineGreenThreadDemo.vue index c529c31..754b967 100644 --- a/docs/.vitepress/theme/components/appendix/concurrency-models/GoroutineGreenThreadDemo.vue +++ b/docs/.vitepress/theme/components/appendix/concurrency-models/GoroutineGreenThreadDemo.vue @@ -218,7 +218,7 @@ initGMP() .demo-container { padding: 20px; background: #f5f7fa; - border-radius: 8px; + border-radius: 6px; } h4 { @@ -236,7 +236,7 @@ h4 { .gmp-view { background: white; - border-radius: 8px; + border-radius: 6px; padding: 16px; margin-bottom: 16px; } @@ -249,7 +249,7 @@ h4 { .queue-section { background: #f5f7fa; - border-radius: 8px; + border-radius: 6px; padding: 12px; } @@ -291,7 +291,7 @@ h4 { .processors-section, .machines-section { background: #f5f7fa; - border-radius: 8px; + border-radius: 6px; padding: 12px; } @@ -314,7 +314,7 @@ h4 { .processor { background: white; border: 2px solid #e4e7ed; - border-radius: 8px; + border-radius: 6px; padding: 10px; transition: all 0.3s; } diff --git a/docs/.vitepress/theme/components/appendix/concurrency-models/ProcessIsolationDemo.vue b/docs/.vitepress/theme/components/appendix/concurrency-models/ProcessIsolationDemo.vue index e1294f1..1be1175 100644 --- a/docs/.vitepress/theme/components/appendix/concurrency-models/ProcessIsolationDemo.vue +++ b/docs/.vitepress/theme/components/appendix/concurrency-models/ProcessIsolationDemo.vue @@ -160,7 +160,7 @@ function reset() { .demo-container { padding: 20px; background: #f5f7fa; - border-radius: 8px; + border-radius: 6px; } h4 { @@ -177,7 +177,7 @@ h4 { .memory-view { background: white; - border-radius: 8px; + border-radius: 6px; padding: 16px; margin-bottom: 16px; } diff --git a/docs/.vitepress/theme/components/appendix/concurrency-models/ProcessThreadCoroutineDemo.vue b/docs/.vitepress/theme/components/appendix/concurrency-models/ProcessThreadCoroutineDemo.vue index f4c7159..775d152 100644 --- a/docs/.vitepress/theme/components/appendix/concurrency-models/ProcessThreadCoroutineDemo.vue +++ b/docs/.vitepress/theme/components/appendix/concurrency-models/ProcessThreadCoroutineDemo.vue @@ -177,7 +177,7 @@ resetSimulation() .demo-container { padding: 20px; background: #f5f7fa; - border-radius: 8px; + border-radius: 6px; margin: 20px 0; } @@ -212,7 +212,7 @@ resetSimulation() .core { background: white; border: 2px solid #dcdfe6; - border-radius: 8px; + border-radius: 6px; padding: 16px; text-align: center; transition: all 0.3s; @@ -253,7 +253,7 @@ resetSimulation() .task-queue { background: white; - border-radius: 8px; + border-radius: 6px; padding: 16px; } diff --git a/docs/.vitepress/theme/components/appendix/concurrency-models/ThreadSchedulingDemo.vue b/docs/.vitepress/theme/components/appendix/concurrency-models/ThreadSchedulingDemo.vue index 5946b3b..a84f98a 100644 --- a/docs/.vitepress/theme/components/appendix/concurrency-models/ThreadSchedulingDemo.vue +++ b/docs/.vitepress/theme/components/appendix/concurrency-models/ThreadSchedulingDemo.vue @@ -358,7 +358,7 @@ onUnmounted(() => { .demo-container { padding: 20px; background: #f5f7fa; - border-radius: 8px; + border-radius: 6px; } h4 { @@ -375,7 +375,7 @@ h4 { .memory-view { background: white; - border-radius: 8px; + border-radius: 6px; padding: 16px; margin-bottom: 16px; } diff --git a/docs/.vitepress/theme/components/appendix/context-engineering/AgentContextFlow.vue b/docs/.vitepress/theme/components/appendix/context-engineering/AgentContextFlow.vue index 9e04b66..a653081 100644 --- a/docs/.vitepress/theme/components/appendix/context-engineering/AgentContextFlow.vue +++ b/docs/.vitepress/theme/components/appendix/context-engineering/AgentContextFlow.vue @@ -149,10 +149,10 @@ const totalHeight = computed(() => systemHeight.value + historyHeight.value + in + + diff --git a/docs/.vitepress/theme/components/appendix/deployment/DeploymentServerDemo.vue b/docs/.vitepress/theme/components/appendix/deployment/DeploymentServerDemo.vue index 94630f4..56b693a 100644 --- a/docs/.vitepress/theme/components/appendix/deployment/DeploymentServerDemo.vue +++ b/docs/.vitepress/theme/components/appendix/deployment/DeploymentServerDemo.vue @@ -39,10 +39,10 @@ const scenario = ref('small') diff --git a/docs/.vitepress/theme/components/appendix/frontend-evolution/ImperativeVsDeclarativeDemo.vue b/docs/.vitepress/theme/components/appendix/frontend-evolution/ImperativeVsDeclarativeDemo.vue index 797b5bf..1e54c54 100644 --- a/docs/.vitepress/theme/components/appendix/frontend-evolution/ImperativeVsDeclarativeDemo.vue +++ b/docs/.vitepress/theme/components/appendix/frontend-evolution/ImperativeVsDeclarativeDemo.vue @@ -1,19 +1,19 @@ @@ -223,14 +231,39 @@ function updateJq(change) { diff --git a/docs/.vitepress/theme/components/appendix/frontend-evolution/RenderingStrategyDemo.vue b/docs/.vitepress/theme/components/appendix/frontend-evolution/RenderingStrategyDemo.vue index b9206d1..25f33a8 100644 --- a/docs/.vitepress/theme/components/appendix/frontend-evolution/RenderingStrategyDemo.vue +++ b/docs/.vitepress/theme/components/appendix/frontend-evolution/RenderingStrategyDemo.vue @@ -359,7 +359,7 @@ const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms)) gap: 4px; padding: 16px; border: none; - border-radius: 8px; + border-radius: 6px; background: transparent; cursor: pointer; transition: all 0.3s ease; @@ -453,7 +453,7 @@ const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms)) width: 48px; height: 48px; background: white; - border-radius: 8px; + border-radius: 6px; display: flex; align-items: center; justify-content: center; @@ -571,7 +571,7 @@ const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms)) .info-label { padding: 8px 16px; background: #e0e0e0; - border-radius: 8px; + border-radius: 6px; } /* 性能指标 */ @@ -627,7 +627,7 @@ const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms)) .btn { padding: 12px 24px; border: none; - border-radius: 8px; + border-radius: 6px; font-size: 16px; font-weight: bold; cursor: pointer; diff --git a/docs/.vitepress/theme/components/appendix/frontend-evolution/ResponsiveGridDemo.vue b/docs/.vitepress/theme/components/appendix/frontend-evolution/ResponsiveGridDemo.vue index ba2a604..032043b 100644 --- a/docs/.vitepress/theme/components/appendix/frontend-evolution/ResponsiveGridDemo.vue +++ b/docs/.vitepress/theme/components/appendix/frontend-evolution/ResponsiveGridDemo.vue @@ -299,7 +299,7 @@ const clothes = [ color: #666; background: #f8f9fa; padding: 8px; - border-radius: 8px; + border-radius: 6px; } /* 衣柜展示 */ diff --git a/docs/.vitepress/theme/components/appendix/frontend-evolution/RoutingModeDemo.vue b/docs/.vitepress/theme/components/appendix/frontend-evolution/RoutingModeDemo.vue index b3a0b94..e36a13f 100644 --- a/docs/.vitepress/theme/components/appendix/frontend-evolution/RoutingModeDemo.vue +++ b/docs/.vitepress/theme/components/appendix/frontend-evolution/RoutingModeDemo.vue @@ -4,16 +4,24 @@ --> @@ -251,7 +258,7 @@ const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms)) diff --git a/docs/.vitepress/theme/components/appendix/git-intro/GitWorkflowDemo.vue b/docs/.vitepress/theme/components/appendix/git-intro/GitWorkflowDemo.vue index 6785e5c..8812c8c 100644 --- a/docs/.vitepress/theme/components/appendix/git-intro/GitWorkflowDemo.vue +++ b/docs/.vitepress/theme/components/appendix/git-intro/GitWorkflowDemo.vue @@ -1,134 +1,136 @@ @@ -136,151 +138,323 @@ diff --git a/docs/.vitepress/theme/components/appendix/ide-intro/AiHelpDemo.vue b/docs/.vitepress/theme/components/appendix/ide-intro/AiHelpDemo.vue index c625e99..f308bfa 100644 --- a/docs/.vitepress/theme/components/appendix/ide-intro/AiHelpDemo.vue +++ b/docs/.vitepress/theme/components/appendix/ide-intro/AiHelpDemo.vue @@ -366,7 +366,7 @@ const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms)) left: 5%; width: 90%; height: 90%; - border-radius: 8px; + border-radius: 6px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5); display: flex; flex-direction: column; @@ -721,7 +721,7 @@ const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms)) .messages-container { flex: 1; - overflow-y: auto; + padding: 20px; display: flex; flex-direction: column; @@ -777,7 +777,7 @@ const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms)) .ai-bubble { background: #444654; padding: 15px; - border-radius: 8px; + border-radius: 6px; box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1); } diff --git a/docs/.vitepress/theme/components/appendix/ide-intro/IdeArchitectureDemo.vue b/docs/.vitepress/theme/components/appendix/ide-intro/IdeArchitectureDemo.vue index afed19f..ee1ccbd 100644 --- a/docs/.vitepress/theme/components/appendix/ide-intro/IdeArchitectureDemo.vue +++ b/docs/.vitepress/theme/components/appendix/ide-intro/IdeArchitectureDemo.vue @@ -285,7 +285,7 @@ const setScenario = (key) => { .tabs { display: flex; background: var(--vp-c-bg-mute); - border-radius: 8px; + border-radius: 6px; padding: 4px; margin-bottom: 16px; gap: 4px; @@ -359,7 +359,7 @@ const setScenario = (key) => { /* VS Code Style */ .vscode .editor-window { background: #1e1e1e; - border-radius: 8px; + border-radius: 6px; overflow: hidden; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); border: 1px solid #333; @@ -403,7 +403,7 @@ const setScenario = (key) => { .comp-box { background: var(--vp-c-bg); border: 2px solid var(--vp-c-divider); - border-radius: 8px; + border-radius: 6px; padding: 12px; min-height: 60px; display: flex; @@ -510,7 +510,7 @@ const setScenario = (key) => { /* Terminal */ .terminal-box { background: #1e1e1e; - border-radius: 8px; + border-radius: 6px; overflow: hidden; font-family: 'Consolas', monospace; border: 1px solid #333; diff --git a/docs/.vitepress/theme/components/appendix/ide-intro/VirtualVSCodeDemo.vue b/docs/.vitepress/theme/components/appendix/ide-intro/VirtualVSCodeDemo.vue index fa83448..857ad76 100644 --- a/docs/.vitepress/theme/components/appendix/ide-intro/VirtualVSCodeDemo.vue +++ b/docs/.vitepress/theme/components/appendix/ide-intro/VirtualVSCodeDemo.vue @@ -1529,7 +1529,7 @@ onUnmounted(() => { box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); z-index: 1000; max-height: 200px; - overflow-y: auto; + padding: 4px 0; } @@ -2119,7 +2119,7 @@ onUnmounted(() => { flex: 1; display: flex; padding-top: 4px; - overflow-y: auto; + } .line-numbers { width: 40px; @@ -2148,7 +2148,7 @@ onUnmounted(() => { flex: 1; background: #1e1e1e; padding: 30px; - overflow-y: auto; + color: #ccc; display: flex; justify-content: center; @@ -2325,7 +2325,7 @@ onUnmounted(() => { .panel-body { flex: 1; padding: 8px 12px; - overflow-y: auto; + font-family: 'Consolas', 'Monaco', monospace; font-size: 11px; } diff --git a/docs/.vitepress/theme/components/appendix/image-gen-intro/CFGScaleDemo.vue b/docs/.vitepress/theme/components/appendix/image-gen-intro/CFGScaleDemo.vue index 53b74c4..9aa38c8 100644 --- a/docs/.vitepress/theme/components/appendix/image-gen-intro/CFGScaleDemo.vue +++ b/docs/.vitepress/theme/components/appendix/image-gen-intro/CFGScaleDemo.vue @@ -307,7 +307,7 @@ watch(cfgScale, updateDisplay) diff --git a/docs/.vitepress/theme/components/appendix/javascript-intro/AsyncRestaurantDemo.vue b/docs/.vitepress/theme/components/appendix/javascript-intro/AsyncRestaurantDemo.vue new file mode 100644 index 0000000..140300c --- /dev/null +++ b/docs/.vitepress/theme/components/appendix/javascript-intro/AsyncRestaurantDemo.vue @@ -0,0 +1,477 @@ + + + + + diff --git a/docs/.vitepress/theme/components/appendix/javascript-intro/ClosureDemo.vue b/docs/.vitepress/theme/components/appendix/javascript-intro/ClosureDemo.vue new file mode 100644 index 0000000..1b1335f --- /dev/null +++ b/docs/.vitepress/theme/components/appendix/javascript-intro/ClosureDemo.vue @@ -0,0 +1,766 @@ + + + + + diff --git a/docs/.vitepress/theme/components/appendix/javascript-intro/DOMTreeDemo.vue b/docs/.vitepress/theme/components/appendix/javascript-intro/DOMTreeDemo.vue new file mode 100644 index 0000000..a289a45 --- /dev/null +++ b/docs/.vitepress/theme/components/appendix/javascript-intro/DOMTreeDemo.vue @@ -0,0 +1,309 @@ + + + + + diff --git a/docs/.vitepress/theme/components/appendix/javascript-intro/DataTypeDemo.vue b/docs/.vitepress/theme/components/appendix/javascript-intro/DataTypeDemo.vue new file mode 100644 index 0000000..3c680c7 --- /dev/null +++ b/docs/.vitepress/theme/components/appendix/javascript-intro/DataTypeDemo.vue @@ -0,0 +1,658 @@ + + + + + diff --git a/docs/.vitepress/theme/components/appendix/javascript-intro/FunctionMachineDemo.vue b/docs/.vitepress/theme/components/appendix/javascript-intro/FunctionMachineDemo.vue new file mode 100644 index 0000000..d0a5da1 --- /dev/null +++ b/docs/.vitepress/theme/components/appendix/javascript-intro/FunctionMachineDemo.vue @@ -0,0 +1,358 @@ + + + + + diff --git a/docs/.vitepress/theme/components/appendix/javascript-intro/JSEventLoopDemo.vue b/docs/.vitepress/theme/components/appendix/javascript-intro/JSEventLoopDemo.vue new file mode 100644 index 0000000..48ac9d9 --- /dev/null +++ b/docs/.vitepress/theme/components/appendix/javascript-intro/JSEventLoopDemo.vue @@ -0,0 +1,475 @@ + + + + + diff --git a/docs/.vitepress/theme/components/appendix/javascript-intro/PrototypeDemo.vue b/docs/.vitepress/theme/components/appendix/javascript-intro/PrototypeDemo.vue new file mode 100644 index 0000000..48c656e --- /dev/null +++ b/docs/.vitepress/theme/components/appendix/javascript-intro/PrototypeDemo.vue @@ -0,0 +1,827 @@ + + + + + diff --git a/docs/.vitepress/theme/components/appendix/javascript-intro/ReferenceDemo.vue b/docs/.vitepress/theme/components/appendix/javascript-intro/ReferenceDemo.vue new file mode 100644 index 0000000..f76e4d0 --- /dev/null +++ b/docs/.vitepress/theme/components/appendix/javascript-intro/ReferenceDemo.vue @@ -0,0 +1,329 @@ + + + + + diff --git a/docs/.vitepress/theme/components/appendix/javascript-intro/ScopeDemo.vue b/docs/.vitepress/theme/components/appendix/javascript-intro/ScopeDemo.vue new file mode 100644 index 0000000..9fe05da --- /dev/null +++ b/docs/.vitepress/theme/components/appendix/javascript-intro/ScopeDemo.vue @@ -0,0 +1,286 @@ + + + + + diff --git a/docs/.vitepress/theme/components/appendix/javascript-intro/ThisContextDemo.vue b/docs/.vitepress/theme/components/appendix/javascript-intro/ThisContextDemo.vue new file mode 100644 index 0000000..d65c6de --- /dev/null +++ b/docs/.vitepress/theme/components/appendix/javascript-intro/ThisContextDemo.vue @@ -0,0 +1,899 @@ + + + + + diff --git a/docs/.vitepress/theme/components/appendix/javascript-intro/VariableBoxDemo.vue b/docs/.vitepress/theme/components/appendix/javascript-intro/VariableBoxDemo.vue new file mode 100644 index 0000000..30bb044 --- /dev/null +++ b/docs/.vitepress/theme/components/appendix/javascript-intro/VariableBoxDemo.vue @@ -0,0 +1,253 @@ + + + + + diff --git a/docs/.vitepress/theme/components/appendix/javascript-intro/VariableScopeDemo.vue b/docs/.vitepress/theme/components/appendix/javascript-intro/VariableScopeDemo.vue new file mode 100644 index 0000000..bfbdafe --- /dev/null +++ b/docs/.vitepress/theme/components/appendix/javascript-intro/VariableScopeDemo.vue @@ -0,0 +1,366 @@ + + + + + diff --git a/docs/.vitepress/theme/components/appendix/js-runtime/CallStackDemo.vue b/docs/.vitepress/theme/components/appendix/js-runtime/CallStackDemo.vue new file mode 100644 index 0000000..cfe08b4 --- /dev/null +++ b/docs/.vitepress/theme/components/appendix/js-runtime/CallStackDemo.vue @@ -0,0 +1,542 @@ + + + + + diff --git a/docs/.vitepress/theme/components/appendix/js-runtime/GarbageCollectionDemo.vue b/docs/.vitepress/theme/components/appendix/js-runtime/GarbageCollectionDemo.vue new file mode 100644 index 0000000..9e45a53 --- /dev/null +++ b/docs/.vitepress/theme/components/appendix/js-runtime/GarbageCollectionDemo.vue @@ -0,0 +1,752 @@ + + + + + diff --git a/docs/.vitepress/theme/components/appendix/js-runtime/MemoryLeakDemo.vue b/docs/.vitepress/theme/components/appendix/js-runtime/MemoryLeakDemo.vue new file mode 100644 index 0000000..6a8dc4e --- /dev/null +++ b/docs/.vitepress/theme/components/appendix/js-runtime/MemoryLeakDemo.vue @@ -0,0 +1,682 @@ + + + + + diff --git a/docs/.vitepress/theme/components/appendix/js-runtime/RuntimeEnvironmentDemo.vue b/docs/.vitepress/theme/components/appendix/js-runtime/RuntimeEnvironmentDemo.vue new file mode 100644 index 0000000..d4f8afa --- /dev/null +++ b/docs/.vitepress/theme/components/appendix/js-runtime/RuntimeEnvironmentDemo.vue @@ -0,0 +1,487 @@ + + + + + diff --git a/docs/.vitepress/theme/components/appendix/js-runtime/TaskQueueDemo.vue b/docs/.vitepress/theme/components/appendix/js-runtime/TaskQueueDemo.vue new file mode 100644 index 0000000..7a8ec1a --- /dev/null +++ b/docs/.vitepress/theme/components/appendix/js-runtime/TaskQueueDemo.vue @@ -0,0 +1,652 @@ + + + + + diff --git a/docs/.vitepress/theme/components/appendix/llm-intro/EmbeddingDemo.vue b/docs/.vitepress/theme/components/appendix/llm-intro/EmbeddingDemo.vue index c42daa3..7506af8 100644 --- a/docs/.vitepress/theme/components/appendix/llm-intro/EmbeddingDemo.vue +++ b/docs/.vitepress/theme/components/appendix/llm-intro/EmbeddingDemo.vue @@ -223,14 +223,14 @@ const setMode = (mode) => { diff --git a/docs/.vitepress/theme/components/appendix/queue-design/DeadLetterQueueDemo.vue b/docs/.vitepress/theme/components/appendix/queue-design/DeadLetterQueueDemo.vue index b3e0db9..e3c8a50 100644 --- a/docs/.vitepress/theme/components/appendix/queue-design/DeadLetterQueueDemo.vue +++ b/docs/.vitepress/theme/components/appendix/queue-design/DeadLetterQueueDemo.vue @@ -4,133 +4,132 @@ --> @@ -174,7 +173,7 @@ const processNext = () => { return } - let msg = mainQueue[0] + let msg = mainQueue.value[0] msg.processing = true processing.value = true currentMessage.value = msg @@ -188,7 +187,7 @@ const processNext = () => { msg.processing = false if (msg.retries >= maxRetries.value) { - // 超过最大重试次数,进入死信队列 + // 超过最大重试次数,进入死信队列 mainQueue.value.shift() deadLetterQueue.value.push({ id: msg.id, @@ -202,7 +201,7 @@ const processNext = () => { // 重新入队 lastResult.value = { type: 'warning', - message: `⚠️ 消息 #${msg.id} 处理失败,重试 ${msg.retries}/${maxRetries.value}` + message: `⚠️ 消息 #${msg.id} 处理失败,重试 ${msg.retries}/${maxRetries.value}` } } @@ -262,39 +261,48 @@ addMessage = addMessageWithAutoProcess .dlq-demo { border: 1px solid var(--vp-c-divider); background: var(--vp-c-bg-soft); - border-radius: 12px; - padding: 1.5rem; - margin: 1.5rem 0; - font-family: var(--vp-font-family-base); + border-radius: 6px; + padding: 0.75rem; + margin: 0.5rem 0; + + } -.header { - margin-bottom: 1rem; +.demo-header { + display: flex; + align-items: center; + gap: 0.5rem; + margin-bottom: 0.75rem; } -.title { - font-weight: 700; - font-size: 1.05rem; +.demo-header .icon { + font-size: 1.25rem; } -.subtitle { +.demo-header .title { + font-weight: bold; + font-size: 1rem; + color: var(--vp-c-text-1); +} + +.demo-header .subtitle { color: var(--vp-c-text-2); - font-size: 0.9rem; - margin-top: 0.25rem; + font-size: 0.85rem; + margin-left: 0.5rem; } .controls { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 1rem; - margin-bottom: 1.5rem; + margin-bottom: 1rem; } .control { display: flex; align-items: center; gap: 0.5rem; - font-size: 0.9rem; + font-size: 0.85rem; } .control input[type='range'] { @@ -307,25 +315,29 @@ addMessage = addMessageWithAutoProcess text-align: right; } +.demo-content { + margin-bottom: 0.75rem; +} + .flow-container { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 1rem; - margin-bottom: 1.5rem; + margin-bottom: 1rem; } .section-title { - font-size: 0.85rem; + font-size: 0.75rem; font-weight: 600; color: var(--vp-c-text-2); text-align: center; - margin-bottom: 0.75rem; + margin-bottom: 0.5rem; } .queue-box { background: var(--vp-c-bg); border: 2px solid var(--vp-c-divider); - border-radius: 10px; + border-radius: 6px; overflow: hidden; } @@ -334,7 +346,7 @@ addMessage = addMessageWithAutoProcess } .queue-box.dead-letter { - border-color: #ef4444; + border-color: var(--vp-c-danger); } .queue-header { @@ -343,13 +355,13 @@ addMessage = addMessageWithAutoProcess align-items: center; padding: 0.5rem 0.75rem; background: var(--vp-c-bg-soft); - font-size: 0.8rem; + font-size: 0.75rem; font-weight: 600; } .message-list { - max-height: 200px; - overflow-y: auto; + max-height: 150px; + padding: 0.5rem; } @@ -361,17 +373,17 @@ addMessage = addMessageWithAutoProcess background: var(--vp-c-bg-soft); border-radius: 6px; margin-bottom: 0.4rem; - font-size: 0.8rem; + font-size: 0.75rem; } .message-item.processing { - border: 1px solid #f59e0b; - background: rgba(245, 158, 11, 0.1); + border: 1px solid var(--vp-c-warning); + background: var(--vp-c-warning-soft); } .message-item.failed { - border: 1px solid #ef4444; - background: rgba(239, 68, 68, 0.1); + border: 1px solid var(--vp-c-danger); + background: var(--vp-c-danger-soft); } .msg-id { @@ -379,32 +391,32 @@ addMessage = addMessageWithAutoProcess } .msg-retries { - font-size: 0.7rem; - color: #f59e0b; + font-size: 0.65rem; + color: var(--vp-c-warning); } .msg-error { - font-size: 0.7rem; - color: #ef4444; + font-size: 0.65rem; + color: var(--vp-c-danger); } -.empty { +.empty, .more { text-align: center; - padding: 1.5rem; + padding: 1rem 0.5rem; color: var(--vp-c-text-3); - font-size: 0.85rem; + font-size: 0.75rem; } .add-btn, .retry-btn { width: 100%; - padding: 0.6rem; + padding: 0.5rem; border: none; - border-radius: 8px; + border-radius: 6px; cursor: pointer; font-weight: 600; - font-size: 0.85rem; - margin-top: 0.75rem; + font-size: 0.8rem; + margin-top: 0.5rem; transition: all 0.2s; } @@ -414,8 +426,7 @@ addMessage = addMessageWithAutoProcess } .add-btn:hover:not(:disabled) { - transform: translateY(-1px); - box-shadow: 0 4px 12px rgba(59, 130, 246, 0.3); + opacity: 0.9; } .add-btn:disabled { @@ -424,21 +435,21 @@ addMessage = addMessageWithAutoProcess } .retry-btn { - background: #f59e0b; + background: var(--vp-c-warning); color: white; } .retry-btn:hover:not(:disabled) { - background: #d97706; + opacity: 0.8; } .processor-box { background: var(--vp-c-bg); border: 2px solid var(--vp-c-divider); - border-radius: 10px; - padding: 1.5rem; + border-radius: 6px; + padding: 0.75rem; text-align: center; - min-height: 200px; + min-height: 150px; display: flex; flex-direction: column; justify-content: center; @@ -446,8 +457,8 @@ addMessage = addMessageWithAutoProcess } .processor-icon { - font-size: 2.5rem; - margin-bottom: 0.75rem; + font-size: 2rem; + margin-bottom: 0.5rem; } .processor-icon.active { @@ -455,97 +466,87 @@ addMessage = addMessageWithAutoProcess } .processor-status { - font-size: 0.9rem; + font-size: 0.8rem; font-weight: 600; margin-bottom: 0.5rem; } .current-msg { - font-size: 0.85rem; + font-size: 0.75rem; color: var(--vp-c-text-2); margin-bottom: 0.5rem; } .last-result { - font-size: 0.8rem; + font-size: 0.75rem; padding: 0.5rem 0.75rem; border-radius: 6px; margin-top: 0.5rem; } .last-result.success { - background: #dcfce7; - color: #166534; + background: var(--vp-c-success); + color: white; } .last-result.warning { - background: rgba(245, 158, 11, 0.1); - color: #d97706; + background: var(--vp-c-warning-soft); + color: var(--vp-c-warning-dark); } .last-result.error { - background: rgba(239, 68, 68, 0.1); - color: #dc2626; + background: var(--vp-c-danger-soft); + color: var(--vp-c-danger-dark); } .stats { display: grid; - grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); + grid-template-columns: repeat(auto-fit, minmax(100px, 1fr)); gap: 1rem; - margin-bottom: 1.5rem; } .stat-card { background: var(--vp-c-bg); - border-radius: 10px; - padding: 1rem; + border-radius: 6px; + padding: 0.75rem; text-align: center; border: 1px solid var(--vp-c-divider); } .stat-card.success { - border-color: #22c55e; - background: rgba(34, 197, 94, 0.05); + border-color: var(--vp-c-success); + background: var(--vp-c-success-soft); } .stat-card.warning { - border-color: #ef4444; - background: rgba(239, 68, 68, 0.05); + border-color: var(--vp-c-danger); + background: var(--vp-c-danger-soft); } .stat-label { - font-size: 0.8rem; + font-size: 0.7rem; color: var(--vp-c-text-2); margin-bottom: 0.35rem; } .stat-value { - font-size: 1.3rem; + font-size: 1.1rem; font-weight: 700; } -.explanation { - background: var(--vp-c-bg); - border-radius: 10px; - padding: 1rem; - border: 1px solid var(--vp-c-divider); -} - -.exp-title { - font-weight: 600; - margin-bottom: 0.75rem; -} - -.exp-content { - display: flex; - flex-direction: column; - gap: 0.5rem; -} - -.exp-item { - font-size: 0.9rem; - line-height: 1.5; +.info-box { + background: var(--vp-c-bg-alt); + padding: 0.75rem; + border-radius: 6px; + font-size: 0.8rem; color: var(--vp-c-text-2); + margin-top: 0.75rem; + display: flex; + gap: 0.25rem; +} + +.info-box .icon { + flex-shrink: 0; } @keyframes spin { diff --git a/docs/.vitepress/theme/components/appendix/queue-design/DecouplingDemo.vue b/docs/.vitepress/theme/components/appendix/queue-design/DecouplingDemo.vue new file mode 100644 index 0000000..166fa1a --- /dev/null +++ b/docs/.vitepress/theme/components/appendix/queue-design/DecouplingDemo.vue @@ -0,0 +1,522 @@ + + + + + + diff --git a/docs/.vitepress/theme/components/appendix/queue-design/DelayedMessageDemo.vue b/docs/.vitepress/theme/components/appendix/queue-design/DelayedMessageDemo.vue index 5582eaa..e2e8998 100644 --- a/docs/.vitepress/theme/components/appendix/queue-design/DelayedMessageDemo.vue +++ b/docs/.vitepress/theme/components/appendix/queue-design/DelayedMessageDemo.vue @@ -333,7 +333,7 @@ onUnmounted(() => { padding: 0.6rem 1rem; border: 2px solid var(--vp-c-divider); background: var(--vp-c-bg); - border-radius: 8px; + border-radius: 6px; cursor: pointer; font-weight: 600; font-size: 0.9rem; @@ -369,7 +369,7 @@ onUnmounted(() => { .result-section { background: var(--vp-c-bg); border-radius: 10px; - padding: 1rem; + padding: 0.75rem; border: 1px solid var(--vp-c-divider); } @@ -377,7 +377,7 @@ onUnmounted(() => { margin-bottom: 1rem; padding: 0.75rem; background: var(--vp-c-bg-soft); - border-radius: 8px; + border-radius: 6px; } .scenario-name { @@ -450,7 +450,7 @@ onUnmounted(() => { background: var(--vp-c-brand); color: white; border: none; - border-radius: 8px; + border-radius: 6px; cursor: pointer; font-weight: 600; transition: all 0.2s; @@ -470,7 +470,7 @@ onUnmounted(() => { position: relative; height: 150px; background: var(--vp-c-bg-soft); - border-radius: 8px; + border-radius: 6px; padding: 0.5rem; margin-top: 0.5rem; } @@ -510,7 +510,7 @@ onUnmounted(() => { .msg-bubble { background: white; border: 2px solid var(--vp-c-brand); - border-radius: 8px; + border-radius: 6px; padding: 0.5rem; text-align: center; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); @@ -565,9 +565,9 @@ onUnmounted(() => { .result-box { max-height: 250px; - overflow-y: auto; + background: var(--vp-c-bg-soft); - border-radius: 8px; + border-radius: 6px; padding: 0.75rem; } @@ -611,7 +611,7 @@ onUnmounted(() => { .use-cases { background: var(--vp-c-bg); border-radius: 10px; - padding: 1rem; + padding: 0.75rem; margin-bottom: 1rem; border: 1px solid var(--vp-c-divider); } @@ -629,7 +629,7 @@ onUnmounted(() => { .case-card { background: var(--vp-c-bg-soft); - border-radius: 8px; + border-radius: 6px; padding: 0.75rem; text-align: center; } @@ -654,7 +654,7 @@ onUnmounted(() => { .implementation { background: var(--vp-c-bg); border-radius: 10px; - padding: 1rem; + padding: 0.75rem; border: 1px solid var(--vp-c-divider); } diff --git a/docs/.vitepress/theme/components/appendix/queue-design/IdempotenceDemo.vue b/docs/.vitepress/theme/components/appendix/queue-design/IdempotenceDemo.vue index 50c818e..8f122fe 100644 --- a/docs/.vitepress/theme/components/appendix/queue-design/IdempotenceDemo.vue +++ b/docs/.vitepress/theme/components/appendix/queue-design/IdempotenceDemo.vue @@ -1,50 +1,881 @@ + diff --git a/docs/.vitepress/theme/components/appendix/queue-design/MQArchitectureDemo.vue b/docs/.vitepress/theme/components/appendix/queue-design/MQArchitectureDemo.vue index 7e5d97c..8d827e6 100644 --- a/docs/.vitepress/theme/components/appendix/queue-design/MQArchitectureDemo.vue +++ b/docs/.vitepress/theme/components/appendix/queue-design/MQArchitectureDemo.vue @@ -22,7 +22,7 @@ const description = ref('展示消息队列的整体架构,包括生产者、 diff --git a/docs/.vitepress/theme/components/appendix/queue-design/SeckillSystemDemo.vue b/docs/.vitepress/theme/components/appendix/queue-design/SeckillSystemDemo.vue index ce35093..83169c8 100644 --- a/docs/.vitepress/theme/components/appendix/queue-design/SeckillSystemDemo.vue +++ b/docs/.vitepress/theme/components/appendix/queue-design/SeckillSystemDemo.vue @@ -448,14 +448,14 @@ onUnmounted(() => { display: flex; gap: 0.75rem; justify-content: center; - margin: 1rem 0; + margin: 0.5rem 0; } .start-btn, .reset-btn { padding: 0.75rem 2rem; border: none; - border-radius: 8px; + border-radius: 6px; cursor: pointer; font-weight: 600; transition: all 0.2s; @@ -495,7 +495,7 @@ onUnmounted(() => { background: var(--vp-c-bg); border: 2px solid var(--vp-c-divider); border-radius: 10px; - padding: 1rem; + padding: 0.75rem; } .layer-title { @@ -513,7 +513,7 @@ onUnmounted(() => { .stat-box { background: var(--vp-c-bg-soft); - border-radius: 8px; + border-radius: 6px; padding: 0.75rem; text-align: center; } @@ -546,7 +546,7 @@ onUnmounted(() => { grid-column: 1 / -1; padding: 0.75rem; background: var(--vp-c-bg-soft); - border-radius: 8px; + border-radius: 6px; } .stock-bar { @@ -600,7 +600,7 @@ onUnmounted(() => { .queue-box { background: var(--vp-c-bg-soft); - border-radius: 8px; + border-radius: 6px; padding: 0.75rem; } @@ -641,8 +641,8 @@ onUnmounted(() => { .real-time-stats { background: var(--vp-c-bg); border-radius: 10px; - padding: 1rem; - margin: 1rem 0; + padding: 0.75rem; + margin: 0.5rem 0; border: 1px solid var(--vp-c-divider); } @@ -661,7 +661,7 @@ onUnmounted(() => { text-align: center; padding: 0.75rem; background: var(--vp-c-bg-soft); - border-radius: 8px; + border-radius: 6px; } .stat-item .stat-label { @@ -679,8 +679,8 @@ onUnmounted(() => { .log-section { background: var(--vp-c-bg); border-radius: 10px; - padding: 1rem; - margin: 1rem 0; + padding: 0.75rem; + margin: 0.5rem 0; border: 1px solid var(--vp-c-divider); } @@ -707,9 +707,9 @@ onUnmounted(() => { .log-content { max-height: 300px; - overflow-y: auto; + background: var(--vp-c-bg-soft); - border-radius: 8px; + border-radius: 6px; padding: 0.75rem; font-size: 0.8rem; } @@ -717,7 +717,7 @@ onUnmounted(() => { .log-empty { text-align: center; color: var(--vp-c-text-3); - padding: 1rem; + padding: 0.75rem; } .log-entry { @@ -759,7 +759,7 @@ onUnmounted(() => { .key-points { background: rgba(59, 130, 246, 0.1); border-radius: 10px; - padding: 1rem; + padding: 0.75rem; border: 1px solid rgba(59, 130, 246, 0.3); } diff --git a/docs/.vitepress/theme/components/appendix/terminal-intro/AdvancedTUIDemo.vue b/docs/.vitepress/theme/components/appendix/terminal-intro/AdvancedTUIDemo.vue index e2f7408..cca6950 100644 --- a/docs/.vitepress/theme/components/appendix/terminal-intro/AdvancedTUIDemo.vue +++ b/docs/.vitepress/theme/components/appendix/terminal-intro/AdvancedTUIDemo.vue @@ -101,7 +101,7 @@ const simulateResize = () => { .advanced-tui { background: #0a0a0a; padding: 20px; - border-radius: 8px; + border-radius: 6px; border: 1px solid #333; font-family: 'Menlo', monospace; } diff --git a/docs/.vitepress/theme/components/appendix/terminal-intro/ArchitectureDemo.vue b/docs/.vitepress/theme/components/appendix/terminal-intro/ArchitectureDemo.vue index 9f1d9eb..1e80c47 100644 --- a/docs/.vitepress/theme/components/appendix/terminal-intro/ArchitectureDemo.vue +++ b/docs/.vitepress/theme/components/appendix/terminal-intro/ArchitectureDemo.vue @@ -596,7 +596,7 @@ const reset = () => { .node { background: #18181b; border: 2px solid #27272a; - border-radius: 8px; + border-radius: 6px; width: 140px; height: 130px; display: flex; @@ -757,7 +757,7 @@ const reset = () => { gap: 20px; background: #18181b; padding: 20px; - border-radius: 8px; + border-radius: 6px; border: 1px solid #27272a; } diff --git a/docs/.vitepress/theme/components/appendix/terminal-intro/BufferSwitchDemo.vue b/docs/.vitepress/theme/components/appendix/terminal-intro/BufferSwitchDemo.vue index 731b615..1c273c8 100644 --- a/docs/.vitepress/theme/components/appendix/terminal-intro/BufferSwitchDemo.vue +++ b/docs/.vitepress/theme/components/appendix/terminal-intro/BufferSwitchDemo.vue @@ -127,7 +127,7 @@ const quitVim = () => { .terminal-frame { background: #1e1e1e; - border-radius: 8px; + border-radius: 6px; overflow: hidden; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3); border: 1px solid #333; @@ -274,7 +274,7 @@ const quitVim = () => { .controls { margin-top: 15px; background: #f6f6f7; - border-radius: 8px; + border-radius: 6px; padding: 15px; border: 1px solid #eee; } diff --git a/docs/.vitepress/theme/components/appendix/terminal-intro/CellInspector.vue b/docs/.vitepress/theme/components/appendix/terminal-intro/CellInspector.vue index 40dce1c..5dda63f 100644 --- a/docs/.vitepress/theme/components/appendix/terminal-intro/CellInspector.vue +++ b/docs/.vitepress/theme/components/appendix/terminal-intro/CellInspector.vue @@ -171,7 +171,7 @@ const cellStyle = computed(() => ({ align-items: center; justify-content: center; border: 1px solid #27272a; - border-radius: 8px; + border-radius: 6px; background: #000; aspect-ratio: 3/4; } diff --git a/docs/.vitepress/theme/components/appendix/terminal-intro/CookedRawDemo.vue b/docs/.vitepress/theme/components/appendix/terminal-intro/CookedRawDemo.vue index ba8cfd9..597b6c4 100644 --- a/docs/.vitepress/theme/components/appendix/terminal-intro/CookedRawDemo.vue +++ b/docs/.vitepress/theme/components/appendix/terminal-intro/CookedRawDemo.vue @@ -191,7 +191,7 @@ const handleRawMode = (e) => { padding: 10px; border: 1px solid var(--vp-c-divider); background: var(--vp-c-bg-soft); - border-radius: 8px; + border-radius: 6px; cursor: pointer; font-weight: bold; transition: all 0.2s; @@ -205,7 +205,7 @@ const handleRawMode = (e) => { .demo-container { background: #1e1e1e; - border-radius: 8px; + border-radius: 6px; padding: 20px; border: 1px solid #333; position: relative; diff --git a/docs/.vitepress/theme/components/appendix/terminal-intro/EscapeParserDemo.vue b/docs/.vitepress/theme/components/appendix/terminal-intro/EscapeParserDemo.vue index 468b4fd..4859ba4 100644 --- a/docs/.vitepress/theme/components/appendix/terminal-intro/EscapeParserDemo.vue +++ b/docs/.vitepress/theme/components/appendix/terminal-intro/EscapeParserDemo.vue @@ -211,7 +211,7 @@ const play = async () => { diff --git a/docs/.vitepress/theme/components/appendix/typescript-intro/InterfaceDemo.vue b/docs/.vitepress/theme/components/appendix/typescript-intro/InterfaceDemo.vue new file mode 100644 index 0000000..a0227dd --- /dev/null +++ b/docs/.vitepress/theme/components/appendix/typescript-intro/InterfaceDemo.vue @@ -0,0 +1,445 @@ + + + + + diff --git a/docs/.vitepress/theme/components/appendix/typescript-intro/TypeAnnotationDemo.vue b/docs/.vitepress/theme/components/appendix/typescript-intro/TypeAnnotationDemo.vue new file mode 100644 index 0000000..537fb1b --- /dev/null +++ b/docs/.vitepress/theme/components/appendix/typescript-intro/TypeAnnotationDemo.vue @@ -0,0 +1,402 @@ + + + + + diff --git a/docs/.vitepress/theme/components/appendix/typescript-intro/TypeInferenceDemo.vue b/docs/.vitepress/theme/components/appendix/typescript-intro/TypeInferenceDemo.vue new file mode 100644 index 0000000..c805bd4 --- /dev/null +++ b/docs/.vitepress/theme/components/appendix/typescript-intro/TypeInferenceDemo.vue @@ -0,0 +1,618 @@ + + + + + diff --git a/docs/.vitepress/theme/components/appendix/url-to-browser/BrowserRenderingDemo.vue b/docs/.vitepress/theme/components/appendix/url-to-browser/BrowserRenderingDemo.vue index 0b1154f..d6c6358 100644 --- a/docs/.vitepress/theme/components/appendix/url-to-browser/BrowserRenderingDemo.vue +++ b/docs/.vitepress/theme/components/appendix/url-to-browser/BrowserRenderingDemo.vue @@ -455,7 +455,7 @@ onUnmounted(() => { .stage-col { background: var(--vp-c-bg); - border-radius: 8px; + border-radius: 6px; border: 1px solid var(--vp-c-divider); display: flex; flex-direction: column; @@ -481,7 +481,7 @@ onUnmounted(() => { font-size: 11px; color: var(--vp-c-text-2); line-height: 1.5; - overflow-y: auto; + } .indent { margin-left: 12px; } .style-tag { color: #e6a23c; } @@ -650,7 +650,7 @@ onUnmounted(() => { display: flex; align-items: center; justify-content: center; - border-radius: 8px; + border-radius: 6px; box-shadow: 0 4px 12px rgba(64, 158, 255, 0.3); } .check-mark { @@ -771,7 +771,7 @@ onUnmounted(() => { margin-top: 16px; background: var(--vp-c-bg-alt); border: 1px solid var(--vp-c-divider); - border-radius: 8px; + border-radius: 6px; padding: 12px; font-size: 13px; } diff --git a/docs/.vitepress/theme/components/appendix/url-to-browser/DnsLookupDemo.vue b/docs/.vitepress/theme/components/appendix/url-to-browser/DnsLookupDemo.vue index 1173f72..4d4dc9f 100644 --- a/docs/.vitepress/theme/components/appendix/url-to-browser/DnsLookupDemo.vue +++ b/docs/.vitepress/theme/components/appendix/url-to-browser/DnsLookupDemo.vue @@ -345,7 +345,7 @@ onUnmounted(() => { diff --git a/docs/.vitepress/theme/components/appendix/web-basics/BrowserRenderingDemo.vue b/docs/.vitepress/theme/components/appendix/web-basics/BrowserRenderingDemo.vue index 7654149..0a5f8b4 100644 --- a/docs/.vitepress/theme/components/appendix/web-basics/BrowserRenderingDemo.vue +++ b/docs/.vitepress/theme/components/appendix/web-basics/BrowserRenderingDemo.vue @@ -339,9 +339,9 @@ const hoveredPart = ref(null) diff --git a/docs/.vitepress/theme/components/appendix/web-basics/CssCommonProperties.vue b/docs/.vitepress/theme/components/appendix/web-basics/CssCommonProperties.vue index 79d1d53..3f7ca8c 100644 --- a/docs/.vitepress/theme/components/appendix/web-basics/CssCommonProperties.vue +++ b/docs/.vitepress/theme/components/appendix/web-basics/CssCommonProperties.vue @@ -135,7 +135,7 @@ const categories = [ desc: '圆角', categoryLabel: '边框', fullDesc: '让盒子的角变圆润。现在的按钮通常都有点圆角。', - example: 'border-radius: 8px;' + example: 'border-radius: 6px;' }, { name: 'box-shadow', @@ -194,7 +194,7 @@ const categories = [ diff --git a/docs/.vitepress/theme/components/appendix/web-basics/CssLayoutDemo.vue b/docs/.vitepress/theme/components/appendix/web-basics/CssLayoutDemo.vue index cc07c4d..6003b30 100644 --- a/docs/.vitepress/theme/components/appendix/web-basics/CssLayoutDemo.vue +++ b/docs/.vitepress/theme/components/appendix/web-basics/CssLayoutDemo.vue @@ -183,7 +183,7 @@ const getItemColor = (n) => { diff --git a/docs/.vitepress/theme/components/appendix/web-basics/FrontendEvolutionDemo.vue b/docs/.vitepress/theme/components/appendix/web-basics/FrontendEvolutionDemo.vue index 6c0975e..99851f4 100644 --- a/docs/.vitepress/theme/components/appendix/web-basics/FrontendEvolutionDemo.vue +++ b/docs/.vitepress/theme/components/appendix/web-basics/FrontendEvolutionDemo.vue @@ -482,7 +482,7 @@ export default { } .editor-content { - padding: 1rem; + padding: 0.75rem; overflow: auto; flex: 1; } @@ -515,7 +515,7 @@ export default { background: white; border: 1px solid rgba(0, 0, 0, 0.1); padding: 0.8rem 1.2rem; - border-radius: 8px; + border-radius: 6px; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05); font-weight: 600; font-size: 0.9rem; diff --git a/docs/.vitepress/theme/components/appendix/web-basics/HttpExchangeDemo.vue b/docs/.vitepress/theme/components/appendix/web-basics/HttpExchangeDemo.vue index 0ef3ec4..10acfa7 100644 --- a/docs/.vitepress/theme/components/appendix/web-basics/HttpExchangeDemo.vue +++ b/docs/.vitepress/theme/components/appendix/web-basics/HttpExchangeDemo.vue @@ -192,9 +192,9 @@ const statusClass = computed(() => { diff --git a/docs/.vitepress/theme/components/appendix/web-basics/JQueryVsStateDemo.vue b/docs/.vitepress/theme/components/appendix/web-basics/JQueryVsStateDemo.vue index 5d146f4..446c3e5 100644 --- a/docs/.vitepress/theme/components/appendix/web-basics/JQueryVsStateDemo.vue +++ b/docs/.vitepress/theme/components/appendix/web-basics/JQueryVsStateDemo.vue @@ -208,7 +208,7 @@ const resetAll = () => { border: 1px solid var(--vp-c-divider); background: var(--vp-c-bg); border-radius: 12px; - padding: 1rem; + padding: 0.75rem; } .pane-title { @@ -359,7 +359,7 @@ const resetAll = () => { color: var(--vp-c-text-2); border: 1px solid var(--vp-c-divider); background: var(--vp-c-bg-soft); - border-radius: 8px; + border-radius: 6px; padding: 0.35rem 0.5rem; } diff --git a/docs/.vitepress/theme/components/appendix/web-basics/NetworkLayers.vue b/docs/.vitepress/theme/components/appendix/web-basics/NetworkLayers.vue index fe621d5..14d828b 100644 --- a/docs/.vitepress/theme/components/appendix/web-basics/NetworkLayers.vue +++ b/docs/.vitepress/theme/components/appendix/web-basics/NetworkLayers.vue @@ -151,7 +151,7 @@ const layers = [ diff --git a/docs/.vitepress/theme/index.js b/docs/.vitepress/theme/index.js index bfc4c03..8659bee 100644 --- a/docs/.vitepress/theme/index.js +++ b/docs/.vitepress/theme/index.js @@ -81,6 +81,12 @@ import AudioWaveformDemo from './components/appendix/audio-intro/AudioWaveformDe import AudioTokenizationDemo from './components/appendix/audio-intro/AudioTokenizationDemo.vue' import SpectrogramViz from './components/appendix/audio-intro/SpectrogramViz.vue' import AutoregressiveAudioDemo from './components/appendix/audio-intro/AutoregressiveAudioDemo.vue' +import AudioQuickStartDemo from './components/appendix/audio-intro/AudioQuickStartDemo.vue' +import MelSpectrogramDemo from './components/appendix/audio-intro/MelSpectrogramDemo.vue' +import TTSPipelineDemo from './components/appendix/audio-intro/TTSPipelineDemo.vue' +import VoiceCloningDemo from './components/appendix/audio-intro/VoiceCloningDemo.vue' +import ASRvsTTSDemo from './components/appendix/audio-intro/ASRvsTTSDemo.vue' +import EmotionControlDemo from './components/appendix/audio-intro/EmotionControlDemo.vue' // Web Basics Components import WebTechTriad from './components/appendix/web-basics/WebTechTriad.vue' @@ -101,6 +107,26 @@ import TcpUdpComparison from './components/appendix/web-basics/TcpUdpComparison. import SubnetCalculator from './components/appendix/web-basics/SubnetCalculator.vue' import NetworkTroubleshooting from './components/appendix/web-basics/NetworkTroubleshooting.vue' +// Computer Fundamentals Components +import TransistorDemo from './components/appendix/computer-fundamentals/TransistorDemo.vue' +import LogicGateDemo from './components/appendix/computer-fundamentals/LogicGateDemo.vue' +import AdderDemo from './components/appendix/computer-fundamentals/AdderDemo.vue' +import CpuArchitectureDemo from './components/appendix/computer-fundamentals/CpuArchitectureDemo.vue' +import ProcessDemo from './components/appendix/computer-fundamentals/ProcessDemo.vue' +import MemoryDemo from './components/appendix/computer-fundamentals/MemoryDemo.vue' +import FilesystemDemo from './components/appendix/computer-fundamentals/FilesystemDemo.vue' +import EncodingDemo from './components/appendix/computer-fundamentals/EncodingDemo.vue' +import StorageDemo from './components/appendix/computer-fundamentals/StorageDemo.vue' +import TransmissionDemo from './components/appendix/computer-fundamentals/TransmissionDemo.vue' +import DataStructureDemo from './components/appendix/computer-fundamentals/DataStructureDemo.vue' +import AlgorithmDemo from './components/appendix/computer-fundamentals/AlgorithmDemo.vue' +import LanguageMapDemo from './components/appendix/computer-fundamentals/LanguageMapDemo.vue' +import TypeSystemDemo from './components/appendix/computer-fundamentals/TypeSystemDemo.vue' +import CompilerDemo from './components/appendix/computer-fundamentals/CompilerDemo.vue' +import CFNetworkLayers from './components/appendix/computer-fundamentals/NetworkLayers.vue' +import CFSubnetCalculator from './components/appendix/computer-fundamentals/SubnetCalculator.vue' +import CFTcpUdpComparison from './components/appendix/computer-fundamentals/TcpUdpComparison.vue' + // Deployment appendix components import DeploymentOverviewDemo from './components/appendix/deployment/DeploymentOverviewDemo.vue' import DeploymentBuildDemo from './components/appendix/deployment/DeploymentBuildDemo.vue' @@ -122,6 +148,9 @@ import TcpHandshakeDemo from './components/appendix/web-basics/TcpHandshakeDemo. import UrlParserDemo from './components/appendix/web-basics/UrlParserDemo.vue' import HttpExchangeDemo from './components/appendix/web-basics/HttpExchangeDemo.vue' import BrowserRenderingDemo from './components/appendix/web-basics/BrowserRenderingDemo.vue' + +// URL to Browser Components +import UrlToBrowserQuickStart from './components/appendix/url-to-browser/UrlToBrowserQuickStart.vue' import FrontendEvolutionDemo from './components/appendix/web-basics/FrontendEvolutionDemo.vue' import SliceRequestDemo from './components/appendix/web-basics/SliceRequestDemo.vue' import ResponsiveGridDemo from './components/appendix/web-basics/ResponsiveGridDemo.vue' @@ -222,6 +251,7 @@ import MessageQueueComponentsDemo from './components/appendix/queue-design/Messa import PointToPointVsPubSubDemo from './components/appendix/queue-design/PointToPointVsPubSubDemo.vue' import MessageQueueComparisonDemo from './components/appendix/queue-design/MessageQueueComparisonDemo.vue' import CouplingDemo from './components/appendix/queue-design/CouplingDemo.vue' +import DecouplingDemo from './components/appendix/queue-design/DecouplingDemo.vue' import PubSubDemo from './components/appendix/queue-design/PubSubDemo.vue' import DeadLetterQueueDemo from './components/appendix/queue-design/DeadLetterQueueDemo.vue' import DelayedMessageDemo from './components/appendix/queue-design/DelayedMessageDemo.vue' @@ -469,6 +499,34 @@ import ResourceAnalogy from './components/appendix/api-design/ResourceAnalogy.vu import RequestStructureDemo from './components/appendix/api-design/RequestStructureDemo.vue' import ResponseStructureDemo from './components/appendix/api-design/ResponseStructureDemo.vue' +// JavaScript Intro Components +import VariableBoxDemo from './components/appendix/javascript-intro/VariableBoxDemo.vue' +import ReferenceDemo from './components/appendix/javascript-intro/ReferenceDemo.vue' +import FunctionMachineDemo from './components/appendix/javascript-intro/FunctionMachineDemo.vue' +import ScopeDemo from './components/appendix/javascript-intro/ScopeDemo.vue' +import ClosureDemo from './components/appendix/javascript-intro/ClosureDemo.vue' +import DOMTreeDemo from './components/appendix/javascript-intro/DOMTreeDemo.vue' +import AsyncRestaurantDemo from './components/appendix/javascript-intro/AsyncRestaurantDemo.vue' +import JSEventLoopDemo from './components/appendix/javascript-intro/JSEventLoopDemo.vue' +import VariableScopeDemo from './components/appendix/javascript-intro/VariableScopeDemo.vue' +import DataTypeDemo from './components/appendix/javascript-intro/DataTypeDemo.vue' +import ThisContextDemo from './components/appendix/javascript-intro/ThisContextDemo.vue' +import PrototypeDemo from './components/appendix/javascript-intro/PrototypeDemo.vue' +import AsyncDemo from './components/appendix/javascript-intro/AsyncDemo.vue' + +// JavaScript Runtime Components +import RuntimeEnvironmentDemo from './components/appendix/js-runtime/RuntimeEnvironmentDemo.vue' +import CallStackDemo from './components/appendix/js-runtime/CallStackDemo.vue' +import TaskQueueDemo from './components/appendix/js-runtime/TaskQueueDemo.vue' +import MemoryLeakDemo from './components/appendix/js-runtime/MemoryLeakDemo.vue' +import GarbageCollectionDemo from './components/appendix/js-runtime/GarbageCollectionDemo.vue' + +// TypeScript Intro Components +import TypeAnnotationDemo from './components/appendix/typescript-intro/TypeAnnotationDemo.vue' +import InterfaceDemo from './components/appendix/typescript-intro/InterfaceDemo.vue' +import GenericDemo from './components/appendix/typescript-intro/GenericDemo.vue' +import TypeInferenceDemo from './components/appendix/typescript-intro/TypeInferenceDemo.vue' + export default { extends: DefaultTheme, Layout, @@ -549,10 +607,17 @@ export default { app.component('AudioTokenizationDemo', AudioTokenizationDemo) app.component('SpectrogramViz', SpectrogramViz) app.component('AutoregressiveAudioDemo', AutoregressiveAudioDemo) + app.component('AudioQuickStartDemo', AudioQuickStartDemo) + app.component('MelSpectrogramDemo', MelSpectrogramDemo) + app.component('TTSPipelineDemo', TTSPipelineDemo) + app.component('VoiceCloningDemo', VoiceCloningDemo) + app.component('ASRvsTTSDemo', ASRvsTTSDemo) + app.component('EmotionControlDemo', EmotionControlDemo) // Web Basics Components Registration app.component('WebTechTriad', WebTechTriad) app.component('UrlToBrowserDemo', UrlToBrowserDemo) + app.component('UrlToBrowserQuickStart', UrlToBrowserQuickStart) app.component('GitWorkflowDemo', GitWorkflowDemo) app.component('GitThreeAreasDemo', GitThreeAreasDemo) app.component('GitStorageDemo', GitStorageDemo) @@ -566,6 +631,27 @@ export default { app.component('TcpUdpComparison', TcpUdpComparison) app.component('SubnetCalculator', SubnetCalculator) app.component('NetworkTroubleshooting', NetworkTroubleshooting) + + // Computer Fundamentals Components Registration + app.component('TransistorDemo', TransistorDemo) + app.component('LogicGateDemo', LogicGateDemo) + app.component('AdderDemo', AdderDemo) + app.component('CpuArchitectureDemo', CpuArchitectureDemo) + app.component('ProcessDemo', ProcessDemo) + app.component('MemoryDemo', MemoryDemo) + app.component('FilesystemDemo', FilesystemDemo) + app.component('EncodingDemo', EncodingDemo) + app.component('StorageDemo', StorageDemo) + app.component('TransmissionDemo', TransmissionDemo) + app.component('DataStructureDemo', DataStructureDemo) + app.component('AlgorithmDemo', AlgorithmDemo) + app.component('LanguageMapDemo', LanguageMapDemo) + app.component('TypeSystemDemo', TypeSystemDemo) + app.component('CompilerDemo', CompilerDemo) + app.component('CFNetworkLayers', CFNetworkLayers) + app.component('CFSubnetCalculator', CFSubnetCalculator) + app.component('CFTcpUdpComparison', CFTcpUdpComparison) + // Deployment appendix app.component('DeploymentOverviewDemo', DeploymentOverviewDemo) app.component('DeploymentBuildDemo', DeploymentBuildDemo) @@ -617,15 +703,6 @@ export default { app.component('ImperativeVsDeclarativeDemo', ImperativeVsDeclarativeDemo) app.component('ComponentReusabilityDemo', ComponentReusabilityDemo) - // Frontend Evolution Components Registration - app.component('FrontendEvolutionDemo', FrontendEvolutionTimelineDemo) - app.component('EvolutionSliceRequestDemo', EvolutionSliceRequestDemo) - app.component('EvolutionResponsiveGridDemo', EvolutionResponsiveGridDemo) - app.component('EvolutionJQueryVsStateDemo', EvolutionJQueryVsStateDemo) - app.component('RoutingModeDemo', EvolutionRoutingModeDemo) - app.component('RenderingStrategyDemo', EvolutionRenderingStrategyDemo) - app.component('ImperativeVsDeclarativeDemo', EvolutionImperativeVsDeclarativeDemo) - app.component('BackendEvolutionDemo', BackendEvolutionDemo) app.component('BackendQuickStartDemo', BackendQuickStartDemo) app.component('EvolutionIntroDemo', EvolutionIntroDemo) @@ -693,6 +770,7 @@ export default { app.component('PointToPointVsPubSubDemo', PointToPointVsPubSubDemo) app.component('MessageQueueComparisonDemo', MessageQueueComparisonDemo) app.component('CouplingDemo', CouplingDemo) + app.component('DecouplingDemo', DecouplingDemo) app.component('PubSubDemo', PubSubDemo) app.component('DeadLetterQueueDemo', DeadLetterQueueDemo) app.component('DelayedMessageDemo', DelayedMessageDemo) @@ -911,6 +989,7 @@ export default { app.component('MacroMicroTaskDemo', MacroMicroTaskDemo) app.component('RenderingPerformanceDemo', RenderingPerformanceDemo) app.component('RenderingPipelineDemo', RenderingPipelineDemo) + app.component('EventLoopDemo', JSEventLoopDemo) // Alias for browser rendering context // Cache Design Extra Components Registration app.component('CacheArchitectureOverview', CacheArchitectureOverview) @@ -947,6 +1026,34 @@ export default { app.component('ReliabilityDemo', ReliabilityDemo) app.component('IdempotenceDemo', IdempotenceDemo) app.component('MQComparisonDemo', MQComparisonDemo) + + // JavaScript Intro Components Registration + app.component('VariableBoxDemo', VariableBoxDemo) + app.component('ReferenceDemo', ReferenceDemo) + app.component('FunctionMachineDemo', FunctionMachineDemo) + app.component('ScopeDemo', ScopeDemo) + app.component('VariableScopeDemo', VariableScopeDemo) + app.component('DataTypeDemo', DataTypeDemo) + app.component('ClosureDemo', ClosureDemo) + app.component('ThisContextDemo', ThisContextDemo) + app.component('PrototypeDemo', PrototypeDemo) + app.component('AsyncDemo', AsyncDemo) + app.component('DOMTreeDemo', DOMTreeDemo) + app.component('AsyncRestaurantDemo', AsyncRestaurantDemo) + app.component('JSEventLoopDemo', JSEventLoopDemo) + + // JavaScript Runtime Components Registration + app.component('RuntimeEnvironmentDemo', RuntimeEnvironmentDemo) + app.component('CallStackDemo', CallStackDemo) + app.component('TaskQueueDemo', TaskQueueDemo) + app.component('MemoryLeakDemo', MemoryLeakDemo) + app.component('GarbageCollectionDemo', GarbageCollectionDemo) + + // TypeScript Intro Components Registration + app.component('TypeAnnotationDemo', TypeAnnotationDemo) + app.component('InterfaceDemo', InterfaceDemo) + app.component('GenericDemo', GenericDemo) + app.component('TypeInferenceDemo', TypeInferenceDemo) }, setup() { const route = useRoute() diff --git a/docs/en-us/stage-3/intro.md b/docs/en-us/stage-3/intro.md index a0f4a7e..c831588 100644 --- a/docs/en-us/stage-3/intro.md +++ b/docs/en-us/stage-3/intro.md @@ -10,7 +10,7 @@ Deeply master the MCP protocol and Claude Code advanced techniques to improve de + +**算法的核心指标:** + +| 指标 | 含义 | 为什么重要 | +|------|------|-----------| +| **时间复杂度** | 运行时间随数据量增长的趋势 | 预测大规模数据的性能 | +| **空间复杂度** | 内存占用随数据量增长的趋势 | 评估内存消耗 | +| **正确性** | 是否总能得到正确结果 | 算法的基本要求 | + +::: tip 📊 逐行解读这张表 +**时间复杂度**:用大 O 表示法描述。O(n) 表示数据量翻倍,时间翻倍;O(n²) 表示数据量翻倍,时间变成 4 倍。 + +**空间复杂度**:同样用大 O 表示法。有些算法用空间换时间(如哈希表),有些用时间换空间(如压缩算法)。 + +**正确性**:算法必须对所有可能的输入都能给出正确结果。边界条件(空输入、极大输入)最容易出错。 +::: + +--- + +## 1. 二分查找:每次排除一半 + +### 1.1 二分查找的原理 + +::: tip 💡 二分查找如何工作? +**前提**:数据必须有序 + +**过程**: +1. 找到中间元素 +2. 如果中间元素等于目标,找到! +3. 如果目标小于中间元素,在左半部分继续 +4. 如果目标大于中间元素,在右半部分继续 +5. 每次排除一半,直到找到或确定不存在 + +**时间复杂度**:O(log n) + +**生活类比**:猜数字游戏。我想一个 1-100 的数,你每次猜中间,我告诉你大了还是小了。最多猜 7 次就能猜中(因为 2⁷ = 128 > 100)。 +::: + +### 1.2 为什么二分查找这么快? + +| 数据量 | 线性查找 | 二分查找 | +|--------|---------|---------| +| 100 | 100 次 | 7 次 | +| 1,000 | 1,000 次 | 10 次 | +| 1,000,000 | 1,000,000 次 | 20 次 | +| 1,000,000,000 | 1,000,000,000 次 | 30 次 | + +::: tip 💡 对数增长的威力 +二分查找的时间复杂度是 O(log n),这意味着: + +- 10 亿数据,最多查找 30 次 +- 1 万亿数据,最多查找 40 次 + +这就是对数增长的威力——数据量增加 1000 倍,查找次数只增加 10 次。 +::: + +--- + +## 2. 排序:将无序变有序 + +### 2.1 常见排序算法 + +| 算法 | 时间复杂度 | 特点 | 适用场景 | +|------|-----------|------|---------| +| **冒泡排序** | O(n²) | 简单但慢 | 教学、小数据量 | +| **选择排序** | O(n²) | 简单但慢 | 小数据量 | +| **插入排序** | O(n²) | 对近乎有序的数据快 | 小数据、近乎有序 | +| **快速排序** | O(n log n) | 实际最快 | 通用排序 | +| **归并排序** | O(n log n) | 稳定排序 | 需要稳定性的场景 | +| **堆排序** | O(n log n) | 原地排序 | 内存受限场景 | + +### 2.2 为什么快速排序"快"? + +::: tip 💡 快速排序的原理 +**核心思想**:分治法 + +1. 选一个"基准"元素 +2. 把比基准小的放左边,比基准大的放右边 +3. 对左右两部分递归排序 +4. 合并结果 + +**为什么快?** +- 每次划分后,基准元素就到了最终位置 +- 平均情况下,每次划分大约排除一半元素 +- 时间复杂度 O(n log n) + +**生活类比**:整理书架。先抽出一本书,把比它薄的放左边,比它厚的放右边。然后对左右两堆分别重复这个过程。 +::: + +--- + +## 3. 递归:自己调用自己 + +### 3.1 递归的本质 + +::: tip 💡 什么是递归? +**递归**是函数调用自身的编程技巧。 + +**两个关键要素**: +1. **基本情况**:什么时候停止递归? +2. **递归步骤**:如何把问题分解成更小的子问题? + +**经典例子:阶乘** +```js +function factorial(n) { + if (n <= 1) return 1 // 基本情况 + return n * factorial(n - 1) // 递归步骤 +} +``` + +**生活类比**:俄罗斯套娃。打开一个娃娃,里面是更小的娃娃,直到最小的那个打不开为止。 +::: + +### 3.2 递归 vs 迭代 + +| 特性 | 递归 | 迭代(循环) | +|------|------|-------------| +| **代码简洁度** | 通常更简洁 | 可能更复杂 | +| **内存消耗** | 较高(调用栈) | 较低 | +| **性能** | 稍慢(函数调用开销) | 更快 | +| **适用场景** | 树遍历、分治算法 | 简单重复任务 | + +::: warning ⚠️ 递归的陷阱 +**栈溢出**:递归层次太深,调用栈空间耗尽。 + +**解决方法**: +- 改用迭代 +- 使用尾递归优化(某些语言支持) +- 限制递归深度 +::: + +--- + +## 4. 贪心算法:每步选最优 + +### 4.1 贪心的思想 + +::: tip 💡 什么是贪心算法? +**贪心算法**在每一步都选择当前看起来最优的选择,希望最终得到全局最优解。 + +**适用条件**: +1. **贪心选择性质**:局部最优能导致全局最优 +2. **最优子结构**:问题的最优解包含子问题的最优解 + +**经典例子:硬币找零** +- 目标:用最少的硬币凑出指定金额 +- 贪心策略:每次选最大的硬币 +- 结果:67 元 = 50 + 10 + 5 + 1 + 1(5 枚) + +**生活类比**:登山时,每次都选最陡的路往上走。虽然不一定能到最高峰,但通常能到不错的位置。 +::: + +### 4.2 贪心的局限性 + +::: warning ⚠️ 贪心不一定得到最优解 +**反例:硬币找零** + +如果硬币面值是 [1, 3, 4],要凑 6 元: +- 贪心:4 + 1 + 1 = 3 枚 +- 最优:3 + 3 = 2 枚 + +贪心算法在这里失败了! + +**教训**:贪心算法简单高效,但不总是能得到最优解。使用前要证明问题满足贪心条件。 +::: + +--- + +## 5. 算法设计范式 + +| 范式 | 思想 | 典型算法 | 适用问题 | +|------|------|---------|---------| +| **分治** | 把问题分解成小问题 | 快速排序、归并排序 | 可分解的问题 | +| **贪心** | 每步选最优 | 最小生成树、霍夫曼编码 | 有贪心性质的问题 | +| **动态规划** | 记录子问题的解 | 背包问题、最短路径 | 有重叠子问题 | +| **回溯** | 试错,走不通就回退 | 八皇后、全排列 | 搜索问题 | + +--- + +## 6. 总结:算法是解决问题的艺术 + +让我们用一个比喻总结各种算法思想: + +| 思想 | 比喻 | 核心要点 | +|------|------|---------| +| **二分查找** | 猜数字 | 每次排除一半 | +| **排序** | 整理书架 | 建立秩序 | +| **递归** | 俄罗斯套娃 | 化大为小 | +| **贪心** | 登山选路 | 局部最优 | + +::: tip 💡 核心启示 +**算法的本质是"效率"和"正确性"的平衡。** + +- 好的算法能让程序效率提升几个数量级 +- 但过度优化可能引入复杂性 +- 先保证正确,再追求效率 + +理解算法思维,比记住具体算法更重要: +- 分治:把大问题分解成小问题 +- 贪心:每步选最优 +- 动态规划:记录子问题的解 +- 回溯:试错,走不通就回退 +::: + +--- + +## 延伸阅读 + +- **算法导论**:系统学习算法的经典教材 +- **LeetCode**:通过刷题提升算法能力 +- **算法可视化**:直观理解算法执行过程 +- **竞赛算法**:学习更高级的算法技巧 diff --git a/docs/zh-cn/appendix/1-computer-fundamentals/computer-networks.md b/docs/zh-cn/appendix/1-computer-fundamentals/computer-networks.md new file mode 100644 index 0000000..dc7518a --- /dev/null +++ b/docs/zh-cn/appendix/1-computer-fundamentals/computer-networks.md @@ -0,0 +1,625 @@ +# 网络:两台电脑如何对话 +::: tip 🎯 核心问题 +**当你在浏览器输入 www.baidu.com 并按下回车,到底发生了什么?** 这个简单动作背后,其实隐藏着一个庞大的"快递系统":从填写订单(URL)到查询地址簿(DNS),从建立运输通道(TCP)到快递员送货(HTTP),最终在你屏幕上展示(渲染)。本章带你完整理解这个神奇的过程。 +::: + +--- + +## 0. 五层模型总览:快递公司的组织架构 + +现代计算机网络就像一个**快递公司**,采用五层分层模型,每层负责不同的工作: + + + +::: tip 💡 为什么需要分层? +想象一个没有分工的快递公司: + +- **每个人什么都干**:接电话、分拣、打包、开车送货... +- **效率极低**:没人专精,什么都做不好 +- **难以扩展**:想加个"航空运输",所有员工都要重新培训 + +**分层设计**解决了这些问题: + +- **模块化**:每层独立设计和实现,改一层不影响其他层 +- **易维护**:网络慢了?查物理层和数据链路层;安全问题?查应用层 +- **标准化**:统一的接口和协议,不同厂商的设备能互相通信 +- **可扩展**:新技术可以替换某一层,比如从铜线换成光纤,只需改物理层 + ::: + +| 层级 | 技术名称 | 快递公司类比 | 核心职责 | 常见协议/设备 | +| ----- | ---------- | ---------------- | ---------------------------------------- | ------------------ | +| **5** | 应用层 | **客户服务部门** | 处理具体业务(网页、邮件、文件传输) | HTTP, FTP, SMTP | +| **4** | 传输层 | **包裹分拣组** | 确保包裹可靠送达(_TCP_)或快速送达(_UDP_) | TCP, UDP | +| **3** | 网络层 | **路由规划部** | 规划最佳运输路线,选择走哪条路 | IP, 路由器 | +| **2** | 数据链路层 | **车队管理** | 管理车辆之间的通信,MAC 地址寻址 | 以太网, 交换机 | +| **1** | 物理层 | **道路和车辆** | 实际的物理传输(电缆、光纤、无线电波) | 网线, 光纤, 无线电 | + +::: tip 📊 逐行解读这张表 +**第5层(应用层)**:这是你直接接触的层。浏览器打开网页、邮件客户端收发邮件,都是在调用这一层的服务。它负责处理"具体的业务逻辑"。 + +**第4层(传输层)**:应用层把数据给它,它负责决定用什么方式"寄送"。TCP 像挂号信(可靠但慢),UDP 像平信(快但可能丢)。这一层用**端口号**区分不同的应用程序。 + +**第3层(网络层)**:这是"全球定位系统"层。IP 地址就在这一层,路由器根据 IP 地址规划路线:"从北京到上海,应该走哪条高速公路?" + +**第2层(数据链路层)**:这一层负责"两站之间"的运输。就像快递车从北京分拣中心开到天津分拣中心,这一段路的通信规则由数据链路层规定。MAC 地址(设备身份证)也在这一层。 + +**第1层(物理层)**:这是最底层,实实在在的物理介质。网线里的电信号、光纤里的光信号、Wi-Fi 的无线电波,都是物理层负责的。 +::: + +--- + +## 1. 物理层:道路和车辆 + +### 1.1 基本概念 + +::: tip 💡 物理层是什么? +物理层负责在物理介质上传输原始的比特流(0 和 1)。 + +**生活类比**:想象快递公司需要有**道路**和**运输车辆**: + +- 道路可以是:高速公路(光纤)、普通公路(网线)、航空线路(无线电波) +- 车辆可以是:卡车(有线传输)、飞机(无线传输) +- 货物(数据)最终都要变成能在这些道路上运输的形式 + ::: + +**关键任务**: + +- **定义物理设备标准**:RJ45 网线接口长什么样、光纤接口怎么接 +- **规定传输介质**: + - 有线:双绞线(网线)、光纤、同轴电缆 + - 无线:Wi-Fi、蓝牙、4G/5G +- **确定电气特性**: + - 用多少电压代表 0 和 1? + - 信号频率是多少? + - 怎么编码(比如曼彻斯特编码)? + +### 1.2 传输介质 + +**有线介质**: + +| 类型 | 速度 | 距离 | 特点 | 用途 | +| ------------ | ---------------- | -------- | ------------------------ | ------------------------ | +| **双绞线** | 100Mbps - 10Gbps | 100m | 成本低,易安装,抗干扰一般 | 家庭、办公室网络 | +| **光纤** | 1Gbps - 100Tbps | 几十公里 | 速度极快,抗干扰强,成本高 | 长距离、高带宽(跨海光缆) | +| **同轴电缆** | 10Mbps - 1Gbps | 500m | 抗干扰好,但较粗 | 早期以太网、有线电视 | + +::: tip 💡 为什么光纤这么快? +光纤用**光**而不是电信号传输: + +- 光的频率极高,能调制大量数据(就像用不同颜色的光同时传输) +- 光在光纤中几乎不衰减,能传输几十公里 +- 不受电磁干扰(高压电线、雷电都不怕) + +这就像用电信号寄快递(铜线)vs 用光速寄快递(光纤),速度差异是本质级别的。 +::: + +**无线介质**: + +| 类型 | 频段 | 速度 | 距离 | 用途 | +| --------- | -------------------- | ------------------- | ------ | -------------------- | +| **Wi-Fi** | 2.4GHz / 5GHz / 6GHz | 几十 Mbps - 几 Gbps | 几十米 | 家庭、办公室无线网络 | +| **蓝牙** | 2.4GHz | 1-3 Mbps | 10m | 耳机、键鼠等短距设备 | +| **4G/5G** | 700MHz - 39GHz | 10Mbps - 10Gbps | 几公里 | 移动网络 | + +### 1.3 常见设备 + +**中继器(Repeater)**: + +- **作用**:放大信号,延长传输距离 +- **生活类比**:快递中转站。快递车开了 500 公里需要加油、司机换班,中继器就是让信号"休息充电"的地方 +- **为什么需要**:电信号在铜线传输会衰减,传几百米就弱得识别不出了 + +**集线器(Hub)**: + +- **作用**:多端口中继器,从一个口收到的信号复制到所有口 +- **缺点**:效率低,已被**交换机**取代 +- **生活类比**:一个大厅,一个人喊话,所有人都能听到,但不是喊给谁的 + +--- + +## 2. 数据链路层:车队管理 + +### 2.1 基本概念 + +::: tip 💡 数据链路层做什么? +数据链路层负责在**直连的两个节点**间传输数据帧。 + +**生活类比**:快递公司的**车队管理**: + +- 快递车从北京分拣中心开到天津分拣中心(点对点) +- 车上有司机(负责驾驶)、装卸工(负责搬运) +- 两边分拣中心之间有约定:"每天 8 点发车""用标准尺寸的快递箱" + ::: + +**核心功能**: + +- **物理地址寻址(MAC 地址)**:每个网卡都有全球唯一的身份证号 +- **帧的封装和解封装**:把网络层的数据包"装进车厢" +- **错误检测**:通过 CRC 校验,发现数据是否损坏 +- **介质访问控制**:多个设备共享一条线时,谁先谁后?(比如 Wi-Fi 多台设备连一个路由器) + +### 2.2 MAC 地址:设备的身份证 + +**MAC 地址格式**:`00:1A:2B:3C:4D:5E` + +::: tip 💡 MAC 地址 vs IP 地址 +这是初学者最容易混淆的两个概念: + +| 特性 | MAC 地址 | IP 地址 | +| ------------ | ----------------------- | --------------------------- | +| **作用范围** | 局域网内(同一个 Wi-Fi) | 全球互联网 | +| **分配方式** | 网卡出厂时烧录,全球唯一 | 由网络管理员动态分配 | +| **变化** | 一般不变(除非换网卡) | 经常变化(连不同 Wi-Fi 会变) | +| **类比** | 身份证号(跟随你一生) | 家庭住址(搬家就变) | +| **层级** | 数据链路层(第2层) | 网络层(第3层) | + +**生活类比**:你要寄快递: + +- **MAC 地址** = 收件人身份证号(唯一标识这个人) +- **IP 地址** = 收件人家庭住址(用于路由) + +快递员实际上需要"住址"才能送货,但身份证号能确保"这个人"是唯一的。 +::: + +**查看你的 MAC 地址**: + +```bash +# Windows +ipconfig /all +# 找到 "物理地址",类似: 00-1A-2B-3C-4D-5E + +# macOS/Linux +ifconfig +# 找到 "ether",类似: 00:1a:2b:3c:4d:5e +``` + +### 2.3 以太网帧:快递车厢的结构 + +**以太网帧**就是数据链路层的"快递车厢",有一套标准格式: + +``` ++------------+----------+---------+-----+----------+ +| 目标 MAC | 源 MAC | 类型 | 数据 | FCS | +| (6 bytes) | (6 bytes) | (2 bytes)| | (4 bytes) | ++------------+----------+---------+-----+----------+ +``` + +::: tip 💡 逐行理解帧结构 +**目标 MAC (6字节)**:这帧数据给谁的?就像快递单上的收件人 + +**源 MAC (6字节)**:这帧数据谁发的?就像寄件人信息 + +**类型 (2字节)**:车厢里装的是什么? + +- `0x0800` = IPv4 数据包 +- `0x0806` = ARP 请求(查询 MAC 地址) +- `0x86DD` = IPv6 数据包 + +**数据(46-1500字节)**:实际要传输的内容,就是网络层的 IP 数据包 + +**FCS (4字节)**:帧校验序列。接收方用这个检查数据是否损坏,就像快递单上的"完好无损"签章 +::: + +### 2.4 交换机:聪明的交通指挥 + +**交换机**是数据链路层的核心设备。 + +::: tip 💡 交换机 vs 集线器 +**集线器**: + +- 收到数据后,简单地"广播"到所有端口 +- 所有设备都能看到,不是给自己的也得收下来再丢弃 +- 效率低,安全性差 + +**交换机**: + +- **学习 MAC 地址**:记住哪个端口连了哪个 MAC 地址 +- **智能转发**:只把数据发到目标设备所在的端口 +- **效率高**:设备 A 和 B 通信,设备 C 不会收到 + ::: + +**交换机工作流程**: + +1. **学习**:设备 A (MAC: 11:11...) 发数据给交换机端口1 + - 交换机记下:"11:11... 在端口1" + +2. **转发**:设备 A 要发数据给设备 B (MAC: 22:22...) + - 交换机查表:"22:22... 在端口3" + - 只把数据从端口3 发出去 + +3. **广播**:如果交换机不知道目标 MAC 在哪(比如第一次通信) + - 向所有端口(除了来源端口)广播 + - "谁是 22:22...?" 目标设备回应后,交换机学习到它的位置 + +--- + +## 3. 网络层:路由规划部 + +### 3.1 IP 地址:互联网的门牌号 + +::: tip 💡 IP 地址是什么? +**IP 地址**就像互联网上的**家庭住址**,每台联网设备都需要一个。 + +**IPv4 地址格式**:`192.168.1.1` + +- 32 位,通常用点分十进制表示 +- 分为**网络部分**(前3段)和**主机部分**(最后1段) +- `192.168.1` 是网络号(这个小区) +- `.1` 是主机号(这个小区的1号房) + ::: + +**IP 地址分类(像城市规模)**: + +| 类别 | 范围示例 | 网络数 | 每个网络主机数 | 用途 | 类比 | +| -------- | --------------------- | --------- | -------------- | ---------------- | ---------- | +| **A 类** | 1.0.0.0 - 126.x.x.x | 126 | 16,777,214 | 超大型网络(早期) | 特大城市 | +| **B 类** | 128.0.0.0 - 191.x.x.x | 16,384 | 65,534 | 中型网络 | 中等城市 | +| **C 类** | 192.0.0.0 - 223.x.x.x | 2,097,152 | 254 | 小型网络(最常见) | 小区、村庄 | + +::: tip 💡 私有 IP 地址:内网 vs 外网 +有些 IP 地址段被保留为"私有",不能直接在互联网上使用: + +| 类别 | 私有 IP 范围 | 为什么用私有 IP? | +| -------- | ------------------------------- | -------------------- | +| **A 类** | `10.0.0.0 - 10.255.255.255` | 大型企业内网 | +| **B 类** | `172.16.0.0 - 172.31.255.255` | 中型企业内网 | +| **C 类** | `192.168.0.0 - 192.168.255.255` | 家庭、小公司(最常见) | + +**生活类比**: + +- **私有 IP** = 你家的门牌号("3单元501室") +- **公网 IP** = 你家在地图上的地址("XX市XX区XX路XX号") + +快递员(互联网)只能送到公网地址(你家楼门口),然后需要"路由器/NAT"转换到你家的私有地址。 +::: + +### 3.2 子网划分:把大楼分成多个单元 + +::: tip 💡 为什么要划分子网? +想象一个公司: + +- **不划分子网**:财务部、技术部、市场部都在 `192.168.1.0` 网段 + - 广播风暴:一个人发广播,所有人都能收到 + - 安全问题:技术部的开发服务器,市场部也能访问 + - 管理混乱:网络出问题,不知道是哪个部门的 + +**划分子网**: + +- 财务部:`192.168.1.0/24` +- 技术部:`192.168.2.0/24` +- 市场部:`192.168.3.0/24` + +各部门隔离,广播不出部门,管理更清晰。 +::: + +**子网掩码的作用**: + +子网掩码用来区分 IP 地址的哪部分是"网络号",哪部分是"主机号"。 + +``` +IP: 192.168.1.10 +掩码: 255.255.255.0 +----------------------- +网络号: 192.168.1.0 (前3段) +主机号: .10 (最后1段) +``` + +**CIDR 表示法**:`192.168.1.0/24` + +- `/24` 表示前 24 位是网络位 +- 剩余 8 位是主机位(2^8 - 2 = 254 个可用 IP) + + + +### 3.3 路由器:GPS 导航 + +**路由器**是网络层的核心设备,负责"规划最佳路线"。 + +::: tip 💡 路由器怎么工作? +**生活类比**:GPS 导航软件 + +- 你输入:"从北京天安门到上海外滩" +- GPS 查询地图数据库,规划出最佳路线 +- 路线可能是:"北京 → 天津 → 济南 → 南京 → 上海" + +**路由器的工作**: + +1. 收到数据包,查看目标 IP 地址 +2. 查询**路由表**(路由器的"地图数据库") +3. 选择最佳路径:"下一站该去哪个路由器?" +4. 转发到下一跳 + ::: + +**路由表示例**: + +``` +目标网络 子网掩码 网关 接口 +192.168.1.0 255.255.255.0 0.0.0.0 eth0 +192.168.2.0 255.255.255.0 192.168.1.2 eth0 +0.0.0.0 0.0.0.0 192.168.1.1 eth0 (默认网关) +``` + +::: tip 💡 理解路由表 +**第1行**:"发往 192.168.1.0 网段的包,直接从 eth0 接口发出去"(本地网络,不需要网关) + +**第2行**:"发往 192.168.2.0 网段的包,发给 192.168.1.2(它是这个网络的'门')" + +**第3行(默认网关)**:"不知道怎么走的包,全部发给 192.168.1.1(它连接互联网,会继续帮你转发)" + +这就像你去外地: + +- 在本地:走路就到(直接路由) +- 去隔壁城市:坐大巴(走网关) +- 去国外:先到机场,再转机(默认网关 → 层层转发) + ::: + +### 3.4 ICMP:网络诊断工具 + +**ICMP (Internet Control Message Protocol)** 用于网络诊断,最常用的就是 `ping` 命令。 + +**Ping 命令**: + +```bash +ping google.com + +# 输出示例 +PING google.com (142.250.185.238): 56 data bytes +64 bytes from 142.250.185.238: icmp_seq=0 ttl=117 time=12.4 ms +64 bytes from 142.250.185.238: icmp_seq=1 ttl=117 time=11.8 ms +``` + +::: tip 💡 理解 ping 的输出 +**`64 bytes`**:数据包大小(64 字节) + +**`icmp_seq=0`**:这是第 0 个包(序列号) + +**`ttl=117`**:Time To Live(生存时间) + +- 每经过一个路由器减 1 +- 防止数据包在网络中无限循环 +- 117 表示这个包经过了 255-117=138 个路由器 + +**`time=12.4 ms`**:往返时间(RTT, Round Trip Time) + +- 你的电脑发送请求 → google.com 收到 → google.com 回应 → 你的电脑收到 +- 整个过程花了 12.4 毫秒 +- 数值越小,网络延迟越低,网速越快 + ::: + +--- + +## 4. 传输层:可靠送达 vs 快速送达 + +### 4.1 端口:应用的门牌号 + +::: tip 💡 为什么需要端口号? +想象一台服务器: + +- **只有 IP 地址**:数据包到了服务器,服务器不知道给哪个程序 + - Web 服务器要? + - 邮件服务器要? + - 数据库服务器要? + +**端口号**就像"公司里的部门号": + +- IP: 公司地址(XX 市XX 路 XX 号) +- 端口: 部门(301 财务部、302 技术部、303 市场部) + +数据包到了公司,前台(操作系统)根据"部门号"(端口)转发给对应部门(应用程序)。 +::: + +**端口号范围**: + +| 范围 | 类型 | 示例 | 需要权限? | +| --------------- | -------- | ----------------------------- | --------------------------------- | +| **0-1023** | 系统端口 | 80(HTTP)、443(HTTPS)、22(SSH) | ✅ 需要(防止普通用户占用关键服务) | +| **1024-49151** | 注册端口 | 3306(MySQL)、5432(PostgreSQL) | ❌ 不需要 | +| **49152-65535** | 动态端口 | 客户端临时使用 | ❌ 不需要 | + +**常见端口速查**: + +| 端口 | 服务 | 用途 | +| --------- | ---------- | --------------- | +| **21** | FTP | 文件传输 | +| **22** | SSH | 远程登录(安全) | +| **80** | HTTP | 网页(不安全) | +| **443** | HTTPS | 网页(安全,加密) | +| **3306** | MySQL | 数据库 | +| **5432** | PostgreSQL | 数据库 | +| **6379** | Redis | 缓存数据库 | +| **27017** | MongoDB | 数据库 | + +### 4.2 TCP vs UDP:挂号信 vs 平信 + + + +**选择建议**: + +| 场景 | 选择 | 原因 | +| ------------------ | ------- | ----------------------------------------- | +| **邮件、文件传输** | **TCP** | 不能丢数据,一个字节错误都可能导致文件损坏 | +| **视频、直播** | **UDP** | 实时性优先,丢几帧没关系,但不能卡顿 | +| **网页浏览** | **TCP** | 可靠性重要,网页内容必须完整 | +| **在线游戏** | **UDP** | 速度优先,位置信息晚到比没到好 | + +::: tip 💡 深入理解:TCP 为什么可靠? +TCP 通过以下机制保证可靠: + +1. **三次握手**:确保双方都能发送和接收 +2. **序列号**:每个字节都有编号,丢包能发现 +3. **确认应答**:收到数据必须回复 ACK,没收到就重传 +4. **流量控制**:接收方告诉发送方"我的缓冲区快满了,慢点发" +5. **拥塞控制**:网络拥堵时,降低发送速度,避免"堵死" + +这就像寄挂号信: + +- 要签收(ACK) +- 丢了邮政局会重传 +- 太多信件会积压,需要控制发送速度 + ::: + +### 4.3 TCP 三次握手:建立可靠连接 + +``` +客户端 服务器 + | | + | -------- SYN(seq=x) ---------> | 第1次:你好,我想和你通信(SYN) + | | (x 是随机数,防止伪造) + | | + | <--- SYN-ACK(seq=y, ack=x+1) ---| 第2次:收到!我也想和你通信(SYN) + | | 我收到了你的 x,所以 ack=x+1 + | | + | -------- ACK(ack=y+1) --------> | 第3次:我收到了你的 y,所以 ack=y+1 + | | 连接建立成功! +``` + +::: tip 💡 为什么需要三次,不是两次? +想象打电话: + +- **A**:你好!(SYN) +- **B**:你好!(SYN-ACK) —- 此时 B 确认了 A 能收到,但 A 还不确定 B 能不能收到 +- **A**:我听到了!(ACK) —- 现在双方都知道对方能收能发 + +如果只有两次: + +- A 发 SYN +- B 回 SYN-ACK +- 连接建立...但 B 不知道 A 有没有收到 SYN-ACK!如果 A 没收到,会重复发 SYN,但 B 以为已经建立连接,会出现问题 + ::: + +--- + +## 5. 应用层:具体的业务 + +### 5.1 HTTP/HTTPS:网页的对话协议 + +**HTTP (HyperText Transfer Protocol)** 是浏览器和服务器之间的"对话规则"。 + +| 特性 | HTTP | HTTPS | +| ---------- | ------------------------ | ----------------------------- | +| **加密** | ❌ 否(明文,任何人都能看) | ✅ 是(TLS/SSL 加密) | +| **端口** | 80 | 443 | +| **安全性** | 低(密码、账号会被窃取) | 高(即使被拦截,看到的也是乱码) | +| **性能** | 略快(无加密开销) | 略慢(加密解密需要时间) | +| **SEO** | 不友好(搜索引擎会降权) | 友好(搜索引擎优先收录 HTTPS) | + +**HTTP 请求方法**: + +| 方法 | 描述 | 生活类比 | 示例 | +| ---------- | ---------------------- | ---------------------------- | ---------------------- | +| **GET** | 获取资源 | "我要看这个商品的详情" | 查看网页、加载图片 | +| **POST** | 提交数据 | "我要下单,这是我的收货信息" | 登录、注册、提交表单 | +| **PUT** | 更新资源(整体替换) | "我要完整更新这个商品的信息" | 修改用户资料(全部字段) | +| **PATCH** | 部分更新 | "我只想改商品的名称" | 修改用户资料(只改名字) | +| **DELETE** | 删除资源 | "我要删除这个订单" | 删除文章、删除评论 | +| **HEAD** | 只获取响应头(不要内容) | "这个文件还在吗?有多大?" | 检查资源是否存在 | + +**HTTP 状态码**(服务器给你的"回复"): + +``` +2xx 成功 +- 200 OK:请求成功,这是你要的内容 +- 201 Created:创建成功(比如注册新用户) + +3xx 重定向 +- 301 Moved Permanently:永久搬家了,请用新地址 +- 302 Found:暂时搬迁,请访问新地址 + +4xx 客户端错误(你发的问题) +- 400 Bad Request:请求格式错误,服务器看不懂 +- 401 Unauthorized:未授权,请先登录 +- 403 Forbidden:禁止访问,即使登录也不行 +- 404 Not Found:资源不存在(网址错了?) + +5xx 服务器错误(服务器的问题) +- 500 Internal Server Error:服务器内部出错了 +- 502 Bad Gateway:网关错误,服务器连不上后端 +- 503 Service Unavailable:服务暂时不可用(过载或维护) +``` + +### 5.2 DNS:互联网的地址簿 + +**DNS (Domain Name System)** 域名系统,把人类可读的域名转换成机器可读的 IP 地址。 + +::: tip 💡 为什么需要 DNS? +**没有 DNS 的世界**: + +- 你需要记住所有网站的 IP 地址 +- 访问百度:`https://110.242.68.66`(你能记住吗?) +- IP 地址会变(服务器迁移),你需要重新记住 + +**有 DNS 的世界**: + +- 记住域名:`baidu.com` +- DNS 帮你转换:`baidu.com` → `110.242.68.66` +- IP 变了?更新 DNS 记录就行,域名不用变 + ::: + +**DNS 查询过程**: + +``` +你(浏览器) + ↓ 问:baidu.com 的 IP 是多少? +本地 DNS 服务器(你的网络运营商,如电信/联通) + ↓ 不知道? 问: +根域名服务器(全球13组,管理所有顶级域) + ↓ 告诉:去问 .cn 的管理者 +顶级域名服务器(Verisign 管理 .cn) + ↓ 告诉:去问 baidu.com 的管理者 +权威 DNS 服务器(Baidu 自己的 DNS) + ↓ 告诉:baidu.com 的 IP 是 110.242.68.66 +返回 IP 地址给浏览器 +``` + +**DNS 记录类型**: + +| 类型 | 用途 | 示例 | +| --------- | ---------------- | ------------------------------------------------------ | +| **A** | 域名 → IPv4 地址 | `www.example.com → 93.184.216.34` | +| **AAAA** | 域名 → IPv6 地址 | `www.example.com → 2606:2800:220:1:248:1893:25c8:1946` | +| **CNAME** | 别名 | `www.baidu.com → a.baidu.com`(多个域名指向同一个 IP) | +| **MX** | 邮件服务器 | `@example.com → mail.example.com`(邮件发到哪里) | + +--- + +## 6. 总结:网络五层模型核心要点 + +| 层级 | 核心概念 | 关键技术 | 生活类比 | +| -------------- | ------------------- | -------------------- | ---------------------------------- | +| **应用层** | 应用程序之间的通信 | HTTP, FTP, SMTP, DNS | 具体业务(寄快递、发邮件、浏览网页) | +| **传输层** | 端到端的可靠传输 | TCP(可靠), UDP(快速) | 快递方式(挂号信 vs 平信) | +| **网络层** | 路由选择,寻址 | IP, 路由器, ICMP | GPS 导航,规划路线 | +| **数据链路层** | 点对点传输,MAC 寻址 | 以太网, 交换机, MAC | 车队管理,车辆之间通信 | +| **物理层** | 实际的物理传输 | 光纤, 网线, 无线电波 | 道路和运输工具 | + +**学习建议**: + +- ✅ **从应用层往下学**:你每天都在用 HTTP,DNS,从熟悉的开始 +- ✅ **多用工具**:ping, traceroute, Wireshark,观察实际网络 +- ✅ **理解协议细节**:阅读 RFC 文档(比如 RFC 791 定义 IP) +- ✅ **抓包分析**:用 Wireshark 观察 TCP 三次握手、HTTP 请求 +- ✅ **关注安全**:了解 DDoS、中间人攻击等常见威胁 + +掌握计算机网络,你就能理解互联网的运作原理,写出更高效的网络应用! + +--- + +## 附录:名词速查表 + +| 名词 | 英文 | 用人话解释 | +| --------------- | ----------------------------- | ------------------------------------------- | +| **OSI 模型** | Open Systems Interconnection | 七层网络模型(理论标准) | +| **TCP/IP 模型** | - | 实际使用的四层/五层模型 | +| **MAC 地址** | Media Access Control | 网卡的物理地址,全球唯一,像身份证 | +| **IP 地址** | Internet Protocol | 设备在互联网上的逻辑地址,像住址 | +| **子网掩码** | Subnet Mask | 区分 IP 地址的网络部分和主机部分 | +| **端口** | Port | 应用程序的"门牌号",区分同一台设备的不同服务 | +| **TCP** | Transmission Control Protocol | 可靠传输协议,三次握手,不丢包 | +| **UDP** | User Datagram Protocol | 快速传输协议,不保证可靠,可能丢包 | +| **DNS** | Domain Name System | 域名系统,把域名转成 IP 地址 | +| **HTTP** | HyperText Transfer Protocol | 超文本传输协议,网页通信规则 | +| **HTTPS** | HTTP Secure | 加密的 HTTP,更安全 | +| **路由器** | Router | 网络层设备,规划路线,连接不同网络 | +| **交换机** | Switch | 数据链路层设备,智能转发数据帧 | +| **TTL** | Time To Live | 生存时间,防止数据包无限循环 | +| **RTT** | Round Trip Time | 往返时间,数据从发送到接收确认的时间 | diff --git a/docs/zh-cn/appendix/1-computer-fundamentals/data-encoding-storage.md b/docs/zh-cn/appendix/1-computer-fundamentals/data-encoding-storage.md new file mode 100644 index 0000000..d13c289 --- /dev/null +++ b/docs/zh-cn/appendix/1-computer-fundamentals/data-encoding-storage.md @@ -0,0 +1,244 @@ +# 数据的编码、存储与传输 + +::: tip 🎯 核心问题 +**计算机如何表示和存储各种数据?** 文字、图片、视频、声音...这些在现实世界中形态各异的信息,是如何变成 0 和 1 的?又是如何存储和传输的?本章带你理解数据的编码、存储和传输原理。 +::: + +--- + +## 0. 全景图:数据的生命周期 + +想象你要寄一封信给朋友: + +1. **编码**:把想法变成文字(信息编码) +2. **存储**:写在纸上(数据存储) +3. **传输**:通过邮局寄出(数据传输) + +计算机处理数据也是类似的过程: + +| 阶段 | 做什么 | 核心问题 | 类比 | +|------|--------|---------|------| +| **编码** | 把信息变成 0 和 1 | 如何用二进制表示各种数据? | 把想法变成文字 | +| **存储** | 把数据保存起来 | 数据存在哪里?怎么组织? | 写在纸上 | +| **传输** | 把数据送到别处 | 如何可靠、高效地传输? | 邮局寄信 | + +::: tip 📊 逐行解读这张表 +**编码**:计算机只认识 0 和 1,所以所有数据都要"翻译"成二进制。文字用 ASCII 或 Unicode 编码,数字用二进制表示,图片用像素值,声音用采样值。 + +**存储**:编码后的数据需要保存起来。存储介质从快到慢有:寄存器 → 缓存 → 内存 → SSD → 硬盘 → 云存储。越快的存储越贵、容量越小。 + +**传输**:数据需要在不同设备间流动。传输方式有串行(一位一位传)和并行(多位同时传)。现代高速接口(USB、PCIe)多采用串行方式。 +::: + +--- + +## 1. 数据编码:用 0 和 1 表示一切 + +### 1.1 文本编码 + + + +::: tip 💡 字符编码的演变 +**ASCII(1963年)**: +- 用 7 位二进制表示 128 个字符 +- 包括英文字母、数字、常用符号 +- 问题:只能表示英语,无法表示中文等 + +**Unicode(1991年)**: +- 统一编码标准,覆盖世界上所有文字 +- 目前已收录超过 14 万个字符 +- 常用编码方式:UTF-8(变长编码,1-4 字节) + +**UTF-8 的巧妙设计**: +- ASCII 字符(0-127)只用 1 字节,完全兼容 +- 常用汉字用 3 字节 +- 根据"前导位"判断一个字符占几个字节 +::: + +**常见字符编码对比:** + +| 编码 | 字节数 | 支持字符 | 特点 | +|------|--------|---------|------| +| **ASCII** | 1 字节 | 128 个 | 仅英语,兼容性好 | +| **UTF-8** | 1-4 字节 | 所有文字 | 变长编码,主流标准 | +| **UTF-16** | 2-4 字节 | 所有文字 | 定长为主,Windows 常用 | +| **GBK** | 1-2 字节 | 中英文 | 中文专用,不推荐新项目使用 | + +### 1.2 数字编码 + +::: tip 💡 整数如何用二进制表示? +**无符号整数**:直接用二进制表示 +- 8 位可以表示 0-255 +- 32 位可以表示 0 到约 42 亿 + +**有符号整数**:用补码表示 +- 最高位是符号位(0 正 1 负) +- 正数:直接用二进制 +- 负数:正数的二进制取反加 1 + +**为什么用补码?** +- 加法减法统一处理 +- 0 的表示唯一 +- 硬件实现简单 +::: + +**浮点数表示(IEEE 754 标准):** + +| 部分 | 作用 | 位数(32位浮点) | +|------|------|-----------------| +| **符号位** | 正负 | 1 位 | +| **指数位** | 决定大小范围 | 8 位 | +| **尾数位** | 决定精度 | 23 位 | + +### 1.3 多媒体编码 + +**图像编码**: +- **位图**:每个像素用 RGB 值表示(红绿蓝各 8 位) +- **压缩**:JPEG(有损)、PNG(无损) +- **矢量图**:用数学公式描述形状(SVG) + +**音频编码**: +- **采样**:把连续声波变成离散点 +- **量化**:把采样值变成数字 +- **压缩**:MP3(有损)、FLAC(无损) + +**视频编码**: +- 视频是一帧帧图像 +- 关键技术:帧间压缩(只记录变化部分) +- 常见格式:H.264、H.265、VP9 + +--- + +## 2. 数据存储:速度与容量的权衡 + +### 2.1 存储层次结构 + + + +### 2.2 存储器类型 + +| 类型 | 原理 | 特点 | 应用 | +|------|------|------|------| +| **SRAM** | 触发器 | 极快,但昂贵 | CPU 缓存 | +| **DRAM** | 电容充放电 | 较快,需刷新 | 内存 | +| **Flash** | 浮栅晶体管 | 断电不丢失,有写入寿命 | SSD、U 盘 | +| **HDD** | 磁盘磁性记录 | 容量大,有机械延迟 | 机械硬盘 | + +### 2.3 存储的关键指标 + +::: tip 💡 如何评估存储性能? +**访问时间**:从发出请求到获得数据的时间 +- 内存:约 100 纳秒 +- SSD:约 100 微秒 +- HDD:约 10 毫秒 + +**吞吐量**:单位时间能传输的数据量 +- 内存:几十 GB/s +- SSD:几 GB/s +- HDD:100-200 MB/s + +**IOPS**:每秒能进行的读写操作次数 +- SSD:几万到几十万 +- HDD:几百 +::: + +--- + +## 3. 数据传输:从串行到并行 + +### 3.1 传输方式 + + + +### 3.2 常见接口标准 + +| 接口 | 类型 | 速度 | 应用 | +|------|------|------|------| +| **USB 3.0** | 串行 | 5 Gbps | 外设连接 | +| **USB 4** | 串行 | 40 Gbps | 高速外设 | +| **SATA III** | 串行 | 6 Gbps | 硬盘接口 | +| **PCIe 4.0 x16** | 串行(多通道) | 32 GB/s | 显卡、SSD | +| **以太网** | 串行 | 1-100 Gbps | 网络传输 | + +### 3.3 传输的可靠性 + +::: tip 💡 如何保证传输不出错? +**校验机制**: +- **奇偶校验**:简单的错误检测 +- **CRC 校验**:更强的错误检测能力 +- **校验和**:快速检测数据完整性 + +**纠错机制**: +- **重传**:发现错误就重新发送 +- **前向纠错**:发送冗余信息,接收方能自动纠正 + +**流量控制**: +- 防止发送方发太快,接收方来不及处理 +- 类似"确认收到再发下一个" +::: + +--- + +## 4. 编码、存储、传输的协作 + +让我们看一个完整的例子:**保存一张照片到云端** + +``` +1. 编码阶段 + - 相机传感器捕捉光线 → 模拟信号 + - ADC 转换 → 数字信号(RAW 格式) + - JPEG 编码 → 压缩后的二进制数据 + +2. 存储阶段 + - 写入手机内存(RAM)→ 临时存储 + - 写入手机闪存(Flash)→ 持久存储 + +3. 传输阶段 + - 读取闪存数据 → 内存 + - 通过 Wi-Fi/4G 发送 → 网络传输 + - 云端接收 → 写入云端存储 +``` + +::: tip 💡 理解这个流程 +每一步都涉及编码、存储、传输: + +1. **编码**:把图像变成二进制数据 +2. **存储**:在本地保存 +3. **传输**:通过网络发送到云端 + +这三个环节紧密配合,才能完成"保存照片到云端"这个看似简单的操作。 +::: + +--- + +## 5. 总结:数据的三重奏 + +让我们用一个比喻总结编码、存储、传输: + +| 概念 | 比喻 | 核心任务 | +|------|------|---------| +| **编码** | 翻译 | 把信息变成 0 和 1 | +| **存储** | 仓库 | 把数据保存起来 | +| **传输** | 快递 | 把数据送到目的地 | + +::: tip 💡 核心启示 +**数据处理的本质是"转换、保存、移动"**。 + +- 编码解决"如何表示"的问题 +- 存储解决"如何保存"的问题 +- 传输解决"如何传递"的问题 + +理解了这三点,你就会明白: +- 为什么不同文件格式要选择不同的编码方式 +- 为什么需要不同层次的存储介质 +- 为什么传输速度和可靠性需要平衡 +::: + +--- + +## 延伸阅读 + +- **字符编码详解**:深入学习 ASCII、Unicode、UTF-8 的设计原理 +- **存储技术发展**:了解从磁带到 SSD 的技术演进 +- **网络传输协议**:学习 TCP/IP 如何保证可靠传输 +- **数据压缩算法**:了解 ZIP、JPEG、MP3 等压缩原理 diff --git a/docs/zh-cn/appendix/1-computer-fundamentals/data-structures.md b/docs/zh-cn/appendix/1-computer-fundamentals/data-structures.md new file mode 100644 index 0000000..608d03b --- /dev/null +++ b/docs/zh-cn/appendix/1-computer-fundamentals/data-structures.md @@ -0,0 +1,214 @@ +# 数据结构 + +::: tip 🎯 核心问题 +**如何高效地组织和存储数据?** 你可能遇到过这样的困惑:为什么有些程序处理几万条数据很快,有些处理几百条就卡住了?答案往往在于数据结构的选择。本章带你理解常见数据结构的特点和适用场景。 +::: + +--- + +## 0. 全景图:数据结构是什么? + +想象你要整理一堆书: + +- **堆在地上**:找书要一本本翻(链表) +- **按编号放书架**:直接去对应位置拿(数组) +- **按类别分柜子**:先找柜子再找书(哈希表) +- **按书名排序**:二分查找,每次排除一半(树) + +不同的整理方式,找书的效率天差地别。**数据结构就是数据的"整理方式"**。 + + + +**常见数据结构分类:** + +| 类型 | 特点 | 典型代表 | 适用场景 | +|------|------|---------|---------| +| **线性结构** | 数据排成一排 | 数组、链表、栈、队列 | 顺序处理、历史记录 | +| **哈希结构** | 键值对映射 | 哈希表 | 快速查找、缓存 | +| **树形结构** | 层次关系 | 二叉树、B树 | 排序、搜索、文件系统 | +| **图结构** | 网状关系 | 有向图、无向图 | 社交网络、路径规划 | + +::: tip 📊 逐行解读这张表 +**线性结构**:最简单的数据组织方式,数据一个接一个排列。数组适合随机访问,链表适合频繁插入删除。 + +**哈希结构**:用"键"直接找到"值",查找速度最快。但需要处理"冲突"问题(两个键映射到同一位置)。 + +**树形结构**:有层次关系的数据。二叉搜索树适合排序和搜索,B树适合磁盘存储(数据库索引)。 + +**图结构**:最复杂的结构,表示任意的关系网络。社交网络、地图导航都用图来建模。 +::: + +--- + +## 1. 线性结构:最基础的组织方式 + +### 1.1 数组:连续存储 + +::: tip 💡 数组的特点 +**数组**是一块连续的内存空间,每个元素大小相同。 + +**优点**: +- 随机访问快:`arr[100]` 直接计算地址,O(1) +- 缓存友好:连续存储,CPU 缓存命中率高 + +**缺点**: +- 插入删除慢:需要移动后面所有元素,O(n) +- 大小固定:需要预先分配空间 + +**生活类比**:一排编号的储物柜,每个柜子大小相同。找第 10 号柜子直接去,但要在中间插入一个柜子,后面的都要往后挪。 +::: + +### 1.2 链表:节点相连 + +::: tip 💡 链表的特点 +**链表**由一系列节点组成,每个节点包含数据和指向下一个节点的指针。 + +**优点**: +- 插入删除快:只需修改指针,O(1) +- 大小灵活:可以动态增长 + +**缺点**: +- 访问慢:要从头开始遍历,O(n) +- 额外空间:每个节点需要存储指针 + +**生活类比**:寻宝游戏,每个线索指向下一个地点。要找第 10 个线索,必须从第 1 个开始一步步找。 +::: + +### 1.3 栈和队列:受限的线性结构 + +| 结构 | 规则 | 操作 | 类比 | 应用 | +|------|------|------|------|------| +| **栈** | 后进先出 (LIFO) | push/pop | 一摞盘子 | 函数调用、撤销操作 | +| **队列** | 先进先出 (FIFO) | enqueue/dequeue | 排队买票 | 任务调度、消息队列 | + +::: tip 💡 为什么要有"受限"的结构? +栈和队列看起来比数组、链表功能少,但正是这种"限制"让它们有明确的用途: + +- **栈**:函数调用时,最后调用的函数最先返回 +- **队列**:任务调度时,先来的任务先处理 + +限制带来简洁,简洁带来高效。 +::: + +--- + +## 2. 哈希表:最快的查找 + +### 2.1 哈希表原理 + +::: tip 💡 哈希表如何工作? +**哈希表**通过"哈希函数"把键映射到数组索引。 + +**工作流程**: +1. 输入键(如 "apple") +2. 哈希函数计算:`hash("apple") = 3` +3. 直接去数组索引 3 的位置找 + +**冲突处理**: +- 两个不同的键可能映射到同一索引 +- 解决方法:链地址法(同一位置用链表存储多个值) + +**生活类比**:图书馆按书名首字母分柜子。"Apple" 开头的书都放 A 柜,"Banana" 开头的放 B 柜。找书时先确定柜子,再在柜子里找。 +::: + +### 2.2 哈希表的时间复杂度 + +| 操作 | 平均情况 | 最坏情况 | +|------|---------|---------| +| **查找** | O(1) | O(n) | +| **插入** | O(1) | O(n) | +| **删除** | O(1) | O(n) | + +::: warning ⚠️ 什么时候会退化? +当所有键都映射到同一个索引时,哈希表退化为链表,所有操作变成 O(n)。 + +**避免方法**: +- 选择好的哈希函数 +- 动态扩容(负载因子超过阈值时扩容) +::: + +--- + +## 3. 树:层次结构 + +### 3.1 二叉搜索树 + +::: tip 💡 二叉搜索树的规则 +**二叉搜索树**是一种特殊的二叉树: +- 左子树的所有值 < 根节点 +- 右子树的所有值 > 根节点 + +**查找过程**: +1. 从根节点开始 +2. 如果目标值 < 当前值,往左走 +3. 如果目标值 > 当前值,往右走 +4. 每次比较排除一半节点 + +**时间复杂度**:O(log n),但最坏情况(变成链表)是 O(n) +::: + +### 3.2 平衡树 + +为了防止二叉搜索树退化,引入了**平衡树**: + +| 类型 | 平衡方式 | 特点 | +|------|---------|------| +| **AVL 树** | 严格平衡(高度差 ≤ 1) | 查找最快,插入删除稍慢 | +| **红黑树** | 近似平衡 | 综合性能好,应用最广 | +| **B 树** | 多路平衡 | 适合磁盘存储,数据库索引 | + +--- + +## 4. 如何选择数据结构? + +| 需求 | 推荐结构 | 原因 | +|------|---------|------| +| **快速随机访问** | 数组 | O(1) 索引访问 | +| **频繁插入删除** | 链表 | O(1) 插入删除 | +| **快速查找** | 哈希表 | O(1) 平均查找 | +| **有序数据** | 平衡树 | O(log n) 查找,保持有序 | +| **最近使用** | 栈 | LIFO 特性 | +| **任务排队** | 队列 | FIFO 特性 | + +::: tip 💡 选择数据结构的心法 +**没有最好的数据结构,只有最合适的数据结构。** + +选择时要考虑: +1. **主要操作是什么?** 查找?插入?删除? +2. **数据量多大?** 小数据量差别不大,大数据量要慎重 +3. **数据有序吗?** 有序数据可以用二分查找 +4. **内存限制?** 某些结构需要额外空间 +::: + +--- + +## 5. 总结:数据结构是程序的基础 + +让我们用一个比喻总结各种数据结构: + +| 结构 | 比喻 | 核心特点 | +|------|------|---------| +| **数组** | 编号储物柜 | 访问快,插入慢 | +| **链表** | 寻宝线索 | 插入快,访问慢 | +| **栈** | 一摞盘子 | 后进先出 | +| **队列** | 排队队伍 | 先进先出 | +| **哈希表** | 分类柜子 | 查找最快 | +| **树** | 家族族谱 | 层次结构 | + +::: tip 💡 核心启示 +**数据结构决定了程序的效率上限。** + +- 选对数据结构,问题迎刃而解 +- 选错数据结构,再好的算法也无济于事 + +理解数据结构,就是理解"如何高效地组织数据"。这是每个程序员的基本功。 +::: + +--- + +## 延伸阅读 + +- **数据结构实现**:自己动手实现各种数据结构,加深理解 +- **高级数据结构**:学习跳表、布隆过滤器、并查集等 +- **数据库索引**:了解 B+ 树在数据库中的应用 +- **缓存设计**:学习 LRU 缓存如何结合哈希表和链表 diff --git a/docs/zh-cn/appendix/1-computer-fundamentals/operating-systems.md b/docs/zh-cn/appendix/1-computer-fundamentals/operating-systems.md new file mode 100644 index 0000000..ca60a6c --- /dev/null +++ b/docs/zh-cn/appendix/1-computer-fundamentals/operating-systems.md @@ -0,0 +1,255 @@ +# 操作系统(进程 / 内存 / 文件系统) + +::: tip 🎯 核心问题 +**操作系统是做什么的?** 你可能每天都在用 Windows、macOS 或 Linux,但你知道它到底在忙什么吗?为什么需要它?没有它电脑还能用吗?本章带你理解操作系统的三大核心职责:管理进程、管理内存、管理文件。 +::: + +--- + +## 0. 全景图:操作系统的角色 + +想象你开了一家餐厅。你需要: +- **安排员工工作**:谁做菜、谁端盘子、谁收银(进程管理) +- **管理厨房空间**:冰箱放什么、操作台怎么分配(内存管理) +- **整理仓库物资**:食材怎么存放、怎么找(文件系统) + +操作系统就是电脑的"餐厅经理",它负责协调所有资源,让程序能顺利运行。 + +**操作系统的三大核心职责:** + +| 职责 | 管理对象 | 核心问题 | 类比 | +|------|---------|---------|------| +| **进程管理** | CPU 时间 | 谁先用 CPU?用多久? | 员工排班 | +| **内存管理** | 内存空间 | 程序放哪里?怎么不冲突? | 厨房空间分配 | +| **文件系统** | 磁盘数据 | 数据怎么存?怎么找? | 仓库物资管理 | + +::: tip 📊 逐行解读这张表 +**进程管理**:CPU 是最宝贵的资源,操作系统要决定哪个程序先用、用多久。就像餐厅经理安排员工轮班,不能让所有人同时挤在厨房里。 + +**内存管理**:内存是程序的"工作台",操作系统要给每个程序分配空间,还要保证它们互不干扰。就像厨房空间有限,要合理分配给不同的厨师。 + +**文件系统**:磁盘是"仓库",操作系统要把数据有序地存进去,需要时能快速找到。就像仓库管理员整理货架,按类别、编号存放。 +::: + +--- + +## 1. 进程管理:程序的"分身术" + +### 1.1 什么是进程? + + + +::: tip 💡 程序 vs 进程 +这是初学者最容易混淆的概念: + +| 概念 | 定义 | 类比 | 特点 | +|------|------|------|------| +| **程序** | 静态的代码文件 | 菜谱 | 存在磁盘上,不会动 | +| **进程** | 程序的运行实例 | 正在按菜谱做菜 | 在内存中运行,会变化 | + +**关键区别**: +- 一个程序可以启动多个进程(比如打开多个浏览器窗口) +- 每个进程有独立的内存空间,互不干扰 +- 进程有生命周期:创建、运行、等待、终止 +::: + +### 1.2 进程的状态 + +进程在运行过程中会在不同状态之间切换: + +| 状态 | 含义 | 什么时候进入 | 类比 | +|------|------|-------------|------| +| **就绪 (Ready)** | 准备好运行,等 CPU | 进程刚创建,或从等待恢复 | 员工在休息室等排班 | +| **运行 (Running)** | 正在 CPU 上执行 | 被调度器选中 | 员工正在工作 | +| **等待 (Waiting)** | 等待 I/O 或其他资源 | 需要读磁盘、等网络 | 员工在等食材送达 | +| **终止 (Terminated)** | 运行结束 | 程序退出或出错 | 员工下班 | + +### 1.3 进程调度:谁先用 CPU? + +::: tip 💡 为什么需要调度? +CPU 核心数有限,但进程可能有几十上百个。操作系统需要决定: +- 哪个进程先运行? +- 运行多久? +- 什么时候切换? + +这就是**进程调度**要解决的问题。 +::: + +**常见调度算法:** + +| 算法 | 思路 | 优点 | 缺点 | +|------|------|------|------| +| **先来先服务 (FCFS)** | 谁先到谁先运行 | 简单公平 | 短任务可能等很久 | +| **短作业优先 (SJF)** | 短任务优先 | 平均等待时间最短 | 需要预知任务长度 | +| **时间片轮转 (RR)** | 每人运行一小段时间 | 公平,响应快 | 切换开销大 | +| **优先级调度** | 重要任务优先 | 重要任务响应快 | 可能导致低优先级任务饿死 | + +--- + +## 2. 内存管理:程序的"工作台" + +### 2.1 为什么需要内存管理? + + + +::: tip 💡 如果没有内存管理会怎样? +想象一个没有管理的厨房: + +- **冲突**:两个厨师同时用同一个灶台,菜都糊了 +- **浪费**:有人占了整个厨房,其他人没地方做饭 +- **安全问题**:有人偷吃了别人的食材 + +操作系统通过**内存管理**解决这些问题: +- 给每个进程分配独立的内存空间 +- 防止进程互相干扰(内存保护) +- 高效利用有限的内存资源 +::: + +### 2.2 虚拟内存:让每个进程都"以为"自己独占内存 + +::: tip 💡 什么是虚拟内存? +**虚拟内存**是操作系统的一个"魔术": + +- 每个进程都以为自己有 4GB(或更多)的内存空间 +- 实际上物理内存可能只有 8GB、16GB +- 操作系统通过"映射"把虚拟地址转换成物理地址 + +**生活类比**:想象一个酒店: +- 每个客人都以为自己独占整个酒店(虚拟空间) +- 实际上酒店只有 100 间房(物理内存) +- 前台(操作系统)负责分配房间、记录谁住哪里 +::: + +**虚拟内存的好处:** + +| 好处 | 说明 | 为什么重要 | +|------|------|-----------| +| **隔离保护** | 进程间内存互不干扰 | 一个崩溃不影响其他 | +| **内存扩展** | 用磁盘当内存用 | 可以运行比物理内存大的程序 | +| **简化编程** | 不用关心物理地址 | 程序员写代码更简单 | + +### 2.3 内存分配策略 + +当进程需要内存时,操作系统如何分配? + +| 策略 | 思路 | 特点 | +|------|------|------| +| **首次适应** | 找到第一个够大的空闲块 | 速度快 | +| **最佳适应** | 找最小的够大的空闲块 | 内存利用率高 | +| **最坏适应** | 找最大的空闲块 | 减少小碎片 | + +--- + +## 3. 文件系统:数据的"档案柜" + +### 3.1 什么是文件系统? + + + +::: tip 💡 文件系统是什么? +**文件系统**是操作系统管理磁盘数据的方式。 + +**生活类比**:想象一个图书馆: +- 书架 = 磁盘 +- 书 = 文件 +- 目录卡片 = inode +- 分类编号 = 路径 + +没有文件系统,磁盘就是一堆杂乱的数据。有了文件系统,我们可以: +- 用"路径"找到文件(如 `/home/user/document.txt`) +- 创建、删除、修改文件 +- 控制谁能访问哪些文件 +::: + +### 3.2 inode:文件的"身份证" + +::: tip 💡 inode 是什么? +每个文件都有一个 **inode**(索引节点),记录了文件的元数据: + +| 信息 | 说明 | +|------|------| +| inode 编号 | 文件的唯一标识 | +| 文件大小 | 多少字节 | +| 权限 | 谁能读写 | +| 时间戳 | 创建、修改、访问时间 | +| 数据块位置 | 文件内容存在哪些磁盘块 | + +**关键理解**: +- 文件名不在 inode 里!文件名只是目录中的一个条目 +- 一个文件可以有多个名字(硬链接) +- 删除文件只是删除目录项,inode 可能还在 +::: + +### 3.3 常见文件系统 + +| 文件系统 | 操作系统 | 特点 | +|---------|---------|------| +| **NTFS** | Windows | 支持大文件、权限控制 | +| **APFS** | macOS | 加密、快照、高效 | +| **ext4** | Linux | 稳定、高效、广泛使用 | +| **FAT32** | 通用 | 兼容性好,但单文件最大 4GB | +| **exFAT** | 通用 | 支持大文件,适合 U 盘 | + +--- + +## 4. 进程、内存、文件系统的协作 + +这三个子系统是如何配合工作的?让我们看一个完整的例子: + +**场景:打开一个文档文件** + +``` +1. 用户双击文件 + ↓ +2. 文件系统:根据路径找到 inode,读取文件内容 + ↓ +3. 进程管理:创建新进程(文档编辑器),分配 PID + ↓ +4. 内存管理:为新进程分配内存,加载程序代码和数据 + ↓ +5. 进程运行:编辑器进程读取文件内容,显示在屏幕上 +``` + +::: tip 💡 理解这个流程 +每一步都涉及操作系统的核心功能: + +1. **文件系统**:负责"找到文件" +2. **进程管理**:负责"启动程序" +3. **内存管理**:负责"给程序分配空间" + +这三者紧密协作,才能完成一个看似简单的"打开文件"操作。 +::: + +--- + +## 5. 总结:操作系统是"大管家" + +让我们用一个比喻总结操作系统的三大职责: + +| 职责 | 比喻 | 核心任务 | +|------|------|---------| +| **进程管理** | 餐厅排班员 | 安排谁先工作、工作多久 | +| **内存管理** | 厨房管理员 | 分配工作台、防止冲突 | +| **文件系统** | 仓库管理员 | 整理物资、快速查找 | + +::: tip 💡 核心启示 +**操作系统的本质是"资源管理"**。 + +- CPU 时间是资源 → 进程管理 +- 内存空间是资源 → 内存管理 +- 磁盘空间是资源 → 文件系统 + +理解了这一点,你就会明白: +- 为什么电脑会变慢(进程太多、内存不足) +- 为什么需要重启(清理资源、释放内存) +- 为什么文件要整理(提高查找效率) +::: + +--- + +## 延伸阅读 + +- **操作系统原理**:深入学习进程调度、内存分页、文件系统实现 +- **Linux 系统编程**:学习如何与操作系统交互(系统调用) +- **并发编程**:学习多进程、多线程编程 +- **系统监控**:学习使用 top、htop、vmstat 等工具监控系统状态 diff --git a/docs/zh-cn/appendix/1-computer-fundamentals/programming-languages.md b/docs/zh-cn/appendix/1-computer-fundamentals/programming-languages.md new file mode 100644 index 0000000..72530e5 --- /dev/null +++ b/docs/zh-cn/appendix/1-computer-fundamentals/programming-languages.md @@ -0,0 +1,398 @@ +# 编程语言图谱 + +::: tip 🎯 核心问题 +**为什么有这么多编程语言?它们之间有什么关系?** 从机器语言到现代高级语言,每种语言都有其设计哲学和适用场景。本章带你理解编程语言的演化历程和核心概念。 +::: + +--- + +## 0. 想象你要和外国人交流: + +- **直接用肢体语言**:最原始,但效率极低(机器语言) +- **学习对方的语言**:需要翻译,但表达丰富(高级语言) +- **使用世界语**:设计完美,但没人用(某些学术语言) +- **使用翻译软件**:自动转换,但可能不准确(编译器/解释器) + +**编程语言就是人类与计算机沟通的桥梁**,不同的语言有不同的设计哲学。 + + + +--- + +## 1. 编程语言的演化 + +### 1.1 第一代:机器语言(1940s) + +::: tip 💡 机器语言是什么? +直接用 0 和 1 编写程序,计算机可以直接执行。 + +**示例**:让计算机计算 1 + 2 +``` +10110000 00000001 ; 将 1 放入寄存器 +10110001 00000010 ; 将 2 放入另一个寄存器 +10100010 ; 执行加法 +``` + +**问题**: +- 人类难以理解和记忆 +- 容易出错,一个 0 写成 1 就全错了 +- 不同 CPU 有不同的机器语言 +::: + +### 1.2 第二代:汇编语言(1950s) + +用**助记符**代替 0 和 1: + +```asm +MOV AX, 1 ; 将 1 放入 AX 寄存器 +MOV BX, 2 ; 将 2 放入 BX 寄存器 +ADD AX, BX ; 将 BX 加到 AX +``` + +::: tip 💡 汇编语言 vs 机器语言 +| 特性 | 机器语言 | 汇编语言 | +|------|---------|---------| +| **可读性** | 极差 | 较好 | +| **执行效率** | 最高 | 最高(汇编器直接转换) | +| **移植性** | 无 | 无(依赖 CPU 架构) | +| **使用场景** | 几乎不用 | 嵌入式、操作系统内核 | +::: + +### 1.3 第三代:高级语言(1950s - 至今) + +**用接近自然语言的方式编程**: + +```c +int sum = 1 + 2; // C 语言 +``` + +**里程碑语言**: + +| 年代 | 语言 | 意义 | +|------|------|------| +| **1957** | Fortran | 第一个高级语言,科学计算 | +| **1958** | Lisp | 函数式编程鼻祖 | +| **1959** | COBOL | 商业数据处理 | +| **1972** | C | 系统编程,影响深远 | +| **1983** | C++ | 面向对象 + C 的效率 | +| **1991** | Python | 简洁优雅,AI 时代主角 | +| **1995** | Java | 跨平台,企业应用 | +| **1995** | JavaScript | Web 开发,无处不在 | +| **2009** | Go | 并发友好,云原生 | +| **2010** | Rust | 内存安全,系统编程新选择 | + +### 1.4 第四代:领域特定语言(DSL) + +为特定领域设计的语言: + +| 语言 | 领域 | 示例 | +|------|------|------| +| **SQL** | 数据库查询 | `SELECT * FROM users` | +| **HTML** | 网页结构 | `
Hello
` | +| **CSS** | 样式定义 | `color: red;` | +| **Regex** | 文本匹配 | `\d{3}-\d{4}` | +| **MATLAB** | 数学计算 | `A = [1 2; 3 4]` | + +--- + +## 2. 编程范式:思考问题的方式 + +::: tip 💡 什么是编程范式? +编程范式是**编程的思维方式**,决定了你如何组织代码和解决问题。 + +就像写作有不同的文体(诗歌、小说、论文),编程也有不同的"文体"。 +::: + +### 2.1 命令式编程(Imperative) + +**核心思想**:告诉计算机"怎么做" + +```c +// 计算数组总和 +int sum = 0; +for (int i = 0; i < n; i++) { + sum += arr[i]; +} +``` + +**特点**: +- 关注**过程**和**步骤** +- 通过**语句**改变程序状态 +- 最接近计算机实际执行方式 + +**代表语言**:C, Fortran, BASIC + +### 2.2 面向对象编程(OOP) + +**核心思想**:把数据和操作封装在"对象"中 + +```python +class Dog: + def __init__(self, name): + self.name = name + + def bark(self): + print(f"{self.name} says woof!") + +dog = Dog("Buddy") +dog.bark() # Buddy says woof! +``` + +**四大特性**: + +| 特性 | 含义 | 生活类比 | +|------|------|---------| +| **封装** | 隐藏内部细节 | 汽车方向盘,不需要知道引擎原理 | +| **继承** | 子类继承父类 | 儿子继承父亲的基因 | +| **多态** | 同一接口不同实现 | 不同动物发出不同叫声 | +| **抽象** | 提取共同特征 | "动物"是对猫、狗的抽象 | + +**代表语言**:Java, C++, Python, Ruby + +### 2.3 函数式编程(Functional) + +**核心思想**:把计算视为函数求值,避免状态变化 + +```haskell +-- 计算数组总和 +sum arr = foldl (+) 0 arr + +-- 或者更简洁 +sum = foldl (+) 0 +``` + +**核心原则**: + +| 原则 | 含义 | 好处 | +|------|------|------| +| **纯函数** | 相同输入永远产生相同输出 | 易测试、易推理 | +| **不可变数据** | 数据一旦创建就不变 | 无副作用、线程安全 | +| **高阶函数** | 函数可以作为参数和返回值 | 代码复用、灵活组合 | +| **无副作用** | 函数不修改外部状态 | 可预测、易调试 | + +**代表语言**:Haskell, Lisp, Erlang, F# + +### 2.4 声明式编程(Declarative) + +**核心思想**:告诉计算机"做什么",而不是"怎么做" + +```sql +-- 查询所有活跃用户 +SELECT name, email +FROM users +WHERE active = true +ORDER BY created_at DESC +``` + +**对比命令式**: + +| 命令式 | 声明式 | +|--------|--------| +| "从第一行开始遍历..." | "给我所有活跃用户" | +| "检查每个用户是否活跃..." | "按创建时间排序" | +| "如果活跃就加入结果..." | 数据库自己决定怎么执行 | +| "最后排序返回..." | | + +**代表语言**:SQL, Prolog, HTML + +--- + +## 3. 类型系统:数据的分类规则 + +::: tip 💡 什么是类型系统? +类型系统是编程语言的**交通规则**,规定数据如何分类和操作。 + +就像现实世界: +- **整数** = 整数类型(1, 2, 3...) +- **文字** = 字符串类型("hello") +- **是/否** = 布尔类型(true/false) +::: + +### 3.1 静态类型 vs 动态类型 + +| 特性 | 静态类型 | 动态类型 | +|------|---------|---------| +| **类型检查时机** | 编译时 | 运行时 | +| **代码示例** | `int x = 1;` | `x = 1` | +| **错误发现** | 编译期就发现 | 运行时才发现 | +| **灵活性** | 较低 | 较高 | +| **性能** | 较高(编译优化) | 较低(运行时检查) | +| **代表语言** | Java, C++, Rust, TypeScript | Python, JavaScript, Ruby | + +**静态类型示例(Java)**: + +```java +String name = "Alice"; +name = 123; // 编译错误!类型不匹配 +``` + +**动态类型示例(Python)**: + +```python +name = "Alice" +name = 123 # 没问题,运行时类型改变 +``` + +### 3.2 强类型 vs 弱类型 + +| 特性 | 强类型 | 弱类型 | +|------|--------|--------| +| **类型转换** | 不允许隐式转换 | 允许隐式转换 | +| **类型安全** | 高 | 低 | +| **代码示例** | `"1" + 1` 报错 | `"1" + 1 = "11"` | +| **代表语言** | Python, Java, Rust | JavaScript, PHP, C | + +**弱类型示例(JavaScript)**: + +```javascript +console.log("1" + 1) // "11" (字符串拼接) +console.log("1" - 1) // 0 (自动转数字) +console.log([] + []) // "" (空字符串) +console.log([] + {}) // "[object Object]" +``` + +**强类型示例(Python)**: + +```python +"1" + 1 # TypeError: can only concatenate str to str +``` + +### 3.3 类型推断 + +现代语言可以**自动推断**变量类型: + +```typescript +// TypeScript +let x = 1; // 推断为 number +let y = "hello"; // 推断为 string + +// Rust +let x = 1; // 推断为 i32 +let y = "hello"; // 推断为 &str +``` + +--- + +## 4. 编译型 vs 解释型 + +::: tip 💡 程序如何运行? +编程语言写的代码需要转换成机器能理解的指令,有两种主要方式: +::: + +### 4.1 编译型语言 + +**流程**:源代码 → 编译器 → 机器码 → 执行 + +``` +源代码 (main.c) + ↓ +编译器 (gcc) + ↓ +可执行文件 (main.exe) + ↓ +CPU 直接执行 +``` + +**特点**: + +| 优点 | 缺点 | +|------|------| +| 执行速度快 | 编译时间长 | +| 编译时发现错误 | 跨平台需要重新编译 | +| 不需要运行时环境 | 调试较困难 | + +**代表语言**:C, C++, Rust, Go + +### 4.2 解释型语言 + +**流程**:源代码 → 解释器 → 逐行执行 + +``` +源代码 (main.py) + ↓ +解释器 (python) + ↓ +逐行解释执行 +``` + +**特点**: + +| 优点 | 缺点 | +|------|------| +| 跨平台 | 执行速度慢 | +| 开发调试快 | 运行时才能发现错误 | +| 代码即运行 | 需要解释器环境 | + +**代表语言**:Python, JavaScript, Ruby, PHP + +### 4.3 混合型语言(JIT) + +**即时编译(Just-In-Time)**:先解释执行,热点代码编译成机器码 + +``` +源代码 + ↓ +字节码(中间代码) + ↓ +解释执行 + JIT 编译热点代码 + ↓ +执行 +``` + +**代表语言**:Java, JavaScript (V8), Python (PyPy) + +--- + +## 5. 如何选择编程语言? + +::: tip 💡 没有最好的语言,只有最适合的语言 +选择语言要考虑: +1. **问题领域**:Web 开发?系统编程?数据分析? +2. **团队熟悉度**:团队擅长什么? +3. **生态系统**:有没有现成的库? +4. **性能需求**:需要多高的性能? +5. **开发效率**:需要多快开发完成? +::: + +### 5.1 按应用场景选择 + +| 场景 | 推荐语言 | 原因 | +|------|---------|------| +| **Web 前端** | JavaScript, TypeScript | 浏览器原生支持 | +| **Web 后端** | Java, Go, Python, Node.js | 生态成熟,框架丰富 | +| **移动开发** | Swift (iOS), Kotlin (Android) | 官方推荐 | +| **数据分析** | Python, R | 库丰富,社区活跃 | +| **人工智能** | Python | TensorFlow, PyTorch | +| **系统编程** | C, C++, Rust | 性能高,控制精细 | +| **游戏开发** | C++, C#, Lua | 引擎支持 | +| **嵌入式** | C, Rust | 资源受限环境 | +| **云原生** | Go, Rust | 并发友好,部署简单 | + +### 5.2 学习路线建议 + +**初学者**: +1. Python(语法简单,应用广泛) +2. JavaScript(Web 开发必备) +3. 选择一门静态类型语言(Java 或 TypeScript) + +**进阶**: +1. 学习 C 理解底层 +2. 学习函数式编程思想(Haskell 或 F#) +3. 学习 Rust 理解内存安全 + +--- + +## 6. 总结 + +::: tip 📚 核心要点 +1. **编程语言演化**:从机器语言到高级语言,越来越接近人类思维 +2. **编程范式**:命令式、面向对象、函数式、声明式,各有优劣 +3. **类型系统**:静态/动态、强/弱类型,影响代码安全和灵活性 +4. **运行方式**:编译型快但需编译,解释型慢但灵活 +5. **选择语言**:没有银弹,根据场景选择合适的工具 +::: + +**下一步学习**: +- [类型系统与编译原理入门](./type-systems-compilers) - 深入理解类型系统和编译过程 +- [数据结构](./data-structures) - 理解数据的组织方式 +- [算法思维入门](./algorithm-thinking) - 学习解决问题的方法 diff --git a/docs/zh-cn/appendix/1-computer-fundamentals/transistor-to-cpu.md b/docs/zh-cn/appendix/1-computer-fundamentals/transistor-to-cpu.md new file mode 100644 index 0000000..681be78 --- /dev/null +++ b/docs/zh-cn/appendix/1-computer-fundamentals/transistor-to-cpu.md @@ -0,0 +1,259 @@ +# 从晶体管到 CPU + +::: tip 🎯 核心问题 +**计算机是怎么"思考"的?** 你可能知道 CPU 是电脑的"大脑",但这个大脑到底是怎么工作的?它怎么从一堆金属和塑料变成能执行程序、处理数据的智能设备?本章带你从最底层的晶体管开始,一步步理解 CPU 的构造原理。 +::: + +--- + +## 0. 全景图:从沙子到智能 + + + +现代计算机的"思考"能力,归根结底来自于一个简单的东西:**开关**。 + +想象你有一个开关,可以控制灯的亮灭。现在,如果你有几十亿个这样的开关,并且能用它们组合出各种复杂的逻辑,会发生什么?这就是计算机的奥秘。 + +**从沙子到智能的层次结构:** + +| 层级 | 名称 | 数量级 | 作用 | 类比 | +|------|------|--------|------|------| +| **1** | 晶体管 | 数十亿 | 最基本的开关单元 | 一个开关 | +| **2** | 逻辑门 | 数亿 | 实现基本逻辑运算 | 开关组合 | +| **3** | 功能单元 | 数百 | 实现特定功能(加法、存储等) | 功能模块 | +| **4** | CPU 核心 | 1-128 | 完整的处理器 | 大脑 | + +::: tip 📊 逐行解读这张表 +**第1层(晶体管)**:这是最底层的"开关"。现代 CPU 使用的是 MOSFET(金属氧化物半导体场效应晶体管),它的特点是:给栅极加电压,源极和漏极之间就导通;不加电压,就断开。这就是"用电控制电"的开关。 + +**第2层(逻辑门)**:把晶体管组合起来,就能实现"与"、"或"、"非"等逻辑运算。比如 AND 门:两个输入都为 1 时输出才为 1。这就像两个串联的开关,必须都按下灯才会亮。 + +**第3层(功能单元)**:把逻辑门组合起来,就能实现更复杂的功能。加法器能做加法,寄存器能存储数据,多路选择器能选择数据。这些是 CPU 的"器官"。 + +**第4层(CPU 核心)**:把功能单元组合起来,加上控制器、总线等,就形成了一个完整的 CPU 核心。它能取指令、解码、执行、写回结果——这就是"计算"的全部过程。 +::: + +--- + +## 1. 晶体管:数字世界的开关 + +### 1.1 什么是晶体管? + +::: tip 💡 晶体管是什么? +**晶体管(Transistor)** 是一种半导体器件,它可以像开关一样控制电流的通断。 + +**生活类比**:想象一个水龙头: +- **水龙头**:你用手拧开关,控制水流 +- **晶体管**:用电压控制开关,控制电流 + +关键区别是:晶体管不是用手拧,而是用"电"来控制。这意味着一个开关可以控制另一个开关,从而实现"自动控制"。 +::: + +**晶体管的三个极:** + +| 极 | 名称 | 作用 | 类比 | +|---|------|------|------| +| **源极 (Source)** | 电流入口 | 电流从这里进入 | 水管入口 | +| **漏极 (Drain)** | 电流出口 | 电流从这里流出 | 水管出口 | +| **栅极 (Gate)** | 控制端 | 控制是否导通 | 水龙头开关 | + +### 1.2 晶体管如何表示 0 和 1? + +计算机只认识 0 和 1,这和晶体管有什么关系? + +::: tip 💡 用电压表示 0 和 1 +**核心思想**:用电压的高低来表示 0 和 1。 + +- **高电压(如 3.3V)**:表示 1 +- **低电压(如 0V)**:表示 0 + +这就像灯泡的亮和灭: +- 灯亮 = 1 +- 灯灭 = 0 + +晶体管的作用就是"控制灯泡的亮灭"——给栅极加高电压,源极和漏极导通,"灯泡"亮了(输出 1);给栅极低电压,源极和漏极断开,"灯泡"灭了(输出 0)。 +::: + +### 1.3 从一个开关到几十亿 + +你可能好奇:一个开关能做什么?答案是:一个开关做不了什么,但几十亿个开关组合起来,就能做任何计算。 + +**现代 CPU 的晶体管数量:** + +| 年份 | CPU | 晶体管数量 | 制程工艺 | +|------|-----|-----------|---------| +| 1971 | Intel 4004 | 2,300 | 10μm | +| 1993 | Intel Pentium | 310万 | 0.8μm | +| 2006 | Intel Core 2 | 2.91亿 | 65nm | +| 2020 | Apple M1 | 160亿 | 5nm | +| 2023 | Apple M3 Max | 920亿 | 3nm | + +::: tip 💡 什么是制程工艺? +**制程工艺**(如 5nm、3nm)指的是晶体管的尺寸。数字越小,晶体管越小,同样面积能容纳的晶体管越多。 + +- **5nm**:大约是 50 个原子的宽度 +- **3nm**:大约是 30 个原子的宽度 + +制程越小,CPU 性能越强、功耗越低。但制造难度也指数级增加。 +::: + +--- + +## 2. 逻辑门:用开关做运算 + +### 2.1 从晶体管到逻辑门 + +一个晶体管只是一个开关,但把多个晶体管组合起来,就能实现"逻辑运算"。 + + + +### 2.2 基本逻辑门详解 + +**AND 门(与门)**: +- **规则**:两个输入都为 1,输出才为 1 +- **生活类比**:串联的两个开关,必须都按下灯才亮 +- **应用**:判断"多个条件是否同时满足" + +**OR 门(或门)**: +- **规则**:任一个输入为 1,输出就为 1 +- **生活类比**:并联的两个开关,按任意一个灯就亮 +- **应用**:判断"是否满足任一条件" + +**NOT 门(非门)**: +- **规则**:输入和输出相反 +- **生活类比**:反相器,开变关、关变开 +- **应用**:取反操作 + +**XOR 门(异或门)**: +- **规则**:两个输入不同时输出 1 +- **生活类比**:判断"两个值是否不同" +- **应用**:比较、加法运算 + +### 2.3 用逻辑门做加法 + + + +::: tip 💡 加法器是怎么工作的? +**半加器**:处理两个 1 位二进制数相加 +- 输入:A、B(各 1 位) +- 输出:和(S)、进位(C) +- 公式:S = A XOR B,C = A AND B + +**全加器**:处理两个 1 位二进制数相加,加上上一位的进位 +- 输入:A、B、Cin(进位输入) +- 输出:和(S)、Cout(进位输出) + +**多位加法器**:把多个全加器级联起来 +- 第 1 位加法器的进位输出,连接到第 2 位加法器的进位输入 +- 就像我们手算加法时"逢二进一" +::: + +--- + +## 3. 功能单元:逻辑门的组合 + +### 3.1 常见功能单元 + +| 单元 | 功能 | 组成 | 类比 | +|------|------|------|------| +| **加法器** | 做加法 | 多个全加器级联 | 计算器的加法功能 | +| **多路选择器** | 选择数据 | AND 门 + OR 门 | 多选一开关 | +| **译码器** | 解码指令 | 多个 AND 门 | 翻译器 | +| **寄存器** | 存储数据 | 触发器(锁存器) | 临时笔记本 | +| **计数器** | 计数 | 触发器级联 | 计分牌 | + +### 3.2 寄存器:存储 1 位数据 + +::: tip 💡 寄存器是怎么存储数据的? +寄存器使用**触发器**电路来存储数据。触发器的特点是:一旦设置了状态,就能保持住,直到下一次改变。 + +**生活类比**:想象一个跷跷板: +- 推一下左边,左边就沉下去,右边翘起来 +- 即使你松手,跷跷板也会保持这个状态 +- 只有再推一下,才会改变状态 + +触发器就是这样的"电子跷跷板",能"记住"上一次被设置的状态。 +::: + +--- + +## 4. CPU 架构:从功能单元到处理器 + +### 4.1 CPU 的核心组件 + + + +### 4.2 CPU 是如何执行指令的? + +CPU 执行一条指令,需要经过四个阶段: + +| 阶段 | 名称 | 做什么 | 类比 | +|------|------|--------|------| +| **1** | 取指 (Fetch) | 从内存读取指令 | 从书架上取书 | +| **2** | 解码 (Decode) | 分析指令要做什么 | 阅读书的内容 | +| **3** | 执行 (Execute) | 执行运算 | 按书中的指示行动 | +| **4** | 写回 (Write Back) | 把结果存回寄存器 | 把结果记在笔记本上 | + +::: tip 💡 指令周期 +这四个阶段组成一个**指令周期**。CPU 不断重复这个周期,一条一条执行指令,就实现了"计算"。 + +现代 CPU 使用**流水线技术**,让多个指令的不同阶段并行执行: +- 第 1 条指令在执行时 +- 第 2 条指令在解码 +- 第 3 条指令在取指 + +这就像工厂流水线,大大提高了效率。 +::: + +### 4.3 CPU 性能的关键指标 + +| 指标 | 含义 | 影响 | 典型值 | +|------|------|------|--------| +| **主频** | 每秒执行多少个时钟周期 | 主频越高,执行越快 | 3-5 GHz | +| **核心数** | 独立的处理器数量 | 核心越多,并行能力越强 | 4-64 核 | +| **缓存** | CPU 内部的高速存储 | 缓存越大,访问内存越少 | 8-64 MB | +| **指令集** | CPU 能理解的指令集合 | 决定兼容性和功能 | x86、ARM | + +--- + +## 5. 总结:从沙子到智能 + +让我们回顾一下从晶体管到 CPU 的完整路径: + +``` +沙子(硅) + ↓ 提纯、切割 +硅晶圆 + ↓ 光刻、蚀刻、掺杂 +晶体管(开关) + ↓ 组合 +逻辑门(AND、OR、NOT...) + ↓ 组合 +功能单元(加法器、寄存器...) + ↓ 组合 +CPU 核心(ALU、控制器、寄存器组...) + ↓ 编程 +软件应用 +``` + +::: tip 💡 核心启示 +**计算机的本质是"开关的组合"**。 + +- 一个开关做不了什么 +- 但几十亿个开关,按特定方式组合,就能执行任何计算 +- 这就是"量变引起质变"的最好例证 + +理解这一点,你就会明白: +- 为什么计算机只认识 0 和 1 +- 为什么编程语言最终都要翻译成机器码 +- 为什么算法效率如此重要(因为每一步操作都需要大量晶体管参与) +::: + +--- + +## 延伸阅读 + +- **计算机组成原理**:深入了解 CPU、内存、I/O 的工作原理 +- **数字电路**:学习逻辑门、触发器、时序电路的设计 +- **计算机体系结构**:研究 CPU 的性能优化、流水线、缓存等 +- **汇编语言**:直接和 CPU 对话,理解指令执行过程 diff --git a/docs/zh-cn/appendix/1-computer-fundamentals/type-systems-compilers.md b/docs/zh-cn/appendix/1-computer-fundamentals/type-systems-compilers.md new file mode 100644 index 0000000..a68f6ba --- /dev/null +++ b/docs/zh-cn/appendix/1-computer-fundamentals/type-systems-compilers.md @@ -0,0 +1,478 @@ +# 类型系统与编译原理入门 + +::: tip 🎯 核心问题 +**编程语言如何理解你的代码?** 当你写下 `int x = 10 + 5;` 时,编译器需要理解每个字符的含义、检查类型是否正确、优化代码、最终生成机器能执行的指令。本章带你理解这个神奇的过程。 +::: + +--- + +## 0. 想象你在翻译一本书: + +- **识别单词**:把句子拆成一个个单词(词法分析) +- **理解语法**:判断句子是否符合语法规则(语法分析) +- **理解含义**:确保句子意思正确(语义分析) +- **优化表达**:让句子更简洁(代码优化) +- **翻译输出**:翻译成目标语言(代码生成) + +**编译器就是编程语言的"翻译官"**,将人类可读的代码转换为机器可执行的指令。 + + + +--- + +## 1. 类型系统基础 + +### 1.1 什么是类型? + +::: tip 💡 类型的本质 +类型是对数据的**分类**,规定了数据可以进行的操作。 + +就像现实世界: +- **整数**:可以加减乘除,但不能分割 +- **字符串**:可以拼接、截取,但不能直接运算 +- **布尔**:只有 true/false,用于逻辑判断 +::: + +**基本数据类型**: + +| 类型 | 表示 | 占用空间 | 取值范围 | +|------|------|---------|---------| +| **整数** | int | 4 字节 | -2^31 到 2^31-1 | +| **浮点数** | float | 4 字节 | 约 ±3.4 × 10^38 | +| **双精度** | double | 8 字节 | 约 ±1.8 × 10^308 | +| **字符** | char | 1 字节 | 0 到 255 | +| **布尔** | bool | 1 字节 | true/false | + +### 1.2 静态类型 vs 动态类型 + +::: tip 💡 核心区别 +**静态类型**:变量类型在**编译时**确定 +**动态类型**:变量类型在**运行时**确定 +::: + +**静态类型示例(Java)**: + +```java +String name = "Alice"; // 编译时确定 name 是 String 类型 +name = 123; // 编译错误!类型不匹配 +``` + +**动态类型示例(Python)**: + +```python +name = "Alice" # 运行时 name 是 str 类型 +name = 123 # 运行时 name 变成 int 类型 +print(type(name)) # +``` + +**对比分析**: + +| 特性 | 静态类型 | 动态类型 | +|------|---------|---------| +| **类型检查时机** | 编译时 | 运行时 | +| **错误发现** | 早(编译期) | 晚(运行时) | +| **代码灵活性** | 低 | 高 | +| **执行性能** | 高(编译优化) | 低(运行时检查) | +| **IDE 支持** | 好(自动补全) | 差(运行时才知道类型) | +| **代表语言** | Java, C++, Rust, TypeScript | Python, JavaScript, Ruby | + +### 1.3 强类型 vs 弱类型 + +::: tip 💡 核心区别 +**强类型**:不允许隐式类型转换 +**弱类型**:允许隐式类型转换 +::: + +**弱类型示例(JavaScript)**: + +```javascript +console.log("1" + 1) // "11" - 字符串拼接 +console.log("1" - 1) // 0 - 自动转数字 +console.log([] + []) // "" - 空数组转空字符串 +console.log(true + 1) // 2 - 布尔转数字 +``` + +**强类型示例(Python)**: + +```python +"1" + 1 # TypeError: can only concatenate str to str +"1" - 1 # TypeError: unsupported operand type(s) +``` + +**类型系统四象限**: + +| | 强类型 | 弱类型 | +|---|--------|--------| +| **静态** | Java, Rust, Haskell | C, C++ | +| **动态** | Python, Ruby | JavaScript, PHP | + +### 1.4 类型推断 + +现代语言可以**自动推断**变量类型,结合静态类型的安全性和动态类型的简洁性: + +```typescript +// TypeScript +let x = 1; // 推断为 number +let arr = [1, 2, 3]; // 推断为 number[] +let fn = (x) => x; // 推断为 (x: any) => any + +// Rust +let x = 1; // 推断为 i32 +let s = "hello"; // 推断为 &str +let v = vec![1, 2]; // 推断为 Vec +``` + +--- + +## 2. 编译原理基础 + +### 2.1 编译器的任务 + +::: tip 💡 编译器做什么? +编译器将**源代码**转换为**目标代码**,主要完成: + +1. **理解代码**:分析源代码的结构和含义 +2. **检查正确性**:发现语法和语义错误 +3. **优化代码**:提高执行效率 +4. **生成代码**:输出目标机器的指令 +::: + + + +### 2.2 词法分析(Lexical Analysis) + +**任务**:将源代码分解为**词法单元(Token)** + +**示例**: + +``` +源代码: int x = 10 + 5; + +词法单元: +[int] → 关键字 +[x] → 标识符 +[=] → 运算符 +[10] → 整数字面量 +[+] → 运算符 +[5] → 整数字面量 +[;] → 分隔符 +``` + +**词法分析器的工作**: + +| 输入 | 处理 | 输出 | +|------|------|------| +| `int` | 匹配关键字表 | `KEYWORD(int)` | +| `x` | 匹配标识符规则 | `IDENTIFIER(x)` | +| `10` | 匹配数字规则 | `NUMBER(10)` | + +### 2.3 语法分析(Syntax Analysis) + +**任务**:根据语法规则,将 Token 流组织成**语法树(AST)** + +**示例**: + +``` +表达式: 1 + 2 * 3 + +语法树: + + + / \ + 1 * + / \ + 2 3 +``` + +::: tip 💡 为什么是这棵树? +根据运算优先级,`*` 优先级高于 `+`,所以 `2 * 3` 先结合。 + +如果表达式是 `(1 + 2) * 3`,语法树会变成: + +``` + * + / \ + + 3 + / \ + 1 2 +``` +::: + +**语法规则(文法)**: + +``` +表达式 → 表达式 + 项 | 表达式 - 项 | 项 +项 → 项 * 因子 | 项 / 因子 | 因子 +因子 → 数字 | (表达式) +``` + +### 2.4 语义分析(Semantic Analysis) + +**任务**:检查语义正确性,进行类型检查 + +**主要工作**: + +| 工作 | 说明 | 示例 | +|------|------|------| +| **类型检查** | 检查类型是否匹配 | `int x = "hello";` → 错误 | +| **作用域分析** | 检查变量是否声明 | 使用未声明变量 → 错误 | +| **符号表构建** | 记录所有标识符信息 | 变量名、类型、作用域 | +| **类型推断** | 推断表达式类型 | `1 + 2.0` → float | + +**符号表示例**: + +``` +int x = 10; +float y = 3.14; +string name = "Alice"; + +符号表: +┌──────────┬────────┬─────────┐ +│ 名称 │ 类型 │ 作用域 │ +├──────────┼────────┼─────────┤ +│ x │ int │ global │ +│ y │ float │ global │ +│ name │ string │ global │ +└──────────┴────────┴─────────┘ +``` + +### 2.5 中间代码生成 + +**任务**:生成平台无关的中间表示(IR) + +**三地址码示例**: + +``` +源代码: int x = (a + b) * c; + +三地址码: +t1 = a + b +t2 = t1 * c +x = t2 +``` + +::: tip 💡 为什么需要中间代码? +1. **平台无关**:一次编写,多平台编译 +2. **便于优化**:在 IR 层面进行优化 +3. **支持多语言**:不同语言可以编译到同一 IR + +例如 LLVM IR 支持 C、C++、Rust、Swift 等多种语言。 +::: + +### 2.6 代码优化 + +**任务**:提高代码执行效率 + +**常见优化技术**: + +| 优化技术 | 说明 | 示例 | +|---------|------|------| +| **常量折叠** | 编译时计算常量表达式 | `10 + 5` → `15` | +| **死代码消除** | 删除不会执行的代码 | `if (false) { ... }` → 删除 | +| **内联展开** | 函数调用替换为函数体 | `add(1, 2)` → `1 + 2` | +| **循环优化** | 减少循环开销 | 循环展开、循环不变量外提 | +| **公共子表达式消除** | 避免重复计算 | `a+b` 计算一次,多次使用 | + +**优化示例**: + +```c +// 优化前 +int x = 10 + 5; // 常量折叠 +int y = x * 2; // x 已知为 15 +if (false) { // 死代码 + printf("never"); +} + +// 优化后 +int x = 15; +int y = 30; +// if 语句被删除 +``` + +### 2.7 目标代码生成 + +**任务**:生成目标机器的机器码 + +**汇编代码示例**: + +```asm +; int x = 15; +mov eax, 15 +mov dword ptr [x], eax + +; int y = 30; +mov eax, 30 +mov dword ptr [y], eax +``` + +**代码生成的主要任务**: + +| 任务 | 说明 | +|------|------| +| **指令选择** | 选择合适的机器指令 | +| **寄存器分配** | 决定哪些变量放在寄存器 | +| **指令调度** | 安排指令顺序,提高流水线效率 | + +--- + +## 3. 编译型 vs 解释型 vs JIT + +### 3.1 编译型语言 + +**流程**:源代码 → 编译器 → 机器码 → 执行 + +``` +main.c → [编译器] → main.exe → [CPU] → 执行 +``` + +**特点**: +- ✅ 执行速度快 +- ✅ 编译期发现错误 +- ❌ 编译时间长 +- ❌ 跨平台需要重新编译 + +**代表语言**:C, C++, Rust, Go + +### 3.2 解释型语言 + +**流程**:源代码 → 解释器 → 逐行执行 + +``` +main.py → [解释器] → 逐行解释执行 +``` + +**特点**: +- ✅ 跨平台 +- ✅ 开发调试快 +- ❌ 执行速度慢 +- ❌ 运行时才能发现错误 + +**代表语言**:Python, Ruby, PHP + +### 3.3 JIT(即时编译) + +**流程**:源代码 → 字节码 → JIT 编译 → 执行 + +``` +源代码 → [编译器] → 字节码 → [JIT] → 机器码 → 执行 +``` + +**工作原理**: +1. 先将源代码编译成字节码(中间代码) +2. 解释器逐行执行字节码 +3. 发现热点代码(频繁执行),JIT 编译成机器码 +4. 后续直接执行机器码 + +**特点**: +- ✅ 兼顾性能和跨平台 +- ✅ 热点代码执行快 +- ❌ 启动慢(需要预热) +- ❌ 内存占用大 + +**代表语言**:Java (JVM), JavaScript (V8), Python (PyPy) + +--- + +## 4. 实践:手写简单解释器 + +### 4.1 目标 + +实现一个简单的计算器,支持加减乘除: + +``` +输入: 1 + 2 * 3 +输出: 7 +``` + +### 4.2 词法分析器 + +```python +import re + +Token = namedtuple('Token', ['type', 'value']) + +def tokenize(code): + tokens = [] + for match in re.finditer(r'\d+|[+\-*/()]', code): + value = match.group() + if value.isdigit(): + tokens.append(Token('NUMBER', int(value))) + else: + tokens.append(Token(value, value)) + return tokens + +# 测试 +print(tokenize('1 + 2 * 3')) +# [Token(type='NUMBER', value=1), Token(type='+', value='+'), ...] +``` + +### 4.3 语法分析器 + +```python +class Parser: + def __init__(self, tokens): + self.tokens = tokens + self.pos = 0 + + def parse(self): + return self.expr() + + def expr(self): + result = self.term() + while self.current() in ('+', '-'): + op = self.consume() + right = self.term() + if op == '+': + result += right + else: + result -= right + return result + + def term(self): + result = self.factor() + while self.current() in ('*', '/'): + op = self.consume() + right = self.factor() + if op == '*': + result *= right + else: + result //= right + return result + + def factor(self): + token = self.consume() + if token.type == 'NUMBER': + return token.value + elif token.value == '(': + result = self.expr() + self.consume() # ) + return result +``` + +### 4.4 完整解释器 + +```python +def evaluate(code): + tokens = tokenize(code) + parser = Parser(tokens) + return parser.parse() + +print(evaluate('1 + 2 * 3')) # 7 +print(evaluate('(1 + 2) * 3')) # 9 +print(evaluate('10 - 2 * 3')) # 4 +``` + +--- + +## 5. 总结 + +::: tip 📚 核心要点 +1. **类型系统**:静态/动态、强/弱类型,影响代码安全和灵活性 +2. **编译流程**:词法分析 → 语法分析 → 语义分析 → 中间代码 → 优化 → 代码生成 +3. **执行方式**:编译型快但需编译,解释型慢但灵活,JIT 兼顾两者 +4. **实践价值**:理解编译原理有助于写出更好的代码 +::: + +**下一步学习**: +- [编程语言图谱](./programming-languages) - 了解更多编程语言 +- [数据结构](./data-structures) - 理解数据的组织方式 +- [算法思维入门](./algorithm-thinking) - 学习解决问题的方法 diff --git a/docs/zh-cn/appendix/terminal-intro.md b/docs/zh-cn/appendix/2-development-tools/command-line-shell.md similarity index 99% rename from docs/zh-cn/appendix/terminal-intro.md rename to docs/zh-cn/appendix/2-development-tools/command-line-shell.md index 6b03bb3..974450d 100644 --- a/docs/zh-cn/appendix/terminal-intro.md +++ b/docs/zh-cn/appendix/2-development-tools/command-line-shell.md @@ -1,5 +1,4 @@ -# 终端原理 (Introduction to Terminal Principles) - +# 命令行与 Shell 脚本 > 💡 **学习指南**:本章节旨在为零基础读者提供一个关于终端(Terminal)工作原理的系统性认知。无需具备计算机专业背景,我们将通过交互式演示,由浅入深地解析终端的运行机制。 ## 0. 快速上手:如何打开终端? diff --git a/docs/zh-cn/appendix/2-development-tools/debugging-art.md b/docs/zh-cn/appendix/2-development-tools/debugging-art.md new file mode 100644 index 0000000..415935d --- /dev/null +++ b/docs/zh-cn/appendix/2-development-tools/debugging-art.md @@ -0,0 +1,2 @@ +# 调试的艺术 +> 待实现 diff --git a/docs/zh-cn/appendix/browser-devtools/index.md b/docs/zh-cn/appendix/2-development-tools/debugging-art/index.md similarity index 100% rename from docs/zh-cn/appendix/browser-devtools/index.md rename to docs/zh-cn/appendix/2-development-tools/debugging-art/index.md diff --git a/docs/zh-cn/appendix/2-development-tools/editors-and-ai.md b/docs/zh-cn/appendix/2-development-tools/editors-and-ai.md new file mode 100644 index 0000000..f913b5c --- /dev/null +++ b/docs/zh-cn/appendix/2-development-tools/editors-and-ai.md @@ -0,0 +1,3 @@ +# 编辑器与 AI 编程助手 + +> 待实现 diff --git a/docs/zh-cn/appendix/ide-intro/images/image23.png b/docs/zh-cn/appendix/2-development-tools/editors-and-ai/images/image23.png similarity index 100% rename from docs/zh-cn/appendix/ide-intro/images/image23.png rename to docs/zh-cn/appendix/2-development-tools/editors-and-ai/images/image23.png diff --git a/docs/zh-cn/appendix/ide-intro/images/index-2026-01-09-11-28-43.png b/docs/zh-cn/appendix/2-development-tools/editors-and-ai/images/index-2026-01-09-11-28-43.png similarity index 100% rename from docs/zh-cn/appendix/ide-intro/images/index-2026-01-09-11-28-43.png rename to docs/zh-cn/appendix/2-development-tools/editors-and-ai/images/index-2026-01-09-11-28-43.png diff --git a/docs/zh-cn/appendix/ide-intro/images/index-2026-01-09-11-35-55.png b/docs/zh-cn/appendix/2-development-tools/editors-and-ai/images/index-2026-01-09-11-35-55.png similarity index 100% rename from docs/zh-cn/appendix/ide-intro/images/index-2026-01-09-11-35-55.png rename to docs/zh-cn/appendix/2-development-tools/editors-and-ai/images/index-2026-01-09-11-35-55.png diff --git a/docs/zh-cn/appendix/ide-intro/images/index-2026-01-09-11-36-23.png b/docs/zh-cn/appendix/2-development-tools/editors-and-ai/images/index-2026-01-09-11-36-23.png similarity index 100% rename from docs/zh-cn/appendix/ide-intro/images/index-2026-01-09-11-36-23.png rename to docs/zh-cn/appendix/2-development-tools/editors-and-ai/images/index-2026-01-09-11-36-23.png diff --git a/docs/zh-cn/appendix/2-development-tools/environment-path.md b/docs/zh-cn/appendix/2-development-tools/environment-path.md new file mode 100644 index 0000000..11b9f9b --- /dev/null +++ b/docs/zh-cn/appendix/2-development-tools/environment-path.md @@ -0,0 +1,3 @@ +# 环境变量与 PATH + +> 待实现 diff --git a/docs/zh-cn/appendix/2-development-tools/git-version-control.md b/docs/zh-cn/appendix/2-development-tools/git-version-control.md new file mode 100644 index 0000000..944eb9c --- /dev/null +++ b/docs/zh-cn/appendix/2-development-tools/git-version-control.md @@ -0,0 +1,348 @@ +# Git:代码的时光机 +::: tip 🎯 核心问题 +**写代码时最怕什么?** 写错了想回退、改崩了想重来、多人同时改同一个文件...这些头疼的事,Git 都能帮你搞定!它就像是代码世界的"时光机",让你随时回到过去,又能和队友在各自的"平行宇宙"里安全开发。 +::: + +--- + +## 0. 最常用的 5 个场景(直接照抄) + +如果你只想"立刻能用",先把这块过一遍:每个场景都是现实工作中最常见的 Git 流程。 + + + +--- + +## 1. 为什么要学 Git?三大痛点 + +### 1.1 痛点一:版本混乱 + +你是否经历过这种绝望? + +```text +论文_初稿.doc +论文_修改版.doc +论文_最终版.doc +论文_最终版_打死不改版.doc +论文_绝对是最后一次修改版.doc +``` + +**Git 的解决方案**:不需要复制副本,一个文件夹搞定所有历史版本。想回到哪次修改,一键恢复。 + +### 1.2 痛点二:无法后悔 + +::: tip 💡 这个场景你一定遇到过 +写代码写了 3 小时,突然发现之前的思路更好,但已经改不回去了...或者删错了一段代码,想找回原来的版本。 + +有了 Git,这种情况永远不会发生。每次重要节点都能"存档",出问题随时"读档"重来。 +::: + +### 1.3 痛点三:协作冲突 + +你和队友同时改同一个文件: + +- 你改了 A 文件的第 10 行 +- 队友改了 A 文件的第 15 行 +- 怎么合并?谁覆盖谁? + +**Git 的解决方案**:智能合并,自动处理大部分冲突。只有当你们真的改了同一行代码时,才需要手动决定用谁的。 + +--- + +## 2. 核心概念:三区模型 + +Git 的设计哲学其实很像**寄快递**。 + + + +### 2.1 三个区域是什么? + +::: tip 📦 用快递理解 Git +想象你在寄快递: + +- **工作区(Working Dir)** = 你的**书桌**。你在这里整理要寄的东西,想怎么乱改都行。 +- **暂存区(Staging Area)** = **快递盒**。你把要寄的文件放进去(`git add`),准备打包。 +- **仓库(Repository)** = **快递柜**。一旦你封箱寄出(`git commit`),这个版本就被永久记录下来了。 + ::: + +| 区域 | 作用 | 对应命令 | 状态 | +| ---------- | ------------------ | --------------------- | ------------- | +| **工作区** | 你当前正在改的代码 | `git status` 查看修改 | 红色 = 未暂存 | +| **暂存区** | 准备提交的文件 | `git add` 添加 | 绿色 = 已暂存 | +| **仓库** | 永久保存的历史版本 | `git commit` 提交 | 只读,不能改 | + +::: tip 💡 关键理解 +只有提交到**仓库**的内容才是安全的。工作区里没提交的内容,丢了就真丢了。所以经常`git commit`是好习惯! +::: + +--- + +## 3. 基础工作流:存档三步走 + +日常开发中,你 90% 的时间都在重复这三个动作。 + + + +### 3.1 第一步:修改代码(工作区) + +在工作区写写画画,想怎么改就怎么改。这时候修改只在你本地,还没记录。 + +### 3.2 第二步:挑选文件(git add → 暂存区) + +::: tip 🤔 为什么要先 add 再 commit? +你可能问:为什么不能直接 commit 所有修改? + +**答案**:因为有时候你不想一次性提交所有改动。 + +- 今天改了 5 个文件,但只想提交其中 3 个(完成了一个功能) +- 另外 2 个文件还在调试中,不想现在提交 + +`git add` 让你有选择权:决定这次提交包含哪些文件。 +::: + +**常用命令**: + +```bash +# 添加单个文件 +git add index.html + +# 添加所有修改 +git add . + +# 查看哪些文件被暂存了 +git status +``` + +### 3.3 第三步:封箱提交(git commit → 仓库) + +给这次修改起个名字(比如"修复了登录 Bug"),永久存档。 + +**重要:commit message 要写清楚!** + +```bash +# ❌ 不好的写法 +git commit -m "update" + +# ✅ 好的写法 +git commit -m "feat: 添加用户登录功能" +git commit -m "fix: 修复首页在 iOS 的显示问题" +git commit -m "docs: 更新 README 的部署说明" +``` + +::: tip 💡 commit message 规范 +推荐用**类型+描述**的格式: + +- `feat:` 新功能 +- `fix:` 修复 bug +- `docs:` 文档更新 +- `style:` 代码格式(不影响功能) +- `refactor:` 重构(不改变功能) +- `test:` 测试相关 +- `chore:` 构建/工具相关 + +这样以后翻历史记录,一眼就知道每次提交做了什么。 +::: + +--- + +## 4. 平行宇宙:分支(Branch)的魔法 + +这是 Git 最强大的功能! + +::: tip 🌌 用游戏理解分支 +想象你在玩游戏,前面有个大 Boss(上线新功能),你怕打不过导致游戏结束(系统崩溃)。 + +这时候,你可以开一个**分支(Branch)**,相当于**复制了一个平行世界**: + +- 在**平行世界**(新分支)里打 Boss,输了也不怕,因为主世界(主分支)没影响 +- 打赢了就把成果"合并"回主世界 +- 多个队友可以在各自的平行世界开发,互不干扰 + ::: + + + +### 4.1 主分支 vs 开发分支 + +| 分支类型 | 作用 | 特点 | +| ------------------- | -------------- | ------------------------------------ | +| **main/master** | 稳定的线上版本 | 只有测试通过的代码才能进来 | +| **dev/feature-xxx** | 你的试验田 | 这里炸了地球也没关系,不影响主分支 | +| **hotfix-xxx** | 紧急修复 | 生产出 bug 时,从 main 开分支快速修复 | + +### 4.2 分支操作流程 + +**创建分支并切换**: + +```bash +# 创建新分支 +git branch feature-login + +# 切换到新分支 +git checkout feature-login + +# 或者一步到位:创建并切换 +git checkout -b feature-login +``` + +**在分支上开发**: + +```bash +# 在 feature-login 分支上改代码... +git add . +git commit -m "feat: 添加登录表单" +``` + +**合并回主分支**: + +```bash +# 切回主分支 +git checkout main + +# 合并 feature-login +git merge feature-login + +# 删除已合并的分支(可选) +git branch -d feature-login +``` + +::: tip 💡 什么时候用分支? +**个人开发**: + +- 要尝试新想法,不确定会不会搞崩现有代码 → 开分支 +- 修一个复杂 bug,需要多次实验 → 开分支 + +**团队开发**: + +- 每个功能一个分支,互不干扰 +- 开发完提 Pull Request,队友 review 后再合并 + ::: + +--- + +## 5. 常用命令速查表 + +| 命令 | 作用 | 人话解释 | 使用频率 | +| ----------------------- | ---------- | ------------------------------ | --------------------- | +| `git init` | 初始化 | "在这里建个新仓库" | 项目开始时用一次 | +| `git status` | 查看状态 | "现在乱不乱?有没有东西没提交?" | ⭐⭐⭐⭐⭐ 极高频 | +| `git add .` | 添加所有 | "把桌上所有文件都扔进快递盒" | ⭐⭐⭐⭐⭐ 每次提交前 | +| `git add file.txt` | 添加单个 | "只要这个文件" | ⭐⭐⭐⭐ 选择性添加 | +| `git commit -m "..."` | 提交 | "封箱!贴上标签,写上这次改了啥" | ⭐⭐⭐⭐⭐ 完成功能时 | +| `git log` | 查看历史 | "翻翻以前的日记" | ⭐⭐⭐ 回顾历史 | +| `git checkout -b dev` | 创建新分支 | "我要去平行宇宙 dev 探险了" | ⭐⭐⭐⭐ 开新功能 | +| `git checkout main` | 切换分支 | "回地球(主分支)看看" | ⭐⭐⭐⭐ 切换任务 | +| `git merge dev` | 合并分支 | "把平行宇宙的成果带回地球" | ⭐⭐⭐ 完成功能 | +| `git branch` | 查看分支 | "现在有哪些平行世界?" | ⭐⭐⭐ 查看状态 | +| `git branch -d feature` | 删除分支 | "这个平行世界不需要了,删掉" | ⭐⭐ 合并后清理 | +| `git push` | 推送 | "把本地存档上传到云端" | ⭐⭐⭐⭐⭐ 团队协作 | +| `git pull` | 拉取 | "把云端最新存档下载到本地" | ⭐⭐⭐⭐⭐ 团队协作 | + +--- + +## 6. 进阶:解决冲突与远程协作 + +### 6.1 冲突(Conflict)是什么? + +当你和队友**同时修改了同一个文件的同一行代码**,Git 就会懵:"我该听谁的?"这就是**冲突(Conflict)**。 + + + +### 6.2 怎么解决冲突? + +**Step 1**:打开冲突文件,会看到这样的标记: + +```text +<<<<<<< HEAD +你的代码 +======= +队友的代码 +>>>>>>> feature-branch +``` + +**Step 2**:手动选择要保留的代码,或合并两者: + +```text +# 保留你的代码 → 删除队友的部分和标记 +# 保留队友的 → 删除你的部分和标记 +# 合并两者 → 综合两边的代码 +``` + +**Step 3**:删除所有标记,保存文件 + +**Step 4**:重新提交 + +```bash +git add 解决冲突的文件 +git commit # Git 会自动生成合并提交 +``` + +::: tip 💡 避免冲突的最佳实践 + +- **频繁沟通**:队友改同一个文件前,先打个招呼 +- **小步提交**:不要攒着大量代码最后才提交,增加冲突概率 +- **分支隔离**:不同功能用不同分支,减少直接冲突 +- **用 Pull Request**:合并前让队友 review,提前发现问题 + ::: + +### 6.3 远程仓库(Remote) + +**远程仓库**(比如 GitHub/GitLab)就是**云端的备份中心**。 + + + +**核心操作**: + +| 操作 | 命令 | 作用 | +| ------------ | ---------------------------------------------- | ------------------------ | +| **关联远程** | `git remote add origin https://github.com/...` | 第一次连接云端 | +| **推送** | `git push -u origin main` | 把本地存档上传 | +| **拉取** | `git pull` | 把云端最新存档下载并合并 | +| **克隆** | `git clone https://github.com/...` | 复制整个仓库到本地 | + +::: tip 💡 push 和 pull 的区别 + +- **push**:你的本地代码 → 云端(你改了东西,要同步给队友) +- **pull**:云端代码 → 你的本地(队友改了东西,你要同步下来) + +**最佳实践**:每天开始工作前先`git pull`,下班前`git push`,这样减少冲突。 +::: + +--- + +## 7. 总结:Git 的核心思想 + +Git 不是简单的"版本备份",而是一个**完整的代码协作系统**: + +| 特性 | 解决的问题 | 生活类比 | +| ------------ | ------------------------------- | --------------------- | +| **版本管理** | 代码改错了怎么办? | 时光机,随时回退 | +| **分支** | 多人同时改同一个文件怎么办? | 平行宇宙,互不干扰 | +| **暂存区** | 这次提交不想包含所有修改怎么办? | 快递盒,挑拣要寄的东西 | +| **远程协作** | 怎么和队友共享代码? | 云备份,随时随地同步 | +| **冲突处理** | 真的改到同一行了怎么办? | 智能合并 + 手动协调 | + +**学习建议**: + +1. **先用起来**:不要等"完全理解"再用,一边用一边理解 +2. **从简单开始**:个人项目先掌握`add/commit/push/pull`,团队项目再学分支 +3. **看 Git 图形化工具**:SourceTree、GitHub Desktop 等,可视化帮助理解 +4. **遇到问题不要慌**:Git 的设计就是为了让你能安全地尝试,大不了`git reset` + +--- + +## 附录:名词速查表 + +| 名词 | 英文 | 用人话解释 | +| -------- | ---------- | ------------------------------------- | +| **仓库** | Repository | 存放所有版本历史的数据库 | +| **提交** | Commit | 一次完整的版本记录,像存档点 | +| **分支** | Branch | 独立的开发线,像平行宇宙 | +| **合并** | Merge | 把一个分支的改动整合到另一个分支 | +| **冲突** | Conflict | 同一行代码被修改多次,Git 不知道选哪个 | +| **暂存** | Stage | 把修改加入"准备提交"的列表 | +| **远程** | Remote | 云端的仓库副本(GitHub/GitLab) | +| **克隆** | Clone | 复制整个远程仓库到本地 | +| **推送** | Push | 本地 → 远程,上传代码 | +| **拉取** | Pull | 远程 → 本地,下载代码 | +| **检出** | Checkout | 切换到某个分支或版本 | +| **HEAD** | - | 当前所在的分支/版本的指针 | diff --git a/docs/zh-cn/appendix/ide-intro/index.md b/docs/zh-cn/appendix/2-development-tools/ide-basics.md similarity index 99% rename from docs/zh-cn/appendix/ide-intro/index.md rename to docs/zh-cn/appendix/2-development-tools/ide-basics.md index 98facac..05f9e1e 100644 --- a/docs/zh-cn/appendix/ide-intro/index.md +++ b/docs/zh-cn/appendix/2-development-tools/ide-basics.md @@ -181,9 +181,9 @@ onMounted(() => { 为了方便大家理解每个选项的含义,在这里我们对菜单栏进行深入解析: -![](images/index-2026-01-09-11-35-55.png) +![](editors-and-ai/images/index-2026-01-09-11-35-55.png) -![](images/index-2026-01-09-11-36-23.png) +![](editors-and-ai/images/index-2026-01-09-11-36-23.png)
File(文件):项目与文件的打开/保存/工作区管理 diff --git a/docs/zh-cn/appendix/2-development-tools/package-managers.md b/docs/zh-cn/appendix/2-development-tools/package-managers.md new file mode 100644 index 0000000..72a82e7 --- /dev/null +++ b/docs/zh-cn/appendix/2-development-tools/package-managers.md @@ -0,0 +1,3 @@ +# 包管理器(npm / pip / cargo) + +> 待实现 diff --git a/docs/zh-cn/appendix/2-development-tools/ports-localhost.md b/docs/zh-cn/appendix/2-development-tools/ports-localhost.md new file mode 100644 index 0000000..8044519 --- /dev/null +++ b/docs/zh-cn/appendix/2-development-tools/ports-localhost.md @@ -0,0 +1,3 @@ +# 端口与 localhost + +> 待实现 diff --git a/docs/zh-cn/appendix/2-development-tools/regex.md b/docs/zh-cn/appendix/2-development-tools/regex.md new file mode 100644 index 0000000..586efa3 --- /dev/null +++ b/docs/zh-cn/appendix/2-development-tools/regex.md @@ -0,0 +1,3 @@ +# 正则表达式 + +> 待实现 diff --git a/docs/zh-cn/appendix/2-development-tools/ssh-authentication.md b/docs/zh-cn/appendix/2-development-tools/ssh-authentication.md new file mode 100644 index 0000000..38ae531 --- /dev/null +++ b/docs/zh-cn/appendix/2-development-tools/ssh-authentication.md @@ -0,0 +1,3 @@ +# SSH 与密钥认证 + +> 待实现 diff --git a/docs/zh-cn/appendix/3-browser-and-frontend/a11n-i18n.md b/docs/zh-cn/appendix/3-browser-and-frontend/a11n-i18n.md new file mode 100644 index 0000000..b78aefa --- /dev/null +++ b/docs/zh-cn/appendix/3-browser-and-frontend/a11n-i18n.md @@ -0,0 +1,3 @@ +# 无障碍与国际化 + +> 待实现 diff --git a/docs/zh-cn/appendix/browser-rendering-pipeline.md b/docs/zh-cn/appendix/3-browser-and-frontend/browser-as-os-rendering.md similarity index 92% rename from docs/zh-cn/appendix/browser-rendering-pipeline.md rename to docs/zh-cn/appendix/3-browser-and-frontend/browser-as-os-rendering.md index a2e3465..d3250af 100644 --- a/docs/zh-cn/appendix/browser-rendering-pipeline.md +++ b/docs/zh-cn/appendix/3-browser-and-frontend/browser-as-os-rendering.md @@ -1,9 +1,24 @@ -# 浏览器渲染管线与事件循环 - +# 浏览器渲染管道 ::: tip 🎯 核心问题 **为什么有些网页流畅如丝,有些却卡成PPT?** 浏览器是怎么把一堆HTML、CSS、JavaScript代码变成你眼前看到的网页的?本章将带你深入浏览器的"车间",理解它的工作流程,从而写出性能更好的网页。 ::: +**这篇文章会带你学什么?** + +| 章节 | 内容 | 学完能干嘛 | +|-----|------|-----------| +| **第 1 章** | 为什么要理解渲染管线 | 理解性能优化的必要性 | +| **第 2 章** | 渲染管线的五个阶段 | 掌握浏览器渲染的基本流程 | +| **第 3 章** | 构建DOM树和CSSOM树 | 理解HTML和CSS如何被解析 | +| **第 4 章** | 构建渲染树 | 知道哪些元素会被渲染 | +| **第 5 章** | 布局与重排 | 避免触发昂贵的布局计算 | +| **第 6 章** | 绘制与重绘 | 减少不必要的绘制操作 | +| **第 7 章** | 合成与GPU加速 | 利用GPU提升动画性能 | +| **第 8 章** | 事件循环 | 理解JavaScript的执行机制 | +| **第 9 章** | 性能优化实战 | 掌握常用的性能优化技巧 | + +每一章都从"理解原理"开始,不需要你会手写优化代码。遇到性能问题时,随时回来查就行。 + --- ## 1. 为什么要理解"渲染管线"? @@ -934,7 +949,41 @@ lazyImages.forEach(img => imageObserver.observe(img)) --- -## 10. 总结:渲染管线优化的本质 +## 10. 你现在应该能识别的性能问题 + +理解了浏览器的渲染管线后,你应该能识别以下常见的性能问题: + +| 问题代码 | 问题所在 | 如何描述给AI | +|---------|---------|-------------| +| `element.style.width = ...` | 在循环中频繁修改宽度 | "这里会触发多次重排,请改用transform或者批量处理" | +| `height = element.offsetHeight` | 在写入后立即读取布局属性 | "这是强制同步布局,请分离读写操作" | +| `element.className = ...` | 频繁修改class触发样式重新计算 | "用classList.add/remove代替,减少样式计算" | +| 动画用`width`/`left` | 触发重排和重绘,性能差 | "改用transform和opacity做动画" | +| 给所有元素加`translateZ(0)` | 滥用GPU加速导致内存爆炸 | "只给需要动画的元素开启GPU加速" | +| 列表项10000个全渲染 | DOM节点过多导致卡顿 | "实现虚拟滚动,只渲染可见区域" | +| scroll事件里直接操作DOM | 触发频率太高导致卡顿 | "用requestAnimationFrame或节流优化" | +| `box-shadow`做hover动画 | 复杂的阴影计算很慢 | "改用transform或伪元素,避免动画阴影" | + +**如果你认真读了每一章的"踩坑实录",你还掌握了这些核心概念:** + +- **渲染管线五阶段**:DOM/CSSOM → 渲染树 → 布局 → 绘制 → 合成 +- **重排 vs 重绘**:重排最昂贵(几何变化),重绘次之(外观变化) +- **强制同步布局**:读写交替会导致布局抖动,必须分离 +- **GPU加速**:transform和opacity由GPU处理,性能最佳 +- **事件循环**:JavaScript是单线程的,通过任务队列实现异步 + +这些概念会帮你快速定位性能瓶颈。 + +::: info 💡 遇到性能问题时这样跟AI说 +- "动画卡顿,检查是否触发了重排或重绘" +- "滚动性能差,可能需要节流或requestAnimationFrame" +- "列表数据量大时卡顿,需要虚拟滚动" +- "频繁修改样式导致性能问题,请用transform优化" +::: + +--- + +## 11. 总结:渲染管线优化的本质 通过本文的学习,我们可以得出以下核心结论: @@ -949,7 +998,7 @@ lazyImages.forEach(img => imageObserver.observe(img)) --- -## 11. 名词对照表 +## 12. 名词对照表 | 英文术语 | 中文对照 | 解释 | | :--- | :--- | :--- | diff --git a/docs/zh-cn/appendix/3-browser-and-frontend/browser-as-os.md b/docs/zh-cn/appendix/3-browser-and-frontend/browser-as-os.md new file mode 100644 index 0000000..1e4d112 --- /dev/null +++ b/docs/zh-cn/appendix/3-browser-and-frontend/browser-as-os.md @@ -0,0 +1,544 @@ +# 浏览器是一个操作系统 + +::: tip 前言 +你每天都在用浏览器——看视频、刷新闻、在线办公。但你有没有想过:**当你在地址栏输入一个网址并按下回车,背后发生了什么?** + +这篇文章会用**"网购"**的生活化比喻,配合**真实的技术过程**,带你一步步理解浏览器如何将一行网址变成丰富多彩的页面。 + +读完这篇,你就能: +- 理解从输入网址到显示页面的完整流程 +- 掌握 URL、DNS、TCP、HTTP 等核心概念 +- 了解浏览器如何渲染页面 +- 知道静态网站和动态网站的区别 + +**无需编程基础**,只需要你平时网购的经验即可。 +::: + +**这篇文章会带你学什么?** + +| 章节 | 内容 | 核心概念 | +|-----|------|---------| +| **第 1 章** | URL 解析 | 网址的结构和作用 | +| **第 2 章** | DNS 查询 | 域名如何转换成 IP 地址 | +| **第 3 章** | TCP 握手 | 如何建立可靠的连接 | +| **第 4 章** | HTTP 通信 | 浏览器和服务器如何对话 | +| **第 5 章** | 浏览器渲染 | 代码如何变成画面 | +| **第 6 章** | 静态 vs 动态 | 网页内容的生成方式 | + +--- + +## 0. 引言:当你按下回车键的那一刻 + +::: tip 🤔 核心问题 +**当你在浏览器输入网址并按下回车,后台发生了什么?** 为什么有的网页打开很快,有的很慢?为什么有时候会出现"找不到服务器"的错误? +::: + +### 生活比喻:一次网购之旅 + +想象你正在进行一次**网购**。整个过程可以分为 5 个步骤: + +
+
+ +**🛒 第 1 步:填写订单** +选好商品,确认收货地址 + +
+
+ +**🗺️ 第 2 步:查找仓库** +系统找到具体的发货仓库 + +
+
+ +**📞 第 3 步:建立通道** +确认仓库营业且能发货 + +
+
+ +
+
+ +**🚚 第 4 步:仓库发货** +快递员把包裹送上门 + +
+
+ +**🎁 第 5 步:拆箱体验** +打开包裹,看到心仪的商品 + +
+
+ +**访问网页的过程和网购惊人地相似!** + +当你在浏览器输入 `google.com` 并按下回车,你就是那个"买家",浏览器通过一系列操作,最终把远方服务器上的"商品"(网页内容)送到你的屏幕上。 + + + +::: info 💡 核心启示 +理解浏览器工作原理的关键是:**把复杂的技术过程映射到熟悉的生活场景**。网购的 5 个步骤完美对应了浏览器访问网页的 5 个技术阶段。 +::: + +--- + +## 1. 第一步:填写"订单" —— URL 解析 + +::: tip 🤔 核心问题 +**为什么网址要写成这样?** `https://www.example.com:8080/path/page.html?id=123#section` — 这串字符到底有什么含义? +::: + +### 生活比喻:填写购物单 + +假设你只在订单上写"买鞋子",仓库肯定不知道发哪双。你需要写清楚: + +- **店铺类型**(官方旗舰店/普通店) +- **店铺名称**(Nike 官方店) +- **商品位置**(男鞋区/跑鞋系列) +- **具体型号**(Air Max 90) +- **备注信息**(我要红色的) + +### 真实过程:浏览器解析 URL + +**URL(Uniform Resource Locator,统一资源定位符)**就是浏览器世界的"商品定位码"。当你在地址栏输入 `https://www.example.com:8080/path/page.html?id=123#section`,浏览器会立即拆解它: + +| URL 部分 | 示例值 | 网购类比 | 技术作用 | +| -------------------------- | -------------------- | -------------------------------------------------- | ------------------------------------------------------------------------ | +| **协议** `https://` | 安全超文本传输协议 | **物流方式**:保密配送(HTTPS)vs 普通配送(HTTP) | 决定使用什么规则通信。`http` 是普通传输,`https` 是加密传输 | +| **域名** `www.example.com` | 服务器的人类可读名字 | **店铺名称**:京东超市 | 告诉浏览器要找哪台服务器。域名是为了让人记住,最终要转换成 IP 地址 | +| **端口** `:8080` | 服务器的具体"门牌号" | **柜台编号**:3号柜台(默认不写) | 服务器上可能有多个服务,端口指定访问哪一个。HTTP 默认 80,HTTPS 默认 443 | +| **路径** `/path/page.html` | 服务器上的文件位置 | **货架位置**:日用品区/第三排 | 指定服务器上的具体资源位置 | +| **查询参数** `?id=123` | 附加信息 | **订单备注**:红色、XL码 | 传递给服务器的额外数据,如搜索关键词、页码等 | +| **锚点** `#section` | 页面内的位置 | **说明书页码**:翻到第5页 | 页面加载后自动滚动到指定位置,不发送给服务器 | + + + +::: info 💡 关键理解 +URL 的存在是为了让**人类**能记住和输入。计算机最终需要的是 **IP 地址**(就像快递员最终需要的是具体的仓库地址,而不是"Nike 官方店"这个名字)。 +::: + +--- + +## 2. 第二步:查"地址簿" —— DNS 查询 + +::: tip 🤔 核心问题 +**为什么浏览器能找到网站?** 你输入的是人类可读的域名(如 `baidu.com`),但计算机真正需要的是数字地址(IP)。这中间发生了什么? +::: + +### 生活比喻:查仓库地址 + +你下单写的是"Nike 官方店",但物流系统不知道仓库在哪。它需要查地址簿: + +1. 先查**常用地址**(最近买过这家吗)→ 浏览器缓存 +2. 没有的话问**小区快递点**(他们知道大区域的分配)→ 本地 DNS 服务器 +3. 问**总部调度中心**(知道.com类店铺归谁管)→ 根域名服务器 +4. 问**品牌管理处**(最终找到 Nike 店铺的真实发货仓库)→ 权威域名服务器 + +### 真实过程:DNS 分层查询 + +**DNS(Domain Name System,域名系统)**是互联网的"分布式地址簿查询系统"。由于全球有数十亿个域名,采用分层架构来分散查询压力: + +``` +你(浏览器) + ↓ 问:google.com 的 IP 是多少? +本地 DNS 服务器(你的网络运营商,如电信/联通) + ↓ 问:.com 归谁管? +根域名服务器(全球13组根服务器,管理所有顶级域) + ↓ 告诉:去问 .com 的管理者 +顶级域服务器(Verisign 管理 .com) + ↓ 告诉:去问 google.com 的管理者 +权威域名服务器(Google 自己的 DNS 服务器) + ↓ 告诉:google.com 的 IP 是 142.250.80.46 +返回 IP 地址给浏览器 +``` + +**查询类型说明:** + +- **递归查询(Recursive Query)**:浏览器只发一次请求,本地 DNS 负责层层查询后返回结果 +- **迭代查询(Iterative Query)**:每一层只告诉下一层去哪查,浏览器需要多次查询 +- **缓存机制**:查询结果会被缓存,下次直接返回,大大加速访问 + + + +::: info 💡 为什么需要这么多层? +想象一下如果全世界只有一个地址簿,几十亿人同时查,早就崩溃了。分层设计让每个层级只管理自己的"辖区",既高效又可靠。 + +这就是互联网设计的核心思想:**分布式系统**。 +::: + +--- + +## 3. 第三步:打电话确认 —— TCP 三次握手 + +::: tip 🤔 核心问题 +**为什么需要"三次握手"?** 找到服务器地址后,为什么不能直接发送数据?为什么要先进行三次通信? +::: + +### 生活比喻:建立物流通道 + +假设物流车直接开到仓库,结果: + +- 仓库关门了 → 白跑一趟 +- 仓库爆仓不接单 → 无法发货 +- 找不到卸货口 → 无法对接 + +**所以在真正发货之前,必须先建立可靠的运输通道**。 + +### 真实过程:TCP 三次握手 + +**TCP(Transmission Control Protocol,传输控制协议)**是确保数据可靠传输的规则。在传输商品(数据)前,必须通过"三次握手"建立连接: + +``` +客户端(你的电脑) 服务器(商家仓库) + | | + |--- SYN=1 --------------------->| 第1次:你好,我在家,准备收货!(SYN) + | | + |<-- SYN=1, ACK=1 ---------------| 第2次:收到!我也准备好发货了,你在家吗?(SYN-ACK) + | | + |--- ACK=1 --------------------->| 第3次:在的!请发货吧。(ACK) + | | + ===== 通道建立,开始发货 ===== +``` + +**为什么是三次,不是两次?** + +- **第一次(SYN)**:客户端证明自己能发送 +- **第二次(SYN-ACK)**:服务器证明自己能接收和发送 +- **第三次(ACK)**:客户端证明自己能接收 + +三次握手确保:**双方都能发、双方都能收** —— 四个条件都满足,才能可靠传输。 + +**TCP 还负责:** + +- **数据分包**:大数据拆成小数据包传输 +- **顺序重组**:确保数据包按正确顺序组装 +- **错误重传**:丢包后自动重新发送 +- **流量控制**:根据网络状况调整发送速度 + + + +> **HTTPS 的额外步骤**:如果是 HTTPS(安全的网站),在 TCP 握手后还会进行 **TLS 握手**(1-RTT 或 2-RTT),双方交换加密密钥,确保之后的对话内容只有双方能看懂,就像用暗语通话。 + +--- + +## 4. 第四步:"买家"和"商家"的对话 —— HTTP 请求与响应 + +::: tip 🤔 核心问题 +**浏览器和服务器在说什么?** 建立连接后,浏览器如何"告诉"服务器它想要什么?服务器又如何"回应"? +::: + +### 生活比喻:仓库发货 + +物流车到达仓库:"这是订单(HTTP请求),**我要取回商品(网页 HTML 源代码)!**" +仓库管理员核对:"订单有效,这是你要的包裹(**HTML 文件**),请拿好。" + +### 真实过程:HTTP 协议通信 + +**HTTP(HyperText Transfer Protocol,超文本传输协议)**是浏览器和服务器之间的"对话规则"。通道建立后,浏览器发送**取货请求**,**核心目标是拿回网页的源代码(HTML 文件)**: + +**HTTP 请求示例:** + +```http +GET /index.html HTTP/1.1 ← 请求方法 + 路径 + 协议版本 +Host: www.example.com ← 目标主机(支持虚拟主机,一台服务器可托管多个网站) +User-Agent: Chrome/120.0 ← 客户端标识(服务器可据此返回适配内容) +Accept: text/html,application/xhtml+xml ← 可接受的响应格式 +Accept-Language: zh-CN,zh;q=0.9 ← 偏好的语言 +Accept-Encoding: gzip, deflate ← 支持的压缩格式 +Connection: keep-alive ← 保持连接(复用 TCP 连接) +Cookie: session_id=abc123 ← 身份凭证 +``` + +::: tip 💡 开发者顿悟:这不就是 API 吗? +**一模一样!** +你平时写的 API 调用(`fetch` / `axios`)和浏览器访问网页,在 **HTTP 层面完全是同一个东西**。 + +它们都是发送一个请求,服务器返回一段文本数据。 + +- 如果服务器给的是 **HTML**,浏览器就把它**画出来**(变成网页)。 +- 如果服务器给的是 **JSON**,你的代码就把它**存起来**(用于逻辑处理)。 + +**根本就没有"两种"请求,只有同一种 HTTP 请求,只是返回的数据格式(Content-Type)不同而已。** +这也是为什么理解了 HTTP,你就理解了 90% 的后端 API 原理。 + +如果你想深入学习 API 开发,请参考 [API 章节](./api-intro.md)。 +::: + +**常见 HTTP 方法:** + +- `GET`:获取资源(安全、幂等,可被缓存) +- `POST`:提交数据(创建资源,如注册、登录) +- `PUT`:更新资源(完整替换) +- `PATCH`:部分更新资源 +- `DELETE`:删除资源 +- `HEAD`:获取响应头(不返回主体,用于检查资源是否存在) + +**服务器返回 HTTP 响应:** + +```http +HTTP/1.1 200 OK ← 协议版本 + 状态码 + 状态描述 +Date: Mon, 23 May 2025 12:00:00 GMT ← 服务器时间 +Content-Type: text/html; charset=UTF-8 ← 内容类型和编码 +Content-Length: 1234 ← 内容长度(字节) +Cache-Control: max-age=3600 ← 缓存策略 +Set-Cookie: user_id=xyz789 ← 设置 Cookie + +... ← 响应体(网页内容) +``` + +**HTTP 状态码分类:** + +| 状态码 | 类别 | 含义 | 生活类比 | +| ----------- | ---------- | ---------------- | -------------------------------- | +| **200** | 成功 | 请求成功处理 | "订单确认,马上发货" | +| **301/302** | 重定向 | 资源已移动 | "本店搬家了,请去新店下单" | +| **304** | 未修改 | 缓存仍有效 | "你上次买的还能用,不用重新发货" | +| **400** | 客户端错误 | 请求格式错误 | "订单填写模糊,看不懂" | +| **401** | 未授权 | 需要身份验证 | "请先出示会员卡" | +| **403** | 禁止访问 | 权限不足 | "非内部人员禁止入内" | +| **404** | 未找到 | 资源不存在 | "仓库里没这款商品" | +| **500** | 服务器错误 | 服务器内部错误 | "仓库起火了,暂时发不了货" | +| **502** | 网关错误 | 上游服务器无响应 | "总仓没货了,分仓也调不到" | +| **503** | 服务不可用 | 服务器过载或维护 | "爆单了,暂停接单" | + + + +--- + +## 5. 第五步:拆开"包裹" —— 浏览器渲染 + +::: tip 🤔 核心问题 +**代码怎么变成画面?** 服务器发来的是枯燥的 HTML/CSS/JavaScript 代码,浏览器如何把它们变成丰富多彩的网页? +::: + +### 生活比喻:拆箱与组装 + +你终于收到了快递包裹(HTTP 响应),但打开一看,里面不是现成的家具,而是一堆**零件**(HTML)和一本**组装说明书**(CSS)。作为"买家"(浏览器),你需要亲自动手组装: + +1. **拆开包装**:取出所有零件,核对清单(解析 HTML → DOM 树)。 +2. **阅读说明**:看懂说明书,知道哪个零件该装哪、什么颜色(解析 CSS → CSSOM 树)。 +3. **分类整理**:挑出需要组装的零件,扔掉包装泡沫(`display: none`),准备组装(构建渲染树)。 +4. **测量位置**:用尺子量好房间尺寸,决定每个家具具体摆在哪(布局/回流)。 +5. **上色装饰**:给家具刷漆、贴贴纸(绘制)。 +6. **最终展示**:打扫干净,开灯展示(合成)。 + +### 真实过程:浏览器渲染引擎 + +浏览器收到的是 **HTML/CSS/JavaScript 代码**(枯燥的文本),但它要变成**像素画面**(精美的网页)。这个过程叫做**渲染(Rendering)**,由浏览器的**渲染引擎**(如 Chrome 的 Blink、Safari 的 WebKit)执行。 + +#### 步骤1:解析 HTML → 构建 DOM 树 (零件清单) + +浏览器读取 HTML 字节流,将其解析为**DOM(Document Object Model,文档对象模型)树**。这就像把一堆散乱的零件整理成一个有层级关系的清单: + +```html + +
标题
+
内容
+``` + +```text +DOM 树结构: +Document + └─ html + └─ body + ├─ div.header ("标题") + └─ div.content ("内容") +``` + +#### 步骤2:解析 CSS → 构建 CSSOM 树 (说明书) + +浏览器解析所有的 CSS(内联、外部文件),构建**CSSOM(CSS Object Model)树**。这就像理解说明书上的样式规则: + +```css +.header { + color: blue; + font-size: 24px; +} /* 标题要是蓝色的 */ +.content { + display: none; +} /* 内容暂时隐藏 */ +``` + +#### 步骤3:合并 → 渲染树 (准备组装) + +DOM 树 + CSSOM 树 = **渲染树 (Render Tree)**。 +关键点:**只有"可见"的元素才会在渲染树中**。 + +- `.header`:在渲染树中(可见)。 +- `.content`:**不在**渲染树中(因为 `display: none`,就像被扔掉的包装纸,不需要组装)。 + +#### 步骤4:布局 (Layout / Reflow) —— 测量尺寸 + +浏览器计算渲染树中每个节点在屏幕上的**精确坐标和大小**。 + +- "这个标题框宽 100px,高 50px,放在屏幕左上角 (0,0) 位置。" +- 这个过程叫**重排 (Reflow)**。如果窗口大小变了(比如手机横屏),所有元素的位置都要重新计算,非常消耗性能。 + +#### 步骤5:绘制 (Paint) —— 上色 + +知道位置后,浏览器开始填充像素:画背景色、文字颜色、边框、阴影等。 + +#### 步骤6:合成 (Composite) —— 最终展示 + +现代浏览器会将页面分成多个**图层 (Layers)** 分别绘制(比如 3D 变换、滚动条独立图层),最后由 GPU 将它们像 Photoshop 图层一样叠加在一起,呈现在屏幕上。 + + + +::: info 💡 你知道吗? +**布局和绘制**是浏览器最忙碌的时候。网页里的元素越多、结构越复杂,浏览器就需要花更多时间来计算位置和上色。这就是为什么有的复杂网页打开会卡顿的原因。 +::: + +--- + +## 5.5 网页是怎么"生成"的?静态网站 vs 动态网站 + +::: tip 🤔 核心问题 +**网页内容从哪里来?** 前面我们讲了浏览器如何渲染页面,但服务器上的 HTML 文件是怎么来的?是提前做好还是现做? +::: + +前面我们讲的都是浏览器如何"拆开包裹"——把服务器发来的 HTML/CSS/JS 渲染成页面。但你有没有想过一个问题:**服务器上那个 HTML 文件是怎么来的?** + +答案是:**有两种方式**,这就是静态网站和动态网站的区别。 + +### 静态网站:提前做好、直接给你 + +想象你去超市买饼干。货架上的饼干都是工厂已经生产好的,你直接拿走就行,不需要等。 + +**静态网站**就是这样的"成品"——网页在服务器上已经准备好了,你访问时服务器直接把现成的 HTML 文件发给你,不做任何额外处理。 + +**特点:** +- ✅ 访问速度快(服务器直接发文件,不用计算) +- ✅ 制作简单(写好 HTML 就能用) +- ✅ 承载力强(可以用 CDN 分发,多少人访问都不怕) +- ❌ 内容难更新(想改内容就要重新生成文件) + +**常见例子:** 公司介绍页、产品文档、帮助中心、个人博客 + +### 动态网站:现点现做、每次不同 + +这次想象你去餐厅点餐。厨师根据你的订单现做,你点宫保鸡丁不会给你上糖醋里脊。 + +**动态网站**就是你访问时才"现场制作"的页面——服务器收到你的请求后,去数据库查资料、计算数据,然后生成一个全新的 HTML 发给你。 + +**特点:** +- ✅ 内容实时(购物车显示最新库存、新闻随时更新) +- ✅ 因人而异(登录后看到你的个人信息) +- ✅ 功能强大(搜索、评论、推荐、支付都能实现) +- ❌ 访问速度慢(服务器需要时间计算) +- ❌ 服务器压力大(同时很多人访问要排队) + +**常见例子:** 淘宝、微博、在线银行、在线文档 + +**需要服务器吗?** 动态网站确实需要某种"后端"来生成内容,但形式多样: +- **传统服务器**:自己买/租服务器(阿里云 ECS、AWS EC2) +- **Serverless**:不用管服务器,云厂商帮你运行代码(AWS Lambda、阿里云函数计算、Cloudflare Workers) +- **调用第三方 API**:支付用 Stripe、天气用气象局 API,自己不写后端代码 + +::: tip 💡 静动态结合 +现在很多网站是"混合"的:网页主体是静态的,但某些部分(比如评论区、搜索框)是动态加载的。JavaScript 可以在页面加载后调用 API 获取数据,实现"静态页面 + 动态功能"。 +::: + +### 📊 静态 vs 动态,一对比就清楚 + +| | 静态网站 | 动态网站 | +|---|---------|---------| +| **怎么来的** | 提前做好,存服务器上 | 访问时现做 | +| **像什么** | 超市货架上的商品 | 餐厅现点的菜 | +| **速度** | 快 | 慢(需要计算) | +| **能改内容吗** | 难(要重新生成) | 容易(后台直接改) | +| **适合做什么** | 展示型内容(介绍页、文档) | 交互型应用(购物、社交) | +| **典型例子** | 公司官网、帮助文档 | 淘宝、微信、在线银行 | + +### 🤔 常见疑问 + +**Q: 静态网站是不是不能用 JavaScript?** + +当然不是!轮播图、折叠菜单、表单验证这些交互功能,静态网站都能用 JavaScript 实现。我们说的"静态""动态",是指**页面内容是不是提前准备好的**,跟有没有交互功能是两回事。 + +**Q: 动态网站一定要自己买服务器吗?** + +不一定。除了传统服务器,你还可以用 Serverless(云函数)、或者直接调用第三方 API。现在的趋势是"能不动服务器就不动"——用静态网站 + JavaScript 调用 API 的方式,既快又省成本。 + +::: tip 💡 重要提示 +无论静态网站还是动态网站,**浏览器渲染的原理都是一样的**!服务器发来的是什么,浏览器就渲染什么。区别只在于: +- 静态网站:服务器发来的是"成品" +- 动态网站:服务器发来的是"现做的" + +作为前端开发者,你主要关注的是浏览器如何处理收到的内容,而不是服务器怎么生成的。 +::: + +--- + +## 6. 总结:一次完整的"网购"之旅 + +::: tip 🎉 学完本章,你应该能 +- 解释从输入网址到显示页面的完整流程 +- 理解 URL、DNS、TCP、HTTP 的作用和关系 +- 知道浏览器如何渲染页面 +- 区分静态网站和动态网站 +- 用生活化比喻向他人解释浏览器工作原理 +::: + +让我们回顾整个旅程: + +| 阶段 | 技术术语 | 网购类比 | 核心任务 | 关键技术 | +| ----------- | ---------- | -------- | ------------------ | ------------------------------ | +| **1. 解析** | URL 解析 | 填写订单 | 理解买家想买什么 | 协议、域名、端口、路径、参数 | +| **2. 查询** | DNS 查询 | 查仓库址 | 找到店铺的发货仓库 | 递归/迭代查询、缓存机制 | +| **3. 连接** | TCP 握手 | 建立通道 | 确保物流通畅 | 三次握手、序列号、流量控制 | +| **4. 对话** | HTTP 交换 | 仓库发货 | 提交订单并收货 | 请求方法、状态码、头部字段 | +| **5. 展示** | 浏览器渲染 | 拆箱组装 | 把商品展示出来 | DOM、CSSOM、渲染树、布局、绘制 | + +**整个过程通常在几百毫秒内完成** —— 想想这有多么不可思议! + +你的浏览器在不到1秒的时间里: + +- 解析了一个复杂的地址 +- 查询了分布在全球的 DNS 服务器 +- 和千里之外的服务器建立了可靠连接 +- 进行了一次完整的 HTTP 对话 +- 把枯燥的代码变成了精美的画面 + +这就是互联网的魅力:**复杂的技术,简单的体验**。 + +::: info 💡 进阶学习 +如果你想深入了解某个环节,可以参考: +- **API 开发**:[API 简介](./api-intro.md) - 学习如何设计和使用 API +- **前端性能**:[前端性能优化](./frontend-performance.md) - 学习如何优化网页加载速度 +- **浏览器渲染**:[浏览器渲染管道](./browser-rendering-pipeline.md) - 深入了解渲染细节 +::: + +--- + +## 7. 名词速查表 (Glossary) + +| 名词 | 全称 | 简单解释 | +| ----------- | ----------------------------- | -------------------------------------------------------------------------- | +| **URL** | Uniform Resource Locator | **统一资源定位符**。网页的"地址",告诉浏览器去哪里找资源。 | +| **DNS** | Domain Name System | **域名系统**。互联网的"电话簿",把人类可读的域名转换成机器可读的 IP 地址。 | +| **IP 地址** | Internet Protocol Address | **互联网协议地址**。每台联网设备的唯一"门牌号",如 `192.168.1.1`。 | +| **TCP** | Transmission Control Protocol | **传输控制协议**。确保数据可靠传输的"规则",通过三次握手建立连接。 | +| **HTTP** | HyperText Transfer Protocol | **超文本传输协议**。浏览器和服务器"对话"的规则。 | +| **HTTPS** | HTTP Secure | **安全的 HTTP**。在 HTTP 基础上加了加密(TLS/SSL),保护数据安全。 | +| **HTML** | HyperText Markup Language | **超文本标记语言**。网页的"骨架",定义内容的结构。 | +| **CSS** | Cascading Style Sheets | **层叠样式表**。网页的"皮肤",定义内容的外观。 | +| **DOM** | Document Object Model | **文档对象模型**。浏览器把 HTML 转换成的树形结构,方便操作。 | +| **CSSOM** | CSS Object Model | **CSS 对象模型**。浏览器把 CSS 转换成的树形结构。 | +| **渲染** | Rendering | 浏览器把代码转换成屏幕像素的过程。 | +| **RTT** | Round Trip Time | **往返时间**。数据包从发送到接收确认的时间,影响网页加载速度。 | + +--- + +::: tip 🎓 恭喜 +现在当你再次在地址栏输入网址并按下回车时,你已经能看到屏幕背后的那个忙碌而精彩的数字世界了。 + +你理解了: +- 为什么有时候网页打不开(DNS 解析失败、服务器宕机) +- 为什么有的网页快、有的慢(网络延迟、服务器性能、页面复杂度) +- 浏览器是如何把代码变成画面的(渲染管道) + +**这就是理解技术原理的价值** — 遇到问题时,你能知道从哪里找原因,而不是束手无策。 +::: diff --git a/docs/zh-cn/appendix/frontend-engineering.md b/docs/zh-cn/appendix/3-browser-and-frontend/frontend-engineering.md similarity index 99% rename from docs/zh-cn/appendix/frontend-engineering.md rename to docs/zh-cn/appendix/3-browser-and-frontend/frontend-engineering.md index 859328f..6dfa524 100644 --- a/docs/zh-cn/appendix/frontend-engineering.md +++ b/docs/zh-cn/appendix/3-browser-and-frontend/frontend-engineering.md @@ -1,5 +1,4 @@ -# 前端工程化与构建流水线 - +# 前端工程化全貌 ::: tip 🎯 核心问题 **如何把你写的代码,变成用户浏览器能跑的网站?** 这就像是问:如何把原材料变成成品,还要保证质量、控制成本?本章将带你深入理解前端工程化的核心概念和构建流程。 ::: diff --git a/docs/zh-cn/appendix/3-browser-and-frontend/frontend-framework-nature.md b/docs/zh-cn/appendix/3-browser-and-frontend/frontend-framework-nature.md new file mode 100644 index 0000000..05c6aec --- /dev/null +++ b/docs/zh-cn/appendix/3-browser-and-frontend/frontend-framework-nature.md @@ -0,0 +1,3 @@ +# 前端框架的本质 + +> 待实现 diff --git a/docs/zh-cn/appendix/3-browser-and-frontend/frontend-frameworks.md b/docs/zh-cn/appendix/3-browser-and-frontend/frontend-frameworks.md new file mode 100644 index 0000000..2a2cfc9 --- /dev/null +++ b/docs/zh-cn/appendix/3-browser-and-frontend/frontend-frameworks.md @@ -0,0 +1,704 @@ +# 前端框架深度指南 + +::: tip 前言 +你已经学会了 HTML、CSS 和 JavaScript 基础,能做出简单的网页了。但随着网页功能越来越复杂,你可能会发现:用原生 JavaScript 写代码变得很难维护,改一处要动很多地方,多人协作时经常冲突。 + +这就是我们需要前端框架的原因——它让代码更有条理、更易维护、更高效开发。在 vibecoding 里,AI 会帮你写大部分代码。但你至少得能看懂不同框架的代码风格,知道它们的优缺点,这样 AI 才能帮你选择最合适的技术栈。 + +读完这篇,你就能: +- 理解前端技术为什么要不断演进 +- 知道 Vue、React、Svelte、Angular 各有什么特点 +- 懂得"数据驱动"、"组件化"这些核心概念 +- 能根据项目选择合适的框架 +::: + +**这篇文章会带你学什么?** + +| 章节 | 内容 | 学完能干嘛 | +|-----|------|-----------| +| **第 1 章** | 为什么要关注前端演进 | 明白技术演进是为了解决什么问题 | +| **第 2 章** | 静态网页时代 | 了解最早期的网页开发方式 | +| **第 3 章** | jQuery 时代 | 理解"命令式"编程的痛点 | +| **第 4 章** | Vue/React 时代 | 掌握"声明式"和"数据驱动"思想 | +| **第 5 章** | 渲染策略 | 知道 CSR、SSR、SSG 的区别和适用场景 | +| **第 6 章** | 工程化工具 | 理解 Webpack、Vite 等构建工具的作用 | + +每一章都从"为什么需要这个技术"开始,让你理解技术演进背后的逻辑。 + +--- + +## 1. 为什么要关注前端演进史? + +::: tip 🤔 核心问题 +**为什么网页越来越复杂?前端技术为什么要不断演进?** 这个问题会带你理解从简单网页到现代 Web 应用的技术演变之路。 +::: + +### 1.1 从"电子海报"到"桌面应用" + +想象一下你在街上看到的**海报**: + +- ✅ 有内容(文字、图片) +- ✅ 有设计(颜色、排版) +- ❌ 但你跟它说话,它不会回应 +- ❌ 你点击某个地方,不会发生什么 + +**最早的网页**就是这样的"电子海报":只能看、不能改、内容固定。 + +**现代网页**完全不同了。它们像**桌面应用**(VS Code、Figma): + +- ✅ 可以编辑文档、画图、玩游戏 +- ✅ 实时响应你的每个操作 +- ✅ 甚至可以离线工作 + +**这种转变的核心原因:网页的功能越来越复杂,需要更高效的技术和开发方式。** + +### 1.2 一个生活的比喻:盖房子 + +前端技术的演进,就像盖房子方式的进化: + +| 时代 | 🏠 盖房比喻 | 实际特点 | 优缺点 | +|------|-----------|---------|--------| +| **2000s** | **贴海报** | 静态网页,写好 HTML 就行 | ✅ 简单 ❌ 不能互动 | +| **2010s** | **请工人手动装修** | jQuery 时代,手动操作每个元素 | ✅ 能互动 ❌ 代码乱、难维护 | +| **2020s** | **用乐高搭房子** | Vue/React 时代,组件化开发 | ✅ 高效、可维护 ❌ 学习曲线 | + +::: tip 💡 从表格中你能看到什么? + +**阶段一 → 阶段二**:从"不能动"到"能动"。这是质的飞跃——网页开始有交互,但代价是代码变得混乱。 + +**阶段二 → 阶段三**:从"能用"到"好用"。组件化让代码像积木一样可复用,大幅提升开发效率。 + +**核心思想**:技术演进不是"为了新而新",而是为了解决上一个阶段的痛点。 +::: + +--- + +--- + +## 2. 第一阶段:静态网页与"切图"(2000s) + +::: tip 🤔 核心问题 +**最早的网页是什么样的?为什么那时候不需要框架?** 理解这个阶段的局限性,才能明白后来技术演进的必要性。 +::: + + + +### 2.1 这个时代是什么样的? + +**开发方式**: + +- 写几个 HTML 文件 +- 内嵌一些 CSS 和 JavaScript +- 直接把文件拖到浏览器就能看效果 +- 上传文件夹到服务器就完成部署 + +**特点**: + +- ✅ **优点**:简单直接,没有学习成本,写完就能跑 +- ❌ **缺点**:无法实现复杂交互,代码一多就乱 + +::: details 查看当时的项目结构 + +``` +project/ +├── index.html +├── login.html +├── css/ +│ ├── bootstrap.css +│ └── custom.css +├── js/ +│ ├── jquery.js +│ └── app.js +└── images/ +``` + +**遇到的问题**: + +1. **全局变量污染**:所有变量都在全局命名空间,容易互相覆盖 +2. **依赖管理混乱**:必须按正确顺序加载 JS 文件,否则会报错 +3. **代码难以复用**:想复用某个功能,只能复制粘贴 +::: + +### 2.2 "切图"是什么? + +你可能听说过"切图"这个词。它是早期前端的主要工作: + +**什么是切图?** + +设计师用 Photoshop 设计好页面 → 前端把设计切成小图片 → 用 HTML 把图片拼成页面 + +**为什么这么慢?** + +网页上的每张小图片,浏览器都要发一次**网络请求**。请求越多,加载越慢。 + +👇 **动手试试看**:观察图片请求对加载性能的影响 + + + +::: tip 💡 雪碧图(Sprite) + +为了减少请求数,出现了"雪碧图"技术:把很多小图合成一张大图。 + +优点是请求数变少,缺点是制作和维护都很麻烦。 + +这个阶段的教训:**请求太多是性能大敌**。 +::: + +--- + +--- + +## 3. 第二阶段:jQuery 时代 - "手动搬砖"(2010s) + +::: tip 🤔 核心问题 +**为什么需要 jQuery?它解决了什么问题,又带来了什么新问题?** 理解 jQuery 的局限性,才能明白 Vue/React 的价值。 +::: + +### 3.1 为什么需要 jQuery? + +随着网页变复杂,原生 JavaScript 的问题暴露出来: + +- ❌ **API 繁琐**:简单的操作也要写很多代码 +- ❌ **浏览器兼容**:不同浏览器的 API 不一样,要写很多兼容代码 +- ❌ **选择器弱**:找元素很麻烦 + +**jQuery** 诞生了。它让 JavaScript 变得简单: + +```javascript +// 原生 JavaScript(繁琐) +const element = document.getElementById('title') + +// jQuery(简洁) +const element = $('#title') +``` + +### 3.2 jQuery 的思路:亲手改页面 + +jQuery 的核心思路是**命令式**:你告诉浏览器"怎么做"。 + +```javascript +// 找到标题元素 +$('#title').text('新标题') + +// 找到按钮并禁用 +$('#submit-btn').attr('disabled', true) + +// 找到列表并添加一项 +$('ul').append('
  • 新项目
  • ') +``` + +**问题**:你需要记住页面上有哪些元素,每次数据变化都要手动更新所有相关元素。 + +👇 **动手试试看**:对比 jQuery 和数据驱动的方式 + + + +::: warning ⚠️ jQuery 的痛点 + +想象你在做一个购物车: + +```javascript +// 用户点击"添加到购物车" +function addToCart() { + cartCount++ // 数据变化 + + // 你要手动更新所有相关地方 + $('#cart-count').text(cartCount) // 右上角小红点 + $('#cart-page-count').text(cartCount) // 购物车页面 + $('#checkout-price').text(calculatePrice()) // 结算按钮 + + // 如果漏了一个地方,页面就不一致了! +} +``` + +**这就是"手动搬砖"的代价**:容易出错,难以维护。 +::: + +### 3.3 移动端普及:响应式设计的出现 + +这个阶段还有一个重要变化:**手机和平板开始流行**。 + +网页必须适配不同屏幕。这需要**响应式布局**:同一套 HTML/CSS,自动根据屏幕宽度变换布局。 + +**响应式布局的核心:媒体查询(Media Query)** + +```css +/* 电脑屏幕(大于 640px) */ +@media (min-width: 640px) { + .container { + display: flex; + } +} + +/* 手机屏幕(小于 640px) */ +@media (max-width: 640px) { + .container { + display: block; + } +} +``` + +👇 **动手试试看**:调整浏览器宽度,观察响应式布局的效果 + + + +::: tip 💡 响应式就像"智能相框" + +想象你在不同房间看同一张照片: + +- 在**大客厅**(电脑屏幕),照片可以摆大一些,旁边还能放其他装饰品 +- 在**小卧室**(手机屏幕),照片需要缩小,其他装饰品要收起来 + +**响应式布局**就是"智能相框",它会自动根据房间大小调整展示方式。 +::: + +--- + +--- + +## 4. 第三阶段:从"手动搬砖"到"数据驱动"(Vue/React) + +::: tip 🤔 核心问题 +**为什么需要 Vue/React?它们和 jQuery 的本质区别是什么?** 理解"声明式"和"数据驱动",是掌握现代前端框架的关键。 +::: + +### 4.1 为什么需要新框架? + +jQuery 时代的问题积累到一定程度: + +- **代码一多就乱**:到处都是 DOM 操作,难以维护 +- **容易出 bug**:漏更新一个地方,页面就不一致 +- **协作困难**:多人修改同一个文件,容易冲突 + +**Vue / React** 的核心思路:**只改数据,页面自动更新**。 + +### 4.2 Vue/React 的思路:声明式 UI + +**jQuery(命令式)**: + +```javascript +// 你要告诉浏览器每一步怎么做 +$('#title').text('新标题') +$('#title').css('color', 'red') +$('#title').show() +``` + +**Vue(声明式)**: + +```javascript +// 你只需告诉浏览器"要显示什么" +data() { + return { + title: "新标题", + color: "red", + visible: true + } +} +``` + +👇 **动手试试看**:对比命令式和声明式的区别 + + + +::: tip 💡 命令式 vs 声明式 + +就像画一幅画: + +- **命令式**:你告诉画家"拿起笔,蘸红颜料,在坐标(10,10)画一个圈" +- **声明式**:你直接给画家一张照片,"给我画成这样" + +Vue/React 就是"声明式":你描述"页面长什么样",框架负责"怎么把它画出来"。 +::: + +### 4.3 组件化:像搭乐高一样写页面 + +**Vue / React** 最强大的特性是**组件化**:把页面拆成一个个独立的"积木"。 + +想象一下你在搭乐高: + +- 你不需要"从头开始雕刻每一块积木"(从头写 HTML/CSS) +- 你只需要"按说明书把积木拼在一起"(把组件组合起来) +- 每个积木都是**独立的**,你可以在不同的套装里**重复使用** + +**组件的好处**: + +- **复用**:写一个"商品卡片"组件,可以用 100 次 +- **封装**:组件内部的状态不影响别人 +- **维护**:修改一个组件,所有用到它的地方都会更新 + +::: info 💡 识别技巧 +- 看到 `` → 这是一个组件 +- 看到 `import xxx from './xxx.vue'` → 在导入一个组件 +- 看到 `props: {...}` → 组件接收的参数 +- 看到 `emit('xxx')` → 组件向父组件发送事件 +::: + +### 4.4 SPA:单页应用的诞生 + +**Vue / React** 时代还有一个重要变化:**从 MPA 到 SPA**。 + +**MPA(Multi-Page Application)**: + +- 点一个链接 → 整页刷新 → 显示新页面 +- 就像**翻书**:每翻一页都要把旧书合上、去书架拿新书 + +**SPA(Single-Page Application)**: + +- 点一个链接 → 只刷新内容区域 → 页面不刷新 +- 就像**同一本书里换章节**:只擦掉旧内容、写上新内容 + +👇 **动手试试看**:体验 MPA 和 SPA 的区别 + + + +**SPA 的优点**: + +- ✅ **体验丝滑**:页面切换快 +- ✅ **状态好管理**:输入的内容、滚动位置都在 +- ❌ **首屏可能慢**:需要先下载 JavaScript +- ❌ **SEO 要额外处理**:搜索引擎可能抓不到内容(需要 SSR/SSG) + +--- + +--- + +## 5. 渲染策略:从 CSR 到 SSR/SSG + +::: tip 🤔 核心问题 +**页面是在服务器生成,还是在浏览器生成?** 不同渲染策略各有优劣,选择合适的策略对性能和 SEO 至关重要。 +::: + +**CSR(Client-Side Rendering)客户端渲染**: + +- 浏览器下载 JavaScript → 执行代码 → 生成页面 +- 优点:交互流畅,服务器压力小 +- 缺点:首屏慢,不利于 SEO + +**SSR(Server-Side Rendering)服务端渲染**: + +- 服务器生成 HTML → 发给浏览器 → 浏览器直接显示 +- 优点:首屏快,利于 SEO +- 缺点:服务器压力大,实现复杂 + +**SSG(Static Site Generation)静态站点生成**: + +- 构建时生成所有页面的 HTML +- 优点:极快,完全静态,CDN 友好 +- 缺点:不适合动态内容 + +👇 **动手试试看**:对比不同渲染策略的特点 + + + +::: info 💡 如何选择? +- **内容网站**(博客、文档):优先 SSG +- **需要 SEO 的动态网站**(电商、新闻):使用 SSR +- **后台管理系统**:使用 CSR +- **混合需求**:考虑 Nuxt/Next.js 的混合渲染 +::: + +--- + +## 6. 第四阶段:工程化与构建工具(2015s-2020s) + +::: tip 🤔 核心问题 +**为什么前端需要"工程化"?构建工具到底在做什么?** 理解工程化,才能看懂现代前端项目的工作流程。 +::: + +### 6.1 为什么需要"工程化"? + +前端项目越来越大,不能再靠"手动引入脚本"。 + +**工程化**就是用工具和规范,让开发更高效、代码更可靠、协作更顺畅。 + +::: tip 💡 工程化 = 从"手工作坊"到"现代化工厂" + +想象一下你在家做饭 vs 开餐厅: + +- **在家做饭**:想吃什么就做什么,很自由 +- **开餐厅**:需要标准化的菜谱、规范的操作流程、统一的原材料采购 + +前端开发也一样: + +- **小项目**:怎么写都行 +- **大项目**:需要统一的代码规范、自动化工具、标准化流程 +::: + +### 6.2 构建工具:Webpack → Vite + +**Webpack**(传统): + +- 工作方式:**先打包,后服务** +- 启动时:打包所有代码 → 启动服务器 +- 问题:**慢**。项目越大,启动越慢(可能要等 30 秒) + +**Vite**(现代): + +- 工作方式:**按需编译** +- 启动时:不打包,直接启动服务器 +- 浏览器请求哪个文件,就实时编译哪个 +- 优势:**快**。通常 1 秒内启动 + +| 对比项 | Webpack | Vite | 提升 | +|--------|---------|------|------| +| 冷启动 | 30s+ | <1s | **快 30 倍** | +| 热更新 | 3-5s | <100ms | **快 30 倍** | +| 配置文件 | 几百行 | 几十行 | **大幅简化** | + +::: tip 💡 为什么 Vite 这么快? + +**Webpack** 就像**整备家当搬家**:先把所有东西打包,再出门。 + +**Vite** 就像**轻装旅行**:只带必需品,用到什么再买什么。 + +在开发环境,大多数时候你只需要修改几个文件,Vite 只编译这几个文件,当然快。 +::: + +--- + +--- + +## 7. 主流框架对比 + +::: tip 🤔 核心问题 +**Vue、React、Svelte、Angular 各有什么特点?如何选择适合自己的框架?** 了解它们的设计理念和使用场景,才能做出明智的选择。 +::: + +### 7.1 四大框架对比 + +| 特性 | Vue | React | Svelte | Angular | +|------|-----|-------|--------|---------| +| **设计理念** | 渐进式框架 | UI 库 | 编译时框架 | 完整平台 | +| **学习曲线** | ⭐⭐ 简单 | ⭐⭐⭐ 中等 | ⭐⭐ 简单 | ⭐⭐⭐⭐ 陡峭 | +| **性能** | 快 | 快 | **极快** | 快 | +| **生态系统** | 完善 | **最完善** | 成长中 | 完善 | +| **包大小** | 小 | 中等 | **最小** | 大 | +| **适合场景** | 中小型项目 | 大型项目 | 性能要求高 | 企业级应用 | +| **公司支持** | 尤雨溪(独立) | Meta | 社区 | Google | + +### 7.2 Vue:渐进式框架 + +**核心理念**:渐进式采用,可以只用一部分,也可以用全家桶 + +```vue + + + +``` + +**优点**: +- ✅ 学习曲线平缓,中文文档完善 +- ✅ 模板语法直观,易于理解 +- ✅ 单文件组件(.vue)结构清晰 +- ✅ 适合快速开发 + +**缺点**: +- ❌ 大型项目的状态管理需要额外学习 Vuex/Pinia +- ❌ 灵活性略逊于 React + +**适用场景**: +- 中小型 Web 应用 +- 快速原型开发 +- 中文团队(文档友好) + +### 7.3 React:UI 库 + +**核心理念**:只负责视图层,其他问题交给社区 + +```jsx +function App() { + const [message, setMessage] = useState('Hello React') + return
    {message}
    +} +``` + +**优点**: +- ✅ 生态系统最完善,组件库丰富 +- ✅ JSX 语法灵活,表达能力强大 +- ✅ 虚拟 DOM 性能优秀 +- ✅ 适合大型项目 + +**缺点**: +- ❌ 学习曲线较陡,需要掌握额外概念 +- ❌ 需要自己选择和搭配各种库 +- ❌ JSX 需要编译,不能直接在浏览器运行 + +**适用场景**: +- 大型复杂应用 +- 需要丰富生态的项目 +- 跨平台开发(React Native) + +### 7.4 Svelte:编译时框架 + +**核心理念**:没有虚拟 DOM,编译时将组件转换为高效的原生代码 + +```svelte + + +
    {message}
    +``` + +**优点**: +- ✅ **性能最优**(无虚拟 DOM 运行时开销) +- ✅ 包体积最小 +- ✅ 语法简单直观 +- ✅ 响应式系统天然支持 + +**缺点**: +- ❌ 生态相对较小 +- ❌ 社区规模不如 Vue/React +- ❌ 第三方库较少 + +**适用场景**: +- 性能要求极高的应用 +- 包体积敏感的项目 +- 愿意尝试新技术的团队 + +### 7.5 Angular:完整平台 + +**核心理念**:提供完整的解决方案,开箱即用 + +```typescript +@Component({ + selector: 'app-root', + template: '
    {{ message }}
    ' +}) +export class AppComponent { + message = 'Hello Angular' +} +``` + +**优点**: +- ✅ 功能完整,路由、HTTP、表单全都有 +- ✅ TypeScript 原生支持 +- ✅ 适合大型团队和项目 +- ✅ 代码规范统一 + +**缺点**: +- ❌ 学习曲线陡峭 +- ❌ 概念多,复杂度高 +- ❌ 包体积大 +- ❌ 不适合小型项目 + +**适用场景**: +- 大型企业级应用 +- 需要严格规范的团队 +- 已有 TypeScript 技术栈的项目 + +--- + +## 8. 总结:演进的本质 + +前端技术的演进,本质上是在解决两个问题: + +### 8.1 效率:从手动到自动 + +| 时代 | 开发方式 | 效率 | +|------|---------|------| +| **2000s** | 手写 HTML/CSS/JS | ⭐ | +| **2010s** | jQuery + 手动 DOM 操作 | ⭐⭐ | +| **2020s** | Vue/React + 数据驱动 | ⭐⭐⭐ | +| **现在** | 组件化 + 工程化 + 自动化 | ⭐⭐⭐⭐⭐ | + +### 8.2 规模:从个人到团队 + +| 时代 | 项目规模 | 协作方式 | +|------|---------|---------| +| **2000s** | 几个文件 | 单人就能维护 | +| **2010s** | 几十个文件 | 小团队,容易冲突 | +| **2020s** | 几百个文件 | 中团队,需要规范 | +| **现在** | 几千个文件 | 大团队,需要完整工程体系 | + +--- + +--- + +## 9. 学习路线图 + +### 9.1 如果你是零基础 + +**第 1 步:HTML/CSS/JavaScript 基础** + +- 理解网页的三大基石 +- 能写出简单的静态页面 + +**第 2 步:学习一个框架(Vue 推荐)** + +- 理解"数据驱动"的思想 +- 掌握组件化开发 + +**第 3 步:实战项目** + +- 做一个完整的单页应用 +- 熟悉路由、状态管理、API 调用 + +### 9.2 如果你有基础 + +**进阶方向**: + +- **工程化**:学习 Vite/Webpack,理解构建流程 +- **性能优化**:学习懒加载、代码分割、缓存策略 +- **TypeScript**:为代码加上类型,提升可靠性 +- **服务端渲染**:学习 Nuxt/Next.js,解决 SEO 和首屏问题 + +--- + +## 10. 你现在应该能识别的代码 + +通过阅读本章,你应该能够: + +- ✅ 理解前端技术演进的脉络和原因 +- ✅ 区分 Vue、React、Svelte、Angular 的特点 +- ✅ 理解"命令式"和"声明式"的区别 +- ✅ 掌握"数据驱动"的核心思想 +- ✅ 知道组件化开发的价值 +- ✅ 了解 CSR、SSR、SSG 的适用场景 +- ✅ 理解构建工具(Webpack、Vite)的作用 +- ✅ 能根据项目选择合适的框架和技术栈 + +::: info 💡 实际应用 +当你用 AI 做项目时,你可以这样告诉它: + +- "这是一个需要 SEO 的博客网站,用 Nuxt(Vue 的 SSR 框架)" +- "这是一个后台管理系统,用 Vue + Element Plus,不需要 SSR" +- "这是一个性能要求高的 Web 应用,考虑使用 Svelte" +- "项目已经用 React 了,继续用 React 生态的库" +::: + +--- + +## 名词速查表 + +| 名词 | 英文 | 用人话解释 | +|------|------|-----------| +| **DOM** | Document Object Model | 文档对象模型。用对象树表示页面,可被 JS 读写。 | +| **jQuery** | - | 早期流行的 JS 库,简化了 DOM 操作。 | +| **Vue/React** | - | 现代前端框架,采用数据驱动和组件化开发。 | +| **组件** | Component | 可复用的 UI 单元,如按钮、卡片、导航栏。 | +| **MPA** | Multi-Page Application | 多页应用。每次跳转都重新加载整个页面。 | +| **SPA** | Single-Page Application | 单页应用。只加载一次,后续切换不刷新页面。 | +| **路由** | Routing | 管理页面之间切换的规则和过程。 | +| **SSR** | Server-Side Rendering | 服务端渲染。服务器生成 HTML 后发给浏览器。 | +| **SSG** | Static Site Generation | 静态站点生成。构建时预渲染页面为静态 HTML。 | +| **CSR** | Client-Side Rendering | 客户端渲染。浏览器通过 JS 生成页面。 | +| **Webpack** | - | 传统打包工具,先打包后服务。 | +| **Vite** | - | 现代构建工具,按需编译,速度极快。 | +| **响应式** | Responsive Design | 页面自动适配不同屏幕尺寸的设计。 | +| **媒体查询** | Media Query | CSS 的条件判断,根据屏幕宽度应用不同样式。 | +| **命令式** | Imperative | 告诉程序"怎么做"。 | +| **声明式** | Declarative | 告诉程序"要什么"。 | +| **数据驱动** | Data-Driven | 只修改数据,界面自动更新。 | +| **Tree Shaking** | - | 摇树优化。自动移除未使用的代码,减小包体积。 | +| **代码分割** | Code Splitting | 把代码分成多个小块,按需加载。 | diff --git a/docs/zh-cn/appendix/3-browser-and-frontend/graphics-animation.md b/docs/zh-cn/appendix/3-browser-and-frontend/graphics-animation.md new file mode 100644 index 0000000..70e8127 --- /dev/null +++ b/docs/zh-cn/appendix/3-browser-and-frontend/graphics-animation.md @@ -0,0 +1,551 @@ +# 图形与动画(Canvas / SVG / WebGL) +::: tip 🎯 核心问题 +**如何在网页上画图、做动画、甚至开发游戏?** Canvas 提供了一个强大的 2D 绘图能力,让你用代码创造视觉内容。 +::: + +--- + +## 1. 为什么要学 Canvas? + +### 1.1 Canvas 是什么? + +**Canvas (画布)** 是 HTML5 提供的一个通过 JavaScript 绘制 2D 图形的元素。 + +你可以把它想象成一张**数字画布**: + +- 🖌️ 你可以用代码"画笔"在上面作画 +- 🎨 可以画任何东西: 简单的形状、复杂的图表、流畅的动画 +- 🎮 甚至可以做成完整的游戏 + +::: tip 💡 Canvas vs SVG:有什么区别? + +在 Web 开发中,绘制图形主要有两种方式: + +| 特性 | Canvas | SVG | +| -------- | -------------------- | --------------------- | +| **类型** | 位图(光栅图形) | 矢量图形 | +| **DOM** | 单个 `` 元素 | 每个图形都是 DOM 元素 | +| **交互** | 需要手动计算碰撞 | 天然支持事件绑定 | +| **性能** | 适合大量对象 | 适合少量复杂对象 | +| **缩放** | 放大会失真 | 无限缩放不失真 | +| **应用** | 游戏、数据可视化 | 图标、插画 | + +**简单总结**: + +- **Canvas** = 像素画,画完就变成像素,性能好但交互麻烦 +- **SVG** = 矢量图,每个图形都是对象,交互方便但对象多了会慢 + ::: + +### 1.2 Canvas 的应用场景 + +Canvas 的用途非常广泛,你可能每天都在用: + +1. **数据可视化**: ECharts、Chart.js 的图表 +2. **游戏开发**: 网页游戏(如 Phaser.js 引擎) +3. **图像处理**: 图片裁剪、滤镜、拼图(如 Fabric.js) +4. **创意效果**: 粒子特效、动画背景 +5. **工程绘图**: CAD、流程图、思维导图 + +--- + +## 2. Canvas 基础 + +### 2.1 Canvas 元素和上下文 + +使用 Canvas 的第一步是在 HTML 中创建一个 `` 元素: + +```html + +``` + +然后通过 JavaScript 获取**渲染上下文 (Rendering Context)**: + +```javascript +const canvas = document.getElementById('myCanvas') +const ctx = canvas.getContext('2d') // 获取 2D 上下文 +``` + +::: tip 💡 关键概念 + +- **canvas** 是 DOM 元素,控制画布的大小和位置 +- **ctx** 是绘图工具,所有的绘制操作都通过它完成 +- **`"2d"`** 表示使用 2D 渲染上下文(WebGL 使用 `"webgl"`) + ::: + +### 2.2 坐标系统:Canvas 的"地图规则" + +Canvas 使用的是**屏幕坐标系**,这与传统数学坐标系有所不同: + +- **原点 (0, 0)**: 在**左上角**(不是中心) +- **X 轴**: 向右为正方向 +- **Y 轴**: **向下**为正方向(注意: 数学坐标系中 Y 轴向上) +- **单位**: 像素 (px) + +```javascript +// 在左上角绘制一个矩形 +ctx.fillRect(0, 0, 10, 10) + +// 在右下角绘制一个矩形 +ctx.fillRect(canvas.width - 10, canvas.height - 10, 10, 10) +``` + +::: tip 💡 记忆技巧 + +想象你在看**屏幕**: + +- 向右移 → X 增加 ✅ +- 向下移(滚动页面) → Y 增加 ✅ +- 向左移 → X 减少 +- 向上移(向上滚动) → Y 减少 + +这就是 Canvas 的坐标规则。 +::: + +### 2.3 绘制基本形状 + +Canvas 提供了几种绘制基本形状的方法: + +**矩形**: + +```javascript +// 填充矩形 +ctx.fillStyle = '#3498db' +ctx.fillRect(x, y, width, height) + +// 描边矩形 +ctx.strokeStyle = '#2c3e50' +ctx.lineWidth = 2 +ctx.strokeRect(x, y, width, height) + +// 清除矩形区域 +ctx.clearRect(x, y, width, height) +``` + +**圆形**: + +```javascript +ctx.beginPath() +ctx.arc(x, y, radius, startAngle, endAngle) +ctx.fill() // 或 ctx.stroke() +``` + +**参数说明**: + +- **x, y**: 圆心坐标 +- **radius**: 半径 +- **startAngle, endAngle**: 起始和结束角度(弧度制) + - `0` = 3 点钟方向 + - `Math.PI / 2` = 6 点钟方向 + - `Math.PI` = 9 点钟方向 + +**线条**: + +```javascript +ctx.beginPath() +ctx.moveTo(x1, y1) // 起点 +ctx.lineTo(x2, y2) // 终点 +ctx.stroke() +``` + +### 2.4 颜色和样式 + +Canvas 支持多种颜色设置方式: + +```javascript +// 纯色 +ctx.fillStyle = '#3498db' // 十六进制 +ctx.fillStyle = 'rgb(52, 152, 219)' // RGB +ctx.fillStyle = 'rgba(52, 152, 219, 0.5)' // RGBA(带透明度) + +// 线性渐变 +const gradient = ctx.createLinearGradient(x1, y1, x2, y2) +gradient.addColorStop(0, '#3498db') +gradient.addColorStop(1, '#e74c3c') +ctx.fillStyle = gradient + +// 径向渐变 +const radialGradient = ctx.createRadialGradient(x1, y1, r1, x2, y2, r2) +radialGradient.addColorStop(0, '#3498db') +radialGradient.addColorStop(1, 'transparent') +ctx.fillStyle = radialGradient +``` + +--- + +## 3. 路径:Canvas 的"笔画" + +### 3.1 什么是路径? + +**路径 (Path)** 是 Canvas 中的核心概念。你可以把它想象成用笔画线的过程: + +1. **`beginPath()`** - 开始新路径(拿起笔) +2. **`moveTo()`** - 移动到起点(不画线) +3. **`lineTo()` / `arc()`** - 绘制线条或曲线 +4. **`closePath()`** - 闭合路径(可选) +5. **`fill()` / `stroke()`** - 填充或描边 + +```javascript +ctx.beginPath() +ctx.moveTo(100, 100) // 移动到起点 +ctx.lineTo(200, 100) // 画横线 +ctx.lineTo(150, 150) // 画斜线 +ctx.closePath() // 闭合路径(回到起点) +ctx.fill() // 填充 +``` + +### 3.2 绘制复杂形状 + +通过组合路径,可以绘制任意复杂的形状。 + +**三角形**: + +```javascript +ctx.beginPath() +ctx.moveTo(100, 50) +ctx.lineTo(150, 150) +ctx.lineTo(50, 150) +ctx.closePath() +ctx.fillStyle = '#e74c3c' +ctx.fill() +``` + +--- + +## 4. 动画基础 + +### 4.1 动画循环 + +在 Canvas 中创建动画,核心是使用 **`requestAnimationFrame`** 方法。 + +```javascript +function animate() { + // 1. 清除画布(或绘制半透明背景产生拖尾效果) + ctx.clearRect(0, 0, canvas.width, canvas.height) + + // 2. 更新状态 + update() + + // 3. 绘制 + draw() + + // 4. 请求下一帧 + requestAnimationFrame(animate) +} + +// 启动动画 +animate() +``` + +::: tip 💡 为什么用 requestAnimationFrame 而不是 setInterval? + +- ✅ 自动优化,通常为 60FPS(每秒 60 帧) +- ✅ 页面不可见时自动暂停,节省资源 +- ✅ 与浏览器刷新周期同步,避免画面撕裂 + ::: + +### 4.2 动画的本质 + +动画的本质是**快速连续绘制静态画面**。每帧需要: + +1. **清除旧画面**: `ctx.clearRect()` 或用半透明背景覆盖 +2. **更新状态**: 计算新位置、新角度等 +3. **绘制新画面**: 重新绘制所有对象 + +```javascript +// 清除画布 +ctx.clearRect(0, 0, canvas.width, canvas.height) + +// 半透明背景(产生拖尾效果) +ctx.fillStyle = 'rgba(255, 255, 255, 0.1)' +ctx.fillRect(0, 0, canvas.width, canvas.height) +``` + +--- + +## 5. 事件处理 + +Canvas 只是一个 DOM 元素,不像 SVG 那样每个图形都是独立的 DOM 元素。因此,我们需要**手动处理交互事件**。 + +### 5.1 鼠标事件 + +```javascript +canvas.addEventListener('click', (e) => { + const rect = canvas.getBoundingClientRect() + const x = e.clientX - rect.left + const y = e.clientY - rect.top + + console.log(`Clicked at (${x}, ${y})`) +}) + +canvas.addEventListener('mousemove', (e) => { + const rect = canvas.getBoundingClientRect() + const x = e.clientX - rect.left + const y = e.clientY - rect.top + + // 检测是否悬停在某个对象上 + objects.forEach((obj) => { + const dist = Math.sqrt((x - obj.x) ** 2 + (y - obj.y) ** 2) + if (dist < obj.radius) { + canvas.style.cursor = 'pointer' + obj.hovered = true + } + }) +}) +``` + +### 5.2 拖拽实现 + +```javascript +let isDragging = false +let selectedObject = null + +canvas.addEventListener('mousedown', (e) => { + const { x, y } = getMousePos(e) + + objects.forEach((obj) => { + const dist = Math.sqrt((x - obj.x) ** 2 + (y - obj.y) ** 2) + if (dist < obj.radius) { + isDragging = true + selectedObject = obj + } + }) +}) + +canvas.addEventListener('mousemove', (e) => { + if (isDragging && selectedObject) { + const { x, y } = getMousePos(e) + selectedObject.x = x + selectedObject.y = y + draw() // 重绘 + } +}) + +canvas.addEventListener('mouseup', () => { + isDragging = false + selectedObject = null +}) +``` + +--- + +## 6. 性能优化 + +随着绘制的对象增多,Canvas 性能会下降。以下是一些常用的优化技巧: + +### 6.1 离屏 Canvas (Offscreen Canvas) + +预渲染静态内容到离屏 Canvas,减少每帧的绘制操作: + +```javascript +// 创建离屏 Canvas +const offscreenCanvas = document.createElement('canvas') +const offscreenCtx = offscreenCanvas.getContext('2d') +offscreenCanvas.width = 600 +offscreenCanvas.height = 400 + +// 预渲染背景 +function drawBackground(ctx) { + ctx.fillStyle = '#f0f0f0' + ctx.fillRect(0, 0, 600, 400) +} +drawBackground(offscreenCtx) + +// 主渲染循环 +function draw() { + // 直接复制预渲染的背景 + ctx.drawImage(offscreenCanvas, 0, 0) + + // 只绘制动态对象 + objects.forEach((obj) => obj.draw(ctx)) +} +``` + +### 6.2 减少重绘(脏矩形优化) + +只重绘变化的部分: + +```javascript +function draw() { + objects.forEach((obj) => { + if (obj.moved) { + // 清除旧位置 + ctx.clearRect( + obj.oldX - obj.size, + obj.oldY - obj.size, + obj.size * 2, + obj.size * 2 + ) + + // 绘制新位置 + obj.draw(ctx) + + obj.moved = false + } + }) +} +``` + +### 6.3 批量渲染 + +减少状态切换(fillStyle、strokeStyle 等): + +```javascript +// 按颜色分组 +const batches = {} +objects.forEach((obj) => { + if (!batches[obj.color]) { + batches[obj.color] = [] + } + batches[obj.color].push(obj) +}) + +// 批量绘制相同颜色的对象 +Object.keys(batches).forEach((color) => { + ctx.fillStyle = color // 只设置一次颜色 + batches[color].forEach((obj) => { + ctx.beginPath() + ctx.arc(obj.x, obj.y, obj.size, 0, Math.PI * 2) + ctx.fill() + }) +}) +``` + +--- + +## 7. 常见库与框架 + +虽然原生 Canvas 已经很强大,但在实际项目中,使用成熟的库可以大大提高开发效率。 + +### 7.1 Fabric.js + +**特点**: 对象模型,支持交互 + +```javascript +const canvas = new fabric.Canvas('c') + +// 创建圆形 +const circle = new fabric.Circle({ + radius: 20, + fill: '#3498db', + left: 100, + top: 100 +}) + +canvas.add(circle) + +// 自动处理事件 +circle.on('click', () => { + circle.set('fill', '#e74c3c') + canvas.renderAll() +}) +``` + +**适用场景**: 图片编辑器、白板工具、图形设计工具 + +### 7.2 PixiJS (WebGL) + +**特点**: WebGL 加速,超高性能 + +```javascript +const app = new PIXI.Application({ + width: 600, + height: 400, + backgroundColor: 0x1099bb +}) +document.body.appendChild(app.view) + +const graphics = new PIXI.Graphics() +graphics.beginFill(0x3498db) +graphics.drawCircle(300, 200, 50) +graphics.endFill() +app.stage.addChild(graphics) +``` + +**适用场景**: 大型游戏、粒子系统、大量对象的场景 + +--- + +## 8. 总结与最佳实践 + +### 8.1 核心要点回顾 + +1. **Canvas 是位图画布**: 绘制后就是像素,无法直接修改已有内容 +2. **坐标系统**: 原点在左上角,Y 轴向下为正 +3. **路径系统**: beginPath → moveTo → lineTo → fill/stroke +4. **动画原理**: 清除 → 更新 → 绘制 → requestAnimationFrame +5. **事件处理**: 需要手动计算碰撞 +6. **性能优化**: 离屏 Canvas、脏矩形、批量渲染 + +### 8.2 最佳实践 + +**代码组织**: + +```javascript +// 使用类封装对象 +class GameObject { + constructor(x, y) { + this.x = x + this.y = y + } + + update() { + // 更新状态 + } + + draw(ctx) { + // 绘制 + } + + isHit(x, y) { + // 碰撞检测 + const dist = Math.sqrt((x - this.x) ** 2 + (y - this.y) ** 2) + return dist < this.radius + } +} +``` + +**性能优化清单**: + +- ✅ 使用 `requestAnimationFrame` 而不是 `setInterval` +- ✅ 减少状态切换(按颜色分组绘制) +- ✅ 使用离屏 Canvas 预渲染静态内容 +- ✅ 只重绘变化的部分(脏矩形) +- ✅ 限制对象数量,使用对象池 +- ✅ 避免 `save()` 和 `restore()` 的频繁调用 + +--- + +## 9. 名词速查表 (Glossary) + +| 名词 | 解释 | +| ------------------------- | ----------------------------------------------------------------------- | +| **Context / 上下文** | Canvas 的渲染环境,通过 `getContext("2d")` 获取,所有绘制操作都通过它完成 | +| **Path / 路径** | 由一系列点连接成的轨迹,是 Canvas 绘图的基础 | +| **Stroke / 描边** | 绘制路径的轮廓线 | +| **Fill / 填充** | 用颜色填充路径内部 | +| **requestAnimationFrame** | 浏览器提供的动画 API,在每次重绘前调用回调函数 | +| **Offscreen Canvas** | 离屏 Canvas,用于预渲染静态内容以提高性能 | +| **Dirty Rect** | 脏矩形优化,只重绘变化的部分 | +| **Collision Detection** | 碰撞检测,判断鼠标或对象是否点击了某个图形 | +| **Raster vs Vector** | 位图 vs 矢量图,Canvas 是位图,SVG 是矢量图 | + +--- + +## 总结 + +现在你已经掌握了 Canvas 2D 的核心概念: + +- **基本绘图**: 矩形、圆形、线条 +- **样式控制**: 颜色、渐变、阴影 +- **动画制作**: requestAnimationFrame + 清除重绘 +- **交互处理**: 鼠标事件、碰撞检测 +- **性能优化**: 离屏 Canvas、批量渲染 + +**下一步建议**: + +- 如果你想深入学习动画,可以尝试制作一个**贪吃蛇游戏**或**打砖块游戏** +- 如果你对数据可视化感兴趣,可以学习 **ECharts** 或 **D3.js** +- 如果你想做游戏开发,可以尝试 **Phaser.js** 游戏引擎 +- 如果你对 WebGL 感兴趣,可以学习 **Three.js** 或 **PixiJS** + +祝你学习愉快! 🎨 diff --git a/docs/zh-cn/appendix/3-browser-and-frontend/html-css-layout.md b/docs/zh-cn/appendix/3-browser-and-frontend/html-css-layout.md new file mode 100644 index 0000000..5e1c627 --- /dev/null +++ b/docs/zh-cn/appendix/3-browser-and-frontend/html-css-layout.md @@ -0,0 +1,1313 @@ +# HTML / CSS 布局体系 +::: tip 🎯 核心问题 +**网页是怎么做出来的?为什么有的网页只有文字,有的却像应用一样可以交互?** 这个问题会引出 Web 开发的三大基石,让你理解每一个网页背后的结构。 +::: + +--- + +## 1. HTML、CSS、JavaScript 分别是什么? + +### 1.1 从静态网页到动态应用 + +想象一下你在街上看到的**海报**。你只能看,不能互动——海报不会因为你看了就改变内容,也不会因为你点了某个地方就弹出更多信息。 + +早期的网页就是这样的"电子海报":只能看、不能改、内容固定。 + +但现代网页完全不同了。它们像**桌面应用**一样: + +- 你可以点击、拖拽、输入、上传 +- 页面会根据你的操作实时变化 +- 可以像软件一样完成复杂任务(比如在线视频剪辑) + +**这种转变的核心原因,就是网页技术的三大基石:HTML + CSS + JavaScript**。 + +### 1.2 一个比喻:盖房子 + +| 技术 | 🏠 房子比喻 | 实际作用 | 具体例子 | +| -------------- | ------------------------ | -------------------- | ------------------------------------ | +| **HTML** | 房子的**结构和材料** | 定义网页的内容和层级 | 这是一面墙、这是一扇窗、这是一个房间 | +| **CSS** | 房子的**装修和外观** | 控制网页的样式和布局 | 墙刷成蓝色、窗户放在东边、地板铺瓷砖 | +| **JavaScript** | 房子的**电器和智能系统** | 让网页具备交互和逻辑 | 按开关灯亮了、开门窗帘自动拉开 | + +::: tip 💡 三者的关系 + +**HTML → CSS**:先有房子,才能装修。HTML 是基础,CSS 是美化。 + +**HTML + CSS → JavaScript**:先有房子和装修,才能装智能系统。JavaScript 会让"死"的页面变"活"。 + +**核心思想**:三者各司其职,缺一不可。只有 HTML 的页面很丑,只有 HTML+CSS 的页面不能互动,三者齐全才能做出像微信网页版、淘宝这样的"Web 应用"。 +::: + +### 1.3 动手试试看 + +👇 下面这个演示展示了 HTML/CSS/JavaScript 三者如何协作: + + + +--- + +## 2. HTML:网页的骨架 + +### 2.1 为什么需要 HTML? + +在 HTML 出现之前,互联网上的内容只是**纯文本**。就像你现在看的这段文字,没有任何格式、没有层级、没有链接。 + +纯文本的问题是什么? + +- ❌ **无法表达层级**:分不清哪是标题、哪是正文、哪是注释 +- ❌ **机器看不懂**:搜索引擎、屏幕阅读器(盲人用)无法理解内容 +- ❌ **无法交互**:没有链接、没有按钮、没有输入框 + +**HTML (HyperText Markup Language)** 就是为了解决这个问题诞生的。它用"标签"(tag)来标记内容的含义,让浏览器知道"这是什么"。 + +### 2.2 HTML 代码长什么样? + +HTML 的基本单位是"标签"(tag)。标签用尖括号 `< >` 包裹,成对出现: + +```html +

    这是标题

    +

    这是段落

    +这是链接 +``` + +**关键概念**: + +| 概念 | 解释 | 例子 | +|------|------|------| +| **标签** | 用尖括号包裹的标记 | `

    `、`

    ` | +| **元素** | 标签 + 内容的整体 | `

    标题

    ` | +| **属性** | 标签上的附加信息 | `href="url"`、`class="card"` | +| **嵌套** | 标签里再放标签 | `

    文字

    ` | + +### 2.3 如何看懂 HTML 代码? + +::: tip 🎯 零基础必读:看代码的方法 + +很多新手看到一堆 `` 就晕了。其实看 HTML 代码有**固定套路**: + +**第一步:找"最外层"** + +```html +
    ← 这是容器,里面装着内容 +

    标题

    +

    描述文字

    +
    +``` + +**第二步:看标签名猜含义** + +| 标签名 | 一眼记住 | 里面放什么 | +|--------|----------|------------| +| `
    ` | 大盒子 | 任何内容,用来分组 | +| `` | 小盒子 | 文字片段,用来标记 | +| `

    ` | 段落 | 一段文字 | +| `

    `-`

    ` | 标题 | 标题文字,数字越小越重要 | +| `` | 锚点/链接 | 可点击跳转的内容 | +| `` | 图片 | 不放内容,用 src 指向图片 | +| ` + +``` + +**语义化标签**(HTML5 新增,让页面含义更明确): + +```html +
    页面头部
    + +
    主要内容区
    +
    一篇文章
    + +
    页脚
    +``` + +::: tip 💡 为什么要用语义化标签? + +`
    ` 和 `
    ` 看起来效果一样,为什么要用后者? + +1. **SEO 友好**:搜索引擎能更好理解页面结构 +2. **可访问性**:屏幕阅读器能快速定位"导航""主要内容"等区域 +3. **代码可读性**:看到 `
    ` 一眼就知道是头部 + +**什么时候用 div?** 当没有合适的语义标签时。比如一个纯装饰性的容器。 +::: + +### 2.5 如何记住这么多 HTML 标签? + +::: tip 🎯 新手困惑 + +"HTML 标签有一百多个,怎么记得住?" + +**答案是:不需要全部记住。** 实际开发中,90% 的情况只用 20 个左右的标签。 +::: + +#### 按用途分类记忆 + +**一、页面结构类(画骨架)** + +| 标签 | 记忆口诀 | 用途 | +|------|----------|------| +| `
    ` | 头 | 页面或区块的头部 | +| `