Files
tiantian-system/.nuxt/content/sql_dump.txt
赵忠林 f9e1286ab1 refactor(developer-config): 移除开发者配置页面相关代码和文档
- 删除应用配置页面及相关组件,重构路由为 /developer/config/[id].vue
- 移除开发者文档页面及其导航与样式实现
- 清理开发者侧功能完善工作日志文件
- 删除全局.gitignore配置文件,清理无用忽略规则
- 优化应用配置页面的参数读取和路由结构,解决刷新404问题
- 解决数据库配置唯一键冲突,调整保存逻辑避免重复插入
- 移除对后端配置加密字段的 secret 标记,修正加密异常问题
2026-04-09 07:35:34 +08:00

18 lines
260 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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.

CREATE TABLE IF NOT EXISTS _content_info (id TEXT PRIMARY KEY, "ready" BOOLEAN, "structureVersion" VARCHAR, "version" VARCHAR, "__hash__" TEXT UNIQUE); -- structure
INSERT INTO _content_info VALUES ('checksum_docs', false, 'quFkNIUZZFAwcn0ok74-KsIERem9u0p5DW-cqEgxrPA', 'v3.5.0--jyttfyMCdlkkD2Cy6uAigSOupLz7w9JK12BEQDx-Jb8', '0Z0mnYn3eH5Uu-q6HoFazESkAO3KD7UVALLwkXG_HCo'); -- meta
DROP TABLE IF EXISTS _content_docs; -- structure
CREATE TABLE IF NOT EXISTS _content_docs (id TEXT PRIMARY KEY, "title" VARCHAR, "body" TEXT, "description" VARCHAR, "extension" VARCHAR, "meta" TEXT, "navigation" TEXT DEFAULT true, "path" VARCHAR, "seo" TEXT DEFAULT '{}', "stem" VARCHAR, "__hash__" TEXT UNIQUE); -- structure
INSERT INTO _content_docs VALUES ('docs/docs/ai/agent.md', 'AI 智能体接入', '{"type":"minimark","value":[["h1",{"id":"ai-智能体接入"},"AI 智能体接入"],["blockquote",{},["p",{},"集成 AI Agent实现知识库问答、工作流触发与多模型切换。"]],["h2",{"id":"什么是-ai-智能体"},"🧠 什么是 AI 智能体?"],["p",{},"AI 智能体AI Agent是 Websopy 平台的核心能力,它能:"],["ul",{},["li",{},"🤖 基于自然语言理解用户意图"],["li",{},"📚 连接你的知识库进行精准问答"],["li",{},"🔗 触发业务工作流执行自动化任务"],["li",{},"🔄 在多个 AI 模型间智能切换"]],["h2",{"id":"前提条件"},"📋 前提条件"],["ul",{},["li",{},"已完成 ",["a",{"href":"/developer/docs/getting-started/quickstart"},"快速上手"]],["li",{},"已开通 AI 功能(控制台 → 开发者中心 → AI 功能)"]],["h2",{"id":"接入步骤"},"🚀 接入步骤"],["h3",{"id":"第一步安装-ai-sdk"},"第一步:安装 AI SDK"],["pre",{"className":"language-bash shiki shiki-themes github-light github-dark","code":"npm install @websopy/ai-sdk\n","language":"bash","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sScJk"},"npm"],["span",{"class":"sZZnC"}," install"],["span",{"class":"sZZnC"}," @websopy/ai-sdk\n"]]]],["h3",{"id":"第二步初始化-agent"},"第二步:初始化 Agent"],["pre",{"className":"language-typescript shiki shiki-themes github-light github-dark","code":"import { AIAgent } from ''@websopy/ai-sdk''\n\nconst agent = new AIAgent({\n apiKey: process.env.WEBSOPY_API_KEY,\n defaultModel: ''gpt-4'',\n models: [''gpt-4'', ''claude-3'', ''gemini-pro'']\n})\n","language":"typescript","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"szBVR"},"import"],["span",{"class":"sVt8B"}," { AIAgent } "],["span",{"class":"szBVR"},"from"],["span",{"class":"sZZnC"}," ''@websopy/ai-sdk''\n"]],["span",{"class":"line","line":2},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":3},["span",{"class":"szBVR"},"const"],["span",{"class":"sj4cs"}," agent"],["span",{"class":"szBVR"}," ="],["span",{"class":"szBVR"}," new"],["span",{"class":"sScJk"}," AIAgent"],["span",{"class":"sVt8B"},"({\n"]],["span",{"class":"line","line":4},["span",{"class":"sVt8B"}," apiKey: process.env."],["span",{"class":"sj4cs"},"WEBSOPY_API_KEY"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":5},["span",{"class":"sVt8B"}," defaultModel: "],["span",{"class":"sZZnC"},"''gpt-4''"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":6},["span",{"class":"sVt8B"}," models: ["],["span",{"class":"sZZnC"},"''gpt-4''"],["span",{"class":"sVt8B"},", "],["span",{"class":"sZZnC"},"''claude-3''"],["span",{"class":"sVt8B"},", "],["span",{"class":"sZZnC"},"''gemini-pro''"],["span",{"class":"sVt8B"},"]\n"]],["span",{"class":"line","line":7},["span",{"class":"sVt8B"},"})\n"]]]],["h3",{"id":"第三步创建会话"},"第三步:创建会话"],["pre",{"className":"language-typescript shiki shiki-themes github-light github-dark","code":"const session = await agent.createSession({\n userId: ''user-123'',\n knowledgeBaseId: ''kb-abc456'',\n metadata: {\n source: ''website'',\n language: ''zh-CN''\n }\n})\n\nconsole.log(''会话 ID:'', session.id)\n","language":"typescript","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"szBVR"},"const"],["span",{"class":"sj4cs"}," session"],["span",{"class":"szBVR"}," ="],["span",{"class":"szBVR"}," await"],["span",{"class":"sVt8B"}," agent."],["span",{"class":"sScJk"},"createSession"],["span",{"class":"sVt8B"},"({\n"]],["span",{"class":"line","line":2},["span",{"class":"sVt8B"}," userId: "],["span",{"class":"sZZnC"},"''user-123''"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":3},["span",{"class":"sVt8B"}," knowledgeBaseId: "],["span",{"class":"sZZnC"},"''kb-abc456''"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":4},["span",{"class":"sVt8B"}," metadata: {\n"]],["span",{"class":"line","line":5},["span",{"class":"sVt8B"}," source: "],["span",{"class":"sZZnC"},"''website''"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":6},["span",{"class":"sVt8B"}," language: "],["span",{"class":"sZZnC"},"''zh-CN''\n"]],["span",{"class":"line","line":7},["span",{"class":"sVt8B"}," }\n"]],["span",{"class":"line","line":8},["span",{"class":"sVt8B"},"})\n"]],["span",{"class":"line","line":9},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":10},["span",{"class":"sVt8B"},"console."],["span",{"class":"sScJk"},"log"],["span",{"class":"sVt8B"},"("],["span",{"class":"sZZnC"},"''会话 ID:''"],["span",{"class":"sVt8B"},", session.id)\n"]]]],["h3",{"id":"第四步发送消息"},"第四步:发送消息"],["pre",{"className":"language-typescript shiki shiki-themes github-light github-dark","code":"const response = await agent.sendMessage(session.id, {\n content: ''我想了解你们的产品价格'',\n context: {\n userPlan: ''free'',\n priority: ''normal''\n }\n})\n\nconsole.log(''AI 回复:'', response.content)\nconsole.log(''使用模型:'', response.model)\n","language":"typescript","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"szBVR"},"const"],["span",{"class":"sj4cs"}," response"],["span",{"class":"szBVR"}," ="],["span",{"class":"szBVR"}," await"],["span",{"class":"sVt8B"}," agent."],["span",{"class":"sScJk"},"sendMessage"],["span",{"class":"sVt8B"},"(session.id, {\n"]],["span",{"class":"line","line":2},["span",{"class":"sVt8B"}," content: "],["span",{"class":"sZZnC"},"''我想了解你们的产品价格''"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":3},["span",{"class":"sVt8B"}," context: {\n"]],["span",{"class":"line","line":4},["span",{"class":"sVt8B"}," userPlan: "],["span",{"class":"sZZnC"},"''free''"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":5},["span",{"class":"sVt8B"}," priority: "],["span",{"class":"sZZnC"},"''normal''\n"]],["span",{"class":"line","line":6},["span",{"class":"sVt8B"}," }\n"]],["span",{"class":"line","line":7},["span",{"class":"sVt8B"},"})\n"]],["span",{"class":"line","line":8},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":9},["span",{"class":"sVt8B"},"console."],["span",{"class":"sScJk"},"log"],["span",{"class":"sVt8B"},"("],["span",{"class":"sZZnC"},"''AI 回复:''"],["span",{"class":"sVt8B"},", response.content)\n"]],["span",{"class":"line","line":10},["span",{"class":"sVt8B"},"console."],["span",{"class":"sScJk"},"log"],["span",{"class":"sVt8B"},"("],["span",{"class":"sZZnC"},"''使用模型:''"],["span",{"class":"sVt8B"},", response.model)\n"]]]],["h3",{"id":"第五步流式响应sse"},"第五步流式响应SSE"],["pre",{"className":"language-typescript shiki shiki-themes github-light github-dark","code":"const stream = await agent.sendMessageStream(session.id, {\n content: ''写一篇关于 AI 的博客文章''\n})\n\nfor await (const chunk of stream) {\n process.stdout.write(chunk.content)\n}\n","language":"typescript","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"szBVR"},"const"],["span",{"class":"sj4cs"}," stream"],["span",{"class":"szBVR"}," ="],["span",{"class":"szBVR"}," await"],["span",{"class":"sVt8B"}," agent."],["span",{"class":"sScJk"},"sendMessageStream"],["span",{"class":"sVt8B"},"(session.id, {\n"]],["span",{"class":"line","line":2},["span",{"class":"sVt8B"}," content: "],["span",{"class":"sZZnC"},"''写一篇关于 AI 的博客文章''\n"]],["span",{"class":"line","line":3},["span",{"class":"sVt8B"},"})\n"]],["span",{"class":"line","line":4},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":5},["span",{"class":"szBVR"},"for"],["span",{"class":"szBVR"}," await"],["span",{"class":"sVt8B"}," ("],["span",{"class":"szBVR"},"const"],["span",{"class":"sj4cs"}," chunk"],["span",{"class":"szBVR"}," of"],["span",{"class":"sVt8B"}," stream) {\n"]],["span",{"class":"line","line":6},["span",{"class":"sVt8B"}," process.stdout."],["span",{"class":"sScJk"},"write"],["span",{"class":"sVt8B"},"(chunk.content)\n"]],["span",{"class":"line","line":7},["span",{"class":"sVt8B"},"}\n"]]]],["h2",{"id":"知识库集成"},"📚 知识库集成"],["pre",{"className":"language-typescript shiki shiki-themes github-light github-dark","code":"const kb = await agent.createKnowledgeBase({\n name: ''产品文档'',\n description: ''公司产品相关文档'',\n embeddingModel: ''text-embedding-3-small''\n})\n\nawait agent.uploadDocument(kb.id, {\n file: ''./docs/product-guide.pdf'',\n metadata: {\n category: ''documentation'',\n version: ''2.0''\n }\n})\n","language":"typescript","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"szBVR"},"const"],["span",{"class":"sj4cs"}," kb"],["span",{"class":"szBVR"}," ="],["span",{"class":"szBVR"}," await"],["span",{"class":"sVt8B"}," agent."],["span",{"class":"sScJk"},"createKnowledgeBase"],["span",{"class":"sVt8B"},"({\n"]],["span",{"class":"line","line":2},["span",{"class":"sVt8B"}," name: "],["span",{"class":"sZZnC"},"''产品文档''"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":3},["span",{"class":"sVt8B"}," description: "],["span",{"class":"sZZnC"},"''公司产品相关文档''"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":4},["span",{"class":"sVt8B"}," embeddingModel: "],["span",{"class":"sZZnC"},"''text-embedding-3-small''\n"]],["span",{"class":"line","line":5},["span",{"class":"sVt8B"},"})\n"]],["span",{"class":"line","line":6},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":7},["span",{"class":"szBVR"},"await"],["span",{"class":"sVt8B"}," agent."],["span",{"class":"sScJk"},"uploadDocument"],["span",{"class":"sVt8B"},"(kb.id, {\n"]],["span",{"class":"line","line":8},["span",{"class":"sVt8B"}," file: "],["span",{"class":"sZZnC"},"''./docs/product-guide.pdf''"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":9},["span",{"class":"sVt8B"}," metadata: {\n"]],["span",{"class":"line","line":10},["span",{"class":"sVt8B"}," category: "],["span",{"class":"sZZnC"},"''documentation''"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":11},["span",{"class":"sVt8B"}," version: "],["span",{"class":"sZZnC"},"''2.0''\n"]],["span",{"class":"line","line":12},["span",{"class":"sVt8B"}," }\n"]],["span",{"class":"line","line":13},["span",{"class":"sVt8B"},"})\n"]]]],["h2",{"id":"多模型切换"},"🔄 多模型切换"],["h3",{"id":"自动路由"},"自动路由"],["p",{},"根据任务类型自动选择最优模型:"],["pre",{"className":"language-typescript shiki shiki-themes github-light github-dark","code":"const agent = new AIAgent({\n apiKey: process.env.WEBSOPY_API_KEY,\n autoRoute: {\n enabled: true,\n rules: [\n { task: ''coding'', models: [''gpt-4'', ''claude-3''] },\n { task: ''creative'', models: [''gpt-4'', ''gemini-pro''] },\n { task: ''analysis'', models: [''claude-3'', ''gpt-4''] }\n ]\n }\n})\n","language":"typescript","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"szBVR"},"const"],["span",{"class":"sj4cs"}," agent"],["span",{"class":"szBVR"}," ="],["span",{"class":"szBVR"}," new"],["span",{"class":"sScJk"}," AIAgent"],["span",{"class":"sVt8B"},"({\n"]],["span",{"class":"line","line":2},["span",{"class":"sVt8B"}," apiKey: process.env."],["span",{"class":"sj4cs"},"WEBSOPY_API_KEY"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":3},["span",{"class":"sVt8B"}," autoRoute: {\n"]],["span",{"class":"line","line":4},["span",{"class":"sVt8B"}," enabled: "],["span",{"class":"sj4cs"},"true"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":5},["span",{"class":"sVt8B"}," rules: [\n"]],["span",{"class":"line","line":6},["span",{"class":"sVt8B"}," { task: "],["span",{"class":"sZZnC"},"''coding''"],["span",{"class":"sVt8B"},", models: ["],["span",{"class":"sZZnC"},"''gpt-4''"],["span",{"class":"sVt8B"},", "],["span",{"class":"sZZnC"},"''claude-3''"],["span",{"class":"sVt8B"},"] },\n"]],["span",{"class":"line","line":7},["span",{"class":"sVt8B"}," { task: "],["span",{"class":"sZZnC"},"''creative''"],["span",{"class":"sVt8B"},", models: ["],["span",{"class":"sZZnC"},"''gpt-4''"],["span",{"class":"sVt8B"},", "],["span",{"class":"sZZnC"},"''gemini-pro''"],["span",{"class":"sVt8B"},"] },\n"]],["span",{"class":"line","line":8},["span",{"class":"sVt8B"}," { task: "],["span",{"class":"sZZnC"},"''analysis''"],["span",{"class":"sVt8B"},", models: ["],["span",{"class":"sZZnC"},"''claude-3''"],["span",{"class":"sVt8B"},", "],["span",{"class":"sZZnC"},"''gpt-4''"],["span",{"class":"sVt8B"},"] }\n"]],["span",{"class":"line","line":9},["span",{"class":"sVt8B"}," ]\n"]],["span",{"class":"line","line":10},["span",{"class":"sVt8B"}," }\n"]],["span",{"class":"line","line":11},["span",{"class":"sVt8B"},"})\n"]]]],["h2",{"id":"完整示例"},"🧪 完整示例"],["pre",{"className":"language-typescript shiki shiki-themes github-light github-dark","code":"import { AIAgent } from ''@websopy/ai-sdk''\n\nasync function main() {\n const agent = new AIAgent({\n apiKey: process.env.WEBSOPY_API_KEY,\n defaultModel: ''gpt-4''\n })\n\n const session = await agent.createSession({\n userId: ''user-123'',\n knowledgeBaseId: ''kb-product-docs''\n })\n\n const messages = [\n ''你好,我想了解一下企业版的功能'',\n ''支持私有化部署吗?'',\n ''好的,我想试用一下''\n ]\n\n for (const msg of messages) {\n const response = await agent.sendMessage(session.id, { content: msg })\n console.log(`\\n👤 用户: ${msg}`)\n console.log(`🤖 AI: ${response.content}`)\n }\n}\n\nmain()\n","language":"typescript","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"szBVR"},"import"],["span",{"class":"sVt8B"}," { AIAgent } "],["span",{"class":"szBVR"},"from"],["span",{"class":"sZZnC"}," ''@websopy/ai-sdk''\n"]],["span",{"class":"line","line":2},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":3},["span",{"class":"szBVR"},"async"],["span",{"class":"szBVR"}," function"],["span",{"class":"sScJk"}," main"],["span",{"class":"sVt8B"},"() {\n"]],["span",{"class":"line","line":4},["span",{"class":"szBVR"}," const"],["span",{"class":"sj4cs"}," agent"],["span",{"class":"szBVR"}," ="],["span",{"class":"szBVR"}," new"],["span",{"class":"sScJk"}," AIAgent"],["span",{"class":"sVt8B"},"({\n"]],["span",{"class":"line","line":5},["span",{"class":"sVt8B"}," apiKey: process.env."],["span",{"class":"sj4cs"},"WEBSOPY_API_KEY"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":6},["span",{"class":"sVt8B"}," defaultModel: "],["span",{"class":"sZZnC"},"''gpt-4''\n"]],["span",{"class":"line","line":7},["span",{"class":"sVt8B"}," })\n"]],["span",{"class":"line","line":8},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":9},["span",{"class":"szBVR"}," const"],["span",{"class":"sj4cs"}," session"],["span",{"class":"szBVR"}," ="],["span",{"class":"szBVR"}," await"],["span",{"class":"sVt8B"}," agent."],["span",{"class":"sScJk"},"createSession"],["span",{"class":"sVt8B"},"({\n"]],["span",{"class":"line","line":10},["span",{"class":"sVt8B"}," userId: "],["span",{"class":"sZZnC"},"''user-123''"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":11},["span",{"class":"sVt8B"}," knowledgeBaseId: "],["span",{"class":"sZZnC"},"''kb-product-docs''\n"]],["span",{"class":"line","line":12},["span",{"class":"sVt8B"}," })\n"]],["span",{"class":"line","line":13},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":14},["span",{"class":"szBVR"}," const"],["span",{"class":"sj4cs"}," messages"],["span",{"class":"szBVR"}," ="],["span",{"class":"sVt8B"}," [\n"]],["span",{"class":"line","line":15},["span",{"class":"sZZnC"}," ''你好,我想了解一下企业版的功能''"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":16},["span",{"class":"sZZnC"}," ''支持私有化部署吗?''"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":17},["span",{"class":"sZZnC"}," ''好的,我想试用一下''\n"]],["span",{"class":"line","line":18},["span",{"class":"sVt8B"}," ]\n"]],["span",{"class":"line","line":19},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":20},["span",{"class":"szBVR"}," for"],["span",{"class":"sVt8B"}," ("],["span",{"class":"szBVR"},"const"],["span",{"class":"sj4cs"}," msg"],["span",{"class":"szBVR"}," of"],["span",{"class":"sVt8B"}," messages) {\n"]],["span",{"class":"line","line":21},["span",{"class":"szBVR"}," const"],["span",{"class":"sj4cs"}," response"],["span",{"class":"szBVR"}," ="],["span",{"class":"szBVR"}," await"],["span",{"class":"sVt8B"}," agent."],["span",{"class":"sScJk"},"sendMessage"],["span",{"class":"sVt8B"},"(session.id, { content: msg })\n"]],["span",{"class":"line","line":22},["span",{"class":"sVt8B"}," console."],["span",{"class":"sScJk"},"log"],["span",{"class":"sVt8B"},"("],["span",{"class":"sZZnC"},"`"],["span",{"class":"sj4cs"},"\\n"],["span",{"class":"sZZnC"},"👤 用户: ${"],["span",{"class":"sVt8B"},"msg"],["span",{"class":"sZZnC"},"}`"],["span",{"class":"sVt8B"},")\n"]],["span",{"class":"line","line":23},["span",{"class":"sVt8B"}," console."],["span",{"class":"sScJk"},"log"],["span",{"class":"sVt8B"},"("],["span",{"class":"sZZnC"},"`🤖 AI: ${"],["span",{"class":"sVt8B"},"response"],["span",{"class":"sZZnC"},"."],["span",{"class":"sVt8B"},"content"],["span",{"class":"sZZnC"},"}`"],["span",{"class":"sVt8B"},")\n"]],["span",{"class":"line","line":24},["span",{"class":"sVt8B"}," }\n"]],["span",{"class":"line","line":25},["span",{"class":"sVt8B"},"}\n"]],["span",{"class":"line","line":26},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":27},["span",{"class":"sScJk"},"main"],["span",{"class":"sVt8B"},"()\n"]]]],["h2",{"id":"常见问题"},"❓ 常见问题"],["h3",{"id":"q-支持哪些-embedding-模型"},"Q: 支持哪些 Embedding 模型?"],["p",{},"目前支持:"],["ul",{},["li",{},["code",{},"text-embedding-3-small"],"(推荐,速度快)"],["li",{},["code",{},"text-embedding-3-large"],"(高精度)"],["li",{},["code",{},"text-embedding-ada-002"],"(兼容性)"]],["h3",{"id":"q-知识库检索不到相关内容"},"Q: 知识库检索不到相关内容?"],["ol",{},["li",{},"检查文档是否已成功上传和向量化"],["li",{},"调整 ",["code",{},"scoreThreshold"]," 降低阈值"],["li",{},"尝试增加 ",["code",{},"topK"]," 获取更多候选"]],["style",{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}"]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"什么是-ai-智能体","depth":2,"text":"🧠 什么是 AI 智能体?"},{"id":"前提条件","depth":2,"text":"📋 前提条件"},{"id":"接入步骤","depth":2,"text":"🚀 接入步骤","children":[{"id":"第一步安装-ai-sdk","depth":3,"text":"第一步:安装 AI SDK"},{"id":"第二步初始化-agent","depth":3,"text":"第二步:初始化 Agent"},{"id":"第三步创建会话","depth":3,"text":"第三步:创建会话"},{"id":"第四步发送消息","depth":3,"text":"第四步:发送消息"},{"id":"第五步流式响应sse","depth":3,"text":"第五步流式响应SSE"}]},{"id":"知识库集成","depth":2,"text":"📚 知识库集成"},{"id":"多模型切换","depth":2,"text":"🔄 多模型切换","children":[{"id":"自动路由","depth":3,"text":"自动路由"}]},{"id":"完整示例","depth":2,"text":"🧪 完整示例"},{"id":"常见问题","depth":2,"text":"❓ 常见问题","children":[{"id":"q-支持哪些-embedding-模型","depth":3,"text":"Q: 支持哪些 Embedding 模型?"},{"id":"q-知识库检索不到相关内容","depth":3,"text":"Q: 知识库检索不到相关内容?"}]}]}}', '集成 AI Agent实现知识库问答、工作流触发与多模型切换。', 'md', '{"category":"ai","order":1}', 'true', '/docs/ai/agent', '{"title":"AI 智能体接入","description":"集成 AI Agent实现知识库问答、工作流触发与多模型切换。"}', 'docs/ai/agent', 'aYeCTE7aiIr5B_LqjvVhtpMOyh9-xfwEvuxpdb32bRQ'); -- aYeCTE7aiIr5B_LqjvVhtpMOyh9-xfwEvuxpdb32bRQ
INSERT INTO _content_docs VALUES ('docs/docs/ai/rag.md', 'RAG 知识库搭建', '{"type":"minimark","value":[["h1",{"id":"rag-知识库搭建"},"RAG 知识库搭建"],["blockquote",{},["p",{},"上传文档、向量化存储,构建企业级知识库问答系统。"]],["h2",{"id":"什么是-rag"},"🧠 什么是 RAG"],["p",{},"RAGRetrieval-Augmented Generation检索增强生成是一种结合「知识检索」和「AI 生成」的技术:"],["ol",{},["li",{},["strong",{},"检索"],":从知识库中找到相关内容"],["li",{},["strong",{},"增强"],":将检索结果作为上下文"],["li",{},["strong",{},"生成"],":让 AI 基于上下文生成答案"]],["pre",{"className":["language-text"],"code":"用户问题 → 检索相关文档 → 拼接到 Prompt → AI 生成回答\n","language":"text"},["code",{"__ignoreMap":""},"用户问题 → 检索相关文档 → 拼接到 Prompt → AI 生成回答\n"]],["h2",{"id":"适用场景"},"📋 适用场景"],["ul",{},["li",{},"📄 企业内部文档问答"],["li",{},"🎯 产品 FAQ 自动化"],["li",{},"📚 培训资料检索"],["li",{},"🔍 合同/政策查询"],["li",{},"🏥 专业知识库"]],["h2",{"id":"搭建步骤"},"🚀 搭建步骤"],["h3",{"id":"第一步创建知识库"},"第一步:创建知识库"],["pre",{"className":"language-typescript shiki shiki-themes github-light github-dark","code":"const knowledgeBase = await client.ai.createKnowledgeBase({\n name: ''产品使用手册'',\n description: ''公司产品相关文档'',\n embeddingModel: ''text-embedding-3-small'',\n chunking: {\n type: ''recursive'',\n chunkSize: 1000,\n chunkOverlap: 200\n }\n})\n\nconsole.log(''知识库 ID:'', knowledgeBase.id)\n","language":"typescript","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"szBVR"},"const"],["span",{"class":"sj4cs"}," knowledgeBase"],["span",{"class":"szBVR"}," ="],["span",{"class":"szBVR"}," await"],["span",{"class":"sVt8B"}," client.ai."],["span",{"class":"sScJk"},"createKnowledgeBase"],["span",{"class":"sVt8B"},"({\n"]],["span",{"class":"line","line":2},["span",{"class":"sVt8B"}," name: "],["span",{"class":"sZZnC"},"''产品使用手册''"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":3},["span",{"class":"sVt8B"}," description: "],["span",{"class":"sZZnC"},"''公司产品相关文档''"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":4},["span",{"class":"sVt8B"}," embeddingModel: "],["span",{"class":"sZZnC"},"''text-embedding-3-small''"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":5},["span",{"class":"sVt8B"}," chunking: {\n"]],["span",{"class":"line","line":6},["span",{"class":"sVt8B"}," type: "],["span",{"class":"sZZnC"},"''recursive''"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":7},["span",{"class":"sVt8B"}," chunkSize: "],["span",{"class":"sj4cs"},"1000"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":8},["span",{"class":"sVt8B"}," chunkOverlap: "],["span",{"class":"sj4cs"},"200\n"]],["span",{"class":"line","line":9},["span",{"class":"sVt8B"}," }\n"]],["span",{"class":"line","line":10},["span",{"class":"sVt8B"},"})\n"]],["span",{"class":"line","line":11},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":12},["span",{"class":"sVt8B"},"console."],["span",{"class":"sScJk"},"log"],["span",{"class":"sVt8B"},"("],["span",{"class":"sZZnC"},"''知识库 ID:''"],["span",{"class":"sVt8B"},", knowledgeBase.id)\n"]]]],["h3",{"id":"第二步上传文档"},"第二步:上传文档"],["p",{},"支持格式PDF、Word、TXT、Markdown、HTML"],["pre",{"className":"language-typescript shiki shiki-themes github-light github-dark","code":"// 上传单个文件\nconst doc = await client.ai.uploadDocument(knowledgeBase.id, {\n file: ''./docs/user-guide.pdf'',\n metadata: {\n category: ''manual'',\n version: ''2.0'',\n language: ''zh-CN''\n }\n})\n\n// 批量上传\nconst docs = await client.ai.uploadDocuments(knowledgeBase.id, [\n { file: ''./docs/faq.md'', metadata: { category: ''faq'' } },\n { file: ''./docs/api.md'', metadata: { category: ''api'' } },\n])\n","language":"typescript","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sJ8bj"},"// 上传单个文件\n"]],["span",{"class":"line","line":2},["span",{"class":"szBVR"},"const"],["span",{"class":"sj4cs"}," doc"],["span",{"class":"szBVR"}," ="],["span",{"class":"szBVR"}," await"],["span",{"class":"sVt8B"}," client.ai."],["span",{"class":"sScJk"},"uploadDocument"],["span",{"class":"sVt8B"},"(knowledgeBase.id, {\n"]],["span",{"class":"line","line":3},["span",{"class":"sVt8B"}," file: "],["span",{"class":"sZZnC"},"''./docs/user-guide.pdf''"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":4},["span",{"class":"sVt8B"}," metadata: {\n"]],["span",{"class":"line","line":5},["span",{"class":"sVt8B"}," category: "],["span",{"class":"sZZnC"},"''manual''"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":6},["span",{"class":"sVt8B"}," version: "],["span",{"class":"sZZnC"},"''2.0''"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":7},["span",{"class":"sVt8B"}," language: "],["span",{"class":"sZZnC"},"''zh-CN''\n"]],["span",{"class":"line","line":8},["span",{"class":"sVt8B"}," }\n"]],["span",{"class":"line","line":9},["span",{"class":"sVt8B"},"})\n"]],["span",{"class":"line","line":10},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":11},["span",{"class":"sJ8bj"},"// 批量上传\n"]],["span",{"class":"line","line":12},["span",{"class":"szBVR"},"const"],["span",{"class":"sj4cs"}," docs"],["span",{"class":"szBVR"}," ="],["span",{"class":"szBVR"}," await"],["span",{"class":"sVt8B"}," client.ai."],["span",{"class":"sScJk"},"uploadDocuments"],["span",{"class":"sVt8B"},"(knowledgeBase.id, [\n"]],["span",{"class":"line","line":13},["span",{"class":"sVt8B"}," { file: "],["span",{"class":"sZZnC"},"''./docs/faq.md''"],["span",{"class":"sVt8B"},", metadata: { category: "],["span",{"class":"sZZnC"},"''faq''"],["span",{"class":"sVt8B"}," } },\n"]],["span",{"class":"line","line":14},["span",{"class":"sVt8B"}," { file: "],["span",{"class":"sZZnC"},"''./docs/api.md''"],["span",{"class":"sVt8B"},", metadata: { category: "],["span",{"class":"sZZnC"},"''api''"],["span",{"class":"sVt8B"}," } },\n"]],["span",{"class":"line","line":15},["span",{"class":"sVt8B"},"])\n"]]]],["h3",{"id":"第三步配置检索"},"第三步:配置检索"],["pre",{"className":"language-typescript shiki shiki-themes github-light github-dark","code":"await client.ai.configureRetrieval(knowledgeBase.id, {\n retrieval: {\n topK: 5,\n scoreThreshold: 0.7,\n hybridSearch: true\n },\n rerank: {\n enabled: true,\n model: ''bge-reranker''\n }\n})\n","language":"typescript","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"szBVR"},"await"],["span",{"class":"sVt8B"}," client.ai."],["span",{"class":"sScJk"},"configureRetrieval"],["span",{"class":"sVt8B"},"(knowledgeBase.id, {\n"]],["span",{"class":"line","line":2},["span",{"class":"sVt8B"}," retrieval: {\n"]],["span",{"class":"line","line":3},["span",{"class":"sVt8B"}," topK: "],["span",{"class":"sj4cs"},"5"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":4},["span",{"class":"sVt8B"}," scoreThreshold: "],["span",{"class":"sj4cs"},"0.7"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":5},["span",{"class":"sVt8B"}," hybridSearch: "],["span",{"class":"sj4cs"},"true\n"]],["span",{"class":"line","line":6},["span",{"class":"sVt8B"}," },\n"]],["span",{"class":"line","line":7},["span",{"class":"sVt8B"}," rerank: {\n"]],["span",{"class":"line","line":8},["span",{"class":"sVt8B"}," enabled: "],["span",{"class":"sj4cs"},"true"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":9},["span",{"class":"sVt8B"}," model: "],["span",{"class":"sZZnC"},"''bge-reranker''\n"]],["span",{"class":"line","line":10},["span",{"class":"sVt8B"}," }\n"]],["span",{"class":"line","line":11},["span",{"class":"sVt8B"},"})\n"]]]],["h3",{"id":"第四步问答"},"第四步:问答"],["pre",{"className":"language-typescript shiki shiki-themes github-light github-dark","code":"const response = await client.ai.ask({\n knowledgeBaseId: knowledgeBase.id,\n question: ''如何创建新项目?'',\n options: {\n maxTokens: 1000,\n temperature: 0.7,\n includeSources: true\n }\n})\n\nconsole.log(''回答:'', response.answer)\nconsole.log(''引用:'', response.citations)\n","language":"typescript","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"szBVR"},"const"],["span",{"class":"sj4cs"}," response"],["span",{"class":"szBVR"}," ="],["span",{"class":"szBVR"}," await"],["span",{"class":"sVt8B"}," client.ai."],["span",{"class":"sScJk"},"ask"],["span",{"class":"sVt8B"},"({\n"]],["span",{"class":"line","line":2},["span",{"class":"sVt8B"}," knowledgeBaseId: knowledgeBase.id,\n"]],["span",{"class":"line","line":3},["span",{"class":"sVt8B"}," question: "],["span",{"class":"sZZnC"},"''如何创建新项目?''"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":4},["span",{"class":"sVt8B"}," options: {\n"]],["span",{"class":"line","line":5},["span",{"class":"sVt8B"}," maxTokens: "],["span",{"class":"sj4cs"},"1000"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":6},["span",{"class":"sVt8B"}," temperature: "],["span",{"class":"sj4cs"},"0.7"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":7},["span",{"class":"sVt8B"}," includeSources: "],["span",{"class":"sj4cs"},"true\n"]],["span",{"class":"line","line":8},["span",{"class":"sVt8B"}," }\n"]],["span",{"class":"line","line":9},["span",{"class":"sVt8B"},"})\n"]],["span",{"class":"line","line":10},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":11},["span",{"class":"sVt8B"},"console."],["span",{"class":"sScJk"},"log"],["span",{"class":"sVt8B"},"("],["span",{"class":"sZZnC"},"''回答:''"],["span",{"class":"sVt8B"},", response.answer)\n"]],["span",{"class":"line","line":12},["span",{"class":"sVt8B"},"console."],["span",{"class":"sScJk"},"log"],["span",{"class":"sVt8B"},"("],["span",{"class":"sZZnC"},"''引用:''"],["span",{"class":"sVt8B"},", response.citations)\n"]]]],["h3",{"id":"响应示例"},"响应示例"],["pre",{"className":"language-json shiki shiki-themes github-light github-dark","code":"{\n \"answer\": \"创建新项目的步骤如下:\\n1. 点击「新建项目」按钮\\n2. 填写项目名称和描述\\n3. 选择项目模板\\n4. 点击「创建」完成\",\n \"citations\": [\n {\n \"document_id\": \"doc_abc123\",\n \"chunk_text\": \"点击「新建项目」按钮,进入项目创建页面...\",\n \"score\": 0.95\n }\n ],\n \"model\": \"gpt-4\",\n \"tokens_used\": 850\n}\n","language":"json","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sVt8B"},"{\n"]],["span",{"class":"line","line":2},["span",{"class":"sj4cs"}," \"answer\""],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"\"创建新项目的步骤如下:"],["span",{"class":"sj4cs"},"\\n"],["span",{"class":"sZZnC"},"1. 点击「新建项目」按钮"],["span",{"class":"sj4cs"},"\\n"],["span",{"class":"sZZnC"},"2. 填写项目名称和描述"],["span",{"class":"sj4cs"},"\\n"],["span",{"class":"sZZnC"},"3. 选择项目模板"],["span",{"class":"sj4cs"},"\\n"],["span",{"class":"sZZnC"},"4. 点击「创建」完成\""],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":3},["span",{"class":"sj4cs"}," \"citations\""],["span",{"class":"sVt8B"},": [\n"]],["span",{"class":"line","line":4},["span",{"class":"sVt8B"}," {\n"]],["span",{"class":"line","line":5},["span",{"class":"sj4cs"}," \"document_id\""],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"\"doc_abc123\""],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":6},["span",{"class":"sj4cs"}," \"chunk_text\""],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"\"点击「新建项目」按钮,进入项目创建页面...\""],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":7},["span",{"class":"sj4cs"}," \"score\""],["span",{"class":"sVt8B"},": "],["span",{"class":"sj4cs"},"0.95\n"]],["span",{"class":"line","line":8},["span",{"class":"sVt8B"}," }\n"]],["span",{"class":"line","line":9},["span",{"class":"sVt8B"}," ],\n"]],["span",{"class":"line","line":10},["span",{"class":"sj4cs"}," \"model\""],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"\"gpt-4\""],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":11},["span",{"class":"sj4cs"}," \"tokens_used\""],["span",{"class":"sVt8B"},": "],["span",{"class":"sj4cs"},"850\n"]],["span",{"class":"line","line":12},["span",{"class":"sVt8B"},"}\n"]]]],["h2",{"id":"最佳实践"},"🧪 最佳实践"],["h3",{"id":"文档准备"},"文档准备"],["ol",{},["li",{},"✅ 清理格式,移除无关内容"],["li",{},"✅ 添加目录和标题结构"],["li",{},"✅ QA 格式文档效果最好"],["li",{},"❌ 避免过长的无结构文本"],["li",{},"❌ 避免大量表格(难以正确分块)"]],["h3",{"id":"检索优化"},"检索优化"],["pre",{"className":"language-typescript shiki shiki-themes github-light github-dark","code":"const optimalConfig = {\n topK: 3, // 不要太多,可能引入噪音\n scoreThreshold: 0.75, // 设置合理阈值\n enableRerank: true // 启用重排序\n}\n","language":"typescript","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"szBVR"},"const"],["span",{"class":"sj4cs"}," optimalConfig"],["span",{"class":"szBVR"}," ="],["span",{"class":"sVt8B"}," {\n"]],["span",{"class":"line","line":2},["span",{"class":"sVt8B"}," topK: "],["span",{"class":"sj4cs"},"3"],["span",{"class":"sVt8B"},", "],["span",{"class":"sJ8bj"},"// 不要太多,可能引入噪音\n"]],["span",{"class":"line","line":3},["span",{"class":"sVt8B"}," scoreThreshold: "],["span",{"class":"sj4cs"},"0.75"],["span",{"class":"sVt8B"},", "],["span",{"class":"sJ8bj"},"// 设置合理阈值\n"]],["span",{"class":"line","line":4},["span",{"class":"sVt8B"}," enableRerank: "],["span",{"class":"sj4cs"},"true"],["span",{"class":"sJ8bj"}," // 启用重排序\n"]],["span",{"class":"line","line":5},["span",{"class":"sVt8B"},"}\n"]]]],["h3",{"id":"prompt-工程"},"Prompt 工程"],["pre",{"className":"language-typescript shiki shiki-themes github-light github-dark","code":"const response = await client.ai.ask({\n knowledgeBaseId: knowledgeBase.id,\n question: ''...'',\n systemPrompt: `你是一个专业客服,请基于给定的知识库内容回答用户问题。\n - 如果知识库中没有相关内容,请如实告知\n - 回答要简洁、专业、易懂\n - 适当引用原文帮助用户理解`\n})\n","language":"typescript","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"szBVR"},"const"],["span",{"class":"sj4cs"}," response"],["span",{"class":"szBVR"}," ="],["span",{"class":"szBVR"}," await"],["span",{"class":"sVt8B"}," client.ai."],["span",{"class":"sScJk"},"ask"],["span",{"class":"sVt8B"},"({\n"]],["span",{"class":"line","line":2},["span",{"class":"sVt8B"}," knowledgeBaseId: knowledgeBase.id,\n"]],["span",{"class":"line","line":3},["span",{"class":"sVt8B"}," question: "],["span",{"class":"sZZnC"},"''...''"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":4},["span",{"class":"sVt8B"}," systemPrompt: "],["span",{"class":"sZZnC"},"`你是一个专业客服,请基于给定的知识库内容回答用户问题。\n"]],["span",{"class":"line","line":5},["span",{"class":"sZZnC"}," - 如果知识库中没有相关内容,请如实告知\n"]],["span",{"class":"line","line":6},["span",{"class":"sZZnC"}," - 回答要简洁、专业、易懂\n"]],["span",{"class":"line","line":7},["span",{"class":"sZZnC"}," - 适当引用原文帮助用户理解`\n"]],["span",{"class":"line","line":8},["span",{"class":"sVt8B"},"})\n"]]]],["h2",{"id":"常见问题"},"❓ 常见问题"],["h3",{"id":"q-检索不到相关内容"},"Q: 检索不到相关内容?"],["ol",{},["li",{},"检查文档是否处理完成(状态为 ",["code",{},"ready"],""],["li",{},"降低 ",["code",{},"scoreThreshold"]," 阈值"],["li",{},"尝试 ",["code",{},"hybridSearch: true"]," 混合搜索"],["li",{},"增加 ",["code",{},"topK"]," 获取更多候选"]],["h3",{"id":"q-回答不准确"},"Q: 回答不准确?"],["ol",{},["li",{},"检查源文档质量"],["li",{},"调整 ",["code",{},"chunkSize"],",太小可能丢失上下文"],["li",{},"启用 ",["code",{},"rerank"]," 提高相关性"],["li",{},"优化 system prompt"]],["style",{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}"]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"什么是-rag","depth":2,"text":"🧠 什么是 RAG"},{"id":"适用场景","depth":2,"text":"📋 适用场景"},{"id":"搭建步骤","depth":2,"text":"🚀 搭建步骤","children":[{"id":"第一步创建知识库","depth":3,"text":"第一步:创建知识库"},{"id":"第二步上传文档","depth":3,"text":"第二步:上传文档"},{"id":"第三步配置检索","depth":3,"text":"第三步:配置检索"},{"id":"第四步问答","depth":3,"text":"第四步:问答"},{"id":"响应示例","depth":3,"text":"响应示例"}]},{"id":"最佳实践","depth":2,"text":"🧪 最佳实践","children":[{"id":"文档准备","depth":3,"text":"文档准备"},{"id":"检索优化","depth":3,"text":"检索优化"},{"id":"prompt-工程","depth":3,"text":"Prompt 工程"}]},{"id":"常见问题","depth":2,"text":"❓ 常见问题","children":[{"id":"q-检索不到相关内容","depth":3,"text":"Q: 检索不到相关内容?"},{"id":"q-回答不准确","depth":3,"text":"Q: 回答不准确?"}]}]}}', '上传文档、向量化存储,构建企业级知识库问答系统。', 'md', '{"category":"ai","order":2}', 'true', '/docs/ai/rag', '{"title":"RAG 知识库搭建","description":"上传文档、向量化存储,构建企业级知识库问答系统。"}', 'docs/ai/rag', 'DcpoLfXPgq7FWv-OLVP6_igv1nI_7FiOGJvjbOBeCDw'); -- DcpoLfXPgq7FWv-OLVP6_igv1nI_7FiOGJvjbOBeCDw
INSERT INTO _content_docs VALUES ('docs/docs/ai/workflow.md', 'AI 工作流配置', '{"type":"minimark","value":[["h1",{"id":"ai-工作流配置"},"AI 工作流配置"],["blockquote",{},["p",{},"使用工作流引擎,构建定时任务与自动化业务流。"]],["h2",{"id":"什么是工作流"},"🔄 什么是工作流?"],["p",{},"工作流Workflow是预定义的一系列自动化步骤可以"],["ul",{},["li",{},"⏰ ",["strong",{},"定时执行"],":每天早上发送报表"],["li",{},"🔗 ",["strong",{},"事件触发"],":用户注册后自动发送欢迎邮件"],["li",{},"🔁 ",["strong",{},"条件分支"],":根据条件执行不同操作"],["li",{},"📊 ",["strong",{},"数据处理"],":批量处理数据"]],["h2",{"id":"-核心概念"},"🏗️ 核心概念"],["table",{},["thead",{},["tr",{},["th",{},"概念"],["th",{},"说明"]]],["tbody",{},["tr",{},["td",{},["strong",{},"触发器 (Trigger)"]],["td",{},"工作流的启动条件"]],["tr",{},["td",{},["strong",{},"节点 (Node)"]],["td",{},"工作流中的单个步骤"]],["tr",{},["td",{},["strong",{},"连接 (Edge)"]],["td",{},"节点之间的数据流向"]],["tr",{},["td",{},["strong",{},"变量 (Variable)"]],["td",{},"存储和传递数据"]],["tr",{},["td",{},["strong",{},"执行日志"]],["td",{},"每次运行的记录"]]]],["h2",{"id":"创建第一个工作流"},"🚀 创建第一个工作流"],["h3",{"id":"代码定义"},"代码定义"],["pre",{"className":"language-typescript shiki shiki-themes github-light github-dark","code":"import { WorkflowBuilder } from ''@websopy/ai-sdk''\n\nconst workflow = new WorkflowBuilder({\n name: ''每日数据报告'',\n description: ''每天早上 9 点生成数据报告''\n})\n\n// 添加触发器:定时执行\nworkflow.addTrigger({\n type: ''schedule'',\n config: {\n cron: ''0 9 * * *'', // 每天 9:00\n timezone: ''Asia/Shanghai''\n }\n})\n\n// 添加节点:获取数据\nworkflow.addNode(''fetch-data'', {\n type: ''http-request'',\n config: {\n url: ''https://api.analytics.com/daily-stats'',\n method: ''GET''\n }\n})\n\n// 添加节点:生成报告\nworkflow.addNode(''generate-report'', {\n type: ''ai-agent'',\n config: {\n prompt: ''根据以下数据生成日报:{{fetch-data.output}}''\n }\n})\n\n// 添加节点:发送邮件\nworkflow.addNode(''send-email'', {\n type: ''email'',\n config: {\n to: [''team@company.com''],\n subject: ''📊 每日数据报告'',\n body: ''{{generate-report.output}}''\n }\n})\n\n// 节点连接\nworkflow.connect(''fetch-data'', ''generate-report'')\nworkflow.connect(''generate-report'', ''send-email'')\n\n// 保存\nconst created = await client.workflow.create(workflow.toJSON())\nconsole.log(''工作流 ID:'', created.id)\n","language":"typescript","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"szBVR"},"import"],["span",{"class":"sVt8B"}," { WorkflowBuilder } "],["span",{"class":"szBVR"},"from"],["span",{"class":"sZZnC"}," ''@websopy/ai-sdk''\n"]],["span",{"class":"line","line":2},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":3},["span",{"class":"szBVR"},"const"],["span",{"class":"sj4cs"}," workflow"],["span",{"class":"szBVR"}," ="],["span",{"class":"szBVR"}," new"],["span",{"class":"sScJk"}," WorkflowBuilder"],["span",{"class":"sVt8B"},"({\n"]],["span",{"class":"line","line":4},["span",{"class":"sVt8B"}," name: "],["span",{"class":"sZZnC"},"''每日数据报告''"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":5},["span",{"class":"sVt8B"}," description: "],["span",{"class":"sZZnC"},"''每天早上 9 点生成数据报告''\n"]],["span",{"class":"line","line":6},["span",{"class":"sVt8B"},"})\n"]],["span",{"class":"line","line":7},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":8},["span",{"class":"sJ8bj"},"// 添加触发器:定时执行\n"]],["span",{"class":"line","line":9},["span",{"class":"sVt8B"},"workflow."],["span",{"class":"sScJk"},"addTrigger"],["span",{"class":"sVt8B"},"({\n"]],["span",{"class":"line","line":10},["span",{"class":"sVt8B"}," type: "],["span",{"class":"sZZnC"},"''schedule''"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":11},["span",{"class":"sVt8B"}," config: {\n"]],["span",{"class":"line","line":12},["span",{"class":"sVt8B"}," cron: "],["span",{"class":"sZZnC"},"''0 9 * * *''"],["span",{"class":"sVt8B"},", "],["span",{"class":"sJ8bj"},"// 每天 9:00\n"]],["span",{"class":"line","line":13},["span",{"class":"sVt8B"}," timezone: "],["span",{"class":"sZZnC"},"''Asia/Shanghai''\n"]],["span",{"class":"line","line":14},["span",{"class":"sVt8B"}," }\n"]],["span",{"class":"line","line":15},["span",{"class":"sVt8B"},"})\n"]],["span",{"class":"line","line":16},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":17},["span",{"class":"sJ8bj"},"// 添加节点:获取数据\n"]],["span",{"class":"line","line":18},["span",{"class":"sVt8B"},"workflow."],["span",{"class":"sScJk"},"addNode"],["span",{"class":"sVt8B"},"("],["span",{"class":"sZZnC"},"''fetch-data''"],["span",{"class":"sVt8B"},", {\n"]],["span",{"class":"line","line":19},["span",{"class":"sVt8B"}," type: "],["span",{"class":"sZZnC"},"''http-request''"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":20},["span",{"class":"sVt8B"}," config: {\n"]],["span",{"class":"line","line":21},["span",{"class":"sVt8B"}," url: "],["span",{"class":"sZZnC"},"''https://api.analytics.com/daily-stats''"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":22},["span",{"class":"sVt8B"}," method: "],["span",{"class":"sZZnC"},"''GET''\n"]],["span",{"class":"line","line":23},["span",{"class":"sVt8B"}," }\n"]],["span",{"class":"line","line":24},["span",{"class":"sVt8B"},"})\n"]],["span",{"class":"line","line":25},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":26},["span",{"class":"sJ8bj"},"// 添加节点:生成报告\n"]],["span",{"class":"line","line":27},["span",{"class":"sVt8B"},"workflow."],["span",{"class":"sScJk"},"addNode"],["span",{"class":"sVt8B"},"("],["span",{"class":"sZZnC"},"''generate-report''"],["span",{"class":"sVt8B"},", {\n"]],["span",{"class":"line","line":28},["span",{"class":"sVt8B"}," type: "],["span",{"class":"sZZnC"},"''ai-agent''"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":29},["span",{"class":"sVt8B"}," config: {\n"]],["span",{"class":"line","line":30},["span",{"class":"sVt8B"}," prompt: "],["span",{"class":"sZZnC"},"''根据以下数据生成日报:{{fetch-data.output}}''\n"]],["span",{"class":"line","line":31},["span",{"class":"sVt8B"}," }\n"]],["span",{"class":"line","line":32},["span",{"class":"sVt8B"},"})\n"]],["span",{"class":"line","line":33},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":34},["span",{"class":"sJ8bj"},"// 添加节点:发送邮件\n"]],["span",{"class":"line","line":35},["span",{"class":"sVt8B"},"workflow."],["span",{"class":"sScJk"},"addNode"],["span",{"class":"sVt8B"},"("],["span",{"class":"sZZnC"},"''send-email''"],["span",{"class":"sVt8B"},", {\n"]],["span",{"class":"line","line":36},["span",{"class":"sVt8B"}," type: "],["span",{"class":"sZZnC"},"''email''"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":37},["span",{"class":"sVt8B"}," config: {\n"]],["span",{"class":"line","line":38},["span",{"class":"sVt8B"}," to: ["],["span",{"class":"sZZnC"},"''team@company.com''"],["span",{"class":"sVt8B"},"],\n"]],["span",{"class":"line","line":39},["span",{"class":"sVt8B"}," subject: "],["span",{"class":"sZZnC"},"''📊 每日数据报告''"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":40},["span",{"class":"sVt8B"}," body: "],["span",{"class":"sZZnC"},"''{{generate-report.output}}''\n"]],["span",{"class":"line","line":41},["span",{"class":"sVt8B"}," }\n"]],["span",{"class":"line","line":42},["span",{"class":"sVt8B"},"})\n"]],["span",{"class":"line","line":43},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":44},["span",{"class":"sJ8bj"},"// 节点连接\n"]],["span",{"class":"line","line":45},["span",{"class":"sVt8B"},"workflow."],["span",{"class":"sScJk"},"connect"],["span",{"class":"sVt8B"},"("],["span",{"class":"sZZnC"},"''fetch-data''"],["span",{"class":"sVt8B"},", "],["span",{"class":"sZZnC"},"''generate-report''"],["span",{"class":"sVt8B"},")\n"]],["span",{"class":"line","line":46},["span",{"class":"sVt8B"},"workflow."],["span",{"class":"sScJk"},"connect"],["span",{"class":"sVt8B"},"("],["span",{"class":"sZZnC"},"''generate-report''"],["span",{"class":"sVt8B"},", "],["span",{"class":"sZZnC"},"''send-email''"],["span",{"class":"sVt8B"},")\n"]],["span",{"class":"line","line":47},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":48},["span",{"class":"sJ8bj"},"// 保存\n"]],["span",{"class":"line","line":49},["span",{"class":"szBVR"},"const"],["span",{"class":"sj4cs"}," created"],["span",{"class":"szBVR"}," ="],["span",{"class":"szBVR"}," await"],["span",{"class":"sVt8B"}," client.workflow."],["span",{"class":"sScJk"},"create"],["span",{"class":"sVt8B"},"(workflow."],["span",{"class":"sScJk"},"toJSON"],["span",{"class":"sVt8B"},"())\n"]],["span",{"class":"line","line":50},["span",{"class":"sVt8B"},"console."],["span",{"class":"sScJk"},"log"],["span",{"class":"sVt8B"},"("],["span",{"class":"sZZnC"},"''工作流 ID:''"],["span",{"class":"sVt8B"},", created.id)\n"]]]],["h3",{"id":"可视化编辑器"},"可视化编辑器"],["p",{},"在控制台 → AI 功能 → 工作流,点击「新建工作流」打开可视化编辑器。"],["h2",{"id":"节点类型"},"📦 节点类型"],["table",{},["thead",{},["tr",{},["th",{},"节点类型"],["th",{},"说明"]]],["tbody",{},["tr",{},["td",{},["code",{},"http-request"]],["td",{},"HTTP 请求"]],["tr",{},["td",{},["code",{},"ai-agent"]],["td",{},"AI 智能体"]],["tr",{},["td",{},["code",{},"condition"]],["td",{},"条件分支"]],["tr",{},["td",{},["code",{},"loop"]],["td",{},"循环"]],["tr",{},["td",{},["code",{},"delay"]],["td",{},"等待/延迟"]],["tr",{},["td",{},["code",{},"webhook"]],["td",{},"Webhook 通知"]],["tr",{},["td",{},["code",{},"transform"]],["td",{},"数据转换"]],["tr",{},["td",{},["code",{},"email"]],["td",{},"发送邮件"]]]],["h2",{"id":"触发器类型"},"🔔 触发器类型"],["h3",{"id":"定时触发"},"定时触发"],["pre",{"className":"language-typescript shiki shiki-themes github-light github-dark","code":"workflow.addTrigger({\n type: ''schedule'',\n config: {\n cron: ''0 */4 * * *'', // 每 4 小时\n interval: ''daily'', // daily, weekly, monthly\n time: ''09:00''\n }\n})\n","language":"typescript","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sVt8B"},"workflow."],["span",{"class":"sScJk"},"addTrigger"],["span",{"class":"sVt8B"},"({\n"]],["span",{"class":"line","line":2},["span",{"class":"sVt8B"}," type: "],["span",{"class":"sZZnC"},"''schedule''"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":3},["span",{"class":"sVt8B"}," config: {\n"]],["span",{"class":"line","line":4},["span",{"class":"sVt8B"}," cron: "],["span",{"class":"sZZnC"},"''0 */4 * * *''"],["span",{"class":"sVt8B"},", "],["span",{"class":"sJ8bj"},"// 每 4 小时\n"]],["span",{"class":"line","line":5},["span",{"class":"sVt8B"}," interval: "],["span",{"class":"sZZnC"},"''daily''"],["span",{"class":"sVt8B"},", "],["span",{"class":"sJ8bj"},"// daily, weekly, monthly\n"]],["span",{"class":"line","line":6},["span",{"class":"sVt8B"}," time: "],["span",{"class":"sZZnC"},"''09:00''\n"]],["span",{"class":"line","line":7},["span",{"class":"sVt8B"}," }\n"]],["span",{"class":"line","line":8},["span",{"class":"sVt8B"},"})\n"]]]],["h3",{"id":"webhook-触发"},"Webhook 触发"],["pre",{"className":"language-typescript shiki shiki-themes github-light github-dark","code":"workflow.addTrigger({\n type: ''webhook'',\n config: {\n // 创建后获得 webhook URL\n }\n})\n","language":"typescript","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sVt8B"},"workflow."],["span",{"class":"sScJk"},"addTrigger"],["span",{"class":"sVt8B"},"({\n"]],["span",{"class":"line","line":2},["span",{"class":"sVt8B"}," type: "],["span",{"class":"sZZnC"},"''webhook''"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":3},["span",{"class":"sVt8B"}," config: {\n"]],["span",{"class":"line","line":4},["span",{"class":"sJ8bj"}," // 创建后获得 webhook URL\n"]],["span",{"class":"line","line":5},["span",{"class":"sVt8B"}," }\n"]],["span",{"class":"line","line":6},["span",{"class":"sVt8B"},"})\n"]]]],["h3",{"id":"事件触发"},"事件触发"],["pre",{"className":"language-typescript shiki shiki-themes github-light github-dark","code":"workflow.addTrigger({\n type: ''event'',\n config: {\n events: [\n ''user.created'',\n ''order.completed'',\n ''ai.task.failed''\n ]\n }\n})\n","language":"typescript","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sVt8B"},"workflow."],["span",{"class":"sScJk"},"addTrigger"],["span",{"class":"sVt8B"},"({\n"]],["span",{"class":"line","line":2},["span",{"class":"sVt8B"}," type: "],["span",{"class":"sZZnC"},"''event''"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":3},["span",{"class":"sVt8B"}," config: {\n"]],["span",{"class":"line","line":4},["span",{"class":"sVt8B"}," events: [\n"]],["span",{"class":"line","line":5},["span",{"class":"sZZnC"}," ''user.created''"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":6},["span",{"class":"sZZnC"}," ''order.completed''"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":7},["span",{"class":"sZZnC"}," ''ai.task.failed''\n"]],["span",{"class":"line","line":8},["span",{"class":"sVt8B"}," ]\n"]],["span",{"class":"line","line":9},["span",{"class":"sVt8B"}," }\n"]],["span",{"class":"line","line":10},["span",{"class":"sVt8B"},"})\n"]]]],["h2",{"id":"执行与监控"},"📊 执行与监控"],["h3",{"id":"手动执行"},"手动执行"],["pre",{"className":"language-typescript shiki shiki-themes github-light github-dark","code":"const run = await client.workflow.run(workflowId, {\n input: { date: ''2024-01-15'' }\n})\n\nconsole.log(''执行 ID:'', run.id)\n","language":"typescript","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"szBVR"},"const"],["span",{"class":"sj4cs"}," run"],["span",{"class":"szBVR"}," ="],["span",{"class":"szBVR"}," await"],["span",{"class":"sVt8B"}," client.workflow."],["span",{"class":"sScJk"},"run"],["span",{"class":"sVt8B"},"(workflowId, {\n"]],["span",{"class":"line","line":2},["span",{"class":"sVt8B"}," input: { date: "],["span",{"class":"sZZnC"},"''2024-01-15''"],["span",{"class":"sVt8B"}," }\n"]],["span",{"class":"line","line":3},["span",{"class":"sVt8B"},"})\n"]],["span",{"class":"line","line":4},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":5},["span",{"class":"sVt8B"},"console."],["span",{"class":"sScJk"},"log"],["span",{"class":"sVt8B"},"("],["span",{"class":"sZZnC"},"''执行 ID:''"],["span",{"class":"sVt8B"},", run.id)\n"]]]],["h3",{"id":"查看执行日志"},"查看执行日志"],["pre",{"className":"language-typescript shiki shiki-themes github-light github-dark","code":"const logs = await client.workflow.getRunLogs(run.id)\n\nfor (const log of logs) {\n console.log(`[${log.timestamp}] ${log.node}: ${log.status}`)\n if (log.error) {\n console.log('' 错误:'', log.error)\n }\n}\n","language":"typescript","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"szBVR"},"const"],["span",{"class":"sj4cs"}," logs"],["span",{"class":"szBVR"}," ="],["span",{"class":"szBVR"}," await"],["span",{"class":"sVt8B"}," client.workflow."],["span",{"class":"sScJk"},"getRunLogs"],["span",{"class":"sVt8B"},"(run.id)\n"]],["span",{"class":"line","line":2},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":3},["span",{"class":"szBVR"},"for"],["span",{"class":"sVt8B"}," ("],["span",{"class":"szBVR"},"const"],["span",{"class":"sj4cs"}," log"],["span",{"class":"szBVR"}," of"],["span",{"class":"sVt8B"}," logs) {\n"]],["span",{"class":"line","line":4},["span",{"class":"sVt8B"}," console."],["span",{"class":"sScJk"},"log"],["span",{"class":"sVt8B"},"("],["span",{"class":"sZZnC"},"`[${"],["span",{"class":"sVt8B"},"log"],["span",{"class":"sZZnC"},"."],["span",{"class":"sVt8B"},"timestamp"],["span",{"class":"sZZnC"},"}] ${"],["span",{"class":"sVt8B"},"log"],["span",{"class":"sZZnC"},"."],["span",{"class":"sVt8B"},"node"],["span",{"class":"sZZnC"},"}: ${"],["span",{"class":"sVt8B"},"log"],["span",{"class":"sZZnC"},"."],["span",{"class":"sVt8B"},"status"],["span",{"class":"sZZnC"},"}`"],["span",{"class":"sVt8B"},")\n"]],["span",{"class":"line","line":5},["span",{"class":"szBVR"}," if"],["span",{"class":"sVt8B"}," (log.error) {\n"]],["span",{"class":"line","line":6},["span",{"class":"sVt8B"}," console."],["span",{"class":"sScJk"},"log"],["span",{"class":"sVt8B"},"("],["span",{"class":"sZZnC"},"'' 错误:''"],["span",{"class":"sVt8B"},", log.error)\n"]],["span",{"class":"line","line":7},["span",{"class":"sVt8B"}," }\n"]],["span",{"class":"line","line":8},["span",{"class":"sVt8B"},"}\n"]]]],["h2",{"id":"常见问题"},"❓ 常见问题"],["h3",{"id":"q-工作流执行失败怎么办"},"Q: 工作流执行失败怎么办?"],["ol",{},["li",{},"查看执行日志定位问题节点"],["li",{},"检查输入数据格式"],["li",{},"查看节点配置是否正确"],["li",{},"联系支持时提供执行 ID"]],["h3",{"id":"q-可以嵌套工作流吗"},"Q: 可以嵌套工作流吗?"],["p",{},"是的,可以在一个工作流中调用另一个工作流:"],["pre",{"className":"language-typescript shiki shiki-themes github-light github-dark","code":"workflow.addNode(''sub-workflow'', {\n type: ''workflow'',\n config: {\n workflowId: ''wf-xxx'',\n input: ''{{current-data}}''\n }\n})\n","language":"typescript","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sVt8B"},"workflow."],["span",{"class":"sScJk"},"addNode"],["span",{"class":"sVt8B"},"("],["span",{"class":"sZZnC"},"''sub-workflow''"],["span",{"class":"sVt8B"},", {\n"]],["span",{"class":"line","line":2},["span",{"class":"sVt8B"}," type: "],["span",{"class":"sZZnC"},"''workflow''"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":3},["span",{"class":"sVt8B"}," config: {\n"]],["span",{"class":"line","line":4},["span",{"class":"sVt8B"}," workflowId: "],["span",{"class":"sZZnC"},"''wf-xxx''"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":5},["span",{"class":"sVt8B"}," input: "],["span",{"class":"sZZnC"},"''{{current-data}}''\n"]],["span",{"class":"line","line":6},["span",{"class":"sVt8B"}," }\n"]],["span",{"class":"line","line":7},["span",{"class":"sVt8B"},"})\n"]]]],["style",{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}"]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"什么是工作流","depth":2,"text":"🔄 什么是工作流?"},{"id":"-核心概念","depth":2,"text":"🏗️ 核心概念"},{"id":"创建第一个工作流","depth":2,"text":"🚀 创建第一个工作流","children":[{"id":"代码定义","depth":3,"text":"代码定义"},{"id":"可视化编辑器","depth":3,"text":"可视化编辑器"}]},{"id":"节点类型","depth":2,"text":"📦 节点类型"},{"id":"触发器类型","depth":2,"text":"🔔 触发器类型","children":[{"id":"定时触发","depth":3,"text":"定时触发"},{"id":"webhook-触发","depth":3,"text":"Webhook 触发"},{"id":"事件触发","depth":3,"text":"事件触发"}]},{"id":"执行与监控","depth":2,"text":"📊 执行与监控","children":[{"id":"手动执行","depth":3,"text":"手动执行"},{"id":"查看执行日志","depth":3,"text":"查看执行日志"}]},{"id":"常见问题","depth":2,"text":"❓ 常见问题","children":[{"id":"q-工作流执行失败怎么办","depth":3,"text":"Q: 工作流执行失败怎么办?"},{"id":"q-可以嵌套工作流吗","depth":3,"text":"Q: 可以嵌套工作流吗?"}]}]}}', '使用工作流引擎,构建定时任务与自动化业务流。', 'md', '{"category":"ai","order":3}', 'true', '/docs/ai/workflow', '{"title":"AI 工作流配置","description":"使用工作流引擎,构建定时任务与自动化业务流。"}', 'docs/ai/workflow', 'EZRBCN9XfN1yY6NZaqT1Tp1EWDfLjaTKQOmEJtLXuwg'); -- EZRBCN9XfN1yY6NZaqT1Tp1EWDfLjaTKQOmEJtLXuwg
INSERT INTO _content_docs VALUES ('docs/docs/api/rest-api.md', 'REST API 完整参考', '{"type":"minimark","value":[["h1",{"id":"rest-api-完整参考"},"REST API 完整参考"],["blockquote",{},["p",{},"200+ 标准接口文档覆盖用户、内容、AI、支付等全部模块。"]],["h2",{"id":"api-概览"},"📚 API 概览"],["p",{},["strong",{},"基础 URL"]," ",["code",{},"https://api.websopy.com/v1"]],["p",{},["strong",{},"认证方式:"]," Bearer Token"],["pre",{"className":"language-bash shiki shiki-themes github-light github-dark","code":"curl -H \"Authorization: Bearer YOUR_API_KEY\" \\\n https://api.websopy.com/v1/user/profile\n","language":"bash","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sScJk"},"curl"],["span",{"class":"sj4cs"}," -H"],["span",{"class":"sZZnC"}," \"Authorization: Bearer YOUR_API_KEY\""],["span",{"class":"sj4cs"}," \\\n"]],["span",{"class":"line","line":2},["span",{"class":"sZZnC"}," https://api.websopy.com/v1/user/profile\n"]]]],["h2",{"id":"端点列表"},"📋 端点列表"],["h3",{"id":"用户管理-user"},"用户管理 ",["code",{},"/user"]],["table",{},["thead",{},["tr",{},["th",{},"方法"],["th",{},"端点"],["th",{},"说明"]]],["tbody",{},["tr",{},["td",{},"GET"],["td",{},["code",{},"/user/profile"]],["td",{},"获取当前用户信息"]],["tr",{},["td",{},"PUT"],["td",{},["code",{},"/user/profile"]],["td",{},"更新用户信息"]],["tr",{},["td",{},"GET"],["td",{},["code",{},"/user/settings"]],["td",{},"获取用户设置"]],["tr",{},["td",{},"PUT"],["td",{},["code",{},"/user/settings"]],["td",{},"更新用户设置"]],["tr",{},["td",{},"POST"],["td",{},["code",{},"/user/avatar"]],["td",{},"上传头像"]]]],["h3",{"id":"项目管理-projects"},"项目管理 ",["code",{},"/projects"]],["table",{},["thead",{},["tr",{},["th",{},"方法"],["th",{},"端点"],["th",{},"说明"]]],["tbody",{},["tr",{},["td",{},"GET"],["td",{},["code",{},"/projects"]],["td",{},"列出项目"]],["tr",{},["td",{},"POST"],["td",{},["code",{},"/projects"]],["td",{},"创建项目"]],["tr",{},["td",{},"GET"],["td",{},["code",{},"/projects/:id"]],["td",{},"获取项目详情"]],["tr",{},["td",{},"PUT"],["td",{},["code",{},"/projects/:id"]],["td",{},"更新项目"]],["tr",{},["td",{},"DELETE"],["td",{},["code",{},"/projects/:id"]],["td",{},"删除项目"]],["tr",{},["td",{},"GET"],["td",{},["code",{},"/projects/:id/members"]],["td",{},"获取项目成员"]],["tr",{},["td",{},"POST"],["td",{},["code",{},"/projects/:id/members"]],["td",{},"添加成员"]]]],["h3",{"id":"文件存储-storage"},"文件存储 ",["code",{},"/storage"]],["table",{},["thead",{},["tr",{},["th",{},"方法"],["th",{},"端点"],["th",{},"说明"]]],["tbody",{},["tr",{},["td",{},"GET"],["td",{},["code",{},"/storage/files"]],["td",{},"列出文件"]],["tr",{},["td",{},"POST"],["td",{},["code",{},"/storage/upload"]],["td",{},"上传文件"]],["tr",{},["td",{},"GET"],["td",{},["code",{},"/storage/files/:id"]],["td",{},"获取文件信息"]],["tr",{},["td",{},"DELETE"],["td",{},["code",{},"/storage/files/:id"]],["td",{},"删除文件"]],["tr",{},["td",{},"GET"],["td",{},["code",{},"/storage/files/:id/download"]],["td",{},"下载文件"]]]],["h3",{"id":"ai-功能-ai"},"AI 功能 ",["code",{},"/ai"]],["table",{},["thead",{},["tr",{},["th",{},"方法"],["th",{},"端点"],["th",{},"说明"]]],["tbody",{},["tr",{},["td",{},"POST"],["td",{},["code",{},"/ai/chat"]],["td",{},"发送对话请求"]],["tr",{},["td",{},"POST"],["td",{},["code",{},"/ai/chat/stream"]],["td",{},"流式对话"]],["tr",{},["td",{},"GET"],["td",{},["code",{},"/ai/sessions"]],["td",{},"列出会话"]],["tr",{},["td",{},"POST"],["td",{},["code",{},"/ai/sessions"]],["td",{},"创建会话"]],["tr",{},["td",{},"GET"],["td",{},["code",{},"/ai/sessions/:id"]],["td",{},"获取会话详情"]],["tr",{},["td",{},"DELETE"],["td",{},["code",{},"/ai/sessions/:id"]],["td",{},"删除会话"]],["tr",{},["td",{},"POST"],["td",{},["code",{},"/ai/knowledge"]],["td",{},"创建知识库"]],["tr",{},["td",{},"POST"],["td",{},["code",{},"/ai/knowledge/:id/documents"]],["td",{},"添加文档"]]]],["h3",{"id":"支付-payments"},"支付 ",["code",{},"/payments"]],["table",{},["thead",{},["tr",{},["th",{},"方法"],["th",{},"端点"],["th",{},"说明"]]],["tbody",{},["tr",{},["td",{},"GET"],["td",{},["code",{},"/payments/orders"]],["td",{},"列出订单"]],["tr",{},["td",{},"POST"],["td",{},["code",{},"/payments/orders"]],["td",{},"创建订单"]],["tr",{},["td",{},"GET"],["td",{},["code",{},"/payments/orders/:id"]],["td",{},"订单详情"]],["tr",{},["td",{},"POST"],["td",{},["code",{},"/payments/checkout"]],["td",{},"创建结算会话"]],["tr",{},["td",{},"GET"],["td",{},["code",{},"/payments/subscriptions"]],["td",{},"订阅列表"]]]],["h2",{"id":"请求与响应"},"🔍 请求与响应"],["h3",{"id":"请求头"},"请求头"],["pre",{"className":"language-http shiki shiki-themes github-light github-dark","code":"Authorization: Bearer YOUR_API_KEY\nContent-Type: application/json\nAccept: application/json\nX-Request-ID: unique-request-id\n","language":"http","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{},"Authorization: Bearer YOUR_API_KEY\n"]],["span",{"class":"line","line":2},["span",{},"Content-Type: application/json\n"]],["span",{"class":"line","line":3},["span",{},"Accept: application/json\n"]],["span",{"class":"line","line":4},["span",{},"X-Request-ID: unique-request-id\n"]]]],["h3",{"id":"分页"},"分页"],["pre",{"className":"language-http shiki shiki-themes github-light github-dark","code":"GET /projects?page=2&limit=20\n","language":"http","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{},"GET /projects?page=2&limit=20\n"]]]],["p",{},"响应包含分页信息:"],["pre",{"className":"language-json shiki shiki-themes github-light github-dark","code":"{\n \"data\": [...],\n \"pagination\": {\n \"page\": 2,\n \"limit\": 20,\n \"total\": 100,\n \"total_pages\": 5\n }\n}\n","language":"json","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sVt8B"},"{\n"]],["span",{"class":"line","line":2},["span",{"class":"sj4cs"}," \"data\""],["span",{"class":"sVt8B"},": ["],["span",{"class":"s7hpK"},"..."],["span",{"class":"sVt8B"},"],\n"]],["span",{"class":"line","line":3},["span",{"class":"sj4cs"}," \"pagination\""],["span",{"class":"sVt8B"},": {\n"]],["span",{"class":"line","line":4},["span",{"class":"sj4cs"}," \"page\""],["span",{"class":"sVt8B"},": "],["span",{"class":"sj4cs"},"2"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":5},["span",{"class":"sj4cs"}," \"limit\""],["span",{"class":"sVt8B"},": "],["span",{"class":"sj4cs"},"20"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":6},["span",{"class":"sj4cs"}," \"total\""],["span",{"class":"sVt8B"},": "],["span",{"class":"sj4cs"},"100"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":7},["span",{"class":"sj4cs"}," \"total_pages\""],["span",{"class":"sVt8B"},": "],["span",{"class":"sj4cs"},"5\n"]],["span",{"class":"line","line":8},["span",{"class":"sVt8B"}," }\n"]],["span",{"class":"line","line":9},["span",{"class":"sVt8B"},"}\n"]]]],["h3",{"id":"排序"},"排序"],["pre",{"className":"language-http shiki shiki-themes github-light github-dark","code":"GET /projects?sort=created_at&order=desc\n","language":"http","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{},"GET /projects?sort=created_at&order=desc\n"]]]],["h3",{"id":"过滤"},"过滤"],["pre",{"className":"language-http shiki shiki-themes github-light github-dark","code":"GET /projects?status=active&category=ai\n","language":"http","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{},"GET /projects?status=active&category=ai\n"]]]],["h2",{"id":"错误处理"},"📝 错误处理"],["h3",{"id":"错误码"},"错误码"],["table",{},["thead",{},["tr",{},["th",{},"状态码"],["th",{},"错误码"],["th",{},"说明"]]],["tbody",{},["tr",{},["td",{},"400"],["td",{},["code",{},"INVALID_REQUEST"]],["td",{},"请求参数错误"]],["tr",{},["td",{},"401"],["td",{},["code",{},"UNAUTHORIZED"]],["td",{},"未认证或 Token 无效"]],["tr",{},["td",{},"403"],["td",{},["code",{},"FORBIDDEN"]],["td",{},"无权限访问"]],["tr",{},["td",{},"404"],["td",{},["code",{},"NOT_FOUND"]],["td",{},"资源不存在"]],["tr",{},["td",{},"429"],["td",{},["code",{},"RATE_LIMITED"]],["td",{},"请求过于频繁"]],["tr",{},["td",{},"500"],["td",{},["code",{},"SERVER_ERROR"]],["td",{},"服务器内部错误"]]]],["h3",{"id":"错误响应格式"},"错误响应格式"],["pre",{"className":"language-json shiki shiki-themes github-light github-dark","code":"{\n \"error\": {\n \"code\": \"INVALID_REQUEST\",\n \"message\": \"参数 ''name'' 不能为空\",\n \"details\": {\n \"field\": \"name\",\n \"constraint\": \"required\"\n }\n }\n}\n","language":"json","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sVt8B"},"{\n"]],["span",{"class":"line","line":2},["span",{"class":"sj4cs"}," \"error\""],["span",{"class":"sVt8B"},": {\n"]],["span",{"class":"line","line":3},["span",{"class":"sj4cs"}," \"code\""],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"\"INVALID_REQUEST\""],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":4},["span",{"class":"sj4cs"}," \"message\""],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"\"参数 ''name'' 不能为空\""],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":5},["span",{"class":"sj4cs"}," \"details\""],["span",{"class":"sVt8B"},": {\n"]],["span",{"class":"line","line":6},["span",{"class":"sj4cs"}," \"field\""],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"\"name\""],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":7},["span",{"class":"sj4cs"}," \"constraint\""],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"\"required\"\n"]],["span",{"class":"line","line":8},["span",{"class":"sVt8B"}," }\n"]],["span",{"class":"line","line":9},["span",{"class":"sVt8B"}," }\n"]],["span",{"class":"line","line":10},["span",{"class":"sVt8B"},"}\n"]]]],["h2",{"id":"使用示例"},"🔧 使用示例"],["h3",{"id":"javascripttypescript"},"JavaScript/TypeScript"],["pre",{"className":"language-typescript shiki shiki-themes github-light github-dark","code":"const response = await fetch(''https://api.websopy.com/v1/projects'', {\n method: ''POST'',\n headers: {\n ''Authorization'': `Bearer ${apiKey}`,\n ''Content-Type'': ''application/json''\n },\n body: JSON.stringify({\n name: ''我的项目'',\n description: ''项目描述''\n })\n})\n\nconst data = await response.json()\nconsole.log(data)\n","language":"typescript","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"szBVR"},"const"],["span",{"class":"sj4cs"}," response"],["span",{"class":"szBVR"}," ="],["span",{"class":"szBVR"}," await"],["span",{"class":"sScJk"}," fetch"],["span",{"class":"sVt8B"},"("],["span",{"class":"sZZnC"},"''https://api.websopy.com/v1/projects''"],["span",{"class":"sVt8B"},", {\n"]],["span",{"class":"line","line":2},["span",{"class":"sVt8B"}," method: "],["span",{"class":"sZZnC"},"''POST''"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":3},["span",{"class":"sVt8B"}," headers: {\n"]],["span",{"class":"line","line":4},["span",{"class":"sZZnC"}," ''Authorization''"],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"`Bearer ${"],["span",{"class":"sVt8B"},"apiKey"],["span",{"class":"sZZnC"},"}`"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":5},["span",{"class":"sZZnC"}," ''Content-Type''"],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"''application/json''\n"]],["span",{"class":"line","line":6},["span",{"class":"sVt8B"}," },\n"]],["span",{"class":"line","line":7},["span",{"class":"sVt8B"}," body: "],["span",{"class":"sj4cs"},"JSON"],["span",{"class":"sVt8B"},"."],["span",{"class":"sScJk"},"stringify"],["span",{"class":"sVt8B"},"({\n"]],["span",{"class":"line","line":8},["span",{"class":"sVt8B"}," name: "],["span",{"class":"sZZnC"},"''我的项目''"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":9},["span",{"class":"sVt8B"}," description: "],["span",{"class":"sZZnC"},"''项目描述''\n"]],["span",{"class":"line","line":10},["span",{"class":"sVt8B"}," })\n"]],["span",{"class":"line","line":11},["span",{"class":"sVt8B"},"})\n"]],["span",{"class":"line","line":12},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":13},["span",{"class":"szBVR"},"const"],["span",{"class":"sj4cs"}," data"],["span",{"class":"szBVR"}," ="],["span",{"class":"szBVR"}," await"],["span",{"class":"sVt8B"}," response."],["span",{"class":"sScJk"},"json"],["span",{"class":"sVt8B"},"()\n"]],["span",{"class":"line","line":14},["span",{"class":"sVt8B"},"console."],["span",{"class":"sScJk"},"log"],["span",{"class":"sVt8B"},"(data)\n"]]]],["h3",{"id":"python"},"Python"],["pre",{"className":"language-python shiki shiki-themes github-light github-dark","code":"import requests\n\nresponse = requests.post(\n ''https://api.websopy.com/v1/projects'',\n headers={\n ''Authorization'': f''Bearer {api_key}'',\n ''Content-Type'': ''application/json''\n },\n json={\n ''name'': ''我的项目'',\n ''description'': ''项目描述''\n }\n)\n\ndata = response.json()\nprint(data)\n","language":"python","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{},"import requests\n"]],["span",{"class":"line","line":2},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":3},["span",{},"response = requests.post(\n"]],["span",{"class":"line","line":4},["span",{}," ''https://api.websopy.com/v1/projects'',\n"]],["span",{"class":"line","line":5},["span",{}," headers={\n"]],["span",{"class":"line","line":6},["span",{}," ''Authorization'': f''Bearer {api_key}'',\n"]],["span",{"class":"line","line":7},["span",{}," ''Content-Type'': ''application/json''\n"]],["span",{"class":"line","line":8},["span",{}," },\n"]],["span",{"class":"line","line":9},["span",{}," json={\n"]],["span",{"class":"line","line":10},["span",{}," ''name'': ''我的项目'',\n"]],["span",{"class":"line","line":11},["span",{}," ''description'': ''项目描述''\n"]],["span",{"class":"line","line":12},["span",{}," }\n"]],["span",{"class":"line","line":13},["span",{},")\n"]],["span",{"class":"line","line":14},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":15},["span",{},"data = response.json()\n"]],["span",{"class":"line","line":16},["span",{},"print(data)\n"]]]],["style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s7hpK, html code.shiki .s7hpK{--shiki-default:#B31D28;--shiki-default-font-style:italic;--shiki-dark:#FDAEB7;--shiki-dark-font-style:italic}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}"]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"api-概览","depth":2,"text":"📚 API 概览"},{"id":"端点列表","depth":2,"text":"📋 端点列表","children":[{"id":"用户管理-user","depth":3,"text":"用户管理 /user"},{"id":"项目管理-projects","depth":3,"text":"项目管理 /projects"},{"id":"文件存储-storage","depth":3,"text":"文件存储 /storage"},{"id":"ai-功能-ai","depth":3,"text":"AI 功能 /ai"},{"id":"支付-payments","depth":3,"text":"支付 /payments"}]},{"id":"请求与响应","depth":2,"text":"🔍 请求与响应","children":[{"id":"请求头","depth":3,"text":"请求头"},{"id":"分页","depth":3,"text":"分页"},{"id":"排序","depth":3,"text":"排序"},{"id":"过滤","depth":3,"text":"过滤"}]},{"id":"错误处理","depth":2,"text":"📝 错误处理","children":[{"id":"错误码","depth":3,"text":"错误码"},{"id":"错误响应格式","depth":3,"text":"错误响应格式"}]},{"id":"使用示例","depth":2,"text":"🔧 使用示例","children":[{"id":"javascripttypescript","depth":3,"text":"JavaScript/TypeScript"},{"id":"python","depth":3,"text":"Python"}]}]}}', '200+ 标准接口文档覆盖用户、内容、AI、支付等全部模块。', 'md', '{"category":"api","order":1}', 'true', '/docs/api/rest-api', '{"title":"REST API 完整参考","description":"200+ 标准接口文档覆盖用户、内容、AI、支付等全部模块。"}', 'docs/api/rest-api', 'UrSAbHsueij0gNTWlXd4iyiJTMb9Byd5YRQx6ZWNkQg'); -- UrSAbHsueij0gNTWlXd4iyiJTMb9Byd5YRQx6ZWNkQg
INSERT INTO _content_docs VALUES ('docs/docs/api/streaming.md', '流式输出SSE接入', '{"type":"minimark","value":[["h1",{"id":"流式输出sse接入"},"流式输出SSE接入"],["blockquote",{},["p",{},"使用 Server-Sent Events 实现 AI 流式响应,提升用户体验。"]],["h2",{"id":"什么是流式输出"},"🌊 什么是流式输出?"],["p",{},"流式输出Streaming是一种数据传输方式服务器将数据「分块」发送给客户端而不是等待全部完成后再返回。"],["h3",{"id":"对比"},"对比"],["table",{},["thead",{},["tr",{},["th",{},"方式"],["th",{},"等待时间"],["th",{},"体验"],["th",{},"适用场景"]]],["tbody",{},["tr",{},["td",{},"普通请求"],["td",{},"等待完整响应"],["td",{},"一般"],["td",{},"简单、快速的请求"]],["tr",{},["td",{},"流式输出"],["td",{},"实时看到生成过程"],["td",{},"⭐ 优秀"],["td",{},"AI 生成、长文本"]]]],["h2",{"id":"开始使用"},"🚀 开始使用"],["h3",{"id":"前端接收流式响应"},"前端:接收流式响应"],["pre",{"className":"language-typescript shiki shiki-themes github-light github-dark","code":"import { WebsopyClient } from ''@websopy/sdk''\n\nconst client = new WebsopyClient({\n apiKey: process.env.WEBSOPY_API_KEY\n})\n\nasync function streamChat() {\n const stream = await client.ai.chatStream({\n messages: [\n { role: ''user'', content: ''写一篇关于 AI 的文章'' }\n ]\n })\n\n // 方法 1遍历数据块\n for await (const chunk of stream) {\n if (chunk.type === ''content'') {\n process.stdout.write(chunk.content)\n }\n }\n}\n","language":"typescript","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"szBVR"},"import"],["span",{"class":"sVt8B"}," { WebsopyClient } "],["span",{"class":"szBVR"},"from"],["span",{"class":"sZZnC"}," ''@websopy/sdk''\n"]],["span",{"class":"line","line":2},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":3},["span",{"class":"szBVR"},"const"],["span",{"class":"sj4cs"}," client"],["span",{"class":"szBVR"}," ="],["span",{"class":"szBVR"}," new"],["span",{"class":"sScJk"}," WebsopyClient"],["span",{"class":"sVt8B"},"({\n"]],["span",{"class":"line","line":4},["span",{"class":"sVt8B"}," apiKey: process.env."],["span",{"class":"sj4cs"},"WEBSOPY_API_KEY\n"]],["span",{"class":"line","line":5},["span",{"class":"sVt8B"},"})\n"]],["span",{"class":"line","line":6},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":7},["span",{"class":"szBVR"},"async"],["span",{"class":"szBVR"}," function"],["span",{"class":"sScJk"}," streamChat"],["span",{"class":"sVt8B"},"() {\n"]],["span",{"class":"line","line":8},["span",{"class":"szBVR"}," const"],["span",{"class":"sj4cs"}," stream"],["span",{"class":"szBVR"}," ="],["span",{"class":"szBVR"}," await"],["span",{"class":"sVt8B"}," client.ai."],["span",{"class":"sScJk"},"chatStream"],["span",{"class":"sVt8B"},"({\n"]],["span",{"class":"line","line":9},["span",{"class":"sVt8B"}," messages: [\n"]],["span",{"class":"line","line":10},["span",{"class":"sVt8B"}," { role: "],["span",{"class":"sZZnC"},"''user''"],["span",{"class":"sVt8B"},", content: "],["span",{"class":"sZZnC"},"''写一篇关于 AI 的文章''"],["span",{"class":"sVt8B"}," }\n"]],["span",{"class":"line","line":11},["span",{"class":"sVt8B"}," ]\n"]],["span",{"class":"line","line":12},["span",{"class":"sVt8B"}," })\n"]],["span",{"class":"line","line":13},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":14},["span",{"class":"sJ8bj"}," // 方法 1遍历数据块\n"]],["span",{"class":"line","line":15},["span",{"class":"szBVR"}," for"],["span",{"class":"szBVR"}," await"],["span",{"class":"sVt8B"}," ("],["span",{"class":"szBVR"},"const"],["span",{"class":"sj4cs"}," chunk"],["span",{"class":"szBVR"}," of"],["span",{"class":"sVt8B"}," stream) {\n"]],["span",{"class":"line","line":16},["span",{"class":"szBVR"}," if"],["span",{"class":"sVt8B"}," (chunk.type "],["span",{"class":"szBVR"},"==="],["span",{"class":"sZZnC"}," ''content''"],["span",{"class":"sVt8B"},") {\n"]],["span",{"class":"line","line":17},["span",{"class":"sVt8B"}," process.stdout."],["span",{"class":"sScJk"},"write"],["span",{"class":"sVt8B"},"(chunk.content)\n"]],["span",{"class":"line","line":18},["span",{"class":"sVt8B"}," }\n"]],["span",{"class":"line","line":19},["span",{"class":"sVt8B"}," }\n"]],["span",{"class":"line","line":20},["span",{"class":"sVt8B"},"}\n"]]]],["h3",{"id":"响应数据结构"},"响应数据结构"],["pre",{"className":"language-typescript shiki shiki-themes github-light github-dark","code":"interface StreamChunk {\n type: ''content'' | ''tool_call'' | ''done'' | ''error''\n content?: string\n tool?: {\n name: string\n arguments: string\n }\n usage?: {\n promptTokens: number\n completionTokens: number\n }\n}\n\n// 示例数据块\n{ type: ''content'', content: ''AI'' }\n{ type: ''content'', content: '' 正在'' }\n{ type: ''content'', content: ''改变'' }\n{ type: ''content'', content: ''世界...'' }\n{ type: ''done'', usage: { promptTokens: 20, completionTokens: 150 } }\n","language":"typescript","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"szBVR"},"interface"],["span",{"class":"sScJk"}," StreamChunk"],["span",{"class":"sVt8B"}," {\n"]],["span",{"class":"line","line":2},["span",{"class":"s4XuR"}," type"],["span",{"class":"szBVR"},":"],["span",{"class":"sZZnC"}," ''content''"],["span",{"class":"szBVR"}," |"],["span",{"class":"sZZnC"}," ''tool_call''"],["span",{"class":"szBVR"}," |"],["span",{"class":"sZZnC"}," ''done''"],["span",{"class":"szBVR"}," |"],["span",{"class":"sZZnC"}," ''error''\n"]],["span",{"class":"line","line":3},["span",{"class":"s4XuR"}," content"],["span",{"class":"szBVR"},"?:"],["span",{"class":"sj4cs"}," string\n"]],["span",{"class":"line","line":4},["span",{"class":"s4XuR"}," tool"],["span",{"class":"szBVR"},"?:"],["span",{"class":"sVt8B"}," {\n"]],["span",{"class":"line","line":5},["span",{"class":"s4XuR"}," name"],["span",{"class":"szBVR"},":"],["span",{"class":"sj4cs"}," string\n"]],["span",{"class":"line","line":6},["span",{"class":"s4XuR"}," arguments"],["span",{"class":"szBVR"},":"],["span",{"class":"sj4cs"}," string\n"]],["span",{"class":"line","line":7},["span",{"class":"sVt8B"}," }\n"]],["span",{"class":"line","line":8},["span",{"class":"s4XuR"}," usage"],["span",{"class":"szBVR"},"?:"],["span",{"class":"sVt8B"}," {\n"]],["span",{"class":"line","line":9},["span",{"class":"s4XuR"}," promptTokens"],["span",{"class":"szBVR"},":"],["span",{"class":"sj4cs"}," number\n"]],["span",{"class":"line","line":10},["span",{"class":"s4XuR"}," completionTokens"],["span",{"class":"szBVR"},":"],["span",{"class":"sj4cs"}," number\n"]],["span",{"class":"line","line":11},["span",{"class":"sVt8B"}," }\n"]],["span",{"class":"line","line":12},["span",{"class":"sVt8B"},"}\n"]],["span",{"class":"line","line":13},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":14},["span",{"class":"sJ8bj"},"// 示例数据块\n"]],["span",{"class":"line","line":15},["span",{"class":"sVt8B"},"{ "],["span",{"class":"sScJk"},"type"],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"''content''"],["span",{"class":"sVt8B"},", "],["span",{"class":"sScJk"},"content"],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"''AI''"],["span",{"class":"sVt8B"}," }\n"]],["span",{"class":"line","line":16},["span",{"class":"sVt8B"},"{ "],["span",{"class":"sScJk"},"type"],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"''content''"],["span",{"class":"sVt8B"},", "],["span",{"class":"sScJk"},"content"],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"'' 正在''"],["span",{"class":"sVt8B"}," }\n"]],["span",{"class":"line","line":17},["span",{"class":"sVt8B"},"{ "],["span",{"class":"sScJk"},"type"],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"''content''"],["span",{"class":"sVt8B"},", "],["span",{"class":"sScJk"},"content"],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"''改变''"],["span",{"class":"sVt8B"}," }\n"]],["span",{"class":"line","line":18},["span",{"class":"sVt8B"},"{ "],["span",{"class":"sScJk"},"type"],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"''content''"],["span",{"class":"sVt8B"},", "],["span",{"class":"sScJk"},"content"],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"''世界...''"],["span",{"class":"sVt8B"}," }\n"]],["span",{"class":"line","line":19},["span",{"class":"sVt8B"},"{ "],["span",{"class":"sScJk"},"type"],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"''done''"],["span",{"class":"sVt8B"},", "],["span",{"class":"sScJk"},"usage"],["span",{"class":"sVt8B"},": { "],["span",{"class":"sScJk"},"promptTokens"],["span",{"class":"sVt8B"},": "],["span",{"class":"sj4cs"},"20"],["span",{"class":"sVt8B"},", "],["span",{"class":"sScJk"},"completionTokens"],["span",{"class":"sVt8B"},": "],["span",{"class":"sj4cs"},"150"],["span",{"class":"sVt8B"}," } }\n"]]]],["h2",{"id":"原生-sse-实现"},"🌐 原生 SSE 实现"],["p",{},"如果不用 SDK直接使用 Fetch API"],["pre",{"className":"language-typescript shiki shiki-themes github-light github-dark","code":"async function nativeStream() {\n const response = await fetch(\n ''https://api.websopy.com/v1/ai/chat?message=Hello'',\n {\n headers: {\n ''Authorization'': `Bearer ${apiKey}`,\n ''Accept'': ''text/event-stream''\n }\n }\n )\n\n const reader = response.body.getReader()\n const decoder = new TextDecoder()\n\n while (true) {\n const { done, value } = await reader.read()\n if (done) break\n \n const chunk = decoder.decode(value)\n const lines = chunk.split(''\\n'')\n for (const line of lines) {\n if (line.startsWith(''data: '')) {\n const data = JSON.parse(line.slice(6))\n console.log(''收到:'', data)\n }\n }\n }\n}\n","language":"typescript","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"szBVR"},"async"],["span",{"class":"szBVR"}," function"],["span",{"class":"sScJk"}," nativeStream"],["span",{"class":"sVt8B"},"() {\n"]],["span",{"class":"line","line":2},["span",{"class":"szBVR"}," const"],["span",{"class":"sj4cs"}," response"],["span",{"class":"szBVR"}," ="],["span",{"class":"szBVR"}," await"],["span",{"class":"sScJk"}," fetch"],["span",{"class":"sVt8B"},"(\n"]],["span",{"class":"line","line":3},["span",{"class":"sZZnC"}," ''https://api.websopy.com/v1/ai/chat?message=Hello''"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":4},["span",{"class":"sVt8B"}," {\n"]],["span",{"class":"line","line":5},["span",{"class":"sVt8B"}," headers: {\n"]],["span",{"class":"line","line":6},["span",{"class":"sZZnC"}," ''Authorization''"],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"`Bearer ${"],["span",{"class":"sVt8B"},"apiKey"],["span",{"class":"sZZnC"},"}`"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":7},["span",{"class":"sZZnC"}," ''Accept''"],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"''text/event-stream''\n"]],["span",{"class":"line","line":8},["span",{"class":"sVt8B"}," }\n"]],["span",{"class":"line","line":9},["span",{"class":"sVt8B"}," }\n"]],["span",{"class":"line","line":10},["span",{"class":"sVt8B"}," )\n"]],["span",{"class":"line","line":11},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":12},["span",{"class":"szBVR"}," const"],["span",{"class":"sj4cs"}," reader"],["span",{"class":"szBVR"}," ="],["span",{"class":"sVt8B"}," response.body."],["span",{"class":"sScJk"},"getReader"],["span",{"class":"sVt8B"},"()\n"]],["span",{"class":"line","line":13},["span",{"class":"szBVR"}," const"],["span",{"class":"sj4cs"}," decoder"],["span",{"class":"szBVR"}," ="],["span",{"class":"szBVR"}," new"],["span",{"class":"sScJk"}," TextDecoder"],["span",{"class":"sVt8B"},"()\n"]],["span",{"class":"line","line":14},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":15},["span",{"class":"szBVR"}," while"],["span",{"class":"sVt8B"}," ("],["span",{"class":"sj4cs"},"true"],["span",{"class":"sVt8B"},") {\n"]],["span",{"class":"line","line":16},["span",{"class":"szBVR"}," const"],["span",{"class":"sVt8B"}," { "],["span",{"class":"sj4cs"},"done"],["span",{"class":"sVt8B"},", "],["span",{"class":"sj4cs"},"value"],["span",{"class":"sVt8B"}," } "],["span",{"class":"szBVR"},"="],["span",{"class":"szBVR"}," await"],["span",{"class":"sVt8B"}," reader."],["span",{"class":"sScJk"},"read"],["span",{"class":"sVt8B"},"()\n"]],["span",{"class":"line","line":17},["span",{"class":"szBVR"}," if"],["span",{"class":"sVt8B"}," (done) "],["span",{"class":"szBVR"},"break\n"]],["span",{"class":"line","line":18},["span",{"class":"sVt8B"}," \n"]],["span",{"class":"line","line":19},["span",{"class":"szBVR"}," const"],["span",{"class":"sj4cs"}," chunk"],["span",{"class":"szBVR"}," ="],["span",{"class":"sVt8B"}," decoder."],["span",{"class":"sScJk"},"decode"],["span",{"class":"sVt8B"},"(value)\n"]],["span",{"class":"line","line":20},["span",{"class":"szBVR"}," const"],["span",{"class":"sj4cs"}," lines"],["span",{"class":"szBVR"}," ="],["span",{"class":"sVt8B"}," chunk."],["span",{"class":"sScJk"},"split"],["span",{"class":"sVt8B"},"("],["span",{"class":"sZZnC"},"''"],["span",{"class":"sj4cs"},"\\n"],["span",{"class":"sZZnC"},"''"],["span",{"class":"sVt8B"},")\n"]],["span",{"class":"line","line":21},["span",{"class":"szBVR"}," for"],["span",{"class":"sVt8B"}," ("],["span",{"class":"szBVR"},"const"],["span",{"class":"sj4cs"}," line"],["span",{"class":"szBVR"}," of"],["span",{"class":"sVt8B"}," lines) {\n"]],["span",{"class":"line","line":22},["span",{"class":"szBVR"}," if"],["span",{"class":"sVt8B"}," (line."],["span",{"class":"sScJk"},"startsWith"],["span",{"class":"sVt8B"},"("],["span",{"class":"sZZnC"},"''data: ''"],["span",{"class":"sVt8B"},")) {\n"]],["span",{"class":"line","line":23},["span",{"class":"szBVR"}," const"],["span",{"class":"sj4cs"}," data"],["span",{"class":"szBVR"}," ="],["span",{"class":"sj4cs"}," JSON"],["span",{"class":"sVt8B"},"."],["span",{"class":"sScJk"},"parse"],["span",{"class":"sVt8B"},"(line."],["span",{"class":"sScJk"},"slice"],["span",{"class":"sVt8B"},"("],["span",{"class":"sj4cs"},"6"],["span",{"class":"sVt8B"},"))\n"]],["span",{"class":"line","line":24},["span",{"class":"sVt8B"}," console."],["span",{"class":"sScJk"},"log"],["span",{"class":"sVt8B"},"("],["span",{"class":"sZZnC"},"''收到:''"],["span",{"class":"sVt8B"},", data)\n"]],["span",{"class":"line","line":25},["span",{"class":"sVt8B"}," }\n"]],["span",{"class":"line","line":26},["span",{"class":"sVt8B"}," }\n"]],["span",{"class":"line","line":27},["span",{"class":"sVt8B"}," }\n"]],["span",{"class":"line","line":28},["span",{"class":"sVt8B"},"}\n"]]]],["h2",{"id":"前端组件示例"},"🎨 前端组件示例"],["h3",{"id":"vue-composition-api"},"Vue Composition API"],["pre",{"className":"language-typescript shiki shiki-themes github-light github-dark","code":"import { ref } from ''vue''\n\nexport function useStreamingChat() {\n const messages = ref([])\n const streaming = ref(false)\n const currentContent = ref('''')\n\n const sendMessage = async (content) => {\n streaming.value = true\n currentContent.value = ''''\n \n messages.value.push({ role: ''user'', content })\n \n const stream = await client.ai.chatStream({\n messages: messages.value\n })\n\n for await (const chunk of stream) {\n if (chunk.type === ''content'') {\n currentContent.value += chunk.content\n }\n }\n \n messages.value.push({ role: ''assistant'', content: currentContent.value })\n streaming.value = false\n }\n\n return { messages, streaming, currentContent, sendMessage }\n}\n","language":"typescript","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"szBVR"},"import"],["span",{"class":"sVt8B"}," { ref } "],["span",{"class":"szBVR"},"from"],["span",{"class":"sZZnC"}," ''vue''\n"]],["span",{"class":"line","line":2},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":3},["span",{"class":"szBVR"},"export"],["span",{"class":"szBVR"}," function"],["span",{"class":"sScJk"}," useStreamingChat"],["span",{"class":"sVt8B"},"() {\n"]],["span",{"class":"line","line":4},["span",{"class":"szBVR"}," const"],["span",{"class":"sj4cs"}," messages"],["span",{"class":"szBVR"}," ="],["span",{"class":"sScJk"}," ref"],["span",{"class":"sVt8B"},"([])\n"]],["span",{"class":"line","line":5},["span",{"class":"szBVR"}," const"],["span",{"class":"sj4cs"}," streaming"],["span",{"class":"szBVR"}," ="],["span",{"class":"sScJk"}," ref"],["span",{"class":"sVt8B"},"("],["span",{"class":"sj4cs"},"false"],["span",{"class":"sVt8B"},")\n"]],["span",{"class":"line","line":6},["span",{"class":"szBVR"}," const"],["span",{"class":"sj4cs"}," currentContent"],["span",{"class":"szBVR"}," ="],["span",{"class":"sScJk"}," ref"],["span",{"class":"sVt8B"},"("],["span",{"class":"sZZnC"},"''''"],["span",{"class":"sVt8B"},")\n"]],["span",{"class":"line","line":7},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":8},["span",{"class":"szBVR"}," const"],["span",{"class":"sScJk"}," sendMessage"],["span",{"class":"szBVR"}," ="],["span",{"class":"szBVR"}," async"],["span",{"class":"sVt8B"}," ("],["span",{"class":"s4XuR"},"content"],["span",{"class":"sVt8B"},") "],["span",{"class":"szBVR"},"=>"],["span",{"class":"sVt8B"}," {\n"]],["span",{"class":"line","line":9},["span",{"class":"sVt8B"}," streaming.value "],["span",{"class":"szBVR"},"="],["span",{"class":"sj4cs"}," true\n"]],["span",{"class":"line","line":10},["span",{"class":"sVt8B"}," currentContent.value "],["span",{"class":"szBVR"},"="],["span",{"class":"sZZnC"}," ''''\n"]],["span",{"class":"line","line":11},["span",{"class":"sVt8B"}," \n"]],["span",{"class":"line","line":12},["span",{"class":"sVt8B"}," messages.value."],["span",{"class":"sScJk"},"push"],["span",{"class":"sVt8B"},"({ role: "],["span",{"class":"sZZnC"},"''user''"],["span",{"class":"sVt8B"},", content })\n"]],["span",{"class":"line","line":13},["span",{"class":"sVt8B"}," \n"]],["span",{"class":"line","line":14},["span",{"class":"szBVR"}," const"],["span",{"class":"sj4cs"}," stream"],["span",{"class":"szBVR"}," ="],["span",{"class":"szBVR"}," await"],["span",{"class":"sVt8B"}," client.ai."],["span",{"class":"sScJk"},"chatStream"],["span",{"class":"sVt8B"},"({\n"]],["span",{"class":"line","line":15},["span",{"class":"sVt8B"}," messages: messages.value\n"]],["span",{"class":"line","line":16},["span",{"class":"sVt8B"}," })\n"]],["span",{"class":"line","line":17},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":18},["span",{"class":"szBVR"}," for"],["span",{"class":"szBVR"}," await"],["span",{"class":"sVt8B"}," ("],["span",{"class":"szBVR"},"const"],["span",{"class":"sj4cs"}," chunk"],["span",{"class":"szBVR"}," of"],["span",{"class":"sVt8B"}," stream) {\n"]],["span",{"class":"line","line":19},["span",{"class":"szBVR"}," if"],["span",{"class":"sVt8B"}," (chunk.type "],["span",{"class":"szBVR"},"==="],["span",{"class":"sZZnC"}," ''content''"],["span",{"class":"sVt8B"},") {\n"]],["span",{"class":"line","line":20},["span",{"class":"sVt8B"}," currentContent.value "],["span",{"class":"szBVR"},"+="],["span",{"class":"sVt8B"}," chunk.content\n"]],["span",{"class":"line","line":21},["span",{"class":"sVt8B"}," }\n"]],["span",{"class":"line","line":22},["span",{"class":"sVt8B"}," }\n"]],["span",{"class":"line","line":23},["span",{"class":"sVt8B"}," \n"]],["span",{"class":"line","line":24},["span",{"class":"sVt8B"}," messages.value."],["span",{"class":"sScJk"},"push"],["span",{"class":"sVt8B"},"({ role: "],["span",{"class":"sZZnC"},"''assistant''"],["span",{"class":"sVt8B"},", content: currentContent.value })\n"]],["span",{"class":"line","line":25},["span",{"class":"sVt8B"}," streaming.value "],["span",{"class":"szBVR"},"="],["span",{"class":"sj4cs"}," false\n"]],["span",{"class":"line","line":26},["span",{"class":"sVt8B"}," }\n"]],["span",{"class":"line","line":27},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":28},["span",{"class":"szBVR"}," return"],["span",{"class":"sVt8B"}," { messages, streaming, currentContent, sendMessage }\n"]],["span",{"class":"line","line":29},["span",{"class":"sVt8B"},"}\n"]]]],["h2",{"id":"常见问题"},"❓ 常见问题"],["h3",{"id":"q-流式中断怎么办"},"Q: 流式中断怎么办?"],["pre",{"className":"language-typescript shiki shiki-themes github-light github-dark","code":"async function streamWithReconnect() {\n const maxRetries = 3\n let retries = 0\n \n while (retries < maxRetries) {\n try {\n const stream = await client.ai.chatStream({...})\n return stream\n } catch (error) {\n retries++\n await sleep(1000 * retries) // 指数退避\n }\n }\n}\n","language":"typescript","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"szBVR"},"async"],["span",{"class":"szBVR"}," function"],["span",{"class":"sScJk"}," streamWithReconnect"],["span",{"class":"sVt8B"},"() {\n"]],["span",{"class":"line","line":2},["span",{"class":"szBVR"}," const"],["span",{"class":"sj4cs"}," maxRetries"],["span",{"class":"szBVR"}," ="],["span",{"class":"sj4cs"}," 3\n"]],["span",{"class":"line","line":3},["span",{"class":"szBVR"}," let"],["span",{"class":"sVt8B"}," retries "],["span",{"class":"szBVR"},"="],["span",{"class":"sj4cs"}," 0\n"]],["span",{"class":"line","line":4},["span",{"class":"sVt8B"}," \n"]],["span",{"class":"line","line":5},["span",{"class":"szBVR"}," while"],["span",{"class":"sVt8B"}," (retries "],["span",{"class":"szBVR"},"<"],["span",{"class":"sVt8B"}," maxRetries) {\n"]],["span",{"class":"line","line":6},["span",{"class":"szBVR"}," try"],["span",{"class":"sVt8B"}," {\n"]],["span",{"class":"line","line":7},["span",{"class":"szBVR"}," const"],["span",{"class":"sj4cs"}," stream"],["span",{"class":"szBVR"}," ="],["span",{"class":"szBVR"}," await"],["span",{"class":"sVt8B"}," client.ai."],["span",{"class":"sScJk"},"chatStream"],["span",{"class":"sVt8B"},"({"],["span",{"class":"szBVR"},"..."],["span",{"class":"sVt8B"},"})\n"]],["span",{"class":"line","line":8},["span",{"class":"szBVR"}," return"],["span",{"class":"sVt8B"}," stream\n"]],["span",{"class":"line","line":9},["span",{"class":"sVt8B"}," } "],["span",{"class":"szBVR"},"catch"],["span",{"class":"sVt8B"}," (error) {\n"]],["span",{"class":"line","line":10},["span",{"class":"sVt8B"}," retries"],["span",{"class":"szBVR"},"++\n"]],["span",{"class":"line","line":11},["span",{"class":"szBVR"}," await"],["span",{"class":"sScJk"}," sleep"],["span",{"class":"sVt8B"},"("],["span",{"class":"sj4cs"},"1000"],["span",{"class":"szBVR"}," *"],["span",{"class":"sVt8B"}," retries) "],["span",{"class":"sJ8bj"},"// 指数退避\n"]],["span",{"class":"line","line":12},["span",{"class":"sVt8B"}," }\n"]],["span",{"class":"line","line":13},["span",{"class":"sVt8B"}," }\n"]],["span",{"class":"line","line":14},["span",{"class":"sVt8B"},"}\n"]]]],["h3",{"id":"q-如何在流式过程中取消请求"},"Q: 如何在流式过程中取消请求?"],["pre",{"className":"language-typescript shiki shiki-themes github-light github-dark","code":"const controller = new AbortController()\n\n// 发送请求\nconst stream = await client.ai.chatStream({\n messages: [...],\n signal: controller.signal\n})\n\n// 取消请求\ncontroller.abort()\n","language":"typescript","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"szBVR"},"const"],["span",{"class":"sj4cs"}," controller"],["span",{"class":"szBVR"}," ="],["span",{"class":"szBVR"}," new"],["span",{"class":"sScJk"}," AbortController"],["span",{"class":"sVt8B"},"()\n"]],["span",{"class":"line","line":2},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":3},["span",{"class":"sJ8bj"},"// 发送请求\n"]],["span",{"class":"line","line":4},["span",{"class":"szBVR"},"const"],["span",{"class":"sj4cs"}," stream"],["span",{"class":"szBVR"}," ="],["span",{"class":"szBVR"}," await"],["span",{"class":"sVt8B"}," client.ai."],["span",{"class":"sScJk"},"chatStream"],["span",{"class":"sVt8B"},"({\n"]],["span",{"class":"line","line":5},["span",{"class":"sVt8B"}," messages: ["],["span",{"class":"szBVR"},"..."],["span",{"class":"sVt8B"},"],\n"]],["span",{"class":"line","line":6},["span",{"class":"sVt8B"}," signal: controller.signal\n"]],["span",{"class":"line","line":7},["span",{"class":"sVt8B"},"})\n"]],["span",{"class":"line","line":8},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":9},["span",{"class":"sJ8bj"},"// 取消请求\n"]],["span",{"class":"line","line":10},["span",{"class":"sVt8B"},"controller."],["span",{"class":"sScJk"},"abort"],["span",{"class":"sVt8B"},"()\n"]]]],["h3",{"id":"q-sse-和-websocket-区别"},"Q: SSE 和 WebSocket 区别?"],["table",{},["thead",{},["tr",{},["th",{},"特性"],["th",{},"SSE"],["th",{},"WebSocket"]]],["tbody",{},["tr",{},["td",{},"方向"],["td",{},"单向(服务端→客户端)"],["td",{},"双向"]],["tr",{},["td",{},"协议"],["td",{},"HTTP"],["td",{},"ws://"]],["tr",{},["td",{},"重连"],["td",{},"自动"],["td",{},"需手动处理"]],["tr",{},["td",{},"复杂度"],["td",{},"简单"],["td",{},"复杂"]],["tr",{},["td",{},"适用"],["td",{},"AI 流式输出"],["td",{},"实时聊天"]]]],["style",{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}"]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"什么是流式输出","depth":2,"text":"🌊 什么是流式输出?","children":[{"id":"对比","depth":3,"text":"对比"}]},{"id":"开始使用","depth":2,"text":"🚀 开始使用","children":[{"id":"前端接收流式响应","depth":3,"text":"前端:接收流式响应"},{"id":"响应数据结构","depth":3,"text":"响应数据结构"}]},{"id":"原生-sse-实现","depth":2,"text":"🌐 原生 SSE 实现"},{"id":"前端组件示例","depth":2,"text":"🎨 前端组件示例","children":[{"id":"vue-composition-api","depth":3,"text":"Vue Composition API"}]},{"id":"常见问题","depth":2,"text":"❓ 常见问题","children":[{"id":"q-流式中断怎么办","depth":3,"text":"Q: 流式中断怎么办?"},{"id":"q-如何在流式过程中取消请求","depth":3,"text":"Q: 如何在流式过程中取消请求?"},{"id":"q-sse-和-websocket-区别","depth":3,"text":"Q: SSE 和 WebSocket 区别?"}]}]}}', '使用 Server-Sent Events 实现 AI 流式响应,提升用户体验。', 'md', '{"category":"api","order":2}', 'true', '/docs/api/streaming', '{"title":"流式输出SSE接入","description":"使用 Server-Sent Events 实现 AI 流式响应,提升用户体验。"}', 'docs/api/streaming', '7KYLowobLFDLS7cOqbBp4iZ20Cc95cZzYg2PYk_PHsE'); -- 7KYLowobLFDLS7cOqbBp4iZ20Cc95cZzYg2PYk_PHsE
INSERT INTO _content_docs VALUES ('docs/docs/api/webhook.md', 'Webhook 事件接入', '{"type":"minimark","value":[["h1",{"id":"webhook-事件接入"},"Webhook 事件接入"],["blockquote",{},["p",{},"订阅业务事件处理订单支付、AI 任务完成等异步通知。"]],["h2",{"id":"什么是-webhook"},"🔔 什么是 Webhook"],["p",{},"Webhook 是一种「反向 API 调用」机制:"],["ul",{},["li",{},"传统 API你 → 平台(主动拉取)"],["li",{},"Webhook平台 → 你(被动接收)"]],["p",{},"当某个事件发生时(如支付成功),平台主动通知你的服务器。"],["h2",{"id":"可订阅的事件"},"📋 可订阅的事件"],["table",{},["thead",{},["tr",{},["th",{},"事件类型"],["th",{},"说明"]]],["tbody",{},["tr",{},["td",{},["code",{},"payment.completed"]],["td",{},"支付完成"]],["tr",{},["td",{},["code",{},"payment.failed"]],["td",{},"支付失败"]],["tr",{},["td",{},["code",{},"subscription.created"]],["td",{},"订阅创建"]],["tr",{},["td",{},["code",{},"subscription.cancelled"]],["td",{},"订阅取消"]],["tr",{},["td",{},["code",{},"ai.task.completed"]],["td",{},"AI 任务完成"]],["tr",{},["td",{},["code",{},"ai.task.failed"]],["td",{},"AI 任务失败"]],["tr",{},["td",{},["code",{},"file.uploaded"]],["td",{},"文件上传完成"]],["tr",{},["td",{},["code",{},"project.created"]],["td",{},"项目创建"]],["tr",{},["td",{},["code",{},"user.invited"]],["td",{},"用户被邀请"]],["tr",{},["td",{},["code",{},"workflow.triggered"]],["td",{},"工作流触发"]]]],["h2",{"id":"配置-webhook"},"🚀 配置 Webhook"],["h3",{"id":"步骤-1创建-webhook-端点"},"步骤 1创建 Webhook 端点"],["p",{},"在你的服务器创建一个 API 端点:"],["pre",{"className":"language-typescript shiki shiki-themes github-light github-dark","code":"// Node.js Express 示例\napp.post(''/webhook/websopy'', express.raw({ type: ''application/json'' }), (req, res) => {\n // 验证签名\n const signature = req.headers[''x-websopy-signature'']\n const timestamp = req.headers[''x-websopy-timestamp'']\n \n if (!verifySignature(req.body, signature, timestamp)) {\n return res.status(401).send(''Invalid signature'')\n }\n \n // 处理事件\n const event = JSON.parse(req.body)\n console.log(''收到事件:'', event.type)\n \n // 立即返回 200重要\n res.status(200).send(''OK'')\n \n // 异步处理业务逻辑\n processEvent(event)\n})\n","language":"typescript","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sJ8bj"},"// Node.js Express 示例\n"]],["span",{"class":"line","line":2},["span",{"class":"sVt8B"},"app."],["span",{"class":"sScJk"},"post"],["span",{"class":"sVt8B"},"("],["span",{"class":"sZZnC"},"''/webhook/websopy''"],["span",{"class":"sVt8B"},", express."],["span",{"class":"sScJk"},"raw"],["span",{"class":"sVt8B"},"({ type: "],["span",{"class":"sZZnC"},"''application/json''"],["span",{"class":"sVt8B"}," }), ("],["span",{"class":"s4XuR"},"req"],["span",{"class":"sVt8B"},", "],["span",{"class":"s4XuR"},"res"],["span",{"class":"sVt8B"},") "],["span",{"class":"szBVR"},"=>"],["span",{"class":"sVt8B"}," {\n"]],["span",{"class":"line","line":3},["span",{"class":"sJ8bj"}," // 验证签名\n"]],["span",{"class":"line","line":4},["span",{"class":"szBVR"}," const"],["span",{"class":"sj4cs"}," signature"],["span",{"class":"szBVR"}," ="],["span",{"class":"sVt8B"}," req.headers["],["span",{"class":"sZZnC"},"''x-websopy-signature''"],["span",{"class":"sVt8B"},"]\n"]],["span",{"class":"line","line":5},["span",{"class":"szBVR"}," const"],["span",{"class":"sj4cs"}," timestamp"],["span",{"class":"szBVR"}," ="],["span",{"class":"sVt8B"}," req.headers["],["span",{"class":"sZZnC"},"''x-websopy-timestamp''"],["span",{"class":"sVt8B"},"]\n"]],["span",{"class":"line","line":6},["span",{"class":"sVt8B"}," \n"]],["span",{"class":"line","line":7},["span",{"class":"szBVR"}," if"],["span",{"class":"sVt8B"}," ("],["span",{"class":"szBVR"},"!"],["span",{"class":"sScJk"},"verifySignature"],["span",{"class":"sVt8B"},"(req.body, signature, timestamp)) {\n"]],["span",{"class":"line","line":8},["span",{"class":"szBVR"}," return"],["span",{"class":"sVt8B"}," res."],["span",{"class":"sScJk"},"status"],["span",{"class":"sVt8B"},"("],["span",{"class":"sj4cs"},"401"],["span",{"class":"sVt8B"},")."],["span",{"class":"sScJk"},"send"],["span",{"class":"sVt8B"},"("],["span",{"class":"sZZnC"},"''Invalid signature''"],["span",{"class":"sVt8B"},")\n"]],["span",{"class":"line","line":9},["span",{"class":"sVt8B"}," }\n"]],["span",{"class":"line","line":10},["span",{"class":"sVt8B"}," \n"]],["span",{"class":"line","line":11},["span",{"class":"sJ8bj"}," // 处理事件\n"]],["span",{"class":"line","line":12},["span",{"class":"szBVR"}," const"],["span",{"class":"sj4cs"}," event"],["span",{"class":"szBVR"}," ="],["span",{"class":"sj4cs"}," JSON"],["span",{"class":"sVt8B"},"."],["span",{"class":"sScJk"},"parse"],["span",{"class":"sVt8B"},"(req.body)\n"]],["span",{"class":"line","line":13},["span",{"class":"sVt8B"}," console."],["span",{"class":"sScJk"},"log"],["span",{"class":"sVt8B"},"("],["span",{"class":"sZZnC"},"''收到事件:''"],["span",{"class":"sVt8B"},", event.type)\n"]],["span",{"class":"line","line":14},["span",{"class":"sVt8B"}," \n"]],["span",{"class":"line","line":15},["span",{"class":"sJ8bj"}," // 立即返回 200重要\n"]],["span",{"class":"line","line":16},["span",{"class":"sVt8B"}," res."],["span",{"class":"sScJk"},"status"],["span",{"class":"sVt8B"},"("],["span",{"class":"sj4cs"},"200"],["span",{"class":"sVt8B"},")."],["span",{"class":"sScJk"},"send"],["span",{"class":"sVt8B"},"("],["span",{"class":"sZZnC"},"''OK''"],["span",{"class":"sVt8B"},")\n"]],["span",{"class":"line","line":17},["span",{"class":"sVt8B"}," \n"]],["span",{"class":"line","line":18},["span",{"class":"sJ8bj"}," // 异步处理业务逻辑\n"]],["span",{"class":"line","line":19},["span",{"class":"sScJk"}," processEvent"],["span",{"class":"sVt8B"},"(event)\n"]],["span",{"class":"line","line":20},["span",{"class":"sVt8B"},"})\n"]]]],["h3",{"id":"步骤-2在控制台配置"},"步骤 2在控制台配置"],["ol",{},["li",{},"进入 ",["strong",{},"开发者中心 → Webhook"]],["li",{},"点击 ",["strong",{},"添加端点"]],["li",{},"填写配置:"]],["table",{},["thead",{},["tr",{},["th",{},"配置项"],["th",{},"说明"]]],["tbody",{},["tr",{},["td",{},"URL"],["td",{},"你的服务器地址,如 ",["code",{},"https://your-server.com/webhook/websopy"]]],["tr",{},["td",{},"事件类型"],["td",{},"选择要订阅的事件"]],["tr",{},["td",{},"密钥"],["td",{},"用于验证签名的密钥"]]]],["h3",{"id":"步骤-3验证签名"},"步骤 3验证签名"],["pre",{"className":"language-typescript shiki shiki-themes github-light github-dark","code":"import crypto from ''crypto''\n\nfunction verifySignature(body, signature, timestamp) {\n const secret = process.env.WEBSOPY_WEBHOOK_SECRET\n \n // 检查时间戳5分钟内有效\n const ts = parseInt(timestamp)\n if (Date.now() - ts > 5 * 60 * 1000) {\n return false\n }\n \n // 计算签名\n const payload = `${timestamp}.${body}`\n const expectedSignature = crypto\n .createHmac(''sha256'', secret)\n .update(payload)\n .digest(''hex'')\n \n return crypto.timingSafeEqual(\n Buffer.from(signature),\n Buffer.from(expectedSignature)\n )\n}\n","language":"typescript","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"szBVR"},"import"],["span",{"class":"sVt8B"}," crypto "],["span",{"class":"szBVR"},"from"],["span",{"class":"sZZnC"}," ''crypto''\n"]],["span",{"class":"line","line":2},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":3},["span",{"class":"szBVR"},"function"],["span",{"class":"sScJk"}," verifySignature"],["span",{"class":"sVt8B"},"("],["span",{"class":"s4XuR"},"body"],["span",{"class":"sVt8B"},", "],["span",{"class":"s4XuR"},"signature"],["span",{"class":"sVt8B"},", "],["span",{"class":"s4XuR"},"timestamp"],["span",{"class":"sVt8B"},") {\n"]],["span",{"class":"line","line":4},["span",{"class":"szBVR"}," const"],["span",{"class":"sj4cs"}," secret"],["span",{"class":"szBVR"}," ="],["span",{"class":"sVt8B"}," process.env."],["span",{"class":"sj4cs"},"WEBSOPY_WEBHOOK_SECRET\n"]],["span",{"class":"line","line":5},["span",{"class":"sVt8B"}," \n"]],["span",{"class":"line","line":6},["span",{"class":"sJ8bj"}," // 检查时间戳5分钟内有效\n"]],["span",{"class":"line","line":7},["span",{"class":"szBVR"}," const"],["span",{"class":"sj4cs"}," ts"],["span",{"class":"szBVR"}," ="],["span",{"class":"sScJk"}," parseInt"],["span",{"class":"sVt8B"},"(timestamp)\n"]],["span",{"class":"line","line":8},["span",{"class":"szBVR"}," if"],["span",{"class":"sVt8B"}," (Date."],["span",{"class":"sScJk"},"now"],["span",{"class":"sVt8B"},"() "],["span",{"class":"szBVR"},"-"],["span",{"class":"sVt8B"}," ts "],["span",{"class":"szBVR"},">"],["span",{"class":"sj4cs"}," 5"],["span",{"class":"szBVR"}," *"],["span",{"class":"sj4cs"}," 60"],["span",{"class":"szBVR"}," *"],["span",{"class":"sj4cs"}," 1000"],["span",{"class":"sVt8B"},") {\n"]],["span",{"class":"line","line":9},["span",{"class":"szBVR"}," return"],["span",{"class":"sj4cs"}," false\n"]],["span",{"class":"line","line":10},["span",{"class":"sVt8B"}," }\n"]],["span",{"class":"line","line":11},["span",{"class":"sVt8B"}," \n"]],["span",{"class":"line","line":12},["span",{"class":"sJ8bj"}," // 计算签名\n"]],["span",{"class":"line","line":13},["span",{"class":"szBVR"}," const"],["span",{"class":"sj4cs"}," payload"],["span",{"class":"szBVR"}," ="],["span",{"class":"sZZnC"}," `${"],["span",{"class":"sVt8B"},"timestamp"],["span",{"class":"sZZnC"},"}.${"],["span",{"class":"sVt8B"},"body"],["span",{"class":"sZZnC"},"}`\n"]],["span",{"class":"line","line":14},["span",{"class":"szBVR"}," const"],["span",{"class":"sj4cs"}," expectedSignature"],["span",{"class":"szBVR"}," ="],["span",{"class":"sVt8B"}," crypto\n"]],["span",{"class":"line","line":15},["span",{"class":"sVt8B"}," ."],["span",{"class":"sScJk"},"createHmac"],["span",{"class":"sVt8B"},"("],["span",{"class":"sZZnC"},"''sha256''"],["span",{"class":"sVt8B"},", secret)\n"]],["span",{"class":"line","line":16},["span",{"class":"sVt8B"}," ."],["span",{"class":"sScJk"},"update"],["span",{"class":"sVt8B"},"(payload)\n"]],["span",{"class":"line","line":17},["span",{"class":"sVt8B"}," ."],["span",{"class":"sScJk"},"digest"],["span",{"class":"sVt8B"},"("],["span",{"class":"sZZnC"},"''hex''"],["span",{"class":"sVt8B"},")\n"]],["span",{"class":"line","line":18},["span",{"class":"sVt8B"}," \n"]],["span",{"class":"line","line":19},["span",{"class":"szBVR"}," return"],["span",{"class":"sVt8B"}," crypto."],["span",{"class":"sScJk"},"timingSafeEqual"],["span",{"class":"sVt8B"},"(\n"]],["span",{"class":"line","line":20},["span",{"class":"sVt8B"}," Buffer."],["span",{"class":"sScJk"},"from"],["span",{"class":"sVt8B"},"(signature),\n"]],["span",{"class":"line","line":21},["span",{"class":"sVt8B"}," Buffer."],["span",{"class":"sScJk"},"from"],["span",{"class":"sVt8B"},"(expectedSignature)\n"]],["span",{"class":"line","line":22},["span",{"class":"sVt8B"}," )\n"]],["span",{"class":"line","line":23},["span",{"class":"sVt8B"},"}\n"]]]],["h2",{"id":"事件数据格式"},"📨 事件数据格式"],["h3",{"id":"通用结构"},"通用结构"],["pre",{"className":"language-json shiki shiki-themes github-light github-dark","code":"{\n \"id\": \"evt_abc123xyz\",\n \"type\": \"payment.completed\",\n \"created_at\": \"2024-01-15T10:30:00Z\",\n \"data\": {\n // 事件相关数据\n }\n}\n","language":"json","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sVt8B"},"{\n"]],["span",{"class":"line","line":2},["span",{"class":"sj4cs"}," \"id\""],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"\"evt_abc123xyz\""],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":3},["span",{"class":"sj4cs"}," \"type\""],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"\"payment.completed\""],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":4},["span",{"class":"sj4cs"}," \"created_at\""],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"\"2024-01-15T10:30:00Z\""],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":5},["span",{"class":"sj4cs"}," \"data\""],["span",{"class":"sVt8B"},": {\n"]],["span",{"class":"line","line":6},["span",{"class":"sJ8bj"}," // 事件相关数据\n"]],["span",{"class":"line","line":7},["span",{"class":"sVt8B"}," }\n"]],["span",{"class":"line","line":8},["span",{"class":"sVt8B"},"}\n"]]]],["h3",{"id":"支付完成事件"},"支付完成事件"],["pre",{"className":"language-json shiki shiki-themes github-light github-dark","code":"{\n \"id\": \"evt_abc123xyz\",\n \"type\": \"payment.completed\",\n \"created_at\": \"2024-01-15T10:30:00Z\",\n \"data\": {\n \"order_id\": \"ord_xyz789\",\n \"amount\": 29900,\n \"currency\": \"CNY\",\n \"payment_method\": \"alipay\",\n \"status\": \"completed\",\n \"user_id\": \"user_123\"\n }\n}\n","language":"json","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sVt8B"},"{\n"]],["span",{"class":"line","line":2},["span",{"class":"sj4cs"}," \"id\""],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"\"evt_abc123xyz\""],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":3},["span",{"class":"sj4cs"}," \"type\""],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"\"payment.completed\""],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":4},["span",{"class":"sj4cs"}," \"created_at\""],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"\"2024-01-15T10:30:00Z\""],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":5},["span",{"class":"sj4cs"}," \"data\""],["span",{"class":"sVt8B"},": {\n"]],["span",{"class":"line","line":6},["span",{"class":"sj4cs"}," \"order_id\""],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"\"ord_xyz789\""],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":7},["span",{"class":"sj4cs"}," \"amount\""],["span",{"class":"sVt8B"},": "],["span",{"class":"sj4cs"},"29900"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":8},["span",{"class":"sj4cs"}," \"currency\""],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"\"CNY\""],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":9},["span",{"class":"sj4cs"}," \"payment_method\""],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"\"alipay\""],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":10},["span",{"class":"sj4cs"}," \"status\""],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"\"completed\""],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":11},["span",{"class":"sj4cs"}," \"user_id\""],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"\"user_123\"\n"]],["span",{"class":"line","line":12},["span",{"class":"sVt8B"}," }\n"]],["span",{"class":"line","line":13},["span",{"class":"sVt8B"},"}\n"]]]],["h2",{"id":"失败重试"},"⏰ 失败重试"],["p",{},"如果你的服务器返回非 200 状态码Websopy 会自动重试:"],["table",{},["thead",{},["tr",{},["th",{},"重试次数"],["th",{},"延迟"]]],["tbody",{},["tr",{},["td",{},"第 1 次"],["td",{},"1 分钟"]],["tr",{},["td",{},"第 2 次"],["td",{},"5 分钟"]],["tr",{},["td",{},"第 3 次"],["td",{},"30 分钟"]],["tr",{},["td",{},"第 4 次"],["td",{},"2 小时"]],["tr",{},["td",{},"第 5 次"],["td",{},"12 小时"]]]],["p",{},"超过重试次数仍未成功,事件将被标记为失败,可在控制台手动重试。"],["h3",{"id":"幂等处理"},"幂等处理"],["pre",{"className":"language-typescript shiki shiki-themes github-light github-dark","code":"const processedEvents = new Set()\n\napp.post(''/webhook/websopy'', async (req, res) => {\n const event = JSON.parse(req.body)\n \n // 幂等检查\n if (processedEvents.has(event.id)) {\n return res.status(200).send(''Already processed'')\n }\n \n try {\n await processEvent(event)\n processedEvents.add(event.id)\n res.status(200).send(''OK'')\n } catch (error) {\n res.status(500).send(''Error'')\n }\n})\n","language":"typescript","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"szBVR"},"const"],["span",{"class":"sj4cs"}," processedEvents"],["span",{"class":"szBVR"}," ="],["span",{"class":"szBVR"}," new"],["span",{"class":"sScJk"}," Set"],["span",{"class":"sVt8B"},"()\n"]],["span",{"class":"line","line":2},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":3},["span",{"class":"sVt8B"},"app."],["span",{"class":"sScJk"},"post"],["span",{"class":"sVt8B"},"("],["span",{"class":"sZZnC"},"''/webhook/websopy''"],["span",{"class":"sVt8B"},", "],["span",{"class":"szBVR"},"async"],["span",{"class":"sVt8B"}," ("],["span",{"class":"s4XuR"},"req"],["span",{"class":"sVt8B"},", "],["span",{"class":"s4XuR"},"res"],["span",{"class":"sVt8B"},") "],["span",{"class":"szBVR"},"=>"],["span",{"class":"sVt8B"}," {\n"]],["span",{"class":"line","line":4},["span",{"class":"szBVR"}," const"],["span",{"class":"sj4cs"}," event"],["span",{"class":"szBVR"}," ="],["span",{"class":"sj4cs"}," JSON"],["span",{"class":"sVt8B"},"."],["span",{"class":"sScJk"},"parse"],["span",{"class":"sVt8B"},"(req.body)\n"]],["span",{"class":"line","line":5},["span",{"class":"sVt8B"}," \n"]],["span",{"class":"line","line":6},["span",{"class":"sJ8bj"}," // 幂等检查\n"]],["span",{"class":"line","line":7},["span",{"class":"szBVR"}," if"],["span",{"class":"sVt8B"}," (processedEvents."],["span",{"class":"sScJk"},"has"],["span",{"class":"sVt8B"},"(event.id)) {\n"]],["span",{"class":"line","line":8},["span",{"class":"szBVR"}," return"],["span",{"class":"sVt8B"}," res."],["span",{"class":"sScJk"},"status"],["span",{"class":"sVt8B"},"("],["span",{"class":"sj4cs"},"200"],["span",{"class":"sVt8B"},")."],["span",{"class":"sScJk"},"send"],["span",{"class":"sVt8B"},"("],["span",{"class":"sZZnC"},"''Already processed''"],["span",{"class":"sVt8B"},")\n"]],["span",{"class":"line","line":9},["span",{"class":"sVt8B"}," }\n"]],["span",{"class":"line","line":10},["span",{"class":"sVt8B"}," \n"]],["span",{"class":"line","line":11},["span",{"class":"szBVR"}," try"],["span",{"class":"sVt8B"}," {\n"]],["span",{"class":"line","line":12},["span",{"class":"szBVR"}," await"],["span",{"class":"sScJk"}," processEvent"],["span",{"class":"sVt8B"},"(event)\n"]],["span",{"class":"line","line":13},["span",{"class":"sVt8B"}," processedEvents."],["span",{"class":"sScJk"},"add"],["span",{"class":"sVt8B"},"(event.id)\n"]],["span",{"class":"line","line":14},["span",{"class":"sVt8B"}," res."],["span",{"class":"sScJk"},"status"],["span",{"class":"sVt8B"},"("],["span",{"class":"sj4cs"},"200"],["span",{"class":"sVt8B"},")."],["span",{"class":"sScJk"},"send"],["span",{"class":"sVt8B"},"("],["span",{"class":"sZZnC"},"''OK''"],["span",{"class":"sVt8B"},")\n"]],["span",{"class":"line","line":15},["span",{"class":"sVt8B"}," } "],["span",{"class":"szBVR"},"catch"],["span",{"class":"sVt8B"}," (error) {\n"]],["span",{"class":"line","line":16},["span",{"class":"sVt8B"}," res."],["span",{"class":"sScJk"},"status"],["span",{"class":"sVt8B"},"("],["span",{"class":"sj4cs"},"500"],["span",{"class":"sVt8B"},")."],["span",{"class":"sScJk"},"send"],["span",{"class":"sVt8B"},"("],["span",{"class":"sZZnC"},"''Error''"],["span",{"class":"sVt8B"},")\n"]],["span",{"class":"line","line":17},["span",{"class":"sVt8B"}," }\n"]],["span",{"class":"line","line":18},["span",{"class":"sVt8B"},"})\n"]]]],["h2",{"id":"本地开发测试"},"🧪 本地开发测试"],["h3",{"id":"使用-ngrok"},"使用 ngrok"],["pre",{"className":"language-bash shiki shiki-themes github-light github-dark","code":"# 安装 ngrok\nnpm install -g ngrok\n\n# 启动本地服务\nngrok http 3000\n\n# 复制输出的 https URL 到 Webhook 配置\n# https://abc123.ngrok.io/webhook/websopy\n","language":"bash","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sJ8bj"},"# 安装 ngrok\n"]],["span",{"class":"line","line":2},["span",{"class":"sScJk"},"npm"],["span",{"class":"sZZnC"}," install"],["span",{"class":"sj4cs"}," -g"],["span",{"class":"sZZnC"}," ngrok\n"]],["span",{"class":"line","line":3},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":4},["span",{"class":"sJ8bj"},"# 启动本地服务\n"]],["span",{"class":"line","line":5},["span",{"class":"sScJk"},"ngrok"],["span",{"class":"sZZnC"}," http"],["span",{"class":"sj4cs"}," 3000\n"]],["span",{"class":"line","line":6},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":7},["span",{"class":"sJ8bj"},"# 复制输出的 https URL 到 Webhook 配置\n"]],["span",{"class":"line","line":8},["span",{"class":"sJ8bj"},"# https://abc123.ngrok.io/webhook/websopy\n"]]]],["h2",{"id":"常见问题"},"❓ 常见问题"],["h3",{"id":"q-收到重复事件怎么办"},"Q: 收到重复事件怎么办?"],["p",{},"使用事件 ID 做幂等检查,参考上文示例。"],["h3",{"id":"q-处理超时怎么办"},"Q: 处理超时怎么办?"],["pre",{"className":"language-typescript shiki shiki-themes github-light github-dark","code":"app.post(''/webhook'', async (req, res) => {\n // 立即返回\n res.status(200).send(''OK'')\n \n // 异步处理\n setImmediate(() => processEvent(req.body))\n})\n","language":"typescript","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sVt8B"},"app."],["span",{"class":"sScJk"},"post"],["span",{"class":"sVt8B"},"("],["span",{"class":"sZZnC"},"''/webhook''"],["span",{"class":"sVt8B"},", "],["span",{"class":"szBVR"},"async"],["span",{"class":"sVt8B"}," ("],["span",{"class":"s4XuR"},"req"],["span",{"class":"sVt8B"},", "],["span",{"class":"s4XuR"},"res"],["span",{"class":"sVt8B"},") "],["span",{"class":"szBVR"},"=>"],["span",{"class":"sVt8B"}," {\n"]],["span",{"class":"line","line":2},["span",{"class":"sJ8bj"}," // 立即返回\n"]],["span",{"class":"line","line":3},["span",{"class":"sVt8B"}," res."],["span",{"class":"sScJk"},"status"],["span",{"class":"sVt8B"},"("],["span",{"class":"sj4cs"},"200"],["span",{"class":"sVt8B"},")."],["span",{"class":"sScJk"},"send"],["span",{"class":"sVt8B"},"("],["span",{"class":"sZZnC"},"''OK''"],["span",{"class":"sVt8B"},")\n"]],["span",{"class":"line","line":4},["span",{"class":"sVt8B"}," \n"]],["span",{"class":"line","line":5},["span",{"class":"sJ8bj"}," // 异步处理\n"]],["span",{"class":"line","line":6},["span",{"class":"sScJk"}," setImmediate"],["span",{"class":"sVt8B"},"(() "],["span",{"class":"szBVR"},"=>"],["span",{"class":"sScJk"}," processEvent"],["span",{"class":"sVt8B"},"(req.body))\n"]],["span",{"class":"line","line":7},["span",{"class":"sVt8B"},"})\n"]]]],["style",{},"html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}"]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"什么是-webhook","depth":2,"text":"🔔 什么是 Webhook"},{"id":"可订阅的事件","depth":2,"text":"📋 可订阅的事件"},{"id":"配置-webhook","depth":2,"text":"🚀 配置 Webhook","children":[{"id":"步骤-1创建-webhook-端点","depth":3,"text":"步骤 1创建 Webhook 端点"},{"id":"步骤-2在控制台配置","depth":3,"text":"步骤 2在控制台配置"},{"id":"步骤-3验证签名","depth":3,"text":"步骤 3验证签名"}]},{"id":"事件数据格式","depth":2,"text":"📨 事件数据格式","children":[{"id":"通用结构","depth":3,"text":"通用结构"},{"id":"支付完成事件","depth":3,"text":"支付完成事件"}]},{"id":"失败重试","depth":2,"text":"⏰ 失败重试","children":[{"id":"幂等处理","depth":3,"text":"幂等处理"}]},{"id":"本地开发测试","depth":2,"text":"🧪 本地开发测试","children":[{"id":"使用-ngrok","depth":3,"text":"使用 ngrok"}]},{"id":"常见问题","depth":2,"text":"❓ 常见问题","children":[{"id":"q-收到重复事件怎么办","depth":3,"text":"Q: 收到重复事件怎么办?"},{"id":"q-处理超时怎么办","depth":3,"text":"Q: 处理超时怎么办?"}]}]}}', '订阅业务事件处理订单支付、AI 任务完成等异步通知。', 'md', '{"category":"api","order":3}', 'true', '/docs/api/webhook', '{"title":"Webhook 事件接入","description":"订阅业务事件处理订单支付、AI 任务完成等异步通知。"}', 'docs/api/webhook', 'JzUDaOPT8P4lqAf6z6op6nMpr0qauqZr8pTO6bB32u8'); -- JzUDaOPT8P4lqAf6z6op6nMpr0qauqZr8pTO6bB32u8
INSERT INTO _content_docs VALUES ('docs/docs/deploy/docker.md', 'Docker Compose 部署', '{"type":"minimark","value":[["h1",{"id":"docker-compose-部署"},"Docker Compose 部署"],["blockquote",{},["p",{},"一键部署全套服务(前端+后端+数据库+AI本地与云端通用。"]],["h2",{"id":"什么是-docker-compose"},"🐳 什么是 Docker Compose"],["p",{},"Docker Compose 是一个工具,用于定义和运行多容器 Docker 应用。通过一个 ",["code",{},"docker-compose.yml"]," 文件,你可以一键启动所有相关服务。"],["h2",{"id":"前提条件"},"📋 前提条件"],["ul",{},["li",{},"Docker 20.10+"],["li",{},"Docker Compose 2.0+"],["li",{},"至少 4GB 内存"]],["h2",{"id":"快速开始"},"🚀 快速开始"],["h3",{"id":"第一步下载模板"},"第一步:下载模板"],["pre",{"className":"language-bash shiki shiki-themes github-light github-dark","code":"# 克隆模板仓库\ngit clone https://github.com/websopy/deploy-templates.git websopy-deploy\ncd websopy-deploy\n\n# 选择版本\ngit checkout v2.3.0\n","language":"bash","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sJ8bj"},"# 克隆模板仓库\n"]],["span",{"class":"line","line":2},["span",{"class":"sScJk"},"git"],["span",{"class":"sZZnC"}," clone"],["span",{"class":"sZZnC"}," https://github.com/websopy/deploy-templates.git"],["span",{"class":"sZZnC"}," websopy-deploy\n"]],["span",{"class":"line","line":3},["span",{"class":"sj4cs"},"cd"],["span",{"class":"sZZnC"}," websopy-deploy\n"]],["span",{"class":"line","line":4},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":5},["span",{"class":"sJ8bj"},"# 选择版本\n"]],["span",{"class":"line","line":6},["span",{"class":"sScJk"},"git"],["span",{"class":"sZZnC"}," checkout"],["span",{"class":"sZZnC"}," v2.3.0\n"]]]],["h3",{"id":"第二步配置环境"},"第二步:配置环境"],["pre",{"className":"language-bash shiki shiki-themes github-light github-dark","code":"# 复制环境变量文件\ncp .env.example .env\n\n# 编辑配置\nnano .env\n","language":"bash","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sJ8bj"},"# 复制环境变量文件\n"]],["span",{"class":"line","line":2},["span",{"class":"sScJk"},"cp"],["span",{"class":"sZZnC"}," .env.example"],["span",{"class":"sZZnC"}," .env\n"]],["span",{"class":"line","line":3},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":4},["span",{"class":"sJ8bj"},"# 编辑配置\n"]],["span",{"class":"line","line":5},["span",{"class":"sScJk"},"nano"],["span",{"class":"sZZnC"}," .env\n"]]]],["p",{},"关键配置:"],["pre",{"className":"language-env shiki shiki-themes github-light github-dark","code":"# 版本\nWEBSOPY_VERSION=2.3.0\n\n# 数据库\nPOSTGRES_DB=websopy\nPOSTGRES_USER=websopy\nPOSTGRES_PASSWORD=your-strong-password\n\n# Redis\nREDIS_PASSWORD=your-redis-password\n\n# JWT 密钥(生成随机字符串)\nJWT_SECRET=$(openssl rand -hex 32)\n\n# 域名(可选)\nDOMAIN=your-domain.com\n","language":"env","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{},"# 版本\n"]],["span",{"class":"line","line":2},["span",{},"WEBSOPY_VERSION=2.3.0\n"]],["span",{"class":"line","line":3},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":4},["span",{},"# 数据库\n"]],["span",{"class":"line","line":5},["span",{},"POSTGRES_DB=websopy\n"]],["span",{"class":"line","line":6},["span",{},"POSTGRES_USER=websopy\n"]],["span",{"class":"line","line":7},["span",{},"POSTGRES_PASSWORD=your-strong-password\n"]],["span",{"class":"line","line":8},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":9},["span",{},"# Redis\n"]],["span",{"class":"line","line":10},["span",{},"REDIS_PASSWORD=your-redis-password\n"]],["span",{"class":"line","line":11},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":12},["span",{},"# JWT 密钥(生成随机字符串)\n"]],["span",{"class":"line","line":13},["span",{},"JWT_SECRET=$(openssl rand -hex 32)\n"]],["span",{"class":"line","line":14},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":15},["span",{},"# 域名(可选)\n"]],["span",{"class":"line","line":16},["span",{},"DOMAIN=your-domain.com\n"]]]],["h3",{"id":"第三步启动服务"},"第三步:启动服务"],["pre",{"className":"language-bash shiki shiki-themes github-light github-dark","code":"# 一键启动所有服务\ndocker-compose up -d\n\n# 查看服务状态\ndocker-compose ps\n\n# 查看日志\ndocker-compose logs -f\n","language":"bash","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sJ8bj"},"# 一键启动所有服务\n"]],["span",{"class":"line","line":2},["span",{"class":"sScJk"},"docker-compose"],["span",{"class":"sZZnC"}," up"],["span",{"class":"sj4cs"}," -d\n"]],["span",{"class":"line","line":3},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":4},["span",{"class":"sJ8bj"},"# 查看服务状态\n"]],["span",{"class":"line","line":5},["span",{"class":"sScJk"},"docker-compose"],["span",{"class":"sZZnC"}," ps\n"]],["span",{"class":"line","line":6},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":7},["span",{"class":"sJ8bj"},"# 查看日志\n"]],["span",{"class":"line","line":8},["span",{"class":"sScJk"},"docker-compose"],["span",{"class":"sZZnC"}," logs"],["span",{"class":"sj4cs"}," -f\n"]]]],["h3",{"id":"第四步验证部署"},"第四步:验证部署"],["pre",{"className":"language-bash shiki shiki-themes github-light github-dark","code":"# 检查服务健康状态\ncurl http://localhost:3000/api/health\n\n# 预期输出\n{\"status\":\"ok\",\"version\":\"2.3.0\",\"services\":{\"db\":\"up\",\"redis\":\"up\",\"ai\":\"up\"}}\n","language":"bash","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sJ8bj"},"# 检查服务健康状态\n"]],["span",{"class":"line","line":2},["span",{"class":"sScJk"},"curl"],["span",{"class":"sZZnC"}," http://localhost:3000/api/health\n"]],["span",{"class":"line","line":3},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":4},["span",{"class":"sJ8bj"},"# 预期输出\n"]],["span",{"class":"line","line":5},["span",{"class":"sVt8B"},"{"],["span",{"class":"sScJk"},"\"status\""],["span",{"class":"sj4cs"},":"],["span",{"class":"sScJk"},"\"ok\""],["span",{"class":"sScJk"},","],["span",{"class":"sScJk"},"\"version\""],["span",{"class":"sj4cs"},":"],["span",{"class":"sScJk"},"\"2.3.0\""],["span",{"class":"sScJk"},","],["span",{"class":"sScJk"},"\"services\""],["span",{"class":"sj4cs"},":"],["span",{"class":"sZZnC"},"{"],["span",{"class":"sVt8B"},"\""],["span",{"class":"sScJk"},"db"],["span",{"class":"sScJk"},"\":\""],["span",{"class":"sScJk"},"up"],["span",{"class":"sScJk"},"\",\""],["span",{"class":"sScJk"},"redis"],["span",{"class":"sScJk"},"\":\""],["span",{"class":"sScJk"},"up"],["span",{"class":"sScJk"},"\",\""],["span",{"class":"sScJk"},"ai"],["span",{"class":"sScJk"},"\":\""],["span",{"class":"sScJk"},"up"],["span",{"class":"sScJk"},"\"}}\n"]]]],["h2",{"id":"-服务架构"},"🏗️ 服务架构"],["pre",{"className":["language-text"],"code":" ┌─────────────┐\n │ Nginx │\n │ (反向代理) │\n └──────┬──────┘\n │\n ┌───────────────┼───────────────┐\n │ │ │\n ┌────▼────┐ ┌─────▼────┐ ┌────▼────┐\n │ Web │ │ API │ │ Worker │\n │ (前端) │ │ (后端) │ │ (异步) │\n └─────────┘ └─────┬────┘ └─────────┘\n │\n ┌────────────┼────────────┐\n │ │ │\n ┌────▼───┐ ┌─────▼────┐ ┌───▼────┐\n │Postgres│ │ Redis │ │ AI │\n │(数据库) │ │ (缓存) │ │(AI服务) │\n └────────┘ └──────────┘ └────────┘\n","language":"text"},["code",{"__ignoreMap":""}," ┌─────────────┐\n │ Nginx │\n │ (反向代理) │\n └──────┬──────┘\n │\n ┌───────────────┼───────────────┐\n │ │ │\n ┌────▼────┐ ┌─────▼────┐ ┌────▼────┐\n │ Web │ │ API │ │ Worker │\n │ (前端) │ │ (后端) │ │ (异步) │\n └─────────┘ └─────┬────┘ └─────────┘\n │\n ┌────────────┼────────────┐\n │ │ │\n ┌────▼───┐ ┌─────▼────┐ ┌───▼────┐\n │Postgres│ │ Redis │ │ AI │\n │(数据库) │ │ (缓存) │ │(AI服务) │\n └────────┘ └──────────┘ └────────┘\n"]],["h2",{"id":"常用命令"},"🔧 常用命令"],["h3",{"id":"启动与停止"},"启动与停止"],["pre",{"className":"language-bash shiki shiki-themes github-light github-dark","code":"# 启动所有服务\ndocker-compose up -d\n\n# 停止所有服务\ndocker-compose down\n\n# 重启所有服务\ndocker-compose restart\n\n# 重启指定服务\ndocker-compose restart api\n","language":"bash","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sJ8bj"},"# 启动所有服务\n"]],["span",{"class":"line","line":2},["span",{"class":"sScJk"},"docker-compose"],["span",{"class":"sZZnC"}," up"],["span",{"class":"sj4cs"}," -d\n"]],["span",{"class":"line","line":3},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":4},["span",{"class":"sJ8bj"},"# 停止所有服务\n"]],["span",{"class":"line","line":5},["span",{"class":"sScJk"},"docker-compose"],["span",{"class":"sZZnC"}," down\n"]],["span",{"class":"line","line":6},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":7},["span",{"class":"sJ8bj"},"# 重启所有服务\n"]],["span",{"class":"line","line":8},["span",{"class":"sScJk"},"docker-compose"],["span",{"class":"sZZnC"}," restart\n"]],["span",{"class":"line","line":9},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":10},["span",{"class":"sJ8bj"},"# 重启指定服务\n"]],["span",{"class":"line","line":11},["span",{"class":"sScJk"},"docker-compose"],["span",{"class":"sZZnC"}," restart"],["span",{"class":"sZZnC"}," api\n"]]]],["h3",{"id":"日志查看"},"日志查看"],["pre",{"className":"language-bash shiki shiki-themes github-light github-dark","code":"# 查看所有日志\ndocker-compose logs -f\n\n# 查看特定服务日志\ndocker-compose logs -f api\ndocker-compose logs -f web\n\n# 查看最近 100 行\ndocker-compose logs --tail=100\n","language":"bash","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sJ8bj"},"# 查看所有日志\n"]],["span",{"class":"line","line":2},["span",{"class":"sScJk"},"docker-compose"],["span",{"class":"sZZnC"}," logs"],["span",{"class":"sj4cs"}," -f\n"]],["span",{"class":"line","line":3},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":4},["span",{"class":"sJ8bj"},"# 查看特定服务日志\n"]],["span",{"class":"line","line":5},["span",{"class":"sScJk"},"docker-compose"],["span",{"class":"sZZnC"}," logs"],["span",{"class":"sj4cs"}," -f"],["span",{"class":"sZZnC"}," api\n"]],["span",{"class":"line","line":6},["span",{"class":"sScJk"},"docker-compose"],["span",{"class":"sZZnC"}," logs"],["span",{"class":"sj4cs"}," -f"],["span",{"class":"sZZnC"}," web\n"]],["span",{"class":"line","line":7},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":8},["span",{"class":"sJ8bj"},"# 查看最近 100 行\n"]],["span",{"class":"line","line":9},["span",{"class":"sScJk"},"docker-compose"],["span",{"class":"sZZnC"}," logs"],["span",{"class":"sj4cs"}," --tail=100\n"]]]],["h3",{"id":"进入容器"},"进入容器"],["pre",{"className":"language-bash shiki shiki-themes github-light github-dark","code":"# 进入 API 容器\ndocker-compose exec api sh\n\n# 进入数据库\ndocker-compose exec postgres psql -U websopy\n","language":"bash","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sJ8bj"},"# 进入 API 容器\n"]],["span",{"class":"line","line":2},["span",{"class":"sScJk"},"docker-compose"],["span",{"class":"sZZnC"}," exec"],["span",{"class":"sZZnC"}," api"],["span",{"class":"sZZnC"}," sh\n"]],["span",{"class":"line","line":3},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":4},["span",{"class":"sJ8bj"},"# 进入数据库\n"]],["span",{"class":"line","line":5},["span",{"class":"sScJk"},"docker-compose"],["span",{"class":"sZZnC"}," exec"],["span",{"class":"sZZnC"}," postgres"],["span",{"class":"sZZnC"}," psql"],["span",{"class":"sj4cs"}," -U"],["span",{"class":"sZZnC"}," websopy\n"]]]],["h2",{"id":"数据持久化"},"💾 数据持久化"],["p",{},"数据存储在 Docker volumes 中:"],["pre",{"className":"language-bash shiki shiki-themes github-light github-dark","code":"# 查看 volumes\ndocker volume ls | grep websopy\n\n# 备份数据\ndocker-compose exec postgres pg_dump -U websopy > backup.sql\n\n# 恢复数据\ndocker exec -i $(docker-compose ps -q postgres) psql -U websopy < backup.sql\n","language":"bash","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sJ8bj"},"# 查看 volumes\n"]],["span",{"class":"line","line":2},["span",{"class":"sScJk"},"docker"],["span",{"class":"sZZnC"}," volume"],["span",{"class":"sZZnC"}," ls"],["span",{"class":"szBVR"}," |"],["span",{"class":"sScJk"}," grep"],["span",{"class":"sZZnC"}," websopy\n"]],["span",{"class":"line","line":3},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":4},["span",{"class":"sJ8bj"},"# 备份数据\n"]],["span",{"class":"line","line":5},["span",{"class":"sScJk"},"docker-compose"],["span",{"class":"sZZnC"}," exec"],["span",{"class":"sZZnC"}," postgres"],["span",{"class":"sZZnC"}," pg_dump"],["span",{"class":"sj4cs"}," -U"],["span",{"class":"sZZnC"}," websopy"],["span",{"class":"szBVR"}," >"],["span",{"class":"sZZnC"}," backup.sql\n"]],["span",{"class":"line","line":6},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":7},["span",{"class":"sJ8bj"},"# 恢复数据\n"]],["span",{"class":"line","line":8},["span",{"class":"sScJk"},"docker"],["span",{"class":"sZZnC"}," exec"],["span",{"class":"sj4cs"}," -i"],["span",{"class":"sVt8B"}," $("],["span",{"class":"sScJk"},"docker-compose"],["span",{"class":"sZZnC"}," ps"],["span",{"class":"sj4cs"}," -q"],["span",{"class":"sZZnC"}," postgres"],["span",{"class":"sVt8B"},") "],["span",{"class":"sZZnC"},"psql"],["span",{"class":"sj4cs"}," -U"],["span",{"class":"sZZnC"}," websopy"],["span",{"class":"szBVR"}," <"],["span",{"class":"sZZnC"}," backup.sql\n"]]]],["h2",{"id":"故障排查"},"🐛 故障排查"],["h3",{"id":"服务无法启动"},"服务无法启动"],["pre",{"className":"language-bash shiki shiki-themes github-light github-dark","code":"# 1. 检查 Docker 是否运行\ndocker info\n\n# 2. 查看详细日志\ndocker-compose up\n\n# 3. 检查端口占用\nlsof -i :80\n","language":"bash","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sJ8bj"},"# 1. 检查 Docker 是否运行\n"]],["span",{"class":"line","line":2},["span",{"class":"sScJk"},"docker"],["span",{"class":"sZZnC"}," info\n"]],["span",{"class":"line","line":3},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":4},["span",{"class":"sJ8bj"},"# 2. 查看详细日志\n"]],["span",{"class":"line","line":5},["span",{"class":"sScJk"},"docker-compose"],["span",{"class":"sZZnC"}," up\n"]],["span",{"class":"line","line":6},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":7},["span",{"class":"sJ8bj"},"# 3. 检查端口占用\n"]],["span",{"class":"line","line":8},["span",{"class":"sScJk"},"lsof"],["span",{"class":"sj4cs"}," -i"],["span",{"class":"sZZnC"}," :80\n"]]]],["h3",{"id":"数据库连接失败"},"数据库连接失败"],["pre",{"className":"language-bash shiki shiki-themes github-light github-dark","code":"# 1. 检查 postgres 是否运行\ndocker-compose ps postgres\n\n# 2. 查看数据库日志\ndocker-compose logs postgres\n\n# 3. 测试连接\ndocker-compose exec postgres psql -U websopy -c \"SELECT 1\"\n","language":"bash","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sJ8bj"},"# 1. 检查 postgres 是否运行\n"]],["span",{"class":"line","line":2},["span",{"class":"sScJk"},"docker-compose"],["span",{"class":"sZZnC"}," ps"],["span",{"class":"sZZnC"}," postgres\n"]],["span",{"class":"line","line":3},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":4},["span",{"class":"sJ8bj"},"# 2. 查看数据库日志\n"]],["span",{"class":"line","line":5},["span",{"class":"sScJk"},"docker-compose"],["span",{"class":"sZZnC"}," logs"],["span",{"class":"sZZnC"}," postgres\n"]],["span",{"class":"line","line":6},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":7},["span",{"class":"sJ8bj"},"# 3. 测试连接\n"]],["span",{"class":"line","line":8},["span",{"class":"sScJk"},"docker-compose"],["span",{"class":"sZZnC"}," exec"],["span",{"class":"sZZnC"}," postgres"],["span",{"class":"sZZnC"}," psql"],["span",{"class":"sj4cs"}," -U"],["span",{"class":"sZZnC"}," websopy"],["span",{"class":"sj4cs"}," -c"],["span",{"class":"sZZnC"}," \"SELECT 1\"\n"]]]],["style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}"]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"什么是-docker-compose","depth":2,"text":"🐳 什么是 Docker Compose"},{"id":"前提条件","depth":2,"text":"📋 前提条件"},{"id":"快速开始","depth":2,"text":"🚀 快速开始","children":[{"id":"第一步下载模板","depth":3,"text":"第一步:下载模板"},{"id":"第二步配置环境","depth":3,"text":"第二步:配置环境"},{"id":"第三步启动服务","depth":3,"text":"第三步:启动服务"},{"id":"第四步验证部署","depth":3,"text":"第四步:验证部署"}]},{"id":"-服务架构","depth":2,"text":"🏗️ 服务架构"},{"id":"常用命令","depth":2,"text":"🔧 常用命令","children":[{"id":"启动与停止","depth":3,"text":"启动与停止"},{"id":"日志查看","depth":3,"text":"日志查看"},{"id":"进入容器","depth":3,"text":"进入容器"}]},{"id":"数据持久化","depth":2,"text":"💾 数据持久化"},{"id":"故障排查","depth":2,"text":"🐛 故障排查","children":[{"id":"服务无法启动","depth":3,"text":"服务无法启动"},{"id":"数据库连接失败","depth":3,"text":"数据库连接失败"}]}]}}', '一键部署全套服务(前端+后端+数据库+AI本地与云端通用。', 'md', '{"category":"deploy","order":1}', 'true', '/docs/deploy/docker', '{"title":"Docker Compose 部署","description":"一键部署全套服务(前端+后端+数据库+AI本地与云端通用。"}', 'docs/deploy/docker', 'JLPDy1ukkZcXDwJc1JrVAKX-blTkv_BsqqzsEhQ4L1A'); -- JLPDy1ukkZcXDwJc1JrVAKX-blTkv_BsqqzsEhQ4L1A
INSERT INTO _content_docs VALUES ('docs/docs/deploy/private-deploy.md', '私有化部署完全指南', '{"type":"minimark","value":[["h1",{"id":"私有化部署完全指南"},"私有化部署完全指南"],["blockquote",{},["p",{},"Docker Compose 一键部署HTTPS 配置、备份策略与版本升级。"]],["h2",{"id":"什么是私有化部署"},"🏠 什么是私有化部署?"],["p",{},"私有化部署让你在自己的服务器上运行 Websopy 平台,享受:"],["ul",{},["li",{},"🔒 ",["strong",{},"数据完全自主"]," - 所有数据存储在你的服务器"],["li",{},"⚙️ ",["strong",{},"完全可控"]," - 自定义配置、插件、界面"],["li",{},"💰 ",["strong",{},"成本可控"]," - 无按调用量计费"],["li",{},"🏢 ",["strong",{},"合规无忧"]," - 满足数据不出网要求"]],["h2",{"id":"系统要求"},"📋 系统要求"],["h3",{"id":"最低配置"},"最低配置"],["table",{},["thead",{},["tr",{},["th",{},"资源"],["th",{},"最低要求"]]],["tbody",{},["tr",{},["td",{},"CPU"],["td",{},"4 核"]],["tr",{},["td",{},"内存"],["td",{},"8 GB"]],["tr",{},["td",{},"硬盘"],["td",{},"100 GB SSD"]],["tr",{},["td",{},"系统"],["td",{},"Ubuntu 20.04+ / CentOS 8+"]]]],["h3",{"id":"推荐配置"},"推荐配置"],["table",{},["thead",{},["tr",{},["th",{},"资源"],["th",{},"推荐配置"]]],["tbody",{},["tr",{},["td",{},"CPU"],["td",{},"8 核+"]],["tr",{},["td",{},"内存"],["td",{},"16 GB+"]],["tr",{},["td",{},"硬盘"],["td",{},"500 GB SSD+"]],["tr",{},["td",{},"系统"],["td",{},"Ubuntu 22.04 LTS"]]]],["h3",{"id":"软件依赖"},"软件依赖"],["ul",{},["li",{},"Docker 20.10+"],["li",{},"Docker Compose 2.0+"],["li",{},"Git"],["li",{},"域名(可选,用于 HTTPS"]],["h2",{"id":"开始部署"},"🚀 开始部署"],["h3",{"id":"第一步准备服务器"},"第一步:准备服务器"],["pre",{"className":"language-bash shiki shiki-themes github-light github-dark","code":"# 更新系统\nsudo apt update && sudo apt upgrade -y\n\n# 安装 DockerUbuntu/Debian\ncurl -fsSL https://get.docker.com | sh\nsudo usermod -aG docker $USER\n\n# 验证安装\ndocker --version\ndocker-compose --version\n","language":"bash","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sJ8bj"},"# 更新系统\n"]],["span",{"class":"line","line":2},["span",{"class":"sScJk"},"sudo"],["span",{"class":"sZZnC"}," apt"],["span",{"class":"sZZnC"}," update"],["span",{"class":"sVt8B"}," && "],["span",{"class":"sScJk"},"sudo"],["span",{"class":"sZZnC"}," apt"],["span",{"class":"sZZnC"}," upgrade"],["span",{"class":"sj4cs"}," -y\n"]],["span",{"class":"line","line":3},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":4},["span",{"class":"sJ8bj"},"# 安装 DockerUbuntu/Debian\n"]],["span",{"class":"line","line":5},["span",{"class":"sScJk"},"curl"],["span",{"class":"sj4cs"}," -fsSL"],["span",{"class":"sZZnC"}," https://get.docker.com"],["span",{"class":"szBVR"}," |"],["span",{"class":"sScJk"}," sh\n"]],["span",{"class":"line","line":6},["span",{"class":"sScJk"},"sudo"],["span",{"class":"sZZnC"}," usermod"],["span",{"class":"sj4cs"}," -aG"],["span",{"class":"sZZnC"}," docker"],["span",{"class":"sVt8B"}," $USER\n"]],["span",{"class":"line","line":7},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":8},["span",{"class":"sJ8bj"},"# 验证安装\n"]],["span",{"class":"line","line":9},["span",{"class":"sScJk"},"docker"],["span",{"class":"sj4cs"}," --version\n"]],["span",{"class":"line","line":10},["span",{"class":"sScJk"},"docker-compose"],["span",{"class":"sj4cs"}," --version\n"]]]],["h3",{"id":"第二步下载部署包"},"第二步:下载部署包"],["pre",{"className":"language-bash shiki shiki-themes github-light github-dark","code":"# 创建工作目录\nmkdir -p ~/websopy && cd ~/websopy\n\n# 下载最新版本\nwget https://releases.websopy.com/on-premise/latest.tar.gz\n\n# 解压\ntar -xzf latest.tar.gz\ncd websopy-deploy\n","language":"bash","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sJ8bj"},"# 创建工作目录\n"]],["span",{"class":"line","line":2},["span",{"class":"sScJk"},"mkdir"],["span",{"class":"sj4cs"}," -p"],["span",{"class":"sZZnC"}," ~/websopy"],["span",{"class":"sVt8B"}," && "],["span",{"class":"sj4cs"},"cd"],["span",{"class":"sZZnC"}," ~/websopy\n"]],["span",{"class":"line","line":3},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":4},["span",{"class":"sJ8bj"},"# 下载最新版本\n"]],["span",{"class":"line","line":5},["span",{"class":"sScJk"},"wget"],["span",{"class":"sZZnC"}," https://releases.websopy.com/on-premise/latest.tar.gz\n"]],["span",{"class":"line","line":6},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":7},["span",{"class":"sJ8bj"},"# 解压\n"]],["span",{"class":"line","line":8},["span",{"class":"sScJk"},"tar"],["span",{"class":"sj4cs"}," -xzf"],["span",{"class":"sZZnC"}," latest.tar.gz\n"]],["span",{"class":"line","line":9},["span",{"class":"sj4cs"},"cd"],["span",{"class":"sZZnC"}," websopy-deploy\n"]]]],["h3",{"id":"第三步配置环境"},"第三步:配置环境"],["pre",{"className":"language-bash shiki shiki-themes github-light github-dark","code":"# 复制配置文件\ncp .env.example .env\n\n# 编辑配置文件\nnano .env\n","language":"bash","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sJ8bj"},"# 复制配置文件\n"]],["span",{"class":"line","line":2},["span",{"class":"sScJk"},"cp"],["span",{"class":"sZZnC"}," .env.example"],["span",{"class":"sZZnC"}," .env\n"]],["span",{"class":"line","line":3},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":4},["span",{"class":"sJ8bj"},"# 编辑配置文件\n"]],["span",{"class":"line","line":5},["span",{"class":"sScJk"},"nano"],["span",{"class":"sZZnC"}," .env\n"]]]],["p",{},"关键配置项:"],["pre",{"className":"language-env shiki shiki-themes github-light github-dark","code":"# 版本配置\nWEBSOPY_VERSION=latest\n\n# 数据库配置\nDB_HOST=postgres\nDB_PORT=5432\nDB_NAME=websopy\nDB_USER=websopy\nDB_PASSWORD=your-secure-password\n\n# Redis 配置\nREDIS_HOST=redis\nREDIS_PORT=6379\nREDIS_PASSWORD=your-redis-password\n\n# 域名配置(可选)\nDOMAIN=your-domain.com\nHTTPS_ENABLED=true\n\n# 管理员账户\nADMIN_EMAIL=admin@yourcompany.com\nADMIN_PASSWORD=your-admin-password\n","language":"env","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{},"# 版本配置\n"]],["span",{"class":"line","line":2},["span",{},"WEBSOPY_VERSION=latest\n"]],["span",{"class":"line","line":3},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":4},["span",{},"# 数据库配置\n"]],["span",{"class":"line","line":5},["span",{},"DB_HOST=postgres\n"]],["span",{"class":"line","line":6},["span",{},"DB_PORT=5432\n"]],["span",{"class":"line","line":7},["span",{},"DB_NAME=websopy\n"]],["span",{"class":"line","line":8},["span",{},"DB_USER=websopy\n"]],["span",{"class":"line","line":9},["span",{},"DB_PASSWORD=your-secure-password\n"]],["span",{"class":"line","line":10},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":11},["span",{},"# Redis 配置\n"]],["span",{"class":"line","line":12},["span",{},"REDIS_HOST=redis\n"]],["span",{"class":"line","line":13},["span",{},"REDIS_PORT=6379\n"]],["span",{"class":"line","line":14},["span",{},"REDIS_PASSWORD=your-redis-password\n"]],["span",{"class":"line","line":15},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":16},["span",{},"# 域名配置(可选)\n"]],["span",{"class":"line","line":17},["span",{},"DOMAIN=your-domain.com\n"]],["span",{"class":"line","line":18},["span",{},"HTTPS_ENABLED=true\n"]],["span",{"class":"line","line":19},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":20},["span",{},"# 管理员账户\n"]],["span",{"class":"line","line":21},["span",{},"ADMIN_EMAIL=admin@yourcompany.com\n"]],["span",{"class":"line","line":22},["span",{},"ADMIN_PASSWORD=your-admin-password\n"]]]],["h3",{"id":"第四步启动服务"},"第四步:启动服务"],["pre",{"className":"language-bash shiki shiki-themes github-light github-dark","code":"# 拉取镜像\ndocker-compose pull\n\n# 启动所有服务\ndocker-compose up -d\n\n# 查看服务状态\ndocker-compose ps\n","language":"bash","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sJ8bj"},"# 拉取镜像\n"]],["span",{"class":"line","line":2},["span",{"class":"sScJk"},"docker-compose"],["span",{"class":"sZZnC"}," pull\n"]],["span",{"class":"line","line":3},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":4},["span",{"class":"sJ8bj"},"# 启动所有服务\n"]],["span",{"class":"line","line":5},["span",{"class":"sScJk"},"docker-compose"],["span",{"class":"sZZnC"}," up"],["span",{"class":"sj4cs"}," -d\n"]],["span",{"class":"line","line":6},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":7},["span",{"class":"sJ8bj"},"# 查看服务状态\n"]],["span",{"class":"line","line":8},["span",{"class":"sScJk"},"docker-compose"],["span",{"class":"sZZnC"}," ps\n"]]]],["h3",{"id":"第五步访问平台"},"第五步:访问平台"],["p",{},"服务启动后,通过浏览器访问:"],["ul",{},["li",{},"前端界面:",["code",{},"http://your-server-ip:80"]],["li",{},"管理后台:",["code",{},"http://your-server-ip:80/admin"]],["li",{},"API 端点:",["code",{},"http://your-server-ip:8080/api/v1"]]],["h2",{"id":"https-配置"},"🔒 HTTPS 配置"],["h3",{"id":"使用-lets-encrypt推荐"},"使用 Let''s Encrypt推荐"],["pre",{"className":"language-bash shiki shiki-themes github-light github-dark","code":"# 申请 SSL 证书\ncertbot --nginx -d your-domain.com\n\n# 重启 nginx\ndocker-compose restart nginx\n","language":"bash","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sJ8bj"},"# 申请 SSL 证书\n"]],["span",{"class":"line","line":2},["span",{"class":"sScJk"},"certbot"],["span",{"class":"sj4cs"}," --nginx"],["span",{"class":"sj4cs"}," -d"],["span",{"class":"sZZnC"}," your-domain.com\n"]],["span",{"class":"line","line":3},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":4},["span",{"class":"sJ8bj"},"# 重启 nginx\n"]],["span",{"class":"line","line":5},["span",{"class":"sScJk"},"docker-compose"],["span",{"class":"sZZnC"}," restart"],["span",{"class":"sZZnC"}," nginx\n"]]]],["h2",{"id":"备份策略"},"💾 备份策略"],["h3",{"id":"自动备份脚本"},"自动备份脚本"],["pre",{"className":"language-bash shiki shiki-themes github-light github-dark","code":"#!/bin/bash\nBACKUP_DIR=/data/backups/websopy\nDATE=$(date +%Y%m%d_%H%M%S)\n\nmkdir -p $BACKUP_DIR\n\n# 备份数据库\ndocker exec websopy-postgres pg_dump -U websopy > $BACKUP_DIR/db_$DATE.sql\n\n# 备份上传文件\ntar -czf $BACKUP_DIR/uploads_$DATE.tar.gz /data/websopy/uploads\n\n# 保留最近 30 天的备份\nfind $BACKUP_DIR -mtime +30 -delete\n\necho \"备份完成: $DATE\"\n","language":"bash","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sJ8bj"},"#!/bin/bash\n"]],["span",{"class":"line","line":2},["span",{"class":"sVt8B"},"BACKUP_DIR"],["span",{"class":"szBVR"},"="],["span",{"class":"sZZnC"},"/data/backups/websopy\n"]],["span",{"class":"line","line":3},["span",{"class":"sVt8B"},"DATE"],["span",{"class":"szBVR"},"="],["span",{"class":"sVt8B"},"$("],["span",{"class":"sScJk"},"date"],["span",{"class":"sZZnC"}," +%Y%m%d_%H%M%S"],["span",{"class":"sVt8B"},")\n"]],["span",{"class":"line","line":4},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":5},["span",{"class":"sScJk"},"mkdir"],["span",{"class":"sj4cs"}," -p"],["span",{"class":"sVt8B"}," $BACKUP_DIR\n"]],["span",{"class":"line","line":6},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":7},["span",{"class":"sJ8bj"},"# 备份数据库\n"]],["span",{"class":"line","line":8},["span",{"class":"sScJk"},"docker"],["span",{"class":"sZZnC"}," exec"],["span",{"class":"sZZnC"}," websopy-postgres"],["span",{"class":"sZZnC"}," pg_dump"],["span",{"class":"sj4cs"}," -U"],["span",{"class":"sZZnC"}," websopy"],["span",{"class":"szBVR"}," >"],["span",{"class":"sVt8B"}," $BACKUP_DIR"],["span",{"class":"sZZnC"},"/db_"],["span",{"class":"sVt8B"},"$DATE"],["span",{"class":"sZZnC"},".sql\n"]],["span",{"class":"line","line":9},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":10},["span",{"class":"sJ8bj"},"# 备份上传文件\n"]],["span",{"class":"line","line":11},["span",{"class":"sScJk"},"tar"],["span",{"class":"sj4cs"}," -czf"],["span",{"class":"sVt8B"}," $BACKUP_DIR"],["span",{"class":"sZZnC"},"/uploads_"],["span",{"class":"sVt8B"},"$DATE"],["span",{"class":"sZZnC"},".tar.gz"],["span",{"class":"sZZnC"}," /data/websopy/uploads\n"]],["span",{"class":"line","line":12},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":13},["span",{"class":"sJ8bj"},"# 保留最近 30 天的备份\n"]],["span",{"class":"line","line":14},["span",{"class":"sScJk"},"find"],["span",{"class":"sVt8B"}," $BACKUP_DIR "],["span",{"class":"sj4cs"},"-mtime"],["span",{"class":"sZZnC"}," +30"],["span",{"class":"sj4cs"}," -delete\n"]],["span",{"class":"line","line":15},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":16},["span",{"class":"sj4cs"},"echo"],["span",{"class":"sZZnC"}," \"备份完成: "],["span",{"class":"sVt8B"},"$DATE"],["span",{"class":"sZZnC"},"\"\n"]]]],["pre",{"className":"language-bash shiki shiki-themes github-light github-dark","code":"# 设置定时任务(每天凌晨 3 点执行)\ncrontab -e\n# 添加行: 0 3 * * * /data/websopy/backup.sh >> /var/log/backup.log 2>&1\n","language":"bash","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sJ8bj"},"# 设置定时任务(每天凌晨 3 点执行)\n"]],["span",{"class":"line","line":2},["span",{"class":"sScJk"},"crontab"],["span",{"class":"sj4cs"}," -e\n"]],["span",{"class":"line","line":3},["span",{"class":"sJ8bj"},"# 添加行: 0 3 * * * /data/websopy/backup.sh >> /var/log/backup.log 2>&1\n"]]]],["h2",{"id":"常见问题"},"🐛 常见问题"],["h3",{"id":"q-服务启动失败"},"Q: 服务启动失败?"],["pre",{"className":"language-bash shiki shiki-themes github-light github-dark","code":"# 查看日志\ndocker-compose logs -f\n\n# 检查端口占用\nnetstat -tlnp | grep -E ''80|443|5432|6379''\n","language":"bash","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sJ8bj"},"# 查看日志\n"]],["span",{"class":"line","line":2},["span",{"class":"sScJk"},"docker-compose"],["span",{"class":"sZZnC"}," logs"],["span",{"class":"sj4cs"}," -f\n"]],["span",{"class":"line","line":3},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":4},["span",{"class":"sJ8bj"},"# 检查端口占用\n"]],["span",{"class":"line","line":5},["span",{"class":"sScJk"},"netstat"],["span",{"class":"sj4cs"}," -tlnp"],["span",{"class":"szBVR"}," |"],["span",{"class":"sScJk"}," grep"],["span",{"class":"sj4cs"}," -E"],["span",{"class":"sZZnC"}," ''80|443|5432|6379''\n"]]]],["h3",{"id":"q-内存不足"},"Q: 内存不足?"],["pre",{"className":"language-bash shiki shiki-themes github-light github-dark","code":"# 查看内存使用\ndocker stats\n\n# 增加 swap\nsudo fallocate -l 4G /swapfile\nsudo chmod 600 /swapfile\nsudo mkswap /swapfile\nsudo swapon /swapfile\n","language":"bash","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sJ8bj"},"# 查看内存使用\n"]],["span",{"class":"line","line":2},["span",{"class":"sScJk"},"docker"],["span",{"class":"sZZnC"}," stats\n"]],["span",{"class":"line","line":3},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":4},["span",{"class":"sJ8bj"},"# 增加 swap\n"]],["span",{"class":"line","line":5},["span",{"class":"sScJk"},"sudo"],["span",{"class":"sZZnC"}," fallocate"],["span",{"class":"sj4cs"}," -l"],["span",{"class":"sZZnC"}," 4G"],["span",{"class":"sZZnC"}," /swapfile\n"]],["span",{"class":"line","line":6},["span",{"class":"sScJk"},"sudo"],["span",{"class":"sZZnC"}," chmod"],["span",{"class":"sj4cs"}," 600"],["span",{"class":"sZZnC"}," /swapfile\n"]],["span",{"class":"line","line":7},["span",{"class":"sScJk"},"sudo"],["span",{"class":"sZZnC"}," mkswap"],["span",{"class":"sZZnC"}," /swapfile\n"]],["span",{"class":"line","line":8},["span",{"class":"sScJk"},"sudo"],["span",{"class":"sZZnC"}," swapon"],["span",{"class":"sZZnC"}," /swapfile\n"]]]],["style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}"]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"什么是私有化部署","depth":2,"text":"🏠 什么是私有化部署?"},{"id":"系统要求","depth":2,"text":"📋 系统要求","children":[{"id":"最低配置","depth":3,"text":"最低配置"},{"id":"推荐配置","depth":3,"text":"推荐配置"},{"id":"软件依赖","depth":3,"text":"软件依赖"}]},{"id":"开始部署","depth":2,"text":"🚀 开始部署","children":[{"id":"第一步准备服务器","depth":3,"text":"第一步:准备服务器"},{"id":"第二步下载部署包","depth":3,"text":"第二步:下载部署包"},{"id":"第三步配置环境","depth":3,"text":"第三步:配置环境"},{"id":"第四步启动服务","depth":3,"text":"第四步:启动服务"},{"id":"第五步访问平台","depth":3,"text":"第五步:访问平台"}]},{"id":"https-配置","depth":2,"text":"🔒 HTTPS 配置","children":[{"id":"使用-lets-encrypt推荐","depth":3,"text":"使用 Let''s Encrypt推荐"}]},{"id":"备份策略","depth":2,"text":"💾 备份策略","children":[{"id":"自动备份脚本","depth":3,"text":"自动备份脚本"}]},{"id":"常见问题","depth":2,"text":"🐛 常见问题","children":[{"id":"q-服务启动失败","depth":3,"text":"Q: 服务启动失败?"},{"id":"q-内存不足","depth":3,"text":"Q: 内存不足?"}]}]}}', 'Docker Compose 一键部署HTTPS 配置、备份策略与版本升级。', 'md', '{"category":"deploy","order":2}', 'true', '/docs/deploy/private-deploy', '{"title":"私有化部署完全指南","description":"Docker Compose 一键部署HTTPS 配置、备份策略与版本升级。"}', 'docs/deploy/private-deploy', 'cEk_JZvZaEC-Q8JKLtEhR4k3b9LNnnRxxcs2pGB9R8w'); -- cEk_JZvZaEC-Q8JKLtEhR4k3b9LNnnRxxcs2pGB9R8w
INSERT INTO _content_docs VALUES ('docs/docs/deploy/upgrade.md', '版本升级与回滚', '{"type":"minimark","value":[["h1",{"id":"版本升级与回滚"},"版本升级与回滚"],["blockquote",{},["p",{},"平滑升级生产环境,数据库迁移方案,紧急回滚操作手册。"]],["h2",{"id":"-升级前必读"},"⚠️ 升级前必读"],["h3",{"id":"重要检查清单"},"重要检查清单"],["ul",{"className":["contains-task-list"]},["li",{"className":["task-list-item"]},["input",{"disabled":true,"type":"checkbox"}]," 备份数据库"],["li",{"className":["task-list-item"]},["input",{"disabled":true,"type":"checkbox"}]," 查阅版本更新日志"],["li",{"className":["task-list-item"]},["input",{"disabled":true,"type":"checkbox"}]," 在测试环境验证"],["li",{"className":["task-list-item"]},["input",{"disabled":true,"type":"checkbox"}]," 确认回滚方案"],["li",{"className":["task-list-item"]},["input",{"disabled":true,"type":"checkbox"}]," 通知相关人员"],["li",{"className":["task-list-item"]},["input",{"disabled":true,"type":"checkbox"}]," 选择低峰期执行"]],["h3",{"id":"版本兼容性"},"版本兼容性"],["table",{},["thead",{},["tr",{},["th",{},"当前版本"],["th",{},"可直接升级到"]]],["tbody",{},["tr",{},["td",{},"2.0.x"],["td",{},"2.1.x"]],["tr",{},["td",{},"2.1.x"],["td",{},"2.2.x, 2.3.x"]],["tr",{},["td",{},"2.2.x"],["td",{},"2.3.x"]],["tr",{},["td",{},"1.x"],["td",{},"需要先升级到 2.0"]]]],["h2",{"id":"升级步骤"},"🚀 升级步骤"],["h3",{"id":"准备工作"},"准备工作"],["pre",{"className":"language-bash shiki shiki-themes github-light github-dark","code":"# 1. 进入部署目录\ncd ~/websopy-deploy\n\n# 2. 备份当前版本配置\ncp docker-compose.yml docker-compose.yml.bak\ncp .env .env.bak\n\n# 3. 备份数据库(必须!)\ndocker-compose exec postgres pg_dump -U websopy > backups/db_backup_$(date +%Y%m%d).sql\n\n# 4. 备份上传文件\ntar -czf backups/uploads_$(date +%Y%m%d).tar.gz -C /data/websopy uploads/\n","language":"bash","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sJ8bj"},"# 1. 进入部署目录\n"]],["span",{"class":"line","line":2},["span",{"class":"sj4cs"},"cd"],["span",{"class":"sZZnC"}," ~/websopy-deploy\n"]],["span",{"class":"line","line":3},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":4},["span",{"class":"sJ8bj"},"# 2. 备份当前版本配置\n"]],["span",{"class":"line","line":5},["span",{"class":"sScJk"},"cp"],["span",{"class":"sZZnC"}," docker-compose.yml"],["span",{"class":"sZZnC"}," docker-compose.yml.bak\n"]],["span",{"class":"line","line":6},["span",{"class":"sScJk"},"cp"],["span",{"class":"sZZnC"}," .env"],["span",{"class":"sZZnC"}," .env.bak\n"]],["span",{"class":"line","line":7},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":8},["span",{"class":"sJ8bj"},"# 3. 备份数据库(必须!)\n"]],["span",{"class":"line","line":9},["span",{"class":"sScJk"},"docker-compose"],["span",{"class":"sZZnC"}," exec"],["span",{"class":"sZZnC"}," postgres"],["span",{"class":"sZZnC"}," pg_dump"],["span",{"class":"sj4cs"}," -U"],["span",{"class":"sZZnC"}," websopy"],["span",{"class":"szBVR"}," >"],["span",{"class":"sZZnC"}," backups/db_backup_"],["span",{"class":"sVt8B"},"$("],["span",{"class":"sScJk"},"date"],["span",{"class":"sZZnC"}," +%Y%m%d"],["span",{"class":"sVt8B"},")"],["span",{"class":"sZZnC"},".sql\n"]],["span",{"class":"line","line":10},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":11},["span",{"class":"sJ8bj"},"# 4. 备份上传文件\n"]],["span",{"class":"line","line":12},["span",{"class":"sScJk"},"tar"],["span",{"class":"sj4cs"}," -czf"],["span",{"class":"sZZnC"}," backups/uploads_"],["span",{"class":"sVt8B"},"$("],["span",{"class":"sScJk"},"date"],["span",{"class":"sZZnC"}," +%Y%m%d"],["span",{"class":"sVt8B"},")"],["span",{"class":"sZZnC"},".tar.gz"],["span",{"class":"sj4cs"}," -C"],["span",{"class":"sZZnC"}," /data/websopy"],["span",{"class":"sZZnC"}," uploads/\n"]]]],["h3",{"id":"执行升级"},"执行升级"],["pre",{"className":"language-bash shiki shiki-themes github-light github-dark","code":"# 1. 停止服务\ndocker-compose down\n\n# 2. 拉取新版本镜像\ndocker-compose pull\n\n# 3. 更新代码(如果使用 git 部署)\ngit fetch origin\ngit checkout v2.3.0\n\n# 4. 检查新版本配置变更\ngit diff v2.2.0 v2.3.0 -- .env.example\n\n# 5. 合并配置变更\nnano .env\n\n# 6. 启动服务\ndocker-compose up -d\n\n# 7. 执行数据库迁移\ndocker-compose run --rm api websopy migrate\n","language":"bash","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sJ8bj"},"# 1. 停止服务\n"]],["span",{"class":"line","line":2},["span",{"class":"sScJk"},"docker-compose"],["span",{"class":"sZZnC"}," down\n"]],["span",{"class":"line","line":3},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":4},["span",{"class":"sJ8bj"},"# 2. 拉取新版本镜像\n"]],["span",{"class":"line","line":5},["span",{"class":"sScJk"},"docker-compose"],["span",{"class":"sZZnC"}," pull\n"]],["span",{"class":"line","line":6},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":7},["span",{"class":"sJ8bj"},"# 3. 更新代码(如果使用 git 部署)\n"]],["span",{"class":"line","line":8},["span",{"class":"sScJk"},"git"],["span",{"class":"sZZnC"}," fetch"],["span",{"class":"sZZnC"}," origin\n"]],["span",{"class":"line","line":9},["span",{"class":"sScJk"},"git"],["span",{"class":"sZZnC"}," checkout"],["span",{"class":"sZZnC"}," v2.3.0\n"]],["span",{"class":"line","line":10},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":11},["span",{"class":"sJ8bj"},"# 4. 检查新版本配置变更\n"]],["span",{"class":"line","line":12},["span",{"class":"sScJk"},"git"],["span",{"class":"sZZnC"}," diff"],["span",{"class":"sZZnC"}," v2.2.0"],["span",{"class":"sZZnC"}," v2.3.0"],["span",{"class":"sj4cs"}," --"],["span",{"class":"sZZnC"}," .env.example\n"]],["span",{"class":"line","line":13},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":14},["span",{"class":"sJ8bj"},"# 5. 合并配置变更\n"]],["span",{"class":"line","line":15},["span",{"class":"sScJk"},"nano"],["span",{"class":"sZZnC"}," .env\n"]],["span",{"class":"line","line":16},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":17},["span",{"class":"sJ8bj"},"# 6. 启动服务\n"]],["span",{"class":"line","line":18},["span",{"class":"sScJk"},"docker-compose"],["span",{"class":"sZZnC"}," up"],["span",{"class":"sj4cs"}," -d\n"]],["span",{"class":"line","line":19},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":20},["span",{"class":"sJ8bj"},"# 7. 执行数据库迁移\n"]],["span",{"class":"line","line":21},["span",{"class":"sScJk"},"docker-compose"],["span",{"class":"sZZnC"}," run"],["span",{"class":"sj4cs"}," --rm"],["span",{"class":"sZZnC"}," api"],["span",{"class":"sZZnC"}," websopy"],["span",{"class":"sZZnC"}," migrate\n"]]]],["h3",{"id":"验证升级"},"验证升级"],["pre",{"className":"language-bash shiki shiki-themes github-light github-dark","code":"# 检查服务状态\ndocker-compose ps\n\n# 检查 API 健康\ncurl http://localhost:3000/api/health\n\n# 检查版本号\ndocker-compose exec api websopy --version\n\n# 查看迁移日志\ndocker-compose logs api | grep -i migrate\n","language":"bash","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sJ8bj"},"# 检查服务状态\n"]],["span",{"class":"line","line":2},["span",{"class":"sScJk"},"docker-compose"],["span",{"class":"sZZnC"}," ps\n"]],["span",{"class":"line","line":3},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":4},["span",{"class":"sJ8bj"},"# 检查 API 健康\n"]],["span",{"class":"line","line":5},["span",{"class":"sScJk"},"curl"],["span",{"class":"sZZnC"}," http://localhost:3000/api/health\n"]],["span",{"class":"line","line":6},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":7},["span",{"class":"sJ8bj"},"# 检查版本号\n"]],["span",{"class":"line","line":8},["span",{"class":"sScJk"},"docker-compose"],["span",{"class":"sZZnC"}," exec"],["span",{"class":"sZZnC"}," api"],["span",{"class":"sZZnC"}," websopy"],["span",{"class":"sj4cs"}," --version\n"]],["span",{"class":"line","line":9},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":10},["span",{"class":"sJ8bj"},"# 查看迁移日志\n"]],["span",{"class":"line","line":11},["span",{"class":"sScJk"},"docker-compose"],["span",{"class":"sZZnC"}," logs"],["span",{"class":"sZZnC"}," api"],["span",{"class":"szBVR"}," |"],["span",{"class":"sScJk"}," grep"],["span",{"class":"sj4cs"}," -i"],["span",{"class":"sZZnC"}," migrate\n"]]]],["h2",{"id":"数据库迁移"},"🔧 数据库迁移"],["h3",{"id":"手动迁移"},"手动迁移"],["pre",{"className":"language-bash shiki shiki-themes github-light github-dark","code":"# 查看待执行迁移\ndocker-compose run --rm api websopy migrate:status\n\n# 执行迁移\ndocker-compose run --rm api websopy migrate\n\n# 回滚上一个迁移\ndocker-compose run --rm api websopy migrate:rollback\n","language":"bash","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sJ8bj"},"# 查看待执行迁移\n"]],["span",{"class":"line","line":2},["span",{"class":"sScJk"},"docker-compose"],["span",{"class":"sZZnC"}," run"],["span",{"class":"sj4cs"}," --rm"],["span",{"class":"sZZnC"}," api"],["span",{"class":"sZZnC"}," websopy"],["span",{"class":"sZZnC"}," migrate:status\n"]],["span",{"class":"line","line":3},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":4},["span",{"class":"sJ8bj"},"# 执行迁移\n"]],["span",{"class":"line","line":5},["span",{"class":"sScJk"},"docker-compose"],["span",{"class":"sZZnC"}," run"],["span",{"class":"sj4cs"}," --rm"],["span",{"class":"sZZnC"}," api"],["span",{"class":"sZZnC"}," websopy"],["span",{"class":"sZZnC"}," migrate\n"]],["span",{"class":"line","line":6},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":7},["span",{"class":"sJ8bj"},"# 回滚上一个迁移\n"]],["span",{"class":"line","line":8},["span",{"class":"sScJk"},"docker-compose"],["span",{"class":"sZZnC"}," run"],["span",{"class":"sj4cs"}," --rm"],["span",{"class":"sZZnC"}," api"],["span",{"class":"sZZnC"}," websopy"],["span",{"class":"sZZnC"}," migrate:rollback\n"]]]],["h2",{"id":"-紧急回滚"},"⤵️ 紧急回滚"],["h3",{"id":"自动回滚"},"自动回滚"],["pre",{"className":"language-bash shiki shiki-themes github-light github-dark","code":"# 如果启动失败,查看错误\ndocker-compose logs api\n\n# 回滚到上一个版本\ndocker-compose down\ngit checkout v2.2.0\ndocker-compose pull\ndocker-compose up -d\n","language":"bash","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sJ8bj"},"# 如果启动失败,查看错误\n"]],["span",{"class":"line","line":2},["span",{"class":"sScJk"},"docker-compose"],["span",{"class":"sZZnC"}," logs"],["span",{"class":"sZZnC"}," api\n"]],["span",{"class":"line","line":3},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":4},["span",{"class":"sJ8bj"},"# 回滚到上一个版本\n"]],["span",{"class":"line","line":5},["span",{"class":"sScJk"},"docker-compose"],["span",{"class":"sZZnC"}," down\n"]],["span",{"class":"line","line":6},["span",{"class":"sScJk"},"git"],["span",{"class":"sZZnC"}," checkout"],["span",{"class":"sZZnC"}," v2.2.0\n"]],["span",{"class":"line","line":7},["span",{"class":"sScJk"},"docker-compose"],["span",{"class":"sZZnC"}," pull\n"]],["span",{"class":"line","line":8},["span",{"class":"sScJk"},"docker-compose"],["span",{"class":"sZZnC"}," up"],["span",{"class":"sj4cs"}," -d\n"]]]],["h3",{"id":"恢复数据库"},"恢复数据库"],["pre",{"className":"language-bash shiki shiki-themes github-light github-dark","code":"# 停止服务\ndocker-compose down\n\n# 删除新数据库\ndocker-compose exec postgres dropdb -U websopy websopy\n\n# 创建空数据库\ndocker-compose exec postgres createdb -U websopy websopy\n\n# 恢复备份\ndocker exec -i $(docker-compose ps -q postgres) psql -U websopy < backups/db_backup_20240115.sql\n\n# 启动服务\ndocker-compose up -d\n","language":"bash","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sJ8bj"},"# 停止服务\n"]],["span",{"class":"line","line":2},["span",{"class":"sScJk"},"docker-compose"],["span",{"class":"sZZnC"}," down\n"]],["span",{"class":"line","line":3},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":4},["span",{"class":"sJ8bj"},"# 删除新数据库\n"]],["span",{"class":"line","line":5},["span",{"class":"sScJk"},"docker-compose"],["span",{"class":"sZZnC"}," exec"],["span",{"class":"sZZnC"}," postgres"],["span",{"class":"sZZnC"}," dropdb"],["span",{"class":"sj4cs"}," -U"],["span",{"class":"sZZnC"}," websopy"],["span",{"class":"sZZnC"}," websopy\n"]],["span",{"class":"line","line":6},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":7},["span",{"class":"sJ8bj"},"# 创建空数据库\n"]],["span",{"class":"line","line":8},["span",{"class":"sScJk"},"docker-compose"],["span",{"class":"sZZnC"}," exec"],["span",{"class":"sZZnC"}," postgres"],["span",{"class":"sZZnC"}," createdb"],["span",{"class":"sj4cs"}," -U"],["span",{"class":"sZZnC"}," websopy"],["span",{"class":"sZZnC"}," websopy\n"]],["span",{"class":"line","line":9},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":10},["span",{"class":"sJ8bj"},"# 恢复备份\n"]],["span",{"class":"line","line":11},["span",{"class":"sScJk"},"docker"],["span",{"class":"sZZnC"}," exec"],["span",{"class":"sj4cs"}," -i"],["span",{"class":"sVt8B"}," $("],["span",{"class":"sScJk"},"docker-compose"],["span",{"class":"sZZnC"}," ps"],["span",{"class":"sj4cs"}," -q"],["span",{"class":"sZZnC"}," postgres"],["span",{"class":"sVt8B"},") "],["span",{"class":"sZZnC"},"psql"],["span",{"class":"sj4cs"}," -U"],["span",{"class":"sZZnC"}," websopy"],["span",{"class":"szBVR"}," <"],["span",{"class":"sZZnC"}," backups/db_backup_20240115.sql\n"]],["span",{"class":"line","line":12},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":13},["span",{"class":"sJ8bj"},"# 启动服务\n"]],["span",{"class":"line","line":14},["span",{"class":"sScJk"},"docker-compose"],["span",{"class":"sZZnC"}," up"],["span",{"class":"sj4cs"}," -d\n"]]]],["h2",{"id":"版本更新日志"},"📊 版本更新日志"],["h3",{"id":"v230最新"},"v2.3.0(最新)"],["p",{},["strong",{},"新增功能:"]],["ul",{},["li",{},"🚀 AI 流式输出优化,延迟降低 50%"],["li",{},"📊 新增数据看板组件"],["li",{},"🔔 支持自定义 Webhook 事件"]],["p",{},["strong",{},"Breaking Changes"]],["ul",{},["li",{},"⚠️ API ",["code",{},"/ai/chat"]," 端点参数变更"],["li",{},"⚠️ 环境变量 ",["code",{},"AI_MODEL"]," 重命名为 ",["code",{},"DEFAULT_MODEL"]]],["h3",{"id":"v220"},"v2.2.0"],["p",{},["strong",{},"新增功能:"]],["ul",{},["li",{},"💬 多语言支持"],["li",{},"📱 移动端优化"],["li",{},"🔐 SSO 单点登录"]],["h3",{"id":"v210"},"v2.1.0"],["p",{},["strong",{},"新增功能:"]],["ul",{},["li",{},"🤖 AI Agent 功能"],["li",{},"📚 RAG 知识库"],["li",{},"⚡ 工作流自动化"]],["h2",{"id":"测试环境验证"},"🧪 测试环境验证"],["h3",{"id":"测试清单"},"测试清单"],["ul",{"className":["contains-task-list"]},["li",{"className":["task-list-item"]},["input",{"disabled":true,"type":"checkbox"}]," 首页访问正常"],["li",{"className":["task-list-item"]},["input",{"disabled":true,"type":"checkbox"}]," 用户登录/注册"],["li",{"className":["task-list-item"]},["input",{"disabled":true,"type":"checkbox"}]," 主要功能操作"],["li",{"className":["task-list-item"]},["input",{"disabled":true,"type":"checkbox"}]," API 接口调用"],["li",{"className":["task-list-item"]},["input",{"disabled":true,"type":"checkbox"}]," Webhook 接收"],["li",{"className":["task-list-item"]},["input",{"disabled":true,"type":"checkbox"}]," 性能无明显下降"]],["h2",{"id":"常见问题"},"❓ 常见问题"],["h3",{"id":"q-迁移失败怎么办"},"Q: 迁移失败怎么办?"],["ol",{},["li",{},"停止所有服务"],["li",{},"恢复数据库备份"],["li",{},"检查迁移脚本错误"],["li",{},"联系技术支持"]],["h3",{"id":"q-镜像拉取失败"},"Q: 镜像拉取失败?"],["pre",{"className":"language-bash shiki shiki-themes github-light github-dark","code":"# 使用国内镜像源\nnano /etc/docker/daemon.json\n","language":"bash","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sJ8bj"},"# 使用国内镜像源\n"]],["span",{"class":"line","line":2},["span",{"class":"sScJk"},"nano"],["span",{"class":"sZZnC"}," /etc/docker/daemon.json\n"]]]],["pre",{"className":"language-json shiki shiki-themes github-light github-dark","code":"{\n \"registry-mirrors\": [\"https://mirror.ccs.tencentyun.com\"]\n}\n","language":"json","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sVt8B"},"{\n"]],["span",{"class":"line","line":2},["span",{"class":"sj4cs"}," \"registry-mirrors\""],["span",{"class":"sVt8B"},": ["],["span",{"class":"sZZnC"},"\"https://mirror.ccs.tencentyun.com\""],["span",{"class":"sVt8B"},"]\n"]],["span",{"class":"line","line":3},["span",{"class":"sVt8B"},"}\n"]]]],["pre",{"className":"language-bash shiki shiki-themes github-light github-dark","code":"sudo systemctl restart docker\ndocker-compose pull\n","language":"bash","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sScJk"},"sudo"],["span",{"class":"sZZnC"}," systemctl"],["span",{"class":"sZZnC"}," restart"],["span",{"class":"sZZnC"}," docker\n"]],["span",{"class":"line","line":2},["span",{"class":"sScJk"},"docker-compose"],["span",{"class":"sZZnC"}," pull\n"]]]],["style",{},"html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}"]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"-升级前必读","depth":2,"text":"⚠️ 升级前必读","children":[{"id":"重要检查清单","depth":3,"text":"重要检查清单"},{"id":"版本兼容性","depth":3,"text":"版本兼容性"}]},{"id":"升级步骤","depth":2,"text":"🚀 升级步骤","children":[{"id":"准备工作","depth":3,"text":"准备工作"},{"id":"执行升级","depth":3,"text":"执行升级"},{"id":"验证升级","depth":3,"text":"验证升级"}]},{"id":"数据库迁移","depth":2,"text":"🔧 数据库迁移","children":[{"id":"手动迁移","depth":3,"text":"手动迁移"}]},{"id":"-紧急回滚","depth":2,"text":"⤵️ 紧急回滚","children":[{"id":"自动回滚","depth":3,"text":"自动回滚"},{"id":"恢复数据库","depth":3,"text":"恢复数据库"}]},{"id":"版本更新日志","depth":2,"text":"📊 版本更新日志","children":[{"id":"v230最新","depth":3,"text":"v2.3.0(最新)"},{"id":"v220","depth":3,"text":"v2.2.0"},{"id":"v210","depth":3,"text":"v2.1.0"}]},{"id":"测试环境验证","depth":2,"text":"🧪 测试环境验证","children":[{"id":"测试清单","depth":3,"text":"测试清单"}]},{"id":"常见问题","depth":2,"text":"❓ 常见问题","children":[{"id":"q-迁移失败怎么办","depth":3,"text":"Q: 迁移失败怎么办?"},{"id":"q-镜像拉取失败","depth":3,"text":"Q: 镜像拉取失败?"}]}]}}', '平滑升级生产环境,数据库迁移方案,紧急回滚操作手册。', 'md', '{"category":"deploy","order":3}', 'true', '/docs/deploy/upgrade', '{"title":"版本升级与回滚","description":"平滑升级生产环境,数据库迁移方案,紧急回滚操作手册。"}', 'docs/deploy/upgrade', '11srh3Gbi3w-1nElqY5llMQiImDxTsYpCUFtqmAQbFA'); -- 11srh3Gbi3w-1nElqY5llMQiImDxTsYpCUFtqmAQbFA
INSERT INTO _content_docs VALUES ('docs/docs/getting-started/apikey.md', 'API Key 创建与管理', '{"type":"minimark","value":[["h1",{"id":"api-key-创建与管理"},"API Key 创建与管理"],["blockquote",{},["p",{},"在控制台创建 API Key了解权限范围与速率限制安全使用建议。"]],["h2",{"id":"什么是-api-key"},"🔑 什么是 API Key"],["p",{},"API Key 是调用 Websopy API 的凭证,类似于「数字身份证」,用于:"],["ul",{},["li",{},"✅ 身份认证 - 证明你是平台用户"],["li",{},"✅ 权限控制 - 控制可以访问哪些资源"],["li",{},"✅ 用量统计 - 记录 API 调用情况"],["li",{},"✅ 计费依据 - 按使用量进行计费"]],["h2",{"id":"创建-api-key"},"📋 创建 API Key"],["h3",{"id":"步骤-1进入控制台"},"步骤 1进入控制台"],["ol",{},["li",{},"登录 ",["a",{"href":"https://console.websopy.com","rel":["nofollow"]},"Websopy 控制台"]],["li",{},"导航到 ",["strong",{},"开发者中心 → API Key"]],["li",{},"点击 ",["strong",{},"创建新 Key"]]],["h3",{"id":"步骤-2配置-key"},"步骤 2配置 Key"],["table",{},["thead",{},["tr",{},["th",{},"配置项"],["th",{},"说明"]]],["tbody",{},["tr",{},["td",{},["strong",{},"名称"]],["td",{},"给 Key 取个易识别的名字,如「生产环境」「测试用」"]],["tr",{},["td",{},["strong",{},"权限范围"]],["td",{},"选择 Key 允许的操作(见下文)"]],["tr",{},["td",{},["strong",{},"有效期"]],["td",{},"设置过期时间(可选)"]],["tr",{},["td",{},["strong",{},"IP 白名单"]],["td",{},"限制只有指定 IP 才能使用(可选)"]]]],["h3",{"id":"步骤-3保存-key"},"步骤 3保存 Key"],["p",{},"⚠️ ",["strong",{},"重要"],"API Key 只显示一次,请立即:"],["ol",{},["li",{},"复制保存到安全位置"],["li",{},"设置环境变量"]],["pre",{"className":"language-bash shiki shiki-themes github-light github-dark","code":"# Linux/macOS\necho ''export WEBSOPY_API_KEY=\"ws_live_xxxxx\"'' >> ~/.bashrc\nsource ~/.bashrc\n\n# Windows PowerShell\n[Environment]::SetEnvironmentVariable(\"WEBSOPY_API_KEY\", \"ws_live_xxxxx\", \"User\")\n","language":"bash","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sJ8bj"},"# Linux/macOS\n"]],["span",{"class":"line","line":2},["span",{"class":"sj4cs"},"echo"],["span",{"class":"sZZnC"}," ''export WEBSOPY_API_KEY=\"ws_live_xxxxx\"''"],["span",{"class":"szBVR"}," >>"],["span",{"class":"sZZnC"}," ~/.bashrc\n"]],["span",{"class":"line","line":3},["span",{"class":"sj4cs"},"source"],["span",{"class":"sZZnC"}," ~/.bashrc\n"]],["span",{"class":"line","line":4},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":5},["span",{"class":"sJ8bj"},"# Windows PowerShell\n"]],["span",{"class":"line","line":6},["span",{"class":"sVt8B"},"[Environment]::SetEnvironmentVariable("],["span",{"class":"sScJk"},"\"WEBSOPY_API_KEY\""],["span",{"class":"sScJk"},","],["span",{"class":"sZZnC"}," \"ws_live_xxxxx\","],["span",{"class":"sZZnC"}," \"User\""],["span",{"class":"sVt8B"},")\n"]]]],["h2",{"id":"-权限范围"},"🛡️ 权限范围"],["h3",{"id":"可用权限"},"可用权限"],["table",{},["thead",{},["tr",{},["th",{},"权限"],["th",{},"说明"],["th",{},"适用场景"]]],["tbody",{},["tr",{},["td",{},["code",{},"user:read"]],["td",{},"读取用户信息"],["td",{},"数据展示"]],["tr",{},["td",{},["code",{},"user:write"]],["td",{},"修改用户信息"],["td",{},"用户管理"]],["tr",{},["td",{},["code",{},"project:read"]],["td",{},"读取项目"],["td",{},"数据展示"]],["tr",{},["td",{},["code",{},"project:write"]],["td",{},"创建/修改/删除项目"],["td",{},"项目管理"]],["tr",{},["td",{},["code",{},"storage:read"]],["td",{},"读取文件"],["td",{},"文件读取"]],["tr",{},["td",{},["code",{},"storage:write"]],["td",{},"上传/删除文件"],["td",{},"文件管理"]],["tr",{},["td",{},["code",{},"ai:agent"]],["td",{},"使用 AI 智能体"],["td",{},"AI 功能"]],["tr",{},["td",{},["code",{},"ai:knowledge"]],["td",{},"管理知识库"],["td",{},"知识库管理"]],["tr",{},["td",{},["code",{},"payment:read"]],["td",{},"读取账单"],["td",{},"账单查看"]],["tr",{},["td",{},["code",{},"admin:*"]],["td",{},"所有权限"],["td",{},"⚠️ 仅管理员"]]]],["h3",{"id":"权限组合"},"权限组合"],["p",{},"推荐按最小权限原则配置:"],["pre",{"className":"language-json shiki shiki-themes github-light github-dark","code":"// 只读权限(安全)\n{\n \"permissions\": [\"user:read\", \"project:read\", \"storage:read\"]\n}\n\n// 读写权限(一般开发)\n{\n \"permissions\": [\"user:read\", \"user:write\", \"project:*\", \"storage:*\"]\n}\n\n// AI 功能\n{\n \"permissions\": [\"ai:agent\", \"ai:knowledge\"]\n}\n","language":"json","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sJ8bj"},"// 只读权限(安全)\n"]],["span",{"class":"line","line":2},["span",{"class":"sVt8B"},"{\n"]],["span",{"class":"line","line":3},["span",{"class":"sj4cs"}," \"permissions\""],["span",{"class":"sVt8B"},": ["],["span",{"class":"sZZnC"},"\"user:read\""],["span",{"class":"sVt8B"},", "],["span",{"class":"sZZnC"},"\"project:read\""],["span",{"class":"sVt8B"},", "],["span",{"class":"sZZnC"},"\"storage:read\""],["span",{"class":"sVt8B"},"]\n"]],["span",{"class":"line","line":4},["span",{"class":"sVt8B"},"}\n"]],["span",{"class":"line","line":5},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":6},["span",{"class":"sJ8bj"},"// 读写权限(一般开发)\n"]],["span",{"class":"line","line":7},["span",{"class":"sVt8B"},"{\n"]],["span",{"class":"line","line":8},["span",{"class":"sj4cs"}," \"permissions\""],["span",{"class":"sVt8B"},": ["],["span",{"class":"sZZnC"},"\"user:read\""],["span",{"class":"sVt8B"},", "],["span",{"class":"sZZnC"},"\"user:write\""],["span",{"class":"sVt8B"},", "],["span",{"class":"sZZnC"},"\"project:*\""],["span",{"class":"sVt8B"},", "],["span",{"class":"sZZnC"},"\"storage:*\""],["span",{"class":"sVt8B"},"]\n"]],["span",{"class":"line","line":9},["span",{"class":"sVt8B"},"}\n"]],["span",{"class":"line","line":10},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":11},["span",{"class":"sJ8bj"},"// AI 功能\n"]],["span",{"class":"line","line":12},["span",{"class":"sVt8B"},"{\n"]],["span",{"class":"line","line":13},["span",{"class":"sj4cs"}," \"permissions\""],["span",{"class":"sVt8B"},": ["],["span",{"class":"sZZnC"},"\"ai:agent\""],["span",{"class":"sVt8B"},", "],["span",{"class":"sZZnC"},"\"ai:knowledge\""],["span",{"class":"sVt8B"},"]\n"]],["span",{"class":"line","line":14},["span",{"class":"sVt8B"},"}\n"]]]],["h2",{"id":"ip-白名单"},"🚫 IP 白名单"],["p",{},"增强安全性,限制只有指定 IP 可以使用 Key"],["ol",{},["li",{},"创建/编辑 Key 时开启「IP 白名单」"],["li",{},"添加允许的 IP 地址或 CIDR 范围"]],["pre",{"className":["language-text"],"code":"# 支持的格式\n203.0.113.1 # 单个 IP\n203.0.113.0/24 # IP 段\n203.0.113.1,198.51.100.0/24 # 多个,用逗号分隔\n","language":"text","meta":""},["code",{"__ignoreMap":""},"# 支持的格式\n203.0.113.1 # 单个 IP\n203.0.113.0/24 # IP 段\n203.0.113.1,198.51.100.0/24 # 多个,用逗号分隔\n"]],["h2",{"id":"-速率限制"},"⏱️ 速率限制"],["table",{},["thead",{},["tr",{},["th",{},"套餐"],["th",{},"请求限制"]]],["tbody",{},["tr",{},["td",{},"免费版"],["td",{},"100 次/分钟"]],["tr",{},["td",{},"专业版"],["td",{},"1,000 次/分钟"]],["tr",{},["td",{},"企业版"],["td",{},"10,000 次/分钟"]]]],["h3",{"id":"查看当前用量"},"查看当前用量"],["pre",{"className":"language-typescript shiki shiki-themes github-light github-dark","code":"const client = new WebsopyClient({\n apiKey: process.env.WEBSOPY_API_KEY\n})\n\n// 获取当前配额\nconst quota = await client.account.getQuota()\nconsole.log(''今日剩余:'', quota.remaining)\nconsole.log(''重置时间:'', quota.resetAt)\n","language":"typescript","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"szBVR"},"const"],["span",{"class":"sj4cs"}," client"],["span",{"class":"szBVR"}," ="],["span",{"class":"szBVR"}," new"],["span",{"class":"sScJk"}," WebsopyClient"],["span",{"class":"sVt8B"},"({\n"]],["span",{"class":"line","line":2},["span",{"class":"sVt8B"}," apiKey: process.env."],["span",{"class":"sj4cs"},"WEBSOPY_API_KEY\n"]],["span",{"class":"line","line":3},["span",{"class":"sVt8B"},"})\n"]],["span",{"class":"line","line":4},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":5},["span",{"class":"sJ8bj"},"// 获取当前配额\n"]],["span",{"class":"line","line":6},["span",{"class":"szBVR"},"const"],["span",{"class":"sj4cs"}," quota"],["span",{"class":"szBVR"}," ="],["span",{"class":"szBVR"}," await"],["span",{"class":"sVt8B"}," client.account."],["span",{"class":"sScJk"},"getQuota"],["span",{"class":"sVt8B"},"()\n"]],["span",{"class":"line","line":7},["span",{"class":"sVt8B"},"console."],["span",{"class":"sScJk"},"log"],["span",{"class":"sVt8B"},"("],["span",{"class":"sZZnC"},"''今日剩余:''"],["span",{"class":"sVt8B"},", quota.remaining)\n"]],["span",{"class":"line","line":8},["span",{"class":"sVt8B"},"console."],["span",{"class":"sScJk"},"log"],["span",{"class":"sVt8B"},"("],["span",{"class":"sZZnC"},"''重置时间:''"],["span",{"class":"sVt8B"},", quota.resetAt)\n"]]]],["h3",{"id":"处理限流"},"处理限流"],["pre",{"className":"language-typescript shiki shiki-themes github-light github-dark","code":"async function callWithRetry(fn, maxRetries = 3) {\n for (let i = 0; i < maxRetries; i++) {\n try {\n return await fn()\n } catch (error) {\n if (error.code === ''RATE_LIMIT_EXCEEDED'') {\n // 等待后重试\n await sleep(error.retryAfter * 1000)\n continue\n }\n throw error\n }\n }\n}\n\nfunction sleep(ms) {\n return new Promise(resolve => setTimeout(resolve, ms))\n}\n","language":"typescript","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"szBVR"},"async"],["span",{"class":"szBVR"}," function"],["span",{"class":"sScJk"}," callWithRetry"],["span",{"class":"sVt8B"},"("],["span",{"class":"s4XuR"},"fn"],["span",{"class":"sVt8B"},", "],["span",{"class":"s4XuR"},"maxRetries"],["span",{"class":"szBVR"}," ="],["span",{"class":"sj4cs"}," 3"],["span",{"class":"sVt8B"},") {\n"]],["span",{"class":"line","line":2},["span",{"class":"szBVR"}," for"],["span",{"class":"sVt8B"}," ("],["span",{"class":"szBVR"},"let"],["span",{"class":"sVt8B"}," i "],["span",{"class":"szBVR"},"="],["span",{"class":"sj4cs"}," 0"],["span",{"class":"sVt8B"},"; i "],["span",{"class":"szBVR"},"<"],["span",{"class":"sVt8B"}," maxRetries; i"],["span",{"class":"szBVR"},"++"],["span",{"class":"sVt8B"},") {\n"]],["span",{"class":"line","line":3},["span",{"class":"szBVR"}," try"],["span",{"class":"sVt8B"}," {\n"]],["span",{"class":"line","line":4},["span",{"class":"szBVR"}," return"],["span",{"class":"szBVR"}," await"],["span",{"class":"sScJk"}," fn"],["span",{"class":"sVt8B"},"()\n"]],["span",{"class":"line","line":5},["span",{"class":"sVt8B"}," } "],["span",{"class":"szBVR"},"catch"],["span",{"class":"sVt8B"}," (error) {\n"]],["span",{"class":"line","line":6},["span",{"class":"szBVR"}," if"],["span",{"class":"sVt8B"}," (error.code "],["span",{"class":"szBVR"},"==="],["span",{"class":"sZZnC"}," ''RATE_LIMIT_EXCEEDED''"],["span",{"class":"sVt8B"},") {\n"]],["span",{"class":"line","line":7},["span",{"class":"sJ8bj"}," // 等待后重试\n"]],["span",{"class":"line","line":8},["span",{"class":"szBVR"}," await"],["span",{"class":"sScJk"}," sleep"],["span",{"class":"sVt8B"},"(error.retryAfter "],["span",{"class":"szBVR"},"*"],["span",{"class":"sj4cs"}," 1000"],["span",{"class":"sVt8B"},")\n"]],["span",{"class":"line","line":9},["span",{"class":"szBVR"}," continue\n"]],["span",{"class":"line","line":10},["span",{"class":"sVt8B"}," }\n"]],["span",{"class":"line","line":11},["span",{"class":"szBVR"}," throw"],["span",{"class":"sVt8B"}," error\n"]],["span",{"class":"line","line":12},["span",{"class":"sVt8B"}," }\n"]],["span",{"class":"line","line":13},["span",{"class":"sVt8B"}," }\n"]],["span",{"class":"line","line":14},["span",{"class":"sVt8B"},"}\n"]],["span",{"class":"line","line":15},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":16},["span",{"class":"szBVR"},"function"],["span",{"class":"sScJk"}," sleep"],["span",{"class":"sVt8B"},"("],["span",{"class":"s4XuR"},"ms"],["span",{"class":"sVt8B"},") {\n"]],["span",{"class":"line","line":17},["span",{"class":"szBVR"}," return"],["span",{"class":"szBVR"}," new"],["span",{"class":"sj4cs"}," Promise"],["span",{"class":"sVt8B"},"("],["span",{"class":"s4XuR"},"resolve"],["span",{"class":"szBVR"}," =>"],["span",{"class":"sScJk"}," setTimeout"],["span",{"class":"sVt8B"},"(resolve, ms))\n"]],["span",{"class":"line","line":18},["span",{"class":"sVt8B"},"}\n"]]]],["h2",{"id":"安全最佳实践"},"🔐 安全最佳实践"],["h3",{"id":"推荐做法"},"✅ 推荐做法"],["pre",{"className":"language-typescript shiki shiki-themes github-light github-dark","code":"// 1. 使用环境变量,不硬编码\nconst client = new WebsopyClient({\n apiKey: process.env.WEBSOPY_API_KEY // ✅ 正确\n})\n\n// ❌ 危险:硬编码在代码中\nconst client = new WebsopyClient({\n apiKey: ''ws_live_xxxxx'' // ❌ 危险\n})\n","language":"typescript","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sJ8bj"},"// 1. 使用环境变量,不硬编码\n"]],["span",{"class":"line","line":2},["span",{"class":"szBVR"},"const"],["span",{"class":"sj4cs"}," client"],["span",{"class":"szBVR"}," ="],["span",{"class":"szBVR"}," new"],["span",{"class":"sScJk"}," WebsopyClient"],["span",{"class":"sVt8B"},"({\n"]],["span",{"class":"line","line":3},["span",{"class":"sVt8B"}," apiKey: process.env."],["span",{"class":"sj4cs"},"WEBSOPY_API_KEY"],["span",{"class":"sJ8bj"}," // ✅ 正确\n"]],["span",{"class":"line","line":4},["span",{"class":"sVt8B"},"})\n"]],["span",{"class":"line","line":5},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":6},["span",{"class":"sJ8bj"},"// ❌ 危险:硬编码在代码中\n"]],["span",{"class":"line","line":7},["span",{"class":"szBVR"},"const"],["span",{"class":"sj4cs"}," client"],["span",{"class":"szBVR"}," ="],["span",{"class":"szBVR"}," new"],["span",{"class":"sScJk"}," WebsopyClient"],["span",{"class":"sVt8B"},"({\n"]],["span",{"class":"line","line":8},["span",{"class":"sVt8B"}," apiKey: "],["span",{"class":"sZZnC"},"''ws_live_xxxxx''"],["span",{"class":"sJ8bj"}," // ❌ 危险\n"]],["span",{"class":"line","line":9},["span",{"class":"sVt8B"},"})\n"]]]],["pre",{"className":"language-typescript shiki shiki-themes github-light github-dark","code":"// 2. 区分不同环境的 Key\nconst client = new WebsopyClient({\n apiKey: process.env.NODE_ENV === ''production'' \n ? process.env.WEBSOPY_API_KEY_PROD \n : process.env.WEBSOPY_API_KEY_DEV\n})\n","language":"typescript","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sJ8bj"},"// 2. 区分不同环境的 Key\n"]],["span",{"class":"line","line":2},["span",{"class":"szBVR"},"const"],["span",{"class":"sj4cs"}," client"],["span",{"class":"szBVR"}," ="],["span",{"class":"szBVR"}," new"],["span",{"class":"sScJk"}," WebsopyClient"],["span",{"class":"sVt8B"},"({\n"]],["span",{"class":"line","line":3},["span",{"class":"sVt8B"}," apiKey: process.env."],["span",{"class":"sj4cs"},"NODE_ENV"],["span",{"class":"szBVR"}," ==="],["span",{"class":"sZZnC"}," ''production''"],["span",{"class":"sVt8B"}," \n"]],["span",{"class":"line","line":4},["span",{"class":"szBVR"}," ?"],["span",{"class":"sVt8B"}," process.env."],["span",{"class":"sj4cs"},"WEBSOPY_API_KEY_PROD"],["span",{"class":"sVt8B"}," \n"]],["span",{"class":"line","line":5},["span",{"class":"szBVR"}," :"],["span",{"class":"sVt8B"}," process.env."],["span",{"class":"sj4cs"},"WEBSOPY_API_KEY_DEV\n"]],["span",{"class":"line","line":6},["span",{"class":"sVt8B"},"})\n"]]]],["pre",{"className":"language-typescript shiki shiki-themes github-light github-dark","code":"// 3. 前端使用受限 Key\nconst client = new WebsopyClient({\n apiKey: process.env.WEBSOPY_API_KEY_PUBLIC,\n // 前端 Key 应该只开只读权限\n allowedMethods: [''user.getProfile'', ''project.list'']\n})\n","language":"typescript","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sJ8bj"},"// 3. 前端使用受限 Key\n"]],["span",{"class":"line","line":2},["span",{"class":"szBVR"},"const"],["span",{"class":"sj4cs"}," client"],["span",{"class":"szBVR"}," ="],["span",{"class":"szBVR"}," new"],["span",{"class":"sScJk"}," WebsopyClient"],["span",{"class":"sVt8B"},"({\n"]],["span",{"class":"line","line":3},["span",{"class":"sVt8B"}," apiKey: process.env."],["span",{"class":"sj4cs"},"WEBSOPY_API_KEY_PUBLIC"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":4},["span",{"class":"sJ8bj"}," // 前端 Key 应该只开只读权限\n"]],["span",{"class":"line","line":5},["span",{"class":"sVt8B"}," allowedMethods: ["],["span",{"class":"sZZnC"},"''user.getProfile''"],["span",{"class":"sVt8B"},", "],["span",{"class":"sZZnC"},"''project.list''"],["span",{"class":"sVt8B"},"]\n"]],["span",{"class":"line","line":6},["span",{"class":"sVt8B"},"})\n"]]]],["h3",{"id":"避免事项"},"❌ 避免事项"],["ol",{},["li",{},["strong",{},"不要"],"将 Key 提交到代码仓库"],["li",{},["strong",{},"不要"],"在前端暴露有写权限的 Key"],["li",{},["strong",{},"不要"],"使用同一个 Key 处理所有业务"],["li",{},["strong",{},"不要"],"通过 URL 参数传递 Key"]],["pre",{"className":"language-gitignore shiki shiki-themes github-light github-dark","code":"# .gitignore\n.env\n.env.*\n*.local\n","language":"gitignore","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{},"# .gitignore\n"]],["span",{"class":"line","line":2},["span",{},".env\n"]],["span",{"class":"line","line":3},["span",{},".env.*\n"]],["span",{"class":"line","line":4},["span",{},"*.local\n"]]]],["h2",{"id":"key-轮换"},"🔄 Key 轮换"],["p",{},"定期更换 API Key 是个好习惯:"],["ol",{},["li",{},"在控制台创建新 Key"],["li",{},"更新所有使用旧 Key 的地方"],["li",{},"验证新 Key 正常工作"],["li",{},"禁用或删除旧 Key"]],["h2",{"id":"审计日志"},"📊 审计日志"],["p",{},"在控制台查看 API Key 的使用记录:"],["ul",{},["li",{},"调用时间、频率"],["li",{},"调用的接口"],["li",{},"请求来源 IP"],["li",{},"错误情况"]],["style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}"]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"什么是-api-key","depth":2,"text":"🔑 什么是 API Key"},{"id":"创建-api-key","depth":2,"text":"📋 创建 API Key","children":[{"id":"步骤-1进入控制台","depth":3,"text":"步骤 1进入控制台"},{"id":"步骤-2配置-key","depth":3,"text":"步骤 2配置 Key"},{"id":"步骤-3保存-key","depth":3,"text":"步骤 3保存 Key"}]},{"id":"-权限范围","depth":2,"text":"🛡️ 权限范围","children":[{"id":"可用权限","depth":3,"text":"可用权限"},{"id":"权限组合","depth":3,"text":"权限组合"}]},{"id":"ip-白名单","depth":2,"text":"🚫 IP 白名单"},{"id":"-速率限制","depth":2,"text":"⏱️ 速率限制","children":[{"id":"查看当前用量","depth":3,"text":"查看当前用量"},{"id":"处理限流","depth":3,"text":"处理限流"}]},{"id":"安全最佳实践","depth":2,"text":"🔐 安全最佳实践","children":[{"id":"推荐做法","depth":3,"text":"✅ 推荐做法"},{"id":"避免事项","depth":3,"text":"❌ 避免事项"}]},{"id":"key-轮换","depth":2,"text":"🔄 Key 轮换"},{"id":"审计日志","depth":2,"text":"📊 审计日志"}]}}', '在控制台创建 API Key了解权限范围与速率限制安全使用建议。', 'md', '{"category":"getting-started","order":3}', 'true', '/docs/getting-started/apikey', '{"title":"API Key 创建与管理","description":"在控制台创建 API Key了解权限范围与速率限制安全使用建议。"}', 'docs/getting-started/apikey', 'fQFIkHHXSPhhlV3j4D80tdOAwNTjeCDNIiP8ku6c2Dc'); -- fQFIkHHXSPhhlV3j4D80tdOAwNTjeCDNIiP8ku6c2Dc
INSERT INTO _content_docs VALUES ('docs/docs/getting-started/quickstart.md', '5 分钟快速上手', '{"type":"minimark","value":[["h1",{"id":"_5-分钟快速上手"},"5 分钟快速上手"],["blockquote",{},["p",{},"本教程将带你完成 Websopy SDK 的安装、配置,并发送你的第一个 API 请求。"]],["h2",{"id":"前提条件"},"📋 前提条件"],["ul",{},["li",{},"Node.js 16.x 或更高版本"],["li",{},"npm 8.x 或 yarn 1.22+"],["li",{},"一个 Websopy 账户(",["a",{"href":"https://websopy.com/register","rel":["nofollow"]},"立即注册"],""]],["h2",{"id":"开始"},"🚀 开始"],["h3",{"id":"第一步安装-sdk"},"第一步:安装 SDK"],["pre",{"className":"language-bash shiki shiki-themes github-light github-dark","code":"# 使用 npm\nnpm install @websopy/sdk\n\n# 或使用 yarn\nyarn add @websopy/sdk\n\n# 或使用 pnpm\npnpm add @websopy/sdk\n","language":"bash","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sJ8bj"},"# 使用 npm\n"]],["span",{"class":"line","line":2},["span",{"class":"sScJk"},"npm"],["span",{"class":"sZZnC"}," install"],["span",{"class":"sZZnC"}," @websopy/sdk\n"]],["span",{"class":"line","line":3},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":4},["span",{"class":"sJ8bj"},"# 或使用 yarn\n"]],["span",{"class":"line","line":5},["span",{"class":"sScJk"},"yarn"],["span",{"class":"sZZnC"}," add"],["span",{"class":"sZZnC"}," @websopy/sdk\n"]],["span",{"class":"line","line":6},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":7},["span",{"class":"sJ8bj"},"# 或使用 pnpm\n"]],["span",{"class":"line","line":8},["span",{"class":"sScJk"},"pnpm"],["span",{"class":"sZZnC"}," add"],["span",{"class":"sZZnC"}," @websopy/sdk\n"]]]],["h3",{"id":"第二步获取-api-key"},"第二步:获取 API Key"],["ol",{},["li",{},"登录 ",["a",{"href":"https://console.websopy.com","rel":["nofollow"]},"Websopy 控制台"]],["li",{},"进入 ",["strong",{},"开发者中心 → API Key"]],["li",{},"点击 ",["strong",{},"创建新 Key"]],["li",{},"选择权限范围(建议先选择「只读」权限测试)"],["li",{},"复制生成的 Key注意Key 只显示一次,请妥善保存)"]],["h3",{"id":"第三步初始化客户端"},"第三步:初始化客户端"],["pre",{"className":"language-typescript shiki shiki-themes github-light github-dark","code":"import { WebsopyClient } from ''@websopy/sdk''\n\nconst client = new WebsopyClient({\n apiKey: ''your-api-key-here'',\n // 可选:指定 API 端点\n baseUrl: ''https://api.websopy.com/v1''\n})\n","language":"typescript","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"szBVR"},"import"],["span",{"class":"sVt8B"}," { WebsopyClient } "],["span",{"class":"szBVR"},"from"],["span",{"class":"sZZnC"}," ''@websopy/sdk''\n"]],["span",{"class":"line","line":2},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":3},["span",{"class":"szBVR"},"const"],["span",{"class":"sj4cs"}," client"],["span",{"class":"szBVR"}," ="],["span",{"class":"szBVR"}," new"],["span",{"class":"sScJk"}," WebsopyClient"],["span",{"class":"sVt8B"},"({\n"]],["span",{"class":"line","line":4},["span",{"class":"sVt8B"}," apiKey: "],["span",{"class":"sZZnC"},"''your-api-key-here''"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":5},["span",{"class":"sJ8bj"}," // 可选:指定 API 端点\n"]],["span",{"class":"line","line":6},["span",{"class":"sVt8B"}," baseUrl: "],["span",{"class":"sZZnC"},"''https://api.websopy.com/v1''\n"]],["span",{"class":"line","line":7},["span",{"class":"sVt8B"},"})\n"]]]],["h3",{"id":"第四步发送第一个请求"},"第四步:发送第一个请求"],["pre",{"className":"language-typescript shiki shiki-themes github-light github-dark","code":"async function main() {\n try {\n // 获取用户信息\n const user = await client.user.getProfile()\n console.log(''当前用户:'', user.name)\n \n // 创建第一个项目\n const project = await client.project.create({\n name: ''我的第一个项目'',\n description: ''通过 API 创建''\n })\n console.log(''项目创建成功:'', project.id)\n \n // 获取项目列表\n const projects = await client.project.list()\n console.log(''项目总数:'', projects.total)\n } catch (error) {\n console.error(''请求失败:'', error.message)\n }\n}\n\nmain()\n","language":"typescript","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"szBVR"},"async"],["span",{"class":"szBVR"}," function"],["span",{"class":"sScJk"}," main"],["span",{"class":"sVt8B"},"() {\n"]],["span",{"class":"line","line":2},["span",{"class":"szBVR"}," try"],["span",{"class":"sVt8B"}," {\n"]],["span",{"class":"line","line":3},["span",{"class":"sJ8bj"}," // 获取用户信息\n"]],["span",{"class":"line","line":4},["span",{"class":"szBVR"}," const"],["span",{"class":"sj4cs"}," user"],["span",{"class":"szBVR"}," ="],["span",{"class":"szBVR"}," await"],["span",{"class":"sVt8B"}," client.user."],["span",{"class":"sScJk"},"getProfile"],["span",{"class":"sVt8B"},"()\n"]],["span",{"class":"line","line":5},["span",{"class":"sVt8B"}," console."],["span",{"class":"sScJk"},"log"],["span",{"class":"sVt8B"},"("],["span",{"class":"sZZnC"},"''当前用户:''"],["span",{"class":"sVt8B"},", user.name)\n"]],["span",{"class":"line","line":6},["span",{"class":"sVt8B"}," \n"]],["span",{"class":"line","line":7},["span",{"class":"sJ8bj"}," // 创建第一个项目\n"]],["span",{"class":"line","line":8},["span",{"class":"szBVR"}," const"],["span",{"class":"sj4cs"}," project"],["span",{"class":"szBVR"}," ="],["span",{"class":"szBVR"}," await"],["span",{"class":"sVt8B"}," client.project."],["span",{"class":"sScJk"},"create"],["span",{"class":"sVt8B"},"({\n"]],["span",{"class":"line","line":9},["span",{"class":"sVt8B"}," name: "],["span",{"class":"sZZnC"},"''我的第一个项目''"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":10},["span",{"class":"sVt8B"}," description: "],["span",{"class":"sZZnC"},"''通过 API 创建''\n"]],["span",{"class":"line","line":11},["span",{"class":"sVt8B"}," })\n"]],["span",{"class":"line","line":12},["span",{"class":"sVt8B"}," console."],["span",{"class":"sScJk"},"log"],["span",{"class":"sVt8B"},"("],["span",{"class":"sZZnC"},"''项目创建成功:''"],["span",{"class":"sVt8B"},", project.id)\n"]],["span",{"class":"line","line":13},["span",{"class":"sVt8B"}," \n"]],["span",{"class":"line","line":14},["span",{"class":"sJ8bj"}," // 获取项目列表\n"]],["span",{"class":"line","line":15},["span",{"class":"szBVR"}," const"],["span",{"class":"sj4cs"}," projects"],["span",{"class":"szBVR"}," ="],["span",{"class":"szBVR"}," await"],["span",{"class":"sVt8B"}," client.project."],["span",{"class":"sScJk"},"list"],["span",{"class":"sVt8B"},"()\n"]],["span",{"class":"line","line":16},["span",{"class":"sVt8B"}," console."],["span",{"class":"sScJk"},"log"],["span",{"class":"sVt8B"},"("],["span",{"class":"sZZnC"},"''项目总数:''"],["span",{"class":"sVt8B"},", projects.total)\n"]],["span",{"class":"line","line":17},["span",{"class":"sVt8B"}," } "],["span",{"class":"szBVR"},"catch"],["span",{"class":"sVt8B"}," (error) {\n"]],["span",{"class":"line","line":18},["span",{"class":"sVt8B"}," console."],["span",{"class":"sScJk"},"error"],["span",{"class":"sVt8B"},"("],["span",{"class":"sZZnC"},"''请求失败:''"],["span",{"class":"sVt8B"},", error.message)\n"]],["span",{"class":"line","line":19},["span",{"class":"sVt8B"}," }\n"]],["span",{"class":"line","line":20},["span",{"class":"sVt8B"},"}\n"]],["span",{"class":"line","line":21},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":22},["span",{"class":"sScJk"},"main"],["span",{"class":"sVt8B"},"()\n"]]]],["h3",{"id":"第五步运行代码"},"第五步:运行代码"],["pre",{"className":"language-bash shiki shiki-themes github-light github-dark","code":"npx ts-node your-script.ts\n# 或\nnode your-script.js\n","language":"bash","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sScJk"},"npx"],["span",{"class":"sZZnC"}," ts-node"],["span",{"class":"sZZnC"}," your-script.ts\n"]],["span",{"class":"line","line":2},["span",{"class":"sJ8bj"},"# 或\n"]],["span",{"class":"line","line":3},["span",{"class":"sScJk"},"node"],["span",{"class":"sZZnC"}," your-script.js\n"]]]],["p",{},["strong",{},"预期输出:"]],["pre",{"className":["language-text"],"code":"当前用户: 张三\n项目创建成功: proj_abc123xyz\n项目总数: 5\n","language":"text"},["code",{"__ignoreMap":""},"当前用户: 张三\n项目创建成功: proj_abc123xyz\n项目总数: 5\n"]],["h2",{"id":"恭喜"},"🎉 恭喜!"],["p",{},"你已经成功发送了第一个 API 请求。接下来你可以:"],["ul",{},["li",{},"📖 继续阅读 ",["a",{"href":"/developer/docs/getting-started/apikey"},"API Key 创建与管理"]],["li",{},"🔌 查看 ",["a",{"href":"/developer/docs/api/rest-api"},"REST API 完整参考"]],["li",{},"🤖 尝试 ",["a",{"href":"/developer/docs/ai/agent"},"AI 智能体接入"]]],["h2",{"id":"-常见问题"},"⚠️ 常见问题"],["h3",{"id":"q-报-invalid-api-key-错误"},"Q: 报 \"Invalid API Key\" 错误?"],["p",{},"检查以下几点:"],["ol",{},["li",{},"API Key 是否正确复制(不要有空格)"],["li",{},"Key 是否已过期或被禁用"],["li",{},"Key 的权限范围是否包含当前操作"]],["h3",{"id":"q-报-rate-limit-exceeded-错误"},"Q: 报 \"Rate Limit Exceeded\" 错误?"],["p",{},"免费账户默认 100 次/分钟。如需更高配额,在控制台升级套餐。"],["h3",{"id":"q-如何开启调试模式"},"Q: 如何开启调试模式?"],["pre",{"className":"language-typescript shiki shiki-themes github-light github-dark","code":"const client = new WebsopyClient({\n apiKey: ''your-api-key'',\n debug: true // 打印详细请求日志\n})\n","language":"typescript","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"szBVR"},"const"],["span",{"class":"sj4cs"}," client"],["span",{"class":"szBVR"}," ="],["span",{"class":"szBVR"}," new"],["span",{"class":"sScJk"}," WebsopyClient"],["span",{"class":"sVt8B"},"({\n"]],["span",{"class":"line","line":2},["span",{"class":"sVt8B"}," apiKey: "],["span",{"class":"sZZnC"},"''your-api-key''"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":3},["span",{"class":"sVt8B"}," debug: "],["span",{"class":"sj4cs"},"true"],["span",{"class":"sJ8bj"}," // 打印详细请求日志\n"]],["span",{"class":"line","line":4},["span",{"class":"sVt8B"},"})\n"]]]],["h2",{"id":"相关资源"},"📚 相关资源"],["ul",{},["li",{},["a",{"href":"https://github.com/websopy/sdk","rel":["nofollow"]},"SDK 源码仓库"]],["li",{},["a",{"href":"https://github.com/websopy/examples","rel":["nofollow"]},"示例代码集合"]],["li",{},["a",{"href":"https://status.websopy.com","rel":["nofollow"]},"API 状态页"]]],["style",{},"html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}"]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"前提条件","depth":2,"text":"📋 前提条件"},{"id":"开始","depth":2,"text":"🚀 开始","children":[{"id":"第一步安装-sdk","depth":3,"text":"第一步:安装 SDK"},{"id":"第二步获取-api-key","depth":3,"text":"第二步:获取 API Key"},{"id":"第三步初始化客户端","depth":3,"text":"第三步:初始化客户端"},{"id":"第四步发送第一个请求","depth":3,"text":"第四步:发送第一个请求"},{"id":"第五步运行代码","depth":3,"text":"第五步:运行代码"}]},{"id":"恭喜","depth":2,"text":"🎉 恭喜!"},{"id":"-常见问题","depth":2,"text":"⚠️ 常见问题","children":[{"id":"q-报-invalid-api-key-错误","depth":3,"text":"Q: 报 \"Invalid API Key\" 错误?"},{"id":"q-报-rate-limit-exceeded-错误","depth":3,"text":"Q: 报 \"Rate Limit Exceeded\" 错误?"},{"id":"q-如何开启调试模式","depth":3,"text":"Q: 如何开启调试模式?"}]},{"id":"相关资源","depth":2,"text":"📚 相关资源"}]}}', '安装 Websopy SDK、配置客户端并发送你的第一个 API 请求。', 'md', '{"category":"getting-started","order":1}', 'true', '/docs/getting-started/quickstart', '{"title":"5 分钟快速上手","description":"安装 Websopy SDK、配置客户端并发送你的第一个 API 请求。"}', 'docs/getting-started/quickstart', '4575Hr8iOEk8iSu56Q0rFEwsSUvUlE6sWzPVgMB-77A'); -- 4575Hr8iOEk8iSu56Q0rFEwsSUvUlE6sWzPVgMB-77A
INSERT INTO _content_docs VALUES ('docs/docs/getting-started/sdk-installation.md', '安装 SDK 与初始化', '{"type":"minimark","value":[["h1",{"id":"安装-sdk-与初始化"},"安装 SDK 与初始化"],["blockquote",{},["p",{},"详细指南:安装 @websopy/sdk配置 WebsopyClient发送第一个 API 请求。"]],["h2",{"id":"sdk-概述"},"📦 SDK 概述"],["p",{},"Websopy 提供多种语言的 SDK"],["table",{},["thead",{},["tr",{},["th",{},"语言"],["th",{},"SDK"],["th",{},"源码"]]],["tbody",{},["tr",{},["td",{},"JavaScript/TypeScript"],["td",{},["code",{},"@websopy/sdk"]],["td",{},["a",{"href":"https://github.com/websopy/sdk-js","rel":["nofollow"]},"GitHub"]]],["tr",{},["td",{},"Python"],["td",{},["code",{},"websopy-sdk"]],["td",{},["a",{"href":"https://github.com/websopy/sdk-python","rel":["nofollow"]},"GitHub"]]],["tr",{},["td",{},"Go"],["td",{},["code",{},"github.com/websopy/sdk-go"]],["td",{},["a",{"href":"https://github.com/websopy/sdk-go","rel":["nofollow"]},"GitHub"]]],["tr",{},["td",{},"Java"],["td",{},["code",{},"com.websopy:sdk"]],["td",{},["a",{"href":"https://github.com/websopy/sdk-java","rel":["nofollow"]},"GitHub"]]]]],["p",{},"本教程以 JavaScript/TypeScript 为例。"],["h2",{"id":"安装"},"🚀 安装"],["h3",{"id":"npm"},"npm"],["pre",{"className":"language-bash shiki shiki-themes github-light github-dark","code":"npm install @websopy/sdk\n","language":"bash","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sScJk"},"npm"],["span",{"class":"sZZnC"}," install"],["span",{"class":"sZZnC"}," @websopy/sdk\n"]]]],["h3",{"id":"yarn"},"yarn"],["pre",{"className":"language-bash shiki shiki-themes github-light github-dark","code":"yarn add @websopy/sdk\n","language":"bash","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sScJk"},"yarn"],["span",{"class":"sZZnC"}," add"],["span",{"class":"sZZnC"}," @websopy/sdk\n"]]]],["h3",{"id":"pnpm"},"pnpm"],["pre",{"className":"language-bash shiki shiki-themes github-light github-dark","code":"pnpm add @websopy/sdk\n","language":"bash","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sScJk"},"pnpm"],["span",{"class":"sZZnC"}," add"],["span",{"class":"sZZnC"}," @websopy/sdk\n"]]]],["h3",{"id":"cdn浏览器端"},"CDN浏览器端"],["pre",{"className":"language-html shiki shiki-themes github-light github-dark","code":"<script src=\"https://unpkg.com/@websopy/sdk/dist/websopy.min.js\"></script>\n","language":"html","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sVt8B"},"<"],["span",{"class":"s9eBZ"},"script"],["span",{"class":"sScJk"}," src"],["span",{"class":"sVt8B"},"="],["span",{"class":"sZZnC"},"\"https://unpkg.com/@websopy/sdk/dist/websopy.min.js\""],["span",{"class":"sVt8B"},"></"],["span",{"class":"s9eBZ"},"script"],["span",{"class":"sVt8B"},">\n"]]]],["h2",{"id":"-初始化配置"},"⚙️ 初始化配置"],["h3",{"id":"基本配置"},"基本配置"],["pre",{"className":"language-typescript shiki shiki-themes github-light github-dark","code":"import { WebsopyClient } from ''@websopy/sdk''\n\nconst client = new WebsopyClient({\n apiKey: ''ws_live_xxxxxxxxxxxx'',\n // API 版本(可选,默认 v1\n version: ''v1'',\n // 超时时间(毫秒)\n timeout: 30000,\n // 重试次数\n retries: 3\n})\n","language":"typescript","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"szBVR"},"import"],["span",{"class":"sVt8B"}," { WebsopyClient } "],["span",{"class":"szBVR"},"from"],["span",{"class":"sZZnC"}," ''@websopy/sdk''\n"]],["span",{"class":"line","line":2},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":3},["span",{"class":"szBVR"},"const"],["span",{"class":"sj4cs"}," client"],["span",{"class":"szBVR"}," ="],["span",{"class":"szBVR"}," new"],["span",{"class":"sScJk"}," WebsopyClient"],["span",{"class":"sVt8B"},"({\n"]],["span",{"class":"line","line":4},["span",{"class":"sVt8B"}," apiKey: "],["span",{"class":"sZZnC"},"''ws_live_xxxxxxxxxxxx''"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":5},["span",{"class":"sJ8bj"}," // API 版本(可选,默认 v1\n"]],["span",{"class":"line","line":6},["span",{"class":"sVt8B"}," version: "],["span",{"class":"sZZnC"},"''v1''"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":7},["span",{"class":"sJ8bj"}," // 超时时间(毫秒)\n"]],["span",{"class":"line","line":8},["span",{"class":"sVt8B"}," timeout: "],["span",{"class":"sj4cs"},"30000"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":9},["span",{"class":"sJ8bj"}," // 重试次数\n"]],["span",{"class":"line","line":10},["span",{"class":"sVt8B"}," retries: "],["span",{"class":"sj4cs"},"3\n"]],["span",{"class":"line","line":11},["span",{"class":"sVt8B"},"})\n"]]]],["h3",{"id":"多环境配置"},"多环境配置"],["pre",{"className":"language-typescript shiki shiki-themes github-light github-dark","code":"const config = {\n // 开发环境\n dev: {\n apiKey: ''ws_test_xxxxx'',\n baseUrl: ''https://api-dev.websopy.com/v1''\n },\n // 生产环境\n prod: {\n apiKey: process.env.WEBSOPY_API_KEY,\n baseUrl: ''https://api.websopy.com/v1''\n }\n}\n\nconst client = new WebsopyClient(\n process.env.NODE_ENV === ''production'' ? config.prod : config.dev\n)\n","language":"typescript","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"szBVR"},"const"],["span",{"class":"sj4cs"}," config"],["span",{"class":"szBVR"}," ="],["span",{"class":"sVt8B"}," {\n"]],["span",{"class":"line","line":2},["span",{"class":"sJ8bj"}," // 开发环境\n"]],["span",{"class":"line","line":3},["span",{"class":"sVt8B"}," dev: {\n"]],["span",{"class":"line","line":4},["span",{"class":"sVt8B"}," apiKey: "],["span",{"class":"sZZnC"},"''ws_test_xxxxx''"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":5},["span",{"class":"sVt8B"}," baseUrl: "],["span",{"class":"sZZnC"},"''https://api-dev.websopy.com/v1''\n"]],["span",{"class":"line","line":6},["span",{"class":"sVt8B"}," },\n"]],["span",{"class":"line","line":7},["span",{"class":"sJ8bj"}," // 生产环境\n"]],["span",{"class":"line","line":8},["span",{"class":"sVt8B"}," prod: {\n"]],["span",{"class":"line","line":9},["span",{"class":"sVt8B"}," apiKey: process.env."],["span",{"class":"sj4cs"},"WEBSOPY_API_KEY"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":10},["span",{"class":"sVt8B"}," baseUrl: "],["span",{"class":"sZZnC"},"''https://api.websopy.com/v1''\n"]],["span",{"class":"line","line":11},["span",{"class":"sVt8B"}," }\n"]],["span",{"class":"line","line":12},["span",{"class":"sVt8B"},"}\n"]],["span",{"class":"line","line":13},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":14},["span",{"class":"szBVR"},"const"],["span",{"class":"sj4cs"}," client"],["span",{"class":"szBVR"}," ="],["span",{"class":"szBVR"}," new"],["span",{"class":"sScJk"}," WebsopyClient"],["span",{"class":"sVt8B"},"(\n"]],["span",{"class":"line","line":15},["span",{"class":"sVt8B"}," process.env."],["span",{"class":"sj4cs"},"NODE_ENV"],["span",{"class":"szBVR"}," ==="],["span",{"class":"sZZnC"}," ''production''"],["span",{"class":"szBVR"}," ?"],["span",{"class":"sVt8B"}," config.prod "],["span",{"class":"szBVR"},":"],["span",{"class":"sVt8B"}," config.dev\n"]],["span",{"class":"line","line":16},["span",{"class":"sVt8B"},")\n"]]]],["h3",{"id":"环境变量"},"环境变量"],["p",{},"创建 ",["code",{},".env"]," 文件:"],["pre",{"className":"language-env shiki shiki-themes github-light github-dark","code":"WEBSOPY_API_KEY=ws_live_xxxxxxxxxxxx\nWEBSOPY_BASE_URL=https://api.websopy.com/v1\nWEBSOPY_TIMEOUT=30000\n","language":"env","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{},"WEBSOPY_API_KEY=ws_live_xxxxxxxxxxxx\n"]],["span",{"class":"line","line":2},["span",{},"WEBSOPY_BASE_URL=https://api.websopy.com/v1\n"]],["span",{"class":"line","line":3},["span",{},"WEBSOPY_TIMEOUT=30000\n"]]]],["pre",{"className":"language-typescript shiki shiki-themes github-light github-dark","code":"import ''dotenv/config''\nimport { WebsopyClient } from ''@websopy/sdk''\n\nconst client = new WebsopyClient({\n apiKey: process.env.WEBSOPY_API_KEY,\n baseUrl: process.env.WEBSOPY_BASE_URL\n})\n","language":"typescript","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"szBVR"},"import"],["span",{"class":"sZZnC"}," ''dotenv/config''\n"]],["span",{"class":"line","line":2},["span",{"class":"szBVR"},"import"],["span",{"class":"sVt8B"}," { WebsopyClient } "],["span",{"class":"szBVR"},"from"],["span",{"class":"sZZnC"}," ''@websopy/sdk''\n"]],["span",{"class":"line","line":3},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":4},["span",{"class":"szBVR"},"const"],["span",{"class":"sj4cs"}," client"],["span",{"class":"szBVR"}," ="],["span",{"class":"szBVR"}," new"],["span",{"class":"sScJk"}," WebsopyClient"],["span",{"class":"sVt8B"},"({\n"]],["span",{"class":"line","line":5},["span",{"class":"sVt8B"}," apiKey: process.env."],["span",{"class":"sj4cs"},"WEBSOPY_API_KEY"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":6},["span",{"class":"sVt8B"}," baseUrl: process.env."],["span",{"class":"sj4cs"},"WEBSOPY_BASE_URL\n"]],["span",{"class":"line","line":7},["span",{"class":"sVt8B"},"})\n"]]]],["h2",{"id":"api-模块"},"📚 API 模块"],["p",{},"SDK 按功能模块组织:"],["pre",{"className":"language-typescript shiki shiki-themes github-light github-dark","code":"// 用户管理\nclient.user\n\n// 项目管理\nclient.project\n\n// 文件存储\nclient.storage\n\n// AI 功能\nclient.ai\n\n// 支付功能\nclient.payment\n\n// Webhook\nclient.webhook\n","language":"typescript","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sJ8bj"},"// 用户管理\n"]],["span",{"class":"line","line":2},["span",{"class":"sVt8B"},"client.user\n"]],["span",{"class":"line","line":3},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":4},["span",{"class":"sJ8bj"},"// 项目管理\n"]],["span",{"class":"line","line":5},["span",{"class":"sVt8B"},"client.project\n"]],["span",{"class":"line","line":6},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":7},["span",{"class":"sJ8bj"},"// 文件存储\n"]],["span",{"class":"line","line":8},["span",{"class":"sVt8B"},"client.storage\n"]],["span",{"class":"line","line":9},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":10},["span",{"class":"sJ8bj"},"// AI 功能\n"]],["span",{"class":"line","line":11},["span",{"class":"sVt8B"},"client.ai\n"]],["span",{"class":"line","line":12},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":13},["span",{"class":"sJ8bj"},"// 支付功能\n"]],["span",{"class":"line","line":14},["span",{"class":"sVt8B"},"client.payment\n"]],["span",{"class":"line","line":15},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":16},["span",{"class":"sJ8bj"},"// Webhook\n"]],["span",{"class":"line","line":17},["span",{"class":"sVt8B"},"client.webhook\n"]]]],["h2",{"id":"完整示例"},"🧪 完整示例"],["pre",{"className":"language-typescript shiki shiki-themes github-light github-dark","code":"import { WebsopyClient } from ''@websopy/sdk''\n\nasync function demo() {\n const client = new WebsopyClient({\n apiKey: process.env.WEBSOPY_API_KEY\n })\n\n // 1. 获取用户信息\n const user = await client.user.getProfile()\n console.log(''用户:'', user.name)\n\n // 2. 列出项目\n const { items: projects } = await client.project.list({\n limit: 10,\n status: ''active''\n })\n\n // 3. 创建项目\n const project = await client.project.create({\n name: ''新项目'',\n description: ''通过 SDK 创建''\n })\n\n // 4. 上传文件\n const file = await client.storage.upload({\n file: ''./demo.pdf'',\n folder: ''documents''\n })\n\n console.log(''文件上传成功:'', file.url)\n}\n\ndemo().catch(console.error)\n","language":"typescript","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"szBVR"},"import"],["span",{"class":"sVt8B"}," { WebsopyClient } "],["span",{"class":"szBVR"},"from"],["span",{"class":"sZZnC"}," ''@websopy/sdk''\n"]],["span",{"class":"line","line":2},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":3},["span",{"class":"szBVR"},"async"],["span",{"class":"szBVR"}," function"],["span",{"class":"sScJk"}," demo"],["span",{"class":"sVt8B"},"() {\n"]],["span",{"class":"line","line":4},["span",{"class":"szBVR"}," const"],["span",{"class":"sj4cs"}," client"],["span",{"class":"szBVR"}," ="],["span",{"class":"szBVR"}," new"],["span",{"class":"sScJk"}," WebsopyClient"],["span",{"class":"sVt8B"},"({\n"]],["span",{"class":"line","line":5},["span",{"class":"sVt8B"}," apiKey: process.env."],["span",{"class":"sj4cs"},"WEBSOPY_API_KEY\n"]],["span",{"class":"line","line":6},["span",{"class":"sVt8B"}," })\n"]],["span",{"class":"line","line":7},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":8},["span",{"class":"sJ8bj"}," // 1. 获取用户信息\n"]],["span",{"class":"line","line":9},["span",{"class":"szBVR"}," const"],["span",{"class":"sj4cs"}," user"],["span",{"class":"szBVR"}," ="],["span",{"class":"szBVR"}," await"],["span",{"class":"sVt8B"}," client.user."],["span",{"class":"sScJk"},"getProfile"],["span",{"class":"sVt8B"},"()\n"]],["span",{"class":"line","line":10},["span",{"class":"sVt8B"}," console."],["span",{"class":"sScJk"},"log"],["span",{"class":"sVt8B"},"("],["span",{"class":"sZZnC"},"''用户:''"],["span",{"class":"sVt8B"},", user.name)\n"]],["span",{"class":"line","line":11},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":12},["span",{"class":"sJ8bj"}," // 2. 列出项目\n"]],["span",{"class":"line","line":13},["span",{"class":"szBVR"}," const"],["span",{"class":"sVt8B"}," { "],["span",{"class":"s4XuR"},"items"],["span",{"class":"sVt8B"},": "],["span",{"class":"sj4cs"},"projects"],["span",{"class":"sVt8B"}," } "],["span",{"class":"szBVR"},"="],["span",{"class":"szBVR"}," await"],["span",{"class":"sVt8B"}," client.project."],["span",{"class":"sScJk"},"list"],["span",{"class":"sVt8B"},"({\n"]],["span",{"class":"line","line":14},["span",{"class":"sVt8B"}," limit: "],["span",{"class":"sj4cs"},"10"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":15},["span",{"class":"sVt8B"}," status: "],["span",{"class":"sZZnC"},"''active''\n"]],["span",{"class":"line","line":16},["span",{"class":"sVt8B"}," })\n"]],["span",{"class":"line","line":17},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":18},["span",{"class":"sJ8bj"}," // 3. 创建项目\n"]],["span",{"class":"line","line":19},["span",{"class":"szBVR"}," const"],["span",{"class":"sj4cs"}," project"],["span",{"class":"szBVR"}," ="],["span",{"class":"szBVR"}," await"],["span",{"class":"sVt8B"}," client.project."],["span",{"class":"sScJk"},"create"],["span",{"class":"sVt8B"},"({\n"]],["span",{"class":"line","line":20},["span",{"class":"sVt8B"}," name: "],["span",{"class":"sZZnC"},"''新项目''"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":21},["span",{"class":"sVt8B"}," description: "],["span",{"class":"sZZnC"},"''通过 SDK 创建''\n"]],["span",{"class":"line","line":22},["span",{"class":"sVt8B"}," })\n"]],["span",{"class":"line","line":23},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":24},["span",{"class":"sJ8bj"}," // 4. 上传文件\n"]],["span",{"class":"line","line":25},["span",{"class":"szBVR"}," const"],["span",{"class":"sj4cs"}," file"],["span",{"class":"szBVR"}," ="],["span",{"class":"szBVR"}," await"],["span",{"class":"sVt8B"}," client.storage."],["span",{"class":"sScJk"},"upload"],["span",{"class":"sVt8B"},"({\n"]],["span",{"class":"line","line":26},["span",{"class":"sVt8B"}," file: "],["span",{"class":"sZZnC"},"''./demo.pdf''"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":27},["span",{"class":"sVt8B"}," folder: "],["span",{"class":"sZZnC"},"''documents''\n"]],["span",{"class":"line","line":28},["span",{"class":"sVt8B"}," })\n"]],["span",{"class":"line","line":29},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":30},["span",{"class":"sVt8B"}," console."],["span",{"class":"sScJk"},"log"],["span",{"class":"sVt8B"},"("],["span",{"class":"sZZnC"},"''文件上传成功:''"],["span",{"class":"sVt8B"},", file.url)\n"]],["span",{"class":"line","line":31},["span",{"class":"sVt8B"},"}\n"]],["span",{"class":"line","line":32},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":33},["span",{"class":"sScJk"},"demo"],["span",{"class":"sVt8B"},"()."],["span",{"class":"sScJk"},"catch"],["span",{"class":"sVt8B"},"(console.error)\n"]]]],["h2",{"id":"typescript-类型"},"🔧 TypeScript 类型"],["p",{},"SDK 提供完整的 TypeScript 类型定义:"],["pre",{"className":"language-typescript shiki shiki-themes github-light github-dark","code":"import type { \n Project, \n User, \n CreateProjectOptions \n} from ''@websopy/sdk/types''\n\nfunction createProject(options: CreateProjectOptions): Promise<Project> {\n return client.project.create(options)\n}\n","language":"typescript","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"szBVR"},"import"],["span",{"class":"szBVR"}," type"],["span",{"class":"sVt8B"}," { \n"]],["span",{"class":"line","line":2},["span",{"class":"sVt8B"}," Project, \n"]],["span",{"class":"line","line":3},["span",{"class":"sVt8B"}," User, \n"]],["span",{"class":"line","line":4},["span",{"class":"sVt8B"}," CreateProjectOptions \n"]],["span",{"class":"line","line":5},["span",{"class":"sVt8B"},"} "],["span",{"class":"szBVR"},"from"],["span",{"class":"sZZnC"}," ''@websopy/sdk/types''\n"]],["span",{"class":"line","line":6},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":7},["span",{"class":"szBVR"},"function"],["span",{"class":"sScJk"}," createProject"],["span",{"class":"sVt8B"},"("],["span",{"class":"s4XuR"},"options"],["span",{"class":"szBVR"},":"],["span",{"class":"sScJk"}," CreateProjectOptions"],["span",{"class":"sVt8B"},")"],["span",{"class":"szBVR"},":"],["span",{"class":"sScJk"}," Promise"],["span",{"class":"sVt8B"},"<"],["span",{"class":"sScJk"},"Project"],["span",{"class":"sVt8B"},"> {\n"]],["span",{"class":"line","line":8},["span",{"class":"szBVR"}," return"],["span",{"class":"sVt8B"}," client.project."],["span",{"class":"sScJk"},"create"],["span",{"class":"sVt8B"},"(options)\n"]],["span",{"class":"line","line":9},["span",{"class":"sVt8B"},"}\n"]]]],["h2",{"id":"常见问题"},"❓ 常见问题"],["h3",{"id":"q-esm-和-commonjs-兼容"},"Q: ESM 和 CommonJS 兼容?"],["p",{},"是的SDK 同时支持两种模块格式:"],["pre",{"className":"language-typescript shiki shiki-themes github-light github-dark","code":"// ESM\nimport { WebsopyClient } from ''@websopy/sdk''\n\n// CommonJS\nconst { WebsopyClient } = require(''@websopy/sdk'')\n","language":"typescript","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sJ8bj"},"// ESM\n"]],["span",{"class":"line","line":2},["span",{"class":"szBVR"},"import"],["span",{"class":"sVt8B"}," { WebsopyClient } "],["span",{"class":"szBVR"},"from"],["span",{"class":"sZZnC"}," ''@websopy/sdk''\n"]],["span",{"class":"line","line":3},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":4},["span",{"class":"sJ8bj"},"// CommonJS\n"]],["span",{"class":"line","line":5},["span",{"class":"szBVR"},"const"],["span",{"class":"sVt8B"}," { "],["span",{"class":"sj4cs"},"WebsopyClient"],["span",{"class":"sVt8B"}," } "],["span",{"class":"szBVR"},"="],["span",{"class":"sScJk"}," require"],["span",{"class":"sVt8B"},"("],["span",{"class":"sZZnC"},"''@websopy/sdk''"],["span",{"class":"sVt8B"},")\n"]]]],["h3",{"id":"q-如何调试"},"Q: 如何调试?"],["pre",{"className":"language-typescript shiki shiki-themes github-light github-dark","code":"const client = new WebsopyClient({\n apiKey: process.env.WEBSOPY_API_KEY,\n debug: true // 打印详细日志\n})\n","language":"typescript","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"szBVR"},"const"],["span",{"class":"sj4cs"}," client"],["span",{"class":"szBVR"}," ="],["span",{"class":"szBVR"}," new"],["span",{"class":"sScJk"}," WebsopyClient"],["span",{"class":"sVt8B"},"({\n"]],["span",{"class":"line","line":2},["span",{"class":"sVt8B"}," apiKey: process.env."],["span",{"class":"sj4cs"},"WEBSOPY_API_KEY"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":3},["span",{"class":"sVt8B"}," debug: "],["span",{"class":"sj4cs"},"true"],["span",{"class":"sJ8bj"}," // 打印详细日志\n"]],["span",{"class":"line","line":4},["span",{"class":"sVt8B"},"})\n"]]]],["style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}"]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"sdk-概述","depth":2,"text":"📦 SDK 概述"},{"id":"安装","depth":2,"text":"🚀 安装","children":[{"id":"npm","depth":3,"text":"npm"},{"id":"yarn","depth":3,"text":"yarn"},{"id":"pnpm","depth":3,"text":"pnpm"},{"id":"cdn浏览器端","depth":3,"text":"CDN浏览器端"}]},{"id":"-初始化配置","depth":2,"text":"⚙️ 初始化配置","children":[{"id":"基本配置","depth":3,"text":"基本配置"},{"id":"多环境配置","depth":3,"text":"多环境配置"},{"id":"环境变量","depth":3,"text":"环境变量"}]},{"id":"api-模块","depth":2,"text":"📚 API 模块"},{"id":"完整示例","depth":2,"text":"🧪 完整示例"},{"id":"typescript-类型","depth":2,"text":"🔧 TypeScript 类型"},{"id":"常见问题","depth":2,"text":"❓ 常见问题","children":[{"id":"q-esm-和-commonjs-兼容","depth":3,"text":"Q: ESM 和 CommonJS 兼容?"},{"id":"q-如何调试","depth":3,"text":"Q: 如何调试?"}]}]}}', '详细指南:安装 @websopy/sdk配置 WebsopyClient发送第一个 API 请求。', 'md', '{"category":"getting-started","order":2}', 'true', '/docs/getting-started/sdk-installation', '{"title":"安装 SDK 与初始化","description":"详细指南:安装 @websopy/sdk配置 WebsopyClient发送第一个 API 请求。"}', 'docs/getting-started/sdk-installation', 'EKNThPWC-_GFUSshnSWFUOfjbjixZ-uyiP-PhVgh7Q8'); -- EKNThPWC-_GFUSshnSWFUOfjbjixZ-uyiP-PhVgh7Q8
INSERT INTO _content_docs VALUES ('docs/docs/index.md', 'Websopy 开发文档', '{"type":"minimark","value":[["h1",{"id":"websopy-开发文档"},"📚 Websopy 开发文档"],["blockquote",{},["p",{},"欢迎来到 Websopy 开发者文档中心。在这里,你可以找到从快速上手到高级功能的所有开发资源。"]],["h2",{"id":"快速开始"},"🚀 快速开始"],["p",{},"新用户推荐从这里开始5 分钟内体验平台核心功能。"],["ul",{},["li",{},["a",{"href":"/developer/docs/getting-started/quickstart"},"5 分钟快速上手"]," — 安装 SDK、获取 API Key、发送第一个请求"],["li",{},["a",{"href":"/developer/docs/getting-started/sdk-installation"},"安装 SDK 与初始化"]," — 多语言 SDK 安装与配置"],["li",{},["a",{"href":"/developer/docs/getting-started/apikey"},"API Key 创建与管理"]," — 创建、配置与安全最佳实践"]],["h2",{"id":"api-参考"},"🔌 API 参考"],["p",{},"学习如何调用平台 API掌握数据交互。"],["ul",{},["li",{},["a",{"href":"/developer/docs/api/rest-api"},"REST API 完整参考"]," — 200+ 标准接口文档"],["li",{},["a",{"href":"/developer/docs/api/streaming"},"流式输出SSE接入"]," — AI 流式响应实现"],["li",{},["a",{"href":"/developer/docs/api/webhook"},"Webhook 事件接入"]," — 异步通知与回调处理"]],["h2",{"id":"ai-功能"},"🤖 AI 功能"],["p",{},"集成 AI 能力,构建智能应用。"],["ul",{},["li",{},["a",{"href":"/developer/docs/ai/agent"},"AI 智能体接入"]," — 知识库问答与多模型切换"],["li",{},["a",{"href":"/developer/docs/ai/rag"},"RAG 知识库搭建"]," — 企业级知识库问答系统"],["li",{},["a",{"href":"/developer/docs/ai/workflow"},"AI 工作流配置"]," — 定时任务与自动化业务流"]],["h2",{"id":"部署运维"},"🚢 部署运维"],["p",{},"私有化部署、升级与运维指南。"],["ul",{},["li",{},["a",{"href":"/developer/docs/deploy/docker"},"Docker Compose 部署"]," — 一键部署全套服务"],["li",{},["a",{"href":"/developer/docs/deploy/private-deploy"},"私有化部署完全指南"]," — HTTPS 配置与备份策略"],["li",{},["a",{"href":"/developer/docs/deploy/upgrade"},"版本升级与回滚"]," — 平滑升级与紧急回滚"]]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"快速开始","depth":2,"text":"🚀 快速开始"},{"id":"api-参考","depth":2,"text":"🔌 API 参考"},{"id":"ai-功能","depth":2,"text":"🤖 AI 功能"},{"id":"部署运维","depth":2,"text":"🚢 部署运维"}]}}', '从快速上手到深度定制,全面的开发指引与 API 参考。', 'md', '{}', 'true', '/docs', '{"title":"Websopy 开发文档","description":"从快速上手到深度定制,全面的开发指引与 API 参考。"}', 'docs/index', 'qEoSynz5hB-SQGtmZjVElCwLL5C7cF4uMYesuclKZW4'); -- qEoSynz5hB-SQGtmZjVElCwLL5C7cF4uMYesuclKZW4
UPDATE _content_info SET ready = true WHERE id = 'checksum_docs'; -- meta