Files
OpenCode 68a9071cf1 feat: reconcile local master with origin (exa/hot-platform hunters, leaks ledger, latest results)
Local branch had diverged from origin/master (sibling commits on the same base). Rewrote local history linearly on top of origin/master, folding in all local content: exa/hot-platform discovery hunters, leaks ledger, nightly sweep orchestrator, updated .gitignore and skill docs, plus the latest hunt output and vault state. Remote-only files (vault keys, channel scripts) were restored rather than dropped, so the resulting tree is a full union of both sides.
2026-08-07 12:53:47 +08:00

1 line
48 KiB
JSON
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{"repo": "anh627/easygame", "files": {"docs/.vitepress/theme/components/appendix/api-intro/ApiFunctionVsHttp.vue": {"64900140d8920e20989a8ac4227900703b4f73e8": {"t": 1785746538.0167036, "n": 17080, "h": "055825151fe86cb8", "c": "<template>\n <div class=\"api-compare-root\">\n <div class=\"demo-header\">\n <span class=\"title\">📚 函数 API vs HTTP API</span>\n <span class=\"subtitle\">本地调用 vs 网络请求,文档怎么看?</span>\n </div>\n\n <div class=\"control-panel\">\n <button\n v-for=\"tab in tabs\"\n :key=\"tab.id\"\n :class=\"['tab-btn', { active: activeTab === tab.id }]\"\n @click=\"activeTab = tab.id\"\n >\n {{ tab.icon }} {{ tab.name }}\n </button>\n </div>\n\n <div class=\"visualization-area\">\n <!-- 对比视图 -->\n <div v-if=\"activeTab === 'compare'\" class=\"compare-view\">\n <div class=\"compare-cards\">\n <div class=\"compare-card\">\n <div class=\"card-header function\">\n <span class=\"card-icon\">📦</span>\n <span class=\"card-title\">函数 API</span>\n </div>\n <div class=\"card-body\">\n <div class=\"feature-list\">\n <div class=\"feature-item\">\n <span class=\"feature-label\">调用方式</span>\n <span class=\"feature-value\">直接函数调用</span>\n </div>\n <div class=\"feature-item\">\n <span class=\"feature-label\">参数传递</span>\n <span class=\"feature-value\">括号内传参</span>\n </div>\n <div class=\"feature-item\">\n <span class=\"feature-label\">返回值</span>\n <span class=\"feature-value\">直接获得结果</span>\n </div>\n <div class=\"feature-item\">\n <span class=\"feature-label\">错误处理</span>\n <span class=\"feature-value\">异常/返回值</span>\n </div>\n </div>\n <div class=\"code-block\">\n <div class=\"code-label\">Python 示例</div>\n <pre><code># 调用内置函数\nlength = len(\"hello\") # 返回 5\n\n# 调用库函数\nimport math\nresult = math.sqrt(16) # 返回 4.0\n\n# 调用自定义函数\ndef add(a, b):\n return a + b\nsum = add(3, 5) # 返回 8</code></pre>\n </div>\n </div>\n </div>\n\n <div class=\"vs-divider\">\n <span class=\"vs-text\">VS</span>\n </div>\n\n <div class=\"compare-card\">\n <div class=\"card-header http\">\n <span class=\"card-icon\">🌐</span>\n <span class=\"card-title\">HTTP API</span>\n </div>\n <div class=\"card-body\">\n <div class=\"feature-list\">\n <div class=\"feature-item\">\n <span class=\"feature-label\">调用方式</span>\n <span class=\"feature-value\">网络请求</span>\n </div>\n <div class=\"feature-item\">\n <span class=\"feature-label\">参数传递</span>\n <span class=\"feature-value\">URL/Body/Header</span>\n </div>\n <div class=\"feature-item\">\n <span class=\"feature-label\">返回值</span>\n <span class=\"feature-value\">JSON/XML 响应</span>\n </div>\n <div class=\"feature-item\">\n <span class=\"feature-label\">错误处理</span>\n <span class=\"feature-value\">状态码判断</span>\n </div>\n </div>\n <div class=\"code-block\">\n <div class=\"code-label\">HTTP 请求示例</div>\n <pre><code>POST /v1/chat/completions HTTP/1.1\nHost: api.deepseek.com\nAuthorization: Bearer sk-xxx\nContent-Type: application/json\n\n{\n \"model\": \"deepseek-chat\",\n \"messages\": [\n {\"role\": \"user\", \"content\": \"你好\"}\n ]\n}</code></pre>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- 文档对比视图 -->\n <div v-if=\"activeTab === 'docs'\" class=\"docs-view\">\n <div class=\"docs-cards\">\n <div class=\"doc-card\">\n <div class=\"doc-header\">\n <span class=\"doc-icon\">📖</span>\n <span class=\"doc-title\">函数文档怎么看</span>\n </div>\n <div class=\"doc-content\">\n <div class=\"doc-section\">\n <div class=\"doc-section-title\">🔍 关注重点</div>\n <ul class=\"doc-list\">\n <li><strong>函数签名</strong>:函数名和参数列表</li>\n <li><strong>参数类型</strong>:每个参数要什么类型</li>\n <li><strong>返回值</strong>:函数返回什么</li>\n <li><strong>异常说明</strong>:可能抛出什么错误</li>\n </ul>\n </div>\n <div class=\"doc-example\">\n <div class=\"doc-example-label\">Python 文档示例</div>\n <pre><code>def open(file: str, mode: str = 'r') -> TextIO:\n \"\"\"\n 打开文件并返回文件对象\n \n Args:\n file: 文件路径\n mode: 打开模式 ('r', 'w', 'a')\n \n Returns:\n 文件对象\n \n Raises:\n FileNotFoundError: 文件不存在\n \"\"\"</code></pre>\n </div>\n </div>\n </div>\n\n <div class=\"doc-card\">\n <div class=\"doc-header\">\n <span class=\"doc-icon\">📡</span>\n <span class=\"doc-title\">HTTP API 文档怎么看</span>\n </div>\n <div class=\"doc-content\">\n <div class=\"doc-section\">\n <div class=\"doc-section-title\">🔍 关注重点</div>\n <ul class=\"doc-list\">\n <li><strong>Endpoint</strong>:URL 路径和 HTTP 方法</li>\n <li><strong>认证方式</strong>:API Key / Token 怎么传</li>\n <li><strong>请求参数</strong>:Body / Query / Header</li>\n <li><strong>响应格式</strong>:成功和错误返回什么</li>\n </ul>\n </div>\n <div class=\"doc-example\">\n <div class=\"doc-example-label\">API 文档示例</div>\n <pre><code>POST /v1/chat/completions\n\nHeaders:\n Authorization: Bearer {api_key}\n Content-Type: application/json\n\nBody:\n{\n \"model\": \"deepseek-chat\",\n \"messages\": [...],\n \"temperature\": 0.7\n}\n\nResponse:\n{\n \"choices\": [{\n \"message\": {\"content\": \"...\"}\n }]\n}</code></pre>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- 快速判断视图 -->\n <div v-if=\"activeTab === 'quick'\" class=\"quick-view\">\n <div class=\"quick-cards\">\n <div class=\"quick-card\">\n <div class=\"quick-header\">\n <span class=\"quick-icon\">⚡</span>\n <span class=\"quick-title\">快速判断指南</span>\n </div>\n <div class=\"quick-content\">\n <div class=\"decision-tree\">\n <div class=\"decision-item\">\n <div class=\"decision-question\">看到代码里有 <code>()</code> 调用?</div>\n <div class=\"decision-answer\">→ 这是 <strong>函数 API</strong></div>\n <div class=\"decision-example\">如:len(), print(), requests.get()</div>\n </div>\n <div class=\"decision-arrow\">↓</div>\n <div class=\"decision-item\">\n <div class=\"decision-question\">看到 URL 和 HTTP 方法?</div>\n <div class=\"decision-answer\">→ 这是 <strong>HTTP API</strong></div>\n <div class=\"decision-example\">如:POST /api/users, GET https://...</div>\n </div>\n <div class=\"decision-arrow\">↓</div>\n <div class=\"decision-item\">\n <div class=\"decision-question\">看到 SDK/Client 对象?</div>\n <div class=\"decision-answer\">→ 这是 <strong>封装后的 HTTP API</strong></div>\n <div class=\"decision-example\">如:client.chat.completions.create()</div>\n </div>\n </div>\n </div>\n </div>\n\n <div class=\"quick-card\">\n <div class=\"quick-header\">\n <span class=\"quick-icon\">🎯</span>\n <span class=\"quick-title\">使用场景对比</span>\n </div>\n <div class=\"quick-content\">\n <div class=\"scenario-table\">\n <div class=\"scenario-row header\">\n <div class=\"scenario-cell\">场景</div>\n <div class=\"scenario-cell\">推荐方式</div>\n <div class=\"scenario-cell\">原因</div>\n </div>\n <div class=\"scenario-row\">\n <div class=\"scenario-cell\">本地数据处理</div>\n <div class=\"scenario-cell\"><span class=\"badge function\">函数 API</span></div>\n <div class=\"scenario-cell\">快速、无需网络</div>\n </div>\n <div class=\"scenario-row\">\n <div class=\"scenario-cell\">调用 AI 模型</div>\n <div class=\"scenario-cell\"><span class=\"badge http\">HTTP API</span></div>\n <div class=\"scenario-cell\">模型在远程服务器</div>\n </div>\n <div class=\"scenario-row\">\n <div class=\"scenario-cell\">获取天气数据</div>\n <div class=\"scenario-cell\"><span class=\"badge http\">HTTP API</span></div>\n <div class=\"scenario-cell\">数据在服务商那里</div>\n </div>\n <div class=\"scenario-row\">\n <div class=\"scenario-cell\">文件读写操作</div>\n <div class=\"scenario-cell\"><span class=\"badge function\">函数 API</span></div>\n <div class=\"scenario-cell\">直接操作本地文件</div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <div class=\"info-box\">\n <strong>核心要点:</strong>函数 API 是\"本地办事\",HTTP API 是\"远程通信\"。看文档时,函数关注参数和返回值,HTTP API 关注 Endpoint、认证和请求/响应格式。\n </div>\n </div>\n</template>\n\n<script setup>\nimport { ref } from 'vue'\n\nconst activeTab = ref('compare')\n\nconst tabs = [\n { id: 'compare', name: '核心区别', icon: '🔍' },\n { id: 'docs', name: '文档对比', icon: '📚' },\n { id: 'quick', name: '快速判断', icon: '⚡' }\n]\n</script>\n\n<style scoped>\n.api-compare-root {\n margin: 20px 0;\n border: 1px solid var(--vp-c-divider);\n border-radius: 8px;\n background: var(--vp-c-bg-soft);\n overflow: hidden;\n}\n\n.demo-header {\n padding: 16px 20px;\n background: var(--vp-c-bg);\n border-bottom: 1px solid var(--vp-c-divider);\n}\n\n.title {\n display: block;\n font-size: 1rem;\n font-weight: 600;\n color: var(--vp-c-text-1);\n margin-bottom: 4px;\n}\n\n.subtitle {\n font-size: 0.85rem;\n color: var(--vp-c-text-2);\n}\n\n.control-panel {\n display: flex;\n gap: 0;\n border-bottom: 1px solid var(--vp-c-divider);\n background: var(--vp-c-bg);\n}\n\n.tab-btn {\n flex: 1;\n padding: 12px 16px;\n background: transparent;\n border: none;\n border-right: 1px solid var(--vp-c-divider);\n font-size: 0.85rem;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.2s;\n color: var(--vp-c-text-2);\n}\n\n.tab-btn:last-child {\n border-right: none;\n}\n\n.tab-btn:hover {\n background: var(--vp-c-bg-mute);\n}\n\n.tab-btn.active {\n background: var(--vp-c-brand);\n color: white;\n}\n\n.visualization-area {\n padding: 20px;\n background: var(--vp-c-bg);\n}\n\n/* 对比视图 */\n.compare-view {\n width: 100%;\n}\n\n.compare-cards {\n display: grid;\n grid-template-columns: 1fr auto 1fr;\n gap: 16px;\n align-items: stretch;\n}\n\n@media (max-width: 768px) {\n .compare-cards {\n grid-template-columns: 1fr;\n }\n .vs-divider {\n display: none;\n }\n}\n\n.compare-card {\n border: 1px solid var(--vp-c-divider);\n border-radius: 8px;\n overflow: hidden;\n background: var(--vp-c-bg-soft);\n}\n\n.card-header {\n padding: 12px 16px;\n display: flex;\n align-items: center;\n gap: 8px;\n font-weight: 600;\n font-size: 0.95rem;\n}\n\n.card-header.function {\n background: linear-gradient(135deg, #10b981 0%, #059669 100%);\n color: white;\n}\n\n.card-header.http {\n background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%);\n color: white;\n}\n\n.card-icon {\n font-size: 1.2rem;\n}\n\n.card-body {\n padding: 16px;\n}\n\n.feature-list {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 12px;\n margin-bottom: 16px;\n}\n\n@media (max-width: 480px) {\n .feature-list {\n grid-template-columns: 1fr;\n }\n}\n\n.feature-item {\n display: flex;\n flex-direction: column;\n gap: 4px;\n padding: 10px 12px;\n background: var(--vp-c-bg);\n border-radius: 6px;\n border: 1px solid var(--vp-c-divider);\n}\n\n.feature-label {\n font-size: 0.7rem;\n color: var(--vp-c-text-3);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.feature-value {\n font-size: 0.85rem;\n color: var(--vp-c-text-1);\n font-weight: 500;\n}\n\n.code-block {\n background: #0a0a0a;\n border-radius: 6px;\n overflow: hidden;\n}\n\n.code-label {\n padding: 8px 12px;\n background: #18181b;\n color: #71717a;\n font-size: 0.75rem;\n font-weight: 600;\n border-bottom: 1px solid #27272a;\n}\n\n.code-block pre {\n margin: 0;\n padding: 12px;\n color: #e4e4e7;\n font-size: 0.8rem;\n line-height: 1.6;\n overflow-x: auto;\n}\n\n.code-block code {\n font-family: 'Menlo', 'Monaco', 'Courier New', monospace;\n}\n\n.vs-divider {\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.vs-text {\n width: 40px;\n height: 40px;\n border-radius: 50%;\n background: var(--vp-c-bg-alt);\n border: 2px solid var(--vp-c-divider);\n display: flex;\n align-items: center;\n justify-content: center;\n font-weight: 700;\n font-size: 0.85rem;\n color: var(--vp-c-text-2);\n}\n\n/* 文档视图 */\n.docs-view {\n width: 100%;\n}\n\n.docs-cards {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 20px;\n}\n\n@media (max-width: 768px) {\n .docs-cards {\n grid-template-columns: 1fr;\n }\n}\n\n.doc-card {\n border: 1px solid var(--vp-c-divider);\n border-radius: 8px;\n overflow: hidden;\n background: var(--vp-c-bg-soft);\n}\n\n.doc-header {\n padding: 14px 16px;\n background: var(--vp-c-bg-alt);\n border-bottom: 1px solid var(--vp-c-divider);\n display: flex;\n align-items: center;\n gap: 8px;\n font-weight: 600;\n font-size: 0.95rem;\n color: var(--vp-c-text-1);\n}\n\n.doc-icon {\n font-size: 1.2rem;\n}\n\n.doc-content {\n padding: 16px;\n}\n\n.doc-section {\n margin-bottom: 16px;\n}\n\n.doc-section-title {\n font-size: 0.85rem;\n font-weight: 600;\n color: var(--vp-c-text-1);\n margin-bottom: 10px;\n}\n\n.doc-list {\n list-style: none;\n padding: 0;\n margin: 0;\n}\n\n.doc-list li {\n padding: 6px 0;\n font-size: 0.85rem;\n color: var(--vp-c-text-2);\n border-bottom: 1px dashed var(--vp-c-divider);\n}\n\n.doc-list li:last-child {\n border-bottom: none;\n}\n\n.doc-list strong {\n color: var(--vp-c-brand);\n}\n\n.doc-example {\n background: #0a0a0a;\n border-radius: 6px;\n overflow: hidden;\n margin-top: 12px;\n}\n\n.doc-example-label {\n padding: 8px 12px;\n background: #18181b;\n color: #71717a;\n font-size: 0.75rem;\n font-weight: 600;\n border-bottom: 1px solid #27272a;\n}\n\n.doc-example pre {\n margin: 0;\n padding: 12px;\n color: #e4e4e7;\n font-size: 0.75rem;\n line-height: 1.6;\n overflow-x: auto;\n}\n\n.doc-example code {\n font-family: 'Menlo', 'Monaco', 'Courier New', monospace;\n}\n\n/* 快速判断视图 */\n.quick-view {\n width: 100%;\n}\n\n.quick-cards {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 20px;\n}\n\n@media (max-width: 768px) {\n .quick-cards {\n grid-template-columns: 1fr;\n }\n}\n\n.quick-card {\n border: 1px solid var(--vp-c-divider);\n border-radius: 8px;\n overflow: hidden;\n background: var(--vp-c-bg-soft);\n}\n\n.quick-header {\n padding: 14px 16px;\n background: var(--vp-c-bg-alt);\n border-bottom: 1px solid var(--vp-c-divider);\n display: flex;\n align-items: center;\n gap: 8px;\n font-weight: 600;\n font-size: 0.95rem;\n color: var(--vp-c-text-1);\n}\n\n.quick-icon {\n font-size: 1.2rem;\n}\n\n.quick-content {\n padding: 16px;\n}\n\n.decision-tree {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.decision-item {\n padding: 14px;\n background: var(--vp-c-bg);\n border-radius: 8px;\n border: 1px solid var(--vp-c-divider);\n}\n\n.decision-question {\n font-size: 0.85rem;\n color: var(--vp-c-text-2);\n margin-bottom: 6px;\n}\n\n.decision-question code {\n background: var(--vp-c-bg-mute);\n padding: 2px 6px;\n border-radius: 4px;\n font-size: 0.8rem;\n}\n\n.decision-answer {\n font-size: 0.9rem;\n color: var(--vp-c-text-1);\n font-weight: 600;\n}\n\n.decision-example {\n font-size: 0.75rem;\n color: var(--vp-c-text-3);\n margin-top: 6px;\n padding-top: 6px;\n border-top: 1px dashed var(--vp-c-divider);\n}\n\n.decision-arrow {\n text-align: center;\n color: var(--vp-c-text-3);\n font-size: 1.2rem;\n}\n\n.scenario-table {\n display: flex;\n flex-direction: column;\n gap: 1px;\n background: var(--vp-c-divider);\n border-radius: 6px;\n overflow: hidden;\n}\n\n.scenario-row {\n display: grid;\n grid-template-columns: 1.2fr 1fr 1.2fr;\n gap: 12px;\n padding: 12px;\n background: var(--vp-c-bg);\n align-items: center;\n}\n\n.scenario-row.header {\n background: var(--vp-c-bg-alt);\n font-weight: 600;\n font-size: 0.8rem;\n color: var(--vp-c-text-2);\n}\n\n.scenario-cell {\n font-size: 0.8rem;\n color: var(--vp-c-text-1);\n}\n\n.badge {\n display: inline-block;\n padding: 4px 10px;\n border-radius: 4px;\n font-size: 0.75rem;\n font-weight: 600;\n}\n\n.badge.function {\n background: rgba(16, 185, 129, 0.15);\n color: #059669;\n}\n\n.badge.http {\n background: rgba(59, 130, 246, 0.15);\n color: #2563eb;\n}\n\n/* Info Box */\n.info-box {\n display: flex;\n gap: 0.5rem;\n padding: 14px 20px;\n background: var(--vp-c-bg-soft);\n border-top: 1px solid var(--vp-c-divider);\n font-size: 0.85rem;\n color: var(--vp-c-text-2);\n line-height: 1.6;\n}\n\n.info-box strong {\n white-space: nowrap;\n flex-shrink: 0;\n color: var(--vp-c-text-1);\n}\n</style>\n"}, "78db819e841b2c0117cf1e09ceb18bb2a17b65a2": {"t": 1785765449.108592, "n": 17080, "h": "055825151fe86cb8", "c": "<template>\n <div class=\"api-compare-root\">\n <div class=\"demo-header\">\n <span class=\"title\">📚 函数 API vs HTTP API</span>\n <span class=\"subtitle\">本地调用 vs 网络请求,文档怎么看?</span>\n </div>\n\n <div class=\"control-panel\">\n <button\n v-for=\"tab in tabs\"\n :key=\"tab.id\"\n :class=\"['tab-btn', { active: activeTab === tab.id }]\"\n @click=\"activeTab = tab.id\"\n >\n {{ tab.icon }} {{ tab.name }}\n </button>\n </div>\n\n <div class=\"visualization-area\">\n <!-- 对比视图 -->\n <div v-if=\"activeTab === 'compare'\" class=\"compare-view\">\n <div class=\"compare-cards\">\n <div class=\"compare-card\">\n <div class=\"card-header function\">\n <span class=\"card-icon\">📦</span>\n <span class=\"card-title\">函数 API</span>\n </div>\n <div class=\"card-body\">\n <div class=\"feature-list\">\n <div class=\"feature-item\">\n <span class=\"feature-label\">调用方式</span>\n <span class=\"feature-value\">直接函数调用</span>\n </div>\n <div class=\"feature-item\">\n <span class=\"feature-label\">参数传递</span>\n <span class=\"feature-value\">括号内传参</span>\n </div>\n <div class=\"feature-item\">\n <span class=\"feature-label\">返回值</span>\n <span class=\"feature-value\">直接获得结果</span>\n </div>\n <div class=\"feature-item\">\n <span class=\"feature-label\">错误处理</span>\n <span class=\"feature-value\">异常/返回值</span>\n </div>\n </div>\n <div class=\"code-block\">\n <div class=\"code-label\">Python 示例</div>\n <pre><code># 调用内置函数\nlength = len(\"hello\") # 返回 5\n\n# 调用库函数\nimport math\nresult = math.sqrt(16) # 返回 4.0\n\n# 调用自定义函数\ndef add(a, b):\n return a + b\nsum = add(3, 5) # 返回 8</code></pre>\n </div>\n </div>\n </div>\n\n <div class=\"vs-divider\">\n <span class=\"vs-text\">VS</span>\n </div>\n\n <div class=\"compare-card\">\n <div class=\"card-header http\">\n <span class=\"card-icon\">🌐</span>\n <span class=\"card-title\">HTTP API</span>\n </div>\n <div class=\"card-body\">\n <div class=\"feature-list\">\n <div class=\"feature-item\">\n <span class=\"feature-label\">调用方式</span>\n <span class=\"feature-value\">网络请求</span>\n </div>\n <div class=\"feature-item\">\n <span class=\"feature-label\">参数传递</span>\n <span class=\"feature-value\">URL/Body/Header</span>\n </div>\n <div class=\"feature-item\">\n <span class=\"feature-label\">返回值</span>\n <span class=\"feature-value\">JSON/XML 响应</span>\n </div>\n <div class=\"feature-item\">\n <span class=\"feature-label\">错误处理</span>\n <span class=\"feature-value\">状态码判断</span>\n </div>\n </div>\n <div class=\"code-block\">\n <div class=\"code-label\">HTTP 请求示例</div>\n <pre><code>POST /v1/chat/completions HTTP/1.1\nHost: api.deepseek.com\nAuthorization: Bearer sk-xxx\nContent-Type: application/json\n\n{\n \"model\": \"deepseek-chat\",\n \"messages\": [\n {\"role\": \"user\", \"content\": \"你好\"}\n ]\n}</code></pre>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- 文档对比视图 -->\n <div v-if=\"activeTab === 'docs'\" class=\"docs-view\">\n <div class=\"docs-cards\">\n <div class=\"doc-card\">\n <div class=\"doc-header\">\n <span class=\"doc-icon\">📖</span>\n <span class=\"doc-title\">函数文档怎么看</span>\n </div>\n <div class=\"doc-content\">\n <div class=\"doc-section\">\n <div class=\"doc-section-title\">🔍 关注重点</div>\n <ul class=\"doc-list\">\n <li><strong>函数签名</strong>:函数名和参数列表</li>\n <li><strong>参数类型</strong>:每个参数要什么类型</li>\n <li><strong>返回值</strong>:函数返回什么</li>\n <li><strong>异常说明</strong>:可能抛出什么错误</li>\n </ul>\n </div>\n <div class=\"doc-example\">\n <div class=\"doc-example-label\">Python 文档示例</div>\n <pre><code>def open(file: str, mode: str = 'r') -> TextIO:\n \"\"\"\n 打开文件并返回文件对象\n \n Args:\n file: 文件路径\n mode: 打开模式 ('r', 'w', 'a')\n \n Returns:\n 文件对象\n \n Raises:\n FileNotFoundError: 文件不存在\n \"\"\"</code></pre>\n </div>\n </div>\n </div>\n\n <div class=\"doc-card\">\n <div class=\"doc-header\">\n <span class=\"doc-icon\">📡</span>\n <span class=\"doc-title\">HTTP API 文档怎么看</span>\n </div>\n <div class=\"doc-content\">\n <div class=\"doc-section\">\n <div class=\"doc-section-title\">🔍 关注重点</div>\n <ul class=\"doc-list\">\n <li><strong>Endpoint</strong>:URL 路径和 HTTP 方法</li>\n <li><strong>认证方式</strong>:API Key / Token 怎么传</li>\n <li><strong>请求参数</strong>:Body / Query / Header</li>\n <li><strong>响应格式</strong>:成功和错误返回什么</li>\n </ul>\n </div>\n <div class=\"doc-example\">\n <div class=\"doc-example-label\">API 文档示例</div>\n <pre><code>POST /v1/chat/completions\n\nHeaders:\n Authorization: Bearer {api_key}\n Content-Type: application/json\n\nBody:\n{\n \"model\": \"deepseek-chat\",\n \"messages\": [...],\n \"temperature\": 0.7\n}\n\nResponse:\n{\n \"choices\": [{\n \"message\": {\"content\": \"...\"}\n }]\n}</code></pre>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- 快速判断视图 -->\n <div v-if=\"activeTab === 'quick'\" class=\"quick-view\">\n <div class=\"quick-cards\">\n <div class=\"quick-card\">\n <div class=\"quick-header\">\n <span class=\"quick-icon\">⚡</span>\n <span class=\"quick-title\">快速判断指南</span>\n </div>\n <div class=\"quick-content\">\n <div class=\"decision-tree\">\n <div class=\"decision-item\">\n <div class=\"decision-question\">看到代码里有 <code>()</code> 调用?</div>\n <div class=\"decision-answer\">→ 这是 <strong>函数 API</strong></div>\n <div class=\"decision-example\">如:len(), print(), requests.get()</div>\n </div>\n <div class=\"decision-arrow\">↓</div>\n <div class=\"decision-item\">\n <div class=\"decision-question\">看到 URL 和 HTTP 方法?</div>\n <div class=\"decision-answer\">→ 这是 <strong>HTTP API</strong></div>\n <div class=\"decision-example\">如:POST /api/users, GET https://...</div>\n </div>\n <div class=\"decision-arrow\">↓</div>\n <div class=\"decision-item\">\n <div class=\"decision-question\">看到 SDK/Client 对象?</div>\n <div class=\"decision-answer\">→ 这是 <strong>封装后的 HTTP API</strong></div>\n <div class=\"decision-example\">如:client.chat.completions.create()</div>\n </div>\n </div>\n </div>\n </div>\n\n <div class=\"quick-card\">\n <div class=\"quick-header\">\n <span class=\"quick-icon\">🎯</span>\n <span class=\"quick-title\">使用场景对比</span>\n </div>\n <div class=\"quick-content\">\n <div class=\"scenario-table\">\n <div class=\"scenario-row header\">\n <div class=\"scenario-cell\">场景</div>\n <div class=\"scenario-cell\">推荐方式</div>\n <div class=\"scenario-cell\">原因</div>\n </div>\n <div class=\"scenario-row\">\n <div class=\"scenario-cell\">本地数据处理</div>\n <div class=\"scenario-cell\"><span class=\"badge function\">函数 API</span></div>\n <div class=\"scenario-cell\">快速、无需网络</div>\n </div>\n <div class=\"scenario-row\">\n <div class=\"scenario-cell\">调用 AI 模型</div>\n <div class=\"scenario-cell\"><span class=\"badge http\">HTTP API</span></div>\n <div class=\"scenario-cell\">模型在远程服务器</div>\n </div>\n <div class=\"scenario-row\">\n <div class=\"scenario-cell\">获取天气数据</div>\n <div class=\"scenario-cell\"><span class=\"badge http\">HTTP API</span></div>\n <div class=\"scenario-cell\">数据在服务商那里</div>\n </div>\n <div class=\"scenario-row\">\n <div class=\"scenario-cell\">文件读写操作</div>\n <div class=\"scenario-cell\"><span class=\"badge function\">函数 API</span></div>\n <div class=\"scenario-cell\">直接操作本地文件</div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <div class=\"info-box\">\n <strong>核心要点:</strong>函数 API 是\"本地办事\",HTTP API 是\"远程通信\"。看文档时,函数关注参数和返回值,HTTP API 关注 Endpoint、认证和请求/响应格式。\n </div>\n </div>\n</template>\n\n<script setup>\nimport { ref } from 'vue'\n\nconst activeTab = ref('compare')\n\nconst tabs = [\n { id: 'compare', name: '核心区别', icon: '🔍' },\n { id: 'docs', name: '文档对比', icon: '📚' },\n { id: 'quick', name: '快速判断', icon: '⚡' }\n]\n</script>\n\n<style scoped>\n.api-compare-root {\n margin: 20px 0;\n border: 1px solid var(--vp-c-divider);\n border-radius: 8px;\n background: var(--vp-c-bg-soft);\n overflow: hidden;\n}\n\n.demo-header {\n padding: 16px 20px;\n background: var(--vp-c-bg);\n border-bottom: 1px solid var(--vp-c-divider);\n}\n\n.title {\n display: block;\n font-size: 1rem;\n font-weight: 600;\n color: var(--vp-c-text-1);\n margin-bottom: 4px;\n}\n\n.subtitle {\n font-size: 0.85rem;\n color: var(--vp-c-text-2);\n}\n\n.control-panel {\n display: flex;\n gap: 0;\n border-bottom: 1px solid var(--vp-c-divider);\n background: var(--vp-c-bg);\n}\n\n.tab-btn {\n flex: 1;\n padding: 12px 16px;\n background: transparent;\n border: none;\n border-right: 1px solid var(--vp-c-divider);\n font-size: 0.85rem;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.2s;\n color: var(--vp-c-text-2);\n}\n\n.tab-btn:last-child {\n border-right: none;\n}\n\n.tab-btn:hover {\n background: var(--vp-c-bg-mute);\n}\n\n.tab-btn.active {\n background: var(--vp-c-brand);\n color: white;\n}\n\n.visualization-area {\n padding: 20px;\n background: var(--vp-c-bg);\n}\n\n/* 对比视图 */\n.compare-view {\n width: 100%;\n}\n\n.compare-cards {\n display: grid;\n grid-template-columns: 1fr auto 1fr;\n gap: 16px;\n align-items: stretch;\n}\n\n@media (max-width: 768px) {\n .compare-cards {\n grid-template-columns: 1fr;\n }\n .vs-divider {\n display: none;\n }\n}\n\n.compare-card {\n border: 1px solid var(--vp-c-divider);\n border-radius: 8px;\n overflow: hidden;\n background: var(--vp-c-bg-soft);\n}\n\n.card-header {\n padding: 12px 16px;\n display: flex;\n align-items: center;\n gap: 8px;\n font-weight: 600;\n font-size: 0.95rem;\n}\n\n.card-header.function {\n background: linear-gradient(135deg, #10b981 0%, #059669 100%);\n color: white;\n}\n\n.card-header.http {\n background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%);\n color: white;\n}\n\n.card-icon {\n font-size: 1.2rem;\n}\n\n.card-body {\n padding: 16px;\n}\n\n.feature-list {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 12px;\n margin-bottom: 16px;\n}\n\n@media (max-width: 480px) {\n .feature-list {\n grid-template-columns: 1fr;\n }\n}\n\n.feature-item {\n display: flex;\n flex-direction: column;\n gap: 4px;\n padding: 10px 12px;\n background: var(--vp-c-bg);\n border-radius: 6px;\n border: 1px solid var(--vp-c-divider);\n}\n\n.feature-label {\n font-size: 0.7rem;\n color: var(--vp-c-text-3);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.feature-value {\n font-size: 0.85rem;\n color: var(--vp-c-text-1);\n font-weight: 500;\n}\n\n.code-block {\n background: #0a0a0a;\n border-radius: 6px;\n overflow: hidden;\n}\n\n.code-label {\n padding: 8px 12px;\n background: #18181b;\n color: #71717a;\n font-size: 0.75rem;\n font-weight: 600;\n border-bottom: 1px solid #27272a;\n}\n\n.code-block pre {\n margin: 0;\n padding: 12px;\n color: #e4e4e7;\n font-size: 0.8rem;\n line-height: 1.6;\n overflow-x: auto;\n}\n\n.code-block code {\n font-family: 'Menlo', 'Monaco', 'Courier New', monospace;\n}\n\n.vs-divider {\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.vs-text {\n width: 40px;\n height: 40px;\n border-radius: 50%;\n background: var(--vp-c-bg-alt);\n border: 2px solid var(--vp-c-divider);\n display: flex;\n align-items: center;\n justify-content: center;\n font-weight: 700;\n font-size: 0.85rem;\n color: var(--vp-c-text-2);\n}\n\n/* 文档视图 */\n.docs-view {\n width: 100%;\n}\n\n.docs-cards {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 20px;\n}\n\n@media (max-width: 768px) {\n .docs-cards {\n grid-template-columns: 1fr;\n }\n}\n\n.doc-card {\n border: 1px solid var(--vp-c-divider);\n border-radius: 8px;\n overflow: hidden;\n background: var(--vp-c-bg-soft);\n}\n\n.doc-header {\n padding: 14px 16px;\n background: var(--vp-c-bg-alt);\n border-bottom: 1px solid var(--vp-c-divider);\n display: flex;\n align-items: center;\n gap: 8px;\n font-weight: 600;\n font-size: 0.95rem;\n color: var(--vp-c-text-1);\n}\n\n.doc-icon {\n font-size: 1.2rem;\n}\n\n.doc-content {\n padding: 16px;\n}\n\n.doc-section {\n margin-bottom: 16px;\n}\n\n.doc-section-title {\n font-size: 0.85rem;\n font-weight: 600;\n color: var(--vp-c-text-1);\n margin-bottom: 10px;\n}\n\n.doc-list {\n list-style: none;\n padding: 0;\n margin: 0;\n}\n\n.doc-list li {\n padding: 6px 0;\n font-size: 0.85rem;\n color: var(--vp-c-text-2);\n border-bottom: 1px dashed var(--vp-c-divider);\n}\n\n.doc-list li:last-child {\n border-bottom: none;\n}\n\n.doc-list strong {\n color: var(--vp-c-brand);\n}\n\n.doc-example {\n background: #0a0a0a;\n border-radius: 6px;\n overflow: hidden;\n margin-top: 12px;\n}\n\n.doc-example-label {\n padding: 8px 12px;\n background: #18181b;\n color: #71717a;\n font-size: 0.75rem;\n font-weight: 600;\n border-bottom: 1px solid #27272a;\n}\n\n.doc-example pre {\n margin: 0;\n padding: 12px;\n color: #e4e4e7;\n font-size: 0.75rem;\n line-height: 1.6;\n overflow-x: auto;\n}\n\n.doc-example code {\n font-family: 'Menlo', 'Monaco', 'Courier New', monospace;\n}\n\n/* 快速判断视图 */\n.quick-view {\n width: 100%;\n}\n\n.quick-cards {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 20px;\n}\n\n@media (max-width: 768px) {\n .quick-cards {\n grid-template-columns: 1fr;\n }\n}\n\n.quick-card {\n border: 1px solid var(--vp-c-divider);\n border-radius: 8px;\n overflow: hidden;\n background: var(--vp-c-bg-soft);\n}\n\n.quick-header {\n padding: 14px 16px;\n background: var(--vp-c-bg-alt);\n border-bottom: 1px solid var(--vp-c-divider);\n display: flex;\n align-items: center;\n gap: 8px;\n font-weight: 600;\n font-size: 0.95rem;\n color: var(--vp-c-text-1);\n}\n\n.quick-icon {\n font-size: 1.2rem;\n}\n\n.quick-content {\n padding: 16px;\n}\n\n.decision-tree {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.decision-item {\n padding: 14px;\n background: var(--vp-c-bg);\n border-radius: 8px;\n border: 1px solid var(--vp-c-divider);\n}\n\n.decision-question {\n font-size: 0.85rem;\n color: var(--vp-c-text-2);\n margin-bottom: 6px;\n}\n\n.decision-question code {\n background: var(--vp-c-bg-mute);\n padding: 2px 6px;\n border-radius: 4px;\n font-size: 0.8rem;\n}\n\n.decision-answer {\n font-size: 0.9rem;\n color: var(--vp-c-text-1);\n font-weight: 600;\n}\n\n.decision-example {\n font-size: 0.75rem;\n color: var(--vp-c-text-3);\n margin-top: 6px;\n padding-top: 6px;\n border-top: 1px dashed var(--vp-c-divider);\n}\n\n.decision-arrow {\n text-align: center;\n color: var(--vp-c-text-3);\n font-size: 1.2rem;\n}\n\n.scenario-table {\n display: flex;\n flex-direction: column;\n gap: 1px;\n background: var(--vp-c-divider);\n border-radius: 6px;\n overflow: hidden;\n}\n\n.scenario-row {\n display: grid;\n grid-template-columns: 1.2fr 1fr 1.2fr;\n gap: 12px;\n padding: 12px;\n background: var(--vp-c-bg);\n align-items: center;\n}\n\n.scenario-row.header {\n background: var(--vp-c-bg-alt);\n font-weight: 600;\n font-size: 0.8rem;\n color: var(--vp-c-text-2);\n}\n\n.scenario-cell {\n font-size: 0.8rem;\n color: var(--vp-c-text-1);\n}\n\n.badge {\n display: inline-block;\n padding: 4px 10px;\n border-radius: 4px;\n font-size: 0.75rem;\n font-weight: 600;\n}\n\n.badge.function {\n background: rgba(16, 185, 129, 0.15);\n color: #059669;\n}\n\n.badge.http {\n background: rgba(59, 130, 246, 0.15);\n color: #2563eb;\n}\n\n/* Info Box */\n.info-box {\n display: flex;\n gap: 0.5rem;\n padding: 14px 20px;\n background: var(--vp-c-bg-soft);\n border-top: 1px solid var(--vp-c-divider);\n font-size: 0.85rem;\n color: var(--vp-c-text-2);\n line-height: 1.6;\n}\n\n.info-box strong {\n white-space: nowrap;\n flex-shrink: 0;\n color: var(--vp-c-text-1);\n}\n</style>\n"}}, "docs/zh-cn/appendix/4-server-and-backend/api-intro.md": {"64900140d8920e20989a8ac4227900703b4f73e8": {"t": 1786067813.1449256, "n": 6234, "h": "0df34a2201308e92", "c": "# API 入门:从零理解\"程序之间的对话\"\n\n::: tip 🎯 核心问题\n**什么是 API?** 这就像问:餐厅的菜单怎么设计,客人一看就懂?服务员怎么记单,不会出错?API 解决的就是\"程序之间如何对话\"的问题。你写代码的第一天就在用 API,只是你可能没意识到。\n:::\n\n---\n\n## 0. 新手常见的三个困惑\n\n**困惑一:API 是很高深的东西吗?**\n\n很多人一听到 API,就觉得是高级工程师才能理解的概念。其实你早就用过 API 了:\n\n```python\nlen(\"hello\") # 这就是 Python 提供的 API\nopen(\"file.txt\") # 这也是 API\nrequests.get(url) # 这还是 API\n```\n\n**困惑二:Web API 和普通 API 有什么区别?**\n\n| 类型 | 调用对象 | 通信方式 | 典型场景 |\n| :--- | :--- | :--- | :--- |\n| **函数 API** | 本地代码 | 函数调用 | `len()`, `open()` |\n| **操作系统 API** | 操作系统 | 系统调用 | 读写文件、创建进程 |\n| **Web API** | 远程服务器 | HTTP 请求 | 调用 AI 模型、获取天气 |\n\n**困惑三:我该用 HTTP 还是 SDK?**\n\n```python\n# HTTP 方式:自己处理所有细节\nimport requests\nresponse = requests.post(\n \"https://api.deepseek.com/v1/chat/completions\",\n headers={\"Authorization\": \"Bearer sk-xxx\"},\n json={\"model\": \"deepseek-chat\", \"messages\": [...]}\n)\nresult = response.json()[\"choices\"][0][\"message\"][\"content\"]\n\n# SDK 方式:管家帮你处理\nfrom openai import OpenAI\nclient = OpenAI(api_key=\"sk-xxx\")\nresponse = client.chat.completions.create(\n model=\"deepseek-chat\",\n messages=[...]\n)\nresult = response.choices[0].message.content\n```\n\n---\n\n## 1. API 的本质:插头与插座\n\n**API**(Application Programming Interface,应用程序编程接口)就是\"程序之间对话的约定\"。\n\n### 1.1 用电器来类比\n\n| 概念 | 电器类比 | API 对应 |\n| :--- | :--- | :--- |\n| **接口** | 插座形状 | 函数签名 / URL |\n| **输入** | 电流输入 | 函数参数 / 请求体 |\n| **输出** | 电器工作 | 返回值 / 响应体 |\n\n### 1.2 三种 API 形态对比\n\n<ApiTypesComparison />\n\n### 1.3 函数 API vs HTTP API 的区别\n\n很多初学者会困惑:函数 API 和 HTTP API 到底有什么区别?看文档时该如何区分?\n\n<ApiFunctionVsHttp />\n\n### 1.4 不同类型的 API 文档怎么看\n\n面对不同类型的 API 文档,关注重点各不相同:\n\n<DocumentTypesComparison />\n\n---\n\n## 2. 一次完整的 API 调用\n\n👇 **动手试试看**:点击下方按钮,观察一次完整的 API 请求-响应流程:\n\n<ApiRequestDemo />\n\n### 2.1 API 调用的四个阶段\n\n| 阶段 | 发生了什么 | 电器类比 |\n| :--- | :--- | :--- |\n| **请求** | 客户端向服务器发送请求 | 按下开关 |\n| **传输** | 请求通过网络传输到服务器 | 电流通过电线 |\n| **处理** | 服务器处理请求并返回数据 | 电器开始工作 |\n| **响应** | 客户端接收并处理返回结果 | 灯泡发光 |\n\n### 2.2 餐厅类比\n\n| 餐厅角色 | API 对应 | 说明 |\n| :--- | :--- | :--- |\n| **菜单** | API 文档 | 告诉你有哪些\"菜\"可以点 |\n| **服务员** | HTTP 协议 | 标准化的\"对话方式\" |\n| **后厨** | 服务端 | 按\"订单\"处理请求 |\n| **上菜** | 响应 | 把结果返回给\"客人\" |\n\n---\n\n## 3. HTTP 方法:你是在\"问\"还是在\"做\"?\n\n调用 Web API 时,你需要告诉服务器你想做什么。这就是 HTTP 方法的由来。\n\n### 3.1 用餐厅点餐来理解\n\n| 场景 | 现实中你会怎么说? | 对应的 HTTP 方法 |\n| :--- | :--- | :--- |\n| 你想知道今天有什么菜 | \"服务员,菜单给我看看\" | **GET** - 纯\"问\",不改数据 |\n| 你想点一份宫保鸡丁 | \"给我来份宫保鸡丁\" | **POST** - \"做\"件事,创建数据 |\n| 你想换一道菜 | \"把宫保鸡丁改成糖醋里脊\" | **PUT** - 替换数据 |\n| 你想改口味 | \"宫保鸡丁不要放花生\" | **PATCH** - 部分修改 |\n| 你不想要了 | \"算了,那道菜不要了\" | **DELETE** - 删除数据 |\n\n<HttpMethodsDemo />\n\n::: warning 关于幂等性\n**幂等性**:多次执行结果是否相同?\n\n- **幂等的操作**(GET/PUT/DELETE):点 10 次和点 1 次,结果一样\n- **不幂等的操作**(POST):点 10 次,可能创建 10 个订单\n\n**解决方案**:POST 操作用唯一 ID 校验,避免重复处理。\n:::\n\n### 3.2 HTTP 方法速查表\n\n| 方法 | 用途 | 幂等性 | 安全性 | 典型场景 |\n| :--- | :--- | :--- | :--- | :--- |\n| **GET** | 获取资源 | 是 | 是 | 查询列表、查看详情 |\n| **POST** | 创建资源 | 否 | 否 | 新增用户、提交订单 |\n| **PUT** | 全量更新 | 是 | 否 | 替换整个用户资料 |\n| **PATCH** | 部分更新 | 否 | 否 | 只修改昵称 |\n| **DELETE** | 删除资源 | 是 | 否 | 删除用户、取消订单 |\n\n---\n\n## 4. HTTP 状态码:服务器在告诉你什么?\n\n服务器回复时,会先返回一个状态码,告诉你请求是否成功。\n\n### 4.1 状态码分类\n\n<StatusCodeCategories />\n\n### 4.2 常见状态码详解\n\n| 状态码 | 含义 | 典型场景 | 客户端处理 |\n| :--- | :--- | :--- | :--- |\n| **200 OK** | 成功 | 请求正常处理 | 展示数据 |\n| **201 Created** | 创建成功 | POST 请求成功创建资源 | 跳转到新资源 |\n| **400 Bad Request** | 请求格式错误 | 参数缺失或格式不对 | 检查参数 |\n| **401 Unauthorized** | 未认证 | 没有提供有效的 API Key | 引导用户登录 |\n| **403 Forbidden** | 无权限 | API Key 没有访问该资源的权限 | 提示权限不足 |\n| **404 Not Found** | 不存在 | 请求的地址或资源不存在 | 检查 URL |\n| **429 Too Many Requests** | 请求过多 | 超过了速率限制 | 稍后重试 |\n| **500 Internal Server Error** | 服务器错误 | 服务端出了问题 | 提示用户稍后重试 |\n\n👇 **动手试试看**:点击下方按钮,了解常见状态码的含义:\n\n<StatusCodeDemo />\n\n---\n\n## 5. HTTP vs SDK:自己跑腿还是让管家代办?\n\n### 5.1 两种调用方式对比\n\n| | 🏃 **HTTP API** | 🤵 **SDK** |\n| :--- | :--- | :--- |\n| **比喻** | 自己跑腿 | 管家代办 |\n| **优点** | ✓ 所有语言都能用<br>✓ 完全控制请求细节<br>✓ 无需额外依赖 | ✓ 代码简洁易读<br>✓ 自动处理鉴权<br>✓ 内置错误重试 |\n| **缺点** | ✗ 需要处理所有细节<br>✗ 代码冗长易出错 | ✗ 需要安装依赖<br>✗ 可能有版本问题 |\n| **代码示例** | `requests.post(url, json=..., headers={...})` | `client.chat.completions.create(...)` |\n\n### 5.2 如何选择?\n\n| 场景 | 推荐方式 | 原因 |\n| :--- | :--- | :--- |\n| **快速开发** | SDK | 自动处理鉴权、错误、重试 |\n| **学习原理** | HTTP | 理解底层机制 |\n| **不支持的语言** | HTTP | 任何语言都能用 |\n| **需要定制** | HTTP | 灵活控制每个细节 |\n\n::: tip 💡 建议\n**能用 SDK 就用 SDK**,把麻烦事留给库,把时间留给自己。\n:::\n\n---\n\n## 6. 如何阅读 API 文档?\n\nAPI 文档就像说明书和菜单的结合体。你不需要从头读到尾,只需要学会\"查字典\"。\n\n### 6.1 文档阅读清单\n\n打开任何一个 API 文档(比如 OpenAI 或 DeepSeek),你只需要找这几样东西:\n\n<ApiDocumentDemo />\n\n| 项目 | 说明 | 示例 |\n| :--- | :--- | :--- |\n| **Base URL** | API 的根地址 | `https://api.deepseek.com` |\n| **Authentication** | 如何证明身份 | `Authorization: Bearer sk-xxx` |\n| **Endpoints** | 具体的接口列表 | `/v1/chat/completions` |\n| **Parameters** | 必填/可选参数 | `model`(必填)、`temperature`(可选) |\n| **Response** | 返回数据结构 | `{\"choices\": [...]}` |\n\n### 6.2 阅读文档的步骤\n\n1. **找到 Base URL** - 这是所有请求的前缀\n2. **看懂认证方式** - API Key 放在 Header 还是 Query?\n3. **找到需要的 Endpoint** - 你要调用的具体接口\n4. **查看请求参数** - 哪些必填?哪些可选?\n5. **理解返回格式** - 数据是如何组织的?\n\n---\n\n## 7. 动手练习:模拟 API 调用\n\n光说不练假把式。这里有个模拟 API,你可以随便填参数、随便改地址,看看会发生什么。\n\n<ApiPlayground />\n\n试着触发以下场景:\n- ✅ **成功请求**:填入正确的 Endpoint 和 API Key\n- ❌ **401 错误**:不填 API Key,看看服务器怎么拒绝你\n- ❌ **404 错误**:填一个不存在的地址\n\n---\n\n## 8. 小结\n\n::: info 核心要点\n1. **API 就是传声筒**,帮你把话传给另一段代码或远程服务器\n2. **你早就用过 API 了**,从 `len()` 到 `open()` 都是 API\n3. **Web API 是超能力**,让你调用千里之外的超级电脑\n4. **SDK 是好管家**,能用 SDK 就别自己跑腿\n5. **看文档找三样**:地址、鉴权、参数\n:::\n\n在 AI 编程的时代,你只需要记住这几个核心概念。剩下的细节,IDE 和 AI 助手会帮你处理。\n\n---\n\n## 名词速查表\n\n| 名词 | 全称 | 解释 |\n| :--- | :--- | :--- |\n| **API** | Application Programming Interface | 应用程序编程接口,定义了软件之间如何交互 |\n| **Web API** | - | 基于 HTTP 协议的 API,用于网络通信 |\n| **Endpoint** | - | 端点,API 的具体地址 |\n| **HTTP** | HyperText Transfer Protocol | Web API 使用的通信协议 |\n| **GET** | - | 获取资源的方法 |\n| **POST** | - | 提交数据的方法 |\n| **SDK** | Software Development Kit | 软件开发工具包,封装了底层 API 调用 |\n| **URL** | Uniform Resource Locator | API 的网络地址 |\n| **JSON** | JavaScript Object Notation | 常用的数据格式 |\n| **Authentication** | - | 验证身份的过程 |\n| **Status Code** | - | HTTP 响应中的状态码 |\n| **Request** | - | 请求 |\n| **Response** | - | 响应 |\n| **Header** | - | HTTP 头,包含元信息 |\n| **Payload** | - | 请求或响应的实际数据 |\n| **Rate Limit** | - | 速率限制 |\n| **Idempotent** | - | 幂等,多次执行结果相同 |\n| **REST** | Representational State Transfer | 一种 API 架构风格 |\n| **RPC** | Remote Procedure Call | 远程过程调用 |\n| **GraphQL** | - | 一种查询语言 API |\n| **gRPC** | - | Google 开发的高性能 RPC 框架 |\n"}}}}