1 line
38 KiB
JSON
1 line
38 KiB
JSON
{"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"}}}} |