# 腾讯云开发 CloudBase - 一站式后端云服务 > 腾讯云开发(Tencent CloudBase)是云端一体化的后端云服务 ,采用 serverless 架构,免去了移动应用构建中繁琐的服务器搭建和运维。同时云开发提供的静态托管、命令行工具(CLI)、Flutter SDK 等能力极大的降低了应用开发的门槛。使用云开发可以快速构建完整的小程序/小游戏、H5、Web、移动 App 等应用。 This file contains all documentation content in a single document following the llmtxt.org standard. ## 更新日志 # 更新日志 --- ## **[1.13.0] - 2025/05/16** --- ### ✨ **核心功能升级** **Agent UI 全平台语音能力增强** - 支持 4 种场景化音色切换(聊天/阅读/咨询/通用) - 新增静音模式播放支持 - 小程序&低码组件开放语音倍速调节 - 优化双标题显示逻辑(隐藏内容区冗余标题) - 解决图文混排抖动问题 **Agent UI Web 组件能力扩展** - 新增语音播放功能 - 支持地图/天气等三类工具卡片 - 修复若干交互问题 ### 🌐 **扩展开放能力** **MCP Server 模板扩充** - 腾讯混元 3D MCP:支持文本/图片生成 3D 模型(MAX/FBX/GLB 格式) - MarkItDown 服务 MCP:实现任意文件 →Markdown 格式转换 - CRIC 物业 AI MCP:对接物业行业专属智能助理能力 **函数型 Agent 扩充** - LKE 函数型 Agent 模板:支持对接大模型知识引擎 --- 🚧 **新能力预告** - Agent 界面支持用户自主切换模型 - 知识库检索效果优化及多格式文件兼容 - 公众号/服务号/微信客服对接函数型 Agent 能力 - Agent 支持对接更多第三方 Agent 开发平台 - 支持一键将 OpenAPI 转换为 MCP - 提供连接第三方知识库检索、Agent 平台的 MCP 功能将分批次上线,具体排期请留意版本更新通知。 ## **[1.12.0] - 2025/04/29** --- ### ✨ **核心功能升级** **Agent 支持语音输入/输出能力** 为 Agent 原生集成语音输入/输出能力,开发者可快速构建多模态交互场景: **Agent 支持多会话能力** 支持同一 Agent 实例同时处理多个独立会话,各会话维护独立历史 **Agent UI 小程序组件支持工具卡片** Agent UI 小程序源码支持 ToolCard 工具卡片,支持灵活自定义 MCP 的显示效果 可实现商品推荐或者地图导航等自定义业务逻辑 --- ### ⚙️ **开发者体验改进** **文件上传组件安全升级** 由于微信小程序基础库安全策略升级,文件上传功能解析流程可能受到影响,请开发者进行 Agent UI 组件升级 - 小程序源码组件,请更新替换至最新版本 - 微搭低码组件,请新建页面然后重新拖动更新 agent-ui 区块,完成后发布应用 --- 🚧 **新能力预告** - Agent 界面支持用户自主切换模型 - 知识库检索效果优化及多格式文件兼容 - 公众号/服务号/微信客服对接函数型 Agent 能力 - Agent 支持对接更多第三方 Agent 开发平台 - 支持一键将 OpenAPI 转换为 MCP - 提供连接第三方知识库检索、Agent 平台的 MCP 功能将分批次上线,具体排期请留意版本更新通知。 ## **[1.11.0] - 2025/04/17** ### ✨ **核心功能升级** - 支持零门槛 MCP Server 云端托管 全面支持 Java/Python/GoLang/PHP 等主流语言编写的 MCP Server,无框架侵入性改造 本地 MCP Server 可无缝迁移至云开发托管,自动获得安全可靠的远程 MCP 服务。 - 云开发 MCP 市场提供[标准化上架流程](https://docs.cloudbase.net/ai/mcp/develop/publish) ### 🌐 **扩展开放能力** - 云开发 MCP 市场正式上线 云开发提供一站式 MCP Server 开发与托管平台,支持快速发布、部署 MCP Server 新增 30+ 标准化服务模块,覆盖主流开发场景: | 领域 | 代表性服务模块 | | -------------- | --------------------------------------------------------------------------- | | AI 增强 | 云开发 AI 能力 / 记忆模块 / 元器插件 / Puppeteer 自动化 | | 数据服务 | MongoDB/MySQL/Postgres/Redis 数据库接入 / COS 文件与数据处理 | | 开发者工具 | Github/Gitee/Gitlab 代码管理 / Figma 设计协同 / Apifox 接口调试 | | 地图与生活服务 | 腾讯位置服务 / 高德地图 / 彩云天气 / ALAPI 短网址与数据热榜 | | 生产力工具 | Notion 知识库 / QuickChart 可视化 / Mermaid 图表渲染 / Zapier 万用工作流 | | 云原生基建 | 云开发环境管理 / Lighthouse 云服务器 / CNB 云原生构建 / Trends Hub 热点分析 | --- 🚧 **新能力预告** - Agent 支持会话功能 - Agent 语音输入与输出功能开放 - Agent 界面支持用户自主切换模型 - 知识库检索效果优化及多格式文件兼容 - 公众号/服务号/微信客服对接函数型 Agent 能力 - Agent 支持对接更多第三方 Agent 开发平台 - 支持一键将 OpenAPI 转换为 MCP - 提供连接第三方知识库检索、Agent 平台的 MCP 功能将分批次上线,具体排期请留意版本更新通知。 ## **[1.10.0] - 2025/03/28** ### ✨ **核心功能升级: 全面支持 MCP** - **Agent 支持 MCP 协议** Agent 中可以添加 MCP Server, AI 可以根据任务需要自动选择工具,通过多次调用工具完成复杂操作 - **云开发支持开发和托管 MCP 服务** 提供从开发到部署的一站式服务,可在云开发平台托管和搭建自己的 MCP 服务 **提供 6 个内置 MCP Server 模板** - 云开发 AI 能力:通过 MCP 协议提供云开发 AI 原子能力,例如知识库检索、数据库查询、大模型调用、联网搜索、图片解析等 - 元器插件: 提供腾讯元器官方 19 个插件内置调用,支持生成图片,生成音频,搜狗搜索等能力 - 元器 Agent: 将腾讯元器 Agent 转为 MCP 插件来使用,支持对接个人的公众号文章(元器 Agent 内置一亿 token) - 记忆模块:基于云开发数据库+知识图谱的记忆模块,可以为大模型提供记忆,支持存储用户级别的信息 - Puppeteer :可以控制 Chrome 浏览器进行操作 - 空白模板: 开发者可快速实现自己的 MCP Server,让 Agent 连接自有的数据和功能 - **Agent UI 组件升级** - 小程序 Agent 支持共享云开发环境调用 - 新增 MCP 工具调用过程的状态显示 --- ### 🚧 **新能力预告** - 快速导入开源的 MCP Server - Agent 支持会话功能 - Agent 语音输入与输出功能开放 - Agent 界面支持用户自主切换模型 - 知识库检索效果优化及多格式文件兼容 - 公众号/服务号/微信客服对接函数型 Agent 能力 **具体上线时间请关注后续通知** --- ## **[1.9.0] - 2025/03/21** ### ✨ **核心功能升级** - **Agent 支持图片上传解析与问答** 新增支持在对话中上传图片进行解析并生成 AI 回答,提升多媒体交互能力。 - **Agent 支持多知识库选择** 支持在对话中选择 3 个知识库进行综合检索,增强回答的准确性和信息覆盖范围。 --- ### ⚙️ **系统改进** - **知识库上传和管理功能升级** 支持拖拽文件上传,操作更便捷 支持批量上传最多 200 个文件 新增批量删除文件功能,提升管理效率 - **错误处理与提示优化** 加强错误信息提示,针对 Token 到期、服务超限等情况提供明确指引 识别企业微信环境并展示适配性提示 - **对话处理逻辑增强** 优化微信公众平台对话逻辑,修复可能重复回复同一问题的异常 重构文件内容解析接口,解决复杂文件解析超时问题 --- ### 🌐 **扩展开放能力** - **开放知识库检索 API** 开发者可通过 API key 调用知识库向量检索服务,实现自定义业务场景集成 接口文档地址:http://docs.cloudbase.net/http-api/knowledge/search --- ### 🚧 **新能力预告** - Agent 自主调用外部工具来实现复杂业务逻辑 - Agent 支持会话功能 - Agent 语音输入与输出功能开放 - Agent 界面支持用户自主切换模型 - 知识库检索效果优化及多格式文件兼容 - 公众号/服务号/微信客服对接函数型 Agent 能力 **功能将分批次上线,具体排期请留意版本更新通知。** --- ## **[1.8.0] - 2025/03/14** ### ✨ **核心功能升级** - **Agent 支持对接云开发数据模型** 新增支持对接云开发数据模型,实现通过自然语言查询结构化数据并生成 AI 回答。 - **Agent UI 功能优化,正式开源** - 历史记录新增文件上传状态展示,提升操作可追溯性 - 可视化 Agent UI 区块支持小程序端上传文件对话功能 - 小程序 Agent UI 组件正式开源 - Github 仓库:[https://github.com/TencentCloudBase/cloudbase-agent-ui](https://github.com/TencentCloudBase/cloudbase-agent-ui) - Gitee 仓库:[https://gitee.com/TencentCloudBase/cloudbase-agent-ui](https://gitee.com/TencentCloudBase/cloudbase-agent-ui) --- ### ⚙️ **系统改进** - **微信开发者工具 IDE 的集成云开发拓展能力** 开发者可在微信 IDE 中通过云开发 - 拓展功能,查看 AI+ 用量统计和开发 Agent - **大模型用量统计功能上线** 可通过 开发平台-套餐用量-资源仪表盘 查看具体 token 用量 - **Agent 上传文件支持管控开关** 由于对话时上传文件会带来额外大模型 token 消耗,Agent 中新增了文件上传管控开关,仅支持入门版及以上套餐可开启,后续大模型资源包上线后,会向个人版开放此能 - **对话处理逻辑优化** - 微信端对话内容自动去除首尾空白字符 - 云端历史记录查询范围优化为最近 1 天,提升对话上下文的关联性 --- ### 🌐 **扩展开放能力** - **函数型 Agent 开发增强** 支持通过环境变量动态配置运行参数,默认资源配置优化至 0.5c1g - **新增腾讯元器函数型 Agent 模板** 支持通过函数型 Agent 来快速对接腾讯元器上的 Agent,开源地址: https://github.com/TencentCloudBase/cloudbase-examples/tree/master/cloudrunfunctions/yuanqi-agent --- ### 🚧 **新能力预告** - Agent 自主调用外部工具来实现复杂业务逻辑 - Agent 支持对话界面图片上传 - Agent 支持会话功能 - Agent 语音输入与输出功能开放 - Agent 界面支持用户自主切换模型 - Agent 支持对接多个知识库 - 知识库检索效果优化及多格式文件兼容 - 公众号/服务号/微信客服对接函数型 Agent 能力 **功能将分批次上线,具体排期请留意版本更新通知。** --- ## **[1.7.0] - 2025/03/07** --- ### ✨ **核心功能升级** - **Agent UI 文档上下文支持上传文件** 新增支持用户在对话中上传文档作为对话上下文(本期覆盖平台:小程序源码组件及可视化搭建的 Web 应用,可视化构建的小程序适配开发中),扩展多模态交互场景。 - **云开发环境资源共享** 支持同主体共享云开发环境调用 AI 及相关资源 - **小程序 Agent UI 组件体验优化** 支持选中复制文本,支持输入框随文本高度动态变化,开放更多组件属性配置 --- ### 🌐 **扩展开放能力** - **函数型 Agent 提供标准接口文档** 函数型 Agent 框架提供了 IBot 接口,开发者只要实现一个满足 IBot 的类,就可以部署起相应的 Agent,具体可参考文档[](https://docs.cloudbase.net/ai/cbrf-agent/IBot) - **Agent API 开放调用** 开发者可通过 API Key 调用 Agent 接口,实现自动化集成与第三方服务对接。 - **自定义 UI 输出解决方案** 新增 Agent 返回自定义 UI 结构的能力,开发者可通过[文档指南](https://docs.cloudbase.net/ai/agent/custom-output)快速实现个性化交互设计。 --- ### ⚙️ **系统改进** - **Agent 对话效果优化** 提升联网搜索结果精准度,优化设定信息的权重分配策略,增强上下文理解与回答相关性。 - **错误提示与流程优化** 优化 Agent 搭建过程中的体验 --- ### 🚧 **新能力预告** - 对接云开发数据库作为结构化数据来源,支持对话中直接引用 - Agent 支持对话界面图片上传 - Agent 支持会话功能 - Agent 语音输入与输出功能开放 - Agent 界面支持用户自主切换模型 - Agent 支持对接多个知识库 - 知识库检索效果优化及多格式文件兼容 - 公众号/服务号/微信客服对接函数型 Agent 能力 - 支持查看大模型调用用量统计 - 提供开箱即用的函数型 Agent 模板及解决方案 **功能将分批次上线,具体排期请留意版本更新通知。** ## **[1.6.0] - 2025/02/27** --- ### ✨ **核心功能升级** - **函数型 Agent 上线** 新增支持复杂逻辑开发的函数型 Agent,兼容开源 Agent 框架,支持对接外部 API 及多样化数据源,提升多场景扩展能力。 - **混元 Turbo S 快思考模型上线** 新增「混元 Turbo S」快思考模型,实现秒级响应(吐字速度提升 100%、首字时延降低 44%),与既有的 DeepSeek-R1 等慢思考模型形成能力互补。 --- ### 🎨 **交互体验优化** - **Agent UI 对话界面焕新** - **重构 Agent UI**,优化思考中状态与联网交互的动效反馈 - **历史对话**:Agent UI 新增历史对话展示功能,支持回溯查询 - **联网开关**:C 端用户可自主关闭联网搜索功能 - **问题修复**:解决 Markdown 加粗文本换行渲染异常问题 --- ### 🌐 **扩展开放能力** - **知识库管理 API** 开发者可通过 API 实现知识库文档的自动化管理,支持创建、删除、批量操作等功能,[查看文档](https://cloud.tencent.com/document/api/1301/116428)。 --- ### ⚙️ **系统改进** - **回答逻辑优化** 修复 Agent 回答中重复用户问题及 Markdown 格式误用的异常,提升输出准确性。 --- ### 🚧 **新能力预告** - 支持对话界面上传文档和图片进行对话 - 支持语音输入和输出功能 - Agent 界面支持用户切换模型 - 对接云开发数据库作为数据来源,便于对话中直接引用结构化数据 - 知识库支持自动同步微信公众号 - 优化知识库检索效果 - 知识库支持更多类型的文件格式 - 支持通过 API key 调用 Agent 的 API 接口 - 支持公众号/服务号/微信客服等对接函数型 Agent **功能将分批次上线,具体排期请留意版本更新通知。** ## [1.5.0] - 2025/02/21 ### ✨ **核心功能升级** - **联网搜索能力** Agent 现支持 DeepSeek 等大模型接入实时互联网数据检索 - **动态模型管理** 新增模型版本控制功能,支持指定 DeepSeek-V3 等不同版本大模型 ### ⚡ **性能改进** - **文档处理能力提升** 知识库文件容量扩展至 100MB(Markdown 文件限 10MB) ### 🌐 **开放接口** - **全场景 API 支持** 开放 HTTP REST API 及 OpenAI SDK 兼容接口调用能力 --- ## [1.4.0] - 2025/02/21 ### 🧠 模型生态 - **新增模型接入** 正式支持 DeepSeek R1 及 DeepSeek-V3 大模型 ### 🚀 应用构建 - **快速部署工具** 提供从对话流构建到发布的端到端 AI 应用发布功能 - **交互体验增强** 控制台新增大模型对话实时预览模块 ### 📱 跨端支持 - **小程序集成方案** 上线 Agent UI 组件库及行业模板套件 --- ## [历史版本] ### 1.3.0 - **架构升级** 微信小程序基础库集成原生 AI SDK ### 1.2.0 - **小程序发布合规支持** 提供小程序算法备案全流程指引 ### 1.1.0 - **开发能力扩展** - SDK 新增工具链调用支持 - 云函数无缝集成 AI 能力 ### 1.0.0 - 首发版本 - **基础能力建设** - 混元大模型 API 集成 - 可视化 Agent 构建框架 - 微信生态多端发布能力(小程序/公众号/企业微信/客服系统) - RAG 知识库引擎(支持文档问答场景) --- ## 常见问题 FAQ # 常见问题 FAQ :::tip 云开发 AI+ 模块近期的更新日志请参考 [AI+ 更新日志](https://docs.cloudbase.net/ai/CHANGELOG) ::: ## 入门与基础功能 ### 如何免费试用云开发 AI 能力? **试用方式**: - **新人特权**:新用户首月 0 元体验。 - 方式 1:已有小程序,通过微信开发者工具或者通过微信公众平台(登录小程序账号,使用微信云服务助手小程序开通,不需要下载开发者工具)开通云开发,首月免费(适用于未使用过云开发的用户)。 - 方式 2:若无小程序,可先开通微搭体验版 [链接](https://console.cloud.tencent.com/lowcode) - 之后登录 [使用入口](https://tcb.cloud.tencent.com/dev?#/ai?tab=home) 试用 AI+ 功能。 ### 云开发 AI Agent 能做什么? ##### 核心功能 - **多种 AI 能力**:可直接调用大模型 API,或自定义 Agent 接入知识库系统。 ##### 全渠道部署 - **发布渠道**:支持小程序、Web 网页、微信公众号/服务号及微信客服系统。 - **模型支持**:同时兼容 DeepSeek 和混元双模型。 ### 小程序如何接入 AI? 请参考《小程序接入云开发 AI 能力指引》: [链接](https://docs.cloudbase.net/ai/miniprogram-using) 如需进一步操作或建议,请查阅该指引文档。 ### 有没有已经开发好的云开发 AI 小程序案例? 有。可通过以小程序体验云开发 AI 能力: ![](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/1c711efa-c6f9-49c2-9fec-068e148f74f6.jpg) 支持 DeepSeek 及智能体实时试玩。 ### 不写代码如何发布一个 AI Agent? 可以选择一键发布 Agent 为网页或者小程序,或者参考上述文档来发布到公众号。 ### 如何快速创建 AI Agent? > 首先,确保已经开通过云开发环境,免费开通体验流程请参考上文**如何免费试用云开发 AI 能力?** 1. **登录 AI+**: Agent 后登录 [使用入口](https://tcb.cloud.tencent.com/dev?#/ai?tab=agent) 试用 AI+ 功能。 2. **创建 Agent**: 创建一个 Agent,选择模型(支持 DeepSeek/混元大模型,)填写设定信息,上传个人知识库,点击保存 Agent ### 是否支持快速基于 AI Agent 创建一个小程序/web 网页 支持,且无需编码基础,零代码可以上线。 完成 Agent 创建之后,可以在保存之后的弹窗中,点击创建应用,支持发布为独立的小程序或网站 ### 如何在现有小程序中使用? 需要一定的编码基础,可参考参考《小程序接入云开发 AI 能力指引》: [链接](https://docs.cloudbase.net/ai/miniprogram-using) ### 公众号是否支持接入 AI 实现智能客服? 支持,云开发 Agent 可以一键发布到公众号和服务号作为智能客服,复用微信公众号都对话界面提供客服能力。 1. **发布到公众号**:参考 [如何快速创建 AI Agent?](#如何快速创建 AI Agent?) ,保存之后,点击发布到微信平台,选择公众号或者服务号,填写公众号的 appid,授权之后即可发布到公众号 2. **体验对话功能**:在公众号界面进行对话,即可体验 > 限制条件: 对于订阅号或者未认证的服务号,只能在 15 秒内进行被动回复。若消息处理时间超出这一时限,系统便会自动发送“思考中,请回复‘继续’”的提示。已经认证的服务号不受此限制。 ##### 其他方式 - **公众号菜单嵌入智能客服**:创建完 Agent 之后可以一键生成一个应用,发布为 h5 网页,然后把地址嵌入到公众号菜单中 ### 视频号是否可以接入 AI 实现智能客服? 支持,可以参考上一步的 1/2 步骤,先创建完 Agent,然后选择发布到微信客服即可,微信客服支持服务视频号的用户。 ### 云开发 Agent 是否支持企业微信智能客服? **支持**。云开发 Agent 可以发布到微信客服系统,可以参考前面流程,先创建完 Agent,,然后选择发布到微信客服即可,底层基于企业微信,能够服务外部微信客户。 ### DeepSeek 是否支持联网搜索? 支持,可通过 Agent 可开启联网搜索能力,支持混元大模型和 DeepSeek ### 是否支持用户在对话中上传文档和图片? 支持,过 Agent 可在对话中上传文档和图片,支持混元大模型和 DeepSeek ### 是否支持用户查看历史记录? 支持,可以使用最新的 Agent UI,默认集成了查看历史记录功能 ### 是否支持多个会话分组功能? 目前仅开放了单会话功能,即一个终端用户和一个 Agent 之间暂时只有一个会话,创建会话功能即将支持,敬请期待 ### 为什么 Agent 回复速度有些慢? 请检查是否使用了 DeepSeek R1 模型, DeepSeek R1 模型思考过程较久, 可以切换到 DeepSeek V3 模型,没有思考过程,回复更快 或者也可以使用混元大模型的 Turbo S 快思考模型 ### 是否支持对接其他平台搭建的智能体? 支持通过函数型智能体对接其他平台的智能体,例如元器等平台开发的 Agent,支持通过 Agent UI 及小程序基础库 SDK 来调用 ### 是否开放了 API 可以通过其他语言或者平台来调用? 支持,模型接入接口将可以无缝对接 OpenAI SDK 等开源库,Agent 对话相关接口,可通过 HTTP 请求方式被其他平台任意语言来调用 ### 是否支持通过服务器方式开发的小程序或者第三方开发的小程序调用? 只要能够开通云开发,都是可以正常在小程序中使用云开发提供的 AI+能力。 已有小程序,通过微信开发者工具开通云开发或者通过微信公众平台-登录小程序-开通云开发,首月免费(适用于未使用过云开发的用户)。 ## 开发 ### 如何隐藏 Agent UI 的推理思考过程? DeepSeek R1 等模型思考过程较久,如果希望隐藏思考过程,可以切换到混元大模型,或者切换到 DeepSeek V3 模型,没有思考过程,回复更快。 或者,在 AgentUI 中进行隐藏 #### 小程序 Agent UI 组件 找到如下代码进行删除 ``` ``` #### Agent UI 可视化组件 找到思考过程,点击**不可见**,即可隐藏思考过程 ![](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/3cf69f7f-ac5b-4fae-86ce-ae7f3189ba73.png) ### Agent 文件上传或解析失败,如何解决? 由于微信小程序基础库安全策略升级,文件上传功能解析流程可能受到影响,请开发者进行 Agent-UI 组件升级: - 小程序源码组件,请更新替换至最新版本 - 微搭低码组件,请新建页面然后重新拖动更新 agent-ui 区块,完成后发布应用 ![](https://qcloudimg.tencent-cloud.cn/raw/e6c34cc0147142daecee2b88edb216eb.png) ### Agent 是否查看历史对话记录? 可以,在开发平台的 Agent 详情,点击查看历史记录 ### 是否支持通过 API 调用大模型? 支持, 可参考 [通过 API 调用](https://docs.cloudbase.net/ai/api-key) ### 是否支持通过 API 调用 Agent? 暂时不支持通过 API key 调用,可以用其他登录方式来对接,然后通过 [HTTP API](https://docs.cloudbase.net/http-api/ai-bot/send-message) 来调用 ### Agent 中是否支持插件和工具调用? 支持,可以通过函数型 Agent 进行开发,支持开源 Agent 框架,如 Langchain、Mastra 等,都可以通过函数型 Agent 进行适配,同时支持通过可视化开发,小程序 和 web 以 API 和 JSSDK 来调用 Agent ### Agent 中是否可以对接外部 API 或者外部数据库? 支持,可以通过函数型 Agent 进行开发,通过工具调用,对接外部 API 或者外部数据库,同时支持通过可视化开发,小程序 和 web 以 API 和 JSSDK 来调用 Agent ### Agent 中是否支持可视化工作流? 暂不支持可视化工作流编排,可通过函数型 Agent 进行代码编排实现复杂的 Agent 功能 ### 是否支持对接元器/LKE 等其他 Agent 开发工具提供的 Agent? 支持,可以通过函数型 Agent 进行适配,可以无缝对接元器/LKE 等 Agent 开发工具提供的 Agent,同时支持通过可视化开发,小程序 和 web 以 API 和 JSSDK 来调用 Agent ### 函数型 Agent 是否可以对接公众号/服务号/微信客服? 函数型 Agent 暂时不支持对接微信公众号、服务号、微信客服,即将上线,敬请期待 支持通过可视化开发,小程序 和 web 以 API 和 JSSDK 来调用 Agent ### UniApp/Taro 等框架如何使用云开发 AI 能力? 如果使用微信 Donut 多端框架开发应用,可以使用 wx.cloud.extend.AI 接口来调用云开发 AI 能力,和微信小程序中保持一致,具体可参考[多端框架 wx.cloud.extend.AI 接口](https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/miniapp/new-capability/cloud/cloud.html#_3-5-wx-cloud-extend-AI-%E6%8E%A5%E5%8F%A3) UniApp/Taro 可以通过分别调用微信基础库和 JSSDK 来实现多端调用,参考 [SDK 初始化](https://docs.cloudbase.net/ai/sdk-reference/init) ### 其他语言或者框架如何使用云开发 AI 能力? 可以通过 HTTP API 来调用,参考 [HTTP API](https://docs.cloudbase.net/http-api/ai-bot/send-message) ## 发布与部署 ### 小程序中使用了 AI 能力,正式上线前如何通过微信审核? 在发布 AI 智能体到小程序时,微信将在代码审核阶段核实小程序运营的内容与所选类目是否相符。AI 问答涉及深度合成技术,需补充【深度合成-AI 问答】服务类目。 目前,个人主体小程序尚未开放深度合成相关服务类目,建议申请企业主体类型小程序。 对于个人客户,考虑到类目限制,建议使用 H5 或公众号(订阅号/服务号均可),或者小程序的客服消息等其他方式实现 AI 智能体的功能。 1. 确认您的小程序通过了**企业**认证 2. 确认您的环境有效期至少为 3 个月,有助于您通过审核 3. 进入云开发平台[AI+概览页](https://tcb.cloud.tencent.com/dev#/ai?tab=home),点击帮助文档中的**小程序算法备案** ![](https://qcloudimg.tencent-cloud.cn/raw/5c2baa1d524af4ad39b2ba1ecdaf457f.png) 4. 填写您的小程序 AppID 和小程序主体名称 5. 平台将会为您生成算法备案资料 ![](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/991e1b53-108e-4f8b-9eeb-9699def55f4b.png) 6. 前往[微信开发者平台](https://mp.weixin.qq.com/),提交上一步生成的备案资料页的清晰截图 7. 您可以在服务类目中选择**深度合成**>**AI 问答/AI 换脸/AI 绘画**,选择 2.2 深度合成服务《在用证明》 (证明须含【小程序主体】 、【小程序 appid】 、【订单有效期】、【算法备案号】等内容),将截图上传到微信开发者平台,保证图片清晰可见 ## 定价与计费 ### 云开发 AI 能力定价如何? 免费版和个人版套餐的用户,可以使用大模型对话能力以及Agent的人设、开场白、问题建议、知识库、数据模型和联网搜索等能力。 团队版及以上的用户,在上述功能的基础上,还可以使用高级能力,如MCP、语音功能、文件上传、多会话模式等。 ### 100万token的限时活动 云开发限时活动,为每个环境赠送100万token,6个月内有效,截止时间到2025年12月31日。具体细则如下: - 在2025年2月14日之前创建的环境,赠送资源包自2025年2月14日生效,到2025年8月14日失效。 - 在2025年2月14日~2025年12月31日创建的环境,赠送资包自环境创建之日起生效,6个月后失效。 ### 赠送token耗尽之后如何收费? 赠送 token 即将用完或者已耗尽,您可以在 AI+ 模块的大模型页面配置混元/deepseek的 API Key,也可以添加自定义模型,平台将不再限制 token 用量。 配置自定义模型请参考 [接入自定义模型](/ai/model/model-access) ## 知识库相关 ### 知识库支持哪些文件格式? 目前支持 .md, .pdf, .docx, or .pptx 等文件格式 ### 知识库的文件大小限制是怎样的? 单个文件最大 100M,md 文件最大支持 10M,一个知识库支持多个文件 ### 知识库是否支持对接微信公众号的文章? 暂时不支持 ### 知识库是否支持数据库? 已经支持,可以在 Agent 对接数据模型。 表格等结构化的数据可通过数据库来作为知识库来源,同时支持按照终端用户的权限来查询数据,避免越权访问数据。 ### 知识库是否支持上传 Excel? 暂时不支持,正在规划中,可以将 Excel 转换为 pdf 或者 docx 格式上传,效果需要尝试下是否满足预期 也可以建一个数据模型,将 Excel 的数据导入使用,在 Agent 支持配置数据模型,通过数据模型来查询数据,同时支持按照终端用户的权限来查询数据,避免越权访问数据。 ## 测试与故障排查 ### 小程序发布之后,为什么 AI 不回复消息? ##### 可能原因及解决方法 1. **Agent UI 参数配置**:检查是否传入正确的 `botId` 或大模型配置。 2. **微搭可视化开发授权认证**:确保小程序使用扫码授权方式,全托管认证方式暂不支持。 3. **小程序 IDE 基础库版本**:选择 3.7.7 及以上版本。 4. **用户微信客户端版本**:需高于 8.0.55,低于此版本建议升级微信。 ##### 进一步操作 - 核对以上各项设置,确保配置正确无误。 - 若问题依旧存在,建议查阅官方文档或联系技术支持获取帮助。 ### 如何优化 AI 对话的输出效果? 可能原因及解决方法: #### 1. 知识库内容质量问题 知识库内容的数量和质量是影响 AI 对话输出效果的重要因素,如果知识库内容数量较少、质量较差,可能导致 AI 对话输出效果较差。建议在知识库中添加高质量的内容,如官方文档、常见问题、FAQ 等。 可以通过**向量检索**的方式来检查知识库内容的质量,如果发现质量较差,可以尝试删除或修改这些内容。 参考[知识库 HTTP API](https://docs.cloudbase.net/http-api/knowledge/search) 1. 在云开发控制台获取 API key,参考文档 [通过 API 调用](https://docs.cloudbase.net/ai/api-key) 2. 使用知识库的向量检索接口来检索知识库内容,需要传入知识库的 id,以及用户的问题,可以看到知识库中与用户问题最相似的内容,可以看到每个内容的相似度,如果相似度较低,说明该内容质量较差,可以尝试删除或修改这些内容。 #### 2. 提示词的配置 Agent 的提示词配置会影响 AI 对话的输出效果,如果提示词配置不当,可能导致 AI 对话输出效果较差。 可以采用提示词工程的一些通用技巧来优化提示词,参考[提示词工程](https://www.promptingguide.ai/zh) 可采用的方法包括: 1. 使用清晰、明确、简洁的提示词来引导 AI 生成答案,避免使用过于复杂或模糊的提示词。 2. 结构化 Prompt 模板(CO-STAR 框架)​ 3. 针对一些必须要遵循的要求,可以通过增加强调词来引导 AI,例如加入 **特别重要** 等字眼来要求 AI 遵循要求。 4. 为 AI 提供输出的样例,例如在提示词中加入 **示例:** 等字眼,引导 AI 生成符合要求的答案。 5. 对于许多复杂任务,,可以设置步骤,例如“第一步:xxx,第二步:xxx,第三步:xxx”等。 6. 引导模型思考,例如在提示词中加入 **请思考** 等字眼,引导 AI 思考后再生成答案。 7. 提示词的迭代,针对现网回答的效果进行评估和迭代提示词。 ### 流式输出过程突然中断的原因是什么? 如果 Agent 出现了思考或者回答中途会停止的问题,目前主要出现在当思考内容较长或者回答内容较长的情况,在请求大模型时,提示词的简单程度、网络速度等多重因素可能都会让请求时长增加。 可能原因:**客户端请求超时**,可以修改客户端网络超时配置 #### 小程序端全局超时配置 可以在微信小程序中的 app.json 中配置全局超时时间,可以根据小程序的实际情况进行配置,建议配置为 10 分钟以内 ```json { "networkTimeout": { "request": 600000 } } ``` 参考链接: #### web 端超时配置 cloudbase-js-sdk 默认设置了超时时间为 15 秒,当请求超时时,会主动取消请求。用户可以在 `cloudbase.init` 时自定义超时时间。 ```js import cloudbase from "@cloudbase/js-sdk"; const app = cloudbase.init({ env: "your-env", // 需替换为实际使用环境 id timeout: 600000, // 设置超时时间为 10 分钟 }); const auth = app.auth(); await auth.signInAnonymously(); // 或者使用其他登录方式 const ai = app.ai(); // 后续就可以按常规方式调用 ai 能力了 ``` ### Agent UI 区块组件引入后小程序包大小超了怎么办 > 在小程序源码中使用推荐使用源码组件,具体参考 [指引三:使用云开发 AI 对话组件,快速接入 AI 对话](https://docs.cloudbase.net/ai/miniprogram-using#%E6%8C%87%E5%BC%95%E4%B8%89%E4%BD%BF%E7%94%A8%E4%BA%91%E5%BC%80%E5%8F%91-ai-%E5%AF%B9%E8%AF%9D%E7%BB%84%E4%BB%B6%E5%BF%AB%E9%80%9F%E6%8E%A5%E5%85%A5-ai-%E5%AF%B9%E8%AF%9D),或者参考下面的链接来使用子包引入。 ##### 第 1 步:使用子包形式引入 1. **下载组件代码包**:[组件下载地址](https://weda.cloud.tencent.com/ai-resource/agent-ui.zip)。 2. **解压并放置**:将组件包放入小程序项目根目录下的 `components/agent-ui` 目录。 3. **配置 app.json**: ```json { "lazyCodeLoading": "requiredComponents", "subpackages": [ { "root": "components/agent-ui", "name": "agent-ui", "pages": [] } ] } ``` 4. **配置 project.config.json**: ```json { "setting": { "ignoreDevUnusedFiles": true, "ignoreUploadUnusedFiles": true } } ``` ##### 第 2 步:初始化对话组件 1. **修改 `./components/agent-ui/index.js`**: ```javascript import * as sdk from "@cloudbase/weda-client"; sdk.init({ envID: "", }); ``` 2. **在组件头部添加引用**:在 `./components/agent-ui/dist/Agent-UI/index.js` 中添加 `import '../../index'`,确保组件加载时立即初始化 SDK。 通过以上步骤,可以有效减小小程序主包的大小,并确保 Agent UI 组件的正确初始化和使用。 ### 为何向订阅号发送消息后会收到“思考中,请回复‘继续’”的回应? 对于订阅号或者未认证的服务号,只能在 15 秒内进行被动回复。若消息处理时间超出这一时限,系统便会自动发送“思考中,请回复‘继续’”的提示。 已经认证的服务号不受此限制。 可以尝试: - 手动回复“继续”:促使系统继续完成回复流程。 - 优化智能回复设置:调整智能体的回复策略,确保回复内容简洁且能在规定时间内完成。 优化建议: 1. 在提示词增加如下设定,可以显著提升回复速度,测试时建议换一个微信号测试公众号的回复效果(更改提示词,历史回复可能会影响模型的输出) ``` - 智能体以极简风格回应问题。 - 简化复杂问题的回答,提炼核心信息。 - 严格限制回复内容的长度和相关性,避免冗余。 - 不要输出 markdown 格式,直接输出纯文本 ``` 2. 如果使用深度思考模型(如 DeepSeek R1),响应的时间会较慢,可以考虑使用混元模型或者 DeepSeek V3 模型。 3. 如果希望更好的体验,可以考虑使用公众号个性化菜单嵌入 H5/小程序的形式,支持更好的对话体验 ### 在流式调用时,如何才能知道流式传输结束了? `for await` 代码块后的代码在流式传输之后才会执行,所以只要在`for await` 代码块后做流式调用结束相关的通知/设定标识的操作即可。 ```js const hy = ai.createModel("hunyuan-exp"); // 创建模型 const res = await hy.streamText({ model: "hunyuan-lite", messages: [{ role: "user", content: "你好,请你介绍一下李白" }], }); for await (let str of res.textStream) { console.log(str); } console.log("流式传输结束啦"); // 流式传输结束后才会执行这里的代码! ``` ### Agent UI 源码版本开发者工具勾选“上传时进行代码保护“会报错? 开启此选项,开发者工具会尝试对项目代码进行保护,主要是对文件进行扁平化处理并替换 require 引用的文件名 由于其中有动态引用的情况,如 var a = 'somefile.js'; require(a);不适合使用此功能,所以建议关闭此选项 ## 技术细节 ### 在小程序中使用 AI+,我该用微信小程序基础库还是 AI SDK? AI SDK 和微信小程序基础库提供的 AI 能力是相同的。 AI SDK 是云开发提供的多端 SDK,在多个平台都有一致的使用体验。如果您有一码多端的需求,可以选用 AI SDK。 然而在小程序上使用 AI SDK 会受到一定的限制: 1. 小程序包体积有限制,引入 AI SDK 会增加一定的包体积 2. 小程序需要配置服务器域名,配置完成后 AI SDK 才能进行请求 微信小程序基础库内置了完整的云开发 AI 能力,不占用包体积,也无需配置服务器域名。对于专注于小程序的开发者们,使用微信小程序基础库是一个好的选择。在不用安装任何外部包的情况下,也能完整地访问到云开发提供的 AI+ 能力。 微信小程序基础库和 AI SDK 在使用方法上有一定的区分,请注意阅读文档。 --- ## Agent UI 大模型模版 # Agent UI 大模型模版 目前云开发的低码组件中,已经提供了可以和 AI 大模型或 Agent 直接对接并使用的 **前端组件**;可以快速在微搭应用或小程序页面中引入组件并配置对接,即可完成与 **大模型** 或 **Agent** 的对接。 ## 下载模版 1. 进入 [云开发AI+](https://tcb.cloud.tencent.com/dev?#/ai?tab=agent) 2. 选择对应的 **应用类型**、**开发方式**、**接入类型**、**AI实例**,完成后点击下载模版 ![](https://qcloudimg.tencent-cloud.cn/raw/15f6064fd3736d0367e1f775616bce50.png) 3. 解压到任意位置,打开 **微信开发者工具** ,点击新建项目 4. 选择到解压的位置,填入对应的AppID,点击创建按钮 5. 点击信任并运行 ![](https://qcloudimg.tencent-cloud.cn/raw/cf29c0ce0bbb588567e010a6041b0842.jpg) 6. 此时页面会自动编译渲染出来,压缩包中带有依赖,无需构建 ![](https://qcloudimg.tencent-cloud.cn/raw/eb6add637be81474210af1b5f70cb0ce.png) 7. 修改 `app.js` 文件中的 **env** 参数,改为当前云开发环境的环境Id 8. 修改 `pages/index/index.js` 中的 **agentConfig** **其中 agentConfig 参数结构如下:** | 参数名称 | 参数可选值 | 说明 | | :----------------------------: | :---------------------: | :--------------------------------------------------------------------------------------------------------------------------------: | | chatMode | 'bot' 或 'model' | 当 chatMode='bot'时,agentConfig.botId 必填;当 chatMode='model'时,modelConfig.modelProvider 和modelConfig.quickResponseModel必填 | | showBotAvatar | boolean | 界面是否展示左侧头像 | | agentConfig.botId | 字符串 | agent id,当 chatMode = 'bot' 时,必填 | | agentConfig.allowUploadFile | boolean | 界面是否展示文件上传 | | agentConfig.allowWebSearch | 字符串 | 允许界面呈现联网配置开关 | | agentConfig.allowPullRefresh | boolean | 允许下拉刷新 | | agentConfig.allowUploadImage | boolean | 允许上传图片 | | modelConfig.modelProvider | 'hunyuan' 或 'deepseek' | 大模型服务商 | | modelConfig.quickResponseModel | 字符串 | 具体的模型版本, 参考[大模型版本](#大模型版本) | | envShareConfig.resourceAppid | 字符串 | 环境共享的资源方 AppID | | envShareConfig.resourceEnv | 字符串 | 环境共享的资源方环境 ID | ** 文件上传说明 ** - **大小限制**:单文件不超过10M - **数量限制**:单次最多支持 5 个文件 - **文件类型**:pdf、txt、doc、docx、ppt、pptx、xls、xlsx、csv - **request合法域名配置**:微信小程序上传文件需要添加“文件上传接口”到request合法域名列表,文件上传域名为:https://{envid}.api.tcloudbasegateway.com,替换envid为真实的环境ID, 前往微信公众平台[https://mp.weixin.qq.com](https://mp.weixin.qq.com)配置request合法域名 ** 图片上传说明 ** 每次仅支持上传单张图片,最大不超过30MB **示例:** - **使用deepseek-v3模型** ```json { chatMode: "model", // bot 表示使用agent,model 表示使用大模型 showBotAvatar: true, // 是否在对话框左侧显示头像 modelConfig: { modelProvider: "deepseek", // 大模型服务厂商 quickResponseModel: "deepseek-v3", //大模型名称 logo: "", // model 头像 welcomeMsg: "欢迎语", // model 欢迎语 }, } ``` - **使用deepseek-r1模型** ```json data: { chatMode: "model", // bot 表示使用agent,model 表示使用大模型 showBotAvatar: true, // 是否在对话框左侧显示头像 modelConfig: { modelProvider: "deepseek", // 大模型服务厂商 quickResponseModel: "deepseek-r1", //大模型名称 logo: "", // model 头像 welcomeMsg: "欢迎语", // model 欢迎语 }, } ``` - **使用Agent** ```json { chatMode: "bot", // bot 表示使用agent,model 表示使用大模型 showBotAvatar: true, // 是否在对话框左侧显示头像 agentConfig: { botId: "bot-e7d1e736", // agent id, allowWebSearch: true, // 允许客户端选择启用联网搜索 allowUploadFile: true, // 允许上传文件 allowPullRefresh: true, // 允许下拉刷新 allowUploadImage: true // 允许上传图片 } } ``` ## 获取Agent ID ![](https://qcloudimg.tencent-cloud.cn/raw/cba2cfa73269dabe7c9067d5a27c67da.png) ## 大模型版本 ### hunyuan | 模型版本 | 说明 | | :----------: | :----------------------------------------------------------------------: | | hunyuan-lite | 具备强大的中文创作能力,复杂语境下的逻辑推理能力,以及可靠的任务执行能力 | ### deepseek | 模型版本 | 说明 | | :---------: | :------------------------------------------------: | | deepseek-v3 | 专注于自然语言处理、知识问答、内容创作等通用任务 | | deepseek-r1 | 推理模型,专为数学、代码生成和复杂逻辑推理任务设计 | ## 相关链接 - [Agent UI 区块组件详细参考文档](../agent-ui/) ## 通过环境共享调用其他环境的AI能力 假设A小程序开通了云开发环境,B小程序想跨环境调用A小程序云开发环境下的AI能力,可参照以下指引。 ### 开通环境共享 登录A小程序,开通环境共享,将A小程序的云开发环境共享给B小程序使用 > A小程序和B小程序必须是同一个主体才能环境共享 ![](https://qcloudimg.tencent-cloud.cn/raw/9d7970656735c76429613055667beb48.png) ### 配置环境共享参数 在B小程序中使用 Agent-UI 时,将A小程序的 appid 和 envId 传给 Agent-UI 组件 参数如下: ```js data: { chatMode: "model", // bot 表示使用agent,model 表示使用大模型 showBotAvatar: true, // 是否在对话框左侧显示头像 modelConfig: { modelProvider: "deepseek", // 大模型服务厂商 quickResponseModel: "deepseek-v3", // 快速响应模型 (混元 turbo, gpt4 turbo版,deepseek v3等) logo: "", // model 头像 welcomeMsg: "欢迎语", // model 欢迎语 }, envShareConfig: { // 不使用环境共享,请删除此配置或配置EnvShareConfig:null // 资源方 AppID resourceAppid: "wx7a******5f4f", // 资源方环境 ID resourceEnv: "chr**************46d2d", }, }, ``` --- ## 概述 # 概述 ## Agent 是什么 Agent,或称为 AI Agent,是以大模型为基础,通过特定指令或指引,能够完成特定任务。Agent 利用 AI 大模型,具有强大的语言理解和生成能力,可以在各种领域执行复杂任务。 ## 云开发 Agent 是什么 云开发 Agent 基于 [`函数型云托管`](https://docs.cloudbase.net/cbrf/intro) 实现的,开发者能够完全掌控业务逻辑,满足高度个性化的需求。在函数中,可以调用第三方模型、设计复杂的决策流程、使用开源的 Agent 开发框架,实现 Agent 的`感知(Perception)`、`规划(Planning)` 和 `行动(Action)` 等方面的能力,从而更好地实现个性化需求。 基于云函数开发一个 AI Agent ,是一个后端适配前端的过程,即,云函数中实现与前端约定好的 API 接口,即可实现与前端的适配对接。 借助云开发提供的 AI Agent 开发框架 [`@cloudbase/aiagent-framework`](https://www.npmjs.com/package/@cloudbase/aiagent-framework),仅需几行代码,即可快速实现一个基于 `函数型云托管` 的简单空白 Agent ,示例代码如下: ```ts const { IBot } = require("@cloudbase/aiagent-framework"); const { BotRunner } = require("@cloudbase/aiagent-framework"); const ANSWER = "你好,我是一个 Agent ,但我只会说这一句话。"; /** * @typedef {import('@cloudbase/aiagent-framework').IAbstractBot} IAbstractBot * * @class * @implements {IAbstractBot} */ class MyBot extends IBot { async sendMessage() { return new Promise((res) => { // 创建个字符数组 const charArr = ANSWER.split(""); const interval = setInterval(() => { // 定时循环从数组中去一个字符 const char = charArr.shift(); if (typeof char === "string") { // 有字符时,发送 SSE 消息给客户端 this.sseSender.send({ data: { content: char } }); } else { // 字符用光后,结束定时循环 clearInterval(interval); // 结束 SSE this.sseSender.end(); res(); } }, 50); }); } } /** * 类型完整定义请参考:https://docs.cloudbase.net/cbrf/how-to-writing-functions-code#%E5%AE%8C%E6%95%B4%E7%A4%BA%E4%BE%8B * "{demo: string}"" 为 event 参数的示例类型声明,请根据实际情况进行修改 * 需要 `pnpm install` 安装依赖后类型提示才会生效 * * @type {import('@cloudbase/functions-typings').TcbEventFunction} */ exports.main = function (event, context) { return BotRunner.run(event, context, new MyBot(context)); }; ``` ## 使用 Agent 开发完成的 Agent ,可以通过以下方式进行使用: - 通过前端组件,在小程序中快速引入并配置对接 Agent ,即可在会话组件中和 Agent 沟通; - 通过 SDK,在小程序、H5、Web 应用的前端逻辑中,或者云函数、服务端等后端逻辑中调用 Agent ,实现与 Agent 的交互; - 通过第三方平台对接能力,将 Agent 与微信小程序客服、微信客服、微信公众号(服务号)、微信公众号(订阅号)完成对接,实现在这些平台中的聊天对话与 Agent 的对接; --- ## 自定义 Artifact 解析 # 自定义 Artifact 解析 通过 Artifact,用户可以轻松创建和管理多种类型的内容,如代码架构图、流程图、网页设计、SVG 图形和交互式组件。Artifact 特别适合开发人员、设计师、产品经理和营销人员,用于将创意快速转化为实际产品。 :::tip 当前**[Agent UI React 组件](../agent-ui/agent-ui-react)** 已支持自定义 Artifact 能力 ::: ## 效果 ### Web 应用 Artifact **源代码** **应用预览** ### Mermaid 图表 Artifact **预览** ## 如何使用 [参考完整代码示例](https://gitee.com/TencentCloudBase/cloudbase-agent-ui/tree/main/apps/react-agent-ui) ### 1. 配置规范 Prompt > artifact 解析依赖大模型输出规范的 artifact 内容结构,可通过 prompt 约束生成 可参考如下 Prompt 示例,定义 `code` 与 `mermaid` 两种 Artifact,分别处理 `Web 前端应用` 与 `Mermaid 图表` 两类 Artifact。 当需要扩展其他类型 Artifact 时,参考实现即可(遵循 cloudbaseArtifact 标签格式)。 ``` 你是 CloudBase 的 AI 助手,负责为用户生成各种类型的内容。 当需要生成专业内容时,请使用如下格式: 支持的内容类型: 1. 用于 HTML/CSS/JS 应用 (type="code"): 2. 用于 Mermaid 流程图 (type="mermaid"): flowchart TD A[Start] --> B{Decision} B -->|Yes| C[Action] B -->|No| D[Another Action] 重要说明: - 必须提供完整且自包含的内容 - 对于 HTML 应用,所有 CSS 和 JavaScript 必须包含在同一个文件中 - 外部库请使用 CDN 链接,不要使用 npm 包 - Mermaid 流程图必须遵循正确语法 - 每个 artifact 必须有唯一的 ID、描述性标题和合适的 type - 不要使用 Fenced Code Blocks 包裹 artifact 内容 Create a simple counter application Here's a simple counter application: Simple Counter body { font-family: Arial, sans-serif; display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0; } .counter { text-align: center; } .count { font-size: 4rem; margin: 1rem 0; } button { padding: 0.5rem 1rem; margin: 0 0.5rem; font-size: 1rem; } Counter App 0 - + Reset let count = 0; const countDisplay = document.getElementById('count'); document.getElementById('increment').addEventListener('click', () => { count++; updateDisplay(); }); document.getElementById('decrement').addEventListener('click', () => { count--; updateDisplay(); }); document.getElementById('reset').addEventListener('click', () => { count = 0; updateDisplay(); }); function updateDisplay() { countDisplay.textContent = count; } Create a flowchart showing a login process Here's a flowchart showing a typical login process: flowchart TD A[开始] --> B[步骤一] B --> C[步骤二] C --> D[结束] ``` ### 2. 实现 Artifact 组件 前端 Code Artifact 组件示例代码段 ```JSX export const CodeArtifactComponent: ArtifactComponent = ({ artifact }) => { const [isPreviewMode, setIsPreviewMode] = useState(false); const handlePreviewToggle = () => { setIsPreviewMode(!isPreviewMode); }; return ( {artifact.title} {isPreviewMode ? 'View Code' : 'Preview'} {isPreviewMode ? ( ) : ( {artifact.content} navigator.clipboard.writeText(artifact.content)}> Copy )} ); }; ``` ### 3. React Agent UI 组件配置 在 extra 属性中传入 artifactMap 对象即可 (`code`与`mermaid` 两个 key 对应前面规范定义的 artifact type) ```JSX ``` --- ## Agent UI 自定义输出结构 # Agent UI 自定义输出结构 ## 概述 希望 **Agent** 返回值中带有一些可视化组件进行操作,此时可以调整 **Agent UI** 组件支持HTML渲染,以及提示AI进行HTML格式返回 在此之前您需要先创建一个 **Agent**,若您还没开始创建,可以参照这里快速开始 [快速开始](../agent/build) ## 示例 ## 操作步骤 ### 1. 修改 **Agent** 提示词 提示词示例: ``` 当我提问 "查询医保时", 通过html标签用一个卡片样式返回医保查询链接 "http://localhost:3000/ai/agent/custom-output" ``` 此时进行测试,返回结果中会带上一个卡片样式的HTML标签 ![返回结果](https://qcloudimg.tencent-cloud.cn/raw/2a69418393411f7c4b3594209fa5c2e5.png) ### 2. 修改 **Agent UI** 组件支持HTML渲染 进入 **可视化开发/应用** 模块,找到 **Agent UI** 组件,左侧大纲树中查询 **markdown**,找到 **markdown** 组件,点击 **属性**,在 **属性** 中找到 **html**,设置为 **true** ![](https://qcloudimg.tencent-cloud.cn/raw/6321efd4a124421d3c2d71fa8e6c2917.png) 此时在可视化中进行测试,返回结果的html标签会被渲染成真实效果 ![](https://qcloudimg.tencent-cloud.cn/raw/e68eb9d6c0ec56675b67c4dbbe6db0ac.png) ## 进阶配置 上述样式示例为 AI 自行产生,若想对样式做定制的话,建议直接提供样式模版给 AI 进行输出 提示词示例: ``` 提供以下样式模版 """ title description link """ 提供以下问题列表,当客户命中问题时返回样式模版并替换模版中的 title、description、link 等字段 | 问题 | title | description | link | | --- | --- | --- | --- | | 查询医保 | 医保查询 | 医保查询链接 | http://localhost:3000/ai/agent/custom-output | ``` 上述 **HTML模版** 也可以用AI进行生成 示例: --- ## 数据库 # 数据库 ## 什么情况使用数据库 开发者已经有小程序/web 应用,用户会通过小程序/web 产生数据,你希望 ai 可以理解这些数据,变成一个千人千面的智能体,同一个问题,每个用户都可以获得与他自身数据相关的答案。 ## 数据库和知识库的对比 | 对比项 | 知识库 | 数据库 | | ------------ | ---------------------------- | ---------------------- | | 数据类型 | docx/pdf/ppt/markdown | 表格/json | | 数据更新频率 | 低频 | 高频 | | 数据维护者 | 开发者 | 开发者 + C 端用户 | | 典型应用 | 智能客服、问答系统、专家决策 | 用户行为分析、数据查询 | ## 怎么配置数据模型 在[云开发平台](https://tcb.cloud.tencent.com/dev)数据库模块,可以新建数据模型 1. 新建数据模型,选择数据库(文档型) ![创建数据模型](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/713b0e8a-2a8a-43a6-8f09-f8b61db7c492.png) 2. 模型名称,字段名称,都要使用中文来描述,方便大模型理解用户问题和数据模型的关系。 ![配置数据模型](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/254720a5-8f3b-49d0-8462-4ce3896d520b.png) ## AI Agent 怎么绑定数据模型 ```ts const msg = "用户问题" const databaseModel = ["数据模型ID-1", "数据模型ID-2"] const result = await this.botContext.bot.tools.searchDB( this.botContext.info.botId, msg, databaseModel ); if (result?.code && result?.code?.length !== 0) { throw new Error(`查询数据模型内容失败: ${result?.message}`); } ``` ## 怎么和 agent 对话 使用自然语言和 agent 对话即可,如果问题里包含与数据库相关的信息,会触发查询数据库。 ## 图书馆agent示例 假如我们要做一个图书馆的 AI 小助手,可以帮助同学们快速查询图书馆是否有对应的藏书,也可以快速查询自己借阅过哪些图书,可以分析自己最喜欢哪种题材的图书。 ### 数据模型 需要有 3 个数据模型:用户信息表,书籍信息表,借阅记录表。 - 用户信息表的权限是所有人可读,仅创建者及管理员可读写。包含的字段至少有:ID、用户名称、用户年级。 - 书籍信息表的权限是所有人可读,仅管理员可写。包含的字段至少有:ID、书籍名称、书籍作者。 - 借阅记录表的权限是仅创建者及管理员可读写。包含的字段至少有:图书 ID、借阅人 ID、借阅时间。 ![书籍信息表](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/8f2d1d54-45aa-43d7-bf70-0624f2f91c65.png) ![用户表](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/783fe487-ddb2-4f5e-a9c8-0a2466b233b5.png) ![借阅记录表](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/1adb6ab8-5e57-4f7a-9b16-92d557e87966.png) ### 对话效果 #### 查询所有书籍 这个会触发查询书籍信息表。 ![匹配一张表](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/c55a67bf-2bc3-46f6-a891-f376126ab402.png) #### 查询借阅过的书 这个会触发查询书籍信息表和借阅记录表。 ![匹配两张表](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/a3161717-2465-4e58-8f70-d77852e99e0e.png) #### 查询大一同学最喜欢的书 这个会触发查询用户信息表、借阅记录表、书籍信息表。 ![匹配三张表](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/39d3a94e-a171-40ac-ba6b-c8c013f053b6.png) --- ## 对接小程序客服 # 对接小程序客服 1步配置让云开发AI对接小程序客服,快速实现智能客服功能 ## 获取小程序AppId 进入[小程序后台](https://mp.weixin.qq.com/),进入 **开发管理** 模块查看 **AppId** ![](https://qcloudimg.tencent-cloud.cn/raw/9c0c0a453d143fb25b52619d8f699c9e.png) ## 新增 Agent 创建 Agent 请查看 [快速开始](../cbrf-agent/quickstart.md) ## 对接小程序 进入云开发AI+,选择 Agent 模块,在**接入指引**中选择在**微信平台**中选择 **小程序客服**,点击**立即授权**,按照指引填入填入 **AppId** 后点击下一步,会跳转到小程序扫码授权页面,该授权为通过云开发代理小程序后台能力,从而代理客服进行回复,完成后小程序则对接完成 ![微信平台](https://qcloudimg.tencent-cloud.cn/raw/044164a298994c3fdc771d93fbe0385f.png) 此时可以去小程序客服进行测试 ## 优化建议 在 **Agent** 提示词增加如下设定,可以显著提升回复速度,测试时建议换一个微信号测试公众号的回复效果 **(更改提示词,历史回复可能会影响模型的输出)** - 智能体以极简风格回应问题 - 简化复杂问题的回答,提炼核心信息 - 严格限制回复内容的长度和相关性,避免冗余 - 不要输出 markdown 格式,直接输出纯文本 如果使用深度思考模型(如 **DeepSeek R1**),响应的时间会较慢,可以考虑使用 **混元模型** 或者 **DeepSeek V3** 模型。 如果希望更好的体验,可以考虑使用个性化页面嵌入 H5/小程序的形式,支持更好的对话体验 --- ## 对接公众号客服(订阅号) # 对接公众号客服(订阅号) 1步配置让云开发AI对接公众号客服,快速实现智能客服功能 ## 获取公众号AppId 进入[公众号后台](https://mp.weixin.qq.com/),进入 **开发接口管理** 模块查看 **AppId** ![](https://qcloudimg.tencent-cloud.cn/raw/81d7dc3ca608deef36f1b1256d24399b.png) ## 新增 Agent 创建 Agent 请查看 [快速开始](../cbrf-agent/quickstart.md) ## 对接公众号 进入云开发AI+,选择 Agent 模块,在**接入指引**中选择在**微信平台**中选择 **公众号**,点击**立即授权**,按照指引填入 **公众号AppId**,后点击下一步,会跳转到公众号扫码授权页面,该授权为通过云开发代理公众号后台能力,从而代理客服进行回复,完成后公众号则对接完成 ![微信平台](https://qcloudimg.tencent-cloud.cn/raw/044164a298994c3fdc771d93fbe0385f.png) 此时可以去公众号客服进行测试 ![](https://qcloudimg.tencent-cloud.cn/raw/114d6fc0e7fa2071284f535eb724e002.png) ## 优化建议 在 **Agent** 提示词增加如下设定,可以显著提升回复速度,测试时建议换一个微信号测试公众号的回复效果 **(更改提示词,历史回复可能会影响模型的输出)** - 智能体以极简风格回应问题 - 简化复杂问题的回答,提炼核心信息 - 严格限制回复内容的长度和相关性,避免冗余 - 不要输出 markdown 格式,直接输出纯文本 如果使用深度思考模型(如 **DeepSeek R1**),响应的时间会较慢,可以考虑使用 **混元模型** 或者 **DeepSeek V3** 模型。 如果希望更好的体验,可以考虑使用公众号个性化菜单嵌入 H5/小程序的形式,支持更好的对话体验 --- ## 对接服务号客服 # 对接服务号客服 1步配置让云开发AI对接服务号客服,快速实现智能客服功能 ## 获取服务号AppId 进入[服务号后台](https://mp.weixin.qq.com/),进入 **开发接口管理** 首次进入需要成为开发者 ![](https://qcloudimg.tencent-cloud.cn/raw/52ac85efc4112c264ee28cf0ad17225e.png) 成为开发者后即可查看 **AppId** ![](https://qcloudimg.tencent-cloud.cn/raw/96fabd3d68afee2bbb1fe49d2fd92066.png) ## 新增 Agent 创建 Agent 请查看 [快速开始](../cbrf-agent/quickstart.md) ## 对接服务号 进入云开发AI+,选择 Agent 模块,在**接入指引**中选择在**微信平台**中选择 **服务号**,点击**立即授权**,按照指引填入 **服务号AppId**,点击下一步,会跳转到服务号扫码授权页面,该授权为通过云开发代理服务号后台能力,从而代理客服进行回复,完成后服务号则对接完成 ![微信平台](https://qcloudimg.tencent-cloud.cn/raw/044164a298994c3fdc771d93fbe0385f.png) 此时可以去服务号客服进行测试 ![](https://qcloudimg.tencent-cloud.cn/raw/c2bea460cbceac8b04b28d75b027cb04.png) ## 优化建议 在 **Agent** 提示词增加如下设定,可以显著提升回复速度,测试时建议换一个微信号测试公众号的回复效果 **(更改提示词,历史回复可能会影响模型的输出)** - 智能体以极简风格回应问题 - 简化复杂问题的回答,提炼核心信息 - 严格限制回复内容的长度和相关性,避免冗余 - 不要输出 markdown 格式,直接输出纯文本 如果使用深度思考模型(如 **DeepSeek R1**),响应的时间会较慢,可以考虑使用 **混元模型** 或者 **DeepSeek V3** 模型。 如果希望更好的体验,可以考虑使用个性化页面嵌入 H5/小程序的形式,支持更好的对话体验 --- ## 对接企微客服 # 对接企微客服 对接企微客服,快速实现智能客服功能 ## 获取企微ID 从 [微信客服平台](https://kf.weixin.qq.com/kf/frame#/corpinfo) 登录或注册,并且通过企业认证,复制**企业ID** ![](https://qcloudimg.tencent-cloud.cn/raw/4b74793a1e29d9c5f14b575d543f7b1f.png) ## 新增 Agent 创建 Agent 请查看 [快速开始](../cbrf-agent/quickstart.md) ## 对接微信客服 1. 进入云开发AI+,选择 Agent 模块,在**接入指引**中选择在**微信平台**中选择 **微信客服**,点击授权,按照指引填入 **Token** 和 **EncodingAESKey**,该参数从 **微信客服平台** 获取,继续向下执行步骤 ![微信平台](https://qcloudimg.tencent-cloud.cn/raw/044164a298994c3fdc771d93fbe0385f.png) 2. 此时回到 **微信客服后台/开发配置** 模块,点击「**开始使用**」 填入 **AppId** 后点击下一步,会跳转到企微扫码授权页面,该授权为通过云开发代理微信客服能力,从而代理客服进行回复,完成后企微则对接完成 ![](https://qcloudimg.tencent-cloud.cn/raw/be2171380d3902c8bcc72fed194b17ec.png) 3. 点击随机获取,生成对应的 **Token** 和 **EncodingAESKey**,此时需要填写 **回调URL**,先不要点完成,继续执行下一步 ![](https://qcloudimg.tencent-cloud.cn/raw/6ae6f0a9ab15734acec475a8fca1b906.png) 4. 将生成的 **Token** 和 **EncodingAESKey** 填回 agent 配置中,点击下一步 5. 此时会生成对应的回调地址,复制该回调地址到 **第3步** 的微信客服后台中填入 6. 填入回调URL,点击完成 ![](https://qcloudimg.tencent-cloud.cn/raw/9bbeda27a8f936cba80255a470ade362.png) 7. agent点击下一步,需要填入secret和客服名称 8. 在微信客服后台获取对应信息填入 **第7步** 中 9. agent点击完成即配置完成 10. 此时可以去企微客服进行测试,可以从 **开始接入** 中获取测试链接 **⚠️ 注意**:只有 **第8步** 录入 **客服账号名称** 的客服才被AI托管,因此测试和正式使用时需要指定客服账号名称 ![](https://qcloudimg.tencent-cloud.cn/raw/fd9f16039e1f9ca9bae88029e6f3db9f.png) 滑到下方选择 **在微信外App/网页中接入** ![](https://qcloudimg.tencent-cloud.cn/raw/be76fc2ba3c3fcfd877acdb8c7f0d7b7.png) 选择对应客服,点击生成二维码进行测试 ![](https://qcloudimg.tencent-cloud.cn/raw/b15c1effcd292ded9971e91595c26066.png) 测试案例: ## 注意事项 当前配置会接管企微客服,因此当前配置完成后 不要 在企微后台进行客服配置,否则会覆盖当前配置。 ![](https://qcloudimg.tencent-cloud.cn/raw/870d904ad66b83ad8290c0ac39371ff8.png) 若不慎把客服服务配置覆盖了,可以手动在 [**微信客服后台**](https://kf.weixin.qq.com/) 重新打开客服服务 ![](https://qcloudimg.tencent-cloud.cn/raw/af0098bef6f6c38cc80f122c3ef6e5f1.png) ## 优化建议 在 **Agent** 提示词增加如下设定,可以显著提升回复速度,测试时建议换一个微信号测试公众号的回复效果 **(更改提示词,历史回复可能会影响模型的输出)** - 智能体以极简风格回应问题 - 简化复杂问题的回答,提炼核心信息 - 严格限制回复内容的长度和相关性,避免冗余 - 不要输出 markdown 格式,直接输出纯文本 如果使用深度思考模型(如 **DeepSeek R1**),响应的时间会较慢,可以考虑使用 **混元模型** 或者 **DeepSeek V3** 模型。 如果希望更好的体验,可以考虑使用个性化页面嵌入 H5/小程序的形式,支持更好的对话体验 --- ## 知识库 # 知识库 ## 知识库是什么 知识库是指存储和组织大量结构化或非结构化信息的数据库或知识图谱。这些知识库包含各种类型的信息,如事实、概念、关系、规则等,用于帮助 AI 系统理解世界、回答问题、做出决策等任务。 知识库在 AI 中扮演着重要的角色,它们可以是专门为某一领域或任务构建的,也可以是通用知识库。一些知识库的例子包括: - 语言知识库:包含词汇、语法规则、语义关系等信息,帮助 AI 系统理解和生成自然语言。 - 领域知识库:包含特定领域的专业知识,如医学知识库、金融知识库等,用于支持相关领域的智能应用。 - 常识知识库:包含日常生活中的常识性信息,帮助 AI 系统做出符合逻辑的推理和决策。 知识库的建立和维护通常需要大量的人工工作和专业知识,但一旦建立完成,它们可以成为 AI 系统的重要资源,为 Agent 提供丰富的背景知识和信息支持,从而提高系统的智能水平和应用能力。 ## 如何构建知识库 ### 进入 AI+ 1. 进入 [云开发 AI+](https://tcb.cloud.tencent.com/dev?#/ai?tab=agent) 2. Agent 创建:[创建 Agent 实例](../agent/build) ### 创建知识库 通过创建知识库,并上传已收集的相关信息,可以构建私有知识库,并将知识库对接 Agent ,达到对 Agent 提供可用信息的目的,协助 Agent 进行更好的推理。 进入对应的 **Agent** 配置页面,点击知识库 ![](https://qcloudimg.tencent-cloud.cn/raw/8347343f7781095f1234b5fe5711f40b.png) 进入到知识库管理页面,点击添加按钮 ![](https://qcloudimg.tencent-cloud.cn/raw/1a7507bdcb61c4624ca37286d9539285.png) 点击新建,填写知识库名称和描述 ![](https://qcloudimg.tencent-cloud.cn/raw/20b1fb0989143ca355684e65c6ebfab9.png) 保存后可以看到所新建的知识库 ![](https://qcloudimg.tencent-cloud.cn/raw/a23ac9925c04efcfeaeec239b7f6e038.png) ### 上传内容 在创建知识库后,就可以在知识库中通过上传文件的方式来添加知识。 上传的文件格式目前支持如下: - markdown 格式编写的文本内容,文件后缀为 md - pdf 文件,文件后缀为 pdf - docx 文件,文件后缀为 docx ![](https://qcloudimg.tencent-cloud.cn/raw/022db7e03035f9832907549eb2cd2806.png) 文件上传后,可以在知识库中已经添加的文件信息。在文件添加后,会有一个解析和处理过程。在解析处理完成后,文件内的内容才会被 Agent 检索到。 ![](https://qcloudimg.tencent-cloud.cn/raw/7b3cbe13ae82fb744365fa03ec212499.png) ## 在 Agent 中使用 ```ts const msg = "用户问题" const knowledgeBase = ["知识库ID-1", "知识库ID-2"] const result = await this.botContext.bot.tools.searchKnowledgeBase( this.botContext.info.botId, msg, knowledgeBase ); if (result?.code && result?.code?.length !== 0) { throw new Error(`查询知识库内容失败: ${result?.message}`); } ``` ## 测试知识库查询效果 通过对话进行提问: 可开启 DeepSeek R1 模型,观察思维链中返回内容中包含知识库信息,证明测试结果正确,接下来按配置化定制 AgentUI 应用方案继续创建 [应用发布](../agent/release) 即可 ## 通过 API 管理知识库 可通过 API 实现知识库文档的自动化管理,支持创建、删除、批量操作等功能 [查看文档](https://cloud.tencent.com/document/api/1301/116428) ## 常见问题 知识库相关的问题,请参考[常见问题](https://docs.cloudbase.net/ai/FAQ#%E7%9F%A5%E8%AF%86%E5%BA%93%E7%9B%B8%E5%85%B3) --- ## MCP # MCP ## MCP 是什么 [MCP(Model Context Protocol)](https://modelcontextprotocol.io/introduction)是 Anthropic 开源的协议,旨在规范化 AI 应用向大语言模型(LLMs)提供上下文的方式。可以把 MCP 想象成 AI 应用的 USB-C 接口,就像 USB-C 为设备连接各种外设和配件提供了标准化方式一样,MCP 为 AI 模型连接不同的数据源和工具提供了标准化方式。 MCP 的核心采用 Client-Server 架构,一个应用程序可以连接多个 MCP Server。 只要 AI 应用实现了 MCP ,即可接入到任意的 MCP Server,扩展自身的能力。加入 MCP Server 后,工具调用的流程如下: ```mermaid sequenceDiagram participant AI as 👨‍💻 AI 应用 participant MCP as 🔌 MCP Server participant LLM as 🧠 大模型 AI->>+MCP: 请求工具列表 MCP-->>-AI: 返回工具列表 AI->>+LLM: Prompt + 可用工具列表 loop 如果需要工具调用 LLM->>+AI: 工具调用请求 AI->>+MCP: 转发工具调用请求 MCP->>MCP: 执行工具调用 MCP-->>-AI: 工具调用结果 AI-->>-LLM: 工具调用结果 end LLM-->>-AI: 文本响应 ``` 通过这种方式,MCP 实现了: 1. **即插即用**:AI 应用只需实现 MCP 协议,即可接入丰富的第三方工具生态 2. **标准化**:所有工具遵循统一的描述格式和调用方式 3. **解耦工具与应用**:工具提供者可以独立开发和维护工具,不需了解 AI 应用内部实现 4. **资源共享**:一次开发的工具可以被多个 AI 应用复用 ## 如何使用 MCP 云开发为 Agent 实现了 MCP 机制。Agent 可以连接到部署在云托管的 MCP Server,获得其提供的扩展能力。 1. 前往[云开发平台](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp)新建一个 MCP Server 2. 在 Agent 代码中使用 MCP 3. 开始对话,大模型判断需要使用工具时,就会自动调用了 更多使用方式,请阅读: - [在 MCP Host 中使用](../mcp/use/mcp-host) - [通过 SDK 接入](../mcp/use/sdk) ## 参考链接 - [云开发 MCP](../mcp/introduce) --- ## 多会话 # 多会话 Agent 允许用户拥有多个相互独立的会话,不同会话间的上下文互不影响。 ## 启用多会话 在云开发平台 AI+ 选择「云开发 Agent 模板」,在 bot-config.yaml 中开启 `multiConversationEnable: true` :::warning 注意事项 需要云开发标准版及以上才支持开启此功能 ::: ![创建Agent](https://qcloudimg.tencent-cloud.cn/raw/101789f6825af86a3013c8ccece73990.png) ![启用多会话](https://qcloudimg.tencent-cloud.cn/raw/49199d687261695e346f0634bb657a51.png) ## 体验 启用多会话后,可在右侧预览区进行体验。 新会话: 会话记录: ## 集成 用户可通过 Agent UI 组件、SDK、HTTP API 等方式集成多会话功能。 ### Agent UI 可视化低码组件、小程序源码组件、React 组件均内置多会话能力,具体用法可参考相关文档: - [可视化低码组件](../agent-ui/agent-ui.md) - [小程序源码组件](../agent-ui/agent-ui-mp.md) - [React 组件](../agent-ui/agent-ui-react.md) ### SDK 集成 初始化 SDK: ```js // 在 Web 项目的根目录下,使用 npm 或 yarn 安装所需的包: // npm i @cloudbase/js-sdk // 引入 SDK,这里我们引入了完整的 clousebase-js-sdk,也支持分模块引入 import cloudbase from "@cloudbase/js-sdk"; const app = cloudbase.init({ env: "your-env", // 需替换为实际使用环境 id }); const auth = app.auth(); await auth.signInAnonymously(); // 或者使用其他登录方式 const ai = app.ai(); // 接下来就可以调用 ai 模块提供的方法了 ``` 新建会话: ```js const res = await ai.bot.createConversation({ botId: "botId-xxx", title: "对话标题", }); ``` 发送消息时携带会话 ID: ```js const res = await ai.bot.sendMessage({ botId: "botId-xxx", history: [{ content: "你好", role: "user" }], msg: "你好", conversationId: "conversation-001", }); ``` 查询消息记录时携带会话 ID: ```js await ai.bot.getChatRecords({ botId: "botId-xxx", pageNumber: 1, pageSize: 10, sort: "asc", conversationId: "conversation-001", }); ``` 获取会话列表: ```js const res = await ai.bot.getConversation({ botId: "botId-xxx", pageSize: 10, pageNumber: 1, }); ``` 删除会话: ```js await ai.bot.deleteConversation({ botId: "botId-xxx", conversationId: "conversation-001", }); ``` 详细参考 [AI SDK 文档](../sdk-reference/api.md) ### HTTP API 集成 参考 [HTTP API 文档](../../http-api/ai-bot/create-conversation) --- ## 发布 小程序 # 发布 小程序 首先您需要创建一个 **agent**,若还没有创建,可前往 [创建Agent](./build) 参考创建流程 发布小程序需要如下几个步骤: - 注册小程序 - 小程序备案 - 自定义域名 - 发布 ## 注册小程序 登录 [微信公众平台](https://mp.weixin.qq.com/) 点击 **立即注册** 进行小程序注册 ![](https://qcloudimg.tencent-cloud.cn/raw/1d7c11dd7d85ea8e83e8d4107edbcffd.jpg) 选择 **小程序** ![](https://qcloudimg.tencent-cloud.cn/raw/c89bbb2ed748fcddabcf3fd109ca696d.png) 注意:每个邮箱仅能申请一个小程序 若您的小程序已经绑定了小程序,可以新注册个邮箱进行绑定 ![](https://qcloudimg.tencent-cloud.cn/raw/86c018ea3505c0f8630f777b77319405.png) 小程序注册完成后,即可进入到小程序后台 ![](https://qcloudimg.tencent-cloud.cn/raw/e255c46a679380d8398c04ce77fdf8ae.png) 此时需要先按要求完善小程序基本信息 ## 小程序备案 在发布 AI 智能体到小程序时,微信将在代码审核阶段核实小程序运营的内容与所选类目是否相符。AI 问答涉及深度合成技术,需补充 【深度合成-AI 问答】 服务类目 目前,个人主体小程序尚未开放深度合成相关服务类目,建议申请 **企业主体** 类型小程序。 对于个人客户,考虑到类目限制,建议使用 H5 或公众号(订阅号/服务号均可),或者小程序的客服消息等其他方式实现 AI 智能体的功能。 1. 确认您的小程序通过了**企业**认证 2. 确认您的环境有效期至少为 3 个月,此项非必须,但有助于您通过审核 3. 进入云开发平台[AI+概览页](https://tcb.cloud.tencent.com/dev#/ai?tab=home),点击帮助文档中的**小程序算法备案** ![](https://qcloudimg.tencent-cloud.cn/raw/5c2baa1d524af4ad39b2ba1ecdaf457f.png) 4. 填写您的小程序 AppID 和小程序主体名称 5. 平台将会为您生成算法备案资料 ![](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/991e1b53-108e-4f8b-9eeb-9699def55f4b.png) 6. 前往[微信开发者平台](https://mp.weixin.qq.com/),提交上一步生成的备案资料页的清晰截图 7. 您可以在服务类目中选择**深度合成**>**AI 问答/AI 换脸/AI 绘画** ## 自定义域名 上述流程完毕后,您的小程序即可正常发布 若您使用的是 **云开发平台** 进行开发的小程序,强制推荐使用 **自定义域名** 进行绑定小程序,防止官方域名被封,影响小程序运行 **相关文档:** - [绑定自定义域名](https://cloud.tencent.com/document/product/1301/70110) - [小程序绑定流程](https://cloud.tencent.com/document/product/1301/86886) ## 发布应用 进入 **云开发平台** 可视化应用,点击右上角发布,选择 **发布到小程序** 具体 **发布文档** 参考:[发布小程序](https://cloud.tencent.com/document/product/1301/55140) 发布完成后根据提供的链接或扫码进行访问 --- ## 发布 PC/H5 # 发布 PC/H5 首先您需要创建一个 **agent**,若还没有创建,可前往 [创建Agent](./build) 参考创建流程 ## 发布应用 **云开发平台** 支持三端发布,支持小程序、H5、APP 点击右上角发布,选择 **发布到web端**,即可发布 **PC/H5** 两端页面 若选择发布到小程序需要先绑定小程序 小程序发布完整流程参考 [AI 小程序发布全流程](./release-mp) **相关文档**: [小程序绑定流程](https://cloud.tencent.com/document/product/1301/86886) [小程序发布与部署问题](../FAQ#发布与部署) ![](https://qcloudimg.tencent-cloud.cn/raw/30b2b3968df58fac915a823b1ae37e05.png) 发布完成后根据提供的链接或扫码进行访问 --- ## Agent API # Agent API 当前 cloudbase sdk 中内置了 ai 模块,可以通过该模块调用 Agent ,实现与 Agent 的对话。 **在调用 Agent 之前,我们需要进行 SDK 初始化。请参考「[SDK 初始化](../sdk-reference/init)」进行操作。** 完成 SDK 初始化后,就可以调用 SDK,实现与 Agent 的交互了: 首先,查看已有的 Agent 列表: ```javascript const list = await ai.bot.list({ pageNumber: 1, pageSize: 10 }); console.log(list); ``` 在返回的 Agent 列表中,会展示 Agent 的 id、名称、设定等信息。在大部分 Agent 接口中,都是通过 Agent id 来指定要与哪个 Agent 进行交互。 接下来,我们将与选中的 Agent 进行对话: ```ts const res = await ai.bot.sendMessage({ botId: "botId-xxx", // 填入 Agent id msg: "你好", }); for await (let str of res.textStream) { console.log(str); } ``` 通过简洁的流式接口,我们完成了和 Agent 的对话交互。 除了简单的对话之外,我们还提供了其他非常有用的 Agent 接口。完整使用示例如下: ## 使用示例 ### 与 Agent 对话 :::tip 该接口为流式调用。 ::: ```ts const res = await ai.bot.sendMessage({ botId: "botId-xxx", msg: "给我一个成语。", }); for await (let str of res.textStream) { console.log(str); } // 当然 // 可以 // ! // 这里 // 有一个 // 成语 // : // // // ** // 画 // 蛇 // 添 // 足 // ** // // // 这个 // 成语 // 的意思 // 是指 // 画 // 蛇 // 时 // 给 // 蛇 // 添 // 上 // 脚 // , // 后 // 比喻 // 做了 // 多余 // 的事 // , // 非 // 但 // 无 // 益 // , // 反 // 而不 // 合适 // , // 也 // 比喻 // 虚构 // 事实 // , // 无 // 中 // 生 // 有 // 。 ``` 参考文档:[Bot.sendMessage()](../sdk-reference/api#sendmessage)。 ### 查看 Agent ```ts const res = await ai.bot.get({ botId: "botId-xxx" }); console.log(res); // { // "botId": "bot-809d4ad1", // "name": "智能体", // "agentSetting": "这是一个智能体", // "introduction": "简介", // "welcomeMessage": "欢迎欢迎", // "avatar": "http://xxx.avatar.image", // "background": "http://xxx.avatar.image", // "isNeedRecommend": false, // "knowledgeBase": [ // "" // ], // "initQuestions": [ // "请问有什么可以帮你的嘛?" // ], // "enable": true, // "type": "text", // "tags": [ // "" // ] // } ``` 参考文档:[Bot.get()](../sdk-reference/api#get)。 ### 查看与 Agent 的聊天记录 ```ts const res = await ai.bot.getChatRecords({ botId: "botId-xxx", pageNumber: 1, pageSize: 10, sort: "asc", }); // { // "recordList": [ // { // "botId": "bot-809d4ad1", // "recordId": "record-96617446", // "role": "user", // "content": "你好", // "conversation": "r3Hjz3qgms3UG7z9lwSYbA", // "type": "text", // "triggerSrc": "TCB" // }, // { // "botId": "bot-809d4ad1", // "recordId": "record-632906dd", // "role": "assistant", // "content": "您好!看起来您可能遇到了一些技术问题,或者只是想打个招呼。无论哪种情况,我都在这里为您提供帮助。如果您有任何具体的问题或需要协助,请随时告诉我!", // "conversation": "r3Hjz3qgms3UG7z9lwSYbA", // "type": "text", // "triggerSrc": "TCB" // } // ], // "total": 2 // } ``` 参考文档:[Bot.getChatRecords()](../sdk-reference/api#getchatrecords)。 ### 对某一条聊天记录进行反馈 ```ts await ai.bot.sendFeedback({ userFeedback: { botId: "botId-xxx", recordId: "recordId-xxx", comment: "我觉得你回答的很好", rating: 5, tags: ["切题"], aiAnswer: "李白是伟大的唐朝诗人。", input: "一句话介绍李白。", type: "upvote", }, }); ``` 参考文档:[Bot.sendFeedback()](../sdk-reference/api#sendfeedback)。 ### 查看反馈记录 ```ts await ai.bot.getFeedBack({ botId: "botId-xxx", }); // { // "feedbackList": [ // { // "comment": "dawd", // "botId": "bot-809d4ad1", // "aiAnswer": "ababa", // "createTime": "2024-09-10T07:03:45.000Z", // "input": "你不好", // "rating": 3, // "sender": "r3Hjz3qgms3UG7z9lwSYbA", // "tags": [], // "type": "downvote" // }, // { // "comment": "dwajoidaw", // "botId": "bot-809d4ad1", // "aiAnswer": "ababa", // "createTime": "2024-09-10T07:06:43.000Z", // "input": "你不好", // "rating": 2, // "sender": "r3Hjz3qgms3UG7z9lwSYbA", // "tags": [], // "type": "downvote" // } // ], // "total": 2 // } ``` 参考文档:[Bot.getFeedBack()](../sdk-reference/api#getfeedback)。 ### 获取 Agent 推荐问题 :::tip 该接口为流式调用。 ::: ```ts const res = await ai.bot.getRecommendQuestions({ botId: "botId-xxx", history: [{ content: "李白是谁", role: "user" }], msg: "你好", agentSetting: "", introduction: "", name: "", }); for await (let str of res.textStream) { console.log(str); } // 你是 // 做什么 // 的 // // 你能 // 提供 // 哪些 // 服务 // // 怎么 // 使用 // 你的 // 功能 ``` 参考文档:[Bot.getRecommendQuestions()](../sdk-reference/api#getrecommendquestions)。 ### 查看 Agent 列表 ```ts const list = await ai.bot.list({ pageNumber: 1, pageSize: 10 }); console.log(list); // { // "botList": [ // { // "botId": "bot-c033e89e", // "name": "智能体", // "agentSetting": "这是一个智能体", // "introduction": "简介", // "welcomeMessage": "欢迎欢迎", // "avatar": "http://xxx.avatar.image", // "background": "http://xxx.avatar.image", // "isNeedRecommend": false, // "knowledgeBase": [ // "" // ], // "initQuestions": [ // "请问有什么可以帮你的嘛?" // ], // "enable": true, // "type": "text", // "tags": [ // "" // ] // } // ], // "total": 1 // } ``` 参考文档:[Bot.list()](../sdk-reference/api#list)。 ## API 参考 详见[参考文档 | AI SDK](../sdk-reference/api)。 --- ## 自定义 MCP 工具卡片 # 自定义 MCP 工具卡片 :::tip 当前 **[Agent UI 小程序组件](../agent-ui/agent-ui-mp.md)** 与 **[Agent UI React 组件](../agent-ui/agent-ui-react.md)** 已支持工具卡片能力 ::: ## 1. 开通 MCP 能力 - 进入云开发平台 AI+ MCP 页面,点击创建MCP Server ![](https://qcloudimg.tencent-cloud.cn/raw/bc2a7815b542b26f5931aa835514dc37.png) - 若未开通过云托管服务,需先开通云托管 ![](https://qcloudimg.tencent-cloud.cn/raw/084b50f265e0335201801c3fb741d04d.png) ## 2. 配置 MCP Server - 以腾讯地图 MCP Server 举例,选择模板进行安装(按照指引获取腾讯地图平台API KEY后,配置环境变量) ![](https://qcloudimg.tencent-cloud.cn/raw/a5b15af9bfff83008257a0c99d252b83.png) ## 3. agent 绑定 MCP Server tools - 在 agent 配置页点击添加MCP 服务,选择对应的MCP Server tools 使用 (此处腾讯地图示例可勾选 geocoder,placeSearchNearby, directionDriving, weather等工具) ![](https://qcloudimg.tencent-cloud.cn/raw/b45a95e06ec0df8dab5c9d9ec7707faa.png) ## 4. 小程序组件 + 工具卡片 ### 4.1 实现 Agent UI customCard 组件 - 下载[项目示例源码包](https://gitee.com/TencentCloudBase/cloudbase-agent-ui/tree/main/apps/miniprogram-agent-ui),导入微信开发者工具 - 配置 Agent-UI 组件,[参考指引](../agent-ui/agent-ui-mp.md) - 在agent-ui customCard 组件(agent-ui/customCard/index.wxml) 中添加自定义逻辑,可根据不同 tool 类型渲染不同自定义组件 ![](https://qcloudimg.tencent-cloud.cn/raw/b4cd35ccaa3e72189934ed59d35f7ae5.png) 如图所示,示例中添加了腾讯地图自定义卡片组件的条件渲染 ### 4.2 自定义卡片组件开发 - 参照本工程中 apps/miniprogram-agent-ui/miniprogram/components/toolCard 目录内自定义腾讯地图卡片组件类似实现 ![](https://qcloudimg.tencent-cloud.cn/raw/14a4a82810f0b45bde0c124cc8f3ed1c.png) ### 4.3 自定义卡片组件引用配置 - 自定义卡片组件引用声明配置(可在用户小程序项目全局app.json中配置 或 agent-ui组件index.json中配置) ![](https://qcloudimg.tencent-cloud.cn/raw/cd1dc376a1e238f3186a2209e5875698.png) ### 4.4 卡片效果 ## 5. React 组件 + 工具卡片 ### 5.1 实现 Agent UI ToolCard 组件 - 访问示例[ Github 模板仓库](https://github.com/TencentCloudBase/cloudbase-agent-ui/tree/main/apps/react-agent-ui) 或[ Gitee 模板仓库](https://gitee.com/TencentCloudBase/cloudbase-agent-ui/tree/main/apps/react-agent-ui), 也可直接下载示例[资源包](https://weda.cloud.tencent.com/ai-resource/agent-ui/agent-ui-example.zip) - 配置 Agent UI 组件,下载示例代码后可拷贝 .env.example 文件并重命名为 .env 文件,填入对应配置 ![](https://qcloudimg.tencent-cloud.cn/raw/06e96cecdcd78f64e58195025a7a8256.png) - 参考示例中components/ToolCard 组件实现,可根据tool name 渲染不同自定义组件 ![](https://qcloudimg.tencent-cloud.cn/raw/c824c107efcb0c1f42c0f65ffb0a6eee.png) ### 5.2 自定义卡片组件开发 - 参考 ToolCard 组件同级目录中如 Weather, TencentMap 组件实现即可 ### 5.3 组件传入 - 使用 Agent-UI 组件时指定 toolCardComponent 属性为 ToolCard 组件即可 ![](https://qcloudimg.tencent-cloud.cn/raw/20a2092dba4f08d2cfcdcac741a0cea5.png) ### 5.3 卡片效果 - 查询某城市未来几天天气 ![](https://qcloudimg.tencent-cloud.cn/raw/99601e0751f47cae7dd61c6529321158.png) - 查询某城市地理位置 ![](https://qcloudimg.tencent-cloud.cn/raw/d5b18ff67ea54a9be6a54fc9faba54b5.png) - 查询某城市周边的加油站 ![](https://qcloudimg.tencent-cloud.cn/raw/015b315e065b82f73ba462c6cc3bd16b.png) - 查询某位置到某位置到驾车路线导航 ![](https://qcloudimg.tencent-cloud.cn/raw/9047193cf621833736524129d2ad8f75.png) --- ## 语音能力接入 # 语音能力接入 目前云开发提供的语音能力包括语音转文本(ASR),文本转语音(TTS),均基于腾讯云提供的语音相关 API 实现。 ## 语音识别介绍 > [腾讯云语音识别官方文档](https://cloud.tencent.com/document/product/1073) 提供语音转文字的产品功能,目前支持一句话识别场景(对60秒之内的短音频文件进行识别)([API参考](https://cloud.tencent.com/document/product/1093/35646)) **限制:** 1. 音频时长不能超过60s,音频文件大小不能超过3MB 2. 语音输入识别场景类型:中文通用/中英粤/中文医疗/英语/粤语 ## 语音合成介绍 > [腾讯云语音合成相关文档](https://cloud.tencent.com/document/product/1073) 提供文字转语音的产品功能,目前支持长文本语音合成场景(适合阅读,播报场景,支持文本长度灵活)([API参考](https://cloud.tencent.com/document/product/1073/57373)) **限制:** 1. 支持对10万字符以内的文本进行语音合成,异步返回音频结果 2. 语音音色类型:通用男声/通用女声/咨询男声/咨询女声/通用男声(大模型)/通用女声(大模型)/聊天男声/聊天女声/阅读男声/阅读女声 ## 如何使用 ### 1. 开通 在云开发平台 AI+ 选择「云开发 Agent 模板」,在 bot-config.yaml 中开启 `voiceSettings: true` :::warning 注意事项 需要云开发标准版及以上才支持开启此功能 ::: ![创建Agent](https://qcloudimg.tencent-cloud.cn/raw/101789f6825af86a3013c8ccece73990.png) ![启用语音功能](https://qcloudimg.tencent-cloud.cn/raw/a2cfff73906a0a1501df7484a7af936a.png) ### 测试 配置后在右侧预览区可实时体验,语音识别&文本转语音入口如图所示: ### 2. 通过组件/HTTP API/SDK 集成 #### 2.1 组件集成 - 低码组件内置语音能力,请[参考文档](../agent-ui/agent-ui.md)集成组件 - 小程序源码组件内置语音能力,请[参考文档](../agent-ui/agent-ui-mp.md)集成组件 - React 组件内置语音能力,请[参考文档](../agent-ui/agent-ui-react.md)集成组件 #### 2.2 HTTP API 集成 参考 [HTTP API 文档](../../http-api/ai-bot/speech-to-text) #### 2.3 SDK 集成 初始化 SDK: ```js // 在 Web 项目的根目录下,使用 npm 或 yarn 安装所需的包: // npm i @cloudbase/js-sdk // 引入 SDK,这里我们引入了完整的 clousebase-js-sdk,也支持分模块引入 import cloudbase from "@cloudbase/js-sdk"; const app = cloudbase.init({ env: "your-env", // 需替换为实际使用环境 id }); const auth = app.auth(); await auth.signInAnonymously(); // 或者使用其他登录方式 const ai = app.ai(); // 接下来就可以调用 ai 模块提供的方法了 ``` 语音转文本: ```js const res = await ai.bot.speechToText({ botId: "botId-xxx", engSerViceType: "16k_zh", voiceFormat: "mp3", url: "https://example.com/audio.mp3", }); ``` 文本转语音(发起异步任务): ```js const res = await ai.bot.textToSpeech({ botId: "botId-xxx", voiceType: 1, text: "你好,我是AI助手", }); ``` 查询文本转语音任务结果: ```js const res = await ai.bot.getTextToSpeechResult({ botId: "botId-xxx", taskId: "task-123", // 从文本转语音 textToSpeech 返回中获取 }); ``` 参考 [SDK 文档](../sdk-reference/api.md)方法使用 --- ## Agent UI 小程序组件 # Agent UI 小程序组件 Agent UI 小程序源码组件可以帮助开发者快速在微信小程序中搭建聊天界面。 Agent UI 提供以下功能: - 对接云开发大模型 - 对接云开发 Agent(智能体) :::tip 由于微信小程序基础库安全策略升级,文件上传功能解析流程可能受到影响,请开发者进行 agent ui 组件升级 - 小程序源码组件,请更新替换至最新版本 - 微搭低码组件,请新建页面然后重新拖动更新 agent-ui 区块,完成后发布应用 ::: ## 快速体验 方式一:在微信开发者工具入口中通过模板创建项目,按照模板指引,快速体验 Agent-UI 小程序源码组件。 ![](https://qcloudimg.tencent-cloud.cn/raw/9e7ce66913a90131071d84b3b8117635.png) 方式二:[下载项目示例源码包](https://gitee.com/TencentCloudBase/cloudbase-agent-ui/tree/main/apps/miniprogram-agent-ui) ,导入到微信开发者工具使用。 > 注意:项目示例包中需手动修改 app.json 中 env 配置为您的环境 ID,pages/chatBot/chatBot.js 中 botId 配置 为您的 agent ID ## 如何引入组件到已有微信小程序 ### 1. 拷贝 miniprogram/components/agent-ui 组件到小程序 ![image](https://qcloudimg.tencent-cloud.cn/raw/2fb0ff731e5fbded35b970589c9ec89d.png) ### 2. 在页面 .json 配置文件中注册组件 ```js { "usingComponents": { "agent-ui":"/components/agent-ui/index" }, } ``` ### 3. 在页面 .wxml 文件中使用组件 ```js ``` ### 4. 在页面 .js 文件中编写配置 ```js data: { chatMode: "model", // bot 表示使用agent,model 表示使用大模型 showBotAvatar: true, // 是否在对话框左侧显示头像 agentConfig: { botId: "bot-e7d1e736", // agent id, allowWebSearch: true, // 允许客户端选择启用联网搜索 allowUploadFile: true, // 允许上传文件 allowPullRefresh: true, // 允许下拉刷新 allowUploadImage: true // 允许上传图片 showToolCallDetail: true, // 是否展示工具调用细节 allowMultiConversation: true, // 是否展示会话列表,创建会话按钮 allowVoice: true // 是否允许客户端界面展示语音按钮 }, modelConfig: { modelProvider: "hunyuan-open", // 大模型服务厂商 quickResponseModel: "hunyuan-lite", // 大模型名称 (混元 turbo, gpt4 turbo版,deepseek v3等) logo: "", // model 头像 welcomeMsg: "欢迎语", // model 欢迎语 }, } ``` ### 5. 在 app.js 中,onLauch 生命周期内,异步初始化 sdk ```js // app.js App({ onLaunch: function () { wx.cloud.init({ env: "", }); }, }); ``` ## 组件参数和相关说明 ### 组件参数 | 参数名称 | 参数可选值 | 说明 | | :--------------------------------: | :---------------------: | :--------------------------------------------------------------------------------------------------------------------------------: | | chatMode | 'bot' 或 'model' | 当 chatMode='bot'时,agentConfig.botId 必填;当 chatMode='model'时,modelConfig.modelProvider 和modelConfig.quickResponseModel必填 | | showBotAvatar | boolean | 界面是否展示左侧头像 | | agentConfig.botId | string | agent id,当 chatMode = 'bot' 时,必填 | | agentConfig.allowUploadFile | boolean | 界面是否展示文件上传 | | agentConfig.allowWebSearch | boolean | 允许界面呈现联网配置开关 | | agentConfig.allowPullRefresh | boolean | 允许下拉刷新 | | agentConfig.allowUploadImage | boolean | 允许上传图片 | | agentConfig.allowMultiConversation | boolean | 是否展示会话列表,创建会话按钮 | | agentConfig.showToolCallDetail | boolean | 是否展示工具调用细节 | | agentConfig.allowVoice | boolean | 是否允许客户端界面展示语音按钮 | | modelConfig.modelProvider | 'hunyuan' 或 'deepseek' | 大模型服务商 | | modelConfig.quickResponseModel | string | 具体的模型版本, 参考[大模型版本](#大模型版本) | | envShareConfig.resourceAppid | string | 环境共享的资源方 AppID | | envShareConfig.resourceEnv | string | 环境共享的资源方环境 ID | ### 相关说明 ** 1. 文件上传说明 ** - **大小限制**:单文件不超过 10M - **数量限制**:单次最多支持 5 个文件 - **文件类型**:pdf、txt、doc、docx、ppt、pptx、xls、xlsx、csv - **request 合法域名配置**:微信小程序上传文件需要添加“文件上传接口”到 request 合法域名列表,文件上传域名为:https://{envid}.api.tcloudbasegateway.com,替换 envid 为真实的环境 ID, 前往微信公众平台[https://mp.weixin.qq.com](https://mp.weixin.qq.com)配置 request 合法域名 ** 2. 图片上传说明 ** 每次仅支持上传单张图片,最大不超过 30MB ** 3. 语音功能说明 ** 若未授予小程序使用麦克风权限,组件会进行权限申请,请同意授予 ### 示例 - **使用 deepseek-v3 模型** ```json { "chatMode": "model", // bot 表示使用agent,model 表示使用大模型 "showBotAvatar": true, // 是否在对话框左侧显示头像 "modelConfig": { "modelProvider": "deepseek", // 大模型服务厂商 "quickResponseModel": "deepseek-v3", //大模型名称 "logo": "", // model 头像 "welcomeMsg": "欢迎语" // model 欢迎语 } } ``` - **使用 deepseek-r1 模型** ```json data: { chatMode: "model", // bot 表示使用agent,model 表示使用大模型 showBotAvatar: true, // 是否在对话框左侧显示头像 modelConfig: { modelProvider: "deepseek", // 大模型服务厂商 quickResponseModel: "deepseek-r1", //大模型名称 logo: "", // model 头像 welcomeMsg: "欢迎语", // model 欢迎语 }, } ``` - **使用 Agent** ```js { chatMode: "bot", // bot 表示使用agent,model 表示使用大模型 showBotAvatar: true, // 是否在对话框左侧显示头像 agentConfig: { botId: "bot-e7d1e736", // agent id, allowWebSearch: true, // 允许客户端选择启用联网搜索 allowUploadFile: true, // 允许上传文件 allowPullRefresh: true, // 允许下拉刷新 allowUploadImage: true // 允许上传图片 showToolCallDetail: true, // 是否展示工具调用细节 allowMultiConversation: true, // 是否展示会话列表,创建会话按钮 allowVoice: true // 是否允许客户端界面展示语音按钮 } } ``` ## 获取 Agent ID ![](https://qcloudimg.tencent-cloud.cn/raw/cba2cfa73269dabe7c9067d5a27c67da.png) ## 大模型版本 ### hunyuan | 模型版本 | 说明 | | :----------: | :----------------------------------------------------------------------: | | hunyuan-lite | 具备强大的中文创作能力,复杂语境下的逻辑推理能力,以及可靠的任务执行能力 | ### deepseek | 模型版本 | 说明 | | :---------: | :------------------------------------------------: | | deepseek-v3 | 专注于自然语言处理、知识问答、内容创作等通用任务 | | deepseek-r1 | 推理模型,专为数学、代码生成和复杂逻辑推理任务设计 | ## 通过环境共享调用其他环境的 AI 能力 假设 A 小程序开通了云开发环境,B 小程序想跨环境调用 A 小程序云开发环境下的 AI 能力,可参照以下指引。 ### 开通环境共享 登录 A 小程序,开通环境共享,将 A 小程序的云开发环境共享给 B 小程序使用 > A 小程序和 B 小程序必须是同一个主体才能环境共享 ![](https://qcloudimg.tencent-cloud.cn/raw/9d7970656735c76429613055667beb48.png) ### 配置环境共享参数 在 B 小程序中使用 Agent-UI 时,将 A 小程序的 appid 和 envId 传给 Agent-UI 组件 参数如下: ```js data: { chatMode: "model", // bot 表示使用agent,model 表示使用大模型 showBotAvatar: true, // 是否在对话框左侧显示头像 modelConfig: { modelProvider: "deepseek", // 大模型服务厂商 quickResponseModel: "deepseek-v3", // 快速响应模型 (混元 turbo, gpt4 turbo版,deepseek v3等) logo: "", // model 头像 welcomeMsg: "欢迎语", // model 欢迎语 }, envShareConfig: { // 不使用环境共享,请删除此配置或配置EnvShareConfig:null // 资源方 AppID resourceAppid: "wx7a******5f4f", // 资源方环境 ID resourceEnv: "chr**************46d2d", }, }, ``` ## 自定义 MCP 工具卡片 参考[工具卡片开发指引](../agent/toolCard) --- ## Agent UI React 组件 # Agent UI React 组件 Agent UI React 组件基于腾讯云 Chat UI 及 Tea 组件设计规范打造,可以帮助开发者快速在 React 应用中搭建 AI 聊天界面。 Agent UI React 组件提供以下功能: - 对接云开发大模型 - 对接云开发 Agent(智能体) :::tip 由于 Agent UI React 组件依赖腾讯云 Tea 组件库,目前适配的 React 版本为17,18 ::: :::tip 开发环境 Node 版本依赖 >= Node.js v18 ::: ## 演示效果 **PC 尺寸效果** ![](https://qcloudimg.tencent-cloud.cn/raw/3e95c76b8b6ec2d3e521e2ff80949ab9.gif) **移动端 H5 尺寸效果** ## 快速体验 方式一:访问云开发 Agent UI Web React [在线应用示例](https://lowcode-6g4bqrjy45e3e14b-1300677802.tcloudbaseapp.com/agent-ui-example),直接体验 方式二:[下载 React 示例项目](https://weda.cloud.tencent.com/ai-resource/agent-ui/agent-ui-example.zip),本地调试体验。 ## 组件使用 ### 1. 安装依赖 ```bash // 安装云开发 @cloudbase/js-sdk,提供 Web 端访问云开发基础资源及 AI 相关能力 npm i @cloudbase/js-sdk // 安装本组件 npm i @cloudbase/agent-ui-react@1.0.0-beta.3 ``` ### 2. 引入组件 ```jsx import cloudbase from '@cloudbase/js-sdk'; import { useEffect, useState } from 'react'; const tcb = cloudbase.init({ // 需替换为实际使用云开发环境 id env: "your envId", }); export function YourComponent() { const [ready, setReady] = useState(false); useEffect(() => { auth.signInAnonymously().then(() => { setReady(true); }); }); if (!ready) { return null; } return ( ); } ``` **其中 agentConfig 参数结构如下:** | 参数名称 | 参数可选值 | 说明 | | :--------------------------------: | :---------------------: | :--------------------------------------------------------------------------------------------------------------------------------: | | chatMode | 'bot' 或 'model' | 当 chatMode='bot'时,agentConfig.botId 必填;当 chatMode='model'时,modelConfig.modelProvider 和modelConfig.quickResponseModel必填 | | showBotAvatar | boolean | 界面是否展示左侧头像 | | agentConfig.botId | string | agent id,当 chatMode = 'bot' 时,必填 | | agentConfig.allowUploadFile | boolean | 界面是否展示文件上传 | | agentConfig.allowWebSearch | boolean | 允许界面呈现联网配置开关 | | agentConfig.allowPullRefresh | boolean | 允许点击刷新 | | agentConfig.allowUploadImage | boolean | 允许上传图片 | | agentConfig.allowMultiConversation | boolean | 是否展示会话列表,创建会话按钮 | | agentConfig.showToolCallDetail | boolean | 是否展示工具调用细节 | | modelConfig.modelProvider | 'hunyuan' 或 'deepseek' | 大模型服务商 | | modelConfig.quickResponseModel | string | 具体的模型版本, 参考[大模型版本](#大模型版本) | ** 云开发平台开启对应能力 ** ![](https://qcloudimg.tencent-cloud.cn/raw/97d157613ce2c5c7dc41b79ce1d3d96c.png) ** 文档文件上传说明 ** - **大小限制**:单文件不超过 10M - **数量限制**:单次最多支持 5 个文件 - **文件类型**:pdf、txt、doc、docx、ppt、pptx、xls、xlsx、csv ** 图片文件上传说明 ** - **大小限制**:单张图片最大不超过 30MB - **数量限制**:单次最多支持 1 张图片 **直连大模型调用示例:** - **使用 deepseek 系列模型** ```json { "chatMode": "model", // bot 表示使用agent,model 表示使用大模型 "showBotAvatar": true, // 是否在对话框左侧显示头像 "modelConfig": { "modelProvider": "deepseek", // 大模型服务厂商 "quickResponseModel": "deepseek-v3", //大模型名称 支持 deepseek-v3/deepseek-r1/deepseek-v3-0324 "logo": "", // model 头像 "welcomeMsg": "欢迎语" // model 欢迎语 } } ``` - **使用 hunyuan 系列模型** ```json data: { chatMode: "model", // bot 表示使用agent,model 表示使用大模型 showBotAvatar: true, // 是否在对话框左侧显示头像 modelConfig: { modelProvider: "hunyuan-exp", // 大模型服务厂商 quickResponseModel: "hunyuan-lite", //大模型名称 支持 hunyuan-lite/hunyuan-turbos-latest/hunyuan-t1 logo: "", // model 头像 welcomeMsg: "欢迎语", // model 欢迎语 }, } ``` **使用 Agent 调用示例:** ```js { chatMode: "bot", // bot 表示使用agent,model 表示使用大模型 showBotAvatar: true, // 是否在对话框左侧显示头像 agentConfig: { botId: "your botid", // agent id, allowWebSearch: true, // 允许客户端选择启用联网搜索 allowUploadFile: true, // 允许上传文件 allowPullRefresh: true, // 允许下拉刷新 allowUploadImage: true // 允许上传图片 showToolCallDetail: true, // 是否展示工具调用细节 allowMultiConversation: true, // 是否展示会话列表,创建会话按钮 } } ``` ## 获取云开发环境 ID ![](https://qcloudimg.tencent-cloud.cn/raw/b8d5eb37077c3c1c63bfbc4d5e91f2d0.png) ## 获取 Agent ID ![](https://qcloudimg.tencent-cloud.cn/raw/cba2cfa73269dabe7c9067d5a27c67da.png) ## 大模型版本 ### hunyuan | 模型版本 | 说明 | | :-------------------: | :-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | | hunyuan-lite | 具备强大的中文创作能力,复杂语境下的逻辑推理能力,以及可靠的任务执行能力 | | hunyuan-turbos-latest | 混元 Turbo S 能够实现“秒回”,更快速输出答案,吐字速度提升一倍,首字时延降低44%。最大输入24k,最大输出8k。预训练底座训练token 数升级;数学/逻辑/代码等思考能力提升;中英文通用体验效果提升,包括文本创作、文本理解、知识问答、闲聊等 | | hunyuan-t1 | 腾讯首个深度推理模型 Hunyuan-T1,该模型基于3月初发布的业界首个超大规模 Hybrid-Transformer-Mamba MoE 大模型 TurboS 快思考基座,扩展了推理能力,超强解码速度,进一步对齐人类偏好。 | ### deepseek | 模型版本 | 说明 | | :--------------: | :-------------------------------------------------------------------------------------------------: | | deepseek-v3 | 专注于自然语言处理、知识问答、内容创作等通用任务 | | deepseek-r1 | 推理模型,专为数学、代码生成和复杂逻辑推理任务设计 | | deepseek-v3-0324 | 相比 DeepSeek-V3 大幅提高了推理任务表现,增强了前端开发能力,升级了中文写作能力,优化了中文搜索能力 | --- ## Agent UI 微搭可视化组件 # Agent UI 微搭可视化组件 Agent UI 可以帮助开发者快速搭建聊天界面,并集成到微信小程序、H5、web 场景中。 Agent UI 提供以下功能: - **Agent 会话组件:** 提供对接 Agent 服务的组件,支持对接 Agent 服务的会话能力。 - **用户反馈:** 提供用 户反馈弹窗,用于提交用户反馈,优化 Agent 服务质量。 :::tip 由于微信小程序基础库安全策略升级,文件上传功能解析流程可能受到影响,请开发者进行 agent ui 组件升级 - 小程序源码组件,请更新替换至最新版本 - 微搭低码组件,请新建页面然后重新拖动更新 agent-ui 区块,完成后发布应用 ::: ## 使用说明 ### 创建 Agent 在 Agent 管理页面,点击创建 Agent 按钮,创建 Agent,并 配置 Agent 的信息。 复制 Agent ID ,用于 Agent UI 区块配置 。 ### 添加 Agent UI 在公共区块中搜索 Agent UI ,并添加到当前页面。 ![](https://qcloudimg.tencent-cloud.cn/raw/cd4d3b88653566d6b8d137db31a3d254.png) ### 配置 Agent ID 点击 Agent UI 区块,配置 Agent ID , Agent ID 可以从 AI + -> Agent -> 具体的 Agent 详情页面复制 ![](https://qcloudimg.tencent-cloud.cn/raw/0d8fcd2f85273a0ee17a2d4c7ea7eab5.png) 完成以上配置,Agent UI 就已经配置好了,并且展示完整的聊天界面。 ### 发布到云开发平台 可视化构建 **Agent UI** 应用参考如下文档:[发布 Agent 应用](../agent/release) ### 集成到微信小程序 Agent UI 集成到微信小程序场景中,需要下载 Agent UI 的代码包,引入到微信小程序中,并配置 Agent ID。建议使用[分包方式集成](#通过小程序分包集成)。 1、进入任意微搭应用 2、下载代码包 在右侧区块中搜索 Agent UI ,并下载代码包。 ![](https://qcloudimg.tencent-cloud.cn/raw/5a832b4042b76939a18362e0d1b71af7.png) 3、解压并添加到小程序目录中 解压 Agent UI 代码包,会得到 components 文件夹,方便区分,这里将文件夹名改为 agent_ui,并将代码包添加到小程序目录 miniprogram 中。 小程序目录结构如下: ![](https://qcloudimg.tencent-cloud.cn/raw/bbbfe3f659bae570af7e175333101c4f.png) 4、安装依赖 在 miniprogram 文件夹上右键,在终端中打开,执行 npm 命令:npm install ./agent_ui > 注意:agent_ui 需要替换成第三步重命名的文件夹名。 ![](https://qcloudimg.tencent-cloud.cn/raw/832cbc065b07ad4303d3a4a4db8a5efd.png) ![](https://qcloudimg.tencent-cloud.cn/raw/a0f2019e6b4ef014f3dba1940d898acd.png) 构建 npm 点击小程序 工具 菜单栏,选择构建 npm ![](https://qcloudimg.tencent-cloud.cn/raw/e8e1c27f1fc8cf212e402ad1cf6e64b1.png) 5、初始化 SDK 在小程序 app.js 顶部初始化 weda-client。 envID 和 staticResourceDomain 可以在下载代码包的弹窗中获取。 ![](https://qcloudimg.tencent-cloud.cn/raw/8d9a76991c805fcbd6fdbcce0af04c8f.png) ```js import { init } from "@cloudbase/weda-client"; init({ envID: "xxx", // 云开发环境Id appConfig: { staticResourceDomain: "xxx.tcloudbaseapp.com", // 云开发环境下静态托管域名,用于使用素材资源 }, customConfig: { async login({ app, auth, loginState, defaultLogin }) { await auth.signInWithOpenId(); }, loginConfig: { needSignIn: true }, }, }); ``` 6、页面引用添加区块 注册 agent_ui 组件 在 pages/index 页面中注册 agent_ui 组件 ![](https://qcloudimg.tencent-cloud.cn/raw/6aa97352bcca054c0b1c4cb9fc37f0ab.png) 添加 agent_ui 组件到页面 在 pages/index 页面中添加 agent_ui 组件 ![](https://qcloudimg.tencent-cloud.cn/raw/40cbd533475131cdfee7333beb1177bc.png) > 注意:agent_ui 组件需要放在 id="wd-page-root"的 view 下。 配置 agent ID 在 pages/index 页面中配置 agent ID ![](https://qcloudimg.tencent-cloud.cn/raw/33a58945f13433719cbcc2484b24dc0d.png) ### 通过小程序分包集成 由于 Agent UI 依赖复杂,体积可能较大,我们推荐使用小程序子包的形式来引入。假设代码包解压至小程序项目中 `agent_ui` 目录,目录下包含 `dist`、`package.json` 等文件。 #### 1. 安装依赖包 可以直接下载最新的[预安装包](https://weda.cloud.tencent.com/ai-resource/agent-ui.zip),安装包中已完成 miniprogram 构建,可跳过该步骤。 1. 在 `agent_ui` 目录下执行命令,安装依赖: ```bash npm install ``` 1. 配置多目录 miniprogram_npm 编译。假设小程序 `project.config.json` 与 `app.json` 同级(即:miniprogramRoot 为根目录),配置 `project.config.json`, 中 setting 配置 ```json { "setting": { /* ... */ "packNpmManually": true, "packNpmRelationList": [ /* 如项目自身也需要 package.json,可添加配置 /* { "packageJsonPath": "package.json", "miniprogramNpmDistDir": "./" }, */ /* 路径和目录名以实际为准 */ { "packageJsonPath": "agent_ui/package.json", "miniprogramNpmDistDir": "agent_ui" } ] } } ``` 1. 构建 npm。在微信开发工具,操作栏上选择 `工具 - 构建 npm`,等待构建出 miniprogra_npm。 #### 2. 配置分包 修改 `app.json`,在 subpackages 中添加分包配置,和外部依赖库配置 ```json { "useExtendedLib": { "weui": true }, "subpackages": [ /* ... */ { "root": "agent_ui", "name": "agent-ui", "pages": [] } ] } ``` 同时在 `project.config.json` 中 `setting` 配置中添加过滤无依赖文件设置: ```json { "setting": { /* 添加下述配置 */ "ignoreDevUnusedFiles": true, "ignoreUploadUnusedFiles": true } } ``` #### 3. 初始化 SDK 使用组件前需要进行 sdk 初始化,由于整体存在于分包中,有两种初始化选择。 1. 在分包中初始化,可以保证组件在使用时,sdk 一定初始化完成,保证时序。 在`agent_ui`目录下创建 `index.js` 文件: ```js import * as ClientSDK from "@cloudbase/weda-client"; ClientSDK.init({ envID: "xxx", // 云开发环境Id }); ``` 在 agent_ui/dist/xxx/index.js 组件头部添加引用 `import '../../index'`,使组件在加载时立即初始化 sdk。 1. 在主包中初始化,需要保证组件使用在初始化完成之后。 在`agent_ui` 目录下创建 `index.js` 文件: ```js export * as ClientSDK from "@cloudbase/weda-client"; ``` 在 app.js 中,onLauch 生命周期内,异步初始化 sdk ```js require.async("./agent_ui/index").then((module) => { module.ClientSDK.init({ envID: "xxx", // 云开发环境Id }); }); ``` #### 4. 在小程序中使用组件 由于使用了分包,引用组件的方式有一些不同。 1. 在 page `index.json` 中引用组件,由于分包异步化,需要配置 componentPlaceholder: ```json { "usingComponents": { "chat": "/agent-ui/dist/Agent-UI/index" }, "componentPlaceholder": { "chat": "block" } } ``` 1. 在 `index.wxml` 中使用组件,注意组件外层需要有 id 为 `wd-page-root` 的组件 ```wxml ``` ### 小程序合法域名处理 如在微搭低代码和小程序中使用 agent ui,发布小程序后,提示`request 合法域名校验出错`,需要前往小程序管理后台配置合法域名。 ![](https://qcloudimg.tencent-cloud.cn/raw/99d63803eeb965a8acd553b533294094.png) 将报错的域名添加到合法域名列表中。 > 如果是授权给微搭的小程序,提示禁用域名配置,可以先在微搭解绑小程序,配置完合法域名后,在绑定到微搭。 ![](https://qcloudimg.tencent-cloud.cn/raw/2f5a59a0e1363d2e5df606613a6a834d.png) ## 属性 区块接收外部传入的属性。 | 属性名称 | 属性标识 | 类型 | 描述 | | --------- | -------- | ------ | -------------- | | 智能体 ID | `botId` | String | 必填,Agent ID | ## 实现细节 Agent UI 区块组件基于可视化技术搭建,为了便于开发者自定义,这里详细描述其中的实现细节,便于开发者自行调整逻辑。 使用 Agent UI 只需配置 Agent ID ,配置 Agent ID 后,Agent UI 会自动加载 Agent ID 对应的 Agent 配置,Agent 加载和会话流程如下。 ### 内部数据交互 初始化 Agent 阶段: - 查询 Agent ID 对应的 Agent 信息 - 加载 Agent 聊天记录 - 初始化 Agent 会话 会话阶段: - 发起 Agent 会话 - 流式加载 Agent 响应 - 查询建议问题 ### 区块 query 和事件说明 | 名称 | 描述 | | --------------------------------------- | ---------------------------------------- | | $w.queryBotById | 根据 Agent UI 配置的 ID 来查 Agent | | $w.queryChatRecords | 查询聊天记录,在 queryBotById 完成后调用 | | $w.sendMessage | 发送消息 | | $w.page.handler.queryRecommendQuestions | 查询推荐问题 | | $w.submitFeedback | 提交用户反馈 | --- ## 可视化组件多 Agent 示例 # 可视化组件多 Agent 示例 Agent UI 区块基础用法参见 [Agent UI 微搭可视化组件](.)。 下面示例如何基于 Agent UI 实现多 Agent 自由切换。 ## 新建 Agent 列表 首先将 Agent UI 区块添加到当前页面。 在左下角代码区新建 `agentList` 变量,用以存储 Agent 列表。修改变量类型为数组,并输入默认值。默认值中的 `id` 和 `name` 替换为自己的 agent 信息,可根据需求调整数量。 ![](https://qcloudimg.tencent-cloud.cn/raw/20b0b04e722a17ed6410cd3acc7e4156.png) ## 修改区块配置 将区块的默认 Agent ID 修改为 `$w.page.dataset.state.agentList[0].id`,即默认使用第一个 Agent。 ![](https://qcloudimg.tencent-cloud.cn/raw/e6e095402c7a51051666746ab518dcf8.png) ## 添加下拉单选组件 ### 引用组件 删除原来的顶栏标题,在右侧 添加-组件 中找到下拉单选组件,添加到原来标题的位置。 ![](https://qcloudimg.tencent-cloud.cn/raw/a3a7a180327727e6ec497ed2414b55ca.png) ### 修改配置 在左侧选中下拉单选组件,在右侧配置区绑定之前定义的 `agentList` 变量,修改 `选项名称` 和 `选项值`,并修改 `选中值` 为 `$w.page.dataset.state.agentList[0].id`,即默认选中第一个 agent。可根据需求调整其他配置,详细用法参见 [下拉单选组件](https://docs.cloudbase.net/lowcode/components/wedaUI/src/docs/compsdocs/form/WdSelect)。 ![](https://qcloudimg.tencent-cloud.cn/raw/59a21a659afbb64be83535102d99faf0.png) ### 绑定事件 点击右下方 `值改变`,执行动作选择 `JavaScript 代码`。 ![](https://qcloudimg.tencent-cloud.cn/raw/ecd560dbb28a16acb36ce57ee6ffaccc.png) 输入下方代码,**注意此处的 `container22` 需要改为自己的区块组件 ID**,右键点击组件,可复制组件 ID。 ```js ({ event }) => { // 此处 container22 需要改为你自己区块的组件 id $w.container22.data.bot.botId = event.detail.value; }; ``` ![](https://qcloudimg.tencent-cloud.cn/raw/5c375fd0849ed17e6de376ddf16cfc3a.png) 此时,点击下拉单选组件,即可选择不同 Agent 自由切换。 ![](https://qcloudimg.tencent-cloud.cn/raw/311b94f145610b2b8bd2fa2d83bd9a34.gif) ## 拓展/优化 ### 样式优化 按照上面的步骤完成后,标题栏并未居中对齐。这是因为下拉单选组件使用了 `input` 标签渲染选项,而 `input` 标签不会根据内容自适应宽度,导致组件的实际宽度和文本宽度不一致。 该问题无法直接通过 `width: auto` 解决,需要用一个占位元素撑开父盒子的宽度,而后将下拉单选组件宽度设置 `100%`,并通过定位覆盖占位元素。可参考如下思路: ```html 这是一段文本 ``` 示例使用下拉选择进行 agent 切换,实际使用可根据需求改为其他形式,如菜单列表、侧边栏等。 ### 动态数据 上面的示例中,`agentList` 及每一项的 `id` 和 `name` 是固定不变的,这意味着每次更新 Agent 名称后,都要手动修改变量。 要避免该问题,可以仅记录每个 Agent 的 ID,在每次进入页面后,手动查询 Agent 信息列表。 ```js // 示例代码 async () => { const ids = [ 'botid-1', 'botid-2', ] const agentList = await Promise.all( ids.map((botId) => $w.app.ai.bot.get({ botId })), ) if (agentList.some((item) => !!item.code)) { console.log('获取失败', agentList) return } console.log('获取成功', agentList) } ``` 同样的,如果想要在后台管理维护可用的 Agent 列表,可以通过自定义[云函数](/cloud-function/introduce)获取。 异步获取数据的话,在请求完成之前,`agentList` 为空数组,此时 Agent UI 会报错缺少 Agent ID,要防止报错,可以给 Agent UI 添加条件渲染: ![](https://qcloudimg.tencent-cloud.cn/raw/3a4f8be1e9b270e335295d70682df0ee.png) ## 总结 要基于 Agent UI 实现多 Agent 切换,流程主要分为两个步骤: 1. 获取 Agent 列表。 2. 切换 Agent 并更新区块的 Agent ID。 更多自定义样式和业务逻辑可根据需求自行调整。 --- ## 应用发布 # 应用发布 应用发布是将 AI Builder 应用从开发环境迁移到正式环境的过程。发布后,应用将对所有用户可见,用户可以通过域名访问应用。 ## 概述 在 Builder 会话页,点击上方菜单栏“发布”按钮,进入应用发布页面。 应用发布包含以下关键环节: - 🌐 **选择发布环境**: 正式版与体验版应用的访问地址不同、数据隔离,体验版可用于测试体验,正式版作为最新线上版本对外发布 - 🔒 **选择数据版本**:选择发布数据的版本 - 👥 **域名选择**:设置发布的域名 ### 域名配置 **使用默认域名**: ``` # AI Builder 提供的默认域名格式 https://envId-appId.tcloudbaseapp.com ``` **绑定自定义域名**: 可以在云开发平台中绑定[自定义域名](https://tcb.cloud.tencent.com/dev?#/env/http-access) 添加域名了,您可以在发布选项中选择自定义域名。 --- ## 细节编辑 import selectIcon from './select.svg' # 细节编辑 ## 概述 细节编辑是一个迭代优化的过程,让您能够通过可视化界面对 AI 生成的应用进行精细调整。通过细节编辑,您可以将初步的应用原型打磨成符合实际需求的完整产品。 主要编辑范围包括: - 🎨 **界面优化**:精确调整布局、颜色、字体等视觉元素,提升用户体验 - 🔧 **功能完善**:添加或修改具体功能细节,增强应用实用性 - 📱 **交互改进**:优化用户操作流程和交互体验,提高易用性 - 🔗 **数据绑定**:配置组件的数据来源和事件处理逻辑 ## 编辑入口 细节编辑提供了多个便捷的入口: - **对话框编辑**:在对话框内点击「编辑」按钮 - **组件选择**:在预览区点击 ![选择组件示意图](./select.svg) 图标选择组件进行编辑 ## 编辑方式 AI Builder 提供了两种互补的编辑方式,您可以根据需求灵活选择: ### AI 对话编辑 在选中组件的下方输入框内,输入对应的修改的需求,Builder 会根据您的描述进行修改。 :::tip 提示:AI 对话编辑能够实现事件绑定,及数据来源的更换,如果您仅需要更换样式,请使用手动编辑,将会更加准确和快捷。 ::: 例如,选中按钮后,更改事件,例如: ``` 添加点击事件,点击后弹出提示框 ``` Builder 会根据您的描述,添加点击事件,点击后弹出提示框。 ### 手动编辑模式 手动编辑模式下,您可以直接在对话框上的样式输入框进行编辑,无需输入自然语言描述。 根据组件不同,可供编辑的样式属性如下: | 属性类型 | 属性名称 | 说明 | | -------- | ------------------ | ---------------------- | | 间距属性 | padding | 内边距设置 | | 间距属性 | margin | 外边距设置 | | 颜色属性 | color | 文字颜色 | | 颜色属性 | background | 背景颜色/图片 | | 字体属性 | font-size | 字体大小 | | 字体属性 | font-weight | 字体粗细 | | 边框属性 | border-radius | 圆角设置 | | 高级设置 | 任意 tailwind 类名 | 自定义样式 | | 内容属性 | 填充文本 | 静态文本内容 | | 图片资源 | 图片地址 | 图片地址,仅限 img 标签 | ## 最佳实践 ### ✅ 推荐做法 1. **渐进式优化**:先完善核心功能,再优化细节 2. **保持一致性**:统一的设计风格和交互模式 3. **及时预览**:每次修改后及时预览效果 4. **记录变更**:重要修改要记录,便于回滚 ### ❌ 避免的做法 1. **过度设计**:避免不必要的复杂效果 2. **不一致性**:同类元素使用不同的样式 3. **频繁大改**:避免推翻重来式的修改 ## 常见问题 ### Q: 修改后的效果不满意,如何撤销? A: 可以使用回滚功能,重新描述期望的效果让 AI 重新生成。 ### Q: 可以添加自定义的 CSS 样式吗? A: 可以通过样式编辑器添加自定义样式,或在 Dev Mode 中进行高级定制。 ## 下一步 完成细节编辑后,如果需要更高级的代码定制,可以进入 Dev Mode: 🛠️ **[进入 Dev Mode 代码编辑 →](./dev-mode.md)** 或者如果当前效果满意,可以直接进行资源发布: 🚀 **[开始资源发布 →](./resource-publish.md)** --- ## Dev Mode 代码编辑器 # Dev Mode 代码编辑器 Dev Mode 是 AI Builder 提供的高级代码编辑环境,允许开发者直接编辑生成的代码,进行深度定制和高级功能开发。 ## 概述 Dev Mode 为有编程经验的用户提供了完整的代码编辑能力,您可以: - 📝 **直接编辑代码**:修改前端、后端和数据库代码 - 🔧 **添加自定义功能**:实现 AI 无法生成的复杂逻辑 - 🐛 **调试和优化**:进行代码调试和性能优化 ## 进入 Dev Mode ### 启动方式 在会话中点击右上角「Dev Mode」滑块按钮,即可进入 Dev Mode 代码编辑器。 ### 环境准备 进入 Dev Mode 前,系统会自动: - 生成完整的项目代码结构 - 配置开发环境和依赖 - 启动本地开发服务器 - 同步云端资源配置 ## 代码编辑器界面 ### 主要区域 1. **文件浏览器**:项目文件目录树 2. **代码编辑区**:主要的代码编辑界面 3. **终端控制台**:命令行操作和日志输出 4. **预览窗口**:实时预览应用效果 5. **调试面板**:断点调试和变量监控 ### 编辑器特性 - **语法高亮**:支持多种编程语言 - **智能补全**:代码自动补全和提示 - **错误检查**:实时语法和逻辑错误检查 - **代码格式化**:自动代码格式化和美化 - **快捷键支持**:丰富的编辑快捷键 ## 项目结构 > **⚠️ 在线编辑重要提示:可编辑范围** > > **支持保存的文件**: > > - `src/components/` 目录下的组件(不包括 `ui` 子目录) > - `src/page/` 目录下的页面文件 > 其他文件也可修改调试,但不会同步到 AI ,您可以下载代码获取编辑器内的修改。 > > **文件保存** > > 编辑完成后,**必须**点击右上角切回 Agent 模式,否则在退出后所有修改都将被舍弃! ### 支持编辑的前端项目结构 ``` ├── src/ │ ├── components/ # 组件目录 │ ├── pages/ # 页面目录 ``` ### 后端项目结构 ``` ├── / ├── .datasources/ # 数据模型目录 ├── .functions/ # 云函数目录 ``` ## 调试和测试 ### 环境要求 - Node.js (推荐 16.x 或更高版本) - Yarn 包管理器 ### 安装依赖 ```bash # 安装 yarn (如果尚未安装) npm install -g yarn # 安装项目依赖 yarn install ``` ### 启动开发服务器 ```bash yarn run dev ``` 启动后,项目将在本地开发服务器上运行,通常可以通过 `http://localhost:8080` 或其他端口访问。 ## 下一步 完成代码开发和调试后,可以进行资源发布: 🚀 **[开始资源发布 →](./resource-publish.md)** 或者如果需要版本管理,可以先设置 Git: 📝 **[配置 Git 管理 →](./git-management.md)** --- ## 常见问题 FAQ # 常见问题 FAQ ## 问题提交优化建议 如问题仍未解决或有建议,请前往 CloudBase 社区提交 [issue](https://cnb.cool/tencent/cloud/cloudbase/community/-/issues) ## 相关问题自查 ### 数据源 = ai_bot_chat_history_5hobd2b 不存在 该问题是因为您手动删除了 ai_bot_chat_history_5hobd2b 数据模型,该模型用于存储会话历史数据,数据无法恢复,您可以新建一个会话,系统会自动新建该模型(但数据无法找回)。 --- ## 后端服务生成 # 后端服务生成 在完成前端页面设计后,AI Builder 可以为您的应用自动生成对应的云开发后端服务,包括数据模型和云函数。这个阶段需要您为每个页面指定所需的后端服务。 ## 概述 后端服务生成是将前端界面与云开发后端能力连接的关键步骤。AI Builder 会根据您的页面功能需求,自动生成: - 📊 **数据模型**:根据页面数据需求设计数据库表结构 - ⚡ **云函数**:为页面功能提供后端 API 接口 - 🔗 **数据绑定**:建立前端组件与后端数据的连接关系 - 🛡️ **权限控制**:配置数据访问权限和安全规则 ## 服务配置流程 ### 1. 页面服务分析 首先,AI Builder 会分析您的前端页面,识别需要后端服务的功能模块: - **数据展示组件**:列表、表格、卡片等需要数据源的组件 - **表单组件**:需要数据提交和处理的表单 - **交互功能**:搜索、筛选、排序等需要后端逻辑的功能 - **用户操作**:登录、注册、权限验证等用户相关功能 ### 2. 服务需求输入 对于每个识别出的功能模块,您需要描述具体的服务需求: #### 数据模型需求 ``` 示例:用户管理页面 需要的数据字段: - 用户ID(主键) - 用户名(字符串,唯一) - 邮箱(字符串,唯一) - 创建时间(时间戳) - 用户状态(枚举:活跃/禁用) ``` #### 云函数需求 ``` 示例:用户列表页面 需要的接口功能: - 获取用户列表(支持分页) - 搜索用户(按用户名或邮箱) - 更新用户状态 - 删除用户 ``` ### 3. 自动生成服务 基于您的输入,AI Builder 会自动生成: #### 数据模型 - **数据库表结构**:根据字段需求创建数据表 - **索引配置**:为查询字段自动添加索引 - **关联关系**:处理表与表之间的关联关系 - **数据验证**:设置字段验证规则 #### 云函数代码 - **CRUD 操作**:创建、读取、更新、删除数据的基础函数 - **业务逻辑**:根据功能需求实现特定的业务逻辑 - **数据处理**:数据格式化、验证、转换等处理逻辑 - **错误处理**:完善的错误处理和异常捕获机制 ### 3. 服务部署 生成服务后,您需要将本次会话的服务部署到云开发环境中: - **数据库部署**:将数据模型部署到数据库中 - **云函数部署**:将云函数代码部署到云开发环境中 - **服务配置**:配置云函数的触发条件、权限设置等 ### 4. 应用接入服务 在服务发布后,需要将应用的 mock 数据改换成真实的服务。 例如: - **数据模型**:将 XXX 页面的 XXX mock 数据模型替换为真实的数据库表结构 - **云函数**:将 XXX 页面的 XXX mock 云函数替换为真实的云函数代码 ## 服务配置示例 ### 示例 1:博客文章管理 **页面功能**:文章列表、文章详情、文章编辑 **服务需求描述**: ``` 数据模型: - 文章表:ID、标题、内容、作者ID、创建时间、更新时间、状态 - 分类表:ID、分类名称、描述 - 标签表:ID、标签名称 云函数需求: - 获取文章列表(支持分页、分类筛选) - 获取文章详情 - 创建/更新文章 - 删除文章 - 获取分类列表 - 获取标签列表 ``` ### 示例 2:电商商品管理 **页面功能**:商品列表、商品详情、购物车、订单管理 **服务需求描述**: ``` 数据模型: - 商品表:ID、名称、价格、库存、描述、图片、分类ID - 订单表:ID、用户ID、总金额、状态、创建时间 - 订单详情表:ID、订单ID、商品ID、数量、单价 云函数需求: - 商品列表查询(支持搜索、分类筛选、价格排序) - 商品详情获取 - 购物车操作(添加、删除、更新数量) - 订单创建和查询 - 库存管理 ``` ## 配置要点 ### 1. 数据模型设计 - **字段类型**:明确每个字段的数据类型(字符串、数字、布尔值、时间等) - **约束条件**:设置必填、唯一、长度限制等约束 ### 2. 云函数设计 - **参数验证**:对输入参数进行严格验证 - **权限控制**:根据用户角色控制数据访问权限 ### 3. 安全考虑 - **数据验证**:对所有用户输入进行验证和过滤 - **权限控制**:实现细粒度的权限控制机制 - **数据加密**:对敏感数据进行加密存储 - **访问限制**:设置合理的访问频率限制 ## 生成结果 完成服务配置后,AI Builder 会为您生成: 1. **数据库表结构文件**:包含完整的表定义和索引配置 2. **云函数代码**:可直接部署的云函数代码文件 3. **API 文档**:详细的接口文档和使用说明 4. **前端集成代码**:前端调用后端服务的示例代码 5. **部署配置**:云开发环境的部署配置文件 通过这种方式,您可以快速获得一个完整的全栈应用,大大提高开发效率。 --- ## Git 管理 # Git 管理 Git 管理是 AI Builder 项目开发中的重要环节,提供版本控制、代码协作、分支管理等功能。合理的 Git 管理策略能够确保代码质量、支持团队协作、便于版本回滚。 ## 概述 AI Builder 的 Git 管理包含以下核心功能: - 📝 **版本控制**:记录代码变更历史和版本信息 - 🌿 **分支管理**:支持多分支开发和合并策略 - 👥 **团队协作**:多人协作开发和代码审查 - 🔄 **自动同步**:与云端环境自动同步代码 - 🚀 **CI/CD 集成**:持续集成和自动部署 ## Git 仓库初始化 ### 1. 创建仓库 **在 AI Builder 中初始化**: ```bash # AI Builder 会自动为项目创建 Git 仓库 # 项目创建时选择「启用 Git 管理」 ``` **手动初始化本地仓库**: ```bash # 进入项目目录 cd your-project # 初始化 Git 仓库 git init # 添加远程仓库 git remote add origin https://github.com/your-username/your-project.git # 设置默认分支 git branch -M main # 首次提交 git add . git commit -m "Initial commit: AI Builder project setup" git push -u origin main ``` ### 2. 仓库结构 **标准项目结构**: ``` your-project/ ├── .git/ # Git 配置目录 ├── .gitignore # 忽略文件配置 ├── README.md # 项目说明文档 ├── package.json # 项目依赖配置 ├── src/ # 源代码目录 │ ├── components/ # 组件目录 │ ├── pages/ # 页面目录 │ ├── utils/ # 工具函数 │ └── styles/ # 样式文件 ├── functions/ # 云函数目录 │ ├── user/ # 用户相关函数 │ └── task/ # 任务相关函数 ├── database/ # 数据库配置 ├── docs/ # 文档目录 └── tests/ # 测试文件 ``` ### 3. .gitignore 配置 **推荐的 .gitignore 文件**: ```gitignore # Dependencies node_modules/ npm-debug.log* yarn-debug.log* yarn-error.log* # Production builds /dist /build *.tgz *.tar.gz # Environment variables .env .env.local .env.development.local .env.test.local .env.production.local # IDE files .vscode/ .idea/ *.swp *.swo *~ # OS generated files .DS_Store .DS_Store? ._* .Spotlight-V100 .Trashes ehthumbs.db Thumbs.db # Logs logs *.log # Runtime data pids *.pid *.seed *.pid.lock # Coverage directory used by tools like istanbul coverage/ # Temporary folders tmp/ temp/ # CloudBase specific .tcb_env .cloudbase/ # AI Builder specific .aibuilder/ *.aibuilder.cache ``` ## 分支管理策略 ### 1. Git Flow 工作流 **主要分支**: - `main/master`:生产环境分支,稳定版本 - `develop`:开发分支,集成最新功能 - `feature/*`:功能分支,开发新功能 - `release/*`:发布分支,准备发布版本 - `hotfix/*`:热修复分支,紧急修复 **分支操作示例**: ```bash # 创建并切换到开发分支 git checkout -b develop # 创建功能分支 git checkout -b feature/user-authentication develop # 功能开发完成后合并到 develop git checkout develop git merge --no-ff feature/user-authentication git branch -d feature/user-authentication # 创建发布分支 git checkout -b release/1.0.0 develop # 发布完成后合并到 main 和 develop git checkout main git merge --no-ff release/1.0.0 git tag -a v1.0.0 -m "Release version 1.0.0" git checkout develop git merge --no-ff release/1.0.0 git branch -d release/1.0.0 ``` ### 2. GitHub Flow 工作流 **简化的分支策略**: ```bash # 从 main 分支创建功能分支 git checkout main git pull origin main git checkout -b feature/task-management # 开发并提交 git add . git commit -m "Add task creation functionality" git push origin feature/task-management # 创建 Pull Request # 代码审查通过后合并到 main # 删除功能分支 git checkout main git pull origin main git branch -d feature/task-management ``` ### 3. 分支命名规范 **功能分支**: ``` feature/user-login feature/task-management feature/data-export ``` **修复分支**: ``` bugfix/login-error bugfix/data-validation hotfix/security-patch ``` **发布分支**: ``` release/1.0.0 release/1.1.0 release/2.0.0-beta ``` ## 提交规范 ### 1. 提交信息格式 **Conventional Commits 规范**: ``` [optional scope]: [optional body] [optional footer(s)] ``` **提交类型**: - `feat`:新功能 - `fix`:修复 Bug - `docs`:文档更新 - `style`:代码格式调整 - `refactor`:代码重构 - `test`:测试相关 - `chore`:构建过程或辅助工具的变动 **提交示例**: ```bash # 新功能 git commit -m "feat(auth): add user login functionality" # Bug 修复 git commit -m "fix(task): resolve task deletion error" # 文档更新 git commit -m "docs: update API documentation" # 代码重构 git commit -m "refactor(utils): optimize date formatting function" # 破坏性变更 git commit -m "feat(api): change user authentication method BREAKING CHANGE: API endpoint /auth/login now requires email instead of username" ``` ### 2. 提交最佳实践 **提交频率**: ```bash # 小而频繁的提交 git add src/components/TaskCard.js git commit -m "feat(task): add task card component" git add src/components/TaskCard.css git commit -m "style(task): add task card styling" git add src/pages/TaskList.js git commit -m "feat(task): integrate task card in task list" ``` **提交前检查**: ```bash # 检查代码状态 git status # 查看变更内容 git diff # 分阶段添加文件 git add -p # 交互式添加 # 提交前运行测试 npm test npm run lint # 提交 git commit -m "feat(task): add task filtering functionality" ``` ## 代码协作 ### 1. Pull Request 流程 **创建 Pull Request**: ```bash # 推送功能分支 git push origin feature/user-profile # 在 GitHub/GitLab 创建 Pull Request # 填写 PR 模板 ``` **PR 模板示例**: ```markdown ## 变更描述 ### 功能说明 - 添加用户个人资料页面 - 实现头像上传功能 - 支持个人信息编辑 ### 变更类型 - [ ] Bug 修复 - [x] 新功能 - [ ] 代码重构 - [ ] 文档更新 ### 测试 - [x] 单元测试通过 - [x] 集成测试通过 - [x] 手动测试完成 ### 截图 ![用户资料页面](./screenshots/user-profile.png) ### 相关 Issue Closes #123 ### 检查清单 - [x] 代码符合项目规范 - [x] 添加了必要的测试 - [x] 更新了相关文档 - [x] 通过了所有检查 ``` ### 2. 代码审查 **审查要点**: ```javascript // 代码质量检查 // ✅ 好的代码 const createTask = async (taskData) => { // 参数验证 if (!taskData.title || taskData.title.trim() === '') { throw new Error('任务标题不能为空'); } // 数据处理 const task = { ...taskData, id: generateId(), createdAt: new Date(), status: 'pending' }; // 保存到数据库 return await db.collection('tasks').add(task); }; // ❌ 需要改进的代码 const createTask = (data) => { // 缺少参数验证 // 缺少错误处理 // 变量命名不清晰 let t = { ...data, id: Math.random() }; db.collection('tasks').add(t); }; ``` **审查评论示例**: ```markdown ## 代码审查意见 ### 总体评价 代码整体结构清晰,功能实现正确。有几个小建议: ### 具体建议 **src/components/TaskCard.js:25** ```suggestion // 建议添加 PropTypes 类型检查 import PropTypes from 'prop-types'; TaskCard.propTypes = { task: PropTypes.object.isRequired, onEdit: PropTypes.func.isRequired, onDelete: PropTypes.func.isRequired }; ``` **src/utils/dateFormat.js:10** ```suggestion // 建议使用更健壮的日期格式化 const formatDate = (date) => { if (!date) return ''; return new Intl.DateTimeFormat('zh-CN').format(new Date(date)); }; ``` ### 测试覆盖 请为新增的 `TaskCard` 组件添加单元测试。 ### 文档 建议更新 README.md 中的组件使用说明。 ``` ### 3. 冲突解决 **合并冲突处理**: ```bash # 更新本地分支 git checkout feature/user-profile git fetch origin git rebase origin/main # 如果有冲突,手动解决 # 编辑冲突文件,保留需要的代码 # 标记冲突已解决 git add . git rebase --continue # 推送更新 git push --force-with-lease origin feature/user-profile ``` **冲突解决示例**: ```javascript // 冲突文件内容 >>>>>> feature/user-profile // 解决后的内容 const API_URL = process.env.NODE_ENV === 'production' ? 'https://api.production.com' : 'https://api.staging.com'; ``` ## 版本管理 ### 1. 语义化版本 **版本号格式**:`MAJOR.MINOR.PATCH` - `MAJOR`:不兼容的 API 修改 - `MINOR`:向下兼容的功能性新增 - `PATCH`:向下兼容的问题修正 **版本示例**: ```bash # 修复 Bug git tag v1.0.1 # 新增功能 git tag v1.1.0 # 重大更新 git tag v2.0.0 # 预发布版本 git tag v1.1.0-beta.1 git tag v1.1.0-rc.1 ``` ### 2. 发布管理 **自动化发布脚本**: ```bash #!/bin/bash # scripts/release.sh set -e # 获取当前版本 CURRENT_VERSION=$(node -p "require('./package.json').version") echo "当前版本: $CURRENT_VERSION" # 获取新版本号 echo "请输入新版本号 (当前: $CURRENT_VERSION):" read NEW_VERSION # 验证版本号格式 if ! [[ $NEW_VERSION =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then echo "错误: 版本号格式不正确" exit 1 fi # 更新版本号 npm version $NEW_VERSION --no-git-tag-version # 构建项目 echo "构建项目..." npm run build # 运行测试 echo "运行测试..." npm test # 提交变更 git add . git commit -m "chore: bump version to $NEW_VERSION" # 创建标签 git tag -a v$NEW_VERSION -m "Release version $NEW_VERSION" # 推送到远程 git push origin main git push origin v$NEW_VERSION echo "版本 $NEW_VERSION 发布完成!" ``` ### 3. 变更日志 **CHANGELOG.md 格式**: ```markdown # 变更日志 所有重要的项目变更都会记录在此文件中。 格式基于 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.0.0/), 版本号遵循 [语义化版本](https://semver.org/lang/zh-CN/)。 ## [未发布] ### 新增 - 用户个人资料页面 - 任务标签功能 ### 修改 - 优化任务列表性能 - 改进移动端适配 ### 修复 - 修复登录状态丢失问题 - 解决任务删除确认对话框显示异常 ## [1.1.0] - 2024-01-15 ### 新增 - 任务分类管理功能 - 数据导出功能 - 暗色主题支持 ### 修改 - 重构用户认证模块 - 优化数据库查询性能 ### 修复 - 修复任务截止日期显示错误 - 解决文件上传失败问题 ### 移除 - 移除过时的 API 接口 ## [1.0.0] - 2024-01-01 ### 新增 - 初始版本发布 - 用户注册登录功能 - 任务管理基础功能 - 响应式界面设计 ``` ## CI/CD 集成 ### 1. GitHub Actions **工作流配置**: ```yaml # .github/workflows/ci.yml name: CI/CD Pipeline on: push: branches: [ main, develop ] pull_request: branches: [ main ] jobs: test: runs-on: ubuntu-latest strategy: matrix: node-version: [14.x, 16.x, 18.x] steps: - uses: actions/checkout@v3 - name: Setup Node.js ${{ matrix.node-version }} uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} cache: 'npm' - name: Install dependencies run: npm ci - name: Run linter run: npm run lint - name: Run tests run: npm test -- --coverage - name: Upload coverage to Codecov uses: codecov/codecov-action@v3 build: needs: test runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Setup Node.js uses: actions/setup-node@v3 with: node-version: '18.x' cache: 'npm' - name: Install dependencies run: npm ci - name: Build project run: npm run build - name: Upload build artifacts uses: actions/upload-artifact@v3 with: name: build-files path: dist/ deploy: needs: build runs-on: ubuntu-latest if: github.ref == 'refs/heads/main' steps: - uses: actions/checkout@v3 - name: Download build artifacts uses: actions/download-artifact@v3 with: name: build-files path: dist/ - name: Deploy to CloudBase env: TCB_ENV: ${{ secrets.TCB_ENV }} TCB_SECRET_ID: ${{ secrets.TCB_SECRET_ID }} TCB_SECRET_KEY: ${{ secrets.TCB_SECRET_KEY }} run: | npm install -g @cloudbase/cli tcb login --apiKeyId $TCB_SECRET_ID --apiKey $TCB_SECRET_KEY tcb hosting:deploy dist/ -e $TCB_ENV tcb functions:deploy -e $TCB_ENV ``` ### 2. 自动化测试 **测试配置**: ```javascript // jest.config.js module.exports = { testEnvironment: 'jsdom', setupFilesAfterEnv: ['/src/setupTests.js'], moduleNameMapping: { '\\.(css|less|scss|sass)$': 'identity-obj-proxy', '^@/(.*)$': '/src/$1' }, collectCoverageFrom: [ 'src/**/*.{js,jsx}', '!src/index.js', '!src/serviceWorker.js', '!src/**/*.test.{js,jsx}' ], coverageThreshold: { global: { branches: 80, functions: 80, lines: 80, statements: 80 } } }; ``` **测试脚本**: ```json { "scripts": { "test": "jest", "test:watch": "jest --watch", "test:coverage": "jest --coverage", "test:ci": "jest --ci --coverage --watchAll=false" } } ``` ## 常见问题 ### Q: 如何处理大文件的版本控制? A: 使用 Git LFS (Large File Storage) 来管理大文件,避免仓库体积过大。 ### Q: 团队成员的 Git 配置不一致怎么办? A: 使用 .editorconfig 和 .gitattributes 文件统一配置,设置代码格式化规则。 ### Q: 如何回滚到之前的版本? A: 使用 `git revert` 或 `git reset` 命令,建议在生产环境使用 revert 保持历史记录。 ### Q: 分支太多导致混乱怎么办? A: 定期清理已合并的分支,建立分支命名规范,使用分支保护规则。 ## 下一步 完成 Git 管理配置后,可以进行资源管理和监控: 📊 **[配置资源管理 →](./resource-management.md)** 或者返回查看其他开发流程: 🚀 **[查看应用发布 →](./app-publish.md)** --- ## AI Builder 介绍 # AI Builder 介绍 ## 概述 AI Builder 是腾讯云开发推出的智能应用构建工具,通过 AI 驱动的方式帮助开发者快速生成前端页面、云开发数据库和云函数。它将传统的手工编码过程转变为智能化的对话式开发体验,让开发者能够通过自然语言描述快速构建完整的云端应用。 ## 核心特性 ### 🎨 智能前端生成 - **AI 驱动的页面生成**:通过自然语言描述,自动生成现代化的前端页面 - **响应式设计**:自动生成适配多端的响应式布局 - **组件化开发**:生成可复用的组件库和模块 ### 🗄️ 云开发数据库集成 - **自动数据库设计**:根据业务需求自动设计数据库结构 - **实时数据同步**:支持实时数据库功能 - **数据安全**:内置数据访问控制和安全规则 - **一键部署**:自动完成数据库的创建和配置 ### ⚡ 云函数自动部署 - **智能函数生成**:根据业务逻辑自动生成云函数代码 - **一键部署**:自动完成云函数的创建和配置 ### 🔧 一站式开发体验 - **可视化编辑**:提供直观的可视化编辑界面 - **实时预览**:支持实时预览和调试 - **版本管理**:内置版本控制和回滚功能 ## 产品优势 ### 🚀 开发效率提升 - **高开发速度**:通过 AI 自动生成,大幅缩短开发周期 - **零基础友好**:无需深度编程知识,通过自然语言即可构建应用 - **一站式解决方案**:前端、后端、数据库一体化生成和部署 ### 💡 智能化程度高 - **深度理解需求**:AI 能够准确理解复杂的业务需求描述 - **最佳实践内置**:自动应用行业最佳实践和设计模式 - **持续优化**:基于使用反馈不断改进生成质量 ## 技术架构 ### 🏗️ 系统架构 - **前端层**:基于 React.js 前端框架生成的现代化页面 - **业务逻辑层**:智能生成的云函数处理业务逻辑 - **数据存储层**:基于云开发数据库的数据持久化 - **基础设施层**:腾讯云提供的高可用云服务 ### 🔄 工作流程 1. **需求分析**:AI 解析自然语言描述的业务需求 2. **架构设计**:自动设计应用架构和数据模型 3. **代码生成**:生成前端页面、后端 API 和数据库结构 4. **自动部署**:一键部署到云端环境 5. **持续优化**:根据使用情况持续优化性能 --- 通过 AI Builder,您可以大幅提升开发效率,专注于业务逻辑而非重复的基础代码编写。立即开始您的智能开发之旅吧! --- ## 注册登录 # 注册登录 :::tip 通过 AI Builder,您可以与 AI 对话来创建个性化的用户登录体验。本文档将指导您如何使用自然语言与 AI 交互,快速构建符合您需求的登录系统。 ::: ## 使用托管登录页 云开发提供了环境维度的统一托管登录页,可以通过[开发平台](https://tcb.cloud.tencent.com/dev?#/identity/land-page)进行配置和管理。 ### 用户登录状态 使用以下方法可以判断用户是否已登录,此方法不包含匿名登录用户。 ```javascript Boolean($w.auth.currentUser.userId); ``` 如需判断用户是否已登录(包含匿名登录),请使用以下方法。注意:匿名登录用户不存在 userId 属性。 ```javascript Boolean($w.auth.currentUser.name === "Anonymous" || $w.auth.currentUser.userId); ``` ### 跳转登录页 如果用户未登录,您可以使用以下方法跳转到登录页。 ```javascript const tcb = await $w.cloud.getCloudInstance(); tcb.auth().toDefaultLoginPage({ config_version: "env", redirect_uri: window.location.href, query: { s_domain: $w.utils .resolveStaticResourceUrl("/") .replace(/^https?:\/\//, "") .split("/")[0], }, }); ``` ### 完整示例:页面登录判断与跳转 以下是一个完整的提示词案例,用于为页面添加登录判断功能,并在用户未登录时自动跳转到托管登录页面: 💡 托管登录页 AI 提示词模板 ```javascript 为所有页面添加登录判断, 通过 Boolean($w.auth.currentUser.userId) 判断当前用户是否已登录, 如果未登录,不渲染页面,并通过如下 checkAuth 方法跳转到登录页。 const checkAuth = async () => { if (!Boolean($w.auth.currentUser.userId)) { const tcb = await $w.cloud.getCloudInstance(); tcb.auth().toDefaultLoginPage({ config_version: "env", redirect_uri: window.location.href, query: { s_domain: $w.utils .resolveStaticResourceUrl("/") .replace(/^https?:\/\//, "") .split("/")[0], }, }); } }; ``` ### 在 Dev Mode 中直接编写代码 如果使用提示词方式不能稳定实现登录判断功能,可以直接在 AI Builder 的 Dev Mode 代码编辑器中编写登录相关的代码: ```javascript useEffect(() => { const checkAuth = async ($w) => { if (!Boolean($w.auth.currentUser.userId)) { const tcb = await $w.cloud.getCloudInstance(); tcb.auth().toDefaultLoginPage({ config_version: "env", redirect_uri: window.location.href, query: { s_domain: $w.utils .resolveStaticResourceUrl("/") .replace(/^https?:\/\//, "") .split("/")[0], }, }); } }; checkAuth(props.$w); }, []); if (!Boolean(props.$w.auth.currentUser.userId)) { return null; } ``` ## 自定义登录页 :::warning 重要前提 **仅当托管登录页无法满足您的特定业务需求时**,才建议创建自定义登录页面。自定义登录页面虽然提供更灵活的用户认证体验,但需要您自行处理安全性、兼容性等问题。 ::: 托管登录页支持您自定义登录页的样式和功能,满足您的特定业务需求。 :::caution 前置条件 1. 前往 [云开发/身份认证](https://tcb.cloud.tencent.com/dev?#/identity/login-manage) 2. 在登录方式列表中,开启所需要的登录方式,如用户名密码登录、手机号验证码登录、邮箱验证码登录等。 ::: ### 1. 用户名密码登录 :::info 重要说明 该登录方式不支持直接注册。用户需要先通过其他方式(如手机号验证码、邮箱验证码)完成注册,并在注册过程中设置用户名和密码。 ::: 以下是 AI 提示词模板,您可以根据实际需求修改功能要求部分: 💡 用户名密码登录 AI 提示词模板 ```javascript 创建登录页面需求: 功能要求: - 用户名/密码输入框 - 显示加载/错误状态 - 简洁美观的UI设计 登录方法: const tcb = await $w.cloud.getCloudInstance(); const loginState = await tcb.auth().signIn({ username, password }); ``` ### 2. 手机号验证码登录 手机号验证码登录支持登录和注册两种场景,为用户提供便捷的身份验证方式。 **登录场景** 以下是登录的 AI 提示词模板,您可以根据实际需求修改功能要求部分: 💡 手机号验证码登录 AI 提示词模板 ```javascript 创建手机号验证码登录页面: 功能要求: - 手机号输入框(支持+86格式) - 验证码输入框 - 发送验证码按钮(带倒计时) - 登录按钮 - 加载状态和错误提示 具体登录方法: const tcb = await $w.cloud.getCloudInstance(); const auth = tcb.auth(); 发送验证码:返回值要保存起来,登录时需要使用 const verificationInfo = await auth.getVerification({ phone_number: `+86 ${phoneNum}`, }); 登录方法: await auth.signInWithSms({ verificationInfo, verificationCode, // 用户输入的验证码 phoneNum, }); ``` **注册场景** 以下是注册的 AI 提示词模板,您可以根据实际需求修改功能要求部分: 💡 手机号验证码注册 AI 提示词模板 ```javascript 创建手机号验证码注册页面: 功能要求: - 手机号输入框(支持+86格式) - 验证码输入框 - 发送验证码按钮(带倒计时) - 必须:password 输入框 - 必须:用户名输入框(密码长度不小于 8 位,不大于 32 位,需要包含字母和数字。) - 可选:昵称输入框 - 注册按钮 - 加载状态和错误提示 具体注册方法: const tcb = await $w.cloud.getCloudInstance(); const auth = tcb.auth(); const verification = await auth.getVerification({ phone_number: phoneNumber }); // 验证验证码的正确性 const verificationTokenRes = await auth.verify({ verification_id: verification.verification_id, verification_code: verificationCode }); // 如果该用户已经存在,则登录 if (verification.is_user) { await auth.signIn({ username: phoneNumber, verification_token: verificationTokenRes.verification_token }); } else { // 否则,则注册新用户,注册新用户时,可以设置密码,用户名,成功后,会自动登录 await auth.signUp({ phone_number: phoneNumber, verification_code: verificationCode, verification_token: verificationTokenRes.verification_token, // 可选,设置昵称 name: "手机用户", // 可选,设置密码 password: "password", // 可选,设置登录用户名 username: "username" }); } ``` ### 3.邮箱验证码登录 邮箱验证码登录同样支持登录和注册两种场景,为用户提供便捷的身份验证方式。 **登录场景** 以下是登录的 AI 提示词模板,您可以根据实际需求修改功能要求部分: 💡 邮箱验证码登录 AI 提示词模板 ```javascript 创建邮箱验证码登录页面: 功能要求: - 邮箱输入框 - 验证码输入框 - 发送验证码按钮(带倒计时) - 登录按钮 - 加载状态和错误提示 具体登录方法: const tcb = await $w.cloud.getCloudInstance(); const auth = tcb.auth(); 发送验证码:返回值要保存起来,登录时需要使用 const verificationInfo = await auth.getVerification({ email: email, }); 登录方法: await auth.signInWithEmail({ verificationInfo, verificationCode, // 用户输入的验证码 email: email, }); ``` **注册场景** 以下是注册的 AI 提示词模板,您可以根据实际需求修改功能要求部分: 💡 邮箱验证码注册 AI 提示词模板 ```javascript 创建邮箱验证码注册页面: 功能要求: - 邮箱输入框 - 验证码输入框 - 发送验证码按钮(带倒计时) - 必须:password 输入框 - 必须:用户名输入框(密码长度不小于 8 位,不大于 32 位,需要包含字母和数字。) - 可选:昵称输入框 - 注册按钮 - 加载状态和错误提示 具体注册方法: const tcb = await $w.cloud.getCloudInstance(); const auth = tcb.auth(); const verification = await auth.getVerification({ email: email }); // 验证验证码的正确性 const verificationTokenRes = await auth.verify({ verification_id: verification.verification_id, verification_code: verificationCode }); // 如果该用户已经存在,则登录 if (verification.is_user) { await auth.signIn({ username: email, verification_token: verificationTokenRes.verification_token }); } else { // 否则,则注册新用户,注册新用户时,可以设置密码,用户名,成功后,会自动登录 await auth.signUp({ email: email, verification_code: verificationCode, verification_token: verificationTokenRes.verification_token, // 可选,设置昵称 name: "邮箱用户", password: password, username: username }); } ``` ## 用户登出 用户登出,即清除当前用户的登录态,使用户再次登录时,需要重新进行身份验证。 以下是注册的 AI 提示词模板,您可以根据实际需求修改功能要求部分: 💡 用户登出 AI 提示词模板 ```javascript 添加退出登录按钮, 具体登出方法: const tcb = await $w.cloud.getCloudInstance(); const auth = tcb.auth(); await auth.signOut(); ``` --- ## 快速开始 # 快速开始 欢迎使用 AI Builder!本指南将帮助您快速上手,从需求描述到应用发布的完整流程。 ## 概览 AI Builder 提供了一套完整的智能应用开发流程,让您能够通过自然语言描述快速构建和部署云端应用。整个开发过程包含以下几个关键步骤: ### 🚀 开发流程 1. **[描述需求](./requirement-description)** - 通过自然语言描述您的应用需求 2. **[应用预览](./detail-editing)** - 完善和调整应用的具体细节 3. **[后台服务](./generate-source)** - 为应用生成数据库结构和云函数 4. **[代码编辑](./dev-mode)** - 使用 Dev Mode 进行高级代码编辑 5. **[资源发布](./resource-publish)** - 发布和管理云端资源 6. **[应用发布](./app-publish)** - 部署和发布您的应用 ## 前置条件 在开始使用 AI Builder 之前,请确保您已经: - ✅ 拥有腾讯云账号 - ✅ 开通云开发服务 - ✅ 了解基本的应用开发概念 - ✅ 准备好您的应用需求描述 ## 第一次使用 ### 1. 访问 AI Builder 登录腾讯云控制台,进入云开发服务,找到 AI Builder 入口: ``` 腾讯云控制台 → 云开发平台 → AI Builder ``` ### 2. 描述需求自动创建项目 AI Builder 支持通过描述需求自动创建项目,让您的开发更加智能化: **操作步骤:** 1. 选择项目类型 2. 在对话区直接输入您的项目需求描述 3. AI 会自动分析需求 **示例需求描述:** - "创建一个用户管理系统,包含用户注册、登录和个人信息管理功能" - "开发一个商品展示网站,支持商品分类浏览和搜索功能" ### 3. 进入开发流程 会话创建完成后,您可以继续完善会话或直接进入开发阶段。详细的会话描述技巧请参考: 👉 **[会话描述指南](./requirement-description.md)** ## 快速导航 根据您当前的开发阶段,选择对应的指南: ## 开发流程指南 | 阶段 | 功能模块 | 说明 | | --------------- | ------------------------------------- | ---------------------------------------- | | 📝 **会话阶段** | [需求描述](./requirement-description) | 如何准确描述您的应用需求,生成页面及样式 | | | [应用预览](./sandbox) | 预览应用的效果 | | | [快捷编辑](./detail-editing) | 手动快捷修改生成页面的样式及内容 | | | [后台服务](./generate-source) | 为应用生成数据库结构和云函数 | | 🛠️ **开发阶段** | [Dev Mode 代码编辑](./dev-mode) | 利用在线编辑器在代码层面进行开发 | | | [资源发布](./resource-publish) | 发布云函数及数据库资源,并创建应用 | | 🚀 **部署阶段** | [应用发布](./app-publish) | 将应用部署到生产环境 | ## 常见问题 ### Q: 我是编程新手,能使用 AI Builder 吗? A: 当然可以!AI Builder 专为降低开发门槛而设计,您只需要用自然语言描述需求即可。 ### Q: AI Builder 支持哪些类型的应用? A: 支持 Web 应用、管理后台等多种应用类型。非常抱歉目前不支持小程序。 ### Q: 生成的代码可以自定义修改吗? A: 是的,您可以在 Dev Mode 中进行高级代码编辑和自定义开发,或者利用快捷编辑功能进行样式修改及对话 AI 修改。 ### Q: 如何获得更多帮助? A: 您可以查看各个详细指南,或在 Builder 界面右上方扫码加入我们的内测群获取技术支持。 --- ## 需求描述 # 需求描述 需求描述是 AI Builder 开发流程的第一步,也是最关键的一步。准确、清晰的需求描述将直接影响 AI 生成应用的质量和准确性。 ## 概述 在需求描述阶段,您需要用自然语言向 AI 描述您想要构建的应用。AI Builder 的智能引擎会分析您的描述,理解应用的功能需求、界面布局、数据结构等,并据此生成相应的前端页面、后端逻辑和数据库结构。 :::info 提示 该阶段请主要聚焦于应用的功能需求和界面风格,在生成应用的基本样式和结构后,再添加后台服务,生成数据模型。 ::: ## 如何编写有效的需求描述 ### 1. 明确应用类型 首先明确您要构建的应用类型: - **Web 应用**:桌面端网页应用 - **移动端 H5**:手机端网页应用 - **管理后台**:数据管理和运营后台 - **展示页面**:产品展示、公司介绍等静态页面 **示例**: ``` 我要创建一个移动端的任务管理应用 ``` ### 2. 描述核心功能 详细说明应用的主要功能模块: **示例**: ``` 应用需要包含以下功能: - 用户可以创建、编辑、删除任务 - 任务可以设置优先级(高、中、低) - 任务可以设置截止日期 - 用户可以标记任务为已完成 - 支持任务分类管理 - 提供任务统计和进度展示 ``` ### 3. 描述界面风格 说明您期望的界面风格和用户体验: **示例**: ``` 界面风格要求: - 简洁现代的设计风格 - 主色调使用蓝色系 - 适配移动端操作,支持手势滑动 - 界面要有良好的视觉层次 ``` ## 需求描述模板 ### 基础模板 ``` 【应用类型】:[Web应用/移动端H5/小程序/管理后台] 【应用名称】:[您的应用名称] 【核心功能】: 1. [功能1描述] 2. [功能2描述] 3. [功能3描述] ... 【界面要求】: - [设计风格要求] - [色彩搭配要求] - [交互体验要求] 【特殊需求】: - [其他特殊要求] ``` ### 完整示例 ``` 【应用类型】:移动端H5应用 【应用名称】:智能任务管理器 【核心功能】: 1. 任务管理:创建、编辑、删除、完成任务 2. 分类管理:支持自定义任务分类,不同分类用不同颜色区分 3. 优先级设置:任务可设置高、中、低三个优先级 4. 日期管理:支持设置任务截止日期,过期任务高亮提醒 5. 搜索功能:支持按任务标题和内容搜索 6. 统计展示:显示任务完成率、分类统计等数据 7. 用户系统:支持用户注册、登录、个人信息管理 【界面要求】: - 采用现代简约设计风格 - 主色调使用渐变蓝色(#4A90E2 到 #357ABD) - 支持深色模式切换 - 界面要有良好的动画效果 - 适配各种手机屏幕尺寸 【特殊需求】: - 支持离线使用,数据本地存储 - 任务提醒功能(浏览器通知) - 支持任务拖拽排序 - 数据支持云端同步 ``` ## 最佳实践 ### ✅ 推荐做法 1. **具体明确**:避免模糊的描述,尽量具体说明功能细节 2. **结构清晰**:使用分点、分段的方式组织描述 3. **举例说明**:对于复杂功能,可以举具体的使用场景 4. **考虑用户体验**:从用户角度描述功能需求 5. **分步描述**:复杂应用可以分阶段描述,先核心功能后扩展功能 ### ❌ 避免的做法 1. **过于简单**:"做一个网站" - 缺乏具体信息 2. **过于复杂**:一次性描述过多功能,建议分阶段实现 3. **技术术语过多**:使用业务语言而非技术术语 4. **矛盾描述**:确保各部分描述逻辑一致 5. **缺乏重点**:没有突出核心功能和主要流程 ## 常见问题 ### Q: 我不知道如何描述技术细节怎么办? A: 不需要描述技术细节,专注于功能和用户体验即可。AI 会自动选择合适的技术实现。 ### Q: 需求描述可以修改吗? A: 可以的,在后续的细节编辑阶段可以进一步完善和修改需求。 ### Q: 一次性描述所有功能还是分阶段? A: 建议先描述核心功能,生成基础版本后再逐步添加高级功能。 ### Q: 如何确保 AI 理解我的需求? A: 使用清晰的结构、具体的描述,并在生成后检查结果是否符合预期。 ## 下一步 完成需求描述后,AI Builder 会根据您的描述生成初始的应用结构。接下来您可以: 🎯 **[进入细节编辑阶段 →](./detail-editing.md)** 在细节编辑阶段,您可以进一步完善应用的具体细节,调整界面布局,优化用户体验。 --- ## 资源管理 # 资源管理 资源管理是 AI Builder 应用运维的重要组成部分,包括云函数、数据库、存储、CDN 等资源的监控、优化和管理。有效的资源管理能够确保应用稳定运行、控制成本、提升性能。 ## 概述 资源管理涵盖以下核心领域: - 📊 **资源监控**:实时监控各项资源使用情况 - 💰 **成本控制**:优化资源配置,控制运营成本 - 🔧 **性能优化**:提升应用性能和用户体验 - 🛡️ **安全管理**:确保资源和数据安全 - 📈 **扩容管理**:根据业务需求调整资源规模 ## 资源概览 ### 1. 资源类型 **计算资源**: - 云函数实例 - 函数执行时长 - 内存使用量 - 并发请求数 **存储资源**: - 数据库存储空间 - 文件存储空间 - 读写操作次数 - 数据传输量 **网络资源**: - CDN 流量 - 带宽使用量 - 请求次数 - 缓存命中率 ### 2. 资源监控面板 **控制台概览**: ```javascript // 资源监控数据结构 const resourceMetrics = { functions: { totalInvocations: 125000, totalDuration: 3600000, // 毫秒 averageMemoryUsage: 128, // MB errorRate: 0.02, // 2% concurrentExecutions: 50 }, database: { storageUsed: 2.5, // GB readOperations: 50000, writeOperations: 15000, indexSize: 0.3 // GB }, storage: { totalFiles: 1200, storageUsed: 5.8, // GB downloadCount: 8500, uploadCount: 1200 }, cdn: { totalRequests: 180000, bandwidth: 45.2, // GB cacheHitRate: 0.85, // 85% averageResponseTime: 120 // 毫秒 } }; ``` ## 云函数管理 ### 1. 函数监控 **性能指标监控**: ```javascript // functions/monitoring/metrics.js const cloud = require('@cloudbase/node-sdk'); class FunctionMetrics { constructor() { this.app = cloud.init({ env: cloud.SYMBOL_CURRENT_ENV }); this.db = this.app.database(); } // 记录函数执行指标 async recordMetrics(functionName, startTime, endTime, memoryUsed, success) { const duration = endTime - startTime; const metrics = { functionName, duration, memoryUsed, success, timestamp: new Date(), date: new Date().toISOString().split('T')[0] }; try { await this.db.collection('function_metrics').add(metrics); } catch (error) { console.error('记录指标失败:', error); } } // 获取函数性能统计 async getFunctionStats(functionName, days = 7) { const startDate = new Date(); startDate.setDate(startDate.getDate() - days); const result = await this.db.collection('function_metrics') .aggregate() .match({ functionName, timestamp: this.db.command.gte(startDate) }) .group({ _id: '$date', totalInvocations: { $sum: 1 }, averageDuration: { $avg: '$duration' }, maxDuration: { $max: '$duration' }, averageMemory: { $avg: '$memoryUsed' }, successRate: { $avg: { $cond: ['$success', 1, 0] } } }) .sort({ _id: 1 }) .end(); return result.data; } } // 在云函数中使用 exports.main = async (event, context) => { const startTime = Date.now(); const metrics = new FunctionMetrics(); try { // 业务逻辑 const result = await processTask(event); // 记录成功指标 await metrics.recordMetrics( context.functionName, startTime, Date.now(), context.memoryLimitInMB, true ); return { code: 0, data: result }; } catch (error) { // 记录失败指标 await metrics.recordMetrics( context.functionName, startTime, Date.now(), context.memoryLimitInMB, false ); throw error; } }; ``` ### 2. 函数优化 **内存配置优化**: ```javascript // scripts/optimize-functions.js const cloud = require('@cloudbase/node-sdk'); class FunctionOptimizer { constructor() { this.app = cloud.init({ env: process.env.TCB_ENV }); } // 分析函数内存使用情况 async analyzeMemoryUsage(functionName) { const stats = await this.getFunctionStats(functionName, 30); const memoryStats = { average: stats.reduce((sum, day) => sum + day.averageMemory, 0) / stats.length, max: Math.max(...stats.map(day => day.maxMemory)), p95: this.calculatePercentile(stats.map(day => day.maxMemory), 95) }; // 推荐内存配置 const recommendedMemory = Math.ceil(memoryStats.p95 * 1.2 / 64) * 64; // 向上取整到64MB return { current: await this.getCurrentMemoryConfig(functionName), recommended: recommendedMemory, stats: memoryStats }; } // 自动调整函数配置 async optimizeFunctionConfig(functionName) { const analysis = await this.analyzeMemoryUsage(functionName); if (analysis.recommended !== analysis.current) { console.log(`建议调整 ${functionName} 内存配置:`); console.log(`当前: ${analysis.current}MB`); console.log(`推荐: ${analysis.recommended}MB`); // 这里可以调用 API 自动更新配置 // await this.updateFunctionConfig(functionName, { // memory: analysis.recommended // }); } } calculatePercentile(values, percentile) { const sorted = values.sort((a, b) => a - b); const index = Math.ceil(sorted.length * percentile / 100) - 1; return sorted[index]; } } // 定期运行优化 const optimizer = new FunctionOptimizer(); optimizer.optimizeFunctionConfig('getTasks'); optimizer.optimizeFunctionConfig('createTask'); ``` ### 3. 错误监控和告警 **错误收集系统**: ```javascript // functions/monitoring/errorCollector.js class ErrorCollector { constructor() { this.app = cloud.init({ env: cloud.SYMBOL_CURRENT_ENV }); this.db = this.app.database(); } // 记录错误信息 async logError(error, context, event) { const errorLog = { functionName: context.functionName, errorMessage: error.message, errorStack: error.stack, requestId: context.requestId, event: JSON.stringify(event), timestamp: new Date(), severity: this.classifyError(error) }; try { await this.db.collection('error_logs').add(errorLog); // 严重错误立即告警 if (errorLog.severity === 'critical') { await this.sendAlert(errorLog); } } catch (logError) { console.error('记录错误日志失败:', logError); } } // 错误分类 classifyError(error) { if (error.message.includes('timeout')) { return 'warning'; } if (error.message.includes('permission') || error.message.includes('auth')) { return 'critical'; } if (error.message.includes('database')) { return 'error'; } return 'info'; } // 发送告警 async sendAlert(errorLog) { // 这里可以集成邮件、短信、钉钉等告警方式 console.log('🚨 严重错误告警:', errorLog.errorMessage); // 示例:发送邮件告警 // await this.sendEmail({ // to: 'admin@yourcompany.com', // subject: `[严重错误] ${errorLog.functionName}`, // body: `错误信息: ${errorLog.errorMessage}\n\n堆栈: ${errorLog.errorStack}` // }); } // 获取错误统计 async getErrorStats(hours = 24) { const startTime = new Date(); startTime.setHours(startTime.getHours() - hours); const result = await this.db.collection('error_logs') .aggregate() .match({ timestamp: this.db.command.gte(startTime) }) .group({ _id: { functionName: '$functionName', severity: '$severity' }, count: { $sum: 1 }, latestError: { $max: '$timestamp' } }) .end(); return result.data; } } // 在云函数中使用 const errorCollector = new ErrorCollector(); exports.main = async (event, context) => { try { // 业务逻辑 return await processRequest(event); } catch (error) { // 记录错误 await errorCollector.logError(error, context, event); // 重新抛出错误 throw error; } }; ``` ## 数据库管理 ### 1. 存储监控 **数据库使用情况分析**: ```javascript // scripts/database-analysis.js class DatabaseAnalyzer { constructor() { this.app = cloud.init({ env: process.env.TCB_ENV }); this.db = this.app.database(); } // 分析集合大小 async analyzeCollections() { const collections = ['users', 'tasks', 'categories', 'logs']; const analysis = []; for (const collectionName of collections) { try { const stats = await this.getCollectionStats(collectionName); analysis.push({ collection: collectionName, ...stats }); } catch (error) { console.error(`分析集合 ${collectionName} 失败:`, error); } } return analysis; } // 获取集合统计信息 async getCollectionStats(collectionName) { const collection = this.db.collection(collectionName); // 获取文档数量 const countResult = await collection.count(); const documentCount = countResult.total; // 获取最新和最旧的文档 const latestDoc = await collection .orderBy('_createTime', 'desc') .limit(1) .get(); const oldestDoc = await collection .orderBy('_createTime', 'asc') .limit(1) .get(); // 估算存储大小(简化计算) const sampleDocs = await collection.limit(100).get(); const avgDocSize = sampleDocs.data.length > 0 ? JSON.stringify(sampleDocs.data).length / sampleDocs.data.length : 0; const estimatedSize = (avgDocSize * documentCount) / (1024 * 1024); // MB return { documentCount, estimatedSizeMB: Math.round(estimatedSize * 100) / 100, oldestDocument: oldestDoc.data[0]?._createTime, latestDocument: latestDoc.data[0]?._createTime, avgDocumentSize: Math.round(avgDocSize) }; } // 数据清理建议 async getCleanupRecommendations() { const recommendations = []; // 检查日志数据 const logStats = await this.getCollectionStats('logs'); if (logStats.documentCount > 100000) { recommendations.push({ type: 'cleanup', collection: 'logs', reason: '日志数据过多,建议清理30天前的数据', action: 'DELETE_OLD_LOGS' }); } // 检查临时数据 const tempDataCount = await this.db.collection('temp_data') .where({ _createTime: this.db.command.lt(new Date(Date.now() - 7 * 24 * 60 * 60 * 1000)) }) .count(); if (tempDataCount.total > 0) { recommendations.push({ type: 'cleanup', collection: 'temp_data', reason: `发现 ${tempDataCount.total} 条过期临时数据`, action: 'DELETE_EXPIRED_TEMP_DATA' }); } return recommendations; } } // 定期运行分析 const analyzer = new DatabaseAnalyzer(); analyzer.analyzeCollections().then(analysis => { console.log('数据库分析结果:', analysis); }); ``` ### 2. 索引优化 **索引性能分析**: ```javascript // scripts/index-optimizer.js class IndexOptimizer { constructor() { this.app = cloud.init({ env: process.env.TCB_ENV }); this.db = this.app.database(); } // 分析查询性能 async analyzeQueryPerformance() { const slowQueries = await this.db.collection('query_logs') .where({ duration: this.db.command.gt(1000), // 超过1秒的查询 timestamp: this.db.command.gte(new Date(Date.now() - 24 * 60 * 60 * 1000)) }) .orderBy('duration', 'desc') .limit(50) .get(); // 分析慢查询模式 const queryPatterns = this.analyzeQueryPatterns(slowQueries.data); // 生成索引建议 const indexRecommendations = this.generateIndexRecommendations(queryPatterns); return { slowQueries: slowQueries.data, patterns: queryPatterns, recommendations: indexRecommendations }; } // 分析查询模式 analyzeQueryPatterns(queries) { const patterns = {}; queries.forEach(query => { const key = `${query.collection}_${JSON.stringify(query.where)}`; if (!patterns[key]) { patterns[key] = { collection: query.collection, whereClause: query.where, count: 0, totalDuration: 0, avgDuration: 0 }; } patterns[key].count++; patterns[key].totalDuration += query.duration; patterns[key].avgDuration = patterns[key].totalDuration / patterns[key].count; }); return Object.values(patterns) .sort((a, b) => b.avgDuration - a.avgDuration) .slice(0, 10); } // 生成索引建议 generateIndexRecommendations(patterns) { const recommendations = []; patterns.forEach(pattern => { const whereFields = Object.keys(pattern.whereClause); if (whereFields.length > 0) { recommendations.push({ collection: pattern.collection, fields: whereFields, reason: `查询频率高且耗时较长 (平均 ${Math.round(pattern.avgDuration)}ms)`, priority: pattern.avgDuration > 2000 ? 'high' : 'medium', createIndexCommand: this.generateCreateIndexCommand(pattern.collection, whereFields) }); } }); return recommendations; } // 生成创建索引的命令 generateCreateIndexCommand(collection, fields) { const indexSpec = fields.map(field => `{ name: '${field}', direction: 1 }`).join(', '); return `db.collection('${collection}').createIndex({ keys: [${indexSpec}] })`; } } // 使用示例 const optimizer = new IndexOptimizer(); optimizer.analyzeQueryPerformance().then(analysis => { console.log('查询性能分析:', analysis); if (analysis.recommendations.length > 0) { console.log('\n索引优化建议:'); analysis.recommendations.forEach((rec, index) => { console.log(`${index + 1}. ${rec.collection} 集合`); console.log(` 字段: ${rec.fields.join(', ')}`); console.log(` 原因: ${rec.reason}`); console.log(` 命令: ${rec.createIndexCommand}`); console.log(''); }); } }); ``` ### 3. 数据备份 **自动备份策略**: ```javascript // scripts/backup-manager.js class BackupManager { constructor() { this.app = cloud.init({ env: process.env.TCB_ENV }); this.db = this.app.database(); this.storage = this.app.storage(); } // 执行数据备份 async performBackup() { const backupId = `backup_${Date.now()}`; const backupPath = `backups/${backupId}`; console.log(`开始执行备份: ${backupId}`); try { const collections = ['users', 'tasks', 'categories']; const backupData = {}; // 备份每个集合 for (const collectionName of collections) { console.log(`备份集合: ${collectionName}`); const data = await this.backupCollection(collectionName); backupData[collectionName] = data; } // 保存备份文件 const backupContent = JSON.stringify(backupData, null, 2); const fileName = `${backupPath}/data.json`; await this.storage.uploadFile({ cloudPath: fileName, fileContent: Buffer.from(backupContent, 'utf8') }); // 记录备份信息 await this.recordBackup({ backupId, fileName, size: backupContent.length, collections: Object.keys(backupData), documentCounts: Object.fromEntries( Object.entries(backupData).map(([name, data]) => [name, data.length]) ), timestamp: new Date() }); console.log(`备份完成: ${fileName}`); return { success: true, backupId, fileName }; } catch (error) { console.error('备份失败:', error); return { success: false, error: error.message }; } } // 备份单个集合 async backupCollection(collectionName) { const collection = this.db.collection(collectionName); const batchSize = 1000; let allData = []; let lastDoc = null; while (true) { let query = collection.limit(batchSize); if (lastDoc) { query = query.where({ _id: this.db.command.gt(lastDoc._id) }); } const result = await query.orderBy('_id', 'asc').get(); if (result.data.length === 0) { break; } allData = allData.concat(result.data); lastDoc = result.data[result.data.length - 1]; console.log(`已备份 ${collectionName}: ${allData.length} 条记录`); } return allData; } // 记录备份信息 async recordBackup(backupInfo) { await this.db.collection('backup_logs').add(backupInfo); } // 清理旧备份 async cleanupOldBackups(retentionDays = 30) { const cutoffDate = new Date(); cutoffDate.setDate(cutoffDate.getDate() - retentionDays); // 查找过期备份 const oldBackups = await this.db.collection('backup_logs') .where({ timestamp: this.db.command.lt(cutoffDate) }) .get(); console.log(`发现 ${oldBackups.data.length} 个过期备份`); // 删除过期备份文件和记录 for (const backup of oldBackups.data) { try { // 删除存储文件 await this.storage.deleteFile({ fileList: [backup.fileName] }); // 删除备份记录 await this.db.collection('backup_logs').doc(backup._id).remove(); console.log(`已删除过期备份: ${backup.backupId}`); } catch (error) { console.error(`删除备份失败: ${backup.backupId}`, error); } } } // 恢复数据 async restoreFromBackup(backupId) { console.log(`开始恢复备份: ${backupId}`); try { // 查找备份记录 const backupRecord = await this.db.collection('backup_logs') .where({ backupId }) .get(); if (backupRecord.data.length === 0) { throw new Error('备份记录不存在'); } const backup = backupRecord.data[0]; // 下载备份文件 const fileResult = await this.storage.downloadFile({ fileID: backup.fileName }); const backupData = JSON.parse(fileResult.fileContent.toString()); // 恢复每个集合 for (const [collectionName, data] of Object.entries(backupData)) { console.log(`恢复集合: ${collectionName}`); await this.restoreCollection(collectionName, data); } console.log('数据恢复完成'); return { success: true }; } catch (error) { console.error('数据恢复失败:', error); return { success: false, error: error.message }; } } // 恢复单个集合 async restoreCollection(collectionName, data) { const collection = this.db.collection(collectionName); const batchSize = 100; for (let i = 0; i { const { _id, ...docData } = doc; return collection.doc(_id).set(docData); }); await Promise.all(promises); console.log(`已恢复 ${collectionName}: ${Math.min(i + batchSize, data.length)}/${data.length}`); } } } // 定期备份任务 const backupManager = new BackupManager(); // 每天凌晨2点执行备份 const scheduleBackup = () => { const now = new Date(); const tomorrow = new Date(now); tomorrow.setDate(tomorrow.getDate() + 1); tomorrow.setHours(2, 0, 0, 0); const timeUntilBackup = tomorrow.getTime() - now.getTime(); setTimeout(async () => { await backupManager.performBackup(); await backupManager.cleanupOldBackups(); // 安排下一次备份 scheduleBackup(); }, timeUntilBackup); }; // 启动定期备份 scheduleBackup(); ``` ## 存储管理 ### 1. 文件存储监控 **存储使用分析**: ```javascript // scripts/storage-analyzer.js class StorageAnalyzer { constructor() { this.app = cloud.init({ env: process.env.TCB_ENV }); this.storage = this.app.storage(); this.db = this.app.database(); } // 分析存储使用情况 async analyzeStorageUsage() { console.log('开始分析存储使用情况...'); const analysis = { totalFiles: 0, totalSize: 0, fileTypes: {}, largeFIles: [], oldFiles: [], duplicateFiles: [] }; // 获取所有文件信息 const files = await this.getAllFiles(); files.forEach(file => { analysis.totalFiles++; analysis.totalSize += file.size; // 按文件类型分类 const extension = this.getFileExtension(file.name); if (!analysis.fileTypes[extension]) { analysis.fileTypes[extension] = { count: 0, size: 0 }; } analysis.fileTypes[extension].count++; analysis.fileTypes[extension].size += file.size; // 识别大文件 (>10MB) if (file.size > 10 * 1024 * 1024) { analysis.largeFIles.push({ name: file.name, size: file.size, sizeFormatted: this.formatFileSize(file.size), lastModified: file.lastModified }); } // 识别旧文件 (>1年) const oneYearAgo = new Date(); oneYearAgo.setFullYear(oneYearAgo.getFullYear() - 1); if (file.lastModified b.size - a.size); // 排序旧文件 analysis.oldFiles.sort((a, b) => a.lastModified - b.lastModified); return analysis; } // 获取所有文件信息 async getAllFiles() { // 这里需要根据实际的云存储 API 来实现 // 示例实现 const files = []; let marker = null; do { const result = await this.storage.listFiles({ prefix: '', marker, maxKeys: 1000 }); files.push(...result.files); marker = result.nextMarker; } while (marker); return files; } // 获取文件扩展名 getFileExtension(filename) { const parts = filename.split('.'); return parts.length > 1 ? parts.pop().toLowerCase() : 'unknown'; } // 格式化文件大小 formatFileSize(bytes) { const units = ['B', 'KB', 'MB', 'GB', 'TB']; let size = bytes; let unitIndex = 0; while (size >= 1024 && unitIndex 0) { const totalLargeFileSize = analysis.largeFIles.reduce((sum, file) => sum + file.size, 0); recommendations.push({ type: 'large_files', count: analysis.largeFIles.length, totalSize: this.formatFileSize(totalLargeFileSize), suggestion: '检查是否需要压缩或删除大文件', files: analysis.largeFIles.slice(0, 10) // 只显示前10个 }); } // 旧文件建议 if (analysis.oldFiles.length > 0) { const totalOldFileSize = analysis.oldFiles.reduce((sum, file) => sum + file.size, 0); recommendations.push({ type: 'old_files', count: analysis.oldFiles.length, totalSize: this.formatFileSize(totalOldFileSize), suggestion: '考虑归档或删除长期未使用的文件', files: analysis.oldFiles.slice(0, 10) }); } // 文件类型建议 const imageTypes = ['jpg', 'jpeg', 'png', 'gif', 'bmp']; const totalImageSize = imageTypes.reduce((sum, type) => { return sum + (analysis.fileTypes[type]?.size || 0); }, 0); if (totalImageSize > 100 * 1024 * 1024) { // 超过100MB recommendations.push({ type: 'image_optimization', totalSize: this.formatFileSize(totalImageSize), suggestion: '考虑压缩图片文件以节省存储空间' }); } return recommendations; } } // 使用示例 const analyzer = new StorageAnalyzer(); analyzer.analyzeStorageUsage().then(async analysis => { console.log('存储分析结果:'); console.log(`总文件数: ${analysis.totalFiles}`); console.log(`总大小: ${analyzer.formatFileSize(analysis.totalSize)}`); console.log('\n文件类型分布:'); Object.entries(analysis.fileTypes) .sort((a, b) => b[1].size - a[1].size) .forEach(([type, info]) => { console.log(` ${type}: ${info.count} 个文件, ${analyzer.formatFileSize(info.size)}`); }); const recommendations = await analyzer.getCleanupRecommendations(analysis); if (recommendations.length > 0) { console.log('\n清理建议:'); recommendations.forEach((rec, index) => { console.log(`${index + 1}. ${rec.suggestion}`); console.log(` 影响: ${rec.count} 个文件, ${rec.totalSize}`); }); } }); ``` ## 成本优化 ### 1. 成本分析 **资源成本计算**: ```javascript // scripts/cost-analyzer.js class CostAnalyzer { constructor() { this.pricing = { functions: { invocations: 0.0000002, // 每次调用 gbSeconds: 0.000016667, // 每GB-秒 outboundTraffic: 0.12 // 每GB流出流量 }, database: { storage: 0.07, // 每GB每月 reads: 0.0000015, // 每次读操作 writes: 0.0000015 // 每次写操作 }, storage: { storage: 0.043, // 每GB每月 downloads: 0.12, // 每GB下载流量 requests: 0.0004 // 每1000次请求 }, cdn: { traffic: 0.18 // 每GB流量 } }; } // 计算云函数成本 calculateFunctionCosts(metrics) { const invocationCost = metrics.totalInvocations * this.pricing.functions.invocations; const computeCost = (metrics.totalDuration / 1000) * (metrics.averageMemoryUsage / 1024) * this.pricing.functions.gbSeconds; const trafficCost = metrics.outboundTraffic * this.pricing.functions.outboundTraffic; return { invocations: invocationCost, compute: computeCost, traffic: trafficCost, total: invocationCost + computeCost + trafficCost }; } // 计算数据库成本 calculateDatabaseCosts(metrics) { const storageCost = metrics.storageUsed * this.pricing.database.storage; const readCost = metrics.readOperations * this.pricing.database.reads; const writeCost = metrics.writeOperations * this.pricing.database.writes; return { storage: storageCost, reads: readCost, writes: writeCost, total: storageCost + readCost + writeCost }; } // 计算存储成本 calculateStorageCosts(metrics) { const storageCost = metrics.storageUsed * this.pricing.storage.storage; const downloadCost = metrics.downloadTraffic * this.pricing.storage.downloads; const requestCost = (metrics.totalRequests / 1000) * this.pricing.storage.requests; return { storage: storageCost, downloads: downloadCost, requests: requestCost, total: storageCost + downloadCost + requestCost }; } // 计算 CDN 成本 calculateCDNCosts(metrics) { const trafficCost = metrics.bandwidth * this.pricing.cdn.traffic; return { traffic: trafficCost, total: trafficCost }; } // 生成成本报告 generateCostReport(resourceMetrics) { const functionCosts = this.calculateFunctionCosts(resourceMetrics.functions); const databaseCosts = this.calculateDatabaseCosts(resourceMetrics.database); const storageCosts = this.calculateStorageCosts(resourceMetrics.storage); const cdnCosts = this.calculateCDNCosts(resourceMetrics.cdn); const totalCost = functionCosts.total + databaseCosts.total + storageCosts.total + cdnCosts.total; return { functions: functionCosts, database: databaseCosts, storage: storageCosts, cdn: cdnCosts, total: totalCost, breakdown: { functions: (functionCosts.total / totalCost * 100).toFixed(1), database: (databaseCosts.total / totalCost * 100).toFixed(1), storage: (storageCosts.total / totalCost * 100).toFixed(1), cdn: (cdnCosts.total / totalCost * 100).toFixed(1) } }; } // 成本优化建议 generateOptimizationSuggestions(costReport, resourceMetrics) { const suggestions = []; // 云函数优化建议 if (costReport.functions.total > costReport.total * 0.4) { suggestions.push({ category: 'functions', priority: 'high', suggestion: '云函数成本占比较高,建议优化函数执行时间和内存配置', potentialSavings: costReport.functions.total * 0.2, actions: [ '优化代码逻辑,减少执行时间', '调整内存配置,避免过度分配', '使用连接池减少数据库连接时间', '启用函数预热减少冷启动' ] }); } // 数据库优化建议 if (resourceMetrics.database.readOperations > resourceMetrics.database.writeOperations * 10) { suggestions.push({ category: 'database', priority: 'medium', suggestion: '读操作频率较高,建议使用缓存减少数据库访问', potentialSavings: costReport.database.reads * 0.5, actions: [ '实现 Redis 缓存层', '使用应用级缓存', '优化查询语句', '建立合适的索引' ] }); } // 存储优化建议 if (costReport.storage.downloads > costReport.storage.storage * 2) { suggestions.push({ category: 'storage', priority: 'medium', suggestion: '下载流量成本较高,建议启用 CDN 加速', potentialSavings: costReport.storage.downloads * 0.3, actions: [ '启用 CDN 加速', '优化图片压缩', '使用适当的缓存策略', '清理不必要的文件' ] }); } return suggestions; } } // 使用示例 const costAnalyzer = new CostAnalyzer(); // 模拟资源使用数据 const resourceMetrics = { functions: { totalInvocations: 125000, totalDuration: 3600000, averageMemoryUsage: 128, outboundTraffic: 2.5 }, database: { storageUsed: 2.5, readOperations: 50000, writeOperations: 15000 }, storage: { storageUsed: 5.8, downloadTraffic: 12.3, totalRequests: 25000 }, cdn: { bandwidth: 45.2 } }; const costReport = costAnalyzer.generateCostReport(resourceMetrics); const suggestions = costAnalyzer.generateOptimizationSuggestions(costReport, resourceMetrics); console.log('成本分析报告:'); console.log(`总成本: $${costReport.total.toFixed(2)}/月`); console.log('\n成本分布:'); console.log(`云函数: $${costReport.functions.total.toFixed(2)} (${costReport.breakdown.functions}%)`); console.log(`数据库: $${costReport.database.total.toFixed(2)} (${costReport.breakdown.database}%)`); console.log(`存储: $${costReport.storage.total.toFixed(2)} (${costReport.breakdown.storage}%)`); console.log(`CDN: $${costReport.cdn.total.toFixed(2)} (${costReport.breakdown.cdn}%)`); if (suggestions.length > 0) { console.log('\n优化建议:'); suggestions.forEach((suggestion, index) => { console.log(`${index + 1}. ${suggestion.suggestion}`); console.log(` 预计节省: $${suggestion.potentialSavings.toFixed(2)}/月`); console.log(` 优先级: ${suggestion.priority}`); console.log(` 行动项目:`); suggestion.actions.forEach(action => { console.log(` - ${action}`); }); console.log(''); }); } ``` ## 告警和通知 ### 1. 告警规则配置 **告警系统**: ```javascript // monitoring/alerting.js class AlertingSystem { constructor() { this.app = cloud.init({ env: cloud.SYMBOL_CURRENT_ENV }); this.db = this.app.database(); // 告警规则配置 this.alertRules = [ { name: '函数错误率过高', type: 'function_error_rate', threshold: 0.05, // 5% duration: 300, // 5分钟 severity: 'critical' }, { name: '数据库连接数过高', type: 'database_connections', threshold: 80, // 80% duration: 60, // 1分钟 severity: 'warning' }, { name: '存储空间不足', type: 'storage_usage', threshold: 0.9, // 90% duration: 0, // 立即 severity: 'critical' }, { name: 'CDN 缓存命中率低', type: 'cdn_hit_rate', threshold: 0.7, // 70% duration: 1800, // 30分钟 severity: 'warning' } ]; } // 检查告警条件 async checkAlerts() { const alerts = []; for (const rule of this.alertRules) { const isTriggered = await this.evaluateRule(rule); if (isTriggered) { const alert = { ruleName: rule.name, type: rule.type, severity: rule.severity, threshold: rule.threshold, currentValue: isTriggered.value, message: this.generateAlertMessage(rule, isTriggered.value), timestamp: new Date() }; alerts.push(alert); await this.sendAlert(alert); } } return alerts; } // 评估告警规则 async evaluateRule(rule) { const endTime = new Date(); const startTime = new Date(endTime.getTime() - rule.duration * 1000); switch (rule.type) { case 'function_error_rate': return await this.checkFunctionErrorRate(startTime, endTime, rule.threshold); case 'database_connections': return await this.checkDatabaseConnections(rule.threshold); case 'storage_usage': return await this.checkStorageUsage(rule.threshold); case 'cdn_hit_rate': return await this.checkCDNHitRate(startTime, endTime, rule.threshold); default: return false; } } // 检查函数错误率 async checkFunctionErrorRate(startTime, endTime, threshold) { const result = await this.db.collection('function_metrics') .aggregate() .match({ timestamp: this.db.command.gte(startTime).and(this.db.command.lte(endTime)) }) .group({ _id: null, totalInvocations: { $sum: 1 }, errorCount: { $sum: { $cond: [{ $eq: ['$success', false] }, 1, 0] } } }) .end(); if (result.data.length > 0) { const stats = result.data[0]; const errorRate = stats.errorCount / stats.totalInvocations; if (errorRate > threshold) { return { value: errorRate }; } } return false; } // 检查数据库连接数 async checkDatabaseConnections(threshold) { // 这里需要根据实际的监控 API 来实现 // 示例实现 const currentConnections = 75; // 假设当前连接数 const maxConnections = 100; // 最大连接数 const usage = currentConnections / maxConnections; if (usage > threshold) { return { value: usage }; } return false; } // 检查存储使用率 async checkStorageUsage(threshold) { // 获取存储使用情况 const storageStats = await this.getStorageStats(); const usage = storageStats.used / storageStats.total; if (usage > threshold) { return { value: usage }; } return false; } // 检查 CDN 缓存命中率 async checkCDNHitRate(startTime, endTime, threshold) { const result = await this.db.collection('cdn_metrics') .aggregate() .match({ timestamp: this.db.command.gte(startTime).and(this.db.command.lte(endTime)) }) .group({ _id: null, totalRequests: { $sum: '$requests' }, cacheHits: { $sum: '$cacheHits' } }) .end(); if (result.data.length > 0) { const stats = result.data[0]; const hitRate = stats.cacheHits / stats.totalRequests; if (hitRate { if (rule.type.includes('rate') || rule.type.includes('usage')) { return `${(value * 100).toFixed(1)}%`; } return value.toString(); }; return `${rule.name}: 当前值 ${formatValue(currentValue)}, 阈值 ${formatValue(rule.threshold)}`; } // 发送告警 async sendAlert(alert) { console.log(`🚨 ${alert.severity.toUpperCase()} 告警: ${alert.message}`); // 记录告警历史 await this.db.collection('alert_history').add(alert); // 根据严重程度选择通知方式 switch (alert.severity) { case 'critical': await this.sendEmailAlert(alert); await this.sendSMSAlert(alert); break; case 'warning': await this.sendEmailAlert(alert); break; case 'info': // 只记录,不发送通知 break; } } // 发送邮件告警 async sendEmailAlert(alert) { // 这里集成邮件服务 console.log(`📧 发送邮件告警: ${alert.message}`); } // 发送短信告警 async sendSMSAlert(alert) { // 这里集成短信服务 console.log(`📱 发送短信告警: ${alert.message}`); } // 获取存储统计信息 async getStorageStats() { // 这里需要根据实际的存储 API 来实现 return { used: 8.5, // GB total: 10 // GB }; } } // 定期检查告警 const alerting = new AlertingSystem(); setInterval(async () => { try { const alerts = await alerting.checkAlerts(); if (alerts.length > 0) { console.log(`检测到 ${alerts.length} 个告警`); } } catch (error) { console.error('告警检查失败:', error); } }, 60000); // 每分钟检查一次 ``` ## 常见问题 ### Q: 如何降低云函数的执行成本? A: 优化代码逻辑、调整内存配置、使用连接池、启用函数预热等方式可以有效降低成本。 ### Q: 数据库查询速度慢怎么办? A: 检查索引配置、优化查询语句、使用缓存、分析慢查询日志等方法可以提升性能。 ### Q: 如何监控应用的实时状态? A: 建立完善的监控体系,包括性能指标、错误日志、告警规则等。 ### Q: 存储空间不足如何处理? A: 清理无用文件、压缩大文件、建立数据归档策略、扩容存储空间。 ## 总结 通过完善的资源管理,您可以: - 📊 **实时监控**:掌握应用运行状态和资源使用情况 - 💰 **成本优化**:通过合理配置和优化策略控制运营成本 - 🚀 **性能提升**:识别瓶颈并进行针对性优化 - 🛡️ **稳定运行**:通过告警和自动化确保应用稳定性 - 📈 **扩展能力**:根据业务增长合理规划资源扩容 建议定期审查资源使用情况,持续优化配置,确保应用高效稳定运行。 --- 🎉 **恭喜!您已完成 AI Builder 的完整学习流程** 从需求描述到资源管理,您现在已经掌握了使用 AI Builder 开发和部署应用的全部技能。继续实践和探索,创造更多精彩的应用! --- ## 资源发布 # 资源发布 资源发布是将开发完成的应用部署到云端环境的关键步骤。AI Builder 提供了完整的资源发布流程,包括云函数、数据模型的部署和管理。 ## 概述 通常在 AI 服务生成完成后,您可以直接在会话界面的发布区域进行资源发布。但在以下情况下,您可能需要重新发布资源: - 首次生成服务后尚未发布 - 执行了版本回滚操作 - 数据模型或云函数内容发生了变更 您可以使用资源发布功能重新发布当前的最新服务内容,包括数据模型、云函数资源。 ## 发布流程 ### 1. 启动发布 1. 在 AI Builder 右上角点击「发布」按钮 2. 选择「资源发布」选项 3. 确认目标发布环境 ### 2. 确认发布资源 在确认发布资源时,系统会自动扫描并显示所有待发布的资源及其变更状态,通过不同的标签来标识: | 标签 | 状态 | 说明 | | -------------- | ---- | -------------------------------- | | U(Untracked) | 新增 | 表示该资源未发布过,为新增的资源 | | D(Deleted) | 删除 | 表示该资源将被删除 | | M(Modify) | 修改 | 表示该资源已被修改 | ### 3. 开始发布 点击「开始发布」后,系统将按照依赖关系自动部署资源。 :::tip 发布过程中请保持网络连接稳定。云函数的发布可能需要一定时间安装依赖,请耐心等待。 ::: ## 回滚机制 如果发布过程中出现了问题,您可以: - **手动回滚**:使用[预览中的版本管理功能](./sandbox.md)选择历史版本重新发布 :::warning 回滚操作不会影响当前版本已发布的数据和配置。 ::: ## 下一步 资源发布完成后,您可以: 🚀 **[进行应用发布 →](./app-publish.md)** 将前端应用部署到线上,为用户提供完整的访问体验 🔧 **[测试应用功能 →](./sandbox.md)** 在预览环境中验证发布后的功能是否正常 --- ## 应用预览 # 应用预览 在对话过程中,AI Builder 会根据您的描述智能生成应用的基础结构。细节编辑阶段则允许您进一步完善和调整应用的具体细节,从而优化用户界面和交互体验。预览区菜单提供的功能包括: | 功能 | 说明 | | -------------- | ------------------------------------------------------ | | **实时预览** | 在编辑过程中实时查看应用效果,所见即所得 | | **细节编辑** | 在预览中选择组件,进行[细节编辑](./detail-editing.md) | | **设备模拟** | 在不同设备(手机、平板、桌面端)上预览应用的响应式效果 | | **应用分享** | 通过链接形式分享当前生成的应用 | | **开发控制台** | 打开预览应用的控制台,便于调试和开发 | | **版本管理** | 预览或回滚到之前的版本 | ## 实时预览 在回滚操作完成或 React 页面生成后,您可以在预览区域查看应用的实时效果。如果预览区域显示为空白,请检查当前会话是否已成功生成 React 页面。 如果当前会话尚未生成 React 页面,您可以通过与 AI 对话来指导生成 React 页面。 :::tip 提示:如果 AI 无法生成 React 页面,请检查您的需求描述是否清晰,是否包含了必要的信息。 预览区默认以超级管理员身份登录,如需测试用户登录功能,请先让 AI 执行退出登录操作,您可以在[登录配置](./login.md)中自定义登录信息。 ::: ## 设备模拟预览 您可以模拟在不同设备上查看应用的效果,包括手机、平板和桌面端。在预览界面中,只需点击相应的设备图标即可切换不同的设备视图,帮助您确保应用在各种屏幕尺寸下都能正常显示。 ## 应用分享 :::warning 注意:分享的应用保留原有的数据访问权限,如果您未妥善配置用户管理,可能存在数据安全风险。 ::: 您可以通过链接或二维码方式,便捷地分享当前生成的应用,让其他人快速体验您的创作成果。 ## 开发控制台 开发控制台是调试和开发应用的重要工具,帮助您快速定位和解决问题。 ### 功能特性 - **实时日志查看**:查看应用运行时的控制台输出和错误信息 - **网络请求监控**:监控 API 调用和数据请求的状态 - **性能分析**:分析页面加载时间和资源使用情况 - **错误追踪**:快速定位 JavaScript 错误和异常 ### 使用方法 1. 在预览界面点击「控制台」按钮 2. 控制台面板将在底部或侧边打开 3. 选择相应的标签页查看不同类型的信息 4. 使用过滤功能快速找到特定的日志或错误 ## 版本管理 版本管理功能让您能够轻松管理生成应用、数据模型及云函数的不同版本,确保开发过程的安全性和可追溯性。 ### 主要功能 - **版本历史**:查看应用的所有历史版本和变更记录 - **版本对比**:对比不同版本之间的差异 - **快速回滚**:一键回滚到任意历史版本 - **版本标记**:为重要版本添加标记和说明 ### 操作步骤 1. 在预览界面点击「版本管理」按钮 2. 浏览版本历史列表,查看各版本的创建时间和变更说明 3. 选择目标版本,可以预览当前版本的内容 4. 确认无误后,点击「回滚」恢复到该版本 :::warning 回滚操作会丢失回滚版本之后版本的内容,请在回滚前确认操作的必要性。 ::: --- ## 通过 API 调用 # 通过 API 调用 前往 [云开发平台/环境配置/API Key 配置页面](https://tcb.cloud.tencent.com/dev#/env/apikey) 即可新建 API Key。 获取到 API Key 后,即可进行 HTTP API 调用,只需要在 HTTP 请求中附带 `Authorization: Bearer ` 请求头。 可用的 HTTP API 包括: - [大模型 HTTP API](/http-api/ai-model/call-llm) - [AI Agent HTTP API](/http-api/ai-bot/send-message) - [知识库 HTTP API](/http-api/knowledge/search) ## 大模型调用 ### cURL 示例 以下是一个使用 cURL 调用大模型 HTTP API 的示例: ```shell curl -X POST 'https://your-env-id.api.tcloudbasegateway.com/v1/ai/deepseek/v1/chat/completions' \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ -H 'Accept: text/event-stream' \ -d '{ "model": "deepseek-r1", "messages": [ { "role": "user", "content": "介绍一下你自己" } ], "stream": true }' ``` ### OpenAI SDK 示例 获取到 API Key 后,也可以使用 OpenAI SDK 访问大模型服务,只需要替换 `baseURL` 及 `apiKey` 即可,以下是一个示例: ```js const OpenAI = require("openai"); const client = new OpenAI({ apiKey: "您的 API Key", baseURL: "https://your-env-id.api.tcloudbasegateway.com/v1/ai/deepseek/v1", }); async function main() { const completion = await client.chat.completions.create({ model: "deepseek-r1", messages: [{ role: "user", content: "你好" }], temperature: 0.3, stream: true, }); for await (const chunk of completion) { console.log(chunk); } } main(); ``` ## AI Agent 调用 ### cURL 示例 以下是一个使用 cURL 调用 AI Agent HTTP API 的示例: ```shell curl 'https://.api.tcloudbasegateway.com/v1/aibot/bots//send-message' \ -H 'Authorization: Bearer ' \ -H 'Accept: text/event-stream' \ -H 'Content-Type: application/json' \ --data-raw '{"msg":"hi"}' ``` ## 知识库调用 ### cURL 示例 以下是一个使用 cURL 调用 知识库 HTTP API 的示例: ```shell curl 'https://.api.tcloudbasegateway.com/v1/knowlege/send-message' \ -H 'Authorization: Bearer ' \ -H 'Accept: text/event-stream' \ -H 'Content-Type: application/json' \ -d '{ "collectionView": "ykfty_6fWO", "search": { "content": "云开发 AI+ 最新有哪些新功能?", "limit": "5" } }' ``` --- ## AITools # AITools BotCore 对外提供的一些工具,用户可以使用 tools 快速实现基础功能。 `AITools` 目前对外提供的工具 | `AITools` 方法名 | 描述 | | --------------------------------------------- | ---------------------- | | [`searchDB`](#searchdb) | 查询数据模型内容 | | [`searchFile`](#searchfile) | 查询文件内容 | | [`searchKnowledgeBase`](#searchknowledgebase) | 查询知识库内容 | | [`searchNetwork`](#searchnetwork) | 查询联网内容 | | [`sendWxClientMessage`](#sendwxclientmessage) | 推送信息到微信客户端 | | [`speechToText`](#speechtotext) | 语音转文字 | | [`textToSpeech`](#texttospeech) | 文字转语音 | | [`getTextToSpeech`](#gettexttospeech) | 获取文字转语音结果 | | [`getWxMediaContent`](#getwxmediacontent) | 获取微信回调中语音内容 | ## 方法 ### searchDB() > **searchDB**(`botId`, `msg`, `databaseModel`): `Promise`\ 查询数据模型内容 #### 参数 ##### botId > `string` botId,即函数型 Agent 的 ID ##### msg > `string` 对话消息内容 ##### databaseModel > `string`[] 数据模型列表 #### Returns `Promise`\ #### 使用示例 ```ts const result = await this.botContext.bot.tools.searchDB( this.botContext.info.botId, msg, this.botContext.info.databaseModel ); if (result?.code && result?.code?.length !== 0) { throw new Error(`查询数据模型内容失败: ${result?.message}`); } ``` --- ### searchFile() > **searchFile**(`botId`, `msg`, `files`): `Promise`\ 查询文件内容 #### 参数 ##### botId > `string` botId,即函数型 Agent 的 ID ##### msg > `string` 对话消息内容 ##### files > `string`[] 文件上传到云存储中的 fileID #### Returns `Promise`\ #### 使用示例 ```ts const result = await this.botContext.bot.tools.searchFile( this.botContext.info.botId, msg, files ); if (result?.code && result?.code?.length !== 0) { throw new Error(`查询文件内容失败: ${result?.message}`); } ``` --- ### searchKnowledgeBase() > **searchKnowledgeBase**(`botId`, `msg`, `knowledgeBase`): `Promise`\ 查询知识库内容 #### 参数 ##### botId > `string` botId,即函数型 Agent 的 ID ##### msg > `string` 对话消息内容 ##### knowledgeBase > `string`[] 知识库 ID #### Returns `Promise`\ #### 使用示例 ```ts const result = await this.botContext.bot.tools.searchKnowledgeBase( this.botContext.info.botId, msg, this.botContext.info.knowledgeBase ); if (result?.code && result?.code?.length !== 0) { throw new Error(`查询知识库内容失败: ${result?.message}`); } ``` --- ### searchNetwork() > **searchNetwork**(`botId`, `msg`): `Promise`\ 查询联网内容 #### 参数 ##### botId > `string` botId,即函数型 Agent 的 ID ##### msg > `string` 对话消息内容 #### Returns `Promise`\ #### 使用示例 ```ts const result = await this.botContext.bot.tools.searchNetwork( this.botContext.info.botId, msg ); if (result?.code && result?.code?.length !== 0) { throw new Error(`查询联网内容失败 ${result?.message}`); } ``` --- ### sendWxClientMessage() > **sendWxClientMessage**(`botId`, `triggerSrc`, `wxClientMessage`): `Promise`\ 推送信息到微信客户端 #### 参数 ##### botId > `string` botId,即函数型 Agent 的 ID ##### triggerSrc > `string` 微信回调来源 ##### wxClientMessage > [`WxClientMessageDto`](#wxclientmessagedto) 推送到微信客户端的消息内容 #### Returns `Promise`\ #### 使用示例 ```ts const sendResult = await this.botContext.bot.tools.sendWxClientMessage( this.botContext.bot.botId, triggerSrc, { msgType: toWxMsgData?.msgType, touser: toWxMsgData?.touser, text: toWxMsgData?.text, openKfId: toWxMsgData?.openKfId, msgId: toWxMsgData?.msgId, } ); console.log("sendResult:", sendResult); ``` --- ### speechToText() > **speechToText**(`botId`, `engSerViceType`, `voiceFormat`, `voiceUrl`): `Promise`\ 语音转文字 #### 参数 ##### botId > `string` botId,即函数型 Agent 的 ID ##### engSerViceType > `string` 语言类型 ##### voiceFormat > `string` 语音文件类型,输入语言 16k_zh:中文通用 16k_zh-PY:中英粤 16k_zh_medical:中文医疗 16k_en:英语 16k_yue:粤语 ##### voiceUrl > `string` 语音文件公网链接 #### Returns `Promise`\ #### 使用示例 ```ts const result = await this.botContext.bot.tools.speechToText( this.botContext.info.botId, input.engSerViceType, input.voiceFormat, input.url ); if (result?.code && result?.code?.length !== 0) { throw new Error(`语音转文字失败: ${result?.message}`); } ``` --- ### textToSpeech() > **textToSpeech**(`botId`, `text`, `voiceType`): `Promise`\ 文字转语音 #### 参数 ##### botId > `string` botId,即函数型 Agent 的 ID ##### text > `string` 需要转换成语音的文字 ##### voiceType > `number` 需要转换成的语音类型, 输出声音类型 101004:通用男声 101005:通用女声 601004:咨询男声 501001:咨询女声 101010:通用男声(大模型) 101035:通用女声(大模型) #### Returns `Promise`\ #### 使用示例 ```ts const result = await this.botContext.bot.tools.textToSpeech( this.botContext.info.botId, input.text, input.voiceType ); if (result?.code && result?.code?.length !== 0) { throw new Error(`文字转语音失败: ${result?.message}`); } ``` --- ### getTextToSpeech() > **getTextToSpeech**(`botId`, `taskId`): `Promise`\ 获取文字转语音结果 #### 参数 ##### botId > `string` botId,即函数型 Agent 的 ID ##### taskId > `string` textToSpeech 接口返回的 taskID #### Returns `Promise`\ #### 使用示例 ```ts const result = await this.botContext.bot.tools.getTextToSpeech( this.botContext.info.botId, input.taskId ); if (result?.code && result?.code?.length !== 0) { throw new Error(`查询文字转语音状态失败: ${result?.message}`); } ``` --- ### getWxMediaContent() > **getWxMediaContent**(`botId`, `triggerSrc`, `media`): `Promise`\ 获取微信回调中语音内容 #### 参数 ##### botId > `string` botId,即函数型 Agent 的 ID ##### triggerSrc > `string` 微信回调来源 ##### media > `string` 微信语音 media ID #### Returns `Promise`\ #### 使用示例 ```ts const mediaResult = await this.botContext.bot.tools.getWxMediaContent( this.botContext.bot.botId, triggerSrc, mediaId ); content = mediaResult?.content; ``` --- ## 类型 ### ChatDBSearchResult #### 属性 ##### answerPrompt > **answerPrompt**: `string` ##### relateTables > **relateTables**: `unknown`[] --- ### SearchDBResult #### 属性 ##### code? > `optional` **code**: `string` ##### message? > `optional` **message**: `string` ##### searchResult > **searchResult**: [`ChatDBSearchResult`](#ChatDBSearchResult) --- ### SearchFileResult #### Properties ##### code? > `optional` **code**: `string` ##### content > **content**: `string` ##### message? > `optional` **message**: `string` --- ### KnowledgeBaseDocument #### 属性 ##### data > **data**: `object` ###### allParentParagraphTitles > **allParentParagraphTitles**: `string`[] ###### endPos > **endPos**: `number` ###### next > **next**: `unknown`[] ###### paragraphTitle > **paragraphTitle**: `string` ###### pre > **pre**: `unknown`[] ###### startPos > **startPos**: `number` ###### text > **text**: `string` ##### documentSet > **documentSet**: `object` ###### author > **author**: `string` ###### documentSetId > **documentSetId**: `string` ###### documentSetName > **documentSetName**: `string` ###### fileId > **fileId**: `string` ###### fileMetaData > **fileMetaData**: `string` ###### fileTitle > **fileTitle**: `string` --- ##### score > **score**: `number` --- ### SearchKnowledgeResult #### 属性 ##### code? > `optional` **code**: `string` ##### documents > **documents**: [`KnowledgeBaseDocument`](#KnowledgeBaseDocument) ##### knowledgeBase? > `optional` **knowledgeBase**: `string`[] ##### knowledgeMeta? > `optional` **knowledgeMeta**: `string`[] ##### message? > `optional` **message**: `string` --- ### SearchResult #### Properties ##### abstract > **abstract**: `string` ##### extra? > `optional` **extra**: `string` ##### index > **index**: `number` ##### publisher > **publisher**: `string` ##### publishTime > **publishTime**: `number` ##### source > **source**: `"thirdparty"` \| `"knowledgebase"` ##### title > **title**: `string` ##### url > **url**: `string` --- ### SearchInfo #### Properties ##### searchResults > **searchResults**: [`SearchResult`](#SearchResult)[] --- ### SearchNetworkResult #### Properties ##### code? > `optional` **code**: `string` ##### content > **content**: `string` ##### message? > `optional` **message**: `string` ##### searchInfo > **searchInfo**: [`SearchInfo`](#SearchInfo) --- ### toolsCommonResp #### 属性 ##### code? > `optional` **code**: `string` ##### message? > `optional` **message**: `string` --- ### WxClientMessageDto #### 属性 ##### msgId > **msgId**: `string` ##### msgType > **msgType**: `string` ##### openKfId? > `optional` **openKfId**: `string` ##### text > **text**: `object` ###### content > **content**: `string` ##### touser > **touser**: `string` --- ### SpeechToTextResult #### 属性 ##### code? > `optional` **code**: `string` ##### message? > `optional` **message**: `string` ##### result > **result**: `string` --- ### TextToSpeechResult #### 属性 ##### code? > `optional` **code**: `string` ##### message? > `optional` **message**: `string` ##### taskId > **taskId**: `string` --- ### GetTextToSpeechResult #### 属性 ##### code? > `optional` **code**: `string` ##### message? > `optional` **message**: `string` ##### resultUrl > **resultUrl**: `string` ##### status > **status**: `number` ##### statusStr > **statusStr**: `string` ##### taskId > **taskId**: `string` --- ### GetWxMediaContentResult #### 属性 ##### code? > `optional` **code**: `string` ##### content > **content**: `string` ##### message? > `optional` **message**: `string` --- --- ## BotCore # BotCore 提供函数型 Agent 基本功能的基类。继承此类以快速实现函数型 Agent。 ## context 云函数上下文,详见[函数型云托管 | 函数的输入参数 `event` 和 `context`](../../cbrf/how-to-writing-functions-code#函数的输入参数-event-和-context)。 ## botId > `string` botId,即函数型 Agent 的 id。 ## botTag > `string` 函数型 Agent 的 [botId](#botid) 的格式为 `ibot-xxx-botTag`,以 `-` 为分隔,一共有三段,我们将第三段称为 `botTag`。 ## sseSender ```ts interface SSESender { send(prop: { data: { content: string } }): void; end(): void; } ``` 提供流式返回 SSE 消息的对象。提供两个方法: - `send()` 发送 SSE 消息,其中 `prop.data.content` 字段为 Agent 的文本输出。 - `end()` 结束 SSE 并发送结尾消息。当所有内容都发送完毕后,可调用此方法结束 SSE 链接。 ### 使用示例 下面是一个将字符串分字符流式传输给客户端的示例: ```ts class MyBot extends BotCore { async sendMessage() { const ANSWER = "这是一条流式传输的内容。"; for (let i = 0; i **tools**: [`AITools`](AITools.md) BotCore 对外提供的一些工具,用户可以使用 tools 快速实现基础功能 ## chatRecord ```ts type ChatRecordDataModel = DataModelMethods; ``` 聊天记录数据模型,提供增删改查等方法。详情可参考 [数据模型 | SDK 类型声明 | DataModelMethods](../../model/sdk-reference/globals#datamodelmethodst)。 :::tip `BotCore` 在此数据模型之上封装了 [`createRecordPair`](#createrecordpair), [`getChatRecords`](#getchatrecords),[`getHistoryMessages`](#gethistorymessages) 等方法,可满足大部分场景下的需求。其他更细致的需求可以通过此属性自行操作聊天记录数据模型实现。 ::: ### 使用示例 下面是一个获取聊天记录列表的示例: ```ts class MyBot extends BotCore { getRecordList() { return this.chatRecord.list({ pageSize: 10, }); } } ``` 更多数据模型使用示例可前往 [数据模型 | SDK 类型声明 | DataModelMethods](../../model/sdk-reference/globals#datamodelmethodst) 查看。 ## createRecordPair() ```ts interface CreateRecordPair { ({ userContent: string }): Promise Promise; }>; } ``` 创建一对 「用户 - Agent」 的聊天记录,并存到数据模型中,返回值中提供更新 Agent 聊天记录的方法。 在 Agent 对话的场景中,聊天记录成对出现,用户发送一条信息后,Agent 应该针对该信息进行回复。 该方法要求传入用户的聊天内容,会在数据模型中创建: - 用户的聊天记录,内容为传入的聊天内容 - Agent 聊天记录,内容为空 开发者能从返回值中获取到 `updateBotRecord` 函数。在收集到完整的 Agent 聊天内容后,可以调用该函数更新 Agent 聊天记录。 ### 使用示例 下面的例子将会通过与大模型对话实现 Agent ,并将用户的消息记录和大模型的回复都存入数据模型中。 ```ts import OpenAI from "openai"; const client = new OpenAI(); class MyBot extends BotCore { sendMessage({ msg }) { // 创建一对 「用户 - Agent」 的聊天记录 const { updateBotRecord } = await this.createRecordPair({ userContent: msg, }); const chatCompletion = await client.chat.completions.create({ messages: [{ role: "user", content: "Say this is a test" }], model: "gpt-4o", stream: true, }); // 创建个变量存储 Agent 的消息 let content = ""; for await (const chunk of stream) { const chunkContent = chunk.choices[0]?.delta?.content || ""; // 发送 SSE 消息给客户端 this.sseSender.send({ data: { content: chunkContent } }); // 将消息片段累加到 content 变量中 content += chunkContent; } // 结束 SSE 传输 this.sseSender.end(); // 更新 Agent 聊天记录 await updateBotRecord({ content }); } } ``` ## getHistoryMessages() ```ts interface GetHistoryMessages { (option?: { size?: number; removeLastUser?: boolean }): Promise >; } ``` 从聊天记录数据模型中获取历史消息,返回值为聊天记录数组,但针对该数组进行了特殊处理,保证: 1. 数组以用户的聊天记录开头 2. 数组中,用户和 Agent 的聊天记录交替出现,呈一问一答状 3. (默认)数组以 Agent 的聊天记录结尾 4. 每个聊天记录的 `content` 字段不为空 ### 参数 #### 入参 | 参数 | 类型 | 描述 | | --------------------- | --------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | | option.size | `number` | 获取的聊天记录数量。该数量对应着从聊天记录数据模型中获取多少条数据,由于在此方法中会对聊天记录进行过滤,因此返回的聊天记录数量可能少于实际传入的值 | | option.removeLastUser | `boolean` | 是否保证以 Agent 聊天记录结尾 | ### 使用示例 下面的例子将会通过与大模型对话实现 Agent,在发起调用时,会从数据模型中读取用户与 Agent 的历史消息,一并传给大模型。 ```ts import OpenAI from "openai"; const client = new OpenAI(); class MyBot extends BotCore { sendMessage({ msg }) { // 获取历史消息 const history = await this.getHistoryMessage(); const chatCompletion = await client.chat.completions.create({ messages: [ ...history, // 在请求参数中加入历史消息 { role: "user", content: "Say this is a test" }, ], model: "gpt-4o", stream: true, }); for await (const chunk of stream) { const chunkContent = chunk.choices[0]?.delta?.content || ""; // 发送 SSE 消息给客户端 this.sseSender.send({ data: { content: chunkContent } }); } // 结束 SSE 传输 this.sseSender.end(); } } ``` ## getChatRecords() 从数据模型中获取聊天记录,`BotCore` 提供的 `IBot` 接口定义的 `getChatRecords` 的默认实现。 --- ## IBot # IBot 函数型 Agent 框架提供了 `IBot` 接口,开发者只要实现一个满足 `IBot` 的类,就可以部署起相应的服务。 `IBot` 完整的方法定义及对应的服务如下: | 提供的服务 | `IBot` 方法名 | 描述 | | --------------------------------------------------------- | ------------------------------------------------- | --------------------------- | | `POST /v1/aibot/bots/:botId/send-message` | [`sendMessage`](#sendmessage) | 与 Agent 进行对话 | | `POST /v1/aibot/bots/:botId/wx-send-message` | [`wxSendMessage`](#wxsendmessage) | 与 Agent 进行对话(微信回调) | | `GET /v1/aibot/bots/:botId` | [`getBotInfo`](#getbotinfo) | 查询 Agent 配置信息 | | `GET /v1/aibot/bots/:botId/records` | [`getChatRecords`](#getchatrecords) | 查询 Agent 历史对话信息 | | `POST /v1/aibot/bots/:botId/recommend-questions` | [`getRecommendQuestions`](#getrecommendquestions) | 获取推荐问题 | | `POST /v1/aibot/bots/:botId/feedback` | [`sendFeedback`](#sendfeedback) | 提交用户反馈 | | `GET /v1/aibot/bots/:botId/feedback` | [`getFeedback`](#getfeedback) | 查询用户反馈 | | `POST /v1/aibot/bots/:botId/speech-to-text` | [`speechToText`](#speechtotext) | 语音转文字 | | `POST /v1/aibot/bots/:botId/text-to-speech` | [`textToSpeech`](#texttospeech) | 文字转语音 | | `GET /v1/aibot/bots/:botId/text-to-speech` | [`getTextToSpeechResult`](#gettexttospeechresult) | 获取文字转语音结果 | | `POST /v1/aibot/bots/:botId/conversation` | [`createConversation`](#createconversation) | 创建会话 | | `GET /v1/aibot/bots/:botId/conversation` | [`getConversation`](#getconversation) | 查询会话 | | `PATCH /v1/aibot/bots/:botId/conversation/:conversation` | [`updateConversation`](#updateconversation) | 更新会话 | | `DELETE /v1/aibot/bots/:botId/conversation/:conversation` | [`deleteConversation`](#deleteconversation) | 删除会话 | 使用 [`BotCore` 基类](BotCore) 能够更加快速地实现 `IBot` 接口。 ## 方法 ### sendMessage() > **sendMessage**(`input`): `Promise`\ sendMessage - POST /v1/aibot/bots/:botId/send-message 与 Agent 问答对话接口实现,该接口无返回值,接口内需要通过 this.sseSender 发送 Server-Sent Events 给客户端 微信基础库 [`wx.cloud.extend.AI.bot.sendMessage`](https://developers.weixin.qq.com/miniprogram/dev/wxcloudservice/wxcloud/reference-sdk-api/extend/ai.html#AI-bot-sendMessage) API 对应接口 #### 参数 调用参数详见 [`HTTP API`](https://docs.cloudbase.net/http-api/ai-bot/send-message) 文档 --- ### wxSendMessage() > **wxSendMessage**(`input`): `Promise`\ wxSendMessage - POST /v1/aibot/bots/:botId/wx-send-message 使用微信接入后,微信客服消息回调 Agent 接口的实现,该接口根据微信 APPID 类型以及认证状态进行返回。 #### 参数 ##### input [`WxSendMessageInput`](#wxsendmessageinput) #### Returns `Promise`\ --- ### getBotInfo() > **getBotInfo**(`input`): `Promise`\ getBotInfo - POST /v1/aibot/bots/:botId 获取 Agent 配置,返回 Agent 信息 微信基础库 wx.cloud.extend.AI.bot.get API 对应接口 https://developers.weixin.qq.com/miniprogram/dev/wxcloudservice/wxcloud/reference-sdk-api/extend/ai.html#AI-bot-get #### 参数 调用参数详见 [`HTTP API`](https://docs.cloudbase.net/http-api/ai-bot/get-bot-info) 文档 --- ### getChatRecords()? > `optional` **getChatRecords**(`input`): `Promise`\ getChatRecords - GET /v1/aibot/bots/:botId/records 查询 Agent 历史对话信息接口实现,返回历史对话记录。 注意:需在 sendMessage 接口中实现记录对话信息,并在此接口查询对话信息并中返回 微信基础库 [`wx.cloud.extend.AI.bot.getChatRecords`](https://developers.weixin.qq.com/miniprogram/dev/wxcloudservice/wxcloud/reference-sdk-api/extend/ai.html#AI-bot-getChatRecords) API 对应接口 #### 参数 调用参数详见 [`HTTP API`](https://docs.cloudbase.net/http-api/ai-bot/get-chat-history) 文档 --- ### getFeedback()? > `optional` **getFeedback**(`input`): `Promise`\ getFeedback - GET /v1/aibot/bots/:botId/feedback 获取用户反馈接口实现,返回用户反馈列表 微信基础库 [`wx.cloud.extend.AI.bot.getFeedBack`](https://developers.weixin.qq.com/miniprogram/dev/wxcloudservice/wxcloud/reference-sdk-api/extend/ai.html#AI-bot-getFeedBack) API 对应接口 #### 参数 调用参数详见 [`HTTP API`](https://docs.cloudbase.net/http-api/ai-bot/get-feedback) 文档 --- ### getRecommendQuestions()? > `optional` **getRecommendQuestions**(`input`): `Promise`\ getRecommendQuestions - POST /v1/aibot/bots/:botId/recommend-questions 获取推荐问题接口实现,返回推荐问题列表 微信基础库 [`wx.cloud.extend.AI.bot.getRecommendQuestions`](https://developers.weixin.qq.com/miniprogram/dev/wxcloudservice/wxcloud/reference-sdk-api/extend/ai.html#AI-bot-getRecommendQuestions) API 对应接口 #### 参数 调用参数详见 [`HTTP API`](https://docs.cloudbase.net/http-api/ai-bot/get-recommend-questions) 文档 --- ### sendFeedback()? > `optional` **sendFeedback**(`input`): `Promise`\ sendFeedback - POST /v1/aibot/bots/:botId/feedback 发送用户反馈接口实现,返回发送用户反馈结果 微信基础库 [`wx.cloud.extend.AI.bot.sendFeedback`](https://developers.weixin.qq.com/miniprogram/dev/wxcloudservice/wxcloud/reference-sdk-api/extend/ai.html#AI-bot-sendFeedback) API 对应接口 #### 参数 ##### input [`SendFeedbackInput`](#sendfeedbackinput) #### 返回 `Promise`\ --- ### speechToText()? > `optional` **speechToText**(`input`): `Promise`\ speechToText - POST /v1/aibot/bots/:botId/speechToText 语音转文字 #### 参数 调用参数详见 [`HTTP API`](https://docs.cloudbase.net/http-api/ai-bot/speech-to-text) 文档 --- ### textToSpeech()? > `optional` **textToSpeech**(`input`): `Promise`\ text-to-speech - POST /v1/aibot/bots/:botId/text-to-speech 文字转语音 #### 参数 调用参数详见 [`HTTP API`](https://docs.cloudbase.net/http-api/ai-bot/text-to-speech) 文档 --- ### getTextToSpeechResult()? > `optional` **getTextToSpeechResult**(`input`): `Promise`\ text-to-speech - GET /v1/aibot/bots/:botId/text-to-speech 获取文字转语音结果 #### 参数 调用参数详见 [`HTTP API`](https://docs.cloudbase.net/http-api/ai-bot/get-text-to-speech-result) 文档 --- ### createConversation()? > `optional` **createConversation**(): `Promise`\ conversation - POST /v1/aibot/bots/:botId/conversation 创建会话 #### 参数 调用参数详见 [`HTTP API`](https://docs.cloudbase.net/http-api/ai-bot/create-conversation) 文档 --- ### getConversation()? > `optional` **getConversation**(`input`): `Promise`\ conversation - GET /v1/aibot/bots/:botId/conversation 查询会话 #### 参数 ##### input [`GetConversationInput`](#getconversationinput) #### Returns `Promise`\ --- ### updateConversation()? > `optional` **updateConversation**(`input`): `Promise`\ conversation - PATCH /v1/aibot/bots/:botId/conversation/:conversation 更新会话 #### 参数 ##### input [`UpdateConversationInput`](#updateconversationinput) #### Returns `Promise`\ --- ### deleteConversation()? > `optional` **deleteConversation**(`input`): `Promise`\ conversation - DELETE /v1/aibot/bots/:botId/conversation/:conversation 删除会话 #### 参数 ##### input [`DeleteConversationInput`](#deleteconversationinput) #### Returns `Promise`\ --- ## 类型 ### GetChatRecordOutput #### 属性 ##### recordList > **recordList**: `object`[] ###### botId? > `optional` **botId**: `string` ###### content? > `optional` **content**: `string` ###### conversation? > `optional` **conversation**: `string` ###### createTime? > `optional` **createTime**: `string` ###### image? > `optional` **image**: `string` ###### recordId? > `optional` **recordId**: `string` ###### reply? > `optional` **reply**: `string` ###### replyTo? > `optional` **replyTo**: `string` ###### role? > `optional` **role**: `string` ###### triggerSrc? > `optional` **triggerSrc**: `string` ###### type? > `optional` **type**: `string` ##### total > **total**: `number` --- ### GetFeedbackOutput #### 属性 ##### feedbackList > **feedbackList**: `object`[] ###### aiAnswer > **aiAnswer**: `string` ###### botId > **botId**: `string` ###### comment > **comment**: `string` ###### createTime > **createTime**: `string` ###### input > **input**: `string` ###### rating > **rating**: `number` ###### sender > **sender**: `string` ###### tags > **tags**: `string`[] ###### type > **type**: `string` ##### total > **total**: `number` --- ### SendFeedbackInput #### 属性 ##### aiAnswer > **aiAnswer**: `string` ##### comment > **comment**: `string` ##### input > **input**: `string` ##### rating > **rating**: `number` ##### recordId > **recordId**: `string` ##### tags > **tags**: `string`[] ##### type > **type**: `string` --- ### SendFeedbackOutput #### 属性 ##### status > **status**: `"success"` --- ### SendMessageInput #### 属性 ##### history? > `optional` **history**: `object`[] ###### content > **content**: `string` ###### role > **role**: `"user"` \| `"assistant"` ##### msg > **msg**: `string` --- ### WeChatTextInput #### Properties ##### content > **content**: `string` ##### createTime > **createTime**: `number` ##### fromUserName > **fromUserName**: `string` ##### msgId > **msgId**: `string` ##### msgType > **msgType**: `string` ##### toUserName > **toUserName**: `string` --- ### WeChatVoiceInput #### 属性 ##### createTime > **createTime**: `number` ##### format > **format**: `string` ##### fromUserName > **fromUserName**: `string` ##### mediaId > **mediaId**: `string` ##### msgId > **msgId**: `string` ##### msgType > **msgType**: `string` ##### toUserName > **toUserName**: `string` --- ### WeChatWorkTextInput #### 属性 ##### externalUserId > **externalUserId**: `string` ##### msgId > **msgId**: `string` ##### msgType > **msgType**: `string` ##### openKfId > **openKfId**: `string` ##### origin > **origin**: `number` ##### sendTime > **sendTime**: `number` ##### text > **text**: `object` ###### content > **content**: `string` --- ### WeChatWorkVoiceInput #### 属性 ##### externalUserId > **externalUserId**: `string` ##### msgId > **msgId**: `string` ##### msgType > **msgType**: `string` ##### openKfId > **openKfId**: `string` ##### origin > **origin**: `number` ##### sendTime > **sendTime**: `number` ##### voice > **voice**: `object` ###### mediaId > **mediaId**: `string` --- ### WxSendMessageInput #### 属性 ##### callbackData 微信回调消息 > **callbackData**: [`WeChatTextInput`](#WeChatTextInput) \| [`WeChatVoiceInput`](#WeChatTextInput) \| [`WeChatWorkTextInput`](#WeChatWorkTextInput) \| [`WeChatWorkVoiceInput`](#WeChatWorkVoiceInput) ##### triggerSrc? 根据微信 APPID 传入来源类型,微信订阅号: WXSubscription 微信服务号: WXService 微信小程序客服: WXMiniapp 企业微信客服: WXCustomerService > `optional` **triggerSrc**: `string` ##### wxVerify? 微信 APPID 的认证状态 > `optional` **wxVerify**: `boolean` --- ### WeChatTextOutput #### 属性 ##### Content? > `optional` **Content**: `string` ##### CreateTime? > `optional` **CreateTime**: `number` ##### FromUserName? > `optional` **FromUserName**: `string` ##### MsgType? > `optional` **MsgType**: `string` ##### ToUserName? > `optional` **ToUserName**: `string` ### SpeechToTextInput #### 属性 ##### engSerViceType 输入语言类型 > **engSerViceType**: `string` ##### url 语音文件链接 > **url**: `string` ##### voiceFormat 识别音频的音频格式,如 wav/mp3 > **voiceFormat**: `string` --- ### SpeechToTextOutput #### 属性 ##### Result > **Result**: `string` --- ### TextToSpeechOutput #### 属性 ##### TaskId > **TaskId**: `string` --- ### GetTextToSpeechResultOutput #### 属性 ##### ResultUrl > **ResultUrl**: `string` ##### Status > **Status**: `number` ##### StatusStr > **StatusStr**: `string` ##### TaskId > **TaskId**: `string` --- ### CreateConversationOutput #### 属性 ##### conversationId > **conversationId**: `string` ##### title > **title**: `string` --- ### GetConversationInput #### 属性 ##### conversationId? > `optional` **conversationId**: `string` ##### limit? > `optional` **limit**: `number` ##### offset? > `optional` **offset**: `number` --- ### GetConversationOutput #### 属性 ##### data > **data**: `object`[] ###### conversationId > **conversationId**: `string` ###### createTime > **createTime**: `string` ###### title > **title**: `string` ###### updateTime > **updateTime**: `string` ##### total > **total**: `number` --- ### UpdateConversationInput #### 属性 ##### conversationId? > `optional` **conversationId**: `string` ##### title > **title**: `string` --- ### UpdateConversationOutput #### 属性 ##### count > **count**: `number` --- ### DeleteConversationInput #### 属性 ##### conversationId > **conversationId**: `string` --- ### DeleteConversationOutput #### 属性 ##### count > **count**: `number` --- ### GetBotInfoOutput #### 属性 ##### agentSetting? > `optional` **agentSetting**: `string` ##### avatar? > `optional` **avatar**: `string` ##### background? > `optional` **background**: `string` ##### botId? > `optional` **botId**: `string` ##### databaseModel? > `optional` **databaseModel**: `string`[] ##### initQuestions? > `optional` **initQuestions**: `string`[] ##### introduction? > `optional` **introduction**: `string` ##### isNeedRecommend? > `optional` **isNeedRecommend**: `boolean` ##### knowledgeBase? > `optional` **knowledgeBase**: `string`[] ##### mcpServerList? > `optional` **mcpServerList**: `object`[] ###### name? > `optional` **name**: `string` ###### tools > **tools**: `object`[] ###### url? > `optional` **url**: `string` ##### model? > `optional` **model**: `string` ##### modelValue? > `optional` **modelValue**: `string` ##### multiConversationEnable? > `optional` **multiConversationEnable**: `boolean` ##### name? > `optional` **name**: `string` ##### searchEnable? > `optional` **searchEnable**: `boolean` ##### searchFileEnable? > `optional` **searchFileEnable**: `boolean` ##### tags? > `optional` **tags**: `string`[] ##### type? > `optional` **type**: `string` ##### updateTime? > `optional` **updateTime**: `number` ##### voiceSettings? > `optional` **voiceSettings**: `object` ###### enable? > `optional` **enable**: `boolean` ###### inputType? > `optional` **inputType**: `string` ###### outputType? > `optional` **outputType**: `number` ##### welcomeMessage? > `optional` **welcomeMessage**: `string` --- --- ## 开发 Agent import webAccessRaw from "./images/web-access-raw.png" import runTcbFF from "./images/run-tcb-ff.png" import webAccessAgent from "./images/web-access-agent.png" import curlAccessAgent from "./images/curl-access-agent.png" import createAgentOnCloud from "./images/tcbdev-aiagent-create.png" # 开发 Agent 本文介绍如何基于函数型云托管开发、调试、并部署一个 AI Agent。 以下为一个简单的 `AI Agent` 示例代码: ```js const { BotRunner, BotCore } = require("@cloudbase/aiagent-framework"); const ANSWER = "你好,我是一个 Agent ,但我只会说这一句话。"; class MyBot extends BotCore { async sendMessage() { for (let i = 0; i BotRunner.run(event, context, new MyBot(context)); ``` > 该代码的完整项目示例可参考模板:[Github](https://github.com/TencentCloudBase/cloudbase-examples/tree/master/cloudrunfunctions/empty-agent)、[Gitee](https://gitee.com/TencentCloudBase/Cloudbase-Examples/tree/master/cloudrunfunctions/empty-agent)。 新建一个文件夹,创建 `index.js` 并填入以上代码,并运行 `npm i @cloudbase/aiagent-framework` 安装相关依赖,即可实现一个简单的 Agent 。 实现 `Agent` 的关键在于实现 [`IBot` 接口](./IBot)上定义好的方法。借助 [`BotCore` 类](./BotCore),我们只需要几段代码即可完成实现: 以上代码实现了一个 `MyBot` 类,它有这几个特点: - 继承自 [`BotCore` 类](./BotCore),可以通过 [`this.sseSender`](./BotCore#ssesender) 获取到发送 SSE 响应的能力 - 实现了 [`IBot` 接口](./IBot),按照定义,我们最少需要实现 [`sendMessage`](./IBot#sendmessage) 方法。此处我们实现的 Agent 将永远返回一句固定的话 云开发 Agent 开发框架 `@cloudbase/aiagent-framework` 使用可以参考: ## 本地开发调试 Agent 新建 `package.json` 文件,并写入以下内容: ```json { "name": "function-agent-test", "main": "index.js", "scripts": { "login": "tcb login", "dev": "tcb cloudrun run --runMode=agent -w", "deploy": "tcb cloudrun deploy" }, "dependencies": { "@cloudbase/aiagent-framework": "^1.0.0-beta.10" }, "devDependencies": { "@cloudbase/cli": "^2.6.16" } } ``` 安装依赖: ```shell npm install ``` 安装完成后,可以输入以下命令进行登录: ```shell npm run login ``` ### 启动 Agent 服务 运行以下命令启动服务: ```shell npm run dev ``` ### 调用 Agent 服务 #### 命令行使用 `cURL` 访问 ```shell curl 'http://127.0.0.1:3000/v1/aibot/bots/ibot-myBot-botTag/send-message' \ -H 'Accept: text/event-stream' \ -H 'Content-Type: application/json' \ --data-raw '{"msg":"hi"}' ``` 运行结果如下: #### Web 使用 `@cloudbase/js-sdk` 访问 [@cloudbase/js-sdk](https://www.npmjs.com/package/@cloudbase/js-sdk) 提供了客户端接入 Agent 接口的方法,可前往 [云开发文档](https://docs.cloudbase.net/ai/agent/sdk#api-%E5%8F%82%E8%80%83) 查看。 以下是个使用 @cloudbase/js-sdk 的 HTML 示例: ```html Test Agent const p = document.getElementById("result"); async function main() { const app = cloudbase.init({ env: "your-env-id", // 填入云开发环境 id }); const auth = app.auth(); await auth.signInAnonymously(); const ai = app.ai(); const res = await ai.bot.sendMessage({ botId: "ibot-myBot-botTag", msg: "hi", }); for await (let x of res.textStream) { console.log(x); p.innerText += x; } } main(); ``` 本地启动一个服务器,以便能够通过浏览器访问这个 HTML 文件。我们还需要配置一定代理服务,以便能将请求访问到本地服务。以 [whistle](https://wproxy.org/whistle/) 举例,按照如下配置: ```shell /.*.api.tcloudbasegateway.com/([^S]*)/ http://localhost:3000/$1 ``` 打开网页,查看调用结果: ## 本地开发部署 Agent 运行以下命令部署 Agent : ```shell npm run deploy ``` 按提示选择环境、服务名即可。服务名格式须符合 `ibot-xxx` 格式。 ### 关联云托管服务与 Agent 若先创建了云托管服务,还未在云开发平台上创建对应的 Agent ,则可前往[云开发平台 AI+ 页面](https://tcb.cloud.tencent.com/dev#/ai?tab=agent)进行创建。 此时标识应该和云托管的服务名对齐,如云托管服务名为 `ibot-testAgent`,对应的 Agent 的标识应为 `ibot-testAgent-123456` (最后一段内容不会用于与云托管服务关联)。 ![ibot-id](https://qcloudimg.tencent-cloud.cn/raw/143f62de083e912aa55a552c500d9ac6.png)。 ## 云端开发调试 Agent ### Step.1: 创建 Agent 参考文档 描述的流程,创建 Agent 。 创建完成后,可在 Agent 列表也查看到对应的 Agent 。 点击 在线开发 后可以进入在线开发页面,进行基于函数型云托管的 Agent 开发。 ### Step.2: 开发调试 Agent 代码 - 如何在云端开发调试部署 Agent ,可以参考文档: - 如何使用 `@cloudbase/aiagent-framework` 框架可参考: - 如何编写基于函数型云托管开发 Agent 代码,可以参考函数编写指南: 更多示例代码可查看: - 空白 Agent 示例 [Github](https://github.com/TencentCloudBase/cloudbase-examples/tree/master/cloudrunfunctions/empty-agent) - 基于 DeepSeek Agent 示例 [Github](https://github.com/TencentCloudBase/cloudbase-examples/tree/master/cloudrunfunctions/deepseek-agent) - 元器 Agent 示例 [Github](https://github.com/TencentCloudBase/cloudbase-examples/tree/master/cloudrunfunctions/yuanqi-agent) - 基于 Mastra Agent 示例 [Github](https://github.com/TencentCloudBase/cloudbase-examples/tree/master/cloudrunfunctions/mastra-agent) ## 参考文档 - [Agent 框架 | IBot](./IBot) - [Agent 框架 | BotCore](./BotCore) --- ## 快速开始 # 快速开始 通过这个教程,我们将在云开发平台上创建一个 函数型 AI Agent 服务,并实现实现与 Agent 对话。 ## 创建函数型 Agent 服务 1. 登录[云开发平台](https://tcb.cloud.tencent.com/dev),点击左侧导航栏的`AI+`,然后切到 `Agent` Tab 页面,进入 Agent 服务列表页面。 2. 选择模板进行创建,点击 `下一步` 按钮,填写相关信息,即可创建 Agent 。 ![选择模板](https://qcloudimg.tencent-cloud.cn/raw/101789f6825af86a3013c8ccece73990.png) ![填写信息](https://qcloudimg.tencent-cloud.cn/raw/143f62de083e912aa55a552c500d9ac6.png) ## 调用 Agent 服务 Agent 创建完成后,即可与 Agent 进行对话。除了在预览界面中与 Agent 进行对话,还可以在 `Web/H5`、`小程序` 等场景中集成 Agent 服务。 ![tcbdev-aiagent-call](https://qcloudimg.tencent-cloud.cn/raw/6768c2c95f42a8bf690ba70bd086558e.png) ![tcbdev-aiagent-call](https://qcloudimg.tencent-cloud.cn/raw/8c164f36645b77abc2c1ad8fb38bec3a.png) --- ## 更新日志 # 更新日志 本文档记录 CloudBase AI ToolKit 的所有重要更新和版本变更。 ## 📦 最新版本 ### v1.8.40 (最新) 当前最新版本,包含完整的 AI CLI 集成和所有最新功能优化。 #### ✨ 新功能 - 🎉 **AI CLI 集成** - 新增 CloudBase AI CLI,支持一键管理多种 AI 编程工具 - 🎯 **智能交互系统** - 新增交互式工具,支持需求澄清、任务确认和用户友好的界面 - ☁️ **云托管插件** - 新增云托管服务管理功能,查询、部署、运维一体化 - 🤖 **AI 数据建模** - 通过 Mermaid ER图智能创建 MySQL 数据模型 - 📋 **工作流优化** - 新增 `/spec` 和 `/no_spec` 命令控制开发流程 - 🔐 **安全规则管理** - 统一管理数据库、云函数、存储的安全规则 - 🎁 **邀请码激活** - 支持 AI 编程用户邀请码激活功能 - 🔧 **多 IDE 支持** - 新增 CodeBuddy、Qwen Code、OpenCode 等 IDE 支持 - 📝 **认证规则优化** - 明确 Web 和小程序的认证方式差异 - 📊 **函数日志 V2** - 升级到新版日志接口,支持按需查询详情 #### 🔧 技术改进 - 优化日志系统,支持跨平台兼容性和竞态条件修复 - 增强遥测功能,改进错误跟踪和请求 ID 支持 - 重构构建系统,采用模块化 Webpack 配置 - 改进工具文档,增强可读性和参数说明 - 优化数据库工具,支持对象数组参数和嵌套 JSON - 增强小程序调试工具和微信开发者工具集成 #### 🐛 问题修复 - 修复 IDE 文件过滤问题,支持特定 IDE 类型 - 解决环境 ID 获取的循环依赖死锁问题 - 修复数据库工具参数序列化和语法错误 - 优化函数部署依赖安装配置 - 改进 README 保护机制和模板下载功能 ## 📋 历史版本 ### v1.8.x 系列 (2025) #### ✨ 核心更新 - 🎉 **AI CLI 集成** - 全新一代 CloudBase AI CLI 工具,支持多种 AI 编程助手统一管理 - 🔧 **MCP 协议升级** - 全面升级 MCP 协议实现,提升 AI 工具集成体验 - 📊 **工具链优化** - 优化 39 个 MCP 工具,合并相关功能,提升使用效率 ### v1.7.0 (2025-06-10) #### ✨ 新功能 - 新增 login 工具交互式选择环境 - 新增 interactiveDialog 统一的交互式对话工具,支持需求澄清和任务确认 - 增加规则:交互式反馈规则,在需求不明确时主动与用户对话澄清 ### v1.6.0 (2025-06-06) #### ✨ 新功能 - 新增跨数据库查询规则 - 新增通用模板支持 - 支持 AI 下载模板功能 - 支持小程序知识库功能 #### 🔧 改进 - 添加 CNB 徽章 - 添加 Cursor 安装链接 - 添加产品横幅 - 函数运行时支持更多 Node.js 版本 - 更新 MCP 日志处理 - 更新环境 ID 未找到的规则 ### v1.5.0 (2025-06-04) #### 🐛 修复 - 修复函数依赖安装问题 #### ✨ 新功能 - 支持文心快码 Comate #### 📚 文档更新 - 更新文档和规则配置 ### v1.4.0 (2025-05-30) #### ✨ 新功能 - 支持 searchKnowledgeBase 工具,智能检索云开发知识库 - 支持 RooCode IDE - 支持通义灵码 #### 📚 文档更新 - 修复文档问题 - 更新下载链接 ### v1.3.0 (2025-05-28) #### ✨ 新功能 - 优化小程序规则 - MCP 支持登出功能 - 支持 Web 认证 #### 🐛 修复 - 修复 logout 出参问题 - 更新函数部署规则 - 修复 windsurf 错误 #### 🔧 改进 - 默认使用最新版本的 MCP - 添加脚本支持 - 修复文档和配置问题 ### v1.2.1 (2025-05-28) #### 🔧 改进 - 默认使用最新版本的 MCP - 添加脚本支持 - 修复文档和配置问题 ## 📖 版本说明 ### 版本号规则 - **主版本号**:重大功能更新或架构变更 - **次版本号**:重要功能新增 - **修订号**:问题修复和优化 ### 兼容性说明 - 所有版本都保持向后兼容 - 建议及时更新到最新版本以获得最佳体验 ## 🔗 相关链接 - [📖 完整文档](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/) - [🐛 问题反馈](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/issues) - [💬 社区讨论](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/discussions) --- *最后更新时间:2025年6月* --- ## 开发指南 # 开发指南 ## 基本开发流程 ### 1. 登录云开发 ``` 登录云开发 ``` AI 会自动完成弹出登录腾讯云界面以及云开发的环境选择。 ### 2. 环境管理 切换环境: ``` 退出云开发 ``` 验证当前环境: ``` 查询当前云开发环境信息 ``` ### 3. 开始开发 向 AI 描述你的需求: ``` 做一个双人在线对战五子棋网站,支持联机对战,最后进行部署 ``` AI 会自动: - 📝 生成前后端代码 - 🚀 部署到云开发 - 🔗 返回在线访问链接 ## 问题调试 ### 报错处理 ``` 报错了,错误是xxxx ``` ### 云函数调试 ``` 云函数代码运行不符合需求,需求是 xxx,请查看日志和数据进行调试,并进行修复 ``` ## 支持的应用类型 ### Web 应用 - 现代化前端 + 静态托管 - 支持 React、Vue 等主流框架 - 国内 CDN 加速 ### 微信小程序 - 云开发小程序解决方案 - 云数据库 + 云函数集成 - 支持云调用等高级功能 ### 后端服务 - 云数据库 - 无服务器云函数 - 文件存储和 CDN ## 开发最佳实践 1. **详细描述需求** - AI 会生成更准确的代码 2. **完整提供错误信息** - 便于 AI 快速定位问题 3. **善用日志查看** - 要求 AI 查看日志进行问题诊断 4. **增量开发** - 支持逐步完善功能 --- ## 使用案例 # 使用案例 ## 案例1:双人在线对战五子棋 **开发过程:** 1. 输入需求:"做个双人在线对战五子棋网站,支持联机对战" 2. AI 生成:Web 应用 + 云数据库 + 实时数据推送 3. 自动部署并获得访问链接 👉 **体验地址:** [五子棋游戏](https://cloud1-5g39elugeec5ba0f-1300855855.tcloudbaseapp.com/gobang/#/) ## 案例2:AI 宠物养成小程序 **开发过程:** 1. 输入:"开发一个宠物小精灵养成小程序,使用 AI 增强互动" 2. AI 生成:小程序 + 云数据库 + AI 云函数 3. 导入微信开发者工具即可发布 ## 案例3:智能问题诊断 当应用出现问题时: 1. AI 自动查看云函数日志 2. 分析错误原因并生成修复代码 3. 自动重新部署 ## 典型开发流程 1. **需求描述** → AI 理解并规划架构 2. **代码生成** → 自动生成前后端代码 3. **云资源创建** → 自动创建数据库、云函数等 4. **部署上线** → 自动部署并返回访问链接 5. **问题修复** → AI 查看日志自动修复问题 --- ## 常见问题 FAQ # 常见问题 FAQ ## 🌟 选择 CloudBase 的原因 ### 为什么选择 CloudBase? - **⚡ 极速部署**:国内节点,访问速度比海外更快 - **🛡️ 稳定可靠**:330 万开发者选择的 Serverless 平台 - **🔧 开发友好**:专为AI时代设计的全栈平台,支持自动环境配置 - **💰 成本优化**:Serverless 架构更具弹性,新用户开发期间可以免费体验 ## 🚀 开始使用 ### 我是新用户,如何快速开始? 1. 安装支持的 AI 开发工具(如 Cursor、WindSurf 等) 2. 在腾讯云开发控制台开通环境(新用户免费) 3. 下载项目模板或在现有项目中配置 MCP 4. 对 AI 说"登录云开发"开始开发 ### 支持哪些 AI 开发工具? 支持 CloudBase AI CLI、Cursor、WindSurf、CodeBuddy、CLINE、GitHub Copilot、Claude Code、Gemini CLI、OpenAI Codex CLI、OpenCode、Trae、通义灵码、RooCode、文心快码、Augment Code、Qwen Code 等主流 AI 开发工具。 ## 🛠️ 技术问题 ### 已有项目如何集成本模板和规则体系? 如果你已经有自己的项目,只需在配置好 MCP 后,对 AI 说 "在当前项目中下载云开发 AI 规则",即可一键下载并补全 AI 编辑器规则配置到当前项目目录,无需手动操作。 如果你只想下载特定IDE的配置文件,避免项目文件混乱,可以指定IDE类型: ``` 在当前项目中下载云开发 AI 规则,只包含Cursor配置 在当前项目中下载云开发 AI 规则,只包含WindSurf配置 在当前项目中下载云开发 AI 规则,只包含Claude Code配置 ``` --- ### 如何获取云开发环境 ID? 1. 访问 [腾讯云开发控制台](https://tcb.cloud.tencent.com/dev)开通环境,新用户可以免费开通体验 2. 在控制台「概览」页面右侧获取 **环境ID** (后续部署需要此 ID) --- ### 如何更新 CloudBase AI ToolKit? **更新 AI 规则** 如果你想在现有项目中更新到最新的云开发 AI 规则,只需对 AI 说: ``` 下载云开发 AI 规则在当前项目中更新 rules ``` AI 会自动下载并更新最新的规则配置到你的项目目录。 **更新 MCP 工具** 当有新版本的 MCP 工具发布时,你可以通过以下方式更新: 1. **自动更新(推荐)**:在你的 AI 开发工具的 MCP 列表中,找到 cloudbase 并重新启用或刷新 MCP 列表即可自动安装最新版本 2. **手动更新**:如果自动更新不成功,可以先禁用再重新启用 cloudbase,或者重启你的 AI IDE **注意事项**: - MCP 配置中使用了 `@latest` 标签,通常会自动获取最新版本 - 如果遇到缓存问题,可以完全重启 AI IDE 后重新启用 MCP - 建议定期检查更新以获得最新功能和修复 --- ### MCP 显示工具数量为 0 怎么办? 如果在 AI 开发工具的 MCP 列表中看到 cloudbase-mcp 显示工具数量为 0,可以按以下步骤排查: **1. 检查环境配置** - 确保 Node.js 版本为 v18.15.0 及以上 - macOS 用户且使用 nvm 管理 Node.js 的,请务必设置默认 Node 版本为 v18.15.0 及以上,避免不同终端版本不一致导致的问题。 - 检查网络连接,建议设置 npm 源为腾讯镜像源: ```bash npm config set registry https://mirrors.cloud.tencent.com/npm/ ``` **2. 重新启用 MCP** - 在 AI 开发工具的 MCP 列表中禁用 cloudbase-mcp - 重新启用 cloudbase 或刷新 MCP 列表 - 如果仍有问题,完全重启 AI IDE 后重试 **3. 手动重新安装** 一般情况下,在 MCP 列表中重新启用或刷新即可正常安装并显示工具。 参考下方的 如何全局安装 CloudBase AI ToolKit? 的步骤进行操作 --- ### MCP 配置后提示 MCP error -32001: Request timed out 如果在配置 MCP 时遇到 `MCP error -32001: Request timed out` 错误,可以按以下步骤解决: 参考下方的 如何全局安装 CloudBase AI ToolKit? 的步骤进行操作 ### 如何全局安装 CloudBase AI ToolKit? #### 遇到的问题 在使用 CloudBase AI ToolKit 时,你是否遇到过以下问题? - **安装速度慢** - 使用 `npx` 每次都要重新下载,等待时间过长 - **配置复杂** - 需要手动配置 npm 源、Node.js 版本等环境依赖 - **重复安装** - 在不同 AI IDE 中需要重复配置 MCP 服务 - **网络问题** - npm 安装时经常遇到网络超时或下载失败 #### 解决方案:CloudBase AI CLI 快速安装 推荐使用 **CloudBase AI CLI** 的快速安装方式,一次性解决所有问题: - 🚀 **快速安装** - 相比 npm 安装通常需要几分钟,一键安装脚本只需几秒即可完成 - 🛠️ **统一管理** - 一个命令管理多种 AI 编程 CLI 工具,包括内置的 CloudBase AI Toolkit MCP - 🌍 **无处不在** - 可在任意环境中运行,包括小程序开发者工具、VS Code、GitHub Actions 等 - 🔧 **开箱即用** - 安装完成后自动配置 MCP 服务,无需额外配置 #### 快速安装步骤 **1. 使用一键安装脚本** Mac/Linux/Windows WSL 用户: ```bash curl https://static.cloudbase.net/cli/install/install.sh -fsS | bash ``` Windows PowerShell 用户: ```powershell irm https://static.cloudbase.net/cli/install/install.ps1 | iex ``` **2. 验证安装** 安装完成后,CloudBase AI CLI 会自动安装 CloudBase AI Toolkit MCP 服务,并生成全局命令 `cloudbase-mcp`。 **3. 配置 MCP** 重启你的 AI IDE,然后修改 MCP 配置: ```json { "mcpServers": { "cloudbase": { "command": "cloudbase-mcp" } } } ``` **4. 验证 MCP 服务** 可以立即看到 CloudBase MCP 正常启动。 #### 支持的 AI IDE CloudBase AI CLI 的快速安装方式适用于所有支持 MCP(Model Context Protocol)的 AI IDE,包括但不限于: - **Cursor** - 基于 VS Code 的 AI 编程助手 - **WindSurf** - 腾讯云推出的 AI 编程工具 - **CodeBuddy** - 智能代码助手 - **Visual Studio Code** - 通过 CodeBuddy 插件支持 - **Claude Code** - Anthropic 的 AI 编程环境 - **GitHub Copilot** - 支持 MCP 的版本 - **其他支持 MCP 的 AI IDE** 这种统一的安装方式让你可以在不同的 AI IDE 之间无缝切换,无需重复配置。 - CodeBuddy中正常配置效果 ![](https://qcloudimg.tencent-cloud.cn/raw/3ad6cefbfee790ad3b42eea0cdb752cb.png) - Visual Studio Code 中 CodeBuddy 插件配置 CloudBase MCP 正常效果 ![](https://qcloudimg.tencent-cloud.cn/raw/b6e70f722768d4a844280102378358fe.png) - Cursor 中正常配置效果 ![](https://qcloudimg.tencent-cloud.cn/raw/344fe2c5a96a3e19c6cafc2bcbe73f96.png) #### 了解更多 CloudBase AI CLI 不仅内置了 CloudBase AI Toolkit MCP,还支持多种主流 AI 编程工具: - **Claude Code** - Anthropic 的 AI 编程助手 - **OpenAI Codex** - OpenAI 的代码生成工具 - **aider** - 开源的 AI 编程助手 - **Qwen Code** - 通义灵码 详细使用说明请参考:[CloudBase AI CLI 使用文档](/cli-v1/ai/introduce) ### MCP 配置不生效怎么办? 1. 检查配置格式是否正确 2. 重启 AI IDE 3. 确认 MCP 服务已启用 ### Safari 浏览器无法完成授权登录怎么处理? 如果在使用 Safari 浏览器时遇到授权登录问题,建议切换到 Chrome 浏览器进行授权登录。 Safari 浏览器在某些情况下可能存在兼容性问题,影响授权流程的正常进行。Chrome 浏览器对云开发授权流程有更好的支持。 --- ### 远程开发环境或服务端如何使用 MCP? #### 遇到的问题 在远程开发环境中使用 CloudBase AI ToolKit 时,你是否遇到过这些挑战? - **无法浏览器授权** - 服务器环境没有图形界面,无法完成浏览器登录 - **环境隔离** - 远程环境无法访问本地浏览器进行授权 - **自动化部署** - CI/CD 流水线中需要无交互的配置方式 - **权限管理** - 需要精确控制云开发资源的访问权限 #### 解决方案:环境变量配置 CloudBase AI CLI 支持通过环境变量进行无浏览器授权,完美解决远程环境的使用问题。 #### 安装 CloudBase AI CLI 使用 CloudBase AI CLI 的快速安装脚本: ```bash curl https://static.cloudbase.net/cli/install/install.sh -fsS | bash ``` 安装完成后会自动生成 `cloudbase-mcp` 全局命令。 **配置方法:** 在 MCP 配置中使用 `env` 环境变量来设置认证信息: ```js { "mcpServers": { "cloudbase": { "command": "cloudbase-mcp", "args": ["--integration-ide", "YOUR_IDE"], "env": { "TENCENTCLOUD_SECRETID": "腾讯云 SecretId", "TENCENTCLOUD_SECRETKEY": "腾讯云 SecretKey", "TENCENTCLOUD_SESSIONTOKEN": "腾讯云临时密钥Token,如果使用临时密钥才需要传入", "CLOUDBASE_ENV_ID": "云开发环境 ID" } } } } ``` **获取密钥信息:** - 腾讯云 SecretId 和 SecretKey:在 [腾讯云访问管理控制台](https://console.cloud.tencent.com/cam/capi) 获取 - 云开发环境 ID:在 [腾讯云开发控制台](https://tcb.cloud.tencent.com/dev) 概览页面获取 这种方式特别适用于: - 远程开发环境(如 GitHub Codespaces、云 IDE 等) - 服务端自动化脚本 - CI/CD 流水线中的自动化部署 --- ### 支持哪些应用类型? - **Web应用**:现代化前端 + 静态托管 - **微信小程序**:云开发小程序解决方案 - **后端服务**:云数据库 + 无服务器函数+云托管 --- ### 开发微信小程序时有什么特别建议? **推荐开发流程:** 1. **在微信开发者工具中开通云开发环境** - 直接在微信开发者工具里开通,确保小程序与云开发环境完美绑定 2. **AI IDE 登录时选择【小程序/公众号】登录** - 跳转登录腾讯云云开发时,选择【小程序/公众号】登录 - 使用你的小程序来登录,而不是腾讯云主账号 这样可以保证权限一致性,避免环境配置问题。 --- ### 如何在微信开发者工具中使用 CloudBase AI ToolKit? CloudBase AI ToolKit 与微信开发者工具可以完美配合使用,提供更高效的开发体验。 #### 方式一:从 AI IDE 开始开发 如果你已经在 AI IDE(如 Cursor、WindSurf、CodeBuddy 等)中开始开发小程序项目: 1. **AI IDE 开发**:在 AI IDE 中使用 CloudBase AI ToolKit 进行代码编写和云开发资源管理 2. **导入微信开发者工具**:在微信开发者工具中导入整个项目文件夹 3. **实时同步**:AI IDE 中的文件变化会实时同步到微信开发者工具 4. **构建预览**:在微信开发者工具中执行构建和预览操作 5. **错误排查**:如果遇到构建或运行错误,可以复制错误信息到 AI IDE 中进行智能排障 **优势:** - 享受 AI 智能编程的便利 - 利用微信开发者工具的原生调试能力 - 实时预览和真机调试 - 完整的开发工具链 #### 方式二:从微信开发者工具开始 如果你已有微信开发者工具中的小程序项目: 1. **打开项目**:在 AI IDE 中打开现有的小程序项目文件夹 2. **配置 MCP**:参考文档配置 CloudBase MCP 服务 3. **下载 AI 规则**:对 AI 说"下载云开发 AI 规则"获取开发规则 4. **开始 AI 开发**:使用 AI 进行代码编写和云开发资源管理 5. **微信开发者工具预览**:在微信开发者工具中进行实时预览和调试 **工作流程:** - AI IDE:负责代码编写、云函数开发、数据库设计等 - 微信开发者工具:负责小程序预览、真机调试、性能分析等 - 两者协同工作,发挥各自优势 **注意事项:** - 确保两个工具打开的是同一个项目文件夹 - 文件保存后会自动同步,无需手动操作 - 建议在 AI IDE 中完成主要开发工作,在微信开发者工具中进行最终测试 --- ## 🔄 环境管理 ### 如何切换云开发环境? ``` 退出云开发 登录云开发 ``` ### 如何切换腾讯云账号? 如果需要切换到不同的腾讯云账号: 1. **清理本地登录态**:对 AI 说 `退出登录` 2. **浏览器退出登录**:到浏览器里面退出原来登录的腾讯云账号 3. **重新登录**:对 AI 说 `登录云开发` 这样就可以切换到新的腾讯云账号了。 ### 如何确认当前环境? ``` 查询当前云开发环境信息 ``` ## 🐛 问题排查 ### 部署失败了怎么办? 把完整的错误信息发给 AI: ``` 报错了,错误是xxxx ``` ### 云函数运行异常如何调试? 让 AI 查看日志并修复: ``` 云函数代码运行不符合需求,需求是 xxx,请查看日志和数据进行调试,并进行修复 ``` ## 💬 技术交流群 遇到问题或想要交流经验?加入我们的技术社区! ### 🔥 微信交流群 扫码加入微信技术交流群 ## 技术支持 ### 遇到问题如何获取帮助? 1. 查看常见问题 FAQ 2. 在 [GitHub Issues](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/issues) 提交问题 3. 加入微信技术交流群获取社区支持 ### 如何参与社区? - 加入微信技术交流群分享项目和交流经验 - 在 GitHub 上 Star 项目并提交 Issue 或 PR - 关注官方文档获取最新功能更新 --- ## 快速开始 # 快速开始 欢迎使用 **CloudBase AI ToolKit**!通过自然语言描述需求,AI 自动生成代码并部署到腾讯云开发平台。 [![GitHub Stars](https://img.shields.io/github/stars/TencentCloudBase/CloudBase-AI-ToolKit?style=social)](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit) [![CNB Community](https://img.shields.io/badge/CNB-开源社区-blue?style=flat-square)](https://cnb.cool/tencent/cloud/cloudbase/CloudBase-AI-ToolKit) ## 🌟 核心能力 - **🤖 AI 智能开发**:自动生成代码和架构设计 - **☁️ 云开发集成**:一键接入数据库、云函数、静态托管 - **🚀 快速部署**:几分钟内完成全栈应用上线 - **📱 全栈支持**:Web + 小程序 + 后端一体化 - **🔧 智能修复**:AI 自动查看日志并修复问题 ### 🎯 适用场景 快速原型、学习实践、业务开发、小程序开发 --- ## 🚀 第一步:选择你的 AI 开发工具 ### 🎯 推荐:CloudBase AI CLI 统一管理多种 AI 编程工具,内置 CloudBase AI Toolkit,支持从开发到部署的完整流程。 **一键安装** ```bash # Mac/Linux/Windows 的 WSL curl https://static.cloudbase.net/cli/install/install.sh -fsS | bash # Windows PowerShell irm https://static.cloudbase.net/cli/install/install.ps1 | iex ``` **开始使用** ```bash tcb ai ``` 👉 [查看文档](https://docs.cloudbase.net/cli-v1/ai/introduce) ### 🛠️ 其他 IDE 配置方式 如果你使用其他 AI IDE,请参考下面的配置指南: | 工具 | 支持平台 | 查看指引 | |------|----------|----------| | [CloudBase AI CLI](https://docs.cloudbase.net/cli-v1/ai/introduce) | 命令行工具 | [查看指引](https://docs.cloudbase.net/cli-v1/ai/introduce) | | [Cursor](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/cursor) | 独立 IDE| [查看指引](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/cursor) | | [WindSurf](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/windsurf) | 独立 IDE, VSCode、JetBrains 插件 | [查看指引](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/windsurf) | | [CodeBuddy](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/codebuddy) | VS Code、JetBrains、微信开发者工具、独立 IDE(推荐,已内置 CloudBase AI Toolkit) | [查看指引](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/codebuddy) | | [CLINE](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/cline) | VS Code 插件 | [查看指引](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/cline) | | [GitHub Copilot](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/github-copilot) | VS Code 插件 | [查看指引](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/github-copilot) | | [Trae](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/trae) | 独立 IDE | [查看指引](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/trae) | | [通义灵码](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/tongyi-lingma) | 独立 IDE,VS Code、 JetBrains插件 | [查看指引](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/tongyi-lingma) | | [RooCode](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/roocode) | VS Code插件 | [查看指引](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/roocode) | | [文心快码](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/baidu-comate) | VS Code、JetBrains插件| [查看指引](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/baidu-comate) | | [Augment Code](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/augment-code) | VS Code、JetBrains 插件 | [查看指引](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/augment-code) | | [Claude Code](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/claude-code) | 命令行工具 | [查看指引](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/claude-code) | | [Gemini CLI](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/gemini-cli) | 命令行工具 | [查看指引](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/gemini-cli) | | [OpenAI Codex CLI](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/openai-codex-cli) | 命令行工具 | [查看指引](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/openai-codex-cli) | | [OpenCode](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/opencode) | 命令行工具 | [查看指引](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/opencode) | | [Qwen Code](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/qwen-code) | 命令行工具 | [查看指引](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/qwen-code) | ### 快速配置(通用) 如果你的工具暂时没有专门的指南,可以使用以下通用 MCP 配置: ```json { "mcpServers": { "cloudbase": { "command": "npx", "args": ["npm-global-exec@latest", "@cloudbase/cloudbase-mcp@latest"] } } } ``` 配置完成后,在 AI 对话中输入以下内容验证: ``` 检查 CloudBase 工具是否可用 ``` ## ✅ 第二步:验证环境 ### 前置条件检查 ✅ Node.js v18.15.0+ 已安装 确保您的计算机上安装了 Node.js v18.15.0 及以上版本。检查版本: ```bash node --version ``` 如果未安装,请从 [Node.js 官网](https://nodejs.org/) 下载安装。 ☁️ 开通云开发环境 访问 [腾讯云开发控制台](https://tcb.cloud.tencent.com/dev) 开通环境,新用户可以免费开通体验。 🚀 可选:加速配置 **设置 npm 镜像源**(提高下载速度): ```bash npm config set registry https://mirrors.cloud.tencent.com/npm/ ``` **清理 npx 缓存**(避免安装问题): ```bash npx clear-npx-cache ``` ## 🎯 第三步:选择项目模板 ### 📦 使用现成模板(推荐新手) 我们为你准备了多种技术栈的项目模板,内置云开发最佳实践和 AI 规则: - **📱 微信小程序** + 云开发 - **⚛️ React Web** + 云开发 - **💚 Vue Web** + 云开发 - **🦄 UniApp** 跨端应用 + 云开发 - **🛠️ 通用模板**(适用于任意技术栈) **👉 [查看所有项目模板](./templates)** 选择合适的模板后,只需对 AI 说: ``` 下载 [模板名称] 到当前目录 ``` 如果你只想下载特定IDE的配置文件,避免项目文件混乱,可以指定IDE类型: ``` 下载小程序云开发模板,只包含Cursor配置 下载React云开发模板,只包含WindSurf配置 下载通用云开发模板,只包含Claude Code配置 ``` ### 🔧 增强现有项目 如果你已经有项目,只需对 AI 说: ``` 在当前项目中下载云开发 AI 规则 ``` AI 会自动下载并配置云开发规则到你的项目中。同样支持指定IDE类型: ``` 在当前项目中下载云开发 AI 规则,只包含Cursor配置 在当前项目中下载云开发 AI 规则,只包含WindSurf配置 ``` ## 🔐 第四步:登录云开发 在 AI 对话中输入: ``` 登录云开发 ``` AI 会自动: - 弹出腾讯云登录界面 - 展示可用的云开发环境 - 完成环境选择和配置 ### 验证登录状态 ``` 查询当前云开发环境信息 ``` ## 🚀 第五步:开始开发 现在你可以通过自然语言描述需求,让 AI 帮你开发应用: ### 示例需求 ``` 帮我创建一个待办事项应用,包含: - 添加、删除、编辑待办事项 - 数据存储到云数据库 - 支持标记完成状态 - 部署到云端 ``` ``` 创建一个简单的博客系统,需要: - 文章列表页面 - 文章详情页面 - 文章发布功能 - 数据存储到云数据库 ``` ### 💡 开发技巧 - **详细描述**:越详细的需求描述,AI 生成的代码越准确 - **增量开发**:可以逐步添加功能,比如先实现基础功能,再添加高级特性 - **错误处理**:遇到问题时,把完整的错误信息提供给 AI - **日志调试**:可以要求 AI 查看云函数日志进行问题诊断 ## 🎯 典型开发流程 ```mermaid graph TD A[描述需求] --> B[AI 生成代码] B --> C[创建云资源] C --> D[本地测试] D --> E{测试通过?} E -->|否| F[AI 查看日志修复] F --> D E -->|是| G[部署上线] G --> H[获得访问链接] style A fill:#e1f5fe style B fill:#e8f5e8 style C fill:#fff3e0 style G fill:#e8eaf6 style H fill:#ffebee ``` ## 🔧 调试和问题修复 ### 遇到错误时 ``` 报错了,错误信息是:[粘贴完整错误信息] ``` ### 云函数调试 ``` 云函数运行异常,需求是 [描述原本的需求],请查看日志进行调试和修复 ``` ### 环境切换 如需切换云开发环境: ``` 退出云开发 ``` 然后重新登录选择其他环境。 ## 🎉 完成!你已准备就绪 ✅ AI 开发工具已配置 ✅ 云开发环境已连接 ✅ 项目模板已准备 ✅ 开发流程已了解 现在开始用自然语言描述你的应用需求,让 AI 帮你快速构建全栈应用吧! ## 📚 进阶学习 - 📖 [项目模板详解](./templates) - 深入了解各种项目模板 - 💻 [开发最佳实践](./development) - 掌握高级开发技巧 - 🎯 [实际案例](./examples) - 学习真实项目经验 - 🛠️ [MCP 工具参考](./mcp-tools) - 了解所有可用工具 - ❓ [常见问题](./faq) - 解决开发中的问题 --- 💫 如果这个项目对你有帮助,欢迎给我们一个 ⭐ Star! [![GitHub](https://img.shields.io/badge/GitHub-CloudBase--AI--ToolKit-black?style=flat-square&logo=github)](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit) [![CNB](https://img.shields.io/badge/CNB-中国开发者社区-blue?style=flat-square)](https://cnb.cool/tencent/cloud/cloudbase/CloudBase-AI-ToolKit) --- ## CloudBase AI Toolkit + [IDE名称] # CloudBase AI Toolkit + [IDE名称] **🚀 [IDE名称] + 云开发 = 几分钟内从想法到上线的全栈应用** [![GitHub Stars](https://img.shields.io/github/stars/TencentCloudBase/CloudBase-AI-ToolKit?style=social)](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit) [![开源协议](https://img.shields.io/badge/License-MIT-blue.svg)](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/blob/main/LICENSE) > 💡 **为什么选择 [IDE名称] + CloudBase AI Toolkit?** > [IDE特色描述] + CloudBase AI Toolkit 的强大组合,让你通过自然语言描述需求,AI 自动生成并部署全栈应用到腾讯云开发平台。特别适合 [适用场景]。 ## ✨ 核心优势 | 🎯 **开发效率** | ⚡ **部署速度** | 🛡️ **稳定可靠** | |---|---|---| | AI 自动生成代码和架构内置云开发最佳实践规则智能错误修复和优化 | 一键部署到腾讯云开发国内 CDN 加速访问Serverless 架构免运维 | 330万开发者验证的平台企业级安全和稳定性完善的监控和日志系统 | ## 🚀 5分钟快速开始 ### 方式一:使用项目模板(推荐) 选择预配置的项目模板,开箱即用: **[📦 查看所有项目模板](../templates)** ### 方式二:现有项目集成 如果你已有项目,只需 3 步集成: ```bash # 1. 配置 MCP(具体配置见下方详细步骤) # 2. 下载 AI 规则 # 3. 开始使用 ``` 配置完成后,对 AI 说:**"登录云开发"** 即可开始! ## 🔧 详细配置指南 ### 步骤 1:安装 [IDE名称] [IDE特定的安装说明] ### 步骤 2:配置 CloudBase MCP > [!TIP] > 如果安装以后工具数量一直为 0,请参考[常见问题](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/faq#mcp-%E6%98%BE%E7%A4%BA%E5%B7%A5%E5%85%B7%E6%95%B0%E9%87%8F%E4%B8%BA-0-%E6%80%8E%E4%B9%88%E5%8A%9E) [IDE特定的MCP配置方法,包括一键安装按钮或手动配置] ### 步骤 3:启用 AI 规则 [AI规则配置说明] ### 步骤 4:开始开发 在 [IDE特定模式] 下与 AI 对话: ``` 登录云开发 ``` ## 🎯 开始使用 配置完成后,对 AI 说: ``` 登录云开发 ``` 然后就可以开始开发了,例如: ``` 创建一个在线投票系统,支持创建投票、参与投票、结果统计,使用云数据库存储,最后部署 ``` ## 🌟 CloudBase AI Toolkit 开源项目 ### 🔥 加入开源社区 [![GitHub](https://img.shields.io/badge/GitHub-TencentCloudBase/CloudBase--AI--ToolKit-black?style=for-the-badge&logo=github)](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit) [![CNB社区](https://img.shields.io/badge/CNB-CloudBase--AI--ToolKit-orange?style=for-the-badge)](https://cnb.cool/tencent/cloud/cloudbase/CloudBase-AI-ToolKit) **⭐ Star 项目 | 🤝 贡献代码 | 💬 技术交流** ## 🛠️ 故障排除 ### 常见问题 **Q: MCP 连接失败?** A: 1. 检查配置文件格式是否正确 2. 重启 [IDE名称] 3. 确认网络连接正常 **Q: AI 生成的代码不符合预期?** A: 1. 明确描述技术栈和框架要求 2. 使用项目模板确保规范一致性 3. 提供更详细的需求描述 更多问题请查看:[完整 FAQ](../faq) ## 📚 相关资源 - [📖 开发指南](../development) - 深入了解开发最佳实践 - [🎯 使用案例](../examples) - 查看实际应用案例 - [🔧 MCP 工具](../mcp-tools) - 了解所有可用工具 - [❓ 常见问题](../faq) - 查看常见问题解答 ## 💬 技术交流 ### 微信技术交流群 扫码加入微信技术交流群 --- **🚀 立即开始使用 [IDE名称] + CloudBase AI Toolkit** [开始使用](../getting-started) | [查看模板](../templates) | [GitHub 仓库](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit) --- ## CloudBase AI Toolkit + Augment Code # CloudBase AI Toolkit + Augment Code **🚀 Augment Code + 云开发 = 几分钟内从想法到上线的全栈应用** [![GitHub Stars](https://img.shields.io/github/stars/TencentCloudBase/CloudBase-AI-ToolKit?style=social)](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit) [![开源协议](https://img.shields.io/badge/License-MIT-blue.svg)](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/blob/main/LICENSE) > 💡 **为什么选择 Augment Code + CloudBase AI Toolkit?** > Augment Code 是一款强大的 AI 编程助手,支持 VS Code 和 JetBrains 平台。结合 CloudBase AI Toolkit,让你通过自然语言描述需求,AI 自动生成并部署全栈应用到腾讯云开发平台。特别适合需要跨平台开发和高度定制化 AI 开发环境的专业开发者。 ## ✨ 核心优势 | 🎯 **开发效率** | ⚡ **部署速度** | 🛡️ **稳定可靠** | |---|---|---| | AI 自动生成代码和架构内置云开发最佳实践规则智能错误修复和优化 | 一键部署到腾讯云开发国内 CDN 加速访问Serverless 架构免运维 | 330万开发者验证的平台企业级安全和稳定性完善的监控和日志系统 | ## 🚀 5分钟快速开始 ### 方式一:使用项目模板(推荐) 选择预配置的项目模板,开箱即用: **[📦 查看所有项目模板](../templates)** ### 方式二:现有项目集成 如果你已有项目,只需 3 步集成: ```bash # 1. 配置 MCP(具体配置见下方详细步骤) # 2. 下载 AI 规则 # 3. 开始使用 ``` 配置完成后,对 AI 说:**"登录云开发"** 即可开始! ## 🔧 详细配置指南 ### 步骤 1:安装 Augment Code 从 [Augment Code 官网](https://www.augmentcode.com/) 下载并安装对应平台的插件。 ### 步骤 2:配置 CloudBase MCP > [!TIP] > 如果安装以后工具数量一直为 0,请参考[常见问题](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/faq#mcp-%E6%98%BE%E7%A4%BA%E5%B7%A5%E5%85%B7%E6%95%B0%E9%87%8F%E4%B8%BA-0-%E6%80%8E%E4%B9%88%E5%8A%9E) 参考 [Augment Code 的 MCP 配置文](https://docs.augmentcode.com/setup-augment/mcp#advanced-mcp-configuration),选择 **Import from JSON** 方式,填写如下内容: 在 `.vscode/settings.json` 中添加: ```json { "mcpServers": { "cloudbase": { "command": "npx", "args": ["npm-global-exec@latest", "@cloudbase/cloudbase-mcp@latest"], "env": { "INTEGRATION_IDE": "Augment" } } } } ``` ### 步骤 3:启用 AI 规则 创建 `.augment-guidelines` 文件,或直接对 AI 说: ``` 在当前项目中下载云开发 AI 规则 ``` 如果你只想下载Augment Code相关的配置文件,避免项目文件混乱,可以指定IDE类型: ``` 在当前项目中下载云开发 AI 规则,只包含Augment Code配置 ``` ### 步骤 4:开始开发 在 Agent 模式下与 AI 对话: ``` 登录云开发 ``` ## 🎯 开始使用 配置完成后,对 AI 说: ``` 登录云开发 ``` 然后就可以开始开发了,例如: ``` 创建一个在线投票系统,支持创建投票、参与投票、结果统计,使用云数据库存储,最后部署 ``` Augment Code 支持跨平台开发(VS Code 和 JetBrains),具有强大的代码生成和重构能力。 ## 🌟 CloudBase AI Toolkit 开源项目 ### 🔥 加入开源社区 [![GitHub](https://img.shields.io/badge/GitHub-TencentCloudBase/CloudBase--AI--ToolKit-black?style=for-the-badge&logo=github)](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit) [![CNB社区](https://img.shields.io/badge/CNB-CloudBase--AI--ToolKit-orange?style=for-the-badge)](https://cnb.cool/tencent/cloud/cloudbase/CloudBase-AI-ToolKit) **⭐ Star 项目 | 🤝 贡献代码 | 💬 技术交流** ## 🛠️ 故障排除 ### 常见问题 **Q: MCP 连接失败?** A: 1. 检查 `.vscode/settings.json` 中的 MCP 配置 2. 确认 npx 命令可用:`npx --version` 3. 重启 VS Code 应用 4. 检查网络连接状态 **Q: Agent 模式无法执行操作?** A: 1. 检查 Augment Code 扩展是否正常启用 2. 确认项目权限设置正确 3. 查看扩展输出日志定位问题 **Q: AI 生成的代码不符合预期?** A: 1. 详细描述功能需求和技术要求 2. 使用项目模板确保规范一致性 3. 分模块逐步实现复杂项目 更多问题请查看:[完整 FAQ](../faq) ## 📚 相关资源 - [📖 开发指南](../development) - 深入了解开发最佳实践 - [🎯 使用案例](../examples) - 查看实际应用案例 - [🔧 MCP 工具](../mcp-tools) - 了解所有可用工具 - [❓ 常见问题](../faq) - 查看常见问题解答 - [Augment Code 官方文档](https://docs.augmentcode.com/) - Augment Code 官方文档 ## 💬 技术交流 ### 微信技术交流群 扫码加入微信技术交流群 --- **🚀 立即开始使用 Augment Code + CloudBase AI Toolkit** [开始使用](../getting-started) | [查看模板](../templates) | [GitHub 仓库](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit) --- ## CloudBase AI Toolkit + 文心快码 Comate # CloudBase AI Toolkit + 文心快码 Comate **🚀 文心快码 + 云开发 = 几分钟内从想法到上线的全栈应用** [![GitHub Stars](https://img.shields.io/github/stars/TencentCloudBase/CloudBase-AI-ToolKit?style=social)](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit) [![开源协议](https://img.shields.io/badge/License-MIT-blue.svg)](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/blob/main/LICENSE) > 💡 **为什么选择 文心快码 + CloudBase AI Toolkit?** > 文心快码是百度推出的 AI 编程助手,支持多种 IDE 平台和中文语言优化。结合 CloudBase AI Toolkit,让你通过自然语言描述需求,AI 自动生成并部署全栈应用到腾讯云开发平台。特别适合中文开发者和需要本土化 AI 编程体验的团队。 ## ✨ 核心优势 | 🎯 **开发效率** | ⚡ **部署速度** | 🛡️ **稳定可靠** | |---|---|---| | AI 自动生成代码和架构内置云开发最佳实践规则智能错误修复和优化 | 一键部署到腾讯云开发国内 CDN 加速访问Serverless 架构免运维 | 330万开发者验证的平台企业级安全和稳定性完善的监控和日志系统 | ## 🚀 5分钟快速开始 ### 方式一:使用项目模板(推荐) 选择预配置的项目模板,开箱即用: **[📦 查看所有项目模板](../templates)** ### 方式二:现有项目集成 如果你已有项目,只需 3 步集成: ```bash # 1. 配置 MCP(具体配置见下方详细步骤) # 2. 下载 AI 规则 # 3. 开始使用 ``` 配置完成后,对 AI 说:**"登录云开发"** 即可开始! ## 🔧 详细配置指南 ### 步骤 1:安装文心快码 从 [文心快码官网](https://comate.baidu.com/) 下载并安装对应平台的插件。 ### 步骤 2:配置 CloudBase MCP > [!TIP] > 如果安装以后工具数量一直为 0,请参考[常见问题](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/faq#mcp-%E6%98%BE%E7%A4%BA%E5%B7%A5%E5%85%B7%E6%95%B0%E9%87%8F%E4%B8%BA-0-%E6%80%8E%E4%B9%88%E5%8A%9E) ```json { "mcpServers": { "cloudbase": { "command": "npx", "args": [ "npm-global-exec@latest", "@cloudbase/cloudbase-mcp@latest" ], "env": { "INTEGRATION_IDE": "Comate" } } } } ``` ### 步骤 3:启用 AI 规则 创建 `.comate/rules/cloudbase.md` 或对 AI 说: ``` 在当前项目中下载云开发 AI 规则 ``` 如果你只想下载百度Comate相关的配置文件,避免项目文件混乱,可以指定IDE类型: ``` 在当前项目中下载云开发 AI 规则,只包含百度Comate配置 ``` ### 步骤 4:开始开发 在 Zulu 模式下与 AI 对话: ``` 登录云开发 ``` ## 🎯 开始使用 配置完成后,对 AI 说: ``` 登录云开发 ``` 然后就可以开始开发了,例如: ``` 创建一个在线投票系统,支持创建投票、参与投票、结果统计,使用云数据库存储,最后部署 ``` 文心快码支持 Zulu 模式和中文语言优化。 ## 🌟 CloudBase AI Toolkit 开源项目 ### 🔥 加入开源社区 [![GitHub](https://img.shields.io/badge/GitHub-TencentCloudBase/CloudBase--AI--ToolKit-black?style=for-the-badge&logo=github)](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit) [![CNB社区](https://img.shields.io/badge/CNB-CloudBase--AI--ToolKit-orange?style=for-the-badge)](https://cnb.cool/tencent/cloud/cloudbase/CloudBase-AI-ToolKit) **⭐ Star 项目 | 🤝 贡献代码 | 💬 技术交流** ## 🛠️ 故障排除 ### 常见问题 **Q: MCP 连接失败?** A: 1. 检查 MCP 配置格式是否正确 2. 确认 npx 命令可用:`npx --version` 3. 重启文心快码 4. 检查网络连接状态 **Q: AI 生成的代码不符合预期?** A: 1. 使用中文详细描述需求 2. 使用项目模板确保规范一致性 3. 提供更详细的技术要求 更多问题请查看:[完整 FAQ](../faq) ## 📚 相关资源 - [📖 开发指南](../development) - 深入了解开发最佳实践 - [🎯 使用案例](../examples) - 查看实际应用案例 - [🔧 MCP 工具](../mcp-tools) - 了解所有可用工具 - [❓ 常见问题](../faq) - 查看常见问题解答 - [文心快码官网](https://comate.baidu.com/) - 文心快码官网 ## 💬 技术交流 ### 微信技术交流群 扫码加入微信技术交流群 --- **🚀 立即开始使用 文心快码 + CloudBase AI Toolkit** [开始使用](../getting-started) | [查看模板](../templates) | [GitHub 仓库](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit) --- ## CloudBase AI Toolkit + Claude Code # CloudBase AI Toolkit + Claude Code **🚀 Claude Code + 云开发 = 几分钟内从想法到上线的全栈应用** [![GitHub Stars](https://img.shields.io/github/stars/TencentCloudBase/CloudBase-AI-ToolKit?style=social)](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit) [![开源协议](https://img.shields.io/badge/License-MIT-blue.svg)](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/blob/main/LICENSE) > 💡 **为什么选择 Claude Code + CloudBase AI Toolkit?** > Claude Code 是 Anthropic 推出的原生 AI 编程环境,具有强大的代码理解和生成能力。结合 CloudBase AI Toolkit,让你通过自然语言描述需求,AI 自动生成并部署全栈应用到腾讯云开发平台。特别适合需要高质量代码生成和深度项目理解的专业开发者。 ## ✨ 核心优势 | 🎯 **开发效率** | ⚡ **部署速度** | 🛡️ **稳定可靠** | |---|---|---| | AI 自动生成代码和架构内置云开发最佳实践规则智能错误修复和优化 | 一键部署到腾讯云开发国内 CDN 加速访问Serverless 架构免运维 | 330万开发者验证的平台企业级安全和稳定性完善的监控和日志系统 | ## 🚀 5分钟快速开始 ### 方式一:使用项目模板(推荐) 选择预配置的项目模板,开箱即用: **[📦 查看所有项目模板](../templates)** ### 方式二:现有项目集成 如果你已有项目,只需 3 步集成: ```bash # 1. 配置 MCP(具体配置见下方详细步骤) # 2. 下载 AI 规则 # 3. 开始使用 ``` 配置完成后,对 AI 说:**"登录云开发"** 即可开始! ## 🔧 详细配置指南 ### 步骤 1:安装 Claude Code 从 [Claude Code 官网](https://www.anthropic.com/claude-code) 下载并安装 Claude Code。 ### 步骤 2:配置 CloudBase MCP > [!TIP] > 如果安装以后工具数量一直为 0,请参考[常见问题](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/faq#mcp-%E6%98%BE%E7%A4%BA%E5%B7%A5%E5%85%B7%E6%95%B0%E9%87%8F%E4%B8%BA-0-%E6%80%8E%E4%B9%88%E5%8A%9E) 如果使用模板项目,MCP 配置已经预置完成。如果不是从模板开始,需要在项目根目录创建 `.mcp.json` 文件: ```json { "mcpServers": { "cloudbase": { "command": "npx", "args": [ "npm-global-exec@latest", "@cloudbase/cloudbase-mcp@latest" ], "env": { "INTEGRATION_IDE": "ClaudeCode" } } } } ``` ### 步骤 3:启用 AI 规则 模板中已包含 `CLAUDE.md` 文件,Claude Code 会自动识别云开发最佳实践。如果不是从模板开始,可以让 AI 帮你下载云开发规则: ``` 在当前项目中下载云开发 AI 规则 ``` 如果你只想下载Claude Code相关的配置文件,避免项目文件混乱,可以指定IDE类型: ``` 在当前项目中下载云开发 AI 规则,只包含Claude Code配置 ``` ### 步骤 4:开始开发 在 Claude Code 中与 AI 对话: ``` 登录云开发 ``` ## 🎯 开始使用 配置完成后,对 AI 说: ``` 登录云开发 ``` 然后就可以开始开发了,例如: ``` 创建一个在线投票系统,支持创建投票、参与投票、结果统计,使用云数据库存储,最后部署 ``` Claude Code 具有强大的代码理解能力,能够深度分析项目结构并生成高质量的代码。 ## 🌟 CloudBase AI Toolkit 开源项目 ### 🔥 加入开源社区 [![GitHub](https://img.shields.io/badge/GitHub-TencentCloudBase/CloudBase--AI--ToolKit-black?style=for-the-badge&logo=github)](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit) [![CNB社区](https://img.shields.io/badge/CNB-CloudBase--AI--ToolKit-orange?style=for-the-badge)](https://cnb.cool/tencent/cloud/cloudbase/CloudBase-AI-ToolKit) **⭐ Star 项目 | 🤝 贡献代码 | 💬 技术交流** ## 🛠️ 故障排除 ### 常见问题 **Q: MCP 连接失败?** A: 1. 检查 `.mcp.json` 文件格式是否正确 2. 确认 npx 命令可用:`npx --version` 3. 重启 Claude Code 应用 4. 检查网络连接状态 **Q: 项目规则未生效?** A: 1. 确认 `CLAUDE.md` 文件在项目根目录 2. 检查文件内容格式是否正确 3. 重新加载项目或重启 Claude Code **Q: AI 生成的代码不符合预期?** A: 1. 详细描述功能需求和技术要求 2. 使用项目模板确保规范一致性 3. 分模块逐步实现复杂项目 更多问题请查看:[完整 FAQ](../faq) ## 📚 相关资源 - [📖 开发指南](../development) - 深入了解开发最佳实践 - [🎯 使用案例](../examples) - 查看实际应用案例 - [🔧 MCP 工具](../mcp-tools) - 了解所有可用工具 - [❓ 常见问题](../faq) - 查看常见问题解答 - [Claude Code 官方文档](https://docs.anthropic.com/en/docs/claude-code) - Claude Code 官方文档 ## 💬 技术交流 ### 微信技术交流群 扫码加入微信技术交流群 --- **🚀 立即开始使用 Claude Code + CloudBase AI Toolkit** [开始使用](../getting-started) | [查看模板](../templates) | [GitHub 仓库](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit) --- ## CloudBase AI Toolkit + CLINE # CloudBase AI Toolkit + CLINE **🚀 CLINE + 云开发 = 几分钟内从想法到上线的全栈应用** [![GitHub Stars](https://img.shields.io/github/stars/TencentCloudBase/CloudBase-AI-ToolKit?style=social)](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit) [![开源协议](https://img.shields.io/badge/License-MIT-blue.svg)](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/blob/main/LICENSE) > 💡 **为什么选择 CLINE + CloudBase AI Toolkit?** > CLINE 是一款强大的 VS Code AI 助手插件,支持复杂的代码生成和项目管理。结合 CloudBase AI Toolkit,让你通过自然语言描述需求,AI 自动生成并部署全栈应用到腾讯云开发平台。特别适合需要精细控制开发流程和熟悉 VS Code 环境的开发者。 ## ✨ 核心优势 | 🎯 **开发效率** | ⚡ **部署速度** | 🛡️ **稳定可靠** | |---|---|---| | AI 自动生成代码和架构内置云开发最佳实践规则智能错误修复和优化 | 一键部署到腾讯云开发国内 CDN 加速访问Serverless 架构免运维 | 330万开发者验证的平台企业级安全和稳定性完善的监控和日志系统 | ## 🚀 5分钟快速开始 ### 方式一:使用项目模板(推荐) 选择预配置的项目模板,开箱即用: **[📦 查看所有项目模板](../templates)** ### 方式二:现有项目集成 如果你已有项目,只需 3 步集成: ```bash # 1. 配置 MCP(具体配置见下方详细步骤) # 2. 下载 AI 规则 # 3. 开始使用 ``` 配置完成后,对 AI 说:**"登录云开发"** 即可开始! ## 🔧 详细配置指南 ### 步骤 1:安装 CLINE 1. 打开 VS Code 2. 在扩展商店搜索 "CLINE" 3. 点击安装 CLINE 插件 ### 步骤 2:配置 CloudBase MCP > [!TIP] > 如果安装以后工具数量一直为 0,请参考[常见问题](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/faq#mcp-%E6%98%BE%E7%A4%BA%E5%B7%A5%E5%85%B7%E6%95%B0%E9%87%8F%E4%B8%BA-0-%E6%80%8E%E4%B9%88%E5%8A%9E) 参考 [cline的 MCP 配置文档](https://docs.cline.bot/mcp/configuring-mcp-servers) ```json { "mcpServers": { "cloudbase": { "autoApprove": [], "timeout": 60, "command": "npx", "args": [ "npm-global-exec@latest", "@cloudbase/cloudbase-mcp@latest" ], "env": { "INTEGRATION_IDE": "Cline" }, "transportType": "stdio", "disabled": false } } } ``` ### 步骤 3:启用 AI 规则 创建 `.clinerules/cloudbase.md` 文件,或直接对 AI 说: ``` 在当前项目中下载云开发 AI 规则 ``` 如果你只想下载CLINE相关的配置文件,避免项目文件混乱,可以指定IDE类型: ``` 在当前项目中下载云开发 AI 规则,只包含CLINE配置 ``` ### 步骤 4:开始开发 1. 在 VS Code 侧边栏点击 CLINE 图标 2. 选择合适的 AI 模型(推荐 Claude 3.5 Sonnet 或 GPT-4) 3. 确认 MCP 连接状态 与 AI 对话: ``` 登录云开发 ``` ## 🎯 开始使用 配置完成后,对 AI 说: ``` 登录云开发 ``` 然后就可以开始开发了,例如: ``` 创建一个在线投票系统,支持创建投票、参与投票、结果统计,使用云数据库存储,最后部署 ``` CLINE 支持多种 AI 模型(Claude、GPT-4、DeepSeek 等),可以根据需要选择。 ## 🌟 CloudBase AI Toolkit 开源项目 ### 🔥 加入开源社区 [![GitHub](https://img.shields.io/badge/GitHub-TencentCloudBase/CloudBase--AI--ToolKit-black?style=for-the-badge&logo=github)](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit) [![CNB社区](https://img.shields.io/badge/CNB-CloudBase--AI--ToolKit-orange?style=for-the-badge)](https://cnb.cool/tencent/cloud/cloudbase/CloudBase-AI-ToolKit) **⭐ Star 项目 | 🤝 贡献代码 | 💬 技术交流** ## 🛠️ 故障排除 ### 常见问题 **Q: MCP 连接失败?** A: 1. 检查 `.clinerules/mcp.json` 配置格式 2. 确认 npx 命令可用:`npx --version` 3. 重启 VS Code 和 CLINE 插件 4. 检查网络连接状态 **Q: AI 生成的代码不符合预期?** A: 1. 提供更详细的需求描述和技术要求 2. 检查 AI 规则文件是否正确配置 3. 尝试分步骤描述需求 4. 使用项目模板确保规范一致性 **Q: 文件操作权限不足?** A: 1. 检查项目目录权限设置 2. 确认 VS Code 有足够的文件访问权限 3. 避免在系统保护目录下操作 更多问题请查看:[完整 FAQ](../faq) ## 📚 相关资源 - [📖 开发指南](../development) - 深入了解开发最佳实践 - [🎯 使用案例](../examples) - 查看实际应用案例 - [🔧 MCP 工具](../mcp-tools) - 了解所有可用工具 - [❓ 常见问题](../faq) - 查看常见问题解答 - [CLINE 官方文档](https://cline.so/docs) - CLINE 插件官方文档 ## 💬 技术交流 ### 微信技术交流群 扫码加入微信技术交流群 --- **🚀 立即开始使用 CLINE + CloudBase AI Toolkit** [开始使用](../getting-started) | [查看模板](../templates) | [GitHub 仓库](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit) --- ## CloudBase AI Toolkit + CodeBuddy # CloudBase AI Toolkit + CodeBuddy **🚀 CodeBuddy + 云开发 = 几分钟内从想法到上线的全栈应用** [![GitHub Stars](https://img.shields.io/github/stars/TencentCloudBase/CloudBase-AI-ToolKit?style=social)](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit) [![开源协议](https://img.shields.io/badge/License-MIT-blue.svg)](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/blob/main/LICENSE) > 💡 **重要提示:CodeBuddy 独立 IDE 已内置集成 CloudBase AI Toolkit,无需手动配置 MCP。** > 只需在 CodeBuddy 对话框点击“配置集成”按钮,选择 Tencent CloudBase 并授权,即可一键启用全部云开发能力。 > > 下文 MCP 配置和插件说明仅适用于 VSCode/JetBrains/微信开发者工具等非独立 IDE 场景。 > 💡 **为什么选择 CodeBuddy + CloudBase AI Toolkit?** > CodeBuddy 是腾讯推出的 AI 编程助手,具有强大的 Craft 智能体功能,能够与微信开发者工具深度集成。结合 CloudBase AI Toolkit,让你通过自然语言描述需求,AI 自动生成并部署全栈应用到腾讯云开发平台。特别适合腾讯生态的全栈开发,包括小程序、Web 应用和企业级项目。 ## ✨ 核心优势 | 🎯 **开发效率** | ⚡ **部署速度** | 🛡️ **稳定可靠** | |---|---|---| | AI 自动生成代码和架构内置云开发最佳实践规则智能错误修复和优化 | 一键部署到腾讯云开发国内 CDN 加速访问Serverless 架构免运维 | 330万开发者验证的平台企业级安全和稳定性完善的监控和日志系统 | ## 前提条件 1. **开通云开发**:请参考文档 [开通云开发环境](https://docs.cloudbase.net/quick-start/create-env) 2. **安装 CodeBuddy**:根据您的开发环境选择对应版本 ## 🔧 配置指南 ### 1. 配置 CloudBase ToolKit #### CodeBuddy IDE版 **CodeBuddy IDE** 用户请直接在设置页/集成点击"Tencent CloudBase"管理按钮并授权,无需手动配置 MCP: ![CodeBuddy IDE 集成配置](https://qcloudimg.tencent-cloud.cn/raw/181adab137d74530cbc2b73b280aa2d6.png) #### CodeBuddy 插件版 ##### 步骤 1:安装 CodeBuddy 根据您的开发环境选择安装方式: * **VS Code**: 在扩展商店搜索 "CodeBuddy" 安装 * **JetBrains**: 在插件市场搜索 "CodeBuddy" 安装 * **微信开发者工具**: 从腾讯云官网下载插件 ##### 步骤 2:配置 CloudBase MCP **方式一:通过 MCP 市场安装(推荐)** 1. 点击 CodeBuddy 右上角的 MCP 按钮 2. 在 MCP 市场中搜索 CloudBase 3. 点击安装即可 ![MCP 市场安装](https://qcloudimg.tencent-cloud.cn/raw/e23e9eb8a71a63c85a6fcb3845e62536.png) **方式二:手动配置** 1. 点击 CodeBuddy 右上角的 MCP 按钮 2. 点击右侧的添加按钮 3. 在 MCP 配置中添加以下内容: ```json { "mcpServers": { "cloudbase": { "command": "npx", "args": ["npm-global-exec@latest", "@cloudbase/cloudbase-mcp@latest"], "env": { "INTEGRATION_IDE": "CodeBuddyManual" } } } } ``` ![手动配置 MCP](https://qcloudimg.tencent-cloud.cn/raw/318db1a04f1f936924d2c4d1eaed1e5c.png) > **故障排查**:如果安装后工具数量显示为 0,请参考[常见问题](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/faq#mcp-%E6%98%BE%E7%A4%BA%E5%B7%A5%E5%85%B7%E6%95%B0%E9%87%8F%E4%B8%BA-0-%E6%80%8E%E4%B9%88%E5%8A%9E) ### 2. 项目初始化 #### 方式一:使用项目模板(推荐) 选择预配置的项目模板,开箱即用: **[📦 查看所有项目模板](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/templates)** 模板项目已包含 `.rules/` 目录,无需手动配置 AI 规则,可以直接开始开发。 #### 方式二:现有项目集成 如果您已有项目,在 Craft 模式下对 CodeBuddy 说: ``` 在当前项目中下载云开发 AI 规则 ``` 如果您只想下载 CodeBuddy 相关的配置文件,避免项目文件混乱,可以指定: ``` 在当前项目中下载云开发 AI 规则,只包含 CodeBuddy 配置 ``` ## 实战案例:在线投票系统 ### 1. 需求描述 在 **Craft** 模式下,选中 `Plan Mode` 模式对 CodeBuddy 说: ``` 创建一个在线投票系统,支持创建投票、参与投票、结果统计,使用云数据库存储,最后部署 ``` ### 2. 需求分析 CodeBuddy 会自动分析需求并生成规范的需求文档: ![需求分析过程](https://qcloudimg.tencent-cloud.cn/raw/4857ac3e9b676b9196d83e8dbb26f4c1.png) ![需求文档生成](https://qcloudimg.tencent-cloud.cn/raw/e020d3e49c45b5c5dcc418b7c113bee1.png) ### 3. 确认需求 需求讨论完毕后,CodeBuddy 会总结并确认需求文档。确认无误后,点击 `继续` 开始生成代码: ![需求确认](https://qcloudimg.tencent-cloud.cn/raw/e279e5a1b5ac1665e43f695a2b1795a2.png) ### 4. 自动开发 编写代码过程中,CodeBuddy 会自动调用 **CloudBase ToolKit** 进行数据库创建: ![数据库创建](https://qcloudimg.tencent-cloud.cn/raw/28a37244afe96630c5db118d235eb774.png) ### 5. 一键部署 开发完成后,CodeBuddy 会调用 **CloudBase ToolKit** 直接部署前端资源到云开发: ![资源部署](https://qcloudimg.tencent-cloud.cn/raw/b8c08a2da14567128c1a1c5c6053d7b2.png) 至此,我们通过一句简单的需求描述,借助 **CodeBuddy** 和 **CloudBase AI Toolkit** 完成了需求分析、代码生成、数据库创建、前后端部署等一系列工作。 ## 效果展示 ### 投票列表 ![投票列表页面](https://qcloudimg.tencent-cloud.cn/raw/e1ee4103c6271c342d189b24e0b96914.png) ### 新建投票 ![新建投票页面](https://qcloudimg.tencent-cloud.cn/raw/4b7774a49bcad87431082a723e8aa5de.png) ### 投票详情 ![投票详情页面](https://qcloudimg.tencent-cloud.cn/raw/ee6e21beb9fcfd75b24e55033ce31f39.png) ### 个人中心 ![个人中心页面](https://qcloudimg.tencent-cloud.cn/raw/12c67750fff593a11b900f1fa96e9835.png) **在线体验**:[https://lowcode-9g2yhkab1a980408-1308771514.tcloudbaseapp.com/vote_base/](https://lowcode-9g2yhkab1a980408-1308771514.tcloudbaseapp.com/vote_base/) ## 🛠️ 故障排除 ### 常见问题 **Q: 独立 IDE 无法集成 CloudBase?** A: 1. 请确保已在对话框点击“配置集成”并完成 Tencent CloudBase 授权 2. 如遇网络或授权问题,重启 IDE 并重试 **Q: MCP 连接失败?(仅插件模式)** A: 1. 检查 MCP 配置格式是否正确 2. 重启 CodeBuddy 3. 确认网络连接正常 **Q: AI 生成的代码不符合预期?** A: 1. 明确描述技术栈和框架要求 2. 使用项目模板确保规范一致性 3. 提供更详细的需求描述 更多问题请查看:[完整 FAQ](../faq) ## 📚 相关资源 - [📖 开发指南](../development) - 深入了解开发最佳实践 - [🎯 使用案例](../examples) - 查看实际应用案例 - [🔧 MCP 工具](../mcp-tools) - 了解所有可用工具 - [❓ 常见问题](../faq) - 查看常见问题解答 ## 💬 技术交流 ### 微信技术交流群 扫码加入微信技术交流群 --- **🚀 立即开始使用 CodeBuddy + CloudBase AI Toolkit** [开始使用](../getting-started) | [查看模板](../templates) | [GitHub 仓库](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit) --- ## CloudBase AI Toolkit + Cursor # CloudBase AI Toolkit + Cursor **🚀 Cursor + 云开发 = 几分钟内从想法到上线的全栈应用** [![GitHub Stars](https://img.shields.io/github/stars/TencentCloudBase/CloudBase-AI-ToolKit?style=social)](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit) [![开源协议](https://img.shields.io/badge/License-MIT-blue.svg)](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/blob/main/LICENSE) > 💡 **为什么选择 Cursor + CloudBase AI Toolkit?** > Cursor 是专为 AI 编程设计的现代化 IDE,拥有强大的 Agent 模式和代码生成能力。结合 CloudBase AI Toolkit,让你通过自然语言描述需求,AI 自动生成并部署全栈应用到腾讯云开发平台。特别适合快速原型开发、全栈项目构建和云端部署场景。 ## ✨ 核心优势 | 🎯 **开发效率** | ⚡ **部署速度** | 🛡️ **稳定可靠** | |---|---|---| | AI 自动生成代码和架构内置云开发最佳实践规则智能错误修复和优化 | 一键部署到腾讯云开发国内 CDN 加速访问Serverless 架构免运维 | 330万开发者验证的平台企业级安全和稳定性完善的监控和日志系统 | ## 🚀 5分钟快速开始 ### 方式一:使用项目模板(推荐) 选择预配置的项目模板,开箱即用: **[📦 查看所有项目模板](../templates)** ### 方式二:现有项目集成 如果你已有项目,只需 3 步集成: ```bash # 1. 配置 MCP(具体配置见下方详细步骤) # 2. 下载 AI 规则 # 3. 开始使用 ``` 配置完成后,对 AI 说:**"登录云开发"** 即可开始! ## 🔧 详细配置指南 ### 步骤 1:安装 Cursor 从 [Cursor 官网](https://cursor.com/) 下载并安装 Cursor IDE。 ### 步骤 2:配置 CloudBase MCP > [!TIP] > 如果安装以后工具数量一直为 0,请参考[常见问题](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/faq#mcp-%E6%98%BE%E7%A4%BA%E5%B7%A5%E5%85%B7%E6%95%B0%E9%87%8F%E4%B8%BA-0-%E6%80%8E%E4%B9%88%E5%8A%9E) **一键安装(推荐):** [![Install MCP Server](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/install-mcp?name=cloudbase&config=JTdCJTIyY29tbWFuZCUyMiUzQSUyMm5weCUyMG5wbS1nbG9iYWwtZXhlYyU0MGxhdGVzdCUyMCU0MGNsb3VkYmFzZSUyRmNsb3VkYmFzZS1tY3AlNDBsYXRlc3QlMjIlMkMlMjJlbnYlMjIlM0ElN0IlMjJJTlRFR1JBVElPTl9JREUlMjIlM0ElMjJDdXJzb3IlMjIlN0QlN0Q%3D) **手动配置:** 在项目根目录创建 `.cursor/mcp.json` 文件: ```json { "mcpServers": { "cloudbase": { "command": "npx", "args": ["npm-global-exec@latest", "@cloudbase/cloudbase-mcp@latest"], "env": { "INTEGRATION_IDE": "Cursor" } } } } ``` 然后点击 Cursor 客户端右上角的 ⚙️ 图标,进入"MCP"设置,找到 cloudbase 并启用。 ### 步骤 3:启用 AI 规则 模板项目已包含 `.cursor/rules/` 目录。如果是现有项目,对 AI 说: ``` 在当前项目中下载云开发 AI 规则 ``` 如果你只想下载Cursor相关的配置文件,避免项目文件混乱,可以指定IDE类型: ``` 在当前项目中下载云开发 AI 规则,只包含Cursor配置 ``` ### 步骤 4:开始开发 在 Agent 模式下与 AI 对话: ``` 登录云开发 ``` ## 🎯 开始使用 配置完成后,对 AI 说: ``` 登录云开发 ``` 然后就可以开始开发了,例如: ``` 创建一个在线投票系统,支持创建投票、参与投票、结果统计,使用云数据库存储,最后部署 ``` ## 🌟 CloudBase AI Toolkit 开源项目 ### 🔥 加入开源社区 [![GitHub](https://img.shields.io/badge/GitHub-TencentCloudBase/CloudBase--AI--ToolKit-black?style=for-the-badge&logo=github)](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit) [![CNB社区](https://img.shields.io/badge/CNB-CloudBase--AI--ToolKit-orange?style=for-the-badge)](https://cnb.cool/tencent/cloud/cloudbase/CloudBase-AI-ToolKit) **⭐ Star 项目 | 🤝 贡献代码 | 💬 技术交流** ## 🛠️ 故障排除 ### 常见问题 **Q: MCP 连接失败?** A: 1. 检查配置文件格式是否正确 2. 重启 Cursor 3. 确认网络连接正常 **Q: AI 生成的代码不符合预期?** A: 1. 明确描述技术栈和框架要求 2. 使用项目模板确保规范一致性 3. 提供更详细的需求描述 更多问题请查看:[完整 FAQ](../faq) ## 📚 相关资源 - [📖 开发指南](../development) - 深入了解开发最佳实践 - [🎯 使用案例](../examples) - 查看实际应用案例 - [🔧 MCP 工具](../mcp-tools) - 了解所有可用工具 - [❓ 常见问题](../faq) - 查看常见问题解答 ## 💬 技术交流 ### 微信技术交流群 扫码加入微信技术交流群 --- **🚀 立即开始使用 Cursor + CloudBase AI Toolkit** [开始使用](../getting-started) | [查看模板](../templates) | [GitHub 仓库](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit) --- ## CloudBase AI Toolkit + Gemini CLI # CloudBase AI Toolkit + Gemini CLI **🚀 Gemini CLI + 云开发 = 几分钟内从想法到上线的全栈应用** [![GitHub Stars](https://img.shields.io/github/stars/TencentCloudBase/CloudBase-AI-ToolKit?style=social)](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit) [![开源协议](https://img.shields.io/badge/License-MIT-blue.svg)](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/blob/main/LICENSE) > 💡 **为什么选择 Gemini CLI + CloudBase AI Toolkit?** > Gemini CLI 是 Google 推出的开源命令行 AI 代理,提供强大的本地 AI 工作流和 MCP 协议支持,拥有 1M 令牌上下文窗口和丰富的内置工具。结合 CloudBase AI Toolkit,让你通过自然语言描述需求,AI 自动生成并部署全栈应用到腾讯云开发平台。特别适合命令行爱好者、自动化脚本开发和快速原型构建。 ## ✨ 核心优势 | 🎯 **开发效率** | ⚡ **部署速度** | 🛡️ **稳定可靠** | |---|---|---| | AI 自动生成代码和架构内置云开发最佳实践规则智能错误修复和优化 | 一键部署到腾讯云开发国内 CDN 加速访问Serverless 架构免运维 | 330万开发者验证的平台企业级安全和稳定性完善的监控和日志系统 | ## 🚀 5分钟快速开始 ### 方式一:使用项目模板(推荐) 选择预配置的项目模板,开箱即用: **[📦 查看所有项目模板](../templates)** ### 方式二:现有项目集成 如果你已有项目,只需 3 步集成: ```bash # 1. 配置 MCP(具体配置见下方详细步骤) # 2. 下载 AI 规则 # 3. 开始使用 ``` 配置完成后,对 AI 说:**"登录云开发"** 即可开始! ## 🔧 详细配置指南 ### 步骤 1:安装 Gemini CLI 确保安装 Node.js 18+,然后全局安装 Gemini CLI: ```bash npm install -g @google/gemini-cli ``` 或直接运行: ```bash npx @google/gemini-cli ``` 首次运行时,使用个人 Google 账户登录即可获得免费额度(每分钟 60 次请求,每天 1000 次请求)。 ### 步骤 2:配置 CloudBase MCP > [!TIP] > 如果安装以后工具数量一直为 0,请参考[常见问题](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/faq#mcp-%E6%98%BE%E7%A4%BA%E5%B7%A5%E5%85%B7%E6%95%B0%E9%87%8F%E4%B8%BA-0-%E6%80%8E%E4%B9%88%E5%8A%9E) 如果使用模板项目,MCP 配置已经预置完成。 如果不是从模板开始,可以在用户主目录(`~`)或项目目录中创建 `.gemini/settings.json` 文件: ```json { "mcpServers": { "cloudbase": { "command": "npx", "args": ["npm-global-exec@latest", "@cloudbase/cloudbase-mcp@latest"], "env": { "INTEGRATION_IDE": "Gemini" } } } } ``` **一键配置验证:** 运行 Gemini CLI,然后使用以下命令: ```bash gemini > /mcp ``` 查看已配置的 MCP 服务器。如果还没有配置 CloudBase MCP,可以手动添加配置文件。 ### 步骤 3:启用 AI 规则 模板项目根目录已经包含 `GEMINI.md` 文件,包含 CloudBase 开发规则。 如果是现有项目,在 Gemini CLI 中对 AI 说: ``` 在当前项目中下载云开发 AI 规则 ``` 如果你只想下载Gemini CLI相关的配置文件,避免项目文件混乱,可以指定IDE类型: ``` 在当前项目中下载云开发 AI 规则,只包含Gemini CLI配置 ``` ### 步骤 4:开始开发 启动 Gemini CLI: ```bash gemini ``` 然后对 AI 说: ``` 登录云开发 ``` ## 🎯 开始使用 配置完成后,对 AI 说: ``` 登录云开发 ``` 然后就可以开始开发了,例如: ``` 创建一个在线投票系统,支持创建投票、参与投票、结果统计,使用云数据库存储,最后部署 ``` ## 💡 Gemini CLI 特色功能 ### 🔧 内置工具 Gemini CLI 提供丰富的内置工具: - **Google Search**: 实时搜索信息 - **文件操作**: 读写、编辑文件 - **Shell 命令**: 执行系统命令 - **MCP 支持**: 扩展第三方能力 查看所有可用工具: ```bash > /tools ``` ### 📚 上下文记忆 Gemini CLI 支持分层的 `GEMINI.md` 文件: - 全局规则:`~/.gemini/GEMINI.md` - 项目规则:项目根目录/`GEMINI.md` - 组件规则:子目录中的 `GEMINI.md` 查看当前加载的规则: ```bash > /memory show ``` 刷新规则: ```bash > /memory refresh ``` ### ⚡ 命令模式 常用命令: - `/tools` - 查看可用工具 - `/mcp` - 查看 MCP 服务器状态 - `/memory` - 管理上下文记忆 - `/stats` - 查看会话统计 - `!command` - 执行 Shell 命令 ### 🚀 YOLO 模式 自动执行所有操作,无需确认: ```bash gemini --yolo ``` **⚠️ 注意:YOLO 模式会自动执行所有操作,请谨慎使用。** ## 🌟 CloudBase AI Toolkit 开源项目 ### 🔥 加入开源社区 [![GitHub](https://img.shields.io/badge/GitHub-TencentCloudBase/CloudBase--AI--ToolKit-black?style=for-the-badge&logo=github)](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit) [![CNB社区](https://img.shields.io/badge/CNB-CloudBase--AI--ToolKit-orange?style=for-the-badge)](https://cnb.cool/tencent/cloud/cloudbase/CloudBase-AI-ToolKit) **⭐ Star 项目 | 🤝 贡献代码 | 💬 技术交流** ## 🛠️ 故障排除 ### 常见问题 **Q: Gemini CLI 连接失败?** A: 1. 检查网络连接 2. 确认 Google 账户登录状态 3. 检查 `.gemini/settings.json` 配置格式 **Q: MCP 服务器启动失败?** A: 1. 确认 Node.js 版本 >= 18 2. 检查 MCP 配置格式 3. 运行 `/mcp` 命令查看状态 **Q: AI 生成的代码不符合预期?** A: 1. 检查 `GEMINI.md` 文件是否存在 2. 使用 `/memory show` 查看当前规则 3. 提供更详细的需求描述 更多问题请查看:[完整 FAQ](../faq) ## 🔗 官方资源 - [Gemini CLI GitHub](https://github.com/google-gemini/gemini-cli) - 官方开源仓库 - [Gemini CLI 文档](https://github.com/google-gemini/gemini-cli/tree/main/docs) - 详细使用文档 - [Google AI Studio](https://aistudio.google.com/) - 获取 API 密钥 ## 📚 相关资源 - [📖 开发指南](../development) - 深入了解开发最佳实践 - [🎯 使用案例](../examples) - 查看实际应用案例 - [🔧 MCP 工具](../mcp-tools) - 了解所有可用工具 - [❓ 常见问题](../faq) - 查看常见问题解答 ## 💬 技术交流 ### 微信技术交流群 扫码加入微信技术交流群 --- **🚀 立即开始使用 Gemini CLI + CloudBase AI Toolkit** [开始使用](../getting-started) | [查看模板](../templates) | [GitHub 仓库](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit) --- ## CloudBase AI Toolkit + GitHub Copilot # CloudBase AI Toolkit + GitHub Copilot **🚀 GitHub Copilot + 云开发 = 几分钟内从想法到上线的全栈应用** [![GitHub Stars](https://img.shields.io/github/stars/TencentCloudBase/CloudBase-AI-ToolKit?style=social)](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit) [![开源协议](https://img.shields.io/badge/License-MIT-blue.svg)](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/blob/main/LICENSE) > 💡 **为什么选择 GitHub Copilot + CloudBase AI Toolkit?** > GitHub Copilot 是 GitHub 官方的 AI 编程助手,支持强大的代码生成和智能建议。结合 CloudBase AI Toolkit,让你通过自然语言描述需求,AI 自动生成并部署全栈应用到腾讯云开发平台。特别适合已有 GitHub Copilot 订阅且习惯 VS Code 环境的开发者。 ## ✨ 核心优势 | 🎯 **开发效率** | ⚡ **部署速度** | 🛡️ **稳定可靠** | |---|---|---| | AI 自动生成代码和架构内置云开发最佳实践规则智能错误修复和优化 | 一键部署到腾讯云开发国内 CDN 加速访问Serverless 架构免运维 | 330万开发者验证的平台企业级安全和稳定性完善的监控和日志系统 | ## 🚀 5分钟快速开始 ### 方式一:使用项目模板(推荐) 选择预配置的项目模板,开箱即用: **[📦 查看所有项目模板](../templates)** ### 方式二:现有项目集成 如果你已有项目,只需 3 步集成: ```bash # 1. 配置 MCP(具体配置见下方详细步骤) # 2. 下载 AI 规则 # 3. 开始使用 ``` 配置完成后,对 AI 说:**"登录云开发"** 即可开始! ## 🔧 详细配置指南 ### 步骤 1:安装 GitHub Copilot 1. 确保拥有 GitHub Copilot 订阅 2. 在 VS Code 中安装 "GitHub Copilot" 和 "GitHub Copilot Chat" 扩展 3. 使用 GitHub 账号登录授权 ### 步骤 2:配置 CloudBase MCP > [!TIP] > 如果安装以后工具数量一直为 0,请参考[常见问题](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/faq#mcp-%E6%98%BE%E7%A4%BA%E5%B7%A5%E5%85%B7%E6%95%B0%E9%87%8F%E4%B8%BA-0-%E6%80%8E%E4%B9%88%E5%8A%9E) 创建 `.vscode/mcp.json` 文件: ```json { "servers": { "cloudbase": { "command": "npx", "args": [ "npm-global-exec@latest", "@cloudbase/cloudbase-mcp@latest", ], "env": { "INTEGRATION_IDE": "VSCode Copilot" } } } } ``` ### 步骤 3:启用 AI 规则 创建 `.github/copilot-instructions.md` 文件,或直接对 AI 说: ``` 在当前项目中下载云开发 AI 规则 ``` 如果你只想下载GitHub Copilot相关的配置文件,避免项目文件混乱,可以指定IDE类型: ``` 在当前项目中下载云开发 AI 规则,只包含GitHub Copilot配置 ``` ### 步骤 4:开始开发 在 VS Code 中: 1. 打开 Copilot Chat 面板 2. 在对话窗口左下角切换到 **Agent** 模式 3. 确认 MCP 工具已连接 与 AI 对话: ``` 登录云开发 ``` ## 🎯 开始使用 配置完成后,对 AI 说: ``` 登录云开发 ``` 然后就可以开始开发了,例如: ``` 创建一个在线投票系统,支持创建投票、参与投票、结果统计,使用云数据库存储,最后部署 ``` GitHub Copilot 支持 @workspace 和 #selection 等指令,可以更好地理解项目上下文。 ## 🌟 CloudBase AI Toolkit 开源项目 ### 🔥 加入开源社区 [![GitHub](https://img.shields.io/badge/GitHub-TencentCloudBase/CloudBase--AI--ToolKit-black?style=for-the-badge&logo=github)](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit) [![CNB社区](https://img.shields.io/badge/CNB-CloudBase--AI--ToolKit-orange?style=for-the-badge)](https://cnb.cool/tencent/cloud/cloudbase/CloudBase-AI-ToolKit) **⭐ Star 项目 | 🤝 贡献代码 | 💬 技术交流** ## 🛠️ 故障排除 ### 常见问题 **Q: GitHub Copilot 无法连接?** A: 1. 检查 GitHub Copilot 订阅状态 2. 在 VS Code 中重新登录 GitHub 账号 3. 重启 VS Code 应用 4. 检查网络连接状态 **Q: MCP 工具不可用?** A: 1. 确认 `.vscode/mcp.json` 配置正确 2. 检查 npx 命令是否可用 3. 重新启用 GitHub Copilot Chat 扩展 4. 查看 VS Code 输出日志 **Q: AI 生成的代码不符合预期?** A: 1. 在 `.github/copilot-instructions.md` 中明确规范 2. 使用 @workspace 让 AI 理解项目上下文 3. 提供示例代码作为参考 更多问题请查看:[完整 FAQ](../faq) ## 📚 相关资源 - [📖 开发指南](../development) - 深入了解开发最佳实践 - [🎯 使用案例](../examples) - 查看实际应用案例 - [🔧 MCP 工具](../mcp-tools) - 了解所有可用工具 - [❓ 常见问题](../faq) - 查看常见问题解答 - [GitHub Copilot 官方文档](https://docs.github.com/copilot) - GitHub Copilot 官方文档 ## 💬 技术交流 ### 微信技术交流群 扫码加入微信技术交流群 --- **🚀 立即开始使用 GitHub Copilot + CloudBase AI Toolkit** [开始使用](../getting-started) | [查看模板](../templates) | [GitHub 仓库](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit) --- ## CloudBase AI Toolkit + OpenAI Codex CLI # CloudBase AI Toolkit + OpenAI Codex CLI **🚀 OpenAI Codex CLI + 云开发 = 几分钟内从想法到上线的全栈应用** [![GitHub Stars](https://img.shields.io/github/stars/TencentCloudBase/CloudBase-AI-ToolKit?style=social)](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit) [![开源协议](https://img.shields.io/badge/License-MIT-blue.svg)](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/blob/main/LICENSE) > 💡 **为什么选择 OpenAI Codex CLI + CloudBase AI Toolkit?** > OpenAI Codex CLI 是基于 OpenAI Codex 模型的命令行工具,支持 MCP (Model Context Protocol) 协议,具有强大的代码生成和理解能力。结合 CloudBase AI Toolkit,让你通过自然语言描述需求,AI 自动生成并部署全栈应用到腾讯云开发平台。特别适合命令行开发者和需要高效 AI 辅助开发的场景。 ## ✨ 核心优势 | 🎯 **开发效率** | ⚡ **部署速度** | 🛡️ **稳定可靠** | |---|---|---| | AI 自动生成代码和架构内置云开发最佳实践规则命令行高效交互方式 | 一键部署到腾讯云开发国内 CDN 加速访问Serverless 架构免运维 | 330万开发者验证的平台企业级安全和稳定性完善的监控和日志系统 | ## 🚀 5分钟快速开始 ### 方式一:使用项目模板(推荐) 选择预配置的项目模板,开箱即用: **[📦 查看所有项目模板](../templates)** ### 方式二:现有项目集成 如果你已有项目,只需 3 步集成: ```bash # 1. 安装 OpenAI Codex CLI # 2. 配置 MCP(具体配置见下方详细步骤) # 3. 启动 Codex CLI 并开始使用 ``` 配置完成后,对 AI 说:**"登录云开发"** 即可开始! ## 🔧 详细配置指南 ### 步骤 1:安装 OpenAI Codex CLI ```bash npm install -g @openai/codex ``` ### 步骤 2:配置 CloudBase MCP > [!TIP] > 如果安装以后工具数量一直为 0,请参考[常见问题](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/faq#mcp-%E6%98%BE%E7%A4%BA%E5%B7%A5%E5%85%B7%E6%95%B0%E9%87%8F%E4%B8%BA-0-%E6%80%8E%E4%B9%88%E5%8A%9E) 如果使用模板项目,MCP 配置已经预置完成。如果不是从模板开始,有两种配置方式: #### 方式一:使用项目配置文件(推荐) 在项目根目录创建 `.codex/config.toml` 文件: ```toml [mcp_servers.cloudbase] command = "npx" args = ["npm-global-exec@latest", "@cloudbase/cloudbase-mcp@latest"] env = { INTEGRATION_IDE = "CodeX" } ``` 然后启动时指定配置文件: ```bash codex --config .codex/config.toml ``` #### 方式二:全局配置 在用户主目录创建 `~/.codex/config.toml` 文件: ```toml [mcp_servers.cloudbase] command = "npx" args = ["@cloudbase/cloudbase-mcp@latest"] ``` ### 步骤 3:启用 AI 规则 模板中已包含 `AGENTS.md` 文件,OpenAI Codex CLI 会自动识别云开发最佳实践。如果不是从模板开始,可以让 AI 帮你下载云开发规则: ``` 在当前项目中下载云开发 AI 规则 ``` 如果你只想下载OpenAI Codex CLI相关的配置文件,避免项目文件混乱,可以指定IDE类型: ``` 在当前项目中下载云开发 AI 规则,只包含OpenAI Codex CLI配置 ``` ### 步骤 4:开始开发 启动 OpenAI Codex CLI: ```bash codex ``` 如果使用项目配置文件: ```bash codex --config .codex/config.toml ``` 在 Codex CLI 中与 AI 对话: ``` 登录云开发 ``` ## 🎯 常用命令 配置完成后,就可以开始开发了,例如: ``` 创建一个在线投票系统,支持创建投票、参与投票、结果统计,使用云数据库存储,最后部署 ``` OpenAI Codex CLI 具有强大的代码理解能力,能够深度分析项目结构并生成高质量的代码。 ## 🌟 CloudBase AI Toolkit 开源项目 ### 🔥 加入开源社区 [![GitHub](https://img.shields.io/badge/GitHub-TencentCloudBase/CloudBase--AI--ToolKit-black?style=for-the-badge&logo=github)](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit) [![CNB社区](https://img.shields.io/badge/CNB-CloudBase--AI--ToolKit-orange?style=for-the-badge)](https://cnb.cool/tencent/cloud/cloudbase/CloudBase-AI-ToolKit) **⭐ Star 项目 | 🤝 贡献代码 | 💬 技术交流** ## 🛠️ 故障排除 ### 常见问题 **Q: MCP 连接失败?** A: 1. 检查 `.codex/config.toml` 文件格式是否正确 2. 确认 npx 命令可用:`npx --version` 3. 重启 Codex CLI 应用 4. 检查网络连接状态 **Q: 项目规则未生效?** A: 1. 确认 `AGENTS.md` 文件在项目根目录 2. 检查文件内容格式是否正确 3. 重新启动 Codex CLI **Q: AI 生成的代码不符合预期?** A: 1. 详细描述功能需求和技术要求 2. 使用项目模板确保规范一致性 3. 分模块逐步实现复杂项目 **Q: 如何使用项目配置文件?** A: 1. 在项目根目录创建 `.codex/config.toml` 文件 2. 启动时使用 `codex --config .codex/config.toml` 3. 这样可以为不同项目使用不同的配置 更多问题请查看:[完整 FAQ](../faq) ## 📚 相关资源 - [📖 开发指南](../development) - 深入了解开发最佳实践 - [🎯 使用案例](../examples) - 查看实际应用案例 - [🔧 MCP 工具](../mcp-tools) - 了解所有可用工具 - [❓ 常见问题](../faq) - 查看常见问题解答 - [OpenAI Codex CLI 官方文档](https://github.com/openai/codex) - OpenAI Codex CLI 官方文档 ## 💬 技术交流 ### 微信技术交流群 扫码加入微信技术交流群 --- **🚀 立即开始使用 OpenAI Codex CLI + CloudBase AI Toolkit** [开始使用](../getting-started) | [查看模板](../templates) | [GitHub 仓库](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit) --- ## CloudBase AI Toolkit + OpenCode # CloudBase AI Toolkit + OpenCode **🚀 OpenCode + 云开发 = 几分钟内从想法到上线的全栈应用** [![GitHub Stars](https://img.shields.io/github/stars/TencentCloudBase/CloudBase-AI-ToolKit?style=social)](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit) [![开源协议](https://img.shields.io/badge/License-MIT-blue.svg)](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/blob/main/LICENSE) > 💡 **为什么选择 OpenCode + CloudBase AI Toolkit?** > OpenCode 是一个开源的 AI 编程 CLI 工具,支持多种 AI 模型和 MCP 协议,具有强大的代码生成和项目管理能力。结合 CloudBase AI Toolkit,让你通过自然语言描述需求,AI 自动生成并部署全栈应用到腾讯云开发平台。特别适合命令行开发者、自动化部署场景和多环境管理。 ## ✨ 核心优势 | 🎯 **开发效率** | ⚡ **部署速度** | 🛡️ **稳定可靠** | |---|---|---| | AI 自动生成代码和架构内置云开发最佳实践规则智能错误修复和优化 | 一键部署到腾讯云开发国内 CDN 加速访问Serverless 架构免运维 | 330万开发者验证的平台企业级安全和稳定性完善的监控和日志系统 | ## 🚀 5分钟快速开始 ### 方式一:使用项目模板(推荐) 选择预配置的项目模板,开箱即用: **[📦 查看所有项目模板](../templates)** ### 方式二:现有项目集成 如果你已有项目,只需 3 步集成: ```bash # 1. 配置 MCP(具体配置见下方详细步骤) # 2. 下载 AI 规则 # 3. 开始使用 ``` 配置完成后,运行 OpenCode 并说:**"登录云开发"** 即可开始! ## 🔧 详细配置指南 ### 步骤 1:安装 OpenCode 从 [OpenCode GitHub](https://github.com/opencode-ai/opencode) 下载并安装 OpenCode CLI 工具。 ```bash # 使用 npm 安装 npm install -g opencode # 或者使用 yarn yarn global add opencode # 或者直接从 GitHub 下载二进制文件 ``` ### 步骤 2:配置 CloudBase MCP > [!TIP] > 如果安装以后工具数量一直为 0,请参考[常见问题](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/faq#mcp-%E6%98%BE%E7%A4%BA%E5%B7%A5%E5%85%B7%E6%95%B0%E9%87%8F%E4%B8%BA-0-%E6%80%8E%E4%B9%88%E5%8A%9E) 在项目根目录创建 `.opencode.json` 文件: ```json { "mcpServers": { "cloudbase": { "command": "npx", "args": [ "npm-global-exec@latest", "@cloudbase/cloudbase-mcp@latest" ], "env": { "INTEGRATION_IDE": "OpenCode" } } } } ``` ### 步骤 3:启用 AI 规则 OpenCode 支持多种规则文件格式,已包含 `OPENCODE.md` 规则文件。如果是现有项目,对 AI 说: ``` 在当前项目中下载云开发 AI 规则 ``` 如果你只想下载OpenCode相关的配置文件,避免项目文件混乱,可以指定IDE类型: ``` 在当前项目中下载云开发 AI 规则,只包含OpenCode配置 ``` ### 步骤 4:开始开发 使用 OpenCode CLI 与 AI 对话: ```bash # 启动 OpenCode opencode # 或者直接提问 opencode "登录云开发" ``` ## 🎯 开始使用 配置完成后,对 AI 说: ``` 登录云开发 ``` 然后就可以开始开发了,例如: ``` 创建一个在线投票系统,支持创建投票、参与投票、结果统计,使用云数据库存储,最后部署 ``` ## 🌟 CloudBase AI Toolkit 开源项目 ### 🔥 加入开源社区 [![GitHub](https://img.shields.io/badge/GitHub-TencentCloudBase/CloudBase--AI--ToolKit-black?style=for-the-badge&logo=github)](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit) [![CNB社区](https://img.shields.io/badge/CNB-CloudBase--AI--ToolKit-orange?style=for-the-badge)](https://cnb.cool/tencent/cloud/cloudbase/CloudBase-AI-ToolKit) **⭐ Star 项目 | 🤝 贡献代码 | 💬 技术交流** ## 🛠️ 故障排除 ### 常见问题 **Q: MCP 连接失败?** A: 1. 检查配置文件格式是否正确 2. 重启 OpenCode 3. 确认网络连接正常 4. 检查 Node.js 版本(建议 18+) **Q: AI 生成的代码不符合预期?** A: 1. 明确描述技术栈和框架要求 2. 使用项目模板确保规范一致性 3. 提供更详细的需求描述 **Q: 命令行工具无响应?** A: 1. 检查是否正确安装了 OpenCode 2. 确认 MCP 服务器配置正确 3. 尝试重新启动终端 更多问题请查看:[完整 FAQ](../faq) ## 📚 相关资源 - [📖 开发指南](../development) - 深入了解开发最佳实践 - [🎯 使用案例](../examples) - 查看实际应用案例 - [🔧 MCP 工具](../mcp-tools) - 了解所有可用工具 - [❓ 常见问题](../faq) - 查看常见问题解答 ## 💬 技术交流 ### 微信技术交流群 扫码加入微信技术交流群 --- **🚀 立即开始使用 OpenCode + CloudBase AI Toolkit** [开始使用](../getting-started) | [查看模板](../templates) | [GitHub 仓库](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit) --- ## CloudBase AI Toolkit + Qwen Code # CloudBase AI Toolkit + Qwen Code **🚀 Qwen Code + 云开发 = 几分钟内从想法到上线的全栈应用** [![GitHub Stars](https://img.shields.io/github/stars/TencentCloudBase/CloudBase-AI-ToolKit?style=social)](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit) [![开源协议](https://img.shields.io/badge/License-MIT-blue.svg)](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/blob/main/LICENSE) > 💡 **为什么选择 Qwen Code + CloudBase AI Toolkit?** > Qwen Code 是基于 Gemini CLI 开源修改的命令行 AI 编程工具,专为 Qwen3-Coder 模型优化,支持超大上下文、丰富的本地 AI 工作流和 MCP 协议。适合命令行爱好者、自动化脚本开发和快速原型构建。 ## ✨ 核心优势 | 🎯 **开发效率** | ⚡ **部署速度** | 🛡️ **稳定可靠** | |---|---|---| | AI 自动生成代码和架构内置云开发最佳实践规则智能错误修复和优化 | 一键部署到腾讯云开发国内 CDN 加速访问Serverless 架构免运维 | 330万开发者验证的平台企业级安全和稳定性完善的监控和日志系统 | ## 🚀 5分钟快速开始 ### 方式一:使用项目模板(推荐) 选择预配置的项目模板,开箱即用: **[📦 查看所有项目模板](../templates)** ### 方式二:现有项目集成 如果你已有项目,只需 3 步集成: ```bash # 1. 配置 MCP(具体配置见下方详细步骤) # 2. 下载 AI 规则 # 3. 开始使用 ``` 配置完成后,对 AI 说:**"登录云开发"** 即可开始! ### 步骤 3:启用 AI 规则 项目根目录下可放置 `.qwen/QWEN.md`,内容结构与 CLAUDE.md/GEMINI.md 保持一致。 如果是现有项目,对 AI 说: ``` 在当前项目中下载云开发 AI 规则 ``` 如果你只想下载Qwen Code相关的配置文件,避免项目文件混乱,可以指定IDE类型: ``` 在当前项目中下载云开发 AI 规则,只包含Qwen Code配置 ``` ## 🔧 详细配置指南 ### 步骤 1:安装 Qwen Code 需 Node.js 20+,推荐全局安装: ```bash npm install -g @qwen-code/qwen-code ``` 或直接运行: ```bash npx @qwen-code/qwen-code ``` ### 步骤 2:配置 CloudBase MCP 在项目根目录或主目录下创建 `.qwen/settings.json`: ```json { "mcpServers": { "cloudbase": { "command": "npx", "args": [ "npm-global-exec@latest", "@cloudbase/cloudbase-mcp@latest" ], "env": { "INTEGRATION_IDE": "Qwen" } } } } ``` ### 步骤 4:开始开发 在 Qwen Code 命令行下与 AI 对话: ``` 登录云开发 ``` ## 🎯 开始使用 配置完成后,对 AI 说: ``` 登录云开发 ``` 然后就可以开始开发了,例如: ``` 创建一个在线投票系统,支持创建投票、参与投票、结果统计,使用云数据库存储,最后部署 ``` ## 🛠️ 故障排除 ### 常见问题 **Q: MCP 连接失败?** A: 1. 检查 `.qwen/settings.json` 配置文件格式是否正确 2. 重启 Qwen Code 3. 确认网络连接正常 **Q: AI 生成的代码不符合预期?** A: 1. 明确描述技术栈和框架要求 2. 使用项目模板确保规范一致性 3. 提供更详细的需求描述 更多问题请查看:[完整 FAQ](../faq) ## 📚 相关资源 - [Qwen Code GitHub](https://github.com/QwenLM/qwen-code) - [Qwen Code 官方文档](https://github.com/QwenLM/qwen-code/tree/main/docs) - [📖 开发指南](../development) - [🎯 使用案例](../examples) - [🔧 MCP 工具](../mcp-tools) - [❓ 常见问题](../faq) ## 💬 技术交流 ### 微信技术交流群 扫码加入微信技术交流群 --- **🚀 立即开始使用 Qwen Code + CloudBase AI Toolkit** [开始使用](../getting-started) | [查看模板](../templates) | [GitHub 仓库](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit) --- ## CloudBase AI Toolkit + RooCode # CloudBase AI Toolkit + RooCode **🚀 RooCode + 云开发 = 几分钟内从想法到上线的全栈应用** [![GitHub Stars](https://img.shields.io/github/stars/TencentCloudBase/CloudBase-AI-ToolKit?style=social)](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit) [![开源协议](https://img.shields.io/badge/License-MIT-blue.svg)](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/blob/main/LICENSE) > 💡 **为什么选择 RooCode + CloudBase AI Toolkit?** > RooCode 是一款专业的 AI 编程助手,支持 VS Code 集成。结合 CloudBase AI Toolkit,让你通过自然语言描述需求,AI 自动生成并部署全栈应用到腾讯云开发平台。特别适合追求轻量级工具和简洁开发体验的个人开发者。 ## ✨ 核心优势 | 🎯 **开发效率** | ⚡ **部署速度** | 🛡️ **稳定可靠** | |---|---|---| | AI 自动生成代码和架构内置云开发最佳实践规则智能错误修复和优化 | 一键部署到腾讯云开发国内 CDN 加速访问Serverless 架构免运维 | 330万开发者验证的平台企业级安全和稳定性完善的监控和日志系统 | ## 🚀 5分钟快速开始 ### 方式一:使用项目模板(推荐) 选择预配置的项目模板,开箱即用: **[📦 查看所有项目模板](../templates)** ### 方式二:现有项目集成 如果你已有项目,只需 3 步集成: ```bash # 1. 配置 MCP(具体配置见下方详细步骤) # 2. 下载 AI 规则 # 3. 开始使用 ``` 配置完成后,对 AI 说:**"登录云开发"** 即可开始! ## 🔧 详细配置指南 ### 步骤 1:安装 RooCode 从 [RooCode 官网](https://roocode.com/) 下载并安装 VS Code 插件。 ### 步骤 2:配置 CloudBase MCP > [!TIP] > 如果安装以后工具数量一直为 0,请参考[常见问题](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/faq#mcp-%E6%98%BE%E7%A4%BA%E5%B7%A5%E5%85%B7%E6%95%B0%E9%87%8F%E4%B8%BA-0-%E6%80%8E%E4%B9%88%E5%8A%9E) ```json { "mcpServers": { "cloudbase": { "command": "npx", "args": [ "npm-global-exec@latest", "@cloudbase/cloudbase-mcp@latest" ], "disabled": false, "env": { "INTEGRATION_IDE": "RooCode" } } } } ``` ### 步骤 3:启用 AI 规则 创建 `.roo/rules/cloudbase.md` 或对 AI 说: ``` 在当前项目中下载云开发 AI 规则 ``` 如果你只想下载RooCode相关的配置文件,避免项目文件混乱,可以指定IDE类型: ``` 在当前项目中下载云开发 AI 规则,只包含RooCode配置 ``` ### 步骤 4:开始开发 与 AI 对话: ``` 登录云开发 ``` ## 🎯 开始使用 配置完成后,对 AI 说: ``` 登录云开发 ``` 然后就可以开始开发了,例如: ``` 创建一个在线投票系统,支持创建投票、参与投票、结果统计,使用云数据库存储,最后部署 ``` RooCode 是轻量级的 AI 编程工具,简单易用。 ## 🌟 CloudBase AI Toolkit 开源项目 ### 🔥 加入开源社区 [![GitHub](https://img.shields.io/badge/GitHub-TencentCloudBase/CloudBase--AI--ToolKit-black?style=for-the-badge&logo=github)](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit) [![CNB社区](https://img.shields.io/badge/CNB-CloudBase--AI--ToolKit-orange?style=for-the-badge)](https://cnb.cool/tencent/cloud/cloudbase/CloudBase-AI-ToolKit) **⭐ Star 项目 | 🤝 贡献代码 | 💬 技术交流** ## 🛠️ 故障排除 ### 常见问题 **Q: MCP 连接失败?** A: 1. 检查 MCP 配置格式是否正确 2. 确认 npx 命令可用:`npx --version` 3. 重启 VS Code 和 RooCode 插件 4. 检查网络连接状态 **Q: AI 生成的代码不符合预期?** A: 1. 详细描述功能需求和技术要求 2. 使用项目模板确保规范一致性 3. 提供更详细的需求描述 更多问题请查看:[完整 FAQ](../faq) ## 📚 相关资源 - [📖 开发指南](../development) - 深入了解开发最佳实践 - [🎯 使用案例](../examples) - 查看实际应用案例 - [🔧 MCP 工具](../mcp-tools) - 了解所有可用工具 - [❓ 常见问题](../faq) - 查看常见问题解答 - [RooCode 官网](https://roocode.com/) - RooCode 官网 ## 💬 技术交流 ### 微信技术交流群 扫码加入微信技术交流群 --- **🚀 立即开始使用 RooCode + CloudBase AI Toolkit** [开始使用](../getting-started) | [查看模板](../templates) | [GitHub 仓库](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit) --- ## CloudBase AI Toolkit + 通义灵码 # CloudBase AI Toolkit + 通义灵码 **🚀 通义灵码 + 云开发 = 几分钟内从想法到上线的全栈应用** [![GitHub Stars](https://img.shields.io/github/stars/TencentCloudBase/CloudBase-AI-ToolKit?style=social)](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit) [![开源协议](https://img.shields.io/badge/License-MIT-blue.svg)](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/blob/main/LICENSE) > 💡 **为什么选择 通义灵码 + CloudBase AI Toolkit?** > 通义灵码是阿里巴巴推出的 AI 编程助手,支持智能代码生成和智能体功能。结合 CloudBase AI Toolkit,让你通过自然语言描述需求,AI 自动生成并部署全栈应用到腾讯云开发平台。特别适合中文开发者和需要本土化 AI 编程体验的团队。 ## ✨ 核心优势 | 🎯 **开发效率** | ⚡ **部署速度** | 🛡️ **稳定可靠** | |---|---|---| | AI 自动生成代码和架构内置云开发最佳实践规则智能错误修复和优化 | 一键部署到腾讯云开发国内 CDN 加速访问Serverless 架构免运维 | 330万开发者验证的平台企业级安全和稳定性完善的监控和日志系统 | ## 🚀 5分钟快速开始 ### 方式一:使用项目模板(推荐) 选择预配置的项目模板,开箱即用: **[📦 查看所有项目模板](../templates)** ### 方式二:现有项目集成 如果你已有项目,只需 3 步集成: ```bash # 1. 配置 MCP(具体配置见下方详细步骤) # 2. 下载 AI 规则 # 3. 开始使用 ``` 配置完成后,对 AI 说:**"登录云开发"** 即可开始! ## 🔧 详细配置指南 ### 步骤 1:安装通义灵码 从 [通义灵码官网](https://tongyi.aliyun.com/lingma) 下载并安装对应平台的插件。 ### 步骤 2:配置 CloudBase MCP > [!TIP] > 如果安装以后工具数量一直为 0,请参考[常见问题](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/faq#mcp-%E6%98%BE%E7%A4%BA%E5%B7%A5%E5%85%B7%E6%95%B0%E9%87%8F%E4%B8%BA-0-%E6%80%8E%E4%B9%88%E5%8A%9E) 在通义灵码的 MCP 配置中添加: ```json { "mcpServers": { "cloudbase": { "command": "npx", "args": ["npm-global-exec@latest", "@cloudbase/cloudbase-mcp@latest"], "env": { "INTEGRATION_IDE": "LingMa" } } } } ``` ### 步骤 3:启用 AI 规则 创建 `.lingma/cloudbase.md` 文件,或直接对 AI 说: ``` 在当前项目中下载云开发 AI 规则 ``` 如果你只想下载通义灵码相关的配置文件,避免项目文件混乱,可以指定IDE类型: ``` 在当前项目中下载云开发 AI 规则,只包含通义灵码配置 ``` ### 步骤 4:开始开发 在智能体模式下与 AI 对话: ``` 登录云开发 ``` ## 🎯 开始使用 配置完成后,对 AI 说: ``` 登录云开发 ``` 然后就可以开始开发了,例如: ``` 创建一个在线投票系统,支持创建投票、参与投票、结果统计,使用云数据库存储,最后部署 ``` 通义灵码支持中文优化,对中文开发者更加友好。 ## 🌟 CloudBase AI Toolkit 开源项目 ### 🔥 加入开源社区 [![GitHub](https://img.shields.io/badge/GitHub-TencentCloudBase/CloudBase--AI--ToolKit-black?style=for-the-badge&logo=github)](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit) [![CNB社区](https://img.shields.io/badge/CNB-CloudBase--AI--ToolKit-orange?style=for-the-badge)](https://cnb.cool/tencent/cloud/cloudbase/CloudBase-AI-ToolKit) **⭐ Star 项目 | 🤝 贡献代码 | 💬 技术交流** ## 🛠️ 故障排除 ### 常见问题 **Q: MCP 连接失败?** A: 1. 检查通义灵码 MCP 配置格式是否正确 2. 确认 npx 命令可用:`npx --version` 3. 重启通义灵码 4. 检查网络连接状态 **Q: AI 生成的代码不符合预期?** A: 1. 使用中文详细描述需求 2. 使用项目模板确保规范一致性 3. 提供更详细的技术要求 更多问题请查看:[完整 FAQ](../faq) ## 📚 相关资源 - [📖 开发指南](../development) - 深入了解开发最佳实践 - [🎯 使用案例](../examples) - 查看实际应用案例 - [🔧 MCP 工具](../mcp-tools) - 了解所有可用工具 - [❓ 常见问题](../faq) - 查看常见问题解答 - [通义灵码官网](https://tongyi.aliyun.com/lingma) - 通义灵码官网 ## 💬 技术交流 ### 微信技术交流群 扫码加入微信技术交流群 --- **🚀 立即开始使用 通义灵码 + CloudBase AI Toolkit** [开始使用](../getting-started) | [查看模板](../templates) | [GitHub 仓库](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit) --- ## CloudBase AI Toolkit + Trae # CloudBase AI Toolkit + Trae **🚀 Trae + 云开发 = 几分钟内从想法到上线的全栈应用** [![GitHub Stars](https://img.shields.io/github/stars/TencentCloudBase/CloudBase-AI-ToolKit?style=social)](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit) [![开源协议](https://img.shields.io/badge/License-MIT-blue.svg)](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/blob/main/LICENSE) > 💡 **为什么选择 Trae + CloudBase AI Toolkit?** > Trae 是一款新兴的 AI 原生开发环境,支持强大的 Builder with MCP 功能。结合 CloudBase AI Toolkit,让你通过自然语言描述需求,AI 自动生成并部署全栈应用到腾讯云开发平台。特别适合喜欢尝试新技术和追求极致 AI 开发体验的创新型开发者。 ## ✨ 核心优势 | 🎯 **开发效率** | ⚡ **部署速度** | 🛡️ **稳定可靠** | |---|---|---| | AI 自动生成代码和架构内置云开发最佳实践规则智能错误修复和优化 | 一键部署到腾讯云开发国内 CDN 加速访问Serverless 架构免运维 | 330万开发者验证的平台企业级安全和稳定性完善的监控和日志系统 | ## 🚀 5分钟快速开始 ### 方式一:使用项目模板(推荐) 选择预配置的项目模板,开箱即用: **[📦 查看所有项目模板](../templates)** ### 方式二:现有项目集成 如果你已有项目,只需 3 步集成: ```bash # 1. 配置 MCP(具体配置见下方详细步骤) # 2. 下载 AI 规则 # 3. 开始使用 ``` 配置完成后,对 AI 说:**"登录云开发"** 即可开始! ## 🔧 详细配置指南 ### 步骤 1:安装 Trae 从 [Trae 官网](https://www.trae.ai/) 下载并安装 Trae 开发环境。 ### 步骤 2:配置 CloudBase MCP > [!TIP] > 如果安装以后工具数量一直为 0,请参考[常见问题](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/faq#mcp-%E6%98%BE%E7%A4%BA%E5%B7%A5%E5%85%B7%E6%95%B0%E9%87%8F%E4%B8%BA-0-%E6%80%8E%E4%B9%88%E5%8A%9E) 在 Trae 的 MCP 配置中添加,Trae 的 [MCP 参考文档](https://docs.trae.ai/ide/model-context-protocol#93db5d1e): ```json { "mcpServers": { "cloudbase": { "command": "npx", "args": ["npm-global-exec@latest", "@cloudbase/cloudbase-mcp@latest"], "env": { "INTEGRATION_IDE": "Trae" } } } } ``` ### 步骤 3:启用 AI 规则 直接对 **Builder with MCP** 说: ``` 在当前项目中下载云开发 AI 规则 ``` 如果你只想下载Trae相关的配置文件,避免项目文件混乱,可以指定IDE类型: ``` 在当前项目中下载云开发 AI 规则,只包含Trae配置 ``` ### 步骤 4:开始开发 1. 在 Trae 的智能体选择中选择 **Builder with MCP** 2. 推荐使用 Claude/DeepSeek V3 或 GPT-4 模型 与 AI 对话: ``` 登录云开发 ``` ## 🎯 开始使用 配置完成后,对 AI 说: ``` 登录云开发 ``` 然后就可以开始开发了,例如: ``` 创建一个在线投票系统,支持创建投票、参与投票、结果统计,使用云数据库存储,最后部署 ``` Trae 的 Builder with MCP 模式支持智能架构设计和实时预览。 ## 🌟 CloudBase AI Toolkit 开源项目 ### 🔥 加入开源社区 [![GitHub](https://img.shields.io/badge/GitHub-TencentCloudBase/CloudBase--AI--ToolKit-black?style=for-the-badge&logo=github)](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit) [![CNB社区](https://img.shields.io/badge/CNB-CloudBase--AI--ToolKit-orange?style=for-the-badge)](https://cnb.cool/tencent/cloud/cloudbase/CloudBase-AI-ToolKit) **⭐ Star 项目 | 🤝 贡献代码 | 💬 技术交流** ## 🛠️ 故障排除 ### 常见问题 **Q: MCP 连接失败?** A: 1. 检查 Trae MCP 配置格式是否正确 2. 确认 npx 命令可用:`npx --version` 3. 重启 Trae 应用 4. 检查网络连接状态 **Q: AI 生成的代码不符合预期?** A: 1. 提供完整的功能需求和技术要求 2. 使用项目模板确保规范一致性 3. 分模块逐步实现大型项目 更多问题请查看:[完整 FAQ](../faq) ## 📚 相关资源 - [📖 开发指南](../development) - 深入了解开发最佳实践 - [🎯 使用案例](../examples) - 查看实际应用案例 - [🔧 MCP 工具](../mcp-tools) - 了解所有可用工具 - [❓ 常见问题](../faq) - 查看常见问题解答 - [Trae 官方网站](https://www.trae.ai/) - Trae 官方网站 ## 💬 技术交流 ### 微信技术交流群 扫码加入微信技术交流群 --- **🚀 立即开始使用 Trae + CloudBase AI Toolkit** [开始使用](../getting-started) | [查看模板](../templates) | [GitHub 仓库](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit) --- ## CloudBase AI Toolkit + WindSurf # CloudBase AI Toolkit + WindSurf **🚀 WindSurf + 云开发 = 几分钟内从想法到上线的全栈应用** [![GitHub Stars](https://img.shields.io/github/stars/TencentCloudBase/CloudBase-AI-ToolKit?style=social)](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit) [![开源协议](https://img.shields.io/badge/License-MIT-blue.svg)](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/blob/main/LICENSE) > 💡 **为什么选择 WindSurf + CloudBase AI Toolkit?** > WindSurf 是 Codeium 推出的 AI 原生编辑器,拥有强大的 Write 模式和 Cascade 多文件编辑功能。结合 CloudBase AI Toolkit,让你通过自然语言描述需求,AI 自动生成并部署全栈应用到腾讯云开发平台。特别适合需要多文件协同编辑的复杂项目开发。 ## ✨ 核心优势 | 🎯 **开发效率** | ⚡ **部署速度** | 🛡️ **稳定可靠** | |---|---|---| | AI 自动生成代码和架构内置云开发最佳实践规则智能错误修复和优化 | 一键部署到腾讯云开发国内 CDN 加速访问Serverless 架构免运维 | 330万开发者验证的平台企业级安全和稳定性完善的监控和日志系统 | ## 🚀 5分钟快速开始 ### 方式一:使用项目模板(推荐) 选择预配置的项目模板,开箱即用: **[📦 查看所有项目模板](../templates)** ### 方式二:现有项目集成 如果你已有项目,只需 3 步集成: ```bash # 1. 配置 MCP(具体配置见下方详细步骤) # 2. 下载 AI 规则 # 3. 开始使用 ``` 配置完成后,对 AI 说:**"登录云开发"** 即可开始! ## 🔧 详细配置指南 ### 步骤 1:安装 WindSurf 从 [WindSurf 官网](https://windsurf.com/editor) 下载并安装 WindSurf 编辑器。 ### 步骤 2:配置 CloudBase MCP > [!TIP] > 如果安装以后工具数量一直为 0,请参考[常见问题](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/faq#mcp-%E6%98%BE%E7%A4%BA%E5%B7%A5%E5%85%B7%E6%95%B0%E9%87%8F%E4%B8%BA-0-%E6%80%8E%E4%B9%88%E5%8A%9E) 在 WindSurf 的 Plugins 配置中添加: ```json { "mcpServers": { "cloudbase": { "command": "npx", "args": ["npm-global-exec@latest", "@cloudbase/cloudbase-mcp@latest"], "env": { "INTEGRATION_IDE": "WindSurf" } } } } ``` ### 步骤 3:启用 AI 规则 模板项目已包含 `.windsurf/` 目录。如果是现有项目,对 AI 说: ``` 在当前项目中下载云开发 AI 规则 ``` 如果你只想下载WindSurf相关的配置文件,避免项目文件混乱,可以指定IDE类型: ``` 在当前项目中下载云开发 AI 规则,只包含WindSurf配置 ``` ### 步骤 4:开始开发 在 Write 模式下与 AI 对话: ``` 登录云开发 ``` ## 🎯 开始使用 配置完成后,对 AI 说: ``` 登录云开发 ``` 然后就可以开始开发了,例如: ``` 创建一个在线投票系统,支持创建投票、参与投票、结果统计,使用云数据库存储,最后部署 ``` ## 🌟 CloudBase AI Toolkit 开源项目 ### 🔥 加入开源社区 [![GitHub](https://img.shields.io/badge/GitHub-TencentCloudBase/CloudBase--AI--ToolKit-black?style=for-the-badge&logo=github)](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit) [![CNB社区](https://img.shields.io/badge/CNB-CloudBase--AI--ToolKit-orange?style=for-the-badge)](https://cnb.cool/tencent/cloud/cloudbase/CloudBase-AI-ToolKit) **⭐ Star 项目 | 🤝 贡献代码 | 💬 技术交流** ## 🛠️ 故障排除 ### 常见问题 **Q: MCP 连接失败?** A: 1. 检查 Plugins 配置格式是否正确 2. 重启 WindSurf 3. 确认网络连接正常 **Q: AI 生成的代码不符合预期?** A: 1. 明确描述技术栈和框架要求 2. 使用项目模板确保规范一致性 3. 提供更详细的需求描述 更多问题请查看:[完整 FAQ](../faq) ## 📚 相关资源 - [📖 开发指南](../development) - 深入了解开发最佳实践 - [🎯 使用案例](../examples) - 查看实际应用案例 - [🔧 MCP 工具](../mcp-tools) - 了解所有可用工具 - [❓ 常见问题](../faq) - 查看常见问题解答 ## 💬 技术交流 ### 微信技术交流群 扫码加入微信技术交流群 --- **🚀 立即开始使用 WindSurf + CloudBase AI Toolkit** [开始使用](../getting-started) | [查看模板](../templates) | [GitHub 仓库](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit) --- ## CloudBase AI ToolKit 概述 # CloudBase AI ToolKit 概述 ![CloudBase AI ToolKit](http://static.cloudbase.net/imgs/toolkit-better.gif) ** 🪐 用 AI IDE 一键生成、部署和托管你的全栈 Web 应用与小程序、数据库和后端服务,无需运维,极速上线你的创意 💫** [![GitHub Stars](https://img.shields.io/github/stars/TencentCloudBase/CloudBase-AI-ToolKit?style=social)](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit) [![CNB Community](https://img.shields.io/badge/CNB-开源社区-blue?style=flat-square)](https://cnb.cool/tencent/cloud/cloudbase/CloudBase-AI-ToolKit) 当你在**Cursor/ VSCode GitHub Copilot/WinSurf/CodeBuddy/Augment Code/Claude Code/OpenAI Codex CLI/OpenCode**等AI编程工具里写代码时,它能自动帮你生成可直接部署的前后端应用+小程序,并一键发布到腾讯云开发 CloudBase。 :::tip 🌟 开源项目 - **GitHub 仓库**: [TencentCloudBase/CloudBase-AI-ToolKit](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit) - 欢迎 Star 和贡献代码 - **CNB 社区**: [CloudBase-AI-ToolKit](https://cnb.cool/tencent/cloud/cloudbase/CloudBase-AI-ToolKit) - 中国开发者社区 ::: **📹 完整视频演示 ⬇️** | 🚀 **核心能力** | 🛠️ **支持平台** | |---|---| | 🤖 **AI智能开发**: AI自动生成代码和架构设计☁️ **云开发集成**: 一键接入数据库、云函数、静态托管⚡ **快速部署**: 几分钟内完成全栈应用上线 | **Web应用**: 现代化前端 + 静态托管**微信小程序**: 云开发小程序解决方案**后端服务**: 云数据库 + 无服务器函数+云托管 | ## ✨ 核心特性 - **🤖 AI 原生** - 专为 AI 编程工具设计的规则库,生成代码符合云开发最佳实践 - **🚀 一键部署** - MCP 自动化部署到腾讯云开发 CloudBase 平台,Serverless 架构无需购买服务器 - **📱 全栈应用** - Web + 小程序 + 数据库 + 后端一体化,支持多种应用形式和后端托管 - **🔧 智能修复** - AI 自动查看日志并修复问题,降低运维成本 - **⚡ 极速体验** - 国内 CDN 加速,比海外平台访问速度更快 - **📚 知识检索** - 内置云开发、微信小程序等专业知识库的智能向量检索 --- 🚩 **快速上手 CloudBase AI ToolKit** ## 🚀 推荐方式:CloudBase AI CLI(最简单) ![](http://static.cloudbase.net/imgs/cli-better.gif) CloudBase AI CLI 是一个集成多种主流 AI 编程工具的统一命令行工具,支持内置模型和自定义模型,让你能够通过一个简单的命令使用 Claude Code、OpenAI Codex、aider、Qwen Code 等 AI 编程助手,同时内置 CloudBase AI Toolkit,支持从开发到部署的完整流程,支持在任意环境中运行。 **核心优势:** - 🏗️ **统一管理** - 一个命令管理多种 AI 编程 CLI 工具,无需在多个工具间切换 - 🤖 **多模型支持** - 支持内置和自定义各种大模型,包括 Kimi K2、智谱 GLM-4.5 等 - 🚀 **一键开发部署** - 从代码生成到云端部署的完整流程,支持 Web 应用、小程序、后端服务 - 🌍 **无处不在** - 可在任意环境中运行,包括小程序开发者工具、VS Code、GitHub Actions 等 **一键安装** ```bash # Mac/Linux/Windows 的 WSL curl https://static.cloudbase.net/cli/install/install.sh -fsS | bash # Windows PowerShell irm https://static.cloudbase.net/cli/install/install.ps1 | iex ``` **开始使用** ```bash tcb ai ``` 首次启动,配置向导会引导你完成 AI 工具选择和配置。完成配置后即可开始使用 AI 工具进行辅助开发,后续可以运行 `tcb ai --setup` 来切换工具和模型。 👉 [查看完整使用文档](https://docs.cloudbase.net/cli-v1/ai/introduce) | [立即体验](https://docs.cloudbase.net/cli-v1/ai/introduce) | [全栈小程序开发详细案例教程](https://docs.cloudbase.net/practices/ai-cli-mini-program) ## 🛠️ 其他 IDE 配置方式 如果你使用其他 AI IDE,请参考下面的配置指南: --- ## 💻 支持的 AI 开发工具 | 工具 | 支持平台 | 查看指引 | |------|----------|----------| | [CloudBase AI CLI](https://docs.cloudbase.net/cli-v1/ai/introduce) | 命令行工具 | [查看指引](https://docs.cloudbase.net/cli-v1/ai/introduce) | | [Cursor](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/cursor) | 独立 IDE| [查看指引](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/cursor) | | [WindSurf](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/windsurf) | 独立 IDE, VSCode、JetBrains 插件 | [查看指引](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/windsurf) | | [CodeBuddy](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/codebuddy) | VS Code、JetBrains、微信开发者工具、独立 IDE(推荐,已内置 CloudBase AI Toolkit) | [查看指引](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/codebuddy) | | [CLINE](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/cline) | VS Code 插件 | [查看指引](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/cline) | | [GitHub Copilot](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/github-copilot) | VS Code 插件 | [查看指引](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/github-copilot) | | [Trae](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/trae) | 独立 IDE | [查看指引](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/trae) | | [通义灵码](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/tongyi-lingma) | 独立 IDE,VS Code、 JetBrains插件 | [查看指引](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/tongyi-lingma) | | [RooCode](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/roocode) | VS Code插件 | [查看指引](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/roocode) | | [文心快码](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/baidu-comate) | VS Code、JetBrains插件| [查看指引](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/baidu-comate) | | [Augment Code](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/augment-code) | VS Code、JetBrains 插件 | [查看指引](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/augment-code) | | [Claude Code](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/claude-code) | 命令行工具 | [查看指引](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/claude-code) | | [Gemini CLI](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/gemini-cli) | 命令行工具 | [查看指引](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/gemini-cli) | | [OpenAI Codex CLI](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/openai-codex-cli) | 命令行工具 | [查看指引](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/openai-codex-cli) | | [OpenCode](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/opencode) | 命令行工具 | [查看指引](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/opencode) | | [Qwen Code](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/qwen-code) | 命令行工具 | [查看指引](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/ide-setup/qwen-code) | ## 🎯 快速导航 - [快速开始](./getting-started) - 几分钟内上手使用 - [IDE配置](./ide-setup/cursor) - 配置你的AI开发工具 - [项目模板](./templates) - 选择合适的项目模板 - [开发指南](./development) - 深入了解开发最佳实践 - [使用案例](./examples) - 查看实际应用案例 - [教程](./tutorials) - 编程实战、AI Coding组合、应用项目和视频教程 - [插件系统](./plugins) - 按需启用工具模块 - [MCP工具](./mcp-tools) - 了解所有可用工具 - [MCP上架材料](./mcp-listing-materials.md) - 第三方市场上架材料(英文) - [MCP上架材料](./mcp-listing-materials-zh.md) - 第三方市场上架材料(中文) - [常见问题](./troubleshooting) - 解决开发中的问题 - [FAQ](./faq) - 查看常见问题解答 ## ☁️ 云开发平台架构 ```mermaid graph TB subgraph "前端应用" A[Web 应用] B[微信小程序] C[移动应用] end D[SDK] subgraph "云开发平台" E[云函数] F[云数据库] G[云存储] H[用户认证] I[权限控制] end A --> D B --> D C --> D D --> E D --> F D --> G D --> H D --> I style A fill:#e1f5fe style B fill:#e8f5e8 style C fill:#fff3e0 style D fill:#f5f5f5 style E fill:#e8eaf6 style F fill:#e8eaf6 style G fill:#e8eaf6 style H fill:#ffebee style I fill:#ffebee ``` ## 🏗️ AI + 云开发工作流 ```mermaid graph TD A[开发者] --> B[AI IDE] B -->|使用| C[CloudBase AI 规则] C --> D[生成代码] B -->|调用| E[CloudBase MCP] E --> F{检测部署} F -->|成功| G[云开发平台] F -->|失败| H[返回日志] H --> I[AI 修复] I --> E G --> J[线上应用] J --> K[Web/小程序/API] ``` ## 🌟 为什么选择 CloudBase? - **⚡ 极速部署**:国内节点,访问速度比海外更快 - **🛡️ 稳定可靠**:330 万开发者选择的 Serverless 平台 - **🔧 开发友好**:专为AI时代设计的全栈平台,支持自动环境配置 - **💰 成本优化**:Serverless 架构更具弹性,新用户开发期间可以免费体验 如有迁移、集成等常见疑问,请查阅 [FAQ 常见问题](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/faq)。 ## 💬 技术交流群 遇到问题或想要交流经验?加入我们的技术社区! ### 🔥 微信交流群 扫码加入微信技术交流群 --- ## 邀请码激活流程 import templates from "./templates.png" import mcp from "./mcp.png" import askai from "./askai.png" # 邀请码激活流程 本文将介绍如何使用 CloudBase AI CLI 启动 Claude Code,以激活云开发 AI ToolKit 编程激励计划邀请码。 无需 API Key,使用云开发环境内置大模型即可驱动 Claude Code。 [云开发 AI ToolKit 编程激励计划](https://tcb.cloud.tencent.com/activity/ai-toolkit) ## 环境准备和安装 请参考 [CloudBase CLI 安装文档](../../cli-v1/install.md) 完成环境准备和 CLI 的安装,包括: - Node.js 环境安装(版本 >= 18) - CloudBase CLI 安装(支持快速安装脚本和 npm 安装) **额外准备:** 访问 [腾讯云开发控制台](https://tcb.cloud.tencent.com/dev) 开通环境,新用户可以免费开通体验。 ## 运行 CloudBase AI CLI 使用终端运行 CloudBase AI CLI: ```shell tcb ai ``` :::tip 若您之前使用过 CloudBase AI CLI 进行配置,此时会直接进入运行流程,无需重复配置。运行 `tcb ai --setup` 可重新配置。 ::: 根据终端提示,配置 AI 工具: 1. 选择配置 `Claude Code` AI CLI 工具 2. 选择 `使用 CloudBase 服务` 3. 选择大模型:`Kimi` -> `Kimi-K2-Instruct-Online-128K` 配置完成后,会在此目录下载 CloudBase AI ToolKit 模板,请根据您想构建的应用类型进行选择。 下载完成后,Claude Code 将被启动。若提示是否要启用项目中附带的 cloudbase MCP Server,请选择启用。 接下来就可以输入 prompt 指挥 AI 帮我们登录云开发环境,并且激活邀请码了: ```plaintext 帮我登录云开发,并且激活邀请码 {输入您的邀请码} ``` 激活后可继续开发,向 Claude Code 输入需求即可体验 AI 辅助编程。 - [更多 CloudBase AI ToolKit 介绍](./) - [CloudBase AI CLI 介绍](../../cli-v1/ai/introduce) ## 活动细则 ### 激活前注意事项 :::tip 注意 - 请确认腾讯云账号是否欠费,欠费会导致激活邀请码代金券奖励发放失败 - 以下腾讯云账号类型无法获取代金券奖励: - 国外账号 - 内测账号 - 代理商、大客户、代客 ::: 如果在活动页面查看奖励时遇到下面提示,表示奖励领取失败: ![奖励领取失败提示](https://qcloudimg.tencent-cloud.cn/raw/72b1857ef95dee6613f21f34adcc86dd.png) ### 邀请码激活奖励说明 活动奖励根据当前环境套餐类型进行不同奖励发放: - **个人付费版:免费续期一个月** - 发放至生成邀请码时选择的云开发环境 - **个人免费版:19 元代金券** - 发放至腾讯云主账户 ### 如何开通免费云开发环境 1. 前往云开发平台,使用腾讯云账号登录,然后新建环境 ![新建环境](https://qcloudimg.tencent-cloud.cn/raw/195a8437ce965057a4b7b02d904e549a.png) 2. 开通环境之前需要腾讯云账号先进行实名注册 ![实名注册](https://qcloudimg.tencent-cloud.cn/raw/929b4da3f35a6822fbb6d459fc8fc91a.png) 3. 首次开通,可以选择个人免费版套餐(试用 6 个月) ![个人免费版套餐](https://qcloudimg.tencent-cloud.cn/raw/3d385ca1807d5686bf3d7e315b643c08.png) :::info 说明 - 免费环境在开发阶段无需开发者续费,若在开发期发布过小程序,则环境的到期时间变更为 15 天,免费环境将转为付费环境,在下一续费周期生效。 - 云开发个人免费环境使用说明可以参考[具体细则](https://cloud.tencent.com/document/product/876/75213) ::: ### 查看活动奖励 1. 前往活动页,查看奖励发放情况 ![奖励发放情况](https://qcloudimg.tencent-cloud.cn/raw/0d4396fe05e50a5928ab0e7e5f5aa1f0.png) 2. 根据奖励发放类型不同,可以前往腾讯云控制台进行明细查看 - 代金券 ![代金券查看](https://qcloudimg.tencent-cloud.cn/raw/bb45d245fb500121ab0c4ced4d67231f.png) - 个人版套餐续期 ![套餐续期查看](https://qcloudimg.tencent-cloud.cn/raw/34dcd6f66681886e2a8242962a5a96f8.png) --- ## CloudBase MCP - 上架材料 # CloudBase MCP - 上架材料 > 用于在第三方目录中上架 CloudBase MCP 的材料 ## 基本信息 - **名称**: CloudBase AI ToolKit - **描述**: 为微信小程序和全栈应用提供一站式后端服务 - **分类**: 云开发与部署 - **提供商**: Tencent CloudBase ## 图标 ## 链接 - **主页**: https://github.com/TencentCloudBase/CloudBase-AI-ToolKit - **NPM**: https://www.npmjs.com/package/@cloudbase/cloudbase-mcp - **文档**: https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/blob/main/README.md - **许可证**: MIT ## 安装 ### MCP 配置 ```json { "mcpServers": { "cloudbase-mcp": { "command": "npx", "args": ["npm-global-exec@latest", "@cloudbase/cloudbase-mcp@latest"] } } } ``` ## 核心功能 - 微信小程序开发和部署 - 无服务器云函数和数据库 - 一键部署到生产环境 - 微信生态系统的中国市场准入 - 内置云开发知识库 - 34个专业MCP工具 ## 标签 ``` cloudbase, tencent-cloud, wechat, mini-programs, serverless, deployment, china, full-stack ``` ## 技术规格 - **Node.js**: 18+ - **平台**: 跨平台 - **工具数量**: 34个 - **传输方式**: stdio, http, sse - **身份验证**: 需要环境ID ## 项目亮点 ### 为什么选择CloudBase AI ToolKit - 接入中国最大的移动平台(微信) - 完整的无服务器后端,无需基础设施管理 - 为现代开发工作流程设计的AI原生工具 - 腾讯云官方支持和可靠性保障 ## 联系方式 - **GitHub Issues**: https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/issues - **提供商**: Tencent CloudBase 团队 --- ## CloudBase MCP - Listing Materials # CloudBase MCP - Listing Materials > Materials for listing CloudBase MCP in third-party directories ## Basic Information - **Name**: CloudBase AI ToolKit - **Package**: `@cloudbase/cloudbase-mcp` - **Description**: One-stop backend services for WeChat Mini-Programs and full-stack apps - **Category**: Cloud Development & Deployment - **Provider**: Tencent CloudBase ## Logo ## Links - **Homepage**: https://github.com/TencentCloudBase/CloudBase-AI-ToolKit - **NPM**: https://www.npmjs.com/package/@cloudbase/cloudbase-mcp - **Documentation**: https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/blob/main/README.md - **License**: MIT ## Installation ### MCP Configuration ```json { "mcpServers": { "cloudbase-mcp": { "command": "npx", "args": ["npm-global-exec@latest", "@cloudbase/cloudbase-mcp@latest"] } } } ``` ## Key Features - WeChat Mini-Program development and deployment - Serverless cloud functions and databases - One-click deployment to production - China market access with WeChat ecosystem - Built-in cloud development knowledge base - 34 specialized MCP tools ## Tags ``` cloudbase, tencent-cloud, wechat, mini-programs, serverless, deployment, china, full-stack ``` ## Technical Specs - **Node.js**: 18+ - **Platform**: Cross-platform - **Tools Count**: 34 - **Transport**: stdio, http, sse - **Authentication**: Environment ID required ## Project Highlights ### Why Choose CloudBase AI ToolKit - Access to China's largest mobile platform (WeChat) - Complete serverless backend without infrastructure management - AI-native tools designed for modern development workflows - Official Tencent Cloud support and reliability ## Contact - **GitHub Issues**: https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/issues - **Provider**: Tencent CloudBase Team --- ## MCP 工具 # MCP 工具 当前包含 39 个工具。 源数据: [tools.json](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/blob/main/scripts/tools.json) --- ## 工具总览 名称描述 login登录云开发环境并选择要使用的环境 logout退出云开发环境 envQuery查询云开发环境相关信息,支持查询环境列表、当前环境信息、安全域名和静态网站托管配置。(原工具名:listEnvs/getEnvInfo/getEnvAuthDomains/getWebsiteConfig,为兼容旧AI规则可继续使用这些名称) envDomainManagement管理云开发环境的安全域名,支持添加和删除操作。(原工具名:createEnvDomain/deleteEnvDomain,为兼容旧AI规则可继续使用这些名称) createCollection管理云开发数据库集合:默认创建。可通过 action 指定 update。 collectionQuery数据库集合的查询操作,支持检查存在性、查看详情、列表查询;并支持索引列表与检查。(兼容旧名称) updateCollection更新云开发数据库集合配置(创建或删除索引) checkIndexExists检查索引是否存在 insertDocuments向云开发数据库集合中插入一个或多个文档(支持对象数组) queryDocuments查询云开发数据库集合中的文档(支持对象参数) updateDocuments更新云开发数据库集合中的文档(支持对象参数) deleteDocuments删除云开发数据库集合中的文档(支持对象参数) manageDataModel数据模型查询工具,支持查询和列表数据模型(只读操作)。list操作返回基础信息(不含Schema),get操作返回详细信息(含简化的Schema,包括字段列表、格式、关联关系等),docs操作生成SDK使用文档 modifyDataModel基于Mermaid classDiagram创建或更新数据模型。支持创建新模型和更新现有模型结构。内置异步任务监控,自动轮询直至完成或超时。 getFunctionList获取云函数列表或单个函数详情,通过 action 参数区分操作类型 createFunction创建云函数 updateFunctionCode更新函数代码 updateFunctionConfig更新云函数配置 invokeFunction调用云函数 getFunctionLogs获取云函数日志基础信息(LogList),如需日志详情请用 RequestId 调用 getFunctionLogDetail 工具。此接口基于 manger-node 4.4.0+ 的 getFunctionLogsV2 实现,不返回具体日志内容。参数 offset+limit 不得大于 10000,startTime/endTime 间隔不得超过一天。 getFunctionLogDetail根据 getFunctionLogs 返回的 RequestId 查询日志详情。参数 startTime、endTime、requestId,返回日志内容(LogJson 等)。仅支持 manger-node 4.4.0+。 manageFunctionTriggers创建或删除云函数触发器,通过 action 参数区分操作类型 uploadFiles上传文件到静态网站托管 deleteFiles删除静态网站托管的文件或文件夹 findFiles搜索静态网站托管的文件 domainManagement统一的域名管理工具,支持绑定、解绑、查询和修改域名配置 queryStorage查询云存储信息,支持列出目录文件、获取文件信息、获取临时下载链接等只读操作。返回的文件信息包括文件名、大小、修改时间、下载链接等。 manageStorage管理云存储文件,支持上传文件/目录、下载文件/目录、删除文件/目录等操作。删除操作需要设置force=true进行确认,防止误删除重要文件。 downloadTemplate自动下载并部署CloudBase项目模板。<br/>支持的模板:<br/>- react: React + CloudBase 全栈应用模板<br/>- vue: Vue + CloudBase 全栈应用模板<br/>- miniprogram: 微信小程序 + 云开发模板 <br/>- uniapp: UniApp + CloudBase 跨端应用模板<br/>- rules: 只包含AI编辑器配置文件(包含Cursor、WindSurf、CodeBuddy等所有主流编辑器配置),适合在已有项目中补充AI编辑器配置<br/>支持的IDE类型:<br/>- all: 下载所有IDE配置(默认)<br/>- cursor: Cursor AI编辑器<br/>- windsurf: WindSurf AI编辑器<br/>- codebuddy: CodeBuddy AI编辑器<br/>- claude-code: Claude Code AI编辑器<br/>- cline: Cline AI编辑器<br/>- gemini-cli: Gemini CLI<br/>- opencode: OpenCode AI编辑器<br/>- qwen-code: 通义灵码<br/>- baidu-comate: 百度Comate<br/>- openai-codex-cli: OpenAI Codex CLI<br/>- augment-code: Augment Code<br/>- github-copilot: GitHub Copilot<br/>- roocode: RooCode AI编辑器<br/>- tongyi-lingma: 通义灵码<br/>- trae: Trae AI编辑器<br/>- vscode: Visual Studio Code<br/>特别说明:<br/>- rules 模板会自动包含当前 mcp 版本号信息(版本号:1.8.41),便于后续维护和版本追踪<br/>- 下载 rules 模板时,如果项目中已存在 README.md 文件,系统会自动保护该文件不被覆盖(除非设置 overwrite=true) interactiveDialog统一的交互式对话工具,支持需求澄清和任务确认,当需要和用户确认下一步的操作的时候,可以调用这个工具的clarify,如果有敏感的操作,需要用户确认,可以调用这个工具的confirm searchWeb使用联网来进行信息检索,如查询最新的新闻、文章、股价、天气等。支持自然语言查询,也可以直接输入网址获取网页内容 searchKnowledgeBase云开发知识库智能检索工具,支持云开发与云函数知识的向量查询 queryCloudRun查询云托管服务信息,支持获取服务列表、查询服务详情和获取可用模板列表。返回的服务信息包括服务名称、状态、访问类型、配置详情等。 manageCloudRun管理云托管服务,按开发顺序支持:初始化项目(可从模板开始,模板列表可通过 queryCloudRun 查询)、下载服务代码、本地运行(仅函数型服务)、部署代码、删除服务。部署可配置CPU、内存、实例数、访问类型等参数。删除操作需要确认,建议设置force=true。 createFunctionHTTPAccess创建云函数的 HTTP 访问 downloadRemoteFile下载远程文件到项目根目录下的指定相对路径。例如:小程序的 Tabbar 等素材图片,必须使用 **png** 格式,可以从 Unsplash、wikimedia【一般选用 500 大小即可、Pexels、Apple 官方 UI 等资源中选择来下载。 readSecurityRule读取指定资源(数据库集合、云函数、存储桶)的安全规则和权限类别。<br/>参数说明:<br/>- resourceType: 资源类型(database/function/storage)<br/>- resourceId: 资源唯一标识(集合名/函数名/桶名) writeSecurityRule设置指定资源(数据库集合、云函数、存储桶)的安全规则。<br/>参数说明:<br/>- resourceType: 资源类型(database/function/storage)<br/>- resourceId: 资源唯一标识(集合名/函数名/桶名)<br/>- aclTag: 权限类别(READONLY/PRIVATE/ADMINWRITE/ADMINONLY/CUSTOM)<br/>- rule: 自定义安全规则内容,仅当 aclTag 为 CUSTOM 时必填 activateInviteCode云开发 AI编程激励计划,通过邀请码激活用户激励。 --- ## 详细规格 ### `login` 登录云开发环境并选择要使用的环境 #### 参数 参数名类型必填说明 forceUpdateboolean是否强制重新选择环境 --- ### `logout` 退出云开发环境 #### 参数 参数名类型必填说明 confirmstring是确认操作,默认传 yes 可填写的值: const "yes" --- ### `envQuery` 查询云开发环境相关信息,支持查询环境列表、当前环境信息、安全域名和静态网站托管配置。(原工具名:listEnvs/getEnvInfo/getEnvAuthDomains/getWebsiteConfig,为兼容旧AI规则可继续使用这些名称) #### 参数 参数名类型必填说明 actionstring是查询类型:list=环境列表,info=当前环境信息,domains=安全域名列表,hosting=静态网站托管配置 可填写的值: "list", "info", "domains", "hosting" --- ### `envDomainManagement` 管理云开发环境的安全域名,支持添加和删除操作。(原工具名:createEnvDomain/deleteEnvDomain,为兼容旧AI规则可继续使用这些名称) #### 参数 参数名类型必填说明 actionstring是操作类型:create=添加域名,delete=删除域名 可填写的值: "create", "delete" domainsarray of string是安全域名数组 --- ### `createCollection` 管理云开发数据库集合:默认创建。可通过 action 指定 update。 #### 参数 参数名类型必填说明 actionstring操作类型:create=创建(默认),update=更新集合配置 可填写的值: "create", "update" collectionNamestring是云开发数据库集合名称 optionsobject更新选项(action=update 时使用) options.CreateIndexesarray of object options.CreateIndexes[].IndexNamestring是 options.CreateIndexes[].MgoKeySchemaobject是 options.CreateIndexes[].MgoKeySchema.MgoIsUniqueboolean是 options.CreateIndexes[].MgoKeySchema.MgoIndexKeysarray of object是 options.CreateIndexes[].MgoKeySchema.MgoIndexKeys[].Namestring是 options.CreateIndexes[].MgoKeySchema.MgoIndexKeys[].Directionstring是 options.DropIndexesarray of object options.DropIndexes[].IndexNamestring是 --- ### `collectionQuery` 数据库集合的查询操作,支持检查存在性、查看详情、列表查询;并支持索引列表与检查。(兼容旧名称) #### 参数 参数名类型必填说明 actionstring是操作类型:check=检查是否存在,describe=查看详情,list=列表查询,index_list=索引列表,index_check=检查索引是否存在 可填写的值: "check", "describe", "list", "index_list", "index_check" collectionNamestring集合名称(check、describe、index_list、index_check 操作时必填) indexNamestring索引名称(index_check 操作时必填) limitnumber返回数量限制(list操作时可选) offsetnumber偏移量(list操作时可选) --- ### `updateCollection` 更新云开发数据库集合配置(创建或删除索引) #### 参数 参数名类型必填说明 collectionNamestring是云开发数据库集合名称 optionsobject是更新选项,支持创建和删除索引 options.CreateIndexesarray of object options.CreateIndexes[].IndexNamestring是 options.CreateIndexes[].MgoKeySchemaobject是 options.CreateIndexes[].MgoKeySchema.MgoIsUniqueboolean是 options.CreateIndexes[].MgoKeySchema.MgoIndexKeysarray of object是 options.CreateIndexes[].MgoKeySchema.MgoIndexKeys[].Namestring是 options.CreateIndexes[].MgoKeySchema.MgoIndexKeys[].Directionstring是 options.DropIndexesarray of object options.DropIndexes[].IndexNamestring是 --- ### `checkIndexExists` 检查索引是否存在 #### 参数 参数名类型必填说明 collectionNamestring是云开发数据库集合名称 indexNamestring是索引名称 --- ### `insertDocuments` 向云开发数据库集合中插入一个或多个文档(支持对象数组) #### 参数 参数名类型必填说明 collectionNamestring是云开发数据库集合名称 documentsarray of object是要插入的文档对象数组,每个文档都是对象 --- ### `queryDocuments` 查询云开发数据库集合中的文档(支持对象参数) #### 参数 参数名类型必填说明 collectionNamestring是云开发数据库集合名称 queryobject \| string查询条件(对象或字符串,推荐对象) projectionobject \| string返回字段投影(对象或字符串,推荐对象) sortobject \| string排序条件(对象或字符串,推荐对象) limitnumber返回数量限制 offsetnumber跳过的记录数 --- ### `updateDocuments` 更新云开发数据库集合中的文档(支持对象参数) #### 参数 参数名类型必填说明 collectionNamestring是云开发数据库集合名称 queryobject \| string是查询条件(对象或字符串,推荐对象) updateobject \| string是更新内容(对象或字符串,推荐对象) isMultiboolean是否更新多条记录 upsertboolean是否在不存在时插入 --- ### `deleteDocuments` 删除云开发数据库集合中的文档(支持对象参数) #### 参数 参数名类型必填说明 collectionNamestring是云开发数据库集合名称 queryobject \| string是查询条件(对象或字符串,推荐对象) isMultiboolean是否删除多条记录 --- ### `manageDataModel` 数据模型查询工具,支持查询和列表数据模型(只读操作)。list操作返回基础信息(不含Schema),get操作返回详细信息(含简化的Schema,包括字段列表、格式、关联关系等),docs操作生成SDK使用文档 #### 参数 参数名类型必填说明 actionstring是操作类型:get=查询单个模型(含Schema字段列表、格式、关联关系),list=获取模型列表(不含Schema),docs=生成SDK使用文档 可填写的值: "get", "list", "docs" namestring模型名称(get操作时必填) namesarray of string模型名称数组(list操作时可选,用于过滤) --- ### `modifyDataModel` 基于Mermaid classDiagram创建或更新数据模型。支持创建新模型和更新现有模型结构。内置异步任务监控,自动轮询直至完成或超时。 #### 参数 参数名类型必填说明 mermaidDiagramstring是Mermaid classDiagram代码,描述数据模型结构。 actionstring操作类型:create=创建新模型 可填写的值: "create", "update";默认值: "create" publishboolean是否立即发布模型 默认值: false dbInstanceTypestring数据库实例类型 默认值: "MYSQL" 示例 ```text classDiagram class Student { name: string > age: number = 18 > gender: x-enum = "男" > classId: string > identityId: string > course: Course[] > required() ["name"] unique() ["name"] enum_gender() ["男", "女"] display_field() "name" } class Class { className: string > display_field() "className" } class Course { name: string > students: Student[] > display_field() "name" } class Identity { number: string > display_field() "number" } %% 关联关系 Student "1" --> "1" Identity : studentId Student "n" --> "1" Class : student2class Student "n" --> "m" Course : course Student "n" --- ### `getFunctionList` 获取云函数列表或单个函数详情,通过 action 参数区分操作类型 #### 参数 参数名类型必填说明 actionstring操作类型:list=获取函数列表(默认),detail=获取函数详情 可填写的值: "list", "detail" limitnumber范围(list 操作时使用) offsetnumber偏移(list 操作时使用) namestring函数名称(detail 操作时必需) codeSecretstring代码保护密钥(detail 操作时使用) --- ### `createFunction` 创建云函数 #### 参数 参数名类型必填说明 funcobject是函数配置 func.namestring是函数名称 func.timeoutnumber函数超时时间 func.envVariablesobject环境变量 func.vpcobject私有网络配置 func.vpc.vpcIdstring是 func.vpc.subnetIdstring是 func.runtimestring运行时环境,建议指定为 'Nodejs18.15',其他可选值:Nodejs18.15,Nodejs16.13,Nodejs14.18,Nodejs12.16,Nodejs10.15,Nodejs8.9 func.triggersarray of objectTrigger configuration array func.triggers[].namestring是Trigger name func.triggers[].typestring是Trigger type, currently only supports 'timer' 可填写的值: "timer" func.triggers[].configstring是Trigger configuration. For timer triggers, use cron expression format: second minute hour day month week year. IMPORTANT: Must include exactly 7 fields (second minute hour day month week year). Examples: '0 0 2 1 * * *' (monthly), '0 30 9 * * * *' (daily at 9:30 AM) func.handlerstring函数入口 func.ignorestring \| array of string忽略文件 func.isWaitInstallboolean是否等待依赖安装 func.layersarray of objectLayer配置 func.layers[].namestring是 func.layers[].versionnumber是 functionRootPathstring函数根目录(云函数目录的父目录),这里需要传操作系统上文件的绝对路径,注意:不要包含函数名本身,例如函数名为 'hello',应传入 '/path/to/cloudfunctions',而不是 '/path/to/cloudfunctions/hello' forceboolean是是否覆盖 --- ### `updateFunctionCode` 更新函数代码 #### 参数 参数名类型必填说明 namestring是函数名称 functionRootPathstring是函数根目录(云函数目录的父目录),这里需要传操作系统上文件的绝对路径 --- ### `updateFunctionConfig` 更新云函数配置 #### 参数 参数名类型必填说明 funcParamobject是函数配置 funcParam.namestring是函数名称 funcParam.timeoutnumber超时时间 funcParam.envVariablesobject环境变量 funcParam.vpcobjectVPC配置 funcParam.vpc.vpcIdstring是 funcParam.vpc.subnetIdstring是 --- ### `invokeFunction` 调用云函数 #### 参数 参数名类型必填说明 namestring是函数名称 paramsobject调用参数 --- ### `getFunctionLogs` 获取云函数日志基础信息(LogList),如需日志详情请用 RequestId 调用 getFunctionLogDetail 工具。此接口基于 manger-node 4.4.0+ 的 getFunctionLogsV2 实现,不返回具体日志内容。参数 offset+limit 不得大于 10000,startTime/endTime 间隔不得超过一天。 #### 参数 参数名类型必填说明 namestring是函数名称 offsetnumber数据的偏移量,Offset+Limit 不能大于 10000 limitnumber返回数据的长度,Offset+Limit 不能大于 10000 startTimestring查询的具体日期,例如:2017-05-16 20:00:00,只能与 EndTime 相差一天之内 endTimestring查询的具体日期,例如:2017-05-16 20:59:59,只能与 StartTime 相差一天之内 requestIdstring执行该函数对应的 requestId qualifierstring函数版本,默认为 $LATEST --- ### `getFunctionLogDetail` 根据 getFunctionLogs 返回的 RequestId 查询日志详情。参数 startTime、endTime、requestId,返回日志内容(LogJson 等)。仅支持 manger-node 4.4.0+。 #### 参数 参数名类型必填说明 startTimestring查询的具体日期,例如:2017-05-16 20:00:00,只能与 EndTime 相差一天之内 endTimestring查询的具体日期,例如:2017-05-16 20:59:59,只能与 StartTime 相差一天之内 requestIdstring是执行该函数对应的 requestId --- ### `manageFunctionTriggers` 创建或删除云函数触发器,通过 action 参数区分操作类型 #### 参数 参数名类型必填说明 actionstring是操作类型:create=创建触发器,delete=删除触发器 可填写的值: "create", "delete" namestring是函数名 triggersarray of object触发器配置数组(创建时必需) triggers[].namestring是Trigger name triggers[].typestring是Trigger type, currently only supports 'timer' 可填写的值: "timer" triggers[].configstring是Trigger configuration. For timer triggers, use cron expression format: second minute hour day month week year. IMPORTANT: Must include exactly 7 fields (second minute hour day month week year). Examples: '0 0 2 1 * * *' (monthly), '0 30 9 * * * *' (daily at 9:30 AM) triggerNamestring触发器名称(删除时必需) --- ### `uploadFiles` 上传文件到静态网站托管 #### 参数 参数名类型必填说明 localPathstring本地文件或文件夹路径,需要是绝对路径,例如 /tmp/files/data.txt cloudPathstring云端文件或文件夹路径,例如files/data.txt filesarray of object多文件上传配置 默认值: [] files[].localPathstring是 files[].cloudPathstring是 ignorestring \| array of string忽略文件模式 --- ### `deleteFiles` 删除静态网站托管的文件或文件夹 #### 参数 参数名类型必填说明 cloudPathstring是云端文件或文件夹路径 isDirboolean是否为文件夹 默认值: false --- ### `findFiles` 搜索静态网站托管的文件 #### 参数 参数名类型必填说明 prefixstring是匹配前缀 markerstring起始对象键标记 maxKeysnumber单次返回最大条目数 --- ### `domainManagement` 统一的域名管理工具,支持绑定、解绑、查询和修改域名配置 #### 参数 参数名类型必填说明 actionstring是操作类型: create=绑定域名, delete=解绑域名, check=查询域名配置, modify=修改域名配置 可填写的值: "create", "delete", "check", "modify" domainstring域名 certIdstring证书ID(绑定域名时必需) domainsarray of string域名列表(查询配置时使用) domainIdnumber域名ID(修改配置时必需) domainConfigobject域名配置(修改配置时使用) domainConfig.Referobject domainConfig.Refer.Switchstring是 domainConfig.Refer.RefererRulesarray of object domainConfig.Refer.RefererRules[].RefererTypestring是 domainConfig.Refer.RefererRules[].Referersarray of string是 domainConfig.Refer.RefererRules[].AllowEmptyboolean是 domainConfig.Cachearray of object domainConfig.Cache[].RuleTypestring是 domainConfig.Cache[].RuleValuestring是 domainConfig.Cache[].CacheTtlnumber是 domainConfig.IpFilterobject domainConfig.IpFilter.Switchstring是 domainConfig.IpFilter.FilterTypestring domainConfig.IpFilter.Filtersarray of string domainConfig.IpFreqLimitobject domainConfig.IpFreqLimit.Switchstring是 domainConfig.IpFreqLimit.Qpsnumber --- ### `queryStorage` 查询云存储信息,支持列出目录文件、获取文件信息、获取临时下载链接等只读操作。返回的文件信息包括文件名、大小、修改时间、下载链接等。 #### 参数 参数名类型必填说明 actionstring是查询操作类型:list=列出目录下的所有文件,info=获取指定文件的详细信息,url=获取文件的临时下载链接 可填写的值: "list", "info", "url" cloudPathstring是云端文件路径,例如 files/data.txt 或 files/(目录) maxAgenumber临时链接有效期,单位为秒,取值范围:1-86400,默认值:3600(1小时) 默认值: 3600 --- ### `manageStorage` 管理云存储文件,支持上传文件/目录、下载文件/目录、删除文件/目录等操作。删除操作需要设置force=true进行确认,防止误删除重要文件。 #### 参数 参数名类型必填说明 actionstring是管理操作类型:upload=上传文件或目录,download=下载文件或目录,delete=删除文件或目录 可填写的值: "upload", "download", "delete" localPathstring是本地文件路径,建议传入绝对路径,例如 /tmp/files/data.txt cloudPathstring是云端文件路径,例如 files/data.txt forceboolean强制操作开关,删除操作时建议设置为true以确认删除,默认false 默认值: false isDirectoryboolean是否为目录操作,true=目录操作,false=文件操作,默认false 默认值: false --- ### `downloadTemplate` 自动下载并部署CloudBase项目模板。 支持的模板: - react: React + CloudBase 全栈应用模板 - vue: Vue + CloudBase 全栈应用模板 - miniprogram: 微信小程序 + 云开发模板 - uniapp: UniApp + CloudBase 跨端应用模板 - rules: 只包含AI编辑器配置文件(包含Cursor、WindSurf、CodeBuddy等所有主流编辑器配置),适合在已有项目中补充AI编辑器配置 支持的IDE类型: - all: 下载所有IDE配置(默认) - cursor: Cursor AI编辑器 - windsurf: WindSurf AI编辑器 - codebuddy: CodeBuddy AI编辑器 - claude-code: Claude Code AI编辑器 - cline: Cline AI编辑器 - gemini-cli: Gemini CLI - opencode: OpenCode AI编辑器 - qwen-code: 通义灵码 - baidu-comate: 百度Comate - openai-codex-cli: OpenAI Codex CLI - augment-code: Augment Code - github-copilot: GitHub Copilot - roocode: RooCode AI编辑器 - tongyi-lingma: 通义灵码 - trae: Trae AI编辑器 - vscode: Visual Studio Code 特别说明: - rules 模板会自动包含当前 mcp 版本号信息(版本号:1.8.41),便于后续维护和版本追踪 - 下载 rules 模板时,如果项目中已存在 README.md 文件,系统会自动保护该文件不被覆盖(除非设置 overwrite=true) #### 参数 参数名类型必填说明 templatestring是要下载的模板类型 可填写的值: "react", "vue", "miniprogram", "uniapp", "rules" idestring指定要下载的IDE类型,默认为all(下载所有IDE配置) 可填写的值: "all", "cursor", "windsurf", "codebuddy", "claude-code", "cline", "gemini-cli", "opencode", "qwen-code", "baidu-comate", "openai-codex-cli", "augment-code", "github-copilot", "roocode", "tongyi-lingma", "trae", "vscode";默认值: "all" overwriteboolean是否覆盖已存在的文件,默认为false(不覆盖) --- ### `interactiveDialog` 统一的交互式对话工具,支持需求澄清和任务确认,当需要和用户确认下一步的操作的时候,可以调用这个工具的clarify,如果有敏感的操作,需要用户确认,可以调用这个工具的confirm #### 参数 参数名类型必填说明 typestring是交互类型: clarify=需求澄清, confirm=任务确认 可填写的值: "clarify", "confirm" messagestring对话消息内容 optionsarray of string可选的预设选项 forceUpdateboolean是否强制更新环境ID配置 risksarray of string操作风险提示 --- ### `searchWeb` 使用联网来进行信息检索,如查询最新的新闻、文章、股价、天气等。支持自然语言查询,也可以直接输入网址获取网页内容 #### 参数 参数名类型必填说明 querystring是搜索关键词、问题或网址,支持自然语言 --- ### `searchKnowledgeBase` 云开发知识库智能检索工具,支持云开发与云函数知识的向量查询 #### 参数 参数名类型必填说明 thresholdnumber相似性检索阈值 默认值: 0.5 idstring是知识库范围,cloudbase=云开发全量知识,scf=云开发的云函数知识, miniprogram=小程序知识(不包含云开发与云函数知识) 可填写的值: "cloudbase", "scf", "miniprogram" contentstring是检索内容 optionsobject其他选项 options.chunkExpandarray of number指定返回的文档内容的展开长度,例如 [3,3]代表前后展开长度 默认值: [3,3] limitnumber指定返回最相似的 Top K 的 K 的值 默认值: 5 --- ### `queryCloudRun` 查询云托管服务信息,支持获取服务列表、查询服务详情和获取可用模板列表。返回的服务信息包括服务名称、状态、访问类型、配置详情等。 #### 参数 参数名类型必填说明 actionstring是查询操作类型:list=获取云托管服务列表(支持分页和筛选),detail=查询指定服务的详细信息(包括配置、版本、访问地址等),templates=获取可用的项目模板列表(用于初始化新项目) 可填写的值: "list", "detail", "templates" pageSizenumber分页大小,控制每页返回的服务数量。取值范围:1-100,默认值:10。建议根据网络性能和显示需求调整 默认值: 10 pageNumnumber页码,用于分页查询。从1开始,默认值:1。配合pageSize使用可实现分页浏览 默认值: 1 serverNamestring服务名称筛选条件,支持模糊匹配。例如:输入"test"可匹配"test-service"、"my-test-app"等服务名称。留空则查询所有服务 serverTypestring服务类型筛选条件:function=函数型云托管(简化开发模式,支持WebSocket/SSE/文件上传等特性,适合快速开发),container=容器型服务(传统容器部署模式,支持任意语言和框架,适合复杂应用) 可填写的值: "function", "container" detailServerNamestring要查询详细信息的服务名称。当action为detail时必需提供,必须是已存在的服务名称。可通过list操作获取可用的服务名称列表 --- ### `manageCloudRun` 管理云托管服务,按开发顺序支持:初始化项目(可从模板开始,模板列表可通过 queryCloudRun 查询)、下载服务代码、本地运行(仅函数型服务)、部署代码、删除服务。部署可配置CPU、内存、实例数、访问类型等参数。删除操作需要确认,建议设置force=true。 #### 参数 参数名类型必填说明 actionstring是云托管服务管理操作类型:init=从模板初始化新的云托管项目代码(在targetPath目录下创建以serverName命名的子目录,支持多种语言和框架模板),download=从云端下载现有服务的代码到本地进行开发,run=在本地运行函数型云托管服务(用于开发和调试,仅支持函数型服务),deploy=将本地代码部署到云端云托管服务(支持函数型和容器型),delete=删除指定的云托管服务(不可恢复,需要确认),createAgent=创建函数型Agent(基于函数型云托管开发AI智能体) 可填写的值: "init", "download", "run", "deploy", "delete", "createAgent" serverNamestring是云托管服务名称,用于标识和管理服务。命名规则:支持大小写字母、数字、连字符和下划线,必须以字母开头,长度3-45个字符。在init操作中会作为在targetPath下创建的子目录名,在其他操作中作为目标服务名 targetPathstring本地代码路径,必须是绝对路径。在deploy操作中指定要部署的代码目录,在download操作中指定下载目标目录,在init操作中指定云托管服务的上级目录(会在该目录下创建以serverName命名的子目录)。建议约定:项目根目录下的cloudrun/目录,例如:/Users/username/projects/my-project/cloudrun serverConfigobject服务配置项,用于部署时设置服务的运行参数。包括资源规格、访问权限、环境变量等配置。不提供时使用默认配置 serverConfig.OpenAccessTypesarray of string公网访问类型配置,控制服务的访问权限:WEB=公网访问(默认,可通过HTTPS域名访问),VPC=私有网络访问(仅同VPC内可访问),PRIVATE=内网访问(仅云开发环境内可访问)。可配置多个类型 serverConfig.CpunumberCPU规格配置,单位为核。可选值:0.25、0.5、1、2、4、8等。注意:内存规格必须是CPU规格的2倍(如CPU=0.25时内存=0.5,CPU=1时内存=2)。影响服务性能和计费 serverConfig.Memnumber内存规格配置,单位为GB。可选值:0.5、1、2、4、8、16等。注意:必须是CPU规格的2倍。影响服务性能和计费 serverConfig.MinNumnumber最小实例数配置,控制服务的最小运行实例数量。设置为0时支持缩容到0(无请求时不产生费用),设置为大于0时始终保持指定数量的实例运行(确保快速响应但会增加成本) serverConfig.MaxNumnumber最大实例数配置,控制服务的最大运行实例数量。当请求量增加时,服务最多可以扩展到指定数量的实例,超过此数量后将拒绝新的请求。建议根据业务峰值设置 serverConfig.Portnumber服务监听端口配置。函数型服务固定为3000,容器型服务可自定义。服务代码必须监听此端口才能正常接收请求 serverConfig.EnvParamsobject环境变量配置,用于传递配置信息给服务代码。格式为键值对,如{"DATABASE_URL":"mysql://..."}。敏感信息建议使用环境变量而非硬编码 serverConfig.DockerfilestringDockerfile文件名配置,仅容器型服务需要。指定用于构建容器镜像的Dockerfile文件路径,默认为项目根目录下的Dockerfile serverConfig.BuildDirstring构建目录配置,指定代码构建的目录路径。当代码结构与标准不同时使用,默认为项目根目录 serverConfig.InternalAccessboolean内网访问开关配置,控制是否启用内网访问。true=启用内网访问(可通过云开发SDK直接调用),false=关闭内网访问(仅公网访问) serverConfig.EntryPointstringDockerfile EntryPoint参数配置,仅容器型服务需要。指定容器启动时的入口程序,如["node","app.js"] serverConfig.CmdstringDockerfile Cmd参数配置,仅容器型服务需要。指定容器启动时的默认命令,如["npm","start"] templatestring项目模板标识符,用于指定初始化项目时使用的模板。可通过queryCloudRun的templates操作获取可用模板列表。常用模板:helloworld=Hello World示例,nodejs=Node.js项目模板,python=Python项目模板等 默认值: "helloworld" runOptionsobject本地运行参数配置,仅函数型云托管服务支持。用于配置本地开发环境的运行参数,不影响云端部署 runOptions.portnumber本地运行端口配置,仅函数型服务有效。指定服务在本地运行时监听的端口号,默认3000。确保端口未被其他程序占用 默认值: 3000 runOptions.envParamsobject本地运行时的附加环境变量配置,用于本地开发和调试。格式为键值对,如{"DEBUG":"true","LOG_LEVEL":"debug"}。这些变量仅在本地运行时生效 runOptions.runModestring运行模式:normal=普通函数模式,agent=Agent模式(用于AI智能体开发) 可填写的值: "normal", "agent";默认值: "normal" runOptions.agentIdstringAgent ID,在agent模式下使用,用于标识特定的Agent实例 agentConfigobjectAgent配置项,仅在createAgent操作时使用 agentConfig.agentNamestring是Agent名称,用于生成BotId agentConfig.botTagstringBot标签,用于生成BotId,不提供时自动生成 agentConfig.descriptionstringAgent描述信息 agentConfig.templatestringAgent模板类型,默认为blank(空白模板) 默认值: "blank" forceboolean强制操作开关,用于跳过确认提示。默认false(需要确认),设置为true时跳过所有确认步骤。删除操作时强烈建议设置为true以避免误操作 默认值: false --- ### `createFunctionHTTPAccess` 创建云函数的 HTTP 访问 #### 参数 参数名类型必填说明 namestring是函数名 pathstring是HTTP 访问路径 --- ### `downloadRemoteFile` 下载远程文件到项目根目录下的指定相对路径。例如:小程序的 Tabbar 等素材图片,必须使用 **png** 格式,可以从 Unsplash、wikimedia【一般选用 500 大小即可、Pexels、Apple 官方 UI 等资源中选择来下载。 #### 参数 参数名类型必填说明 urlstring是远程文件的 URL 地址 relativePathstring是相对于项目根目录的路径,例如:'assets/images/logo.png' 或 'docs/api.md'。不允许使用 ../ 等路径遍历操作。 --- ### `readSecurityRule` 读取指定资源(数据库集合、云函数、存储桶)的安全规则和权限类别。 参数说明: - resourceType: 资源类型(database/function/storage) - resourceId: 资源唯一标识(集合名/函数名/桶名) #### 参数 参数名类型必填说明 resourceTypestring是资源类型:database=数据库集合,function=云函数,storage=存储桶 可填写的值: "database", "function", "storage" resourceIdstring是资源唯一标识。数据库为集合名,云函数为函数名,存储为桶名。 --- ### `writeSecurityRule` 设置指定资源(数据库集合、云函数、存储桶)的安全规则。 参数说明: - resourceType: 资源类型(database/function/storage) - resourceId: 资源唯一标识(集合名/函数名/桶名) - aclTag: 权限类别(READONLY/PRIVATE/ADMINWRITE/ADMINONLY/CUSTOM) - rule: 自定义安全规则内容,仅当 aclTag 为 CUSTOM 时必填 #### 参数 参数名类型必填说明 resourceTypestring是资源类型:database=数据库集合,function=云函数,storage=存储桶 可填写的值: "database", "function", "storage" resourceIdstring是资源唯一标识。数据库为集合名,云函数为函数名,存储为桶名。 aclTagstring是权限类别 可填写的值: "READONLY", "PRIVATE", "ADMINWRITE", "ADMINONLY", "CUSTOM" rulestring自定义安全规则内容,仅当 aclTag 为 CUSTOM 时必填 --- ### `activateInviteCode` 云开发 AI编程激励计划,通过邀请码激活用户激励。 #### 参数 参数名类型必填说明 InviteCodestring是待激活的邀请码 --- --- ## 云托管开发部署 # 云托管开发部署 CloudBase AI ToolKit 内置支持云托管开发部署功能,云托管让你可以轻松部署和运行各种后端服务,支持长连接、文件上传、多语言等场景。这个插件已经默认启用,你只需要用自然语言告诉 AI 你想要做什么。 ## 新增功能:AI 智能体开发 现在支持基于函数型云托管开发 AI 智能体,让你可以快速创建和部署个性化的 AI 应用。 ## 什么时候用云托管? 当你需要: - **实时通信**:WebSocket、SSE、流式响应 - **长任务**:后台处理 - **多语言**:Java、Go、PHP、Python、Node.js 等 - **AI 智能体**:个性化 AI 应用开发 ## 两种模式怎么选? **函数型**:推荐新手,支持 Node.js,内置 WebSocket 支持,可以本地运行调试,端口固定 3000 **容器型**:适合已有项目,支持任意语言,需要提供 Dockerfile ## 快速开始 ### 1. 查看有什么模板 ``` 请列出可用的云托管模板 ``` ### 2. 创建新项目 ``` 用 helloworld 模板创建一个名为 my-service 的项目 ``` ### 3. 本地运行(函数型) ``` 在本地运行 my-service,端口 3000 ``` ### 4. 部署到云端 ``` 部署 my-service,开启公网访问,CPU 0.5 核,内存 1GB ``` ### 5. 创建 AI 智能体 ``` 创建一个名为 my-agent 的智能体,用于客服对话 ``` ## 常见场景 ### 小程序后端 ``` 创建一个支持 WebSocket 的函数型服务,用于小程序聊天功能 ``` ### Java Spring Boot 应用 ``` 部署一个 Spring Boot 应用,提供 REST API 服务 ``` ### Go 微服务 ``` 用 Go 创建一个高性能的微服务,处理用户认证 ``` ### Python 数据处理 ``` 部署一个 Python 服务,定时处理数据并生成报表 ``` ### PHP Laravel 应用 ``` 部署一个 Laravel 应用,提供完整的 Web 后台管理 ``` ### AI 智能体应用 ``` 创建一个智能体,用于处理用户咨询和提供个性化服务 ``` ## 访问你的服务 部署完成后,你可以通过以下方式访问: **小程序直接调用**(推荐): ```js const res = await wx.cloud.callContainer({ config: { env: "your-env-id" }, path: "/api/data", method: "POST", header: { "X-WX-SERVICE": "my-service" } }); ``` **Web 应用**: ```js import cloudbase from "@cloudbase/js-sdk"; const app = cloudbase.init({ env: "your-env-id" }); const res = await app.callContainer({ name: "my-service", method: "GET", path: "/health" }); ``` **直接 HTTP 访问**: ```bash curl https://your-service-domain.com ``` ## AI 智能体开发 ### 创建智能体 ``` 创建一个名为 customer-service 的智能体,用于客服对话 ``` ### 本地运行智能体 ``` 在本地运行 customer-service 智能体,端口 3000 ``` ### 调用智能体 ```js // Web 应用调用 const app = cloudbase.init({ env: "your-env-id" }); const ai = app.ai(); const res = await ai.bot.sendMessage({ botId: "ibot-customer-service-demo", msg: "你好,我需要帮助" }); for await (let x of res.textStream) { console.log(x); } ``` ```bash # 命令行测试 curl 'http://127.0.0.1:3000/v1/aibot/bots/ibot-customer-service-demo/send-message' \ -H 'Accept: text/event-stream' \ -H 'Content-Type: application/json' \ --data-raw '{"msg":"你好"}' ``` --- ## 小程序插件 # 小程序插件 小程序插件提供了微信小程序开发和部署的完整工具链支持,包括代码上传、预览、构建等功能。 ## 配置 ### 环境变量 ```bash # 设置小程序代码上传密钥(二选一) export MINIPROGRAM_PRIVATE_KEY="私钥内容" # 或者 export MINIPROGRAM_PRIVATE_KEY_PATH="/path/to/private.key" # 启用小程序插件 export CLOUDBASE_MCP_PLUGINS_ENABLED="env,database,functions,hosting,storage,setup,interactive,rag,gateway,download,miniprogram" ``` ### MCP 配置 ```json { "mcpServers": { "cloudbase": { "command": "npx", "args": ["npm-global-exec@latest", "@cloudbase/cloudbase-mcp@latest"], "env": { "MINIPROGRAM_PRIVATE_KEY": "你的小程序私钥", "CLOUDBASE_MCP_PLUGINS_ENABLED": "env,database,functions,hosting,storage,setup,interactive,rag,gateway,download,miniprogram" } } } } ``` ## 工具 ### uploadMiniprogramCode 上传小程序代码到微信平台 **参数:** - `appId`: 小程序 appId - `projectPath`: 项目路径 - `version`: 版本号 - `desc`: 版本描述(可选) - `setting`: 编译设置(可选) - `robot`: 机器人编号 1-30(可选) - `type`: 项目类型 miniProgram/miniGame(可选) ### previewMiniprogramCode 预览小程序代码并生成二维码 **参数:** - `appId`: 小程序 appId - `projectPath`: 项目路径 - `desc`: 预览描述(可选) - `setting`: 编译设置(可选) - `robot`: 机器人编号 1-30(可选) - `type`: 项目类型 miniProgram/miniGame(可选) - `qrcodeFormat`: 二维码格式 image/base64/terminal(可选) - `qrcodeOutputDest`: 二维码输出路径(可选) - `pagePath`: 预览页面路径(可选) - `searchQuery`: 预览页面参数(可选) ### buildMiniprogramNpm 构建小程序 npm 包 **参数:** - `appId`: 小程序 appId - `projectPath`: 项目路径 - `type`: 项目类型 miniProgram/miniGame(可选) - `robot`: 机器人编号 1-30(可选) ### getMiniprogramProjectConfig 获取小程序项目配置 **参数:** - `appId`: 小程序 appId - `projectPath`: 项目路径 - `type`: 项目类型 miniProgram/miniGame(可选) ### getMiniprogramSourceMap 获取最近上传版本的 SourceMap,用于生产环境错误调试 **参数:** - `appId`: 小程序 appId - `projectPath`: 项目路径 - `robot`: 指定使用哪一个 ci 机器人,1-30 - `sourceMapSavePath`: SourceMap 保存路径 - `type`: 项目类型 miniProgram/miniGame(可选) ### checkMiniprogramCodeQuality 检查小程序代码质量,生成质量报告(需要 miniprogram-ci 1.9.11+) **参数:** - `appId`: 小程序 appId - `projectPath`: 项目路径 - `saveReportPath`: 质量报告保存路径 - `type`: 项目类型 miniProgram/miniGame(可选) ### packMiniprogramNpmManually 自定义 node_modules 位置的小程序 npm 构建,支持复杂项目结构 **参数:** - `packageJsonPath`: 希望被构建的 node_modules 对应的 package.json 的路径 - `miniprogramNpmDistDir`: 被构建 miniprogram_npm 的目标位置 - `ignores`: 指定需要排除的规则(可选) ## 使用场景 ### 开发流程 1. **构建依赖** ``` 调用 buildMiniprogramNpm 构建 npm 包 调用 packMiniprogramNpmManually 自定义构建复杂项目结构 ``` 2. **预览测试** ``` 调用 previewMiniprogramCode 生成预览二维码 ``` 3. **发布上线** ``` 调用 uploadMiniprogramCode 上传代码到微信平台 ``` 4. **调试优化** ``` 调用 getMiniprogramSourceMap 获取 SourceMap 进行错误调试 调用 checkMiniprogramCodeQuality 检查代码质量并生成报告 ``` ### 密钥配置 使用此插件前,需要在微信公众平台配置: 1. 访问 [微信公众平台](https://mp.weixin.qq.com/) 2. 进入"管理-开发管理-开发设置-小程序代码上传" 3. 生成「代码上传密钥」 4. 配置 IP 白名单(推荐开启) ## 注意事项 - 代码上传密钥拥有预览、上传代码的权限 - 密钥不会明文存储在微信公众平台上 - 密钥一旦遗失必须重置,请妥善保管 - 建议开启 IP 白名单以降低安全风险 ## 常见问题 ### Q: 如何获取小程序 appId? A: 在微信公众平台的小程序管理页面可以查看到 appId。 ### Q: 机器人编号有什么作用? A: 机器人编号用于区分不同的上传任务,可以设置 1-30 之间的数字。 ### Q: 支持哪些编译设置? A: 支持 ES6/ES7 转换、代码压缩、WXSS 压缩等常见编译选项。 ### Q: SourceMap 有什么作用? A: SourceMap 用于生产环境错误调试,可以将压缩后的代码错误映射回原始代码位置,便于问题定位。 ### Q: 代码质量检查包含哪些内容? A: 包含代码规范、性能问题、潜在 bug、可优化项等多维度的质量分析,生成详细的质量报告。 ### Q: 何时需要使用自定义 npm 构建? A: 当项目有特殊的目录结构、需要自定义 node_modules 位置或有特殊的构建需求时使用。 --- ## 插件系统 # 插件系统 CloudBase MCP 采用插件化架构,支持按需启用工具模块,解决 MCP 客户端工具数量限制问题。 ## 📋 插件列表 ### 默认插件 (开箱即用) | 插件名称 | 功能描述 | |----------|----------| | `env` | 环境管理 (登录、退出、环境查询) | | `database` | 数据库操作 (集合、文档、索引管理) | | `functions` | 云函数管理 (创建、更新、调用、日志) | | `hosting` | 静态托管 (文件上传、域名配置) | | `storage` | 云存储管理 (文件存储、CDN) | | `setup` | 项目初始化 (模板下载、配置) | | `interactive` | 交互对话 (用户确认、选择) | | `security-rule` | 安全规则管理(数据库、云函数、存储安全规则读写) | ### 可选插件 (按需启用) | 插件名称 | 功能描述 | |----------|----------| | `rag` | 知识库搜索 (AI 增强问答) | | `download` | 远程文件下载 | | `gateway` | API 网关管理 | | `miniprogram` | 小程序发布 (上传、预览、构建) | | `cloudrun` | 云托管服务 (容器部署、服务管理) | ## ⚙️ 插件配置 ### 指定启用插件 ```json { "mcpServers": { "cloudbase-mcp": { "command": "npx", "args": ["npm-global-exec@latest", "@cloudbase/cloudbase-mcp@latest"], "env": { "CLOUDBASE_MCP_PLUGINS_ENABLED": "env,database,functions,hosting" } } } } ``` ### 禁用特定插件 ```json { "mcpServers": { "cloudbase-mcp": { "command": "npx", "args": ["npm-global-exec@latest", "@cloudbase/cloudbase-mcp@latest"], "env": { "CLOUDBASE_MCP_PLUGINS_DISABLED": "rag,download,gateway" } } } } ``` ## 🎯 常用配置 | 场景 | 推荐插件 | |------|----------| | **基础开发** | `env,database,functions,hosting` | | **完整功能** | `env,database,functions,hosting,storage,setup,interactive,rag,download,gateway,miniprogram` | | **纯后端** | `env,database,functions` | | **小程序** | `env,database,functions,storage,setup,miniprogram` | | **AI 应用** | `env,database,functions,hosting,rag,interactive` | ## 📚 相关文档 - [MCP 工具详细说明](mcp-tools.md) - 查看所有可用工具 - [快速开始](getting-started.md) - 开始使用指南 - [常见问题](faq.md) - 插件配置问题 --- ## Spec 工作流说明 # Spec 工作流说明 ## 简介 CloudBase AI ToolKit 内置了 Kiro 风格的 Spec 工作流,旨在让 AI 编程过程更加工程化、规范化,提升需求梳理、设计、开发、验收的全流程体验。现在支持灵活的斜杠命令控制,让用户可以根据任务复杂度选择合适的开发模式。 ## 工作流理念 - **工程化**:将需求、设计、任务分明,避免"拉霸式" vibe coding。 - **可追溯**:每一步都有文档记录,便于回溯和团队协作。 - **AI 协作**:AI 负责梳理需求、设计方案、拆分任务,人类专注决策与评审。 - **自动生成**:自动生成 requirements.md、design.md、tasks.md 等规范文档。 - **灵活控制**:支持斜杠命令控制,智能判断任务复杂度。 ## 工作流控制 ### 斜杠命令系统 CloudBase AI ToolKit 提供了灵活的斜杠命令来控制工作流: - **`/spec`** - 强制使用完整 spec 流程(需求文档、技术方案、任务拆分) - **`/no_spec`** - 跳过 spec 流程,直接执行任务 - **`/help`** - 显示 workflow 命令帮助 - **默认** - AI 根据任务复杂度智能判断 ### 智能判断机制 AI 会根据任务复杂度自动选择合适的开发模式: **使用 spec 流程的场景:** - 新功能开发 - 复杂架构设计 - 多模块集成 - 涉及数据库设计 - 涉及用户界面设计 - 涉及第三方服务集成 **跳过 spec 流程的场景:** - 简单 bug 修复 - 文档更新 - 配置修改 - 代码重构 - 性能优化 - 测试用例编写 ## 工作流流程 ### Spec 流程(/spec 或智能判断使用) 1. **需求梳理** - 采用 EARS(简易需求语法)方法,AI 协助用户梳理需求,生成 `requirements.md`。 2. **技术方案设计** - 基于需求,AI 生成技术架构、技术选型、接口/数据库设计等,形成 `design.md`。 3. **任务拆分** - 按照需求和设计,AI 拆分具体开发任务,生成 `tasks.md`。 4. **自动执行与追踪** - AI 根据任务清单自动推进开发,实时更新任务状态。 ### No-Spec 流程(/no_spec 或智能判断跳过) 1. **直接分析任务需求** 2. **快速制定执行计划** 3. **直接执行任务** 4. **保持代码质量和项目规范** 5. **必要时使用 interactiveDialog 确认** ## 典型文件结构 ``` specs/ your-feature/ requirements.md # 需求文档 design.md # 技术方案设计 tasks.md # 任务拆分与进度 ``` ### requirements.md 示例 ```markdown # 需求文档 ## 介绍 简要描述需求背景和目标。 ## 需求 ### 需求 1 - 需求名称 **用户故事:** 用户故事内容 #### 验收标准 1. While , when , the shall 2. ... ``` ### design.md 示例 ```markdown # 技术方案设计 - 架构图(可用 mermaid) - 技术选型说明 - 数据库/接口设计 - 安全性与测试策略 ``` ### tasks.md 示例 ```markdown # 实施计划 - [ ] 1. 任务信息 - 具体要做的事情 - _需求: 相关的需求点编号 ``` ## 使用示例 ### 强制使用 Spec 流程 **用户输入:** ``` /spec 开发一个用户管理系统 ``` **AI 响应:** ``` 🎯 Workflow 模式:Spec 流程 📋 判断依据:用户明确指定使用 /spec 命令 🔄 后续流程:将按照标准软件工程方式执行 1. 需求澄清和确认 2. 需求文档设计(requirements.md) 3. 技术方案设计(design.md) 4. 任务拆分(tasks.md) 5. 执行任务并更新状态 ✅ 确认:我将开始需求澄清阶段,请确认是否继续? ``` ### 跳过 Spec 流程 **用户输入:** ``` /no_spec 修复登录按钮的样式问题 ``` **AI 响应:** ``` 🎯 Workflow 模式:No-Spec 流程 📋 判断依据:用户明确指定使用 /no_spec 命令 🔄 后续流程:将直接分析并执行任务 1. 直接分析任务需求 2. 快速制定执行计划 3. 直接执行任务 4. 保持代码质量和项目规范 ⚠️ 注意:将跳过需求文档和技术方案设计阶段,直接执行修复任务 ✅ 确认:我将开始分析登录按钮样式问题,请确认是否继续? ``` ### 智能判断(默认) **用户输入:** ``` 开发一个复杂的电商购物车功能 ``` **AI 响应:** ``` 🎯 Workflow 模式:Spec 流程 📋 判断依据:任务涉及复杂功能开发(电商购物车) 🔄 后续流程:将按照标准软件工程方式执行 1. 需求澄清和确认 2. 需求文档设计(requirements.md) 3. 技术方案设计(design.md) 4. 任务拆分(tasks.md) 5. 执行任务并更新状态 ✅ 确认:我将开始需求澄清阶段,请确认是否继续? ``` ## 与 AI IDE 的集成 - 支持 Cursor、Claude Code、WindSurf、CodeBuddy 等主流 AI IDE - 通过内置规则和 MCP 工具,AI 可自动识别并执行 Spec 工作流 - 用户只需用自然语言描述需求,AI 自动生成并维护 Spec 文档 - 支持斜杠命令控制,提供灵活的开发模式选择 ## 优势 - **规范化开发流程**:降低沟通和协作成本 - **灵活控制**:根据任务复杂度选择合适的开发模式 - **智能判断**:AI 自动判断是否需要使用 spec 流程 - **便于团队协作**:需求追溯和文档管理 - **支持自动化测试**:与持续集成流程集成 - **让 AI 真正成为开发流程的"助理工程师"** ## 最佳实践 ### 选择合适的命令 **使用 /spec 的场景:** - 新功能开发 - 复杂架构设计 - 多模块集成 - 涉及数据库设计 - 涉及用户界面设计 - 涉及第三方服务集成 **使用 /no_spec 的场景:** - 简单 bug 修复 - 文档更新 - 配置修改 - 代码重构 - 性能优化 - 测试用例编写 ### 智能判断的使用 **建议:** - 不确定时可以不指定命令,让 AI 智能判断 - 观察 AI 的判断依据,了解其逻辑 - 如果判断不准确,可以手动指定命令 ### 质量保证 **注意事项:** - /no_spec 模式仍需要遵循项目规范 - 复杂任务建议使用 /spec 确保质量 - 任何模式下都需要用户确认重要操作 - 保持代码质量和可维护性 ## 典型用法 1. 用户在 AI IDE 中输入需求(可选择使用斜杠命令) 2. AI 根据命令或智能判断选择合适的开发模式 3. 如果使用 spec 流程,AI 自动生成 specs/your-feature/ 下的 requirements.md、design.md、tasks.md 4. 用户确认后,AI 按流程推进开发并持续更新任务状态 5. 开发完成后,所有文档可用于评审、归档和后续维护 --- 如需进一步了解 Spec 工作流或遇到问题,欢迎查阅[官方文档](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/development)或加入技术交流群。 --- ## 项目模板 # 项目模板 我们为你准备了内置云开发最佳实践和 AI IDE 规则的项目模板: ## 🚀 新项目推荐 ### 微信小程序 + 云开发模板 云开发小程序解决方案模板,包含小程序基础配置。 - **下载地址**:[代码包下载](https://static.cloudbase.net/cloudbase-examples/miniprogram-cloudbase-miniprogram-template.zip?v=2025053001) - **开源代码**:[GitHub](https://github.com/TencentCloudBase/awesome-cloudbase-examples/tree/master/miniprogram/cloudbase-miniprogram-template) - **适用场景**:微信小程序开发 ### React Web 应用 + 云开发模板 现代化的 React 全栈应用模板,包含云开发集成配置。 - **下载地址**:[代码包下载](https://static.cloudbase.net/cloudbase-examples/web-cloudbase-react-template.zip?v=2025053001) - **开源代码**:[GitHub](https://github.com/TencentCloudBase/awesome-cloudbase-examples/tree/master/web/cloudbase-react-template) - **适用场景**:Web 应用开发 ### Vue Web 应用 + 云开发模板 现代化的 Vue 全栈应用模板,包含云开发集成配置。 - **下载地址**:[代码包下载](https://static.cloudbase.net/cloudbase-examples/web-cloudbase-vue-template.zip?v=2025053001) - **开源代码**:[GitHub](https://github.com/TencentCloudBase/awesome-cloudbase-examples/tree/master/web/cloudbase-vue-template) - **适用场景**:Web 应用开发 ### UniApp 跨端应用 + 云开发模板 基于 UniApp 的云开发跨端应用模板,可编译到 H5 和微信小程序。 - **下载地址**:[代码包下载](https://static.cloudbase.net/cloudbase-examples/universal-cloudbase-uniapp-template.zip?v=2025053001) - **开源代码**:[GitHub](https://github.com/TencentCloudBase/awesome-cloudbase-examples/tree/master/universal/cloudbase-uniapp-template) - **适用场景**:跨端应用开发(H5、微信小程序) ### AI 规则通用云开发模板 不限定语言和框架,内置 CloudBase AI 规则和MCP,适用于任意云开发项目。 - **下载地址**:[代码包下载](https://static.cloudbase.net/cloudbase-examples/web-cloudbase-project.zip) - **开源代码**:[GitHub](https://github.com/TencentCloudBase/awesome-cloudbase-examples/tree/master/web/cloudbase-project) - **适用场景**:任意云开发项目 ## 🛠️ 已有项目增强 如果你已经有自己的项目,只需在配置好 MCP 后,对 AI 说: ``` 在当前项目中下载云开发 AI 规则 ``` 即可一键下载并补全 AI 编辑器规则配置到当前项目目录,无需手动操作。 如果你只想下载特定IDE的配置文件,避免项目文件混乱,可以指定IDE类型: ``` 在当前项目中下载云开发 AI 规则,只包含Cursor配置 在当前项目中下载云开发 AI 规则,只包含WindSurf配置 在当前项目中下载云开发 AI 规则,只包含Claude Code配置 ``` 支持的IDE类型包括:cursor、windsurf、codebuddy、claude-code、cline、gemini-cli、opencode、qwen-code、baidu-comate、openai-codex-cli、augment-code、github-copilot、roocode、tongyi-lingma、trae、vscode 等。 ## 📁 模板包含内容 所有模板都包含以下配置: - ✅ AI IDE 规则配置(针对不同编辑器) - ✅ CloudBase MCP 配置 - ✅ 云开发最佳实践代码结构 - ✅ 项目说明文档 --- ## 故障排除 # 故障排除 ## 常见问题解决 ### 登录问题 **问题:无法登录云开发** ``` 登录云开发 ``` 如果登录失败,请检查: - 网络连接是否正常 - 是否已开通云开发环境 ### 部署问题 **问题:部署失败** 把完整的错误信息发给 AI: ``` 报错了,错误是xxxx ``` **问题:云函数运行异常** ``` 云函数代码运行不符合需求,需求是 xxx,请查看日志和数据进行调试,并进行修复 ``` ### MCP 配置问题 **问题:MCP 工具无法使用** 1. 检查 MCP 配置是否正确添加 2. 重启 AI IDE 3. 确认使用了正确的配置格式: ```json { "mcpServers": { "cloudbase-mcp": { "command": "npx", "args": ["-y", "@cloudbase/cloudbase-mcp@latest"] } } } ``` ### 环境切换问题 **切换到其他环境:** ``` 退出云开发 登录云开发 ``` **查看当前环境:** ``` 查询当前云开发环境信息 ``` ## 调试技巧 1. **详细描述错误** - 提供完整错误信息给 AI 2. **查看日志** - 要求 AI 查看云函数日志 3. **分步排查** - 从简单功能开始验证 4. **重新部署** - 修改代码后重新部署测试 ## 获取帮助 如果问题仍未解决,可以: 1. **查看 FAQ** - [常见问题解答](./faq) 2. **GitHub Issues** - [提交问题](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/issues) 3. **技术交流群** - 加入微信技术交流群获取帮助 --- ## 📚 教程 # 📚 教程 ## 📄 文章 ### 🚀 CloudBase AI CLI 实战案例 - [用 CloudBase AI CLI 开发邻里闲置物品循环利用小程序](https://docs.cloudbase.net/practices/ai-cli-mini-program) - 详细案例教程,展示如何使用 CloudBase AI CLI 从零开始开发完整的小程序项目 ### 🌐 全栈Web应用 - [使用 CodeBuddy IDE + CloudBase 一站式开发卡片翻翻翻游戏](https://mp.weixin.qq.com/s/2EM3RBzdQUCdfld2CglWgg) - [1小时开发微信小游戏《我的早餐店》——基于CloudBase AI Toolkit](https://cloud.tencent.com/developer/article/2532595) - [AI Coding宝藏组合:Cursor + Cloudbase-AI-Toolkit 开发游戏实战](https://juejin.cn/post/7518783423277695028#comment) - [2天上线一款可联机的分手厨房小游戏](https://mp.weixin.qq.com/s/nKfhHUf8w-EVKvA0u1rdeg) - [CloudBase AI Toolkit 做一个医院实习生排班系统,告别痛苦的excel表格](https://cloud.tencent.com/developer/article/2538023) - [没有服务器,怎么云化部署前后端项目](https://cloud.tencent.com/developer/article/2537971) - [快速打造程序员专属名片网站](https://cloud.tencent.com/developer/article/2536273) ### 📱 全栈小程序 - [我用「CloudBase AI ToolKit」一天做出"网络热词"小程序](https://cloud.tencent.com/developer/article/2537907) - [用AI打造你的专属"云书房"小程序!](https://cloud.tencent.com/developer/article/2535789) - [一人挑战全栈研发简历制作小程序](https://cloud.tencent.com/developer/article/2535894) - [我用AI开发并上线了一款小程序:解忧百宝盒](https://mp.weixin.qq.com/s/DYekRheNQ2u8LAl_F830fA) - [AI时代,从零基础到全栈开发者之路:Figma + Cursor + Cloudbase快速搭建微信小程序](https://mp.weixin.qq.com/s/nT2JsKnwBiup1imniCr2jA) ## 📱 应用项目 - [简历助手小程序](https://gitcode.com/qq_33681891/resume_template) - [五子棋联机游戏](https://github.com/TencentCloudBase/awesome-cloudbase-examples/tree/master/web/gomoku-game) - [分手厨房联机游戏](https://github.com/TencentCloudBase/awesome-cloudbase-examples/tree/master/web/overcooked-game) - [电商管理后台](https://github.com/TencentCloudBase/awesome-cloudbase-examples/tree/master/web/ecommerce-management-backend) - [短视频小程序](https://github.com/TencentCloudBase/awesome-cloudbase-examples/tree/master/miniprogram/cloudbase-ai-video) - [约会小程序](https://github.com/TencentCloudBase/awesome-cloudbase-examples/tree/master/miniprogram/dating) ## 🎥 视频教程 - [云开发CloudBase:用AI开发一款分手厨房小游戏](https://www.bilibili.com/video/BV1v5KAzwEf9/) - [软件3.0:AI 编程新时代的最佳拍档 CloudBase AI ToolKit,以开发微信小程序为例](https://www.bilibili.com/video/BV15gKdz1E5N/) - [用AiCoding 一人挑战全栈研发简历制作小程序](https://www.bilibili.com/video/BV1D23Nz1Ec3/) - [5分钟在本地创造一个程序员专属名片网站](https://www.bilibili.com/video/BV19y3EzsEHQ/?vd_source=c8763f6ab9c7c6f7f760ad7ea9157011) ## 🚀 更多资源 ### 官方文档 - [快速开始指南](./getting-started) - 几分钟内上手使用 - [开发指南](./development) - 深入了解开发最佳实践 - [MCP工具文档](./mcp-tools) - 了解所有可用工具 ### 社区资源 - [GitHub 仓库](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit) - 开源代码和问题反馈 - [微信技术交流群](./faq#技术交流群) - 加入开发者社区 - [常见问题 FAQ](./faq) - 解决开发中的问题 ### 项目模板 - [微信小程序模板](./templates#微信小程序--云开发模板) - [React Web 应用模板](./templates#react-web-应用--云开发模板) - [Vue Web 应用模板](./templates#vue-web-应用--云开发模板) ## 💡 学习建议 1. **循序渐进**:建议先阅读快速开始指南,然后观看视频教程,最后尝试实战项目 2. **动手实践**:跟着教程一步步操作,遇到问题及时查阅文档或寻求社区帮助 3. **举一反三**:掌握基础后,尝试修改和扩展项目功能,加深理解 4. **分享交流**:在社区中分享你的学习心得和项目成果 ## 🤝 贡献教程 如果你有使用 CloudBase AI ToolKit 的精彩教程或项目案例,欢迎分享给社区! **贡献方式:** - 在 [GitHub Issues](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit/issues) 中提交教程建议 - 在微信技术交流群中分享你的项目 - 提交 Pull Request 添加新的教程内容 让我们一起构建更丰富的 AI + 云开发学习资源! --- ## Copilot 智能问答 # Copilot 智能问答 ```mdx-code-block import AgentCard from "@site/src/components/AgentCard"; ``` ## 功能介绍 ### 智能问答 云开发 Copilot 基于混元大模型以及大量的云开发知识库训练,可以帮助用户解答使用过程中的问题,例如使用咨询、故障排除、代码编写辅助等。 #### 解答用户使用的问题 ![](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/5ea8466f-f342-4b75-ad3b-6dff1da74918.png) #### 用户代码排障 用户代码报错时,可以 AI 排障 ![](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/a6cee15a-1f53-4d36-873c-012f3bb089f1.png) ## 工具调用 除了智能问答,云开发 Copilot 还能串联更多底层其他的专业的 AI 智能体功能,例如 AI 生成应用、AI 生成组件、AI 生成区块、AI 生成云函数、AI 生成数据模型、AI 生成 CMS 内容等。 云开发 Copilot 有时会根据用户的输入给出智能调用 ![](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/c4950f4f-6941-464f-924a-f76ef5cea539.png) ## 使用步骤 ### 1. 打开云开发 Copilot - 访问[云开发 Copilot](https://tcb.cloud.tencent.com/dev?#/helper/copilot)(需要腾讯云账号) - 或访问[云开发 Copilot 游客版](https://tcb.cloud.tencent.com/copilot) ### 2. 和云开发 Copilot 对话 可以直接和 Copilot 对话,或者点击 @ 召唤更多专业智能体 --- ## AI 生成低代码应用 # AI 生成低代码应用 ```mdx-code-block import AgentCard from "@site/src/components/AgentCard"; ``` ## 功能介绍 :::tip 平台兼容性 AI 生成的低代码应用支持发布到小程序和 web 页面,支持多端访问 ::: ### 根据截图生成应用 上传截图,AI 识别截图中的元素,生成对应的应用 ![](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/45ba40c3-8ad0-4940-a8f7-ec21cb2e62c2.png) ### 根据需求生成应用 输入关键字,AI 生成对应的应用 ![](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/c655c86c-4fa2-41b4-89f7-f8605c9e44b6.png) ### 在当前应用中用 AI 生成区块 除了可以生成应用,也可以在当前页面中生成区块 在应用编辑器中,打开云开发 Copilot ,输入 @ 切换到 AI 生成区块,输入关键字或者上传图片,生成对应的区块 点击生成,可以插入到当前页面中 ![](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/386ea1ef-896b-494e-97f1-e9df1eeee662.png) ## 使用步骤 ### 1. 打开云开发 Copilot - 访问[云开发 Copilot](https://tcb.cloud.tencent.com/dev?#/helper/copilot)(需要腾讯云账号) - 或访问[云开发 Copilot 游客版](https://tcb.cloud.tencent.com/copilot) ### 2. 切换到 AI 生成可视化应用/区块 输入 @ ,选择 AI 生成可视化,输入关键字,点击生成 ### 3. 预览效果并确认生成 在 Copilot 预览窗口中可以看到生成的应用的效果,确认无误后点击确定生成 ### 4. 精调应用 生成完成后,点击进入编辑器,可对应用的功能、界面等进行精细调整。 ### 5. 发布应用 - **发布到小程序**:在编辑器中找到发布设置选项,选择小程序发布渠道。按照提示填写小程序相关信息,如小程序名称、AppID 等,然后点击“发布”按钮,系统将自动打包并上传代码到小程序平台进行审核和发布。 - **发布到 web 页面**:同样在发布设置里选择 web 发布选项,确认后点击“发布”,生成可访问的网址。 --- ## AI 生成低代码组件 # AI 生成低代码组件 ```mdx-code-block import AgentCard from "@site/src/components/AgentCard"; ``` ## 功能介绍 :::warning 平台兼容性 当前 AI 生成的低代码组件仅支持发布到 web 页面 ::: 针对于复杂的业务场景,AI 可以根据用户的需求,自动生成带有逻辑的相应的组件代码,帮助开发者快速实现业务功能。 ### 根据截图生成组件 输入 @ 切换到 AI 生成组件,上传截图,输入基本的要求,AI 识别截图中的元素,生成对应的组件,支持多轮会话进行调整 ![](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/2f1f37aa-8394-4e93-b3d2-cefa55305b27.png) 生成完成后,点击确认生成即可插入到当前页面中,或者创建新的应用 ### 根据需求生成组件 输入 @ 切换到 AI 生成组件,输入关键字,AI 生成对应的组件,支持多轮会话进行调整 生成完成后,点击确认生成即可插入到当前页面中,或者创建新的应用 ![](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/6f625df8-d063-4d3d-8254-1d86ce795e07.png) ### AI 生成排障 有时 AI 生成的组件实现会有问题,可以通过 AI 排障功能,点击预览区域的 AI 排障按钮,AI 会自动进行排障,尝试重新修改代码 ![](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/131b91ff-a63a-45b1-80b1-5afe04b349e8.png) ## 使用步骤 ### 1. 打开云开发 Copilot - 访问[云开发 Copilot](https://tcb.cloud.tencent.com/dev?#/helper/copilot)(需要腾讯云账号) - 或访问[云开发 Copilot 游客版](https://tcb.cloud.tencent.com/copilot) ### 2. 切换到 AI 生成组件 输入 @ ,选择 AI 生成可视化,输入关键字,点击生成 可上传截图,AI 识别截图中的元素,或者输入提示词,生成对应的组件 ### 3. 预览效果并确认生成 在 Copilot 预览窗口中可以看到生成的应用的效果,确认无误后点击确定生成 --- ## AI 编辑组件样式 # AI 编辑组件样式 ```mdx-code-block import AgentCard from "@site/src/components/AgentCard"; ``` ## 功能介绍 :::tip 平台兼容性 AI 编辑样式支持小程序和 web 页面的组件样式编辑 ::: 可以通过 AI 优化低代码组件的样式,无需编写代码,让组件更符合用户需求,提高用户体验。 ![](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/04ed5659-bcbf-4d47-9eb8-ffc09e16486e.png) ## 使用步骤 ### 1. 打开云开发平台的应用编辑器 在[云开发平台可视化开发](https://tcb.cloud.tencent.com/dev?#/lowcode/apps)中,创建应用或者进入已有的应用,选择目标的组件 ### 2. 选中组件并启动 AI 编写 CSS 功能 选中任意组件之后,Copilot 会自动切换到 CSS 编辑模式,点击开启 AI 编写 CSS 功能,即可开始使用 AI 优化样式 ### 3. 预览效果并确认生成 输入要求,点击生成,AI 会根据输入的要求生成样式优化建议,并在组件的预览区域实时显示优化后的效果,可直观看到样式变化,保存后即可生效 --- ## AI 生成数据模型 # AI 生成数据模型 ```mdx-code-block import AgentCard from "@site/src/components/AgentCard"; ``` ## 功能介绍 ### AI 生成数据模型 可以根据用户输入的需求,自动生成对应的数据模型,帮助开发者快速实现业务功能 ![](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/570f1d41-607a-4fdd-8e00-61e415bb547a.png) ## 使用步骤 ### 1. 打开云开发 Copilot - 访问[云开发 Copilot](https://tcb.cloud.tencent.com/dev?#/helper/copilot)(需要腾讯云账号) - 或访问[云开发 Copilot 游客版](https://tcb.cloud.tencent.com/copilot) ### 2. 切换到 AI 生成数据模型 输入 @ ,选择 AI 生成数据模型,输入关键字,点击生成 ### 3. 预览效果并确认生成 在 Copilot 预览窗口中可以看到生成的数据模型的描述信息,确认无误后点击确定生成,即可打开数据模型的创建页面 可以对已经生成的表结构和字段进行修改和调整,然后点击保存,即可生成数据模型 ### 4. 数据模型调试 生成完成后,可以在云开发控制台中查看生成的数据模型,对数据模型进行调试和修改 可参考界面中的查看指引,对数据模型进行增删改查等操作 --- ## AI 生成低代码页面/区块 # AI 生成低代码页面/区块 ```mdx-code-block import AgentCard from "@site/src/components/AgentCard"; ``` ## 功能介绍 能够依据关键字迅速生成小程序/web 页面,操作简单且高效。只需一句话,即可生成可以可视化编辑的页面/区块,该页面支持发布至小程序和网页。 ![](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/80e2e954-18b3-403f-a49e-aad3f43abdc8.png) ## 使用步骤 1. **进入云开发平台的可视化编辑器**:在[云开发平台可视化开发](https://tcb.cloud.tencent.com/dev?#/lowcode/apps)中,创建应用或者进入已有的应用,在添加页面的时候可以选择 AI 生成页面,在当前页面中可以选择 AI 生成区块。 2. **输入需求并生成**:输入对页面或区块的功能、样式等相关描述,如有需要可指定色彩主题等其他细节,然后点击生成按钮。 3. **多轮调整**:在生成后,可以对页面或区块进行多轮的修改和调整。通过对话进行调整,比如修改元素布局、样式、交互逻辑等,以满足特定需求。 4. **添加页面或区块**::生成完毕之后,点击确定即可添加生成的页面或区块。 --- ## AI 生成需求文档 # AI 生成需求文档 ```mdx-code-block import AgentCard from "@site/src/components/AgentCard"; ``` ## 功能介绍 能够根据用户的想法来细化和拆解需求,生成完整的需求文档 ## 使用步骤 ### 1. 打开云开发 Copilot - 访问[云开发 Copilot](https://tcb.cloud.tencent.com/dev?#/helper/copilot)(需要腾讯云账号) - 或访问[云开发 Copilot 游客版](https://tcb.cloud.tencent.com/copilot) ### 2. 切换到 写需求高手 输入 @ ,选择 写需求高手,输入关键字,点击生成 ### 3. 查看生成效果 生成完毕后,可以查看生成的需求提示词和需求,可以根据需求提示词和需求,快速实现你的想法。 --- ## AI 生成云函数 # AI 生成云函数 ```mdx-code-block import AgentCard from "@site/src/components/AgentCard"; ``` ## 功能介绍 ### AI 生成云函数 可以输入关键字,AI 生成对应的云函数代码,帮助开发者快速实现业务功能。 ![](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/04af5c74-30d8-4590-9d26-9d3fc69f5aec.png) ### 云函数调试 生成完成后,可点击云开发 Copilot 中的调试按钮,在云端 IDE 中,可以对生成的云函数代码进行编辑和调试。 ### 云函数部署 生产完成后,点击云开发 Copilot 中“部署”按钮,即可将云函数部署到云开发环境中。 ### 修改云函数代码 可输入提示词让 AI 修改当前的云函数实现。 在云函数列表中,点击云端开发,可以打开现有的云函数,云开发 Copilot 支持对当前的函数代码进行修改。 ## 使用步骤 ### 1. 打开云开发 Copilot - 访问[云开发 Copilot](https://tcb.cloud.tencent.com/dev?#/helper/copilot)(需要腾讯云账号) - 或访问[云开发 Copilot 游客版](https://tcb.cloud.tencent.com/copilot) ### 2. 切换到 AI 生成云函数 输入 @ ,选择 AI 生成云函数,输入关键字,点击生成 ### 3. 确认生成 生成完毕后,可点击“确认生成”按钮,即可在云端 IDE 中打开生成的云函数代码,进行编辑和调试。 如果生成不满意,可以输入新的要求,进行修改。 ### 4. 云函数调试 可点击云开发 Copilot 中的调试按钮,在云端 IDE 中,可以对生成的云函数代码进行编辑和调试。 ### 5. 云函数部署 调试完成后,点击云开发 Copilot 中“部署”按钮,即可将云函数部署到云开发环境中。 --- ## 使用指引 # 使用指引 云开发 Copilot 是云开发推出的一款 AI 开发辅助工具,可以帮助用户快速生成多种类型的应用功能,包括低代码应用、页面、组件、数据模型、CMS 内容等,帮助开发者快速构建自己的小程序、web 等云开发应用。 可以帮助用户加快开发效率,提升开发体验。 ## 如何使用云开发 Copilot ### 开通流程 1. **拥有腾讯云账号** 2. **开通云环境**: 推荐[开通微搭免费体验版](https://console.cloud.tencent.com/lowcode) 或者使用已有的云开发环境 3. **使用云开发 Copilot 功能**: - 访问[云开发 Copilot](https://tcb.cloud.tencent.com/dev?#/helper/copilot)(需要腾讯云账号) - 或访问[云开发 Copilot 游客版](https://tcb.cloud.tencent.com/copilot) (无需登录即可使用云开发 Copilot 部分功能) ## 云开发智能开发功能指引 ```mdx-code-block import AgentList from "@site/src/components/AgentList"; ``` ## 演示视频 云开发 Copilot 可以解答用户使用过程中的问题,也可以帮助用户开发应用/页面/区块/组件等。 通过 AI 在不同阶段的辅助,用户可以在现有的应用/页面/组件中,通过 AI 实现需要的功能,可以和现有的组件混合使用,通过可视化编辑进一步调整和实时预览,大大加快开发效率和持续的业务交付。 ## 社区实践和教程 - [《15 分钟做完一个小程序,腾讯这个工具有点东西》](https://mp.weixin.qq.com/s/IUcYIVNKrwUnxUQ7XwfIIA) - [《教你 5 分钟用 AI 开发一个产品官网(无需编码)》](https://mp.weixin.qq.com/s/hk40eDPHAQ7xaqdjyVLCFA) - [《AI 代码生成太疯狂!不懂编程也能做开发,程序员要失业了?》](https://mp.weixin.qq.com/s/-8sguTcmwKHEUq-m2qUz1A) - [🎥**视频**:截图生成提示词和应用功能演示](https://www.bilibili.com/video/BV1bDBaYkEqQ/?share_source=copy_web&vd_source=068decbd00a3d00ff8662b6a358e5e1e) --- ## AI 识图 # AI 识图 ```mdx-code-block import AgentCard from "@site/src/components/AgentCard"; ``` ## 功能介绍 ## 截图生成提示词和需求 你可以上传一张截图(设计稿、参考的网站截图等),云开发 Copilot 会自动生成相关的需求提示词。 再配合云开发 Copilot 或者其他 AI 编程助手,可以快速把截图变成代码,快速实现你的想法。 ## 使用步骤 ### 1. 打开云开发 Copilot - 访问[云开发 Copilot](https://tcb.cloud.tencent.com/dev?#/helper/copilot)(需要腾讯云账号) - 或访问[云开发 Copilot 游客版](https://tcb.cloud.tencent.com/copilot) ### 2. 切换到 AI 识图 输入 @ ,选择 AI 识图,上传图片,或者粘贴图片,输入关键字,点击生成 ### 3. 查看生成效果 生成完毕后,可以查看生成的需求提示词和需求,可以根据需求提示词和需求,快速实现你的想法。 --- ## Post Transport # Post Transport :::tip 在阅读本篇文章前,建议先熟悉 [MCP(Model Context Protocol)的基本概念](../introduce)。 ::: ## 什么是 Transport Transport 是 MCP Client 与 MCP Server 依赖的通信层。MCP Client 能向 MCP Server 请求上下文,MCP Server 能向 MCP Client 发送响应提供上下文,而 Transport 则负责这二者之间的通信。 **MCP Transport 不是具体实现,而是一个接口。**目前官方有两种实现: - Stdio Transport:通过标准输入输出进行通信,适用于本地的 MCP Server - SSE Transport:通过 SSE(Server Sent Event)进行通信,适用于远程的 MCP Server 我们根据云开发特定的场景,自定义实现了 Transport 接口,基于 HTTP Post 请求。我们称之为 Post Transport。 ## 什么是 Post Transport 官方 SDK 提供的 SSE Transport 并不是很适合在云函数上构建 MCP Server。传统的云函数是无状态的,而 SSE Transport 是有状态的。 因此,我们实现了无状态的基于 HTTP Post 进行通信的 Transport,即 Post Transport。 Post Transport 适合在云函数场景构建**本身也是无状态**的 MCP Server。 > 当 MCP Server 也是有状态时,就需要使用 SSE Transport 了。假设我们要构建一个 puppeteer MCP Server,它通过 [puppeteer](https://pptr.dev/) 提供两个工具: > > 1. 导航到某个网址 > 2. 在当前网址截图 > > 很明显,导航到某个网址会影响截图的结果——导航到百度后再截图和导航到知乎再截图,会得到不同的结果。 > 我们称这样的 MCP Server 为有状态的。 > > **理解服务状态性的关键:** > > - 有状态服务:请求之间存在“记忆”依赖,后续请求的处理结果受先前请求的影响。如同电话客服,需要记住整个对话上下文才能有效响应。 > - 无状态服务:每个请求都是独立事件,处理结果仅取决于当前请求内容和外部共享数据。如同自动售货机,每次投币购买都是独立交易。 ### 为什么 SSE Transport 不适合在云函数场景使用 使用 SSE Transport 时建立链接过程如下: 1. Client 向 Server 的服务 URL(假定为 `/sse`)发送 HTTP GET 请求,Server 接收到请求后,建立起 SSE 长链接。建立链接后,Server 所有的消息都会从这个 SSE 长链接发送给 Client 2. Server 通过这个 SSE 长链接发送一条消息,其中包含了另一个 URL(假定为`/messages`)。后续 Client 向 Server 发送的消息都会从这个 URL 通过 HTTP Post 发送,以此区分开从 `/sse` 发起的建立链接的请求 3. 后续 Client 对 Server 发送的具体请求,如请求工具列表、请求调用工具等都会从 `/messages` 发送出去,但是 Server 的响应内容都从 SSE 链接返回,举个请求工具列表的例子: 1. Client 从 `/sse` 发一个 HTTP Post 请求给 Server 2. Server 接收到后,返回 `"Accepted"` 字符串,无其他实际的响应内容 3. Server 从一开始建立的 SSE 链接中返回具体的工具列表 ```mermaid sequenceDiagram Client->>+Server /sse: 建立链接 Server /sse->>-Client: URL: /messages Client->>+Server /messages: 具体请求.e.g list tools Server /messages->>-Client: "Accepted" Server /sse->>Client: 对应请求返回的数据 ``` 为什么说这是个有状态的 Transport 呢?就是因为 Server 在 `/messages` 接收到的消息,需要从 `/sse` 建立的长链接中返回。 具体到云函数场景,**假设我们需要且能够在云函数中使用 SSE Transport**,会有这样的一个流程: 1. 第一次调用 A,Client 和 Server 建立起了长链接 2. 第二次调用 B,Client 向 Server 请求工具列表,**此时需要某种机制,能让 Server 在调用 A 中建立的长链接返回消息** 这在云函数中是非常少见的场景。一般来说,我们要求云函数的实现为无状态的,幂等的。 --- ## Cloudbase MCP Deploy 按钮 import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import CloudbaseMCPDeployButtonGenerator from '@site/src/components/CloudbaseMCPDeployButtonGenerator'; # Cloudbase MCP Deploy 按钮 CloudBase MCP Deploy 按钮允许用户能够快速完成云开发平台的 MCP Server 创建流程,一键部署以 npx/uvx 方式运行的 MCP Server 。 ## 生成您的 Cloudbase MCP Deploy 按钮 您可以使用下面的生成器创建您的 Cloudbase MCP Deploy 按钮: ## 示例 使用 Cloudbase MCP Deploy 按钮,能让用户点击后跳转至云开发平台,并且一键部署您的 MCP Server 。 下面是一个完整的代码片段示例,能够生成一个 Cloudbase MCP Deploy 按钮: ```markdown [![Deploy MCP Server with CloudBase](https://qcloudimg.tencent-cloud.cn/raw/fdfede7f163bddfef9b826bbc94a1f32/cloudbase-deploy-button.svg)](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp&show-add-custom-mcp-server-modal=1&custom-mcp-server-json-config=%7B%22mcpServers%22%3A%7B%22everything%22%3A%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40modelcontextprotocol%2Fserver-everything%22%5D%7D%7D%7D&custom-mcp-server-title=title&custom-mcp-server-name=name&custom-mcp-server-type=npx) ``` ```html ``` ```plaintext https://tcb.cloud.tencent.com/dev#/ai?tab=mcp&show-add-custom-mcp-server-modal=1&custom-mcp-server-json-config=%7B%22mcpServers%22%3A%7B%22everything%22%3A%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40modelcontextprotocol%2Fserver-everything%22%5D%7D%7D%7D&custom-mcp-server-title=title&custom-mcp-server-name=name&custom-mcp-server-type=npx ``` ### 效果预览 点击按钮后,用户将会跳转到云开发平台的下图所示页面,并自动填充好表单: [![Deploy MCP Server with CloudBase](https://qcloudimg.tencent-cloud.cn/raw/fdfede7f163bddfef9b826bbc94a1f32/cloudbase-deploy-button.svg)](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp&show-add-custom-mcp-server-modal=1&custom-mcp-server-json-config=%7B%22mcpServers%22%3A%7B%22everything%22%3A%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40modelcontextprotocol%2Fserver-everything%22%5D%7D%7D%7D&custom-mcp-server-title=title&custom-mcp-server-name=name&custom-mcp-server-type=npx) ![Deploy 按钮示例](./custom-mcp.png) --- ## @cloudbase/mcp-transformer # @cloudbase/mcp-transformer 云开发 MCP 协议转换工具,支持多种传输协议转换模式。 安装到全局: ```shell npm i -g @cloudbase/mcp-transformer ``` ## 命令列表 ### streamableToStdio - Streamable HTTP 转 STDIO ```shell USAGE npx @cloudbase/mcp-transformer streamableToStdio (--url value) [--token value] [--header value]... FLAGS --url POST 服务器 URL [必填] [--token] 认证令牌,自动添加到 Authorization 请求头 [--header]... 自定义请求头(格式:"Header: Value") -h --help 显示帮助信息 示例: npx @cloudbase/mcp-transformer streamableToStdio --url https://api.example.com/messages \ --token "Bearer xyz" \ --header "X-Request-ID: 123" ``` ### postToStdio - POST 转 STDIO ```shell USAGE npx @cloudbase/mcp-transformer postToStdio (--url value) [--token value] [--header value]... FLAGS --url POST 服务器 URL [必填] [--token] 认证令牌,自动添加到 Authorization 请求头 [--header]... 自定义请求头(格式:"Header: Value") -h --help 显示帮助信息 示例: npx @cloudbase/mcp-transformer postToStdio --url https://api.example.com/messages \ --token "Bearer xyz" \ --header "X-Request-ID: 123" ``` ### sseToStdio - SSE 转 STDIO ```shell USAGE npx @cloudbase/mcp-transformer sseToStdio (--url value) [--token value] [--header value]... FLAGS --url SSE 服务器 URL [必填] [--token] 认证令牌 [--header]... 自定义请求头 -h --help 显示帮助信息 示例: npx @cloudbase/mcp-transformer sseToStdio --url https://sse.example.com/events \ --header "Cache-Control: no-cache" ``` ### stdioToStreamable - STDIO 转 Streamable HTTP ```shell USAGE npx @cloudbase/mcp-transformer stdioToStreamable (--stdioCmd value) [--verifyAccess] [--port value] [--enableCors] [--stateful] [--sessionTimeout value] [--streamableHTTPPath value] FLAGS --stdioCmd STDIO 服务启动命令 [必填] [--verifyAccess/--noVerifyAccess] 验证访问令牌 [default = true] [--port] 服务端口 [default = 3000] [--enableCors] 启用 CORS [default = false] [--stateful] 启用有状态会话 [default = false] [--sessionTimeout] 会话超时时间(毫秒)。仅支持有状态模式,如不设置则仅在客户端明确终止时删除会话 [--streamableHTTPPath] Streamable HTTP 端点路径 [default = /messages] -h --help 显示帮助信息 示例: npx @cloudbase/mcp-transformer stdioToStreamable \ --stdioCmd "node server.js" \ --port 8080 \ --enableCors \ --stateful \ --sessionTimeout 300000 ``` ### stdioToCloudrunSse - STDIO 转云托管 SSE ```shell USAGE npx @cloudbase/mcp-transformer stdioToCloudrunSse (--stdioCmd value) [--verifyAccess] [--port value] [--ssePath value] [--enableCors] FLAGS --stdioCmd STDIO 服务启动命令 [必填] [--verifyAccess] 验证访问令牌 [default = true] [--port] 服务端口 [default = 3000] [--ssePath] SSE 端点路径 [default = /messages] [--enableCors] 启用 CORS [default = false] -h --help 显示帮助信息 示例: npx @cloudbase/mcp-transformer stdioToCloudrunSse \ --stdioCmd "python server.py" \ --port 8080 \ --enableCors ``` ### stdioToCloudrun - STDIO 转云托管 POST + SSE ```shell USAGE npx @cloudbase/mcp-transformer stdioToCloudrun (--stdioCmd value) [--verifyAccess] [--port value] [--enableCors] [--sseRoute local] FLAGS --stdioCmd STDIO 服务启动命令 [必填] [--verifyAccess] 验证访问令牌 [default = true] [--port] 服务端口 [default = 3000] [--enableCors] 启用 CORS [default = false] [--sseRoute] SSE 路由设置(本地开发使用 'local') -h --help 显示帮助信息 示例(本地开发): npx @cloudbase/mcp-transformer stdioToCloudrun \ --stdioCmd "node ./server.js" \ --sseRoute local \ --noVerifyAccess ``` --- ## @cloudbase/mcp # @cloudbase/mcp `@cloudbase/mcp` 提供了一系列构建 MCP 的工具。包括 - Cloudbase 函数型云托管 支持。提供了针对函数型云托管 的框架,专注 MCP Server 开发,快速接入部署至函数型云托管 ## 安装 ```shell npm i @cloudbase/mcp ``` ## 使用示例 ### 在函数型云托管上构建 MCP Server 此代码会默认在 `/messages` 提供 MCP Server 服务。 ```ts import { StreamableHTTPMCPServerRunner } from "@cloudbase/mcp/cloudrun"; import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { z } from "zod"; const createServer = () => { const server = new McpServer({ name: "hello-world", version: "1.0.0", }) server.registerTool("getUserAge", { description: "查询用户的年龄", inputSchema: { userName: z.string().describe("用户名"), }, outputSchema: { age: z.number().describe("年龄"), }, }, ({userName}) => { let structuredContent if (userName === "张三") { structuredContent = { age: 18, }; } else if (userName === "李四") { structuredContent = { age: 20, }; } else { throw new Error("未找到该用户的年龄"); } return { structuredContent, content: [ { type: "text", text: JSON.stringify(structuredContent), } ] } }) return { server }; } export const main = (event, context) => { return StreamableHTTPMCPServerRunner.run(event, context,createServer) } ``` ## API Reference ### StreamableHTTPMCPServerRunner 在函数型云托管 中运行 MCP Server 的工具类,提供了以下功能: - 路由判断 - 鉴权 - 自动处理 HTTP 请求/响应 - Streamable HTTP Transport 支持 可以用几行代码在函数型云托管 上运行 MCP Server: ```ts // 函数型云托管 // ...省略 createServer 函数实现 export const main = (event, context) => StreamableHTTPMCPServerRunner.run(event, context, createServer) ``` 上述代码会在 `/messages` 提供 MCP Server 服务,默认根据从 HTTP Header 中读取的云开发 accessToken 进行拦截,只允许来自 apiKey 和管理员身份的调用。可以传入特定参数,修改默认行为: ```ts // 函数型云托管 // ...省略 createServer 函数实现 const runner = new StreamableHTTPMCPServerRunner(createServer, { verifyAccess: false // 控制是否进行鉴权拦截 }); export const main = (event, context) => runner.run(event, context); ``` #### 导入 ```ts import { StreamableHTTPMCPServerRunner } from '@cloudbase/mcp/cloudrun'; ``` #### `static run()` `StreamableHTTPMCPServerRunner` 上的静态方法,按默认配置在函数型云托管 上运行 MCP Server。 ```ts // 函数型云托管 // ...省略 createServer 函数实现 export const main = (event, context) => StreamableHTTPMCPServerRunner.run(event, context, createServer) ``` ##### 参数 | 名称 | 类型 | 必需 | 描述 | | --- | --- | --- | --- | | event | | 是 | 将函数型云托管 接收的 event 参数传入即可 | | context | | 是 | 将函数型云托管 接收的 context 参数传入即可 | | createServer | | 是 | 返回 MCP Server 的实例的函数 | #### `new()` 创建一个 `MCPServerRunner` 实例,可传入参数控制 `run()` 方法的行为。 ```ts // ...省略 createServer 函数实现 const runner = new MCPServerRunner(createServer, { verifyAccess: true // 控制是否进行鉴权拦截 }); ``` ##### 参数 | 名称 | 类型 | 必需 | 描述 | | --- | --- | --- | --- | | createServer | function | 是 | 创建并返回 MCP Server 实例的函数 | | prop | `object` | 否 | 控制 `MCPServerRunner` 的行为 | | prop.verifyAccess | `boolean` | 否 | 控制是否进行鉴权拦截,若为 `true`,则只允许来自 apiKey 和管理员身份的调用 | | prop.sessionIdGenerator | `() => string` | 否 | sessionId 生成函数,若传入则会建立有状态的服务 | | prop.sessionTimeout | `number` | 否 | sessionId 过期时间(ms),此参数仅在有状态的服务中生效 | #### `run()` 根据 `MCPServerRunner` 实例上的参数配置在函数型云托管 上运行 MCP Server。 ```ts // 函数型云托管 // ...省略创建 MCP Server 实例过程 const runner = new MCPServerRunner(createServer, { verifyAccess: true // 控制是否进行鉴权拦截 }); export const main = (event, context) => runner.run(event, context); ``` ##### 参数 | 名称 | 类型 | 必需 | 描述 | | --- | --- | --- | --- | | event | | 是 | 将函数型云托管 接收的 event 参数传入即可 | | context | | 是 | 将函数型云托管 接收的 context 参数传入即可 | ### MCPServerRunner 在函数型云托管 中运行 MCP Server 的工具类,提供了以下功能: - 路由判断 - 鉴权 - 自动处理 HTTP 请求/响应 - SSE Transport 支持 可以用几行代码在函数型云托管 上运行 MCP Server: ```ts // 函数型云托管 // ...省略 createServer 函数实现 export const main = (event, context) => MCPServerRunner.run(event, context, createServer) ``` 上述代码会在 `/messages` 提供 MCP Server 服务,默认根据从 HTTP Header 中读取的云开发 accessToken 进行拦截,只允许来自 apiKey 和管理员身份的调用。可以传入特定参数,修改默认行为: ```ts // 函数型云托管 // ...省略 createServer 函数实现 const runner = new MCPServerRunner(createServer, { verifyAccess: false // 控制是否进行鉴权拦截 }); export const main = (event, context) => runner.run(event, context); ``` #### 导入 ```ts import { MCPServerRunner } from '@cloudbase/mcp/cloudrun'; ``` #### `static run()` `MCPServerRunner` 上的静态方法,按默认配置在函数型云托管 上运行 MCP Server。 ```ts // 函数型云托管 // ...省略 createServer 函数实现 export const main = (event, context) => MCPServerRunner.run(event, context, createServer) ``` ##### 参数 | 名称 | 类型 | 必需 | 描述 | | --- | --- | --- | --- | | event | | 是 | 将函数型云托管 接收的 event 参数传入即可 | | context | | 是 | 将函数型云托管 接收的 context 参数传入即可 | | createServer | | 是 | 返回 MCP Server 的实例的函数 | #### `new()` 创建一个 `MCPServerRunner` 实例,可传入参数控制 `run()` 方法的行为。 ```ts // ...省略 createServer 函数实现 const runner = new MCPServerRunner(createServer, { verifyAccess: true // 控制是否进行鉴权拦截 }); ``` ##### 参数 | 名称 | 类型 | 必需 | 描述 | | --- | --- | --- | --- | | createServer | function | 是 | 创建并返回MCP Server实例的函数 | | prop | `object` | 否 | 控制 `MCPServerRunner` 的行为 | | prop.verifyAccess | `boolean` | 否 | 控制是否进行鉴权拦截,若为 `true`,则只允许来自 apiKey 和管理员身份的调用 | #### `run()` 根据 `MCPServerRunner` 实例上的参数配置在函数型云托管 上运行 MCP Server。 ```ts // 函数型云托管 // ...省略创建 MCP Server 实例过程 const runner = new MCPServerRunner(createServer, { verifyAccess: true // 控制是否进行鉴权拦截 }); export const main = (event, context) => runner.run(event, context); ``` ##### 参数 | 名称 | 类型 | 必需 | 描述 | | --- | --- | --- | --- | | event | | 是 | 将函数型云托管 接收的 event 参数传入即可 | | context | | 是 | 将函数型云托管 接收的 context 参数传入即可 | ### CloudbaseMcpServer 【deprecated】 :::danger 【重要】该类已废弃。 `CloudbaseMcpServer` 相比于早期的 MCP 官方 SDK ,额外提供了 outputSchema 的支持。目前 MCP 官方 SDK 已经提供了对 outputSchema 的支持,我们推荐直接使用 MCP 官方 SDK。 ::: Cloudbase 扩展的 MCP Server。使用此类可以快速构建一个 MCP Server 实例。此类基于 Claude MCP SDK 中的 [McpServer](https://github.com/modelcontextprotocol/typescript-sdk?tab=readme-ov-file#server) 进行扩展,为 `tool()` 方法新增了链式调用的使用形式,其他能力保持不变 #### 导入 ```ts import { CloudbaseMcpServer } from "@cloudbase/mcp/server"; ``` #### tool() 在此 server 上创建一个工具。此方法有多种方式调用。 ##### 推荐用法:链式调用 我们推荐使用链式调用:通过调用 `tool()` 且***只传入 1 个*** `name` 参数触发链式调用。可连续调用 `description()`、`inputSchema()`、`outputSchema()`、`formatter()` 来为工具添加不同的属性,最后通过调用 `.create()` 传入该工具对应的函数实现,完成该工具的创建。 - 在 `tool()` 和 `create()` 之间出现的 `description()`、`inputSchema()`、`outputSchema()`、`formatter()` 均为可选,可以省略任一调用 - `description()`、`inputSchema()`、`outputSchema()`、`formatter()` 的出现顺序是任意的,可按任意的顺序进行调用 - 需要保证链式调用以 `tool()` 开始、以 `create()` 结束 ```ts // ...省略创建 server 实例的过程 server // 只传入一个 `name` 参数触发链式调用 .tool('add') // 为工具添加参数 .description('将两个数字相加') // 为工具添加入参 schema 说明 .inputSchema({ a: z.number({ description: '被加数', }), b: z.number({ description: '加数', }), }) // 为工具添加出参 schema 说明 .outputSchema({ result: z.number({ description: '两个数字相加的结果', }), }) // 为工具添加出参 formatter .formatter(({ a, b }, { result }) => { return { content: [ { type: 'text', text: `${a} + ${b} = ${result}`, }, ], }; }) // 最终传入实现函数,完成工具创建 .create(({ a, b }) => ({ result: a + b })); ``` ##### 其他用法 注册一个无参数工具: ```ts // 注册一个无参数工具 server.tool('sayHello', () => { return { content: [{ type: 'text', text: 'Hello World' }] } }) ``` 注册一个带描述的无参数工具: ```ts // 注册一个带描述的无参数工具 server.tool('sayHello', '返回一个简单的问候语', () => { return { content: [{ type: 'text', text: 'Hello World' }] } }) ``` 注册一个带参数的工具: ```ts // 注册一个带参数的工具 server.tool('add', { a: z.number(), b: z.number() }, ({ a, b }) => { return { result: a + b } }) ``` 注册一个带描述和参数的工具: ```ts // 注册一个带描述和参数的工具 server.tool('add', '将两个数字相加', { a: z.number(), b: z.number() }, ({ a, b }) => { return { result: a + b } }) ``` ### PostClientTransport 【deprecated】 :::danger 【重要】该类已废弃。 `PostClientTransport` 相比于早期的 MCP 官方 SDK ,对无状态 MCP Server 的支持更为友好。目前 MCP 官方 SDK 已经提供了 Streamable HTTP Transport ,无状态和有状态的 MCP Server 都能使用该 Transport 类型进行构建。对于无状态的服务,我们推荐直接使用 Streamable HTTP Transport 。 ::: MCP Client 使用的 Post Transport。 #### 导入 ```ts import { PostClientTransport } from '@cloudbase/mcp/transport/client/post'; ``` #### `new()` 创建 `PostClientTransport` 实例,可传入第二个参数 `opts` 控制网络请求行为。 ```ts const transport = new PostClientTransport(new URL("https://your-url"), { requestInit: { headers: { Authorization: "Bearer ", } } }) // 省略创建 MCP Client 过程 await client.connect(transport); ``` ##### 参数 | 名称 | 类型 | 必需 | 描述 | | --- | --- | --- | --- | | url | `URL` | 是 | 指向 MCP Server 的 url | | opts | `PostClientTransportOptions` | 否 | | | opts.requestInit | `RequestInit` | 否 | 发起网络请求时携带的参数,当 PostClientTransport 发送网络请求时,会携带上传入的参数。可用来传入鉴权请求头等。 | ### PostServerTransport 【deprecated】 :::danger 【重要】该类已废弃。 `PostServerTransport` 相比于早期的 MCP 官方 SDK ,对无状态 MCP Server 的支持更为友好。目前 MCP 官方 SDK 已经提供了 Streamable HTTP Transport ,无状态和有状态的 MCP Server 都能使用该 Transport 类型进行构建。对于无状态的服务,我们推荐直接使用 Streamable HTTP Transport 。 ::: MCP Server 使用的 Post Transport。 ***在函数型云托管 场景下,无需直接使用 `PostServerTransport`,推荐直接使用 `CloudbaseMcpServer`,只需要关注 MCP Server 的实现。*** 在其他平台/环境下,可按需使用此类构建基于 Post Transport 的 MCP Server。 #### 导入 ```ts import { PostServerTransport } from '@cloudbase/mcp/transport/server/post'; ``` #### `new()` 创建 `PostServerTransport` 实例。 ```ts const transport = new PostServerTransport(); ``` #### `handleMessage(message: JSONRPCMessage)` 处理客户端发送过来的 JSON RPC 消息。当服务器接收到客户端用 HTTP 请求发送的 JSON RPC 消息时,需要调用此方法进行处理。该方法可能会返回一个 JSON RPC 消息,此时调用者需要将结果作为 HTTP 响应体返回给客户端。 ```ts // 函数型云托管 export const main = async (context, event) => { // ...省略判断路由、HTTP Method 等过程 const transport = new PostServerTransport(); // ...省略创建 MCP Server 实例过程 server.connect(transport); // ...省略判断 event 是否为合法 JSON RPC 消息过程 return server.handleMessage(event); } ``` ##### 参数 | 名称 | 类型 | 必需 | 描述 | | --- | --- | --- | --- | | message | `JSONRPCMessage` | 是 | 接收到的 JSON RPC 消息 | --- ## 基于模板开发 # 基于模板开发 我们提供了一个基本的 MCP Server 模板,包含了一个完整的 MCP Server 项目。可以以此项目为基础进行修改,开发您自己的 MCP Server。 本文将会介绍如何使用此项目代码进行本地开发调试以及部署。 [点击此处下载项目代码](https://tcb.cloud.tencent.com/cloud-run-function-template/cloudrun-mcp-basic.zip?v=2025) ## 本地开发调试 ### 安装依赖 ```shell npm i ``` ### 登录命令行 `@cloudbase/cli` 需要登录后才能使用,使用云开发账号登录: ```shell npm run login ``` ### 环境变量 将 `.env.template` 更名为 `.env.development` ,该文件定义了环境变量: - `MCP_SSE_ROUTE=LOCAL`:设置后可启用本地 SSE 服务,将 MCP Inspector/MCP Host(如 Cursor)连接至本地 MCP Server - `SKIP_VERIFY_ACCESS=true`:设置后可跳过 token 校验。原有 token 校验将只允许来自 API Key 和超管身份的 token 调用 - `CLOUDBASE_ENVIRONMENT=your-env-id`:在云托管线上环境中,上下文里包含了云开发环境 id。在本地开发时,我们通过设置该环境变量来提供环境 id。请设置一个当前登录账号下的环境 id :::tip 设置 `MCP_SSE_ROUTE`、`SKIP_VERIFY_ACCESS` 这两个环境变量有助于我们在本地进行调试,但不建议在线上生产环境设置。 ::: ### 启动本地 MCP Server 服务 ```shell npm run dev ``` 启动后,将会在 提供服务。 修改代码,即可触发重新编译并重启服务。 ### 启动图形界面调试 运行 MCP Inspector: ```shell npx @cloudbase/mcp-inspector ``` 前往 进行调试。 1. 在左侧选择 `POST` 或 `SSE` 类型,并填入 `URL` 为 `http://localhost:3000/messages` 2. 在左侧点击 `Connect` 3. 在 `Tools` tab 下点击 `List Tools` 展示工具列表 4. 选择任一工具进行调用 ## 部署至云托管 ### 构建 ```shell npm run build ``` ### 部署 该 MCP Server 能够直接部署至云托管,但要在云开发 Agent 中使用,需要在控制台先创建一个 MCP Server,再覆盖其云托管服务。 首先,前往[云开发平台](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp)创建一个 MCP Server。 创建完成后,运行 cli 部署命令,填入对应的 MCP 标识。 ```shell npm run deploy ``` 部署后,即可阅读以下文档使用 MCP Server 了: - [在云开发 Agent 中使用](../use/agent) - [在 MCP Host 中使用](../use/mcp-host) - [通过 SDK 接入](../use/sdk) --- ## 开发第一个 MCP Server # 开发第一个 MCP Server > 推荐使用 Node.js 18 以上的版本 本文将逐步说明如何在云开发平台上开发一个 MCP Server,包含以下几个步骤: 1. 用模板创建出 MCP Server 云托管服务 2. 使用云开发 MCP 框架开发 MCP Server 3. 使用图形界面本地调试 MCP Server 4. 部署至线上,覆盖原有云托管服务 5. 在 Agent 中使用 MCP Server ## 创建空白 MCP Server 前往 [云开发平台](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp) 创建一个空白 MCP Server,设置标识为 `first-mcp`。 > 该步骤会自动创建一个云托管服务承载 MCP Server,在后文中我们将会自己开发一个 MCP Server 并覆盖该云托管服务。 ## 准备代码 我们提供了一个基本的 MCP Server 模板,包含了一个完整的 MCP Server 项目。可以以此项目为基础进行修改,开发您自己的 MCP Server。 本文将会介绍如何使用此项目代码进行本地开发调试以及部署。 [点击此处下载项目代码](https://tcb.cloud.tencent.com/cloud-run-function-template/cloudrun-mcp-basic.zip?v=2025) ## 安装依赖 下载项目代码,解压后进入项目目录,通过命令行执行如下命令,安装依赖: ```shell npm i ``` ## 为 MCP Server 添加第一个工具 修改 `src/server.ts` 中的实现,实现一个获取用户访问信息的工具,该工具会返回最近 count 条用户访问信息。 也可以使用模板自带的工具,直接进入下一步。 ```ts import { ContextInjected, TcbExtendedContext } from '@cloudbase/functions-typings'; import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import tcb from '@cloudbase/node-sdk'; import { z } from 'zod'; export function createServer(context: ContextInjected) { const server = new McpServer( { name: 'Basic Server', version: '1.0.0', }, { capabilities: { tools: {} } }, ); const env = context.extendedContext?.envId || process.env.CLOUDBASE_ENVIRONMENT; // 本地开发从环境变量读 const secretId = context.extendedContext?.tmpSecret?.secretId; const secretKey = context.extendedContext?.tmpSecret?.secretKey; const sessionToken = context.extendedContext?.tmpSecret?.token; // 创建 Cloudbase Node sdk 实例 const app = tcb.init({ env, secretId, secretKey, sessionToken, }); server.registerTool( 'getUserVisitInfo', { description: '获取最新的用户访问信息', // 工具的入参 inputSchema: { count: z.number().describe('获取最近 {count} 条用户访问信息'), }, // 工具的出参 outputSchema: { total: z.number().describe('数据模型中总共的用户访问信息数量'), }, }, async ({ count }) => { const res = await app.models.sys_user_dau.list({ pageSize: count, getCount: true, orderBy: [ { visit_time: 'desc', }, ], }); const structuredContent = { total: res.data.total, records: res.data.records.map((x) => ({ device: x.device, visitTime: x.visit_time, })), }; return { content: [ { type: 'text', text: JSON.stringify(structuredContent), }, ], structuredContent, }; }, ); // todo // 可以添加更多工具 return { server }; } ``` ## 本地调试 MCP Server ### 添加环境变量文件 新建一个 `.env.development` 文件,填入以下内容: ```shell SKIP_VERIFY_ACCESS=true ``` 该文件定义了环境变量: - `SKIP_VERIFY_ACCESS=true`:设置后可跳过 token 校验。原有 token 校验将只允许来自 API Key 和超管身份的 token 调用 :::tip 设置 `SKIP_VERIFY_ACCESS` 这环境变量有助于我们在本地进行调试,但不建议在线上生产环境设置。 ::: ### 启动本地 MCP Server ```shell npm run login # 登录云开发 npm run dev ``` 启动后,将会在 提供服务。 修改代码,即可触发重新编译并重启服务。 ### 启动图形界面调试 开启另一个终端,启动 `@modelcontextprotocol/inspector`: ```shell npx -y @modelcontextprotocol/inspector ``` 根据终端输出,访问调试地址,即可看到调试页面了。 1. 在左侧选择 `Streamable HTTP` 类型,并填入 `URL` 为 `http://localhost:3000/messages` 2. 在左侧点击 `Connect` 3. 在 `Tools` tab 下点击 `List Tools` 展示工具列表 4. 选择任一工具进行调用 ## 构建 开发调试完成后,在项目根目录运行构建命令: ```shell npm run build ``` ## 部署 构建完成后,运行部署命令: ```shell npm run login npm run deploy ``` 选择环境后,服务名称输入前面创建 MCP 服务时候指定的服务标识,例如 `first-mcp`。 ## 使用线上的 MCP Server 部署后,即可阅读以下文档使用 MCP Server 了: - [在云开发 Agent 中使用](../use/agent) - [在 MCP Host 中使用](../use/mcp-host) - [通过 SDK 接入](../use/sdk) ## 问题排查 ### 本地调试时,MCP Server 无法连接 检查本地环境变量是否正确设置,检查本地端口是否被占用。 可以在 `inspector` 界面中开启 F12 打开浏览器的调试工具查看网络请求 查看类似 `http://localhost:6277/mcp?url=https%3A%2F%2Flowcode-2gp2855c5ce22e35.api.tcloudbasegateway.com%2Fv1%2Fcloudrun%2Fmcp-kuaidi100-qt03oc%2Fmessages&transportType=streamable-http` 这个请求返回的响应,一般如果连接不成功,这里都会有对应的错误信息 --- ## 通用 MCP Server # 通用 MCP Server :::tip 本文适用于托管任意通用的本地运行的 MCP Server 。 对于以 npx/uvx 方式运行的 MCP Server ,云开发平台提供了一键托管的能力,详情可以阅读 [托管现有的 MCP Server / 以 npx/uvx 运行的 MCP Server](./npx-uvx-mcp) 。 ::: ## 介绍 如果你想将只支持本地运行的 MCP Server 部署到云开发,来提供远程 MCP 服务,可以使用云开发托管本地 MCP Server 的功能。 托管后的 MCP Server 具备以下能力: - 支持远程 Streamable HTTP 访问 - 支持 ApiKey 认证,保护 MCP Server 代码和密钥信息的安全 - 支持在 Cursor 等支持 MCP 的客户端访问 - 支持在 云开发 Agent 使用,构建复杂的自动化 Agent - 可[提交上架到云开发 MCP 市场](./publish.md),审核通过后即可让更多人来部署使用 支持托管的 MCP Server 需要满足以下条件: - 不限语言/框架,Java/Python/GoLang/PHP 均可 - 支持 MCP 的 Stdio Transport 我们会采用云托管服务来运行你的 MCP Server,因此需要你的 MCP Server 支持 Stdio Transport,即支持通过 Stdio 传输数据。 在容器内网我们会通过 `cloudbase-mcp-transformer` 工具将本地 MCP Server 的 Stdio 转换为远程 MCP 服务,从而实现远程访问,同时支持鉴权/认证/一个服务支持多会话/一个服务支持多实例。 ```mermaid graph TD subgraph 云托管环境 B[Java/Go/Python/Node.js MCP Server] -->|Stdio 通信| C end subgraph 开放 API C[cloudbase-mcp-transformer] -->|HTTP| D[认证鉴权模块] D --> F[HTTP接入和流量控制] end subgraph 客户端访问层 F -->|SSE 流式响应| G[Cursor 客户端] F -->|SSE 流式响应| H[云开发 Agent] F -->|SDK 接入| I[第三方应用] end style C fill:#e1f5fe,stroke:#039be5 style D fill:#f0f4c3,stroke:#afb42b style F fill:#ffcdd2,stroke:#e53935 classDef security fill:#f0f4c3,stroke:#afb42b; classDef session fill:#c8e6c9,stroke:#43a047; classDef http fill:#ffcdd2,stroke:#e53935; classDef client fill:#dcedc8,stroke:#689f38; ``` 本篇文章将会使用社区中的 [MongoDB MCP](https://github.com/QuantGeekDev/mongo-mcp) 进行演示 最终代码地址:[托管本地 MCP 到云开发服务端示例项目](https://cnb.cool/cloudbase/mcp-tpl) ## 准备工作 1. 在开始前请确保已经[开通云开发环境](/quick-start/create-env) 2. 本地具有 Node.js 环境(建议使用 Node.js LTS 版本),用于运行 `@cloudbase/cli` 命令来部署云托管服务 ## 创建空白 MCP Server 在[云开发 AI+](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp) 中创建一个 MCP Server,选择**空白模板**, 名称和服务名可以根据自己需要进行命名 ## 准备代码 准备一个本地 MCP Server,例如支持 npx、uv 等命令运行的 MCP Server,本文将使用 [MongoDB MCP](https://github.com/QuantGeekDev/mongo-mcp) 进行演示 可以下载 [托管本地 MCP 到云开发服务端示例项目](https://cnb.cool/cloudbase/mcp-tpl) 来进行测试 其中包含 3 个文件 - `Dockerfile`:云开发 MCP 服务 Dockerfile 文件 - `DOC.md`:MCP 服务的展示文档(选填,需要上架云开发 MCP 时必填) - `mcp-meta.json`: 云开发 MCP 服务的配置文件(选填,需要上架云开发 MCP 时必填) ## 编写 Dockerfile Dockerfile 内容如下: ```dockerfile # 使用 Node.js 官方 Alpine 镜像作为基础 FROM node:20-alpine # 配置腾讯云镜像源 RUN npm config set registry https://mirrors.cloud.tencent.com/npm/ \ && yarn config set registry https://mirrors.cloud.tencent.com/npm/ # 配置 Alpine 国内镜像源 RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.tencent.com/g' /etc/apk/repositories # 安装 Python(自动创建 python/pip 链接) RUN apk update \ && apk add --no-cache python3 py3-pip \ && apk add curl # 如果你的项目是一个 python 项目,推荐全局安装,提升运行态的性能 # 例如 RUN pip3 install --break-system-packages mysql-mcp-server RUN pip3 install --break-system-packages uv ## 全局安装必须的 npm 依赖 ## @cloudbase/mcp-transformer 必须安装 ## 如果你的项目是一个 npm 包,推荐全局安装,提升运行态的性能 RUN npm install -g @cloudbase/mcp-transformer@1.0.0-beta.18 mongo-mcp # 固定暴露端口 EXPOSE 80 # 启动命令 ## 这里是使用 cloudbase-mcp-transformer 命令来将 Stdio 转换为远程 MCP 服务 ## --stdioCmd 是指定需要转换的命令,其中可以引用环境变量,例如 $USER、$PASSWORD、$HOST、$PORT、$DATABASE ## 在创建云托管服务的时候,用户可以指定环境变量 ## 如果你的项目依赖环境变量,需要在 mcp-meta.json 中进行声明 ## --port 是指定转换后的服务端口,默认为 3000 CMD cloudbase-mcp-transformer stdioToStreamable --stdioCmd "mongodb-mcp mongodb://$USER:$PASSWORD@$HOST:$PORT/$DATABASE?authSource=admin ./" --port 80 ``` 完成 Dockerfile 编写后,我们可以将 MCP Server 部署至云托管了。 ## 部署到云端 ### 部署代码 ```shell # 请保证全局安装了 `@cloudbase/cli` 并登录。 npm i -g @cloudbase/cli@latest # 登录: tcb login ``` 进入 Dockerfile 所在的目录,运行以下命令进行部署,根据提示输入在[准备工作章节](#准备工作)中使用的云开发环境 id 及云托管服务名: ```shell tcb cloudrun deploy ``` ### 配置环境变量 部署完成后可以在云托管服务详情页配置服务依赖的环境变量,例如 mongodb 例子中的 `USER`、`PASSWORD`、`HOST`、`PORT`、`DATABASE` 等环境变量。 如果服务不依赖环境变量就可以运行,可以忽略这个步骤 ## 使用 部署成功后即可在云开发 MCP Server 详情页中进行测试啦。进入 `Tools` 标签页,即可看到可用工具,并进行调用。 阅读以下文档使用托管的 MCP Server: - [在云开发 Agent 中使用](../use/agent) - [在 MCP Host 中使用](../use/mcp-host) - [通过 SDK 接入](../use/sdk) ## 发布上架 如果需要将 MCP Server 发布到云开发 MCP 市场,请参考 - [发布上架](./publish) ## FAQ ### 如何验证本地 MCP Server 是否功能可用? 首先我们在本地运行下 MCP Server,验证其功能的可用性。 以 [Github MCP](https://github.com/modelcontextprotocol/servers/tree/main/src/github#npx) 为例,其给出了如下配置: ```json { "mcpServers": { "github": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-github"], "env": { "GITHUB_PERSONAL_ACCESS_TOKEN": "" } } } } ``` 这个配置说明: - 运行 `npx -y @modelcontextprotocol/server-github` 来启动 MCP Server - 需要配置环境变量 `GITHUB_PERSONAL_ACCESS_TOKEN` 为了方便本地调试,MCP 官方提供了 `@modelcontextprotocol/inspector` 调试工具,运行以下命令启动图形界面: ```shell npx -y @modelcontextprotocol/inspector ``` 运行后,可根据终端输出,前往调试地址,按以下步骤进行操作: 1. `Transport Type` 选中 `STDIO` 2. `Command` 填入 `npx` 3. `Arguments` 填入 `-y @modelcontextprotocol/server-github` 4. 前往 创建 Github Token 5. 点击 `Environment Variables` ,在展开的列表中添加 `GITHUB_PERSONAL_ACCESS_TOKEN: ` ,填入刚刚创建的 Github Token 6. 点击 `Connect` ,等待连接后即可测试其提供的工具了 本地测试了一两个工具后,我们可以确认这个 MCP Server 是可用的了。接下来,让我们开始将它转换为远程的 MCP Server。 ### 如何本地调试 MCP Server 转换成远程 MCP 的效果? 将 Stdio 模式的 MCP Server 转换成 Streamable HTTP 模式非常简单,只需运行: ```shell npx -y cross-env GITHUB_PERSONAL_ACCESS_TOKEN= \ npx -y @cloudbase/mcp-transformer stdioToStreamable \ --stdioCmd "npx -y @modelcontextprotocol/server-github" --noVerifyAccess ``` 这串命令挺长的,我们拆分下逐一解释各个部分的作用: - `npx -y cross-env GITHUB_PERSONAL_ACCESS_TOKEN=`:设置环境变量 - `npx -y @cloudbase/mcp-transformer stdioToStreamable`:运行 `@cloudbase/mcp-transformer`,这是我们提供的命令行工具,能够提供一个服务,将 Stdio 模式的 MCP Server 转换成以 Streamable HTTP 模式运行的 MCP Server。运行后,默认会在 提供服务 - `--stdioCmd "npx -y @modelcontextprotocol/server-github"`:运行 Stdio 模式的 MCP Server 的命令。`@cloudbase/mcp-transformer` 会使用此命令运行 Stdio 模式的 MCP Server,并提供 HTTP 服务,以此转换为以 Streamable HTTP 模式运行的 MCP Server - `--noVerifyAccess`:跳过鉴权的参数。在云托管上运行的 MCP Server 能够拿到调用者的身份,默认情况下会根据身份进行鉴权,仅允许来自超级管理员的调用。此处在本地运行时,为了方便,跳过鉴权 运行后,再次回到调试界面,按以下步骤进行操作: 1. `Transport Type` 选中 `Streamable HTTP` 2. `URL` 填入 `http://127.0.0.1:3000/messages` 3. 点击 `Connect` ,等待连接后即可测试其提供的工具了 测试无误,则说明我们已经成功将本地 MCP Server 以 Streamable HTTP 模式运行了,可以通过 URL 进行远程访问了。 --- ## 以 npx/uvx 运行的 MCP Server # 以 npx/uvx 运行的 MCP Server 社区中有大量 MCP Server 以 npx/uvx 的方式运行,只需复制一个 JSON 配置文件即可进行使用。如 [mcp-everything](https://www.npmjs.com/package/@modelcontextprotocol/server-everything): ```json { "mcpServers": { "everything": { "command": "npx", "args": [ "-y", "@modelcontextprotocol/server-everything" ] } } } ``` 云开发平台支持一键托管以这种方式运行的 MCP Server,只需将上述配置复制进表单即可: ![创建自定义 MCP Server](./custom-mcp.png) 具体步骤如下: 1. 前往 [云开发平台 AI+](https://tcb.cloud.tencent.com/dev?envId=lowcode-2gp2855c5ce22e35#/ai?tab=mcp&show-add-custom-mcp-server-modal=1) 2. 点击 `添加自定义 MCP Server` 3. 根据不同类型(npx/uvx)选择 tab ,填写剩余表单,提交后即可创建 4. 创建完成后,可前往 Agent 配置使用 若您开发了能够以 npx/uvx 运行的 MCP Server ,可以通过创建 Cloudbase MCP Deploy 按钮,让用户一键在云开发平台上托管您的 MCP Server。详见 [Cloudbase MCP Deploy 按钮](./cloudbase-mcp-deploy)。 :::info 如何托管不是通过 npx/uvx 的方式运行的 MCP Server ? 请阅读 [托管现有的 MCP Server / 通用 MCP Server](./host-mcp) 。 ::: --- ## 上架云开发 MCP 市场 # 上架云开发 MCP 市场 :::tip 在将您的 MCP Server 提交到云开发 MCP 市场之前,请检查以下事项: - 代码开源:您的 MCP Server 应该是开源的,并具有商业使用友好许可证,如 MIT、Apache 等 - 安全性:您的 MCP Server 不会读取用户本地数据,如本地文件、本地数据库、非必要的环境变量等 - Transport 类型:您的 MCP Server 使用的是 Stdio 方式提供服务 ::: ## 开发测试 请参考 [开发指南](./host-mcp) 来开发和测试您的 MCP Server。 在经过充分开发测试后,您可以将您的 MCP Server 提交到云开发 MCP 市场,供更多人使用。 ## 编写文档和上架信息 请准备编写两个必要的文档,参考 [托管本地 MCP 到云开发服务端示例项目](https://cnb.cool/cloudbase/mcp-tpl) - `DOC.md`:MCP 服务的展示文档,会展示在模板详情页,请参考示例格式进行编写,使用标准的 markdown 格式 - `meta.json`: 云开发 MCP 服务的配置文件,请参考示例格式进行编写,使用标准的 json 格式 ## 提交上架 请确保您的 MCP Server 已经在云开发中部署运行通过,且准备好文档和上架信息 然后按照以下方式提交上架: 1. 点击 [**提交 云开发 MCP Server 模板 / 需求**](https://doc.weixin.qq.com/forms/AJEAIQdfAAoALAAaAa6ACgYH8yRdSbQif#/fill) 2. 填写上架信息,选择提交模板,填写包括 MCP Server 名称和代码仓库信息、联系方式 3. 如果 MCP Server 依赖特殊环境变量,可以提供一个测试环境变量供审核人员进行测试 4. 点击**提交**按钮,等待审核通过 5. 通过审核后,云开发 MCP 市场将展示您的 MCP Server,供更多人使用 ## 友情链接 成功上架之后,您的 MCP 将会在云开发 MCP 市场展示,供更多人使用。 非常欢迎您在项目文档中添加如下友情链接,方便更多人了解和使用您的 MCP Server。 ```markdown ## 远程 MCP 本项目支持[一键部署到腾讯云开发平台](https://docs.cloudbase.net/ai/mcp/develop/host-mcp),提供远程 Streamable HTTP 访问 [☁️ 前往云开发平台部署 MCP Server](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp&p&mcp-template=mcp-alapi-cn) ``` ## 参考信息 ### `meta.json` 字段说明 | 字段名称 | 类型 | 描述 | 示例 | | ------------- | ------ | ---------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | | `name` | 字符串 | 应用程序或服务的唯一标识符,通常采用小写字母和下划线的组合,便于在命令行和代码中引用。 | `"mcp-mongo"` | | `title` | 字符串 | 应用程序或服务的显示名称,通常用于用户界面和文档中,便于用户识别。 | `"MongoDB"` | | `description` | 字符串 | 对应用程序或服务的简要说明,概述其主要功能和用途。 | `"提供对 MongoDB 数据库的访问及管理的能力"` | | `author` | 对象 | 包含作者信息的对象,通常包括作者名称,有时还可以包括联系方式等信息。 | `{ "name": "社区模板" }` | | `gitUrl` | 字符串 | 项目代码仓库的 URL 地址,通常指向 Git 版本控制系统(如 GitHub、GitLab 等)。用户可以通过该链接查看源码、提交问题或贡献代码。 | `"https://github.com/QuantGeekDev/mongo-mcp"` | | `tags` | 数组 | 包含描述应用程序或服务的标签列表,便于分类和搜索。 | `["数据库管理", "MongoDB", "社区 MCP"]` | | `port` | 数字 | 应用程序监听的端口号,用于接收外部请求。 需要和 Dockerfile 中的 `EXPOSE` 命令保持一致。 | `80` | | `logo` | 数组 | 包含应用程序标志(Logo)的 URL 列表,通常用于展示在用户界面或文档中。 | `["cloud://tcb-advanced-a656fc.7463-tcb-advanced-a656fc-1257967285/mcp-logo.png"]` | | `env_params` | 对象 | 包含环境变量的键值对,用于配置应用程序运行所需的环境参数。 | `{ "HOST": "数据库服务器地址", "PORT": "数据库端口号", "USER": "数据库登录用户名", "PASSWORD": "数据库登录密码", "DATABASE": "要连接的数据库名称" }` | --- ## ALAPI接口平台 MCP 接入 # ALAPI接口平台 MCP 接入 通过 MCP 协议提供与 ALAPI 接口平台交互,可快捷查询IP归属地、天气情况、数据热榜、文本审核、短网址缩短等操作 [前往云开发平台运行 MCP Server](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp&p&mcp-template=mcp-alapi-cn) --- ## 环境变量 - 需要将 **ALAPI_TOKEN** 配置为您在 ALAPI 上创建的 [TOKEN](https://www.alapi.cn/dashboard/data/token) - 可选配置 **ALAPI_ID** 为接口ID,如果不指定使用的接口,请填 0 --- ## 🔗 相关链接 - [ALAPI官网](https://www.alapi.cn) - 获取API服务和Token ## 🗺️ 功能清单 以下仅罗列部分功能,具体请以实际调用为准 | 命令名称 | 功能描述 | 核心参数 | | ----------------------------- | --------------------------------------------------------------------------------------- | ------------- | | user_apis | 获取已申请的接口列表 | | | /api/ip | 查询IP归属地信息 | ip | | /api/tianqi | 查询国内天气详情、包含天气信息、天气预警、天气指数、AQI 等 | city | | /api/tophub | 查询今日热榜数据,包含抖音热搜、头条热榜、知乎、36k、百度热搜、搜狗热搜、微博热搜等数据 | id,type | | /api/censor/text | 查询文本是否违规,特别适合AI内容审核 | text | | /api/url | 短网址缩短,将长网址缩短为短网址,方便短信发送、二维码生成等场景 | url | | /api/qr/decode | 支持一图多码,支持数十二维码,条形码的识别 | url | | /api/eventHistory | 历史上的今天,查历史上的指定日期发生的大事 | date | | /api/exchange | 汇率查询,根据货币代码查询货币汇率和换算,支持全球170+个国家和地区货币查询 | money,from,to | | /api/enterprise/simple_search | 企业工商信息搜索,根据企业名称或统一社会信用代码查询企业基本工商信息 | keyword | | /api/kd | 快递查询V1,免费查询快递物流轨迹,支持中通、申通、顺丰、极兔、百世、圆通等 | numner,phone | | /api/star | 星座运势查询,提供星座运势查询服务,支持查询十二星座今日或明日、本周、本月、本年的运势。 | star | | /api/gold | 查询当前黄金的实时价格,最高价,最低价,品牌黄金的价格 | market | ## 仓库地址 [https://cnb.cool/alapi/mcp-alapi-cn](https://cnb.cool/alapi/mcp-alapi-cn) --- ## 🔌 使用方式 - [在云开发 Agent 中使用](https://docs.cloudbase.net/ai/mcp/use/agent) - [在 MCP Host 中使用](https://docs.cloudbase.net/ai/mcp/use/mcp-host) - [通过 SDK 接入](https://docs.cloudbase.net/ai/mcp/use/sdk) --- [云开发 MCP 控制台](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp) --- ## 高德地图服务 MCP 接入 # 高德地图服务 MCP 接入 通过 MCP 协议提供标准化地图服务调用,支持位置服务快速集成。 提供高德地图的 API 接口,支持地图渲染、地理编码、路径规划等功能 [前往云开发平台运行 MCP Server](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp&p&mcp-template=mcp-amap) --- ## 环境变量 - 需要将 **AMAP_MAPS_API_KEY** 配置为 **您在高德官网上申请的key** ## 使用说明 [高德地图参考文档](https://lbs.amap.com/api/mcp-server/gettingstarted) ## 🗺️ 功能清单 | 工具标识 | 功能描述 | 核心参数 | |----------------------------------|-----------------------------------------|------------------------------------| | `maps_regeocode` | 经纬度转行政区地址 | location | | `maps_geo` | 地址转经纬度坐标 | address, city | | `maps_ip_location` | IP定位查询 | ip | | `maps_weather` | 城市天气查询 | city | | `maps_bicycling` | 骑行路径规划(支持500km) | origin, destination | | `maps_direction_walking` | 步行路径规划(100km内) | origin, destination | | `maps_direction_driving` | 驾车路径规划 | origin, destination | | `maps_distance` | 多模式距离测量 | origins, destination, type | | `maps_text_search` | 关键词POI搜索 | keywords, city | | `maps_around_search` | 周边半径搜索 | location, radius | | `maps_search_detail` | POI详情查询 | id | ## 仓库地址 [https://github.com/devsapp/amap-maps-mcp-server](https://github.com/devsapp/amap-maps-mcp-server) --- ## 🔌 使用方式 - [在云开发 Agent 中使用](https://docs.cloudbase.net/ai/mcp/use/agent) - [在 MCP Host 中使用](https://docs.cloudbase.net/ai/mcp/use/mcp-host) - [通过 SDK 接入](https://docs.cloudbase.net/ai/mcp/use/sdk) --- [云开发 MCP 控制台](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp) --- ## Apifox 服务 MCP 接入 # Apifox 服务 MCP 接入 Apifox MCP Server,可以将 Apifox 的接口文档提供给 Cursor 等支持 AI 编程的 IDE,或其他支持 MCP 的 AI 工具。 开发者可以通过 AI 助手完成以下工作:根据接口文档生成或修改代码、搜索接口文档内容等等,至于通过这个接口文档数据能让 AI 干什么更多更强大的活,请发挥你和你们团队的想象力 [部署 MCP Server](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp&p&mcp-template=mcp-apifox) --- Apifox MCP Server 支持三种不同的使用场景,您可以根据实际需求选择对应的配置方法: ## 1. 使用 Apifox 项目内的 API 文档 > 如果您希望通过 MCP 来使用 Apifox 项目内的 API 文档,请参考我们的配置方法。具体操作请参考[帮助文档](https://docs.apifox.com/6327888m0) ### 环境变量 - 需要将 APIFOX_ACCESS_TOKEN 配置为**您在 Apifox 上创建的 [API 访问令牌](https://docs.apifox.com/doc-5723694)** - 需要将 PROJECTID 配置为您在 Apifox 中项目的项目ID ## 2. 使用公开发布的 API 文档 > 如果您希望通过 MCP 来使用公开发布的 API 文档,请查阅我们的详细配置指南。具体操作请参考[帮助文档](https://docs.apifox.com/6327890m0) ### 环境变量 - 需要将 APIFOX_ACCESS_TOKEN 配置为**您在 Apifox 上创建的 [API 访问令牌](https://docs.apifox.com/doc-5723694)** - 需要将 SITEID 配置为您在 Apifox 中已启用AI 功能的文档 site-id ## 3. 使用 OpenAPI/Swagger 文档 > 如果您希望通过 MCP 来使用 OpenAPI/Swagger 文档,我们同样提供了详细的配置说明,并能对文档进行美化。具体操作请参考[帮助文档](https://docs.apifox.com/6327891m0) - 需要将 APIFOX_ACCESS_TOKEN 配置为**您在 Apifox 上创建的 [API 访问令牌](https://docs.apifox.com/doc-5723694)** - 需要将 OAS 配置为Swagger/OpenAPI 文件的 远程URL (例:https://petstore.swagger.io/v2/swagger.json) ## 使用说明 [Apifox MCP Server 参考文档](https://docs.apifox.com/apifox-mcp-server) ## 🗺️ 功能清单 | 工具标识 | 功能描述 | 核心参数 | | ---------------------------------- | -------------------------------------------------- | -------- | | `refresh_project_oas` | 重新下载最新的指定项目的 OpenAPI Spec 文件内容 | - | | `read_project_oas_ref_resources` | 读取指定项目的 OpenAPI Spec 文件内 $ref 的文件内容 | path | | `read_project_oas` | 读取指定项目的 OpenAPI Spec 文件内容 | - | ## 仓库地址 [https://github.com/apifox/apifox-mcp-server](https://github.com/apifox/apifox-mcp-server) --- ## 🔌 使用方式 - [在云开发 Agent 中使用](https://docs.cloudbase.net/ai/mcp/use/agent) - [在 MCP Host 中使用](https://docs.cloudbase.net/ai/mcp/use/mcp-host) - [通过 SDK 接入](https://docs.cloudbase.net/ai/mcp/use/sdk) --- [云开发 MCP 控制台](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp) ## 参数说明 ### refresh_project_oas_随机标识 从服务器重新下载最新的“指定项目”的 OpenAPI Spec 文件内容 **返回**: 文件内容 ### read_project_oas_ref_resources_随机标识 读取 “指定项目” 的 OpenAPI Spec 文件内 $ref 的文件内容, 可以同时获取多个文件内容 | 输入参数 | Type | 描述 | | -------- | -------- | ----------------------------------------------------------------------------------------------------- | | path | string[] | 接口文档地址path,例如 /paths/_pet_{petId}.json,可从 read_project_oas 接口返回中获取 $ref 字段内容 | **返回**: 文件内容 ### read_project_oas_随机标识 读取“指定项目”的 OpenAPI Spec 文件内容 **返回**: 文件内容 --- ## 百度地图服务 MCP 接入 # 百度地图服务 MCP 接入 通过 MCP 协议提供标准化地图服务调用,支持位置服务快速集成。 提供百度地图的 API 接口,支持地理编码、地点检索、路线规划等功能 [部署 MCP Server](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp&p&mcp-template=mcp-baidumap) --- ## 环境变量 - 需要将 **BAIDU_MAP_API_KEY** 配置为**您在百度地图开放平台上申请的key** ## 使用说明 [百度地图参考文档](https://lbs.baidu.com/faq/api?title=mcpserver/base) ## 🗺️ 功能清单 | 工具标识 | 功能描述 | 核心参数 | |----------------------------------|-----------------------------------------|------------------------------------| | `map_geocode` | 将地址解析为对应的位置坐标 | address | | `map_reverse_geocode` | 将坐标点转换为对应语义化地址 | location | | `map_search_places` | 多种场景的地点以及POI检索, 包括城市检索、圆形区域检索 | query 检索关键词,location 圆形检索的中心点,radius 圆形检索的半径,region 城市检索指定城市 | | `map_place_details` | 根据POI的uid, 检索POI详情信息 | uid | | `map_distance_matrix` | 根据起点和终点坐标, 计算所有起终点组合间的路线距离和行驶时间 | origins 起点经纬度列表,destinations 终点经纬度列表,mode 出行类型,可选取值包括 driving, walking, riding, 默认使用driving | | `map_directions` | 根据起终点坐标规划出行路线和耗时, 可指定驾车、步行、骑行、公交等出行方式 | origin 起点经纬度,destination 终点经纬度,model 出行类型, 可选取值包括 driving, walking, riding, transit, 默认使用driving | | `map_weather` | 根据行政区划编码或经纬度坐标查询天气 (通过location经纬度坐标查询天气需用户拥有高级权限) | district_id 行政区划编码,location 经纬度坐 | | `map_ip_location` | 根据请求的IP获取当前请求的位置 (定位到城市), 如果请求参数ip为IPv6则需要高级权限 | ip | ## 仓库地址 [https://github.com/baidu-maps/mcp](https://github.com/baidu-maps/mcp) --- ## 🔌 使用方式 - [在云开发 Agent 中使用](https://docs.cloudbase.net/ai/mcp/use/agent) - [在 MCP Host 中使用](https://docs.cloudbase.net/ai/mcp/use/mcp-host) - [通过 SDK 接入](https://docs.cloudbase.net/ai/mcp/use/sdk) --- [云开发 MCP 控制台](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp) --- ## 空白 MCP Server # 空白 MCP Server [前往云开发平台通过空白模板创建 MCP Server](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp&mcp-template=empty-tpl) ## 介绍 当前模板是一个基本的 MCP Server 模板,包含了一个完整的 MCP Server 项目。可以以此项目为基础进行修改,开发您自己的 MCP Server。 会介绍如何使用此项目代码进行本地开发调试以及部署。 ## 下载代码包 [点击此处下载项目代码](https://tcb.cloud.tencent.com/cloud-run-function-template/cloudrun-mcp-basic.zip?v=2025) ## 本地开发调试 ### 安装依赖 ```shell npm i ``` ### 登录命令行 `@cloudbase/cli` 需要登录后才能使用,使用云开发账号登录: ```shell npm run login ``` ### 环境变量 将 `.env.template` 更名为 `.env.development` ,该文件定义了环境变量: - `SKIP_VERIFY_ACCESS=true`:设置后可跳过 token 校验。原有 token 校验将只允许来自 API Key 和超管身份的 token 调用 - `CLOUDBASE_ENVIRONMENT=your-env-id`:在云托管线上环境中,上下文里包含了云开发环境 id。在本地开发时,我们通过设置该环境变量来提供环境 id。请设置一个当前登录账号下的环境 id > 设置 `SKIP_VERIFY_ACCESS` 这两个环境变量有助于我们在本地进行调试,但不建议在线上生产环境设置。 ### 启动本地 MCP Server 服务 ```shell npm run dev ``` 启动后,将会在 提供服务。 修改代码,即可触发重新编译并重启服务。 ### 启动图形界面调试 运行 MCP Inspector: ```shell npx @modelcontextprotocol/inspector ``` 前往 进行调试。 1. 在左侧选择 `Streamable HTTP` 类型,并填入 `URL` 为 `http://localhost:3000/messages` 2. 在左侧点击 `Connect` 3. 在 `Tools` tab 下点击 `List Tools` 展示工具列表 4. 选择任一工具进行调用 ## 部署至云托管 ### 构建 ```shell npm run build ``` ### 部署 该 MCP Server 能够直接部署至云托管,但要在云开发 Agent 中使用,需要在控制台先创建一个 MCP Server,再覆盖其云托管服务。 首先,前往[云开发平台](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp)创建一个 MCP Server。 创建完成后,运行 cli 部署命令,填入对应的 MCP 标识。 ```shell npm run deploy ``` ## 🔌 使用方式 - [在云开发 Agent 中使用](https://docs.cloudbase.net/ai/mcp/use/agent) - [在 MCP Host 中使用](https://docs.cloudbase.net/ai/mcp/use/mcp-host) - [通过 SDK 接入](https://docs.cloudbase.net/ai/mcp/use/sdk) --- [云开发 MCP 控制台](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp) --- ## 彩云天气服务 MCP 接入 # 彩云天气服务 MCP 接入 通过 MCP 协议提供对彩云天气的 API 访问能力。 [前往云开发平台运行 MCP Server](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp&p&mcp-template=mcp-caiyun-weather) --- ## 环境变量 - 需要将 **CAIYUN_WEATHER_API_TOKEN** 配置为 **彩云天气 API 令牌** ## 🗺️ 功能清单 | 工具标识 | 功能描述 | 核心参数 | |-----------------------|---------------------------------|----------------------------------| | `get_realtime_weather` | 获取指定位置的实时天气数据 | `lng`(经度), `lat`(纬度) | | `get_hourly_forecast` | 获取未来72小时的逐小时天气预报 | `lng`(经度), `lat`(纬度) | | `get_weekly_forecast` | 获取未来7天的每日天气预报 | `lng`(经度), `lat`(纬度) | | `get_historical_weather` | 获取过去24小时的历史天气数据 | `lng`(经度), `lat`(纬度) | | `get_weather_alerts` | 获取指定位置的天气警报 | `lng`(经度), `lat`(纬度) | ## 仓库地址 [https://github.com/caiyunapp/mcp-caiyun-weather](https://github.com/caiyunapp/mcp-caiyun-weather) --- ## 🔌 使用方式 - [在云开发 Agent 中使用](https://docs.cloudbase.net/ai/mcp/use/agent) - [在 MCP Host 中使用](https://docs.cloudbase.net/ai/mcp/use/mcp-host) - [通过 SDK 接入](https://docs.cloudbase.net/ai/mcp/use/sdk) --- [云开发 MCP 控制台](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp) --- ## 云开发 AI 能力 MCP Server # 云开发 AI 能力 MCP Server 通过 MCP 协议提供标准化 AI 工具调用,支持 Agent 智能体快速集成。 [前往云开发平台通过云开发 AI 能力模板创建 MCP Server](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp&mcp-template=cloudrun-mcp-memory) --- ## 🛠️ 工具清单 | 工具标识 | 功能描述 | 典型应用场景 | | ----------------------- | -------------------- | ------------------------------ | | `search_web` | 使用联网进行信息检索 | 查询新闻、股价、天气等实时信息 | | `analyze_vision` | 图像理解与分析 | 图片内容描述、视觉问答 | | `search_knowledge_base` | 知识库向量检索 | 企业内部文档查询、知识问答 | | `chat_db` | 自然语言查询数据库 | 数据统计、业务报表生成 | | `llm_generate_text` | 调用大模型文生文 | 内容创作、问答、翻译等 | | `chat_with_agent` | 调用云开发 Agent | 专业领域问答、定制化对话 | --- ## 🔌 使用方式 - [在云开发 Agent 中使用](https://docs.cloudbase.net/ai/mcp/use/agent) - [在 MCP Host 中使用](https://docs.cloudbase.net/ai/mcp/use/mcp-host) - [通过 SDK 接入](https://docs.cloudbase.net/ai/mcp/use/sdk) --- [云开发 MCP 控制台](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp) --- ## CNB (云原生构建) 服务 MCP 接入 # CNB (云原生构建) 服务 MCP 接入 通过 MCP 协议提供 CNB 服务调用,支持查询仓库,查看issue,创建issue等能力。 [部署 MCP Server](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp&p&mcp-template=mcp-cnb) --- ## 环境变量 - 需要将 API_TOKEN 配置为**您在 CNB 上创建的 [访问令牌](https://cnb.cool/profile/token/create)** ## 使用说明 [CNB MCP Server 参考文档](https://cnb.cool/cnb/tools/cnb-mcp-server) ## 🗺️ 功能清单 | 工具标识 | 功能描述 | 核心参数 | |----------------------------------|-----------------------------------------|---------------------------------------------------------------------------------------------| | `list-repositories` | 获取当前用户拥有指定权限及其以上权限的仓库 | page, page_size, search, filter_type, role, order_by, desc | | `list-group-repositories` | 获取分组里当前用户有权限的仓库 | page, page_size, search, group, filter_type, order_by, desc, descendant | | `get-repository` | 获取指定仓库信息 | repoId | | `list-issues` | 查询仓库的 Issues | repoId, page, page_size, state, keyword, priority, labels, authors, assignees, updated_time_begin, updated_time_end, order_by | | `get-issue` | 获取指定 Issue 信息 | repoId, issueId | | `create-issue` | 创建一个 Issue | repoId, title, body, assignees, labels, priority | ## 仓库地址 [https://cnb.cool/cnb/tools/cnb-mcp-server](https://cnb.cool/cnb/tools/cnb-mcp-server) --- ## 🔌 使用方式 - [在云开发 Agent 中使用](https://docs.cloudbase.net/ai/mcp/use/agent) - [在 MCP Host 中使用](https://docs.cloudbase.net/ai/mcp/use/mcp-host) - [通过 SDK 接入](https://docs.cloudbase.net/ai/mcp/use/sdk) --- [云开发 MCP 控制台](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp) ## 参数说明 ### list-repositories 获取当前用户拥有指定权限及其以上权限的仓库 | 输入参数 | Type | 描述 | | -------- | --------------- | ------------------------- | | page | optional number | 页数 | | page_size | optional number | 页大小 | | search | string | 查询关键词 | | filter_type | optional string | 仓库类型 private, public, encrypted | | role | optional string | 最小仓库权限,默认owner, 枚举值:Reporter, Developer, Master, Owner | | order_by | optional string | 排序类型,默认last_updated_at,枚举值:created_at, last_updated_at, stars, slug_path, forks | | desc | optional boolean | 是否降序 | **返回**: 仓库信息 ### list-group-repositories 获取分组里当前用户有权限的仓库 | 输入参数 | Type | 描述 | | -------- | --------------- | ------------------------- | | page | optional number | 页数 | | page_size | optional number | 页大小 | | search | string | 查询关键词 | | group | string | 组织名称 | | filter_type | optional string | 仓库类型 private, public, encrypted | | order_by | optional string | 排序类型,默认last_updated_at,枚举值:created_at, last_updated_at, stars, slug_path, forks | | desc | optional boolean | 是否降序 | | descendant | optional boolean | 枚举值:查全部/查询直接属于当前组织的仓库/查询子组织的仓库, all/sub/grand | **返回**: 仓库信息 ### get-repository 获取指定仓库信息 | 输入参数 | Type | 描述 | | -------- | --------------- | ------------------------- | | repoId | optional string | repo path | **返回**: 仓库信息 ### list-issues 查询仓库的 Issues | 输入参数 | Type | 描述 | | -------- | --------------- | ------------------------- | | repoId | optional string | repo path | | page | optional number | 页数 | | page_size | optional number | 页大小 | | state | optional string | open or closed | | keyword | optional string | 查询关键词 | | priority | optional string | issue 优先级,枚举值:p0,p1,p2,p3 | | labels | optional string | issue 标签,枚举值:git,bug,feature | | authors | optional string | issue 作者名 | | assignees | optional string | issue 处理人 | | updated_time_begin | optional string | issue 更新时间的范围,开始时间点,举例:2022-01-31 | | updated_time_end | optional string | issue 更新时间的范围,结束时间点,举例:2022-01-31 | | order_by | optional string | issue 排序顺序,枚举值:created_at, -updated_at, reference_count (‘-’ 前缀表示降序) | **返回**: issue信息 ### get-issue 获取指定 Issue 信息 | 输入参数 | Type | 描述 | | -------- | --------------- | ------------------------- | | repoId | optional string | repo path | | issueId | optional number | issue 编号 | **返回**: issue信息 ### create-issue 创建一个 Issue | 输入参数 | Type | 描述 | | -------- | --------------- | ------------------------- | | repoId | optional string | repo path | | title | optional string | issue 标题 | | body | optional string | issue 描述 | | assignees | optional string[] | 一个或多个 Issue 处理人的用户名 | | labels | optional string[] | 一个或多个 Issue 标签 | | priority | optional string | issue 优先级,枚举值:p0,p1,p2,p3 | **返回**: issue信息 --- ## COS (对象存储 COS 与数据万象 CI) 服务 MCP 接入 # COS (对象存储 COS 与数据万象 CI) 服务 MCP 接入 提供 COS/CI API 能力的 MCP 服务器,提供上传/下载对象、获取对象列表、文档转 pdf、图片文字水印、图片二维码识别、图片质量评分、图片超分、图片通用抠图、图片智能裁剪、智能检索 MetaInsight(文搜图、图搜图)、视频智能封面等能力 [部署 MCP Server](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp&p&mcp-template=mcp-cos) --- ## 环境变量 - 需要将 SECRET_ID、 SECRET_KEY 配置为**您在 API密码管理页面获取 [SecretId、SecretKey](https://console.cloud.tencent.com/cam/capi)** - 需要将 BUCKET 配置为存储桶名称 - 需要将 REGION 配置为存储桶所在的区域 - 需要将 DATASET_NAME 配置为智能检索的数据集名(非必填) ## 🗺️ 功能清单 | 工具标识 | 功能描述 | 核心参数 | |----------------------------------|-----------------------------------------|---------------------------------------------------------------------------------------------| | `putObject` | 上传本地文件到存储桶(仅支持 server 本地文件) | `filePath`, `fileName`, `targetDir` | | `putObjectSourceUrl` | 通过 url下载文件并将文件上传到存储桶 | `sourceUrl`, `fileName`, `targetDir` | | `getObject` | 下载存储桶内的文件 | `objectKey` | | `getBucket` | 获取指定存储桶的文件列表 | `Prefix` | | `imageInfo` | 获取图片信息 | `objectKey` | | `assessQuality` | 图片质量评估 | `objectKey` | | `aiSuperResolution` | 图片超分辨率处理 | `objectKey` | | `aiPicMatting` | 图片抠图处理 | `objectKey`, `width`, `height` | | `aiQrcode` | 二维码识别 | `objectKey` | | `waterMarkFont` | 生成带文字水印的图片 | `objectKey`, `text` | | `createMediaSmartCoverJob` | 创建媒体智能封面任务 | `objectKey` | | `describeMediaJob` | 查询媒体智能封面任务结果 | `jobId` | | `imageSearchPic` | 根据图片检索相似图片 | `uri` | | `imageSearchText` | 根据文本检索相似图片 | `text` | | `createDocToPdfJob` | 创建文档转 PDF 处理任务 | `objectKey` | | `describeDocProcessJob` | 查询文档转码任务结果 | `jobId` | ## 🔌 使用方式 - [在云开发 Agent 中使用](https://docs.cloudbase.net/ai/mcp/use/agent) - [在 MCP Host 中使用](https://docs.cloudbase.net/ai/mcp/use/mcp-host) - [通过 SDK 接入](https://docs.cloudbase.net/ai/mcp/use/sdk) --- [云开发 MCP 控制台](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp) ## 参数说明 ### putObject 上传文件到存储桶 | 输入参数 | Type | 描述 | | -------- | --------------- | ------------------------- | | filePath | string | 文件路径(包含文件名) | | fileName | optional string | 文件名 (存在存储桶里的名称) | | targetDir | optional string | 目标目录 (存在存储桶的哪个目录)| **返回**: 对象地址 ### putObjectSourceUrl 通过 url下载文件并将文件上传到存储桶 | 输入参数 | Type | 描述 | | -------- | --------------- | ------------------------- | | sourceUrl | string | 可下载的文件 url | | fileName | optional string | 文件名 (存在存储桶里的名称) | | targetDir | optional string | 目标目录 (存在存储桶的哪个目录)| **返回**: 对象地址 ### getObject 下载存储桶内的文件 | 输入参数 | Type | 描述 | | -------- | --------------- | ------------------------- | | objectKey | string | 文件的路径 | **返回**: 文件内容 ### getBucket 获取指定仓库信息 | 输入参数 | Type | 描述 | | -------- | --------------- | ------------------------- | | Prefix | optional string | 文件列表的路径前缀,默认根路径 | **返回**: 在桶中的文件列表 ### imageInfo 图片处理-获取图片信息 | 输入参数 | Type | 描述 | | -------- | --------------- | ------------------------- | | objectKey | string | 图片在存储桶里的路径 | **返回**: | 输出参数 | 描述 | | -------- | ------------------------- | | format | 图片类型。例如 png、gif 等 | | width | 图片的宽度。单位为像素(px) | | height | 图片的高度。单位为像素(px) | | size | 图片的大小。单位为 Bytes | | md5 | 图片的 md5 值 | | frame_count | 图片的帧数。静态图为1,动图为对应的帧数 | | bit_depth | 图片的位深 | | vertical_dpi | 图片的垂直分辨率 | | horizontal_dpi | 图片的水平分辨率 | ### assessQuality 图片处理-图片质量评估 | 输入参数 | Type | 描述 | | -------- | --------------- | ------------------------- | | objectKey | string | 图片在存储桶里的路径 | **返回**: | 输出参数 | 描述 | |----------------|---------------------------------------------------------| | LongImage | 长图(长宽比 ≥3 或 ≤1/3),TRUE 表示是,FALSE 表示否 | | BlackAndWhite | 黑白图(灰度图,RGB 三通道均为灰度色阶),TRUE 表示是,FALSE 表示否 | | SmallImage | 小图(最长边 1000 像素),TRUE 表示是,FALSE 表示否 | | PureImage | 纯色图/纯文字图(无内容或内容简单),TRUE 表示是,FALSE 表示否 | | ClarityScore | 清晰度得分(0-100,综合噪声/曝光/模糊/压缩等评估,≥50 较清晰) | | AestheticScore | 美观度得分(0-100,构图/色彩等艺术性评估,≥50 较美观) | | LowQualityScore | 内容质量得分(0-100,背景/内容等质量评估,≥50 质量较好) | | RequestId | 唯一请求 ID,用于问题定位 | ### aiSuperResolution 图片处理-超分辨率 | 输入参数 | Type | 描述 | | -------- | --------------- | ------------------------- | | objectKey | string | 图片在存储桶里的路径 | **返回**: | 输出参数节点名称 | 父结点 | 描述 | | -------- | --------------- | ------------------------- | | UploadResult |无 |请求结果容器 | | OriginalInfo |UploadResult |原图信息容器 | Key |OriginalInfo |原图文件名(如:example.jpg) | | Location |OriginalInfo |原图存储路径 | | ETag |OriginalInfo |原图文件的唯一标识符 | | ProcessResults |UploadResult |图片处理结果容器 | | Object |ProcessResults |单张图片处理结果容器 | | Key |Object |超分后图片文件名(如:output.jpg) | | Location |Object |超分后图片访问链接 | | ETag |Object |超分后图片的唯一标识符 | | Size |Object |超分后图片大小(单位:字节) | ### aiPicMatting 图片处理-抠图 | 输入参数 | Type | 描述 | | -------- | --------------- | ------------------------- | | objectKey | string | 图片在存储桶里的路径 | | width | optional string | 宽度 | | height | optional string | 高度 | **返回**: | 输出参数节点名称 | 父结点 | 描述 | |----------------|----------------|-------------------------| | UploadResult | 无 | 请求结果容器 | | OriginalInfo | UploadResult | 原图信息容器 | | Key | OriginalInfo | 原图文件名(如:example.jpg) | | Location | OriginalInfo | 原图存储路径 | | ETag | OriginalInfo | 原图ETag 值 | | ProcessResults | UploadResult | 图片处理结果容器 | | Object | ProcessResults | 单张图片处理结果容器 | | Key | Object | 抠图后图片文件名(如:output.jpg) | | Location | Object | 抠图后图片链接 | | ETag | Object | 抠图后图片的ETag 值 | | Size | Object | 抠图后图片大小(单位:字节) | ### aiQrcode 图片处理-二维码识别-识别存储桶内二维码图片内容 | 输入参数 | Type | 描述 | |--------|---------------|-------------------------| | objectKey | string | COS对象键(完整路径)示例: images/qrcode.jpg | **返回**: | 输出参数节点名称 | 父结点 | 描述 | |----------------|----------------|-------------------------| | UploadResult | 无 | 原图信息容器 | | OriginalInfo | UploadResult | 原图信息容器 | | Key | OriginalInfo | 原图文件名 | | Location | OriginalInfo | 图片路径 | | ImageInfo | OriginalInfo | 原图图片信息容器 | | Format | ImageInfo | 图片格式 | | Width | ImageInfo | 图片宽度 | | Height | ImageInfo | 图片高度 | | Quality | ImageInfo | 图片质量 | | Ave | ImageInfo | 图片主色调 | | Orientation | ImageInfo | 图片旋转角度 | | ProcessResults | UploadResult | 图片处理结果容器 | | Object | ProcessResults | 单条处理结果容器 | | Key | Object | 处理后文件名 | | Location | Object | 处理后图片路径 | | Format | Object | 处理后图片格式 | | Width | Object | 处理后图片宽度 | | Height | Object | 处理后图片高度 | | Size | Object | 处理后图片大小 | | Quality | Object | 处理后图片质量 | | codeStatus | Object | 二维码识别状态(0无/1有) | | QRcodeInfo | Object | 二维码识别结果容器 | | codeUrl | QRcodeInfo | 二维码解析内容 | | codelocation | QRcodeInfo | 二维码坐标容器 | | point | codelocation | 坐标点(格式: x1,y1;x2,y2;...) | ### waterMarkFont 生成带文字水印的图片 | 输入参数 | Type | 描述 | | -------- | --------------- | ------------------------- | | objectKey | string | COS对象键(完整路径)示例: images/photo.jpg | | text | string | 水印文字内容(支持中文) | **返回**: | 输出参数节点名称 | 父结点 | 描述 | | -------- | --------------- | ------------------------- | | UploadResult | 无 | 原图信息(请求结果容器) | OriginalInfo | UploadResult | 原图信息容器| | Key | OriginalInfo | 原图文件名| | Location | OriginalInfo | 图片路径| | ImageInfo | OriginalInfo | 原图图片信息容器| | ETag | OriginalInfo | 原图/结果图 ETag 信息(覆盖时更新)| | Format | ImageInfo | 图片格式| | Width | ImageInfo | 图片宽度(单位:像素)| | Height | ImageInfo | 图片高度(单位:像素)| | Quality | ImageInfo | 图片质量(数值)| | Ave | ImageInfo | 图片主色调(十六进制格式 0xRRGGBB)| | Orientation | ImageInfo | 图片旋转角度(1-8对应不同旋转/翻转模式)| | FrameCount | ImageInfo | 图片帧数(静态图=1,动图为实际帧数)| | ProcessResults | UploadResult | 图片处理结果容器| | Object | ProcessResults | 单个图片处理结果容器| | Key | Object | 结果图文件名| | Location | Object | 结果图路径| | Format | Object | 结果图格式| | Width | Object | 结果图宽度(单位:像素)| | Height | Object | 结果图高度(单位:像素)| | Size | Object | 结果图大小(单位:字节)| | Quality | Object | 结果图质量(数值)| | ETag | Object | 处理结果图 ETag 信息| | FrameCount | Object | 结果图帧数(静态图=1,动图为实际帧数)| ### createMediaSmartCoverJob 创建媒体智能封面任务 | 输入参数 | Type | 描述 | | -------- | --------------- | ------------------------- | | objectKey | string | 对象在存储桶里的路径 | **返回** | 输出参数节点名称 | 父结点 | 描述 | |------------------|-----------------------------------------|---------------------------------------| | Response | 无 | 保存结果的容器 | | JobsDetail | Response | 任务的详细信息 | | Code | Response.JobsDetail | 错误码,只有 State 为 Failed 时有意义 | | Message | Response.JobsDetail | 错误描述,只有 State 为 Failed 时有意义 | | JobId | Response.JobsDetail | 新创建任务的 ID | | Tag | Response.JobsDetail | 新创建任务的 Tag:SmartCover | | State | Response.JobsDetail | 任务状态 | | CreationTime | Response.JobsDetail | 任务的创建时间 | | EndTime | Response.JobsDetail | 任务的结束时间 | | QueueId | Response.JobsDetail | 任务所属的队列 ID | | Input | Response.JobsDetail | 该任务的输入资源地址 | | Operation | Response.JobsDetail | 该任务的规则 | | Region | Response.JobsDetail.Input | 存储桶的地域 | | Bucket | Response.JobsDetail.Input | 存储结果的存储桶 | | Object | Response.JobsDetail.Input | 输出结果的文件名 | | SmartCover | Response.JobsDetail.Operation | 同请求中的 Request.Operation.SmartCover | | Output | Response.JobsDetail.Operation | 同请求中的 Request.Operation.Output | | MediaResult | Response.JobsDetail.Operation | 输出文件的基本信息,任务未完成时不返回,详见 MediaResult | | UserData | Response.JobsDetail.Operation | 透传用户信息 | | JobLevel | Response.JobsDetail.Operation | 任务优先级 | | OutputFile | Response.JobsDetail.Operation.MediaResult | 输出文件的基本信息 | | Bucket_OutputFile| Response.JobsDetail.Operation.MediaResult.OutputFile | 输出文件所在的存储桶 | | Region_OutputFile| Response.JobsDetail.Operation.MediaResult.OutputFile | 输出文件所在的存储桶所在的园区 | | ObjectName | Response.JobsDetail.Operation.MediaResult.OutputFile | 输出文件名,可能有多个 | | Md5Info | Response.JobsDetail.Operation.MediaResult.OutputFile | 输出文件的 MD5 信息 | | ObjectName_MD5 | Response.JobsDetail.Operation.MediaResult.OutputFile.Md5Info | 输出文件名(带 MD5 后缀) | | Md5 | Response.JobsDetail.Operation.MediaResult.OutputFile.Md5Info | 输出文件的 MD5 值 | ### describeMediaJob 根据 jobid 查询指定的媒体智能封面任务结果 | 输入参数 | Type | 描述 | | -------- | --------------- | ------------------------- | | jobId | string | 要查询的任务ID,可通过提交智能封面任务的响应中获取。 | **返回**: | 输出参数节点名称 | 父结点 | 描述 | |------------------|-----------------------------------------|---------------------------------------| | Response | 无 | 保存结果的容器 | | JobsDetail | Response | 任务的详细信息 | | Code | Response.JobsDetail | 错误码,只有 State 为 Failed 时有意义 | | Message | Response.JobsDetail | 错误描述,只有 State 为 Failed 时有意义 | | JobId | Response.JobsDetail | 新创建任务的 ID | | Tag | Response.JobsDetail | 新创建任务的 Tag:SmartCover | | State | Response.JobsDetail | 任务状态 | | CreationTime | Response.JobsDetail | 任务的创建时间 | | EndTime | Response.JobsDetail | 任务的结束时间 | | QueueId | Response.JobsDetail | 任务所属的队列 ID | | Input | Response.JobsDetail | 该任务的输入资源地址 | | Operation | Response.JobsDetail | 该任务的规则 | | Region | Response.JobsDetail.Input | 存储桶的地域 | | Bucket | Response.JobsDetail.Input | 存储结果的存储桶 | | Object | Response.JobsDetail.Input | 输出结果的文件名 | | SmartCover | Response.JobsDetail.Operation | 同请求中的 Request.Operation.SmartCover | | Output | Response.JobsDetail.Operation | 同请求中的 Request.Operation.Output | | MediaResult | Response.JobsDetail.Operation | 输出文件的基本信息,任务未完成时不返回,详见 MediaResult | | UserData | Response.JobsDetail.Operation | 透传用户信息 | | JobLevel | Response.JobsDetail.Operation | 任务优先级 | | OutputFile | Response.JobsDetail.Operation.MediaResult | 输出文件的基本信息 | | Bucket_OutputFile| Response.JobsDetail.Operation.MediaResult.OutputFile | 输出文件所在的存储桶 | | Region_OutputFile| Response.JobsDetail.Operation.MediaResult.OutputFile | 输出文件所在的存储桶所在的园区 | | ObjectName | Response.JobsDetail.Operation.MediaResult.OutputFile | 输出文件名,可能有多个 | | Md5Info | Response.JobsDetail.Operation.MediaResult.OutputFile | 输出文件的 MD5 信息 | | ObjectName_Info | Response.JobsDetail.Operation.MediaResult.OutputFile.Md5Info | 输出文件名(带 MD5 后缀) | | Md5_Value | Response.JobsDetail.Operation.MediaResult.OutputFile.Md5Info | 输出文件的 MD5 值 | ### imageSearchPic 根据输入的图片,从数据集中检索出与输入的图片内容相似的图片 | 输入参数 | Type | 描述 | | -------- | --------------- | ------------------------- | | uri | string | 根据输入的图片,从数据集中检索出与输入的图片内容相似的图片 | **返回**: | 输出参数节点名称 | 父结点 | 描述 | | -------- | --------------- | ------------------------- | | ImageResult | 无 | 图像检索识别结果信息列表 | | RequestId | 无 | 请求 ID | | URI | ImageResult | 相似的图片地址 | | Score | ImageResult | 图片相关度分数,分数越高表示与检索条件越相符 | ### imageSearchText 根据输入的文本内容,从数据集中检索出与输入的文本内容相符的图片 | 输入参数 | Type | 描述 | | -------- | --------------- | ------------------------- | | text | string | 检索的文本 | **返回**: | 输出参数节点名称 | 父结点 | 描述 | | -------- | --------------- | ------------------------- | | ImageResult | 无 | 图像检索识别结果信息列表 | | RequestId | 无 | 请求 ID | | URI | ImageResult | 相似的图片地址 | | Score | ImageResult | 图片相关度分数,分数越高表示与检索条件越相符 | ### createDocToPdfJob 创建文档转 pdf 处理任务 | 输入参数 | Type | 描述 | | -------- | --------------- | ------------------------- | | objectKey | string | 对象在存储桶里的路径 | **返回**: | 输出参数节点名称 | 父结点 | 描述 | |------------------|-----------------------------------------|---------------------------------------| | Response | 无 | 保存结果的容器 | | JobsDetail | Response | 任务的详细信息,同 CreateDocProcessJobs 接口的 Response.JobsDetail 节点 | | NonExistJobIds | Response | 查询的 ID 中不存在的任务,所有任务都存在时不返回 | | DocProcess | Response.JobsDetail.Operation | 文档预览任务参数 | | DocProcessResult | Response.JobsDetail.Operation | 在 job 类型为 DocProcess 且状态为 success 时,返回文档预览任务结果详情 | | Output | Response.JobsDetail.Operation | 结果输出地址,同 CreateDocProcessJobs 接口的 Request.Operation.Output 节点 | | PageInfo | Response.JobsDetail.Operation.DocProcessResult | 预览任务产物详情 | | TgtType | Response.JobsDetail.Operation.DocProcessResult | 预览产物目标格式 | | TotalPageCount | Response.JobsDetail.Operation.DocProcessResult | 预览任务产物的总数 | | SuccPageCount | Response.JobsDetail.Operation.DocProcessResult | 预览任务产物的成功数 | | FailPageCount | Response.JobsDetail.Operation.DocProcessResult | 预览任务产物的失败数 | | TotalSheetCount | Response.JobsDetail.Operation.DocProcessResult | 预览任务的 Sheet 总数(Excel 特有参数) | | PageNo | Response.JobsDetail.Operation.DocProcessResult.PageInfo | 预览产物页码/SheetId(Excel 格式时) | | TgtUri | Response.JobsDetail.Operation.DocProcessResult.PageInfo | 预览产物生成的 COS 桶路径 | | X-SheetPics | Response.JobsDetail.Operation.DocProcessResult.PageInfo | 当前 Sheet 生成的图片总数(Excel 特有参数) | | PicIndex | Response.JobsDetail.Operation.DocProcessResult.PageInfo | 当前预览产物在整个源文件中的序号(Excel 特有参数) | | PicNum | Response.JobsDetail.Operation.DocProcessResult.PageInfo | 当前预览产物在 Sheet 中的序号(Excel 特有参数) | ### describeDocProcessJob 根据 jobid 查询指定的文档转码任务结果 | 输入参数 | Type | 描述 | | -------- | --------------- | ------------------------- | | jobId | string | 要查询的任务ID,可通过提交文档任务的响应中获取。 | **返回**: | 输出参数节点名称 | 父结点 | 描述 | |------------------|-----------------------------------------|---------------------------------------| | Response | 无 | 保存结果的容器 | | JobsDetail | Response | 任务的详细信息,同 CreateDocProcessJobs 接口的 Response.JobsDetail 节点 | | NonExistJobIds | Response | 查询的 ID 中不存在的任务,所有任务都存在时不返回 | | DocProcess | Response.JobsDetail.Operation | 文档预览任务参数 | | DocProcessResult | Response.JobsDetail.Operation | 在 job 类型为 DocProcess 且状态为 success 时,返回文档预览任务结果详情 | | Output | Response.JobsDetail.Operation | 结果输出地址,同 CreateDocProcessJobs 接口的 Request.Operation.Output 节点 | | PageInfo | Response.JobsDetail.Operation.DocProcessResult | 预览任务产物详情 | | TgtType | Response.JobsDetail.Operation.DocProcessResult | 预览产物目标格式 | | TotalPageCount | Response.JobsDetail.Operation.DocProcessResult | 预览任务产物的总数 | | SuccPageCount | Response.JobsDetail.Operation.DocProcessResult | 预览任务产物的成功数 | | FailPageCount | Response.JobsDetail.Operation.DocProcessResult | 预览任务产物的失败数 | | TotalSheetCount | Response.JobsDetail.Operation.DocProcessResult | 预览任务的 Sheet 总数(Excel 特有参数) | | PageNo | Response.JobsDetail.Operation.DocProcessResult.PageInfo | 预览产物页码/SheetId(Excel 格式时) | | TgtUri | Response.JobsDetail.Operation.DocProcessResult.PageInfo | 预览产物生成的 COS 桶路径 | | X-SheetPics | Response.JobsDetail.Operation.DocProcessResult.PageInfo | 当前 Sheet 生成的图片总数(Excel 特有参数) | | PicIndex | Response.JobsDetail.Operation.DocProcessResult.PageInfo | 当前预览产物在整个源文件中的序号(Excel 特有参数) | | PicNum | Response.JobsDetail.Operation.DocProcessResult.PageInfo | 当前预览产物在 Sheet 中的序号(Excel 特有参数) | --- ## CRIC 物业 AI MCP # CRIC 物业 AI MCP 接入 **CRIC物业AI 平台** 的 MCP 服务器。**CRIC物业AI** 是克而瑞专为物业行业打造的智能 AI 助理。 [前往云开发平台运行 MCP Server](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp&p&mcp-template=mcp-server-wuye-ai) --- ## 环境变量 - 需要将 **CRIC_WUYE_AI_ACCESS_TOKEN** 配置为 **CRIC物业AI Access Token**。 - 可选配置项:需要将 **CRIC_WUYE_AI_PROVIDER_API_BASE** 配置为 **CRIC物业AI 后端接入 API**。如果不提供,默认为生产环境(`https://export.wuye-ai.cricbigdata.com`)。请注意 ***此 URL 不是 CRIC物业AI MCP Server 的 URL*** 。可选值为 `https://export.wuye-ai-staging.cricbigdata.com` (测试环境)、 `https://export.wuye-ai.cricbigdata.com` (生产环境) 具体配置要求也可以参考 [README](https://github.com/wuye-ai/mcp-server-wuye-ai/blob/master/README.md)。 ## 🗺️ 功能清单 | 命令名称 | 功能描述 | 核心参数 | |--------------|---------------------------------------------------|-------------------------------------------------------------------| | `获取资讯日报` | 根据YYYY-MM-DD形式的日期,获取当日物业行业资讯日报。 | `date`(要获取资讯日报的日期,形如 YYYY-MM-DD。如果不提供,则默认为今天。) | | `获取行业热点问题列表` | 获取当前CRIC物业AI应用内物业行业热点问题的分类和列表。 | 无 | | `获取可用知识库列表` | 获取可用知识库列表,后续可以使用其中的知识库搜索相关知识。 | 无 | | `搜索知识库` | 指定具体知识库ID,以及具体查询的问题,获取知识库搜索结果,以文档片段或全文形式返回,供AI参考。 | `knowledge_base_id`(知识库的 ID), `query`(查询的问题), `top_k`(最大返回结果数量) 等 | ## 仓库地址 [https://github.com/wuye-ai/mcp-server-wuye-ai](https://github.com/wuye-ai/mcp-server-wuye-ai) --- ## 🔌 使用方式 - [在云开发 Agent 中使用](https://docs.cloudbase.net/ai/mcp/use/agent) - [在 MCP Host 中使用](https://docs.cloudbase.net/ai/mcp/use/mcp-host) - [通过 SDK 接入](https://docs.cloudbase.net/ai/mcp/use/sdk) --- [云开发 MCP 控制台](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp) --- ## Fetch 服务 MCP 接入 # Fetch 服务 MCP 接入 通过 MCP 协议提供 Fetch 能力,根据网页URL获取网页内容和处理图像。 [部署 MCP Server](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp&p&mcp-template=mcp-fetch) --- ## 使用说明 [Fetch MCP Server 参考文档](https://github.com/smithery-ai/mcp-fetch) ## 🗺️ 功能清单 | 工具标识 | 功能描述 | 核心参数 | |--------------|----------------------------------------|---------------------------------------------| | `fetch` | 从互联网检索URL内容并转换为markdown,可处理图像 | url, maxLength, enableFetchImages | ## 仓库地址 [https://github.com/smithery-ai/mcp-fetch](https://github.com/smithery-ai/mcp-fetch) --- ## 🔌 使用方式 - [在云开发 Agent 中使用](https://docs.cloudbase.net/ai/mcp/use/agent) - [在 MCP Host 中使用](https://docs.cloudbase.net/ai/mcp/use/mcp-host) - [通过 SDK 接入](https://docs.cloudbase.net/ai/mcp/use/sdk) --- [云开发 MCP 控制台](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp) ## 参数说明 ### fetch 从互联网检索 URL 并提取其内容为 markdown。图像会自动处理并准备好进行剪贴板操作 | 输入参数 | Type | 描述 | | -------- | --------------- | ------------------------- | | url | string | 要获取内容的 URL | | maxLength | optional number | 返回内容的最大长度(默认20000) | | startIndex | optional number | 内容的起始位置 | | imageStartIndex | optional number | 图像收集的起始位置 | | raw | optional boolean | 返回原始内容而不是处理过的 markdown | | imageMaxCount | optional number | 每个请求处理的最大图像数量(默认:3) | | imageMaxHeight | optional number | 合并图像的最大高度(默认:4000) | | imageMaxWidth | optional string | 合并图像的最大宽度(默认:1000) | | imageQuality | optional number | JPEG 质量(1-100)(默认:80) | | enableFetchImages | optional boolean | 启用图像的获取和处理(默认值:false) | | ignoreRobotsTxt | optional boolean | 忽略 robots.txt 限制 图像处理(默认值:false) | **返回**: 检索内容文本 --- ## Figma 服务 MCP 接入 # Figma 服务 MCP 接入 通过 MCP 协议提供与 Figma API的安全交互。 [前往云开发平台运行 MCP Server](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp&p&mcp-template=mcp-figma) --- ## 环境变量 - 需要将 **FIGMA_API_KEY** 配置为 **Figma API 访问令牌** ## 🗺️ 功能清单 | 命令名称 | 功能描述 | 核心参数 | |------------------------|--------------------------------------------|--------------------------------------------------------------------------| | `get_figma_data` | 当无法获取 nodeId 时获取整个 Figma 文件的布局信息 | `fileKey`(文件密钥), `nodeId`(节点ID, 可选), `depth`(遍历深度, 可选) | | `download_figma_images`| 根据图像或图标节点 ID 下载 Figma 文件中使用的 SVG 和 PNG 图像 | `fileKey`(文件密钥), `nodes`(节点数组), `localPath`(本地存储路径) | ## 仓库地址 [https://github.com/GLips/Figma-Context-MCP](https://github.com/GLips/Figma-Context-MCP) --- ## 🔌 使用方式 - [在云开发 Agent 中使用](https://docs.cloudbase.net/ai/mcp/use/agent) - [在 MCP Host 中使用](https://docs.cloudbase.net/ai/mcp/use/mcp-host) - [通过 SDK 接入](https://docs.cloudbase.net/ai/mcp/use/sdk) --- [云开发 MCP 控制台](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp) --- ## MCP 服务接入 — Firecrawl 网页抓取与深度研究 # MCP 服务接入 — Firecrawl 网页抓取与深度研究 通过 MCP 协议提供强大的网页抓取、搜索和深度研究能力。 > Firecrawl MCP Server 接受查询文本,利用 Firecrawl 的网页抓取能力,返回最相关的网页内容,支持从多种网页中提取文本,并将其转换为 Markdown/HTML 格式,供 LLM(大语言模型)进行处理和生成。 [部署 MCP Server](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp&p&mcp-template=mcp-firecrawl) --- ## 环境变量 - **FIRECRAWL_API_KEY**:您的 Firecrawl API 密钥。 - **FIRECRAWL_API_URL**(可选):自托管实例的自定义 API 端点。 - **FIRECRAWL_RETRY_MAX_ATTEMPTS**(可选):最大重试次数(默认:3)。 - **FIRECRAWL_RETRY_INITIAL_DELAY**(可选):首次重试的初始延迟时间(默认:1000 毫秒)。 - **FIRECRAWL_RETRY_MAX_DELAY**(可选):重试之间的最大延迟时间(默认:10000 毫秒)。 - **FIRECRAWL_RETRY_BACKOFF_FACTOR**(可选):指数退避因子(默认:2)。 ## 使用说明 [Firecrawl MCP Server 参考文档](https://github.com/mendableai/firecrawl-mcp-server) ## 🗺️ 功能清单 | 工具标识 | 功能描述 | 核心参数 | |----------------------|------------------------------------------------------|-------------------------------------------------------------| | `firecrawl_scrape` | 抓取单个网页内容,支持 JavaScript 渲染,返回清理后的文本内容。 | `url`(网页 URL),`formats`(返回格式,如 `["markdown"]`),`waitFor`(等待时间,毫秒),`timeout`(超时时间,毫秒),`mobile`(是否使用移动视图) | | `firecrawl_map` | 映射网站,发现所有索引的 URL。 | `url`(网站 URL),`search`(可选的搜索词),`ignoreSitemap`(是否忽略 sitemap.xml),`includeSubdomains`(是否包括子域名),`limit`(最大 URL 数量) | | `firecrawl_search` | 在网页中搜索指定内容,返回匹配的结果。 | `query`(查询文本),`limit`(返回的结果数量),`lang`(语言),`country`(国家),`scrapeOptions`(抓取选项) | | `firecrawl_crawl` | 启动异步抓取,支持多页面提取。 | `url`(网站 URL),`excludePaths` (排除路径),`includePaths` (包含路径), `maxDepth`(最大深度),`limit`(最大页面数),`allowExternalLinks`(是否允许外部链接),`deduplicateSimilarURLs`(是否去重相似 URL) | | `firecrawl_check_crawl_status` | 检查爬虫爬取状态。 | `id`(爬虫任务ID) | | `firecrawl_extract` | 从页面中提取结构化数据。 | `urls`(网页 URL 列表),`prompt` (用于 LLM 提取的自定义提示词), `systemPrompt` (指导 LLM 的系统提示词), `schema` (用于结构化数据提取的 JSON 模式), `allowExternalLinks` (允许从外部链接提取信息), `enableWebSearch` (启用网页搜索以获取额外上下文), `includeSubdomains` (在提取时包含子域名) | | `firecrawl_deep_research` | 执行深入的多源研究,提供摘要和来源。 | `query`(查询文本),`maxDepth`(最大深度), `timeLimit` (时间限制 秒), `maxUrls` (要分析的最大 URL 数量, 默认50) | | `firecrawl_generate_llmstxt` | 为特定领域生成 LLMs.txt 文件。 | `url`(要分析的网站的基础 URL),`maxUrls` 要包含的最大 URL 数量(默认:10), `showFullText` 是否在响应中包含 llms-full.txt 的内容 | ## 仓库地址 [https://github.com/mendableai/firecrawl-mcp-server](https://github.com/mendableai/firecrawl-mcp-server) --- ## 🔌 使用方式 - [在云开发 Agent 中使用](https://docs.cloudbase.net/ai/mcp/use/agent) - [在 MCP Host 中使用](https://docs.cloudbase.net/ai/mcp/use/mcp-host) - [通过 SDK 接入](https://docs.cloudbase.net/ai/mcp/use/sdk) --- [云开发 MCP 控制台](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp) --- ## Gitee 服务 MCP 接入 # Gitee 服务 MCP 接入 通过 MCP 协议提供 Gitee 服务调用,支持代码评审,文件操作、仓库管理、搜索功能等。 [部署 MCP Server](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp&p&mcp-template=mcp-gitee) --- ## 环境变量 - 需要将 GITEE_ACCESS_TOKEN 配置为**您在Gitee 上创建的 [私人令牌](https://gitee.com/profile/personal_access_tokens)** - 需要将 GITEE_API_BASE 设置为 https://gitee.com/api/v5 (默认设置即可) ## 使用说明 [Gitee MCP Server 参考文档](https://gitee.com/oschina/mcp-gitee) ## 🗺️ 功能清单 | 工具标识 | 功能描述 | 核心参数 | | ------------------------------- | ------------------------ | ------------------------------------------------------------------------------------------------------------------------- | | comment_issue | 在仓库问题上创建评论 | body(评论内容), number(问题编号), owner(仓库所属空间地址), repo(仓库路径) | | comment_pull | 在拉取请求上创建评论 | body(评论内容), number(拉取请求编号), owner(仓库所属空间地址), repo(仓库路径) | | create_enterprise_repo | 创建企业仓库 | auto_init(是否初始化仓库), description(仓库描述), enterprise(企业路径), name(仓库名称), private(是否私有) | | create_issue | 创建问题 | assignee(问题负责人), body(问题描述), title(问题标题), owner(仓库所属空间地址), repo(仓库路径) | | create_org_repo | 创建组织仓库 | auto_init(是否初始化仓库), description(仓库描述), org(组织路径), name(仓库名称), private(是否私有) | | create_pull | 创建拉取请求 | assignees(负责人), base(目标分支), body(请求内容), head(源分支), title(请求标题), owner(仓库所属空间地址), repo(仓库路径) | | create_release | 创建发布 | body(发布描述), name(发布名称), owner(仓库所属空间地址), repo(仓库路径), tag_name(标签名称) | | create_user_repo | 创建用户仓库 | auto_init(是否初始化仓库), description(仓库描述), name(仓库名称), private(是否私有) | | fork_repository | 拷贝仓库 | name(新仓库名称), owner(原仓库所属空间地址), repo(原仓库路径) | | get_file_content | 获取仓库中指定文件的内容 | owner(仓库所属空间地址), path(文件路径), ref(分支名称或提交ID), repo(仓库路径) | | get_pull_detail | 获取拉取请求详情 | number(拉取请求编号), owner(仓库所属空间地址), repo(仓库路径) | | get_repo_issue_detail | 获取问题详情 | number(问题编号), owner(仓库所属空间地址), repo(仓库路径) | | get_user_info | 获取已认证用户的信息 | 无参数 | | list_issue_comments | 获取仓库问题的所有评论 | number(问题编号), owner(仓库所属空间地址), repo(仓库路径), page(页码), per_page(每页数量) | | list_pull_comments | 列出拉取请求的所有评论 | number(拉取请求编号), owner(仓库所属空间地址), repo(仓库路径), page(页码), per_page(每页数量) | | list_releases | 列出仓库的所有发布 | owner(仓库所属空间地址), repo(仓库路径), page(页码), per_page(每页数量) | | list_repo_issues | 列出仓库的所有问题 | owner(仓库所有者命名空间), repo(仓库路径), page(页码), per_page(每页数量), state(问题状态) | | list_repo_pulls | 列出仓库的所有拉取请求 | owner(仓库所有者命名空间), repo(仓库路径), page(页码), per_page(每页数量), state(请求状态) | | list_user_notifications | 列出授权用户的所有通知 | page(页码), per_page(每页数量), unread(仅未读通知), type(通知类型), since(更新时间) | | list_user_repos | 列出用户授权的仓库 | page(页码), per_page(每页数量), visibility(仓库可见性), affiliation(用户与仓库的关系) | | merge_pull | 合并拉取请求 | number(拉取请求编号), owner(仓库所属空间地址), repo(仓库路径), merge_method(合并方法) | | search_open_source_repositories | 搜索功能开开源仓库 | q(搜索关键词), from(搜索起始位置), size(页面大小), sort_by_f(排序字段) | | search_users | 在 Gitee 上搜索用户 | page(页码), per_page(每页数量), q(搜索关键词) | | update_issue | 更新问题 | number(问题编号), owner(仓库所属空间地址), repo(仓库路径), title(问题标题), state(问题状态) | | update_pull | 更新拉取请求 | number(拉取请求编号), owner(仓库所属空间地址), repo(仓库路径), title(请求标题), state(请求状态) | ## 仓库地址 [https://gitee.com/oschina/mcp-gitee](https://gitee.com/oschina/mcp-gitee) --- ## 🔌 使用方式 - [在云开发 Agent 中使用](https://docs.cloudbase.net/ai/mcp/use/agent) - [在 MCP Host 中使用](https://docs.cloudbase.net/ai/mcp/use/mcp-host) - [通过 SDK 接入](https://docs.cloudbase.net/ai/mcp/use/sdk) --- [云开发 MCP 控制台](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp) --- ## Github 服务 MCP 接入 # Github 服务 MCP 接入 通过 MCP 协议提供 Github 服务调用,支持代码评审,文件操作、仓库管理、搜索功能等。 [部署 MCP Server](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp&p&mcp-template=mcp-github) --- ## 环境变量 - 需要将GITHUB_PERSONAL_ACCESS_TOKEN 配置为**您在Github 上创建的 [Personal access token](https://github.com/settings/tokens)** ## 使用说明 [Github MCP Server 参考文档](https://github.com/modelcontextprotocol/servers/tree/main/src/github) ## 🗺️ 功能清单 | 工具标识 | 功能描述 | 核心参数 | |-----------------------------|---------------------------------|-------------------------------------| | `create_or_update_file` | 创建或更新单个文件 | owner, repo, path, content, message | | `push_files` | 单次提交推送多个文件 | owner, repo, branch, files, message | | `search_repositories` | 搜索GitHub仓库 | query, page, perPage | | `create_repository` | 创建新GitHub仓库 | name, description, private | | `get_file_contents` | 获取文件或目录内容 | owner, repo, path, branch | | `create_issue` | 创建新issue | owner, repo, title, body, assignees | | `create_pull_request` | 创建新PR | owner, repo, title, head, base | | `fork_repository` | Fork仓库 | owner, repo, organization | | `create_branch` | 创建新分支 | owner, repo, branch, from_branch | | `list_issues` | 列出和筛选仓库issues | owner, repo, state, labels | | `update_issue` | 更新现有issue | owner, repo, issue_number, title | | `add_issue_comment` | 添加issue评论 | owner, repo, issue_number, body | | `search_code` | 跨仓库搜索代码 | q, sort, order | | `search_issues` | 搜索issues和PR | q, sort, order | | `search_users` | 搜索GitHub用户 | q, sort, order | | `list_commits` | 获取仓库分支的提交记录 | owner, repo, sha | | `get_issue` | 获取issue内容 | owner, repo, issue_number | | `get_pull_request` | 获取PR详情 | owner, repo, pull_number | | `list_pull_requests` | 列出和筛选仓库PR | owner, repo, state | | `create_pull_request_review`| 创建PR审查 | owner, repo, pull_number, body, event| | `merge_pull_request` | 合并PR | owner, repo, pull_number | | `get_pull_request_files` | 获取PR更改的文件列表 | owner, repo, pull_number | | `get_pull_request_status` | 获取PR所有状态检查 | owner, repo, pull_number | | `update_pull_request_branch`| 更新PR分支 | owner, repo, pull_number | | `get_pull_request_comments` | 获取PR评论 | owner, repo, pull_number | | `get_pull_request_reviews` | 获取PR审查记录 | owner, repo, pull_number | ## 仓库地址 [https://github.com/modelcontextprotocol/servers/tree/main/src/github](https://github.com/modelcontextprotocol/servers/tree/main/src/github) --- ## 使用方式 - [在云开发 Agent 中使用](https://docs.cloudbase.net/ai/mcp/use/agent) - [在 MCP Host 中使用](https://docs.cloudbase.net/ai/mcp/use/mcp-host) - [通过 SDK 接入](https://docs.cloudbase.net/ai/mcp/use/sdk) --- [云开发 MCP 控制台](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp) ## 参数说明 ### create_or_update_file 在仓库中创建或更新单个文件 | 输入参数 | Type | 描述 | | -------- | --------------- | ------------------------- | | owner | string | 仓库所有者(用户名或组织) | | repo | string | 仓库名称 | | path | string | 文件创建/更新的路径 | | content | string | 文件内容 | | message | string | 提交信息 | | branch | string | 操作的目标分支 | | sha | optional string | 被替换文件的SHA(用于更新) | **返回**: 文件内容和提交详情 ### push_files 在单次提交中推送多个文件 | 输入参数 | Type | 描述 | | -------- | ------ | ------------------------------------ | | owner | string | 仓库所有者 | | repo | string | 仓库名称 | | branch | string | 推送目标分支 | | files | array | 要推送的文件数组(每个包含路径和内容) | | message | string | 提交信息 | **返回**: 更新后的分支引用 ### search_repositories 搜索GitHub仓库 | 输入参数 | Type | 描述 | | -------- | --------------- | ------------------- | | query | string | 搜索关键词 | | page | optional number | 分页页码 | | perPage | optional number | 每页结果数(最大100) | **返回**: 仓库搜索结果 ### create_repository 创建新GitHub仓库 | 输入参数 | Type | 描述 | | ----------- | ---------------- | ---------------- | | name | string | 仓库名称 | | description | optional string | 仓库描述 | | private | optional boolean | 是否私有仓库 | | autoInit | optional boolean | 是否初始化README | **返回**: 创建的仓库详情 ### get_file_contents 获取文件或目录内容 | 输入参数 | Type | 描述 | | -------- | --------------- | -------------- | | owner | string | 仓库所有者 | | repo | string | 仓库名称 | | path | string | 文件/目录路径 | | branch | optional string | 获取内容的分支 | **返回**: 文件/目录内容 ### create_issue 创建新issue | 输入参数 | Type | 描述 | | --------- | ----------------- | ------------ | | owner | string | 仓库所有者 | | repo | string | 仓库名称 | | title | string | issue标题 | | body | optional string | issue描述 | | assignees | optional string[] | 分配的用户名 | | labels | optional string[] | 添加的标签 | | milestone | optional number | 里程碑编号 | **返回**: 创建的issue详情 ### create_pull_request 创建新PR | 输入参数 | Type | 描述 | | --------------------- | ---------------- | ------------------ | | owner | string | 仓库所有者 | | repo | string | 仓库名称 | | title | string | PR标题 | | body | optional string | PR描述 | | head | string | 包含更改的分支 | | base | string | 要合并到的目标分支 | | draft | optional boolean | 是否创建为草稿PR | | maintainer_can_modify | optional boolean | 是否允许维护者修改 | **返回**: 创建的PR详情 ### fork_repository Fork仓库 | 输入参数 | Type | 描述 | | ------------ | --------------- | ------------ | | owner | string | 仓库所有者 | | repo | string | 仓库名称 | | organization | optional string | Fork到的组织 | **返回**: Fork后的仓库详情 ### create_branch 创建新分支 | 输入参数 | Type | 描述 | | ----------- | --------------- | -------------------------- | | owner | string | 仓库所有者 | | repo | string | 仓库名称 | | branch | string | 新分支名称 | | from_branch | optional string | 源分支(默认为仓库默认分支) | **返回**: 创建的分支引用 ### list_issues 列出和筛选仓库issues | 输入参数 | Type | 描述 | | --------- | ----------------- | ------------------------------------------ | | owner | string | 仓库所有者 | | repo | string | 仓库名称 | | state | optional string | 状态筛选('open', 'closed', 'all') | | labels | optional string[] | 标签筛选 | | sort | optional string | 排序方式('created', 'updated', 'comments') | | direction | optional string | 排序方向('asc', 'desc') | | since | optional string | 日期筛选(ISO 8601时间戳) | | page | optional number | 页码 | | per_page | optional number | 每页结果数 | **返回**: issue详情数组 ### update_issue 更新现有issue | 输入参数 | Type | 描述 | | ------------ | ----------------- | ------------------------ | | owner | string | 仓库所有者 | | repo | string | 仓库名称 | | issue_number | number | 要更新的issue编号 | | title | optional string | 新标题 | | body | optional string | 新描述 | | state | optional string | 新状态('open'或'closed') | | labels | optional string[] | 新标签 | | assignees | optional string[] | 新分配者 | | milestone | optional number | 新里程碑编号 | **返回**: 更新后的issue详情 ### add_issue_comment 添加issue评论 | 输入参数 | Type | 描述 | | ------------ | ------ | ----------------- | | owner | string | 仓库所有者 | | repo | string | 仓库名称 | | issue_number | number | 要评论的issue编号 | | body | string | 评论内容 | **返回**: 创建的评论详情 ### search_code 跨仓库搜索代码 | 输入参数 | Type | 描述 | | -------- | --------------- | ------------------------------ | | q | string | 使用GitHub代码搜索语法的搜索词 | | sort | optional string | 排序字段(仅'indexed') | | order | optional string | 排序方向('asc'或'desc') | | per_page | optional number | 每页结果数(最大100) | | page | optional number | 页码 | **返回**: 带仓库上下文的代码搜索结果 ### search_issues 搜索issues和PR | 输入参数 | Type | 描述 | | -------- | --------------- | ---------------------------------------- | | q | string | 使用GitHub issues搜索语法的搜索词 | | sort | optional string | 排序字段(comments, reactions, created等) | | order | optional string | 排序方向('asc'或'desc') | | per_page | optional number | 每页结果数(最大100) | | page | optional number | 页码 | **返回**: issues和PR搜索结果 ### search_users 搜索GitHub用户 | 输入参数 | Type | 描述 | | -------- | --------------- | ----------------------------------------- | | q | string | 使用GitHub用户搜索语法的搜索词 | | sort | optional string | 排序字段(followers, repositories, joined) | | order | optional string | 排序方向('asc'或'desc') | | per_page | optional number | 每页结果数(最大100) | | page | optional number | 页码 | **返回**: 用户搜索结果 ### list_commits 获取仓库分支的提交记录 | 输入参数 | Type | 描述 | | -------- | --------------- | ---------- | | owner | string | 仓库所有者 | | repo | string | 仓库名称 | | page | optional string | 页码 | | per_page | optional string | 每页记录数 | | sha | optional string | 分支名称 | **返回**: 提交记录列表 ### get_issue 获取仓库中某个issue的内容 | 输入参数 | Type | 描述 | | ------------ | ------ | ----------------- | | owner | string | 仓库所有者 | | repo | string | 仓库名称 | | issue_number | number | 要获取的issue编号 | **返回**: GitHub Issue对象及详情 ### get_pull_request 获取特定PR的详情 | 输入参数 | Type | 描述 | | ----------- | ------ | ---------- | | owner | string | 仓库所有者 | | repo | string | 仓库名称 | | pull_number | number | PR编号 | **返回**: 包含diff和审查状态的PR详情 ### list_pull_requests 列出和筛选仓库PR | 输入参数 | Type | 描述 | | --------- | --------------- | ------------------------------------------------------------ | | owner | string | 仓库所有者 | | repo | string | 仓库名称 | | state | optional string | 状态筛选('open', 'closed', 'all') | | head | optional string | 按head用户/组织和分支筛选 | | base | optional string | 按base分支筛选 | | sort | optional string | 排序方式('created', 'updated', 'popularity', 'long-running') | | direction | optional string | 排序方向('asc', 'desc') | | per_page | optional number | 每页结果数(最大100) | | page | optional number | 页码 | **返回**: PR详情数组 ### create_pull_request_review 创建PR审查 | 输入参数 | Type | 描述 | | ----------- | --------------- | ------------------------------------------------------------------------------ | | owner | string | 仓库所有者 | | repo | string | 仓库名称 | | pull_number | number | PR编号 | | body | string | 审查评论文本 | | event | string | 审查动作('APPROVE', 'REQUEST_CHANGES', 'COMMENT') | | commit_id | optional string | 要审查的提交SHA | | comments | optional array | 行级评论数组(每个包含: path: 文件路径 position: diff中的行位置 body: 评论文本) | **返回**: 创建的审查详情 ### merge_pull_request 合并PR | 输入参数 | Type | 描述 | | -------------- | --------------- | ------------------------------------- | | owner | string | 仓库所有者 | | repo | string | 仓库名称 | | pull_number | number | PR编号 | | commit_title | optional string | 合并提交的标题 | | commit_message | optional string | 合并提交的额外详情 | | merge_method | optional string | 合并方式('merge', 'squash', 'rebase') | **返回**: 合并结果详情 ### get_pull_request_files 获取PR中更改的文件列表 | 输入参数 | Type | 描述 | | ----------- | ------ | ---------- | | owner | string | 仓库所有者 | | repo | string | 仓库名称 | | pull_number | number | PR编号 | **返回**: 包含patch和状态详情的更改文件数组 ### get_pull_request_status 获取PR所有状态检查的合并状态 | 输入参数 | Type | 描述 | | ----------- | ------ | ---------- | | owner | string | 仓库所有者 | | repo | string | 仓库名称 | | pull_number | number | PR编号 | **返回**: 合并的状态检查结果和单个检查详情 ### update_pull_request_branch 用base分支的最新更改更新PR分支(相当于GitHub的"Update branch"按钮) | 输入参数 | Type | 描述 | | ----------------- | --------------- | --------------------- | | owner | string | 仓库所有者 | | repo | string | 仓库名称 | | pull_number | number | PR编号 | | expected_head_sha | optional string | PR的HEAD引用的预期SHA | **返回**: 分支更新成功时的成功消息 ### get_pull_request_comments 获取PR的审查评论 | 输入参数 | Type | 描述 | | ----------- | ------ | ---------- | | owner | string | 仓库所有者 | | repo | string | 仓库名称 | | pull_number | number | PR编号 | **返回**: 包含评论文本、作者和diff位置等详情的PR审查评论数组 ### get_pull_request_reviews 获取PR的审查记录 | 输入参数 | Type | 描述 | | ----------- | ------ | ---------- | | owner | string | 仓库所有者 | | repo | string | 仓库名称 | | pull_number | number | PR编号 | **返回**: 包含审查状态(APPROVED, CHANGES_REQUESTED等)、审查者和审查正文等详情的PR审查数组 ## 搜索查询语法 ### 代码搜索 - `language:javascript`: 按编程语言搜索 - `repo:owner/name`: 在特定仓库中搜索 - `path:app/src`: 在特定路径中搜索 - `extension:js`: 按文件扩展名搜索 **示例**: `q: "import express" language:typescript path:src/` ### Issues搜索 - `is:issue` 或 `is:pr`: 按类型筛选 - `is:open` 或 `is:closed`: 按状态筛选 - `label:bug`: 按标签搜索 - `author:username`: 按作者搜索 **示例**: `q: "内存泄漏" is:issue is:open label:bug` ### 用户搜索 - `type:user` 或 `type:org`: 按账户类型筛选 - `followers:>1000`: 按关注者数量筛选 - `location:London`: 按位置搜索 **示例**: `q: "全栈开发" location:北京 followers:>100` ## Personal Access Token (个人访问令牌)相关 1. 选择令牌可访问的仓库范围(公开、全部或选定) 2. 创建具有repo作用域的令牌("私有仓库的完全控制") 3. 或者如果仅使用公开仓库,选择仅public_repo作用域 4. 复制保存生成的令牌 --- ## Gitlab 服务 MCP 接入 # Gitlab 服务 MCP 接入 通过 MCP 协议提供 Gitlab 服务调用,支持项目仓库管理、文件操作等功能。 [部署 MCP Server](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp&p&mcp-template=mcp-gitlab) --- ## 环境变量 - 需要将 GITLAB_PERSONAL_ACCESS_TOKEN 配置为**您在 Gitlab 上创建的 [Personal access token](https://gitlab.com/-/user_settings/personal_access_tokens)** ## 使用说明 [Gitlab MCP Server 参考文档](https://github.com/modelcontextprotocol/servers/tree/main/src/gitlab) ## 🗺️ 功能清单 | 工具标识 | 功能描述 | 核心参数 | |-------------------------|-----------------------|----------------------------------------| | `create_or_update_file` | 文件创建/更新 | project_id, file_path, content, branch | | `push_files` | 批量推送文件 | project_id, branch, files | | `search_repositories` | 仓库搜索 | search, page | | `create_repository` | 创建仓库 | name, visibility | | `get_file_contents` | 获取文件或目录的内容 | project_id, file_path, ref | | `create_issue` | 创建issue | project_id, title, description | | `create_merge_request` | 创建合并请求 | project_id, source_branch, target_branch| | `fork_repository` | 分叉仓库 | project_id, namespace | | `create_branch` | 创建分支 | project_id, branch, ref | ## 仓库地址 [https://github.com/modelcontextprotocol/servers/tree/main/src/gitlab](https://github.com/modelcontextprotocol/servers/tree/main/src/gitlab) ## 使用方式 - [在云开发 Agent 中使用](https://docs.cloudbase.net/ai/mcp/use/agent) - [在 MCP Host 中使用](https://docs.cloudbase.net/ai/mcp/use/mcp-host) - [通过 SDK 接入](https://docs.cloudbase.net/ai/mcp/use/sdk) [云开发 MCP 控制台](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp) ## 参数说明 ### 1. create_or_update_file 文件创建/更新 | 参数名称 | 类型 | 是否可选 | 功能描述 | |--------------------|-----------------|----------|--------------------------------------------------------------------------| | `project_id` | string | 必填 | 项目 ID 或 URL 编码路径 | | `file_path` | string | 必填 | 文件存储路径(需包含扩展名) | | `content` | string | 必填 | 文件内容 | | `commit_message` | string | 必填 | 提交描述 | | `branch` | string | 必填 | 创建/更新文件的分支| | `previous_path` | string | 可选 | 要移动/重命名的文件路径 | **返回**: 文件内容和提交详情 ### 2. push_files 批量推送文件 | 参数名称 | 类型 | 是否可选 | 功能描述 | |--------------------|-----------------|----------|--------------------------------------------------------------------------| | `project_id` | string | 必填 | 项目 ID 或 URL 编码路径 | | `branch` | string | 必填 | 要推送到的分支 | | `files` | array | 必填 | 要推送的文件,每个文件包含 file_path 和 content| | `commit_message` | string | 必填 | 提交信息 | **返回**: 更新的分支引用 ### 3. search_repositories 仓库搜索 | 参数名称 | 类型 | 是否可选 | 功能描述 | |--------------------|-----------------|----------|--------------------------------------------------------------------------| | `search` | string | 必填 | 搜索关键词 | | `page` | number | 可选 | 分页页码 | | `per_page` | number | 可选 | 每页结果数(默认20) | **返回**: 仓库搜索结果 ### 4. create_repository 创建仓库 | 参数名称 | 类型 | 是否可选 | 功能描述 | |---------------------------|-----------------|----------|--------------------------------------------------------------------------| | `name` | string | 必填 | 仓库名称 | | `description` | string | 可选 | 项目描述 | | `visibility` | string | 可选 | 可见性级别:`private`/`internal`/`public`(默认private) | | `initialize_with_readme` | boolean | 可选 | 是否自动生成README.md | **返回**: 创建的项目详细信息 ### 5. get_file_contents 获取文件或目录的内容 | 参数名称 | 类型 | 是否可选 | 功能描述 | |--------------------|-----------------|----------|--------------------------------------------------------------------------| | `project_id` | string | 必填 | 项目 ID 或 URL 编码路径 | | `file_path` | string | 必填 | 文件/目录路径 | | `ref` | string | 可选 | 要获取内容的分支/标签/提交 | **返回**: 文件/目录内容 ### 6. create_issue 创建issue | 参数名称 | 类型 | 是否可选 | 功能描述 | |--------------------|-----------------|----------|--------------------------------------------------------------------------| | `project_id` | string | 必填 | 项目 ID 或 URL 编码路径 | | `title` | string | 必填 | issue 标题 | | `description` | string | 可选 | issue 描述 | | `assignee_ids` | number[] | 可选 | 被指派人ID数组 | | `labels` | string[] | 可选 | 标签数组 | | `milestone_id` | number | 可选 | 里程碑ID | **返回**: 创建的 issue 详情 ### 7. create_merge_request 创建合并请求 | 参数名称 | 类型 | 是否可选 | 功能描述 | |------------------------|-----------------|----------|--------------------------------------------------------------------------| | `project_id` | string | 必填 | 项目 ID 或 URL 编码路径 | | `source_branch` | string | 必填 | 源分支名称 | | `target_branch` | string | 必填 | 要合并到的分支 | | `draft` | boolean | 可选 | 作为草稿合并请求创建 | | `allow_collaboration` | boolean | 可选 | 允许来自上游成员的提交 | | `title` | string | 必填 | MR 标题 | | `description` | string | 可选 | MR 描述 | **返回**: 创建的合并请求详情 ### 8. fork_repository 分叉仓库 | 参数名称 | 类型 | 是否可选 | 功能描述 | |--------------------|-----------------|----------|--------------------------------------------------------------------------| | `project_id` | string | 必填 | 项目 ID 或 URL 编码路径 | | `namespace` | string | 可选 | 要fork到的目标命名空间 | **返回**: 分叉项目的详细信息 ### 9. create_branch 创建分支 | 参数名称 | 类型 | 是否可选 | 功能描述 | |--------------------|-----------------|----------|--------------------------------------------------------------------------| | `project_id` | string | 必填 | 项目 ID 或 URL 编码路径 | | `branch` | string | 必填 | 新分支名称 | | `ref` | string | 可选 | 源分支 | **返回**: 创建的分支引用 --- ## 国金证券A股情绪脉冲指数 MCP 服务 # 国金证券A股情绪脉冲指数 MCP 服务 AIGC 时代,量化市场情绪已成为投资决策的重要参考。国金证券A股情绪脉冲指数 MCP Server,基于大数据与AI技术,面向开发者和投资者,提供**沪深A股市场实时情绪指数**,每5分钟更新一次,助力智能投研、行情监控、策略辅助等多元场景。 适用于行情监控、智能投顾、策略回测、情绪分析等多种AI场景。 [前往云开发平台创建 MCP Server](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp) --- ## 环境变量 - **API_KEY**:服务访问密钥,默认值为 `gjzqtest`,如需商业合作请联系官方获取专属密钥。 --- ## 指数说明 - **情绪指数 > 75**:市场高度亢奋,投资者情绪积极,短期有回调风险。 - **情绪指数 ⚠️ 本指数仅供参考,不构成投资建议。 --- ## 应用示例 - **智能投顾**:结合情绪脉冲指数,辅助判断市场拐点,优化资产配置。 - **行情监控**:实时监测市场情绪波动,预警极端情绪风险。 - **策略回测**:将情绪指数作为因子,丰富量化策略维度。 --- ## 🧩 功能清单 | 工具标识 | 功能描述 | 核心参数 | | ---------------- | ------------------------ | ------------------ | | `getSentiment` | 查询当前A股市场情绪指数 | `无`(实时返回) | --- ## 关键特性 - **实时更新**:每5分钟自动刷新,紧跟市场脉搏 - **全云托管**:零运维成本,自动升级 - **易集成**:标准 MCP 协议,主流 AI/Agent/SDK 皆可用 - **安全合规**:API Key 认证,数据安全可控 --- ## 常见问题(FAQ) **Q:服务是否收费?** A:目前限时免费体验,未来如有调整会提前公告。如需商业合作请联系官方。 **Q:指数如何解读?** A:数值越高市场越乐观,越低越谨慎,极端值提示短期风险或机会。 **Q:如何获取专属API Key?** A:请联系官方邮箱申请。 --- ## 联系方式 - 邮箱:[zhangjunhang@gjzq.com.cn](mailto:zhangjunhang@gjzq.com.cn) - 联系人:张女士 --- ## 腾讯混元3D MCP # 腾讯混元3D MCP 通过 MCP 协议提供腾讯混元 3D 服务调用,支持基于文本/图片调用 AI 大模型生成 3D 模型 [前往云开发平台运行 MCP Server](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp&p&mcp-template=mcp-hunyuan-3d) ![](https://7463-tcb-advanced-a656fc-1257967285.tcb.qcloud.la/%E4%BC%81%E4%B8%9A%E5%BE%AE%E4%BF%A1%E6%88%AA%E5%9B%BE_4977e0a4-351a-492e-949f-10f2755801d3.png) --- ## 环境变量配置 在运行之前,需要设置以下环境变量: - `TENCENTCLOUD_SECRET_KEY`: 腾讯云 API SecretKey - `TENCENTCLOUD_SECRET_ID`: 腾讯云 API SecretId ## 🗺️ 功能清单 | 工具标识 | 功能描述 | 核心参数 | | ---------------------- | ------------------------ | ----------------------------------------- | | `submitHunyuanTo3DJob` | 提交3D内容生成任务 | `Prompt`/`ImageBase64`/`ImageUrl`(三选一) | | `queryHunyuanTo3DJob` | 查询3D生成任务状态和结果 | `JobId`(字符串类型,必填) | ## 相关链接 - [腾讯混元3D](https://3d.hunyuan.tencent.com/) - [腾讯混元3D接口接入文档](https://cloud.tencent.com/document/product/1729/117861) ## 🔌 使用方式 - [在云开发 Agent 中使用](https://docs.cloudbase.net/ai/mcp/use/agent) - [在 MCP Host 中使用](https://docs.cloudbase.net/ai/mcp/use/mcp-host) - [通过 SDK 接入](https://docs.cloudbase.net/ai/mcp/use/sdk) --- [云开发 MCP 控制台](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp) --- ## 快递100 MCP 接入 # 快递100 MCP 接入 快递100 MCP Server提供快递信息查询、快递运费预估比价、快递时效查询(含发货前时效查询与在途动态时效查询)等功能。 [部署 MCP Server](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp&p&mcp-template=mcp-kuaidi100) --- ## 环境变量 - **KUAIDI100_API_KEY**:快递100 API KEY,前往 [登录快递100获取](https://poll.kuaidi100.com/manager/page/myinfo/enterprise) ## 🗺️ 功能清单 | 工具标识 | 功能描述 | 核心参数 | | ---------------------------------- | -------------------------------------------------- | -------- | | `query_trace` | 查询物流轨迹服务 | 快递单号, 手机号 | | `estimate_time` | 查询物流轨迹服务 | 快递单号, 手机号 | | `estimate_time_with_logistic` | 预估快递送达时间 | 快递公司编码, 收寄件地址, 下单时间, 业务类型, 历史物流轨迹 | | `estimate_price` | 预估快递运费 | 快递公司, 收寄件地址, 重量 | ## 仓库地址 [https://github.com/kuaidi100-api/kuaidi100-MCP](https://github.com/kuaidi100-api/kuaidi100-MCP) --- ## 🔌 使用方式 - [在云开发 Agent 中使用](https://docs.cloudbase.net/ai/mcp/use/agent) - [在 MCP Host 中使用](https://docs.cloudbase.net/ai/mcp/use/mcp-host) - [通过 SDK 接入](https://docs.cloudbase.net/ai/mcp/use/sdk) --- [云开发 MCP 控制台](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp) --- ## Lighthouse MCP Server # Lighthouse MCP Server 基于腾讯云 Lighthouse API 开发的 MCP 服务,实现云服务器智能化管理。 [前往云开发平台创建 MCP Server](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp) 该服务器提供以下核心功能: - 实例管理 - 获取实例列表 - 获取可用地域 - 实例监控数据查询 - 实例自我诊断 - 安全管理 - 防火墙规则配置 --- ## 环境变量配置 在运行之前,需要设置以下环境变量: - `TENCENTCLOUD_SECRET_KEY`: 腾讯云 API SecretKey - `TENCENTCLOUD_SECRET_ID`: 腾讯云 API SecretId ## 🛠️ 工具清单 | 工具标识 | 功能描述 | 典型应用场景 | |-------------------------|----------------------------------|--------------------------| | `get_instances` | 获取服务器实例列表 | 实例状态监控、资产管理 | | `get_monitor_data` | 查询实例监控数据 | 性能分析、故障排查 | | `set_firewall` | 配置防火墙规则 | 网络安全管控 | | `get_regions` | 获取可用地域列表 | 资源部署规划 | | `self_test` | 执行实例自我诊断 | 安全审计、系统健康检查 | --- ## 工具列表 服务器提供以下工具: 1. `get_instances`: 获取用户名下的服务器实例列表 - 返回实例名称、实例ID、系统盘ID等信息 2. `get_monitor_data`: 获取实例监控数据 - 支持不同时间范围的数据查询 - 自动适配查询间隔 - 支持多种监控指标 3. `set_firewall`: 设置防火墙规则 - 支持配置端口、协议、访问控制等 - 支持 IPv4/IPv6 4. `get_regions`: 获取可用地域列表 5. `self_test`: 实例自我诊断 - 支持多维度安全检查 - 生成风险评估报告 - 支持深度诊断 --- [云开发 MCP 控制台](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp) --- ## MarkItDown服务 MCP 接入 # MarkItDown服务 MCP 接入 通过 MCP 协议来调用 MarkItDown,可以将任意类型的文件转换为 markdown 格式。 [前往云开发平台运行 MCP Server](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp&p&mcp-template=mcp-markitdown) --- ## 🗺️ 功能清单 | 工具标识 | 功能描述 | 核心参数 | |-----------------------|--------------------------------------------|----------------------------------| | `convert_to_markdown` | 将 http/https/file/data 协议描述的URI资源转换为Markdown格式 | `uri`(字符串类型,必填) | ## 仓库地址 [https://github.com/microsoft/markitdown/tree/main/packages/markitdown-mcp](https://github.com/microsoft/markitdown/tree/main/packages/markitdown-mcp) --- ## 🔌 使用方式 - [在云开发 Agent 中使用](https://docs.cloudbase.net/ai/mcp/use/agent) - [在 MCP Host 中使用](https://docs.cloudbase.net/ai/mcp/use/mcp-host) - [通过 SDK 接入](https://docs.cloudbase.net/ai/mcp/use/sdk) --- [云开发 MCP 控制台](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp) --- ## 记忆模块 MCP Server # 记忆模块 MCP Server 通过 MCP 协议提供标准化 AI 工具调用,支持 Agent 智能体快速集成。 [前往云开发平台通过记忆模块模板创建 MCP Server](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp&mcp-template=cloudbase-ai-base) --- ## 🛠️ 工具清单 | 工具标识 | 功能描述 | 典型应用场景 | | --------------------- | -------------------------- | -------------------------- | | `create_entities` | 在知识图谱中创建新实体 | 知识图谱构建、实体管理 | | `create_relations` | 创建实体间的关系 | 建立知识关联、关系网络构建 | | `add_observations` | 为实体添加观察项 | 丰富实体信息、记录观察数据 | | `delete_entities` | 删除实体及其关联关系 | 知识图谱维护、数据清理 | | `delete_observations` | 删除实体的观察项 | 数据修正、观察项管理 | | `delete_relations` | 删除实体间的关系 | 关系网络维护、错误关系修正 | | `read_graph` | 读取整个知识图谱 | 知识图谱导出、全局查看 | | `search_nodes` | 根据条件搜索节点及相关关系 | 知识查询、关联分析 | | `open_nodes` | 读取特定节点及其关联关系 | 定点知识查询、节点详情查看 | --- ## 🔌 使用方式 - [在云开发 Agent 中使用](https://docs.cloudbase.net/ai/mcp/use/agent) - [在 MCP Host 中使用](https://docs.cloudbase.net/ai/mcp/use/mcp-host) - [通过 SDK 接入](https://docs.cloudbase.net/ai/mcp/use/sdk) --- [云开发 MCP 控制台](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp) --- ## Mermaid 服务 MCP 接入 # Mermaid 服务 MCP 接入 通过 MCP 协议提供将 Mermaid 图表转换为 PNG 图像能力。 [前往云开发平台运行 MCP Server](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp&p&mcp-template=mcp-mermaid) --- ## 🗺️ 功能清单 | 工具标识 | 功能描述 | 核心参数 | |--------------|---------------------------------|-------------------------------------------------------------------------| | `generate` | 从Mermaid标记生成PNG图片 | `code`(Mermaid标记代码), 可选`theme`(主题), `backgroundColor`(背景色), `name`(图表名称), `folder`(保存路径) | ## 仓库地址 [https://github.com/peng-shawn/mermaid-mcp-server](https://github.com/peng-shawn/mermaid-mcp-server) --- ## 🔌 使用方式 - [在云开发 Agent 中使用](https://docs.cloudbase.net/ai/mcp/use/agent) - [在 MCP Host 中使用](https://docs.cloudbase.net/ai/mcp/use/mcp-host) - [通过 SDK 接入](https://docs.cloudbase.net/ai/mcp/use/sdk) --- [云开发 MCP 控制台](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp) --- ## MongoDB 数据库服务 MCP 接入 # MongoDB 数据库服务 MCP 接入 通过 MCP 协议提供与 MongoDB 数据库的安全交互。 [前往云开发平台运行 MCP Server](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp&p&mcp-template=mcp-mongo) --- ## 环境变量 - 需要将 **MONGO_CONNECT_STRING** 配置为 **MongoDB 连接字符串**(例如:`mongodb://user:password@host:port/database?authSource=admin`) ## 🗺️ 功能清单 ### MongoDB Atlas 工具 *注意:Atlas 工具仅在配置部分设置凭据时可用* | 命令名称 | 功能描述 | |---------------------------|-------------------------------------------| | `atlas-list-orgs` | 列出 MongoDB Atlas 组织 | | `atlas-list-projects` | 列出 MongoDB Atlas 项目 | | `atlas-create-project` | 创建新的 MongoDB Atlas 项目 | | `atlas-list-clusters` | 列出 MongoDB Atlas 集群 | | `atlas-inspect-cluster` | 检查特定的 MongoDB Atlas 集群 | | `atlas-create-free-cluster` | 创建免费的 MongoDB Atlas 集群 | | `atlas-connect-cluster` | 连接到 MongoDB Atlas 集群 | | `atlas-inspect-access-list` | 检查可访问 MongoDB Atlas 集群的 IP/CIDR 范围 | | `atlas-create-access-list` | 配置 MongoDB Atlas 集群的 IP/CIDR 访问列表 | | `atlas-list-db-users` | 列出 MongoDB Atlas 数据库用户 | | `atlas-create-db-user` | 创建 MongoDB Atlas 数据库用户 | | `atlas-list-alerts` | 列出项目的 MongoDB Atlas 警报 | ### MongoDB 数据库工具 | 命令名称 | 功能描述 | |---------------------------|-------------------------------------------| | `connect` | 连接到 MongoDB 实例 | | `find` | 对 MongoDB 集合运行查找查询 | | `aggregate` | 对 MongoDB 集合运行聚合查询 | | `count` | 获取 MongoDB 集合中的文档数量 | | `insert-one` | 向 MongoDB 集合插入单个文档 | | `insert-many` | 向 MongoDB 集合插入多个文档 | | `create-index` | 为 MongoDB 集合创建索引 | | `update-one` | 更新 MongoDB 集合中的单个文档 | | `update-many` | 更新 MongoDB 集合中的多个文档 | | `rename-collection` | 重命名 MongoDB 集合 | | `delete-one` | 从 MongoDB 集合删除单个文档 | | `delete-many` | 从 MongoDB 集合删除多个文档 | | `drop-collection` | 从 MongoDB 数据库中删除集合 | | `drop-database` | 删除 MongoDB 数据库 | | `list-databases` | 列出 MongoDB 连接的所有数据库 | | `list-collections` | 列出给定数据库的所有集合 | | `collection-indexes` | 描述集合的索引 | | `collection-schema` | 描述集合的模式 | | `collection-storage-size` | 获取集合的大小(MB) | | `db-stats` | 返回 MongoDB 数据库的统计信息 | ## 仓库地址 [https://github.com/mongodb-js/mongodb-mcp-server](https://github.com/mongodb-js/mongodb-mcp-server) --- ## 🔌 使用方式 - [在云开发 Agent 中使用](https://docs.cloudbase.net/ai/mcp/use/agent) - [在 MCP Host 中使用](https://docs.cloudbase.net/ai/mcp/use/mcp-host) - [通过 SDK 接入](https://docs.cloudbase.net/ai/mcp/use/sdk) --- [云开发 MCP 控制台](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp) --- ## MySQL 数据库服务 MCP 接入 # MySQL 数据库服务 MCP 接入 通过 MCP 协议提供与 MySQL 数据库的安全交互。 提供 MySQL 数据库的 API 接口,支持列出可用的 MySQL 表作为资源、执行 SQL 查询并进行适当的错误处理等功能 [前往云开发平台运行 MCP Server](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp&p&mcp-template=mcp-mysql) --- ## 环境变量 - 需要将 **MYSQL_HOST** 配置为 **数据库服务器地址** - 需要将 **MYSQL_PORT** 配置为 **数据库端口号** - 需要将 **MYSQL_USER** 配置为 **数据库登录用户名** - 需要将 **MYSQL_PASSWORD** 配置为 **数据库登录密码** - 需要将 **MYSQL_DATABASE** 配置为 **要连接的数据库名称** ## 🗺️ 功能清单 | 工具标识 | 功能描述 | 核心参数 | |----------------------------------|-----------------------------------------|------------------------------------| | `execute_sql` | 在 MySQL 服务器上执行 SQL 查询 | 待执行的 SQL 查询语句 | ## 仓库地址 [https://github.com/designcomputer/mysql_mcp_server](https://github.com/designcomputer/mysql_mcp_server) --- ## 🔌 使用方式 - [在云开发 Agent 中使用](https://docs.cloudbase.net/ai/mcp/use/agent) - [在 MCP Host 中使用](https://docs.cloudbase.net/ai/mcp/use/mcp-host) - [通过 SDK 接入](https://docs.cloudbase.net/ai/mcp/use/sdk) --- [云开发 MCP 控制台](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp) --- ## Notion 服务 MCP 接入 # Notion 服务 MCP 接入 通过 MCP 协议提供 Notion API 服务调用,使 LLM 能够与 Notion 工作区进行交互。此外,它采用 Markdown 转换来减少与 LLMs 通信时的上下文大小,优化令牌使用,使交互更加高效。 [部署 MCP Server](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp&p&mcp-template=mcp-notion) --- ## 环境变量 - 需要将 NOTION_API_TOKEN 配置为**您在 Notion 上创建的 [API integration token](https://www.notion.so/profile/integrations)** - 可选配置 NOTION_MARKDOWN_CONVERSION,设置为“true”以启用实验性的 Markdown 转换。这可以显著减少查看内容时的令牌消耗,但在尝试编辑页面内容时可能会导致问题 ## 🗺️ 功能清单 | 工具标识 | 功能描述 | 核心参数 | |----------------------------------|-----------------------------------------|---------------------------------------------------------------------------------------------| | `notion_append_block_children` | 追加子区块到目标父区块 | `block_id`, `children` | | `notion_retrieve_block` | 获取指定区块的详细信息 | `block_id` | | `notion_retrieve_block_children` | 获取父区块的子区块列表 | `block_id`, `start_cursor`, `page_size` | | `notion_delete_block` | 删除指定区块 | `block_id` | | `notion_retrieve_page` | 获取指定页面的详细信息 | `page_id` | | `notion_update_page_properties` | 更新页面属性 | `page_id`, `properties` | | `notion_create_database` | 创建数据库 | `parent`, `properties`, `title` | | `notion_query_database` | 查询数据库中的记录 | `database_id`, `filter`, `sorts`, `start_cursor`, `page_size` | | `notion_retrieve_database` | 获取指定数据库的详细信息 | `database_id` | | `notion_update_database` | 更新数据库信息 | `database_id`, `title`, `description`, `properties` | | `notion_create_database_item` | 在数据库中创建新条目 | `database_id`, `properties` | | `notion_search` | 搜索页面或数据库 | `query`, `filter`, `sort`, `start_cursor`, `page_size` | | `notion_list_all_users` | 列出工作区中的所有用户(企业版功能) | `start_cursor`, `page_size` | | `notion_retrieve_user` | 获取指定用户的详细信息(企业版功能) | `user_id` | | `notion_retrieve_bot_user` | 获取机器人用户的信息 | 无 | | `notion_create_comment` | 创建评论 | `rich_text`, `parent`, `discussion_id` | | `notion_retrieve_comments` | 获取与区块或页面相关的评论列表 | `block_id`, `start_cursor`, `page_size` | ## 仓库地址 [https://github.com/suekou/mcp-notion-server/tree/main](https://github.com/suekou/mcp-notion-server/tree/main) --- ## 🔌 使用方式 - [在云开发 Agent 中使用](https://docs.cloudbase.net/ai/mcp/use/agent) - [在 MCP Host 中使用](https://docs.cloudbase.net/ai/mcp/use/mcp-host) - [通过 SDK 接入](https://docs.cloudbase.net/ai/mcp/use/sdk) --- [云开发 MCP 控制台](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp) ## 参数说明 ### 1. notion_append_block_children | 参数名称 | 描述 | 参数类型 | 参数描述 | |----------------|---------------------------|----------|--------------------------------------------------------------------------| | block_id | 目标父区块ID | string | 需要追加子区块的父区块标识符 | | children | 子区块对象列表 | array | 要追加的区块对象数组(遵循Notion Block Object规范) | **返回**: 有关附加块的信息 ### 2. notion_retrieve_block | 参数名称 | 描述 | 参数类型 | 参数描述 | |----------------|---------------------------|----------|--------------------------------------------------------------------------| | block_id | 目标区块ID | string | 需要获取信息的区块标识符 | **返回**: 有关该区块的详细信息 ### 3. notion_retrieve_block_children | 参数名称 | 描述 | 参数类型 | 参数描述 | |----------------|---------------------------|----------|--------------------------------------------------------------------------| | block_id | 父区块ID | string | 需要获取子列表的父区块标识符 | | start_cursor | 分页起始位置 | string | 可选,分页查询起始游标(来自前一次响应) | | page_size | 返回数量限制 | number | 可选,单次请求最大返回数量(默认100,最大值100) | **返回**: 子块列表 ### 4. notion_delete_block | 参数名称 | 描述 | 参数类型 | 参数描述 | |----------------|---------------------------|----------|--------------------------------------------------------------------------| | block_id | 待删除区块ID | string | 需要删除的区块标识符 | **返回**: 删除确认 ### 5. notion_retrieve_page | 参数名称 | 描述 | 参数类型 | 参数描述 | |----------------|---------------------------|----------|--------------------------------------------------------------------------| | page_id | 目标页面ID | string | 需要获取详细信息的页面标识符 | **返回**: 关于页面的详细信息 ### 6. notion_update_page_properties | 参数名称 | 描述 | 参数类型 | 参数描述 | |----------------|---------------------------|----------|--------------------------------------------------------------------------| | page_id | 目标页面ID | string | 需要更新的页面标识符 | | properties | 更新属性对象 | object | 包含需要更新的属性键值对(遵循Notion Properties规范) | **返回**: 有关更新页面的信息 ### 7. notion_create_database | 参数名称 | 描述 | 参数类型 | 参数描述 | |----------------|---------------------------|----------|--------------------------------------------------------------------------| | parent | 父对象信息 | object | 数据库的父级对象(需包含page_id或workspace信息) | | properties | 属性结构定义 | object | 数据库的字段类型定义 | | title | 数据库标题 | array | 可选,标题富文本数组 | **返回**: 有关创建的数据库的信息 ### 8. notion_query_database | 参数名称 | 描述 | 参数类型 | 参数描述 | |----------------|---------------------------|----------|--------------------------------------------------------------------------| | database_id | 目标数据库ID | string | 需要查询的数据库标识符 | | filter | 过滤条件 | object | 可选,查询过滤条件 | | sorts | 排序规则 | array | 可选,结果排序规则数组 | | start_cursor | 分页起始位置 | string | 可选,分页查询起始游标 | | page_size | 返回数量限制 | number | 可选,单次请求最大返回数量(默认100,最大值100) | **返回**: 查询结果列表 ### 9. notion_retrieve_database | 参数名称 | 描述 | 参数类型 | 参数描述 | |----------------|---------------------------|----------|--------------------------------------------------------------------------| | database_id | 目标数据库ID | string | 需要获取信息的数据库标识符 | **返回**: 关于数据库的详细信息 ### 10. notion_update_database | 参数名称 | 描述 | 参数类型 | 参数描述 | |----------------|---------------------------|----------|--------------------------------------------------------------------------| | database_id | 目标数据库ID | string | 需要更新的数据库标识符 | | title | 新标题 | array | 可选,标题数组 | | description | 新描述 | array | 可选,描述数组 | | properties | 更新属性架构 | object | 可选,新的属性字段定义 | **返回**: 有关更新数据库的信息 ### 11. notion_create_database_item | 参数名称 | 描述 | 参数类型 | 参数描述 | |----------------|---------------------------|----------|--------------------------------------------------------------------------| | database_id | 目标数据库ID | string | 需要添加条目的数据库标识符 | | properties | 条目属性值 | object | 必须匹配数据库结构的属性 | **返回**: 有关新创建数据库项的信息 ### 12. notion_search | 参数名称 | 描述 | 参数类型 | 参数描述 | |----------------|---------------------------|----------|--------------------------------------------------------------------------| | query | 搜索关键词 | string | 可选,在标题中搜索的关键词 | | filter | 结果类型过滤 | object | 可选,限制结果为pages/databases(默认返回全部) | | sort | 排序规则 | object | 可选,结果排序规则 | | start_cursor | 分页起始位置 | string | 可选,分页查询起始游标 | | page_size | 返回数量限制 | number | 可选,单次请求最大返回数量(默认100,最大值100) | **返回**: 匹配页面或数据库的列表 ### 13. notion_list_all_users **此功能需要升级到 Notion 企业计划,并使用组织 API 密钥以避免权限错误** | 参数名称 | 描述 | 参数类型 | 参数描述 | |----------------|---------------------------|----------|--------------------------------------------------------------------------| | start_cursor | 分页起始位置 | string | 可选,分页查询起始游标 | | page_size | 返回数量限制 | number | 可选,单次请求最大返回数量(最大值100) | **返回**: 工作区中所有用户的分页列表 ### 14. notion_retrieve_user **此功能需要升级到 Notion 企业计划,并使用组织 API 密钥以避免权限错误** | 参数名称 | 描述 | 参数类型 | 参数描述 | |----------------|---------------------------|----------|--------------------------------------------------------------------------| | user_id | 目标用户ID | string | 需要获取信息的用户标识符 | **返回**: 关于指定用户的详细信息 ### 15. notion_retrieve_bot_user **返回**: 关于机器人用户的信息,包括授权集成的人的详细信息 ### 16. notion_create_comment | 参数名称 | 描述 | 参数类型 | 参数描述 | |----------------|---------------------------|----------|--------------------------------------------------------------------------| | rich_text | 评论内容 | array | 富文本内容数组(包含text对象) | | parent | 关联页面 | object | 可选,必须包含page_id(与discussion_id二选一) | | discussion_id | 讨论ID | string | 可选,现有讨论标识符 | **返回**: 有关创建的评论的信息 ### 17. notion_retrieve_comments | 参数名称 | 描述 | 参数类型 | 参数描述 | |----------------|---------------------------|----------|--------------------------------------------------------------------------| | block_id | 目标区块/页面ID | string | 需要获取评论的区块或页面标识符 | | start_cursor | 分页起始位置 | string | 可选,分页查询起始游标 | | page_size | 返回数量限制 | number | 可选,单次请求最大返回数量(最大值100) | **返回**: 与指定块或页面相关的评论的分页列表 --- ## MCP 服务接入 — Pinecone 向量数据库 # MCP 服务接入 — Pinecone 向量数据库 通过 MCP 协议提供 Pinecone 高效的向量检索能力, 可以完成设置索引、插入数据或文本搜索等功能。 [部署 MCP Server](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp&p&mcp-template=mcp-pinecone) --- ## 环境变量 - 需要将 **PINECONE_API_KEY** 配置为 **[您的 Pinecone API 密钥](https://app.pinecone.io/)** ## 使用说明 [Pinecone MCP Server 参考文档](https://github.com/pinecone-io/pinecone-mcp/tree/main) ## 🗺️ 功能清单 | 工具标识 | 功能描述 | 核心参数 | |---------------------|------------------------------------------------------|-------------------------------------------------------------| | `search-docs` | 搜索 Pinecone 官方文档,回答相关问题 | query 查询文本 | | `list-indexes` | 列出所有 Pinecone 索引 | 无需参数 | | `describe-index` | 描述某个索引的配置 | name(索引名称) | | `describe-index-stats` | 提供索引的数据统计信息,包括记录数量和可用的命名空间 | name(索引名称) | | `create-index-for-model` | 创建一个新的索引,使用集成的推理模型将文本嵌入为向量 | name(索引名称) 、[embed 配置](#EmbedOption) 参考 EmbedOption | | `upsert-records` | 向索引中插入或更新记录,使用集成的推理模型进行文本嵌入 | name(索引名称)、namespace (命令空间,自行指定) records(记录数组) ,例 [{ "_id": "rec1", "chunk_text": "The Eiffel Tower was completed in 1889 and stands in Paris, France.", "category": "history" }] | | `search-records` | 在索引中搜索记录,使用集成的推理模型进行文本嵌入 | name(索引名称)、namespace (命令空间) 、query(查询配置)参考 QueryOption| ### EmbedOption | 参数标识 | 参数描述 | | |---------------------|------------------------------------------------------|-------------------------------------------------------------| | `model` | 向量化使用的模型 | multilingual-e5-large,llama-text-embed-v2 ,pinecone-sparse-english-v0 | | `fieldMap` | 向量化使用的模型 | 数据记录中包含要嵌入的文本内容的字段名称。索引中的记录必须包含此字段 ,示例 { text: 'chunk_text' }, 'chunk_test' 为字段名称 | ### QueryOption | 参数标识 | 参数描述 | | |---------------------|------------------------------------------------------|-------------------------------------------------------------| | `topK` | 相关性最高的前K条 | 数字 | | `inputs` | 检索的文本串 | 示例 { text: '检索内容' } | ## 仓库地址 [https://github.com/pinecone-io/pinecone-mcp](https://github.com/pinecone-io/pinecone-mcp/tree/main) --- ## 🔌 使用方式 - [在云开发 Agent 中使用](https://docs.cloudbase.net/ai/mcp/use/agent) - [在 MCP Host 中使用](https://docs.cloudbase.net/ai/mcp/use/mcp-host) - [通过 SDK 接入](https://docs.cloudbase.net/ai/mcp/use/sdk) --- [云开发 MCP 控制台](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp) --- ## Postgres 数据库服务 MCP 接入 # Postgres 数据库服务 MCP 接入 通过 MCP 协议提供与 Postgres 数据库的安全交互。 [前往云开发平台运行 MCP Server](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp&p&mcp-template=mcp-postgres) --- ## 环境变量 - 需要将 **HOST** 配置为 **数据库服务器地址** - 需要将 **PORT** 配置为 **数据库端口号** - 需要将 **USER** 配置为 **数据库登录用户名** - 需要将 **PASSWORD** 配置为 **数据库登录密码** - 需要将 **DATABASE** 配置为 **要连接的数据库名称** ## 🗺️ 功能清单 | 工具标识 | 功能描述 | 核心参数 | |----------|----------------|------------------| | `query` | 执行只读SQL查询 | `sql`(SQL查询语句) | ## 仓库地址 [https://github.com/modelcontextprotocol/servers/tree/main/src/postgres](https://github.com/modelcontextprotocol/servers/tree/main/src/postgres) --- ## 🔌 使用方式 - [在云开发 Agent 中使用](https://docs.cloudbase.net/ai/mcp/use/agent) - [在 MCP Host 中使用](https://docs.cloudbase.net/ai/mcp/use/mcp-host) - [通过 SDK 接入](https://docs.cloudbase.net/ai/mcp/use/sdk) --- [云开发 MCP 控制台](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp) --- ## Puppeteer MCP Server # Puppeteer MCP Server 通过 MCP 协议提供标准化 AI 工具调用,支持 Agent 智能体快速集成 [前往云开发平台通过 Puppeteer 模板创建 MCP Server](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp&mcp-template=mcp-puppeteer) --- ## 🛠️ 工具清单 | 工具标识 | 功能描述 | 典型应用场景 | | ---------------------- | ---------------------------------- | ---------------------- | | `puppeteer_navigate` | 导航到指定 URL | 网页访问、页面跳转 | | `puppeteer_screenshot` | 截取当前页面或特定元素的屏幕截图 | 页面快照、元素截图 | | `puppeteer_click` | 点击页面上的元素 | 按钮点击、链接跳转 | | `puppeteer_fill` | 填写输入框内容 | 表单填写、搜索框输入 | | `puppeteer_select` | 选择下拉框选项 | 表单选择、选项切换 | | `puppeteer_hover` | 鼠标悬停在元素上 | 触发悬停效果、菜单展开 | | `puppeteer_evaluate` | 在浏览器控制台执行 JavaScript 代码 | 页面交互、数据提取 | | `puppeteer_set_cookie` | 设置 Cookie | 登录 | --- ## 🔌 使用方式 - [在云开发 Agent 中使用](../../use/agent) - [在 MCP Host 中使用](../../use/mcp-host) - [通过 SDK 接入](../../use/sdk) --- [云开发 MCP 控制台](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp) --- ## QuickChart MCP 接入 # QuickChart MCP 接入 通过 MCP 协议提供 QuickChart 的图表生成能力。 - 支持多种图表类型:条形图、折线图、饼图、甜甜圈图、雷达图、极坐标图、散点图、气泡图、径向仪表、速度计 - 可自定义标签、数据集、颜色和其他选项 - 可自定义标签、数据集、颜色和其他选项 - 返回生成的图表的 URL [前往云开发平台运行 MCP Server](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp&p&mcp-template=mcp-quickchart) --- ## 使用说明 [QuickChart 参考文档](https://quickchart.io/documentation/) ## 🗺️ 功能清单 | 工具标识 | 功能描述 | 核心参数 | |-------------------|-----------------------------------------|---------------------------------------------------------------------------------------------| | `generate_chart` | 创建图表并返回图表图片的 URL | `type`, `labels`, `datasets`, `title`, `option` | --- ## 仓库地址 [https://github.com/GongRzhe/Quickchart-MCP-Server?tab=readme-ov-file](https://github.com/GongRzhe/Quickchart-MCP-Server?tab=readme-ov-file) --- ## 🔌 使用方式 - [在云开发 Agent 中使用](https://docs.cloudbase.net/ai/mcp/use/agent) - [在 MCP Host 中使用](https://docs.cloudbase.net/ai/mcp/use/mcp-host) - [通过 SDK 接入](https://docs.cloudbase.net/ai/mcp/use/sdk) --- [云开发 MCP 控制台](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp) ## 参数说明 ### generate_chart 创建图表 | 输入参数 | Type | 描述 | | -------- | --------------- | ------------------------- | | type | string | bar, line, pie, doughnut, radar, polarArea, scatter, bubble, radialGauge, speedometer (条形图、折线图、饼图、甜甜圈图、雷达图、极坐标图、散点图、气泡图、径向仪表、速度计) | | labels | string[] | 自定义标签,例如(2023年,2024年,2025年) | | datasets | array | 自定义数据集,例如 `[{"label": "产量(吨)","data": [10000,20000,30000],"backgroundColor": "red","borderColor": "green","additionalConfig": {}}]` | | title | string | 自定义标题 | | option | string | 其他选项配置,参照[官方文档示例](https://quickchart.io/documentation/reference/chart-title/) | **返回**: 图表图片 URL 链接 ![示例图](https://quickchart.io/chart?c=%7B%22type%22%3A%22bar%22%2C%22data%22%3A%7B%22labels%22%3A%5B%222022%E5%B9%B4%22%2C%222023%E5%B9%B4%22%2C%222024%E5%B9%B4%22%5D%2C%22datasets%22%3A%5B%7B%22label%22%3A%22%E4%BA%A7%E9%87%8F%EF%BC%88%E5%90%A8%EF%BC%89%22%2C%22data%22%3A%5B10000%2C20000%2C30000%5D%2C%22backgroundColor%22%3A%22red%22%2C%22borderColor%22%3A%22green%22%7D%5D%7D%2C%22options%22%3A%7B%22title%22%3A%7B%22display%22%3Atrue%2C%22text%22%3A%22xxx%E7%9F%BF%E5%8E%82%E5%B9%B4%E4%BA%A7%E9%87%8F%E5%8F%98%E5%8C%96%22%7D%7D%7D) --- ## MCP 服务接入 — RAG Web Browser # MCP 服务接入 — RAG Web Browser 通过 MCP 协议提供基于 Web 浏览器的检索能力,利用 Web 页面数据和模型能力结合处理生成内容。 > Apify RAG Web Browser 接受搜索短语或 URL,查询 Google 搜索,然后抓取顶部搜索结果的网页,清理 HTML,将其转换为文本或 Markdown,并返回给 LLM 进行处理。提取的文本可以被注入到提示词和检索增强生成(RAG)管道中,为您的 LLM 应用提供来自网络的最新上下文 [部署 MCP Server](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp&p&mcp-template=mcp-rag-web-browser) --- ## 环境变量 - 需要将 **APIFY_TOKEN** 配置为 **[您在Apify 平台上的 API Token](https://console.apify.com/settings/integrations)** ## 使用说明 [Web 浏览器 RAG MCP Server 参考文档](https://github.com/apify/mcp-server-rag-web-browser) ## 🗺️ 功能清单 | 工具标识 | 功能描述 | 核心参数 | |-------------------|------------------------------------------------------|-------------------------------------| | `search` | 查询 Google 搜索,从结果中抓取前 N 个 URL,并以 Markdown 形式返回其清理后的内容 | query(搜索词或url), maxResults (最大搜索结果数,默认1), scrapingTool 选择用于提取网页的抓取工具 (选项包括 browser-playwright 或 raw-http, 默认raw-http), outputFormats 输出类型数组 markdown, text, html(如 ['markdown']), requestTimeoutSecs 请求的最大时间(默认40秒) | ## 仓库地址 [https://github.com/apify/mcp-server-rag-web-browser](https://github.com/apify/mcp-server-rag-web-browser) --- ## 🔌 使用方式 - [在云开发 Agent 中使用](https://docs.cloudbase.net/ai/mcp/use/agent) - [在 MCP Host 中使用](https://docs.cloudbase.net/ai/mcp/use/mcp-host) - [通过 SDK 接入](https://docs.cloudbase.net/ai/mcp/use/sdk) --- [云开发 MCP 控制台](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp) --- ## Redis 数据库服务 MCP 接入 # Redis 数据库服务 MCP 接入 通过 MCP 协议提供与 Redis 数据库的自然语言交互接口,支持 AI 智能体高效管理和搜索 Redis 数据。 [前往云开发平台运行 MCP Server](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp&p&mcp-template=mcp-redis) --- ## 环境变量 - **REDIS_HOST** - Redis 数据库服务器地址(默认:localhost) - **REDIS_PORT** - Redis 数据库端口号(默认:6379) - **REDIS_USERNAME** - Redis 用户名(可选) - **REDIS_PWD** - Redis 密码(可选) - **REDIS_SSL** - 是否启用 SSL/TLS(默认:false) - **REDIS_CA_PATH** - SSL 证书路径(启用 SSL 时需要) - **REDIS_CLUSTER_MODE** - 是否为集群模式(默认:false) ## 🗺️ 功能清单 ### 字符串操作 | 工具标识 | 功能描述 | 核心参数 | |------------------|------------------------------------------|-------------------------------------------------------------------------| | `string_set` | 设置字符串值(支持过期时间) | `key`(键名), `value`(值), 可选`expiration`(过期时间-秒) | | `string_get` | 获取字符串值 | `key`(键名) | ### 哈希表操作 | 工具标识 | 功能描述 | 核心参数 | |------------------|------------------------------------------|-------------------------------------------------------------------------| | `hash_set` | 设置哈希表字段值 | `key`(哈希键), `field`(字段名), `value`(字段值) | | `hash_get` | 获取哈希表指定字段的值 | `key`(哈希键), `field`(字段名) | | `hash_get_all` | 获取哈希表所有字段和值 | `key`(哈希键) | | `hash_delete` | 删除哈希表指定字段 | `key`(哈希键), `field`(字段名) | ### 列表操作 | 工具标识 | 功能描述 | 核心参数 | |------------------|------------------------------------------|-------------------------------------------------------------------------| | `list_push` | 向列表添加元素 | `key`(列表键), `values`(值数组), 可选`direction`(left/right) | | `list_pop` | 从列表弹出元素 | `key`(列表键), 可选`direction`(left/right) | | `list_range` | 获取列表指定范围的元素 | `key`(列表键), `start`(起始索引), `stop`(结束索引) | ### 集合操作 | 工具标识 | 功能描述 | 核心参数 | |------------------|------------------------------------------|-------------------------------------------------------------------------| | `set_add` | 向集合添加成员 | `key`(集合键), `members`(要添加的成员数组) | | `set_remove` | 从集合移除成员 | `key`(集合键), `members`(要移除的成员数组) | | `set_members` | 获取集合所有成员 | `key`(集合键) | | `set_is_member` | 检查成员是否在集合中 | `key`(集合键), `member`(成员) | ### 有序集合操作 | 工具标识 | 功能描述 | 核心参数 | |------------------|------------------------------------------|-------------------------------------------------------------------------| | `sorted_set_add` | 向有序集合添加成员 | `key`(集合键), `members`(包含`score`和`member`的对象数组) | | `sorted_set_range` | 按索引范围获取有序集合成员 | `key`(集合键), `start`(起始索引), `stop`(结束索引), 可选`with_scores` | | `sorted_set_range_by_score` | 按分数范围获取有序集合成员 | `key`(集合键), `min`(最小分数), `max`(最大分数), 可选`with_scores` | | `sorted_set_remove` | 从有序集合移除成员 | `key`(集合键), `members`(要移除的成员数组) | ### 流操作 | 工具标识 | 功能描述 | 核心参数 | |------------------|------------------------------------------|-------------------------------------------------------------------------| | `stream_add` | 向流添加条目 | `key`(流键), `fields`(字段-值对对象), 可选`id`(条目ID) | | `stream_read` | 从流读取条目 | `streams`(流键和起始ID的对象), 可选`count`(读取数量) | | `stream_delete` | 从流删除条目 | `key`(流键), `ids`(要删除的条目ID数组) | ### 发布/订阅操作 | 工具标识 | 功能描述 | 核心参数 | |------------------|------------------------------------------|-------------------------------------------------------------------------| | `publish` | 向频道发布消息 | `channel`(频道名), `message`(消息内容) | ### JSON 操作 | 工具标识 | 功能描述 | 核心参数 | |------------------|------------------------------------------|-------------------------------------------------------------------------| | `json_set` | 设置 JSON 文档 | `key`(键名), `path`(JSON路径), `value`(JSON值) | | `json_get` | 获取 JSON 文档或路径值 | `key`(键名), 可选`path`(JSON路径) | | `json_delete` | 删除 JSON 文档的指定路径 | `key`(键名), `path`(JSON路径) | ### 通用操作 | 工具标识 | 功能描述 | 核心参数 | |------------------|------------------------------------------|-------------------------------------------------------------------------| | `key_delete` | 删除键 | `keys`(要删除的键数组) | | `key_exists` | 检查键是否存在 | `key`(键名) | | `key_expire` | 设置键的过期时间 | `key`(键名), `seconds`(过期时间-秒) | | `scan_keys` | 扫描匹配模式的 Redis 键 | `pattern`(匹配模式), 可选`count`(每次迭代返回键数量) | ## 仓库地址 [https://github.com/redis/mcp-redis](https://github.com/redis/mcp-redis) --- ## 🔌 使用方式 - [在云开发 Agent 中使用](https://docs.cloudbase.net/ai/mcp/use/agent) - [在 MCP Host 中使用](https://docs.cloudbase.net/ai/mcp/use/mcp-host) - [通过 SDK 接入](https://docs.cloudbase.net/ai/mcp/use/sdk) --- [云开发 MCP 控制台](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp) --- ## 云开发基础能力 MCP 接入 # 云开发基础能力 MCP 接入 支持通过 MCP 协议来管理云开发基础能力,包括云开发环境管理、静态网站部署,数据库集合管理、数据库文档操作等。 [前往云开发平台运行 MCP Server](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp&p&mcp-template=mcp-tcb) --- ### 🚀 专为 AI 编程助手优化:认识 CloudBase-AI-ToolKit **如果您正在使用 Cursor、VSCode GitHub Copilot、Claude Code 等 AI 编程工具,我们强烈推荐您直接使用 [CloudBase-AI-ToolKit](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit)!** `CloudBase-AI-ToolKit` 是一个专为本地 IDE 开发流程设计的上层应用。它封装了本项目的底层能力,为您提供无缝的智能开发体验: - **🤖 AI 生成即部署**:让您的 AI 编程助手不仅能写代码,更能直接生成可部署的全栈应用、小程序项目。 - **☁️ 一键发布上云**:在 IDE 中与 AI 对话完成开发后,一键将应用发布到腾讯云开发 CloudBase,免去所有繁琐配置。 简单来说,`CloudBase-AI-ToolKit` 是您在 **本地 IDE** 中使用 AI 驱动云开发的最佳选择。本项目(`cloudbase-mcp`)则是其背后的核心引擎。 👉 **[前往 CloudBase-AI-ToolKit,开启您的 AI 云开发之旅!](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/)** --- ## 功能特点 - **☁️ 云开发环境管理**:提供获取所有云开发环境信息、获取环境合法域名列表、添加和删除安全域名、获取和修改当前环境信息等功能。 - **💻 数据库集合管理**:支持创建、检查存在、更新、获取详细信息、列出集合、检查索引存在、查询数据分布等数据库集合相关操作。 - **📒 数据库文档操作**:可向集合中插入文档、查询文档、更新文档、删除文档。 - **🌍 静态托管管理**:实现上传文件到静态网站托管、获取文件列表、删除文件或文件夹、搜索文件、绑定和解绑自定义域名、获取静态网站配置、检查域名配置、修改域名配置等功能。 - **💻临时文件管理**:能在临时目录创建文件,支持文本内容或 base64 编码的二进制内容;读取临时目录中的文件,支持文本和二进制文件。 ## 使用示例 ![](https://tcb-advanced-a656fc-1257967285.tcloudbaseapp.com/resources/2025-04/lowcode-2256227) ## 使用说明 ### 远程 MCP 本项目支持[一键部署到腾讯云开发平台](https://docs.cloudbase.net/ai/mcp/develop/host-mcp),提供远程 SSE 访问 [☁️ 前往云开发平台部署 MCP Server](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp&p&mcp-template=mcp-alapi-cn) 部署完毕之后,可参考页面中的使用 MCP 说明,使用远程 SSE 访问 MCP Server。 ### 本地 MCP 在支持 MCP 的本地客户端运行时,也可以使用通过 `npx` 来调用 `cloudbase-mcp` 工具。 ```js { "mcpServers": { "cloudbase-mcp": { "command": "npx", "args": ["@cloudbase/cloudbase-mcp"], "env": { "TENCENTCLOUD_SECRETID": "腾讯云 SecretId", "TENCENTCLOUD_SECRETKEY": "腾讯云 SecretKey", "TENCENTCLOUD_SESSIONTOKEN": "腾讯云临时密钥Token,如果使用临时密钥才需要传入", "CLOUDBASE_ENV_ID": "云开发环境 ID" } } } } ``` ## 环境变量 - 需要将 `TENCENTCLOUD_SECRETID` 和 `TENCENTCLOUD_SECRETKEY` / `TENCENTCLOUD_SESSIONTOKEN`配置为**您在云开发控制台获取的 SecretId 和 SecretKey** ([获取腾讯云 API 密钥](https://console.cloud.tencent.com/cam/capi)) - 需要将 `CLOUDBASE_ENV_ID` 配置为**您在云开发控制台获取的环境 ID**, [获取云开发环境 ID](https://tcb.cloud.tencent.com/dev) --- ## 🗺️ 功能清单 ### 云开发环境管理 | 工具标识 | 功能描述 | 核心参数 | |---------------------------|-----------------------------------------|---------------------------------------------------------------------------------------------| | `listEnvs` | 获取所有云开发环境信息 | 无 | | `getEnvAuthDomains` | 获取云开发环境的合法域名列表 | 无 | | `createEnvDomain` | 为云开发环境添加安全域名 | `domains`(必填,安全域名数组) | | `deleteEnvDomain` | 删除云开发环境的指定安全域名 | `domains`(必填,安全域名数组) | | `getEnvInfo` | 获取当前云开发环境信息 | 无 | | `updateEnvInfo` | 修改云开发环境别名 | `alias`(必填,环境别名) | --- ### 数据库集合管理 | 工具标识 | 功能描述 | 核心参数 | |---------------------------|-----------------------------------------|---------------------------------------------------------------------------------------------| | `createCollection` | 创建一个新的云开发数据库集合 | `collectionName`(必填,集合名称) | | `checkCollectionExists` | 检查云开发数据库集合是否存在 | `collectionName`(必填,集合名称) | | `updateCollection` | 更新云开发数据库集合配置(创建或删除索引) | `collectionName`(必填,集合名称),`options`(必填,更新选项,支持创建和删除索引) | | `describeCollection` | 获取云开发数据库集合的详细信息 | `collectionName`(必填,集合名称) | | `listCollections` | 获取云开发数据库集合列表 | `offset`(选填,偏移量),`limit`(选填,返回数量限制) | | `checkIndexExists` | 检查索引是否存在 | `collectionName`(必填,集合名称),`indexName`(必填,索引名称) | | `distribution` | 查询数据库中集合的数据分布情况 | 无 | --- ### 数据库文档操作 | 工具标识 | 功能描述 | 核心参数 | |---------------------------|-----------------------------------------|---------------------------------------------------------------------------------------------| | `insertDocuments` | 向集合中插入一个或多个文档 | `collectionName`(必填,集合名称),`documents`(必填,要插入的文档数组,每个文档为 JSON 字符串) | | `queryDocuments` | 查询集合中的文档 | `collectionName`(必填,集合名称),`query`(选填,查询条件,JSON 字符串),`projection`(选填,返回字段投影,JSON 字符串),`sort`(选填,排序条件,JSON 字符串),`limit`(选填,返回数量限制),`offset`(选填,跳过的记录数) | | `updateDocuments` | 更新集合中的文档 | `collectionName`(必填,集合名称),`query`(必填,查询条件,JSON 字符串),`update`(必填,更新内容,JSON 字符串),`isMulti`(选填,是否更新多条记录),`upsert`(选填,是否在不存在时插入) | | `deleteDocuments` | 删除集合中的文档 | `collectionName`(必填,集合名称),`query`(必填,查询条件,JSON 字符串),`isMulti`(选填,是否删除多条记录) | --- ### 静态托管管理 | 工具标识 | 功能描述 | 核心参数 | |---------------------------|-----------------------------------------|---------------------------------------------------------------------------------------------| | `uploadFiles` | 上传文件到静态网站托管 | `localPath`(选填,本地文件或文件夹路径),`cloudPath`(选填,云端文件或文件夹路径),`files`(选填,多文件上传配置),`ignore`(选填,忽略文件模式) | | `listFiles` | 获取静态网站托管的文件列表 | 无 | | `deleteFiles` | 删除静态网站托管的文件或文件夹 | `cloudPath`(必填,云端文件或文件夹路径),`isDir`(选填,是否为文件夹,默认为 `false`) | | `findFiles` | 搜索静态网站托管的文件 | `prefix`(必填,匹配前缀),`marker`(选填,起始对象键标记),`maxKeys`(选填,单次返回最大条目数) | | `createHostingDomain` | 绑定自定义域名 | `domain`(必填,自定义域名),`certId`(必填,证书 ID) | | `deleteHostingDomain` | 解绑自定义域名 | `domain`(必填,自定义域名) | | `getWebsiteConfig` | 获取静态网站配置 | 无 | | `tcbCheckResource` | 检查域名配置 | `domains`(必填,域名列表) | | `tcbModifyAttribute` | 修改域名配置 | `domain`(必填,域名),`domainId`(必填,域名 ID),`domainConfig`(必填,域名配置) | --- ### 临时文件管理 | 工具标识 | 功能描述 | 核心参数 | |---------------------------|-----------------------------------------|---------------------------------------------------------------------------------------------| | `createTempFile` | 在临时目录创建文件,支持文本内容或 base64 编码的二进制内容 | `content`(必填,文件内容,可以是普通文本或 base64 编码的二进制内容),`isBase64`(选填,是否为 base64 编码,默认为 `false`),`extension`(选填,文件扩展名,如 `.txt`, `.png` 等) | | `readTempFile` | 读取临时目录中的文件,支持文本和二进制文件 | `filePath`(必填,文件路径),`asBase64`(选填,是否以 base64 格式返回内容,默认为 `false`) | --- ## 🔌 使用方式 - [在云开发 Agent 中使用](https://docs.cloudbase.net/ai/mcp/use/agent) - [在 MCP Host 中使用](https://docs.cloudbase.net/ai/mcp/use/mcp-host) - [通过 SDK 接入](https://docs.cloudbase.net/ai/mcp/use/sdk) --- [云开发 MCP 控制台](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp) --- ## 腾讯位置服务 MCP 接入 # 腾讯位置服务 MCP 接入 在AI应用场景中,与真实世界取得连接,进行个性化推荐(推荐餐厅、酒店、活动、景区等),行程规划,获取实时出行信息等,让AI服务于人们现实生活,是很多企业与开发者迫切希望实现的。 对此腾讯位置服务推出基于MCP协议的位置服务开发接口,助开发者们快速实现基于地理位置的AI服务。 [前往云开发平台创建 MCP Server](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp&p&mcp-template=mcp-tencent-map) --- ## 环境变量 创建APIKey 腾讯位置服务MCP 依赖WebServiceAPI构建,因此需要先创建key,并开启WebServiceAPI功能,取得相关接口调用配额后方可使用, 具体方法可参见: https://lbs.qq.com/service/webService/webServiceGuide/overview - 需要将 **API_KEY** 环境变量配置为**您在腾讯位置服务创建的 API Key**。 - 配置 **JSON_FORMAT**: 需要返回 JSON 结构化数据则设置为 1,否则设置为0(返回格式化的文本段) ## 使用说明 腾讯位置服务MCP Server依赖地图WebServiceAPI构建,因此受WebServiceAPI接口本身限制,需要具备以下相应接口的调用权限和配额方可使用。 点击查看:[WebServiceAPI调用限制说明、WebServiceAPI入门指南](https://lbs.qq.com/service/webService/webServiceGuide/overview) 在用户与智能体对话的过程中,智能体根据对话内容判断是否需要调用外部工具(MCPServer)获取信息来解答用户问题,MCPServer根据智能体提供的参数,会调用对应的WebServiceAPI接口获取结果,智能体理解其中内容,并加以整理最后回复给用户。 智能体可能在这一过程中调用多个MCPServer中的工具接口(可能对应多个WebServiceAPI接口),因此相关接口都需要具备调用权限和配额。 ## 应用示例 **城市/区域搜索** 根据指定的市、区范围(名称或区域代码)、地点关键词,搜索符合的地点信息。 应用场景:如搜索北京的景点、酒店、购物场景,搜索某个地方的详细地址等。 ![](https://p.qpic.cn/lbsconsole/0/c82d3407a49d81dd0b020f96d173b0f2/0) (注:不同大模型因其推理、计算能力不同,实际应用效果可能不同,本示例仅供参考) ## 🗺️ 功能清单 | 工具标识 | 功能描述 | 核心参数 | | -------------------------- | ---------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `geocoder` | 提供由文字地址到经纬度的转换能力,并返回结构化的省市区地址信息 | `address`(必填,包含省市区信息的格式化地址或包含城市名的地点关键词) | | `placeSuggestion` | 根据关键词和城市搜索地点信息,返回地点名称、地址、经纬度、分类等 | `keyword`(必填,关键词或地点名称),`region`(选填,搜索城市) | | `placeSearchNearby` | 搜索指定中心点经纬度周边的地点信息,返回地点名称、地址、经纬度、分类等 | `location`(必填,搜索中心点经纬度,格式 `lat,lng`),`keyword`(必填,搜索关键词) | | `directionDriving` | 规划驾车路线,支持参考路况、少收费、不走高速等偏好,返回路线预估用时、距离、过路费等信息 | `from`(必填,起点经纬度,格式 `lat,lng`),`to`(必填,终点经纬度,格式 `lat,lng`) | | `placeAlongby` | 在路线沿途搜索符合条件的地点,返回地点名称、地址、经纬度、分类等 | `polyline`(必填,路线经纬度点串),`keyword`(必填,搜索关键词) | | `placeDetail` | 根据 POI ID 获取 POI 详情信息,包括名称、地址、经纬度、分类等 | `id`(必填,POI ID) | | `matrix` | 批量计算多个起终点之间的路面距离(导航距离) | `from`(必填,起点经纬度,格式 `lat,lng`),`to`(必填,终点经纬度,格式 `lat,lng`),`mode`(必填,通行方式:`driving`、`walking`、`bicycling`) | | `reverseGeocoder` | 输入经纬度坐标,返回语义化地址、省市区信息等 | `location`(必填,经纬度坐标,格式 `lat,lng`) | | `ipLocation` | 通过 IP 地址获取当前所在省、市、区信息 | `ip`(必填,IP 地址,IPv4 或 IPv6) | | `weather` | 查询行政区划代码对应的城市实时天气或预报天气 | `adcode`(必填,行政区划代码),`type`(选填,查询类型:`now` 或 `future`,默认为 `now`) | | `directionWalking` | 规划步行路线,返回路线总距离、预估用时等信息 | `from`(必填,起点经纬度,格式 `lat,lng`),`to`(必填,终点经纬度,格式 `lat,lng`) | | `directionBicycling` | 规划自行车骑行路线,返回路线总距离、预估用时等信息 | `from`(必填,起点经纬度,格式 `lat,lng`),`to`(必填,终点经纬度,格式 `lat,lng`) | | `directionTransit` | 规划公共交通路线,返回多组乘坐方案及详细信息 | `from`(必填,起点经纬度,格式 `lat,lng`),`to`(必填,终点经纬度,格式 `lat,lng`) | | `futureDrivingDirection` | 根据未来出发时间规划驾车路线,考虑预测路况,返回预估用时、总距离等信息 | `departure_time`(必填,出发时间,时间戳格式),`from`(必填,起点经纬度,格式 `lat,lng`),`to`(必填,终点经纬度,格式 `lat,lng`) | | `waypointOrder` | 对途经点进行最顺路排序并规划驾车路线,支持最多 16 个途经点 | `from`(必填,起点经纬度,格式 `lat,lng`),`to`(必填,终点经纬度,格式 `lat,lng`),`waypoints`(选填,途经点经纬度,最多 16 个,格式 `lat1,lng1;lat2,lng2...`),`need_waypoint_order`(选填,是否需要对途经点排序,值为 `true` 或 `false`) | ## 🔌 使用方式 - [在云开发 Agent 中使用](https://docs.cloudbase.net/ai/mcp/use/agent) - [在 MCP Host 中使用](https://docs.cloudbase.net/ai/mcp/use/mcp-host) - [通过 SDK 接入](https://docs.cloudbase.net/ai/mcp/use/sdk) [云开发 MCP 控制台](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp) --- ## Time服务 MCP 接入 # Time服务 MCP 接入 通过 MCP 协议提供提供时间和时区转换功能的能力。 [前往云开发平台运行 MCP Server](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp&p&mcp-template=mcp-time) --- ## 🗺️ 功能清单 | 工具标识 | 功能描述 | 核心参数 | | ------------------ | ---------------------- | ---------------------------------------------------------------------------- | | `get_current_time` | 获取指定时区的当前时间 | `timezone`(IANA时区名称,如'America/New_York',未提供则默认'UTC') | | `convert_time` | 在不同时区间转换时间 | `source_timezone`(源时区), `time`(24小时制时间), `target_timezone`(目标时区) | ## 仓库地址 [https://github.com/modelcontextprotocol/servers/tree/main/src/time](https://github.com/modelcontextprotocol/servers/tree/main/src/time) --- ## 🔌 使用方式 - [在云开发 Agent 中使用](https://docs.cloudbase.net/ai/mcp/use/agent) - [在 MCP Host 中使用](https://docs.cloudbase.net/ai/mcp/use/mcp-host) - [通过 SDK 接入](https://docs.cloudbase.net/ai/mcp/use/sdk) --- [云开发 MCP 控制台](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp) --- ## Trends Hub # Trends Hub 基于 MCP 协议的全网热点趋势一站式聚合服务 [前往云开发平台运行 MCP Server](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp&p&mcp-template=mcp-trends-hub) --- ## 🗺️ 功能清单 | 命令名称 | 功能描述 | 核心参数 | 必填参数 | 默认值 | | --------------------------- | ------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------- | -------- | -------------------------------- | | `get-36kr-trending` | 获取36氪热榜,包含创业、商业、科技领域的热门资讯 | `type`: 分类(hot-人气榜/video-视频榜/comment-热议榜/collect-收藏榜) | 无 | hot | | `get-9to5mac-news` | 获取9to5Mac苹果相关新闻 | 无 | 无 | 无 | | `get-bbc-news` | 获取BBC新闻 | `category`: 分类(空-热门/world-国际/uk-英国/business-商业等) `edition`: 版本(空/uk/US & Canada/Rest of the world) | 无 | category: 空 edition: 空 | | `get-bilibili-rank` | 获取哔哩哔哩视频排行榜 | `type`: 分区(0-全站/1-动画/3-音乐/4-游戏等) | 无 | 0 | | `get-douban-rank` | 获取豆瓣实时热门榜单 | `type`: 类型(subject-综合/movie-电影/tv-电视剧) `start`: 起始位置 `count`: 数量 | 无 | type: subject start: 0 count: 10 | | `get-douyin-trending` | 获取抖音热搜榜单 | 无 | 无 | 无 | | `get-gcores-new` | 获取机核网游戏资讯 | 无 | 无 | 无 | | `get-ifanr-news` | 获取爱范儿科技快讯 | `limit`: 数量 `offset`: 偏移量 | 无 | limit: 20 offset: 0 | | `get-infoq-news` | 获取InfoQ技术资讯 | `region`: 地区(cn/global) | 无 | cn | | `get-juejin-article-rank` | 获取掘金文章榜 | `category_id`: 分类(后端/前端/Android/iOS等) | 无 | 6809637769959178254(后端) | | `get-netease-news-trending` | 获取网易新闻热点榜 | 无 | 无 | 无 | | `get-nytimes-news` | 获取纽约时报新闻 | `region`: 语言(cn-中文/global-全球) `section`: 分类(仅global有效) | 无 | region: cn section: HomePage | | `get-smzdm-rank` | 获取什么值得买热门 | `unit`: 时间范围(1-今日/7-周/30-月) | 无 | 1 | | `get-sspai-rank` | 获取少数派热榜 | `tag`: 分类(热门文章/应用推荐等) `limit`: 数量 | 无 | tag: 热门文章 limit: 40 | | `get-tencent-news-trending` | 获取腾讯新闻热点榜 | `page_size`: 每页数量 | 无 | 20 | | `get-thepaper-trending` | 获取澎湃新闻热榜 | 无 | 无 | 无 | | `get-theverge-news` | 获取The Verge新闻 | 无 | 无 | 无 | | `get-toutiao-trending` | 获取今日头条热榜 | 无 | 无 | 无 | | `get-weibo-trending` | 获取微博热搜榜 | 无 | 无 | 无 | | `get-weread-rank` | 获取微信读书排行榜 | `category`: 分类(rising-飙升榜/hot_search-热搜榜/newbook-新书榜等) | 无 | rising | | `get-zhihu-trending` | 获取知乎热榜 | `limit`: 数量 | 无 | 50 | ## 仓库地址 [https://github.com/baranwang/mcp-trends-hub](https://github.com/baranwang/mcp-trends-hub) --- ## 🔌 使用方式 - [在云开发 Agent 中使用](https://docs.cloudbase.net/ai/mcp/use/agent) - [在 MCP Host 中使用](https://docs.cloudbase.net/ai/mcp/use/mcp-host) - [通过 SDK 接入](https://docs.cloudbase.net/ai/mcp/use/sdk) --- [云开发 MCP 控制台](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp) --- ## MCP 服务接入 — Vectorize # MCP 服务接入 — Vectorize 通过 MCP 协议 Vectorize 的能力, 可基于 Vectorize 上配置好的 RAG 流水线执行检索或深度研究。 > Vectorize 帮助您更快、更轻松地构建人工智能应用。它自动提取数据,使用 RAG 评估找到最佳向量化策略,并让您快速部署非结构化数据的实时 RAG 管道。您的向量搜索索引始终保持最新,并且它可以与您现有的向量数据库集成,让您完全控制自己的数据。Vectorize 处理繁重的工作,使您能够专注于构建强大的人工智能解决方案,而无需陷入数据管理的泥潭 Vectorize RAG 流水线示意图 ![](https://qcloudimg.tencent-cloud.cn/raw/462b1cd5507e73a949c368350a0c5ff2.png) [部署 MCP Server](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp&p&mcp-template=mcp-vectorize) --- ## 环境变量 - 需要将 **VECTORIZE_ORG_ID** 配置为 **[您在 Vectorize 平台的 组织ID](https://platform.vectorize.io/)** - 需要将 **VECTORIZE_PIPELINE_ID** 配置为 **[您在 Vectorize 平台创建的 RAG 流水线ID](https://platform.vectorize.io/)** - 需要将 **VECTORIZE_TOKEN** 配置为 **[您在 Vectorize 平台的 Token](https://platform.vectorize.io/)** ## 使用说明 [Vectorize MCP Server 参考文档](https://github.com/vectorize-io/vectorize-mcp-server/) ## 🗺️ 功能清单 | 工具标识 | 功能描述 | 核心参数 | |--------------------|------------------------------------------------------|-----------------------------------------------------------| | `retrieve` | 执行向量检索,返回与查询最相关的文档内容。 | `question`(查询文本),`k`(返回的文档数量) | | `extract` | 从文件中提取文本内容,并将其转换为 Markdown 格式。 | `base64document`(Base64 编码的文件内容),`contentType`(文件类型) | | `deep-research` | 生成私有的深度研究内容,支持 Web 搜索。 | `query`(查询文本),`webSearch`(是否启用 Web 搜索) | ## 仓库地址 [https://github.com/vectorize-io/vectorize-mcp-server](https://github.com/vectorize-io/vectorize-mcp-server) --- ## 🔌 使用方式 - [在云开发 Agent 中使用](https://docs.cloudbase.net/ai/mcp/use/agent) - [在 MCP Host 中使用](https://docs.cloudbase.net/ai/mcp/use/mcp-host) - [通过 SDK 接入](https://docs.cloudbase.net/ai/mcp/use/sdk) --- [云开发 MCP 控制台](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp) --- ## 元器 Agent MCP Server # 元器 Agent MCP Server 通过 MCP 协议提供标准化 AI 工具调用,支持腾讯元器 Agent 智能体快速集成。 - 支持对接获取公众号文章(需要在元器平台上创建并授权公众号) - 每个 Agent 均提供一亿 token 免费额度 [前往云开发平台通过元器 Agent 模板创建 MCP Server](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp&mcp-template=yuanqi-agent) --- ## 环境变量 在元器上创建 Agent 之后,需要[开启 API 访问](https://docs.qq.com/aio/p/scxmsn78nzsuj64?p=BVUAh9OGFvSEFA7CgBOyED4) - 需要将**元器的智能体 ID** 配置到 `YUAN_QI_AGENT_ID` 环境变量 - 需要将**元器的 Token** 配置到 `YUAN_QI_API_KEY` 环境变量 ## 参考链接 - [腾讯元器](https://yuanqi.tencent.com/my-creation/agent) - [以 API 方式调用元器智能体](https://docs.qq.com/aio/p/scxmsn78nzsuj64?p=BVUAh9OGFvSEFA7CgBOyED4) ## 🛠️ 工具清单 | 工具标识 | 功能描述 | 典型应用场景 | | --------------------- | ------------------------ | ---------------------------- | | `chatWithYuanQiAgent` | 与元器智能体进行对话交互 | 智能问答、知识咨询、对话服务 | --- ## 🔌 使用方式 - [在云开发 Agent 中使用](https://docs.cloudbase.net/ai/mcp/use/agent) - [在 MCP Host 中使用](https://docs.cloudbase.net/ai/mcp/use/mcp-host) - [通过 SDK 接入](https://docs.cloudbase.net/ai/mcp/use/sdk) --- [云开发 MCP 控制台](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp) --- ## 元器插件 MCP Server # 元器插件 MCP Server 通过 MCP 协议提供标准化 AI 工具调用,支持 Agent 智能体快速集成。 [前往云开发平台通过元器插件模板创建 MCP Server](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp&mcp-template=yuanqi-tool) --- ## 🛠️ 工具清单 | 工具标识 | 功能描述 | 典型应用场景 | | ------------------------ | --------------------- | ---------------------- | | `imageClarity` | 模糊图片高清化处理 | 图片修复、画质提升 | | `pdfParse` | 解析 PDF 文件完整内容 | 文档阅读、内容提取 | | `hunyuanImage2Text` | 图片内容分析理解 | 图像识别、内容解读 | | `sogouSearch` | 搜狗搜索引擎查询 | 信息检索、事实核查 | | `photoStylize` | 人像风格化转换 | 艺术创作、头像生成 | | `faceMerge` | 人脸融合替换 | 换脸特效、创意图片 | | `documentDeepRead` | 论文/研报深度阅读 | 学术研究、文档速览 | | `imageSearch` | 自然语言图片检索 | 素材查找、创意灵感 | | `imageReplaceBackground` | 图片背景替换 | 证件照处理、创意设计 | | `textTranslation` | 多语言文本翻译 | 跨语言交流、文档翻译 | | `imageRetouchSwitch` | 图片风格转换 | 艺术创作、视觉设计 | | `imageCanny` | 线稿生成图片 | 设计辅助、创意实现 | | `hunyuanSearch` | 内容搜索 | 信息查询、知识获取 | | `ocr` | 图片文字识别 | 文档数字化、信息提取 | | `webBrowser` | 网页内容提取 | 网页信息抓取、内容摘要 | | `hunyuanText2Image` | 文本生成/修改图片 | 创意设计、视觉内容生成 | | `musicGeneration` | 音频生成 | 音乐创作、音效制作 | | `writingAssistant` | AI 写作辅助 | 内容创作、文案生成 | | `pdfContentSearch` | PDF 内容检索 | 文档查询、信息定位 | --- ## 🔌 使用方式 - [在云开发 Agent 中使用](https://docs.cloudbase.net/ai/mcp/use/agent) - [在 MCP Host 中使用](https://docs.cloudbase.net/ai/mcp/use/mcp-host) - [通过 SDK 接入](https://docs.cloudbase.net/ai/mcp/use/sdk) --- [云开发 MCP 控制台](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp) --- ## Zapier MCP 接入 # Zapier MCP 接入 Zapier是一个集成平台,托管着 7,000 多个第三方应用,并拥有 30,000 多个 AI Actions。AI Actions 可让您的 AI 或系统在 Zapier 上运行任何操作(例如,发送 Slack 消息、查找 Google 日历活动、起草 Gmail 回复、创建 HubSpot 潜在客户等)。 [前往云开发平台创建 MCP Server](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp&p&mcp-template=mcp-zapier) --- ## 环境变量 - 需要将 **ZAPIER_SKEY** 环境变量配置为**您在 Zapier 上创建的 [MCP URL](https://actions.zapier.com/settings/mcp/)** 中的 ZAPIER_SKEY,例如 `https://actions.zapier.com/mcp/ZAPIER_SKEY/sse` 中的 `ZAPIER_SKEY` ## 使用说明 [配置 MCP actions](https://actions.zapier.com/mcp/actions/) ## 🗺️ 功能清单 | 工具标识 | 功能描述 | 核心参数 | | ---------------- | -------------------------------------------------------------- | ------------------------------------- | | `dynamic_action` | 在 Zapier 上创建的动作,例如 `google_calendar_quick_add_event` | - | | `edit_actions` | 编辑现有的 MCP 提供程序操作。 | `random_string`:无参数工具的虚拟参数 | | `add_actions` | 向您的 MCP 提供程序添加新操作。 | `random_string`:无参数工具的虚拟参数 | ## 🔌 使用方式 - [在云开发 Agent 中使用](https://docs.cloudbase.net/ai/mcp/use/agent) - [在 MCP Host 中使用](https://docs.cloudbase.net/ai/mcp/use/mcp-host) - [通过 SDK 接入](https://docs.cloudbase.net/ai/mcp/use/sdk) [云开发 MCP 控制台](https://tcb.cloud.tencent.com/dev#/ai?tab=mcp) --- ## 云开发 MCP 市场 # 云开发 MCP 市场 [云开发 MCP 市场](https://tcb.cloud.tencent.com/mcp-server)提供了丰富的 MCP 服务模板,帮助您快速构建 Agent。 - 如果你是 MCP Server 的开发者,欢迎提交上架到云开发 MCP 市场,请参考[上架指南](./publish) - 如果你有新的 MCP 需求,请点击 [提交需求](https://doc.weixin.qq.com/forms/AJEAIQdfAAoALAAaAa6ACgYH8yRdSbQif#/fill)。 ## 已支持的 MCP Server ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## 概述 # 概述 ## 什么是 MCP MCP 是一个开放协议,它标准化了 AI 应用如何向大语言模型(LLMs)提供上下文。可以把 MCP 想象成 AI 应用的 USB-C 接口。就像 USB-C 为设备连接各种外设和配件提供了标准化方式一样,MCP 为 AI 模型连接不同的数据源和工具提供了标准化方式。 MCP 的核心采用 Client-Server 架构,一个应用程序可以连接多个 MCP Server。 只要 AI 应用实现了 MCP ,即可接入到任意的 MCP Server,扩展自身的能力。加入 MCP Server 后,工具调用的流程如下: ```mermaid sequenceDiagram participant AI as 👨‍💻 AI 应用 participant MCP as 🔌 MCP Server participant LLM as 🧠 大模型 AI->>+MCP: 请求工具列表 MCP-->>-AI: 返回工具列表 AI->>+LLM: Prompt + 可用工具列表 loop 如果需要工具调用 LLM->>+AI: 工具调用请求 AI->>+MCP: 转发工具调用请求 MCP->>MCP: 执行工具调用 MCP-->>-AI: 工具调用结果 AI-->>-LLM: 工具调用结果 end LLM-->>-AI: 文本响应 ``` 通过这种方式,MCP 实现了: 1. **即插即用**:AI 应用只需实现 MCP 协议,即可接入丰富的第三方工具生态 2. **标准化**:所有工具遵循统一的描述格式和调用方式 3. **解耦工具与应用**:工具提供者可以独立开发和维护工具,不需了解 AI 应用内部实现 4. **资源共享**:一次开发的工具可以被多个 AI 应用复用 云开发提供了丰富的 MCP 支持: - [MCP 使用](./use/agent) - [MCP Server 开发](./develop/) - [MCP Server 托管](https://tcb.cloud.tencent.com/dev?#/ai?tab=mcp) --- ## 在 Agent 中使用 # 在 Agent 中使用 1. 请确保已经有一个 Agent,可[前往云开发平台创建](https://tcb.cloud.tencent.com/dev#/ai?tab=agent) 2. 在 Agent 中添加 MCP Server 选择第一步安装的 MCP 服务,并选择需要的工具,并保存 3. 和 AI 进行对话,例如要求 AI 使用工具完成某个功能, 当 Agent 使用了 MCP 执行任务时,会提示正在执行某个工具 --- ## 在 MCP Host 中使用 import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # 在 MCP Host 中使用 支持了 MCP 的应用程序被称为 MCP Host。以下是一些当前可用的 MCP Host: - Cursor - Claude Desktop - Cherry Studio - …… 这些 MCP Host 均提供了配置 MCP Server 的入口。以 Cursor 举例,我们可以通过以下几步配置 `mcp.json` 文件来连接到云开发 MCP Server: 1. 保证系统中有 Node.js 环境,推荐版本 >= 18 2. 前往[云开发平台获取 API KEY](https://docs.cloudbase.net/http-api/basic/apikey) 3. 获取 MCP Server 的云托管服务名 4. 根据你的 MCP Server transport 类型,编辑 `mcp.json` 配置: ```json { "mcpServers": { "your-server-name": { "command": "npx", "args": [ "-y", "@cloudbase/mcp-transformer", "streamableToStdio", "--url", "https://your-env-id.api.tcloudbasegateway.com/v1/cloudrun/your-service-name/messages", "--token", "your-token" ] } } } ``` ```json { "mcpServers": { "your-server-name": { "command": "npx", "args": [ "-y", "@cloudbase/mcp-transformer", "sseToStdio", "--url", "https://your-env-id.api.tcloudbasegateway.com/v1/cloudrun/your-service-name/messages", "--token", "your-token" ] } } } ``` ```json { "mcpServers": { "your-server-name": { "command": "npx", "args": [ "-y", "@cloudbase/mcp-transformer", "postToStdio", "--url", "https://your-env-id.api.tcloudbasegateway.com/v1/cloudrun/your-service-name/messages", "--token", "your-token" ] } } } ``` 上述配置中,替换以下内容: - `your-server-name`: MCP Server 名称 - `your-token`: 在云开发平台获取的 API KEY - `your-env-id`: 云开发环境 ID - `your-service-name`: 云托管服务名 可参考云开发平台 MCP 详情页中的 `使用 MCP` Tab 下的指引进行接入。 --- ## 通过 SDK 调用 import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # 通过 SDK 调用 安装依赖: ```shell npm i @cloudbase/mcp @modelcontextprotocol/sdk ``` 前往[云开发平台获取 API KEY](https://tcb.cloud.tencent.com/dev#/env/apikey)。 根据 MCP Server 的 Transport 类型连接至 MCP Server: ```ts import { Client } from "@modelcontextprotocol/sdk/client/index.js"; import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js"; const transport = new StreamableHTTPClientTransport( // 将链接中的 your-env-id 替换为云开发环境 id // 将链接中的 your-service-name 替换为云托管服务名 new URL( "https://your-env-id.api.tcloudbasegateway.com/v1/cloudrun/your-service-name/messages" ), { requestInit: { headers: { // 将 your-api-key 替换为实际的 API KEY Authorization: `Bearer your-api-key`, }, }, } ); const client = new Client( { name: "your-mcp-name", version: "1.0.0", }, { capabilities: { tools: {}, }, } ); await client.connect(transport); ``` ```ts import { Client } from "@modelcontextprotocol/sdk/client/index.js"; import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js"; const transport = new SSEClientTransport( // 将链接中的 your-env-id 替换为云开发环境 id // 将链接中的 your-service-name 替换为云托管服务名 new URL( "https://your-env-id.api.tcloudbasegateway.com/v1/cloudrun/your-service-name/messages" ), { requestInit: { headers: { // 将 your-api-key 替换为实际的 API KEY Authorization: `Bearer your-api-key`, } }, eventSourceInit: { fetch: (url, init) => { return fetch(url, { ...(init || {}), headers: { ...(init?.headers || {}), // 将 your-api-key 替换为实际的 API KEY Authorization: `Bearer your-api-key`, } }) } } } ); const client = new Client( { name: "your-mcp-name", version: "1.0.0", }, { capabilities: { tools: {}, }, } ); await client.connect(transport); ``` ```ts import { Client } from "@modelcontextprotocol/sdk/client/index.js"; import { PostClientTransport } from "@cloudbase/mcp/transport/client/post"; const transport = new PostClientTransport( // 将链接中的 your-env-id 替换为云开发环境 id // 将链接中的 your-service-name 替换为云托管服务名 new URL( "https://your-env-id.api.tcloudbasegateway.com/v1/cloudrun/your-service-name/messages" ), { requestInit: { headers: { // 将 your-api-key 替换为实际的 API KEY Authorization: `Bearer your-api-key`, }, }, } ); const client = new Client( { name: "your-mcp-name", version: "1.0.0", }, { capabilities: { tools: {}, }, } ); await client.connect(transport); ``` 从 MCP Server 获取工具列表: ```ts const prompts = await client.listTools(); ``` 发起工具调用: ```ts const result = await client.callTool({ name: "example-tool", arguments: { arg1: "value", }, }); ``` --- ## 小程序接入云开发 AI 能力指引 # 小程序接入云开发 AI 能力指引 :::tip 云开发 AI+ 无缝接入 DeepSeek + 混元双模型开发智能体,支持小程序、h5、公众号、微信客服等场景 新用户首月免费体验,并赠送 100 万 token 立即体验云开发平台AI能力,点击查看 [完整指引](./quickstart) ::: 本文介绍 **小程序** 如何快速接入 **云开发AI**(满血版DeepSeek)能力 解锁云开发平台更多AI核心能力,**智能问答机器人、企业知识库AI化、微信平台客服AI化** 点击查看 [快速指引](./quickstart) ## 准备工作 - 注册一个微信小程序账号,并且创建本地小程序工程项目 - 小程序基础库需要在 3.7.1 及以上版本,具备 `wx.cloud.extend.AI` 对象 - 小程序需要开通「云开发」,可在小程序开发工具中点击工具栏里的「云开发」按钮进行开通,并创建环境(PS:对于首次使用云开发的用户,第一个月套餐免费): - ![image](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/3103c75d-07f3-4085-aac3-30840942acb1.png) ## 指引一:调用大模型,实现文本生成 在小程序中,直接调用大模型的文本生成能力,实现最简单的文本生成。 这里以一个“七言绝句”生成器的简单 Demo 为例: ### 第 1 步:初始化云开发环境 在小程序代码中,通过以下代码进行云开发环境初始化: ```js wx.cloud.init({ env: "", }); ``` 其中 `""` 需替换为实际云开发环境 ID。初始化成功后,就可使用 `wx.cloud.extend.AI` 调用 AI 能力。 ### 第 2 步: 创建 AI 模型,并调用生成文本 在小程序基础库 3.7.1 及以上,以调用 DeepSeek-R1 模型为例,小程序端的代码如下: ```js // 创建模型实例,这里我们使用 DeepSeek 大模型 const model = wx.cloud.extend.AI.createModel("deepseek"); // 我们先设定好 AI 的系统提示词,这里以七言绝句生成为例 const systemPrompt = "请严格按照七言绝句或七言律诗的格律要求创作,平仄需符合规则,押韵要和谐自然,韵脚字需在同一韵部。创作内容围绕用户给定的主题,七言绝句共四句,每句七个字;七言律诗共八句,每句七个字,颔联和颈联需对仗工整。同时,要融入生动的意象、丰富的情感与优美的意境,展现出古诗词的韵味与美感。"; // 用户的自然语言输入,如‘帮我写一首赞美玉龙雪山的诗’ const userInput = "帮我写一首赞美玉龙雪山的诗"; // 将系统提示词和用户输入,传入大模型 const res = await model.streamText({ data: { model: "deepseek-r1", // 指定具体的模型 messages: [ { role: "system", content: systemPrompt }, { role: "user", content: userInput }, ], }, }); // 接收大模型的响应 // 由于大模型的返回结果是流式的,所以我们这里需要循环接收完整的响应文本。 for await (let str of res.textStream) { console.log(str); } // 输出结果: // "# 咏玉龙雪山\n" // "皑皑峻岭入云巅,玉骨冰肌傲九天。\n" // "雪影岚光添胜景,神山圣境韵绵绵。\n" ``` 可见,仅需几行小程序代码,就可以通过云开发直接调用大模型的文本生成能力。 ## 指引二:通过 Agent(智能体)实现智能对话 通过调用大模型的文本生成接口,可以快速实现一问一答的场景。但对于一个完整的对话功能来说,仅仅有一个大模型的输入、输出还不够,还需要把大模型变为完整的 Agent,才能更好地与用户进行对话。 云开发的 AI 能力不仅提供了原始的大模型接入,还提供了 Agent 接入的能力,开发者可以在云开发上定义自己的 Agent,然后通过小程序直接调用 Agent 进行对话。 ### 第 1 步:初始化云开发环境 在小程序代码中,通过以下代码进行云开发环境初始化: ```js wx.cloud.init({ env: "", }); ``` 其中 `""` 需替换为实际云开发环境 ID。初始化成功后,就可使用 `wx.cloud.extend.AI` 调用 AI 能力。 ### 第 2 步:创建一个 Agent 进入[云开发平台-AI+](https://tcb.cloud.tencent.com/dev?#/ai?tab=agent),选择模板并创建一个 Agent。 您可以通过 LangChain、LangGraph 等开源框架创建 Agent,也可以对接元器、智能体开发平台、Dify 等第三方 Agent。 ![image](https://qcloudimg.tencent-cloud.cn/raw/101789f6825af86a3013c8ccece73990.png) 点击页面中上方的“复制 ID”,我们会获得一个 `bot-id`,即 Agent 的唯一标识,在下面的代码中会用到。 ![image](https://qcloudimg.tencent-cloud.cn/raw/6768c2c95f42a8bf690ba70bd086558e.png) ### 第 3 步:在小程序中实现与 Agent 的对话 刚才创建了一个“小程序开发专家”的 Agent 智能体,下面来试试与它进行对话,看他能不能处理云开发常见的报错问题。 在小程序中,使用以下代码直接调用刚刚我们创建的 Agent,进行对话: ```js // 初始化 wx.cloud.init({ env: "", }); // 用户的输入,这里我们以某个报错信息为例 const userInput = "我的小程序这个报错是什么意思:FunctionName parameter could not be found"; const res = await wx.cloud.extend.AI.bot.sendMessage({ data: { botId: "xxx-bot-id", // 第2步中获取的Agent唯一标识 msg: userInput, // 用户的输入 history: [], // 历史对话的内容,这里我们是第一轮对话,所以可以不传入 }, }); for await (let x of res.textStream) { console.log(x); } // 输出结果: // "### 报错解释\n" // "**错误信息:** `FunctionName \n" // "parameter could not be found` \n // "这个错误通常表示在调用某个函数时,\n" // "指定的函数名参数没有找到。具体来说,\n" // "可能是以下几种情况之一:\n" // …… ``` 我们也可以把对话内容记录下来,重复调用 Agent 的接口,从而实现多轮对话 ```js const res = await wx.cloud.extend.AI.bot.sendMessage({ data: { botId: "xxx-bot-id", // 第2步中获取的Agent唯一标识 msg: userInput, // 用户的输入 history: [ { role: "user", message: "我这个报错是什么意思?……"}, { role: "bot", message: "### 报错解释……" }, { role: "user", message: "那我要如何操作来修复呢?" } // …… ] }, }); ``` ### 第 4 步:实现更加丰富的聊天功能 云开发在 SDK 中提供了一整套接入 Agent(智能体)的 API 接口,包括基础对话、对话历史保存、对话反馈收集、次轮问题推荐等。 小程序开发者可在[云开发平台](https://tcb.cloud.tencent.com/dev?#/ai?tab=agent)中创建 Agent,然后在小程序前端代码中直接调用 `wx.cloud.extend.AI` 下的各类接口直接与 Agent 进行交互,包含: - 获取聊天记录 - 发送、获取用户反馈 - 获取推荐次轮问题 下面是一些代码示例: #### 获取聊天记录 ```js await wx.cloud.extend.AI.bot.getChatRecords({ botId: "botId-xxx", pageNumber: 1, pageSize: 10, sort: "asc", }); ``` 传入 botId、分页信息和排序方式,获取指定 Agent 的聊天记录。 #### 发送反馈与获取反馈 发送用户反馈: ```js const res = await wx.cloud.extend.AI.bot.sendFeedback({ userFeedback: { botId: "botId-xxx", recordId: "recordId-xxx", comment: "非常棒", rating: 5, tags: ["优美"], aiAnswer: "落英缤纷", input: "来个成语", type: "upvote", }, }); ``` #### 获取次轮推荐问题 ```js const res = await wx.cloud.extend.AI.bot.getRecommendQuestions({ data: { botId: "xxx-bot-id", msg: "介绍一下 Python 语言", }, }); for await (let x of res.textStream) { console.log(x); } ``` 在 `data` 参数中设置 `botId` 和用户消息 `msg`,通过遍历 `textStream` 获取推荐问题。 ## 指引三:使用云开发 AI 对话组件,快速接入 AI 对话 为了方便开发者快速在自己的小程序里实现 AI 对话功能,云开发提供了一个 AI 对话的小程序源码组件供开发者直接使用,效果如下图: ### 第 1 步:下载组件包 方式一:直接[下载组件示例包](https://gitee.com/TencentCloudBase/cloudbase-agent-ui/tree/main/apps/miniprogram-agent-ui),包含agent-ui 源码组件和使用指引 方式二:通过微信开发者工具创建 agent-ui 组件模板,根据指引配置使用 ![](https://qcloudimg.tencent-cloud.cn/raw/9e7ce66913a90131071d84b3b8117635.png) ### 第 2 步:引入组件到自己的小程序项目 1. 拷贝 miniprogram/components/agent-ui 组件到小程序中 ![image](https://qcloudimg.tencent-cloud.cn/raw/2fb0ff731e5fbded35b970589c9ec89d.png) 2. 在页面 index.json 配置文件中注册组件 ```js { "usingComponents": { "agent-ui":"/components/agent-ui/index" }, } ``` 3. 在页面 index.wxml 文件中使用组件 ```js ``` 4. 在页面 index.js 文件中编写配置 对接 Agent : ```js data: { chatMode: "bot", // bot 表示使用agent,model 表示使用大模型 showBotAvatar: true, // 是否在对话框左侧显示头像 agentConfig: { botId: "bot-e7d1e736", // agent id, allowWebSearch: true, // 允许客户端选择启用联网搜索 allowUploadFile: true, // 允许上传文件 allowPullRefresh: true, // 允许下拉刷新 allowUploadImage: true // 允许上传图片 showToolCallDetail: true, // 是否展示工具调用细节 allowMultiConversation: true, // 是否展示会话列表,创建会话按钮 } } ``` 对接大模型: ```js data: { chatMode: "model", // bot 表示使用agent,model 表示使用大模型 showBotAvatar: true, // 是否在对话框左侧显示头像 modelConfig: { modelProvider: "hunyuan-open", // 大模型服务厂商 quickResponseModel: "hunyuan-lite", // 大模型名称 logo: "", // model 头像 welcomeMsg: "欢迎语", // model 欢迎语 }, } ``` ### 第 3 步:初始化云开发环境 在 app.js 中,onLauch 生命周期内,初始化 sdk ```js // app.js App({ onLaunch: function () { wx.cloud.init({ env: "", }); }, }); ``` 随后便可以直接在页面中使用 AI 对话组件了: ![image](https://qcloudimg.tencent-cloud.cn/raw/a1b717e5ab264d89977f564aecb9c30c.png) ## 总结 这篇文章一共介绍了云开发的以下三种方式接入大模型,分别适用于不同的场景: 1. 通过 SDK 直接调用大模型:适用于非对话类的通用场景,如文本生成、智能补全、智能翻译等。 2. 通过 SDK 调用 Agent(智能体)对话能力:这种方式适合专门的 AI 对话场景,支持配置欢迎语、提示词、知识库等对话中需要的能力。 3. 使用 AI 对话组件:这种方式对于专业前端开发者更友好,可以基于云开发提供的 UI 组件,快速在小程序中植入 AI 对话能力。 以上的三种小程序接入 AI 的方式,云开发将完整的代码示例放在了代码仓库中,供大家参考: - Gitee:https://gitee.com/TencentCloudBase/cloudbase-ai-example - Github:https://github.com/TencentCloudBase/cloudbase-ai-example 当然,不只是小程序,云开发的 AI 能力也支持通过 Web 应用、Node.js、 HTTP API 来对大模型进行调用,可以参考以下文档: - Web 应用接入:https://docs.cloudbase.net/ai/sdk-reference/init - Node.js 接入:https://docs.cloudbase.net/ai/sdk-reference/init - HTTP API 接入:https://docs.cloudbase.net/http-api/ai-bot/ai-agent-%E6%8E%A5%E5%85%A5 :::tip 解锁云开发平台更多AI核心能力,点击查看 [快速指引](./quickstart) ::: 未来,云开发计划推出更多的 AI 能力,如 Tool Calling(工具调用)、多 Agent 串联、工作流编排等,敬请期待,可访问以下内容获取更多信息: - 腾讯云开发主页:https://tcb.cloud.tencent.com/ - 云开发官方文档:https://docs.cloudbase.net/ - 云开发 Agent 能力用户交流群: - ![image](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/c14f5766-59cf-4d98-acda-0b83eb501da8.png) --- ## 概述 # 概述 ## 大模型接入是什么 我们提供了快速接入**腾讯混元大模型**、**DeepSeek**的服务,我们为开发者提供了 Web、小程序双端可用的 AI SDK ,做到一套代码多端、多模型适用。**除此之外,微信小程序基础库已经内置支持了大模型接入,专注于小程序的开发者可以直接通过小程序原生代码调用 AI+ 模块提供的相关功能。** ## 如何启用大模型接入 可访问「[云开发/AI+](https://tcb.cloud.tencent.com/dev#/ai)」,选择接入 AI 大模型后,在已有的大模型列表中启用任一大模型。 启用大模型时,需要在大模型厂商处获取到调用模型的 key 或相关认证信息,并填写到大模型配置中。 各个可用模型的调用密钥、key 或相关认证信息,可以通过大模型的产品文档中了解到获取方法。 大模型启用后即可使用 AI SDK 在您的应用中接入大模型了。 :::tip 云开发 AI+ 无缝接入 DeepSeek 新用户首月免费体验,并赠送 100 万 token ::: ## 有什么大模型可以被接入 目前支持接入的大模型列表包含: - [腾讯混元](https://hunyuan.tencent.com/) - [DeepSeek](https://www.deepseek.com/) 也可访问「[云开发/AI+](https://tcb.cloud.tencent.com/dev#/ai)」,在大模型列表中查看支持接入的大模型。 ## 为什么要使用大模型接入 使用大模型接入服务可以提高为应用接入大模型的效率,不用被各家大模型的调用细节干扰,还可以在多家大模型之间快速切换使用。同时 AI SDK 提供了简洁的文本生成接口,并且支持流式调用。 ### 多端适用兼容的文本生成 AI SDK 支持在 Web 端和小程序端使用,并且提供了统一的对接大模型的接口。无论是运行在 Web 端还是小程序端,都可以使用一套代码实现 AI 接入。 :::tip 除了 SDK 支持之外,我们还开放了 HTTP API,发起 HTTP 请求即可接入大模型。 ::: 这里我们选择接入混元大模型,调用大模型生成介绍李白的文本,并且将结果打印出来。 ```ts const model = ai.createModel("hunyuan-exp"); // 创建模型 const result = await model.generateText({ model: "hunyuan-lite", messages: [{ role: "user", content: "你好,请你介绍一下李白" }], }); console.log(result.text); ``` ### 易用的流式文本生成接口 AI SDK 提供了同样简洁的流式文本生成接口,这在需要与用户交互的场景十分有用,比如构建智能聊天机器人、流式展示长生成文本等等。 这里我们会试着将大模型流式返回的文本增量地添加到网页上: ```ts const model = ai.createModel("hunyuan-exp"); // 创建模型 const result = await model.streamText({ model: "hunyuan-lite", messages: [{ role: "user", content: "你好,请你介绍一下李白" }], }); for await (let str of result.textStream) { document.body.innerText += str; } ``` 同样的简洁程度,我们完成了流式调用文本生成! ### 强大的工具调用支持 AI SDK 支持大模型工具调用。使用工具调用功能,可以增强模型推理效果或进行其他外部操作,包括信息检索、数据库操作、知识图谱搜索与推理、操作系统、触发外部操作等场景。 ```mermaid sequenceDiagram 用户->>+大模型: 请问北京天气怎么样? 大模型->>+查询天气函数: 调用查询天气函数,city=北京 查询天气函数->>-大模型: 北京天气为 26 摄氏度 大模型->>-用户: 北京天气为 26 摄氏度,总体凉爽偏热,适宜穿短袖 Note over 大模型,查询天气函数: 工具调用 ``` 使用 AI SDK,只需几步即可完成工具调用: 1. 定义工具 2. 注册工具 3. 告知大模型有哪些可用工具并与大模型进行对话 ```js // 省略初始化 AI sdk 的操作... // 1. 定义获取天气的工具,详见 FunctionTool 类型 const getWeatherTool = { name: "get_weather", description: "返回某个城市的天气信息。调用示例:get_weather({city: '北京'})", fn: ({ city }) => `${city}的天气是:秋高气爽!!!`, // 在这定义工具执行的内容 parameters: { type: "object", properties: { city: { type: "string", description: "要查询的城市", }, }, required: ["city"], }, }; // 2. 注册我们刚定义好的工具 ai.registerFunctionTool(getWeatherTool); // 3. 在给大模型发送消息的同时,告知大模型可用一个获取天气的工具 const model = ai.createModel("hunyuan-exp"); const result = await model.generateText({ model: "hunyuan-turbo", tools: [getWeatherTool], // 这里我们传入了获取天气工具 messages: [ { role: "user", content: "请告诉我北京的天气状况" } ] }) console.log(result.text); ``` 在简单地添加了三个步骤后,我们实现了带有工具调用功能的大模型接入。AI SDK 帮我们处理了以下内容: 1. 解析大模型响应中的工具调用 2. 执行对应的工具调用 3. 将工具调用结果构造成新的消息再次发送给大模型 4. 将最终结果返回给调用者 --- ## 大模型配置指南 # 大模型配置指南 本文档将指导您如何在云开发平台中接入和配置各类大模型 云开发已预先集成 **混元、DeepSeek** 到平台中 ## 接入大模型 :::warning 注意事项 自定义模型仅支持兼容 **OpenAI** 协议的大模型接口 ::: ### 所需参数 接入自定义模型需要准备以下三个关键参数: * **BaseURL**:大模型API的请求地址(**兼容 OpenAI 协议的大模型接口**) * **APIKey**:访问大模型API的密钥 * **模型名称**:具体的模型标识符,如`hunyuan-turbos-latest`、`deepseek-chat`等 ### 接入步骤 1. **获取 BaseURL、API Key** 以下提供hunyuan、DeepSeek的接入示例,其他大模型请参考对应模型供应商文档获取 | 模型 | 模型提供商 | BaseURL示例 | 模型名称 | 计费相关 | | ------ | ------------------ | ---- | ---- | ---- | | hunyuan | [腾讯混元大模型](https://cloud.tencent.com/document/product/1729/111007) | https://api.hunyuan.cloud.tencent.com/v1 | 参考 [混元模型列表](https://cloud.tencent.com/document/product/1729/104753#5302f6cb-c29a-4e77-a579-2c2053122c1e) | 参考 [计费文档](https://cloud.tencent.com/document/product/1729/106126) | | DeepSeek | [腾讯云智能体平台/DeepSeek](https://cloud.tencent.com/document/product/1772/115969) | https://api.lkeap.cloud.tencent.com/v1 | 参考 [DeepSeek模型列表](https://cloud.tencent.com/document/product/1772/115969#7ff8883d-341b-44ca-aceb-79627349700d) | 参考 [计费文档](https://cloud.tencent.com/document/product/1772/111126) DeepSeek 仅支持开通 **后付费** | | DeepSeek | [DeepSeek官方](https://api-docs.deepseek.com/zh-cn/) | https://api.deepseek.com/v1 | 参考 [DeepSeek模型列表](https://api-docs.deepseek.com/zh-cn/quick_start/pricing) | 参考 [DeepSeek文档](https://api-docs.deepseek.com/zh-cn/) | 2. **在平台中配置** - 进入 [云开发/ai+](https://tcb.cloud.tencent.com/dev?#/ai?tab=ai-model) 控制台 - 点击「新增」或「修改配置」 3. **填写BaseURL、API Key** 云开发平台已默认配置 [腾讯混元大模型](https://cloud.tencent.com/document/product/1729/111007) 和 [腾讯云智能体平台/DeepSeek](https://cloud.tencent.com/document/product/1729/111007) 的模型名称 若您需要接入其他大模型,请在「**模型名称**」中填写对应的模型名称 ![API Key配置界面](https://qcloudimg.tencent-cloud.cn/raw/8092ccc21f97af144ffe6697664d0e15.png) ## 接入示例 ### 官方DeepSeek 1. **获取BaseURL和模型名称** - 访问 [DeepSeek API文档](https://api-docs.deepseek.com/zh-cn/) - 确认 **BaseURL**: `https://api.deepseek.com/v1` - 查看可用 **模型名称**: * `deepseek-chat` (对应DeepSeek-V3-0324) * `deepseek-reasoner` (对应DeepSeek-R1-0528) 2. **获取API Key** - 登录[DeepSeek控制台](https://platform.deepseek.com/) - 在**APIkeys**页面创建并获取API Key 3. **在云开发平台配置** - 进入[云开发/ai+](https://tcb.cloud.tencent.com/dev?#/ai?tab=ai-model)控制台 - 点击「**新建大模型**」按钮 - 填写以下信息: * 分组名称(自定义) * BaseURL * API Key * 模型名称 ![](https://qcloudimg.tencent-cloud.cn/raw/e8eb2b2d91ec7c6bc6b4b451ce375a65.png) 4. **等待配置生效** - 系统需要几分钟时间完成配置 - 配置成功后,您将看到如下效果: ![自定义模型配置成功](https://qcloudimg.tencent-cloud.cn/raw/3805a7c4bb0cab84275c00920884fb01.png) ## 常见问题 ### 1: 如何判断我的大模型是否兼容OpenAI协议? A: 兼容OpenAI协议的大模型通常在其API文档中会明确说明,或者其API结构与OpenAI的接口规范一致(如使用相似的端点和参数结构)。 ### 2: 配置后无法正常使用大模型怎么办? A: 请检查以下几点: * API Key是否正确且未过期 * BaseURL是否准确 * 模型名称是否与提供商文档中的一致 * 网络连接是否正常 ### 3: 大模型支持多少并发? 使用平台赠送 token 时,一个环境支持 5 个并发。 您可以添加了自定义模型,或者修改了deepseek/hunyuan的配置,填写第三方的API Key。 做了上述配置之后,平台将不再限制并发,需要看下第三方模型提供商的限制。 --- ## 快速开始 # 快速开始 :::tip 云开发 AI+ 无缝接入 DeepSeek + 混元双模型开发智能体,支持小程序、h5、公众号、微信客服等场景 新用户首月免费体验,并赠送 100 万 token [了解更多](/ai/FAQ) ::: 在云开发 [AI+](https://tcb.cloud.tencent.com/dev?#/ai) 中,我们提供一系列与 AI 相关的功能,如大模型接入、 Agent开发、MCP托管等,帮助开发者为自己的小程序、web 或者应用快速接入 AI 能力。同时也提供了云开发 Copilot,来加速用户的开发,帮助用户更快构建自己的应用。 ## 🚀 快速开始 1. 首先您需要拥有腾讯云账号并开通云开发环境,[立即开通云开发环境](/quick-start/create-env) 2. 登录 [云开发平台](https://tcb.cloud.tencent.com/dev) ## 🧠 Agent 选择 Agent 搭建功能入口:[Agent 搭建](https://tcb.cloud.tencent.com/dev?#/ai?tab=agent),[查看详细文档](./agent/) | 核心场景 | 能力介绍 | 操作指引 | | -------------------- | -------------------------------------------------------------------------------------------------------------------------- | :----------------------------: | | **智能问答 Agent** | 🧠 支持对接垂直知识库 ✅ 支持多轮对话/意图识别/多语言场景 | [搭建指南](./agent/quickstart) | | **自动化智能 Agent** | 🧠 通过 MCP 为 AI 提供调用外部世界的能力,AI 自动拆解任务,调用 MCP 连接万物并执行 | [搭建指南](./agent/mcp) | | **复杂 Agent** | 🧠 通过编码来调用 AI 大模型、 MCP 插件、知识库、对接业务数据和业务接口,实现自定义代码逻辑 | [搭建指南](./cbrf-agent/intro) | 云开发 Copilot就是基于 AI+ 的 Agent 构建能力搭建的 ## 💻 Agent 集成 开发完成的 Agent ,可以通过以下方式进行使用: | 核心场景 | 能力介绍 | 操作指引 | | ------------------ | ---------------------------------------------- | :------------------------------------: | | **小程序** | ⚡ 即时响应/智能应答/多场景话术支持 | [立即接入](./agent/release-mp) | | **web 应用** | ⚡ 即时响应/智能应答/多场景话术支持 | [立即接入](./agent/release) | | **公众号客服** | ⚡ 即时响应/智能应答/多场景话术支持 | [立即接入](./agent/integration-pa) | | **小程序客服** | ⚡ 即时响应/智能应答/多场景话术支持 | [立即接入](./agent/integration-mp) | | **企微客服** | ⚡ 即时响应/智能应答/知识库联动/多场景话术支持 | [立即接入](./agent/integration-workwx) | | **服务号客服** | ⚡ 即时响应/智能应答/知识库联动/多场景话术支持 | [立即接入](./agent/integration-server) | | **现有应用中集成** | 🔧 现有**小程序/PC/H5**无缝接入方案 | [代码对接方案](./agent/agent-ui) | ## 🧩 AI 组件接入 | 组件名称 | 操作指引 | | ----------------------- | :-----------------------------------: | | **小程序源码组件** 集成 | [快速接入](./agent-ui/agent-ui-mp) | | **微搭可视化组件** 集成 | [快速接入](./agent-ui/) | | **React 组件** 集成 | [快速接入](./agent-ui/agent-ui-react) | ## ⚙️ AI SDK 接入 | 核心场景 | 操作指引 | | ----------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------: | | **微信小程序** 集成 | [快速接入](./sdk-reference/init#小程序端初始化) | | **微信小游戏** 集成 | [快速接入](./sdk-reference/init#小程序端初始化) | | **微信跨端框架** 集成 | [快速接入](https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/miniapp/new-capability/cloud/cloud.html#_3-5-wx-cloud-extend-AI-%E6%8E%A5%E5%8F%A3) | | **web 端** 集成 | [快速接入](./sdk-reference/init#web-端初始化) | | **Node 端** 集成 | [快速接入](./sdk-reference/init#云函数-nodejs-端初始化) | | **微搭中** 集成 | [快速接入](./sdk-reference/init#在微搭中初始化) | | **App 端** 集成 | [快速接入](./FAQ#uniapptaro-等框架如何使用云开发-ai-能力) | | **其他语言和框架** 集成 | [快速接入](./api-key) | ## 产品简介 [云开发平台](https://cloud.tencent.com/document/product/1301/48874) 是一个 **高智能高效率** 的 **应用开发搭建平台**,提供如下能力: - **拖拽式开发** 与 **可视化配置**,快速构建 **PC Web/H5/小程序** 应用 - 深度集成 **企业微信管理**、工作流、消息推送等**企业级能力** - 无缝连接微信生态,支持 **微信支付/腾讯会议/腾讯文档** 等 SaaS 产品联动 - 原生小程序支持,助力企业内外协同与数字化运营 - **AI+** 集成能力,轻松集成 满血版 DeepSeek ![](https://qcloudimg.tencent-cloud.cn/raw/6ddba4ebad49d2c540693e1781afe76c.png) ### 特色功能 - 产品 **AI** 助手 [了解更多](./copilot/ai-copilot) - **AI** 对话生成应用 [了解更多](./copilot/ai-gen-app) - **AI** 对话编辑组件样式 [了解更多](./copilot/ai-gen-css) - **AI** 识图生成提示词和需求 [了解更多](./copilot/screenshot-to-prompt) ## 常见问题 FAQ 若遇到问题,请先参考 [常见问题 FAQ 文档](./FAQ),若还未解决,请加入社群和我们交流 --- ## AI SDK # AI SDK ## 初始化 SDK 初始化方法请参考[初始化 SDK](../sdk-reference/init)。 ## app.ai 初始化后,可以使用挂载至 cloudbase 实例上的 ai 方法创建 [AI](#ai) 实例,用于后续模型创建。 ### 使用示例 ```ts app = cloudbase.init({ env: "your-env" }); const ai = app.ai(); ``` ### 类型声明 ```ts function ai(): AI; ``` #### 返回值 > `AI` 返回新创建的 [AI](#ai) 实例。 ## AI 用于创建 AI 模型的类。 ### createModel() 创建指定的 AI 模型。 #### 使用示例 ```ts const model = ai.createModel("hunyuan-exp"); ``` #### 类型声明 ```ts function createModel(model: string): ChatModel; ``` 返回一个实现了 ChatModel 抽象类的模型实例,该实例提供 AI 生成文本相关能力。 ### bot 挂载了 Bot 类的实例,上面集合了一系列与 Agent 交互的方法。具体可参考 [Bot 类](#bot-1) 的详细文档。 #### 使用示例 ```ts const agentList = await ai.bot.list({ pageNumber: 1, pageSize: 10 }); ``` ### registerFunctionTool() 注册函数工具。在进行大模型调用时,可以告知大模型可用的函数工具,当大模型的响应被解析为工具调用时,会自动调用对应的函数工具。 #### 使用示例 ```js // 省略初始化 AI sdk 的操作... // 1. 定义获取天气的工具,详见 FunctionTool 类型 const getWeatherTool = { name: "get_weather", description: "返回某个城市的天气信息。调用示例:get_weather({city: '北京'})", fn: ({ city }) => `${city}的天气是:秋高气爽!!!`, // 在这定义工具执行的内容 parameters: { type: "object", properties: { city: { type: "string", description: "要查询的城市", }, }, required: ["city"], }, }; // 2. 注册我们刚定义好的工具 ai.registerFunctionTool(getWeatherTool); // 3. 在给大模型发送消息的同时,告知大模型可用一个获取天气的工具 const model = ai.createModel("hunyuan-exp"); const result = await model.generateText({ model: "hunyuan-turbo", tools: [getWeatherTool], // 这里我们传入了获取天气工具 messages: [ { role: "user", content: "请告诉我北京的天气状况", }, ], }); console.log(result.text); ``` #### 类型声明 ```ts function registerFunctionTool(functionTool: FunctionTool); ``` #### 参数 | 参数名 | 必填 | 类型 | 说明 | | ------------ | ---- | ------------ | ---------------------------------- | | functionTool | 是 | FunctionTool | 详见 [FunctionTool](#functiontool) | #### 返回值 `undefined` ## ChatModel 这个抽象类描述了 AI 生文模型类提供的接口。 ### generateText() 调用大模型生成文本。 #### 使用示例 ```ts const hy = ai.createModel("hunyuan-exp"); // 创建模型 const res = await hy.generateText({ model: "hunyuan-lite", messages: [{ role: "user", content: "你好,请你介绍一下李白" }], }); console.log(res.text); // 打印生成的文本 ``` #### 类型声明 ```ts function generateText(data: BaseChatModelInput): Promise; text: string; messages: Array; usage: Usage; error?: unknown; }>; ``` #### 参数 | 参数名 | 必填 | 类型 | 示例 | 说明 | | ------ | ---- | ------------------ | ------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | data | 是 | BaseChatModelInput | `{model: "hunyuan-lite", messages: [{ role: "user", content: "你好,请你介绍一下李白" }]}` | 参数类型定义为 [BaseChatModelInput](#basechatmodelinput) ,作为基础的入参定义。实际上各家大模型还会有各自独特的输入参数,开发者可按需根据实际使用的大模型官方文档传入其他不在此类型中被定义的参数,充分利用大模型提供的能力。其他参数会被透传至大模型接口, SDK 侧不对它们不做额外处理。 | #### 返回值 | 属性名 | 类型 | 示例 | 说明 | | ------------ | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------ | | text | string | `"李白是一位唐朝诗人。"` | 大模型生成的文本。 | | rawResponses | unknown[] | `[{"choices": [{"finish_reason": "stop","message": {"role": "assistant", "content": "你好呀,有什么我可以帮忙的吗?"}}], "usage": {"prompt_tokens": 14, "completion_tokens": 9, "total_tokens": 23}}]` | 大模型的完整返回值,包含更多详细数据,如消息创建时间等等。由于各家大模型返回值互有出入,请根据实际情况使用。 | | res.messages | ChatModelMessage[] | `[{role: 'user', content: '你好'},{role: 'assistant', content: '你好!很高兴与你交流。请问有什么我可以帮助你的吗?无论是关于生活、工作、学习还是其他方面的问题,我都会尽力为你提供帮助。'}]` | 本次调用的完整消息列表。 | | usage | Usage | `{"completion_tokens":33,"prompt_tokens":3,"total_tokens":36}` | 本次调用消耗的 token。 | | error | unknown | | 调用过程中产生的错误。 | ### streamText() 以流式调用大模型生成文本。流式调用时,生成的文本及其他响应数据会通过 SSE 返回,该接口的返回值对 SSE 做了不同程度的封装,开发者能根据实际需求获取到文本流和完整数据流。 #### 使用示例 ```ts const hy = ai.createModel("hunyuan-exp"); // 创建模型 const res = await hy.streamText({ model: "hunyuan-lite", messages: [{ role: "user", content: "你好,请你介绍一下李白" }], }); for await (let str of res.textStream) { console.log(str); // 打印生成的文本 } for await (let data of res.dataStream) { console.log(data); // 打印每次返回的完整数据 } ``` #### 类型声明 ```ts function streamText(data: BaseChatModelInput): Promise; ``` #### 参数 | 参数名 | 必填 | 类型 | 示例 | 说明 | | ------ | ---- | ------------------ | ------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | data | 是 | BaseChatModelInput | `{model: "hunyuan-lite", messages: [{ role: "user", content: "你好,请你介绍一下李白" }]}` | 参数类型定义为 [BaseChatModelInput](#basechatmodelinput) ,作为基础的入参定义。实际上各家大模型还会有各自独特的输入参数,开发者可按需根据实际使用的大模型官方文档传入其他不在此类型中被定义的参数,充分利用大模型提供的能力。其他参数会被透传至大模型接口, SDK 侧不对它们不做额外处理。 | #### 返回值 | StreamTextResult 属性名 | 类型 | 说明 | | ----------------------- | ----------------------------- | ---------------------------------------------------------------------------------------------------------------------- | | textStream | `ReadableStream` | 以流式返回的大模型生成文本,可参考使用示例获取到生成的增量文本。 | | dataStream | `ReadableStream` | 以流式返回的大模型响应数据,可参考使用示例获取到生成的增量数据。由于各家大模型响应值互有出入,请根据实际情况合理使用。 | | messages | `Promise` | 本次调用的完整消息列表。 | | usage | `Promise` | 本次调用消耗的 token。 | | error | `unknown` | 本次调用产生的错误。 | | DataChunk 属性名 | 类型 | 说明 | | ------------------------ | ------------------ | ---------------------- | | choices | `Array` | | | choices[n].finish_reason | `string` | 模型终止推断的原因。 | | choices[n].delta | `ChatModelMessage` | 本次请求的消息。 | | usage | `Usage` | 本次请求消耗的 token。 | | rawResponse | `unknown` | 大模型返回的原始回复。 | #### 示例 ```js const hy = ai.createModel("hunyuan-exp"); const res = await hy.streamText({ model: "hunyuan-lite", messages: [{ role: "user", content: "1+1结果是" }], }); // 文本流 for await (let str of res.textStream) { console.log(str); } // 1 // 加 // 1 // 的结果 // 是 // 2 // 。 // 数据流 for await (let str of res.dataStream) { console.log(str); } // {created: 1723013866, id: "a95a54b5c5d2144eb700e60d0dfa5c98", model: "hunyuan-lite", version: "202404011000", choices: Array(1), …} // {created: 1723013866, id: "a95a54b5c5d2144eb700e60d0dfa5c98", model: "hunyuan-lite", version: "202404011000", choices: Array(1), …} // {created: 1723013866, id: "a95a54b5c5d2144eb700e60d0dfa5c98", model: "hunyuan-lite", version: "202404011000", choices: Array(1), …} // {created: 1723013866, id: "a95a54b5c5d2144eb700e60d0dfa5c98", model: "hunyuan-lite", version: "202404011000", choices: Array(1), …} // {created: 1723013866, id: "a95a54b5c5d2144eb700e60d0dfa5c98", model: "hunyuan-lite", version: "202404011000", choices: Array(1), …} // {created: 1723013866, id: "a95a54b5c5d2144eb700e60d0dfa5c98", model: "hunyuan-lite", version: "202404011000", choices: Array(1), …} // {created: 1723013866, id: "a95a54b5c5d2144eb700e60d0dfa5c98", model: "hunyuan-lite", version: "202404011000", choices: Array(1), …} // {created: 1723013866, id: "a95a54b5c5d2144eb700e60d0dfa5c98", model: "hunyuan-lite", version: "202404011000", choices: Array(1), …} ``` ## Bot 用于与 Agent 交互的类。 ### get() 获取某个 Agent 的信息。 #### 使用示例 ```ts const res = await ai.bot.get({ botId: "botId-xxx" }); console.log(res); ``` #### 类型声明 ```ts function get(props: { botId: string }); ``` #### 参数 | 参数名 | 必填 | 类型 | 说明 | | ----------- | ---- | ------ | ------------------------ | | props.botId | 是 | string | 要获取信息的 Agent 的 id | #### 返回值 | 属性名 | 类型 | 示例 | 说明 | | --------------- | ------- | ---------------- | ------------------------ | | botId | string | `"bot-27973647"` | Agent ID | | name | string | `"信达雅翻译"` | Agent 名称 | | introduction | string | | Agent 简介 | | welcomeMessage | string | | Agent 欢迎语 | | avatar | string | | Agent 头像链接 | | background | string | | Agent 聊天背景图链接 | | isNeedRecommend | boolean | | Agent 回答后是否推荐问题 | | type | string | | Agent 类型 | ### list() 批量获取多个 Agent 的信息。 #### 使用示例 ```ts await ai.bot.list({ pageNumber: 1, pageSize: 10, name: "", enable: true, information: "", introduction: "", }); ``` #### 类型声明 ```ts function list(props: { name: string; introduction: string; information: string; enable: boolean; pageSize: number; pageNumber: number; }); ``` #### 参数 | 参数名 | 必填 | 类型 | 说明 | | ------------------ | ---- | ------- | ------------------------ | | props.pageNumber | 是 | number | 分页下标 | | props.pageSize | 是 | number | 分页大小 | | props.enable | 是 | boolean | Agent 是否启用 | | props.name | 是 | string | Agent 名字,用于模糊查询 | | props.information | 是 | string | Agent 信息,用于模糊查询 | | props.introduction | 是 | string | Agent 简介,用于模糊查询 | #### 返回值 | 属性名 | 类型 | 示例 | 说明 | | ---------------------------- | --------------- | ---------------- | ------------------------ | | total | number | --- | Agent 总数 | | botList | `Array` | | Agent 列表 | | `botList[n].botId` | string | `"bot-27973647"` | Agent ID | | `botList[n].name` | string | `"信达雅翻译"` | Agent 名称 | | `botList[n].introduction` | string | | Agent 简介 | | `botList[n].welcomeMessage` | string | | Agent 欢迎语 | | `botList[n].avatar` | string | | Agent 头像链接 | | `botList[n].background` | string | | Agent 聊天背景图链接 | | `botList[n].isNeedRecommend` | boolean | | Agent 回答后是否推荐问题 | | `botList[n].type` | string | | Agent 类型 | ### sendMessage() 与 Agent 进行对话。响应会通过 SSE 返回,该接口的返回值对 SSE 做了不同程度的封装,开发者能根据实际需求获取到文本流和完整数据流。 #### 使用示例 ```ts const res = await ai.bot.sendMessage({ botId: "botId-xxx", history: [{ content: "你是李白。", role: "user" }], msg: "你好", }); for await (let str of res.textStream) { console.log(str); } for await (let data of res.dataStream) { console.log(data); } ``` #### 类型声明 ```ts function sendMessage(props: { botId: string; msg: string; history: Array; }): Promise; ``` #### 参数 | 参数名 | 必填 | 类型 | 说明 | | -------------------------- | ---- | ------ | -------------------------- | | props.botId | 是 | string | Agent id | | props.msg | 是 | string | 此次对话要发送的消息 | | props.history | 是 | [] | 在此次对话前发生的聊天记录 | | `props.history[n].role` | 是 | string | 本聊天信息的发送角色 | | `props.history[n].content` | 是 | string | 本聊天信息的内容 | #### 返回值 `Promise` | StreamResult 属性名 | 类型 | 说明 | | ------------------- | ---- | ---- | | textStream | `AsyncIterable` | 以流式返回的 Agent 生成文本,可参考使用示例获取到生成的增量文本。 | | dataStream | `AsyncIterable` | 以流式返回的 Agent 生成文本,可参考使用示例获取到生成的增量文本。 | | AgentStreamChunk 属性名 | 类型 | 说明 | | ------------------- | ---- | ---- | | created | number | 对话时间戳 | | record_id | string | 对话记录ID | | model | string | 大模型类型 | | version | string | 大模型版本 | | type | string | 回复类型: text: 主要回答内容,thinking: 思考过程,search: 查询结果,knowledge: 知识库 | | role | string | 对话角色,响应中固定为 assistant | | content | string | 对话内容 | | finish_reasion | string | 对话结束标志,continue 表示对话未结束,stop 表示对话结束 | | reasoning_content | string | 深度思考内容(仅deepseek-r1是不为空字符串) | | usage | object | token使用量 | | usage.prompt_tokens | number | 表示prompt的tokens数,多次返回中保持不变 | | usage.completion_tokens | number | 回答的token总数,在流式返回中,表示到目前为止所有completion的tokens总数,多次返回中持续累加 | | usage.total_tokens | number | 表示prompt_tokens和completion_tokens之和 | | knowledge_base | string[] | 对话中使用到的知识库 | | search_info | object | 搜索结果信息,需要开启联网查询 | | search_info.search_results | object[] | 搜索引文信息 | | search_info.search_results[n].index | string | 搜索引文序号 | | search_info.search_results[n].title | string | 搜索引文标题 | | search_info.search_results[n].url | string | 搜索引文链接 | ### getChatRecords() 获取聊天记录。 #### 使用示例 ```ts await ai.bot.getChatRecords({ botId: "botId-xxx", pageNumber: 1, pageSize: 10, sort: "asc", }); ``` #### 类型声明 ```ts function getChatRecords(props: { botId: string; sort: string; pageSize: number; pageNumber: number; }); ``` #### 参数 | 参数名 | 必填 | 类型 | 说明 | | ---------------- | ---- | ------ | -------- | | props.botId | 是 | string | Agent id | | props.sort | 是 | string | 排序方式 | | props.pageSize | 是 | number | 分页大小 | | props.pageNumber | 是 | number | 分页下标 | #### 返回值 | 属性名 | 类型 | 说明 | | ---------------------------- | --------------- | ------------------- | | total | number | 对话总数 | | recordList | `Array` | 对话总数 | | `recordList[n].botId` | string | Agent ID | | `recordList[n].recordId` | string | 对话 ID,由系统生成 | | `recordList[n].role` | string | 对话中的角色 | | `recordList[n].content` | string | 对话内容 | | `recordList[n].conversation` | string | 用户标识 | | `recordList[n].type` | string | 对话数据类型 | | `recordList[n].image` | string | 对话生成的图片链接 | | `recordList[n].triggerSrc` | string | 对话发起来源 | | `recordList[n].replyTo` | string | 对话回复的记录 ID | | `recordList[n].createTime` | string | 对话时间 | ### sendFeedback() 发送对某条聊天记录的反馈信息。 #### 使用示例 ```ts const res = await ai.bot.sendFeedback({ userFeedback: { botId: "botId-xxx", recordId: "recordId-xxx", comment: "非常棒", rating: 5, tags: ["优美"], aiAnswer: "落英缤纷", input: "来个成语", type: "upvote", }, botId: "botId-xxx", }); ``` #### 类型声明 ```ts function sendFeedback(props: { userFeedback: IUserFeedback; botId: string }); ``` #### 参数 | 参数名 | 必填 | 类型 | 说明 | | ------------------ | ---- | ------------- | ------------------------------------------------------- | | props.userFeedback | 是 | IUserFeedback | 用户反馈,详见 [IUserFeedback 类型定义](#iuserfeedback) | | props.botId | 是 | string | 将要反馈的 Agent id | ### getFeedback() 获取已存在的反馈信息。 #### 使用示例 ```ts const res = await ai.bot.getFeedback({ botId: "botId-xxx", from: 0, to: 0, maxRating: 4, minRating: 3, pageNumber: 1, pageSize: 10, sender: "user-a", senderFilter: "include", type: "upvote", }); ``` #### 类型声明 ```ts function sendFeedback(props: { botId: string; type: string; sender: string; senderFilter: string; minRating: number; maxRating: number; from: number; to: number; pageSize: number; pageNumber: number; }); ``` #### 参数 | 参数名 | 必填 | 类型 | 说明 | | ------------------ | ---- | ------ | -------------------------------------------------------------------------------------- | | props.botId | 是 | string | Agent id | | props.type | 是 | string | 用户反馈类型,点赞 upvote 点踩 downvote | | props.sender | 是 | string | 评论创建用户 | | props.senderFilter | 是 | string | 评论创建用户过滤关系 include:包含 exclude:不包含 equal:等于 unequal:不等于 prefix:前缀 | | props.minRating | 是 | number | 最低评分 | | props.maxRating | 是 | number | 最高评分 | | props.from | 是 | number | 开始时间戳 | | props.to | 是 | number | 结束时间戳 | | props.pageSize | 是 | number | 分页大小 | | props.pageNumber | 是 | number | 分页下标 | #### 返回值 | 属性名 | 类型 | 说明 | | ------------------------ | -------- | --------------------------------------- | | feedbackList | object[] | 反馈查询结果 | | feedbackList[n].recordId | string | 对话记录 ID | | feedbackList[n].type | string | 用户反馈类型,点赞 upvote 点踩 downvote | | feedbackList[n].botId | string | Agent ID | | feedbackList[n].comment | string | 用户评论 | | feedbackList[n].rating | number | 用户评分 | | feedbackList[n].tags | string[] | 用户反馈的标签数组 | | feedbackList[n].input | string | 用户输入的问题 | | feedbackList[n].aiAnswer | string | Agent 的回答 | | total | number | 反馈总数 | ### uploadFiles() 将云存储中的文件上传至 Agent,用于进行文档聊天。 #### 使用示例 ```ts // 上传文件 await ai.bot.uploadFiles({ botId: "botId-xxx", fileList: [ { fileId: "cloud://xxx.docx", fileName: "xxx.docx", type: "file", }, ], }); // 进行文档聊天 const res = await ai.bot.sendMessage({ botId: "your-bot-id", msg: "这个文件的内容是什么", files: ["xxx.docx"], // 文件 fileId 数组 }); for await (let text of res.textStream) { console.let(text); } ``` #### 类型声明 ```ts function uploadFiles(props: { botId: string; fileList: Array; }); ``` #### 参数 | 参数名 | 必填 | 类型 | 说明 | | -------------------------- | ---- | ------ | ------------------- | | props.botId | 是 | string | Agent id | | props.fileList | 是 | string | 文件列表 | | props.fileList[n].fileId | 是 | string | 云存储文件 id | | props.fileList[n].fileName | 是 | string | 文件名 | | props.fileList[n].type | 是 | string | 暂时只支持 `"file"` | ### getRecommendQuestions() 获取推荐的问题。 #### 使用示例 ```ts const res = ai.bot.getRecommendQuestions({ botId: "botId-xxx", history: [{ content: "你是谁啊", role: "user" }], msg: "你好", agentSetting: "", introduction: "", name: "", }); for await (let str of res.textStream) { console.log(str); } ``` #### 类型声明 ```ts function getRecommendQuestions(props: { botId: string; name: string; introduction: string; agentSetting: string; msg: string; history: Array; }): Promise; ``` #### 参数 | 参数名 | 必填 | 类型 | 说明 | | -------------------------- | ---- | ------ | ------------ | | props.botId | 是 | string | Agent id | | props.name | 是 | string | Agent 名称 | | props.introduction | 是 | string | Agent 简介 | | props.agentSetting | 是 | string | Agent 设定 | | props.msg | 是 | string | 用户发送信息 | | props.history | 是 | Array | 历史对话信息 | | `props.history[n].role` | 是 | string | 历史信息角色 | | `props.history[n].content` | 是 | string | 历史信息内容 | #### 返回值 `Promise` | StreamResult 属性名 | 类型 | 说明 | | ------------------- | ---- | ---- | | textStream | `AsyncIterable` | 以流式返回的 Agent 生成文本,可参考使用示例获取到生成的增量文本。 | | dataStream | `AsyncIterable` | 以流式返回的 Agent 生成文本,可参考使用示例获取到生成的增量文本。 | | AgentStreamChunk 属性名 | 类型 | 说明 | | ------------------- | ---- | ---- | | created | number | 对话时间戳 | | record_id | string | 对话记录ID | | model | string | 大模型类型 | | version | string | 大模型版本 | | type | string | 回复类型: text: 主要回答内容,thinking: 思考过程,search: 查询结果,knowledge: 知识库 | | role | string | 对话角色,响应中固定为 assistant | | content | string | 对话内容 | | finish_reasion | string | 对话结束标志,continue 表示对话未结束,stop 表示对话结束 | | reasoning_content | string | 深度思考内容(仅deepseek-r1是不为空字符串) | | usage | object | token使用量 | | usage.prompt_tokens | number | 表示prompt的tokens数,多次返回中保持不变 | | usage.completion_tokens | number | 回答的token总数,在流式返回中,表示到目前为止所有completion的tokens总数,多次返回中持续累加 | | usage.total_tokens | number | 表示prompt_tokens和completion_tokens之和 | | knowledge_base | string[] | 对话中使用到的知识库 | | search_info | object | 搜索结果信息,需要开启联网查询 | | search_info.search_results | object[] | 搜索引文信息 | | search_info.search_results[n].index | string | 搜索引文序号 | | search_info.search_results[n].title | string | 搜索引文标题 | | search_info.search_results[n].url | string | 搜索引文链接 | ### createConversation() 创建与 Agent 的新对话。 #### 使用示例 ```ts const res = await ai.bot.createConversation({ botId: "botId-xxx", title: "我的对话", }): Promise; ``` #### 类型声明 ```ts function createConversation(props: IBotCreateConversation); ``` #### 参数 | 参数名 | 必填 | 类型 | 说明 | | ----------- | ---- | ------ | -------- | | props.botId | 是 | string | Agent ID | | props.title | 否 | string | 对话标题 | #### 返回值 `Promise` 相关类型:[IConversation](#iconversation) ### getConversation() 获取对话列表。 #### 使用示例 ```ts const res = await ai.bot.getConversation({ botId: "botId-xxx", pageSize: 10, pageNumber: 1, isDefault: false, }); ``` #### 类型声明 ```ts function getConversation(props: IBotGetConversation); ``` #### 参数 | 参数名 | 必填 | 类型 | 说明 | | ---------------- | ---- | ------- | ------------------ | | props.botId | 是 | string | Agent ID | | props.pageSize | 否 | number | 分页大小,默认 10 | | props.pageNumber | 否 | number | 分页下标,默认 1 | | props.isDefault | 否 | boolean | 是否只获取默认对话 | ### deleteConversation() 删除指定对话。 #### 使用示例 ```ts await ai.bot.deleteConversation({ botId: "botId-xxx", conversationId: "conv-123", }); ``` #### 类型声明 ```ts function deleteConversation(props: IBotDeleteConversation); ``` #### 参数 | 参数名 | 必填 | 类型 | 说明 | | -------------------- | ---- | ------ | --------------- | | props.botId | 是 | string | Agent ID | | props.conversationId | 是 | string | 要删除的对话 ID | ### speechToText() 语音转文字。 #### 使用示例 ```ts const res = await ai.bot.speechToText({ botId: "botId-xxx", engSerViceType: "16k_zh", voiceFormat: "mp3", url: "https://example.com/audio.mp3", }); ``` #### 类型声明 ```ts function speechToText(props: IBotSpeechToText); ``` #### 参数 | 参数名 | 必填 | 类型 | 说明 | | -------------------- | ---- | ------- | -------------------- | | props.botId | 是 | string | Agent ID | | props.engSerViceType | 是 | string | 引擎类型,如"16k_zh" | | props.voiceFormat | 是 | string | 音频格式,如"mp3" | | props.url | 是 | string | 音频文件 URL | | props.isPreview | 否 | boolean | 是否为预览模式 | ### textToSpeech() 文字转语音。 #### 使用示例 ```ts const res = await ai.bot.textToSpeech({ botId: "botId-xxx", voiceType: 1, text: "你好,我是AI助手", }); ``` #### 类型声明 ```ts function textToSpeech(props: IBotTextToSpeech); ``` #### 参数 | 参数名 | 必填 | 类型 | 说明 | | --------------- | ---- | ------- | -------------- | | props.botId | 是 | string | Agent ID | | props.voiceType | 是 | number | 语音类型 | | props.text | 是 | string | 要转换的文本 | | props.isPreview | 否 | boolean | 是否为预览模式 | ### getTextToSpeechResult() 获取文字转语音的结果。 #### 使用示例 ```ts const res = await ai.bot.getTextToSpeechResult({ botId: "botId-xxx", taskId: "task-123", }); ``` #### 类型声明 ```ts function getTextToSpeechResult(props: IBotGetTextToSpeechResult); ``` #### 参数 | 参数名 | 必填 | 类型 | 说明 | | --------------- | ---- | ------- | -------------- | | props.botId | 是 | string | Agent ID | | props.taskId | 是 | string | 任务 ID | | props.isPreview | 否 | boolean | 是否为预览模式 | ## IBotCreateConversation ```ts interface IBotCreateConversation { botId: string; title?: string; } ``` ## IBotGetConversation ```ts interface IBotGetConversation { botId: string; pageSize?: number; pageNumber?: number; isDefault?: boolean; } ``` ## IBotDeleteConversation ```ts interface IBotDeleteConversation { botId: string; conversationId: string; } ``` ## IBotSpeechToText ```ts interface IBotSpeechToText { botId: string; engSerViceType: string; voiceFormat: string; url: string; isPreview?: boolean; } ``` ## IBotTextToSpeech ```ts interface IBotTextToSpeech { botId: string; voiceType: number; text: string; isPreview?: boolean; } ``` ## IBotGetTextToSpeechResult ```ts interface IBotGetTextToSpeechResult { botId: string; taskId: string; isPreview?: boolean; } ``` ## BaseChatModelInput ```ts interface BaseChatModelInput { model: string; messages: Array; temperature?: number; topP?: number; tools?: Array; toolChoice?: "none" | "auto" | "custom"; maxSteps?: number; onStepFinish?: (prop: IOnStepFinish) => unknown; } ``` | BaseChatModelInput 属性名 | 类型 | 说明 | | ------------------------- | ---------------------------------- | --------------------------------------------------- | | model | `string` | 模型名称。 | | messages | `Array` | 消息列表。 | | temperature | `number` | 采样温度,控制输出的随机性。 | | topP | `number` | 温度采样,即模型考虑概率质量为 top_p 的标记的结果。 | | tools | `Array` | 大模型可用的工具列表。 | | toolChoice | `string` | 指定大模型选择工具的方式。 | | maxSteps | `number` | 请求大模型的最大次数。 | | onStepFinish | `(prop: IOnStepFinish) => unknown` | 当对大模型的一次请求完成时,出发的回调函数。 | ## BotInfo ```ts interface BotInfo { botId: string; name: string; introduction: string; agentSetting: string; welcomeMessage: string; avatar: string; background: string; tags: Array; isNeedRecommend: boolean; knowledgeBase: Array; type: string; initQuestions: Array; enable: true; } ``` ## IUserFeedback ```ts interface IUserFeedback { recordId: string; type: string; botId: string; comment: string; rating: number; tags: Array; input: string; aiAnswer: string; } ``` ## ChatModelMessage ```ts type ChatModelMessage = | UserMessage | SystemMessage | AssistantMessage | ToolMessage; ``` ### UserMessage ```ts type UserMessage = { role: "user"; content: string; }; ``` ### SystemMessage ```ts type SystemMessage = { role: "system"; content: string; }; ``` ### AssistantMessage ```ts type AssistantMessage = { role: "assistant"; content?: string; tool_calls?: Array; }; ``` ### ToolMessage ```ts type ToolMessage = { role: "tool"; tool_call_id: string; content: string; }; ``` ## ToolCall ```ts export type ToolCall = { id: string; type: string; function: { name: string; arguments: string }; }; ``` ## FunctionTool 工具定义类型。 ```ts type FunctionTool = { name: string; description: string; fn: CallableFunction; parameters: object; }; ``` | FunctionTool 属性名 | 类型 | 说明 | | ------------------- | ------------------ | -------------------------------------------------------------------------------------------------- | | name | `string` | 工具名称。 | | description | `string` | 工具的描述。清楚的工具描述有助于大模型认识工具的用途。 | | fn | `CallableFunction` | 工具的执行函数。当 AI SDK 解析出大模型的响应需要该工具调用时,会调用此函数,并将结果返回给大模型。 | | parameters | `object` | 工具执行函数的入参。需要使用 JSON Schema 的格式定义入参。 | ## IOnStepFinish 大模型响应后出发的回调函数的入参类型。 ```ts interface IOnStepFinish { messages: Array; text?: string; toolCall?: ToolCall; toolResult?: unknown; finishReason?: string; stepUsage?: Usage; totalUsage?: Usage; } ``` | IOnStepFinish 属性名 | 类型 | 说明 | | -------------------- | ------------------------- | -------------------------------- | | messages | `Array` | 到当前步骤为止所有的消息列表。 | | text | `string` | 当前响应的文本。 | | toolCall | `ToolCall` | 当前响应调用的工具。 | | toolResult | `unknown` | 对应的工具调用结果。 | | finishReason | `string` | 大模型推理结束的原因。 | | stepUsage | `Usage` | 当前步骤所花费的 token。 | | totalUsage | `Usage` | 到当前步骤为止所花费的总 token。 | ## Usage ```ts type Usage = { completion_tokens: number; prompt_tokens: number; total_tokens: number; }; ``` ## IConversation Agent 会话。 ```ts interface IConversation { id: string; envId: string; ownerUin: string; userId: string; conversationId: string; title: string; startTime: string; // date-time format createTime: string; updateTime: string; } ``` --- ## 混元大模型使用指南 # 混元大模型使用指南 ## 图生文 :::tip 调用 `createModel` 并传入 `"hunyuan-exp"` 或 `"hunyuan-open"` 创建混元大模型,并且使用 `"hunyuan-vision"` 作为调用 `streamText` / `generateText` 时传入的 `model` 参数。 详情可参考下文示例代码。 ::: 在使用图生文时,传入的参数与普通对话生文有所不同,`messages[n].content` 为数组,数组内的元素可以为表示文字/图片的对象,如下所示: ```js async function readImage() { const model = ai.createModel("hunyuan-exp"); const res = await model.streamText({ model: "hunyuan-vision", messages: [ { role: "user", content: [ { type: "text", text: "下面图片的内容是什么?", }, { type: "image_url", image_url: { url: "https://cloudcache.tencent-cloud.com/qcloud/ui/portal-set/build/About/images/bg-product-series_87d.png", }, }, ], }, ], }); for await (let x of res.textStream) { console.log(x); } } ``` 当 `messages[n].content` 表示文字时,对象类型表示为: ```ts interface TextContent { type: "text", // 固定值 text: string, // 文字内容 } ``` 当 `messages[n].content` 表示图片时,对象类型表示为: ```ts interface ImageContent { type: "image_url", // 固定值 image_url: { url: string, // 图片链接 }, } ``` --- ## SDK 初始化 # SDK 初始化 ## web 端初始化 ```javascript // 在 Web 项目的根目录下,使用 npm 或 yarn 安装所需的包: // npm i @cloudbase/js-sdk // 引入 SDK,这里我们引入了完整的 clousebase-js-sdk,也支持分模块引入 import cloudbase from "@cloudbase/js-sdk"; const app = cloudbase.init({ env: "your-env", // 需替换为实际使用环境 id }); const auth = app.auth(); await auth.signInAnonymously(); // 或者使用其他登录方式 const ai = app.ai(); // 接下来就可以调用 ai 模块提供的方法了 ``` ## 小程序端初始化 :::tip 微信小程序基础库和 AI SDK,我该用哪个? **AI SDK 和微信小程序基础库提供的 AI 能力是相同的。** AI SDK 是云开发提供的多端 SDK,在多个平台都有一致的使用体验。如果您有一码多端的需求,可以选用 AI SDK。 然而在小程序上使用 AI SDK 会受到一定的限制: 1. [小程序包体积有限制](https://developers.weixin.qq.com/miniprogram/dev/framework/subpackages.html),引入 AI SDK 会增加一定的包体积 2. [小程序需要配置服务器域名](https://developers.weixin.qq.com/miniprogram/dev/framework/ability/network.html#_1-%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%9F%9F%E5%90%8D%E9%85%8D%E7%BD%AE),配置完成后 AI SDK 才能进行请求 微信小程序基础库内置了完整的云开发 AI 能力,不占用包体积,也无需配置服务器域名。对于专注于小程序的开发者们,使用微信小程序基础库是一个好的选择。在不用安装任何外部包的情况下,也能完整地访问到云开发提供的 AI+ 能力。 微信小程序基础库和 AI SDK 在使用方法上有一定的区分,请注意阅读文档。 ::: ### 使用微信小程序基础库 ```javascript wx.cloud.init({ env: "lowcode-2gp2855c5ce22e35", // 指定云开发环境 ID }); const ai = wx.cloud.extend.AI; // 接下来就可以调用 ai 模块提供的方法了 ``` ### 使用 AI SDK ```javascript // 在开始之前,请确保完成配置了小程序 request 合法域名,详情请参考 https://docs.cloudbase.net/quick-start/baas/wx-mini // 在小程序 package.json 所在的目录(一般是 miniprogram 目录)执行命令安装 npm 包: // npm i @cloudbase/js-sdk // 安装完成后,点击微信开发者工具的菜单栏中「工具 -> 构建 npm」 // 引入 SDK,这里我们以分模块的形式按需引入了 cloudbase-js-sdk,也支持完整引入 import cloudbase from "@cloudbase/js-sdk/app"; import { registerAuth } from "@cloudbase/js-sdk/auth"; import { registerAi } from "@cloudbase/js-sdk/ai"; registerAuth(cloudbase); registerAi(cloudbase); const app = cloudbase.init({ env: "your-env", // 需替换为实际使用环境 id }); const auth = app.auth({ persistence: "local" }); await auth.signInWithOpenId(); // 或者使用其他登录方式 const ai = app.ai(); // 接下来就可以调用 ai 模块提供的方法了 ``` ## 云函数 Node.js 端初始化 云函数的运行环境为 Node.js。在云函数中使用 AI SDK 接入大模型,Agent 之前,需要完成以下的初始化工作。 :::danger Node.js 版本要求 Node.js 要求 18 以上版本,请在新建云函数时注意选择符合要求的 Node.js 版本。 ::: ```javascript // 在 Node.js 项目的根目录下,使用 npm 或 yarn 安装所需的包: // npm i @cloudbase/js-sdk // npm i @cloudbase/adapter-node // 引入 SDK,这里我们引入了完整的 clousebase-js-sdk,也支持分模块引入 const cloudbase = require("@cloudbase/js-sdk"); // 引入 node.js 端的适配器,详情请参考 https://docs.cloudbase.net/api-reference/webv3/adapter#%E4%B8%80%E5%A5%97%E4%BB%A3%E7%A0%81%E5%A4%9A%E7%AB%AF%E9%80%82%E9%85%8D const adapter = require("@cloudbase/adapter-node"); const { sessionStorage } = adapter.genAdapter(); cloudbase.useAdapters(adapter); const app = cloudbase.init({ env: "your-env", // 需替换为实际使用环境 id }); /** * auth 初始化的时候要传入storage 和 captchaOptions.openURIWithCallback * 否则会用默认的,依赖于平台,在 nodejs 环境报错 */ const auth = app.auth({ storage: sessionStorage, captchaOptions: { openURIWithCallback: () => console.log("open uri with callback"), }, }); exports.main = async (event, context) => { await auth.signInAnonymously(); // 或者使用其他登录方式 const ai = app.ai(); // 接下来就可以调用 ai 模块提供的方法了 }; ``` ## 在微搭中初始化 在微搭应用中可以通过 `$w.cloud.getCloudInstance` 获取 cloudbase 实例,并且不用关心登录等逻辑。 ```javascript async function initAi() { const app = await $w.cloud.getCloudInstance(); const ai = app.ai(); // 接下来就可以调用 ai 模块提供的方法了 } ``` ## 完成初始化后 在完成 SDK 初始化后,即可开始使用 AI+ 的各种能力了。可以参考以下文章进行使用: - [接入大模型](../model/aimodel.md) - [接入 Agent](../agent/sdk.md) - [大模型 API](./api.md) ## 参考链接 AI SDK 以 Cloudbase BaaS 为基础,在开发前推荐了解 BaaS 的各项配置,如安全域名、登录权限等,详情可参考: - [Cloudbase BaaS 后台即服务](../../quick-start/baas/introduce) --- ## 微信小程序基础库 API # 微信小程序基础库 API 微信小程序基础库从 `3.7.1` 版本开始内置了云开发 AI+ 能力,开发者可以直接通过小程序中的 `wx.cloud.extend.AI` 调用。 ## 初始化 在使用基础库 AI+ 能力前,需要传入云开发环境进行初始化。 ```javascript wx.cloud.init({ env: "your-env-id" }); ``` 初始化完毕后,即可通过 `wx.cloud.extend.AI` 使用云开发 AI+ 能力。 ## 大模型 ### AI.createModel() 创建指定的 AI 模型。 #### 使用示例 ```ts const model = wx.cloud.extend.AI.createModel("hunyuan-exp"); ``` #### 类型声明 ```ts function createModel(model: string): ChatModel; ``` 返回一个提供 AI 生成文本能力的对象。 ### ChatModel.streamText() 以流式调用大模型生成文本。流式调用时,生成的文本及其他响应数据会通过 [SSE](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events) 返回,该接口的返回值对 SSE 做了不同程度的封装,开发者能根据实际需求获取到文本流和完整数据流。 #### 使用示例 ```ts const hy = wx.cloud.extend.AI.createModel("hunyuan-exp"); // 创建模型 const res = await hy.streamText({ data: { model: "hunyuan-lite", messages: [ { role: "user", content: "hi" } ] } }); for await (let str of res.textStream) { console.log(str); // 打印生成的文本 } for await (let event of res.eventStream) { console.log(event); // 打印每次返回的完整数据 // 当大模型结束传输时,通常会发一条 [DONE] 数据,在此之后即可停止循环 if (event.data === "[DONE]") { break; } } ``` #### 类型声明 ```ts function streamText(props: StreamTextInput): Promise; interface StreamTextResult { eventStream: EventStream; textStream: TextStream; } interface StreamTextInput { data: unknown; onEvent?: OnEvent; onText?: OnText; onFinish?: OnFinish; } interface OnEvent { (prop: { data: string }): unknown; } interface OnText { (text: string): unknown; } interface OnFinish { (text: string): unknown; } interface EventStream { [Symbol.asyncIterator](): AsyncIterator; } interface TextStream { [Symbol.asyncIterator](): AsyncIterator; } ``` #### 参数 | 参数名 | 必填 | 类型 | 示例 | 说明 | | ------ | ---- | ------------------ | ------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | props.data | 是 | `unknown` | `{model: "hunyuan-lite", messages: [{ role: "user", content: "你好,请你介绍一下李白" }]}` | 各家大模型的调用参数不同,请根据实际调用模型传入正确的参数。 | | props.tools | 否 | `object` | -- | 工具调用相关参数 | | props.tools.autoExecute | 否 | `boolean` | `true` | 是否自动调用工具,默认为 `true` | | props.tools.maxStep | 否 | `number` | `10` | 最大自动执行的次数,默认为 10 次 | | props.tools.list | 否 | `Array` | -- | 工具列表 | | `props.tools.list[n].name` | 是 | `string` | `"get_weather"` | 工具名称 | | `props.tools.list[n].description` | 否 | `string` | `返回某个城市的某天的温度信息。调用示例:get_weather({city: '北京',date: '03-19'})` | 工具描述 | | `props.tools.list[n].fn` | 是 | `function` | `({ city, date }) => city + "在" + date + "的温度是:" + (20 + (Math.random() * 10))` | 工具执行的回调函数 | | `props.tools.list[n].parameters` | 否 | `{"type":"object","properties":{"city":{"type":"string","description":"要查询的城市"},"date":{"type":"string","description":"要查询的日期"}},"required":["city","date"]}` | -- | 工具执行回调函数的入参 schema 定义 | | props.tools.onToolEvent | 否 | `function` | `console.warn` | 监听大模型执行 tool_call 的事件 | | props.onText | 否 | `(text: string) => unknown;` | `(text) => console.log(text)` | 接收到新文本返回时触发的回调函数,参数为增量的文本 | | props.onEvent | 否 | `(prop: { data: string }) => unknown;` | `({data}) => console.log(data)` | 接收到新事件返回时触发的回调函数,参数为事件,prop.data 为此次事件包含的数据 | | props.onFinish | 否 | `(text: string) => unknown;` | `(text) => console.log(text)` | 当本次调用完全结束时触发的回调函数,参数为本次调用返回的完整文本 | #### 返回值 | StreamTextResult 属性名 | 类型 | 说明 | | -------------- | ----------------------------- | ----------------------------------------------------------- | | textStream | `AsyncIterable` | 以流式返回的大模型生成文本,可参考使用示例获取到生成的增量文本。 | | eventStream | `AsyncIterable` | 以流式返回的大模型响应数据,可参考使用示例获取到生成的增量数据。由于各家大模型响应值互有出入,请根据实际情况合理使用。 | ### ChatModel.generateText() 调用大模型生成文本。 #### 使用示例 ```ts const hy = wx.cloud.extend.AI.createModel("hunyuan-exp"); // 创建模型 const res = await hy.generateText({ model: "hunyuan-lite", messages: [{ role: "user", content: "你好" }], }); console.log(res); // { // "id": "27dae91f4e9a4777782c61f89acf8ea4", // "object": "chat.completion", // "created": 1737602298, // "model": "hunyuan-lite", // "system_fingerprint": "", // "choices": [ // { // "index": 0, // "message": { // "role": "assistant", // "content": "你好!很高兴与你交流。请问有什么我可以帮助你的吗?无论是关于生活、工作、学习还是其他方面的问题,我都会尽力为你提供帮助。" // }, // "finish_reason": "stop" // } // ], // "usage": { // "prompt_tokens": 3, // "completion_tokens": 33, // "total_tokens": 36 // }, // "note": "以上内容为AI生成,不代表开发者立场,请勿删除或修改本标记" // } console.log(res.choices[0].message.content); // 你好!很高兴与你交流。请问有什么我可以帮助你的吗?无论是关于生活、工作、学习还是其他方面的问题,我都会尽力为你提供帮助。 ``` #### 类型声明 ```ts function generateText(data: unknown): Promise; ``` #### 参数 | 参数名 | 必填 | 类型 | 示例 | 说明 | | ------ | ---- | ------------------ | ------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | data | 是 | unknown | `{model: "hunyuan-lite", messages: [{ role: "user", content: "你好,请你介绍一下李白" }]}` | 各家大模型的调用参数不同,请根据实际调用模型传入正确的参数。 | #### 返回值 该接口直接返回实际调用大模型的响应值,需要根据实际响应内容解析出需要的数据。参见上文使用示例。 ## Agent ### AI.bot.get() 获取某个 Agent 的信息。 #### 使用示例 ```ts await wx.cloud.extend.AI.bot.get({ botId: "botId-xxx" }); ``` #### 类型声明 ```ts function get(props: { botId: string }); ``` #### 参数 | 参数名 | 必填 | 类型 | 说明 | | -------- | ---- | ------ | ------------------------ | | props.botId | 是 | string | 要获取信息的 Agent 的 id | #### 返回值 | 属性名 | 类型 | 示例 | 说明 | | --- | --- | --- | --- | | botId | string | `"bot-27973647"` | Agent ID | | name | string | `"信达雅翻译"` | Agent 名称 | | introduction | string | | Agent 简介 | | welcomeMessage | string | | Agent 欢迎语 | | avatar | string | | Agent 头像链接 | | background |string | | Agent 聊天背景图链接 | | isNeedRecommend | boolean | | Agent 回答后是否推荐问题 | | type | string | | Agent 类型 | ### AI.bot.list() 批量获取多个 Agent 的信息。 #### 使用示例 ```ts await wx.cloud.extend.AI.bot.list({ pageNumber: 1, pageSize: 10, name: "", enable: true, information: "", introduction: "", }); ``` #### 类型声明 ```ts function list(props: { name: string; introduction: string; information: string; enable: boolean; pageSize: number; pageNumber: number; }); ``` #### 参数 | 参数名 | 必填 | 类型 | 说明 | | ------------------ | ---- | ------- | ------------------------ | | props.pageNumber | 是 | number | 分页大小 | | props.pageSize | 是 | number | 分页下标 | | props.enable | 是 | boolean | Agent 是否启用 | | props.name | 是 | string | Agent 名字,用于模糊查询 | | props.information | 是 | string | Agent 信息,用于模糊查询 | | props.introduction | 是 | string | Agent 简介,用于模糊查询 | #### 返回值 | 属性名 | 类型 | 示例 | 说明 | | --- | --- | --- | --- | | total | number | --- | Agent 总数 | | botList | `Array` | | Agent 列表 | | `botList[n].botId` | string | `"bot-27973647"` | Agent ID | | `botList[n].name` | string | `"信达雅翻译"` | Agent 名称 | | `botList[n].introduction` | string | | Agent 简介 | | `botList[n].welcomeMessage` | string | | Agent 欢迎语 | | `botList[n].avatar` | string | | Agent 头像链接 | | `botList[n].background` |string | | Agent 聊天背景图链接 | | `botList[n].isNeedRecommend` | boolean | | Agent 回答后是否推荐问题 | | `botList[n].type` | string | | Agent 类型 | ### AI.bot.sendMessage() 与 Agent 进行对话。 #### 使用示例 ```ts const res = await wx.cloud.extend.AI.bot.sendMessage({ data: { botId: 'xxx-bot-id', msg: "你是谁" } }) for await (let x of res.textStream) { console.log(x) } ``` #### 类型声明 ```ts function sendMessage(props: { data: { botId: string; msg: string; history: Array; files?: Array, }, onText: OnText, onEvent: OnEvent, onFinish: OnFinish }); ``` #### 参数 | 参数名 | 必填 | 类型 | 说明 | | -------------------------- | ---- | ------- | -------------------------- | | props.data.botId | 是 | number | Agent id | | props.data.msg | 是 | number | 此次对话要发送的消息 | | props.data.history | 是 | boolean | 在此次对话前发生的聊天记录 | | `props.data.history[n].role` | 是 | string | 本聊天信息的发送角色 | | `props.data.history[n].content` | 是 | string | 本聊天信息的内容 | | `props.data.files` | 否 | `Array` | 本聊天信息附带的文件内容,需要填入云存储的文件 cloud id | | props.onText | 否 | `(text: string) => unknown;` | 接收到新文本返回时触发的回调函数,参数为增量的文本 | | props.onEvent | 否 | `(prop: { data: string }) => unknown;` | 接收到新事件返回时触发的回调函数,参数为事件,prop.data 为此次事件包含的数据的字符串 | | props.onFinish | 否 | `(text: string) => unknown;` | 当本次调用完全结束时触发的回调函数,参数为本次调用返回的完整文本 | ### AI.bot.getChatRecords() 获取聊天记录。 #### 使用示例 ```ts await wx.cloud.extend.AI.bot.getChatRecords({ botId: "botId-xxx", pageNumber: 1, pageSize: 10, sort: "asc", }); ``` #### 类型声明 ```ts function getChatRecords(props: { botId: string; sort: string; pageSize: number; pageNumber: number; }); ``` #### 参数 | 参数名 | 必填 | 类型 | 说明 | | ---------------- | ---- | ------ | -------- | | props.botId | 是 | string | Agent id | | props.sort | 是 | string | 排序方式 | | props.pageSize | 是 | number | 分页大小 | | props.pageNumber | 是 | number | 分页下标 | #### 返回值 | 属性名 | 类型 | 说明 | |--------------|--------|------------------------| | total | number | 对话总数 | | recordList | `Array` | 对话总数 | | `recordList[n].botId` | string | Agent ID | | `recordList[n].recordId` | string | 对话ID,由系统生成 | | `recordList[n].role` | string | 对话中的角色 | | `recordList[n].content` | string | 对话内容 | | `recordList[n].conversation` | string | 用户标识 | | `recordList[n].type` | string | 对话数据类型 | | `recordList[n].image` | string | 对话生成的图片链接 | | `recordList[n].triggerSrc` | string | 对话发起来源 | | `recordList[n].replyTo` | string | 对话回复的记录ID | | `recordList[n].createTime` | string | 对话时间 | ### AI.bot.sendFeedback() 发送对某条聊天记录的反馈信息。 #### 使用示例 ```ts const res = await wx.cloud.extend.AI.bot.sendFeedback({ userFeedback: { botId: "botId-xxx", recordId: "recordId-xxx", comment: "非常棒", rating: 5, tags: ["优美"], aiAnswer: "落英缤纷", input: "来个成语", type: "upvote", }, }); ``` #### 类型声明 ```ts function sendFeedback(props: { userFeedback: IUserFeedback, botId: string }); ``` #### 参数 | 参数名 | 必填 | 类型 | 说明 | | ------------------ | ---- | ------------- | ---------------------------------------------------------------- | | props.userFeedback | 是 | IUserFeedback | 用户反馈,详见 [IUserFeedback 类型定义](./api#iuserfeedback) | | props.botId | 是 | string | 将要反馈的 Agent id | ### AI.bot.getFeedBack() 获取已存在的反馈信息。 #### 使用示例 ```ts const res = await wx.cloud.extend.AI.bot.getFeedBack({ botId: "botId-xxx", from: 0, to: 0, maxRating: 4, minRating: 3, pageNumber: 1, pageSize: 10, sender: "user-a", senderFilter: "include", type: "upvote", }); ``` #### 类型声明 ```ts function getFeedBack(props: { botId: string; type: string; sender: string; senderFilter: string; minRating: number; maxRating: number; from: number; to: number; pageSize: number; pageNumber: number; }); ``` #### 参数 | 参数名 | 必填 | 类型 | 说明 | | ------------------ | ---- | ------ | -------------------------------------------------------------------------------------- | | props.botId | 是 | string | Agent id | | props.type | 是 | string | 用户反馈类型,点赞 upvote 点踩 downvote | | props.sender | 是 | string | 评论创建用户 | | props.senderFilter | 是 | string | 评论创建用户过滤关系 include:包含 exclude:不包含 equal:等于 unequal:不等于 prefix:前缀 | | props.minRating | 是 | number | 最低评分 | | props.maxRating | 是 | number | 最高评分 | | props.from | 是 | number | 开始时间戳 | | props.to | 是 | number | 结束时间戳 | | props.pageSize | 是 | number | 分页大小 | | props.pageNumber | 是 | number | 分页下标 | #### 返回值 | 属性名 | 类型 | 说明 | |---------------------------|----------|--------------------------------------------------| | feedbackList | object[] | 反馈查询结果 | | feedbackList[n].recordId | string | 对话记录 ID | | feedbackList[n].type | string | 用户反馈类型,点赞 upvote 点踩 downvote | | feedbackList[n].botId | string | Agent ID | | feedbackList[n].comment | string | 用户评论 | | feedbackList[n].rating | number | 用户评分 | | feedbackList[n].tags | string[] | 用户反馈的标签数组 | | feedbackList[n].input | string | 用户输入的问题 | | feedbackList[n].aiAnswer | string | Agent 的回答 | | total | number | 反馈总数 | ### AI.bot.getRecommendQuestions() 获取推荐的问题。 #### 使用示例 ```ts const res = await wx.cloud.extend.AI.bot.getRecommendQuestions({ data: { botId: "xxx-bot-id", msg: "你是谁" } }) for await (let x of res.textStream) { console.log(x) } ``` #### 类型声明 ```ts function getRecommendQuestions(props: { data: { botId: string; name: string; introduction: string; agentSetting: string; msg: string; history: Array; }, onText: OnText, onEvent: OnEvent, onFinish: OnFinish }); ``` #### 参数 | 参数名 | 必填 | 类型 | 说明 | | -------------------------- | ---- | ------ | ------------ | | props.data.botId | 是 | string | Agent id | | props.data.name | 是 | string | Agent 名称 | | props.data.introduction | 是 | string | Agent 简介 | | props.data.agentSetting | 是 | string | Agent 设定 | | props.data.msg | 是 | string | 用户发送信息 | | props.data.history | 是 | Array | 历史对话信息 | | `props.data.history[n].role` | 是 | string | 历史信息角色 | | `props.data.history[n].content` | 是 | string | 历史信息内容 | | props.onText | 否 | `(text: string) => unknown;` | 接收到新文本返回时触发的回调函数,参数为增量的文本 | | props.onEvent | 否 | `(prop: { data: string }) => unknown;` | 接收到新事件返回时触发的回调函数,参数为事件,prop.data 为此次事件包含的数据的字符串 | | props.onFinish | 否 | `(text: string) => unknown;` | 当本次调用完全结束时触发的回调函数,参数为本次调用返回的完整文本 | ### AI.bot.uploadFiles() 将云存储中的文件上传至 Agent,用于进行文档聊天。 #### 使用示例 ```ts await wx.cloud.extend.AI.bot.uploadFiles({ botId: 'bot-xx', fileList: [{ fileId: 'cloud://xxx.pdf', fileName: 'xxx.pdf', type: 'file' }] }) ``` #### 类型声明 ```ts function uploadFiles(props: { botId: string, fileList: Array }); ``` #### 参数 | 参数名 | 必填 | 类型 | 说明 | | -------- | ---- | ------ | ------------------------ | | props.botId | 是 | string | Agent id | | props.fileList | 是 | `Array` | 文件列表 | | props.fileList[n].fileId | 是 | string | 文件的云存储 cloud id | | props.fileList[n].fileName | 是 | string | 文件名 | | props.fileList[n].type | 是 | string | 暂时只支持 `"file"` | --- ## 微搭 AI+ 执行动作 import configModel from "./img/configModel.png" import actionPanel from "./img/actionPanel.png" import actionPanelAgent from "./img/actionPanelAgent.png" import newText from "./img/newText.png" import newTextAgent from "./img/newTextAgent.png" import configLLMChat from "./img/configLLMChat.png" import runApp from "./img/runApp.gif" import runAppAgent from "./img/runAppAgent.gif" import eventFlow from "./img/eventFlow.png" import addEventFlow from "./img/addEventFlow.png" import runAppWithEventFlow from "./img/runAppWithEventFlow.gif" import actionList from "./img/actionList.png" import configAgent from "./img/configAgent.png" import configBotSendMessage from "./img/configBotSendMessage.png" import initApp from "./img/initApp.png" import loadingVar from "./img/loadingVar.png" import buttonBindLoading from "./img/buttonBindLoading.png" import loadingTrue from "./img/loadingTrue.png" import loadingFalse from "./img/loadingFalse.png" import runLoadingApp from "./img/runLoadingApp.gif" import initActionConfig from "./img/initActionConfig.png" import toggleCode from "./img/toggleCode.png" import vision from "./img/vision.png" import runVisionApp from "./img/runVisionApp.gif" # 微搭 AI+ 执行动作 微搭中集成了具有 AI+ 能力的执行动作,帮助开发者快速搭建具有 AI+ 能力的低代码应用。我们提供了以下执行动作: - 调用大模型对话:调用大模型,进行对话,支持流式和非流式调用 - 调用 Agent 对话:调用 Agent 进行流式对话 支持一键将生成的文本赋值到变量中,并提供处理完整 SSE 事件的能力。 ## 使用示例 ### 调用大模型对话 本小节我们将演示如何使用「调用大模型对话」执行动作。 #### 配置大模型 首先,进入[云开发 AI+配置](https://tcb.cloud.tencent.com/dev#/ai?tab=ai-model)配置我们想用的大模型。这里我们选择配置混元(Open)。 #### 搭建页面 接下来,我们进入到可视化开发页面。 首先,我们在本页面中新建一个字符串变量 `text`,并新建一个文本组件,并将文本组件的内容设置为 `"大模型生成内容:" + $w.page.dataset.state.text`。我们会把大模型的输出结果保存到此变量中,从而可以在应用中显示出大模型的输出结果。 接着,在页面中添加一个按钮,点击右侧菜单中的点击事件,即可唤出执行动作面板。在此选择当此按钮被点击时会触发的执行动作。 点击「调用大模型对话」,进入执行动作的参数配置面板,这里是我们配置的参数: - 模型供应商:设置为 `hunyuan-open`,对应我们刚刚配置的大模型 - 模型:设置为 `hunyaun-lite` - 对话消息列表:添加一条消息,角色为 `user`,意为这是我们对大模型发送的消息 - 流式调用:选中「流式」,开启流式调用。后续调用大模型时,每当大模型有新的内容生成,我们就能够接收到响应。不需要等待整个文本处理完毕,可以边产生文本边得到结果。当然有需要的话也可关闭流式调用,这样我们能够一次性得到完整的大模型生成结果 - temperature 温度参数:这个参数用来控制大模型生成文本的多样性,建议参考具体使用的大模型文档详细了解后再按需使用,这里我们就先不设置此参数了 - top_p 核采样参数:同 temperature 温度参数,我们此处先不设置 - 文本赋值变量:此处我们选中刚刚新建的 `text` 变量,当我们获取到大模型的生成文本时,会将文本保存到此变量中。此前我们新建了绑定该变量的文本组件,因此预期效果是,当大模型生成文本时,会自动更新文本组件的内容 - SSE 回调事件流:当接收到 SSE 流式调用时,会触发此事件流。我们先不配置这个参数,后文将会详细介绍下这个参数的用法 配置完成后,点击保存。在页面中点击按钮,即可调用大模型,并看到大模型生成的文本在页面上被打印出来了。 #### 进阶:配置 SSE 回调事件流 还记得上一小节我们没有配置的「SSE 回调事件流」参数吗?在这一小节我们将详细介绍下这个参数该如何使用。 大模型和 Agent 的流式调用都是基于 SSE 实现的。当大模型生成了新的内容时,就会返回一个 SSE 事件。在 SSE 事件中,包含着这次生成的详细信息,包括生成内容、时间、ID 等等。有进阶需求的开发者们或许希望充分解析 SSE 事件中传递的信息,此时就能够配置「SSE 回调事件流」参数实现。 在左侧代码区新建一个 `print_SSE` 的事件流,设置为 Javascript 代码事件,并填入这段代码: ```js // 这段代码会打印出接收到的 SSE 事件。 ({event}) => { console.log(event.detail); } ``` 配置好后,再次打开「调用大模型对话」的参数配置面板,在「SSE 回调事件流」参数中,添加刚刚新建的 `print_SSE` 事件流。 点击保存,即可开始运行了。打开浏览器的开发者控制台,再次点击按钮,即可调用大模型,生成的文本显示在应用界面中,同时控制台也打印出了接收到的一系列 SSE 事件。 ### 调用 Agent 对话 本小节我们将演示如何使用「调用 Agent 对话」执行动作。 #### 配置 Agent 首先,进入[云开发 AI+配置](https://tcb.cloud.tencent.com/dev#/ai?tab=agent)配置我们想用的 Agent,点击复制 ID 按钮记录下来该 Agent 的 ID。 #### 搭建页面 接下来,我们进入到可视化开发页面。 首先,我们在本页面中新建一个字符串变量 `text`,并新建一个文本组件,并将文本组件的内容设置为 `"Agent 生成内容:" + $w.page.dataset.state.text`。我们会把 Agent 的输出结果保存到此变量中,从而可以在应用中显示出 Agent 的输出结果。 接着,在页面中添加一个按钮,点击右侧菜单中的点击事件,即可唤出执行动作面板。在此选择当此按钮被点击时会触发的执行动作。 点击「调用 Agent 对话」,进入执行动作的参数配置面板,这里是我们配置的参数: - Agent ID:填入刚刚在 AI+ 页面中配置好的 Agent ID - 消息内容:填入要发送给 Agent 的对话内容 - 历史对话记录:如果有添加上下文的需求,可以在此填入你和 Agent 的历史对话列表 - 文本赋值变量:此处我们选中刚刚新建的 `text` 变量,当我们获取到 Agent 的生成文本时,会将文本保存到此变量中。此前我们新建了绑定该变量的文本组件,因此预期效果是,当 Agent 生成文本时,会自动更新文本组件的内容 - SSE 回调事件流:当接收到 SSE 流式调用时,会触发此事件流。可以参考调用大模型对话中的使用示例进行使用 配置完成后,点击保存。在页面中点击按钮,即可调用 Agent,并看到 Agent 生成的文本在页面上被打印出来了。 ## 最佳实践 ### 在应用中体现「加载中」的状态 调用大模型、Agent 对话时,需要耗费一定时间才能看到响应。为了让用户感知到应用正在等待调用完成、防止多次调用造成赋值混乱等现象,我们可以在应用中体现出「加载中」的状态。 首先,按照[调用大模型对话使用示例](#调用大模型对话),搭建出一个能够调用大模型的应用。预期中,此时页面上会有: - 一个文本组件 - 一个按钮组件 - 一个 `text` 文本变量 其中,按钮组件绑定了调用大模型的动作;文本组件的值被绑定为 `"大模型生成内容:" + $w.page.dataset.state.text`。当点击按钮时,会调用大模型,页面中出现大模型生成内容。 接下来,新建一个 `loading` 变量,类型为布尔值,默认值设置为 `false`,这个值会用来表示我们的「加载中」状态。 随后,我们配置下按钮组件,在右方的高级属性栏下,可以找到「加载中」和「禁用」的属性,点击切换为表达式,绑定上我们刚刚新建的 `loading` 变量。 最后,只要分别在调用大模型前后给 `loading` 变量赋上不同的值就可以了。 先在调用大模型之前给 `loading` 变量赋上 `true` 的值。由于调用大模型是在点击后触发的动作,因此只要在点击事件上加上赋值变量的动作即可: 接着,在调用大模型成功时,再加上赋值变量的动作即可。在这里,我们给 `loading` 变量赋上 `false` 的值: 运行代码,即可看到在调用大模型时,按钮状态为加载中,且不可用。这样一来既让用户感知到了请求状态,也防止用户多次点击重复触发了。在大模型调用结束后,按钮状态也随之恢复正常,可以再次点击了。 ### 调用混元图生文能力 混元大模型具备图生文能力,在微搭「调用大模型」的执行动作中,也可以传入图片相关的参数,让大模型读取图片。 首先,按照[调用大模型对话使用示例](#调用大模型对话),搭建出一个能够调用大模型的应用。预期中,此时页面上会有: - 一个文本组件 - 一个按钮组件 - 一个 `text` 文本变量 其中,按钮组件绑定了调用大模型的动作;文本组件的值被绑定为 `"大模型生成内容:" + $w.page.dataset.state.text`。当点击按钮时,会调用大模型,页面中出现大模型生成内容。 接着,让我们修改下「调用大模型」动作的配置。这是我们修改前的动作配置: 可以看到,表单中并没有地方输入图片内容。点击「对话消息列表」表单右边的 `fx` 图标,会看见对应的表单变成了代码表达式。这是因为微搭提供了可视化的表单替代代码表达式。用户在操作表单时,实际上会改变对应的代码表达式。此时我们为了利用大模型的图生文能力,需要在此处直接填写代码表达式。 如图所示,我们这里的代码表达式为: ```js [ { "role": "user", "content": "你好" } ] ``` 这表示了发给大模型的对话消息列表,其中只有一条用户消息,内容为「你好」。 调用图生文时,代码格式要发生一些变化,上面的代码要写成: ```js [ { "role": "user", "content": [ { "type": "text", "text": "这个图片内容是什么?" } ] } ] ``` 可以看到,本来写在 `content` 字段中的字符串「你好」,现在变成了一个数组,其中包含一个对象元素,它有两个字段: - `type` 中填的是 `"text"`,表示这个元素是个文本类型的消息 - `text` 中填的是 `"这个图片内容是什么?"`,就是这个消息的文本内容了 以上就是调用图生文时传入文本消息的方法。接下来我们再传入图片消息。我们在 `content` 字段的数组中追加一个表示图片消息的对象元素: ```js [ { "role": "user", "content": [ { "type": "text", "text": "这个图片内容是什么?" }, { "type": "image_url", "image_url": { "url": "https://cloudcache.tencent-cloud.com/qcloud/ui/portal-set/build/About/images/bg-product-series_87d.png" } } ] } ] ``` 这个对象元素也有两个字段: - `type` 中填的是 `"image_url"`,表示这个元素是个图片的链接 - `image_url` 中填的是一个带 `url` 字段的对象,就是这个消息对应的图片链接了 至此,大功告成,按照这样的格式就可以传入图片,调用大模型的图生文能力了。 最后,只需要选择具有图生文能力的模型即可,这里我们选择 `hunyuan-vision`。 运行下代码,即可看到大模型对我们传入图片的解读了! --- ## 常见问题 # 常见问题 ## 对接相关 ### 为何选择不到腾讯云的相关资源 目前仅支持上海地域的资源选择,需要在环境所在的腾讯云账号下,有上海地域的 CLB 负载均衡、CVM 云主机、Lighthouse 轻量主机,才可以通过 AnyService 对接。 ## 计费相关 #### AnyService 是如何计费的? 通过 AnyService 发生的调用,除调用本身受到环境维度整体的 QPS 限制外,没有其他计量计费的地方,调用不记录调用次数或流量;如果服务是通过公网回源,在请求从 AnyService 服务到源站时,会有出流量相关计量,统计到云开发环境的整体流量中。 AnyService 能力目前在云开发入门版及以上、微搭团队版及以上可用。 在有进一步的通知前,针对已付费的云开发个人版,我们提供了限时免费试用,在此期间可以使用 AnyService 能力。 如果界面上有相关套餐不符、无法使用的提示,可以进行环境的套餐变更或升级,以满足如上条件的套餐情况;或进一步通过工单联系我们,以获取详细情况或操作指导。 --- ## 概述 # 概述 ## 什么是 AnyService AnyService 是腾讯云开发(CloudBase)提供的服务接入解决方案,帮助开发者将已有的服务器资源快速接入**小程序**或**微信 H5**,无需迁移原有服务即可享受云开发的便捷性和安全性。 ![AnyService 架构图](https://qcloudimg.tencent-cloud.cn/raw/e9b41713a892cfda2b4f7fe62d14cee6.png) ## 核心特性 ### 🌐 无需域名备案 通过 AnyService 接入的服务仅需 IP 地址即可,无需配套域名。小程序调用时也无需配置域名白名单,显著简化了传统后端服务的部署流程。 ### 🔒 SSL/TLS 安全加密 请求默认通过证书加密传输,防止数据泄露,确保数据安全。 ### 🤖 AI 协议支持 除 HTTP/HTTPS 外,还支持 AI 开发中常用的 SSE(Server-Sent Events)协议和 WebSocket 长连接协议,适用于实时通信、大模型推理等场景。 ### ⚡ 快速接入与统一管理 通过云开发控制台或 CLI 工具简单配置 IP/域名即可完成服务接入,并通过微信内置 SDK 或云开发 JSSDK 即可快速、统一调用。 ### 🔗 多种接入源支持 支持多种服务接入源,满足不同场景下的业务需求: | 接入源类型 | 说明 | | --- | --- | | [公网访问源站接入](./quickstart.md) | 可接入任何具有公网 IP 的服务器 | | [腾讯云Lighthouse轻量主机接入](./quickstart-lh.md) | 支持腾讯云轻量应用服务器 | | 腾讯云 CVM | 支持腾讯云云服务器实例 | | 腾讯云 CLB 负载均衡 | 支持腾讯云负载均衡服务 | ## 典型使用场景 ### 存量计算资源复用 已有服务器、容器集群或 API 服务无需迁移,直接通过 AnyService 接入云开发,避免资源浪费。 **示例**:企业可将已有微服务接口快速整合到小程序生态中。 ### 无域名后端开发 传统开发需额外申请域名并进行备案流程,而 AnyService 允许直接通过 IP 地址提供服务,尤其适合内部测试或快速上线阶段。 ### 存量服务快速接入 已有开发完成的服务,期望在小程序中继续使用的情况下,可以将已有服务直接接入,避免重复开发。 ### AI 服务集成 支持 SSE 和 WebSocket 协议的特性,使其适用于大模型交互、实时数据推送等 AI 场景。 **示例**:结合后端接口,实现流式响应,提升用户体验。 ## 对比传统主机模式 | 对比项 | 云开发 AnyService | 传统主机模式 | | --- | --- | --- | | 域名与备案 | ✅ 支持 IP 直连,无需域名 | ❌ 需申请域名、备案 + 配置 SSL 证书(约 7 天) | | 安全防护 | ✅ 默认加密 + 安全防护 | ❌ 需自购 WAF、防火墙(≥2 人天、>3000 元/月) | | 接入成本 | ✅ 低成本快速接入 | ❌ 需额外购买安全组件 | | 维护复杂度 | ✅ 统一管理,简化运维 | ❌ 需独立维护多个组件 | ## 快速接入指南 参考如下文档,快速接入 AnyService 服务 [公网访问源站接入](./quickstart.md) [腾讯云Lighthouse轻量主机接入](./quickstart-lh.md) --- ## 腾讯云Lighthouse轻量主机接入 # 腾讯云Lighthouse轻量主机接入 ## 前置条件 * 已创建并配置好 **上海地区** 的轻量主机服务 * 在主机内 **启动服务** 且在 **特定端口监听** 满足以上条件的轻量主机,则可以通过 AnyService 服务进行对接,并在后续可通过 **小程序** 请求到主机内运行的服务。 **举例说明** 这里选择 nodejs 的应用模版进行举例,您可以选择 **任意方式** 创建轻量主机服务 1. 通过轻量主机的创建面板,选择带有 **Nodejs** 的应用模板并选择 **上海地域** 创建 2. 在创建完成后,通过防火墙**放通主机的 80 端口** ![alt](https://qcloudimg.tencent-cloud.cn/raw/766ce03cd9e26172142646e2956bf1d9.png) 3. 通过 curl 操作,或浏览器访问主机 ip,确保可访问到主机内的服务: ```bash curl http://xxx.xxx.xx.xxx Hello World% ``` ## 创建服务 1. 进入[云开发/AnyService](https://tcb.cloud.tencent.com/dev?#/any-service) 2. 点击「**新建服务接入**」。并根据表单要求填写相关信息: * **服务名称**:对接轻量主机 * **服务标识**:lh * **源站类型**:腾讯云Lighthouse轻量主机 * **源站连接信息**:选择在前置条件中创建好的轻量主机;端口配置为 80 填写完成后确认保存,完成接入服务创建。 ![](https://qcloudimg.tencent-cloud.cn/raw/778498e417da90b22fe3403f42e20e53.png) ## 小程序端请求验证 小程序 **wx.cloud.init** 初始化中的 env 参数需要和创建 anyService服务的环境一致 在小程序端中增加如下代码: ```js // 在调用前,或在小程序 onLaunch 中初始化环境 wx.cloud.init({ env: 'test-xxxxx', traceUser: true, }) const result = await wx.cloud.callContainer({ "path": "/", "header": { "X-WX-SERVICE": "tcbanyservice", // 固定为 tcbanyservice "X-AnyService-Name": "lh", // X-AnyService-Name 中填入 AnyService 服务标识,从「腾讯云开发平台 - AnyService」获取服务标识 "content-type": "application/json", }, "method": "GET", }) console.log(result); ``` 示例运行结果将能获取并输出相同的 "Hello World" 内容 ![alt](./quickstart-coderun-lh.png) --- ## 公网访问源站接入 # 公网访问源站接入 这里使用 [https://postman-echo.com](https://postman-echo.com) 这个服务作为示例 ## 创建服务 1. 进入[云开发/AnyService](https://tcb.cloud.tencent.com/dev?#/any-service) 2. 点击「**新建服务接入**」。并根据表单要求填写相关信息: * **服务名称**:postman-echo * **服务标识**:postman-echo * **源站类型**:通过公网访问源站 * **源站协议**:https * **源站连接信息**:postman-echo.com 填写完成后确认保存,完成接入服务创建。 ![](https://qcloudimg.tencent-cloud.cn/raw/173dea52f5960b12cd661eb34e1a5808.png) ## 小程序端请求验证 小程序 **wx.cloud.init** 初始化中的 env 参数需要和创建 anyService服务的环境一致 在小程序端中增加如下代码: ```js // 在调用前,或在小程序 onLaunch 中初始化环境 wx.cloud.init({ env: 'test-xxxxx', traceUser: true, }) const result = await wx.cloud.callContainer({ "path": "/post", "header": { "X-WX-SERVICE": "tcbanyservice", // 固定为 tcbanyservice "X-AnyService-Name": "postman-echo", // X-AnyService-Name 中填入 AnyService 服务标识,从「腾讯云开发平台 - AnyService」获取服务标识 "content-type": "application/json", }, "method": "POST", "data": { "a": 1, "b": 2 } }) console.log(result); // ``` 示例运行结果如下: ![alt](./quickstart-coderun.png) --- ## 使用指南 # 使用指南 ## 服务管理 ### 创建服务 通过 AnyService 控制台创建服务,需要配置以下基本信息: #### 基本配置 | 配置项 | 说明 | 要求 | | --- | --- | --- | | 服务名称 | 服务的显示名称 | 便于识别和管理 | | 服务标识 | 服务的唯一标识符 | 仅支持英文、数字、下划线,环境内唯一 | | 备注 | 服务描述信息 | 可选,用于记录服务用途 | | 源站类型 | 后端服务的接入方式 | 公网访问源站 或 腾讯云资源 | #### 公网访问源站配置 当选择通过公网访问源站时,需要配置: | 配置项 | 说明 | 示例 | | --- | --- | --- | | 源站协议 | HTTP 或 HTTPS | 默认端口:HTTP(80)、HTTPS(443) | | 源站连接信息 | IP 地址或域名 | `139.186.239.126` 或 `tcb.tencentcloudapi.com:8080` | ![alt](./create-outsource.png) #### 腾讯云资源配置 当选择对接腾讯云资源时,需要配置: | 配置项 | 说明 | 支持范围 | | --- | --- | --- | | 对应资源 | 选择具体的云资源实例 | 上海区的 CVM、CLB、Lighthouse | | 端口 | 服务监听端口 | 1-65535 | ![alt](https://qcloudimg.tencent-cloud.cn/raw/fa8f2e55594d2d8d1489f9576f8d9f07.png) #### 安全配置(可选) | 配置项 | 说明 | 注意事项 | | --- | --- | --- | | 源站访问凭证 | Basic Auth 认证信息 | 遵循 [Authorization Basic](https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Reference/Headers/Authorization#basic) 规范 | **工作原理**:配置后,每次请求会在 Header 中添加 `x-anyservice-authorization` 字段,源站可用于身份验证或请求来源识别。 > ⚠️ **安全提示**:使用 HTTP 协议时,访问凭证将以明文传输,建议生产环境使用 HTTPS。 ### 管理服务 在服务列表中可以查看和管理已创建的服务: | 操作 | 说明 | 注意事项 | | --- | --- | --- | | 查看详情 | 查看服务的配置信息和运行状态 | - | | 编辑服务 | 修改除标识外的所有配置 | 服务标识不可修改 | | 删除服务 | 彻底删除服务及其配置 | 删除前请确保无代码依赖 | > ⚠️ **重要提示**:服务的修改和删除操作可能影响正在使用该服务的应用,请在操作前谨慎评估影响范围。 ## 服务调用 ### 在小程序中调用 #### 1. 初始化云开发环境 在小程序加载阶段调用一次初始化,全局执行一次即可: ```javascript // app.js - 全局初始化 App({ async onLaunch() { // 初始化云开发环境 wx.cloud.init({ env: "your-env-id" // 替换为您的环境 ID }) } }) ``` #### 2. 调用 AnyService 服务 使用 `wx.cloud.callContainer` 方法调用 AnyService 服务: ```javascript // 调用示例 const callAnyService = async () => { try { const res = await wx.cloud.callContainer({ path: '/api/users', // 后端 API 路径 method: 'POST', // HTTP 方法 header: { "X-WX-SERVICE": "tcbanyservice", // 固定值 "X-AnyService-Name": "my-service", // 您的服务标识 "Content-Type": "application/json" }, data: { name: '张三', email: 'zhangsan@example.com' } // dataType: 'text' // 可选:不要 SDK 自动解析 JSON 时使用 }) console.log('调用成功:', res.data) return res.data } catch (error) { console.error('调用失败:', error) throw error } } ``` #### 关键参数说明 | 参数 | 值 | 说明 | | --- | --- | --- | | `X-WX-SERVICE` | `tcbanyservice` | 固定值,标识调用 AnyService | | `X-AnyService-Name` | 您的服务标识 | 创建服务时设置的标识符 | | `path` | `/api/path` | 后端 API 路径,从根目录开始 | | `method` | `GET/POST/PUT/DELETE` | HTTP 请求方法 | | `dataType` | `json`(默认)/`text` | 响应数据解析方式 | #### 错误处理与最佳实践 **常见错误处理** ```javascript const callAnyService = async (path, data = {}) => { try { const res = await wx.cloud.callContainer({ path, method: 'POST', header: { "X-WX-SERVICE": "tcbanyservice", "X-AnyService-Name": "my-service", "Content-Type": "application/json" }, data, timeout: 10000 // 设置超时时间 }) return res.data } catch (error) { // 处理不同类型的错误 if (error.errCode === -1) { console.error('网络请求失败:', error.errMsg) wx.showToast({ title: '网络连接失败', icon: 'none' }) } else if (error.errCode === 40001) { console.error('服务未找到:', error.errMsg) wx.showToast({ title: '服务暂不可用', icon: 'none' }) } else { console.error('调用失败:', error) wx.showToast({ title: '请求失败,请重试', icon: 'none' }) } throw error } } ``` **最佳实践建议** 1. **请求封装**:建议将 AnyService 调用封装成通用函数 2. **错误处理**:为不同错误类型提供相应的用户提示 3. **超时设置**:为网络请求设置合理的超时时间 4. **状态管理**:在调用过程中显示加载状态 5. **重试机制**:对于临时性错误可以实现重试逻辑 > 📝 **提示**:其他参数均与 [wx.request](https://developers.weixin.qq.com/miniprogram/dev/api/network/request/wx.request.html) 保持一致。 ## 请求与响应数据 ### 请求 Header 通过 SDK 调用服务时,系统会自动在 HTTP Header 中携带小程序相关信息,后端可以通过解析这些 Header 获取用户和环境信息: | Header 字段 | 含义 | 说明 | | --- | --- | --- | | `X-WX-OPENID` | 小程序用户 openid | 用户唯一标识 | | `X-WX-APPID` | 小程序 AppID | 小程序应用标识 | | `X-WX-UNIONID` | 小程序用户 unionid | 跨应用用户标识(需满足获取条件) | | `X-WX-FROM-OPENID` | 资源复用场景下的用户 openid | 资源复用时的原始用户标识 | | `X-WX-FROM-APPID` | 资源复用场景下的小程序 AppID | 资源复用时的原始应用标识 | | `X-WX-FROM-UNIONID` | 资源复用场景下的用户 unionid | 资源复用时的原始用户跨应用标识 | | `X-WX-ENV` | 云环境 ID | 当前调用所在的云开发环境 | | `X-WX-SOURCE` | 调用来源 | 触发本次调用的来源类型 | | `X-WX-PLATFORM` | 调用平台 | 发起调用的平台信息 | | `X-Forwarded-For` | 客户端 IP 地址 | 支持 IPv4 和 IPv6 | | `X-AnyService-Name` | AnyService 服务标识 | 当前调用的服务标识符 | ### 响应 Header AnyService 会在响应中添加以下 Header 字段,用于调试和监控: | Header 字段 | 含义 | 说明 | | --- | --- | --- | | `X-Cloudbase-Request-Id` | 云开发请求 ID | 用于问题追踪和日志查询 | | `X-Cloudbase-Upstream-Status-Code` | 源站响应状态码 | 后端服务实际返回的 HTTP 状态码 | | `X-Cloudbase-Upstream-Timecost` | 源站响应耗时 | 后端服务处理请求的时间(毫秒) | | `X-Cloudbase-Upstream-Type` | 源站服务类型 | 后端服务的类型标识 | --- ## HTTP 访问服务 # HTTP 访问服务 HTTP 访问服务让开发者可以通过 HTTP 访问到自己的云开发资源。 从 3.4.0+ 版本,新增了 `access` 服务接口,你可以使用新增的接口,原 SDK 可以更换到新接口,或者继续使用[旧的接口](/api-reference/manager/node/httpservice)。 :::tip 以下所有接口添加于 3.4.0+ 版本 ::: ## 创建 HTTP 访问服务 ### 1. 接口描述 接口功能:创建 HTTP 访问服务。 接口声明:`async createAccess(options: ICreateAccessOptions): Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ---- | ---- | ------- | ----------------------------------------------- | | path | 是 | String | 访问路径,必须以 / 开头 | | name | 是 | String | 绑定的服务名称 | | type | 是 | Number | 绑定的服务类型,云函数:1,Serverless 云应用:2 | | auth | 否 | Boolean | 是否开启 HTTP 访问服务对应的路径的鉴权 | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | ------------------ | | RequestId | 是 | String | 请求唯一标识 | | APIId | 是 | String | HTTP 访问服务的 Id | ### 4. 示例代码 ```javascript import CloudBase from "@cloudbase/manager-node"; const app = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId" // 云开发环境ID,可在腾讯云云开发控制台获取 }); async function test() { const res = await app.access.createAccess({ path: "/sum", type: 1, name: "sum" }); const { APIId } = res; console.log(APIId); } test(); ``` ## 获取 HTTP 访问服务 ### 1. 接口描述 接口功能:获取 HTTP 访问服务 接口声明:`async getAccessList(options: IGetOptions): Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ------ | ---- | ------ | ----------------------- | | path | 否 | String | 访问路径,必须以 / 开头 | | name | 否 | String | 绑定的服务名称 | | offset | 否 | Number | 查询 List 的偏移量 | | limit | 否 | Number | 每次查询返回的数据条数 | ### 3. 返回结果 | 字段 | 类型 | 说明 | | ------------- | --------------------------- | ------------------------ | | RequestId | String | 请求唯一标识 | | APISet | `Array` | HTTP 访问服务列表 | | Total | Number | HTTP 访问服务服务的总量 | | EnableService | Boolean | 是否开启了 HTTP 访问服务 | **CloudBaseGWAPI** | 字段 | 类型 | 说明 | | ---------- | ------- | ----------------------------------- | | APIId | String | APIId | | Path | String | 自定义路径 | | Type | Number | service type ,云函数默认为 1 | | Name | String | 云函数名 | | CreateTime | Number | service 创建时间 | | EnvId | String | 环境 ID | | EnableAuth | Boolean | HTTP 访问服务对应的路径是否开启鉴权 | ### 4. 示例代码 ```javascript import CloudBase from "@cloudbase/manager-node"; const manager = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId" // 云开发环境ID,可在腾讯云云开发控制台获取 }); async function test() { const res = await app.access.getAccessList(); console.log(res); } test(); ``` ## 删除 HTTP 访问服务 ### 1. 接口描述 接口功能:删除绑定的 HTTP 访问服务 接口声明:`async deleteAccess(options: IDeleteOptions): Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ----- | ---- | ------ | ----------------------------------------------- | | name | 否 | String | 绑定的服务名称 | | type | 否 | String | 绑定的服务类型,云函数:1,Serverless 云应用:2 | | apiId | 否 | String | HTTP 访问服务的 Id | | path | 否 | String | HTTP 访问服务的访问路径 | `deleteAccess` 接口支持三种删除条件: - 根据绑定的服务名删除,即使用 `name` 和 `type` 选项,将会删除此服务绑定的所有访问路径 - 根据服务 Id 删除,即 `apiId` 选项 - 根据访问路径,即 `path` 选项 ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | ------------ | | RequestId | 是 | String | 请求唯一标识 | ### 4. 示例代码 ```javascript import CloudBase from "@cloudbase/manager-node"; const manager = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId" // 云开发环境ID,可在腾讯云云开发控制台获取 }); async function test() { const res = await app.access.deleteAccess({ name: "sum" }); } test(); ``` ## 切换 HTTP 访问服务鉴权 ### 1. 接口描述 接口功能:切换 HTTP 访问服务鉴权,全局生效 接口声明:`async switchAuth(auth: boolean): Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ---- | ---- | ------- | ----------------------------------------------------- | | auth | 是 | Boolean | 是否开启 HTTP 访问服务鉴权,`true` 开通,`false` 关闭 | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | ------------ | | RequestId | 是 | String | 请求唯一标识 | ### 4. 示例代码 ```javascript import CloudBase from "@cloudbase/manager-node"; const manager = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId" // 云开发环境ID,可在腾讯云云开发控制台获取 }); async function test() { const res = await app.access.switchAuth(false); console.log("切换鉴权", res); } test(); ``` ## 切换 HTTP 访问服务路径鉴权 ### 1. 接口描述 接口功能:切换 HTTP 访问服务路径鉴权,只针对单个路径生效 接口声明:`async switchPathAuth(options: IUpdateOptions)` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ------ | ---- | --------------- | ------------------------------------------- | | apiIds | 是 | `Array` | HTTP 访问服务 Id 列表 | | auth | 是 | Boolean | 是否开通服务鉴权,`true` 开通,`false` 关闭 | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | ------------ | | RequestId | 是 | String | 请求唯一标识 | ### 4. 示例代码 ```javascript import CloudBase from "@cloudbase/manager-node"; const manager = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId" // 云开发环境ID,可在腾讯云云开发控制台获取 }); async function test() { const res = await app.access.switchPathAuth({ apiIds: ["xxxxx"], auth: false }); } test(); ``` ## HTTP 访问服务添加自定义域名 ### 1. 接口描述 接口功能:添加自定义域名 接口声明:`async addCustomDomain(options: IDomainOptions): Promise` > 绑定自定义域名时,请务必在您的自定义域名厂商处 配置 CNAME 域名解析 ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ------ | ---- | ------ | -------------------------------------------- | | domain | 是 | String | 自定义域名 | | certId | 否 | String | 腾讯云 SSL 证书 Id,SSL 证书需要在调用账户下 | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | ------------ | | RequestId | 是 | String | 请求唯一标识 | ### 4. 示例代码 ```javascript import CloudBase from "@cloudbase/manager-node"; const manager = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId" // 云开发环境ID,可在腾讯云云开发控制台获取 }); async function test() { const res = await app.access.addCustomDomain({ domain: "xxx", certId: "xxx" }); } test(); ``` ## 获取 HTTP 访问服务自定义域名列表 ### 1. 接口描述 接口功能:获取自定义域名列表 接口声明:`async getDomainList(): Promise` ### 2. 输入参数 无 ### 3. 返回结果 | 字段 | 类型 | 说明 | | ------------- | ----------------- | ------------------------ | | RequestId | String | 请求唯一标识 | | DefaultDomain | String | HTTP 访问服务默认域名 | | EnableService | Boolean | 是否开启了 HTTP 访问服务 | | ServiceSet | `Array` | HTTP 访问服务域名列表 | #### IService | 字段 | 类型 | 说明 | | -------- | ------ | ------------------------------------------ | | Domain | String | 域名 | | OpenTime | Number | 开启时间 | | Status | Number | 绑定状态,1 绑定中;2 绑定失败;3 绑定成功 | ### 4. 示例代码 ```javascript import CloudBase from "@cloudbase/manager-node"; const manager = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId" // 云开发环境ID,可在腾讯云云开发控制台获取 }); async function test() { const res = await app.access.getDomainList(); } test(); ``` ## HTTP 访问服务删除自定义域名 ### 1. 接口描述 接口功能:删除自定义域名 接口声明:`async deleteCustomDomain(domain: string): Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ------ | ---- | ------ | ---------- | | domain | 是 | String | 自定义域名 | ### 3. 返回结果 | 字段 | 类型 | 说明 | | --------- | ------ | ------------ | | RequestId | String | 请求唯一标识 | ### 4. 示例代码 ```javascript import CloudBase from "@cloudbase/manager-node"; const manager = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId" // 云开发环境ID,可在腾讯云云开发控制台获取 }); async function test() { const res = await app.access.deleteCustomDomain("xxxx"); } test(); ``` --- ## 更新日志 # 更新日志 # v3.7.0 - 新增[创建新用户接口](/api-reference/manager/node/user#chuang-jian-xin-yong-hu) - 新增[修改用户信息接口](/api-reference/manager/node/user.md#xiu-gai-yong-hu-xin-xi) # v3.6.0 - 新增云应用调整服务版本流量接口 # v3.5.0 - 新增获取云开发用户列表接口 - 新增停用云开发用户接口 - 新增批量删除云开发用户接口 # v3.4.0 - 增加云接入服务 - 创建函数支持同时创建云接入 - 优化请求错误栈 # v3.3.2 - 函数轮询状态时间修复 30s => 300s # v3.3.0 - 静态托管支持配置重定向规则 - 新增删除静态托管自定义域名接口 - 新增获取静态网站配置接口 - 新增获取域名配置接口 - 新增域名配置接口 # v3.2.0 - 新增静态托管查询文件,配置文档,绑定自定义域名接口 # v3.1.1 - 优化文件夹删除接口 - 增加批量上传文件接口 - 修复静态网站上传单个文件没有回调的问题 # v3.1.0 - 优化文件上传操作 - 增加静态网站操作接口 - 移除获取函数详情字段限制,返回更多信息 # v3.0.0 - [breakchange] common 接口改造 - 支持数据库 CRUD # v2.4.1 - [fix] 修复并行调用 createFunction 接口报错的问题 - [add] 支持通过指定函数路径创建函数 # v2.4.0 - [add] 新增安全来源 API - [fix] 修复云函数环境下取环境变量 bug (入口函数外部调用,未取到报错) # v2.3.4 - [fix] 修复函数配置更新问题 # v2.3.2 - [fix] 修复更新函数 VPC 配置导致无法访问公网的问题 # v2.3.1 - [fix] 修复创建函数、更新函数代码,代码保护参数遗漏的问题 # v2.3.0 - [add] 支持文件层 - [add] 支持查询修改存储安全规则异步任务状态 - [fix] 文档订正 # v2.2.1 - [fix] 修复查询所有集合信息接口,集合为空时报错 - [fix] updateFunctionCode 支持自动安装依赖 # v2.2.0 - [fix] 修复上传文件夹等接口 `onFileFinish` 参数 TS 定义错误 - [add] 创建云函数返回 RequestId 响应值 - [add] 支持 L5 选项 # v2.1.0 - [add] 支持上传或更新函数时 等待依赖安装完成 - [add] 支持增量上传函数代码 - [add] 新增创建自定义登录私钥 - [add] 新增 HTTP Service API - [add] 新增安全规则 API # v2.0.0 - [refactor] 重构 storage , function 接口(breaking change) - [add] 支持闭环完成环境创建 - [add] 支持函数操作代码保护 - [fix] 修复 windows 下上传文件路径 bug # v1.3.0 - [add] 支持获取云函数代码下载链接 # v1.2.0 - [deprecated] env 创建环境功能暂时停用 - [add] 支持创建云函数自动安装依赖 --- ## 云应用 # 云应用 Serverless 云应用(Serverless Cloud App)是云开发提供的一种无服务器容器服务,用户可面向代码/镜像等多种方式使用。无需维护复杂的容器环境,可专注于自身的业务,一键开通后即可享受能自动扩缩容的容器资源。 在 Serverless 云应用中,用户同时可享受云开发提供的其他相应开发能力与 SDK ,以及云开发自带的默认域名用于服务端业务访问。 :::tip 以下所有接口添加于 3.6.0+ 版本 ::: ## 调整服务版本流量配置 ### 1. 接口描述 接口功能:调整服务版本流量配置。 接口声明:`async modifyServerFlow(options: IModifyServerFlowOption)` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ---------------- | ---- | -------------------------------------------------------------------------- | -------- | | serverName | 是 | String | 服务名称 | | versionFlowItems | 否 | `Array` | 流量占比 | #### ICloudBaseRunVersionFlowItem | 字段 | 必填 | 类型 | 说明 | | ----------- | ---- | ------ | -------- | | versionName | 是 | String | 版本名称 | | flowRatio | 是 | Number | 流量占比 | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | ----------------------- | | RequestId | 是 | String | 请求唯一标识 | | Result | 是 | String | 返回结果,succ 代表成功 | ### 4. 示例代码 ```javascript import CloudBase from "@cloudbase/manager-node"; const app = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId" // 云开发环境ID,可在腾讯云云开发控制台获取 }); async function test() { const res = await app.cloudApp.modifyServerFlow({ serverName: "test", versionFlowItems: [ { versionName: "test-001", flowRatio: 30 }, { versionName: "test-002", flowRatio: 70 } ] }); const { Result } = res; console.log(Result === "succ"); } test(); ``` --- ## 云托管 # 云托管 ## init ### 1. 接口描述 接口功能:初始化云托管代码项目 接口声明:`init(params: { serverName: string; template?: string; targetPath?: string }): Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ---------- | ---- | ------ | ------------------------------ | | serverName | 是 | String | 服务名称,将作为项目目录名 | | template | 否 | String | 模板标识符,默认为'helloworld' | | targetPath | 否 | String | 目标路径,默认为当前目录 | ### 3. 返回结果 | 字段 | 类型 | 说明 | | ---------- | ------ | ------------------ | | projectDir | String | 初始化后的项目目录 | ### 4. 示例代码 ```javascript import CloudBase from "@cloudbase/manager-node"; const manager = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId", }); async function test() { const { projectDir } = await manager.cloudrun.init({ serverName: "my-server", template: "helloworld", targetPath: "./projects", }); console.log("项目已初始化到:", projectDir); } test(); ``` ## download ### 1. 接口描述 接口功能:下载云托管服务代码到本地目录 接口声明:`download(params: { serverName: string; targetPath: string }): Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ---------- | ---- | ------ | ------------------------------ | | serverName | 是 | String | 要下载的服务名称 | | targetPath | 是 | String | 下载的目标路径(绝对或相对路径) | ### 3. 返回结果 无直接返回数据,成功时 Promise 解析,失败时拒绝。 ### 4. 示例代码 ```javascript import CloudBase from "@cloudbase/manager-node"; const manager = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId", }); async function test() { await manager.cloudrun.download({ serverName: "my-server", targetPath: "./downloads", }); console.log("代码下载完成"); } test(); ``` ## list ### 1. 接口描述 接口功能:获取云托管服务列表 接口声明:`list(params?: { pageSize?: number; pageNum?: number; serverName?: string; serverType?: CloudrunServerType }): Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ---------- | ---- | ------------------ | -------------------------------- | | pageSize | 否 | Number | 每页数量,默认 10 | | pageNum | 否 | Number | 页码,默认 1 | | serverName | 否 | String | 服务名称筛选 | | serverType | 否 | CloudrunServerType | 服务类型筛选(function/container) | ### 3. 返回结果 | 字段 | 类型 | 说明 | | ------------------------------ | ------------------------- | ----------------------------------------- | | ServerList | ICloudrunServerBaseInfo[] | 服务列表数组 | | ServerList[].ServerName | String | 服务名称 | | ServerList[].DefaultDomainName | String | 默认服务域名 | | ServerList[].CustomDomainName | String | 自定义域名 | | ServerList[].Status | String | 服务状态(running/deploying/deploy_failed) | | ServerList[].UpdateTime | String | 更新时间 | | ServerList[].AccessTypes | String[] | 公网访问类型数组 | | ServerList[].CustomDomainNames | String[] | 自定义域名数组 | | ServerList[].ServerType | String | 服务类型(function/container) | | ServerList[].TrafficType | String | 流量类型 | | Total | Number | 服务总数 | | RequestId | String | 请求 ID | ### 4. 示例代码 ```javascript import CloudBase from "@cloudbase/manager-node"; const manager = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId", }); async function test() { const { ServerList, Total } = await manager.cloudrun.list({ pageSize: 20, pageNum: 1, }); console.log(`共 ${Total} 个服务:`, ServerList); } test(); ``` ## detail ### 1. 接口描述 接口功能:查询云托管服务详情 接口声明:`detail(params: { serverName: string }): Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ---------- | ---- | ------ | ---------------- | | serverName | 是 | String | 要查询的服务名称 | ### 3. 返回结果 | 字段 | 类型 | 说明 | | -------------------------------------------- | ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | | BaseInfo | ICloudrunServerBaseInfo | 服务基本信息 | | BaseInfo.ServerName | String | 服务名称 | | BaseInfo.DefaultDomainName | String | 默认服务域名 | | BaseInfo.CustomDomainName | String | 自定义域名 | | BaseInfo.Status | String | 服务状态 | | BaseInfo.UpdateTime | String | 更新时间 | | BaseInfo.AccessTypes | String[] | 公网访问类型 | | BaseInfo.CustomDomainNames | String[] | 自定义域名数组 | | BaseInfo.ServerType | String | 服务类型 | | BaseInfo.TrafficType | String | 流量类型 | | ServerConfig | ICloudrunServerBaseConfig | 服务配置信息 | | ServerConfig.EnvId | String | 环境 ID | | ServerConfig.ServerName | String | 服务名称 | | ServerConfig.OpenAccessTypes | String[] | 公网访问类型 | | ServerConfig.Cpu | Number | CPU 规格 | | ServerConfig.Mem | Number | 内存规格 | | ServerConfig.MinNum | Number | 最小副本数 | | ServerConfig.MaxNum | Number | 最大副本数 | | ServerConfig.PolicyDetails | ICloudrunHpaPolicy[] | 扩缩容配置 | | ServerConfig.PolicyDetails[].PolicyType | String | 扩缩容类型,可选值:- `"cpu"`: 基于 CPU 利用率的扩缩容- `"mem"`: 基于内存利用率的扩缩容;- `"cpu/mem"`: 基于 CPU 和内存利用率的扩缩容 | | ServerConfig.PolicyDetails[].PolicyThreshold | Number | 扩缩容阈值(百分比),取值范围 0-100,如 60 表示当资源利用率达到 60%时触发扩缩容 | | ServerConfig.CustomLogs | String | 日志采集路径 | | ServerConfig.EnvParams | String | 环境变量 | | ServerConfig.InitialDelaySeconds | Number | 延迟检测时间 | | ServerConfig.CreateTime | String | 创建时间 | | ServerConfig.Port | Number | 服务端口 | | ServerConfig.HasDockerfile | Boolean | 是否有 Dockerfile | | ServerConfig.Dockerfile | String | Dockerfile 文件名 | | ServerConfig.BuildDir | String | 构建目录 | | ServerConfig.LogType | String | 日志类型 | | ServerConfig.LogSetId | String | CLS 日志集 ID | | ServerConfig.LogTopicId | String | CLS 主题 ID | | ServerConfig.LogParseType | String | 日志解析类型 | | ServerConfig.Tag | String | 服务标签 | | ServerConfig.InternalAccess | String | 内网访问开关 | | ServerConfig.InternalDomain | String | 内网域名 | | ServerConfig.OperationMode | String | 运行模式 | | ServerConfig.TimerScale | ICloudrunTimerScale[] | 定时扩缩容配置 | | ServerConfig.TimerScale[].CycleType | String | 循环类型,可选值:- `"none"`: 无循环- `"daily"`: 每日循环- `"weekly"`: 每周循环- `"monthly"`: 每月循环 | | ServerConfig.TimerScale[].StartDate | String | 循环起始日期(格式: YYYY-MM-DD) | | ServerConfig.TimerScale[].EndDate | String | 循环结束日期(格式: YYYY-MM-DD) | | ServerConfig.TimerScale[].StartTime | String | 起始时间(格式: HH:mm:ss) | | ServerConfig.TimerScale[].EndTime | String | 结束时间(格式: HH:mm:ss) | | ServerConfig.TimerScale[].ReplicaNum | Number | 副本个数(最小值: 0) | | ServerConfig.EntryPoint | String[] | Dockerfile EntryPoint 参数 | | ServerConfig.Cmd | String[] | Dockerfile Cmd 参数 | | OnlineVersionInfos | ICloudrunOnlineVersionInfo[] | 在线版本信息 | | OnlineVersionInfos[].VersionName | String | 版本名称 | | OnlineVersionInfos[].ImageUrl | String | 镜像 URL | | OnlineVersionInfos[].FlowRatio | String | 流量比例 | | RequestId | String | 请求 ID | ### 4. 示例代码 ```javascript import CloudBase from "@cloudbase/manager-node"; const manager = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId", }); async function test() { const detail = await manager.cloudrun.detail({ serverName: "my-server", }); console.log("服务详情:", detail); } test(); ``` ## delete ### 1. 接口描述 接口功能:删除指定的云托管服务 接口声明:`delete(params: { serverName: string }): Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ---------- | ---- | ------ | ---------------- | | serverName | 是 | String | 要删除的服务名称 | ### 3. 返回结果 | 字段 | 类型 | 说明 | | --------- | ------ | ------- | | RequestId | String | 请求 ID | ### 4. 示例代码 ```javascript import CloudBase from "@cloudbase/manager-node"; const manager = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId", }); async function test() { await manager.cloudrun.delete({ serverName: "my-server", }); console.log("服务删除成功"); } test(); ``` ## deploy ### 1. 接口描述 接口功能:本地代码部署云托管服务 接口声明:`deploy(params: { serverName: string; targetPath: string; serverConfig?: Partial }): Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ------------ | ---- | ----------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | serverName | 是 | String | 要部署的服务名称 | | targetPath | 是 | String | 本地代码路径 | | serverConfig | 否 | Partial | 服务配置项,包含以下可选字段: | | | | | - OpenAccessTypes: string[] - 公网访问类型数组,可选值:`"OA"` - 办公网访问`"PUBLIC"` - 公网访问`"MINIAPP"` - 小程序访问`"VPC"` - VPC 访问 | | | | | - Cpu: number - CPU 规格 | | | | | - Mem: number - 内存规格 | | | | | - MinNum: number - 最小实例数 | | | | | - MaxNum: number - 最大实例数 | | | | | - PolicyDetails: ICloudrunHpaPolicy[] - 扩缩容配置数组,每个元素包含:`PolicyType: string` - 扩缩容类型,可选值:`"cpu"`、`"mem"`、`"cpu/mem"``PolicyThreshold: number` - 扩缩容阈值(百分比),如 60 表示 60% | | | | | - CustomLogs: string - 自定义日志配置 | | | | | - EnvParams: string - 环境变量 JSON 字符串 | | | | | - Port: number - 服务端口(函数型服务固定为 3000) | | | | | - Dockerfile: string - Dockerfile 文件名 | | | | | - BuildDir: string - 构建目录 | | | | | - InternalAccess: string - 内网访问开关 | | | | | - InternalDomain: string - 内网域名 | | | | | - EntryPoint: string[] - Dockerfile EntryPoint 参数 | | | | | - Cmd: string[] - Dockerfile Cmd 参数 | ## ### 3. 返回结果 | 字段 | 类型 | 说明 | | --------- | ------ | ------- | | RequestId | String | 请求 ID | ### 4. 示例代码 ```javascript import CloudBase from "@cloudbase/manager-node"; const manager = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId", }); async function test() { await manager.cloudrun.deploy({ serverName: "my-server", targetPath: "./my-project", serverConfig: { Cpu: 0.5, Mem: 1, MinNum: 1, MaxNum: 5, }, }); console.log("服务部署成功"); } test(); ``` ## getTemplates ### 1. 接口描述 接口功能:获取云托管服务模板列表 接口声明:`getTemplates(): Promise` ### 2. 输入参数 无 ### 3. 返回结果 | 字段 | 类型 | 说明 | | ----------------- | ------ | ------------------ | | ITemplate[] | Array | 模板数组 | | [].identifier | String | 模板唯一标识符 | | [].title | String | 模板标题 | | [].description | String | 模板描述 | | [].runtimeVersion | String | 运行时版本 | | [].language | String | 编程语言 | | [].zipFileStore | String | 模板压缩包存储地址 | ### 4. 示例代码 ```javascript import CloudBase from "@cloudbase/manager-node"; const manager = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId", }); async function test() { const templates = await manager.cloudrun.getTemplates(); console.log("可用模板:", templates); templates.forEach((template) => { console.log(`模板ID: ${template.identifier}`); console.log(`标题: ${template.title}`); console.log(`描述: ${template.description}`); console.log(`运行时版本: ${template.runtimeVersion}`); console.log(`语言: ${template.language}`); console.log(`下载地址: ${template.zipFileStore}`); }); } test(); ``` --- ## CLS 日志 # CLS 日志 查询环境 CLS 日志的接口,可通过 [commonService ](./common)来调用 ## 日志查询 ### 1. 接口描述 接口功能:查询指定条件的 CLS 日志 接口声明:`manager.commonService().call({ Action: 'SearchClsLog', Param: {}}): Promise` > ⚠️ 本接口从 3.0.0 版本后,commonService 作为方法使用,请求参数为(service?:string, version?:string) ,属于不兼容变更 ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ----------- | ---- | ------- | -------------------------------------------------------------------------- | | EnvId | 是 | String | 环境 ID | | StartTime | 是 | String | 查询起始时间条件, 日期格式为 YYYY-MM-DD HH:mm:ss | | EndTime | 是 | String | 查询结束时间条件, 日期格式为 YYYY-MM-DD HH:mm:ss | | QueryString | 是 | String | 查询语句,详情[参考](https://cloud.tencent.com/document/product/614/47044) | | Limit | 是 | String | 单次要返回的日志条数,单次返回的最大条数为 100 | | Sort | 否 | Boolean | 按时间排序 asc(升序)或者 desc(降序),默认为 desc | | UseLucene | 否 | Boolean | 是否使用 Lucene 语法,默认为 false | ### 3. 返回结果 | 字段 | 类型 | 说明 | | ---------- | ------ | ------------ | | RequestId | String | 请求唯一标识 | | LogResults | String | 日志内容结果 | #### ILogResObject | 字段 | 类型 | 说明 | | -------- | ----------------------- | ------------------------ | | Context | String | 获取更多检索结果的游标 | | ListOver | Boolean | 搜索结果是否已经全部返回 | | Results | `Array` | 日志内容信息 | #### ILogObject | 字段 | 类型 | 说明 | | --------- | ------ | ------------------- | | TopicId | String | 日志属于的 topic ID | | TopicName | String | 日志主题的名字 | | Timestamp | String | 日志时间 | | Content | String | 日志内容 | | FileName | String | 采集路径 | | Source | String | 日志来源设备 | ### 4. 示例代码 ```javascript import CloudBase from "@cloudbase/manager-node"; const moment = require("moment"); // 格式化日期库需自行安装依赖 const manager = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId" // 云开发环境ID,可在腾讯云云开发控制台获取 }); const { functions } = manager; async function test() { const logs = await functions.getFunctionLogs({ name: "your function name" }); const { Data } = logs; for (let item in Data) { console.log(item.RequestId); // 基于 requestId 查 cls 日志 const clsLogRes = await manager.commonService().call({ Action: "SearchClsLog", Param: { EnvId: cloudBaseConfig.envId, StartTime: moment(new Date().getTime() - 24 * 60 * 60 * 1000).format("YYYY-MM-DD HH:mm:ss"), // 开始时间,例如取一天前时间 EndTime: moment().format("YYYY-MM-DD HH:mm:ss"), // 截止时间,例如取当前时间 Limit: 100, Sort: "asc", QueryString: `requestId:${item.RequestId}` } }); console.log("clsLogRes", clsLogRes); } } test(); ``` --- ## 公共接口 # 公共接口 ### 1. 接口描述 接口功能:manager-node 针对 部分接口形式相对固定的功能, 提供了 commonService 的公共方法调用 接口声明:`manager.commonService(service, version).call(option): Promise` > ⚠️ 本接口从 3.0.0 版本后,commonService 作为方法使用,请求参数为(service?:string, version?:string) ,属于不兼容变更 ### 2. 输入参数 commonService 方法 | 字段 | 类型 | 必填 | 说明 | | ------- | ------ | ---- | ------------ | | service | string | 否 | 请求资源所属 | | version | string | 否 | 接口版本 | call 方法 | 字段 | 类型 | 必填 | 说明 | | ---- | ----------------------- | ---- | ------------ | | - | ICommonApiServiceOption | 是 | 公共接口传参 | #### ICommonApiServiceOption 结构体 | 字段 | 类型 | 必填 | 说明 | | ------ | ------ | ---- | -------------------------------- | | Action | String | 是 | 接口名 | | Param | Object | 是 | 接口传参,具体形式参考各接口指引 | ### 3. 返回结果 | 字段 | 类型 | 必填 | 说明 | | ---- | ------ | ---- | ------------------------------- | | - | Object | 是 | 不同的 action,请求回包对象不同 | ### 4. 示例代码 ```javascript import CloudBase from '@cloudbase/manager-node' const manager = new CloudBase({ secretId: 'Your SecretId', secretKey: 'Your SecretKey', envId: 'Your envId' // 云开发环境ID,可在腾讯云云开发控制台获取 }) async function test() { const res = await manager.commonService().call({ Action: 'DescribeDatabaseACL', Param: { CollectionName: 'xxx', EnvId: 'xxx' } }) console.log(res) } test() ``` --- ## 数据库 # 数据库 ## createCollection ### 1. 接口描述 接口功能:该接口可创建集合 接口声明: `createCollection(collectionName: string): Promise` `createCollectionIfNotExists(collectionName: string): Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | -------------- | ---- | ------ | ------ | | CollectionName | 是 | String | 集合名 | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | ------------ | | RequestId | 是 | String | 请求唯一标识 | ### 4. 示例代码 ```javascript const cloudbaseConfig = { secretId: 'Your SecretId', secretKey: 'Your SecretKey', envId: 'Your envId' // 云开发环境ID,可在腾讯云云开发控制台获取 } let { database } = new CloudBase(cloudbaseConfig) async function test() { let result = await database.createCollection('collectionName') console.log(result) } test() ``` ## checkCollectionExists ### 1. 接口描述 接口功能:检查集合是否存在 接口声明:`checkCollectionExists(collectionName: string): Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ---- | ---- | ------ | ------ | | - | 是 | String | 集合名 | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------- | ---------------- | | RequestId | 是 | String | 请求唯一标识 | | Msg | 否 | String | 错误信息 | | Exists | 是 | Boolean | 集合是否已经存在 | ### 4. 示例代码 ```javascript const cloudbaseConfig = { secretId: 'Your SecretId', secretKey: 'Your SecretKey', envId: 'Your envId' // 云开发环境ID,可在腾讯云云开发控制台获取 } let { database } = new CloudBase(cloudbaseConfig) async function test() { let result = await database.checkCollectionExists('collectionAlreadyExists') if (result.Exists) { // 集合存在 } else { // 集合不存在 } } test() ``` ## deleteCollection ### 1. 接口描述 接口功能:删除集合 接口声明:`deleteCollection(collectionName: string): Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | -------------- | ---- | ------ | ------ | | CollectionName | 是 | String | 集合名 | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------- | ------------------------------------ | | RequestId | 是 | String | 请求唯一标识 | | Exists | 否 | Boolean | 存在不返回该字段,不存在则返回 false | ### 4. 示例代码 ```javascript const cloudbaseConfig = { secretId: 'Your SecretId', secretKey: 'Your SecretKey', envId: 'Your envId' // 云开发环境ID,可在腾讯云云开发控制台获取 } let { database } = new CloudBase(cloudbaseConfig) async function test() { let result = await database.deleteCollection('collectionAlreadyExists') if (result.Exists === false) { // 集合不存在 } } test() ``` ## updateCollection ### 1. 接口描述 接口功能:更新集合 接口声明:`updateCollection(collectionName: string, options: array): Promise` 该接口可更新集合,但目前支持更新索引。 > ⚠️ 目前该接口只能更新索引,包括创建和删除。 - 索引创建时如果已经存在,则会先删除再创建索引。 - 因为一次接口调用可同时创建多个索引,所以可能部分索引创建失败,部分创建成功,接口报异常。 ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | -------------- | ---- | -------------------- | -------- | | collectionName | 是 | String | 集合名 | | options | 是 | `Array` | 配置选项 | **Option** | 字段 | 必填 | 类型 | 说明 | | ------------- | ---- | ------------------------- | ------------------ | | CreateIndexes | 否 | `Array` | 需要创建的索引列表 | | DropIndexes | 否 | `Array` | 需要删除的索引列表 | **CreateIndex** | 字段 | 必填 | 类型 | 说明 | | ------------ | ---- | -------------------------- | -------- | | IndexName | 是 | String | 索引名称 | | MgoKeySchema | 是 | `Array` | 索引规则 | **MgoKeySchema** | 字段 | 必填 | 类型 | 说明 | | ------------ | ---- | ------------------------- | ------------------ | | MgoIsUnique | 是 | boolean | 是否唯一 | | MgoIndexKeys | 是 | `Array` | 索引包含的字段列表 | **MgoIndexKey** | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | -------------------------------------------------------------------------------------------------------- | | Name | 是 | String | 索引名称 | | Direction | 是 | String | 索引方向,1:ASC,-1:DESC,2d:双向,如果有 2d,2d 必须放最前面,注:地理位置索引应设置该值为 "2dsphere" | **DropIndex** | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | -------- | | IndexName | 是 | String | 索引名称 | > 更新索引支持的两种方式,创建与删除,相互独立,不可在 options 同时传入 CreateIndexes,DropIndexes ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | ------------ | | RequestId | 是 | String | 请求唯一标识 | ### 4. 示例代码 创建新索引 ```javascript const cloudbaseConfig = { secretId: 'Your SecretId', secretKey: 'Your SecretKey', envId: 'Your envId' // 云开发环境ID,可在腾讯云云开发控制台获取 } let { database } = new CloudBase(cloudbaseConfig) async function test() { let result = await database.updateCollection('collectionAlreadyExists', { CreateIndexes: [ { IndexName: 'index_a', MgoKeySchema: { MgoIndexKeys: [ // 2d要放最前面 { Name: 'a_2d', Direction: '2d' }, { Name: 'a_1', Direction: '1' }, { Name: 'a_-1', Direction: '-1' } ], MgoIsUnique: false } }, { IndexName: 'index_b', MgoKeySchema: { MgoIndexKeys: [{ Name: 'b_1', Direction: '2d' }], MgoIsUnique: true } }, { IndexName: 'index_to_be_delete', MgoKeySchema: { MgoIndexKeys: [{ Name: 'xxx', Direction: '2d' }], MgoIsUnique: true } } ] }) console.log(result) } test() ``` 删除索引 ```javascript const cloudbaseConfig = { secretId: 'Your SecretId', secretKey: 'Your SecretKey', envId: 'Your envId' // 云开发环境ID,可在腾讯云云开发控制台获取 } let { database } = new CloudBase(cloudbaseConfig) async function test() { let result = await database.updateCollection('collectionAlreadyExists', { DropIndexes: [{ IndexName: 'index_to_be_delete' }] }) console.log(result) } test() ``` ## describeCollection ### 1. 接口描述 接口功能:查询集合详细信息 接口声明:`describeCollection(collectionName: string): Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | -------------- | ---- | ------ | ------ | | CollectionName | 是 | String | 集合名 | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | ---------------------------- | ---- | ------ | ---------------------------------------- | | RequestId | 是 | String | 请求唯一标识 | | IndexNum | 是 | Number | 索引个数 | | Indexes | 是 | Array | 索引列表 | | Indexes[N].Name | 是 | String | 索引名称 | | Indexes[N].Size | 是 | String | 索引大小,单位: 字节 | | Indexes[N].Unique | 是 | String | 是否为唯一索引 | | Indexes[N].Keys | 是 | Array | 索引键值 | | Indexes[N].Keys[N].Name | 是 | String | 键名 | | Indexes[N].Keys[N].Direction | 是 | String | 索引方向,1: ASC, -1: DESC, 2d:双向 | | Indexes[N].Accesses | 是 | Array | 索引使用信息 | | Indexes[N].Accesses[N].Ops | 是 | Number | 索引命中次数 | | Indexes[N].Accesses[N].Since | 是 | String | 命中次数从何时开始计数 | ### 4. 示例代码 ```javascript const cloudbaseConfig = { secretId: 'Your SecretId', secretKey: 'Your SecretKey', envId: 'Your envId' // 云开发环境ID,可在腾讯云云开发控制台获取 } let { database } = new CloudBase(cloudbaseConfig) async function test() { let result = await database.describeCollection('collectionAlreadyExists') const { Indexes } = result for (let index in Indexes) { console.log(index) // 遍历全部索引 } } test() ``` ## listCollections ### 1. 接口描述 接口功能:查询集合详细信息 接口声明:`listCollections(options: object): Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | -------------- | | MgoOffset | 否 | Number | 可选,偏移量 | | MgoLimit | 否 | Number | 可选,数量限制 | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | ----------------------------- | ---- | ------ | ---------------------------- | | RequestId | 是 | String | 请求唯一标识 | | Collections | 是 | Array | 集合列表 | | Collections[N].CollectionName | 是 | String | 集合名称 | | Collections[N].Count | 是 | Number | 集合中文档数量 | | Collections[N].Size | 是 | Number | 集合占用空间大小,字节 | | Collections[N].IndexCount | 是 | Number | 集合中索引个数 | | Collections[N].IndexSize | 是 | Number | 集合中索引占用空间大小,字节 | | Pager | 是 | Object | 本次查询分页信息 | | Pager.Offset | 是 | Number | 偏移量 | | Pager.Limit | 是 | Number | 限制数量 | | Pager.Total | 是 | Number | 集合数量 | ### 4. 示例代码 ```javascript const cloudbaseConfig = { secretId: 'Your SecretId', secretKey: 'Your SecretKey', envId: 'Your envId' // 云开发环境ID,可在腾讯云云开发控制台获取 } let { database } = new CloudBase(cloudbaseConfig) async function test() { let result = await database.listCollections({ MgoOffset: 100, MgoLimit: 10 }) const { Collections } = result for (let collection in Collections) { console.log(collection) // 遍历全部collection } } ``` ## checkIndexExists ### 1. 接口描述 接口功能:检查索引是否存在 接口声明:`checkIndexExists(collectionName: string, indexName: string): Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | -------------- | ---- | ------ | ------ | | collectionName | 是 | String | 集合名 | | indexName | 是 | String | 索引名 | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------- | ------------ | | RequestId | 是 | String | 请求唯一标识 | | Exists | 是 | Boolean | 索引是否存在 | ### 4. 示例代码 ```javascript const cloudbaseConfig = { secretId: 'Your SecretId', secretKey: 'Your SecretKey', envId: 'Your envId' // 云开发环境ID,可在腾讯云云开发控制台获取 } let { database } = new CloudBase(cloudbaseConfig) async function test() { let result = await database.checkIndexExists( 'collectionAlreadyExists', 'index_to_be_delete' ) const { Exists } = result if (Exists === true) { //索引存在 } } test() ``` ## import ### 1. 接口描述 接口功能:导入数据 接口声明:`import(collectionName: string, file: object, options: object): Promise` 注意: - 该接口立即返回,迁移状态(成功|失败)可通过 migrateStatus 查询。 - 导入数据需要先将文件上传到该环境(同一个 EnvId)下的对象存储中,所以会在对象存储中创建对象。 - 因为该函数成功返回只意味着上传成功,导入操作在上传后开始,该接口无法判断导入是否完成,所以该对象用完后需要手动删除。 ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ----------------- | ---- | ------- | --------------------------------------------------------------------------------- | | collectionName | 是 | String | 集合名 | | file | 是 | Array | 数据,以下方式必选一种 | | ⁃ FilePath | 是 | String | 本地数据文件路径 | | ⁃ ObjectKey | 是 | String | 本环境下对象存储 Key | | options | 否 | Array | 可选参数 | | ⁃ ObjectKeyPrefix | 否 | String | 对象存储 Key 前缀,默认 tmp/db-imports/ | | ⁃ FileType | 否 | String | 文件类型:csv 或 json,如果为传递此参数,默认为文件后缀名,注意使用正确的后缀名。 | | ⁃ StopOnError | 否 | Boolean | 遇到错误时是否停止导入。 | | ⁃ ConflictMode | 否 | String | 冲突处理方式:insert 或 upsert | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | ---------------------------------------------- | | RequestId | 是 | String | 请求唯一标识 | | JobId | 是 | Number | 任务 ID,用于在 migrateStatus 接口查询迁移状态 | ### 4. 示例代码 ```javascript const cloudbaseConfig = { secretId: 'Your SecretId', secretKey: 'Your SecretKey', envId: 'Your envId' // 云开发环境ID,可在腾讯云云开发控制台获取 } let { database } = new CloudBase(cloudbaseConfig) async function test() { let res = await database.import( 'collectionAlreadyExists', { ObjectKey: 'data.csv' }, { // "FileType" : "csv", StopOnError: true, ConflictMode: 'upsert' } ) const { JobId } = res console.log(JobId) } test() ``` ## export ### 1. 接口描述 接口功能:导出数据,迁移状态(成功|失败)可通过 migrateStatus 查询。 接口声明:`export(collectionName: string, file: object, options: object): Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | -------------- | ---- | ------ | -------------------------------------------------------------------------------- | | collectionName | 是 | String | 集合名 | | file | 是 | Array | 数据,以下方式必选一种 | | ⁃ ObjectKey | 是 | String | 本环境下对象存储 Key | | options | 否 | Array | 可选参数 | | ⁃ FileType | 否 | String | 文件类型:csv 或 json,如果为传递此参数,默认为文件后缀名,注意使用正确的后缀名 | | ⁃ Query | 否 | String | JSON 字符串,支持 mongo 指令。例如:'{ a: { gte: 3 } }'。与 mongodb 查询语法兼容 | | ⁃ Skip | 否 | Number | 偏移量 | | ⁃ Limit | 否 | Number | 限制数目 | | ⁃ Sort | 否 | Number | JSON 字符串,如果有索引则不支持排序,数据集的长度必须少于 32 兆 | | ⁃ Fields | 否 | String | 字符串,字段以逗号分割。FileType=csv 时必填 | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | ---------------------------------------------- | | RequestId | 是 | String | 请求唯一标识 | | JobId | 是 | Number | 任务 ID,用于在 migrateStatus 接口查询迁移状态 | ### 4. 示例代码 ```javascript const cloudbaseConfig = { secretId: 'Your SecretId', secretKey: 'Your SecretKey', envId: 'Your envId' // 云开发环境ID,可在腾讯云云开发控制台获取 } let { database } = new CloudBase(cloudbaseConfig) async function test() { let result = await database.export( 'users', { ObjectKey: 'users.json' }, { Fields: '_id,name', Query: '{"name":{"$exists":true}}', Sort: '{"name": -1}', Skip: 0, Limit: 1000 } ) const { JobId } = res console.log(JobId) } test() ``` ## migrateStatus ### 1. 接口描述 接口功能:该接口可查询迁移(导入|导出)状态。 接口声明:`migrateStatus(jobId: number): Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ----- | ---- | ------- | ------------------------------------------ | | jobId | 是 | Integer | 任务 ID,import 和 export 接口返回的 JobId | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | ------------- | ---- | ------- | --------------------------------------------------------------------------------------------------------- | | RequestId | 是 | String | 请求唯一标识 | | Status | 是 | String | 任务状态。可能值:waiting:等待中,reading:读,writing:写,migrating:转移中,success:成功,fail:失败 | | RecordSuccess | 是 | Integer | 迁移成功的数据条数 | | RecordFail | 是 | Integer | 迁移失败的数据条数 | | ErrorMsg | 是 | String | 迁移失败的原因 | | FileUrl | 是 | String | 文件下载链接,仅在数据库导出中有效 | ### 4. 示例代码 ```javascript const cloudbaseConfig = { secretId: 'Your SecretId', secretKey: 'Your SecretKey', envId: 'Your envId' // 云开发环境ID,可在腾讯云云开发控制台获取 } let { database } = new CloudBase(cloudbaseConfig) async function test() { let result = await database.migrateStatus(100093275) console.log(result.Status) // 打印迁移状态 } test() ``` ## distribution ### 1. 接口描述 接口功能:查询数据分布 接口声明:`distribution(): Promise` ### 2. 输入参数 无 ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | ----------------------------- | ---- | ------ | ------------ | | RequestId | 是 | String | 请求唯一标识 | | Collections | 是 | Array | 集合列表 | | Collections[N].CollectionName | 是 | String | 集合名称 | | Collections[N].DocCount | 是 | Number | 文档数量 | ### 4. 示例代码 ```javascript const cloudbaseConfig = { secretId: 'Your SecretId', secretKey: 'Your SecretKey', envId: 'Your envId' // 云开发环境ID,可在腾讯云云开发控制台获取 } let { database } = new CloudBase(cloudbaseConfig) async function test() { let result = await database.distribution() const { Collections } = result for (let collection in Collections) { console.log(collection) } } test() ``` ## 插入文档 ### 1. 接口描述 接口功能:该接口用于向数据库中插入数据 接口声明:`manager.commonService('flexdb').call(option): Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ------ | ---- | ------ | -------- | | Action | 是 | String | 接口名称 | | Param | 是 | Object | 接口参数 | #### Param 字段说明 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | -------------------- | --------------------------------------- | | TableName | 是 | String | 表名 | | MgoDocs | 是 | `Array` | 待插入文档 | | Tag | 是 | String | mongo 实例 ID, 可通过 envInfo 接口获取 | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | ----------- | ---- | -------------------- | -------------------------- | | RequestId | 是 | String | 请求唯一标识 | | InsertedIds | 是 | `Array` | 插入成功的数据集合主键\_id | ### 4. 示例代码 ```javascript const cloudbaseConfig = { secretId: 'Your SecretId', secretKey: 'Your SecretKey', envId: 'Your envId' // 云开发环境ID,可在腾讯云云开发控制台获取 } const manager = new CloudBase(cloudBaseConfig) const data = JSON.stringify({ a: 1 }) // 获取数据库实例ID const { EnvInfo } = await manager.env.getEnvInfo() const { Databases } = EnvInfo console.log('Databases:', Databases) const { InsertedIds } = await manager.commonService('flexdb').call({ Action: 'PutItem', Param: { TableName: 'coll-1', MgoDocs: [data], Tag: Databases[0].InstanceId } }) console.log('InsertedIds:', InsertedIds) ``` ## 查询文档 ### 1. 接口描述 接口功能:该接口用于查询数据库文档 接口声明:`manager.commonService('flexdb').call(option): Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ------ | ---- | ------ | -------- | | Action | 是 | String | 接口名称 | | Param | 是 | Object | 接口参数 | #### Param 字段说明 | 字段 | 必填 | 类型 | 说明 | | ------------- | ---- | ------ | -------------------------------------------------------------------------------------------------------------------- | | TableName | 是 | String | 表名 | | MgoLimit | 是 | Number | 查询返回结果 limit 数 | | MgoProjection | 否 | String | 投影条件,为一个 json 串,如{ item: 1, status: 1 }表示结果中返回 item 和 status 两个列;{ item: 0}表示不返回 item 列 | | Tag | 是 | String | mongo 实例 ID, 可通过 envInfo 接口获取 | | MgoQuery | 否 | String | 查询条件,查询条件为一个 json 串,如{"test":1} | | MgoOffset | 否 | Number | 查询结果从 offset 条开始返回 | | MgoSort | 否 | String | 排序条件,排序条件为一个 json 串 | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | -------------------- | ---------------------- | | RequestId | 是 | String | 请求唯一标识 | | Pager | 是 | Pager | 分页信息 | | Data | 是 | `Array` | 满足查询条件的数据集合 | | 字段 | 必填 | 类型 | 说明 | | ------ | ---- | ------ | -------------- | | Offset | 是 | Number | 分页偏移量 | | Limit | 是 | Number | 每页返回记录数 | ### 4. 示例代码 ```javascript const cloudbaseConfig = { secretId: 'Your SecretId', secretKey: 'Your SecretKey', envId: 'Your envId' // 云开发环境ID,可在腾讯云云开发控制台获取 } const manager = new CloudBase(cloudBaseConfig) // 获取数据库实例ID const { EnvInfo } = await manager.env.getEnvInfo() const { Databases } = EnvInfo console.log('Databases:', Databases) const { Data } = await manager.commonService('flexdb').call({ Action: 'Query', Param: { TableName: 'coll-1', MgoQuery: JSON.stringify({ a: 1 }), Tag: Databases[0].InstanceId, MgoLimit: 20 } }) console.log('Data:', Data) ``` ## 更新文档 ### 1. 接口描述 接口功能:该接口用于更新数据库文档 接口声明:`manager.commonService('flexdb').call(option): Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ------ | ---- | ------ | -------- | | Action | 是 | String | 接口名称 | | Param | 是 | Object | 接口参数 | #### Param 字段说明 | 字段 | 必填 | 类型 | 说明 | | ---------- | ---- | ------- | ---------------------------------------------- | | Tag | 是 | String | mongo 实例 ID, 可通过 envInfo 接口获取 | | MgoQuery | 否 | String | 查询条件,查询条件为一个 json 串,如{"test":1} | | MgoUpdate | 是 | String | 更新内容 | | TableName | 是 | String | 表名 | | MgoIsMulti | 否 | Boolean | 是否更新多条 | | MgoUpsert | 否 | Boolean | 是否使用 upsert 模式 | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | ----------- | ---- | ------ | ---------------------- | | RequestId | 是 | String | 请求唯一标识 | | UpsertedId | 是 | String | 插入的数据\_id | | ModifiedNum | 是 | Number | 已经修改的行数 | | MatchedNum | 是 | Number | 更新条件匹配到的结果数 | ### 4. 示例代码 ```javascript const cloudbaseConfig = { secretId: 'Your SecretId', secretKey: 'Your SecretKey', envId: 'Your envId' // 云开发环境ID,可在腾讯云云开发控制台获取 } const manager = new CloudBase(cloudBaseConfig) // 获取数据库实例ID const { EnvInfo } = await manager.env.getEnvInfo() const { Databases } = EnvInfo console.log('Databases:', Databases) const { ModifiedNum } = await manager.commonService('flexdb').call({ Action: 'UpdateItem', Param: { TableName: 'coll-1', MgoUpdate: JSON.stringify({ a: 2 }), MgoQuery: JSON.stringify({ a: 1 }), Tag: Databases[0].InstanceId } }) console.log('ModifiedNum:', ModifiedNum) ``` ## 删除文档 ### 1. 接口描述 接口功能:该接口用于删除数据库文档 接口声明:`manager.commonService('flexdb').call(option): Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ------ | ---- | ------ | -------- | | Action | 是 | String | 接口名称 | | Param | 是 | Object | 接口参数 | #### Param 字段说明 | 字段 | 必填 | 类型 | 说明 | | ---------- | ---- | ------- | ---------------------------------------------- | | Tag | 是 | String | mongo 实例 ID, 可通过 envInfo 接口获取 | | MgoQuery | 否 | String | 查询条件,查询条件为一个 json 串,如{"test":1} | | TableName | 是 | String | 表名 | | MgoIsMulti | 否 | Boolean | 是否更新多条 | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | -------------- | | RequestId | 是 | String | 请求唯一标识 | | Deleted | 是 | Number | 删除数据的条数 | ### 4. 示例代码 ```javascript const cloudbaseConfig = { secretId: 'Your SecretId', secretKey: 'Your SecretKey', envId: 'Your envId' // 云开发环境ID,可在腾讯云云开发控制台获取 } const manager = new CloudBase(cloudBaseConfig) // 获取数据库实例ID const { EnvInfo } = await manager.env.getEnvInfo() const { Databases } = EnvInfo console.log('Databases:', Databases) const { Deleted } = await manager.commonService('flexdb').call({ Action: 'DeleteItem', Param: { TableName: 'coll-1', MgoQuery: JSON.stringify({ a: 2 }), Tag: Databases[0].InstanceId } }) console.log('Deleted:', Deleted) ``` ## 查询可回档时间 ### 1. 接口描述 接口功能:获取所选表格可回档时间的交集 接口声明:`manager.commonService('flexdb').call(option): Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ------ | ---- | ------ | -------- | | Action | 是 | String | 接口名称 | | Param | 是 | Object | 接口参数 | #### Param 字段说明 | 字段 | 必填 | 类型 | 说明 | | ---------- | ---- | ------ | --------------------------------------- | | InstanceId | 是 | String | mongo 实例 ID, 可通过 envInfo 接口获取 | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | ------------ | ---- | -------------------- | -------------- | | RestoreTimes | 是 | `Array` | 可回档时间列表 | | RequestId | 是 | String | 请求唯一标识 | ### 4. 示例代码 ```javascript const cloudbaseConfig = { secretId: 'Your SecretId', secretKey: 'Your SecretKey', envId: 'Your envId' // 云开发环境ID,可在腾讯云云开发控制台获取 } const manager = new CloudBase(cloudBaseConfig) // 获取数据库实例ID const { EnvInfo } = await manager.env.getEnvInfo() const { Databases } = EnvInfo // 查询可回档时间 const { RestoreTimes } = await manager.commonService('flexdb').call({ Action: 'DescribeRestoreTime', Param: { InstanceId: Databases[0].InstanceId } }) console.log(RestoreTimes) ``` ## 获取可回档表格 ### 1. 接口描述 接口功能:获取可回档表格 接口声明:`manager.commonService('flexdb').call(option): Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ------ | ---- | ------ | -------- | | Action | 是 | String | 接口名称 | | Param | 是 | Object | 接口参数 | #### Param 字段说明 | 字段 | 必填 | 类型 | 说明 | | ---------- | ---- | ------ | --------------------------------------- | | InstanceId | 是 | String | mongo 实例 ID, 可通过 envInfo 接口获取 | | Time | 是 | String | 可回档时间 | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | -------------------- | -------------- | | Tables | 是 | `Array` | 可回档表格列表 | | RequestId | 是 | String | 请求唯一标识 | ### 4. 示例代码 ```javascript const cloudbaseConfig = { secretId: 'Your SecretId', secretKey: 'Your SecretKey', envId: 'Your envId' // 云开发环境ID,可在腾讯云云开发控制台获取 } const manager = new CloudBase(cloudBaseConfig) // 获取数据库实例ID const { EnvInfo } = await manager.env.getEnvInfo() const { Databases } = EnvInfo // 查询可回档时间 const { RestoreTimes } = await manager.commonService('flexdb').call({ Action: 'DescribeRestoreTime', Param: { InstanceId: Databases[0].InstanceId } }) console.log(RestoreTimes) // 获取可回档表格 const { Tables } = await manager.commonService('flexdb').call({ Action: 'DescribeRestoreTables', Param: { InstanceId: Databases[0].InstanceId, Time: RestoreTimes[0] } }) console.log(Tables) ``` ## 实例表格回档 ### 1. 接口描述 接口功能:实例表格回档 接口声明:`manager.commonService('flexdb').call(option): Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ------ | ---- | ------ | -------- | | Action | 是 | String | 接口名称 | | Param | 是 | Object | 接口参数 | #### Param 字段说明 | 字段 | 必填 | 类型 | 说明 | | -------------------- | ---- | -------------------------------------- | --------------------------------------- | | InstanceId | 是 | String | mongo 实例 ID, 可通过 envInfo 接口获取 | | Time | 是 | String | 可回档时间 | | ModifyTableNamesInfo | 是 | `Array` | 回档表格信息 | #### ModifyTableNamesInfoItem | 字段 | 必填 | 类型 | 说明 | | ------------ | ---- | ------ | ------------------------------------ | | OldTableName | 是 | String | 原表名 | | NewTableName | 是 | String | 新表名(新表名一定不能与原表名相同!) | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | ------------ | | FlowId | 是 | String | 流程 ID | | RequestId | 是 | String | 请求唯一标识 | ### 4. 示例代码 ```javascript const cloudbaseConfig = { secretId: 'Your SecretId', secretKey: 'Your SecretKey', envId: 'Your envId' // 云开发环境ID,可在腾讯云云开发控制台获取 } const manager = new CloudBase(cloudBaseConfig) // 获取数据库实例ID const { EnvInfo } = await manager.env.getEnvInfo() const { Databases } = EnvInfo // 查询可回档时间 const { RestoreTimes } = await manager.commonService('flexdb').call({ Action: 'DescribeRestoreTime', Param: { InstanceId: Databases[0].InstanceId } }) console.log(RestoreTimes) // 获取可回档表格 const { Tables } = await manager.commonService('flexdb').call({ Action: 'DescribeRestoreTables', Param: { InstanceId: Databases[0].InstanceId, Time: RestoreTimes[0] } }) console.log(Tables) const { FlowId } = await manager.commonService('flexdb').call({ Action: 'RestoreTCBTables', Param: { InstanceId: Databases[0].InstanceId, Time: RestoreTimes[0], ModifyTableNamesInfo: [ { OldTableName: 'coll-1', NewTableName: 'coll-1_bak' } ] } }) console.log('FlowId:', FlowId) ``` ## 获取回档任务 ### 1. 接口描述 接口功能:获取回档任务 接口声明:`manager.commonService('flexdb').call(option): Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ------ | ---- | ------ | -------- | | Action | 是 | String | 接口名称 | | Param | 是 | Object | 接口参数 | #### Param 字段说明 | 字段 | 必填 | 类型 | 说明 | | ---------- | ---- | ------ | --------------------------------------- | | InstanceId | 是 | String | mongo 实例 ID, 可通过 envInfo 接口获取 | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------------------------- | -------------- | | Tasks | 是 | `Array` | 可回档表格列表 | | RequestId | 是 | String | 请求唯一标识 | #### RestoreTask | 字段 | 必填 | 类型 | 说明 | | ----------- | ---- | ------------------------------------------------------------------- | ------------------------------------------ | | Tables | 是 | `Array` | 回档任务涉及表格 | | CreateTime | 是 | String | 任务创建时间 | | Status | 是 | Number | 当前任务状态(0-待执行,1-运行中,2-已完成) | | EndTime | 是 | String | 任务完成时间 | | RestoreTime | 是 | String | 回档时间点 | ### 4. 示例代码 ```javascript const cloudbaseConfig = { secretId: 'Your SecretId', secretKey: 'Your SecretKey', envId: 'Your envId' // 云开发环境ID,可在腾讯云云开发控制台获取 } const manager = new CloudBase(cloudBaseConfig) // 获取数据库实例ID const { EnvInfo } = await manager.env.getEnvInfo() const { Databases } = EnvInfo const { Tasks } = await manager.commonService('flexdb').call({ Action: 'DescribeRestoreTask', Param: { InstanceId: Databases[0].InstanceId } }) console.log('Tasks:', Tasks) ``` ## 修改表名 ### 1. 接口描述 接口功能:修改表名 接口声明:`manager.commonService('flexdb').call(option): Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ------ | ---- | ------ | -------- | | Action | 是 | String | 接口名称 | | Param | 是 | Object | 接口参数 | #### Param 字段说明 | 字段 | 必填 | 类型 | 说明 | | --------------- | ---- | ------------------------------------------------------------------- | --------------------------------------- | | Tag | 是 | String | mongo 实例 ID, 可通过 envInfo 接口获取 | | ModifyTableInfo | 是 | `Array` | 修改表名信息 | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | ------------ | | FlowId | 是 | String | 流程 ID | | RequestId | 是 | String | 请求唯一标识 | ### 4. 示例代码 ```javascript const cloudbaseConfig = { secretId: 'Your SecretId', secretKey: 'Your SecretKey', envId: 'Your envId' // 云开发环境ID,可在腾讯云云开发控制台获取 } const manager = new CloudBase(cloudBaseConfig) // 获取数据库实例ID const { EnvInfo } = await manager.env.getEnvInfo() const { Databases } = EnvInfo const { FlowId } = await manager.commonService('flexdb').call({ Action: 'ModifyNameSpace', Param: { Tag: Databases[0].InstanceId, ModifyTableInfo: [ { OldTableName: 'coll-1_bak', NewTableName: 'coll-1_bak_modify' } ] } }) console.log('FlowId:', FlowId) ``` --- ## 环境管理 # 环境管理 ## listEnvs ### 1. 接口描述 接口功能:获取所有环境信息 接口声明:`listEnvs(): Promise` ### 2. 输入参数 无 ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | --------------------- | ------------ | | RequestId | 是 | String | 请求唯一标识 | | EnvList | 是 | `Array` | 环境数组 | #### EnvItem | 字段 | 必填 | 类型 | 说明 | | ----------- | ---- | ------ | -------------- | | EnvId | 是 | String | 环境 ID | | Source | 是 | String | 来源 | | Alias | 是 | String | 环境别名 | | Status | 是 | String | 环境状态 | | CreateTime | 是 | String | 创建时间 | | UpdateTime | 是 | String | 更新时间 | | PackageId | 是 | String | 环境套餐 ID | | PackageName | 是 | String | 套餐名 | | Databases | 是 | Array | 数据库资源详情 | | Storages | 是 | Array | 存储资源详情 | | Functions | 是 | Array | 函数资源详情 | | LogServices | 是 | Array | 日志资源详情 | ### 4. 示例代码 ```javascript import CloudBase from '@cloudbase/manager-node' const { env } = new CloudBase({ secretId: 'Your SecretId', secretKey: 'Your SecretKey', envId: 'Your envId' // 云开发环境ID,可在腾讯云云开发控制台获取 }) async function test() { const res = await env.listEnvs() const { EnvList } = res for (let env in EnvList) { // 遍历envList console.log(env) } } test() ``` ## getEnvAuthDomains ### 1. 接口描述 接口功能:获取合法域名列表 接口声明:`getEnvAuthDomains(): Promise` ### 2. 输入参数 无 ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | ------- | ---- | -------------------- | -------- | | Domains | 是 | `Array` | 域名列表 | | envId | 是 | String | 环境 ID | **Domain** | 字段 | 必填 | 类型 | 说明 | | ---------- | ---- | ------ | ----------------------------------- | | Id | 是 | String | 域名 ID | | Domain | 是 | String | 域名 | | Type | 是 | String | 域名类型。包含以下取值:system user | | Status | 是 | String | 状态。包含以下取值:ENABLE DISABLE | | CreateTime | 是 | String | 创建时间 | | UpdateTime | 是 | String | 更新时间 | ### 4. 示例代码 ```javascript import CloudBase from '@cloudbase/manager-node' const { env } = new CloudBase({ secretId: 'Your SecretId', secretKey: 'Your SecretKey', envId: 'Your envId' // 云开发环境ID,可在腾讯云云开发控制台获取 }) async function test() { const res = await env.getEnvAuthDomains() const { Domains } = res for (let domain in Domains) { console.log(domain) } } test() ``` ## createEnvDomain ### 1. 接口描述 接口功能:添加环境安全域名 接口声明:`createEnvDomain(domains: string[]): Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ------- | ---- | -------------------- | ------------ | | domains | 是 | `Array` | 安全域名数组 | ### 3. 返回结果 | 字段 | 类型 | 说明 | | --------- | ------ | ------- | | RequestId | String | 请求 ID | ### 4. 示例代码 ```javascript import CloudBase from '@cloudbase/manager-node' const { env } = new CloudBase({ secretId: 'Your SecretId', secretKey: 'Your SecretKey', envId: 'Your envId' // 云开发环境ID,可在腾讯云云开发控制台获取 }) async function test() { const res = await env.createEnvDomain(['luke.com']) console.log(res) } test() ``` ## deleteEnvDomain ### 1. 接口描述 接口功能:删除环境安全域名 接口声明:`deleteEnvDomain(domains: string[]): Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ------- | ---- | -------------------- | ------------ | | domains | 是 | `Array` | 安全域名数组 | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | ---------------- | | RequestId | 是 | String | 请求 ID | | Deleted | 是 | Number | 删除成功的域名数 | ### 4. 示例代码 ```javascript import CloudBase from '@cloudbase/manager-node' const { env } = new CloudBase({ secretId: 'Your SecretId', secretKey: 'Your SecretKey', envId: 'Your envId' // 云开发环境ID,可在腾讯云云开发控制台获取 }) async function test() { const res = await env.deleteEnvDomain(['luke.com']) const { Deleted } = res console.log(Deleted) // 删除域名数 } test() ``` ## getEnvInfo ### 1. 接口描述 接口功能:获取环境信息 接口声明:`getEnvInfo(): Promise` ### 2. 输入参数 无 ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------------------- | -------- | | RequestId | 是 | String | 请求 ID | | EnvInfo | 是 | [EnvItem](#EnvItem) | 环境信息 | ### 4. 示例代码 ```javascript import CloudBase from '@cloudbase/manager-node' const { env } = new CloudBase({ secretId: 'Your SecretId', secretKey: 'Your SecretKey', envId: 'Your envId' // 云开发环境ID,可在腾讯云云开发控制台获取 }) async function test() { const res = await env.getEnvInfo() const { EnvInfo } = res console.log(EnvInfo) } test() ``` ## updateEnvInfo ### 1. 接口描述 接口功能:修改环境别名 接口声明:`updateEnvInfo(alias: string): Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ----- | ---- | ------ | -------- | | alias | 是 | String | 环境别名 | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | ------- | | RequestId | 是 | String | 请求 ID | ### 4. 示例代码 ```javascript import CloudBase from '@cloudbase/manager-node' const { env } = new CloudBase({ secretId: 'Your SecretId', secretKey: 'Your SecretKey', envId: 'Your envId' // 云开发环境ID,可在腾讯云云开发控制台获取 }) async function test() { const res = await env.updateEnvInfo('lukemodify') console.log(res) } test() ``` ## getLoginConfigList ### 1. 接口描述 接口功能:拉取登录配置列表 接口声明:`getLoginConfigList(): Promise` ### 2. 输入参数 无 ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | ---------- | ---- | ------------------------ | ------------ | | RequestId | 是 | String | 请求 ID | | ConfigList | 是 | `Array` | 登录配置列表 | #### ConfigItem | 字段 | 必填 | 类型 | 说明 | | ---------- | ---- | ------ | ------------ | | Id | 是 | String | 配置 ID | | Platform | 是 | String | 平台类型 | | PlatformId | 是 | String | 平台 ID | | Status | 是 | String | 配置状态 | | UpdateTime | 是 | String | 配置更新时间 | | CreateTime | 是 | String | 配置创建时间 | ### 4. 示例代码 ```javascript import CloudBase from '@cloudbase/manager-node' const { env } = new CloudBase({ secretId: 'Your SecretId', secretKey: 'Your SecretKey', envId: 'Your envId' // 云开发环境ID,可在腾讯云云开发控制台获取 }) async function test() { const res = await env.getLoginConfigList() const { ConfigList } = res for (let config in ConfigList) { console.log(config) } } test() ``` ## createLoginConfig ### 1. 接口描述 接口功能:创建登录方式 接口声明:`createLoginConfig(platform, appId, appSecret): Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | --------------------------------------------------------------------------------------- | | platform | 是 | String | 平台 "WECHAT-OPEN" "WECHAT-PUBLIC" "QQ" "ANONYMOUS" | | appId | 是 | String | 第三方平台的 AppID 注意:如果是匿名登录方式(platform:ANONYMOUS),appId 填: anonymous | | appSecret | 否 | String | 第三方平台的 AppSecret,注意:如果是 匿名登录方式(platform:ANONYMOUS), appSecret 可不填 | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | ------- | | RequestId | 是 | String | 请求 ID | ### 4. 示例代码 ```javascript import CloudBase from '@cloudbase/manager-node' const { env } = new CloudBase({ secretId: 'Your SecretId', secretKey: 'Your SecretKey', envId: 'Your envId' // 云开发环境ID,可在腾讯云云开发控制台获取 }) async function test() { await env.createLoginConfig('WECHAT-OPEN', 'appId', 'appSecret') } test() ``` ## updateLoginConfig ### 1. 接口描述 接口功能:更新登录方式配置 接口声明:`updateLoginConfig(configId, status, appId, appSecret): Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | -------------------------------------------------------- | | configId | 是 | String | 配置的记录 ID | | status | 是 | String | ”ENABLE”, “DISABLE” | | appId | 是 | String | 第三方平台的 AppId,如果是匿名登录, appId 填: anonymous | | appSecret | 否 | String | 第三方平台的 AppSecret,如果是匿名登录,可不填该字段 | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | ------- | | RequestId | 是 | String | 请求 ID | ### 4. 示例代码 ```javascript import CloudBase from '@cloudbase/manager-node' const { env } = new CloudBase({ secretId: 'Your SecretId', secretKey: 'Your SecretKey', envId: 'Your envId' // 云开发环境ID,可在腾讯云云开发控制台获取 }) async function test() { const loginConfigRes = await env.getLoginConfigList() await env.updateLoginConfig( loginConfigRes.ConfigList[0].Id, 'ENABLE', 'appId', 'appSecret' ) } test() ``` ## createCustomLoginKeys ### 1. 接口描述 接口功能:创建自定义登录密钥 接口声明:`createCustomLoginKeys(): Promise` ### 2. 输入参数 无 ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | ---------- | ---- | ------ | ------- | | RequestId | 是 | String | 请求 ID | | KeyID | 是 | String | 密钥 ID | | PrivateKey | 是 | String | 私钥 | ### 4. 示例代码 ```javascript import CloudBase from '@cloudbase/manager-node' const { env } = new CloudBase({ secretId: 'Your SecretId', secretKey: 'Your SecretKey', envId: 'Your envId' // 云开发环境ID,可在腾讯云云开发控制台获取 }) async function test() { const res = await env.createCustomLoginKeys() const { KeyID, PrivateKey } = res console.log(KeyID, PrivateKey) } test() ``` --- ## 云函数 # 云函数 ## listFunctions :::danger 注意 此接口之后将会废弃,推荐使用 [getFunctionList()](#getFunctionList) ::: ### 1. 接口描述 接口功能:获取云函数列表 接口声明:`listFunctions(limit, offset): Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ------ | ---- | ------ | ---- | | limit | 否 | Number | 范围 | | offset | 否 | Number | 偏移 | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | ------------------------ | ---- | ------ | ------------ | | RequestID | 是 | String | 请求唯一标识 | | TotalCount | 是 | Number | 总数 | | Functions | 是 | Array | 函数列表 | | Functions[].FunctionId | 是 | String | 函数 ID | | Functions[].FunctionName | 是 | String | 函数名称 | | Functions[].Namespace | 是 | String | 命名空间 | | Functions[].Runtime | 是 | String | 运行时间 | | Functions[].AddTime | 是 | String | 创建时间 | | Functions[].ModTime | 是 | String | 修改时间 | ### 4. 示例代码 ```javascript import CloudBase from '@cloudbase/manager-node' const { functions } = new CloudBase({ secretId: 'Your SecretId', secretKey: 'Your SecretKey', envId: 'Your envId' // 云开发环境ID,可在腾讯云云开发控制台获取 }) async function test() { let res = await functions.listFunctions(20, 0) const { Functions } = res for(let function in Functions) { console.log(function) } } test() ``` ## getFunctionList ### 1. 接口描述 接口功能:获取云函数列表 接口声明:`getFunctionList(limit, offset): Promise` :::tip 提示 自 3.7.0 版本起支持此接口 ::: ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ------ | ---- | ------ | ---- | | limit | 否 | Number | 范围 | | offset | 否 | Number | 偏移 | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | ------------------------ | ---- | ------ | ------------ | | RequestID | 是 | String | 请求唯一标识 | | TotalCount | 是 | Number | 总数 | | Functions | 是 | Array | 函数列表 | | Functions[].FunctionId | 是 | String | 函数 ID | | Functions[].FunctionName | 是 | String | 函数名称 | | Functions[].Namespace | 是 | String | 命名空间 | | Functions[].Runtime | 是 | String | 运行时间 | | Functions[].AddTime | 是 | String | 创建时间 | | Functions[].ModTime | 是 | String | 修改时间 | | Functions[].Status | 是 | String | 函数状态 | | Functions[].StatusDesc | 是 | String | 函数状态详情 | | Functions[].Description | 是 | String | 函数描述 | ### 4. 示例代码 ```javascript import CloudBase from '@cloudbase/manager-node' const { functions } = new CloudBase({ secretId: 'Your SecretId', secretKey: 'Your SecretKey', envId: 'Your envId' // 云开发环境ID,可在腾讯云云开发控制台获取 }) async function test() { let res = await functions.getFunctionList(20, 0) const { Functions } = res for(let function in Functions) { console.log(function) } } test() ``` ## createFunction ### 1. 接口描述 接口功能:创建函数 接口声明:`createFunction(funcParam: ICreateFunctionParam): Promise` > ⚠️ 本接口从 2.0.0 版本后,请求参数由( func: ICloudFunction, functionRootPath: string, force: boolean, base64Code: string ) 转换为 (funcParam: ICreateFunctionParam),属于不兼容变更 ### 2. 输入参数 #### ICreateFunctionParam | 字段 | 必填 | 类型 | 说明 | | ---------------- | ---- | -------------- | ---------------------- | | func | 是 | ICloudFunction | 函数配置 | | functionRootPath | 否 | String | 用户本地函数文件目录 | | force | 是 | Boolean | 是否覆盖同名函数 | | base64Code | 否 | String | 函数文件的 base64 编码 | | codeSecret | 否 | String | 代码保护密钥 | | functionPath | 否 | String | 函数所在文件夹路径 | **注:如果只更新函数代码,请使用 `updateFunctionCode` 接口。** **注:如果存在同名云函数,并设置了 force 选项为 true,SDK 将会自动更新函数代码,更新函数配置并创建触发器。** **注:createFunction 支持多种方式创建函数:** 1. 用户直接指定函数文件夹的路径 2. 用户指定本地的存放函数文件夹的根目录 `functionRootPath`,根据 `functionRootPath + name` 确定函数文件路径 3. 用户将函数代码包压缩为 zip 文件后进行 base64 转码,传入 base64Code 参数 **注:`ICloudFunctionConfig` 为旧参数结构体** #### ICloudFunctionConfig | 字段 | 必填 | 类型 | 说明 | | ----------------- | ---- | ----------------------------- | -------------------------------------------------------------- | | timeout | 否 | Number | 函数超时时间 | | envVariables | 否 | Object | 包含环境变量的键值对对象 | | vpc | 否 | [IFunctionVPC](#ifunctionvpc) | 私有网络配置 | | runtime | 否 | String | 运行时环境配置,可选值: `Nodejs8.9, Nodejs10.15, Php7, Java8` | | installDependency | 否 | Boolean | 是否安装依赖,仅 Node.js 有效 | #### ICloudFunction | 字段 | 必填 | 类型 | 说明 | | ----------------- | ---- | -------------------------------------------------------- | --------------------------------------------------------------- | | name | 是 | String | 函数名称 | | timeout | 否 | Number | 函数超时时间 | | envVariables | 否 | Object | 包含环境变量的键值对对象 | | vpc | 否 | [IFunctionVPC](#IFunctionVPC) | 私有网络配置 | | runtime | 否 | String | 运行时环境配置,可选值: `Nodejs8.9, Nodejs10.15, Php7, Java8` | | installDependency | 否 | Boolean | 是否安装依赖,仅 Node.js 有效 | | triggers | 否 | Array of [ICloudFunctionTrigger](#ICloudFunctionTrigger) | | | handler | 否 | String | 函数入口 | | ignore | 否 | String 或 `Array` | 上传函数代码时忽略的文件,以 Glob 模式匹配 | | isWaitInstall | 否 | Boolean | 是否等待依赖安装完成 | | layers | 否 | `Array` | 函数要关联的 Layer 版本列表,Layer 会按照在列表中顺序依次覆盖。 | #### ILayerItem | 字段 | 必填 | 类型 | 说明 | | ------- | ---- | ------ | ---------- | | name | 是 | String | layer 名称 | | version | 是 | Number | 版本号 | **注:`handler` 函数处理入口,Node.js 项目默认值为 index.main,入口文件只能在根目录,如 Node.js 项目的 index.main,指向的是 index.js 文件的 main 方法** **注:如果使用在线安装依赖 Node.js 运行时 `runtime` 必须设置为 `Nodejs10.15`,且必须在入口文件同级目录设置 package.json,在线安装依赖暂不支持其他运行时** **如果不使用在线安装依赖,Node.js 运行时无需填 `runtime` (默认`Nodejs10.15`),但使用 Php 和 Java 则必填`runtime` 。** #### ICloudFunctionTrigger | 字段 | 必填 | 类型 | 说明 | | ------ | ---- | ------ | ----------------------------------------------------- | | name | 是 | String | 触发器名称 | | type | 是 | String | 触发器类型,可选值:timer | | config | 是 | String | 触发器配置,在定时触发器下,config 格式为 cron 表达式 | #### IFunctionVPC | 字段 | 必填 | 类型 | 说明 | | -------- | ---- | ------ | ----------- | | vpcId | 是 | String | VPC Id | | subnetId | 是 | String | VPC 子网 Id | > ⚠️ 请在测试时在云开发控制台确认函数创建并部署成功,有可能创建成功,`createFunction` 成功返回,但是部署失败,部署失败的原因通常为 `handler` 参数与源码包不对应。 ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | ------- | | RequestId | 是 | String | 请求 ID | ### 4. 示例代码 ```javascript import CloudBase from "@cloudbase/manager-node"; const { functions } = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId", // 云开发环境ID,可在腾讯云云开发控制台获取 }); async function test() { await functions.createFunction({ func: { // functions 文件夹下函数文件夹的名称,即函数名 name: "app", // 超时时间 timeout: 5, // 环境变量 envVariables: { key: "value", akey: "c", }, runtime: "Nodejs10.15", // 函数触发器,说明见文档: https://cloud.tencent.com/document/product/876/32314 triggers: [ { // name: 触发器的名字 name: "myTrigger", // type: 触发器类型,目前仅支持 timer (即定时触发器) type: "timer", // config: 触发器配置,在定时触发器下,config 格式为 cron 表达式 config: "0 0 2 1 * * *", }, ], layers: [ { version: 1, name: "layerName", }, ], }, functionRootPath: "", force: true, base64Code: "UEsDBAoAAAAAAOdCBU8AAAAAAAAAAAAAAAAFAAAAZGlzdC9QSwMEFAAIAAgAkhkBTwAAAAAAAAAAAAAAAAgAAABpbmRleC5qc2WNMQrDMBRDd59Cmx0IuUEy9wadXfdTQlT/Yv+UQMndmxZv0ST0kOTXKqhW5mTeOdleWqwOzzhnjAjylmw9kmaT7WcieYtp6TBO+DgcOlhVykB9BH8RUnHVwrvvTvi/do7begPtIeSV7NEqu/sCUEsHCLKdLCxuAAAAqAAAAFBLAwQUAAgACADnQgVPAAAAAAAAAAAAAAAADQAAAGRpc3QvZGlzdC56aXAL8GZm4WIAgedOrP5gBpRgBdIpmcUl+gFAJSIMHEA4SZIRRQkHUElmXkpqhV5WcWqvIddhAxHn8vlOs2U5djoafWebG/s92Cnkf9L/KQ4n784Wy7+o8mXCk+taK8KepdyzvBkXtYbvvEV6D8enaTm2k9Imv01XquzOfGng98NCxioi9JRDLUu9YFDh1UO73/v92F/Wd7uK+a3ik6lvLmrt/s0U4M3OsWmujk4e0AUrgBjhRnRv8MK8AfKLXlVmAQBQSwcITXynOsAAAADyAAAAUEsBAi0DCgAAAAAA50IFTwAAAAAAAAAAAAAAAAUAAAAAAAAAAAAQAO1BAAAAAGRpc3QvUEsBAi0DFAAIAAgAkhkBT7KdLCxuAAAAqAAAAAgAAAAAAAAAAAAgAKSBIwAAAGluZGV4LmpzUEsBAi0DFAAIAAgA50IFT018pzrAAAAA8gAAAA0AAAAAAAAAAAAgAKSBxwAAAGRpc3QvZGlzdC56aXBQSwUGAAAAAAMAAwCkAAAAwgEAAAAA", }); } test(); ``` ## updateFunctionCode ### 1. 接口描述 接口功能:更新云函数代码 接口声明:`updateFunctionCode(funcParam: IUpdateFunctionCodeParam): Promise` > ⚠️ 本接口从 2.0.0 版本后,请求参数由( func: ICloudFunction, functionRootPath: string, base64Code: string ) 转换为 (funcParam: IUpdateFunctionCodeParam),属于不兼容变更 ### 2. 输入参数 #### IUpdateFunctionCodeParam | 字段 | 必填 | 类型 | 说明 | | ---------------- | ---- | -------------- | ---------------------- | | func | 是 | ICloudFunction | 函数配置 | | functionRootPath | 否 | String | 用户本地函数文件目录 | | base64Code | 否 | String | 函数文件的 base64 编码 | | codeSecret | 否 | String | 函数文件的 base64 编码 | [ICloudFunction 结构体](#ICloudFunction) ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | ------- | | RequestId | 是 | String | 请求 ID | ### 4. 示例代码 ```javascript import CloudBase from "@cloudbase/manager-node"; const { functions } = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId", // 云开发环境ID,可在腾讯云云开发控制台获取 }); async function test() { let res = await functions.updateFunctionCode({ func: { // functions 文件夹下函数文件夹的名称,即函数名 name: "app", }, functionRootPath: "", base64Code: "UEsDBAoAAAAAAOdCBU8AAAAAAAAAAAAAAAAFAAAAZGlzdC9QSwMEFAAIAAgAkhkBTwAAAAAAAAAAAAAAAAgAAABpbmRleC5qc2WNMQrDMBRDd59Cmx0IuUEy9wadXfdTQlT/Yv+UQMndmxZv0ST0kOTXKqhW5mTeOdleWqwOzzhnjAjylmw9kmaT7WcieYtp6TBO+DgcOlhVykB9BH8RUnHVwrvvTvi/do7begPtIeSV7NEqu/sCUEsHCLKdLCxuAAAAqAAAAFBLAwQUAAgACADnQgVPAAAAAAAAAAAAAAAADQAAAGRpc3QvZGlzdC56aXAL8GZm4WIAgedOrP5gBpRgBdIpmcUl+gFAJSIMHEA4SZIRRQkHUElmXkpqhV5WcWqvIddhAxHn8vlOs2U5djoafWebG/s92Cnkf9L/KQ4n784Wy7+o8mXCk+taK8KepdyzvBkXtYbvvEV6D8enaTm2k9Imv01XquzOfGng98NCxioi9JRDLUu9YFDh1UO73/v92F/Wd7uK+a3ik6lvLmrt/s0U4M3OsWmujk4e0AUrgBjhRnRv8MK8AfKLXlVmAQBQSwcITXynOsAAAADyAAAAUEsBAi0DCgAAAAAA50IFTwAAAAAAAAAAAAAAAAUAAAAAAAAAAAAQAO1BAAAAAGRpc3QvUEsBAi0DFAAIAAgAkhkBT7KdLCxuAAAAqAAAAAgAAAAAAAAAAAAgAKSBIwAAAGluZGV4LmpzUEsBAi0DFAAIAAgA50IFT018pzrAAAAA8gAAAA0AAAAAAAAAAAAgAKSBxwAAAGRpc3QvZGlzdC56aXBQSwUGAAAAAAMAAwCkAAAAwgEAAAAA", }); console.log(res); } test(); ``` ## updateFunctionConfig ### 1. 接口描述 接口功能:更新云函数配置 接口声明:`updateFunctionConfig(funcParam: ICloudFunction): Promise` > ⚠️ 本接口从 2.0.0 版本后,请求参数由( name: string, config: ICloudFunctionConfig ) 转换为 (funcParam: ICloudFunction),属于不兼容变更 ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | -------------- | -------- | | funcParam | 是 | ICloudFunction | 函数配置 | [ICloudFunction 结构体](#ICloudFunction) ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | ------- | | RequestId | 是 | String | 请求 ID | ### 4. 示例代码 ```javascript import CloudBase from "@cloudbase/manager-node"; const { functions } = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId", // 云开发环境ID,可在腾讯云云开发控制台获取 }); async function test() { let res = await functions.updateFunctionConfig({ name: "app", timeout: 6, }); console.log(res); } test(); ``` ## deleteFunction ### 1. 接口描述 接口功能:删除云函数 接口声明:`deleteFunction(name: string): Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | -------------------------------------------- | | name | 是 | String | 函数名称 | | qualifier | 否 | String | 需要删除的版本号,不填默认删除函数下全部版本 | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | ------- | | RequestId | 是 | String | 请求 ID | ### 4. 示例代码 ```javascript import CloudBase from "@cloudbase/manager-node"; const { functions } = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId", // 云开发环境ID,可在腾讯云云开发控制台获取 }); async function test() { await functions.deleteFunction("functionName", "1"); } test(); ``` ## getFunctionDetail ### 1. 接口描述 接口功能:获取云函数详情 接口声明:`getFunctionDetail(name: string, codeSecret?: string): Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ---------- | ---- | ------ | ------------ | | name | 是 | String | 函数名称 | | codeSecret | 否 | String | 代码保护密钥 | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | ----------------------------- | ---- | ----------------- | ------------------ | | RequestId | 是 | String | 请求唯一标识 | | FunctionName | 是 | String | 函数名称 | | Namespace | 是 | String | 命名空间 | | Runtime | 是 | String | 运行时 | | Handler | 是 | String | 函数入口 | | Description | 是 | String | 函数的描述信息 | | ModTime | 是 | String | 函数修改时间 | | Environment | 是 | Object | 函数的环境变量 | | Environment.Variables | 是 | Array | 环境变量数组 | | Environment.Variables[].Key | 是 | String | 变量的 Key | | Environment.Variables[].Value | 是 | String | 变量的 Value | | MemorySize | 是 | Number | 函数的最大可用内存 | | Timeout | 是 | Number | 函数的超时时间 | | CodeInfo | 是 | String | 函数代码 | | Triggers | 是 | `Array` | 函数的触发器列表 | #### ITrigger | 字段 | 必填 | 类型 | 说明 | | --------------- | ---- | --------- | ------------------ | | Type | 是 | String | 触发器类型 | | TriggerName | 是 | String | 触发器名称 | | TriggerDesc | 是 | String | 触发器详细配置 | | ModTime | 是 | Timestamp | 触发器最后修改时间 | | AddTime | 是 | Timestamp | 触发器创建时间 | | AvailableStatus | 是 | String | 触发器状态 | | Enable | 是 | Number | 使能开关 | | CustomArgument | 是 | String | 客户自定义参数 | ### 4. 示例代码 ```javascript import CloudBase from "@cloudbase/manager-node"; const { functions } = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId", // 云开发环境ID,可在腾讯云云开发控制台获取 }); async function test() { let res = await functions.getFunctionDetail("functionName"); console.log(res); // 输出云函数详情 } test(); ``` ## invokeFunction ### 1. 接口描述 接口功能:调用云函数 接口声明:`invokeFunction(name: string, params: object): Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ------------ | ---- | ------ | ----------------------------- | | functionName | 是 | String | 函数名称 | | params | 否 | Object | 可选参数 用户调用函数时的入参 | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | ----------------- | ---- | ------ | --------------------------------------------------- | | RequestId | 是 | String | 请求唯一标识 | | FunctionRequestId | 是 | String | 此次函数执行的 ID | | Duration | 是 | Number | 表示执行函数的耗时,单位是毫秒,异步调用返回为空 | | BillDuration | 是 | Number | 表示函数的计费耗时,单位是毫秒,异步调用返回为空 | | MemUsage | 是 | Number | 执行函数时的内存大小,单位为 Byte,异步调用返回为空 | | InvokeResult | 是 | Number | 0 为正确,异步调用返回为空 | | RetMsg | 是 | String | 表示执行函数的返回,异步调用返回为空 | | ErrMsg | 是 | String | 表示执行函数的错误返回信息,异步调用返回为空 | | Log | 是 | String | 表示执行过程中的日志输出,异步调用返回为空 | ### 4. 示例代码 ```javascript import CloudBase from "@cloudbase/manager-node"; const { functions } = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId", // 云开发环境ID,可在腾讯云云开发控制台获取 }); async function test() { const res = await functions.invokeFunction("app", { a: 1, }); console.log(res.RetMsg); } test(); ``` ## getFunctionLogs :::danger 注意 此接口已废弃 ::: :::danger 注意 此接口将不再返回具体的日志详情,请基于接口返回的 requestId,调用 [searchClsLog](/api-reference/manager/node/clsLog#ri-zhi-cha-xun) 函数查询日志详情。 ::: ### 1. 接口描述 接口功能:获取云函数调用日志 接口声明:`getFunctionLogs(options: IFunctionLogOptions): Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ------- | ---- | ------------------------------------------- | ------------ | | options | 是 | [IFunctionLogOptions](#ifunctionlogoptions) | 日志查询选项 | #### IFunctionLogOptions | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | --------------------------------------------------------------------------------- | | name | 是 | String | 函数名词 | | offset | 否 | Number | 数据的偏移量,Offset+Limit 不能大于 10000 | | limit | 否 | Number | 返回数据的长度,Offset+Limit 不能大于 10000 | | order | 否 | String | 以升序还是降序的方式对日志进行排序,可选值 desc 和 asc | | orderBy | 否 | String | 根据某个字段排序日志,支持以下字段:function_name, duration, mem_usage, start_time | | startTime | 否 | String | 查询的具体日期,例如:2017-05-16 20:00:00,只能与 EndTime 相差一天之内 | | endTime | 否 | String | 查询的具体日期,例如:2017-05-16 20:59:59,只能与 StartTime 相差一天之内 | | requestId | 否 | String | 执行该函数对应的 requestId | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | --------------------- | ---- | ------ | ----------------------------------------------------------- | | RequestId | 是 | String | 请求唯一标识 | | TotalCount | 是 | String | 函数日志的总数 | | Data[] | 是 | Array | 运行函数的返回 | | Data[].RequestId | 是 | String | 执行该函数对应的 requestId | | Data[].FunctionName | 是 | String | 函数的名称 | | Data[].RetCode | 是 | Number | 函数执行结果,如果是 0 表示执行成功,其他值表示失败 | | Data[].InvokeFinished | 是 | Number | 函数调用是否结束,如果是 1 表示执行结束,其他值表示调用异常 | | Data[].StartTime | 是 | String | 函数开始执行时的时间点 | | Data[].Duration | 是 | Number | 表示执行函数的耗时,单位是毫秒,异步调用返回为空 | | Data[].BillDuration | 是 | Number | 表示函数的计费耗时,单位是毫秒,异步调用返回为空 | | Data[].MemUsage | 是 | Number | 执行函数时的内存大小,单位为 Byte,异步调用返回为空 | | Data[].RetMsg | 是 | String | 表示执行函数的返回,异步调用返回为空 | ### 4. 示例代码 ```javascript import CloudBase from "@cloudbase/manager-node"; const manager = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId", // 云开发环境ID,可在腾讯云云开发控制台获取 }); const { functions } = manager; async function test() { const logs = await functions.getFunctionLogs({ name: "app" }); const { Data } = logs; for (let item in Data) { console.log(item.RequestId); // 基于 requestId 查 cls 日志 const clsLogRes = await manager.commonService().call({ Action: "SearchClsLog", Param: { EnvId: cloudBaseConfig.envId, StartTime: "2021-06-11 11:06:20", // 开始时间 EndTime: "2021-06-30 11:06:20", // 截止时间 Limit: 100, Sort: "asc", QueryString: `requestId:${item.RequestId}`, }, }); console.log("clsLogRes", clsLogRes); } } test(); ``` ## getFunctionLogsV2 :::tip 注意 此接口不返回具体的日志详情,请基于接口返回的 LogList 数组中单条日志的 RequestId,调用 [getFunctionLogDetail](#getFunctionLogDetail) 函数查询日志详情。 ::: ### 1. 接口描述 接口功能:获取云函数调用日志列表 接口声明:`getFunctionLogsV2(options: IFunctionLogOptionsV2): Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ------- | ---- | ------------------------------------------- | ------------ | | options | 是 | [IFunctionLogOptions](#ifunctionlogoptions) | 日志查询选项 | #### IFunctionLogOptionsV2 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | --------------------------------------------------------------------------------- | | name | 是 | String | 函数名词 | | offset | 否 | Number | 数据的偏移量,Offset+Limit 不能大于 10000 | | limit | 否 | Number | 返回数据的长度,Offset+Limit 不能大于 10000 | | startTime | 否 | String | 查询的具体日期,例如:2017-05-16 20:00:00,只能与 EndTime 相差一天之内 | | endTime | 否 | String | 查询的具体日期,例如:2017-05-16 20:59:59,只能与 StartTime 相差一天之内 | | requestId | 否 | String | 执行该函数对应的 requestId | | qualifier | 否 | String | 函数版本,默认为 $LATEST | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | --------------------- | ---- | ------ | ----------------------------------------------------------- | | RequestId | 是 | String | 请求唯一标识 | | LogList[] | 是 | Array | 运行函数的返回 | | Data[].RequestId | 是 | String | 函数日志请求ID | | Data[].RetryNum | 是 | String | 函数日志重试ID | | Data[].RetCode | 是 | Number | 函数执行状态码,200/500 | | Data[].StartTime | 是 | String | 函数日志开始时间点 | ### 4. 示例代码 ```javascript import CloudBase from "@cloudbase/manager-node"; const manager = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId", // 云开发环境ID,可在腾讯云云开发控制台获取 }); const { functions } = manager; async function test() { const logs = await functions.getFunctionLogs({ name: "app", startTime: "2025-07-19 09:00:00", endTime: "2025-07-19 19:00:00" }); const { LogList } = logs; for (let item in LogList) { // console.log(item.RequestId); logId = item.RequestId // 基于 requestId 查 cls 日志 const logDetail = await functions.getFunctionLogDetail({ startTime: "2025-07-19 09:00:00", logRequestId: logId, endTime: "2025-07-19 19:00:00" }) } } test(); ``` ## getFunctionLogDetail ### 1. 接口描述 接口功能:根据 getFunctionLogsV2 中返回的日志 requestId 查询日志详情 接口声明:`getFunctionLogDetail(options: IFunctionLogDetailOptions): Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ------- | ---- | ------------------------------------------- | ------------ | | options | 是 | [IFunctionLogDetailOptions](#IFunctionLogDetailOptions) | 日志详情查询选项 | #### IFunctionLogDetailOptions | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | --------------------------------------------------------------------------------- | | startTime | 否 | String | 查询的具体日期,例如:2017-05-16 20:00:00,只能与 EndTime 相差一天之内 | | endTime | 否 | String | 查询的具体日期,例如:2017-05-16 20:59:59,只能与 StartTime 相差一天之内 | | requestId | 否 | String | 执行该函数对应的 requestId | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | --------------------- | ---- | ------ | ----------------------------------------------------------- | | StartTime | 否 | String | 调用时间 | | Duration | 否 | Number | 调用耗时 | | MemUsage | 否 | Number | 内存占用 | | LogJson | 否 | String | 日志内容 | | ListOver | 否 | Boolean | 分页标志 | | Context | 否 | String | 分页游标 | ### 4. 示例代码 ```javascript import CloudBase from "@cloudbase/manager-node"; const manager = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId", // 云开发环境ID,可在腾讯云云开发控制台获取 }); const { functions } = manager; async function test() { const logs = await functions.getFunctionLogs({ name: "app", startTime: "2025-07-19 09:00:00", endTime: "2025-07-19 19:00:00" }); const { LogList } = logs; for (let item in LogList) { // console.log(item.RequestId); logId = item.RequestId // 基于 requestId 查 cls 日志 const logDetail = await functions.getFunctionLogDetail({ startTime: "2025-07-19 09:00:00", logRequestId: logId, endTime: "2025-07-19 19:00:00" }) } } test(); ``` ## copyFunction ### 1. 接口描述 接口功能:拷贝云函数 接口声明:`copyFunction(name, newFunctionName, targetEnvId, force): Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | --------------- | ---- | ------- | --------------------------------- | | name | 是 | String | 原函数名 | | newFunctionName | 是 | String | 新函数名 | | targetEnvId | 是 | String | 新环境 ID(跨环境拷贝函数时填写) | | force | 否 | Boolean | 是否覆盖同名函数 | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | ------- | | RequestId | 是 | String | 请求 ID | ### 4. 示例代码 ```javascript import CloudBase from "@cloudbase/manager-node"; const { functions } = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId", // 云开发环境ID,可在腾讯云云开发控制台获取 }); async function test() { await functions.copyFunction(); } test(); ``` ## createFunctionTriggers ### 1. 接口描述 接口功能:创建云函数触发器 接口声明:`createFunctionTriggers(name: string, triggers: ICloudFunctionTrigger[]): Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | -------- | ---- | ----------------------------------------------- | -------------- | | name | 是 | String | 函数名 | | triggers | 是 | [ICloudFunctionTrigger](#icloudfunctiontrigger) | 触发器配置数组 | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | ------- | | RequestId | 是 | String | 请求 ID | ### 4. 示例代码 ```javascript import CloudBase from "@cloudbase/manager-node"; const { functions } = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId", // 云开发环境ID,可在腾讯云云开发控制台获取 }); async function test() { await functions.createFunctionTriggers("app", [ { // name: 触发器的名字 name: "newTrigger", // type: 触发器类型,目前仅支持 timer (即定时触发器) type: "timer", // config: 触发器配置,在定时触发器下,config 格式为 cron 表达式 config: "0 0 2 1 * * *", }, ]); } test(); ``` ## deleteFunctionTrigger ### 1. 接口描述 接口功能:删除云函数触发器 接口声明:`deleteFunctionTrigger(name: string, triggerName: string): Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ----------- | ---- | ------ | -------- | | name | 是 | String | 函数名 | | triggerName | 是 | String | 触发器名 | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | ------- | | RequestId | 是 | String | 请求 ID | ### 4. 示例代码 ```javascript import CloudBase from "@cloudbase/manager-node"; const { functions } = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId", // 云开发环境ID,可在腾讯云云开发控制台获取 }); async function test() { await functions.deleteFunctionTrigger("app", "newTrigger"); } test(); ``` ## getFunctionDownloadUrl ### 1. 接口描述 接口功能:获取云函数代码下载链接 接口声明:`getFunctionDownloadUrl(functionName:string, codeSecret?: string): Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ------------ | ---- | ------ | ------------ | | functionName | 是 | String | 函数名 | | codeSecret | 否 | String | 代码保护密钥 | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | ---------- | ---- | ------ | ---------------- | | RequestID | 是 | String | 请求唯一标识 | | Url | 是 | String | 函数代码下载链接 | | CodeSha256 | 是 | String | 函数的 SHA256 编 | ### 4. 示例代码 ```javascript import CloudBase from "@cloudbase/manager-node"; const { functions } = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId", // 云开发环境ID,可在腾讯云云开发控制台获取 }); async function test() { const res = await functions.getFunctionDownloadUrl("sum"); const { Url } = res; console.log(Url); } test(); ``` ## updateFunctionIncrementalCode ### 1. 接口描述 接口功能:增量上传云函数代码 接口声明:`updateFunctionIncrementalCode(funcParam: IUpdateFunctionIncrementalCodeParam): Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------------------------------------------ | -------------- | | funcParam | 是 | IUpdateFunctionIncrementalCodeParam 结构体 | 增量更新函数项 | #### IUpdateFunctionIncrementalCodeParam 结构体 | 字段 | 必填 | 类型 | 说明 | | ---------------- | ---- | --------------- | ------------------------------------------------------------------------------------- | | func | 是 | ICloudFunction | 函数配置项,针对增量更新,目前只支持 name,runTime 字段设置 d | | functionRootPath | 是 | String | 用户本地函数文件目录 | | deleteFiles | 否 | `Array` | 要删除的文件,目录的列表,使用相对路径, 删除目录时必须以/结尾 | | addFiles | 否 | String | 新增或修改的文件/目录 对应的 glob 匹配模式,目前支持 新增或修改 单个文件 或单个文件夹 | > ⚠️ 填写路径时请注意 Linux 及 Windows 下的区别('/'与'\\') > ⚠️ 增量更新 package.json 并不会触发依赖安装 ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | ------- | | RequestId | 是 | String | 请求 ID | ### 4. 示例代码 ```javascript import CloudBase from "@cloudbase/manager-node"; const { functions } = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId", // 云开发环境ID,可在腾讯云云开发控制台获取 }); async function test() { // 本地存在sum 函数文件夹,新增test/index.js 文件 (index.js相对路径为 sum/test/index.js) await functions.updateFunctionIncrementalCode({ func: { name: "sum", runTime: "Nodejs10.15", }, addFiles: "test/index.js", }); // 本地存在sum 函数文件夹,新增test/目录 (test相对路径为 sum/test/) await functions.updateFunctionIncrementalCode({ func: { name: "sum", runTime: "Nodejs10.15", }, addFiles: "test/*", // 匹配test目录下所有文件, 这里采用 glob 匹配模式 而非相对路径 }); // 本地存在sum 函数文件夹,删除test/index.js (index.js相对路径为 sum/test/index.js) await functions.updateFunctionIncrementalCode({ func: { name: "sum", runTime: "Nodejs10.15", }, deleteFiles: ["test/index.js"], }); // 本地存在sum 函数文件夹,删除test/ 目录 (test相对路径为 sum/test/) await functions.updateFunctionIncrementalCode({ func: { name: "sum", runTime: "Nodejs10.15", }, deleteFiles: ["test/"], // 删除目录时必须以 /结尾 }); } test(); ``` ## createLayer ### 1. 接口描述 接口功能:发布层版本 接口声明:`createLayer(options: IFunctionLayerOptions): Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ------- | ---- | ---------------------------- | ------ | | options | 是 | IFunctionLayerOptions 结构体 | 请求项 | #### IFunctionLayerOptions 结构体 | 字段 | 必填 | 类型 | 说明 | | ------------- | ---- | --------------- | ----------------------------------------------------------------------------------------------------------------------------------- | | contentPath | 否 | String | 可以指定 contentPath 为文件夹 或者 ZIP 文件路径 | | base64Content | 否 | String | 文件的 base64 编码 | | name | 是 | String | 层名称,支持 26 个英文字母大小写、数字、连接符和下划线,第一个字符只能以字母开头,最后一个字符不能为连接符或者下划线,名称长度 1-64 | | runtimes | 是 | `Array` | 层适用的运行时,可多选,可选的值对应函数的 Runtime 可选值。 | | description | 否 | String | 层版本描述 | | licenseInfo | 否 | String | 层的软件许可证 | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | ------------ | ---- | ------ | -------- | | RequestId | 是 | String | 请求 ID | | LayerVersion | 是 | Number | 层版本号 | ### 4. 示例代码 ```javascript import CloudBase from "@cloudbase/manager-node"; const { functions } = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId", // 云开发环境ID,可在腾讯云云开发控制台获取 }); async function test() { const res = await functions.createLayer({ name: layerName, contentPath: "./test/functions/luke/", runtimes: ["Nodejs10.15"], }); console.log(res.LayerVersion); } test(); ``` ## deleteLayerVersion ### 1. 接口描述 接口功能:删除层版本 接口声明:`deleteLayerVersion(options: ILayerOptions): Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ------- | ---- | -------------------- | ------ | | options | 是 | ILayerOptions 结构体 | 请求项 | #### ILayerOptions 结构体 | 字段 | 必填 | 类型 | 说明 | | ------- | ---- | ------ | ------ | | name | 是 | String | 层名称 | | version | 是 | Number | 版本号 | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | ------- | | RequestId | 是 | String | 请求 ID | ### 4. 示例代码 ```javascript import CloudBase from "@cloudbase/manager-node"; const { functions } = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId", // 云开发环境ID,可在腾讯云云开发控制台获取 }); async function test() { const res = await functions.deleteLayerVersion({ name: layerName, version: 1, }); console.log(res.RequestId); } test(); ``` ## listLayerVersions ### 1. 接口描述 接口功能:获取层版本列表 接口声明:`listLayerVersions(options: IVersionListOptions): Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ------- | ---- | -------------------------- | ------ | | options | 是 | IVersionListOptions 结构体 | 请求项 | #### IVersionListOptions 结构体 | 字段 | 必填 | 类型 | 说明 | | -------- | ---- | --------------- | ------ | | name | 是 | String | 层名称 | | runtimes | 否 | `Array` | 版本号 | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | ------------- | ---- | -------------------------- | ---------- | | RequestId | 是 | String | 请求 ID | | LayerVersions | 是 | `Array` | 文件层详情 | #### ILayerVersionInfo 结构体 | 字段 | 必填 | 类型 | 说明 | | ------------------ | ---- | --------------- | ------------------------------------------------------------------------------------------- | | CompatibleRuntimes | 是 | `Array` | 版本适用的运行时 | | AddTime | 是 | String | 创建时间 | | Description | 是 | String | 版本描述 | | LicenseInfo | 是 | String | 许可证信息 | | LayerVersion | 是 | Number | 版本号 | | LayerName | 是 | String | 层名称 | | Status | 是 | String | 层的具体版本当前状态, Active 正常, Publishing 发布中,PublishFailed 发布失败,Deleted 已删除 | ### 4. 示例代码 ```javascript import CloudBase from "@cloudbase/manager-node"; const { functions } = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId", // 云开发环境ID,可在腾讯云云开发控制台获取 }); async function test() { const res = await functions.listLayerVersions({ name: layerName, }); console.log(res.LayerVersions); } test(); ``` ## listLayers ### 1. 接口描述 接口功能:获取层列表 接口声明:`listLayers(options: ILayerListOptions): Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ------- | ---- | ------------------------ | ------ | | options | 是 | ILayerListOptions 结构体 | 请求项 | #### ILayerListOptions 结构体 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | ---------------------- | | offset | 否 | Number | 偏移 | | limit | 否 | Number | 限制数 | | runtime | 否 | String | 适配的运行时 | | searchKey | 否 | String | 查询 key,模糊匹配名称 | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | ---------- | ---- | -------------------------- | ---------- | | RequestId | 是 | String | 请求 ID | | TotalCount | 是 | Number | 层总数 | | Layers | 是 | `Array` | 文件层详情 | #### ILayerVersionInfo 结构体 | 字段 | 必填 | 类型 | 说明 | | ------------------ | ---- | --------------- | ------------------------------------------------------------------------------------------- | | CompatibleRuntimes | 是 | `Array` | 版本适用的运行时 | | AddTime | 是 | String | 创建时间 | | Description | 是 | String | 版本描述 | | LicenseInfo | 是 | String | 许可证信息 | | LayerVersion | 是 | Number | 版本号 | | LayerName | 是 | String | 层名称 | | Status | 是 | String | 层的具体版本当前状态, Active 正常, Publishing 发布中,PublishFailed 发布失败,Deleted 已删除 | ### 4. 示例代码 ```javascript import CloudBase from "@cloudbase/manager-node"; const { functions } = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId", // 云开发环境ID,可在腾讯云云开发控制台获取 }); async function test() { const res = await functions.listLayers({}); console.log(res.Layers); } test(); ``` ## getLayerVersion ### 1. 接口描述 接口功能:获取层版本详细信息 接口声明:`getLayerVersion(options: ILayerOptions): Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ------- | ---- | -------------------- | ------ | | options | 是 | ILayerOptions 结构体 | 请求项 | #### ILayerOptions 结构体 | 字段 | 必填 | 类型 | 说明 | | ------- | ---- | ------ | ------ | | name | 是 | String | 层名称 | | version | 是 | Number | 版本号 | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | ------------------ | ---- | --------------- | ------------------------------------------------------------------------------------------- | | RequestId | 是 | String | 请求 ID | | CompatibleRuntimes | 是 | `Array` | 适配的运行时 | | CodeSha256 | 是 | String | 层中版本文件的 SHA256 编码 | | Location | 是 | String | 层中版本文件的下载地址 | | AddTime | 是 | String | 版本的创建时间 | | Description | 是 | String | 版本的描述 | | LicenseInfo | 是 | String | 许可证信息 | | LayerVersion | 是 | Number | 版本号 | | LayerName | 是 | String | 层名称 | | Status | 是 | String | 层的具体版本当前状态, Active 正常, Publishing 发布中,PublishFailed 发布失败,Deleted 已删除 | ### 4. 示例代码 ```javascript import CloudBase from "@cloudbase/manager-node"; const { functions } = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId", // 云开发环境ID,可在腾讯云云开发控制台获取 }); async function test() { const res = await functions.getLayerVersion({ name: layerName, version: 2 }); console.log(res.LayerVersion); } test(); ``` ## setProvisionedConcurrencyConfig ### 1. 接口描述 接口功能:设置函数预置并发 接口声明:`setProvisionedConcurrencyConfig(options: ISetProvisionedConcurrencyConfig): Promise` ### 2. 输入参数 #### ISetProvisionedConcurrencyConfig 结构体 | 字段 | 必填 | 类型 | 说明 | | -------------------------------- | ---- | ------ | ------------------ | | functionName | 是 | String | 函数名 | | qualifier | 是 | String | 函数版本名 | | versionProvisionedConcurrencyNum | 是 | Number | 当前版本预置并发数 | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | ------- | | RequestId | 是 | String | 请求 ID | ### 4. 示例代码 ```javascript import CloudBase from "@cloudbase/manager-node"; const { functions } = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId", // 云开发环境ID,可在腾讯云云开发控制台获取 }); async function test() { const setProvisionedConcurrencyConfigRes = await functions.setProvisionedConcurrencyConfig({ functionName: "sum", qualifier: "1", // 版本1 versionProvisionedConcurrencyNum: 10, // 设置10并发 }); console.log(setProvisionedConcurrencyConfigRes); } test(); ``` ## getProvisionedConcurrencyConfig ### 1. 接口描述 接口功能:查询函数预置并发 接口声明:`getProvisionedConcurrencyConfig(options: IGetProvisionedConcurrencyConfig): Promise` ### 2. 输入参数 #### IGetProvisionedConcurrencyConfig 结构体 | 字段 | 必填 | 类型 | 说明 | | ------------ | ---- | ------ | -------------------------------------------------- | | functionName | 是 | String | 函数名 | | qualifier | 否 | String | 函数版本名,不填则查询该函数所有版本的预置并发信息 | ### 3. 返回结果 | 字段 | 类型 | 说明 | | ------------------------- | ----------------------------------------------- | ------------------------------ | | RequestId | String | 请求 ID | | UnallocatedConcurrencyNum | Number | 该函数剩余可配置的预置并发数。 | | Allocated | Array<IVersionProvisionedConcurrencyInfo> | 函数已预置的并发配置详情。 | #### IVersionProvisionedConcurrencyInfo | 字段 | 类型 | 说明 | | ---------------------------------- | ------ | --------------------------------------------------------------------------------- | | AllocatedProvisionedConcurrencyNum | Number | 设置的预置并发数。 | | AvailableProvisionedConcurrencyNum | Number | 已完成设置的并发数 | | Status | String | 预置任务状态,Done 表示已完成,InProgress 表示进行中,Failed 表示部分或全部失败。 | | StatusReason | String | 任务状态说明 | | Qualifier | String | 版本号 | ### 4. 示例代码 ```javascript import CloudBase from "@cloudbase/manager-node"; const { functions } = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId", // 云开发环境ID,可在腾讯云云开发控制台获取 }); async function test() { const getProvisionedConcurrencyConfigRes = await functions.getProvisionedConcurrencyConfig({ functionName: "sum", qualifier: "1", // 版本1 }); console.log(getProvisionedConcurrencyConfigRes); } test(); ``` ## deleteProvisionedConcurrencyConfig ### 1. 接口描述 接口功能:删除函数预置并发 接口声明:`deleteProvisionedConcurrencyConfig(options: IDeleteProvisionedConcurrencyConfig): Promise` ### 2. 输入参数 #### IDeleteProvisionedConcurrencyConfig 结构体 | 字段 | 必填 | 类型 | 说明 | | ------------ | ---- | ------ | -------------------------------------------------- | | functionName | 是 | String | 函数名 | | qualifier | 是 | String | 函数版本名,不填则查询该函数所有版本的预置并发信息 | ### 3. 返回结果 | 字段 | 类型 | 说明 | | --------- | ------ | ------- | | RequestId | String | 请求 ID | ### 4. 示例代码 ```javascript import CloudBase from "@cloudbase/manager-node"; const { functions } = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId", // 云开发环境ID,可在腾讯云云开发控制台获取 }); async function test() { const deleteProvisionedConcurrencyConfigRes = await functions.deleteProvisionedConcurrencyConfig({ functionName: "sum", qualifier: "1", // 版本1 }); console.log(deleteProvisionedConcurrencyConfigRes); } test(); ``` ## publishVersion ### 1. 接口描述 接口功能:发布函数新版本 接口声明:`publishVersion(options: IPublishVersionParams): Promise` ### 2. 输入参数 #### IPublishVersionParams 结构体 | 字段 | 必填 | 类型 | 说明 | | ------------ | ---- | ------ | -------- | | functionName | 是 | String | 函数名 | | description | 否 | String | 版本描述 | ### 3. 返回结果 | 字段 | 类型 | 说明 | | --------------- | ------ | -------------- | | RequestId | String | 请求 ID | | FunctionVersion | String | 函数版本 | | CodeSize | Number | 代码大小 | | MemorySize | Number | 最大可用内存 | | Handler | String | 函数入口 | | Timeout | Number | 函数的超时时间 | | Runtime | String | 函数的运行环境 | | Namespace | String | 函数的命名空间 | ### 4. 示例代码 ```javascript import CloudBase from "@cloudbase/manager-node"; const { functions } = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId", // 云开发环境ID,可在腾讯云云开发控制台获取 }); async function test() { const createNewVersionRes = await functions.publishVersion({ functionName: "sum", description: "test", // 给sum函数创建新版本,描述为test }); console.log(createNewVersionRes); } test(); ``` ## listVersionByFunction ### 1. 接口描述 接口功能:查询函数版本列表 接口声明:`listVersionByFunction(options: IListFunctionVersionParams): Promise` ### 2. 输入参数 #### IListFunctionVersionParams 结构体 | 字段 | 必填 | 类型 | 说明 | | ------------ | ---- | ------ | ----------------------------------------------------------- | | functionName | 是 | String | 函数名 | | offset | 否 | Number | 数据偏移量,默认值为 0 | | limit | 否 | Number | 返回数据长度,默认值为 20 | | order | 否 | Number | 以升序还是降序的方式返回结果,可选值 ASC 和 DESC | | orderBy | 否 | Number | 根据哪个字段进行返回结果排序,支持以下字段:AddTime, ModTime | ### 3. 返回结果 | 字段 | 类型 | 说明 | | --------------- | ----------------------------- | -------------- | | RequestId | String | 请求 ID | | TotalCount | String | 函数版本总数。 | | FunctionVersion | Array<String> | 函数版本名列表 | | Versions | Array<IFunctionVersion> | 函数版本列表。 | #### IFunctionVersion | 字段 | 类型 | 说明 | | ----------- | ------ | ------------ | | Version | String | 函数版本名 | | Description | String | 版本描述信息 | | AddTime | String | 创建时间 | | ModTime | String | 修改时间 | | Status | String | 版本状态 | ### 4. 示例代码 ```javascript import CloudBase from "@cloudbase/manager-node"; const { functions } = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId", // 云开发环境ID,可在腾讯云云开发控制台获取 }); async function test() { const functionVersions = await functions.listVersionByFunction({ functionName: "sum", }); console.log(functionVersions); } test(); ``` ## updateFunctionAliasConfig ### 1. 接口描述 接口功能:更新函数版本配置(别名配置) 接口声明:`updateFunctionAliasConfig(options: IUpdateFunctionAliasConfig): Promise` ### 2. 输入参数 #### IUpdateFunctionAliasConfig 结构体 | 字段 | 必填 | 类型 | 说明 | | --------------- | ---- | -------------- | ------------------------------------- | | functionName | 是 | String | 函数名 | | name | 是 | String | 别名名称,默认设置为 '$DEFAULT' 即可 | | functionVersion | 是 | String | 别名主版本,默认设置为 '$LATEST' 即可 | | description | 否 | String | 别名描述 | | routingConfig | 否 | IRoutingConfig | 路由配置 | #### IRoutingConfig | 字段 | 必填 | 类型 | 说明 | | -------------------- | ---- | -------------------------- | ---------------- | | AddtionVersionMatchs | 是 | Array<IVersionMatch> | 规则路由附加版本 | #### IVersionMatch | 字段 | 必填 | 类型 | 说明 | | ---------- | ---- | ------ | ------------------------------------------------------------------------------------------------------ | | Version | 是 | String | 函数版本名称 | | Key | 是 | String | 匹配规则的 key,调用时通过传 key 来匹配规则路由到指定版本,此处默认填 'invoke.headers.X-Tcb-Route-Key' | | Method | 是 | String | 匹配方式,默认为 'range' | | Expression | 是 | String | range 匹配规则要求:需要为开区间或闭区间描述 (a,b) [a,b],其中 a、b 均为整数 | :::warning 此处仅支持两种配置方式,1. 指定单版本及对应流量比例,其余流量均打入 $LATEST 版本;2. 指定两个版本分配全部流量,示例如下所示 ::: ### 3. 返回结果 | 字段 | 类型 | 说明 | | --------- | ------ | ------- | | RequestId | String | 请求 ID | ### 4. 示例代码 ```javascript import CloudBase from "@cloudbase/manager-node"; const { functions } = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId", // 云开发环境ID,可在腾讯云云开发控制台获取 }); async function test() { const updateFunctionAliasConfigRes1 = await functions.updateFunctionAliasConfig({ functionName: "sum", name: "$DEFAULT", functionVersion: "$LATEST", routingConfig: { AddtionVersionMatchs: [ { Expression: "[0,3)", // 设置版本 1 的流量比例为 3%,其余 97% 流量指向 latest 版本 Key: "invoke.headers.X-Tcb-Route-Key", Method: "range", Version: "1", }, ], }, }); console.log("updateFunctionAliasConfig1", updateFunctionAliasConfigRes1); const updateFunctionAliasConfigRes2 = await functions.updateFunctionAliasConfig({ functionName: "sum", name: "$DEFAULT", functionVersion: "$LATEST", routingConfig: { AddtionVersionMatchs: [ { Expression: "[0,10)", // 设置版本 1 的流量比例为 10% Key: "invoke.headers.X-Tcb-Route-Key", Method: "range", Version: "1", }, { Expression: "[10,100)", // 设置版本 2 的流量比例为 90% Key: "invoke.headers.X-Tcb-Route-Key", Method: "range", Version: "2", }, ], }, }); console.log("updateFunctionAliasConfigRes2", updateFunctionAliasConfigRes2); } test(); ``` ## getFunctionAlias ### 1. 接口描述 接口功能:查询函数版本配置(别名配置) 接口声明:`getFunctionAlias(options: IGetFunctionAlias): Promise` ### 2. 输入参数 #### IGetFunctionAlias 结构体 | 字段 | 必填 | 类型 | 说明 | | ------------ | ---- | ------ | ------------------------------------ | | functionName | 是 | String | 函数名 | | name | 是 | String | 别名名称,默认设置为 '$DEFAULT' 即可 | ### 3. 返回结果 | 字段 | 类型 | 说明 | | --------------- | --------------------------------- | ---------------- | | RequestId | String | 请求 ID | | FunctionVersion | String | 别名指向的主版本 | | Name | String | 别名的名称 | | RoutingConfig | [IRoutingConfig](#IRoutingConfig) | 别名的路由信息 | | Description | String | 描述信息 | | AddTime | String | 创建时间 | | ModTime | String | 修改时间 | ### 4. 示例代码 ```javascript import CloudBase from "@cloudbase/manager-node"; const { functions } = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId", // 云开发环境ID,可在腾讯云云开发控制台获取 }); async function test() { // 查询流量配置比例 const getVersionConfigRes = await functions.getFunctionAlias({ name: "$DEFAULT", functionName: "sum", }); console.log("getVersionConfigRes", JSON.stringify(getVersionConfigRes)); } test(); ``` --- ## 静态网站托管 # 静态网站托管 云开发为开发者提供静态网站托管的能力,静态资源(HTML、CSS、JavaScript、字体等)的分发由对象存储 COS 和拥有多个边缘网点的 CDN 提供支持。您可在腾讯云控制台进行静态网站的部署,提供给您的用户访问。目前云开发静态网站托管能力仅在腾讯云云开发控制台支持,小程序 IDE 侧控制台暂不支持。 :::tip 提示 仅有付费方式为按量付费的环境可开通静态网站托管能力,预付费方式环境不可开通。 云开发的静态网站托管能力,目前在开通环境时,静态网站托管服务不会直接开通,而是需要您在环境中单独开通。 ::: ## uploadFiles > 新增于 3.1.0 版本 ### 1. 接口描述 接口功能:上传单个文件,多个文件,文件夹到静态网站托管中 接口声明:`async uploadFiles(options: IHostingOptions)` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ------------ | ---- | --------------------------------------------- | -------------------------------------------------------------- | | localPath | 否 | String | 单个文件或文件夹的本地路径 | | cloudPath | 否 | String | 单个文件或文件夹的云端路径 | | files | 否 | `Array` | 由 localPath 和 cloudPath 文件信息组成的数组,用于上传多个文件 | | onProgress | 否 | Function | 上传进度回调事件,会在上传过程中多次触发 | | onFileFinish | 否 | (err, data) => void | 每个文件上传完成后的回调,如果上传失败,则回调 err | | ingore | 否 | String 或 `Array` | 忽略文件模式 | 上传文件夹时,请指定 `localPath` 和 `cloudPath`参数,文件夹下的所有文件会上传到指定目录下,不包含文件夹本身。 当需要上传多个文件时,请指定 `files` 参数。 当 `cloudPath`为空时,文件会被上传到根目录下。 ### 3. 返回结果 ### 4. 示例代码 ```js import CloudBase from '@cloudbase/manager-node' const { hosting } = new CloudBase({ secretId: 'Your SecretId', secretKey: 'Your SecretKey', envId: 'Your envId' // 云开发环境ID,可在腾讯云云开发控制台获取 }) async function test() { // 上传文件夹 await hosting.uploadFiles({ localPath: './dir', cloudPath: '', ignore: ['**/ignore.*'] }) let fileCount = 0 // 上传多个文件 await hosting.uploadFiles({ files: [ { localPath: 'test/storage/test_data/data.txt', cloudPath: 'hosting/test_data/data.txt' } ], ignore: ['**/ignore.*'], onFileFinish: () => { fileCount++ } }) console.log(fileCount) // 1 } test() ``` ## listFiles > 新增于 3.1.0 版本 ### 1. 接口描述 接口功能:获取全部文件列表 接口声明:async listFiles(): Promise ### 2. 输入参数 无 ### 3. 返回结果 | 字段 | 类型 | 说明 | | ------------ | ------ | ---------------------------------------------------------------------------------------------------- | | Key | String | 对象键 | | LastModified | String | 对象最后修改时间,为 ISO8601 格式,如 2019-05-24T10:56:40Z date | | ETag | String | 对象的实体标签(Entity Tag),是对象被创建时标识对象内容的信息标签,可用于检查对象的内容是否发生变化 | | Size | String | 对象大小,单位为 Byte | | Owner | String | 对象持有者信息 | | StorageClass | String | 对象存储类型,标准存储 STANDARD | ### 4. 代码示例 ```js import CloudBase from '@cloudbase/manager-node' const { hosting } = new CloudBase({ secretId: 'Your SecretId', secretKey: 'Your SecretKey', envId: 'Your envId' // 云开发环境ID,可在腾讯云云开发控制台获取 }) async function test() { const res1 = await hosting.listFiles() for (let item in res1) { console.log(item) } } test() ``` ## deleteFiles > 新增于 3.1.0 版本 ### 1. 接口描述 接口功能:删除静态网站托管的文件或文件夹 接口声明:`async deleteFiles(options: IHostingCloudOptions)` ### 2. 参数说明 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------- | ---------------------- | | cloudPath | 是 | String | 文件或文件夹的云端路径 | | isDir | 否 | Boolean | cloudPath 是否为文件夹 | ### 3. 返回结果 无 ### 4. 示例代码 ```js import CloudBase from '@cloudbase/manager-node' const { hosting } = new CloudBase({ secretId: 'Your SecretId', secretKey: 'Your SecretKey', envId: 'Your envId' // 云开发环境ID,可在腾讯云云开发控制台获取 }) async function test() { await hosting.deleteFiles({ cloudPath: 'files/data.txt', isDir: false }) } test() ``` ### 关于路径 - `localPath` 为本地文件或文件夹的路径,为 `目录/文件名` 的形式,如 `./index.js`、`static/css/index.css` 等。 - `cloudPath` 为文件或文件夹的相对根目录的路径,为 `目录/文件名` 的形式,如 `index.js`、`static/css/index.js` 等。 :::caution 注意事项 Windows 系统中 localPath 为本地路径形式,是系统可以识别的路径,通常使用 `\` 分隔符。`cloudPath` 是云端文件路径,均需要使用 `/` 分隔符。 ::: ## findFiles > 新增于 3.2.0 版本 ### 1. 接口描述 接口功能:搜索静态网站托管的文件(支持按前缀搜索文件名称) 接口声明:`async findFiles(options: IFindOptions)` ### 2. 参数说明 | 字段 | 必填 | 类型 | 说明 | | ------- | ---- | ------- | ------------------------------------------------------------------- | | prefix | 是 | String | 匹配前缀,限定响应中只包含指定前缀的文件(对象) | | marker | 否 | Boolean | 起始对象键标记,从该标记之后(不含)按照 UTF-8 字典序返回对象键条目 | | maxKeys | 否 | Boolean | 单次返回最大的条目数量,默认值为 1000,最大为 1000 | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | -------- | ---- | ------------ | --------------------------------------------------------------------------------------------- | | Name | 是 | String | 存储桶的名称,格式为\ | | Prefix | 是 | String | 对象键匹配前缀,对应请求中的 prefix 参数 | | Marker | 是 | String | 起始对象键标记,从该标记之后(不含)按照 UTF-8 字典序返回对象键条目,对应请求中的 marker 参数 | | MaxKeys | 是 | Number | 单次响应返回结果的最大条目数量,对应请求中的 max-keys 参数 | | Contents | 是 | IContentItem | 对象条目 | #### IContentItem | 字段 | 必填 | 类型 | 说明 | | ------------ | ---- | ---------- | ---------------------------------------------------------------------------------------------------- | | Key | 是 | String | 对象键 | | LastModified | 是 | String | 对象最后修改时间,为 ISO8601 格式,如 2019-05-24T10:56:40Z | | ETag | 是 | String | 对象的实体标签(Entity Tag),是对象被创建时标识对象内容的信息标签,可用于检查对象的内容是否发生变化 | | Size | 是 | Number | 对象大小,单位为 Byte | | Owner | 是 | IOwnerInfo | 对象持有者信息 | | StorageClass | 是 | String | 对象存储类型。STANDARD_IA,ARCHIVE 等 | #### IOwnerInfo | 字段 | 必填 | 类型 | 说明 | | ----------- | ---- | ------ | ------------------ | | ID | 是 | String | 对象持有者的 APPID | | DisplayName | 是 | String | 对象持有者的名称 | ### 4. 示例代码 ```js import CloudBase from '@cloudbase/manager-node' const { hosting } = new CloudBase({ secretId: 'Your SecretId', secretKey: 'Your SecretKey', envId: 'Your envId' // 云开发环境ID,可在腾讯云云开发控制台获取 }) async function test() { const { Contents } = await hosting.findFiles({ prefix: 'hosting/', marker: '/' }) console.log(Contents) } test() ``` ## setWebsiteDocument > 新增于 3.2.0 版本 ### 1. 接口描述 接口功能:配置静态网站的错误文档,索引文档,重定向规则 接口声明:`async setWebsiteDocument(options: IBucketWebsiteOptiosn)` ### 2. 参数说明 | 字段 | 必填 | 类型 | 说明 | | ------------- | ---- | ------------------------------- | -------- | | indexDocument | 是 | String | 文档地址 | | errorDocument | 否 | String | 文档地址 | | routingRules | 否 | [IRoutingRules](#IRoutingRules) | 文档地址 | #### IRoutingRules | 字段 | 必填 | 类型 | 说明 | | --------------------------- | ---- | ------ | ----------------------------------------------------------------- | | keyPrefixEquals | 否 | String | 指定前缀重定向的路径,替换指定的 folder/ | | httpErrorCodeReturnedEquals | 否 | String | 指定重定向错误码,只支持配置 4XX 返回码,优先级高于 ErrorDocument | | replaceKeyWith | 否 | String | 替换整个 Key 为指定的内容 | | replaceKeyPrefixWith | 否 | String | 替换匹配到的前缀为指定的内容,设置 KeyPrefixEquals 时 才可设置 | **注:设置前缀匹配 keyPrefixEquals 时,替换内容可指定 replaceKeyWith(替换整个路径) 或 replaceKeyPrefixWith(替换前缀),设置指定重定向错误码 httpErrorCodeReturnedEquals 时,只能指定 replaceKeyWith(替换整个路径)** ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | ---------- | ---- | ------ | ------------------------------------------- | | statusCode | 是 | Number | 请求返回的 HTTP 状态码,如 200、403、404 等 | | headers | 否 | Object | 请求返回的头部信息 | ### 4. 示例代码 ```js import CloudBase from '@cloudbase/manager-node' const { hosting } = new CloudBase({ secretId: 'Your SecretId', secretKey: 'Your SecretKey', envId: 'Your envId' // 云开发环境ID,可在腾讯云云开发控制台获取 }) async function test() { const res = await hosting.setWebsiteDocument({ errorDocument: 'error.html', indexDocument: 'success.html', routingRules: [ { keyPrefixEquals: 'test.html', replaceKeyWith: 'index.html' }, { keyPrefixEquals: 'test1.html', replaceKeyPrefixWith: 'index1.html' }, { httpErrorCodeReturnedEquals: '400', replaceKeyWith: 'index.html' } ] }) if (res.statusCode === 200) { // todo } } test() ``` ## CreateHostingDomain > 新增于 3.2.0 版本 ### 1. 接口描述 接口功能:绑定自定义域名 接口声明:`async CreateHostingDomain(options: IBindDomainOptions)` ### 2. 参数说明 | 字段 | 必填 | 类型 | 说明 | | ------ | ---- | ------ | ---------- | | domain | 是 | String | 自定义域名 | | certId | 是 | String | 证书 ID | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | ------- | | RequestId | 是 | String | 请求 ID | ### 4. 示例代码 ```js import CloudBase from '@cloudbase/manager-node' const { hosting } = new CloudBase({ secretId: 'Your SecretId', secretKey: 'Your SecretKey', envId: 'Your envId' // 云开发环境ID,可在腾讯云云开发控制台获取 }) async function test() { const res = await hosting.CreateHostingDomain({ domain: 'xxx.xxx.xxx', certId: 'xxxxx' }) console.log(res) } test() ``` ## deleteHostingDomain > 新增于 3.3.0 版本 ### 1. 接口描述 接口功能:解绑自定义域名 接口声明:`async deleteHostingDomain(options: IDeleteDomainOptions)` ### 2. 参数说明 | 字段 | 必填 | 类型 | 说明 | | ------ | ---- | ------ | ---------- | | domain | 是 | String | 自定义域名 | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | ------- | | RequestId | 是 | String | 请求 ID | ### 4. 示例代码 ```js import CloudBase from '@cloudbase/manager-node' const { hosting } = new CloudBase({ secretId: 'Your SecretId', secretKey: 'Your SecretKey', envId: 'Your envId' // 云开发环境ID,可在腾讯云云开发控制台获取 }) async function test() { const res = await hosting.deleteHostingDomain({ domain: 'xxx.xxx.xxx' }) console.log(res) } test() ``` ## getWebsiteConfig > 新增于 3.3.0 版本 ### 1. 接口描述 接口功能:获取静态网站配置 接口声明:`async getWebsiteConfig()` ### 2. 参数说明 无 ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | -------------------- | ---- | --------------------------------- | ------------------------------------------- | | statusCode | 是 | Number | 请求返回的 HTTP 状态码,如 200、403、404 等 | | headers | 是 | Object | 请求返回的头部信息 | | WebsiteConfiguration | 是 | [IWebsiteConfig](#IWebsiteConfig) | 静态网站配置 | #### IWebsiteConfig | 字段 | 必填 | 类型 | 说明 | | ------------- | ---- | ------------------------------------------- | ------------ | | IndexDocument | 是 | [IIndexDocument](#IIndexDocument) | 索引文档 | | ErrorDocument | 是 | [IErrorDocument](#IErrorDocument) | 错误文档 | | RoutingRules | 是 | `Array` | 静态网站配置 | #### IIndexDocument | 字段 | 必填 | 类型 | 说明 | | ------ | ---- | ------ | ------------ | | Suffix | 是 | String | 指定索引文档 | #### IErrorDocument | 字段 | 必填 | 类型 | 说明 | | ---- | ---- | ------ | ---------------- | | Key | 是 | String | 指定通用错误返回 | #### IRoutingRule | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------------------------- | -------------------------------------------------------------- | | Condition | 是 | [ICondition](#ICondition) | 指定重定向发生的条件,前缀匹配重定向和错误码重定向只能指定一个 | | Redirect | 是 | [IRedirect](#IRedirect) | 指定满足重定向 conditon 时重定向的具体替换规则 | #### ICondition | 字段 | 必填 | 类型 | 说明 | | --------------------------- | ---- | ------ | ----------------------------------------------------------------- | | HttpErrorCodeReturnedEquals | 是 | String | 指定重定向错误码,只支持配置 4XX 返回码,优先级高于 ErrorDocument | | KeyPrefixEquals | 是 | String | 指定前缀重定向的路径,替换指定的 folder/ | #### IRedirect | 字段 | 必填 | 类型 | 说明 | | -------------------- | ---- | ------ | ------------------------------------------------------------------ | | ReplaceKeyWith | 是 | String | 替换整个 Key 为指定的内容 | | ReplaceKeyPrefixWith | 是 | String | 替换匹配到的前缀为指定的内容,Conditon 为 KeyPrefixEquals 才可设置 | ### 4. 示例代码 ```js import CloudBase from '@cloudbase/manager-node' const { hosting } = new CloudBase({ secretId: 'Your SecretId', secretKey: 'Your SecretKey', envId: 'Your envId' // 云开发环境ID,可在腾讯云云开发控制台获取 }) async function test() { const getConfig = await hosting.getWebsiteConfig() console.log('getConfig :', getConfig) } test() ``` ## tcbCheckResource > 新增于 3.3.0 版本 ### 1. 接口描述 接口功能:获取域名配置 接口声明:`async tcbCheckResource(options: ICheckSourceOptions)` ### 2. 参数说明 | 字段 | 必填 | 类型 | 说明 | | ------- | ---- | -------------------- | -------- | | domains | 是 | `Array` | 域名列表 | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | ----------- | ---- | ----------------------------------------------- | ----------------------------------------------------------------------- | | RecordCount | 是 | Number | 记录域名数 | | RequestId | 是 | String | 唯一请求 ID,每次请求都会返回。定位问题时需要提供该次请求的 RequestId。 | | Domains | 是 | `Array` | 域名清单 | #### ITcbDomainInfo | 字段 | 必填 | 类型 | 说明 | | ------------ | ---- | ------------------------------------- | ----------------------------------- | | Domain | 是 | String | 域名 | | DomainId | 是 | Number | 域名 Id | | Status | 是 | String | process , online , offline 域名状态 | | DomainConfig | 是 | [ITcbDomainConfig](#ITcbDomainConfig) | 域名配置 | | CName | 是 | String | 域名 CName | #### ITcbDomainConfig | 字段 | 必填 | 类型 | 说明 | | ----------- | ---- | ------------------------------------- | ------------------ | | Refer | 否 | [ITcbReferer](#ITcbReferer) | Referer 防盗链配置 | | Cache | 否 | `Array` | 缓存策略列表 | | IpFilter | 否 | [IIpFilter](#IIpFilter) | IP 黑白名单配置 | | IpFreqLimit | 否 | [IIpFreqLimit](#IIpFreqLimit) | IP 限频配置 | #### ITcbReferer | 字段 | 必填 | 类型 | 说明 | | ------------ | ---- | ------------------------------------------------- | -------------------------------------------- | | Switch | 是 | String | referer 黑白名单配置开关 on:开启 off:关闭 | | RefererRules | 否 | `Array` | referer 黑白名单配置规则 switch 为 on 时必填 | #### ITcbRefererRule | 字段 | 必填 | 类型 | 说明 | | ----------- | ---- | -------------------- | ------------------------------------------------------------------------------ | | RefererType | 是 | String | referer 配置类型, whitelist:白名单, blacklist:黑名单 | | Referers | 是 | `Array` | referer 内容列表,列表最大长度 400 个, 不需要http://开头,填写形如:www.test.com | | AllowEmpty | 是 | Boolean | 是否允许空 referer, true:允许空 refere, false:不允许空 referer | #### ITcbCache | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------- | | RuleType | 是 | String | 规则类型 all 全部文件,suffix 按后缀名匹配, path 文件夹类型按目录匹配, file 全路径匹配 四选一 必填。 | | RuleValue | 是 | String | 规则内容 依据规则类型而不同 以;分割 必填,suffix 类型每个后缀不超过 10 字节,总长度不超过 512 字节,file 不能以`/`或结尾,path 不能包含; `| \/`" | | CacheTtl | 是 | Number | Number | 缓存时间 单位秒 必填 | #### IIpFilter | 字段 | 必填 | 类型 | 说明 | | ---------- | ---- | -------------------- | ---------------------------------------------------------------------------------------------------- | | Switch | 是 | String | IP 黑白名单配置开关,on:开启,off:关闭 | | FilterType | 否 | String | IP 黑白名单类型,whitelist:白名单,blacklist:黑名单 | | Filters | 否 | `Array` | IP 黑白名单列表,支持 X.X.X.X 形式 IP,或 /8、 /16、/24 形式网段,最多可填充 50 个白名单或 50 个黑名单 | #### IIpFreqLimit | 字段 | 必填 | 类型 | 说明 | | ------ | ---- | ------ | ----------------------------------------------- | | Switch | 是 | String | IP 限频配置开关, on:开启, off:关闭 | | Qps | 否 | Number | 设置每秒请求数限制,超出限制的请求会直接返回 514 | ### 4. 示例代码 ```js import CloudBase from '@cloudbase/manager-node' const { hosting } = new CloudBase({ secretId: 'Your SecretId', secretKey: 'Your SecretKey', envId: 'Your envId' // 云开发环境ID,可在腾讯云云开发控制台获取 }) async function test() { const res = await hosting.tcbCheckResource({ domains: ['domain'] }) console.log('res:', res) } test() ``` ## tcbModifyAttribute > 新增于 3.3.0 版本 ### 1. 接口描述 接口功能:域名配置 接口声明:`async tcbModifyAttribute(options: IModifyOptions)` ### 2. 参数说明 | 字段 | 必填 | 类型 | 说明 | | ------------ | ---- | ------------------------------------- | -------- | | Domain | 是 | String | 域名 | | DomainId | 是 | Number | 域名 Id | | DomainConfig | 是 | [ITcbDomainConfig](#ITcbDomainConfig) | 域名配置 | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | ---------------- | ---- | ----------------------------------------- | ----------------------------- | | DomainId | 是 | Number | 域名 Id | | Origin | 是 | [ITcbOrigin](#ITcbOrigin) | cos 源域名 | | CosPrivateAccess | 是 | String | yes,no 是否开始 cos 私有读 | | Authentication | 是 | [ITcbAuthentication](#ITcbAuthentication) | 防盗链 key | | Cache | 是 | `Array` | 缓存策略 | | StaticWeb | 是 | [ITcbStatic](#ITcbStatic) | 静态网站 | | RootAccess | 是 | String | no off,是否访问根目录 | | RequestId | 是 | String | 唯一请求 ID,每次请求都会返回 | #### ITcbOrigin | 字段 | 必填 | 类型 | 说明 | | ------ | ---- | ------ | ---- | | Master | 是 | String | 主站 | | Slave | 否 | String | 副站 | #### ITcbAuthentication | 字段 | 必填 | 类型 | 说明 | | ---------- | ---- | ------ | --------------------------------------------------------------------------- | | Switch | 是 | String | on/off 开启或关闭’ | | SecretKey | 是 | String | 开启时必填,用户计算签名的秘钥,仅支持字母和数字组合,6 到 32 位 | | SignParam | 否 | String | url 串中签名的字段名,字母数字组合,不能以数字开头,低于 32 位,默认为 sign | | TimeParam | 否 | String | url 串中时间的字段名,字母数字组合,不能以数字开头,,低于 32 位,默认为 t | | ExpireTime | 否 | Number | 开启时必填过期时间,小于 31536000 秒,单位为秒 | #### ITcbStatic | 字段 | 必填 | 类型 | 说明 | | ------ | ---- | ------ | ------------------------------------------------------------ | | Switch | 是 | String | 开启,关闭静态网站功能 | | Path | 否 | String | 静态网站跳转的路径,以/开头,不支持路径包含空白和`;| /\*"` | ### 4. 示例代码 ```js import CloudBase from '@cloudbase/manager-node' const { hosting } = new CloudBase({ secretId: 'Your SecretId', secretKey: 'Your SecretKey', envId: 'Your envId' // 云开发环境ID,可在腾讯云云开发控制台获取 }) async function test() { const res = await hosting.tcbCheckResource({ domains: ['domain'] }) const domainId = res.Domains[0].DomainId const setRes = await hosting.tcbModifyAttribute({ domain: 'domain', domainId, domainConfig: { Refer: { Switch: 'on', RefererRules: [ { AllowEmpty: false, RefererType: 'blacklist', Referers: ['www.test11.com'] } ] }, IpFilter: { Switch: 'on', FilterType: 'blacklist', Filters: ['xxx.xxx.xxx.xxx'] }, IpFreqLimit: { Switch: 'on', Qps: 100 }, Cache: [ { RuleType: 'suffix', RuleValue: '.jpg', CacheTtl: 60 } ] } }) console.log('setRes:', setRes) } test() ``` --- ## HTTP 访问服务 # HTTP Service HTTP Service 是云开发为开发者提供的 HTTP 访问服务,让开发者可以通过 HTTP 访问到自己的云开发资源。 HTTP Service 的接口,可通过 [commonService ](./common)来调用 ## 创建云函数 HTTPService ### 1. 接口描述 接口功能:创建云函数 HTTPService 接口声明:`manager.commonService().call({ Action: 'CreateCloudBaseGWAPI', Param: {}}): Promise` > ⚠️ 本接口从 3.0.0 版本后,commonService 作为方法使用,请求参数为(service?:string, version?:string) ,属于不兼容变更 ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ------ | ---- | ------ | -------- | | Action | 是 | String | 接口名称 | | Param | 是 | Object | 接口参数 | #### Param 字段说明 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | ------------------------------- | | ServiceId | 是 | String | Service ID,该字段取值为环境 ID | | Path | 是 | String | 自定义路径 | | Type | 是 | Number | service type ,云函数默认为 1 | | Name | 是 | String | 函数名 | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | ------------ | | RequestId | 是 | String | 请求唯一标识 | | APIId | 是 | String | APIId | ### 4. 示例代码 ```javascript import CloudBase from '@cloudbase/manager-node' const manager = new CloudBase({ secretId: 'Your SecretId', secretKey: 'Your SecretKey', envId: 'Your envId' // 云开发环境ID,可在腾讯云云开发控制台获取 }) async function test() { const res = await manager.commonService().call({ Action: 'CreateCloudBaseGWAPI', Param: { ServiceId: envId, Path: '/sum', Type: 1, Name: 'sum' } }) const { APIId } = res console.log(APIId) } test() ``` ## 查询云函数 HTTP Service ### 1. 接口描述 接口功能:查询云函数 HTTP Service 接口声明:`manager.commonService().call({ Action: 'DescribeCloudBaseGWAPI', Param: {}}): Promise` > ⚠️ 本接口从 3.0.0 版本后,commonService 作为方法使用,请求参数为(service?:string, version?:string) ,属于不兼容变更 ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ------ | ---- | ------ | -------- | | Action | 是 | String | 接口名称 | | Param | 是 | Object | 接口参数 | #### Param 字段说明 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | ------------------------------- | | ServiceId | 否 | String | Service ID,该字段取值为环境 ID | | Domain | 否 | String | 绑定的域名 | | Path | 否 | String | 自定义路径 | | APIId | 否 | String | APIId | > ServiceId 与 Domain 至少要设置其中一个字段! ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ---------------------------- | ----------------- | | RequestId | 是 | String | 请求唯一标识 | | APISet | 是 | `Array` | HTTP service 列表 | **CloudBaseGWAPI** | 字段 | 必填 | 类型 | 说明 | | ---------- | ---- | ------ | ----------------------------- | | ServiceId | 是 | String | 环境 ID | | APIId | 是 | String | APIId | | Path | 是 | String | 自定义路径 | | Type | 是 | Number | service type ,云函数默认为 1 | | Name | 是 | String | 云函数名 | | CreateTime | 是 | Number | service 创建时间 | | EnvId | 是 | String | 环境 ID | ### 4. 示例代码 ```javascript import CloudBase from '@cloudbase/manager-node' const manager = new CloudBase({ secretId: 'Your SecretId', secretKey: 'Your SecretKey', envId: 'Your envId' // 云开发环境ID,可在腾讯云云开发控制台获取 }) async function test() { const res = await manager.commonService().call({ Action: 'DescribeCloudBaseGWAPI', Param: { ServiceId: envId, Path: '/sum' } }) const { APISet } = res for (let api in APISet) { console.log(api) } } test() ``` ## 删除云函数 HTTP Service ### 1. 接口描述 接口功能:删除云函数 HTTP Service 接口声明:`manager.commonService().call({ Action: 'DeleteCloudBaseGWAPI', Param: {}}): Promise` > ⚠️ 本接口从 3.0.0 版本后,commonService 作为方法使用,请求参数为(service?:string, version?:string) ,属于不兼容变更 ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ------ | ---- | ------ | -------- | | Action | 是 | String | 接口名称 | | Param | 是 | Object | 接口参数 | #### Param 字段说明 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | ------------------------------- | | ServiceId | 是 | String | Service ID,该字段取值为环境 ID | | Path | 否 | String | 自定义路径 | | APIId | 否 | String | APIId | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | -------------------------- | | RequestId | 是 | String | 请求唯一标识 | | Count | 是 | Number | 被删除的 HTTP Service 个数 | ### 4. 示例代码 ```javascript import CloudBase from '@cloudbase/manager-node' const manager = new CloudBase({ secretId: 'Your SecretId', secretKey: 'Your SecretKey', envId: 'Your envId' // 云开发环境ID,可在腾讯云云开发控制台获取 }) async function test() { const res = await manager.commonService().call({ Action: 'DeleteCloudBaseGWAPI', Param: { ServiceId: envId, Path: '/sum' // APIId: apiId } }) console.log(res.Count) } test() ``` ## 绑定 HTTP Service 自定义域名 ### 1. 接口描述 接口功能:绑定 HTTP Service 自定义域名 接口声明:`manager.commonService().call({ Action: 'BindCloudBaseGWDomain', Param: {}}): Promise` > ⚠️ 本接口从 3.0.0 版本后,commonService 作为方法使用,请求参数为(service?:string, version?:string) ,属于不兼容变更 > 绑定自定义域名时,请务必在您的自定义域名厂商处 配置 CNAME 域名解析 ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ------ | ---- | ------ | -------- | | Action | 是 | String | 接口名称 | | Param | 是 | Object | 接口参数 | #### Param 字段说明 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | ------------------------------- | | ServiceId | 是 | String | Service ID,该字段取值为环境 ID | | Domain | 是 | String | 绑定的域名 | | CertId | 否 | String | 证书 ID | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | ------------ | | RequestId | 是 | String | 请求唯一标识 | ### 4. 示例代码 ```javascript import CloudBase from '@cloudbase/manager-node' const manager = new CloudBase({ secretId: 'Your SecretId', secretKey: 'Your SecretKey', envId: 'Your envId' // 云开发环境ID,可在腾讯云云开发控制台获取 }) async function test() { await manager.commonService().call({ Action: 'BindCloudBaseGWDomain', Param: { ServiceId: envId, Domain: 'xxx.xxx.xxx' } }) } test() ``` ## 查询 HTTP Service 域名 ### 1. 接口描述 接口功能:查询 HTTP Service 域名 接口声明:`manager.commonService().call({ Action: 'DescribeCloudBaseGWService', Param: {}}): Promise` > ⚠️ 本接口从 3.0.0 版本后,commonService 作为方法使用,请求参数为(service?:string, version?:string) ,属于不兼容变更 ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ------ | ---- | ------ | -------- | | Action | 是 | String | 接口名称 | | Param | 是 | Object | 接口参数 | #### Param 字段说明 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | ------------------------------- | | ServiceId | 否 | String | Service ID,该字段取值为环境 ID | | Domain | 否 | String | 绑定的域名 | > ServiceId 与 Domain 至少要设置其中一个字段! ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | ---------- | ---- | -------------------------------- | --------------------- | | RequestId | 是 | String | 请求唯一标识 | | ServiceSet | 是 | `Array` | HTTP Service 域名信息 | **CloudBaseGWService** | 字段 | 必填 | 类型 | 说明 | | --------------------------------------------- | ---- | ------ | ------------------------------------------ | | ServiceId | 是 | String | 请求唯一标识 | | Domain | 是 | String | HTTP Service 域名信息 | | OpenTime | 是 | Number | service 开启时间 | | Status | 是 | Number | 绑定状态,1 绑定中;2 绑定失败;3 绑定成功 | | 注意:此字段可能返回 null,表示取不到有效值。 | ### 4. 示例代码 ```javascript import CloudBase from '@cloudbase/manager-node' const manager = new CloudBase({ secretId: 'Your SecretId', secretKey: 'Your SecretKey', envId: 'Your envId' // 云开发环境ID,可在腾讯云云开发控制台获取 }) async function test() { const res = await manager.commonService().call({ Action: 'DescribeCloudBaseGWService', Param: { ServiceId: envId } }) const { Domain } = res console.log(Domain) } test() ``` ## 解绑 HTTP Service 域名 ### 1. 接口描述 接口功能:解绑 HTTP Service 域名 接口声明:`manager.commonService().call({ Action: 'DeleteCloudBaseGWDomain', Param: {}}): Promise` > ⚠️ 本接口从 3.0.0 版本后,commonService 作为方法使用,请求参数为(service?:string, version?:string) ,属于不兼容变更 ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ------ | ---- | ------ | -------- | | Action | 是 | String | 接口名称 | | Param | 是 | Object | 接口参数 | #### Param 字段说明 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | ------------------------------- | | ServiceId | 是 | String | Service ID,该字段取值为环境 ID | | Domain | 是 | String | 绑定的域名 | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | ---------------------------- | | RequestId | 是 | String | 请求唯一标识 | | Count | 是 | Number | 解绑的 HTTP Service 域名个数 | ### 4. 示例代码 ```javascript import CloudBase from '@cloudbase/manager-node' const manager = new CloudBase({ secretId: 'Your SecretId', secretKey: 'Your SecretKey', envId: 'Your envId' // 云开发环境ID,可在腾讯云云开发控制台获取 }) async function test() { const res = await manager.commonService().call({ Action: 'DeleteCloudBaseGWDomain', Param: { ServiceId: envId, Domain: 'xxx.xxx.xxx' } }) console.log(res.Count) } test() ``` --- ## SDK 初始化 # SDK 初始化 ### 1. 接口描述 接口功能:初始化管理端 sdk 接口声明: 两种初始化方式 1. `静态方法(推荐) init(object)` > init 得到的实例是单例的,多次调用 CloudBase.init 只会初始化一次 2. `构造方法 new CloudBase(object)` > 每次初始化都会得到一个全新的 CloudBase 实例,如果需要管理多个腾讯云账号下的云开发服务,可通过此种方式创建多个 CloudBase 实例。 注意事项: 同一腾讯云 云开发 账户对应一个类实例 > ⚠️ 需要提前开通云开发服务并创建环境,否则无法使用。 > ⚠️ 服务端环境下(非云函数环境),需要用户传入 SecretId, SecretKey(腾讯云控制台获取) > 若当前账户为子账户,请先通过主账户授权开通 QcloudTCBFullAccess(云开发全读写访问), QcloudAccessForTCBRole(云开发对云资源的访问权限) > [子账户权限设置指引](https://cloud.tencent.com/document/product/598/36256) ### 2. 输入参数 | 字段 | 类型 | 必填 | 说明 | | --------- | ------ | ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | secretId | string | 否 | 腾讯云凭证 SecretId,`secretId` 与 `secretKey` 必须同时传递,在云函数内执行可不填。[前往获取](https://console.cloud.tencent.com/cam/capi) | | secretKey | string | 否 | 腾讯云凭证 SecretKey,`secretId` 与 `secretKey` 必须同时传递 ,在云函数内执行可不填。[前往获取](https://console.cloud.tencent.com/cam/capi) | | token | string | 否 | 腾讯云临时凭证 `token`,传递此字段时意味着使用的是临时凭证,如果显式传递临时凭证,则此参数必传 | | envId | string | 否 | TCB 环境 ID,不填使用默认环境 ,可在腾讯云云开发控制台获取;因为后续的很多接口依赖于环境,在未传递的情况下,需要通过 `addEnvironment()` 添加环境方可进行后续接口调用 | | proxy | string | 否 | 调用接口时使用的 http 代理 url | | region | string | 否 | 指定地域,目前支持的地域列表[参考](https://cloud.tencent.com/document/product/876/51107),云函数环境下默认取当前云函数环境地域 | ### 3. 返回结果 | 字段 | 类型 | 必填 | 说明 | | ---- | --------- | ---- | ------------------------------- | | - | CloudBase | 是 | 初始化后得到一个 CloudBase 实例 | #### CloudBase 实例方法描述 1. 环境相关: `CloudBase` 通过 `EnvironmentManager` 可管理多个 `Environment` 实例,存在一个当前环境的 `Environment`。 - `getEnvironmentManager(): EnvironmentManager` 获取环境管理器实例,可对多个 `Environment` 进行管理,存在一个当前的 `Environment` 对应于当前环境 - `addEnvironment(string envId): void` 增加环境的实例,如果不存在当前环境,新增加的环境实例自动成为当前环境。注意,该方法不会在腾讯云 云开发 服务中创建环境,所以 `envId` 对应的环境需要预先存在 - `currentEnvironment(): Environment` 获取当前环境 `Environment` 的实例 2. 能力相关: 能力是与环境 `Environment` 相关联的,所以以下函数都是获取当前 `Environment` 环境下的资源管理对象。 在没有切换当前环境的情况下,对应于初始化 `CloudbaseManager` 时的 `envId` 所对应的环境。 ```javascript const app = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId" // 云开发环境ID,可在腾讯云云开发控制台获取 }); ``` - `app.functions` - 获取当前环境下的 `FunctionService` 对象实例,通过该对象实例可以管理云函数 - `app.database` - 获取当前环境下的 `DatabaseService` 对象实例,通过该对象实例可以管理数据库 - `app.storage` - 获取当前环境下的 `StorageService` 对象实例,通过该对象实例可以管理文件存储 - `app.env` - 获取当前环境下的 `EnvService` 对象实例,通过该对象实例可以管理环境 #### 地域 指定 region 时,必须与当前环境所属地域信息一致,示例如下: 当前有上海地域的环境 env-shanghai,广州地域的环境 env-guangzhou,则正确的用法为 ```js // 假设在上海地域 云函数下,则默认 region 为上海,信息一致 const app = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "env-shanghai" }); ``` ```js // 假设在上海地域 云函数下,指定上海 region const app = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "env-shanghai", region: "ap-shanghai" }); ``` ```js // 假设在上海地域 云函数下,同时指定广州 region 及 广州 env const app = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "env-guangzhou", region: "ap-guangzhou" }); ``` :::tip 提示 当前使用的环境所属地域,必须与当前指定的地域信息一致! ::: ### 4. 示例代码 通过腾讯云 API 密钥初始化,示例代码如下: ```javascript import CloudBase from "@cloudbase/manager-node"; const app = CloudBase.init({ secretId: "Your SecretId", secretKey: "Your SecretKey", token: "Your SecretToken", // 使用临时凭证需要此字段 envId: "Your envId", // 云开发环境ID,可在腾讯云云开发控制台获取 proxy: "" // 支持代理设置 }); ``` 在云函数环境下,支持免密钥初始化,示例代码如下: ```javascript const app = new CloudBase({ envId: "Your envId" }); ``` 初始化完成之后,即可使用相关功能。 ```javascript // 1. 初始化 CloudBase const app = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId" // 云开发环境ID,可在腾讯云云开发控制台获取 }); async function test() { // 2. 调用云函数管理下的getFunction let result = await app.functions.getFunctionDetail("test"); // 3. 打印结果 console.log(result); } test(); ``` --- ## 介绍 # 介绍 云开发 manager-node sdk 支持开发者通过接口形式对云开发提供的云函数、数据库、文件存储等资源进行创建、管理、配置等操作。更多源码内容请参见 [cloudbase-manager-node](https://github.com/TencentCloudBase/cloudbase-manager-node)。 ## 安装 npm ```bash npm install @cloudbase/manager-node ``` yarn ```bash yarn add @cloudbase/manager-node ``` ## 使用示例 要在您的代码内使用该模块: ```js const CloudBase = require('@cloudbase/manager-node') ``` 或 ```js import CloudBase from '@cloudbase/manager-node' ``` 初始化 ```js const app = CloudBase.init({ secretId: 'Your SecretId', secretKey: 'Your SecretKey', token: 'Your SecretToken', // 使用临时凭证需要此字段 envId: 'Your envId' // 云环境 ID,可在腾讯云-云开发控制台获取 }) // 获取各功能模块 const { database, functions, storage, env, commonService } = app ``` --- ## 安全规则 # 安全规则 安全规则的接口,可通过 [commonService ](./common)来调用 ### 权限类别(以下前 4 种属于简易权限,CUSTOM 属于安全规则特有) - READONLY:所有用户可读,仅创建者和管理员可写 - PRIVATE:仅创建者及管理员可读写 - ADMINWRITE:所有用户可读,仅管理员可写 - ADMINONLY:仅管理员可读写 - CUSTOM: 自定义安全规则 ## 获取数据库简易权限 ### 1. 接口描述 接口功能:获取数据库简易权限 接口声明:`manager.commonService().call({Action: 'DescribeDatabaseACL',Param: {}}): Promise` > ⚠️ 本接口从 3.0.0 版本后,commonService 作为方法使用,请求参数为(service?:string, version?:string) ,属于不兼容变更 ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ------ | ---- | ------ | -------- | | Action | 是 | String | 接口名称 | | Param | 是 | Object | 接口参数 | #### Param 字段说明 | 字段 | 必填 | 类型 | 说明 | | -------------- | ---- | ------ | ------- | | CollectionName | 是 | String | 集合名 | | EnvId | 是 | String | 环境 ID | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | ------------ | | RequestId | 是 | String | 请求唯一标识 | | AclTag | 否 | String | 权限类别 | ### 4. 示例代码 ```js const cloudbaseConfig = { secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId" // 云开发环境ID,可在腾讯云云开发控制台获取 }; let manager = new CloudBase(cloudbaseConfig); async function test() { const res = await manager.commonService().call({ Action: "DescribeDatabaseACL", Param: { CollectionName: "xxx", EnvId: cloudbaseConfig.envId } }); console.log(res.AclTag); // 打印权限类别 } test(); ``` ## 修改数据库简易权限 ### 1. 接口描述 接口功能:修改数据库简易权限 接口声明:`manager.commonService().call({Action: 'ModifyDatabaseACL',Param: {}}): Promise` > ⚠️ 本接口从 3.0.0 版本后,commonService 作为方法使用,请求参数为(service?:string, version?:string) ,属于不兼容变更 ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ------ | ---- | ------ | -------- | | Action | 是 | String | 接口名称 | | Param | 是 | Object | 接口参数 | #### Param 字段说明 | 字段 | 必填 | 类型 | 说明 | | -------------- | ---- | ------ | ---------------------------------------------------- | | CollectionName | 是 | String | 集合名 | | AclTag | 是 | String | 数据库简易权限 READONLY PRIVATE ADMINWRITE ADMINONLY | | EnvId | 是 | String | 环境 ID | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | --------- | ------ | ---- | ------------ | | RequestId | String | 是 | 请求唯一标识 | ### 4. 示例代码 ```js const cloudbaseConfig = { secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId" // 云开发环境ID,可在腾讯云云开发控制台获取 }; let manager = new CloudBase(cloudBaseConfig); async function test() { const res = await manager.commonService().call({ Action: "ModifyDatabaseACL", Param: { CollectionName: "xxx", EnvId: cloudbaseConfig.envId, AclTag: "PRIVATE" } }); console.log(res); } test(); ``` ## 设置数据库安全规则 ### 1. 接口描述 接口功能:设置数据库安全规则 接口声明:`manager.commonService().call({Action: 'ModifySafeRule',Param: {}}): Promise` > ⚠️ 本接口从 3.0.0 版本后,commonService 作为方法使用,请求参数为(service?:string, version?:string) ,属于不兼容变更 ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ------ | ---- | ------ | -------- | | Action | 是 | String | 接口名称 | | Param | 是 | Object | 接口参数 | #### Param 字段说明 | 字段 | 必填 | 类型 | 说明 | | -------------- | ---- | ------ | ---------------------------------------------------------------------------------------------------------------------- | | CollectionName | 是 | String | 集合名 | | EnvId | 是 | String | 环境 ID | | AclTag | 是 | String | 权限类别 | | Rule | 否 | String | 权限类别设置为 CUSTOM 时,需要设置该字段([数据库安全规则文档](https://cloud.tencent.com/document/product/876/36414)) | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | ------------ | | RequestId | 是 | String | 请求唯一标识 | ### 4. 示例代码 ```js const cloudbaseConfig = { secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId" // 云开发环境ID,可在腾讯云云开发控制台获取 }; let manager = new CloudBase(cloudBaseConfig); async function test() { const res = await manager.commonService().call({ Action: "ModifySafeRule", Param: { CollectionName: "coll-1", AclTag: "CUSTOM", EnvId: "xxx", Rule: JSON.stringify({ read: true, write: "doc._openid == auth.openid" }) } }); console.log(res); } test(); ``` ## 查询数据库安全规则 ### 1. 接口描述 接口功能:查询数据库安全规则 接口声明:`manager.commonService().call({Action: 'DescribeSafeRule',Param: {}}): Promise` > ⚠️ 本接口从 3.0.0 版本后,commonService 作为方法使用,请求参数为(service?:string, version?:string) ,属于不兼容变更 ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ------ | ---- | ------ | -------- | | Action | 是 | String | 接口名称 | | Param | 是 | Object | 接口参数 | #### Param 字段说明 | 字段 | 必填 | 类型 | 说明 | | -------------- | ---- | ------ | ------- | | CollectionName | 是 | String | 集合名 | | EnvId | 是 | String | 环境 ID | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | -------------- | ------------ | | RequestId | 是 | String | 请求唯一标识 | | AclTag | 是 | String | 权限类别 | | Rule | 是 | String or null | 安全规则 | ### 4. 示例代码 ```js const cloudbaseConfig = { secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId" // 云开发环境ID,可在腾讯云云开发控制台获取 }; let manager = new CloudBase(cloudBaseConfig); async function test() { const res = await manager.commonService().call({ Action: "DescribeSafeRule", Param: { CollectionName: "coll-1", EnvId: cloudbaseConfig.envId } }); console.log(res.AclTag); console.log(res.Rule); } test(); ``` ## 设置云函数安全规则 ### 1. 接口描述 接口功能:设置云函数安全规则 接口声明:`manager.commonService().call({Action: 'ModifySecurityRule',Param: {}}): Promise` > ⚠️ 本接口从 3.0.0 版本后,commonService 作为方法使用,请求参数为(service?:string, version?:string) ,属于不兼容变更 ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ------ | ---- | ------ | -------- | | Action | 是 | String | 接口名称 | | Param | 是 | Object | 接口参数 | #### Param 字段说明 | 字段 | 必填 | 类型 | 说明 | | ------------ | ---- | ------ | --------------------------------------------------------------------------------------- | | AclTag | 是 | String | 此处填 CUSTOM | | EnvId | 是 | String | 环境 ID | | ResourceType | 是 | String | 此处填 FUNCTION | | Rule | 是 | String | 查看[云函数安全规则文档](https://docs.cloudbase.net/cloud-function/security-rules.html) | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | ------------ | | RequestId | 是 | String | 请求唯一标识 | ### 4. 示例代码 ```js const manager = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId" // 云开发环境ID,可在腾讯云云开发控制台获取 }); const { env } = manager; async function test() { const res = await manager.commonService().call({ Action: "ModifySecurityRule", Param: { AclTag: "CUSTOM", EnvId: envId, ResourceType: "FUNCTION", Rule: JSON.stringify({ "*": { invoke: true } }) } }); console.log(res); } test(); ``` ## 查询云函数安全规则 ### 1. 接口描述 接口功能:查询云函数安全规则 接口声明:`manager.commonService().call({Action: 'DescribeSecurityRule',Param: {}}): Promise` > ⚠️ 本接口从 3.0.0 版本后,commonService 作为方法使用,请求参数为(service?:string, version?:string) ,属于不兼容变更 ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ------ | ---- | ------ | -------- | | Action | 是 | String | 接口名称 | | Param | 是 | Object | 接口参数 | #### Param 字段说明 | 字段 | 必填 | 类型 | 说明 | | ------------ | ---- | ------ | --------------- | | ResourceType | 是 | String | 此处填 FUNCTION | | EnvId | 是 | String | 环境 ID | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | -------------- | ------------ | | RequestId | 是 | String | 请求唯一标识 | | AclTag | 是 | String | 权限类别 | | Rule | 是 | String or null | 安全规则 | ### 4. 示例代码 ```js const cloudbaseConfig = { secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId" // 云开发环境ID,可在腾讯云云开发控制台获取 }; let manager = new CloudBase(cloudBaseConfig); async function test() { const res = await manager.commonService().call({ Action: "DescribeSecurityRule", Param: { EnvId: "hello-tcb-9glo12vd5bd3bd0d", ResourceType: "FUNCTION" } }); console.log(res.AclTag); console.log(res.Rule); } test(); ``` ## 设置存储安全规则 ### 1. 接口描述 接口功能:设置存储安全规则 接口声明:`manager.commonService().call({Action: 'ModifyStorageSafeRule',Param: {}}): Promise` > ⚠️ 本接口从 3.0.0 版本后,commonService 作为方法使用,请求参数为(service?:string, version?:string) ,属于不兼容变更 ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ------ | ---- | ------ | -------- | | Action | 是 | String | 接口名称 | | Param | 是 | Object | 接口参数 | #### Param 字段说明 | 字段 | 必填 | 类型 | 说明 | | ------ | ---- | ------ | ------------------------------------------------------------------------------------------------------------ | | Bucket | 是 | String | 桶名 | | AclTag | 是 | String | [权限类别](#权限类别) | | EnvId | 是 | String | 环境 ID | | Rule | 否 | String | 权限类别为 CUSTOM 时,设置该字段,[存储安全规则文档](https://docs.cloudbase.net/storage/security-rules.html) | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | ------------ | | RequestId | 是 | String | 请求唯一标识 | ### 4. 示例代码 ```js const manager = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId" // 云开发环境ID,可在腾讯云云开发控制台获取 }); const { env } = manager; // 先获取桶名 const { EnvInfo: { Storages } } = await env.getEnvInfo(); const { Bucket } = Storages[0]; async function test() { const res = await manager.commonService().call({ Action: "ModifyStorageSafeRule", Param: { Bucket, AclTag: "CUSTOM", EnvId: envId, Rule: JSON.stringify({ read: true, write: "resource.openid == auth.uid" }) } }); console.log(res); } test(); ``` ## 查询存储安全规则 ### 1. 接口描述 接口功能:查询存储安全规则 接口声明:`manager.commonService().call({Action: 'DescribeStorageSafeRule',Param: {}}): Promise` > ⚠️ 本接口从 3.0.0 版本后,commonService 作为方法使用,请求参数为(service?:string, version?:string) ,属于不兼容变更 ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ------ | ---- | ------ | -------- | | Action | 是 | String | 接口名称 | | Param | 是 | Object | 接口参数 | #### Param 字段说明 | 字段 | 必填 | 类型 | 说明 | | ------ | ---- | ------ | ------- | | Bucket | 是 | String | 桶名称 | | EnvId | 是 | String | 环境 ID | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | -------------- | ------------ | | RequestId | 是 | String | 请求唯一标识 | | AclTag | 是 | String | 权限类别 | | Rule | 是 | String or null | 安全规则 | ### 4. 示例代码 ```js const cloudbaseConfig = { secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId" // 云开发环境ID,可在腾讯云云开发控制台获取 }; let manager = new CloudBase(cloudBaseConfig); async function test() { const res = await manager.commonService().call({ Action: "DescribeStorageSafeRule", Param: { Bucket: "xxx", EnvId: cloudBaseConfig.envId } }); console.log(res.AclTag); console.log(res.Rule); } test(); ``` ## 查询存储安全规则修改异步任务状态 ### 1. 接口描述 接口功能:查询存储安全规则修改异步任务状态 接口声明:`manager.commonService().call({Action: 'DescribeCDNChainTask',Param: {}}): Promise` > ⚠️ 本接口从 3.0.0 版本后,commonService 作为方法使用,请求参数为(service?:string, version?:string) ,属于不兼容变更 ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ------ | ---- | ------ | -------- | | Action | 是 | String | 接口名称 | | Param | 是 | Object | 接口参数 | #### Param 字段说明 | 字段 | 必填 | 类型 | 说明 | | ------ | ---- | ------ | ------- | | Bucket | 是 | String | 桶名称 | | EnvId | 是 | String | 环境 ID | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | ------------------------------------------------------ | | RequestId | 是 | String | 请求唯一标识 | | Status | 是 | String | 开/关防盗链任务状态。WAITING、PENDING、FINISHED、ERROR | ### 4. 示例代码 ```js const cloudbaseConfig = { secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId" // 云开发环境ID,可在腾讯云云开发控制台获取 }; let manager = new CloudBase(cloudBaseConfig); async function test() { // 获取环境信息 取bucket const { EnvInfo: { Storages } } = await env.getEnvInfo(); console.log(Storages); const { Bucket } = Storages[0]; const res = await manager.commonService().call({ Action: "ModifyStorageSafeRule", Param: { Bucket, AclTag: "CUSTOM", EnvId: envId, Rule: JSON.stringify({ read: true, write: "resource.openid == auth.uid" }) } }); console.log(res); expect(res.RequestId !== undefined).toBe(true); let status = ""; do { status = ( await commonService.call({ Action: "DescribeCDNChainTask", Param: { Bucket, EnvId: envId } }) ).Status; console.log(status); } while (status !== "FINISHED" && status !== "ERROR"); } test(); ``` --- ## 安全来源 # 安全来源 安全规则的接口,可通过 [commonService ](./common)来调用 ## 新增安全来源 ### 1. 接口描述 接口功能:新增安全来源 接口声明:`manager.commonService().call({ Action: 'CreateSafetySource', Param: {}}): Promise` > ⚠️ 本接口从 3.0.0 版本后,commonService 作为方法使用,请求参数为(service?:string, version?:string) ,属于不兼容变更 ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ------- | ---- | ------ | -------- | | EnvId | 是 | String | 环境 ID | | AppName | 是 | String | 应用标识 | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | ------------ | | RequestId | 是 | String | 请求唯一标识 | ### 4. 示例代码 ```javascript import CloudBase from '@cloudbase/manager-node' const manager = new CloudBase({ secretId: 'Your SecretId', secretKey: 'Your SecretKey', envId: 'Your envId' // 云开发环境ID,可在腾讯云云开发控制台获取 }) async function test() { await manager.commonService().call({ Action: 'CreateSafetySource', Param: { EnvId: 'Your envId', AppName: 'xxx' } }) } test() ``` ## 获取安全来源列表 ### 1. 接口描述 接口功能:获取安全来源列表 接口声明:`manager.commonService().call({ Action: 'DescribeSafetySource', Param: {}}): Promise` > ⚠️ 本接口从 3.0.0 版本后,commonService 作为方法使用,请求参数为(service?:string, version?:string) ,属于不兼容变更 ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ------ | ---- | ------ | -------- | | EnvId | 是 | String | 环境 ID | | Offset | 是 | Number | 偏移量 | | Limit | 是 | Number | 限制数目 | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | ---------- | ---- | ------------------------------ | ------------ | | TotalCount | 是 | Number | 总数 | | Data | 是 | `Array` | 安全来源列表 | | RequestId | 是 | String | 请求唯一标识 | #### SafetySourceItem 字段说明 | 字段 | 必填 | 类型 | 说明 | | ---------------- | ---- | ------ | -------- | | Id | 是 | String | 记录 ID | | AppName | 是 | String | 应用标识 | | AppSecretVersion | 是 | String | 密钥版本 | | CreateTime | 是 | String | 创建时间 | ### 4. 示例代码 ```javascript import CloudBase from '@cloudbase/manager-node' const manager = new CloudBase({ secretId: 'Your SecretId', secretKey: 'Your SecretKey', envId: 'Your envId' // 云开发环境ID,可在腾讯云云开发控制台获取 }) async function test() { const res = await manager.commonService().call({ Action: 'DescribeSafetySource', Param: { EnvId: 'Your envId', Offset: 0, Limit: 20 } }) const { Data } = res for (let item in Data) { console.log(item) } } test() ``` ## 查看安全来源的密钥 ### 1. 接口描述 接口功能:查看安全来源的密钥 接口声明:`manager.commonService().call({ Action: 'DescribeSafetySourceSecretKey', Param: {}}): Promise` > ⚠️ 本接口从 3.0.0 版本后,commonService 作为方法使用,请求参数为(service?:string, version?:string) ,属于不兼容变更 ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ------ | ---- | ------ | --------------------------------- | | EnvId | 是 | String | 环境 ID | | ItemId | 是 | Object | 记录 ID,从列表接口的返回数据里看 | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | ------------ | ---- | ------ | ------------ | | RequestId | 是 | String | 请求唯一标识 | | AppSecretKey | 是 | String | 凭证 | ### 4. 示例代码 ```javascript import CloudBase from '@cloudbase/manager-node' const manager = new CloudBase({ secretId: 'Your SecretId', secretKey: 'Your SecretKey', envId: 'Your envId' // 云开发环境ID,可在腾讯云云开发控制台获取 }) async function test() { const res = await manager.commonService().call({ Action: 'DescribeSafetySource', Param: { EnvId: envId, Offset: 0, Limit: 20 } }) const res1 = await manager.commonService().call({ Action: 'DescribeSafetySourceSecretKey', Param: { EnvId: envId, ItemId: res.Data[0].Id // APIId: apiId } }) console.log(res1.AppSecretKey) } test() ``` ## 删除安全来源 ### 1. 接口描述 接口功能:删除安全来源 接口声明:`manager.commonService().call({ Action: 'DeleteSafetySource', Param: {}}): Promise` > ⚠️ 本接口从 3.0.0 版本后,commonService 作为方法使用,请求参数为(service?:string, version?:string) ,属于不兼容变更 ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ------ | ---- | ------ | --------------------------------- | | EnvId | 是 | String | 环境 ID | | ItemId | 是 | Object | 记录 ID,从列表接口的返回数据里看 | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | ------------ | | RequestId | 是 | String | 请求唯一标识 | ### 4. 示例代码 ```javascript import CloudBase from '@cloudbase/manager-node' const manager = new CloudBase({ secretId: 'Your SecretId', secretKey: 'Your SecretKey', envId: 'Your envId' // 云开发环境ID,可在腾讯云云开发控制台获取 }) async function test() { const res = await manager.commonService().call({ Action: 'DescribeSafetySource', Param: { EnvId: envId, Offset: 0, Limit: 20 } }) // 删除第一个安全来源 await commonService.call({ Action: 'DeleteSafetySource', Param: { EnvId: envId, ItemId: res.Data[0].Id } }) } test() ``` --- ## 云存储 # 云存储 ## uploadFile ### 1. 接口描述 接口功能:上传文件 接口声明: 2.x 版本 > `uploadFile(options)` 1.x 版本 > `uploadFile(localPath: string, cloudPath: string)` 注意事项: v2.x 与 v1.x 不兼容 ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ---------- | ---- | -------- | ------------------------------ | | localPath | 是 | String | 本地文件路径,建议传入绝对路径 | | cloudPath | 是 | String | 云端文件路径:`dir/data.txt` | | onProgress | 是 | Function | 上传进度回调函数 | 注:当 localPath 为文件夹时,SDK 会尝试在此文件夹下(一级目录,不深度遍历)寻找和 cloudPath 中所存在文件同名的文件,如 cloudPath 为 `dir/data.txt`,则会寻找 'data.txt'。 ### 3. 返回结果 无 ### 4. 示例代码 ```js import path from "path"; import CloudBase from "@cloudbase/manager-node"; const { storage } = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId", // 云开发环境ID,可在腾讯云云开发控制台获取 }); async function test() { await storage.uploadFile({ localPath: path.resolve("./data.txt"), cloudPath: "files/data.txt", onProgress: (data) => {}, }); } test(); ``` ## uploadDirectory ### 1. 接口描述 接口功能:上传文件夹 接口声明: 2.x 版本 > `uploadDirectory(options)` 1.x 版本 > `uploadDirectory(source: string, cloudPath: string)` 注意事项: v2.x 与 v1.x 不兼容 此接口会遍历目标文件夹下所有的文件并上传,同时保持文件夹结构。 ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ---------- | ---- | -------- | ---------------- | | localPath | 是 | String | 本地文件夹路径 | | cloudPath | 是 | String | 云端文件夹路径 | | onProgress | 是 | Function | 上传进度回调函数 | ### 3. 返回结果 无 ### 4. 示例代码 ```js import path from "path"; import CloudBase from "@cloudbase/manager-node"; const { storage } = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId", // 云开发环境ID,可在腾讯云云开发控制台获取 }); async function test() { await storage.uploadDirectory({ localPath: path.resolve("./files"), cloudPath: "", onProgress: (data) => {}, }); } test(); ``` ## downloadFile ### 1. 接口描述 接口功能:下载文件 接口声明: 2.x 版本 > `downloadFile(options)` 1.x 版本 > `downloadFile(cloudPath: string, localPath)` 注意事项: v2.x 与 v1.x 不兼容 ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | ------------------------------------ | | cloudPath | 是 | String | 云端文件路径:`dir/data.txt` | | localPath | 是 | String | 本地文件存储路径,文件需指定文件名称 | ### 3. 返回结果 无(undefined) ### 4. 示例代码 ```js import path from "path"; import CloudBase from "@cloudbase/manager-node"; const { storage } = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId", // 云开发环境ID,可在腾讯云云开发控制台获取 }); async function test() { await storage.downloadFile({ cloudPath: "files/data.txt", localPath: path.resolve("./data.txt"), }); } test(); ``` ## downloadDirectory ### 1. 接口描述 接口功能:下载文件夹 接口声明: 2.x 版本 > `downloadDirectory(options)` 1.x 版本 > `downloadDirectory(cloudPath: string, localPath: string)` 注意事项: v2.x 与 v1.x 不兼容 ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | ------------------------------------ | | cloudPath | 是 | String | 云端文件夹 | | localPath | 是 | String | 本地文件存储路径,文件需指定文件名称 | ### 3. 返回结果 无 ### 4. 示例代码 ```js import path from "path"; import CloudBase from "@cloudbase/manager-node"; const { storage } = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId", // 云开发环境ID,可在腾讯云云开发控制台获取 }); async function test() { await storage.downloadDirectory({ cloudPath: "files/music", localPath: path.resolve("./music"), }); } test(); ``` **NOTE:** - 此操作会遍历文件夹下的所有文件,如果文件数量过多,可能会造成执行失败。 - 当 cloudPath 不存在时,SDK 不会下载文件,也不会抛出错误。 ## listDirectoryFiles ### 1. 接口描述 接口功能:列出文件夹下的所有文件 接口声明:`listDirectoryFiles(cloudPath: string): Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | --------------------------- | | cloudPath | 是 | String | 云端文件夹路径:`dir/data/` | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | ---- | ---- | ----------------- | -------- | | - | 是 | `Array` | 文件数组 | #### FileItem | 字段 | 类型 | 说明 | | ------------ | ------ | ---------------------------------------------------------------------------------------------------- | | Key | String | 对象键 | | LastModified | String | 对象最后修改时间,为 ISO8601 格式,如 2019-05-24T10:56:40Z date | | ETag | String | 对象的实体标签(Entity Tag),是对象被创建时标识对象内容的信息标签,可用于检查对象的内容是否发生变化 | | Size | String | 对象大小,单位为 Byte | | Owner | String | 对象持有者信息 | | StorageClass | String | 对象存储类型,标准存储 STANDARD | ### 4. 示例代码 ```js import CloudBase from "@cloudbase/manager-node"; const { storage } = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId", // 云开发环境ID,可在腾讯云云开发控制台获取 }); async function test() { const res1 = await storage.listDirectoryFiles("dir/data"); const res2 = await storage.listDirectoryFiles("dir/data", 20); const res3 = await storage.listDirectoryFiles("dir/data", 20, "dir/dat"); for (let item in res1) { console.log(item); } } test(); ``` ## getFileInfo ### 1. 接口描述 接口功能:获取文件信息 接口声明:`getFileInfo(cloudPath: string): Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | --------------------------- | | cloudPath | 是 | String | 云端文件路径 `dir/data.txt` | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | ---- | ---- | ------ | ---------------------------- | | Size | 是 | String | 文件大小 KB | | Type | 是 | String | 文件类型 | | Date | 是 | String | 修改时间 | | ETag | 是 | String | 对象的实体标签(Entity Tag) | ### 4. 示例代码 ```js import CloudBase from "@cloudbase/manager-node"; const { storage } = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId", // 云开发环境ID,可在腾讯云云开发控制台获取 }); async function test() { const info = await storage.getFileInfo("files/data.txt"); console.log(info); } test(); ``` ## deleteFile ### 1. 接口描述 接口功能:批量删除文件 接口声明:`deleteFile(cloudPathList: string[])` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ------------- | ---- | --------------- | ----------------------------------------------- | | cloudPathList | 是 | `Array` | 云端文件路径组成的字符串数组 `['dir/data.txt']` | ### 3. 返回结果 无 ### 4. 示例代码 ```js import CloudBase from "@cloudbase/manager-node"; const { storage } = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId", // 云开发环境ID,可在腾讯云云开发控制台获取 }); async function test() { await storage.deleteFile(["files/data.txt"]); } test(); ``` ## deleteDirectory ### 1. 接口描述 接口功能:删除文件夹 接口声明:`deleteDirectory(cloudPath: string)` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | -------------- | | cloudPath | 是 | String | 云端文件夹路径 | **注意:** 当 cloudPath 不存在时,SDK 不会抛出错误。 ### 3. 返回结果 无 ### 4. 示例代码 ```js import CloudBase from "@cloudbase/manager-node"; const { storage } = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId", // 云开发环境ID,可在腾讯云云开发控制台获取 }); async function test() { await storage.deleteDirectory("files/"); } test(); ``` ## getTemporaryUrl ### 1. 接口描述 接口功能:获取文件临时下载链接 接口声明:`getTemporaryUrl(fileList: (string | TempUrlInfo)[]):Promise>` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | -------- | ---- | --------------------------------- | ----------------------------------- | | fileList | 是 | `String` 或 `Array.` | 云端文件路径数组或 TempUrlInfo 数组 | #### TempUrlInfo | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | ------------------------------ | | cloudPath | 是 | String | 云端文件路径 | | maxAge | 是 | Number | 临时下载链接有效时间,单位:秒 | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | ---- | ---- | --------------------- | ---------------- | | - | 是 | `Array.` | 文件下载链接列表 | #### FileUrlItem | 字段 | 必填 | 类型 | 说明 | | ------ | ---- | ------ | -------- | | fileId | 是 | String | 文件 Id | | url | 是 | String | 下载链接 | ### 4. 示例代码 ```js import CloudBase from "@cloudbase/manager-node"; const { storage } = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId", // 云开发环境ID,可在腾讯云云开发控制台获取 }); async function test() { const urls = await storage.getTemporaryUrl(["files/data.txt"]); const urls2 = await storage.getTemporaryUrl([ { cloudPath: "files/data.txt", maxAge: 86400, }, ]); for (let item in urls) { console.log(item.url); } } test(); ``` ## getStorageAcl ### 1. 接口描述 接口功能:获取文件存储权限 接口声明:`getStorageAcl(): Promise` ### 2. 输入参数 空 ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | ---- | ---- | ------ | -------- | | - | 是 | String | 权限类型 | 所有权限类型: - READONLY:所有用户可读,仅创建者和管理员可写 - PRIVATE:仅创建者及管理员可读写 - ADMINWRITE:所有用户可读,仅管理员可写 - ADMINONLY:仅管理员可读写 ### 4. 示例代码 ```js import CloudBase from "@cloudbase/manager-node"; const { storage } = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId", // 云开发环境ID,可在腾讯云云开发控制台获取 }); async function test() { const acl = await storage.getStorageAcl(); console.log(acl); } test(); ``` ## setStorageAcl ### 1. 接口描述 接口功能:设置文件存储权限 接口声明:`setStorageAcl(acl: string):Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ---- | ---- | -------- | ---------------- | | acl | 是 | `String` | 文件存储权限描述 | acl 支持选项: - READONLY:所有用户可读,仅创建者和管理员可写 - PRIVATE:仅创建者及管理员可读写 - ADMINWRITE:所有用户可读,仅管理员可写 - ADMINONLY:仅管理员可读写 ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | ------- | | RequestId | 是 | String | 请求 ID | ### 4. 示例代码 ```js import CloudBase from "@cloudbase/manager-node"; const { storage } = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId", // 云开发环境ID,可在腾讯云云开发控制台获取 }); async function test() { await storage.setStorageAcl("READONLY"); } test(); ``` --- ## 用户管理 # 用户管理 ## 获取用户列表 ### 1. 接口描述 接口功能:获取指定云环境下的用户列表 接口声明:`getEndUserList(options: Object): Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ------ | ---- | ------ | ------------ | | limit | 是 | Number | 拉取用户数量 | | offset | 是 | Number | 偏移量 | ### 3. 返回结果 | 字段 | 类型 | 说明 | | --------- | ------------------------ | ------------ | | Total | Number | 用户总数 | | RequestId | String | 请求唯一标识 | | Users | `Array` | 用户信息列表 | **EndUserInfo** | 字段 | 类型 | 说明 | | ----------- | ------- | -------------- | | UUId | String | 用户唯一 ID | | WXOpenId | String | 微信 ID | | QQOpenId | String | qq ID | | Phone | String | 手机号 | | Email | String | 邮箱 | | NickName | String | 昵称 | | Gender | String | 性别 | | AvatarUrl | String | 头像地址 | | UpdateTime | String | 更新时间 | | CreateTime | String | 创建时间 | | IsAnonymous | Boolean | 是否为匿名用户 | | IsDisabled | Boolean | 是否禁用账户 | | HasPassword | Boolean | 是否设置过密码 | | UserName | String | 用户名 | ### 4. 示例代码 ```javascript const cloudbaseConfig = { secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId" // 云开发环境ID,可在腾讯云云开发控制台获取 }; const app = new CloudBase(cloudBaseConfig); async function main() { const { Users } = await app.user.getEndUserList({ limit: 20, offset: 0 }); console.log(">>> Users are:", Users); } main(); ``` ## 创建新用户 ### 1. 接口描述 接口功能:在指定云环境下,创建用户名和密码 接口声明:`createEndUser(options: Object): Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | -------- | ---- | ------ | ------ | | username | 是 | String | 用户名 | | password | 是 | String | 密码 | :::caution 密码强度要求 密码长度不小于 8 位,不大于 32 位,需要包含字母和数字。 ::: ### 3. 返回结果 | 字段 | 类型 | 说明 | | --------- | ----------- | ------------ | | RequestId | String | 请求唯一标识 | | User | EndUserInfo | 用户信息 | ### 4. 示例代码 ```javascript const cloudbaseConfig = { secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId" // 云开发环境ID,可在腾讯云云开发控制台获取 }; const app = new CloudBase(cloudBaseConfig); async function main() { try { const { User } = await app.user.createEndUser({ username: "your username", password: "your password" }); console.log(">>> 新建用户信息:", User); } catch (error) { console.log(">>> 新建用户失败:", error.message); } } main(); ``` ## 修改用户账户信息 ### 1. 接口描述 接口功能:修改指定云环境下的特定用户的信息 接口声明:`modifyEndUser(options: Object): Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | -------- | ---- | ------ | ------------------ | | uuid | 是 | String | 云开发用户唯一标识 | | username | 否 | String | 新用户名 | | password | 否 | String | 新密码 | ### 3. 返回结果 | 字段 | 类型 | 说明 | | --------- | ------ | ------------ | | RequestId | String | 请求唯一标识 | ### 4. 示例代码 ```javascript const cloudbaseConfig = { secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId" // 云开发环境ID,可在腾讯云云开发控制台获取 }; const app = new CloudBase(cloudBaseConfig); async function main() { try { await app.user.modifyEndUser({ uuid: "your user uuid", username: "your new username", password: "your new password" }); console.log(">>> 修改用户账户信息成功"); } catch (error) { console.log(">>> 修改用户账户信息失败:", error.message); } } main(); ``` ## 修改用户信息 ### 1. 接口描述 接口功能:修改指定云环境下的特定用户的信息 接口声明:`updateEndUser(options: Object): Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | ------------------ | | uuid | 是 | String | 云开发用户唯一标识 | | nickName | 是 | String | 新昵称 | | gender | 是 | String | 新性别, `MALE | FEMALE` | | avatarUrl | 是 | String | 新头像 | | country | 是 | String | 新国家 | | province | 是 | String | 新省份 | | city | 是 | String | 新城市 | ### 3. 返回结果 | 字段 | 类型 | 说明 | | --------- | ------ | ------------ | | RequestId | String | 请求唯一标识 | ### 4. 示例代码 ```javascript const cloudbaseConfig = { secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId" // 云开发环境ID,可在腾讯云云开发控制台获取 }; const app = new CloudBase(cloudBaseConfig); async function main() { try { await app.user.updateEndUser({ uuid: "your user uuid", nickName: "your new nickName", gender: "your new gender", avatarUrl: "your new avatarUrl", country: "your new country", province: "your new province", city: "your new city" }); console.log(">>> 修改用户信息成功"); } catch (error) { console.log(">>> 修改用户信息失败:", error.message); } } main(); ``` ## 设置用户状态 ### 1. 接口描述 接口功能:停用或启用云环境下的特定用户 接口声明:`setEndUserStatus(options: object): Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | ------ | ---- | ------ | --------------------- | | uuid | 是 | String | 云开发用户唯一标识 | | status | 是 | String | 'DISABLE'或者'ENABLE' | ### 3. 返回结果 | 字段 | 类型 | 说明 | | --------- | ------ | ------------ | | RequestId | String | 请求唯一标识 | ### 4. 示例代码 ```javascript const cloudbaseConfig = { secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId" // 云开发环境ID,可在腾讯云云开发控制台获取 }; const app = new CloudBase(cloudBaseConfig); async function main() { try { const { RequestId } = await app.user.setEndUserStatus({ uuid: "User uuid", status: "DISABLE" }); console.log(">>> 停用成功"); } catch (error) { console.log(">>> 停用失败", error.message); } } main(); ``` ## 批量删除用户 ### 1. 接口描述 接口功能:批量删除指定云环境下的用户 接口声明:`deleteEndUsers(options: Object): Promise` ### 2. 输入参数 | 字段 | 必填 | 类型 | 说明 | | -------- | ---- | ------------------- | -------------- | | userList | 是 | `Array` | 用户 uuid 列表 | ### 3. 返回结果 | 字段 | 必填 | 类型 | 说明 | | --------- | ---- | ------ | ------------ | | RequestId | 是 | String | 请求唯一标识 | ### 4. 示例代码 ```javascript const cloudbaseConfig = { secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId" // 云开发环境ID,可在腾讯云云开发控制台获取 }; const app = new CloudBase(cloudBaseConfig); async function main() { try { const { RequestId } = await app.user.deleteEndUsers({ userList: [ "uuid a", "uuid b", "uuid c" // ...... ] }); console.log(">>> 批量删除成功"); } catch (error) { console.log(">>> 批量删除失败", error.message); } } main(); ``` --- ## 广告数据上报 # 广告数据上报 ## analytics #### 1. 接口描述 接口功能:上报广告数据 接口声明:`analytics(object: Object): Promise` :::tip 提示 自 SDK 2.5.0 版本起支持此接口 ::: #### 2. 输入参数 | 字段 | 类型 | 必填 | 说明 | | ----------- | ----------- | ---- | ------------------------- | | report_type | string | 是 | 上报类型,目前支持 "mall" | | report_data | IReportData | 是 | 上报内容 | ##### IReportData | 字段 | 类型 | 必填 | 说明 | | ------------- | ------------- | ---- | ------------------------------------------------------------------------------------------------ | | action_time | number | 否 | 上报时间,不填默认取当前客户端时间,单位为秒 | | action_type | string | 是 | 行为类型 如 访问 visit_store,分享 share,加入购物车 add_to_cart 等,详细类型参考表 action_types | | click_id | string | 否 | 广告平台会在 URL 增加 click_id,取值方式[参考](https://ad.weixin.qq.com/guide/457) | | action_param | IActionParam | 否 | 行为所带的参数 | | product_param | IProductParam | 否 | 商品结构内容 | ##### IActionParam | 字段 | 类型 | 必填 | 说明 | | ---------- | ------ | ---- | --------------------------------------------------------- | | value | number | 否 | 行为所带的参数,转化行为价值(例如金额) | | leads_type | string | 否 | 行为来源,目前支持 PHONE(电话直呼),RESERVE(表单预约) | ##### IProductParam | 字段 | 类型 | 必填 | 说明 | | ----------------------- | ------ | ---- | ---------------------------------------------- | | product_yun_type | string | 否 | 商品 goods ,优惠券 coupon, 搜索词 search_term | | product_yun_id | string | 否 | 商品 id | | product_yun_category | string | 否 | 商品类目 自定义 | | product_yun_keywords | string | 否 | 商品关键词 | | product_yun_price | number | 否 | 商品原价 | | product_yun_value | number | 否 | 商品成交价 | | product_yun_name | string | 否 | 商品名 | | product_yun_id_ad | string | 否 | 广告商品库中商品 id | | product_yun_category_ad | string | 否 | 广告商品库中商品类目 | ##### action_types | 类型值 | 说明 | | --------------- | ---------- | | visit_store | 访问 | | share | 分享 | | consult | 咨询 | | claim_offer | 卡券领取 | | add_to_cart | 加入购物车 | | add_to_wishlist | 收藏 | | complete_order | 下单 | | purchase | 支付 | | search | 搜索 | | deliver | 发货 | | sign_in | 签收 | #### 3. 输出参数 无 #### 4. 示例代码 ```javascript const tcb = require("@cloudbase/node-sdk"); const app = tcb.init({ env: "xxx" }); app.analytics({ report_type: "mall", report_data: { action_type: "visit_store", action_param: { value: 100 }, product_param: { product_yun_type: "goods", product_yun_id: 1, product_yun_keywords: "优衣库", product_yun_price: 200, product_yun_value: 100, product_yun_name: "优衣库Utee-迪士尼" } } }); ``` --- ## Auth 登录认证 # Auth 登录认证 ## getUserInfo ### 1. 接口描述 接口功能:获取用户信息 接口声明:`getUserInfo(): IGetUserInfoResult` ### 2. 输入参数 无 ### 3. 返回结果 | 字段 | 类型 | 必填 | 说明 | | -------------- | -------- | ---- | ------------------------------------------- | | `openId` | `string` | 是 | 微信 `openId`,非微信授权登录则空 | | `appId` | `string` | 是 | 微信 `appId`,非微信授权登录则空 | | `uid` | `string` | 是 | 用户唯一 ID | | `customUserId` | `string` | 是 | 开发者自定义的用户唯一 id,非自定义登录则空 | ### 4. 示例代码 ```ts import tcb from '@cloudbase/node-sdk' const app = tcb.init({ env: 'xxx' }) const auth = app.auth() exports.main = async (event, context) => { const { openId, //微信openId,非微信授权登录则空 appId, //微信appId,非微信授权登录则空 uid, //用户唯一ID customUserId //开发者自定义的用户唯一id,非自定义登录则空 } = auth.getUserInfo() console.log(openId, appId, uid, customUserId) } ``` ## getEndUserInfo ### 1. 接口描述 接口功能:获取用户信息 接口声明:`getEndUserInfo(uid?: string, opts?: ICustomReqOpts): Promise` :::tip 提示 自 Node SDK 2.2.5 版本起支持此接口 ::: ### 2. 输入参数 | 字段 | 类型 | 必填 | 说明 | | ------ | -------- | ---- | --------------------------------------------------------- | | `uid` | `string` | 否 | 云开发用户身份标识。如果不传入,则从环境变量中读取用户信息。 | | `opts` | `Object` | 否 | 自定义请求配置 | ### 3. 返回结果 | 字段 | 类型 | 必填 | 说明 | | ----------- | ------------- | ---- | -------------- | | `userInfo` | `EndUserInfo` | 是 | 云开发用户信息 | | `requestId` | `string` | 否 | 请求唯一标识 | **EndUserInfo**: | 字段 | 类型 | 说明 | | -------------- | --------------------------------- | ------------------------------------------- | | `openId` | `string` | 微信 openId,非微信授权登录则空 | | `appId` | `string` | 微信 appId,非微信授权登录则空 | | `uid` | `string` | 用户唯一 ID | | `customUserId` | `string` | 开发者自定义的用户唯一 id,非自定义登录则空 | | `envName` | `string` | 云开发环境名 | | `nickName` | `string` | 用户昵称 | | `email` | `string` | 用户登录邮箱 | | `username` | `string` | 用户登录用户名 | | `hasPassword` | `boolean` | 用户是否设置密码 | | `gender` | `"MALE" \| "FEMALE" \| "UNKNOWN"` | 云开发登录用户名 | | `country` | `string` | 地理位置(国家) | | `province` | `string` | 地理位置(省份) | | `city` | `string` | 地理位置(城市) | | `avatarUrl` | `string` | 用户头像地址 | | `qqMiniOpenId` | `string` | 用户绑定的 qq 小程序标识 | ### 4. 示例代码 ```ts import tcb from '@cloudbase/node-sdk' const app = tcb.init({ env: "xxx" }); const auth = app.auth(); exports.main = async (event, context) => { try { const { userInfo } = await auth.getEndUserInfo("your user uuid"); console.log(userInfo); } catch (error) { console.log(error.message); } }; ``` ## queryUserInfo ### 1. 接口描述 接口功能:获取用户信息 接口声明:`queryUserInfo(query: IUserInfoQuery, opts?: ICustomReqOpts): Promise` :::tip 提示 自 Node SDK 2.6.1 版本起支持此接口 ::: ### 2. 输入参数 | 字段 | 类型 | 必填 | 说明 | | ----- | -------------- | ---- | -------------------- | | `query` | `IUserInfoQuery` | 否 | 云开发用户身份标识。 | | `opts` | `Object` | 否 | 自定义请求配置 | ### IUserInfoQuery | 字段 | 类型 | 必填 | 说明 | | ------------ | -------- | ---- | ----------------------------------------------------------------- | | `platform` | `string` | 否 | 登录类型,已支持 PHONE, USERNAME, EMAIL,CUSTOM | | `platformId` | `string` | 否 | 登录标识,对应 platform 分别为手机号,用户名,邮箱,自定义登录 ID | | `uid` | `string` | 否 | 用户唯一 ID,若指定该字段,则优先用该字段搜索 | ### 3. 返回结果 | 字段 | 类型 | 必填 | 说明 | | ----------- | ------------- | ---- | -------------- | | `userInfo` | `EndUserInfo` | 是 | 云开发用户信息 | | `requestId` | `string` | 否 | 请求唯一标识 | **EndUserInfo**: | 字段 | 类型 | 说明 | | -------------- | --------------------------------- | ------------------------------------------- | | `openId` | `string` | 微信 openId,非微信授权登录则空 | | `appId` | `string` | 微信 appId,非微信授权登录则空 | | `uid` | `string` | 用户唯一 ID | | `customUserId` | `string` | 开发者自定义的用户唯一 id,非自定义登录则空 | | `envName` | `string` | 云开发环境名 | | `nickName` | `string` | 用户昵称 | | `email` | `string` | 用户登录邮箱 | | `username` | `string` | 用户登录用户名 | | `hasPassword` | `boolean` | 用户是否设置密码 | | `gender` | `"MALE" \| "FEMALE" \| "UNKNOWN"` | 云开发登录用户名 | | `country` | `string` | 地理位置(国家) | | `province` | `string` | 地理位置(省份) | | `city` | `string` | 地理位置(城市) | | `avatarUrl` | `string` | 用户头像地址 | | `qqMiniOpenId` | `string` | 用户绑定的 qq 小程序标识 | ### 4. 示例代码 ```ts import tcb from '@cloudbase/node-sdk' const app = tcb.init({ env: "xxx" }); const auth = app.auth(); exports.main = async (event, context) => { try { const { userInfo } = await auth.getEndUserInfo("your user uuid"); console.log(userInfo); } catch (error) { console.log(error.message); } }; ``` ## getClientIP ### 1. 接口描述 接口功能:获取客户端 IP 接口声明:`getClientIP(): string` ### 2. 输入参数 无 ### 3. 返回结果 | 字段 | 类型 | 必填 | 说明 | | ---- | ------ | ---- | --------- | | - | string | 是 | 客户端 IP | ### 4. 示例代码 ```ts import tcb from '@cloudbase/node-sdk' const app = tcb.init({ env: 'xxx' }) const auth = app.auth() exports.main = async (event, context) => { const ip = auth.getClientIP() // string console.log(ip) } ``` ## createTicket ### 1. 接口描述 接口功能:获取自定义登录的登录凭据 ticket 接口声明:`createTicket: (customUserId: string, options?: ICreateTicketOpts) => string` ### 2. 输入参数 | 字段 | 类型 | 必填 | 说明 | | -------------------- | -------- | ---- | ------------------------------ | | `customUserId` | `string` | 是 | 开发者自定义的用户唯一 id | | `ICreateTicketOpts` | `string` | 是 | 微信 `appId`,非微信授权登录则空 | `ICreateTicketOpts` | 字段 | 类型 | 必填 | 说明 | | --------- | ------ | ---- | ----------------------- | | `refresh` | `number` | 否 | `access_token` 的刷新时间 | | `expire` | `number` | 否 | `access_token` 的过期时间 | ### 3. 返回结果 | 字段 | 类型 | 必填 | 说明 | | ---- | ------ | ---- | --------------------- | | - | string | 是 | 自定义登录凭据 ticket | ### 4. 示例代码 ```ts import tcb from '@cloudbase/node-sdk' const app = tcb.init({ env: 'xxx', credentials: require('/path/to/your/tcb_custom_login.json') }) const auth = app.auth() const customUserId = '123456' // 开发者自定义的用户唯一id const ticket = auth.createTicket(customUserId, { refresh: 3600 * 1000 // access_token的刷新时间 }) console.log(ticket) ``` --- ## 更新日志 # 更新日志 ## v3.4.0 - [add] 新增 `tcb.SYMBOL_DEFAULT_ENV` 用于指定默认环境 ## v3.1.0 - [add] 新增 [sendTemplateNotification](/api-reference/server/node-sdk/templateNotify) 用于发送消息通知 ## v3.0.0 功能特性变更: 1. [change] Node.js >=12,即不再保证更低版本的兼容性,产品特性上控制台可以考虑不再支持新增 Node.js12 以下的版本 2. [change] 云函数中,初始化未指定环境 ID,使用当前云函数环境 ID,原来使用的是云开发默认环境,即不再需要指定 `init({env: SYMBOL_CURRENT_ENV})`,指定了也没关系 3. [change] 非云函数环境下默认开启 `keepalive` 其他变更: 1. [refactor] 整体重构优化代码 2. [refactor] TS 导出类型重构,完善类型导出,DB 类型直接导出 `@cloudbase/database` 的类型定义 3. [refactor] 更新 `axios、jsonwebtoken、xml2js、@cloudbase/signature-nodejs` 等依赖库版本 4. [refactor] 移除 `request` 包,改为原生实现,解决 `request` 不维护问题,优化请求处理逻辑 5. [test] 补充优化单元测试用例,提升单元测试覆盖率 ## v2.3.0 - [add] 新增 [updateAndReturn](/api-reference/server/node-sdk/database#updateandreturn) 接口 - [refactor] 重构 aggregate 接口 ## v2.2.5 - [add] 新增 [getEndUserInfo](/api-reference/server/node-sdk/auth#getenduserinfo) 接口 ## v2.2.4 - [fix] 修复获取用户信息接口 ## v2.2.3 - [add] 支持云开发容器免秘钥调用 ## v2.2.1 - [add] 数据库条件查询,批量插入支持事务 ## v2.1.1 - [fix] 修复数据库处理 query 或 data 内容时 undefined 转为 null 导致报错的问题 ## v2.1.0 - [add] 新增获取云函数下全部环境变量方法 [getCloudbaseContext](/api-reference/server/node-sdk/env#getCloudbaseContext) - [add] 新增 env 参数校验逻辑,若 init 时未指定 env,则 warning 提示使用默认环境, 若指定 env 但请求时发现为空,则抛错处理 - [add][createticket](/api-reference/server/node-sdk/auth#createTicket) 时 校验私钥中环境与 init 指定环境是否一致,不一致则报错 ## v2.0.2 - [add] 新增扩展注册,调用方法 ## v2.0.1 - [fix] 修复 db transaction add 接口未携带事务 ID 导致异常问题 ## v2.0.0 - [add] 支持 db 新特性&灰度兼容 ## v1.1.1 - [fix] 修复函数调函数时请求签名问题 ## v1.1.0 - [add] 支持函数灰度发布 - [fix] 修复 elemMatch 中使用 neq 无效 bug ## v1.0.2 - [fix] 本地调试逻辑优化 ## v1.0.0 - [add] 迁移 tcb-admin-node sdk 功能至本仓库 --- ## 云托管 # 云托管 ## callContainer ### 1. 接口描述 接口功能:调用云托管服务 接口声明:`callContainer(callContainerOptions: ICallContainerOptions, opts?: ICustomReqOpts): Promise>` ### 2. 输入参数 | 字段 | 类型 | 必填 | 说明 | | ---------------------- | ------------------------------ | ---- | -------------------------------------------------------------- | | `callContainerOptions` | `ICallContainerOptions` | 是 | 云托管调用请求参数 | | `opts` | `ICustomReqOpts` | 否 | 自定义配置,目前支持 SDK 请求超时时间设置,`{timeout: number}` | `ICallContainerOptions` | 字段 | 类型 | 必填 | 说明 | | -------- | ------------------------ | ---- | ------------- | | `name` | `string` | 是 | 云托管服务名 | | `method` | `string` | 否 | HTTP 请求方法 | | `path` | `string` | 否 | HTTP 请求路径 | | `header` | `Record` | 否 | HTTP 请求头 | | `data` | `object` | 否 | HTTP 请求体 | ### 3. 返回结果 `Promise>` | 字段 | 类型 | 必填 | 说明 | | ------------ | ------------------------ | ---- | ----------------------------- | | `requestId` | `string` | 否 | RequestId,用于错误排查 | | `statusCode` | `number` | 否 | HTTP 响应状态码,用于错误排查 | | `header` | `Record` | 否 | HTTP 响应头,用于错误排查 | | `data` | `ResultT` | 否 | HTTP 响应体数据 | > 函数执行报错,将通过异常抛出 ### 4. 示例代码 ```ts import tcb from "@cloudbase/node-sdk"; exports.main = async (event, context) => { const { httpContext } = context; const { url, httpMethod } = httpContext; console.log(`[${httpMethod}][${url}]`); const tcbapp = tcb.init({ context }); const result = await tcbapp.callContainer( { name: "helloworld", method: "POST", path: "/abc", data: { key1: "test value 1", key2: "test value 2", }, }, { timeout: 5000, } ); console.log(result); }; ``` --- ## Aggregate # Aggregate 数据库集合的聚合操作实例 ### [Aggregate.addFields(object: Object): Aggregate](./stages/addFields) 描述: 聚合阶段。添加新字段到输出的记录。经过 addFields 聚合阶段,输出的所有记录中除了输入时带有的字段外,还将带有 addFields 指定的字段。 ### [Aggregate.bucket(object: Object): Aggregate](./stages/bucket) 描述: 聚合阶段。将输入记录根据给定的条件和边界划分成不同的组,每组即一个 bucket。 ### [Aggregate.bucketAuto(object: Object): Aggregate](./stages/bucketAuto) 描述: 聚合阶段。将输入记录根据给定的条件划分成不同的组,每组即一个 bucket。与 bucket 的其中一个不同之处在于无需指定 boundaries,bucketAuto 会自动尝试将记录尽可能平均的分散到每组中。 ### [Aggregate.count(fieldName: string): Aggregate](./stages/count) 描述: 聚合阶段。计算上一聚合阶段输入到本阶段的记录数,输出一个记录,其中指定字段的值为记录数。 ### [Aggregate.end(): Promise\](./stages/end) 描述: 聚合阶段。标志聚合操作定义完成,发起实际聚合操作 ### [Aggregate.geoNear(options: Object): Aggregate](./stages/geoNear) 描述: 聚合阶段。将记录按照离给定点从近到远输出。 ### [Aggregate.group(object: Object): Aggregate](./stages/group) 描述: 聚合阶段。将输入记录按给定表达式分组,输出时每个记录代表一个分组,每个记录的 \_id 是区分不同组的 key。输出记录中也可以包括累计值,将输出字段设为累计值即会从该分组中计算累计值。 ### [Aggregate.limit(value: number): Aggregate](./stages/limit) 描述: 聚合阶段。限制输出到下一阶段的记录数。 ### [Aggregate.lookup(object: Object): Aggregate](./stages/lookup) 描述: 聚合阶段。联表查询。与同个数据库下的一个指定的集合做 left outer join(左外连接)。对该阶段的每一个输入记录,lookup 会在该记录中增加一个数组字段,该数组是被联表中满足匹配条件的记录列表。lookup 会将连接后的结果输出给下个阶段。 ### [Aggregate.match(object: Object): Aggregate](./stages/match) 描述: 聚合阶段。根据条件过滤文档,并且把符合条件的文档传递给下一个流水线阶段。 ### [Aggregate.project(object: Object): Aggregate](./stages/project) 描述: 聚合阶段。把指定的字段传递给下一个流水线,指定的字段可以是某个已经存在的字段,也可以是计算出来的新字段。 ### [Aggregate.replaceRoot(object: Object): Aggregate](./stages/replaceRoot) 描述: 聚合阶段。指定一个已有字段作为输出的根节点,也可以指定一个计算出的新字段作为根节点。 ### [Aggregate.sample(size: number): Aggregate](./stages/sample) 描述: 聚合阶段。随机从文档中选取指定数量的记录。 ### [Aggregate.skip(value: number): Aggregate](./stages/skip) 描述: 聚合阶段。指定一个正整数,跳过对应数量的文档,输出剩下的文档。 ### [Aggregate.sort(object: Object): Aggregate](./stages/sort) 描述: 聚合阶段。根据指定的字段,对输入的文档进行排序。 ### [Aggregate.sortByCount(object: Object): Aggregate](./stages/sortByCount) 描述: 聚合阶段。根据传入的表达式,将传入的集合进行分组(group)。然后计算不同组的数量,并且将这些组按照它们的数量进行排序,返回排序后的结果。 ### [Aggregate.unwind(value: string|object): Aggregate](./stages/unwind) 描述: 聚合阶段。使用指定的数组字段中的每个元素,对文档进行拆分。拆分后,文档会从一个变为一个或多个,分别对应数组的每个元素。 ### [Aggregate.bucket(object: Object): Aggregate](./stages/bucket) 描述: 聚合阶段。将输入记录根据给定的条件和边界划分成不同的组,每组即一个 bucket。 ### [Aggregate.bucketAuto(object: Object): Aggregate](./stages/bucketAuto) 描述: 聚合阶段。将输入记录根据给定的条件划分成不同的组,每组即一个 bucket。与 bucket 的其中一个不同之处在于无需指定 boundaries,bucketAuto 会自动尝试将记录尽可能平均的分散到每组中。 ### [Aggregate.count(fieldName: string): Aggregate](./stages/count) 描述: 聚合阶段。计算上一聚合阶段输入到本阶段的记录数,输出一个记录,其中指定字段的值为记录数。 ### [Aggregate.end(): Promise\](./stages/end) 描述: 标志聚合操作定义完成,发起实际聚合操作。 ### [Aggregate.geoNear(options: Object): Aggregate](./stages/geoNear) 描述: 聚合阶段。将记录按照离给定点从近到远输出。 ### [Aggregate.group(object: Object): Aggregate](./stages/group) 描述: 聚合阶段。将输入记录按给定表达式分组,输出时每个记录代表一个分组,每个记录的 \_id 是区分不同组的 key。输出记录中也可以包括累计值,将输出字段设为累计值即会从该分组中计算累计值。 ### [Aggregate.limit(value: number): Aggregate](./stages/limit) 描述: 聚合阶段。限制输出到下一阶段的记录数。 ### [Aggregate.lookup(object: Object): Aggregate](./stages/lookup) 描述: 聚合阶段。描述: 聚合阶段。联表查询。与同个数据库下的一个指定的集合做 left outer join(左外连接)。对该阶段的每一个输入记录,lookup 会在该记录中增加一个数组字段,该数组是被联表中满足匹配条件的记录列表。lookup 会将连接后的结果输出给下个阶段。 ### [Aggregate.match(object: Object): Aggregate](./stages/match) 描述: 聚合阶段。根据条件过滤文档,并且把符合条件的文档传递给下一个流水线阶段。 ### [Aggregate.project(object: Object): Aggregate](./stages/project) 描述: 聚合阶段。把指定的字段传递给下一个流水线,指定的字段可以是某个已经存在的字段,也可以是计算出来的新字段。 ### [Aggregate.replaceRoot(object: Object): Aggregate](./stages/replaceRoot) 描述: 聚合阶段。指定一个已有字段作为输出的根节点,也可以指定一个计算出的新字段作为根节点。 ### [Aggregate.sample(size: number): Aggregate](./stages/sample) 描述: 聚合阶段。随机从文档中选取指定数量的记录。 ### [Aggregate.skip(value: number): Aggregate](./stages/skip) 描述: 聚合阶段。指定一个正整数,跳过对应数量的文档,输出剩下的文档。 ### [Aggregate.sort(object: Object): Aggregate](./stages/sort) 描述: 聚合阶段。根据指定的字段,对输入的文档进行排序。 ### [Aggregate.sortByCount(object: Object): Aggregate](./stages/sortByCount) 描述: 聚合阶段。根据传入的表达式,将传入的集合进行分组(group)。然后计算不同组的数量,并且将这些组按照它们的数量进行排序,返回排序后的结果。 ### [Aggregate.unwind(value: string|object): Aggregate](./stages/unwind) 描述: 聚合阶段。使用指定的数组字段中的每个元素,对文档进行拆分。拆分后,文档会从一个变为一个或多个,分别对应数组的每个元素。 --- ## AggregateCommand # AggregateCommand 数据库聚合操作符,通过 db.command.aggregate 获取 ### [AggregateCommand.abs(value: number | Expression\)](./operators/abs) 描述: 聚合操作符。返回一个数字的绝对值。 ### [AggregateCommand.add(value: Expression[])](./operators/add) 描述: 聚合操作符。将数字相加或将数字加在日期上。如果数组中的其中一个值是日期,那么其他值将被视为毫秒数加在该日期上。 ### [AggregateCommand.addToSet(value: Expression)](./operators/addToSet) 描述: 聚合操作符。聚合运算符。向数组中添加值,如果数组中已存在该值,不执行任何操作。它只能在 group stage 中使用。 ### [AggregateCommand.allElementsTrue(value: Expression[])](./operators/allElementsTrue) 描述: 聚合操作符。输入一个数组,或者数组字段的表达式。如果数组中所有元素均为真值,那么返回 true,否则返回 false。空数组永远返回 true。 ### [AggregateCommand.and(value: Expression[])](./operators/and) 描述: 聚合操作符。给定多个表达式,and 仅在所有表达式都返回 true 时返回 true,否则返回 false。 ### [AggregateCommand.anyElementTrue(value: Expression[])](./operators/anyElementTrue) 描述: 聚合操作符。输入一个数组,或者数组字段的表达式。如果数组中任意一个元素为真值,那么返回 true,否则返回 false。空数组永远返回 false。 ### [AggregateCommand.arrayElemAt(value: Expression[])](./operators/arrayElemAt) 描述: 聚合操作符。返回在指定数组下标的元素。 ### [AggregateCommand.arrayToObject(value: any)](./operators/arrayToObject) 描述: 聚合操作符。将一个数组转换为对象。 ### [AggregateCommand.avg(value: Expression\)](./operators/avg) 描述: 聚合操作符。返回一组集合中,指定字段对应数据的平均值。 ### [AggregateCommand.ceil(value: Expression\)](./operators/ceil) 描述: 聚合操作符。向上取整,返回大于或等于给定数字的最小整数。 ### [AggregateCommand.cmp(value: Expression[])](./operators/cmp) 描述: 聚合操作符。给定两个值,返回其比较值: ### [AggregateCommand.concat(value: Expression[])](./operators/concat) 描述: 聚合操作符。连接字符串,返回拼接后的字符串。 ### [AggregateCommand.concatArrays(value: Expression[])](./operators/concatArrays) 描述: 聚合操作符。将多个数组拼接成一个数组。 ### [AggregateCommand.cond(value: any)](./operators/cond) 描述: 聚合操作符。计算布尔表达式,返回指定的两个值其中之一。 ### [AggregateCommand.dateFromParts(value: any)](./operators/dateFromParts) 描述: 聚合操作符。给定日期的相关信息,构建并返回一个日期对象。 ### [AggregateCommand.dateFromString(value: any)](./operators/dateFromString) 描述: 聚合操作符。将一个日期/时间字符串转换为日期对象 ### [AggregateCommand.dateToString(value: any)](./operators/dateToString) 描述: 聚合操作符。根据指定的表达式将日期对象格式化为符合要求的字符串。 ### [AggregateCommand.dayOfMonth(value: Expression\)](./operators/dayOfMonth) 描述: 聚合操作符。返回日期字段对应的  天数(一个月中的哪一天),是一个介于 1 至 31 之间的数字。 ### [AggregateCommand.dayOfWeek(value: Expression\)](./operators/dayOfWeek) 描述: 聚合操作符。返回日期字段对应的天数(一周中的第几天),是一个介于 1(周日)到 7(周六)之间的整数。 ### [AggregateCommand.dayOfYear(value: Expression\)](./operators/dayOfYear) 描述: 聚合操作符。返回日期字段对应的天数(一年中的第几天),是一个介于 1 到 366 之间的整数。 ### [AggregateCommand.divide(value: Expression[])](./operators/divide) 描述: 聚合操作符。传入被除数和除数,求商。 ### [AggregateCommand.eq(value: Expression[])](./operators/eq) 描述: 聚合操作符。匹配两个值,如果相等则返回 true,否则返回 false。 ### [AggregateCommand.exp(value: Expression\)](./operators/exp) 描述: 聚合操作符。取 e(自然对数的底数,欧拉数) 的 n 次方。 ### [AggregateCommand.filter(value: any)](./operators/filter) 描述: 聚合操作符。根据给定条件返回满足条件的数组的子集。 ### [AggregateCommand.first(value: Expression)](./operators/first) 描述: 聚合操作符。返回指定字段在一组集合的第一条记录对应的值。仅当这组集合是按照某种定义排序( sort )后,此操作才有意义。 ### [AggregateCommand.floor(value: Expression\)](./operators/floor) 描述: 聚合操作符。向下取整,返回大于或等于给定数字的最小整数。 ### [AggregateCommand.gt(value: Expression[])](./operators/gt) 描述: 聚合操作符。匹配两个值,如果前者大于后者则返回 true,否则返回 false。 ### [AggregateCommand.gte(value: Expression[])](./operators/gte) 描述: 聚合操作符。匹配两个值,如果前者大于或等于后者则返回 true,否则返回 false。 ### [AggregateCommand.hour(value: Expression\)](./operators/hour) 描述: 聚合操作符。返回日期字段对应的小时数,是一个介于 0 到 23 之间的整数。 ### [AggregateCommand.ifNull(value: Expression[])](./operators/ifNull) 描述: 聚合操作符。计算给定的表达式,如果表达式结果为 null、undefined 或者不存在,那么返回一个替代值;否则返回原值。 ### [AggregateCommand.in(value: Expression[])](./operators/in) 描述: 聚合操作符。给定一个值和一个数组,如果值在数组中则返回 true,否则返回 false。 ### [AggregateCommand.indexOfArray(value: Expression[])](./operators/indexOfArray) 描述: 聚合操作符。在数组中找出等于给定值的第一个元素的下标,如果找不到则返回 -1。 ### [AggregateCommand.indexOfBytes(value: Expression[])](./operators/indexOfBytes) 描述: 聚合操作符。在目标字符串中查找子字符串,并返回第一次出现的 UTF-8 的字节索引(从 0 开始)。如果不存在子字符串,返回 -1。 ### [AggregateCommand.indexOfCP(value: Expression[])](./operators/indexOfCP) 描述: 聚合操作符。在目标字符串中查找子字符串,并返回第一次出现的 UTF-8 的 code point 索引(从 0 开始)。如果不存在子字符串,返回 -1。 ### [AggregateCommand.isArray(value: Expression)](./operators/isArray) 描述: 聚合操作符。判断给定表达式是否是数组,返回布尔值。 ### [AggregateCommand.isoDayOfWeek(value: Expression\)](./operators/isoDayOfWeek) 描述: 聚合操作符。返回日期字段对应的 ISO 8601 标准的天数(一周中的第几天),是一个介于 1(周一)到 7(周日)之间的整数。 ### [AggregateCommand.isoWeek(value: Expression\)](./operators/isoWeek) 描述: 聚合操作符。返回日期字段对应的 ISO 8601 标准的周数(一年中的第几周),是一个介于 1 到 53 之间的整数。 ### [AggregateCommand.isoWeekYear(value: Expression\)](./operators/isoWeekYear) 描述: 聚合操作符。返回日期字段对应的 ISO 8601 标准的天数(一年中的第几天)。 ### [AggregateCommand.last(value: Expression)](./operators/last) 描述: 聚合操作符。返回指定字段在一组集合的最后一条记录对应的值。仅当这组集合是按照某种定义排序( sort )后,此操作才有意义。 ### [AggregateCommand.let(value: any)](./operators/let) 描述: 聚合操作符。自定义变量,并且在指定表达式中使用,返回的结果是表达式的结果。 ### [AggregateCommand.literal(value: any)](./operators/literal) 描述: 聚合操作符。直接返回一个值的字面量,不经过任何解析和处理。 ### [AggregateCommand.ln(value: Expression\)](./operators/ln) 描述: 聚合操作符。计算给定数字在自然对数值。 ### [AggregateCommand.log(value: Expression[])](./operators/log) 描述: 聚合操作符。计算给定数字在给定对数底下的 log 值。 ### [AggregateCommand.log10(value: Expression\)](./operators/log10) 描述: 聚合操作符。计算给定数字在对数底为 10 下的 log 值。 ### [AggregateCommand.lt(value: Expression[])](./operators/lt) 描述: 聚合操作符。匹配两个值,如果前者小于后者则返回 true,否则返回 false。 ### [AggregateCommand.lte(value: Expression[])](./operators/lte) 描述: 聚合操作符。匹配两个值,如果前者小于或等于后者则返回 true,否则返回 false。 ### [AggregateCommand.map(value: any)](./operators/map) 描述: 聚合操作符。类似 JavaScript Array 上的 map 方法,将给定数组的每个元素按给定转换方法转换后得出新的数组。 ### [AggregateCommand.max(value: Expression)](./operators/max) 描述: 聚合操作符。返回一组数值的最大值。 ### [AggregateCommand.mergeObjects(value: Expression\)](./operators/mergeObjects) 描述: 聚合操作符。将多个文档合并为单个文档。 ### [AggregateCommand.millisecond(value: Expression\)](./operators/millisecond) 描述: 聚合操作符。返回日期字段对应的毫秒数,是一个介于 0 到 999 之间的整数。 ### [AggregateCommand.min(value: Expression)](./operators/min) 描述: 聚合操作符。返回一组数值的最小值。 ### [AggregateCommand.minute(value: Expression\)](./operators/minute) 描述: 聚合操作符。返回日期字段对应的分钟数,是一个介于 0 到 59 之间的整数。 ### [AggregateCommand.mod(value: Expression[])](./operators/mod) 描述: 聚合操作符。取模运算,取数字取模后的值。 ### [AggregateCommand.month(value: Expression\)](./operators/month) 描述: 聚合操作符。返回日期字段对应的月份,是一个介于 1 到 12 之间的整数。 ### [AggregateCommand.multiply(value: Expression[])](./operators/multiply) 描述: 聚合操作符。取传入的数字参数相乘的结果。 ### [AggregateCommand.neq(value: Expression[])](./operators/neq) 描述: 聚合操作符。匹配两个值,如果不相等则返回 true,否则返回 false。 ### [AggregateCommand.not(value: Expression)](./operators/not) 描述: 聚合操作符。给定一个表达式,如果表达式返回 true,则 not 返回 false,否则返回 true。注意表达式不能为逻辑表达式(and、or、nor、not)。 ### [AggregateCommand.objectToArray(value: Expression\)](./operators/objectToArray) 描述: 聚合操作符。将一个对象转换为数组。方法把对象的每个键值对都变成输出数组的一个元素,元素形如 { k: \, v: \ }。 ### [AggregateCommand.or(value: Expression[])](./operators/or) 描述: 聚合操作符。给定多个表达式,如果任意一个表达式返回 true,则 or 返回 true,否则返回 false。 ### [AggregateCommand.pow(value: Expression[])](./operators/pow) 描述: 聚合操作符。求给定基数的指数次幂。 ### [AggregateCommand.push(value: any)](./operators/push) 描述: 聚合操作符。在 group 阶段,返回一组中表达式指定列与对应的值,一起组成的数组。 ### [AggregateCommand.range(value: Expression[])](./operators/range) 描述: 聚合操作符。返回一组生成的序列数字。给定开始值、结束值、非零的步长,range 会返回从开始值开始逐步增长、步长为给定步长、但不包括结束值的序列。 ### [AggregateCommand.reduce(value: any)](./operators/reduce) 描述: 聚合操作符。类似 JavaScript 的 reduce 方法,应用一个表达式于数组各个元素然后归一成一个元素。 ### [AggregateCommand.reverseArray(value: Expression\)](./operators/reverseArray) 描述: 聚合操作符。返回给定数组的倒序形式。 ### [AggregateCommand.second(value: Expression\)](./operators/second) 描述: 聚合操作符。返回日期字段对应的秒数,是一个介于 0 到 59 之间的整数,在特殊情况下(闰秒)可能等于 60。 ### [AggregateCommand.setDifference(value: Expression[])](./operators/setDifference) 描述: 聚合操作符,输入两个集合,输出只存在于第一个集合中的元素。 ### [AggregateCommand.setEquals(value: Expression[])](./operators/setEquals) 描述: 聚合操作符,输入两个集合,判断两个集合中包含的元素是否相同(不考虑顺序、去重)。 ### [AggregateCommand.setIntersection(value: Expression[])](./operators/setIntersection) 描述: 聚合操作符,输入两个集合,输出两个集合的交集。 ### [AggregateCommand.setIsSubset(value: Expression[])](./operators/setIsSubset) 描述: 聚合操作符,输入两个集合,判断第一个集合是否是第二个集合的子集。 ### [AggregateCommand.setUnion(value: Expression[])](./operators/setUnion) 描述: 聚合操作符,输入两个集合,输出两个集合的并集。 ### [AggregateCommand.size(value: Expression\)](./operators/size) 描述: 聚合操作符。返回数组长度。 ### [AggregateCommand.slice(value: Expression[])](./operators/slice) 描述: 聚合操作符。类似 JavaScritp 的 slice 方法。返回给定数组的指定子集。 ### [AggregateCommand.split(value: Expression[])](./operators/split) 描述: 聚合操作符。按照分隔符分隔数组,并且删除分隔符,返回子字符串组成的数组。如果字符串无法找到分隔符进行分隔,返回原字符串作为数组的唯一元素。 ### [AggregateCommand.sqrt(value: Expression[])](./operators/sqrt) 描述: 聚合操作符。求平方根。 ### [AggregateCommand.stdDevPop(value: Expression)](./operators/stdDevPop) 描述: 聚合操作符。返回一组字段对应值的标准差。 ### [AggregateCommand.stdDevSamp(value: Expression)](./operators/stdDevSamp) 描述: 聚合操作符。计算输入值的样本标准偏差。如果输入值代表数据总体,或者不概括更多的数据,请改用 db.command.aggregate.stdDevPop。 ### [AggregateCommand.strLenBytes(value: Expression)](./operators/strLenBytes) 描述: 聚合操作符。计算并返回指定字符串中 utf-8 编码的字节数量。 ### [AggregateCommand.strLenCP(value: Expression)](./operators/strLenCP) 描述: 聚合操作符。计算并返回指定字符串的 UTF-8 code points 数量。 ### [AggregateCommand.strcasecmp(value: Expression[])](./operators/strcasecmp) 描述: 聚合操作符。对两个字符串在不区分大小写的情况下进行大小比较,并返回比较的结果。 ### [AggregateCommand.substr(value: Expression[])](./operators/substr) 描述: 聚合操作符。返回字符串从指定位置开始的指定长度的子字符串。它是 db.command.aggregate.substrBytes 的别名,更推荐使用后者。 ### [AggregateCommand.substrBytes(value: Expression[])](./operators/substrBytes) 描述: 聚合操作符。返回字符串从指定位置开始的指定长度的子字符串。子字符串是由字符串中指定的 UTF-8 字节索引的字符开始,长度为指定的字节数。 ### [AggregateCommand.substrCP(value: Expression[])](./operators/substrCP) 描述: 聚合操作符。返回字符串从指定位置开始的指定长度的子字符串。子字符串是由字符串中指定的 UTF-8 字节索引的字符开始,长度为指定的字节数。 ### [AggregateCommand.subtract(value: Expression[])](./operators/subtract) 描述: 聚合操作符。将两个数字相减然后返回差值,或将两个日期相减然后返回相差的毫秒数,或将一个日期减去一个数字返回结果的日期。 ### [AggregateCommand.sum(value: Expression)](./operators/sum) 描述: 聚合操作符。计算并且返回一组字段所有数值的总和。 ### [AggregateCommand.switch(value: any)](./operators/switch) 描述: 聚合操作符。根据给定的 switch-case-default 计算返回值、 ### [AggregateCommand.toLower(value: any)](./operators/toLower) 描述: 聚合操作符。将字符串转化为小写并返回。 ### [AggregateCommand.toUpper(value: any)](./operators/toUpper) 描述: 聚合操作符。将字符串转化为大写并返回。 ### [AggregateCommand.trunc(value: Expression\)](./operators/trunc) 描述: 聚合操作符。将数字截断为整形。 ### [AggregateCommand.week(value: Expression\)](./operators/week) 描述: 聚合操作符。返回日期字段对应的周数(一年中的第几周),是一个介于 0 到 53 之间的整数。 ### [AggregateCommand.year(value: Expression\)](./operators/year) 描述: 聚合操作符。返回日期字段对应的年份。 ### [AggregateCommand.zip(value: any)](./operators/zip) 描述: 聚合操作符。把二维数组的第二维数组中的相同序号的元素分别拼装成一个新的数组进而组装成一个新的二维数组。如可将 [ [ 1, 2, 3 ], [ "a", "b", "c" ] ] 转换成 [ [ 1, "a" ], [ 2, "b" ], [ 3, "c" ] ]。 --- ## Expression # Expression 聚合表达式 ### 说明 表达式可以是字段路径、常量、或聚合操作符。表达式可以嵌套表达式。 #### 字段路径 表达式用字段路径表示法来指定记录中的字段。字段路径的表示由一个 $ 符号加上字段名或嵌套字段名。嵌套字段名用点将嵌套的各级字段连接起来。如 $profile 就表示 profile 的字段路径,\$profile.name 就表示 profile.name 的字段路径(profile 字段中嵌套的 name 字段)。 #### 常量 常量可以是任意类型。默认情况下 \$ 开头的字符串都会被当做字段路径处理,如果想要避免这种行为,使用 AggregateCommand.literal 声明为常量。 #### 聚合操作符 [AggregateCommand](./aggregateCommand) --- ## db.command.aggregate.abs # db.command.aggregate.abs ### 1. 操作符描述 功能:返回一个数字参数的绝对值。 声明:`db.command.aggregate.abs(num)` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------ | ---- | ------------------------ | | - | [Expression](../expression) | 是 | 聚合表达式(可解析为数字) | 注意事项: > 如果表达式解析为 `null` 或者指向一个不存在的字段,则 `abs` 的结果是 `null`。如果值解析为 `NaN`,则结果是 `NaN`。 ### 3. 示例代码 假设集合 `ratings` 有如下记录: ``` { _id: 1, start: 5, end: 8 } { _id: 2, start: 4, end: 4 } { _id: 3, start: 9, end: 7 } { _id: 4, start: 6, end: 7 } ``` ··· 可以用如下方式求得各个记录的 `start` 和 `end` 之间的绝对差异大小: ```js // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate exports.main = async (event, context) => { const res = await db .collection('ratings') .aggregate() .project({ delta: $.abs($.subtract(['$start', '$end'])) }) .end() console.log(res.data) } ``` 返回结果如下: ``` { "_id" : 1, "delta" : 3 } { "_id" : 2, "delta" : 0 } { "_id" : 3, "delta" : 2 } { "_id" : 4, "delta" : 1 } ``` --- ## db.command.aggregate.add # db.command.aggregate.add ### 1. 操作符描述 功能:将数字相加或将数字加在日期上。如果数组中的其中一个值是日期,那么其他值将被视为毫秒数加在该日期上。 声明:`db.command.aggregate.add([expression1, expression2, ...])` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------------------- | ---- | --------------------------------------------------------------------------------------- | | - | <Array>[Expression](../expression) | 是 | 字符串表达式可以是形如 `$ + 指定字段`,也可以是普通字符串。只要能够被解析成字符串即可。 | ### 3. 示例代码 假设集合 `staff` 有如下记录: ``` { _id: 1, department: "x", sales: 5, engineer: 10, lastUpdate: ISODate("2019-05-01T00:00:00Z") } { _id: 2, department: "y", sales: 10, engineer: 20, lastUpdate: ISODate("2019-05-01T02:00:00Z") } { _id: 3, department: "z", sales: 20, engineer: 5, lastUpdate: ISODate("2019-05-02T03:00:00Z") } ``` #### 数字求和 可以用如下方式求得各个记录人数总数: ```js // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate exports.main = async (event, context) => { const res = await db .collection('staff') .aggregate() .project({ department: 1, total: $.add(['$sales', '$engineer']) }) .end() console.log(res.data) // 打印聚合结果 } ``` 返回结果如下: ``` { _id: 1, department: "x", total: 15 } { _id: 2, department: "y", total: 30 } { _id: 3, department: "z", total: 25 } ``` #### 增加日期值 如下操作可以获取各个记录的 `lastUpdate` 加一个小时之后的值: ```js // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate exports.main = async (event, context) => { const res = await db .collection('staff') .aggregate() .project({ department: 1, lastUpdate: $.add(['$lastUpdate', 60 * 60 * 1000]) }) .end() console.log(res.data) // 打印聚合结果 } ``` 返回结果如下: ``` { _id: 1, department: "x", lastUpdate: ISODate("2019-05-01T01:00:00Z") } { _id: 2, department: "y", lastUpdate: ISODate("2019-05-01T03:00:00Z") } { _id: 3, department: "z", lastUpdate: ISODate("2019-05-02T04:00:00Z") } ``` --- ## db.command.aggregate.addToSet # db.command.aggregate.addToSet ### 1. 操作符描述 功能:向数组中添加值,如果数组中已存在该值,不执行任何操作。它只能在 `group stage` 中使用。 声明:`db.command.aggregate.addToSet(expression)` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------ | ---- | -------------------------------------------------------------------------------------------------- | | - | [Expression](../expression) | 是 | 字符串表达式是形如 `$ + 指定字段` 的字符串。如果指定字段的值是数组,那么整个数组会被当作一个元素。 | ### 3. 示例代码 假设集合 `passages` 的记录如下: ```json { "category": "web", "tags": [ "JavaScript", "CSS" ], "title": "title1" } { "category": "System", "tags": [ "C++", "C" ], "title": "title2" } ``` #### 非数组字段 每条记录的 `category` 对应值的类型是非数组,利用 `addToSet` 统计所有分类: ```javascript // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate exports.main = async (event, context) => { const res = await db .collection('passages') .aggregate() .group({ _id: null, categories: $.addToSet('$category') }) .end() console.log(res.data) } ``` 返回的结果如下: ```json { "_id": null, "categories": ["System", "web"] } ``` #### 数组字段 每条记录的 `tags` 对应值的类型是数组,数组不会被自动展开: ```javascript // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate exports.main = async (event, context) => { const res = await db .collection('passages') .aggregate() .group({ _id: null, tagsList: $.addToSet('$tags') }) .end() console.log(res.data) } ``` 返回的结果如下: ```json { "_id": null, "tagsList": [ ["C++", "C"], ["JavaScript", "CSS"] ] } ``` --- ## db.command.aggregate.allElementsTrue # db.command.aggregate.allElementsTrue ### 1. 操作符描述 功能:输入一个数组,或者数组字段的表达式。如果数组中所有元素均为真值,那么返回 `true`,否则返回 `false`。空数组永远返回 `true`。 声明:`db.command.aggregate.allElementsTrue([expression])` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------------------- | ---- | ------------------------------------------ | | - | <Array>[Expression](../expression) | 是 | 字符串表达式是形如 `$ + 指定字段` 的字符串 | ### 3. 示例代码 假设集合 `test` 有如下记录: ```json { "_id": 1, "array": [ true ] } { "_id": 2, "array": [ ] } { "_id": 3, "array": [ false ] } { "_id": 4, "array": [ true, false ] } { "_id": 5, "array": [ 0 ] } { "_id": 6, "array": [ "stark" ] } ``` 下面的代码使用 `allElementsTrue()`,判断 `array` 字段中是否均为真值: ```js // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate exports.main = async (event, context) => { const res = await db .collection('price') .aggregate() .project({ isAllTrue: $.allElementsTrue(['$array']) }) .end() console.log(res.data) } ``` 返回结果如下: ```json { "_id": 1, "isAllTrue": true } { "_id": 2, "isAllTrue": true } { "_id": 3, "isAllTrue": false } { "_id": 4, "isAllTrue": false } { "_id": 5, "isAllTrue": false } { "_id": 6, "isAllTrue": true } ``` --- ## db.command.aggregate.and # db.command.aggregate.and ### 1. 操作符描述 功能:给定多个表达式,`and` 仅在所有表达式都返回 `true` 时返回 `true`,否则返回 `false`。 声明:`db.command.aggregate.and([expression1, expression2, ...])` 注意事项: > 如果表达式返回 `false`、`null`、`0`、或 `undefined`,表达式会解析为 `false`,否则对其他返回值都认为是 `true`。 ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------------------- | ---- | ---------- | | - | <Array>[Expression](../expression) | 是 | 聚合表达式 | ### 3. 示例代码 假设集合 `price` 有如下记录: ```json { "_id": 1, "min": 10, "max": 100 } { "_id": 2, "min": 60, "max": 80 } { "_id": 3, "min": 30, "max": 50 } ``` 求 `min` 大于等于 30 且 `max` 小于等于 80 的记录。 ```js // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate exports.main = async (event, context) => { const res = await db .collection('price') .aggregate() .project({ fullfilled: $.and([$.gte(['$min', 30]), $.lte(['$max', 80])]) }) .end() console.log(res.data) } ``` 返回结果如下: ```json { "_id": 1, "fullfilled": false } { "_id": 2, "fullfilled": true } { "_id": 3, "fullfilled": true } ``` --- ## db.command.aggregate.anyElementTrue # db.command.aggregate.anyElementTrue ### 1. 操作符描述 功能:输入一个数组,或者数组字段的表达式。如果数组中任意一个元素为真值,那么返回 `true`,否则返回 `false`。空数组永远返回 `false`。 声明:`db.command.aggregate.anyElementTrue([expression])` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------------------- | ---- | ---------- | | - | <Array>[Expression](../expression) | 是 | 聚合表达式 | ### 3. 示例代码 假设集合 `test` 有如下记录: ```json { "_id": 1, "array": [ true ] } { "_id": 2, "array": [ ] } { "_id": 3, "array": [ false ] } { "_id": 4, "array": [ true, false ] } { "_id": 5, "array": [ 0 ] } { "_id": 6, "array": [ "stark" ] } ``` 下面的代码使用 `anyElementTrue()`,判断 `array` 字段中是否含有真值: ```js // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate exports.main = async (event, context) => { const res = await db .collection('price') .aggregate() .project({ isAnyTrue: $.anyElementTrue(['$array']) }) .end() console.log(res.data) } ``` 返回结果如下: ```json { "_id": 1, "isAnyTrue": true } { "_id": 2, "isAnyTrue": false } { "_id": 3, "isAnyTrue": false } { "_id": 4, "isAnyTrue": true } { "_id": 5, "isAnyTrue": false } { "_id": 6, "isAnyTrue": true } ``` --- ## db.command.aggregate.arrayElemAt # db.command.aggregate.arrayElemAt ### 1. 操作符描述 功能:返回在指定数组下标的元素。 声明:`db.command.aggregate.arrayElemAt([array, index])` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------------------- | ---- | ------------------------------------------------------------------------------------------------ | | - | <Array>[Expression](../expression) | 是 | 第一个元素`array` 可以是任意解析为数组的表达式,第二个元素`index` 可以是任意解析为整形的表达式。 | 注意事项: > 如果是正数,`arrayElemAt` 返回在 `index` 位置的元素,如果是负数,`arrayElemAt` 返回从数组尾部算起的 `index` 位置的元素。 ### 3. 示例代码 假设集合 `exams` 有如下记录: ```json { "_id": 1, "scores": [80, 60, 65, 90] } { "_id": 2, "scores": [78] } { "_id": 3, "scores": [95, 88, 92] } ``` 求各个第一次考试的分数和和最后一次的分数: ```js // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate exports.main = async (event, context) => { const res = await db .collection('exams') .aggregate() .project({ first: $.arraElemAt(['$scores', 0]), last: $.arraElemAt(['$scores', -1]) }) .end() console.log(res.data) } ``` 返回结果如下: ```json { "_id": 1, "first": 80, "last": 90 } { "_id": 2, "first": 78, "last": 78 } { "_id": 3, "first": 95, "last": 92 } ``` --- ## db.command.aggregate.arrayToObject # db.command.aggregate.arrayToObject ### 1. 操作符描述 功能:将一个数组转换为对象。 声明: 两种形式 1. 传入一个二维数组,第二维的数组长度必须为 2,其第一个值为字段名,第二个值为字段值 `db.command.aggregate.arrayToObject([ [key1, value1], [key2, value2], ... ])` 2. 传入一个对象数组,各个对象必须包含字段 `k` 和 `v`,分别指定字段名和字段值 `db.command.aggregate.arrayToObject([ { "k": key1, "v": value1 }, { "k": key2, "v": value2 }, ... ])` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ----------------------------- | ---- | ------------ | | - | <Array> Array Or Object | 是 | 如声明中所述 | ### 3. 示例代码 假设集合 `shops` 有如下记录: ```json { "_id": 1, "sales": [ ["max", 100], ["min", 50] ] } { "_id": 2, "sales": [ ["max", 70], ["min", 60] ] } { "_id": 3, "sales": [ { "k": "max", "v": 50 }, { "k": "min", "v": 30 } ] } ``` 求各个第一次考试的分数和和最后一次的分数: ```js // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate exports.main = async (event, context) => { const res = await db .collection('shops') .aggregate() .project({ sales: $.arrayToObject('$sales') }) .end() console.log(res.data) } ``` 返回结果如下: ```json { "_id": 1, "sales": { "max": 100, "min": 50 } } { "_id": 2, "sales": { "max": 70, "min": 60 } } { "_id": 3, "sales": { "max": 50, "min": 30 } } ``` --- ## db.command.aggregate.avg # db.command.aggregate.avg ### 1. 操作符描述 功能:返回一组集合中,指定字段对应数据的平均值。 声明:`db.command.aggregate.avg(expression)` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------ | ---- | ---------------------------------------------------------------------------------------- | | - | [Expression](../expression) | 是 | `avg` 传入的值除了数字常量外,也可以是任何最终解析成一个数字的表达式。它会忽略非数字值。 | ### 3. 示例代码 假设集合 `students` 的记录如下: ```json { "group": "a", "name": "stu1", "score": 84 } { "group": "a", "name": "stu2", "score": 96 } { "group": "b", "name": "stu3", "score": 80 } { "group": "b", "name": "stu4", "score": 100 } ``` 借助 `avg` 可以计算所有记录的 `score` 的平均值: ```javascript // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate exports.main = async (event, context) => { const res = await db .collection('students') .aggregate() .group({ _id: null, average: $.avg('$score') }) .end() console.log(res.data) } ``` 返回的结果如下: ```json { "_id": null, "average": 90 } ``` --- ## db.command.aggregate.ceil # db.command.aggregate.ceil ### 1. 操作符描述 功能:向上取整,返回大于或等于给定数字的最小整数。 声明:`db.command.aggregate.ceil(expression)` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------ | ---- | ----------------------------------------------------------------------------------------------------------------------------- | | - | [Expression](../expression) | 是 | 可以是任意解析为数字的表达式。如果表达式解析为 `null` 或指向一个不存在的字段,则返回 `null`,如果解析为 `NaN`,则返回 `NaN`。 | ### 3. 示例代码 假设集合 `sales` 有如下记录: ``` { _id: 1, sales: 5.2 } { _id: 2, sales: 1.32 } { _id: 3, sales: -3.2 } ``` 可以用如下方式取各个数字的向上取整值: ```js // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate exports.main = async (event, context) => { const res = await db .collection('sales') .aggregate() .project({ sales: $.ceil('$sales') }) .end() console.log(res.data) } ``` 返回结果如下: ``` { _id: 1, sales: 6 } { _id: 2, sales: 2 } { _id: 3, sales: -3 } ``` --- ## db.command.aggregate.cmp # db.command.aggregate.cmp ### 1. 操作符描述 功能:给定两个值,返回其比较值。 声明:`db.command.aggregate.cmp([expression1, expression2])` - 如果第一个值小于第二个值,返回 -1 - 如果第一个值大于第二个值,返回 1 - 如果两个值相等,返回 0 ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------------------- | ---- | ---------------------- | | - | <Array>[Expression](../expression) | 是 | 含两个聚合表达式的数组 | ### 3. 示例代码 假设集合 `price` 有如下记录: ```json { "_id": 1, "shop1": 10, "shop2": 100 } { "_id": 2, "shop1": 80, "shop2": 20 } { "_id": 3, "shop1": 50, "shop2": 50 } ``` 求 `shop1` 和 `shop2` 的各个物品的价格对比。 ```js // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk'); const app = tcb.init({ env:'xxx' }) const db = app.database(); const $ = db.command.aggregate exports.main = async (event, context) => { const res = await db.collection('price').aggregate() .project({ compare: $.cmp(['$shop1', '$shop2'])) }) .end() console.log(res.data) } ``` 返回结果如下: ```json { "_id": 1, "compare": -1 } { "_id": 2, "compare": 1 } { "_id": 3, "compare": 0 } ``` --- ## db.command.aggregate.concat # db.command.aggregate.concat ### 1. 操作符描述 功能:连接字符串,返回拼接后的字符串。 声明:`db.command.aggregate.concat([expression1, expression2, ...])` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------------------- | ---- | ----------------------------------------------------------------------------------------- | | - | <Array>[Expression](../expression) | 是 | 数组中的表达式可以是形如 `$ + 指定字段`,也可以是普通字符串。只要能够被解析成字符串即可。 | ### 3. 示例代码 假设集合 `students` 的记录如下: ```json { "firstName": "Yuanxin", "group": "a", "lastName": "Dong", "score": 84 } { "firstName": "Weijia", "group": "a", "lastName": "Wang", "score": 96 } { "firstName": "Chengxi", "group": "b", "lastName": "Li", "score": 80 } ``` 借助 `concat` 可以拼接 `lastName` 和 `firstName` 字段,得到每位学生的名字全称: ```javascript // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate exports.main = async (event, context) => { const res = await db .collection('students') .aggregate() .project({ _id: 0, fullName: $.concat(['$firstName', ' ', '$lastName']) }) .end() console.log(res.data) } ``` 返回的结果如下: ```json { "fullName": "Yuanxin Dong" } { "fullName": "Weijia Wang" } { "fullName": "Chengxi Li" } ``` --- ## db.command.aggregate.concatArrays # db.command.aggregate.concatArrays ### 1. 操作符描述 功能:将多个数组拼接成一个数组。 声明:`db.command.aggregate.arrayToObject([ array1, array2, ... ])` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------------------- | ---- | ------------------------------------ | | - | <Array>[Expression](../expression) | 是 | 表达式可以是任意解析为数组的表达式。 | ### 3. 示例代码 假设集合 `items` 有如下记录: ```json { "_id": 1, "fruits": [ "apple" ], "vegetables": [ "carrot" ] } { "_id": 2, "fruits": [ "orange", "lemon" ], "vegetables": [ "cabbage" ] } { "_id": 3, "fruits": [ "strawberry" ], "vegetables": [ "spinach" ] } ``` ```js // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate exports.main = async (event, context) => { const res = await db .collection('items') .aggregate() .project({ sales: $.concatArrays(['$fruits', '$vegetables']) }) .end() console.log(res.data) } ``` 返回结果如下: ```json { "_id": 1, "first": 80, "last": 90 } { "_id": 2, "first": 78, "last": 78 } { "_id": 3, "first": 95, "last": 92 } ``` --- ## db.command.aggregate.cond # db.command.aggregate.cond ### 1. 操作符描述 功能:计算布尔表达式,返回指定的两个值其中之一。 声明: 两种形式 1. `cond({ if: , then: , else: })` 2. `cond([ , , ])` 注意事项: > 两种形式中,三个参数(`if`、`then`、`else`)都是必须的。 > 如果布尔表达式为真,那么 `$cond` 将会返回 ``,否则会返回 `` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ---------------------------- | ---- | -------------------- | | - | Object or <Array>[any] | 是 | 两种形式(如声明说示) | ### 3. 示例代码 假设集合 `items` 的记录如下: ```json { "_id": "0", "name": "item-a", "amount": 100 } { "_id": "1", "name": "item-b", "amount": 200 } { "_id": "2", "name": "item-c", "amount": 300 } ``` 我们可以使用 `cond`,根据 `amount` 字段,来生成新的字段 `discount`: ```javascript // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate exports.main = async (event, context) => { const res = await db .collection('items') .aggregate() .project({ name: 1, discount: $.cond({ if: $.gte(['$amount', 200]), then: 0.7, else: 0.9 }) }) .end() console.log(res.data) } ``` 输出如下: ```json { "_id": "0", "name": "item-a", "discount": 0.9 } { "_id": "1", "name": "item-b", "discount": 0.7 } { "_id": "2", "name": "item-c", "discount": 0.7 } ``` --- ## db.command.aggregate.dateFromParts # db.command.aggregate.dateFromParts ### 1. 操作符描述 功能:给定日期的相关信息,构建并返回一个日期对象。 声明:`db.command.aggregate.dateFromParts(object)` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ------------ | ------ | ---- | ------------ | | year | number | 否 | 年 | | month | number | 否 | 月 | | day | number | 否 | 日 | | hour | number | 否 | 小时 | | minute | number | 否 | 分钟 | | second | number | 否 | 秒 | | millisecond | number | 否 | 毫秒 | | timezone | string | 否 | 时区 | | isoWeekYear | number | 否 | isoWeekYear | | isoWeek | number | 否 | isoWeek | | isoDayOfWeek | number | 否 | isoDayOfWeek | 语法如下: ``` db.command.aggregate.dateFromParts({ year: , month: , day: , hour: , minute: , second: , millisecond: , timezone: }) ``` 您也可以使用 ISO 8601 的标准: ``` db.command.aggregate.dateFromParts({ isoWeekYear: , isoWeek: , isoDayOfWeek: , hour: , minute: , second: , millisecond: , timezone: }) ``` ### 3. 示例代码 ```javascript // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate exports.main = async (event, context) => { const res = await db .collection('dates') .aggregate() .project({ _id: 0, date: $.dateFromParts({ year: 2017, month: 2, day: 8, hour: 12, timezone: 'America/New_York' }) }) .end() console.log(res.data) } ``` 输出如下: ```json { "date": ISODate("2017-02-08T17:00:00.000Z") } ``` --- ## db.command.aggregate.dateFromString # db.command.aggregate.dateFromString ### 1. 操作符描述 功能:将一个日期/时间字符串转换为日期对象 声明:`db.command.aggregate.dateFromString({dateString,timezone})` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---------- | ------ | ---- | ---------- | | dateString | string | 是 | 日期字符串 | | timezone | string | 否 | 时区 | ### 3. 示例代码 ```javascript // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate exports.main = async (event, context) => { const res = await db .collection('dates') .aggregate() .project({ _id: 0, date: $.dateFromString({ dateString: '2019-05-14T09:38:51.686Z' }) }) .end() console.log(res.data) } ``` 输出如下: ```json { "date": ISODate("2019-05-14T09:38:51.686Z") } ``` --- ## Aggregate.dateToString # Aggregate.dateToString ### 1. 操作符描述 功能:将一个日期/时间字符串转换为日期对象 声明:`db.command.aggregate.dateToString({date: ,format: ,timezone: ,onNull: })` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | -------- | ------ | ---- | ------------ | | date | string | 是 | 日期表达式 | | format | string | 否 | 格式化表达式 | | timezone | string | 否 | 时区表达式 | | onNull | string | 否 | 空值表达式 | 下面是四种表达式的详细说明: | 名称 | 描述 | | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | 日期表达式 | 必选。指定字段值应该是能转化为字符串的日期。 | | 格式化表达式 | 可选。它可以是任何包含“格式说明符”的有效字符串。 | | 时区表达式 | 可选。指明运算结果的时区。它可以解析格式为 [UTC Offset](https://en.wikipedia.org/wiki/List_of_UTC_time_offsets) 或者 [Olson Timezone Identifier](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) 的字符串。 | | 空值表达式 | 可选。当 `` 返回空或者不存在的时候,会返回此表达式指明的值。 | 下面是格式说明符的详细说明: | 说明符 | 描述 | 合法值 | | ------ | --------------------------------- | ------------- | | %d | 月份的日期(2 位数,0 填充) | 01 - 31 | | %G | ISO 8601 格式的年份 | 0000 - 9999 | | %H | 小时(2 位数,0 填充,24 小时制) | 00 - 23 | | %j | 一年中的一天(3 位数,0 填充) | 001 - 366 | | %L | 毫秒(3 位数,0 填充) | 000 - 999 | | %m | 月份(2 位数,0 填充) | 01 - 12 | | %M | 分钟(2 位数,0 填充) | 00 - 59 | | %S | 秒(2 位数,0 填充) | 00 - 60 | | %w | 星期几 | 1 - 7 | | %u | ISO 8601 格式的星期几 | 1 - 7 | | %U | 一年中的一周(2 位数,0 填充) | 00 - 53 | | %V | ISO 8601 格式的一年中的一周 | 1 - 53 | | %Y | 年份(4 位数,0 填充) | 0000 - 9999 | | %z | 与 UTC 的时区偏移量 | `+/-[hh][mm]` | | %Z | 以分钟为单位,与 UTC 的时区偏移量 | `+/-mmm` | | %% | 百分号作为字符 | `%` | ### 3. 示例代码 假设集合 `students` 有如下记录: ```json { "date": "1999-12-11T16:00:00.000Z", "firstName": "Yuanxin", "lastName": "Dong" } { "date": "1998-11-10T16:00:00.000Z", "firstName": "Weijia", "lastName": "Wang" } { "date": "1997-10-09T16:00:00.000Z", "firstName": "Chengxi", "lastName": "Li" } ``` #### 格式化日期 下面是将 `date` 字段的值,格式化成形如 `年份-月份-日期` 的字符串: ```javascript // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate exports.main = async (event, context) => { const res = await db .collection('students') .aggregate() .project({ _id: 0, formatDate: $.dateToString({ date: '$date', format: '%Y-%m-%d' }) }) .end() console.log(res.data) } ``` 返回的结果如下: ```json { "formatDate": "1999-12-11" } { "formatDate": "1998-11-10" } { "formatDate": "1997-10-09" } ``` #### 时区时间 下面是将 `date` 字段值格式化为上海时区时间的例子: ```javascript // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate exports.main = async (event, context) => { const res = await db .collection('students') .aggregate() .project({ _id: 0, formatDate: $.dateToString({ date: '$date', format: '%H:%M:%S', timezone: 'Asia/Shanghai' }) }) .end() console.log(res.data) } ``` 返回的结果如下: ```json { "formatDate": "00:00:00" } { "formatDate": "00:00:00" } { "formatDate": "00:00:00" } ``` #### 缺失情况的默认值 当指定的 `` 返回空或者不存在的时候,可以设置缺失情况下的默认值: ```javascript // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate exports.main = async (event, context) => { const res = await db .collection('students') .aggregate() .project({ _id: 0, formatDate: $.dateToString({ date: '$empty', onNull: 'null' }) }) .end() console.log(res.data) } ``` 返回的结果如下: ```json { "formatDate": "null" } { "formatDate": "null" } { "formatDate": "null" } ``` --- ## db.command.aggregate.dayOfMonth # db.command.aggregate.dayOfMonth ### 1. 操作符描述 功能:返回日期字段对应的  天数(一个月中的哪一天),是一个介于 1 至 31 之间的数字。 声明:`db.command.aggregate.dayOfMonth()` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------ | ---- | -------- | | - | [Expression](../expression) | 是 | 日期字段 | ### 3. 示例代码 假设集合 `dates` 有以下文档: ```json { "_id": 1, "date": ISODate("2019-05-14T09:38:51.686Z") } ``` 我们使用 `dayOfMonth()` 对 `date` 字段进行投影,获取对应的日期: ```javascript // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate exports.main = async (event, context) => { const res = await db .collection('dates') .aggregate() .project({ _id: 0, dayOfMonth: $.dayOfMonth('$date') }) .end() console.log(res.data) } ``` 输出如下: ```json { "dayOfMonth": 14 } ``` --- ## db.command.aggregate.dayOfWeek # db.command.aggregate.dayOfWeek ### 1. 操作符描述 功能:返回日期字段对应的天数(一周中的第几天),是一个介于 1(周日)到 7(周六)之间的整数。 声明:`db.command.aggregate.dayOfWeek()` 注意事项:周日是每周的第 1 天 ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------ | ---- | -------- | | - | [Expression](../expression) | 是 | 日期字段 | ### 3. 示例代码 假设集合 `dates` 有以下文档: ```json { "_id": 1, "date": ISODate("2019-05-14T09:38:51.686Z") } ``` 我们使用 `dayOfWeek()` 对 `date` 字段进行投影,获取对应的天数(一周中的第几天): ```javascript // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate exports.main = async (event, context) => { const res = await db .collection('dates') .aggregate() .project({ _id: 0, dayOfWeek: $.dayOfWeek('$date') }) .end() console.log(res.data) } ``` 输出如下: ```json { "dayOfWeek": 3 } ``` --- ## db.command.aggregate.dayOfYear # db.command.aggregate.dayOfYear ### 1. 操作符描述 功能:返回日期字段对应的天数(一年中的第几天),是一个介于 1 到 366 之间的整数。 声明:`db.command.aggregate.dayOfYear()` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------ | ---- | -------- | | - | [Expression](../expression) | 是 | 日期字段 | ### 3. 示例代码 假设集合 `dates` 有以下文档: ```json { "_id": 1, "date": ISODate("2019-05-14T09:38:51.686Z") } ``` 我们使用 `dayOfYear()` 对 `date` 字段进行投影,获取对应的天数(一年中的第几天): ```javascript // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate exports.main = async (event, context) => { const res = await db .collection('dates') .aggregate() .project({ _id: 0, dayOfYear: $.dayOfYear('$date') }) .end() console.log(res.data) } ``` 输出如下: ```json { "dayOfYear": 134 } ``` --- ## db.command.aggregate.divide # db.command.aggregate.divide ### 1. 操作符描述 功能:传入被除数和除数,求商。 声明:`db.command.aggregate.divide([, ])` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------------------- | ---- | ------------------------------------ | | - | <Array>[Expression](../expression) | 是 | 表达式可以是任意解析为数字的表达式。 | ### 3. 示例代码 假设集合 `railroads` 有如下记录: ``` { _id: 1, meters: 5300 } { _id: 2, meters: 64000 } { _id: 3, meters: 130 } ``` 可以用如下方式取各个数字转换为千米之后的值: ```js // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate exports.main = async (event, context) => { const res = await db .collection('railroads') .aggregate() .project({ km: $.divide(['$meters', 1000]) }) .end() console.log(res.data) } ``` 返回结果如下: ``` { _id: 1, km: 5.3 } { _id: 2, km: 64 } { _id: 3, km: 0.13 } ``` --- ## db.command.aggregate.eq # db.command.aggregate.eq ### 1. 操作符描述 功能:匹配两个值,如果相等则返回 `true`,否则返回 `false`。 声明:`db.command.aggregate.eq([value1, value2])` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------------------- | ---- | -------------- | | - | <Array>[Expression](../expression) | 是 | 聚合表达式数组 | ### 3. 示例代码 假设集合 `price` 有如下记录: ```json { "_id": 1, "value": 10 } { "_id": 2, "value": 80 } { "_id": 3, "value": 50 } ``` 求 `value` 等于 50 的记录。 ```js // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate exports.main = async (event, context) => { const res = await db .collection('price') .aggregate() .project({ matched: $.eq(['$value', 50]) }) .end() console.log(res.data) } ``` 返回结果如下: ```json { "_id": 1, "matched": false } { "_id": 2, "matched": false } { "_id": 3, "matched": true } ``` --- ## db.command.aggregate.exp # db.command.aggregate.exp ### 1. 操作符描述 功能:取 e(自然对数的底数,欧拉数) 的 n 次方。 声明:`db.command.aggregate.exp(exponent)` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------ | ---- | ---------------------------------------------------------------------------------------------------------------------------------------- | | - | [Expression](../expression) | 是 | `exponent` 可以是任意解析为数字的表达式。如果表达式解析为 `null` 或指向一个不存在的字段,则返回 `null`,如果解析为 `NaN`,则返回 `NaN`。 | ### 3. 示例代码 假设集合 `math` 有如下记录: ``` { _id: 1, exp: 0 } { _id: 2, exp: 1 } { _id: 3, exp: 2 } ``` ```js // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate exports.main = async (event, context) => { const res = await db .collection('math') .aggregate() .project({ result: $.exp('$exp') }) .end() console.log(res.data) } ``` 返回结果如下: ``` { _id: 1, result: 1 } { _id: 2, result: 2.71828182845905 } { _id: 3, result: 7.38905609893065 } ``` --- ## db.command.aggregate.filter # db.command.aggregate.filter ### 1. 操作符描述 功能:根据给定条件返回满足条件的数组的子集。 声明:`db.command.aggregate.filter({ input: array, as: string, cond: expression })` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ----- | ------------------------------ | ---- | ------------------------------------------------------------------------------------------------------------------------------- | | input | [Expression](../expression) | 是 | 一个可以解析为数组的表达式 | | as | string | 否 | 可选,用于表示数组各个元素的变量,默认为 this | | cond | [Expression](../expression) | 是 | 一个可以解析为布尔值的表达式,用于判断各个元素是否满足条件,各个元素的名字由 `as` 参数决定(参数名需加 `$$` 前缀,如 `$$this`) | ### 3. 示例代码 假设集合 `fruits` 有如下记录: ```json { "_id": 1, "stock": [ { "name": "apple", "price": 10 }, { "name": "orange", "price": 20 } ], } { "_id": 2, "stock": [ { "name": "lemon", "price": 15 }, ], } ``` ```js // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('fruits') .aggregate() .project({ stock: $.filter({ input: '$stock', as: 'item', cond: $.gte(['$$item.price', 15]) }) }) .end() console.log(res.data) } ``` 返回结果如下: ```json { "_id": 1, "stock": [ { "name": "orange", "price": 20} ] } { "_id": 2, "stock": [ { "name": "lemon", "price": 15 } ] } ``` --- ## db.command.aggregate.first # db.command.aggregate.first ### 1. 操作符描述 功能:返回指定字段在一组集合的第一条记录对应的值。仅当这组集合是按照某种定义排序( `sort` )后,此操作才有意义。 声明:`db.command.aggregate.first(expression)` 注意事项: > `first` 只能在 `group` 阶段被使用,并且需要配合 `sort` 才有意义。 ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------ | ---- | -------------------------------------- | | - | [Expression](../expression) | 是 | 表达式是形如 `$ + 指定字段` 的字符串。 | ### 3. 示例代码 假设集合 `students` 的记录如下: ```json { "group": "a", "name": "stu1", "score": 84 } { "group": "a", "name": "stu2", "score": 96 } { "group": "b", "name": "stu3", "score": 80 } { "group": "b", "name": "stu4", "score": 100 } ``` 如果需要得到所有记录中 `score` 的最小值,可以先将所有记录按照 `score` 排序,然后取出第一条记录的 `first`。 ```javascript // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('students') .aggregate() .sort({ score: 1 }) .group({ _id: null, min: $.first('$score') }) .end() console.log(res.data) } ``` 返回的数据结果如下: ```json { "_id": null, "min": 80 } ``` --- ## db.command.aggregate.ceil # db.command.aggregate.ceil ### 1. 操作符描述 功能:向下取整,返回大于或等于给定数字的最小整数。 声明:`db.command.aggregate.floor(number)` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------ | ---- | -------------------------------------------------------------------------------------------------------------------------------------- | | - | [Expression](../expression) | 是 | `number` 可以是任意解析为数字的表达式。如果表达式解析为 `null` 或指向一个不存在的字段,则返回 `null`,如果解析为 `NaN`,则返回 `NaN`。 | ### 3. 示例代码 假设集合 `sales` 有如下记录: ``` { _id: 1, sales: 5.2 } { _id: 2, sales: 1.32 } { _id: 3, sales: -3.2 } ``` 可以用如下方式取各个数字的向下取整值: ```js // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('sales') .aggregate() .project({ sales: $.floor('$sales') }) .end() console.log(res.data) } ``` 返回结果如下: ``` { _id: 1, sales: 5 } { _id: 2, sales: 1 } { _id: 3, sales: -6 } ``` --- ## db.command.aggregate.gt # db.command.aggregate.gt ### 1. 操作符描述 功能:匹配两个值,如果前者大于后者则返回 `true`,否则返回 `false`。 声明:`db.command.aggregate.gt([value1, value2])` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------------------- | ---- | -------------- | | - | <Array>[Expression](../expression) | 是 | 聚合表达式数组 | ### 3. 示例代码 假设集合 `price` 有如下记录: ```json { "_id": 1, "value": 10 } { "_id": 2, "value": 80 } { "_id": 3, "value": 50 } ``` 判断 `value` 是否大于 50。 ```js // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('price') .aggregate() .project({ matched: $.gt(['$value', 50]) }) .end() console.log(res.data) } ``` 返回结果如下: ```json { "_id": 1, "matched": false } { "_id": 2, "matched": true } { "_id": 3, "matched": false } ``` --- ## db.command.aggregate.gte # db.command.aggregate.gte ### 1. 操作符描述 功能:匹配两个值,如果前者大于或等于后者则返回 `true`,否则返回 `false`。 声明:`db.command.aggregate.gte([value1, value2])` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------------------- | ---- | -------------- | | - | <Array>[Expression](../expression) | 是 | 聚合表达式数组 | ### 3. 示例代码 假设集合 `price` 有如下记录: ```json { "_id": 1, "value": 10 } { "_id": 2, "value": 80 } { "_id": 3, "value": 50 } ``` 判断 `value` 是否大于或等于 50。 ```js // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('price') .aggregate() .project({ matched: $.gte(['$value', 50]) }) .end() console.log(res.data) } ``` 返回结果如下: ```json { "_id": 1, "matched": false } { "_id": 2, "matched": true } { "_id": 3, "matched": true } ``` --- ## db.command.aggregate.hour # db.command.aggregate.hour ### 1. 操作符描述 功能:返回日期字段对应的小时数,是一个介于 0 到 23 之间的整数。 声明:`db.command.aggregate.hour(日期字段)` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------ | ---- | ---------- | | - | [Expression](../expression) | 是 | 聚合表达式 | ### 3. 示例代码 假设集合 `dates` 有以下文档: ```json { "_id": 1, "date": ISODate("2019-05-14T09:38:51.686Z") } ``` 我们使用 `hour()` 对 `date` 字段进行投影,获取对应的小时数: ```javascript // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('dates') .aggregate() .project({ _id: 0, hour: $.hour('$date') }) .end() console.log(res.data) } ``` 输出如下: ```json { "hour": 9 } ``` --- ## db.command.aggregate.ifNull # db.command.aggregate.ifNull ### 1. 操作符描述 功能:计算给定的表达式,如果表达式结果为 null、undefined 或者不存在,那么返回一个替代值;否则返回原值。 声明:`ifNull([ , ])` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------------------- | ---- | -------------- | | - | <Array>[Expression](../expression) | 是 | 聚合表达式数组 | ### 3. 示例代码 假设集合 `items` 的记录如下: ```json { "_id": "0", "name": "A", "description": "这是商品A" } { "_id": "1", "name": "B", "description": null } { "_id": "2", "name": "C" } ``` 我们可以使用 `ifNull`,对不存在 `desc` 字段的文档,或者 `desc` 字段为 `null` 的文档,补充一个替代值。 ```javascript // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('items') .aggregate() .project({ _id: 0, name: 1, description: $.ifNull(['$description', '商品描述空缺']) }) .end() console.log(res.data) } ``` 输出如下: ```json { "name": "A", "description": "这是商品A" } { "name": "B", "description": "商品描述空缺" } { "name": "C", "description": "商品描述空缺" } ``` --- ## db.command.aggregate.in # db.command.aggregate.in ### 1. 操作符描述 功能:给定一个值和一个数组,如果值在数组中则返回 `true`,否则返回 `false`。 声明:`db.command.aggregate.in([value, array])` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------------------- | ---- | ------------------------------------------ | | - | <Array>[Expression](../expression) | 是 | 聚合表达式数组,`value` 可以是任意表达式, | `array` 可以是任意解析为数组的表达式。 | ### 3. 示例代码 假设集合 `shops` 有如下记录: ```json { "_id": 1, "topsellers": ["bread", "ice cream", "butter"] } { "_id": 2, "topsellers": ["ice cream", "cheese", "yagurt"] } { "_id": 3, "topsellers": ["croissant", "cucumber", "coconut"] } ``` 标记销量最高的商品包含 `ice cream` 的记录。 ```js // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('price') .aggregate() .project({ included: $.in('ice cream', '$topsellers') }) .end() console.log(res.data) } ``` 返回结果如下: ```json { "_id": 1, "included": true } { "_id": 2, "included": true } { "_id": 3, "included": false } ``` --- ## db.command.aggregate.indexOfArray # db.command.aggregate.indexOfArray ### 1. 操作符描述 功能:在数组中找出等于给定值的第一个元素的下标,如果找不到则返回 -1。 声明:`db.command.aggregate.indexOfArray([ , , , ])` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ---------------- | ---- | ------------------ | | - | <Array>any | 是 | 各位置元素详述如下 | | 字段 | 类型 | 必填 | 说明 | | ---------- | ------- | ---- | ------------------------------------------------------------------------------------------------------------ | | `` | string | 是 | 一个可以解析为数组的表达式,如果解析为 null,则 `indexOfArray` 返回 null | | `` | string | 是 | 对数据各个元素应用的条件匹配表达式 | | `` | integer | 否 | 用于指定搜索的开始下标,必须是非负整数 | | `` | integer | 否 | 用于指定搜索的结束下标,必须是非负整数,指定了 `` 时也应指定 ``,否则 `` 默认当做 `` | ### 3. 示例代码 假设集合 `stats` 有如下记录: ```json { "_id": 1, "sales": [ 1, 6, 2, 2, 5 ] } { "_id": 2, "sales": [ 4, 2, 1, 5, 2 ] } { "_id": 3, "sales": [ 2, 5, 3, 3, 1 ] } ``` ```js // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('stats') .aggregate() .project({ index: $.indexOfArray(['$sales', 2, 2]) }) .end() console.log(res.data) } ``` 返回结果如下: ```json { "_id": 1, "index": 2 } { "_id": 2, "index": 4 } { "_id": 3, "index": -1 } ``` --- ## db.command.aggregate.indexOfBytes # db.command.aggregate.indexOfBytes ### 1. 操作符描述 功能:在目标字符串中查找子字符串,并返回第一次出现的 `UTF-8` 的字节索引(从 0 开始)。如果不存在子字符串,返回 -1。 声明:`db.command.aggregate.indexOfBytes([, , , ])` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------------------- | ---- | ---------------------------------- | | - | <Array>[Expression](../expression) | 是 | 聚合表达式数组,各位置元素含义如下 | 下面是 4 种表达式的详细描述: | 表达式 | 描述 | | ---------------- | -------------------------------- | | 目标字符串表达式 | 任何可以被解析为字符串的表达式 | | 子字符串表达式 | 任何可以被解析为字符串的表达式 | | 开始位置表达式 | 任何可以被解析为非负整数的表达式 | | 结束位置表达式 | 任何可以被解析为非负整数的表达式 | ### 3. 示例代码 假设集合 `students` 的记录如下: ```json { "firstName": "Yuanxin", "group": "a", "lastName": "Dong", "score": 84 } { "firstName": "Weijia", "group": "a", "lastName": "Wang", "score": 96 } { "firstName": "Chengxi", "group": "b", "lastName": "Li", "score": 80 } ``` 借助 `indexOfBytes` 查找字符 `"a"` 在字段 `firstName` 中的位置: ```javascript // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('students') .aggregate() .project({ _id: 0, aStrIndex: $.indexOfBytes(['$firstName', 'a']) }) .end() console.log(res.data) } ``` 返回的结果如下: ```json { "aStrIndex": 2 } { "aStrIndex": 5 } { "aStrIndex": -1 } ``` --- ## db.command.aggregate.indexOfCP # db.command.aggregate.indexOfCP ### 1. 操作符描述 功能:在目标字符串中查找子字符串,并返回第一次出现的 `UTF-8` 的 `code point` 索引(从 0 开始)。如果不存在子字符串,返回 -1。 声明:`db.command.aggregate.indexOfCP([, , , ])` 注意事项: > `code point` 是“码位”,又名“编码位置”。这里特指 `Unicode` 包中的码位,范围是从 0(16 进制)到 10FFFF(16 进制)。 ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------------------- | ---- | ---------------------------------- | | - | <Array>[Expression](../expression) | 是 | 聚合表达式数组,各位置元素含义如下 | 下面是 4 种表达式的详细描述: | 表达式 | 描述 | | ---------------- | -------------------------------- | | 目标字符串表达式 | 任何可以被解析为字符串的表达式 | | 子字符串表达式 | 任何可以被解析为字符串的表达式 | | 开始位置表达式 | 任何可以被解析为非负整数的表达式 | | 结束位置表达式 | 任何可以被解析为非负整数的表达式 | ### 3. 示例代码 假设集合 `students` 的记录如下: ```json { "firstName": "Yuanxin", "group": "a", "lastName": "Dong", "score": 84 } { "firstName": "Weijia", "group": "a", "lastName": "Wang", "score": 96 } { "firstName": "Chengxi", "group": "b", "lastName": "Li", "score": 80 } ``` 借助 `indexOfCP` 查找字符 `"a"` 在字段 `firstName` 中的位置: ```javascript // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('students') .aggregate() .project({ _id: 0, aStrIndex: $.indexOfCP(['$firstName', 'a']) }) .end() console.log(res.data) } ``` 返回的结果如下: ```json { "aStrIndex": 2 } { "aStrIndex": 5 } { "aStrIndex": -1 } ``` --- ## db.command.aggregate.isArray # db.command.aggregate.isArray ### 1. 操作符描述 功能:判断给定表达式是否是数组,返回布尔值。 声明:`db.command.aggregate.isArray(expression)` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------ | ---- | -------------------------- | | - | [Expression](../expression) | 是 | 参数可以是任意聚合表达式。 | ### 3. 示例代码 假设集合 `stats` 有如下记录: ```json { "_id": 1, "base": 10, "sales": [ 1, 6, 2, 2, 5 ] } { "_id": 2, "base": 1, "sales": 100 } ``` 计算总销量,如果 `sales` 是数字,则求 `sales * base`,如果 `sales` 是数组,则求数组元素之和与 `base` 的乘积。 ```js // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('stats') .aggregate() .project({ sum: $.cond({ if: $.isArray('$sales'), then: $.multiply([$.sum(['$sales']), '$base']), else: $.multiply(['$sales', '$base']) }) }) .end() console.log(res.data) } ``` 返回结果如下: ```json { "_id": 1, "index": 160 } { "_id": 2, "index": 100 } ``` --- ## db.command.aggregate.isoDayOfWeek # db.command.aggregate.isoDayOfWeek ### 1. 操作符描述 功能:返回日期字段对应的 ISO 8601 标准的天数(一周中的第几天),是一个介于 1(周一)到 7(周日)之间的整数。 声明:`db.command.aggregate.isoDayOfWeek()` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------ | ---- | ------------ | | - | [Expression](../expression) | 是 | 聚合表达式。 | ### 3. 示例代码 假设集合 `dates` 有以下文档: ```json { "_id": 1, "date": ISODate("2019-05-14T09:38:51.686Z") } ``` 我们使用 `isoDayOfWeek()` 对 `date` 字段进行投影,获取对应的 ISO 8601 标准的天数(一周中的第几天): ```javascript // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('dates') .aggregate() .project({ _id: 0, isoDayOfWeek: $.isoDayOfWeek('$date') }) .end() console.log(res.data) } ``` 输出如下: ```json { "isoDayOfWeek": 2 } ``` --- ## db.command.aggregate.isoWeek # db.command.aggregate.isoWeek ### 1. 操作符描述 功能:返回日期字段对应的 ISO 8601 标准的周数(一年中的第几周),是一个介于 1 到 53 之间的整数。 声明:`db.command.aggregate.isoWeek()` 例如:2016 年 1 月 7 日是那年的第一个周四,那么 2016.01.04(周一)到 2016.01.10(周日) 即为第 1 周。同理,2016 年 1 月 1 日的周数为 53。 ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------ | ---- | ------------ | | - | [Expression](../expression) | 是 | 聚合表达式。 | ### 3. 示例代码 假设集合 `dates` 有以下文档: ```json { "_id": 1, "date": ISODate("2019-05-14T09:38:51.686Z") } ``` 我们使用 `isoWeek()` 对 `date` 字段进行投影,获取对应的 ISO 8601 标准的周数(一年中的第几周): ```javascript // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('dates') .aggregate() .project({ _id: 0, isoWeek: $.isoWeek('$date') }) .end() console.log(res.data) } ``` 输出如下: ```json { "isoWeek": 20 } ``` --- ## db.command.aggregate.isoWeekYear # db.command.aggregate.isoWeekYear ### 1. 操作符描述 功能:返回日期字段对应的 ISO 8601 标准的天数(一年中的第几天)。 声明:`db.command.aggregate.isoWeekYear()` 注意事项: > 此处的“年”以第一周的周一为开始,以最后一周的周日为结束。 ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------ | ---- | ------------ | | - | [Expression](../expression) | 是 | 聚合表达式。 | ### 3. 示例代码 假设集合 `dates` 有以下文档: ```json { "_id": 1, "date": ISODate("2019-05-14T09:38:51.686Z") } ``` 我们使用 `isoWeekYear()` 对 `date` 字段进行投影,获取对应的 ISO 8601 标准的天数(一年中的第几天): ```javascript // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('dates') .aggregate() .project({ _id: 0, isoWeekYear: $.isoWeekYear('$date') }) .end() console.log(res.data) } ``` 输出如下: ```json { "isoWeekYear": 2019 } ``` --- ## db.command.aggregate.last # db.command.aggregate.last ### 1. 操作符描述 功能:返回指定字段在一组集合的最后一条记录对应的值。仅当这组集合是按照某种定义排序( `sort` )后,此操作才有意义。 声明:`db.command.aggregate.last()` 注意事项: > `last` 只能在 `group` 阶段被使用,并且需要配合 `sort` 才有意义。 ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------ | ---- | -------------------------------------- | | - | [Expression](../expression) | 是 | 表达式是形如 `$ + 指定字段` 的字符串。 | ### 3. 示例代码 假设集合 `students` 的记录如下: ```json { "group": "a", "name": "stu1", "score": 84 } { "group": "a", "name": "stu2", "score": 96 } { "group": "b", "name": "stu3", "score": 80 } { "group": "b", "name": "stu4", "score": 100 } ``` 如果需要得到所有记录中 `score` 的最大值,可以先将所有记录按照 `score` 排序,然后取出最后一条记录的 `last`。 ```javascript // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('students') .aggregate() .sort({ score: 1 }) .group({ _id: null, max: $.last('$score') }) .end() console.log(res.data) } ``` 返回的数据结果如下: ```json { "_id": null, "max": 100 } ``` --- ## db.command.aggregate.let # db.command.aggregate.let ### 1. 操作符描述 功能:自定义变量,并且在指定表达式中使用,返回的结果是表达式的结果。 声明:`db.command.aggregate.let({ vars: { : , : , ... }, in: })` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------ | ---- | -------------------------------------------------- | | - | Object | 是 | 形如{ vars: {xxx:xxx, ...}, in: xxx}, 参数详述如下 | 参数说明: `vars` 中可以定义多个变量,变量的值由 `变量表达式` 计算而来,并且被定义的变量只有在 `in` 中的 `结果表达式` 才可以访问。 在 `in` 的结果表达式中访问自定义变量时候,请在变量名前加上双美元符号( `$$` )并用引号括起来。 ### 3. 示例代码 假设代表商品的集合 `goods` 的记录如下:`price` 代表商品价格,`discount` 代表商品折扣率,`cost` 代表商品成本 ``` { "cost": -10, "discount": 0.95, "price": 100 } { "cost": -15, "discount": 0.98, "price": 1 } { "cost": -10, "discount": 1, "price": 10 } ``` 借助 `let` 可以定义并计算每件商品实际的销售价格,并将其赋值给自定义变量 `priceTotal`。最后再将 `priceTotal` 与 `cost` 进行取和( `sum` )运算,得到每件商品的利润。 代码如下: ```javascript // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('goods') .aggregate() .project({ profit: $.let({ vars: { priceTotal: $.multiply(['$price', '$discount']) }, in: $.sum(['$$priceTotal', '$cost']) }) }) .end() console.log(res.data) } ``` 返回的数据结果如下: ``` { "profit": 85 } { "profit": -14.02 } { "profit": 0 } ``` --- ## db.command.aggregate.literal # db.command.aggregate.literal ### 1. 操作符描述 功能:直接返回一个值的字面量,不经过任何解析和处理。 声明:`literal()` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ---- | ---- | ------------------------------------------------------------------------------------------------- | | - | any | 是 | 如果 `` 是一个表达式,那么 `literal` **不会**解析或者计算这个表达式,而是直接返回这个表达式。 | ### 3. 示例代码 比如我们有一个 `items` 集合,其中数据如下: ```json { "_id": "0", "price": "$1" } { "_id": "1", "price": "$5.60" } { "_id": "2", "price": "$8.90" } ``` #### 以字面量的形式使用 \$ 下面的代码使用 `literal`,生成了一个新的字段 `isOneDollar`,表示 `price` 字段是否严格等于 `"$1"`。 注意:我们这里无法使用 `eq(['$price', '$1'])`,因为 `"$1"` 是一个表达式,代表 `"1"` 字段对应的值,而不是字符串字面量 `"$1"`。 ```js // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('items') .aggregate() .project({ isOneDollar: $.eq(['$price', $.literal('$1')]) }) .end() console.log(res.data) } ``` 输出如下: ```json { "_id": "0", "isOneDollar": true } { "_id": "1", "isOneDollar": false } { "_id": "2", "isOneDollar": false } ``` #### 投影一个字段,对应的值为 1 下面的代码使用 `literal`,投影了一个新的字段 `amount`,其值为 `1`。 ```js // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('items') .aggregate() .project({ price: 1, amount: $.literal(1) }) .end() console.log(res.data) } ``` 输出如下: ```json { "_id": "0", "price": "$1", "amount": 1 } { "_id": "1", "price": "$5.60", "amount": 1 } { "_id": "2", "price": "$8.90", "amount": 1 } ``` --- ## db.command.aggregate.ln # db.command.aggregate.ln ### 1. 操作符描述 功能:计算给定数字在自然对数值。 声明:`db.command.aggregate.ln(number)` 注意事项: > `ln` 等价于 `log([, Math.E])`,其中 `Math.E` 是 `JavaScript` 获取 `e` 的值的方法。 ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------ | ---- | --------------------------------------------- | | - | [Expression](../expression) | 是 | `` 可以是任意解析为非负数字的表达式。 | ### 3. 示例代码 假设集合 `staff` 有如下记录: ``` { _id: 1, x: 1 } { _id: 2, x: 2 } { _id: 3, x: 3 } ``` 计算 `ln(x)` 的值: ```js // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate exports.main = async (event, context) => { const res = await db .collection('ratings') .aggregate() .project({ ln: $.ln('$x') }) .end() console.log(res.data) } ``` --- ## db.command.aggregate.log # db.command.aggregate.log ### 1. 操作符描述 功能:计算给定数字在给定对数底下的 log 值。 声明:`db.command.aggregate.log([number, base])` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------------------- | ---- | --------------------------------------------------------------------------------------------- | | - | <Array>[Expression](../expression) | 是 | `` 可以是任意解析为非负数字的表达式。`` 可以是任意解析为大于 1 的数字的表达式。 | 注意事项: > 如果任一参数解析为 `null` 或指向任意一个不存在的字段,`log` 返回 `null`。如果任一参数解析为 `NaN`,`log` 返回 `NaN`。 ### 3. 示例代码 假设集合 `staff` 有如下记录: ``` { _id: 1, x: 1 } { _id: 2, x: 2 } { _id: 3, x: 3 } ``` 计算 `log2(x)` 的值: ```js // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate exports.main = async (event, context) => { const res = await db .collection('staff') .aggregate() .project({ log: $.log(['$x', 2]) }) .end() console.log(res.data) } ``` 返回结果如下: ``` { _id: 1, log: 0 } { _id: 2, log: 1 } { _id: 3, log: 1.58496250072 } ``` --- ## db.command.aggregate.log10 # db.command.aggregate.log10 ### 1. 操作符描述 功能:计算给定数字在对数底为 10 下的 log 值。 声明:`db.command.aggregate.log10(number)` 注意事项: > `log10` 等同于 `log` 方法的第二个参数固定为 10。 ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------ | ---- | ------------------------------------------- | | - | [Expression](../expression) | 是 | `number` 可以是任意解析为非负数字的表达式。 | ### 3. 示例代码 假设集合 `staff` 有如下记录: ``` { _id: 1, x: 1 } { _id: 2, x: 2 } { _id: 3, x: 3 } ``` 计算 `log10(x)` 的值: ```js // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate exports.main = async (event, context) => { const res = await db .collection('ratings') .aggregate() .project({ log10: $.log10('$x') }) .end() console.log(res.data) } ``` --- ## db.command.aggregate.lt # db.command.aggregate.lt ### 1. 操作符描述 功能:匹配两个值,如果前者小于后者则返回 `true`,否则返回 `false`。 声明:`db.command.aggregate.lt([value1, value2])` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------------------- | ---- | -------------- | | - | <Array>[Expression](../expression) | 是 | 聚合表达式数组 | ### 3. 示例代码 假设集合 `price` 有如下记录: ```json { "_id": 1, "value": 10 } { "_id": 2, "value": 80 } { "_id": 3, "value": 50 } ``` 判断 `value` 是否小于 50。 ```js // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate exports.main = async (event, context) => { const res = await db .collection('price') .aggregate() .project({ matched: $.lt(['$value', 50]) }) .end() console.log(res.data) } ``` 返回结果如下: ```json { "_id": 1, "matched": true } { "_id": 2, "matched": false } { "_id": 3, "matched": false } ``` --- ## db.command.aggregate.lte # db.command.aggregate.lte ### 1. 操作符描述 功能:匹配两个值,如果前者小于或等于后者则返回 `true`,否则返回 `false`。 声明:`db.command.aggregate.lte([value1, value2])` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------------------- | ---- | -------------- | | - | <Array>[Expression](../expression) | 是 | 聚合表达式数组 | ### 3. 示例代码 假设集合 `price` 有如下记录: ```json { "_id": 1, "value": 10 } { "_id": 2, "value": 80 } { "_id": 3, "value": 50 } ``` 判断 `value` 是否小于 50。 ```js // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate exports.main = async (event, context) => { const res = await db .collection('price') .aggregate() .project({ matched: $.lte(['$value', 50]) }) .end() console.log(res.data) } ``` 返回结果如下: ```json { "_id": 1, "matched": true } { "_id": 2, "matched": false } { "_id": 3, "matched": true } ``` --- ## db.command.aggregate.map # db.command.aggregate.map ### 1. 操作符描述 功能:类似 JavaScript Array 上的 `map` 方法,将给定数组的每个元素按给定转换方法转换后得出新的数组。 声明:`db.command.aggregate.map({ input: expression, as: string, in: expression })` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ----- | ------------------------------ | ---- | --------------------------------------------------------------------------------------------------------------- | | input | [Expression](../expression) | 是 | 一个可以解析为数组的表达式 | | as | string | 否 | 可选,用于表示数组各个元素的变量,默认为 this | | in | [Expression](../expression) | 是 | 一个可以应用在给定数组的各个元素上的表达式,各个元素的名字由 `as` 参数决定(参数名需加 `$$` 前缀,如 `$$this`) | ### 3. 示例代码 假设集合 `stats` 有如下记录: ```json { "_id": 1, "sales": [ 1.32, 6.93, 2.48, 2.82, 5.74 ] } { "_id": 2, "sales": [ 2.97, 7.13, 1.58, 6.37, 3.69 ] } ``` 将各个数字截断为整形,然后求和 ```js // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate exports.main = async (event, context) => { const res = await db .collection('stats') .aggregate() .project({ truncated: $.map({ input: '$sales', as: 'num', in: $.trunc('$$num') }) }) .project({ total: $.sum('$truncated') }) .end() console.log(res.data) } ``` 返回结果如下: ```json { "_id": 1, "index": 16 } { "_id": 2, "index": 19 } ``` --- ## db.command.aggregate.max # db.command.aggregate.max ### 1. 操作符描述 功能:返回一组数值的最大值。 声明:`db.command.aggregate.max()` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------ | ---- | -------------------------------------- | | - | [Expression](../expression) | 是 | 表达式是形如 `$ + 指定字段` 的字符串。 | ### 3. 示例代码 假设集合 `students` 的记录如下: ```json { "group": "a", "name": "stu1", "score": 84 } { "group": "a", "name": "stu2", "score": 96 } { "group": "b", "name": "stu3", "score": 80 } { "group": "b", "name": "stu4", "score": 100 } ``` 借助 `max` 可以统计不同组( `group` )中成绩的最高值,代码如下: ```javascript // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate exports.main = async (event, context) => { const res = await db .collection('students') .aggregate() .group({ _id: '$group', maxScore: $.max('$score') }) .end() console.log(res.data) } ``` 返回的数据结果如下: ```json { "_id": "b", "maxScore": 100 } { "_id": "a", "maxScore": 96 } ``` --- ## db.command.aggregate.mergeObjects # db.command.aggregate.mergeObjects ### 1. 操作符描述 功能:将多个文档合并为单个文档。 声明:`db.command.aggregate.max()` 表达式有两种使用形式如下: - 在 `group()` 中使用时: ``` mergeObjects() ``` - 在其它表达式中使用时: ``` mergeObjects([, , ...]) ``` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ----------------------------------------------------------------------------- | ---- | ---------- | | - | [Expression](../expression) or <Array>[Expression](../expression.md) | 是 | 聚合表达式 | ### 3. 示例代码 #### 搭配 `group()` 使用 假设集合 `sales` 存在以下文档: ```json { "_id": 1, "year": 2018, "name": "A", "volume": { "2018Q1": 500, "2018Q2": 500 } } { "_id": 2, "year": 2017, "name": "A", "volume": { "2017Q1": 400, "2017Q2": 300, "2017Q3": 0, "2017Q4": 0 } } { "_id": 3, "year": 2018, "name": "B", "volume": { "2018Q1": 100 } } { "_id": 4, "year": 2017, "name": "B", "volume": { "2017Q3": 100, "2017Q4": 250 } } ``` 下面的代码使用 `mergeObjects()`,将用相同 `name` 的文档合并: ```js // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('sales') .aggregate() .group({ _id: '$name', mergedVolume: $.mergeObjects('$volume') }) .end() console.log(res.data) } ``` 输出如下: ```json { "_id": "A", "mergedVolume": { "2017Q1": 400, "2017Q2": 300, "2017Q3": 0, "2017Q4": 0, "2018Q1": 500, "2018Q2": 500 } } { "_id": "B", "mergedVolume": { "2017Q3": 100, "2017Q4": 250, "2018Q1": 100 } } ``` #### 一般用法 假设集合 `test` 存在以下文档: ```json { "_id": 1, "foo": { "a": 1 }, "bar": { "b": 2 } } { "_id": 2, "foo": { "c": 1 }, "bar": { "d": 2 } } { "_id": 3, "foo": { "e": 1 }, "bar": { "f": 2 } } ``` 下面的代码使用 `mergeObjects()`,将文档中的 `foo` 和 `bar` 字段合并为 `foobar`: ```js // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('sales') .aggregate() .project({ foobar: $.mergeObjects(['$foo', '$bar']) }) .end() console.log(res.data) } ``` 输出结果如下: ```json { "_id": 1, "foobar": { "a": 1, "b": 2 } } { "_id": 2, "foobar": { "c": 1, "d": 2 } } { "_id": 3, "foobar": { "e": 1, "f": 2 } } ``` --- ## db.command.aggregate.millisecond # db.command.aggregate.millisecond ### 1. 操作符描述 功能:返回日期字段对应的毫秒数,是一个介于 0 到 999 之间的整数。 声明:`db.command.aggregate.millisecond()` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------ | ---- | ---------- | | - | [Expression](../expression) | 是 | 聚合表达式 | ### 3. 示例代码 假设集合 `dates` 有以下文档: ```json { "_id": 1, "date": ISODate("2019-05-14T09:38:51.686Z") } ``` 我们使用 `millisecond()` 对 `date` 字段进行投影,获取对应的毫秒数: ```javascript // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('dates') .aggregate() .project({ _id: 0, millisecond: $.millisecond('$date') }) .end() console.log(res.data) } ``` 输出如下: ```json { "millisecond": 686 } ``` --- ## db.command.aggregate.min # db.command.aggregate.min ### 1. 操作符描述 功能:返回一组数值的最小值。 声明:`db.command.aggregate.min()` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------ | ---- | -------------------------------------- | | - | [Expression](../expression) | 是 | 表达式是形如 `$ + 指定字段` 的字符串。 | ### 3. 示例代码 假设集合 `students` 的记录如下: ```json { "group": "a", "name": "stu1", "score": 84 } { "group": "a", "name": "stu2", "score": 96 } { "group": "b", "name": "stu3", "score": 80 } { "group": "b", "name": "stu4", "score": 100 } ``` 借助 `min` 可以统计不同组( `group` )中成绩的最低值,代码如下: ```javascript // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('students') .aggregate() .group({ _id: '$group', minScore: $.min('$score') }) .end() console.log(res.data) } ``` 返回的数据结果如下: ```json { "_id": "b", "minScore": 80 } { "_id": "a", "minScore": 84 } ``` --- ## db.command.aggregate.minute # db.command.aggregate.minute ### 1. 操作符描述 功能:返回日期字段对应的分钟数,是一个介于 0 到 59 之间的整数。 声明:`db.command.aggregate.minute()` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------ | ---- | ---------- | | - | [Expression](../expression) | 是 | 聚合表达式 | ### 3. 示例代码 假设集合 `dates` 有以下文档: ```json { "_id": 1, "date": ISODate("2019-05-14T09:38:51.686Z") } ``` 我们使用 `minute()` 对 `date` 字段进行投影,获取对应的分钟数: ```javascript // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('dates') .aggregate() .project({ _id: 0, minute: $.minute('$date') }) .end() console.log(res.data) } ``` 输出如下: ```json { "minute": 38 } ``` --- ## db.command.aggregate.mod # db.command.aggregate.mod ### 1. 操作符描述 功能:取模运算,取数字取模后的值。 声明:`db.command.aggregate.mod([dividend, divisor])` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------------------- | ---- | ------------------------------------------------------------------------ | | - | <Array>[Expression](../expression) | 是 | 第一个数字是被除数,第二个数字是除数。参数可以是任意解析为数字的表达式。 | ### 3. 示例代码 假设集合 `shopping` 有如下记录: ``` { _id: 1, bags: 3, items: 5 } { _id: 2, bags: 2, items: 8 } { _id: 3, bags: 5, items: 16 } ``` 各记录取 `items` 除以 `bags` 的余数(`items % bags`): ```js // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('shopping') .aggregate() .project({ overflow: $.mod(['$items', '$bags']) }) .end() console.log(res.data) } ``` 返回结果如下: ``` { _id: 1, log: 2 } { _id: 2, log: 0 } { _id: 3, log: 1 } ``` --- ## db.command.aggregate.month # db.command.aggregate.month ### 1. 操作符描述 功能:返回日期字段对应的月份,是一个介于 1 到 12 之间的整数。 声明:`db.command.aggregate.month()` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------ | ---- | ------------ | | - | [Expression](../expression) | 是 | 聚合表达式。 | ### 3. 示例代码 假设集合 `dates` 有以下文档: ```json { "_id": 1, "date": ISODate("2019-05-14T09:38:51.686Z") } ``` 我们使用 `month()` 对 `date` 字段进行投影,获取对应的月份: ```javascript // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('dates') .aggregate() .project({ _id: 0, month: $.month('$date') }) .end() console.log(res.data) } ``` 输出如下: ```json { "month": 5 } ``` --- ## db.command.aggregate.multiply # db.command.aggregate.multiply ### 1. 操作符描述 功能:取传入的数字参数相乘的结果。 声明:`db.command.aggregate.multiply([expression1, expression2, ...])` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------ | ---- | ---------------------------------- | | - | [Expression](../expression) | 是 | 参数可以是任意解析为数字的表达式。 | ### 3. 示例代码 假设集合 `fruits` 有如下记录: ```json { "_id": 1, "name": "apple", "price": 10, "quantity": 100 } { "_id": 2, "name": "orange", "price": 15, "quantity": 50 } { "_id": 3, "name": "lemon", "price": 5, "quantity": 20 } ``` 求各个水果的的总价值: ```js // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('fruits') .aggregate() .project({ name: 1, total: $.multiply(['$price', '$quantity']) }) .end() console.log(res.data) } ``` 返回结果如下: ```json { "_id": 1, "name": "apple", "total": 1000 } { "_id": 2, "name": "orange", "total": 750 } { "_id": 3, "name": "lemo", "total": 100 } ``` --- ## db.command.aggregate.neq # db.command.aggregate.neq ### 1. 操作符描述 功能:匹配两个值,如果不相等则返回 `true`,否则返回 `false`。 声明:`db.command.aggregate.neq([value1, value2])` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------------------- | ---- | -------------- | | - | <Array>[Expression](../expression) | 是 | 聚合表达式数组 | ### 3. 示例代码 假设集合 `price` 有如下记录: ```json { "_id": 1, "value": 10 } { "_id": 2, "value": 80 } { "_id": 3, "value": 50 } ``` 求 `value` 不等于 50 的记录。 ```js // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('price') .aggregate() .project({ matched: $.neq(['$value', 50]) }) .end() console.log(res.data) } ``` 返回结果如下: ```json { "_id": 1, "matched": true } { "_id": 2, "matched": true } { "_id": 3, "matched": false } ``` --- ## db.command.aggregate.not # db.command.aggregate.not ### 1. 操作符描述 功能:给定一个表达式,如果表达式返回 `true`,则 `not` 返回 `false`,否则返回 `true`。 声明:`db.command.aggregate.not(expression)` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------ | ---- | -------------------------------------------------------------------------------------------------------------- | | - | [Expression](../expression) | 是 | 如果表达式返回 `false`、`null`、`0`、或 `undefined`,表达式会解析为 `false`,否则对其他返回值都认为是 `true`。 | ### 3. 示例代码 假设集合 `price` 有如下记录: ```json { "_id": 1, "min": 10, "max": 100 } { "_id": 2, "min": 60, "max": 80 } { "_id": 3, "min": 30, "max": 50 } ``` 求 `min` 不大于 40 的记录。 ```js // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('price') .aggregate() .project({ fullfilled: $.not($.gt(['$min', 40])) }) .end() console.log(res.data) } ``` 返回结果如下: ```json { "_id": 1, "fullfilled": true } { "_id": 2, "fullfilled": false } { "_id": 3, "fullfilled": true } ``` --- ## db.command.aggregate.objectToArray # db.command.aggregate.objectToArray ### 1. 操作符描述 功能:将一个对象转换为数组。方法把对象的每个键值对都变成输出数组的一个元素,元素形如 `{ k: , v: }`。 声明:`db.command.aggregate.objectToArray(object)` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------ | ---- | ---------- | | - | Object | 是 | 键值对对象 | ### 3. 示例代码 假设集合 `items` 有如下记录: ```json { "_id": 1, "attributes": { "color": "red", "price": 150 } } { "_id": 2, "attributes": { "color": "blue", "price": 50 } } { "_id": 3, "attributes": { "color": "yellow", "price": 10 } } ``` ```js // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('items') .aggregate() .project({ array: $.objectToArray('$attributes') }) .end() console.log(res.data) } ``` 返回结果如下: ```json { "_id": 1, "array": [{ "k": "color", "v": "red" }, { "k": "price", "v": 150 }] } { "_id": 2, "array": [{ "k": "color", "v": "blue" }, { "k": "price", "v": 50 }] } { "_id": 3, "array": [{ "k": "color", "v": "yellow" }, { "k": "price", "v": 10 }] } ``` --- ## db.command.aggregate.or # db.command.aggregate.or ### 1. 操作符描述 功能:给定多个表达式,如果任意一个表达式返回 `true`,则 `or` 返回 `true`,否则返回 `false`。 声明:`db.command.aggregate.or([expression1, expression2, ...])` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------------------- | ---- | -------------- | | - | <Array>[Expression](../expression) | 是 | 聚合表达式数组 | ### 3. 示例代码 假设集合 `price` 有如下记录: ```json { "_id": 1, "min": 10, "max": 100 } { "_id": 2, "min": 60, "max": 80 } { "_id": 3, "min": 30, "max": 50 } ``` 求 `min` 小于 40 且 `max` 大于 60 的记录。 ```js // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('price') .aggregate() .project({ fullfilled: $.or([$.lt(['$min', 30]), $.gt(['$max', 60])]) }) .end() console.log(res.data) } ``` 返回结果如下: ```json { "_id": 1, "fullfilled": true } { "_id": 2, "fullfilled": false } { "_id": 3, "fullfilled": true } ``` --- ## db.command.aggregate.pow # db.command.aggregate.pow ### 1. 操作符描述 功能:求给定基数的指数次幂。 声明:`db.command.aggregate.pow([base, exponent])` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------------------- | ---- | -------------- | | - | <Array>[Expression](../expression) | 是 | 聚合表达式数组 | ### 3. 示例代码 假设集合 `stats` 有如下记录: ```json { "_id": 1, "x": 2, "y": 3 } { "_id": 2, "x": 5, "y": 7 } { "_id": 3, "x": 10, "y": 20 } ``` 求 `x` 和 `y` 的平方和: ```js // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('stats') .aggregate() .project({ sumOfSquares: $.add([$.pow(['$x', 2]), $.pow(['$y', 2])]) }) .end() console.log(res.data) } ``` 返回结果如下: ```json { "_id": 1, "sumOfSquares": 13 } { "_id": 2, "sumOfSquares": 74 } { "_id": 3, "sumOfSquares": 500 } ``` --- ## db.command.aggregate.push # db.command.aggregate.push ### 1. 操作符描述 功能:在 `group` 阶段,返回一组中表达式指定列与对应的值,一起组成的数组。 声明:`db.command.aggregate.push({ : , : , ... })` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------ | ---- | ------------------------ | | - | Object | 是 | 对象键值为任意聚合表达式 | ### 3. 示例代码 假设集合 `students` 的记录如下: ```json { "group": "a", "name": "stu1", "score": 84 } { "group": "a", "name": "stu2", "score": 96 } { "group": "b", "name": "stu3", "score": 80 } { "group": "b", "name": "stu4", "score": 100 } ``` 借助 `push` 操作,对不同分组( `group` )的所有记录,聚合所有数据并且将其放入一个新的字段中,进一步结构化和语义化数据。 ```javascript // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('students') .aggregate() .group({ _id: '$group', students: $.push({ name: '$name', score: '$score' }) }) .end() console.log(res.data) } ``` 输出结果如下: ```json { "_id": "b", "students": [{ "name": "stu3", "score": 80 }, { "name": "stu4", "score": 100 }] } { "_id": "a", "students": [{ "name": "stu1", "score": 84 }, { "name": "stu2", "score": 96 }] } ``` --- ## db.command.aggregate.range # db.command.aggregate.range ### 1. 操作符描述 功能:返回一组生成的序列数字。给定开始值、结束值、非零的步长,`range` 会返回从开始值开始逐步增长、步长为给定步长、但不包括结束值的序列。 声明:`db.command.aggregate.range([, , ])` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------------------- | ---- | -------------- | | - | <Array>[Expression](../expression) | 是 | 聚合表达式数组 | | 字段 | 类型 | 必填 | 说明 | | ------------- | ------------------------------ | ---- | ---------------------------------------------------- | | start | [Expression](../expression) | 是 | 开始值,一个可以解析为整形的表达式 | | end | [Expression](../expression.md) | 是 | 结束值,一个可以解析为整形的表达式 | | non-zero step | number | 否 | 可选,步长,一个可以解析为非零整形的表达式,默认为 1 | ### 3. 示例代码 假设集合 `stats` 有如下记录: ```json { "_id": 1, "max": 52 } { "_id": 2, "max": 38 } ``` ```js // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('stats') .aggregate() .project({ points: $.range([0, '$max', 10]) }) .end() console.log(res.data) } ``` 返回结果如下: ```json { "_id": 1, "points": [0, 10, 20, 30, 40, 50] } { "_id": 2, "points": [0, 10, 20] } ``` --- ## db.command.aggregate.reduce # db.command.aggregate.reduce ### 1. 操作符描述 功能:类似 JavaScript 的 `reduce` 方法,应用一个表达式于数组各个元素然后归一成一个元素。 声明:`db.command.aggregate.reduce({ input: array initialValue: expression, in: expression })` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ------------ | ------------------------------ | ---- | ----------------------------------------------------------------------------------------------------------------- | | input | [Expression](../expression) | 是 | 输入数组,可以是任意解析为数组的表达式 | | initialValue | [Expression](../expression.md) | 是 | 初始值 | | in | [Expression](../expression) | 是 | 用来作用于每个元素的表达式,在 `in` 中有两个可用变量,`value` 是表示累计值的变量,`this` 是表示当前数组元素的变量 | ### 3. 示例代码 #### 简易字符串拼接 假设集合 `player` 有如下记录: ```json { "_id": 1, "fullname": [ "Stephen", "Curry" ] } { "_id": 2, "fullname": [ "Klay", "Thompsom" ] } ``` 获取各个球员的全名,并加 `Player:` 前缀: ```js // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('player') .aggregate() .project({ info: $.reduce({ input: '$fullname', initialValue: 'Player:', in: $.concat(['$$value', ' ', '$$this']) }) }) .end() console.log(res.data) } ``` 返回结果如下: ```json { "_id": 1, "info": "Player: Stephen Curry" } { "_id": 2, "info": "Player: Klay Thompson" } ``` 获取各个球员的全名,不加前缀: ```js const $ = db.command.aggregate db.collection('player') .aggregate() .project({ name: $.reduce({ input: '$fullname', initialValue: '', in: $.concat([ '$$value', $.cond({ if: $.eq(['$$value', '']), then: '', else: ' ' }), '$$this' ]) }) }) .end() ``` 返回结果如下: ```json { "_id": 1, "name": "Stephen Curry" } { "_id": 2, "name": "Klay Thompson" } ``` --- ## db.command.aggregate.reverseArray # db.command.aggregate.reverseArray ### 1. 操作符描述 功能:返回给定数组的倒序形式。 声明:`db.command.aggregate.reverseArray(array)` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------ | ---- | -------------------------------- | | - | [Expression](../expression) | 是 | 参数可以是任意解析为数组表达式。 | ### 3. 示例代码 假设集合 `stats` 有如下记录: ```json { "_id": 1, "sales": [1, 2, 3, 4, 5] } ``` 取 `sales` 倒序: ```js // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('stats') .aggregate() .project({ reversed: $.reverseArray('$sales') }) .end() console.log(res.data) } ``` 返回结果如下: ```json { "_id": 1, "reversed": [5, 4, 3, 2, 1] } ``` --- ## db.command.aggregate.second # db.command.aggregate.second ### 1. 操作符描述 功能:返回日期字段对应的秒数,是一个介于 0 到 59 之间的整数,在特殊情况下(闰秒)可能等于 60。 声明:`db.command.aggregate.second()` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------ | ---- | ---------- | | - | [Expression](../expression) | 是 | 聚合表达式 | ### 3. 示例代码 假设集合 `dates` 有以下文档: ```json { "_id": 1, "date": ISODate("2019-05-14T09:38:51.686Z") } ``` 我们使用 `second()` 对 `date` 字段进行投影,获取对应的秒数: ```javascript // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('dates') .aggregate() .project({ _id: 0, second: $.second('$date') }) .end() console.log(res.data) } ``` 输出如下: ```json { "second": 51 } ``` --- ## db.command.aggregate.setDifference # db.command.aggregate.setDifference ### 1. 操作符描述 功能:输入两个集合,输出只存在于第一个集合中的元素。 声明:`setDifference([expression1, expression2])` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------------------- | ---- | -------------- | | - | <Array>[Expression](../expression) | 是 | 聚合表达式数组 | ### 3. 示例代码 假设集合 `test` 存在以下数据: ```json { "_id": 1, "A": [ 1, 2 ], "B": [ 1, 2 ] } { "_id": 2, "A": [ 1, 2 ], "B": [ 2, 1, 2 ] } { "_id": 3, "A": [ 1, 2 ], "B": [ 1, 2, 3 ] } { "_id": 4, "A": [ 1, 2 ], "B": [ 3, 1 ] } { "_id": 5, "A": [ 1, 2 ], "B": [ ] } { "_id": 6, "A": [ 1, 2 ], "B": [ {}, [] ] } { "_id": 7, "A": [ ], "B": [ ] } { "_id": 8, "A": [ ], "B": [ 1 ] } ``` 下面的代码使用 `setDifference`,找到只存在于 `B` 中的数字: ```js // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('test') .aggregate() .project({ isBOnly: $.setDifference(['$B', '$A']) }) .end() console.log(res.data) } ``` ```json { "_id": 1, "isBOnly": [] } { "_id": 2, "isBOnly": [3] } { "_id": 3, "isBOnly": [3] } { "_id": 4, "isBOnly": [5] } { "_id": 5, "isBOnly": [] } { "_id": 6, "isBOnly": [{}, []] } { "_id": 7, "isBOnly": [] } { "_id": 8, "isBOnly": [1] } ``` --- ## db.command.aggregate.setEquals # db.command.aggregate.setEquals ### 1. 操作符描述 功能:输入两个集合,判断两个集合中包含的元素是否相同(不考虑顺序、去重)。 声明:`setEquals([expression1, expression2])` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------------------- | ---- | -------------- | | - | <Array>[Expression](../expression) | 是 | 聚合表达式数组 | ### 3. 示例代码 假设集合 `test` 存在以下数据: ```json { "_id": 1, "A": [ 1, 2 ], "B": [ 1, 2 ] } { "_id": 2, "A": [ 1, 2 ], "B": [ 2, 1, 2 ] } { "_id": 3, "A": [ 1, 2 ], "B": [ 1, 2, 3 ] } { "_id": 4, "A": [ 1, 2 ], "B": [ 3, 1 ] } { "_id": 5, "A": [ 1, 2 ], "B": [ ] } { "_id": 6, "A": [ 1, 2 ], "B": [ {}, [] ] } { "_id": 7, "A": [ ], "B": [ ] } { "_id": 8, "A": [ ], "B": [ 1 ] } ``` 下面的代码使用 `setEquals`,判断两个集合中包含的元素是否相同: ```js // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('test') .aggregate() .project({ sameElements: $.setEquals(['$A', '$B']) }) .end() console.log(res.data) } ``` ```json { "_id": 1, "sameElements": true } { "_id": 2, "sameElements": true } { "_id": 3, "sameElements": false } { "_id": 4, "sameElements": false } { "_id": 5, "sameElements": false } { "_id": 6, "sameElements": false } { "_id": 7, "sameElements": true } { "_id": 8, "sameElements": false } ``` --- ## db.command.aggregate.setIntersection # db.command.aggregate.setIntersection ### 1. 操作符描述 功能:输入两个集合,输出两个集合的交集。 声明:`setIntersection([expression1, expression2])` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------------------- | ---- | -------------- | | - | <Array>[Expression](../expression) | 是 | 聚合表达式数组 | ### 3. 示例代码 假设集合 `test` 存在以下数据: ```json { "_id": 1, "A": [ 1, 2 ], "B": [ 1, 2 ] } { "_id": 2, "A": [ 1, 2 ], "B": [ 2, 1, 2 ] } { "_id": 3, "A": [ 1, 2 ], "B": [ 1, 2, 3 ] } { "_id": 4, "A": [ 1, 2 ], "B": [ 3, 1 ] } { "_id": 5, "A": [ 1, 2 ], "B": [ ] } { "_id": 6, "A": [ 1, 2 ], "B": [ {}, [] ] } { "_id": 7, "A": [ ], "B": [ ] } { "_id": 8, "A": [ ], "B": [ 1 ] } ``` 下面的代码使用 `setIntersection`,输出两个集合的交集: ```js // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('test') .aggregate() .project({ commonToBoth: $.setIntersection(['$A', '$B']) }) .end() console.log(res.data) } ``` 输出如下: ```json { "_id": 1, "commonToBoth": [ 1, 2 ] } { "_id": 2, "commonToBoth": [ 1, 2 ] } { "_id": 3, "commonToBoth": [ 1, 2 ] } { "_id": 4, "commonToBoth": [ 1 ] } { "_id": 5, "commonToBoth": [ ] } { "_id": 6, "commonToBoth": [ ] } { "_id": 7, "commonToBoth": [ ] } { "_id": 8, "commonToBoth": [ ] } ``` --- ## db.command.aggregate.setIsSubset # db.command.aggregate.setIsSubset ### 1. 操作符描述 功能:输入两个集合,判断第一个集合是否是第二个集合的子集。 声明:``setIsSubset([expression1, expression2])` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------------------- | ---- | -------------- | | - | <Array>[Expression](../expression) | 是 | 聚合表达式数组 | ### 3. 示例代码 假设集合 `test` 存在以下数据: ```json { "_id": 1, "A": [ 1, 2 ], "B": [ 1, 2 ] } { "_id": 2, "A": [ 1, 2 ], "B": [ 2, 1, 2 ] } { "_id": 3, "A": [ 1, 2 ], "B": [ 1, 2, 3 ] } { "_id": 4, "A": [ 1, 2 ], "B": [ 3, 1 ] } { "_id": 5, "A": [ 1, 2 ], "B": [ ] } { "_id": 6, "A": [ 1, 2 ], "B": [ {}, [] ] } { "_id": 7, "A": [ ], "B": [ ] } { "_id": 8, "A": [ ], "B": [ 1 ] } ``` 下面的代码使用 `setIsSubset`,判断第一个集合是否是第二个集合的子集: ```js // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('test') .aggregate() .project({ AisSubsetOfB: $.setIsSubset(['$A', '$B']) }) .end() console.log(res.data) } ``` ```json { "_id": 1, "AisSubsetOfB": true } { "_id": 2, "AisSubsetOfB": true } { "_id": 3, "AisSubsetOfB": true } { "_id": 4, "AisSubsetOfB": false } { "_id": 5, "AisSubsetOfB": false } { "_id": 6, "AisSubsetOfB": false } { "_id": 7, "AisSubsetOfB": true } { "_id": 8, "AisSubsetOfB": true } ``` --- ## db.command.aggregate.setUnion # db.command.aggregate.setUnion ### 1. 操作符描述 功能:输入两个集合,输出两个集合的并集。 声明:``db.command.aggregate.setUnion([expression1, expression2])` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------------------- | ---- | -------------- | | - | <Array>[Expression](../expression) | 是 | 聚合表达式数组 | ### 3. 示例代码 假设集合 `test` 存在以下数据: ```json { "_id": 1, "A": [ 1, 2 ], "B": [ 1, 2 ] } { "_id": 2, "A": [ 1, 2 ], "B": [ 2, 1, 2 ] } { "_id": 3, "A": [ 1, 2 ], "B": [ 1, 2, 3 ] } { "_id": 4, "A": [ 1, 2 ], "B": [ 3, 1 ] } { "_id": 5, "A": [ 1, 2 ], "B": [ ] } { "_id": 6, "A": [ 1, 2 ], "B": [ {}, [] ] } { "_id": 7, "A": [ ], "B": [ ] } { "_id": 8, "A": [ ], "B": [ 1 ] } ``` 下面的代码使用 `setUnion`,输出两个集合的并集: ```js // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('test') .aggregate() .project({ AB: $.setUnion(['$A', '$B']) }) .end() console.log(res.data) } ``` 输出如下: ```json { "_id": 1, "AB": [ 1, 2 ] } { "_id": 2, "AB": [ 1, 2 ] } { "_id": 3, "AB": [ 1, 2, 3 ] } { "_id": 4, "AB": [ 1, 2, 3 ] } { "_id": 5, "AB": [ 1, 2 ] } { "_id": 6, "AB": [ 1, 2, {}, [] ] } { "_id": 7, "AB": [ ] } { "_id": 8, "AB": [ 1 ] } ``` --- ## db.command.aggregate.size # db.command.aggregate.size ### 1. 操作符描述 功能:返回数组长度。 声明:``db.command.aggregate.size(array)` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------ | ---- | ------------------------------ | | - | [Expression](../expression) | 是 | 可以是任意解析为数组的表达式。 | ### 3. 示例代码 假设集合 `shops` 有如下记录: ```json { "_id": 1, "staff": [ "John", "Middleton", "George" ] } { "_id": 2, "staff": [ "Steph", "Jack" ] } ``` 计算各个商店的雇员数量: ```js // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('staff') .aggregate() .project({ totalStaff: $.size('$staff') }) .end() console.log(res.data) } ``` 返回结果如下: ```json { "_id": 1, "totalStaff": 3 } { "_id": 2, "totalStaff": 2 } ``` --- ## db.command.aggregate.slice # db.command.aggregate.slice ### 1. 操作符描述 功能:类似 JavaScritp 的 `slice` 方法。返回给定数组的指定子集。 声明:``db.command.aggregate.slice([array, n])` 语法有两种: 返回从开头或结尾开始的 `n` 个元素: ``` db.command.aggregate.slice([array, n]) ``` 返回从指定位置算作数组开头、再向后或向前的 `n` 个元素: ``` db.command.aggregate.slice([array, position, n]) ``` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------------------- | ---- | ---------------------- | | - | <Array>[Expression](../expression) | 是 | 数组各位置元素详述如下 | 数组元素说明: `` 可以是任意解析为数组的表达式。 `` 可以是任意解析为整形的表达式。如果是正数,则将数组的第 `` 个元素作为数组开始;如果 `` 比数组长度更长,`slice` 返回空数组。如果是负数,则将数组倒数第 `` 个元素作为数组开始;如果 `` 的绝对值大于数组长度,则开始位置即为数组开始位置。 `` 可以是任意解析为整形的表达式。如果 `` 有提供,则 `` 必须为正整数。如果是正数,`slice` 返回前 `n` 个元素。如果是负数,`slice` 返回后 `n` 个元素。 ### 3. 示例代码 假设集合 `people` 有如下记录: ```json { "_id": 1, "hobbies": [ "basketball", "football", "tennis", "badminton" ] } { "_id": 2, "hobbies": [ "golf", "handball" ] } { "_id": 3, "hobbies": [ "table tennis", "swimming", "rowing" ] } ``` 统一返回前两个爱好: ```js // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('fruits') .aggregate() .project({ hobbies: $.slice(['$hobbies', 2]) }) .end() console.log(res.data) } ``` 返回结果如下: ```json { "_id": 1, "hobbies": [ "basketball", "football" ] } { "_id": 2, "hobbies": [ "golf", "handball" ] } { "_id": 3, "hobbies": [ "table tennis", "swimming" ] } ``` --- ## db.command.aggregate.split # db.command.aggregate.split ### 1. 操作符描述 功能:按照分隔符分隔数组,并且删除分隔符,返回子字符串组成的数组。如果字符串无法找到分隔符进行分隔,返回原字符串作为数组的唯一元素。 声明:``db.command.aggregate.split([字符串表达式, 分隔符表达式])` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------------------- | ---- | -------------------------------------------------------------------------------- | | - | <Array>[Expression](../expression) | 是 | 字符串表达式和分隔符表达式可以是任意形式的表达式,只要它可以被解析为字符串即可。 | ### 3. 示例代码 假设集合 `students` 的记录如下: ```json { "birthday": "1999/12/12" } { "birthday": "1998/11/11" } { "birthday": "1997/10/10" } ``` 通过 `split` 将每条记录中的 `birthday` 字段对应值分隔成数组,每个数组分别由代表年、月、日的 3 个元素组成: ```javascript // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('students') .aggregate() .project({ _id: 0, birthday: $.split(['$birthday', '/']) }) .end() console.log(res.data) } ``` 返回的结果如下: ```json { "birthday": [ "1999", "12", "12" ] } { "birthday": [ "1998", "11", "11" ] } { "birthday": [ "1997", "10", "10" ] } ``` --- ## db.command.aggregate.sqrt # db.command.aggregate.sqrt ### 1. 操作符描述 功能:求平方根。 声明:``db.command.aggregate.sqrt([number])` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------------------- | ---- | -------------------------------------- | | - | <Array>[Expression](../expression) | 是 | 参数可以是任意解析为非负数字的表达式。 | ### 3. 示例代码 假设直角三角形集合 `triangle` 有如下记录: ```json { "_id": 1, "x": 2, "y": 3 } { "_id": 2, "x": 5, "y": 7 } { "_id": 3, "x": 10, "y": 20 } ``` 假设 `x` 和 `y` 分别为两直角边,则求斜边长: ```js // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('triangle') .aggregate() .project({ len: $.sqrt([$.add([$.pow(['$x', 2]), $.pow(['$y', 2])])]) }) .end() console.log(res.data) } ``` 返回结果如下: ```json { "_id": 1, "len": 3.605551275463989 } { "_id": 2, "len": 8.602325267042627 } { "_id": 3, "len": 22.360679774997898 } ``` --- ## db.command.aggregate.stdDevPop # db.command.aggregate.stdDevPop ### 1. 操作符描述 功能:返回一组字段对应值的标准差。 声明:``db.command.aggregate.stdDevPop()` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------ | ---- | ------------------------------------------------------------------------------------------- | | - | [Expression](../expression) | 是 | 表达式传入的是指定字段,指定字段对应的值的数据类型必须是 `number` ,否则结果会返回 `null`。 | ### 3. 示例代码 假设集合 `students` 的记录如下:`a` 组同学的成绩分别是 84 和 96,`b`组同学的成绩分别是 80 和 100。 ``` { "group":"a", "score":84 } { "group":"a", "score":96 } { "group":"b", "score":80 } { "group":"b", "score":100 } ``` 可以用 `stdDevPop` 来分别计算 `a` 和 `b` 两组同学成绩的标准差,以此来比较哪一组同学的成绩更稳定。代码如下: ```javascript // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('students') .aggregate() .group({ _id: '$group', stdDev: $.stdDevPop('$score') }) .end() console.log(res.data) } ``` 返回的数据结果如下: ``` { "_id": "b", "stdDev": 10 } { "_id": "a", "stdDev": 6 } ``` --- ## db.command.aggregate.stdDevSamp # db.command.aggregate.stdDevSamp ### 1. 操作符描述 功能:计算输入值的样本标准偏差。如果输入值代表数据总体,或者不概括更多的数据,请改用 `db.command.aggregate.stdDevPop`。 声明:``db.command.aggregate.stdDevSamp()` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------ | ---- | -------------------------------------------------------------------------------------------------------------- | | - | [Expression](../expression) | 是 | 表达式传入的是指定字段,`stdDevSamp` 会自动忽略非数字值。如果指定字段所有的值均是非数字,那么结果返回 `null`。 | ### 3. 示例代码 假设集合 `students` 的记录如下: ``` { "score": 80 } { "score": 100 } ``` 可以用 `stdDevSamp` 来计算成绩的标准样本偏差。代码如下: ```javascript // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('students') .aggregate() .group({ _id: null, ageStdDev: $.stdDevSamp('$score') }) .end() console.log(res.data) } ``` 返回的数据结果如下: ``` { "_id": null, "ageStdDev": 14.142135623730951 } ``` 如果向集合 `students` 添加一条新记录,它的 `score` 字段类型是 `string`: ``` { "score": "aa" } ``` 用上面代码计算标准样本偏差时,`stdDevSamp` 会自动忽略类型不为 `number` 的记录,返回结果保持不变。 --- ## db.command.aggregate.strLenBytes # db.command.aggregate.strLenBytes ### 1. 操作符描述 功能:计算并返回指定字符串中 `utf-8` 编码的字节数量。 声明:``db.command.aggregate.strLenBytes()` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------ | ---- | ------------------------------ | | - | [Expression](../expression) | 是 | 可以被解析成字符串的聚合表达式 | ### 3. 示例代码 假设集合 `students` 的记录如下: ```json { "name": "dongyuanxin", "nickname": "心谭" } ``` 借助 `strLenBytes` 计算 `name` 字段和 `nickname` 字段对应值的字节长度: ```javascript // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('students') .aggregate() .project({ _id: 0, nameLength: $.strLenBytes('$name'), nicknameLength: $.strLenBytes('$nickname') }) .end() console.log(res.data) } ``` 返回结果如下: ```javascript { "nameLength": 11, "nicknameLength": 6 } ``` --- ## db.command.aggregate.strLenCP # db.command.aggregate.strLenCP ### 1. 操作符描述 功能:计算并返回指定字符串的 UTF-8 [code points](http://www.unicode.org/glossary/#code_point) 数量。 声明:``db.command.aggregate.strLenCP()` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------ | ---- | ------------------------------ | | - | [Expression](../expression) | 是 | 可以被解析成字符串的聚合表达式 | ### 3. 示例代码 假设集合 `students` 的记录如下: ```json { "name": "dongyuanxin", "nickname": "心谭" } ``` 借助 `strLenCP` 计算 `name` 字段和 `nickname` 字段对应值的 UTF-8 [code points](http://www.unicode.org/glossary/#code_point)的数量: ```javascript // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('students') .aggregate() .project({ _id: 0, nameLength: $.strLenCP('$name'), nicknameLength: $.strLenCP('$nickname') }) .end() console.log(res.data) } ``` 返回结果如下: ```javascript { "nameLength": 11, "nicknameLength": 2 } ``` --- ## db.command.aggregate.strcasecmp # db.command.aggregate.strcasecmp ### 1. 操作符描述 功能:对两个字符串在不区分大小写的情况下进行大小比较,并返回比较的结果。 声明:``db.command.aggregate.strcasecmp([表达式1, 表达式2])` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------------------- | ---- | ----------------------------------------------------------------------------------- | | - | <Array>[Expression](../expression) | 是 | 聚合表达式数组,只要 `表达式1`和 `表达式2` 可以被解析成字符串,那么它们就是有效的。 | 说明: 返回的比较结果有 1,0 和-1 三种 - 1:`表达式1` 解析的字符串 > `表达式2` 解析的字符串 - 0:`表达式1` 解析的字符串 = `表达式2` 解析的字符串 - -1:`表达式1` 解析的字符串 { const res = await db .collection('students') .aggregate() .project({ _id: 0, result: $.strcasecmp(['$firstName', '$lastName']) }) .end() console.log(res.data) } ``` 返回结果如下: ```json { "result": 1 } { "result": 1 } { "result": -1 } ``` --- ## db.command.aggregate.substr # db.command.aggregate.substr ### 1. 操作符描述 功能:返回字符串从指定位置开始的指定长度的子字符串。它是 `db.command.aggregate.substrBytes` 的别名,更推荐使用后者。 声明:``db.command.aggregate.substr([, , ])` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------------------- | ---- | ------------------------------------ | | - | <Array>[Expression](../expression) | 是 | 聚合表达式数组,各位置表达式详述如下 | 参数说明: `表达式1` 是任何可以解析为字符串的有效表达式,`表达式2` 和 `表达式3` 是任何可以解析为数字的有效表达式。 如果 `表达式2` 是负数,返回的结果为 `""`。 如果 `表达式3` 是负数,返回的结果为从 `表达式2` 指定的开始位置以及之后其余部分的子字符串。 ### 3. 示例代码 假设集合 `students` 的记录如下: ```json { "birthday": "1999/12/12", "firstName": "Yuanxin", "group": "a", "lastName": "Dong", "score": 84 } { "birthday": "1998/11/11", "firstName": "Weijia", "group": "a", "lastName": "Wang", "score": 96 } { "birthday": "1997/10/10", "firstName": "Chengxi", "group": "b", "lastName": "Li", "score": 80 } ``` 借助 `substr` 可以提取 `birthday` 中的年、月、日信息,代码如下: ```javascript // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('students') .aggregate() .project({ _id: 0, year: $.substr(['$birthday', 0, 4]), month: $.substr(['$birthday', 5, 2]), day: $.substr(['$birthday', 8, -1]) }) .end() console.log(res.data) } ``` 返回的结果如下: ```json { "day": "12", "month": "12", "year": "1999" } { "day": "11", "month": "11", "year": "1998" } { "day": "10", "month": "10", "year": "1997" } ``` --- ## db.command.aggregate.substrBytes # db.command.aggregate.substrBytes ### 1. 操作符描述 功能:返回字符串从指定位置开始的指定长度的子字符串。子字符串是由字符串中指定的 `UTF-8` 字节索引的字符开始,长度为指定的字节数。 声明:``db.command.aggregate.substrBytes([, , ])` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------------------- | ---- | ------------------------------------ | | - | <Array>[Expression](../expression) | 是 | 聚合表达式数组,各位置表达式详述如下 | 参数说明: `表达式1` 是任何可以解析为字符串的有效表达式,`表达式2` 和 `表达式3` 是任何可以解析为数字的有效表达式。 如果 `表达式2` 是负数,返回的结果为 `""`。 如果 `表达式3` 是负数,返回的结果为从 `表达式2` 指定的开始位置以及之后其余部分的子字符串。 ### 3. 示例代码 假设集合 `students` 的记录如下: ```json { "birthday": "1999/12/12", "firstName": "Yuanxin", "group": "a", "lastName": "Dong", "score": 84 } { "birthday": "1998/11/11", "firstName": "Weijia", "group": "a", "lastName": "Wang", "score": 96 } { "birthday": "1997/10/10", "firstName": "Chengxi", "group": "b", "lastName": "Li", "score": 80 } ``` 借助 `substrBytes` 可以提取 `birthday` 中的年、月、日信息,代码如下: ```javascript // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('students') .aggregate() .project({ _id: 0, year: $.substrBytes(['$birthday', 0, 4]), month: $.substrBytes(['$birthday', 5, 2]), day: $.substrBytes(['$birthday', 8, -1]) }) .end() console.log(res.data) } ``` 返回的结果如下: ```json { "day": "12", "month": "12", "year": "1999" } { "day": "11", "month": "11", "year": "1998" } { "day": "10", "month": "10", "year": "1997" } ``` --- ## db.command.aggregate.substrCP # db.command.aggregate.substrCP ### 1. 操作符描述 功能:返回字符串从指定位置开始的指定长度的子字符串。子字符串是由字符串中指定的 `UTF-8` 字节索引的字符开始,长度为指定的字节数。 声明:``db.command.aggregate.substrCP([, , ])` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------------------- | ---- | ------------------------------------ | | - | <Array>[Expression](../expression) | 是 | 聚合表达式数组,各位置表达式详述如下 | 参数说明: `表达式1` 是任何可以解析为字符串的有效表达式,`表达式2` 和 `表达式3` 是任何可以解析为数字的有效表达式。 如果 `表达式2` 是负数,返回的结果为 `""`。 如果 `表达式3` 是负数,返回的结果为从 `表达式2` 指定的开始位置以及之后其余部分的子字符串。 ### 3. 示例代码 假设集合 `students` 的记录如下: ```json { "name": "dongyuanxin", "nickname": "心谭" } ``` 借助 `substrCP` 可以提取 `nickname` 字段值的第一个汉字: ```javascript // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('students') .aggregate() .project({ _id: 0, firstCh: $.substrCP(['$nickname', 0, 1]) }) .end() console.log(res.data) } ``` 返回的结果如下: ```json { "firstCh": "心" } ``` --- ## db.command.aggregate.subtract # db.command.aggregate.subtract ### 1. 操作符描述 功能:将两个数字相减然后返回差值,或将两个日期相减然后返回相差的毫秒数,或将一个日期减去一个数字返回结果的日期。 声明:``db.command.aggregate.subtract([expression1, expression2])` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------------------- | ---- | -------------------------------------------------------- | | - | <Array>[Expression](../expression) | 是 | 聚合表达式数组,参数可以是任意解析为数字或日期的表达式。 | ### 3. 示例代码 假设集合 `scores` 有如下记录: ```json { "_id": 1, "max": 10, "min": 1 } { "_id": 2, "max": 7, "min": 5 } { "_id": 3, "max": 6, "min": 6 } ``` 求各个记录的 `max` 和 `min` 的差值。: ```js // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('scores') .aggregate() .project({ diff: $.subtract(['$max', '$min']) }) .end() console.log(res.data) } ``` 返回结果如下: ```json { "_id": 1, "diff": 9 } { "_id": 2, "diff": 2 } { "_id": 3, "diff": 0 } ``` --- ## db.command.aggregate.sum # db.command.aggregate.sum ### 1. 操作符描述 功能:计算并且返回一组字段所有数值的总和。 声明:``db.command.aggregate.sum()` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------ | ---- | ---------- | | - | [Expression](../expression) | 是 | 聚合表达式 | 参数说明: 表达式可以传入指定字段,也可以传入指定字段组成的列表。`sum` 会自动忽略非数字值。如果字段下的所有值均是非数字,那么结果返回 0。若传入数字常量,则当做所有记录该字段的值都给给定常量,在聚合时相加,最终值为输入记录数乘以常量。 ### 3. 示例代码 假设代表商品的集合 `goods` 的记录如下:`price` 代表商品销售额,`cost` 代表商品成本 ``` { "cost": -10, "price": 100 } { "cost": -15, "price": 1 } { "cost": -10, "price": 10 } ``` #### 单独字段 借助 `sum` 可以计算所有商品的销售总和,代码如下: ```javascript // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('goods') .aggregate() .group({ _id: null, totalPrice: $.sum('$price') }) .end() console.log(res.data) } ``` 返回的数据结果如下:销售额是 111 ``` { "_id": null, "totalPrice": 111 } ``` #### 字段列表 如果需要计算所有商品的利润总额,那么需要将每条记录的 `cost` 和 `price` 相加得到此记录对应商品的利润。最后再计算所有商品的利润总额。 借助 `sum`,代码如下: ```javascript // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('goods') .aggregate() .group({ _id: null, totalProfit: $.sum($.sum(['$price', '$cost'])) }) .end() console.log(res.data) } ``` 返回的数据结果如下:利润总额为 76 ``` { "_id": null, "totalProfit": 76 } ``` --- ## db.command.aggregate.switch # db.command.aggregate.switch ### 1. 操作符描述 功能:根据给定的 `switch-case-default` 计算返回值、 声明:``db.command.aggregate.switch({ branches: [ case: , then: , case: , then: , ... ], default: })` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------ | ---- | ---------------------------------------------------- | | - | Object | 是 | switch-case-default 语句中各表达式可为任意聚合表达式 | ### 3. 示例代码 假设集合 `items` 的记录如下: ```json { "_id": "0", "name": "item-a", "amount": 100 } { "_id": "1", "name": "item-b", "amount": 200 } { "_id": "2", "name": "item-c", "amount": 300 } ``` 我们可以使用 `switch`,根据 `amount` 字段,来生成新的字段 `discount`: ```javascript // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('items') .aggregate() .project({ name: 1, discount: $.switch({ branches: [ { case: $.gt(['$amount', 250]), then: 0.8 }, { case: $.gt(['$amount', 150]), then: 0.9 } ], default: 1 }) }) .end() console.log(res.data) } ``` 输出如下: ```json { "_id": "0", "name": "item-a", "discount": 1 } { "_id": "1", "name": "item-b", "discount": 0.9 } { "_id": "2", "name": "item-c", "discount": 0.8 } ``` --- ## db.command.aggregate.toLower # db.command.aggregate.toLower ### 1. 操作符描述 功能:将字符串转化为小写并返回。 声明:`db.command.aggregate.toLower()` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------ | ---- | -------------------------------------------------------------------------- | | - | [Expression](../expression) | 是 | 只要表达式可以被解析成字符串,那么它就是有效表达式。例如:`$ + 指定字段`。 | ### 3. 示例代码 假设集合 `students` 的记录如下: ```json { "firstName": "Yuanxin", "group": "a", "lastName": "Dong", "score": 84 } { "firstName": "Weijia", "group": "a", "lastName": "Wang", "score": 96 } { "firstName": "Chengxi", "group": "b", "lastName": "Li", "score": 80 } ``` 借助 `toLower` 将 `firstName` 的字段值转化为小写: ```javascript // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('students') .aggregate() .project({ _id: 0, result: $.toLower('$firstName') }) .end() console.log(res.data) } ``` 返回的结果如下: ```json { "result": "yuanxin" } { "result": "weijia" } { "result": "chengxi" } ``` --- ## db.command.aggregate.toUpper # db.command.aggregate.toUpper ### 1. 操作符描述 功能:将字符串转化为大写并返回。 声明:`db.command.aggregate.toUpper()` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------ | ---- | -------------------------------------------------------------------------- | | - | [Expression](../expression) | 是 | 只要表达式可以被解析成字符串,那么它就是有效表达式。例如:`$ + 指定字段`。 | ### 3. 示例代码 假设集合 `students` 的记录如下: ```json { "firstName": "Yuanxin", "group": "a", "lastName": "Dong", "score": 84 } { "firstName": "Weijia", "group": "a", "lastName": "Wang", "score": 96 } { "firstName": "Chengxi", "group": "b", "lastName": "Li", "score": 80 } ``` 借助 `toUpper` 将 `lastName` 的字段值转化为大写: ```javascript // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('students') .aggregate() .project({ _id: 0, result: $.toUpper('$lastName') }) .end() console.log(res.data) } ``` 返回的结果如下: ```json { "result": "DONG" } { "result": "WANG" } { "result": "LI" } ``` --- ## db.command.aggregate.trunc # db.command.aggregate.trunc ### 1. 操作符描述 功能:将数字截断为整形。 声明:`db.command.aggregate.trunc(number)` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------ | ---- | ---------------------------------- | | - | [Expression](../expression) | 是 | 参数可以是任意解析为数字的表达式。 | ### 3. 示例代码 假设集合 `scores` 有如下记录: ```json { "_id": 1, "value": 1.21 } { "_id": 2, "value": 3.83 } { "_id": 3, "value": -4.94 } ``` ```js // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('scores') .aggregate() .project({ int: $.trunc('$value') }) .end() console.log(res.data) } ``` 返回结果如下: ```json { "_id": 1, "value": 1 } { "_id": 2, "value": 3 } { "_id": 3, "value": -4 } ``` --- ## db.command.aggregate.week # db.command.aggregate.week ### 1. 操作符描述 功能:返回日期字段对应的周数(一年中的第几周),是一个介于 0 到 53 之间的整数。 声明:`db.command.aggregate.week()` 注意事项: > 每周以周日为开头,**每年的第一个周日**即为 `week 1` 的开始,这天之前是 `week 0`。 ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------ | ---- | ---------- | | - | [Expression](../expression) | 是 | 聚合表达式 | ### 3. 示例代码 假设集合 `dates` 有以下文档: ```json { "_id": 1, "date": ISODate("2019-05-14T09:38:51.686Z") } ``` 我们使用 `week()` 对 `date` 字段进行投影,获取对应的周数(一年中的第几周): ```javascript // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('dates') .aggregate() .project({ _id: 0, week: $.week('$date') }) .end() console.log(res.data) } ``` 输出如下: ```json { "week": 19 } ``` --- ## db.command.aggregate.year # db.command.aggregate.year ### 1. 操作符描述 功能:返回日期字段对应的年份。 声明:`db.command.aggregate.year()` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------------------------------ | ---- | ---------- | | - | [Expression](../expression) | 是 | 聚合表达式 | ### 3. 示例代码 假设集合 `dates` 有以下文档: ```json { "_id": 1, "date": ISODate("2019-05-14T09:38:51.686Z") } ``` 我们使用 `year()` 对 `date` 字段进行投影,获取对应的年份: ```javascript // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('dates') .aggregate() .project({ _id: 0, year: $.year('$date') }) .end() console.log(res.data) } ``` 输出如下: ```json { "year": 2019 } ``` --- ## db.command.aggregate.zip # db.command.aggregate.zip ### 1. 操作符描述 功能:把二维数组的第二维数组中的相同序号的元素分别拼装成一个新的数组进而组装成一个新的二维数组。如可将 `[ [ 1, 2, 3 ], [ "a", "b", "c" ] ]` 转换成 `[ [ 1, "a" ], [ 2, "b" ], [ 3, "c" ] ]`。 声明:`db.command.aggregate.zip({ inputs: [array1, array2, ...], useLongestLength: boolean, defaults: array })` ### 2. 操作符参数 | 字段 | 类型 | 必填 | 说明 | | ---------------- | ------------------------------------------- | ---- | ----------------------------- | | inputs | <Array>[Expression](../expression) | 是 | inputs 字段详述如下 | | useLongestLength | boolean | 是 | useLongestLength 字段详述如下 | | defaults | <Array>any | 是 | defaults 字段详述如下 | 参数说明: `inputs` 是一个二维数组(`inputs` 不可以是字段引用),其中每个元素的表达式(这个可以是字段引用)都可以解析为数组。如果其中任意一个表达式返回 `null`,`` 也返回 `null`。如果其中任意一个表达式不是指向一个合法的字段 / 解析为数组 / 解析为 `null`,则返回错误。 `useLongestLength` 决定输出数组的长度是否采用输入数组中的最长数组的长度。默认为 `false`,即输入数组中的最短的数组的长度即是输出数组的各个元素的长度。 `defaults` 是一个数组,用于指定在输入数组长度不一的情况下时采用的数组各元素默认值。指定这个字段则必须指定 `useLongestLength`,否则返回错误。如果 `useLongestLength` 是 `true` 但是 `defaults` 是空或没有指定,则 `zip` 用 `null` 做数组元素的缺省默认值。指定各元素默认值时 `defaults` 数组的长度必须是输入数组最大的长度。 ### 3. 示例代码 假设集合 `stats` 有如下记录: ```json { "_id": 1, "zip1": [1, 2], "zip2": [3, 4], "zip3": [5, 6] ] } { "_id": 2, "zip1": [1, 2], "zip2": [3], "zip3": [4, 5, 6] ] } { "_id": 3, "zip1": [1, 2], "zip2": [3] ] } ``` #### 只传 inputs ```js // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('items') .aggregate() .project({ zip: $.zip({ inputs: [ '$zip1', // 字段引用 '$zip2', '$zip3' ] }) }) .end() console.log(res.data) } ``` 返回结果如下: ```json { "_id": 1, "zip": [ [1, 3, 5], [2, 4, 6] ] } { "_id": 2, "zip": [ [1, 3, 4] ] } { "_id": 3, "zip": null } ``` #### 设置 useLongestLength 如果设 `useLongestLength` 为 `true`: ```js // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('items') .aggregate() .project({ zip: $.zip({ inputs: [ '$zip1', // 字段引用 '$zip2', '$zip3' ], useLongestLength: true }) }) .end() console.log(res.data) } ``` 返回结果如下: ```json { "_id": 1, "zip": [ [1, 3, 5], [2, 4, 6] ] } { "_id": 2, "zip": [ [1, 3, 4], [2, null, 5], [null, null, 6] ] } { "_id": 3, "zip": null } ``` #### 设置 defaults ```js // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate const _ = db.command exports.main = async (event, context) => { const res = await db .collection('items') .aggregate() .project({ zip: $.zip({ inputs: [ '$zip1', // 字段引用 '$zip2', '$zip3' ], useLongestLength: true, defaults: [-300, -200, -100] }) }) .end() console.log(res.data) } ``` 返回结果如下: ```json { "_id": 1, "zip": [ [1, 3, 5], [2, 4, 6] ] } { "_id": 2, "zip": [ [1, 3, 4], [2, -200, 5], [-300, -200, 6] ] } { "_id": 3, "zip": null } ``` --- ## Aggregate.addFields # Aggregate.addFields ### 1. 接口描述 功能: 聚合阶段。添加新字段到输出的记录。经过 `addFields` 聚合阶段,输出的所有记录中除了输入时带有的字段外,还将带有 `addFields` 指定的字段。 声明: `addFields({: })` 注意事项: > `addFields` 等同于同时指定了所有已有字段和新增字段的 `project` 阶段。 > `addFields` 可指定多个新字段,每个新字段的值由使用的表达式决定。如果指定的新字段与原有字段重名,则新字段的值会覆盖原有字段的值。注意 `addFields` 不能用来给数组字段添加元素。 ### 2. 输入参数 | 参数 | 类型 | 必填 | 说明 | | ----------- | --------------------------- | ---- | ---------- | | key(新字段) | [expression](../expression) | 是 | 聚合表达式 | ### 3. 返回结果 | 参数 | 类型 | 必填 | 说明 | | ---- | ---------------- | ---- | -------- | | - | [Aggregate](../) | 是 | 聚合对象 | ### 4. 示例代码 #### 示例 1:连续两次 addFields 假设集合 `scores` 有如下记录: ``` { _id: 1, student: "Maya", homework: [ 10, 5, 10 ], quiz: [ 10, 8 ], extraCredit: 0 } { _id: 2, student: "Ryan", homework: [ 5, 6, 5 ], quiz: [ 8, 8 ], extraCredit: 8 } ``` 应用两次 `addFields`,第一次增加两个字段分别为 `homework` 和 `quiz` 的和值,第二次增加一个字段再基于上两个和值求一次和值。 ```js const tcb = require("@cloudbase/node-sdk"); const app = tcb.init({ env: "xxx", }); const db = app.database(); const $ = db.command.aggregate; exports.main = async (event, context) => { const res = await db .collection("scores") .aggregate() .addFields({ totalHomework: $.sum("$homework"), totalQuiz: $.sum("$quiz"), }) .addFields({ totalScore: $.add(["$totalHomework", "$totalQuiz", "$extraCredit"]), }) .end(); console.log(res.data); }; ``` 返回结果如下: ``` { "_id" : 1, "student" : "Maya", "homework" : [ 10, 5, 10 ], "quiz" : [ 10, 8 ], "extraCredit" : 0, "totalHomework" : 25, "totalQuiz" : 18, "totalScore" : 43 } { "_id" : 2, "student" : "Ryan", "homework" : [ 5, 6, 5 ], "quiz" : [ 8, 8 ], "extraCredit" : 8, "totalHomework" : 16, "totalQuiz" : 16, "totalScore" : 40 } ``` #### 示例 2:在嵌套记录里增加字段 可以用点表示法在嵌套记录里增加字段。假设 `vehicles` 集合含有如下记录: ``` { _id: 1, type: "car", specs: { doors: 4, wheels: 4 } } { _id: 2, type: "motorcycle", specs: { doors: 0, wheels: 2 } } { _id: 3, type: "jet ski" } ``` 可以用如下操作在 `specs` 字段下增加一个新的字段 `fuel_type`,值都设为固定字符串 `unleaded`: ```js const tcb = require("@cloudbase/node-sdk"); const app = tcb.init({ env: "xxx", }); const db = app.database(); const $ = db.command.aggregate; exports.main = async (event, context) => { const res = await db .collection("vehicles") .aggregate() .addFields({ "spec.fuel_type": "unleaded", }) .end(); console.log(res.data); }; ``` 返回结果如下: ``` { _id: 1, type: "car", specs: { doors: 4, wheels: 4, fuel_type: "unleaded" } } { _id: 2, type: "motorcycle", specs: { doors: 0, wheels: 2, fuel_type: "unleaded" } } { _id: 3, type: "jet ski", specs: { fuel_type: "unleaded" } } ``` #### 示例 3:设置字段值为另一个字段 可以通过 `$` 加字段名组成的字符串作为值的表达式来设置字段的值为另一个字段的值。 同样用上一个集合示例,可以用如下操作添加一个字段 `vehicle_type`,将其值设置为 `type` 字段的值: ```js const tcb = require("@cloudbase/node-sdk"); const app = tcb.init({ env: "xxx", }); const db = app.database(); const $ = db.command.aggregate; exports.main = async (event, context) => { const res = await db .collection("vehicles") .aggregate() .addFields({ vehicle_type: "$type", }) .end(); console.log(res.data); }; ``` 返回结果如下: ``` { _id: 1, type: "car", vehicle_type: "car", specs: { doors: 4, wheels: 4, fuel_type: "unleaded" } } { _id: 2, type: "motorcycle", vehicle_type: "motorcycle", specs: { doors: 0, wheels: 2, fuel_type: "unleaded" } } { _id: 3, type: "jet ski", vehicle_type: "jet ski", specs: { fuel_type: "unleaded" } } ``` --- ## Aggregate.bucket # Aggregate.bucket ### 1. 接口描述 功能: 聚合阶段。将输入记录根据给定的条件和边界划分成不同的组,每组即一个 `bucket`。 声明: `bucket({ groupBy: , boundaries: [, , ...], default: , output: { : , ... : } })` 注意事项: > 每组分别作为一个记录输出,包含一个以下界为值的 `_id` 字段和一个以组中记录数为值的 `count` 字段。`count` 在没有指定 `output` 的时候是默认输出的。 > `bucket` 只会在组内有至少一个记录的时候输出。 > 使用 `bucket` 需要满足以下至少一个条件,否则会抛出错误: - 每一个输入记录应用 `groupBy` 表达式获取的值都必须是一个在 `boundaries` 内的值 - 指定一个 `default` 值,该值在 `boundaries` 以外,或与 `boundaries` 元素的值不同的类型。 ### 2. 输入参数 | 参数 | 类型 | 必填 | 说明 | | ---------- | --------------------------- | ---- | ------------ | | groupBy | [expression](../expression) | 是 | 字段详述如下 | | boundaries | Array | 是 | 字段详述如下 | | default | any | 否 | 字段详述如下 | | output | Object | 否 | 字段详述如下 | > `groupBy` 是一个用以决定分组的表达式,会应用在各个输入记录上。可以用 `$` 前缀加上要用以分组的字段路径来作为表达式。除非用 `default` 指定了默认值,否则每个记录都需要包含指定的字段,且字段值必须在 `boundaries` 指定的范围之内。 > `boundaries` 是一个数组,每个元素分别是每组的下界。必须至少指定两个边界值。数组值必须是同类型递增的值。 > `default` 可选,指定之后,没有进入任何分组的记录将都进入一个默认分组,这个分组记录的 `_id` 即由 `default` 决定。`default` 的值必须小于 `boundaries` 中的最小值或大于等于其中的最大值。`default` 的值可以与 `boundaries` 元素值类型不同。 > `output` 可选,用以决定输出记录除了 `_id` 外还要包含哪些字段,各个字段的值必须用累加器表达式指定。当 `output` 指定时,默认的 `count` 是不会被默认输出的,必须手动指定: ``` output: { count: $.sum(1), ... : } ``` ### 3. 返回结果 | 参数 | 类型 | 必填 | 说明 | | ---- | ---------------- | ---- | -------- | | - | [Aggregate](../) | 是 | 聚合对象 | ### 4. 示例代码 假设集合 `items` 有如下记录: ``` { _id: "1", price: 10 } { _id: "2", price: 50 } { _id: "3", price: 20 } { _id: "4", price: 80 } { _id: "5", price: 200 } ``` 对上述记录进行分组,将 [0, 50) 分为一组,[50, 100) 分为一组,其他分为一组: ```js const tcb = require("@cloudbase/node-sdk"); const app = tcb.init({ env: "xxx", }); const db = app.database(); const $ = db.command.aggregate; exports.main = async (event, context) => { const res = await db .collection("items") .aggregate() .bucket({ groupBy: "$price", boundaries: [0, 50, 100], default: "other", output: { count: $.sum(), ids: $.push("$_id"), }, }) .end(); console.log(res.data); }; ``` 返回结果如下: ``` [ { "_id": 0, "count": 2, "ids": [ "1", "3" ] }, { "_id": 50, "count": 2, "ids": [ "2", "4" ] }, { "_id": "other", "count": 1, "ids": [ "5" ] } ] ``` --- ## Aggregate.bucketAuto # Aggregate.bucketAuto ### 1. 接口描述 功能: 聚合阶段。将输入记录根据给定的条件划分成不同的组,每组即一个 `bucket`。 声明: `bucket({ groupBy: , buckets: , granularity: , output: { : , ... : } })` 注意事项: > 与 [`bucket`](./bucket) 的其中一个不同之处在于无需指定 `boundaries`,`bucketAuto` 会自动尝试将记录尽可能平均的分散到每组中。 > 每组分别作为一个记录输出,包含一个以包含组中最大值和最小值两个字段的对象为值的 `_id` 字段和一个以组中记录数为值的 `count` 字段。`count` 在没有指定 `output` 的时候是默认输出的。 ### 2. 输入参数 | 参数 | 类型 | 必填 | 说明 | | ----------- | --------------------------- | ---- | -------------------------- | | groupBy | [expression](../expression) | 是 | 字段详述如下 | | buckets | number | 是 | 用于指定划分组数的正整数。 | | granularity | string | 否 | 字段详述如下 | | output | Object | 否 | 字段详述如下 | > `groupBy` 是一个用以决定分组的表达式,会应用在各个输入记录上。可以用 `$` 前缀加上要用以分组的字段路径来作为表达式。除非用 `default` 指定了默认值,否则每个记录都需要包含指定的字段,且字段值必须在 `boundaries` 指定的范围之内。 > `granularity` 是可选枚举值字符串,用于保证自动计算出的边界符合给定的规则。这个字段仅可在所有 `groupBy` 值都是数字并且没有 `NaN` 的情况下使用。枚举值包括:`R5`、`R10`、`R20`、`R40`、`R80`、`1-2-5`、`E6`、`E12`、`E24`、`E48`、`E96`、`E192`、`POWERSOF2`。 `output` 可选,用以决定输出记录除了 `_id` 外还要包含哪些字段,各个字段的值必须用累加器表达式指定。当 `output` 指定时,默认的 `count` 是不会被默认输出的,必须手动指定: ``` output: { count: $.sum(1), ... : } ``` 在以下情况中,输出的分组可能会小于给定的组数: - 输入记录数少于分组数 - `groupBy` 计算得到的唯一值少于分组数 - `granularity` 的间距少于分组数 - `granularity` 不够精细以至于不能平均分配到各组 #### granularity 详细说明 `granularity` 用于保证边界值属于一个给定的数字序列。 **Renard 序列** [Renard 序列](https://en.wikipedia.org/wiki/Renard_series)是以 10 的 5 / 10 / 20 / 40 / 80 次方根来推导的、在 1.0 到 10.0 (如果是 R80 则是 10.3) 之间的数字序列。 设置 `granularity` 为 R5 / R10 / R20 / R40 / R80 就把边界值限定在序列内。如果 `groupBy` 的值不在 1.0 到 10.0 (如果是 R80 则是 10.3) 内,则序列数字会自动乘以 10。 **E 序列** [E 序列](https://en.wikipedia.org/wiki/E_series_of_preferred_numbers)是以 10 的 6 / 12 / 24 / 48 / 96 / 192 次方跟来推导的、带有一个特定误差的、在 1.0 到 10.0 之间的数字序列。 **1-2-5 序列** [1-2-5 序列](https://en.wikipedia.org/wiki/Preferred_number#1-2-5_series) 表现与三值 Renard 序列一样。 **2 的次方序列** 由 2 的各次方组成的序列数字。 ### 3. 返回结果 | 参数 | 类型 | 必填 | 说明 | | ---- | ---------------- | ---- | -------- | | - | [Aggregate](../) | 是 | 聚合对象 | ### 4. 示例代码 假设集合 `items` 有如下记录: ``` { _id: "1", price: 10.5 } { _id: "2", price: 50.3 } { _id: "3", price: 20.8 } { _id: "4", price: 80.2 } { _id: "5", price: 200.3 } ``` 对上述记录进行自动分组,分成三组: ```js const tcb = require("@cloudbase/node-sdk"); const app = tcb.init({ env: "xxx", }); const db = app.database(); const $ = db.command.aggregate; exports.main = async (event, context) => { const res = await db .collection("items") .aggregate() .bucket({ groupBy: "$price", buckets: 3, }) .end(); console.log(res.data); }; ``` 返回结果如下: ``` { "_id": { "min": 10.5, "max": 50.3 }, "count": 2 } { "_id": { "min": 50.3, "max": 200.3 }, "count": 2 } { "_id": { "min": 200.3, "max": 200.3 }, "count": 1 } ``` --- ## Aggregate.count # Aggregate.count ### 1. 接口描述 功能: 聚合阶段。计算输入记录数,输出一个记录,其中指定字段的值为记录数。`count` 阶段等同于 `group` + `project` 的操作。 声明: `count(string)` ### 2. 输入参数 | 参数 | 类型 | 必填 | 说明 | | ---- | --------------------------- | ---- | --------------------------------------------------------------------------------------- | | - | [expression](../expression) | 是 | `string` 是输出记录数的字段的名字,不能是空字符串,不能以 `$` 开头,不能包含 `.` 字符。 | ### 3. 返回结果 | 参数 | 类型 | 必填 | 说明 | | ---- | ---------------- | ---- | -------- | | - | [Aggregate](../) | 是 | 聚合对象 | ### 4. 示例代码 假设集合 `items` 有如下记录: ``` { _id: "1", price: 10.5 } { _id: "2", price: 50.3 } { _id: "3", price: 20.8 } { _id: "4", price: 80.2 } { _id: "5", price: 200.3 } ``` 找出加个大于 50 的记录数: ```js const tcb = require("@cloudbase/node-sdk"); const app = tcb.init({ env: "xxx", }); const db = app.database(); const $ = db.command.aggregate; const _ = db.command; exports.main = async (event, context) => { const res = await db .collection("items") .aggregate() .match({ price: _.gt(50), }) .count("expensiveCount") .end(); console.log(res.data); }; ``` 返回结果如下: ``` { "expensiveCount": 3 } ``` --- ## Aggregate.end # Aggregate.end ### 1. 接口描述 功能: 标志聚合操作定义完成,发起实际聚合操作 声明: `end()` ### 2. 输入参数 无 ### 3. 返回结果 | 参数 | 类型 | 必填 | 说明 | | ---- | ----------------- | ---- | ------------ | | data | Array.<any> | 是 | 聚合结果列表 | ### 4. 示例代码 ```js const tcb = require('@cloudbase/node-sdk') const app = tcb.init({ env: 'xxx' }) const db = app.database() const $ = db.command.aggregate exports.main = async (event, context) => { const res = await db .collection('books') .aggregate() .group({ // 按 category 字段分组 _id: '$category', // 让输出的每组记录有一个 avgSales 字段,其值是组内所有记录的 sales 字段的平均值 avgSales: $.avg('$sales') }) .end() console.log(res.data) } ``` --- ## Aggregate.geoNear # Aggregate.geoNear ### 1. 接口描述 功能: 将记录按照离给定点从近到远输出。 声明: `geoNear(options)` 注意事项: > `geoNear` 必须为第一个聚合阶段 > 必须有地理位置索引。如果有多个,必须用 `key` 参数指定要使用的索引。 ### 2. 输入参数 | 参数 | 类型 | 必填 | 说明 | | ------------------ | ------------- | ---- | ---------------------------------------------------------------------------------------------- | | near | GeoJSON Point | 否 | 用于判断距离的点 | | spherical | boolean | 是 | 必填,值为 true | | limit | number | 是 | 限制返回记录数 | | maxDistance | number | 是 | 距离最大值 | | minDistance | number | 是 | 距离最小值 | | query | document | 是 | 要求记录必须同时满足该条件(语法同 where) | | distanceMultiplier | number | 是 | 返回时在距离上乘以该数字 | | distanceField | string | 否 | 存放距离的输出字段名,可以用点表示法表示一个嵌套字段 | | includeLocs | string | 是 | 列出要用于距离计算的字段,如果记录中有多个字段都是地理位置时有用 | | key | string | 是 | 选择要用的地理位置索引。如果集合由多个地理位置索引,则必须指定一个,指定的方式是指定对应的字段 | ### 3. 返回结果 | 参数 | 类型 | 必填 | 说明 | | ---- | ---------------- | ---- | -------- | | - | [Aggregate](../) | 是 | 聚合对象 | ### 4. 示例代码 假设集合 `attractions` 有如下记录: ``` { "_id": "geoNear.0", "city": "Guangzhou", "docType": "geoNear", "location": { "type": "Point", "coordinates": [ 113.30593, 23.1361155 ] }, "name": "Canton Tower" }, { "_id": "geoNear.1", "city": "Guangzhou", "docType": "geoNear", "location": { "type": "Point", "coordinates": [ 113.306789, 23.1564721 ] }, "name": "Baiyun Mountain" }, { "_id": "geoNear.2", "city": "Beijing", "docType": "geoNear", "location": { "type": "Point", "coordinates": [ 116.3949659, 39.9163447 ] }, "name": "The Palace Museum" }, { "_id": "geoNear.3", "city": "Beijing", "docType": "geoNear", "location": { "type": "Point", "coordinates": [ 116.2328567, 40.242373 ] }, "name": "Great Wall" } ``` ```js const tcb = require("@cloudbase/node-sdk"); const app = tcb.init({ env: "xxx", }); const db = app.database(); const $ = db.command.aggregate; const _ = db.command; exports.main = async (event, context) => { const res = await db .collection("attractions") .aggregate() .geoNear({ distanceField: "distance", // 输出的每个记录中 distance 即是与给定点的距离 spherical: true, near: db.Geo.Point(113.3089506, 23.0968251), query: { docType: "geoNear", }, key: "location", // 若只有 location 一个地理位置索引的字段,则不需填 includeLocs: "location", // 若只有 location 一个是地理位置,则不需填 }) .end(); console.log(res.data); }; ``` 返回结果如下: ``` { "_id": "geoNear.0", "location": { "type": "Point", "coordinates": [ 113.30593, 23.1361155 ] }, "docType": "geoNear", "name": "Canton Tower", "city": "Guangzhou", "distance": 4384.68131486958 }, { "_id": "geoNear.1", "city": "Guangzhou", "location": { "type": "Point", "coordinates": [ 113.306789, 23.1564721 ] }, "docType": "geoNear", "name": "Baiyun Mountain", "distance": 6643.521654040738 }, { "_id": "geoNear.2", "docType": "geoNear", "name": "The Palace Museum", "city": "Beijing", "location": { "coordinates": [ 116.3949659, 39.9163447 ], "type": "Point" }, "distance": 1894750.4414538583 }, { "_id": "geoNear.3", "docType": "geoNear", "name": "Great Wall", "city": "Beijing", "location": { "type": "Point", "coordinates": [ 116.2328567, 40.242373 ] }, "distance": 1928300.3308822548 } ``` --- ## Aggregate.group # Aggregate.group ### 1. 接口描述 功能: 将输入记录按给定表达式分组,输出时每个记录代表一个分组,每个记录的 `_id` 是区分不同组的 key。输出记录中也可以包括累计值,将输出字段设为累计值即会从该分组中计算累计值。 声明: `group({ _id: , : , ... : })` ### 2. 输入参数 | 参数 | 类型 | 必填 | 说明 | | ------ | ------------------------------ | ---- | -------------------------------------------------------------------------------------- | | \_id | [expression](../expression) | 是 | 是用于区分不同组的 key | | fieldN | [expression](../expression.md) | 否 | fieldN 这些其他字段是可选的,都是累计值,用 `$.sum` 等累计器,但也可以使用其他表达式。 | 累计器必须是以下操作符之一: - addToSet - avg - first - last - max - min - push - stdDevPop - stdDevSamp - sum #### 内存限制 该阶段有 100M 内存使用限制。 ### 3. 返回结果 | 参数 | 类型 | 必填 | 说明 | | ---- | ---------------- | ---- | -------- | | - | [Aggregate](../) | 是 | 聚合对象 | ### 4. 示例代码 #### 按字段值分组 假设集合 `avatar` 有如下记录: ``` { _id: "1", alias: "john", region: "asia", scores: [40, 20, 80], coins: 100 } { _id: "2", alias: "arthur", region: "europe", scores: [60, 90], coins: 20 } { _id: "3", alias: "george", region: "europe", scores: [50, 70, 90], coins: 50 } { _id: "4", alias: "john", region: "asia", scores: [30, 60, 100, 90], coins: 40 } { _id: "5", alias: "george", region: "europe", scores: [20], coins: 60 } { _id: "6", alias: "john", region: "asia", scores: [40, 80, 70], coins: 120 } ``` ```js const tcb = require("@cloudbase/node-sdk"); const app = tcb.init({ env: "xxx", }); const db = app.database(); const $ = db.command.aggregate; const _ = db.command; exports.main = async (event, context) => { const res = await db .collection("avatar") .aggregate() .group({ _id: "$alias", num: $.sum(1), }) .end(); console.log(res.data); }; ``` 返回结果如下: ``` { "_id": "john", "num": 3 } { "_id": "authur", "num": 1 } { "_id": "george", "num": 2 } ``` #### 按多个值分组 可以给 `_id` 传入记录的方式按多个值分组。还是沿用上面的示例数据,按各个区域(region)获得相同最高分(score)的来分组,并求出各组虚拟币(coins)的总量: ```js const tcb = require("@cloudbase/node-sdk"); const app = tcb.init({ env: "xxx", }); const db = app.database(); const $ = db.command.aggregate; const _ = db.command; exports.main = async (event, context) => { const res = await db .collection("avatar") .aggregate() .group({ _id: { region: "$region", maxScore: $.max("$scores"), }, totalCoins: $.sum("$coins"), }) .end(); console.log(res.data); }; ``` 返回结果如下: ``` { "_id": { "region": "asia", "maxScore": 80 }, "totalCoins": 220 } { "_id": { "region": "asia", "maxScore": 100 }, "totalCoins": 100 } { "_id": { "region": "europe", "maxScore": 90 }, "totalCoins": 70 } { "_id": { "region": "europe", "maxScore": 20 }, "totalCoins": 60 } ``` --- ## Aggregate.limit # Aggregate.limit ### 1. 接口描述 功能: 聚合阶段。限制输出到下一阶段的记录数。 声明: `limit(number)` ### 2. 输入参数 | 参数 | 类型 | 必填 | 说明 | | ---- | ------ | ---- | ------ | | - | number | 是 | 正整数 | ### 3. 返回结果 | 参数 | 类型 | 必填 | 说明 | | ---- | ---------------- | ---- | -------- | | - | [Aggregate](../) | 是 | 聚合对象 | ### 4. 示例代码 假设集合 `items` 有如下记录: ``` { _id: "1", price: 10 } { _id: "2", price: 50 } { _id: "3", price: 20 } { _id: "4", price: 80 } { _id: "5", price: 200 } ``` 返回加个大于 20 的记录的最小的两个记录: ```js const tcb = require("@cloudbase/node-sdk"); const app = tcb.init({ env: "xxx", }); const db = app.database(); const $ = db.command.aggregate; const _ = db.command; exports.main = async (event, context) => { const res = await db .collection("items") .aggregate() .match({ price: _.gt(20), }) .sort({ price: 1, }) .limit(2) .end(); console.log(res.data); }; ``` 返回结果如下: ``` { "_id": "3", "price": 20 } { "_id": "4", "price": 80 } ``` --- ## Aggregate.lookup # Aggregate.lookup ### 1. 接口描述 功能: 聚合阶段。联表查询。与同个数据库下的一个指定的集合做 left outer join(左外连接)。对该阶段的每一个输入记录,lookup 会在该记录中增加一个数组字段,该数组是被联表中满足匹配条件的记录列表。lookup 会将连接后的结果输出给下个阶段。 声明: `limit(object)` 两种形式 1. 相等匹配 将输入记录的一个字段和被连接集合的一个字段进行相等匹配时,采用以下定义: ``` lookup({ from: , localField: , foreignField: , as: }) ``` 2. 自定义连接条件、拼接子查询 如果需要指定除相等匹配之外的连接条件,或指定多个相等匹配条件,或需要拼接被连接集合的子查询结果,那可以使用如下定义: ``` lookup({ from: , let: { : , ..., : }, pipeline: [ ], as: }) ``` ### 2. 输入参数 1. 相等匹配 | 参数 | 类型 | 必填 | 说明 | | ------------ | ------ | ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | | from | string | 是 | 要进行连接的另外一个集合的名字 | | localField | string | 是 | 当前流水线的输入记录的字段名,该字段将被用于与 from 指定的集合的 foreignField 进行相等匹配。如果输入记录中没有该字段,则该字段的值在匹配时会被视作 null | | foreignField | string | 是 | 被连接集合的字段名,该字段会被用于与 localField 进行相等匹配。如果被连接集合的记录中没有该字段,该字段的值将在匹配时被视作 null | | as | string | 是 | 指定连接匹配出的记录列表要存放的字段名,这个数组包含的是匹配出的来自 from 集合的记录。如果输入记录中本来就已有该字段,则该字段会被覆写 | | | - 操作等价于以下伪 SQL 操作: ```SQL SELECT *, FROM collection WHERE IN (SELECT * FROM WHERE = ); ``` 2. 自定义连接条件、拼接子查询 | 参数 | 类型 | 必填 | 说明 | | -------- | ------ | ---- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | from | string | 是 | 要进行连接的另外一个集合的名字 | | let | string | 否 | 指定在 pipeline 中可以使用的变量,变量的值可以引用输入记录的字段,比如 let: { userName: '$name' } 就代表将输入记录的 name 字段作为变量 userName 的值。在 pipeline 中无法直接访问输入记录的字段,必须通过 let 定义之后才能访问,访问的方式是在 expr 操作符中用 $$变量名 的方式访问,比如 $\$userName。 | | pipeline | any | 是 | 指定要在被连接集合中运行的聚合操作。如果要返回整个集合,则该字段取值空数组 []。在 pipeline 中无法直接访问输入记录的字段,必须通过 let 定义之后才能访问,访问的方式是在 expr 操作符中用 $$变量名 的方式访问,比如 $$userName。 | | as | string | 是 | 指定连接匹配出的记录列表要存放的字段名,这个数组包含的是匹配出的来自 from 集合的记录。如果输入记录中本来就已有该字段,则该字段会被覆写 | | | - 操作等价于以下伪 SQL 操作: ```SQL SELECT *, FROM collection WHERE IN (SELECT FROM WHERE ); ``` ### 3. 返回结果 | 参数 | 类型 | 必填 | 说明 | | ---- | ---------------- | ---- | -------- | | - | [Aggregate](../) | 是 | 聚合对象 | ### 4. 示例代码 #### 指定一个相等匹配条件 假设 orders 集合有以下记录: ``` [ {"_id":4,"book":"novel 1","price":30,"quantity":2}, {"_id":5,"book":"science 1","price":20,"quantity":1}, {"_id":6} ] ``` books 集合有以下记录: ``` [ {"_id":"book1","author":"author 1","category":"novel","stock":10,"time":1564456048486,"title":"novel 1"}, {"_id":"book3","author":"author 3","category":"science","stock":30,"title":"science 1"}, {"_id":"book4","author":"author 3","category":"science","stock":40,"title":"science 2"}, {"_id":"book2","author":"author 2","category":"novel","stock":20,"title":"novel 2"}, {"_id":"book5","author":"author 4","category":"science","stock":50,"title":null}, {"_id":"book6","author":"author 5","category":"novel","stock":"60"} ] ``` 以下聚合操作可以通过一个相等匹配条件连接 orders 和 books 集合,匹配的字段是 orders 集合的 book 字段和 books 集合的 title 字段: ```js const tcb = require("@cloudbase/node-sdk"); const app = tcb.init({ env: "xxx", }); const db = app.database(); const $ = db.command.aggregate; const _ = db.command; exports.main = async (event, context) => { const res = await db .collection("orders") .aggregate() .lookup({ from: "books", localField: "book", foreignField: "title", as: "bookList", }) .end(); console.log(res.data); }; ``` 结果: ``` [ { "_id": 4, "book": "novel 1", "price": 30, "quantity": 2, "bookList": [ { "_id": "book1", "title": "novel 1", "author": "author 1", "category": "novel", "stock": 10 } ] }, { "_id": 5, "book": "science 1", "price": 20, "quantity": 1, "bookList": [ { "_id": "book3", "category": "science", "title": "science 1", "author": "author 3", "stock": 30 } ] }, { "_id": 6, "bookList": [ { "_id": "book5", "category": "science", "author": "author 4", "stock": 50, "title": null }, { "_id": "book6", "author": "author 5", "stock": "60", "category": "novel" } ] } ] ``` #### 对数组字段应用相等匹配 假设 authors 集合有以下记录: ``` [ {"_id": 1, "name": "author 1", "intro": "Two-time best-selling sci-fiction novelist"}, {"_id": 3, "name": "author 3", "intro": "UCB assistant professor"}, {"_id": 4, "name": "author 4", "intro": "major in CS"} ] ``` books 集合有以下记录: ``` [ {"_id":"book1","authors":["author 1"],"category":"novel","stock":10,"time":1564456048486,"title":"novel 1"}, {"_id":"book3","authors":["author 3", "author 4"],"category":"science","stock":30,"title":"science 1"}, {"_id":"book4","authors":["author 3"],"category":"science","stock":40,"title":"science 2"} ] ``` 以下操作获取作者信息及他们分别发表的书籍,使用了 lookup 操作匹配 authors 集合的 name 字段和 books 集合的 authors 数组字段: ```js const tcb = require("@cloudbase/node-sdk"); const app = tcb.init({ env: "xxx", }); const db = app.database(); const $ = db.command.aggregate; const _ = db.command; exports.main = async (event, context) => { const res = await db .collection("authors") .aggregate() .lookup({ from: "books", localField: "name", foreignField: "authors", as: "publishedBooks", }) .end(); console.log(res.data); }; ``` 结果 ``` [ { "_id": 1, "intro": "Two-time best-selling sci-fiction novelist", "name": "author 1", "publishedBooks": [ { "_id": "book1", "title": "novel 1", "category": "novel", "stock": 10, "authors": [ "author 1" ] } ] }, { "_id": 3, "name": "author 3", "intro": "UCB assistant professor", "publishedBooks": [ { "_id": "book3", "category": "science", "title": "science 1", "stock": 30, "authors": [ "author 3", "author 4" ] }, { "_id": "book4", "title": "science 2", "category": "science", "stock": 40, "authors": [ "author 3" ] } ] }, { "_id": 4, "intro": "major in CS", "name": "author 4", "publishedBooks": [ { "_id": "book3", "category": "science", "title": "science 1", "stock": 30, "authors": [ "author 3", "author 4" ] } ] } ] ``` #### 组合 mergeObjects 应用相等匹配 假设 orders 集合有以下记录: ``` [ {"_id":4,"book":"novel 1","price":30,"quantity":2}, {"_id":5,"book":"science 1","price":20,"quantity":1}, {"_id":6} ] ``` books 集合有以下记录: ``` [ {"_id":"book1","author":"author 1","category":"novel","stock":10,"time":1564456048486,"title":"novel 1"}, {"_id":"book3","author":"author 3","category":"science","stock":30,"title":"science 1"}, {"_id":"book4","author":"author 3","category":"science","stock":40,"title":"science 2"}, {"_id":"book2","author":"author 2","category":"novel","stock":20,"title":"novel 2"}, {"_id":"book5","author":"author 4","category":"science","stock":50,"title":null}, {"_id":"book6","author":"author 5","category":"novel","stock":"60"} ] ``` 以下操作匹配 orders 的 book 字段和 books 的 title 字段,并将 books 匹配结果直接 merge 到 orders 记录中。 ```js const tcb = require("@cloudbase/node-sdk"); const app = tcb.init({ env: "xxx", }); const db = app.database(); const $ = db.command.aggregate; const _ = db.command; exports.main = async (event, context) => { const res = await db .collection("orders") .aggregate() .lookup({ from: "books", localField: "book", foreignField: "title", as: "bookList", }) .replaceRoot({ newRoot: $.mergeObjects([$.arrayElemAt(["$bookList", 0]), "$$ROOT"]), }) .project({ bookList: 0, }) .end(); console.log(res.data); }; ``` 结果 ``` [ { "_id": 4, "title": "novel 1", "author": "author 1", "category": "novel", "stock": 10, "book": "novel 1", "price": 30, "quantity": 2 }, { "_id": 5, "category": "science", "title": "science 1", "author": "author 3", "stock": 30, "book": "science 1", "price": 20, "quantity": 1 }, { "_id": 6, "category": "science", "author": "author 4", "stock": 50, "title": null } ] ``` #### 指定多个连接条件 假设 orders 集合有以下记录: ``` [ {"_id":4,"book":"novel 1","price":300,"quantity":20}, {"_id":5,"book":"science 1","price":20,"quantity":1} ] ``` books 集合有以下记录: ``` [ {"_id":"book1","author":"author 1","category":"novel","stock":10,"time":1564456048486,"title":"novel 1"}, {"_id":"book3","author":"author 3","category":"science","stock":30,"title":"science 1"} ] ``` 以下操作连接 orders 和 books 集合,要求两个条件: orders 的 book 字段与 books 的 title 字段相等 orders 的 quantity 字段大于或等于 books 的 stock 字段 ```js const tcb = require("@cloudbase/node-sdk"); const app = tcb.init({ env: "xxx", }); const db = app.database(); const $ = db.command.aggregate; const _ = db.command; exports.main = async (event, context) => { const res = await db .collection("orders") .aggregate() .lookup({ from: "books", let: { order_book: "$book", order_quantity: "$quantity", }, pipeline: $.pipeline() .match( _.expr( $.and([ $.eq(["$title", "$$order_book"]), $.gte(["$stock", "$$order_quantity"]), ]) ) ) .project({ _id: 0, title: 1, author: 1, stock: 1, }) .done(), as: "bookList", }) .end(); console.log(res.data); }; ``` 结果: [ { "\_id": 4, "book": "novel 1", "price": 300, "quantity": 20, "bookList": [] }, { "\_id": 5, "book": "science 1", "price": 20, "quantity": 1, "bookList": [ { "title": "science 1", "author": "author 3", "stock": 30 } ] } ] #### 拼接被连接集合的子查询 假设 orders 集合有以下记录: ``` [ {"_id":4,"book":"novel 1","price":30,"quantity":2}, {"_id":5,"book":"science 1","price":20,"quantity":1} ] ``` books 集合有以下记录: ``` [ {"_id":"book1","author":"author 1","category":"novel","stock":10,"time":1564456048486,"title":"novel 1"}, {"_id":"book3","author":"author 3","category":"science","stock":30,"title":"science 1"}, {"_id":"book4","author":"author 3","category":"science","stock":40,"title":"science 2"} ] ``` 在每条输出记录上加上一个数组字段,该数组字段的值是对 books 集合的一个查询语句的结果: ```js const tcb = require("@cloudbase/node-sdk"); const app = tcb.init({ env: "xxx", }); const db = app.database(); const $ = db.command.aggregate; const _ = db.command; exports.main = async (event, context) => { const res = await db .collection("orders") .aggregate() .lookup({ from: "books", let: { order_book: "$book", order_quantity: "$quantity", }, pipeline: $.pipeline() .match({ author: "author 3", }) .project({ _id: 0, title: 1, author: 1, stock: 1, }) .done(), as: "bookList", }) .end(); console.log(res.data); }; ``` 结果 ``` [ { "_id": 4, "book": "novel 1", "price": 30, "quantity": 20, "bookList": [ { "title": "science 1", "author": "author 3", "stock": 30 }, { "title": "science 2", "author": "author 3", "stock": 40 } ] }, { "_id": 5, "book": "science 1", "price": 20, "quantity": 1, "bookList": [ { "title": "science 1", "author": "author 3", "stock": 30 }, { "title": "science 2", "author": "author 3", "stock": 40 } ] } ] ``` --- ## Aggregate.match # Aggregate.match ### 1. 接口描述 功能: 聚合阶段。根据条件过滤文档,并且把符合条件的文档传递给下一个流水线阶段。 声明: `match({ : })` ### 2. 输入参数 | 参数 | 类型 | 必填 | 说明 | | ---- | --------------------------- | ---- | ------------------------------------------------------------------------------------------------------------ | | key | [expression](../expression) | 是 | key 为任意自定义字段名,其值表达式可以直接使用 `number`、`string` 这样的原生类型,也可以使用聚合搜索操作符: | ### 3. 返回结果 | 参数 | 类型 | 必填 | 说明 | | ---- | ---------------- | ---- | -------- | | - | [Aggregate](../) | 是 | 聚合对象 | ### 4. 示例代码 假设集合 `articles` 有如下记录: ```json { "_id" : "1", "author" : "stark", "score" : 80 } { "_id" : "2", "author" : "stark", "score" : 85 } { "_id" : "3", "author" : "bob", "score" : 60 } { "_id" : "4", "author" : "li", "score" : 55 } { "_id" : "5", "author" : "jimmy", "score" : 60 } { "_id" : "6", "author" : "li", "score" : 94 } { "_id" : "7", "author" : "justan", "score" : 95 } ``` #### 匹配 下面是一个直接匹配的例子: ```js const tcb = require("@cloudbase/node-sdk"); const app = tcb.init({ env: "xxx", }); const db = app.database(); const $ = db.command.aggregate; const _ = db.command; exports.main = async (event, context) => { const res = await db .collection("articles") .aggregate() .match({ author: "stark", }) .end(); console.log(res.data); }; ``` 这里的代码尝试找到所有 `author` 字段是 `stark` 的文章,那么匹配如下: ```json { "_id" : "1", "author" : "stark", "score" : 80 } { "_id" : "2", "author" : "stark", "score" : 85 } ``` #### 计数 `match` 过滤出文档后,还可以与其他流水线阶段配合使用。 比如下面这个例子,我们使用 `group` 进行搭配,计算 `score` 字段大于 `80` 的文档数量: ```js const tcb = require("@cloudbase/node-sdk"); const app = tcb.init({ env: "xxx", }); const db = app.database(); const { gt, sum } = db.command.aggregate; exports.main = async (event, context) => { const res = await db .collection("articles") .aggregate() .match({ score: gt(80), }) .group({ _id: null, count: sum(1), }) .end(); console.log(res.data); }; ``` 返回值如下: ```json { "_id": null, "count": 3 } ``` --- ## Aggregate.project # Aggregate.project ### 1. 接口描述 功能: 聚合阶段。把指定的字段传递给下一个流水线,指定的字段可以是某个已经存在的字段,也可以是计算出来的新字段。 声明: `project({ : })` ### 2. 输入参数 字段表达式可以有以下格式: | 格式 | 说明 | | ------------------------ | --------------------------------------------------------------------------------------------------- | | : | 指定包含某个已有字段 | | \_id: | 舍弃 \_id 字段 | | : | 加入一个新字段,或者重置某个已有字段 | | : | 舍弃某个字段(_如果您指定舍弃了某个非 \_id 字段,那么在此次 `project` 中,您不能再使用其它表达式_) | ### 说明 #### 指定包含字段 - `_id` 字段是默认包含在输出中的,除此之外其他任何字段,如果想要在输出中体现的话,必须在 `project` 中指定; - 如果指定包含一个尚不存在的字段,那么 `project` 会忽略这个字段,不会加入到输出的文档中; #### 指定排除字段 - 如果您在 `project` 中指定排除某个字段,那么其它字段都会体现在输出中; - 如果指定排除的是非 `_id` 字段,那么在本次 `project` 中,不能再使用其它表达式; #### 加入新的字段或重置某个已有字段 您可以使用一些特殊的表达式加入新的字段,或重置某个已有字段。 #### 多层嵌套的字段 有时有些字段处于多层嵌套的底层,我们可以使用**点记法**: ```js "contact.phone.number": ``` 也可以直接使用嵌套的格式: ```js contact: { phone: { number: } } ``` ### 3. 返回结果 | 参数 | 类型 | 必填 | 说明 | | ---- | ---------------- | ---- | -------- | | - | [Aggregate](../) | 是 | 聚合对象 | ### 4. 示例代码 假设我们有一个 `articles` 集合,其中含有以下文档: ```json { "_id": 666, "title": "This is title", "author": "Nobody", "isbn": "123456789", "introduction": "......" } ``` #### 指定包含某些字段 下面的代码使用 `project`,让输出只包含 `_id`、`title` 和 `author` 字段: ```js const tcb = require("@cloudbase/node-sdk"); const app = tcb.init({ env: "xxx", }); const db = app.database(); const { gt, sum } = db.command.aggregate; exports.main = async (event, context) => { const res = await db .collection("articles") .aggregate() .project({ title: 1, author: 1, }) .end(); console.log(res.data); }; ``` 输出如下: ```js { "_id" : 666, "title" : "This is title", "author" : "Nobody" } ``` #### 去除输出中的 \_id 字段 `_id` 是默认包含在输出中的,如果不想要它,可以指定去除它: ```js const tcb = require("@cloudbase/node-sdk"); const app = tcb.init({ env: "xxx", }); const db = app.database(); const { gt, sum } = db.command.aggregate; exports.main = async (event, context) => { const res = await db .collection("articles") .aggregate() .project({ _id: 0, // 指定去除 _id 字段 title: 1, author: 1, }) .end(); console.log(res.data); }; ``` 输出如下: ```js { "title" : "This is title", "author" : "Nobody" } ``` #### 去除某个非 \_id 字段 我们还可以指定在输出中去掉某个非 `_id` 字段,这样其它字段都会被输出: ```js const tcb = require("@cloudbase/node-sdk"); const app = tcb.init({ env: "xxx", }); const db = app.database(); const { gt, sum } = db.command.aggregate; exports.main = async (event, context) => { const res = await db .collection("articles") .aggregate() .project({ isbn: 0, // 指定去除 isbn 字段 }) .end(); console.log(res.data); }; ``` 输出如下,相比输入,没有了 `isbn` 字段: ```json { "_id": 666, "title": "This is title", "author": "Nobody", "introduction": "......" } ``` #### 加入计算出的新字段 假设我们有一个 `students` 集合,其中包含以下文档: ```json { "_id": 1, "name": "小明", "scores": { "chinese": 80, "math": 90, "english": 70 } } ``` 下面的代码,我们使用 `project`,在输出中加入了一个新的字段 `totalScore`: ```js const tcb = require("@cloudbase/node-sdk"); const app = tcb.init({ env: "xxx", }); const db = app.database(); const { gt, sum } = db.command.aggregate; exports.main = async (event, context) => { const res = await db .collection("students") .aggregate() .project({ _id: 0, name: 1, totalScore: sum(["$scores.chinese", "$scores.math", "$scores.english"]), }) .end(); console.log(res.data); }; ``` 输出为: ```json { "name": "小明", "totalScore": 240 } ``` #### 加入新的数组字段 假设我们有一个 `points` 集合,包含以下文档: ```json { "_id": 1, "x": 1, "y": 1 } { "_id": 2, "x": 2, "y": 2 } { "_id": 3, "x": 3, "y": 3 } ``` 下面的代码,我们使用 `project`,把 `x` 和 `y` 字段,放入到一个新的数组字段 `coordinate` 中: ```js const tcb = require("@cloudbase/node-sdk"); const app = tcb.init({ env: "xxx", }); const db = app.database(); const { gt, sum } = db.command.aggregate; exports.main = async (event, context) => { const res = await db .collection("points") .aggregate() .project({ coordinate: ["$x", "$y"], }) .end(); console.log(res.data); }; ``` 输出如下: ```json { "_id": 1, "coordinate": [1, 1] } { "_id": 2, "coordinate": [2, 2] } { "_id": 3, "coordinate": [3, 3] } ``` --- ## Aggregate.replaceRoot # Aggregate.replaceRoot ### 1. 接口描述 功能: 聚合阶段。指定一个已有字段作为输出的根节点,也可以指定一个计算出的新字段作为根节点。 声明: `replaceRoot({ newRoot: })` ### 2. 输入参数 | 参数 | 类型 | 必填 | 说明 | | ------- | -------------------------- | ---- | ---------------- | | newRoot | [Aggregate](../) or Object | 是 | 两种格式详述如下 | 表达式格式如下: | 格式 | 说明 | | -------- | ---------------------------------------------------------- | | | 指定一个已有字段作为输出的根节点(_如果字段不存在则报错_) | | | 计算一个新字段,并且把这个新字段作为根节点 | ### 3. 返回结果 | 参数 | 类型 | 必填 | 说明 | | ---- | ---------------- | ---- | -------- | | - | [Aggregate](../) | 是 | 聚合对象 | ### 4. 示例代码 #### 使用已有字段作为根节点 假设我们有一个 `schools` 集合,内容如下: ```json { "_id": 1, "name": "SFLS", "teachers": { "chinese": 22, "math": 18, "english": 21, "other": 123 } } ``` 下面的代码使用 `replaceRoot`,把 `teachers` 字段作为根节点输出: ```js const tcb = require("@cloudbase/node-sdk"); const app = tcb.init({ env: "xxx", }); const db = app.database(); const { gt, sum } = db.command.aggregate; exports.main = async (event, context) => { const res = await db .collection("schools") .aggregate() .replaceRoot({ newRoot: "$teachers", }) .end(); console.log(res.data); }; ``` 输出如下: ```json { "chinese": 22, "math": 18, "english": 21, "other": 123 } ``` #### 使用计算出的新字段作为根节点 假设我们有一个 `roles` 集合,内容如下: ```json { "_id": 1, "first_name": "四郎", "last_name": "黄" } { "_id": 2, "first_name": "邦德", "last_name": "马" } { "_id": 3, "first_name": "牧之", "last_name": "张" } ``` 下面的代码使用 `replaceRoot`,把 `first_name` 和 `last_name` 拼在一起: ```js const tcb = require("@cloudbase/node-sdk"); const app = tcb.init({ env: "xxx", }); const db = app.database(); const { gt, sum, concat } = db.command.aggregate; exports.main = async (event, context) => { const res = await db .collection("roles") .aggregate() .replaceRoot({ newRoot: { full_name: concat(["$last_name", "$first_name"]), }, }) .end(); console.log(res.data); }; ``` 输出如下: ```json { "full_name": "黄四郎" } { "full_name": "马邦德" } { "full_name": "张牧之" } ``` --- ## Aggregate.sample # Aggregate.sample ### 1. 接口描述 功能: 聚合阶段。随机从文档中选取指定数量的记录。 声明: `sample({ size: })` ### 2. 输入参数 | 参数 | 类型 | 必填 | 说明 | | ---- | ------ | ---- | ----------------------------- | | size | number | 是 | `size` 是正整数,否则会出错。 | ### 3. 返回结果 | 参数 | 类型 | 必填 | 说明 | | ---- | ---------------- | ---- | -------- | | - | [Aggregate](../) | 是 | 聚合对象 | ### 4. 示例代码 假设文档 `users` 有以下记录: ``` { "name": "a" } { "name": "b" } ``` #### 随机选取 如果现在进行抽奖活动,需要选出一名幸运用户。那么 `sample` 的调用方式如下: ```javascript const tcb = require("@cloudbase/node-sdk"); const app = tcb.init({ env: "xxx", }); const db = app.database(); const { gt, sum, concat } = db.command.aggregate; exports.main = async (event, context) => { const res = await db .collection("users") .aggregate() .sample({ size: 1, }) .end(); console.log(res.data); }; ``` 返回了随机选中的一个用户对应的记录,结果如下: ``` { "_id": "696529e4-7e82-4e7f-812e-5144714edff6", "name": "b" } ``` --- ## Aggregate.skip # Aggregate.skip ### 1. 接口描述 功能: 聚合阶段。指定一个正整数,跳过对应数量的文档,输出剩下的文档。 声明: `skip()` ### 2. 输入参数 | 参数 | 类型 | 必填 | 说明 | | ---- | ------ | ---- | -------------------- | | - | number | 是 | 正整数,否则会出错。 | ### 3. 返回结果 | 参数 | 类型 | 必填 | 说明 | | ---- | ---------------- | ---- | -------- | | - | [Aggregate](../) | 是 | 聚合对象 | ### 4. 示例代码 ```javascript const tcb = require("@cloudbase/node-sdk"); const app = tcb.init({ env: "xxx", }); const db = app.database(); const { gt, sum, concat } = db.command.aggregate; exports.main = async (event, context) => { const res = await db.collection("users").aggregate().skip(5).end(); console.log(res.data); }; ``` 这段代码会跳过查找到的**前 5 个**文档,并且把剩余的文档输出。 --- ## Aggregate.sort # Aggregate.sort ### 1. 接口描述 功能: 聚合阶段。`sort` 根据指定的字段,对输入的文档进行排序。 声明: `sort({ key1: sortRule1, key2: sortRule2, })` ### 2. 输入参数 | 参数 | 类型 | 必填 | 说明 | | ---- | ------ | ---- | ------------------------------------------------------------------------ | | key | number | 是 | 值为排序规则,`1` 代表升序排列(从小到大), `-1` 代表降序排列(从大到小) | ### 3. 返回结果 | 参数 | 类型 | 必填 | 说明 | | ---- | ---------------- | ---- | -------- | | - | [Aggregate](../) | 是 | 聚合对象 | ### 4. 示例代码 #### 升序/降序排列 假设我们有集合 `articles`,其中包含数据如下: ```json { "_id": "1", "author": "stark", "score": 80, "age": 18 } { "_id": "2", "author": "bob", "score": 60, "age": 18 } { "_id": "3", "author": "li", "score": 55, "age": 19 } { "_id": "4", "author": "jimmy", "score": 60, "age": 22 } { "_id": "5", "author": "justan", "score": 95, "age": 33 } ``` ```js const tcb = require("@cloudbase/node-sdk"); const app = tcb.init({ env: "xxx", }); const db = app.database(); const { gt, sum, concat } = db.command.aggregate; exports.main = async (event, context) => { const res = await db .collection("articles") .aggregate() .sort({ age: -1, score: -1, }) .end(); console.log(res.data); }; ``` 上面的代码在 `students` 集合中进行聚合搜索,并且将结果排序,首先根据 `age` 字段降序排列,然后再根据 `score` 字段进行降序排列。 输出结果如下: ```json { "_id": "5", "author": "justan", "score": 95, "age": 33 } { "_id": "4", "author": "jimmy", "score": 60, "age": 22 } { "_id": "3", "author": "li", "score": 55, "age": 19 } { "_id": "1", "author": "stark", "score": 80, "age": 18 } { "_id": "2", "author": "bob", "score": 60, "age": 18 } ``` --- ## Aggregate.sortByCount # Aggregate.sortByCount ### 1. 接口描述 功能: 根据传入的表达式,将传入的集合进行分组(`group`)。然后计算不同组的数量,并且将这些组按照它们的数量进行排序,返回排序后的结果。 声明: `sortByCount()` ### 2. 输入参数 | 参数 | 类型 | 必填 | 说明 | | ---- | ---------------- | ---- | ----------------------------------------------------------- | | - | [Aggregate](../) | 是 | 表达式的形式是:`$ + 指定字段`。请注意:不要漏写 `$` 符号。 | ### 3. 返回结果 | 参数 | 类型 | 必填 | 说明 | | ---- | ---------------- | ---- | -------- | | - | [Aggregate](../) | 是 | 聚合对象 | ### 4. 示例代码 #### 统计基础类型 假设集合 `passages` 的记录如下: ``` { "category": "Web" } { "category": "Web" } { "category": "Life" } ``` 下面的代码就可以统计文章的分类信息,并且计算每个分类的数量。即对 `category` 字段执行 `sortByCount` 聚合操作。 ```javascript const tcb = require("@cloudbase/node-sdk"); const app = tcb.init({ env: "xxx", }); const db = app.database(); exports.main = async (event, context) => { const res = await db .collection("passages") .aggregate() .sortByCount("$category") .end(); console.log(res.data); }; ``` 返回的结果如下所示:`Web` 分类下有 2 篇文章,`Life` 分类下有 1 篇文章。 ``` { "_id": "Web", "count": 2 } { "_id": "Life", "count": 1 } ``` #### 解构数组类型 假设集合 `passages` 的记录如下:`tags` 字段对应的值是数组类型。 ``` { "tags": [ "JavaScript", "C#" ] } { "tags": [ "Go", "C#" ] } { "tags": [ "Go", "Python", "JavaScript" ] } ``` 如何统计文章的标签信息,并且计算每个标签的数量?因为 `tags` 字段对应的数组,所以需要借助 `unwind` 操作解构 `tags` 字段,然后再调用 `sortByCount`。 下面的代码实现了这个功能: ```javascript const tcb = require("@cloudbase/node-sdk"); const app = tcb.init({ env: "xxx", }); const db = app.database(); exports.main = async (event, context) => { const res = await db .collection("passages") .aggregate() .unwind(`$tags`) .sortByCount(`$tags`) .end(); console.log(res.data); }; ``` 返回的结果如下所示: ``` { "_id": "Go", "count": 2 } { "_id": "C#", "count": 2 } { "_id": "JavaScript", "count": 2 } { "_id": "Python", "count": 1 } ``` --- ## Aggregate.unwind # Aggregate.unwind ### 1. 接口描述 功能: 使用指定的数组字段中的每个元素,对文档进行拆分。拆分后,文档会从一个变为一个或多个,分别对应数组的每个元素。 声明: 两种形式 - 参数是一个字段名 `unwind()` - 参数是一个对象 `unwind({ path: , includeArrayIndex: , preserveNullAndEmptyArrays: })` ### 2. 输入参数 | 参数 | 类型 | 必填 | 说明 | | -------------------------- | ------- | ---- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | | path | string | 是 | 想要拆分的数组的字段名,需要以 `$` 开头。 | | includeArrayIndex | string | 否 | 可选项,传入一个新的字段名,数组索引会保存在这个新的字段上。新的字段名不能以 `$` 开头。 | | preserveNullAndEmptyArrays | boolean | 是 | 如果为 `true`,那么在 `path` 对应的字段为 `null`、空数组或者这个字段不存在时,依然会输出这个文档;如果为 `false`,`unwind` 将不会输出这些文档。默认为 `false`。 | ### 3. 返回结果 | 参数 | 类型 | 必填 | 说明 | | ---- | ---------------- | ---- | -------- | | - | [Aggregate](../) | 是 | 聚合对象 | ### 4. 示例代码 #### 拆分数组 假设我们有一个 `products` 集合,包含数据如下: ```json { "_id": "1", "product": "tshirt", "size": ["S", "M", "L"] } { "_id": "2", "product": "pants", "size": [] } { "_id": "3", "product": "socks", "size": null } { "_id": "4", "product": "trousers", "size": ["S"] } { "_id": "5", "product": "sweater", "size": ["M", "L"] } ``` 我们根据 `size` 字段对这些文档进行拆分 ```js const tcb = require("@cloudbase/node-sdk"); const app = tcb.init({ env: "xxx", }); const db = app.database(); exports.main = async (event, context) => { const res = await db.collection("products").aggregate().unwind("$size").end(); console.log(res.data); }; ``` 输出如下: ```json { "_id": "1", "product": "tshirt", "size": "S" } { "_id": "1", "product": "tshirt", "size": "M" } { "_id": "1", "product": "tshirt", "size": "L" } { "_id": "4", "product": "trousers", "size": "S" } { "_id": "5", "product": "sweater", "size": "M" } { "_id": "5", "product": "sweater", "size": "L" } ``` #### 拆分后,保留原数组的索引 我们根据 `size` 字段对文档进行拆分后,想要保留原数组索引在新的 `index` 字段中。 ```js const tcb = require("@cloudbase/node-sdk"); const app = tcb.init({ env: "xxx", }); const db = app.database(); exports.main = async (event, context) => { const res = await db .collection("products") .aggregate() .unwind({ path: "$size", includeArrayIndex: "index", }) .end(); console.log(res.data); }; ``` 输出如下: ```json { "_id": "1", "product": "tshirt", "size": "S", "index": 0 } { "_id": "1", "product": "tshirt", "size": "M", "index": 1 } { "_id": "1", "product": "tshirt", "size": "L", "index": 2 } { "_id": "4", "product": "trousers", "size": "S", "index": 0 } { "_id": "5", "product": "sweater", "size": "M", "index": 0 } { "_id": "5", "product": "sweater", "size": "L", "index": 1 } ``` #### 保留字段为空的文档 注意到我们的集合中有两行特殊的空值数据: ```json ... { "_id": "2", "product": "pants", "size": [] } { "_id": "3", "product": "socks", "size": null } ... ``` 如果想要在输出中保留 `size` 为空数组、null,或者 `size` 字段不存在的文档,可以使用 `preserveNullAndEmptyArrays` 参数 ```js const tcb = require("@cloudbase/node-sdk"); const app = tcb.init({ env: "xxx", }); const db = app.database(); exports.main = async (event, context) => { const res = await db .collection("products") .aggregate() .unwind({ path: "$size", preserveNullAndEmptyArrays: true, }) .end(); console.log(res.data); }; ``` 输出如下: ```json { "_id": "1", "product": "tshirt", "size": "S" } { "_id": "1", "product": "tshirt", "size": "M" } { "_id": "1", "product": "tshirt", "size": "L" } { "_id": "2", "product": "pants", "size": null } { "_id": "3", "product": "socks", "size": null } { "_id": "4", "product": "trousers", "size": "S" } { "_id": "5", "product": "sweater", "size": "M" } { "_id": "5", "product": "sweater", "size": "L" } ``` --- ## API # API ## 基础概念 ### Collection 集合是一系列的文档集,通过 `db.collection(name)` 可以获取指定集合的引用,在集合上可以进行以下操作 | 类型 | 接口 | 说明 | | -------- | ------- | ---------------------------------------------------------------------------------- | | 写 | add | 新增文档(触发请求) | | 计数 | count | 获取符合条件的文档条数 | | 读 | get | 获取集合中的文档,如果有使用 where 语句定义查询条件,则会返回匹配结果集 (触发请求) | | 引用 | doc | 获取对该集合中指定 id 的文档的引用 | | 查询条件 | where | 通过指定条件筛选出匹配的文档,可搭配查询指令(eq, gt, in, ...)使用 | | | skip | 跳过指定数量的文档,常用于分页,传入 offset | | | orderBy | 排序方式 | | | limit | 返回的结果集(文档数量)的限制,有默认值和上限值 | | | field | 指定需要返回的字段 | 查询及更新指令用于在 `where` 中指定字段需满足的条件,指令可通过 `db.command` 对象取得。 ### Record / Document 文档是数据库集合中的一个存储单元,在云开发里是一个 json 对象。通过 `db.collection(collectionName).doc(docId)` 可以获取指定集合上指定 id 的文档的引用,在文档上可以进行以下操作 | 接口 | 说明 | | ---- | ------ | ---------------------- | | 写 | set | 覆写文档 | | | update | 局部更新文档(触发请求) | | | remove | 删除文档(触发请求) | | 读 | get | 获取文档(触发请求) | ### Query Command 查询指令,应用于构建查询条件。以下指令皆挂载在 `db.command` 下 | 类型 | 接口 | 说明 | | -------- | ---- | ---------------------------------- | | 比较运算 | eq | 字段 == | | | neq | 字段 != | | | gt | 字段 > | | | gte | 字段 >= | | | lt | 字段 { // 创建集合名为 articles 的集合 await db.createCollection("articles"); const res = await db.collection("articles").add({ \_openid: "luke-111111" }); return { id: res.id }; }; ``` ### eq 表示字段等于某个值。`eq` 指令接受一个字面量 (literal),可以是 `number`, `boolean`, `string`, `object`, `array`。 比如筛选出所有自己发表的文章,除了用传对象的方式: ```javascript // 云函数环境下示例代码 const tcb = require("@cloudbase/node-sdk") const app = tcb.init({}) const db = app.database() const _ = db.command exports.main = async (event, context) => { const myOpenID = "luke-111111" const res = await db .collection("articles") .where({ _openid: myOpenID }) .get() // 用指令的方式 const res1 = await db .collection("articles") .where({ _openid: _.eq(myOpenID) }) .get() return { data: res.data, data1: res1.data } } ``` 注意 `eq` 指令比对象的方式有更大的灵活性,可以用于表示字段等于某个对象的情况,比如: ```js // 云函数环境下示例代码 const tcb = require("@cloudbase/node-sdk") const app = tcb.init({ env: "xxx" }) const db = app.database() const _ = db.command exports.main = async (event, context) => { // 这种写法表示匹配 stat.publishYear == 2018 且 stat.language == 'zh-CN' const res = await db .collection("articles") .where({ stat: { publishYear: 2018, language: "zh-CN" } }) .get() console.log(res.data) // 打印查询的文档数组 // 这种写法表示 stat 对象等于 { publishYear: 2018, language: 'zh-CN' } const res1 = await db .collection("articles") .where({ stat: _.eq({ publishYear: 2018, language: "zh-CN" }) }) .get() console.log(res1.data) // 打印查询的文档数组 } ``` ### neq 字段不等于。`neq` 指令接受一个字面量 (literal),可以是 `number`, `boolean`, `string`, `object`, `array`。 如筛选出品牌不为 X 的计算机: ```js // 云函数环境下示例代码 const tcb = require("@cloudbase/node-sdk") const app = tcb.init({ env: "xxx" }) const db = app.database() const _ = db.command exports.main = async (event, context) => { const res = await db .collection("goods") .where({ category: "computer", type: { brand: _.neq("X") } }) .get() console.log(res.data) // 打印查询的文档数组 } ``` ### gt 字段大于指定值。 如筛选出价格大于 2000 的计算机: ```js // 云函数环境下示例代码 const tcb = require("@cloudbase/node-sdk") const app = tcb.init({ env: "xxx" }) const db = app.database() const _ = db.command exports.main = async (event, context) => { const res = await db .collection("goods") .where({ category: "computer", price: _.gt(2000) }) .get() console.log(res.data) // 打印查询的文档数组 } ``` ### gte 字段大于或等于指定值。 ### lt 字段小于指定值。 ### lte 字段小于或等于指定值。 ### in 字段值在给定的数组中。 筛选出内存为 8g 或 16g 的计算机商品: ```js // 云函数环境下示例代码 const tcb = require("@cloudbase/node-sdk") const app = tcb.init({ env: "xxx" }) const db = app.database() const _ = db.command exports.main = async (event, context) => { const res = await db .collection("goods") .where({ category: "computer", type: { memory: _.in([8, 16]) } }) .get() console.log(res.data) // 打印查询的文档数组 } ``` ### nin 字段值不在给定的数组中。 筛选出内存不是 8g 或 16g 的计算机商品: ```js // 云函数环境下示例代码 const tcb = require("@cloudbase/node-sdk") const app = tcb.init({ env: "xxx" }) const db = app.database() const _ = db.command exports.main = async (event, context) => { const res = await db .collection("goods") .where({ category: "computer", type: { memory: _.nin([8, 16]) } }) .get() console.log(res.data) // 打印查询的文档数组 } ``` ### and 表示需同时满足指定的两个或以上的条件。 如筛选出内存大于 4g 小于 32g 的计算机商品: ```js // 云函数环境下示例代码 const tcb = require("@cloudbase/node-sdk") const app = tcb.init({ env: "xxx" }) const db = app.database() const _ = db.command exports.main = async (event, context) => { // 流式写法 const res = await db .collection("goods") .where({ category: "computer", type: { memory: _.gt(4).and(_.lt(32)) } }) .get() console.log(res.data) // 打印查询的文档数组 // 前置写法 const res1 = await db .collection("goods") .where({ category: "computer", type: { memory: _.and(_.gt(4), _.lt(32)) } }) .get() console.log(res1.data) // 打印查询的文档数组 } ``` ### or 表示需满足所有指定条件中的至少一个。如筛选出价格小于 4000 或在 6000-8000 之间的计算机: ```js // 云函数环境下示例代码 const tcb = require("@cloudbase/node-sdk") const app = tcb.init({ env: "xxx" }) const db = app.database() const _ = db.command exports.main = async (event, context) => { //流式写法: const res = await db .collection("goods") .where({ category: "computer", type: { price: _.lt(4000).or(_.gt(6000).and(_.lt(8000))) } }) .get() console.log(res.data) // 打印查询的文档数组 // 前置写法 const res1 = await db .collection("goods") .where({ category: "computer", type: { price: _.or(_.lt(4000), _.and(_.gt(6000), _.lt(8000))) } }) .get() console.log(res1.data) // 打印查询的文档数组 // 如果要跨字段 “或” 操作:(如筛选出内存 8g 或 cpu 3.2 ghz 的计算机) const res2 = await db .collection("goods") .where( _.or( { type: { memory: _.gt(8) } }, { type: { cpu: 3.2 } } ) ) .get() console.log(res2.data) // 打印查询的文档数组 } ``` ### RegExp 根据正则表达式进行筛选 例如下面可以筛选出 `version` 字段开头是 "数字+s" 的文档,并且忽略大小写: ```js // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk'); const app = tcb.init({ env:'xxx' }) const db = app.database() exports.main = async (event, context) => { // 可以直接使用正则表达式 const res = await db.collection('articles').where({ version: /^\ds/i }).get() console.log(res.data) // 打印查询的文档数组 // 或者 const res1 = await db.collection('articles').where({ version: new db.RegExp({ regexp: '^\\ds' // 正则表达式为 /^\ds/,转义后变成 '^\\ds' options: 'i' // i表示忽略大小写 }) }).get() console.log(res1.data) // 打印查询的文档数组 } ``` ## 更新指令 ### set 描述:用于设定字段等于指定值。这种方法相比传入纯 JS 对象的好处是能够指定字段等于一个对象。 示例代码: ```js // 云函数环境下示例代码 const tcb = require("@cloudbase/node-sdk") const app = tcb.init({ env: "xxx" }) const db = app.database() const _ = db.command exports.main = async (event, context) => { const res = await db .collection("photo") .doc("doc-id") .update({ data: { style: _.set({ color: "red", size: "large" }) } }) console.log(res.updated) // 打印更新成功的文档数量 } ``` ### inc 描述:用于指示字段自增某个值,这是个原子操作,使用这个操作指令而不是先读数据、再加、再写回的好处是: 备注: 1. 原子性:多个用户同时写,对数据库来说都是将字段加一,不会有后来者覆写前者的情况 2. 减少一次网络请求:不需先读再写 之后的 mul 指令同理。 示例代码: ```js // 云函数环境下示例代码 const tcb = require("@cloudbase/node-sdk") const app = tcb.init({ env: "xxx" }) const db = app.database() const _ = db.command exports.main = async (event, context) => { const res = await db .collection("user") .where({ _openid: "my-open-id" }) .update({ count: { favorites: _.inc(1) } }) console.log(res.updated) // 打印更新成功的文档数量 } ``` ### mul 描述:用于指示字段自乘某个值。 ### remove 更新指令。用于表示删除某个字段。如某人删除了自己一条商品评价中的评分: ```js // 云函数环境下示例代码 const tcb = require("@cloudbase/node-sdk") const app = tcb.init({ env: "xxx" }) const db = app.database() const _ = db.command exports.main = async (event, context) => { const res = await db.collection("comments").doc("comment-id").update({ rating: _.remove() }) console.log(res.updated) // 打印更新成功的文档数量 } ``` ### push 向数组尾部追加元素,支持传入单个元素或数组 ```js // 云函数环境下示例代码 const tcb = require("@cloudbase/node-sdk") const app = tcb.init({ env: "xxx" }) const db = app.database() const _ = db.command exports.main = async (event, context) => { const res = await db .collection("comments") .doc("comment-id") .update({ // users: _.push('aaa') users: _.push(["aaa", "bbb"]) }) console.log(res.updated) // 打印更新成功的文档数量 } ``` ### pop 删除数组尾部元素 ```js // 云函数环境下示例代码 const tcb = require("@cloudbase/node-sdk") const app = tcb.init({ env: "xxx" }) const db = app.database() const _ = db.command exports.main = async (event, context) => { const res = await db.collection("comments").doc("comment-id").update({ users: _.pop() }) console.log(res.updated) // 打印更新成功的文档数量 } ``` ### unshift 向数组头部添加元素,支持传入单个元素或数组。使用同 push ### shift 删除数组头部元素。使用同 pop ## 构建查询条件 支持 `where()`、`limit()`、`skip()`、`orderBy()`、`get()`、`update()`、`field()`、`count()` 等操作。 只有当调用`get()`、 `update()`时才会真正发送请求。 ### where 描述:设置过滤条件。where 可接收对象作为参数,表示筛选出拥有和传入对象相同的 key-value 的文档。 输入参数: 无 比如筛选出所有类型为计算机的、内存为 8g 的商品: ```js // 云函数环境下示例代码 const tcb = require("@cloudbase/node-sdk") const app = tcb.init({ env: "xxx" }) const db = app.database() exports.main = async (event, context) => { const res = await db .collection("goods") .where({ category: "computer", type: { memory: 8 } }) .get() console.log(res.data) // 打印查询的文档数组 } ``` 如果要表达更复杂的查询,可使用高级查询指令,比如筛选出所有内存大于 8g 的计算机商品: ```js // 云函数环境下示例代码 const tcb = require('@cloudbase/node-sdk'); const app = tcb.init({ env:'xxx' }) const db = app.database(); const _ = db.command // 取指令 exports.main = async (event, context) => { const res = await db.collection('goods').where({ category: 'computer', type: { memory: _.gt(8), // 表示大于 8 } }).get() console.log(res.data) // 打印查询的文档数组 ``` ### limit 描述:指定查询结果集数量上限 输入参数: | 参数 | 类型 | 必填 | 说明 | | ---- | ------- | ---- | -------------- | | - | Integer | 是 | 限制展示的数值 | 使用示例 ```js // 云函数环境下示例代码 const tcb = require("@cloudbase/node-sdk") const app = tcb.init({ env: "xxx" }) const db = app.database() const collection = db.collection("user") // 例 操作 user 集合 exports.main = async (event, context) => { const res = await collection.where({}).limit(1).get() console.log(res.data) // 打印查询的文档数组 } ``` ### skip 描述:指定查询返回结果时从指定序列后的结果开始返回,常用于分页 输入参数: | 参数 | 类型 | 必填 | 说明 | | ---- | ------- | ---- | -------------- | | - | Integer | 是 | 限制展示的数值 | 示例代码 ```js // 云函数环境下示例代码 const tcb = require("@cloudbase/node-sdk") const app = tcb.init({ env: "xxx" }) const db = app.database() const collection = db.collection("user") // 例 操作 user 集合 exports.main = async (event, context) => { const res = await collection.where({}).skip(4).get() console.log(res.data) // 打印查询的文档数组 } ``` ### field 描述:指定返回结果中文档需返回的字段 输入参数: | 参数 | 类型 | 必填 | 说明 | | ---- | ------ | ---- | ----------------------------------------- | | - | Object | 是 | 要过滤的字段,不返回传 false,返回传 true | 示例代码 ```js // 云函数环境下示例代码 const tcb = require("@cloudbase/node-sdk") const app = tcb.init({ env: "xxx" }) const db = app.database() const collection = db.collection("user") // 例 操作 user 集合 exports.main = async (event, context) => { const res = await collection.where({}).field({ age: true }).get() console.log(res.data) // 打印查询的文档数组 } ``` 备注:field 方法接受一个必填对象用于指定需返回的字段,对象的各个 key 表示要返回或不要返回的字段,value 传入 true|false(或 1|0)表示要返回还是不要返回。 ### orderBy 描述:指定查询排序条件 输入参数: | 参数 | 类型 | 必填 | 说明 | | --------- | ------ | ---- | ----------------------------------- | | field | String | 是 | 排序的字段 | | orderType | String | 是 | 排序的顺序,升序(asc) 或 降序(desc) | 备注:方法接受一个必填字符串参数 fieldName 用于定义需要排序的字段,一个字符串参数 order 定义排序顺序。order 只能取 asc 或 desc。 如果需要对嵌套字段排序,需要用 "点表示法" 连接嵌套字段,比如 style.color 表示字段 style 里的嵌套字段 color。 同时也支持按多个字段排序,多次调用 orderBy 即可,多字段排序时的顺序会按照 orderBy 调用顺序先后对多个字段排序 示例代码 ```js // 云函数环境下示例代码 const tcb = require("@cloudbase/node-sdk") const app = tcb.init({ env: "xxx" }) const db = app.database() const collection = db.collection("user") // 例 操作 user 集合 exports.main = async (event, context) => { const res = await collection.where({}).orderBy("name", "asc").get() console.log(res.data) // 打印查询的文档数组 } ``` ### options 描述:数据库接口配置 输入参数: | 参数 | 类型 | 必填 | 说明 | | -------- | ------- | ---- | ------------------------------------------ | | timeout | Number | 否 | SDK 请求超时时间设置, 默认 15000ms | | multiple | Boolean | 否 | 是否仅操作单个文档,update/delete 方法可用 | 示例代码 ```js // 云函数环境下示例代码 const tcb = require("@cloudbase/node-sdk") const app = tcb.init({ env: "xxx" }) const db = app.database() const collection = db.collection("user") // 例 操作 user 集合 exports.main = async (event, context) => { // 更新单文档 const updateRes = await collection .where({ name: "luke" }) .options({ multiple: false }) .update({ name: "lake" }) console.log(res.updated === 1) // 更新文档数为1 // 删除单文档 const deleteRes = await collection .where({ name: "luke" }) .options({ multiple: false }) .remove() console.log(res.deleted === 1) // 删除文档数为1 // 设置SDK单接口请求超时 const getRes = await collection .where({ name: "luke" }) .options({ timeout: 10000 }) .get() console.log(getRes) } ``` ## createCollection #### 1. 接口描述 接口功能:新增集合 接口声明:`createCollection(collName): Promise` #### 2. 输入参数 | 参数 | 类型 | 必填 | 说明 | | ---- | ------ | ---- | ------ | | - | String | 是 | 集合名 | #### 3. 返回结果 | 字段 | 类型 | 必填 | 说明 | | --------- | ------ | ---- | -------------------- | | requestId | String | 是 | 请求 ID | | message | String | 否 | 接口报错时的错误信息 | | code | String | 否 | 接口报错时的错误码 | #### 4. 示例代码 ```js // 云函数环境下示例代码 const tcb = require("@cloudbase/node-sdk") const app = tcb.init({ env: "xxx" }) const db = app.database() exports.main = async (event, context) => { // 创建集合名为coll-name的集合 const res = await db.createCollection("coll-name") if (!res.code) { // 创建成功 } } ``` ## add #### 1. 接口描述 接口功能:插入一条文档或文档数组 接口声明:`collection.add(object: Array | Object): Promise` 备注:set 方法也可以用来新增文档,请参看文档更新部分 [set](#update-set) 方法 #### 2. 输入参数 | 参数 | 类型 | 必填 | 说明 | | ---- | --------------------------- | ---- | --------------------------------------------------------------------------------------------------------------------------------------------------- | | - | `Array` 或 `Object` | 是 | 可支持批量插入或插入单个文档,例 [{\_id: '10001', 'name': 'Ben'}, {\_id: '10002', 'name': 'Booker'}] 或 {\_id: '10001', 'name': 'Ben'}, \_id 非必填 | #### 3. 返回结果 | 字段 | 类型 | 必填 | 说明 | | --------- | --------------- | ---- | ------------------------------- | | code | String | 否 | 状态码,操作成功则不返回 | | message | String | 否 | 错误描述,操作成功不返回 | | requestId | String | 是 | 请求 ID | | id | String | 否 | 文档 ID,插入单文档成功则返回 | | ids | `Array` | 否 | 文档 ID,批量插入文档成功则返回 | #### 4. 示例代码 ```js // 云函数环境下示例代码 const tcb = require("@cloudbase/node-sdk") const app = tcb.init({ env: "xxx" }) const db = app.database() const collection = db.collection("user") // 例 操作 user 集合 exports.main = async (event, context) => { // 创建集合名为coll-name的集合 const res = await collection.add({ name: "Ben" }) console.log(res.id) //打印新增的文档ID const batchRes = await collection.add([{ name: "luke" }, { name: "jimmy" }]) console.log(batchRes.ids) } ``` ## get #### 1. 接口描述 接口功能:获取数据库查询结果 接口声明:`get(): Promise` 注:get()如不指定 limit 则默认取前 100 条数据;如指定数量大于1000,则最大只取前 1000 条数据。 #### 2. 输入参数 空 #### 3. 返回结果 | 字段 | 类型 | 必填 | 说明 | | --------- | ------ | ---- | ------------------------ | | code | string | 否 | 状态码,操作成功则不返回 | | message | string | 否 | 错误描述 | | data | Object | 否 | 操作成功返回查询结果 | | requestId | string | 是 | 请求序列号,用于错误排查 | #### 4. 示例代码 ```js // 云函数环境下示例代码 const tcb = require("@cloudbase/node-sdk") const app = tcb.init({ env: "xxx" }) const db = app.database() exports.main = async (event, context) => { const res = await db .collection("goods") .where({ category: "computer", type: { memory: 8 } }) .count() console.log(res.data) // 打印查询的文档数组 } ``` ## count #### 1. 接口描述 接口功能:获取数据库查询结果 接口声明:`cout(): Promise` #### 2. 输入参数 空 #### 3. 返回结果 | 字段 | 类型 | 必填 | 说明 | | --------- | ------- | ---- | ------------------------ | | code | string | 否 | 状态码,操作成功则不返回 | | message | string | 否 | 错误描述 | | total | integer | 否 | 计数结果 | | requestId | string | 否 | 请求序列号,用于错误排查 | #### 4. 示例代码 ```js // 云函数环境下示例代码 const tcb = require("@cloudbase/node-sdk") const app = tcb.init({ env: "xxx" }) const db = app.database() exports.main = async (event, context) => { const res = await db .collection("goods") .where({ category: "computer", type: { memory: 8 } }) .count() console.log(res.total) // 打印查询的文档数量 } ``` ## remove #### 1. 接口描述 接口功能:删除一条文档 接口声明:`remove(): Promise` #### 2. 输入参数 无 #### 3. 返回结果 | 字段 | 类型 | 必填 | 说明 | | --------- | ------- | ---- | ------------------------ | | code | string | 否 | 状态码,操作成功则不返回 | | message | string | 否 | 错误描述 | | deleted | integer | 否 | 删除的文档数量 | | requestId | string | 是 | 请求序列号,用于错误排查 | #### 4. 示例代码 方式 1. 通过  指定文档 ID 删除 collection.doc(\_id).remove() ```js // 云函数环境下示例代码 const tcb = require("@cloudbase/node-sdk") const app = tcb.init({ env: "xxx" }) const db = app.database() exports.main = async (event, context) => { const res = await db.collection("articles").doc("xxx").remove() console.log(res.deleted) // 打印删除的文档数量 } ``` 方式 2. 条件查找文档然后直接批量删除 ```js // 云函数环境下示例代码 const tcb = require("@cloudbase/node-sdk") const app = tcb.init({ env: "xxx" }) const db = app.database() exports.main = async (event, context) => { // 删除字段a的值大于2的文档 const res = await db .collection("articles") .where({ a: _.gt(2) }) .remove() console.log(res.deleted) // 打印删除的文档数量 } ``` ## update / set #### 1. 接口描述 接口功能:更新文档 接口声明: `update(object: ): Promise` `set(object: ): Promise` 备注:update 和 set 都可以用来更新文档,区别是 set 方法在要更新的文档不存在时新增一个文档;而 update 方法什么也不会做,返回 updated 为 0 #### 2. 输入参数 | 字段 | 类型 | 必填 | 说明 | | ---- | --------- | ---- | -------------- | | - | | 是 | 替换文档的定义 | #### 3. 返回结果 | 字段 | 类型 | 必填 | 说明 | | ---------- | ------- | ---- | ------------------------ | | code | string | 否 | 状态码,操作成功则不返回 | | message | string | 否 | 错误描述 | | updated | integer | 否 | 影响的文档数量 | | upsertedId | string | 否 | 插入的文档的 id | | requestId | string | 是 | 请求序列号,用于错误排查 | #### 4. 示例代码 更新指定文档 ```js // 云函数环境下示例代码 const tcb = require("@cloudbase/node-sdk") const app = tcb.init({ env: "xxx" }) const db = app.database() exports.main = async (event, context) => { // 更新单文档 const res = await db.collection("articles").doc("doc-id").update({ name: "Hey" }) console.log(res.updated) // 打印更新成功的文档数量 // 批量更新文档 const res1 = await db .collection("articles") .where({ name: _.eq("hey") }) .update({ age: 18 }) console.log(res1.updated) // 打印更新成功的文档数量 } ``` 更新文档,如果不存在则创建 ```js // 云函数环境下示例代码 const tcb = require("@cloudbase/node-sdk") const app = tcb.init({ env: "xxx" }) const db = app.database() exports.main = async (event, context) => { // 更新单文档 const res = await db.collection("articles").doc("doc-id").set({ name: "Hey" }) console.log(res.upsertedId) // 打印插入的文档的id } ``` ## updateAndReturn #### 1. 接口描述 接口功能:更新文档并返回更新后数据 接口声明: `updateAndReturn(object: ): Promise` :::tip 仅支持更新符合查询条件的第一条文档,并返回更新后的该文档 ::: #### 2. 输入参数 | 字段 | 类型 | 必填 | 说明 | | ---- | --------- | ---- | -------------- | | - | | 是 | 替换文档的定义 | #### 3. 返回结果 | 字段 | 类型 | 必填 | 说明 | | --------- | ------- | ---- | ------------------------------ | | code | string | 否 | 状态码,操作成功则不返回 | | message | string | 否 | 错误描述 | | updated | integer | 是 | 1 or 0,表示成功更新的文档数量 | | doc | object | 否 | 更新成功则返回更新后的文档 | | requestId | string | 是 | 请求序列号,用于错误排查 | #### 4. 示例代码 ```js // 云函数环境下示例代码 const tcb = require("@cloudbase/node-sdk") const app = tcb.init({ env: "xxx" }) const db = app.database() exports.main = async (event, context) => { // 更新并返回更新后文档 const res = await db .collection("articles") .where({ name: _.eq("hey") }) .updateAndReturn({ age: 18 }) console.log(res.doc) // 打印更新后的文档 } ``` ## GEO 地理位置 注意:**如果需要对类型为地理位置的字段进行搜索,一定要建立地理位置索引**。 ### GEO 数据类型 #### Point 用于表示地理位置点,用经纬度唯一标记一个点,这是一个特殊的数据存储类型。 签名:`Point(longitude: number, latitude: number)` 示例: ```js new db.Geo.Point(longitude, latitude) ``` #### LineString 用于表示地理路径,是由两个或者更多的 `Point` 组成的线段。 签名:`LineString(points: Point[])` 示例: ```js new db.Geo.LineString([ new db.Geo.Point(lngA, latA), new db.Geo.Point(lngB, latB) // ... ]) ``` #### Polygon 用于表示地理上的一个多边形(有洞或无洞均可),它是由一个或多个**闭环** `LineString` 组成的几何图形。 由一个环组成的 `Polygon` 是没有洞的多边形,由多个环组成的是有洞的多边形。对由多个环(`LineString`)组成的多边形(`Polygon`),第一个环是外环,所有其他环是内环(洞)。 签名:`Polygon(lines: LineString[])` 示例: ```js new db.Geo.Polygon([ new db.Geo.LineString(...), new db.Geo.LineString(...), // ... ]) ``` #### MultiPoint 用于表示多个点 `Point` 的集合。 签名:`MultiPoint(points: Point[])` 示例: ```js new db.Geo.MultiPoint([ new db.Geo.Point(lngA, latA), new db.Geo.Point(lngB, latB) // ... ]) ``` #### MultiLineString 用于表示多个地理路径 `LineString` 的集合。 签名:`MultiLineString(lines: LineString[])` 示例: ```js new db.Geo.MultiLineString([ new db.Geo.LineString(...), new db.Geo.LineString(...), // ... ]) ``` #### MultiPolygon 用于表示多个地理多边形 `Polygon` 的集合。 签名:`MultiPolygon(polygons: Polygon[])` 示例: ```js new db.Geo.MultiPolygon([ new db.Geo.Polygon(...), new db.Geo.Polygon(...), // ... ]) ``` ### GEO 操作符 #### geoNear 按从近到远的顺序,找出字段值在给定点的附近的文档。 签名: ```js db.command.geoNear(options: IOptions) interface IOptions { geometry: Point // 点的地理位置 maxDistance?: number // 选填,最大距离,米为单位 minDistance?: number // 选填,最小距离,米为单位 } ``` 示例: ```js // 云函数环境下示例代码 const tcb = require("@cloudbase/node-sdk") const app = tcb.init({ env: "xxx" }) const db = app.database() const _ = db.command exports.main = async (event, context) => { const res = await db .collection("user") .where({ location: db.command.geoNear({ geometry: new db.Geo.Point(lngA, latA), maxDistance: 1000, minDistance: 0 }) }) .get() console.log(res.data) // 打印查询的文档数组 } ``` #### geoWithin 找出字段值在指定 Polygon / MultiPolygon,或 centerSphere 内的文档,无排序 用法: ```js db.command.geoWithin(IOptions) interface IOptions { geometry?: Polygon | MultiPolygon; // 多边形 centerSphere?: [Point, number]; // 圆形 } ``` :::tip centerSphere 用法仅在 2.3.1 以上版本支持 centerSphere 对应的值的定义是:[ 地理位置点, 半径 ] 半径需以弧度计,比如需要 10km 的半径,则用距离除以地球半径 6378.1km 得出的数字。 ::: 示例: ```js // 云函数环境下示例代码 const tcb = require("@cloudbase/node-sdk") const app = tcb.init({ env: "xxx" }) const db = app.database() const _ = db.command exports.main = async (event, context) => { // 一个闭合的多边形区域 const area1 = new Polygon([ new LineString([ new Point(lngA, latA), new Point(lngB, latB), new Point(lngC, latC), new Point(lngA, latA) ]) ]) // 搜索 location 字段在这个多边形区域中的 user const res1 = await db .collection("user") .where({ location: db.command.geoWithin({ geometry: area1 }) }) .get() console.log(res1.data) // 打印查询的文档数组 // centerSphere表示 const area2 = [new Point(-88, 30), 10 / 6378.1] // 搜索 location 字段在这个圆形区域中的 user const res2 = await db .collection("user") .where({ location: db.command.geoWithin({ centerSphere: area2 }) }) .get() console.log(res2.data) // 打印查询的文档数组 } ``` #### geoIntersects 找出字段值和给定的地理位置图形相交的文档 签名: ```js db.command.geoIntersects(IOptions) interface IOptions { geometry: | Point | LineString | MultiPoint | MultiLineString | Polygon | MultiPolygon; // 地理位置 } ``` 示例: ```js // 云函数环境下示例代码 const tcb = require("@cloudbase/node-sdk") const app = tcb.init({ env: "xxx" }) const db = app.database() const _ = db.command exports.main = async (event, context) => { // 一条路径 const line = new LineString([new Point(lngA, latA), new Point(lngB, latB)]) // 搜索 location 与这条路径相交的 user const res = await db .collection("user") .where({ location: db.command.geoIntersects({ geometry: line }) }) .get() console.log(res.data) // 打印查询的文档数组 } ``` ## 时间 Date Date 类型用于表示时间,精确到毫秒,可以用 JavaScript 内置 Date 对象创建。需要特别注意的是,用此方法创建的时间是客户端时间,不是服务端时间。如果需要使用服务端时间,应该用 API 中提供的 serverDate 对象来创建一个服务端当前时间的标记,当使用了 serverDate 对象的请求抵达服务端处理时,该字段会被转换成服务端当前的时间,更棒的是,我们在构造 serverDate 对象时还可通过传入一个有 offset 字段的对象来标记一个与当前服务端时间偏移 offset 毫秒的时间,这样我们就可以达到比如如下效果:指定一个字段为服务端时间往后一个小时。 那么当我们需要使用客户端时间时,存放 Date 对象和存放毫秒数是否是一样的效果呢?不是的,我们的数据库有针对日期类型的优化,建议大家使用时都用 Date 或 serverDate 构造时间对象。 ```js //服务端当前时间 new db.serverDate() ``` ```js //服务端当前时间加1S new db.serverDate({ offset: 1000 }) ``` ## ObjectId 类型 为解决原生 Mongo 数据库导出数据至云开发数据库后,产生的 ObjectId 数据结构兼容问题,现支持 ObjectId 类型使用。 #### 插入 ObjectId 类型值 & 查询 ```javascript const app = tcb.init() const db = app.database() const collName = "db-test-oid-test" const collection = db.collection(collName) const insertRes = await collection.add({ a: db.ObjectId({ id: "61642e2da293c008ac5e8690" }) }) const getRes = await collection .where({ a: db.ObjectId({ id: "61642e2da293c008ac5e8690" }) }) .get() console.log("getRes", getRes) ``` #### ObjectId 类型联表查询 ```javascript const app = tcb.init() const db = app.database() const collName = "db-test-oid-test" const lookupCollName = "db-test-oid-test-lookup" const collection = db.collection(collName) const lookupCollection = db.collection(lookupCollName) const objId1 = "61642e2da293c008ac5e868f" const objId2 = "61642e2da293c008ac5e8690" const addRes = await collection.add({ _id: db.ObjectId({ id: objId1 }), inviter_uid: db.ObjectId({ id: objId2 }), name: "test" }) console.log(addRes.id === objId1) const addRes1 = await lookupCollection.add({ _id: db.ObjectId({ id: objId2 }), inviter_uid: db.ObjectId({ id: objId1 }), name: "test1" }) console.log(addRes1.id === objId2) const aggregateRes = await lookupCollection .aggregate() .lookup({ from: collName, localField: "inviter_uid", foreignField: "_id", as: "newTest" }) .end() console.log("aggregateRes", aggregateRes) /* { "requestId":"17c6f5463f2_8", "data":[ { "_id":"61642e2da293c008ac5e8690", // id2 "inviter_uid":"61642e2da293c008ac5e868f", // id1 "name":"test1", "newTest":[ { "_id":"61642e2da293c008ac5e868f", // id1 "inviter_uid":"61642e2da293c008ac5e8690", // id2 "name":"test" } ] } ] } */ ``` ## 数据库事务 ### startTransaction #### 1. 接口描述 接口功能:发起事务 接口声明:`startTransaction(): Promise` #### 2. 输入参数 无 #### 3. 返回结果 | 参数 | 类型 | 必填 | 说明 | | ------- | ------ | ---- | ------------------------ | | \_id | string | 否 | 成功则返回事务 id | | code | string | 否 | 状态码,操作成功则不返回 | | message | string | 否 | 错误描述 | #### 4. 示例代码 ```javascript // 云函数环境下示例代码 const tcb = require("@cloudbase/node-sdk") const app = tcb.init({ env: "xxx" }) const db = app.database() exports.main = async (event, context) => { const transaction = await db.startTransaction() console.log(transaction._id) // 打印事务id } ``` ### commit #### 1. 接口描述 接口功能:提交事务 接口声明:`commit(): Promise` #### 2. 输入参数 无 #### 3. 返回结果 | 字段 | 类型 | 必填 | 说明 | | --------- | ------ | ---- | --------------------------- | | requestId | string | 是 | 请求 id | | code | string | 否 | 状态码,操作成功则不返回 | | message | string | 否 | 错误描述, 操作成功则不返回 | #### 4. 示例代码 ```javascript // 云函数环境下示例代码 const tcb = require("@cloudbase/node-sdk") const app = tcb.init({ env: "xxx" }) const db = app.database() exports.main = async (event, context) => { const transaction = await db.startTransaction() await transaction.commit() } ``` ### get #### 1. 接口描述 接口功能:事务查询文档 接口声明: - `doc().get(): Promise` 单文档查询 - `where().get(): Promise` 条件查询 #### 2. 输入参数 无 #### 3. 返回结果 | 参数 | 类型 | 必填 | 说明 | | --------- | ------------------------------ | ---- | ------------------------------------------------------------------ | | data | <Array>.Object or Object | 否 | 操作成功,条件查询时返回文档对象数组,单文档查询时返回单个文档对象 | | requestId | string | 是 | 请求 id | | code | string | 否 | 状态码,操作成功则不返回 | | message | string | 否 | 错误描述, 操作成功则不返回 | #### 4. 示例代码 ```javascript // 云函数环境下示例代码 const tcb = require("@cloudbase/node-sdk") const app = tcb.init({ env: "xxx" }) const db = app.database() exports.main = async (event, context) => { /** * 事务操作支持两种写法,写法一如下,1. 调用startTransaction发起事务 2. 事务操作 3.调用commitTransactio提交事务 * * */ const transaction = await db.startTransaction() const doc = await transaction.collection(collectionName).doc("docId").get() console.log(doc.data) // 打印查询的文档 await transaction.commit() /** * 写法二,runTransaction(callback(transaction)), 支持用户传入回调,回调参数为transaction * * */ await db.runTransaction(async function (transaction) { const doc = await transaction.collection(collectionName).doc("docId").get() console.log(doc.data) // 打印查询的文档 }) } ``` ```javascript // 云函数下示例代码 const tcb = require("@cloudbase/node-sdk") const app = tcb.init({ env: "xxx" }) const db = app.database() exports.main = async (event, context) => { // 事务条件查询 const transaction = await db.startTransaction() const res = await transaction .collection(collectionName) .where({ name: "luke" }) .get() console.log(res.data) // 打印查询的文档 await transaction.commit() } ``` ### add #### 1. 接口描述 接口功能:事务插入文档 接口声明:`add(data): Promise` #### 2. 输入参数 | 参数 | 类型 | 必填 | 说明 | | ---- | ------------------------------ | ---- | ---------------------------------------------------------------------------------------------------------- | | - | <Array>.Object or Object | 是 | 插入单文档: 例 {\_id: '10001', 'name': 'Ben'} \_id 非必填 ,插入多文档 ['name': 'Ben'}, {'name': 'luke'}] | #### 3. 返回结果 | 参数 | 类型 | 必填 | 说明 | | --------- | ------ | ---- | ----------------------------------------- | | requestId | string | 是 | 请求 id | | code | string | 否 | 状态码,操作成功则不返回 | | message | string | 否 | 错误描述, 操作成功则不返回 | | id | string | 否 | 插入单文档数据返回的 docId | | ids | string | 否 | 插入多文档数据返回的 docId 数组 | | inserted | number | 否 | 仅在单文档插入时,返回插入成功的条数 | | ok | number | 否 | 仅在单文档插入时,返回插入状态 1 表示成功 | #### 4. 示例代码 ```javascript // 云函数环境下示例代码 const tcb = require("@cloudbase/node-sdk") const app = tcb.init({ env: "xxx" }) const db = app.database() exports.main = async (event, context) => { const transaction = await db.startTransaction() // 插入单文档 const res = await transaction .collection(collectionName) .add({ category: "Web", tags: ["JavaScript", "C#"], date }) console.log(res.id) // 打印添加的docId // 插入多文档 const batchRes = await transaction.collection(collectionName).add([ { category: "Web", tags: ["JavaScript", "C#"], date }, { category: "Backend", tags: ["Java"], date } ]) console.log(batchRes.ids) // 打印添加的docId数组 await transaction.commit() } ``` ### update / set #### 1. 接口描述 接口功能:事务更新文档(仅支持单文档) 接口声明: `update(data): Promise` `set(object: Object): Promise` 备注:update 和 set 都可以用来更新文档,区别是 set 方法在要更新的文档不存在时新增一个文档;而 update 方法什么也不会做,返回 updated 为 0 #### 2. 输入参数 | 参数 | 类型 | 必填 | 说明 | | ---- | ------ | ---- | ---------------- | | - | Object | 是 | 要更新的字段对象 | #### 3. 返回结果 | 参数 | 类型 | 必填 | 说明 | | --------- | ------ | ---- | --------------------------- | | updated | number | 否 | 更新成功的条数 | | upserted | number | 否 | 插入成功的条数 | | requestId | string | 是 | 请求 id | | code | string | 否 | 状态码,操作成功则不返回 | | message | string | 否 | 错误描述, 操作成功则不返回 | #### 4. 示例代码 ```javascript // 云函数环境下示例代码 const tcb = require("@cloudbase/node-sdk") const app = tcb.init({ env: "xxx" }) const db = app.database() exports.main = async (event, context) => { const transaction = await db.startTransaction() // update const updateResult = await transaction .collection(collectionName) .doc("docId") .update({ category: "Node.js", date }) console.log(updateResult.updated) // 更新的条数 // set const setResult = await transaction .collection(collectionName) .doc("docId") .set({ category: "Node.js", date }) console.log(setResult.updated, setResult.upserted) await transaction.commit() } ``` ### updateAndReturn #### 1. 接口描述 接口功能:事务更新并返回文档 接口声明: `updateAndReturn(data): Promise` :::tip 仅支持更新符合查询条件的第一条文档,并返回更新后的该文档 ::: #### 2. 输入参数 | 参数 | 类型 | 必填 | 说明 | | ---- | ------ | ---- | ---------------- | | - | Object | 是 | 要更新的字段对象 | #### 3. 返回结果 | 字段 | 类型 | 必填 | 说明 | | --------- | ------- | ---- | ------------------------------ | | code | string | 否 | 状态码,操作成功则不返回 | | message | string | 否 | 错误描述 | | updated | integer | 是 | 1 or 0,表示成功更新的文档数量 | | doc | object | 否 | 更新成功则返回更新后的文档 | | requestId | string | 是 | 请求序列号,用于错误排查 | #### 4. 示例代码 ```javascript // 云函数环境下示例代码 const tcb = require("@cloudbase/node-sdk") const app = tcb.init({ env: "xxx" }) const db = app.database() exports.main = async (event, context) => { const updateResult = await transaction .collection(collectionName) .where({ name: "goreliu" }) .updateAndReturn({ age: 18 }) console.log(updateResult.updated, updateResult.doc) await transaction.commit() } ``` ### delete #### 1. 接口描述 接口功能:事务删除文档(仅支持单文档) 接口声明:`delete(): Promise` #### 2. 输入参数 无 #### 3. 返回结果 | 字段 | 类型 | 必填 | 说明 | | --------- | ------ | ---- | --------------------------- | | deleted | number | 否 | 删除成功的条数 | | requestId | string | 是 | 请求 id | | code | string | 否 | 状态码,操作成功则不返回 | | message | string | 否 | 错误描述, 操作成功则不返回 | #### 4. 示例代码 ```javascript // 云函数环境下示例代码 const tcb = require("@cloudbase/node-sdk") const app = tcb.init({ env: "xxx" }) const db = app.database() exports.main = async (event, context) => { // deletaDocument const transaction = await db.startTransaction() const deleteResult = await transaction .collection(collectionName) .doc("docId") .delete() console.log(deleteResult.deleted) // 删除成功的条数 await transaction.commit() } ``` ### rollback #### 1. 接口描述 接口功能:事务回滚 接口声明:`rollback(): Promise` #### 2. 输入参数 无 #### 3. 返回结果 | 字段 | 类型 | 必填 | 说明 | | --------- | ------ | ---- | ------- | | requestId | string | 是 | 请求 id | #### 4. 示例代码 ```javascript // 云函数环境下示例代码 const tcb = require("@cloudbase/node-sdk") const app = tcb.init({ env: "xxx" }) const db = app.database() exports.main = async (event, context) => { // 云函数环境下,下面代码放置入口函数体内 const transaction = await db.startTransaction() const doc = await transaction.collection(collectionName).doc("docId").get() console.log(doc.data) await transaction.rollback() } ``` ### runTransaction 使用说明 1. 支持自定义返回 (正常 return 或 throw error) ```javascript // 云函数环境下示例代码 const tcb = require("@cloudbase/node-sdk") const app = tcb.init({ env: "xxx" }) const db = app.database() exports.main = async (event, context) => { const result = await db.runTransaction(async function (transaction) { const doc = await transaction.collection(collectionName).doc("1").get() console.log(doc.data) return "luke" }) } // result === 'luke' ``` ```javascript // 云函数环境下示例代码 const tcb = require("@cloudbase/node-sdk") const app = tcb.init({ env: "xxx" }) const db = app.database() exports.main = async (event, context) => { try { await db.runTransaction(async (transaction) => { const doc = await transaction.collection(collectionName).doc("1").get() console.log(doc.data) // mock 事务冲突 throw { code: "DATABASE_TRANSACTION_CONFLICT", message: "[ResourceUnavailable.TransactionConflict] Transaction is conflict, maybe resource operated by others. Please check your request, but if the problem persists, contact us." } }) } catch (e) { // e.code === 'DATABASE_TRANSACTION_CONFLICT' } } ``` 2. rollback 使用 ```javascript // 云函数环境下示例代码 const tcb = require("@cloudbase/node-sdk") const app = tcb.init({ env: "xxx" }) const db = app.database() exports.main = async (event, context) => { try { await db.runTransaction(async function (transaction) { const doc = await transaction.collection(collectionName).doc("1").get() console.log(doc.data) await transaction.rollback("luke") }) } catch (err) { // err === 'luke' } try { await db.runTransaction(async function (transaction) { const doc = await transaction.collection(collectionName).doc("1").get() console.log(doc.data) await transaction.rollback() }) } catch (err) { // assert(err.requestId) console.log(err.requestId) // 默认rollback返回回滚的requestId } } ``` ### 事务注意事项 事务中进行并发操作时(如 Promise.all 触发数据库请求),容易引起冲突,请尽量使用串行方式触发请求。 --- ## 环境 # 环境 ## `tcb.SYMBOL_CURRENT_ENV` 字段说明: 初始化时使用该字段,可指定请求当前云函数的环境 > 注意:从 v3 版本开始,如在初始化 `init({})` 未指定 `env` 参数,则默认使用当前云函数环境 ID,不再使用云开发默认环境。如需要使用云开发默认环境,可以指定 `init({env: tcb.SYMBOL_DEFAULT_ENV})`。 ### 示例代码 ```ts import tcb from '@cloudbase/node-sdk' // 取当前云函数的环境初始化 const app = tcb.init({ env: tcb.SYMBOL_CURRENT_ENV }) exports.main = async (event, context) => { // 业务逻辑 } ``` ## `parseContext` ### 1. 接口描述 接口功能:解析云函数环境下的环境变量(参数取用 云函数入口参数 `context` 即可) 接口声明:`parseContext(context): Object` ### 2. 输入参数 | 字段 | 类型 | 必填 | 说明 | | -------------------- | -------- | -- | -------------- | | `memory_limit_in_mb` | `Number` | 是 | 云函数内存限制 | | `time_limit_in_ms` | `Number` | 是 | 运行时间限制 | | `request_id` | `String` | 是 | 请求 ID | | `environ` | `String` | 是 | 环境变量字符串 | | `function_version` | `String` | 是 | 云函数版本 | | `function_name` | `String` | 是 | 云函数名 | | `namespace` | `String` | 是 | 命名空间 | ### 3. 返回结果 | 字段 | 类型 | 必填 | 说明 | | -------------------- | -------- | -- | ------------------------------------------ | | `memory_limit_in_mb` | `Number` | 是 | 云函数内存限制 | | `time_limit_in_ms` | `Number` | 是 | 运行时间限制 | | `request_id` | `String` | 是 | 请求 ID | | `environ` | `Object` | 是 | 环境变量对象(含用户设置的自定义环境变量值) | | `function_version` | `String` | 是 | 云函数版本 | | `function_name` | `String` | 是 | 云函数名 | | `namespace` | `String` | 是 | 命名空间 | ### 4. 示例代码 ```ts import tcb from '@cloudbase/node-sdk' exports.main = async (event, context) => { // context 参数 取自云函数入口函数handler的context对象 const envObj = tcb.parseContext(context) // 打印云函数环境变量 console.log(envObj) } ``` --- ## 云函数 # 云函数 ## callFunction ### 1. 接口描述 接口功能:执行云函数 接口声明:`callFunction(callFunctionOptions: ICallFunctionOptions, opts?: ICustomReqOpts): Promise>` ### 2. 输入参数 | 字段 | 类型 | 必填 | 说明 | | --------------------- | ----------------------------- | ---- | -------------------------------------------------------------- | | `callFunctionOptions` | `ICallFunctionOptions` | 是 | 云函数调用请求参数 | | `opts` | `ICustomReqOpts` | 否 | 自定义配置,目前支持 SDK 请求超时时间设置,`{timeout: number}` | `ICallFunctionOptions` 云函数参数: | 字段 | 类型 | 必填 | 说明 | | ----------- | -------- | ---- | --------------------------------------------------------------------------------- | | `name` | `string` | 是 | 云函数名称 | | `data` | `ParaT` | 否 | 云函数参数 | | `qualifier` | `string` | 否 | 云函数版本标识:`$LATEST`(最新版本) `1` `2` `3`,缺省时按平台配置流量比例分配流量 | 函数型云托管 额外可以传参数,传入 `type:'cloudrun'` 参数后,将调用函数型云托管服务 | 字段 | 类型 | 必填 | 说明 | | -------- | ------------------------ | ---- | ---------------------------------- | | `type` | `cloudrun` | 否 | 是否调用 基于 云托管的函数型云托管 | | `method` | `string` | 否 | HTTP 请求方法 | | `path` | `string` | 否 | HTTP 请求路径 | | `header` | `Record` | 否 | HTTP 请求头 | | `data` | `object` | 否 | HTTP 请求体 | ### 3. 返回结果 `Promise>` | 字段 | 类型 | 必填 | 说明 | | ----------- | --------- | ---- | ------------------------ | | `result` | `ResultT` | 否 | 云函数执行结果 | | `requestId` | `string` | 否 | 请求序列号,用于错误排查 | > 函数执行报错,将通过异常抛出 ### 4. 示例代码 ```ts import tcb from "@cloudbase/node-sdk"; const app = tcb.init({ env: "xxx", }); exports.main = async (event, context) => { const res = await app.callFunction({ name: "test", data: { a: 1 }, }); console.log(res); // 打印函数调用结果 const res1 = await app.callFunction( { name: "test", data: { a: 1 }, }, { timeout: 5000, } ); console.log(res1); }; ``` 函数型云托管 示例代码: ```ts import tcb from "@cloudbase/node-sdk"; exports.main = async (event, context) => { const { httpContext } = context; const { url, httpMethod } = httpContext; return `[${httpMethod}][${url}] Hello world!`; const tcbapp = tcb.init({ context }); const result = await tcbapp.callFunction( { name: "helloworld", // 函数型云托管 参数 type: "cloudrun", method: "POST", path: "/abc", data: { key1: "test value 1", key2: "test value 2", }, }, { timeout: 5000, } ); console.log(result); }; ``` --- ## SDK 初始化 # SDK 初始化 ## init ### 1. 接口描述 接口功能:SDK 实例初始化 接口声明:`init: (config?: ICloudBaseConfig): CloudBase` ### 2. 输入参数 | 字段 | 类型 | 必填 | 说明 | | -------------- | -------- | -- | ----------------------------------------------------------------------------------------------------------------------------------------- | | `secretId` | `string` | 否 | 腾讯云 API 固定密钥对 `secretId`,在云函数内执行可不填。[前往控制台获取](https://console.cloud.tencent.com/cam/capi) | | `secretKey` | `string` | 否 | 腾讯云 API 固定密钥对 `secretKey`,在云函数内执行可不填。[前往控制台获取](https://console.cloud.tencent.com/cam/capi) | | `sessionToken` | `string` | 否 | 腾讯云 API 临时密钥对 `Token`,临时凭证需通过 `sts.AssumeRole` 接口获取临时访问凭证 [查看文档](https://cloud.tencent.com/document/product/1312/48197) | | `env` | `string` | 否 | TCB 环境 ID。如果 SDK 运行在 `TCB云函数` 环境下,默认使用函数所在环境的环境ID,运行在其他环境缺省该参数则会使用默认境 | | `timeout` | `number` | 否 | 调用接口的超时时间(ms),默认为 `15000ms`,即 `15s` | | `proxy` | `string` | 否 | 调用接口时使用的 http 代理 url | | `credentials` | `object` | 否 | Cloudbase 私钥,包含 `private_key` 和 `private_key_id` 两个字符串,可以登录[云开发控制台](https://console.cloud.tencent.com/tcb)获取 | | `version` | `string` | 否 | 版本号,依赖项目的版本号 | 函数型云托管中可通过以下参数初始化 SDK 实现免签名调用: | 字段 | 类型 | 必填 | 说明 | | -------------- | -------- | -- | ------------------------------- | | `context` | `Context` | 否 | 函数型云托管 入口函数 context 参数 | 如果传入了 `context` 参数,但是是没有 `env` 参数,则会使用 `context` 中的 `envID` 参数作为 `环境ID`。 ### 3. 返回结果 | 字段 | 类型 | 必填 | 说明 | | ---- | --------- | ---- | ------------ | | - | `CloudBase` | 是 | tcb 对象实例 | ### 4. 示例代码 ```ts import tcb from '@cloudbase/node-sdk' // 初始化,云函数下可省略 secretId 和 secretKey,env 如果不指定则使用当前函数所在环境的环境ID const app = tcb.init() const app = tcb.init({env: 'xxx'}) const app = tcb.init({ secretId: 'xxxxx', secretKey: 'xxxx', sessionToken: 'xxxx', env: 'xxx' }) // 设置请求超时时间 const app = tcb.init({ timeout: 5000 }) // 初始化环境'xx'和'zz' const app1 = tcb.init({env: 'xx'}) const app2 = tcb.init({env: 'zz'}) ``` 函数型云托管中初始化SDK并调用 ```ts import tcb from '@cloudbase/node-sdk' exports.main = async (event, context) => { const { httpContext } = context const { url, httpMethod } = httpContext console.log(`[${httpMethod}][${url}]`) const tcbapp = tcb.init({ context }) const result = await tcbapp.callFunction({ name: 'helloworld', // 函数型云托管 参数 type: 'cloudrun', method: 'POST', path: '/abc', data: { key1: 'test value 1', key2: 'test value 2' }, { timeout: 5000 } }) console.log(result) // 其他业务逻辑,例如: // 调用容器 // 调用数据库 // 调用云存储 } ``` --- ## 介绍 # 介绍 [![NPM Version](https://img.shields.io/npm/v/@cloudbase/node-sdk)](https://www.npmjs.com/package/@cloudbase/node-sdk) ![node (scoped)](https://img.shields.io/node/v/@cloudbase/node-sdk) Cloudbase Server Node.js SDK 让您可以在服务端(如腾讯云云函数或 云主机 等)使用 Node.js 服务访问 TCB 的服务,如云函数调用,文件上传下载,数据库集合文档操作等,方便快速搭建应用。 从 `v3.0.0` 开始需要 Node.js `v12.0` 及以上版本,需要更低版本可以选择 `v2.0.0` 版本。 > 注意:从 v3 版本开始,如在初始化 `init({})` 未指定 `env` 参数,则默认使用当前云函数环境 ID,不再使用云开发默认环境。如需要使用云开发默认环境,可以指定 `init({env: tcb.SYMBOL_DEFAULT_ENV})`。 ## 安装 Cloudbase Server Node.js SDK 可以通过 `npm` 安装: ```bash npm install --save @cloudbase/node-sdk ``` ## 使用示例 要在您的代码内使用该模块: ```ts import tcb from "@cloudbase/node-sdk"; ``` 或 ```ts import tcb from "@cloudbase/node-sdk"; ``` 或 ```ts import * as tcb from "@cloudbase/node-sdk"; ``` --- ## 打印日志 # 打印日志 ## log #### 1. 接口描述 接口功能:按 log 级别上报日志 接口声明:`log(data: Object): void` #### 2. 输入参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------ | ---- | -------------- | | - | Object | 是 | 打印的日志对象 | #### 3. 返回结果 无 #### 4. 示例代码 ```javascript const tcb = require('@cloudbase/node-sdk') const app = tcb.init() let logMsg = { name: 'luke', age: '25' } // msg必须为对象 exports.main = async (event, context) => { // 输出log级别 app.logger().log(logMsg) } ``` ## warn #### 1. 接口描述 接口功能:按 warn 级别上报日志 接口声明:`warn(data: Object): void` #### 2. 输入参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------ | ---- | -------------- | | - | Object | 是 | 打印的日志对象 | #### 3. 返回结果 无 #### 4. 示例代码 ```javascript const tcb = require('@cloudbase/node-sdk') const app = tcb.init() let logMsg = { name: 'luke', age: '25' } // msg必须为对象 exports.main = async (event, context) => { // 输出warn级别 app.logger().warn(logMsg) } ``` ## error #### 1. 接口描述 接口功能:按 error 级别上报日志 接口声明:`error(data: Object): void` #### 2. 输入参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------ | ---- | -------------- | | - | Object | 是 | 打印的日志对象 | #### 3. 返回结果 无 #### 4. 示例代码 ```javascript const tcb = require('@cloudbase/node-sdk') const app = tcb.init() let logMsg = { name: 'luke', age: '25' } // msg必须为对象 exports.main = async (event, context) => { // 输出error级别 app.logger().error(logMsg) } ``` ## info #### 1. 接口描述 接口功能:按 info 级别上报日志 接口声明:`info(data: Object): void` #### 2. 输入参数 | 字段 | 类型 | 必填 | 说明 | | ---- | ------ | ---- | -------------- | | - | Object | 是 | 打印的日志对象 | #### 3. 返回结果 无 #### 4. 示例代码 ```javascript const tcb = require('@cloudbase/node-sdk') const app = tcb.init() let logMsg = { name: 'luke', age: '25' } // msg必须为对象 exports.main = async (event, context) => { // 输出info级别 app.logger().info(logMsg) } ``` --- ## 初始化 # 初始化 使用 node-sdk 进行初始化后,通过 `.models` 获取数据模型实例。 ```js import tcb from '@cloudbase/node-sdk' // 初始化,云函数下可省略 secretId 和 secretKey,env 如果不指定则使用当前函数所在环境的环境ID const app = tcb.init({ secretId: 'xxxxx', secretKey: 'xxxx', sessionToken: 'xxxx', env: 'xxx' }) const models = app.models ``` --- ## 增删改查 import Doc from '@site/docs/model/sdk-reference/_model.md'; # 增删改查 --- ## 查询参数详解 import Doc from "@site/docs/model/_select.md" # 查询参数详解 --- ## 包升级 # 包升级 node-sdk 与 tcb-admin-node 目前在 云函数,文件存储,数据库功能上保持了一致,但是 node-sdk 为用户提供了更友好的开发体验,未来 node-sdk 将继续迭代支持新特性,而 tcb-admin-node 会处于维护阶段,不会新增特性。 1. 支持[批量插入](./database/database.md#add),[更新/删除单文档(批量查询时)](./database/database.md#options) 2. 业务错误码 throw 抛出,携带报错堆栈信息,方便定位问题 3. [部分接口支持超时时间设置](#timeoutSetOpts) 4. [云函数中使用当前环境](./env.md#SYMBOL_CURRENT_ENV) 5. 更好的支持 TypeScript # 如何从 tcb-admin-node 迁移至 @cloudbase/node-sdk ? ## sdk 初始化方式变动 示例如下: - 使用 tcb-admin-node 支持两种初始化方式 ```javascript // 方式一 使用tcb对象调用api const tcb = require("tcb-admin-node"); tcb.init({ env: "xxx" }); const db = tcb.database(); const result = await db.collection("coll").where({}).get(); // 方式二 使用tcb.init() 得到的对象调用api const tcb = require("tcb-admin-node"); const app = tcb.init({ env: "xxx" }); const db = app.database(); const result = await db.collection("coll").where({}).get(); ``` - 使用 node-sdk 只支持 init 初始化实例 ```javascript // 只支持 使用tcb.init() 得到的对象调用api,方式一(使用require的对象直接调用api)被废弃 // database const tcb = require("@cloudbase/node-sdk"); const app = tcb.init({ env: "xxx" }); const db = app.database(); const result = await db.collection("coll").where({}).get(); // function const result = await app.callFunction({ name: "test", data: { a: 1 }, }); // storage const result = await app.uploadFile({ cloudPath: "a|b测试.jpeg", fileContent, }); ``` > 实例必须由 init 方法生成,然后由实例调用 api 方法,多次 init 将会得到多个不同实例 > ⚠️ 使用 node-sdk 库时,请务必使用 init 方法初始化的实例 来调用 api,否则会导致报错 ## 错误处理变动 示例如下: - 使用 tcb-admin-node sdk 时的错误处理 ```javascript const tcb = require("tcb-admin-node"); tcb.init({ env: "xxx" }); const result = await app.callFunction({ name: "test", data: { a: 1 }, }); if (result.code) { // 函数执行报错,此处填写对sdk错误进行处理的逻辑 } ``` - 使用 node-sdk 时的错误处理 ```javascript const tcb = require("tcb-admin-node"); const app = tcb.init({ env: "xxx" }); let result; try { result = await app.callFunction({ name: "test", data: { a: 1 }, }); } catch (e) { console.log(e.code, e.message); // 函数执行报错,此处填写对sdk错误进行处理的逻辑 } ``` 自定义超时时间 数据库相关 示例如下: ```javascript // database const tcb = require("@cloudbase/node-sdk"); const app = tcb.init({ env: "xxx" }); const db = app.database(); const queryDocumentOpts = { timeout: 5000, }; // 举例:查询文档 const result = await db .collection("coll") .where({}) .options({ timeout: 10000 }) .get(); ``` 函数相关 ```javascript // function const tcb = require("@cloudbase/node-sdk"); const app = tcb.init({ env: "xxx" }); const functionOpts = { timeout: 5000, }; const result = await app.callFunction( { name: "test", data: { a: 1 }, }, functionOpts ); ``` 存储相关 ```javascript // storage 上传文件 const tcb = require("@cloudbase/node-sdk"); const app = tcb.init({ env: "xxx" }); const uploadFileOpts = { timeout: 5000, }; const result = await app.uploadFile( { cloudPath: "a|b测试.jpeg", fileContent, }, uploadFileOpts ); ``` 其他文件存储接口的自定义超时设置请参考[文件存储接口详细文档](./storage) --- ## 云存储 # 云存储 ## uploadFile #### 1. 接口描述 接口功能:上传文件到文件管理服务 接口声明:`uploadFile(object: Object): Promise` #### 2. 输入参数 | 字段 | 类型 | 必填 | 说明 | | ----------- | ------------- | ---- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | cloudPath | String | 是 | 文件的绝对路径,包含文件名。例如 foo/bar.jpg、foo/bar/baz.jpg 等,不能包含除[0-9 , a-z , A-Z]、/、!、-、\_、.、、\*和中文以外的字符,使用 / 字符来实现类似传统文件系统的层级结构。[查看详情](https://cloud.tencent.com/document/product/436/13324) | | fileContent | fs.ReadStream | 是 | buffer 或要上传的文件[可读流](https://nodejs.org/api/stream.html#stream_class_stream_readable) | #### 3. 返回结果 | 字段 | 类型 | 必填 | 说明 | | --------- | ------ | ---- | --------------------------------------- | | fileID | string | 否 | 文件唯一 ID,用来访问文件,建议存储起来 | | requestId | string | 是 | 请求序列号,用于错误排查 | | code | string | 否 | 状态码,操作成功则不返回 | | message | string | 否 | 错误描述,操作成功则不返回 | #### 4. 示例代码 ```javascript // 初始化 const tcb = require("@cloudbase/node-sdk"); const fs = require("fs"); const app = tcb.init({ env: "xxx", }); exports.main = async (event, context) => { const result = await app.uploadFile({ cloudPath: "test-admin.jpeg", fileContent: fs.createReadStream(`${__dirname}/cos.jpeg`), }); console.log(result.fileID); // 输出文件ID }; ``` ## getTempFileURL #### 1. 接口描述 接口功能:获取文件 CDN 下载链接 接口声明:`getTempFileURL(object: IGetTempFileURLOpts, opts: Object): Promise` #### 2. 输入参数 | 字段 | 类型 | 必填 | 说明 | | ------ | ------------------- | ---- | ----------------------------------------------------- | | object | IGetTempFileURLOpts | 是 | 获取下载链接请求参数 | | opts | Object | 否 | 自定义配置,目前只支持超时时间设置,{timeout: number} | ##### IGetTempFileURLOpts | 字段 | 类型 | 必填 | 说明 | | -------- | -------------------------------- | ---- | -------------------------- | | fileList | <Array>.string Or fileItem | 是 | 要下载的文件 ID 组成的数组 | ##### fileItem | 字段 | 类型 | 必填 | 说明 | | ------ | ------ | ---- | -------------- | | fileID | string | 是 | 文件 ID | | maxAge | number | 是 | 文件链接有效期 | #### 3. 返回结果 | 字段 | 类型 | 必填 | 说明 | | --------- | ------------------------- | ---- | ---------------------------- | | fileList | <Array>.fileUrlItem | 否 | 存储下载链接的数组 | | requestId | string | 是 | 请求序列号,用于错误排查 | | code | string | 否 | 状态码,操作成功则为 SUCCESS | | message | string | 否 | 错误描述 | ##### fileUrlItem | 字段 | 类型 | 必填 | 说明 | | ----------- | ------ | ---- | ------------------------ | | code | string | 否 | 删除结果,成功为 SUCCESS | | fileID | string | 是 | 文件 ID | | tempFileURL | string | 是 | 文件访问链接 | #### 4. 示例代码 ```javascript // 初始化 const tcb = require("@cloudbase/node-sdk"); const app = tcb.init({ env: "xxx", }); exports.main = async (event, context) => { const result = await app.getTempFileURL({ fileList: ["cloud://test-28farb/a.png"], }); result.fileList.forEach((item) => { console.log(item.tempFileURL); // 打印文件访问链接 }); }; ``` ## deleteFile #### 1. 接口描述 接口功能:删除文件 接口声明:`deleteFile(object: IDeleteFileOpts, opts: Object): Promise` #### 2. 输入参数 | 字段 | 类型 | 必填 | 说明 | | ------ | --------------- | ---- | ----------------------------------------------------- | | object | IDeleteFileOpts | 是 | 删除文件请求参数 | | opts | Object | 否 | 自定义配置,目前只支持超时时间设置,{timeout: number} | ##### IDeleteFileOpts | 字段 | 类型 | 必填 | 说明 | | -------- | -------------------- | ---- | -------------------------- | | fileList | <Array>.string | 是 | 要删除的文件 ID 组成的数组 | #### 3. 返回结果 | 字段 | 类型 | 必填 | 说明 | | --------- | ---------------------------- | ---- | ------------------------ | | code | string | 否 | 状态码,操作成功则不返回 | | message | string | 否 | 错误描述 | | fileList | <Array>.deleteFileItem | 否 | 删除结果组成的数组 | | requestId | string | 是 | 请求序列号,用于错误排查 | ##### deleteFileItem | 字段 | 类型 | 必填 | 说明 | | ------ | ------ | ---- | ------------------------ | | code | string | 否 | 删除结果,成功为 SUCCESS | | fileID | string | 是 | 文件 ID | #### 4. 示例代码 ```javascript // 初始化 const tcb = require("@cloudbase/node-sdk"); const app = tcb.init({ env: "xxx", }); exports.main = async (event, context) => { const result = await app.deleteFile({ fileList: ["HHOeahVQ0fRTDsums4GVgMCsF6CE3wb7kmIkZbX+yilTJE4NPSQQW5EYks"], }); result.fileList.forEach((item) => { if (item.code === "SUCCESS") { // 文件删除成功 } }); }; ``` ## downloadFile #### 1. 接口描述 接口功能:下载文件到本地 接口声明:`downloadFile(object: IDownloadFileOpts, opts: Object): Promise` #### 2. 输入参数 | 字段 | 类型 | 必填 | 说明 | | ------ | ----------------- | ---- | ----------------------------------------------------- | | object | IDownloadFileOpts | 是 | 下载文件请求参数 | | opts | Object | 否 | 自定义配置,目前只支持超时时间设置,{timeout: number} | ##### IDownloadFileOpts | 字段 | 类型 | 必填 | 说明 | | ------------ | ------ | ---- | ---------------------- | | fileID | string | 是 | 要下载的文件的 id | | tempFilePath | string | 否 | 下载的文件要存储的位置 | #### 3. 返回结果 | 字段 | 类型 | 必填 | 说明 | | ----------- | ------ | ---- | ------------------------------------------------------ | | code | string | 否 | 状态码,操作成功则不返回 | | message | string | 否 | 错误描述 | | fileContent | buffer | 否 | 下载的文件的内容。如果传入 tempFilePath 则不返回该字段 | | requestId | string | 是 | 请求序列号,用于错误排查 | #### 4. 示例代码 ```javascript // 初始化 const tcb = require("@cloudbase/node-sdk"); const app = tcb.init({ env: "xxx", }); exports.main = async (event, context) => { const result = await app.downloadFile({ fileID: "cloud://aa-99j9f/my-photo.png", // tempFilePath: '/tmp/test/storage/my-photo.png' }); // 未传入tempFilePath 可打印fileContent, 传入则进入对应目录查看文件 console.log(result.fileContent); }; ``` ## copyFile #### 1. 接口描述 接口功能:批量复制文件 接口声明:`copyFile({ fileList }: { fileList: ICopyFileParam[] }): Promise` :::tip 注意 该操作不会对文件的权限进行更改。 ::: #### 2. 输入参数 | 字段 | 类型 | 必填 | 说明 | | -------- | ---------------------------- | ---- | -------------------------- | | fileList | <Array>.ICopyFileParam | 是 | 要复制的文件信息组成的数组 | `ICopyFileParam`: | 字段 | 类型 | 必填 | 说明 | | -------------- | ------- | ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | srcPath | string | 是 | 源文件的绝对路径,包含文件名。例如 foo/bar.jpg、foo/bar/baz.jpg 等,不能包含除[0-9 , a-z , A-Z]、/、!、-、\_、.、、\*和中文以外的字符,使用 / 字符来实现类似传统文件系统的层级结构 | | dstPath | string | 是 | 目标文件的绝对路径,包含文件名。例如 foo/bar.jpg、foo/bar/baz.jpg 等,不能包含除[0-9 , a-z , A-Z]、/、!、-、\_、.、、\*和中文以外的字符,使用 / 字符来实现类似传统文件系统的层级结构 | | overwrite | boolean | 否 | 当目标文件已经存在时,是否允许覆盖已有文件,默认 true | | removeOriginal | boolean | 否 | 复制文件后是否删除源文件,默认 false | #### 3. 返回结果 | 字段 | 类型 | 必填 | 说明 | | --------- | -------------------------------------------------------------- | ---- | ------------------------------------------------------------------------------------------------------------------------- | | requestId | string | 是 | 请求序列号,用于错误排查 | | fileList | <Array>.{fileId?: string,code?: string,message?: string} | 是 | 请求结果列表。若该请求成功,fileId 为文件 id,如 cloud://xxx.yyy/abc.png;若该请求失败,返回 code 和 message 描述错误信息 | #### 4. 示例代码 ```javascript // 初始化 sdk const tcb = require("@cloudbase/node-sdk"); const app = tcb.init({ env: "xxx", // 填入环境 ID }); const path = "a.png"; // 填入源文件路径 const fileList = [ { srcPath: path, dstPath: `dst/${path}`, // 填入目标文件路径 removeOriginal: true, // 复制后删除源文件,等效为移动文件 }, ]; const result = await app.copyFile({ fileList }); ``` --- ## 消息通知 # 消息通知 ## 能力介绍 “消息通知”是云开发工作台提供的一种消息通知能力,开发者可根据自定义通知策略,在满足相关通知触发规则时,进行包括不限于站内信、短信等渠道的消息通知发送。 ## 能力特征 ### 通知策略管理 * 包含当前环境下所有消息通知策略,可进行策略的启停、编辑、删除(通知策略失效并不可恢复)。 * 通知策略主要构成部分包含监控类型、触发动作、触发条件、通知内容、通知对象、通知渠道。 ### 通知触发历史 * 成功触发的通知消息记录,支持以时间维度进行消息通知的记录查询。 * 支持历史通知消息的查看与删除(不可恢复)。 ## 使用说明 ### 1.自动触发 1. 前往工作台-数据管理,新建目标监控数据模型“消息通知”,以姓名(name)和年龄(age)字段为触发条件示例。 ![image.png](https://qcloudimg.tencent-cloud.cn/raw/454a0d9782726a4f15b4d8c25375bb53.png) 2. 前往工作台-消息通知管理,新建通知策略。 ![image.png](https://qcloudimg.tencent-cloud.cn/raw/92aae5011b51a28899336b3b2727a66c.png) 3. 编辑通知策略相关信息,例如设置数据模型触发动作为新增数据,触发条件为“name=rocky并且age >55“,那么当目标数据模型新增的数据满足此条件时,才会触发通知消息。 ![image.png](https://qcloudimg.tencent-cloud.cn/raw/4490ac7764075ccb88ec96c2adc09630.png) * 触发方式:自动触发和手动触发(默认为自动触发)。 * 监控类型:目前支持“数据模型”,模型名选择预先创建好的数据模型,触发动作包含数据的增删改,触发条件支持同时设置多个字段。 * 通知机制:实时推送。 * 通知内容:根据多行输入框里面的提示内容,填写相应的文案,其中双大括号“{{}}”表示模板变量,用来引用数据模型字段值。 * 通知用户:表示可接收到通知消息的用户对象,可在工作台-用户权限管理添加更多用户。 ![](https://qcloudimg.tencent-cloud.cn/raw/9a6a1c823ed6967748c1b3f30a186c00.png) * 通知渠道:目前支持工作台站内信和短信(以通知用户绑定的手机号为推送对象)通知。 4. 配置好相关信息后,保存通知策略。 ![image.png](https://qcloudimg.tencent-cloud.cn/raw/9fa88a67d9b4d10614df03b0612edaf2.png) 5. 前往数据模型管理界面,在模板模型中新增数据,进行消息通知推送测试。 ![image.png](https://qcloudimg.tencent-cloud.cn/raw/06f5abaeb42f88556617581acfcbb4fd.png) 6. 通知策略触发成功后,工作台会收到站内通知。 ![image.png](https://qcloudimg.tencent-cloud.cn/raw/bf75f427a4daf8b9cd73b4eac4d7cfbb.png) 7. 站内信消息面板,可以查询全部类型消息,包括监控告警和业务消息。 ![image.png](https://qcloudimg.tencent-cloud.cn/raw/ea190e3b0086513be099e558f721a969.png) 8. 手机短信通知展示。 ![image.png](https://qcloudimg.tencent-cloud.cn/raw/7301673bc3721b08a125335a05c9eae1.png) 9. 可以在消息通知管理界面,查询消息通知触发历史。 ![image.png](https://qcloudimg.tencent-cloud.cn/raw/ae64798c1639829bce52f4e0c2865556.png) ### 2.手动触发(SDK触发) #### **1. 接口介绍** * 接口描述:可在 [微信云开发云后台 / 消息通知管理](https://tcb.cloud.tencent.com/cloud-admin/#/management/notification/policyList) 模块配置消息策略,触发方式选择“手动触发”,需要在业务代码中主动调用,才会触发消息通知。 ![image.png](https://qcloudimg.tencent-cloud.cn/raw/a98ff0430a3361c2c40ee7318ae70597.png) * 接口功能:发送通知消息。 * 接口声明:`sendTemplateNotification(params: ITemplateNotifyReq, opts?: ICustomReqOpts)`。 #### **2. 输入参数** | 字段 | 类型 | 必填 | 说明 | | -------- | -------------------- | ---- | -------------------------------------------------------------- | | `params` | `ITemplateNotifyReq` | 是 | 请求参数 | | `opts` | `ICustomReqOpts` | 否 | 自定义配置,目前支持 SDK 请求超时时间设置,`{timeout: number}` | `ITemplateNotifyReq` | 字段 | 类型 | 必填 | 说明 | | ---------- | ------------------------- | ---- | ------------------------------------ | | `notifyId` | `string` | 是 | 告警策略 Id | | `data` | `Record` | 否 | 告警策略中模板变量键值对 | | `url` | `string` | 否 | 用户收到告警消息后点击打开的页面地址 | #### **3. 返回结果** `Promise>` | 字段 | 类型 | 必填 | 说明 | | ----------- | --------- | ---- | ------------------------- | | `result` | `ResultT` | 否 | 执行结果 | | `requestId` | `string` | 否 | 请求唯一 Id,用于错误排查 | > 代码执行报错,将通过异常抛出 #### **4. 示例代码** ```ts // 云函数入口文件 const tcb = require("@cloudbase/node-sdk"); const app = tcb.init({ secretId: "", // 腾讯云 API 固定密钥对,在云函数内执行可不填 secretKey: "", // 同上 env: "", // 云开发环境id }); exports.main = async (event, context) => { const result = await app.sendTemplateNotification({ notifyId: "xxx", data: { orderId: "aaa", amount: 200 }, url: "https://cloud.tencent.com/solution/la", }); return result; }; ``` :::info说明 云开发数据库支持监听集合中符合查询条件的数据的更新事件,更多可参考文档 [实时推送](https://docs.cloudbase.net/database/realtime) ::: --- ## 跨端开发 # 跨端开发 @cloudbase/js-sdk 只支持常规 Web 应用(即浏览器环境)的开发,不兼容其他类 Web 平台,比如微信小程序、快应用、Cocos 等。虽然这些平台大多支持 JavaScript 运行环境,但在网络请求、本地存储、平台标识等特性上与浏览器环境有明显差异。针对这些差异特性,@cloudbase/js-sdk 提供一套完整的适配扩展方案,遵循此方案规范可开发对应平台的适配器,然后搭配 @cloudbase/js-sdk 和适配器实现平台的兼容性。 ## 适配规范 开发适配器之前需要安装官方提供的接口声明模块[`@cloudbase/adapter-interface`](https://www.npmjs.com/package/@cloudbase/adapter-interface): ```bash # npm npm i @cloudbase/adapter-interface # yarn yarn add @cloudbase/adapter-interface ``` 适配器模块需要导出一个`adapter`对象: ```js const adapter = { genAdapter, isMatch, // runtime标记平台唯一性 runtime: '平台名称' }; export adapter; export default adapter; ``` 必须包含以下三个字段: - `runtime`: `string`,平台的名称,用于标记平台唯一性; - `isMatch`: `Function`,判断当前运行环境是否为平台,返回`boolean`值; - `genAdapter`: `Function`,创建`adapter`实体。 ### runtime `runtime`用于标记平台的唯一性,建议尽量以平台的英文名称或简写命名,比如百度小程序`baidu_miniapp`、QQ 小程序`qq_miniapp`等等。 ### isMatch `isMatch`函数用于判断当前运行环境是否与适配器匹配,通常是通过判断平台特有的一些全局变量、API 等。比如以下代码是判断运行环境是否为 Cocos 原生平台: ```js function isMatch(): boolean { if (typeof cc === "undefined") { return false; } if (typeof WebSocket === "undefined") { return false; } if (typeof XMLHttpRequest === "undefined") { return false; } if (!cc.game) { return false; } if (typeof cc.game.on !== "function") { return false; } if (!cc.game.EVENT_HIDE) { return false; } if (!cc.game.EVENT_SHOW) { return false; } if (!cc.sys) { return false; } if (!cc.sys.isNative) { return false; } return true; } ``` ### genAdapter `genAdapter`函数返回适配器的实体对象,结构如下: ```typescript interface SDKAdapterInterface { // 全局根变量,浏览器环境为window root: any; // WebSocket类 wsClass: WebSocketContructor; // request类 reqClass: SDKRequestConstructor; // 无localstorage时persistence=local降级为none localStorage?: StorageInterface; // 无sessionStorage时persistence=session降级为none sessionStorage?: StorageInterface; // storage模式首选,优先级高于persistence primaryStorage?: StorageType; // 获取平台唯一应用标识的api getAppSign?(): string; } ``` ### 示例 ```typescript import { AbstractSDKRequest, IRequestOptions, IUploadRequestOptions, StorageInterface, WebSocketInterface, WebSocketContructor, SDKAdapterInterface, StorageType, formatUrl, } from "@cloudbase/adapter-interface"; // isMatch函数判断当前平台是否匹配 function isMatch(): boolean { // ... return true; } // Request类为平台特有的网络请求,必须实现post/upload/download三个public接口 export class Request extends AbstractSDKRequest { // 实现post接口 public post(options: IRequestOptions) { return new Promise((resolve) => { // ... resolve(); }); } // 实现upload接口 public upload(options: IUploadRequestOptions) { return new Promise((resolve) => { // ... resolve(); }); } // 实现download接口 public download(options: IRequestOptions) { return new Promise((resolve) => { // ... resolve(); }); } } // Storage为平台特有的本地存储,必须实现setItem/getItem/removeItem/clear四个接口 export const Storage: StorageInterface = { setItem(key: string, value: any) { // ... }, getItem(key: string): any { // ... }, removeItem(key: string) { // ... }, clear() { // ... }, }; // WebSocket为平台特有的WebSocket,与HTML5标准规范一致 export class WebSocket { constructor(url: string, options: object = {}) { const socketTask: WebSocketInterface = { set onopen(cb) { // ... }, set onmessage(cb) { // ... }, set onclose(cb) { // ... }, set onerror(cb) { // ... }, send: (data) => { // ... }, close: (code?: number, reason?: string) => { // ... }, get readyState() { // ... return readyState; }, CONNECTING: 0, OPEN: 1, CLOSING: 2, CLOSED: 3, }; return socketTask; } } // genAdapter函数创建adapter实体 function genAdapter() { const adapter: SDKAdapterInterface = { // root对象为全局根对象,没有则填空对象{} root: window, reqClass: Request, wsClass: WebSocket as WebSocketContructor, localStorage: Storage, // 首先缓存存放策略,建议始终保持localstorage primaryStorage: StorageType.local, // sessionStorage为可选项,如果平台不支持可不填 sessionStorage: sessionStorage, }; return adapter; } // 三者缺一不可 const adapter = { genAdapter, isMatch, // runtime标记平台唯一性 runtime: "平台名称", }; export default adapter; ``` ## 接入流程 ### 第 1 步:安装并引入适配器 安装 @cloudbase/js-sdk 和所需平台的适配器,比如 QQ 小游戏平台: ```bash # 安装 @cloudbase/js-sdk npm i @cloudbase/js-sdk # 安装 QQ 小游戏适配器 npm i cloudbase-adapter-qq_game ``` 然后在业务代码中将引入适配器: ```js import cloudbase from "@cloudbase/js-sdk"; import adapter from "cloudbase-adapter-qq_game"; cloudbase.useAdapters(adapter); ``` ### 第 2 步:配置安全应用来源 云开发需验证请求来源的合法性,常规 Web 通过验证安全域名,而由于上文提到的诸多类 Web 环境并没有域名的概念,所以需要借助安全应用凭证区分请求来源是否合法。 登录 [云开发平台](https://tcb.cloud.tencent.com/dev) ,在 [安全来源](https://tcb.cloud.tencent.com/dev#/env/safety-source) 页面中的**移动应用安全来源**一栏,点击“**添加应用**”按钮,输入应用标识。 :::tip 应用标识必须是能够标记应用唯一性的信息,比如微信小程序的`appId`、移动应用的包名等。 ::: 添加成功后会创建一个安全应用的信息,如下图所示: ![](https://main.qcloudimg.com/raw/6542df6800b71b91289bebc29d38de94.png) ### 第 3 步:初始化云开发 在业务代码中初始化云开发时将第 2 步配置的安全应用信息作为参数传递给 `init` 方法: ```js import cloudbase from '@cloudbase/js-sdk'; import adapter from 'cloudbase-adapter-qq_game'; cloudbase.useAdapters(adapter); cloudbase.init({ env: '环境ID', appSign: '应用标识', appSecret: { appAccessKeyId: '应用凭证版本号' appAccessKey: '应用凭证' } }) ``` - `appSign`:`string`,应用标识,对应上图中“应用标识”一栏; - `appSecret`:`Object`,应用凭证信息,包括以下字段: - `appAccessKeyId`:`string`,对应上图中“版本”一栏,**同一个应用标识可以最多可以添加两个版本的凭证信息**,以便区分开发和生产环境; - `appAccessKey`:`string`,对应上图中“操作”一栏点击“获取凭证”之后获取到的信息。 :::tip `appAccessKey`和`appAccessKeyId`必须一一对应。 ::: ### 第 4 步:编写业务代码 经过以上准备工作之后便可以编写自身的业务代码。 ## 一套代码多端适配 如果您需要将一套代码兼容多种平台,tcb-js-sdk 可以同时引入多个适配器,在运行时通过各适配器的`isMatch`函数判断平台类型,然后引入对应的兼容逻辑。比如以下代码可以同时兼容 QQ 小游戏、 Cocos 原生和百度小游戏三种平台: ```js import cloudbase from '@cloudbase/js-sdk'; import adapter as adapterOfQQGame from 'cloudbase-adapter-qq_game'; import adapter as adapterOfCocosNative from 'cloudbase-adapter-cocos_native'; import adapter as adapterOfBDGame from 'cloudbase-adapter-bd_game'; cloudbase.useAdapters([ adapterOfQQGame, adapterOfCocosNative, adapterOfBDGame ]); ``` --- ## 广告数据上报 # 广告数据上报 ## analytics #### 1. 接口描述 接口功能:上报广告数据 接口声明:`analytics(object: Object): Promise` :::tip 提示 自 SDK 1.4.0 版本起支持此接口,使用时需结合微信授权登录使用 ::: #### 2. 输入参数 | 字段 | 类型 | 必填 | 说明 | | ----------- | ----------- | ---- | ------------------------- | | report_type | string | 是 | 上报类型,目前支持 "mall" | | report_data | IReportData | 是 | 上报内容 | ##### IReportData | 字段 | 类型 | 必填 | 说明 | | ------------- | ------------- | ---- | ------------------------------------------------------------------------------------------------ | | action_time | number | 否 | 上报时间,不填默认取当前客户端时间,单位为秒 | | action_type | string | 是 | 行为类型 如 访问 visit_store,分享 share,加入购物车 add_to_cart 等,详细类型参考表 action_types | | click_id | string | 否 | 广告平台会在 URL 增加 click_id,取值方式[参考](https://ad.weixin.qq.com/guide/457) | | action_param | IActionParam | 否 | 行为所带的参数 | | product_param | IProductParam | 否 | 商品结构内容 | ##### IActionParam | 字段 | 类型 | 必填 | 说明 | | ---------- | ------ | ---- | --------------------------------------------------------- | | value | number | 否 | 行为所带的参数,转化行为价值(例如金额) | | leads_type | string | 否 | 行为来源,目前支持 PHONE(电话直呼),RESERVE(表单预约) | ##### IProductParam | 字段 | 类型 | 必填 | 说明 | | ----------------------- | ------ | ---- | ---------------------------------------------- | | product_yun_type | string | 否 | 商品 goods ,优惠券 coupon, 搜索词 search_term | | product_yun_id | string | 否 | 商品 id | | product_yun_category | string | 否 | 商品类目 自定义 | | product_yun_keywords | string | 否 | 商品关键词 | | product_yun_price | number | 否 | 商品原价 | | product_yun_value | number | 否 | 商品成交价 | | product_yun_name | string | 否 | 商品名 | | product_yun_id_ad | string | 否 | 广告商品库中商品 id | | product_yun_category_ad | string | 否 | 广告商品库中商品类目 | ##### action_types | 类型值 | 说明 | | --------------- | ---------- | | visit_store | 访问 | | share | 分享 | | consult | 咨询 | | claim_offer | 卡券领取 | | add_to_cart | 加入购物车 | | add_to_wishlist | 收藏 | | complete_order | 下单 | | purchase | 支付 | | search | 搜索 | | deliver | 发货 | | sign_in | 签收 | #### 3. 输出参数 无 #### 4. 示例代码 ```javascript import cloudbase from "@cloudbase/js-sdk"; //初始化SDK实例 const app = cloudbase.init({ env: "xxxx-yyy" }); // 微信授权登录 const provider = auth.weixinAuthProvider({ appid: "...", scope: "xxxx" }); provider.getRedirectResult().then((loginState) => { if (loginState) { // 登录成功! app.analytics({ report_type: "mall", report_data: { action_type: "visit_store", action_param: { value: 100 }, product_param: { product_yun_type: "goods", product_yun_id: 1, product_yun_keywords: "优衣库", product_yun_price: 200, product_yun_value: 100, product_yun_name: "优衣库Utee-迪士尼" } } }); } }); ``` --- ## 登录认证 # 登录认证 ## app.auth() #### 接口描述 返回 [`Auth`](#auth) 对象 签名:`auth({ persistence: string }): Auth` #### 输入参数 | 字段 | 类型 | 必填 | 说明 | | ----------- | ------ | ---- | ------------------------------------------------------------------------------------- | | persistence | string | 否 | 身份认证状态如何持久保留,有三个选项 `local`、`session` 和 `none`,默认为 `session`。 | - `local`:在显式退出登录之前的 30 天内保留身份验证状态 - `session`:在窗口关闭时清除身份验证状态 - `none`:在页面重新加载时清除身份验证状态 #### 示例代码 ```js import cloudbase from "@cloudbase/js-sdk"; const app = cloudbase.init({ env: "xxxx-yyy", }); const auth = app.auth({ persistence: "local", //用户显式退出或更改密码之前的30天一直有效 }); ``` ## Auth ### Auth.currentUser #### 接口描述 返回表示当前用户的 [`User`](#user) 实例 #### 示例代码 ```js const app = cloudbase.init({ env: "xxxx-yyy", }); // 执行某种登录之后... const user = app.auth().currentUser; ``` ### Auth.getCurrenUser() :::tip 提示 自 1.8.x 版本起接口更名为 Auth.getCurrentUser ::: #### 接口描述 `Auth.currentUser`的异步操作,返回表示当前用户的 [`User`](#user) 实例 签名:`getCurrenUser(): Promise` #### 示例代码 ```js const app = cloudbase.init({ env: "xxxx-yyy", }); // 执行某种登录之后... app .auth() .getCurrenUser() .then((user) => { // ... }); ``` ### Auth.hasLoginState() #### 接口描述 返回当前登录状态 [`LoginState`](#loginstate),如果未登录,则返回 null 签名:`hasLoginState(): LoginState | null` #### 示例代码 ```js const app = cloudbase.init({ env: "xxxx-yyy", }); const loginState = app.auth().hasLoginState(); if (loginState) { // 登录态有效 } else { // 没有登录态,或者登录态已经失效 } ``` ### Auth.getLoginState() #### 接口描述 `Auth.hasLoginState()`的异步操作,返回当前登录状态 [`LoginState`](#loginstate),如果未登录,则返回 null 签名:`getLoginState(): Promise` :::tip 提示 此 API 是 `hasLoginState` 的异步模式,适用于本地存储为异步的平台,比如 React Native ::: #### 示例代码 ```js const app = cloudbase.init({ env: "xxxx-yyy", }); const loginState = app .auth() .getLoginState() .then((loginState) => { if (loginState) { // 登录态有效 } else { // 没有登录态,或者登录态已经失效 } }); ``` ### Auth.weixinAuthProvider() #### 接口描述 获取用于微信登录的 [WeixinAuthProvider](#weixinauthprovider) 签名:`weixinAuthProvider({ appid: string, scope: string }): WeixinAuthProvider` | 字段 | 类型 | 必填 | 说明 | | ----- | ------ | ---- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | | appid | string | 是 | 微信公众平台(或开放平台)应用的 appid。 | | scope | string | 是 | 网页授权类型,可选值为 `snsapi_base`(公众平台,只获取用户的 openid)、`snsapi_userinfo`(公众平台,获取用户的基本信息)和 `snsapi_login`(开放平台网页授权)。 | #### 示例代码 ```javascript const app = cloudbase.init({ env: "xxxx-yyy", }); const provider = app.auth().weixinAuthProvider({ appid: "your-appid", scope: "snsapi_base", }); provider.getRedirectResult().then((loginState) => { if (loginState) { // 登录成功,本地已存在登录态 } else { // 未登录,唤起微信登录 provider.signInWithRedirect(); } }); ``` ### Auth.customAuthProvider() #### 接口描述 获取用于自定义登录的 [CustomAuthProvider](#customauthprovider) 签名:`customAuthProvider(): CustomAuthProvider` #### 示例代码 ```javascript // 将 your-envId 替换成您的环境 ID const app = cloudbase.init({ env: "your-envId", }); async function login() { // 获取自定义登录 ticket // 将 your-api 替换成获取 ticket 的 URL const ticket = await fetch("your-api"); app .auth({ persistence: "session", }) .customAuthProvider() .signIn(ticket) .then(() => { // 登录成功 }) .catch((err) => { // 登录失败 }); } login(); ``` ### Auth.anonymousAuthProvider() #### 接口描述 获取用于匿名登录的 [AnonymousAuthProvider](#anonymousauthprovider) 签名:`anonymousAuthProvider(): AnonymousAuthProvider` #### 示例代码 ```javascript const app = cloudbase.init({ env: "xxxx-yyy", }); app .auth({ persistence: "session", }) .anonymousAuthProvider() .signIn() .then(() => { // 登录成功 }) .catch((err) => { // 登录失败 }); ``` ### Auth.signUpWithEmailAndPassword() #### 接口描述 使用邮箱和密码注册一个云开发账户,调用后,会自动向注册邮箱发送**邮箱验证邮件**。 签名:`signUpWithEmailAndPassword(email: string, password: string): Promise` #### 示例代码 ```js const app = cloudbase.init({ env: "xxxx-yyy", }); const auth = app.auth(); const email = "foo@bar.com"; const password = "your_awesome_password"; auth.signUpWithEmailAndPassword(email, password).then(() => { // 发送验证邮件成功 }); ``` ### Auth.signInWithEmailAndPassword() #### 接口描述 使用邮箱和密码登录云开发。 签名:`signInWithEmailAndPassword(email: string, password: string): Promise` #### 示例代码 ```js const app = cloudbase.init({ env: "xxxx-yyy", }); const auth = app.auth(); const email = "foo@bar.com"; const password = "your_awesome_password"; auth.signInWithEmailAndPassword(email, password).then((loginState) => { // 邮箱密码登录成功 }); ``` ### Auth.sendPasswordResetEmail() #### 接口描述 发送重置密码的邮件。 签名:`sendPasswordResetEmail(email: string): Promise` #### 示例代码 ```js const app = cloudbase.init({ env: "xxxx-yyy", }); const auth = app.auth(); const email = "foo@bar.com"; auth.sendPasswordResetEmail(email).then(() => { // 发送重置密码邮件成功 }); ``` ### Auth.signInWithUsernameAndPassword() #### 接口描述 使用用户名密码登录云开发。 签名:`signInWithUsernameAndPassword(username: string, password: string): Promise` #### 示例代码 ```js const app = cloudbase.init({ env: "xxxx-yyy", }); const auth = app.auth(); const username = "your_awesome_username"; const password = "your_awesome_password"; auth.signInWithUsernameAndPassword(username, password).then((loginState) => { // 用户名密码登录成功 }); ``` ### Auth.isUsernameRegistered() #### 接口描述 检查用户名是否被绑定过。 签名:`isUsernameRegistered(username: string): Promise` #### 示例代码 ```js const app = cloudbase.init({ env: "xxxx-yyy", }); const auth = app.auth(); const username = "your_awesome_username"; auth.isUsernameRegistered(username).then((registered) => { // }); ``` ### Auth.sendPhoneCode() #### 接口描述 发送手机验证码。 签名:`sendPhoneCode(phoneNumber: string): Promise` #### 示例代码 ```js const app = cloudbase.init({ env: "xxxx-yyy", }); const auth = app.auth(); auth.sendPhoneCode("18600000000").then((res) => { if (res === true) { console.log("验证码发送成功!"); } }); ``` ### Auth.signUpWithPhoneCode() #### 接口描述 手机号注册(支持短信验证码+密码方式)。 签名:`signUpWithPhoneCode(phoneNumber: string,phoneCode: string,password?: string): Promise` #### 示例代码 ```js const app = cloudbase.init({ env: "xxxx-yyy", }); const auth = app.auth(); auth.signUpWithPhoneCode("18600000000", "000000", "12345678").then((res) => { // 注册成功 }); ``` ### Auth.signInWithPhoneCodeOrPassword() #### 接口描述 手机号登录(支持短信验证码 or 密码方式)。 签名:`signInWithPhoneCodeOrPassword({phoneNumber: string, phoneCode?: string, password?: string}): Promise` #### 示例代码 ```js const app = cloudbase.init({ env: "xxxx-yyy", }); const auth = app.auth(); // 手机短信验证码登录 auth .signInWithPhoneCodeOrPassword({ phoneNumber: "18600000000", phoneCode: "000000", }) .then((res) => { // 登录成功 }); // 手机密码登录 auth .signInWithPhoneCodeOrPassword({ phoneNumber: "18600000000", password: "12345678", }) .then((res) => { // 登录成功 }); ``` ### Auth.forceResetPwdByPhoneCode() #### 接口描述 手机号强制重置密码。 签名:`forceResetPwdByPhoneCode({phoneNumber: string, phoneCode: string, password: string}): Promise` :::tip 提示 自 @cloudbase/js-sdk@1.6.0 版本起支持此接口 ::: #### 示例代码 ```js const app = cloudbase.init({ env: "xxxx-yyy", }); const auth = app.auth(); // 手机短信验证码登录 auth .forceResetPwdByPhoneCode({ phoneNumber: "your phoneNumber", phoneCode: "code", password: "your password", }) .then((res) => { // 重置密码成功,自动获得登录态 }); ``` ### Auth.signOut() #### 接口描述 登出云开发 签名:`signOut(): Promise` #### 示例代码 ```js const app = cloudbase.init({ env: "xxxx-yyy", }); const auth = app.auth(); auth.signOut(); ``` ### Auth.getAuthHeader() #### 接口描述 获取 HTTP 鉴权头部,可用于 HTTP 访问云函数或者云托管时的鉴权。如果未登录,则返回 `null`。 签名:`getAuthHeader(): { "x-cloudbase-credentials": string } | null` :::tip 此接口获取的是本地的登录态,并不会判断登录态是否过期,如果担心登录态过期建议使用对应的异步接口`Auth.getAuthHeaderAsync()`。 ::: #### 示例代码 ```js const app = cloudbase.init({ env: "xxxx-yyy", }); const auth = app.auth(); auth.getAuthHeader(); // { "x-cloudbase-credentials": "......" } ``` ### Auth.getAuthHeaderAsync() #### 接口描述 `Auth.getAuthHeader()`的异步操作,获取 HTTP 鉴权头部,可用于 HTTP 访问云函数时的鉴权。如果未登录,则返回 `null`。 签名:`getAuthHeaderAsync(): Promise` :::tip 调用此接口会刷新本地登录态,不存在登录态过期问题。 ::: #### 示例代码 ```js const app = cloudbase.init({ env: "xxxx-yyy", }); const auth = app.auth(); auth.getAuthHeaderAsync().then((res) => { // { "x-cloudbase-credentials": "......" } }); ``` ### Auth.shouldRefreshAccessToken() #### 接口描述 接收一个回调函数,并且会在刷新短期访问令牌前调用此回调函数,根据返回值决定是否要刷新短期访问令牌。 对于两种登录态并存(Cloudbase、自身业务登录态)的 Web 应用,可以在回调函数内判断自身业务登录态是否失效,从而决定是否续期 Cloudbase 的短期访问令牌。 签名:`shouldRefreshAccessToken(callback: () => boolean): void` #### 示例代码 ```js auth.shouldRefreshAccessToken(() => { if (/* 自身业务登录态还有效 */) { return true; } else { return false; } }); ``` ### Auth.onLoginStateChanged() #### 接口描述 接收一个回调函数,并且会在登录状态改变时,调用此回调函数。 签名:`onLoginStateChanged(callback: (loginState: LoginState) => any): void` #### 示例代码 ```js auth.onLoginStateChanged((loginState) => { if (loginState) { // 有登录状态 } else { // 没有登录 } }); ``` ### Auth.onLoginStateExpired() #### 接口描述 接收一个回调函数,并且会在登录状态过期,调用此回调函数。 签名:`onLoginStateExpired(callback: Function): void` #### 示例代码 ```js auth.onLoginStateExpired(() => { // 此时登录状态过期,需要重新登录 }); ``` ### Auth.onAccessTokenRefreshed() #### 接口描述 接收一个回调函数,并且会在短期访问令牌刷新后,调用此回调函数。 签名:`onAccessTokenRefreshed(callback: Function): void` #### 示例代码 ```js auth.onAccessTokenRefreshed(() => { // 此时短期访问令牌已经被刷新 }); ``` ### Auth.onAnonymousConverted() #### 接口描述 接收一个回调函数,并且会在匿名登录状态被转换后,调用此回调函数。 签名:`onAnonymousConverted(callback: Function): void` #### 示例代码 ```js auth.onAnonymousConverted(() => { // 此时匿名登录状态已经被转换 }); ``` ### Auth.onLoginTypeChanged() #### 接口描述 接收一个回调函数,并且会在登录类型发生变化后,调用此回调函数。 签名:`onLoginTypeChanged(callback: Function): void` #### 示例代码 ```js auth.onLoginTypeChanged(() => { // 此时登录类型已经发生变化 }); ``` ## LoginState `LoginState` 对象是对用户当前的登录态的抽象 ### LoginState.loginType 类型:`string` 表示当前的登录类型 | 取值 | 含义 | | ------------- | ---------- | | `"ANONYMOUS"` | 匿名登录 | | `"WECHAT"` | 微信登录 | | `"CUSTOM"` | 自定义登录 | ### LoginState.user 类型:`User | null` 表示当前用户,具体请参考 [User](#user) 如果没有登录,则为 `null` ### LoginState.isAnonymousAuth 类型:`boolean` 表示当前是否为匿名登录 ### LoginState.isCustomAuth 类型:`boolean` 表示当前是否为自定义登录 ### LoginState.isWeixinAuth 类型:`boolean` 表示当前是否为微信登录 ### LoginState.isUsernameAuth 类型:`boolean` 表示当前是否为用户名密码登录 ## User `User` 对象是对云开发用户的抽象表示 ### User.uid 类型:`string` 云开发用户的全局唯一 ID ### User.loginType 类型:`string` 表示当前的登录类型 | 取值 | 含义 | | ------------- | ---------- | | `"ANONYMOUS"` | 匿名登录 | | `"WECHAT"` | 微信登录 | | `"CUSTOM"` | 自定义登录 | ### User.openid 类型:`string` 表示此用户绑定的微信 openid ### User.unionId 类型:`string` 表示此用户绑定的微信 unionId ### User.wxOpenId 表示此用户绑定的微信 openid ### User.wxPublicId 表示此用户绑定的微信开放平台 openid ### User.customUserId 表示此用户绑定的自定义登录 customUserId ### User.qqMiniOpenId 类型:`string` 表示此用户对应的 QQ 小程序 openid ### User.nickName 类型:`string` 用户昵称 ### User.gender 类型:`string` 用户性别,取值仅限于:`"MALE"`、`"FEMALE`、`"UNKNOWN"` ### User.avatarUrl 类型:`string` 用户头像 URL ### User.location 类型: `{ country: string; province: string; city: string }` 用户地理位置 ### User.username 类型:`string` 用户名 ### User.hasPassword 类型:`boolean` 是否设置了密码 ### User.update() #### 接口描述 更新用户信息 签名:`update(userInfo): Promise` #### 示例代码 ```js const user = auth.currentUser; user .update({ nickName: "王小黑", // 昵称,不超过 45 个字符 gender: "MALE", // 性别,取值仅限于 MALE、FEMALE、UNKNOWN avatarUrl: "https://...", // 头像地址,不超过 255 个字符 country: "中国", // 不超过 45 个字符 province: "广东", // 不超过 45 个字符 city: "深圳", // 不超过 45 个字符 }) .then(() => { // 更新用户信息成功 }); ``` ### User.refresh() #### 接口描述 刷新本地用户信息。当用户在其他客户端更新用户信息之后,可以调用此接口同步更新之后的信息。 签名:`refresh(): Promise` #### 示例代码 ```js const user = auth.currentUser; user.refresh().then(() => { // 刷新用户信息成功 }); ``` ### User.linkWithTicket() #### 接口描述 将当前账户与自定义登录 Ticket 进行绑定,绑定之后便可以通过自定义登录登录当前云开发账户。 签名:`linkWithTicket(ticket: string): Promise` #### 示例代码 ```js const user = auth.currentUser; // ticket 为获取到的自定义登录 Ticket user.linkWithTicket(ticket).then(() => { // 绑定成功 }); ``` ### User.linkWithRedirect() #### 接口描述 将当前账户与第三方鉴权提供方,以重定向的形式,进行绑定,绑定之后便可以通过第三方鉴权提供方登录当前的云开发账户。 签名:`linkWithRedirect(provider: AuthProvider): void` #### 示例代码 以绑定微信登录为例: ```js const user = auth.currentUser; const provider = auth.weixinAuthProvider({ appid: "....", scope: "snsapi_base", }); user.linkWithRedirect(provider); // 调用之后,网页会被重定向至第三方登录页面 ``` ### User.updatePassword() #### 接口描述 修改密码。如果用户之前没有设置过密码,那么无需填写 `oldPassword`。 签名:`updatePassword(newPassword: string, oldPassword?: string): Promise` #### 示例代码 ```js const user = auth.currentUser; user.updatePassword("new_password", "old_password").then(() => { // 更新密码成功 }); ``` ### User.updateEmail() 更新当前的登录邮箱,调用后会发送**验证邮件**到新邮箱,用户需要访问验证邮件中的激活链接来完成更新。 :::tip 注意 该接口还可用于其他登录方式(如匿名登录)绑定邮箱登录,若原登录方式未设置密码,需指定密码参数。(自 sdk 1.6.0 版本后支持) ::: #### 接口描述 修改登录邮箱。 签名:`updateEmail(newEmail: string, password?: string): Promise` #### 示例代码 ```js const user = auth.currentUser; user.updateEmail("new_email@foo.com").then(() => { // 发送验证邮件 }); ``` ```js // 匿名登录绑邮箱转正 import cloudbase from "@cloudbase/js-sdk"; const app = cloudbase.init({ env: "xxx", }); const auth = app.auth({ persistence: "local", }); async function login() { const loginState = await auth.getLoginState(); if (!loginState) { // 匿名登录 await auth.anonymousAuthProvider().signIn(); // 绑邮箱 const updateEmailRes = await auth.currentUser.updateEmail( "your email address", "your password" ); console.log("updateEmailRes", updateEmailRes); } } login(); ``` ### User.updateUsername() #### 接口描述 修改用户名。 签名:`updateUsername(newUsername: string): Promise` #### 示例代码 ```js const user = auth.currentUser; user.updateUsername("new_username").then(() => { // 修改成功 }); ``` ### User.linkWithPhoneNumber() #### 接口描述 绑定手机号 签名:`linkWithPhoneNumber(phoneNumber: string,phoneCode: string): Promise` #### 示例代码 ```js const user = auth.currentUser; user.linkWithPhoneNumber("18600000000", "000000").then(() => { // 修改成功 }); ``` ### User.updatePhoneNumber() #### 接口描述 更新手机号 签名:`updatePhoneNumber(phoneNumber: string,phoneCode: string): Promise` #### 示例代码 ```js const user = auth.currentUser; user.updatePhoneNumber("18600000000", "000000").then(() => { // 修改成功 }); ``` ### User.unlink() #### 接口描述 解绑某个登录方式。 签名:`unlink(loginType): Promise` | loginType 取值 | 含义 | | --------------- | ------------ | | `WECHAT-OPEN` | 微信开放平台 | | `WECHAT-PUBLIC` | 微信公众平台 | | `WECHAT-UNION` | 微信 UnionID | | `CUSTOM` | 自定义登录 | | `EMAIL` | 邮箱登录 | | `PHONE` | 手机号登录 | :::tip 注意 不能解绑当前登录方式 ::: #### 示例代码 ```js const user = auth.currentUser; user.unlink("CUSTOM").then(() => { // 解绑自定义登录成功 }); ``` ## WeixinAuthProvider ### WeixinAuthProvider.signInWithRedirect() #### 接口描述 跳转到微信登录页面。 :::tip 建议 推荐使用此接口搭配 [WeixinAuthProvider.getRedirectResult()](#weixinauthprovider-getredirectresult) 完成完整的登录流程。 ::: 签名:`signInWithRedirect(): void` #### 示例代码 ```js // 直接跳转到微信登录页面 app .auth() .weixinAuthProvider({ appid: "...", scope: "snsapi_base", }) .signInWithRedirect(); ``` ### WeixinAuthProvider.getRedirectResult() #### 接口描述 微信登录页面重定向回来后,使用重定向的返回值登录,并获取登录态。 签名:`getRedirectResult({ createUser?: boolean; syncUserInfo?: boolean }): Promise` | 参数名 | 含义 | 默认值 | | ------------ | -------------------------------------------------------------------- | ------- | | createUser | 当微信 openid 没有对应的云开发用户时,是否自动创建一个新的云开发用户 | `true` | | syncUserInfo | 同步微信账号信息作为云开发用户信息 | `false` | :::caution 为什么无法同步微信账号信息? 当 `syncUserInfo` 为 `true` ,并且网页授权类型为 `snsapi_userinfo` 或者 `snsapi_login` 时,才可以同步微信账号信息作为云开发用户信息。 ::: #### 示例代码 ```js const provider = app.auth().weixinAuthProvider({ appid: "...", scope: "snsapi_base", }); // 假设我们有一个“微信登录”按钮,点击后跳转登录页面 document.getElementById("login").onclick = function () { provider.signInWithRedirect(); }; // 如果页面含有微信的登录态,那么回调中会存在 LoginState provider.getRedirectResult().then((loginState) => { if (loginState) { // 有登录态 } }); ``` ### WeixinAuthProvider.getLinkRedirectResult() #### 接口描述 获取微信重定向绑定结果。如果 `withUnionId` 为 `true`,且存在微信 UnionID,则会一同绑定微信 UnionID。 签名:`getLinkRedirectResult({ withUnionId?: boolean }): Promise` #### 示例代码 ```js // 用户以任意一种登录方式(除微信登录)登录云开发之后 // 获取 Provider const auth = app.auth(); const provider = auth.weixinAuthProvider({ appid: "....", scope: "snsapi_base", }); // 重定向到提供方的页面进行登录 auth.currentUser.linkWithRedirect(provider); ``` 用户在微信的页面登录之后,会被重定向回您的页面。然后,可以在页面加载时通过调用 `Provider.getLinkRedirectResult()` 来获取关联结果: ```js provider.getLinkRedirectResult().then((result) => { // 关联成功 }); ``` ## CustomAuthProvider ### CustomAuthProvider.signIn() #### 接口描述 使用自定义登录凭据 `ticket` 登录云开发。 签名:`signIn(ticket: string): Promise` #### 示例代码 ```javascript // 将 your-envId 替换成您的环境 ID const app = cloudbase.init({ env: "your-envId", }); async function login() { // 获取自定义登录 ticket // 将 your-api 替换成获取 ticket 的 URL const ticket = await fetch("your-api"); app .auth({ persistence: "session", }) .customAuthProvider() .signIn(ticket) .then(() => { // 登录成功 }) .catch((err) => { // 登录失败 }); } login(); ``` ## AnonymousAuthProvider ### AnonymousAuthProvider.signIn() #### 接口描述 匿名登录云开发。 签名:`signIn(): Promise` #### 示例代码 ```javascript const app = cloudbase.init({ env: "xxxx-yyy", }); app .auth({ persistence: "session", }) .anonymousAuthProvider() .signIn() .then(() => { // 登录成功 }) .catch((err) => { // 登录失败 }); ``` --- ## 数据库 # 数据库 ## 基础概念 ### Collection 集合是一系列的文档集,通过 `db.collection(name)` 可以获取指定集合的引用,在集合上可以进行以下操作 | 类型 | 接口 | 说明 | | -------- | ------- | ---------------------------------------------------------------------------------- | | 写 | add | 新增文档(触发请求) | | 计数 | count | 获取符合条件的文档条数 | | 读 | get | 获取集合中的文档,如果有使用 where 语句定义查询条件,则会返回匹配结果集 (触发请求) | | 引用 | doc | 获取对该集合中指定 id 的文档的引用 | | 查询条件 | where | 通过指定条件筛选出匹配的文档,可搭配查询指令(eq, gt, in, ...)使用 | | | skip | 跳过指定数量的文档,常用于分页,传入 offset | | | orderBy | 排序方式 | | | limit | 返回的结果集(文档数量)的限制,有默认值和上限值(限制最大值是 1000) | | | field | 指定需要返回的字段 | 查询及更新指令用于在 `where` 中指定字段需满足的条件,指令可通过 `db.command` 对象取得。 ### Record / Document 文档是数据库集合中的一个存储单元,在云开发里是一个 json 对象。通过 `db.collection(collectionName).doc(docId)` 可以获取指定集合上指定 id 的文档的引用,在文档上可以进行以下操作 | 接口 | 说明 | | ---- | ------ | ---------------------- | | 写 | set | 覆写文档 | | | update | 局部更新文档(触发请求) | | | remove | 删除文档(触发请求) | | 读 | get | 获取文档(触发请求) | ### Query Command 查询指令,应用于构建查询条件。以下指令皆挂载在 `db.command` 下 | 类型 | 接口 | 说明 | | -------- | ---- | ---------------------------------- | | 比较运算 | eq | 字段 == | | | neq | 字段 != | | | gt | 字段 > | | | gte | 字段 >= | | | lt | 字段 ` 备注:set 方法也可以用来新增文档,请参看文档更新部分 [set](#update-set) 方法 示例: #### 2. 输入参数 | 参数 | 类型 | 必填 | 说明 | | ---- | ------ | ---- | ------------------------------------------ | | data | object | 是 | {\_id: '10001', 'name': 'Ben'} \_id 非必填 | #### 3. 输出参数 | 字段 | 类型 | 必填 | 说明 | | ------- | ------ | ---- | ------------------------ | | code | string | 否 | 状态码,操作成功则不返回 | | message | string | 否 | 错误描述 | #### 4. 示例代码 ```js collection .add({ name: "Ben", }) .then((res) => {}) .catch((e) => {}); ``` ## get #### 1. 接口描述 接口功能:获取数据库查询结果 接口声明:`get(): Promise` 注:get()如不指定 limit 则默认取前 100 条数据,且最大取前 100 条数据。 #### 2. 输入参数 空 #### 3. 输出参数 | 字段 | 类型 | 必填 | 说明 | | --------- | ------ | ---- | ------------------------ | | code | string | 否 | 状态码,操作成功则不返回 | | message | string | 否 | 错误描述 | | data | object | 否 | 查询结果 | | requestId | string | 是 | 请求序列号,用于错误排查 | #### 4. 示例代码 ```js collection .where({ category: "computer", type: { memory: 8, }, }) .get() .then((res) => {}) .catch((e) => {}); ``` ## count #### 1. 接口描述 接口功能:获取数据库查询结果的数目 接口声明:`cout(): Promise` #### 2. 输入参数 空 #### 3. 输出参数 | 字段 | 类型 | 必填 | 说明 | | --------- | ------- | ---- | ------------------------ | | code | string | 否 | 状态码,操作成功则不返回 | | message | string | 否 | 错误描述 | | total | Integer | 否 | 计数结果 | | requestId | string | 否 | 请求序列号,用于错误排查 | #### 4. 示例代码 ```js db.collection("goods") .where({ category: "computer", type: { memory: 8, }, }) .count() .then(function (res) { const total = res.total; //符合条件的文档的数量 }); ``` ## remove #### 1. 接口描述 接口功能:删除一条文档 接口声明:`remove(): Promise` #### 2. 输入参数 无 #### 3. 输出参数 | 字段 | 类型 | 必填 | 说明 | | --------- | ------- | ---- | ------------------------ | | code | string | 否 | 状态码,操作成功则不返回 | | message | string | 否 | 错误描述 | | deleted | Inteter | 否 | 删除的文档数量 | | requestId | string | 是 | 请求序列号,用于错误排查 | #### 4. 示例代码 方式 1:通过  指定文档 ID 删除 collection.doc(\_id).remove() ```js collection .doc("xxx") .remove() .then((res) => { console.log(`${res.deleted} docs deleted`); }) .catch((e) => {}); ``` 方式 2:条件查找文档然后直接批量删除 ```js // 删除字段a的值大于2的文档 collection .where({ a: _.gt(2), }) .remove() .then(function (res) { const deleted = res.deleted; }); ``` ## update / set #### 1. 接口描述 接口功能:更新文档 接口声明: `update(object: ): Promise` `set(object: ): Promise` 备注:update 和 set 都可以用来更新文档,区别是 set 方法在要更新的文档不存在时新增一个文档;而 update 方法什么也不会做,返回 updated 为 0 #### 2. 输入参数 | 字段 | 类型 | 必填 | 说明 | | ---- | --------- | ---- | -------------- | | - | | 是 | 替换文档的定义 | #### 3. 输出参数 | 字段 | 类型 | 必填 | 说明 | | ---------- | ------- | ---- | ------------------------ | | code | string | 否 | 状态码,操作成功则不返回 | | message | string | 否 | 错误描述 | | updated | Integer | 否 | 影响的文档数量 | | upsertedId | string | 否 | 插入的文档的 id | | requestId | string | 是 | 请求序列号,用于错误排查 | #### 4. 示例代码 更新指定文档 ```js //更新指定文档 collection .doc("doc-id") .update({ name: "Hey", }) .then(function (res) {}); ``` 更新文档,如果不存在则创建 ```js //更新单个文档 collection .doc("doc-id") .set({ name: "Hey", }) .then(function (res) {}); //批量更新文档 collection .where({ name: _.eq("hey") }) .update({ age: 18, }) .then(function (res) {}); ``` ## GEO 地理位置 注意:**如果需要对类型为地理位置的字段进行搜索,一定要建立地理位置索引**。 ### GEO 数据类型 #### Point 用于表示地理位置点,用经纬度唯一标记一个点,这是一个特殊的数据存储类型。 签名:`Point(longitude: number, latitude: number)` 示例: ```js new db.Geo.Point(longitude, latitude); ``` #### LineString 用于表示地理路径,是由两个或者更多的 `Point` 组成的线段。 签名:`LineString(points: Point[])` 示例: ```js new db.Geo.LineString([ new db.Geo.Point(lngA, latA), new db.Geo.Point(lngB, latB), // ... ]); ``` #### Polygon 用于表示地理上的一个多边形(有洞或无洞均可),它是由一个或多个**闭环** `LineString` 组成的几何图形。 由一个环组成的 `Polygon` 是没有洞的多边形,由多个环组成的是有洞的多边形。对由多个环(`LineString`)组成的多边形(`Polygon`),第一个环是外环,所有其他环是内环(洞)。 签名:`Polygon(lines: LineString[])` 示例: ```js new db.Geo.Polygon([ new db.Geo.LineString(...), new db.Geo.LineString(...), // ... ]) ``` #### MultiPoint 用于表示多个点 `Point` 的集合。 签名:`MultiPoint(points: Point[])` 示例: ```js new db.Geo.MultiPoint([ new db.Geo.Point(lngA, latA), new db.Geo.Point(lngB, latB), // ... ]); ``` #### MultiLineString 用于表示多个地理路径 `LineString` 的集合。 签名:`MultiLineString(lines: LineString[])` 示例: ```js new db.Geo.MultiLineString([ new db.Geo.LineString(...), new db.Geo.LineString(...), // ... ]) ``` #### MultiPolygon 用于表示多个地理多边形 `Polygon` 的集合。 签名:`MultiPolygon(polygons: Polygon[])` 示例: ```js new db.Geo.MultiPolygon([ new db.Geo.Polygon(...), new db.Geo.Polygon(...), // ... ]) ``` ### GEO 操作符 #### geoNear 按从近到远的顺序,找出字段值在给定点的附近的文档。 签名: ```js db.command.geoNear(options: IOptions) interface IOptions { geometry: Point // 点的地理位置 maxDistance?: number // 选填,最大距离,米为单位 minDistance?: number // 选填,最小距离,米为单位 } ``` 示例: ```js db.collection("user").where({ location: db.command.geoNear({ geometry: new db.Geo.Point(lngA, latA), maxDistance: 1000, minDistance: 0, }), }); ``` #### geoWithin 找出字段值在指定 Polygon / MultiPolygon 内的文档,无排序 签名: ```js db.command.geoWithin(IOptions); interface IOptions { geometry: Polygon | MultiPolygon; // 地理位置 } ``` 示例: ```js // 一个闭合的区域 const area = new Polygon([ new LineString([ new Point(lngA, latA), new Point(lngB, latB), new Point(lngC, latC), new Point(lngA, latA), ]), ]); // 搜索 location 字段在这个区域中的 user db.collection("user").where({ location: db.command.geoWithin({ geometry: area, }), }); ``` #### geoIntersects 找出字段值和给定的地理位置图形相交的文档 签名: ```js db.command.geoIntersects(IOptions); interface IOptions { geometry: | Point | LineString | MultiPoint | MultiLineString | Polygon | MultiPolygon; // 地理位置 } ``` 示例: ```js // 一条路径 const line = new LineString([new Point(lngA, latA), new Point(lngB, latB)]); // 搜索 location 与这条路径相交的 user db.collection("user").where({ location: db.command.geoIntersects({ geometry: line, }), }); ``` ## 数据库实时推送 监听指定集合中符合查询条件的文档,通过 onchange 回调获得文档的变化详情 (where 参数为查询条件 参考 [查询文档](#查询文档)) ```js import cloudbase from "@cloudbase/js-sdk"; const app = cloudbase.init({ env: "tcbenv-mPIgjhnq", }); const db = app.database(); const _ = db.command; const collection = db.collection("collName"); // collName 需填当前env下集合名称 let ref = collection.where({ test: _.gt(0) }).watch({ onChange: (snapshot) => { console.log("收到snapshot**********", snapshot); }, onError: (error) => { console.log("收到error**********", error); }, }); ``` 单个 doc 的监听,也可以采用 doc('docId').watch()形式 ```js let ref = collection.doc("one docId").watch({ onChange: (snapshot) => { console.log("收到snapshot**********", snapshot); }, onError: (error) => { console.log("收到error**********", error); }, }); ``` 手动关闭监听,当前监听将不再收到推送 ```js ref.close().then((result) => { // 监听被关闭 }); ``` --- ## 云函数 # 云函数 ## callFunction #### 1. 接口描述 接口功能:执行云函数 接口声明:`callFunction(object: Object): Promise` #### 2. 输入参数 | 字段 | 类型 | 必填 | 说明 | | -------- | -------- | ---- | ---------------------------------------------------------------------------------------------------------------------- | | name | string | 是 | 云函数名称 | | data | object | 否 | 云函数参数 | | callback | function | 否 | 回调函数 | | parse | boolean | 否 | 设置为 true 时,当函数返回值为对象时,API 请求会返回解析对象,而不是 JSON 字符串,适用于在浏览器调试时直接查看返回结果 | #### 3. 输出参数 | 字段 | 类型 | 必填 | 说明 | | --------- | ------ | ---- | ------------------------ | | code | string | 否 | 状态码,操作成功则不返回 | | message | string | 否 | 错误描述 | | result | object | 否 | 云函数执行结果 | | requestId | string | 否 | 请求序列号,用于错误排查 | #### 4. 示例代码 ```javascript import cloudbase from "@cloudbase/js-sdk"; //初始化SDK实例 const app = cloudbase.init({ env: "xxxx-yyy" }); app .callFunction({ name: "test", data: { a: 1 } }) .then((res) => { const result = res.result; //云函数执行结果 }); ``` --- ## 初始化 # 初始化 @cloudbase/js-sdk 让您可以在 Web 端(如 PC Web 页面、微信公众平台 H5 等)使用 JavaScript 访问 Cloudbase 服务和资源。 :::tip 提示 当前@cloudbase/js-sdk latest 版本已升级至 [v2 版本],v1 版本不再继续升级维护,推荐使用 [v2 版本],若需使用 v1 版本,请在安装时指定版本号。v1 迁移至 [v2 版本]请参考[迁移文档](https://docs.cloudbase.net/api-reference/webv3/migration) ::: ## 安装 ### 方式一:通过包管理器引入 ```bash #npm npm install @cloudbase/js-sdk@v1 -S # yarn yarn add @cloudbase/js-sdk@v1 ``` ### 方式二:通过 CDN 引入 通过 CDN 引入有两种方式: 注:可前往 npm 源查看当前最新版本 https://www.npmjs.com/package/@cloudbase/js-sdk #### 引入全量 SDK ```html const app = cloudbase.init({ env: "your-env-id", }); ``` #### 按需引入功能模块 ```html const app = cloudbase.init({ env: "your-env-id", }); ``` :::tip 提示 功能模块必须在内核之后引入,并且登录模块必须引入。 ::: 最新的版本号 version 可以前往 [NPM](https://www.npmjs.com/package/@cloudbase/js-sdk) 查看。 ## 使用 通过包管理器安装 @cloudbase/js-sdk 之后,在项目源码中有两种引入方式: ### 方式一:引入全量 SDK ```js import cloudbase from "@cloudbase/js-sdk"; const app = cloudbase.init({ env: "your-env-id", }); ``` ### 方式二:按需引入功能模块 ```js // 内核 import cloudbase from "@cloudbase/js-sdk/app"; // 登录模块 import "@cloudbase/js-sdk/auth"; // 云函数模块 import "@cloudbase/js-sdk/functions"; // 云存储模块 import "@cloudbase/js-sdk/storage"; // 数据库模块 import "@cloudbase/js-sdk/database"; // 实时推送模块,引入前必须首先引入数据库模块 import "@cloudbase/js-sdk/realtime"; // 广告上报模块 import "@cloudbase/js-sdk/analytics"; const app = cloudbase.init({ env: "your-env-id", }); ``` :::tip 提示 功能模块必须在内核之后引入,并且登录模块必须引入。 ::: **请注意**:以上代码展示的功能模块引入方式仅在浏览器环境下有效,对于非浏览器环境的 JavaScript 运行时,必须在引入功能模块后手动注册模块,代码如下: ```js // 内核 import cloudbase from "@cloudbase/js-sdk/app"; // 登录模块 import { registerAuth } from "@cloudbase/js-sdk/auth"; // 云函数模块 import { registerFunctions } from "@cloudbase/js-sdk/functions"; // 云存储模块 import { registerStorage } from "@cloudbase/js-sdk/storage"; // 数据库模块 import { registerDatabase } from "@cloudbase/js-sdk/database"; // 实时推送模块,引入前必须首先引入数据库模块 import { registerRealtime } from "@cloudbase/js-sdk/realtime"; // 注册功能模块 registerAuth(cloudbase); registerFunctions(cloudbase); registerStorage(cloudbase); registerDatabase(cloudbase); registerRealtime(cloudbase); const app = cloudbase.init({ env: "your-env-id", }); ``` ## 地域 init 初始化时可以指定 region,默认使用上海地域(ap-shanghai),目前支持的地域列表[参考](https://cloud.tencent.com/document/product/876/51107)。 示例: 当前有上海地域的环境 env-shanghai,广州地域的环境 env-guangzhou 则正确的初始化方式为: ```js // region 不填默认为上海地域,信息一致 const app = cloudbase.init({ env: "env-shanghai", }); ``` ```js // env地域 与 region 一致 const app = cloudbase.init({ env: "env-shanghai", region: "ap-shanghai", }); ``` ```js // env地域 与 region 一致 const app = cloudbase.init({ env: "env-guangzhou", region: "ap-guangzhou", }); ``` :::tip 提示 当前使用的环境所属地域,必须与当前指定的地域信息一致! ::: ## 更友好的错误日志 @cloudbase/js-sdk 在开发环境下会将调用 API 的错误信息以更友好的方式打印到控制台,如下图所示: ![](https://main.qcloudimg.com/raw/5e8d21f2784f03501a27eba39ceb27a8.png) 图中打印的错误是当前的登录类型受到函数的安全规则限制,导致没有调用函数的权限。错误信息分为两部分: 1. 上半部分的黑色字体提示包含了后端 API 返回的错误信息以及基于此报错的一些解决方案提示; 2. 下半部分的红色字体是经优化后的错误堆栈,由于原始错误堆栈层次太深导致 debug 非常困难,所以此处打印的错误堆栈的第一条直接定位到 SDK 源码,第二条定位到调用报错 API 的业务源码。 优化的错误提示仅在开发环境中使用,根据`process.env.NODE_ENV`判断是否为开发环境。此外,定位到 SDK 源码需要借助 SourceMap。 以上两点依赖构建工具的部分特性,目前仅支持 Webpack 和 Rollup。 #### Webpack 在 Webpack 4+ 版本中可以配置`mode`选项为`development`,如下: ```js module.exports = { mode: "development", }; ``` 如果是旧版本的 Webpack 需要使用[DefinePlugin](https://webpack.js.org/plugins/define-plugin/): ```js const webpack = require("webpack"); module.exports = { plugins: [ new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("development"), }), // ...其他插件 ], // ...其他配置 }; ``` 然后为 js 的编译选项加入 sourcemap 预处理,这里需要使用[source-map-loader](https://github.com/webpack-contrib/source-map-loader): ```js module.exports = { module: { rules: [ { test: /\.js$/, enforce: "pre", use: ["source-map-loader"], }, // ...其他rules ], }, // ...其他配置 }; ``` 配置完成后启动 webpack-dev-server 即可。 #### Rollup Rollup 需要使用两个插件: - [rollup-plugin-replace](https://github.com/rollup/rollup-plugin-replace)用来注入`process.env.NODE_ENV` - [rollup-plugin-sourcemaps](https://github.com/maxdavidson/rollup-plugin-sourcemaps)用来加载 sourcemap 配置如下: ```js import sourcemaps from "rollup-plugin-sourcemaps"; import replace from "rollup-plugin-replace"; export default { plugins: [ sourcemaps(), replace({ "process.env.NODE_ENV": JSON.stringify("development"), }), // ...其他插件 ], // ...其他配置 }; ``` 配置完成使用[rollup-plugin-serve](https://github.com/thgh/rollup-plugin-serve)启动 dev server 即可。 [v2 版本]: /api-reference/webv3/initialization --- ## 从 tcb-js-sdk 迁移 # 从 tcb-js-sdk 迁移 @cloudbase/js-sdk 保留了 tcb-js-sdk 全部的核心概念,所以您可以沿袭使用 tcb-js-sdk 的大部分逻辑,在迁移过程中仅需要关注以下两点: - 全量变量 - API 迁移 ## 迁移指南 ### 全局变量 tcb-js-sdk 暴露的全局变量名称为 `tcb`, @cloudbase/js-sdk 将全局变量更名为 `cloudbase`。 ### API 迁移 tcb-js-sdk 文档中标明的即将废弃的 API 在 @cloudbase/js-sdk 中不再提供,清单如下: #### Auth.on() - 废弃 废弃 tcb-js-sdk 用于监听登录相关事件的 API `Auth.on()`,@cloudbase/js-sdk 针对每种事件提供对应的监听 API,列表如下 |事件名称| API | |:--:|:--:| |loginStateExpire|[Auth.onLoginStateExpired()](./authentication#auth-onloginstatechanged)| |loginStateChanged|[Auth.onLoginTypeChanged()](./authentication.md#auth-onloginstatechanged)| |refreshAccessToken|[Auth.onAccessTokenRefreshed()](./authentication#auth-onaccesstokenrefreshed)| |anonymousConverted|[Auth.onAnonymousConverted()](./authentication.md#auth-onanonymousconverted)| |loginTypeChanged|[Auth.onLoginTypeChanged()](./authentication#auth-onlogintypechanged)| #### Auth.signInAnonymously() - 代替 废弃 tcb-js-sdk 用于匿名登录的 API `Auth.signInAnonymously()`, @cloudbase/js-sdk 中提供 API [`AnonymousAuthProvider.signIn()`](./authentication#anonymousauthprovider-signin) 实现同样功能。 #### Auth.linkAndRetrieveDataWithTicket() - 代替 废弃 tcb-js-sdk 用于匿名账号转正的 API `Auth.linkAndRetrieveDataWithTicket()`, @cloudbase/js-sdk 中提供 API [`User.linkWithTicket()`](./authentication#user-linkwithticket) 实现同样功能。 #### Auth.signInWithTicket() - 代替 废弃 tcb-js-sdk 用于自定义登录的 API `Auth.signInWithTicket()`, @cloudbase/js-sdk 中提供 API [`CustomAuthProvider.signIn()`](./authentication#customauthprovider-signin) 实现同样功能。 ## 新版特性 ### 模块体系 tcb-js-sdk 只能一次性引入全量 SDK,造成打包后的 JavaScript 文件体积过大,这对于只需要云开发部分功能的用户很不友好。@cloudbase/js-sdk 新增按需引入功能模块的特性,您可以根据自身业务需求引入对应的功能模块,详情请查看[初始化](./initialization#shi-yong)章节。 ### 更友好的语法提示 如果您使用 TypeScript 或 VSCode 等具备语法提示功能的 IDE,将会在开发过程中体验到更友好的语法提示。 --- ## 文件存储 # 文件存储 ## uploadFile #### 1. 接口描述 接口功能:上传文件到文件管理服务 接口声明:`uploadFile(object: Object): Promise` :::tip 提示 1.0.1 版本后,为了提高文件上传性能,文件上传方式修改为直接上传到对象存储,为了防止在使用过程中出现 CORS 报错,需要登录 **[云开发平台](https://tcb.cloud.tencent.com/dev)** ,在 **[安全来源](https://tcb.cloud.tencent.com/dev#/env/safety-source)** 页面的 **安全域名** 添加域名。如果已有域名出现 CORS 报错,请删除安全域名,重新添加。 ::: #### 2. 输入参数 | 字段 | 类型 | 必填 | 说明 | | ---------------- | ---------------- | ---- | -------------------------- | | cloudPath | string | 是 | 文件的绝对路径,包含文件名 | | filePath | HTML upload file | 是 | 要上传的文件对象 | | onUploadProgress | function | 否 | 上传进度回调 | :::tip 提示 `cloudPath` 为文件的绝对路径,包含文件名 foo/bar.jpg、foo/bar/baz.jpg 等,不能包含除[0-9 , a-z , A-Z]、/、!、-、\_、.、、\*和中文以外的字符,使用 / 字符来实现类似传统文件系统的层级结构。[查看详情](https://cloud.tencent.com/document/product/436/13324) ::: #### 3. 输出参数 | 字段 | 类型 | 必填 | 说明 | | --------- | ------ | ---- | --------------------------------------- | | code | string | 否 | 状态码,操作成功则不返回 | | message | string | 否 | 错误描述 | | fileID | fileID | 是 | 文件唯一 ID,用来访问文件,建议存储起来 | | requestId | string | 否 | 请求序列号,用于错误排查 | #### 4. 示例代码 ```javascript import cloudbase from "@cloudbase/js-sdk"; const app = cloudbase.init({ env: "xxxx-yyy" }); app .uploadFile({ cloudPath: "test-admin.jpeg", filePath: document.getElementById("file").files[0], onUploadProgress: function (progressEvent) { console.log(progressEvent); var percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total); } }) .then((result) => { // 上传结果 }); ``` ## getTempFileURL #### 1. 接口描述 接口功能:获取文件 CDN 下载链接 接口声明:`getTempFileURL(object: Object): Promise` #### 2. 输入参数 | 字段 | 类型 | 必填 | 说明 | | -------- | -------------------- | ---- | -------------------------- | | fileList | <Array>.string | 是 | 要下载的文件 ID 组成的数组 | ##### fileList | 字段 | 类型 | 必填 | 说明 | | ------ | ------- | ---- | -------------- | | fileID | string | 是 | 文件 ID | | maxAge | Integer | 是 | 文件链接有效期 | #### 3. 输出参数 | 字段 | 类型 | 必填 | 说明 | | --------- | -------------------- | ---- | ---------------------------- | | code | string | 否 | 状态码,操作成功则为 SUCCESS | | message | string | 否 | 错误描述 | | fileList | <Array>.object | 否 | 存储下载链接的数组 | | requestId | string | 否 | 请求序列号,用于错误排查 | ##### fileList | 字段 | 类型 | 必填 | 说明 | | ----------- | ------ | ---- | ------------------------ | | code | string | 否 | 删除结果,成功为 SUCCESS | | message | string | 否 | 错误描述 | | fileID | string | 是 | 文件 ID | | tempFileURL | string | 是 | 文件访问链接 | #### 4. 示例代码 ```javascript //初始化SDK实例部分代码如上 app .getTempFileURL({ fileList: ["cloud://jimmytest-088bef.jimmytest-088bef-1251059088/a|b测试.jpeg"] }) .then((res) => { res.fileList.forEach((el) => { if (el.code === "SUCCESS") { console.log(el.tempFileURL); } else { //获取下载链接失败 } }); }); ``` ## deleteFile #### 1. 接口描述 接口功能:删除文件 接口声明:`deleteFile(object: Object): Promise` #### 2. 输入参数 | 字段 | 类型 | 必填 | 说明 | | -------- | -------------------- | ---- | -------------------------- | | fileList | <Array>.string | 是 | 要删除的文件 ID 组成的数组 | #### 3. 输出参数 | 字段 | 类型 | 必填 | 说明 | | --------- | -------------------- | ---- | ------------------------ | | code | string | 否 | 状态码,操作成功则不返回 | | message | string | 否 | 错误描述 | | fileList | <Array>.object | 否 | 删除结果组成的数组 | | requestId | string | 否 | 请求序列号,用于错误排查 | #### fileList | 字段 | 类型 | 必填 | 说明 | | ------ | ------ | ---- | ------------------------ | | code | string | 否 | 删除结果,成功为 SUCCESS | | fileID | string | 是 | 文件 ID | #### 4. 示例代码 ```javascript app .deleteFile({ fileList: ["cloud://jimmytest-088bef/1534576354877.jpg"] }) .then((res) => { res.fileList.forEach((el) => { if (el.code === "SUCCESS") { //删除成功 } else { } }); }); ``` ## downloadFile #### 1. 接口描述 接口功能:下载文件到本地 接口声明:`downloadFile(object: Object): Promise` #### 2. 输入参数 | 字段 | 类型 | 必填 | 说明 | | ------ | ------ | ---- | ----------------- | | fileID | string | 是 | 要下载的文件的 id | #### 3. 输出参数 | 字段 | 类型 | 必填 | 说明 | | --------- | ------ | ---- | ------------------------ | | code | string | 否 | 状态码,操作成功则不返回 | | message | string | 否 | 错误描述 | | requestId | string | 否 | 请求序列号,用于错误排查 | #### 4. 示例代码 ```javascript cloudbase .downloadFile({ fileID: "cloud://aa-99j9f/my-photo.png" }) .then((res) => {}); ``` --- ## 适配器开发指引 # 适配器开发指引 @cloudbase/js-sdk 只支持常规 Web 应用(即浏览器环境)的开发,不兼容其他类 Web 平台,比如微信小程序、快应用、Cocos 等。虽然这些平台大多支持 JavaScript 运行环境,但在网络请求、本地存储、平台标识等特性上与浏览器环境有明显差异。针对这些差异特性,@cloudbase/js-sdk 提供一套完整的适配扩展方案,遵循此方案规范可开发对应平台的适配器,然后搭配 @cloudbase/js-sdk 和适配器实现平台的兼容性。 ## 适配规范 开发适配器之前需要安装官方提供的接口声明模块[`@cloudbase/adapter-interface`](https://www.npmjs.com/package/@cloudbase/adapter-interface): ```bash # npm npm i @cloudbase/adapter-interface # yarn yarn add @cloudbase/adapter-interface ``` 适配器模块需要导出一个`adapter`对象: ```js const adapter = { genAdapter, isMatch, // runtime标记平台唯一性 runtime: '平台名称' }; export adapter; export default adapter; ``` 必须包含以下三个字段: - `runtime`: `string`,平台的名称,用于标记平台唯一性; - `isMatch`: `Function`,判断当前运行环境是否为平台,返回`boolean`值; - `genAdapter`: `Function`,创建`adapter`实体。 ### runtime `runtime`用于标记平台的唯一性,建议尽量以平台的英文名称或简写命名,比如百度小程序`baidu_miniapp`、QQ 小程序`qq_miniapp`等等。 ### isMatch `isMatch`函数用于判断当前运行环境是否与适配器匹配,通常是通过判断平台特有的一些全局变量、API 等。比如以下代码是判断运行环境是否为 Cocos 原生平台: ```js function isMatch(): boolean { if (typeof cc === "undefined") { return false; } if (typeof WebSocket === "undefined") { return false; } if (typeof XMLHttpRequest === "undefined") { return false; } if (!cc.game) { return false; } if (typeof cc.game.on !== "function") { return false; } if (!cc.game.EVENT_HIDE) { return false; } if (!cc.game.EVENT_SHOW) { return false; } if (!cc.sys) { return false; } if (!cc.sys.isNative) { return false; } return true; } ``` ### genAdapter `genAdapter`函数返回适配器的实体对象,结构如下: ```typescript interface SDKAdapterInterface { // 全局根变量,浏览器环境为window root: any; // WebSocket类 wsClass: WebSocketContructor; // request类 reqClass: SDKRequestConstructor; // 无localstorage时persistence=local降级为none localStorage?: StorageInterface; // 无sessionStorage时persistence=session降级为none sessionStorage?: StorageInterface; // storage模式首选,优先级高于persistence primaryStorage?: StorageType; // Captcha验证码配置 captchaOptions?: { // 打开网页并通过URL回调获取 CaptchaToken,针对不同的平台,该函数可以自定义实现 openURIWithCallback?: (url: string) => Promise; }; // 获取平台唯一应用标识的api getAppSign?(): string; } ``` ### 示例 ```typescript import { AbstractSDKRequest, IRequestOptions, IUploadRequestOptions, StorageInterface, WebSocketInterface, WebSocketContructor, SDKAdapterInterface, StorageType, formatUrl, } from "@cloudbase/adapter-interface"; // isMatch函数判断当前平台是否匹配 function isMatch(): boolean { // ... return true; } // Request类为平台特有的网络请求,必须实现post/upload/download三个public接口 export class Request extends AbstractSDKRequest { // 实现post接口 public post(options: IRequestOptions) { return new Promise((resolve) => { // ... resolve(); }); } // 实现upload接口 public upload(options: IUploadRequestOptions) { return new Promise((resolve) => { // ... resolve(); }); } // 实现download接口 public download(options: IRequestOptions) { return new Promise((resolve) => { // ... resolve(); }); } } // Storage为平台特有的本地存储,必须实现setItem/getItem/removeItem/clear四个接口 export const Storage: StorageInterface = { setItem(key: string, value: any) { // ... }, getItem(key: string): any { // ... }, removeItem(key: string) { // ... }, clear() { // ... }, }; // WebSocket为平台特有的WebSocket,与HTML5标准规范一致 export class WebSocket { constructor(url: string, options: object = {}) { const socketTask: WebSocketInterface = { set onopen(cb) { // ... }, set onmessage(cb) { // ... }, set onclose(cb) { // ... }, set onerror(cb) { // ... }, send: (data) => { // ... }, close: (code?: number, reason?: string) => { // ... }, get readyState() { // ... return readyState; }, CONNECTING: 0, OPEN: 1, CLOSING: 2, CLOSED: 3, }; return socketTask; } } // genAdapter函数创建adapter实体 // options 为 cloudbase.useAdapters(adapter, options) 时传入的参数 function genAdapter(options) { const adapter: SDKAdapterInterface = { // root对象为全局根对象,没有则填空对象{} root: window, reqClass: Request, wsClass: WebSocket as WebSocketContructor, localStorage: Storage, // 首先缓存存放策略,建议始终保持localstorage primaryStorage: StorageType.local, // sessionStorage为可选项,如果平台不支持可不填 sessionStorage: sessionStorage, }; return adapter; } // 三者缺一不可 const adapter = { genAdapter, isMatch, // runtime标记平台唯一性 runtime: "平台名称", }; export default adapter; ``` ## 接入流程 ### 第 1 步:安装并引入适配器 安装 @cloudbase/js-sdk 和所需平台的适配器,比如 QQ 小游戏平台: ```bash # 安装 @cloudbase/js-sdk npm i @cloudbase/js-sdk # 安装 QQ 小游戏适配器 npm i cloudbase-adapter-qq_game ``` 然后在业务代码中将引入适配器: ```js import cloudbase from "@cloudbase/js-sdk"; import adapter from "cloudbase-adapter-qq_game"; // options传入后,可以在 adapter 的 genAdapter 中获取到该参数 cloudbase.useAdapters(adapter, options); ``` ### 第 2 步:配置安全应用来源 云开发需验证请求来源的合法性,常规 Web 通过验证安全域名,而由于上文提到的诸多类 Web 环境并没有域名的概念,所以需要借助安全应用凭证区分请求来源是否合法。 登录 [云开发平台](https://tcb.cloud.tencent.com/dev) ,在 [安全来源](https://tcb.cloud.tencent.com/dev#/env/safety-source) 页面中的**移动应用安全来源**一栏,点击“**添加应用**”按钮,输入应用标识。 :::tip 应用标识必须是能够标记应用唯一性的信息,比如微信小程序的`appId`、移动应用的包名等。 ::: 添加成功后会创建一个安全应用的信息,如下图所示: ![](https://main.qcloudimg.com/raw/6542df6800b71b91289bebc29d38de94.png) ### 第 3 步:初始化云开发 在业务代码中初始化云开发时将第 2 步配置的安全应用信息作为参数传递给 `init` 方法: ```js import cloudbase from '@cloudbase/js-sdk'; import adapter from 'cloudbase-adapter-qq_game'; cloudbase.useAdapters(adapter); cloudbase.init({ env: '环境ID', appSign: '应用标识', appSecret: { appAccessKeyId: '应用凭证版本号' appAccessKey: '应用凭证' } }) ``` - `appSign`:`string`,应用标识,对应上图中“应用标识”一栏; - `appSecret`:`Object`,应用凭证信息,包括以下字段: - `appAccessKeyId`:`string`,对应上图中“版本”一栏,**同一个应用标识可以最多可以添加两个版本的凭证信息**,以便区分开发和生产环境; - `appAccessKey`:`string`,对应上图中“操作”一栏点击“获取凭证”之后获取到的信息。 :::tip `appAccessKey`和`appAccessKeyId`必须一一对应。 ::: ### 第 4 步:编写业务代码 经过以上准备工作之后便可以编写自身的业务代码。 ## 一套代码多端适配 :::tip Web 和小程序无需配置 @cloudbase/js-sdk 已经内置了 Web 端和小程序端的 adapter,在这两个平台下无需配置即可使用。 ::: 如果您需要将一套代码兼容多种平台,@cloudbase/js-sdk 可以同时引入多个适配器,在运行时通过各适配器的`isMatch`函数判断平台类型,然后引入对应的兼容逻辑。比如以下代码可以同时兼容 QQ 小游戏、 Cocos 原生和百度小游戏三种平台: ```js import cloudbase from '@cloudbase/js-sdk'; import adapter as adapterOfQQGame from 'cloudbase-adapter-qq_game'; import adapter as adapterOfCocosNative from 'cloudbase-adapter-cocos_native'; import adapter as adapterOfBDGame from 'cloudbase-adapter-bd_game'; cloudbase.useAdapters([ adapterOfQQGame, adapterOfCocosNative, adapterOfBDGame ]); ``` ## 验证码处理指南 ### 1、概述 详细说明了处理验证码的完整流程,包括验证码触发场景、适配器改造、事件处理和用户交互。 ### 2、验证码触发场景 验证码会在以下情况被要求输入: - 用户名密码登录失败 5 次后 - 发送手机号或邮箱验证码时达到频率限制 > 需要验证码时,接口会返回如下错误信息 ```typescript { // ... data: { error: "captcha_required", error_code: 4001, error_description: "captcha_token required" } } ``` ### 3、完整处理流程 #### 适配器(Adapter)改造 ```typescript // options 通过 useAdapters 第二参数传入 // 例如:cloudbase.useAdapters(adapter, options); function genAdapter(options) { const adapter: SDKAdapterInterface = { // 其他适配器配置... captchaOptions: { // 当检测到需要验证码时,自动触发此函数 // url 为包含验证码图片、token、state等参数的字符串 openURIWithCallback: async (url: string) => { // 解析URL中的验证码参数 const { captchaData, state, token } = cloudbase.parseCaptcha(url); // 通过事件总线发送验证码数据,进行前端缓存及展示 options.EVENT_BUS.emit("CAPTCHA_DATA_CHANGE", { captchaData, // Base64编码的验证码图片 state, // 验证码状态标识 token, // 验证码token }); // 监听验证码校验结果 return new Promise((resolve) => { console.log("等待验证码校验结果..."); options.EVENT_BUS.once("RESOLVE_CAPTCHA_DATA", (res) => { // auth.verifyCaptchaData的校验结果 resolve(res); }); }); }, }, }; return adapter; } ``` #### 初始化与适配器配置 ```typescript // 创建事件总线实例 const EVENT_BUS = new EventBus(); // 配置并使用适配器,将 EVENT_BUS 注入给 genAdapter cloudbase.useAdapters(adapter, { EVENT_BUS }); const app = cloudbase.init({ env: '环境ID', appSign: '应用标识', appSecret: { appAccessKeyId: '应用凭证版本号' appAccessKey: '应用凭证' } }); const auth = app.auth(); ``` #### 验证码界面实现 ```typescript // 存储当前验证码状态 let captchaState = { captchaData: "", // Base64编码的验证码图片 state: "", // 验证码状态标识 token: "", // 验证码token }; // 监听验证码数据变化 EVENT_BUS.on("CAPTCHA_DATA_CHANGE", ({ captchaData, state, token }) => { console.log("收到验证码数据", { captchaData, state, token }); // 更新本地验证码状态 captchaState = { captchaData, state, token }; // 在页面中显示验证码图片,例如在web使用img标签展示方式如下 document.getElementById('captcha-image').src = captchaData; }); // 用户点击刷新验证码,触发该函数 const refreshCaptcha = async () => { try { // 获取最新验证码信息 const result = await auth.createCaptchaData({ state: captchaState.state }); // 更新本地验证码状态 captchaState = { ...captchaState captchaData: result.data, token: result.token, }; // 更新显示的验证码,例如在web使用img标签展示方式如下 document.getElementById('captcha-image').src = result.data; } catch (error) { console.error("刷新验证码失败", error); } }; // 用户提交验证码,触发该函数 const verifyCaptchaData = async (userCaptcha) => { try { // 校验验证码 const verifyResult = await auth.verifyCaptchaData({ token: captchaState.token, key: userCaptcha }); // 将校验结果通知适配器 EVENT_BUS.emit("RESOLVE_CAPTCHA_DATA", verifyResult); // 验证成功,继续登录流程 console.log("验证码校验成功"); } catch (error) { console.error("验证码校验失败", error); // 可以选择刷新验证码 await refreshCaptcha() } }; ``` #### 完整流程 1. 用户尝试登录或发送验证码 2. 若触发验证码要求,SDK 抛出 captcha_required 错误 3. 适配器捕获错误并调用 openURIWithCallback 4. 系统解析验证码参数并通过 EVENT_BUS 发送 5. 前端展示验证码图片并等待用户输入 6. 用户输入验证码并提交 7. 系统验证并返回结果 8. 根据验证结果决定是否重试原操作 #### 验证码展示效果 --- ## Node.js 适配器 # Node.js 适配器 ## 概览 Node.js 适配器是为 Node.js 环境设计的,提供了对云开发服务的访问能力。它允许开发者在 Node.js 应用中使用云开发的功能,如数据库、存储、函数等。 ## 安装 使用 npm 安装 Node.js 适配器: ```bash npm i @cloudbase/adapter-node ``` ## 快速开始 ### 使用 ```javascript const cloudbase = require("@cloudbase/js-sdk"); const adapter = require("@cloudbase/adapter-node"); // 使用 Node.js 适配器 cloudbase.useAdapters(adapter); const app = cloudbase.init({ env: "your-env", // 需替换为实际使用环境 id }); ``` ## 使用示例 ### 云函数调用示例 ```javascript // 云函数调用示例 const result = await app.callFunction({ name: "your-function-name", data: { key: "value" } }); ``` ### 数据库操作示例 ```javascript // 数据库操作示例 const db = app.database(); // 创建测试集合 const testCollection = db.collection('test_collection'); // 插入测试数据 const insertResult = await testCollection.add({ name: "Node.js 测试", timestamp: new Date().toISOString(), }); ``` ### 文件上传示例 ```javascript // 上传文件示例 const fileName = `test-files/app-upload-${Date.now()}.jpg`; const fs = require('fs'); const testFilePath = '/your/local/path/XXX.jpg'; // 替换为你的本地文件路径 // 读取文件内容 const fileBuffer = fs.readFileSync(testFilePath); const uploadResult = await app.uploadFile({ cloudPath: fileName, filePath: fileBuffer, onUploadProgress: function (progressEvent) { console.log("上传进度:", progressEvent); var percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total); } }); ``` --- ## UniApp 适配器 # UniApp 适配器 ## 概览 UniApp 适配器是云开发为 UniApp 框架提供的专用适配器,让开发者能够在 UniApp 项目中无缝使用云开发的完整功能。通过该适配器,您可以轻松实现跨平台的云端数据存储、用户认证、文件管理和云函数调用等。 ### 支持平台 目前已适配以下平台: - H5 端 - 微信小程序 - 支付宝小程序 - 抖音小程序 - iOS - Android ## 各平台展示效果 完整示例项目请参考:[CloudBase UniApp 模板](https://github.com/TencentCloudBase/awesome-cloudbase-examples/tree/master/universal/cloudbase-uniapp-template) 各平台展示如下: H5 端 | 微信小程序 | |:---:|:---:| | ![H5 端](https://qcloudimg.tencent-cloud.cn/raw/cec528e3e0d4dddadff11c66a11013cc.png) | ![微信小程序](https://qcloudimg.tencent-cloud.cn/raw/826666e480af55c2c886ffa1a451dea8.png) | 支付宝小程序 | 抖音小程序 | |:---:|:---:| | ![支付宝小程序](https://qcloudimg.tencent-cloud.cn/raw/5fa5a46ae73b325bb1199b7e4059e480.png) | ![抖音小程序](https://qcloudimg.tencent-cloud.cn/raw/c4750c695aa81dab6cd3ef2de0aee8f0.png) | Android 和 iOS | |:---:| | | ## 安装 使用 npm 安装: ```bash npm install @cloudbase/adapter-uni-app ``` ## 快速开始 ### 适配器配置 如果需要使用登录功能或自定义配置,需要传入 `options` 参数: :::tip 注意 `options` 传入后可以在适配器内部的 `genAdapter` 中接收和使用。详细说明请参考 [跨端开发指南](https://docs.cloudbase.net/api-reference/webv3/adapter#%E9%AA%8C%E8%AF%81%E7%A0%81%E5%A4%84%E7%90%86%E6%8C%87%E5%8D%97)。 - `uni` 对象是必需的,用于处理图形验证码功能。 ::: ```javascript import cloudbase from '@cloudbase/js-sdk' import adapter from '@cloudbase/adapter-uni-app' // 传入配置选项 const options = { uni: uni, // 传入 uni 对象,用于图形验证码功能 } cloudbase.useAdapters(adapter, options) const app = cloudbase.init({ env: 'your-env-id', // 替换为您的环境 ID // 仅在App端需要配置 appSign: 'your-app-sign', appSecret: { appAccessKeyId: 1, appAccessKey: 'your-app-access-key' } }) export default app ``` :::warning 重要提示 - `adapter` 必须在 `cloudbase.init()` 之前调用 - 如果需要实现登录相关功能,必须传入 UniApp 的 `uni` 对象 - App端需要额外配置应用标识和凭证信息 ::: ## 安全域名配置 云开发 SDK 在使用过程中,向云开发服务发送的请求都需要验证请求来源的合法性。以下是不同平台的域名配置方法: ### H5 端 开发环境域名: ``` http://localhost:本地端口号 ``` 生产环境需要配置您的实际域名。 ### 微信小程序 在微信小程序管理后台的【开发】→【开发管理】→【开发设置】→【服务器域名】中配置: **request 合法域名:** ``` https://tcb-api.tencentcloudapi.com https://your-env-id.service.tcloudbase.com ``` **uploadFile 合法域名:** ``` https://cos.ap-shanghai.myqcloud.com ``` **downloadFile 合法域名:** ``` https://your-env-id.tcb.qcloud.la https://cos.ap-shanghai.myqcloud.com ``` :::info 提示 请将 `your-env-id` 替换为您的实际环境 ID,地域根据您的云开发环境所在地域调整。 ::: ### 支付宝小程序 开发环境域名: ``` devappid.hybrid.alipay-eco.com ``` ### 抖音小程序 开发环境域名: ``` tmaservice.developer.toutiao.com ``` ### App 端配置 在云开发控制台的【环境配置】→【安全来源】→【移动应用安全来源】中添加应用: - **应用标识**:`your-app-sign` - **应用凭证**:`your-app-access-key` ```typescript const appConfig = { env: 'your-env-id', appSign: 'your-app-sign', // 应用标识 appSecret: { appAccessKeyId: 1, // 凭证版本 appAccessKey: 'your-app-access-key' // 应用凭证 } } ``` ### 开发环境启动 ```bash # H5 开发 npm run dev:h5 # 微信小程序开发 npm run dev:mp-weixin # 抖音小程序开发 npm run dev:mp-toutiao # 支付宝小程序开发 npm run dev:mp-alipay # App (iOS/Android) 开发 # 1. 使用 HBuilderX 打开项目 # 2. 在顶部菜单栏选择【运行】->【运行到手机或模拟器】-> 选择您的设备 ``` :::info 平台支持说明 目前稳定支持 APP、H5、微信小程序、抖音小程序和支付宝小程序平台,其他平台适配正在开发中。 ::: ## 图形验证码机制说明 在某些安全敏感的操作场景下(如用户登录),腾讯云开发会要求进行图形验证码验证。UniApp Adapter 通过事件总线机制处理图形验证码交互。 ### 工作流程 1. 触发验证码 - 当云开发检测到需要图形验证码时,自动调用适配器的图形验证码处理函数 2. 解析数据 - 适配器解析图形验证码 URL,提取图片数据、token 和状态信息 3. 前端展示 - 通过事件通知前端页面显示图形验证码 4. 用户输入 - 用户查看验证码图片并输入答案 5. 结果回传 - 前端将用户输入结果通过事件发送回适配器 6. 完成验证 - 适配器接收结果并继续后续流程 ### 适配器内部图形验证码处理实现 在适配器内部,可以访问到传入的 `uni` 对象,通过事件总线发送图形验证码数据: ```javascript function genAdapter(options) { const adapter: SDKAdapterInterface = { // 其他适配器配置... captchaOptions: { // 当检测到需要验证码时,自动触发此函数 // _url 为包含验证码图片、token、state等参数的字符串 openURIWithCallback: (_url: string) => { // 在适配器内部使用传入的 uni 对象 const uni = options.uni // 解析URL中的验证码参数 const { captchaData, state, token } = cloudbase.parseCaptcha(_url) return new Promise((resolve) => { console.log('等待验证码输入...') // 发送验证码数据到前端 uni.$emit('CAPTCHA_DATA_CHANGE', { state, // 验证码状态标识 token, // 验证码token captchaData // Base64编码的验证码图片 }) // 监听验证码验证结果 uni.$once('RESOLVE_CAPTCHA_DATA', (res: { captcha_token: string expires_in: number }) => { resolve(res) }) }) } } } return adapter } ``` ### 前端验证码处理 在您的 UniApp 页面中,需要监听验证码事件并处理用户输入: ```javascript // 在页面中监听验证码事件 uni.$on('CAPTCHA_DATA_CHANGE', ({ state, token, captchaData }) => { console.log("收到验证码数据", { state, token, captchaData }); // 更新本地验证码状态 captchaState = { state, token, captchaData }; // 在页面中显示验证码图片... }); ``` ## 常见问题 ### Q: 为什么要在 init 之前调用 useAdapters? A: 适配器需要在 SDK 初始化之前注册,以确保 SDK 能够正确识别当前运行环境并使用相应的适配器。 ### Q: 如何处理不同平台的差异? A: UniApp Adapter 会自动检测当前运行平台并使用相应的适配逻辑,开发者无需手动处理平台差异。 ### Q: 图形验证码功能如何自定义样式? A: 图形验证码的显示和交互完全由开发者控制,您可以根据需要自定义图形验证码弹窗的样式和交互逻辑。 ### Q: 支持哪些云开发功能? A: 支持云开发的所有核心功能,包括: - 身份验证(匿名登录、自定义登录等) - 数据库(增删改查、实时数据库等) - 文件存储(文件上传、下载、删除等) - 云函数 - 云托管 --- ## 微信小程序适配器 # 微信小程序适配器 ## 概览 微信小程序适配器是云开发为微信小程序提供的专用适配器。通过该适配器,开发者可以方便地在小程序中调用云函数、访问数据库、使用文件存储等功能。 ## 安装 ```bash npm install @cloudbase/adapter-wx_mp ``` ## 快速开始 ### 基础使用 ```javascript import cloudbase from '@cloudbase/js-sdk'; import adapter from '@cloudbase/adapter-wx_mp'; // 使用微信小程序适配器 cloudbase.useAdapters(adapter); const app = cloudbase.init({ env: 'your-env-id', // 替换为您的环境ID // 其他配置项 } }); export default app; ``` ### 高级配置 如果需要使用验证码功能或自定义事件总线,可以传入配置参数: ```javascript import cloudbase from '@cloudbase/js-sdk'; import adapter from '@cloudbase/adapter-wx_mp'; // 自定义事件总线(可选) const EventBus = { $emit: (event, data) => { // 处理事件发送逻辑 }, $on: (event, callback) => { // 处理事件监听逻辑 }, $once: (event, callback) => { // 处理一次性事件监听逻辑 }, $off: (event, callback) => { // 处理事件取消监听逻辑 } }; // cloudbase.useAdapters(adapter, {EventBus: uni}); cloudbase.useAdapters(adapter, { EventBus }); const app = cloudbase.init({ env: 'your-env-id', // 替换为您的环境ID // 其他配置项 } }); export default app; ``` :::warning 重要提示 - `adapter` 必须在 `cloudbase.init()` 之前调用 - 如果需要使用验证码功能,建议传入自定义的事件总线对象 ::: ### 配置参数说明 `options` 是一个可选的配置对象,传入后可以在适配器内部的 `genAdapter` 中接收和使用。详细说明请参考 [跨端开发指南](https://docs.cloudbase.net/api-reference/webv3/adapter#%E9%AA%8C%E8%AF%81%E7%A0%81%E5%A4%84%E7%90%86%E6%8C%87%E5%8D%97)。 ## 验证码处理 ### 验证码机制说明 在某些场景下(如登录时),云开发可能需要验证码验证。**微信小程序适配器**通过事件总线机制处理验证码交互。在初始化适配器时,可以传入一个事件总线对象,用于处理验证码相关事件。 ### 适配器验证码处理逻辑 以下是适配器内部的验证码处理逻辑: ```javascript function genAdapter(options) { const adapter: SDKAdapterInterface = { // 其他适配器配置... captchaOptions: { // 当检测到需要验证码时,自动触发此函数 // _url 为包含验证码图片、token、state等参数的字符串 openURIWithCallback: (_url: string) => { // 在适配器内部使用传入的 EventBus 对象 const EventBus = options.EventBus; // 解析URL中的验证码参数 const { captchaData, state, token } = cloudbase.parseCaptcha(_url) return new Promise((resolve) => { console.log('等待验证码输入...') // 发送验证码数据到前端 EventBus.$emit('CAPTCHA_DATA_CHANGE', { state, // 验证码状态标识 token, // 验证码token captchaData // Base64编码的验证码图片 }) // 监听验证码验证结果 EventBus.$once('RESOLVE_CAPTCHA_DATA', (res: { captcha_token: string expires_in: number }) => { resolve(res) }) }) } } } return adapter } ``` ### 前端处理验证码 在小程序前端页面中,可以通过事件总线监听验证码数据变化,并处理用户输入的验证码。以下是一个示例: ```javascript // 在页面中监听验证码事件 EventBus.$on('CAPTCHA_DATA_CHANGE', ({ state, token, captchaData }) => { console.log("收到验证码数据", { state, token, captchaData }); // 更新本地验证码状态 captchaState = { state, token, captchaData }; // 在页面中显示验证码图片... }); //... // 发送验证结果 EventBus.$emit('RESOLVE_CAPTCHA_DATA', result); ``` ## 完整示例 弹窗实现可以参考awesome-cloudbase-examples 的 [uniapp 模版](https://github.com/TencentCloudBase/awesome-cloudbase-examples/blob/master/universal/cloudbase-uniapp-template/src/components/show-captcha.vue). --- ## AI # AI 提供云开发 AI 接入能力,快速接入大模型和 Agent。 ## 初始化 使用 js-sdk 进行初始化并登录后,通过 `.ai()` 获取 [AI](#ai-1) 实例。 ```js import cloudbase from "@cloudbase/js-sdk"; const app = cloudbase.init({ env: "your-env-id" }); const auth = app.auth(); await auth.signInAnonymously(); const ai = app.ai(); ``` ## app.ai 初始化后,可以使用挂载至 cloudbase 实例上的 ai 方法创建 [AI](#ai-1) 实例,用于后续模型创建。 ### 使用示例 ```ts app = cloudbase.init({ env: "your-env" }); const ai = app.ai(); ``` ### 类型声明 ```ts function ai(): AI; ``` #### 返回值 > `AI` 返回新创建的 [AI](#ai-1) 实例。 ## AI 用于创建 AI 模型的类。 ### createModel() 创建指定的 AI 模型。 #### 使用示例 ```ts const model = ai.createModel("hunyuan-exp"); ``` #### 类型声明 ```ts function createModel(model: string): ChatModel; ``` 返回一个实现了 ChatModel 抽象类的模型实例,该实例提供 AI 生成文本相关能力。 ### bot 挂载了 Bot 类的实例,上面集合了一系列与 Agent 交互的方法。具体可参考 [Bot 类](#bot-1) 的详细文档。 #### 使用示例 ```ts const agentList = await ai.bot.list({ pageNumber: 1, pageSize: 10 }); ``` ### registerFunctionTool() 注册函数工具。在进行大模型调用时,可以告知大模型可用的函数工具,当大模型的响应被解析为工具调用时,会自动调用对应的函数工具。 #### 使用示例 ```js // 省略初始化 AI sdk 的操作... // 1. 定义获取天气的工具,详见 FunctionTool 类型 const getWeatherTool = { name: "get_weather", description: "返回某个城市的天气信息。调用示例:get_weather({city: '北京'})", fn: ({ city }) => `${city}的天气是:秋高气爽!!!`, // 在这定义工具执行的内容 parameters: { type: "object", properties: { city: { type: "string", description: "要查询的城市", }, }, required: ["city"], }, }; // 2. 注册我们刚定义好的工具 ai.registerFunctionTool(getWeatherTool); // 3. 在给大模型发送消息的同时,告知大模型可用一个获取天气的工具 const model = ai.createModel("hunyuan-exp"); const result = await model.generateText({ model: "hunyuan-turbo", tools: [getWeatherTool], // 这里我们传入了获取天气工具 messages: [ { role: "user", content: "请告诉我北京的天气状况", }, ], }); console.log(result.text); ``` #### 类型声明 ```ts function registerFunctionTool(functionTool: FunctionTool); ``` #### 参数 | 参数名 | 必填 | 类型 | 说明 | | ------------ | ---- | ------------ | ---------------------------------- | | functionTool | 是 | FunctionTool | 详见 [FunctionTool](#functiontool) | #### 返回值 `undefined` ## ChatModel 这个抽象类描述了 AI 生文模型类提供的接口。 ### generateText() 调用大模型生成文本。 #### 使用示例 ```ts const hy = ai.createModel("hunyuan-exp"); // 创建模型 const res = await hy.generateText({ model: "hunyuan-lite", messages: [{ role: "user", content: "你好,请你介绍一下李白" }], }); console.log(res.text); // 打印生成的文本 ``` #### 类型声明 ```ts function generateText(data: BaseChatModelInput): Promise; text: string; messages: Array; usage: Usage; error?: unknown; }>; ``` #### 参数 | 参数名 | 必填 | 类型 | 示例 | 说明 | | ------ | ---- | ------------------ | ------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | data | 是 | BaseChatModelInput | `{model: "hunyuan-lite", messages: [{ role: "user", content: "你好,请你介绍一下李白" }]}` | 参数类型定义为 [BaseChatModelInput](#basechatmodelinput) ,作为基础的入参定义。实际上各家大模型还会有各自独特的输入参数,开发者可按需根据实际使用的大模型官方文档传入其他不在此类型中被定义的参数,充分利用大模型提供的能力。其他参数会被透传至大模型接口, SDK 侧不对它们不做额外处理。 | #### 返回值 | 属性名 | 类型 | 示例 | 说明 | | ------------ | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------ | | text | string | `"李白是一位唐朝诗人。"` | 大模型生成的文本。 | | rawResponses | unknown[] | `[{"choices": [{"finish_reason": "stop","message": {"role": "assistant", "content": "你好呀,有什么我可以帮忙的吗?"}}], "usage": {"prompt_tokens": 14, "completion_tokens": 9, "total_tokens": 23}}]` | 大模型的完整返回值,包含更多详细数据,如消息创建时间等等。由于各家大模型返回值互有出入,请根据实际情况使用。 | | res.messages | ChatModelMessage[] | `[{role: 'user', content: '你好'},{role: 'assistant', content: '你好!很高兴与你交流。请问有什么我可以帮助你的吗?无论是关于生活、工作、学习还是其他方面的问题,我都会尽力为你提供帮助。'}]` | 本次调用的完整消息列表。 | | usage | Usage | `{"completion_tokens":33,"prompt_tokens":3,"total_tokens":36}` | 本次调用消耗的 token。 | | error | unknown | | 调用过程中产生的错误。 | ### streamText() 以流式调用大模型生成文本。流式调用时,生成的文本及其他响应数据会通过 SSE 返回,该接口的返回值对 SSE 做了不同程度的封装,开发者能根据实际需求获取到文本流和完整数据流。 #### 使用示例 ```ts const hy = ai.createModel("hunyuan-exp"); // 创建模型 const res = await hy.streamText({ model: "hunyuan-lite", messages: [{ role: "user", content: "你好,请你介绍一下李白" }], }); for await (let str of res.textStream) { console.log(str); // 打印生成的文本 } for await (let data of res.dataStream) { console.log(data); // 打印每次返回的完整数据 } ``` #### 类型声明 ```ts function streamText(data: BaseChatModelInput): Promise; ``` #### 参数 | 参数名 | 必填 | 类型 | 示例 | 说明 | | ------ | ---- | ------------------ | ------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | data | 是 | BaseChatModelInput | `{model: "hunyuan-lite", messages: [{ role: "user", content: "你好,请你介绍一下李白" }]}` | 参数类型定义为 [BaseChatModelInput](#basechatmodelinput) ,作为基础的入参定义。实际上各家大模型还会有各自独特的输入参数,开发者可按需根据实际使用的大模型官方文档传入其他不在此类型中被定义的参数,充分利用大模型提供的能力。其他参数会被透传至大模型接口, SDK 侧不对它们不做额外处理。 | #### 返回值 | StreamTextResult 属性名 | 类型 | 说明 | | ----------------------- | ----------------------------- | ---------------------------------------------------------------------------------------------------------------------- | | textStream | `ReadableStream` | 以流式返回的大模型生成文本,可参考使用示例获取到生成的增量文本。 | | dataStream | `ReadableStream` | 以流式返回的大模型响应数据,可参考使用示例获取到生成的增量数据。由于各家大模型响应值互有出入,请根据实际情况合理使用。 | | messages | `Promise` | 本次调用的完整消息列表。 | | usage | `Promise` | 本次调用消耗的 token。 | | error | `unknown` | 本次调用产生的错误。 | | DataChunk 属性名 | 类型 | 说明 | | ------------------------ | ------------------ | ---------------------- | | choices | `Array` | | | choices[n].finish_reason | `string` | 模型终止推断的原因。 | | choices[n].delta | `ChatModelMessage` | 本次请求的消息。 | | usage | `Usage` | 本次请求消耗的 token。 | | rawResponse | `unknown` | 大模型返回的原始回复。 | #### 示例 ```js const hy = ai.createModel("hunyuan-exp"); const res = await hy.streamText({ model: "hunyuan-lite", messages: [{ role: "user", content: "1+1结果是" }], }); // 文本流 for await (let str of res.textStream) { console.log(str); } // 1 // 加 // 1 // 的结果 // 是 // 2 // 。 // 数据流 for await (let str of res.dataStream) { console.log(str); } // {created: 1723013866, id: "a95a54b5c5d2144eb700e60d0dfa5c98", model: "hunyuan-lite", version: "202404011000", choices: Array(1), …} // {created: 1723013866, id: "a95a54b5c5d2144eb700e60d0dfa5c98", model: "hunyuan-lite", version: "202404011000", choices: Array(1), …} // {created: 1723013866, id: "a95a54b5c5d2144eb700e60d0dfa5c98", model: "hunyuan-lite", version: "202404011000", choices: Array(1), …} // {created: 1723013866, id: "a95a54b5c5d2144eb700e60d0dfa5c98", model: "hunyuan-lite", version: "202404011000", choices: Array(1), …} // {created: 1723013866, id: "a95a54b5c5d2144eb700e60d0dfa5c98", model: "hunyuan-lite", version: "202404011000", choices: Array(1), …} // {created: 1723013866, id: "a95a54b5c5d2144eb700e60d0dfa5c98", model: "hunyuan-lite", version: "202404011000", choices: Array(1), …} // {created: 1723013866, id: "a95a54b5c5d2144eb700e60d0dfa5c98", model: "hunyuan-lite", version: "202404011000", choices: Array(1), …} // {created: 1723013866, id: "a95a54b5c5d2144eb700e60d0dfa5c98", model: "hunyuan-lite", version: "202404011000", choices: Array(1), …} ``` ## Bot 用于与 Agent 交互的类。 ### get() 获取某个 Agent 的信息。 #### 使用示例 ```ts const res = await ai.bot.get({ botId: "botId-xxx" }); console.log(res); ``` #### 类型声明 ```ts function get(props: { botId: string }); ``` #### 参数 | 参数名 | 必填 | 类型 | 说明 | | ----------- | ---- | ------ | ------------------------ | | props.botId | 是 | string | 要获取信息的 Agent 的 id | #### 返回值 | 属性名 | 类型 | 示例 | 说明 | | --------------- | ------- | ---------------- | ------------------------ | | botId | string | `"bot-27973647"` | Agent ID | | name | string | `"信达雅翻译"` | Agent 名称 | | introduction | string | | Agent 简介 | | welcomeMessage | string | | Agent 欢迎语 | | avatar | string | | Agent 头像链接 | | background | string | | Agent 聊天背景图链接 | | isNeedRecommend | boolean | | Agent 回答后是否推荐问题 | | type | string | | Agent 类型 | ### list() 批量获取多个 Agent 的信息。 #### 使用示例 ```ts await ai.bot.list({ pageNumber: 1, pageSize: 10, name: "", enable: true, information: "", introduction: "", }); ``` #### 类型声明 ```ts function list(props: { name: string; introduction: string; information: string; enable: boolean; pageSize: number; pageNumber: number; }); ``` #### 参数 | 参数名 | 必填 | 类型 | 说明 | | ------------------ | ---- | ------- | ------------------------ | | props.pageNumber | 是 | number | 分页下标 | | props.pageSize | 是 | number | 分页大小 | | props.enable | 是 | boolean | Agent 是否启用 | | props.name | 是 | string | Agent 名字,用于模糊查询 | | props.information | 是 | string | Agent 信息,用于模糊查询 | | props.introduction | 是 | string | Agent 简介,用于模糊查询 | #### 返回值 | 属性名 | 类型 | 示例 | 说明 | | ---------------------------- | --------------- | ---------------- | ------------------------ | | total | number | --- | Agent 总数 | | botList | `Array` | | Agent 列表 | | `botList[n].botId` | string | `"bot-27973647"` | Agent ID | | `botList[n].name` | string | `"信达雅翻译"` | Agent 名称 | | `botList[n].introduction` | string | | Agent 简介 | | `botList[n].welcomeMessage` | string | | Agent 欢迎语 | | `botList[n].avatar` | string | | Agent 头像链接 | | `botList[n].background` | string | | Agent 聊天背景图链接 | | `botList[n].isNeedRecommend` | boolean | | Agent 回答后是否推荐问题 | | `botList[n].type` | string | | Agent 类型 | ### sendMessage() 与 Agent 进行对话。响应会通过 SSE 返回,该接口的返回值对 SSE 做了不同程度的封装,开发者能根据实际需求获取到文本流和完整数据流。 #### 使用示例 ```ts const res = await ai.bot.sendMessage({ botId: "botId-xxx", history: [{ content: "你是李白。", role: "user" }], msg: "你好", }); for await (let str of res.textStream) { console.log(str); } for await (let data of res.dataStream) { console.log(data); } ``` #### 类型声明 ```ts function sendMessage(props: { botId: string; msg: string; history: Array; }): Promise; ``` #### 参数 | 参数名 | 必填 | 类型 | 说明 | | -------------------------- | ---- | ------ | -------------------------- | | props.botId | 是 | string | Agent id | | props.msg | 是 | string | 此次对话要发送的消息 | | props.history | 是 | [] | 在此次对话前发生的聊天记录 | | `props.history[n].role` | 是 | string | 本聊天信息的发送角色 | | `props.history[n].content` | 是 | string | 本聊天信息的内容 | #### 返回值 `Promise` | StreamResult 属性名 | 类型 | 说明 | | ------------------- | ---- | ---- | | textStream | `AsyncIterable` | 以流式返回的 Agent 生成文本,可参考使用示例获取到生成的增量文本。 | | dataStream | `AsyncIterable` | 以流式返回的 Agent 生成文本,可参考使用示例获取到生成的增量文本。 | | AgentStreamChunk 属性名 | 类型 | 说明 | | ------------------- | ---- | ---- | | created | number | 对话时间戳 | | record_id | string | 对话记录ID | | model | string | 大模型类型 | | version | string | 大模型版本 | | type | string | 回复类型: text: 主要回答内容,thinking: 思考过程,search: 查询结果,knowledge: 知识库 | | role | string | 对话角色,响应中固定为 assistant | | content | string | 对话内容 | | finish_reasion | string | 对话结束标志,continue 表示对话未结束,stop 表示对话结束 | | reasoning_content | string | 深度思考内容(仅deepseek-r1是不为空字符串) | | usage | object | token使用量 | | usage.prompt_tokens | number | 表示prompt的tokens数,多次返回中保持不变 | | usage.completion_tokens | number | 回答的token总数,在流式返回中,表示到目前为止所有completion的tokens总数,多次返回中持续累加 | | usage.total_tokens | number | 表示prompt_tokens和completion_tokens之和 | | knowledge_base | string[] | 对话中使用到的知识库 | | search_info | object | 搜索结果信息,需要开启联网查询 | | search_info.search_results | object[] | 搜索引文信息 | | search_info.search_results[n].index | string | 搜索引文序号 | | search_info.search_results[n].title | string | 搜索引文标题 | | search_info.search_results[n].url | string | 搜索引文链接 | ### getChatRecords() 获取聊天记录。 #### 使用示例 ```ts await ai.bot.getChatRecords({ botId: "botId-xxx", pageNumber: 1, pageSize: 10, sort: "asc", }); ``` #### 类型声明 ```ts function getChatRecords(props: { botId: string; sort: string; pageSize: number; pageNumber: number; }); ``` #### 参数 | 参数名 | 必填 | 类型 | 说明 | | ---------------- | ---- | ------ | -------- | | props.botId | 是 | string | Agent id | | props.sort | 是 | string | 排序方式 | | props.pageSize | 是 | number | 分页大小 | | props.pageNumber | 是 | number | 分页下标 | #### 返回值 | 属性名 | 类型 | 说明 | | ---------------------------- | --------------- | ------------------- | | total | number | 对话总数 | | recordList | `Array` | 对话总数 | | `recordList[n].botId` | string | Agent ID | | `recordList[n].recordId` | string | 对话 ID,由系统生成 | | `recordList[n].role` | string | 对话中的角色 | | `recordList[n].content` | string | 对话内容 | | `recordList[n].conversation` | string | 用户标识 | | `recordList[n].type` | string | 对话数据类型 | | `recordList[n].image` | string | 对话生成的图片链接 | | `recordList[n].triggerSrc` | string | 对话发起来源 | | `recordList[n].replyTo` | string | 对话回复的记录 ID | | `recordList[n].createTime` | string | 对话时间 | ### sendFeedback() 发送对某条聊天记录的反馈信息。 #### 使用示例 ```ts const res = await ai.bot.sendFeedback({ userFeedback: { botId: "botId-xxx", recordId: "recordId-xxx", comment: "非常棒", rating: 5, tags: ["优美"], aiAnswer: "落英缤纷", input: "来个成语", type: "upvote", }, botId: "botId-xxx", }); ``` #### 类型声明 ```ts function sendFeedback(props: { userFeedback: IUserFeedback; botId: string }); ``` #### 参数 | 参数名 | 必填 | 类型 | 说明 | | ------------------ | ---- | ------------- | ------------------------------------------------------- | | props.userFeedback | 是 | IUserFeedback | 用户反馈,详见 [IUserFeedback 类型定义](#iuserfeedback) | | props.botId | 是 | string | 将要反馈的 Agent id | ### getFeedback() 获取已存在的反馈信息。 #### 使用示例 ```ts const res = await ai.bot.getFeedback({ botId: "botId-xxx", from: 0, to: 0, maxRating: 4, minRating: 3, pageNumber: 1, pageSize: 10, sender: "user-a", senderFilter: "include", type: "upvote", }); ``` #### 类型声明 ```ts function sendFeedback(props: { botId: string; type: string; sender: string; senderFilter: string; minRating: number; maxRating: number; from: number; to: number; pageSize: number; pageNumber: number; }); ``` #### 参数 | 参数名 | 必填 | 类型 | 说明 | | ------------------ | ---- | ------ | -------------------------------------------------------------------------------------- | | props.botId | 是 | string | Agent id | | props.type | 是 | string | 用户反馈类型,点赞 upvote 点踩 downvote | | props.sender | 是 | string | 评论创建用户 | | props.senderFilter | 是 | string | 评论创建用户过滤关系 include:包含 exclude:不包含 equal:等于 unequal:不等于 prefix:前缀 | | props.minRating | 是 | number | 最低评分 | | props.maxRating | 是 | number | 最高评分 | | props.from | 是 | number | 开始时间戳 | | props.to | 是 | number | 结束时间戳 | | props.pageSize | 是 | number | 分页大小 | | props.pageNumber | 是 | number | 分页下标 | #### 返回值 | 属性名 | 类型 | 说明 | | ------------------------ | -------- | --------------------------------------- | | feedbackList | object[] | 反馈查询结果 | | feedbackList[n].recordId | string | 对话记录 ID | | feedbackList[n].type | string | 用户反馈类型,点赞 upvote 点踩 downvote | | feedbackList[n].botId | string | Agent ID | | feedbackList[n].comment | string | 用户评论 | | feedbackList[n].rating | number | 用户评分 | | feedbackList[n].tags | string[] | 用户反馈的标签数组 | | feedbackList[n].input | string | 用户输入的问题 | | feedbackList[n].aiAnswer | string | Agent 的回答 | | total | number | 反馈总数 | ### uploadFiles() 将云存储中的文件上传至 Agent,用于进行文档聊天。 #### 使用示例 ```ts // 上传文件 await ai.bot.uploadFiles({ botId: "botId-xxx", fileList: [ { fileId: "cloud://xxx.docx", fileName: "xxx.docx", type: "file", }, ], }); // 进行文档聊天 const res = await ai.bot.sendMessage({ botId: "your-bot-id", msg: "这个文件的内容是什么", files: ["xxx.docx"], // 文件 fileId 数组 }); for await (let text of res.textStream) { console.let(text); } ``` #### 类型声明 ```ts function uploadFiles(props: { botId: string; fileList: Array; }); ``` #### 参数 | 参数名 | 必填 | 类型 | 说明 | | -------------------------- | ---- | ------ | ------------------- | | props.botId | 是 | string | Agent id | | props.fileList | 是 | string | 文件列表 | | props.fileList[n].fileId | 是 | string | 云存储文件 id | | props.fileList[n].fileName | 是 | string | 文件名 | | props.fileList[n].type | 是 | string | 暂时只支持 `"file"` | ### getRecommendQuestions() 获取推荐的问题。 #### 使用示例 ```ts const res = ai.bot.getRecommendQuestions({ botId: "botId-xxx", history: [{ content: "你是谁啊", role: "user" }], msg: "你好", agentSetting: "", introduction: "", name: "", }); for await (let str of res.textStream) { console.log(str); } ``` #### 类型声明 ```ts function getRecommendQuestions(props: { botId: string; name: string; introduction: string; agentSetting: string; msg: string; history: Array; }): Promise; ``` #### 参数 | 参数名 | 必填 | 类型 | 说明 | | -------------------------- | ---- | ------ | ------------ | | props.botId | 是 | string | Agent id | | props.name | 是 | string | Agent 名称 | | props.introduction | 是 | string | Agent 简介 | | props.agentSetting | 是 | string | Agent 设定 | | props.msg | 是 | string | 用户发送信息 | | props.history | 是 | Array | 历史对话信息 | | `props.history[n].role` | 是 | string | 历史信息角色 | | `props.history[n].content` | 是 | string | 历史信息内容 | #### 返回值 `Promise` | StreamResult 属性名 | 类型 | 说明 | | ------------------- | ---- | ---- | | textStream | `AsyncIterable` | 以流式返回的 Agent 生成文本,可参考使用示例获取到生成的增量文本。 | | dataStream | `AsyncIterable` | 以流式返回的 Agent 生成文本,可参考使用示例获取到生成的增量文本。 | | AgentStreamChunk 属性名 | 类型 | 说明 | | ------------------- | ---- | ---- | | created | number | 对话时间戳 | | record_id | string | 对话记录ID | | model | string | 大模型类型 | | version | string | 大模型版本 | | type | string | 回复类型: text: 主要回答内容,thinking: 思考过程,search: 查询结果,knowledge: 知识库 | | role | string | 对话角色,响应中固定为 assistant | | content | string | 对话内容 | | finish_reasion | string | 对话结束标志,continue 表示对话未结束,stop 表示对话结束 | | reasoning_content | string | 深度思考内容(仅deepseek-r1是不为空字符串) | | usage | object | token使用量 | | usage.prompt_tokens | number | 表示prompt的tokens数,多次返回中保持不变 | | usage.completion_tokens | number | 回答的token总数,在流式返回中,表示到目前为止所有completion的tokens总数,多次返回中持续累加 | | usage.total_tokens | number | 表示prompt_tokens和completion_tokens之和 | | knowledge_base | string[] | 对话中使用到的知识库 | | search_info | object | 搜索结果信息,需要开启联网查询 | | search_info.search_results | object[] | 搜索引文信息 | | search_info.search_results[n].index | string | 搜索引文序号 | | search_info.search_results[n].title | string | 搜索引文标题 | | search_info.search_results[n].url | string | 搜索引文链接 | ### createConversation() 创建与 Agent 的新对话。 #### 使用示例 ```ts const res = await ai.bot.createConversation({ botId: "botId-xxx", title: "我的对话", }): Promise; ``` #### 类型声明 ```ts function createConversation(props: IBotCreateConversation); ``` #### 参数 | 参数名 | 必填 | 类型 | 说明 | | ----------- | ---- | ------ | -------- | | props.botId | 是 | string | Agent ID | | props.title | 否 | string | 对话标题 | #### 返回值 `Promise` 相关类型:[IConversation](#iconversation) ### getConversation() 获取对话列表。 #### 使用示例 ```ts const res = await ai.bot.getConversation({ botId: "botId-xxx", pageSize: 10, pageNumber: 1, isDefault: false, }); ``` #### 类型声明 ```ts function getConversation(props: IBotGetConversation); ``` #### 参数 | 参数名 | 必填 | 类型 | 说明 | | ---------------- | ---- | ------- | ------------------ | | props.botId | 是 | string | Agent ID | | props.pageSize | 否 | number | 分页大小,默认 10 | | props.pageNumber | 否 | number | 分页下标,默认 1 | | props.isDefault | 否 | boolean | 是否只获取默认对话 | ### deleteConversation() 删除指定对话。 #### 使用示例 ```ts await ai.bot.deleteConversation({ botId: "botId-xxx", conversationId: "conv-123", }); ``` #### 类型声明 ```ts function deleteConversation(props: IBotDeleteConversation); ``` #### 参数 | 参数名 | 必填 | 类型 | 说明 | | -------------------- | ---- | ------ | --------------- | | props.botId | 是 | string | Agent ID | | props.conversationId | 是 | string | 要删除的对话 ID | ### speechToText() 语音转文字。 #### 使用示例 ```ts const res = await ai.bot.speechToText({ botId: "botId-xxx", engSerViceType: "16k_zh", voiceFormat: "mp3", url: "https://example.com/audio.mp3", }); ``` #### 类型声明 ```ts function speechToText(props: IBotSpeechToText); ``` #### 参数 | 参数名 | 必填 | 类型 | 说明 | | -------------------- | ---- | ------- | -------------------- | | props.botId | 是 | string | Agent ID | | props.engSerViceType | 是 | string | 引擎类型,如"16k_zh" | | props.voiceFormat | 是 | string | 音频格式,如"mp3" | | props.url | 是 | string | 音频文件 URL | | props.isPreview | 否 | boolean | 是否为预览模式 | ### textToSpeech() 文字转语音。 #### 使用示例 ```ts const res = await ai.bot.textToSpeech({ botId: "botId-xxx", voiceType: 1, text: "你好,我是AI助手", }); ``` #### 类型声明 ```ts function textToSpeech(props: IBotTextToSpeech); ``` #### 参数 | 参数名 | 必填 | 类型 | 说明 | | --------------- | ---- | ------- | -------------- | | props.botId | 是 | string | Agent ID | | props.voiceType | 是 | number | 语音类型 | | props.text | 是 | string | 要转换的文本 | | props.isPreview | 否 | boolean | 是否为预览模式 | ### getTextToSpeechResult() 获取文字转语音的结果。 #### 使用示例 ```ts const res = await ai.bot.getTextToSpeechResult({ botId: "botId-xxx", taskId: "task-123", }); ``` #### 类型声明 ```ts function getTextToSpeechResult(props: IBotGetTextToSpeechResult); ``` #### 参数 | 参数名 | 必填 | 类型 | 说明 | | --------------- | ---- | ------- | -------------- | | props.botId | 是 | string | Agent ID | | props.taskId | 是 | string | 任务 ID | | props.isPreview | 否 | boolean | 是否为预览模式 | ## IBotCreateConversation ```ts interface IBotCreateConversation { botId: string; title?: string; } ``` ## IBotGetConversation ```ts interface IBotGetConversation { botId: string; pageSize?: number; pageNumber?: number; isDefault?: boolean; } ``` ## IBotDeleteConversation ```ts interface IBotDeleteConversation { botId: string; conversationId: string; } ``` ## IBotSpeechToText ```ts interface IBotSpeechToText { botId: string; engSerViceType: string; voiceFormat: string; url: string; isPreview?: boolean; } ``` ## IBotTextToSpeech ```ts interface IBotTextToSpeech { botId: string; voiceType: number; text: string; isPreview?: boolean; } ``` ## IBotGetTextToSpeechResult ```ts interface IBotGetTextToSpeechResult { botId: string; taskId: string; isPreview?: boolean; } ``` ## BaseChatModelInput ```ts interface BaseChatModelInput { model: string; messages: Array; temperature?: number; topP?: number; tools?: Array; toolChoice?: "none" | "auto" | "custom"; maxSteps?: number; onStepFinish?: (prop: IOnStepFinish) => unknown; } ``` | BaseChatModelInput 属性名 | 类型 | 说明 | | ------------------------- | ---------------------------------- | --------------------------------------------------- | | model | `string` | 模型名称。 | | messages | `Array` | 消息列表。 | | temperature | `number` | 采样温度,控制输出的随机性。 | | topP | `number` | 温度采样,即模型考虑概率质量为 top_p 的标记的结果。 | | tools | `Array` | 大模型可用的工具列表。 | | toolChoice | `string` | 指定大模型选择工具的方式。 | | maxSteps | `number` | 请求大模型的最大次数。 | | onStepFinish | `(prop: IOnStepFinish) => unknown` | 当对大模型的一次请求完成时,出发的回调函数。 | ## BotInfo ```ts interface BotInfo { botId: string; name: string; introduction: string; agentSetting: string; welcomeMessage: string; avatar: string; background: string; tags: Array; isNeedRecommend: boolean; knowledgeBase: Array; type: string; initQuestions: Array; enable: true; } ``` ## IUserFeedback ```ts interface IUserFeedback { recordId: string; type: string; botId: string; comment: string; rating: number; tags: Array; input: string; aiAnswer: string; } ``` ## ChatModelMessage ```ts type ChatModelMessage = | UserMessage | SystemMessage | AssistantMessage | ToolMessage; ``` ### UserMessage ```ts type UserMessage = { role: "user"; content: string; }; ``` ### SystemMessage ```ts type SystemMessage = { role: "system"; content: string; }; ``` ### AssistantMessage ```ts type AssistantMessage = { role: "assistant"; content?: string; tool_calls?: Array; }; ``` ### ToolMessage ```ts type ToolMessage = { role: "tool"; tool_call_id: string; content: string; }; ``` ## ToolCall ```ts export type ToolCall = { id: string; type: string; function: { name: string; arguments: string }; }; ``` ## FunctionTool 工具定义类型。 ```ts type FunctionTool = { name: string; description: string; fn: CallableFunction; parameters: object; }; ``` | FunctionTool 属性名 | 类型 | 说明 | | ------------------- | ------------------ | -------------------------------------------------------------------------------------------------- | | name | `string` | 工具名称。 | | description | `string` | 工具的描述。清楚的工具描述有助于大模型认识工具的用途。 | | fn | `CallableFunction` | 工具的执行函数。当 AI SDK 解析出大模型的响应需要该工具调用时,会调用此函数,并将结果返回给大模型。 | | parameters | `object` | 工具执行函数的入参。需要使用 JSON Schema 的格式定义入参。 | ## IOnStepFinish 大模型响应后出发的回调函数的入参类型。 ```ts interface IOnStepFinish { messages: Array; text?: string; toolCall?: ToolCall; toolResult?: unknown; finishReason?: string; stepUsage?: Usage; totalUsage?: Usage; } ``` | IOnStepFinish 属性名 | 类型 | 说明 | | -------------------- | ------------------------- | -------------------------------- | | messages | `Array` | 到当前步骤为止所有的消息列表。 | | text | `string` | 当前响应的文本。 | | toolCall | `ToolCall` | 当前响应调用的工具。 | | toolResult | `unknown` | 对应的工具调用结果。 | | finishReason | `string` | 大模型推理结束的原因。 | | stepUsage | `Usage` | 当前步骤所花费的 token。 | | totalUsage | `Usage` | 到当前步骤为止所花费的总 token。 | ## Usage ```ts type Usage = { completion_tokens: number; prompt_tokens: number; total_tokens: number; }; ``` ## IConversation Agent 会话。 ```ts interface IConversation { id: string; envId: string; ownerUin: string; userId: string; conversationId: string; title: string; startTime: string; // date-time format createTime: string; updateTime: string; } ``` --- ## 广告数据上报 # 广告数据上报 ## analytics #### 1. 接口描述 接口功能:上报广告数据 接口声明:`analytics(object: Object): Promise` :::tip 提示 自 SDK 1.4.0 版本起支持此接口,使用时需结合微信授权登录使用 ::: #### 2. 输入参数 | 字段 | 类型 | 必填 | 说明 | | ----------- | ----------- | ---- | ------------------------- | | report_type | string | 是 | 上报类型,目前支持 "mall" | | report_data | IReportData | 是 | 上报内容 | ##### IReportData | 字段 | 类型 | 必填 | 说明 | | ------------- | ------------- | ---- | ------------------------------------------------------------------------------------------------ | | action_time | number | 否 | 上报时间,不填默认取当前客户端时间,单位为秒 | | action_type | string | 是 | 行为类型 如 访问 visit_store,分享 share,加入购物车 add_to_cart 等,详细类型参考表 action_types | | click_id | string | 否 | 广告平台会在 URL 增加 click_id,取值方式[参考](https://ad.weixin.qq.com/guide/457) | | action_param | IActionParam | 否 | 行为所带的参数 | | product_param | IProductParam | 否 | 商品结构内容 | ##### IActionParam | 字段 | 类型 | 必填 | 说明 | | ---------- | ------ | ---- | --------------------------------------------------------- | | value | number | 否 | 行为所带的参数,转化行为价值(例如金额) | | leads_type | string | 否 | 行为来源,目前支持 PHONE(电话直呼),RESERVE(表单预约) | ##### IProductParam | 字段 | 类型 | 必填 | 说明 | | ----------------------- | ------ | ---- | ---------------------------------------------- | | product_yun_type | string | 否 | 商品 goods ,优惠券 coupon, 搜索词 search_term | | product_yun_id | string | 否 | 商品 id | | product_yun_category | string | 否 | 商品类目 自定义 | | product_yun_keywords | string | 否 | 商品关键词 | | product_yun_price | number | 否 | 商品原价 | | product_yun_value | number | 否 | 商品成交价 | | product_yun_name | string | 否 | 商品名 | | product_yun_id_ad | string | 否 | 广告商品库中商品 id | | product_yun_category_ad | string | 否 | 广告商品库中商品类目 | ##### action_types | 类型值 | 说明 | | --------------- | ---------- | | visit_store | 访问 | | share | 分享 | | consult | 咨询 | | claim_offer | 卡券领取 | | add_to_cart | 加入购物车 | | add_to_wishlist | 收藏 | | complete_order | 下单 | | purchase | 支付 | | search | 搜索 | | deliver | 发货 | | sign_in | 签收 | #### 3. 输出参数 无 #### 4. 示例代码 ```javascript import cloudbase from "@cloudbase/js-sdk"; //初始化SDK实例 const app = cloudbase.init({ env: "xxxx-yyy" }); // 微信授权登录 const provider = auth.weixinAuthProvider({ appid: "...", scope: "xxxx" }); provider.getRedirectResult().then((loginState) => { if (loginState) { // 登录成功! app.analytics({ report_type: "mall", report_data: { action_type: "visit_store", action_param: { value: 100 }, product_param: { product_yun_type: "goods", product_yun_id: 1, product_yun_keywords: "优衣库", product_yun_price: 200, product_yun_value: 100, product_yun_name: "优衣库Utee-迪士尼" } } }); } }); ``` --- ## API Key 配置 # API Key 配置 ## 概述 API Keys 是腾讯云开发(Tencent Cloud Base)的核心身份验证凭证,用于控制资源访问权限。 其功能定位是决定哪些资源可被访问(如 HTTP API、云函数、云托管等),而非用户身份认证。 与登录认证的区别: | 类型 | 含义 | 举例 | | -------- | ---------------------- | --------------------------------------------------- | | API Keys | 资源访问权限控制 | HTTP API、云函数、云托管、数据库、数据模型、AI 等 | | 登录认证 | 用户身份验证与权限管理 | 默认访客、默认外部用户、默认内部用户等 | ## API Keys 类型 API Keys 用于验证资源访问的权限,使应用能够访问腾讯云的资源服务。资源可以是 [HTTP API](https://docs.cloudbase.net/http-api/basic/overview)、[云函数](https://docs.cloudbase.net/api-reference/webv3/functions)、[云托管](https://docs.cloudbase.net/api-reference/webv3/cloudrun)等。API Keys 不用于区分用户。 目前腾讯云支持 2 类 API Keys,需在 [API Key 配置](https://tcb.cloud.tencent.com/dev?#/env/apikey)进行管理,配置示例如下: API Keys 的含义如下所示: | 类型 | 格式 | 使用场景 | 安全要求 | | ---------------------- | ------------------- | ---------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------ | | 客户端 Publishable key | JWT(长期有效) | 可以暴露在浏览器,用于请求公开访问的资源,如云函数、云托管等。Publishable Key 实际是一个匿名用户权限,可以有效降低 MAU | 禁止用于敏感操作 | | 服务端 API Key | JWT(可配置有效期) | API Key 用于请求云开发的 HTTP API,仅在创建时可见,请妥善保管。 | 请勿与他人共享你的 API Key,也不要将其暴露于浏览器或其他客户端代码之中 ​ | ## API Keys 使用规范 API Keys 提供最基础的腾讯云公共资源保护,但访问公共资源的应用可能运行在不受任何密钥保护的环境中,例如: * Web 应用,API Keys 会被暴露在源代码中 * 移动或桌面应用程序,API Keys 被暴露在编译后的包或可执行文件中 * 小程序应用,API Keys 会被暴露在打包的产物中 * 其他公开发布的 API,无需事先额外授权即可返回密钥 所以使用 API Keys 清注意对以下行为进行保护 * 静态或动态代码分析和逆向工程尝试获取 * 在浏览器中使用网络检查器 * 跨站请求伪造、跨站脚本、网络钓鱼攻击 * 中间人攻击 :::tip 安全警示 Publishable Key 可能需配合默认访客角色权限限制数据访问。 服务端 API Key 推荐存储于安全环境(如服务器内存),避免写入代码/配置文件 ::: ## Publishable Key 与登录认证的关系 使用 Publishable Key 并不意味着已经采用默认访客的身份进行了登录,可以理解为仅仅是使用可公开访问的密钥进行资源访问,而不携带任何其他用户信息。 在应用中可以使用 Publishable Key 进行腾讯云资源访问,而使用应用的用户也可以通过[登录认证](https://docs.cloudbase.net/api-reference/webv3/authentication)的方式使用个人的 access_token 进行访问,二者并不冲突,关系如下图所示: 例如:当用户访问应用时,未进行任何登录认证,存在 Publishable Key 的情况下,使用 Publishable Key 进行资源访问;当用户进行登录认证后,他将不再以 Publishable Key 的方式进行资源访问,而是使用个人的 access_token 进行资源访问。 ## 使用方式 ### 客户端 Publishable Key 使用 首先前往[ API Key 配置页面](https://tcb.cloud.tencent.com/dev?#/env/apikey)获取长期有效的 Publishable Key,然后在初始化 sdk 时将其赋值给 accessKey 字段 :::tip 提示 Publishable Key 只能生成一次,并且是长期有效的、不能删除的,请妥善保管 使用此功能请升级 @cloudbase/js-sdk 至 2.21.0 及以后版本 ::: ```js const app = cloudbase.init({ env: "xxxx-yyy", clientId: "xxxxx", accessKey: "Publishable Key", }); // 此时访问资源时会带上 accessKey // 调用云函数,携带在参数中的 access_token app.callFunction({ name: "test" }); // 调用云托管,携带在请求头中的 Authorization app.callContainer({ name: "xxx", method: "POST", path: "/", header: { "Content-Type": "application/json; charset=utf-8", }, data: {}, }); // 调用数据模型,携带在请求头中的 Authorization app.models.test.get(); ``` ### 服务端 API Key 使用 首先前往[ API Key 配置页面](https://tcb.cloud.tencent.com/dev?#/env/apikey)获取 API Key,然后在使用 HTTP API 请求时带上 API Key,详见 [HTTP API 使用说明](https://docs.cloudbase.net/http-api/basic/overview) :::tip 提示 服务端 API Key 可以创建多个,并且可以单独设置过期时间,创建 API Key 时系统不会保存对应的值,仅在创建时可见,请妥善保管。请勿与他人共享,也不要将其暴露于浏览器或其他客户端代码之中 ::: --- ## 登录认证 import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # 登录认证 :::tip 提示 新登录体系下,确保一个环境对应一个 tcb 实例(避免多次初始化相同环境的 tcb 实例) ::: ## App.auth() #### 接口描述 返回 [`Auth`](#auth) 对象 签名:`auth(): Auth` :::warning @cloudbase/js-sdk@2.x 版本将只支持 `local` 方式(Web 端在显式退出登录之前 30 天保留身份验证状态)存储身份状态。(原 1.x 版本的 `session` 及 `none` 模式不再支持) ::: #### 示例代码 ```js import cloudbase from "@cloudbase/js-sdk"; const app = cloudbase.init({ env: "xxxx-yyy", clientId: "xxxx", }); const auth = app.auth(); ``` ## 注册/登录/登出相关 ### Auth.signUp #### 接口描述 接口功能:注册用户,目前支持手机号验证码注册,邮箱验证码注册。 接口声明:`signUp(params: SignUpRequest): Promise` ##### SignUpRequest | 字段 | 类型 | 必填 | 说明 | | ------------------ | ------ | ---- | ------------------------------------------------------ | | phone_number | string | 否 | 注册所用手机号,phone_number 与 email 必须任选其一使用 | | email | string | 否 | 注册所用邮箱 ,phone_number 与 email 必须任选其一使用 | | verification_code | string | 否 | 验证码 | | verification_token | string | 否 | 验证码 token | | provider_token | string | 否 | 第三方 provider token | | password | string | 否 | 密码 | | name | string | 否 | 用户名 | | gender | string | 否 | 性别 | | picture | string | 否 | 头像 | | locale | string | 否 | 地址 | #### 示例代码 ```js // 初始化SDK const app = cloudbase.init({ env: "xxxx-yyy", clientId: "xxxxx", }); const auth = app.auth(); // 例:手机号验证码注册 // 1. 发送手机验证码 const phoneNumber = "+86 13800000000"; const verification = await auth.getVerification({ phone_number: phoneNumber, }); // 若使用邮箱验证,第一步代码改为 const email = "test@example.com"; const verification = await auth.getVerification({ email: email, }); // 2. 验证码验证 // 调用发送短信接口后,手机将会收到云开发的短信验证码。 // 用户填入短信验证码,可以调用下面的接口进行验证。 // 假设已收到用户填入的验证码"000000" const verificationCode = "000000"; // 验证验证码的正确性 const verificationTokenRes = await auth.verify({ verification_id: verification.verification_id, verification_code: verificationCode, }); // 3. 注册 // 如果该用户已经存,则登录 if (verification.is_user) { await auth.signIn({ username: phoneNumber, verification_token: verificationTokenRes.verification_token, }); } else { // 否则,则注册新用户,注册新用户时,可以设置密码,用户名 // 备注:signUp 成功后,会自动登录 await auth.signUp({ phone_number: phoneNumber, verification_code: verificationCode, verification_token: verificationTokenRes.verification_token, // 可选,设置昵称 name: "手机用户", // 可选,设置密码 password: "password", // 可选,设置登录用户名 username: "username", }); } ``` ```bash # bash 下调用接口的例子 # 环境ID export env="your-env-id" # 获取设备ID,安卓,IOS 或 小程序平台可调用接口获取 export deviceID="demo_device_5dh6nf" # 生成request ID (默认采用 32 位UUID 即可,可自行生成) export requestID="3af464bf930dbdb83f587990a1a55cb9" # 1. 发送手机验证码 curl 'https://${env}.ap-shanghai.tcb-api.tencentcloudapi.com/auth/v1/verification' \ -H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36' \ -H 'x-device-id': ${deviceID} \ -H 'x-request-id': ${requestID} \ -u ${clientID}:${clientSecrect} --data-raw '{"phone_number":"+86 13800000000"}' \ --compressed # 2. 验证码验证 curl 'https://${env}.ap-shanghai.tcb-api.tencentcloudapi.com/auth/v1/verification/verify' \ -H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36' \ -H 'x-device-id': ${deviceID} \ -H 'x-request-id': ${requestID} \ -u ${clientID}:${clientSecrect} --data-raw '{"verification_code":"000000", "verification_id": "verification_id"}' \ --compressed # 3. 登录 curl 'https://${env}.ap-shanghai.tcb-api.tencentcloudapi.com/auth/v1/signin' \ -H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36' \ -H 'x-device-id': ${deviceID} \ -H 'x-request-id': ${requestID} \ -u ${clientID}:${clientSecrect} --data-raw '{"username":"test","password":"test"}' \ --compressed ``` ### Auth.signIn #### 接口描述 接口功能:登录用户,目前支持手机号,邮箱,用户名密码登录。 接口声明:`signIn(params: SignInRequest): Promise` ##### SignInRequest | 字段 | 类型 | 必填 | 说明 | | ------------------ | ------ | ---- | ---------------------------------------------------------- | | username | string | 是 | 用户手机号,邮箱或自定义用户名 | | password | string | 否 | 用户密码 ,password 与 verification_token 必须任选其一 | | verification_token | string | 否 | 验证码 token ,password 与 verification_token 必须任选其一 | #### 示例代码 ```js const app = cloudbase.init({ env: "xxxx-yyy", clientId: "xxxxx", }); const auth = app.auth(); // 已完成注册 // 例:手机号登录 const phoneNumber = "+86 13800000000"; await auth.signIn({ username: phoneNumber, password: "your password", }); // 例:邮箱登录 const email = "test@example.com"; await auth.signIn({ username: email, password: "your password", }); // 例:用户名登录 const username = "myname"; await auth.signIn({ username, password: "your password", }); ``` ```bash # bash 下调用接口的例子 # 环境ID export env="your-env-id" # 获取设备ID,安卓,IOS 或 小程序平台可调用接口获取 export deviceID="demo_device_5dh6nf" # 生成request ID (默认采用 32 位UUID 即可,可自行生成) export requestID="3af464bf930dbdb83f587990a1a55cb9" # 1. 手机号登录 curl 'https://${env}.ap-shanghai.tcb-api.tencentcloudapi.com/auth/v1/signin' \ -X POST \ -H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36' \ -H 'x-device-id': ${deviceID} \ -H 'x-request-id': ${requestID} \ -u ${clientID}:${clientSecrect} --data-raw '{"phone_number":"+86 13800000000", "password": "your password"}' \ --compressed ``` ### Auth.signOut() #### 接口描述 登出云开发 签名:`signOut(): Promise` #### 示例代码 ```js const app = cloudbase.init({ env: "xxxx-yyy", }); const auth = app.auth(); await auth.signOut(); ``` ```bash # bash 下调用接口的例子 # 环境ID export env="your-env-id" # 获取设备ID,安卓,IOS 或 小程序平台可调用接口获取 export deviceID="demo_device_5dh6nf" # 生成request ID (默认采用 32 位UUID 即可,可自行生成) export requestID="3af464bf930dbdb83f587990a1a55cb9" curl 'https://${env}.ap-shanghai.tcb-api.tencentcloudapi.com/auth/v1/revoke' \ -H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36' \ -H 'x-device-id': ${deviceID} \ -H 'x-request-id': ${requestID} \ -u ${clientID}:${clientSecrect} --data-raw '{"token": "your access token"}' \ --compressed ``` ### Auth.signInAnonymously() #### 接口描述 匿名登录 接口声明 `signInAnonymously(): Promise` #### 示例代码 ```js const app = cloudbase.init({ env: "xxxx-yyy", }); const auth = app.auth(); await auth.signInAnonymously(); ``` ```bash # bash 下调用接口的例子 # 环境ID export env="your-env-id" # 获取设备ID,安卓,IOS 或 小程序平台可调用接口获取 export deviceID="demo_device_5dh6nf" # 生成request ID (默认采用 32 位UUID 即可,可自行生成) export requestID="3af464bf930dbdb83f587990a1a55cb9" curl 'https://${env}.ap-shanghai.tcb-api.tencentcloudapi.com/auth/v1/signin/anonymously' \ -H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36' \ -H 'x-device-id': ${deviceID} \ -H 'x-request-id': ${requestID} \ -u ${clientID}:${clientSecrect} --data-raw '{}' \ --compressed ``` 匿名登录转正示例 ```js const app = cloudbase.init({ env: "xxxx-yyy" }) const auth = app.auth() // 1. 匿名登录 await auth.signInAnonymously() // 2. 获取accesstoken const access_token = await auth.getAccessToken() // 3. 转正注册 await auth.signUp({ ...// 传参参考 Auth.signUp接口 anonymous_token: access_token }) ``` ### Auth.setCustomSignFunc() #### 接口描述 设置获取自定义登录 ticket 函数 接口声明 `setCustomSignFunc(getTickFn: GetCustomSignTicketFn): void` #### GetCustomSignTicketFn ```js GetCustomSignTicketFn = () => Promise ``` #### 示例代码 ```js const app = cloudbase.init({ env: "xxxx-yyy", }); const getTickFn = new Promise((resolve, reject)); const auth = app.auth(); await auth.setCustomSignFunc(getTickFn); ``` ### Auth.signInWithCustomTicket() #### 接口描述 自定义登录 接口声明 `signInWithCustomTicket(): Promise` #### 示例代码 ```js const app = cloudbase.init({ env: "xxxx-yyy", }); const auth = app.auth(); await auth.signInWithCustomTicket(); ``` ```bash curl 'https://${env}.ap-shanghai.tcb-api.tencentcloudapi.com/auth/v1/signin/with/provider' \ -H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36' \ -H 'x-device-id': ${deviceID} \ -H 'x-request-id': ${requestID} \ -u ${clientID}:${clientSecrect} --data-raw '{"provider_id": "custom", "provider_token":"your ticket"}' \ --compressed ``` ### Auth.signInWithOpenId() #### 接口描述 微信小程序 openId 静默登录 接口声明 `signInWithOpenId(params: SignInWithOpenIdReq): Promise` ##### SignInWithOpenIdReq | 字段 | 类型 | 必填 | 默认值 | 说明 | | ---------- | ------- | ---- | ------ | ----------------------------------------------------------------------------------------- | | useWxCloud | boolean | 否 | true | true: 使用微信云开发模式进行请求,需开通小程序微信云开发环境; false:使用普通 http 请求 | #### 示例代码 ```js const app = cloudbase.init({ env: "xxxx-yyy", }); const auth = app.auth(); await auth.signInWithOpenId(); ``` ### Auth.signInWithUnionId() #### 接口描述 微信小程序 unionId 静默登录 接口声明 `signInWithUnionId(): Promise` #### 示例代码 ```js const app = cloudbase.init({ env: "xxxx-yyy", }); const auth = app.auth(); await auth.signInWithUnionId(); ``` ### Auth.signInWithPhoneAuth() #### 接口描述 微信小程序手机号授权登录 接口声明 `signInWithPhoneAuth(params: SignInWithPhoneAuthReq): Promise` ##### SignInWithPhoneAuthReq | 字段 | 类型 | 必填 | 默认值 | 说明 | | --------- | ------ | ---- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | phoneCode | string | 是 | 空 | 微信小程序手机号授权码,通过[微信小程序手机号快速验证组件](https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/getPhoneNumber.html#%E8%BF%94%E5%9B%9E%E5%8F%82%E6%95%B0%E8%AF%B4%E6%98%8E) | #### 示例代码 ```js const app = cloudbase.init({ env: "xxxx-yyy", }); const auth = app.auth(); await auth.signInWithPhoneAuth({ phoneCode: "xxx" }); ``` ### Auth.signInWithSms() #### 接口描述 短信验证码登陆 接口声明 `signInWithSms(params: SignInWithSmsReq): Promise` ##### SignInWithSmsReq | 字段 | 类型 | 必填 | 默认值 | 说明 | | ---------------- | ------ | ----------------- | ------ | ----------------------------------------------------------------------------------------- | | verificationInfo | object | 验证码 token 信息 | {} | [Auth.getVerification()](/api-reference/webv3/authentication#authgetverification)的返回值 | | verificationCode | string | 验证码 | 空 | 获取到的短信验证码 | | phoneNum | string | 手机号 | 空 | 获取验证码的手机号 | #### 示例代码 ```js const app = cloudbase.init({ env: "xxxx-yyy", }); const auth = app.auth(); const verificationInfo = await auth.getVerification({ phone_number: phoneNumber, }); await auth.signInWithSms({ verificationInfo, verificationCode: "xxx", phoneNum: "xxx", }); ``` ### Auth.signInWithEmail() #### 接口描述 邮箱验证码登陆 接口声明 `signInWithEmail(params: SignInWithEmailReq): Promise` ##### SignInWithEmailReq | 字段 | 类型 | 必填 | 默认值 | 说明 | | ---------------- | ------ | ----------------- | ------ | ----------------------------------------------------------------------------------------- | | verificationInfo | object | 验证码 token 信息 | {} | [Auth.getVerification()](/api-reference/webv3/authentication#authgetverification)的返回值 | | verificationCode | string | 验证码 | 空 | 获取到的邮箱验证码 | | email | string | 邮箱 | 空 | 获取验证码的邮箱地址 | #### 示例代码 ```js const app = cloudbase.init({ env: "xxxx-yyy", }); const auth = app.auth(); const verificationInfo = await auth.getVerification({ email: email, }); await auth.signInWithEmail({ verificationInfo, verificationCode: "xxx", email: "xxx", }); ``` ### Auth.toDefaultLoginPage() #### 接口描述 跳转系统默认登录页,兼容 web 和小程序端 接口声明 `toDefaultLoginPage(params: authModels.ToDefaultLoginPage): Promise` ##### ToDefaultLoginPagelReq | 字段 | 类型 | 含义 | 默认值 | 说明 | | -------------- | ------ | -------------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | config_version | string | 默认登录页面的登录配置版本 | env | 1、‘env’表示托管登录页配置,可在[“云开发平台-身份认证”](https://tcb.cloud.tencent.com/dev?#/identity/land-page)中设置,2、非‘env’表示使用独立的托管登录页配置,可在“云开发平台-可视化低代码-访问控制”中设置,相应的 config_version 可以在应用自动跳转的\_\_auth 登录页面的链接中参数获取到 | | redirect_uri | string | 登录后重定向地址 | 默认为当前页面地址 | | | app_id | string | 应用 id | 空 | config_version 不是‘env’的时候为必填项,如 app-xxx | #### 示例代码 ```js const app = cloudbase.init({ env: "xxxx-yyy", }); const auth = app.auth(); await auth.toDefaultLoginPage({ config_version: "env", app_id: "app-xxx", redirect_uri: "xxx", }); ``` ## 第三方平台登录相关 ### Auth.genProviderRedirectUri() #### 接口描述 生成第三方平台授权 Uri (如微信二维码扫码授权网页) 接口声明 `genProviderRedirectUri(params: GenProviderRedirectUriRequest): Promise` #### GenProviderRedirectUriRequest | 字段 | 类型 | 必填 | 说明 | | --------------------- | ---------------------- | ---- | ------------------------------------------------------------------- | | provider_id | string | 是 | 第三方平台 ID,参考系统内置三方平台[列表](#系统内置三方列表) | | provider_redirect_uri | string | 是 | 第三方平台重定向 Uri,授权完成后,重定向时会在 url 中携带 code 参数 | | state | string | 是 | 用户自定义状态标识字段,识别三方平台回调来源 | | other_params | {sign_out_uri?:string} | 否 | 其他参数 | #### GenProviderRedirectUriResponse | 字段 | 类型 | 必填 | 说明 | | ----------- | ------ | ---- | ---------- | | uri | string | 是 | 客户端请求 | | signout_uri | string | 是 | 登出 Uri | #### 示例代码 ```js const app = cloudbase.init({ env: "xxxx-yyy", }); const auth = app.auth(); const providerId = "test_provider_id"; const providerUri = "test_provider_redirect_uri"; const state = "wx_open"; const otherParams = { sign_out_uri: "test_sign_out_uri" }; // 三方平台授权登录示例 // 1. 获取第三方平台授权页地址(如微信授权) const { uri } = await auth.genProviderRedirectUri({ provider_id: providerId, provider_redirect_uri: providerUri, state: state, other_params: otherParams, }); // 2. 访问uri (如 location.href = uri) // 3. 授权 (如微信扫码授权) // 4. 回调至 provider_redirect_uri 地址(url query中携带 授权code,state等参数),此时检查 state 是否符合预期(如 自己设置的 wx_open) const provider_code = "your provider code"; // 5. state符合预期(微信开放平台授权 wx_open),则获取该三方平台token const { provider_token } = await auth.grantProviderToken({ provider_id: "wx_open", provider_redirect_uri: "cur page", // 指定三方平台跳回的 url 地址 provider_code: provider_code, // 第三方平台跳转回页面时,url param 中携带的 code 参数 }); // 6. 通过 provider_token 登录 await auth.signInWithProvider({ provider_token, }); ``` ```bash # bash 下调用接口的例子 # 环境ID export env="your-env-id" # 获取设备ID,安卓,IOS 或 小程序平台可调用接口获取 export deviceID="demo_device_5dh6nf" # 生成request ID (默认采用 32 位UUID 即可,可自行生成) export requestID="3af464bf930dbdb83f587990a1a55cb9" curl 'https://${env}.ap-shanghai.tcb-api.tencentcloudapi.com/auth/v1/provider/uri' \ -H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36' \ -H 'x-device-id': ${deviceID} \ -H 'x-request-id': ${requestID} \ -u ${clientID}:${clientSecrect} --data-raw '{"provider_id":"test_provider_id","provider_redirect_uri":"test_provider_redirect_uri","state":"test_state","otherParams":"{"sign_out_uri":"test_sign_out_uri"}"}' \ --compressed ``` ### Auth.grantProviderToken() #### 接口描述 提供第三方平台登录 token 接口声明 `grantProviderToken(params: GrantProviderTokenRequest): Promise` #### GrantProviderTokenRequest | 字段 | 类型 | 必填 | 说明 | | --------------------- | ------ | ---- | -------------------------------------------------------- | | provider_id | string | 是 | 第三方平台 ID,参考系统内置[三方列表](#系统内置三方列表) | | provider_redirect_uri | string | 否 | 第三方平台重定向 uri | | provider_code | string | 否 | 第三方平台授权 code(重定向 uri 中携带) | | provider_access_token | string | 否 | 第三方平台访问 token(重定向 uri 中携带) | | provider_id_token | string | 否 | 第三方平台 ID token(重定向 uri 中携带) | #### GrantProviderTokenResponse | 字段 | 类型 | 必填 | 说明 | | ---------------- | --------------- | ---- | ---------------- | | provider_token | string | 是 | 第三方平台 token | | expires_in | number | 是 | 有效期 | | provider_profile | ProviderProfile | 否 | 第三方身份源信息 | ##### ProviderProfile | 字段 | 类型 | 必填 | 说明 | | ------------ | ------------------- | ---- | ------------------------------------------------- | | provider_id | string | 是 | 默认内置的三方 providerid,**wx_open**, **wx_mp** | | sub | string | 是 | 第三方用户 id (如 wxopenid) | | name | string | 否 | 名称 | | phone_number | string | 否 | 手机号 | | picture | string | 否 | 头像 | | meta | ProviderProfileMeta | 否 | 第三方身份源扩展信息(小程序返回) | ##### ProviderProfileMeta | 字段 | 类型 | 必填 | 说明 | | ------ | ------ | ---- | --------------- | | appid | string | 否 | 小程序的 appid | | openid | string | 否 | 小程序的 openid | #### 示例代码 ```js const app = cloudbase.init({ env: "xxxx-yyy", }); const auth = app.auth(); const providerId = "wx_open"; // 微信开放平台 auth.grantProviderToken({ provider_id: providerId, provider_redirect_uri: "cur page", // 指定三方平台跳回的 url 地址 provider_code: "provider code", // 第三方平台跳转回页面时,url param 中携带的 code 参数 }); ``` ```bash # bash 下调用接口的例子 # 环境ID export env="your-env-id" # 获取设备ID,安卓,IOS 或 小程序平台可调用接口获取 export deviceID="demo_device_5dh6nf" # 生成request ID (默认采用 32 位UUID 即可,可自行生成) export requestID="3af464bf930dbdb83f587990a1a55cb9" curl 'https://${env}.ap-shanghai.tcb-api.tencentcloudapi.com/auth/v1/provider/token' \ -H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36' \ -H 'x-device-id': ${deviceID} \ -H 'x-request-id': ${requestID} \ -u ${clientID}:${clientSecrect} --data-raw '{"provider_id":"wx_open", "provider_redirect_uri": "cur page", "provider_code": "provider code" }' \ --compressed ``` ### Auth.signInWithProvider() #### 接口描述 第三方平台登录 接口声明 `signInWithProvider(params: SignInWithProviderRequest): Promise` ##### SignInWithProviderRequest | 字段 | 类型 | 必填 | 说明 | | -------------- | ------ | ---- | -------------------------------------------------------------------------- | | provider_token | string | 是 | 第三方平台 token,参考 [Auth.grantProviderToken](#Auth.grantProviderToken) | #### 示例代码 ```js const app = cloudbase.init({ env: "xxxx-yyy", }); const auth = app.auth(); const providerToken = "test_provider_token"; auth.signInWithProvider({ provider_token: providerToken, }); ``` ```bash # bash 下调用接口的例子 # 环境ID export env="your-env-id" # 获取设备ID,安卓,IOS 或 小程序平台可调用接口获取 export deviceID="demo_device_5dh6nf" # 生成request ID (默认采用 32 位UUID 即可,可自行生成) export requestID="3af464bf930dbdb83f587990a1a55cb9" curl 'https://${env}.ap-shanghai.tcb-api.tencentcloudapi.com/auth/v1/signin/with/provider' \ -H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36' \ -H 'x-device-id': ${deviceID} \ -H 'x-request-id': ${requestID} \ -u ${clientID}:${clientSecrect} --data-raw '{"provider_token":"test_provider_token"}' \ --compressed ``` ### Auth.unbindProvider() #### 接口描述 解除第三方绑定 接口声明:`unbindProvider(params: UnbindProviderRequest): Promise` ##### UnbindProviderRequest | 字段 | 类型 | 必填 | 说明 | | ----------- | ------ | ---- | ------------------------------------- | | provider_id | string | 是 | 第三方平台 ID,参考第三方绑定时回包的 | #### 示例代码 ```js const app = cloudbase.init({ env: "xxxx-yyy", }); const auth = app.auth(); // 完成登录后 // 获取绑定第三方平台ID const { id } = await auth.getProviders(); await auth.unbindProvider({ provider_id: id, }); ``` ```bash # bash 下调用接口的例子 # 环境ID export env="your-env-id" # 获取设备ID,安卓,IOS 或 小程序平台可调用接口获取 export deviceID="demo_device_5dh6nf" # 生成request ID (默认采用 32 位UUID 即可,可自行生成) export requestID="3af464bf930dbdb83f587990a1a55cb9" curl 'https://${env}.ap-shanghai.tcb-api.tencentcloudapi.com/auth/v1/user/provider/{your provider_id}' \ -X DELETE \ -H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36' \ -H 'x-device-id': ${deviceID} \ -H 'x-request-id': ${requestID} \ -u ${clientID}:${clientSecrect} --compressed ``` ### Auth.getProviders() #### 接口描述 获取第三方绑定列表 接口声明:`getProviders(): Promise` ##### UserProfileProvider | 字段 | 类型 | 必填 | 说明 | | ---------------- | ------ | ---- | ----------------- | | id | string | 是 | 第三方平台 ID | | provider_user_id | string | 是 | 第三方平台用户 ID | | name | string | 是 | 第三方平台昵称 | #### 示例代码 ```js const app = cloudbase.init({ env: "xxxx-yyy", }); const auth = app.auth(); // 完成登录后 await auth.getProviders(); ``` ```bash # bash 下调用接口的例子 # 环境ID export env="your-env-id" # 获取设备ID,安卓,IOS 或 小程序平台可调用接口获取 export deviceID="demo_device_5dh6nf" # 生成request ID (默认采用 32 位UUID 即可,可自行生成) export requestID="3af464bf930dbdb83f587990a1a55cb9" curl 'https://${env}.ap-shanghai.tcb-api.tencentcloudapi.com/auth/v1/user/provider' \ -X GET -H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36' \ -H 'x-device-id': ${deviceID} \ -H 'x-request-id': ${requestID} \ -u ${clientID}:${clientSecrect} --data-raw '{}' \ --compressed ``` ### Auth.bindWithProvider() #### 接口描述 绑定第三方登录 接口声明 `bindWithProvider(params: BindWithProviderRequest): Promise` ##### BindWithProviderRequest | 字段 | 类型 | 必填 | 说明 | | -------------- | ------ | ---- | -------------------- | | provider_token | string | 是 | 第三方平台授权 token | #### 示例代码 ```js const app = cloudbase.init({ env: "xxxx-yyy", }); const provider_token = "test_provider_token"; // 参考Auth.grantProviderToken 获取 const auth = app.auth(); await auth.bindWithProvider({ provider_token, }); ``` ```bash # bash 下调用接口的例子 # 环境ID export env="your-env-id" # 获取设备ID,安卓,IOS 或 小程序平台可调用接口获取 export deviceID="demo_device_5dh6nf" # 生成request ID (默认采用 32 位UUID 即可,可自行生成) export requestID="3af464bf930dbdb83f587990a1a55cb9" curl 'https://${env}.ap-shanghai.tcb-api.tencentcloudapi.com/auth/v1/user/provider/bind' \ -H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36' \ -H 'x-device-id': ${deviceID} \ -H 'x-request-id': ${requestID} \ -u ${clientID}:${clientSecrect} --data-raw '{"provider_token": "your provider_token"}' \ --compressed ``` ## 验证/授权相关 ### Auth.verify() #### 接口描述 验证码验证 接口声明 `verify(params: VerifyRequest): Promise` #### VerifyRequest | 字段 | 类型 | 必填 | 说明 | | ----------------- | ------ | ---- | --------- | | verification_code | string | 是 | 验证码 | | verification_id | string | 是 | 验证码 ID | #### VerifyResponse | 字段 | 类型 | 必填 | 说明 | | ------------------ | ------ | ---- | ------------ | | verification_token | string | 否 | 验证码 token | #### 示例代码 ```js const app = cloudbase.init({ env: "xxxx-yyy", }); const auth = app.auth(); // 例:手机号验证码/ 邮箱验证码注册 // 1. 发送手机验证码 const phoneNumber = "+86 13800000000"; const verification = await auth.getVerification({ phone_number: phoneNumber, }); /* // 若使用邮箱验证,第一步代码改为 const email = "test@example.com" const verification = await auth.getVerification({ email: email }); */ const verificationCode = "000000"; await auth.verify({ verification_code: verificationCode, verification_id: verification.verification_id, }); ``` ```bash # bash 下调用接口的例子 # 环境ID export env="your-env-id" # 获取设备ID,安卓,IOS 或 小程序平台可调用接口获取 export deviceID="demo_device_5dh6nf" # 生成request ID (默认采用 32 位UUID 即可,可自行生成) export requestID="3af464bf930dbdb83f587990a1a55cb9" # 1. 发送验证码 curl 'https://${env}.ap-shanghai.tcb-api.tencentcloudapi.com/auth/v1/verification' \ -H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36' \ -H 'x-device-id': ${deviceID} \ -H 'x-request-id': ${requestID} \ -u ${clientID}:${clientSecrect} --data-raw '{"phone_number":"+86 13800000000"}' \ --compressed # 2. 验证码验证 curl 'https://${env}.ap-shanghai.tcb-api.tencentcloudapi.com/auth/v1/verification/verify' \ -H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36' \ -H 'x-device-id': ${deviceID} \ -H 'x-request-id': ${requestID} \ -u ${clientID}:${clientSecrect} --data-raw '{"verification_code":"verification_code","verification_id":"verification_id"}' \ --compressed ``` ### Auth.getVerification() #### 接口描述 获取短信/邮件验证码 接口声明 `getVerification(params: GetVerificationRequest): Promise` #### GetVerificationRequest | 字段 | 类型 | 必填 | 说明 | | ------------ | ----------- | ---- | ------ | | phone_number | string | 否 | 手机号 | | email | string | 否 | 邮箱 | | target | string\|any | 否 | target | | usage | string | 否 | usage | #### GetVerificationResponse | 字段 | 类型 | 说明 | | --------------- | ------- | -------------- | | verification_id | string | 验证码 id | | is_user | boolean | 是否是注册用户 | #### 示例代码 ```js const app = cloudbase.init({ env: "xxxx-yyy", }); const auth = app.auth(); const verificationCode = "000000"; const email = "test@example.com"; const phoneNumber = "+86 13800000000"; const usage = "test_usage"; const verification = await auth.getVerification({ phone_number: phoneNumber, // email: email, }); ``` ```bash # bash 下调用接口的例子 # 环境ID export env="your-env-id" # 获取设备ID,安卓,IOS 或 小程序平台可调用接口获取 export deviceID="demo_device_5dh6nf" # 生成request ID (默认采用 32 位UUID 即可,可自行生成) export requestID="3af464bf930dbdb83f587990a1a55cb9" curl 'https://${env}.ap-shanghai.tcb-api.tencentcloudapi.com/auth/v1/verification' \ -H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36' \ -H 'x-device-id': ${deviceID} \ -H 'x-request-id': ${requestID} \ -u ${clientID}:${clientSecrect} --data-raw '{"phone_number":"+86 13800000000"}' \ --compressed ``` ### Auth.sudo() #### 接口描述 通过 sudo 接口获取高级操作权限,如修改密码,修改手机号,修改邮箱等操作 接口声明 `Auth.sudo(params: SudoRequest): Promise` #### SudoRequest | 字段 | 类型 | 必填 | 说明 | | ------------------ | ------ | ---- | ---------------------------------------------- | | password | string | 否 | 密码 | | verification_token | string | 否 | token 令牌,通过账号绑定的手机号或邮箱验证获取 | #### 示例代码 ```js const app = cloudbase.init({ env: "xxxx-yyy", }); const auth = app.auth(); // 方式一:使用密码 const pass = "test_password"; const sudoRes = await auth.sudo({ password: pass, }); console.log(sudoRes.sudo_token); // 方式二:通过邮箱验证码,手机号验证码获取。 // 当前账号绑定的邮箱地址或手机号 const email = "test@example.com"; // const phoneNumber = "+86 13800000000" // 获取验证码 const verification = await auth.getVerification({ email: email, // phone_number: phoneNumber }); // 假设收到的验证码是 000000 const verificationCode = "000000"; // 验证验证码的正确性 const verificationTokenRes = await auth.verify({ verification_id: verification.verification_id, verification_code: verificationCode, }); // 获取 sudo_token const sudoRes = await auth.sudo({ verification_token: verificationTokenRes.verification_token, }); console.log(sudoRes.sudo_token); ``` ```bash # bash 下调用接口的例子 # 环境ID export env="your-env-id" # 获取设备ID,安卓,IOS 或 小程序平台可调用接口获取 export deviceID="demo_device_5dh6nf" # 生成request ID (默认采用 32 位UUID 即可,可自行生成) export requestID="3af464bf930dbdb83f587990a1a55cb9" curl 'https://${env}.ap-shanghai.tcb-api.tencentcloudapi.com/auth/v1/user/sudo' \ -H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36' \ -H 'x-device-id': ${deviceID} \ -H 'x-request-id': ${requestID} \ -u ${clientID}:${clientSecrect} --data-raw '{"password":"your old_password"}' \ --compressed ``` ### Auth.getAccessToken() #### 接口描述 获取访问凭证 accessToken 接口声明 `Auth.getAccessToken(): Promise` #### 示例代码 ```js const app = cloudbase.init({ env: "xxxx-yyy", }); const auth = app.auth(); // 某种方式登录后... // 获取access_token const { accessToken } = await auth.getAccessToken(); console.log(accessToken); ``` ## 用户信息相关 ### Auth.getCurrentUser() #### 接口描述 `Auth.currentUser`的异步操作,返回表示当前用户的 [`User`](#user) 实例 签名:`getCurrentUser(): Promise` #### 示例代码 ```js const app = cloudbase.init({ env: "xxxx-yyy", clientId: "xxxx", }); // 执行某种登录之后... app .auth() .getCurrentUser() .then((user) => { // ... }); ``` ### Auth.bindPhoneNumber() #### 接口描述 绑定手机号 接口声明:`bindPhone(params: BindPhoneRequest): Promise` ##### BindPhoneRequest | 字段 | 类型 | 必填 | 说明 | | ------------------ | ------ | ---- | ------------------- | | phone_number | string | 是 | 新手机号 | | sudo_token | string | 是 | 高级权限 token 令牌 | | verification_token | string | 是 | 验证码 token 令牌 | #### 示例代码 ```js const app = cloudbase.init({ env: "xxxx-yyy", }); // 前置条件,先登录 const auth = app.auth(); // 第一步:获取 sudo token, 参考 Auth.sudo 接口获取 const sudo_token = "test_sudo_token"; // 第二步:给手机号发验证码 const phone_number = "+86 13800000000"; const verification = await auth.getVerification({ phone_number: phone_number, }); // 假设验证码是 000000 const verification_code = "000000"; // 第三步:验证验证码的正确性 const verification_token_res = await auth.verify({ verification_id: verification.verification_id, verification_code: verification_code, }); const verification_token = verification_token_res.verification_token; // 第四步:绑定手机号 await auth.bindPhoneNumber({ phone_number: phone_number, sudo_token: sudo_token, verification_token: verification_token, }); ``` ```bash # bash 下调用接口的例子 # 环境ID export env="your-env-id" # 获取设备ID,安卓,IOS 或 小程序平台可调用接口获取 export deviceID="demo_device_5dh6nf" # 生成request ID (默认采用 32 位UUID 即可,可自行生成) export requestID="3af464bf930dbdb83f587990a1a55cb9" # 1. 发送手机验证码 curl 'https://${env}.ap-shanghai.tcb-api.tencentcloudapi.com/auth/v1/verification' \ -H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36' \ -H 'x-device-id': ${deviceID} \ -H 'x-request-id': ${requestID} \ -u ${clientID}:${clientSecrect} --data-raw '{"phone_number":"+86 13800000000"}' \ --compressed # 2. 验证码验证 curl 'https://${env}.ap-shanghai.tcb-api.tencentcloudapi.com/auth/v1/verification/verify' \ -H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36' \ -H 'x-device-id': ${deviceID} \ -H 'x-request-id': ${requestID} \ -u ${clientID}:${clientSecrect} --data-raw '{"verification_code":"000000", "verification_id": "verification_id"}' \ --compressed # 3. 获取sudo token curl 'https://${env}.ap-shanghai.tcb-api.tencentcloudapi.com/auth/v1/user/sudo' \ -H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36' \ -H 'x-device-id': ${deviceID} \ -H 'x-request-id': ${requestID} \ -u ${clientID}:${clientSecrect} --data-raw '{"verification_token": "your verification_token"}' \ --compressed # 4. 绑定手机号 curl 'https://${env}.ap-shanghai.tcb-api.tencentcloudapi.com/auth/v1/user/contact' \ -H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36' \ -H 'x-device-id': ${deviceID} \ -H 'x-request-id': ${requestID} \ -u ${clientID}:${clientSecrect} --data-raw '{"phone_number":"+86 13800000000", "sudo_token": "your sudo_token","verification_token": "your verification_token"}' \ --compressed ``` ### Auth.bindEmail() #### 接口描述 更新邮箱地址 接口声明:`bindEmail(params: BindEmailRequest): Promise` ##### BindEmailRequest | 字段 | 类型 | 必填 | 说明 | | ------------------ | ------ | ---- | ------------ | | email | string | 是 | 邮箱地址 | | sudo_token | string | 是 | token 令牌 | | verification_token | string | 是 | 验证码 token | #### 示例代码 ```js const app = cloudbase.init({ env: "xxxx-yyy", }); // 前置条件,先登录 const auth = app.auth(); // 第一步:获取 sudo token, 参考 Auth.sudo 接口获取 const sudoToken = "test_sudo_token" // 第二步:验证新邮箱地址 const newEmail = "new@example.com"; const verification = await auth.getVerification({ email: newEmail }); // 假设用户输入的验证码为 000000 const verificationCode = "000001"; // 检查验证码的正确性 const newEmailTokenRes = await auth.verify({ verification_id: verification.verification_id, verification_code: verificationCode, }); const verificationToken = newEmailTokenRes.verification_token // 第三步:绑定新邮箱 await auth.bindEmail({ email: newEmail, sudo_token: sudoToken verification_token: verificationToken }); ``` ```bash # bash 下调用接口的例子 # 环境ID export env="your-env-id" # 获取设备ID,安卓,IOS 或 小程序平台可调用接口获取 export deviceID="demo_device_5dh6nf" # 生成request ID (默认采用 32 位UUID 即可,可自行生成) export requestID="3af464bf930dbdb83f587990a1a55cb9" # 1. 发送邮箱验证码 curl 'https://${env}.ap-shanghai.tcb-api.tencentcloudapi.com/auth/v1/verification' \ -H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36' \ -H 'x-device-id': ${deviceID} \ -H 'x-request-id': ${requestID} \ -u ${clientID}:${clientSecrect} --data-raw '{"email":"test@example.com"}' \ --compressed # 2. 验证码验证 curl 'https://${env}.ap-shanghai.tcb-api.tencentcloudapi.com/auth/v1/verification/verify' \ -H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36' \ -H 'x-device-id': ${deviceID} \ -H 'x-request-id': ${requestID} \ -u ${clientID}:${clientSecrect} --data-raw '{"verification_code":"000000", "verification_id": "verification_id"}' \ --compressed # 3. 获取sudo token curl 'https://${env}.ap-shanghai.tcb-api.tencentcloudapi.com/auth/v1/user/sudo' \ -H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36' \ -H 'x-device-id': ${deviceID} \ -H 'x-request-id': ${requestID} \ -u ${clientID}:${clientSecrect} --data-raw '{"verification_token": "your verification_token"}' \ --compressed # 4. 绑定邮箱 curl 'https://${env}.ap-shanghai.tcb-api.tencentcloudapi.com/auth/v1/user/contact' \ -H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36' \ -H 'x-device-id': ${deviceID} \ -H 'x-request-id': ${requestID} \ -u ${clientID}:${clientSecrect} --data-raw '{"email":"test@example.com","sudo_token":"test_sudo_token","verification_token":"verification_token"}' \ --compressed ``` ### Auth.setPassword() #### 接口描述 设置密码(已登录状态下,更新用户密码) 接口声明 `setPassword(params: SetPasswordRequest): Promise` #### SetPasswordRequest | 字段 | 类型 | 必填 | 说明 | | ------------ | ------ | ---- | ------------------------------------------------------------------------------------- | | new_password | string | 是 | 新密码 | | sudo_token | string | 是 | token 令牌 (如果用户只开启三方登录, 没有设置密码的情况下,sudo token 为 "" 空字符串) | #### 示例代码 ```js const app = cloudbase.init({ env: "xxxx-yyy", }); const auth = app.auth(); // 第一步:获取 sudo token,参考 Auth.sudo 接口获取 const sudoToken = "test_sudo_token"; // 第二步:更新密码 const newPassWord = "test_new_password"; await auth.setPassword({ new_password: newPassWord, sudo_token: sudoToken, }); ``` ```bash # bash 下调用接口的例子 # 环境ID export env="your-env-id" # 获取设备ID,安卓,IOS 或 小程序平台可调用接口获取 export deviceID="demo_device_5dh6nf" # 生成request ID (默认采用 32 位UUID 即可,可自行生成) export requestID="3af464bf930dbdb83f587990a1a55cb9" curl 'https://${env}.ap-shanghai.tcb-api.tencentcloudapi.com/auth/v1/user/password' \ -X PATCH \ -H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36' \ -H 'x-device-id': ${deviceID} \ -H 'x-request-id': ${requestID} \ -u ${clientID}:${clientSecrect} --data-raw '{"new_password":"your new_password","sudo_token":"sudo_token"}' \ --compressed ``` ### Auth.getUserInfo() #### 接口描述 获取用户信息失败 接口声明 `getUserInfo(): Promise` ##### UserInfo | 字段 | 类型 | 说明 | | ------------------------ | ------------------- | ------------------------------------------- | | User.name | string | 用户昵称(区分与 登录用户名 User.username) | | User.picture | string | 用户上传头像 | | User.phone_number | string | 用户绑定手机号 | | User.email_verified | boolean | 用户是否经过邮箱验证 | | User.birthdate | string | 用户生日 | | User.locale | string | 用户设置语言 | | User.zoneinfo | string | 时区 | | User.UserProfileProvider | UserProfileProvider | 第三方平台配置 | ##### UserProfileProvider | 字段 | 类型 | 必填 | 说明 | | ---------------- | ------ | ---- | ------------------------------------------------- | | id | string | 否 | 默认内置的三方 providerid,**wx_open**, **wx_mp** | | provider_user_id | string | 否 | 第三方 provider 用户 id (如 wxopenid) | | name | string | 否 | 名称 | ##### 系统内置三方列表 | provider_id | 含义 | | ----------- | ------------ | | wx_open | 微信开放平台 | | wx_mp | 微信公众号 | #### 示例代码 ```js const app = cloudbase.init({ env: "xxxx-yyy", }); const newPassWord = "test_new_password"; const sudoToken = "test_sudo_token"; const auth = app.auth(); const userInfo = await auth.getUserInfo(); ``` ```bash # bash 下调用接口的例子 # 环境ID export env="your-env-id" # 获取设备ID,安卓,IOS 或 小程序平台可调用接口获取 export deviceID="demo_device_5dh6nf" # 生成request ID (默认采用 32 位UUID 即可,可自行生成) export requestID="3af464bf930dbdb83f587990a1a55cb9" curl 'https://${env}.ap-shanghai.tcb-api.tencentcloudapi.com/auth/v1/user/me' \ -H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36' \ -H 'x-device-id': ${deviceID} \ -H 'x-request-id': ${requestID} \ -u ${clientID}:${clientSecrect} --data-raw '{}' \ --compressed ``` ### Auth.queryUser() :::warning 自定义登录场景和匿名登录场景,不支持使用该接口查询用户信息(自定义登录场景请在业务服务中自行查询用户信息,匿名登录场景不支持) ::: #### 接口描述 查询用户 接口声明 `queryUser(queryObj: QueryUserProfileRequest): Promise;` ##### QueryUserProfileRequest | 字段 | 类型 | 必填 | 说明 | | ------------ | ------------------- | ---- | ----------------------------------------------- | | id | Array<string> | 否 | 用户 uid 数组,最多支持查询 50 个 id 对应的用户 | | username | string | 否 | 用户名称 | | email | string | 否 | 邮箱 | | phone_number | string | 否 | 手机号 | ##### QueryUserProfileResponse | 字段 | 类型 | 必填 | 说明 | | ----- | ------------------- | ---- | -------- | | total | string | 否 | 数量 | | data | SimpleUserProfile[] | 否 | 用户列表 | #### SimpleUserProfile | 字段 | 类型 | 必填 | 说明 | | ------------ | ------ | ---- | ------ | | sub | string | 是 | 下标 | | name | string | 是 | 名称 | | picture | string | 否 | 图片 | | gender | string | 否 | 性别 | | locale | string | 否 | 地点 | | email | string | 否 | 邮箱 | | phone_number | string | 否 | 手机号 | #### 示例代码 ```js const app = cloudbase.init({ env: "xxxx-yyy", }); const auth = app.auth(); const email = "test@example.com"; const phoneNumber = "+86 13800000000"; const username = "test_username"; const userInfo = await auth.queryUser({ username: username, }); ``` ```bash # bash 下调用接口的例子 # 环境ID export env="your-env-id" # 获取设备ID,安卓,IOS 或 小程序平台可调用接口获取 export deviceID="demo_device_5dh6nf" # 生成request ID (默认采用 32 位UUID 即可,可自行生成) export requestID="3af464bf930dbdb83f587990a1a55cb9" curl 'https://${env}.ap-shanghai.tcb-api.tencentcloudapi.com/auth/v1/user/query' \ -H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36' \ -H 'x-device-id': ${deviceID} \ -H 'x-request-id': ${requestID} \ -u ${clientID}:${clientSecrect} --data-raw '{"usename":"test_username",}' \ --compressed ``` ### Auth.resetPassword() #### 接口描述 重置密码(用户忘记密码无法登录时,可使用该接口强制设置密码) 接口声明 `resetPassword(params: ResetPasswordRequest): Promise` #### ResetPasswordRequest | 字段 | 类型 | 必填 | 说明 | | ------------------ | ------ | ---- | ---------- | | email | string | 是 | 邮箱 | | phone_number | string | 是 | 手机号 | | new_password | string | 是 | 新密码 | | verification_token | string | 是 | 验证 token | #### 示例代码 ```js const app = cloudbase.init({ env: "xxxx-yyy", }); const auth = app.auth(); const email = "testexample.com"; const newPassword = "test_new_password"; const phoneNumber = "+86 13800000000"; const verification = await auth.getVerification({ phone_number: phoneNumber, }); const verificationCode = "000000"; // 验证验证码的正确性 const verificationToken = await auth.verify({ verification_id: verification.verification_id, verification_code: verificationCode, }); await auth.resetPassword({ // email: email, phone_number: phoneNumber, new_password: newPassword, verification_token: verificationToken.verificationToken, }); ``` ```bash # bash 下调用接口的例子 # 环境ID export env="your-env-id" # 获取设备ID,安卓,IOS 或 小程序平台可调用接口获取 export deviceID="demo_device_5dh6nf" # 生成request ID (默认采用 32 位UUID 即可,可自行生成) export requestID="3af464bf930dbdb83f587990a1a55cb9" curl 'https://${env}.ap-shanghai.tcb-api.tencentcloudapi.com/auth/v1/user/password' \ -X POST \ -H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36' \ -H 'x-device-id': ${deviceID} \ -H 'x-request-id': ${requestID} \ -u ${clientID}:${clientSecrect} --data-raw '{"phone_number":"+86 13800000000","new_password":"test_new_password","verification_token":"verificationToken"}' \ --compressed ``` ### Auth.isUsernameRegistered() #### 接口描述 检查用户名是否被绑定过。 签名:`isUsernameRegistered(username: string): Promise` #### 示例代码 ```js const app = cloudbase.init({ env: "xxxx-yyy", }); const auth = app.auth(); const username = "your_awesome_username"; auth.isUsernameRegistered(username).then((registered) => { // }); ``` ### Auth.deleteMe() #### 接口描述 删除用户。 签名:`deleteMe(params: WithSudoRequest): Promise` #### 示例代码 ```js const app = cloudbase.init({ env: "xxxx-yyy", }); const auth = app.auth(); // 1. 通过 sudo 操作获取 sudo_token,参考 Auth.sudo 方法 // 2. deleteMe const user = await auth.deleteMe({ sudo_token: "your sudo_token", }); ``` ### Auth.loginScope() #### 接口描述 查询用户是否为匿名登录状态 签名:`loginScope(): Promise` #### 示例代码 ```js const app = cloudbase.init({ env: "xxxx-yyy", }); const auth = app.auth(); const username = "your_awesome_username"; // 经过某种方式登录后... const loginScope = await auth.loginScope(); if (loginScope === "anonymous") { console.log("当前为匿名登录方式"); } ``` ## LoginState `LoginState` 对象是对用户当前的登录态的抽象 ### Auth.hasLoginState() #### 接口描述 返回当前登录状态 [`LoginState`](#loginstate),如果未登录,则返回 null 签名:`hasLoginState(): LoginState | null` #### 示例代码 ```js const app = cloudbase.init({ env: "xxxx-yyy", clientId: "xxxx", }); const loginState = app.auth().hasLoginState(); if (loginState) { // 登录态有效 } else { // 没有登录态,或者登录态已经失效 } ``` ### Auth.getLoginState() #### 接口描述 `Auth.hasLoginState()`的异步操作,返回当前登录状态 [`LoginState`](#loginstate),如果未登录,则返回 null 签名:`getLoginState(): Promise` :::tip 提示 此 API 是 `hasLoginState` 的异步模式,适用于本地存储为异步的平台,比如 React Native ::: #### 示例代码 ```js const app = cloudbase.init({ env: "xxxx-yyy", clientId: "xxxx", }); const loginState = app .auth() .getLoginState() .then((loginState) => { if (loginState) { // 登录态有效 } else { // 没有登录态,或者登录态已经失效 } }); ``` ### Auth.onLoginStateChanged() #### 接口描述 监听登录状态变化,当登录状态发生变化时会触发该函数。比如调用[注册/登录/登出相关接口](#注册登录登出相关)、或者 Credentials 出现异常(如'credentials not found'、'no refresh token found in credentials'错误)等。 接口声明 `onLoginStateChanged(callback: Function): Promise` #### OnLoginStateChangedParams | 字段 | 类型 | 必填 | 说明 | | -------- | -------- | ---- | -------- | | callback | Function | 是 | 回调函数 | #### callback 回调函数入参定义 | 字段 | 类型 | 说明 | | ---- | ------ | -------------------------------------------------------------------------------- | | name | string | 默认值为 loginStateChanged | | data | object | 包括 { msg?: string; eventType: 'sign_in' \| 'sign_out' \| 'credentials_error' } | :::tip 提示 如果 eventType 是 sign_in 或 sign_out,还会返回当前登录状态 LoginState ::: #### 示例代码 ```js const app = cloudbase.init({ env: "xxxx-yyy", clientId: "xxxx", }); app.auth().onLoginStateChanged((params) => { console.log(params); const { eventType } = params?.data || {}; switch (eventType) { case "sign_in": // 登录成功 break; case "sign_out": // 退出登录成功 break; case "credentials_error": // 权限失效 break; default: return; } }); ``` ### LoginState.user 类型:`User | null` 表示当前用户,具体请参考 [User](#UserInfo) 如果没有登录,则为 `null` ## User ### User.update() #### 接口描述 更新用户信息 签名:`update(userInfo): Promise` #### 示例代码 ```js const user = auth.currentUser; user .update({ gender: "MALE", // 性别,取值仅限于 MALE、FEMALE、UNKNOWN }) .then(() => { // 更新用户信息成功 }); ``` ### User.refresh() #### 接口描述 刷新本地用户信息。当用户在其他客户端更新用户信息之后,可以调用此接口同步更新之后的信息。 签名:`refresh(): Promise` #### 示例代码 ```js const user = auth.currentUser; user.refresh().then(() => { // 刷新用户信息成功 }); ``` ## 错误码 ### 登录错误 | 错误码 | 说明 | | ------------------ | ---------------------------------------------------- | | not_found | 用户不存在 | | password_not_set | 当前用户未设置密码,请使用验证码登录或第三方登录方式 | | invalid_password | 密码不正确 | | user_pending | 该用户未激活 | | user_blocked | 该用户被停用 | | invalid_status | 您已经超过了密码最大重试次数, 请稍后重试 | | invalid_two_factor | 二次验证码不匹配或已过时 | ### 注册错误 | 错误码 | 说明 | | ------------------- | -------------------------------------------- | | failed_precondition | 你输入的手机号或邮箱已被注册,请使用其他号码 | ### 验证码相关错误 | 错误码 | 说明 | | ------------------- | -------------------------------------- | | failed_precondition | 从第三方获取用户信息失败 | | resource_exhausted | 你尝试过于频繁,请稍后重试 | | invalid_argument | 您输入的验证码不正确或已过期 | | aborted | 你尝试的次数过多,请返回首页,稍后重试 | | permission_denied | 您当前的会话已过期,请返回重试 | | captcha_required | 需要输入验证码, 需根据反机器人服务接入 | | captcha_invalid | 验证码不正确, 需根据反机器人服务接入 | ### 其他错误 | 错误码 | 说明 | | ----------- | -------------------------------------- | | unreachable | 网络错误,请检查您的网络连接,稍后重试 | ### 错误描述 | 错误码 | 错误描述 | 说明 | | ----------------- | ------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | | permission_denied | cors permission denied,please check if {url} in your client {env} domains | 请在“云开发平台-环境配置-安全来源-安全域名”中检查对应{env}环境下是否已经配置了安全域名{url},配置后 10 分钟生效 | ### 验证码相关处理 error==captcha_required 或 error==captcha_invalid 表示请求触发了验证码相关逻辑。需要进行机器验证。 > 验证码流程完成后,若业务接口返回 error 等于 captcha_required,表示请求需要 captcha_token 参数,尽可能使用本地的未过期的验证码。当 error 等于 captcha_invalid 时,表示验证码无效,需要需要重新获取验证码。在同一个验证流程内,captcha_invalid 最多尝试一次即可。 > 如需使用 adapter 进行处理,请参考[adapter 的验证码处理指南](https://docs.cloudbase.net/api-reference/webv3/adapter#%E9%AA%8C%E8%AF%81%E7%A0%81%E5%A4%84%E7%90%86%E6%8C%87%E5%8D%97) #### 初始化验证码 ```bash curl -X POST "https://${env}.ap-shanghai.tcb-api.tencentcloudapi.com/auth/v1/captcha/init" \ -H "Content-Type:application/json" \ -u ${clientID}:${clientSecrect} -d \ '{ "redirect_uri": "https://example.com/callback", "state": "your_state string" }' ``` ##### 请求参数 redirect_uri: (必传) 验证码验证完成后的地址。 state: (必传) 系统状态字符串,该字符串在验证码验证完成后后将 state 携带到。 ##### 响应 1:状态码 200 且返回 url 字段非空,需要展示验证码并完成验证 如果用户请求比较频繁或存在其他风险,验证码服务会返回下面的形式。 ```json { "url": "https://exmaple.com/captcha.html", "expires_in": 600 } ``` 此时表示,用户行为需要经过验证码验证才可以通过,请求成功后,客户端通过浏览器或 webview/iframe 等 打开 url 地址,比如上面的https://exmaple.com/captcha.html 用户在 web 中处理完成后,会自动重定向到下面的地址:(其中 captcha_token 为验证码 token,expires_in 为过期时间,单位为秒), https://example.com/callback?state=xxxxx&captcha_token=hbGciOiJeyJhbGciOiJSUAeyJhbGciOiJ&expires_in=600 业务方需要监听 redirect_uri 的地址变化,当地址为 appanme://com.package.name/callback 时,比对 state 是否和传入的相同,并获取到 captcha_token 和 expires_in。 若验证过程发生错误,验证页面会展示错误信息,用户点击返回后,验证页面会将错误信息 error 和 error_description 拼接到 redirect_uri 后重定向,例如: https://example.com/callback?state=xxxxx&error=xxx&error_description=xxx 此时业务方可以根据需要恢复初始页或做其它处理。 ##### 响应 2:状态码非 200,需要进行错误处理 如果用户请求比较频繁或存在其他风险,验证码服务会返回下面的形式。 ```json { "error": "resource_exhausted", "error_description": "Your operation is too frequent, please try again later" } ``` 此时客户端需要展示 error_descriprion, 可以结合 i18n 展示进行多语言展示。 ##### 拿到 captcha_token 再次请求 拿到 captcha_token 后,将 captcha_token 放到 url 参数中进行请求; 比如,请求 /v1/example 返回 captcha_invalid 错误,此时,则需要再次请求 /v1/example?captcha_token=hbGciOiJeyJhbGciOiJSUAeyJhbGciOiJ 即可完成操作。 --- ## 云托管 # 云托管 ## callContainer ### 1. 接口描述 接口功能:调用云托管服务 接口声明:`callContainer(object: Object): Promise` ### 2. 输入参数 | 字段 | 类型 | 必填 | 说明 | | ------ | ----------------------- | ---- | ------------- | | name | string | 是 | 云托管服务名 | | method | string | 否 | HTTP 请求方法 | | path | string | 否 | HTTP 请求路径 | | header | Record | 否 | HTTP 请求头 | | data | object | 否 | HTTP 请求体 | ### 3. 输出参数 | 字段 | 类型 | 必填 | 说明 | | --------- | ------ | ---- | ------------------------ | | code | string | 否 | 状态码,操作成功则不返回 | | message | string | 否 | 错误描述 | | result | object | 否 | HTTP响应体数据 | | requestId | string | 否 | 请求序列号,用于错误排查 | > 服务执行报错,将通过异常抛出 ### 4. 示例代码 ```javascript import cloudbase from "@cloudbase/js-sdk"; //初始化SDK实例 const app = cloudbase.init({ env: "xxxx-yyy" }); app .callContainer({ name: 'helloworld', method: 'POST', path: '/abc', header:{ 'Content-Type': 'application/json; charset=utf-8' }, data: { key1: 'test value 1', key2: 'test value 2' }, }) .then((res) => { console.log(res) }); ``` --- ## 数据库 # 数据库 ## 基础概念 ### Collection 集合是一系列的文档集,通过 `db.collection(name)` 可以获取指定集合的引用,在集合上可以进行以下操作 | 类型 | 接口 | 说明 | | -------- | ------- | ---------------------------------------------------------------------------------- | | 写 | add | 新增文档(触发请求) | | 计数 | count | 获取符合条件的文档条数 | | 读 | get | 获取集合中的文档,如果有使用 where 语句定义查询条件,则会返回匹配结果集 (触发请求) | | 引用 | doc | 获取对该集合中指定 id 的文档的引用 | | 查询条件 | where | 通过指定条件筛选出匹配的文档,可搭配查询指令(eq, gt, in, ...)使用 | | | skip | 跳过指定数量的文档,常用于分页,传入 offset | | | orderBy | 排序方式 | | | limit | 返回的结果集(文档数量)的限制,有默认值和上限值 | | | field | 指定需要返回的字段 | 查询及更新指令用于在 `where` 中指定字段需满足的条件,指令可通过 `db.command` 对象取得。 ### Record / Document 文档是数据库集合中的一个存储单元,在云开发里是一个 json 对象。通过 `db.collection(collectionName).doc(docId)` 可以获取指定集合上指定 id 的文档的引用,在文档上可以进行以下操作 | 接口 | 说明 | | ---- | ------ | ---------------------- | | 写 | set | 覆写文档 | | | update | 局部更新文档(触发请求) | | | remove | 删除文档(触发请求) | | 读 | get | 获取文档(触发请求) | ### Query Command 查询指令,应用于构建查询条件。以下指令皆挂载在 `db.command` 下 | 类型 | 接口 | 说明 | | -------- | ---- | ---------------------------------- | | 比较运算 | eq | 字段 == | | | neq | 字段 != | | | gt | 字段 > | | | gte | 字段 >= | | | lt | 字段 ` 备注:set 方法也可以用来新增文档,请参看文档更新部分 [set](#update-set) 方法 示例: #### 2. 输入参数 | 参数 | 类型 | 必填 | 说明 | | ---- | ------ | ---- | ------------------------------------------ | | data | object | 是 | {\_id: '10001', 'name': 'Ben'} \_id 非必填 | #### 3. 输出参数 | 字段 | 类型 | 必填 | 说明 | | ------- | ------ | ---- | ------------------------ | | code | string | 否 | 状态码,操作成功则不返回 | | message | string | 否 | 错误描述 | #### 4. 示例代码 ```js collection .add({ name: "Ben", }) .then((res) => {}) .catch((e) => {}); ``` ## get #### 1. 接口描述 接口功能:获取数据库查询结果 接口声明:`get(): Promise` 注:get()如不指定 limit 则默认取前 100 条数据,且最大取前 100 条数据。 #### 2. 输入参数 空 #### 3. 输出参数 | 字段 | 类型 | 必填 | 说明 | | --------- | ------ | ---- | ------------------------ | | code | string | 否 | 状态码,操作成功则不返回 | | message | string | 否 | 错误描述 | | data | object | 否 | 查询结果 | | requestId | string | 是 | 请求序列号,用于错误排查 | #### 4. 示例代码 ```js collection .where({ category: "computer", type: { memory: 8, }, }) .get() .then((res) => {}) .catch((e) => {}); ``` ## count #### 1. 接口描述 接口功能:获取数据库查询结果的数目 接口声明:`cout(): Promise` #### 2. 输入参数 空 #### 3. 输出参数 | 字段 | 类型 | 必填 | 说明 | | --------- | ------- | ---- | ------------------------ | | code | string | 否 | 状态码,操作成功则不返回 | | message | string | 否 | 错误描述 | | total | Integer | 否 | 计数结果 | | requestId | string | 否 | 请求序列号,用于错误排查 | #### 4. 示例代码 ```js db.collection("goods") .where({ category: "computer", type: { memory: 8, }, }) .count() .then(function (res) { const total = res.total; //符合条件的文档的数量 }); ``` ## remove #### 1. 接口描述 接口功能:删除一条文档 接口声明:`remove(): Promise` #### 2. 输入参数 无 #### 3. 输出参数 | 字段 | 类型 | 必填 | 说明 | | --------- | ------- | ---- | ------------------------ | | code | string | 否 | 状态码,操作成功则不返回 | | message | string | 否 | 错误描述 | | deleted | Inteter | 否 | 删除的文档数量 | | requestId | string | 是 | 请求序列号,用于错误排查 | #### 4. 示例代码 方式 1:通过  指定文档 ID 删除 collection.doc(\_id).remove() ```js collection .doc("xxx") .remove() .then((res) => { console.log(`${res.deleted} docs deleted`); }) .catch((e) => {}); ``` 方式 2:条件查找文档然后直接批量删除 ```js // 删除字段a的值大于2的文档 collection .where({ a: _.gt(2), }) .remove() .then(function (res) { const deleted = res.deleted; }); ``` ## update / set #### 1. 接口描述 接口功能:更新文档 接口声明: `update(object: ): Promise` `set(object: ): Promise` 备注:update 和 set 都可以用来更新文档,区别是 set 方法在要更新的文档不存在时新增一个文档;而 update 方法什么也不会做,返回 updated 为 0 #### 2. 输入参数 | 字段 | 类型 | 必填 | 说明 | | ---- | --------- | ---- | -------------- | | - | | 是 | 替换文档的定义 | #### 3. 输出参数 | 字段 | 类型 | 必填 | 说明 | | ---------- | ------- | ---- | ------------------------ | | code | string | 否 | 状态码,操作成功则不返回 | | message | string | 否 | 错误描述 | | updated | Integer | 否 | 影响的文档数量 | | upsertedId | string | 否 | 插入的文档的 id | | requestId | string | 是 | 请求序列号,用于错误排查 | #### 4. 示例代码 更新指定文档 ```js //更新指定文档 collection .doc("doc-id") .update({ name: "Hey", }) .then(function (res) {}); ``` 更新文档,如果不存在则创建 ```js //更新单个文档 collection .doc("doc-id") .set({ name: "Hey", }) .then(function (res) {}); //批量更新文档 collection .where({ name: _.eq("hey") }) .update({ age: 18, }) .then(function (res) {}); ``` ## GEO 地理位置 注意:**如果需要对类型为地理位置的字段进行搜索,一定要建立地理位置索引**。 ### GEO 数据类型 #### Point 用于表示地理位置点,用经纬度唯一标记一个点,这是一个特殊的数据存储类型。 签名:`Point(longitude: number, latitude: number)` 示例: ```js new db.Geo.Point(longitude, latitude); ``` #### LineString 用于表示地理路径,是由两个或者更多的 `Point` 组成的线段。 签名:`LineString(points: Point[])` 示例: ```js new db.Geo.LineString([ new db.Geo.Point(lngA, latA), new db.Geo.Point(lngB, latB), // ... ]); ``` #### Polygon 用于表示地理上的一个多边形(有洞或无洞均可),它是由一个或多个**闭环** `LineString` 组成的几何图形。 由一个环组成的 `Polygon` 是没有洞的多边形,由多个环组成的是有洞的多边形。对由多个环(`LineString`)组成的多边形(`Polygon`),第一个环是外环,所有其他环是内环(洞)。 签名:`Polygon(lines: LineString[])` 示例: ```js new db.Geo.Polygon([ new db.Geo.LineString(...), new db.Geo.LineString(...), // ... ]) ``` #### MultiPoint 用于表示多个点 `Point` 的集合。 签名:`MultiPoint(points: Point[])` 示例: ```js new db.Geo.MultiPoint([ new db.Geo.Point(lngA, latA), new db.Geo.Point(lngB, latB), // ... ]); ``` #### MultiLineString 用于表示多个地理路径 `LineString` 的集合。 签名:`MultiLineString(lines: LineString[])` 示例: ```js new db.Geo.MultiLineString([ new db.Geo.LineString(...), new db.Geo.LineString(...), // ... ]) ``` #### MultiPolygon 用于表示多个地理多边形 `Polygon` 的集合。 签名:`MultiPolygon(polygons: Polygon[])` 示例: ```js new db.Geo.MultiPolygon([ new db.Geo.Polygon(...), new db.Geo.Polygon(...), // ... ]) ``` ### GEO 操作符 #### geoNear 按从近到远的顺序,找出字段值在给定点的附近的文档。 签名: ```js db.command.geoNear(options: IOptions) interface IOptions { geometry: Point // 点的地理位置 maxDistance?: number // 选填,最大距离,米为单位 minDistance?: number // 选填,最小距离,米为单位 } ``` 示例: ```js db.collection("user").where({ location: db.command.geoNear({ geometry: new db.Geo.Point(lngA, latA), maxDistance: 1000, minDistance: 0, }), }); ``` #### geoWithin 找出字段值在指定 Polygon / MultiPolygon 内的文档,无排序 签名: ```js db.command.geoWithin(IOptions); interface IOptions { geometry: Polygon | MultiPolygon; // 地理位置 } ``` 示例: ```js // 一个闭合的区域 const area = new Polygon([ new LineString([ new Point(lngA, latA), new Point(lngB, latB), new Point(lngC, latC), new Point(lngA, latA), ]), ]); // 搜索 location 字段在这个区域中的 user db.collection("user").where({ location: db.command.geoWithin({ geometry: area, }), }); ``` #### geoIntersects 找出字段值和给定的地理位置图形相交的文档 签名: ```js db.command.geoIntersects(IOptions); interface IOptions { geometry: | Point | LineString | MultiPoint | MultiLineString | Polygon | MultiPolygon; // 地理位置 } ``` 示例: ```js // 一条路径 const line = new LineString([new Point(lngA, latA), new Point(lngB, latB)]); // 搜索 location 与这条路径相交的 user db.collection("user").where({ location: db.command.geoIntersects({ geometry: line, }), }); ``` ## 数据库实时推送 监听指定集合中符合查询条件的文档,通过 onchange 回调获得文档的变化详情 (where 参数为查询条件 参考 [查询文档](#查询文档)) ```js import cloudbase from "@cloudbase/js-sdk"; const app = cloudbase.init({ env: "tcbenv-mPIgjhnq", }); const db = app.database(); const _ = db.command; const collection = db.collection("collName"); // collName 需填当前env下集合名称 let ref = collection.where({ test: _.gt(0) }).watch({ onChange: (snapshot) => { console.log("收到snapshot**********", snapshot); }, onError: (error) => { console.log("收到error**********", error); }, }); ``` 单个 doc 的监听,也可以采用 doc('docId').watch()形式 ```js let ref = collection.doc("one docId").watch({ onChange: (snapshot) => { console.log("收到snapshot**********", snapshot); }, onError: (error) => { console.log("收到error**********", error); }, }); ``` 手动关闭监听,当前监听将不再收到推送 ```js ref.close().then((result) => { // 监听被关闭 }); ``` --- ## 云函数 # 云函数 ## callFunction ### 1. 接口描述 接口功能:执行云函数 接口声明:`callFunction(object: Object): Promise` ### 2. 输入参数 | 字段 | 类型 | 必填 | 说明 | | -------- | -------- | ---- | ---------------------------------------------------------------------------------------------------------------------- | | name | string | 是 | 云函数名称 | | data | object | 否 | 云函数参数 | | callback | function | 否 | 回调函数 | | parse | boolean | 否 | 设置为 true 时,当函数返回值为对象时,API 请求会返回解析对象,而不是 JSON 字符串,适用于在浏览器调试时直接查看返回结果 | 函数型云托管 额外可以传参数,传入 `type:'cloudrun'` 参数后,将调用函数型云托管 服务 | 字段 | 类型 | 必填 | 说明 | | -------- | ------------------------ | ---- | -------------------------------- | | `type` | `cloudrun` | 否 | 是否调用 基于 云托管的函数型云托管 | | `method` | `string` | 否 | HTTP 请求方法 | | `path` | `string` | 否 | HTTP 请求路径 | | `header` | `Record` | 否 | HTTP 请求头 | | `data` | `object` | 否 | HTTP 请求体 | ### 3. 输出参数 | 字段 | 类型 | 必填 | 说明 | | --------- | ------ | ---- | ------------------------ | | code | string | 否 | 状态码,操作成功则不返回 | | message | string | 否 | 错误描述 | | result | object | 否 | 云函数执行结果 | | requestId | string | 否 | 请求序列号,用于错误排查 | ### 4. 示例代码 ```javascript import cloudbase from "@cloudbase/js-sdk"; //初始化SDK实例 const app = cloudbase.init({ env: "xxxx-yyy", }); app .callFunction({ name: "test", data: { a: 1 }, }) .then((res) => { const result = res.result; //云函数执行结果 }); ``` 函数型云托管 示例代码: ```ts import cloudbase from "@cloudbase/js-sdk"; //初始化SDK实例 const app = cloudbase.init({ env: "xxxx-yyy", }); app .callFunction({ name: "test", // 函数型云托管 参数 type: "cloudrun", method: "POST", path: "/abc", data: { key1: "test value 1", key2: "test value 2", }, }) .then((res) => { const result = res.result; //云函数执行结果 }); ``` --- ## 初始化 # 初始化 @cloudbase/js-sdk 让您可以在 Web 端(如 PC Web 页面、微信公众平台 H5 等)使用 JavaScript 访问 Cloudbase 服务和资源。 :::tip 提示 当前@cloudbase/js-sdk latest 版本已升级至 v2 版本,若需使用 v1 版本,请参考[v1 文档](/api-reference/webv2/initialization)。 ::: ## 安装 ### 方式一:通过包管理器引入 ```bash #npm npm install @cloudbase/js-sdk -S # yarn yarn add @cloudbase/js-sdk ``` ### 方式二:通过 CDN 引入 通过 CDN 引入有两种方式: #### 引入全量 SDK ```html const app = cloudbase.init({ env: "your-env-id", clientId: "xxxx", // 应用ID }); ``` #### 按需引入功能模块 ```html const app = cloudbase.init({ env: "your-env-id", clientId: "xxxx", // 应用ID }); ``` :::tip 提示 功能模块必须在内核之后引入,并且登录模块必须引入。 ::: 最新的版本号 version 可以前往 [NPM](https://www.npmjs.com/package/@cloudbase/js-sdk) 查看。 ## 使用 通过包管理器安装 @cloudbase/js-sdk 之后,在项目源码中有两种引入方式: ### 方式一:引入全量 SDK ```js import cloudbase from "@cloudbase/js-sdk"; const app = cloudbase.init({ env: "your-env-id", clientId: "xxxx", // 应用ID }); ``` ### 方式二:按需引入功能模块 ```js // 内核 import cloudbase from "@cloudbase/js-sdk/app"; // 登录模块 import "@cloudbase/js-sdk/auth"; // 云函数模块 import "@cloudbase/js-sdk/functions"; // 云存储模块 import "@cloudbase/js-sdk/storage"; // 数据库模块 import "@cloudbase/js-sdk/database"; // 实时推送模块,引入前必须首先引入数据库模块 import "@cloudbase/js-sdk/realtime"; // 广告上报模块 import "@cloudbase/js-sdk/analytics"; const app = cloudbase.init({ env: "your-env-id", }); ``` :::tip 提示 功能模块必须在内核之后引入,并且登录模块必须引入。 ::: **请注意**:以上代码展示的功能模块引入方式仅在浏览器环境下有效,对于非浏览器环境的 JavaScript 运行时,必须在引入功能模块后手动注册模块,代码如下: ```js // 内核 import cloudbase from "@cloudbase/js-sdk/app"; // 登录模块 import { registerAuth } from "@cloudbase/js-sdk/auth"; // 云函数模块 import { registerFunctions } from "@cloudbase/js-sdk/functions"; // 云存储模块 import { registerStorage } from "@cloudbase/js-sdk/storage"; // 数据库模块 import { registerDatabase } from "@cloudbase/js-sdk/database"; // 实时推送模块,引入前必须首先引入数据库模块 import { registerRealtime } from "@cloudbase/js-sdk/realtime"; // 数据模型模块 import { registerModel } from "@cloudbase/js-sdk/model"; // AI 模块 import { registerAi } from "@cloudbase/js-sdk/ai"; // 注册功能模块 registerAuth(cloudbase); registerFunctions(cloudbase); registerStorage(cloudbase); registerDatabase(cloudbase); registerRealtime(cloudbase); registerModel(cloudbase); registerAi(cloudbase); const app = cloudbase.init({ env: "your-env-id", clientId: "xxxx", // 应用ID }); ``` ## 地域 init 初始化时可以指定 region,默认使用上海地域(ap-shanghai),目前支持的地域列表[参考](https://cloud.tencent.com/document/product/876/51107)。 示例: 当前有上海地域的环境 env-shanghai,广州地域的环境 env-guangzhou 则正确的初始化方式为: ```js // region 不填默认为上海地域,信息一致 const app = cloudbase.init({ env: "env-shanghai", clientId: "xxxx", // 应用ID }); ``` ```js // env地域 与 region 一致 const app = cloudbase.init({ env: "env-shanghai", clientId: "xxxx", // 应用ID region: "ap-shanghai", }); ``` ```js // env地域 与 region 一致 const app = cloudbase.init({ env: "env-guangzhou", clientId: "xxxx", // 应用ID region: "ap-guangzhou", }); ``` :::tip 提示 当前使用的环境所属地域,必须与当前指定的地域信息一致! ::: ## 更友好的错误日志 @cloudbase/js-sdk 在开发环境下会将调用 API 的错误信息以更友好的方式打印到控制台,如下图所示: ![](https://main.qcloudimg.com/raw/5e8d21f2784f03501a27eba39ceb27a8.png) 图中打印的错误是当前的登录类型受到函数的安全规则限制,导致没有调用函数的权限。错误信息分为两部分: 1. 上半部分的黑色字体提示包含了后端 API 返回的错误信息以及基于此报错的一些解决方案提示; 2. 下半部分的红色字体是经优化后的错误堆栈,由于原始错误堆栈层次太深导致 debug 非常困难,所以此处打印的错误堆栈的第一条直接定位到 SDK 源码,第二条定位到调用报错 API 的业务源码。 优化的错误提示仅在开发环境中使用,根据`process.env.NODE_ENV`判断是否为开发环境。此外,定位到 SDK 源码需要借助 SourceMap。 以上两点依赖构建工具的部分特性,目前仅支持 Webpack 和 Rollup。 #### Webpack 在 Webpack 4+ 版本中可以配置`mode`选项为`development`,如下: ```js module.exports = { mode: "development", }; ``` 如果是旧版本的 Webpack 需要使用[DefinePlugin](https://webpack.js.org/plugins/define-plugin/): ```js const webpack = require("webpack"); module.exports = { plugins: [ new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("development"), }), // ...其他插件 ], // ...其他配置 }; ``` 然后为 js 的编译选项加入 sourcemap 预处理,这里需要使用[source-map-loader](https://github.com/webpack-contrib/source-map-loader): ```js module.exports = { module: { rules: [ { test: /\.js$/, enforce: "pre", use: ["source-map-loader"], }, // ...其他rules ], }, // ...其他配置 }; ``` 配置完成后启动 webpack-dev-server 即可。 #### Rollup Rollup 需要使用两个插件: - [rollup-plugin-replace](https://github.com/rollup/rollup-plugin-replace)用来注入`process.env.NODE_ENV` - [rollup-plugin-sourcemaps](https://github.com/maxdavidson/rollup-plugin-sourcemaps)用来加载 sourcemap 配置如下: ```js import sourcemaps from "rollup-plugin-sourcemaps"; import replace from "rollup-plugin-replace"; export default { plugins: [ sourcemaps(), replace({ "process.env.NODE_ENV": JSON.stringify("development"), }), // ...其他插件 ], // ...其他配置 }; ``` 配置完成使用[rollup-plugin-serve](https://github.com/thgh/rollup-plugin-serve)启动 dev server 即可。 --- ## 从 cloudbase js sdk v1 迁移 # 从 cloudbase js sdk v1 迁移 ## 登录认证 从 v1 到 v2,登录认证模块有以下变化: - 登录状态持久化:登录状态只支持 `local` 模式 - v2 版本不再支持监听用户登录状态改变 - **v2 版本不再支持公众号登录方式**,如需使用该方式,请用 [v1 版本](/authentication/method/wechat-login) - 用户字段信息精简化,详见 [User](#user) - 对账户关联使用方式进行了调整,并且不再支持关联自定义登录,详见「[登录认证 v2 |账户关联](../../authentication-v2/auth/account-linking.md)」 - 对登录的使用方式进行了调整,详见「[登录认证 v2 |登录认证](../../authentication-v2/method/anonymous.md)」 ### 接口调整 #### Auth ##### 更新 - 接口命名 typo 修正:不再使用 `Auth.getCurrenUser()`,请使用 [`Auth.getCurrentUser()`](./authentication.md#authgetcurrentuser) ##### 新增 - [Auth.bindEmail](./authentication.md#authbindemail) - [Auth.bindPhoneNumber](./authentication.md#authbindphonenumber) - [Auth.bindWithProvider](./authentication.md#authbindwithprovider) - [Auth.deleteMe](./authentication.md#authdeleteme) - [Auth.genProviderRedirectUri](./authentication.md#authgenproviderredirecturi) - [Auth.getAccessToken](./authentication.md#authgetaccesstoken) - [Auth.getProviders](./authentication.md#authgetproviders) - [Auth.getUserInfo](./authentication.md#authgetuserinfo) - [Auth.getVerification](./authentication.md#authgetverification) - [Auth.grantProviderToken](./authentication.md#authgrantprovidertoken) - [Auth.loginScope](./authentication.md#authloginscope) - [Auth.queryUser](./authentication.md#authqueryuser) - [Auth.resetPassword](./authentication.md#authresetpassword) - [Auth.setCustomSignFunc](./authentication.md#authsetcustomsignfunc) - [Auth.setPassword](./authentication.md#authsetpassword) - [Auth.signIn](./authentication.md#authsignin) - [Auth.signInAnonymously](./authentication.md#authsigninanonymously) - [Auth.signInWithCustomTicket](./authentication.md#authsigninwithcustomticket) - [Auth.signInWithOpenId](./authentication.md#authsigninwithopenid) - [Auth.signInWithPhoneAuth](./authentication.md#authsigninwithphoneauth) - [Auth.signInWithProvider](./authentication.md#authsigninwithprovider) - [Auth.signInWithSms](./authentication.md#authsigninwithsms) - [Auth.signInWithEmail](./authentication.md#signInWithEmail) - [Auth.signInWithUnionId](./authentication.md#authsigninwithunionid) - [Auth.signUp](./authentication.md#authsignup) - [Auth.sudo](./authentication.md#authsudo) - [Auth.unbindProvider](./authentication.md#authunbindprovider) - [Auth.verify](./authentication.md#authverify) ##### 废弃 - Auth.anonymousAuthProvider - Auth.customAuthProvider - Auth.forceResetPwdByPhoneCode - Auth.getAuthHeader - Auth.getAuthHeaderAsync - Auth.onAccessTokenRefreshed - Auth.onAnonymousConverted - Auth.onLoginStateExpired - Auth.onLoginTypeChanged - Auth.sendPasswordResetEmail - Auth.sendPhoneCode - Auth.shouldRefreshAccessToken - Auth.signInWithEmailAndPassword - Auth.signInWithPhoneCodeOrPassword - Auth.signInWithUsernameAndPassword - Auth.signUpWithEmailAndPassword - Auth.signUpWithPhoneCode - Auth.weixinAuthProvider #### LoginState ##### 废弃 - LoginState.isAnonymousAuth - LoginState.isCustomAuth - LoginState.isUsernameAuth - LoginState.isWeixinAuth - LoginState.loginType #### User ##### 废弃 - User.avatarUrl - User.linkWithPhoneNumber - User.nickName - User.updateEmail - User.updatePassword - User.updatePhoneNumber - User.updateUsername --- ## 初始化 # 初始化 使用 js-sdk 进行初始化并登录后,通过 `.models` 获取数据模型实例。 ```js import cloudbase from "@cloudbase/js-sdk"; const app = cloudbase.init({ env: "your-env-id" }); const auth = app.auth(); await auth.signInAnonymously(); const models = app.models; ``` --- ## 增删改查 import Doc from '@site/docs/model/sdk-reference/_model.md'; # 增删改查 --- ## 查询参数详解 import Doc from "@site/docs/model/_select.md" # 查询参数详解 --- ## 云存储 # 云存储 ## uploadFile #### 1. 接口描述 接口功能:上传文件到文件管理服务 接口声明:`uploadFile(object: Object): Promise` :::tip 提示 1.0.1 版本后,为了提高文件上传性能,文件上传方式修改为直接上传到对象存储,为了防止在使用过程中出现 CORS 报错,需要登录 **[云开发平台](https://tcb.cloud.tencent.com/dev)** ,在 **[安全来源](https://tcb.cloud.tencent.com/dev#/env/safety-source)** 页面的 **安全域名** 添加域名。如果已有域名出现 CORS 报错,请删除安全域名,重新添加。 ::: #### 2. 输入参数 | 字段 | 类型 | 必填 | 说明 | | ---------------- | ---------------- | ---- | -------------------------- | | cloudPath | string | 是 | 文件的绝对路径,包含文件名 | | filePath | HTML upload file | 是 | 要上传的文件对象 | | method | 'post' \| 'put' | 否 | 上传方法,默认为 put | | onUploadProgress | function | 否 | 上传进度回调 | :::tip 提示 `cloudPath` 为文件的绝对路径,包含文件名 foo/bar.jpg、foo/bar/baz.jpg 等,不能包含除[0-9 , a-z , A-Z]、/、!、-、\_、.、、\*和中文以外的字符,使用 / 字符来实现类似传统文件系统的层级结构。[查看详情](https://cloud.tencent.com/document/product/436/13324) ::: #### 3. 输出参数 | 字段 | 类型 | 必填 | 说明 | | --------- | ------ | ---- | --------------------------------------- | | code | string | 否 | 状态码,操作成功则不返回 | | message | string | 否 | 错误描述 | | fileID | fileID | 是 | 文件唯一 ID,用来访问文件,建议存储起来 | | requestId | string | 否 | 请求序列号,用于错误排查 | #### 4. 示例代码 ```javascript import cloudbase from "@cloudbase/js-sdk"; const app = cloudbase.init({ env: "xxxx-yyy", }); app .uploadFile({ cloudPath: "test-admin.jpeg", filePath: document.getElementById("file").files[0], onUploadProgress: function (progressEvent) { console.log(progressEvent); var percentCompleted = Math.round( (progressEvent.loaded * 100) / progressEvent.total ); }, }) .then((result) => { // 上传结果 }); ``` ## getTempFileURL #### 1. 接口描述 接口功能:获取文件 CDN 下载链接 接口声明:`getTempFileURL(object: Object): Promise` #### 2. 输入参数 | 字段 | 类型 | 必填 | 说明 | | -------- | -------------------- | ---- | -------------------------- | | fileList | <Array>.string | 是 | 要下载的文件 ID 组成的数组 | ##### fileList | 字段 | 类型 | 必填 | 说明 | | ------ | ------- | ---- | -------------- | | fileID | string | 是 | 文件 ID | | maxAge | Integer | 是 | 文件链接有效期 | #### 3. 输出参数 | 字段 | 类型 | 必填 | 说明 | | --------- | -------------------- | ---- | ---------------------------- | | code | string | 否 | 状态码,操作成功则为 SUCCESS | | message | string | 否 | 错误描述 | | fileList | <Array>.object | 否 | 存储下载链接的数组 | | requestId | string | 否 | 请求序列号,用于错误排查 | ##### fileList | 字段 | 类型 | 必填 | 说明 | | ----------- | ------ | ---- | ------------------------ | | code | string | 否 | 删除结果,成功为 SUCCESS | | message | string | 否 | 错误描述 | | fileID | string | 是 | 文件 ID | | tempFileURL | string | 是 | 文件访问链接 | #### 4. 示例代码 ```javascript //初始化SDK实例部分代码如上 app .getTempFileURL({ fileList: [ "cloud://jimmytest-088bef.jimmytest-088bef-1251059088/a|b测试.jpeg", ], }) .then((res) => { res.fileList.forEach((el) => { if (el.code === "SUCCESS") { console.log(el.tempFileURL); } else { //获取下载链接失败 } }); }); ``` ## deleteFile #### 1. 接口描述 接口功能:删除文件 接口声明:`deleteFile(object: Object): Promise` #### 2. 输入参数 | 字段 | 类型 | 必填 | 说明 | | -------- | -------------------- | ---- | -------------------------- | | fileList | <Array>.string | 是 | 要删除的文件 ID 组成的数组 | #### 3. 输出参数 | 字段 | 类型 | 必填 | 说明 | | --------- | -------------------- | ---- | ------------------------ | | code | string | 否 | 状态码,操作成功则不返回 | | message | string | 否 | 错误描述 | | fileList | <Array>.object | 否 | 删除结果组成的数组 | | requestId | string | 否 | 请求序列号,用于错误排查 | #### fileList | 字段 | 类型 | 必填 | 说明 | | ------ | ------ | ---- | ------------------------ | | code | string | 否 | 删除结果,成功为 SUCCESS | | fileID | string | 是 | 文件 ID | #### 4. 示例代码 ```javascript app .deleteFile({ fileList: ["cloud://jimmytest-088bef/1534576354877.jpg"], }) .then((res) => { res.fileList.forEach((el) => { if (el.code === "SUCCESS") { //删除成功 } else { } }); }); ``` ## downloadFile #### 1. 接口描述 接口功能:下载文件到本地 接口声明:`downloadFile(object: Object): Promise` #### 2. 输入参数 | 字段 | 类型 | 必填 | 说明 | | ------ | ------ | ---- | ----------------- | | fileID | string | 是 | 要下载的文件的 id | #### 3. 输出参数 | 字段 | 类型 | 必填 | 说明 | | --------- | ------ | ---- | ------------------------ | | code | string | 否 | 状态码,操作成功则不返回 | | message | string | 否 | 错误描述 | | requestId | string | 否 | 请求序列号,用于错误排查 | #### 4. 示例代码 ```javascript cloudbase .downloadFile({ fileID: "cloud://aa-99j9f/my-photo.png", }) .then((res) => {}); ``` --- ## SDK 1.x 版本升级至 2.x 版本 # SDK 1.x 版本升级至 2.x 版本 **@cloudbase/js-sdk@2.x** 相比 1.x,做了登录模块的重新设计,而其他资源模块(函数,数据库,存储)的使用方式不变。 ## 迁移指南 ### 新旧版本登录模块对比(接口&属性) #### LoginType 相关 SDK 2.x 登录模块移除了 loginType 概念,不再对外暴露 **ANONYMOUS**, **WECHAT**, **CUSTOM**, **EMAIL**, **PHONE** 等类型。 :::tip 解释 ::: #### LoginState 相关 | 废弃 API(属性) | 说明 | | -------------------------- | ------------------------------------------------------- | | Auth.onLoginStateExpired | SDK 登录完成后, 内部维护登录态,无需开发者关心是否过期 | | LoginState.loginType | 废弃 loginType | | LoginState.isAnonymousAuth | 废弃 loginType | | LoginState.isCustomAuth | 废弃 loginType | | LoginState.isWeixinAuth | 废弃 loginType | | LoginState.isUsernameAuth | 废弃 loginType | #### AuthProvider 相关 | 废弃 API(属性) | 说明 | | -------------------------- | --------------------------------------------------------- | | Auth.weixinAuthProvider | 改为统一的第三方授权登录接口,参考接口 | | Auth.customAuthProvider | 废弃 customAuthProvider,改为 Auth.signInWithCustomTicket | | Auth.anonymousAuthProvider | 废弃 anonymousAuthProvider,改为 Auth.signInAnonymously | #### User 相关 废弃属性 | API(属性) | 说明 | | ------------------------ | -------------------------------------------------------------- | | User.loginType | 废弃 loginType | | User.openid | 废弃 User.openid, 使用参考新增属性 User.providers | | User.wxOpenId | 废弃 User.wxOpenId,使用参考新增属性 User.providers | | User.wxPublicId | 废弃 User.wxPublicId,使用参考新增属性 User.providers | | User.qqMiniOpenId | 废弃 User.qqMiniOpenId,使用参考新增属性 User.providers | | User.customUserId | 废弃 User.customUserId,用户唯一标识使用 User.uid | | User.nickName | 废弃 User.nickName,昵称使用新增属性 User.name | | User.avatarUrl | 废弃 User.avatarUrl,头像使用新增属性 User.picture | | User.hasPassword | 废弃 User.hasPassword | | User.location | 废弃 User.location | | User.linkWithTicket | 已废弃,目前自定义登录 userId 与云开发 uid 一致,无需关联操作 | | User.linkWithRedirect | 废弃 User.linkWithRedirect,使用新接口 Auth.bindWithProvider | | User.linkWithPhoneNumber | 废弃 User.linkWithPhoneNumber,使用新接口 Auth.bindPhoneNumber | | User.updateEmail | 废弃 User.updateEmail,使用新接口 Auth.bindEmail | | User.updatePhoneNumber | 废弃 User.updatePhoneNumber Auth.bindPhoneNumber | 新增属性 | API(属性) | 说明 | | ------------------- | ----------------------------------------------- | | User.name | 用户昵称(区分与 登录用户名 User.username) | | User.picture | 用户上传头像 | | User.phone_number | 用户绑定手机号 | | User.email_verified | 用户是否经过邮箱验证 | | User.birthdate | 用户生日 | | User.locale | 用户设置语言 | | User.zoneinfo | 时区 | | User.providers | 参考[UserProfileProvider](#UserProfileProvider) | #### UserProfileProvider | 字段 | 说明 | | ---------------- | ------------------------------------------------- | | id | 默认内置的三方 providerid,**wx_open**, **wx_mp** | | provider_user_id | 第三方 provider 用户 id (如 wxopenid) | | name | 名称 | ### Auth API 相关 新增 API | API | 说明 | | ----------------------- | --------------------------------------------- | | Auth.signIn | 登录接口(除匿名登录,第三方登录) | | Auth.signUp | 注册接口 | | Auth.getVerification | 统一获取验证码接口(手机号,邮箱) | | Auth.bindPhoneNumber | 绑定/更新手机号(原更新用户信息方式不再支持) | | Auth.bindEmail | 绑定/更新邮箱 (原更新用户信息方式不再支持) | | Auth.bindWithProvider | 绑定第三方平台(如微信开放/公众平台) | | Auth.unbindProvider | 解绑第三方平台 | | Auth.setPassword | 设置密码 | | Auth.queryUser | 条件查询用户信息 | | Auth.signInWithProvider | 第三方平台登录 | --- ## 账户关联 # 账户关联 每个云开发用户账号,除了最初注册时使用的登录方式外,还可以关联其它登录方式。关联后,无论用户使用哪种登录方式,均可以登录到同一个云开发账户。 例如: 1. 使用**自定义登录**的用户,可以关联微信登录,关联后便可以使用这两种方法的任意一种登录; 2. 使用**邮箱登录**的用户,可以关联用户名密码登录,关联后便可以使用这两种方法的任意一种登录; 3. 使用**匿名登录**的用户,可以关联自定义登录与微信登录,关联后账号会被转为正式用户,可以使用任一种方法登录云开发。 ## 关联微信登录 关联微信登录的步骤如下: 1. 用户**以任意一种登录方式(除微信登录)登录云开发** 2. 获取 Provider: ```js const auth = app.auth(); const provider = auth.weixinAuthProvider({ appid: "....", scope: "snsapi_base" }); ``` 3. 重定向到提供方的页面进行登录: ```js auth.currentUser.linkWithRedirect(provider); ``` 4. 用户在微信的页面登录之后,会被重定向回您的页面。然后,可以在页面加载时通过调用 `Provider.getLinkRedirectResult()` 来获取关联结果: ```js const provider = auth.weixinAuthProvider(); provider.getLinkRedirectResult().then((result) => { // 关联成功 }); ``` ## 关联自定义登录 关联自定义登录的步骤如下: 1. 用户**以任意一种登录方式(除自定义登录)登录云开发**; 2. 使用 `User.linkWithTicket`,[获取自定义登录 Ticket](/authentication/method/custom-login) 后,关联自定义用户: ```js const auth = app.auth(); const ticket = "......"; // 自定义登录 Ticket auth.currentUser.linkWithTicket(ticket).then((result) => { // 关联成功 }); ``` ## 关联邮箱密码登录 关联邮箱密码登录的步骤如下: 1. 用户**以任意一种登录方式登录云开发** 2. 更新用户的密码: ```js const auth = app.auth(); auth.currentUser.updatePassword(password).then(() => { // 设置密码成功 }); ``` 3. 更新用户的邮箱,用户点击验证邮件之后,便关联成功: ```js auth.currentUser.updateEmail(email).then(() => { // 发送验证邮件成功 }); ``` ## 关联用户名密码登录 关联邮箱密码登录的步骤如下: 1. 用户**以任意一种登录方式(除匿名登录)登录云开发**: ```js // 以邮箱登录为例 await app.auth().signInWithEmailAndPassword(email, password); ``` 2. 绑定登录的用户名: ```js await app.auth().currentUser.updateUsername(username); // 绑定用户名 ``` 3. 绑定成功后,便可以使用用户名密码登录: ```js const loginState = await app.auth().signInWithUsernameAndPassword(username, password); // 用户名密码登录 ``` { const { users, // UnionID 对应的云开发账号 hasPrimaryUid // 其中是否含有主账号 } = list }) ``` 获取到列表后,您可以询问用户,或者自动为用户选择其中一个账号作为主账号 ### 设置主账号 您可以通过 `User.setPrimaryUid()` 设置 UnionId 对应的主账号: ```js auth.currentUser.setPrimaryUid(uid).then(() => { // 设置主账号成功 }) ``` 设置为主账号之后,使用 UnionID 登录都会登录到此主账号之上。 --> --- ## 最佳实践 import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # 最佳实践 ## 避免重复登录 执行登录流程之前,我们非常建议您**先判断用户端是否已经登录 CloudBase**,如已经登录,那么不需要执行登录流程,以**避免无意义的重复登录**。 ```js const auth = app.auth(); // 应用初始化时 if (auth.hasLoginState()) { // 此时已经登录 } else { // 此时未登录,执行您的登录流程 } ``` ## 登录状态的持久保留 您可以指定登录状态如何持久保留。默认为 `local`,相关选项包括: | 值 | 说明 | | --------- | ---------------------------------------------------------- | | `session` | 在 SessionStorage 中保留登录状态,当前页面关闭后会被清除。 | | `local` | 在本地存储中长期地保留登录状态。 | | `none` | 在内存中保留登录状态,当前页面刷新、重定向之后会被清除。 | 例如,对于网页应用,最佳选择是 `local`,即在用户关闭浏览器之后仍保留该用户的会话。这样,用户不需要每次访问该网页时重复登录,避免给用户带来诸多不便体验。 ```js const auth = app.auth({ persistence: "local" }); ``` --- ## 概述 # 概述 CloudBase 提供跨平台的登录认证功能,您可以基于此为自己的应用构建用户体系,包括但不限于: - 为用户分配全局唯一的身份标识 uid; - 储存和管理用户个人信息; - 关联多种登录方式; - 管理用户对数据、资源的访问权限; - 用户行为的收集和分析。 同时,CloudBase 登录认证还是**保护您的服务资源**的重要手段,CloudBase 对用户端发来的每一个请求,都会进行身份和权限的检查,避免您的资源被恶意攻击者消耗或者盗用。 :::caution 适用范围 **[登录认证(v1)](/authentication/auth/introduce)** 适用于`@cloudbase/js-sdk@1.x`版本,如您使用的 SDK 版本为 2.x,请参考 **[登录认证(v2 beta)](/authentication-v2/auth/introduce)**。 ::: ## 登录认证方式 云开发 CloudBase 提供以下登录认证方式供不同的用户场景使用: | 登录类型 | 场景 | | ------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------- | | [匿名登录](/authentication/method/anonymous) | 用户以临时的匿名身份登录云开发,无需注册。 | | [邮箱登录](/authentication/method/email-login) | 用户使用自己的邮箱+密码登录。 | | [微信授权登录](/authentication/method/wechat-login) | 1、经**微信公众平台**授权的**公众号网页**; 2、经**微信开放平台**用授权的**网站**。 | | [自定义登录](/authentication/method/custom-login) | 开发者可以完全接管登录流程,例如与自有的账号体系打通、自定义登录逻辑等。 | | [用户名密码登录](/authentication/method/username-login) | 用户使用自己的用户名+密码登录。 | | [微信小程序登录](https://developers.weixin.qq.com/miniprogram/dev/wxcloud/guide/init.html) | 已开通云开发的微信小程序初始化后便同步完成登录认证,无需额外操作。 | | [短信验证码登录](/authentication/method/sms-login) | 用户使用自己的手机号+验证码登录。 | ## CloudBase 用户 每个登录 CloudBase 的用户,都有一个对应的 CloudBase 账号,用户通过此账号访问调用 CloudBase 的数据与资源。 ### UID 每个账号都有全局唯一的 UID,即账号 ID,作为用户的唯一身份标识。 ### 用户信息 每个账号可以添加、修改用户信息,请参考 [管理用户](/authentication/auth/manage-users)。 ### 登录方式 每个账号除了最初的登录方式之外,还可以关联其它登录方式,请参考 [账户关联](/authentication/auth/account-linking)。 ## 登录状态的持久化 您可以指定登录状态如何持久保留。默认为 `local`,相关选项包括: | 值 | 说明 | | --------- | ---------------------------------------------------------- | | `session` | 在 SessionStorage 中保留登录状态,当前页面关闭后会被清除。 | | `local` | 在本地存储中长期地保留登录状态。 | | `none` | 在内存中保留登录状态,当前页面刷新、重定向之后会被清除。 | 例如,对于网页应用,最佳选择是 `local`,即在用户关闭浏览器之后仍保留该用户的会话。这样,用户不需要每次访问该网页时重复登录,避免给用户带来诸多不便体验。 :::tip 注意 [匿名登录](/authentication/method/anonymous) 的持久化类型强制设为 `local`,外部设置的值会被忽略。 ::: ## 访问令牌与刷新令牌 用户登录 CloudBase 之后,会获得**访问令牌(Access Token)** 作为访问 CloudBase 的凭证,访问令牌**默认具有两小时有效期**。 登录时还会获得**刷新令牌(Refresh Token)**,**默认有效期 30 天**,用于访问令牌过期后,获取新的访问令牌。 CloudBase 用户端 SDK 会自动维护令牌的刷新和有效期,开发者无需特别关注此流程。 :::tip 注意 [匿名登录](/authentication/method/anonymous) 的刷新令牌(Refresh Token)会在到期后自动续期,以实现长期的匿名登录状态。 ::: --- ## 管理用户 # 管理用户 ## 创建用户 开发者可以调用以下登录方式,登录或者创建一个用户: - [邮箱登录](/authentication/method/email-login) - [微信登录](/authentication/method/wechat-login) - [自定义登录](/authentication/method/custom-login) - [用户名密码登录](/authentication/method/username-login) - [匿名登录](/authentication/method/anonymous) ## 获取当前登录的用户 ### 订阅登录状态变化的回调函数 获取当前用户,推荐在 `Auth` 对象上设置一个回调函数,每当用户登录状态转变时,会触发这个回调函数,并且获得当前的 `LoginState`: ```js import cloudbase from "@cloudbase/js-sdk"; const app = cloudbase.init({ env: "your-env-id" }); const auth = app.auth(); // 设置一个观察者 auth.onLoginStateChanged((loginState) => { if (loginState) { // 此时用户已经登录 } else { // 没有登录 } }); ``` ### 直接获取当前用户 您还可以使用 `Auth.currentUser` 属性来获取当前登录的用户。如果用户未登录,则 `currentUser` 为 `null`: ```js const user = auth.currentUser; if (user) { // 此时用户已经登录 } else { // 没有登录 } ``` ## 获取用户个人资料 您可以通过 `User` 对象的各个属性来获取用户的个人资料信息: ```js const user = auth.currentUser; let uid, nickName, gender, avatarUrl, location; if (user) { // 云开发唯一用户 id uid = user.uid; // 昵称 nickName = user.nickName; // 性别 gender = user.gender; // 头像URL avatarUrl = user.avatarUrl; // 用户地理位置 location = user.location; } ``` ## 更新用户个人资料 您可以使用 `User.update` 方法来更新用户的个人资料信息。例如: ```js const user = auth.currentUser; user .update({ nickName: "Tony Stark", gender: "MALE", avatarUrl: "https://..." }) .then(() => { // 更新用户资料成功 }); ``` ## 刷新用户资料信息 对于一个多端应用,用户可能在其中某个端上更新过自己的个人资料信息,此时其它端上可能需要刷新信息: ```js const user = auth.currentUser; // 刷新用户信息 user.refresh().then(() => { // 刷新后,获取到的用户信息即为最新的信息 const { nickName, gender, avatarUrl } = user; }); ``` --- ## 匿名登录 import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; CloudBase 匿名登录的所有逻辑均可由客户端代码主动执行,无需用户手动操作。在匿名登录状态下可正常的调用 CloudBase 的资源,开发者同时可以配合安全规则针对匿名用户制定对应的访问限制。 ## 开通流程 ### 开启匿名登录 登录 [腾讯云 CloudBase 控制台](https://console.cloud.tencent.com/tcb),在 [登录授权](https://console.cloud.tencent.com/tcb/env/login)页面中,将**匿名登录**一栏打开或关闭。 ![开启匿名登录](https://main.qcloudimg.com/raw/9687b33a65415e39299f12a57ae741a6.jpg) ### 添加安全域名(可选) Web 应用需要将域名添加到 CloudBase 控制台的 [Web 安全域名](https://console.cloud.tencent.com/tcb/env/safety)列表中,否则将被识别为非法来源: ## 登录流程 ```js import cloudbase from '@cloudbase/js-sdk'; const app = cloudbase.init({ env: 'xxxx-yyy'; }); const auth = app.auth(); async function login(){ await auth.anonymousAuthProvider().signIn(); // 匿名登录成功检测登录状态isAnonymous字段为true const loginState = await auth.getLoginState(); console.log(loginState.isAnonymousAuth); // true } login(); ``` ## 安全规则 匿名用户在安全规则中的`auth.loginType`值为`ANONYMOUS`,配合安全规则可以限制匿名用户的 [数据库](/database/introduce) 和 [云存储](/storage/introduce.md) 的访问权限。比如下述代码展示的安全规则为: - 数据库匿名用户不可读写; - 云存储所有用户可读,匿名用户不可写。 ```json { "read": "auth.loginType != 'ANONYMOUS'", "write": "auth.loginType != 'ANONYMOUS'" } ``` ```json { "read": "auth != null", "write": "auth.loginType != 'ANONYMOUS'" } ``` :::tip 详细请查看 [安全规则-用户身份认证](/rule/rule-example#用户身份认证)。 ::: ## 转化为正式用户 如果用户在匿名状态下产生了一些私有数据(例如游戏中获取了个人成就和装备),想将此匿名账号转化为正式账号长久持有。 针对这种需求,您可以 [**将匿名账号与任意一种登录方式关联**](/authentication/auth/account-linking),关联后,便可以永久使用该种登录方式登录 CloudBase,达成”匿名账号转正“的效果。 详情请参考:[账户关联](/authentication/auth/account-linking)。 ## 常见问题 - **匿名登录与未登录有什么区别?** 从 C 端用户的角度来讲: - 匿名登录和未登录在上手使用上没有任何区别,都无需注册; - 匿名登录用户有独立的用户标识,在同设备有效期内,用户可以产生独立的私有数据; - 与未登录相比,匿名登录可以转为正式用户,匿名登录期间的私有数据会自动继承到正式用户名下。 从应用开发者的角度来讲: - CloudBase 匿名登录产生的匿名用户本质上是一个有效用户,拥有唯一的用户 ID。从而可以为其创建私有的 [数据库](/database/introduce) 和 [云存储](/storage/introduce.md) 数据,以及配合 [安全规则](/rule/introduce.md) 制定个性化的访问策略; - 未登录模式是纯粹的无登录态访问,该模式下的访问都不会进入用户的追踪统计; - 未登录的用户默认权限下无法使用任何 CloudBase 的服务和资源,而匿名登录在基础权限下也可以进行对应的资源读写,也可以结合安全规则实现更细粒度的管控。 - **匿名用户是否会过期?** CloudBase 对匿名用户的有效期限策略是:每个设备同时只存在一个匿名用户,并且此用户永不过期。当然,如果用户手动清除了设备或浏览器的本地数据,那么匿名用户的数据便会被同步清除,再次调用 CloudBase 匿名登录 API 会产生一个新的匿名用户。 --- ## 自定义登录 import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; 开发者可以使用**自定义登录**,在自己的服务器或者云函数内,为用户签发带有**自定义身份 ID** 的自定义登录凭证 Ticket,随后用户端 SDK 便可以使用 Ticket 登录 CloudBase。 ## 适用场景 自定义登录一般用于下面几种场景: - 开发者希望将自有的账号体系与云开发 CloudBase 账号进行一对一关联; - 开发者希望自行接管鉴权流程。 ## 步骤概览 自定义登录需要以下几个步骤: 1. 获取 CloudBase 自定义登录私钥; 2. 使用 CloudBase 服务端 SDK,通过私钥签发出 Ticket,并返回至用户端; 3. 用户端 SDK 使用 Ticket 登录 CloudBase。 ## 第 1 步:获取自定义登录私钥 登录 [CloudBase 控制台](https://console.cloud.tencent.com/tcb),在 [**环境 -> 登录授权**](https://console.cloud.tencent.com/tcb/env/login)下的**自定义登录**栏中,点击「**私钥下载**」或者「**私钥复制**」: ![云开发下载私钥](https://main.qcloudimg.com/raw/0bb09d8396a8be694d2fa1c7390efe6d.jpg) 私钥是一份携带有 JSON 数据的文件,请将下载或复制的私钥文件保存到您的服务器或者云函数中,假设路径为`/path/to/your/tcb_custom_login.json`。 :::caution 注意 1. 私钥文件是证明管理员身份的重要凭证,请务必妥善保存,避免泄漏; 2. 每次生成私钥文件都会**使之前生成的私钥文件在 2 小时后失效**。 ::: ## 第 2 步:签发 Ticket 调用 CloudBase 服务端 SDK,在初始化时传入自定义登录私钥,随后便可以签发出 Ticket,并返回至用户端。 ```js const cloudbase = require("@cloudbase/node-sdk"); // 1. 初始化 SDK const app = cloudbase.init({ env: "your-env-id", // 传入自定义登录私钥 credentials: require("/path/to/your/tcb_custom_login.json") }); // 2. 开发者自定义的用户唯一身份标识 const customUserId = "your-customUserId"; // 3. 创建ticket const ticket = app.auth().createTicket(customUserId); // 4. 将ticket返回至客户端 return ticket; ``` :::tip 开发者也可以编写一个**云函数**用于生成 Ticket,并为其设置 HTTP 访问服务,随后用户端便可以通过 HTTP 请求的形式获取 Ticket,详细的方案请参阅 [使用 HTTP 访问云函数](/service/access-cloud-function)。 ::: :::caution 注意 customUserId 必须满足以下需求: - 4-32 位字符; - 字符只能是大小写英文字母、数字、以及 `_-#@(){}[]:.,+#~` 中的字符。 ::: ## 第 3 步:使用 Ticket 登录 CloudBase 用户端应用获取到 Ticket 之后,便可以调用客户端 SDK 提供的 `auth.signInWithTicket()` 登录 CloudBase: ```js import cloudbase from '@cloudbase/js-sdk'; const app = cloudbase.init({ env: 'your-env-id' }); const auth = app.auth(); async function login(){ const loginState = await auth.getLoginState(); // 1. 建议登录前检查当前是否已经登录 if(!loginState){ // 2. 请求开发者自有服务接口获取ticket const ticket = await fetch('...'); // 3. 登录 CloudBase await auth.customAuthProvider().signIn(ticket); } } login(); ``` 整体流程示意如下: ![自定义登录](https://main.qcloudimg.com/raw/9574ad543504b4a4a8d784a3a224cf69.png) ## 常见问题 **自定义登录一定需要自己假设用于创建 Ticket 的服务器吗?** 自定义登录必须有一个创建 Ticket 的服务,但是开发者并非一定要自己搭建服务器。 开发者还可以编写一个云函数来创建 Ticket,然后客户端使用 HTTP 请求调用这个云函数获取 Ticket,详细请参阅 [使用 HTTP 访问云函数](/service/access-cloud-function)。 --- ## 邮箱登录 import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; 使用邮箱登录,您可以让您的用户**使用自己的邮箱和密码注册、登录 CloudBase**,并且还可以**更新登录使用的邮箱和密码**。 ## 开通邮箱登录 ### 第 1 步:开启邮箱登录 进入 [云开发 CloudBase 控制台](https://console.cloud.tencent.com/tcb/env/index),在 [登录授权](https://console.cloud.tencent.com/tcb/env/login) 设置页面中,开启邮箱登录: ![](https://main.qcloudimg.com/raw/8fa15115bce561b9a17cf188e4802565.png) ### 第 2 步:配置发件邮箱 打开右侧「配置发件人」页面,填入您邮箱的 **SMTP 账号信息**。 ![](https://main.qcloudimg.com/raw/d2dc0f0a3ae35169d1da4623f95b361b.png) ### 第 3 步:设置应用名称及自动跳转链接 打开右侧「应用配置」页面,设置您的**应用名称**和**自动跳转链接**。 :::tip - 您设置的**应用名称**将会出现在验证邮件的内容中; - CloudBase 发送的邮件中会包含一个 URL,用户打开邮件中的 URL 后,会自动跳转到您设置的**自动跳转链接**。 ::: ![](https://main.qcloudimg.com/raw/9a959e873b751455de27e3a517cafb20.png) ## 登录流程 ### 第 1 步:初始化 SDK ```js import cloudbase from "@cloudbase/js-sdk"; const app = cloudbase.init({ env: "your-env-id" }); ``` ### 第 2 步:使用邮箱注册账号 首先需要用户填入自己的邮箱和密码,然后调用 SDK 的注册接口: ```js app .auth() .signUpWithEmailAndPassword(email, password) .then(() => { // 发送验证邮件成功 }); ``` 调用注册接口之后,CloudBase 会使用您**预先设置的邮箱**,发送一封**验证邮件**到用户的邮箱。邮件中包含一个**激活链接**,用户在点击激活链接后,账号才会正式注册成功。 :::caution 密码强度要求 密码长度不小于 8 位,不大于 32 位,需要包含字母和数字。 ::: ### 第 3 步:使用邮箱+密码登录 CloudBase ```js app .auth() .signInWithEmailAndPassword(email, password) .then((loginState) => { // 登录成功 }); ``` ## 使用 QQ 邮箱配置邮箱登录 ### 第 1 步:登录 QQ 邮箱 进入 [QQ 邮箱首页](https://mail.qq.com/),登录您的 QQ 邮箱。 ### 第 2 步:开启 IMAP/SMTP 服务 登录邮箱后,进入「设置-账户」: ![](https://main.qcloudimg.com/raw/4ff92bd6b591d91fa48418c744e3d2b5/%E9%82%AE%E7%AE%B1%E7%99%BB%E5%BD%95-2.png) 然后,在「账户」设置中,找到「开启服务」设置项,开启 IMAP/SMTP 服务: ![](https://main.qcloudimg.com/raw/dbf325fbdc0d776e6ca451248cc3aaf4/%E9%82%AE%E7%AE%B1%E7%99%BB%E5%BD%95-2.2.png) 开启成功后,请保存您的邮箱登录授权码: ![](https://main.qcloudimg.com/raw/29b26a35a4303f7014de7de6aa554f2e/%E9%82%AE%E7%AE%B1%E7%99%BB%E5%BD%952-3.png) :::tip 注意 您也可以开启 POP3/SMTP 服务,两种服务的授权码都可以作为第 3 步的 SMTP 账号密码。 ::: ### 第 3 步:配置 QQ 邮箱作为发件人 进入 [云开发 CloudBase 控制台](https://console.cloud.tencent.com/tcb/env/index),在 [登录授权](https://console.cloud.tencent.com/tcb/env/login) 页面中,打开右侧「配置发件人」页面,选择 QQ 邮箱作为邮箱服务,使用 QQ 邮箱作为发件人地址和 SMTP 账号用户名,使用第 2 步的授权码作为 SMTP 账号密码。 ![](https://main.qcloudimg.com/raw/d732ed946f63faa9d05ffaed9e8d62a5/%E9%82%AE%E7%AE%B1%E7%99%BB%E5%BD%95-3.png) --- ## 未登录 import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; CloudBase 允许客户端在未登录的情况下调用 CloudBase 的资源,开发者可以配合安全规则限制未登录对资源的访问权限。 ## 开通流程 ### 第 1 步:开启未登录 登录 [云开发 CloudBase 控制台](https://console.cloud.tencent.com/tcb),在 [登录授权](https://console.cloud.tencent.com/tcb/env/login) 中,将**未登录**一栏打开或关闭。 ![开启未登录](https://main.qcloudimg.com/raw/ca0f903c6a0311068d297cd62ec4c074.png) ### 第 2 步:添加安全域名(可选) 登录 **[云开发平台](https://tcb.cloud.tencent.com/dev)** ,在 **[安全来源](https://tcb.cloud.tencent.com/dev#/env/safety-source)** 页面的 **安全域名** 将域名添加到列表中,否则将被识别为非法来源。 ## 使用流程 ### 第 1 步:设置自定义安全规则,放通未登录访问 您需要使用**自定义安全规则**,来放通未登录模式下的资源访问。 :::tip 注意 基于安全性的考虑,**基础的四种权限设置下,均不允许未登录进行访问**。 ::: 例如,您可以这样设置数据库的权限: ```JSON { "read": "doc._openid==auth.openid || auth == null" } ``` 在原始私有读 `doc._openid==auth.openid` 的基础上,允许了所有未登录用户进行读资源。详细可查看 [编写安全规则](/rule/rule-example)。 ### 第 2 步:初始化 SDK 发起调用 ```js import cloudbase from '@cloudbase/js-sdk'; const app = cloudbase.init({ env: 'xxxx-yyy'; }); ``` SDK 初始化完成后可以正常发起云开发资源的调用。 :::tip 注意 1. tcb-js-sdk 在 1.9.0 版本(包含)之后支持在未登录模式下调用资源,之前的版本必须在登录有效期内进行资源调用; 2. 在未登录模式下写入的数据(数据库、云存储),都将成为无主数据,即数据上不会自动包含相应的身份标识字段。 ::: ## 常见问题 - **匿名登录与未登录有什么区别?** 从 C 端用户的角度来讲: - 匿名登录和未登录在上手使用上没有任何区别,都无需注册; - 未登录场景下无法产生私有数据,数据在所有未登录用户间共享,单个用户没有特征标识; - 与匿名登录相比,未登录无法转为注册登录,未登录期间生成的数据无法自动的过渡到注册登录的用户上。 从应用开发者的角度来讲: - CloudBase 匿名登录产生的匿名用户本质上是一个有效用户,拥有唯一的用户 ID。从而可以为其创建私有的 [数据库](/database/introduce) 和 [云存储](/storage/introduce) 数据,以及配合 [安全规则](/rule/introduce) 制定个性化的访问策略; - 未登录模式是纯粹的无登录态访问,该模式下的访问都不会进入用户的追踪统计; - 未登录的用户默认权限下无法使用任何 CloudBase 的服务和资源,需要通过安全规则对需要的资源访问进行放通。同时由于无法界定未登录用户的唯一性,在开发者自身的服务体系下也无法创建私有数据和个性化策略。 - **已经开启未登录开关但访问资源仍报权限错误** 因为未登录访问是一种低安全,公开的访问方式,为保证开发者云资源的安全性,系统限制需要同时开启未登录开关,以及显式地通过安全规则放通未登录模式的资源访问,未登录模式下才可以真正访问云资源,两步相互独立,又缺一不可。 --- ## 短信验证码登录 import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; 使用短信验证码登录,您可以让用户**使用自己的手机号,结合短信验证码或密码注册、登录 CloudBase**,并且还可以**更新或者解绑登录使用的手机号**。 ## 使用限制及费用 - 新开通的按量计费环境,或者 2021 年 4 月 9 日前开通的按量计费环境,享有首月 100 条的免费额度; - 超出免费额度的需求,开发者可以前往云开发控制台 [购买资源包](https://console.cloud.tencent.com/tcb/env/resource); - 短信下发存在频率限制: - 同一号码 30 秒内最多发送 1 条; - 同一手机号一个自然日最多发送 10 条; ## 开通短信验证码登录 进入 [云开发 CloudBase 控制台](https://console.cloud.tencent.com/tcb/env/index),在 [登录授权](https://console.cloud.tencent.com/tcb/env/login) 设置页面中,开启短信验证码登录: ![](https://main.qcloudimg.com/raw/328906a723de6216a7121af5d8bba048.png) ## 登录流程 ### 第 1 步:初始化 SDK ```js import cloudbase from "@cloudbase/js-sdk"; const app = cloudbase.init({ env: "your-env-id" }); ``` ### 第 2 步:使用手机号注册账号 首先需要用户填入自己的手机号,然后调用 SDK 的发送短信验证码接口: ```js app .auth() .sendPhoneCode(phoneNumber) .then(() => { // 发送短信验证码 }); ``` 调用发送短信接口后,手机将会收到云开发的短信验证码。用户填入短信验证码,以及自定义密码后,调用注册账号接口: ```js app .auth() .signUpWithPhoneCode(phoneNumber, phoneCode, password) .then(() => { // 手机短信注册账号 }); ``` :::caution 密码强度要求 密码长度不小于 8 位,不大于 32 位,需要包含字母和数字。 ::: ### 第 3 步:使用手机号 + 密码 or 手机号 + 短信验证码登录 CloudBase ```js app .auth() .signInWithPhoneCodeOrPassword({ phoneNumber, phoneCode, // 非必填,验证码和密码至少二选一 password // 非必填,验证码和密码至少二选一 }) .then((loginState) => { // 登录成功 }); ``` --- ## 用户名密码登录 import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; 使用用户名密码登录,您可以让您的用户**绑定用户名,并使用用户名密码登录 CloudBase**。您可以**更改用户名和密码**,还可以**查询用户名是否绑定过**。 如果**用户名未被绑定过**,需要先使用其他登录方式完成登录后,才可以绑定用户名。绑定成功后,可以使用用户名和密码完成登录。 ## 开通用户名密码登录 进入 [云开发 CloudBase 控制台](https://console.cloud.tencent.com/tcb/env/index),在 [登录授权](https://console.cloud.tencent.com/tcb/env/login) 设置页面中,开启用户名密码登录: ![](https://main.qcloudimg.com/raw/4eda5f00d4e6a2cfb355d47a78c549f0/%E7%94%A8%E6%88%B7%E5%90%8D%E5%AF%86%E7%A0%81%E7%99%BB%E5%BD%95-2.png) ## 绑定用户名流程 ### 第 1 步:初始化 SDK ```js import cloudbase from "@cloudbase/js-sdk"; const app = cloudbase.init({ env: "your-env-id" }); ``` ### 第 2 步:使用其他方式进行登录 绑定用户名之前,用户需要先使用其他方式进行登录,例如邮箱登录、微信公众号登录等,但**不包括匿名登录**。 下面以[邮箱登录](/authentication/method/email-login)为例: ```js const auth = app.auth(); await auth.signInWithEmailAndPassword(email, password); // 邮箱登录 ``` :::tip 为什么必须先登录,再绑定用户名? 用户名可以是符合规则的任意字符串,为了避免您的应用被恶意者注册过多无效的用户名,CloudBase 目前不允许直接使用用户名 + 密码的形式注册用户。 ::: ### 第 3 步:绑定用户名 绑定用户名时,可以检查在当前云开发环境下,此用户名是否存在。然后再调用绑定用户名的接口: ```js const auth = app.auth(); if (!(await auth.isUsernameRegistered(username))) { // 检查用户名是否绑定过 await auth.currentUser.updateUsername(username); // 绑定用户名 } ``` :::caution 用户名规则 1. 可以包含数字和字母,但是不允许是纯数字 2. 符号只允许出现 `-` 和 `_`,不允许这两个符号出现在开头和结尾 3. 长度范围是 `[1, 32]` ::: ## 登录流程 ### 第 1 步:初始化 SDK ```js import cloudbase from "@cloudbase/js-sdk"; const app = cloudbase.init({ env: "your-env-id" }); ``` ### 第 2 步:使用用户名+密码登录 CloudBase ```js const auth = app.auth(); const loginState = await auth.signInWithUsernameAndPassword(username, password); // 用户名密码登录 ``` :::caution 注意 用户名登录和邮箱登录的密码是相同的。 ::: --- ## 微信授权登录 import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; 经微信授权的网页应用可以直接使用微信登录 CloudBase,包括两种授权类型: - 微信公众平台(公众号网页); - 微信开放平台(普通网站应用及移动应用等)。 ## 开通流程 ### 1. 开通平台账号 首先需要一个微信公众平台 / 开放平台的注册账号,如果没有,请前往 [微信公众平台](https://mp.weixin.qq.com/) 或 [微信开放平台](https://open.weixin.qq.com/)申请。 然后在微信公众平台/开放平台的管理后台中,查看**开发者 ID(AppId)**和**开发者密码(AppSecret)**。 以微信公众平台为例,在“开发 - 基本配置”中有以下内容: ![微信公众平台](https://main.qcloudimg.com/raw/cb40490394d61c8c95b74355e352d0f0.png) :::tip 注意 开发者密码(AppSecret)是非常私密的信息,每次点击上图中的「重置」按钮都会获取一个新的 AppSecret。 ::: ### 2. 开启微信登录 在 [控制台](https://console.cloud.tencent.com/tcb/env/login) 的 [登录授权管理页](https://console.cloud.tencent.com/tcb/env/login) 启动对应的平台登录授权: ![微信授权登录开启](https://main.qcloudimg.com/raw/f01ebbccbf987dec6b579906155fbf8d.jpg) 点击启用按钮后在弹窗的对应位置填入 AppId 和 AppSecret。 ### 3. 添加安全域名(可选) 对于 Web 应用,需要将域名添加到 [安全配置](https://console.cloud.tencent.com/tcb/env/safety) 的 Web 安全域名列表中,否则将被识别为非法来源: ## 微信登录流程 在使用微信登录 CloudBase 前,请先在控制台中 [启用微信登录](#开通流程)。 ### 第 1 步:初始化 SDK ```js import cloudbase from "@cloudbase/js-sdk"; const app = cloudbase.init({ env: "your-env-id" }); ``` ### 第 2 步:使用 SDK 处理登录流程 #### 1. 创建 Provider 首先我们创建一个 Provider 实例,并且填入参数: ```js const auth = app.auth(); const provider = auth.weixinAuthProvider({ appid: "...", scope: "xxxx" }); ``` 参数说明如下: | 参数名称 | 类型 | 必填 | 说明 | | -------- | -------- | ---- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `appid` | `string` | 是 | 微信公众平台/开放平台的 AppId。 | | `scope` | `string` | 是 | 网页授权类型,可选值包括:`snsapi_base`:微信公众平台,只获取用户的微信 OpenId`snsapi_userinfo`:微信公众平台,获取用户的基本信息 `snsapi_login`:开放平台网页授权,获取用户的基本信息 | :::tip 提示 如果用户使用 `snsapi_userinfo` 或 `snsapi_login` 登录,并且是**首次登录**,那么 CloudBase 将会自动拉取、同步微信的用户基本信息。 如果用户**不是首次登录,将不会有此行为**。 ::: #### 2. 使用 Provider 进行登录 首先调用 [`Provider.signInWithRedirect()`](/api-reference/webv2/authentication#weixinauthprovider-signinwithredirect),用户将会跳转到微信 OAuth 授权页面: ```js provider.signInWithRedirect(); ``` 在授权页面内,需要用户对登录行为进行授权,成功后,会返回至当前页面。 然后调用 [`Provider.getRedirectResult()`](/api-reference/webv2/authentication#weixinauthprovider-getredirectresult),获取登录结果: ```js provider.getRedirectResult().then((loginState) => { if (loginState) { // 登录成功! } }); ``` 关于如何给用户更好的登录体验,请参阅 [最佳实践](/authentication/auth/best-practice)。 --- ## 账户关联 # 账户关联 每个云开发用户账号,除了最初注册时使用的登录方式外,还可以关联其他登录方式。关联后,无论用户使用哪种登录方式,均可以登录到同一个云开发账户。 ## 关联微信登录 关联微信登录的步骤如下: 1. 用户**以任意一种登录方式(除微信登录)登录云开发** 2. 参考 [微信授权登录](/authentication-v2/method/wechat-login#第-2-步使用-sdk-处理登录流程) 获取微信授权 `provider_token` 3. 使用授权 token 关联微信登录 ```js const app = cloudbase.init({ env: "xxxx-yyy" }); const provider_token = "test_provider_token"; // 上一步取得的授权 token const auth = app.auth(); await auth.bindWithProvider({ provider_token }); ``` ## 关联邮箱密码登录 假设当前用户支持密码登录,则下面的方式可以为当前用户绑定邮箱,绑定后,用户则可以使用邮箱+密码完成登录: 1. 用户**以任意一种登录方式登录云开发** 2. 获取 `sudo_token`,这里以密码的方式获取 `sudo_token`,还可以使用邮箱验证码、手机号验证码等方式,具体请参考 Auth.sudo 接口。 ```js const auth = app.auth(); // 假设用户输入的密码为 passwd const password = "passwd"; // 获取 sudo_token, sudo_token 的过期时间默认为10分钟。 const sudo_token = await auth.sudo({ password: password }); ``` 3. 给邮箱发送验证码 ```js // 假设用户邮箱为 "test@example.com" const email = "test@example.com"; // 获取邮箱验证码 const verification = await auth.getVerification({ email: email }); ``` 4. 校验用户输入的验证码 ```js // 假设用户输入的验证码为 000000 const verificationCode = "000000"; // 校验验证码 const verificationTokenRes = await auth.verify({ verification_id: verification.verification_id, verification_code: verificationCode }); const verification_token = verificationTokenRes.verification_token ``` 5. 使用 verification_token 和 sudo_token 绑定邮箱 ```js await auth.bindEmail({ sudo_token: sudo_token, email: email, verification_token: verification_token }); ``` ## 关联手机号密码登录 假设当前用户支持密码登录,则下面的方式可以为当前用户绑定手机号,绑定后,用户则可以使用手机号+密码完成登录: 1. 用户**以任意一种登录方式登录云开发** 2. 获取 sudo_token,这里以密码的方式获取 sudo token,还可以使用邮箱验证码、手机号验证码等方式,具体请参考 Auth.sudo 接口。 ```js const auth = app.auth(); // 假设用户输入的密码为 passwd const password = "passwd"; // 获取 sudo_token, sudo_token 的过期时间默认为10分钟。 const sudo_token = await auth.sudo({ password: password }); ``` 3. 向用户手机发送验证短信 ```js const auth = app.auth(); // 假设用户手机号为 13800000000 const phoneNumber = "+86 13800000000"; // 获取验证码 const verification = await auth.getVerification({ phone_number: phoneNumber }); ``` 4. 校验用户输入的验证码 ```js // 假设用户输入的验证码为 000000 const verificationCode = "000000"; // 校验验证码 const verificationTokenRes = await auth.verify({ verification_id: verification.verification_id, verification_code: verificationCode }); const verification_token = verificationTokenRes.verification_token ``` 5. 使用 verification_token 和 sudo_token 绑定手机号 ```js await auth.bindPhoneNumber({ sudo_token: sudo_token, phone_number: phoneNumber, verification_token: verification_token }); ``` { const { users, // UnionID 对应的云开发账号 hasPrimaryUid // 其中是否含有主账号 } = list }) ``` 获取到列表后,您可以询问用户,或者自动为用户选择其中一个账号作为主账号 ### 设置主账号 您可以通过 `User.setPrimaryUid()` 设置 UnionId 对应的主账号: ```js auth.currentUser.setPrimaryUid(uid).then(() => { // 设置主账号成功 }) ``` 设置为主账号之后,使用 UnionID 登录都会登录到此主账号之上。 --> --- ## 最佳实践 import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # 最佳实践 ## 避免重复登录 执行登录流程之前,我们非常建议您**先判断用户端是否已经登录 CloudBase**,如已经登录,那么不需要执行登录流程,以**避免无意义的重复登录**。 ```js const auth = app.auth(); // 应用初始化时 if (auth.hasLoginState()) { // 此时已经登录 } else { // 此时未登录或登录态失效,执行您的登录流程 } ``` ## 登录状态的持久保留 `@cloudbase/js-sdk@2.x` 版本移除了对登录状态为 `session` 和 `none` 的支持,登录状态只能为 `local` ,即在本地存储中长期地保留登录状态。这意味着即使用户关闭浏览器,会话信息也依然会被保留。这使得用户不需要在每次访问网页应用时重复登录,从而可以避免诸多不便体验。 具体差异请参考[V1 Auth对象](/api-reference/webv2/authentication#appauth) --- ## 概述 # 概述 **云开发** 登录认证为您的应用提供完整的 **用户身份管理** 和 **访问控制解决方案**。通过内置的多种登录方式和安全机制,帮助您快速构建可靠的用户体系。 **云开发** 登录认证是 **保护您服务资源** 的重要防护机制,对用户端发起的每个请求都会进行身份验证和权限检查,有效防止资源被恶意访问或盗用。 ## 核心功能 * **🔐 身份标识管理**:为每个用户分配全局唯一的身份标识 UID * **👤 用户信息管理**:存储和管理用户个人信息 * **🔑 多种登录方式**:支持微信、邮箱、短信等多种登录方式 * **🛡️ 权限控制**:管理用户对数据和资源的访问权限 * **📊 用户行为分析**:收集和分析用户行为数据 ## 支持的登录方式 **云开发** 提供多种登录方式,您可以根据业务场景选择合适的方案: | 登录方式 | 适用场景 | 特点 | | --- | --- | --- | | [匿名登录](/authentication-v2/method/anonymous) | 快速体验、临时用户 | 无需注册,临时身份 | | [用户名密码登录](/authentication-v2/method/username-login) | 传统应用 | 用户名 + 密码 | | [短信验证码登录](/authentication-v2/method/sms-login) | 移动端应用 | 手机号 + 验证码 | | [邮箱登录](/authentication-v2/method/email-login) | 企业应用、正式用户 | 邮箱 + 密码,传统方式 | | [微信授权登录](/authentication-v2/method/wechat-login) | 微信生态应用 | 微信公众号、开放平台 | | [自定义登录](/authentication-v2/method/custom-login) | 已有用户体系 | 与现有账号体系集成 | | [微信小程序登录](https://developers.weixin.qq.com/miniprogram/dev/wxcloud/guide/init.html) | 微信小程序 | 自动完成登录认证 | ## 用户账号体系 ### 可视化管理 在 [云开发/云后台](https://tcb.cloud.tencent.com/dev?#/cloud-admin) 中可以看到「**用户管理**」模块,进入后可以查看和管理用户信息、角色、权限等 每个登录 **云开发** 的用户都拥有一个独立的 **云开发** 账号,作为访问数据和资源的身份凭证 ![](https://qcloudimg.tencent-cloud.cn/raw/9f56d3a181ef2ec68f5d97fea7b57e8d.png) ### 用户标识符 (UID) * **全局唯一**:每个账号都有全局唯一的 UID,作为用户的唯一身份标识 * **持久稳定**:UID 在用户整个生命周期内保持不变 * **跨平台统一**:同一用户在不同平台上的 UID 保持一致 ### 用户信息管理 每个账号可以存储和管理丰富的用户信息,包括: * 基本信息(昵称、头像、邮箱等) * 自定义字段 * 登录记录和行为数据 详细操作请参考 [管理用户](/authentication-v2/auth/manage-users) ### 多账号关联 支持将多种登录方式关联到同一个账号,实现: * **统一身份**:用户可以使用不同方式登录同一账号 * **无缝切换**:在不同设备或场景下灵活切换登录方式 * **数据一致性**:确保用户数据在不同登录方式下保持一致 详细操作请参考 [账户关联](/authentication-v2/auth/account-linking)。 ## 登录状态管理 ### 状态持久化 * **Web 端**:在显式退出登录之前,身份验证状态保留 30 天 * **移动端**:根据平台特性自动管理状态持久化 ### 令牌机制 CloudBase 使用双令牌机制保障访问安全: #### 访问令牌 (Access Token) * **用途**:作为访问 CloudBase 服务的身份凭证 * **有效期**:默认 2 小时 * **自动管理**:SDK 自动维护令牌的使用和刷新 #### 刷新令牌 (Refresh Token) * **用途**:用于获取新的访问令牌 * **有效期**:默认 30 天 * **自动续期**:访问令牌过期时自动使用刷新令牌获取新的访问令牌 :::tip 特殊说明 [匿名登录](/authentication-v2/method/anonymous) 的刷新令牌会在到期后自动续期,以实现长期的匿名登录状态。 ::: ## 立即开始 请参考 [快速开始](/authentication-v2/auth/quick-start) --- ## 管理登录方式 import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import CodeBlock from '@theme/CodeBlock'; # 管理登录方式 云开发提供多种身份认证方式,您可以根据业务需求灵活配置 ## 云开发平台手动开启 1. 在[云开发平台](https://tcb.cloud.tencent.com/),选择需要管理的环境 2. 进入 "身份认证" > "登录方式" 页面 3. 在登录方式列表中,选择所需的登录方式,点击开启/关闭按钮进行配置 ![](https://qcloudimg.tencent-cloud.cn/raw/874aaf9030bd9cd500a7fbbf2547b324.png) ## SDK方式开启 支持通过腾讯云SDK([tencentcloud-sdk](https://cloud.tencent.com/document/sdk))进行登录方式开启、关闭的管理,支持java、go、js等多种语言 :::tip 腾讯云SDK([tencentcloud-sdk](https://cloud.tencent.com/document/sdk))方式开启/关闭登录方式,只会开启云开发平台登录认证v2的登录方式,不会同步开启/关闭旧的云开发控制台v1登录方式。 开启/关闭v1登录方式,请前往云开发控制台手动操作 ::: 支持的登录方式及参数: | 登录方式 | 参数 | 参数值 | | ----------- | ----------- | ----------- | | 手机号验证码登录 | PhoneNumberLogin | TRUE、FALSE,TRUE代表开启,FALSE代表关闭 | | 匿名登录 | AnonymousLogin | TRUE、FALSE,TRUE代表开启,FALSE代表关闭 | | 用户名密码登录 | UsernameLogin | TRUE、FALSE,TRUE代表开启,FALSE代表关闭 | ```json { "EnvId": "your-env-id", "PhoneNumberLogin": "TRUE", "AnonymousLogin": "TRUE", "UsernameLogin": "TRUE", } ``` 示例代码如下,了解更多使用方式前往[腾讯云云API](https://console.cloud.tencent.com/api/explorer?Product=tcb&Version=2018-06-08&Action=EditAuthConfig): {`package main import ( "fmt" "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common" "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/errors" "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile" tcb "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tcb/v20180608" ) func main() { // 实例化一个认证对象,入参需要传入腾讯云账户 SecretId 和 SecretKey,此处还需注意密钥对的保密 // 代码泄露可能会导致 SecretId 和 SecretKey 泄露,并威胁账号下所有资源的安全性。以下代码示例仅供参考,建议采用更安全的方式来使用密钥,请参见:https://cloud.tencent.com/document/product/1278/85305 // 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取 credential := common.NewCredential( "", "", ) // 实例化一个client选项,可选的,没有特殊需求可以跳过 cpf := profile.NewClientProfile() cpf.HttpProfile.Endpoint = "tcb.tencentcloudapi.com" // 实例化要请求产品的client对象,clientProfile是可选的 client, _ := tcb.NewClient(credential, "", cpf) // 实例化一个请求对象,每个接口都会对应一个request对象 request := tcb.NewEditAuthConfigRequest() // 返回的resp是一个EditAuthConfigResponse的实例,与请求对象对应 response, err := client.EditAuthConfig(request) if _, ok := err.(*errors.TencentCloudSDKError); ok { fmt.Printf("An API error has returned: %s", err) return } if err != nil { panic(err) } // 输出json格式的字符串回包 fmt.Printf("%s", response.ToJsonString()) } `} {`const tencentcloud = require("tencentcloud-sdk-nodejs-tcb"); const TcbClient = tencentcloud.tcb.v20180608.Client; // 实例化一个认证对象,入参需要传入腾讯云账户 SecretId 和 SecretKey,此处还需注意密钥对的保密 // 代码泄露可能会导致 SecretId 和 SecretKey 泄露,并威胁账号下所有资源的安全性。以下代码示例仅供参考,建议采用更安全的方式来使用密钥,请参见:https://cloud.tencent.com/document/product/1278/85305 // 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取 const clientConfig = { credential: { secretId: "", secretKey: "", }, region: "", profile: { httpProfile: { endpoint: "tcb.tencentcloudapi.com", }, }, }; // 实例化要请求产品的client对象,clientProfile是可选的 const client = new TcbClient(clientConfig); const params = {}; client.EditAuthConfig(params).then( (data) => { console.log(data); }, (err) => { console.error("error", err); } ); `} {`package com.tencent; import com.tencentcloudapi.common.AbstractModel; import com.tencentcloudapi.common.Credential; import com.tencentcloudapi.common.profile.ClientProfile; import com.tencentcloudapi.common.profile.HttpProfile; import com.tencentcloudapi.common.exception.TencentCloudSDKException; import com.tencentcloudapi.tcb.v20180608.TcbClient; import com.tencentcloudapi.tcb.v20180608.models.*; public class Sample { public static void main(String [] args) { try{ // 实例化一个认证对象,入参需要传入腾讯云账户 SecretId 和 SecretKey,此处还需注意密钥对的保密 // 代码泄露可能会导致 SecretId 和 SecretKey 泄露,并威胁账号下所有资源的安全性。以下代码示例仅供参考,建议采用更安全的方式来使用密钥,请参见:https://cloud.tencent.com/document/product/1278/85305 // 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取 Credential cred = new Credential("", ""); // 实例化一个http选项,可选的,没有特殊需求可以跳过 HttpProfile httpProfile = new HttpProfile(); httpProfile.setEndpoint("tcb.tencentcloudapi.com"); // 实例化一个client选项,可选的,没有特殊需求可以跳过 ClientProfile clientProfile = new ClientProfile(); clientProfile.setHttpProfile(httpProfile); // 实例化要请求产品的client对象,clientProfile是可选的 TcbClient client = new TcbClient(cred, "", clientProfile); // 实例化一个请求对象,每个接口都会对应一个request对象 EditAuthConfigRequest req = new EditAuthConfigRequest(); // 返回的resp是一个EditAuthConfigResponse的实例,与请求对象对应 EditAuthConfigResponse resp = client.EditAuthConfig(req); // 输出json格式的字符串回包 System.out.println(AbstractModel.toJsonString(resp)); } catch (TencentCloudSDKException e) { System.out.println(e.toString()); } } } `} --- ## 管理用户 # 管理用户 ## 创建用户 开发者可以调用以下登录方式,登录或者创建一个用户: * [微信授权登录](/authentication-v2/method/wechat-login) * [用户名密码登录](/authentication-v2/method/username-login) * [短信验证码登录](/authentication-v2/method/sms-login) * [邮箱登录](/authentication-v2/method/email-login) * [自定义登录](/authentication-v2/method/custom-login) ## 用户类型 用户分为内部用户、外部注册用户、匿名用户: | 用户类型 | 角色 | 用户数限制 | 用户信息 | | --- | --- | --- | --- | | 内部用户 | 固定的「默认内部用户角色」,可分配自定义角色 | 受套餐限制,参考 [计费文档](https://cloud.tencent.com/document/product/876/75213) | 系统保存 | | 外部注册用户 | 固定的「默认外部用户」角色 | 不限用户数 | 系统保存 | | 匿名用户 | 固定的「默认访客」角色 | 不限用户数 | 系统不保存 | ## 获取当前登录的用户 **auth** 实例请参考 [SDK 初始化](/authentication-v2/method/sdk-init) 您可以使用 `auth.currentUser` 属性或者 `auth.getCurrentUser()` 方法来获取当前登录的用户,该方法会返回当前登录用户的[ `User` ](/api-reference/webv3/authentication#user)实例。如果用户未登录,则返回 `null` : ```js const app = cloudbase.init({ env: "xxxx-yyy" }) const auth = app.auth() // 进行登录后... // 获取用户信息 const user = auth.currentUser // 或者 // const user = await auth.getCurrentUser() ``` ## 获取用户个人资料 您可以通过 `User` 对象的各个属性来获取用户的个人资料信息: ```js const user = auth.currentUser let uid, name, gender, created_from if (user) { // 云开发唯一用户 id uid = user.uid // 昵称 name = user.name // 性别 gender = user.gender // 创建来源 created_from = user.created_from; } ``` ## 更新用户个人资料 您可以使用 `User.update` 方法来更新用户的个人资料信息。例如: ```js const user = auth.currentUser user .update({ name: "Tony Stark", gender: "MALE" }) .then(() => { // 更新用户资料成功 }); ``` ## 刷新用户资料信息 对于一个多端应用,用户可能在其中某个端上更新过自己的个人资料信息,此时其它端上可能需要刷新信息: ```js const user = auth.currentUser; // 刷新用户信息 user.refresh().then(() => { // 刷新后,获取到的用户信息即为最新的信息 const { username, gender } = user; }); ``` --- ## 快速开始 # 快速开始 CloudBase 登录认证为您的应用提供完整的 **用户身份管理** 和 **访问控制解决方案**。通过内置的多种登录方式和安全机制,帮助您快速构建可靠的用户体系。 :::caution 版本说明 * **登录认证(v2)** 适用于 `@cloudbase/js-sdk@2.x` 版本 * 如您使用的 SDK 版本为 1.x,请参考 **[登录认证(v1)](/authentication/auth/introduce)** * **v2 版本暂不支持公众号登录方式**,如需使用该方式,请用 [v1 版本](/authentication/method/wechat-login) ::: 本文将以 **V2** 版本进行介绍 ## 1. 安装并初始化 ### 安装 SDK 在您的项目中引入 `@cloudBase/js-sdk@2.x` ```bash npm install --save @cloudbase/js-sdk ``` ### 初始化 SDK ```js import cloudbase from "@cloudbase/js-sdk"; const app = cloudbase.init({ env: "your-env-id" }); // 获取 auth 实例 const auth = app.auth(); ``` ## 2. 用户注册 目前支持 **手机号验证码、邮箱验证码** 注册 两种注册方式开发只在 **发送验证码** 时有所区别,后续校验步骤均一致 ### 打开登录方式 前往 [云开发/身份认证](https://tcb.cloud.tencent.com/dev?#/identity/login-manage) 打开 **短信验证码登录** 或 **邮箱验证码登录**,如下图所示: ![](https://qcloudimg.tencent-cloud.cn/raw/874aaf9030bd9cd500a7fbbf2547b324.png) ### 发送验证码 **1. 发送手机号验证码** ```js // 1. 发送验证码 // 需要加区号 const phoneNumber = "+86 13800000000"; const verification = await auth.getVerification({ phone_number: phoneNumber, }); ``` **2. 发送邮箱验证码** ```js // 1. 发送邮箱验证码 const email = "test@example.com"; const verification = await auth.getVerification({ email: email, }); ``` ### 验证并注册 发送验证码,并获取到验证码后续步骤 ```js // 2. 验证码验证 // 假设这里收到用户填写的验证码"000000" const verificationCode = "000000"; // 验证验证码的正确性 const verificationTokenRes = await auth.verify({ verification_id: verification.verification_id, verification_code: verificationCode, }); // 3. 注册 // 如果该用户已经存,则登录 if (verification.is_user) { await auth.signIn({ username: phoneNumber, verification_token: verificationTokenRes.verification_token, }); } else { // 否则,则注册新用户,注册新用户时,可以设置密码,用户名 // 备注:signUp 成功后,会自动登录 await auth.signUp({ phone_number: phoneNumber, verification_code: verificationCode, verification_token: verificationTokenRes.verification_token, // 可选,设置昵称 name: "手机用户", // 可选,设置密码 password: "password", // 可选,设置登录用户名 username: "username", }); } ``` 注册成功,即可在 [云开发/云后台/用户管理](https://tcb.cloud.tencent.com/dev?#/cloud-admin)「**外部注册用户**」中看到 ![](https://qcloudimg.tencent-cloud.cn/raw/dc09f2658a3932a90ff5186fcca62c22.png) ## 3. 账号登录 目前支持 **手机号,邮箱,自定义用户名** 作为账号进行登录 密码需要手动设置,如果没有设置可以使用验证码登录 在您的项目中需要登录的位置获取到账号密码后,执行如下代码: ```js const loginState = await auth.signIn({ username: "your username", password: "your password" }); ``` ## 4. 登录完成 登录后,即可操作数据库、云函数、操作文件存储 ## 下一步 恭喜!您已经掌握了登录认证的基本使用方法。 具体登录方式请参考: * [匿名登录](/authentication-v2/method/anonymous) * [微信授权登录](/authentication-v2/method/wechat-login) * [用户名密码登录](/authentication-v2/method/username-login) * [短信验证码登录](/authentication-v2/method/sms-login) * [邮箱登录](/authentication-v2/method/email-login) * [自定义登录](/authentication-v2/method/custom-login) --- ## access_token 的异同点 # access_token 的异同点 | | v2 | v1 | | ---- | --- | --- | | 格式 | 标准 jwt | 非标准 jwt | | 加密方式 | 非对称加密 | 对称加密 | | 加密协议 | ES256 | HS256 | | 加密 key | 公私钥定时轮换 | 每个环境独立密钥 | | 公钥 | [查看公钥](https://apis.ap-shanghai.tcb-api.tencentcloudapi.com/auth/v1/certs) | 无 | | 分布式验证 | 支持 | 不支持 | | 开放性 | 开放 | 无 | ## v2 access_token 示例 ``` eyJhbGciOiJSUzI1NiIsImtpZCI6IjlkMWRjMzFlLWI0ZDAtNDQ4Yi1hNzZmLWIwY2M2M2Q4MTQ5OCJ9.eyJpc3MiOiJodHRwczovL21pbmctMGdyZXhicGZkYWQxNzViYS5hcC1zaGFuZ2hhaS50Y2ItYXBpLnRlbmNlbnRjbG91ZGFwaS5jb20iLCJzdWIiOiJWWTA3LVBaWlI0VldZbFlLTy04MFBnIiwiYXVkIjoibWluZy0wZ3JleGJwZmRhZDE3NWJhIiwiZXhwIjoxNzMwMTkyNTc2LCJpYXQiOjE3MzAxODUzNzYsIm5vbmNlIjoiNjY3YzU5NGMtYmJlNy00MzIzLWI3MjgtYTg5ZGU5MjhhMzM5IiwiYXRfaGFzaCI6IjZBZ205RWVOUXl5VjBMbXZ6bmRhOFEiLCJuYW1lIjoiQW5vbnltb3VzIiwic2NvcGUiOiJhbm9ueW1vdXMiLCJwcm9qZWN0X2lkIjoibWluZy0wZ3JleGJwZmRhZDE3NWJhIiwibWV0YSI6eyJ3eE9wZW5JZCI6IiIsInd4VW5pb25JZCI6IiJ9LCJ1c2VyX2lkIjoiVlkwNy1QWlpSNFZXWWxZS08tODBQZyIsInVzZXJfdHlwZSI6IiJ9.j_9x0qvfZv03DT87O-QWT3TWqrGmI87TS1GTakfCqAeMCGGBZEX6WKgz5jsLcCj4xsEdGiVh-OIA1Ssb_0qci4U-2b7Il7cp3SHQAjyan3gHBBjDuPpW7WTsTH1MslHXbkC_YTePjvf9A4U2PqU65HvlrvhOEE3gwK5VUJQ8oGs-HLKHKRIlkEoBGfJwjzA7G13QMX_52obHw73vqdvxQve20mYG7CzLoyoJjSH2FO56DY6iYXPjcy21tHgMyX7DWZGhRdk0KmmXmTUOpEP4ijvm9bGS06F0S4T_b3ed-HgsWXtoSTQ_BgeVFMUufbHdspOHuPaNj5wvjfMszIVKeQ ``` ![alt text](image-1.png) ### 如何分布式验证 v2 的 access_token - 选择适合你的 [jwt 标准库](https://jwt.io/libraries) - 获取 tcb 系统的公钥,地址为: https://{{EnvID}}.ap-shanghai.tcb-api.tencentcloudapi.com/auth/v1/certs,替换 URL 中的 {{EnvID}} 为你真是的环境ID - 使用公钥验证 access_token - 只要签名是正确的,那么 access_token 就是正确的 ## v1 access_token 示例 ``` eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkYXRhIjoie1wibG9naW5UeXBlXCI6XCJBTk9OWU1PVVNcIixcImVudk5hbWVcIjpcIm1pbmctMGdyZXhicGZkYWQxNzViYVwiLFwidXVpZFwiOlwiYTc1ZmFkODk0MmMwNDVkOGE0ZmZiMmYyYmNlZTkzYzJcIn0iLCJpYXQiOjE3MzAxODUwMDksImV4cCI6MTczMDE4ODYwOX0.Mc5fD7RaADrnh_j2Xe5sRNqFsuhaNOhf570tze4rnDI;1730185009 ``` ![alt text](image.png) --- ## 匿名登录 import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # 匿名登录 CloudBase 匿名登录的所有逻辑均可由客户端代码主动执行,无需用户手动操作。在匿名登录状态下可正常的调用 CloudBase 的资源,开发者同时可以配合安全规则针对匿名用户制定对应的访问限制。 :::caution 版本说明 * **登录认证(v2)** 适用于 `@cloudbase/js-sdk@2.x` 版本 * 如您使用的 SDK 版本为 1.x,请参考 **[登录认证(v1)](/authentication/auth/introduce)** * **v2 版本暂不支持公众号登录方式**,如需使用该方式,请用 [v1 版本](/authentication/method/wechat-login) ::: 本文将以 **V2** 版本进行介绍 ## 前置动作 ### 开启匿名登录 1. 前往 [云开发/身份认证](https://tcb.cloud.tencent.com/dev?#/identity/login-manage) 2. 在登录方式列表中,选择 **匿名登录** 方式,点击开启 ## 登录流程 **auth** 实例请参考 [SDK 初始化](./sdk-init) [Auth.signInAnonymously](/api-reference/webv3/authentication#authsigninanonymously) 用于匿名登录 ```js await auth.signInAnonymously(); const loginScope = await auth.loginScope(); // 如为匿名登录,则输出 true console.log(loginScope === "anonymous"); ``` ## 权限控制 匿名用户在安全规则中的 `auth.loginType` 值为 `ANONYMOUS` ,配合安全规则可以限制匿名用户的 [数据库](/database/introduce) 和 [云存储](/storage/introduce.md) 的访问权限。比如下述代码展示的安全规则为: * 数据库匿名用户不可读写; * 云存储所有用户可读,匿名用户不可写。 ```json { "read": "auth.loginType != 'ANONYMOUS'", "write": "auth.loginType != 'ANONYMOUS'" } ``` ```json { "read": "auth != null", "write": "auth.loginType != 'ANONYMOUS'" } ``` :::tip 详细请查看 [安全规则-用户身份认证](/rule/rule-example#用户身份认证)。 ::: ## 转化为正式用户 如果用户在匿名状态下产生了一些私有数据(例如游戏中获取了个人成就和装备),想将此匿名账号转化为正式账号长久持有。 针对这种需求,您可以进行[匿名用户转正注册](/api-reference/webv3/authentication#authsigninanonymously),即可将此匿名账号的私有数据转移到正式账号中。 转正示例参考: 1. 匿名登录 ```js const auth = app.auth(); await auth.signInAnonymously(); ``` 2. 进行某种方式的登录 3. 获取 access_token 并进行转正注册 ```js const { accessToken } = await auth.getAccessToken(); await auth.signUp({ // 其他参数参考 auth.signUp anonymous_token: access_token, }); ``` :::tip 另外可参考:**[账户关联](/authentication-v2/auth/account-linking)**。 ::: ## 常见问题 * **匿名登录与未登录有什么区别?** 从 C 端用户的角度来讲: + 匿名登录和未登录在上手使用上没有任何区别,都无需注册; + 匿名登录用户有独立的用户标识,在同设备有效期内,用户可以产生独立的私有数据; + 与未登录相比,匿名登录可以转为正式用户,匿名登录期间的私有数据会自动继承到正式用户名下。 从应用开发者的角度来讲: + CloudBase 匿名登录产生的匿名用户本质上是一个有效用户,拥有唯一的用户 ID。从而可以为其创建私有的 [数据库](/database/introduce) 和 [云存储](/storage/introduce.md) 数据,以及配合 [安全规则](/rule/introduce.md) 制定个性化的访问策略; + 未登录模式是纯粹的无登录态访问,该模式下的访问都不会进入用户的追踪统计; + 未登录的用户默认权限下无法使用任何 CloudBase 的服务和资源,而匿名登录在基础权限下也可以进行对应的资源读写,也可以结合安全规则实现更细粒度的管控。 * **匿名用户是否会过期?** CloudBase 对匿名用户的有效期限策略是:每个设备同时只存在一个匿名用户,并且此用户永不过期。当然,如果用户手动清除了设备或浏览器的本地数据,那么匿名用户的数据便会被同步清除,再次调用 CloudBase 匿名登录 API 会产生一个新的匿名用户。 --- ## 验证码处理指南 # 验证码处理指南 本文档介绍如何在腾讯云开发身份验证中处理验证码相关逻辑,包括触发条件、错误处理和完整的实现流程。 ## 触发条件 验证码会在以下情况下被要求输入: - 用户名密码登录失败 5 次后 - 发送手机号或邮箱验证码时达到频率限制 ## 错误信息 当需要验证码时,接口会返回相应的错误信息: - `error == captcha_required`:表示请求触发了验证码相关逻辑,需要进行机器验证 - `error == captcha_invalid`:表示验证码无效,需要重新获取验证码 :::tip 注意 验证码流程完成后,若业务接口返回 `error` 等于 `captcha_required`,表示请求需要 `captcha_token` 参数,应尽可能使用本地未过期的验证码。当 `error` 等于 `captcha_invalid` 时,表示验证码无效,需要重新获取验证码。在同一个验证流程内,`captcha_invalid` 最多尝试一次即可。 ::: ```typescript // 错误信息示例: { data: { error: "captcha_required", error_code: 4001, error_description: "captcha_token required" } } ``` ## 处理流程 ### 完整流程 验证码处理的完整流程如下: 1. 用户尝试登录或发送验证码 2. 若触发验证码要求,SDK 抛出 `captcha_required` 错误 3. 编写SDK适配器,捕获错误并触发 `openURIWithCallback` 4. `openURIWithCallback` 方法中获取验证码参数,并通过 `EVENT_BUS` 发送给前端展示 5. 前端展示验证码图片并等待用户输入 6. 用户输入验证码并提交 7. 系统验证并返回结果 8. 根据验证结果决定是否重试原操作 关于第三步的 SDK适配器以及 `openURIWithCallback` 方法请参考 [适配器指引](/api-reference/webv3/adapter/) ### 适配器实现 ```typescript function genAdapter(options) { const adapter: SDKAdapterInterface = { captchaOptions: { openURIWithCallback: async (url: string) => { // 解析 URL 中的验证码参数 const { captchaData, state, token } = cloudbase.parseCaptcha(url); // 通过事件总线发送验证码数据,进行前端缓存及展示 options.EVENT_BUS.emit("CAPTCHA_DATA_CHANGE", { captchaData, // Base64 编码的验证码图片 state, // 验证码状态标识 token, // 验证码 token }); // 监听验证码校验结果 return new Promise((resolve) => { console.log("等待验证码校验结果..."); options.EVENT_BUS.once("RESOLVE_CAPTCHA_DATA", (res) => { // auth.verifyCaptchaData 的校验结果 resolve(res); }); }); }, }, }; return adapter; } ``` ### 初始化SDK ```typescript import cloudbase from '@cloudbase/js-sdk' // 创建事件总线实例,具体EventBus实现可参考网上示例 const EVENT_BUS = new EventBus(); // 配置并使用适配器,将 EVENT_BUS 注入给 genAdapter cloudbase.useAdapters(adapter, { EVENT_BUS }); const app = cloudbase.init({ env: '环境ID', appSign: '应用标识', appSecret: { appAccessKeyId: '应用凭证版本号', appAccessKey: '应用凭证' } }); const auth = app.auth(); ``` ### 验证码界面实现 ```typescript // 存储当前验证码状态 let captchaState = { captchaData: "", // Base64 编码的验证码图片 state: "", // 验证码状态标识 token: "", // 验证码 token }; // 监听验证码数据变化 EVENT_BUS.on("CAPTCHA_DATA_CHANGE", ({ captchaData, state, token }) => { console.log("收到验证码数据", { captchaData, state, token }); // 更新本地验证码状态 captchaState = { captchaData, state, token }; // 在页面中显示验证码图片,例如在 Web 中使用 img 标签展示 const captchaImage = document.getElementById('captcha-image'); if (captchaImage) { captchaImage.src = captchaData; } }); // 用户点击刷新验证码时调用 const refreshCaptcha = async () => { try { // 获取最新验证码信息 const result = await auth.createCaptchaData({ state: captchaState.state }); // 更新本地验证码状态 captchaState = { ...captchaState, captchaData: result.data, token: result.token, }; // 更新显示的验证码图片 const captchaImage = document.getElementById('captcha-image'); if (captchaImage) { captchaImage.src = result.data; } } catch (error) { console.error("刷新验证码失败", error); } }; // 用户提交验证码时调用 const verifyCaptchaData = async (userCaptcha) => { try { // 校验验证码 const verifyResult = await auth.verifyCaptchaData({ token: captchaState.token, key: userCaptcha }); // 将校验结果通知适配器 EVENT_BUS.emit("RESOLVE_CAPTCHA_DATA", verifyResult); console.log("验证码校验成功"); } catch (error) { console.error("验证码校验失败", error); // 校验失败时可以选择刷新验证码 await refreshCaptcha(); } }; ``` ## 验证码展示效果 示例代码地址: [示例代码](https://github.com/TencentCloudBase/awesome-cloudbase-examples/blob/f38fe782c6c099612eb591866e3c35039e816bb6/universal/soul-chat/src/components/show-captcha.vue) ## 相关 API - `auth.createCaptchaData(options)` - 创建验证码数据 - `auth.verifyCaptchaData(options)` - 验证验证码 - `cloudbase.parseCaptcha(url)` - 解析验证码 URL 参数 ## 注意事项 1. 验证码具有时效性,建议在获取后及时使用 2. 同一验证流程中,验证码校验失败最多重试一次 3. 建议在验证码校验失败后提供刷新验证码的功能 4. 确保事件总线的正确初始化和事件监听 --- ## 自定义登录 import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # 自定义登录 开发者可以使用**自定义登录**,在自己的服务器或者云函数内,为用户签发带有**自定义身份 ID** 的自定义登录凭证 Ticket,随后用户端 SDK 便可以使用 Ticket 登录 CloudBase。 :::caution 版本说明 * **登录认证(v2)** 适用于 `@cloudbase/js-sdk@2.x` 版本 * 如您使用的 SDK 版本为 1.x,请参考 **[登录认证(v1)](/authentication/auth/introduce)** * **v2 版本暂不支持公众号登录方式**,如需使用该方式,请用 [v1 版本](/authentication/method/wechat-login) ::: 本文将以 **V2** 版本进行介绍 ## 适用场景 自定义登录一般用于下面几种场景: * 开发者希望将自有的账号体系与云开发 CloudBase 账号进行一对一关联; * 开发者希望自行接管鉴权流程。 ## 步骤概览 自定义登录需要以下几个步骤: 1. 获取 CloudBase 自定义登录私钥; 2. 使用 CloudBase 服务端 SDK,通过私钥签发出 Ticket,并返回至用户端; 3. 用户端 SDK 使用 Ticket 登录 CloudBase。 ## 前置动作 ### 获取自定义登录私钥 1. 前往 [云开发/身份认证](https://tcb.cloud.tencent.com/dev?#/identity/login-manage) 2. 在登录方式列表中,选择自定义登录方式,点击"去设置"启用自定义登录,再点击私钥下载 ![云开发下载私钥](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/c5871d48-e08a-4109-ae62-26ad3c3a66ae.png) 私钥是一份携带有 JSON 数据的文件,请将下载或复制的私钥文件保存到您的服务器或者云函数中,假设路径为 `/path/to/your/tcb_custom_login.json` 。 :::caution 注意 1. 私钥文件是证明管理员身份的重要凭证,请务必妥善保存,避免泄漏; 2. 每次生成私钥文件都会**使之前生成的私钥文件在 2 小时后失效**。 ::: ## 签发 Ticket 调用 CloudBase 服务端 SDK,在初始化时传入自定义登录私钥,随后便可以签发出 Ticket,并返回至用户端。 ```js const cloudbase = require("@cloudbase/node-sdk"); // 1. 初始化 SDK const app = cloudbase.init({ env: "your-env-id", // 传入自定义登录私钥 credentials: require("/path/to/your/tcb_custom_login.json") }); // 2. 开发者自定义的用户唯一身份标识 const customUserId = "your-customUserId"; // 3. 创建ticket const ticket = app.auth().createTicket(customUserId); // 4. 将ticket返回至客户端 return ticket; ``` :::caution 注意 customUserId 必须满足以下需求: * 4-32 位字符; * 字符只能是大小写英文字母、数字、以及 `_-#@(){}[]:.,+#~` 中的字符。 ::: :::tip 开发者也可以编写一个**云函数**用于生成 Ticket,并为其设置 HTTP 访问服务,随后用户端便可以通过 HTTP 请求的形式获取 Ticket,详细的方案请参阅 [使用 HTTP 访问云函数](/service/access-cloud-function)。 ::: ## 注册流程 使用自定义登录时,用户管理完全由开发者自行处理。在 CloudBase 中,自定义登录不需要单独的注册流程,用户在第一次使用自定义登录时会自动创建对应的 CloudBase 用户。 注册流程主要包括: 1. 在您的用户系统中创建用户账号 2. 使用 CloudBase 服务端 SDK 为该用户签发 Ticket 3. 客户端使用 Ticket 完成首次登录(此时 CloudBase 会自动创建对应用户) ## 登录流程 用户端应用获取到 Ticket 之后,便可以调用 [客户端 SDK](./sdk-init) 的方法登录 CloudBase: [Auth.setCustomSignFunc](/api-reference/webv3/authentication#authsetcustomsignfunc) 用于获取自定义登录的ticket ```js import cloudbase from '@cloudbase/js-sdk'; const app = cloudbase.init({ env: 'your-env-id' }); const auth = app.auth(); async function login() { const loginState = auth.hasLoginState(); // 1. 建议登录前检查当前是否已经登录 if (!loginState) { // 2. 请求开发者自有服务接口获取ticket await auth.setCustomSignFunc(() => { // 获取 ticket 并返回 return Promise.resolve( /* ticket */ ); }) // 3. 登录 CloudBase await auth.signInWithCustomTicket(); } } login(); ``` 整体流程示意如下: ![自定义登录](https://main.qcloudimg.com/raw/9574ad543504b4a4a8d784a3a224cf69.png) ## 常见问题 **自定义登录一定需要自己假设用于创建 Ticket 的服务器吗?** 自定义登录必须有一个创建 Ticket 的服务,但是开发者并非一定要自己搭建服务器。 开发者还可以编写一个云函数来创建 Ticket,然后客户端使用 HTTP 请求调用这个云函数获取 Ticket,详细请参阅 [使用 HTTP 访问云函数](/service/access-cloud-function)。 --- ## 邮箱登录 # 邮箱登录 使用邮箱登录,您可以让您的用户**使用自己的邮箱和密码注册、登录 CloudBase**,并且还可以**更新登录使用的邮箱和密码**。 :::caution 版本说明 * **登录认证(v2)** 适用于 `@cloudbase/js-sdk@2.x` 版本 * 如您使用的 SDK 版本为 1.x,请参考 **[登录认证(v1)](/authentication/auth/introduce)** * **v2 版本暂不支持公众号登录方式**,如需使用该方式,请用 [v1 版本](/authentication/method/wechat-login) ::: 本文将以 **V2** 版本进行介绍 ## 前置动作 ### 开启邮箱登录 1. 前往 [云开发/身份认证](https://tcb.cloud.tencent.com/dev?#/identity/login-manage) 2. 在登录方式列表中,选择 **邮箱登录** - **配置发件人** 3. 配置邮箱发件人SMTP配置后,开启邮箱登录 ![](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/082f40c7-9ff8-49e9-ab55-03a0b96f7800.png) 常见邮箱SMTP配置 | 邮箱 | SMTP服务器主机 | SMTP服务器端口 | SMTP安全模式 | | ----------- | ----------- | ----------- | ----------- | | qq邮箱 | smtp.qq.com | 465/578 | SSL(465)/STARTSSL(587) | | 腾讯企业邮箱 | smtp.exmail.qq.com | 465 | SSL | | 163邮箱 | smtp.163.com | 465 | SSL | | gmail | smtp.gmail.com | 465/578 | SSL(465)/STARTSSL(587) | ## 注册流程 使用邮箱进行注册时,您需要先发送邮箱验证码,然后通过验证码完成注册。 **auth** 实例请参考 [SDK 初始化](./sdk-init) ```js // 1. 发送邮箱验证码 const email = "test@example.com"; const verification = await auth.getVerification({ email: email }); // 2. 验证码验证 // 假设这里收到用户填写的验证码"000000" const verificationCode = "000000"; // 验证验证码的正确性 const verificationTokenRes = await auth.verify({ verification_id: verification.verification_id, verification_code: verificationCode }); // 3. 如果该用户已经存在,则登录 if (verification.is_user) { await auth.signIn({ username: email, verification_token: verificationTokenRes.verification_token }); } else { // 4. 否则,则注册新用户,注册新用户时,可以设置密码,用户名 // 备注:signUp 成功后,会自动登录 await auth.signUp({ email: email, verification_code: verificationCode, verification_token: verificationTokenRes.verification_token, // 可选,设置昵称 name: "手机用户", // 可选,设置密码 password: "password", // 可选,设置登录用户名 username: "username" }); } ``` :::caution 密码强度要求 密码长度不小于 8 位,不大于 32 位,需要包含字母和数字。 ::: ## 登录流程 ### 邮箱密码登录 [Auth.signIn](/api-reference/webv3/authentication#authsignin) 方法可用于 **手机号,邮箱,用户名** 登录 ```js await auth.signIn({ username: email, password: "your-password" }); ``` ### 验证码登录 [Auth.signInWithEmail](/api-reference/webv3/authentication#authsigninwithemail) 方法可用于 **手机号验证码** 登录 ```js const email = 'xxx' // 发送验证码 const verificationInfo = await auth.getVerification({ email: email, }); // 假设这里收到用户填写的验证码"000000" const verificationCode = "000000"; // 验证码登录 await auth.signInWithEmail({ verificationInfo, verificationCode: verificationCode, email: email, }); ``` ## 常见邮箱服务器 ### QQ邮箱 #### 第 1 步:登录 QQ 邮箱 进入 [QQ 邮箱首页](https://mail.qq.com/),登录您的 QQ 邮箱。 #### 第 2 步:开启 IMAP/SMTP 服务 登录邮箱后,进入「设置-账户」: 然后,在「账户」设置中,找到「开启服务」设置项,开启 IMAP/SMTP 服务: 开启成功后,请保存您的邮箱登录授权码: :::tip 注意 您也可以开启 POP3/SMTP 服务,两种服务的授权码都可以作为第 3 步的 SMTP 账号密码。 ::: #### 第 3 步:配置 QQ 邮箱作为发件人 使用 QQ 邮箱作为发件人地址和 SMTP 账号用户名,使用第 2 步的授权码作为 SMTP 账号密码。 ### gmail邮箱 #### 第 1 步:登录 gmail 邮箱 gamil邮箱默认已开启IMAP/SMTP服务,此步骤验证邮箱是否可用 #### 第 2 步:开启google账号两步验证 https://myaccount.google.com/security?utm_source=OGB&utm_medium=app 点击安全(Security)-->两步验证(2-Step Verification)开启 #### 第 3 步:开启google账号app密码 https://support.google.com/accounts/answer/185833?hl=zh-Hans #### 第 4 步:配置云开发平台邮箱登录SMTP | 邮箱 | SMTP服务器主机 | | ----------- | ----------- | | 发件人 | 你的gmail邮箱 | | SMTP服务器主机 |smtp.gmail.com | | 端口 |465 | | SMTP账号用户名 |你的gmail邮箱 | | SMTP账号密码 |第3步的app密码 | | SMTP安全模式 |SSL | --- ## SDK 初始化 # SDK 初始化 登录出现在客户端,小程序接入云开发后,会自动根据 **UID** 去完成鉴权 因此这里提供 `js-sdk` 用于在 Web 端进行鉴权 ## 安装 SDK 在您的项目中引入 `@cloudbase/js-sdk@2.x` ```bash npm install --save @cloudbase/js-sdk ``` ## 初始化 SDK ```js import cloudbase from "@cloudbase/js-sdk"; const app = cloudbase.init({ env: "your-env-id" }); // 获取 auth 实例 const auth = app.auth(); ``` ## 添加安全域名(可选) Web 应用需要将域名添加到 [云开发/安全来源列表](https://tcb.cloud.tencent.com/dev?#/env/safety-source) 中,否则将被识别为非法来源: ![添加安全域名](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/69fa96ef-c310-447c-b1a4-a352163bb268.png) --- ## 短信验证码登录 # 短信验证码登录 使用短信验证码登录,您可以让用户**使用自己的手机号,结合短信验证码或密码注册、登录 CloudBase**。 :::caution 版本说明 * **登录认证(v2)** 适用于 `@cloudbase/js-sdk@2.x` 版本 * 如您使用的 SDK 版本为 1.x,请参考 **[登录认证(v1)](/authentication/auth/introduce)** * **v2 版本暂不支持公众号登录方式**,如需使用该方式,请用 [v1 版本](/authentication/method/wechat-login) ::: 本文将以 **V2** 版本进行介绍 ## 使用限制及费用 * 新开通的按量计费环境,或者 2021 年 4 月 9 日前开通的按量计费环境,享有首月 100 条的免费额度; * 超出免费额度的需求,开发者可以前往云开发控制台 [购买资源包](https://console.cloud.tencent.com/tcb/env/resource); * 短信下发存在频率限制: + 同一号码 30 秒内最多发送 1 条; + 同一手机号一个自然日最多发送 10 条; ## 前置动作 ### 开启短信验证码登录 1. 前往 [云开发/身份认证](https://tcb.cloud.tencent.com/dev?#/identity/login-manage) 2. 在登录方式列表中,选择 **短信验证码登录** 方式,点击开启 ## 注册流程 使用手机号进行注册时,您需要先发送短信验证码,然后通过验证码完成注册。 **auth** 实例请参考 [SDK 初始化](./sdk-init) ```js // 1. 发送手机号验证码 // 需要加区号 const phoneNumber = "+86 13800000000"; const verification = await auth.getVerification({ phone_number: phoneNumber }); // 2. 验证码验证 // 假设这里收到用户填写的验证码"000000" const verificationCode = "000000"; // 验证验证码的正确性 const verificationTokenRes = await auth.verify({ verification_id: verification.verification_id, verification_code: verificationCode }); // 3. 如果该用户已经存在,则登录 if (verification.is_user) { await auth.signIn({ username: phoneNumber, verification_token: verificationTokenRes.verification_token }); } else { // 4. 否则,则注册新用户,注册新用户时,可以设置密码,用户名 // 备注:signUp 成功后,会自动登录 await auth.signUp({ phone_number: phoneNumber, verification_code: verificationCode, verification_token: verificationTokenRes.verification_token, // 可选,设置昵称 name: "手机用户", // 可选,设置密码 password: "password", // 可选,设置登录用户名 username: "username" }); } ``` :::caution 密码强度要求 密码长度不小于 8 位,不大于 32 位,需要包含字母和数字。 ::: ## 登录流程 ### 手机号密码登录 [Auth.signIn](/api-reference/webv3/authentication#authsignin) 方法可用于 **手机号,邮箱,用户名** 登录 ```js await auth.signIn({ username: phoneNumber, password: "your-password" }); ``` ### 验证码登录 [Auth.signInWithSms](/api-reference/webv3/authentication#authsigninwithsms) 方法可用于 **手机号验证码** 登录 ```js const phoneNum = 'xxx' // 发送验证码 const verificationInfo = await auth.getVerification({ phone_number: `+86 ${phoneNum}`, }); // 假设这里收到用户填写的验证码"000000" const verificationCode = "000000"; // 验证码登录 await auth.signInWithSms({ verificationInfo, verificationCode: verificationCode, phoneNum: phoneNum, }); ``` --- ## 用户名密码登录 import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # 用户名密码登录 使用用户名密码登录,您可以让您的用户**绑定用户名,并使用用户名密码登录 CloudBase**。您还可以[更改密码](/api-reference/webv3/authentication#authsetpassword)或者[重置密码](/api-reference/webv3/authentication#authresetpassword)。 :::caution 版本说明 * **登录认证(v2)** 适用于 `@cloudbase/js-sdk@2.x` 版本 * 如您使用的 SDK 版本为 1.x,请参考 **[登录认证(v1)](/authentication/auth/introduce)** * **v2 版本暂不支持公众号登录方式**,如需使用该方式,请用 [v1 版本](/authentication/method/wechat-login) ::: 本文将以 **V2** 版本进行介绍 如果**用户名未被绑定过**,需要先使用其他登录方式完成登录后,才可以绑定用户名。绑定成功后,可以使用用户名和密码完成登录。 ## 前置动作 ### 开启用户名密码登录 1. 前往 [云开发/身份认证](https://tcb.cloud.tencent.com/dev?#/identity/login-manage) 2. 在登录方式列表中,选择 **用户名密码登录** 方式,点击开启 ## 注册流程 用户名登录的注册比较特殊,需要先使用 **其他方式** 完成注册,然后在注册过程中设置用户名 目前支持 **手机号验证码、邮箱验证码** 注册 ### 使用其他方式注册并设置用户名 以 [邮箱登录](/authentication-v2/method/email-login) 为例,在注册新用户时设置用户名: **auth** 实例请参考 [SDK 初始化](./sdk-init) ```js const email = "test@example.com"; auth.signUp({ email: email, // 参考邮箱登录过程中获得的验证码和校验 token verification_code: verificationCode, verification_token: verificationTokenRes.verification_token, // 设置用户名 username: "userFromEmail", // 可选,设置密码 password: "password123" }); ``` :::caution 用户名规则 1. 可以包含数字和字母,但是不允许是纯数字 2. 符号只允许出现 `-` 和 `_`,不允许这两个符号出现在开头和结尾 3. 长度范围是 `[1, 32]` ::: :::tip 为什么必须先使用其他方式注册,再绑定用户名? 用户名可以是符合规则的任意字符串,为了避免您的应用被恶意者注册过多无效的用户名,CloudBase 目前不允许直接使用用户名 + 密码的形式注册用户。 ::: ## 登录流程 在您的项目中需要登录的位置获取到账号密码后,执行如下代码: ```js const loginState = await auth.signIn({ username: "your username", password: "your password" }); ``` :::caution 注意 用户名登录和邮箱登录的密码是相同的。 ::: --- ## 微信授权登录 import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # 微信授权登录 经微信开放平台(普通网站应用及移动应用等)授权的应用可以直接使用微信登录 CloudBase。 :::caution 版本说明 * **登录认证(v2)** 适用于 `@cloudbase/js-sdk@2.x` 版本 * 如您使用的 SDK 版本为 1.x,请参考 **[登录认证(v1)](/authentication/auth/introduce)** * **v2 版本暂不支持公众号登录方式**,如需使用该方式,请用 [v1 版本](/authentication/method/wechat-login) ::: 本文将以 **V2** 版本进行介绍 ## 前置动作 ### 开启微信登录 1. 首先需要一个开放平台的注册账号,如果没有,请前往 [微信开放平台](https://open.weixin.qq.com/) 申请 2. 前往 [云开发/身份认证](https://tcb.cloud.tencent.com/dev?#/identity/login-manage) 3. 在登录方式列表中,选择 **微信开放平台登录** 方式,点击「**去设置**」填入 **AppId** 和 **AppSecret** ## 注册流程 使用微信授权登录时,用户在第一次使用微信登录时会自动创建对应的 **CloudBase** 用户账号,无需单独的注册流程。 具体流程如下: 1. 用户第一次使用微信登录时,系统会自动创建 **CloudBase** 用户 2. 用户的微信信息(如昵称、头像等)会自动同步到 **CloudBase** 用户资料中 3. 后续使用相同微信账号登录时,会直接登录到对应的 **CloudBase** 用户 ## 登录流程 ### 获取第三方平台授权页地址 填入微信平台 ID、重定向 URI 和自定义状态标识字段用于识别平台回调来源。系统内置有**微信开放平台**的[平台 ID](/api-reference/webv3/authentication#系统内置三方列表)。 **auth** 实例请参考 [SDK 初始化](./sdk-init) [Auth.genProviderRedirectUri](/api-reference/webv3/authentication#authgenproviderredirecturi) 用于生成第三方平台授权页URL ```js const { uri } = await auth.genProviderRedirectUri({ provider_id: "wx_open", // 微信开放平台 provider_redirect_uri: providerUri, // 重定向 URI state: state, // 自定义状态标识 other_params: otherParams // 其他参数 }); ``` ### 访问 URI 并进行授权后,回调至指定地址,获取第三方平台 token 将用户重定向至 URI,例如 `location.href = uri` ;待用户授权完毕后,回调至指定的 `provider_redirect_uri` 地址。 ```js // 此时 url query 中携带授权 code,state 等参数 // 1. 检查 state 是否符合预期(如设置的 wx_open) // 2. 获取第三方平台跳转回页面时,url param 中携带的 code 参数 const provider_code = "your_provider_code"; // 3. 如符合预期,获取第三方平台 token const { provider_token } = await auth.grantProviderToken({ provider_id: "wx_open", provider_redirect_uri: "curpage", // 指定三方平台跳回的 url 地址 provider_code: provider_code // 第三方平台跳转回页面时,url param 中携带的 code 参数 }); ``` ### 通过第三方平台 token 登录 ```js await auth.signInWithProvider({ provider_token: provider_token }); ``` --- ## 环境级访问权限控制 import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # 环境级访问权限控制 云开发 针对管理端 SDK(例如:[`@cloudbase/node-sdk`](/api-reference/server/node-sdk/introduction))调用提供 `环境` 和 `操作` 级别的权限控制能力,允许按实际需要限定(密钥)仅能对指定环境进行某些操作。 即,可以为不同的访问密钥(`SecretId/SecretKey`),分配不同的权限,实现对资源访问权限的管控。 该能力基于 腾讯云统一的 [访问管理 CAM](https://cloud.tencent.com/product/cam) ,所以需要对 CAM 相关能力具备一定了解。 该能力适用于管理端 SDK 通过显式指定访问密钥进行初始化的方式。如以下 `@cloudbase/node-sdk` 示例: ```ts const app = tcb.init({ secretId: "your_secret_id", secretKey: "your_secret_key", }); ``` > 注意:以下描述的权限策略应用于云开发管理端 SDK,所以仅描述了如何分配管理端 SDK 中需要使用的权限。云开发控制台及云 API 相关的访问权限,需增加控制台访问的权限策略,一般将预定义策略授予相关用户即可。 ## 操作步骤 1. **创建策略**:控制台 -> 访问管理 -> 策略 -> 创建策略 -> 按策略语法或标签创建策略 -> 空白模版 -> 填入策略配置 -> 提交 2. **关联策略**:将策略关联到账户/子账号/用户组/协作者 3. **获取密钥**:通过控制台或云 API 创建并获取密钥 4. **使用密钥**:通过访问密钥初始化管理端 SDK 访问和管理环境下的云资源 > 以上步骤主要用于通过腾讯云控制台创建策略并将策略关联到账户/子账号/用户组/协作者方式进行权限控制的方式。 ## 创建策略 策略通过 `策略语法` 定义和描述一条或多条权限规则,策略内包含了 资源和操作 的权限控制,例如 对某 TCB 环境调用云函数的权限。 将策略关联到 账户/子账号/用户组/协作者 后,相关实体的访问密钥将具备相应的权限,更多相关内容请参考 [权限与策略](https://cloud.tencent.com/document/product/598/10600) 云开发支持按 `环境` 和 `标签` 两种方式进行权限控制,以下为按 `策略语法` 创建策略示例 策略中需要的 `Resoures & Actions` 请参考 [Resoures & Actions](#resoures--actions) ### 1. 按 `Tag` 进行权限控制的策略 通过该方式创建的策略,该策略将应用于具备某标签的一个或多个资源(环境),当标签进行调整时,相应的权限也将同步更新。 以下策略为:授予 具备 `标签键Tag:env` 等于 `标签值Value:development` 的资源的全部操作(`tcb:*`)权限。 注意:这里需要创建标签,再设置资源标签,TCB 环境标签管理 在环境详情页-资源购买页-基本配置。创建标签请参考:https://console.cloud.tencent.com/tag/taglist ```json { "version": "2.0", "statement": [ { "effect": "allow", "action": ["tcb:*"], "resource": "*", "condition": { "for_any_value:string_equal": { "qcs:resource_tag": [ "env&development" // 标签键Tag:env=标签值Value:production ] } } } ] } ``` 以下策略为:授予 具备 `env=development` 标签的资源的调用云函数(`tcb:InvokeFunction`)权限。 ```json { "version": "2.0", "statement": [ { "effect": "allow", "action": ["tcb:InvokeFunction"], "resource": "*", "condition": { "for_any_value:string_equal": { "qcs:resource_tag": [ "env&development" // 标签键Tag:env=标签值Value:production ] } } } ] } ``` 更多标签相关内容,请参考: - [标签](https://cloud.tencent.com/document/product/651) - [创建标签并绑定资源](https://cloud.tencent.com/document/product/651/56731) - [授予标签下部分操作权限](https://cloud.tencent.com/document/product/598/55150) ### 2. 按 `EnvID` 进行权限控制的策略 通过该方式创建的策略,该策略将应用于 `resource` 字段列表中的资源。 以下策略为:授予 `resource` 字段列表中的资源的全部操作(`tcb:*`)权限。 ```json { "version": "2.0", "statement": [ { "effect": "allow", "action": ["tcb:*"], "resource": [ "qcs::tcb:::env/${your-env-id}", "qcs::tcb:${region}::env/${your-env-id}" ] } ] } ``` 以下策略为:授予 `resource` 字段列表中的资源的调用云函数(`tcb:InvokeFunction`)权限。 ```json { "version": "2.0", "statement": [ { "effect": "allow", "action": ["tcb:InvokeFunction"], "resource": [ "qcs::tcb:::env/${your-env-id}", "qcs::tcb:${region}::env/${your-env-id}" ] } ] } ``` ## 获取密钥 创建好策略之后,即可将策略授权给 `账户/子账号/用户组/协作者`,其相关联的的访问密钥(`SecretId/SecretKey`)将会限定性的拥有策略中描述的资源(Resources)及相关操作(Actions)的权限。 可以通过以下 3 种方式获得 `访问凭证` ### 1. 控制台获取子账号/协作者访问凭证 可在 [访问管理](https://console.cloud.tencent.com/cam) -> 用户管理 -> 用户列表 -> 子用户详情页 -> API 密钥 页面新建或获取永久访问凭证 该方式适用于为子账号分配相关资源的访问权限,密钥有效期长 参考文档:[创建子账号并授权](https://cloud.tencent.com/document/product/598/54458) > 该方式需要预先创建 策略 和 子账号/协作者,并将 策略 授予 子账号/协作者 ### 2. 通过 `sts:AssumeRole` 扮演角色获取临时访问凭证 该方式通过腾讯云 CAM 云 API 接口创建临时访问凭证,需要先创建角色,并将相关的权限策略授予该角色,使该角色具备相关权限,继而通过该角色创建的访问凭证也具备相关权限。 参考文档:[申请扮演角色](https://cloud.tencent.com/document/product/1312/48197) > 该方式需要预先创建 策略 和 角色 ### 3. 通过 `sts:GetFederationToken` 获取联合身份临时访问凭证 该方式通过腾讯云 CAM 云 API 接口创建临时访问凭证,该方式不需要事先创建角色,但是需要每次调用接口创建访问凭证时,传入策略,继而分配具备相关权限的密钥。 参考文档:[获取联合身份临时访问凭证](https://cloud.tencent.com/document/product/1312/48195) > 该方式不需要预先创建 策略 和 角色 ## 使用密钥 以下 `@cloudbase/node-sdk` 示例: ```ts const app = tcb.init({ secretId: "your_secret_id", secretKey: "your_secret_key", }); ``` ### 鉴权通过 鉴权通过将能够正常访问对应环境下的资源 ### 鉴权失败 `SIGN_PARAM_INVALID` 以下为鉴权失败的示例,该错误信息描述了因为 无 `tcb:InvokeFunction` 操作权限而导致的鉴权失败,将包含 `tcb:InvokeFunction` 权限的策略授予 `账户/子账号/用户组/协作者` 后,重新获取访问密钥,即可通过鉴权。 ```json { "code": "SIGN_PARAM_INVALID", "message": "you are not authorized to perform operation (tcb:InvokeFunction)" } ``` ## Resoures & Actions ### Resoure 用于描述资源,对应于 TCB 的环境 格式:`qcs::tcb:${Region}::env/${EnvId}`,该字符串描述了环境资源。 示例如下: ```json ["qcs::tcb:::env/${your-env-id}"] ``` ### Action 用于描述操作,具备对某资源(`Resoure`)具备哪些操作 | Action | 描述 | | ----------------------- | ---------------------------------------------------------- | | `tcb:InvokeFunction` | 调用云函数 | | `tcb:InsertDocument` | 插入数据 | | `tcb:DeleteDocument` | 删除数据 | | `tcb:UpdateDocument` | 更新数据 | | `tcb:QueryDocument` | 查询数据 | | `tcb:AggregateDocument` | 聚合数据 | | `tcb:RunTransaction` | 运行事务。在事务中进行 CURD 等操作,需要分配对应操作的权限 | | `tcb:ExplainQuery` | 查询分析 | | `tcb:GetFileAuthority` | 获取文件权限信息 | | `tcb:GetDownloadUrl` | 获取文件下载地址 | | `tcb:DeleteFile` | 删除文件 | | `tcb:UploadFile` | 上传文件 | | `tcb:QueryUserInfo` | 获取用户信息 | > 注意:以上仅包含管理端 SDK 用到的 `Action`,不包括控制台及云 API 的接口权限控制涉及的 `Action` --- ## CLI工具介绍 # CLI工具介绍 ## CLI工具介绍 当前存在两个 CLI 工具,以下为两个工具的介绍: * `tcb` - `@cloudbase/cli` 云开发统一 CLI 工具,提供 云托管函数代码 部署、下载、运行 等能力,主要是与云端进行交互。参考文档:[tcb cloudrunfunction](../cli-v1/runf/intro) * `tcb-ff` - `@cloudbase/functions-framework` 云函数框架 CLI 工具,该框架为云函数运行时,提供函数代码运行能力,`tcb` 命令运行 函数代码 也是通过调用 `tcb-ff` 来实现的。参考文档:[tcb-ff](./tcb-ff-help.md) 两个 `cli` 工具的关系:`tcb` 通过 `tcb-ff` 来运行函数代码,并额外提供了与云端交互的能力,进行函数代码的部署。推荐使用 `tcb`。 --- ## 开发函数型智能体 # 开发函数型智能体 函数型云托管 支持开发函数型智能体,详情可参考:[函数型智能体](../ai/cbrf-agent/intro) --- ## 在线开发云函数 # 在线开发云函数 云开发平台提供在线开发云函数的能力,无需配置本地开发环墋,即可在线开发、调试、部署云函数。 ## 进入在线开发环境 通过点击 云函数服务 详情页的 `在线开发` 按钮,即可进入在线开发环境。 ![goto-develop-online](./images/goto-develop-online.png) 进入环境前可能会需要进行云端环境准备 ![cloudstudio-init](./images/cs-cloudstudio-init.png) ## 工作区介绍 进入在线开发环境会,会来到类似如下的一个工作区,该工作区环境的编辑器界面与 `VSCode` 是相同的,支持代码编辑、调试、终端等功能。 下图描述了 `文件浏览器区域` 的主要内容: ![cs-workspace-intro](./images/cs-workspace-intro.png) ### `cloudrunfunctions` 目录 `函数型云托管` 函数代码存放目录为 `cloudrunfunctions`,在此目录上右键,可进行 `函数型云托管` `创建`、`同步列表` 等操作。 ![cs-workspace-cloudrunfunctions](./images/cs-workspace-cloudrunfunctions.png) #### 同步列表 点击 `【函数型云托管】同步列表` 后同步云函数列表,同步完成后,会在下方输出同步状态信息。 ![cs-workspace-sync-cbrf](./images/cs-workspace-sync-cbrf.png) #### 新建云函数 点击 `【函数型云托管】新建` 后,会弹出对话框,输入云函数名称,即可创建云函数。 ![cs-workspace-create-cbrf](./images/cs-workspace-create-cbrf.png) ### `cloudrunfunctions/{函数名}` 目录 `函数型云托管` 的函数代码存放目录为 `cloudrunfunctions/{函数名}`,在此目录下,可进行 `调试`、`部署` 等操作。 ![cs-workspace-cbrf-op](./images/cs-workspace-cbrf-op.png) #### 调试云函数 函数代码编写完成后,点击 `【函数型云托管】调试`,即可启动调试。 ![cs-workspace-debug-cbrf](./images/cs-workspace-debug-cbrf.png) 如启动调试出现错误,可通过控制台输出查看错误原因,并进行修复。 调试完成之后,即可进行云函数的部署。 --- ## 函数代码示例 # 函数代码示例 如下提供了若干 函数型云托管 的使用示例,以下示例为简单起见,主要使用 `JavaScript` 编写。 ## 引入外部模块 在函数中引入外部模块,例如 `lodash`,并使用其提供的方法: 函数代码文件示例: ```js // index.js const _ = require('lodash') exports.main = function(event, context) { return _.kebabCase('Hello world') } ``` package.json文件: ```json // package.json { "name": "example", "version": "1.0.0", "main": "index.js", "dependencies": { "lodash": "^4.17.21" } } ``` 执行该函数后客户端可以收到 `hello-world` 的响应。 ## 在不同函数间共享代码 利用单实例多函数能力和函数间路由,可以使用一般的模块导入方法,在不同的函数间共享公共模块。 假设有函数 `funcA` 和 `funcB` 需要共享一个获取当前时间的方法 `now`,有如下目录结构: ```shell . ├── cloudbase-functions.json # 多函数配置文件 ├── cloudrunfunctions/common # 公共方法目录 │ └── time.js # 公共方法 ├── cloudrunfunctions/funcA # 函数 A 目录 │ └── index.js └── cloudrunfunctions/funcB # 函数 B 目录 ├── package.json # 指定 index.mjs 为入口文件 └── index.mjs ``` 在 `time.js` 中导出 `now` 方法: ```js // common/time.js exports.now = function () { return new Date().toLocaleString() } ``` 在函数 A 和函数 B 代码中直接引入即可: ```js // cloudrunfunctions/funcA/index.js const now = require('../common/time').now ``` ```js // cloudrunfunctions/funcB/index.mjs import { now } from '../common/time.js' ``` 在 `cloudbase-functions.json` 中对不同的函数进行声明: ```json { "functionsRoot":"./cloudrunfunctions/", // 函数根目录,指定为当前目录 "functions": [ // 声明各函数及其入口文件 { "name":"funcA", // 声明函数 A "directory":"funcA", "triggerPath": "/a" }, { "name":"funcB", // 声明函数 B "directory":"funcB", "triggerPath": "/b" } ] } ``` 这样函数 A 和函数 B 将部署在同一个服务中,同时均可以使用 `now` 方法 ## 在函数中路由 可根据 `context` 中获取到的 HTTP 相关路径、query 等信息,实现简单的路由功能。 函数代码: ```js exports.main = function(event, context) { const { httpContext } = context const { url } = httpContext const path = new URL(url).pathname // 根据访问路径返回不同的内容 switch (path) { case '/': return { statusCode: 200, body: 'Hello world!' } case '/index.html': return { statusCode: 200, headers: { 'Content-Type': 'text/html' }, body: 'Hello world!' } default: return { statusCode: 404, body: 'Not found' } } } ``` ## 返回不同类型的响应 可以通过不同的路由路径,返回不同的响应类型及响应内容。 函数代码: ```js exports.main = function(event, context) { const { httpContext } = context const { url } = httpContext const path = new URL(url).pathname // 根据访问路径返回不同的内容 switch (path) { // 直接返回字符串 case '/': return 'Hello world!' // 返回当前时间戳 case '/now': return new Date().getTime() // 使用集成响应返回 HTML case '/index.html': return { statusCode: 200, headers: { 'Content-Type': 'text/html' }, body: 'Hello world!' } // 使用集成响应返回 JSON default: return { statusCode: 404, headers: { 'Content-Type': 'application/json' }, body: { message: 'Not found' } } } } ``` 可综合使用集成响应、非集成响应,获得更丰富的响应类型。 ## 使用 Server-sent Event 推送消息 为了适配 AI 大模型 API 常用的 SSE 协议,函数型云托管 可以支持 SSE 方式推送内容。 函数代码: ```js exports.main = async function (event, context) { // 切换到 SSE 模式 const sse = context.sse() // 可选参数,设置 SSE 连接的请求头 // const sse = context.sse({ // keepalive: false, // 是否保持连接,默认开启,可关闭 // headers: { // 'Mcp-Session-ID': 'this-is-a-mcp-session-id', // 'X-ABC': ['A', 'B', 'C'], // } // }) sse.on('close', () => { console.log('sse closed') }) // 发送事件到客户端,发送前先检查是否已经关闭,如未关闭可发送 if (!sse.closed) { // 多次发送多个事件 sse.send({ data: 'No.1 message' }) sse.send({ data: 'No.2 message with\n\r\r\n\r\r\rtwo lines.' }) // 单次发送多个事件 sse.send([ { data: 'No.1 message' }, { data: 'No.2 message with\n\r\r\n\r\r\rtwo lines.' } ]) // 以下为发送原始消息的示例 // 该方式用于扩展 SSE 协议,例如发送其他 Event Field 字段 // 注意:末尾必须有换行符数据才会立即发送 sse.send('message: This is a raw message. ') sse.send(['message: This is another raw message.\n\n']) // 函数执行时间以函数返回时间计算 // 函数返回后,HTTP 请求处理完成,函数内的异步逻辑继续进行处理,不影响函数返回时间 // TCP 网络连接依然被 SSE 占用,在 SSE 连接被客户端或服务端关闭之前,可以继续发送消息到客户端 // SSE 协议已经将 HTTP 转换到长连接模式,需要客户端或服务端在适当的时候主动关闭连接,否则将导致连接一直占用,消耗网络资源 // 因TCP主动关闭的一方将进入TIME_WAIT 状态,大量 TIME_WAIT 状态的连接将导致网络资源耗尽,无法建立新的连接,所以客户端主动关闭连接更符合最佳实践 // 因客户端可能并不知晓在什么时间关闭连接,服务端可以发送一个特殊的消息,告诉客户端消息已经结束,可以关闭连接了 // 浏览器中调用 EventSource#close 关闭连接,见:https://developer.mozilla.org/en-US/docs/Web/API/EventSource/close return '' } } ``` ## 使用 WebSocket 长连接收发消息 函数代码: ```js exports.main = function (event, context) { console.log({ event, context }) if (context.ws) { context.ws.on('close', (msg) => { console.log('close: ', msg) }) context.ws.on('message', (msg) => { console.log('message: ', msg) }) setInterval(() => { context.ws.send(`now: ${new Date().toISOString()}`) }, 100) } } // 支持同步异步 exports.main.handleUpgrade = async function (upgradeContext) { console.log(upgradeContext, 'upgradeContext') if (upgradeContext.httpContext.url === '/upgrade-handle-throw-error') { throw new Error('test throw error') } else if (upgradeContext.httpContext.url === '/upgrade-handle-reject-error') { return Promise.reject(new Error('test reject error')) } else if (upgradeContext.httpContext.url === '/allow-websocket-false') { return { allowWebSocket: false, statusCode: 403, body: JSON.stringify({ code: 'code', message: 'message' }), contentType: 'appliaction/json; charset=utf-8' } } return { allowWebSocket: true } } ``` node.js 客户端代码: ```js import WebSocket from 'ws' function run () { const ws = new WebSocket('ws://127.0.0.1:3000/') ws.on('close', (code, reason) => { console.log('close:', code, `${reason}`) }) ws.on('error', (err) => { console.error('error: ', err) }) ws.on('upgrade', () => { console.log('upgrade') }) ws.on('ping', () => { console.log('recv ping message') }) ws.on('pong', () => { console.log('recv pong message') setTimeout(() => { ws.ping() }, 1000) }) ws.on('unexpected-response', (ws, req, res) => { // 非 upgrade 响应和 3xx 重定向响应认为是 unexpected-response console.log('recv unexpected-response message') }) ws.on('message', (data) => { console.log('received: %s', data) }) ws.on('open', () => { ws.ping() ws.send('string data') ws.send(Buffer.from('buffer data')) }) } run() ``` ## 使用 `multipart/form-data` 提交表单数据(文件) 函数型云托管 支持前端以 `multipart/form-data` 格式提交表单内容,可以包含文件内容。 函数代码: ```js const path = require('path') const fs = require('fs') exports.main = async function (event, context) { // 从 event.file 属性上获取要保存的文件(与传参对应) // event.file 类型为 PersistentFile,见 https://www.npmjs.com/package/formidable#file // 如有其他传参,可用 form data 传参中的对应名称 event.[your param name] 获取,如 event.name, event.size 等 const file = event.file // 获取原始文件名 const fileName = file.originalFilename; // 保存文件的目录 const fileDir = path.join(process.cwd(), 'tmp') if (!fs.existsSync(fileDir)) { fs.mkdirSync(fileDir) } const filePath = path.join(fileDir, fileName) // 从参数中读取文件流 const readStream = fs.createReadStream(file.filepath) // 尝试保存文件到指定目录 try { await fs.promises.writeFile(filePath, readStream) } catch (error) { return { statusCode: 500, body: `Error saving file: ${error.message}` } } // 注意:删除临时文件 return { statusCode: 200, body: `File saved to: ${filePath}` } } ``` 发送上传文件请求: ```sh curl --location 'url' \ --form 'file=@file.png' ``` 注意: 1. 文件上传完成后会保存到本地文件,您应该在函数执行结束后删除文件,以免占用过多磁盘空间。 2. 上传的文件如需持久化,应该保存到云存储或其他服务中,以免文件丢失,避免保存在本地。 ## 使用 PUT 上传二进制数据或文件 函数代码: ```js const path = require('path') const fs = require('fs') exports.main = async function(event, context) { const { httpContext } = context const { url } = httpContext // 从 query 中获取文件名 const filename = new URL(url).searchParams.get('filename') // 保存文件的目录 const fileDir = path.join(process.cwd(), 'tmp') if (!fs.existsSync(fileDir)) { fs.mkdirSync(fileDir) } // 保存文件的路径 const filePath = path.join(fileDir, filename) try { // 从 event 中获取文件内容 const buffer = Buffer.from(event, 'binary') await fs.promises.writeFile(filePath, buffer); return { statusCode: 200, body: `File saved to: ${filePath}`, }; } catch (error) { return { statusCode: 500, body: `Error saving file: ${error.message}`, }; } } ``` 发送上传文件请求: ```sh curl --location --request PUT 'url?filename=file.png' \ --header 'Content-Type: application/octet-stream' \ --data 'file.png' ``` ## 使用 `puppeteer` 实现网页截屏 ```json { "name": "example", "version": "1.0.0", "main": "index.mjs", "type": "module", "dependencies": { "puppeteer": "^23.11.1" } } ``` ```ts import * as path from 'path' import * as url from 'url' import * as fs from 'fs' import puppeteer from 'puppeteer' const __filename = url.fileURLToPath(import.meta.url) const __dirname = path.dirname(__filename) async function screenshotWebPage(webPageUrl, savePath) { const browser = await puppeteer.launch({ args: ['--no-sandbox', '--disable-setuid-sandbox'] }) const page = await browser.newPage() await page.goto(webPageUrl) await page.pdf({ path: savePath, format: 'letter', }) await browser.close() } export const main = async function (event, context) { const webPageUrl = 'https://docs.cloudbase.net/cbrf/intro' const savePath = 'cbrf-intro.pdf' await screenshotWebPage(webPageUrl, savePath) return { statusCode: 200, headers: { 'Content-Disposition': `attachment; filename=${savePath}`, 'Content-Type': 'application/pdf', }, body: fs.createReadStream(path.join(__dirname, savePath)) } } ``` --- ## 常见问题 FAQ # 常见问题 FAQ ## 产品规划 ### 目前提供函数型云托管 后,后续会如何处理云函数或云函数 1.0,是否会下线云函数1.0 ? 函数型云托管 提供了一套与云函数不同的运行机制,在使用体验、运行感受上各有特性。 两者产品能力均会长期存在,不会由于提供了函数型云托管 而在后续取消下线云函数。 ### 为什么会提示开通过云托管 函数型云托管 的底层使用了新版本架构的云托管;如果您的云开发环境,在以前通过腾讯云控制台上开通过云托管服务,则会开通过旧架构的云托管,导致没法再次开启新架构的云托管服务。 您可以通过:腾讯云控制台-云开发-右上角旧版本控制台,进入到旧版本控制台,通过左侧栏的云托管,进入到旧架构的云托管服务。 您可以通过删除旧架构云托管服务中的全部服务,以便清理并不再使用旧架构的云托管。清理完成后,后续通过开发平台入口,开启新版本云托管及函数型云托管。 如果您有进一步的问题或不知道如何操作,可以通过[提交工单](https://console.cloud.tencent.com/workorder/category?level1_id=536&level2_id=821&source=14&data_title=%E4%BA%91%E5%BC%80%E5%8F%91%20CloudBase&step=1)寻求帮助。 ## 计量、费用相关 ### 函数型云托管 如何计费 当前函数型云托管 使用了云托管实例方式运行,会根据实例的规格、运行时长来进行计费。使用函数型云托管 时的计费项包括: * 核x小时:实例启动后,实例使用的核数运行一个小时,计为 1 核x小时,或称为核时;例如:1核的1个实例运行一个小时,计为 1 核*小时; * GBx小时:实例启动后,实例使用的内存运行一个小时,计为 GBx小时,或称为GB时;例如:2GB内存的1个实例运行一个小时,计为 2 GB*小时; * 调用次数:通过callContainer方法,从小程序端或 web 端调用函数型云托管,会计入调用次数,跟随云托管整体套餐一同计量;**通过函数型云托管 提供的公网地址发起的调用,将不记调用次数** * 出流量:从函数实例内流出的流量,均会计为出流量;例如从函数内向外上传文件、发起请求的请求包,均为出流量;函数内下载文件,发起请求的响应包,为入流量,不计入计费; ### 使用函数型云托管 时,为什么需要开启云开发环境的超限按量 目前函数型云托管 的计费项均未包含在云开发套餐中,而是通过按量计费的方式收取。在云开发环境启用超限按量后,按量计费的计费项才可正常启用。函数型云托管 依赖计费项正常启用后,服务才可正常启动运行,因此需要函数所在的云开发环境启用超限按量。 --- ## 如何按需构建自定义函数镜像 # 如何按需构建自定义函数镜像 函数型云托管服务部署时只需要提供函数代码即可,并不需要提供 `Dockerfile`,因此,函数运行容器镜像包含的内容由平台提供的镜像决定。 如对镜像有个性化需求,例如安装特定的依赖包、字体等,可以通过自定义 `Dockerfile` 的方式构建自己的容器镜像。 > 注意:自定义镜像需要通过 容器型服务 部署。 以下为云端构建时使用的 `Dockerfile` 内容,可在此基础上按需修改,仅供参考: ```Dockerfile # 可通过该变量指定 functions-framework 基础镜像版本 ARG FRAMEWORK_VERSION=20.18.3-1.17.0-33-5b218e FROM crunbuild-az-new.tencentcloudcr.com/cloudbase/functions-framework:${FRAMEWORK_VERSION} RUN PASSWORD=$(dd bs=1 count=12 if=/dev/urandom | md5sum | cut -d' ' -f1) && echo "root:$PASSWORD" | chpasswd -c SHA512 WORKDIR /workspace COPY . . ################################### #### 可以在此执行个性化配置相关指令 #### ################################### RUN . ~/.profile \ && ls -liha \ && rm -rf logs \ && echo "\n\n===> step.1 install specified node.js version" \ && \ if [ -e .node-version ]; then \ echo " File '.node-version' exists, use '.node-version', content: '$(cat .node-version)'"; \ nvm install $(cat .node-version) && nvm alias default $(cat .node-version); \ elif [ -e .nvmrc ]; then \ echo " File '.nvmrc' exists, use '.node-version', content: '$(cat .node-version)'"; \ nvm install && nvm use && nvm alias default $(nvm current); \ else \ echo " File '.node-version' or '.nvmrc' not exists, use buildin node"; \ fi; \ echo " node version $(node -v)" \ && echo "\n\n===> step.2 install dependency packages" \ && \ if [ ! -e package.json ]; then \ echo " File 'package.json' not exists, skip install dependencies"; \ elif [ -e package.json ] && [ -d node_modules ]; then \ echo " File 'node_modules' exists, skip install dependencies"; \ elif [ -e package.json ] && [ ! -d node_modules ]; then \ echo " File 'package.json' exists and 'node_modules' not exists, install dependencies"; \ echo " ----------- package.json begin -----------"; \ cat package.json; \ echo " ----------- package.json end -----------"; \ echo " Configure npm"; \ { \ echo "omit=dev"; \ echo "registry=https://mirrors.tencent.com/npm/"; \ echo "# prebuild-install"; \ echo "faiss_node_binary_host_mirror=https://static.cloudbase.net/npm_binary_mirrors/faiss-node/"; \ echo "# puppeteer"; \ echo "puppeteer-download-base-url=https://cdn.npmmirror.com/binaries/chrome-for-testing"; \ } >> ~/.npmrc; \ if [ -e pnpm-lock.yaml ]; then \ echo " File 'pnpm-lock.yaml' exists, use 'pnpm install'"; \ pnpm install; \ elif [ -e yarn.lock ]; then \ echo " File 'yarn.lock' exists, use 'yarn install'"; \ yarn install; \ yarn cache clean; \ else \ echo " Default, use 'npm install'"; \ npm install; \ npm cache clean --force; \ fi; \ if jq -e '(.dependencies | has("puppeteer")) or (.devDependencies | has("puppeteer"))' package.json; then \ echo " File 'package.json' dependencies include puppeteer, install dependencies libraries(.so) for puppeteer"; \ sed -i 's/archive\.ubuntu\.com/mirrors.cloud.tencent.com/g' /etc/apt/sources.list.d/ubuntu.sources; \ export DEBIAN_FRONTEND=noninteractive; \ apt update && apt upgrade -y; \ # 安装 puppeteer 需要的依赖库,比较耗费空间 # https://source.chromium.org/chromium/chromium/src/+/main:chrome/installer/linux/debian/dist_package_versions.json apt install -y libasound2t64 libatk-bridge2.0-0t64 libatk1.0-0 libcairo2 \ libcups2t64 libdbus-1-3 libdrm2 libgbm1 libglib2.0-0t64 libglibd-2.0-0 libnss3 \ libpango-1.0-0 libxcomposite1 libxdamage1 libxfixes3 libxkbcommon0 libxrandr2; \ # 安装 puppeteer 可能需要的字体,如网页截屏场景,比较耗费空间 apt install -y fonts-noto fonts-dejavu fonts-font-awesome; \ apt clean; \ rm -rf /var/lib/apt/lists/*; \ sed -i 's/mirrors\.cloud\.tencent\.com/archive.ubuntu.com/g' /etc/apt/sources.list.d/ubuntu.sources; \ fi \ fi ``` 可通过 [`skopeo`](https://github.com/containers/skopeo) 工具 获得 `functions-framework` 基础镜像版本 ```sh skopeo list-tags docker://crunbuild-az-new.tencentcloudcr.com/cloudbase/functions-framework { "Repository": "crunbuild-az-new.tencentcloudcr.com/cloudbase/functions-framework", "Tags": [ "20.18.3-1.13.0-31-695a62", "20.18.3-1.14.0-32-dafdb5", "20.18.3-1.14.0-arm64", "20.18.3-1.17.0-33-5b218e" ] } ``` 推荐根据 `Tag` 列表,选择最新版本。 --- ## 如何调试函数代码? # 如何调试函数代码? 在日常开发过程中,经常需要调试代码,以便高效的完成功能开发与问题定位。`函数型云托管` 支持用户在线开发和本地开发两种断点调试方式 ## 在线开发断点调试方式 ### 1. 进入“在线开发”模式 在云托管列表界面,找到您想要调试的云函数,点击其对应的「在线开发」按钮,进入 “在线开发” 模式 ![](https://qcloudimg.tencent-cloud.cn/raw/d4aaa62dfdbf64738a70af97034dff48.png) ### 2. 点击「【函数型云托管】调试」菜单启动调试服务 有两个地方能调出「【函数型云托管】调试」菜单: - 一种是在要调试的云函数目录上右键 ![](https://qcloudimg.tencent-cloud.cn/raw/d58f77738ba62e7b7cdbd938dfa83adb.png) - 一种是在打开的云函数代码编辑器内右键 ![](https://qcloudimg.tencent-cloud.cn/raw/79e2545eccc66ef96ba0daed3a520713.png) ### 3. 设置断点,填参数,点击「运行测试」 等待调试服务启动,即可开始调试 ![](https://qcloudimg.tencent-cloud.cn/raw/91a122d36e2e2220e52b62b6b1d048bc.png) ## 本地开发断点调试方式 ### 配置说明 通过 `vscode` 调试需创建 `.vscode/launch.json` 配置文件,并配置如下参考内容: > 注意:以下配置需要根据文件内注释的描述进行调整 ```json { // Use IntelliSense to learn about possible attributes. // Hover to view descriptions of existing attributes. // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ { "type": "node", "request": "launch", "name": "launch-tcb-ff-global", // 注意:请确保全局安装了 @cloudbase/functions-framework 模块 // npm install -g @cloudbase/functions-framework // 因不同环境下全局安装路径可能不同,需要手动替换 // Windows 系统可通过 `where tcb-ff` 命令查看全局安装路径 // MacOS/Linux 系统下可通过 `which tcb-ff` 命令查看全局安装路径 "program": "please-replace-this-with-the-path-to-your-global-tcb-ff", // 单实例多函数模式下,可通过 --functionsConfigFile 参数指定函数配置文件 "args": ["--functionsConfigFile cloudbase-functions.json"], // 单函数模式下,通过 --source 参数指定函数代码目录,支持 TS/JS 代码 // 注意:--functionsConfigFile 参数会使 --source 参数失效 // "args": ["--source func-abc"], "env": { // 通过 ts-node 可支持直接调试 TS 代码,如不需要可以移除 "NODE_OPTIONS": "--require ts-node/register/transpile-only" }, "skipFiles": ["/**"], "outFiles": ["!**/node_modules/**"] }, { "type": "node", "request": "launch", "name": "launch-tcb-ff-local", // 注意:请确保安装在当前项目下安装了 @cloudbase/functions-framework 模块 // npm install @cloudbase/functions-framework "program": "${workspaceFolder}/node_modules/.bin/tcb-ff", // 直接启动 src 目录下的 ts 函数代码,如需调试编译后的 js 代码,可将 --source 参数替换为编译后的目录 // 单实例多函数模式下,可通过 --functionsConfigFile 参数指定函数配置文件 // 注意:functionsConfigFile 参数会使 --source 参数失效 "args": ["--functionsConfigFile cloudbase-functions.json"], // 单函数模式下,通过 --source 参数指定函数代码目录,支持 TS/JS 代码 // "args": ["--source func-abc"], "env": { // 通过 ts-node 可支持直接调试 TS 代码,如不需要可以移除 "NODE_OPTIONS": "--require ts-node/register/transpile-only" }, "skipFiles": ["/**"], "outFiles": ["!**/node_modules/**"] }, { // 注意:在启动调试进程前,需确保已通过 `NODE_OPTIONS='--inspect=localhost:9229' tcb-ff .` 等调试命令启动了服务 "address": "localhost", "port": 9229, // 配置端口为 9229 "localRoot": "${workspaceFolder}", // 采用 Attach Node.js 进程的方式调试 "name": "attach-to-remote-9229", "request": "attach", "skipFiles": ["/**"], "type": "node" } ] } ``` 以上配置文件中包含了两种类型(`launch/attach` )的三种方式配置: #### 1.【推荐】vscode `launch` 启动 node 进程进行调试 该模式分为两种不同的配置: 1. `launch-tcb-ff-global`:使用全局安装的 `tcb-ff` 运行函数代码 2. `launch-tcb-ff-local`:使用本地安装的 `tcb-ff` 运行函数代码 #### 2. vscode `attach` 方式调试 1. `attach-to-remote-9229`:Attach 到远程 9229 端口的 Node.js 进程 如果采用该方式进行调试,则需要独立运行云函数,相比 `launch` 方式更麻烦,调试步骤如下: 首先,在终端手动执行如下命令: ```sh # 指定调试服务器端口为 9229 NODE_OPTIONS="--inspect=localhost:9229" tcb-ff ``` 然后,在 vscode 中,通过快捷键(`F5`)启动调试进程(或在 `Run And Debug` 界面选择 `Attach to Remote 9229` 启动调试),即可开始进行断点调试。 ### 操作示例 #### 调试 TypeScript 代码 > 本示例演示如何调试 `TS` 编写的函数代码,采用全局安装的 `tcb-ff` 命令,对应配置文件中的 `launch-tcb-ff-global`。 前置条件:通过 `npm install -g @cloudbase/functions-framework` 全局安装 `functions-framework` 模块,包含 `tcb-ff` 命令 1. 通过 `GitClone` 下载示例代码: 2. vscode 打开 `cloudbase-examples/cloudrunfunctions/ts-multiple-functions` 示例代码目录 3. 可通过 `npm/pnpm/yarn` 安装依赖,例如 `pnpm install` 4. 替换 `.vscode/launch.json` 中的 `program` 为全局安装的 `tcb-ff` 路径 5. 开始调试函数代码 可在 `RunAndDebug` 界面启动调试,操作路径按下图所示: ![functions-debug-ts-1.png](./images/functions-debug-ts-1.png) 设置断点,并通过 `curl` 调用触发函数执行,函数会在断点处停止执行: ![functions-debug-ts-2.png](./images/functions-debug-ts-2.png) 可回到 `RunAndDebug` 界面查看此时的函数堆栈信息: ![functions-debug-ts-3.png](./images/functions-debug-ts-3.png) 点击 `调试控制面板` 的 `继续` 按钮,函数即可继续向下执行。 #### 调试 JavaScript 代码 > 本示例演示如何调试 `JS` 编写的函数代码,采用项目本地安装的 `tcb-ff` 命令,对应配置文件中的 `launch-tcb-ff-local`。 1. 通过 `GitClone` 下载示例代码: 2. vscode 打开 `func-v2-template` 示例代码目录 3. 可通过 `npm/pnpm/yarn` 安装依赖,例如 `pnpm install` 4. 开始调试函数代码 按下图所示的路径启动调试 ![functions-debug-js-1.png](./images/functions-debug-js-1.png) 设置断点,并通过 `curl` 调用触发函数执行,函数会在断点处停止执行: ![functions-debug-js-2.png](./images/functions-debug-js-2.png) 可回到 `RunAndDebug` 界面查看此时的函数堆栈信息: ![functions-debug-js-3.png](./images/functions-debug-js-3.png) 点击 `调试控制面板` 的 `继续` 按钮,函数即可继续向下执行。 --- ## 本地开发云函数 # 本地开发云函数 云函数不仅可以运行在 `云端环境` 中,通过云开发提供的 `tcb-ff` 命令行工具,云函数也可以运行在 `本地环境` 中,这样就可以方便的在本地环境进行云函数的开发调试。 相比 `云端环境`,`本地环境` 需要通过 `tcb-ff` 命令先将云函数运行起来,然后再通过 `http` 请求触发云函数执行。 各种发起 `http` 的方式都可以调用云函数,例如 `curl`、`postman` 或者 各编程语言提供的请求库进行调用 等。 本地开发云函数示例项目可参考:[基于函数型云托管的全栈项目](https://github.com/TencentCloudBase/cloudbase-examples/tree/master/cloudrunfunctions/fullstack-project) 以下为如何本地开发云函数的详细步骤,可结合示例项目进行体验。 ## 调用本地运行的云函数 触发云函数的方式主要有: 1. 通过云开发提供的SDK进行调用 1. `@cloudbase/js-sdk` 运行在浏览器环境中,例如 小程序、web 等 2. `@cloudbase/node-sdk` 运行在服务端 `node.js` 环境中,例如云函数中 2. 通过 `curl` 命令行工具进行调用 ### 通过云开发提供的SDK进行调用 如下图所示,图中演示了 通过 `@cloudbase/js-sdk` 调用 `云函数-A`,`云函数-A` 中再通过 `@cloudbase/node-sdk` 调用 `云函数-B` 的场景。 调用链路:客户端(`@cloudbase/js-sdk`) ----> `云函数-A`(`@cloudbase/node-sdk`) ----> `云函数-B` 云开发SDK默认会调用云端环境中运行的云函数,如果需要调用本地运行的云函数,则需要将到云端环境的中请求切换到本地运行的云函数。通过增加一个 `本地代理层`,即可实现将请求转发到本地。 ![call-local-cbrf](./images/call-local-cbrf.svg) * `@cloudbase/node-sdk` 调用云函数的参考文档: * `@cloudbase/js-sdk` 调用云函数的参考文档: 实现对本地运行的云函数的调用,首先需要启动一个 `本地代理层`,将请求转发到本地运行的云函数。 #### 搭建 `本地代理层` 服务 `whistle` 是一个常用的跨平台的网络代理工具,可以实现将请求转发到本地。可以实现上图描述的 `本地代理层` 的功能,将请求转发到本地运行的云函数。 `whistle` 参考: 安装 `whistle`: ```sh npm install -g whistle ``` 启动 `whistle`: ```sh $ w2 start [!] whistle@2.9.94 is running [i] 1. use your device to visit the following URL list, gets the IP of the URL you can access: http://127.0.0.1:8899/ http://10.0.0.123:8899/ http://192.168.0.123:8899/ Note: If all the above URLs are unable to access, check the firewall settings For help see https://github.com/avwo/whistle [i] 2. set the HTTP proxy on your device with the above IP & PORT(8899) [i] 3. use Chrome to visit http://local.whistlejs.com/ to get started ``` 浏览器打开配置页面 ```sh open http://127.0.0.1:8899/ ``` 配置规则(将请求重写到本地): ```sh ^https://*.api.tcloudbasegateway.com/v1/cloudrun/*/* http://127.0.0.1:3000/$3?@fn=$2 ^http://*.api.tcloudbasegateway.com/v1/cloudrun/*/* http://127.0.0.1:3000/$3?@fn=$2 ``` 最后,将浏览器 HTTP 代理配置为 即可,可通过 Chrome 浏览器插件 `ZeroOmega/SwitchyOmega` 配置浏览器代理。 也可以通过配置系统级别的代理进行配置,执行 `whistle` 提供的 `w2 proxy` 命令会配置系统代理。 #### 使用 `@cloudbase/js-sdk` 调用本地运行的云函数 使用 `@cloudbase/js-sdk` 在浏览器环境中调用本地运行的云函数,无需修改任何代码,只需要将浏览器发起的请求转发到本地 `whistle` 代理服务器即可实现调用本地运行的云函数。 例如如下示例的前端代码: ```ts import cloudbase from '@cloudbase/js-sdk' const tcbapp = cloudbase.init({ env: 'your-env-id', clientId: 'your-client-id' }) const auth = tcbapp.auth() await auth.signInAnonymously() // 调用 cloudbaserunfunctions/helloworld 函数 const result = await tcbapp.callFunction({ name: 'helloworld', type: 'cloudrun' }) console.log('result:', result) ``` 完整示例项目代码可查看: #### 使用 `@cloudbase/node-sdk` 调用本地运行的云函数 服务端使用 `@cloudbase/node-sdk` 调用本地运行的云函数,需要 `tcb.init({})` 初始化时,增加 `proxy` 参数,即可将请求转发到本地 `whistle` 代理服务器。 > 注意:通常仅在本地环境中调用本地运行的云函数时,才需要配置 `proxy` 参数。该参数可以通过动态的方式进行配置。 ```ts const tcbapp = tcb.init({ // 这里 Proxy 配置为本地代理层服务 Whistle // Whistle 可以将请求转发到本地运行的云函数 proxy: 'http://127.0.0.1:8899' }) ``` 完整代码: ```ts import tcb from '@cloudbase/node-sdk' exports.main = async (event, context) => { const { httpContext } = context const { url, httpMethod } = httpContext const tcbapp = tcb.init({ // 这里 Proxy 配置为本地代理层服务 Whistle proxy: 'http://127.0.0.1:8899', context: { extendedContext: { tmpSecret: { secretId: 'this-is-a-fak-secretId', secretKey: 'this-is-a-fake-secretKey', } }, ...context, } }) const result = await tcbapp.callFunction({ name: event.otherFuncName, // 函数型云托管 参数 type: 'cloudrun', method: 'POST', path: '/abc', data: { key1: 'test value 1', key2: 'test value 2' } }, { timeout: 5000 }) return { result } } ``` 完整示例项目代码可查看: ### 通过 `curl` 命令行工具进行调用 通过 `curl` 可以直接发起对 云函数的 `http` 请求,无需进行任何配置。 该方式与调用云端运行的云函数时,使用的 云函数默认域名、HTTP访问服务 的方式是类似的。 ```sh # 发送 GET 请求 curl -v -XGET http://localhost:3000/path/to/xxx # 发送 POST 请求 curl -v -XPOST 'http://127.0.0.1:3000/path/to/xxx \ -H 'Content-Type: application/json' \ --data-raw '{"name":"xxxxx"}' # 发送 PUT 请求 curl -v -XPUT 'http://127.0.0.1:3000/path/to/xxx \ -H 'Content-Type: application/json' \ --data-raw '{"name":"xxxxx"}' # 发送 DELETE 请求 curl -v -XDELETE 'http://127.0.0.1:3000/path/to/xxx ``` 一个通过云函数开发AI智能体请求的示例: ```sh curl -XPOST 'http://127.0.0.1:3000/v1/aibot/bots/ibot-xxxx/send-message' \ -H 'Accept: text/event-stream' \ -H 'Content-Type: application/json' \ --data-raw '{"name":"xxxxx"}' ``` 以上是通过 `curl` 发起请求的示例,可以通过任意其他方式发起 `http` 请求,例如 `postman`、`浏览器 fetch`、`node.js http.request` 等。 --- ## 在线开发云函数 # 在线开发云函数 云开发平台提供在线开发云函数的能力,无需配置本地开发环墋,即可在线开发、调试、部署云函数。 ## 进入在线开发环境 通过点击 云函数服务 详情页的 `在线开发` 按钮,即可进入在线开发环境。 ![goto-develop-online](./images/goto-develop-online.png) 进入环境前可能会需要进行云端环境准备 ![cloudstudio-init](./images/cs-cloudstudio-init.png) ## 工作区介绍 进入在线开发环境会,会来到类似如下的一个工作区,该工作区环境的编辑器界面与 `VSCode` 是相同的,支持代码编辑、调试、终端等功能。 下图描述了 `文件浏览器区域` 的主要内容: ![cs-workspace-intro](./images/cs-workspace-intro.png) ### `cloudrunfunctions` 目录 `函数型云托管` 函数代码存放目录为 `cloudrunfunctions`,在此目录上右键,可进行 `函数型云托管` `创建`、`同步列表` 等操作。 ![cs-workspace-cloudrunfunctions](./images/cs-workspace-cloudrunfunctions.png) #### 同步列表 点击 `【函数型云托管】同步列表` 后同步云函数列表,同步完成后,会在下方输出同步状态信息。 ![cs-workspace-sync-cbrf](./images/cs-workspace-sync-cbrf.png) #### 新建云函数 点击 `【函数型云托管】新建` 后,会弹出对话框,输入云函数名称,即可创建云函数。 ![cs-workspace-create-cbrf](./images/cs-workspace-create-cbrf.png) ### `cloudrunfunctions/{函数名}` 目录 `函数型云托管` 的函数代码存放目录为 `cloudrunfunctions/{函数名}`,在此目录下,可进行 `调试`、`部署` 等操作。 ![cs-workspace-cbrf-op](./images/cs-workspace-cbrf-op.png) #### 编写云函数代码 可在在线编辑器界面进行代码编写。如何编写 `函数型云托管` 的代码,可参考 [函数编写指南](./how-to-writing-functions-code)。 #### 运行云函数代码 在线开发环境支持集成终端,可通过终端运行云函数代码。 ![cs-use-integrated-terminals](./images/cs-use-integrated-terminals.png) 启动成功之后,可通过右下角打开浏览器。 #### 调试云函数 函数代码编写完成后,点击 `【函数型云托管】调试`,即可启动调试。 ![cs-workspace-debug-cbrf](./images/cs-workspace-debug-cbrf.png) 如启动调试出现错误,可通过控制台输出查看错误原因,并进行修复。 调试完成之后,即可进行云函数的部署。 --- ## 如何调用TCB云开发的其他能力? # 如何调用TCB云开发的其他能力? 如 TCB云函数环境中运行的 函数代码 一样,可以在 `函数型云托管` 环境中使用 [@cloudbase/node](https://docs.cloudbase.net/api-reference/server/node-sdk/introduction) 调用 TCB的其他能力,如数据库、存储等,当然也可以调用云函数。 因 `函数型云托管` 同 `云函数` 运行式环境存在一定的差异,`@cloudbase/node` 在使用上存在细微差异,在 SDK 的初始化时,需要传入 `context` 参数,如下所示: ```ts import { TcbEventFunction } from '@cloudbase/functions-typings' export const main: TcbEventFunction = function(event, context) { // 注意:因依赖 context 参数,所以必须放在 `main` 函数内部,不要缓存 tcbapp 实例,该实例仅有有限的有效期。 const tcbapp = tcb.init({ context: context, env: 'abc-xyz', // 指定调用的环境Id,如果不传 `env` 则调用当前环境 }) tcbapp.uploadFile({cloudPath: '', fileContent: Buffer.from('')}) // ... return 'done' } ``` 传入 `context` 参数后,`@cloudbase/node` 即可调用 TCB云开发的相关能力。 ## 完整示例代码 ```ts import { TcbEventFunction } from '@cloudbase/functions-typings' import tcb from '@cloudbase/node-sdk' async function sleep (time: number) { return await new Promise(resolve => { setTimeout(() => { resolve(undefined) }, time) }) } async function uploadFile (tcbapp: tcb.CloudBase) { const result = await tcbapp.uploadFile({ cloudPath: ' hello world 你好 世界 .png', fileContent: Buffer.from(' hello world 你好 世界 ') }) return await tcbapp.getTempFileURL({ fileList: [result.fileID] }) } async function runCmdWithCloudbaseNodeSDK (tcbapp: tcb.CloudBase) { const result = await tcbapp .database() .collection('articles') .where({ _id: 'not-exists-id' }) .options({ multiple: true }) .update({ 'a.b.c': 'a.b.c' }) return result } export const main: TcbEventFunction = function(event, context) { console.log({ event, context }) const tcbapp = tcb.init({ context }) // 调用 云函数 try { const result = await tcbapp.callFunction({ name: 'test', data: { a: 1 } }) console.log(result) } catch (e) { console.error(e, 'callFunction.error') return e } // 上传文件 try { const result = await uploadFile(tcbapp) console.log(result, 'uploadFile.result') } catch (e) { console.error(e, 'uploadFile.error') return e } // 调用数据库 try { const result = await Promise.all([ runCmdWithCloudbaseNodeSDK(tcbapp) ]) console.log(result, 'run.result') } catch (e) { console.error(e, 'e') return e } await sleep(3) return 'done' } ``` --- ## 如何迁移云函数代码到云托管 # 如何迁移云函数代码到云托管 如果需要将原有的云函数代码迁移到函数型云托管,可以参考如下内容,了解到需要做的一些变更。 ## 函数代码编写的调整 ### 函数入口函数差异 云函数写法: ```js export const main = function(event, context) {} ``` 函数型云托管写法: ```js export const main = function(event, context) {} ``` 两种函数的入口函数格式是一致的,参数内容格式存在一定差异: * `event`:云函数触发时传入的事件参数,两种函数基本一致,`函数型云托管` 支持更多类型的入参格式 * `context`:云函数运行时的上下文参数,两种函数完全不同 因此,如果你在云函数中使用了 `context` 参数,迁移到函数型云托管时可能需要进行一定的调整。 ### 函数返回值差异 ### `@cloudbase/node-sdk` 使用差异 云函数写法: ```js import tcb from '@cloudbase/node-sdk' // tcb.init 可以写在入口函数外 tcb.init({ env: 'abc-xyz' }) export const main = function(event, context) { // tcb.init 可以写在入口函数内 const tcbapp = tcb.init({ env: 'abc-xyz' }) // ... return 'done' } ``` 函数型云托管写法: ```js import tcb from '@cloudbase/node-sdk' export const main = function(event, context) { // tcb.init 需要写在入口函数内,因依赖 context 参数,所以必须放在 `main` 函数内部 const tcbapp = tcb.init({ context: context, env: 'abc-xyz' }) // ... return 'done' } ``` 在函数型云托管中,`tcb.init` 需要传入的 `context` 参数获得相关信息,所以在使用时需要将 `tcb.init` 放在 `main` 函数内。 如何在函数型云托管中使用 `@cloudbase/node-sdk` 相关能力,可参考 [如何调用TCB云开发的其他能力?](./how-to-invoke-tcb.md) 文档。 ## 目录结构的调整 云函数代码目录结构示例: ```bash function_nodejs / - index.js - package.json ``` 函数型云托管代码目录结构示例 * 单服务内包含一个函数逻辑: ```bash runfunction_nodejs / - index.js - package.json ``` * 单服务内包含多个函数逻辑: ```bash runfunction_nodejs / - cloudbase-functions.json # 多函数配置文件 - cloudrunfunctions/funcA # 函数 A 目录 - index.js - cloudrunfunctions/funcB # 函数 B 目录 - index.mjs - package.json # 指定 index.mjs 为入口文件 ``` 在函数型云托管中,既可以按原有函数目录方式组织代码,也可以将多个函数逻辑整合在一个云托管服务中。 在实际使用中,更加建议**将多个函数整合在一个服务中**。这种方式可以充分利用云托管服务的运行实例资源,降低冷启动,同时简化服务管理。 ## 调用函数的方法调整 在小程序中调用云函数的方法示例: ```js wx.cloud .callFunction({ // 云函数名称 name: "hello_world", // 传给云函数的参数 data: { a: 1, b: 2, }, }) .then((res) => { console.log(res.result); // 3 }) .catch(console.error); ``` 在小程序中调用函数型云托管的方法示例: * 单服务内包含一个函数逻辑: ```js // 容器调用必填环境id,不能为空 const c1 = new wx.cloud.Cloud({ resourceEnv: "环境id", }); await c1.init(); const r = await c1.callContainer({ path: "/", // 填入业务自定义路径 header: { "X-WX-SERVICE": "xxx", // 填入服务名称 }, // 其余参数同 wx.request method: "POST", }); console.log(r); ``` * 单服务内包含多个函数逻辑: ```js // 调用必填环境id,不能为空 const c1 = new wx.cloud.Cloud({ resourceEnv: '环境id' //填入云开发环境 id }) await c1.init() const r1 = await c1.callContainer({ path: '/', // 默认函数对应的请求路径 header: { 'X-WX-SERVICE': 'testfunc2', // 填入创建时的函数名称 testfunc2 }, // 其余参数同 wx.request method: 'GET', }) console.log(r1) //输出 Hello world! const r2 = await c1.callContainer({ path: '/echo', // echo 函数对应的请求路径 header: { 'X-WX-SERVICE': 'testfunc2', // 填入创建时的函数名称 testfunc2 }, // 其余参数同 wx.request method: 'POST', data: { a: 1, b: 2 } }) console.log(r2) //输出具体请求及时间 ``` 更多的函数型云托管的调用方法可见[文档](https://docs.cloudbase.net/cbrf/how-to-writing-functions-code#%E7%AC%AC%E4%B8%89%E6%AD%A5%E8%B0%83%E7%94%A8%E5%87%BD%E6%95%B0)。 --- ## 函数编写指南 # 函数编写指南 本文介绍如何编写基于 `@cloudbase/functions-framework` 的函数代码,如何进行错误处理,以及函数结构、出入参等基本信息,并提供一系列的示例以供参考。 ## 快速开始 ### 第一步:编写函数 1. 在本地创建一个空的文件夹,作为项目的根目录。 2. 新建 `index.js` 文件,作为函数的入口文件。 3. 在`index.js` 文件中,填写以下内容: ```js exports.main = function (event, context) { const { httpContext } = context; const { url, httpMethod } = httpContext; return `[${httpMethod}][${url}] Hello world!`; }; ``` 以上即为一个简单的函数代码示例,函数的入口函数为 `main`,函数的输入参数为 `event` 和 `context`,函数的返回值为 `字符串`。 - 更多函数示例可参考: - - - 模板代码可参考: - JavaScript: - TypeScript: - 如何调试函数代码可参考: - 当前代码为简单的函数示例,`函数型云托管` 在框架层面支持 `单实例多函数及函数路由`,即多个函数跑在同一个函数实例上,具体可参考:[单实例多函数及函数路由](#单实例多函数及函数路由) ### 第二步:运行函数 云函数代码编写完毕后,既可以将函数运行起来,之后便可以通过 HTTP 请求来调用函数。 运行函数的方式有两种: #### 1. 通过命令行工具本地运行,通常在开发调试阶段 首先需要全局安装 `tcb-ff` 命令行工具: ```sh npm install -g @cloudbase/cli ``` 在函数代码根路径下执行以下命令,即可本地运行函数: ```sh tcb cloudrun run ``` #### 2. 部署在云托管环境中 可在云开发平台创建 `函数型云托管` 服务,部署函数代码。 将代码部署到 `函数型云托管` 可跳转 [云开发平台](https://tcb.cloud.tencent.com/dev) ### 第三步:调用函数 #### 1. 调用本地运行的函数 本地可以通过 `curl` 命令或其他 HTTP 请求工具来调用本地运行的云函数。 函数框架加载并运行云函数后,默认会监听 `http(3000)` 端口,可以通过 `http` 调用触发云函数执行。 ```sh # 发送 GET 请求 curl -v -XGET http://localhost:3000/path/to/xxx # 发送 POST 请求 curl -v -XPOST 'http://127.0.0.1:3000/path/to/xxx \ -H 'Content-Type: application/json' \ --data-raw '{"name":"xxxxx"}' # 发送 PUT 请求 curl -v -XPUT 'http://127.0.0.1:3000/path/to/xxx \ -H 'Content-Type: application/json' \ --data-raw '{"name":"xxxxx"}' curl -v -XDELETE 'http://127.0.0.1:3000/path/to/xxx ``` 函数型智能体请求示例: ```sh curl -XPOST 'http://127.0.0.1:3000/v1/aibot/bots/ibot-xxxx/send-message' \ -H 'Accept: text/event-stream' \ -H 'Content-Type: application/json' \ --data-raw '{"name":"xxxxx"}' ``` 如上请求示例,`@cloudbase/functions-framework` 支持 `GET` 、`POST`、`PUT`、`DELETE` 等请求方式,同时也支持指定路径。 #### 2. 调用云端环境中运行的函数 因为 `云端环境中运行的函数` 是基于云托管的,因此,可以通过调用云托管服务的方式来调用函数。 1. 通过 `服务域名` 进行调用,在 `函数型云托管服务页面` 可以查询到域名信息。 2. 通过 `HTTP访问服务` 进行调用,在 `访问服务页面` 配置路由后关联到对应资源后,即可进行调用。 3. 通过 `开放API` 进行调用,可参考:。 4. 通过 `SDK` 进行调用 1. 服务端 `@cloudbase/node-sdk` 调用,可参考: 1. `callFunction`: 2. `callContainer`: 2. 浏览器 `@cloudbase/js-sdk` 调用,可参考: 1. `callFunction`: 2. `callContainer`: 3. 微信小程序可通过 `wx.cloud.callContainer` 方式进行调用,见:[Cloud.callContainer](https://developers.weixin.qq.com/miniprogram/dev/wxcloud/reference-sdk-api/container/Cloud.callContainer.html) ##### 2.1 微信小程序中通过 `callContainer` 调用示例 ```ts // 容器调用必填环境id,不能为空 const c1 = new wx.cloud.Cloud({ resourceEnv: "环境id", }); await c1.init(); const r = await c1.callContainer({ path: "/", // 填入业务自定义路径 header: { "X-WX-SERVICE": "xxx", // 填入服务名称 }, // 其余参数同 wx.request method: "POST", }); console.log(r); ``` 通过该方式调用,您可以省去配置自定义域名、证书等操作,快速调用函数,并获得微信私密链路的安全性提升。 更多信息可参考 `wx.cloud.callContainer` 相关文档: - [wx.cloud.callContainer 技术原理和使用指南](https://developers.weixin.qq.com/miniprogram/dev/wxcloudrun/src/practice/call.html) - [Cloud.callContainer](https://developers.weixin.qq.com/miniprogram/dev/wxcloud/reference-sdk-api/container/Cloud.callContainer.html) ##### 2.2 通过 `服务域名` 进行调用 在 `函数型云托管服务页面` 可以查询到域名信息,以下示例为默认域名: ```sh curl -v -XGET https://{}.run.tcloudbase.com/ ``` ##### 2.3 通过 `HTTP访问服务` 进行调用 在 `访问服务页面` 配置路由后关联到对应资源后,即可进行调用,以下示例为默认域名: ```sh curl -v -XGET https://{}.app.tcloudbase.com/ ``` ## 了解函数 本部分内容主要介绍函数的 `基本结构`、`输入输出`、`错误处理`、`函数日志` 等内容。 云开发提供了 `入口main函数` 的 `TypeScript` 类型定义 `@cloudbase/functions-typings@v-1` 辅助代码编写,可参考:[函数类型定义](#使用-typescript-编写函数代码) ### 函数的输入参数 `event` 和 `context` 函数的基本结构如下: ```js exports.main = function (event, context) { // 函数逻辑 }; ``` 或 ```js exports.main = async function (event, context) { // 函数逻辑 }; ``` 该文件导出一个 `main` 函数,该函数即为函数的入口方法,当请求到达时,该方法会作为代码执行的起点。该方法接受两个固定的参数 `event` 和 `context`,分别代表函数的输入和上下文。 其中,`event` 为函数的触发事件,在当前的 HTTP 访问场景下,可以认为是 HTTP 请求体,例如 `POST` 请求的 `body`,`multipart/form-data` 请求的 `form-data`,`PUT` 请求所传输的二进制文件等。如果 HTTP 请求没有传递请求体,`event` 将会是一个空对象。 `context` 为函数执行的上下文信息,包含以下属性和方法: | Name | 类型 | 含义 | | --------------- | ------------------------- | ----------------------------------------------- | | eventID | `string` | 事件唯一标识,用于关联上下文 | | eventType | `string` | 事件类型,当前固定为 `http` | | timestamp | `number` | 请求时间戳 | | httpContext | `httpBasis` | HTTP 请求的相关信息 | | extendedContext | `Record` | 扩展的上下文信息,平台提供,包含 环境相关信息 | | sse() | `ISeverSentEvent` | 返回用于发送 `Server-Sent Event` 格式响应的对象 | `httpBasis` 定义如下: | 名称 | 类型 | 含义 | | ---------- | --------------------- | ------------------------------ | | url | `string` | 本次请求的完整 URL | | httpMethod | `string` | 本次请求的 HTTP 方法,如 `GET` | | headers | `IncomingHttpHeaders` | 本次请求的 HTTP 头部 | 其中,从 `extendedContext` 中可以获得以下属性: ```ts // import { TcbExtendedContext } from '@cloudbase/functions-typings' interface TcbExtendedContext { envId: string; // 环境 ID uin: string; // 请求的 UIN source: string; // 请求来源,如 wx serviceName: string; // 服务名称 serviceVersion: string; // 服务版本 authMethod?: string; // 认证方式 UNAUTHORIZED | CAM_TC3 | TCB_OAUTH2_B | TCB_OAUTH2_C | WX_SERVER_AUTH userType?: string; // 用户类型 NONE | B_SIDE_USER | C_SIDE_USER isAdministrator?: boolean; // C 端用户(C_SIDE_USER)是否为管理员 accessToken?: string; // 调用请求时的 AccessToken userId?: string; // 请求的用户 ID tmpSecret?: { // 临时凭证 secretId: string; // secretId secretKey: string; // secretKey token: string; // token }; wechatContext?: { // 微信上下文信息 callId: string; // 微信调用 ID source: string; // 请求来源,如 wx appId: string; // 访问小程序的 AppID openId: string; // 访问用户的 OpenID unionId: string; // 访问用户的 UnionID fromOpenId?: string; // 环境资源共享时的 fromOpenID fromUnionId?: string; // 环境资源共享时的 fromUnionID fromAppId?: string; // 环境资源共享时的 fromAppID }; } ``` 云函数支持 `SSE(Server-Sent Event)` 格式的响应,通过调用 `sse()` 即可以切换到 `SSE` 模式并得到 `ISeverSentEvent` 实例。 ```ts interface ISeverSentEvent { setEncoder(encoder: TextEncoder): void; send(event: SseEvent): boolean; end(msg: SseEvent): void; } interface SseEvent> { data: T; comment?: string; event?: string; id?: string; retry?: number; } ``` 可以通过 `send()` 方法来发送 SSE 响应,例如: ```js const { sse } = context; sse.send({ data: "Hello world!", }); ``` 更多 `SSE` 使用示例可参考:[使用-server-sent-event-推送消息](./example#使用-server-sent-event-推送消息) 当函数执行完毕(即从入口函数返回)时,返回值将会被直接返回给客户端,不会进行额外的序列化处理。 ### 函数的输出(即返回值) 函数执行最后的返回值将作为最终返回值返回给客户端,此时,将使用 `默认的HTTP状态码`(如正常返回时`200`、未带有响应体时`204`、抛出异常时`500`)和 `默认的HTTP响应头` 返回给客户端。 函数支持 `同步`、`异步` 模式,支持 `普通类型` | `Promise` 的返回值。可以返回 `Buffer | Stream` 类型的返回值,实现下载文件的能力。 > 注意:函数返回后,仍可能会有异步操作在后台执行。 函数的返回值可以支持 `普通响应` 和 `集成响应` 两种形式。 函数框架通过返回值的格式来区分两种类型的响应,如果返回值格式为 `{statusCode: number, headers: { [key: string]: string | string[] }}` 即会被判定为 `集成响应`,其他均为 `普通响应`。 #### 普通响应 `普通响应` 直接将 `返回值` 完整的返回给客户端。 #### 集成响应 通过集成响应,可以自定义 HTTP 响应的结构,包括响应状态码、头部字段等,可以采用集成响应的返回结构。集成响应的定义如下: ```ts interface IntegrationResponse { statusCode: number; headers: { [key: string]: string | string[] }; body?: unknown; } ``` `statusCode` 为 HTTP 响应状态码,`headers` 为自定义的 HTTP 响应头部,`body` 为 HTTP 响应体。例如返回下面的集成响应: ```js exports.main = function (event, context) { return { statusCode: 200, headers: { "Content-Type": "text/html", }, body: { message: "Hello world!", }, }; }; ``` 将可以在浏览器中渲染出 HTML。 ### 错误处理 函数运行过程中可能或抛出异常,异常整体可以分为以下几类: 1. 不可恢复的错误:如启动时未加载成功代码、Out of Memory(OOM)、堆栈溢出,这类错误会导致函数无法启动或从运行中退出,此类错误是严重错误,会导致函数实例重启,应当尽量规避; 2. 请求处理过程中的错误:这类错误通常是可捕获的,函数需要对这些错误进行处理,记录相关日志并返回相关信息给客户端。如果用户代码未捕获相关异常,函数框架将会捕获该错误,记录相关日志并返回框架定义的错误信息给客户端; 3. 未被捕获的异常 `UncaughtException` 和 `UnhandledRejection`:通常发生在异步代码逻辑中,因为是未捕获异常,业务上是感知不到的,这类错误会被框架捕获,并打印相关信息到日志中。因为通常发生在异步逻辑中,该错误不会体现在函数返回值中; 4. 函数框架报错:函数框架内部可能发生一些错误,可能是函数框架代码存在 Bug,也可能是函数框架的限制,这类错误会被框架捕获,并打印相关信息到日志中; 5. 网络错误:在客户端往返函数实例的网络链路中也可能出现异常,导致一些错误。该类错误非云函数本身的错误,需结合具体部署平台进行排查。 ### 函数的模块化和依赖安装 如通常的 `Node.js` 代码一样,函数也可以通过 `Javascript` 模块化方式来组织代码。对于遵循 `CommonJS` 规范的模块,可以通过 `require` 来引入依赖。例如: ```js // index.js const { add } = require("./sum"); exports.main = function (event, context) { return add(1, 2); }; // sum.js exports.add = function (a, b) { return a + b; }; ``` 对使用 `ECMAScript` 模块化(需在 `package.json` 中声明模块化方式)的代码,可以通过 `import` 语句来引入依赖。例如: ```js // index.mjs import { add } from './sum.mjs' export function main(event, context) { return add(1, 2) } // sum.mjs export function add(a, b) { return a + b } // package.json { "name": "example", "version": "1.0.0", "main": "index.mjs", // 指定入口文件 "type": "module", // 声明模块化方式 "dependencies": { } } ``` 对于外部依赖安装,可在 `package.json` 中声明依赖,函数构建时会根据依赖声明自动安装依赖包。如果目录下存在 `package-lock.json` 等 lock 文件,可以起到锁定依赖版本的作用。 对于通过云托管部署的云函数,构建过程支持 `npm` 、`yarn`、`pnpm` 包依赖管理工具,会识别代码使用的包管理工具进行依赖安装。 ### 函数日志 在函数代码中打印的日志可以分为两类,一类是函数实例级别日志,即主入口函数之外的日志,这部分日志在函数实例启动时、模块被加载时被打印,跟某次具体的请求无关;另一类是请求级别日志,即某次请求触发、代码执行流程进入主入口函数内部之后才会打印的日志,这部分日志往往跟某次具体的请求相关联,一般可以通过请求的 `eventID` 搜索得到。 请求级别的日志从内容上划分,又可以分为以下几类: 1. 每次请求自动打印的结构化访问日志(access log),包括该次请求的基本信息,如处理请求的主机名、访问的 URL、请求方法、响应结果、请求处理耗时等; 2. 函数代码中主动打印的日志,即代码中使用 `console.log` 等方法打印的日志,这部分日志会跟 `eventID` 所关联,有助于排查某次请求的具体执行流程; 3. 函数框架捕获的异常日志,如 `UncaughtException` 和 `UnhandledRejection` ,这部分日志会自动跟 `eventID` 关联,并打印出异常的堆栈信息等便于排查问题。 日志的逻辑级别如下所示: ```text 函数日志 ├── 函数实例日志 ├── 请求级别日志 │ ├── 访问日志 │ ├── 函数代码中打印的日志 │ ├── 框架捕获的异常日志 ``` 日志内容记录位置 `{process.env.CWD}/logs/`,具体内容如下: - `{process.env.CWD}/logs/accesslog*.log`:访问日志,每次函数调用都会有一条日志 - `{process.env.CWD}/logs/usercodelog*.log`:函数代码中打印的日志,可通过 `RequestID` 关联到每一次请求 - `stdout`:标准输出日志,内容包括:函数实例日志、框架捕获的异常日志,以及函数框架打印的日志 例如下面的函数代码: ```js // 函数实例日志 console.log("func initialization started."); // 函数实例日志 setTimeout(() => { console.log("timeout log."); }, 1000); exports.main = function (event, context) { // 请求级别日志 console.log({ event, context }); setTimeout(() => { throwReject(); }, 1000); return "Hello world"; }; async function throwReject() { // 这里会触发未捕获的异常,因为没有捕获,会被框架捕获 // 该异常在 main 中 setTimeout 中抛出,因此不会体现在 main 的返回值中 // 该异常由 函数框架捕获并打印到日志中 Promise.reject(new Error("This is an error.")); } // 函数实例日志 console.log("func initialization finish."); ``` 在函数实例启动时,`App started.` 会被打印。请求到达并处理完毕后,客户端会收到 `Hello world` 响应,1s 后该请求抛出异常被框架捕获,这次请求的访问日志形如: ```json { "@timestamp": "2024-xx-xxTxx:xx:xx.xxxZ", // 日志打印的时间戳 "startAt": "2024-xx-xxTxx:xx:xx.xxxZ", // 请求开始处理的时间 "endAt": "2024-xx-xxTxx:xx:xx.xxxZ", // 请求处理结束的时间 "logType": "accesslog", // 日志类型 "hostname": "host", // 处理请求的主机名 "pid": 13506, // 进程 ID "version": "x.y.z", // 函数框架版本 "nodeEnv": "", // Node.js 相关的环境变量 "tcbEnv": "", // 云开发相关的环境变量 "eventId": "b0900934-79d7-4441-856f-dd46392a5f91", // 本次请求的 eventID "method": "GET", // 请求方法 "url": "http://127.0.0.1/", // 请求 URL "path": "/", // 请求路径 "status": 200, // 响应状态码 "httphost": "127.0.0.1", // 请求的主机名 "ua": "PostmanRuntime/7.39.0", // 请求的 User-Agent "connection": "keep-alive", "contentType": "application/json", // 请求的 Content-Type "clientIp": "::1", // 请求的客户端 IP "resSize": 12, // 响应体大小 "resContentType": "text/plain", // 响应的 Content-Type "timeCost": 11, // 本次请求的总耗时 "userTimeCost": 0 // 从函数主入口开始到从入口返回的耗时 } ``` 随后异常会被框架捕获,可通过 `eventID`(`b0900934-79d7-4441-856f-dd46392a5f91`) 关联,并打印出如下堆栈: ```text Unhandled Rejection for: Error: This is an error. at throwReject (/path/to/your/project/index.js:9:18) at Timeout._onTimeout (/path/to/your/project/index.js:4:22) ``` > 注意:日志对于问题排查是非常重要的,建议在函数代码中适当打印日志,以便排查问题。 > 但是打印大量日志将会带来其他问题,如日志消耗磁盘空间可能导致磁盘可用空间不足,日志采集组件采集解析文件消耗较多 CPU,日志上报到存储系统会消耗大量网络带宽,存储大量日志导致成本增加,日志写入和查询性能下降延迟高等诸多问题,因此建议适度打印日志。 ## 函数路由 函数框架在框架层面支持将一个 `大函数` 拆分成多个 `子函数`,并支持通过配置请求 `path` 将不同的请求路由到不同函数上。 基于函数路由能力,可以方便的将多个函数合并为一个大函数并部署在同一个云托管服务上,可以实现资源共享、较少资源消耗、节约成本。 要使用函数路由能力,需要添加命名为 `cloudbase-functions.json` 的配置文件,对不同函数进行声明,并进行路由配置。 `cloudbase-functions.json` 文件说明: ```ts export interface FunctionDefinition { name: string; // 函数名称 directory: string; // 函数目录,相对于函数 functionsRoot 的路径 source?: string; // 函数入口文件,默认为 index.js target?: string; // 入口函数名称,默认为 main triggerPath?: string; // 匹配的路径,前缀匹配,与 RouteDefinition 中的 path 作用相同,简化配置 } export interface RouteDefinition { functionName: string; // 目标函数名称,与 FunctionDefinition 中的 name 对应 path?: string; // 匹配的路径,前缀匹配,匹配后会调用 functionName 对应的函数 } export interface FunctionsConfig { functionsRoot: string; // 函数根目录,会到此目录下查找并加载函数 functions: FunctionDefinition[]; // 函数定义,描述函数信息,包括函数名称、目录、入口文件等 routes: RouteDefinition[]; // 路由定义,即 path -> functionName } ``` 函数路由规则说明: 1. 路由匹配为前缀匹配模式,如:请求路径 `/a`、`/a/b`、`/a/b/c` 均可匹配 `path=/a` 的路由规则 2. 路由匹配遵循最长匹配原则,即匹配到最长的路由规则,例如 `/a/b/c` 会优先匹配 `/a/b` 而不会匹配 `/a` 3. 路由规则中 `path` 末尾带 `/` 的和不带 `/` 的路由匹配效果相同,例如 `/aa` 和 `/aa/` 是等价的,但不会被认为是冲突的 4. 路由匹配以 `/` 分隔为路径单元,路径单元需精确匹配,如 `/aaa` 不会匹配 `/a -> functionA` 规则 5. 一个函数可以有多个路由,即可以通过多个不同路径规则触发同一个函数,例如 `/a1` 和 `/a2` 可配置都触发 `a` 函数 6. 同一个路由只能指向一个函数,例如:`/a` 只能指向一个函数,不能同时指向 `a` 和 `b` 函数 编辑器支持:使用 VSCode 开发时,可以在 `.vscode/settings.json` 中声明如下配置以获得 `cloudbase-functions.json` 的 schema 提示: ```json { "json.schemas": [ { "fileMatch": ["cloudbase-functions.json"], "url": "./node_modules/@cloudbase/functions-framework/functions-schema.json" } ] } ``` ### 示例 假设有如下目录结构: ```shell . ├── cloudbase-functions.json # 多函数配置文件 ├── index.js # 默认函数入口文件 ├── echo # 函数 echo │ └── echo.js # 函数 echo 入口文件 ├── sse # 处理 SSE 请求的函数 sse │ ├── index.mjs │ └── package.json ├── sum # 函数 sum │ ├── index.js │ ├── package.json │ └── sum.js └── ws # 处理 websocket 请求的函数 ws ├── client.mjs ├── index.mjs └── package.json ``` 在 `cloudbase-functions.json` 配置文件中,需要对 `默认函数(index.js)`、`echo`、`sse`、`sum`、`ws` 等函数进行声明和路由,配置文件如下: ```json { "functionsRoot": ".", // 函数根目录,指定为当前目录 "functions": [ // 声明各函数及其入口文件 { "name": "default", // 声明默认函数,即入口为 index.js 的函数 "directory": "." // 函数目录为当前目录 }, { "name": "echo", // 声明函数 echo "directory": "echo", // 声明 echo 函数所在目录为 echo (相对于函数根目录) "source": "echo.js", // 函数入口文件为 echo.js "triggerPath": "/echo" // 函数触发路径,即请求 path 匹配 /echo 时,路由至函数 echo }, { "name": "sum", // 声明函数 sum "directory": "sum" }, { "name": "ws", // 声明函数 ws "directory": "ws" }, { "name": "sse", // 声明函数 sse "directory": "sse" } ], "routes": [ // 声明路由规则,可通过 triggerPath 方式简化路由规则配置 { "functionName": "sum", // 路由至函数 sum,名称需要与上述定义的函数名称对应 "path": "/sum" // 满足请求 path 前缀匹配 /sum 条件的请求匹配该规则 }, // path 前缀匹配 /echo 的请求路由至函数 echo { "functionName": "echo", "path": "/echo" }, // path 前缀匹配 /ws 的请求路由至函数 ws { "functionName": "ws", "path": "/ws" }, // path 前缀匹配 /sse 的请求路由至函数 sse { "functionName": "sse", "path": "/sse" }, // 请求默认匹配到 default 函数 { "functionName": "default", "path": "/" } ] } ``` 使用该配置文件启动服务,根据路径的不同,请求会被路由至不同的函数: - path 前缀匹配 `/sum` 时,路由至函数 `sum` - path 前缀匹配 `/echo`时,路由至函数 `echo` - path 前缀匹配 `/ws` 时,路由至函数 `ws` - path 前缀匹配 `/sse` 时,路由至函数 `sse` - 未能匹配任一规则的请求,路由至函数 `default` ## 使用 `TypeScript` 编写函数代码 相比 `JavaScript` 通过 `TypeScript` 编写代码可以获得诸多好处,例如: - `更好的开发体验`:编辑器可以提供更好的代码补全、重构和导航功能。这使得开发过程更加高效 - `语法特性`:`TypeScript` 支持最新的 `ECMAScript` 特性,如装饰器、泛型、异步函数等 - `静态类型检查`:可以在编译时捕获类型错误,减少运行时错误,提高代码的可靠性 - `接口和类型别名`:`TypeScript` 支持接口和类型别名,允许开发者定义复杂的数据结构。这使得代码更加模块化和可重用 - `可读性和可维护性`:通过明确的类型定义,`TypeScript` 代码通常更易于理解和维护 - `更好的文档`:类型定义本身可以作为文档,帮助开发者理解函数和模块的用法,而不需要额外的文档 推荐使用 `TypeScript` 编写函数代码,尤其是相对复杂一点儿的项目中。 ### TS 类型定义 云函数入口的格式是在入口文件导出一个 `main` 函数,如: ```ts // index.ts export const main = function(event, context) {} // 等价于 export const main = function(event: any, context: any) any {} ``` 如上示例的函数声明中,函数入参 `event`, `context` 以及 `函数的返回值` 均为 `any` 类型。 参数和返回值类型不明确,导致没有良好的基于类型的代码补全能力,也没有类型检查的约束能力,不利于代码的维护和调试。 针对以上 `参数和返回值` 类型的不同特点: - `event` 是由业务逻辑定义的,需根据业务需要进行类型定义,并指定 - `context` 是云函数框架提供的,由函数框架定义 - `函数的返回值` 也是由业务逻辑定义的,需根据业务需要进行类型定义,并指定 云函数框架提供了云函数的入口函数类型定义,可以增强对参数和返回值类型的感知和约束能力。 可以通过安装 `@cloudbase/functions-typings` 包来获取云函数的入口函数类型定义: ```sh npm install @cloudbase/functions-typings@v-1 ``` 安装完成后,即可在函数代码中引入云函数的入口函数类型定义: ```ts import { TcbEventFunction } from "@cloudbase/functions-typings"; ``` 如上示例中导入的 `TcbEventFunction` 为云函数的入口函数类型定义,支持定义函数的 `event` 和 `context` 参数类型,以及函数的 `返回值` 类型。 该类型是一个泛型类型 `TcbEventFunction` 1. 通过 `EventT` 可定义 `event` 参数的类型 2. 通过 `ResultT` 可定义函数的 `返回值` 的类型 这两个类型具有业务逻辑决定,这里开放了灵活的定义方式。 #### 定义函数的 `event` 参数类型 可通过 `TcbEventFunction` 的第一个泛型参数 `EventT` 来指定函数 `event` 参数的类型。 如下为定义 `event` 参数类型一个示例: ```ts type jsonEvent = {a: number, b: string, c: boolean, d: {e: string}} export const main: TcbEventFunction = function(event, context) { event.a event.b } ``` 如果是通过 `FormData` 方式进行文件上传,函数框架会将文件上传时对应的字段放在 `event` 入参的对应字段中,类型为 `File` 类型,用于描述文件信息,例如文件名称、文件大小、文件路径等。 可通过如下示例的方式定义包含文件 `File` 的 `event` 参数类型: ```ts import { TcbEventFunction, File } from "@cloudbase/functions-typings"; type formEvent = { str: string; file: File }; export const main: TcbEventFunction = function (event, context) { event.str; event.file.filepath; }; ``` #### 定义函数的 `返回值` 类型 可通过 `TcbEventFunction` 的第二个泛型参数 `ResultT` 来指定函数的返回值类型。 函数返回值支持 [`普通响应`](#普通响应) 和 [`集成响应`](#集成响应) 两种类型。 普通响应直接指定具体类型即可,普通响应类型示例: ```ts import { TcbEventFunction } from "@cloudbase/functions-typings"; // 普通响应-有返回值,返回值类型为 string // ReturnT = string export const main: TcbEventFunction = function (event, context) { return "done."; }; ``` 集成响应可通过 `IntegrationResponse` 进行定义,通过 `BodyT` 可以定义响应体类型,如下示例: ```ts import { TcbEventFunction, IntegrationResponse, } from "@cloudbase/functions-typings"; // 集成响应,返回值 body 类型为 string // ReturnT = IntegrationResponse export const main: TcbEventFunction > = function (event, context) { return { statusCode: 200, headers: {}, body: "", }; }; ``` 函数的返回值类型支持 `Promise` 类型,如 `ReturnT = Promise` 或 `ReturnT = Promise>` 如下风格的函数定义,也可以指定类型,但是会略麻烦,推荐使用如上描述的风格。 ```ts export function main(event, context) {} ``` ### 完整示例 ```ts import { TcbEventFunction, File, IntegrationResponse, } from "@cloudbase/functions-typings"; // GET no boyd export const main: TcbEventFunction = function (event, context) {}; // Content-Type: application/json type jsonEvent = { a: number; b: string }; export const main: TcbEventFunction = function (event, context) { event.a; event.b; }; // Content-Type: multipart/form-data type formEvent = { str: string; file: File }; export const main: TcbEventFunction = function (event, context) { event.str; event.file.filepath; }; // Content-Type: application/octet-stream export const main: TcbEventFunction = function (event, context) { event.byteLength; }; // 访问 Context 信息 export const main: TcbEventFunction = function (event, context) { context.extendedContext?.envId; context.extendedContext?.userId; }; // 普通响应-无返回值 export const main: TcbEventFunction = function (event, context) { return; }; // 普通响应-有返回值 export const main: TcbEventFunction = function (event, context) { return "done."; }; // 集成响应 export const main: TcbEventFunction > = function (event, context) { return { statusCode: 200, headers: {}, body: "", }; }; // 异步函数 export const main: TcbEventFunction> = async function ( event, context ) { return new Promise((resolve) => { setImmediate(() => { resolve("done."); }); }); }; // SSE export const main: TcbEventFunction> = async function ( event, context ) { const sse = context.sse?.(); // 可选参数,设置 SSE 连接的请求头 // const sse = context.sse?.({ // keepalive: false, // 是否保持连接,默认开启,可关闭 // headers: { // 'Mcp-Session-ID': 'this-is-a-mcp-session-id', // 'X-ABC': ['A', 'B', 'C'], // } // }) if (sse && !sse.closed) { sse.on("close", () => { console.log("sse closed"); }); sse.send({ data: "hello from sse function, abcedfg..., €€€€€⭐⭐⭐⭐⭐" }); sse.send({ data: "message with linebreak symbol:\\nThis is the first line.\\n\\nThis is the second line.\\r\\r\\r\n", }); // 单次发送多个事件 sse.send([ { data: "This is the first message." }, { data: "This is the second message, it\n\r\r\n\r\r\rhas two lines." }, { data: "This is the third message." }, ]); // 以下为发送原始消息的示例 // 该方式用于扩展 SSE 协议,例如发送其他 Event Field 字段 // 注意:末尾必须有换行符数据才会立即发送 sse.send("message: This is a raw message. "); sse.send(["message: This is another raw message.\n\n"]); const msgs = [ "This is a raw message. \n", "This is another raw message.\n\n", ]; sse.send(msgs); } return ""; }; // WebSocket export const main: TcbEventFunction = async function (event, context) { if (context.ws) { context.ws.on("open", (msg) => { console.log("open: ", msg); }); context.ws.on("error", (msg) => { console.log("error: ", msg); }); context.ws.on("close", (msg) => { console.log("close: ", msg); }); context.ws.on("message", (msg) => { console.log("message: ", msg); }); context.ws.send("hello from websocket function"); } }; main.handleUpgrade = async function (context) { return { allowWebSocket: true, }; }; ``` ## 项目组织结构 ### 基于 TypeScript 的项目结构 ```tree . ├── README.md # 项目说明 ├── cloudrunfunctions # 函数型云托管项目代码目录,每个目录对应一个函数 │ ├── README.md # 云函数说明 │ ├── func-a # 云函数 `func-a` 代码目录,单函数示例多函数 │ │ ├── README.md # 当前云函数说明 │ │ ├── built # TypeScript 编译后代码目录 │ │ ├── src # TypeScript 源代码目录 │ │ ├── package.json │ │ ├── cloudbase-functions.json # 云函数声明及配置文件 │ │ └── tsconfig.json # TypeScript 配置文件 │ └── func-b # 云函数 `func-b` 代码目录,单函数示例单函数 │ ├── README.md # 当前云函数说明 │ ├── built # TypeScript 编译后代码目录 │ ├── src # TypeScript 源代码目录 │ ├── package.json │ └── tsconfig.json # TypeScript 配置文件 ├── node_modules # node_modules [可能有] ├── package.json # package.json [可能有] ├── tsconfig.json # tsconfig.json [可能有] ``` 该项目结构对应源代码见: 以上,是一个基于 `TypeScript` 的项目结构示例,项目中 需要 `src`、`built` 目录 包含 源代码和编译后的代码,因此需要在云函数代码中配置 `tsconfig.json` 文件。 如果是个 `JavaScript` 编码的项目,则不需要 `src`、`built`、`tsconfig.json` 等目录和文件。 因每个函数是独立部署的,所以每个函数也是相互独立的,但是代码结构比较相似。 非运行时依赖的部分,可以在多个函数之间共享,如 `tsconfig.json` `公共依赖` 等。 项目中还可能包含很多其他类型的文件,其他文件的组织根据项目需要进行即可。 以上是一个相对复杂的项目结构,针对较复杂的项目。 如果整个项目目录中,只有一个云函数,也可以采用单函数的方式进行 `目录结构` 组织,例如如下项目结构: ```txt . ├── README.md # 当前云函数说明 ├── built # TypeScript 编译后代码目录 ├── src # TypeScript 源代码目录 ├── package.json ├── cloudbase-functions.json # 云函数声明及配置文件 └── tsconfig.json # TypeScript 配置文件 ``` 以目录结构是把 `项目根路径/cloudrunfunctions/func-a/*` 目录中的文件移动到 `项目根路径/` 目录下,这样的目录结构适用于单函数的场景。 例如模板项目的示例结构: 也是此类型的项目结构。 --- ## 介绍 # 介绍 `函数型云托管` 是云开发推出的支持在 `云托管` 上运行 `函数式代码` 的一种 函数托管模式,因此也可以称为 `云托管-函数模式`。 `函数型云托管` 本质上是 `云托管` 服务的一种开发和运行模式,支持在 `云托管` 上开发和运行 `函数式代码`,而不需要像开发传统容器服务一样开发一个完整的服务。 `函数型云托管` 可以让容器服务开发像开发云函数一样简单。 技术原理:`函数型云托管` = `云托管` + `函数框架 (@cloudbase/functions-framework)` + `函数代码`。`函数框架` 通常也称为 `运行时(Runtime)`,可以加载云函数并运行。`云托管` 提供云端容器化运行环境。 --- Q:**`函数型云托管` 解决什么问题?** 1. 相比 `云托管`,`函数型云托管` 具备更简单的开发方式 2. 相比 `云函数`,`函数型云托管` 可支持更多场景能力 `函数型云托管` 在一定程度上结合了两者的优点,开发者可以根据自己的业务场景进行选择 --- Q:**如何选择是否需要 `函数代码` 部署到 `云托管`?** 1. 如果业务场景需要支持 `WebSocket 长连接`、`Server-Sent Events (SSE)`、`表单提交`、`文件上传下载`、`流式响应`、`单实例多函数`、`函数间共享内存数据` 等特性,需要使用 `函数型云托管` 2. 如果业务场景对响应耗时更高要求,更好的用户体验,推荐使用 `函数型云托管` 3. 如果需要在函数中连接 `Redis`、`MySQL` 等 `数据库`,推荐使用 `函数型云托管` 4. 如果需要在函数中对接 `Kafka`、`Pulsar` 等 `消息队列`,需要使用 `函数型云托管` 5. 如果业务场景中需要进行长耗时异步任务处理,推荐使用 `函数型云托管` 6. 如果需要更好的 `日志查询能力`,推荐使用 `函数型云托管` 7. 如果想获得更好的开发调试体验,推荐使用 `函数型云托管` 8. 目前 `函数型云托管` 还在不断迭代中,如某些功能特性在 `函数型云托管` 中尚未支持,推荐使用 `云函数` 进行开发 > 函数框架 `@cloudbase/functions-framework` 提供了更好的能力支持 --- Q:**`函数型云托管` 是否需要理了解云托管或容器** 1. 需要了解 `云托管`,例如需要决定选择 `实例规格`、`实例数量` 等,`云托管` 本身也比较简单,也很容易上手 2. 不需要理解 `容器`,开发者不需要了解容器的概念和原理以及如何使用容器等 3. 总体上来说,相比 `云函数` 并没有需要学习和了解很多新内容 --- Q:**现有云函数代码如何迁移到 `云托管`?** 1. 现有云函数代码进行简单的改造后可以运行到云托管环境中 2. 除了云函数代码本身进行改造外,客户端侧代码也需要进行简单的改造 > 因 `函数框架 (@cloudbase/functions-framework)` 与 `云函数` 运行时机制存在一定差异,因此可能需要进行一定的改造。 --- Q:**基于函数型云托管编写的函数代码是否可以运行在其他环境?** 1. 可以,通过 `函数框架 (@cloudbase/functions-framework)` 即在任何支持 `node.js` 运行的环境中运行函数代码 2. 支持 本地运行,主要针对开发调试场景 3. 支持 部署在传统主机环境中,例如云服务器环境中 4. 支持 部署在容器环境中,例如 `Docker` 环境中 > 相比运行在云托管环境中,部署在其他环境中时,需要自行解决构建部署等问题。 --- 更多详细的差异对比见 [对比其他方案-对比云函数](../cbrf/vs?#对比云函数) 文档。 > 注意:函数型云托管 和 云函数 在调用方式、调用链路、和运行时机制上是不同的,现有 云函数代码 在 函数型云托管 上运行需要进行简单的改造。 ## 相关链接 - [快速开始](./quickstart.md) - [函数编写指南](./how-to-writing-functions-code.md) - [本地开发云函数](./how-to-develop-local.md) - [在线开发云函数](./how-to-develop-online.md) - [如何调试函数代码?](./how-to-debug-functions-code.md) - [如何调用TCB云开发的其他能力?](./how-to-invoke-tcb.md) - [开发函数型智能体](./develop-cbrf-agent.md) - [函数代码示例](./example.md) - [与其他方案对比](../cbrf/vs.md) - [CLI工具](./cli.md) - [@cloudbase/functions-framework](https://www.npmjs.com/package/@cloudbase/functions-framework) --- ## 快速开始 # 快速开始 本文将介绍如何快速创建一个函数型云托管 ,并从小程序端发起调用。 ## 通过模板创建函数型云托管 在云函数界面,选择创建云函数,并选择新建函数型云托管,选择函数型云托管 空白模板。 在模板右侧的基本信息中,函数名称可以输入 “testfunc2“ 。 ![](./images/quickstart-create.png) 点击“开始创建“,完成函数的创建过程,并等待版本部署完成。 ![](./images/quickstart-created.png) 同时在创建时,可以通过模板详情,了解后续如何调用当前函数。 当前模板内置了的可调用的函数,可以参考[模板项目](https://github.com/TencentCloudBase/func-v2-template/tree/main)。 ## 小程序端调用 可以通过如下方式,在小程序中调用函数: ```js // 调用必填环境id,不能为空 const c1 = new wx.cloud.Cloud({ resourceEnv: '环境id' //填入云开发环境 id }) await c1.init() const r1 = await c1.callContainer({ path: '/', // 默认函数对应的请求路径 header: { 'X-WX-SERVICE': 'testfunc2', // 填入创建时的函数名称 testfunc2 }, // 其余参数同 wx.request method: 'GET', }) console.log(r1) //输出 Hello world! const r2 = await c1.callContainer({ path: '/echo', // echo 函数对应的请求路径 header: { 'X-WX-SERVICE': 'testfunc2', // 填入创建时的函数名称 testfunc2 }, // 其余参数同 wx.request method: 'POST', data: { a: 1, b: 2 } }) console.log(r2) //输出具体请求及时间 ``` 可以在调试器中查看到请求结果如下类似: ![](./images/quickstart-call.png) --- ## `tcb-ff` 使用指南 # `tcb-ff` 使用指南 `tcb-ff` 由 `@cloudbase/functions-framework` 提供,用于启动云函数服务。 `@cloudbase/functions-framework` 是云开发提供的函数框架,用于云端运行云函数,以及本地开发和调试云函数。 > Q: 什么情况下需要安装 `tcb-ff`? > > A: 云函数本地开发和调试时,需要安装 `tcb-ff`。 ## 安装 `tcb-ff` 安装到全局 ```bash # 全局安装 tcb-ff npm install -g @cloudbase/functions-framework # 运行 tcb-ff tcb-ff ``` 安装到项目下 ```bash # 本地安装 tcb-ff npm install @cloudbase/functions-framework # 运行 tcb-ff npx tcb-ff ``` ## 使用 `tcb-ff` 启动云函数服务 如下为一个常用的示例,启动云函数同时监听文件(基于 `nodemon`)变化,文件变化后会重新启动,该命令开启 CORS 了能力,允许浏览器在 `*.example.com` 和 `www.another.com` 域名上访问服务。 ```sh tcb-ff -w --enableCors=true --allowedOrigins=*.example.com,www.another.com ``` 在函数代码根路径下执行 `tcb-ff` 即可启动云函数服务 ```sh tcb-ff ``` 默认情况下,`tcb-ff` 会监听 `3000` 端口,如需指定端口,可通过 `--port` 参数指定 ```sh tcb-ff --port=30000 tcb-ff -p=30000 ``` `tcb-ff` 支持监听本地文件变更,如需启用热重启模式,可通过 `-w` 参数启用 ```sh tcb-ff -w ``` 如果通过浏览器访问云函数服务,可能会遇到跨域问题,可以通过 `--enableCors` 参数启用 CORS ```sh tcb-ff --enableCors=true ``` `--enableCors` 默认启用 `Origin` 为 `localhost | 127.0.0.1` 的跨域访问,如需配置其他域名,可通过 `--allowedOrigins` 参数配置 ```sh tcb-ff --enableCors=true --allowedOrigins=*.example.com,www.another.com ``` `tcb-ff` 支持开启 `Basic Auth` 进行身份认证,可以通过 `--allowedAccounts` 参数指定允许访问的账号 ```sh tcb-ff --allowedAccounts=abc:123,efg:456 ``` ## `tcb-ff` 参数说明 参数说明 | 命令行参数 | 环境变量 | 默认值 | 示例 | 说明 | | --------------------- | --------------------- | ----------------------------------- | ------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | -w, --watch | / | false | -w | 是否启用热重启模式,如启用,将会在函数代码文件变更时自动重启服务 | | --port | PORT | 3000 | --port=3000 | 监听的端口 | | --extendedContextKey | EXTENDED_CONTEXT_KEY | `''` | --extendedContextKey=X-Functions-Extended-Context | 指定获取扩展 `context.extendedContext` 的头部字段 | | --enableCors | ENABLE_CORS | false | --enableCors=true | 是否启用 CORS,启用后可配置放通的域名,默认放通 `localhost` 和 `127.0.0.1` | | --allowedOrigins | ALLOWED_ORIGINS | `localhost,127.0.0.1` | --allowedOrigins="example.com,*.abc.com" | 需放通 CORS 的域名,默认放通 `localhost` 和 `127.0.0.1`。支持通配符,如 `*.example.com` 可匹配 `www.example.com` 和 `auth.example.com`。该配置项仅在启用`enableCors`时生效。 | | --allowedAccounts | ALLOWED_ACCOUNTS | 无 | --allowedAccounts=abc:123,efg:456 | 允许访问的账号,配置后开启 Basic Auth | | --gracefulShutdown | GRACEFUL_SHUTDOWN | `NODE_ENV` 不为 `production` 时开启 | --gracefulShutdown=false | 是否启用服务的优雅停止 | | --timeout | TIMEOUT | 0 | --timeout=5000 | Node.js Server 超时时间,见 | | --keepAliveTimeout | KEEP_ALIVE_TIMEOUT | 65000 | --keepAliveTimeout=10000 | Node.js Server keep-alive 超时时间,见 | | --captureStack | CAPTURE_STACK | `NODE_ENV` 不为 `production` 时开启 | --captureStack=true | 请求出错时,是否返回错误堆栈 | | --concurrencyLimit | CONCURRENCY_LIMIT | 1000 | --concurrencyLimit=100 | 并发请求数限制,0 为不限制 | | --noExit | NO_EXIT | false | --noExit=true | 是否禁用 `process.exit()` 避免进程意外退出 | | --logHeaderBody | LOG_HEADER_BODY | false | --logHeaderBody=true | 是否在请求日志中记录请求头、请求体、响应头、响应体,如记录,将会限制 body 大小为 2KB | | --logEventContext | LOG_EVENT_CONTEXT | true | --logEventContext=false | 是否在请求日志中记录入参 `event` 和 `context` | | --logDirname | LOG_DIRNAME | ./logs | --logDirname=/var/logs | 日志文件目录 | | --maxLogFileSize | MAX_LOG_FILE_SIZE | `1024 * 1024 * 128`(128m) | --maxLogFileSize=`2097152` | 单个日志文件最大字节数 | | --maxLogFiles | MAX_LOG_FILES | 4 | --maxLogFiles=5 | 最多同时存在的日志文件数量 | | --interceptOutput | INTERCEPT_OUTPUT | false | --interceptOutput=true | 是否拦截`console.log`等标准输出,若拦截,会将标准输出的内容记录到日志文件中 | 可以通过 `tcb-ff -h` 查看全部参数 ```bash $ tcb-ff -h [@cloudbase/functions-framework@1.6.0][pid:0] Usage: tcb-ff [options] Options: -w, --watch Watch the source file for changes and restart the service. Default is false. Example: -w --port, -p Set the port to listen on. Default is 3000. Example: --port=3000 Environment Variable: PORT --target Set the target function name. Default is 'main'. Example: --target=hello Environment Variable: FUNCTION_TARGET --source Set the target function filename. Default is 'index.js' (extension differs based on module type). Example: --source=main.mjs Environment Variable: FUNCTION_SOURCE --loadAllFunctions Whether to load all functions in the 'functionsRoot' directory. Default: false. Example: --loadAllFunctions=true Environment Variable: LOAD_ALL_FUNCTIONS --functionsRoot The root directory of the functions. only effective when 'loadAllFunctions' is true. Example: --functionsRoot=path/to/functionsRoot Environment Variable: FUNCTIONS_ROOT --signatureType Set the function format. Currently only 'event' is supported. Example: --signatureType=event Environment Variable: SIGNATURE_TYPE --gracefulShutdown Enable graceful shutdown of the service. Default true when 'NODE_ENV=production' otherwise false. Example: --gracefulShutdown=false Environment Variable: GRACEFUL_SHUTDOWN --timeout Set the Node.js Server timeout. Default is 0. Example: --timeout=5000 Environment Variable: TIMEOUT --keepAliveTimeout Set the Node.js Server keep-alive timeout. Default is 65000. Example: --keepAliveTimeout=10000 Environment Variable: KEEP_ALIVE_TIMEOUT --captureStack Return error stack when a request fails. Enabled when 'NODE_ENV=production'. Example: --captureStack=true Environment Variable: CAPTURE_STACK --concurrencyLimit Limit the number of concurrent requests. 0 means no limit. Default is 1000. Example: --concurrencyLimit=100 Environment Variable: CONCURRENCY_LIMIT --noExit Disable 'process.exit()' to prevent accidental process exit. Default is false. Example: --noExit=true Environment Variable: NO_EXIT --interceptOutput If true, intercept console、process.stdout、process.stderr output. Default: false. Example: --interceptOutput=true Environment Variable: INTERCEPT_OUTPUT --logHeaderBody Log request and response headers and bodies in the request log. Default is false. Example: --logHeaderBody=false Environment Variable: LOG_HEADER_BODY --logEventContext Log original event and context in the access log. Default is true. Example: --logEventContext=false Environment Variable: LOG_EVENT_CONTEXT --extendedContextKey The key of headers to parse `context.extendedContext`. `''` means that the feature is turned off. Default is . Example: --extendedContextKey=X-Functions-Extended-Context Environment Variable: EXTENDED_CONTEXT_KEY --extendedContext The value to parse `context.extendedContext`. `''` means that the feature is turned off. This parameter will be ignore when 'extendedContextKey' is specified. Default is null. Example: --extendedContext='{"a":1,"b":2}' Environment Variable: EXTENDED_CONTEXT --functionsConfigFile Set the multi-functions definition config file. Default is 'cloudbase-functions.json'. Example: --functionsConfigFile=functions.json Environment Variable: FUNCTIONS_CONFIG_FILE --enableCors If true, enable CORS for configured origins. Default is false. Example: --enableCors=true Environment Variable: ENABLE_CORS --allowedOrigins Set the allowed origins for CORS. Default allows localhost,127.0.0.1. Origins should be domain names without protocol or port. Wildcard origins are supported. e.g. ['*.example.com']. Multiple origins should be separated by comma. Example: --allowedOrigins=*.example.com,www.another.com Environment Variable: ALLOWED_ORIGINS --allowedAccounts Set the accounts allowed to access. If specified, The 'username:password' of request will be verified. Parameter Format: username1:password1,username1:password1,.... Example: --allowedAccounts=abc:123,efg:456 Access Example: curl http://username:password@127.0.0.1:3000/ curl -H "Authorization: Basic base64encode(username:password)" http://127.0.0.1:3000/ Environment Variable: ALLOWED_ACCOUNTS --dry-run Do not start the service, only validate that the code can be loaded. Default is false. Example: --dry-run ``` --- ## 对比其他方案 # 对比其他方案 ## 对比云托管 `函数型云托管` 在云托管的基础上提供了函数式代码开发框架,相比直接使用云托管优势在于: 1. **函数**:`函数型云托管` 支持云托管中部署函数式代码,更适合函数式编程风格,更容易编写 2. **轻量**:`函数型云托管` 不涉及容器、镜像等概念,不需要编写 `Dockerfile`,更轻量 3. **稳定**:`函数型云托管` 框架内部内置 Graceful优雅重启、并发控制、超时控制、参数优化、日志等能力,开发者可以更聚焦业务逻辑编写 4. **日志**:`函数型云托管` 框架提供日志能力,相比直接使用云托管需要自行处理日志更方便 5. **易用**:`函数型云托管` 提供了更多的开发辅助功能,如 cli 工具,本地调试、热重启、函数间路由和代码复用等 6. **底座**:`函数型云托管` 基于云托管,支持云托管的所有功能,如自动扩容、自动伸缩等 ## 对比云函数 相比云函数,函数型云托管 在运行时、触发方式、部署、能力等方面有一些不同。函数型云托管 可以支持 `SSE、WebSocket` 等长连接能力,支持 `Stream` 流式响应,支持文件上传下载能力,支持单实例多函数,对数据库长连接场景友好,开发调试更便利,调用耗时更短 等特性。下表对比了 `函数型云托管` 和 `云函数` 的主要区别: ### 运行时 | 差异项 | 云函数 | 函数型云托管 | | ------------------ | ------------------------------------------------ | ---------------------------------------------------------------------------- | | **并发模型** | 单实例单并发 | 单实例多并发 | | **HPA模式** | 云函数平台根据并发数量HPA,可预置并发 | 基于部署平台HPA能力,如k8s容器平台可以基于CPU/MEM配置HPA | | **内存限制** | 支持MEM大小限制 | 通过运行平台控制 | | **CPU限制** | 不感知CPU核数 | 感知CPU核数,通过运行平台控制 | | **超时控制** | 支持函数执行超时控制,超时后可中断执行 | 支持函数调用超时控制,超时后函数代码可继续执行 | | **调试能力** | 本地调试较难 | 框架支持本地运行,支持热重启,调试更容易 | | **开发体验** | 本地开发不便 | 本地开发较方便,提供 `ts` 类型支持 | | **日志** | 提供调用记录、高级日志 | 提供访问日志、高级日志,访问日志面向用户提供更多信息 | | **依赖安装** | 支持云端 npm 安装依赖 | 支持云端 npm、yarn、pnpm 安装依赖 | | **运行时版本** | 平台提供的指定 node.js 运行时版本 | 可使用满足最低要求的任意 node.js 运行时版本 | | **冷启动** | 存在冷启动,耗时较短,可通过预置并发降低冷启动率 | 存在冷启动,耗时较长,可通过配置最小实例数避免缩容到0产生冷启动 | | **常驻实例** | "不支持"(不感知函数实例) | 感知实例概念,实例可以自定义是否常驻 | | **预置并发** | 支持 | 无此概念,类似于手动扩容 | | **长连接能力** | 不支持 | 支持 SSE、WebSocket 方式的长连接能力 | | **连接数据库** | 基于单实例单并发模型,对数据库长连接不友好 | 跟普通 node.js 程序无区别 | | **异步函数** | 支持,静态配置无法动态切换,限制执行时长 | 支持,函数代码自行控制是否异步执行 | | **异步任务** | 部分版本支持 | 支持,函数代码自行控制是否异步执行 | | **文件上传** | 不支持文件上传 | 支持 `form-data` 等 HTTP原生二进制 上传能力 | | **文件下载** | 不支持文件下载 | 支持文件下载 | | **流式响应** | 不支持 | 支持 Stream 流式响应 | | **内置路由** | 无 | 框架内置路由,支持多函数启动,函数间共享代码更方便,可以在函数间共享内存数据 | | **单实例多函数** | 无此概念 | 支持,可在单个实例内运行多个函数,便于进行代码共享及工程管理 | ### 触发方式 | 分类 | 云函数 | 函数型云托管 | | ---------------- | ----------------------- | ------------------------------------------------------------------ | | **触发方式** | 通过云开发SDK、HTTP、定时器触发 | 原生HTTP调用 或 `wx.cloud.callContainer`,支持获取 HTTP 请求上下文,目前不支持定时器触发 | | **链路差异** | 链路耗时相对较长 | 链路耗时较短 | ### 部署 | 分类 | 云函数 | 函数型云托管 | | -------------- | ---------------------------- | ------------------------------------------------------- | | **平台依赖性** | 仅支持部署到云开发云函数平台 | 可以部署到任意支持运行 `Node.js` 的环境中,支持本地运行 | --- ## aider 配置文档 # aider 配置文档 ## 概述 本文将说明如何使用 CloudBase AI CLI 配置 aider 。 [Cloudbase AI CLI 介绍文档](./introduce) CloudBase AI CLI 支持以两种方式配置 aider: - 云开发配置:一键登录云开发,并选择云开发环境,使用云开发环境中的 Deepseek/Kimi 大模型 - 自定义配置:配置您的 OpenAI 兼容的 Base URL、API Key ## 云开发配置 运行: ```shell tcb ai --setup ``` 命令运行后,将会进入配置向导。 1. 选择当前要配置的 AI 编程助手,选择 `aider` 2. 选择配置方式,选择 `使用 CloudBase 服务,一键登录,无需配置` 3. 根据提示,按需登录账号、选择云开发环境 4. 选择要使用的大模型供应商、模型名称,配置完成后会直接接入到在云开发平台上配置好的大模型,详情可参考 [大模型接入指南](../../ai/model/model-access) 5. 最后可选择默认要使用的 AI 编程助手,后续运行 `tcb ai` 时即可默认打开 全部输入后即可完成配置。 ## 自定义配置 运行: ```shell tcb ai --setup ``` 命令运行后,将会进入配置向导。 1. 选择当前要配置的 AI 编程助手,选择 `aider` 2. 选择配置方式,选择 `自配置 API KEY 和 Base URL` 3. 输入 Base URL、API KEY、模型名称 4. 最后可选择默认要使用的 AI 编程助手,后续运行 `tcb ai` 时即可默认打开 全部输入后即可完成配置。 ## 启动 aider ```shell tcb ai -a aider ``` :::tip 如果配置了默认使用 `aider`,可以直接执行 `tcb ai` ::: ## 详细配置指引 ### 自定义配置 #### 配置 Kimi K2 参考 [自定义配置](#自定义配置) 小节,其中: - Base URL 选择预设的 Kimi Base URL - API KEY 填入您的 Kimi API KEY,可前往 [Kimi](https://platform.moonshot.cn/console/api-keys) 获取 - 模型名称填入 `kimi-k2-0711-preview` #### 配置 智谱 glm-4.5 参考 [自定义配置](#自定义配置) 小节,其中: - Base URL 选择预设的智谱 Base URL - API KEY 填入您的 智谱 API KEY,可前往前往 [智谱 BigModel](https://open.bigmodel.cn/usercenter/proj-mgmt/apikeys) 获取 - 模型名称填入 `glm-4.5` --- ## Claude Code 配置文档 # Claude Code 配置文档 ## 概述 本文将说明如何使用 CloudBase AI CLI 配置 Claude Code 。 [Cloudbase AI CLI 介绍文档](./introduce) CloudBase AI CLI 支持以两种方式配置 Claude Code: - 云开发配置:一键登录云开发,并选择云开发环境,使用云开发环境中的 Deepseek/Kimi 大模型 - 自定义配置:配置您的 Anthropic 兼容的 Base URL、API Key ## 云开发配置 运行: ```shell tcb ai --setup ``` 命令运行后,将会进入配置向导。 1. 选择当前要配置的 AI 编程助手,选择 `Claude Code` 2. 选择配置方式,选择 `使用 CloudBase 服务,一键登录,无需配置` 3. 根据提示,按需登录账号、选择云开发环境 4. 选择要使用的大模型供应商、模型名称,配置完成后会直接接入到在云开发平台上配置好的大模型,详情可参考 [大模型接入指南](../../ai/model/model-access) 5. 最后可选择默认要使用的 AI 编程助手,后续运行 `tcb ai` 时即可默认打开 全部输入后即可完成配置。 ## 自定义配置 运行: ```shell tcb ai --setup ``` 命令运行后,将会进入配置向导。 1. 选择当前要配置的 AI 编程助手,选择 `Claude Code` 2. 选择配置方式,选择 `自配置 API KEY 和 Base URL` 3. 输入 Base URL、API KEY 4. 最后可选择默认要使用的 AI 编程助手,后续运行 `tcb ai` 时即可默认打开 全部输入后即可完成配置。 ## 启动 Claude Code ```shell tcb ai -a claude ``` :::tip 如果配置了默认使用 `Claude Code`,可以直接执行 `tcb ai` ::: ## 详细配置指引 ### 自定义配置 #### 配置 Kimi K2 参考 [自定义配置](#自定义配置) 小节,其中: - Base URL 选择预设的 Kimi Base URL - API KEY 填入您的 Kimi API KEY,可前往 [Kimi](https://platform.moonshot.cn/console/api-keys) 获取 #### 配置 智谱 glm-4.5 参考 [自定义配置](#自定义配置) 小节,其中: - Base URL 选择预设的智谱 Base URL - API KEY 填入您的 智谱 API KEY,可前往前往 [智谱 BigModel](https://open.bigmodel.cn/usercenter/proj-mgmt/apikeys) 获取 ##### 参考文档 - #### 配置 Claude 参考 [自定义配置](#自定义配置) 小节,其中: - Base URL 选择自定义 URL,输入 `https://api.anthropic.com` - API KEY 填入您的 Anthropic API KEY,可前往前往 [Anthropic](https://console.anthropic.com/) 获取 ##### 参考文档 - --- ## CodeBuddy Code 配置文档 # CodeBuddy Code 配置文档 ## 概述 本文将说明如何使用 CloudBase AI CLI 配置 CodeBuddy Code 。 [Cloudbase AI CLI 介绍文档](./introduce) CloudBase AI CLI 支持以两种方式配置 CodeBuddy Code: - CodeBuddy 账号登录:使用 CodeBuddy 账号登录,支持 OAuth 身份验证 - API key配置:使用 CodeBuddy API key 登录 ## CodeBuddy 配置 运行: ```shell tcb ai --setup ``` 命令运行后,将会进入配置向导。 1. 选择当前要配置的 AI 编程助手,选择 `CodeBuddy Code` 2. 选择配置方式,选择 `使用 CodeBuddy 账号登录` 3. 根据提示登录您的 CodeBuddy 账号 4. 最后可选择默认要使用的 AI 编程助手,后续运行 `tcb ai` 时即可默认打开 ## 启动 CodeBuddy Code ```shell tcb ai -a codebuddy ``` :::tip 如果配置了默认使用 `CodeBuddy Code`,可以直接执行 `tcb ai` ::: ## 详细配置指引 ### 自定义配置 #### 配置 CodeBuddy API Key - API Key 填入您的 CodeBuddy API Key ### 环境变量配置 CodeBuddy Code 支持通过环境变量进行配置: ```bash export CODEBUDDY_API_KEY="your-api-key-here" ``` ### MCP 服务器配置 CodeBuddy Code 支持通过参数透传实现 MCP 命令管理: ```shell # 通过 CloudBase AI CLI 透传参数 tcb ai -a codebuddy -- --mcp-server "your-mcp-server-config" ``` ## 配置验证 CodeBuddy Code 的配置会自动进行验证,包括: - API Key 格式验证 - 网络连通性测试 - MCP 服务器配置检查 ## 故障排除 ### 常见问题 1. **API Key 无效** - 检查 API Key 是否正确 - 确认 API Key 是否有足够的使用权限 - 查看 CodeBuddy 账户状态 2. **网络连接问题** - 检查防火墙设置 - 确认网络能够访问 CodeBuddy 服务 - 尝试更换网络环境 3. **MCP 服务器配置错误** - 验证 MCP 服务器配置格式 - 检查服务器地址是否可访问 - 确认服务器认证信息 ### 日志查看 启用详细日志来排查问题: ```shell tcb ai -a codebuddy -- --verbose ``` ## 最佳实践 1. **API Key 安全管理** - 使用环境变量而不是硬编码 API Key - 定期轮换 API Key - 限制 API Key 的权限范围 2. **MCP 服务器管理** - 使用配置文件管理多个 MCP 服务器 - 定期检查服务器状态 - 备份重要的服务器配置 3. **性能优化** - 根据项目规模选择合适的模型 - 合理配置并发请求数 - 监控 API 使用量和费用 --- ## Codex 配置文档 # Codex 配置文档 ## 概述 本文将说明如何使用 CloudBase AI CLI 配置 OpenAI Codex 。 [Cloudbase AI CLI 介绍文档](./introduce) CloudBase AI CLI 支持以两种方式配置 OpenAI Codex: - 云开发配置:一键登录云开发,并选择云开发环境,使用云开发环境中的 Deepseek/Kimi 大模型 - 自定义配置:配置您的 OpenAI 兼容的 Base URL、API Key ## 云开发配置 运行: ```shell tcb ai --setup ``` 命令运行后,将会进入配置向导。 1. 选择当前要配置的 AI 编程助手,选择 `OpenAI Codex` 2. 选择配置方式,选择 `使用 CloudBase 服务,一键登录,无需配置` 3. 根据提示,按需登录账号、选择云开发环境 4. 选择要使用的大模型供应商、模型名称,配置完成后会直接接入到在云开发平台上配置好的大模型,详情可参考 [大模型接入指南](../../ai/model/model-access) 5. 最后可选择默认要使用的 AI 编程助手,后续运行 `tcb ai` 时即可默认打开 全部输入后即可完成配置。 ## 自定义配置 运行: ```shell tcb ai --setup ``` 命令运行后,将会进入配置向导。 1. 选择当前要配置的 AI 编程助手,选择 `OpenAI Codex` 2. 选择配置方式,选择 `自配置 API KEY 和 Base URL` 3. 输入 Base URL、API KEY、模型名称 4. 最后可选择默认要使用的 AI 编程助手,后续运行 `tcb ai` 时即可默认打开 全部输入后即可完成配置。 ## 启动 OpenAI Codex ```shell tcb ai -a codex ``` :::tip 如果配置了默认使用 `OpenAI Codex`,可以直接执行 `tcb ai` ::: ## 详细配置指引 ### 自定义配置 #### 配置 Kimi K2 参考 [自定义配置](#自定义配置) 小节,其中: - Base URL 选择预设的 Kimi Base URL - API KEY 填入您的 Kimi API KEY,可前往 [Kimi](https://platform.moonshot.cn/console/api-keys) 获取 - 模型名称填入 `kimi-k2-0711-preview` #### 配置 智谱 glm-4.5 参考 [自定义配置](#自定义配置) 小节,其中: - Base URL 选择预设的智谱 Base URL - API KEY 填入您的 智谱 API KEY,可前往前往 [智谱 BigModel](https://open.bigmodel.cn/usercenter/proj-mgmt/apikeys) 获取 - 模型名称填入 `glm-4.5` --- ## Cursor CLI 配置文档 # Cursor CLI 配置文档 ## 概述 本文将说明如何使用 CloudBase AI CLI 配置 Cursor CLI 。 [Cloudbase AI CLI 介绍文档](./introduce) CloudBase AI CLI 目前只支持以 Cursor 内置鉴权方式配置 Cursor CLI: ## 配置 运行: ```shell tcb ai --setup ``` 1. 命令运行后,将会进入配置向导。 2. 选择当前要配置的 AI 编程助手,选择 `Cursor CLI` 即可 ## 启动 Cursor CLI ```shell tcb ai -a cursor ``` :::tip 如果配置了默认使用 `cursor`,可以直接执行 `tcb ai` ::: --- ## CloudBase AI CLI 使用文档 # CloudBase AI CLI 使用文档 ## 简介 CloudBase AI CLI 是一个集成多种主流 AI 编程工具的统一命令行工具,支持内置模型和自定义模型 让你能够通过一个简单的命令使用 CodeBuddy Code、Claude Code、OpenAI Codex、aider、Qwen Code 等 AI 编程助手 同时内置[CloudBase AI Toolkit](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/),支持从开发到部署的完整流程,支持在任意环境中运行 ![](http://static.cloudbase.net/imgs/cli-better.gif) ## 核心优势 ```mermaid graph LR A["统一管理"] --> B["多模型支持"] B --> C["一键开发部署"] C --> D["无处不在"] E["CodeBuddy CodeClaude CodeOpenAI CodexaiderQwen Code"] -.-> A style A fill:#e3f2fd style B fill:#e3f2fd style C fill:#e3f2fd style D fill:#e3f2fd style E fill:#fff3e0 ``` - 🏗️ **统一管理** - 一个命令管理多种 AI 编程 CLI 工具,无需在多个工具间切换 - 🤖 **多模型支持** - 支持内置和自定义各种大模型,包括 Kimi K2、智谱 GLM-4.5 等 - 🚀 **一键开发部署** - 从代码生成到云端部署的完整流程,支持 Web 应用、小程序、后端服务 - 🌍 **无处不在** - 可在任意环境中运行,包括小程序开发者工具、VS Code、GitHub Actions 等 ## 应用场景 ```mermaid graph LR subgraph "调用场景" A1[小程序开发者工具] A2[VS Code 终端] A3[GitHub Actions] A4[服务器环境] A5[本地开发环境] end subgraph "统一入口" B[tcb ai 命令] end subgraph "支持开发部署的应用" C1[Web 应用] C2[微信小程序] C3[后端服务] C4[UniApp应用] end A1 --> B A2 --> B A3 --> B A4 --> B A5 --> B B --> C1 B --> C2 B --> C3 B --> C4 style A1 fill:#e3f2fd style A2 fill:#e3f2fd style A3 fill:#e3f2fd style A4 fill:#e3f2fd style A5 fill:#e3f2fd style B fill:#fff3e0 style C1 fill:#e8f5e8 style C2 fill:#e8f5e8 style C3 fill:#e8f5e8 style C4 fill:#e8f5e8 ``` ## 快速开始 ### 1. 安装 import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; **推荐:一键安装脚本** 只需几秒即可完成安装(相比 npm 安装通常需几分钟),体验更快更便捷: ```bash curl https://static.cloudbase.net/cli/install/install.sh -fsS | bash ``` ```powershell irm https://static.cloudbase.net/cli/install/install.ps1 | iex ``` **如需使用 npm/yarn/pnpm 安装:** ```sh npm i -g @cloudbase/cli ``` 或者使用 Yarn 1.x : ```sh yarn global add @cloudbase/cli ``` 或者 Pnpm: ```sh pnpm add -g @cloudbase/cli ``` 如果访问官方 npm 源有问题,一般安装过程中报类似 "ETIMEOUT"、"npm ERR! network request to https://registry.npmjs.org/@cloudbase%2fcli failed" 这种错误,这个时候需要临时指定一个国内 npm 镜像源: ```sh npm i -g @cloudbase/cli --registry=http://mirrors.cloud.tencent.com/npm/ ``` ```sh yarn global add @cloudbase/cli --registry=http://mirrors.cloud.tencent.com/npm/ ``` ### 2. 初始化 AI 配置 使用终端运行 CloudBase AI CLI: ```bash # 启动配置向导 tcb ai ``` 首次启动,配置向导会引导你完成: - 选择 AI 工具 - 完成 AI 工具的配置 完成配置后,即可开始使用 AI 工具进行辅助开发,后续可以运行 `tcb ai --setup` 来切换工具和模型。 ### 3. 开始体验 ```bash tcb ai # 或预设提示词 tcb ai -- "帮我创建一个订单管理系统" # 或使用非交互式模式 tcb ai -- -p "你好" # 查看所有可用命令 tcb ai --help ``` ## 详细开发指引 参考详细教程: [用 CloudBase AI CLI 开发邻里闲置物品循环利用小程序](/practices/ai-cli-mini-program) :::tip 立即体验 **到处皆可运行,从代码生成到云端部署!** 无需 API Key,新环境赠送 100 万 token,支持 DeepSeek、Kimi K2 等主流模型快速体验。 ::: ## 工作原理 ```mermaid graph TB A[开发者] --> B[tcb ai 命令] B --> I[AI 模型层云开发内置模型 + 自定义模型] I --> C[统一管理层] C --> D[CodeBuddy Code] C --> E[Claude Code] C --> F[OpenAI Codex] C --> G[aider] C --> H[Qwen Code] C --> I[其他 AI CLI] D --> J[代码生成] E --> J F --> J G --> J H --> J I --> J C --> L[其他 AI CLI 工具] J --> K[云开发平台] K --> M[Web 应用] K --> N[微信小程序] K --> O[后端服务] style A fill:#e1f5fe style B fill:#fff3e0 style I fill:#f3e5f5 style C fill:#f3e5f5 style K fill:#e8f5e8 ``` ## 详细使用说明 ### 启动 AI 工具 ```bash # 使用默认配置的 AI 工具 tcb ai # 指定 AI 工具 tcb ai -a codebuddy tcb ai -a claude tcb ai -a codex tcb ai -a aider tcb ai -a qwen ``` ### 参数透传 使用 `--` 分隔符将参数直接传递给目标 AI 工具: ```bash # 传递参数给 CodeBuddy tcb ai -a codebuddy -- --mcp-server "config.json" # 传递参数给 Claude tcb ai -a claude -- -p hi # 相当于运行 codebuddy --mcp-server "config.json" 或 claude -p hi ``` ### 指定模板 在 AI 开发时直接指定模板: ```bash # 使用 AI 命令并下载模板 tcb ai --template rules tcb ai --template miniprogram tcb ai --template react ``` 支持的模板 - `miniprogram` - 微信小程序 + CloudBase - `react` - Web 应用 - React + CloudBase - `vue` - Web 应用 - Vue + CloudBase - `uniapp` - 跨端应用 - UniApp + CloudBase - `rules` - AI 规则和配置 - `none` - 不下载任何模板 ### 查看当前配置 ```bash tcb ai --config ``` ### 重新配置 ```bash # 重置所有配置 tcb ai --reset # 运行配置向导 tcb ai --setup ``` ## 支持的 AI 工具 | AI 工具 | 命令参数 | |---------|----------| | [CodeBuddy Code](https://codebuddy.co/) | `-a codebuddy` | | [Claude Code](https://www.anthropic.com/claude-code) | `-a claude` | | [Openai Codex](https://github.com/openai/codex) | `-a codex` | | [aider](https://aider.chat/) | `-a aider` | | [Qwen Code](https://github.com/QwenLM/qwen-code) | `-a qwen` | ## 获取帮助 ### 命令行帮助 ```bash # 查看命令帮助 tcb ai --help ``` ### 常见问题 遇到问题?查看 [CloudBase CLI 常见问题解答](../faq.md#ai-cli-相关) 获取详细帮助。 ### 技术支持 - **帮助中心**:[https://tcb.cloud.tencent.com/help-center](https://tcb.cloud.tencent.com/help-center) - 在线咨询、工单系统、技术文档 - **官方文档**:[https://docs.cloudbase.net](https://docs.cloudbase.net) - 完整的产品文档和使用指南 - **GitHub 仓库**:[CloudBase-AI-ToolKit](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit) - 开源代码和问题反馈 ### 🔥 微信交流群 遇到问题或想要交流经验?加入我们的技术社区! 扫码加入微信技术交流群 ## 为什么选择 CLI? CLI 让 AI 编程能力变成可编程的基础设施,可以被脚本、自动化流程、CI/CD 系统调用,无需在多个 GUI 工具间切换,可以集成到现有开发工作流中 同时支持云原生开发、容器化部署、持续集成/持续部署(CI/CD),推动 AI 从"生成代码"到"全流程协作"的进化 ```mermaid graph TD A[AI IDE] --> B[独立应用程序] B --> C[GUI 界面] C --> D[手动操作] E[AI CLI] --> F[可编程基础设施] F --> G[脚本调用] G --> H[自动化流程] H --> I[CI/CD 集成] style A fill:#ffebee style E fill:#e8f5e8 style B fill:#ffebee style F fill:#e8f5e8 ``` ## 配置说明 当前 CloudBase AI CLI 支持以下 AI 工具的配置: - CodeBuddy Code - Claude Code - Openai Codex - aider - Qwen Code 所有工具都支持两种配置方式: - 配置自定义的 LLM:通常需要配置自己的 API KEY 和对应的 Base URL - 配置云开发环境中的 LLM:无需自行配置 API KEY,只需按照命令行提示登录并选择云开发环境即可 | AI 工具 | 自定义配置要求 | 云开发环境配置 | 相关文档 | |---------|--------------|--------------| ---- | | CodeBuddy Code | - API KEY - 支持 OAuth 身份验证 - MCP 服务器配置 - 环境变量配置 | ✨ 一键登录,自动配置 | [配置文档](./codebuddy) | | Claude Code | - Base URL- API KEY - 需要配置为 Anthropic 兼容的模型 - 支持配置 Kimi-K2、智谱 GLM-4.5 | ✨ 一键登录,自动配置 | [配置文档](./claude) | | OpenAI Codex | - Base URL- API KEY - 模型名称 - 需要配置为 OpenAI 兼容的模型 | ✨ 一键登录,自动配置 | [配置文档](./codex) | | aider | - Base URL- API KEY - 模型名称 - 需要配置为 OpenAI 兼容的模型 | ✨ 一键登录,自动配置 | [配置文档](./aider) | | Qwen Code | - Base URL- API KEY - 模型名称 - 需要配置为 OpenAI 兼容的模型 | ✨ 一键登录,自动配置 | [配置文档](./qwen) | --- ## Qwen Code 配置文档 # Qwen Code 配置文档 ## 概述 本文将说明如何使用 CloudBase AI CLI 配置 Qwen Code 。 [Cloudbase AI CLI 介绍文档](./introduce) CloudBase AI CLI 支持以两种方式配置 Qwen Code: - 云开发配置:一键登录云开发,并选择云开发环境,使用云开发环境中的 Deepseek/Kimi 大模型 - 自定义配置:配置您的 OpenAI 兼容的 Base URL、API Key ## 云开发配置 运行: ```shell tcb ai --setup ``` 命令运行后,将会进入配置向导。 1. 选择当前要配置的 AI 编程助手,选择 `Qwen Code` 2. 选择配置方式,选择 `使用 CloudBase 服务,一键登录,无需配置` 3. 根据提示,按需登录账号、选择云开发环境 4. 选择要使用的大模型供应商、模型名称,配置完成后会直接接入到在云开发平台上配置好的大模型,详情可参考 [大模型接入指南](../../ai/model/model-access) 5. 最后可选择默认要使用的 AI 编程助手,后续运行 `tcb ai` 时即可默认打开 全部输入后即可完成配置。 ## 自定义配置 运行: ```shell tcb ai --setup ``` 命令运行后,将会进入配置向导。 1. 选择当前要配置的 AI 编程助手,选择 `Qwen Code` 2. 选择配置方式,选择 `自配置 API KEY 和 Base URL` 3. 输入 Base URL、API KEY、模型名称 4. 最后可选择默认要使用的 AI 编程助手,后续运行 `tcb ai` 时即可默认打开 全部输入后即可完成配置。 ## 启动 Qwen Code ```shell tcb ai -a qwen ``` :::tip 如果配置了默认使用 `Qwen Code`,可以直接执行 `tcb ai` ::: ## 详细配置指引 ### 自定义配置 #### 配置 Qwen 参考 [自定义配置](#自定义配置) 小节,其中: - Base URL 使用默认配置即可 - API KEY 填入您的 百炼 API KEY,可前往 [阿里云百炼](https://bailian.console.aliyun.com/) 获取 - 输入要使用的模型名称 ##### 参考文档 - --- ## 删除服务 # 删除服务 删除云托管服务 ## 基本用法 输入以下命令删除当前环境下的云托管服务: ```sh tcb cloudrun delete ``` ## 进阶用法 手动指定相关参数来删除特定服务: ```sh tcb cloudrun delete -e --serviceName --force ``` ## 命令行参数 支持的命令行参数如下: ```sh Options: -e, --envId 环境 ID -s, --serviceName 服务名称 --force 强制删除,不提示确认 -h, --help 查看命令帮助信息 ``` --- ## 代码部署 # 代码部署 将云托管项目代码部署到云托管环境 > 云托管代码项目可参考示例:[nodejs_hello_world](https://github.com/TencentCloudBase/awesome-cloudbase-examples/tree/master/cloudbaserun/node) ## 基本用法 输入以下命令即可开始交互式部署,在此过程中 CLI 会自动询问您需要发布的服务、环境等信息 ```sh tcb cloudrun deploy ``` ## 进阶用法 指定端口来部署容器型云托管服务: ```sh tcb cloudrun deploy -e -s --port 3000 --force ``` 创建函数型 Agent(同时会部署其所依赖的函数型云托管服务) ```sh tcb cloudrun deploy -e --createAgent ``` ## 命令行参数 支持的命令行参数如下: ```sh Options: -e, --envId 环境 Id -s, --serviceName 服务名称 --port 容器型云托管服务端口(函数型云托管设置无效) --source 部署代码所在目录路径(绝对路径或相对路径,默认: 当前目录) --createAgent 创建函数型 Agent --force 强制部署,跳过所有确认提示 -h, --help 查看命令帮助信息 ``` --- ## 下载服务代码 # 下载服务代码 下载云托管服务代码 ## 基本用法 输入以下命令下载指定服务的代码: ```sh tcb cloudrun download ``` ## 进阶用法 手动指定相关参数来下载服务代码: ```sh tcb cloudrun download -e --serviceName --targetPath --force ``` ## 命令行参数 支持的命令行参数如下: ```sh Options: -e, --envId 环境 ID -s, --serviceName 服务名称 --targetPath 代码下载目标路径(绝对路径或相对路径,默认: 当前目录) --force 强制覆盖,不提示确认 -h, --help 查看命令帮助信息 ``` --- ## 初始化项目 # 初始化项目 初始化云托管服务代码项目 ## 基本用法 输入以下命令即可开始交互式初始化,在此过程中 CLI 会自动询问您需要的环境、服务名称等信息 ```sh tcb cloudrun init ``` ## 进阶用法 手动指定相关参数来初始化项目: ```sh tcb cloudrun init -e -s ``` ## 命令行参数 支持的命令行参数如下: ```sh Options: -e, --envId 环境 ID -s, --serviceName 服务名称 --template 模板名称 --targetPath 项目初始化目标路径(绝对路径或相对路径,默认: 当前目录) -h, --help 查看命令帮助信息 ``` --- ## 查看服务列表 # 查看服务列表 查看云托管服务列表 ## 基本用法 输入以下命令查看当前环境下的云托管服务列表: ```sh tcb cloudrun list ``` ## 进阶用法 手动指定相关参数来筛选服务列表: ```sh tcb cloudrun list -e --pageSize 20 --pageNum 2 --serviceName --serverType container ``` ## 命令行参数 支持的命令行参数如下: ```sh Options: -e, --envId 环境 ID --pageSize 每页数量(默认值: 10) --pageNum 页码(默认值: 1) --serviceName 服务名称筛选 --serverType 服务类型筛选(可选值: function | container) -h, --help 查看命令帮助信息 ``` --- ## 本地运行 # 本地运行 本地运行函数型云托管服务(不支持容器型云托管服务) ## 基本用法 ```sh tcb cloudrun run [options] ``` ## 命令行参数 支持的命令行参数如下: ```sh Options: --runMode 运行模式,可选值: normal(普通函数) | agent(函数式 Agent),默认值: normal --agentId 在 agent 模式下需要提供 Agent ID 进行调试 -e, --envId 环境 ID --port 监听的端口,默认为 3000 -w, --watch 是否启用热重启模式,如启用,将会在文件变更时自动重启服务,默认为 false --dry-run 是否不启动服务,只验证代码可以正常加载,默认为 false --logDirname 日志文件目录,默认为 ./logs --functionsConfigFile 多函数定义配置文件,默认为 ./cloudbase-functions.json 环境变量: FUNCTIONS_CONFIG_FILE --loadAllFunctions 是否加载 "functionsRoot" 目录中的所有函数。默认为 false --extendedContext 用于解析 context.extendedContext 的值。""表示该功能已关闭。默认值为 null 示例:--extendedContext '{"a":1,"b":2}' 环境变量:EXTENDED_CONTEXT --open-debug-panel 是否打开调试面板,默认为 'true' -h, --help 查看命令帮助信息 ``` ## 运行模式示例 ### 1. normal 模式 (默认) 普通函数模式,适用于常规函数运行场景: ```sh # 基本用法 tcb cloudrun run -e env-123456 # 带热重启 tcb cloudrun run -e env-123456 -w ``` ### 2. agent 模式 函数式 Agent 模式,需要提供 Agent ID 进行调试: ```sh # 基本 agent 模式 tcb cloudrun run --runMode agent --agentId ibot-agent-xxx -e env-123456 # agent 模式带热重启 tcb cloudrun run --runMode agent --agentId ibot-agent-xxx -e env-123456 -w ``` 更多示例见:[函数示例](../../cbrf/how-to-writing-functions-code.md#函数示例) ## 环境变量 在本地运行时,需在项目根目录下创建名为 **.env.local** 的配置文件(注意文件名以英文句点开头),并按 KEY=VALUE 的格式写入环境变量,示例如下: ``` # .env.local API_KEY=your_api_key123 ``` 项目部署完成后,请在该云托管服务的管理控制台中完成环境变量的配置操作 --- ## 配置文件 # 配置文件 为了应对复杂的使用场景,我们提供了项目级的 `cloudbaserc.json` 配置文件,可以在 CLI 和 VS Code 插件中共享使用。 配置文件包含了使用云开发 CLI 或 VS Code 插件的过程中的相关配置,可以简化 CLI 和 VS Code 的使用。 默认情况下,使用 `cloudbase init` 初始化项目时,会生成 `cloudbaserc.json` 文件作为配置文件,您也可以使用 `--config-file` 指定其他文件作为配置文件,文件必须满足格式要求。 ## 动态变量 CLI 0.9.1+ 版本引入了 2.0 新版本配置文件,支持了动态变量的特性。在 `cloudbaserc.json` 中声明 `"version": "2.0"` 即可启用新的特性,新版配置文件只支持 JSON 格式。 动态变量特性允许在 `cloudbaserc.json` 配置文件中使用动态变量,从环境变量或其他数据源获取动态的数据。使用 `{{}}` 包围的值定义为动态变量,可以引用数据源中的值。如下所示 ```json { "version": "2.0", "envId": "envId", "functionRoot": "./functions", "functions": [ { "name": "{{variable}}" } ] } ``` ### 数据源 CloudBase 定义多个数据源的命名空间,用于区分不同的数据源。你可以通过 `命名空间.变量名` 引用数据,如 `{{tcb.envId}}` | 命名空间 | 变量名 | 含义 | | -------- | ------- | ------------------------------------- | | tcb | `envId` | 配置文件或通过命令行参数指定的环境 Id | | util | `uid` | 24 位的随机字符串 | | env | `*` | 从 `.env` 类型文件中加载的环境变量 | ### 环境变量 CloudBase 对环境变量做了特别支持,以解决不同开发阶段、不同配置,使用 CLI & Framework 部署资源的问题。CloudBase 支持使用 [`.env`](https://github.com/motdotla/dotenv) 类型文件作为主要数据源,使用不同的后缀区分不同的阶段、场景,如 `.env.development` 可以表示开发阶段的配置,`.env.production` 可以表示生产环境的配置等。 CloudBase 定义了一些约束:默认情况下,CLI & Framework 会自动加载 `.env` 和 `.env.local` 文件中的数据,开发者可以通过使用 `--mode ` 选项添加特定环境的配置。 ``` .env # 在所有的环境中被载入 .env.local # 在所有的环境中被载入,可以加入 .gitignore 忽略 .env.[mode] # 只在指定的模式中被载入 ``` 在加载数据源时,`.env` 和 `.env.local` 会被直接加载(如果存在的话),当指定 `--mode [mode]` 时,会再加载 `.env.[mode]` 文件,并按照如下的顺序合并覆盖同名变量:`.env.[mode] > .env.local > .env`,即 `.env.[mode]` 中的同名变量会覆盖 `.env.local` 和 `.env` 文件中的同名变量,以此类推。 当使用 `tcb framework deploy --mode test` 命令时,会自动加载 `.env`,`.env.local` 以及 `.env.test` 等三个文件中的环境变量合并使用。 :::tip 我们建议你将秘钥等私密配置放在 `.env.local` 文件中,并将 `.env.local` 加入 `.gitignore` 配置中。 ::: 如 `.env.local` 文件中存在以下变量 ```bash DB_HOST = localhost DB_USER = root DB_PASSWORD = s1mpl3 ``` 则可以在配置文件中使用 ```json { "version": "2.0", "envId": "xxx", "functionRoot": "./functions", "functions": [ { "name": "test", "envVariables": { "PASSWORD": "{{env.DB_PASSWORD}}" } } ] } ``` ### 扩展 env 语法 一般情况下,你可以直接在 `env` 文件中使用键值对 ``` FOO=bar VUE_APP_SECRET=secret ``` 但是,当我们需要使用复杂的环境变量时,简单的键值对就有些力不从心了。所以,CloudBase 扩展了 `.env` 支持的语法,支持了复合键值对,你可以通过 `.` 为同名键添加属性,如 ```bash Book.Name=Test Book.Publish=2020 Book.Authors.0=Jack Book.Authors.1=Mike ``` 会被编译为包含以下属性的 Book 对象 ```json { "Name": "Test", "Publish": "2020", "Authors": ["Jack", "Mike"] } ``` 你可以在 `cloudbaserc.json` 直接使用 `{{env.Book.Name}}` 引用相关属性。 :::caution 当使用的 `.env` 值为对象时,在编译时会被转换成 JSON 字符串,如 `{{env.Book}}` 会被编译为 `{"Name":"Test","Publish":"2020","Authors":["Jack","Mike"]}`。 ::: ## 字段 下面是 CloudBase 配置文件支持的字段以及其含义。 ### version **类型**:`String` version 表示当前配置文件的版本,目前支持的版本号有:`"2.0"`。当 `version` 字段不存在时,默认当前配置文件为 `"1.0"` 版本。 ### envId **类型**: `String` envId 代表环境 ID,是环境的唯一标识。 ### region **类型**:`String` region 指定了当前环境的地域信息,上海地域的环境可以不填,其他地域的环境则必须填写。 ### functionRoot **类型**:`String` 云函数函数代码存放的文件夹路径,相对于根目录的路径。 ### functions **类型**: `Array` 函数配置项组成的数组,有关函数配置项的详细信息,请参考[函数配置项文档](https://docs.cloudbase.net/cli-v1/functions/configs)。 ## 简单参考配置 下面是一个简单的 CLI 配置文件包含的基本信息: ```json { "version": "2.0", "envId": "dev-xxxx", "functionRoot": "functions", "functions": [ { "name": "app", "timeout": 5, "envVariables": { "key": "value" } } ] } ``` --- ## 数据库管理 # 数据库管理 云开发中提供了 [数据库](/database/introduce) 和 [数据模型](/model/introduce) 来组织和管理数据。 用户可以通过 CloudBase CLI 管理数据库,进行数据模型的拉取、推送等操作。 ## 查看数据模型 您可以使用下面的命令列出云端所有数据模型,查看模型的基本信息: ```sh tcb db list ``` 您会得到类似下面的输出: ```plaintext ? 请先选择一个云开发环境 tcb-advanced (tcb-advanced-a656fc) 正常 | 名称 | 标识 | 创建时间 | |---------------------|-------------------|--------------------| | 智能路书-路书 | itinerary | 2024-07-06T06:11:13.000+0000 | | 用户 | sys_user | 2024-05-17T08:17:06.000+0000 | | 部门 | sys_department | 2024-05-17T08:17:03.000+0000 | ``` ### `tcb db list` 命令参考 ``` Usage: tcb db list [options] 列出云端所有数据模型 Options: -e, --envId 环境 Id -h, --help 查看命令帮助信息 ``` ## 拉取数据模型 您可以通过下面的命令从云端拉取数据模型到本地: ```sh tcb db pull ``` 您会得到类似下面的输出: ```plaintext ℹ 当前环境 Id:tcb-advanced-a656fc ? 请选择数据模型 sys_department, sys_user, itinerary ✔ 同步数据模型成功。文件名称:database-schemas/itinerary.json ✔ 同步数据模型成功。文件名称:database-schemas/sys_user.json ✔ 同步数据模型成功。文件名称:database-schemas/sys_department.json ✔ 同步数据模型类型定义文件成功,调用 SDK 时可支持智能字段提示。文件名称:cloud-models.d.ts ``` ### `tcb db pull` 命令参考 ``` Usage: tcb db pull [options] 从云端拉取多个数据模型到本地 Options: -e, --envId 环境 Id -d, --dir 本地存储数据库模型定义的目录,默认为 database-schemas -n, --name 要拉取的模型英文标识列表,可指定多个,使用逗号分隔.不指定的情况下默认会拉取所有模型 -h, --help 查看命令帮助信息 ``` ## 推送数据模型 您可以使用下面的命令将本地的数据模型推送到云端: ```sh tcb db push ``` 可以交互式处理数据模型的推送和发布 ```plaintext ℹ 使用环境 Id:tcb-advanced-a656fc ℹ 开始检查数据模型 itinerary ? 数据模型 itinerary 已存在,是否更新? Yes ✔ 更新数据模型 itinerary 成功,点击查看 https://tcb.cloud.tencent.com/cloud-admin/#/management/data-model/data-3YqErZah7 ℹ 开始检查数据模型 sys_department ? 数据模型 sys_department 已存在,是否更新? Yes ✔ 更新数据模型 sys_department 成功,点击查看 https://tcb.cloud.tencent.com/cloud-admin/#/management/data-model/data-3RjUdvQzf ℹ 开始检查数据模型 sys_user ? 数据模型 sys_user 已存在,是否更新? Yes ✔ 更新数据模型 sys_user 成功,点击查看 https://tcb.cloud.tencent.com/cloud-admin/#/management/data-model/data-3RjUeo6NE ? 数据模型已经导入成功,是否发布? Yes ``` ### `tcb db push` 命令参考 ```plain Usage: tcb db push [options] 将本地数据模型推送到云端 Options: -e, --envId 环境 Id -d, --dir 本地存储数据库模型定义的目录,默认为 database-schemas -n, --name 要推送的模型名称列表,可指定多个,使用逗号分隔.不指定的情况下默认会推送本地目录下的所有数据模型 -h, --help 查看命令帮助信息 ``` --- ## 环境基础 # 环境基础 ## 查看所有环境 当您想要查看您所拥有的所有环境的基本信息时,您可以使用下面的命令获取环境列表: ```sh tcb env list ``` 您会得到类似下面的输出: ![](https://main.qcloudimg.com/raw/0771911fd9a91e777e9d0e74131b880b.png) 环境 Id 是环境的的唯一标志,在全局范围内是唯一的。环境的名称是用户自行定义的,可以帮助用户方便的区分不同的环境。 Status 表明了环境的状态,只有当环境状态正常时,您才可以操作函数、数据库、存储等资源。新建的环境也可能处于不可用的状态,请耐心等待初始化完成。如果您的环境状态一直处于不可用状态时,请及时联系我们解决。 ## 创建环境 您可以使用下面的命令创建一个新的环境 ```sh tcb env create env-name ``` 每个用户可以创建的环境数量是有限的,如果您的环境数量已经使用完,您会得到一个创建失败的提醒。 --- ## 登录方式 # 登录方式 当您需要使用云开发的身份验证服务时,您需要配置您想使用的登录方式。目前云开发支持自定义登录、微信公众平台、微信开放平台登录等多种登录方式。 ## 查看登录方式 您可以使用下面的命令列出环境配置的登录方式列表,查看环境配置的登录方式,以及相关的状态。 ```sh tcb env login list ``` 您会得到类似于下面的输出 ![](https://main.qcloudimg.com/raw/d0e6a4357be0c039b87624a3250f5dcf.png) ## 新建登录方式 您可以使用下面的命令新建登录方式: ```sh tcb env login create ``` 您需要选择配置的平台,登录方式状态,以及对应的 AppId 和 AppSecret,登录方式请选择启用。在添加方式时不会校验 AppId 和 AppSecret 的有效性,只有在请求时,AppId 和 AppSecret 才会被校验,所以请确保您添加的 AppId 和 AppSecret 是有效的。 ## 修改登录方式 您也可以使用 `tcb env login update` 修改已经配置的登录方式,如切换启用状态,修改 AppId 和 AppSecret。 --- ## 安全域名 # 安全域名 当您需要在网页应用中使用云开发的身份验证服务时,您需要将您的网站的域名(发起请求的页面的域名)加入安全域名名单中。安全域名是云开发服务认可的用户请求来源域名,所有来自非安全域名名单中的请求都不会被响应。 ## 查看安全域名 使用下面的命令查看所有配置的安全域名 ```sh tcb env domain list ``` ## 新增安全域名 您可以使用下面的命令添加新的安全域名: ```sh tcb env domain create ``` 您需要指定被添加的域名 domain,当需要添加多个域名时,需要以 `/` 分隔,如 `abc.com/def.com`。 ```sh # 添加一个域名 tcb env domain create www.xxx.com # 添加多个域名 tcb env domain create www.domain1.com/www.domain2.com/www.domain3.com ``` ## 删除安全域名 您可以使用下面的命令删除安全域名: ```sh tcb env domain delete ``` 回车后,CloudBase CLI 会拉取您配置的所有安全域名,您可以选择删除指定的域名。 --- ## CloudBase CLI 常见问题 # CloudBase CLI 常见问题 ## 基础使用 ### 无法登录,CLI 工具没有响应 请检查您的终端能否访问网络。 ## 云函数 ### 函数部署失败的常见原因 - `package.json` 中依赖不存在 ## AI CLI 相关 ### 什么是 CLI?为什么这很重要? CLI(命令行界面)是一种通过文本命令与计算机交互的接口方式。与图形用户界面(GUI)相比,CLI 提供了更直接、更高效的交互方式。 **GUI vs CLI 的核心差异**: - **GUI**:基于图形元素和鼠标操作,适合直观交互和可视化操作 - **CLI**:基于文本命令和键盘输入,适合自动化、批处理和远程操作 CLI 的重要性在于: - **可编程性**:让 AI 编程能力可以被脚本、CI/CD、自动化流程调用 - **可集成性**:可以嵌入到现有的开发工具链和工作流中 - **可扩展性**:不受 GUI 限制,可以在任何环境中运行 - **效率提升**:支持批量处理、远程操作和自动化工作流 ### CloudBase AI CLI 的价格是多少? CloudBase AI CLI 本身完全免费。新用户可获得丰富的免费体验额度: **云开发环境**: - 云函数调用次数、数据库存储空间等基础服务免费额度 - 详细定价请参考腾讯云开发官方定价页面 **AI 模型体验**: - 新环境赠送 100 万 token,支持 DeepSeek、Kimi K2 等主流模型快速体验 - 支持用户自定义配置模型和 API Key - 可按需选择不同模型,灵活控制成本 **付费服务**: - 超出免费额度后按实际使用量计费 - 支持多种付费方式,价格透明 ### CloudBase AI CLI 是如何工作的? CloudBase AI CLI 是一个统一的集成工具,不是独立的 AI 编程工具。它通过统一的命令行界面集成多种 AI 编程 CLI 工具,如 Claude Code、OpenAI Codex、aider、Qwen Code 等。开发者可以通过 `tcb ai -a [工具名]` 选择不同的 AI 工具,支持交互式对话和非交互式脚本模式。CLI 集成了腾讯云开发平台,支持一键开发部署生成的代码到云端,让 AI 编程能力真正成为可编程的基础设施。 ```mermaid sequenceDiagram participant D as 开发者 participant CLI as CloudBase AI CLI participant AI as AI 编程工具 participant Cloud as 云开发平台 D->>CLI: tcb ai -a claude CLI->>AI: 调用 Claude Code AI->>CLI: 返回代码 CLI->>Cloud: 部署到云端 Cloud->>CLI: 部署完成 CLI->>D: 返回结果 Note over D,Cloud: 支持多种应用场景 Note over CLI: 统一管理多种 AI 工具 ``` **应用场景包括:** - **小程序开发者工具**:在微信开发者工具中直接运行,实现小程序开发调试部署一体化 - **VS Code 终端**:在 VS Code 集成终端中使用,与现有开发工作流无缝集成 - **GitHub Actions**:在 CI/CD 流水线中自动执行,实现代码生成和部署的自动化 - **任意终端环境**:支持在服务器、容器、本地开发环境等任何地方运行 ### 为什么现在 AI 编程工具都在推出 CLI 版本? 这是一个重要的技术趋势,原因包括: 1. **从"工具"到"基础设施"的转变**: - 传统 AI 编程工具只是独立的应用程序 - CLI 让 AI 编程能力变成可编程的基础设施 - 可以被脚本、自动化流程、CI/CD 系统调用 2. **提高开发效率**: - 无需在多个 GUI 工具间切换 - 支持批量处理和自动化 - 可以集成到现有开发工作流中 - 大幅减少编码量 3. **适应现代开发环境**: - 云原生开发、容器化部署 - 远程开发、服务器环境 - 持续集成/持续部署(CI/CD) - 推动 AI 从"生成代码"到"全流程协作"的进化 ```mermaid graph TD A[AI IDE] --> B[独立应用程序] B --> C[GUI 界面] C --> D[手动操作] E[AI CLI] --> F[可编程基础设施] F --> G[脚本调用] G --> H[自动化流程] H --> I[CI/CD 集成] style A fill:#ffebee style E fill:#e8f5e8 style B fill:#ffebee style F fill:#e8f5e8 ``` ### CLI 和 GUI 有什么区别?我应该选择哪个? 两者各有优势,最佳实践是结合使用: **GUI(图形界面)的优势**: - 直观的交互体验,适合探索和调试 - 丰富的视觉反馈,便于理解复杂任务 - 提高一次成功率,适合学习和实验 **CLI(命令行界面)的价值**: - 可编程和自动化,适合批处理和 CI/CD - 不受环境限制,可在任何地方运行 - 结构化输出,便于集成到现有工作流 **最佳实践**:**GUI 探索方案,CLI 固化流程**。先用 GUI 工具探索和调试,找到最佳方案后,用 CLI 将流程固化和自动化。 ```mermaid graph LR A[需求分析] --> B[GUI 探索] B --> C[方案验证] C --> D[CLI 固化] D --> E[自动化部署] F[开发阶段] --> B G[生产阶段] --> D style A fill:#e3f2fd style B fill:#fff3e0 style C fill:#fff3e0 style D fill:#e8f5e8 style E fill:#e8f5e8 style F fill:#e3f2fd style G fill:#e8f5e8 ``` ### 我需要学习命令行才能使用 CloudBase AI CLI 吗? CloudBase AI CLI 设计为渐进式学习曲线: **基础使用**(最小学习成本): ```bash # 安装 curl https://static.cloudbase.net/cli/install/install.sh | bash # 启动 AI 助手 tcb ai # 直接描述需求 tcb ai -- -p "帮我创建一个用户管理系统" ``` 详细安装说明请参考 [CloudBase CLI 安装文档](../install)。 **高级功能**(按需学习): - 自动化脚本编写 - CI/CD 集成 - 批量处理 - 自定义工作流 我们提供详细的技术文档和最佳实践指南,支持从入门到精通的完整学习路径。 ### 我如何获得帮助和客户支持? 我们提供多种支持渠道: - 官方文档:https://docs.cloudbase.net/cli-v1/ai/introduce - GitHub 仓库:https://github.com/TencentCloudBase/CloudBase-AI-ToolKit - 技术交流群:微信扫码加入官方技术群 - 工单支持:https://tcb.cloud.tencent.com/help-center ### 我在哪里可以下载 CloudBase AI CLI? CloudBase AI CLI 是免费工具,可以通过以下方式获取: ```bash curl https://static.cloudbase.net/cli/install/install.sh | bash ``` 详细安装方式和说明请参考: - [CloudBase CLI 安装文档](./install) - 完整的安装指南 - [AI CLI 使用文档](./ai/introduce) - AI 功能使用说明 ### CloudBase AI CLI 与 CloudBase AI Toolkit 的关系 CloudBase AI CLI 内置了 CloudBase AI Toolkit 的全部功能,并提供了 CLI 形态的产品体验。如果你之前使用过 CloudBase AI Toolkit,可以继续使用,同时通过安装 CloudBase AI CLI 获得更强大的功能。CloudBase AI Toolkit 将继续维护,为需要轻量级集成的用户提供服务。 详细介绍可参考 [CloudBase AI Toolkit 文档](/ai/cloudbase-ai-toolkit/) --- ## 代码更新 # 代码更新 当您的函数代码发生改变时,您可以使用下面的命令更新您的云函数的代码: ```sh # 更新 app 函数的代码 tcb fn code update app ``` ### code update 和 deploy 命令的区别 `fn code update` 命令和 `fn deploy` 命令的主要区别是:`fn code update` 命令只会更新函数的代码以及执行入口,不会修改函数的其他配置,而 `fn deploy` 命令则会修改函数的代码、配置以及触发器等。 --- ## 预置并发 # 预置并发 预置并发支持并发实例按配置预先启动,同时云函数平台不会主动回收这些实例,会尽可能地保障有相应数量的可以处理请求的并发实例。 您可通过此功能,为函数的指定版本设定预置并发额度。通过配置预置并发,可预先进行计算资源的准备,降低冷启动、运行环境初始化及业务代码初始化引起的耗时。 ## 设置预置并发 您可以使用下面的命令设置函数指定版本的预置并发: ```sh tcb fn set-provisioned-concurrency // name 函数名,version 函数版本,concurrency 预置并发数 ``` ## 查看预置并发 您可以通过下面的命令查看函数预置并发: ```sh tcb fn get-provisioned-concurrency [version] ``` 您会得到类似下面的输出: ![](https://qcloudimg.tencent-cloud.cn/raw/4976ea5cf25c5b28bebbd0262c88f407.png) ## 删除函数预置并发 您可以通过下面的命令删除函数预置并发: ```sh tcb fn delete-provisioned-concurrency ``` --- ## 配置 # 配置 在 CLI 配置文件中,functions 数组可以包含多个函数配置项,函数配置项包含了`函数名称(name)`,`函数运行配置(config)`,`函数调用传入参数(params)`等多项与函数相关的信息,影响着函数操作的行为表现。 ## 函数配置项 一个简单的例子: ```json { // 关联环境 ID "envId": "dev-xxxx", // 函数配置 "functions": [ { // functions 文件夹下函数文件夹的名称,即函数名 "name": "app", // 超时时间,单位:秒 S "timeout": 5, "runtime": "Nodejs10.15", "installDependency": true, "handler": "index.main" } ] } ``` :::caution 注意事项 **0.6.0 版本起,为了简化使用,我们对 `cloudbaserc.json` 配置文件 `functions` 选项中的 `config` 选项进行了扁平化处理,原有 `config` 选项中的所有配置项都可以直接写在 `functions` 选项中。** ::: 下面为目前所有支持的配置项 | 配置项 | 是否必填 | 类型 | 描述 | | :---------------: | :------: | :----------------------------------------------------: | :-----------------------------------------------------------: | | name | 是 | String | 云函数名称,即为函数部署后的名称 | | params | 否 | Object/JSONObject | CIL 调用云函数时的函数入参 | | triggers | 否 | [`Array`](#cloudfunctiontrigger) | 触发器配置 | | handler | 否 | String | 函数处理方法名称,名称格式支持“文件名称.函数名称”形式 | | ignore | 否 | `String/Array` | 部署/更新云函数代码时的忽略文件,支持 glob 匹配规则 | | timeout | 否 | Number | 函数超时时间(1 - 60S) | | envVariables | 否 | Object | 包含环境变量的键值对对象 | | vpc | 否 | [VPC](#vpc) | 私有网络配置 | | runtime | 否 | String | 运行时环境配置,可选值: `Nodejs8.9, Nodejs10.15 Php7, Java8` | | memorySize | 否 | Number | 函数内存,默认值为 256,可选 128、256、512、1024、2048 | | installDependency | 否 | Boolean | 是否云端安装依赖,目前仅支持 Node.js | | codeSecret | 否 | String | 代码加密秘钥,格式为 36 位大小写字母、数字 | - **注:`runtime` 默认为 `Nodejs10.15`,使用 Node.js 运行时可不填,使用 Php 和 Java 则必填。** - **启用代码加密后,将无法在小程序 IDE、腾讯云控制台中查看云函数的代码和信息** #### CloudFunctionTrigger | 名称 | 是否必填 | 类型 | 描述 | | :----: | :------: | :----: | :---------------------------------------------------: | | name | 是 | String | 触发器名称 | | type | 是 | String | 触发器类型,可选值:timer | | config | 是 | String | 触发器配置,在定时触发器下,config 格式为 cron 表达式 | #### VPC | 名称 | 是否必填 | 类型 | 描述 | | :------: | :------: | :----: | :---------: | | vpcId | 是 | String | VPC Id | | subnetId | 是 | String | VPC 子网 Id | ## 更新函数运行时配置 创建函数式,Cloudbase CLI 会为函数提供一些默认的配置,所以您不需要添加配置信息也可以直接部署函数。您也可以通过下面的命令修改函数的运行时配置 ```sh # 更新 app 函数的配置 tcb fn config update app # 更新配置文件中所有函数的配置信息 tcb fn config update ``` 目前支持修改的函数配置包含超时时间 `timeout`、环境变量 `envVariables`、运行时 `runtime`,`vpc`网络以及 `installDependency` 等选项。 CloudBase CLI 会从配置文件中读取函数的配置信息并更新,CloudBase CLI 会更新配置文件中存在的函数的所有配置,暂不支持指定更新单个配置选项。 ## 配置项参考 ```json { // 关联环境 ID "envId": "dev-xxxx", // 函数配置 "functions": [ { // functions 文件夹下函数文件夹的名称,即函数名 "name": "app", // 超时时间,单位:秒 S "timeout": 5, // 环境变量 "envVariables": { "key": "value" }, // 私有网络配置,如果不使用私有网络,可不配置 "vpc": { // vpc id "vpcId": "vpc-xxx", // 子网 id "subnetId": "subnet-xxx" }, // 运行时,目前可选运行包含:Nodejs 18.15, Nodejs 16.13, Nodejs 14.18, Nodejs 12.16, Nodejs 10.15, Php 8.0, Php 7.4, Php 7.2, Python 3.9, Python 3.7, Python 3.6, Python 2.7, Golang 1, Java 8 // 此参数可以省略,默认为 Nodejs10.15 "runtime": "Nodejs10.15", // 是否云端安装依赖,仅支持 Node.js 项目 "installDependency": true, // 函数触发器,说明见文档: https://cloud.tencent.com/document/product/876/32314 "triggers": [ { // name: 触发器的名字 "name": "myTrigger", // type: 触发器类型,目前仅支持 timer (即定时触发器) "type": "timer", // config: 触发器配置,在定时触发器下,config 格式为 cron 表达式 "config": "0 0 2 1 * * *" } ], // 函数处理入口,Node.js 和 PHP 项目可以省略,默认值为 index.main // 因 Java 的 handler 配置较为特殊,所以当运行时为 Java 时,handler 不能省略 // 如:package.Class::mainHandler "handler": "index.main", // fn invoke 本地触发云函数时的调用参数 "params": {}, // 部署/更新云函数时忽略的文件 "ignore": [ // 忽略 markdown 文件 "*.md", // 忽略 node_modules 文件夹 "node_modules", "node_modules/**/*" ] } ] } ``` --- ## 部署 # 部署 :::warning `fn deploy` 命令部署函数的文件大小总计不能超过 50 M,否则可能会部署失败。 ::: 在一个包含 `cloudbaserc.json` 配置文件的项目下,您可以直接使用下面的命令部署云函数: ```sh tcb fn deploy ``` 使用 `fn deploy` 时,`functionName` 选项是可以省略的,当 `functionName` 省略时,Cloudbase CLI 会部署配置文件中的全部函数: ```sh # 部署配置文件中的全部函数 tcb fn deploy ``` ### 全部参数 ```bash Usage: tcb fn deploy [options] [name] 部署云函数 Options: -e, --envId 环境 Id --code-secret 传入此参数将保护代码,格式为 36 位大小写字母和数字 --force 如果存在同名函数,上传后覆盖同名函数 --path 自动创建HTTP 访问服务访问路径 --all 部署配置文件中的包含的全部云函数 --dir 指定云函数的文件夹路径 -h, --help 查看命令帮助信息 ``` ## 代码加密 在部署云函数时,你可以通过指定 `--code-secret codeSecret` 对上传的代码进行加密,`codeSecret` 支持 36 位的大小写字母、数字组成: ``` tcb fn deploy app --code-secret 7sGLwMnhgEfKmkqg2dMjB6xWk2hCxsAgGR6w ``` :::warning 启用代码加密后,将无法在小程序 IDE、腾讯云控制台中查看云函数的代码和信息。 ::: ## 覆盖同名函数 部署函数时,很可能会遇到已经存在同名云函数的情况,此时 Cloudbase CLI 会终止部署,询问是否覆盖同名函数,您可以选择覆盖已有的云函数或者终止部署。 如果您确定要覆盖可能存在的同名云函数,您可以在命令后附加 `--force` 选项指定 Cloudbase CLI 覆盖已存在的云函数。 ```sh tcb fn deploy dev --force ``` **注意**:覆盖函数时,也会覆盖函数的配置和触发器。 ## 默认选项 Cloudbase CLI 为 Node.js 云函数提供了默认选项,您在部署 Node.js 云函数时可以不用指定云函数的配置,使用默认配置即可部署云函数。 云函数默认配置: ```json { // 超时时间 5S "timeout": 5, // 运行时 "runtime": "Nodejs10.15", // 自动安装依赖 "installDependency": true, // 处理入口 "handler": "index.main", // 忽略 node_modules 目录 "ignore": ["node_modules", "node_modules/**/*", ".git"] } ``` ## deploy 命令做了啥? `fn deploy` 会读取 `cloudbaserc.json` 文件中指定函数的配置,并完成以下几项工作: 1. 将函数打包成压缩文件,并上传函数代码。 2. 部署函数配置,包括超时时间、网络配置等。 3. 部署函数触发器。 --- ## 文件层 # 文件层 如果您的云函数拥有较多的依赖库或公共代码文件,您可以使用云函数中的层进行管理。使用层管理,您可以将依赖放在层中而不是部署包中,可确保部署包保持较小的体积。 ## 说明 - 层中的文件将会添加到 `/opt` 目录中,此目录在函数执行期间可访问。 - 如果您的函数已绑定了多个层,这些层将按顺序合并到 `/opt` 目录中。如果同一个文件出现在多个层中,平台将会保留最大序号层里的文件。 - 如果您正在使用层版本被删除,与该层版本绑定的函数将会继续运行。 ## 创建层 您可以使用下面的命令创建层,创建层时,需要指定层别名、环境 Id、以及层内容的路径。层的名称由层别名和环境 Id 组成,层名称为层的唯一标识。每个层支持多种云函数运行时,既可以与多种不同运行时的云函数进行绑定。CLI 创建的层默认支持 `Nodejs8.9`、`Nodejs12.16`、 `Php7`、`Java8` 等 4 个运行时。 上传层内容为 ZIP 文件格式,使用 CLI 上传时,您可以指定 `file` 选项为文件夹或者 ZIP 文件路径,当路径为文件夹时,CLI 将会打包文件夹中的内容为 ZIP 文件。 每次创建成功后,会生成新的层版本,层版本从 1 开始,新的层版本为已有版本的最大值 + 1。文件层不能更新,仅能发布新的层或删除已有的层。文件层的任意一个版本均可以删除,删除后的版本无法再绑定到新的云函数。删除文件层及版本不影响已经绑定的云函数,在已经绑定的函数中仍然可以使用。 单个用户最多创建 20 个文件层,单个文件层版本号从 1 开始,最大可到 200。 :::tip 不建议层文件的大小超过 100M ::: ```bash # 上传文件目录 tcb fn layer create -e envId --file ./content # 上传 ZIP 文件 tcb fn layer create -e envId --file ./file.zip ``` ## 云函数绑定层 云函数绑定层后,就可以在云函数中访问层内容。您可以使用下面的命令绑定层到云函数,`name` 参数为云函数的名称。 ```bash tcb fn layer bind -e envId ``` :::tip 每个函数最大可配置 5 个文件层(层名 + 版本唯一确定) ::: ## 云函数解绑层 您可以使用下面的命令解绑云函数绑定的层,`name` 参数为云函数的名称。 ```bash tcb fn layer unbind -e envId ``` ## 调整层的顺序 您可以使用下面的命令对云函数绑定的层进行重新排序,`name` 参数为云函数的名称。 ```bash tcb fn layer sort -e envId ``` ## 下载层的文件 您可以使用下面的命令下载层的文件,只能下载指定环境的层文件。 ```bash tcb fn layer download -e envId ``` ## 删除层 您可以使用下面的命令删除层,只能删除指定环境中创建的层,当层的所有版本都被删除时,即意味着层也被删除,您无法再看到此层。 ```bash tcb fn layer delete -e envId ``` 在完全删除文件层后,如果创建新的同名文件层,使用原有文件层最大版本 + 1 的版本号。 ## 层展示 您可以使用下面命令获取层的相关信息。 ```bash # 展示所有环境中的层 tcb fn layer list # 展示指定环境中的层 tcb fn layer list -e envId # 展示函数绑定的层 tcb fn layer list -e envId --name # 展示层的版本信息 tcb fn layer list -e envId --layer ``` --- ## 日志 # 日志 您可以通过下面的命令打印云函数的运行日志,使用此命令时必须指定函数的名称: ```sh # 查看 app 函数的调用日志 tcb fn log app ``` 输出: ```sh 请求时间:2019-08-15 12:12:00 函数名称:app 计费时间(ms):100 运行时间(ms):0.38 调用次数:1 占用内存:35.730 MB 请求 Id:d451aac7-bf12-11e9-xxxx-525400697544 调用状态:成功 返回结果:{"Message":"","Time":"2019-08-15T04:12:00Z","TriggerName":"myTrigger","Type":"Timer"} 日志: ... END RequestId: d451aac7-bf12-11e9-xxxx-525400697544 Report RequestId: d451aac7-bf12-11e9-xxxx-525400697544 Duration:0ms Memory:256MB MaxMemoryUsed:35.730469MB ``` 默认情况下,Cloudbase CLI 会打印最近的 20 条日志,您可以通过在命令后附加下面的可用选项指定返回日志的筛选条件: ```sh -i, --reqId 函数请求 Id -o, --offset 数据的偏移量,Offset + Limit不能大于10000 -l, --limit 返回数据的长度,Offset + Limit不能大于10000 --order 以升序还是降序的方式对日志进行排序,可选值 desc 和 asc --orderBy 根据某个字段排序日志,支持以下字段:function_name,duration, mem_usage, start_time --startTime 查询的具体日期,例如:2019-05-16 20:00:00,只能与endtime 相差一天之内 --endTime 查询的具体日期,例如:2019-05-16 20:59:59,只能与startTime 相差一天之内 -e, --error 只返回错误类型的日志 -s, --success 只返回正确类型的日志 ``` 如:`tcb fn log app -l 2` 打印 `app` 函数的最新 2 条日志信息 ```sh 请求时间:2019-08-15 17:04:43 函数名称:test-scf 计费时间(ms):100 运行时间(ms):0.44 调用次数:1 占用内存:NaN MB 请求 Id:68649b0f-af84-11e9-a803-525400e8849e 调用状态:成功 返回结果:{"key":"test","userInfo":{"appId":"wx9c4c30a432a38ebc","openId":"on01a6UeSuBLGTQpc_PAjS_RK_4o"}} 日志:.... ``` --- ## 管理 # 管理 云函数是一段运行在云端的代码,无需管理服务器,在开发工具内编写、一键上传部署即可运行后端代码。云开发中的云函数可让用户将自身的业务逻辑代码上传,并通过云开发的调用触发函数,从而实现后端的业务运作。 ## 查看函数 您可以使用下面的命令列出所有云函数,查看函数的基本信息: ```sh tcb fn list ``` 您会得到类似下面的输出: ![](https://main.qcloudimg.com/raw/248eadf2caeb4d1609647deb475bc429.png) ### 指定返回条数和偏移量 默认情况下,`fn list` 命令只会列出前 20 个函数,如果您的函数较多,需要列出其他的函数,您可以通过下面的选项指定命令返回的数据长度以及数据的偏移量: ```sh -l, --limit 返回数据长度,默认值为 20 -o, --offset 数据偏移量,默认值为 0 ``` 如: ```sh # 返回前 10 个函数的信息 tcb fn list -l 10 # 返回第 3 - 22 个函数的信息(包含 3 和 22) tcb fn list -l 20 -o 2 ``` ## 下载云函数代码 您可以通过下面的命令下载云函数代码: ```sh tcb fn code download [destPath] ``` 默认情况下,函数代码会下载到 [`functionRoot`](https://docs.cloudbase.net/cli-v1/config.html) 下,以函数名称作为存储文件夹,您可以指定函数存放的文件夹地址,函数的所有代码文件会直接下载到指定的文件夹中。 ## 触发函数 您可以在本地通过 Cloudbase CLI 直接触发您的云函数: ```sh # 触发 app 函数 tcb fn invoke app # 触发配置文件中的全部函数 tcb fn invoke ``` ### 触发函数时传入参数 ```sh # 触发 app 函数,并传入参数 tcb fn invoke app --params '{"key1": "value1", "key2": "value2"}' ``` :::tip 注意 如果您使用的是 Windows 系统,传入参数时需要使用双引号包裹参数字符串,并且需要使用 `\` 转义双引号,如: ```sh tcb fn invoke app --params "{\"key1\": \"value1\", \"key2\": \"value2\"}" ``` ::: ## 查看函数详情 前面提到的 `fn list` 命令只能查看函数的简单信息,如果您想查看函数的详细信息,您可以使用下面的命令: ```sh # 查看 app 函数的详情 tcb fn detail app ``` 输出 ```sh 状态:部署完成 代码大小(B):1695 环境变量(key=value):key=value 函数名称:test 执行方法:index.main 内存配置(MB):256 修改时间:2019-08-19 21:15:39 环境 Id:dev-xxx 运行环境:Nodejs10.15 超时时间(S):20 网络配置:无 触发器: myTrigger:{"cron": "0 0 2 1 * * *"} 函数代码(Java 函数以及入口大于 1 M 的函数不会显示): 'use strict'; exports.main = async (event, context, callback) => { console.log(event); return 'hello world' }; ``` ## 删除函数 您可以通过下面的命令删除函数 ```sh # 删除 app 函数 tcb fn delete app # 删除配置文件中的所有的函数 tcb fn delete ``` ## 复制函数 您可以通过下面的命令快速复制一个已经存在的函数: ```sh # 复制 app 函数为 app2 函数 tcb fn copy app app2 ``` 使用 `fn copy` 命令时需要指定原函数名称以及复制后新的函数名称。当前环境 Id 和目标环境环境 Id 是可选的,如果没有指定目标环境 Id,函数会被复制到当前环境中。 如果新函数的名称已经存在,则复制操作会被终止。如果您想要覆盖已经存在的函数,您可以使用下面的命令 ### 覆盖同名函数 ```sh # 复制 app 函数为 app2 函数,如果 app2 函数存在,覆盖已经存在的 app2 函数 tcb fn copy app app2 --force ``` **注意**:复制函数操作不会复制函数的函数的触发器。 --- ## 流量路由 # 流量路由 云函数支持流量路由设置。通过该设置,您可便捷控制函数版本在实际使用场合或环境中的灰度上线或回滚流程,避免一次性上线可能带来的风险。 ## 配置函数版本路由 您可以使用下面的命令配置函数版本路由: ```sh tcb fn config-route [version2] [traffic2] ``` :::tip 如果只指定 version1 及 traffic1,其余流量均分配至 $LATEST 版本。 如果同时指定 version1 traffic1 及 version2 traffic2,全部流量分配至两版本上。 ::: ## 查看函数版本路由 您可以通过下面的命令查看函数版本路由配置: ```sh tcb fn get-route ``` 您会得到类似下面的输出: ![](https://qcloudimg.tencent-cloud.cn/raw/e6e70a7ec67de9a08e37e8bd847e91a7.png) --- ## 触发器 # 触发器 触发器是按照一定规则触发函数的模块的抽象,CloudBase 云函数目前仅支持定时触发器。 如果云函数需要定时/定期执行,即定时触发,您可以使用云函数定时触发器。已配置定时触发器的云函数,会在相应时间点被自动触发,函数的返回结果不会返回给调用方。 一个例子: ```json { "version": "2.0", "envId": "xxx", "functions": [ { // triggers 字段是触发器数组,目前仅支持一个触发器,即数组只能填写一个,不可添加多个 "triggers": [ { // name: 触发器的名字,规则见下方说明 "name": "myTrigger", // type: 触发器类型,目前仅支持 timer (即定时触发器) "type": "timer", // config: 触发器配置,在定时触发器下,config 格式为 cron 表达式,规则见下方说明 "config": "0 0 2 1 * * *" } ] } ] } ``` ## 创建函数触发器 您可以使用下面的命令创建一个触发器: ```sh # 创建 app 函数配置的触发器 tcb fn trigger create app ``` Cloudbase CLI 会自动读取 `cloudbaserc.json` 文件中指定函数配置的定时触发器,并创建云函数触发器。如果配置文件中没有包含触发器配置,则会创建失败。 一个函数可以包含多个触发器,一个触发器包含了以下 3 个主要信息:`name, type, config` ```json { // name: 触发器的名字,规则见下方说明 "name": "myTrigger", // type: 触发器类型,目前仅支持 timer (即定时触发器) "type": "timer", // config: 触发器配置,在定时触发器下,config 格式为 cron 表达式 "config": "0 0 2 1 * * *" } ``` 当没有指定函数名时,Cloudbase CLI 会创建 `cloudbaserc.json` 文件包含的**所有函数**的**所有触发器**。 ## 删除函数触发器 您可以使用下面的命令删除函数的触发器: ```sh # 删除 app 函数的名为 trigger 的触发器 tcb fn trigger delete app trigger ``` 同样,当没有指定函数名时,Cloudbase CLI 会删除 `cloudbaserc.json` 文件包含的**所有函数**的**所有触发器**。当只指定了函数名时,Cloudbase CLI 会删除指定函数的所有触发器,当同时指定了函数名称和触发器名称时,Cloudbase CLI 只会删除指定的触发器。 ```sh # 删除 cloudbaserc.json 文件中所有函数的所有触发器 tcb fn trigger delete # 删除函数 app 的所有触发器 tcb fn trigger delete app # 删除函数 app 的触发器 trigger tcb fn trigger delete app trigger ``` ## 触发器规则 - 定时触发器名称(name) :最大支持 60 个字符,支持 `a-z`, `A-Z`, `0-9`, `-` 和 `_`。必须以字母开头,且一个函数下不支持同名的多个定时触发器。 - 定时触发器触发周期(config):指定的函数触发时间。填写自定义标准的 Cron 表达式来决定何时触发函数。有关 Cron 表达式的更多信息,请参考以下内容。 Cron 表达式有七个必需字段,按空格分隔。其中,每个字段都有相应的取值范围: | 排序 | 字段 | 值 | 通配符 | | ------ | ---- | --------------------------------------------------------------------------------------- | --------- | | 第一位 | 秒 | 0 - 59 的整数 | `, - * /` | | 第二位 | 分钟 | 0 - 59 的整数 | `, - * /` | | 第三位 | 小时 | 0 - 23 的整数 | `, - * /` | | 第四位 | 日 | 1 - 31 的整数(需要考虑月的天数) | `, - * /` | | 第五位 | 月 | 1 - 12 的整数或 JAN、FEB、MAR、APR、MAY、JUN、JUL、AUG、SEP、OCT、NOV 和 DEC | `, - * /` | | 第六位 | 星期 | 0 - 6 的整数或 MON、TUE、WED、THU、FRI、SAT 和 SUN,其中 0 指周日,1 指星期一,以此类推 | `, - * /` | | 第七位 | 年 | 1970 - 2099 的整数 | `, - * /` | ### 通配符 | 通配符 | 含义 | | ------------- | ---------------------------------------------------------------------------------------------------------------------------- | | `,`(逗号) | 代表取用逗号隔开的字符的并集。例如:在“小时”字段中 1,2,3 表示 1 点、2 点和 3 点 | | `-`(短横线) | 包含指定范围的所有值。例如:在“日”字段中,1 - 15 包含指定月份的 1 号到 15 号 | | `*`(星号) | 表示所有值。在“小时”字段中,`*` 表示每个小时 | | `/`(正斜杠) | 指定增量。在“分钟”字段中,输入 1/10 以指定从第一分钟开始的每隔十分钟重复。例如,第 11 分钟、第 21 分钟和第 31 分钟,以此类推 | > !在 Cron 表达式中的“日”和“星期”字段同时指定值时,两者为“或”关系,即两者的条件均生效。 ### 示例 下面列举一些 Cron 表达式和相关含义: - `*/5 * * * * * *` 表示每 5 秒触发一次 - `0 0 2 1 * * *` 表示在每月的 1 日的凌晨 2 点触发 - `0 15 10 * * MON-FRI *` 表示在周一到周五每天上午 10:15 触发 - `0 0 10,14,16 * * * *` 表示在每天上午 10 点,下午 2 点,下午 4 点触发 - `0 */30 9-17 * * * *` 表示在每天上午 9 点到下午 5 点内每半小时触发 - `0 0 12 * * WED *` 表示在每个星期三中午 12 点触发 --- ## 函数版本 # 函数版本 云函数的版本包含了函数的代码及配置。在实际的开发过程中,可通过发布版本固定函数代码及配置内容,减少影响业务系统的问题因素。 :::tip 函数在创建后缺省具有一个最近版本/最新版本($LATEST),仅 $LATEST 版本的配置和代码支持修改。发布时以 $LATEST 版本的配置和代码作为基础进行发布,生成新版本。 ::: ## 发布新版本 您可以使用下面的命令发布新的函数版本: ```sh tcb fn publish-version [description] // name 函数名,description 版本描述 ``` ## 查看函数版本列表 您可以通过下面的命令查看函数版本: ```sh tcb fn list-function-versions ``` 您会得到类似下面的输出: ![](https://qcloudimg.tencent-cloud.cn/raw/b4f99416051cc68986e052b910923c01.png) --- ## 静态网站托管 # 静态网站托管 云开发为开发者提供静态网页托管能力,支持 HTML、CSS、JavaScript、字体等静态资源的分发。底层基于腾讯云对象存储 COS 和全球 CDN 网络,为您的网站提供高性能、高可用的访问体验。 ## 前置条件 在使用 CLI 操作静态网站服务前,请确保: 1. **开通静态网站服务**:前往 [云开发控制台](https://console.cloud.tencent.com/tcb) 开通静态网站服务 2. **环境类型要求**:仅支持按量付费环境,预付费环境暂不支持 3. **手动开通**:静态网站托管服务需要在环境创建后单独开通 :::tip 提示 目前静态网站托管功能仅在腾讯云云开发控制台支持,小程序 IDE 控制台暂不支持。 ::: ## 部署网站 ### 全量部署 使用 `tcb hosting deploy` 命令可以将当前目录下的所有文件部署到静态网站。 ```bash # 进入构建目录 cd docs # 部署当前目录下的所有文件 tcb hosting deploy -e envId ``` ### 指定文件部署 您可以指定特定的文件或文件夹进行部署: ```bash # 基本语法 tcb hosting deploy [cloudPath] -e envId ``` **参数说明:** - `localPath`:本地文件或文件夹路径 - `cloudPath`:云端目标路径(可选,默认为根目录) - `envId`:环境 ID **示例:** ```bash # 将 hosting 目录下的所有文件部署到根目录 tcb hosting deploy hosting -e envId # 将本地 index.html 部署到云端根目录 tcb hosting deploy ./index.html -e envId # 将 static 目录下的 index.js 部署到云端 static/index.js tcb hosting deploy ./static/index.js static/index.js -e envId ``` ### 部署限制 - **文件大小**:单个文件最大支持 50TB - **文件数量**:无限制 - **网络优化**:如遇到大量文件上传报错 `{ message: 'socket hang up', code: 'ECONNRESET' }`,请先执行: ```bash export COS_SDK_KEEPALIVE=false ``` ### SPA 应用配置 :::caution Vue History 模式 使用 Vue Router 的 history 模式时,需要在 [静态网站控制台](https://console.cloud.tencent.com/tcb/hosting) 的设置页面配置错误页面为应用的入口页面(通常是 `index.html`)。 ::: ## 管理网站 ### 查看服务信息 查看静态网站的状态、访问域名等详细信息: ```bash tcb hosting detail -e envId ``` ### 查看文件列表 列出静态网站存储空间中的所有文件: ```bash tcb hosting list -e envId ``` ### 删除文件 删除静态网站中的指定文件或文件夹: ```bash # 删除指定文件或文件夹 tcb hosting delete -e envId # 删除所有文件(cloudPath 为空) tcb hosting delete -e envId ``` **示例:** ```bash # 删除根目录下的 index.html tcb hosting delete index.html -e envId # 删除 static 文件夹及其所有内容 tcb hosting delete static -e envId # 清空整个静态网站 tcb hosting delete -e envId ``` ## 路径说明 ### 路径格式 - **localPath**:本地文件或文件夹路径 - 格式:`目录/文件名` - 示例:`./index.js`、`static/css/index.css` - **cloudPath**:云端文件或文件夹的相对路径 - 格式:`目录/文件名`(相对于根目录) - 示例:`index.js`、`static/css/index.js` ### 跨平台注意事项 :::caution Windows 系统 - **localPath**:使用系统路径格式,通常使用 `\` 分隔符 - **cloudPath**:统一使用 `/` 分隔符,与操作系统无关 ::: ## 常见问题 ### 上传失败处理 如果遇到网络连接问题导致上传失败,可以尝试: ```bash # 关闭 SDK 长连接 export COS_SDK_KEEPALIVE=false # 然后重新执行部署命令 tcb hosting deploy -e envId ``` ### 域名访问 部署完成后,您可以通过以下方式访问网站: - 在控制台查看分配的默认域名 - 配置自定义域名(需要 ICP 备案) --- ## 安装 # 安装 import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; **推荐:一键安装脚本** 只需几秒即可完成安装(相比 npm 安装通常需几分钟),体验更快更便捷: ```bash curl https://static.cloudbase.net/cli/install/install.sh -fsS | bash ``` ```powershell irm https://static.cloudbase.net/cli/install/install.ps1 | iex ``` **如需使用 npm/yarn/pnpm 安装:** ```sh npm i -g @cloudbase/cli ``` 或者使用 Yarn 1.x : ```sh yarn global add @cloudbase/cli ``` 或者 Pnpm: ```sh pnpm add -g @cloudbase/cli ``` 如果访问官方 npm 源有问题,一般安装过程中报类似 "ETIMEOUT"、"npm ERR! network request to https://registry.npmjs.org/@cloudbase%2fcli failed" 这种错误,这个时候需要临时指定一个国内 npm 镜像源: ```sh npm i -g @cloudbase/cli --registry=http://mirrors.cloud.tencent.com/npm/ ``` ```sh yarn global add @cloudbase/cli --registry=http://mirrors.cloud.tencent.com/npm/ ``` ## AI 开发 使用 `tcb ai` 即可开启 AI 开发 ```sh tcb ai ``` ## 所有命令 使用 `tcb -h` 查看所有可用命令 ```sh tcb -h ``` ## [可选]使用代理 使用 CloudBase CLI 时,需要您的终端能够访问公网。**如果您的终端无法直接访问公网**,您可以设置 HTTP 代理使 CLI 能够正常使用。CLI 会读取 `http_proxy` 或 `HTTP_PROXY` 环境变量,自动设置网络代理服务。 例如,您可以在终端中运行以下命令,设置 CLI 通过 `http://127.0.0.1:8000` 的代理服务访问网络: ```bash export HTTP_PROXY=http://127.0.0.1:8000 ``` :::warning `http://127.0.0.1:8000` 只是一个示例,请勿直接使用,具体的代理配置根据你的网络配置决定 ::: 上面的命令只是临时设置,当您关闭终端后,代理会自动失效,下次开启终端后需要重新设置。如果您需要一直通过代理访问公网,可以把命令加入到终端的配置文件中。 --- ## 介绍 # [介绍](https://github.com/TencentCloudBase/cloud-base-cli) ![npm (tag)](https://img.shields.io/npm/v/@cloudbase/cli) 云开发(Tencent CloudBase,TCB)是腾讯云提供的云原生一体化开发环境和工具平台,为开发者提供高可用、自动弹性扩缩的后端云服务,包含计算、存储、托管等 serverless 化能力,可用于云端一体化开发多种端应用(小程序,公众号,Web 应用,Flutter 客户端等),帮助开发者统一构建和管理后端服务和云资源,避免了应用开发过程中繁琐的服务器搭建及运维,开发者可以专注于业务逻辑的实现,开发门槛更低,效率更高。 CloudBase CLI 是云开发(Tencent CloudBase,TCB)开源的命令行界面交互工具,用于帮助用户快速、方便的部署项目,管理云开发资源。 ## 使用 - [安装](/cli-v1/install):使用 Node.js 安装 CloudBase CLI - [快速开始](/cli-v1/quick-start):使用 CloudBase CLI 部署一个云函数 --- ## 登录方式 # 登录方式 在获取到您的授权之后,Cloudbase CLI 才能操作您的资源。Cloudbase CLI 提供了两种获取授权的方式:**腾讯云-云开发控制台授权**以及**腾讯云-云 API 密钥授权**。 ## 腾讯云-云开发控制台授权 在您的终端中输入下面的命令 ```sh tcb login ``` CloudBase CLI 会自动打开云开发控制台获取授权,您需要点击同意授权按钮允许 CloudBase CLI 获取授权。如您没有登录,您需要登录后才能进行此操作。 ## 腾讯云-云 API 密钥授权 > **注意**:腾讯云 API 密钥可以操作您名下的所有腾讯云资源,请妥善保存和定期更换密钥,当您更换密钥后,请及时删除旧密钥。 首先您需要到腾讯云官网获取[云 API 密钥](https://console.cloud.tencent.com/cam/capi),然后在终端中输入下面的命令: ```sh tcb login --key ``` 回车后,请按提示输入云 API 密钥的 SecretId 和 SecretKey 既可完成登录。 ## CI 中的登录 在 CI(持续集成)构建中,您可以使用下面的方式通过 API 秘钥直接登录,避免交互式输入 ```sh tcb login --apiKeyId xxx --apiKey xxx ``` ## 临时秘钥登录 通过腾讯云临时秘钥登录,可以在某些比较敏感的场景下使用,使用短期有效的秘钥 ```sh tcb login --apiKeyId xxx --apiKey xxx --token xxx ``` ## 子账号 子账号需要主账号授权资源访问后,才可使用云开发资源。子账号默认没有访问云开发资源的权限,因此使用子账号登录云开发控制台,无法访问云开发资源。 此时,需要为子账号添加预设策略的方式来访问云开发资源。具体操作步骤如下: 1. 登录 [CAM 控制台](https://console.cloud.tencent.com/cam/overview),选择左侧菜单【用户】>【用户列表】。 2. 进入用户列表页面,单击【新建用户】。 3. 进入新建用户页面,根据提示填写用户相关信息。 4. 信息填写完毕后,前往策略列表中选择 TCB 预设授权策略。 5. 单击【完成】,即可完成创建子账号。 除了上述在创建子账号时添加策略的方式外,也可通过策略关联用户的方式授权,具体请参见 [授权管理](https://cloud.tencent.com/document/product/598/10602) 指引。 ### TCB 预设策略 您可以使用以下预设策略为您的子账号授予相关权限: | 策略 | 描述 | | -------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | | `QcloudAccessForTCBRole` | 该策略授予云开发(TCB)对云资源的访问权限。 | | `QcloudAccessForTCBRoleInAccessCloudBaseRun` | 该策略供云开发(TCB)服务角色(TCB_QcsRole)进行关联,用于 TCB 访问其他云服务资源。包含私有网络 VPC、云服务器 CVM 相关操作权限。 | :::warning 该权限包含底层对象存储、云函数、日志、监控、VPC 等资源的全读写权限,一旦为子账号添加此策略,将意味着子账号拥有上述资源,并自动拥有后续新增资源的全读写权限,因此请慎重选择,详情可点击权限名称跳转查看权限规则。 ::: 以下预设策略是在您使用 TCB 服务时,授予子账号 CAM 只读访问权限。对子账号进行`QcloudCamReadOnlyAccess`授权操作后,子账号可使用 CLI 工具网页授权登录;若未进行授权,仅可使用子账号 **API 密钥**进行登录。您可根据需要对子账号进行开通: | 策略 | 描述 | | ------------------------- | ----------------------------------------- | | `QcloudCamReadOnlyAccess` | 该策略授予用户与权限(CAM)只读访问权限。 | --- ## 从 v0 升级到 v1 # 从 v0 升级到 v1 CloudBase CLI v1 版本已经规划了许久,在 v1 版本中,我们完全改变了命令的使用方法,简化了部分命令的长度,并向更为标准的规范对齐,这也是后期我们努力的发展发向:为用户提供更简单、更强大的 CLI 工具。 同时,CloudBase CLI v1 版本完全兼容了 CloudBase v.0 中的命令用法,您不用担心升级所可能带来的问题,这并不是一次破坏性的、不兼容的升级。尽管如此,我们任建议您使用新的命令,这是未来的发展方向。 ## 升级说明 ### tcb 命令 在 v1 版本中,我们引入了 `tcb` 命令,可以一键创建、部署云开发项目, ### 命令格式变更 在 v1 版本中,所有的命令由 `env:list` 格式变成了 `env list` 格式,即命令中所有的 `:` 符号修改为空格使用。这有助于我们合并同类型的命令,提供更简单易懂的命令 help 提示。同时也符合大部分的命令使用习惯,降低学习成本。 ### 命令名变更 1. 原 `functions` 命令改为了简短的 `fn` 命令,如 `tcb fn list` 2. 原云接入 `service` 命令改为了 `access` 命令 ### 移除编程式 API 在 v1 版本中,我们彻底移除了 CLI 的编程式使用,如果你需要以管理员身份操作云开发的资源,请使用 [`@cloudbase/manager-node`](https://docs.cloudbase.net/api-reference/manager/node/introduction.html) SDK --- ## 模板拉取 # 模板拉取 CloudBase CLI 提供了便捷的模板拉取功能,支持内置模板、Git 仓库和子目录下载。 ## 内置模板 ### 支持的模板 - `miniprogram` - 微信小程序 + CloudBase - `react` - Web 应用 - React + CloudBase - `vue` - Web 应用 - Vue + CloudBase - `uniapp` - 跨端应用 - UniApp + CloudBase - `rules` - AI 规则和配置 ### 基本用法 ```bash # 下载模板 tcb pull -s miniprogram tcb pull -s react tcb pull -s vue # 指定输出目录 tcb pull -s miniprogram --output ./my-project # 强制覆盖 tcb pull -s vue --output ./existing-project --force # 查看可用模板 tcb pull list ``` ## 云开发模板中心 ### 开源项目模板 云开发模板中心提供了丰富的开源项目模板,涵盖电商、管理系统、游戏、工具等多种场景。您可以在 [云开发模板中心](https://tcb.cloud.tencent.com/cloud-template) 浏览和选择适合的开源项目模板。 #### 使用流程 1. **浏览模板**: 访问 [云开发模板中心](https://tcb.cloud.tencent.com/cloud-template),在"开源项目"分类中浏览模板 2. **获取 Git 链接**: 点击感兴趣的模板,查看详情页面获取 Git 仓库链接 3. **拉取模板**: 使用 `tcb pull` 命令拉取模板到本地 4. **AI 开发**: 使用 `tcb ai` 或者其他 AIIDE 开始 AI 辅助开发 #### 示例操作 ```bash # 1. 拉取开源项目模板 tcb pull -s https://github.com/example/ai-ecommerce-miniprogram # 2. 进入项目目录 cd ai-ecommerce-miniprogram # 3. 使用 AI CLI 开始开发 tcb ai ``` #### 支持的其他 AI IDE 如需配置其他 AI IDE,请参考 [CloudBase AI ToolKit 快速开始](https://docs.cloudbase.net/ai/cloudbase-ai-toolkit/getting-started) 中的"其他 IDE 配置方式"部分,包含: - **Cursor** - 独立 IDE - **WindSurf** - 独立 IDE、VSCode、JetBrains 插件 - **CodeBuddy** - VS Code、JetBrains、微信开发者工具、独立 IDE - **通义灵码** - 独立 IDE、VS Code、JetBrains 插件 - **百度 Comate** - VS Code、JetBrains 插件 - **GitHub Copilot** - VS Code 插件 - **Claude Code** - 命令行工具 - 更多工具配置指南... ## Git 仓库 ### 支持的格式 - GitHub: `https://github.com/user/repo` - Gitee: `https://gitee.com/user/repo` - SSH: `git@github.com:user/repo.git` ### 基本用法 ```bash # 拉取整个仓库 tcb pull -s https://github.com/TencentCloudBase/awesome-cloudbase-examples # 拉取子目录 tcb pull -s https://github.com/TencentCloudBase/awesome-cloudbase-examples/tree/master/web/overcooked-game ``` ## AI 命令集成 在 AI 开发时直接指定模板: ```bash # 使用 AI 命令并下载模板 tcb ai --template rules tcb ai --template miniprogram tcb ai --template react ``` ## 错误处理 - **目录不为空**: 系统会询问是否覆盖,或使用 `--force` 强制覆盖 - **Git 仓库不存在**: 检查地址是否正确,确认为公开仓库 - **网络错误**: 检查网络连接后重试 - **子目录路径无效**: 确认路径和分支名称正确 ## 注意事项 - Windows 系统使用 `\` 分隔符,云端路径使用 `/` 分隔符 - Git 子目录路径必须使用 `/` 分隔符 - 建议在空目录中拉取模板 --- ## 快速开始 # 快速开始 此快速入门会引导你使用 CloudBase CLI 部署一个 Vue Website ## 0. 开通云开发服务 如果你已经拥有按量计费的云开发环境,你可以跳过此步骤。 在开始使用云开发服务之前,您需要登录腾讯云 [云开发控制台](https://console.cloud.tencent.com/tcb),确保已经开通了云开发服务,并且已经创建了可以使用的环境。如果您不了解如何创建环境,可以参照云开发快速入门 - [开通环境](https://cloud.tencent.com/document/product/876/41391) 文档进行操作。 ## 1. 登录 首先登录您的腾讯云账号,在获取到您的授权之后,CloudBase CLI 才能操作您的资源。CloudBase CLI 提供了两种获取授权的方式:腾讯云-云开发控制台授权以及腾讯云-云 API 密钥授权。 #### 腾讯云-云开发控制台授权 在您的终端中输入下面的命令 ```sh tcb login ``` CloudBase CLI 会自动打开云开发控制台获取授权,您需要点击同意授权按钮允许 CloudBase CLI 获取授权。如您没有登录,您需要登录后才能进行此操作。 :::tip 如果你的账号不是主账户,请参考登录说明中的[子账号登录](https://docs.cloudbase.net/cli-v1/login.html#zi-zhang-hao)。 ::: #### 腾讯云-云 API 密钥授权 :::tip 腾讯云 API 密钥可以操作您名下的所有腾讯云资源,请妥善保存和定期更换密钥,当您更换密钥后,请及时删除旧密钥。 ::: 首先您需要到腾讯云官网获取 [云 API 密钥](https://console.cloud.tencent.com/cam/capi),然后在终端中输入下面的命令: ```sh tcb login --key ``` 回车后,请按提示输入云 API 密钥的 SecretId 和 SecretKey 即可完成登录。 #### CI 中的登录 在 CI(持续集成)构建中,您可以使用下面的方式通过 API 密钥直接登录,避免交互式输入: ```sh tcb login --apiKeyId xxx --apiKey xxx ``` ## 2. 创建项目 ### 初始化 您可以使用下面的命令创建一个项目,创建项目时 CloudBase CLI 根据您输入的项目名创建一个文件夹,并写入相关的配置和模板文件。 :::tip 使用 tcb new 命令需要 CLI 1.0+ 版本 ::: ```sh tcb new app node-starter ``` 云开发项目是和云开发环境资源关联的实体,云开发项目聚合了云函数、数据库、文件存储等服务,您可以在云开发项目中编写函数,存储文件,并通过 CloudBase 快速的操作您的云函数、文件存储、数据库等资源。 云开发项目文件结构: ``` . ├── .gitignore ├── functions // 云函数目录 │   └── node-app │   └── index.js └── cloudbaserc.json // 项目配置文件 ``` ### 编写函数 默认情况下,所有 Node 和 PHP 函数都统一存放在 `functions` 目录下,并以函数名作为文件夹名称,如 `functions/node-app/index.js`。对于 Java 函数时,则需要将 jar 文件名修改为函数名称,放在`functions`目录下即可,例如 `functions/cloudbase.jar`。 如果您想将函数存放在其他目录,您可以通过配置文件中的`functionRoot`选项指定您想存放函数的目录,`functionRoot`选项代表了云函数文件夹相对于项目根目录的路径。 例如,创建一个 Node.js 函数 App,下面是`functions/app/index.js`的内容 ``` "use strict"; exports.main = async (event, context) => { console.log("Hello World"); console.log(event); console.log(context); }; ``` ### 修改配置 默认情况下,项目配置存储在 `cloudbaserc.json` 文件中,默认生成的函数配置为 Node 语言相关的配置,其他语言如 PHP,Java 等需要修改对应的 handler(运行入口)和 runtime(运行时),参考 [配置文件 ](https://cloud.tencent.com/document/product/876/41541) cloudbaserc.json 文件说明部分。 如果您想指定其他文件作为配置文件,可以在使用 CLI 命令时添加`--config-file config-path`参数指定配置文件,目前支持 JS 和 JSON 格式的配置文件。 ```json { "envId": "xxx", "functionRoot": "./functions", "functions": [ { "name": "node-app", "timeout": 5, "envVariables": {}, "runtime": "Nodejs10.15", "memorySize": 128, "handler": "index.main" } ] } ``` ## 3. 部署函数 在项目根目录下(cloudbaserc.json 所在目录)运行 `tcb fn deploy node-app` 命令,即可部署 `node-app` 函数 ```sh tcb fn deploy node-app ``` 部署完成后可以使用 `tcb fn list` 命令查看已经部署完成的函数列表 ```sh tcb fn list ``` --- ## 多地域 # 多地域 CLI 1.2.0 版本起,增加了对多地域的支持,你可以通过 CLI 操作云开发不同地域的资源。 默认情况下,CLI 可以直接操作上海地域的环境,当你需要操作其他地域的环境时,请通过 `-r` 全局参数指定地域,如 ```bash # 展示出广州地域的环境列表 tcb env list -r gz # 将函数部署到广州地域的环境 tcb fn deploy app -r gz -e envID ... ``` 当不指定 `-r` 参数时,即视为环境为上海地域的环境。 :::tip `-r` **参数适用于全部的命令** ::: ## 地域列表 `gz` 为广州地域的缩写,全称为 `ap-guangzhou`,在使用 CLI 时,可以使用缩写,下面是全部地域的简称信息 ```bash # 已支持地域 gz: ap-guangzhou bj: ap-beijing sh: ap-shanghai # 可能会支持的地域 # nj: ap-nanjing # cd: ap-chengdu # cq: ap-chongqing ``` ## 配置文件 你也可以在配置文件中指定环境的地域信息,无需添加 `-r` 参数,如下所示 ```json { "version": "2.0", "envId": "envId", "region": "ap-guangzhou", "framework": { "name": "koa-starter", "plugins": { "node": { "use": "@cloudbase/framework-plugin-node", "inputs": { "name": "koa-starter", "path": "/koa-starter" } } } } } ``` --- ## 代码部署 # 代码部署 将云托管项目代码部署到云托管环境 > 云托管代码项目可参考示例:[nodejs_hello_world](https://github.com/TencentCloudBase/awesome-cloudbase-examples/tree/master/cloudbaserun/node) ## 基本用法 输入以下命令即可开始交互式部署,在此过程中 CLI 会自动询问您需要发布的服务、环境等信息 ```sh tcb cloudrun deploy ``` ## 进阶用法 手动指定相关参数来部署: ```sh tcb cloudrun deploy -e -s ``` ## 命令行参数 支持的命令行参数如下: ```sh Options: -e, --envId 环境 Id -s, --serviceName 服务名称 --source 云托管代码文件所在目录路径。默认为当前路径 -h, --help 查看命令帮助信息 ``` --- ## 介绍 # 介绍 `函数型云托管` 是云开发推出的支持在 `云托管` 上运行 `云函数代码` 的一种托管模式。见:[函数型云托管](../../cbrf/intro) ```sh npm i @cloudbase/cli -g ``` 如何编写云函数可参考: [函数编写指南](../../cbrf/how-to-writing-functions-code.md) --- ## HTTP 访问服务 # HTTP 访问服务 HTTP 访问服务支持通过 HTTP 链接访问云开发资源。 可以通过 CLI 工具、控制台管理访问域名和云函数访问路径。 ## 创建 您可以使用下面的命令,通过 CLI 命令行交互的方式创建 HTTP 访问服务地址 ```sh tcb service create -e envId ``` 您也可以指定指定云函数名称 `functionName` 和触发路径 `servicePath` 创建 HTTP 访问服务地址 ``` tcb service create -p servicePath -f functionName ``` ## 删除 HTTP 访问服务链接 您可以使用下面的命令,通过 CLI 命令行交互的方式删除云函数 HTTP 访问服务链接 ```sh tcb service delete -e envId ``` 您也可以通过参数指定需要删除的 HTTP 访问服务信息,如 HTTP 访问服务地址的路径,或者 HTTP 访问服务 Id ```sh # 指定 HTTP 访问服务绑定的路径 tcb service delete -p servicePath # 指定 HTTP 访问服务 Id tcb service delete -i serviceId ``` ## 查询 HTTP 访问服务信息 您可以通过下面的命令列出所有的 HTTP 访问服务链接,查看它们的基本信息: ```sh tcb service list ``` 您会得到类似下面的输出: ![](https://main.qcloudimg.com/raw/efb14cddfa4942a1dce615c48547ab6f.png) ### 设置更多的查询约束条件 ```sh -d domain 指定域名 -p servicePath 指定 HTTP 访问服务路径 -i serviceId 指定 HTTP 访问服务 Id ``` ## 绑定 HTTP 访问服务自定义域名 :::caution 注意事项 **绑定自定义域名之前,请先设置您的域名的 CNAME 记录值为[默认域名](https://tcb.cloud.tencent.com/dev#/env/http-access),CNAME 记录不存在时会导致域名绑定失败!** ::: 您可以通过下面的命令绑定 HTTP 访问服务域名: ```sh tcb service domain bind domain ``` ## 解绑 HTTP 访问服务自定义域名 您可以通过下面的命令解绑 HTTP 访问服务域名: ```sh tcb service domain unbind domain ``` ## 查询 HTTP 访问服务自定义域名 您可以通过下面的命令列出所有的 HTTP 访问服务域名,查看它们的基本信息: ```sh tcb service domain list ``` 您会得到类似下面的输出: ![](https://main.qcloudimg.com/raw/32b243c13c3f5d6083e7ae502996c83b.png) ### 设置更多的查询约束条件 ```sh -d domain 指定域名 ``` --- ## 云存储 # 云存储 云存储是云开发为用户提供的文件存储能力,用户可以通过云开发提供的 CLI 工具、SDK 对存储进行操作,如上传、下载文件。存储在云存储中的文件默认提供 CDN 加速访问,用户可以快速访问云存储中的文件。 ## 路径说明 - `localPath` 为本地文件或文件夹的路径,为 `目录/文件名` 的形式,如 `./index.js`、`static/css/index.css` 等。 - `cloudPath` 为云存储文件或文件夹的相对根目录的路径,为 `目录/文件名` 的形式,如 `index.js`、`static/css/index.js` 等。 :::caution ⚠️ 注意事项 Windows 系统中 localPath 为本地路径形式,是系统可以识别的路径,通常使用 `\` 分隔符。`cloudPath` 是云端文件路径,均需要使用 `/` 分隔符。 ::: ## 上传文件 您可以使用下面的命令上传文件/文件夹,当 CLI 检测到 localPath 为文件夹时,会自动上传文件内的所有文件。 ```sh tcb storage upload localPath cloudPath ``` ## 下载文件 您可以使用下面的命令下载文件/文件夹,需要下载文件夹时,需要指定 `--dir` 参数。 ```sh # 下载文件 tcb storage download cloudPath localPath # 下载文件夹 tcb storage download cloudPath localPath --dir ``` ### 下载全部文件 当指定 cloudPath 为 `/` 时,即代表下载云存储中的全部文件 ```sh # 下载文件夹 tcb storage download / localPath --dir ``` ## 删除文件 您可以使用下面的命令删除云端文件/文件夹,需要删除文件夹时,需要指定 `--dir` 参数。 ```sh # 删除文件 tcb storage delete cloudPath # 删除文件夹 tcb storage delete cloudPath --dir ``` ### 删除全部文件 云端路径为空时,即代表删除云存储中的全部文件 ```sh tcb storage delete ``` ## 列出文件列表 您可以使用下面的命令列出文件夹下的文件 ```sh tcb storage list cloudPath ``` ## 获取文件访问链接 您可以使用下面的命令获取文件的临时访问链接 ```sh tcb storage url cloudPath ``` ## 获取文件简单信息 您可以使用下面的命令获取文件的简单信息 ```sh tcb storage detail cloudPath ``` ## 获取文件访问权限 您可以使用下面的命令获取文件的访问权限设置信息 ```sh tcb storage get-acl ``` ## 设置文件访问权限 您可以使用下面的命令设置文件的访问权限 ```sh tcb storage set-acl ``` --- ## 多语言支持 # 多语言支持 CloudBase 云函数目前支持多种语言: - Node.js - PHP - Python - Golang - Java ## 跨语言调用 您可以在任何 SDK 中调用某个云函数,并且无需了解这个云函数是由什么语言编写的。 例如,您可以在 Web 端内使用 Web SDK 调用 Python 编写的云函数;也可以在 Flutter 中调用 Golang 编写的云函数。 ## Python 云函数 请参考 [腾讯云 SCF 文档 - Python](https://cloud.tencent.com/document/product/583/11061)。 ## Golang 云函数 请参考 [腾讯云 SCF 文档 - Golang](https://cloud.tencent.com/document/product/583/18032)。 ## PHP 云函数 请参考 [腾讯云 SCF 文档 - PHP](https://cloud.tencent.com/document/product/583/17531)。 --- ## 深入理解云函数 # 深入理解云函数 云函数中,Node.js 的运行机制和本地 Node.js 运行的行为有些差异。 ## 启动时间 云函数存在两种启动: - **冷启动**:需要平台分配计算资源、加载代码、启动 Node.js 进程,**耗时较长**; - **热启动**:函数实例、执行进程都被复用(即下文提到的「实例复用」),**耗时很短**。 云函数如果在**一定时间内(几十分钟)没有被调用**,那么平台会收回分配的计算资源,直到函数被调用前,再分配计算资源,这种情况下,会发生冷启动。 如果对云函数发起连续的请求,已经冷启动完毕的实例会得到复用,可以在很短时间投入计算,此时即热启动。 :::tip 提示 CloudBase 会根据您云函数长期的访问情况,自动调度、调配实例的数量,保证足够好的性能的同时,节省您的资源。 ::: ## 实例复用 考虑下面这个云函数: ```js let i = 0; exports.main = async (event = {}) => { i++; console.log(i); return i; }; ``` 在第一次调用该云函数的时候函数返回值为 1,这是符合预期的。 但如果连续调用这个云函数,**其返回值有可能是从 2 递增,也有可能变成 1**,这便是实例复用的结果: - 当**热启动**时,执行函数的 Node.js 进程被复用,进程的上下文也得到了保留,所以**变量 `i` 自增**。 - 当**冷启动**时,Node.js 进程是全新的, 代码会从头完整的执行一遍,**此时返回 1**。 所以,**开发者在编写云函数时,应注意保证云函数是无状态的、幂等的**,即当次云函数的执行不依赖上一次云函数执行过程中在运行环境中残留的信息。 ## 时区 **云函数中的时区默认是 UTC+0**,在函数中获取本地时间会和北京时间有 8 个小时的差异。 定义环境变量 `TZ` 可以改变函数运行时的时区,例如设置 `TZ` 为 `Asia/Shanghai` 可以指定函数的时区为北京时间。 更多关于时区的信息,可以参考:[Time Zone Database](https://www.iana.org/time-zones)。 :::tip 提示 在服务端处理时间(包括数据库和云函数)应尽量**避免使用受到时区影响的本地时间**,而是**使用 Unix 时间戳这样的绝对值**,这样可以避免服务端和客户端时区差异带来的众多问题。 ::: ## Node.js 8 的异步行为 考虑下面这段代码: ```js exports.main = async (event = {}, context) => { setTimeout(() => { console.log("rid: ", context.request_id); }, 0); return "ok"; }; ``` 在本地调用时,函数返回 “ok”,并且随后可以看到 requestId 的打印。 但如果在 Node.js 8 的云函数中运行此代码,函数依然返回 “ok”,**但是 `setTimeout` 中异步函数打印的内容却不会在这次调用日志里看到**,例如: ![screenshot0](https://main.qcloudimg.com/raw/881830f2f95f040c6bdca7eb002e90d5.png) **如果继续调用第二次,您可能会在调用日志里看到上次 `setTimeout` 中打印**: ![screenshot1](https://main.qcloudimg.com/raw/a27bc68df8caf5b753fc40ccc36c7f91.png) 这一点是很多开发者感到困惑的地方。 对于异步函数,主流程(例如示例中的 `await main(event, context)`)执行完成后,函数实例进程会**被冻结**,进程中的所有异步任务会暂停执行,直到这个进程被再次唤起。 另一方面,如果函数实例进程由于某些原因**没被复用**(例如更新了函数代码),这个异步流程中的代码就**永远不会被执行**。 :::tip 提示 开发者**不应将关键代码放入 Node.js 8 云函数的异步流程中**。 如果想让关键代码稳定运行,请将其**放到函数主流程中**,或者**使用 Node.js 10 及以上版本的云函数**: ::: ### 示例 Node.js 8 云函数的异步特性可能会带来某些预期之外的行为,例如: 小程序 `wx-server-sdk` 提供了 `getWXContext` 方法来获取函数的一些上下文信息(appId,openId,unionId)来方便开发者,该方法本质是从环境变量中读取若干参数。 如果在异步流程中使用该方法获取 `openId` 或 `unionId`,可能会产生**身份漂移**的异常情况。 考虑这样的一段代码: ```js const cloud = require("wx-server-sdk"); exports.main = async (event) => { console.log("openid a: ", cloud.getWXContext().OPENID); setTimeout(() => { const { OPENID } = cloud.getWXContext(); console.log("openid b: ", OPENID); }, 0); }; ``` 假如两个不同的用户通过小程序访问该函数,用户 A 的 openid 为 1111,用户 B 的 openid 为 2222。 他们两次调用的日志将分别为: ![screenshot2](https://main.qcloudimg.com/raw/854ea3e9fed03f48c926c140e8cb6f59.png) ![screenshot3](https://main.qcloudimg.com/raw/24a0d7a8702cc313984fe6526a9ab326.png) 可以看到,第一次调用打印出了用户 A 的 openid,这是符合预期的,但**异步流程的逻辑当次调用并没有执行**。 第二次调用时,函数实例进程得到复用,**第一次调用产生的异步逻辑继续运行**,打印出了用户 B 的 openid,而这次调用其实是**属于用户 A 调用函数的异步流程**。 --- ## 灰度发布 import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # 灰度发布 CloudBase 云函数支持多版本管理功能,通过灰度发布能力可以**调整不同版本间的请求流量比例**,实现线上业务的平滑过渡、灰度验证和快速回滚,确保业务发布的稳定性和安全性。 ## 核心概念 ### 版本管理 每个云函数可以发布多个**版本**,版本是函数在特定时刻的完整快照,包含: - 函数代码 - 配置信息(超时时间、环境变量、内存规格等) - 运行时环境 ### LATEST 版本 云函数始终存在一个 `LATEST` 版本,代表最新版本。当您上传、更新或部署云函数代码时,都是在修改 `LATEST` 版本。 ### 流量分配 您可以精确控制不同版本云函数的流量比例,CloudBase 会根据设定的比例自动分发请求流量到对应版本。 ### 一致性保证 CloudBase 使用用户的全局唯一标识来保证请求的一致性: - **有用户信息的请求**:同一用户的所有请求会始终路由到同一个版本,确保用户体验的一致性 - **无用户信息的请求**:采用随机调度策略进行流量分配 :::tip 示例说明 假设云函数的 `LATEST` 版本流量占比 10%,版本 1 占比 90%。如果某个用户被分配到版本 1,则该用户对此云函数的所有后续请求都会路由到版本 1,而不是按概率随机分配。 ::: ## 灰度发布流程 ### 推荐流程 1. **创建稳定版本**:从当前 `LATEST` 版本发布一个新版本(如版本 1) 2. **切换流量**:将 `LATEST` 版本流量设置为 0%,新版本流量设置为 100% 3. **更新代码**:在 `LATEST` 版本中部署新功能代码 4. **灰度验证**:逐步调整 `LATEST` 版本的流量比例进行灰度验证 1. 发布版本 1(保存当前稳定代码) 2. 设置版本 1 流量为 100%,`LATEST` 流量为 0% 3. 在 `LATEST` 版本中部署新功能代码 4. 设置 `LATEST` 流量为 10%,版本 1 流量为 90%,开始灰度验证 5. 根据验证结果调整流量比例或进行回滚 ## 操作指南 ### 创建版本 1. 进入 [云函数管理页面](https://tcb.cloud.tencent.com/dev#/scf?tab=function) 2. 选择需要进行灰度发布的函数 3. 在「灰度配置」模块中,点击「发布新版本」 ![](https://qcloudimg.tencent-cloud.cn/raw/89bb6a84fc0b45f774a66e168dd284b8.png) 4. 输入版本描述信息,确认发布 > ⚠️ 注意:版本发布后,该版本的代码和配置将被锁定,无法再次修改。 ### 配置流量比例 在灰度配置页面中,可以实时调整不同版本的流量分配比例: > ⚠️ 注意:流量比例调整后会立即生效,请谨慎操作并及时验证效果。 ## 最佳实践 ### 首次灰度发布 对于从未使用过灰度功能的云函数,推荐按以下步骤操作: 1. **发布基准版本** ``` 当前状态:只有 LATEST 版本(100% 流量) 操作:发布版本 1,设置版本 1 流量为 100% ``` 2. **部署新功能** ``` 当前状态:版本 1(100% 流量),LATEST(0% 流量) 操作:在 LATEST 版本中部署新功能代码 ``` 3. **开始灰度** ``` 设置流量分配:LATEST(10%),版本 1(90%) 结果:10% 用户体验新功能,90% 用户使用稳定版本 ``` ### 版本回滚与全量发布 #### 快速回滚 当发现新版本存在问题时,可以快速将流量切回稳定版本: ``` 紧急回滚:将稳定版本流量设置为 100%,问题版本流量设置为 0% ``` #### 全量发布 当新版本验证通过后,可以进行全量发布: ``` 全量发布:将新版本流量设置为 100%,旧版本流量设置为 0% ``` ### 灰度策略建议 | 阶段 | LATEST 流量 | 稳定版本流量 | 说明 | | -------- | ----------- | ------------ | ------------------ | | 初始验证 | 5% | 95% | 小范围验证基本功能 | | 扩大验证 | 20% | 80% | 验证性能和稳定性 | | 准备全量 | 50% | 50% | 大规模验证 | | 全量发布 | 100% | 0% | 完成发布 | :::tip 建议 - 建议在业务低峰期进行灰度发布操作 - 密切监控新版本的错误率、响应时间等关键指标 - 准备好快速回滚方案,确保业务稳定性 ::: --- ## 如何编写云函数 # 如何编写云函数 ## 函数入参详解 每个云函数调用都会收到两个重要对象:`event` 和 `context`。 ### event 对象 `event` 对象包含**触发云函数的事件数据**,其内容根据触发方式不同而变化: - **小程序调用**:包含小程序端传入的参数 - **HTTP 请求调用**:包含 [HTTP 请求信息](/service/access-cloud-function)(如请求头、请求体等) - **定时触发**:包含定时触发的相关信息 ### context 对象 `context` 对象提供**调用上下文信息**,帮助您了解函数的运行环境和调用方式: - **请求 ID**:当前调用的唯一标识符 - **调用来源**:触发函数的服务或客户端信息 - **执行环境**:函数的运行时信息 - **用户身份**:调用方的身份信息(如有) ### 基础代码示例 以下是一个简单的 Node.js 云函数示例,展示如何处理入参并返回结果: ```js // index.js - 云函数入口文件 exports.main = async (event, context) => { // 1. 解析云函数入参 const { a, b } = event; // 2. 执行业务逻辑 const sum = a + b; // 3. 返回结果 return { sum, timestamp: Date.now(), requestId: context.requestId }; }; ``` ### 异步处理最佳实践 由于实例的管理由平台自动处理,推荐云函数采用 async/await 模式,避免使用 Promise 链式调用: ```js exports.main = async (event, context) => { // ❌ 不推荐:Promise 链式调用 getList().then((res) => { // do something... }); // ✅ 推荐:使用 async/await const res = await getList(); // do something... }; ``` ## 环境变量使用 云函数可以通过 `process.env` 获取环境变量,这是管理配置信息的最佳实践: ### 获取环境变量 ```js exports.main = async (event, context) => { // 获取环境变量 const dbUrl = process.env.DATABASE_URL; const apiKey = process.env.API_KEY; const nodeEnv = process.env.NODE_ENV || 'development'; // 使用环境变量进行配置 const config = { database: dbUrl, apiKey: apiKey, debug: nodeEnv === 'development' }; return { message: '环境变量获取成功', environment: nodeEnv }; }; ``` ### 环境变量最佳实践 ```js exports.main = async (event, context) => { // 检查必需的环境变量 const requiredEnvVars = ['DATABASE_URL', 'API_KEY']; const missingVars = requiredEnvVars.filter(varName => !process.env[varName]); if (missingVars.length > 0) { throw new Error(`缺少必需的环境变量: ${missingVars.join(', ')}`); } // 安全地使用环境变量 const config = { dbUrl: process.env.DATABASE_URL, apiKey: process.env.API_KEY, timeout: parseInt(process.env.TIMEOUT) || 5000 }; return { success: true, config }; }; ``` :::tip 注意 - 敏感信息(如 API 密钥、数据库连接字符串)应通过环境变量传递,不要硬编码在代码中 - 环境变量值始终是字符串类型,需要时请进行类型转换 - 建议为环境变量设置默认值,提高代码的健壮性 ::: ## 时区设置 云函数的运行环境内保持的是 UTC 时间,即 0 时区时间,和北京时间有 8 小时的时间差。 可以通过语言的时间处理相关库或代码包(如 moment-timezone),识别 UTC 时间并转换为+8 区北京时间。 :::tip 注意 当前云开发支持的函数版本为 Node 10,无法通过设置环境变量 TZ=Asia/Shanghai 指定时区(Node 15+版本支持)。 ::: ### 时区处理示例 ```javascript const moment = require("moment-timezone"); // 需在 package.json 中指定并安装依赖 exports.main = async (event, context) => { // javascript date console.log(new Date()); // 2021-03-16T08:04:07.441Z (UTC+0) console.log(moment().tz("Asia/Shanghai").format()); // 2021-03-16T16:04:07+08:00 (UTC+8) // 获取当前北京时间 const beijingTime = moment().tz("Asia/Shanghai"); return { utcTime: new Date().toISOString(), beijingTime: beijingTime.format(), timestamp: beijingTime.valueOf() }; }; ``` ### 时区处理最佳实践 ```javascript exports.main = async (event, context) => { const moment = require("moment-timezone"); // 统一时区处理函数 const getBeijingTime = (date = new Date()) => { return moment(date).tz("Asia/Shanghai"); }; // 格式化时间输出 const formatTime = (date, format = 'YYYY-MM-DD HH:mm:ss') => { return getBeijingTime(date).format(format); }; // 业务逻辑中使用 const currentTime = getBeijingTime(); const formattedTime = formatTime(); console.log('当前北京时间:', formattedTime); return { success: true, currentTime: formattedTime, timestamp: currentTime.valueOf() }; }; ``` ## 使用 ES Module 规范 在云函数 Node.js 环境中无法直接采用 ES Module 规范编写代码,主要原因在于,云函数默认支持的入口文件(`index.js`)必须遵循 CommonJS 规范,并且文件名必须为 **「index.js」**。然而,Node.js 对于符合 ES Module 规范的模块文件要求其扩展名为 `.mjs`。 ### 全新云函数中使用 ES Module #### 1. 创建 Nodejs v14+ 环境云函数 :::tip 提示 Nodejs 版本必须大于等于14才支持 ES Module。 ::: #### 2. 创建入口文件 entry.mjs 创建一个名为 `entry.mjs` 的文件,作为 ES Module 入口点: ```js // entry.mjs import { foo } from './util.js'; // 入口函数 export const entry = (event, context) => { return foo(event, context); }; ``` #### 3. 在 index.js 中引入入口文件 ```js // index.js exports.main = async (event, context) => { const { entry } = await import('./entry.mjs'); return entry(event, context); }; ``` #### 4. 创建业务模块 ```js // util.js export const foo = async (event, context) => { console.log('使用 ES Module 语法'); return { success: true, message: 'ES Module 调用成功', data: event }; }; ``` ### 改造现有云函数支持 ES Module 对于现有的云函数代码想要适配 ES Module 规范,本着对代码最小侵入性以及改造成本最低原则: #### 1. 创建入口文件 entry.mjs ```js // entry.mjs // 假设src文件夹是现有的业务代码 import { businessLogic } from './src/index.js'; // 入口函数 export const entry = (event, context) => { return businessLogic(event, context); }; ``` #### 2. 创建 package.json 文件 在业务代码目录下创建 `package.json` 文件: ```json { "type": "module" } ``` 这将告诉 Node.js 将此目录视为 ES Module,并允许使用 ESM 语法导入和导出模块。 #### 3. 修改现有业务代码 将现有的 CommonJS 语法改为 ES Module 语法: ```js // src/index.js - 改造前(CommonJS) const helper = require('./helper'); module.exports = { businessLogic: async (event, context) => { return helper.process(event); } }; // src/index.js - 改造后(ES Module) import { process } from './helper.js'; export const businessLogic = async (event, context) => { return process(event); }; ``` ### ES Module 最佳实践 ```js // entry.mjs import { createRequire } from 'module'; import { fileURLToPath } from 'url'; import { dirname } from 'path'; // 在 ES Module 中使用 require(如果需要) const require = createRequire(import.meta.url); // 获取当前文件路径(ES Module 中的 __dirname 替代) const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); // 动态导入 const loadModule = async (moduleName) => { try { const module = await import(moduleName); return module; } catch (error) { console.error(`模块加载失败: ${moduleName}`, error); throw error; } }; export const entry = async (event, context) => { // 条件导入 const moduleName = event.moduleType || 'default'; const handler = await loadModule(`./handlers/${moduleName}.js`); return handler.default(event, context); }; ``` ## 错误处理与日志记录 ### 错误处理最佳实践 ```js exports.main = async (event, context) => { try { // 参数验证 if (!event.userId) { throw new Error('缺少必需参数: userId'); } // 业务逻辑处理 const result = await processUserData(event.userId); return { success: true, data: result }; } catch (error) { // 记录错误日志 console.error('函数执行失败:', { error: error.message, stack: error.stack, event, requestId: context.requestId }); // 返回友好的错误信息 return { success: false, error: error.message, requestId: context.requestId }; } }; ``` ### 日志记录规范 ```js exports.main = async (event, context) => { // 记录函数开始执行 console.log('函数开始执行:', { requestId: context.requestId, event: event }); const startTime = Date.now(); try { const result = await businessLogic(event); // 记录成功日志 console.log('函数执行成功:', { requestId: context.requestId, duration: Date.now() - startTime, resultSize: JSON.stringify(result).length }); return result; } catch (error) { // 记录错误日志 console.error('函数执行失败:', { requestId: context.requestId, duration: Date.now() - startTime, error: error.message }); throw error; } }; ``` ## 性能优化建议 ### 执行时间优化 ```js exports.main = async (event, context) => { const startTime = Date.now(); try { // 使用并行处理提升性能 const promises = event.items.map(item => processItem(item)); const results = await Promise.all(promises); const duration = Date.now() - startTime; console.log(`函数执行耗时: ${duration}ms`); return { success: true, data: results, duration }; } catch (error) { console.error('执行错误:', error); throw error; } }; ``` ### 内存使用优化 ```js exports.main = async (event, context) => { // 分批处理大数据,避免内存溢出 const batchSize = parseInt(process.env.BATCH_SIZE) || 100; const results = []; for (let i = 0; i { let connection; try { // 从连接池获取连接 connection = await pool.getConnection(); const [rows] = await connection.execute( 'SELECT * FROM users WHERE id = ?', [event.userId] ); return { success: true, data: rows }; } catch (error) { console.error('数据库操作失败:', error); throw error; } finally { // 释放连接回连接池 if (connection) { connection.release(); } } }; ``` ## 常见问题排查 ### 函数超时问题 **问题现象**:函数执行时间超过配置的超时时间 **排查步骤**: 1. 查看监控数据中的执行时间分布 2. 检查日志中的具体执行步骤耗时 3. 分析代码中的耗时操作 **解决方案**: ```js exports.main = async (event, context) => { // 设置超时处理 const timeout = parseInt(process.env.FUNCTION_TIMEOUT) || 30000; const timeoutPromise = new Promise((_, reject) => { setTimeout(() => reject(new Error('函数执行超时')), timeout - 1000); }); try { // 使用 Promise.race 实现超时控制 const result = await Promise.race([ businessLogic(event), timeoutPromise ]); return result; } catch (error) { if (error.message === '函数执行超时') { console.error('函数执行超时,请优化代码逻辑'); } throw error; } }; ``` ### 内存不足问题 **问题现象**:函数运行时内存使用超过配置限制 **排查步骤**: 1. 查看监控数据中的内存使用情况 2. 检查代码中的大对象创建和使用 3. 分析是否存在内存泄漏 **解决方案**: ```js exports.main = async (event, context) => { // 监控内存使用 const memoryUsage = process.memoryUsage(); console.log('初始内存使用:', memoryUsage); try { // 分批处理大数据 const results = []; const batchSize = 50; // 根据内存限制调整批次大小 for (let i = 0; i setTimeout(resolve, delay * Math.pow(2, i))); } } } exports.main = async (event, context) => { try { // 参数校验 if (!event || typeof event !== 'object') { throw new Error('无效的事件参数'); } // 使用重试机制调用外部服务 const result = await retryOperation(async () => { return await callExternalAPI(event.data); }); return { success: true, data: result }; } catch (error) { // 详细的错误日志 console.error('函数执行失败:', { error: error.message, stack: error.stack, event, requestId: context.requestId, timestamp: new Date().toISOString() }); return { success: false, error: error.message, requestId: context.requestId }; } }; ``` ## 开发调试技巧 ### 本地调试 ```js // 本地调试时的环境检测 const isLocal = process.env.NODE_ENV === 'development' || !process.env.TENCENTCLOUD_RUNENV; exports.main = async (event, context) => { // 本地调试时提供模拟数据 if (isLocal) { console.log('本地调试模式'); event = event || { userId: 'test-user-123' }; context = context || { requestId: 'local-request-id' }; } // 调试信息输出 if (process.env.DEBUG === 'true') { console.log('调试信息:', { event, context, env: process.env.NODE_ENV }); } return await businessLogic(event, context); }; ``` ### 性能监控 ```js exports.main = async (event, context) => { const startTime = process.hrtime.bigint(); const startMemory = process.memoryUsage(); try { const result = await businessLogic(event); // 性能统计 const endTime = process.hrtime.bigint(); const endMemory = process.memoryUsage(); const duration = Number(endTime - startTime) / 1000000; // 转换为毫秒 console.log('性能统计:', { duration: `${duration.toFixed(2)}ms`, memoryDelta: { rss: endMemory.rss - startMemory.rss, heapUsed: endMemory.heapUsed - startMemory.heapUsed } }); return result; } catch (error) { console.error('执行异常:', error); throw error; } }; ``` 通过合理使用测试、日志和监控功能,可以有效提升云函数的开发效率和运行稳定性。建议开发者在函数开发过程中充分利用这些工具,及时发现和解决问题。 --- ## 如何使用ES Module # 如何使用ES Module ## 前言 在云函数 ``Node.js`` 环境中无法直接采用 `ES Module` 规范编写代码,主要原因在于,云函数默认支持的入口文件(`index.js`)必须遵循 `CommonJS` 规范,并且文件名必须为 **「index.js」**。然而,`Node.js` 对于符合 `ES Module` 规范的模块文件要求其扩展名为 `.mjs`。因此,在云函数的入口文件中,我们无法直接使用 `ES Module` 规范进行编码。此外,`Node.js` 默认支持 `CommonJS` 模块,即通过 `require` 加载和 `module.exports` 输出。而对于采用 `import` 和 `export` 的 `ES Module` 模块,`Node.js` 无法直接识别。若要让 `Node.js` 正确识别这些模块,则必须将这些模块的后缀名改为 `.mjs` 这样 `Node.js` 即可识别它是 `ES Module` 模块。如果不希望将后缀名改成 `.mjs`,可以在项目的 `package.json` 文件中,指定 `type` 字段为 `module`。一旦设置了以后,该目录里面的 `JS` 脚本,就被解释用 `ES Module` 模块。 本篇文档介绍如何在云函数 `Node.js` 环境中编写符合 `ES Module` 规范的代码的方法,以及如何对现有云函数代码进行改造以适配 `ES Module` 规范。本文将从以下两个使用场景出发: - 场景一:如何在全新的云函数中编写符合 `ES Module` 规范的代码。 - 场景二:改造现有的云函数代码使其支持 `ES Module` 规范。 通过以上两个场景的详细解析,您将能够全面掌握在云函数 `Node.js` 环境中运用 `ES Module` 规范的方法与技巧。 ## 如何在全新的云函数中编写符合 ES Module 规范的代码 ### 创建 Nodejs v14环境云函数 ![](https://qcloudimg.tencent-cloud.cn/raw/a6ada639c32a22ca573948bf77a9ae43.png) :::tip 提示 Nodejs 版本必须大于等于14。 ::: ### 创建入口文件 entry.mjs 创建一个名为 `entry.mjs` 的文件,作为 `ES Module` 入口点。此文件将使用 `ES Module` 语法导入其他模块并导出一个函数。 ```js // entry.mjs import { foo } from './util.js'; // 入口函数 export const entry = (event, context) => { foo(event, context); }; ``` 在上述代码中,假设 `util.js` 模块中的 `foo` 函数是我们的业务代码,并且在 `entry.mjs` 中使用 `ES Module` 语法导入 `foo` 函数,并在入口函数 `entry` 中调用。 ### 引入入口文件 接下来,在 `index.js` 中,需要动态地引入 `entry.mjs` 模块,并调用其导出的 `entry` 函数。 ```js // index.js exports.main = async (event, context) => { const { entry } = await import('./entry.mjs'); return entry(event, context); }; ``` 完整代码目录结构如下: ![](https://qcloudimg.tencent-cloud.cn/raw/e9830e669d868cf2df89c6fde08db166.png) ## 改造现有的云函数代码使其支持 ES Module 规范 对于现有的云函数代码想要适配 `ES Module` 规范,本着对代码最小侵入性以及改造成本最低原则,我们可以这样做: ### 创建入口文件 entry.mjs 创建一个名为 `entry.mjs` 的文件,作为 `ES Module` 入口点。此文件将使用 `ES Module` 语法导入现有的业务代码。 ```js // entry.mjs // 假设src文件夹是现有的业务代码 import { foo } from './src'; // 入口函数 export const entry = (event, context) => { foo(event, context); }; ``` 在上述代码中,假设 `src` 文件夹里存放的是业务代码,我们在 `entry.mjs` 中使用 `ES Module` 语法导入业务代码,并在入口函数 `entry` 中调用。 ### 创建 package.json 文件 由于 `Node.js` 要求 `ES6` 模块必须采用 `.mjs` 作为文件后缀名,如果把现有的所有代码文件后缀名都手动一个个改成 `.mjs` 就太麻烦了,我们可以在业务代码目录下,创建一个名为 `package.json` 的文件,并写入以下内容: ```json { "type": "module" } ``` 这将告诉 `Node.js` 将此目录视为 `ES Module`,并允许你使用 `ESM` 语法导入和导出模块。 完整代码目录结构如下: ![](https://qcloudimg.tencent-cloud.cn/raw/473016c9045475bf15e2a79efa603e64.png) ## 总结 本文档详细介绍了如何在云函数的 `Node.js` 环境中编写和改造代码以适配 `ES Module` 规范。主要涉及两个场景: - 全新云函数的编写: - 创建 `entry.mjs` 作为 `ES Module` 入口。 - 在 `index.js` 中动态引入并调用 `entry.mjs`。 - 现有云函数的改造: - 同样创建 `entry.mjs` 作为入口。 - 添加 `package.json` 指定 `"type": "module"`,避免更改所有文件后缀。 --- ## 运行机制 # 运行机制 云函数(Cloud Functions)是一种无服务器计算服务,让您无需管理服务器即可运行代码。CloudBase 云函数为您提供了一个简单、可靠且高效的代码运行环境,自动处理所有底层基础设施,让您专注于业务逻辑的开发。 ## 核心特性 ### 无状态计算 CloudBase 根据实时负载情况,动态控制云函数实例数量并均衡分发请求。**连续的多次请求可能由不同的实例处理**,因此: * **云函数必须设计为无状态的**:每次执行应独立于之前的执行 * **函数应具有幂等性**:多次调用产生的副作用应与单次调用相同 * **不应依赖实例间的共享状态**:每个函数实例都是隔离的执行环境 > **最佳实践**:如需保存状态,请使用外部存储服务(如数据库或云存储),而非依赖函数实例的内存或本地存储。 ### 事件驱动模型 云函数采用事件驱动架构,每次调用本质上是触发了一个云函数执行事件。 #### 支持的触发器类型 | 触发器类型 | 描述 | 文档链接 | |---------|------|---------| | SDK/API 调用 | 通过各语言 SDK 或 REST API 直接调用 | [web端调用](/api-reference/webv3/functions) [node服务端调用](/api-reference/server/node-sdk/functions) | | HTTP 触发 | 通过 HTTP 请求调用,可用于构建 API | [使用 HTTP 访问云函数](/service/access-cloud-function) | | 定时触发 | 按预设的时间规则自动触发执行 | [定时触发器](/cloud-function/timer-trigger.md) | ### 自动弹性伸缩 CloudBase 平台自动处理云函数的扩缩容,您无需关心基础设施管理: * **按需扩容**:流量增加时自动创建更多实例 * **自动缩容**:流量减少时释放多余实例 * **零实例冷启动**:无流量时不占用资源,有请求时自动启动 ## 运行环境详情 ### 容器化执行环境 * 云函数在**隔离的容器化 Unix 环境**中运行 * 每个函数实例拥有独立的执行环境,相互之间完全隔离 * 实例的创建、管理和销毁由平台全自动处理 ### 临时存储 * 每个函数实例提供 **512MB 的 /tmp 临时存储空间** * 适用于单次执行过程中的临时文件读写 * 函数执行完毕后临时存储可能被清空 :::tip 重要提示 * 当前运行环境基于 CentOS 7.2,但**不应依赖特定操作系统或版本**,因为运行环境可能随时更新 * 临时存储在函数执行结束后不保证持久化,**需要持久存储请使用[云存储](/storage/introduce)** ::: ### 支持的运行时 CloudBase 云函数支持多种编程语言运行时: | 语言 | 支持的版本 | |------|-----------| | Node.js | 12.16、 10.15、 8.9 | | PHP | 7.2 | | Python | 3.6、 2.7 | | Golang | 1 | | Java | 8 | ## 资源限制与性能 ### 内存配置 * **默认内存**:256 MB * **可配置范围**:128 MB ~ 2048 MB * **建议**:根据函数复杂度和处理数据量选择合适的内存配置 > **性能提示**:增加内存配置通常也会提升 CPU 性能,对于计算密集型任务尤为重要。 ### 并发处理能力 云函数的并发数量指在任意时间点同时执行的函数实例数: * **最大并发实例数**:单个云函数默认为 1000 实例 * **并发限制行为**:超出限制的调用会被阻塞(不会执行) #### 并发计算公式 ``` 并发函数实例数 = 每秒请求量 × 函数执行时间(秒) ``` #### 实例计算 | 场景 | 计算过程 | 结果 | |------|---------|------| | 函数执行 0.2 秒,每秒 300 请求 | 300 × 0.2 | 60 个并发实例 | | 函数执行 0.2 秒,要达到最大并发 1000 | 1000 ÷ 0.2 | 需要 5000 QPS | ## 性能优化建议 为确保云函数高效运行,请考虑以下优化建议: 1. **减少冷启动影响** - 避免在全局范围内加载大型依赖 - 将初始化代码与处理逻辑分离 - 考虑使用 **预置并发** 2. **优化执行时间** - 使用异步并行处理独立任务 - 避免不必要的网络请求 - 优化数据库查询和文件操作 3. **合理使用内存** - 避免不必要的大对象创建 - 处理完大型数据后及时释放 - 为计算密集型任务分配足够内存 4. **处理错误和异常** - 实现完善的错误处理机制 - 记录关键操作的日志 - 设置合理的超时时间 通过理解云函数的运行机制并遵循最佳实践,您可以构建高效、可靠且可扩展的无服务器应用。 --- ## 安装 Node.js 依赖 import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # 安装 Node.js 依赖 云函数安装 Node.js 依赖有两种方式:**本地 npm 安装**和**在线依赖安装**。 ## 本地 npm 安装 使用 npm 安装第三方依赖,只能对每个云函数分别安装依赖。 进入函数代码根目录,如安装 request 库,终端执行 ```bash npm install request --save ``` 安装成功的依赖文件会作为该云函数代码的一部分,手动上传到云端使用。 ## 在线依赖安装 CloudBase 提供了云端安装依赖,免去了在终端手动安装依赖的工作。 进入云开发平台 [函数编辑页面](https://tcb.cloud.tencent.com/dev#/scf?tab=function),在线编辑或者上传 zip 代码包之后,点击「保存并安装依赖」。 ![](https://main.qcloudimg.com/raw/f51de788458b296091f3017ff999e6c3.png) 在配置文件 **cloudbaserc.json** 对应的云函数的配置项中添加 ```bash installDependency:true ``` 示例如下: ```json { "envId": "xxx", "functionRoot": "./functions", "functions": [ { "name": "app", "config": { // 超时时间 "timeout": 5, // 环境变量 "envVariables": { "key": "value" }, "runtime": "Nodejs10.15", "installDependency": true }, // 调用云函数时的输入参数 "params": {}, "handler": "index.main" } ] } ``` --- ## 概述 # 概述 **CloudBase 云函数**是云开发提供的无服务器计算服务,让您无需管理服务器即可运行后端代码。 ## 什么是云函数 云函数基于 **Serverless** 架构运行,您只需使用平台支持的语言编写代码,CloudBase 将完全管理底层计算资源,包括: * 🖥️ **服务器管理**:自动处理基础设施的管理和维护 * 🔄 **资源调度**:根据请求量自动分配和回收计算资源 * 📊 **监控运维**:提供完整的日志、监控和告警能力 如果您是首次使用云函数,建议先阅读 [快速开始](./quick-start) 文档,快速体验云函数的基本功能。 > 💡 **提示**:云开发还提供了 [函数型云托管](../cbrf/intro) 服务,具有更强的性能和更丰富的特性,您可以根据实际需求选择合适的服务。 ## 多语言支持 CloudBase 云函数支持多种主流编程语言,让您可以使用熟悉的语言进行开发: | 语言 | 版本支持 | 特点 | 文档链接 | |------|---------|------|----------| | **Node.js** | 12.x, 14.x, 16.x, 18.x | 生态丰富,适合快速开发 | [Node.js 文档](https://cloud.tencent.com/document/product/583/11060) | | **Python** | 3.6, 3.7, 3.9 | 数据处理能力强,AI/ML 友好 | [Python 文档](https://cloud.tencent.com/document/product/583/11061) | | **Java** | 8, 11 | 企业级应用,性能稳定 | [Java 文档](https://cloud.tencent.com/document/product/583/12214) | | **Golang** | 1.x | 高性能,并发处理优秀 | [Golang 文档](https://cloud.tencent.com/document/product/583/67384) | | **PHP** | 7.2, 8.0 | Web 开发友好 | [PHP 文档](https://cloud.tencent.com/document/product/583/17531) | ### 🔄 跨语言调用 云函数支持跨语言调用,您可以: * 在 **Web 端**使用 JavaScript SDK 调用 Python 编写的云函数 * 在 **小程序**中调用 Golang 编写的云函数 * 在 **Flutter 应用**中调用 Java 编写的云函数 **优势:** * 🎯 **语言无关**:调用方无需了解函数的实现语言 * 🔧 **统一接口**:所有语言的函数都使用相同的调用方式 * 🚀 **灵活选择**:可根据业务特点选择最适合的语言 ## 函数类型 CloudBase 云函数提供两种类型,满足不同场景需求: | 函数类型 | 事件函数 | Web 云函数 | |---------|---------|-----------| | **适用场景** | 数据处理、定时任务、API 接口 | Web 应用、SSE 实时通信、文件上传下载 | | **调用方式** | SDK 调用、HTTP 请求、定时器触发 | 直接处理 HTTP 请求 | | **框架支持** | 无特定框架要求 | 支持 Express.js、Koa.js 等 Web 框架 | | **特点** | 简单易用,专注业务逻辑处理 | 具备完整的 HTTP 服务能力 | ### 事件函数(Event Function) 适合处理事件驱动的业务逻辑,如数据处理、定时任务等场景。 **主要特点:** * 🎯 专注业务逻辑,无需关心 HTTP 协议细节 * 🔧 支持多种触发方式(SDK、HTTP、定时器) * 📝 简单的入参和返回值格式 ### Web 云函数(Web Function) 适合构建完整的 Web 应用和 API 服务。 **主要特点:** * 🌐 完整的 HTTP 请求/响应处理能力 * 🚀 支持主流 Web 框架(Express.js、Koa.js) * 📡 支持 SSE、WebSocket 等实时通信 **了解更多:** * [Web 云函数详细介绍](./web-func) * [云函数类型选型指南](https://cloud.tencent.com/document/product/583/73483) ## 核心优势 ### 🌐 多端访问 **全平台支持,随处可用** * **多 SDK 支持**:Web、小程序、Node.js 等 * **HTTP 接口**:支持任意客户端通过 HTTP 请求访问 * **无缝集成**:与 CloudBase 其他服务内部调用无需密钥认证 ### 🚀 零运维 **专注业务,无需关心基础设施** * **免服务器管理**:自动处理服务器配置、部署、监控 * **高可用保障**:内置负载均衡和故障转移机制 * **多运行时**:支持 Node.js、Python、Java、Go、PHP ### 📈 弹性伸缩 **按需扩容,成本优化** * **快速启动**:毫秒级冷启动,快速响应用户请求 * **自动扩缩容**:根据请求量自动调整实例数量,最大并发数达 1000 * **按量计费**:按实际调用次数和执行时间计费,空闲时零费用 ### 🔧 开发便捷 **工具完善,开发高效** * **CLI 工具**:使用 [CloudBase CLI](/cli-v1/intro) 快速部署和管理 * **可视化管理**:[云开发控制台](https://tcb.cloud.tencent.com/dev#/scf?tab=function) 提供完整的可视化操作界面 * **丰富资源**:提供多种示例代码和项目模板,快速上手 --- ## 层管理 import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # 层管理 云函数层(Layer)是一种代码共享机制,可以将依赖库、公共代码文件等资源独立管理,实现多个函数间的代码复用。 ## 什么是层 层是云函数的一个重要特性,允许您将依赖库、运行时环境、配置文件等打包成独立的层,供多个函数共享使用。使用层可以: - **减小部署包体积**:将依赖库从函数代码中分离,保持部署包轻量化 - **提高开发效率**:公共代码只需维护一份,多个函数可复用 - **支持在线编辑**:对于 Node.js、Python 和 PHP 函数,代码包保持在 10MB 以下时可在控制台在线编辑 ## 工作原理 ### 层的创建与版本管理 - 每个层都有独立的版本管理,创建层时会生成对应的版本号 - 层的内容以压缩包形式存储,支持版本迭代和回滚 - 层可以设置兼容的运行环境,确保与函数运行时匹配 ### 层的绑定机制 - 函数与层按照具体版本进行绑定,确保运行环境的稳定性 - 单个函数最多支持绑定 5 个层 - 绑定时可以指定层的加载顺序 ### 运行时加载流程 当绑定了层的函数被触发时,系统会按以下流程加载: 1. **函数代码加载**:函数代码解压至 `/var/user/` 目录 2. **层内容加载**:所有绑定的层按顺序解压至 `/opt` 目录 3. **文件访问规则**: - 层根目录的文件:通过 `/opt/文件名` 访问 - 层子目录的文件:通过 `/opt/目录名/文件名` 访问 ### 多层加载顺序 当函数绑定多个层时: - 按绑定时设置的序号从小到大依次加载 - 后加载的层会覆盖先加载层中的同名文件 - 所有层在函数实例启动前完成加载,函数初始化时即可使用 ## 使用场景与最佳实践 ### 适用场景 - **依赖库管理**:将第三方库、SDK 等依赖统一管理 - **公共代码复用**:多个函数共享的工具类、配置文件 - **静态资源存储**:模型文件、配置文件等不常变更的资源 ### 最佳实践 ```bash # 1. 创建依赖目录 mkdir python-layer cd python-layer # 2. 安装依赖到指定目录 pip install requests -t python/ # 3. 打包成 zip 文件 zip -r python-layer.zip python/ ``` 在函数中使用: ```python import requests # 直接导入层中的依赖 def main_handler(event, context): response = requests.get('https://api.example.com') return response.json() ``` ```bash # 1. 创建依赖目录 mkdir nodejs-layer cd nodejs-layer # 2. 初始化并安装依赖 npm init -y npm install axios lodash # 3. 打包 node_modules zip -r nodejs-layer.zip node_modules/ ``` 在函数中使用: ```javascript const axios = require('axios'); // 直接引用层中的依赖 const _ = require('lodash'); exports.main_handler = async (event, context) => { const response = await axios.get('https://api.example.com'); return _.pick(response.data, ['id', 'name']); }; ``` ### 层结构建议 ``` layer.zip ├── python/ # Python 依赖目录 │ ├── requests/ │ └── urllib3/ ├── lib/ # 共享库目录 │ └── utils.py └── config/ # 配置文件目录 └── settings.json ``` ## 注意事项 :::tip 重要提醒 - 层中的文件会解压到 `/opt` 目录,函数执行期间可直接访问 - 多个层绑定时按序号顺序合并,同名文件会被序号较大的层覆盖 - 层的总大小限制为 50MB,建议合理规划层的内容 - 层版本一旦创建不可修改,需要更新时请创建新版本 ::: ## 操作指南 ### 创建层 1. **进入层管理页面** 进入 [云开发控制台/层管理](https://tcb.cloud.tencent.com/dev#/scf?tab=layer) 2. **配置层信息** 点击「新建」,填写以下信息: | 配置项 | 说明 | | -------- | ---------------------------------- | | 层名称 | 自定义层名称,建议使用有意义的命名 | | 描述 | 层的用途和内容描述,便于团队协作 | | 层代码 | 上传 zip 压缩包,最大支持 500MB | | 运行环境 | 选择兼容的运行时环境,最多 8 个 | 3. **上传层代码** 点击「上传」按钮,选择准备好的 zip 压缩包,确认后点击「确定」完成创建。 ### 绑定层到函数 1. **选择目标函数** 在云函数列表中选择需要绑定层的函数,进入函数详情页。 2. **进入层管理** 切换到「层管理」标签页,点击「绑定」按钮。 ![](https://qcloudimg.tencent-cloud.cn/raw/6f45b146c4856debe7a28ffb6b9e678a.png) 3. **选择层版本** 在弹出窗口中选择要绑定的层名称和版本: ![](https://main.qcloudimg.com/raw/4220214d87b10e17baf67bde8c0033df.jpg) - 可以同时绑定多个层(最多 5 个) - 可以调整层的加载顺序 - 建议选择稳定的层版本 4. **确认绑定** 确认配置无误后,点击「确定」完成绑定。 ### 管理层版本 - **查看版本历史**:在层详情页可查看所有历史版本 - **创建新版本**:修改层内容时创建新版本,保持向后兼容 - **删除版本**:删除不再使用的版本,释放存储空间 ## 常见问题 ### 层无法正常加载 **可能原因**: - 层的运行环境与函数不匹配 - 层文件结构不正确 - 层大小超过限制 **解决方案**: - 检查层的兼容运行环境设置 - 确认层文件按正确目录结构打包 - 优化层内容,控制在 500MB 以内 ### 依赖库导入失败 **可能原因**: - Python 依赖未安装到正确目录 - Node.js 模块路径不正确 **解决方案**: - Python:使用 `pip install -t python/` 安装到 python 目录 - Node.js:确保 node_modules 在层的根目录 ### 多层文件冲突 **可能原因**: - 不同层包含同名文件 - 层加载顺序不当 **解决方案**: - 合理规划层的内容分工 - 调整层的绑定顺序 - 使用不同目录避免文件名冲突 --- ## 控制台管理云函数 # 控制台管理云函数 云函数是云开发平台的核心功能之一,有效管理云函数可以提高应用的性能、可靠性和安全性。本文档将指导您如何通过控制台管理云函数的生命周期。 ## 管理方式 您可以通过以下两种方式管理云函数: * **控制台管理**:使用云开发平台 [云函数管理页面](https://tcb.cloud.tencent.com/dev#/scf?tab=function) 进行可视化操作 * **命令行管理**:使用 [CloudBase CLI 工具](/cli-v1/functions/deploy) 进行命令行操作 本文档主要介绍控制台管理方式,CLI 管理请参考 [CLI 管理云函数](/cli-v1/functions/deploy)。 ## 创建云函数 ### 通过控制台创建 1. 登录云开发平台,进入 [云函数管理页面](https://tcb.cloud.tencent.com/dev#/scf?tab=function) 2. 点击「新建云函数」按钮 3. 填写函数名称、运行环境、函数描述等信息 4. 选择函数模板或从头开始编写代码 5. 点击「确定」完成创建 ![创建云函数界面](https://qcloudimg.tencent-cloud.cn/raw/67065e1719f97ad6cd8ae529aff90e3e.png) ## 开发与部署 ### 在线编辑与部署 您可以直接在云开发控制台编辑云函数代码: 1. 在 [云函数管理页面](https://tcb.cloud.tencent.com/dev#/scf?tab=function) 选择目标函数 2. 在代码编辑器中修改代码 3. 点击「保存并安装依赖」完成部署 ![在线编辑函数代码](https://qcloudimg.tencent-cloud.cn/raw/81a6898ac5cfc68c9e64a3f1973e8999.png) ### 上传代码包部署 对于较复杂的项目,您可以将代码打包后上传: 1. 将函数代码及依赖打包成 ZIP 文件 2. 在云函数详情页面,选择「上传 ZIP 包」 3. 选择本地 ZIP 文件并上传 4. 点击「保存并安装依赖」完成部署 :::tip 提示 ZIP 包的根目录应该包含入口文件,例如 Node.js 环境下的 `index.js` 。 ::: ## 函数配置 在 [云函数管理页面](https://tcb.cloud.tencent.com/dev#/scf?tab=function) 选择目标函数,点击「配置」选项卡,可以调整以下配置项: ### 基础配置 | 配置项 | 说明 | 默认值 | 可选范围 | | -------- | ---------------------------------- | ------ | -------------- | | 内存配置 | 云函数运行时的最大内存限制 | 256MB | 128MB - 2048MB | | 超时时间 | 函数最大运行时间,超时将被强制中断 | 20秒 | 1秒 - 900秒 | | 环境变量 | 以键/值对形式定义的环境变量 | 无 | 自定义 | :::warning 注意 内存配置会影响函数的性能和计费,请根据实际需求合理设置。 ::: ### 网络配置 #### 公网访问 云函数默认开启公网访问能力,您可以根据安全需求选择关闭。关闭后,函数将无法访问公网资源。 #### 内网访问(VPC 配置) 您可以配置云函数访问 VPC 私有网络: * **未配置 VPC**:函数实例在独立网络环境中运行,具备外网访问能力 * **配置 VPC**:函数实例在指定 VPC 网络中运行,可访问 VPC 内资源 :::tip 提示 * 配置 VPC 后如需外网访问能力,请确认 VPC 网络中配置了 [公网网关](https://cloud.tencent.com/document/product/215/20078) 或 [NAT 网关](https://cloud.tencent.com/document/product/215/4975) * 有关 VPC 网络配置的更多信息,请参考 [VPC 私有网络说明](https://cloud.tencent.com/document/product/215) * 关于云函数网络配置的详细说明,请参考 [网络配置详情](https://cloud.tencent.com/document/product/583/14571) ::: #### 固定出口 IP 开启此功能后,云函数将获得一个固定的公网出口 IP,该 IP 会与同一命名空间下其他开启此功能的函数共享。 :::tip 提示 只有云函数开启公网访问时,固定出口 IP 功能才能生效。 ::: ### 限频配置 云函数支持配置访问限频,帮助您控制函数的调用频率,防止恶意调用和资源滥用: * **限频规则**:可以设置每秒、每分钟或每小时的最大调用次数 * **限频策略**:支持基于 IP、用户 ID 等维度进行限频控制 * **超限处理**:当调用频率超过限制时,系统会返回相应的错误信息 :::tip 提示 合理配置限频规则可以有效保护您的云函数免受恶意攻击,同时控制成本。详细配置方法请参考 [限频功能配置指南](/envconfig/ratelimit/intro)。 ::: ### 预置并发配置 预置并发是云函数的高级功能,可以预先启动指定数量的函数实例,有效解决冷启动问题: #### 功能特点 * **消除冷启动**:预置实例始终保持运行状态,请求到达时可立即处理 * **性能提升**:避免了实例启动时间,显著提高响应速度 * **成本优化**:按预置实例的运行时间计费,适合高频访问场景 #### 配置方式 1. 在云函数详情页面,选择「预置并发」选项卡 2. 设置预置并发实例数量 3. 配置预置并发的版本或别名 4. 点击「保存」完成配置 :::tip 提示 * 预置并发适用于访问量稳定且对响应时间要求较高的场景 * 预置实例会持续计费,请根据实际业务需求合理配置数量 ::: ## 函数监控 ### 查看运行日志 在云函数详情页面,选择「日志」选项卡: 1. 设置时间范围和日志级别 2. 查看函数执行日志和错误信息 3. 支持实时日志查看和历史日志检索 ### 监控指标 在云函数详情页面的「监控」选项卡,您可以查看以下关键指标: * 调用次数 * 错误次数 * 平均执行时长 * 内存使用情况 ## 删除云函数 ### 通过控制台删除 1. 在 [云函数管理页面](https://tcb.cloud.tencent.com/dev#/scf?tab=function) 找到目标函数 2. 点击「更多」→「删除」 3. 在确认对话框中输入函数名称确认删除 :::warning 警告 **删除云函数操作不可恢复,删除后函数将不可访问,请谨慎操作。** ::: ## 使用 CLI 管理 如需使用命令行工具进行自动化部署和批量管理,请参考 [CLI 管理云函数](/cli-v1/functions/deploy) 文档。 ## 常见问题 ### 云函数部署失败怎么办? 1. 检查代码是否有语法错误 2. 确认依赖包是否兼容云函数环境 3. 查看部署日志,定位具体错误原因 4. 尝试减小部署包大小,云函数部署包有大小限制 ### 云函数执行超时如何解决? 1. 增加函数超时时间配置 2. 优化代码执行效率 3. 对于长时间运行的任务,考虑拆分为多个函数或使用异步执行 ### 如何处理云函数冷启动问题? 1. 保持函数代码精简,减少不必要的依赖 2. 使用预置并发实例 3. 定期预热函数,保持活跃状态 ### 云函数如何访问数据库? 云函数可以通过 SDK 直接访问云开发数据库,无需额外的认证配置。示例代码: ```javascript const tcb = require('@cloudbase/node-sdk'); const app = tcb.init(); const db = app.database(); exports.main = async (event, context) => { const collection = db.collection('users'); const result = await collection.get(); return result; }; ``` 更多云函数相关问题,请参考 [云函数常见问题解答](https://cloud.tencent.com/document/product/583/9179)。 --- ## 在线开发 # 在线开发 云函数提供了在线开发能力,让您可以通过浏览器中的在线编辑器直接进行云函数的开发、调试、部署等操作 点击云函数右侧的“在线开发”按钮,即可进入在线编辑器 ![](https://qcloudimg.tencent-cloud.cn/raw/b6061f217cd43e9db43bce9c201dc19a.png) > 注意:如果进入编辑器的时间过长,您可以尝试返回再重新进入 ## 调试 在在线编辑器中使用调试功能时,系统会自动启动调试服务并打开测试面板,随后您可以按下图所示进行调试操作 ![](https://qcloudimg.tencent-cloud.cn/raw/269ef9c0025dd36c62fbb43078ad98e5.png) 您可以在以下位置找到指定云函数的调试功能: - 资源管理器 > 云函数通常位于 cloudfunctions 目录下 在指定云函数的目录上点击右键菜单,选择“调试” ![](https://qcloudimg.tencent-cloud.cn/raw/bb05f6381aa1cc576ae4dda0a32997ce.png) - 编辑区 在打开的云函数代码编辑区上点击右键菜单,选择“调试” ![](https://qcloudimg.tencent-cloud.cn/raw/f4ebae8524a9bc18fd97e4ead59acae4.png) - 编辑区右上角 在打开的云函数代码编辑区右上角,点击"云函数操作",选择“调试” ![](https://qcloudimg.tencent-cloud.cn/raw/6fb5836becf5c6b435caa3c1c1cfe502.png) ## 部署 > 功能菜单位置请参考【调试】 在使用部署功能时,系统会进行完整的部署,即同时更新云函数的配置和代码 配置文件通常位于云函数目录下的 serverless.yaml 文件中 部署成功后,系统会显示以下提示: ![](https://qcloudimg.tencent-cloud.cn/raw/8013f2dccd38a65d76e06ae5388583ad.png) ## 增量更新 > 功能菜单位置请参考【调试】 在使用增量更新功能时,系统只会更新云函数的代码,速度较快 增量更新成功后,系统会显示以下提示: ![](https://qcloudimg.tencent-cloud.cn/raw/8013f2dccd38a65d76e06ae5388583ad.png) ## 下载 > 功能菜单位置请参考【调试】 下载功能能够将云函数的代码及配置文件同步到本地 下载成功后,系统会显示以下提示: ![](https://qcloudimg.tencent-cloud.cn/raw/c6dd89fbb94103eab7eacf697b9e0a94.png) --- ## 快速开始 import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # 快速开始 云函数本质也是一份代码,这里拿 **Node.js** 作为示例,介绍如何创建云函数 **Node.js** 服务一般都需要一个 **入口文件 index.js** ,如果您用到了 **npm** 包,还需要一个 **package.json** 文件,用于描述依赖关系。 因此最基本的 node 服务目录结构如下: ```bash └── helloWorld ├── index.js └── package.json ``` ## 创建云函数 你可以在云开发控制台创建云函数,也可以选择在本地项目中创建云函数 ### 云开发控制台创建 进入 [云开发/云函数](https://tcb.cloud.tencent.com/dev?#/scf),点击「**新建云函数**」按钮 1. 选择合适的模版,没有合适的可以选择从空白创建 2. 选择运行环境为 **Nodejs 18.15** (也可以选择其他版本) 3. 填入函数名称 4. 点击「**开始创建**」按钮 ![](https://qcloudimg.tencent-cloud.cn/raw/53a66c0e31594220c634f3741a47660a.png) 创建完成后,进入到云函数中,可以看到默认有个 **index.js** 文件 ![](https://qcloudimg.tencent-cloud.cn/raw/6d46e2a1966c65982fe460444d6886a1.png) 5. 编写 `index.js` 文件内容如下: ```js exports.main = async function () { return "Hello World!"; }; ``` 6. 点击下方「**保存并安装依赖**」,即可完成云函数的 **部署** ### 小程序 IDE 创建 如果您是基于「**微信开发者工具**」进行开发云函数,那么可以直接在微信开发者工具中创建云函数,步骤参考 [云函数快速开始](https://developers.weixin.qq.com/miniprogram/dev/wxcloudservice/wxcloud/guide/functions/getting-started.html) 1. 右键云函数目录,选择「**新建 Node.js 云函数**」,即可创建云函数 2. 编写 `index.js` 文件内容如下: ```js exports.main = async function () { return "Hello World!"; }; ``` 3. 选择云函数目录,右键点击,选择「**创建并部署:云端安装依赖**」,即可完成云函数的 **部署**。 ### 本地创建 1. 在本地创建一个空的文件夹,作为项目的根目录,这里命名为 `cloud-demo` (项目根目录) 2. 进入根目录,创建 **functions** 文件夹 (存放云函数的目录) 3. 在 **functions** 下创建 **hello_world** 文件夹 (具体云函数目录) 4. 在云函数 **hello_world** 中创建 **index.js** (云函数入口文件) 此时目录结构如下: ``` └── cloud-demo // 项目根目录 └── functions // 云函数目录 └── hello_world // 云函数实例 └── index.js // 云函数入口文件 ``` 4. 编写 `index.js` 文件内容如下: ```js exports.main = async function () { return "Hello World!"; }; ``` 5. 然后打开终端到当前 `hello_world` 文件夹下,执行以下命令初始化 **package.json** ```bash npm init -y ``` 6. 安装并登录 CLI 工具,在终端执行如下命令全局安装 cli: cli 工具具体详情参考:[cli 快速开始](/cli-v1/quick-start) ```bash npm i -g @cloudbase/cli ``` 安装成功后输入如下命令检查是否安装成功: ```bash tcb -v ``` 如果看到输出版本号,说明已经安装成功 7. cli 登录 需要让 cli 登录到云函数需要发布的环境中,执行如下命令: ```bash tcb login ``` CloudBase CLI 会自动打开云开发控制台获取授权,您需要点击「**同意授权**」按钮允许 CloudBase CLI 获取授权。如您没有登录,您需要登录后才能进行此操作 8. 在**项目根目录**运行以下命令,并且使用**默认配置**: ⚠️ 注意:需要获取云开发环境的 **环境 ID** ```bash tcb fn deploy hello_world -e ``` ![](https://qcloudimg.tencent-cloud.cn/raw/5022534c1b74d6f2d11c838b680dcdb9.png) ## 调用云函数 调用云函数主要有以下几种方法: - 使用云开发 **SDK** - 使用 **HTTP 访问服务** - 使用 **HTTP API** - 使用**触发器** ### 使用 SDK 调用云函数 ```js wx.cloud .callFunction({ // 云函数名称 name: "hello_world", // 传给云函数的参数 data: { a: 1, }, }) .then((res) => { console.log(res); // Hello World! }) .catch(console.error); ``` ```js //初始化SDK实例 const cloudbase = require("@cloudbase/js-sdk"); const app = cloudbase.init({ env: "xxxx-yyy", }); app .callFunction({ // 云函数名称 name: "hello_world", // 传给云函数的参数 data: { a: 1, }, }) .then((res) => { console.log(res); // Hello World! }) .catch(console.error); ``` ```js const cloudbase = require("@cloudbase/node-sdk"); const app = cloudbase.init({ env: "xxxx-yyy", }); app .callFunction({ // 云函数名称 name: "hello_world", // 传给云函数的参数 data: { a: 1, }, }) .then((res) => { console.log(res); // Hello World! }) .catch(console.error); ``` ### 使用 HTTP 访问服务调用云函数 您可以选择创建 **HTTP 服务** 用来访问云函数,然后通过 HTTP 调用云函数。 有如下两种操作方式: #### 云开发控制台 1. 进入 [云开发/HTTP 访问服务](https://tcb.cloud.tencent.com/dev?#/env/http-access) 2. 新建一个「域名关联资源」 - 关联资源 选择云函数,hello_world - 域名选择默认域名,也可以选择您自定义域名 - 填写触发路径,这里填写/hello ![](https://qcloudimg.tencent-cloud.cn/raw/342a027d8d10805110608dce3f914b04.png) 3. 点击确定,等待 3-5 分钟后,即可完成 **HTTP 服务** 创建 ![](https://qcloudimg.tencent-cloud.cn/raw/9144a724e4fa6a106ed3449c0124f5ce.png) 4. HTTP 服务地址为 `默认域名+触发路径`,您也可以选择用自定义域名进行绑定资源 #### cli 工具 具体请参考 [http 访问服务](/cli-v1/service) 执行以下命令创建一条 HTTP 服务路由,路径为 `/hello` ,指向的云函数为 `hello_world` : ```bash tcb service create -p hello -f hello_world -e ``` 随后便可以通过 进入 [云开发/HTTP 访问服务](https://tcb.cloud.tencent.com/dev?#/env/http-access) 查看创建的 HTTP 服务 ### 使用 HTTP API 调用云函数 创建好云函数后,可以通过 HTTP API 在任意客户端调用云函数,无需 SDK。 具体请参考 [HTTP API 调用云函数](/http-api/functions/functions-post),访问 HTTP API 需要一个 [access_token](/http-api/basic/access-token)。 ```bash curl -L 'https://your-envId.api.tcloudbasegateway.com/v1/functions/:name' \ -H 'Content-Type: application/json' \ -H 'Accept: application/json' \ -H 'Authorization: Bearer ' \ -d '{}' ``` ### 触发器 #### 定时触发器 您在云函数详情页中可以配置定时触发器,配置完成后,云函数将会在指定时间自动触发。如配置下面配置,则云函数将会在每个月的 1 号凌晨 2 点自动触发: ```json { // triggers 字段是触发器数组,目前仅支持一个触发器,即数组只能填写一个,不可添加多个 "triggers": [ { // name: 触发器的名字,规则见下方说明 "name": "myTrigger", // type: 触发器类型,目前仅支持 timer (即定时触发器) "type": "timer", // config: 触发器配置,在定时触发器下,config 格式为 cron 表达式,规则见下方说明 "config": "0 0 2 1 * * *" } ] } ``` 详情请参考 [定时触发器](/cloud-function/timer-trigger)。 #### 其他触发器 云开发云函数还能被丰富的触发器类型触发,比如[小程序云开发环境](/quick-start/create-env#方式一微信开发者工具推荐小程序开发者)中可以云函数的[消息推送](https://developers.weixin.qq.com/miniprogram/dev/wxcloudservice/wxcloud/guide/functions/openapi.html)和[事件触发器](https://developers.weixin.qq.com/miniprogram/dev/wxcloudservice/wxcloud/guide/functions/EveTrigger.html)。 --- ## 使用服务端 SDK 访问 CloudBase import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # 使用服务端 SDK 访问 CloudBase 如需在云函数中访问 CloudBase 的各项服务,例如操作数据库、管理云文件等,可使用 CloudBase 服务端 SDK。 例如,您可以在 Node.js 云函数中,使用 [CloudBase Node.js SDK](/api-reference/server/node-sdk/introduction) 调用 CloudBase 服务。 ```js const cloudbase = require("@cloudbase/node-sdk"); const app = cloudbase.init({ env: cloudbase.SYMBOL_CURRENT_ENV }); const db = app.database(); exports.main = async (event, context) => { return db.collection("todos").get(); }; ``` :::tip 提示 CloudBase 服务端 SDK 已经与云函数进行集成,无需手工填入密钥即可使用。 ::: ## 初始化 SDK ```js const cloudbase = require("@cloudbase/node-sdk"); const app = cloudbase.init({ env: cloudbase.SYMBOL_CURRENT_ENV }); ``` ## 调用数据库 ```js const db = app.database(); exports.main = async (event, context) => { return db.collection("todos").get(); }; ``` ## 调用云存储 ```js exports.main = async (event, context) => { const fileStream = fs.createReadStream(path.join(__dirname, "demo.jpg")); return await app.uploadFile({ cloudPath: "demo.jpg", fileContent: fileStream }); }; ``` ## 调用其它云函数 ```js exports.main = async (event, context) => { return await cloud.callFunction({ name: "sum", data: { x: 1, y: 2 } }); }; ``` ## 获取用户信息 当从客户端调用云函数时,如在小程序中或者 web 端使用微信登录授权,云函数的传入参数中会被注入用户的 `openid`,开发者无需校验 `openid` 的正确性,可以直接使用该 `openid`。与 `openid` 一起注入云函数的还有其它相关的用户身份信息。 ```js //引用SDK const tcb = require("@cloudbase/node-sdk"); //初始化SDK const app = tcb.init(); //获取用户信息 const userInfo = await app.auth().getUserInfo(); const { openId, //微信openId,非微信授权登录则空 appId, //微信appId,非微信授权登录则空 uid, //用户唯一ID customUserId //开发者自定义的用户唯一id,非自定义登录则空 } = userInfo; ``` 从小程序端调用云函数时,开发者可以在云函数内使用 [wx-server-sdk](https://developers.weixin.qq.com/miniprogram/dev/wxcloud/guide/functions/wx-server-sdk.html) 提供的 [getWXContext](https://developers.weixin.qq.com/miniprogram/dev/wxcloud/reference-sdk-api/utils/Cloud.getWXContext.html) 方法获取到每次调用的上下文(`appid`、`openid` 等),无需维护复杂的鉴权机制,即可获取可信任的用户登录态(`openid`)。 示例代码 ```js // index.js const cloud = require("wx-server-sdk"); exports.main = async (event, context) => { // 这里获取到的 openId、 appId 和 unionId 是可信的,注意 unionId 仅在满足 unionId 获取条件时返回 const { OPENID, APPID, UNIONID } = cloud.getWXContext(); return { OPENID, APPID, UNIONID }; }; ``` ## 参考 更多详细信息请参考: - [Node.js SDK 文档](/api-reference/server/node-sdk/introduction) - [wx-server-sdk](https://developers.weixin.qq.com/miniprogram/dev/wxcloud/reference-sdk-api/init/server.init.html) --- ## 云函数安全规则 # 云函数安全规则 ## 概述 云函数安全规则是基于用户身份的权限管理系统,可以根据当前登录用户的身份进行函数调用权限控制。通过配置安全规则,您可以精确控制哪些用户可以调用特定的云函数,从而保障应用的安全性。 ## 适用范围 云函数安全规则适用于以下调用场景: - 客户端 SDK 的 `callFunction` 操作 - 小程序、Web 应用等 C 端用户调用 **不适用场景:** - 管理端 API 调用 - HTTP 触发器调用 - 定时触发器调用 - 数据库触发器调用 ## 配置方法 ### 1. 进入控制台配置 1. 登录 [腾讯云开发控制台/云函数](https://tcb.cloud.tencent.com/dev?#/scf?tab=function) 2. 选择对应的环境 3. 进入「安全规则」页面 4. 选择「云函数」标签页 ### 2. 编写安全规则 函数安全规则配置在环境级别,环境内所有函数共享一个配置文件。配置采用 JSON 格式,具有以下层级结构: **配置层级说明:** 1. **顶级 key**:表示函数名,特殊的 `*` 表示所有函数的通配规则 2. **操作 key**:表示操作类型,当前仅支持 `invoke`(调用) 3. **规则值**:可以是布尔值或安全规则表达式字符串 **匹配优先级:** - 优先匹配具体的函数名配置 - 如果没有匹配到具体函数名,则使用 `*` 通配配置 ## 配置示例 ### 基础配置 ```json { "*": { "invoke": "auth != null" } } ``` ### 复合配置示例 ```json { "*": { "invoke": "auth != null" }, "function1": { "invoke": false } } ``` **配置要求:** 1. 安全规则顶级配置**必须**包含 key 为 `*` 的配置。 2. 每个函数下的配置中**必须**包含 invoke 配置。 ## 支持的规则类型 目前云函数安全规则支持以下三种配置: | 规则值 | 说明 | 适用场景 | | ---------------- | ---------------- | -------------------------- | | `true` | 允许所有用户调用 | 公开接口,如获取公告信息 | | `false` | 禁止所有用户调用 | 已废弃的函数或内部函数 | | `"auth != null"` | 仅登录用户可调用 | 需要用户身份验证的业务函数 | ## 配置要求 :::tip 注意 1. 安全规则顶级配置**必须**包含 key 为 `*` 的通配配置 2. 每个函数配置中**必须**包含 `invoke` 操作配置 3. 默认情况下,所有函数都要求用户登录后才能调用 ::: ## 常见问题 ### Q: 如何测试安全规则是否生效? A: 可以通过客户端 SDK 调用函数进行测试: - 未登录状态调用需要登录的函数,应该返回权限错误 - 登录后调用相同函数,应该正常执行 ### Q: 可以针对不同用户设置不同权限吗? A: 当前版本仅支持基于登录状态的简单权限控制。如需更复杂的权限控制,建议在函数内部进行用户身份和权限验证。 --- ## 测试、日志与监控 import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # 测试、日志与监控 本文档详细介绍如何使用云开发提供的测试、日志查看和监控功能,帮助开发者高效调试和监控云函数运行状态。 ## 前置条件 在开始测试和监控云函数之前,请确保: - 已创建腾讯云开发环境 - 已部署至少一个云函数 - 具有相应的访问权限 ## 云函数测试 云开发提供了多种云函数测试方式,支持在线调试和本地测试,帮助开发者更加方便地调试代码。 ### 控制台测试 通过云开发控制台可以快速测试云函数的执行效果。 #### 测试步骤 1. 在控制台的对应云函数管理面板中,点击「测试」按钮,打开测试弹窗 2. 选择测试模板或自定义测试参数 3. 点击「执行」运行测试 4. 查看运行结果和日志输出 ![控制台测试界面](https://qcloudimg.tencent-cloud.cn/raw/d7a91502cc57ebf17c8323fbf24a57e0.png) #### 测试参数配置 **使用模板参数** - 点击「提交方法」下拉菜单,选择测试函数的模板方法 - 模板参数在测试时作为 `event` 参数传递给函数 **自定义参数** 在测试参数编辑器中输入 JSON 格式的测试数据: ```json { "name": "test", "data": { "key": "value", "number": 123 } } ``` #### 本地调试工具 除了可视化测试功能,还可以使用命令行工具 [scf-cli](https://github.com/TencentCloud/scf-node-debug) 进行本地调试: ```bash # 安装 scf-cli npm install -g scf-cli # 本地调试函数 scf local invoke --template template.yaml --event event.json ``` ### 微信开发者工具测试 在微信开发者工具中可以直接测试云函数。 #### 测试步骤 1. 在控制台的对应云函数管理面板中,点击「云端测试」,打开测试弹窗 2. 配置测试参数 3. 点击「执行」运行测试 4. 查看执行结果 ![微信工具测试界面](https://main.qcloudimg.com/raw/0b5740fd250161df3801d547aed42fbe.jpg) #### 参数配置说明 - **提交方法**:选择测试函数的模板方法,当前支持 `Hello World` 事件模板 - **测试参数**:在编辑器中输入 JSON 格式的测试参数 - **运行结果**:执行完毕后,结果将显示在"运行测试"栏中 #### 本地调试支持 微信开发者工具同样支持使用 [scf-cli](https://github.com/TencentCloud/scf-node-debug) 进行本地快速调试。 ## 日志查看 云开发提供了完善的日志系统,帮助开发者快速定位和解决问题。 ### 日志功能特点 - **实时日志**:支持实时查看函数执行日志 - **结构化展示**:日志信息结构化展示,便于分析 - **多维度筛选**:支持按时间、状态等条件筛选日志 - **详细信息**:包含请求ID、执行时间、内存使用等详细信息 ### 控制台日志查看 1. 登录云开发控制台 2. 进入对应的云函数管理页面 3. 点击「日志」标签页 4. 选择时间范围查看日志记录 ![控制台日志界面](https://main.qcloudimg.com/raw/a31e3ac2425422971153658ab93b3c0f.jpg) #### 日志信息说明 每条日志记录包含以下信息: - **时间戳**:函数执行的具体时间 - **请求ID**:唯一标识一次函数调用 - **执行状态**:成功或失败状态 - **执行时长**:函数执行耗时 - **内存使用**:函数运行时的内存占用 - **日志内容**:函数中 console.log 等输出的内容 ### 微信开发者工具日志 在微信开发者工具中查看云函数日志: 1. 打开微信开发者工具 2. 进入云开发控制台 3. 选择对应的云函数 4. 点击「日志」查看执行记录 ![微信工具日志界面](https://main.qcloudimg.com/raw/3a4486f57df5c51c2ff08620f17c733f.jpg) ### 日志最佳实践 #### 结构化日志记录 在函数代码中使用结构化的日志记录方式: ```javascript exports.main = async (event, context) => { const requestId = context.requestId; // 记录请求开始 console.log(JSON.stringify({ level: 'INFO', requestId, message: '函数开始执行', timestamp: new Date().toISOString(), event: event })); try { // 业务逻辑 const result = await processData(event); // 记录成功结果 console.log(JSON.stringify({ level: 'INFO', requestId, message: '函数执行成功', result: result })); return result; } catch (error) { // 记录错误信息 console.error(JSON.stringify({ level: 'ERROR', requestId, message: '函数执行失败', error: { message: error.message, stack: error.stack } })); throw error; } }; ``` #### 日志级别使用 合理使用不同的日志级别: ```javascript // 普通信息 console.log('普通日志信息'); // 重要信息 console.info('重要信息级别日志'); // 警告信息 console.warn('警告级别日志'); // 错误信息 console.error('错误级别日志'); ``` :::tip 注意事项 - 避免在日志中记录敏感信息(如密码、密钥等) - 合理控制日志输出量,避免产生过多日志 - 使用结构化日志格式,便于后续分析和处理 ::: ## 监控数据 云开发提供了丰富的监控指标,帮助开发者了解云函数的运行状况和性能表现。 ### 监控指标 云函数监控包含以下核心指标: - **调用次数**:函数被调用的总次数 - **运行时间**:函数执行的平均时间和最大时间 - **错误次数**:函数执行失败的次数 - **成功率**:函数执行成功的百分比 - **内存使用**:函数运行时的内存占用情况 - **并发数**:同时执行的函数实例数量 ### 控制台监控查看 1. 登录云开发控制台 2. 进入对应的云函数管理页面 3. 点击「监控」标签页 4. 选择时间范围查看监控数据 5. 点击「导出数据」可以导出监控数据 ![控制台监控界面](https://main.qcloudimg.com/raw/d03c9fbb6204c2c5b1850c6463625a30.png) #### 监控功能特点 - **多时间维度**:支持查看不同时间范围的监控数据 - **图表展示**:直观的图表展示各项指标趋势 - **数据导出**:支持导出监控数据进行离线分析 - **实时更新**:监控数据实时更新,反映最新状态 ### 微信开发者工具监控 在微信开发者工具中查看云函数监控数据: 1. 打开微信开发者工具 2. 进入云开发控制台 3. 选择对应的云函数 4. 点击「监控」查看各项指标 ![微信工具监控界面](https://main.qcloudimg.com/raw/a1d5365cd4b05f407b321f3878a2314d.jpg) --- ## 定时触发器 import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # 定时触发器 您可以使用定时触发器结合云函数,实现定时任务的功能。 ## 设置定时触发器 进入 [云函数管理页面](https://tcb.cloud.tencent.com/dev#/scf?tab=function),选择要配置的函数,点击编辑,修改表单的定时触发器选项,可以上传配置文件或配置内容 详见 [CloudBase CLI 文档](/cli-v1/functions/trigger)。 ## 配置示例 ```js { // triggers 字段是触发器数组,目前仅支持一个触发器,即数组只能填写一个,不可添加多个 "triggers": [ { // name: 触发器的名字,规则见下方说明 "name": "myTrigger", // type: 触发器类型,目前仅支持 timer (即定时触发器) "type": "timer", // config: 触发器配置,在定时触发器下,config 格式为 cron 表达式,规则见下方说明 "config": "0 0 2 1 * * *" } ] } ``` ## 配置详解 #### 字段规则 - 定时触发器名称(name) :最大支持 60 个字符,支持 `a-z`, `A-Z`, `0-9`, `-` 和 `_`。必须以字母开头,且一个函数下不支持同名的多个定时触发器。 - 定时触发器触发周期 (config):指定的函数触发时间。填写自定义标准的 Cron 表达式来决定何时触发函数。有关 Cron 表达式的更多信息,请参考以下内容。 #### Cron 表达式 Cron 表达式有七个必需字段,按空格分隔。其中,每个字段都有相应的取值范围: | 排序 | 字段 | 值 | | ------ | ---- | --------------------------------------------------------------------------------------- | | 第一位 | 秒 | 0 - 59 的整数 | | 第二位 | 分钟 | 0 - 59 的整数 | | 第三位 | 小时 | 0 - 23 的整数 | | 第四位 | 日 | 1 - 31 的整数(需要考虑月的天数) | | 第五位 | 月 | 1 - 12 的整数或 JAN、FEB、MAR、APR、MAY、JUN、JUL、AUG、SEP、OCT、NOV 和 DEC | | 第六位 | 星期 | 0 - 6 的整数或 MON、TUE、WED、THU、FRI、SAT 和 SUN,其中 0 指周日,1 指星期一,以此类推 | | 第七位 | 年 | 1970 - 2099 的整数 | #### 通配符 | 通配符 | 含义 | | ------ | ------------------------------------------------------------------------------------------------------------------------------ | | `,` | 代表取用逗号隔开的字符的并集。例如:在“小时”字段中 1,2,3 表示 1 点、2 点和 3 点。 | | `-` | 包含指定范围的所有值。例如:在“日”字段中,1 - 15 包含指定月份的 1 号到 15 号。 | | `*` | 表示所有值。在“小时”字段中,表示每个小时。 | | `/` | 指定增量。在“分钟”字段中,输入 1/10 以指定从第一分钟开始的每隔十分钟重复。例如,第 11 分钟、第 21 分钟和第 31 分钟,以此类推。 | :::tip 注意 在 Cron 表达式中的“日”和“星期”字段同时指定值时,两者为“或”关系,即两者的条件均生效。 ::: #### cronjob 示例 下面列举一些 Cron 表达式和相关含义: - `*/5 * * * * * *` 表示每 5 秒触发一次 - `0 0 2 1 * * *` 表示在每月的 1 日的凌晨 2 点触发 - `0 15 10 * * MON-FRI *` 表示在周一到周五每天上午 10:15 触发 - `0 0 10,14,16 * * * *` 表示在每天上午 10 点,下午 2 点,下午 4 点触发 - `0 */30 9-17 * * * *` 表示在每天上午 9 点到下午 5 点内每半小时触发 - `0 0 12 * * WED *` 表示在每个星期三中午 12 点触发 --- ## 时区设置 # 时区设置 云函数的运行环境内保持的是 UTC 时间,即 0 时区时间,和北京时间有 8 小时的时间差。 可以通过语言的时间处理相关库或代码包(如 moment-timezone),识别 UTC 时间并转换为+8 区北京时间。 > 注意:当前云开发支持的函数版本为 Node 10,无法通过设置环境变量 TZ=Asia/Shanghai 指定时区(Node 15+版本支持)。 参考代码: ```javascript const moment = require("moment-timezone"); // 需在 package.json 中指定并安装依赖 exports.main = async (event, context) => { // javascript date console.log(new Date()); // 2021-03-16T08:04:07.441Z (UTC+0) console.log(moment().tz("Asia/Shanghai").format()); // 2021-03-16T16:04:07+08:00 (UTC+8) }; ``` --- ## Web 函数 # Web 函数 Web 函数是云开发提供的新一代云函数运行环境,专门针对 Web 服务场景进行了优化。相比于事件函数,Web 函数支持标准的 HTTP 请求响应模式,用户可以快速将现有的 Web 服务迁移到 Serverless 架构上。 ## 前置条件 - 已开通云开发服务 - 已创建云开发环境 - 本地已安装 [CloudBase CLI](/cli-v1/intro) ## 运行机制 Web 函数与事件函数的运行机制对比: | 特性 | 事件函数 | Web 函数 | |------|----------|----------| | 触发方式 | 事件驱动 | HTTP 请求 | | 执行环境 | 每次调用创建新环境 | 支持环境复用 | | 连接方式 | 短连接 | 支持长连接 | | 端口监听 | 无需监听端口 | 监听 9000 端口 | | 适用场景 | 事件处理、定时任务 | Web 服务、API 接口 | ## 核心特性 Web 函数具备以下核心能力: - **HTTP 请求处理**:直接接收和处理标准 HTTP 请求 - **SSE 支持**:支持 Server-Sent Events 实时推送 - **WebSocket 支持**:支持 WebSocket 长连接通信 - **文件上传下载**:支持文件的上传和下载操作 - **框架兼容**:兼容 Express.js、Koa.js 等主流 Web 框架 ## 适用场景 Web 函数特别适用于以下场景: - **RESTful API 服务**:构建标准的 REST API 接口 - **Web 应用迁移**:将现有 Web 应用迁移到 Serverless 架构 - **微服务架构**:将单体应用拆分为多个独立的微服务 - **实时通信**:基于 SSE 或 WebSocket 的实时数据推送 - **文件处理服务**:提供文件上传、下载、转换等功能 ## 开发方式 云开发 Web 函数支持两种开发方式: ### 1. 框架模式 使用 `@cloudbase/functions-framework` 框架,保持函数式编程风格: ```javascript // 使用函数式写法 exports.main = async function(event, context) { // 业务逻辑 return { statusCode: 200, body: JSON.stringify({ message: 'Hello World' }) }; }; ``` ### 2. 原生模式 编写完整的 HTTP 服务代码,监听 9000 端口: ```javascript // 使用 Express.js 框架 const express = require('express'); const app = express(); app.get('/', (req, res) => { res.json({ message: 'Hello World' }); }); app.listen(9000, () => { console.log('Server running on port 9000'); }); ``` ## 使用 Functions Framework 开发 推荐使用 `@cloudbase/functions-framework` 框架进行开发,它提供了更简洁的函数式编程体验。 ### 项目结构 ``` my-web-function/ ├── scf_bootstrap # 启动脚本(必需) ├── package.json # 项目配置 └── index.js # 函数代码 ``` ### 启动脚本 创建 `scf_bootstrap` 文件: ```bash #!/bin/bash node node_modules/@cloudbase/functions-framework/bin/tcb-ff.js --port=9000 --logDirname=/tmp/logs --interceptOutput=false --extendedContextKey=X-Cloudbase-Context ``` :::tip 注意 `scf_bootstrap` 文件需要具有可执行权限,在 Linux/macOS 系统中使用 `chmod +x scf_bootstrap` 命令设置权限。 ::: ### 依赖配置 `package.json` 文件: ```json { "name": "my-web-function", "version": "1.0.0", "main": "index.js", "dependencies": { "@cloudbase/functions-framework": "^1.14.0" } } ``` ### 基础示例 `index.js` 文件: ```javascript exports.main = async function(event, context) { const { method, path, headers, body } = event; // 处理不同的 HTTP 方法 switch (method) { case 'GET': return { statusCode: 200, headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ message: 'Hello from Web Function', path, timestamp: new Date().toISOString() }) }; case 'POST': return { statusCode: 201, headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ message: 'Data received', data: JSON.parse(body || '{}') }) }; default: return { statusCode: 405, body: JSON.stringify({ error: 'Method not allowed' }) }; } }; ``` ## SSE 实时推送示例 Web 函数支持 Server-Sent Events,可以实现实时数据推送: ```javascript exports.main = async function(event, context) { // 切换到 SSE 模式 const sse = context.sse(); // 监听连接关闭事件 sse.on('close', () => { console.log('SSE connection closed'); }); // 发送实时数据 if (!sse.closed) { // 发送文本数据 sse.send({ data: 'Hello from SSE function' }); // 发送 JSON 数据 sse.send({ data: JSON.stringify({ type: 'notification', message: 'New message received', timestamp: Date.now() }) }); // 发送 Buffer 数据 sse.send({ data: Buffer.from('Binary data message') }); } return ''; }; ``` ## 部署配置 ### 使用 CLI 部署 1. 安装依赖: ```bash npm install ``` 2. 创建 `cloudbaserc.json` 配置文件: ```json { "envId": "your-env-id", "functions": [ { "name": "webFunction", "type": "web", "source": "./", "runtime": "Nodejs16.13", "memorySize": 256, "timeout": 60, "environment": { "NODE_ENV": "production" } } ] } ``` 3. 部署函数: ```bash cloudbase functions:deploy webFunction ``` ### 通过云开发平台部署 1. 登录 [云开发平台](https://console.cloud.tencent.com/tcb) 2. 选择目标环境,进入「云函数」页面 3. 点击「新建函数」,选择「Web 函数」类型 4. 上传代码包或在线编辑代码 5. 配置函数参数并部署 ## 函数调用 ### HTTP API 调用 Web 函数部署成功后,可通过 HTTP API 进行调用: ```bash curl -L 'https://{envId}.api.tcloudbasegateway.com/v1/functions/{functionName}?webfn=true' \ -H 'Content-Type: application/json' \ -H 'Accept: application/json' \ -H 'Authorization: Bearer ' \ -d '{}' ``` :::tip 重要提示 调用 Web 函数时必须在 URL 中添加 `webfn=true` 参数,否则调用会失败。 ::: ### 获取访问令牌 调用 Web 函数需要携带访问令牌,获取方式请参考:[Access Token](/http-api/basic/access-token) ## 最佳实践 ### 1. 错误处理 ```javascript exports.main = async function(event, context) { try { // 业务逻辑 const result = await processRequest(event); return { statusCode: 200, headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(result) }; } catch (error) { console.error('Function error:', error); return { statusCode: 500, headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ error: 'Internal server error', message: error.message }) }; } }; ``` ### 2. 参数验证 ```javascript function validateRequest(event) { const { method, body } = event; if (method === 'POST') { const data = JSON.parse(body || '{}'); if (!data.name || !data.email) { throw new Error('Missing required fields: name, email'); } // 邮箱格式验证 const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; if (!emailRegex.test(data.email)) { throw new Error('Invalid email format'); } } } ``` ### 3. 环境变量使用 ```javascript exports.main = async function(event, context) { const config = { apiKey: process.env.API_KEY, dbUrl: process.env.DATABASE_URL, debug: process.env.NODE_ENV === 'development' }; if (!config.apiKey) { return { statusCode: 500, body: JSON.stringify({ error: 'Missing API key configuration' }) }; } // 使用配置进行业务处理 }; ``` ## 注意事项 :::tip 重要说明 - Web 函数必须监听 9000 端口 - 使用 Functions Framework 时需要包含 `scf_bootstrap` 启动脚本 - 函数代码包大小限制为 50MB(压缩后) - 单次请求超时时间最长为 900 秒 - 支持的运行时:Node.js 12.16、14.18、16.13、18.15 ::: ### 与事件函数的差异 Web 函数的 `event` 和 `context` 参数与事件函数存在差异: - **event 对象**:包含 HTTP 请求的完整信息(method、path、headers、body 等) - **context 对象**:提供 SSE 支持等 Web 特有功能 - **环境变量**:运行时环境变量可能有所不同 ## 常见问题 ### 如何处理文件上传? ```javascript exports.main = async function(event, context) { const { method, headers, body } = event; if (method === 'POST' && headers['content-type']?.includes('multipart/form-data')) { // 处理文件上传逻辑 // 注意:需要解析 multipart 数据 return { statusCode: 200, body: JSON.stringify({ message: 'File uploaded successfully' }) }; } return { statusCode: 400, body: JSON.stringify({ error: 'Invalid request' }) }; }; ``` ### 如何实现跨域支持? ```javascript exports.main = async function(event, context) { const corsHeaders = { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS', 'Access-Control-Allow-Headers': 'Content-Type, Authorization' }; // 处理预检请求 if (event.method === 'OPTIONS') { return { statusCode: 200, headers: corsHeaders, body: '' }; } // 正常请求处理 return { statusCode: 200, headers: { ...corsHeaders, 'Content-Type': 'application/json' }, body: JSON.stringify({ message: 'Success' }) }; }; ``` ## 相关文档 - [Access Token 获取](/http-api/basic/access-token) - [CloudBase CLI 使用指南](/cli-v1/intro) - [函数型托管](/cbrf/intro) --- ## 操作指引 # 操作指引 ## 创建活动 活动配置能力强大,赋能运营推广 - 活动开关:可灵活控制开关 - 活动开始结束时间:可提前预设好活动时间,无需盯着时间打开开关 - 自定义背景图:自定义跳转页,提高单个活动的拉起率 - 小程序跳转地址:每个活动都可以跳到不同的地址,服务端更新后,用户打开页面即生效 ![](https://main.qcloudimg.com/raw/1ea7f9017aaf817c80e35c68eaaf89c3.png) ## 投放渠道管理 支持自定义渠道,可为不同渠道生成定制链接,使用该链接投放后,可提供后续的一站式转化数据分析 ![](https://main.qcloudimg.com/raw/5d05119ba5f6dac3664baa1748eab0b4.png) ### H5 投放渠道 ![](https://main.qcloudimg.com/raw/85d022de12e6a39bb5bc62ee6ff4753f.png) ### 短信渠道 发送短信时,需要指定活动,下发的短信将与该活动的配置关联。 ![](https://main.qcloudimg.com/raw/26a653456088fba245c968892a1cc9d4.jpg) ![](https://main.qcloudimg.com/raw/37e1e839e04d39b400ccfbcd421f05ff.png) ## 中间页跳转 中间页拉起小程序,可自定义背景图 ![](https://main.qcloudimg.com/raw/58a3e04e993870def40579a24067c5cb.jpg) ## 统计分析 支持针对不同活动进行数据统计分析。后续将提供基于活动带来的跳转小程序用户做更多的数据分析,提供留存、画像、支付等数据,助力小程序运营。 1. 概览:短信下发总数、H5 页面访问总数(各个渠道累计值)、跳转小程序总数(各个渠道累计值) 2. 占比饼图:H5 访问累计占比、跳转小程序累计占比 3. 短信渠道转化漏斗 4. 实时访问曲线:可勾选指定渠道、实时查看转化数据 ![](https://main.qcloudimg.com/raw/49ca47a06a11c0f4fa1c8da1b8cc5b4d.png) --- ## 更新日志 # 更新日志 ## 🚀 云开发内容管理全新升级 ✨ ### 更新日期:20240918 ### ✨ 【新特性概览】 - 🌐 支持对接多种数据源:MySQL 、云开发数据库等 - 🚀 一键生成应用:自定义可视化编辑,支持发布到管理后台 - 🛠️ 无需部署:云端一键开启使用 - 💰 内容管理免费使用,无文档数量限制 - 📱 支持移动端访问 - 📤 数据导入/导出能力提升 - ☁️ 数据支持存储在云开发数据集合 - 🛠️ 提供 SDK 及 HTTP API:支持数据校验和类型检查 ### 📢 【新功能预告】 - 💻 本地部署:支持整体独立部署在用户服务器 - 📊 AI 数据分析:使用 AI 基于内容数据一键生成图表分析页面 📒【产品文档】:https://docs.cloudbase.net/cms/intro 👉 点击进入 【新版本内容管理】: https://tcb.cloud.tencent.com/cloud-admin/#/management/content-mgr/index --- ## 常见问题 import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # 常见问题 ## 安装 ### 云控制台、微信 IDE 云开发控制台找不到内容管理? 不同于原开源版 CMS 以及 CMS 云模板,内容管理 属于云后台的内置系统要开通云后台后进行使用。 进入 [内容管理](https://tcb.cloud.tencent.com/cloud-admin/#/management/content-mgr/index) ## 功能 ### 云数据库与内容管理与什么区别和联系? #### 区别 **定位与功能**: - **云数据库**:专注于数据的结构、关系及其操作。它提供了一系列数据库操作功能,如增删改查,并支持高级查询与校验。这类应用主要用于数据的维护与管理,确保数据的完整性与一致性。 - **内容管理**:聚焦于内容的展示与编辑。其直观的可视化界面让非技术人员也能便捷地进行内容管理。它适用于多种类型内容的管理,如文本、图片、文件等,并支持富文本及 Markdown 格式的编辑。 **使用场景**: - **云数据库**:适合那些需要精细控制数据结构与关系的场景,如企业级应用、数据分析以及复杂的数据操作等。 - **内容管理**:适用于需要迅速搭建内容展示与编辑平台的场合,例如新闻网站、博客、电商平台等。 #### 联系 - **数据共享**:无论是云数据库还是内容管理,都可以访问并操作云开发数据库中的数据。内容管理应用中的内容数据可通过云开发的各端 SDK 进行访问与操作。 - **集成能力**:内容管理能够与云开发的生态系统紧密集成,支持与云函数、触发器、API 等其他云开发组件的整合,从而实现更为丰富的业务逻辑。 - **用户体验**:内容管理通过直观的可视化编辑界面降低了内容管理的难度,提升了运营效率;而云数据库则凭借强大的数据操作能力确保了数据的准确性与时效性。 简而言之,云数据库主要服务于开发者,侧重于数据模型的精细化管理;而内容管理应用则更多地面向运营人员,注重内容的快速编辑和使用。内容管理是基于一定的数据模型构建的,两者在功能和目标上虽有差异,却也存在紧密的联系与互补性。 ### 如何转换 cloud:// 为 https 链接 文件字段、图片字段、多媒体字段在处理用户上传的资源时,以及 富文本、Markdown 等字段中上传的图片信息,为了安全起见,会将图片存储为 `cloud://` 这种云文件 ID 的形式,在使用时可能需要进行转换(小程序的 `image` 组件等本身支持云文件 ID 的)。 如果需要转换 cloud:// 为 https 链接,可参考以下两个方法: #### 方法 1: 不更改云存储权限,调用 sdk 实现 使用 sdk 调用 [getTempFileURL](https://docs.cloudbase.net/storage/get-temp-url) 方法获取云存储文件的临时访问链,即将 loud://xxxx 协议的私有地址转换为 http 协议的正常地址。可参考以下方法实现。 注意:cloud://xxx 协议地址错误或者无访问权限等,该方法将不会返回地址,不要随意变更云存储默认权限。 ```js //第一步,引入 Web SDK, import tcb from '@cloudbase/js-sdk'; //第二步,初始化 const app = tcb.init({ env: 'your-env-id', }); //第三步,登录认证,下面非完整代码,需选择登录方式,具体可以参考「快速开始」-「登录与用户案例」 const auth = app.auth({ persistence: 'local', //用户显式退出或更改密码之前的30天一直有效 }); const transformImgUrl = async (fileList) => { const res = await app.getTempFileURL({ fileList, }); const urlList = res.fileList?.map((i) => i.tempFileURL); // 返回fileList 是一个有如下结构的对象数组 // [{ // fileID: 'cloud://webtestjimmy-5328c3.7765-webtestjimmy-5328c3-1251059088/腾讯云.png', // 文件 ID // tempFileURL: '', // 临时文件网络链接 // maxAge: 120 * 60 * 1000, // 有效期 // }] return urlList; }; const urlList = transformImgUrl(['cloud://a/b/c', 'cloud://d/e/f']); console.log(urlList); // ['https://a/b/c', 'https://d/e/f'] ``` ```js //需先使用 wx.cloud.init 初始化,小程序端无需再引入 SDK ,且免鉴权 const transformImgUrl = async (fileList) => { const res = await wx.cloud.getTempFileURL({ fileList, }); const urlList = res.fileList?.map((i) => i.tempFileURL); // 返回fileList 是一个有如下结构的对象数组 // [{ // fileID: 'cloud://webtestjimmy-5328c3.7765-webtestjimmy-5328c3-1251059088/腾讯云.png', // 文件 ID // tempFileURL: '', // 临时文件网络链接 // maxAge: 120 * 60 * 1000, // 有效期 // }] return urlList; }; const urlList = transformImgUrl(['cloud://a/b/c', 'cloud://d/e/f']); console.log(urlList); // ['https://a/b/c', 'https://d/e/f'] ``` ```js const tcb = require('@cloudbase/node-sdk'); const app = tcb.init(); const transformImgUrl = async (fileList) => { const res = await app.getTempFileURL({ fileList, }); const urlList = res.fileList?.map((i) => i.tempFileURL); // 返回fileList 是一个有如下结构的对象数组 // [{ // fileID: 'cloud://webtestjimmy-5328c3.7765-webtestjimmy-5328c3-1251059088/腾讯云.png', // 文件 ID // tempFileURL: '', // 临时文件网络链接 // maxAge: 120 * 60 * 1000, // 有效期 // }] return urlList; }; const urlList = transformImgUrl(['cloud://a/b/c', 'cloud://d/e/f']); console.log(urlList); // ['https://a/b/c', 'https://d/e/f'] ``` #### 方法 2: 设置云存储权限为所有人可读,通过正则转换文件地址 注意:cloud://xxx 协议地址错误或者无访问权限等,该方法转换的地址不可访问。云存储权限设置为所有人可读,存在一定风险,修改权限需谨慎。 ```js const transformImgUrl = (value) => { const regex = /^(cloud):\/\/([0-9\-A-Za-z]+)?\.([0-9\-A-Za-z]+)\/(.*)/; let matched = value.match(regex); if (matched) { const [_, protocol, envid, origin, path] = matched; return protocol === 'cloud' ? `https://${origin}.tcb.qcloud.la/${path}` : ''; } }; ``` #### 富文本内容转换 对于包含图片的富文本内容做转换,可参考以下方案: 内容管理中上传图片存储的图片地址为 cloud 协议地址。如需要自定义处理图片展示,可参考以下方法实现。 - 定义 transformValue 方法,通过正则匹配到需要转换包含图片内容,对图片地址做转换 ```js export const transformValue = async (value, transformImgUrl) => { // 匹配img的正则表达式 const regex = new RegExp(/]*src=\\*"([^"]*?)\\*"/g); // 通过正则获取到图片地址是cloud协议的img const imgList = value?.match(regex) || []; let imgUrl = imgList .map((i) => i.replace(regex, '$1')) .filter((j) => j.includes('cloud://')); if (imgUrl.length) { // 转换图片链接 imgUrl = await transformImgUrl(imgUrl); } let tempValue = value; if (imgList && imgList.length > 0) { // 将得到的http地址设置到图片的src,以便展示 imgList.forEach((img, index) => { const url = img.replace(regex, '$1'); if (imgList[index]) { tempValue = tempValue.replace(new RegExp(url, 'g'), imgUrl[index]); } }); } return tempValue; }; ``` - 调用 transformValue 事件即可获取转换后的富文本值 ## 费用 内容管理应用开通不单独收费,属于云后台默认系统应用。当您开通云开发环境后即可进入云后台使用内容管理,您只需要为您使用的云资源付费,您可以在 [费用中心](https://console.cloud.tencent.com/expense/bill/overview) 查看具体信息。 --- ## 新版本特性 🌟 # 新版本特性 🌟 新版内容管理(CMS) 有以下的新变化: - 🌐 [支持对接外部 MySQL 数据库](#%E6%94%AF%E6%8C%81%E5%AF%B9%E6%8E%A5%E5%A4%96%E9%83%A8-mysql-%E6%95%B0%E6%8D%AE%E5%BA%93) - 🚀 [一键生成应用](#%E4%B8%80%E9%94%AE%E7%94%9F%E6%88%90%E5%BA%94%E7%94%A8) - 🛠️ [无需部署](#%E6%97%A0%E9%9C%80%E9%83%A8%E7%BD%B2) - 📱 [移动端支持](#%E7%A7%BB%E5%8A%A8%E7%AB%AF%E6%94%AF%E6%8C%81) - 🔐 [权限管理](#%E6%9D%83%E9%99%90%E7%AE%A1%E7%90%86) - 💰 [计费调整,无单独的文档数量限制](#%E8%AE%A1%E8%B4%B9%E8%B0%83%E6%95%B4%E6%97%A0%E5%8D%95%E7%8B%AC%E7%9A%84%E6%96%87%E6%A1%A3%E6%95%B0%E9%87%8F%E9%99%90%E5%88%B6) - 📤 [数据导出能力提升](#%E6%95%B0%E6%8D%AE%E5%AF%BC%E5%87%BA%E8%83%BD%E5%8A%9B%E6%8F%90%E5%8D%87) - 📥 [数据导入增强](#%E6%95%B0%E6%8D%AE%E5%AF%BC%E5%85%A5%E5%A2%9E%E5%BC%BA) - ☁️ [数据支持存储在云开发数据集合](#%E6%95%B0%E6%8D%AE%E6%94%AF%E6%8C%81%E5%AD%98%E5%82%A8%E5%9C%A8%E4%BA%91%E5%BC%80%E5%8F%91%E6%95%B0%E6%8D%AE%E9%9B%86%E5%90%88) - 🔍 [数据校验和类型检查](#%E6%95%B0%E6%8D%AE%E6%A0%A1%E9%AA%8C%E5%92%8C%E7%B1%BB%E5%9E%8B%E6%A3%80%E6%9F%A5) - 🧠 [一键 AI 智能分析数据](#%E4%B8%80%E9%94%AE-ai-%E6%99%BA%E8%83%BD%E5%88%86%E6%9E%90%E6%95%B0%E6%8D%AE) - 🛠️ [提供 SDK](#%E6%8F%90%E4%BE%9B-sdk) - 🌐 [提供 HTTP API](#%E6%8F%90%E4%BE%9B-http-api) ## 支持对接外部 MySQL 数据库 支持通过数据模型连接外部 MySQL 数据库,直接对接已有的外部数据库。 ## 一键生成应用 支持一键生成可编辑的管理端应用,采用低代码技术可视化修改和定制开发,使得开发者无需手动编写管理界面,进一步提高开发效率 ## 无需部署 无需在本地安装和维护软件,只需通过 Web 浏览器登录云后台即可访问和使用。 ## 移动端支持 管理界面适配移动端,随时随地进行便捷内容管理。 ## 权限管理 接入云后台统一的 RBAC 用户权限管理系统,可通过角色权限控制账号拥有具体权限 ## 计费调整,无单独的文档数量限制 内容管理为内置于云后台的默认应用,以云环境统一套餐进行计算,不单独计费,详情请查阅云环境计费套餐。如果希望提高规模上限,可以升级环境套餐。如果更高级版本的规模数也不符合需求,可在升级页面联系客服反馈您的需求。 ## 数据导出能力提升 将导出条数限制从 1000 条提升至 10 万行,支持导出特定筛选条件的数据。 ## 数据导入增强 支持导入高达 5 万行的数据 ## 数据支持存储在云开发数据集合 数据集合基于数据模型应用构建,数据模型可以提高开发效率、降低维护成本、增强数据安全性,并拥有强大的数据分析和管理能力 ## 数据校验和类型检查 数据模型可以自动处理数据的校验和类型检查,确保数据的准确性和一致性。这有助于在数据输入、更新和查询过程中避免错误,提高数据质量。 ## 一键 AI 智能分析数据 数据模型可以使用 AI 来对数据进行智能分析。有助于从海量数据中提取有价值的信息,为决策提供有力支持。 ## 提供 SDK 提供了小程序和云函数可用的 SDK,方便开发者快速集成和开发 详请请阅读[SDK 对接](./reference/sdk) 文档 ## 提供 HTTP API 提供了数据模型的 HTTP API 可供多端多语言进行调用,支持例如移动 App、服务器、小游戏等其他语言的软件调用 详请请阅读[HTTP API](./reference/http-api) 文档 --- ## 微信开发者工具 # 微信开发者工具 本文介绍了在微信开发工具中安装 CloudBase CMS 的过程,适用于只管理微信小程序内容数据的情况。开发者工具 1.03.2011272 Nightly 起,支持通过扩展安装 CloudBase CMS。 ## 安装指南 1. 点击 小程序 IDE 下载 ,选择电脑系统对应的版本进行安装 ![](https://main.qcloudimg.com/raw/8595803cd6f03b06340ae5cddb84af0f.png) 2. 创建小程序,输入小程序 AppID,后端服务上勾选”小程序\*云开发“ ![](https://main.qcloudimg.com/raw/4839de902cadc4bebb49b04f9a778086.png) 3. 点击左上角的”小程序云开发“ ![](https://main.qcloudimg.com/raw/e2a2436b5b1e3e8ef6f35c372cac3a23.png) 4. 直接”开通“按钮将创建一个新的腾讯云账号。推荐:”通过腾讯云账号开通”将会绑定已有腾讯云账号 ![](https://main.qcloudimg.com/raw/9b49a856f79857dd43a39e28c10a87d6.jpg) 5. 在工具顶部 Tab 栏中,点击「更多」-「内容管理」 ![](https://res.wx.qq.com/wxdoc/dist/assets/img/cms-intro-1.40b341ef.png) 6. 点击开通,勾选同意协议后,点击确定 ![](https://res.wx.qq.com/wxdoc/dist/assets/img/cms-intro-2.251c9351.png) 7. 开通内容管理需要填写管理员账号,填写账号后,点击「确定」完成 ![](https://res.wx.qq.com/wxdoc/dist/assets/img/cms-intro-3.9b59c531.png) 8. 开通拓展需要一定时间,请耐心等待 9. 完成后,点击「更多」-「内容管理」,即可看到内容管理的入口和相关信息。点击访问地址,即可在弹出的窗口中进行内容管理的相关配置。 ![](https://res.wx.qq.com/wxdoc/dist/assets/img/cms-intro-4.dabb5fa2.png) 10. 新建项目,系统可通过项目进行数据隔离与权限管控 ![](https://main.qcloudimg.com/raw/e70622a84967ff8f507ea1bc7de73b62.png) --- ## 概述 # 概述 :::tip 🚧 内容管理已停止维护 当前模块已停止维护,欢迎使用 [云后台/数据管理](/toolbox/manage-data) ::: ## 内容管理是什么 [内容管理](https://tcb.cloud.tencent.com/cloud-admin/#/management/content-mgr/index) 是云开发内置的开箱即用的内容管理工具。 无需编写代码,用户可从空白开始,或从数据库一键生成一个用户友好的内容管理系统,支持文本、图片、富文本、markdown 等多种字段类型。 数据来源支持云开发云数据库和 MySQL 数据库。 通过简化的内容编辑流程,帮助开发者快速、高效地管理网站、小程序或者其他应用中的内容,同时可通过 SDK 和 HTTP API 来读写数据。 ![](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/cca8e556-cc2f-4ab1-96dd-a15d69963a95.png) ![](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/9ecfdc78-8f61-4827-bc99-cdc9e6465bd4.png) ## 功能特性 | 特性 | 介绍 | | :----------------------- | ----------------------------------------------------------------------------------------------------- | | **免开发** | 根据数据库一键生成内容管理界面,无须编写代码 | | **无需部署** | 在云开发云后台直接开箱即用,无需安装和部署 | | **支持多种数据源** | 支持管理已有的云开发数据,也可以链接外部的 MySQL 数据库 | | **用户友好** | 支持文本、图片、文件、枚举、富文本、markdown 等多种类型内容的可视化编辑,支持表格就地编辑,支持移动端 | | **一键生成管理后台应用** | 支持一键生成可以可视化编辑的管理后台应用,可在内容管理的基础上拓展业务逻辑 | | **权限管理** | 提供更精细的权限管理功能,确保数据安全。 | | **HTTP API 及 SDK** | 提供 HTTP API 及 SDK 接口,便于在应用中读写数据。 | ## 适用场景 ### 适用于需要为小程序或者应用增加一个运营管理后台的业务 内容管理非常适合小程序、Web 网站、移动 App的商品管理、文章编辑和发布、运营活动配置、素材管理等数据和内容管理的场景。使用 CMS 扩展,可以省去手动线上修改数据库数据或者投入人力物力开发管理后台的麻烦,只需要安装之后进行一些简单的配置,就可随时随地使用 CMS 内容管理系统来管理内容。 ### 适用于快速开发内容型的小程序或应用的场景 内容管理还可以用来配小程序、Web 网站、移动 App,提升开发效率。使用内容管理可以解决内容、数据的管理和生产问题,并且省去一部分后端开发工作,可以直接结合SDK 和 HTTP API读写数据进行渲染。可以快速开发博客、企业官网等内容型的网站、小程序应用或移动 App 等 ### 适用于管理已有的数据库 内容管理为数据库增加一个友好的界面方便管理内容,可以连接云开发数据库、外部 MySQL 数据等多种数据来源的数据库 --- ## 旧版cms迁移到模型字段映射 # 旧版cms迁移到模型字段映射 1、理论上说,如果旧版cms字段和数据模型字段二者对应的基础数据类型相同,就可以做数据迁移,然后根据自己的目的来灵活使用;以下表格中的“是否兼容旧数据”表示该类型字段在数据模型中是否可以不需要其他转换直接映射。 2、推荐映射的数据模型子类型主要指迁移时推荐的类型,如果没有历史数据负担,可自行参考设计。如cms的枚举类型,可直接使用数据模型中的枚举类型来替代;http格式的文件、图片、多媒体等资源类型,可直接对应同类型的数据模型资源等。 cms字段 cms字段子类型 基础数据类型 推荐数据模型类型 推荐数据模型子类型 是否兼容旧数据 是否可跨环境迁移 单行字符串 - string 文本 单行文本 ✔️ ✔️ 多行字符串 - string 多行文本 ✔️ ✔️ 数字 - number 数字 - ✔️ ✔️ 布尔值 - boolean 布尔值 - ✔️ ✔️ 枚举 字符串枚举 string 文本 单行文本 ✔️ ✔️ 数字枚举 number 数字 - ✔️ ✔️ 日期 Unix Timestamp 毫秒 number 日期时间 日期 ✔️ ✔️ Unix Timestamp 秒 number 数字 - ✔️ ✔️ Date 对象 - - - ❌ ❌ 时间字符串 string 文本 单行文本 ✔️ ✔️ 日期与时间 Unix Timestamp 毫秒 number 日期时间 日期时间 ✔️ ✔️ Unix Timestamp 秒 number 数字 - ✔️ ✔️ Date 对象 - - - ❌ ❌ 时间字符串 string 文本 单行文本 ✔️ ✔️ 文件-不允许多个 field string 文件 - ✔️ ❌ http string 文本 单行文本 ✔️ ❌ 文件-允许多个 field string[] 数组 文件 ✔️ ❌ http string[] 数组 文本|单行文本 ✔️ ❌ 图片-不允许多个 field string 图片 - ✔️ ❌ http string 文本 单行文本 ✔️ ❌ 图片-允许多个 field string[] 数组 图片 ✔️ ❌ http string[] 数组 文本|单行文本 ✔️ ❌ 多媒体-不允许多个 field string 多媒体 - ✔️ ❌ http string 文本 单行文本 ✔️ ❌ 多媒体-允许多个 field string[] 数组 多媒体 ✔️ ❌ http string[] 数组 文本|单行文本 ✔️ ❌ 邮箱地址 - string 邮箱 - ✔️ ✔️ 电话号码 - string 电话 手机号码/固定电话 ✔️ ✔️ 网址 - string 网址 - ✔️ ✔️ 富文本 - string 富文本 - ✔️ ✔️ Markdown - string Markdown - ✔️ ✔️ 关联 不关联多个 string 关联关系(新) 一对一 ❌ ❌ 关联多个 string 关联关系(新) 一对多 ❌ ❌ 数组 - string[] 数组 文本|单行文本 ✔️ ✔️ Json对象 - string 对象 - ✔️ ✔️ --- ## 迁移指南 # 迁移指南 CMS 推出以来,深受用户欢迎,我们基于用户的反馈进行了升级和优化,推出了新版的内容管理功能。 新版内容管理旨在解决旧版系统在性能、功能和用户体验方面的局限性。它提供了更加强大和灵活的数据连接能力,支持对接外部的数据源,例如 MySQL,同时支持强大的管理系统页面自定义开发能力,可以解决用户不仅仅需要一个内容管理,而是一个管理后台的需求。 ## 新版本变化 新版内容管理(CMS) 有以下的新变化: - 🌐 [支持对接外部 MySQL 数据库](/cms/features#%E6%94%AF%E6%8C%81%E5%AF%B9%E6%8E%A5%E5%A4%96%E9%83%A8-mysql-%E6%95%B0%E6%8D%AE%E5%BA%93) - 🚀 [一键生成应用](/cms/features#%E4%B8%80%E9%94%AE%E7%94%9F%E6%88%90%E5%BA%94%E7%94%A8) - 🛠️ [无需部署](/cms/features#%E6%97%A0%E9%9C%80%E9%83%A8%E7%BD%B2) - 📱 [移动端支持](/cms/features#%E7%A7%BB%E5%8A%A8%E7%AB%AF%E6%94%AF%E6%8C%81) - 🔐 [权限管理](/cms/features#%E6%9D%83%E9%99%90%E7%AE%A1%E7%90%86) - 💰 [计费调整,无单独的文档数量限制](/cms/features#%E8%AE%A1%E8%B4%B9%E8%B0%83%E6%95%B4%E6%97%A0%E5%8D%95%E7%8B%AC%E7%9A%84%E6%96%87%E6%A1%A3%E6%95%B0%E9%87%8F%E9%99%90%E5%88%B6) - 📤 [数据导出能力提升](/cms/features#%E6%95%B0%E6%8D%AE%E5%AF%BC%E5%87%BA%E8%83%BD%E5%8A%9B%E6%8F%90%E5%8D%87) - 📥 [数据导入增强](/cms/features#%E6%95%B0%E6%8D%AE%E5%AF%BC%E5%85%A5%E5%A2%9E%E5%BC%BA) - ☁️ [数据支持存储在云开发数据集合](/cms/features#%E6%95%B0%E6%8D%AE%E6%94%AF%E6%8C%81%E5%AD%98%E5%82%A8%E5%9C%A8%E4%BA%91%E5%BC%80%E5%8F%91%E6%95%B0%E6%8D%AE%E9%9B%86%E5%90%88) - 🔍 [数据校验和类型检查](/cms/features#%E6%95%B0%E6%8D%AE%E6%A0%A1%E9%AA%8C%E5%92%8C%E7%B1%BB%E5%9E%8B%E6%A3%80%E6%9F%A5) - 🧠 [一键 AI 智能分析数据](/cms/features#%E4%B8%80%E9%94%AE-ai-%E6%99%BA%E8%83%BD%E5%88%86%E6%9E%90%E6%95%B0%E6%8D%AE) - 🛠️ [提供 SDK](/cms/features#%E6%8F%90%E4%BE%9B-sdk) - 🌐 [提供 HTTP API](/cms/features#%E6%8F%90%E4%BE%9B-http-api) ## 迁移步骤 ### 1. 进入新版内容管理 可通过 [微信云开发云后台-内容管理](https://tcb.cloud.tencent.com/cloud-admin/#/management/content-mgr/index) 来通过管理员身份登录内容管理。 ![](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/bce416a5-2531-45c1-8abf-dc57e7d54122.png) ### 2. 选择“使用现有 CMS 创建” ![](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/44afc114-29e2-4755-bf05-d8c8d317484d.png) ### 3. 选择项目和 CMS 模型进行导入 ![](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/c87f1058-48ed-4fd9-89e3-2cb4eae97883.png) 导入的过程可对模型的名称进行修改,也可以确认和修改字段 ![](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/e1d394e7-7c35-48cb-9946-b8bec14c7e0b.png) ### 4. 模型导入成功后即可进行模型的管理和内容的管理 ![](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/c2c6e90f-03b6-4b8e-98ca-cf87a83484ad.png) ## 常见问题与解决方案 ### 迁移过程中是否会迁移数据 当前的迁移工具只支持导入模型的字段配置,不支持导入数据,可以基于数据库导入,或者在内容管理中选择数据导入,对照数据导入模板来准备导入的表格数据,然后再分别导入。 ### 关联数据下拉选择只展示_id 如何处理? 关联数据展示时,默认会显示被关联的模型的主显示字段,如果希望显示用户可读的字段,例如标题等,可以在被关联的模型的字段设置中,找到要展示的字段进行编辑,将它设置为主显示字段即可。 ### 新版 CMS 的权限管理如何设置? 参考官方文档中的权限管理指南,根据组织的需求设置相应的权限。 ### 在 CMS 云模板中看不到原来的 CMS 项目和模型如何处理? 这种情况可能是使用了较旧的 CMS 版本,可以在内容管理中选择从 CMS 导入,选择对应的项目和模型即可迁移到新版本的内容管理 ## 后续支持与资源 如果在导入过程中遇到问题,可加入云开发交流群进行反馈和交流 [加入云开发交流群](https://cloud.tencent.com/apply/p/4d7etmgxz0j) --- ## 基本概念 # 基本概念 内容管理可以帮助你处理复杂的场景,在这种情况下,我们引入了一些抽象的、通用的概念来表述系统的能力。为了更好地理解、使用,我们建议你在使用前了解内容管理(CMS)中的一些概念。 | 概念 | 定义 | | -------- | ---------------------------------------------------------------------------- | | 数据模型 | 对内容文档的结构定义 | | 内容表 | 由一类内容文档组成的数据集,表现为表格的形式,表格中的每一列代表一个内容文档 | | Id | 通常表示一件事物的唯一标志,如公民的身份证号 | | 标识 | 通过程序和代码访问时,会依据标识,例如模型标识,字段标识,建议用英文 | | 字段名称 | 字段在界面中的友好可读的显示名称,一般建议用中文 | --- ## HTTP API # HTTP API 新版本内容管理是工作在数据模型之上的,通过数据模型 HTTP API 提供了完整的 API 接口。 支持移动应用、web 应用、游戏开发、IoT 或者开发者自有服务调用,支持多种语言。 ## 使用指南 请查阅 [数据模型 OpenAPI 接入指引](/http-api/model/数据模型-openapi) 可参考接入指引进行接入,也可以查阅对应的接口返回的错误码及其含义。 ### 数据模型操作方法参考 请查阅 [数据模型提供的操作方法](/http-api/model/数据模型的方法) ### 在线调试 数据模型 HTTP API 支持在线调试,可参考 [接口在线调试指南](/http-api/basic/online-api-call) 使用。 --- ## 工作原理 # 工作原理 ![](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/37035ab2-53cd-4a2d-8efb-bda94013ec43.png) --- ## SDK 对接 # SDK 对接 新版本内容管理是工作在数据模型之上的,通过数据模型 SDK 提供了便捷的操作方法。 支持在 web 、小程序和云函数及 Node 服务端便捷使用。 ## 初始化 SDK 参考 [引入和初始化数据模型 SDK](/model/init-sdk) ## 数据模型命名空间 ### `models` 在初始化 SDK 之后,会自动在 `models` 上挂载针对当前云开发环境下的数据模型的操作方法 通过 `models.` 可以访问某个模型的操作方法 例如: ```js // const wxCloud = client.init(wx.cloud); // const models = wxCloud.models; models..create() // 创建单条数据 models..createMany() // 创建多条数据 models..update() // 更新单条数据 models..updateMany() // 更新多条数据 models..delete() // 删除单条数据 models..deleteMany() // 删除多条数据 models..get() // 查询单条数据 models..list() // 查询多条数据 models.runSQL() // MySQL 类型的数据模型支持数据库参数化查询语句,仅支持服务端调用 models.runSQLRaw() // MySQL 类型的数据模型支持数据库原始查询语句,仅支持服务端调用 ``` 数据模型的方法可以在云函数中和小程序中均可使用 - 在小程序端运行时,默认是当前登录用户的身份调用 - 在云函数中运行时,默认是管理员权限,后续会支持选择以客户端小程序用户身份调用 ### 数据模型操作方法参考 详情请参考 [模型查询方法](/model/sdk-reference/model#模型查询方法) --- ## 进入内容管理 # 进入内容管理 本文主要面向首次使用 内容管理 的新用户,介绍了使用 内容管理 来 管理数据的主要过程 可通过 [微信云开发云后台-内容管理](https://tcb.cloud.tencent.com/cloud-admin/#/management/content-mgr/index) 来通过管理员身份登录内容管理。 在开始管理内容数据前,我们需要先拥有[数据模型](https://docs.cloudbase.net/model/introduce)。内容管理中的数据 根据 [数据模型](https://docs.cloudbase.net/model/introduce) 中的 表、字段进行组织,如果已经存在数据模型,则我的内容列表中会展示。 若内容列表为空 或 需要新增内容表,我们当前支持 从空白创建 、从现在 CMS 项目导入、从数据库创建和从模板创建等多种方式: ![](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/bce416a5-2531-45c1-8abf-dc57e7d54122.png) --- ## 从现有 CMS 创建 # 从现有 CMS 创建 详细流程请参考[迁移指南](../migrating/from-legacy-cms.md) --- ## 从数据库创建 # 从数据库创建 如果您需要使用关系型数据库,也可以使用自建的 MySQL 数据库创建模型。 自建 MySQL 数据库,不限制使用的是腾讯云或其他云服务商,或自行使用的服务器构建的 MySQL 数据库,只要通过公网可访问的数据库,均可以对接。 在使用自建的 MySQL 数据库时,需要选择配置数据库连接,用于对接自建数据库。连接配置包括了数据库的连接地址(域名或 IP )、端口、库名、用户名、密码及可选的连接参数信息。 ## 1. 创建模型 选择从自有 MySQL 数据库导入。 选择已有数据库连接信息,或者配置新的数据库连接信息。 ![image](https://qcloudimg.tencent-cloud.cn/raw/6a292fcaf7b7df1eb8739264ad29195f.png) 选择数据库连接信息后,后台将读取所选的数据库表。 进一步选择需要将哪个表导入到模型中。 系统会自动根据已有数据做字段映射,您也可以根据实际情况进行调整。 ![image](https://qcloudimg.tencent-cloud.cn/raw/8da269c955f856a6ee50a2d1841246d3.png) 另外,系统会自动生成若干字段(数据标识 (\_id),创建时间 (createdAt),更新时间 (updatedAt),所有人 (owner),创建人 (createBy),修改人 (updateBy),记录创建者 (\_openid)),并更新数据库表。 ![image.png](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/6ecb6c78-3d7c-427c-b442-3ed09b72b2ff.png) 导入成功后,可以在内容管理中看到原有的数据 ![image.png](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/16717ff1-7f36-4156-9963-583c2379d900.png) 在数据表中写入的数据均会同步到集合中,同时集合中写入的数据也会在数据表中展示出来。 ## 2. 写入内容 在数据表中编辑数据,执行增删改查,导入/导出,筛选/排序等操作 ![image.png](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/9579143a-b8e8-486e-847e-3aeb05be069a.png) --- ## 从空白开始 # 从空白开始 ## 云数据库 ### 1.创建数据模型 选择从空白创建并使用云数据库。 ![image](https://qcloudimg.tencent-cloud.cn/raw/d66dc4716964d229f08c396039d1a4e8.png) 填写模型名称,模型标识,并为您的模型增添字段。 字段说明请参考[云数据库支持的字段类型](/cms/usage/schema-field#云数据库支持的字段类型) ![image](https://qcloudimg.tencent-cloud.cn/raw/4639bdc7247e39f1471306cba80c0343.png) 系统会自动生成若干字段(数据标识 (\_id),创建时间 (createdAt),更新时间 (updatedAt),所有人 (owner),创建人 (createBy),修改人 (updateBy),记录创建者 (\_openid)),您的字段标识不应与此重复。 ![image](https://qcloudimg.tencent-cloud.cn/raw/4b7204cbed202c0bd397ef1ed962d022.png) ### 2.写入内容 返回内容管理应用中,在数据表中编辑数据,执行增删改查,导入/导出,筛选/排序等操作。 ![image](https://qcloudimg.tencent-cloud.cn/raw/7f49a059e6d0cf53cfe935035ba84db8.png) ## MySQL 数据库 ### 1. 创建数据模型 选择从空白创建并使用 MySQL 数据库。 ![image](https://qcloudimg.tencent-cloud.cn/raw/1817be7936de31a38ac106b11549a837.png) 填写模型名称,模型标识,并为您的模型增添字段。 ![image](https://qcloudimg.tencent-cloud.cn/raw/4639bdc7247e39f1471306cba80c0343.png) 字段说明请参考[MySQL-数据库支持的字段类型](/cms/usage/schema-field#mysql-数据库支持的字段类型) 系统会自动生成若干字段(数据标识 (\_id),创建时间 (createdAt),更新时间 (updatedAt),所有人 (owner),创建人 (createBy),修改人 (updateBy),记录创建者 (\_openid)),您的字段标识不应与此重复。 ![image](https://qcloudimg.tencent-cloud.cn/raw/4b7204cbed202c0bd397ef1ed962d022.png) | ### 2. 写入内容 返回内容管理应用中,在数据表中编辑数据,执行增删改查,导入/导出,筛选/排序等操作。 ![image](https://qcloudimg.tencent-cloud.cn/raw/93db25de033087c34fbe838b2bbad244.png) --- ## 从模板创建 # 从模板创建 在[微信云开发云后台-数据模型](https://tcb.cloud.tencent.com/cloud-admin?_tcbProviderId=mp#/management/data-model/)中,用户可以使用已有的模板,快速批量创建适用于不同业务场景的数据模型,减少因手动创建产生的错误,保证数据一致性。 ## 模板列表 目前提供了五套模板供用户使用 - [电商](https://tcb.cloud.tencent.com/cloud-admin?_tcbProviderId=mp#/management/data-model?showType=create&createType=templete&templete=online_shopping_tpl) - [项目管理](https://tcb.cloud.tencent.com/cloud-admin?_tcbProviderId=mp#/management/data-model?showType=create&createType=templete&templete=project_mgmt_tpl) - [进销存](https://tcb.cloud.tencent.com/cloud-admin?_tcbProviderId=mp#/management/data-model?showType=create&createType=templete&templete=inventory_mgmt_tpl) - [会员管理](https://tcb.cloud.tencent.com/cloud-admin?_tcbProviderId=mp#/management/data-model?showType=create&createType=templete&templete=mem_mgmt_tpl) - [博客](https://tcb.cloud.tencent.com/cloud-admin?_tcbProviderId=mp#/management/data-model?showType=create&createType=templete&templete=blog_tpl) 电商模板内容列表示例: ![](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/bed38f84-0771-447b-85d3-32aeeff6d84d.png) ## 使用流程 ### 1.创建模型 创建模型时,选择从模板创建。可将模型写入云开发 NoSQL 数据库、云开发 MySQL 数据库或自有 MySQL 数据库。 ![image](https://qcloudimg.tencent-cloud.cn/raw/def2c6abb237af1e40dec052f9f5a27f.png) :::tip 温馨提示 由于云开发 NoSQL 数据库不支持多对多关联关系,模板中设计多对多关联的字段将将不会写入模型中。 ::: 选择模板,会帮用户生成一系列数据模型,可根据需要添加或修改字段。 ![image](https://qcloudimg.tencent-cloud.cn/raw/13b536c60209b00105f1f5c2b7b2d59d.png) 完成后即可看到模型已成功生成。 ![image](https://qcloudimg.tencent-cloud.cn/raw/9a001b4e7c7122a55f585f8faf4b0bd3.png) ### 2.写入内容 在数据表中编辑数据,执行增删改查,导入/导出,筛选/排序等操作 ![](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/9579143a-b8e8-486e-847e-3aeb05be069a.png) --- ## 生成自定义应用 # 生成自定义应用 内容管理是云开发用于管理、创建、编辑和发布内容的基础组件,若内容管理提供的功能无法满足您的需求,希望自定义页面内容,或在自主开发应用中使用内容数据,则可基于低代码工具能力生成运营系统内的应用,通过拖拽组件生成前端 UI 定制各类管理端应用。 ![](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/9ecfdc78-8f61-4827-bc99-cdc9e6465bd4.png) [微搭低代码](https://cloud.tencent.com/document/product/1301/67121) 提供模板、编辑器、组件/区块等能力帮助开发者连接内容数据、快速构建应用: ## 数据模型选择 从已有的数据模型中选中应用需要使用的内容: ![](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/2c05d608-423a-4a90-bfaf-20a8966dff3c.png) ## 场景配置 根据实际应用使用场景配置页面基础能力、布局样式: ![](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/28735a3a-5308-40f8-b059-14b7ed7baf08.png) ## 应用编辑 进入编辑器进行使用组件/区块进行页面可视化配置,同时支持代码编辑、主题设计、多端设计、APIs 数据连接外部等能力: 更多使用指南请查阅[微搭低代码产品文档](https://cloud.tencent.com/document/product/1301/57913) 。 ![](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/da8f4881-da7e-4516-accc-59521b8ec258.png) --- ## 内容管理器 # 内容管理器 内容管理器在选中具体内容表后可进行使用,是内容管理应用的核心组件。 ## 列表切换 点击左上角列表进行列表切换 ![](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/07361ee0-f765-4f28-81fd-7da88b71869e.png) ## 新增内容 点击列表中“添加一行”。填写该表单,输入新内容相关信息。点击提交。 新增内容后,你可以返回内容管理应用中该列表查看新增的内容,确保数据已经正确保存。 ![](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/3e85f12a-fcb4-4818-a293-08fa9ae77d6b.png) ## 修改内容 选中某条数据,并点击操作中“编辑”按钮进行单条数据修改。修改表单,输入内容更新信息。点击提交。 ## 删除内容 选中某条数据,并点击操作中“删除”按钮进行单条数据删除,需要进行二次确认。 ![](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/f44b9c2c-5cb6-4ba4-9b23-ab38f1f27a55.png) 同时勾选多条数据,并点击表头的“删除数据”按钮,进行多条数据的疲劳删除,需要进行二次确认。 ## 列管理 点击“列管理”按钮,在下拉弹窗中进行字段的隐藏或取消隐藏设置。 ![](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/5d06b33f-f365-4c20-9f95-b7ae725e6fc7.png) ## 筛选 点击“筛选”按钮,通过选取表字段,并进行逻辑关系配置进行表内数据筛选。 ![](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/a858becf-4972-4baa-87aa-17fb1ce325f3.png) ## 排序 点击排序按钮,通过选择字段,并配置升序/降序规则进行排列。可同时选择多个字段进行组合排序。 ![](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/f47603cb-ec15-49c8-b8be-46b15d33e5a6.png) ## 导出数据 点击 导出 按钮,可以进行数据的导出,导出数据范围支持 10 万行,可选择全部数据、筛选后的数据或者当前页面选中的数据。 ![](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/1bc8ae3b-112f-4b84-b1ea-a504ca9af272.png) ## 导入数据 点击 导入 按钮,可以进行数据的导入,可下载导入数据的模板,在模板的表格中进行数据的批量管理,然后上传。 导入数据支持多种模式,例如仅新增及新增或更新。 ![](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/70b053ed-7df1-4546-a5d7-d48755a7b72c.png) --- ## 权限设置 # 权限设置 内容管理应用支持根据角色设置 查看及编辑 权限,支持管理到具体的某一行、某一列。 ![](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/b16fe2f3-168b-41b9-a79a-036882b02bb2.png) 因为内容管理应用中内容基于数据模型应用中模型进行维护,所以数据模型与管理内容权限统一,则您只需设置数据模型应用权限即可设置内容管理应用权限。 ![](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/5130718a-9d3e-4973-a209-f371ebca88b5.png) 具体操作指南见[用户权限文档](https://cloud.tencent.com/document/product/1301/82060) --- ## RESTful API # RESTful API CloudBase CMS 2.3.0 版本起,提供了通过 RESTful API 访问内容集合数据的能力。 ## 开启 RESTful API 默认情况下,API 访问为关闭状态,此时无法使用 RESTful API 功能。你需要在项目设置中启用 API 访问功能,并设置访问路径后,才可以通过完整的访问路径访问 RESTful API ![](https://main.qcloudimg.com/raw/0be20df1a8549f70ae14e182c8f3075c.png) ### 访问权限 默认情况下,RESTful API 无法访问任何数据,你需要设置允许**访问/修改**的内容: - 允许访问:能通过 RESTful API 读取内容 - 允许修改:能通过 RESTful API 创建、更新内容 - 允许删除:能通过 RESTful API 删除内容 ![](https://main.qcloudimg.com/raw/2e46f4a2f392a3f5db838f47b08ba197.png) ## 请求路径 CloudBase CMS 的 RESTful API 请求路径由三部分组成:部署路径 + API 版本路径 + 服务路径。如 CMS 服务部署路径(下方的域名为示例,真实域名请查看您的 [**HTTP 访问服务默认域名**](https://tcb.cloud.tencent.com/dev#/env/http-access)) ``` https://xxxx.tcloudbase.com/api/ ``` API 版本路径 ``` /v1.0 ``` 服务路径,`collectionName` 为数据库集合名 ``` /{collectionName} ``` 则获取数据库名为 `goods` 的文档列表的请求路径为 ```Bash GET https://xxx.tcloudbase.com/api/v1.0/goods ``` ## 注意事项 1. **所有 POST 请求的 body 均应为 `application/json` 类型,请勿使用其他的类型** 2. 查询数据时,默认最多一次返回 100 条数据 3. **请求时传入的参数会覆盖默认的行为表现**,如指定了返回结果要携带某个字段,但是在模型定义中此字段在 API 返回值中为隐藏的,遵循以上原则,则返回数据时,此字段会存在 4. CMS 中默认会将上传的图片、文件存储在云存储中,并在数据库中存储 `cloudId` 形式的访问链接,使用 RESTful API 获取数据时,返回结果中的 `cloudId` 会被转换成 `HTTP` 链接。自动转换仅针对直接记录的 `cloudId`,关联文档中的 `cloudId` 不会处理。 5. 使用 RESTful API 获取数据时,返回结果中的关联字段会被转换为完整的关联文档的值,如当一个**商品内容模型**中关联了**标签内容模型(tag)**,数据库底层存储如下: ```Bash { "_createTime": 1603183501849, "_id": "112557505f8ea38e001e1fc210bd51ed", "_updateTime": 1604541130908, "name": "苹果", "price": 6299, "stock": 100000, "tags": [ "b8df3bd65f681d43002b894d0bdce7ac" ] } ``` 则返回的结果为: ```Bash { "_createTime": 1603183501849, "_id": "112557505f8ea38e001e1fc210bd51ed", "_updateTime": 1604541130908, "name": "苹果", "price": 6299, "stock": 100000, "tags": [ { "_id": "b8df3bd65f681d43002b894d0bdce7ac", "_createTime": 1603183501849, "_updateTime": 1604541130908, "name": "水果", "count": 10 } ] } ``` ## 公共参数 查询操作时,可以在 URL 中添加以下的 Query 参数 | 字段 | 类型 | 必填 | 说明 | | ------ | ------ | ---- | ------------------------------------------------------------------------------ | | limit | String | 否 | 查询返回的文档数量,最大值 1000 | | skip | String | 否 | 查询偏移的文档数量 | | fields | String | 否 | JSON 对象字符串,例:`{ key1: 1, key2: 0 }`,表示取 key1 字段,丢弃 key2 字段 | | sort | String | 否 | JSON 对象字符串,例:`{ key1: 1, key2: -1 }`,表示按 key1 升序,key2 降序 排序 | 如: ```Bash GET /{collectionName}/?limit=10&skip=0&fields={"name":1}&sort={"name":1} ``` ## 获取文档列表 根据简单的排序、分组条件,获取某内容集合的文档数据 ### 请求路径 ``` GET /{collectionName}/?limit={limit}&skip={skip}&fields={fields}&sort={sort} ``` ### 响应体 | 字段 | 类型 | 说明 | | --------- | ------ | -------------------- | | requestId | String | 请求 ID | | data | Object | 返回结果 | | code | String | 发生错误时的错误码 | | message | String | 发生错误时的错误信息 | | total | Number | 文档总数量 | 响应示例 ```JSON { "data": [ { "_id": "ecdacfc05f3f28a800000bf51126de2f", "name": "test", "arr": ["sss", "sss", "ssss"], "markdown": "markdown 文本", "textarea": "ssssssssssssssssssssssssssssss", "_createTime": 1597974695982, "_updateTime": 1597974695982 } ], "offset": 0, "limit": 10, "requestId": "1742eb3145c_11", "total": 1 } ``` ## 查询文档列表 获取符合查询条件的文档列表 ### 请求路径 ```Bash POST /{collectionName}/find?limit={limit}&skip={skip}&fields={fields}&sort={sort} ``` ### 请求体 如下所示,`query` 为查询条件, 并支持使用[Query Command](#query-command) ```JSON { "query": { "price": { "$ge": 100 } } } ``` ### 响应 ```JSON { "data": [ { "_id": "ecdacfc05f3f28a800000bf51126de2f", "name": "test", "arr": ["sss", "sss", "ssss"], "markdown": "markdown 文本", "textarea": "ssssssssssssssssssssssssssssss", "_createTime": 1597974695982, "_updateTime": 1597974695982 } ], "requestId": "1742eb3145c_11", "total": 1, "offset": 0, "limit": 10 } ``` ## 获取单个文档 获取指定 Id 的文档 ### 请求路径 ``` GET /{collectionName}/{docId} ``` ### 参数说明 | 参数 | 类型 | 是否必填 | 说明 | | ----- | ------ | -------- | ----------- | | docId | String | 是 | 内容文档 Id | ### 响应 ```JSON { "data": { "_id": "ecdacfc05f3f28a800000bf51126de2f", "name": "test", "arr": ["sss", "sss", "ssss"], "markdown": "markdown 文本", "textarea": "ssssssssssssssssssssssssssssss", "_createTime": 1597974695982, "_updateTime": 1597974695982 }, "requestId": "175d6218c00_6" } ``` ## 创建新的文档 创建新的内容文档 ### 请求路径 ``` POST /{collectionName} ``` ### 请求体 请求体如下所示,`data` 为由新建文档组成的数组,支持一次创建多个文档 ```JSON { "data": [ { "name": "商品名称", "price": 100 } ] } ``` ### 响应 ```JSON { "id": "b5416b755f476d450088360c0054b6fb", "requestId": "1742f02d897_42" } ``` ## 更新单个文档 更新文档的内容,更新操作时,文档的最终结果为传入的 `data` 与现有文档内容的合并值,即同名字段替换原值。 ### 请求路径 `docId` 为需要更新的文档 ``` PATCH /{collectionName}/{docId} ``` ### 请求体 请求体如下所示,`data` 为需要更新的内容,并且支持使用 [Update Command](#update-command) ```JSON { "data": { "name": "商品名称", "price": 100 } } ``` ### 响应 ```JSON { "updated": 1, "requestId": "1742ef4477b_12" } ``` ## 批量更新文档 批量更新符合查询条件的数据为指定的内容 ### 请求路径 ``` PATCH /{collectionName}/ ``` ### 请求体 `query` 为查询条件,`data` 为更新的内容,如下面的示例,将 `name` 为 `oldName` 所有的内容, 更新`name`为 `newName`,同时,`query` 也支持 Query Command ```JSON { "query": { "name": "oldName" }, "data": { "name": "newName" } } ``` ### 响应 | 字段 | 类型 | 说明 | | --------- | ------ | ------------------------------------------- | | updated | Number | 更新成功的文档数量 | | matched | Number | 符合条件的文档数量 | | upsert_id | String | 替换更新 插入新 doc 时存在,其余情况为 null | ```Bash { "requestId": "2a3ec45e223a4", "updated": 1, "matched": 1, "upsert_id": null } ``` ## 替换单个文档 替换指定的文档为新的内容,替换操作只支持对单个文档进行。 ### 请求路径 `docId` 为需要替换的文档 ```JSON PUT /{collectionName}/{docId} ``` ### 请求体 请求体如下所示,`data` 为需要更新的内容 ```JSON { "data": { "name": "商品名称", "price": 100 } } ``` ### 响应 ```JSON { "updated": 1, "upsertedId": null, "requestId": "175d648919d_e" } ``` ## 删除单个文档 删除某个项目下某内容类型的指定文档 #### 请求路径 `docId` 为需要删除的文档的 `_id` ``` DELETE /{collectionName}/{docId} ``` #### 响应 ```JSON { "deleted": 1, "requestId": "175d649a89f_a" } ``` ## 批量删除文档 批量删除符合查询条件的内容文档 ### 请求路径 ``` DELETE /{collectionName}/ ``` ### 请求体 如下所示,`query` 为查询条件, 并支持使用[Query Command](#query-command) ```JSON { "query": { "price": { "$gt": 100 } } } ``` ### 响应 | 字段 | 类型 | 说明 | | ------- | ------ | ---------------- | | deleted | Number | 删除成功的文档数 | ```Bash { "requestId": "23f416d4f8722", "deleted": 1 } ``` ## Query Command :::tip 下面仅列出了部分 Command,全部 Command 请查看[数据库 SDK 文档](https://developers.weixin.qq.com/miniprogram/dev/wxcloud/reference-sdk-api/database/Command.html) ::: ### `$eq` 表示字段等于某个值。 语法:`{ : { $eq: }}` ```JavaScript { "data": { "name": { "$eq": "cms" } } } ``` ### `$ne` 表示字段等于某个值。 语法:`{ : { $ne: }}` ```JavaScript { "data": { "name": { "$ne": "luke" } } } ``` ### `$gt` 表示字段大于某个值。 语法:`{ : { $gt: }}` ```JavaScript { "data": { "age": { "$gt": 18 } } } ``` ### `$gte` 表示字段大于或等于某个值。 语法:`{ : { $gte: }}` ```JavaScript { "data": { "age": { "$gte": 18 } } } ``` ### `$lt` 表示字段小于某个值。 语法:`{ : { $lt: }}` ```JavaScript { "data": { "age": { "$lt": 18 } } } ``` ### `$lte` 表示字段小于或等于某个值。 语法:`{ : { $lte: }}` ```JavaScript { "data": { "age": { "$lte": 18 } } } ``` ### `$in` 字段值在给定的数组中。 语法:`{ : { $in: [, , ... ] }}` ```JavaScript { "data": { "category": { "$in": ["science", "computer"] } } } ``` ### `$nin` 字段值不在给定的数组中。 语法:`{ : { $nin: [, , ... ] }}` ```JavaScript { "data": { "category": { "$nin": ["science", "computer"] } } } ``` ### `$and` 表示需同时满足指定的两个或以上的条件。 语法:`{ $and: [{ }, { } , ... , { }] }` ```JavaScript { "data": { "$and": [ { "price": { "$lt": 200 } }, { "price": { "$gt": 100 } } ] } } ``` ### `$or` 表示需满足所有指定条件中的至少一个。 语法:`{ $or: [{ }, { }, ... , { }] }` ```JavaScript { "data": { "$or": [ { "price": { "$lt": 200 } }, { "price": { "$gt": 100 } } ] } } ``` ### `$nor` 表示逻辑 "都不" 的关系,表示需不满足指定的所有条件。 语法:`{ $nor: [{ }, { }, ... { }] }` ```JavaScript { "data": { "$nor": [ { "price": { "$lt": 200 } }, { "price": { "$gt": 100 } } ] } } ``` ## Update Command :::tip 下面仅列出了部分 Command,全部 Command 请查看[数据库 SDK 文档](https://developers.weixin.qq.com/miniprogram/dev/wxcloud/reference-sdk-api/database/Command.html) ::: ### `$set` 用于设定字段等于指定值,支持以点操作符表示法访问数组的元素和访问嵌入文档的字段 语法:`{ $set: { : , ... } }` ```JSON { "data": { "$set": { "text": "a", "style.color": "red", } } } ``` ### `$inc` 用于指示字段自增某个值,这是个原子操作 语法:`{ $inc: { : : , ... }}` ```JSON { "data": { "$inc": { "price": 1000 } } } ``` ### `$mul` 用于指示字段自乘某个值 语法:`{ $mul: { : }}` ```JSON { "data": { "$mul": { "price": 1.5 } } } ``` ### `$unset` 用于表示删除某个字段 语法:`{ $unset: { : "" }}` ```JSON { "data": { "$unset": { "rating": "" } } } ``` ### `$push` 向数组尾部追加元素,支持传入单个元素或数组 语法:`{ $push: { : }}` ```JSON { "data": { "$push": { "tags": { "$each": ["tag1", "tag2", "tag3"] } } } } ``` ### `$pop` 删除数组尾部元素 语法:`{ $pop: { : }}` > 1 表示从数组尾部剔除  元素,-1 表示从数组头部剔除元素 ```JSON { "data": { "$pop": { "tags": 1 } } } ``` ## 点操作符 云开发数据库支持**点操作符表示法**访问数组的元素、嵌套文档的字段 ### 数组 ```JSON "." ``` 如下面的数组,可以使用 `contribs.2` 获取 `colors` 数组的第三个元素 `C` ```JSON { colors: [ "A", "B", "C" ] } ``` ### 嵌套文档 ```JSON "." ``` 如下面的文档,可以使用 `address.city` 获取 `city` 的值,使用 `contact.phone.number` 获取 `number` 的值 ```JSON { address: { city: "Sans" }, contact: { phone: { type: "cell", number: "111-222-3333" } } } ``` --- ## 模型字段说明 # 模型字段说明 ## 字段通用属性 - 字段名称:在内容管理界面上显示的友好的文本名称 - 字段标识:对应数据库中的字段名,通过 SDK 或者 HTTP API 读写时会依据字段标识 - 字段描述:在内容管理界面上展示的描述信息 - 默认值:在内容管理界面中,如果用户不填写内容,默认会取默认值 - 是否必填:限制某个字段是否必须填写,不填写则会报错 - 是否唯一:开启后,该字段内容在一个内容表中只能存在一份 - 是否为主显示列:在被其他内容表关联时,显示的列表中默认会依据主显示列的字段来显示,默认是根据 \_id 来作为主显示列 ## 支持的字段类型 目前支持以下类型:文本、布尔值、数字、数组、对象、JSON、邮箱、电话、网址、图片、富文本、Markdown、日期时间、枚举、地理位置、文件、自动编号、地区、关联关系(新) | 类型 | 说明 | 示例 | 备注 | | :----------- | ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | | 文本 | 用于存储字符串类型的文本信息,支持单行文本和多行文本。 | `"Hello, World!"` | 最长可存储 4000 字节,若需存储更长内容,可使用富文本字段 | | 布尔值 | 用于存储真或假的逻辑值。 | `true`/ `false` | - | | 数字 | 用于存储整数或浮点数 | `42` / `3.14` | 整数位加小数位不超过 16 位,小数计算可能有精度缺失 | | 数组 | 用于存储一组相同类型的元素。 | `[1, 2, 3]` | - | | 对象 | 用于存储键值对的集合,支持类型嵌套。 | `{"name": "Alice", "age": 30}` | - | | Json | 用于存储 JSON 格式的数据。 | `{"key": "value"}` | 适用于复杂的数据结构或动态属性 | | 邮箱 | 用于存储电子邮件地址。 | `"john@example.com"` | - | | 电话 | 用于存储电话号码,支持手机号码和固定电话。 | `"18888888888"` | 手机号码校验规则为符合大陆手机号规范的 11 位字符串,固定电话校验规则为有 0 开头的 2,3 位区号或者没有区号的 7-8 位字符串 | | 网址 | 用于存储网页链接。 | `"https://www.example.com"` | - | | 图片 | 用于存储图片文件的链接或路径。 | `"cloud://xxx.com/path/to/image.jpg"` / `"https://foo.bar/example.png"` | 单张图片最大 10M | | 多媒体 | 用于存储音频或视频文件的链接或路径。 | `"cloud://xxx.com/path/to/a.mp4"` / `"https://foo.bar/example.mp4"` | 单文件最大 500M | | 富文本 | 用于存储格式化的文本内容,如 HTML。 | `This is a paragraph` | 最大长度 262144 字节 | | Markdown | 用于存储 Markdown 格式的文本内容。 | `"# This is a heading"` | 可使用 Markdown 编辑器编辑内容,并支持实时预览 | | 日期时间 | 用于存储日期和时间信息。 | `"1645977600000"` | 时间戳,单位 ms | | 枚举 | 用于存储预定义的值集合中的值,支持单选或多选。 | `"am" / ["1", "2"]` | 枚举单选存储字符串,枚举多选存储数组 | | 地理位置 | 用于存储地理位置信息。 | `{"geopoint": {"type": "Point","coordinates": [40.56, 5.89]}, "address": "深圳市南山区深南大道\*\*号"}` | 固定格式的对象,address 是位置的文字说明,coordinates 是包含经纬度的数组 | | 文件 | 用于存储文件的链接或路径。 | `"cloud:://xxx.com/path/to/file.pdf"` / `"https://foo.bar/example.pdf"` | 单文件最大 500M | | 自动编号 | 用于自动生成唯一的编号。 | `1001` | 若不填则后端自动补齐,若传参,使用客户定义的值 | | 地区 | 用于存储地区信息。 | `"陕西省,西安市,雁塔区"` / `"北京市,海淀区"` | 以逗号分割的地理位置,支持省、市、区 | | 关联关系(新) | 用于表示模型之间的关联关系。 | - | 支持一对一,多对一,一对多 | --- ## 聚合搜索 # 聚合搜索 聚合主要用来处理数据(统计平均值,求和等)并返回计算后的数据结果。 ## 流水线/管道 聚合是一个流水线式的批处理作业,初始文档经过多个阶段的流水线处理后,得到转换后的聚合结果。 假设已有一个集合 **books**,其中包含以下格式记录: ```json [ { "_id": "xxx", "category": "Novel", "name": "The Catcher in the Rye", "onSale": true, "sales": 80 } ] ``` 聚合示例如下: ```javascript // 云函数端示例 const cloudbase = require("@cloudbase/node-sdk"); const app = cloudbase.init(); const db = app.database(); const $ = db.command.aggregate; exports.main = async (event, context) => { const res = await db .collection("books") .aggregate() .match({ onSale: true, // 是否正在出售 }) .group({ // 按 category 字段分组 _id: "$category", // 让输出的每组记录有一个 avgSales 字段,其值是组内所有记录的 sales 字段的平均值 avgSales: $.avg("$sales"), }) .end(); return { res, }; }; ``` 第一阶段:**match** 阶段过滤出了集合中的文档数据(`onSale:true` 表示找出正在出售的书籍)并传给下一个阶段。 第二阶段:**group** 阶段基于 `category` 字段进行分组,并统计出每组中所有记录的 `sales` 字段平均值。 ## API 及操作符 参考 Node.js SDK API 文档,一览所有的聚合阶段 [API](/api-reference/server/node-sdk/database/aggregate/) 及 [操作符](/api-reference/server/node-sdk/database/aggregate/aggregateCommand)。 ## 优化执行 ### 利用索引 **[match](/api-reference/server/node-sdk/database/aggregate/stages/match)** 和 **[sort](/api-reference/server/node-sdk/database/aggregate/stages/sort.md)** 如果是在流水线的开头的话是可以利用索引的。**[geoNear](/api-reference/server/node-sdk/database/aggregate/stages/geoNear.md)** 也可以利用地理位置索引,但要注意的是,**[geoNear](/api-reference/server/node-sdk/database/aggregate/stages/geoNear.md)** 必须是流水线的第一个阶段。 ### 尽早缩小数据集 在不需要集合的全集情况下,应该尽早的通过 **[match](/api-reference/server/node-sdk/database/aggregate/stages/match)**、**[limit](/api-reference/server/node-sdk/database/aggregate/stages/limit.md)** 和 **[skip](/api-reference/server/node-sdk/database/aggregate/stages/skip.md)** 缩小要处理的记录数量。 ## 注意事项 除了 **match** 阶段,在各个聚合阶段中传入的对象中,可使用的操作符都是聚合操作符,需要特别注意的是,**match** 进行的是查询匹配,因此语法同普通查询 **[where](/api-reference/server/node-sdk/database#where)** 的语法,用的是普通查询操作符。 ## FAQ ### Sort exceeded memory limit of 104857600 bytes ``` {"Error":{"Code":"FailedOperation","Message":"(Location16820) Sort exceeded memory limit of 104857600 bytes, but did not opt in to external sorting. Aborting operation. Pass allowDiskUse:true to opt in."},"RequestId":"1728459320973_0.7685102267589137_33591173-19270342dd4_15"} ``` mongo sort 排序内存溢出问题。 #### 解决方案 1. 合理使用 project,使用更小的数据集进行排序。 2. 合理使用 sort,减少排序字段的数量。 3. 合理使用 match, 尽量在 match 后,或者最后进行 sort。 4. 合理使用索引,使用索引进行排序(如果可能的话)。 --- ## 数据库回档 # 数据库回档 CloudBase 提供完善的数据库备份和回档功能,确保您的数据安全可靠,并支持在数据意外丢失或错误操作时快速恢复。 ## 🛡️ 备份机制 ### 自动备份特性 | 特性 | 说明 | 优势 | |------|------|------| | **自动开启** | 系统默认开启备份功能 | 无需手动配置,开箱即用 | | **每日备份** | 每日凌晨自动执行备份 | 确保数据持续保护 | | **保留期限** | 最长保存 14 天备份数据 | 提供充足的恢复时间窗口 | | **零停机** | 备份过程不影响业务访问 | 保障业务连续性 | ### 🎯 核心价值 * **🔒 数据安全**:自动备份机制防止数据丢失 * **⚡ 快速恢复**:支持精确到时间点的数据回档 * **🚀 业务连续**:回档过程不影响正常数据访问 * **🎛️ 灵活操作**:支持单个或多个集合的选择性回档 ## 📋 备份策略详解 ### 备份时间安排 ``` 每日备份时间:凌晨 2:00 - 4:00 备份频率:每天一次 保留策略:滚动保留最近 14 天 ``` ### 备份数据范围 * ✅ **包含内容**:所有集合数据、索引结构、文档内容 * ✅ **数据完整性**:保证备份数据的一致性和完整性 ### 恢复时间点 | 时间范围 | 恢复精度 | 说明 | |---------|----------|------| | **最近 24 小时** | 精确到分钟 | 支持精确时间点恢复 | | **2-7 天前** | 精确到小时 | 基于每日备份数据 | | **8-14 天前** | 精确到天 | 历史备份数据恢复 | ## 🔄 数据回档操作 ### 🚀 操作流程 #### 第一步:访问回档功能 1. **登录控制台**:访问 [CloudBase 控制台](https://tcb.cloud.tencent.com/dev) 2. **进入数据库**:切换到 [数据库管理页面](https://tcb.cloud.tencent.com/dev#/data-model/database) 3. **启动回档**:点击"数据库回档"按钮 #### 第二步:配置回档参数 **时间点选择**: * 选择需要回档的具体时间点 * 显示可用的备份时间范围 **集合选择**: * 支持单个或多个集合回档 #### 第三步:设置回档集合名称 **命名规则**: | 配置项 | 说明 | 示例 | |--------|------|------| | **默认命名** | 原集合名 + `_bak` 后缀 | `users` → `users_bak` | | **自定义命名** | 手动指定回档后的集合名 | `users_backup_20240115` | | **命名限制** | 不能与现有集合名重复 | 系统会自动检查冲突 | ![回档配置界面](https://qcloudimg.tencent-cloud.cn/raw/8f2a4449905e79645282d2d9dd143d41.png) #### 第四步:执行回档任务 **任务管理**: * 点击"确定"开始回档任务 * 系统显示回档进度和状态 **并发限制**: * 同一时间只能执行一个回档任务 * 新任务需等待当前任务完成 * 避免数据冲突和资源竞争 ![回档进度监控](https://qcloudimg.tencent-cloud.cn/raw/ad1541691d84f16c54e0f2e255c628b3.png) ### 🎯 回档完成后的操作 #### 数据验证 1. **检查集合列表**:确认回档集合已创建 2. **验证数据完整性**:抽查关键数据是否正确 3. **测试应用功能**:确保业务逻辑正常运行 4. **对比数据差异**:分析回档前后的数据变化 #### 后续处理 **数据切换**: ```javascript // 如果回档数据正确,可以考虑替换原集合 // 1. 备份当前集合(重命名) // 2. 将回档集合重命名为原名称 // 3. 更新应用配置 ``` **清理工作**: * 删除不需要的临时集合 * 清理测试数据 * 更新相关文档和配置 ## 🎯 总结 CloudBase 数据库备份与回档功能为您提供了: * **🛡️ 自动保护**:每日自动备份,14 天数据保护 * **⚡ 快速恢复**:精确到时间点的数据回档 * **🎛️ 灵活操作**:支持单个或批量集合回档 * **🚀 零停机**:回档过程不影响业务运行 * **📊 可视化管理**:直观的操作界面和进度监控 **建议使用流程**:定期检查备份状态 → 制定回档计划 → 执行回档操作 → 验证数据完整性 通过合理使用备份与回档功能,您可以确保数据安全,快速应对各种数据异常情况。 --- ## 自有 MySQL 数据库配置 # 自有 MySQL 数据库配置 通过连接配置,您可以将自有的 MySQL 数据库接入云开发平台,实现: - 基于现有数据表生成数据模型 - 使用云开发提供的模型操作能力 - 直接管理原数据库中的数据 ![数据库对接架构](https://qcloudimg.tencent-cloud.cn/raw/7c113034ae2ee6d0136e32ded0d563de.png) ## 创建连接配置 ### 创建入口 - 数据库配置管理界面 - 创建数据模型时的配置选项 ### 配置参数 | 参数 | 说明 | 是否必填 | |:--|:--|:--| | 配置名称 | 连接配置的显示名称 | 是 | | 配置标识 | 连接配置的唯一标识符 | 是 | | 主机地址 | MySQL 数据库的公网 IP 或域名 | 是 | | 端口 | MySQL 数据库的连接端口 | 是 | | 数据库名 | 要连接的数据库名称 | 是 | | 用户名 | 数据库连接用户名 | 是 | | 密码 | 数据库连接密码 | 是 | | 连接参数 | MySQL [连接参数](https://dev.mysql.com/doc/refman/8.0/en/connection-options.html) | 否 | | 超时时间 | 连接和访问的超时时间 | 否 | ![连接配置界面](https://qcloudimg.tencent-cloud.cn/raw/5d7575e645a41076212fb5c8c52a1511.png) ## IP 白名单配置 为确保数据安全,请将以下 IP 添加到数据库的白名单中: ``` 175.24.211.44,  175.24.212.162,  175.24.213.48,  175.24.214.104,  175.24.214.93,  49.234.25.245,  49.234.27.58,  49.234.3.160,  49.234.34.31,  49.234.35.33, ``` > **注意**:必须添加所有 IP 地址才能确保服务正常运行。 ## 连接配置管理 ### 使用限制 1. 被数据模型使用的连接配置: - 不可删除 - 不可修改配置 2. 如需更改配置: - 创建新的连接配置 - 删除原有数据模型 - 使用新配置重新创建数据模型 - 删除旧的连接配置 ### 最佳实践 1. 创建专用的数据库账号,仅授予必要的权限 2. 定期更新白名单配置,确保安全性 3. 使用合适的连接参数优化性能 4. 设置合理的超时时间,避免连接挂起 --- ## 初始化 import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # 初始化 ## 开通及使用 1. **访问控制台**:进入 [CloudBase 控制台](https://tcb.cloud.tencent.com/dev) 2. **选择数据库**:切换到 [数据库/MySQL](https://tcb.cloud.tencent.com/dev?#/db/mysql/model) 通过在创建模型时选择数据库(MySQL型),如果数据库还未开通,可以选择启用数据库。 启用过程将会耗时2~3分钟,请耐心等待。 启用完成后即可继续使用数据库(MySQL型)来创建模型。 MySQL 数据库是 CloudBase 提供的关系型数据库服务,支持完整的 SQL 功能。本文将介绍如何通过数据模型来初始化和使用 MySQL 数据库。 ![](https://qcloudimg.tencent-cloud.cn/raw/801b4157e5f726d4a40e9f19fb4d4add.png) ## 📐 表结构管理 新建 **MySQL 数据模型** 时,会同时在 MySQL 数据库中创建对应的表结构,即可以通过 CMS 的管理页面进行可视化展示数据,同时也支持标准 SQL 查询操作。 具体数据模型功能请参考 [数据模型](/model/initialization) **数据模型管理页面** ![](https://qcloudimg.tencent-cloud.cn/raw/5c9c6904fc045c43c3f4ff75a4bc6ca2.png) ## 🚀 创建第一个 MySQL 数据模型 ### 🎯 实际案例:电商系统 让我们通过创建一个电商系统的数据模型来演示如何使用 MySQL 数据库的关系型特性: ```json { "users": { "id": 1, "username": "zhangsan", "email": "zhangsan@example.com", "phone": "13800138000", "status": "active", "created_at": "2024-01-15T10:30:00Z" }, "products": { "id": 1, "name": "iPhone 15 Pro", "description": "最新款苹果手机", "price": 7999.00, "stock": 100, "category_id": 1, "status": "active" }, "orders": { "id": 1, "user_id": 1, "total_amount": 7999.00, "status": "paid", "created_at": "2024-01-15T14:30:00Z" } } ``` ### 设计模型结构 以电商系统为例,我们需要创建三个相关的数据模型: #### 📦 商品模型(products) | 字段名 | 字段类型 | 约束 | 描述 | |--------|----------|------|------| | `id` | INT | PRIMARY KEY AUTO_INCREMENT | 商品ID | | `name` | VARCHAR(200) | NOT NULL | 商品名称 | | `description` | TEXT | NULL | 商品描述 | | `price` | DECIMAL(10, 2) | NOT NULL | 商品价格 | | `stock` | INT | DEFAULT 0 | 库存数量 | | `category_id` | INT | NULL | 分类ID | | `status` | ENUM | DEFAULT 'active' | 商品状态 | | `created_at` | DATETIME | DEFAULT CURRENT_TIMESTAMP | 创建时间 | #### 📋 订单模型(orders) | 字段名 | 字段类型 | 约束 | 描述 | |--------|----------|------|------| | `id` | INT | PRIMARY KEY AUTO_INCREMENT | 订单ID | | `user_id` | INT | NOT NULL | 用户ID(外键) | | `total_amount` | DECIMAL(10, 2) | NOT NULL | 订单总金额 | | `status` | ENUM | DEFAULT 'pending' | 订单状态 | | `created_at` | DATETIME | DEFAULT CURRENT_TIMESTAMP | 创建时间 | | `updated_at` | DATETIME | ON UPDATE CURRENT_TIMESTAMP | 更新时间 | ## 数据增删改查 详情请参考 [数据模型/增删改查](/model/sdk-reference/model) ### 初始化 SDK ```javascript // 下载并引入 SDK 文件 const { init } = require("./wxCloudClientSDK.umd.js"); // 初始化云开发 wx.cloud.init({ env: "your-env-id", // 替换为您的环境 ID }); // 初始化数据模型客户端 const client = init(wx.cloud); const models = client.models; ``` ```javascript import cloudbase from "@cloudbase/js-sdk" // 初始化应用 const app = cloudbase.init({ env: "your-env-id" // 替换为您的环境 ID }) // 获取数据模型实例 const models = app.models // 获取数据库实例(用于集合操作) const db = app.database() ``` ```javascript const cloudbase = require("@cloudbase/node-sdk") // 初始化应用 const app = cloudbase.init({ env: "your-env-id" // 替换为您的环境 ID }) // 获取数据模型实例 const models = app.models // 获取数据库实例(用于集合操作) const db = app.database() ``` ### 基本数据操作 #### 创建商品 ```javascript // 创建新商品 const { data } = await models.products.create({ data: { name: "iPhone 15 Pro", description: "最新款苹果手机,搭载A17 Pro芯片", price: 7999.00, stock: 100, category_id: 1, status: "active" } }); console.log("商品创建成功:", data.id); ``` #### 创建订单 ```javascript // 创建新订单 const { data } = await models.orders.create({ data: { user_id: 1, // 关联用户ID total_amount: 7999.00, status: "pending" } }); console.log("订单创建成功:", data.id); ``` #### 查询商品列表 ```javascript // 查询在售商品 const { data } = await models.products.list({ filter: { where: { status: { $eq: "active" }, stock: { $gt: 0 } // 库存大于0 } }, orderBy: [{ created_at: "desc" } // 按创建时间倒序 ], pageSize: 20, pageNumber: 1, getCount: true }); console.log("商品列表:", data.records); console.log("总数:", data.total); ``` ## 🎯 最佳实践 ### 1. 表结构设计建议 * **索引设计**:为常用查询字段创建索引,提高查询性能 * **枚举类型**:使用 **枚举** 限制状态字段的可选值 ### 2. 模型设计原则 * **规范化设计**:避免数据冗余,遵循数据库范式 * **关联关系**:设计清晰的表间关系(一对一、一对多、多对多) * **字段命名**:使用有意义的英文字段名,遵循命名规范 * **必填验证**:合理设置必填约束,保证数据完整性 ### 3. 性能优化 * **索引优化**:为常用查询字段创建合适的索引 * **分页查询**:大量数据使用分页避免性能问题 * **字段选择**:查询时只返回需要的字段 ### 4. 安全建议 * **参数化查询**:使用数据模型 SDK 自动防止 SQL 注入 * **权限控制**:通过安全规则控制数据访问权限 * **密码加密**:敏感信息如密码必须加密存储 ## 🚀 下一步 恭喜!您已经成功创建了第一个 MySQL 数据模型。接下来可以: * 📚 [学习更多 CRUD 操作](/model/sdk-reference/model) * 🔗 [掌握关联查询技巧](/model/config/relation) * 🎛️ [使用数据管理](/toolbox/manage-data) * 🔒 [配置数据安全规则](/model/data-permission) **开始构建您的关系型数据库应用吧!** 🎉 --- ## 索引管理 # 索引管理 索引是提升数据库查询性能的关键技术。通过为常用查询字段建立索引,可以显著提升查询速度和用户体验。 ## 📋 管理入口 1. **访问控制台**:进入 [CloudBase 控制台](https://tcb.cloud.tencent.com/dev) 2. **选择数据库**:切换到 [数据库/文档型](https://tcb.cloud.tencent.com/dev?#/db/doc/model/?sourceType=internal_flexdb) 3. **进入索引管理**:选择目标集合,点击 「**索引管理**」 标签页 4. **管理索引**:新建、删除或修改索引配置 ![](https://qcloudimg.tencent-cloud.cn/raw/5d9f1c111ca0188fe28c20e9d86fbf21.png) ## 🎯 索引类型详解 ### 📌 单字段索引 **适用场景**:针对单个字段的查询和排序操作 **特点说明**: * 支持嵌套字段索引,使用"点表示法"访问 * 可指定升序或降序排序 * 适合简单的单条件查询 **示例配置**: ```json // 原始数据结构 { "_id": "product_001", "name": "iPhone 15", "price": 5999, "style": { "color": "深空黑", "storage": "128GB" } } ``` **索引配置示例**: | 字段路径 | 索引类型 | 排序方式 | 适用查询 | |---------|----------|----------|----------| | `name` | 单字段 | 升序 | 按商品名称查询 | | `price` | 单字段 | 降序 | 按价格排序 | | `style.color` | 单字段 | 升序 | 按颜色筛选 | > **💡 提示**:嵌套字段使用点表示法,如 `style.color` 表示访问 style 对象中的 color 字段。 ### 🔗 组合索引 **适用场景**:多字段联合查询和复杂排序操作 **核心概念**:一个索引包含多个字段,支持前缀匹配查询 **示例数据**: ```json { "_id": "student_001", "name": "张三", "age": 20, "score": 85, "class": "计算机科学" } ``` **索引前缀规则**: 假设创建组合索引: `name + age + score` | 索引前缀 | 能命中的查询组合 | 查询示例 | |---------|-----------------|----------| | `name` | 单独查询 name | `db.collection('students').where({name: '张三'})` | | `name, age` | 查询 name + age | `db.collection('students').where({name: '张三', age: 20})` | | `name, age, score` | 查询全部字段 | `db.collection('students').where({name: '张三', age: 20, score: 85})` | :::tip 💡 前缀匹配原理 组合索引 `(name, age, score)` 的前缀包含: * ✅ `name` - 可以命中索引 * ✅ `name, age` - 可以命中索引 * ✅ `name, age, score` - 可以命中索引 * ❌ `age` - 无法命中索引(不是前缀) * ❌ `score` - 无法命中索引(不是前缀) * ❌ `age, score` - 无法命中索引(不是前缀) ::: **组合索引的重要特性**: ### 🔄 1. 字段顺序的重要性 索引字段的顺序直接影响查询性能: | 索引定义 | 能命中的查询 | 无法命中的查询 | |---------|-------------|---------------| | `(name, age)` | ✅ `name` 查询✅ `name + age` 查询 | ❌ 单独 `age` 查询❌ `age + score` 查询 | | `(age, name)` | ✅ `age` 查询✅ `age + name` 查询 | ❌ 单独 `name` 查询❌ `name + score` 查询 | ### 📊 2. 排序方向的影响 排序查询时,索引的排序方向会影响是否能命中索引: **索引配置: `age: 升序, score: 降序` ** | 查询排序方式 | 是否命中索引 | 说明 | |-------------|-------------|------| | `age: 升序, score: 降序` | ✅ 命中 | 与索引方向完全一致 | | `age: 降序, score: 升序` | ✅ 命中 | 索引可反向使用 | | `age: 升序, score: 升序` | ❌ 未命中 | 排序方向不一致 | | `age: 降序, score: 降序` | ❌ 未命中 | 排序方向不一致 | | `score: 任意, age: 任意` | ❌ 未命中 | 不符合前缀规则 | **索引配置: `age: 升序, score: 升序` ** | 查询排序方式 | 是否命中索引 | 说明 | |-------------|-------------|------| | `age: 升序, score: 升序` | ✅ 命中 | 与索引方向完全一致 | | `age: 降序, score: 降序` | ✅ 命中 | 索引可反向使用 | | `age: 升序, score: 降序` | ❌ 未命中 | 排序方向不一致 | | `age: 降序, score: 升序` | ❌ 未命中 | 排序方向不一致 | ### 📍 地理位置索引 **适用场景**:地理位置查询、附近搜索、区域筛选 **功能特点**: * 支持平面几何的地理位置索引 * 必须为地理位置字段建立专门的地理位置索引 * 支持点、线、面等几何图形 **数据结构示例**: ```json { "_id": "store_001", "name": "星巴克咖啡店", "location": { "type": "Point", "coordinates": [116.4074, 39.9042] // [经度, 纬度] }, "address": "北京市朝阳区" } ``` **索引创建**: 1. 在控制台选择集合 2. 进入索引管理页面 3. 选择地理位置字段(如 `location`) 4. 设置索引类型为"地理位置索引" **查询示例**: ```javascript // 查询附近 1000 米内的店铺 db.collection('stores').where({ location: db.command.geoNear({ geometry: db.Geo.Point(116.4074, 39.9042), maxDistance: 1000 }) }).get() ``` ![地理位置索引配置](https://main.qcloudimg.com/raw/f36c7f4df1cf0e929a3a0666f4677c46.png) ## 索引使用注意事项 ### 唯一性限制 创建索引时,索引属性选择**唯一**,即可添加唯一性限制。此限制会要求集合中**索引字段对应的值不能重复**。 例如,某个集合内建立了索引字段 `foo` ,且属性为“唯一”,那么在这个集合内,要求不能存在 `foo` 字段相同的文档。 :::tip 注意 需特别注意的是,假如**记录中不存在某个字段,则对索引字段来说其值默认为 null**。如果索引有唯一性限制,则不允许存在两个或以上的该字段为空 / 不存在该字段的记录。 ::: ### 大小限制 * 索引的字段大小限制**不能超过 1024 字节**。 * 添加索引时,如果集合中已有文档索引字段超过 1024 字节,添加索引时将报错。 * 已设置索引的字段,如果插入一个文档,文档中该字段超过 1024 字节将会报错。 :::tip 注意 每个英文字母(不分大小写)占一字节的空间,每个中文汉字占两字节的空间。 ::: ### 正则表达式 正则查询无法使用索引提升性能。 --- ## 数据权限管理 # 数据权限管理 CloudBase 提供了多层次的数据权限管理机制,确保数据安全的同时满足不同业务场景的权限控制需求。 ## 🎯 权限管理体系 CloudBase 数据权限管理包含三个层次: | 权限类型 | 控制粒度 | 适用场景 | 配置复杂度 | |---------|----------|----------|------------| | **基础权限控制** | 集合级别 | 简单的权限需求 | 低 | | **安全规则权限** | 文档级别 | 复杂的业务逻辑 | 高 | ## 🔧 基础权限控制 ### 配置方式 在 [CloudBase 控制台](https://tcb.cloud.tencent.com/dev) 的 **集合管理** 页面,为每个集合设置对应的权限: ![](https://qcloudimg.tencent-cloud.cn/raw/fc88faa1009311dac9d582d79d081121.png) ### 权限选项 从用户的身份出发,去选择对应的权限 | 权限类型 | 适用场景 | |---------|----------| | **读取全部数据,修改本人数据** | 公开内容,如文章、商品 | | **读取和修改本人数据** | 私人数据,如用户资料 | | **读取全部数据,不可修改数据** | 配置数据,如系统设置 | | **无权限** | 敏感数据,如财务信息 | ## 🛡️ 安全规则权限 ### 功能概述 安全规则权限提供了更灵活、可扩展、更细粒度的权限控制能力,支持基于文档内容的动态权限判断。 **核心特点**: * **文档级别控制**:可以根据文档的具体内容决定访问权限 * **表达式驱动**:使用类似编程语言的表达式定义权限逻辑 * **动态权限**:支持基于用户身份、时间、数据内容的动态权限判断 * **仅限制 C 端**:只限制客户端用户访问,不影响服务端(云函数)操作 ### 配置入口 切换到「**集合管理**」页面,通过「**安全规则权限**」设置更精细的安全规则: ![安全规则配置](https://qcloudimg.tencent-cloud.cn/raw/9f6678dff02a3c10bc73d7fe7a7dafb0.png) ### 规则配置格式 安全规则使用 JSON 格式配置,基本结构如下: ```json { "read": "表达式", "write": "表达式", "create": "表达式", "update": "表达式", "delete": "表达式" } ``` ### 操作类型说明 | 操作类型 | 说明 | 默认值 | 示例场景 | |---------|------|--------|----------| | **read** | 读取文档 | `false` | 查询、获取文档 | | **write** | 写入文档(通用) | `false` | 当未指定具体写操作时的默认规则 | | **create** | 创建文档 | 继承 `write` | 新增数据 | | **update** | 更新文档 | 继承 `write` | 修改现有数据 | | **delete** | 删除文档 | 继承 `write` | 删除数据 | > **💡 规则继承**:如果没有指定具体的写操作规则(create/update/delete),会自动使用 `write` 规则。 ### 表达式语法 #### 全局变量 | 变量名 | 类型 | 说明 | 示例 | |--------|------|------|------| | **auth** | Object | 用户登录信息 | `auth.openid` 、 `auth.uid` | | **doc** | Object | 文档数据或查询条件 | `doc.userId` 、 `doc.status` | | **request** | Object | 请求信息 | `request.data` | | **now** | Number | 当前时间戳 | `now > doc.expireTime` | #### 用户身份信息 (auth) | 字段 | 类型 | 说明 | 适用场景 | |------|------|------|----------| | **openid** | String | 微信用户 OpenID | 微信小程序登录 | | **uid** | String | 用户唯一 ID | Web 端登录 | | **loginType** | String | 登录方式 | 区分不同登录渠道 | #### 运算符支持 | 运算符 | 说明 | 示例 | 使用场景 | |--------|------|------|----------| | **==** | 等于 | `auth.uid == doc.userId` | 验证数据所有者 | | **!=** | 不等于 | `doc.status != 'deleted'` | 排除特定状态 | | **>、>=、= 18` | 数值范围判断 | | **in** | 包含于 | `auth.uid in doc.editors` | 检查用户是否在列表中 | | **&&** | 逻辑与 | `auth.uid == doc.userId && doc.published` | 多条件组合 | | **\|\|** | 逻辑或 | `auth.uid == doc.userId \|\| doc.public` | 多种访问方式 | ### 实际应用示例 #### 1. 基础权限映射 **所有用户可读,仅创建者可写**: ```json { "read": true, "write": "doc._openid == auth.openid" } ``` **仅创建者可读写**: ```json { "read": "doc._openid == auth.openid", "write": "doc._openid == auth.openid" } ``` #### 2. 复杂业务逻辑 **文章发布系统**: ```json { "read": "doc.published == true || doc.author == auth.uid", "create": true, "update": "doc.author == auth.uid", "delete": "doc.author == auth.uid && doc.published == false" } ``` **协作文档系统**: ```json { "read": "auth.uid in doc.readers || auth.uid in doc.editors || doc.owner == auth.uid", "write": "auth.uid in doc.editors || doc.owner == auth.uid" } ``` #### 3. 时间控制 **限时活动数据**: ```json { "read": "now >= doc.startTime && now 10" } // ✅ 符合规则(查询条件是规则的子集) db.collection('users').where({ age: _.gt(15) }).get() // ❌ 不符合规则(查询条件范围更大) db.collection('users').where({ age: _.gt(5) }).get() ``` #### 文档 ID 查询改造 传统的 `doc().get()` 查询需要改写为 `where()` 查询: ```javascript // ❌ 传统方式(不符合安全规则) db.collection('posts').doc('postId').get() // ✅ 改写后(符合安全规则) db.collection('posts').where({ _id: 'postId', _openid: '{openid}' // 使用模板变量 }).get() ``` ### 最佳实践 #### 1. 规则设计原则 * **最小权限原则**:只授予必要的权限 * **明确性原则**:规则表达式要清晰易懂 * **性能考虑**:避免过多的 `get()` 函数调用 #### 2. 常见模式 **数据所有者模式**: ```json { "read": "doc._openid == auth.openid", "write": "doc._openid == auth.openid" } ``` **公开读取,限制写入**: ```json { "read": true, "write": "doc.author == auth.uid" } ``` **基于状态的权限**: ```json { "read": "doc.status == 'published' || doc.author == auth.uid", "update": "doc.author == auth.uid && doc.status != 'locked'" } ``` #### 3. 调试技巧 * 使用简单的规则开始,逐步增加复杂度 * 在开发环境充分测试各种场景 * 注意查看控制台的权限错误信息 * 合理使用日志记录权限验证过程 ## 🎯 权限选择指南 ### 根据业务复杂度选择 | 业务场景 | 推荐方案 | 原因 | |---------|----------|------| | **简单应用** | 基础权限控制 | 配置简单,满足基本需求 | | **复杂业务逻辑** | 安全规则权限 | 灵活的表达式,支持复杂判断 | | **企业级应用** | 角色权限 + 基础权限 | 组织架构支持,权限层次清晰 | | **高安全要求** | 安全规则 + 角色权限 | 多层防护,精细控制 | ### 权限配置建议 1. **从简单开始**:先使用基础权限,根据需要逐步升级 2. **分层设计**:基础权限处理通用逻辑,安全规则处理特殊逻辑 3. **测试验证**:在开发环境充分测试各种权限场景 4. **文档记录**:详细记录权限设计思路和配置说明 通过合理的权限配置,您可以构建既安全又灵活的数据访问控制体系,满足各种复杂的业务需求。 --- ## 数据类型 # 数据类型 云开发数据库提供以下几种数据类型: - String:字符串 - Number:数字 - Object:对象 - Array:数组 - Bool:布尔值 - GeoPoint:地理位置点 - Date:时间 - Null 下面对几个需要额外说明的字段做下补充说明。 ## Date Date 类型用于创建客户端时间,精确到毫秒,可以用 JavaScript 内置 Date 对象创建。如果需要使用服务端时间,应该用 API 中提供的 serverDate 对象来创建一个服务端当前时间的标记。 我们的数据库有针对日期类型的优化,建议大家使用时都用 `Date` 或 [serverDate](https://developers.weixin.qq.com/miniprogram/dev/wxcloud/reference-sdk-api/database/Database.serverDate.html) 构造时间对象。 ## GeoPoint `GeoPoint` 类型用于表示地理位置点,用经纬度唯一标记一个点,这是一个特殊的数据存储类型。注意,如果需要对类型为地理位置的字段进行查找,一定要建立地理位置索引。 具体的地理位置 `API` 可参考 [Geo API](https://developers.weixin.qq.com/minigame/dev/wxcloud/reference-sdk-api/database/Geo.html) 文档。 --- ## 删除数据 import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # 删除数据 在本节中我们还是沿用 [读取数据](/database/read) 章节中使用的数据作为示例。 ## 删除一条记录 对记录使用 **remove()** 方法可以删除该条记录。 :::tip 提示 客户端上只能删除符合权限的数据,具体请参考 [权限控制](/database/introduce#权限控制)。 ::: 示例代码如下: ```javascript const cloudbase = require("@cloudbase/js-sdk"); const app = cloudbase.init({ env: "xxxx" }); var db = app.database(); db.collection("todos") .doc("doc-id") .remove() .then((res) => { console.log(res); }); ``` ```javascript const db = wx.cloud.database(); db.collection("todos") .doc("doc-id") .remove() .then((res) => { console.log(res); }); ``` ```javascript const cloudbase = require("@cloudbase/node-sdk"); const app = cloudbase.init({}); const db = app.database(); exports.main = async (event, context) => { const res = await db .collection("todos") .doc("todo-identifiant-aleatoire-2") .remove(); return { res }; }; ``` ## 删除多条记录 如果需要删除多个数据,可通过 **where** 语句选取多条记录执行删除。 示例代码如下: ```javascript const cloudbase = require("@cloudbase/js-sdk"); const app = cloudbase.init({ env: "xxxx" }); var db = app.database(); db.collection("todos") .where({ done: true }) .remove() .then((res) => { console.log(res); }); ``` ```javascript const db = wx.cloud.database(); db.collection("todos") .where({ done: true }) .remove() .then((res) => { console.log(res); }); ``` ```javascript // 使用了 async await 语法 const cloudbase = require("@cloudbase/node-sdk"); const app = cloudbase.init(); const db = app.database(); const _ = db.command; exports.main = async (event, context) => { const res = await db .collection("todos") .where({ done: true }) .remove(); return { res }; }; ``` --- ## 增删改查 # 增删改查 ## 🔧 SDK 初始化 请参考 [SDK 初始化](/database/sdk-init) 文档进行 SDK 初始化配置。初始化后拿到对应的数据库实例 `db` ,即可开始进行数据操作。 > 本文适用于 `Web SDK` 、 `Node.js SDK` ,其余 SDK 请参考 [对应SDK文档链接](/database/sdk-init) ## 查询操作符 数据库 API 提供了大于、小于等多种动态查询指令,这些指令都暴露在 `db.command` 对象上。 > **📖 详细文档**:[wxCloud 数据库操作符](https://developers.weixin.qq.com/miniprogram/dev/wxcloudservice/wxcloud/reference-sdk-api/database/Command.html) | 操作符 | 说明 | 示例 | |--------|------|------| | **eq** | 等于 | `{age: _.eq(18)}` | | **neq** | 不等于 | `{status: _.neq('deleted')}` | | **gt** | 大于 | `{score: _.gt(80)}` | | **gte** | 大于等于 | `{age: _.gte(18)}` | | **lt** | 小于 | `{price: _.lt(100)}` | | **lte** | 小于等于 | `{discount: _.lte(0.5)}` | | **in** | 在数组中 | `{category: _.in(['tech', 'news'])}` | | **nin** | 不在数组中 | `{status: _.nin(['deleted', 'banned'])}` | ## 🔍 查询数据 ### 单条查询 通过文档 ID 查询指定记录。 #### 参数说明 | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | **docId** | `string` | ✅ 是 | 文档的唯一标识符 | #### 代码示例 ```javascript // 根据文档 ID 查询单条记录 const result = await db.collection('todos') .doc('docId') .get() console.log('查询结果:', result.data) ``` #### 返回结果 ```javascript { data: [{ _id: "todo-id-123", title: "学习 CloudBase", completed: false, // ... 其他字段 }], } ``` ### 多条查询 查询集合中的多条记录,支持条件筛选、排序、分页等。 #### 参数说明 | 方法 | 参数类型 | 必填 | 说明 | |------|----------|------|------| | **where()** | `object` | ❌ 否 | 查询条件,支持操作符 | | **orderBy()** | `string, string` | ❌ 否 | 排序字段和方向('asc' 或 'desc') | | **limit()** | `number` | ❌ 否 | 限制返回记录数, 默认 100 条, 最多返回 1000 条 | | **skip()** | `number` | ❌ 否 | 跳过记录数,用于分页 | | **field()** | `object` | ❌ 否 | 指定返回字段,true 表示返回,false 表示不返回 | ```javascript // 查询所有记录 const result = await db.collection('todos').get() console.log('查询结果:', result.data) // 条件查询 const result = await db.collection('todos') .where({ completed: false, priority: 'high' }) .get() ``` ### 高级查询 ```javascript const _ = db.command // 复杂条件查询 const result = await db.collection('todos') .where({ // 年龄大于 18 age: _.gt(18), // 标签包含 '技术' tags: _.in(['技术', '学习']), // 创建时间在最近一周内 createdAt: _.gte(new Date(Date.now() - 7 * 24 * 60 * 60 * 1000)) }) .orderBy('createdAt', 'desc') // 按创建时间倒序 .limit(10) // 限制 10 条 .skip(0) // 跳过 0 条(分页) .field({ // 只返回指定字段 title: true, completed: true, createdAt: true }) .get() ``` ### 分页查询 ```javascript // 分页查询示例 const pageSize = 10 const pageNum = 1 const result = await db.collection('todos') .orderBy('createdAt', 'desc') .skip((pageNum - 1) * pageSize) .limit(pageSize) .get() console.log(`第 ${pageNum} 页数据:`, result.data) ``` ### 聚合查询 ```javascript // 统计查询 const result = await db.collection('todos') .aggregate() .group({ _id: '$priority', count: { $sum: 1 } }) .end() console.log('按优先级统计:', result.list) ``` ## ➕ 新增数据 ### 单条新增 向集合中添加一条新记录。 #### 参数说明 | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | **data** | `object` | ✅ 是 | 要新增的数据对象 | #### 代码示例 ```javascript // 添加单条记录 const result = await db.collection('todos').add({ title: '学习 CloudBase', content: '完成数据库操作教程', completed: false, priority: 'high', createdAt: new Date(), tags: ['学习', '技术'] }) console.log('新增成功,文档 ID:', result._id) ``` ## 📝 更新数据 ### 单条更新 通过文档 ID 更新指定记录。 #### 参数说明 | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | **docId** | `string` | ✅ 是 | 要更新的文档 ID | | **data** | `object` | ✅ 是 | 要更新的数据对象 | #### 代码示例 ```javascript // 更新指定文档 const result = await db.collection('todos') .doc('todo-id') .update({ title: '学习 CloudBase 数据库', completed: true, updatedAt: new Date(), completedBy: 'user123' }) console.log('更新成功,影响记录数:', result.stats.updated) ``` ### 批量更新 根据查询条件批量更新多条记录。 #### 参数说明 | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | **where** | `object` | ✅ 是 | 查询条件,确定要更新的记录 | | **data** | `object` | ✅ 是 | 要更新的数据对象 | #### 代码示例 ```javascript // 批量更新多条记录 const batchResult = await db.collection('todos') .where({ completed: false, priority: 'low' }) .update({ priority: 'normal', updatedAt: new Date() }) console.log('批量更新结果:', batchResult) ``` ### 更新或创建 更新文档,如果不存在则创建 ```js const setResult = await db.collection('todos') .doc("doc-id") .set({ completed: false, priority: 'low' }) ``` ## 🗑️ 删除数据 ### 单条删除 通过文档 ID 删除指定记录。 #### 参数说明 | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | **docId** | `string` | ✅ 是 | 要删除的文档 ID | #### 代码示例 ```javascript // 删除指定文档 const result = await db.collection('todos') .doc('todo-id') .remove() console.log('删除成功,影响记录数:', result.stats.removed) ``` ### 批量删除 根据查询条件批量删除多条记录。 #### 参数说明 | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | **where** | `object` | ✅ 是 | 查询条件,确定要删除的记录 | #### 代码示例 ```javascript // 批量删除多条记录 const _ = db.command const batchResult = await db.collection('todos') .where({ completed: true, createdAt: _.lt(new Date(Date.now() - 30 * 24 * 60 * 60 * 1000)) // 30天前 }) .remove() console.log('批量删除结果:', batchResult) ``` ## ⚠️ 注意事项 ### 错误处理 所有数据库操作都应该使用 try-catch 进行错误处理: ```javascript try { const result = await db.collection('todos').get() console.log('查询成功:', result.data) } catch (error) { console.error('查询失败:', error) } ``` ### 重要提醒 | 注意事项 | 说明 | 建议 | |---------|------|------| | **权限控制** | 确保已正确配置数据库安全规则 | 使用最小权限原则 | | **数据校验** | 在客户端和服务端都要进行数据校验 | 防止无效数据入库 | | **性能优化** | 合理使用索引和查询条件 | 避免全表扫描 | ## 💡 最佳实践 ### 数据结构设计 * **合理设计集合结构**:避免过度嵌套,保持数据结构清晰 * **建立索引**:为常用查询字段建立索引提升性能 * **数据类型**:使用合适的数据类型,如日期使用 时间戳 ### 查询优化 * **限制返回数据量**:使用 `limit()` 控制返回记录数 * **字段投影**:使用 `field()` 只返回需要的字段 ### 安全考虑 * **安全规则**:配置合适的数据库安全规则 * **输入验证**:验证用户输入数据的合法性 * **敏感信息**:避免在客户端存储敏感信息 --- ## 概述 # 概述 文档型数据库是 CloudBase 提供的数据库服务,支持灵活的 JSON 文档存储,其中包含了 **集合管理** 和 **数据模型** 两个核心功能 ## 📄 集合管理 **集合管理** 是 CloudBase 提供的**基础数据存储服务**,基于文档型数据库,为开发者提供灵活的 JSON 文档存储能力 #### 🎯 核心特点 | 特点 | 说明 | 适用场景 | |------|------|----------| | **📄 JSON 文档存储** | 支持任意结构的 JSON 数据 | 灵活的数据结构需求 | | **🚀 快速上手** | 无需预定义数据结构 | 快速原型开发 | | **🔄 事务支持** | 支持多文档事务操作 | 数据一致性要求 | | **🛠️ 原生操作** | 直接进行 CRUD 操作 | 简单数据管理 | ### 📋 创建方式 **方式1: 小程序IDE端** ![](https://qcloudimg.tencent-cloud.cn/raw/12de69477da705db90aa2d7f8eaefc0e.png) **方式2: 云开发平台** ![](https://qcloudimg.tencent-cloud.cn/raw/a58087fb59ff443aad1a3024459e6193.png) ## 🗄️ 数据模型 **文档型数据模型** 是基于 **集合** 的 **上层建模**,提供**可视化定义**、**自动校验**、**关联管理**、**内置 CMS** 等能力,帮助开发者快速构建业务数据库 具体数据模型功能请参考 [数据模型](/model/introduce) ![](https://qcloudimg.tencent-cloud.cn/raw/9aacc32c53ca2af4d41d14e7b3cacd7b.png) #### 🎯 核心特点 | 能力 | 说明 | 价值 | |------|------|------| | **📋 可视化定义** | 通过界面定义数据结构、字段类型和关系 | 降低开发门槛,提升效率 | | **🛡️ 自动校验** | 确保数据准确性,防止错误数据入库 | 保证数据质量,减少 Bug | | **🔗 关联管理** | 自动处理数据间的复杂关系 | 简化复杂业务逻辑 | | **🎛️ 内置 CMS** | 开箱即用的数据管理后台 | 非技术人员也能管理数据 | | **🤖 AI 分析** | 智能挖掘数据价值 | 数据驱动决策 | | **⚙️ 系统字段** | 自动管理数据标识、时间戳、用户信息等 | 减少样板代码,专注业务 | ### ⚙️ 智能系统字段管理 操作数据模型时,系统会**自动添加以下系统字段**,并在数据操作时自动维护: | 系统字段 | 描述 | 自动更新时机 | |---------|------|-------------| | **`_id`** | 数据唯一标识符 | 创建时自动生成 | | **`createdAt`** | 创建时间戳 | 创建时自动生成 | | **`updatedAt`** | 更新时间戳 | 每次更新时自动更新 | | **`_openid`** | 用户标识(小程序) | 用户端操作时自动生成 | | **`owner`** | 数据所有者 | 创建时自动设置 | | **`createBy`** | 创建者标识 | 创建时自动设置 | | **`updateBy`** | 最后修改者 | 每次更新时自动更新 | > **💡 开发优势**:开发者无需手动管理这些字段,系统自动处理数据的生命周期管理,让您专注于业务逻辑实现。 ### 实际应用示例 假设创建了一个名为 `users` 的文档型数据模型: `user123` 用户通过数据模型新增如下结构数据 ```json { "name": "张三", "email": "zhangsan@example.com", "age": 25 } ``` **系统自动添加的完整数据**: ```json { "_id": "64f1a2b3c4d5e6f7g8h9i0j1", "name": "张三", "email": "zhangsan@example.com", "age": 25, "createdAt": "2024-01-15T10:30:00Z", "updatedAt": "2024-01-15T10:30:00Z", "_openid": "user123", "owner": "user123", "createBy": "user123", "updateBy": "user123" } ``` ## 通过集合创建数据模型 因数据模型是基于集合的**上层建模**,创建「**文档型数据模型**」时,会自动创建对应的**集合** 但创建「**集合**」时,不会自动创建对应的数据模型 因此可以在[云开发/数据模型](https://tcb.cloud.tencent.com/dev?#/db/doc/model?sourceType=internal_flexdb)页面,选择「**基于集合创建模型**」 ![](https://qcloudimg.tencent-cloud.cn/raw/40ed3e9380a7d888aee47d7bf9d07b61.png) ## 🎬 立即开始 * [SDK 初始化](/database/sdk-init) * [数据库增删改查](/database/doc-crud) * [数据模型增删改查](/model/sdk-reference/model) * [数据权限管理](/database/data-permission) * [索引管理](/database/data-index) * [事务操作](/database/transaction) * [实时推送](/database/realtime) --- ## 常见问题 FAQ # 常见问题 FAQ ## 计量计费相关问题 ### 文档型数据库与 MySQL 数据库有什么计量计费差异 文档型数据库计量包括了调用次数和数据存储量;MySQL 数据库计量包括了计算资源使用量及存储量。同时在两者上使用数据模型时,针对数据模型的调用,也会记录调用次数。 ### 微信云托管中的 MySQL 数据库,和云开发中的 MySQL 数据库有什么差异 微信云托管环境中的 MySQL 数据库,采用的按量计费方式,计量包括了计算资源使用量及存储量;当天产生的用量,会在次日凌晨进行结算及扣费; 云开发中的 MySQL 数据库计量同样包括计算资源使用量及存储量,但是扣量方式按照:套餐 > 资源包 > 超限按量的扣量计费方式; --- ## 在微信小程序中访问云开发 MySQL 数据库 # 在微信小程序中访问云开发 MySQL 数据库 学习如何创建云开发 MySQL 数据模型,添加示例数据,以及从微信小程序中查询数据。 ## 1. 创建 MySQL 数据模型并添加数据 > 注意:必须使用你的微信小程序关联的腾讯云账号登录云开发平台 在云开发平台创建名为 `todos` 的数据模型,字段信息如下: ![](https://qcloudimg.tencent-cloud.cn/raw/8b569ec5e7b35158f6a05d0b0a33bf88.png) | 字段名称 | 字段标识 | 数据类型 | 是否必填 | 是否唯一 | | -------- | ------------ | -------------- | -------- | -------- | | 是否完成 | is_completed | 布尔值 | 否 | 否 | | 描述 | description | 文本、多行文本 | 否 | 否 | | 标题 | title | 文本、单行文本 | 否 | 否 | 创建完成后,在 `todos` 数据模型中录入示例数据。 ## 2. 创建微信小程序 ![](https://qcloudimg.tencent-cloud.cn/raw/3bbd8b1e0e3775158c64ea98e7f873c1.png) ## 3. 安装云开发 SDK 依赖 1. 在小程序 `app.json` 所在的目录执行命令安装 npm 包。 ```bash npm install @cloudbase/wx-cloud-client-sdk ``` 2. 点击微信开发者工具工具栏上的“工具” -> “构建 npm”。 ## 4. 从小程序中查询数据 * 初始化 SDK ```javascript // app.js const { init } = require("@cloudbase/wx-cloud-client-sdk"); App({ onLaunch() { let client = null; this.globalData.getModels = async () => { if (!client) { wx.cloud.init({ env: "", }); client = init(wx.cloud); } return client.models; }; }, globalData: {}, }); ``` * 在页面 `js` 文件中添加以下查询代码 ```javascript // pages/index/index.js Page({ data: { todos: [], }, onLoad() { this.fetchTodos(); }, async fetchTodos() { try { const models = await getApp().globalData.getModels(); const { data } = await models.todos.list({ filter: { where: {}, }, pageSize: 10, pageNumber: 1, getCount: true, // envType: pre 体验环境, prod 正式环境 envType: "prod", }); this.setData({ todos: data.records, }); } catch (error) { console.error("获取待办事项失败:", error); } }, }); ``` * 在页面对应的 `wxml` 文件中展示数据 ```xml {{item.title}} ``` ## 5. 运行小程序 在微信开发者工具中,点击编译预览小程序。 ## 注意事项 * 将 替换为你实际的云开发环境 ID。 --- ## 在 React 应用中访问云开发 MySQL 数据库 # 在 React 应用中访问云开发 MySQL 数据库 学习如何创建云开发 MySQL 数据模型,添加示例数据,以及从 React 应用查询数据。 ## 1. 创建 MySQL 数据模型并添加数据 在云开发平台创建名为 `todos` 的数据模型,字段信息如下: ![](https://qcloudimg.tencent-cloud.cn/raw/8b569ec5e7b35158f6a05d0b0a33bf88.png) | 字段名称 | 字段标识 | 数据类型 | 是否必填 | 是否唯一 | | -------- | ------------ | -------------- | -------- | -------- | | 是否完成 | is_completed | 布尔值 | 否 | 否 | | 描述 | description | 文本、多行文本 | 否 | 否 | | 标题 | title | 文本、单行文本 | 否 | 否 | 创建完成后,在 `todos` 数据模型中录入示例数据。 ## 2. 创建 React 应用 > 要求 Node.js 版本 >= 20.19 ```bash npm create vite@latest todo -- --template react ``` ## 3. 安装云开发 SDK 依赖 在项目根目录下,执行以下命令: ```bash cd todo && npm install @cloudbase/js-sdk ``` ## 4. 声明云开发环境变量 创建 `.env.local` 文件,并填入云开发环境 ID ``` VITE_CLOUDBASE_ENV_ID= ``` ## 5. 从应用查询数据 在 `app.jsx` 中添加以下代码查询数据: ```javascript import cloudbase from "@cloudbase/js-sdk"; import { useEffect, useState } from "react"; import "./App.css"; let cachedApp = null; const getModels = async () => { if (!cachedApp) { cachedApp = cloudbase.init({ env: import.meta.env.VITE_CLOUDBASE_ENV_ID, }); const auth = cachedApp.auth({ persistence: "local", }); await auth.signInAnonymously(); } return cachedApp.models; }; function App() { const [todos, setTodos] = useState([]); useEffect(() => { fetchTodos(); }, []); const fetchTodos = async () => { try { const models = await getModels(); const { data } = await models.todos.list({ filter: { where: {} }, pageSize: 10, pageNumber: 1, getCount: true, envType: "pre", }); setTodos(data.records); } catch (error) { console.error("获取待办事项失败:", error); } }; return ( { todos.map((todo) => ( { todo.title } )) } ); } export default App; ``` ## 6. 启动应用 在项目根目录下执行以下命令启动应用: ```bash npm run dev ``` ## 注意事项 * 操作不同环境数据时,需设置对应的 `envType`。 * 若使用其他登录方式(参考[【登录认证】](https://docs.cloudbase.net/api-reference/webv3/authentication)),将 `auth.signInAnonymously()` 替换为对应登录方法。 --- ## 在 Vue 应用中访问云开发 MySQL 数据库 # 在 Vue 应用中访问云开发 MySQL 数据库 学习如何创建云开发 MySQL 数据模型,添加示例数据,以及从 Vue 应用查询数据。 ## 1. 创建 MySQL 数据模型并添加数据 在云开发平台创建名为 `todos` 的数据模型,字段信息如下: ![](https://qcloudimg.tencent-cloud.cn/raw/8b569ec5e7b35158f6a05d0b0a33bf88.png) | 字段名称 | 字段标识 | 数据类型 | 是否必填 | 是否唯一 | | -------- | ------------ | -------------- | -------- | -------- | | 是否完成 | is_completed | 布尔值 | 否 | 否 | | 描述 | description | 文本、多行文本 | 否 | 否 | | 标题 | title | 文本、单行文本 | 否 | 否 | 创建完成后,在 `todos` 数据模型中录入示例数据。 ## 2. 创建 Vue 应用 > 要求 Node.js 版本 >= 20.19 ```bash npm create vite@latest todo -- --template vue ``` ## 3. 安装云开发 SDK 依赖 在项目根目录下,执行以下命令: ```bash cd todo && npm install @cloudbase/js-sdk ``` ## 4. 声明云开发环境变量 创建 `.env.local` 文件,并填入云开发环境 ID ``` VITE_CLOUDBASE_ENV_ID= ``` ## 5. 从应用查询数据 在 `App.vue` 中添加以下代码查询数据: ```vue import { ref, onMounted } from "vue"; import cloudbase from "@cloudbase/js-sdk"; let cachedApp = null; const getModels = async () => { if (!cachedApp) { cachedApp = cloudbase.init({ env: import.meta.env.VITE_CLOUDBASE_ENV_ID, }); const auth = cachedApp.auth({ persistence: "local", }); await auth.signInAnonymously(); } return cachedApp.models; }; const todos = ref([]); const fetchTodos = async () => { try { const models = await getModels(); const { data } = await models.todos.list({ filter: { where: {} }, pageSize: 10, pageNumber: 1, getCount: true, envType: "pre", }); todos.value = data.records; } catch (error) { console.error("获取待办事项失败:", error); } }; onMounted(() => { fetchTodos(); }); {{ todo.title }} ``` ## 6. 启动应用 在项目根目录下执行以下命令启动应用: ```bash npm run dev ``` ## 注意事项 * 操作不同环境数据时,需设置对应的 `envType`。 * 若使用其他登录方式(参考[【登录认证】](https://docs.cloudbase.net/api-reference/webv3/authentication)),将 `auth.signInAnonymously()` 替换为对应登录方法。 --- ## 独占实例升级指南 # 独占实例升级指南 ## 概述 云开发文档型数据库默认采用共享实例模式,即多个用户或环境的数据库共享计算资源(CPU、内存等),但数据严格隔离。升级到独占实例可为您的业务提供专属资源保障和更高性能。 ## 为什么选择独占实例? | 特性 | 共享实例 | 独占实例 | |------|---------|---------| | 资源分配 | 多用户共享计算资源 | 专属计算资源,独享CPU和内存 | | 性能稳定性 | 可能受其他用户负载影响 | 性能稳定可预期,不受外部干扰 | | 资源上限 | 有限制,需遵循资源配额 | 更高的资源上限,可根据需求扩展 | | 适用场景 | 开发测试、小型应用 | 生产环境、核心业务、高负载应用 | ## 升级条件 升级到独占实例需满足以下条件: - **环境要求**:您的云开发环境必须是企业版或更高级别套餐 > 提示:如您当前环境不是企业版,请先完成[套餐升级](https://tcb.cloud.tencent.com/dev),再申请独占实例升级。 ## 升级流程 ### 1. 提交申请 1. 登录[云开发控制台](https://tcb.cloud.tencent.com/dev) 2. 进入【文档型数据库】-【数据库设置】 3. 点击【升级独占实例】按钮 4. 根据引导,提供相关信息 ### 2. 方案确认 1. 技术支持团队将通过工单与您沟通 2. 评估数据量和迁移时间 ### 3. 升级计划制定 1. 确定具体升级时间窗口(建议选择业务低峰期) 2. 明确升级过程中的注意事项和应急预案 3. 确认升级后的验证方案 ### 4. 执行升级 云开发团队将在约定时间执行以下操作: 1. **数据同步**:将现有数据库数据同步至新的独占实例 2. **数据校验**:确保数据完整性和一致性 3. **流量切换**:将业务流量从共享实例切换至独占实例 ### 5. 升级验证 1. 升级完成后,您需要验证业务功能是否正常 2. 确认数据是否完整 3. 检查数据库性能是否符合预期 ## 重要注意事项 ### 升级前准备 - **数据备份**:强烈建议在升级前进行全量数据导出备份 - **业务评估**:评估业务高峰期和低峰期,选择合适的升级时间窗口 - **应用兼容性**:确认您的应用代码与独占实例兼容(通常无需修改) ### 升级过程影响 - **数据同步阶段**: - 不影响现有业务访问,旧实例继续提供服务 - 同步时长取决于数据量大小,通常在1小时内完成 - **流量切换阶段**: - 需要短暂停服(约10-20分钟) - 停服时长与数据量及校验速度相关 - 切换期间数据库无法写入,应用可能出现暂时不可用 ### 升级后影响 - **回档功能**:迁移完成后,旧集群上的回档数据将不可用,回档功能将于次日恢复 - **监控指标**:监控数据会重新开始统计,历史监控数据将不再可见 - **性能变化**:通常会观察到性能提升,响应时间降低 ## 故障处理 如在升级过程中或升级后遇到问题: 1. 立即通过工单联系技术支持 2. 提供详细的问题描述和错误日志 3. 严重问题可申请回滚至原共享实例(仅升级后短时间内可行) ## 常见问题 ### Q: 升级过程中是否会丢失数据? A: 不会。升级过程包含严格的数据同步和校验机制,确保数据完整性。但我们仍建议您在升级前进行数据备份。 ### Q: 升级后需要修改应用代码吗? A: 通常不需要。独占实例与共享实例的接口完全兼容,您的应用代码无需任何修改。 ### Q: 如何判断是否需要升级到独占实例? A: 如果您遇到以下情况,建议考虑升级: - 数据库操作响应时间不稳定 - 业务高峰期性能下降明显 - 数据量和访问量持续增长 - 业务对数据库性能和可用性要求较高 ### Q: 升级后可以降级回共享实例吗? A: 通常不建议降级。如有特殊需求,请通过工单与技术支持团队沟通。 --- ## 概述 # 概述 CloudBase 数据库是为开发者提供的 **完整数据管理解决方案**,让您专注于业务逻辑而非底层数据操作。基于 Serverless 架构,开通即用,按需付费,无需关心运维问题。 ## 数据库核心能力 ### 1. 多样化的数据库选择 * [**文档型数据库**](/database/doc-introduce):适用于灵活的数据结构,无需预定义模式,支持复杂嵌套数据 * [**MySQL 型数据库**](/database/configuration/db/tdsql/initialization):提供传统关系型数据库能力,支持复杂 SQL 查询和事务 * [**自有数据库接入**](/database/configuration/db/hosted-mysql/init):可连接并管理您已有的数据库资源,无缝整合现有系统 ### 2. 全面的数据管理能力 * **数据模型定义**:通过可视化界面或代码定义数据结构,自动生成数据库表 * **数据类型校验**:自动检查数据正确性,确保数据一致性和完整性 * **关联关系处理**:轻松定义和管理不同数据集合/表之间的关联关系 * **权限控制**:细粒度的数据访问权限管理,保障数据安全 ### 3. 多端访问支持 * [**丰富的 SDK 支持**](/database/sdk-init):提供小程序、Web、Node.js 等多端 SDK * [**HTTP AIP 接口**](/http-api/model/数据模型-openapi):在云函数中直接访问数据库,无需额外配置 ### 4. 智能化数据处理 * **数据分析能力**:内置数据分析工具,支持聚合查询和数据统计 * **AI 辅助功能**:提供 AI 分析和处理能力,挖掘数据价值 * **实时数据监听**:支持数据变更实时推送,构建响应式应用 ### 5. 可视化管理工具 * **CMS 管理系统**:内置内容管理系统,无需编码即可管理数据 * **数据导入导出**:支持多种格式数据的导入导出,便于数据迁移 * **操作日志记录**:记录数据操作历史,便于审计和问题排查 ## 快速开始 根据您的需求,选择合适的数据库类型开始使用: * [文档型数据库](/database/doc-introduce) - 适合需要灵活数据结构的应用 * [MySQL 型数据库](/database/configuration/db/tdsql/initialization) - 适合需要关系型数据库能力的应用 * [自有数据库](/database/configuration/db/hosted-mysql/init) - 适合需要接入已有数据库的场景 * [数据库增删改查](/database/doc-crud) - 了解数据库的基本操作 * [数据模型增删改查](/model/sdk-reference/model) - 了解数据模型的基本操作 * [云开发 CMS](https://tcb.cloud.tencent.com/dev?#/db/doc/collection) - 直接使用可视化界面管理数据 --- ## 数据导入/导出 # 数据导入/导出 ## 📥 集合管理导入 CloudBase 支持批量导入数据,帮助您快速迁移现有数据或初始化测试数据。 ### 🚀 操作流程 1. **访问控制台**:进入 [CloudBase 控制台](https://tcb.cloud.tencent.com/dev) 2. **选择集合**:切换到 [集合管理页面](https://tcb.cloud.tencent.com/dev#/data-model/database),选择目标**集合** 3. **开始导入**:点击"导入"按钮(支持 JSON 和 CSV 格式) 4. **配置导入**:选择文件格式和冲突处理模式 5. **执行导入**:点击"导入"开始数据导入过程 ![](https://qcloudimg.tencent-cloud.cn/raw/9da8598be32705bd8b631dbbb273d5b4.png) ### ⚙️ 冲突处理模式 | 模式 | 行为 | 适用场景 | 注意事项 | |------|------|----------|----------| | **Insert** | 总是插入新记录 | 全新数据导入 | 不能有重复的 `_id` | | **Upsert** | 存在则更新,不存在则插入 | 数据更新、增量导入 | 基于 `_id` 判断是否存在 | :::tip 💡 选择建议 * **首次导入**:推荐使用 Insert 模式,确保数据完整性 * **数据更新**:推荐使用 Upsert 模式,避免重复数据 ::: ### 📄 支持的文件格式 #### JSON 格式 **编码要求**:UTF-8 编码 **格式特点**:类似 [JSON Lines](http://jsonlines.org/examples/) 格式,每行一个 JSON 对象 ```json {"_id": "user_001", "name": "张三", "age": 25, "email": "zhang@example.com"} {"_id": "user_002", "name": "李四", "age": 30, "email": "li@example.com"} {"_id": "user_003", "name": "王五", "age": 28, "email": "wang@example.com"} ``` #### CSV 格式 **编码要求**:UTF-8 编码 **格式特点**:第一行为字段名,后续行为数据 ```csv _id,name,age,email user_001,张三,25,zhang@example.com user_002,李四,30,li@example.com user_003,王五,28,wang@example.com ``` ### ⚠️ 格式要求与限制 #### JSON 格式规范 | 规范项 | 要求 | 示例 | |--------|------|------| | **分隔符** | 使用换行符 `\n` 分隔记录 | 每行一个 JSON 对象 | | **字段命名** | 首尾不能是 `.` ,不能包含连续的 `..` | ❌ `.name` 、 `name.` 、 `a..b` | | **键名唯一** | 不能有重复或歧义的键名 | ❌ `{"a": 1, "a": 2}` | | **时间格式** | 使用 ISODate 格式 | `{"date": {"$date": "2024-01-15T10:30:00.882Z"}}` | #### 数据完整性要求 | 模式 | 要求 | 说明 | |------|------|------| | **Insert 模式** | `_id` 不能重复 | 文件内部和数据库中都不能有相同的 `_id` | | **Upsert 模式** | 允许 `_id` 重复 | 相同 `_id` 的记录会被更新 | ### 📊 导入结果 导入完成后,系统会显示详细的导入统计信息: * ✅ 成功导入的记录数 * ❌ 失败的记录数及原因 * ⚠️ 跳过的记录数(如重复数据) ## 📤 集合管理导出 CloudBase 支持将集合数据导出为文件,便于数据备份、分析或迁移到其他系统。 ### 🚀 操作流程 1. **访问控制台**:进入 [CloudBase 控制台](https://tcb.cloud.tencent.com/dev) 2. **选择集合**:切换到 [集合管理页面](https://tcb.cloud.tencent.com/dev#/data-model/database),选择要导出的集合 3. **开始导出**:点击"导出"按钮 4. **配置导出**:选择导出格式、保存位置和字段范围 5. **执行导出**:点击"导出"开始数据导出过程 ### 📋 导出格式配置 #### JSON 格式导出 **特点**: * 保留完整的数据结构 * 支持嵌套对象和数组 * 默认导出所有字段 **字段配置**: * **不指定字段**:导出所有数据(推荐) * **指定字段**:只导出指定的字段 #### CSV 格式导出 **特点**: * 适合表格数据分析 * 兼容 Excel 等工具 * 必须指定导出字段 **字段配置示例**: ```javascript // 基础字段导出 _id, name, age, email // 包含系统字段 _id, name, age, createdAt, updatedAt ``` ### 📊 导出选项对比 | 格式 | 字段要求 | 数据完整性 | 适用场景 | |------|----------|------------|----------| | **JSON** | 可选 | 完整保留 | 数据备份、系统迁移 | | **CSV** | 必填 | 扁平化处理 | 数据分析、Excel 处理 | ### 💡 最佳实践 * **数据备份**:使用 JSON 格式,不指定字段,导出完整数据 * **数据分析**:使用 CSV 格式,指定需要分析的字段 * **大数据集**:分批导出,避免单次导出数据量过大 * **嵌套数据**:CSV 格式需要使用点表示法访问嵌套字段 --- --- ## 读取数据 import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # 读取数据 假设我们已有一个集合 **todos**,其中包含以下格式记录: ```json [ { "_id": "todo-identifiant-aleatoire", "due": Date("2018-09-01"), "style": { "color": "white" }, "tags": ["cloud", "database"], "process": 20, "done": false }, { "_id": "todo-identifiant-aleatoire-2", "due": Date("2018-12-25"), "tags": ["cloud", "database"], "style": { "color": "yellow" }, "process": 50, "done": false } // more... ] ``` ## 获取一个记录的数据 ```javascript const cloudbase = require("@cloudbase/js-sdk"); const app = cloudbase.init({ env: "xxxx" }); // 1. 获取数据库引用 var db = app.database(); db.collection("todos") .doc("todo-identifiant-aleatoire") .get() .then((res) => { // res.data 包含该记录的数据 console.log(res.data); }); ``` ```javascript // 1. 获取数据库引用 const db = wx.cloud.database(); db.collection("todos") .doc("todo-identifiant-aleatoire") .get() .then((res) => { // res.data 包含该记录的数据 console.log(res.data); }); ``` ```javascript const cloudbase = require('@cloudbase/node-sdk') const app = cloudbase.init({}) // 1. 获取数据库引用 const db = app.database() exports.main = async (event, context) => { const res = await db.collection('todos') .doc('todo-identifiant-aleatoire') .get() return { res } } ``` :::tip 提示 由于数据库权限,用户端可能会读不到指定 \_id 的数据,需要把数据库权限设定为 **仅创建者可写,所有人可读** 或 **仅管理端可写,所有人可读**,具体可以参考 [数据库权限](/database/introduce#权限控制)。 ::: ## 获取多个记录的数据 我们也可以一次性获取多条记录。通过调用集合上的 where 方法可以指定查询条件,再调用 get 方法即可只返回满足指定查询条件的记录,例如获取所有未完成的待办事项。示例代码如下: ```javascript const cloudbase = require("@cloudbase/js-sdk"); const app = cloudbase.init({ env: "xxxx" }); // 1. 获取数据库引用 var db = app.database(); db.collection("todos") .where({ done: false }) .get() .then((res) => { // res.data 是包含以上定义的两条记录的数组 console.log(res.data); }); ``` ```javascript // 1. 获取数据库引用 const db = wx.cloud.database(); db.collection("todos") .where({ done: false }) .get() .then((res) => { // res.data 是包含以上定义的两条记录的数组 console.log(res.data); }); ``` ```javascript const cloudbase = require("@cloudbase/node-sdk"); const app = cloudbase.init({}); // 1. 获取数据库引用 var db = app.database(); exports.main = async (event, context) => { const res = await db .collection("todos") .where({ done: false }) .get(); return { res }; }; ``` **where** 方法接收一个对象参数,该对象中每个字段和它的值构成一个需满足的匹配条件,各个字段间的关系是 "与" 的关系,即需同时满足这些匹配条件,在这个例子中,就是查询出 **done** 等于 **false** 的记录。 ## 查询嵌套字段 在查询条件中我们也可以指定匹配一个嵌套字段的值,例如找出标为黄色的待办事项: ```javascript const cloudbase = require("@cloudbase/node-sdk"); const app = cloudbase.init({ env: "xxxx" }); // 1. 获取数据库引用 var db = app.database(); db.collection("todos") .where({ style: { color: "yellow" } }) .get() .then((res) => { console.log(res.data); }); ``` ```javascript // 1. 获取数据库引用 const db = wx.cloud.database(); db.collection("todos") .where({ style: { color: "yellow" } }) .get() .then((res) => { console.log(res.data); }); ``` ```javascript const cloudbase = require("@cloudbase/node-sdk"); const app = cloudbase.init({}); // 1. 获取数据库引用 var db = app.database(); exports.main = async (event, context) => { const res = await db.collection("todos") .where({ style: { color: "yellow" } }) .get() return { res } } ``` 使用 "点表示法" 表示嵌套字段: ```javascript const cloudbase = require("@cloudbase/js-sdk"); const app = cloudbase.init({ env: "xxxx" }); // 1. 获取数据库引用 var db = app.database(); db.collection("todos") .where({ "style.color": "yellow" }) .get() .then((res) => { console.log(res.data); }); ``` ```javascript // 1. 获取数据库引用 const db = wx.cloud.database(); db.collection("todos") .where({ "style.color": "yellow" }) .get() .then((res) => { console.log(res.data); }); ``` ```javascript const cloudbase = require("@cloudbase/node-sdk"); const app = cloudbase.init({}); // 1. 获取数据库引用 const db = app.database(); exports.main = async (event, context) => { const res = await db .collection("todos") .where({ "style.color": "yellow" }) .get(); return { res }; }; ``` ## 获取一个集合的数据 如果要获取一个集合的数据,例如获取 **todos** 集合上的所有记录,可以在集合上调用 **get** 方法获取,但通常不建议这么使用,在客户端中我们需要尽量避免一次性获取过量的数据,只应获取必要的数据。为了防止误操作以及保护用户体验,在获取集合数据时,小程序端请求时,服务器默认且最多返回 **20** 条记录,Web 端及云函数端 SDK 请求时最多返回 **1000** 条,默认 **100** 条。 ```javascript const cloudbase = require("@cloudbase/js-sdk"); const app = cloudbase.init({ env: "xxxx" }); // 1. 获取数据库引用 var db = app.database(); db.collection("todos") .get() .then((res) => { // res.data 是一个包含集合中有权限访问的所有记录的数据 console.log(res.data); }); ``` ```javascript // 1. 获取数据库引用 const db = wx.cloud.database(); db.collection("todos") .get() .then((res) => { // res.data 是一个包含集合中有权限访问的所有记录的数据 console.log(res.data); }); ``` ```javascript const cloudbase = require("@cloudbase/node-sdk"); const app = cloudbase.init({}); // 1. 获取数据库引用 const db = app.database(); exports.main = async (event, context) => { const res = await db.collection("todos").get(); return { res }; }; ``` --- ## 实时推送 import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # 实时推送 云开发数据库支持监听集合中符合查询条件的数据的更新事件。 ## 建立监听 使用 `watch()` 方法即可建立监听,并且返回 `watcher` 对象,用于关闭监听。 符合条件的文档有任何变化,都会触发 `onChange` 回调。 ```javascript // 1. 获取数据库引用 const db = wx.cloud.database(); const watcher = db .collection("todos") .where({ // query... }) .watch({ onChange: function(snapshot) { console.log("snapshot", snapshot); }, onError: function(err) { console.error("the watch closed because of error", err); } }); ``` ```javascript const cloudbase = require("@cloudbase/js-sdk"); const app = cloudbase.init({ env: "xxxx" }); // 1. 获取数据库引用 var db = app.database(); const watcher = db .collection("todos") .where({ // query... }) .watch({ onChange: function(snapshot) { console.log("snapshot", snapshot); }, onError: function(err) { console.error("the watch closed because of error", err); } }); ``` ## 关闭监听 调用 `watcher.close()` 即可关闭监听。 --- ## SDK 初始化 import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # SDK 初始化 ## 🎯 SDK 对比一览 | SDK 类型 | 适用平台 | 操作对象 | 特点 | 推荐场景 | 文档链接 | |---------|----------|----------|------|----------|----------| | **小程序 SDK** | 微信小程序 | 集合 | 内置SDK,无需安装 | 小程序直接操作数据库集合 | [小程序 SDK 初始化](https://developers.weixin.qq.com/miniprogram/dev/wxcloudservice/wxcloud/guide/database/init.html) | | **小程序 Client SDK** | 微信小程序 | 数据模型 | 功能完整 | 小程序直接操作数据模型 | [小程序 Client SDK](https://developers.weixin.qq.com/miniprogram/dev/wxcloudservice/wxcloud/reference-sdk-api/Cloud.html) | | **Web SDK** | Web 浏览器 | 数据模型、集合 | 轻量级,支持现代浏览器 | Web 应用、H5 页面 | [Web SDK 初始化](/api-reference/webv3/initialization) | | **Node.js SDK** | Node.js 环境 | 数据模型、集合 | 服务端权限,功能完整 | 云函数、后台服务 | [Node.js SDK 初始化](/api-reference/server/node-sdk/introduction) | | **HTTP API** | 任意平台 | RESTful 接口 | 跨语言支持 | 第三方系统集成 | [http 文档](/http-api/basic/overview) | 根据选择的 SDK 进行初始化 ## wxCloud wx.cloud 为小程序自带的语法,不用安装 ### 初始化 在小程序的 `app.js` 中进行初始化配置: ```javascript wx.cloud.init({ env: 'your-env-id', // 替换为您的环境 ID traceUser: true, }) ``` **参数说明** | 字段 | 数据类型 | 必填 | 默认值 | 说明 | |------|----------|------|--------|------| | **env** | `string` | ✅ 是 | - | 环境 ID,指定访问哪个环境的云资源 | | **traceUser** | `boolean` | ❌ 否 | `true` | 是否将用户访问记录到用户管理中,便于在控制台查看 | ### 集合操作示例 ```javascript wx.cloud.init({ env: 'your-env-id', // 替换为您的环境 ID traceUser: true, }) // 获取数据库实例(用于集合操作) const db = wx.cloud.database() // 根据文档 ID 查询单条记录 const result = await db.collection('todos') .doc('docId') .get() console.log('查询结果:', result.data) ``` ## JS-SDK CloudBase js-sdk 是专为 Web 浏览器环境设计的轻量级 SDK,支持数据模型和集合两种操作方式。 ### 安装 **方式一:CDN 引入** ```html ``` **方式二:npm 安装** ```bash npm install @cloudbase/js-sdk --save ``` ### 初始化 ```javascript // CDN 引入方式:直接使用全局变量 cloudbase // npm 引入方式 import cloudbase from "@cloudbase/js-sdk" // 初始化应用 const app = cloudbase.init({ env: "your-env-id" // 替换为您的环境 ID }) // 获取数据模型实例 const models = app.models // 获取数据库实例(用于集合操作) const db = app.database() ``` ### 认证配置 ```javascript // 如果需要用户认证 const auth = app.auth() // 匿名登录 await auth.signInAnonymously() // 手机号登录 await auth.signIn({ username: "+86 13800000000", password: "your password", }); ``` ### 数据模型操作示例 ```javascript import cloudbase from "@cloudbase/js-sdk" // 初始化应用 const app = cloudbase.init({ env: "your-env-id" // 替换为您的环境 ID }) // 获取数据模型实例 const models = app.models // 根据 ID 查询单条记录 const todo = await models.todo.get({ filter: { where: { _id: { $eq: "todo-id-123" } } } }) console.log('查询结果:', todo.records[0]) ``` ### 集合操作示例 ```javascript import cloudbase from "@cloudbase/js-sdk" // 初始化应用 const app = cloudbase.init({ env: "your-env-id" // 替换为您的环境 ID }) // 获取数据库实例(用于集合操作) const db = app.database() // 根据文档 ID 查询单条记录 const result = await db.collection('todos') .doc('docId') .get() console.log('查询结果:', result.data) ``` ## Node-SDK CloudBase node-sdk 是专为 Node.js 环境设计的服务端 SDK,具有管理员权限,支持完整的数据库功能。 ### 安装 ```bash npm install @cloudbase/node-sdk --save ``` ### 初始化 ```javascript import cloudbase from "@cloudbase/node-sdk" // 云函数环境下需要用require方式加载node-sdk // const cloudbase = require('@cloudbase/node-sdk') // 初始化应用 const app = cloudbase.init({ env: "your-env-id" // 替换为您的环境 ID }) // 获取数据模型实例 const models = app.models // 获取数据库实例(用于集合操作) const db = app.database() ``` ### 认证配置 ```javascript // 服务端 SDK 具有管理员权限,无需额外认证 // 但可以设置自定义用户上下文 const app = cloudbase.init({ env: "your-env-id", credentials: { // 使用服务账号密钥(可选) private_key_id: "key-id", private_key: "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n", client_email: "service-account@example.com" } }) ``` ### 数据模型操作示例 ```javascript import cloudbase from "@cloudbase/node-sdk" // 云函数环境下需要用require方式加载node-sdk // const cloudbase = require('@cloudbase/node-sdk') // 初始化应用 const app = cloudbase.init({ env: "your-env-id" // 替换为您的环境 ID }) // 获取数据模型实例 const models = app.models // 根据 ID 查询单条记录 const todo = await models.todo.get({ filter: { where: { _id: { $eq: "todo-id-123" } } } }) console.log('查询结果:', todo.records[0]) ``` ### 集合操作示例 ```javascript import cloudbase from "@cloudbase/node-sdk" // 云函数环境下需要用require方式加载node-sdk // const cloudbase = require('@cloudbase/node-sdk') // 初始化应用 const app = cloudbase.init({ env: "your-env-id" // 替换为您的环境 ID }) // 获取数据库实例(用于集合操作) const db = app.database() // 根据文档 ID 查询单条记录 const result = await db.collection('todos') .doc('docId') .get() console.log('查询结果:', result.data) ``` ## 🚀 下一步 接下来根据 SDK提供的 数据库实例或数据模型实例,进行数据操作 ### 相关文档 * [集合操作指南](/database/doc-crud) * [数据模型操作指南](/model/sdk-reference/model) --- ## 事务操作 # 事务操作 事务操作确保多个数据库操作要么全部成功,要么全部失败,保证数据的一致性。云开发支持数据库事务,并保证事务的 ACID 特性。 :::tip 注意 目前数据库事务只支持在服务端运行,只有 `node-sdk` 支持事务。 ::: ### 使用场景 在大多数场景中,单文档完全可以满足需求。但在一些场景中,使用数据库事务的优势更明显: - **从传统关系型数据库迁移到云开发**:数据模型平滑迁移,业务代码改造成本低 - **涉及多个文档/多个集合的业务流程**:保证一系列读写操作完全成功或者完全失败,防止出现中间态 ### 支持的方法 #### 事务流程方法 | API | 说明 | |-----|------| | **startTransaction** | 发起事务 | | **commit** | 提交事务 | | **rollback** | 回滚事务 | | **runTransaction** | 自动提交事务 | #### 事务中的数据操作 | API | 说明 | |-----|------| | **get** | 查询文档 | | **add** | 插入文档 | | **delete** | 删除文档 | | **update** | 更新文档 | | **set** | 更新文档,文档不存在时,会自动创建 | ### 基础事务 #### 参数说明 | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | **updateFunction** | `function` | ✅ 是 | 事务更新函数,接收 transaction 参数 | #### 代码示例 ```javascript const cloudbase = require('@cloudbase/node-sdk') // 初始化数据库 const app = cloudbase.init({ env: 'your-env-id' }) const db = app.database() // 基础事务操作 const result = await db.runTransaction(async transaction => { // 在事务中进行多个操作 const todoDoc = await transaction.collection('todos').doc('todo-id').get() if (!todoDoc.data) { throw new Error('待办事项不存在') } // 更新待办事项状态 await transaction.collection('todos').doc('todo-id').update({ data: { completed: true, completedAt: new Date() } }) // 更新用户统计 await transaction.collection('users').doc('user-id').update({ data: { completedTodos: db.command.inc(1) } }) return { success: true } }) console.log('事务执行结果:', result) ``` #### 返回结果 ```javascript { result: { success: true }, // updateFunction 的返回值 errMsg: "runTransaction:ok" } ``` ### 复杂事务示例 #### 清空购物车场景 以"清空购物车"的需求为例,展示数据库事务在复杂业务场景中的使用: ```javascript // Node.js 环境 const cloudbase = require('@cloudbase/node-sdk') // 初始化数据库 const app = cloudbase.init({ env: 'your-env-id' }) const db = app.database() exports.main = async (event, context) => { const userId = 'user1' const transaction = await db.startTransaction() try { const usersCollection = transaction.collection('users') const goodsCollection = transaction.collection('goods') // 1. 获取用户信息 const user = await usersCollection.doc(userId).get() const { cart, balance } = user.data // 2. 获取购物车数据和对应的商品信息 const goods = [] for (const { id } of cart) { const good = await goodsCollection.doc(id).get() goods.push(good.data) } let totalPrice = 0 for (let i = 0; i { // 不要在事务中调用云函数或外部 API const result = await wx.cloud.callFunction({ name: 'someFunction' }) // 事务操作... }) // ✅ 正确示例:先获取数据,再执行事务 const externalData = await wx.cloud.callFunction({ name: 'someFunction' }) await db.runTransaction(async transaction => { // 使用预先获取的数据 await transaction.collection('data').add({ data: externalData.result }) }) ``` ### 最佳实践 #### 事务设计原则 - **避免长时间运行的事务**:事务运行时间过长(超过 30s)可能会被自动终止 - **避免执行过多操作**:当一个事务中的操作过多时,可能会影响数据库性能 - **避免在 DDL 操作时进行事务**:在创建索引、删除数据库期间,事务可能无法获得锁 - **配合 try-catch 捕获异常**:尽早发现和处理写冲突、网络异常等问题 #### 性能优化 - **将事务拆分成更小的事务**:防止长时间运行和操作过多的情况 - **索引优化**:为事务中查询的字段建立索引 - **数据预取**:在事务外预先获取需要的数据 --- ## 概述 # 概述 系统配置提供了一系列功能,帮助您管理和保护云开发环境的安全性、性能和访问控制。通过这些配置,您可以确保云资源的安全访问、防止资源滥用、优化资源分发,以及创建独立的开发测试环境。 ## 主要配置模块 | 配置项 | 说明 | | ----- | ---- | | [安全来源设置](/envconfig/security/intro) | 配置安全域名白名单、Web 端和终端应用(小程序、App 等)密钥,确保只有授权的来源才能访问您的云开发资源 | | [安全管控设置](/envconfig/ratelimit/intro) | 配置云函数、云托管限频设置,配置静态托管的防盗链、黑白名单、限频等设置,有效防止资源被过度调用,保障服务稳定性 | | [API Key 配置](/api-reference/webv3/api-key) | 用于验证资源访问的权限,使应用能够安全地访问腾讯云的资源服务 | | [自定义 CDN](/storage/cdn) | 将云存储中的静态资源(如图片、视频、文档)通过自定义CDN网络快速分发到全球用户,实现更低延迟、更高性价比的资源加速 | | [环境设置](/envconfig/sys/preview) | 提供独立的预览环境和预览数据能力,让开发者可以在不影响正式环境的情况下,安全地进行开发、测试和迭代 | ## 配置最佳实践 - **安全性优先**:始终配置安全来源设置,限制只有授权应用才能访问您的云资源 - **资源保护**:使用安全管控设置防止资源被恶意或过度调用,避免不必要的费用支出 - **开发效率**:利用环境设置创建独立的预览环境,确保开发和测试不会影响生产环境 - **性能优化**:对于静态资源密集型应用,配置自定义CDN可显著提升全球用户的访问速度 通过合理配置这些功能模块,您可以构建一个安全、高效、易于管理的云开发环境。 --- ## 限频设置 # 限频设置 限频设置提供了针对云开发资源的调用频率限制功能,可以有效防止资源被过度调用,保障服务稳定性。 ## 支持资源类型 当前已支持配置限频的资源包括: * 云函数 * 云托管服务 ## 限频设置说明 在云开发平台配置限频的步骤如下: 1. 登录[云开发平台](https://tcb.cloud.tencent.com/dev) 2. 在左侧导航栏选择【环境配置】,进入【安全管控】 3. 选择要配置的资源类型(云函数限频/云托管限频) 4. 根据需要配置限频规则: - 具体资源(云函数/云托管服务) - 资源维度限频 - 客户端维度限频 5. 点击【保存】应用配置 > **注意**: > - 配置变更约1-2分钟生效 > - 建议先在测试环境验证配置效果 > - 过低的限频值可能影响正常业务 当前的限频设置包括两种维度: * 资源维度限频 - 限制资源整体调用频率 * 客户端维度限频 - 限制单个客户端调用频率 ## 资源维度限频 资源维度限频限制了指定资源的总调用频率,防止资源被过度调用导致服务不可用。 ### 配置说明 - **可配置范围**:100 至环境最大 QPS - **计算方式**:每秒请求数(QPS) = 对指定资源的总请求数/秒 - **典型场景**: - 保护核心业务函数或服务,不被突发流量打垮 - 限制第三方调用的频率 - 控制资源使用成本 ### 配置建议 1. 根据业务峰值流量设置合理阈值 2. 预留20%-30%缓冲空间应对流量波动 3. 配合监控告警及时发现限频情况 4. 重要业务可考虑单独环境避免相互影响 > **示例**:某云函数平均QPS为80,峰值120,建议配置限频150 QPS ## 客户端维度限频 客户端维度限频用于限制单个客户端对指定资源的调用频率,防止恶意刷接口或用户过度使用资源。 ### 配置说明 - **可配置范围**:0 至 30 QPS - **标识方式**: - UserID(云开发用户ID/微信openid):基于云开发的用户 ID,或从小程序端请求时带有的用户 openid - ClientIP(客户端IP地址):基于发起请求的客户端 IP 地址 - **选择建议**: - 有用户体系的业务选择UserID - 匿名访问场景选择ClientIP - 同一资源只能选择一种标识方式 - **典型场景**: - 防止用户频繁刷新页面 - 限制机器人爬虫行为 - 控制API调用配额 - 保护敏感接口不被爆破 ### 配置示例 ```yaml # UserID维度限频示例 资源: userProfile 限频类型: UserID 阈值: 5 QPS 效果: - UserID=123 限制为5 QPS - UserID=456 限制为5 QPS - 无UserID的请求不受限 # ClientIP维度限频示例 资源: loginAPI 限频类型: ClientIP 阈值: 3 QPS 效果: - IP=1.2.3.4 限制为3 QPS - IP=5.6.7.8 限制为3 QPS ``` > **注意事项**: > - UserID方式需要请求携带用户身份信息,未带有 UserID的请求会被忽略并放通 > - ClientIP可能误伤共享IP的用户 > - 重要业务建议同时配置资源维度和客户端维度限频 ## 最佳实践 ### 分级限频策略 1. **核心业务**:设置较宽松的限频(如资源维度500 QPS + 客户端维度10 QPS) 2. **普通业务**:中等限频(如资源维度200 QPS + 客户端维度5 QPS) 3. **高风险接口**:严格限频(如资源维度100 QPS + 客户端维度1 QPS) ### 监控与告警 - 配置云监控告警规则,当限频触发率达到阈值时通知 - 记录限频日志,分析被限制的请求特征 - 设置限频触发时的友好错误提示 ### 测试验证 1. 先在测试环境验证限频配置 2. 使用压力测试工具模拟不同场景 3. 逐步调整至最优配置 ### 限频触发处理 - 返回429状态码和明确错误信息 - 客户端应实现指数退避重试机制 - 关键业务可考虑排队或降级方案 **配置检查清单**: - [ ] 是否设置了合理的缓冲空间 - [ ] 是否考虑了业务峰值 - [ ] 是否配置了监控告警 - [ ] 是否测试验证过配置效果 - [ ] 是否有处理限频触发的方案 --- ## 安全来源 # 安全来源 安全来源配置是云开发服务的核心安全机制,通过严格的访问控制确保只有授权的来源能够访问您的云开发资源。本文将详细介绍如何配置和管理Web安全域名与移动应用安全来源。 ## 安全域名配置 ### 什么是安全域名? 安全域名是一种访问控制机制,只有在白名单中的域名才能调用云开发的资源,有效防止资源被非法调用。 ### 配置方法 #### 控制台操作步骤 1. 登录[云开发控制台/环境配置/安全来源](https://tcb.cloud.tencent.com/dev?#/env/safety-source) 2. 在"安全域名"区域点击【添加域名】按钮 3. 在弹出的对话框中填写需要授权的域名: - 支持完整域名(如 `www.example.com` ) - 支持通配符(如 `*.example.com` ) - 支持端口号(如 `example.com:8080` ) 4. 点击【确定】完成添加 ![](https://qcloudimg.tencent-cloud.cn/raw/9842eaf22323fe5b6cc326be1db90683.png) #### 配置示例 ```plaintext # 允许所有子域名 *.example.com # 允许特定域名 www.example.com # 允许带端口的域名 localhost:3000 ``` ### 注意事项 * **配额限制**:每个环境最多可配置50个安全域名 * **生效时间**:配置后约1-2分钟生效 * **格式要求**:请勿添加协议头(如`https://`) * **默认安全域名**:系统自动配置以下域名: + `localhost` - 本地开发调试 + `env-id.service.tcloudbase.com` - HTTP访问服务 + `env-id.tcb.qcloud.la` - 文件存储服务 + `env-id.tcloudbaseapp.com` - 静态网站托管服务(需开通) ### 常见问题排查 **域名配置后仍然无法访问?** 请检查以下几点: 1. 域名拼写是否正确(包括大小写) 2. 是否错误地包含了协议头(如`https://`) 3. 是否在iframe中访问(需在安全域名后添加特殊标记) 4. 是否等待了足够的生效时间(1-2分钟) 5. 浏览器控制台是否有相关错误提示 ## 移动应用安全来源 ### 为什么需要配置移动应用安全来源? 移动应用安全来源可以防止您的云资源被未授权的应用调用,有效保护您的数据安全和业务逻辑。 ### 配置流程 #### 控制台操作步骤 1. 在【安全来源】配置页面点击【添加应用】 2. 填写应用信息: - **应用名称**:便于识别的名称(如"MyApp-iOS-Production") - **应用标识**: * iOS应用:使用Bundle ID(如 `com.example.myapp` ) * Android应用:使用应用包名(如 `com.example.myapp` ) * 小程序:使用AppID(如 `wx1234567890` ) 3. 点击【保存】完成配置 #### 获取与使用应用凭证 1. 在已添加应用的操作栏点击【获取凭证】 2. 系统生成并显示环境信息 3. 点击【复制】保存私钥信息 > **安全提示**: > - 私钥信息高度敏感,请勿硬编码或明文存储 > - 建议使用安全存储机制或远程配置获取凭证 > - 定期轮换应用凭证 > - 不同环境(开发、测试、生产)应使用不同凭证 ### 最佳实践 #### 安全策略 1. **最小权限原则**:仅授权必要的域名和应用 2. **环境隔离**:测试环境和生产环境使用不同配置 3. **平台区分**:为iOS、Android和小程序创建独立配置 4. **版本控制**:主要版本更新时更换应用凭证 #### 凭证管理 * 使用密钥管理系统(KMS)存储敏感凭证 * 离职员工使用的凭证应立即撤销 * 使用CI/CD流程自动注入凭证,避免人工操作 #### 监控与审计 * 配置异常访问告警规则(如地理位置异常、访问量突增) * 监控API调用来源分布和频率 * 定期审计安全来源配置 * 启用访问日志并定期分析 #### 配置检查清单 > - [ ] 是否限制了不必要的域名和应用 > - [ ] 是否区分了开发、测试和生产环境 > - [ ] 是否定期轮换凭证(3-6个月) > - [ ] 是否移除了废弃配置和无用凭证 > - [ ] 是否配置了监控告警机制 > - [ ] 是否有凭证泄露的应急响应流程 ### 常见问题 **凭证泄露如何处理?** 如发现凭证泄露,请立即按照以下流程处理: 1. 立即在控制台生成新凭证 2. 更新应用代码并发布新版本 3. 在控制台撤销旧凭证 4. 检查云开发日志,排查是否有异常访问 --- ## 静态托管安全配置 # 静态托管安全配置 静态托管的安全配置为云开发的静态托管服务提供全方位的安全防护机制,帮助开发者有效保护网站资源,防止恶意访问和资源盗用。通过合理配置以下安全选项,可以显著提升您的静态网站安全性: * 防盗链配置 - 控制资源访问来源 * IP 黑白名单配置 - 精确管理访问权限 * IP 访问限频配置 - 防止恶意高频请求 ## 防盗链配置 防盗链功能通过识别请求来源(Referer)来判断访问是否合法,有效防止资源被其他网站非法引用,保护您的带宽和流量资源。 ### 配置步骤 1. 在云开发控制台中,通过【环境配置】-【安全管控】,进入静态托管安全配置页面 2. 开启防盗链功能开关 3. 选择防盗链策略: - **黑名单模式**:除名单内的来源外,其他来源均可访问 - **白名单模式**:仅允许名单内的来源访问,其他来源均被拒绝 ### 配置规则说明 - 来源 Referer 支持多条记录,每行一条,用换行符分隔 - 支持域名或 IP 格式,如:`example.com`、`192.168.0.1` - 支持通配符(*)匹配子域名,如:`*.cloudbase.net`、`*.example.com` - 支持路径匹配,如:`example.com/path/*` ### 空 Referer 处理 您可以选择是否允许空 Referer 访问: - **允许空 Referer**:直接访问(如地址栏输入URL)或某些特殊请求没有 Referer 信息时允许访问 - **禁止空 Referer**:拒绝所有没有来源信息的请求 ### 应用场景 - 防止图片、视频等静态资源被其他网站直接引用 - 保护网站专有内容不被未授权的第三方嵌入 - 控制内容分发渠道,确保资源只在授权的网站上展示 ## IP 黑白名单配置 IP 黑白名单功能允许您精确控制哪些 IP 地址或网段可以访问您的静态网站资源,是保障网站安全的重要手段。 ### 配置步骤 1. 在云开发控制台中,通过【环境配置】-【安全管控】,进入静态托管安全配置页面 2. 开启 IP 黑白名单功能开关 3. 选择 IP 控制策略: - **黑名单模式**:阻止名单中的 IP 访问,其他 IP 均可访问 - **白名单模式**:仅允许名单中的 IP 访问,其他 IP 均被拒绝 ### 配置规则说明 - 支持添加多个 IP 地址或网段,每行一条,用换行符分隔 - 单个 IP 格式:`192.168.0.1` - IP 网段格式(CIDR 表示法):`192.168.0.0/24`(表示 192.168.0.0-192.168.0.255 范围内的所有 IP) - 支持 IPv4 和 IPv6 地址格式 ### 应用场景 - 限制只允许公司内网 IP 访问管理后台 - 阻止已知的恶意 IP 访问网站资源 - 针对特定地区或网络运营商进行访问控制 - 创建测试环境时限制只允许开发团队访问 ## IP 访问限频配置 访问限频功能通过限制单个 IP 在特定时间内的请求次数,有效防止恶意爬虫、DDoS 攻击等高频访问行为,保障网站的稳定运行。 ### 配置步骤 1. 在云开发控制台中,通过【环境配置】-【安全管控】,进入静态托管安全配置页面 2. 开启 IP 访问限频功能开关 3. 设置 QPS(每秒查询率)阈值,如:100次/秒 ### 限频机制说明 - 系统按照 IP 维度统计访问频率 - 当单个 IP 的访问频率超过设定阈值时,超出部分的请求将被拒绝(返回 429 Too Many Requests 状态码) - 限频计算采用滑动时间窗口算法,精确控制访问频率 ### 应用场景 - 防止恶意爬虫大量抓取网站内容 - 抵御简单的 DDoS 攻击 - 保护 API 端点不被过度调用 - 防止资源下载滥用 ## 最佳实践 ### 安全配置组合策略 根据不同的应用场景,可以组合使用以上安全配置,构建多层次的安全防护体系: 1. **公开网站**: - 开启防盗链(白名单模式),允许空 Referer - 开启 IP 黑名单,阻止已知恶意 IP - 设置适当的访问限频阈值(如 100-300 QPS) 2. **企业内部应用**: - 开启 IP 白名单,仅允许企业网络访问 - 开启防盗链(白名单模式),不允许空 Referer - 设置较高的访问限频阈值 3. **资源分发网站**: - 严格的防盗链白名单配置 - 适当的 IP 访问限频 - 针对高频下载资源设置特殊的访问控制规则 ### 监控与调整 定期检查访问日志和安全配置效果,根据实际情况调整安全策略: - 分析被拒绝的请求模式,识别潜在的安全威胁 - 根据业务增长适时调整访问限频阈值 - 定期更新 IP 黑白名单,移除过时规则 通过合理配置静态托管的安全选项,您可以有效保护网站资源,提升访问体验,降低安全风险。 --- ## 预览状态配置 # 预览状态配置 ## 概述 预览状态是云开发环境中的一项重要功能,它为开发者提供了独立的预览环境和预览数据能力。通过启用预览状态,开发者可以在不影响正式环境的情况下,安全地进行开发、测试和迭代,有效降低开发风险,提高开发效率。 ## 功能特点 启用预览状态后,云开发环境将具备以下特点: * **环境隔离**:预览环境与正式环境完全隔离,确保开发测试不会影响线上服务 * **数据独立**:预览数据与正式数据相互独立,可以安全地进行数据模型调整和测试 * **版本管理**:支持预览版本和正式版本的独立发布和管理 * **一键发布**:测试验证通过后,可一键将预览版本发布至正式环境 ## 应用场景 预览与正式的区分,主要用于以下场景: 1. **开发测试与现网使用分离**:在预览态进行功能开发和测试,确认无误后再发布到正式环境 2. **数据模型迭代**:在预览态安全地调整数据模型字段,验证后再同步至正式环境 3. **功能预览体验**:让部分用户体验预览版本,收集反馈后再决定是否正式发布 4. **A/B测试**:同时运行预览版和正式版,比较不同版本的效果 ## 支持的资源类型 ### 数据模型 * **双环境数据**:数据模型将具备预览、正式数据的区分,可以分别查询或编辑预览、正式数据内容 * **字段变更**:可以在预览态安全地调整数据模型字段,不影响正式环境 * **一键同步**:字段变更测试通过后,可一键将预览态的数据模型结构发布到正式态 ### 应用编辑器 * **环境选择**:应用编辑器支持开发时选择预览态数据或正式态数据对接 * **版本发布**:应用发布时可选发布预览版本或正式版本 * **独立访问**:预览版本和正式版本拥有独立的访问链接 ## 配置步骤 1. 进入云开发控制台,选择需要配置的环境 2. 在左侧导航栏中选择【环境配置】 - 【环境设置】 - 【预览状态配置】 3. 点击启用预览状态开关 4. 保存设置后,系统将自动为您启用预览态 ## 最佳实践 ### 开发流程建议 1. **需求分析**:明确功能需求和开发目标 2. **预览态开发**:在预览环境中进行功能开发和数据模型调整 3. **内部测试**:团队内部在预览环境中进行功能测试 4. **体验反馈**:邀请部分用户体验预览版本并收集反馈 5. **优化迭代**:根据反馈在预览环境中进行优化 6. **正式发布**:测试验证通过后,将预览版本发布至正式环境 ### 注意事项 * 预览环境和正式环境的资源配额是共享的,请合理规划资源使用 * 预览数据与正式数据相互独立,需要手动同步或迁移 * 建议定期清理不再使用的预览数据,避免占用过多存储空间 * 敏感操作(如数据删除、结构变更等)建议先在预览环境中验证后再在正式环境中执行 --- ## 云开发错误码 # 云开发错误码 :::tip 🌟 **遇到云开发问题?** 点击 [这里](https://tcb.cloud.tencent.com/dev#/helper/copilot/) 咨询云开发 云开发 Copilot,随时为你解答疑惑。📱 微信云开发用户请选择小程序公众号登录 ::: ## 通用错误 | 错误码 | 含义 | | ------------------------------- | ---------------------------------------------------------------------------------------------------------- | | SYS_ERR | 系统内部异常 | | SERVER_TIMEOUT | 服务响应超时 | | INVALID_APPID | 非法的 AppId (微信 appId 或腾讯云 appId) | | - | - | | INVALID_ACTION | 调用接口名非法 | | EXCEED_REQUEST_SIZE_LIMIT | 请求包体积超限 | | EXCEED_RATELIMIT | 请求频率超过套餐资源限制 | | INVALID_REQUEST_SOURCE | 请求来源非法,请检查 WEB [安全域名配置](https://tcb.cloud.tencent.com/dev?envId=go#/env/safety-source)等。 | | INVALID_COMMON_PARAM | 请求公共参数错误 | | INVALID_PARAM | 请求参数错误 | | SIGN_PARAM_INVALID | 认证参数非法 | | LOGIN_MANNER_UNREGISTED | 使用的登录方式已被关闭 | | APP_SIGN_EXPIRED | 移动应用签名过期 | | INVALID_APP_SIGN | 移动应用签名非法、签名格式错误 | | INVALID_APP_ACCESS | 非法的移动应用访问、移动应用版本未找到 | | CHECK_LOGIN_FAILED | 登录态校验失败、access token 过期(旧) | | ACCESS_TOKEN_EXPIRED | access token 已过期 | | REFRESH_TOKEN_EXPIRED | refresh token 已过期或不存在 | | INVALID_REFRESH_TOKEN | 非法的 refresh token | | REFRESH_TOKEN_EXHAUSTED | 多点登录数量超限 | | INVALID_ENV | 错误的环境、环境未找到 | | INVALID_ENV_STATUS | 环境状态非法、不可用 | | INVALID_ENV_SOURCE | 小程序绑定云开发环境来源非法 | | RESOURCE_NOT_INITIAL | 云资源未初始化完成、云资源不可用 | | EXCEED_REQUEST_LIMIT | 请求次数超限、套餐资源耗尽 | | EXCEED_CONCURRENT_REQUEST_LIMIT | 请求并发超限 | | INVALID_OPERATION | 操作非法,当前状态(资源、账号等)不允许进行相应操作 | | PERMISSION_DENIED | 无操作权限 | | INVALID_THIRDAPP_STATUS | 绑定第三方小程序状态异常 | ## 登录认证 | 错误码 | 含义 | | ---------------------------------- | ------------------------------------------------ | | AUTH_INVALID_CUSTOM_LOGIN_TICKET | 自定义登录凭证非法(格式错误、过期、校验失败等) | | AUTH_WX_OAUTH_FAILED | 微信 OAuth 失败 | | AUTH_CUSTOM_USER_ID_HAS_BEEN_BOUND | CustomUserId 已关联帐户 | | AUTH_OPEN_ID_HAS_BEEN_BOUND | openId 已关联帐户 | | AUTH_UNION_ID_HAS_BEEN_BOUND | unionId 已关联帐户 | | AUTH_EMAIL_HAS_BEEN_BOUND | email 已关联帐户 | | INVALID_EMAIL_TOKEN | 邮箱激活 token 过期或者不存在 | | AUTH_LOGIN_FAILED | 登录失败 | ## 数据库 | 错误码 | 含义 | | --------------------------------- | ---------------------------------------------------- | | DATABASE_REQUEST_FAILED | 数据库请求失败,数据库通用错误 | | DATABASE_INVALID_OPERRATOR | 不支持的操作、非法的数据库操作符 | | DATABASE_PERMISSION_DENIED | 无权限操作数据库资源 | | DATABASE_COLLECTION_EXCEED_LIMIT | 数据库集合数量超限 | | DATABASE_COLLECTION_NOT_EXIST | 操作集合不存在 | | DATABASE_COLLECTION_ALREADY_EXIST | 创建集合的时候,集合已存在 | | DATABASE_TIMEOUT | 数据库请求超时 | | DATABASE_TRANSACTION_FAIL | 数据库事务请求失败 | | DATABASE_TRANSACTION_CONFLICT | 数据库事务间冲突 | | DATABASE_DUPLICATE_WRITE | 写数据库失败,索引键重复(例如插入相同 \_id 的数据) | ## 云函数 | 错误码 | 含义 | | ------------------------------- | ------------------------------ | | FUNCTIONS_EXECUTE_FAIL | 云函数执行失败,云函数通用错误 | | FUNCTIONS_TIME_LIMIT_EXCEEDED | 云函数执行超时 | | FUNCTIONS_MEMORY_LIMIT_EXCEEDED | 云函数运行内存超限 | | FUNCTION_NOT_FOUND | 云函数未找到 | ## 云存储 | 错误码 | 含义 | | -------------------------- | --------------------------------------------------------------------------------------------------------- | | STORAGE_REQUEST_FAIL | 云存储请求失败,云存储通用错误 | | EXCEED_UPLOAD_MAXFILESIZE | 云存储上传文件大小超限 | | STORAGE_SIGN_PARAM_INVALID | 云存储文件元数据解析失败 | | STORAGE_EXCEED_AUTHORITY | 当前用户无权限操作云存储资源,请检查[云存储权限配置](https://tcb.cloud.tencent.com/dev#/storage?tab=auth) | | STORAGE_FILE_NONEXIST | 云存储文件不存在 | | STORAGE_FILE_PATH_CONFLICT | 云存储文件路径冲突 | :::tip 注意 `DATABASE_REQUEST_FAILED`、`STORAGE_REQUEST_FAIL`、`FUNCTIONS_EXECUTE_FAIL` 分别为通用的数据库、云存储请求错误、云函数请求错误,无特殊的语义,未来将细化出独立特征语义的错误码,请避免基于该错误码进行特殊逻辑判断。 ::: --- ## HTTP 访问服务错误码 # HTTP 访问服务错误码 :::tip 🌟 **遇到 HTTP 访问问题?** 点击 [这里](https://tcb.cloud.tencent.com/dev?#/helper/copilot/) 咨询云开发 Copilot,随时为你解答疑惑。📱 微信云开发用户请选择小程序公众号登录 ::: ## 通用错误 ### BAD_REQUEST 请求数据或参数格式非法,请检查访问域名或 Host 是否正确填写,请求头和请求体是否正常设置。 ### ENV_ABNORMAL 环境状态异常,可尝试新建服务版本。 ### INVALID_ENV_ID 环境 ID 非法或没有找到对应的云开发环境,请检查访问域名是否正确。 ### INVALID_HOST 无效或者非法的主机名,原因可能是: 1. 访问域名或 Host 未正确填写; 2. 请求的域名既不是 CloudBase 合法的默认域名,也不是绑定的自定义域名; 3. 请求的域名为自定义域名,但是未配置正确的 DNS 解析; 4. 请求的域名为自定义域名,但是修改了 DNS 解析,还未生效。 可检查域名是否填写正确、是否配置了正确的 DNS 解析,如修改了 DNS 解析,请到域名服务商处查看解析是否生效,或稍等片刻再试。 ### INVALID_PATH 未找到匹配的转发规则,请检查 HTTP 访问服务转发规则配置。 ### SERVICE_FORBIDDEN 服务被禁用,原因可能是: 1. HTTP 访问路径权限被关闭,服务禁止访问。如果想打开相关权限,请前往 [云开发平台](https://tcb.cloud.tencent.com/dev#/env/http-access) 操作; 2. 服务或环境状态不正常,请检查环境是否欠费或被冻结; 3. 使用微信云托管时,服务首次部署成功后,存在 1-3 分钟的启动时间,可等待后再次尝试。 4. 使用微信云托管[资源复用](https://developers.weixin.qq.com/miniprogram/dev/wxcloudrun/src/guide/reuse/)时,携带了不正确的签名信息。 ### HTTPSERVICE_NONACTIVATED 未开启 HTTP 访问服务,请到 [云开发平台](https://tcb.cloud.tencent.com/dev#/env/http-access) 开启服务。 如果已开启服务,请稍后再试。 ### EXCEED_RATELIMIT 请求速率超过所购买套餐的 QPS 配额,您可以通过升级套餐来提高 QPS 配额。 ### EXCEED_MAX_PAYLOAD_SIZE 请求体大小超过限制,云函数请求体超出最大体积限制(文本 100 KB,其他 6 MB)。 ### BAD_GATEWAY 网关传输过程中出现错误,当前仅云托管场景会出现此错误码。请求转发到云托管服务或从云托管接收响应过程中失败,请检查云托管服务负载是否正常,或检查客户端或服务日志。 ### EXCEED_CONCURRENT_REQUEST_LIMIT 调用接口超出并发限制,请稍等片刻再试,或提交工单申请提高并发。 ### EXCEED_TOKEN_QUOTA_LIMIT 大模型 Token 用量已超出配额,请购买资源包以提升配额。 ### ERR_ABORT_HANDLER 该错误的出现有多种原因,若在调用大模型的过程中出现该错误,请尝试以下解决方法: 1. 确保使用流式输出(Server-sent Event)的请求在请求头 `Accept` 中包含 `text/event-stream`,否则请求将在 60 秒后超时; 2. 确保 SSE (Server-sent Event) 响应持续返回数据,避免连接长时间空闲(超过 60 秒)被关闭。可以在 SSE 连接中通过注释行(`comment line`)进行定时心跳保活,例如 `: ping`。详见:[事件流格式](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#event_stream_format)。 若在云托管(函数型)的响应中出现该错误,可尝试重新部署托管服务以升级到内置 SSE 保活的最新框架版本。 ### DEFAULT_DOMAIN_EXPIRED 应安全合规要求,默认域名仅限开发测试使用,当前默认域名已经超过使用有效期,请在云开发平台上点击续期,续期预计 5 分钟内生效。 建议绑定自定义域名使用,避免因平台默认域名可访问性降低带来的服务可用性隐患。 ## 鉴权和认证错误 ### MISSING_CREDENTIALS 请求头中缺少必要的身份鉴权信息,原因可能是: 1. 开启了 HTTP 访问鉴权,但是请求头中没有鉴权信息,请参考 [HTTP 访问鉴权](/service/authentication)。 2. 使用开放 API 访问,但是请求头中没有鉴权信息,请参考 [接入指南](/http-api/basic/guide)。 ### INVALID_CREDENTIALS 身份认证失败,原因可能是: 1. 开启 HTTP 访问鉴权的情况下,请求头中的用户信息校验失败,请参考 [HTTP 访问鉴权](/service/authentication)。 2. 使用开放 API 访问,请求头中的用户信息校验失败,请参考 [接入指南](/http-api/basic/guide)。 ### ACCESS_TOKEN_EXPIRED 请求头中身份认证信息过期,请重新获取认证信息。 ### ACCESS_TOKEN_INVALID 请求头中身份认证信息无效,请检查身份认证信息的格式,或重新获取认证信息。 ### ACTION_FORBIDDEN 请求头中对应的身份无权限执行当前操作,请检查当前身份是否有权限执行该操作,或在云开发平台-扩展能力-云后台管理-[权限控制](/toolbox/acl)-策略管理更新当前角色关联的访问策略。 ### AUTHENTICATION_FAILED 请求鉴权失败,请稍等片刻再试,或提交工单给我们。 ## 云托管相关错误 ### SERVICE_NOT_FOUND 未找到对应的云托管服务,请检查服务是否存在。 ### SERVICE_RESOURCE_NOT_FOUND 未找到对应的资源,请检查服务和版本状态是否正常,或新建版本。 ### SERVICE_VERSION_NOT_FOUND 找不到匹配的云托管服务版本,原因可能是没有创建云托管服务的版本,或新创建的版本还未生效,可稍等片刻再试。 ### SERVICE_ENDPOINT_NOT_FOUND 找不到云托管服务可用的上游地址,原因可能是云托管的所有版本流量均被设置为零。 ### SERVICE_LB_STATUS_ABNORMAL 云托管负载均衡状态异常,可尝试新建版本。 ### SERVICE_CHARGE_OVERDUE 欠费停机,请及时充值。 ### SERVICE_NOT_READY 上游云托管服务处于未就绪状态,服务节点可能已经缩容到 0 或服务版本正在冷启动中,还未能提供正常访问,可稍等片刻再试。 ### SERVICE_TIMEOUT 调用云托管服务超时,可查看云托管服务日志进行排查。 ## 云函数相关错误 ### FUNCTION_NOT_FOUND 未找到对应的云函数,请检查云函数是否存在。 ### FUNCTION_INVOCATION_FAILED 调用云函数超时或者失败,请确认云函数自身逻辑是否存在问题。 错误信息中可能会包含云函数报错的堆栈信息,您也可以通过 [云函数日志](/cloud-function/test-log-monitor) 来查询错误信息。 ## 静态托管相关错误 ### STATIC_RESOURCE_NONACTIVATED 未开启静态网站托管服务,请到 [CloudBase 控制台](https://console.cloud.tencent.com/tcb) 开启服务。 ### STATIC_RESOURCE_TOO_MANY_REDIRECTS 请求重定向次数过多,请检查静态托管服务配置是否存在重定向死循环。 ### STATIC_RESOURCE_REQUESTS_FAILED 请求静态托管资源失败,请稍后再试或提交工单给我们。 ## 云存储相关错误 ### CDN_SIGNATURE_MISSING 当前访问链接的签名缺失,请检查链接是否携带了正确的签名参数。 ### CDN_INVALID_SIGNATURE 当前访问链接的签名不正确,请检查链接携带的签名参数市是否正确。 ### CDN_SIGNATURE_EXPIRED 当前访问链接的签名已过期,请重新生成签名。 ## 系统错误 ### INTERNAL_REQUEST_FAIL 系统内部请求错误,请稍后再试或提交工单给我们。 ### SYS_ERR 系统内部错误,请提交工单给我们。 --- ## 安全域名相关 # 安全域名相关 对网站应用来说,请先登录腾讯云云开发控制台,选择左侧菜单栏【用户管理】>【登录设置】,单击【设置】 添加安全域名。然后才能正常使用云开发的jssdk访问云开发的各项服务,否则会报 **INVALID_REQUEST_SOURCE** 或禁止跨域访问错误,如 ![](https://main.qcloudimg.com/raw/409fd71d1d000e6f100713ac1d5552b7.png) 安全域名不支持模糊匹配,需要填入准确的域名,端口是可选项,不支持填入协议。如localhost:8000或localhost都是合法的安全域名,http://localhost则不是合法的。 系统默认不添加安全域名,所有用到的域名都需要开发者手动添加,如localhost和127.0.0.1等。 --- ## 数据库相关 # 数据库相关 ## 数据库容量达到上限之后怎么办? 为了保证资源的合理利用,CloudBase 对各环境有数据库存储容量的限制。每个环境的数据库存储容量都是独立计算的。 - 如果数据库的剩余存储容量低于 10%,则会通过短信、站内信、邮件等方式进行告知,您可以升级您的环境版本,以享有更多的数据库存储容量,避免影响业务的正常运行。 - 如果该环境的数据库存储容量已用尽,则不允许继续往该数据库写入数据,但可以读取数据及删除数据。 ## 集合创建数量有限制吗? 每个环境最多可创建100个集合。 ## 集合内文档的创建有限制吗? 集合内的文档创建没有限制,不过如果集合内的文档数量较多,建议创建索引,以加快查询和搜索的速度。 ## 索引创建数量有限制吗? 每个集合内最多可创建100个索引,每个索引最多可包含31个字段。 ## 为什么数据库都有 _openid 字段? 每个从 微信客户端 写入的数据,都默认带一个 _openid 字段,用于标识该文档来自哪个用户。 ## 数据库最大并发多少? 基础版最大支持30个并发,超过该限制的请求将阻塞等待。为了保证您的业务顺利,请根据查询条件创建适当的索引,确保查询不要阻塞太长时间。 ## 修改了数据库集合权限后为什么不生效? 后台有数据缓存,最迟1分钟全部生效。 ## 数据库文档 field 格式有何限制? 字母 + 数字 + 下划线 + 点,不超过32位,且不以下划线、/、点开头。 ## 为什么数据库中的部分数据在控制台可以看到,但是在客户端却获取不到? 请检查下集合权限,对于非 “公有读”的权限类型,系统会强制校验 _openid 字段,是否与当前用户身份是否相同。 如果是在控制台添加的数据,属于管理员添加的数据,没有 _openid 信息,因此不属于任何一个用户。这部分数据只能由管理员通过控制台进行编辑,而不支持通过客户端进入写入操作(即使管理员,也不能通过客户端进行写入操作)。 --- ## 环境相关 # 环境相关 ## 如何创建云开发环境? 请参考文档 [开通云开发服务](https://cloud.tencent.com/document/product/876/31614)。 ## 能否创建多个资源环境? 资源环境是您在开发小程序过程中所用到资源集合,包括数据库、文件存储等。 每个环境的资源是独立且相互隔离的,您可以根据自身需求创建多个环境,以用于开发、测试及生产等多种场景。 如果您有多个应用,对应不同的业务数据,也是需要创建多个环境。当前在微信侧(微信开发者工具)可创建两个免费环境,在腾讯云侧可创建一个免费环境。 ## 不同客户端能否使用同一个资源环境? 目前在微信侧创建的环境,可支持开发小程序端和 Web 端;而在腾讯云侧创建的环境暂时只支持开发 Web 端。 ## 环境的 API 调用次数达到上限之后怎么办? 为了保证资源的合理利用,云开发对各环境有 API 调用次数的限制。每个环境的调用次数都是独立计算的,并且以天为单位进行统计。 - 如果当天的 API 调用次数在超过 80%及 90%时,则会通过微信、短信、站内信、邮件等不同方式进行告知,若您开发小程序,是微信侧触发的此告警,则发送渠道为微信,否则为腾讯云。您可以升级您的环境版本,以享有更多的 API 调用次数,避免影响业务的正常运行。 - 如果当天的 API 调用次数已用尽,则调用 API 时,会报【调用次数已达上限】的错误。隔天调用次数重置时,将会恢复至正常状态。 ### 云开发环境是什么概念,不同环境如何切换,数据如何同步 在 SDK 里切换不同环境只需在 init 时传入对应的 env 参数即可。云函数和文件存储可以使用 CLI 工具简化跨环境数据复制的功能, 数据库目前仍需要去控制台导出后再导入到目标环境。 ### 小程序端和腾讯云端的云开发是什么关系 两者都由腾讯云提供云服务支持,目前存在以下差异:在小程序端创建的环境,在两端都可以访问(云函数的管理除外);在腾讯云端创建的环境,只可以在腾讯云端访问 ### 是否可以不通过云控制台管理云开发 使用云开发提供的命令行工具管理云开发资源 --- ## 费用相关 # 费用相关 ## 免费版套餐的环境会到期吗 免费版不需要支付任何费用,提供有限的免费资源,超出用量上限的话本账单周期内(一个月)会停用,下一个账单周期内清零重新计算 ## 付费到期时会直接清空数据吗 云开发升配到期之后,如果没有自行降配到免费版,数据会被清空 ## 资源到期后如何降为免费版? 预付费套餐到期进入隔离期后,只能进行续费操作,不能升降配。如果想降为免费版,需要在到期隔离前操作;如果已经到期隔离,需要先续费一个月,再执行降配操作,未使用时长的相关费用会退还。 ## 免费环境是否需要手动续费? 免费环境不需要用户手动续费,由系统自动续期。 ## 环境到期后,资源是否会保留? 付费环境到期后会进入7天的隔离期,隔离期期间,用户可以续费找回资源,隔离期后系统会销毁环境,且数据不可恢复。所以想保留数据的用户,请及时降配到免费版。 ## 降配退费时,使用的代金券是否退还? 代金券一旦使用,退费时不再退还。 --- ## 云函数相关 # 云函数相关 ## 云函数执行超时怎么处理? 超时客户端会直接断开连接并报错,建议控制函数执行时间,尽量不要把耗时长的操作放在客户端直接调用的云函数内。 ## 云函数内置模块怎么使用? - 云函数内置模块已经集成于运行环境,可以直接使用。 - 如果内置模块的版本不能满足需求,可以自行安装模块到云函数内,默认会被优先使用。 > ?目前已支持的内置模块为 request 2.87.1 。 ## 如果需要在云函数执行一些长耗时的处理怎么办? 为了保证客户端的体验,不允许直接调用长耗时的云函数。 - 建议在云控制台调整为需要的超时时间(上限为 60s),在云函数内使用 callback() 返回成功,客户端不等待执行结果。 - 云函数会在超时时间内继续执行直到完毕或超时,将执行结果写入数据库等存储服务,再在客户端获取该结果。 ## 为什么云函数更新时,返回 exit status 11? 请检查一下函数的打包方式和入口方法。 - 云函数创建时,默认执行方法是 index.main ,其入口文件为 index.js ,且 index.js 必须用 export 暴露出 main 方法。 - 云函数更新时,如果选择用 zip 包上传,打包的方式需要注意,要保证 zip 包解压后的第一级内容必须包含入口文件(常见的错误打包方式是,将某个云函数代码放在某个文件夹内,并针对这个文件夹进行压缩,这样解压出来的文件是一个文件夹,不包含入口文件 index.js )。 ## 云函数测试时,部分日志丢失了? - 云函数测试时,如果以同步调用的方式(超时时间小于 20 秒),返回的日志最多为 4k,超过 4k 的日志不显示。 - 如果以异步调用的方式(超时时间大于或等于 20 秒),返回的日志最多为 6M,超过 6M 的日志不显示。 ## 云函数如何调用云函数 目前只可以通过云开发提供的 SDK 调用,没有其它方式 ## 不同的云函数可以共用代码文件(目录)吗 未上线 ## Node.js 云函数同时支持异步和同步写法吗 是的,推荐使用同步(async/await)写法。 ## 云函数内怎么保存密钥等配置信息 云函数是无状态的,配置信息建议存储在云开发的数据库服务 --- ## 总览 :::tip 🌟 **遇到云开发问题?** 点击 [这里](https://tcb.cloud.tencent.com/cloud-admin#/copilot/) 咨询云开发 云开发 Copilot,随时为你解答疑惑。📱 微信云开发用户请选择小程序公众号登录 ::: # 云开发 CloudBase 使用指南 ## 一、小程序·云开发和腾讯云·云开发的区别 ### 1.云开发 CloudBase 云开发 CloudBase 是概念,它描述了整个生态所有的能力,从平台性角度描述了能力和功能,以及产品矩阵。 云开发 CloudBase 概念下面有「微信·云开发」和「腾讯云·云开发」两种实例产品 ### 2.微信·云开发 「微信·云开发」(之前为小程序·云开发)是联合微信团队打造的,在微信生态上有出色的云原生体现,比如云调用、微信支付、微信侧免鉴权获取信息等等,都是微信侧加持的表现。 「微信·云开发」的标志就是从开发者工具控制台依附于一个小程序下进行创建,在创建时,会以微信公众号(小程序也是公众号的一种)的方式注册一个腾讯云账号(也可以在创建时选择已有腾讯云账号绑定,就不会创建新的账号)。 开发者可以通过 [微信授权](https://cloud.tencent.com/login/mp?s_url=https%3a%2f%2fconsole.cloud.tencent.com%2ftcb%2fenv) 的形式进入到腾讯云官网控制台,在腾讯云云开发控制台,你仍然可以操作云开发环境。 云开发推出的一些新能力,会直观的体现在腾讯云官网控制台。有些能力(比如云函数 HTTP 访问服务)需要经过微信侧团队加持和评估后,才能够在开发者工具控制台中体现。 所以并不是「微信·云开发」没有某些能力,而是控制台中不体现而已。由此可以得出,「微信·云开发」仍然可以做 WEB 等多端开发的事情,而且在微信生态上更胜一筹 ### 3.腾讯云·云开发 「腾讯云·云开发」是独立性实例产品,不需要拥有微信小程序就可以直接在腾讯云官网控制台创建的,也是云开发 CloudBase 能力最先应用的环境。 **一般我们说云开发支持一些能力,基本上都是说的「腾讯云·云开发」**(小程序·云开发具体显性支持还需要和微信侧团队评审打通) 「腾讯云·云开发」还在多端支持上有出色的优势,目前和其他小程序做的免鉴权打通都是从腾讯云·云开发侧触发的。**_比如 QQ 小程序,只支持腾讯云·云开发,不支持微信·云开发。_** 所以当你不太依赖微信生态,做多端应用时,建议使用「腾讯云·云开发」。 目前,我们和多个框架展开合作,从框架侧开通的云开发环境均属于「腾讯云·云开发」。 ## 二、云开发 SDK 及能力相关 ### 1、 微信·云开发开发微信小程序 如果你使用的是微信·云开发,开发微信小程序! 推荐小程序端使用 wx.cloud 、云函数端使用 wx-server-sdk 文档均在 [微信官方文档](https://developers.weixin.qq.com/miniprogram/dev/wxcloud/basis/getting-started.html) ### 2、腾讯云·云开发开发微信小程序 如果你想使用「腾讯云·云开发」,开发微信小程序。有两种可选方式: 1. 你的「腾讯云·云开发」环境所属腾讯云账号绑定了目标小程序。可以直接在腾讯云控制台进行环境转换,具体参见 [文档](https://cloud.tencent.com/document/product/876/41391) ,转换后你可以在小程序中直接使用 wx.cloud 的形式来使用该环境,但是你无法在小程序开发者工具的云开发控制台中管理。 2. 你的「腾讯云·云开发」环境所属腾讯云账号没有绑定目标小程序,建议如下使用:小程序端使用 [JS-SDK](/api-reference/webv3/initialization) ,此 SDK 已经集成微信小程序适配器支持,可直接使用,需要配置移动安全来源(应用标识应填写小程序 appid ),使用代码如下: ![](https://main.qcloudimg.com/raw/18969e4996de60d3daa367da9efdf206.png) :::tip 注意 不使用微信侧 SDK ,就意味着自己放弃微信免鉴权的加持,需要独自搭设 openid 系统程序,除非你做多端应用开发,否则不建议这么做。 ::: 云函数端使用 [Node-SDK](/api-reference/server/node-sdk/introduction) ,直接使用即可,不需要加 key 密钥等信息。 ### 3、腾讯云·云开发开发 QQ 小程序 小程序端使用 [qq.cloud](https://q.qq.com/wiki/cloud/base/intro.html) ,和微信小程序使用体验一致。 云函数端使用 [qq-server-sdk](https://q.qq.com/wiki/cloud/server-sdk/) ,和微信使用体验一致,具体差异看文档描述。 在开发 QQ 小程序时,有一个绑定腾讯云账号的过程,在这里就是绑定的腾讯云侧云开发环境,即使你绑定的腾讯云账号中包含「微信·云开发」环境,也不支持 QQ 小程序开发。 也就是说,QQ 小程序只支持「腾讯云·云开发」环境。 ### 4、微信·云开发开发公众号网页 微信·云开发可使用环境共享能力将环境共享给公众号使用,具体表现就是公众号网页可以原生登录,并且云函数可以免鉴权调用公众号服务端能力。 环境共享具体可以参照 [官方文档](https://developers.weixin.qq.com/miniprogram/dev/wxcloud/guide/resource-sharing/) ,公众号网页登录的官方示例 [在此](https://developers.weixin.qq.com/miniprogram/dev/wxcloud/guide/web/minimal-example/) ,还需要编写云函数  cloudbase_auth 。 有一个 [简单的 DEMO](https://github.com/TCloudBase/WXH5-TodoList) ,可以帮助大家快速上手。在 DEMO 中有封装好的登录模块,大家可以根据自己的需要修改使用。 小程序·云开发原生支持的公众号只限于有 [网页授权](https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html) 能力的公众号,目前只有已认证的服务号才可以,其他的公众号目前暂不支持,共享环境也没有什么实质的用处。 另外,**非个人主体**的小程序·云开发静态网站托管,可以无需 config 直接打开任意小程序,具体实现文档参照 [官方示例](https://developers.weixin.qq.com/miniprogram/dev/wxcloud/guide/staticstorage/jump-miniprogram.html) 最后,可以用「微信·云开发」来做公众号接收消息,被动回复消息,还有模版消息发送的能力,具体使用参见 [微信官方文档](https://developers.weixin.qq.com/miniprogram/dev/wxcloud/basis/web.html) 如果你想要自己实现公众号消息和模版发送能力,可以参照 [云开发支持公众号示例 DEMO](https://github.com/TCloudBase/WXH5-PUBLIC) 。 ### 5、所有的云开发开发普通 WEB 以及 APP 应用 不管是「腾讯云·云开发」还是「微信·云开发」,都支持普通 WEB 和其他应用的开发。 WEB 开发或者是以 JS 为基础的应用开发,基本上就使用 [JS-SDK](/api-reference/webv3/initialization) ,有特殊的语言和框架需求的,可以直接使用 [http api](/http-api/basic/overview) 自己搭建。 云函数端基本上使用 [Node-SDK](/api-reference/server/node-sdk/introduction) ,如果有一些更高级的需求,比如批量管理什么的,就使用 [manage-sdk](/api-reference/manager/node/initialization) ,还是缺少直接发送需求到 Cloudbase@tencent.com ,我们会及时评估。 欢迎各位贡献 SDK ,如果有 SDK 贡献,可以发送 SDK 的 github 仓库链接和相关描述信息到 Cloudbase@tencent.com ,我们在审核之后给予收录,并将你纳入布道师体系换算积分。 ## 三、云开发计费有关说明 在小程序控制台中,会看到有腾讯云扣费和微信侧扣费两种,而腾讯云扣费又分为包年包月和按量计费。 在这里,腾讯云扣费指的就是通过微信授权登录到腾讯云官网里,从腾讯云侧余额中做扣费。而微信侧扣费只是通过微信支付扫码来进行扣费。 另外,按量计费必须是腾讯云扣费,虽然每个小程序下有两个免费额度,但是如果超过额度,则需要前往腾讯云官网充值保证余额充足,否则就可能停服。 你可以通过在自己的主腾讯云账号个人信息中绑定微信公众平台(小程序侧腾讯云账号),则可以使用主腾讯云账号余额。 ## 四、关于云开发相关问题 ### (1)只要是「微信·云开发」环境就可以使用云调用吗? 微信云函数中使用云调用必须满足三个使用条件: 1. 「微信·云开发」环境或转换后的「腾讯云·云开发」环境的云函数 2. 云函数使用 wx-server-sdk (其他的不支持) 3. 部分云调用接口必须有真实用户调用(比如小程序码) 微信云托管中使用云调用满足一个使用条件: 1. 「微信·云托管」所属环境属于或被共享于目标小程序 从严格意义来说,云托管的云调用,其实是为服务端调用提供了令牌,此令牌无需开发者管理;所以开发者可以直接正常调用服务端接口,或者使用云托管官方提供的封装服务。 ### (2)云托管品牌升级为微信云托管,和云开发有什么区别和联系? 之前「微信·云开发」内的云托管和「微信·云托管」的区别除了品牌升级外,还做了独立的控制台,原有的容器引擎升级为完整的后端项目托管解决方案。从代码管理到 CI/CD 流水线部署发布,提供全链路、低成本、企业级的云原生解决方案,功能更强大、体验更友好。 以上总结一下,目前来看「微信·云开发」和「微信·云托管」都是微信联合腾讯云打造的「微信云服务」生态的组成部分,都提供了免服务器免运维的能力,而云开发主要是面向前后端一体化架构的场景,更适合个人开发者全栈开发;云托管主要是面向前后端分离架构的场景,不限语言不限框架,对团队协作和企业级应用场景更友好,两者也可以组合进行使用。 这里给一些 DEMO 入门示例项目,供大家学习: - [微信·云托管官方案例合集](https://developers.weixin.qq.com/miniprogram/dev/wxcloudrun/src/example/SpringBoot.html) - [微信·云托管入门| Node DEMO](https://github.com/TCloudBase/wxcloudrun_minidemo) - [微信·云托管入门| SpringBoot DEMO](https://github.com/TCloudBase/springboot_demo) - [小程序商城案例 DEMO](https://github.com/TCloudBase/WXAPP-SHOP-CONTAINER) ### (3)小程序·云开发有关于微信支付的例子吗? 请参考微信支付演示[DEMO](https://github.com/TCloudBase/WXAPP-PAY) 云开发还提供了 [分账服务](https://developers.weixin.qq.com/miniprogram/dev/wxcloud/guide/wechatpay/profitsharing.html) ,如果有需要可以填写申请。 ## 五、更新说明 - 更新时间:2021 年 7 月 7 日 - 更新描述:根据云开发形态发展会不定期更新 - 以上内容仍然找不到解决方案的,推荐去社区提问: - 「腾讯云·云开发」相关:[腾讯兔小巢](https://support.qq.com/products/148793) (云开发能力相关的首选这里) - 「微信·云开发」相关:[微信开放社区](https://developers.weixin.qq.com/community/minihome/mixflow/1286298401038155776) (微信相关的都在这里问) - 「微信·云托管」相关:[微信开放社区](https://developers.weixin.qq.com/community/minihome/mixflow/1919566493118201863) (云托管相关的都在这里问) - 关注「腾讯云云开发」公众号,回复关键词「加群」,加入各个产品能力官方交流群 --- ## 微搭中怎么同时引用顶部布局和 Tab 栏布局 # 微搭中怎么同时引用顶部布局和 Tab 栏布局 微搭编辑器布局设计模板提供了“工字导航布局”。 ![image.png](http://git.woa.com/QBase/cloudbase-docs/uploads/B08970E8270A4AE28015BBB2ACDB472D/image.png) 通过以上步骤,你就可以在微搭中同时引用顶部布局和 Tab 栏布局,创建出功能丰富、界面美观的页面。 ## 相似问题 - 微搭编辑器中如何添加顶部布局? - 如何在微搭中设置 Tab 栏布局? - 微搭的工字导航布局是如何工作的? - 如何在微搭中同时使用顶部布局和 Tab 栏布局? - 微搭编辑器中布局设计的步骤是什么? - 在微搭中创建页面布局时需要注意什么? - 微搭中的工字导航布局适用于哪些场景? - 如何在微搭编辑器中调整布局? - 微搭编辑器支持哪些类型的布局? - 如何在微搭中实现复杂的页面布局? --- ## APIs 自定义代码与第三方库支持 # APIs 自定义代码与第三方库支持 APIs 的自定义代码默认不支持引入第三方库。自定义代码中内置了标准的 Node.js 库以及 `node-fetch`、`request`、`@cloudbase/node-sdk` 及其相关依赖库。这些内置库可以通过 `require` 方式引用并在代码中使用。 ## 解决方案 如果需要引入第三方库,除了使用自定义代码外,还可以选择直接对接使用云开发云函数。在创建 APIs 时,可以选择使用云函数作为执行后端。 ### 云开发云函数的优势 - **多语言支持**:云函数不仅限于 Node.js,还可以使用 Python、PHP、Golang、Java 等语言进行开发。 - **自由引入依赖**:云函数允许开发者自行引入所需的依赖库。 - **网络配置灵活**:云函数可以通过网络配置,打通腾讯云 VPC 网络,对接已有的云上资源、数据库等。 - **超时时间控制**:云函数允许开发者自行控制超时时间,允许代码或任务运行更长时间。 - **预置并发配置**:云函数可以通过配置预置并发,保持实例运行,提升请求响应的速度。 ## 相似问题 - APIs 自定义代码能引入第三方库吗? - 如何解决 APIs 自定义代码无法引入第三方库的问题? - 云开发云函数支持哪些编程语言? - 云函数的依赖库可以自由引入吗? - 云函数的网络配置有什么优势? - 云函数能控制超时时间吗? - 云函数的预置并发配置有什么作用? - 云函数相比自定义代码有哪些好处? - APIs 自定义代码内置了哪些库? - 怎样将 APIs 对接到云开发云函数? --- ## 如何升级套餐? # 如何升级套餐? 如您是云开发免费期或微搭体验版用户,发布应用后,会在顶部看到以上红色升级提示 ![](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/e4b16f6f-8dcb-4c43-bac5-e6032b55e4f6.png) 如需移除该提示,您需要升级至任意付费版套餐。 登录云开发平台,进入[套餐用量模块](https://tcb.cloud.tencent.com/dev#/env/package-usage/basic),选择升级套餐。 购买完成后,重新发布应用即可看到红色升级提示已消失。 --- ## 微搭应用误删后是否可以恢复? # 微搭应用误删后是否可以恢复? 微搭应用如果被误删,是可以恢复的。为了恢复应用,您需要提供以下信息并联系云开发小助手提供支持: - **腾讯云账号** (`Uin`) - **微搭环境 ID** (`EnvId`) - **需要恢复的微搭应用 ID** (`AppId`) (如不记得,可提供应用的名称等信息) 您可以通过以下链接联系云开发小助手:[点击这里](https://t.1yb.co/KJ10) 请注意,恢复应用可能需要一定的时间,并且应尽快采取行动以确保数据不会丢失。确保您保存了所有相关的账号和环境信息,以便在需要时提供。 ## 使用 Git 模式进行版本控制 为了避免未来发生误删或其他问题,建议您开启并使用 Git 模式。Git 模式允许您将应用连接到 Git 托管提供商(例如 GitHub、Coding)来为您的应用提供版本控制功能。这使得跟踪更改、回滚更改或使用 Git 分支进行协作变得更加简单。 ### 如何开启 Git 模式 - **访问 Git 模式文档**:详细的 Git 模式使用指引可以在腾讯云官方文档中找到:[Git 模式](https://cloud.tencent.com/document/product/1301/104391) - **连接 Git 托管服务**:按照文档指引,将您的微搭应用与 Git 托管服务连接起来。 - **配置 Git 仓库**:确保您的 Git 仓库已经设置好,并且您有权限对其进行操作。 - **启用 Git 模式**:在微搭平台中,找到您的应用设置,并启用 Git 模式。 通过 Git 模式,您可以更有效地管理您的微搭应用代码,确保每次部署都是经过验证的,并且可以轻松回滚到之前的版本。 ## 相似问题 - 微搭应用误删后怎么恢复? - 恢复微搭应用需要提供哪些信息? - 如何联系云开发小助手? - 微搭应用误删恢复要多久? - 怎样避免微搭应用误删? - Git 模式对微搭有什么作用? - 如何开启微搭的 Git 模式? - 开启 Git 模式有哪些步骤? - Git 模式能进行版本控制吗? - 微搭应用代码如何有效管理? --- ## 微搭中能集成大模型知识引擎吗? # 微搭中能集成大模型知识引擎吗? 暂时不支持,后续会推出函数型云托管,这种方式能支持流式输出。 现在的微搭中的 APIs 设计在链路上和实现上都无法支持流式输出。 ## 相似问题 - 微搭目前能集成大模型知识引擎吗? - 微搭未来怎么支持大模型知识引擎? - 函数型云托管 对微搭集成大模型有何作用? - 为什么现在微搭的 APIs 不支持流式输出? - 微搭 APIs 的设计为何无法支持流式输出? - 微搭后续推出函数型云托管 能解决什么问题? - 函数型云托管 怎样实现流式输出支持? - 微搭集成大模型知识引擎有哪些限制? - 微搭在链路和实现上为何不支持流式输出? - 微搭未来对大模型知识引擎的支持计划是什么? --- ## 云后台和应用的关系 # 云后台和应用的关系 云后台的应用主要包括以下几类: 1. **系统内置的模块**:例如 CMS(内容管理系统),这类模块为开发者提供了内容创建、发布和管理等功能。 2. **云模板安装的应用**:云模板是一种预先配置好的应用模板,开发者可以通过安装云模板快速搭建应用,无需从零开始开发。 3. **微搭开发的应用**:微搭是腾讯云提供的一种低代码开发平台,开发者可以通过微搭快速构建和部署应用,利用云开发提供的云函数、数据库、存储等服务。 云后台和应用之间的关系是相辅相成的。云后台提供了应用运行所需的基础设施和资源,而应用则利用这些资源来实现具体的功能,服务用户。 ## 相似问题 - 云后台的应用主要有哪些类别? - 系统内置模块在云后台中有什么作用? - 云模板安装的应用有何优势? - 微搭开发的应用怎么利用云服务? - 云后台和应用的关系是怎样的? - 云后台为应用提供了哪些基础设施? - 应用如何借助云后台的资源服务用户? - 云模板应用和微搭应用的差异是什么? - 系统内置模块能进行内容管理吗? - 微搭开发的应用有哪些具体功能? --- ## 云函数等在线开发功能无法正常使用 # 云函数等在线开发功能无法正常使用 ## 问题原因 云开发平台中的在线开发使用的编辑器是 CloudStudio,并依赖于“Tencent CloudBase Toolkit V2”扩展来实现云开发的在线开发能力。因此需要确保“Tencent CloudBase Toolkit V2”这一扩展始终是最新版本 ## 解决方式 1. 尝试重新打开在线编辑器 当您重新打开在线编辑器时,系统会自动检测并更新扩展,更新成功后会提示刷新,如下图所示: ![](https://qcloudimg.tencent-cloud.cn/raw/b4157e12162f5ffd0177526b520b3675.png) ![](https://qcloudimg.tencent-cloud.cn/raw/e2d5651379ab175fd3d1a6af1678589d.png) 2. 手动更新扩展 有时候,由于扩展市场的网络问题可能导致自动更新失败,在这种情况下,您可以尝试手动更新扩展,如下图所示: ![](https://qcloudimg.tencent-cloud.cn/raw/4c206aa83602a909f9acb9a16fbfff33.png) 如果更新依然失败,可以按照提示将扩展下载到本地,然后将其拖到编辑器中进行安装,如下图所示: ![](https://qcloudimg.tencent-cloud.cn/raw/4febb2e79a9fdbc5d9f0b6bee5ff1320.png) --- ## 云存储文件突然不能访问了 # 云存储文件突然不能访问了 当遇到云存储文件无法访问的情况时,可以按照以下步骤进行问题定位和解决: 1. **检查云存储权限配置**: 确保云存储的权限配置正确,特别是是否设置了公有读权限。错误的权限设置可能导致文件无法被正确访问。 2. **检查云开发套餐的 CDN 流量**: 前往云开发控制台,查看当前云开发套餐的 CDN 流量使用情况。如果 CDN 流量已用完,可能会导致文件访问受限。 3. **开启超限按量计费**: 如果 CDN 流量确实已用完,可以通过以下路径开启超限按量计费,以继续使用云存储服务: - 微信开发者工具 -> 云开发控制台 -> 设置 -> 环境设置 -> 按量计费 按照以上步骤操作后,云存储文件访问问题通常可以得到解决。如果问题依旧存在,建议查阅微信云开发官方文档或联系技术支持获取进一步帮助。 ## 相似问题 - 云存储文件不能访问怎么办? - 云存储权限配置错误会导致什么后果? - 如何查看云开发套餐的 CDN 流量使用情况? - CDN 流量用完如何继续使用云存储服务? - 云存储文件访问问题在哪解决? - 云存储超限按量计费在哪开启? - 云存储文件无法访问的原因有哪些? - 如何检查云存储权限配置是否正确? - 云开发控制台在哪查看 CDN 流量? - 云存储文件访问问题联系谁获取帮助? --- ## 云托管相关问题 # 云托管相关问题 ## 部署新版本后,云托管旧版本实例为什么不会自动销毁? 创建新版本实例后,旧版本实例不能立即缩容,否则已有连接和新版本未成功启动前的流量都会报错。 如果线上存在多个版本,且均有流量,将不会自动缩容。 实例缩容需满足以下两个条件: - 三十分钟无流量(最小副本数设置为0才生效) - 下线延迟缩容(版本无流量) 需要注意的是:配置的最大副本数控制的是**单个**版本的pod,如果有多个版本存在,则: `最大pod数` = `配置的最大副本数` × `版本数` 通过手动删除旧版本也可实现强制缩容。 ## 从监控看CPU和内存使用率均未到达设置的扩容限制,云托管为什么会自动扩容? 监控中您可以看到CPU和内存使用率。但是监控中的内存使用率,并不包含Page Cache。 Page Cache中的数据是也是占用内存的,如使用率一直在设置值以上,将导致无法缩容。 了解Page Cache: - 在Kubernetes中,Pod内存中的Cache通常是指应用程序使用的Page Cache。 - 当应用程序读取或写入文件时,Page Cache会缓存文件数据和元数据,以提高文件访问的性能。 - 如果Pod中的应用程序频繁读写大量的文件,Page Cache可能会占用大量的内存,导致Pod的内存使用率过高 ## 相似问题 - 部署新版本后云托管旧版本实例为何不自动销毁? - 云托管旧版本实例满足什么条件才会缩容? - 云托管自动扩容的原因是什么? - Page Cache 对云托管内存使用率有何影响? - 如何手动实现云托管旧版本的强制缩容? - 云托管中最大副本数如何计算? - 云托管监控的内存使用率为什么不准确? - 怎样避免云托管不必要的自动扩容? - 云托管中 Page Cache 是什么? - 云托管多版本时副本数如何控制? --- ## 云开发数据库如何修改存储的时区 # 云开发数据库如何修改存储的时区 云开发数据库没有时区概念,以时间戳形式存储,您可以使用服务端时间。 ## 相似问题 - 云开发数据库如何设置时区? - 云开发数据库时间存储形式是什么? - 云开发数据库中如何处理时区问题? - 云开发数据库可以使用本地时间吗? - 云开发数据库时间戳如何转换为时区时间? - 云开发数据库存储的时间是全国统一的吗? - 云开发数据库如何获取准确的时间? - 云开发数据库时间戳有什么作用? - 云开发数据库不支持时区设置怎么办? - 云开发数据库时间如何进行时区转换? --- ## 体验版或团队版能否使用数据库(MySQL型) # 体验版或团队版能否使用数据库(MySQL型) 在云开发平台-数据库-数据模型中,所有版本套餐均可使用数据库(MySQL型) # 什么版本能支持连接自有MySQL数据库 在云开发平台-数据库-数据模型中,所有版本套餐均支持连接自有MySQL数据库 # 什么版本可以支持连接已有的SQLServer数据库? 公有云需要企业版及以上可以通过开白名单方式开通sql server连接器功能,但只支持连接腾讯云数据库的sql server数据库,不支持连接客户自建的。 本地部署版本可支持连接用户自建数据库,用户需自己准备服务器。目前该版本按开发者人数计费,一个人一年5000,第一年优惠2000/年。 ## 相似问题 - 体验版或团队版可以使用数据库(MySQL型)吗? - 哪个版本能支持连接自有MySQL数据库? - 什么版本可以支持连接已有的SQLServer数据库? - 公有云连接腾讯云数据库的sql server数据库有什么要求? - 本地部署版本连接用户自建数据库怎么收费? - 云开发平台所有版本套餐都能连接自有MySQL数据库吗? - 企业版及以上如何开通sql server连接器功能? - 本地部署版本支持连接哪些类型的数据库? - 云开发平台中数据库数据模型的版本限制有哪些? - 云开发平台对连接自建SQLServer数据库有何限制? --- ## 微搭数据列表如何展示关联字段 # 微搭数据列表如何展示关联字段 在微搭中,数据列表是展示数据的主要方式之一。如果你想在数据列表中展示关联字段,可以按照以下步骤进行 ## 方法 1 在表达式弹窗中快速引用关联模型需要展示的字段 ![image.png](http://git.woa.com/QBase/cloudbase-docs/uploads/E2BAA5A990574C72B85A887A6BCC98B2/image.png) ## 方法 2 关联模型字段显示表达式格式: ``` $w.item_listView1['@主模型关联字段'].v1.record.关联模型字段 ``` **主模型字段**:数据列表配置的数据模型与另外一个模型进行关联的字段 **关联模型字段**:被关联的数据模型,想要展示哪个字段,就填哪个字段 ## 相似问题 - 微搭数据列表中如何展示关联字段的方法有哪些? - 微搭数据列表展示关联字段的表达式格式是什么? - 在微搭中如何快速引用关联模型字段进行数据列表展示? - 微搭数据列表关联字段展示中主模型字段是什么? - 微搭数据列表关联字段展示中关联模型字段怎么填写? - 微搭中数据列表能否展示关联模型的字段? - 微搭数据列表展示关联字段有没有快捷方式? - 微搭数据列表关联字段的表达式中各部分代表什么? - 微搭里怎么通过表达式在数据列表展示关联字段? - 微搭数据列表怎样设置才能展示关联字段? --- ## 微搭支持websocket吗? # 微搭支持websocket吗? WebSocket是一种网络通信协议,它允许在单个TCP连接上进行全双工通信。 微搭中暂时不支持websocket协议。 ## 相似问题 - 微搭支持WebSocket协议吗? - 微搭是否提供了WebSocket的支持? - 在微搭中使用WebSocket有什么限制? - 微搭未来会不会支持WebSocket? - 微搭不支持WebSocket该怎么办? - WebSocket协议在微搭中的应用情况如何? - 微搭对WebSocket的态度是什么? - 微搭有没有计划添加WebSocket支持? - 为什么微搭不支持WebSocket? - 在微搭中如何实现类似WebSocket的功能? --- ## 微搭的域名,为什么不能设置在企业微信中,进行网页回调? # 微搭的域名,为什么不能设置在企业微信中,进行网页回调? 默认域名建议仅用来开发测试,该域名有被运营商屏蔽的风险。 如果应用需要正式上线提供服务,请申请自定义域名。 企业微信集成微搭必须设置为自定义域名,如何配置自定义域名请[参考](https://cloud.tencent.com/document/product/1301/70110) ## 相似问题 - 微搭的默认域名为什么不能用于企业微信网页回调? - 微搭在企业微信集成中必须使用自定义域名吗? - 如何为微搭申请自定义域名以用于企业微信集成? - 微搭默认域名有什么风险? - 企业微信集成微搭时自定义域名怎么配置? - 为什么企业微信集成微搭不能使用默认域名? - 微搭自定义域名设置对企业微信集成有何重要性? - 微搭默认域名会被运营商屏蔽吗? - 如何避免微搭域名在企业微信集成中被屏蔽? - 微搭自定义域名的申请流程是怎样的? --- ## 为什么云函数中会报错 errMsg: urlscheme.generate:fail env status is isolated # 为什么云函数中会报错 errMsg: urlscheme.generate:fail env status is isolated 完整报错信息如下:cloud.js:16 Uncaught (in promise) Error: errCode: -1 | errMsg: cloud.callFunction:fail Error: errCode: -504002 functions execute fail | errMsg: Error: errCode: -501001 resource system error | errMsg: urlscheme.generate:fail env status is isolated 请前往云开发AI小助手查看问题:https://tcb.cloud.tencent.com/cloud-admin#/copilot?q=INVALID_ENV at callGeneralOpenAPI (/var/user/node_modules/wx-server-sdk/index.js:425:19) errMsg中可以看到"env status is isolated",证明当前环境已经处于隔离状态。 解决方案是,前往云开发控制台,找到已隔离的环境,进行续费操作,即可恢复。 需要注意的是,云函数初始化时如果使用以下方式初始化`cloud.DYNAMIC_CURRENT_ENV`将会默认使用环境列表中的第一个环境。您可以按以下方式`cloud.init({env:'环境id'})`显式指定环境id, ## 相似问题 - 云函数中报错 errMsg: urlscheme.generate:fail env status is isolated 是什么原因? - 云函数出现 env status is isolated 报错怎么解决? - 云函数报错显示环境已隔离如何处理? - 云函数中遇到 env status is isolated 错误怎么办? - 云函数初始化时如何避免 env status is isolated 错误? - 云函数报错 urlscheme.generate:fail env status is isolated 如何恢复环境? - 云函数中 env status is isolated 报错与环境初始化有关吗? - 云函数报错 env status is isolated 后如何指定环境id? - 云函数出现 urlscheme.generate:fail env status is isolated 是环境有问题吗? - 云函数中 env status is isolated 错误提示是什么意思? --- ## 资源包存储超限说明 # 资源包存储超限说明 - 当资源包的文件量超过套餐额度会导致文件存储服务被暂停,文件可能无法上传,您将无法上传、下载或访问任何存储在云端的文件 - 若需要更大的文件量存储,建议先升级您的套餐。 ## 相似问题 - 资源包存储超限会发生什么情况? - 资源包文件量超过套餐额度怎么解决? - 资源包存储超限后如何恢复文件存储服务? - 怎样避免资源包存储超限? - 资源包存储超限能否继续上传文件? - 资源包存储超限对下载文件有何影响? - 资源包存储超限时如何访问云端文件? - 资源包存储超限需要升级套餐吗? - 升级套餐能解决资源包存储超限问题吗? - 资源包存储超限是怎样的错误提示? --- ## 使用云编辑器调试云函数时依赖包找不到 # 使用云编辑器调试云函数时依赖包找不到 当使用云编辑器调试云函数时,若提示依赖包找不到,如提示找不到 `wx-server-sdk` ,可按以下步骤处理: **解决步骤**: 1. 修改 `/workspace/pnpm-workspace.yaml` 文件,添加缺少的目录,或直接写成 `'*/*'` ,示例如下: ```yaml packages: - '*/*' ``` 2. 若在左侧资源管理器看不到此文件: - 点击【终端】>【新建终端】打开终端。 - 执行 `cloudstudio /workspace/pnpm-workspace.yaml` 命令打开文件。 ## 相似问题 - 云函数调试时提示依赖包缺失如何解决? - 云编辑器调试云函数找不到依赖包怎么办? - 调试云函数提示依赖包不存在怎么处理? - 云函数调试中依赖包找不到的解决方法? - 如何应对云编辑器调试云函数的依赖包缺失? - 云编辑器里云函数调试依赖包找不到咋办? - 调试云函数时依赖包找不到怎么破? - 云函数调试提示依赖包缺失有何对策? - 怎样处理云编辑器调试云函数的依赖包找不到? - 云编辑器调试云函数依赖包缺失的解决办法? --- ## 数据模型中如何查询id列的最大值 # 数据模型中如何查询id列的最大值 系统默认的数据标识(_id)为字符串类型,其排序规则是根据ascii码的顺序。 如需查询id列的最大值,您需要按id列降序排列后,获取第一条数据 ```js const { data } = await models.post.list({ filter: { where: {}, }, orderBy: [ { _id: "desc", // 按照_id降序排列 }, ], pageSize: 1, // 分页大小,建议指定,如需设置为其它值,需要和 pageNumber 配合使用,两者同时指定才会生效 pageNumber: 1, // 第几页 getCount: true, // 开启用来获取总数 }); ``` ## 相似问题 - 数据模型中如何获取id列的最大值? - 在数据模型里怎样查询id的最大值? - 数据模型中查询id列最大值的代码示例有哪些? - 怎么通过数据模型获取id的最大数值? - 数据模型查询id最大值要用什么方法? - 如何在数据模型中找出id列的最大值? - 数据模型里id列最大值的查询步骤是什么? - 怎样实现数据模型中id列最大值的查询? - 数据模型中求id列最大值的具体操作是怎样的? - 在数据模型中查询id最大值的技巧有哪些? --- ## 在微搭可视化开发中添加 vConsole # 在微搭可视化开发中添加 vConsole 在微搭可视化开发中引入外部 JavaScript 库(例如 `vConsole`)可以通过以下步骤完成: ## 步骤一:获取外部 JS 库的链接 首先,你需要获取外部 JS 库的 CDN 链接。例如,`vConsole` 的 CDN 链接如下: - `vConsole` JS 文件:[https://unpkg.com/vconsole@3.13.0/dist/vconsole.min.js](https://unpkg.com/vconsole@3.13.0/dist/vconsole.min.js) - `vConsole` CSS 文件(可选):[https://unpkg.com/vconsole@3.13.0/dist/vconsole.min.css](https://unpkg.com/vconsole@3.13.0/dist/vconsole.min.css) ## 步骤二:在微搭中添加外部资源 1. **登录微搭编辑器**,进入你的项目。 2. **点击打开“设置”**,然后选择“开发设置”。 3. **在“开发设置”页面中**,找到“外部资源”部分。 4. **点击“添加外部资源”**,在弹出的对话框中输入以下信息: - **资源类型**:选择 `JS` 或 `CSS`,根据你需要引入的文件类型。 - **资源链接**:粘贴你获取到的 CDN 链接。 5. **点击“确定”**,保存你的设置。 ## 步骤三:验证引入 1. **保存并预览你的应用**,确保外部资源已经成功加载。 2. **打开浏览器的开发者工具**,在控制台中你应该能看到 `vConsole` 的相关信息。 3. **在应用运行时**,初始化 `vConsole`: ```javascript // 在页面加载时初始化 vConsole export default function ({ event, data }) { if (typeof VConsole !== "undefined") { new VConsole(); } } ``` 通过以上步骤,你就可以在微搭可视化开发中成功引入并使用 `vConsole`。 ## 相似问题 - 如何在微搭可视化开发中引入其他外部 JavaScript 库? - 微搭可视化开发如何支持外部 CSS 文件的引入? - 在微搭中添加外部资源后如何验证是否成功? - vConsole 在微搭可视化开发中的使用场景有哪些? - 如何在微搭项目中使用 vConsole 进行调试? - 微搭可视化开发的“开发设置”中如何配置外部资源? - 在微搭中引入 vConsole 是否需要额外配置? - 微搭可视化开发支持哪些方式添加外部资源? - vConsole 的 CDN 链接在哪里可以找到? - 如何在微搭项目中初始化 vConsole? --- ## 怎么在小程序中调用 AI 大模型 # 怎么在小程序中调用 AI 大模型 在微信小程序中调用 AI 大模型,可以通过微信小程序基础库内置的云开发 AI+ 能力来实现。以下是详细的步骤指南: ## 一、准备工作 1. **开通云开发环境**: - 登录腾讯云控制台,开通云开发环境,获取 `envId`。 2. **初始化云环境**: - 在小程序的 `app.js` 文件中,初始化云环境。 ```javascript wx.cloud.init({ env: "your-env-id", // 替换为你的云开发环境ID }); ``` ## 二、调用 AI 大模型 1. **使用 `wx.cloud.extend.AI` 调用 AI 功能**: - 在需要调用 AI 大模型的页面或组件中,使用 `wx.cloud.extend.AI` 提供的 API 进行调用。 - 例如,调用 `hunyuan` 模型进行文本生成: ```javascript const hy = wx.cloud.extend.AI.createModel("hunyuan"); // 创建模型 const res = await hy.streamText({ data: { model: "hunyuan-lite", messages: [ { role: "user", content: "hi", }, ], }, }); for await (let str of res.textStream) { console.log(str); // 打印生成的文本 } for await (let event of res.eventStream) { console.log(event); // 打印每次返回的完整数据 } ``` ## 相似问题 1. 在小程序中调用 AI 大模型需要什么条件? 2. 如何开通微信云开发的 AI+ 能力? 3. 小程序中调用 AI 大模型的步骤是什么? 4. `wx.cloud.extend.AI` 提供哪些 API? 5. 如何在小程序中使用 `hunyuan` 模型? 6. 调用 AI 大模型时如何初始化云环境? 7. 调用 AI 大模型的代码示例有哪些? 8. 调用 AI 大模型时需要注意什么? 9. 调用 AI 大模型的返回结果如何处理? 10. 调用 AI 大模型的性能如何? 希望以上信息能帮助您更好地理解如何在微信小程序中调用 AI 大模型。如有其他问题,请随时提问! --- ## 如何使子账号只能创建自己的微搭项目,但是不能访问别人的或者主账号创建的项目? # 如何使子账号只能创建自己的微搭项目,但是不能访问别人的或者主账号创建的项目? 可以通过腾讯云账号的CAM策略实现,具体可[参考](https://cloud.tencent.com/document/product/1301/82617#.E5.9C.BA.E6.99.AF.E4.B8.89.EF.BC.9A.E5.AD.90.E8.B4.A6.E5.8F.B7.E6.8B.A5.E6.9C.89.E5.BE.AE.E6.90.AD.E3.80.81.E4.BA.91.E5.BC.80.E5.8F.91.E6.8C.87.E5.AE.9A.E6.9F.90.E7.8E.AF.E5.A2.83.E8.B5.84.E6.BA.90.E6.9D.83.E9.99.90) 不仅可以控制用户创建应用的权限,其他权限也可通过此方式控制。 ## 相似问题 - 如何设置子账号只能创建自己的微搭项目? - 怎样限制子账号访问别人的微搭项目? - 如何防止子账号访问主账号创建的微搭项目? - 腾讯云中如何通过CAM策略控制子账号权限? - 子账号无法访问其他微搭项目的设置方法是什么? - 怎样让子账号只能操作自己的微搭项目? - 腾讯云里限制子账号访问权限的操作有哪些? - 如何通过腾讯云设置子账号的微搭项目访问权限? - 子账号创建自己微搭项目的权限如何配置? - 在腾讯云中怎样确保子账号不能访问指定微搭项目? --- ## 如何开发一个 AI 小程序 # 如何开发一个 AI 小程序 在云开发 AI+ 中提供了构建 AI 小程序的能力。以下是开发 AI 小程序的步骤和参考资源: ## 搭建教程 你可以参考以下链接中的搭建教程来开发 AI 小程序: [云开发 AI+ 搭建教程](https://mp.weixin.qq.com/s?__biz=Mzg3NTA1NjcyNQ==&mid=2247535871&idx=1&sn=3fbc43644ed1288298c14e7f15564b06&chksm=cf55b12afa4f63ecbab2307c2a1a2886755632115094a49573fad8a667cca944c0541b80a55d&mpshare=1&scene=1&srcid=11124XVG6A4397Yfm9N0iEr0&sharer_shareinfo=2e3e1f26ddfc3b29d8d7842ee9c7d474&sharer_shareinfo_first=2e3e1f26ddfc3b29d8d7842ee9c7d474&version=4.1.26.99469&platform=mac&nwr_flag=1#wechat_redirect) 通过该教程,你可以了解如何利用云开发 AI+ 平台来构建和部署 AI 小程序。 ## 总结 开发 AI 小程序需要结合云开发 AI+ 平台的能力,并参考官方提供的搭建教程。通过这些资源,你可以逐步实现一个功能丰富的 AI 小程序。 ## 相似问题 - 如何利用云开发 AI+ 平台构建 AI 小程序? - 云开发 AI+ 搭建教程在哪里可以找到? - 开发 AI 小程序需要哪些步骤? - 云开发 AI+ 平台有哪些能力可以帮助开发 AI 小程序? - 有没有详细的教程教我如何开发 AI 小程序? - AI 小程序的开发资源有哪些? - 如何部署通过云开发 AI+ 平台构建的 AI 小程序? - 云开发 AI+ 平台适合初学者吗? - 开发 AI 小程序需要编程基础吗? - 云开发 AI+ 平台提供哪些工具来辅助 AI 小程序的开发? --- ## 如何在微搭中获取小程序的配置文件 # 如何在微搭中获取小程序的配置文件 在云开发平台界面点击底部导航栏 [代码编辑器](https://cloud.tencent.com/document/product/1301/57912),前往本地代码编辑页面,具体请参考 [如何在微搭修改小程序全局配置文件](https://cloud.tencent.com/document/product/1301/104574) ## 相似问题 - 微搭中如何获取小程序的全局配置文件? - 在微搭里怎样找到小程序的配置文件? - 微搭获取小程序配置文件的步骤是什么? - 云开发平台中如何在微搭获取小程序配置文件? - 怎样在微搭修改小程序的全局配置文件? - 微搭获取小程序配置文件的链接在哪里? - 云开发里微搭获取小程序配置文件的方法是什么? - 如何在微搭中查看小程序的配置文件? - 微搭中获取小程序配置文件的操作指南在哪? - 在微搭平台上怎样获取小程序的配置文件? --- ## 微搭web应用如何获取公网IP地址 # 微搭web应用如何获取公网IP地址 ### 目前不支持获取公网IP: * ip非固定的, 可能随时变化,相同后端接口也是不同的ip。 * 静态托管页面的ip地址因为会就近接入cdn ,所以ip也不是固定的。 ## 相似问题 - 微搭web应用为何不支持获取公网IP? - 微搭web应用的IP地址为何不固定? - 微搭web应用能否获取到固定的公网IP? - 微搭web应用接入cdn会影响公网IP吗? - 为什么说微搭web应用的ip随时可能变化? - 微搭web应用相同后端接口IP不同的原因是什么? - 微搭web应用获取公网IP存在哪些困难? - 微搭web应用的静态托管页面IP有何特点? - 微搭web应用IP不固定会造成什么影响? - 微搭web应用有没有办法得到公网IP? --- ## 微搭怎么实现开屏倒计时 # 微搭怎么实现开屏倒计时 在微搭中实现开屏倒计时,可以通过以下步骤进行: 2. **设计开屏页面**:在项目中设计一个开屏页面,这将是用户打开小程序时首先看到的页面。 3. **添加倒计时方法**:在开屏页面中添加一个倒计时js方法,可以使用`setInterval`定时函数来实现倒计时逻辑。 4. **调用倒计时方法**:在页面的的生命周期函数中,调用上述倒计时方法。 5. **更新倒计时显示**:在倒计时逻辑中,不断更新倒计时承载组件(比如文本组件)的显示,直到倒计时结束。 6. **倒计时结束后的操作**:倒计时结束后,可以执行跳转到首页或其他页面的操作。 ### 相关资源说明 - [腾讯云微搭低代码 开屏倒计时实现思路](https://cloud.tencent.com/document/product/1301/108619) ## 相似问题 - 微搭实现开屏倒计时的步骤有哪些? - 微搭中如何设计开屏倒计时页面? - 在微搭里开屏倒计时的js方法怎么写? - 微搭开屏倒计时如何更新显示? - 微搭开屏倒计时结束后怎么跳转页面? - 微搭开屏倒计时的生命周期函数怎么调用? - 腾讯云微搭低代码的开屏倒计时怎么实现? - 微搭开屏倒计时用到的组件有哪些? - 微搭中开屏倒计时的定时函数是什么? - 微搭开屏倒计时有什么相关资源? --- ## 如何在发布自定义组件时包含npm依赖? # 如何在发布自定义组件时包含npm依赖? 当您在开发自定义组件并使用npm包时,这些依赖会在您执行`tcb lowcode publish`命令部署组件库时自动打包并上传到云开发平台。您不需要手动进行任何特别的操作来确保npm包的包含。 ## 步骤 1. **开发自定义组件**:在您的开发环境中,使用npm或yarn安装所需的依赖包,并在组件代码中引入这些依赖。 2. **配置云开发环境**:确保您的云开发环境已经配置好,并且您已经登录到云开发控制台。 3. **发布组件**:在项目根目录下,运行以下命令来发布您的组件库: ```bash tcb lowcode publish ``` 这个命令会自动处理所有依赖,包括npm包,并将它们打包到最终的组件库中。 ## 相似问题 - 发布自定义组件时npm依赖怎么处理? - 自定义组件发布会不会丢失npm依赖? - 如何在自定义组件发布中包含npm包? - 发布自定义组件需不需要手动添加npm依赖? - tcb lowcode publish命令能处理npm依赖吗? - 自定义组件发布时npm依赖自动打包吗? - 云开发平台发布自定义组件的步骤是什么? - 发布自定义组件要注意哪些关于npm依赖的事? - 怎样确保发布自定义组件时npm依赖被包含? - 自定义组件发布中npm依赖的作用是什么? --- ## 如何根据数据模型生成管理后台 # 如何根据数据模型生成管理后台 进入云开发平台,找到数据库-数据模型,选取需要的模型,点击右上方生成应用按钮,将会跳转至可视化开发编辑器中,可根据不同场景(增删改查、列表、表单新增、图文卡片、图文列表、标准列表)生成不同类型的管理后台应用。 您还可以选择不同的布局形式,实现统一的导航栏。 页面开发完成后,可以在应用设置-访问控制中设置登录后访问,为后台管理应用配置合适的登录方式及访问权限。 全部设置完成后,点击发布即可拥有一个管理后台应用。 ## 相似问题 - 如何根据数据模型创建管理后台? - 云开发平台中怎样生成管理后台应用? - 根据数据模型生成管理后台的具体步骤是什么? - 数据库-数据模型如何生成应用? - 生成管理后台应用后如何设置访问权限? - 在云开发中根据数据模型生成的管理后台有哪些功能? - 如何选择不同的布局形式来实现统一的导航栏? - 管理后台应用的可视化开发编辑器怎么使用? - 如何在管理后台应用中配置登录方式和权限? - 完成管理后台页面开发后如何发布? --- ## 数据模型如何实现多个字段联合判断唯一性 # 数据模型如何实现多个字段联合判断唯一性 数据模型中,目前仅能针对单个字段设置唯一性校验。我们可以利用数据库自身能力,设置多个字段联合判断唯一性。 了解数据库,可以参考这篇文档。[数据库](/database/introduce) 以下举例说明如何设置: 会员信息表,记录注册会员的`姓名`、`电话`、`地区`等信息。需要校验`姓名+电话`是否唯一。 在模型中设置姓名,电话的唯一性为“否”,详情如图所示 ![](https://qcloudimg.tencent-cloud.cn/raw/0405b2e1085be955c0739d62b0bbde33.png) 在“基础信息”中,找到对应的集合名称。 ![](https://qcloudimg.tencent-cloud.cn/raw/f9669ebe119550306b1d4da16397a040.png) 然后前往云开发-数据库中找到对应集合。 ![](https://qcloudimg.tencent-cloud.cn/raw/c92e8b32bb9fd20209125e53f346de77.png) 进入该集合中,设置姓名+电话的唯一索引 ![](https://qcloudimg.tencent-cloud.cn/raw/51d33b3d494f2b1fe4d1b5a5ea5c4d1e.png) ![](https://qcloudimg.tencent-cloud.cn/raw/1cc77f3f24e632c3fe142de5a3a700c0.png) 完成后,可以在数据模型中验证一下。当我们想添加一条不符合姓名+电话唯一性校验的数据时,会返回错误. ![](https://qcloudimg.tencent-cloud.cn/raw/2bb62aeb9ef0998070884cc4e94b52ec.png) ## 相似问题 - 数据模型如何设置多个字段联合唯一性? - 数据库中怎样实现多个字段联合判断唯一性? - 如何在数据模型中校验姓名+电话的唯一性? - 数据模型单个字段唯一性校验和多个字段联合校验有什么区别? - 在云开发中如何为集合设置多个字段的唯一索引? - 设置多个字段联合唯一性后如何验证? - 数据模型中联合唯一性校验失败会怎样? - 如何在数据库中找到对应集合进行唯一性设置? - 云开发平台中如何设置姓名和电话的联合唯一性? - 数据模型中如何查看多个字段联合唯一性的设置效果? --- ## 云函数如何设置全局环境变量 # 云函数如何设置全局环境变量 **答案:云函数没有全局环境变量的设置,每个函数的环境变量是独立的**。 在微信云开发中,环境变量是与每个云函数单独关联的,这意味着您需要为每个云函数分别设置其环境变量。目前,微信云开发不支持设置全局的环境变量。 ## 设置云函数环境变量的步骤 1. 登录微信开发者工具。 2. 进入到云开发控制台。 3. 选择您需要设置环境变量的云函数。 4. 在云函数的设置页面中,找到环境变量设置选项。 5. 添加或修改环境变量。 ## 注意事项 - 环境变量是敏感信息,不应包含在代码库中。 - 确保环境变量的设置遵循最小权限原则,仅提供必要的访问权限。 ## 相似问题 1. 云函数的环境变量可以跨函数共享吗? 2. 如何在云函数中访问环境变量? 3. 云函数的环境变量是否支持动态更新? 4. 如何删除云函数的环境变量? 5. 云函数的环境变量有大小限制吗? 6. 是否可以在云函数中设置默认的环境变量? 7. 云函数的环境变量是否可以在运行时修改? 8. 如何确保云函数环境变量的安全性? 9. 云函数的环境变量可以用于存储配置信息吗? 10. 云函数的环境变量是否支持加密存储? 如果您需要为多个云函数设置相同的环境变量,您可能需要在每个函数的配置中重复这些设置,或者考虑使用其他机制(如配置中心)来集中管理这些变量。 --- ## 微搭中怎么使用录音功能 # 微搭中怎么使用录音功能 需要使用微信小程序开发能力RecorderManager(全局唯一的录音管理器)。 ### 录音流程 - 用户进入页面,加载录音RecorderManager实例 - 开始录音 - 录音完成后,结束录音 - 通过RecorderManager.onStop()获取录音临时文件 - 通过wx.uploadFile将临时文件上传至云服务器 - 云服务文件id转换成https链接 - 页面回显录音文件提供用户播放 ![image.png](http://git.woa.com/QBase/cloudbase-docs/uploads/43664E704C844E0A92DF840776AA7024/image.png) ### 示例代码 ``` const recorderManager = wx.getRecorderManager() recorderManager.onStart(() => {//监听开始录音 console.log('recorder start') }) recorderManager.onPause(() => {//监听暂停录音 console.log('recorder pause') }) recorderManager.onStop((res) => {//监听停止录音 console.log('recorder stop', res) const { tempFilePath } = res }) recorderManager.onFrameRecorded((res) => { const { frameBuffer } = res console.log('frameBuffer.byteLength', frameBuffer.byteLength) }) const options = {//录音配置 duration: 10000, sampleRate: 44100, numberOfChannels: 1, encodeBitRate: 192000, format: 'aac', frameSize: 50 } recorderManager.start(options) //开始录音 recorderManager.pause()//暂停录音 recorderManager.stop()//停止/结束录音 ``` 更多信息请参考: [微搭应用实现录音功能 ](https://tcloud.woa.com/document/product/1301/109326?!preview) [全局唯一的录音管理器 ](https://developers.weixin.qq.com/miniprogram/dev/api/media/recorder/RecorderManager.start.html) ## 相似问题 - 微搭中如何实现录音功能? - 微信小程序录音管理器RecorderManager怎么用? - 微搭录音功能的流程是什么? - 如何在微搭中开始和停止录音? - 微搭录音完成后文件怎么上传? - 微搭中录音文件如何转换为可播放链接? - 微搭录音功能的示例代码有哪些? - 微搭录音功能如何配置参数? - 微搭中如何暂停和恢复录音? - 微搭录音功能的相关文档在哪里查看? --- ## 云开发中的云存储和数据库删减如何同步? # 云开发中的云存储和数据库删减如何同步? 在云开发中,如果你遇到了数据库数据删除后,云存储中的图片文件依然保存的问题,通常的做法是在存储数据时保存对应的云存储文件ID。这样,在删除数据库数据时,可以一并删除对应的云存储文件。 以下是处理步骤: 1. **关联字段**:确保在数据库中为每个文件存储一个对应的云存储文件ID。 2. **删除操作**:在删除数据库记录时,使用该关联字段找到云存储中的文件,并执行删除操作。 3. **自动化脚本**:如果数据量较大,可以考虑编写自动化脚本来处理数据库和云存储的同步删除。 4. **注意事项**:在执行删除操作前,请确保有数据备份,以防数据丢失。 通过这种方式,可以避免手动一个个删除文件的麻烦,并确保数据库和云存储的数据保持一致。 ## 相似问题 - 云开发中如何同步删除云存储和数据库的数据? - 数据库数据删除后云存储文件怎么同步删除? - 云开发中云存储和数据库删减不同步怎么办? - 如何在云开发中确保云存储和数据库数据一致性? - 云开发中删除数据库记录时如何删除对应的云存储文件? - 云开发中云存储文件ID怎么与数据库记录关联? - 云开发中大量数据删除时如何同步云存储和数据库? - 云开发中如何编写自动化脚本同步删除云存储和数据库数据? - 云开发中删除操作需要注意什么避免数据丢失? - 云开发中云存储和数据库数据不同步有什么后果? --- ## 日志是如何计费的 # 日志是如何计费的 如您未开通高级日志,将不会有额外费用。 如您开通了高级日志,将会根据[价格文档](https://cloud.tencent.com/document/product/876/75213)中-日志服务中的收费项收取费用。 如您将日志投递至CLS,将会按CLS的方案独立计费,参考[文档](https://cloud.tencent.com/document/product/614/45803)。 ## 相似问题 - 日志计费规则是怎样的? - 未开通高级日志有费用吗? - 开通高级日志如何计算费用? - 日志投递至CLS怎么计费? - 如何查看日志服务的收费项? - 高级日志和普通日志计费有什么区别? - 日志服务计费参考哪个文档? - CLS计费方案在哪里查看? - 日志计费和日志存储有什么关系? - 如何避免日志服务产生额外费用? --- ## 素材库如何设置访问权限 # 素材库如何设置访问权限 素材库不支持直接设置访问权限。 但素材库的底层是云开发静态网站托管服务,如果您有安全需求,可前往当前环境的静态托管页面访问配置中进行**防盗链配置**、**IP黑白名单配置**、**IP访问限频配置**。 详情请[参考](/hosting/manage#安全配置) ## 相似问题 - 素材库能设置访问权限吗? - 素材库如何实现访问控制? - 素材库防盗链怎么配置? - 素材库 IP 黑白名单在哪设置? - 素材库 IP 访问限频如何操作? - 素材库安全配置在哪查看? - 素材库没有直接访问权限设置怎么办? - 云开发静态网站托管服务与素材库权限有何关系? - 如何在素材库当前环境进行安全配置? - 素材库防盗链配置的方法是什么? --- ## 遇到 `missing wxCloudApiToken` 报错是怎么回事 # 遇到 `missing wxCloudApiToken` 报错是怎么回事 当在微信云开发中遇到 `missing wxCloudApiToken` 报错时,通常是由于云调用发起方式不符合微信云开发的要求所致。 ## 问题原因 `missing wxCloudApiToken` 说明没有云调用相关的票据,不能调用云调用相关接口。 因为云调用在微信云开发中有一些特定的使用限制,主要包括: - 必须从小程序端发起:云调用必须由小程序端触发,不支持从云控制台、Web 端、云函数调用云函数、定时触发云函数等方式发起(通过微信 IDE 设置的云函数定时触发除外)。 ## 解决方案 ### 确保从小程序端发起 - 确保所有的云调用都是通过小程序端触发的,而不是通过云控制台或其他非微信端的方式。 - 如果需要在云函数中发起云调用,确保该云函数是由小程序端触发的。 ### 使用微信 IDE 设置定时触发 - 如果需要定时触发云函数并进行云调用,可以使用微信开发者工具(微信 IDE)设置定时触发器。 - 在微信开发者工具中,进入云开发控制台,选择相应的云函数,设置定时触发规则。 ### 检查云函数的触发方式 - 确保云函数的触发方式是从小程序端触发的,例如通过按钮点击、页面加载等用户交互行为。 - 避免使用非小程序端的触发方式,如直接在云控制台调用云函数或通过 Web 端 API 调用。 ## 相似问题 1. 云调用为什么必须在小程序端发起? 2. 如何在微信 IDE 中设置云函数的定时触发? 3. 云函数可以通过 Web 端 API 调用吗? 4. `missing wxCloudApiToken` 报错如何解决? 5. 微信云开发的云调用有哪些限制? 6. 如何确保云函数是由小程序端触发的? 7. 微信云开发中云调用的正确发起方式是什么? 8. `getWXCloudApiToken failed` 错误是什么意思? 9. 微信云开发中定时触发云函数的设置方法是什么? 10. 如何避免 `missing wxCloudApiToken` 报错? ## 相关错误 ```json { "errorCode": -1, "errorMessage": "User code exception caught", "stackTrace": "Error: errCode: -501007 invalid parameters | errMsg: urlscheme.generate:fail missing wxCloudApiToken 请前往云开发AI小助手查看问题:https://tcb.cloud.tencent.com/cloud-admin#/copilot?q=INVALID_PARAM" } ``` --- ## 云函数运行时Node.js16 ETIMEDOUT问题 # 云函数运行时Node.js16 ETIMEDOUT问题 云函数运行时Node.jsV16版本运行机制有调整,可能导致ETIMEDOUT问题。 ## 问题现象 函数执行失败,且失败的报错信息中包含 ETIMEOUT、ESOCKETTIMEOUT 等信息,且函数执行时间仅有几毫秒。 ## 问题原因 异步调用回调被触发时,可能串到之后的某次调用中。如果异步回调中抛出一个异常,运行时会捕获这个`uncaughtException`异常,并认为是本次云函数调用执行有问题,并将异常作为云函数运行结果返回。 ## 复现代码 ```javascript function nowISOString() { return new Date().toISOString() } exports.main = async function (event, context) { console.log('request start', context.request_id, nowISOString()) setTimeout(() => { throw new Error('ETIMEDOUT' + context.request_id) }, 6000) console.log('request finish', context.request_id, nowISOString()) await new Promise((resolve) => { setTimeout(() => { resolve() }, 3000) }) return 'success' } ``` ## 解决方式 1. **使用v10或v12版本**:如果可能,建议使用Node.js的v10或v12版本。 2. **检查异步代码**:检查代码中是否存在没有`await`的异步调用,并确保所有异步操作都被正确等待。 ## 更多信息 云函数Node.js 14.18、Node.js 16.13等版本运行时有变化,不再支持某些异步特性。当前出现超时错误问题的原因可能是函数代码中存在没有`await`等待的异步任务,在函数返回之后仍在运行,这可能会在之后的某次调用中引发问题。 更多详细信息,请参考:[云函数异常处理文档](https://cloud.tencent.com/document/product/583/67790#.E5.BC.82.E6.AD.A5.E7.89.B9.E6.80.A7.E6.94.AF.E6.8C.81) ## 相似问题 - 云函数运行时Node.js16出现ETIMEDOUT问题的原因是什么? - 如何解决云函数运行时Node.js16的ETIMEDOUT问题? - 云函数运行时Node.js16报错ETIMEOUT怎么处理? - 云函数中异步调用导致ETIMEDOUT怎么解决? - 为什么云函数运行时Node.js16会有ETIMEDOUT问题? - 云函数运行时Node.js16 ETIMEDOUT问题的复现代码是怎样的? - 云函数运行时Node.js16 ETIMEDOUT问题有哪些解决方式? - 云函数运行时Node.js16不再支持哪些异步特性导致ETIMEDOUT? - 云函数运行时Node.js16 ETIMEDOUT问题如何避免? - 云函数运行时Node.js16 ETIMEDOUT相关的详细文档在哪里查看? --- ## 微搭支持本地上传的文件在线预览吗? # 微搭支持本地上传的文件在线预览吗? 微搭目前支持获取上传文件的下载链接,并直接在浏览器中打开预览。以下是详细信息: ## 文件预览方式 - **直接预览**:对于某些文件类型,例如 PDF,浏览器可以直接支持预览。 - **下载链接**:您可以获取文件的下载链接,然后在浏览器中打开。 ## 不支持直接预览的文件类型 对于不支持直接预览的文件类型,例如 DOC 文件,您可以考虑以下预览方式: - **微软 Office Web Viewer**:使用微软提供的在线文档查看器。 - **ONLYOFFICE**:可以私有部署 ONLYOFFICE 社区版来预览文档。 ## 未来规划 我们也在规划支持基于 COS(Cloud Object Storage)的在线直接预览功能。 ## 参考资料 - [获取临时文件下载链接](https://docs.cloudbase.net/lowcode/api/cloud#wcloudgettempfileurl) ## 相似问题 - 微搭支持本地上传文件的在线预览吗? - 微搭如何预览本地上传的文件? - 微搭支持哪些文件类型的直接预览? - 微搭不支持直接预览的文件类型怎么办? - 如何使用微软 Office Web Viewer 预览微搭上传的文件? - ONLYOFFICE 如何用于预览微搭上传的文件? - 微搭未来会支持基于 COS 的在线直接预览吗? - 如何获取微搭上传文件的下载链接? - 微搭文件预览方式有哪些? - 微搭本地上传文件预览的相关资料在哪里查看? --- ## PHP SDK支持PHP 8.0吗? # PHP SDK支持PHP 8.0吗? PHP SDK已经不维护了,建议使用Open API。详细信息可以参考[腾讯云云开发Open API文档](https://docs.cloudbase.net/api-reference/openapi/introduction)。 ## 相似问题 - PHP SDK支持PHP 8.0吗? - PHP SDK还维护吗? - PHP SDK不维护了怎么办? - 如何使用Open API替代PHP SDK? - 腾讯云云开发Open API文档在哪里查看? - PHP SDK为什么不支持PHP 8.0? - Open API和PHP SDK有什么区别? - 使用Open API有什么优势? - PHP SDK停止维护会影响现有项目吗? - 如何迁移到Open API? --- ## 小程序如何实现下拉刷新 # 小程序如何实现下拉刷新 具体样式及数据列表组件的下拉刷新,可以[参考](https://cloud.tencent.com/document/product/1301/93146) 如果需要刷新当前整个页面,可以使用`wx.redirectTo`方法,将页面重定向到当前页面。详细可[参考](https://developers.weixin.qq.com/miniprogram/dev/api/route/wx.redirectTo.html) ```js wx.redirectTo({ url: '/pages/current-page/current-page', success: function(res) { console.log('刷新成功'); }, fail: function(res) { console.log('刷新失败') } }) ``` 也可以使用`wx.reLaunch`方法,跳转到当前页面,且可以携带参数。详情可[参考](https://developers.weixin.qq.com/miniprogram/dev/api/route/wx.reLaunch.html) ```js wx.reLaunch({ url: 'current-page?id=1' }) ``` ## 相似问题 - 小程序如何实现下拉刷新? - 小程序下拉刷新的具体样式和数据列表组件怎么弄? - 怎样刷新当前整个小程序页面? - 使用`wx.redirectTo`方法刷新页面怎么写代码? - `wx.redirectTo`方法刷新页面成功或失败怎么判断? - 小程序中`wx.reLaunch`方法的作用是什么? - `wx.reLaunch`方法跳转到当前页面携带参数怎么设置? - 小程序下拉刷新功能在哪里查看详细文档? - 除了下拉刷新,小程序还有其他页面刷新方式吗? - 小程序下拉刷新有什么注意事项? --- ## 微搭应用开启注册后,支持国外手机号吗? # 微搭应用开启注册后,支持国外手机号吗? 暂时不支持,目前只支持+86号段。 ## 相似问题 - 微搭应用开启注册后支持国外手机号吗? - 微搭目前支持哪些号段的手机号注册? - 微搭未来会支持国外手机号注册吗? - 微搭为什么暂时不支持国外手机号注册? - 如果用户使用国外手机号如何注册微搭应用? - 微搭对手机号注册有什么限制? - 微搭支持国际号码注册吗? - 微搭手机号注册支持的号段有哪些? - 微搭注册时手机号格式有什么要求? - 微搭对国外手机号注册有什么计划? --- ## 云开发可以提供什么等级的安全防护 # 云开发可以提供什么等级的安全防护 云开发提供腾讯云基础的DDoS防护能力,具体[参见](https://cloud.tencent.com/document/product/1020/31625) 同时,云开发作为腾讯云公有云产品,自身具备三级等保认证和可信云认证,可[参考](https://cloud.tencent.com/document/product/363/2487) 云开发网关提供了防爬虫机制,可以有效防止恶意爬虫对服务的攻击。 ## 相似问题 - 云开发提供哪些等级的安全防护? - 云开发的DDoS防护能力如何? - 云开发具备哪些安全认证? - 云开发的防爬虫机制是怎样工作的? - 云开发如何防止恶意爬虫攻击? - 云开发的安全防护等级有哪些具体标准? - 云开发的等保认证级别是多少? - 可信云认证对云开发意味着什么? - 云开发在安全方面还有哪些特色功能? - 云开发的安全防护能力与同行相比如何? --- ## 为什么找不到修改短信签名的入口? # 为什么找不到修改短信签名的入口? 目前云开发控制台适用V2版本的登录认证,不支持使用自定义签名。 使用旧版V1版本登录认证的用户,可前往旧版云开发控制台配置。但V1版本登录认证会逐步下线,请尽快迁移至V2版本。[如何迁移](https://docs.cloudbase.net/api-reference/webv3/migration) # 为什么自定义签名的短信发送失败 由于运营商策略变化,V1版本登录认证的自定义签名短信,有几率被拦截,请您切换为云开发统一签名短信。 对于企业版及以上用户,已配置自定义签名,且不愿切换V2版本的登录认证的用户,请联系客服。 --- ## 解决云后台(cloud-admin路径)404错误 # 解决云后台(cloud-admin路径)404错误 当访问云后台(cloud-admin路径)出现404错误时,通常是由于用户删除了自己静态托管里面的 `index.html` 文件。以下是解决此问题的步骤: ## 修复步骤 1. **下载 `index.html` 文件** 访问以下链接下载 `index.html` 文件: [https://weda-cloud-1258344699.cos.ap-shanghai.myqcloud.com/workbench/templates/index.html](https://weda-cloud-1258344699.cos.ap-shanghai.myqcloud.com/workbench/templates/index.html) 2. **编辑 `index.html` 文件** 打开下载的 `index.html` 文件,将 `window.WedaPortalConfig = {envId: '{{ envId }}'} {{ envId }}` 替换成自己真实的环境ID。另存为 `index.html` 文件,注意添加 `.html` 的后缀。 3. **上传 `index.html` 文件** ![](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/bc86a2de-74ea-4d10-9ce1-24fe1457dd34.png) 如果在使用新版云开发控制台,先返回旧版控制台: [https://console.cloud.tencent.com/tcb/hosting](https://console.cloud.tencent.com/tcb/hosting) 选到正确环境,检查有无 `cloud-admin` 目录。如果没有,新建一个名为 `cloud-admin` 的文件夹,将修改过的 `index.html` 文件上传到 `cloud-admin` 目录下。 通过以上步骤,您应该能够解决云后台(cloud-admin路径)404错误。 ![](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/014b0d3f-0fb9-424c-a71a-1eaa41cae842.png) ## 相似问题 - 云后台(cloud-admin路径)出现404错误是什么原因? - 如何解决云后台(cloud-admin路径)404错误? - 云后台404错误是因为删除了什么文件? - 云后台的index.html文件从哪里下载? - 如何编辑云后台的index.html文件? - 云后台的index.html文件上传步骤是什么? - 新版云开发控制台如何返回旧版控制台? - 云后台cloud-admin目录不存在怎么办? - 云后台404错误修复后如何验证? - 云后台index.html文件的正确格式是什么样的? --- ## 在微搭编辑器中使用非微搭版的组件 # 在微搭编辑器中使用非微搭版的组件 微搭编辑器允许用户使用自定义组件来扩展其功能。 - [自定义组件](https://docs.cloudbase.net/lowcode/custom-components/quick-start/comps): 支持 web 和小程序,需要一定的开发门槛 - [JSX组件](https://docs.cloudbase.net/lowcode/components/wedaUI/src/docs/compsdocs/super/Jsx): 仅支持 Web ,可快速引入外部组件,如TDesign、Antd 等第三方的开源组件库。可配置出多种组件如水印、步骤条、级联选择、评分、滑动输入条等。 具体步骤请参考微搭官方文档或相关组件的文档说明。 ## 相似问题 - 在微搭编辑器中能使用非微搭版的组件吗? - 微搭编辑器使用自定义组件有什么要求? - JSX组件在微搭编辑器中如何使用? - 如何在微搭中使用TDesign等第三方开源组件库? - 微搭自定义组件支持哪些平台? - JSX组件仅支持 Web 吗? - 在微搭中使用非微搭版组件有哪些步骤? - 微搭自定义组件的开发门槛高吗? - 微搭编辑器引入外部组件的方式有哪些? - 微搭中自定义组件和JSX组件有什么区别? --- ## 微信云开发控制台打不开或白屏问题 # 微信云开发控制台打不开或白屏问题 遇到微信云开发控制台打不开或白屏的情况,可以尝试以下解决方案: 1. **更新微信开发者工具**:确保使用的微信开发者工具是最新版本,因为旧版本在插件更新时可能会出现白屏问题。 2. **临时解决方案**:如果更新开发者工具后问题仍然存在,可以尝试以下步骤: - 打开微信开发者工具,点击左上角“微信开发者工具”菜单。 - 选择“调试”选项。 - 点击“插件目录”以打开插件目录。 - 将插件目录(WeappPlugins)重命名(例如改为 WeappPlugins_1)。 - 重启微信开发者工具。 执行上述步骤后,问题通常可以得到解决。如果问题依旧,建议查看微信开发者工具的官方文档或联系微信开发者社区寻求帮助。 ## 相似问题 - 微信云开发控制台打不开怎么办? - 微信云开发控制台白屏是什么原因? - 如何解决微信云开发控制台白屏问题? - 微信开发者工具需要更新吗? - 更新微信开发者工具能解决云开发控制台白屏吗? - 微信云开发控制台打不开的临时解决方案是什么? - 如何重命名微信开发者工具的插件目录? - 重命名插件目录后要重启微信开发者工具吗? - 微信云开发控制台问题依旧怎么处理? - 微信开发者社区能帮忙解决云开发控制台问题吗? --- ## 我想在小程序中加入微信支付功能,有什么限制 # 我想在小程序中加入微信支付功能,有什么限制 您的小程序认证需要属于个体工商户、企业或党政、机关、事业单位、民办非企业、社会团体、基金会等,个人认证将无法申请微信支付。 云开发提供的微信支付APIs相关不限制套餐版本,所有版本套餐均可使用。使用方式请[查看](https://cloud.tencent.com/document/product/1301/97121). ## 相似问题 - 小程序加入微信支付功能有什么认证限制? - 哪些主体可以进行微信支付功能认证? - 个人认证能申请微信支付吗? - 云开发的微信支付APIs有套餐版本限制吗? - 如何查看云开发微信支付APIs的使用方式? - 个体工商户能否申请小程序微信支付? - 民办非企业可以进行微信支付认证吗? - 基金会申请微信支付有什么要求? - 企业申请微信支付功能有何条件? - 党政机关申请微信支付功能流程是怎样的? --- ## 环境状态为隔离(env status is isolated)是什么意思? # 环境状态为隔离(env status is isolated)是什么意思? 环境状态显示为“隔离”(isolated)通常意味着您的云开发环境由于某些原因已经被隔离。这可能是因为环境到期、账号欠费或其他原因导致的。为了解决这个问题,您需要: 1. **登录控制台**:前往微信云开发控制台。 2. **检查环境状态**:在控制台中确认您的环境可用状态。 3. **解决问题**:根据控制台提供的信息,采取相应的措施来解除隔离状态,比如续费或解决其他问题。 请尽快处理,以免影响您的开发工作。 ## 相似问题 - 环境状态为隔离是什么意思? - 云开发环境为什么会被隔离? - 如何检查云开发环境的隔离状态? - 云开发环境隔离后怎么解决? - 云开发环境隔离是因为账号欠费吗? - 云开发环境到期会导致隔离吗? - 如何登录微信云开发控制台查看环境状态? - 云开发环境隔离会影响开发工作吗? - 解除云开发环境隔离状态有哪些措施? - 云开发环境隔离后多久需要处理? --- ## 微信小程序云开发,内容管理中的营销工具哪里去了? # 微信小程序云开发,内容管理中的营销工具哪里去了? 目前,微信小程序云开发的内容管理中的营销工具正在改版中,预计将在近期重新上线。在此期间,您可能无法直接访问营销工具。我们理解这可能会给您带来不便,并诚挚地感谢您的理解与支持。 我们致力于为用户提供更优质、更高效的营销工具,以满足您在微信小程序云开发中的各种需求。一旦新版营销工具上线,我们将第一时间通知您,并详细介绍新功能和使用方法。 如有任何疑问或建议,请随时联系我们,我们将竭诚为您服务。 ## 相似问题 - 微信小程序云开发的营销工具去哪了? - 云开发内容管理中的营销工具为何无法访问? - 营销工具改版预计何时上线? - 如何获取新版营销工具上线的通知? - 新版营销工具有哪些新功能? - 怎样联系微信小程序云开发团队询问营销工具情况? - 云开发营销工具改版期间能使用类似替代工具吗? - 云开发内容管理的其他功能正常吗? - 营销工具改版会对现有业务造成影响吗? - 如何给微信小程序云开发的营销工具提建议? --- ## 为什么云函数中调用其他云函数报错socket timeout,但是被调用的云函数实际是有执行成功并且返回数据的 # 为什么云函数中调用其他云函数报错socket timeout,但是被调用的云函数实际是有执行成功并且返回数据的 您可在页面上的函数配置-基本信息中,为云函数设置超时时长。 同时,如果使用到SDK,SDK默认的超时时间是15秒,两者以最短时间为准。 ## 相似问题 - 云函数调用其他云函数报错socket timeout怎么解决? - 云函数设置超时时长的位置在哪? - SDK默认的超时时间是多少? - 云函数执行成功但调用方报错如何处理? - 如何调整云函数的超时时间避免报错? - 云函数超时时间以哪个为准? - 云函数调用超时的原因只有时长设置吗? - 怎样判断云函数是否真的执行成功了? - 云函数之间调用超时会影响数据返回吗? - 除了调整时长,还有其他办法解决云函数调用超时吗? --- ## 工作流条件分支是否有数量限制 # 工作流条件分支是否有数量限制 目前工作流条件分支最多支持10个分支。 ## 相似问题 - 工作流条件分支有数量限制吗? - 工作流条件分支最多支持几个分支? - 工作流条件分支数量达到上限怎么办? - 如何增加工作流条件分支的数量限制? - 工作流条件分支数量限制会影响工作流功能吗? - 有没有办法突破工作流条件分支的数量限制? - 工作流条件分支数量限制是永久的吗? - 不同类型的工作流条件分支数量限制一样吗? - 工作流条件分支数量限制从何而来? - 工作流条件分支数量限制会调整吗? --- ## WxCloudSDKError: 【错误】secret id error # WxCloudSDKError: 【错误】secret id error 在微信开发者工具中本地调试云函数时,可能会遇到 `WxCloudSDKError: 【错误】secret id error` 的错误提示。这个错误通常是由于本地调试环境无法正确验证 `secretId` 导致的。 ## 解决方法 **部署云函数到云端**:建议将云函数部署到云端后重新进行测试。云端环境可以正确验证 `secretId`,从而避免这个错误。 通过以上步骤,您应该能够解决 `WxCloudSDKError: 【错误】secret id error` 的问题。如果问题仍然存在,建议检查其他配置或联系微信开发者支持团队获取进一步帮助。 ## 相似问题 - WxCloudSDKError: 【错误】secret id error是什么原因? - 本地调试云函数出现secret id error怎么解决? - 为什么本地环境无法正确验证secretId? - 部署云函数到云端能解决secret id error吗? - 如何将云函数部署到云端? - 云函数部署到云端后测试步骤是什么? - 除了部署到云端,还有其他办法解决secret id error吗? - secret id error会影响云函数的其他功能吗? - 检查哪些配置能解决secret id error? - 联系微信开发者支持团队的途径有哪些? --- ## 登录相关 # 登录相关 ## 小程序中接口无法正常请求怎么处理? 在[微信公众平台](https://mp.weixin.qq.com/)中添加 request 域名,如果只是调试可以在小程序访问请打开调试模式,开发者工具中请开启不校验业务域名 ## 小程序中页面提示无法正常打开怎么处理? 在[微信公众平台](https://mp.weixin.qq.com/)中添加业务域名,如果只是调试可以在小程序访问请打开调试模式,开发者工具中请开启不校验业务域名 ## 提示未开启手机号短信登录怎么处理? 请前往[身份源页面](https://console.cloud.tencent.com/lowcode/permission/identity/index)配置 --- ## 在线开发相关 # 在线开发相关 ### 在云开发平台删除云函数后,在线编辑器仍存在这个云函数 - 原因分析 在云开发平台中,云函数属于部署服务,而在线编辑器用于存放云函数的代码。这两者相互独立,删除云函数部署并不会自动删除对应的代码 打个比方,我们在本地编写一个服务的代码,然后将其部署到线上环境。当不再需要这个服务时,我们可以把服务下线,也就是删除部署。但此时,本地的服务代码依然会保留,并不会因为线上服务的删除而自动消失。 云开发平台的在线编辑器,其实就相当于本地编辑器的远程版本,本质上只是换了个地方编写代码,其代码存储机制和本地编写、部署的模式原理一致 - 解决方法 若你已明确不再需要某个云函数的代码,直接在在线编辑器中删除该云函数代码就行 ### 在云开发平台删除并重新创建了同名的云函数后,在线编辑器仍显示之前的版本 - 原因分析 这与在线编辑器的自动下载策略有关。当工作空间中已经存在同名的云函数时,为了避免代码被覆盖,在线编辑器会自动跳过下载过程,并提示用户手动下载更新 ![](https://qcloudimg.tencent-cloud.cn/raw/af910b11a45c699ec12544d973baa500.png) - 解决方法 通过手动下载方式同步云函数代码即可 具体步骤参考[云函数在线开发](/cloud-function/online-dev#下载)手册中的下载部分 ### 创建了函数型云托管 后,进入在线开发时下载失败 - 原因分析 函数型云托管 是基于云托管的。在没有部署历史的情况下,在线开发无法下载到对应的代码包,所以会出现以下提示 ![](https://qcloudimg.tencent-cloud.cn/raw/7366a1e56047056ec9c9c338598a9d74.png) - 解决方法 请耐心等待云函数的部署完成,然后再进入在线开发进行操作 ### 在线开发的功能操作菜单在哪里? 请参考 [云函数在线开发](/cloud-function/online-dev#下载) ### pnpm 安装依赖时报错 ![](https://qcloudimg.tencent-cloud.cn/raw/5789ee6efee29e25f42a98279f67e35a.png) - 原因分析 项目的 package.json 中声明的 pnpm 版本与当前环境安装的 pnpm 版本不一致 - 解决方法 打开终端,执行命令 `corepack enable` 即可 ### 在线编辑器提示磁盘使用率过高 当在线编辑器的磁盘空间使用率超过 85% 时,您将会看到以下提示: 您可以点击【自动清理缓存】按钮,清理 npm / yarn / pnpm / pip 等依赖缓存。同时请检查工作空间中是否存在较大的文件(如压缩包、二进制安装文件等),建议仅保留必要的代码文件。 ![](https://qcloudimg.tencent-cloud.cn/raw/d00ed6f81dc5b2e5e22fab4bf9e5fc9b.png) 若磁盘空间使用率超过 90%,为了确保在线编辑器的正常运行,系统将自动进行缓存清理。 ![](https://qcloudimg.tencent-cloud.cn/raw/c8c4c998ac1be9e0328a2a50212202a7.png) 您可以通过执行命令 "df -h" 来查看工作空间的磁盘使用情况。 ![](https://qcloudimg.tencent-cloud.cn/raw/19306132bf3e30a002519190776386b9.png) ### 获取临时凭证超时,在线编辑器部分功能将无法正常使用 ![](https://qcloudimg.tencent-cloud.cn/raw/3e99f5cb0b94104c8ed00999ac32d2d2.png) - 原因分析 当遇到上述提示时,首先请检查在线编辑器中是否已安装“Tencent CloudBase Toolkit V2”扩展。如果未安装,请在扩展市场中搜索关键字“Tencent CloudBase Toolkit V2”来查找并安装该扩展,然后刷新页面重试 如果不是以上问题,那么很可能是在线编辑器的磁盘空间不足,导致扩展执行异常,请根据以下解决方法进行处理 - 解决方法 通常,进入在线编辑器时会有相关提示,参考[【在线编辑器提示磁盘使用率过高】](#在线编辑器提示磁盘使用率过高) 如果没有提示,您可以先打开终端,执行命令 `df -h` 查看磁盘的剩余空间 ![](https://qcloudimg.tencent-cloud.cn/raw/c12e5d3edf9554bce614d63496a6360c.png) 如果发现磁盘空间已经所剩无几,可以先尝试运行以下命令清除缓存,同时清理工作空间中非必要的大文件 ```sh npm cache clean --force pnpm store prune yarn cache clean pip cache purge ``` 最后,再次通过 `df -h` 命令检查磁盘空间使用率是否有所降低。如果空间使用率有所降低,可重新进入在线编辑器进行操作 ### 打开云函数调试服务链接时提示登录 ![](https://qcloudimg.tencent-cloud.cn/raw/30315b7e72c708ce0c236ce989999aee.png) - 原因分析 调试链接仅在在线编辑器内有效。为了防止外部访问,调试链接只能在【测试面板】内进行访问,其他位置均无法访问 - 解决方法 请使用在线编辑器调试时自动打开的【测试面板】进行调试操作,如下图所示: ![](https://qcloudimg.tencent-cloud.cn/raw/57378b1236cf285ef193f565d9f5adeb.png) --- ## 存储相关 # 存储相关 ## 文件存储的容量达到上限之后怎么办? 为了保证资源的合理利用,CloudBase 对各环境有文件存储容量的限制。每个环境的文件存储容量都是独立计算的。 - 如果文件存储的剩余容量低于10%,则会通过短信、站内信、邮件等方式进行告知,您可以升级您的环境版本,以享有更多的文件存储容量,避免影响业务的正常运行。 - 如果该环境的数据库存储容量已用尽,则不允许继续往文件存储中上传文件,但可以下载及删除文件。 ## 文件夹创建数量有限制吗? 文件夹的创建没有数量限制。 ## 文件夹内的文件上传数量有限制吗? 文件夹内可上传的文件数量没有限制。 - 尽量不要在同一个文件夹下放置太多文件,到达一定量时会对性能有比较大的影响。 - 删除文件夹时,会同时删除该文件夹内的所有文件,当文件夹内的文件数量过多时,也会影响删除文件夹的效率。 具体参见 [请求速率与性能优化](https://cloud.tencent.com/document/product/436/13653)。 ## 上传已经存在的文件会有什么动作? 会覆盖已经存在的文件,表现与上传不存在的文件完全一样。 ## 我可以直接使用文件链接下载文件吗? 即使存储桶是公有读的,仍然不建议这样做,使用 fileid 通过 SDK 访问文件是最安全稳固的做法。 ## 有批量上传或下载文件的方式吗 可以使用云开发命令行工具(CLI)完成文件(夹)批量上传或下载 --- ## 与Git平台CI/CD集成 # 与Git平台CI/CD集成 随着前端项目的日益复杂,自动化部署成为了提升开发效率、保证代码质量的关键一环。腾讯云CloudBase(云开发)提供的静态托管服务,结合其强大的CLI工具,可以轻松实现前端项目的快速部署。 本文将详细介绍如何利用CloudBase CLI工具,配合GitHub Actions、GitLab CI/CD和Gitee Go等主流Git平台的流水线能力,实现Git仓库中前端项目的自动部署到CloudBase静态托管服务。 ## 前置准备 ### 安装CLI工具 ```bash # 全局安装(推荐) npm install -g @cloudbase/cli # 验证安装 tcb --version ``` > 💡 **提示**:如果尚未安装,请参考 [CLI安装指南](/cli-v1/install) ### 获取API密钥 1. 登录 [腾讯云控制台/访问管理/API密钥管理](https://console.cloud.tencent.com/cam/capi) 2. 创建或获取现有的 `SecretId` 和 `SecretKey` 3. 记录您的云开发环境ID(在云开发控制台可查看) > ⚠️ **安全提醒**:请妥善保管您的API密钥,不要在代码中硬编码,务必使用CI/CD平台的密钥管理功能 ![API密钥管理](https://qcloudimg.tencent-cloud.cn/raw/eed695cf61aa1d5b3092fb7418b63900.png) ### 准备项目配置 确保您的项目具备以下条件: * ✅ 项目根目录包含构建脚本(如 `npm run build`) * ✅ 构建后生成静态文件目录(如 `dist/`、`build/` 等) * ✅ 项目可以在CI/CD环境中正常构建 * ✅ 已配置正确的Node.js版本 ## 平台集成指南 ### GitHub Actions GitHub Actions是GitHub提供的CI/CD服务,可以直接在GitHub仓库中配置工作流。 #### 步骤1:配置GitHub Secrets 在您的GitHub仓库中,依次点击 **Settings** → **Secrets and variables** → **Actions** → **New repository secret**。 添加以下Secrets: * `TCB_SECRET_ID`: 您的腾讯云SecretId * `TCB_SECRET_KEY`: 您的腾讯云SecretKey * `TCB_ENV_ID`: 您的云开发环境ID > 💡 **多环境提示**:建议为不同环境创建不同的Secrets,如 `TCB_ENV_ID_DEV` 、 `TCB_ENV_ID_PROD` ![](https://qcloudimg.tencent-cloud.cn/raw/7e0cfadf12c79dd26c1799c6123792e9.png) #### 步骤2:创建工作流文件 在项目根目录创建 `.github/workflows/deploy.yml` : 示例参考: ```yaml name: Deploy to CloudBase Static Hosting on: push: branches: - main # 主分支推送时触发 pull_request: branches: - main # PR时触发(可选) jobs: build-and-deploy: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '18' cache: 'npm' # 启用npm缓存加速构建 - name: Install dependencies run: npm ci # 使用npm ci替代npm install,更适合CI环境 - name: Build project run: npm run build - name: Install CloudBase CLI run: npm install -g @cloudbase/cli - name: Login CloudBase CLI run: tcb login --apiKeyId ${{ secrets.TCB_SECRET_ID }} --apiKey ${{ secrets.TCB_SECRET_KEY }} - name: Deploy to CloudBase Static Hosting run: tcb hosting deploy ./dist /home -e ${{ secrets.TCB_ENV_ID }} ``` #### 配置参数说明 静态托管命令具体参考:[CLI管理](/cli-v1/hosting) | 参数 | 说明 | 示例 | |------|------|------| | `./dist` | 构建产物目录 | `./build` 、 `./public` | | `/home` | 云端目标路径 | `/` 、 `/static` | ### GitLab CI/CD GitLab CI/CD是GitLab内置的CI/CD服务,通过 `.gitlab-ci.yml` 文件进行配置。 #### 步骤1:配置CI/CD变量 在GitLab项目中,依次点击 **Settings** → **CI/CD** → **Variables** → **Add variable**。 添加以下变量: * `TCB_SECRET_ID`: 您的腾讯云SecretId * `TCB_SECRET_KEY`: 您的腾讯云SecretKey * `TCB_ENV_ID`: 您的云开发环境ID > 🔒 **安全建议**:将变量标记为 "Protected" 和 "Masked" 以增加安全性 #### 步骤2:创建 `.gitlab-ci.yml` 文件 在项目根目录创建 `.gitlab-ci.yml` : 示例参考: ```yaml stages: - build - deploy variables: NODE_VERSION: "18" CACHE_KEY: "$CI_COMMIT_REF_SLUG-$CI_PROJECT_DIR" # 缓存配置 cache: key: ${CACHE_KEY} paths: - node_modules/ - .npm/ build: stage: build image: node:18-alpine before_script: - npm config set cache .npm - npm ci script: - npm run build artifacts: paths: - dist/ expire_in: 1 hour only: - main - merge_requests deploy: stage: deploy image: node:18-alpine dependencies: - build before_script: - npm install -g @cloudbase/cli script: - tcb login --apiKeyId $TCB_SECRET_ID --apiKey $TCB_SECRET_KEY - tcb hosting deploy ./dist /home -e $TCB_ENV_ID only: - main when: on_success ``` #### GitLab CI/CD 特性 * **Pipeline缓存**:自动缓存 `node_modules` 和 `.npm` 目录 * **Artifacts管理**:构建产物在stages间传递 * **环境管理**:支持多环境部署和环境变量 * **条件部署**:基于分支的条件部署 ### Gitee Go Gitee Go是Gitee(码云)提供的CI/CD服务,语法与GitHub Actions相似。 #### 步骤1:配置环境变量 在Gitee仓库中,依次点击 **管理** → **WebHooks** → **Gitee Go** → **环境变量**。 添加以下环境变量: * `TCB_SECRET_ID`: 您的腾讯云SecretId * `TCB_SECRET_KEY`: 您的腾讯云SecretKey * `TCB_ENV_ID`: 您的云开发环境ID > 🔐 **安全提示**:勾选"敏感信息"以保护您的密钥 #### 步骤2:创建工作流文件 在项目根目录创建 `.gitee/workflows/deploy.yml` : 示例参考: ```yaml name: Deploy to CloudBase Static Hosting on: push: branches: - main # 主分支推送时触发 pull_request: branches: - main # PR时触发(可选) jobs: build-and-deploy: runs-on: ubuntu-latest steps: - name: 检出代码 uses: actions/checkout@v3 - name: 设置 Node.js 环境 uses: actions/setup-node@v3 with: node-version: '18' cache: 'npm' # 启用npm缓存加速构建 - name: 安装依赖 run: npm ci # 使用npm ci替代npm install,更适合CI环境 - name: 构建项目 run: npm run build - name: 安装 CloudBase CLI run: npm install -g @cloudbase/cli - name: 登录 CloudBase CLI run: tcb login --apiKeyId ${{ secrets.TCB_SECRET_ID }} --apiKey ${{ secrets.TCB_SECRET_KEY }} - name: 部署到 CloudBase 静态托管 run: tcb hosting deploy ./dist /home -e ${{ secrets.TCB_ENV_ID }} - name: 部署成功通知 if: success() run: echo "🎉 部署成功!项目已发布到 CloudBase 静态托管" - name: 部署失败通知 if: failure() run: echo "❌ 部署失败,请检查配置和日志" ``` --- ## 使用 CLI 管理静态托管 # 使用 CLI 管理静态托管 ## 查看静态网站服务信息 您可以使用下面的命令展示静态网站的状态,访问域名等信息。 ```bash cloudbase hosting detail -e envId ``` ## 部署文件 您可以使用下面的命令将文件上传到静态网站的存储空间中的指定路径,当不指定 cloudPath 时,CLI 会将文件上传到根目录。 ```bash cloudbase hosting deploy localPath cloudPath -e envId ``` ```bash # 将当前目录的文件部署到根目录 cloudbase hosting deploy . -e envId # 将 static 目录下的 index.js 文件部署到 static/index.js cloudbase hosting deploy ./static/index.js static/index.js -e envId ``` ## 删除文件和文件夹 您可以使用下面的命令删除静态网站的存储空间中的文件: ```bash cloudbase hosting delete cloudPath -e envId ``` 您可以使用下面的命令删除静态网站的存储空间中的文件夹: ```bash cloudbase hosting delete -d cloudPath -e envId ``` ## 查看文件列表 您可以使用下面的命令部署展示静态网站存储空间中文件。 ```bash cloudbase hosting list -e envId ``` :::tip 提示 Windows 系统中 localPath 为本地路径形式,是系统可以识别的路径,通常使用`\`分隔符。`cloudPath`是云端文件路径,均需要使用`/`分隔符。 ::: - `localPath`为本地文件或文件夹的路径,为`目录/文件名`的形式,例如`./index.js`、`static/css/index.css`等。 - `cloudPath`为文件或文件夹的相对根目录的路径,为`目录/文件名`的形式,例如`index.js`、`static/css/index.js`等。 --- ## 自定义域名 # 自定义域名 CloudBase 静态网站托管提供了可供开发、测试使用的默认域名,在开发期间,您可以通过默认域名访问静态网站。默认域名有一定的**访问频率限制**,超过访问频率限制,默认域名将不可访问。 对于生产环境的应用,我们推荐您使用自定义域名来避免限频,加速用户的访问。 ## 添加自定义域名 1. 登录 [云开发 CloudBase 控制台](https://console.cloud.tencent.com/tcb),进入 [静态网站托管](https://console.cloud.tencent.com/tcb/hosting) 页面,选择「基础设置」,在「域名信息」板块中,单击「添加域名」,进行域名添加,如下图所示: ![](https://main.qcloudimg.com/raw/f469527ecc47ae43d424f72b3451e58a.png) 2. 添加后,系统会为您自动分配一个以 `.cdn.dnsv1.com` 为后缀的 CNAME 域名,CNAME 域名不能直接访问,您需要在域名服务提供商处完成 CNAME 配置,配置生效后,您的托管服务方可对自定义域名生效,如何配置 CNAME 请参考下文。 ## 强制 HTTPS 开启后,所有对于自定义域名的 HTTP 请求,都会被转换为 HTTPS 请求。 开启此项功能可以提高您的网站安全性,建议您不要主动关闭此功能。 ## CNAME 配置 ### 腾讯云设置方法 若您的 DNS 服务商为腾讯云,您可通过如下步骤添加 CNAME 记录。 1. 登录 [域名服务](https://console.cloud.tencent.com/domain) 控制台,在列表中,找到需要添加 CNAME 记录的域名所在行,单击操作栏的「解析」。 ![CNAME配置](https://main.qcloudimg.com/raw/12eba66e1d073aade459318d6e9c53ef.png) 2. 在跳转到的页面中,单击「添加记录」。 ![](https://main.qcloudimg.com/raw/88a0cda619aeaf1a88120ad5294250fa.png) 3. 在 **主机记录** 处填写域名前缀(例如:www),将 **记录类型** 设置为 CNAME,在 **记录值** 处填写 CNAME 域名,单击「保存」,即可添加 CNAME 记录。 ![](https://main.qcloudimg.com/raw/24ee35e7bba9d181abbdaf65fe7fc3cb.png) :::tip 提示 域名解析各种记录类型之间是有优先级差异的,在主机记录相同的情况下,同一条线路有几种不同的记录类型不能共存,否则将会提示冲突。CNAME 记录与除 CNAME 记录以外的任何记录类型都冲突,需要先删除掉其他记录,再进行配置。详情请参见 [为什么添加解析记录的时候提示 "记录有冲突" ](https://cloud.tencent.com/document/product/302/3468#.E4.B8.BA.E4.BB.80.E4.B9.88.E6.B7.BB.E5.8A.A0.E8.A7.A3.E6.9E.90.E8.AE.B0.E5.BD.95.E7.9A.84.E6.97.B6.E5.80.99.E6.8F.90.E7.A4.BA-.26quot.3B.E8.AE.B0.E5.BD.95.E6.9C.89.E5.86.B2.E7.AA.81.26quot.3B-.EF.BC.9F)。 ::: ### DNSPod 设置方法 若您的 DNS 服务商为 DNSPod,登录 [DNSPod 域名服务控制台](https://console.dnspod.cn/dns/list),在列表中,找到需要添加 CNAME 记录的域名所在行,单击对应域名名称,跳转至“添加记录”界面,通过如下步骤添加 CNAME 记录。 ![](https://main.qcloudimg.com/raw/c5e256fcc42261105b674151aa6561a3.png) 1. 主机记录处填子域名(例如需要添加`www.123.com`的解析,只需要在主机记录处填写`www`即可。如果只是想添加`123.com`的解析,主机记录直接留空,系统会自动填一个“@”到输入框内,@的 CNAME 会影响到 MX 记录的正常解析,添加时慎重考虑)。 2. 记录类型为 CNAME。 3. 线路类型(默认为必填项,否则会导致部分用户无法解析。在上图中,默认的作用为:除了联通用户之外的所有用户,都会指向 1.com)。 4. 记录值为 CNAME 指向的域名,只可以填写域名,记录生成后会自动在域名后面补一个“.”,这是正常现象。 5. MX 优先级不需要填写。 6. TTL 不需要填写,添加时系统会自动生成,默认为 600 秒(TTL 为缓存时间,数值越小,修改记录各地生效时间越快)。 ### 万网设置方法 若您的 DNS 服务商为万网,您可通过如下步骤添加 CNAME 记录。 1. 登录万网会员中心。 2. 单击会员中心左侧导航栏中的「产品管理」> 「我的云解析」进入万维网云解析列表页。 3. 单击要解析的域名,进入解析记录页。 4. 进入解析记录页后,单击新增解析按钮,开始设置解析记录。 ![](https://main.qcloudimg.com/raw/54825b2a66e6752cd451d79d72929833.png) 5. 若要设置 CNAME 解析记录,将记录类型选择为 CNAME。主机记录即域名前缀,可任意填写(如:`www`)。记录值填写为当前域名指向的另一个域名。解析线路,TTL 默认即可。 ![](https://main.qcloudimg.com/raw/b321d20332ca1b93eb78376cac43683b.png) 6. 填写完成后,单击「保存」,完成解析设置。 ### 新网设置方法 若您的 DNS 服务商为新网,您可通过如下步骤添加 CNAME 记录。 **设置别名(CNAME 记录)** 即:别名记录。这种记录允许您将多个名字映射到同一台计算机。通常用于同时提供 WWW 和 MAIL 服务的计算机。例如,有一台计算机名为`host.mydomain.com`(A 记录)。它同时提供 WWW 和 MAIL 服务,为了便于用户访问服务。可以为该计算机设置两个别名(CNAME):WWW 和 MAIL 。如下图: ![](https://main.qcloudimg.com/raw/2e93d51c7fe8502670475d71bbfb20cb.png) ## 验证 CNAME 是否生效 不同的 DNS 服务商,CNAME 生效的时间略有不同,一般会在半个小时之内生效。您也可以通过 dig 的方式来查询 CNAME 是否生效,如果 dig 到后缀为 `.cdn.dnsv1.com` 的域名,表示域名 CNAME 已生效。 --- ## 概述 # 概述 CloudBase 静态网站托管可以为您的 Web 应用、静态资源提供快速、安全的托管服务。只需要一个命令,并可以快速地部署静态资源,并且使用 CDN(内容分发网络)加快资源的访问速度。 ## 主要功能 ### HTTPS CloudBase 静态网站托管内置 HTTP 与 HTTPS,无需额外配置即可使用。 ### 自定义域名 CloudBase 静态网站托管支持自定义域名,用户可以通过使用您的私有域名访问静态资源,详情请参考 [自定义域名](/service/custom-domain)。 ### 快速分发 静态资源将会被缓存在遍布各地的 CDN 边缘服务器上。无论您的用户身处何处,内容都可快速加载。 ### 命令行部署 利用 CloudBase CLI,您可以轻松部署您的文件到 CloudBase。 --- ## 控制台管理静态资源 # 控制台管理静态资源 本文档介绍如何管理 CloudBase 静态托管服务,包括资源管理、域名配置、安全设置等核心功能。 ## 概述 CloudBase 静态托管为您提供了完整的静态网站管理能力,支持文件上传、域名绑定、缓存配置、安全防护等功能。通过 [云开发CloudBase/静态网站托管](https://console.cloud.tencent.com/tcb/hosting/index) 可以便捷地管理您的静态网站。 ## 资源管理 ![](https://qcloudimg.tencent-cloud.cn/raw/e562eda285e2f7caeee55908039da5ad.png) ### 基本操作 在静态托管控制台中,您可以执行以下操作: * **文件管理**:上传、下载、删除文件 * **文件夹管理**:创建、删除文件夹 * **批量操作**:支持批量上传和删除 * **在线编辑**:支持在线编辑文本文件 ### 文件命名规范 :::tip 命名要求 * 文件和文件夹名称仅支持数字、中英文字符组合 * 名称长度限制为 255 个字符 * 建议使用有意义的命名,便于管理和维护 ::: ### 服务状态 :::info 自动管理 静态托管服务无需手动启停: * 当托管空间内有文件时,服务自动运行 * 当托管空间为空时,服务自动暂停 * 暂停状态下不产生费用 ::: ## 域名管理 ### 默认域名 CloudBase 为每个静态托管提供默认域名,特点如下: * **免费使用**:无需额外配置即可访问 * **测试用途**:适合开发和测试阶段使用 * **访问限制**:存在访问频率限制,超限后暂时不可访问 ### 自定义域名 为了获得更好的访问体验和品牌展示,建议配置自定义域名: * **无访问限制**:不受默认域名的频率限制 * **品牌展示**:使用自己的域名提升品牌形象 * **SEO 友好**:有利于搜索引擎优化 :::tip 推荐配置 建议为生产环境配置自定义域名,详细配置方法请参考 [配置自定义域名](/service/custom-domain)。 ::: ## 索引文档配置 ![](https://qcloudimg.tencent-cloud.cn/raw/0c36b73b387687de6b0c8dd0c1d53264.png) ### 默认索引文档 * **默认文件**:`index.html` * **作用范围**:根目录和所有子目录 * **访问行为**:访问目录时自动返回索引文档 ### 配置建议 :::tip 最佳实践 * 在根目录和重要子目录下都放置 `index.html` 文件 * 确保索引文档内容完整,提供良好的用户体验 * 可以在索引文档中添加导航链接,方便用户访问其他页面 ::: ## 重定向规则 重定向规则帮助您处理 URL 变更和错误页面,提升用户体验。 ### 应用场景 * **文件迁移**:文件移动或重命名后的 URL 重定向 * **URL 简化**:将长 URL 重定向到短 URL * **错误处理**:自定义 404 等错误页面 * **SEO 优化**:保持搜索引擎排名 ### 规则类型 #### 1. 错误码重定向 针对 HTTP 错误状态码(如 404、403)进行重定向: * **支持范围**:4xx 错误码 * **自定义页面**:可以设计友好的错误页面 * **用户引导**:在错误页面提供导航和帮助信息 #### 2. 前缀匹配重定向 基于 URL 前缀进行重定向: * **灵活匹配**:支持文件和文件夹的前缀匹配 * **批量重定向**:一条规则可以处理多个相似 URL * **路径映射**:将旧路径映射到新路径 **示例场景**: ``` 旧路径:docs/guide.html 新路径:documents/guide.html 规则:docs/ → documents/ ``` ### 配置注意事项 :::warning 重要提醒 * **优先级**:重定向规则优先级高于索引文档配置 * **路径格式**:替换路径只需填写相对路径,无需包含域名 * **测试验证**:配置后请充分测试确保重定向正常工作 ::: ## 缓存配置 合理的缓存配置可以显著提升网站访问速度,减少带宽消耗。 ![](https://qcloudimg.tencent-cloud.cn/raw/9810ac5ba3b786bc363523142da6b6d4.png) ### 缓存类型 CloudBase 静态托管支持两级缓存: 1. **浏览器缓存**:在用户浏览器中缓存资源 2. **节点缓存**:在 CDN 节点中缓存资源 ### 配置方式 支持多种缓存配置方式: * **文件后缀**:如 `.jpg`、`.png`、`.css`、`.js` * **文件夹**:如 `/static`、`/assets`、`/images` * **文件路径**:如 `/static/*.js`、`/css/main.css` ### 缓存策略建议 | 资源类型 | 建议缓存时间 | 说明 | |---------|-------------|------| | 图片文件 | 30 天 | 图片通常不经常变更 | | CSS/JS 文件 | 7 天 | 样式和脚本文件相对稳定 | | HTML 文件 | 1 小时 | 页面内容可能经常更新 | | 字体文件 | 30 天 | 字体文件很少变更 | :::tip 缓存机制 * 缓存时间以 `Cache-Control: max-age=` 形式设置 * 控制台上传文件会自动刷新 CDN 缓存 * 用户访问时优先使用浏览器缓存,其次是节点缓存 ::: ## 安全配置 CloudBase 静态托管提供多层安全防护,保护您的资源免受恶意访问。 ![](https://qcloudimg.tencent-cloud.cn/raw/1ff50a97d1c40316afc255c0a3c2a63b.png) ### 防盗链配置 通过 Referer 检查防止资源被盗用: #### 黑名单模式 * **功能**:拒绝指定域名的访问请求 * **适用场景**:已知恶意域名的防护 * **配置方式**:添加需要拒绝的域名列表 #### 白名单模式 * **功能**:仅允许指定域名的访问请求 * **适用场景**:严格控制访问来源 * **配置方式**:添加允许访问的域名列表 :::info 检测机制 CloudBase 通过检查 HTTP 请求头中的 `Referer` 字段来判断请求来源,非法请求将返回 403 状态码。 ::: ### IP 访问控制 #### IP 黑白名单 **支持格式**: * IPv4 地址:`192.168.1.1` * IPv4 网段:`192.168.1.0/24`、`10.0.0.0/8` * IPv6 地址:完整的 IPv6 地址格式 **配置模式**: * **黑名单**:阻止指定 IP 或网段的访问 * **白名单**:仅允许指定 IP 或网段的访问 #### IP 访问限频 * **功能**:限制单个 IP 的访问频率 * **防护效果**:可防御部分 CC 攻击 * **配置建议**:根据业务需求合理设置限频阈值 :::warning 配置提醒 IP 访问限频可能影响正常用户访问,请根据实际业务情况谨慎配置。建议先在测试环境验证配置效果。 ::: --- ## 快速开始 # 快速开始 本文档将指导您快速上手云开发静态网站托管服务,通过控制台管理和部署您的静态网站文件。 ## 概述 云开发静态网站托管为您提供便捷的静态资源(HTML、CSS、JavaScript、图片等)托管服务,支持自定义域名、HTTPS、CDN 加速等功能。 ## 前置条件 在开始之前,请确保您已经: * 拥有腾讯云账号并完成实名认证 * 创建了云开发环境 ## 第 1 步:开通静态网站托管 1. 进入 [云开发CloudBase/静态网站托管](https://console.cloud.tencent.com/tcb/hosting/index) 2. 选择您的环境,点击左侧菜单中的「静态网站托管」 3. 点击「开通静态网站托管」按钮 ![开通静态网站托管](https://qcloudimg.tencent-cloud.cn/raw/e562eda285e2f7caeee55908039da5ad.png) :::tip 提示 * 首次开通过程大约需要 1-3 分钟 * 开通后会自动分配一个默认域名,格式为:`环境ID.xxx.tcloudbaseapp.com` * 静态网站托管服务容量等具体请参考 [计费说明](https://cloud.tencent.com/document/product/876/75213) ::: ## 第 2 步:准备网站文件 创建一个简单的 HTML 文件作为示例,命名为 `index.html` : ```html 欢迎使用云开发静态网站托管 body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; margin: 0; padding: 40px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; text-align: center; min-height: 100vh; display: flex; align-items: center; justify-content: center; flex-direction: column; } .container { max-width: 600px; } h1 { font-size: 2.5em; margin-bottom: 20px; } p { font-size: 1.2em; line-height: 1.6; margin-bottom: 30px; } .btn { display: inline-block; padding: 12px 24px; background: rgba(255, 255, 255, 0.2); border: 2px solid white; border-radius: 25px; color: white; text-decoration: none; transition: all 0.3s ease; } .btn:hover { background: white; color: #667eea; } 🎉 恭喜! 您的静态网站已成功部署到云开发平台 现在您可以开始构建您的网站了 查看文档 ``` :::info 说明 您也可以准备其他类型的文件: * CSS 样式文件 * JavaScript 脚本文件 * 图片、字体等静态资源 * 单页应用(SPA)构建产物 ::: ## 第 3 步:上传文件 ### 方式一:控制台上传 1. 在静态网站托管页面,点击「上传文件」按钮 2. 选择准备好的 `index.html` 文件 3. 点击「确定」完成上传 ![上传文件](https://qcloudimg.tencent-cloud.cn/raw/1e0a277e1b6bdbb760a88d807aed4976.png) ### 方式二:批量上传 如果您有多个文件需要上传: 1. 点击「上传文件夹」按钮 2. 选择包含网站文件的整个文件夹 3. 系统会保持原有的目录结构进行上传 :::warning 注意事项 * 单个文件大小限制为 50MB * 文件名不能包含特殊字符,建议使用英文、数字、下划线和连字符 * 上传会覆盖同名文件,请谨慎操作 ::: ## 第 4 步:访问您的网站 ### 访问规则 静态资源的访问链接格式为: `默认域名/文件路径` * **默认域名**:`环境ID.xxx.tcloudbaseapp.com` * **默认索引文档**:`index.html` ### 访问示例 假设您的环境 ID 为 `my-env-123.xxx` ,则访问链接如下: | 文件路径 | 访问链接 | 说明 | |---------|---------|------| | `/index.html` | `https://my-env-123.xxx.tcloudbaseapp.com` | 根目录默认页面 | | `/about/index.html` | `https://my-env-123.xxx.tcloudbaseapp.com/about` | 子目录默认页面 | | `/css/style.css` | `https://my-env-123.xxx.tcloudbaseapp.com/css/style.css` | CSS 文件 | | `/images/logo.png` | `https://my-env-123.xxx.tcloudbaseapp.com/images/logo.png` | 图片文件 | ### 验证部署 1. 复制您的默认域名 2. 在浏览器中打开该链接 3. 如果看到您上传的页面内容,说明部署成功 ![](https://qcloudimg.tencent-cloud.cn/raw/9e1f35ebdfb49d70a89732e5d2507b2d.png) ## 下一步 恭喜您成功部署了第一个静态网站!接下来您可以: * [配置自定义域名](/service/custom-domain) - 使用您自己的域名访问网站 --- ## AI Agent 接入 import ApiLogo from "@theme/ApiLogo"; import SchemaTabs from "@theme/SchemaTabs"; import TabItem from "@theme/TabItem"; import Export from "@theme/ApiExplorer/Export"; Version: 1.0.0 AI Agent 接入 # 功能介绍 无论你是否有编程基础,都可以在云后台上快速搭建基于 AI 模型的各类问答 Agent。而且你还可以将搭建的 Agent 发布到小程序客服、服务号、公众号、微信客服,让更多的用户与你搭建的 Agent 聊天。 我们已经将 AI Agent 发布为 API 服务,你可以通过 HTTP 访问方式与 Agent 进行交互。 该系列开放 API 提供了统一对接 AI Agent 的能力,只需在云开发环境中配置所需 Agent 的 token,即可快速接入 Agent。该系列接对话接口支持 [SSE](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events) 格式响应。 # 接入指引 调用以下接口需要传递 AccessToken,格式如`Authorization: Bearer `。Token 获取方式参考: [获取token](https://docs.cloudbase.net/http-api/basic/access-token) # HTTP 状态码 根据返回结果的不同,可能会出现 `2xx`, `4xx`, `5xx` 状态码。Agent 在 200 状态码中通过响应体指示错误,应当视情况处理。 # 错误码 以下列出了该系列 API 特定的错误码 错误码 含义 AGENT_INVALID_PARAM 调用 Agent 参数不合法 AGENT_GET_INFO_ERROR 查询 Agent 信息失败 AGENT_REQUEST_LLM_ERROR Agent 调用大模型异常 AGENT_REQUEST_KNOWLEDGE_ERROR Agent 查询知识库异常 AGENT_SERVER_ERR Agent 系统异常 Authentication 环境 ID 所对应的 token,使用登录认证(v2)获取 Security Scheme Type:httpHTTP Authorization Scheme:bearer --- ## 创建会话 import ApiTabs from "@theme/ApiTabs"; import DiscriminatorTabs from "@theme/DiscriminatorTabs"; import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes"; import MimeTabs from "@theme/MimeTabs"; import ParamsItem from "@theme/ParamsItem"; import ResponseSamples from "@theme/ResponseSamples"; import SchemaItem from "@theme/SchemaItem"; import SchemaTabs from "@theme/SchemaTabs"; import Heading from "@theme/Heading"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; 创建会话 创建会话 ## Request Path ParametersSchema --- ## 查询 Agent 信息 import ApiTabs from "@theme/ApiTabs"; import DiscriminatorTabs from "@theme/DiscriminatorTabs"; import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes"; import MimeTabs from "@theme/MimeTabs"; import ParamsItem from "@theme/ParamsItem"; import ResponseSamples from "@theme/ResponseSamples"; import SchemaItem from "@theme/SchemaItem"; import SchemaTabs from "@theme/SchemaTabs"; import Heading from "@theme/Heading"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; 查询 Agent 信息 查询 Agent 信息 ## Request Path Parameters 查询 AI Agent 成功时返回 Response HeadersX-Request-Id string 请求ID Schema 查询 AI Agent 失败时返回 Schema --- ## 查询 Agent 列表信息 import ApiTabs from "@theme/ApiTabs"; import DiscriminatorTabs from "@theme/DiscriminatorTabs"; import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes"; import MimeTabs from "@theme/MimeTabs"; import ParamsItem from "@theme/ParamsItem"; import ResponseSamples from "@theme/ResponseSamples"; import SchemaItem from "@theme/SchemaItem"; import SchemaTabs from "@theme/SchemaTabs"; import Heading from "@theme/Heading"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; 查询 Agent 列表信息 查询 Agent 列表信息 ## Request Query Parameters 查询 AI Agent 成功时返回 Response HeadersX-Request-Id string 请求ID SchemabotList object[]required Agent 列表 Array [] 查询 AI Agent 失败时返回 Schema --- ## 查询 Agent 历史对话信息 import ApiTabs from "@theme/ApiTabs"; import DiscriminatorTabs from "@theme/DiscriminatorTabs"; import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes"; import MimeTabs from "@theme/MimeTabs"; import ParamsItem from "@theme/ParamsItem"; import ResponseSamples from "@theme/ResponseSamples"; import SchemaItem from "@theme/SchemaItem"; import SchemaTabs from "@theme/SchemaTabs"; import Heading from "@theme/Heading"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; 查询 Agent 历史对话信息 查询 Agent 历史对话信息 ## Request Path ParametersQuery Parameters 查询聊天记录成功时返回 Response HeadersX-Request-Id string 请求ID SchemarecordList object[]required 历史对话列表 Array [] 查询聊天记录失败时返回 Schema --- ## 查询会话列表 import ApiTabs from "@theme/ApiTabs"; import DiscriminatorTabs from "@theme/DiscriminatorTabs"; import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes"; import MimeTabs from "@theme/MimeTabs"; import ParamsItem from "@theme/ParamsItem"; import ResponseSamples from "@theme/ResponseSamples"; import SchemaItem from "@theme/SchemaItem"; import SchemaTabs from "@theme/SchemaTabs"; import Heading from "@theme/Heading"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; 查询会话列表 查询会话列表 ## Request Path ParametersQuery ParametersSchemadata object[]required 会话查询结果 Array [] --- ## 获取推荐问题 import ApiTabs from "@theme/ApiTabs"; import DiscriminatorTabs from "@theme/DiscriminatorTabs"; import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes"; import MimeTabs from "@theme/MimeTabs"; import ParamsItem from "@theme/ParamsItem"; import ResponseSamples from "@theme/ResponseSamples"; import SchemaItem from "@theme/SchemaItem"; import SchemaTabs from "@theme/SchemaTabs"; import Heading from "@theme/Heading"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; 获取推荐问题 获取推荐问题 ## Request Path ParametersBodyrequiredhistory object[] 历史对话信息 Array [] 获取推荐问题成功时返回, 返回格式为 SSE 格式 Response HeadersX-Request-Id string 请求ID Schemausage object token使用量 search_info object 搜索结果信息,需要开启联网查询 search_results undefined[] 搜索引文信息 Array [] 获取推荐问题失败时返回 Schema --- ## 文字转语音结果轮询 import ApiTabs from "@theme/ApiTabs"; import DiscriminatorTabs from "@theme/DiscriminatorTabs"; import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes"; import MimeTabs from "@theme/MimeTabs"; import ParamsItem from "@theme/ParamsItem"; import ResponseSamples from "@theme/ResponseSamples"; import SchemaItem from "@theme/SchemaItem"; import SchemaTabs from "@theme/SchemaTabs"; import Heading from "@theme/Heading"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; 文字转语音结果轮询 文字转语音结果轮询 ## Request Path ParametersQuery ParametersSchema object --- ## 进行 Agent 问答对话(OpenAI 协议) import ApiTabs from "@theme/ApiTabs"; import DiscriminatorTabs from "@theme/DiscriminatorTabs"; import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes"; import MimeTabs from "@theme/MimeTabs"; import ParamsItem from "@theme/ParamsItem"; import ResponseSamples from "@theme/ResponseSamples"; import SchemaItem from "@theme/SchemaItem"; import SchemaTabs from "@theme/SchemaTabs"; import Heading from "@theme/Heading"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; 进行 Agent 问答对话(OpenAI 协议) 进行 Agent 问答对话(OpenAI 协议) ## Request Bodyrequiredmessages object[]required 消息 Array [] Agent 对话成功时,非流失返回 Response HeadersX-Request-Id string 请求ID Schemachoices undefined[] choices Array [message object]usage object token使用量 Agent 对话成功时,流失返回 Schemachoices undefined[] choices Array [delta object]usage object token使用量 Agent 对话失败时返回 Schema --- ## 进行 Agent 问答对话 import ApiTabs from "@theme/ApiTabs"; import DiscriminatorTabs from "@theme/DiscriminatorTabs"; import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes"; import MimeTabs from "@theme/MimeTabs"; import ParamsItem from "@theme/ParamsItem"; import ResponseSamples from "@theme/ResponseSamples"; import SchemaItem from "@theme/SchemaItem"; import SchemaTabs from "@theme/SchemaTabs"; import Heading from "@theme/Heading"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; 进行 Agent 问答对话 进行 Agent 问答对话 ## Request Path ParametersBodyrequiredhistory object[] 历史对话信息 Array [] Agent 对话成功时返回, 返回格式为 SSE 格式 Response HeadersX-Request-Id string 请求ID Schemausage object token使用量 search_info object 搜索结果信息,需要开启联网查询 search_results undefined[] 搜索引文信息 Array [] Agent 对话失败时返回 Schema --- ## 语音转文字 import ApiTabs from "@theme/ApiTabs"; import DiscriminatorTabs from "@theme/DiscriminatorTabs"; import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes"; import MimeTabs from "@theme/MimeTabs"; import ParamsItem from "@theme/ParamsItem"; import ResponseSamples from "@theme/ResponseSamples"; import SchemaItem from "@theme/SchemaItem"; import SchemaTabs from "@theme/SchemaTabs"; import Heading from "@theme/Heading"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; 语音转文字 语音转文字 ## Request Path ParametersBodyrequiredSchema object --- ## 文字转语音 import ApiTabs from "@theme/ApiTabs"; import DiscriminatorTabs from "@theme/DiscriminatorTabs"; import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes"; import MimeTabs from "@theme/MimeTabs"; import ParamsItem from "@theme/ParamsItem"; import ResponseSamples from "@theme/ResponseSamples"; import SchemaItem from "@theme/SchemaItem"; import SchemaTabs from "@theme/SchemaTabs"; import Heading from "@theme/Heading"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; 文字转语音 文字转语音 ## Request Path ParametersBodyrequiredSchema object --- ## AI 大模型接入 import ApiLogo from "@theme/ApiLogo"; import SchemaTabs from "@theme/SchemaTabs"; import TabItem from "@theme/TabItem"; import Export from "@theme/ApiExplorer/Export"; Version: 1.0.0 AI 大模型接入 # 功能介绍 该系列开放 API 提供了统一对接各个大模型的能力,只需在云开发环境中配置所需大模型的 token(或其他大模型要求的认证方式),即可快速接入不同大模型。该系列模型支持 [SSE](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events) 格式响应。 # 接入指引 调用以下接口需要传递 AccessToken,格式如`Authorization: Bearer `。Token 获取方式参考:https://docs.cloudbase.net/http-api/basic/access-token # HTTP 状态码 根据返回结果的不同,可能会出现 `2xx`, `4xx`, `5xx` 状态码。某些大模型会在`200`状态码中通过响应体指示错误,应当视情况处理。 # 错误码 以下列出了该系列 API 特定的错误码,完整列表参考:https://docs.cloudbase.net/error-code/service 错误码 含义 AI_MODEL_CONFIG_MISSING 缺少 API Key 等调用模型的必要配置 AI_MODEL_PARAM_INVALID 调用模型的参数异常 AI_MODEL_REQUEST_FAILED 请求模型失败 AI_MODEL_DISABLED 模型已停用,请在控制台上检查模型是否启用,或稍等 2 分钟再试。 AI_MODEL_NOT_FOUND 未找到指定模型 EXCEED_CONCURRENT_REQUEST_LIMIT 调用接口超出并发限制,请稍等片刻再试,或提交工单申请提高并发。 EXCEED_TOKEN_QUOTA_LIMIT 大模型 Token 用量已超出配额,请购买资源包以提升配额。 Authentication 环境 ID 所对应的 token,使用登录认证(v2)获取 Security Scheme Type:httpHTTP Authorization Scheme:bearer TC3-HMAC-SHA256开头的腾讯云 3.0 版签名,将 Timestamp 和 Token 拼接在签名最后 Security Scheme Type:apiKeyHeader parameter name:AuthorizationContactTCB: URL: https://cloud.tencent.com/product/tcbLicenseApache 2.0 --- ## 调用大模型服务 import ApiTabs from "@theme/ApiTabs"; import DiscriminatorTabs from "@theme/DiscriminatorTabs"; import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes"; import MimeTabs from "@theme/MimeTabs"; import ParamsItem from "@theme/ParamsItem"; import ResponseSamples from "@theme/ResponseSamples"; import SchemaItem from "@theme/SchemaItem"; import SchemaTabs from "@theme/SchemaTabs"; import Heading from "@theme/Heading"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; 调用大模型服务 当调用大模型时需要传递额外路径时,可追加 `path` 参数,如 `v1/chat/completions`。具体路径定义参考各大模型文档。 ### 流式输出 (server-sent events) 当启用流式输出时,应显式在请求头 `Accept` 中指定 `text/event-stream`,否则请求将在 60 秒后超时。 ## Request Path Parameters `hunyuan-exp`: 混元体验版 `deepseek`: 体验版 \n或填写在控制台上配置的其他自定义模型分组。","required":true,"schema":{"oneOf":[{"description":"调用的模型代码,下列平台提供的模型组中的任意一个: `hunyuan-exp`: 混元体验版 `deepseek`: 体验版 \n或填写在控制台上配置的其他自定义模型分组。","type":"string","enum":["hunyuan-exp","deepseek"],"title":"ModelEnum"},{"type":"string","nullable":false,"example":"qwen","title":"ModelCustom"}]}}}>Bodyrequired 请求参数参考各个大模型文档进行传递。 object 调用大模型成功时返回(不一定返回正确结果) Response HeadersX-Request-Id string 请求ID SchemaSchema string 请求失败 Response HeadersX-Request-Id string 请求ID Schema缺少调用模型的必要配置,如 token, clientID 等(400)调用模型的参数异常(400)请求模型失败(400) 请求失败 Response HeadersX-Request-Id string 请求ID Schema未启用大模型(404)未找到指定模型(404) 通用报错信息,详见 https://docs.cloudbase.net/error-code/service Response HeadersX-Request-Id string 请求ID Schema请求地址异常 --- ## 大模型接入服务 ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## 获取三方登录的回调地址 import ApiTabs from "@theme/ApiTabs"; import DiscriminatorTabs from "@theme/DiscriminatorTabs"; import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes"; import MimeTabs from "@theme/MimeTabs"; import ParamsItem from "@theme/ParamsItem"; import ResponseSamples from "@theme/ResponseSamples"; import SchemaItem from "@theme/SchemaItem"; import SchemaTabs from "@theme/SchemaTabs"; import Heading from "@theme/Heading"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; 获取三方登录的回调地址 获取三方登录的回调地址 ## Request Query ParametersHeader Parameters A successful response. Response HeadersSchema An unexpected error response. Response HeadersSchema --- ## 获取三方授权信息 import ApiTabs from "@theme/ApiTabs"; import DiscriminatorTabs from "@theme/DiscriminatorTabs"; import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes"; import MimeTabs from "@theme/MimeTabs"; import ParamsItem from "@theme/ParamsItem"; import ResponseSamples from "@theme/ResponseSamples"; import SchemaItem from "@theme/SchemaItem"; import SchemaTabs from "@theme/SchemaTabs"; import Heading from "@theme/Heading"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; 获取三方授权信息 获取三方服务的授权信息,如通过oauth登录,获取oauth client对应的授权用户信息生成一个provider_token, 调用身份源登录接口需要 ## Request Query ParametersHeader ParametersBody A successful response. Response HeadersSchemaprovider_profile objectmeta object An unexpected error response. Response HeadersSchema --- ## 获取或刷新token import ApiTabs from "@theme/ApiTabs"; import DiscriminatorTabs from "@theme/DiscriminatorTabs"; import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes"; import MimeTabs from "@theme/MimeTabs"; import ParamsItem from "@theme/ParamsItem"; import ResponseSamples from "@theme/ResponseSamples"; import SchemaItem from "@theme/SchemaItem"; import SchemaTabs from "@theme/SchemaTabs"; import Heading from "@theme/Heading"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; 获取或刷新token ### 1.Refresh Token 刷新机制 #### 接口说明 通过有效的refresh_token获取新的access_token,原refresh_token随即失效(符合RFC 6749 Section 6) #### 请求示例: ``` { "client_id": "mock_AAU5Pw78ioGQnUP4", "grant_type": "refresh_token", "refresh_token": "mock_m.yPxK8mLnVrQwEoDzFcHbNtGsYvXpRjWq-3eSd2fA1gU5iI9kO0lP7uJ4mT6nB8yC_1xZ2vD3aQ4wF5eR6tG7hY8jM9kL0oN1iP2uK3lQ4mW5nX6bV7cC8dA9fS0gH1jJ2kL3mN4o" } ``` ### 2.密码模式认证 #### 接口说明 基于Resource Owner Password Credentials Grant(RFC 6749 Section 4.3)获取access_token #### 请求示例: ``` { "client_id": "mock_AAU5Pw78ioGQnUP4", "grant_type": "password", "username": "mock_user001", "password": "mock_password@123" } ``` ### 3.客户端凭证模式 #### 接口说明 采用Client Credentials Grant(RFC 6749 Section 4.4)获取服务端access_token #### 认证方式 ``` 请求头添加: Authorization: Basic ${base64(SecretId:SecretKey)} ``` ``` { "client_id": "mock_AAU5Pw78ioGQnUP4", "grant_type": "client_credentials" } ``` #### 关键特性: - 不返回refresh_token - 自动授予超级管理员权限 - 需通过[腾讯云cam](https://console.cloud.tencent.com/cam/capi)获取SecretId/SecretKey #### 安全规范: - SecretKey需存储于安全介质 - 调用方需具备服务端可信环境 ## Request Query ParametersHeader ParametersBody A successful response. Response HeadersSchema An unexpected error response. Response HeadersSchema --- ## 匿名登录 import ApiTabs from "@theme/ApiTabs"; import DiscriminatorTabs from "@theme/DiscriminatorTabs"; import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes"; import MimeTabs from "@theme/MimeTabs"; import ParamsItem from "@theme/ParamsItem"; import ResponseSamples from "@theme/ResponseSamples"; import SchemaItem from "@theme/SchemaItem"; import SchemaTabs from "@theme/SchemaTabs"; import Heading from "@theme/Heading"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; 匿名登录 同一个设备ID,最多只能注册一个匿名用户, 生成一个匿名用户的access_token ## Request Query Parameters身份认证-->开发设置获取。默认为环境id,可以不传","required":false,"schema":{"type":"string"}}}>Header ParametersBody A successful response. Response HeadersSchema - invalid_argument请在请求头添加设备id,x-device-id在Header中未传入 - unimplemented请联系管理员开启匿名登录,匿名登录未开启,前往云开发平台开启 Response HeadersSchemaResponse HeadersSchema An unexpected error response. Response HeadersSchema --- ## 第三方授权token登录 import ApiTabs from "@theme/ApiTabs"; import DiscriminatorTabs from "@theme/DiscriminatorTabs"; import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes"; import MimeTabs from "@theme/MimeTabs"; import ParamsItem from "@theme/ParamsItem"; import ResponseSamples from "@theme/ResponseSamples"; import SchemaItem from "@theme/SchemaItem"; import SchemaTabs from "@theme/SchemaTabs"; import Heading from "@theme/Heading"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; 第三方授权token登录 通过三方授权信息生成的provider_token进行登录 ## Request Query ParametersHeader ParametersBody A successful response. Response HeadersSchema An unexpected error response. Response HeadersSchema --- ## 用户名密码登录 import ApiTabs from "@theme/ApiTabs"; import DiscriminatorTabs from "@theme/DiscriminatorTabs"; import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes"; import MimeTabs from "@theme/MimeTabs"; import ParamsItem from "@theme/ParamsItem"; import ResponseSamples from "@theme/ResponseSamples"; import SchemaItem from "@theme/SchemaItem"; import SchemaTabs from "@theme/SchemaTabs"; import Heading from "@theme/Heading"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; 用户名密码登录 - 用户名密码登录,传入username、password; - 手机号验证码登录,传入verification_token ## Request Query Parameters身份认证-->开发设置获取。默认为环境id,可以不传","required":false,"schema":{"type":"string"}}}>Header ParametersBodyResponse HeadersSchema - invalid_username_or_password,用户名或密码有误 - captcha_required,登录失败重试次数过多等原因,需要验证码 - password_not_set,用户密码未设置,需要设置密码 - invalid_status,账号重试次数过多等原因导致账号被锁定,请稍后重试 Response HeadersX-Request-Id stringExample: 1e55ed89-4a2b-47f8-b7de-27b4775c2adb 请求id Schema - username login is disabled by admin,用户名密码未开启,前往https://tcb.cloud.tencent.com身份认证功能开启 Response HeadersSchema --- ## 注册新用户 import ApiTabs from "@theme/ApiTabs"; import DiscriminatorTabs from "@theme/DiscriminatorTabs"; import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes"; import MimeTabs from "@theme/MimeTabs"; import ParamsItem from "@theme/ParamsItem"; import ResponseSamples from "@theme/ResponseSamples"; import SchemaItem from "@theme/SchemaItem"; import SchemaTabs from "@theme/SchemaTabs"; import Heading from "@theme/Heading"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; 注册新用户 注册新用户,适用场景: - 手机号+验证码注册新用户 - 邮箱+验证码注册新用户 - 第三方授权后获取provider_token注册新用户。 可在注册时同时设置用户名、密码。不支持仅传入用户名、密码注册。用户名密码创建用户,请前往云后台创建。 ## Request Query Parameters身份认证-->开发设置获取。默认为环境id,可以不传","required":false,"schema":{"type":"string"}}}>Header ParametersBody A successful response. Response HeadersSchema - you can not signup just by username and password,不允许仅用用户名密码注册,用户身份需经过验证 - phone number login is disabled by admin,手机号登录未开启,需在云开发平台开启 - you can not set phone number and email at same time,手机号、邮箱不可同时设置 Response HeadersSchema --- ## token管理 ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## 发送短信、邮箱验证码 import ApiTabs from "@theme/ApiTabs"; import DiscriminatorTabs from "@theme/DiscriminatorTabs"; import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes"; import MimeTabs from "@theme/MimeTabs"; import ParamsItem from "@theme/ParamsItem"; import ResponseSamples from "@theme/ResponseSamples"; import SchemaItem from "@theme/SchemaItem"; import SchemaTabs from "@theme/SchemaTabs"; import Heading from "@theme/Heading"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; 发送短信、邮箱验证码 #### 接口说明 发送手机号、邮箱验证码,手机号、邮箱根据验证场景传入,不支持同时传入 #### 前置条件 - 需要在云开发平台开启手机号或邮箱登录 - 邮箱登录需配置好SMTP服务器配置 #### 后续登录流程 - is_user为true,直接调用登录接口 - is_user为空或false,调用注册接口进行注册后再登录 ## Request Header ParametersBodyResponse HeadersSchema --- ## 登录认证 ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## 登录认证接口 import ApiLogo from "@theme/ApiLogo"; import SchemaTabs from "@theme/SchemaTabs"; import TabItem from "@theme/TabItem"; import Export from "@theme/ApiExplorer/Export"; Version: 1.0.0 登录认证接口 ### 功能介绍 这里给出了登录认证接口的API,以及每个API的参数参考。 ### 接入指引 ### HTTP 状态码 根据返回结果的不同,可能会出现 `2xx`, `4xx`, `5xx` 状态码。应当视情况处理。 --- ## 第三方登录认证 ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## 自定义登录 import ApiTabs from "@theme/ApiTabs"; import DiscriminatorTabs from "@theme/DiscriminatorTabs"; import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes"; import MimeTabs from "@theme/MimeTabs"; import ParamsItem from "@theme/ParamsItem"; import ResponseSamples from "@theme/ResponseSamples"; import SchemaItem from "@theme/SchemaItem"; import SchemaTabs from "@theme/SchemaTabs"; import Markdown from "@theme/Markdown"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; 自定义登录 ## 适用场景 - 企业自有账号体系与 CloudBase 账号体系的一对一映射 - 需要完全自定义鉴权流程的业务场景 - 需要实现自有账号系统与云开发服务的无缝集成 ## 功能说明 ### 1.服务端签发 Ticket 开发者需在服务端使用 CloudBase SDK 签发登录凭证(Ticket),该凭证用于后续客户端认证 - 参考[自定义登录文档](https://docs.cloudbase.net/authentication-v2/method/custom-login),获取ticket前的部分 #### 代码示例: ``` const cloudbase = require("@cloudbase/node-sdk"); // 1. 初始化 SDK const app = cloudbase.init({ env: "your-env-id", // 传入自定义登录私钥 credentials: require("/path/to/your/tcb_custom_login.json") }); // 2. 开发者自定义的用户唯一身份标识 const customUserId = "your-customUserId"; // 3. 创建ticket const ticket = app.auth().createTicket(customUserId); // 4. 将ticket返回至客户端 return ticket; ``` ### 2.客户端自定义登录 #### 接口说明 客户端使用服务端签发的 Ticket 获取访问凭证 #### 请求示例: ``` { "provider_id": "custom", "ticket": "cd7382ee-2f2f-4edf-831e-2f7c68ed3b43/@@/eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhbGciOiJSUzI1NiIsImVudiI6ImJlZ2luZ3JvdXAtMWc2czgyZTIwNWY5ODNjMCIsImlhdCI6MTc1ODU5NzQ4NzY5MSwiZXhwIjo" } ``` #### 关键特性: - access_token 有效期为 7200 秒(2小时) - refresh_token 有效期为 2592000 秒(30天) - 建议实现 token 自动刷新机制 ## Request Query ParametersHeader ParametersBodyResponse HeadersSchema --- ## 获取图片验证码 import ApiTabs from "@theme/ApiTabs"; import DiscriminatorTabs from "@theme/DiscriminatorTabs"; import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes"; import MimeTabs from "@theme/MimeTabs"; import ParamsItem from "@theme/ParamsItem"; import ResponseSamples from "@theme/ResponseSamples"; import SchemaItem from "@theme/SchemaItem"; import SchemaTabs from "@theme/SchemaTabs"; import Heading from "@theme/Heading"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; 获取图片验证码 #### 接口说明 获取验证码图片RFC 2397标准的内联图片数据URI,响应参数的data字段为图片内容 #### 使用步骤 ##### 1. 获取验证码图片 - 前端调用该接口获取验证码数据 - 将image_base64直接作为的值渲染 - 在本地存储中保存返回的token(建议localStorage) ##### 2. 提交验证码验证 POST /api/v1/captcha/verify ##### 3. 业务接口鉴权 在需要验证码保护的业务请求中附加头部: ```js x-captcha-token: d8f7e2a5c6 ``` ## Request Response HeadersSchema --- ## 验证图片验证码 import ApiTabs from "@theme/ApiTabs"; import DiscriminatorTabs from "@theme/DiscriminatorTabs"; import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes"; import MimeTabs from "@theme/MimeTabs"; import ParamsItem from "@theme/ParamsItem"; import ResponseSamples from "@theme/ResponseSamples"; import SchemaItem from "@theme/SchemaItem"; import SchemaTabs from "@theme/SchemaTabs"; import Heading from "@theme/Heading"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; 验证图片验证码 #### 接口说明 验证验证码图片获取captcha_token。将/auth/v1/captcha/data接口获取的验证码展示在用户界面上,用户识别后进行验证,获取captcha_token ## Request BodyResponse HeadersSchema --- ## 验证短信、邮箱验证码 import ApiTabs from "@theme/ApiTabs"; import DiscriminatorTabs from "@theme/DiscriminatorTabs"; import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes"; import MimeTabs from "@theme/MimeTabs"; import ParamsItem from "@theme/ParamsItem"; import ResponseSamples from "@theme/ResponseSamples"; import SchemaItem from "@theme/SchemaItem"; import SchemaTabs from "@theme/SchemaTabs"; import Heading from "@theme/Heading"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; 验证短信、邮箱验证码 #### 接口说明 验证码验证,返回verification_token ## Request BodyResponse HeadersSchema --- ## 验证码 ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## 获取 AccessToken # 获取 AccessToken ## 什么是 AccessToken AccessToken 是一种安全令牌,用于在无状态协议中代表用户的认证信息。在云开发平台中,AccessToken 允许应用访问受保护的资源,例如用户数据和特定服务。 - **安全性**:AccessToken 提供了一种安全的方式来控制对 API 的访问。 - **灵活性**:允许用户在不同的应用和服务之间共享和传输认证信息。 目前云开发平台有三种 access_token 获取方式: :::warning Access token 数据用户身份的关键凭证,请妥善保管,避免在浏览器等客户端中直接暴露(publishable key 因其匿名身份视具体情况而定)。 ::: 1. 用户登录获取,例如 [用户名密码登录 API](/http-api/auth/auth-sign-in)/[登录 js-sdk](/api-reference/webv3/authentication#authgetaccesstoken) 来进行账号密码登录,该方式获取的 access_token 属于 C 端身份,权限根据所登录用户权限而定。 2. API Key,可以通过[云开发平台](https://tcb.cloud.tencent.com/dev#/env/apikey)获取,有效期可为长期,该方式获取的 access_token 属于管理员端身份,拥有所有资源的操作权限。 3. Publishable Key,[云开发平台](https://tcb.cloud.tencent.com/dev#/env/apikey)获取,有效期可为长期,该方式获取的 access_token 属于匿名身份,权限为匿名用户权限。 ## 使用 AccessToken 在进行 API 调用时,将 AccessToken 作为请求头的一部分发送。 示例: ``` Authorization: Bearer ``` 将 `AccessToken` 替换为实际的 AccessToken,注意: Bearer 不能省略。 ## AccessToken 的有效期和刷新 ### 有效期 AccessToken 通常有一个有限的有效期。在有效期结束后,AccessToken 将不再有效。 ### 刷新 AccessToken 在 AccessToken 过期前,可以使用 RefreshToken(如果可用)来获取新的 AccessToken,而无需用户重新认证。 ## 安全性考虑 ### 存储 确保 AccessToken 被安全地存储,避免在客户端暴露给最终用户。 ### 传输 使用 HTTPS 等安全协议传输 AccessToken,防止中间人攻击。 ### 监控 监控 AccessToken 的使用情况,以便在发现异常时及时采取措施。 ## 错误处理 ### 无效 AccessToken 如果使用无效的 AccessToken,API 将返回 401 Unauthorized 错误。 ### 过期 AccessToken 如果 AccessToken 过期,API 可能会返回 401 Unauthorized 错误,并提示需要刷新。 正确获取和管理 AccessToken 是确保应用安全和用户数据保护的关键。遵循最佳实践,确保 AccessToken 的安全性和有效性。 --- ## 获取 `ApiKey` # 获取 `ApiKey` ## 什么是 `ApiKey` `ApiKey` 与 `AccessToken` 类似,是一种安全 `令牌(Token)`,用于进行用户身份认证。 `ApiKey` 与 `AccessToken` 差异: 1. `ApiKey` 属于 `B端身份` 即开发者身份,具备管理员级别的权限,而通过登录获取的 `AccessToken` 属于 `C端身份`,具备普通用户级别的权限 2. `ApiKey` 通常在服务端使用,而 `AccessToken` 通常用于在客户端使用 3. `ApiKey` 通常是长期有效的,而 `AccessToken` 通常是短期有效的,需要配合使用 `RefreshToken` 定期刷新 ## 如何获取 ApiKey? 1. 进入 [云开发平台](https://tcb.cloud.tencent.com/dev),选择对应环境 2. 进入 `环境配置` -> `ApiKey 管理页` -> `创建 ApiKey`,即可获取 `ApiKey` ## 如何使用 ApiKey? 与 `AccessToken` 类似,在进行 `API` 调用时,将 `ApiKey` 作为请求头的一部分发送。 ```http Authorization: Bearer ``` 如果使用 `openai` SDK 调用大模型接口,可以在初始化 `OpenAI` 实例时传入 `ApiKey`。 ```ts import OpenAI from "openai"; const client = new OpenAI({ apiKey: `your-apui-key`, }); ``` --- ## 接入指南 # 接入指南 ## 前提条件 在开始使用云开发 HTTP API 之前,请确保您满足以下条件: - 拥有云开发平台的账户。 - 对 HTTP 协议和 RESTful API 设计原则有基本了解。 - 熟悉您选择的编程语言和开发环境。 ## 注册和创建环境 ### 注册云开发并开通环境 访问[云开发](https://tcb.cloud.tencent.com/dev)并开通一个环境,如果已有账户则直接登录。 ## 环境配置 ### 配置安全域名 如果是 web 应用,需要先进行[安全域名配置](/faq/allowed_domain) 来支持 CORS 跨域 ## 认证和授权 ### 了解认证机制 熟悉云开发平台支持的[用户认证](/authentication-v2/auth/introduce)机制,选择适合您应用场景的认证方式。 认证方式对比: 1. **[AccessToken](./access-token)** - **适用身份**:用户身份 - **适用环境**:客户端/服务端 - **描述**:常用于客户端应用程序(如移动应用、Web 前端)访问后端服务,支持对用户身份进行精细的访问控制。 2. **[腾讯云签名 V3](./tc3-auth)** - **适用身份**:开发者身份 - **适用环境**:服务端 - **描述**:适用于服务器之间的通信,特别是需要高安全性的管理操作,如云资源的创建、更新和删除。 #### 注意事项 - AccessToken 通常具有较短的有效期,需要定期刷新 ### 实现用户认证 根据选定的认证方式,在您的应用中集成用户认证流程。 具体可参考 [用户和认证相关接口](../auth/auth-sign-in) ### 获取操作权限 确保您的应用在认证后能够获取必要的操作权限,如数据库访问、文件存储、云函数调用等。 使用 accessToken 访问接口时,可以通过[策略管理](https://tcb.cloud.tencent.com/cloud-admin#/settings/strategy)来控制用户及角色访问每个接口的权限。 ## 快速开始 ### 选择 API 接口 根据您的需求,选择适当的 API 接口进行操作。 ### 阅读接口文档 详细阅读所选接口的使用说明,包括请求方法、请求参数、请求头和请求体。 ### 获取 AccessToken 在云开发平台中,调用大部分接口时必须要提供 AccessToken,请参考 [获取 AccessToken](./access-token) ### 发送第一个请求 使用[云开发接口在线调试](/http-api/basic/online-api-call)或者直接通过 HTTP 客户端发送您的第一个 API 请求,并检查响应。 ## 错误处理 ### 理解错误响应 了解 API 可能返回的错误响应格式,包括状态码和错误信息。 ### 实现错误处理逻辑 在您的应用中实现错误处理逻辑,确保能够妥善处理 API 调用中可能出现的问题。 ## 调试和测试 ### 使用日志 利用日志记录 API 调用和响应,帮助调试和监控应用状态。 ### 接口在线调试 使用云开发平台提供的[在线调试工具](/http-api/basic/online-api-call)测试 API 调用,确保功能正确。 --- ## 接口在线调试 # 接口在线调试 ## 接口调试工具介绍 云开发平台提供了一个在线调试工具,允许开发者在不编写任何代码的情况下测试 API 接口。这个工具对于快速验证 API 请求和查看响应非常有用。 ## 访问调试界面 ### 打开 HTTP 接口文档页面 我们在 HTTP 接口文档页面直接集成了调试工具,可以直接进行调用,例如 [用户认证/Sign In By Email/Phone/Username](/http-api/auth/auth-sign-in) 接口可以在线进行测试。 ### 定位调试工具 在管理界面中,找到 API 调试工具的入口,通常位于文档的右侧 ## 发送请求 ![](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/a0166ac1-0025-421f-963e-666245b1333e.png) - 1. 点击 API 地址上的 Edit - 2. 输入 env_id: 填写自己的云开发环境的 id - 3. 在 body 中输入参数 - 4. 点击 SEND API REQUEST 发送请求 - 5. 查看 RESPONSE 接口响应 ### 选择 API 接口 在调试工具中,选择您想要测试的 API 接口。 ### 配置请求参数 根据所选 API 的要求,填写必要的请求参数。这可能包括路径参数、查询参数、请求头和请求体。 - 输入 env_id: 填写自己的云开发环境的 id - 在 body 中输入参数 ### 发送请求 点击“SEND API REQUEST”按钮,您的请求将被发送到服务器,并且您可以立即看到响应。 ## 查看和分析响应 RESPONSE 面板中会返回接口的响应 ### 查看响应状态码 检查响应的 HTTP 状态码,以确定请求是否成功。 ### 分析响应体 查看响应体中的数据,分析返回的信息是否符合预期。 ### 调试信息 如果请求失败,查看错误信息和文档,以帮助诊断问题。 ## 注意事项 在 Web 调试之前,需要把 `docs.cloudbase.net` 加入 WEB 安全域名,请参考 [配置安全域名](./guide#配置安全域名) ![](https://qcloudimg.tencent-cloud.cn/raw/89c542d800429d0e482cb6c660e7ec0b.png) --- ## 概述 # 概述 ## 引言 云开发 HTTP API 是一套为开发者设计的接口,旨在通过 HTTP 协议提供从客户端及服务端对云开发平台功能的访问。这些 API 允许开发者以编程方式实现用户认证、云函数、数据库、数据模型、AI 等功能,从而加速应用开发流程。 ## 核心特性 云开发 HTTP API 提供以下核心特性: - **用户认证**:支持多种认证方式,包括匿名登录、账号密码登录、OAuth 2.0 等,确保从各端调用的安全性。 - **基础能力**:统一支持云开发的后端能力 - **扩展性**:API 设计考虑了未来功能的扩展,确保长期兼容性。 ## 架构概览 云开发平台的架构设计为多层结构,包括: - **前端应用层**:开发者的应用前端,通过 API 与云开发平台交互。 - **API 层**:处理 API 请求的入口,提供请求路由、认证等功能。 - **后端服务层**:实现具体业务逻辑,如云函数、数据库、数据模型、AI 等业务模块 - **数据存储层**:云存储、数据库,存储用户数据,保证数据的持久化和安全性。 ## 使用场景 云开发 HTTP API 适用于以下场景: - **移动应用开发**:为移动应用提供后端服务 - **Web 应用开发**:构建动态网站和 Web 应用 - **游戏开发**:使用 unity 等游戏构建平台 - **IoT 设备**:连接物联网设备,实现数据收集和远程控制 - **开发者自有服务**:在开发者自有服务器端调用云开发, 实现特定功能 ## 文档结构 本文档集包括以下部分: - **概述**:提供对云开发 HTTP API 的基本介绍。 - **接入指南**:指导开发者如何开始使用 API。 - **获取 AccessToken**:详细说明如何获取和使用访问令牌。 - **接口在线调试**:介绍如何使用在线工具进行 API 调试。 ## 支持和反馈 我们鼓励开发者通过官方渠道提供反馈和建议。云开发平台拥有活跃的开发者社区,为开发者提供支持和帮助。 --- ## 使用腾讯云签名 V3 认证 # 使用腾讯云签名 V3 认证 云开发 HTTP API 支持通过腾讯云签名方法 V3 进行认证并调用接口。腾讯云签名方法 V3 参考文档:[https://cloud.tencent.com/document/product/876/34813](https://cloud.tencent.com/document/product/876/34813)。 :::caution 云开发 HTTP API 与腾讯云签名方法 V3 的不同之处 在腾讯云签名方法 V3 中,规范请求串 `CanonicalRequest` 中的 `CanonicalURI` 字段固定为 `/`,但在计算云开发 HTTP API 时,需要根据实际情况填写 `CanonicalURI` 为请求路径。例如,当请求 AI 大模型接口 `/v1/ai/hunyuan/` 时,签名的 `CanonicalURI` 为 `/v1/ai/hunyuan/`。 ::: 根据签名方法 V3 可得到类似如下格式的签名: ```text TC3-HMAC-SHA256 Credential=*************/2018-06-08/tcb/tc3_request, SignedHeaders=content-type;host;x-tc-action, Signature=************* ``` 在得到上述签名之后,将签名中使用的 `Timestamp` (即公共参数 `X-Tc-Timestamp` 值)拼接在签名串之后,得到: ```text TC3-HMAC-SHA256 Credential=*************/2024-08-08/tcb/tc3_request, SignedHeaders=content-type;host;x-tc-action, Signature=*************, Timestamp=******* ``` 如在签名当中有使用临时访问凭证,需要将临时访问凭证的 `Token` (即 `X-Tc-Token`)作为参数拼接在签名串之后,临时访问凭证获取方式见:[https://cloud.tencent.com/document/product/1312/48197](https://cloud.tencent.com/document/product/1312/48197)。拼接后得到: ```text TC3-HMAC-SHA256 Credential=*************/2024-08-08/tcb/tc3_request, SignedHeaders=content-type;host;x-tc-action, Signature=*************, Timestamp=*******, Token=************* ``` 将上述过程后得到签名串作为请求头 `Authorization` 的值,在调用 HTTP API 时一并传递,例如: ```shell curl 'https://${your-env}.api.tcloudbasegateway.com/${path}' \ -H 'Authorization: TC3-HMAC-SHA256 Credential=*************/2024-08-08/tcb/tc3_request, SignedHeaders=content-type;host;x-tc-action, Signature=*************, Timestamp=*******, Token=*************' ``` :::info 腾讯云签名 V3 的支持范围 当前,下列功能模块不支持直接使用腾讯云签名 V3 直接调用: - 数据模型 - 用户认证 对于不支持使用腾讯云签名 V3 直接调用的功能,可通过换取 OAuth 2.0 Access Token 调用。参考文档:[https://docs.cloudbase.net/http-api/basic/access-token](./access-token)。 ::: --- ## 调用云托管服务 import ApiTabs from "@theme/ApiTabs"; import DiscriminatorTabs from "@theme/DiscriminatorTabs"; import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes"; import MimeTabs from "@theme/MimeTabs"; import ParamsItem from "@theme/ParamsItem"; import ResponseSamples from "@theme/ResponseSamples"; import SchemaItem from "@theme/SchemaItem"; import SchemaTabs from "@theme/SchemaTabs"; import Heading from "@theme/Heading"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; 调用云托管服务 调用指定云托管服务。 通过开放 API 访问云托管时,针对可能存在的合规封禁风险,开放 API 会对响应头进行如下更改: 1. 对于所有的 `GET` 请求返回的响应,响应头添加 `Content-Disposition: attachment`; 2. 对于非文本类型(文本类型包括响应头`Content-Type`中值是`application/json`、`application/x-www-form-urlencoded`、`text/plain`类型的返回内容)的响应,响应头添加 `Content-Disposition: attachment`; > **_注意_**:`SSE(Server-Sent Event)` 和 `WebSocket` 请求不受到上述限制。 ## Request Path Parameters 调用成功时返回 Response HeadersX-Request-Id string 请求 ID SchemaechoSchema string text 云托管服务调用出错时返回 Response HeadersX-Request-Id string 请求 ID Schema云托管服务拒绝访问 云托管服务调用出错时返回 Response HeadersX-Request-Id string 请求 ID Schema未找到云托管服务 通用报错信息,详见 https://docs.cloudbase.net/error-code/service Response HeadersX-Request-Id string 请求 ID Schema请求地址异常 --- ## 调用云托管服务 import ApiTabs from "@theme/ApiTabs"; import DiscriminatorTabs from "@theme/DiscriminatorTabs"; import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes"; import MimeTabs from "@theme/MimeTabs"; import ParamsItem from "@theme/ParamsItem"; import ResponseSamples from "@theme/ResponseSamples"; import SchemaItem from "@theme/SchemaItem"; import SchemaTabs from "@theme/SchemaTabs"; import Heading from "@theme/Heading"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; 调用云托管服务 调用指定云托管服务。 通过开放 API 访问云托管时,针对可能存在的合规封禁风险,开放 API 会对响应头进行如下更改: 1. 对于所有的 `GET` 请求返回的响应,响应头添加 `Content-Disposition: attachment`; 2. 对于非文本类型(文本类型包括响应头`Content-Type`中值是`application/json`、`application/x-www-form-urlencoded`、`text/plain`类型的返回内容)的响应,响应头添加 `Content-Disposition: attachment`; > **_注意_**:`SSE(Server-Sent Event)` 和 `WebSocket` 请求不受到上述限制。 ## Request Path ParametersBody 调用云托管服务的请求参数 调用成功时返回 Response HeadersX-Request-Id string 请求 ID SchemaechoSchema string text 云托管服务调用出错时返回 Response HeadersX-Request-Id string 请求 ID Schema云托管服务拒绝访问 云托管服务调用出错时返回 Response HeadersX-Request-Id string 请求 ID Schema未找到云托管服务 通用报错信息,详见 https://docs.cloudbase.net/error-code/service Response HeadersX-Request-Id string 请求 ID Schema请求地址异常 --- ## 云托管 import ApiLogo from "@theme/ApiLogo"; import SchemaTabs from "@theme/SchemaTabs"; import TabItem from "@theme/TabItem"; import Export from "@theme/ApiExplorer/Export"; Version: 1.0.0 云托管 # 功能介绍 该系列开放 API 提供了对接云托管(Cloudbase Run)服务的能力,可通过开放 API 对环境下的云托管服务进行调用,支持 `SSE(Server-Sent Event)` 和 `WebSocket` 请求。 # 接入指引 调用以下接口需要传递 AccessToken,格式如`Authorization: Bearer `。Token 获取方式参考:https://docs.cloudbase.net/http-api/basic/access-token # HTTP 状态码 根据返回结果的不同,可能会出现 `2xx`, `4xx`, `5xx` 状态码。 # 错误码 以下列出了该系列 API 特定的错误码,完整列表参考:https://docs.cloudbase.net/error-code/service 错误码 含义 SERVICE_NOT_FOUND 未找到指定服务 SERVICE_TIMEOUT 调用云托管服务超时 SERVICE_FORBIDDEN 云托管服务拒绝访问,可能是由于权限配置或服务状态异常 SERVICE_NOT_READY 云托管服务处于未就绪状态 SERVICE_VERSION_NOT_FOUND 找不到匹配的云托管服务版本 SERVICE_ENDPOINT_NOT_FOUND 找不到云托管服务可用的地址 SERVICE_LB_STATUS_ABNORMAL 云托管负载均衡状态异常,可尝试新建版本 SERVICE_RESOURCE_NOT_FOUND 未找到服务对应的资源 SERVICE_CHARGE_OVERDUE 欠费停机,请及时充值 Authentication 环境 ID 所对应的 token,使用登录认证(v2)获取 Security Scheme Type:httpHTTP Authorization Scheme:bearer TC3-HMAC-SHA256开头的腾讯云 3.0 版签名,将 Timestamp 和 Token 拼接在签名最后 Security Scheme Type:apiKeyHeader parameter name:AuthorizationContactTCB: URL: https://cloud.tencent.com/product/tcbLicenseApache 2.0 --- ## 调用云函数 import ApiTabs from "@theme/ApiTabs"; import DiscriminatorTabs from "@theme/DiscriminatorTabs"; import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes"; import MimeTabs from "@theme/MimeTabs"; import ParamsItem from "@theme/ParamsItem"; import ResponseSamples from "@theme/ResponseSamples"; import SchemaItem from "@theme/SchemaItem"; import SchemaTabs from "@theme/SchemaTabs"; import Heading from "@theme/Heading"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; 调用云函数 调用指定云函数。 ## Request Path ParametersQuery ParametersHeader ParametersBody 调用函数的请求参数,请求参数需为 JSON 对象 调用成功时返回 Response HeadersX-Request-Id string 请求ID SchemaechoSchema string text 函数调用出错时返回 Response HeadersX-Request-Id string 请求ID Schema函数执行失败 通用报错信息,详见 https://docs.cloudbase.net/error-code/service Response HeadersX-Request-Id string 请求ID Schema请求地址异常 --- ## 云函数 import ApiLogo from "@theme/ApiLogo"; import SchemaTabs from "@theme/SchemaTabs"; import TabItem from "@theme/TabItem"; import Export from "@theme/ApiExplorer/Export"; Version: 1.0.0 云函数 # 功能介绍 该系列开放 API 提供了对接云函数([云开发-云函数](https://docs.cloudbase.net/cloud-function/introduce))的能力,可调用开放 API 对环境下的云函数进行调用。 # 接入指引 调用以下接口需要传递 AccessToken,格式如`Authorization: Bearer `。Token 获取方式参考:https://docs.cloudbase.net/http-api/basic/access-token # HTTP 状态码 根据返回结果的不同,可能会出现 `2xx`, `4xx`, `5xx` 状态码。 # 错误码 以下列出了该系列 API 特定的错误码,完整列表参考:https://docs.cloudbase.net/error-code/service 错误码 含义 FUNCTION_NOT_FOUND 未找到指定函数 FUNCTION_QUALIFIER_NOT_FOUND 未找到函数的指定版本 FUNCTION_INVOCATION_FAILED 函数执行失败,需检查函数代码 FUNCTION_PARAM_INVALID 调用函数的参数异常 FUNCTION_EXCEED_RESOURCE_LIMIT 请求资源超过预置并发 FUNCTION_STATUS_ABNORMAL 函数状态异常 FUNCTION_TIME_LIMIT_EXCEEDED 函数执行超时 FUNCTION_MEMORY_LIMIT_EXCEEDED 函数执行内存超出限制 Authentication 环境 ID 所对应的 token,使用登录认证(v2)获取 Security Scheme Type:httpHTTP Authorization Scheme:bearer TC3-HMAC-SHA256开头的腾讯云 3.0 版签名,将 Timestamp 和 Token 拼接在签名最后 Security Scheme Type:apiKeyHeader parameter name:AuthorizationContactTCB: URL: https://cloud.tencent.com/product/tcbLicenseApache 2.0 --- ## 云函数调用 ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## 知识库检索文档 import ApiTabs from "@theme/ApiTabs"; import DiscriminatorTabs from "@theme/DiscriminatorTabs"; import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes"; import MimeTabs from "@theme/MimeTabs"; import ParamsItem from "@theme/ParamsItem"; import ResponseSamples from "@theme/ResponseSamples"; import SchemaItem from "@theme/SchemaItem"; import SchemaTabs from "@theme/SchemaTabs"; import Heading from "@theme/Heading"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; 知识库检索文档 支持指定文件名称检索最相似的文本信息。支持文件名搭配文件元数据的标量字段的 Filter 表达式检索最相似的文本信息。支持仅使用文件元数据的标量字段的 Filter 表达式检索最相似的文本信息。 ## Request Bodysearch objectoptions object 成功 SchemaoneOfdata objectdocuments object[]Array [data objectdocumentSet object] --- ## 知识库 OpenAPI import ApiLogo from "@theme/ApiLogo"; import SchemaTabs from "@theme/SchemaTabs"; import TabItem from "@theme/TabItem"; import Export from "@theme/ApiExplorer/Export"; Version: 1.0.0 知识库 OpenAPI ### 功能介绍 这里是知识库相关openapi。 ### 接入指引 调用以下接口需要传递 AccessToken 或者ApiKey,格式如`Authorization: Bearer ` 或者 `Authorization: Bearer `。Token 获取方式参考:https://docs.cloudbase.net/http-api/basic/access-token; ApiKey 获取方式参考:https://docs.cloudbase.net/http-api/basic/api-key ### HTTP 状态码 根据返回结果的不同,可能会出现 `2xx`, `4xx`, `5xx` 状态码。 ### 错误码 以下列出了该系列 API 特定的错误码,完整列表参考:https://docs.cloudbase.net/error-code/service 错误码 含义 INVALID_PARAMETER 参数错误 MISSING_PARAMETER 缺少参数错误 RESOURCE_NOTFOUND 资源不存在 INVALID_PARAMETER_VALUE 参数取值错误 REQUEST_LIMIT_EXCEEDED 请求的次数超过了频率限制 SYS_ERR 内部错误 FAILED_OPERATION 操作失败 Authentication 环境 ID 所对应的 token,使用登录认证(v2)获取 Security Scheme Type:httpHTTP Authorization Scheme:bearer TC3-HMAC-SHA256开头的腾讯云 3.0 版签名,将 Timestamp 和 Token 拼接在签名最后 Security Scheme Type:apiKeyHeader parameter name:Authorization --- ## 知识库方法 ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## 根据条件查询查询数据源聚合列表 import ApiTabs from "@theme/ApiTabs"; import DiscriminatorTabs from "@theme/DiscriminatorTabs"; import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes"; import MimeTabs from "@theme/MimeTabs"; import ParamsItem from "@theme/ParamsItem"; import ResponseSamples from "@theme/ResponseSamples"; import SchemaItem from "@theme/SchemaItem"; import SchemaTabs from "@theme/SchemaTabs"; import Heading from "@theme/Heading"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; 根据条件查询查询数据源聚合列表 ## Request Query Parameters 成功 SchemaoneOfdata objectRows object[]Array [AppUsageList object[]Array []] --- ## 根据条件查询查询基础数据源信息列表 import ApiTabs from "@theme/ApiTabs"; import DiscriminatorTabs from "@theme/DiscriminatorTabs"; import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes"; import MimeTabs from "@theme/MimeTabs"; import ParamsItem from "@theme/ParamsItem"; import ResponseSamples from "@theme/ResponseSamples"; import SchemaItem from "@theme/SchemaItem"; import SchemaTabs from "@theme/SchemaTabs"; import Heading from "@theme/Heading"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; 根据条件查询查询基础数据源信息列表 ## Request Bodyrequired= 1`"} schema={{"type":"integer","minimum":1,"default":1,"description":"PageNum , default = 1"}}>= 1`"} schema={{"type":"integer","minimum":1,"default":10,"description":"PageSize"}}>QueryFilterList object[] 查询Filter Array [] 成功 SchemaoneOfdata objectDataSourceList object[]Array [] --- ## 根据条件查询查询基础数据源信息 import ApiTabs from "@theme/ApiTabs"; import DiscriminatorTabs from "@theme/DiscriminatorTabs"; import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes"; import MimeTabs from "@theme/MimeTabs"; import ParamsItem from "@theme/ParamsItem"; import ResponseSamples from "@theme/ResponseSamples"; import SchemaItem from "@theme/SchemaItem"; import SchemaTabs from "@theme/SchemaTabs"; import Heading from "@theme/Heading"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; 根据条件查询查询基础数据源信息 ## Request Query Parameters 成功 SchemaoneOfdata object --- ## 创建单条数据 import ApiTabs from "@theme/ApiTabs"; import DiscriminatorTabs from "@theme/DiscriminatorTabs"; import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes"; import MimeTabs from "@theme/MimeTabs"; import ParamsItem from "@theme/ParamsItem"; import ResponseSamples from "@theme/ResponseSamples"; import SchemaItem from "@theme/SchemaItem"; import SchemaTabs from "@theme/SchemaTabs"; import Heading from "@theme/Heading"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; 创建单条数据 ## Request Path ParametersBody 成功 SchemaoneOfdata object --- ## 创建多条数据 import ApiTabs from "@theme/ApiTabs"; import DiscriminatorTabs from "@theme/DiscriminatorTabs"; import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes"; import MimeTabs from "@theme/MimeTabs"; import ParamsItem from "@theme/ParamsItem"; import ResponseSamples from "@theme/ResponseSamples"; import SchemaItem from "@theme/SchemaItem"; import SchemaTabs from "@theme/SchemaTabs"; import Heading from "@theme/Heading"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; 创建多条数据 ## Request Path ParametersBody 成功 SchemaoneOfdata object --- ## 根据条件查询查询数据源聚合详情 import ApiTabs from "@theme/ApiTabs"; import DiscriminatorTabs from "@theme/DiscriminatorTabs"; import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes"; import MimeTabs from "@theme/MimeTabs"; import ParamsItem from "@theme/ParamsItem"; import ResponseSamples from "@theme/ResponseSamples"; import SchemaItem from "@theme/SchemaItem"; import SchemaTabs from "@theme/SchemaTabs"; import Heading from "@theme/Heading"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; 根据条件查询查询数据源聚合详情 ## Request Query Parameters 成功 SchemaoneOfdata objectAppUsageList object[]Array [] --- ## 根据表名称查询查询数据源Schema定义 import ApiTabs from "@theme/ApiTabs"; import DiscriminatorTabs from "@theme/DiscriminatorTabs"; import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes"; import MimeTabs from "@theme/MimeTabs"; import ParamsItem from "@theme/ParamsItem"; import ResponseSamples from "@theme/ResponseSamples"; import SchemaItem from "@theme/SchemaItem"; import SchemaTabs from "@theme/SchemaTabs"; import Heading from "@theme/Heading"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; 根据表名称查询查询数据源Schema定义 ## Request Query Parameters 成功 SchemaoneOfdata objectDataSourceTableInfos object[]Array [] --- ## 根据id删除单条数据 import ApiTabs from "@theme/ApiTabs"; import DiscriminatorTabs from "@theme/DiscriminatorTabs"; import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes"; import MimeTabs from "@theme/MimeTabs"; import ParamsItem from "@theme/ParamsItem"; import ResponseSamples from "@theme/ResponseSamples"; import SchemaItem from "@theme/SchemaItem"; import SchemaTabs from "@theme/SchemaTabs"; import Heading from "@theme/Heading"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; 根据id删除单条数据 ## Request Path Parameters 成功 SchemaoneOfdata object --- ## 删除单条数据 import ApiTabs from "@theme/ApiTabs"; import DiscriminatorTabs from "@theme/DiscriminatorTabs"; import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes"; import MimeTabs from "@theme/MimeTabs"; import ParamsItem from "@theme/ParamsItem"; import ResponseSamples from "@theme/ResponseSamples"; import SchemaItem from "@theme/SchemaItem"; import SchemaTabs from "@theme/SchemaTabs"; import Heading from "@theme/Heading"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; 删除单条数据 ## Request Path ParametersBodyfilter object 成功 SchemaoneOfdata object --- ## 删除多条数据 import ApiTabs from "@theme/ApiTabs"; import DiscriminatorTabs from "@theme/DiscriminatorTabs"; import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes"; import MimeTabs from "@theme/MimeTabs"; import ParamsItem from "@theme/ParamsItem"; import ResponseSamples from "@theme/ResponseSamples"; import SchemaItem from "@theme/SchemaItem"; import SchemaTabs from "@theme/SchemaTabs"; import Heading from "@theme/Heading"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; 删除多条数据 ## Request Path ParametersBodyfilter object 成功 SchemaoneOfdata object --- ## 根据id获取单条数据 import ApiTabs from "@theme/ApiTabs"; import DiscriminatorTabs from "@theme/DiscriminatorTabs"; import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes"; import MimeTabs from "@theme/MimeTabs"; import ParamsItem from "@theme/ParamsItem"; import ResponseSamples from "@theme/ResponseSamples"; import SchemaItem from "@theme/SchemaItem"; import SchemaTabs from "@theme/SchemaTabs"; import Heading from "@theme/Heading"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; 根据id获取单条数据 ## Request Path Parameters 成功 SchemaoneOfdata object --- ## 根据条件获取单条数据 import ApiTabs from "@theme/ApiTabs"; import DiscriminatorTabs from "@theme/DiscriminatorTabs"; import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes"; import MimeTabs from "@theme/MimeTabs"; import ParamsItem from "@theme/ParamsItem"; import ResponseSamples from "@theme/ResponseSamples"; import SchemaItem from "@theme/SchemaItem"; import SchemaTabs from "@theme/SchemaTabs"; import Heading from "@theme/Heading"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; 根据条件获取单条数据 ## Request Path ParametersBodyfilter object 成功 SchemaoneOfdata object --- ## 简单查询多条数据 import ApiTabs from "@theme/ApiTabs"; import DiscriminatorTabs from "@theme/DiscriminatorTabs"; import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes"; import MimeTabs from "@theme/MimeTabs"; import ParamsItem from "@theme/ParamsItem"; import ResponseSamples from "@theme/ResponseSamples"; import SchemaItem from "@theme/SchemaItem"; import SchemaTabs from "@theme/SchemaTabs"; import Heading from "@theme/Heading"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; 简单查询多条数据 ## Request Path ParametersQuery Parameters 成功 SchemaoneOfdata object --- ## 查询多条数据 import ApiTabs from "@theme/ApiTabs"; import DiscriminatorTabs from "@theme/DiscriminatorTabs"; import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes"; import MimeTabs from "@theme/MimeTabs"; import ParamsItem from "@theme/ParamsItem"; import ResponseSamples from "@theme/ResponseSamples"; import SchemaItem from "@theme/SchemaItem"; import SchemaTabs from "@theme/SchemaTabs"; import Heading from "@theme/Heading"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; 查询多条数据 ## Request Path ParametersBodyfilter object 成功 SchemaoneOfdata object --- ## 执行mysql命令 import ApiTabs from "@theme/ApiTabs"; import DiscriminatorTabs from "@theme/DiscriminatorTabs"; import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes"; import MimeTabs from "@theme/MimeTabs"; import ParamsItem from "@theme/ParamsItem"; import ResponseSamples from "@theme/ResponseSamples"; import SchemaItem from "@theme/SchemaItem"; import SchemaTabs from "@theme/SchemaTabs"; import Heading from "@theme/Heading"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; 执行mysql命令 执行mysql命令,身份只支持:[管理端Token](/lowcode/manage/introduce),[API Key](/http-api/basic/apikey) ## Request Bodyrequiredparameter object[] Query参数,非必传,当sqlTemplate携带参数时,需要传该参数 Array []config object RunMysqlCommand 配置,非必传,例如:{"preparedStatements":true} 成功 SchemaoneOfdata object --- ## 查询环境下所有数据源Schema import ApiTabs from "@theme/ApiTabs"; import DiscriminatorTabs from "@theme/DiscriminatorTabs"; import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes"; import MimeTabs from "@theme/MimeTabs"; import ParamsItem from "@theme/ParamsItem"; import ResponseSamples from "@theme/ResponseSamples"; import SchemaItem from "@theme/SchemaItem"; import SchemaTabs from "@theme/SchemaTabs"; import Heading from "@theme/Heading"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; 查询环境下所有数据源Schema ## Request Query Parameters 成功 SchemaoneOfdata objectDataSourceRelationInfoList object[]Array [] --- ## 根据数据源名称查询表名称 import ApiTabs from "@theme/ApiTabs"; import DiscriminatorTabs from "@theme/DiscriminatorTabs"; import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes"; import MimeTabs from "@theme/MimeTabs"; import ParamsItem from "@theme/ParamsItem"; import ResponseSamples from "@theme/ResponseSamples"; import SchemaItem from "@theme/SchemaItem"; import SchemaTabs from "@theme/SchemaTabs"; import Heading from "@theme/Heading"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; 根据数据源名称查询表名称 ## Request Query Parameters 成功 SchemaoneOf --- ## 更新单条数据 import ApiTabs from "@theme/ApiTabs"; import DiscriminatorTabs from "@theme/DiscriminatorTabs"; import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes"; import MimeTabs from "@theme/MimeTabs"; import ParamsItem from "@theme/ParamsItem"; import ResponseSamples from "@theme/ResponseSamples"; import SchemaItem from "@theme/SchemaItem"; import SchemaTabs from "@theme/SchemaTabs"; import Heading from "@theme/Heading"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; 更新单条数据 ## Request Path ParametersBodyfilter object 成功 SchemaoneOfdata object --- ## 更新多条数据 import ApiTabs from "@theme/ApiTabs"; import DiscriminatorTabs from "@theme/DiscriminatorTabs"; import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes"; import MimeTabs from "@theme/MimeTabs"; import ParamsItem from "@theme/ParamsItem"; import ResponseSamples from "@theme/ResponseSamples"; import SchemaItem from "@theme/SchemaItem"; import SchemaTabs from "@theme/SchemaTabs"; import Heading from "@theme/Heading"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; 更新多条数据 ## Request Path ParametersBodyfilter object 成功 SchemaoneOfdata object --- ## 创建或更新单条数据 import ApiTabs from "@theme/ApiTabs"; import DiscriminatorTabs from "@theme/DiscriminatorTabs"; import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes"; import MimeTabs from "@theme/MimeTabs"; import ParamsItem from "@theme/ParamsItem"; import ResponseSamples from "@theme/ResponseSamples"; import SchemaItem from "@theme/SchemaItem"; import SchemaTabs from "@theme/SchemaTabs"; import Heading from "@theme/Heading"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; 创建或更新单条数据 ## Request Path ParametersBodyfilter object 成功 SchemaoneOfdata object --- ## 数据操作的方法 ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## 数据模型 OpenAPI import ApiLogo from "@theme/ApiLogo"; import SchemaTabs from "@theme/SchemaTabs"; import TabItem from "@theme/TabItem"; import Export from "@theme/ApiExplorer/Export"; Version: 1.0.0 数据模型 OpenAPI ### 功能介绍 这里给出了数据模型所有操作的API,以及每个API的参数参考。 ### 接入指引 调用以下接口需要传递 AccessToken,格式如`Authorization: Bearer `。Token 获取方式参考:https://docs.cloudbase.net/http-api/basic/access-token ### HTTP 状态码 只会出现`2xx`状态码。数据模型API的业务错误会在`2xx`状态码中通过响应体指示,应当视情况处理。 ### 错误码 以下列出了该系列 API 特定的错误码,完整列表参考:https://docs.cloudbase.net/error-code/service 错误码 含义 AUTH_FAILURE 没有权限 FAILED_OPERATION 操作失败 OPERATION_TIMEOUT 操作超时 INVALID_PARAMETER 参数错误 INVALID_PARAMETER_VALUE 参数取值错误 MISSING_PARAMETER 缺少参数错误 LIMIT_EXCEEDED 超过配额限制 RESOURCE_NOT_FOUND 资源不存在 RESOURCE_UNAVAILABLE 资源不可用 RESOURCE_INSUFFICIENT 资源不足 RESOURCE_IN_USE 资源被占用 RESOURCE_SOLD_OUT 资源售罄 OPERATION_DENIED 操作被拒绝 UNAUTHORIZED_OPERATION 未授权操作 UNKNOWN_PARAMETER 未知参数错误 UNSUPPORTED_OPERATION 操作不支持 DATA_SOURCE_OP_AUTH_FAILURE 数据源模型作鉴权失败,请在用户权限模块设置对应角色合理权限 FLEXDB_INTERNAL_ERROR 请求数据库错误,请检查参数 FLEXDB_REQUEST_TIMEOUT 请求Mongo数据库超时。请优化您的查询,或者添加索引 AUTH_FAILURE_TOKEN_FAILURE token错误 NO_SUCH_VERSION 接口版本不存在 REQUEST_LIMIT_EXCEEDED 请求的次数超过了频率限制 FLEXDB_RESOURCE_OVERDUE 数据库资源到期或者数据库读写次数超过套餐包限制。请升级套餐读写次数,或者等待第二天重置读写次数。如有问题,请在数据库平台核对资源 FLEXDB_READ_LIMIT 数据库读取次数超过上限,请升级套餐包 FLEXDB_WRITE_LIMIT 数据库写入次数超过上限,请升级套餐包 FAILED_OPERATION_CUSTOMIZED_METHODS_ERROR 云函数错误,用户自定义方法错误 DATASOURCE_NOT_EXIST 数据源不存在,请在控制台数据源检查对应数据源是否存在 TABLE_NOT_EXIST 表不存在 FAILED_AGGREGATE 聚合查询失败 Authentication 环境 ID 所对应的 token,使用登录认证(v2)获取 Security Scheme Type:httpHTTP Authorization Scheme:bearer TC3-HMAC-SHA256开头的腾讯云 3.0 版签名,将 Timestamp 和 Token 拼接在签名最后 Security Scheme Type:apiKeyHeader parameter name:Authorization --- ## 数据模型的方法 ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## 删除对象 import ApiTabs from "@theme/ApiTabs"; import DiscriminatorTabs from "@theme/DiscriminatorTabs"; import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes"; import MimeTabs from "@theme/MimeTabs"; import ParamsItem from "@theme/ParamsItem"; import ResponseSamples from "@theme/ResponseSamples"; import SchemaItem from "@theme/SchemaItem"; import SchemaTabs from "@theme/SchemaTabs"; import Heading from "@theme/Heading"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; 删除对象 批量删除对象。 ## Request Body arrayrequired 下载对象请求参数,数组格式 Array [] 调用成功时返回 Response HeadersX-Request-Id string 请求ID SchemaArray [oneOf] 通用报错信息,详见 https://docs.cloudbase.net/error-code/service Response HeadersX-Request-Id string 请求ID Schema请求地址异常 --- ## 获取对象下载信息 import ApiTabs from "@theme/ApiTabs"; import DiscriminatorTabs from "@theme/DiscriminatorTabs"; import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes"; import MimeTabs from "@theme/MimeTabs"; import ParamsItem from "@theme/ParamsItem"; import ResponseSamples from "@theme/ResponseSamples"; import SchemaItem from "@theme/SchemaItem"; import SchemaTabs from "@theme/SchemaTabs"; import Heading from "@theme/Heading"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; 获取对象下载信息 批量获取对象下载 URL。 ## Request Body arrayrequired 下载对象请求参数,数组格式 Array [] 调用成功时返回 Response HeadersX-Request-Id string 请求ID SchemaArray [oneOf] 通用报错信息,详见 https://docs.cloudbase.net/error-code/service Response HeadersX-Request-Id string 请求ID Schema请求地址异常 --- ## 获取对象上传信息 import ApiTabs from "@theme/ApiTabs"; import DiscriminatorTabs from "@theme/DiscriminatorTabs"; import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes"; import MimeTabs from "@theme/MimeTabs"; import ParamsItem from "@theme/ParamsItem"; import ResponseSamples from "@theme/ResponseSamples"; import SchemaItem from "@theme/SchemaItem"; import SchemaTabs from "@theme/SchemaTabs"; import Heading from "@theme/Heading"; import OperationTabs from "@theme/OperationTabs"; import TabItem from "@theme/TabItem"; 获取对象上传信息 批量获取上传对象所需信息。 ## Request Body arrayrequired 上传对象请求参数,数组格式 Array [signedHeader objectproperty name* string[]Array [ string ]] 调用成功时返回 Response HeadersX-Request-Id string 请求ID SchemaArray [oneOf] 通用报错信息,详见 https://docs.cloudbase.net/error-code/service Response HeadersX-Request-Id string 请求ID Schema请求地址异常 --- ## 云存储 import ApiLogo from "@theme/ApiLogo"; import SchemaTabs from "@theme/SchemaTabs"; import TabItem from "@theme/TabItem"; import Export from "@theme/ApiExplorer/Export"; Version: 1.0.0 云存储 # 功能介绍 该系列开放 API 提供了对接云存储(COS 服务)的能力,可调用开放 API 获取对象上传信息、下载链接等操作。该系列开放 API 均支持批量操作。 # 接入指引 调用以下接口需要传递 AccessToken,格式如`Authorization: Bearer `。Token 获取方式参考:https://docs.cloudbase.net/http-api/basic/access-token # HTTP 状态码 根据返回结果的不同,可能会出现 `2xx`, `4xx`, `5xx` 状态码。 # 错误码 以下列出了该系列 API 特定的错误码,完整列表参考:https://docs.cloudbase.net/error-code/service 错误码 含义 STORAGE_EXCEED_AUTHORITY 无权限对此对象执行对应操作 COS_ACTION_FAILED 请求 COS 执行操作失败 OBJECT_NOT_EXIST 请求的对象不存在 Authentication 环境 ID 所对应的 token,使用登录认证(v2)获取 Security Scheme Type:httpHTTP Authorization Scheme:bearer TC3-HMAC-SHA256开头的腾讯云 3.0 版签名,将 Timestamp 和 Token 拼接在签名最后 Security Scheme Type:apiKeyHeader parameter name:AuthorizationContactTCB: URL: https://cloud.tencent.com/product/tcbLicenseApache 2.0 --- ## 云存储对象操作 ```mdx-code-block import DocCardList from '@theme/DocCardList'; import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` --- ## _select 云开发数据模型提供了强大的查询功能,支持复杂的查询条件、字段选择、排序、分页和关联查询。本文将详细介绍数据模型查询操作的各种参数和使用方法。 ## 查询参数概览 数据模型的查询操作主要包含以下参数: | 参数 | 类型 | 说明 | 必填 | |------|------|------|------| | `select` | `SelectParams` | 指定返回的字段 | 否 | | `filter` | `FilterParams` | 查询过滤条件 | 否 | | `orderBy` | `OrderByParams[]` | 排序条件 | 否 | | `pageSize` | `number` | 分页大小, 最大200 | 否 | | `pageNumber` | `number` | 页码 | 否 | | `getCount` | `boolean` | 是否返回总数 | 否 | ## 字段选择 `select` `select` 参数用于指定查询结果中应包含的字段,支持主模型字段和关联模型字段的精确控制。 > ✅ 建议仅选择需要的字段和关系来减少响应数据的大小并提高查询速度。 ### 返回主模型所有字段 使用 `$master: true` 可以返回主模型的所有字段: ```javascript const { data } = await models.post.get({ select: { $master: true, // 查询主模型所有的字段 }, filter: { where: { _id: { $eq: _id, // 推荐传入_id数据标识进行操作 }, }, }, }); console.log(data); // { // "owner": "Anonymous(95fblM7nvPi01yQmYxBvBg)", // "createdAt": 1717488585078, // "createBy": "Anonymous(95fblM7nvPi01yQmYxBvBg)", // "updateBy": "Anonymous(95fblM7nvPi01yQmYxBvBg)", // "_openid": "95fblM7nvPi01yQmYxBvBg", // "_id": "e2764d2d665ecbc9024b058f1d6b33a4", // "title": "你好,世界👋", // "body": "文章内容...", // "slug": "hello-world", // "updatedAt": 1717490751944 // } ``` ### 返回指定字段 通过指定字段名为 `true` 来选择特定字段: ```javascript const { data } = await models.post.list({ select: { _id: true, title: true, updatedAt: true, }, filter: { where: {}, }, getCount: true, }); console.log(data); // { // "records": [ // { // "_id": "e2764d2d665ecbc9024b058f1d6b33a4", // "title": "你好,世界👋", // "updatedAt": 1717492882289 // } // // ... 更多记录 // ], // "total": 51 // } ``` ### 返回关联模型字段 可以同时查询关联模型的字段: ```javascript const { data } = await models.post.list({ select: { _id: true, title: true, updatedAt: true, // 关联查询评论数据 comments: { _id: true, createdAt: true, comment: true, }, // 也可以直接传 true 返回评论中所有的字段 }, filter: { where: {}, }, getCount: true, }); console.log(data); // { // "records": [ // { // "_id": "9FSAHWM9VV", // "title": "Bonjour le Monde👋", // "updatedAt": 1718096503886, // "comments": [ // { // "_id": "9FSAJF3GLG", // "createdAt": 1718096509916, // "comment": "这是一条评论" // } // ] // } // // ... 更多记录 // ], // "total": 2 // } ``` ## 查询过滤 `filter` `filter` 参数用于指定查询条件,支持基础查询和关联查询两种方式。 ### 基础查询 `where` 基础查询用于对主模型字段进行过滤: ```javascript const { data } = await models.post.list({ filter: { where: { // 标题包含"世界" title: { $search: "世界", }, // 正文不为空 body: { $nempty: true, }, }, }, select: { $master: true, }, }); ``` ### 关联查询 `relateWhere` 关联查询用于根据关联模型的条件进行过滤: ```javascript const { data } = await models.post.list({ filter: { // 查询有评论的文章 relateWhere: { comments: { where: { comment: { $nempty: true, // 评论内容不为空 }, }, }, }, where: {}, // 主模型查询条件 }, select: { $master: true, comments: { comment: true, }, }, }); ``` ### 组合查询示例 需要用到与或关系时,可以使用 `where` 参数的 `$and` 和 `$or` 操作符 如果用到了 `$and` 和 `$or` 操作符,需要将它们放在一个数组中: ```javascript const { data } = await models.post.list({ filter: { where: { $and: [{ // 标题包含"技术"或"教程" $or: [{ title: { $search: "技术" } }, { title: { $search: "教程" } } ] }, { // 创建时间在最近30天内 createdAt: { $gte: Date.now() - 30 * 24 * 60 * 60 * 1000 } }, { // 状态为已发布 status: { $eq: "published" } } ] }, }, select: { _id: true, title: true, createdAt: true, status: true, }, }); ``` ### 查询运算符 | 操作符 | 说明 | 示例 | |--------|------|------| | **$eq** | 等于 | `{status: {$eq: "active"}}` | | **$ne** | 不等于 | `{status: {$ne: "deleted"}}` | | **$gt** | 大于 | `{score: {$gt: 80}}` | | **$gte** | 大于等于 | `{age: {$gte: 18}}` | | **$lt** | 小于 | `{price: {$lt: 100}}` | | **$lte** | 小于等于 | `{discount: {$lte: 0.5}}` | | **$in** | 在数组中 | `{category: {$in: ["tech", "news"]}}` | | **$nin** | 不在数组中 | `{status: {$nin: ["deleted", "banned"]}}` | | **$and** | 逻辑与 | `{$and: [{age: {$gte: 18}}, {status: {$eq: "active"}}]}` | | **$or** | 逻辑或 | `{$or: [{priority: {$eq: "high"}}, {urgent: {$eq: true}}]}` | | **$search** | 模糊查询, 大小写敏感 | `{status: {$search: "active"}}` | | **$search_ci** | 模糊查询, 大小写不敏感 | `{status: {$search_ci: "active"}}` | | **$nsearch** | 查找不包含指定字符串值的记录, 大小写敏感 | `{status: {$nsearch: "active"}}` | | **$nsearch_ci** | 查找不包含指定字符串值的记录, 大小写不敏感 | `{status: {$nsearch_ci: "active"}}` | | **$empty** | 数据为 null | `{status: {$empty: true}}` | | **$nempty** | 数据不为 null | `{status: {$nempty: true}}` | ## 排序 `orderBy` `orderBy` 参数用于指定查询结果的排序方式,支持多字段排序(最多3个字段)。 ### 单字段排序 ```javascript const { data } = await models.post.list({ filter: { where: {}, }, orderBy: [{ createdAt: "desc", // 按创建时间倒序 }, ], select: { $master: true, }, }); ``` ### 多字段排序 ```javascript const { data } = await models.post.list({ filter: { where: {}, }, orderBy: [{ featured: "desc", // 首先按推荐状态倒序 }, { createdAt: "desc", // 然后按创建时间倒序 }, { title: "asc", // 最后按标题升序 }, ], select: { $master: true, }, }); ``` 排序方向: * `"asc"`: 升序排列 * `"desc"`: 降序排列 ## 分页参数 ### `pageSize` 和 `pageNumber` 用于实现分页查询: ```javascript const { data } = await models.post.list({ filter: { where: {}, }, pageSize: 10, // 每页10条记录 pageNumber: 2, // 第2页(从1开始) getCount: true, // 获取总数用于计算总页数 select: { $master: true, }, }); console.log(data); // { // "records": [...], // 第2页的10条记录 // "total": 156 // 总记录数 // } // 计算总页数 const totalPages = Math.ceil(data.total / 10); ``` ### `getCount` 控制是否返回满足条件的记录总数: ```javascript const { data } = await models.post.list({ filter: { where: { status: { $eq: "published" } }, }, getCount: true, // 设置为 true 时返回 total 字段 select: { _id: true, title: true, }, }); console.log(data.total); // 满足条件的总记录数 ``` ## 完整查询示例 以下是一个包含所有参数的完整查询示例: ```javascript const { data } = await models.post.list({ // 字段选择 select: { _id: true, title: true, excerpt: true, createdAt: true, updatedAt: true, author: { _id: true, name: true, avatar: true, }, comments: { _id: true, content: true, createdAt: true, }, }, // 查询条件 filter: { where: { $and: [{ status: { $eq: "published" } }, { $or: [{ title: { $search: "技术" } }, { tags: { $in: ["前端", "后端"] } } ] }, { createdAt: { $gte: Date.now() - 7 * 24 * 60 * 60 * 1000 // 最近7天 } } ] }, relateWhere: { comments: { where: { status: { $eq: "approved" } // 只查询已审核的评论 } } } }, // 排序 orderBy: [{ featured: "desc" }, { createdAt: "desc" } ], // 分页 pageSize: 20, pageNumber: 1, getCount: true, }); console.log("查询结果:", data.records); console.log("总记录数:", data.total); console.log("总页数:", Math.ceil(data.total / 20)); ``` ## 关联查询详解 ### 按关联关系过滤 使用 `relateWhere` 可以根据关联模型的条件来过滤主模型: ```javascript // 查询有特定评论的文章 const { data } = await models.post.list({ filter: { relateWhere: { // 文章必须有评论 comments: { where: { $and: [{ content: { $nempty: true } }, // 评论内容不为空 { status: { $eq: "approved" } }, // 评论已审核 { rating: { $gte: 4 } } // 评论评分>=4 ] } }, // 文章必须有标签 tags: { where: { name: { $in: ["技术", "教程", "分享"] } } } }, where: { status: { $eq: "published" } } }, select: { $master: true, comments: { content: true, rating: true, status: true, }, tags: { name: true, } } }); ``` ### 关联查询性能优化 1. **精确选择字段**:只选择需要的关联字段 2. **合理使用关联过滤**:避免过于复杂的关联条件 3. **分页处理**:对于大量关联数据使用分页 ```javascript // 优化示例:只获取必要的关联数据 const { data } = await models.post.list({ filter: { where: { status: { $eq: "published" } } }, select: { _id: true, title: true, excerpt: true, // 只获取作者的基本信息 author: { _id: true, name: true, }, // 只获取最新的3条评论 comments: { _id: true, content: true, createdAt: true, } }, orderBy: [{ createdAt: "desc" }], pageSize: 10, pageNumber: 1, }); ``` ## 最佳实践 ### 1. 字段选择优化 ```javascript // ❌ 不推荐:查询所有字段 const { data } = await models.post.list({ select: { $master: true }, filter: { where: {} } }); // ✅ 推荐:只选择需要的字段 const { data } = await models.post.list({ select: { _id: true, title: true, excerpt: true, createdAt: true, }, filter: { where: {} } }); ``` ### 2. 查询条件优化 ```javascript // ✅ 推荐:使用索引字段进行查询 const { data } = await models.post.list({ filter: { where: { _id: { $eq: "specific-id" }, // 主键查询,性能最佳 status: { $eq: "published" }, // 索引字段 createdAt: { $gte: timestamp } // 时间范围查询 } } }); // ⚠️ 注意:模糊查询性能较差,谨慎使用 const { data } = await models.post.list({ filter: { where: { title: { $search: "关键词" } // 模糊查询,建议配合其他条件 } } }); ``` ### 3. 分页处理 ```javascript // ✅ 推荐:合理的分页大小 const pageSize = 20; // 建议10-50之间 const pageNumber = 1; const { data } = await models.post.list({ filter: { where: {} }, pageSize, pageNumber, getCount: true, // 获取总数用于分页计算 select: { _id: true, title: true, createdAt: true, } }); // 计算分页信息 const totalPages = Math.ceil(data.total / pageSize); const hasNextPage = pageNumber 1; ``` ### 4. 错误处理 ```javascript try { const { data } = await models.post.list({ filter: { where: { status: { $eq: "published" } } }, select: { _id: true, title: true, }, pageSize: 10, pageNumber: 1, getCount: true, }); console.log("查询成功:", data); } catch (error) { console.error("查询失败:", error); // 处理错误情况 } ``` 通过合理使用这些查询参数,可以实现高效、灵活的数据查询操作,满足各种复杂的业务需求。 --- ## 使用 CLI 工具 # 使用 CLI 工具 您可以使用 [CloudBase CLI 工具](/cli-v1/db/management) 来完成对数据模型的管理和配置。 ## 使用 CLI 工具管理数据模型 CloudBase CLI 工具提供了一系列的命令,帮助您高效地管理数据模型。 ### 命令概览 - `list`: 列出云端所有数据模型。 - `pull`: 从云端拉取数据模型到本地。 - `push`: 将本地数据模型推送到云端。 ### 列出云端所有数据模型 ```bash tcb db list # 如果本地没有安装 CloudBase CLI ,可使用以下命令 npx --package=@cloudbase/cli@2.5 tcb db list ``` 此命令将展示您在云端的所有数据模型列表。 ### 从云端拉取数据模型到本地 ```bash tcb db pull # 如果本地没有安装 CloudBase CLI ,可使用以下命令 npx --package=@cloudbase/cli@2.5 tcb db pull ``` 使用此命令,您可以将云端的数据模型同步到本地环境。 ### 将本地数据模型推送到云端 ```bash tcb db push # 如果本地没有安装 CloudBase CLI ,可使用以下命令 npx --package=@cloudbase/cli@2.5 tcb db push ``` 通过此命令,您可以一键创建或者更新云端的数据模型,以反映本地的更改。 ## 更多信息 要获取更多关于 CloudBase CLI 工具的信息,请访问 [CloudBase CLI 命令行工具](/cli-v1/intro)。 --- ## 关联关系详解 # 关联关系详解 ## 什么是关联关系 关联关系是指数据模型之间的连接关系,通过关联字段将不同模型的数据关联起来。例如: * 学生属于某个班级(学生 → 班级) * 文章有多个评论(文章 → 评论) * 用户有一个个人资料(用户 → 个人资料) ## 关联关系类型 ### 一对一(1:1) 一个记录只能关联另一个模型的一个记录。 **示例**:用户 ↔ 个人资料 ```javascript // 用户模型 { name: "张三", profile: { _id: "profile_123" } // 关联个人资料 } // 个人资料模型 { _id: "profile_123", avatar: "avatar.jpg", bio: "个人简介" } ``` ### 一对多(1: N) 一个记录可以关联另一个模型的多个记录。 **示例**:班级 ↔ 学生 ```javascript // 班级模型 { name: "一年级1班", students: [{ _id: "student_1" }, { _id: "student_2" } ] } ``` ### 多对一(N:1) 多个记录关联另一个模型的一个记录。 **示例**:学生 ↔ 班级 ```javascript // 学生模型 { name: "小明", class: { _id: "class_123" } // 多个学生属于同一个班级 } ``` ### 多对多(M: N) 多个记录可以关联另一个模型的多个记录。 **示例**:学生 ↔ 课程 ```javascript // 学生模型 { name: "小明", courses: [{ _id: "course_1" }, // 语文 { _id: "course_2" } // 数学 ] } ``` ## 支持的数据库类型 | 数据库类型 | 支持的关联关系 | |-----------|---------------| | 数据库(文档型) | 一对一、一对多、多对一 | | 数据库(MySQL) | 一对一、一对多、多对一、多对多 | | 自有MySQL数据库 | 一对一、一对多、多对一、多对多 | ## 增删改查 ### 查询 **查询结果包含关联数据** ```javascript // 查询文章及其评论 const { data } = await models.post.get({ filter: { where: { _id: { $eq: "post_123" } } }, select: { _id: true, title: true, content: true, // 包含关联的评论数据 comments: { _id: true, content: true, createdAt: true } } }); ``` **根据关联条件过滤** ```javascript // 查询有评论的文章 const { data } = await models.post.list({ filter: { relateWhere: { comments: { where: { content: { $nempty: true } // 评论内容不为空 } } } }, select: { _id: true, title: true, comments: { content: true } } }); ``` ### 创建 **创建时建立关联** 关联关系字段需要以 `{_id:xxx}` 格式传入,其中 `xxx` 为关联数据的 `_id` ```javascript // 创建学生并关联班级和课程 const { data } = await models.student.create({ data: { name: "小明", age: 8, // 关联班级(多对一) class: { _id: "class_123" }, // 关联多个课程(多对多) courses: [{ _id: "course_1" }, { _id: "course_2" } ] } }); ``` ### 更新 ```javascript // 更新学生的班级 const { data } = await models.student.update({ filter: { where: { _id: { $eq: "student_123" } } }, data: { class: { _id: "new_class_456" } } }); ``` ### 删除 配置关联关系时,可以设置不同的删除行为: * **删除关联模型数据**:删除主记录时,同时删除关联的记录 * **不删除关联模型数据**:只删除主记录,保留关联记录 * **禁止删除存在关联关系的数据**:如果存在关联记录,则禁止删除主记录 ## 最佳实践 1. **合理设计关联关系**:根据业务需求选择合适的关联类型 2. **避免过深的嵌套查询**:影响查询性能 3. **使用精确的字段选择**:只查询需要的关联字段 4. **注意循环引用**:避免模型之间的循环关联 通过关联关系,可以轻松实现复杂的数据查询和操作,让数据模型更贴近真实的业务场景。 --- ## 字段类型详解 # 字段类型详解 数据模型字段是数据源的表结构基础,可以理解为 Excel 表格的表头(列),而数据可以理解为 Excel 表格的行。CloudBase 数据模型支持丰富的字段类型,满足各种业务场景的数据存储需求。 ## 🎯 字段类型概览 CloudBase 数据模型提供了 **20+ 种字段类型**,涵盖基础数据、格式化验证、媒体文件、内容编辑、时间位置、特殊功能等各个方面: ## 📊 字段类型完整列表 | 字段类型 | DB字段类型 | 使用说明 | 示例 | |---------|-----------|----------|------| | **文本/单行** | `string` | 适合标题、姓名等短文本(最长 4000 字节) | `"张三"` | | **文本/多行** | `string` | 适合描述、备注等长文本(最长 4000 字节) | `"这是一段描述文字"` | | **布尔值** | `boolean` | true 或 false | `true` | | **数字** | `number` | 支持整数和浮点数 | `123456.78` | | **数组** | `array` | 根据数组元素类型进行校验 | `["技术", "前端", "Vue"]` | | **对象** | `object` | 嵌套的键值对结构 | `{"name": "张三", "age": 25}` | | **JSON** | `object` | 复杂的数据结构或动态属性 | `{"title": "博客", "tags": ["技术"]}` | | **邮箱** | `string` | 包含 xx\@yy.zz 格式验证 | `"email@qq.com"` | | **电话/固定号码** | `string` | 0开头的2-3位区号或7-8位号码 | `"027-1234567"` | | **电话/手机号码** | `string` | 符合手机号规范的11位字符串 | `"13812341234"` | | **网址** | `string` | 符合网址规范的字符串 | `"https://example.com"` | | **图片** | `string` | 默认从前端组件获得图片的 cloudId | `"cloud://xxx.xxx.xxx.png"` | | **多媒体/视频** | `string` | 支持 ogm、wmv、mpg、webm、ogv、mov、asx、mpeg、mp4、m4v、avi | `"cloud://xxx.xxx.xxx/video.mp4"` | | **多媒体/音频** | `string` | 支持 opus、flac、webm、weba、wav、ogg、m4a、oga、mid、mp3、aiff、wma、au | `"cloud://xxx.xxx.xxx/audio.wav"` | | **富文本** | `string` | 支持格式化、链接、图片(最长 262144 字节) | `"标题内容"` | | **Markdown** | `string` | 支持 Markdown 编辑器和实时预览 | `"# 这是一个Markdown示例"` | | **日期时间** | `number` | 默认从前端组件获取的时间戳(ms) | `1645977600000` | | **枚举** | `string` | 所填值必须为设置的枚举值中的某一个 | `"牛奶"` | | **地理位置** | `object` | 固定格式的对象,包含地址和坐标 | `{"geopoint": {"type": "Point", "coordinates": [40.56, 5.89]}, "address": "深圳市南山区"}` | | **文件** | `string` | 默认从前端组件获得文件的 cloudId | `"cloud://xxx.xxx.xxx.pdf"` | | **自动编号** | `string` | 用户不填则后端自动补齐;用户传参则使用客户定义的值 | `"1001"` | | **地区** | `string` | 省级行政区划 | `"陕西省"` | | **关联关系** | `string` | 支持一对一、一对多、多对一 | 存储关联记录的 ID | ### 逻辑列(计算字段)说明 逻辑列是在数据模型中定义但不在物理数据库表中实际存储的字段。这些字段的值由后台服务实时计算得出,通常用于表示关联关系。 #### 三种逻辑列类型: 1. **一对多关联** - 描述:当前模型的一条记录关联到另一个模型的多条记录 - 特点:物理表中不存在,通过LEFT JOIN查询获得 - 示例:一个"班级"关联多个"学生"。在班级表中,一对多字段并不真实存在。 2. **多对多关联** - 描述:当前模型的多条记录关联到另一个模型的多条记录 - 特点:物理表中不存在,通过中间表和LEFT JOIN查询获得 - 示例:"学生"与"课程"之间的选课关系。在学生表和课程表中,多对多字段并不真实存在。 3. **一对一反向关联** - 描述:一对多关系的特例,通过唯一索引约束实现一对一 - 特点:物理表中不存在,通过LEFT JOIN查询获得 - 示例:"学生证"与"学生"的一对一关系。 在学生证表中,一对一反向关联字段并不真实存在。 ### 🔧 自动编号格式说明 自动编号支持三种格式类型: 1. **字符串前缀**:`{前缀}-{SEQNUM:最小位数+起始值}` - 示例:`CAR-1000, CAR-1001, CAR-1002` 2. **日期前缀**:`{DATETIMEUTC:日期格式}-{SEQNUM:最小位数+起始值}` - 示例:`2024-01-15-0001, 2024-01-15-0002` 3. **自定义格式**:支持多种格式组合 - `{SEQNUM:4}` - 连续数字:`0001, 0002` - `{DATETIMEUTC:yyyy-MM-dd}` - 时间日期:`2024-01-15` - `{RANDSTRING:4}` - 随机字符串:`AB7L` ## ⚙️ 字段通用配置 ### 基础配置项 | 配置项 | 说明 | 规则 | |--------|------|------| | **字段名称** | 字段的显示名称 | 支持中英文 | | **字段标识** | 字段的唯一标识符 | 不能为空,不能以数字开头,只能包含字母、数字或_ | | **数据类型** | 字段的数据类型 | 从支持的字段类型中选择 | | **是否必填** | 该字段是否为必填项 | 影响数据校验 | | **是否唯一** | 该字段的取值是否允许重复 | 设置为唯一则不允许填重复值 | ### 主展示列配置 **适用条件**:数据类型为**文本**时可选择 **功能说明**:当其他数据模型配置关联关系指向本模型时,该字段会作为主展示列显示,方便用户查看 **配置影响**: - ✅ **影响展示效果**:在关联选择时显示该字段的值 - ❌ **不影响存储**:实际存储的仍然是关联记录的 ID #### 主展示列最佳实践: - 选择具有业务意义的字段作为主展示列(如"产品名称"而非"产品ID")。 - 保持主展示列值的唯一性和可读性。建议设置为唯一字段。 - 避免使用过长的文本作为主展示列。 ### 主展示列使用示例 以学生和课程模型为例: **学生模型配置**: ```json { "name": "张三", "course": "93e4b6a0640e9139042f27941b0ab7e6" // 存储课程ID } ``` **课程模型配置**: - 课程名称字段设置为主展示列 **查询结果**: ```json { "records": [{ "name": "张三", "course": "93e4b6a0640e9139042f27941b0ab7e6", "@course": { "v1": { "primaryColumn": "courseName", // 主展示列标识 "record": { "courseName": "语文", // 主展示列的值 "_id": "93e4b6a0640e9139042f27941b0ab7e6" } } } }] } ``` **表单组件中的效果**: - 下拉选择显示:`语文`(主展示列值) - 实际提交数据:`93e4b6a0640e9139042f27941b0ab7e6`(ID值) ## 💡 字段使用最佳实践 ### 字段类型选择建议 | 使用场景 | 推荐字段类型 | 原因 | |---------|-------------|------| | **用户姓名** | 单行文本 | 简短文本,便于显示和搜索 | | **商品描述** | 富文本 | 支持格式化,提升展示效果 | | **技术文档** | Markdown | 轻量级标记,便于编辑 | | **用户头像** | 图片 | 专门的图片处理和展示 | | **商品价格** | 数字 | 支持数值计算和比较 | | **订单状态** | 枚举(单选) | 限制可选值,保证数据一致性 | | **商品标签** | 枚举(多选) | 支持多个标签,便于分类 | | **订单编号** | 自动编号 | 自动生成,保证唯一性 | ### 性能优化建议 1. **文本长度控制**: - 短文本使用单行文本(4000字节限制) - 长文本使用富文本(262144字节限制) 2. **索引优化**: - 为常用查询字段建立索引 - 唯一字段自动创建唯一索引 3. **存储优化**: - 媒体文件使用云存储,字段存储 CloudID - 大对象数据考虑使用 JSON 类型 ### 数据校验注意事项 1. **格式化字段**:邮箱、电话、网址会自动进行格式验证 2. **枚举字段**:只能填入预设的枚举值 3. **关联字段**:必须是有效的关联记录 ID 4. **自动编号**:在新增和更新方法中不可修改 通过合理选择和配置字段类型,您可以构建出既灵活又高效的数据模型,满足各种复杂的业务需求。 --- ## 索引管理 # 索引管理 索引是提升数据库查询性能的关键技术。通过为常用查询字段建立索引,可以显著提升查询速度和用户体验。 ## 📋 管理入口 1. **访问控制台**:进入 [CloudBase 控制台](https://tcb.cloud.tencent.com/dev) 2. **选择数据库**:切换到 [数据库/文档型](https://tcb.cloud.tencent.com/dev?#/db/doc/model/?sourceType=internal_flexdb) 3. **进入索引管理**:选择目标集合,点击 「**索引管理**」 标签页 4. **管理索引**:新建、删除或修改索引配置 ![](https://qcloudimg.tencent-cloud.cn/raw/cd2458f2736dbf9010cc497dddee1524.png) ## 🎯 索引类型详解 ### 📌 单字段索引 **适用场景**:针对单个字段的查询和排序操作 **特点说明**: * 支持嵌套字段索引,使用"点表示法"访问 * 可指定升序或降序排序 * 适合简单的单条件查询 **示例配置**: ```json // 原始数据结构 { "_id": "product_001", "name": "iPhone 15", "price": 5999, "style": { "color": "深空黑", "storage": "128GB" } } ``` **索引配置示例**: | 字段路径 | 索引类型 | 排序方式 | 适用查询 | |---------|----------|----------|----------| | `name` | 单字段 | 升序 | 按商品名称查询 | | `price` | 单字段 | 降序 | 按价格排序 | | `style.color` | 单字段 | 升序 | 按颜色筛选 | > **💡 提示**:嵌套字段使用点表示法,如 `style.color` 表示访问 style 对象中的 color 字段。 ### 🔗 组合索引 **适用场景**:多字段联合查询和复杂排序操作 **核心概念**:一个索引包含多个字段,支持前缀匹配查询 **示例数据**: ```json { "_id": "student_001", "name": "张三", "age": 20, "score": 85, "class": "计算机科学" } ``` **索引前缀规则**: 假设创建组合索引: `name + age + score` | 索引前缀 | 能命中的查询组合 | 查询示例 | |---------|-----------------|----------| | `name` | 单独查询 name | `db.collection('students').where({name: '张三'})` | | `name, age` | 查询 name + age | `db.collection('students').where({name: '张三', age: 20})` | | `name, age, score` | 查询全部字段 | `db.collection('students').where({name: '张三', age: 20, score: 85})` | :::tip 💡 前缀匹配原理 组合索引 `(name, age, score)` 的前缀包含: * ✅ `name` - 可以命中索引 * ✅ `name, age` - 可以命中索引 * ✅ `name, age, score` - 可以命中索引 * ❌ `age` - 无法命中索引(不是前缀) * ❌ `score` - 无法命中索引(不是前缀) * ❌ `age, score` - 无法命中索引(不是前缀) ::: **组合索引的重要特性**: ### 🔄 1. 字段顺序的重要性 索引字段的顺序直接影响查询性能: | 索引定义 | 能命中的查询 | 无法命中的查询 | |---------|-------------|---------------| | `(name, age)` | ✅ `name` 查询✅ `name + age` 查询 | ❌ 单独 `age` 查询❌ `age + score` 查询 | | `(age, name)` | ✅ `age` 查询✅ `age + name` 查询 | ❌ 单独 `name` 查询❌ `name + score` 查询 | ### 📊 2. 排序方向的影响 排序查询时,索引的排序方向会影响是否能命中索引: **索引配置: `age: 升序, score: 降序` ** | 查询排序方式 | 是否命中索引 | 说明 | |-------------|-------------|------| | `age: 升序, score: 降序` | ✅ 命中 | 与索引方向完全一致 | | `age: 降序, score: 升序` | ✅ 命中 | 索引可反向使用 | | `age: 升序, score: 升序` | ❌ 未命中 | 排序方向不一致 | | `age: 降序, score: 降序` | ❌ 未命中 | 排序方向不一致 | | `score: 任意, age: 任意` | ❌ 未命中 | 不符合前缀规则 | **索引配置: `age: 升序, score: 升序` ** | 查询排序方式 | 是否命中索引 | 说明 | |-------------|-------------|------| | `age: 升序, score: 升序` | ✅ 命中 | 与索引方向完全一致 | | `age: 降序, score: 降序` | ✅ 命中 | 索引可反向使用 | | `age: 升序, score: 降序` | ❌ 未命中 | 排序方向不一致 | | `age: 降序, score: 升序` | ❌ 未命中 | 排序方向不一致 | ### 📍 地理位置索引 **适用场景**:地理位置查询、附近搜索、区域筛选 **功能特点**: * 支持平面几何的地理位置索引 * 必须为地理位置字段建立专门的地理位置索引 * 支持点、线、面等几何图形 **数据结构示例**: ```json { "_id": "store_001", "name": "星巴克咖啡店", "location": { "type": "Point", "coordinates": [116.4074, 39.9042] // [经度, 纬度] }, "address": "北京市朝阳区" } ``` **索引创建**: 1. 在控制台选择集合 2. 进入索引管理页面 3. 选择地理位置字段(如 `location`) 4. 设置索引类型为"地理位置索引" **查询示例**: ```javascript // 查询附近 1000 米内的店铺 db.collection('stores').where({ location: db.command.geoNear({ geometry: db.Geo.Point(116.4074, 39.9042), maxDistance: 1000 }) }).get() ``` ![地理位置索引配置](https://main.qcloudimg.com/raw/f36c7f4df1cf0e929a3a0666f4677c46.png) ## 索引使用注意事项 ### 唯一性限制 创建索引时,索引属性选择**唯一**,即可添加唯一性限制。此限制会要求集合中**索引字段对应的值不能重复**。 例如,某个集合内建立了索引字段 `foo` ,且属性为“唯一”,那么在这个集合内,要求不能存在 `foo` 字段相同的文档。 :::tip 注意 需特别注意的是,假如**记录中不存在某个字段,则对索引字段来说其值默认为 null**。如果索引有唯一性限制,则不允许存在两个或以上的该字段为空 / 不存在该字段的记录。 ::: ### 大小限制 * 索引的字段大小限制**不能超过 1024 字节**。 * 添加索引时,如果集合中已有文档索引字段超过 1024 字节,添加索引时将报错。 * 已设置索引的字段,如果插入一个文档,文档中该字段超过 1024 字节将会报错。 :::tip 注意 每个英文字母(不分大小写)占一字节的空间,每个中文汉字占两字节的空间。 ::: ### 正则表达式 正则查询无法使用索引提升性能。 --- ## 数据权限管理 # 数据权限管理 CloudBase 提供了多层次的数据权限管理机制,确保数据安全的同时满足不同业务场景的权限控制需求。 ## 🎯 权限管理体系 CloudBase 数据权限管理包含三个层次: | 权限类型 | 控制粒度 | 适用场景 | 配置复杂度 | |---------|----------|----------|------------| | **基础权限控制** | 模型级别 | 简单的权限需求 | 低 | | **角色权限** | 用户级别 | 组织架构权限 | 中 | | **安全规则权限** | 文档级别 | 复杂的业务逻辑 | 高 | ### 权限优先级 不同权限类型之间的关系: * **角色权限** 和 **基础权限** 取 **并集** 为最终权限 * **安全规则权限** 具有最高优先级,会覆盖其他权限设置 * 建议根据业务复杂度选择合适的权限管理方式 ## 🔧 基础权限控制 ### 功能特点 基础权限控制是最简单的权限管理方式,适合大多数常见的业务场景: * **模型级别控制**:针对整个数据模型设置统一权限 * **预设权限模板**:提供常用的权限配置模板 * **简单易用**:无需编写复杂的规则表达式 ### 配置方式 在 [CloudBase 控制台](https://tcb.cloud.tencent.com/dev) 的数据模型页面,为每个模型设置对应的权限: ![基础权限配置](https://qcloudimg.tencent-cloud.cn/raw/1f732163a324fb3bd90d6ea917ecbaaf.png) ### 权限选项 从用户的身份出发,去选择对应的权限 * 所有用户包含匿名用户、外部用户、内部用户。 * 一个匿名用户的实际权限是所有用户和匿名用户的权限最大集;外部用户和内部用户也是同理。 * **最佳实践一**:只通过所有用户来管理权限;设置匿名用户、外部用户、内部用户的权限为无权限。 * **最佳实践二**:删除"所有用户"的规则,通过细分角色来管理权限。 | 权限类型 | 适用场景 | |---------|----------| | **读取全部数据,修改本人数据** | 公开内容,如文章、商品 | | **读取和修改本人数据** | 私人数据,如用户资料 | | **读取全部数据,不可修改数据** | 配置数据,如系统设置 | | **无权限** | 敏感数据,如财务信息 | ## 👥 自定义角色权限控制 ### 功能概述 角色权限是基于组织架构的权限管理方式,适合企业级应用中的层级权限控制。它与基础权限控制相互补充,最终权限为两者的**并集**。 **核心特点**: * **组织架构支持**:基于部门、上下级关系的权限控制 * **角色继承**:支持权限的层级继承 * **灵活组合**:与基础权限取并集,提供更灵活的权限配置 ### 配置步骤 #### 第一步:进入角色管理 访问 **[自定义角色页面](https://tcb.cloud.tencent.com/cloud-admin?#/settings/roleManage)**,管理组织架构和角色定义: ![角色管理入口](https://qcloudimg.tencent-cloud.cn/raw/680553d87ff54c445070a5637aeae1c2.png) #### 第二步:配置行权限 选择目标角色,点击「**行权限设置**」进行详细配置: ![行权限设置](https://qcloudimg.tencent-cloud.cn/raw/4357984844dfe01b460a3178439c6015.png) ### 权限级别说明 | 权限级别 | 数据范围 | 适用场景 | 示例 | |---------|----------|----------|------| | **查看本人** | 所有人字段值为自己的数据 | 个人数据管理 | 员工只能查看自己的考勤记录 | | **查看本人及下属** | 自己和下属的数据 | 团队管理 | 主管可以查看团队成员的工作报告 | | **查看本部门及子部门** | 本部门及子部门的数据 | 部门管理 | 部门经理查看部门内所有项目 | | **查看全部** | 所有数据 | 系统管理 | 管理员查看全公司数据 | ### 权限组合规则 #### 读写权限关系 > **⚠️ 重要**:行修改权限自动包含读权限,即有修改权限就有读权限。 #### 权限并集计算 **基础权限** + **角色权限** = **最终权限** **示例场景**: ``` 基础权限:仅创建者及管理员可读写 角色权限:查看全部 + 无修改权限 ───────────────────────────────── 最终权限:可以查看所有数据,但只能修改自己创建的数据 ``` ### 实际应用案例 #### 案例 1:博客权限 **业务需求**: * 可以查看所有人的博客 * 自己更新自己的博客 **基础权限配置** 所有用户/读取全部数据,修改本人数据 #### 案例 2:项目管理系统 **业务需求**: * 项目成员只能查看参与的项目 * 项目经理可以管理负责的项目 * 部门经理可以查看部门所有项目 **基础权限配置** 所有用户/读取和修改本人数据 **角色权限配置** | 角色 | 角色数据权限 | 行修改权限 | 最终效果 | |------|-------------|-----------|----------| | **销售员** | 查看本人 | 本人 | 只能查看和修改自己的客户 | | **销售主管** | 查看本人及下属 | 本人及下属 | 可以管理团队所有客户 | | **销售总监** | 查看全部 | 查看全部 | 可以管理所有客户 | ### 权限设计最佳实践 #### 1. 权限设计原则 * **最小权限原则**:只授予完成工作所需的最小权限 * **职责分离**:不同角色承担不同的数据责任 * **权限继承**:合理利用组织架构的层级关系 #### 2. 常见配置模式 **只读扩展模式**: ``` 基础权限:仅创建者可读写 角色权限:扩大查看范围,不给修改权限 效果:扩大数据可见性,保持修改控制 ``` **管理员模式**: ``` 基础权限:仅创建者可读写 角色权限:查看全部 + 修改全部 效果:管理员可以管理所有数据 ``` **部门隔离模式**: ``` 基础权限:仅创建者可读写 角色权限:查看本部门 + 修改本部门 效果:部门间数据隔离,部门内共享 ``` #### 3. 注意事项 * **权限测试**:在生产环境前充分测试各种角色的权限 * **权限审计**:定期检查和调整权限配置 * **文档记录**:详细记录权限设计的业务逻辑 * **变更管理**:权限变更要有审批流程 --- ## 🛡️ 安全规则权限 ### 功能概述 安全规则权限提供了更灵活、可扩展、更细粒度的权限控制能力,支持基于文档内容的动态权限判断。 **核心特点**: * **文档级别控制**:可以根据文档的具体内容决定访问权限 * **表达式驱动**:使用类似编程语言的表达式定义权限逻辑 * **动态权限**:支持基于用户身份、时间、数据内容的动态权限判断 * **仅限制 C 端**:只限制客户端用户访问,不影响服务端(云函数)操作 ### 配置入口 切换到「**集合管理**」页面,通过「**安全规则权限**」设置更精细的安全规则: ![安全规则配置](https://qcloudimg.tencent-cloud.cn/raw/a830d7005bc59ddb8cdeba8ca234e48a.png) ### 规则配置格式 安全规则使用 JSON 格式配置,基本结构如下: ```json { "read": "表达式", "write": "表达式", "create": "表达式", "update": "表达式", "delete": "表达式" } ``` ### 操作类型说明 | 操作类型 | 说明 | 默认值 | 示例场景 | |---------|------|--------|----------| | **read** | 读取文档 | `false` | 查询、获取文档 | | **write** | 写入文档(通用) | `false` | 当未指定具体写操作时的默认规则 | | **create** | 创建文档 | 继承 `write` | 新增数据 | | **update** | 更新文档 | 继承 `write` | 修改现有数据 | | **delete** | 删除文档 | 继承 `write` | 删除数据 | > **💡 规则继承**:如果没有指定具体的写操作规则(create/update/delete),会自动使用 `write` 规则。 ### 表达式语法 #### 全局变量 | 变量名 | 类型 | 说明 | 示例 | |--------|------|------|------| | **auth** | Object | 用户登录信息 | `auth.openid` 、 `auth.uid` | | **doc** | Object | 文档数据或查询条件 | `doc.userId` 、 `doc.status` | | **request** | Object | 请求信息 | `request.data` | | **now** | Number | 当前时间戳 | `now > doc.expireTime` | #### 用户身份信息 (auth) | 字段 | 类型 | 说明 | 适用场景 | |------|------|------|----------| | **openid** | String | 微信用户 OpenID | 微信小程序登录 | | **uid** | String | 用户唯一 ID | Web 端登录 | | **loginType** | String | 登录方式 | 区分不同登录渠道 | #### 运算符支持 | 运算符 | 说明 | 示例 | 使用场景 | |--------|------|------|----------| | **==** | 等于 | `auth.uid == doc.userId` | 验证数据所有者 | | **!=** | 不等于 | `doc.status != 'deleted'` | 排除特定状态 | | **>、>=、= 18` | 数值范围判断 | | **in** | 包含于 | `auth.uid in doc.editors` | 检查用户是否在列表中 | | **&&** | 逻辑与 | `auth.uid == doc.userId && doc.published` | 多条件组合 | | **\|\|** | 逻辑或 | `auth.uid == doc.userId \|\| doc.public` | 多种访问方式 | ### 实际应用示例 #### 1. 基础权限映射 **所有用户可读,仅创建者可写**: ```json { "read": true, "write": "doc._openid == auth.openid" } ``` **仅创建者可读写**: ```json { "read": "doc._openid == auth.openid", "write": "doc._openid == auth.openid" } ``` #### 2. 复杂业务逻辑 **文章发布系统**: ```json { "read": "doc.published == true || doc.author == auth.uid", "create": true, "update": "doc.author == auth.uid", "delete": "doc.author == auth.uid && doc.published == false" } ``` **协作文档系统**: ```json { "read": "auth.uid in doc.readers || auth.uid in doc.editors || doc.owner == auth.uid", "write": "auth.uid in doc.editors || doc.owner == auth.uid" } ``` #### 3. 时间控制 **限时活动数据**: ```json { "read": "now >= doc.startTime && now 10" } // ✅ 符合规则(查询条件是规则的子集) db.collection('users').where({ age: _.gt(15) }).get() // ❌ 不符合规则(查询条件范围更大) db.collection('users').where({ age: _.gt(5) }).get() ``` #### 文档 ID 查询改造 传统的 `doc().get()` 查询需要改写为 `where()` 查询: ```javascript // ❌ 传统方式(不符合安全规则) db.collection('posts').doc('postId').get() // ✅ 改写后(符合安全规则) db.collection('posts').where({ _id: 'postId', _openid: '{openid}' // 使用模板变量 }).get() ``` ### 最佳实践 #### 1. 规则设计原则 * **最小权限原则**:只授予必要的权限 * **明确性原则**:规则表达式要清晰易懂 * **性能考虑**:避免过多的 `get()` 函数调用 #### 2. 常见模式 **数据所有者模式**: ```json { "read": "doc._openid == auth.openid", "write": "doc._openid == auth.openid" } ``` **公开读取,限制写入**: ```json { "read": true, "write": "doc.author == auth.uid" } ``` **基于状态的权限**: ```json { "read": "doc.status == 'published' || doc.author == auth.uid", "update": "doc.author == auth.uid && doc.status != 'locked'" } ``` #### 3. 调试技巧 * 使用简单的规则开始,逐步增加复杂度 * 在开发环境充分测试各种场景 * 注意查看控制台的权限错误信息 * 合理使用日志记录权限验证过程 ## 🎯 权限选择指南 ### 根据业务复杂度选择 | 业务场景 | 推荐方案 | 原因 | |---------|----------|------| | **简单应用** | 基础权限控制 | 配置简单,满足基本需求 | | **复杂业务逻辑** | 安全规则权限 | 灵活的表达式,支持复杂判断 | | **企业级应用** | 角色权限 + 基础权限 | 组织架构支持,权限层次清晰 | | **高安全要求** | 安全规则 + 角色权限 | 多层防护,精细控制 | ### 权限配置建议 1. **从简单开始**:先使用基础权限,根据需要逐步升级 2. **分层设计**:基础权限处理通用逻辑,安全规则处理特殊逻辑 3. **测试验证**:在开发环境充分测试各种权限场景 4. **文档记录**:详细记录权限设计思路和配置说明 通过合理的权限配置,您可以构建既安全又灵活的数据访问控制体系,满足各种复杂的业务需求。 --- ## 数据库SQL操作 # 数据库SQL操作 当数据模型 SDK 无法满足复杂查询需求时,可以直接使用 SQL 语句进行数据库操作。 此方法仅支持服务端调用 ## 适用场景 * 复杂的多表联查 * 聚合函数和统计查询 * 数据库特定功能 * 性能优化查询 ## 查询方法 MySQL 数据模型提供两种 SQL 查询方式: | 方法 | 说明 | 安全性 | 推荐度 | |------|------|--------|--------| | `$runSQL` | 预编译模式,参数化查询 | 高(防SQL注入) | ⭐⭐⭐ | | `$runSQLRaw` | 原始模式,直接执行SQL | 低(需自行防护) | ⭐ | > ⚠️ **重要提醒** > - 仅支持服务端调用(云函数、云托管等) > - 当前已支持 `CRUD` 语句 > - 建议优先使用 `$runSQL` 预编译模式 ## 初始化 SDK 请参考 [SDK 初始化](/database/sdk-init) 中 **node-sdk** 初始化方式进行初始化 1. **安装** ```bash npm install @cloudbase/node-sdk --save ``` 2. **初始化** ```js import cloudbase from "@cloudbase/node-sdk" // 云函数环境下需要用require方式加载node-sdk // const cloudbase = require('@cloudbase/node-sdk') // 初始化应用 const app = cloudbase.init({ env: "your-env-id" // 替换为您的环境 ID }) // 获取数据模型实例 const models = app.models ``` ## 预编译模式 `$runSQL` 使用参数化查询,通过 Mustache 语法( `{{ }}` )绑定参数,有效防止 SQL 注入。 ### 基础查询 ```js // 条件查询 const result = await models.$runSQL( "SELECT * FROM `table_name` WHERE title = {{title}} LIMIT 10", { title: "hello" } ); // 数值比较 const result = await models.$runSQL( "SELECT * FROM `table_name` WHERE read_num > {{num}}", { num: 1000 } ); // 时间查询 const result = await models.$runSQL( "SELECT * FROM `table_name` WHERE updatedAt > UNIX_TIMESTAMP({{timestamp}})", { timestamp: "2024-06-01 00:00:00" } ); ``` ### 模糊查询和聚合 ```js // LIKE 查询 const result = await models.$runSQL( "SELECT * FROM `table_name` WHERE author_tel LIKE {{tel}}", { tel: "1858%" } ); // 聚合函数 const result = await models.$runSQL( "SELECT COUNT(*) FROM `table_name` WHERE is_published = {{isPublished}}", { isPublished: true } ); // 指定字段 const result = await models.$runSQL( "SELECT read_num, title FROM `table_name`" ); ``` ### 返回结果格式 ```js // 成功返回示例 { "data": { "total": 1, "executeResultList": [{ "_id": "9JXU7BWFZJ", "title": "hello", "read_num": 997, // ... 其他字段 }], "backendExecute": "27" }, "requestId": "16244844-19fe-4946-8924-d35408ced576" } ``` ## 原始模式 `$runSQLRaw` 用于动态表名等特殊场景,需要自行处理 SQL 注入防范。 ### 基础用法 ```js // 直接执行 SQL const result = await models.$runSQLRaw( "SELECT * FROM `table_name` WHERE title = 'hello' LIMIT 10" ); // 动态表名场景 const tableName = getTableName(); // 确保来源安全 const result = await models.$runSQLRaw( `SELECT * FROM \`${tableName}\` WHERE status = 'active'` ); ``` ## 安全注意事项 使用 `$runSQLRaw` 时必须注意以下安全措施: * **优先使用预编译模式**:除非必要,建议使用 `$runSQL` * **验证用户输入**:严格验证和过滤所有用户输入 * **使用白名单**:只允许预定义的安全值 * **转义特殊字符**:特别注意单引号等 SQL 特殊字符 * **错误处理**:避免暴露详细的数据库错误信息 --- ## 初始化 SDK # 初始化 SDK 在创建数据模型中,自动会生成多端的操作 SDK,例如 小程序/云函数/Web 等,可以参考如下文档进行初始化和使用。 ## 在小程序中调用 ### 安装依赖 #### 方式一:下载 SDK 可以直接把下方的 SDK 链接文件下载到小程序代码的目录(一般是 `miniprogram` 目录)中,保存为 `wxCloudClientSDK.umd.js` https://weda.cloud.tencent.com/wx-cloud-client-sdk/1.6.1/wxCloudClientSDK.umd.js #### 方式二:通过 npm 引入 > [微信开发者工具使用 npm 指引](https://developers.weixin.qq.com/miniprogram/dev/devtools/npm.html) 在小程序 `package.json` 所在的目录(一般是 `miniprogram` 目录)执行命令安装 npm 包: ```bash npm install @cloudbase/wx-cloud-client-sdk --save ``` 然后点击微信开发者工具工具栏上的“工具” -> “构建 npm”。 ### 初始化和使用 SDK 在 app.js 中加入如下代码: ```js // 如果是下载 SDK 的方式,改成 const { init } = require('./wxCloudClientSDK.umd.js') const { init } = require("@cloudbase/wx-cloud-client-sdk"); // 指定云开发环境 ID wx.cloud.init({ env: "some-env-id", // 当前的云开发环境 ID }); const client = init(wx.cloud); const models = client.models; // 或者也可以直接从 wx.cloud.models 上获取,这种方式的类型提示会弱一些 // 接下来就可以调用 models 上的数据模型增删改查等方法了 // models.post.create({ // data: { // body: "你好,世界👋\n\nfrom china", // title: "你好,世界👋", // slug: "hello-world-cn", // }, // }).then(({ data } => { console.log(data)})) ``` ## 在云函数中调用 云函数中使用需在对应云函数目录下安装 `@cloudbase/node-sdk` 3.10.0 以上的版本 ### 安装依赖 在创建云函数时会在云函数目录下默认新建一个 `package.json` 并提示用户是否立即本地安装依赖。请注意云函数的运行环境是 Node.js,因此在本地安装依赖时务必保证已安装 Node.js,同时 `node` 和 `npm` 都在环境变量中。如不本地安装依赖,可以用命令行在该目录下运行: ``` npm install --save @cloudbase/node-sdk@3.10 ``` ### 初始化和使用 SDK 在云函数中调用数据模型 SDK 之前,需要执行一次初始化方法: ```js const cloudbase = require("@cloudbase/node-sdk"); // 指定云开发环境 ID const app = cloudbase.init({ env: "some-env-id", }); exports.main = async (event, context) => { const models = app.models; // 接下来就可以调用 models 上的数据模型增删改查等方法了 // models.post.create({ // data: { // body: "你好,世界👋\n\nfrom china", // title: "你好,世界👋", // slug: "hello-world-cn", // }, // }).then(({ data } => { console.log(data)})) }; ``` ## 在 Web 页面中调用 ### 安装依赖 在 Web 项目的根目录下,使用 npm 或 yarn 安装所需的包: ```bash npm install @cloudbase/js-sdk --save ``` ### 初始化和使用 SDK ```js import cloudbase from "@cloudbase/js-sdk"; // 引入 SDK const app = cloudbase.init({ env: "your-cloud-env-id", // 替换为你的云开发环境 ID clientId: "your-cloud-env-id", // 替换为你的云开发环境 ID }); const auth = app.auth({ persistence: "local", }); await auth.signInAnonymously(); // 或者使用其他登录方式 const models = app.models; // 接下来就可以调用 models 上的数据模型增删改查等方法了 // 示例:创建一个 post 数据记录 // models.post.create({ // data: { // body: "你好,世界👋\n\nfrom china", // title: "你好,世界👋", // slug: "hello-world-cn", // }, // }).then(({ data } => { console.log(data)})) ``` ## 多端支持 @cloudbase/js-sdk 支持多端调用,详情可参考[一套代码多端适配](../api-reference/webv3/adapter/adapter.md#一套代码多端适配)。若有 Web 和小程序多端开发需求,请使用 @cloudbase/js-sdk 的方式调用。在小程序使用 @cloudbase/js-sdk 时,若有减少小程序包体积的需求,可以参考[按需引入功能模块](../api-reference/webv3/initialization.md#方式二按需引入功能模块)。 --- ## 快速开始 import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # 快速开始 ### 🎯 实际案例:博客系统 让我们通过创建一个博客系统的数据模型来演示如何使用这些字段类型: ```json { "title": "我的第一篇博客", // 文章标题 "content": "这是富文本内容", // 文章正文内容 "author": "张三", // 作者姓名 "email": "zhangsan@example.com", // 作者邮箱 "published": true, // 是否已发布 "viewCount": 1024, // 浏览次数 "tags": ["技术", "前端", "Vue"], // 文章标签 "metadata": { // 文章元数据 "seo": { "keywords": "Vue, 前端开发", // SEO 关键词 "description": "Vue 前端开发教程" // SEO 描述 } }, "coverImage": "https://example.com/cover.jpg", // 封面图片 "publishedAt": "2024-01-15T10:30:00Z", // 发布时间 "status": "published", // 文章状态 "articleNo": "A000001", // 文章编号 "location": { // 发布地点 "type": "Point", "coordinates": [116.4074, 39.9042] // 经纬度坐标(北京) } } ``` ### 第一步:访问数据模型管理页面 1. **访问控制台**:进入 [CloudBase 控制台](https://tcb.cloud.tencent.com/dev) 2. **选择数据库**:切换到 [数据库/文档型](https://tcb.cloud.tencent.com/dev?#/db/doc/model/?sourceType=internal_flexdb) 3. **创建模型**:点击「**新建模型**」 ### 第二步:设计模型结构 以博客系统为例,我们需要创建两个相关的数据模型: #### 📝 文章模型(article) | 字段名 | 字段类型 | 是否必填 | 描述 | |--------|----------|----------|------| | `title` | 文本 | 是 | 文章标题 | | `content` | 富文本 | 是 | 文章内容 | | `summary` | 文本 | 否 | 文章摘要 | | `author` | 文本 | 是 | 作者姓名 | | `email` | 邮箱 | 是 | 作者邮箱 | | `coverImage` | 图片 | 否 | 封面图片 | | `tags` | 数组 | 否 | 文章标签 | | `published` | 布尔值 | 是 | 是否发布 | | `viewCount` | 数字 | 否 | 浏览次数 | | `publishedAt` | 日期时间 | 否 | 发布时间 | | `status` | 枚举 | 是 | 文章状态(草稿/已发布/已下线) | #### 💬 评论模型(comment) | 字段名 | 字段类型 | 是否必填 | 描述 | |--------|----------|----------|------| | `content` | 文本 | 是 | 评论内容 | | `author` | 文本 | 是 | 评论者姓名 | | `email` | 邮箱 | 是 | 评论者邮箱 | | `website` | 网址 | 否 | 评论者网站 | | `article` | 文本 | 是 | 关联的文章Id | | `approved` | 布尔值 | 是 | 是否审核通过 | ## 📱 使用 SDK 操作数据 ### 初始化 SDK ```javascript // 下载并引入 SDK 文件 const cloudbase = require("@cloudbase/wx-cloud-client-sdk"); // 初始化云开发 wx.cloud.init({ env: "your-env-id", // 替换为您的环境 ID }); // 初始化数据模型客户端 const client = cloudbase.init(wx.cloud); const models = client.models; ``` ```javascript import cloudbase from "@cloudbase/js-sdk" // 初始化应用 const app = cloudbase.init({ env: "your-env-id" // 替换为您的环境 ID }) // 获取数据模型实例 const models = app.models // 获取数据库实例(用于集合操作) const db = app.database() ``` ```javascript const cloudbase = require("@cloudbase/node-sdk") // 初始化应用 const app = cloudbase.init({ env: "your-env-id" // 替换为您的环境 ID }) // 获取数据模型实例 const models = app.models // 获取数据库实例(用于集合操作) const db = app.database() ``` ### 基本数据操作 #### 创建文章 ```javascript // 创建新文章 const { data } = await models.article.create({ data: { title: "Vue 3 入门教程", content: "Vue 3 简介Vue 3 是一个现代化的前端框架...", summary: "本文介绍 Vue 3 的基本概念和使用方法", author: "张三", email: "zhangsan@example.com", tags: ["Vue", "前端", "教程"], published: true, status: "published", publishedAt: new Date().toISOString() } }); console.log("文章创建成功:", data.id); ``` #### 查询文章列表 ```javascript // 查询已发布的文章 const { data } = await models.article.list({ filter: { where: { published: { $eq: true }, status: { $eq: "published" } } }, sort: { publishedAt: 'desc' // 按发布时间倒序 }, pageSize: 10, pageNumber: 1 }); console.log("文章列表:", data.records); console.log("总数:", data.total); ``` #### 创建评论 ```javascript // 为文章创建评论 const { data } = await models.comment.create({ data: { content: "这篇文章写得很好!", author: "李四", email: "lisi@example.com", website: "https://lisi.blog", article: "文章ID", // 关联到具体文章 approved: false // 待审核 } }); console.log("评论创建成功:", data.id); ``` #### 关联查询 ```javascript // 查询文章及其评论 const { data } = await models.article.get({ filter: { where: { _id: { $eq: "文章ID" } } }, select: { $master: true, comments: true } }); console.log("文章详情:", data); console.log("评论列表:", data.comments); ``` ## 🎯 最佳实践 ### 1. 表结构设计建议 * **索引设计**:为常用查询字段创建索引,提高查询性能 * **枚举类型**:使用 **枚举** 限制状态字段的可选值 ### 2. 模型设计原则 * **规范化设计**:避免数据冗余,遵循数据库范式 * **关联关系**:设计清晰的表间关系(一对一、一对多) * **字段命名**:使用有意义的英文字段名,遵循命名规范 * **必填验证**:合理设置必填约束,保证数据完整性 ### 3. 性能优化 * **索引优化**:为常用查询字段创建合适的索引 * **分页查询**:大量数据使用分页避免性能问题 * **字段选择**:查询时只返回需要的字段 ### 4. 安全建议 * **权限控制**:通过安全规则控制数据访问权限 * **密码加密**:敏感信息如密码必须加密存储 ## 🚀 下一步 恭喜!您已经成功创建了第一个文档型数据模型。接下来可以: * 📚 [学习更多 CRUD 操作](/model/sdk-reference/model) * 🔗 [掌握关联查询技巧](/model/config/relation) * 🎛️ [使用数据管理](/toolbox/manage-data) * 🔒 [配置数据安全规则](/database/data-permission) **开始构建您的应用吧!** 🎉 --- ## 概述 # 概述 ## 什么是数据模型? 数据模型是云开发提供的**声明式数据管理解决方案**,它构建在云开发数据库之上,为开发者提供了一种更高效、更安全的数据操作方式。 简单来说,数据模型就像是为您的数据定制的"智能管家": - 📋 **定义数据结构**:通过可视化界面定义数据的字段、类型和关系 - 🛡️ **自动数据校验**:确保数据的准确性和一致性 - 🔗 **处理关联关系**:自动管理数据之间的复杂关系 - 🚀 **包含多端 SDK**:一次定义,多端使用(小程序、Web、云函数) - 🎛️ **内置管理界面**:提供开箱即用的数据管理后台 - 🤖 **AI 智能分析**:利用人工智能挖掘数据价值 > **💡 核心理念**:让开发者专注于业务逻辑,而不是底层数据操作的复杂性。 ## 核心特性一览 | 特性 | 描述 | 价值 | |------|------|------| | 🔍 **智能数据校验** | 自动检查数据类型和格式,防止错误数据入库 | 提高数据质量,减少 Bug | | 🔗 **关联关系管理** | 自动处理一对一、一对多、多对多关系 | 简化复杂查询,提升开发效率 | | ⚡ **包含多端 SDK** | 一次定义,自动生成小程序/Web/云函数 SDK | 统一开发体验,减少重复工作 | | 🎛️ **可视化管理** | 内置 CMS 管理界面,支持非技术人员操作 | 降低运营成本,提升协作效率 | | 🏗️ **低代码应用生成** | 一键生成可定制的管理后台应用 | 快速交付,缩短开发周期 | | 🤖 **AI 数据分析** | 智能分析数据趋势和模式 | 数据驱动决策,挖掘业务价值 | | 🚀 **高级查询能力** | 支持复杂条件查询、聚合分析等 | 满足多样化业务需求 | ![数据模型架构图](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/37035ab2-53cd-4a2d-8efb-bda94013ec43.png) ## 数据模型和数据库的关系 数据模型是对数据库的建模,它定义了数据模型的结构、字段、约束和关系。数据模型提供了一种统一的方式来描述和操作数据,简化了数据操作和查询。数据模型能力即为开发中常用的对象关系映射 ORM。 数据模型和数据库是关联关系,一个数据模型,对应了数据库中的一个集合(非结构化数据库)或表(结构化数据库)。 使用数据模型,不代表被限制为仅能使用数据模型。在使用数据模型的同时,如果需要有更复杂、或数据模型无法很好完成的操作,也可以通过数据库的原生方法,直接操作数据库完成数据读写。 相对于传统开发框架中的 ORM,云开发数据模型除 ORM 相关的 SDK 操作数据的能力外,额外整合了数据管理界面、用户及权限体系、内容管理以及进一步的基于数据模型的应用生成、数据分析等更多能力。更多优势点可以查看 “为什么要使用数据模型”。 ## 如何开始使用数据模型? ### 🚀 快速开始 1. **访问控制台**:进入 [CloudBase 控制台](https://tcb.cloud.tencent.com/dev) 2. **选择数据库**:切换到 [数据库/文档型](https://tcb.cloud.tencent.com/dev?#/db/doc/model/?sourceType=internal_flexdb) 3. **创建模型**:点击【新建模型】,选择创建方式 ### 📋 创建方式 | 方式 | 适用场景 | 说明 | |------|----------|------| | **🆕 添加模型** | 新项目开发 | 从零开始创建全新的数据模型 | | **📦 导入旧版 CMS** | 项目迁移 | 从现有的云开发 CMS 导入模型,享受新版本的功能升级 | ![创建数据模型](https://qcloudimg.tencent-cloud.cn/raw/90697e01ebe194a85f6075665bd61d1c.png) ### ✅ 创建完成 新建模型后,您就可以立即使用数据模型提供的各项强大能力了! > **💡 提示**:建议先阅读 [快速开始](/model/initialization) 教程,通过实际案例快速上手。 ## 为什么选择数据模型? 数据模型为开发者带来了**全方位的开发体验提升**: - 🚀 **提高开发效率**:自动生成 SDK,减少重复代码编写 - 💰 **降低维护成本**:统一的数据管理,减少运维工作量 - 🛡️ **增强数据安全**:内置权限控制和数据校验机制 - 📊 **强化数据分析**:AI 智能分析,挖掘数据价值 - 🎯 **简化团队协作**:可视化管理界面,技术与非技术人员都能轻松使用 ### 🛡️ 智能数据校验和类型检查 数据模型提供**自动化的数据校验机制**,在数据入库前进行严格的类型检查和格式验证,确保数据的准确性和一致性,从源头避免数据质量问题。 #### 📝 实际案例演示 假设我们定义了一个文章模型 `post`,包含以下字段: - `title`(字符串类型)- 文章标题 - `body`(字符串类型)- 文章内容 现在我们故意传入错误类型的数据来测试校验机制: ```javascript try { const { data } = await models.post.create({ data: { title: "你好,世界👋", body: 123456, // ❌ 故意传入数字类型,期望的是字符串类型 }, }); console.log("创建成功:", data); } catch (error) { console.error("校验失败:", error); } ``` #### 🚨 校验结果 当我们尝试插入类型错误的数据时,数据模型会立即检测到问题并阻止操作: ```bash Error: WxCloudSDKError: 【错误】数据格式校验失败。根因:[#/body: expected type: String, found: Integer],原因:字段[正文], 标识[body], 类型不匹配:期望类型:字符串。,解决步骤:请按照原因修改数据类型。 errRecord:{"title":"你好,世界👋","body":123456}【操作】调用 post.create ``` #### ✅ 校验优势 - **🔍 精确定位**:准确指出哪个字段出现了什么问题 - **📝 友好提示**:提供清晰的错误原因和解决建议 - **🛡️ 数据保护**:防止脏数据进入数据库 - **🐛 减少 Bug**:在开发阶段就发现数据类型问题 ### 🔗 智能关联关系处理 数据模型能够**自动处理复杂的数据关联关系**,支持一对一、一对多、多对多等各种关系类型。无需手动编写复杂的 JOIN 查询,系统会自动处理数据之间的关联逻辑。 #### 🎯 关联查询示例 以文章和评论的关联关系为例,我们可以轻松实现跨模型的数据查询。通过 [`select`](sdk-reference/model#select) 参数,可以精确控制返回的字段和关联数据: ```javascript const { data } = await models.post.list({ // 精确控制返回字段,优化查询性能 select: { _id: true, title: true, updatedAt: true, // 关联查询评论数据 comments: { _id: true, createdAt: true, comment: true, }, }, filter: { where: {}, // 查询条件 }, getCount: true, // 获取总数 }); console.log("查询结果:", data); ``` #### 📊 返回结果 系统会自动处理关联关系,返回结构化的数据: ```json { "records": [ { "_id": "9FSAHWM9VV", "title": "Bonjour le Monde👋", "updatedAt": 1718096503886, "comments": [ { "_id": "9FSAJF3GLG", "createdAt": 1718096509916, "comment": "这是一条评论" } ] }, { "_id": "9FSAHWM9VU", "title": "你好,世界👋", "updatedAt": 1718096503886, "comments": [] // 暂无评论 } ], "total": 2 } ``` #### ✨ 关联查询优势 - **🚀 性能优化**:只返回需要的字段,减少数据传输 - **🔄 自动关联**:无需手写复杂的 JOIN 语句 - **📱 多层嵌套**:支持深层次的关联数据查询 - **🎯 精确控制**:灵活指定每个关联对象的返回字段 ### ⚡ 多端 SDK 自动生成 云开发平台提供了**多端对接的 SDK**,支持小程序、Web、云函数等多个平台。一次定义,多端复用,大幅提升开发效率。 #### 🔄 智能 Upsert 操作 以 [upsert()](sdk-reference/model#upsert) 方法为例,它能智能判断是创建新记录还是更新现有记录: ```javascript const postData = { title: "Hello World", body: "这是一篇示例文章", _id: "hello-world-post", }; const { data } = await models.post.upsert({ create: postData, // 如果不存在则创建 update: postData, // 如果存在则更新 filter: { where: { _id: { $eq: postData._id } }, }, }); console.log("操作结果:", data); ``` #### 📊 返回结果说明 ```javascript // 🆕 创建新记录时 { "count": 0, // 更新的记录数为 0 "id": "hello-world-post" // 新创建记录的 ID } // 🔄 更新现有记录时 { "count": 1, // 更新的记录数为 1 "id": "" // 更新操作不返回 ID } ``` #### 🎯 多端 SDK 优势 - **📱 统一接口**:所有平台使用相同的 API 调用方式 - **🔒 类型安全**:TypeScript 支持,编译时发现错误 - **⚡ 自动优化**:根据平台特性自动优化性能 - **🔄 实时同步**:模型变更后 SDK 自动更新 ### 🎛️ 内置数据管理系统 数据模型提供**开箱即用的内容管理系统(CMS)**,让非技术人员也能轻松进行数据管理和维护,大幅降低运营成本。 #### ✨ 核心功能 - **📝 可视化编辑**:直观的表单界面,无需编程知识 - **👥 权限管理**:细粒度的用户权限控制 - **📊 数据统计**:内置数据分析和报表功能 - **🔍 高级搜索**:支持多条件筛选和排序 - **📱 响应式设计**:支持桌面和移动端访问 > **📚 了解更多**:查看 * 🎛️ [使用数据管理](/toolbox/manage-data) 了解完整功能 ![管理界面](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/8cdd0b8d-83b7-496f-a93b-38949ac362d5.png) ### 🏗️ 低代码应用生成器 数据模型支持**一键生成完整的管理后台应用**,采用先进的低代码技术,支持可视化修改和定制开发,让您无需从零编写管理界面。 #### 🎨 低代码特性 - **🖱️ 拖拽式设计**:通过拖拽组件快速构建界面 - **🎯 模板丰富**:提供多种预设模板和组件 - **🔧 深度定制**:支持自定义样式和业务逻辑 - **📦 一键部署**:生成的应用可直接部署使用 - **🔄 实时预览**:所见即所得的开发体验 ![低代码应用生成器](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/b2b54b47-7b1d-48ec-b294-4e98a27e5d58.png) ### 🤖 AI 智能数据分析 数据模型集成了**强大的 AI 分析引擎**,能够自动挖掘数据中的模式和趋势,为业务决策提供智能化支持。 #### 🧠 AI 分析能力 - **📈 趋势预测**:基于历史数据预测未来趋势 - **🔍 异常检测**:自动识别数据中的异常模式 - **📊 智能报表**:自动生成可视化分析报告 - **💡 洞察建议**:提供基于数据的业务建议 - **🎯 用户画像**:智能分析用户行为特征 > **🚀 价值体现**:从海量数据中提取有价值的商业洞察,让数据真正驱动业务增长 ![AI 智能分析界面](https://qcloudimg.tencent-cloud.cn/image/document/22a107ad53ac7ac6d527c6630b46ce7a.png) ### 🚀 高级数据库查询支持 数据模型支持**原生 SQL 查询**,兼容 MySQL 等关系型数据库的高级查询功能。当模型 API 无法满足复杂查询需求时,您可以直接使用 SQL 语句进行精确控制。 #### 💪 高级查询能力 - **🔍 复杂条件筛选**:支持多表联查、子查询等 - **📊 聚合分析**:GROUP BY、HAVING、聚合函数等 - **⚡ 性能优化**:索引优化、查询计划分析 - **🔒 安全防护**:参数化查询,防止 SQL 注入 #### 📝 实际案例 查询作者联系电话以"1858"开头的记录: ```javascript const result = await models.$runSQL( "SELECT * FROM `article_table` WHERE author_tel LIKE '{{tel}}';", { tel: "1858%", // 参数化查询,安全可靠 } ); console.log("查询结果:", result); ``` #### 📊 返回结果 ```json { "data": { "total": 1, "executeResultList": [ { "_id": "9JXU7BWFZJ", "title": "示例文章", "author_tel": "18588881111", "createdAt": 1719475245475, "region": "北京市" // ... 其他字段 } ], "backendExecute": "28" }, "requestId": "0d4c98c3-a3ff-4c55-93cc-d0f5c835f82c" } ``` > **📚 深入学习**:查看 [数据库原生查询文档](/model/db-raw-query) 了解更多高级用法 --- ## 🎯 总结 云开发数据模型为现代应用开发提供了**全方位的数据管理解决方案**: - 🏗️ **架构优势**:基于云原生架构,稳定可靠 - 🚀 **开发效率**:自动生成 SDK,减少重复工作 - 🛡️ **数据安全**:内置校验和权限控制机制 - 🎛️ **管理便捷**:可视化管理界面,降低运营成本 - 🤖 **智能分析**:AI 驱动的数据洞察能力 - 🔧 **灵活扩展**:支持原生查询和自定义逻辑 **立即开始您的数据模型之旅!** 👉 [快速开始教程](/model/quickstart) --- ## 数据导入/导出 # 数据导入/导出 ## 🗄️ 数据模型快速导入导出 进入对应 [数据模型](https://tcb.cloud.tencent.com/dev#/data-model/database) 页面,选择对应数据模型,点击「**导入/导出**」按钮即可,导入导出格式均为Excel格式(.xlsx) ![](https://qcloudimg.tencent-cloud.cn/raw/bfbe630d95cb07ed5bde0c6b414248af.png) 若您想导出JSON/CSV格式的数据,请参考 [集合管理](/database/manage) 进行导入导出章节 --- ## 快速开始 import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # 快速开始 ### 🎯 实际案例:博客系统 让我们通过创建一个博客系统的数据模型来演示如何使用这些字段类型: ```json { "title": "我的第一篇博客", // 文章标题 "content": "这是富文本内容", // 文章正文内容 "author": "张三", // 作者姓名 "email": "zhangsan@example.com", // 作者邮箱 "published": true, // 是否已发布 "viewCount": 1024, // 浏览次数 "tags": ["技术", "前端", "Vue"], // 文章标签 "metadata": { // 文章元数据 "seo": { "keywords": "Vue, 前端开发", // SEO 关键词 "description": "Vue 前端开发教程" // SEO 描述 } }, "coverImage": "https://example.com/cover.jpg", // 封面图片 "publishedAt": "2024-01-15T10:30:00Z", // 发布时间 "status": "published", // 文章状态 "articleNo": "A000001", // 文章编号 "location": { // 发布地点 "type": "Point", "coordinates": [116.4074, 39.9042] // 经纬度坐标(北京) } } ``` ## 文档型 文档型数据库是 CloudBase 提供的 NoSQL 数据库服务,支持灵活的 JSON 文档存储。本文将介绍如何通过数据模型来初始化和使用文档型数据库。 ### 第一步:访问数据模型管理页面 1. **访问控制台**:进入 [CloudBase 控制台](https://tcb.cloud.tencent.com/dev) 2. **选择数据库**:切换到 [数据库/文档型](https://tcb.cloud.tencent.com/dev?#/db/doc/model/?sourceType=internal_flexdb) 3. **创建模型**:点击「**新建模型**」 ### 第二步:设计模型结构 以博客系统为例,我们需要创建两个相关的数据模型: #### 📝 文章模型(article) | 字段名 | 字段类型 | 是否必填 | 描述 | |--------|----------|----------|------| | `title` | 文本 | 是 | 文章标题 | | `content` | 富文本 | 是 | 文章内容 | | `summary` | 文本 | 否 | 文章摘要 | | `author` | 文本 | 是 | 作者姓名 | | `email` | 邮箱 | 是 | 作者邮箱 | | `coverImage` | 图片 | 否 | 封面图片 | | `tags` | 数组 | 否 | 文章标签 | | `published` | 布尔值 | 是 | 是否发布 | | `viewCount` | 数字 | 否 | 浏览次数 | | `publishedAt` | 日期时间 | 否 | 发布时间 | | `status` | 枚举 | 是 | 文章状态(草稿/已发布/已下线) | #### 💬 评论模型(comment) | 字段名 | 字段类型 | 是否必填 | 描述 | |--------|----------|----------|------| | `content` | 文本 | 是 | 评论内容 | | `author` | 文本 | 是 | 评论者姓名 | | `email` | 邮箱 | 是 | 评论者邮箱 | | `website` | 网址 | 否 | 评论者网站 | | `article` | 文本 | 是 | 关联的文章Id | | `approved` | 布尔值 | 是 | 是否审核通过 | ## 📱 使用 SDK 操作数据 ### 初始化 SDK ```javascript // 下载并引入 SDK 文件 const { init } = require("./wxCloudClientSDK.umd.js"); // 初始化云开发 wx.cloud.init({ env: "your-env-id", // 替换为您的环境 ID }); // 初始化数据模型客户端 const client = init(wx.cloud); const models = client.models; ``` ```javascript import cloudbase from "@cloudbase/js-sdk" // 初始化应用 const app = cloudbase.init({ env: "your-env-id" // 替换为您的环境 ID }) // 获取数据模型实例 const models = app.models // 获取数据库实例(用于集合操作) const db = app.database() ``` ```javascript import cloudbase from "@cloudbase/node-sdk" // 初始化应用 const app = cloudbase.init({ env: "your-env-id" // 替换为您的环境 ID }) // 获取数据模型实例 const models = app.models // 获取数据库实例(用于集合操作) const db = app.database() ``` ### 基本数据操作 #### 创建文章 ```javascript // 创建新文章 const { data } = await models.article.create({ data: { title: "Vue 3 入门教程", content: "Vue 3 简介Vue 3 是一个现代化的前端框架...", summary: "本文介绍 Vue 3 的基本概念和使用方法", author: "张三", email: "zhangsan@example.com", tags: ["Vue", "前端", "教程"], published: true, status: "published", publishedAt: new Date().toISOString() } }); console.log("文章创建成功:", data.id); ``` #### 查询文章列表 ```javascript // 查询已发布的文章 const { data } = await models.article.list({ filter: { where: { published: true, status: "published" } }, sort: { publishedAt: -1 // 按发布时间倒序 }, pageSize: 10, pageNumber: 1 }); console.log("文章列表:", data.records); console.log("总数:", data.total); ``` #### 创建评论 ```javascript // 为文章创建评论 const { data } = await models.comment.create({ data: { content: "这篇文章写得很好!", author: "李四", email: "lisi@example.com", website: "https://lisi.blog", article: "文章ID", // 关联到具体文章 approved: false // 待审核 } }); console.log("评论创建成功:", data.id); ``` #### 关联查询 ```javascript // 查询文章及其评论 const { data } = await models.article.get({ filter: { where: { _id: "文章ID" } }, expand: ["comments"] // 展开关联的评论 }); console.log("文章详情:", data); console.log("评论列表:", data.comments); ``` ## 🎯 最佳实践 ### 1. 表结构设计建议 * **索引设计**:为常用查询字段创建索引,提高查询性能 * **枚举类型**:使用 **枚举** 限制状态字段的可选值 ### 2. 模型设计原则 * **规范化设计**:避免数据冗余,遵循数据库范式 * **关联关系**:设计清晰的表间关系(一对一、一对多) * **字段命名**:使用有意义的英文字段名,遵循命名规范 * **必填验证**:合理设置必填约束,保证数据完整性 ### 3. 性能优化 * **索引优化**:为常用查询字段创建合适的索引 * **分页查询**:大量数据使用分页避免性能问题 * **字段选择**:查询时只返回需要的字段 ### 4. 安全建议 * **权限控制**:通过安全规则控制数据访问权限 * **密码加密**:敏感信息如密码必须加密存储 ## 🚀 下一步 恭喜!您已经成功创建了第一个文档型数据模型。接下来可以: * 📚 [学习更多 CRUD 操作](/model/sdk-reference/model) * 🔗 [掌握关联查询技巧](/model/config/relation) * 🎛️ [使用数据管理](/toolbox/manage-data) * 🔒 [配置数据安全规则](/database/data-permission) **开始构建您的应用吧!** 🎉 --- ## _model ## 🔍 查询数据 ### 单条查询 通过指定条件查询单条记录。 #### 参数说明 | 参数 | 类型 | 必填 | 说明 | |------|------|---|------| | **filter.where** | `object` | ❌ 否 | 查询条件 | | **select** | `object` | ✅ 是 | 指定返回字段 | #### 代码示例 ```javascript // 根据 ID 查询单条记录 const todo = await models.todo.get({ filter: { where: { _id: { $eq: "todo-id-123" } } } }) console.log('查询结果:', todo.data) ``` #### 返回结果 ```javascript { data: { records: [{ _id: "todo-id-123", title: "服务端任务", completed: false, // ... 其他字段 }], total: 1 } } ``` ### 多条查询 查询多条记录,支持条件筛选、排序、分页等。具体参数说明请参考 [查询参数详解](/model/select) 文档。 #### 参数说明 | 参数 | 类型 | 必填 | 说明 | |------|------|---|------| | **filter.where** | `object` | ❌ 否 | 查询条件 | | **select** | `object` | ✅ 是 | 指定返回字段 | #### 代码示例 ```javascript // 基础查询 const todos = await models.todo.list({ filter: { where: { completed: { $eq: false } }, orderBy: [{ field: "priority", direction: "desc" }, { field: "createdAt", direction: "asc" } ] } }) console.log('查询结果:', todos.data) ``` #### 返回结果 ```javascript { data: { records: [{ _id: "todo-id-1", title: "任务1", completed: false }, { _id: "todo-id-2", title: "任务2", completed: true } ], total: 2 } } ``` ## ➕ 新增数据 ### 单条新增 向数据模型中添加一条新记录。 #### 参数说明 | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | **data** | `object` | ✅ 是 | 要新增的数据对象 | #### 代码示例 ```javascript // 创建单条记录 const todo = await models.todo.create({ data: { title: "服务端任务", description: "使用 node-sdk 创建的任务", priority: "high", completed: false, createdAt: new Date(), createdBy: "system", metadata: { source: "api", version: "1.0" } } }) console.log('创建成功:', todo) ``` ### 批量新增 一次性向数据模型中添加多条记录。 #### 参数说明 | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | **data** | `array` | ✅ 是 | 包含多个数据对象的数组 | #### 代码示例 ```javascript // 批量创建多条记录 const todos = await models.todo.createMany({ data: [{ title: "批量任务1", priority: "high" }, { title: "批量任务2", priority: "medium" }, { title: "批量任务3", priority: "low" } ] }) console.log('批量创建成功:', todos) ``` ## 📝 更新数据 ### 单条更新 根据条件更新单条记录。 #### 参数说明 | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | **data** | `object` | ✅ 是 | 要更新的数据对象 | | **filter.where** | `object` | ✅ 是 | 查询条件,确定要更新的记录 | #### 代码示例 ```javascript // 更新单条记录 const result = await models.todo.update({ data: { title: "更新后的任务", completed: true, updatedAt: new Date(), updatedBy: "admin" }, filter: { where: { _id: { $eq: "todo-id" // 推荐使用 _id 进行精确操作 } } } }) console.log('更新结果:', result) ``` ### 批量更新 根据查询条件批量更新多条记录。 #### 参数说明 | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | **data** | `object` | ✅ 是 | 要更新的数据对象 | | **filter.where** | `object` | ✅ 是 | 查询条件,确定要更新的记录 | #### 代码示例 ```javascript // 批量更新多条记录 const result = await models.todo.updateMany({ data: { status: "archived", archivedAt: new Date() }, filter: { where: { completed: { $eq: true }, createdAt: { $lt: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000) // 30天前 } } } }) console.log('批量更新结果:', result) ``` ### 创建或更新数据 根据查询条件创建或更新记录。 #### 参数说明 | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | **create** | `object` | ✅ 是 | 要新增的数据对象 | | **update** | `object` | ✅ 是 | 要更新的数据对象 | | **filter.where** | `object` | ✅ 是 | 查询条件,确定要更新的记录 | ```javascript const post = { title: "Hello World", body: "Hello World", _id: "foo", }; const { data } = await models.post.upsert({ create: post, update: post, filter: { where: { _id: { $eq: post._id, }, }, }, }); console.log(data); ``` ## 🗑️ 删除数据 ### 单条删除 根据条件删除单条记录。 #### 参数说明 | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | **filter.where** | `object` | ✅ 是 | 查询条件,确定要删除的记录 | #### 代码示例 ```javascript // 删除单条记录 const result = await models.todo.delete({ filter: { where: { _id: { $eq: "todo-id" } } } }) console.log('删除结果:', result) ``` ### 批量删除 根据查询条件批量删除多条记录。 #### 参数说明 | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | **filter.where** | `object` | ✅ 是 | 查询条件,确定要删除的记录 | #### 代码示例 ```javascript // 批量删除已完成的任务 const result = await models.todo.deleteMany({ filter: { where: { completed: { $eq: true }, createdAt: { $lt: new Date(Date.now() - 90 * 24 * 60 * 60 * 1000) // 90天前 } } } }) console.log('批量删除结果:', result) ``` --- ## SDK 类型声明 # SDK 类型声明 ## 接口 ### DataModelMethods\ 模型操作方法接口定义。 #### 类型参数 | 类型参数 | 描述 | | :------- | :--------------- | | `T` | 模型字段的类型。 | #### 属性 ##### create() > **create**: (`params`) => `Promise`\\>\> 创建单条数据的方法。 ###### Example ```ts models..create({ data: { // 模型字段数据 } }).then(({ data }) => { console.log(data.id); // 输出创建的数据ID }); ``` ###### 参数 | 参数 | 类型 | 描述 | | :------------ | :------- | :----------------------- | | `params` | `object` | 包含创建数据的参数对象。 | | `params.data` | `T` | - | | `params.envType`? | `prod` 或 `pre` | 操作正式数据或体验数据 | ###### 返回 `Promise`\\>\> ##### createMany() > **createMany**: (`params`) => `Promise`\\>\> 创建多条数据的方法。 ###### Example ```ts models..createMany({ data: [ // 模型字段数据数组 ] }).then(({ data }) => { console.log(data.idList); // 输出创建的数据ID列表 }); ``` ###### 参数 | 参数 | 类型 | 描述 | | :------------ | :------- | :--------------------------- | | `params` | `object` | 包含创建数据数组的参数对象。 | | `params.data` | `T`[] | - | | `params.envType`? | `prod` 或 `pre` | 操作正式数据或体验数据 | ###### 返回 `Promise`\\>\> ##### delete() > **delete**: (`params`) => `Promise`\\>\> 删除单条数据的方法。 ###### Example ```ts models..delete({ filter: { where: { // 筛选条件,例如根据ID删除特定记录 _id: { $eq: "特定ID值" } } } }).then(({ data }) => { console.log(data.count); // 输出删除的数据条数 }); ``` ###### 参数 | 参数 | 类型 | 描述 | | :-------------- | :--------------------------------------------- | :----------------------- | | `params` | `object` | 包含筛选条件的参数对象。 | | `params.filter` | [`FilterParams`](globals#filterparamst)\ | - | | `params.envType`? | `prod` 或 `pre` | 操作正式数据或体验数据 | ###### 返回 `Promise`\\>\> ##### deleteMany() > **deleteMany**: (`params`) => `Promise`\\>\> 删除多条数据的方法。 ###### Example ```ts models..deleteMany({ filter: { where: { // 筛选条件,例如删除所有满足特定条件的记录 } } }).then(({ data }) => { console.log(data.count); // 输出删除的数据条数 }); ``` ###### 参数 | 参数 | 类型 | 描述 | | :-------------- | :--------------------------------------------- | :----------------------- | | `params` | `object` | 包含筛选条件的参数对象。 | | `params.filter` | [`FilterParams`](globals#filterparamst)\ | - | | `params.envType`? | `prod` 或 `pre` | 操作正式数据或体验数据 | ###### 返回 `Promise`\\>\> ##### get() > **get**: (`params`) => `Promise`\\> 获取单条数据的方法。 ###### Example ```ts models..get({ filter: { where: { // 筛选条件 } }, select: { $master: true // 选择主表所有字段 } }).then(({ data }) => { console.log(data); // 输出查询到的数据 }); ``` ###### 参数 | 参数 | 类型 | 描述 | | :--------------- | :--------------------------------------------- | :--------------------------------- | | `params` | `object` | 包含筛选条件和选择字段的参数对象。 | | `params.filter` | [`FilterParams`](globals#filterparamst)\ | - | | `params.select`? | [`SelectParams`](globals#selectparamst)\ | - | | `params.envType`? | `prod` 或 `pre` | 操作正式数据或体验数据 | ###### 返回 `Promise`\\> ##### list() > **list**: (`params`) => `Promise`\\> 获取多条数据的方法。 ###### Example ```ts models..list({ filter: { where: { // 筛选条件 } }, select: { $master: true // 选择主表所有字段 }, getCount: true, // 开启用来获取总数 pageSize: 10, // 分页大小 pageNumber: 1, // 当前页码 orderBy: [{ createdAt: 'desc' }] // 排序参数 }).then(({ data }) => { console.log(data.records, data.total); // 输出查询到的数据列表和总数 }); ``` ###### 参数 | 参数 | 类型 | 描述 | | :------------------- | :--------------------------------------------- | :------------------------------------------------------------------------------------- | | `params` | `object` | 包含筛选条件、选择字段、分页和排序选项的参数对象。 | | `params.filter`? | [`FilterParams`](globals#filterparamst)\ | 过滤条件 | | `params.getCount`? | `boolean` | 是否获取 filter 命中条件的查询条数 | | `params.orderBy`? | [`OrderByParams`](globals#orderbyparams)[] | 排序参数,当前仅支持最多 3 字段排序 | | `params.pageNumber`? | `number` | 分页数目 | | `params.pageSize`? | `number` | 分页大小,建议指定,如需设置为其它值,需要和 pageNumber 配合使用,两者同时指定才会生效 | | `params.select`? | [`SelectParams`](globals#selectparamst)\ | 可以指定返回本表或者关联表的字段,如果想查询本表所有字段,请使用 { $master: true } | | `params.envType`? | `prod` 或 `pre` | 操作正式数据或体验数据 | ###### 返回 `Promise`\\> ##### update() > **update**: (`params`) => `Promise`\\>\> 更新单条数据的方法。 ###### Example ```ts models..update({ data: { // 更新的数据字段 }, filter: { where: { // 筛选条件 } } }).then(({ data }) => { console.log(data.count); // 输出更新的数据条数 }); ``` ###### 参数 | 参数 | 类型 | 描述 | | :-------------- | :--------------------------------------------- | :--------------------------------- | | `params` | `object` | 包含更新数据和筛选条件的参数对象。 | | `params.data` | `T` | - | | `params.filter` | [`FilterParams`](globals#filterparamst)\ | - | | `params.envType`? | `prod` 或 `pre` | 操作正式数据或体验数据 | ###### 返回 `Promise`\\>\> ##### updateMany() > **updateMany**: (`params`) => `Promise`\\>\> 更新多条数据的方法。 ###### Example ```ts models..updateMany({ data: { // 更新的数据字段 }, filter: { where: { // 筛选条件 } } }).then(({ data }) => { console.log(data.count); // 输出更新的数据条数 }); ``` ###### 参数 | 参数 | 类型 | 描述 | | :-------------- | :--------------------------------------------- | :--------------------------------- | | `params` | `object` | 包含更新数据和筛选条件的参数对象。 | | `params.data` | `T` | - | | `params.filter` | [`FilterParams`](globals#filterparamst)\ | - | | `params.envType`? | `prod` 或 `pre` | 操作正式数据或体验数据 | ###### 返回 `Promise`\\>\> ##### upsert() > **upsert**: (`params`) => `Promise`\\>\> 创建或者更新的方法 ###### Example ```ts models..upsert({ update: { // 更新的数据字段 }, create: { // 创建的数据字段 }, filter: { where: { // 筛选条件 } } }).then(({ data }) => { console.log(data.count); // 输出更新的数据条数 }); ``` ###### 参数 | 参数 | 类型 | 描述 | | :-------------- | :--------------------------------------------- | :--------------------------------------------- | | `params` | `object` | 包含创建或者更新对象以及和筛选条件的参数对象。 | | `params.create` | `T` | - | | `params.filter` | [`FilterParams`](globals#filterparamst)\ | - | | `params.update` | `T` | - | | `params.envType`? | `prod` 或 `pre` | 操作正式数据或体验数据 | ###### 返回 `Promise`\\>\> --- ### Model 基础 Model 类型定义 #### 属性 ##### \_id? > `optional` **\_id**: `string` ##### \_openid? > `optional` **\_openid**: `string` ##### createBy? > `optional` **createBy**: `string` ##### createdAt? > `optional` **createdAt**: `number` ##### owner? > `optional` **owner**: `string` ##### updateBy? > `optional` **updateBy**: `string` ##### updatedAt? > `optional` **updatedAt**: `number` ## 类型别名 ### BasicComparisonOperator > **BasicComparisonOperator**: `"$eq"` \| `"$neq"` \| `"$gt"` \| `"$gte"` \| `"$lt"` \| `"$lte"` \| `"$in"` \| `"$nin"` 基础比较运算符类型定义。 --- ### ComparisonOperator > **ComparisonOperator**: [`BasicComparisonOperator`](globals#basiccomparisonoperator) \| [`SpecialComparisonOperator`](globals#specialcomparisonoperator) 比较运算符类型定义,包括基础和特殊运算符。 #### Example ```ts $eq: 等于; ``` --- ### CreateManyResponse\ > **CreateManyResponse**\: `object` 创建多条记录的响应类型定义。 #### 类型参数 | 类型参数 | 描述 | | :------- | :--------------- | | `T` | 模型字段的类型。 | #### 类型声明 ##### idList > **idList**: `string`[] 创建的记录的 ID 列表。 --- ### CreateResponse\ > **CreateResponse**\: `object` 数据创建方法的返回类型定义。 #### 类型参数 | 类型参数 | 描述 | | :------- | :--------------- | | `T` | 模型字段的类型。 | #### 类型声明 ##### id > **id**: `string` --- ### DeleteManyResponse\ > **DeleteManyResponse**\: [`UpdateResponse`](globals#updateresponset)\ 删除多条记录的响应类型定义,与更新操作的响应类型相同。 #### 类型参数 | 类型参数 | 描述 | | :------- | :--------------- | | `T` | 模型字段的类型。 | --- ### DeleteResponse\ > **DeleteResponse**\: `object` 删除操作的响应类型定义,用于表示删除操作影响的记录数量。 #### 类型参数 | 类型参数 | 描述 | | :------- | :--------------- | | `T` | 模型字段的类型。 | #### 类型声明 ##### count > **count**: `number` 删除操作影响的记录数量。 如果 count 为 0,表示没有记录被删除; 如果 count 大于 0,表示有相应数量的记录被成功删除。 --- ### FilterCondition > **FilterCondition**: `{ [key in ComparisonOperator]?: any }` 复杂查询条件类型定义 #### Example ```ts { * "$eq": "val" * } ``` --- ### FilterConditionItem\ > **FilterConditionItem**\: `{ [key in keyof T]?: FilterCondition }` 过滤参数类型定义。 此类型定义允许对模型字段进行条件过滤,支持复杂的查询操作。 #### Examples 示例 1: 使用`$and`运算符来组合条件,确保所有条件都满足。 ```json { "$and": [ { "key": { "$eq": "val" } } ] } ``` 示例 2: 使用`$and`运算符来组合条件,其中包含`$in`运算符来检查数组包含性。 ```json { "$and": [ { "key1": { "$in": ["foo", "bar"] } }, { "key2": { "$in": [1, 2] } } ] } ``` #### 类型参数 | 类型参数 | 描述 | | :------- | :--------------- | | `T` | 模型字段的类型。 | --- ### FilterObject\ > **FilterObject**\: \{ \[operator in LogicalOperator\]?: FilterConditionItem\\[\] \| FilterObject\ \} 定义过滤参数的类型。 #### Examples ```ts { "$and": [ { "title": { "$eq": "hello" } } ] } ``` ```ts { "$or": [ { "$and": [ { "title": { "$eq": "hello" } }, { "body": { "$neq": "world" } } ] }, { "createdBy": { "$eq": "xxx" } } ] } ``` #### 类型参数 | 类型参数 | 描述 | | :------- | :----------------------------------------------------------------------------- | | `T` | 表示模型字段的类型。此类型定义允许使用复杂的查询条件来过滤数据。 | --- ### FilterParams\ > **FilterParams**\: `object` 定义过滤参数的类型。 #### Example ```ts { relateWhere: { comments: { where: { comment: { $nempty: true, }, }, }, }, where: {}, } ``` #### 类型参数 | 类型参数 | 描述 | | :------- | :------------------- | | `T` | 表示模型字段的类型。 | #### 类型声明 ##### relateWhere? > `optional` **relateWhere**: `{ [K in RelationKeys]?: Object }` 关联关系查询 ##### where? > `optional` **where**: [`FilterConditionItem`](globals#filterconditionitemt)\ \| [`FilterObject`](globals#filterobjectt)\ 基础查询 --- ### ListParams\ > **ListParams**\: `object` list 方法参数定义。 #### 类型参数 | 类型参数 | 描述 | | :------- | :--------------- | | `T` | 模型字段的类型。 | #### 类型声明 ##### filter? > `optional` **filter**: [`FilterParams`](globals#filterparamst)\ ##### getCount? > `optional` **getCount**: `boolean` ##### orderBy? > `optional` **orderBy**: [`OrderByParams`](globals#orderbyparams)[] ##### pageNumber? > `optional` **pageNumber**: `number` ##### pageSize? > `optional` **pageSize**: `number` ##### relateWhere? > `optional` **relateWhere**: `any` ##### select? > `optional` **select**: [`SelectParams`](globals#selectparamst)\ \| `object` --- ### ListResponse\ > **ListResponse**\: [`MethodResponse`](globals#methodresponset)\ 数据列表方法的返回类型定义。 #### 类型声明 ##### records > **records**: `T`[] ##### total? > `optional` **total**: `number` #### 类型参数 | 类型参数 | 描述 | | :------- | :--------------- | | `T` | 模型字段的类型。 | --- ### LogicalOperator > **LogicalOperator**: `"$and"` \| `"$or"` 逻辑运算符类型定义。 --- ### MethodResponse\ > **MethodResponse**\: `object` 模型操作方法的返回类型定义。 #### 类型参数 | 类型参数 | 描述 | | :------- | :--------------- | | `T` | 返回数据的类型。 | #### 类型声明 ##### data > **data**: `T` 返回的数据。 ##### requestId? > `optional` **requestId**: `string` 请求的唯一标识符。 --- ### OrderByParams > **OrderByParams**: `object` 排序参数结构定义。 #### Example ```ts { "createdAt": "asc", } ``` #### 索引签名 \[`key`: `string`\]: `"asc"` \| `"desc"` --- ### RelationField\ > **RelationField**\: `T` _extends_ `object` ? `U` : `never` #### 类型参数 | 类型参数 | | :------- | | `T` | --- ### SelectParams\ > **SelectParams**\: \{ \[K in keyof T\]?: T\[K\] extends (infer U)\[\] \| undefined ? SelectParams\ \| boolean : T\[K\] extends object \| undefined ? SelectParams\ \| boolean : boolean \} & `object` 选择参数结构定义,用于指定查询时返回的字段。 #### Examples ```ts { "key1": true, } ``` ```ts { $master: true, } ``` ```ts { $master: true, comments: { comment: true, } } ``` #### 类型声明 ##### $master? > `optional` **$master**: `boolean` #### 类型参数 | 类型参数 | 描述 | | :------- | :--------------- | | `T` | 模型字段的类型。 | --- ### SpecialComparisonOperator > **SpecialComparisonOperator**: `"$search"` \| `"$nsearch"` \| `"$empty"` \| `"$nempty"` 特殊比较运算符类型定义 --- ### UpdateResponse\ > **UpdateResponse**\: `object` 更新操作的响应类型定义。 #### 类型参数 | 类型参数 | 描述 | | :------- | :--------------- | | `T` | 模型字段的类型。 | #### 类型声明 ##### count > **count**: `number` 更新操作影响的记录数量。 --- ### UpsertResponse\ > **UpsertResponse**\: `object` 创建或者更新的响应类型定义。 #### 类型参数 | 类型参数 | 描述 | | :------- | :--------------- | | `T` | 模型字段的类型。 | #### 类型声明 ##### count > **count**: `number` 变更的条数,返回非 0 值代表更新成功 ##### id > **id**: `string` 变更的条数,返回非 "" 值代表创建成功 ### OrmRawQueryClient 运行原生 SQL 的 ORM 客户端接口 #### 属性 ##### $runSQL()? 此方法仅支持服务端调用 > `optional` **$runSQL**: (`sql`, `params`?, `config`?) => `Promise`\\> ###### 参数 | 参数 | 类型 | 描述 | | :-------- | :--------------------------------------------- | :----------- | | `sql` | `string` | sql 语句 | | `params`? | `Record`\ | sql 模版变量 | | `config`? | [`SQLCommandParams`](globals#sqlcommandparams) | 配置 | ###### 返回 `Promise`\\> ##### $runSQLRaw()? 此方法仅支持服务端调用 > `optional` **$runSQLRaw**: (`sql`, `config`?) => `Promise`\\> ###### 参数 | 参数 | 类型 | 描述 | | :-------- | :--------------------------------------------- | :------- | | `sql` | `string` | sql 语句 | | `config`? | [`SQLCommandParams`](globals#sqlcommandparams) | 配置 | ###### 返回 `Promise`\\> --- ### SQLCommandParams #### 属性 ##### timeout? > `optional` **timeout**: `number` 超时时间,默认是 5s,最大不超过 **15s** > `optional` **dbLinkName**: `string` 数据连接器英文标识,默认值是数据库MySQL标识。使用自有MySQL时,需要变更。 --- ## 增删改查 # 增删改查 ## 🔧 SDK 初始化 请参考 [SDK 初始化](/database/sdk-init) 文档进行初始化配置。初始化后拿到对应的模型实例 `models` ,即可开始进行数据操作。 具体查询参数参考 [查询参数详解](/model/select) 文档。 > 本文适用于 `Web SDK` 、 `Node.js SDK` ,其余 SDK 请参考 [对应SDK文档链接](/database/sdk-init) ## 🔍 查询数据 ### 单条查询 通过指定条件查询单条记录。 #### 参数说明 | 参数 | 类型 | 必填 | 说明 | |------|------|---|------| | **filter.where** | `object` | ❌ 否 | 查询条件 | | **select** | `object` | ✅ 是 | 指定返回字段 | #### 代码示例 ```javascript // 根据 ID 查询单条记录 const todo = await models.todo.get({ filter: { where: { _id: { $eq: "todo-id-123" } } } }) console.log('查询结果:', todo.data) ``` #### 返回结果 ```javascript { data: { records: [{ _id: "todo-id-123", title: "服务端任务", completed: false, // ... 其他字段 }], total: 1 } } ``` ### 多条查询 查询多条记录,支持条件筛选、排序、分页等。具体参数说明请参考 [查询参数详解](/model/select) 文档。 #### 参数说明 | 参数 | 类型 | 必填 | 说明 | |------|------|--|------| | **filter.where** | `object` | ❌ 否 | 查询条件 | | **select** | `object` | ✅ 是 | 指定返回字段 | #### 代码示例 ```javascript // 基础查询 const todos = await models.todo.list({ filter: { where: { completed: { $eq: false } }, orderBy: [{ field: "priority", direction: "desc" }, { field: "createdAt", direction: "asc" } ] } }) console.log('查询结果:', todos.data) ``` #### 返回结果 ```javascript { data: { records: [{ _id: "todo-id-1", title: "任务1", completed: false }, { _id: "todo-id-2", title: "任务2", completed: true } ], total: 2 } } ``` ## ➕ 新增数据 ### 单条新增 向数据模型中添加一条新记录。 #### 参数说明 | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | **data** | `object` | ✅ 是 | 要新增的数据对象 | #### 代码示例 ```javascript // 创建单条记录 const todo = await models.todo.create({ data: { title: "服务端任务", description: "使用 node-sdk 创建的任务", priority: "high", completed: false, createdAt: new Date(), createdBy: "system", metadata: { source: "api", version: "1.0" } } }) console.log('创建成功:', todo) ``` ### 批量新增 一次性向数据模型中添加多条记录。 > 暂不支持批量新增关联关系字段 #### 参数说明 | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | **data** | `array` | ✅ 是 | 包含多个数据对象的数组 | #### 代码示例 ```javascript // 批量创建多条记录 const todos = await models.todo.createMany({ data: [{ title: "批量任务1", priority: "high" }, { title: "批量任务2", priority: "medium" }, { title: "批量任务3", priority: "low" } ] }) console.log('批量创建成功:', todos) ``` ## 📝 更新数据 ### 单条更新 根据条件更新单条记录。 #### 参数说明 | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | **data** | `object` | ✅ 是 | 要更新的数据对象 | | **filter.where** | `object` | ✅ 是 | 查询条件,确定要更新的记录 | #### 代码示例 ```javascript // 更新单条记录 const result = await models.todo.update({ data: { title: "更新后的任务", completed: true, updatedAt: new Date(), updatedBy: "admin" }, filter: { where: { _id: { $eq: "todo-id" // 推荐使用 _id 进行精确操作 } } } }) console.log('更新结果:', result) ``` ### 批量更新 根据查询条件批量更新多条记录。 > 暂不支持批量更新关联关系字段 #### 参数说明 | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | **data** | `object` | ✅ 是 | 要更新的数据对象 | | **filter.where** | `object` | ✅ 是 | 查询条件,确定要更新的记录 | #### 代码示例 ```javascript // 批量更新多条记录 const result = await models.todo.updateMany({ data: { status: "archived", archivedAt: new Date() }, filter: { where: { completed: { $eq: true }, createdAt: { $lt: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000) // 30天前 } } } }) console.log('批量更新结果:', result) ``` ### 创建或更新数据 根据查询条件创建或更新记录。 > 暂不支持批量新增更新关联关系字段 #### 参数说明 | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | **create** | `object` | ✅ 是 | 要新增的数据对象 | | **update** | `object` | ✅ 是 | 要更新的数据对象 | | **filter.where** | `object` | ✅ 是 | 查询条件,确定要更新的记录 | ```javascript const post = { title: "Hello World", body: "Hello World", _id: "foo", }; const { data } = await models.post.upsert({ create: post, update: post, filter: { where: { _id: { $eq: post._id, }, }, }, }); console.log(data); ``` ## 🗑️ 删除数据 ### 单条删除 根据条件删除单条记录。 #### 参数说明 | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | **filter.where** | `object` | ✅ 是 | 查询条件,确定要删除的记录 | #### 代码示例 ```javascript // 删除单条记录 const result = await models.todo.delete({ filter: { where: { _id: { $eq: "todo-id" } } } }) console.log('删除结果:', result) ``` ### 批量删除 根据查询条件批量删除多条记录。 #### 参数说明 | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | **filter.where** | `object` | ✅ 是 | 查询条件,确定要删除的记录 | #### 代码示例 ```javascript // 批量删除已完成的任务 const result = await models.todo.deleteMany({ filter: { where: { completed: { $eq: true }, createdAt: { $lt: new Date(Date.now() - 90 * 24 * 60 * 60 * 1000) // 90天前 } } } }) console.log('批量删除结果:', result) ``` --- ## 查询参数详解 # 查询参数详解 云开发数据模型提供了强大的查询功能,支持复杂的查询条件、字段选择、排序、分页和关联查询。本文将详细介绍数据模型查询操作的各种参数和使用方法。 > 本文适用于 `Web SDK` 、 `Node.js SDK` ,其余 SDK 请参考 [对应SDK文档链接](/database/sdk-init) ## 查询参数概览 数据模型的查询操作主要包含以下参数: | 参数 | 类型 | 说明 | 必填 | |------|------|------|------| | `envType` | `pre` \| `prod` | 指定查询的数据环境,不传为正式数据 `pre` :体验数据, `prod` :正式数据 | 否 | | `select` | `SelectParams` | 指定返回的字段 | 否 | | `filter` | `FilterParams` | 查询过滤条件 | 否 | | `orderBy` | `OrderByParams[]` | 排序条件 | 否 | | `pageSize` | `number` | 分页大小, 最大200,默认为10 | 否 | | `pageNumber` | `number` | 页码 | 否 | | `getCount` | `boolean` | 是否返回总数 | 否 | ## 指定数据环境 `envType` `envType` 参数用于指定查询的数据环境,默认为正式数据, `pre` :体验数据, `prod` :正式数据。 ```javascript const { data } = await models.post.list({ envType: 'pre', filter: { where: {}, }, select: { $master: true, }, }); ``` ## 字段选择 `select` `select` 参数用于指定查询结果中应包含的字段,支持主模型字段和关联模型字段的精确控制。 > ✅ 建议仅选择需要的字段和关系来减少响应数据的大小并提高查询速度。 ### 返回主模型所有字段 使用 `$master: true` 可以返回主模型的所有字段: ```javascript const { data } = await models.post.get({ select: { $master: true, // 查询主模型所有的字段 }, filter: { where: { _id: { $eq: _id, // 推荐传入_id数据标识进行操作 }, }, }, }); console.log(data); // { // "owner": "Anonymous(95fblM7nvPi01yQmYxBvBg)", // "createdAt": 1717488585078, // "createBy": "Anonymous(95fblM7nvPi01yQmYxBvBg)", // "updateBy": "Anonymous(95fblM7nvPi01yQmYxBvBg)", // "_openid": "95fblM7nvPi01yQmYxBvBg", // "_id": "e2764d2d665ecbc9024b058f1d6b33a4", // "title": "你好,世界👋", // "body": "文章内容...", // "slug": "hello-world", // "updatedAt": 1717490751944 // } ``` ### 返回指定字段 通过指定字段名为 `true` 来选择特定字段: ```javascript const { data } = await models.post.list({ select: { _id: true, title: true, updatedAt: true, }, filter: { where: {}, }, getCount: true, }); console.log(data); // { // "records": [ // { // "_id": "e2764d2d665ecbc9024b058f1d6b33a4", // "title": "你好,世界👋", // "updatedAt": 1717492882289 // } // // ... 更多记录 // ], // "total": 51 // } ``` ### 返回关联模型字段 可以同时查询关联模型的字段: ```javascript const { data } = await models.post.list({ select: { _id: true, title: true, updatedAt: true, // 关联查询评论数据 comments: { _id: true, createdAt: true, comment: true, }, // 也可以直接传 true 返回评论中所有的字段 }, filter: { where: {}, }, getCount: true, }); console.log(data); // { // "records": [ // { // "_id": "9FSAHWM9VV", // "title": "Bonjour le Monde👋", // "updatedAt": 1718096503886, // "comments": [ // { // "_id": "9FSAJF3GLG", // "createdAt": 1718096509916, // "comment": "这是一条评论" // } // ] // } // // ... 更多记录 // ], // "total": 2 // } ``` ## 查询过滤 `filter` `filter` 参数用于指定查询条件,支持基础查询和关联查询两种方式。 ### 基础查询 `where` 基础查询用于对主模型字段进行过滤: ```javascript const { data } = await models.post.list({ filter: { where: { // 标题包含"世界" title: { $search: "世界", }, // 正文不为空 body: { $nempty: true, }, }, }, select: { $master: true, }, }); ``` ### 关联查询 `relateWhere` 关联查询用于根据关联模型的条件进行过滤: ```javascript const { data } = await models.post.list({ filter: { // 查询有评论的文章 relateWhere: { comments: { where: { comment: { $nempty: true, // 评论内容不为空 }, }, }, }, where: {}, // 主模型查询条件 }, select: { $master: true, comments: { comment: true, }, }, }); ``` ### 组合查询示例 需要用到与或关系时,可以使用 `where` 参数的 `$and` 和 `$or` 操作符 如果用到了 `$and` 和 `$or` 操作符,需要将它们放在一个数组中: ```javascript const { data } = await models.post.list({ filter: { where: { $and: [{ // 标题包含"技术"或"教程" $or: [{ title: { $search: "技术" } }, { title: { $search: "教程" } } ] }, { // 创建时间在最近30天内 createdAt: { $gte: Date.now() - 30 * 24 * 60 * 60 * 1000 } }, { // 状态为已发布 status: { $eq: "published" } } ] }, }, select: { _id: true, title: true, createdAt: true, status: true, }, }); ``` ### 查询运算符 | 操作符 | 说明 | 示例 | |--------|------|------| | **$eq** | 等于 | `{status: {$eq: "active"}}` | | **$neq** | 不等于 | `{status: {$neq: "deleted"}}` | | **$ne** | 同$neq,兼容语法 | `{status: {$ne: "deleted"}}` | | **$gt** | 大于 | `{score: {$gt: 80}}` | | **$gte** | 大于等于 | `{age: {$gte: 18}}` | | **$lt** | 小于 | `{price: {$lt: 100}}` | | **$lte** | 小于等于 | `{discount: {$lte: 0.5}}` | | **$in** | 在数组中 | `{category: {$in: ["tech", "news"]}}` | | **$nin** | 不在数组中 | `{status: {$nin: ["deleted", "banned"]}}` | | **$and** | 逻辑与 | `{$and: [{age: {$gte: 18}}, {status: {$eq: "active"}}]}` | | **$or** | 逻辑或 | `{$or: [{priority: {$eq: "high"}}, {urgent: {$eq: true}}]}` | | **$search** | 模糊查询, 大小写敏感 | `{status: {$search: "active"}}` | | **$search_ci** | 模糊查询, 大小写不敏感 | `{status: {$search_ci: "active"}}` | | **$nsearch** | 查找不包含指定字符串值的记录, 大小写敏感 | `{status: {$nsearch: "active"}}` | | **$nsearch_ci** | 查找不包含指定字符串值的记录, 大小写不敏感 | `{status: {$nsearch_ci: "active"}}` | | **$empty** | 数据为 null | `{status: {$empty: true}}` | | **$nempty** | 数据不为 null | `{status: {$nempty: true}}` | ## 排序 `orderBy` `orderBy` 参数用于指定查询结果的排序方式,支持多字段排序(最多3个字段)。 ### 单字段排序 ```javascript const { data } = await models.post.list({ filter: { where: {}, }, orderBy: [{ createdAt: "desc", // 按创建时间倒序 }, ], select: { $master: true, }, }); ``` ### 多字段排序 ```javascript const { data } = await models.post.list({ filter: { where: {}, }, orderBy: [{ featured: "desc", // 首先按推荐状态倒序 }, { createdAt: "desc", // 然后按创建时间倒序 }, { title: "asc", // 最后按标题升序 }, ], select: { $master: true, }, }); ``` 排序方向: * `"asc"`: 升序排列 * `"desc"`: 降序排列 ## 分页参数 ### `pageSize` 和 `pageNumber` 用于实现分页查询: ```javascript const { data } = await models.post.list({ filter: { where: {}, }, pageSize: 10, // 每页10条记录 pageNumber: 2, // 第2页(从1开始) getCount: true, // 获取总数用于计算总页数 select: { $master: true, }, }); console.log(data); // { // "records": [...], // 第2页的10条记录 // "total": 156 // 总记录数 // } // 计算总页数 const totalPages = Math.ceil(data.total / 10); ``` ### `getCount` 控制是否返回满足条件的记录总数: ```javascript const { data } = await models.post.list({ filter: { where: { status: { $eq: "published" } }, }, getCount: true, // 设置为 true 时返回 total 字段 select: { _id: true, title: true, }, }); console.log(data.total); // 满足条件的总记录数 ``` ## 完整查询示例 以下是一个包含所有参数的完整查询示例: ```javascript const { data } = await models.post.list({ // 字段选择 select: { _id: true, title: true, excerpt: true, createdAt: true, updatedAt: true, author: { _id: true, name: true, avatar: true, }, comments: { _id: true, content: true, createdAt: true, }, }, // 查询条件 filter: { where: { $and: [{ status: { $eq: "published" } }, { $or: [{ title: { $search: "技术" } }, { tags: { $in: ["前端", "后端"] } } ] }, { createdAt: { $gte: Date.now() - 7 * 24 * 60 * 60 * 1000 // 最近7天 } } ] }, relateWhere: { comments: { where: { status: { $eq: "approved" } // 只查询已审核的评论 } } } }, // 排序 orderBy: [{ featured: "desc" }, { createdAt: "desc" } ], // 分页 pageSize: 20, pageNumber: 1, getCount: true, }); console.log("查询结果:", data.records); console.log("总记录数:", data.total); console.log("总页数:", Math.ceil(data.total / 20)); ``` ## 关联查询详解 ### 按关联关系过滤 使用 `relateWhere` 可以根据关联模型的条件来过滤主模型: ```javascript // 查询有特定评论的文章 const { data } = await models.post.list({ filter: { relateWhere: { // 文章必须有评论 comments: { where: { $and: [{ content: { $nempty: true } }, // 评论内容不为空 { status: { $eq: "approved" } }, // 评论已审核 { rating: { $gte: 4 } } // 评论评分>=4 ] } }, // 文章必须有标签 tags: { where: { name: { $in: ["技术", "教程", "分享"] } } } }, where: { status: { $eq: "published" } } }, select: { $master: true, comments: { content: true, rating: true, status: true, }, tags: { name: true, } } }); ``` ### 关联查询性能优化 1. **精确选择字段**:只选择需要的关联字段 2. **合理使用关联过滤**:避免过于复杂的关联条件 3. **分页处理**:对于大量关联数据使用分页 ```javascript // 优化示例:只获取必要的关联数据 const { data } = await models.post.list({ filter: { where: { status: { $eq: "published" } } }, select: { _id: true, title: true, excerpt: true, // 只获取作者的基本信息 author: { _id: true, name: true, }, // 只获取最新的3条评论 comments: { _id: true, content: true, createdAt: true, } }, orderBy: [{ createdAt: "desc" }], pageSize: 10, pageNumber: 1, }); ``` ## 最佳实践 ### 1. 字段选择优化 ```javascript // ❌ 不推荐:查询所有字段 const { data } = await models.post.list({ select: { $master: true }, filter: { where: {} } }); // ✅ 推荐:只选择需要的字段 const { data } = await models.post.list({ select: { _id: true, title: true, excerpt: true, createdAt: true, }, filter: { where: {} } }); ``` ### 2. 查询条件优化 ```javascript // ✅ 推荐:使用索引字段进行查询 const { data } = await models.post.list({ filter: { where: { _id: { $eq: "specific-id" }, // 主键查询,性能最佳 status: { $eq: "published" }, // 索引字段 createdAt: { $gte: timestamp } // 时间范围查询 } } }); // ⚠️ 注意:模糊查询性能较差,谨慎使用 const { data } = await models.post.list({ filter: { where: { title: { $search: "关键词" } // 模糊查询,建议配合其他条件 } } }); ``` ### 3. 分页处理 ```javascript // ✅ 推荐:合理的分页大小 const pageSize = 20; // 建议10-50之间 const pageNumber = 1; const { data } = await models.post.list({ filter: { where: {} }, pageSize, pageNumber, getCount: true, // 获取总数用于分页计算 select: { _id: true, title: true, createdAt: true, } }); // 计算分页信息 const totalPages = Math.ceil(data.total / pageSize); const hasNextPage = pageNumber 1; ``` ### 4. 错误处理 ```javascript try { const { data } = await models.post.list({ filter: { where: { status: { $eq: "published" } } }, select: { _id: true, title: true, }, pageSize: 10, pageNumber: 1, getCount: true, }); console.log("查询成功:", data); } catch (error) { console.error("查询失败:", error); // 处理错误情况 } ``` 通过合理使用这些查询参数,可以实现高效、灵活的数据查询操作,满足各种复杂的业务需求。 --- ## 同步模型定义 # 同步模型定义 为了提高开发者的代码编写体验,可以将用户的云端数据模型同步为本地的类型定义文件,享受代码编辑器的智能类型提示和检查功能。同步后效果如下: 数据模型智能提示 ![](https://qcloudimg.tencent-cloud.cn/raw/ba70dda1d42a9c8b9850f995ff415232.png) 字段智能提示 ![](https://qcloudimg.tencent-cloud.cn/raw/0f42f0a02f707d107a0c6e4230f8cf3c.png) ## 同步流程 选择以下任一方式同步数据模型定义: > 注意: > > 1. 对于微信小程序,需要在 `app.json` 文件同目录下运行命令 > 2. 对于微信云开发的云函数,需要在 `cloudfunctions/` 目录下运行命令 > 3. 首次运行需要指定环境 ID 参数 `--envId=`,以后就不需再指定 > 4. 运行 tcb 需要登录,使用微信云开发的,请在登录时选择【小程序公众号】的登录方式 > ### 方式一:以 npx 直接运行 tcb 命令 > 此方式仅适用于本地未安装 `tcb` 的情况。如果本地已安装 `tcb`,请使用[【方式二】](#方式二安装-tcb-命令行工具) 进入项目目录中(目录位置参考注意事项),然后执行以下命令 ```shell npx --package=@cloudbase/cli tcb sync-model-dts --envId= ``` ### 方式二:安装 tcb 命令行工具 > 如果本地未安装 `tcb` 或已安装的 `tcb` 版本 ``` ## 常见问题与解决 ### 问题:代码编辑器无模型提示 1. 确保 `@cloudbase/wx-cloud-client-sdk` 模块已正确安装。 2. 确保 `tsconfig.json` 文件配置正确: ```json { "compilerOptions": { "allowJs": true } } ``` --- ## 用 CloudBase AI CLI 开发邻里闲置物品循环利用小程序 # 用 CloudBase AI CLI 开发邻里闲置物品循环利用小程序 > 本文将通过一个邻里闲置物品循环利用小程序的示例项目,详细介绍如何使用 CloudBase AI CLI 进行全栈开发。从环境准备到最终部署,手把手教你如何用 AI 编程工具快速构建一个完整的微信小程序。 ## 🎯 项目背景 在快节奏的现代生活中,我们经常会有一些闲置物品:看过的书籍、换季的衣服、升级后的数码产品...这些物品往往被遗忘在角落,既占空间又浪费资源。同时,我们也会需要一些物品,却不想花大价钱购买新的。 基于这个痛点,我们设计了一个**邻里闲置物品循环利用平台**的示例项目,展示如何让社区内的闲置物品能够重新焕发生命,既环保又经济,还能增进邻里关系。 ```mermaid graph LR A[闲置物品] --> B[循环利用平台] B --> C[环保价值] B --> D[经济价值] B --> E[社交价值] F[用户A] --> B G[用户B] --> B style A fill:#e8f5e8 style B fill:#fff3e0 style C fill:#e3f2fd style D fill:#e3f2fd style E fill:#e3f2fd ``` ## 🏗️ 技术架构设计 ### 整体架构 ```mermaid graph TB subgraph "前端层" A[微信小程序] B[WXML + WXSS] C[JavaScript ES6+] end subgraph "云开发层" D[云函数] E[数据库] F[云存储] end subgraph "AI 开发工具" G[CloudBase AI CLI] H[Claude Code/Kimi K2] end A --> D D --> E A --> F G --> A G --> D G --> E G --> F style G fill:#fff3e0 style H fill:#fff3e0 ``` ### 核心功能模块 ```mermaid graph LR A[首页浏览] --> B[物品展示] A --> C[搜索筛选] A --> D[分类排序] E[物品详情] --> F[图片轮播] E --> G[信息展示] E --> H[联系方式] I[物品发布] --> J[图片上传] I --> K[信息填写] I --> L[位置选择] M[用户中心] --> N[个人信息] M --> O[我的发布] M --> P[我的收藏] style A fill:#e3f2fd style E fill:#e3f2fd style I fill:#e3f2fd style M fill:#e3f2fd ``` ## 🚀 开发环境准备 ### 1. 准备基础环境 首先,我们需要准备开发环境: **下载微信开发者工具** - 访问 [微信开发者工具官网](https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html) - 下载适合你操作系统的版本 - 安装并登录微信开发者账号 **注册小程序** - 访问 [微信公众平台](https://mp.weixin.qq.com/) - 注册小程序账号(个人或企业) - 获取 AppID(开发时需要使用) ### 2. 安装 CloudBase AI CLI CloudBase AI CLI 是腾讯云开发推出的统一 AI 编程工具管理平台,支持多种 AI 模型,让我们能够用自然语言进行全栈开发。 **一键安装(推荐)** ```bash # Mac/Linux/Windows 的 WSL curl https://static.cloudbase.net/cli/install/install.sh -fsS | bash # Windows PowerShell irm https://static.cloudbase.net/cli/install/install.ps1 | iex ``` **npm 安装(备选)** ```bash npm install -g @cloudbase/cli ``` 安装完成后,验证安装: ```bash tcb --version ``` ### 3. 登录云开发环境 ```bash tcb login ``` 按照提示完成微信扫码登录,选择或创建云开发环境。 ## 🎨 项目开发实践 ### 第一步:创建项目 1. **创建项目目录** ```bash mkdir neighborhood-recycling cd neighborhood-recycling ``` 2. **启动 AI 助手** ```bash tcb ai ``` 3. **选择 AI 模型和模板** 在 AI 对话中,我们选择: - AI 模型:Claude Code(或 Kimi K2) - 项目模板:小程序云开发模板 4. **描述项目需求** ``` 请帮我创建一个邻里闲置物品循环利用的微信小程序示例,包含以下功能: 1. 首页:物品浏览、搜索、分类筛选、排序 2. 物品详情:图片轮播、详细信息、联系方式、收藏 3. 物品发布:多图上传、信息填写、位置选择 4. 用户中心:个人信息、我的发布、我的收藏 技术栈:微信小程序 + 云开发(云函数、数据库、云存储) 设计风格:简洁现代,绿色环保主题 ``` ### 第二步:项目结构生成 AI 会根据需求自动生成项目结构 ### 第三步:数据库设计 AI 会帮我们设计示例项目的数据库结构: ```javascript // items 集合结构 { _id: "自动生成的ID", title: "物品标题", description: "物品描述", category: "物品分类", // 数码、图书、服装、家居、运动、其他 price: 0, // 价格(0表示免费) images: ["图片URL数组"], contactWechat: "微信号", contactPhone: "手机号", location: { latitude: "纬度", longitude: "经度", address: "地址" }, status: "available", // available, sold, removed openid: "用户openid", createTime: "创建时间戳", updateTime: "更新时间戳", views: "浏览量", favorites: "收藏数" } ``` ### 第四步:云函数开发 AI 会自动生成示例项目的云函数代码: **itemManager 云函数**(物品管理) ```javascript // 处理物品的增删改查、搜索等功能 const cloud = require('wx-server-sdk') cloud.init() exports.main = async (event, context) => { const db = cloud.database() const { action, data } = event switch(action) { case 'create': return await createItem(db, data) case 'query': return await queryItems(db, data) case 'update': return await updateItem(db, data) case 'delete': return await deleteItem(db, data) default: return { error: 'Unknown action' } } } ``` **getOpenId 云函数**(用户身份获取) ```javascript const cloud = require('wx-server-sdk') cloud.init() exports.main = async (event, context) => { const wxContext = cloud.getWXContext() return { openid: wxContext.OPENID, appid: wxContext.APPID, unionid: wxContext.UNIONID, } } ``` ### 第五步:前端页面开发 AI 会生成示例项目的完整前端代码,包括: **首页(index)** - 响应式物品网格布局 - 实时搜索功能 - 分类筛选和排序 - 下拉刷新和上拉加载 **物品详情页(detail)** - 图片轮播展示 - 详细物品信息 - 收藏功能 - 联系方式展示 **发布页(publish)** - 多图片上传 - 完整的表单验证 - 位置选择 - 智能分类 **用户中心(profile)** - 用户信息管理 - 个人统计数据 - 我的发布管理 - 我的收藏 ### 第六步:在微信开发者工具中开发 1. **打开项目** ```bash # 在项目目录中运行 tcb ai -- "使用微信开发者工具打开当前项目" ``` 2. **配置项目** - 在微信开发者工具中导入项目 - 配置 AppID - 开启云开发功能 3. **实时开发** 在微信开发者工具的终端中,你可以继续使用 AI 助手: ```bash tcb ai ``` 这样你就可以边开发边预览,AI 会实时帮你优化代码和解决问题。 ## 🔧 核心功能实现 ### 1. 首页物品展示 ```mermaid sequenceDiagram participant U as 用户 participant P as 首页 participant C as 云函数 participant D as 数据库 U->>P: 打开首页 P->>C: 请求物品列表 C->>D: 查询物品数据 D->>C: 返回数据 C->>P: 返回物品列表 P->>U: 展示物品网格 ``` **关键代码实现:** ```javascript // pages/index/index.js Page({ data: { items: [], loading: false, hasMore: true }, onLoad() { this.loadItems() }, async loadItems() { this.setData({ loading: true }) try { const result = await wx.cloud.callFunction({ name: 'itemManager', data: { action: 'query', data: { status: 'available' } } }) this.setData({ items: result.result.data, loading: false }) } catch (error) { console.error('加载失败:', error) } } }) ``` ### 2. 图片上传功能 ```mermaid graph LR A[选择图片] --> B[压缩处理] B --> C[上传到云存储] C --> D[获取文件ID] D --> E[保存到数据库] style A fill:#e3f2fd style C fill:#fff3e0 style E fill:#e8f5e8 ``` **实现代码:** ```javascript async uploadImages(tempFilePaths) { const uploadTasks = tempFilePaths.map(filePath => { return wx.cloud.uploadFile({ cloudPath: `items/${Date.now()}-${Math.random().toString(36).substr(2, 9)}.jpg`, filePath: filePath }) }) const uploadResults = await Promise.all(uploadTasks) return uploadResults.map(result => result.fileID) } ``` ### 3. 搜索和筛选 ```mermaid graph TD A[用户输入] --> B[防抖处理] B --> C[构建查询条件] C --> D[调用云函数] D --> E[数据库查询] E --> F[返回结果] F --> G[更新界面] style A fill:#e3f2fd style B fill:#fff3e0 style E fill:#e8f5e8 ``` ## 🎨 设计亮点 ### 视觉设计 我们采用了绿色环保主题,体现循环利用的环保理念: ```css /* 主题色彩 */ :root { --primary-color: #4CAF50; /* 主色调:环保绿 */ --secondary-color: #81C784; /* 辅助色:浅绿 */ --accent-color: #FF9800; /* 强调色:橙色 */ --text-color: #333333; /* 文字色:深灰 */ --bg-color: #F5F5F5; /* 背景色:浅灰 */ } ``` ### 用户体验优化 1. **响应式设计**:适配不同屏幕尺寸 2. **加载状态**:提供友好的加载反馈 3. **错误处理**:优雅的错误提示 4. **操作反馈**:即时的操作结果反馈 ## 🚀 部署和发布 ### 1. 云函数部署 ```bash # 在项目根目录执行 tcb ai -- -p "部署所有云函数到云开发环境" ``` ### 2. 数据库初始化 ```bash tcb ai -- -p "创建数据库集合和索引" ``` ### 3. 小程序预览 1. 在微信开发者工具中点击"预览" 2. 使用微信扫码在手机上预览 3. 测试各项功能是否正常 ### 4. 提交审核 1. 完善小程序信息 2. 上传小程序图标和截图 3. 填写功能介绍 4. 提交审核 ## 📊 项目成果 通过 CloudBase AI CLI 的开发,我们成功构建了一个功能完整的邻里闲置物品循环利用小程序示例: ### 技术成果 - ✅ 完整的微信小程序应用 - ✅ 云函数后端服务 - ✅ 数据库数据存储 - ✅ 云存储文件管理 - ✅ 响应式用户界面 ### 业务价值 - 🌱 **环保价值**:促进资源循环利用 - 🤝 **社交价值**:增强邻里互动 - 💰 **经济价值**:帮助用户节省开支 - 🏠 **社区价值**:建设和谐社区环境 ## 🎯 开发经验总结 ### CloudBase AI CLI 的优势 1. **统一管理**:一个命令管理多种 AI 编程工具 2. **多模型支持**:支持 Claude Code、Kimi K2 等多种模型 3. **云开发集成**:深度集成腾讯云开发平台 4. **快速开发**:大幅减少编码时间,提升开发效率 ### 最佳实践 1. **需求明确**:在开始前明确功能需求和技术要求 2. **渐进开发**:先实现核心功能,再逐步完善 3. **实时测试**:边开发边测试,及时发现问题 4. **文档记录**:记录开发过程和关键决策 ## 🔗 相关资源 - [CloudBase AI CLI 官方文档](https://docs.cloudbase.net/cli-v1/ai/introduce) - [CloudBase AI Toolkit GitHub](https://github.com/TencentCloudBase/CloudBase-AI-ToolKit) - [微信小程序开发文档](https://developers.weixin.qq.com/miniprogram/dev/framework/) - [微信云开发文档](https://developers.weixin.qq.com/miniprogram/dev/wxcloud/basis/getting-started.html) ## 🎉 结语 通过 CloudBase AI CLI,我们成功地将一个复杂的全栈小程序示例项目从概念转化为现实。这不仅展示了 AI 编程工具的强大能力,也证明了云开发平台在快速应用开发中的价值。 未来,随着 AI 技术的不断发展,我们相信会有更多开发者通过类似的方式,快速构建出有价值的产品,推动技术的普及和应用。 --- ## 内容审核 # 内容审核 ## 操作场景 本文介绍云开发内容审核的使用场景,并演示如何使用内容审核功能。 ##内容审核介绍 ### 一、什么是内容审核 内容审核是基于图像、文本、音视频的检测技术,可自动检测低俗、违法违规、色情、广告、图文违规等内容,对用户上传的图片、文字、音视频进行内容审核,以满足上传要求,帮助客户降低业务违规风险。 常见的内容审核方式有: * 图像内容审核 图像内容审核,利用深度神经网络模型对图片内容进行检测,准确识别图像中的敏感违法元素、违规内容等,帮助业务规避违规风险。 * 文本内容审核 文本内容审核,采用人工智能文本检测技术有效识别违法违规、广告、辱骂、违禁品和灌水文本内容,提供定制化的文本敏感内容审核方案。 ![](1.png) ### 二、云开发内容审核介绍 [云开发内容审核](https://cloud.tencent.com/document/product/876/66140)为托管在云开发内的内容(数据库里存储的数据、云存储上存储的文件)提供快速的内容审核服务。可快速设置内容审核规则(审核范围、审核场景、违规后自动封禁处理),数据库文档变更后异步审核,文本内容秒级完成审核与处理。 ![](21.png) >?注意: >当前仅支持数据库内的文档进行内容审核。 ### 三、内容审核的常见场景 在当下的互联网环境下,内容审核可以说是无处不在,以一个论坛网站为例:小到一个用户的用户名注册内容审核、用户在评论区或留言区的评论内容审核,大到用户发帖的整个帖子的内容审核。 凡是能让用户自由输入内容的地方都需要对其内容进行审核,从而防止论坛被大量不良信息所围绕,造成网站服务器资源被浪费,严重的影响了网站形象,更有甚者网站站长可能会承担相关法律责任。 ## 前提条件 已有一个可用的[按量计费环境](https://cloud.tencent.com/document/product/876/41391)。 ## 操作步骤 点击一个按量计费环境,进入环境首页,点开【环境】进入到【内容审核】页,点击之后,在内容审核页可以看到有两大部分:审核规则和审核详情。 ![](2.png) ### 一、创建审核规则 在进行内容审核之前,需要先创建审核规则,即制定对哪些内容进行什么样的规则进行审核。 ![](3.png) 1.点击「新建」按钮,开始创建审核规则。 ![](4.png) 2.选择对数据库中哪个集合进行内容审核,例如需要对用户评论内容进行审核,则选择存储用户评论的集合,如下: ![](5.png) >?说明 >该下拉框中所列出的集合即是数据库中所有的集合,如果当前下拉框中没有集合,则您需要在左侧导航栏数据库中先创建一个集合。 3.选择完集合后,还需填写对该集合下的哪个字段进行审核,例如需要对用户评论内容进行审核,则填写评论集合里的评论内容字段,如下: ![](6.png) 4.拟定一个屏蔽文案,当出现违规内容时,用于提示用户的信息,默认为:该内容已违规暂不显示。如下: ![](7.png) 5.开启对违规内容进行自动屏蔽开关。开启后,系统如果检测到某条内容违规,则会对内容进行自动屏蔽,并以4中拟定的自定义屏蔽文案进行重写。如果不开启,则只对内容进行审核打分,不自动重写屏蔽。一般建议开启,如下: ![](8.png) 6.开启后,需要选择审核场景,即对什么类型的违规内容进行审核,如谩骂、广告、违法、政治、色情等。一般建议全选,如下: ![](9.png) >?说明 >违规类型后的审核分数是指:当系统对内容进行审核时,会对被审核的内容进行打分,分数越高表示内容违规程度越高,当打出的分数大于所填写的审核分数时,系统将会对内容进行自动屏蔽。 审核分数可理解为对当前违规类型的“容忍度”,分数越低表示容忍度越低,例如对违法信息零容忍,本着“宁可错杀一千,也不放过一个”的原则,即可将违法类型的分数填写的低一点(最低60分),这样系统一旦发现内容疑似属于违法信息,立即将其屏蔽。 7.填写完审核场景后,最后点击勾选条款,点击【确定】即可创建一条新的审核规则。 ![](10.png) ![](11.png) ### 二、测试审核规则 审核规则创建完毕后,即可测试下创建的审核规则是否生效。 1.点击左侧导航栏中的【数据库】页,进入到上述所选的集合中,点击【添加文档】,先添加一条正常的内容: ![](12.png) 如下图,对于没有违规的内容是会正常插入到集合中的。 ![](13.png) 2.再次添加文档,并尝试故意输入一些违规内容: ![](14.png) 如下图,插入的文档字段包含违规内容,已经被自动屏蔽重写了。 ![](15.png) 以上说明创建的审核规则已生效。 ### 三、查看审核详情 1.点击左侧导航栏中的【内容审核】页后,再点击顶部的【审核详情】,能看到审核平台的审核内容以及审核结果,如下: ![](16.png) 2.在测试审核规则时,第二次故意输入的违规内容已成功被审核系统监测到,并准确地识别出违规类型以及对内容的审核评分,如下: ![](17.png) 3.在某些特定的需求场景下,如果发现某条在特定场景下属于是正常内容,但被审核系统“误判”为违规内容时: ![](18.png) 可对该条违规记录进行【回滚】。 ![](19.png) 回滚后该条内容在审核记录里的处理状态也变成了“已回滚”, 并且在数据库中该条记录也可正常显示。 ![](20.png) --- ## 校园交友小程序开发实践 # 校园交友小程序开发实践 import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; ## 概述 本文介绍如何用云开发相关能力,快速完成一个校园交友小程序的开发。并围绕**抽个对象**和**我的纸条**两个页面进行功能展示和讲解。 ![](https://qcloudimg.tencent-cloud.cn/raw/73f348ca74e2f5d149c1ee12b51c6858.png) :::tip 说明 本实例教程所涉及到的相关源码材料,均已得到相应授权。 ::: ### 准备工作 1. [注册腾讯云](https://cloud.tencent.com/document/product/378/17985)。 2. 开通了云开发的小程序,详情请参见 [小程序端快速入门](/quick-start/mini-program/introduce)。 ### 操作流程 具体操作流程可分为以下 6 步。更多详情可参见 [示例](https://gitee.com/hhh3167253066/school_friends)。 - [校园交友小程序开发实践](#校园交友小程序开发实践) - [概述](#概述) - [准备工作](#准备工作) - [操作流程](#操作流程) - [数据库表的设计](#数据库表的设计) - [步骤 1:编写登录功能及主页代码](#步骤-1编写登录功能及主页代码) - [小程序配置及页面创建](#小程序配置及页面创建) - [实现用户登录功能及 openId 的记录](#实现用户登录功能及-openid-的记录) - [编写 index 前端页面](#编写-index-前端页面) - [步骤 2:主页逻辑处理](#步骤-2主页逻辑处理) - [步骤 3:实现抽取纸条功能](#步骤-3实现抽取纸条功能) - [步骤 4:我的纸条页面设计](#步骤-4我的纸条页面设计) - [我放入的纸条页面设计](#我放入的纸条页面设计) - [我抽到的纸条页面设计](#我抽到的纸条页面设计) - [步骤 5:我的纸条页面逻辑处理](#步骤-5我的纸条页面逻辑处理) - [步骤 6:细节补充](#步骤-6细节补充) ### 数据库表的设计 将用户的登录与用户对应放入的纸条数据分离开,就要建个**users_school**表来存储微信小程序用户,所有用户放入的纸条再建一个**body_girl_yun**表,为了便于让用户管理抽出的纸条就再建一个**body_girl_yun_put**表用来存储所有用户抽出的纸条。 打开微信开发者工具,单击**云开发**进入**云开发控制台** > **数据库**页面。单击**新建按钮**创建 **users_school**、**body_girl_yun** 和 **body_girl_yun_put** 三个集合,如下图所示: ![](https://qcloudimg.tencent-cloud.cn/raw/ed6bb763f7a603da0ec485d6d519e336.png) ## 步骤 1:编写登录功能及主页代码 本文主要围绕主页的 index.wxml 和 index.wxss 进行讲解,更多 index 前端页面代码细节可参见 [index 前端页面](https://gitee.com/hhh3167253066/school_friends/blob/master/miniprogram/pages/index/index.wxml) 和 [index 页面样式](https://gitee.com/hhh3167253066/school_friends/blob/master/miniprogram/pages/index/index.wxss)。 ### 小程序配置及页面创建 1. app.json 中,配置两个页面的路径: ```json "pages": [ "pages/index/index", "pages/history/history" ] ``` 配置好后刷新开发者工具,就会在页面 pages 文件夹下生成 index,history 文件夹以及对应的 `.js`,`.wxml`, `.wxss` 和 `.json` 文件。 2. 在 app.json 中设置 tabbar 的位置,在页面顶部以及设置里面的内容: ```json "tabBar": { "color": "black", "selectedColor": "#D00000", "position": "top", "list": [{ "pagePath": "pages/index/index", "text": "抽个对象" }, { "pagePath": "pages/history/history", "text": "我的纸条" } ] }, ``` ```` 3. 在 app.js 里新增全局的数据,用来存放当前用户的 openId: ```js this.globalData = { openId: '' } ```` ### 实现用户登录功能及 openId 的记录 1. 右击**当前环境**文件夹,单击**新建 Node.js 云函数**,并将文件命名为 login_yun。 ![](https://qcloudimg.tencent-cloud.cn/raw/fbc2d81502e939b58d4f9d423a139fce.png) 2. 进入 login_yun 目录下的 index.js 文件,在 `cloud.init()` 函数内配置环境。 ```js cloud.init({ // env 参数说明: // env 参数决定接下来小程序发起的云开发调用(wx.cloud.xxx)会默认请求到哪个云环境的资源 // 此处请填入环境 ID, 环境 ID 可打开云控制台查看 // 如不填则使用默认环境(第一个创建的环境) // env: 'my-env-id', env: "cloud1234567890XXXXXXX", }); ``` 3. 在云函数入口函数里进行 openId 的操作 ```js exports.main = async (event, context) => { const wxContext = cloud.getWXContext(); const openId = md5(wxContext.OPENID); // 查询这个openid下有无数据 let user_data = await db .collection("users_school") .where({ openId: openId, }) .get(); // 没有此用户则将openId添加到数据库 if (user_data.data.length === 0) { try { let data_add = await db.collection("users_school").add({ data: { openId: openId, }, }); return { data_add, openId, status: 202, // 新添加的数据 }; } catch (e) { console.error(e); } // 有了则直接返回 } else { return { user_data, status: 200, // 已经有了用户 }; } }; ``` 4. 然后右击 login_yun 文件夹,单击**上传并部署:云端安装依赖**,即完成了云函数的编写。 ![](https://qcloudimg.tencent-cloud.cn/raw/28f7b496512e408a47b01a5d093ea021.png) 5. 登录功能的云函数的调用,是在 index 页面加载 index.js 时进行调用,且在 onload 的生命周期中。 ```js const that = this; if (wx.getUserProfile) { that.setData({ canIUseGetUserProfile: false, }); } wx.cloud .callFunction({ name: "login_yun", // 调用云函数 }) .then((res) => { console.log(res); if (res.result.status === 200) { // 存到全局的globalData里,便于后续使用 app.globalData.openId = res.result.user_data.data[0].openId; } else { app.globalData.openId = res.result.openId; } }); ``` ### 编写 index 前端页面 1. 顶部的轮播图,直接可以用小程序提供的 **swiper** 加上 **swiper-item** 标签来实现。 ```html ``` ```` 2. 中间的盒子部分用基本的标签、图片和 CSS 样式来编写。单击放入与抽取都会跳出一个收集信息的框,使用 bindtap 来绑定点击的事件,并在 index.js 里处理对应的事件。 ```html 放入一张男生纸条 抽取一张男生纸条 ```` 3. 黑遮罩层用一个 view 标签,结合 CSS 的样式来完成。点击遮罩层对应 cancelHide 来隐藏遮罩层。 ```html ``` CSS 占满整个屏幕,加上颜色与透明度即可。 ```css /_ 遮罩层 _/ .hide { width: 100vw; height: 100vh; background-color: black; opacity: 0.5; position: fixed; top: 0vw; left: 0vh; } ``` ```` 4. 男女生放入与抽取的弹出框,picker 用来选择分类的不同的学校。 ```html - {{arrayBody4[indexBody4]}} - ```` 5. 将 index 前端页面和样式细化后,最后效果如下图所示: ![](https://qcloudimg.tencent-cloud.cn/raw/687bc341dd3ef9bd9d4d4e602496e136.png) ## 步骤 2:主页逻辑处理 本文主要围绕主页的 index.js 进行讲解,更多详情请参见 [主页逻辑代码](https://gitee.com/hhh3167253066/school_friends/blob/master/miniprogram/pages/index/index.js)。 1. 进入 index.js 页面,在 onload 的生命周期里,调用 login_yun 云函数实现登录的操作。 ```js wx.cloud .callFunction({ name: "login_yun", }) .then((res) => { console.log(res); if (res.result.status === 200) { app.globalData.openId = res.result.user_data.data[0].openId; } else { app.globalData.openId = res.result.openId; } }); ``` 2. 在 index.js 页面,添加 data 存放所需要的数据。 ```js data: { // 遮罩层标志 putBodyMask: false, putGirlMask: false, xuzhiMask: true, // 抽出的遮罩层 outBodyMask: false, outGirlMask: false, // 交友宣言 textareaBody: '', textareaGirl: '', // qq微信号 numberBody: '', numberGirl: '', // 上传图片预览的src srcListBody: [], srcListGirl: [], // 放入的学校 arrayBody4: ["河南理工大学", "焦作大学", "焦作师范"], indexBody4: 0, // 纸条的生命 arrayBody2: ["被抽中一次销毁", "被抽中两次销毁", "被抽中三次销毁"], indexBody2: 0, arrayBody3: ["河南理工大学", "焦作大学", "焦作师范"], indexBody3: 0, // 放入的学校 arrayGirl4: ["河南理工大学", "焦作大学", "焦作师范"], indexGirl4: 0 // 纸条的生命 arrayGirl2: ["被抽中一次销毁", "被抽中两次销毁", "被抽中三次销毁"], indexGirl2: 0, arrayGirl3: ["河南理工大学", "焦作大学", "焦作师范"], indexGirl3: 0, // 添加图片的加号 addMask: true }, ``` 3. 学校选择的逻辑。 1. picker 中 bindchange="bindSchoolChangePut",通过 bindSchoolChangePut 来触发学校改变的事件,选择对应的学校。 2. e.detail.value 来获取在 data 中绑定的学校的列表索引。 ```js // 放入时,学校的选择 bindSchoolChangePut: function(e){ this.setData({ indexBody4: parseInt(e.detail.value) }) } ``` 4. 在点击确认放入,触发对应的 surePutBodyBtns 事件,再进行判断,进而实现限制交友宣言长度。 ```js if (that.data.textareaBody.length 1200000){ return wx.showToast({ title: '图片过大', icon: 'error', duration: 2000 }) } const filePath = res.tempFilePaths[0] let timeStamp = Date.parse(new Date()); const cloudPath = "image/" + timeStamp + filePath.match(/\.[^.]+?$/)[0] that.pageData.filePath = filePath that.pageData.cloudPath = cloudPath that.setData({ srcListGirl: res.tempFilePaths }) } }) } ``` 7. 单击纸条的生命,相应值的选择对应数据库 life 字段。 ![](https://qcloudimg.tencent-cloud.cn/raw/133df03a052bb1b3686e83d3c2890027.png) 8. 点击确认放入之后,相应逻辑是先上传图片,再上传 location,weChatId 等信息到 body_girl_yun 表,上传成功要跳转到 history 页面。 ```js // 上传图片的api,先上传图片到云存储 wx.cloud.uploadFile({ cloudPath, filePath, success: function(res){ wx.hideLoading() wx.showLoading({ title: '信息上传中', mask: true }) // 上传图片完成后上传数据 db.collection("body_girl_yun").add({ data: { location: that.data.indexGirl4, weChatId: that.data.numberGirl, picture: res.fileID, life: parseInt(that.data.indexGirl2) + 1, des: that.data.textareaGirl, sex: 2, openId: app.globalData.openId, time: new Date().getTime() } }).then(result => { wx.hideLoading() that.pageData = { filePath: '', cloudPath: '' } that.setData({ putGirlMask: false, srcListGirl: [], textareaGirl: '', numberGirl: '' }) // 上传完成后跳转到history页 wx.switchTab({ url: '/pages/history/history', success: res=>{ wx.showToast({ title: '放入纸条成功', icon: 'success' }) }, fail: err => { wx.showToast({ title: err, icon: 'error' }) } }) } }) ``` 9. 页面底部两个点击事件:联系客服与 uu 须知。联系客服主要是在 index.wxml 里通过小程序的 open-type=“concat” 来实现。 ```html UU须知 | --> 遇到问题?联系客服 ``` ```js // 点击UU须知 xuzhi: function(){ this.setData({ xuzhiMask: true }) }, // 联系客服 contact: function(){ console.log() } ``` ## 步骤 3:实现抽取纸条功能 本文主要继续围绕主页的 index.js 进行抽取纸条功能的讲解,更多详情请参见 [主页逻辑代码](https://gitee.com/hhh3167253066/school_friends/blob/master/miniprogram/pages/index/index.js)。 1. 随机抽取可以用微信开放文档提供的 [开发者资源](https://developers.weixin.qq.com/miniprogram/dev/wxcloud/reference-http-api/) 来查找,进行随机的查询抽取,抽取的条件是**“性别,学校和生命值必须大于 0”**。 ```js // 随机抽取 db.collection("body_girl_yun") .aggregate() .match({ sex: 1, location: parseInt(that.data.indexBody3), life: _.gt(0), // 生命值要大于0 }) .sample({ size: 1 }) .end(); ``` 2. 抽到则处理,抽不到则提示处理时要把生命值减 1。 ```js // 数据库没有这个学校的男生的纸条就 if (res.list.length == 0) { return wx.showToast({ title: "此学校暂无纸条", icon: "error", mask: true, }); } // 抽取到了纸条,则进行操作 // 生命值减一, 生命值为0的不会抽出来 db.collection("body_girl_yun") .where({ _id: res.list[0]._id, }) .update({ data: { life: parseInt(res.list[0].life) - 1, }, }) .then((resultUpdate) => { wx.showToast({ title: "抽取成功", icon: "success", mask: true, }); }) .catch((err) => { wx.showToast({ title: err, icon: "error", }); }); ``` 3. 把数据写到 body_girl_yun_put 表中。 ```js // 并将数据添加到 body_girl_yun_put db.collection("body_girl_yun_put") .add({ data: { picture: res.list[0].picture, des: res.list[0].des, location: res.list[0].location, sex: res.list[0].sex, weChatId: res.list[0].weChatId, openId: app.globalData.openId, time: new Date().getTime(), }, }) .then((resultAdd) => {}) .catch((err) => { wx.showToast({ title: err, icon: "error", }); }); ``` 4. 数据存入成功则跳转页面 history。 ```js wx.switchTab({ url: "/pages/history/history", success: (res) => { wx.showToast({ title: "抽出纸条成功", icon: "success", }); }, fail: (err) => {}, }); that.setData({ outBodyMask: false, }); ``` 5. 加上提示框与 loading 效果,wx.showLoading, wx.hideLoading(), 并添加了一些基本的错误处理。 ```js // 确认抽取一张男生纸条 sureOutBodyBtn: function(){ const that = this wx.showLoading({ title: '随机抽取中', mask: true }) // 随机抽取 db.collection('body_girl_yun').aggregate().match({ sex: 1, location: parseInt(that.data.indexBody3), life: _.gt(0) // 生命值要大于0 }).sample({ size: 1}).end() .then(res => { wx.hideLoading() // 数据库没有这个学校的男生的纸条就 if(res.list.length == 0){ return wx.showToast({ title: '此学校暂无纸条', icon: 'error', mask: true }) } console.log(res) // 生命值减一, 生命值为0的不会抽出来 db.collection('body_girl_yun').where({ _id: res.list[0]._id }).update({ data: { life: parseInt(res.list[0].life) - 1 } }).then( resultUpdate => { wx.showToast({ title: '抽取成功', icon: 'success', mask: true }) }).catch(err=>{ wx.showToast({ title: err, icon: 'error' }) }) // 并将数据添加到 body_girl_yun_put db.collection('body_girl_yun_put').add({ data: { picture: res.list[0].picture, des: res.list[0].des, location: res.list[0].location, sex: res.list[0].sex, weChatId: res.list[0].weChatId, openId: app.globalData.openId, time: new Date().getTime() } }).then( resultAdd => { wx.switchTab({ url: '/pages/history/history', success: res=>{ wx.showToast({ title: '抽出纸条成功', icon: 'success' }) }, fail: err => { wx.showToast({ title: err, icon: 'error' }) } }) // console.log("数据add"resultAdd) that.setData({ outBodyMask: false }) }).catch(err=>{ wx.showToast({ title: err, icon: 'error' }) }) }) } ``` ## 步骤 4:我的纸条页面设计 本文主要围绕我的纸条前端页面 history.wxml 进行讲解,更多详情请参见 [我的纸条前端代码](https://gitee.com/hhh3167253066/school_friends/blob/master/miniprogram/pages/history/history.wxml)。 ### 我放入的纸条页面设计 1. 顶部的“我放入的纸条”与“我抽到的纸条”通过改变 active 的值来切换 class。 ```html 我放入的纸条 我抽到的纸条 ``` 2. 前端 for 循环出每个数据进行展示。dataList 为在数据库查出来的数据,指明 `wx:key`。 ```html 交友宣言:{{item.des}} ``` 在删除时需要数据的 `_id`,所以需要配合 JS 进行传递参数:`data-id="{{item._id}}"`。 ```html {{schoolList[item.location]}} {{item.sex == 1? '男': '女'}} 删除 ! ``` 通过 `e.target.dataset.id` 获取到传递过来的参数。 ```js deletePut: function (e) { const that = this const _id = e.target.dataset.id } ``` 3. 实现交友宣言的 3 行,超出则用省略号展示。 ```css .outTopDes_1 { height: 15vh; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; word-break: break-all; } ``` 4. 前端判断是否有数据,没有数据则显示“空空如也”。 ```html 空空如也 空空如也 ``` ### 我抽到的纸条页面设计 1. 基本跟“我放入的纸条”页面相同。多出了微信号的展示位置,交友宣言的行数减少一行。微信号的居中显示: ```css .outTopDes_2 { color: rgb(62, 88, 238); text-align: center; font-size: 35rpx; } ``` 2. 用户上传的图片可在**云开发控制台** > **存储** > **存储管理**页面中获取。 ![](https://qcloudimg.tencent-cloud.cn/raw/7f564d15899a92c66d93e59584c6e4ae.png) ## 步骤 5:我的纸条页面逻辑处理 本文主要围绕我的纸条 history.js 进行讲解,更多详情请参见 [我的纸条逻辑代码](https://gitee.com/hhh3167253066/school_friends/blob/master/miniprogram/pages/history/history.js)。 1. data 数据的设计。 ```json { "active": true, // 用来改变当前选中的样式 "dataListPut": [], // 用来存put页面的数据 "dataListOut": [], "schoolList": ["河南理工", "河南师范", "焦作师范"] } ``` 2. onload 生命周期的设计。 - 因为这个页面没有获取用户 openId 的功能,所以需要先判断下是否已经获取到了用户的 openId。如果没有,则直接跳到 index 页面获取 openId,并提示相应错误。 ```js if (app.globalData.openId == "") { wx.switchTab({ url: "/pages/index/index", success: (res) => {}, fail: (err) => { wx.showToast({ title: err, icon: "error", }); }, }); } ``` - 调用请求“我放入的纸条”的数据函数 ```js that.getPutData(); ``` 3. 通过小程序开放文档提供查询方式,用用户的 openId 来获取到数据,并且把获取到的数据,通过 that.setData 给到 dataListPut 供页面渲染。 查询方法 作用 limit 来限制获取数据的条数 orderBy 数据排序 ```js // 获取数据put getPutData: function(e){ const that = this db.collection('body_girl_yun').where({ openId: app.globalData.openId }).limit(10).orderBy('time', 'desc').get().then(res => { console.log(res) if(res.data.length == 0){ that.setData({ dataListPut: res.data }) return wx.showToast({ title: '没有数据', icon: 'none' }) } that.setData({ dataListPut: res.data }) }).catch(err=>{ wx.showToast({ title: '加载数据失败', icon: 'error' }) }) }, ``` 4. 删除纸条的逻辑实现。 - 实现删除提示。 ```js wx.showModal({ title: '提示', // content: '确认删除纸条?', content: '删除后友友大厅将不可见,确认?', success (res) { }) ``` - 如果用户确认删除,用 remove 通过前端传过来的 `_id`,对应唯一一个数据,进行删除,包括基本的错误处理。否则提示取消删除。 ```js if (res.confirm) { db.collection("body_girl_yun").where({ _id: _id }).remove().then(res => { wx.hideLoading() if(res.errMsg == 'collection.remove:ok'){ that.getPutData() }else{ wx.showToast({ title: '删除失败', icon: 'error', mask: true }) } }).catch( console.error ) } else if (res.cancel) { wx.showToast({ title: '删除取消', icon: 'error', mask: true }) } } ``` 5. 进行分页查询结合上划触底加载数据。 - 通过 onReachBottom 触发事件。 ```js /** * 页面上拉触底事件的处理函数 */ onReachBottom: function () { if(this.data.active==true){ this.getPutDataBottom() }else{ this.getOutDataBottom() } }, ``` - 通过 `skip(pagePut * 10).limit(10)` 中的 `pagePut` 参数来记录页数。 - 通过 concat 进行新旧数据的拼接,并更新到页面。 ```js // 上划触底的事件 getPutDataBottom: function(){ const that = this let pagePut = that.data.pagePut + 1 db.collection('body_girl_yun').where({ openId: app.globalData.openId }).skip(pagePut * 10).limit(10).orderBy('time', 'desc').get().then(res => { console.log(res) wx.hideLoading() // 如果还有数据 if(res.data.length > 0){ // 通过concat进行数据的拼接 let all_data = that.data.dataListPut.concat(res.data) that.setData({ dataListPut: all_data, pagePut: pagePut }) }else{ wx.hideLoading() wx.showToast({ title: '没有更多数据', icon: 'none' }) } }) }, ``` 6. 实现下拉刷新数据。 - 需要先在 app.json 文件里配置开启下拉刷新功能 enablePullDownRefresh。 ```json "window": { "backgroundColor": "#FFCCFF", "backgroundTextStyle": "light", "navigationBarBackgroundColor": "#FFCCFF", "navigationBarTitleText": "校园交U", "navigationBarTextStyle": "black", "enablePullDownRefresh": true }, ``` - 用户 onPullDownRefresh 下拉触发请求数据的函数,重新获取数据。 ```js /** * 页面相关事件处理函数--监听用户下拉动作 */ onPullDownRefresh: function () { if(this.data.active == true){ this.getPutData("pull") }else{ this.getOutData("pull") } }, ``` ## 步骤 6:细节补充 1. 加上删除纸条的 showLoading 效果。 ```js wx.showLoading({ title: "删除中", mask: true, }); ``` 还有获取 put 数据的 showLoading 等。 2. 加上 showModal 提示。 ```js wx.showModal({ title: '提示', content: '确认删除纸条?', success (res) { }) }) ``` 至此,该小程序的全部功能已实现完成。更多详情请参见 [示例代码](https://gitee.com/hhh3167253066/school_friends)。 --- ## 手把手教你搭建电商小程序 # 手把手教你搭建电商小程序 ## 准备工作 **工欲善其事 必先利其器** 1. 注册微信公众平台,并完成相关认证备案,开通微信支付。 2. 安装微信开发者工具,并创建项目。 3. 开通 云开发环境。 4. 进入云开发控制台 > 设置 > 拓展功能页面,单击开通内容管理和内容安全。 可以参考之前教程中的方法进行操作[云开发 CloudBase 概述-示例教程-文档中心-腾讯云](https://cloud.tencent.com/document/product/876/71440) **课程概述** 1. 从 0-1 完成一个电商小程序的快速搭建。 2. 学习云开发相关基本知识。 3. 了解小程序的开发。 4. 云模版的基本使用。 :::tip 在学习本次课程前建议了解基本 html css 的相关基础知识。 ::: 本次课程为电商小程序的基础讲解,为了更好让大家理解代码实现中仅完成功能的基本搭建,功能的完善会在后续进阶课程中展现。 #### 学习方法 你可以边看视频边看文档,结合自己动手实际编写以便更好理解。在学习过程中有任何问题,你可以通过百度,在无法解决时通过留言的方式进行提问。 当然你也可以借助腾讯云云开发 云开发 Copilot,帮助您解答关于云开发的各种问题。 代码:[https://gitee.com/liu-zitao/e-commerce-mini-program.git](https://gitee.com/liu-zitao/e-commerce-mini-program.git) ## 步骤 1:轮播图与公告搭建 本文主要围绕主页的 index 页面、[云开发内容管理](https://developers.weixin.qq.com/miniprogram/dev/wxcloud/guide/extensions/cms/introduction.html) 和 [云开发数据库](https://developers.weixin.qq.com/miniprogram/dev/wxcloud/guide/database.html) 进行讲解,更多 index 代码细节可参见 [index 页面](https://gitee.com/liu-zitao/e-commerce-mini-program/tree/master/miniprogram/pages/index) #### 操作步骤 ### 步骤 1:开通内容管理 1. 首先进入**云开发控制台** > **内容管理**页面,单击**开通**,并设置账号密码。内容管理创建需要一定的时间请安心等待。 ![](./audit/cloud-admin-1.png) 2. 在创建成功之后选择继续使用云开发 CMS,单击**打开管理端**即可访问**内容管理平台**。 ![](./audit/cloud-admin-2.png) 3. 输入登录账号和密码,进入**内容管理(CMS)**后台,单击**创建新项目**这里我们起名为电商小程序。 ![](./audit/cloud-admin-3.png) ### 步骤 2:搭建轮播图 :::tip 说明 **数据库创建流程** 新建模型 》 设置字段 》 新增数据 》 修改数据库权限 》 页面中查询数据 》 展现数据 ::: 1. 进入上述新建的**电商后台管理系统**,进入**内容模型**页面,单击**新建模型**,这里我们设置**展示名称**为**轮播图**,**数据库名**为 **banner**。设置完成后单击**创建**。 ![](./audit/cloud-admin-4.png) :::tip 更改**数据库名**会自动重命名原数据库,请谨慎操作。 ::: 字段名称 数据库字段名 内容类型 是否必须 图片 banner_photo 图片 是 链接 banner_link 单行字符串 否 2. 单击右侧**内容类型** > **图片**,进入**添加图片字段**页面,设置**展示名称**为**轮播图**,**数据库字段名**为 **photo**。 ![](./audit/cloud-admin-5.png) 单击**添加**后完成**内容模型**的创建。 ![](./audit/cloud-admin-6.png) 3. 进入**内容集合** > **轮播图**页面,单击**新建**。 ![](./audit/cloud-admin-7.png) 拖动图片并单击**创建**后完成轮播图片的上传,这样一个轮播图的内容模型我们就创建完成了。 ![](./audit/cloud-admin-9.png) 4. 通过上面操作后,相应的会在**云开发控制台**生成 **banner** 数据库以及上述导入的图片数据。进入**云开发控制台** > **数据库** > **banner** > **数据权限**页面,将数据库数据权限改为**所有用户可读,仅创建者可读写**,这样所有用户就可以看到数据了。 ![](./audit/cloud-admin-10.png) 5. 接下来在 pages/index 中开始编写轮播图。这里我们可以参见 [swiper 文档](https://developers.weixin.qq.com/miniprogram/dev/component/swiper.html),帮助我们绑定数据,这样我们使用 wx:for 进行列表绑定。 ![](./audit/cloud-admin-11.png) 6. 参数 env 可以在**微信开发者工具** > **云开发控制台**里获取。通过以下代码绑定 banner 数据。 ```javascript db.collection("banner").get({ success: (res) => { console.log(res.data); this.setData({ banner: res.data, }); }, }); ``` ```html ``` :::tip 说明 在组件上使用 wx:for 控制属性绑定一个数组,即可使用数组中各项的数据重复渲染该组件。 默认数组的当前项的下标变量名默认为 index,数组当前项的变量名默认为 item\* 使用 wx:for-item 可以指定数组当前元素的变量名。 ::: 7. 保存运行编译之后,可以看到轮播图。 ![](./audit/cloud-admin-12.png) :::tip 说明 如果出现运行编译后无法加载轮播图,请在**微信开发者工具**单击右上角**详情**,进入**本地设置**页面,尝试切换**调试基础库**为较低版本即可。 ::: ### 步骤 3:搭建通知公告 通知公告与轮播图模型创建以及数据读取操作相似这里不在进行详细讲述。 1. 创建模型并添加数据。 字段名称 数据库字段名 内容类型 是否必须 标题 notice_title 单行字符串 是 内容 notice_main 富文本 是 ![](./audit/cloud-admin-13.png) 2. 修改数据读取权限,**所有用户可读,仅创建者可读写。(后续步骤中不在体现本步骤)** 3. 通过以下代码绑定 notice 数据。 ```javascript db.collection("notice").get({ success: (res) => { console.log(res.data); this.setData({ notice: res.data, }); }, }); ``` ```html 【 公告 】 · {{item.notice_title}} ``` 4. 保存运行编译之后,可以看到通知公告。 ![](./audit/cloud-admin-14.png) ## 步骤 2:用户模块搭建 本文主要围绕主页的 user 页面、[云开发内容管理](https://developers.weixin.qq.com/miniprogram/dev/wxcloud/guide/extensions/cms/introduction.html) 和 [云开发数据库](https://developers.weixin.qq.com/miniprogram/dev/wxcloud/guide/database.html) 进行讲解,更多 user 代码细节可参见[user 页面](https://gitee.com/liu-zitao/e-commerce-mini-program/tree/master/miniprogram/pages/user) 用户登录我们借助云函数快速实现获取手机号码和 openid 的方式实现,总体设置思路如下图所示,用户一次登录之后借助缓存实现下一次使用时候无感登录方法。 ![](./audit/cloud-admin-15.png) 云开发的云函数的独特优势在于与微信登录认证的无缝整合。当小程序端调用云函数时,云函数的传入参数中会被注入小程序端用户的 openid,开发者无需校验 openid 的正确性,因为微信已经完成了这部分鉴权,开发者可以直接使用该 openid。与 openid 一起同时注入云函数的还有小程序的 appid。 :::tip 说明 从小程序端调用云函数时,开发者可以在云函数内使用 [wx-server-sdk](https://developers.weixin.qq.com/miniprogram/dev/wxcloud/guide/functions/wx-server-sdk.html) 提供的 [getWXContext](https://developers.weixin.qq.com/miniprogram/dev/wxcloud/reference-sdk-api/utils/Cloud.getWXContext.html) 方法获取到每次调用的上下文(appid、openid 等),无需维护复杂的鉴权机制,即可获取天然可信任的用户登录态(openid)。 ::: **操作步骤 ** ### 步骤 1:获取手机号 1. 需要将 [button](https://developers.weixin.qq.com/miniprogram/dev/component/button.html) 组件 open-type 的值设置为 getPhoneNumber,当用户点击并同意之后,通过 bindgetphonenumber 事件获取回调信息; ```html ``` 2. 创建云函数 getphonenumber ,并在云函数 index.js 页面中填写以下代码,完成后点击上传并部署:云端安装依赖。 ![](./audit/cloud-admin-16.png) ```javascript // 云函数入口文件 const cloud = require("wx-server-sdk"); cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV }); // 使用当前云环境 // 云函数入口函数 exports.main = async (event, context) => { const wxContext = cloud.getWXContext(); var moblie = event.weRunData.data.phoneNumber; return { event, openid: wxContext.OPENID, moblie, }; }; ``` ![](./audit/cloud-admin-17.png) 3. 将 bindgetphonenumber 事件回调中借助云函数获取手机号码 。 ```javascript getPhoneNumber(e){ wx.cloud.callFunction({ name: 'getphonenumber', data: { weRunData: wx.cloud.CloudID(e.detail.cloudID), } }).then(res => { console.log(res.result.moblie) }).catch(err => { console.error(err); }); }, ``` :::tip 说明 目前该接口针对**非个人开发者,且完成了认证的小程序开放(境外主体开放香港和澳门灰度内测,暂不开放其他境外主体。**[详见文档](https://docs.qq.com/doc/DZWpqblRwU3labktJ)**)**; ::: ### 步骤 2:创建用户 1. 创建 user 模型并添加以下字段。修改数据权限。 字段名称 数据库字段名 内容类型 是否必须 用户统一标识 openid 单行字符串 是 电话 phone 单行字符串 是 昵称 nick_name 单行字符串 是 :::tip 说明 更多 CMS 内容管理详细操作请参见 [搭建轮播图](https://www.yuque.com/liuzitao-qk9tf/bcqev8/tyt1gsemc6gdhs0g) ::: 2. 在刚才 bindgetphonenumber 事件回调事件中添加创建用户代码,并通过缓存把信息存储到 wx.setStorageSync。 ```javascript getPhoneNumber(e){ wx.cloud.callFunction({ name: 'getphonenumber', data: { weRunData: wx.cloud.CloudID(e.detail.cloudID), } }).then(res => { console.log(res) var user=res.result db.collection("user").where({openid:res.result.openid}).get().then(res=>{ console.log(res) if(res.data.length!=0){ wx.setStorageSync('wb_openid', res.data[0]) this.setData({ userinfo: res.data[0], }) }else{ db.collection("user").add({ data: { name: user.moblie, phone: user.moblie, openid: user.openid, _createTime: Date.parse(new Date()), }, success: function (res) { db.collection("user").where({openid:res.result.openid}).get().then(res=>{ wx.setStorageSync('wb_openid', res.data[0]), this.setData({ userinfo: res.data[0], })}) } }) } }) }).catch(err => { console.error(err); }); ``` ![](./audit/cloud-admin-18.png) 3. 之后再 onLoad 中添加读取缓存信息代码 ```javascript onLoad(options) { let userinfo = wx.getStorageSync('wb_openid') } ``` ![](./audit/cloud-admin-19.png) ## 步骤 3:商品页面搭建 本文主要围绕主页的 index 页面、[云开发内容管理](https://developers.weixin.qq.com/miniprogram/dev/wxcloud/guide/extensions/cms/introduction.html) 和 [云开发数据库](https://developers.weixin.qq.com/miniprogram/dev/wxcloud/guide/database.html) 进行讲解,更多 index 代码细节可参见[index 页面](https://gitee.com/liu-zitao/e-commerce-mini-program/tree/master/miniprogram/pages/index) **操作步骤 ** ### 步骤 1:创建商品模型 1. 创建 goods 模型并添加以下字段,修改数据权限。 字段名称 数据库字段名 内容类型 是否必须 商品名称 goods_name 单行字符串 是 商品价格 goods_price 数字 是 封面图 goods_pho 图片 是 商品简介 goods_int 单行字符串 是 :::tip 说明 更多 CMS 内容管理详细操作请参见 搭建轮播图 ::: 2. 添加商品信息。 ![](./audit/cloud-admin-20.png) ### 步骤 2:页面中展现商品 1. 展示商品 页面的逻辑及前端代码如下: ```html {{item.goods_name}} ¥{{item.goods_price}}元已售0件 ``` ```javascript // pages/index/index.js const db = wx.cloud.database(); // pages/index/index.js const db = wx.cloud.database(); Page({ /** * 生命周期函数--监听页面加载 */ onLoad(options) { db.collection("goods").get({ success: (res) => { console.log(res); this.setData({ goods: res.data, }); }, }); }, }); ``` ![](./audit/cloud-admin-21.png) 2. 通过 bindtap 事件 实现点击跳转商品详情页面。 ```javascript spxx(e){ console.log(e.currentTarget.id) wx.navigateTo({ url: '../goodslist/goodslist?scene=' + e.currentTarget.id, }) }, ``` :::tip 说明 保留当前页面,跳转到应用内的某个页面。其中可使用 [wx.navigateBack](https://developers.weixin.qq.com/miniprogram/dev/api/route/wx.navigateBack.html) 返回到原页面。小程序中页面栈最多十层。 ::: 3. 在 goodslist 页面接收 scene 值并展现商品详细信息。 ```javascript // pages/goodslist/goodslist.js const db = wx.cloud.database(); Page({ onLoad(options) { db.collection("goods") .doc(options.scene) .get({ success: (res) => { console.log(res); this.setData({ goods: res.data, }); }, }); }, }); ``` 到这里商品页面就搭建完成。 ![](./audit/cloud-admin-22.png) ## 步骤 4:商品分享二维码搭建 本文主要围绕商品页的 goods 页面、[云开发内容管理](https://developers.weixin.qq.com/miniprogram/dev/wxcloud/guide/extensions/cms/introduction.html) 和 [管理工具 云模版](https://developers.weixin.qq.com/miniprogram/dev/wxcloud/guide/extensions/cloud-builder/intro.html) 进行讲解,更多 goods 代码细节可参见 [goods 页面](https://gitee.com/liu-zitao/e-commerce-mini-program/tree/master/miniprogram/pages/goodslist) #### 操作步骤 ### 步骤 1:开通云模版 打开[开发者工具](https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html),在编辑器中 miniprogram 下的任意路径右键菜单下,选择“使用云模板或 AI 配置页面”(新版开发工具)或“配置单页模板”(旧版开发工具),即可进入云模板功能页面。 :::tip 说明 目前仅[nightly 最新版](https://developers.weixin.qq.com/miniprogram/dev/devtools/nightly.html)可以体验云模版功能,后续将应用至全部工具版本。 **目前仅支持企业主体的小程序开通使用云模版**,后续将会支持个人主体的小程序,敬请期待。 ::: ![](./audit/cloud-admin-23.png) ### 步骤 2:使用 微信小程序码和链接 接口 当前模板提供了 3 个接口方法: - **wx_qrcode_get_qrcode:**获取小程序码,适用于需要的码数量较少的业务场景。通过该接口生成的小程序码,永久有效,有数量限制。 - **wx_qrcode_get_unlimited_qrcode:** 获取小程序码,适用于需要的码数量极多的业务场景。通过该接口生成的小程序码,永久有效,数量暂无限制。 - **wx_qrcode_generate_short_link:**获取小程序 Short Link,适用于微信内拉起小程序的业务场景。目前**只开放给电商类目**(具体包含以下一级类目:电商平台、商家自营、跨境电商)。通过该接口,可以选择生成到期失效和永久有效的小程序短链。 **更多说明和错误码参考微信小程序**[小程序码](https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/qrcode-link/qr-code/getQRCode.html) 点击进入该接口后进行安装,然后点击接口展示,使用其中的获取不限制的小程序码(wx_qrcode_get_unlimited_qrcode)。 :::tip **相关提示** 该接口用于获取小程序码,适用于需要的码数量极多的业务场景。通过该接口生成的小程序码,永久有效,数量暂无限制。 这里只展示如何使用其生成小程序码的操作,生成小程序 Short Link,适用于微信内拉起小程序的业务场景操作与其相似不在进行阐述。 ::: ![](./audit/cloud-admin-24.png) ### 步骤 3:生成相应商品小程序码 这里我们通过用户进行点击操作后,调用云函数生成并在展现给用户的模式进行编辑。商品基本信息相关字段已在上一章节中进行展现故本章不在进行相关的展示。 :::tip 说明 scene 存储的为商品\_id ::: ```javascript sdsy() { var spxx = this.data.goods var qrcode = 10 wx.cloud.callFunction({ name: 'cloudbase_module', data: { name: 'wx_qrcode_get_unlimited_qrcode', data: { scene: spxx._id, //最大32个可见字符,只支持数字,大小写英文以及部分特殊字符:!#$&'()*+,/:;=?@-._~,其它字符请自行编码为合法字符(因不支持%,中文无法使用 urlencode 处理,请使用其他编码方式) page: 'pages/goodslist/goodslist', //默认是主页,页面 page,例如 pages/index/index,根路径前不要填加 /,不能携带参数(参数请放在scene字段里),如果不填写这个字段,默认跳主页面。scancode_time为系统保留参数,不允许配置 check_path: false, //默认是true,检查page 是否存在,为 true 时 page 必须是已经发布的小程序存在的页面(否则报错);为 false 时允许小程序未发布或者 page 不存在, 但page 有数量上限(60000个)请勿滥用。 env_version: 'develop', //要打开的小程序版本。正式版为 "release",体验版为 "trial",开发版为 "develop"。默认是正式版。 width: 430, // 默认430,二维码的宽度,单位 px,最小 280px,最大 1280px auto_color: false, //自动配置线条颜色,如果颜色依然是黑色,则说明不建议配置主色调,默认 false line_color: { "r": 0, "g": 0, "b": 0 }, //默认是{"r":0,"g":0,"b":0} 。auto_color 为 false 时生效,使用 rgb 设置颜色 例如 {"r":"xxx","g":"xxx","b":"xxx"} 十进制表示 is_hyaline: false, //默认是false,是否需要透明底色,为 true 时,生成透明底色的小程序 }, } }).then(res => { console.log(res.result.fileID); wx.previewImage({ current: res.result.fileID, // 当前显示的图片链接 urls: [res.result.fileID] // 需要预览的图片链接列表 }) }); }, ``` [wx.previewImage](https://developers.weixin.qq.com/miniprogram/dev/api/media/image/wx.previewImage.html) 在新页面中全屏预览图片。预览的过程中用户可以进行保存图片、发送给朋友等操作。 至此商品分享二维码搭建完成。 ![](./audit/cloud-admin-25.png) ## 步骤 5:下单以及微信支付搭建 本文主要围绕商品页的 goods,order 页面、[云开发内容管理](https://developers.weixin.qq.com/miniprogram/dev/wxcloud/guide/extensions/cms/introduction.html) 和 [管理工具 云模版](https://developers.weixin.qq.com/miniprogram/dev/wxcloud/guide/extensions/cloud-builder/intro.html) 进行讲解,更多 goods ,order 代码细节可参见 [goods 页面](https://gitee.com/liu-zitao/e-commerce-mini-program/tree/master/miniprogram/pages/goodslist)[order 页面](https://gitee.com/liu-zitao/e-commerce-mini-program/tree/master/miniprogram/pages/order) #### 操作步骤 ### 步骤 1:安装云模板订单管理 主要用于订单的列表查看,可通过分类、关键字查询来筛选数据,并可导出查询到的订单。 ![](./audit/cloud-admin-26.png) **步骤 2:创建数据库 cloudbase-sample-orders,并在小程中实现创建订单** 1. 我们点开页面设置查看管理系统相关参数。 ![](./audit/cloud-admin-26-1.png) 2. 将相关参数添加并创建订单。 借助 wx.chooseAddress 快速获取用户收回地址,然后创建数据。 :::tip 说明 **wx.chooseAddress** **功能描述** 获取用户收货地址。调起用户编辑收货地址原生界面,并在编辑完成后返回用户选择的地址。 **使用方法** 自 2022 年 7 月 14 日后发布的小程序,若使用该接口,需要在 app.json 中进行声明,否则将无法正常使用该接口。 **申请开通** 暂只针对具备与地理位置强相关的使用场景的小程序开放,在小程序管理后台,「开发」-「开发管理」-「接口设置」中自助开通该接口权限。 ::: ```javascript xd() { var goods=this.data.goods wx.chooseAddress({ success: function (res) { var userinfo=res db.collection("cloudbase-sample-orders").add({ data: { receiver:userinfo.userName, receivePhone: userinfo.telNumber, goodPic:goods.goods_pho, afterSales:'', deliveryInformation:{area:res}, payTime: '', paymentWay:'', totalPrice:'', orderTime:Date.parse(new Date()), expreePrice: 0, paymentPrice:0, orderStatus: 1, number:1, unitPrice:goods.goods_price, name:goods.goods_name, orderId: Date.parse(new Date()), _createTime: Date.parse(new Date()), }, success: function (res) {} }) }, fail: function(err){ console.log(JSON.stringify(err)) } }) }, ``` ### 步骤 3:开通云模版微信支付 1. 安装微信支付模版,并开通微信支付。 ![](./audit/cloud-admin-27.png) 2. 配置商户信息 微信支付云模板需要配置商户信息后才能使用。点击参数设置,打开配置表单,填写微信支付必须的商户信息,保存后后模板初始化完成。 如果需要自行处理支付和退款通知,可通过接收支付通知的回调函数和接收退款通知的回调函数配置项来设置。 ![](./audit/cloud-admin-28.png) :::tip 说明 **参数获取可以借助说明文档操作** [https://cloud.tencent.com/document/product/1301/101447](https://cloud.tencent.com/document/product/1301/101447) ::: ![](./audit/cloud-admin-29.png) ![](./audit/cloud-admin-30.png) ### 步骤 2:使用云函数调用云模板下单接口 **模板已内置了云函数代码,可以直接在微信开发者工具中下载到本地修改后使用。** 也可以手动创建云函数来完成,点击在线代码示例,可以查看云函数示例代码。 1. 载模板云函数代码到本地 打开微信开发者工具界面,在 cloudfunctions 目录点击右键,选择同步云函数列表,同步模板中的云函数 wxpayFunctions 到本地;然后在云函数 wxpayFunctions 目录右键,选择下载,即可下载模板内置的云函数代码到本地。 ![](./audit/cloud-admin-31.png) ![](./audit/cloud-admin-32.png) :::tip 说明 **本模板提供了 5 个接口方法:** - wxpay_order: 小程序下单 - wxpay_query_order_by_transaction_id: 微信支付订单号查询订单 - wxpay_query_order_by_out_trade_no: 商户订单号查询订单 - wxpay_refund: 申请退款 - wxpay_refund_query: 通过商户退款单号查询单笔退款 具体调用方式可查看对应接口详情。 ::: 2. 编辑下单云函数 修改云函数 wxpayFunctions 下的 wxpay_order/index.js 代码,参数更新为业务实际参数。云函数编辑后,需要重新部署。 :::tip 说明 这里我们可以通过小程序传输值过来在 event 中获取这些参数数据。 ::: ![](./audit/cloud-admin-33.png) ### 步骤 3:小程序端获取预付单信息并完成支付 在小程序中调用第 2 步中的云函数,获取预付订单信息后,调用 wx.requestPayment 唤起微信支付组件完成支付。 :::tip 说明 这里为了方便大家理解,并未通过传值方法传入商品价格,我们可以将商品价格以及商品信息通过 data 其他业务参数传入。 ::: ```javascript zf(e){ wx.cloud.callFunction({ // 云函数名称 name: 'wxpayFunctions', data: { // 调用云函数中的下单方法 type: 'wxpay_order', // 业务其他参数... }, success: (res) => { console.log('下单结果: ', res); const paymentData = res.result?.data; // 唤起微信支付组件,完成支付 wx.requestPayment({ timeStamp: paymentData?.timeStamp, nonceStr: paymentData?.nonceStr, package: paymentData?.packageVal, paySign: paymentData?.paySign, signType: 'RSA', // 该参数为固定值 success(res) { // 支付成功回调,实现自定义的业务逻辑 console.log('唤起支付组件成功:', res); }, fail(err) { // 支付失败回调 console.error('唤起支付组件失败:', err); }, }); }, }); }, ``` ![](./audit/cloud-admin-34.jpg) ### 步骤 4:支付完成后修改订单状态 这里我们通过在页面中绑定数据\_id 然后支付完成后调用 db.update 完成操作,然后更新订单状态,支付信息等。 ```javascript zf(e){ var goods=this.data.order[0] console.log(e.currentTarget.id) var id=e.currentTarget.id wx.cloud.callFunction({ // 云函数名称 name: 'wxpayFunctions', data: { // 调用云函数中的下单方法 type: 'wxpay_order', // 业务其他参数... }, success: (res) => { console.log('下单结果: ', res); const paymentData = res.result?.data; // 唤起微信支付组件,完成支付 wx.requestPayment({ timeStamp: paymentData?.timeStamp, nonceStr: paymentData?.nonceStr, package: paymentData?.packageVal, paySign: paymentData?.paySign, signType: 'RSA', // 该参数为固定值 success(res) { // 支付成功回调,实现自定义的业务逻辑 console.log('唤起支付组件成功:', res); db.collection("cloudbase-sample-orders").doc(id).update({ data: { payTime:Date.parse(new Date()), paymentWay:'', totalPrice:'', orderTime:Date.parse(new Date()), expreePrice: 0, paymentPrice:0, orderStatus: 2, }, success: function (res) { } }) }, fail(err) { // 支付失败回调 console.error('唤起支付组件失败:', err); }, }); }, }); }, ``` 然后我们就可以在订单管理中查看到相关订单的状态。 ![](./audit/cloud-admin-35.png) 至此,该小程序的全部功能已实现完成。更多详情请参见 [示例代码](https://gitee.com/liu-zitao/e-commerce-mini-program.git)。 本次课程为电商小程序的基础讲解,为了更好让大家理解代码实现中仅完成功能的基本搭建,功能的完善会在后续进阶课程中展现。 ## 步骤 6:AI 客服的搭建 本文主要围绕 [管理工具 云模版](https://developers.weixin.qq.com/miniprogram/dev/wxcloud/guide/extensions/cloud-builder/intro.html) 进行讲解 #### 操作步骤 ### 1. 开通云模版,安装微信 AI 客服 打开[开发者工具](https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html),在编辑器中 miniprogram 下的任意路径右键菜单下,选择“使用云模板或 AI 配置页面”(新版开发工具)或“配置单页模板”(旧版开发工具),即可进入云模板功能页面,安装微信 AI 客服。 :::tip 说明 目前仅[nightly 最新版](https://developers.weixin.qq.com/miniprogram/dev/devtools/nightly.html)可以体验云模版功能,后续将应用至全部工具版本。 **目前仅支持企业主体的小程序开通使用云模版**,后续将会支持个人主体的小程序,敬请期待。 ::: ![](./audit/cloud-admin-36.png) ### 2. 使用管理端配置知识库、配置人工回复消息 点击模板模板详情页顶部**打开管理端**按钮,即可访问模板内置的管理端应用。使用上一步中添加的用户登录系统,上传并启用自己的知识库、配置人工回复消息的类型和内容。 ![](./audit/cloud-admin-37.png) ### 3. 使用模板 点击模板模板详情页顶部**添加至多平台**按钮,可将智能客服分发至不同的平台使用,目前支持微信小程序和微信公众号。 此处以小程序客服为例,配置小程序客服,输入小程序 AppId,系统会打开授权页面,使用微信扫码完成授权,小程序客服即由智能客服接管。 ![](./audit/cloud-admin-38.png) ![](./audit/cloud-admin-39.png) ![](./audit/cloud-admin-40.png) ### 4. 在小程序客服会话中使用 在小程序页面 wxml 中使用小程序的 button 组件,设置其 open-type 属性值为 contact,即可打开微信小程序客服会话页面。在客服对话页面中提问,即可收到智能客服的回答。 ```html 联系客服 ``` 基于大模型和自定义的知识库实现的 AI 智能客服已经能正确运行。同时,我们可以在模板内置的管理端应用中查看到客服会话的聊天记录。 ![](./audit/cloud-admin-41.png) --- ## CloudBase 数据库实现联表+聚合查询 # CloudBase 数据库实现联表+聚合查询 ## 场景说明 我们假设数据库内存在两个集合,`class` 与 `student`,存在以下数据: **class(班级信息)** | id | cname | teacher | | --- | ----- | ------- | | 1 | 一班 | 王老师 | | 2 | 二班 | 徐老师 | **student(学生信息)** | sname | class_id | score | | ----- | -------- | ----- | | 宁一 | 1 | 90 | | 张二 | 2 | 100 | | 李二 | 2 | 80 | 现在需要查询徐老师所带的班级里面所有学生的平均成绩。 ## 代码示例 ### 1、lookup 联表查询 首先我们需要把 `student` 内的所有数据,按照 `class_id` 进行分组,这里我们使用数据库的 [lookup 操作符](/api-reference/server/node-sdk/database/aggregate/stages/lookup): ```js lookup({ from: "student", //要关联的表student localField: "id", //class表中的关联字段 foreignField: "class_id", //student表中关联字段 as: "stu", //定义输出数组的别名 }).end(); ``` 这个语句会查出来下面的结果,会查出班级的信息以及该班级所对应的所有学生的信息: ```js {"list": [{ "id":1, "teacher":"王老师", "cname":"一班", "stu":[ { "sname":"宁一", "class_id":1, "score":90 } ] }, { "id":2, "teacher":"徐老师", "cname":"二班", "stu":[ { "class_id":2, "sname":"张二", "score":100 }, { "class_id":2, "sname":"李二", "score":80 } ] }] } ``` 但是我们只需要徐老师所在班级学生的数据,所以需要进一步过滤。 ### 2、match 条件匹配 ```js .lookup({ from: 'student', localField: 'id', foreignField: 'class_id', as: 'stu' }) .match({ teacher:"徐老师" }) .end() ``` 现在就只是返回徐老师所在班级的学生数据了,学生数据在 stu 对应的数组里面: ```json { "list": [ { "_id": "5e847ab25eb9428600a512352fa6c7c4", "id": 2, "teacher": "徐老师", "cname": "二班", //学生数据 "stu": [ { "_id": "37e26adb5eb945a70084351e57f6d717", "class_id": 2, "sname": "张二", "score": 100 }, { "_id": "5e847ab25eb945cf00a5884204297ed8", "class_id": 2, "sname": "李二", "score": 80 } ] } ] } ``` 接下来我们继续优化代码,直接返回学生的平均分数。 ### 3、直接返回学生成绩平均值 如果想要在被连接的表格中(本课程中的 student)做聚合操作,就用 **pipeline** 方法: ```js .lookup({ from: 'student', pipeline: $.pipeline() .group({ _id: null, score: $.avg('$score') }) .done(), as: 'stu' }) .match({ teacher:"徐老师" }) .end() ``` 现在输出的数据是这样的: ```json { "list": [ { "_id": "5e847ab25eb9428600a512352fa6c7c4", "id": 2, "teacher": "徐老师", "cname": "二班", "stu": [{ "_id": null, "score": 90 }] } ] } ``` 但是现在输出的数据有点复杂,如果只想显示 **teacher** 和 **score** 这两个值,我们再进行下面的操作。 ### 4、只显示 teacher 和 score 这两个值 我们使用 [replaceRoot](/api-reference/server/node-sdk/database/aggregate/stages/replaceRoot)、[mergeObjects](/api-reference/server/node-sdk/database/aggregate/operators/mergeObjects.md) 和 [project](/api-reference/server/node-sdk/database/aggregate/stages/project.md) 进行最后的处理: ```js .lookup({ from: 'student', pipeline: $.pipeline() .group({ _id: null, score: $.avg('$score') }) .done(), as: 'stu' }) .match({ teacher:"徐老师" }) .replaceRoot({ newRoot: $.mergeObjects([$.arrayElemAt(['$stu', 0]), '$$ROOT']) }) .project({ _id:0, teacher:1, score:1 }) .end() ``` 现在输出的数据是这样的: ```json { "list": [{ "score": 90, "teacher": "徐老师" }] } ``` ## 相关文档 - [数据库聚合搜索](/database/aggregate) --- ## 获取、传输微信开放数据 # 获取、传输微信开放数据 ## 概述 微信开放了一系列的前端接口用于获取微信的开放数据,考虑到开发者服务端也需要获取这些开放数据,微信提供了两种获取方式: 1. 传统方案:开发者后台校验与解密开放数据 2. 云开发:云调用直接获取开放数据 本文将介绍第二种方式。 参考:[服务端获取开放数据](https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/signature.html)。 ## 方案对比:传统方案 vs 云开发 ![](https://main.qcloudimg.com/raw/1a535499ed7274cb05337eb70508e9e5.png) ## 代码示例 获取开放数据的接口,如果涉及到敏感数据(如 [`wx.getWeRunData()`](https://developers.weixin.qq.com/miniprogram/dev/api/open-api/werun/wx.getWeRunData.html)),接口的明文内容将不包含这些敏感数据,而是在返回的接口中包含对应敏感数据的 `cloudID` 字段,数据可以通过云函数获取。完整流程如下: ### 第一步:获取 cloudID 使用 2.7.0 或以上版本的基础库,如果小程序已开通云开发,在开放数据接口的返回值中可以通过 `cloudID` 字段获取(与 `encryptedData` 同级),`cloudID` 有效期五分钟。 以[获取用户微信运动步数](https://developers.weixin.qq.com/miniprogram/dev/api/open-api/werun/wx.getWeRunData.html)为例: ```js wx.getWeRunData({ success(res) { const cloudID = res.cloudID; // ... }, }); ``` ### 第二步:调用云函数 调用云函数时,对传入的 `data` 参数,如果有顶层字段的值为通过 `wx.cloud.CloudID` 构造的 `cloudID`,则调用云函数时,这些字段的值会被替换为 `cloudID` 对应的开放数据,一次调用最多可替换 5 个 `cloudID`。 示例: 在小程序获取到 `cloudID` 之后发起调用: ```js wx.getWeRunData({ success(res) { const id = res.cloudID; wx.cloud.callFunction({ name: "myFunction", data: { weRunData: wx.cloud.CloudID(id), // 这个 CloudID 值到云函数端会被替换, obj: { shareInfo: wx.cloud.CloudID("yyy"), // 非顶层 CloudID,不会被替换 }, }, }); }, }); ``` 在云函数收到的 `event` 示例: ```json // event { // weRunData 的值已被替换为开放数据 "weRunData": { "cloudID": "xxx", "data": { "stepInfoList": [ { "step": 5000, "timestamp": 1554814312 } ], "watermark": { "appid": "wx1111111111", "timestamp": 1554815786 } } }, "obj": { // 非顶层字段维持原样 "shareInfo": "yyy" } } ``` 如果 `cloudID` 非法或过期,则在 `event` 中获取得到的将是一个有包含错误码、错误信息和原始 `cloudID` 的对象。过期 `cloudID` 换取结果示例: ```json // event { "weRunData": { "cloudID": "xxx", "errCode": -601006, "errMsg": "cloudID expired." } // ... } ``` ## 相关文档 - [服务端获取微信开放数据](https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/signature.html) - [小程序开放接口文档](https://developers.weixin.qq.com/miniprogram/dev/api/open-api/login/wx.login.html) --- ## 目录 # 目录 ## CloudBase 扩展 - [在云函数内使用 Redis 扩展](/practices/use-redis-extension) ## CloudBase 数据库 - [从 MySQL/MongoDB 迁移数据至 CloudBase 数据库](/practices/mysql-mongodb-migrate) - [CloudBase 数据库实现联表+聚合查询](/practices/database-lookup.md) ## 微信生态 - [使用云调用打通微信支付](/practices/use-wechat-pay) - [接收、推送微信消息](/practices/use-wechat-message.md) - [获取、传输微信开放数据](/practices/get-wechat-open-data) --- ## 登录方式实践教程 import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # 登录方式实践教程 云开发 CloudBase 提供了跨平台的登录认证功能,可基于此构建用户体系,包括匿名登录、邮箱登录、微信授权登录、自定义登录、用户名密码登录以及手机短信验证码登录。 ## 前提条件 [开通环境](/quick-start/create-env) 且计费模式选择**按量计费**。 ## 登录认证方式 云开发 CloudBase 提供以下登录认证方式供不同的用户场景使用: | 登录类型 | 场景 | | ------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- | | [未登录](/authentication/method/non-login) | 允许未登录后,用户将不需要登录即可访问应用。 | | [匿名登录](/authentication/method/anonymous) | 用户以临时的匿名身份登录云开发,无需注册。 | | [邮箱登录](/authentication/method/email-login) | 用户使用自己的邮箱+密码登录。 | | [微信授权登录](/authentication/method/wechat-login) | 经**微信公众平台**授权的**公众号网页**。经**微信开放平台**用授权的**网站**(需要认证)。 | | [自定义登录](/authentication/method/custom-login) | 开发者可以完全接管登录流程,例如与自有的账号体系打通、自定义登录逻辑等。 | | [用户名密码登录](/authentication/method/username-login) | 用户使用自己的用户名和密码登录。 | | [短信验证码登录](/authentication/method/sms-login) | 用户使用自己的手机号和验证码登录。 | ## 登录类型 [](id:non-login) ### 未登录 1. 登录 [云开发 CloudBase 控制台](https://console.cloud.tencent.com/tcb),在 [登录授权](https://console.cloud.tencent.com/tcb/env/login) 中,将未登录一栏打开。 2. 进入**环境** > **安全配置**页面,单击**添加域名**。 3. 设置自定义安全规则,放通未登录访问。 4. 初始化 SDK 发起调用。更多详情请参见 [使用流程](/authentication/method/non-login)。 [](id:anonymous) ### 匿名登录 1. 登录 [云开发 CloudBase 控制台](https://console.cloud.tencent.com/tcb),在 [登录授权](https://console.cloud.tencent.com/tcb/env/login) 页面中,将**匿名登录**一栏打开,开启匿名登录。 ![](https://qcloudimg.tencent-cloud.cn/raw/12b68d4a0693d9ee8c57eb3dce0d4e8d.png) 2. 进入**环境** > **安全配置**页面,单击**添加域名**。 ![](https://qcloudimg.tencent-cloud.cn/raw/6e7b4d5ef761ba6f8ef1362db10b4f3f.png) 3. 登录流程编写。 ```javascript import cloudbase from '@cloudbase/js-sdk'; const app = cloudbase.init({ env: 'xxxx-yyy'; //此处为环境 ID }); const auth = app.auth(); async function login(){ await auth.anonymousAuthProvider().signIn(); // 匿名登录成功检测登录状态isAnonymous字段为true const loginState = await auth.getLoginState(); console.log(loginState.isAnonymousAuth); // true } login(); ``` ```html 会议管理系统登录 匿名登录 import cloudbase from "@cloudbase/js-sdk"; const app = cloudbase.init({ env: "xxxx-yyy", //此处为环境 ID }); export default { name: "login", data() { return {}; }, methods: { onasy() { const app = this.$cloudbase; app .auth({ persistence: "session", }) .anonymousAuthProvider() .signIn() .then((res) => { console.log(res); this.$message({ message: "登录成功", type: "success", }); }) .catch((err) => { console.log(err); this.$message({ message: "请检查输入" + err, type: "warning", }); }); }, }, }; .block { width: 40%; margin: 50px auto; } .title { margin-left: 30px; border-left: 5px solid rgb(3, 89, 202); padding-left: 10px; } ``` ```js // The Vue build version to load with the `import` command // (runtime-only or standalone) has been set in webpack.base.conf with an alias. import Vue from "vue"; import App from "./App"; import VueRouter from "vue-router"; import router from "./router"; import ElementUI from "element-ui"; import "element-ui/lib/theme-chalk/index.css"; import Cloudbase from "@cloudbase/vue-provider"; Vue.use(Cloudbase, { env: "xxxx-yyy", //此处为环境 ID }); Vue.use(VueRouter); Vue.use(ElementUI); Vue.config.productionTip = false; import cloudbase from "@cloudbase/js-sdk"; const app = cloudbase.init({ env: "xxxx-yyy", //此处为环境 ID }); /* eslint-disable no-new */ new Vue({ el: "#app", router, render: (h) => h(App), }); ``` 匿名登录效果如下图所示: [](id:email) ### 邮箱登录 1. 进入 [云开发 CloudBase 控制台](https://console.cloud.tencent.com/tcb),在 [登录授权](https://console.cloud.tencent.com/tcb/env/login) 设置页面中,开启邮箱登录。 ![](https://qcloudimg.tencent-cloud.cn/raw/da155ac116ab5a8a6f2890a9e8c4e25b.png) 2. 单击**配置发件人**,填入您邮箱的 **SMTP 账号信息**。 3. 单击**应用配置**,设置您的**应用名称**和**自动跳转链接**。 4. 配置成功邮箱会收到测试邮件。 ![](https://qcloudimg.tencent-cloud.cn/raw/8694ce3b54359221112af1c9b1c043b8.png) 5. 示例代码如下所示: ```js import cloudbase from "@cloudbase/js-sdk"; const app = cloudbase.init({ env: "your-env-id", }); ``` ```js app .auth() .signUpWithEmailAndPassword(email, password) .then(() => { // 发送验证邮件成功 }); ``` ```js app .auth() .signInWithEmailAndPassword(email, password) .then((loginState) => { // 登录成功 }); ``` ```html 会议管理系统登录 立即登录 注册 import cloudbase from "@cloudbase/js-sdk"; const app = cloudbase.init({ env: "your-env-id", }); export default { name: "login", data() { return { form: { email: "", password: "", }, }; }, methods: { onSubmit() { const app = this.$cloudbase; app .auth() .signInWithEmailAndPassword(this.form.email, this.form.password) .then((loginState) => { console.log(loginState); this.$message({ message: "登录成功", type: "success", }); }) .catch((err) => { console.log(err); this.$message({ message: "请检查输入", type: "warning", }); }); }, onRegister() { const app = this.$cloudbase; app .auth() .signUpWithEmailAndPassword(this.form.email, this.form.password) .then((res) => { this.$message({ message: "注册成功", type: "success", }); }) .catch((err) => { console.log(err); this.$message({ message: "请检查输入", type: "warning", }); }); }, }, }; .block { width: 40%; margin: 50px auto; } .title { margin-left: 30px; border-left: 5px solid rgb(3, 89, 202); padding-left: 10px; } ``` [](id:wechat-login) ### 微信公众号登录 #### 前提条件 - 在 [注册公众号](https://mp.weixin.qq.com/cgi-bin/registermidpage?action=index) 页面,已成功注册**服务号**(“订阅号”没有“网页授权”接口的权限)。 - 登录新注册的**服务号**,进入**设置** > **基本信息** > **微信认证**栏,完成微信认证。 - 完成公众号添加网页授权域名。 - 进入**开发** > **基础配置**页面获取服务号的 AppId 与 AppSecret。 #### 操作步骤 1. 登录 [云开发 CloudBase 控制台](https://console.cloud.tencent.com/tcb),在 [登录授权](https://console.cloud.tencent.com/tcb/env/login) 中单击开启**微信公众号**登录授权。 2. 单击**启用按钮**后输入对应的 AppId 和 AppSecret。 3. 进入**环境** > **安全配置**页面,单击**添加安全域名**。 4. 示例代码如下所示: ```js import cloudbase from "@cloudbase/js-sdk"; const app = cloudbase.init({ env: "your-env-id", }); ``` ```js const auth = app.auth(); const provider = auth.weixinAuthProvider({ appid: "...", scope: "xxxx" }); async function login() { // 1. 建议登录前先判断当前是否已经登录 const loginState = await auth.getLoginState(); if (!loginState) { // 2. 调用微信登录API provider.getRedirectResult().then((loginState) => { if (loginState) { // 登录成功,本地已存在登录态 } else { // 未登录,唤起微信登录 provider.signInWithRedirect(); } }); } } login(); ``` ```html 会议管理系统登录 微信公众号登录 import cloudbase from "@cloudbase/js-sdk"; const app = cloudbase.init({ env: "your-env-id" }); export default { name: "login", data() { return { }; }, methods: { onWechat(){ const app = this.$cloudbase; const auth = app.auth(); const provider = auth.weixinAuthProvider({ appid: "your-wx-id", scope: "snsapi_userinfo", }); async function login() { // 1. 建议登录前先判断当前是否已经登录 const loginState = await auth.getLoginState(); if (!loginState) { // 2. 调用微信登录API provider.getRedirectResult().then((loginState) => { if (loginState) { // 登录成功,本地已存在登录态 } else { // 未登录,唤起微信登录 provider.signInWithRedirect(); } }); } } login(); }, }, }; .block { width: 40%; margin: 50px auto; } .title { margin-left: 30px; border-left: 5px solid rgb(3, 89, 202); padding-left: 10px; } ``` [](id:wechatplatform-login) ### 微信开放平台登录 #### 前提条件 - 完成 [微信开放平台](https://open.weixin.qq.com/) 的注册。 - 登录新注册的微信开放平台,进入 **账号中心** > **开发者资质认证**页面完成申请**微信认证**。 - 在微信开放平台成功创建网站应用。 - 获取微信开放平台网站应用的 AppId 与 AppSecret。 #### 操作步骤 1. 登录 [云开发 CloudBase 控制台](https://console.cloud.tencent.com/tcb),在 [登录授权](https://console.cloud.tencent.com/tcb/env/login) 中单击开启**微信开放平台**登录授权。 2. 单击**启用按钮**后输入对应的 AppId 和 AppSecret。 3. 将云开发的 SDK 添加到您的 Web 应用。 ```html const app = cloudbase.init({ // 您的环境id env: "your-env-id", }); ``` :::tip 说明 复制下方的代码片段,将其粘贴到您的 HTML 代码底部,其他 script 标记之前。 ::: 4. 示例代码如下所示: ```js const auth = app.auth(); const provider = auth.weixinAuthProvider({ appid: "...", scope: "xxxx" }); async function login() { // 1. 建议登录前先判断当前是否已经登录 const loginState = await auth.getLoginState(); if (!loginState) { // 2. 调用微信登录API provider.getRedirectResult().then((loginState) => { if (loginState) { // 登录成功,本地已存在登录态 } else { // 未登录,唤起微信登录 provider.signInWithRedirect(); } }); } } login(); ``` ```html 会议管理系统登录 微信开放平台登录 import cloudbase from "@cloudbase/js-sdk"; const app = cloudbase.init({ env: "your-env-id", }); export default { name: "login", data() { return {}; }, methods: { onWechatopen() { const app = this.$cloudbase; const auth = app.auth(); const provider = auth.weixinAuthProvider({ appid: "your-wx-id", scope: "snsapi_login", }); async function login() { // 1. 建议登录前先判断当前是否已经登录 const loginState = await auth.getLoginState(); if (!loginState) { // 2. 调用微信登录API provider .getRedirectResult() .then((loginState) => { if (loginState) { // 登录成功,本地已存在登录态 } else { // 未登录,唤起微信登录 provider.signInWithRedirect(); } }) .catch((err) => { console.log(err); }); } } login(); }, }, }; .block { width: 40%; margin: 50px auto; } .title { margin-left: 30px; border-left: 5px solid rgb(3, 89, 202); padding-left: 10px; } ``` [](id:custom-login) ### 自定义登录 自定义登录适用于开发者自行控制登录认证,并有自己的账户体系。 1. 登录 [云开发 CloudBase 控制台](https://console.cloud.tencent.com/tcb),在 [登录授权](https://console.cloud.tencent.com/tcb/env/login) 页面**自定义登录**栏中,单击**私钥下载**获取自定义登录私钥。 ![](https://qcloudimg.tencent-cloud.cn/raw/56af4a5af4288bb318d2453f69ad5a59.png) :::tip 说明 私钥是一份携带有 JSON 数据的文件,请将下载或复制的私钥文件保存到您的服务器或者云函数中,假设路径为`/path/to/your/tcb_custom_login.json`。 私钥文件是证明管理员身份的重要凭证,请务必妥善保存,避免泄漏。 每次生成私钥文件都会使之前生成的私钥文件在 2 小时后失效。 ::: 2. 调用 CloudBase 服务端 SDK,在初始化时传入自定义登录私钥,随后便可以签发出 Ticket,并返回至用户端。 ```js const cloudbase = require("@cloudbase/node-sdk"); // 1. 初始化 SDK const app = cloudbase.init({ env: "your-env-id", // 传入自定义登录私钥 credentials: require("/path/to/your/tcb_custom_login.json") }); // 2. 开发者自定义的用户唯一身份标识 const customUserId = "your-customUserId"; // 3. 创建ticket const ticket = app.auth().createTicket(customUserId); // 4. 将ticket返回至客户端return ticket; ``` :::tip 说明 开发者也可以编写一个**云函数**用于生成 Ticket,并为其设置 HTTP 访问服务,随后用户端便可以通过 HTTP 请求的形式获取 Ticket,详细的方案请参见 [使用 HTTP 访问云函数](/service/access-cloud-function)。 ::: 3. 用户端应用获取到 Ticket 之后,便可以使用 Ticket 登录 CloudBase。通过调用客户端 SDK 提供的 `auth.signInWithTicket()` 登录 CloudBase。 ```js import cloudbase from "@cloudbase/js-sdk"; const app = cloudbase.init({ env: "your-env-id" }); const auth = app.auth(); async function login() { // 1. 建议登录前检查当前是否已经登录 const loginState = await auth.getLoginState(); if (!loginState) { // 2. 请求开发者自有服务接口获取ticket const ticket = await fetch("..."); // 3. 登录 CloudBase await auth.customAuthProvider().signIn(ticket); } } login(); ``` 整体流程示意如下: [](id:username-login) ### 用户名密码登录 1. 登录 [云开发 CloudBase 控制台](https://console.cloud.tencent.com/tcb),在 [登录授权](https://console.cloud.tencent.com/tcb/env/login) 中单击开启**用户名密码登录**。 2. 初始化 SDK。 ```js import cloudbase from "@cloudbase/js-sdk"; const app = cloudbase.init({ env: "your-env-id", }); ``` 3. 使用其他方式进行登录。 :::tip 说明 绑定用户名之前,用户需要先使用其他方式进行登录,例如邮箱登录、微信公众号登录等,但**不包括匿名登录**。 ::: 下面以 邮箱登录 为例: ```js const auth = app.auth(); await auth.signInWithEmailAndPassword(email, password); // 邮箱登录 ``` 4. 绑定用户名。 ```js const auth = app.auth(); if (!(await auth.isUsernameRegistered(username))) { // 检查用户名是否绑定过 await auth.currentUser.updateUsername(username); // 绑定用户名 } ``` 5. 示例代码如下所示: ```js import cloudbase from "@cloudbase/js-sdk"; const app = cloudbase.init({ env: "your-env-id", }); ``` ```js const auth = app.auth(); const loginState = await auth.signInWithUsernameAndPassword(username, password); // 用户名密码登录 ``` ```html 会议管理系统登录 立即登录 绑定用户名流程 立即登录 import cloudbase from "@cloudbase/js-sdk"; const app = cloudbase.init({ env: "your-env-id", }); export default { name: "login", data() { return { form: { email: "", password: "", }, form1: { phone: "", yz: "", password: "", }, form2: { email: "", password: "", username: "", }, }; }, methods: { onSubmit() { const app = this.$cloudbase; app .auth() .signInWithEmailAndPassword(this.form.email, this.form.password) .then((loginState) => { console.log(loginState); this.$message({ message: "登录成功", type: "success", }); }) .catch((err) => { console.log(err); this.$message({ message: "请检查输入", type: "warning", }); }); }, onSubmit1() { const auth1 = this.$cloudbase.auth(); if (auth1.hasLoginState()) { console.log("已经登录"); console.log(auth1); if (!auth1.isUsernameRegistered(this.form2.username)) { // 检查用户名是否绑定过 console.log("没绑定"); auth1.currentUser.updateUsername(this.form2.username); // 绑定用户名 } else { console.log("绑定了"); } } else { console.log("登录"); } }, }, }; .block { width: 40%; margin: 50px auto; } .title { margin-left: 30px; border-left: 5px solid rgb(3, 89, 202); padding-left: 10px; } ``` [](id:sms-login) ### 短信验证码登录 1. 登录 [云开发 CloudBase 控制台](https://console.cloud.tencent.com/tcb),在 [登录授权](https://console.cloud.tencent.com/tcb/env/login) 中单击开启**短信验证码**登录。 2. 单击操作栏下的**签名配置**,输入相应参数后单击**保存**。 3. 初始化 SDK。 ```js import cloudbase from "@cloudbase/js-sdk"; const app = cloudbase.init({ env: "your-env-id", }); ``` 4. 使用手机号注册账号,首先需要用户填入自己的手机号,然后调用 SDK 的发送短信验证码接口。 ```js //发送验证码 app .auth() .sendPhoneCode("手机号") .then((res) => { console.log("验证码发送成功"); }); // 验证码+密码注册 app .auth() .signUpWithPhoneCode("手机号", "六位验证码", "自定义密码") .then((res) => { console.log("注册成功"); }); ``` 5. 手机密码和短信验证码登录方法如下所示: ```javascript app .auth() .signInWithPhoneCodeOrPassword({ phoneNumber: "手机号", phoneCode: "验证码", }) .then((res) => { // 登录成功 }); ``` ```javascript app .auth() .signInWithPhoneCodeOrPassword({ phoneNumber: "手机号", password: "密码", }) .then((res) => { // 登录成功 }); ``` --- ## 云开发多环境管理实践 # 云开发多环境管理实践 ## 背景 云开发提供环境复制能力,方便开发者进行多环境下项目开发。 ## 环境资源复制实践 (A -> B) ### 函数资源 1. 云函数代码从 **A** 环境对应函数拷贝,注意代码中写死的环境 ID **A**需手动修改为 **B** 若函数中使用 Node SDK 且 使用当前环境,建议写法 ```javascript const cloudbase = require("@cloudbase/node-sdk") const app = cloudbase.init({ env: cloudbase.SYMBOL_CURRENT_ENV // 自动选取当前环境 }) ``` 2. 函数属性配置如 内存,超时时间,环境变量,定时触发器,vpc,公网访问配置,函数对应云接入配置&鉴权,CLS 日志配置均拷贝,无需开发者操作。 3. 函数层不会复制,需手动在 **B** 中新建层。 ### 数据库资源 1. 数据库复制时仅在新环境中创建出同名的空集合,表数据需用户在控制台中手动导 (**A**环境库导出,导入到**B**环境库)。 2. 数据库安全规则,索引设置均拷贝,开发者无需操作。 ### 云存储资源 1. 云存储配置如权限配置,缓存配置均拷贝,无需用户操作 2. 具体的文件资源,需用户手动导(A 环境导出文件资源,导入到 B 环境) 推荐实践 - 安装 cloudbase cli 工具并登陆 ```shell npm i -g @cloudbase/cli tcb login ``` - 下载**A** 环境全部文件至本地 ``` # 下载全部文件 tcb storage download / localPath --dir -e A ``` - 上传本地文件至**B**环境 ``` tcb storage upload localPath -e B ``` ## 多环境项目开发实践 ### 1. 开发环境,生产环境区分 基于环境复制能力,可以快速搭建开发 **dev** 和生产 **prod** 两套环境(免去了重复建表,重复建函数的操作)。 > https://developers.weixin.qq.com/miniprogram/dev/wxcloud/basis/concepts/environment.html #### 操作实践 1. 云函数端使用**SDK** 时采用取动态环境写法(类似函数资源复制),避免写死环境 ID **小程序侧示例** ``` const cloud = require('wx-server-sdk') cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV }) ``` **腾讯云侧示例** ``` const cloudbase = require("@cloudbase/node-sdk") const app = cloudbase.init({ env: cloudbase.SYMBOL_CURRENT_ENV // 自动选取当前环境 }) ``` 2. 客户端在开发及生产环境下,分别指定对应环境 ID 即可 ``` wx.cloud.init({ // 此处请填入环境 ID, 环境 ID 可打开云控制台查看 env: config.ENV // dev or prod }) ``` > 更进一步,为免去人为操作带来的风险,可通过工程化的方式配置环境 ID,如 开发模式下配置 dev 环境 ID,生产模式下配置为 prod 环境 ID,具体实现此处不展开。 ### 2. 项目协同开发 同环境下,多人协作开发时容易产生脏数据问题,各开发人员可基于项目初始环境复制出各自开发环境,各环境下调试开发互不影响。 --- ## 从 MySQL/MongoDB 迁移数据至 CloudBase 数据库 # 从 MySQL/MongoDB 迁移数据至 CloudBase 数据库 ## 迁移说明 本篇文章从 MySQL、MongoDB 迁移到云开发数据库,其他数据库迁移也都大同小异。 迁移大致分为以下几步: 1. 从 MySQL、MongoDB 将数据库导出为 JSON 或 CSV 格式 2. 创建一个云开发环境 3. 到云开发数据库新建一个集合 4. 在集合内导入 JSON 或 CSV 格式文件 ## 导出 ### 导出 MySQL 数据 下面的流程中,我们使用 [Navicat for MySQL](https://www.navicat.com.cn/products/navicat-for-mysql) 进行导出。您也可以使用其它 MySQL 导出工具。 #### 导出为 CSV 格式 选中表后进行导出 ![img](https://ask.qcloudimg.com/http-save/yehe-4744530/aj5qb37cx2.png) 类型中选择 csv 格式 ![img](https://ask.qcloudimg.com/http-save/yehe-4744530/c86q6xgin0.png) 注:在第 4 步时,我们需要勾选包含列的标题 ![img](https://ask.qcloudimg.com/http-save/yehe-4744530/cjzp9s4f4k.png) 导出后的 csv 文件内容 第一行为所有键名,余下的每一行则是与首行键名相对应的键值记录。类似这样: ![img](https://ask.qcloudimg.com/http-save/yehe-4744530/h426isb11c.png) #### 导出为 JSON 格式 同样的我们将选中的表进行导出为 json 格式: ![img](https://ask.qcloudimg.com/http-save/yehe-4744530/h4avkl4t6q.png) 剩余步骤全部选择默认即可。 导出后的样子? ![img](https://ask.qcloudimg.com/http-save/yehe-4744530/5twlr5t2lr.png) 我们将数组去除,最后是这样? ![img](https://ask.qcloudimg.com/http-save/yehe-4744530/8y1mhlzmlx.png) ### 导出 MongoDB 数据 首先我们先启动 mongod 服务: ![img](https://ask.qcloudimg.com/http-save/yehe-4744530/i3dwewqy15.png) 启动后此终端不要关闭。 #### 导出为 CSV 格式 新打开一个终端,输入以下命令 ``` mongoexport -db --collection --type csv -f -o ``` 更详细的参数说明,请参考 [MongoDB 文档](https://docs.mongodb.com/v3.6/reference/program/mongoexport/)。 注:导出 csv 格式时需要指定导出的字段名,否则会报错: csv mode requires a field list 导出后的样子: ![img](https://ask.qcloudimg.com/http-save/yehe-4744530/c9dqnyn06v.png) #### 导出为 JSON 格式 新打开一个终端,输入以下命令: ``` mongoexport -db --collection -o ``` 更详细的参数说明,请参考 [MongoDB 文档](https://docs.mongodb.com/v3.6/reference/program/mongoexport/)。 导出后的样子: ![img](https://ask.qcloudimg.com/http-save/yehe-4744530/t8zrj7rdc7.png) ## 导入 ### 新建云环境 如果已有云环境,可直接跳过这一步打开云开发控制台新建云环境: ![img](https://ask.qcloudimg.com/http-save/yehe-4744530/i9homo4kr0.png) 新建环境后耐心等待 2 分钟环境初始化过程。 ### 数据库导入 点击添加集合来创建一个集合: ![img](https://ask.qcloudimg.com/http-save/yehe-4744530/ek0sedvkv0.png) 新建之后我们点进去,并进行导入操作: ![img](https://ask.qcloudimg.com/http-save/yehe-4744530/b3r230zq4k.png) 选择我们之前导出的 CSV 或 JSON 格式文件。 :::tip 注意 这里有两种冲突处理模式:Insert 和 Upsert - Insert 模式会在导入时总是插入新记录,同一文件不能存在重复的 \_id 字段,或与数据库已有记录相同的 \_id 字段。**如果希望已经存在的数据不被覆盖掉,应该 Insert 模式。** - Upsert 模式会判断有无该条记录,如果有则更新该条记录,否则就插入一条新记录。**如果不希望产生冗余重复的数据,应该使用 Upsert 模式。** ::: 这里我们选择 Upsert 模式: ![img](https://ask.qcloudimg.com/http-save/yehe-4744530/lsh807v3m3.png) 导入过程完毕后,数据库内可以看到导入的数据: ![img](https://ask.qcloudimg.com/http-save/yehe-4744530/2wx5fyxq6a.png) --- ## 预约点餐小程序开发 import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # 预约点餐小程序开发 ## 概述 本文介绍如何用云开发相关能力,快速搭建预约点餐系统。 :::tip 说明 本实例教程所涉及到的相关源码材料,均已得到相应授权。 ::: ### 准备工作 1. [注册腾讯云](https://cloud.tencent.com/document/product/378/17985)。 2. 开通了云开发的小程序,详情请参见 [小程序端快速入门](/quick-start/mini-program/introduce)。 3. 进入**云开发控制台** > **设置** > **拓展功能页面**,单击开通**内容管理**和**内容安全**。 ![](https://qcloudimg.tencent-cloud.cn/raw/238fd1c03496b1c0e88711d4bf8bd526.png) ### 操作流程 具体操作流程可分为以下 6 步。更多详情可参见 [示例代码](https://github.com/ZiTao-Liu/Canteen-management-system)。 - [搭建轮播图与公告](#步骤1搭建轮播图与公告) - [搭建首页热门栏目](#步骤2搭建首页热门栏目) - [搭建我的页面](#步骤3搭建我的页面) - [搭建攻略页面](#步骤4搭建攻略页面) - [搭建店铺页面](#步骤5搭建店铺页面) - [搭建订单页面](#步骤6搭建订单页面) ## 步骤1:搭建轮播图与公告 本文主要围绕主页的 index 页面、[云开发内容管理](https://developers.weixin.qq.com/miniprogram/dev/wxcloud/guide/extensions/cms/introduction.html) 和 [云开发数据库](https://developers.weixin.qq.com/miniprogram/dev/wxcloud/guide/database.html) 进行讲解,更多 index 代码细节可参见 [index 页面](https://github.com/ZiTao-Liu/Canteen-management-system/tree/main/miniprogram/pages/index)。 ### 步骤 1:开通内容管理 1. 首先进入**云开发控制台** > **内容管理**页面,单击**开通**,并设置账号密码。内容管理创建需要一定的时间请安心等待。 ![](https://qcloudimg.tencent-cloud.cn/raw/922f8781f613c1eaefd5ba2b2ed2cf9b.png) 2. 在创建成功之后返回**内容管理**页面,单击**访问地址**即可访问**内容管理平台**。 ![](https://qcloudimg.tencent-cloud.cn/raw/51c7d5c556a4dbe9a8d1d4ff94927013.png) 3. 输入登录账号和密码,进入**内容管理(CMS)**后台,单击**创建新项目**这里我们起名为预约点餐管理系统。 ![](https://qcloudimg.tencent-cloud.cn/raw/39c60d29464734b173a89198624396b3.png) [](id:step2) ### 步骤 2:搭建轮播图 1. 进入上述新建的**预约点餐管理系统**,进入**内容模型**页面,单击**新建模型**,这里我们设置**展示名称**为**轮播图**,**数据库名**为 **banner**。设置完成后单击**创建**。 ![](https://qcloudimg.tencent-cloud.cn/raw/1197d13ab0a32a0775833f71119c4f90.png) :::caution 注意事项 更改**数据库名**会自动重命名原数据库,请谨慎操作。 ::: 2. 单击右侧**内容类型** > **图片**,进入**添加图片字段**页面,设置**展示名称**为**轮播图**,**数据库字段名**为 **photo**。 ![](https://qcloudimg.tencent-cloud.cn/raw/dd32576a1b5b0a101aace59831185317.png) 单击**添加**后完成**内容模型**的创建。 ![](https://qcloudimg.tencent-cloud.cn/raw/f11919caa88f0f8825a7db71fdfd23f4.png) 3. 进入**内容集合** > **轮播图**页面,单击**新建**。 ![](https://qcloudimg.tencent-cloud.cn/raw/6dd08d23b09be400138b82a05caf2000.png) 拖动图片并单击**创建**后完成轮播图片的上传,这样一个轮播图的内容模型我们就创建完成了。 ![](https://qcloudimg.tencent-cloud.cn/raw/fa4447438a445b482d96209dea56ea18.png) 4. 通过上面操作后,相应的会在**云开发控制台**生成 **banner** 数据库以及上述导入的图片数据。进入**云开发控制台** > **数据库** > **banner** > **数据权限**页面,将数据库数据权限改为**所有用户可读,仅创建者可读写**,这样所有用户就可以看到数据了。 ![](https://qcloudimg.tencent-cloud.cn/raw/e6357bdfbb9bbf0caf288b144a62da7b.png) 4. 接下来在 pages/index 中开始编写轮播图。这里我们可以参见 [swiper 文档](https://developers.weixin.qq.com/miniprogram/dev/component/swiper.html),帮助我们绑定数据,这样我们使用 wx:for 进行列表绑定。 5. 参数 env 可以在**微信开发者工具** > **云开发控制台**里获取。 ```js // pages/index/index.js wx.cloud.init({ env: '您的环境ID', traceUser: true, }) const db = wx.cloud.database() Page({ /** * 页面的初始数据 */ data: { mgList: '' }, /** * 生命周期函数--监听页面加载 */ onLoad: function (options) { //这里执行的是在页面首次加载时候在banner数据库获取数据,并将他们存在mgList里面 db.collection("banner").get({ success: res => { console.log(res) this.setData({ mgList: res.data }) } }) } }) ``` > - 在组件上使用 `wx:for` 控制属性绑定一个数组,即可使用数组中各项的数据重复渲染该组件。 - 默认数组的当前项的下标变量名默认为 `index`,数组当前项的变量名默认为 `item*` - 使用 `wx:for-item` 可以指定数组当前元素的变量名, 6. 通过以下代码绑定 mgList 数据。 ```xml ``` ```css /* pages/index/index.wxss */ .banner { width: 100%; height: 350rpx; } .swip_main { width: 100%; height: 100%; } ``` 7. 保存运行编译之后,可以看到轮播图。 :::tip 说明 如果出现运行编译后无法加载轮播图,请在**微信开发者工具**单击右上角**详情**,进入**本地设置**页面,尝试切换**调试基础库**为较低版本即可。 ::: ### 步骤 3:搭建通知公告 1. 参照 [步骤 2](#step2) 创建**通知公告**内容模型。 2. 其中**通知公告**内容模型数据库名设置为 **tz**。新增的**内容类型** > **单行字符串**数据库字段名设置为 **text**。 ![](https://qcloudimg.tencent-cloud.cn/raw/0bfa1c2df76d2107a8710bd7aa469fb3.png) 3. 进入**内容集合** > **通知公告**单击**新建**创建公告内容。 ![](https://qcloudimg.tencent-cloud.cn/raw/3483a1a4228e806592888bce785cbe99.png) 4. 通过以下代码绑定 mgList 数据。 ```xml {{item.text}} ``` ```css /* pages/index/index.wxss */ .banner { width: 100%; height: 350rpx; } .swip_main { width: 100%; height: 100%; } .tz { width: 100%; height: 100rpx; background-color: rgb(224, 222, 213); } .tz_zp { width: 80rpx; height: 80rpx; margin-top: 10rpx; margin-left: 40rpx; float: left; } .tz_zp image { width: 100%; height: 100%; } .swiper-news-top { width: 600rpx; height: 80rpx; float: right; margin-top: 10rpx; margin-right: 30rpx; } .swiper_item { font-size: 28rpx; font-weight: 700; line-height: 80rpx; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; letter-spacing: 2px; text-align: center; } ``` ```js // pages/index/index.js wx.cloud.init({ env: '您的环境ID', traceUser: true, }) const db=wx.cloud.database() Page({ /** * 页面的初始数据 */ data: { mgList:'', msgList:'' }, /** * 生命周期函数--监听页面加载 */ onLoad: function (options) { db.collection("banner").get({ success:res=>{ console.log(res) this.setData({ mgList:res.data }) } }) db.collection("tz").get({ success:res=>{ console.log(res) this.setData({ msgList:res.data }) } }) }, ``` 5. 保存运行编译后即可。 ## 步骤2:搭建首页热门栏目 本文主要围绕主页的 index 页面和配置文件 app.json 进行讲解,更多 index 代码细节可参见 [index 页面](https://github.com/ZiTao-Liu/Canteen-management-system/tree/main/miniprogram/pages/index) 和配置文件 [app.json](https://github.com/ZiTao-Liu/Canteen-management-system/blob/main/miniprogram/app.json)。 ### 步骤 1:搭建底部导航栏 1. 在 app.json 的 pages 数组配置好相应页面。 2. 然后在 app.json 页面。通过设置 tabBar 配置底部导航栏。 ```json "pages": [ "pages/index/index", "pages/my/my", "pages/dp/dp", "pages/gltl/gltl", "pages/grxx/grxx", "pages/xgxx/xgxx", "pages/gywm/gywm", "pages/buzx/buzx", "pages/glxq/glxq", "pages/xpl/xpl", "pages/fbgl/fbgl", "pages/xdym/xdym", "pages/jqqt/jqqd", "pages/dingdan/dingdan", "pages/xd/xd", "pages/gwx/gwx", "pages/ddgl/ddgl", "pages/qccg/qccg", "pages/sjgl/sjgl", "pages/fbpl/fbpl" ], ``` ```json "tabBar": { "color": "#a9b7b7", "selectedColor": "#11cd6e", "borderStyle": "black", "list": [ { "pagePath": "pages/index/index", "iconPath": "images/font-ui/shouye.png", "selectedIconPath": "images/font-ui/shouye.png", "text": "首页" }, { "pagePath": "pages/dp/dp", "iconPath": "images/font-ui/dianpu.png", "selectedIconPath": "images/font-ui/dianpu.png", "text": "店铺" }, { "pagePath": "pages/dingdan/dingdan", "iconPath": "images/font-ui/dingdan.png", "selectedIconPath": "images/font-ui/dingdan.png", "text": "订单" }, { "pagePath": "pages/gltl/gltl", "iconPath": "images/font-ui/gonglve.png", "selectedIconPath": "images/font-ui/gonglve.png", "text": "攻略" }, { "pagePath": "pages/my/my", "iconPath": "images/font-ui/wode.png", "selectedIconPath": "images/font-ui/wode.png", "text": "我" } ] }, ``` 3. 将 tarBar 中相应的 UI 图片存到小程序 imges 目录中编译即可。 ### 步骤 2:搭建中部导航栏 1. 进入首页 index 目录,通过 index.wxml 和 index.wxss 编写前端页面首页导航栏。 ```xml {{item.text}} 东区食堂 西区食堂 每日优惠 南湖食堂 美食分享 ``` ```css .nav { width: 100%; height: 150rpx; } .nav-banner { height: 100%; width: 20%; background-color: azure; float: left; } .nav-banner-img { width: 100%; height: 75%; } .nav-banner-img image { width: 70%; height: 80%; padding: 10% 15%; } .nav-banner-text { text-align: center; margin-top: -10rpx; font-size: 26rpx; } ``` 2. 进入 index.js 页面,我们使用 wx.navigateTo(Object object) 跳转到应用内的某个页面,我们对导航栏给他点击事件,在用户在点击之后跳转到敬请期待页面。 ```js // index.js showwd:function(){ wx.navigateTo({ url: '../jqqd/jqqd', }) }, showtk:function(){ wx.switchTab({ url: '../gltl/gltl' }) }, ``` :::tip 说明 保留当前页面,跳转到应用内的某个页面。其中可使用 [wx.navigateBack](https://developers.weixin.qq.com/miniprogram/dev/api/route/wx.navigateBack.html) 返回到原页面。小程序中页面栈最多十层。 ::: ### 步骤 3:搭建首页热门美食栏目 1. 进入 CMS 内容管理控制台,新建**美食列表**内容模型,数据库名称设置为 **mslb**。 2. 进入新建的**美食列表**页面,如下设置内容集合: 内容类型 展示名称 数据库字段名 图片 附件照片 src 单行字符串 名称 name 单行字符串 简介 jj 单行字符串 地址 dz 单行字符串 btn1 btn1 单行字符串 btn2 btn2 单行字符串 btn3 btn3 > 更多 CMS 内容管理详细操作请参见 [搭建轮播图](https://cloud.tencent.com/document/product/876/71443#step2)。 3. 进入 index.wxml 页面,使用列表渲染 wx:for 进行列表展示。 ```xml 热门美食 查看更多 > {{item.name}} {{item.jj}} 地址:{{item.zd}} {{item.btn1}} {{item.btn2}} {{item.btn3}} {{item.btn4}} ``` 这里我们会发现有的时候 item.btn1 要是为空也会显示出来,我们可以改进一下,使用 wx:if 条件渲染。增加判断之后如果是空置就不显示这个按钮。 ```xml {{item.btn1}} {{item.btn2}} {{item.btn3}} ``` 最终效果如下: ## 步骤3:搭建我的页面 本文主要围绕我的页面 my 和 [云函数](https://developers.weixin.qq.com/miniprogram/dev/wxcloud/guide/functions.html) 进行讲解,更多代码细节可参见 [my 页面](https://github.com/ZiTao-Liu/Canteen-management-system/tree/main/miniprogram/pages/my)。 ### 步骤1:配置云函数 1. 右击**当前环境**文件夹,单击**新建 Node.js 云函数**,并将文件命名为 **open**。 ![](https://qcloudimg.tencent-cloud.cn/raw/fbc2d81502e939b58d4f9d423a139fce.png) 2. 在 open 云函数下,index.js 文件下编写获取 openid 的代码。 ```js // 云函数入口文件 const cloud = require('wx-server-sdk') cloud.init() // 云函数入口函数 exports.main = async (event, context) => { const wxContext = cloud.getWXContext() return { event, openid: wxContext.OPENID, appid: wxContext.APPID, unionid: wxContext.UNIONID, } } ``` :::tip 说明 从小程序端调用云函数时,开发者可以在云函数内使用 [`wx-server-sdk`](https://developers.weixin.qq.com/miniprogram/dev/wxcloud/guide/functions/wx-server-sdk.html) 提供的 [`getWXContext`](https://developers.weixin.qq.com/miniprogram/dev/wxcloud/reference-sdk-api/utils/Cloud.getWXContext.html) 方法获取到每次调用的上下文(`appid`、`openid` 等),无需维护复杂的鉴权机制,即可获取天然可信任的用户登录态(`openid`)。 ::: 3. 然后右击 open 文件夹,单击**上传并部署:云端安装依赖**,即完成了云函数的编写。 ![](https://qcloudimg.tencent-cloud.cn/raw/42162813a155c6eb9eabdf52cae913ee.png) ### 步骤2:搭建登录授权功能 1. 进入 app.js 初始化云开发。 ```js // app.js App({ onLaunch: function () { if (!wx.cloud) { console.error('请使用 2.2.3 或以上的基础库以使用云能力'); } else { wx.cloud.init({ // env 参数说明: // env 参数决定接下来小程序发起的云开发调用(wx.cloud.xxx)会默认请求到哪个云环境的资源 // 此处请填入环境 ID, 环境 ID 可打开云控制台查看 // 如不填则使用默认环境(第一个创建的环境) env: '环境ID', traceUser: true, }); } this.globalData = {}; }, globalData:{ userid:'' } }); ``` 2. 进入 my.js 在页面编写我的页面代码。在这里我们写一个点击事件,在用户点击我们绑定 getUserInfo 事件的按钮之后,我们调用获取用户信息。getopenid 是通过云函数获取用户 openid 方法。并将这个值存在 app.js 里面这样我们在其他页面可以直接进行调用。 ```js const app = getApp(); Page({ /** * 页面的初始数据 */ data: { username:"", openid: '', }, /** * 生命周期函数--监听页面加载 */ onLoad: function (options) { }, getUserInfo(e){ console.log(e); this.setData({ username:e.detail.userInfo.nickName }) }, getopenid(){ var that=this; wx.cloud.callFunction({ name: 'open', success:(res)=> { var usid = res.result.openid console.log(usid) this.setData({ openid:res.result.openid, }) getApp().globalData. userid=res.result.openid }, fail(res) { console.log("获取失败", res); } }) }, }) ``` 3. 进入 my.wxml 页面,添加判断登录状态代码,我们可以进行判断如果没有获取到提醒用户登录,如果获取到的 openid 为空我们显示授权登录版块。 ```xml 爱国、敬业、求实、创新 您还未授权登录 去授权登录 登录 ``` ## 步骤4:搭建攻略页面 本文主要围绕**攻略**页面进行讲解,更多代码细节可参见 [攻略列表](https://github.com/ZiTao-Liu/Canteen-management-system/tree/main/miniprogram/pages/gltl)、[攻略详情](https://github.com/ZiTao-Liu/Canteen-management-system/tree/main/miniprogram/pages/glxq) 、 [发布评论](https://github.com/ZiTao-Liu/Canteen-management-system/tree/main/miniprogram/pages/xpl) 和 [发布攻略](https://github.com/ZiTao-Liu/Canteen-management-system/tree/main/miniprogram/pages/fbpl)。 ### 步骤1:搭建攻略展示页 1. 进入 CMS 内容管理控制台,新建**攻略**内容模型,数据库名称设置为 **glpj**。 2. 进入新建的**攻略**页面,如下设置内容集合: 内容类型 展示名称 数据库字段名 图片 照片 photo 单行字符串 标题 title 日期与时间 时间 time 单行字符串 作者 user 数字 浏览量 lll 富文本 简介 xq :::tip 说明 更多 CMS 内容管理详细操作请参见 [搭建轮播图](https://cloud.tencent.com/document/product/876/71443#step2)。 ::: 3. 这里我们依然通过 wx:for 渲染出列表,并给他点击跳转事件,并将当前文章 ID 编号进行传递。 ```xml 攻略评论 发表 {{item.title}} {{item.user}} {{item.lll}}+ ``` ```js // pages/gltl/gltl.js wx.cloud.init({ env: '环境 ID', traceUser: true, }) const db=wx.cloud.database() Page({ /** * 页面的初始数据 */ data: { rmbs:'' }, /** * 生命周期函数--监听页面加载 */ onLoad: function (options) { db.collection("glpj").get().then(res=>{ console.log(res) this.setData({ rmbs:res.data }) }) }, showbs:function(e){ console.log(e.currentTarget.id) wx.navigateTo({ url:'/pages/glxq/glxq?list_id='+e.currentTarget.id, }) }, showtl:function(e){ wx.navigateTo({ url:'/pages/fbpl/fbpl', }) }, }) ``` ### 步骤2:搭建攻略详情及发表评论功能 1. 进入 CMS 内容管理控制台,新建**攻略评论**内容模型,数据库名称设置为 **glplgl**。 2. 进入新建的**攻略评论**页面,如下设置内容集合: 内容类型 展示名称 数据库字段名 单行字符串 用户 user 单行字符串 文字 text 单行字符串 用户名字 username 日期与时间 data data 单行字符串 plwz plwz :::tip 说明 更多 CMS 内容管理详细操作请参见 [搭建轮播图](https://cloud.tencent.com/document/product/876/71443#step2)。 ::: 3. **攻略详情**页面的逻辑及前端代码如下: ```js // pages/glxq/glxq.js wx.cloud.init({ env: '环境 ID', traceUser: true, }) const db=wx.cloud.database() Page({ /** * 页面的初始数据 */ data: { list_id:"", rmb:"" }, /** * 生命周期函数--监听页面加载 */ onLoad: function (options) { this.setData({ list_id:options.list_id }) console.log( this.data.list_id), /**/ db.collection("glpj").doc(this.data.list_id).get().then(res=>{ console.log(res) this.setData({ rmbs:res.data }) }) const _=db.command db.collection('glpj').doc(this.data.list_id).update({ data:{ lll:_.inc(1) } }) db.collection("glplgl").where({plwz:this.data.list_id}).get().then(res=>{ console.log(res) this.setData({ rmb:res.data }) }) }, /** * 生命周期函数--监听页面初次渲染完成 */ onReady: function () { }, /** * 生命周期函数--监听页面显示 */ onShow: function () { }, showbs:function(e){ console.log(e.currentTarget.id) wx.navigateTo({ url:'/pages/xpl/xpl?list_id='+e.currentTarget.id, }) }, }) ``` ```xml 发布时间:{{rmbs.time}} {{rmbs.lll}}+ 评论 去评论 {{item.username}} {{item.data}} {{item.text}} ``` 4. 在对应的**攻略详情**页面,单击**去评论**的时候我们需要获取到用户的 openid 和当前要发布评论的文章 ID。**去评论**的逻辑及前端代码如下: ```js // pages/xpl/xpl.js wx.cloud.init({ env: '环境 ID', traceUser: true, }) const db = wx.cloud.database() var myDate = new Date(); Page({ /** * 页面的初始数据 */ data: { list_id: "", userid: '', }, /** * 生命周期函数--监听页面加载 */ onLoad: function (options) { this.setData({ list_id: options.list_id }) console.log(this.data.list_id) const app = getApp() var userid = app.globalData.userid this.setData({ userid: userid, }) }, showsq: function () { wx.switchTab({ url: '../my/my', }) }, /** * 生命周期函数--监听页面初次渲染完成 */ onReady: function () { }, btnSub(res) { if (res.detail.value.text != '' && res.detail.value.username != '') { var { text, username } = res.detail.value; db.collection("glplgl").add({ data: { user: this.data.userid, text: text, plwz: this.data.list_id, username: username, data: myDate.toLocaleString(), _createTime: Date.parse(new Date()), } }).then(res => { wx.showToast({ title: '成功', icon: 'success', duration: 2000 }) }) } else { wx.showToast({ title: '请填写信息', icon: 'error', duration: 2000 }) } }, }) ``` ```xml 您还未授权登录,请授权登录! 去授权 用户名称: 评论: 发表评论 ``` :::tip 说明 针对内容安全,微信云开发提供内容安全功能,可对云开发数据库中存储的信息进行内容安全的规则设置,自动进行内容审核并对触发违规的内容进行处理。详情请参见 [内容安全](https://developers.weixin.qq.com/miniprogram/dev/wxcloud/basis/Consecurity.html)。 ::: 5. 最终效果如下: ### 步骤3:搭建发表攻略功能 1. 进入 app.json 页面,添加 weui 框架。 ```json { "useExtendedLib": { "weui": true } } ``` 2. 然后进入 fbpl.json 页面再次引入 weui 的框架并在 fbpl.wxml 中调用。相关代码如下: ```json { "usingComponents": { "mp-uploader": "weui-miniprogram/uploader/uploader", "mp-cells": "weui-miniprogram/cells/cells", "mp-cell": "weui-miniprogram/cell/cell", "mp-form-page": "weui-miniprogram/form-page/form-page", "mp-form": "weui-miniprogram/form/form", "mp-toptips": "weui-miniprogram/toptips/toptips", "mp-checkbox-group": "weui-miniprogram/checkbox-group/checkbox-group", "mp-half-screen-dialog": "weui-miniprogram/half-screen-dialog/half-screen-dialog" } } ``` ```xml 发布攻略 攻略 200 确定 ``` ```js // pages/fbpl/fbpl.js wx.cloud.init({ env: '您的环境ID', traceUser: true, }) const db=wx.cloud.database() Page({ /** * 页面的初始数据 */ data: { userid:'', files: [] }, /** * 生命周期函数--监听页面加载 在这里我们在app.js里面的openid */ onLoad: function (options) { const app = getApp() var userid = app.globalData.userid this.setData({ userid:userid, }) wx.cloud.init({ traceUser: true }) this.setData({ selectFile: this.selectFile.bind(this), uplaodFile: this.uplaodFile.bind(this) }) }, formInputChange(e) { const { field } = e.currentTarget.dataset this.setData({ [`formData.${field}`]: e.detail.value }) }, formplInputChange(e) { console.log(e) this.setData({ palce: e.detail.value }) }, formwtInputChange(e) { console.log(e) this.setData({ wt: e.detail.value }) }, submitForm(e) { this.setData({ name: this.data.formData.name, phone: this.data.formData.mobile, tsbm: this.data.tsbmun, }) if(this.data.wt.length>10 && this.data.openid!='') { db.collection('glpj').add({ // data 字段表示需新增的 JSON 数据 data: { title: this.data.name, user: this.data.mobile, xq: this.data.wt, phpto:this.data.files, userid: this.data.openid, time: Date.parse(new Date()), _createTime: Date.parse(new Date()), lll:0, } }) wx.reLaunch({ url: '../gltl/gltl', success: (res)=> { wx.showToast({ title: '完成', success:(res)=>{ wx.navigateTo({ url: '../index/index', }) } }) } }) }else{ wx.showToast({ title: '描述', icon: 'error', duration: 2000 }) } }, /** * 生命周期函数--监听页面显示 */ showsq: function () { wx.switchTab({ url: '../my/my', }) }, chooseImage: function (e) { var that = this; wx.chooseImage({ sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有 sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有 success: function (res) { // 返回选定照片的本地文件路径列表,tempFilePath可以作为img标签的src属性显示图片 that.setData({ files: that.data.files.concat(res.tempFilePaths) }); } }) }, previewImage: function(e){ wx.previewImage({ current: e.currentTarget.id, // 当前显示图片的http链接 urls: this.data.files // 需要预览的图片http链接列表 }) }, selectFile(files) { console.log('files', files) // 返回false可以阻止某次文件上传 }, uplaodFile(files) { console.log('upload files', files) console.log('upload files', files) // 文件上传的函数,返回一个promise return new Promise((resolve, reject) => { const tempFilePaths = files.tempFilePaths; //上传返回值 const that = this; const object = {}; for (var i = 0; i { } }) } }) // 文件上传的函数,返回一个promise }, uploadError(e) { console.log('upload error', e.detail) }, uploadSuccess(e) { console.log('upload success', e.detail) } }); ``` 3. 最终效果如下: ![](https://qcloudimg.tencent-cloud.cn/raw/f03ca645960e79643bfd31008af4f80c.png) ## 步骤5:搭建店铺页面 本文主要围绕**店铺**页面进行讲解,更多代码细节可参见 [店铺](https://github.com/ZiTao-Liu/Canteen-management-system/tree/main/miniprogram/pages/dp) 和 [商家](https://github.com/ZiTao-Liu/Canteen-management-system/tree/main/miniprogram/pages/fbgl)。 ### 步骤1:搭建店铺页面 1. 进入 CMS 内容管理控制台,新建**店铺**内容模型,数据库名称设置为 **dp**。 2. 进入新建的**店铺**页面,如下设置内容集合: 内容类型 展示名称 数据库字段名 单行字符串 店铺名称 name 单行字符串 店铺地点 dpdd 日期与时间 时间 time 布尔值 是否营业 sfyy 图片 店铺照片 dpzp 单行字符串 简介 jj :::tip 说明 更多 CMS 内容管理详细操作请参见 [搭建轮播图](https://cloud.tencent.com/document/product/876/71443#step2)。 ::: 3. 然后将它在小程序进行展示。 ```xml {{item.name}} {{item.jj}} 地址:{{item.dpdd}} 营业中 休息中 ``` ```js // pages/dp/dp.js wx.cloud.init({ env: 'ccntst-8gsp6zkw250f8e38', traceUser: true, }) const db=wx.cloud.database() Page({ /** * 页面的初始数据 */ data: { rmbs:"", list: [], list_id:'' }, bindPickerChange: function(e) { console.log('picker发送选择改变,携带值为', e.detail.value) this.setData({ index: e.detail.value }) }, bindPickerChange1: function(e) { console.log('picker发送选择改变,携带值为', e.detail.value) this.setData({ index1: e.detail.value }) }, input(e) { console.log(e) this.search(e.detail.value) }, //点击完成按钮时触发 confirm(e) { this.search(e.detail.value) }, search(key) { var that = this; //从本地缓存中异步获取指定 key 的内容 var list = wx.getStorage({ key: 'list', //从Storage中取出存储的数据 success: function (res) { // console.log(res) if (key == '') { //用户没有输入时全部显示 that.setData({ list: res.data }) return; } var arr = []; //临时数组,用于存放匹配到的数组 for (let i in res.data) { res.data[i].show = false; //所有数据隐藏 if (res.data[i].name.indexOf(key) >= 0) { res.data[i].show = true; //让匹配到的数据显示 arr.push(res.data[i]) } } if (arr.length == 0) { that.setData({ list: [{ show: true, name: '没有相关数据!' }] }) } else { that.setData({ list: arr }) } }, }) }, bindPickerChange2: function(e) { console.log('picker发送选择改变,携带值为', e.detail.value) this.setData({ index1: e.detail.value }) }, /** * 生命周期函数--监听页面加载 */ onLoad: function (options) { this.setData({ list_id:options.list_id }) console.log( this.data.list_id), db.collection("dp").get().then(res=>{ wx.setStorage({ key: 'list', data: res.data }) this.setData({ list: res.data, }) }) }, showbs:function(e){ console.log(e.currentTarget.id) wx.navigateTo({ url:'/pages/fbgl/fbgl?list_id='+e.currentTarget.id, }) }, }) ``` 4. 效果如下: ![](https://qcloudimg.tencent-cloud.cn/raw/e66239721196a7f269ef2908265b16c8.png) ### 步骤2:搭建商品页面 1. 进入 CMS 内容管理控制台,新建**商品**内容模型,数据库名称设置为 **sp**。 2. 进入新建的**商品**页面,如下设置内容集合: 内容类型 展示名称 数据库字段名 单行字符串 名称 name 数字 价格 jg 数字 销量 xl 单行字符串 配料 pl 图片 照片 zp 关联 商家 sj 其中,商家关联内容选择店铺,展示字段选择店铺名称。 :::tip 说明 更多 CMS 内容管理详细操作请参见 [搭建轮播图](https://cloud.tencent.com/document/product/876/71443#step2)。 ::: 3. 在用户点击商家跳转到商品页面,我们依然需要传递商家的 ID。 ```xml 您还未授权登录,请授权登录! 去授权 {{item.name}} 配料:{{item.pl}} 月售:{{item.xl}} ¥ {{item.jg}} 购买 ``` ```js // pages/fbgl/fbgl.js wx.cloud.init({ env: 'ccntst-8gsp6zkw250f8e38', traceUser: true, }) const db=wx.cloud.database() var myDate = new Date(); Page({ /** * 页面的初始数据 */ data: { userid: '', list_id:'', rmb:'' }, /** * 生命周期函数--监听页面加载 */ onLoad: function (options) { this.setData({ list_id:options.list_id }) console.log( this.data.list_id) const app = getApp() var userid = app.globalData.userid this.setData({ userid: userid, }) db.collection("sp").where({sj:this.data.list_id}).get().then(res=>{ console.log(res) this.setData({ rmb:res.data }) }) }, showsq: function () { wx.switchTab({ url: '../my/my', }) }, }) ``` 4. 效果如下: ![](https://qcloudimg.tencent-cloud.cn/raw/a3433173ae40fc8dccdb2e7f30dce136.png) ### 步骤3:搭建下单功能 1. 进入 CMS 内容管理控制台,新建**订单**内容模型,数据库名称设置为 **dd**。 2. 进入新建的**订单**页面,如下设置内容集合: 内容类型 展示名称 数据库字段名 单行字符串 userid userid 关联 商品 sp 单行字符串 时间 time 布尔值 下单 xd 布尔值 是否取餐 qccg 单行字符串 取餐时间 qcsj 其中,商品关联内容选择店铺,展示字段选择店铺名 :::tip 说明 更多 CMS 内容管理详细操作请参见 [搭建轮播图](https://cloud.tencent.com/document/product/876/71443#step2)。 ::: 3. 接下来进入 fbgl.js 页面配置下单事件。 ```js addCart(res) { console.log(res) const _=db.command db.collection('sp').doc(res.currentTarget.id).update({ data:{ xl:_.inc(1) } }) db.collection("sp").get().then(res=>{ console.log(res) this.setData({ rmb:res.data }) }) db.collection("dd").add({ data: { userid: this.data.userid, sp: res.currentTarget.id, _createTime: Date.parse(new Date()), time: myDate.toLocaleString(), xd:0, qccg:0, } }).then(res => { wx.showToast({ title: '添加成功', icon: 'success', duration: 2000 }) }) }, ``` :::tip 说明 我们思考可以知道,我们用户下单里面需要有用户openid,商品,时间等信息。 我们使用插入数据方法将数据存入数据库,新增记录,如果传入的记录对象没有 _id 字段,则由后台自动生成 _id;若指定了 _id,则不能与已有记录冲突 ::: ## 步骤6:搭建订单页面 本文主要围绕**订单**页面进行讲解,更多代码细节可参见 [订单](https://github.com/ZiTao-Liu/Canteen-management-system/tree/main/miniprogram/pages/dingdan) 和 [订单管理](https://github.com/ZiTao-Liu/Canteen-management-system/tree/main/miniprogram/pages/ddgl)。 ### 步骤1:搭建云函数 look 1. 右击**当前环境**文件夹,单击**新建 Node.js 云函数**,并将文件命名为 **look**。 ![](https://qcloudimg.tencent-cloud.cn/raw/fbc2d81502e939b58d4f9d423a139fce.png) 2. 在 look 云函数下,index.js 文件下编写聚合阶段联表查询代码。 ```js // 云函数入口文件 const cloud = require('wx-server-sdk') cloud.init({ env: '环境 ID'} ) const db = cloud.database() // 云函数入口函数 exports.main = async (event, context) => { var text= event.userid return await db.collection('dd').aggregate() .lookup({ from: 'sp', localField: 'sp', foreignField: '_id', as: 'bookList', }) .end() } ``` :::tip 说明 与同个数据库下的一个指定的集合做 `left outer join`(左外连接)。对该阶段的每一个输入记录,`lookup` 会在该记录中增加一个数组字段,该数组是被联表中满足匹配条件的记录列表。`lookup` 会将连接后的结果输出给下个阶段。 ::: 这里我们使用连表查询,使用 Aggregate.lookup(object: Object): Aggregate 方法。 ```json lookup({ from: , localField: , foreignField: , as: }) ``` 参数字段 说明 from 要进行连接的另外一个集合的名字 let 可选。指定在 pipeline 中可以使用的变量,变量的值可以引用输入记录的字段,例如 let: userName: '$name' 就代表将输入记录的 name 字段作为变量 userName 的值。在 pipeline 中无法直接访问输入记录的字段,必须通过 let 定义之后才能访问,访问的方式是在 expr 操作符中用 $$变量名 的方式访问,例如 $$userName。 pipeline 指定要在被连接集合中运行的聚合操作。如果要返回整个集合,则该字段取值空数组 []。在 pipeline 中无法直接访问输入记录的字段,必须通过 let 定义之后才能访问,访问的方式是在 expr 操作符中用 $$变量名 的方式访问,例如 $$userName。 as 指定连接匹配出的记录列表要存放的字段名,这个数组包含的是匹配出的来自 from 集合的记录。如果输入记录中本来就已有该字段,则该字段会被覆写 该操作等价于以下伪 SQL 语句: ```sql SELECT *, FROM collection WHERE IN (SELECT FROM WHERE ); ``` ### 步骤2:搭建云函数 lookup 1. 右击**当前环境**文件夹,单击**新建 Node.js 云函数**,并将文件命名为 **lookup**。 ![](https://qcloudimg.tencent-cloud.cn/raw/fbc2d81502e939b58d4f9d423a139fce.png) 2. 由于商品里面的 \_id 与订单里面 sp 相同,在 lookup 云函数下,index.js 文件编写以下代码,实现两个表的关联。 ```js // 云函数入口文件 const cloud = require('wx-server-sdk') cloud.init({ env: '环境 ID'} ) const db = cloud.database() // 云函数入口函数 exports.main = async (event, context) => { var text= event.userid return await db.collection('dd').aggregate() .lookup({ from: 'sp', localField: 'sp', foreignField: '_id', as: 'bookList', }) .end() } ``` 2. 然后我们在 dingdan.js 页面传 openid 到云函数 look。 ```js onLoad: function (options) { const app = getApp() var userid = app.globalData.userid this.setData({ userid: userid, }) wx.cloud.callFunction({ name: 'lookup', data: { userid: app.globalData.userid }, complete: res => { console.log(res.result.list) this.setData({ rmb: res.result.list }) } }) }, ``` ### 步骤3:搭建购物车页面 1. 接下来我们搭建购物车页面。 ```xml 暂未有订单,快去下单吧! 您还未授权登录,请授权登录! 登录 {{item.bookList[0].name}} 下单 清除商品 配料:{{item.bookList[0].pl}} 价格:{{item.bookList[0].jg}} 加入时间:{{item.time}} ``` ```js // pages/dingdan/dingdan.js wx.cloud.init({ env: '环境 ID', traceUser: true, }) const db = wx.cloud.database() const app = getApp(); Page({ /** * 页面的初始数据 */ data: { msgList: "", userid: '', username: "", openid: '', rmb: '' }, showsq: function () { wx.switchTab({ url: '../my/my', }) }, /** * 生命周期函数--监听页面加载 */ onLoad: function (options) { const app = getApp() var userid = app.globalData.userid this.setData({ openid: userid, }) wx.cloud.callFunction({ name: 'lookup', data: { userid: app.globalData.userid }, complete: res => { console.log(res.result.list) this.setData({ rmb: res.result.list }) } }) }, binqc: function (e) { console.log(e.currentTarget.id) db.collection('dd').doc(e.currentTarget.id).remove({ success: function (res) { } }) wx.cloud.callFunction({ name: 'lookup', data: { userid: app.globalData.userid }, complete: res => { console.log(res.result.list) this.setData({ rmb: res.result.list }) } }) }, binxd: function (e) { db.collection('dd').doc(e.currentTarget.id).update({ // data 传入需要局部更新的数据 data: { // 表示将 done 字段置为 true在用户下单我们将xd状态变更成1 xd: 1 }, success: function(res) { wx.showToast({ title: '下单成功', icon: 'success', duration: 2000 }) } }) wx.cloud.callFunction({ name: 'lookup', data: { userid: app.globalData.userid }, complete: res => { console.log(res.result.list) this.setData({ rmb: res.result.list }) } }) }, xd: function (e) { wx.navigateTo({ url: '/pages/xd/xd', }) }, sxxxx(e) { wx.cloud.callFunction({ name: 'lookup', data: { userid: app.globalData.userid }, complete: res => { console.log(res.result.list) this.setData({ rmb: res.result.list }) } }) }, }) ``` 2. 效果如下: ![](https://qcloudimg.tencent-cloud.cn/raw/f98a86c5f2ca35e8c372440d7bea764e.png) ### 步骤4:搭建取餐功能 1. 进入 ddgl.js 页面,增加以下方法实现**取餐**和**取消商品**功能。 ```js binqc: function (e) { wx.showModal({ title: '提示', content: '是否确认取消订单,会影响您的诚信度哦!', success(res) { if (res.confirm) { console.log('确定') console.log(e.currentTarget.id) db.collection('dd').doc(e.currentTarget.id).remove({ success: function (res) { wx.navigateTo({ url: '/pages/index/index', }) } }) } else if (res.cancel) { console.log('取消') } } }) }, binxd: function (e) { wx.showModal({ title: '取餐', content: '取餐号为' + e.currentTarget.id, success(res) { if (res.confirm) { db.collection('dd').doc(e.currentTarget.id).update({ // data 传入需要局部更新的数据 data: { // 表示将 done 字段置为 true qccg: 1, qcsj: myDate.toLocaleString(), }, success: res => { wx.showToast({ title: '取餐成功', icon: 'success', duration: 2000 }) } }) } else if (res.cancel) { console.log('用户点击取消') } } }) }, ``` 2. 最终效果如下: ![](https://qcloudimg.tencent-cloud.cn/raw/139f90251fabfc939de52b08206f0fc9.png) 至此,该小程序的全部功能已实现完成。更多详情请参见 [示例代码](https://github.com/ZiTao-Liu/Canteen-management-system)。 --- ## 预置并发 # 预置并发 ## 并发概述 并发是云函数在某个时刻同时处理的请求数。在业务其他服务可以支撑的情况下,您可以通过简单的配置实现云函数从几个并发到数以万计并发的拓展。 ### 并发运行原理 在调用函数时,云函数会分配一个并发实例处理请求或事件。函数代码运行完毕返回后,该实例会处理其他请求。如果在请求到来时,所有实例都在运行中,云函数则会分配一个新的并发实例。 :::tip 说明 云函数遵循一个并发实例同一时刻仅处理一个事件的运行逻辑,保障每个事件的处理效率和稳定性。 ::: ### 并发的计算 云函数的并发指的是函数代码同时处理请求或调用的数量,您可以通过以下公式估算: 并发数 = 请求速率 × 函数运行时间 = 每秒请求次数 × 每个请求的平均耗时 :::tip 说明 您可以在监控信息中的“运行时间”看到每个请求的平均耗时。 例如:某业务 QPS 为2000,每个请求的平均耗时为0.02s,则每个时刻的并发数为 2000qps × 0.02s = 40 ::: ### 并发实例复用与回收 当并发实例处理完事件请求后,不会立刻被回收,而是会保留一段时间以便复用。在保留期内,如有新的请求事件需要处理,将会优先使用保留中的并发实例,从而实现事件的快速处理,无需新启动并发实例。 :::tip 注意 - 保留期过后,如果没有请求需要该实例处理,云函数平台则会回收该实例。对于低并发的场景,不再设置保留期,平台将启动智能回收机制进行回收。 - 并发保留的时间由云函数平台根据情况动态调整,故函数业务代码中不能假设某个特定保留时间进行程序编写。 ::: ### 并发扩容 如果请求到来时,没有该版本的并发实例可以处理该请求,云函数平台会启动新的并发实例来处理。新启动的并发实例在初始化的过程后,便可以处理事件,我们称之为由弹性并发带来的扩容。 在地域维度,每个账号的弹性并发的扩容速度默认限制为500个/分钟,即在1分钟内,最多可以启动500个新的并发实例。如在1分钟内已经达到了当前限制,则将无法再启动新的并发实例,持续到下1分钟。在此期间有新的并发扩容请求,将会产生扩容受限错误(429 ResourceLimit)。 例如,广州地域的账号默认并发额度可以支撑128MB函数的1000个并发实例。有大量请求到来时,第一分钟可以从0个并发实例启动到500个并发实例。如果还有请求需要处理,第二分钟可以从500个并发实例启动到1000个并发实例,直至并发实例可以满足请求的需要或达到并发上限。 :::tip 说明 500个/分钟的弹性并发扩容速度可以满足多数业务场景。如果您的业务遇到该扩容速度的限制,您可以选择使用预置并发进行预热或购买 [预留资源套餐](https://cloud.tencent.com/document/product/876/64972) 以提高弹性并发扩容速度限制。 ::: ### 预置并发 云函数平台弹性并发扩容的并发实例需要经历初始化的过程:包括运行环境初始化及业务代码初始化等过程。您可以使用预置并发功能,预先配置并发实例。云函数平台将在您配置后开始启动并发实例,同时不会主动回收预置并发的实例,尽可能地保障有相应数量的并发实例。如遇到并发实例因代码内存泄漏等错误,云函数平台会将其替换为新的实例。 ### 并发服务承诺 #### 扩容并发限制 | 限制类型 | 个人用户 | 企业用户 | | ---------------- | ------------ | ------------- | | 弹性扩容并发限制 | 500并发/分钟 | 1000并发/分钟 | | 预置扩容并发限制 | 100并发/分钟 | 100并发/分钟 | 在地域维度,个人用户弹性并发的扩容速度默认限制为500并发/分钟,企业用户为1000并发/分钟。例如客户有10w并发的诉求,按照最大弹性并发的扩容速度,需要10w/ 1000 =100分钟就能完成扩容操作,需要提升配额可以购买 [预留资源套餐](https://cloud.tencent.com/document/product/876/64972)。 :::tip 说明 并发额度配额:单个环境下最大为256,000MB。 ::: ## 预置并发 预置并发支持并发实例按配置预先启动,同时云函数平台不会主动回收这些实例,会尽可能地保障有相应数量的可以处理请求的并发实例。您可通过此功能,为函数的指定版本设定预置并发额度。通过配置预置并发,可预先进行计算资源的准备,降低冷启动、运行环境初始化及业务代码初始化引起的耗时。 预置并发是在版本维度上解决请求到来时遇到并发实例初始化的问题。当您为一个函数版本配置预置并发之后,将会有以下效果: - 云函数平台立刻开始启动并发实例,直至达到配置值。 - 云函数平台不会主动回收预置并发实例,同时会尽可能地保障预置并发实例数。 - 预置并发与弹性调用的并发实例启动速度是分开的,预置并发的启动不会占用地域维度500个/分钟的弹性扩容速度。云函数平台会根据您业务的情况调整预置并发的启动速度,默认为100个/分钟。 :::tip 注意 - 云函数平台不会主动回收预置并发实例,但并发实例可能由于进程退出、内存超限等问题不可用。一旦有不可用的实例,云函数平台会回收同时准备新的并发实例以达到预置并发实例的配置。期间可能出现短暂的实际并发实例数小于预置并发实例的情况,未启动的并发实例不会纳入计费范围。您可以在函数的监控信息“并发执行个数和预置并发”图中查看预置并发启动情况。 - 预置并发只能配置在已发布的版本上,无法配置在 $LATEST 版本上。$LATEST 版本处于可编辑态,而预置并发需要在请求到来前启动并发实例。为了保障业务的稳定,避免因代码和配置编辑带来的版本不一致问题,预置并发只能配置在已发布的版本上。已发布版本的代码和配置无法修改,适合生产环境使用。 ::: ## 操作步骤 ### 新增预置并发 针对函数已发布的版本,可以设定期望数量的预置并发数。 1. 登录云开发控制台,选择左侧导航栏中的”云函数“。 2. 在“函数服务”列表页面,单击需进行配置函数名**操作**下的**预置管理**,进入”预置并发“页面。如下图所示: ![](https://qcloudimg.tencent-cloud.cn/raw/e7bfb1e6d8d78302eb8791e922f0ea29.png) 3. 在云函数详情页单击预置并发。如下图所示: ![](https://qcloudimg.tencent-cloud.cn/raw/bd014ee24358a9304e3a10c116730731.png) 4. 在弹出的“新增预置并发”窗口中,选择期望版本,单击**下一步**。如下图所示: ![](https://qcloudimg.tencent-cloud.cn/raw/c32d225bd3e942b604dd668c46fb8789.png) 5. 完成版本选择后进行预置实例,设置预置并发数后单击**确认**即可。如下图所示: ![](https://qcloudimg.tencent-cloud.cn/raw/d36c8b24a4229164c8b564cbf33fd4a4.png) 设置完成后,您可在“预置并发”中查看配置的状态。云函数后台将花费一定的时间完成预置并发的扩容,并将已启动准备的并发数、完成情况展示在列表中。 :::tip 说明 通过 [灰度发布](https://cloud.tencent.com/document/product/876/44717),逐步将流量从旧版本切到新版本。如遇到问题,则流量切回旧版本。 ::: ### 更新预置并发 当后台完成预置并发的扩容时,您可按需修改并发数。 1. 登录云开发控制台,选择左侧导航栏中的”云函数“。 2. 在“函数服务”列表页面,单击需进行配置函数名操作下的**预置管理**,进入”预置并发“页面。如下图所示: ![](https://qcloudimg.tencent-cloud.cn/raw/e7bfb1e6d8d78302eb8791e922f0ea29.png) 3. 在“预置并发”页面中,选择需更新版本所在行右侧的**设置**。如下图所示: ![](https://qcloudimg.tencent-cloud.cn/raw/e448b1f95eb1ebab12191088515dc9f3.png) 4. 在弹出的“设置预置并发”窗口中,更新设置值并单击**确定**即可。 ![](https://qcloudimg.tencent-cloud.cn/raw/11e3bc9d9ab703171db71af1c18ac3f5.png) 设置完成后,平台将根据您的修改情况,在一定时间内再次完成并发数的增加或减少。 ### 删除预置并发 流量完全切至新版本,观察一段时间无异样后,删除旧版本的预置并发或当您不再计划使用某个预置并发配置时,可进行删除操作。 1. 登录云开发控制台,选择左侧导航栏中的”云函数“。 2. 在“函数服务”列表页面,单击需进行配置函数名操作下的**预置管理**,进入”预置并发“页面。如下图所示: ![](https://qcloudimg.tencent-cloud.cn/raw/e7bfb1e6d8d78302eb8791e922f0ea29.png) 3. 在“预置并发”页面中,选择需调整版本所在行右侧的**删除**。如下图所示: ![](https://qcloudimg.tencent-cloud.cn/raw/50d860d9e68810f25a5196ad3b3cb94b.png) 4. 在弹出的“删除函数预置并发配额”窗口中单击**确认**即可。如下图所示: ![](https://qcloudimg.tencent-cloud.cn/raw/03781d0147cf56e248bd96ee432d2350.png) 配置删除后,平台将逐步回收并发实例。 ## 最佳实践 并发是云函数在某个时刻同时处理的请求数。在业务其他服务可以支撑的情况下,您可以通过简单的配置实现云函数从几个并发到数以万计并发的拓展。 ### 应用场景 #### 高 QPS 短运行时长 使用云函数进行简单的数据、文件处理,例如云存储触发云函数进行信息上报、对文件处理等。此类场景下单次请求运行时间较短。 ### 实践建议 一个账号下有多个业务同时使用云函数进行支撑时,云函数的并发配额则需要进行按需调度。例如,根据客户端业务的特点进行分析配置:客户端业务,会随着用户流量存在波峰波谷,为了保障用户体验,要求加载速度快,可以有一定的错误容忍度。 针对上述业务,可以为函数配置一定量的预置额度。如按最大使用量的60%来设置,但同时不配置函数的最大独占配额,确保在高峰到来时能充分利用总配额。云函数额度变化如下图所示: ![](https://main.qcloudimg.com/raw/37924aebd90201ce90a37f3097633aa4.jpg) --- ## 商店小程序开发实践 # 商店小程序开发实践 ## 概述 本文以一个商城小程序开发项目为例,介绍了在微信小程序开发的项目过程中的准备工作,小程序的创建过程、目录中各个文件的功能,以及在开发过程中要使用的云开发功能,如云存储、数据库和云函数。 :::tip 说明 本实例教程所涉及到的相关源码材料,均已得到相应授权。 ::: ### 准备工作 1. [注册腾讯云](https://cloud.tencent.com/document/product/378/17985)。 2. 开通了云开发的小程序,详情请参见 [微信小程序端快速入门](quick-start/mini-program/introduce)。 ### 操作流程 具体操作流程可分为以下 4 步。更多详情可参见 [示例](https://github.com/jiro-max/-)。 - [环境配置](#环境配置) - [搭建商城首页](#搭建商城首页) - [搭建详情页](#搭建详情页) - [搭建购物车](#搭建详情页) ### 项目目录 文件 说明 配置文件 .json 项目配置文件 `app.json`:用于配置各个页面的路径,设置窗口和底部的导航栏。页面的配置文件如 `index.json`:用于实现所属页面的个性化设置。 模板文件 .wxml 常用的是页面模板文件如 `index.wxml`,类似于 HTML,使用的是标签语言,用于设计界面的各个组件、事件系统,进而构建出页面的结构。 样式文件 .wxss 项目样式文件 `app.wxss`:用于配置全局的样式。 页面样式文件如 `index.wxss`:用于配置页面的个性化样式,在所在页面中可以覆盖掉全局样式。 逻辑文件 .js 逻辑文件是用来实现页面的业务逻辑功能的,例如数据的获取、判定,页面提示等功能,都是由逻辑文件中编写方法来实现的。 ## 环境配置 本文主要围绕项目配置文件 app.json 和 app.js 进行讲解,更多项目配置文件代码细节可参见 [app.json 配置](https://github.com/jiro-max/-/blob/master/app.json) 和 [app.js 配置](https://github.com/jiro-max/-/blob/master/app.js)。 ### 步骤 1:创建项目所需页面 首先进行需求分析: - 一个商城至少需要一个首页用来给用户展示商城有的商品。 - 一个商品详情页用来介绍单个商品的信息。 - 一个购物车用来给用户存放自己想要的商品。 所以我们需要在小程序项目配置文件 `app.json` 中编写 pages 中的内容,输入相应的路径后,开发者工具就会生成对应路径上的页面文件。 ```js "pages":[ "pages/index/index", "pages/cart/cart", "pages/detail/detail" ], ``` ### 步骤 2:配置商城的导航栏 生成 [步骤1](#步骤-1创建项目所需页面) 页面后,需要将页面添加到导航栏中,方便用户使用。 在 `app.json` 里,添加一个 tabBar 属性,因为商城的两大块分为首页和购物车。所以在 tarBar 里的 list 属性添加两个按钮,并将它们的页面地址、标题、图标配置好。 ```js "tabBar": { "selectedColor": "#f00", "list": [ { "pagePath": "pages/index/index", "text": "首页", "iconPath": "./汤圆酱/1.jpeg", "selectedIconPath": "./汤圆酱/3.jpeg" }, { "pagePath": "pages/cart/cart", "text": "购物车", "iconPath": "./汤圆酱/2.jpeg", "selectedIconPath": "./汤圆酱/4.jpeg" } ] } ``` 效果图如下: ![](https://qcloudimg.tencent-cloud.cn/raw/3cd84f3d2b0ef3953b2437d382d3bdc7.png) ### 步骤 3:配置云开发环境 1. 进入**微信开发者工具** > **云开发控制台**页面,复制**环境 ID**。 ![](https://qcloudimg.tencent-cloud.cn/raw/b37f49eb0c418236c445d28e72a53092.png) 2. 在 `app.js` 里面调用 API,wx.cloud.init 传入云开发控制台中的云环境 ID,方便项目调用控制台中的数据和资源。 ```js // app.js App({ onLaunch: function () { wx.cloud.init({ env: "xxxxx", //输入您的环境 ID }); }, globalData: { userInfo: null, }, }); ``` ### 步骤 4:创建数据库 将商城的商品使用数据库来存储,方便后面页面使用数据库进行商品的展示。 1. 进入**微信开发者工具** > **云开发控制台** > **数据库**页面。创建 **carts**、**goods** 和 **orders** 三个集合。 2. 进入 goods 集合,单击**添加记录**添加一些初始信息,每个数据记录的属性如下: ![](https://qcloudimg.tencent-cloud.cn/raw/7536be2aa109fa43e36f51f0f48223c5.png) - count:商品数量。 - imageSrc:商品图片,从云存储中获取。 - price:商品价格。 - tags:商品类别标签。 - title:商品名称。 :::tip 说明 商品图片要在云存储中先导入才能生成图片的位置,便于开发时图片数据的调用。 ::: ### 步骤 5:云存储导入图片 1. 进入**微信开发者工具** > **云开发控制台** > **存储**页面。 2. 单击**新建文件夹**并命名为 **goods**。 ![](https://qcloudimg.tencent-cloud.cn/raw/3ad9e87e44e58645cf2dd69409730779.png) 3. 进入 **goods** 文件夹,单击**上传文件**并传入所需要的图片,这些文件可以使用 FileID 在项目中进行调用。 ![](https://qcloudimg.tencent-cloud.cn/raw/f8f19cebb216e7218b2177c4f62ef334.png) ### 步骤 6:创建云函数 1. 在目录中创建云函数的文件夹 cloudfunction,然后在 project.config.json 中设置云函数的 cloudfunctionRoot 属性值为“cloudfunction/”。 2. 当文件夹 cloudfunction 目录下的文件变成绿色,就代表云函数的初始化完成。可右击文件夹单击**新建 Node.js 云函数**,即可创建一个云函数。创建结果如下图: ![](https://qcloudimg.tencent-cloud.cn/raw/5c73634b97a80744db355d484717f965.png) ## 搭建商城首页 本文主要围绕商城首页 index.js 和 index.wxml 进行讲解,更多项目配置文件代码细节可参见 [index.js 配置](https://github.com/jiro-max/-/blob/master/pages/index/index.js) 和 [前端页面 index.wxml](https://github.com/jiro-max/-/blob/master/pages/index/index.wxml)。 商城首页效果图如下: ### 步骤1:访问云端数据库 在商城页面的 `index.js` 中,调用 wx.cloud.database().collection() 获取当前云开发环境商品数据库的引用。 ```js //获取数据库 const db = wx.cloud.database() //获取集合 const goods_col = db.collection('goods') const carts_col = db.collection('carts') ``` :::tip 说明 在访问数据库数据时经常报错,或者在控制台更改数据一直报错的情况,一般为云端数据库的权限问题,通过自定义规则权限把数据库的所有权限全部设置成true,即可解决该类报错。 ::: ### 步骤2:加载商品列表数据 在首页页面的 `index.js` 中编写加载商品数据列表的逻辑,设置隐藏加载的动画以及列表一次展示的商品,访问 good_col 来读取商品的数据。 ```js //加载列表数据 async loadListData(){ const LIMIT = 5 let{_page,goods}=this.data//0 /*wx.showLoading({//加载 title: 'Loading...', })*/ await ml_showLoading let res = await goods_col.limit(LIMIT).skip(_page * LIMIT).get() //wx.hideLoading()//隐藏加载 await ml_hideLoading //手动停止下拉刷新 wx.stopPullDownRefresh() console.log('列表数据',res.data) this.setData({ goods :[...goods,...res.data],//追加,与之前数据拼接 _page: ++_page, hasmore : res.data.length === LIMIT }) }, ``` #### 代码说明 - **res**:存放查询商品数据库的返回值的变量。 - **limit()**:限制一次性显示的商品的数量。 - **LIMIT**:初始值数值为5。 - **\_page**:初始为0,后面会迭代加一。 - **\_page\*LIMIT**:指示从数据库中跳过几个元素开始获取数据。 - **setData()**:把每次取出来的商品数据进行拼接。 ### 步骤3:设置上拉事件商品加载数据 先限制数据加载函数中一次获取数据的数量,可定义为一次从云端访问五条商品信息;每次加载新数据时,可调用 wx.showLoading() 进行一个加载提示,当加载完成后为了提高用户的使用体验,添加一个 onReachBottom() 事件处理函数,在里面调用商品数据加载函数。 ```js onReachBottom(){ //没有跟多数据可以刷新 if(!this.data.hasmore) { /*wx.showToast({ title: '没有更多数据了', icon : "none" })*/ ml_showToast('没有更多数据了') return console.log('没有数据了') } console.log('上拉刷新') this.loadListData() }, ``` :::tip 说明 数据加载函数中由于一次加载只有五条信息,所以需要在数据加载函数的末尾,将之前加载的数据与本次函数调用加载的数据,用 setData 进行一个拼接,保障用户在下滑时还可以看到前面的商品数据。 ::: ### 步骤4:配置商品加载完成提示 1. 设置一个 bool 变量,初始值为 true,在数据加载函数中,判断从数据库中获取的数据,是否少于限制获取的数据数量。如果少于,则表明数据库中的数据已加载完成,将 bool 变量的值改为 false;反之则没有加载完成。 2. 然后在上拉事件处理函数中,在开始位置设置一个监听,当检测到 bool 变量为 false 时,调用 wx.showToast() 提示没有更多数据可加载,直接 return 上拉加载函数。 :::tip 说明 由于 wx.showToast() 的调用可用在很多地方,所以进行封装,在需要的页面处import 就可以直接调用。 ::: ### 步骤5:设置下拉事件刷新页面 1. 使用 onPullDownRefresh() 事件处理函数,将所有数值都重新设置成初始值,并重新调用最新数据加载函数。在数据加载函数中,设置手动关闭下拉刷新调用 wx.stopPullDownRefresh()。 ```js //下拉刷新 onPullDownRefresh(){ this.setData({ goods : [], _page :0, hasmore :true }) this.loadListData() console.log('下拉刷新') }, ``` 2. 在此之前还需要将 index.json 里设置配置,将"enablePullDownRefresh"改成默认为 true;再设置刷新加载的背景白点(默认)改为灰色。 ```json { "usingComponents": {}, "enablePullDownRefresh" : true, "backgroundTextStyle" : "dark" } ``` ### 步骤6:注册下单点击事件 在商城首页的下单按钮使用 catchtap 属性,设置加入购物车的功能函数。 :::danger 注意 其中不能使用 bindtap 属性,因为使用 bindtap 会在点击时冒泡进入商品详情页;catchtap 则不会跳转,而是直接触发将商品加入购物车的功能函数,再将首页点击下单的商品数据传入购物车页面。 ::: 加入购物车功能的实现,还需判断要下单的商品在购物车中是否已经存在。使用从首页下单传入的 ID 在购物车数据库中进行数据获取: - 获取成功则表示该商品已经加入购物车,调用 update() 让 num 累加一,调用封装的 wx.showToast() 提示商品已添加过。 - 获取失败则表示该商品还未加入购物车,需将该商品数据加入到购物车数据库中,调用 add() 添加购物车数据库的商品数据。数据属性包括: - **_id**:商品 ID - **imageSrc**:商品图片 - **price**:商品价格 - **title**:商品名称 添加成功调用之前封装的 wx.showToast() 提示添加成功。代码实现如下: ```js 加入购物车 async addCart(e){ //拿到商品 let { item }=e.currentTarget.dataset console.log('item' ,item) //判断商品在不在购物车里面 try{ let res =await carts_col.doc(item._id).get() console.log('有数值',res) //有值 await carts_col.doc(item._id).update({ data:{ num: db.command.inc(1) } }) } catch(err){ console.log('没有值') //把该商品加到购物车里面 await carts_col.add({ data :{ _id :item._id, imageSrc : item.imageSrc, price : item.price, title : item.title, num :1 } }) } this.setTabBar() await ml_showSuccess('下单成功') } ``` ### 步骤7:修改导航栏右上角的数值 在首页下单调用 wx.setTabBarBadge() 方法,index 属性指定购物车页面,text 指定数值(字符串类型),获取购物车数据库中的数据,调用 forEach() 函数将购物车数据库里面的商品的 num 值相加,如果 num 累加的结果为0,则直接返回 return 函数,不为零则将结果给 text 赋值(强制转换为字符串类型)。调用点击触发事件函数 onTabItemTap(),当点击购物车时,调用 wx.setTabBarBadge() 方法,给 text 赋值为空字符,达到隐藏右上角数值的效果。 ```js //修改tebbar右上角数值 async setTabBar(){ let total=0 let res=await carts_col.get() res.data.forEach(v => { total += v.num }) if(total === 0) return //console.log('123333333333') wx.setTabBarBadge({ index: 1, text: total + '',//转换成字符串 }) } ``` ## 搭建详情页 本文主要围绕详情页 detail.js进行讲解,更多详情页代码细节可参见 [detail.js 配置](https://github.com/jiro-max/-/blob/master/pages/detail/detail.js) 和 [前端页面 detail.wxml](https://github.com/jiro-max/-/blob/master/pages/detail/detail.wxml)。 ### 步骤1:设置跳转 在 index.wxml 处使用 navigator 导航组件跳转到商品详情页。 ```xml ``` ### 步骤2:获取点击商品信息 根据跳转详情页传入的商品 ID,在商品数据库中获取商品的详细信息,同样是调用 wx.cloud.database().collection(),再调用 doc() 通过传入 ID 过滤商品。 ```js const db = wx.cloud.database() const goods_col = db.collection('goods') Page({ data : { detail : {} }, onLoad(options){ let { id } =options console.log('id',id) this.loadDetailData(id) }, //加载数据详情 async loadDetailData(id){ //拿到数据库商品 let ins = goods_col.doc(id) //累计 await ins.update({ data: { count : db.command.inc(1) //log('123') } }) //获取 let res =await ins.get() //赋值 this.setData({ detail : res.data }) } }) ``` ### 步骤3:修改商品访问量 通过从首页传入的 ID 过滤出商品,然后调用 update 修改 count 的值,使其每次被访问时累加一。 ```js //累计 await ins.update({ data: { count : db.command.inc(1) //log('123') } }) ``` 效果如下: ![](https://qcloudimg.tencent-cloud.cn/raw/0ecacc2209481fd5dcb7cd30bfe6b54d.png) ## 搭建购物车 本文主要围绕购物车 cart.js 进行讲解,更多购物车代码细节可参见 [cart.js 配置](https://github.com/jiro-max/-/blob/master/pages/cart/cart.js) 和 [前端页面 cart.wxml](https://github.com/jiro-max/-/blob/master/pages/cart/cart.wxml)。 ### 步骤1:加载购物车列表 调用 wx.cloud.database().collection() 方法访问云端购物车数据库,将数据显示出来。 ```js async loadCartsData(){ let res = await carts_col.get() console.log('carts' , res) this.setData({ carts : res.data }) this.setCart(res.data)//统计总数 }, ``` ### 步骤2:设置商品总价格和个数 将加载购物车数据库函数中,购物车的数据传入计算商品总价格与总个数的函数中,调用 forEach() 方法计算商品总价格与总个数。总价格是通过遍历购物车数据库中的元素,计算每一个商品的个数与其单价的乘积的总和得到的;总个数是通过遍历购物车数据库中每个商品的个数的总和来得到的。最后通过 setData() 来设置购物车页面中显示的总价格与总商品个数。 ```js //统计总数 setCart(carts){ let totalCount=0 let totalPrice=0 carts.forEach(v =>{ totalCount += v.num totalPrice += v.num*v.price }) this.setData({ totalCount, totalPrice, }) }, ``` ### 步骤3:修改商品数量 通过点击购物车页面的加减号按钮,调用 bindtap 属性触发对应添加购物车商品与减少购物车商品的功能函数,传入被点击商品的 ID,在功能函数中通过 ID 过滤购物车数据库中的商品,再调用 update() 方法,对指定商品的 num 的值进行加减操作。 ```js //加一 async addCount(e){ //获取id let id = e.currentTarget.dataset.id //修改num数量 let res =await carts_col.doc(id).update({ data:{ num :db.command.inc(1) } }) this.loadCartsData() await ml_showSuccess('添加成功') }, //删除商品 async deleteCount(e){ //获取商品id let id = e.currentTarget.dataset.id //修改num数量 let res =await carts_col.doc(id).update({ data:{ num :db.command.inc(-1) } }) console.log('res ----',res) console.log('id-------',e.currentTarget.dataset.num) await ml_showSuccess('删除成功') let num=await carts_col.doc(id).num console.log('num的值',num) if( num === 0 ) { console.log('商品数量为0') } this.loadCartsData() }, ``` 效果如图所示: ![](https://qcloudimg.tencent-cloud.cn/raw/a10a25ece3ea4ed33404f1d361290d12.png) 至此,该小程序的全部功能已实现完成。更多详情请参见 [示例代码](https://github.com/jiro-max/-.git)。 --- ## 在云函数内使用 Redis 扩展 # 在云函数内使用 Redis 扩展 ## 什么时候应该使用 Redis? Redis 的适用场景包括但不仅限于: - **计数器**:因为 Redis 操作是原子性的,通过原子递增或递减来做高并发用户的数据计数,比如点赞数、收藏数、分享数、商品抢购时的库存量、商品文章总数、评论数量等; - **排行榜**:Redis 支持集合和有序集合的数据结构,且运行在内存中,因此可以存储一些类似于排行榜的数据,比如最近、最热、点击率最高、活跃度最高、评论最多等等的文章、商品、用户等; - **哈希表**:用户粉丝列表、用户点赞列表、用户收藏列表、用户关注列表等; - **自动排序**:存储时间戳,随着时间的变化,按照用户关注用户的最新动态列表等自动排序; - **会话缓存**:使用 Redis 进行会话缓存,将 web session 存放在 Redis 中; - **全页缓存 FPC**:可以将服务端渲染结果的缓存在 Redis 中; - **记录用户操作信息**:用户是否点赞、用户是否收藏、用户是否分享等。 ## 安装 Redis 拓展 ### 1、安装扩展 打开腾讯云控制台,进入到环境详情页面,点击左侧的「拓展管理」,进入到拓展管理详情页,并点击 Redis 拓展,安装拓展。 ![img](https://main.qcloudimg.com/raw/c5d18dc4b50d49d7e14609e112e7bb76.png) ### 2、创建 Redis 实例 倘若安装中没有实例(即还没有购买 Redis 数据库,点击新建实例),倘若已经有实例的可以跳过,进入下一步。 ![img](https://main.qcloudimg.com/raw/64168d18f94af51f695cfde061030451.png) 购买 Redis 数据库,创建实例,配备好私有网络。 ![img](https://main.qcloudimg.com/raw/0b3767e51a24c229b7a3081faada3390.png) 创建好实例后回到扩展选择刚刚创建(或者已有的)的实例: ![img](https://main.qcloudimg.com/raw/95c04e9e1a059856ba50d56e67e1f830.png) 点击完成创建: ![img](https://main.qcloudimg.com/raw/c1da108dfa30a060f7e1e84bb9d4acee.png) 看到有如下扩展即安装成功: ![img](https://main.qcloudimg.com/raw/0db653c9034cc4798654336283174bf0.png) ### 3、获取 Redis 信息 创建好后查看拓展相关信息(在这里面我们便可以看到一起创建好的云函数啦): ![img](https://main.qcloudimg.com/raw/3f92c5aa21fe27213463b8986932f425.png) ## 在云函数中使用 Redis 云函数内可以通过 Redis 客户端连接和操作 Redis 实例,推荐使用 [redis](https://www.npmjs.com/package/redis)。 ### 1、安装依赖 首先进入到 Redis 的云函数目录中,然后执行命令 `npm init -y` 初始化一个配置文件。 随后,执行`npm install --save redis` 来安装相应的依赖。 安装完成后,云函数目录下将会出现 `package.json` 文件,内容类似以下: ```json { "name": "redis", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC", "dependencies": { "redis": "^3.0.2" } } ``` ### 2、调用 Redis 接下来可以在代码中调用 Redis 数据库了。 由于使用了云开发的 Redis 拓展,系统运行环境中会自动带上相应的配置,你可以直接使用相应的环境变量来链接 Redis 数据库。 ```js 'use strict'; const redis = require('redis') let client = redis.createClient({ host: process.env.HOST, port: process.env.PORT, // 需要填写真实的密码 password: 'xxx' }) exports.main = async (event, context, callback) => { let res = await new Promise((resolve, reject) => { client.get('test', function (err, reply) { if (err) { resolve({ err }) } resolve({ data: reply.toString() }) }) }) return { res } } ``` --- ## 使用云调用接收、发送微信消息 # 使用云调用接收、发送微信消息 ## 概述 开发者可能会使用微信客服消息功能,接收小程序用户的客服对话消息,以及发送消息给用户。 小程序·云开发的云调用功能**天然打通**微信消息推送接口,开发者只需要调用相应的函数即可简单完成消息推送流程。 ## 方案对比 ### 接收消息 ![](https://main.qcloudimg.com/raw/19c7a98378765ce2ccf9252d2e79149f.png) ### 发送消息 ![](https://main.qcloudimg.com/raw/2c95d1dbf8fafccce90186c77416e39d.png) ## 代码示例 开通了云开发的小程序可以使用云函数接收消息推送,目前仅支持客服消息推送。 参考:[使用云函数接受消息推送](https://developers.weixin.qq.com/miniprogram/dev/framework/server-ability/message-push.html#option-cloud) ### 第一步:开发者工具云开发控制台中增加配置 打开云开发控制台,到设置 Tab 中选择「全局设置」-「添加消息推送配置」,添加接收消息的云函数。 消息类型对应收包的 `MsgType`,事件类型对应收包的 `Event`,同一个 `` 二元组只能推到一个环境的一个云函数。例如客服消息文本消息对应的就是消息类型为 `text`,事件类型为空。具体值请查看各个消息的消息格式。 ### 第二步:云函数中接收、处理消息 云函数被触发时,其 `event` 参数即是接口所定义的 JSON 结构的对象(统一 JSON 格式,不支持 XML 格式)。 以客服消息为例,接收到客服消息推送时,`event` 结构如下: ```json { "FromUserName": "ohl4L0Rnhq7vmmbT_DaNQa4ePaz0", "ToUserName": "wx3d289323f5900f8e", "Content": "测试", "CreateTime": 1555684067, "MsgId": "49d72d67b16d115e7935ac386f2f0fa41535298877_1555684067", "MsgType": "text" } ``` ### 第三步:发送客服消息 此时可调用[客服消息发送接口](https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/customer-message/customerServiceMessage.send.html)回复消息,一个简单的接收到消息后统一回复 “收到” 的示例如下: ```js // 云函数入口文件 const cloud = require("wx-server-sdk"); cloud.init(); // 云函数入口函数 exports.main = async (event, context) => { const wxContext = cloud.getWXContext(); await cloud.openapi.customerServiceMessage.send({ touser: wxContext.OPENID, msgtype: "text", text: { content: "收到", }, }); return "success"; }; ``` ## 相关文档 - [云函数文档](/cloud-function/introduce) - [云调用文档](https://developers.weixin.qq.com/miniprogram/dev/wxcloud/guide/openapi/openapi.html) - [wx-server-sdk 文档](https://developers.weixin.qq.com/miniprogram/dev/wxcloud/reference-sdk-api/Cloud.html) - [微信消息推送文档](https://developers.weixin.qq.com/miniprogram/dev/framework/server-ability/message-push.html) --- ## 使用云函数+云调用打通微信支付 # 使用云函数+云调用打通微信支付 ## 概述 小程序·云开发的云调用功能**天然打通**微信支付接口,开发者只需要调用相应的函数即可简单完成整套支付流程。 - 无需关心证书、签名,支付**流程简化**; - 基于微信**私有协议**和**私有链路**,更加安全、高效; - 免运维,**高可用性**; - 按需扩容,弹性伸缩,按量计费,**成本缩减**; - 支持通过云函数接受支付回调,无需自建回调服务。 ## 流程对比:传统流程 vs 云开发 ![](https://main.qcloudimg.com/raw/602e71f9a3513a3a1d399ea82ce2a557.png) ## 代码示例 ### 第 1 步:小程序调用云函数 C 端用户发起支付流程后,小程序端调用云函数(我们假设云函数名为 `makeOrder`): ```js // 小程序代码 wx.cloud.callFunction({ name: "makeOrder", data: { /* 开发者自定义参数 */ }, }); ``` ### 第 2 步:云函数生成订单,返回订单信息 云函数 `makeOrder` 收到调用之后,使用微信服务端 SDK 提供的 API,**无需证书和签名**,可直接生成订单。 生成订单之后,将订单信息返回给小程序。 [`cloudPay.unifiedOrder()` 接口文档](https://developers.weixin.qq.com/miniprogram/dev/wxcloud/reference-sdk-api/open/pay/CloudPay.unifiedOrder.html) ```js // 云函数 makeOrder const cloud = require("wx-server-sdk"); cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV, }); exports.main = async (event, context) => { const res = await cloud.cloudPay.unifiedOrder({ body: "小秋TIT店-超市", outTradeNo: "1217752501201407033233368018", spbillCreateIp: "127.0.0.1", subMchId: "1900009231", totalFee: 1, envId: "test-f0b102", functionName: "payCallback", // 支付回调的函数名 }); return res; }; ``` ### 第 3 步:小程序端发起支付 小程序端收到云函数返回的订单信息后,发起支付: ```js // 小程序代码 wx.cloud.callFunction({ name: "makeOrder", data: { /* 开发者自定义参数 */ }, success: (res) => { // 取得云函数返回的订单信息 const payment = res.result.payment; // 调起微信客户端支付 wx.requestPayment({ ...payment, success(res) { /* 成功回调 */ }, fail(res) { /* 失败回调 */ }, }); }, }); ``` ### 第 4 步:使用云函数接收支付回调,完成支付流程 用户完成付款之后,微信后台将会调用指定的云函数(我们假设名为 `payCallback`),传入的参数中会带有订单信息。 开发者可以在此云函数中,实现自己的发货、完成订单的逻辑。 ```js // 云函数 payCallback exports.main = async (event, context) => { const { return_code, // 状态码 appid, // 小程序 AppID mch_id, // 微信支付的商户号 device_info, // 微信支付分配的终端设备号 openid, // 用户在商户appid下的唯一标识 trade_type, // 交易类型:JSAPI、NATIVE、APP bank_type, // 银行类型 // ...... // 更多参数请参考:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7&index=8 } = event; /* 开发者自己的逻辑 */ // 向微信后台返回成功,否则微信后台将会重复调用此函数 return { errcode: 0 }; }; ``` ## 相关文档 - [云函数文档](/cloud-function/introduce) - [云调用文档](https://developers.weixin.qq.com/miniprogram/dev/wxcloud/guide/openapi/openapi.html) - [wx-server-sdk 文档](https://developers.weixin.qq.com/miniprogram/dev/wxcloud/reference-sdk-api/Cloud.html) - [`cloudPay.unifiedOrder()` 接口文档](https://developers.weixin.qq.com/miniprogram/dev/wxcloud/reference-sdk-api/open/pay/CloudPay.unifiedOrder.html) --- ## .NET 快速开始 # .NET 快速开始 ## 准备工作 1. 拥有腾讯云账号; 2. [创建云开发环境](/quick-start/create-env),获得 **环境 ID**; 3. 安装 [.NET Core](https://dotnet.microsoft.com/download)。 ## 第 1 步: 开启匿名登录 在[环境设置页面](https://console.cloud.tencent.com/tcb/env/setting)中,点击“登录方式”,然后**启用匿名登录**: ## 第 2 步:创建 .NET Core 项目 ```sh dotnet new console -o Demo cd Demo ``` ## 第 3 步:添加 CloudBase Sdk 依赖 ```sh dotnet add package TencentCloudBase ``` ## 第 4 步:初始化环境并调用匿名登录 ```csharp using System; using System.Threading.Tasks; using CloudBase; namespace Demo { class Program { static void Main(string[] args) { // 初始化 CloudBase CloudBaseApp app = CloudBaseApp.Init( // 填写您的云开发 env "your-env-id", // 填写网络请求超时时间 3000 ); // 获取登录状态 AuthState state = await app.Auth.GetAuthStateAsync(); // 唤起匿名登录 if (state == null) { state = await app.Auth.SignInAnonymouslyAsync(); } } } } ``` 登录成功后,便可以访问和使用云开发的各类资源,详情请参看 CloudBase SDK 文档 - [初始化](/api-reference/dotnet/initialization) - [登录认证](/api-reference/dotnet/authentication) - [云函数](/api-reference/dotnet/functions) - [数据库](/api-reference/dotnet/database) - [文件存储](/api-reference/dotnet/storage) --- ## Flutter 快速开始 # Flutter 快速开始 ## 准备工作 1. 拥有腾讯云账号; 2. [创建云开发环境](/quick-start/create-env),获得 **环境 ID**; 3. 安装 [Flutter](https://flutter.cn/docs/get-started/install)。 ## 第 1 步:创建 Flutter 项目 ```sh flutter create cloudbase_demo cd cloudbase_demo ``` ## 第 2 步:添加 CloudBase 插件依赖 在项目的 `pubspec.yaml` 文件中添加 `dependencies` 。 ```yaml dependencies: cloudbase_core: ^0.0.9 cloudbase_auth: ^0.0.11 ``` 从 `pub` 安装依赖。 ```sh flutter pub get ``` ## 第 3 步:创建移动应用安全来源的凭证 打开[安全设置页面](https://console.cloud.tencent.com/tcb/env/safety)中,在移动应用安全来源里**添加应用**. :::tip 提示 因为 Flutter 是跨端开发框架, 所以需要为 Android 和 iOS 各申请一个应用凭证。 应用标识应该是 Android 包名 和 iOS Bundle ID。 ::: ## 第 4 步:开启匿名登录 在[环境设置页面](https://console.cloud.tencent.com/tcb/env/setting)中,点击“登录方式”,然后**启用匿名登录**: ## 第 5 步:初始化环境并调用匿名登录 在项目的 `lib/main.dart` 文件中初始化环境并进行匿名登录。 ```dart import 'package:cloudbase_core/cloudbase_core.dart'; import 'package:cloudbase_auth/cloudbase_auth.dart'; void main() async { // 初始化 CloudBase CloudBaseCore core = CloudBaseCore.init({ // 填写您的云开发 env 'env': 'your-env-id', // 填写您的移动应用安全来源凭证 // 生成凭证的应用标识必须是 Android 包名或者 iOS BundleID 'appAccess': { // 凭证 'key': 'your-app-access-key', // 版本 'version': 'your-app-access-version' } }); // 获取登录状态 CloudBaseAuth auth = CloudBaseAuth(core); CloudBaseAuthState authState = await auth.getAuthState(); // 唤起匿名登录 if (authState == null) { await auth.signInAnonymously().then((success) { // 登录成功 print(success); }).catchError((err) { // 登录失败 print(err); }); } } ``` :::tip 提示 初始化 CloudBase 时用到的 `appAccess` 参数可以从控制台的安全来源凭证模块中获取。 ::: 登录成功后,便可以访问和使用云开发的各类资源,详情请参看 Flutter SDK 文档 - [初始化](/api-reference/flutter/initialization) - [登录认证](/api-reference/flutter/authentication) - [云函数](/api-reference/flutter/functions) - [数据库](/api-reference/flutter/database) - [文件存储](/api-reference/flutter/storage) --- ## 使用 SDK 开发 # 使用 SDK 开发 CloudBase 提供一站式的后台即服务(BaaS),支持小程序、Web、移动应用等多个平台,帮助开发者快速构建应用后端服务。 ## 🌟 SDK 开发的优势 - **🚀 快速集成**:几行代码即可接入云开发服务 - **🔒 安全可靠**:内置身份认证和数据安全保护 - **📱 多端支持**:一套后端服务,多端共享 - **⚡ 高性能**:全球分布式架构,毫秒级响应 - **💰 成本优化**:按需付费,无需维护服务器 ## 🛠️ 核心功能 ### 身份认证 - 匿名登录、邮箱登录、手机号登录 - 微信登录、QQ 登录等第三方登录 - 自定义登录和用户管理 ### 数据库 - NoSQL 文档数据库 - 实时数据同步 - 复杂查询和聚合操作 ### 云存储 - 文件上传、下载、删除 - 图片处理和 CDN 加速 - 安全的文件访问控制 ### 云函数 - 服务端逻辑执行 - 定时任务和触发器 - 与其他云服务无缝集成 ## 📱 选择您的平台 根据您的开发平台,选择对应的 SDK 快速开始指南: ### 🔥 热门平台 #### 微信小程序 最受欢迎的小程序开发平台,与微信生态深度集成。 **特点**: - 原生云开发支持 - 丰富的微信 API - 完善的开发工具链 [开始微信小程序开发 →](/quick-start/baas/wx-mini) #### Web 应用 适用于网站、H5 应用、PWA 等 Web 应用开发。 **特点**: - 支持所有现代浏览器 - 完整的 JavaScript SDK - 支持 TypeScript [开始 Web 开发 →](/quick-start/baas/web) ### 🚀 更多平台 #### Flutter 应用 跨平台移动应用开发框架,一套代码多端运行。 **特点**: - iOS 和 Android 双端支持 - 原生性能体验 - 丰富的 UI 组件 [查看 Flutter 开发指南 →](/quick-start/baas/flutter) #### Unity 游戏 游戏开发引擎,支持多平台游戏开发。 **特点**: - 跨平台游戏支持 - 实时数据同步 - 游戏数据分析 [查看 Unity 开发指南 →](/quick-start/baas/dotnet) ## 🎯 5 分钟快速体验 想要快速体验 SDK 的能力?选择您熟悉的平台: ### Web 快速体验 ```html const app = cloudbase.init({ env: 'your-env-id' }); app.auth().anonymousAuthProvider().signIn() .then(() => console.log('登录成功!')); ``` ### 小程序快速体验 ```javascript // 在 app.js 中初始化 wx.cloud.init({ env: 'your-env-id' }); // 在页面中使用 const db = wx.cloud.database(); db.collection('todos').get().then(res => { console.log('数据获取成功', res.data); }); ``` ## 📚 学习路径 ### 新手入门 1. [开通云开发环境](/quick-start/create-env) 2. 选择平台开始开发(上方链接) 3. [学习身份认证](/authentication/introduce) 4. [掌握数据库操作](/database/introduce) ### 进阶学习 1. [云存储文件管理](/storage/introduce) 2. [云函数服务端开发](/functions/introduce) 3. [实时数据库](/database/realtime) 4. [扩展能力集成](/extensions/introduce) ### 最佳实践 1. [应用架构设计](/best-practice/architecture) 2. [性能优化技巧](/best-practice/performance) 3. [安全最佳实践](/best-practice/security) 4. [多环境管理](/best-practice/multi-env) ## 🔗 相关资源 ### 开发文档 - [API 参考文档](/api-reference/) - [SDK 下载和更新日志](https://github.com/TencentCloudBase) - [示例项目](https://github.com/TencentCloudBase/awesome-cloudbase-examples) ### 社区支持 - [开发者社区](https://cloud.tencent.com/developer/tag/10532) - [GitHub Issues](https://github.com/TencentCloudBase/cloudbase-js-sdk/issues) - [技术交流群](https://cloud.tencent.com/document/product/876/46906) --- **🚀 准备好了吗?** 选择您的开发平台,开始构建强大的云端应用! --- ## Web 快速开始 import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # Web 快速开始 ## 准备工作 1. [拥有腾讯云账号](/quick-start/create-env); 2. **务必**[创建云开发环境](/quick-start/create-env),获得 **环境 ID**; 3. 安装 [Node.js](https://nodejs.org/en/); 4. 安装 [Cloudbase CLI](/quick-start/install-cli)。 ```sh npm install -g @cloudbase/cli ``` :::tip 注意 如果 `npm install -g @cloudbase/cli` 失败,您可能需要[修改 npm 权限](https://docs.npmjs.com/resolving-eacces-permissions-errors-when-installing-packages-globally),或者以系统管理员身份运行: ```sh sudo npm install -g @cloudbase/cli ``` ::: ## 第 1 步:创建初始项目 使用命令行创建目录 my-cloudbase-app,和其下的两个文件。 ```sh mkdir my-cloudbase-app && cd my-cloudbase-app && touch index.html && touch cloudbaserc.json ``` 该目录下存在两个文件:`index.html` 与 `cloudbaserc.json` ``` ├── cloudbaserc.json └── index.html ``` 1. 创建 `my-cloudbase-app` 文件夹 2. 在此文件夹下,创建两个空白文件 `index.html` 与 `cloudbaserc.json` 以下是 `index.html` 内容,我们尝试登录云开发,如果成功,那么产生一个弹窗: ```html const app = cloudbase.init({ env: "您的环境ID", // 此处填入您的环境ID }); app .auth() .anonymousAuthProvider() .signIn() .then(() => { alert("登录云开发成功!"); }); Hello Cloudbase! ``` 以下是 `cloudbaserc.json` 的内容: ```json { "envId": "此处填入您的环境ID" } ``` ## 第 2 步:添加安全域名 登录[云开发 CloudBase 控制台](https://console.cloud.tencent.com/tcb),在[安全配置](https://console.cloud.tencent.com/tcb/env/safety)页面中,将域名添加到 Web 安全域名中。 :::tip 提示 这里我们把 `localhost:5000` 加入到安全域名中,让此域名下的页面可以使用 SDK 访问云开发服务。 ::: ## 第 3 步:开启匿名登录 请参考:[开启匿名登录授权](/authentication/method/anonymous#开启匿名登录授权) ## 第 4 步:开启本地开发环境 在项目根目录运行: ```sh npx serve ``` 即可打开一个本地静态服务器,然后访问 [http://localhost:5000](http://localhost:5000) :::tip 提示 如果 SDK 成功使用匿名身份登录,那么您应该可以看到一个弹窗。 ::: 登录成功后,便可以访问和使用云开发的各类资源,详情请参看 [Web SDK 文档](/api-reference/webv3/initialization) - [登录认证](/api-reference/webv2/authentication) - [云函数](/api-reference/webv2/functions) - [数据库](/api-reference/webv2/database) - [文件存储](/api-reference/webv2/storage) ## 第 5 步(可选):使用云开发部署静态页面 1. 开通 [静态网站服务](https://console.cloud.tencent.com/tcb/hosting) 2. 在项目根目录下运行以下命令,上传网站文件: ```sh cloudbase hosting deploy index.html ``` :::tip 注意 在运行 `cloudbase hosting deploy` 之前,请先登录命令行工具: ```sh cloudbase login ``` ::: 3. 使用 _envId_-_instanceId_.tcloudbaseapp.com 访问您的网站,其中 `envId` 与 `instanceId` 是您 CloudBase 环境的标识符。 详情请参考[静态网站托管](/hosting/introduce)相关文档 ## 查看更多示例 - [示例:登录与用户](https://tdemo-1258016615.tcloudbaseapp.com/auth/) - [示例:云函数](https://tdemo-1258016615.tcloudbaseapp.com/functions/) - [示例:数据库](https://tdemo-1258016615.tcloudbaseapp.com/database/) - [示例:云存储](https://tdemo-1258016615.tcloudbaseapp.com/storage/) --- ## 微信小程序 快速开始 # 微信小程序 快速开始 ## 准备工作 1. [下载微信开发者工具](https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html); 2. [注册微信小程序](https://mp.weixin.qq.com/cgi-bin/wx?token=&lang=zh_CN); 3. 安装 [Node.js](https://nodejs.org/en/); ## 第 1 步:创建初始项目 打开微信开发者工具,创建小程序项目,填写 `AppId`,后端服务选择 `微信云开发`,然后选择任意模板启动项目,具体示例如下图所示: ## 第 2 步:创建云开发环境 微信开发者工具进入到项目后,点击菜单中的 `云开发` 菜单,开通云开发环境,开通成功后可以看到分配的 `环境ID`,将其复制以备用,具体示例如下图所示: ## 第 3 步:配置小程序 Request 域名 登录 [微信公众平台](https://mp.weixin.qq.com),在 `开发管理` 中,添加 `request合法域名` :::tip 提示 需要添加 2 个域名,分别为: - `https://{环境ID}.ap-shanghai.tcb-api.tencentcloudapi.com` - `https://{环境ID}.api.tcloudbasegateway.com` 例如环境 ID 为 `my-cloud-2glzt9x5c014bb0d`,则域名为 - `https://my-cloud-2glzt9x5c014bb0d.ap-shanghai.tcb-api.tencentcloudapi.com` - `https://my-cloud-2glzt9x5c014bb0d.api.tcloudbasegateway.com` ::: 具体示例如下图所示: ## 第 4 步:安装依赖包 在微信开发者工具中打开 `终端` 工具,安装最新的 `@cloudbase/js-sdk` 依赖包,注意要安装 `2.x.x` 的版本,最新版本可以在 [npm 官网](https://www.npmjs.com/package/@cloudbase/js-sdk?activeTab=versions) 查到,以下是安装指令: ```sh npm i @cloudbase/js-sdk ``` 安装好依赖包后,点击微信开发者工具的 `工具-构建npm`,成功后会看到自动生成的 `miniprogram_npm` 目录 :::tip 提示 如果构建不成功请检查 `project.config.json` 文件中的 `packNpmRelationList` 配置是否正确,一般配置如下,具体可以参考 [官方 npm 支持介绍](https://developers.weixin.qq.com/miniprogram/dev/devtools/npm.html) ```json "packNpmRelationList": [ { "packageJsonPath": "./package.json", "miniprogramNpmDistDir": "./miniprogram/" } ] ``` ::: 具体示例如下图所示: ## 第 5 步:功能代码编写 相关功能编写可以参考[官方文档](https://docs.cloudbase.net/api-reference/webv3/initialization),以下是简单的初始化和 openId 静默登录示例: ```javascript // 内核 import cloudbase from "@cloudbase/js-sdk/app"; // 登录模块 import { registerAuth } from "@cloudbase/js-sdk/auth"; // 云函数模块 import { registerFunctions } from "@cloudbase/js-sdk/functions"; // 云存储模块 import { registerStorage } from "@cloudbase/js-sdk/storage"; // 数据库模块 import { registerDatabase } from "@cloudbase/js-sdk/database"; // 注册功能模块 registerAuth(cloudbase); registerFunctions(cloudbase); registerStorage(cloudbase); registerDatabase(cloudbase); const app = cloudbase.init({ env: "环境ID", // 用第二步获取到的环境ID替换 }); const auth = app.auth(); auth.signInWithOpenId(); console.log(auth.currentUser); ``` ## 其他小程序示例 请参考 [小程序快速开始](/quick-start/mini-program/introduce) --- ## 开通云开发环境 import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # 开通云开发环境 云开发环境是您应用的后端服务基础,每个环境相互隔离,拥有唯一的环境 ID,包含独立的数据库实例、存储空间、云函数配置等资源 ## 开通方式选择 根据您的开发场景,选择合适的开通方式: ### 方式一:微信开发者工具(推荐小程序开发者) 1. 打开微信开发者工具,点击上方的「云开发」按钮 ![](https://qcloudimg.tencent-cloud.cn/raw/b52828ae2056120cbb5bc7c96b8ba1e1.png) 2. 首次进入时,按照提示开通云开发环境 :::tip 提示 * 初始创建的环境自动成为默认环境 * 开始创建环境后,需要等待几分钟时间进行资源初始化 ::: ### 方式二:腾讯云控制台(推荐 Web/移动应用开发者) :::tip 云开发为新用户提供开发期免费环境,开发免费、正式使用需付费。但免费环境存在一些功能使用限制,如需使用更多功能,建议升级为付费版本。详细说明请参见 [价格文档](https://cloud.tencent.com/document/product/876/75213) ::: 1. 进入 [云开发控制台](https://console.cloud.tencent.com/tcb/platform/env),勾选服务条款,然后单击「**免费开发,开启智能应用**」 ![](https://write-document-release-1258344699.cos.ap-guangzhou.tencentcos.cn/100040303667/ddfd6bc745ef11f0b0ce5254007c27c5.png) 2. 进行云开发服务角色权限授权 ![](https://qcloudimg.tencent-cloud.cn/image/document/e3d722f3f723871f3df530952674cf2d.png) 3. 授权完成后,系统将自动发货 **个人版免费期**, 新环境进行免费体验,同时系统将并打开云开发平台 1. 前往 [云开发控制台](https://console.cloud.tencent.com/tcb/platform/env) 2. 点击「**开通环境**」按钮 进入环境下单页 ![](https://qcloudimg.tencent-cloud.cn/raw/778846dd2633ec8d39682e3632fe5faa.png) 3. 支付完成后即可进入云开发平台 ## 环境管理 开通环境后,您可以通过以下方式管理环境: ### 云开发控制台 访问 [CloudBase 云开发控制台](https://console.cloud.tencent.com/tcb/platform/env) 进行环境管理、资源配置等操作 ### 云开发平台(可视化管理) 访问 [云开发平台](https://tcb.cloud.tencent.com/dev) 进行可视化的数据管理、内容管理等操作 ![](https://qcloudimg.tencent-cloud.cn/raw/a3a29aa29388e49823e750f5e217e790.png) ## 关联微信小程序 在某些情况下,您可能要在 **微信开发者工具** 中使用 **腾讯云** 侧开通的 CloudBase 环境,使用云开发服务作为小程序的后端资源,那么您需要首先进行关联操作,步骤如下 ### 步骤1:登录控制台 登录 [CloudBase 云开发控制台](https://console.cloud.tencent.com/tcb),在菜单栏右上角的用户名下拉菜单中,单击账号信息,进入到账号中心 ⚠️ 注意:若您当前为 **子账号** 登录环境,需要切换登录到 **主账号** 进行登录 ### 步骤2:关联登录方式 在 **登录方式** 中,单击 **微信公众平台** 右侧的关联 ![](https://qcloudimg.tencent-cloud.cn/image/document/d437549578b326a5421ca01ec06a3d7c.png) ### 步骤3:授权操作 利用弹出的二维码进行微信登录后,在弹出的账号关联窗口中,单击「**去授权**」 按提示进行授权操作,即可完成账号关联 ### 步骤4:打开微信开发者工具,进入云开发控制台 接下来在微信开发者工具中使用该环境,您可以进行环境转换,将云侧创建的环境转换为微信小程序环境 打开开发工具,进入云开发控制台 ![](https://qcloudimg.tencent-cloud.cn/raw/b52828ae2056120cbb5bc7c96b8ba1e1.png) ### 步骤5:环境转换 1. 在 **云开发控制台** 中,进入「设置」,下拉「环境名称」列表,单击「管理我的环境」 ![](https://qcloudimg.tencent-cloud.cn/image/document/0d24994baf780aa28fffd688d9c5d91d.png) 2. 使用现有的云环境,在「微信开发者工具 > 环境管理」侧边栏中,单击使用已有腾讯云环境 3. 选择环境进行转换,选择您需要转换的云侧环境,确定环境转换,扫码完成验证后即可成功转换 ## 下一步 环境开通完成后,请根据您的开发需求选择对应的快速开始指南: * [微信小程序开发](/quick-start/mini-program/introduce) * [Web 应用开发](/quick-start/web/introduce) * [小游戏开发](/quick-start/game/introduce) * [托管后台服务开发](/run/quick-start/introduce) * [用 AI 工具开发](/ai/cloudbase-ai-toolkit/getting-started) --- ## 小游戏快速开始 # 小游戏快速开始 通过本指南,您将学会如何在小游戏中使用云开发,包括数据库、云存储和云函数等核心功能,快速构建具备后端能力的小游戏。 ## 🎮 微信小游戏 ### 📋 准备工作 在开始之前,请确保您已完成以下准备: 1. **开发工具**:下载并安装 [微信开发者工具](https://developers.weixin.qq.com/minigame/dev/devtools/download.html) 2. **小游戏账号**:[注册微信小游戏](https://mp.weixin.qq.com/),获取小游戏的 **AppID** 3. **基础库版本**:确保小游戏基础库版本 ≥ 2.2.3 4. **游戏引擎**:支持 Cocos Creator、Laya、白鹭等主流游戏引擎 ### 🚀 第 1 步:创建小游戏项目 1. **打开微信开发者工具**,使用微信扫码登录 2. **新建小游戏项目**: - 填入您的小游戏 **AppID** - 选择项目存放目录 ### ☁️ 第 2 步:开通云开发环境 按照 [开通云开发环境](/quick-start/create-env#方式一微信开发者工具推荐小程序开发者) 步骤进行开通 ### 💻 第 3 步:初始化云开发 在 `game.js` 中初始化云开发: ```javascript // game.js // 初始化云开发 if (!wx.cloud) { console.error('请使用 2.2.3 或以上的基础库以使用云能力'); } else { wx.cloud.init({ env: 'your-env-id', // 替换为您的环境 ID traceUser: true, }); } // 游戏主逻辑 class Game { constructor() { this.init(); } init() { // 游戏初始化逻辑 console.log('游戏初始化完成'); this.loadGameData(); } // 加载游戏数据 async loadGameData() { try { const db = wx.cloud.database(); const result = await db.collection('gameData').get(); console.log('游戏数据加载成功', result.data); } catch (error) { console.error('游戏数据加载失败', error); } } } // 启动游戏 new Game(); ``` ### 🎯 第 4 步:集成游戏引擎 #### Cocos Creator 集成 1. **安装云开发插件**: - 在 Cocos Creator 中打开「扩展」>「扩展商店」 - 搜索并安装「微信小游戏云开发」插件 2. **配置云开发**: ```javascript // 在 Cocos Creator 脚本中 cc.Class({ extends: cc.Component, onLoad() { // 初始化云开发 if (typeof wx !== 'undefined' && wx.cloud) { wx.cloud.init({ env: 'your-env-id' }); } }, // 保存游戏分数 async saveScore(score) { try { const db = wx.cloud.database(); await db.collection('scores').add({ data: { score: score, timestamp: new Date(), openid: '{openid}' // 自动填充 } }); console.log('分数保存成功'); } catch (error) { console.error('分数保存失败', error); } } }); ``` ### 🎮 第 5 步:实现核心游戏功能 #### 用户系统 ```javascript // 用户登录和数据管理 class UserManager { constructor() { this.userInfo = null; this.db = wx.cloud.database(); } // 用户登录 async login() { try { // 获取用户信息 const loginResult = await wx.cloud.callFunction({ name: 'login' }); this.userInfo = loginResult.result; await this.initUserData(); } catch (error) { console.error('登录失败', error); } } // 初始化用户数据 async initUserData() { try { const userCollection = this.db.collection('users'); const userDoc = await userCollection.doc(this.userInfo.openid).get(); if (userDoc.data.length === 0) { // 新用户,创建初始数据 await userCollection.add({ data: { _id: this.userInfo.openid, nickname: '新玩家', level: 1, score: 0, coins: 100, createTime: new Date() } }); } } catch (error) { console.error('用户数据初始化失败', error); } } } ``` #### 排行榜系统 ```javascript // 排行榜管理 class LeaderboardManager { constructor() { this.db = wx.cloud.database(); } // 提交分数 async submitScore(score) { try { await this.db.collection('leaderboard').add({ data: { score: score, timestamp: new Date(), openid: '{openid}' // 自动填充 } }); console.log('分数提交成功'); } catch (error) { console.error('分数提交失败', error); } } // 获取排行榜 async getLeaderboard(limit = 10) { try { const result = await this.db.collection('leaderboard') .orderBy('score', 'desc') .limit(limit) .get(); return result.data; } catch (error) { console.error('获取排行榜失败', error); return []; } } } ``` ### 🎯 第 6 步:体验云开发功能 创建完项目后,您可以体验以下功能: * **数据库**:存储游戏数据、用户信息、排行榜等 * **云存储**:上传游戏截图、音频资源等 * **云函数**:实现游戏逻辑、数据处理、第三方API调用 ### 📚 深入学习 * [数据库操作](/database/introduce) * [云存储管理](/storage/introduce) * [云函数开发](/cloud-function/introduce) * [微信小游戏官方文档](https://developers.weixin.qq.com/minigame/dev/guide/) ## 🎮 QQ 小游戏 ### 📋 准备工作 1. **开发工具**:下载并安装 [QQ 小游戏开发者工具](https://q.qq.com/wiki/tools/devtool/) 2. **QQ 小游戏账号**:注册 QQ 小游戏开发者账号 3. **腾讯云账号**:需要与腾讯云账号进行绑定 ### 🚀 快速开始 1. **创建项目**: - 打开 QQ 小游戏开发者工具 - 创建新的小游戏项目 - 选择云开发模板 2. **开通云开发**: - 通过 QQ 小游戏 IDE 访问云开发控制台 - 按照提示开通云开发环境 3. **账号绑定**: - 系统会自动引导您完成 QQ 小游戏账户与腾讯云账户的绑定 - 绑定后即可使用完整的云开发能力 ### 📚 学习资源 * [QQ 小游戏官方文档](https://q.qq.com/wiki/cloud/base/intro.html) :::tip 账号绑定说明 为方便开发者在 QQ 小游戏中使用云开发,系统会自动建立以下绑定关系: * 在「[身份提供商](https://console.cloud.tencent.com/cam/idp)」中建立身份提供商「TcbSamlProvider_qq」 * 在「[角色](https://console.cloud.tencent.com/cam/role)」中建立角色「TcbSamlRole_qq」 **重要**:上述信息是您在 QQ 小游戏中使用云开发的必要信息,请不要删除。 ::: ## 🎮 完整游戏示例:云端飞机大战 让我们通过一个完整的飞机大战游戏示例,展示如何在小游戏中使用云开发的各项功能。 当前案例以微信小游戏模版为基础进行开发 ### 游戏功能特性 * **实时排行榜**:使用数据库存储和展示玩家分数 ### 核心代码实现 #### 1. 排行榜主逻辑(这里只展示和数据的交互逻辑) ```javascript // js/runtime/leaderboard.js import Emitter from '../libs/tinyemitter'; import { SCREEN_WIDTH, SCREEN_HEIGHT } from '../render'; import leaderboardService from '../../services/leaderboard'; /** * 排行榜UI组件 * 负责排行榜的显示和交互 */ export default class Leaderboard extends Emitter { constructor() { super(); this.leaderboardData = []; // 排行榜数据 this.loading = false; // 是否正在加载 this.playerRank = 0; // 玩家当前排名 } /** * 加载排行榜数据 */ async loadLeaderboard() { try { const result = await leaderboardService.getLeaderboard(10); if (result.success) { this.leaderboardData = result.data; } else { console.error('加载排行榜失败:', result.error); this.leaderboardData = []; } } catch (error) { console.error('加载排行榜异常:', error); this.leaderboardData = []; } } /** * 加载玩家排名 */ async loadPlayerRank(score) { try { const result = await leaderboardService.getPlayerRank(score); if (result.success) { this.playerRank = result.rank; } } catch (error) { console.error('获取排名失败:', error); this.playerRank = 0; } } /** * 渲染排行榜 */ render(ctx) { if (!this.visible) return; // 绘制UI this.renderBackground(ctx); this.renderRankings(ctx); this.renderPlayerRank(ctx); // 其他渲染逻辑... } } ``` #### 2. 排行榜Service层 ```javascript // services/leaderboard.js - 排行榜数据管理 class LeaderboardService { constructor() { this.db = wx.cloud.database(); this.collection = this.db.collection('leaderboard'); } /** * 提交玩家分数 * @param {Object} scoreData - 分数数据 * @param {string} scoreData.nickname - 玩家昵称 * @param {number} scoreData.score - 玩家分数 * @param {string} scoreData.avatar - 玩家头像URL(可选) * @returns {Promise} 提交结果 */ async submitScore(scoreData) { try { const { nickname, score, avatar = '' } = scoreData; // 验证数据 if (!nickname || typeof score !== 'number') { throw new Error('昵称和分数不能为空'); } // 准备插入的数据 const data = { nickname, score, avatar, timestamp: new Date().toISOString(), createTime: new Date(), }; const result = await this.collection.add({ data, }); return { success: true, data: result, message: '分数提交成功', }; } catch (error) { console.error('提交分数失败:', error); return { success: false, error: error.message, }; } } /** * 获取排行榜数据 * @param {number} limit - 获取的记录数量,默认10条 * @returns {Promise} 排行榜数据 */ async getLeaderboard(limit = 10) { try { const result = await this.collection .orderBy('score', 'desc') // 按分数降序排列 .limit(limit) .get(); return { success: true, data: result.data, total: result.data.length, }; } catch (error) { console.error('获取排行榜失败:', error); return { success: false, error: error.message, data: [], }; } } /** * 获取玩家排名 * @param {number} score - 玩家分数 * @returns {Promise} 排名信息 */ async getPlayerRank(score) { try { // 获取比当前分数高的记录数量 const result = await this.collection .where({ score: this.db.command.gt(score), }) .count(); const rank = result.total + 1; // 排名从1开始 return { success: true, rank, message: `当前排名第${rank}位`, }; } catch (error) { console.error('获取排名失败:', error); return { success: false, error: error.message, rank: 0, }; } } } ``` ### 部署和测试 1. **创建数据库集合**: - `leaderboard` :存储排行榜信息 - `users` :存储用户信息 2. **设置数据库权限**: ```json { "read": "auth != null", "write": "auth != null && doc._openid == auth.openid" } ``` ## 🔗 相关资源 ### 示例项目 * [小游戏云开发示例](https://github.com/TencentCloudBase/awesome-cloudbase-examples/tree/master/minigame) ### 开发工具 * [云开发 CLI 工具](/quick-start/install-cli) * [云开发平台](https://tcb.cloud.tencent.com/dev) ### 学习文档 * [常见问题解答](/faq/) --- **🎉 开始您的小游戏云开发之旅!** 选择适合您的平台和游戏引擎,快速构建功能强大的云端小游戏。 --- ## HTTP API 快速开始 # HTTP API 快速开始 云开发 HTTP API 是一套为开发者设计的接口,旨在通过 HTTP 协议提供从客户端及服务端对云开发平台功能的访问。这些 API 允许开发者以编程方式实现用户认证、云函数、数据模型、AI 等功能,从而加速应用开发流程。 HTTP API 是通用的访问方式,您可以在任意端/语言中使用。本文将会以 Javascript 语言为例,介绍如何使用 HTTP API 。 :::tip 在 [HTTP API 文档](../../http-api/basic/overview) 中,我们为接口提供了不同语言的接入代码生成功能,包括 C++、Java、Go 等等。选择您的语言、复制粘贴,即可为您的应用接入 HTTP API 。 ::: --- ## 前置准备 在使用特定模块的 HTTP API 之前,请确认为对应角色开启了 HTTP API 权限。 1. [前往云后台](https://tcb.cloud.tencent.com/cloud-admin) -> 权限控制 -> 策略管理 2. 为角色设置各模块的开放 API (HTTP API)访问策略 ## 1. 身份验证 ### 匿名登录 ```javascript const env = "your-env-id"; const deviceId = Math.random().toString(36).substring(2, 15); // 随机生成,并应缓存到客户端 const { token_type, access_token } = await ( await fetch( `https://${env}.api.tcloudbasegateway.com/auth/v1/signin/anonymously`, { method: "POST", headers: { "x-device-id": deviceId, }, }, ) ).json(); console.log(token_type, access_token); ``` ### 用户名/密码登录 ```javascript const env = "your-env-id"; const deviceId = Math.random().toString(36).substring(2, 15); // 随机生成,并应缓存到客户端 const { token_type, access_token } = await ( await fetch(`https://${env}.api.tcloudbasegateway.com/auth/v1/signin`, { method: "POST", headers: { "x-device-id": deviceId, }, body: JSON.stringify({ password: "your-password", username: "your-username", }), }) ).json(); console.log(token_type, access_token); ``` [详情请参考用户认证 HTTP API](../../http-api/auth/登录认证接口) --- ## 2. 调用云函数 ```javascript const functonName = "add-two"; const functionParams = { a: 1, b: 101, }; const functionResult = await ( await fetch( `https://${env}.api.tcloudbasegateway.com/v1/functions/${functonName}`, { method: "POST", body: JSON.stringify(functionParams), headers: { "Content-Type": "application/json", Accept: "application/json", Authorization: `${token_type} ${access_token}`, }, }, ) ).text(); console.log(functionResult); ``` [详情请参考云函数 HTTP API](../../http-api/functions/云函数) --- ## 3. 调用云托管 ```javascript const cloudRunName = "helloworld"; const cloudRunResult = await ( await fetch( `https://${env}.api.tcloudbasegateway.com/v1/cloudrun/${cloudRunName}`, { headers: { Authorization: `${token_type} ${access_token}` }, }, ) ).text(); console.log(cloudRunResult); ``` [详情请参考云托管 HTTP API](../../http-api/cloudrun/云托管) --- ## 4. 使用云存储 ```javascript const objectId = "test.txt"; // 调用 HTTP API 获取上传信息 const [uploadInfo] = await ( await fetch( `https://${env}.api.tcloudbasegateway.com/v1/storages/get-objects-upload-info `, { headers: { Authorization: `${token_type} ${access_token}`, }, body: JSON.stringify([{ objectId }]), method: "POST", }, ) ).json(); // 使用上传信息进行上传 const uploadResult = await fetch(uploadInfo.uploadUrl, { method: "PUT", headers: { Authorization: uploadInfo.authorization, "X-Cos-Meta-Fileid": uploadInfo.cloudObjectMeta, "X-Cos-Security-Token": uploadInfo.token, }, body: "Hello, World!", }); console.log(uploadResult.status, uploadResult.statusText); ``` [详情请参考云存储 HTTP API](../../http-api/storage/云存储) --- ## 5. 查询数据模型 ```javascript const dataModelName = "post"; const listParams = { select: { $master: true }, getCount: true, pageSize: 3, }; const result = await ( await fetch( `https://${env}.api.tcloudbasegateway.com/v1/model/prod/${dataModelName}/list`, { headers: { Authorization: `${token_type} ${access_token}`, "Content-Type": "application/json", }, method: "POST", body: JSON.stringify(listParams), }, ) ).json(); console.log(JSON.stringify(result, null, 2)); ``` [详情请参考数据模型 HTTP API](../../http-api/model/数据模型-openapi) --- ## 6. 使用 AI 大模型 ```javascript const provider = "deepseek"; // 大模型提供商 const model = "deepseek-v3"; // 模型名 const llmMessages = [{ role: "user", content: "hi" }]; // 非流式生成文本 const llmGenerateResult = await ( await fetch( `https://${env}.api.tcloudbasegateway.com/v1/ai/${provider}/chat/completion`, { headers: { Authorization: `${token_type} ${access_token}`, "Content-Type": "application/json", }, method: "POST", body: JSON.stringify({ model, messages: llmMessages, stream: false, // 非流式,stream 为 false }), }, ) ).json(); console.log(JSON.stringify(llmGenerateResult, null, 2)); // 流式生成文本 const llmStreamResult = await ( await fetch( `https://${env}.api.tcloudbasegateway.com/v1/ai/${provider}/chat/completion`, { headers: { Authorization: `${token_type} ${access_token}`, "Content-Type": "application/json", Accept: "text/event-stream", }, method: "POST", body: JSON.stringify({ model, messages: llmMessages, stream: true, // 流式,stream 为 true }), }, ) ).text(); console.log(llmStreamResult); ``` [详情请参考 AI 大模型接入 HTTP API](../../http-api/ai-model/ai-大模型接入) --- ## 7. 使用智能体 (Agents) ```javascript const agentId = "your-agent-id"; // 填写云开发平台上创建的 Agent ID const agentMessages = [{ role: "user", content: "hi" }]; // 非流式生成文本 const agentGenerateResult = await ( await fetch( `https://${env}.api.tcloudbasegateway.com/v1/aibot/openai/chat/completions`, { headers: { Authorization: `${token_type} ${access_token}`, "Content-Type": "application/json", }, method: "POST", body: JSON.stringify({ model: agentId, messages: agentMessages, stream: false, // 非流式,stream 为 false }), }, ) ).json(); console.log(JSON.stringify(agentGenerateResult, null, 2)); // 流式生成文本 const agentStreamResult = await ( await fetch( `https://${env}.api.tcloudbasegateway.com/v1/aibot/openai/chat/completions`, { headers: { Authorization: `${token_type} ${access_token}`, "Content-Type": "application/json", Accept: "text/event-stream", }, method: "POST", body: JSON.stringify({ model: agentId, messages: agentMessages, stream: true, // 流式,stream 为 true }), }, ) ).text(); console.log(agentStreamResult); ``` [详情请参考 AI 智能体接入 HTTP API](../../http-api/ai-bot/ai-agent-接入) --- [点击查看更多 HTTP API 详情](../../http-api/basic/overview) --- ## 快速开始 # 快速开始 欢迎使用云开发!本指南将帮助您在 5 分钟内快速上手云开发,构建您的第一个应用。 ## 🚀 选择您的开发场景 根据您要开发的应用类型,选择对应的快速开始路径: | 开发场景 | 适用场景 | 推荐工具 | 特点 | 快速开始 | | ----------- | ------- | ------- | ------- | ------- | | **📱 微信小程序开发** | 开发微信小程序 | 云开发能力 | • 与微信生态深度集成• 开箱即用的云开发能力• 支持云函数、数据库、云存储 | [开始小程序开发 →](/quick-start/mini-program/introduce) | | **🌐 Web 应用开发** | 开发网站、H5 应用或 Web 应用 | 云开发的静态托管和后端服务 | • 支持静态网站托管• 提供完整的后端服务• 支持 React、Vue 等主流框架 | [开始 Web 开发 →](/quick-start/web/introduce) | | **🎮 小游戏开发** | 开发微信小游戏 | 云开发能力 | • 提供游戏服务器托管• 支持实时对战、排行榜功能• 高性能游戏数据存储 | [小游戏开发指南 →](/quick-start/game/introduce) | | **☁️ 托管后台服务** | 开发API服务、数据处理服务、定时任务 | 云函数、云托管 | • 自动弹性伸缩• 按量计费• 支持多种编程语言 | [后台服务开发 →](/run/quick-start/introduce) | | **🤖 AI开发工具开发** | 集成AI能力到应用中 | 云开发AI工具集 | • **AI 智能开发**:自动生成代码和架构设计• **云开发集成**:一键接入数据库、云函数、静态托管• **快速部署**:几分钟内完成全栈应用上线• **全栈支持**:Web + 小程序 + 后端一体化 • **智能修复**:AI 自动查看日志并修复问题| [AI开发指南 →](/ai/cloudbase-ai-toolkit/getting-started) | ## 📋 开发前准备 无论选择哪种开发方式,您都需要: ### 1. 开通云开发环境 云开发环境是您应用的后端基础设施,包含数据库、存储、云函数等服务。 [立即开通环境 →](/quick-start/create-env) ### 2. 安装开发工具(可选) 如果您需要使用命令行工具进行开发和部署: [安装 CLI 工具 →](/quick-start/install-cli) ## 🎯 5 分钟快速体验 想要快速体验云开发的能力?我们为您准备了最简单的入门示例: ### Web 快速体验 ```html Hello CloudBase! // 初始化云开发 const app = cloudbase.init({ env: '您的环境ID' // 替换为您的环境ID }); // 匿名登录 const login = async () => { const auth = app.auth() await auth.signInAnonymously() console.log('登录成功!'); const userInfo = await auth.getUserInfo(); alert(`云开发连接成功!${userInfo.name}`); } login() ``` ### 小程序快速体验 ```javascript // app.js App({ onLaunch() { // 初始化云开发 wx.cloud.init({ env: '您的环境ID' // 替换为您的环境ID }); console.log('云开发初始化完成'); } }); ``` ## 🔗 相关资源 * [常见问题](/faq/) - 开发过程中的常见问题解答 ## � 获取帮助 遇到问题?我们提供多种支持方式: * [GitHub Issues](https://github.com/TencentCloudBase/cloudbase-js-sdk/issues) - 提交 Bug 或功能请求 * [开发者社区](https://cnb.cool/tencent/cloud/cloudbase/community/-/issues) - 与其他开发者交流 --- **准备好了吗?** 选择上面的任一路径开始您的云开发之旅! --- ## 安装 CLI 工具 # 安装 CLI 工具 CloudBase CLI 是云开发官方提供的[命令行工具](https://github.com/TencentCloudBase/cloudbase-cli),让您可以通过命令行快速管理云开发资源、部署应用、管理数据库等。 ## 🌟 CLI 工具的优势 - **🚀 快速部署**:一键部署云函数、静态网站 - **📊 资源管理**:管理数据库、存储、环境配置 - **🔄 自动化**:支持 CI/CD 集成 - **💻 跨平台**:支持 Windows、macOS、Linux - **🛠️ 丰富功能**:涵盖云开发所有核心功能 ## 📋 系统要求 - **Node.js**:版本 ≥ 12.0.0(推荐 LTS 版本) - **npm**:版本 ≥ 6.0.0 - **操作系统**:Windows、macOS、Linux ## 🚀 第 1 步:安装 Node.js 如果您还没有安装 Node.js,请先安装: ### 方式一:官网下载(推荐) 1. 访问 [Node.js 官网](https://nodejs.org/zh-cn/) 2. 下载 **LTS 版本**(长期支持版本) 3. 按照安装向导完成安装 ### 方式二:使用包管理器 **macOS(使用 Homebrew)**: ```bash brew install node ``` **Windows(使用 Chocolatey)**: ```bash choco install nodejs ``` **Ubuntu/Debian**: ```bash sudo apt update sudo apt install nodejs npm ``` ### 验证安装 ```bash node --version npm --version ``` ## ⚡ 第 2 步:安装 CloudBase CLI 打开命令行终端,执行以下命令: ```bash npm install -g @cloudbase/cli ``` ### 安装问题解决 **权限错误(macOS/Linux)**: ```bash sudo npm install -g @cloudbase/cli ``` **网络问题**: ```bash # 使用淘宝镜像 npm install -g @cloudbase/cli --registry=https://registry.npmmirror.com ``` **Windows 权限问题**: 以管理员身份运行命令提示符或 PowerShell :::tip 安装建议 - 推荐使用 LTS 版本的 Node.js - 如果安装失败,可能需要[修改 npm 权限](https://docs.npmjs.com/resolving-eacces-permissions-errors-when-installing-packages-globally) - 企业网络环境可能需要配置代理 ::: ## ✅ 第 3 步:验证安装 安装完成后,验证 CLI 是否正常工作: ```bash # 查看版本号 cloudbase --version # 或使用简写命令 tcb --version ``` 如果看到版本号输出,说明安装成功! ## 🎯 第 4 步:了解基本命令 CloudBase CLI 提供了丰富的命令,以下是一些常用命令: ### 查看帮助 ```bash # 查看所有命令 cloudbase --help # 查看特定命令的帮助 cloudbase login --help ``` ### 登录和环境管理 ```bash # 登录到云开发 cloudbase login # 查看环境列表 cloudbase env:list # 切换环境 cloudbase env:switch ``` ### 部署相关 ```bash # 部署云函数 cloudbase functions:deploy # 部署静态网站 cloudbase hosting:deploy # 一键部署(根据配置文件) cloudbase deploy ``` :::tip 命令简写 为了简化输入,`cloudbase` 命令可以简写成 `tcb`: - `cloudbase login` = `tcb login` - `cloudbase deploy` = `tcb deploy` `tcb` 是云开发产品英文的简称:**T**encent **C**loud**B**ase ::: ## 🔧 第 5 步:配置代理(可选) 如果您的网络环境需要代理才能访问外网,可以配置 HTTP 代理: ### 临时设置 ```bash # macOS/Linux export HTTP_PROXY=http://127.0.0.1:8000 export HTTPS_PROXY=http://127.0.0.1:8000 # Windows set HTTP_PROXY=http://127.0.0.1:8000 set HTTPS_PROXY=http://127.0.0.1:8000 ``` ### 永久设置 将代理配置添加到系统环境变量或终端配置文件中(如 `.bashrc`、`.zshrc`)。 ## 🚀 第 6 步:开始使用 现在您可以开始使用 CLI 工具了! ### 首次使用流程 1. **登录**:`cloudbase login` 2. **选择环境**:`cloudbase env:list` 查看环境,`cloudbase env:switch` 切换 3. **初始化项目**:`cloudbase init` 创建项目模板 4. **部署应用**:`cloudbase deploy` 一键部署 ## 🆘 获取帮助 如果在使用过程中遇到问题: 1. **查看帮助**:`cloudbase --help` 或 `cloudbase --help` 2. **查看文档**:[CLI 文档](/cli-v1/intro) 3. **提交 Issue**:[GitHub Issues](https://github.com/TencentCloudBase/cloudbase-cli/issues) --- **🎉 恭喜!** 您已经成功安装了 CloudBase CLI 工具。现在可以开始高效的云开发之旅了! --- ## 小程序快速开始 # 小程序快速开始 通过本指南,您将学会如何在小程序中使用云开发,包括数据库、云存储和云函数等核心功能。 ## 📱 微信小程序 ### 📋 准备工作 在开始之前,请确保您已完成以下准备: 1. **开发工具**:下载并安装 [微信开发者工具](https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html) 2. **小程序账号**:[注册微信小程序](https://mp.weixin.qq.com/),获取小程序的 **AppID** 3. **基础库版本**:确保小程序基础库版本 ≥ 2.2.3 ### 🚀 第 1 步:创建小程序项目 1. **打开微信开发者工具**,使用微信扫码登录 2. **新建小程序项目**: - 填入您的小程序 **AppID** - 选择项目存放目录 - **重要**:后端服务选择「**微信云开发**」 - 勾选同意「云开发服务条款」 3. **选择模板**:推荐选择「云开发 QuickStart」模板 ### ☁️ 第 2 步:开通云开发环境 按照 [开通云开发环境](/quick-start/create-env#方式一微信开发者工具推荐小程序开发者) 步骤进行开通 ### 💻 第 3 步:初始化云开发 在 `app.js` 中初始化云开发: ```javascript // app.js App({ onLaunch() { // 初始化云开发 if (!wx.cloud) { console.error('请使用 2.2.3 或以上的基础库以使用云能力'); } else { wx.cloud.init({ env: 'your-env-id', // 替换为您的环境 ID traceUser: true, }); } } }); ``` ### 🎯 第 4 步:体验云开发功能 创建完项目后,您可以体验以下功能: * **数据库**:点击「数据库」按钮,体验数据的增删改查 * **云存储**:点击「存储」按钮,体验文件上传和下载 * **云函数**:点击「云函数」按钮,体验服务端逻辑调用 ### 📚 深入学习 * [数据库操作](/database/introduce) * [云存储管理](/storage/introduce) * [云函数开发](/cloud-function/introduce) * [微信小程序官方文档](https://developers.weixin.qq.com/miniprogram/dev/wxcloud/basis/getting-started.html) ## 🎮 QQ 小程序 ### 📋 准备工作 1. **开发工具**:下载并安装 [QQ 小程序开发者工具](https://q.qq.com/wiki/tools/devtool/) 2. **QQ 小程序账号**:注册 QQ 小程序开发者账号 3. **腾讯云账号**:需要与腾讯云账号进行绑定 ### 🚀 快速开始 1. **创建项目**: - 打开 QQ 小程序开发者工具 - 创建新的小程序项目 - 选择云开发模板 2. **开通云开发**: - 通过 QQ 小程序 IDE 访问云开发控制台 - 按照提示开通云开发环境 3. **账号绑定**: - 系统会自动引导您完成 QQ 小程序账户与腾讯云账户的绑定 - 绑定后即可使用完整的云开发能力 ### 📚 学习资源 * [QQ 小程序官方文档](https://q.qq.com/wiki/cloud/base/intro.html) :::tip 账号绑定说明 为方便开发者在 QQ 小程序中使用云开发,系统会自动建立以下绑定关系: * 在「[身份提供商](https://console.cloud.tencent.com/cam/idp)」中建立身份提供商「TcbSamlProvider_qq」 * 在「[角色](https://console.cloud.tencent.com/cam/role)」中建立角色「TcbSamlRole_qq」 **重要**:上述信息是您在 QQ 小程序中使用云开发的必要信息,请不要删除。 ::: ## 🔗 相关资源 ### 示例项目 * [小程序云开发示例](https://github.com/TencentCloudBase/awesome-cloudbase-examples/tree/master/miniprogram) ### 开发工具 * [云开发 CLI 工具](/quick-start/install-cli) * [云开发平台](https://tcb.cloud.tencent.com/dev) ### 学习文档 * [常见问题解答](/faq/) --- **🎉 开始您的小程序云开发之旅!** 选择适合您的平台,快速构建功能强大的小程序应用。 --- ## Web 应用快速开始 # Web 应用快速开始 通过本指南,您将学会如何使用云开发构建和部署 Web 应用,包括静态网站、动态网站、SSR 等多种应用形式。 ## 🌟 云开发 Web 应用的优势 * **🚀 快速部署**:一键部署到全球 CDN * **🔒 安全可靠**:内置身份认证和权限管理 * **📊 数据管理**:数据库和云存储 * **⚡ 高性能**:全球加速和智能缓存 * **💰 成本优化**:按需付费,无需维护服务器 ## 📋 准备工作 在开始之前,请确保您已完成: 1. **开通云开发环境**:[开通云开发环境](/quick-start/create-env) 2. **安装 Node.js**:[下载 Node.js](https://nodejs.org/en/)(建议 LTS 版本) 3. **安装 CLI 工具**:[安装 CloudBase CLI](/quick-start/install-cli) ## 🚀 第 1 步:使用官方模板(推荐) ### 1. 选择技术栈 我们提供多种主流框架的模板: * **React + Vite**:[cloudbase-react-template](https://github.com/TencentCloudBase/awesome-cloudbase-examples/tree/master/web/cloudbase-react-template) * **Vue + Vite**:[cloudbase-vue-template](https://github.com/TencentCloudBase/awesome-cloudbase-examples/tree/master/web/cloudbase-vue-template) ### 2. 克隆模板项目 以 React 模板为例: ```bash # 克隆项目 git clone https://github.com/TencentCloudBase/awesome-cloudbase-examples.git # 进入项目 cd awesome-cloudbase-examples/web/cloudbase-react-template # 安装依赖 npm install ``` ### 3. 配置环境 1. **配置环境 ID**: 将 `src/utils/cloudbase.js` 中的 `ENV_ID` 替换为您的环境 ID ```javascript // src/utils/cloudbase.js const ENV_ID = 'your-env-id'; // 替换为您的环境 ID ``` 2. **配置部署域名**: 将 `vite.config.js` 中的 base 路径替换为您的云开发环境域名 ```javascript // vite.config.js export default { base: '/react-temp/', // 自定义根路径,部署后通过 $ip/react-temp/ 访问 // ... 其他配置 } ``` ## 🔧 第 2 步:配置安全域名 在使用云开发 Web SDK 之前,需要配置安全域名: 1. 登录 [云开发控制台](https://console.cloud.tencent.com/tcb) 2. 进入「环境」>「安全配置」 3. 在「Web 安全域名」中添加您的域名: - 本地开发: `localhost:3000` 、 `127.0.0.1:3000` - 生产环境:您的实际域名 :::tip 安全域名说明 只有在安全域名列表中的域名才能使用云开发 Web SDK,这是为了保护您的数据安全。 ::: ## 🎯 第 3 步:开启身份认证 为了让用户能够登录,需要开启匿名登录: 1. 在云开发控制台进入「环境」>「登录授权」 2. 启用「匿名登录」 3. 保存配置 ## 🚀 第 4 步:本地开发 ### 使用模板项目 ```bash # 启动开发服务器 npm run dev ``` 项目将在 `http://localhost:5173` 启动(端口可能不同) ![](https://qcloudimg.tencent-cloud.cn/raw/3679ae26b28e34baaabe823cca3bc8c1.png) ## 🚀 第 5 步:部署到云开发 ### 方式一:使用 CLI 部署(推荐) 1. **构建项目**: ```bash npm run build ``` 2. **登录 CLI**: ```bash cloudbase login ``` 3. **开通静态托管**: 在云开发控制台开通「静态网站托管」服务 4. **部署应用**: ```bash # 部署构建产物到静态托管 cloudbase hosting deploy dist -e your-env-id ``` ### 方式二:控制台手动上传 1. **构建项目**:生成 `dist` 目录 2. **上传文件**: - 登录 [云开发控制台/静态网站托管](https://console.cloud.tencent.com/tcb/hosting/index) - 上传 `dist` 目录中的所有文件到 `vite.config.js` 中 `base` 一致的路径 ![](https://qcloudimg.tencent-cloud.cn/raw/342142a1796aaa2633b82639b057a05b.png) 3. **访问应用**: 使用分配的默认域名访问您的应用 ![](https://qcloudimg.tencent-cloud.cn/raw/ed338f41e87e95ad7f08fea4f5c59cb1.png) ## 🎯 第 7 步:添加云开发功能 现在您可以为 Web 应用添加强大的后端能力: ### 数据库示例 ```javascript // 获取数据库引用 const db = app.database(); // 添加数据 async function addData() { try { const result = await db.collection('todos').add({ title: '学习云开发', completed: false, createTime: new Date() }); console.log('添加成功', result); } catch (error) { console.error('添加失败', error); } } // 查询数据 async function getData() { try { const result = await db.collection('todos').get(); console.log('查询结果', result.data); } catch (error) { console.error('查询失败', error); } } ``` ### 云存储示例 ```javascript // 上传文件 async function uploadFile(file) { try { const result = await app.uploadFile({ cloudPath: `images/${Date.now()}-${file.name}`, filePath: file }); console.log('上传成功', result); return result.fileID; } catch (error) { console.error('上传失败', error); } } ``` ### 云函数调用示例 ```javascript // 调用云函数 async function callFunction() { try { const result = await app.callFunction({ name: 'hello', data: { name: 'CloudBase' } }); console.log('调用成功', result); } catch (error) { console.error('调用失败', error); } } ``` ## 📚 深入学习 ### 核心功能 * [数据库](/database/introduce) - 存储和查询数据 * [云存储](/storage/introduce) - 文件存储和管理 * [云函数开发](/cloud-function/introduce) - 服务端逻辑 ### 高级功能 * [静态网站托管](/hosting/introduce) - 网站部署和 CDN ### 开发工具 * [@cloudbase/js-sdk 文档](/api-reference/webv3/initialization) * [云开发 CLI 工具](/quick-start/install-cli) * [云开发平台](https://tcb.cloud.tencent.com/dev) ### 学习文档 * [常见问题解答](/faq/) --- **🎉 恭喜!** 您已经成功创建并部署了第一个云开发 Web 应用。现在可以开始构建更复杂的功能了! --- ## 使用入门 # 使用入门 安全规则为数据库与云存储中的数据提供强大的、完全可自定义的保护。您可以按照本指南中的步骤轻松开始使用规则,确保数据安全,并保护您的应用免受恶意用户攻击。 ## 准备:了解安全规则语言 安全规则语言使用一种 JSON 结构,`key` 指代操作类型,`value` 为允许操作是的条件,可以为 `boolean` 或`表达式字符串`,表达式字符串语法类似 Javascript 语言,其是单个逻辑表达式,或多个逻辑表达式通过与/或方式组合,当表达式的计算值决定了操作是否被允许。 ## 1. 定义规则和数据结构 安全规则提供了内部变量获取请求数据的内容以根据数据进行访问控制,数据的组织方式可能会影响规则的写法,例如,论坛应用中需要限制所有登录用户可以浏览内容,用户只能修改、删除自己的帖子,那么论坛帖集合(posts)中记录需要存储 userID 表示记录归属,安全规则根据 userID 字段限制 update 与 delete 行为,放过所有的登录用户的 read 行为。 ## 2. 获取安全规则 使用/查看现有安全规则可登录[云开发控制台](https://console.cloud.tencent.com/tcb),选定需要的环境,进入数据库集合权限控制页或云存储权限控制页,可以选择使用高级权限控制或查看已经在使用的安全规则。 1. 以数据库集合权限管理为例,进入[控制台](https://console.cloud.tencent.com/tcb/database),选择对应环境,查看环境下数据库集合的详情信息。 1. 在详情中切换至权限设置页面,可由基础权限控制选择切换为安全规则。![权限设置](https://main.qcloudimg.com/raw/82da420358175617e86c355b63832ed7.png) 1. 选择切换为安全规则,系统会根据已有的基础权限转化为对应的安全规则信息,开发者也可在其基础上进行修改。![切换安全规则](https://main.qcloudimg.com/raw/e3a28796274c4baee53fba35a829a300.png) 1. 已经设置成功,正在使用的安全规则后续可以在权限设置中进行查看及修改。![获取安全规则](https://main.qcloudimg.com/raw/a756d3199e0440209b94302fb2c4f543.png) ## 3. 编辑发布安全规则 在云开发控制台权限控制页中可编辑所需的安全规则,例如上述论坛应用的例子,可改 posts 集合的权限为以下规则: ```json { "read": "auth != null", // 所有登录用户可读 "create": "auth != null", // 所有登录用户可以发帖 "update": "doc.userID == auth.openid", // 用户只能修改自己的帖子 "delete": "doc.userID == auth.openid" // 用户只能删除自己的帖子 } ``` 通过保存按鈕使编辑的新规则部署云端,保存成功后安全规则即时生效。 --- ## 安全规则 # 安全规则 ## 简介 安全规则是在基础权限控制之上的一种更高级、更灵活、更可扩展的权限控制方式,专为保护用户云端数据安全而设计。 ### 为什么需要安全规则? 基础权限控制是根据开发过程中常见场景预置的权限组,能够实现简单的权限管控。然而,随着应用业务场景日益复杂,这种管控方式已无法满足根据用户角色或登录模式等条件进行精细化管控的需求。 在传统的基础权限控制模式下,要实现复杂的权限管理,开发者需要: - 将所有客户端操作集中到云函数中 - 在云函数内部编写校验判断逻辑 - 通过这种方式间接实现访问控制 而使用安全规则,开发者可以: - 自定义精确的管控条件 - 通过简洁的规则语句完成权限配置 - 让系统根据规则自动完成访问控制 - 实现数据校验等更高级功能 安全规则基于 JSON 格式的可扩展配置语言,清晰定义用户可访问的数据库与存储资源范围。开发者可根据应用需求的细化程度,编写简单或复杂的规则来全面保护应用数据。 ## 核心优势 1. **高度灵活性** - 开发者可根据业务特性自定义规则,支持基于应用数据本身的动态访问控制,实现条件化的数据访问策略。 2. **精细化粒度** - 规则可以精确到字段级别,根据需求设置简单或复杂的访问条件,满足不同场景的安全需求。 3. **安全性与独立性** - 规则在管理端独立配置,完全分离于应用业务逻辑: - 客户端无法获取规则内容 - 无法绕过规则验证 - 确保所有数据访问都经过严格校验 4. **开发便捷性** - 通过配置式规则即可完成权限控制: - 无需开发额外的接入层管控代码 - 免去复杂的部署流程 - 支持快速验证和调整 ## 工作原理 安全规则的工作流程如下: 1. **规则读取** - 当用户尝试访问数据时,系统首先读取管理端设置的完整规则配置(JSON格式) 2. **操作匹配** - 系统根据请求的操作类型(如`read`、`write`等)匹配对应的规则配置 3. **规则解析** - 配置值可能是: - 简单的布尔值(`true`/`false`) - 类JavaScript语法的逻辑表达式字符串 4. **权限判定** - 当布尔值为`true`或表达式计算结果为`true`时,允许访问;否则拒绝访问 5. **操作执行** - 只有在允许访问的情况下,系统才会执行后续的数据操作 ### 基础规则配置示例 ```json { // 读取权限:设为false表示禁止读取 "read": false, // 写入权限:使用条件表达式动态判断 "write": > } ``` 表达式中可使用内置变量获取请求的身份信息和元数据,实现复杂的逻辑判断。要深入了解规则语法和可用变量,请参阅[规则语言详解](./learn-rules)。 ## 计费说明 安全规则功能本身**完全免费**,不收取任何额外费用。但需要注意: - 规则中使用元数据变量(如`doc`、`resource`)或获取函数(如`get`)时,会对相应资源产生读取操作 - 这些读取操作将消耗相应资源的用量配额 - 计费方式遵循各资源自身的计费规则 ## 使用限制 ### 表达式限制 - 每个表达式(组)最大长度限制为**1024字符** ### 支持的语法元素 - **变量**:支持各类变量引用(不支持正则表达式) - **数组表达式**:数组成员限制为数字或字符串类型 - **逻辑表达式**:支持`&&`(与)、`||`(或)等逻辑运算符 - **一元表达式**:支持`+1`、`-1`、`!a`等一元运算 - **二元表达式**:支持`>`、`>=`、`<`、`<=`、`==`、`!=`、`in`等比较运算符 - **成员表达式**:支持`a.b`、`a["b"]`等成员访问方式 - **调用表达式**:仅数据库安全规则支持函数调用 - **字符串模板表达式**:用于数据库函数调用的动态参数,例如:\`database.collection.\$\{doc.objectId}\` --- ## 了解安全规则 import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # 了解安全规则 ## 安全规则语言 安全规则基于灵活、强大的自定义语言,能够支持各种复杂度和精细化程度的权限控制。开发者可以根据应用的具体需求,设置特定的规则或一般性的规则。安全规则使用 JSON 结构,其中: - `key` 指代操作类型(如读取、写入等) - `value` 为允许操作的条件,可以是: - 简单的 `boolean` 值(true/false) - 类似 JavaScript 的表达式字符串 表达式可以是单个逻辑表达式,或通过与/或逻辑组合的多个表达式,系统会根据表达式的计算结果决定是否允许操作。 由于安全规则是专门设计的语言,可能需要一定的学习时间。本指南将帮助您理解规则语言的基础知识,为后续编写更复杂的规则打下基础。 ### 基本结构与语法 安全规则基于 JSON 结构,`value` 为 `boolean` 或类似 JavaScript 的表达式: ```JSON { "read": true, "write": >, "create": true, "update": false, "delete": > } ``` 其中包含几个关键概念 - **操作类型:** JSON `key` 为支持权限控制的操作类型,`create`、`delete`、`read`、`update`为集合的增删查改操作,`write` 为简便的控制集合的写权限配置,若没有配置 `create`、`delete`、`update` 操作,则按照 `write` 配置处理。 - **规则:** JSON `value` 为规则条件,可以为 `boolean` 值或逻辑表达式(组),当条件值为 true 时表示允许进行操作。 默认情况下,遇到没有定义的操作类型,则拒绝该操作访问 安全规则基于 JSON 结构,`value` 为 `boolean` 或类似 JavaScript 的表达式: ```JSON { "read": true, "write": >, } ``` 其中包含几个关键概念 - **操作类型:** JSON `key` 为支持权限控制的操作类型,`read`、`write`为云存储文件的读写操作。 - **条件:** JSON `value` 为规则条件,可以为 `boolean` 值或逻辑表达式(组),当条件值为 true 时表示允许进行操作。 默认情况下,遇到没有定义的操作类型,则拒绝该操作访问 云函数安全规则基于 JSON 结构,层级较特殊,顶级 `key` 为表示函数名,value 为对应函数的权限配置,也为 JSON 格式,子配置 `key` 为操作名(invoke),`value` 为 `boolean` 或类似 JavaScript 的表达式: ```JSON { "*": { "invoke": "auth!==null" }, "function1": { "invoke": false }, "function3": { "invoke": true } } ``` 其中包含几个关键概念 - **函数名:** JSON 顶级 `key` 为函数名,用于匹配获取某个具体函数的配置,特殊的允许配置 `*` 作为函数名的通配符,当没有匹配到具体函数时将获取 `*` 的配置,云函数安全规则中必须包含 `*` 配置。 - **操作类型:** 函数名下子配置 JSON 的 `key` 为操作类型,暂只支持 invoke,且必须为 invoke。 - **条件:** 子配置 JSON `value` 为规则条件,可以为 `boolean` 值或逻辑表达式(组),当条件值为 true 时表示允许进行操作。表达式只支持使用 `auth!=null`。 ### 条件构造 条件可以为 `boolean` 或`表达式字符串`,表达式字符串语法类似 Javascript 语言,其是单个逻辑表达式,或多个逻辑表达式通过与/或方式组合,当表达式的计算值决定了操作是否被允许。 #### 预置变量 | 变量 | 类型 | 说明 | | ------- | ------------------- | ----------------------------------------------------------------------------------------------------------------------- | | now | number | 当前时间戳,表示从 Linux 计时原点开始的毫秒数 | | auth | [Auth](#auth) | 用户登录信息,包含 uid(用户唯一ID)和 loginType(登录类型);未登录时为 null | | doc | Object | 当前操作的记录对象,引用时会从服务中读取一次,此查询会计入相关资源配额 | | request | [Request](#request) | 请求对象,包含请求相关的各种信息 | ##### Auth | 字段名 | 类型 | 说明 | | :-------- | :----- | :------------------------------------------------------------ | | loginType | string | 登录方式,如公众平台登录、开放平台登录、自定义登录、匿名登录等 | | uid | string | 用户唯一标识ID,注意:微信小程序请求中不包含此值 | | openid | string | 用户的微信openid,仅在微信相关登录方式下存在 | ##### LoginType 枚举值 | 枚举值 | 登录方式 | | ------------- | ------------ | | WECHAT_PUBLIC | 微信公众号 | | WECHAT_OPEN | 微信开放平台 | | ANONYMOUS | 匿名登录 | | EMAIL | 邮箱登录 | | CUSTOM | 自定义登录 | ##### Request | 字段名 | 类型 | 说明 | | :----- | :----- | :------------------------------------------------------------------- | | data | object | 请求传入的数据对象,仅在 create 和 update 操作类型时存在 | 变量可用于规则表达式中,通过 `doc` 与 `request.data` 可以获取数据当前的值与请求传入的值。例如,在订单集合中,为防止订单金额被篡改,可使用以下规则: ```JSON { // ... 其他规则 ... // "update": "doc.price == request.data.price || request.data.price == undefined" // ... 其他规则 ... // } ``` 这条规则确保:要么请求不修改价格字段,要么修改后的价格与原价格相同。 #### 内置方法 目前仅支持 [get](./reference/function#get) 函数,该函数接受一个参数,格式必须为 `database.集合名称.文档id`。通过此函数,您可以访问其它文档的数据,用于判断当前操作是否符合安全规则。 例如,检查用户是否有权限修改特定文档: ```JSON { "update": "get(`database.users.${auth.uid}`).role == 'admin'" } ``` #### 预置变量 | 变量 | 类型 | 说明 | | -------- | --------------------- | -------------------------------------------------------------------------------------------- | | now | number | 当前时间戳,表示从 Linux 计时原点开始的毫秒数 | | auth | [Auth](#auth-2) | 用户登录信息,包含 uid(用户唯一ID)和 loginType(登录类型);未登录时为 null | | resource | [Resource](#resource) | 请求文件的元数据信息,引用时会从服务中读取一次 | ##### Auth | 字段名 | 类型 | 说明 | | :-------- | :----- | :------------------------------------------------------------ | | loginType | string | 登录方式 公众平台登录,开放平台登录,自定义登录,匿名登录等等 | | uid | string | 用户唯一 id,微信小程序的请求没有此值 | | openid | string | 用户 openid,仅在微信登录方式下存在值 | ##### LoginType 枚举 | 枚举值 | 登录方式说明 | | ------------- | ------------ | | WECHAT_PUBLIC | 微信公众号 | | WECHAT_OPEN | 微信开放平台 | | ANONYMOUS | 匿名登录 | | EMAIL | 邮箱登录 | | CUSTOM | 自定义登录 | ##### Resource | 字段名 | 类型 | 说明 | | ------ | ------ | ---------------------------------------------------------------------------------------------------- | | openid | string | 文件的私有归属标识,用于标记文件所有者ID | | path | string | 文件在云存储中的相对路径(不包含桶名),格式为 `path/image.jpg`,**注意:路径起始不包含 ./、/、. 等路径符** | 变量可用于规则表达式中,例如:设置 public 目录下的文件所有用户可读,但限制用户只能修改归属于自己的文件。 ```JSON { "read": "/^public\\//.test(resource.path) == true", "write": "resource.openid == auth.uid" } ``` 这条规则确保: 1. 所有以 "public/" 开头的路径中的文件对所有用户可读 2. 用户只能修改自己创建的文件(文件所有者ID与用户ID匹配) #### 特殊方法 云存储安全规则支持特殊的正则表达式语法。您可以通过字面量方式引入正则对象(例如 `/^reg\$/`),并通过调用正则对象的 `test` 方法来验证参数是否匹配该正则表达式。 :::tip 重要注意事项 1. 在规则表达式中使用 `test` 方法时,必须显式地与 `true` 或 `false` 进行比较。例如: - 正确写法:`read: "/^public/.test(resource.path) == true"` - 错误写法:`read: "/^public/.test(resource.path)"` 2. 由于安全规则表达式存储在字符串中,正则表达式中的特殊字符需要进行多重转义: - 例如,要匹配字符串 `test/image`: - 正则对象本身为:`/^test\/image/` - 在规则表达式中应写为:`"/^test\\/image/.test(resource.path)"` 3. 转义规则:在JSON字符串中表示正则表达式时,反斜杠`\`需要写成`\\` ::: #### 预置变量 | 变量 | 类型 | 说明 | | ---- | ---- | ------------------------------------------------------------------------- | | auth | - | 云函数安全规则中,auth 只有 null 与非 null 两种状态,不支持访问 auth 的成员属性 | #### 运算符 | 运算符 | 说明 | 示例 | 含义说明 | | :---------- | :--------------------- | :--------------------------- | :--------------------------------------- | | == | 等于 | auth.uid == 'zzz' | 用户的 uid 等于 'zzz' | | != | 不等于 | auth.uid != 'zzz' | 用户的 uid 不等于 'zzz' | | > | 大于 | a>10 | 变量 a 的值大于 10 | | >= | 大于等于 | a>=10 | 变量 a 的值大于等于 10 | | < | 小于 | a<10 | 变量 a 的值小于 10 | | 10 | 用户的 uid 为 'zzz' 或者 a 值大于 10 | | . | 对象属性访问符 | auth.uid | 访问 auth 对象的 uid 属性 | | [] | 对象属性或数组元素访问 | a[auth.uid] == 'zzz' | 对象 a 中键名为用户 uid 的属性值等于 'zzz' | --- ## 系统函数 # 系统函数 安全规则内置了一系列系统级函数,这些函数提供强大的通用能力,使开发者能够在规则表达式中直接调用,实现更灵活的资源访问权限控制。 ## get _静态函数_ **语法:** `get(path)` **返回:** document 对象 **功能:** 根据指定路径获取文档内容。 ### 参数 | 参数 | 类型 | 说明 | | ---- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------- | | path | string | 非空,格式为 `database.集合名称.文档ID` 的字符串。可通过多种方式计算得到,例如使用字符串模板进行拼接:`` `database.${doc.collection}.${doc._id}` `` | ### 返回值 - 如果文档不存在,返回 `undefined` 或 `null` - 如果文档存在,返回包含文档数据的 document 对象 ### 使用示例 **示例1:** 用户权限存储在独立文档中,使用数值表示权限范围 ```json { "read": "get('database.test.123')[auth.uid] in [1,2,3]", "delete": "get('database.permissions.user_rights')[auth.uid] == 1 && doc.user in ['user1','user2']" } ``` **示例2:** 跨集合权限验证 - 集合A包含shopId、orderId关联关系,集合B包含owner、shopId关联关系,限制用户只能查询有权限的商店订单 ```json { "read": "auth.openid in get(`database.B.${doc.shopId}`).owner" } ``` ### 使用限制 1. 当`get`参数中包含`doc`变量时,该变量需要在查询条件中以`==`或`in`方式出现。如使用`in`方式,只允许`in`单一值,即`doc.shopId in array`且`array.length == 1` 2. 单个表达式中最多可使用`3`个`get`函数,最多可访问`10`个不同的文档 3. `get`函数的嵌套深度最多为2,即可以使用`get(get(path))`形式,但不能更深层嵌套 ### 性能说明 每次调用`get`函数都会产生数据库读取操作: - 不使用变量时:每个`get`产生一次读操作 - 使用变量时:每个`get`对应每个变量值会产生一次读操作 **例如:** 规则 `` get(`database.collection.${doc._id}`).test ``,在查询 `_.or([{_id:1},{_id:2},{_id:3},{_id:4},{_id:5}])` 时会产生5次读取操作。 系统会对相同文档、相同字段的读取进行缓存优化。在可能的情况下,安全规则会合并部分相同文档不同字段的读取,在一次操作中获取多个字段,以减少数据库资源消耗。合并效率与规则的复杂度和写法相关。 --- ## 编写安全规则 import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # 编写安全规则 安全规则是一种强大的访问控制机制,允许您精确控制数据的访问权限。通过灵活的规则语法,您可以在数据库集合或存储桶上实现不同粒度的读写控制组合,确保数据安全。 ## 默认规则 默认情况下,安全规则会拒绝所有的数据访问请求。这种"默认拒绝"的安全策略确保您的数据在未明确授权的情况下不会被访问。 ```JSON {} // 空规则对象表示拒绝所有访问 ``` ## 用户身份认证 当经过身份认证的用户发起请求时,系统会自动使用用户唯一标识 `uid` 及用户登录方式 `loginType` 填充 `auth` 变量。当未经身份验证的用户发出请求时,`auth` 变量值为 `null`。 通过 `auth` 变量,您可以使用以下常用方式根据用户身份控制数据访问: - **公开访问**:不判断 `auth` 值,允许所有用户访问 - **仅登录用户访问**:检查 `auth != null`,确保用户已登录 - **用户私有数据**:检查 `auth.uid` 是否等于资源 `openid`,确保用户只能访问自己的数据 - **特定登录方式限制**:检查 `auth.loginType`,例如限制匿名登录用户访问(`auth.loginType != "ANONYMOUS"`) ### 公开访问规则 任何不考虑 `auth` 的规则均可被视为公开(`public`)规则,因为它不依赖用户的身份验证上下文。这类规则在提供公开数据(如静态资源内容、公共信息等)的场景下非常适用。 ```json { "read": "doc._openid != null" } ``` ```json { "read": "resource.openid != null" } ``` ### 仅对登录用户开放 在许多应用场景中,您可能希望限制只有已登录用户才能访问某些数据。例如,只有登录用户才可以查看论坛中的讨论内容或用户评论。由于所有未登录用户的 `auth` 变量值为 `null`,因此可以设置如下规则: ```json { "read": "auth != null" // 只有已登录用户可以读取数据 } ``` ### 所有用户可读,仅创建者可写 数据通过 `_openid` 字段记录当前数据的归属用户 ID: ```JSON { "read": true, // 所有用户都可以读取 "write": "doc._openid == auth.openid || doc._openid == auth.uid" // 只有创建者可以修改 } ``` > 注意:`auth.openid` 适用于微信登录方式,`auth.uid` 适用于非微信登录方式 ```JSON { "read": true, // 所有用户都可以读取 "write": "resource.openid == auth.openid || resource.openid == auth.uid" // 只有创建者可以修改 } ``` > 注意:`auth.openid` 适用于微信登录方式,`auth.uid` 适用于非微信登录方式 ### 仅创建者可读写 数据通过 `_openid` 字段记录当前数据的归属用户 ID: ```JSON { "read": "doc._openid == auth.openid || doc._openid == auth.uid", // 只有创建者可以读取 "write": "doc._openid == auth.openid || doc._openid == auth.uid" // 只有创建者可以修改 } ``` > 注意:`auth.openid` 适用于微信登录方式,`auth.uid` 适用于非微信登录方式 ```JSON { "read": "resource.openid == auth.openid || resource.openid == auth.uid", // 只有创建者可以读取 "write": "resource.openid == auth.openid || resource.openid == auth.uid" // 只有创建者可以修改 } ``` > 注意:`auth.openid` 适用于微信登录方式,`auth.uid` 适用于非微信登录方式 ### 所有用户可读,仅管理员可写 此规则适用于公共内容,普通用户可以查看但不能修改,只有管理员通过云函数或管理控制台才能修改: ```javascript { "read": true, // 所有用户都可以读取 "write": false // 普通用户不能写入,管理员通过云函数或控制台操作 } ``` ### 仅管理员可读写 此规则适用于敏感数据,只允许管理员通过云函数或管理控制台访问: ```javascript { "read": false, // 普通用户不能读取 "write": false // 普通用户不能写入 } ``` > 注意:设置为 `false` 的规则表示普通客户端无法访问,但管理员仍可通过云函数或控制台进行操作 ## 数据验证 安全规则不仅可以控制访问权限,还可以用于数据验证。您可以根据数据库或存储分区中的现有数据,使用安全规则有条件地写入新数据。通过编写数据验证规则,您可以根据写入的新数据内容来限制写入操作,确保数据符合预期格式和业务规则。 ### 对新数据的限制与验证 如果要对新创建的数据进行字段验证,例如,如果要拒绝创建包含 `ranking` 字段的所有文档(可能是为了防止用户自行设置排名),您可以在 `create` 条件中进行限制: ```JSON { "read": true, "create": "request.data.ranking == undefined", // 拒绝包含ranking字段的文档创建 "update": true // 允许更新操作 } ``` 对于云存储,您可以确保上传的文件都必须有归属值,且归属于当前用户: ```JSON { "read": true, // 允许所有用户读取 "write": "resource.openid == auth.openid || resource.openid == auth.uid" // 确保文件归属于当前用户 } ``` ### 基于现有数据的访问控制 许多应用会将访问权限控制信息以字段形式存储在数据库文档中。安全规则可以根据这些文档数据属性来控制访问权限,实现更复杂的权限管理。 要实现基于角色的权限控制,您需要在用户数据中定义对应的角色和权限属性。安全规则会根据这些数据属性检查请求,决定是否允许或拒绝访问。 #### 实际案例:教育系统权限控制 例如,在一个教育系统中,我们需要存储学生成绩,并向不同用户组分配不同的访问权限: - "学生"组只能查看自己的成绩(只读权限) - "教师"组可以查看和修改他们所教科目的所有学生成绩(读写权限) 用户表(`user` 集合)可以设计如下结构: ```ts { userID: string, // 用户唯一ID role: string, // 用户角色:'STUDENT'或'TEACHER' projects: string[] // 教师所教科目列表(仅教师角色有此字段) } ``` 成绩表(`score` 集合)设计如下: ```ts { studentID: string, // 学生ID project: string, // 科目名称 score: number // 分数 } ``` 成绩表的安全规则可设置为: ```json { "read": "get(`database.user.${auth.uid}`).role == 'STUDENT' && doc.studentID == auth.uid || (get(`database.user.${auth.uid}`).role == 'TEACHER' && doc.project in get(`database.user.${auth.uid}`).projects)", "write": "get(`database.user.${auth.uid}`).role == 'TEACHER' && doc.project in get(`database.user.${auth.uid}`).projects" } ``` 这个规则表示: 1. 学生只能查看自己的成绩(`studentID == auth.uid`) 2. 教师可以查看他们所教科目的所有学生成绩 3. 只有教师可以修改他们所教科目的成绩 --- ## 解决时区不一致问题 # 解决时区不一致问题 ## 问题背景 容器系统时间默认为 UTC 协调世界时间 (Universal Time Coordinated),与本地所属时区 CST (上海时间)相差 8 个小时。当需要获取系统时间用于日志记录、数据库存储等相关操作时,容器内时区不一致问题将会带来一系列困扰。 ## 操作步骤 在构建基础镜像或在基础镜像的基础上制作自定义镜像时,在 Dockerfile 中创建时区文件即可解决单一容器内时区不一致问题,且后续使用该镜像时,将不再受时区问题困扰。 1. 打开 Dockerfile 文件。 2. 写入以下内容,配置时区文件。 ``` FROM centos RUN rm -f /etc/localtime \ && ln -sv /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \ && echo "Asia/Shanghai" > /etc/timezone ``` 3. 重新构建容器镜像,使用新的镜像重新部署。或直接上传含新的 Dockerfile 的代码包重新部署。 --- ## 将您的服务迁移到云托管 # 将您的服务迁移到云托管 大多数后台服务,通常包含以下组件: - 服务本体 - 持久化服务(各类数据库、文件存储) - 基础设施(如消息队列、服务注册发现中心、监控系统、日志系统等) ## 迁移服务本体 CloudBase 云托管适用于部署**无状态的容器化服务**,您需要将您的服务改造为此种类型。 ### 无状态服务 无状态服务即服务在处理单个请求时,不需要持久性地保存上下文,以保证服务可以做到任意**横向扩容**。 无状态服务的每个服务节点之间是完全等价的,请求可能会由随机的任意节点进行处理,并且节点可能会被动态地销毁、重建、扩容,所以您**不应该在节点上保存任何状态**,例如: - 使用本地内存储存 HTTP Session; - 使用本地文件储存数据; - 业务逻辑中使用某个节点的 IP。 如果您有以上的需求,可以考虑如下解决方法: - 使用 Redis 等外部数据库储存 HTTP Session; - 使用 CFS、对象存储等外部服务保存文件; - 使用服务对外 URL。 ### 容器化 CloudBase 云托管只能部署基于 Docker 容器的应用,为了将服务封装到容器中,您应该使用 Dockerfile 来定义您的应用运行环境。 ### 使用标准输出打印日志 CloudBase 云托管会自动收集您应用产生的标准输出,并提供服务日志查询功能。 ## 迁移基础设施 云托管应用可以通过其所在的 VPC 访问任意云上资源,如果您的基础设施已经部署在腾讯云内,则只需要打通 VPC 即可让您的服务访问您的基础设施。 --- ## 对用户进行身份校验 # 对用户进行身份校验 默认云托管不提供鉴权服务,如果客户没有实现鉴权功能,则在某些情况下存在安全问题。如果您的服务要处理来自客户的请求,则最佳实践是只让允许的用户进行访问。 您可以通过[自定义域名](../networking/custom-domains)功能,并根据要求配置相关 path, 同时为 path 开启```鉴权```功能,来设置云托管服务的访问权限。 ## 用户创建 * 1、登录腾讯云托管 * 2、在导航菜单```扩展能力``` 中选择 [云后台](https://tcb.cloud.tencent.com/dev?envId=lowcode-9gms1m53798f7294#/cloud-admin), 点击前往云后台 * 3、在云后台中选择 ```用户管理``` 添加用户, 设置用户高名称和密码 ## 用户权限配置 云托管服务默认只能以下几种角色客户访问: * 默认内部用户 * 默认外部用户 * 自定义策略访问 注意: 其中在 ```用户创建``` 步骤创建的客户为 ```默认内部用户```。 如果不想某些用户访问,可以给客户解绑 ```默认内部用户``` 和 ```默认外部用户``` 角色 ### 自定义策略 * 1、登录腾讯云托管 * 2、在导航菜单```扩展能力``` 中选择 [云后台](https://tcb.cloud.tencent.com/dev?envId=lowcode-9gms1m53798f7294#/cloud-admin), 点击前往云后台 * 3、在云后台中选择 ```权限控制```, 在权限控制页面选择 ```策略管理```, 如果没有该选项,可以刷新页面。 * 4、点击```新增自定义策略```,填写表单: * 策略标识: 英文填写 * 策略名称: 中英文填写 * 策略内容: 我们以允许 ```/api``` 访问为例, 如下在 action 配置 ```/api``` 路径即可。 ``` { "statement": [ { "action": "cloudrun:/api", "resource": "*", "effect": "allow" } ], "version": "1.0" } ``` * 5、配置完自定义策略之后,将改策略关联到需要访问该资源的角色上,然后将该角色中关联需要访问的用户即可。 ## 获取用户 Token 参考[用户名密码登录](https://docs.cloudbase.net/http-api/auth/auth-sign-in) OpenAPI 获取用户登录 token。 ## 通过自定义域名访问云托管 我们以设置路由为 ```/api``` 开头的服务为例。 参考[自定义域名](../networking/custom-domains)功能,在域名关联资源时,```鉴权开关```选择打开, 路径透穿根据实际情况填写,比如我们 api 路径为 ```/api```, 我们不开启路径透传的情况下,我们使用 ```/api/users``` 访问,后端服务收到的 url 为 ```/users```, 反之开启情况下收到的为 ```/api/users```。 我们配置完成之后,通过以下方式访问: ``` curl -H "Content-Type: application/json" -H "Authorization: Bearer " https:///api/users ``` 即可获取到访问结果。 ## 通过其他登录方式获取 Token 可以参考[用户登录设置](https://docs.cloudbase.net/http-api/auth/%E7%99%BB%E5%BD%95%E8%AE%A4%E8%AF%81%E6%8E%A5%E5%8F%A3)。 ## 获取用户信息 我们会将客户的 token 透穿给后端,后端可以通过获取请求 Header 中 ```Authorization``` 字段获取到请求 Token, 注意去除 Bearer 字段。 然后通过 jwt 解码 token, 解码后 ```user_id``` 字段为用户的唯一标识。解析后 payload 内容如下: ``` { "iss": "", "sub": "22332323", "aud": "", "exp": 1750073415, "iat": 1750066215, "at_hash": "", "scope": "", "project_id": "", "provider_type": "username", "meta": { "wxOpenId": "", "wxUnionId": "" }, "user_id": "1934543672625225729", "user_type": "internal" } ``` 如需查询客户详细信息,请参考 [用户详情](https://docs.cloudbase.net/lowcode/manage/auth#%E7%94%A8%E6%88%B7%E8%AF%A6%E6%83%85)。 --- ## 允许公开访问 # 允许公开访问 默认情况下,云托管服务为公开访问(即不需要任何的权限验证),任何用户都可以通过访问域名来访问服务。 如果您希望只有部分用户可以访问云托管服务,可以参考[对用户开启身份认证](./end-users)。 --- ## 服务到服务 # 服务到服务 服务到服务之间如果采用内网访问则不需要任何的权限验证操作。 --- ## 运行模式与扩缩容 # 运行模式与扩缩容 本文档介绍云托管的运行模式及扩缩容机制,帮助您选择最适合业务场景的配置方案。 ## 运行模式概览 云托管提供以下几种运行模式,满足不同的业务需求: - [始终自动扩缩容](#始终自动扩缩容):根据负载自动调整实例数量,最大程度节约资源 - [持续运行](#持续运行):保持固定数量的实例,适合流量稳定的场景 - [白天持续运行,夜间自动扩缩容](#白天持续运行夜间自动扩缩容):工作时间固定实例,非工作时间自动扩缩 - [自定义](#自定义):灵活配置自动扩缩容和定时扩缩容策略 - [手工启停实例](#手工启停实例):完全手动控制实例数量 ## 运行模式详解 ### 始终自动扩缩容 在此模式下,云托管服务会根据实际负载情况自动调整实例数量: - **扩缩容范围**:实例数量可在 0-10 之间自动调整 - **触发指标**:可选择 CPU 使用率、内存使用率或两者同时作为扩缩容触发条件 - **优势**:最大程度节约资源,自动应对流量波动,降低运营成本 此模式特别适合流量波动较大或不可预测的业务场景。 ### 持续运行 持续运行模式下,服务会保持固定数量的实例持续运行,不会自动扩缩容。 **适用场景**: - 服务流量相对稳定,无明显波峰波谷 - 需要保证服务始终处于热启动状态,避免冷启动延迟 - 对服务可用性要求极高的核心业务 在此模式下,您需要根据业务峰值预估所需实例数量,确保服务稳定运行。 ### 白天持续运行,夜间自动扩缩容 此模式结合了持续运行和自动扩缩容的优势: - **白天时段**(8:00-24:00):保持指定数量的实例持续运行 - **夜间时段**(0:00-8:00):启用自动扩缩容,实例可缩至 0 适合工作时间流量较高、非工作时间流量显著降低的业务场景,如企业内部系统、办公应用等。 ### 自定义 自定义模式提供最灵活的配置选项,包括: - **自动扩缩容**: - 配置实例的最大及最小数量 - 选择 CPU 或内存使用率作为触发条件 - 设置触发阈值和检测周期 - **定时扩容**: - 指定时间段内保持最小实例数 - 定时扩容的实例数需大于自动扩缩容的最小实例数 - 在定时期间仍可自动扩容,但不超过最大实例限制 此模式适合有明确流量模式且需要精细控制资源的场景,如电商促销、定期任务处理等。 ### 手工启停实例 手工启停模式下,实例完全由人工控制,不会自动扩缩: - 实例不会因无请求而自动缩容 - 实例不会因负载增加而自动扩容 - 所有实例变更都需通过控制台或 API 手动操作 **操作方式**: - **启动实例**: - 通过控制台版本列表中的"启动实例"操作 - 通过 API 调用启动实例 - 控制台的每次操作启动一个实例,需多次操作启动多个实例 - **停止实例**: - 通过控制台实例列表中的"停止实例"操作 - 通过 API 调用停止实例 - 可选择指定实例进行停止 此模式适合需要完全控制实例生命周期的场景,如开发测试环境或特殊业务需求。 :::warning 实例资源使用 手工启停实例的情况下,如果实例启动后遗忘了停止实例,可能会产生不必要的资源浪费,会产生较多的计费开销。 ::: ## 扩缩容机制详解 ### 实例扩容过程 实例扩容分为两个阶段: 1. **从 0 到 1 扩容(冷启动)**: - 触发条件:服务完全缩容后收到新请求 - 过程:启动一个新实例,实例就绪后开始处理请求 - 耗时因素:平台资源状态、镜像大小、业务代码启动时间等 - 用户体验:首次请求可能有一定延迟 2. **从 1 到多实例扩容**: - 触发条件:已有实例的平均 CPU/内存使用率达到或超过配置的扩容阈值 - 过程:启动新实例,新实例就绪后加入负载均衡 - 持续监测:如检测周期后仍超过阈值,将继续扩容 - 限制:实例数量不超过配置的最大值 ### 实例缩容机制 - **触发条件**:实例无访问、无流量,闲置 10 分钟 - **缩容行为**:回收并销毁闲置实例 - **最小实例**:当配置了最小实例为 0 时,可能缩容至无实例状态 - **后续请求**:全部缩容后的新请求将触发冷启动过程 ### 实例销毁说明 - 实例在缩容后将被完全销毁 - 实例内的临时文件、内存数据等将一并清除 - **重要提示**:请确保您的应用是无状态的,所有持久化数据应存储在外部存储服务中 ## 选择合适的运行模式 | 运行模式 | 适用场景 | 成本效益 | 响应速度 | |---------|---------|---------|---------| | 始终自动扩缩容 | 流量波动大、不可预测 | 最优 | 可能有冷启动延迟 | | 持续运行 | 流量稳定、高可用要求 | 固定较高 | 最佳(无冷启动) | | 白天持续运行,夜间自动扩缩容 | 工作时间集中型应用 | 较优 | 工作时间最佳,非工作时间可能有延迟 | | 自定义 | 有明确流量模式、需精细控制 | 可优化 | 可根据配置优化 | | 手工启停实例 | 开发测试、特殊业务需求 | 完全可控 | 取决于人工操作及时性 | --- ## 容器端口和入口点 # 容器端口和入口点 本页面介绍如何为云托管服务配置容器端口、入口点命令和参数。 当腾讯云托管启动容器时,它会运行映像的默认入口点命令和默认命令参数。 ## 配置容器端口 任何配置更改都会创建新的版本。后续版本也将自动采用该配置。 您可以在创建服务时,在```容器配置``` -> ```端口``` 指定您的服务端口。注意,该端口必须和您的服务实际访问端口保持一致,否则会导致云托管服务启动失败。 您也可以在服务创建后,在 ```服务配置``` 中修改您的服务端口。 --- ## 环境变量 # 环境变量 本页介绍了如何为云托管服务配置环境变量。 ## 设置环境变量 您可以为新服务和现有服务设置环境变量。环境变量会绑定到特定的服务版本中,并且对云托管中的其他服务不可见。 您可以在创建新服务或新建服务后在 ```服务设置``` 中修改环境变量。 ## 在容器中设置默认环境变量 您可以使用 Dockerfile 中的 ENV 语句设置环境变量的默认值: ``` ENV KEY1=VALUE1,KEY2=VALUE2 ``` ## 优先顺序 如果您在容器中设置默认环境变量,并在云托管服务上设置具有相同名称的环境变量,则该服务中设置的值优先。 --- ## 会话亲和性 # 会话亲和性 本页面介绍如何为云托管服务配置如何开启会话亲和性。 通过启用会话亲和性,云托管会尽力将携带特定请求头的请求路由到同一云托管实例上,会话亲和性需要客户端和服务端配合实现。 ## 配置会话亲和性 您也可以在服务创建后,在 ```服务配置``` -> ```访问配置```中 来操作开启和关闭,开启会话亲和性,云托管会尽力将携带特定请求头的请求路由到同一云托管实例上,会话亲和性需要客户端和服务端配合实现。 。 ## 通用客户端 对于一般的客户端,在第一次调用后云托管服务后,客户端需要保存云托管返回的 X-Cloudbase-Session-Id 响应头,并在接下来的请求头中携带相同值的 X-Cloudbase-Session-Id 请求头以路由到相同的云托管示例。默认情况下,X-Cloudbase-Session-Id 的有效期为 4 小时,活跃的 X-Cloudbase-Session-Id 将保持有效,不会被自动清除。 调用示意图如下: ![](https://qcloudimg.tencent-cloud.cn/raw/fbda67b392b85a79360d7bc3846c1a5d/affinity-0.png) ### MCP 客户端 云托管会话亲和性内置了对 Model Context Protocol 协议所声明的 MCP Session 的支持,对于符合协议的 MCP 客户端,云托管会自动处理 Mcp-Session-Id 的会话亲和性保持,无需额外携带请求头。 调用示意图如下: ![](https://qcloudimg.tencent-cloud.cn/raw/356eee08357a259f35fa990ae6d3a95b/affinity-1.png) --- ## CPU 及内存配置 # CPU 及内存配置 本文档介绍如何指定每个云托管实例所使用的 CPU 和内存量。默认情况下,系统会将云托管容器实例配置为 1 核 CPU、2 GiB 内存。您可以按照本页中的说明增加或减少此值。 ## 设置和更新 CPU 设置 默认情况下,系统会将每个实例配置为 1 核 CPU, 2 GiB 内存。您可以将此值更改为本页面中所述的其他值。 ### CPU 和 内存 以下是 CPU 和内存的配置要求: | CPU(核数) | 内存(GiB) | | ---- | ---- | | 0.25 | 0.5 | | 0.5 | 1 | | 1 | 2 | | 2 | 4 | | 4 | 8 | | 8 | 16 | | 16 | 32 | 或者如果您想使用的 CPU 少于 1, 则可以选择 0.25 或 0.5 核。大于 1 的值为整数值。CPU 及内存配置符合以下要求: * CPU 和 内存的比例关系为 1:2, 即 1 个 CPU 需要 2GiB 内存 * 最小 CPU 设置为 0.25 * 最大 CPU 设置为 16 ## 配置 CPU 限制 任何配置更改都会导致新版本的创建。后续的发布新版本也将采用此配置。 你可以在创建服务后,在 ```服务设置``` 中 中修改 CPU 及内存配置。 ## 查看 CPU 配置 你可以在创建服务后,在 ```服务设置``` 中 查看当前的 CPU 及内存配置。 --- ## 挂载对象存储 # 挂载对象存储 ## 概述 云托管服务需要持久化存储时,可以通过挂载云开发对象存储,或腾讯云对象存储来实现。COS 提供了高可用、高可靠、低成本的数据存储服务,将其挂载到云托管实例后,应用可以像使用本地文件系统一样访问和管理存储在 COS 中的数据。 ### 主要优势 - **数据持久化**:与临时存储不同,COS 中的数据在实例销毁后仍然保留 - **高可靠性**:COS 提供 99.999999999% 的数据可靠性 - **多实例共享**:所有实例可访问相同的存储内容,便于数据共享 - **按需付费**:根据实际存储用量和请求次数计费,经济实惠 ## 使用场景 COS 对象存储挂载特别适用于以下场景: - **静态资源存储**:存储网站图片、视频、文档等静态资源 - **用户上传内容**:保存用户上传的文件,如头像、附件等 - **数据备份归档**:存储应用日志、数据备份等需长期保存的信息 - **跨实例数据共享**:在多个实例间共享配置文件、模板等数据 - **大文件处理**:处理超出临时存储容量限制的大型文件 ## 配置步骤 ### 准备工作 1. **获取访问密钥**:前往[腾讯云访问管理控制台](https://console.cloud.tencent.com/cam/capi),创建或获取 SecretID 和 SecretKey > 可以为对象存储创建单独的子用户,并仅授予必要的 COS 访问权限,遵循最小权限原则 ### 详细步骤 1. **配置访问密钥** - 进入[云开发平台控制台](https://tcb.cloud.tencent.com/dev) - 选择「资源连接」>「连接管理」,或在云托管服务的「存储挂载」>「新增连接密钥」 - 添加腾讯云 API 密钥,填入获取的 SecretID 和 SecretKey 2. **启用存储挂载** - 在云托管服务详情页面,选择「存储挂载」 - 点击「启用存储挂载」,选择存储类型为「对象存储」 3. **选择存储桶** - 选择「云开发对象存储」:系统自动填充存储桶信息 - 选择「腾讯云对象存储」:需手动填写存储桶名称 4. **配置挂载路径** - **对象存储挂载路径**:指定要挂载的 COS 目录,默认为根目录「/」 - **实例挂载路径**:指定 COS 在实例中的挂载位置,默认为「/mnt」 5. **确认并保存配置** :::tip 挂载路径限制 实例中以下目录不能被挂载:`/`, `/proc`, `/sys`, `/dev`, `/var/run`, `/app/cert` ::: ## 代码示例 ### Node.js 示例 ```javascript const fs = require('fs'); const path = require('path'); // 假设 COS 挂载在 /mnt/cos 目录 const cosPath = '/mnt/cos'; // 写入文件 app.post('/upload', (req, res) => { const fileName = `file-${Date.now()}.txt`; const filePath = path.join(cosPath, fileName); fs.writeFileSync(filePath, req.body.content); res.send(`文件已保存至: ${fileName}`); }); // 读取文件 app.get('/files/:fileName', (req, res) => { const filePath = path.join(cosPath, req.params.fileName); if (fs.existsSync(filePath)) { const content = fs.readFileSync(filePath, 'utf8'); res.send(content); } else { res.status(404).send('文件不存在'); } }); ``` ### Python 示例 ```python import os from flask import Flask, request, jsonify app = Flask(__name__) # 假设 COS 挂载在 /mnt/cos 目录 cos_path = '/mnt/cos' @app.route('/upload', methods=['POST']) def upload_file(): file_name = f"file-{int(time.time())}.txt" file_path = os.path.join(cos_path, file_name) with open(file_path, 'w') as f: f.write(request.json.get('content', '')) return jsonify({"message": f"文件已保存至: {file_name}"}) @app.route('/files/', methods=['GET']) def get_file(file_name): file_path = os.path.join(cos_path, file_name) if os.path.exists(file_path): with open(file_path, 'r') as f: content = f.read() return content else: return jsonify({"error": "文件不存在"}), 404 ``` ## 注意事项及最佳实践 ### 性能考量 - **缓存策略**:频繁访问的文件考虑先缓存到内存或临时存储 - **批量操作**:尽量批量读写文件,减少 I/O 操作次数 - **文件大小**:对于大文件操作,考虑分片处理 ### 多实例协作 - **路径隔离**:不同实例操作时,建议使用唯一标识(如实例ID)创建子目录 - **文件锁**:读写共享文件时,实现适当的锁机制避免冲突 - **原子操作**:使用原子重命名等技术确保文件操作的完整性 ```javascript // 安全的文件更新示例(Node.js) const fs = require('fs').promises; const path = require('path'); async function safelyUpdateFile(filePath, newContent) { const tempPath = `${filePath}.tmp`; // 先写入临时文件 await fs.writeFile(tempPath, newContent); // 原子性地重命名替换原文件 await fs.rename(tempPath, filePath); } ``` ### 安全性 - **权限控制**:定期检查 COS 存储桶的访问权限设置 - **敏感数据**:避免在 COS 中存储未加密的敏感信息 - **公开访问**:使用云开发对象存储时,注意公有读权限可能导致文件被外部访问 ### 成本优化 - **生命周期管理**:为不常用数据配置生命周期规则,自动转换存储类型或删除 - **按需挂载**:只在需要时挂载 COS,不需要时可以卸载以减少资源占用 ## 相关资源 - [COS 对象存储产品文档](https://cloud.tencent.com/document/product/436) - [访问密钥管理](https://cloud.tencent.com/document/product/598/40488) --- ## 临时存储 # 临时存储 ## 概述 云托管服务在接收请求后,会启动实例并在实例内运行相关代码逻辑。每个实例内都配备了临时存储空间,可用于存储请求处理过程中产生的中间数据。 临时存储的主要特点: - **易于使用**:通过标准文件系统接口访问,无需额外配置 - **临时性**:数据仅在实例生命周期内有效 - **实例隔离**:不同实例间的临时存储相互独立 ## 使用场景 临时存储适用于以下场景: - **文件上传处理**:临时存储上传文件,进行处理后转存至持久化存储 - **请求级缓存**:存储当前请求处理过程中的中间结果 - **日志记录**:记录业务日志,便于问题排查 - **临时计算数据**:存储计算过程中的中间结果 ## 使用限制与注意事项 :::warning 重要提醒 - **数据非持久化**:实例回收或销毁后,临时存储中的所有数据将被清除 - **内存占用**:临时存储实际占用实例的内存空间,过度使用可能导致内存不足 - **性能影响**:大量或频繁的文件操作可能影响应用性能 ::: ### 最佳实践 1. **合理使用空间**:仅存储必要的临时数据,及时清理不再需要的文件 2. **控制文件大小**:避免存储过大的文件,防止出现OOM(内存溢出)错误 3. **定期转移**:对需要长期保存的数据,及时转移至持久化存储 4. **监控内存使用**:关注实例内存使用情况,避免因临时存储导致的内存压力 ## 代码示例 ```javascript // Node.js 示例:使用临时存储处理上传文件 const fs = require('fs'); const path = require('path'); // 将上传的文件保存到临时存储 app.post('/upload', (req, res) => { const tempFilePath = path.join('/tmp', `upload-${Date.now()}.dat`); // 保存到临时存储 fs.writeFileSync(tempFilePath, req.body.fileData); // 处理文件... // 处理完成后删除临时文件 fs.unlinkSync(tempFilePath); res.send('文件处理完成'); }); ``` ## 持久化存储方案 对于需要持久保存的数据,建议使用以下存储方案: - [COS 对象存储挂载](/run/deploy/configuring/storage/cos):适用于需要长期保存的文件数据 - 数据库:适用于结构化数据的持久化存储 --- ## 新建服务 # 新建服务 ## 操作流程 ### 第 1 步:新建服务 在 [云托管控制台](https://console.cloud.tencent.com/tcb/service) 的服务列表页面,选择对应的环境,单击「新建服务」或「新建此私有网络下的服务」。 ### 第 2 步:配置服务信息 填写新建服务所需的所有信息。字段详解请参见[服务配置说明](/run/deploy/service-setting)。 - 若您在上一步选择的是「新建服务」,且这是您在本环境创建的首个服务,则“云托管网络”字段会默认选中“系统推荐”。 - 若您在上一步选择的是「新建服务」,但这不是您在本环境创建的首个服务,则“云托管网络”字段会默认选中“已有私有网络“,VPC 默认选中上一个服务所在 VPC,子网默认选中上一个服务所在子网。 - 若您在上一步选择的是「新建此私有网络下的服务」,则“云托管网络”字段会默认选中“已有私有网络“,VPC 默认选中您所选 VPC,子网需要手动选择。 ### 第 3 步:提交 单击「提交」,如果部署成功,便可以看到如下弹框: ![](https://main.qcloudimg.com/raw/49ee89fd54955cce5cdd008f5ccaa914.png) 单击「新建版本」可立刻开始新建版本并部署,详情请参考 [部署服务](/run/deploy/deploy-service)。 ## 使用限制 - **当前每个环境支持服务总数**:每个环境支持同时存在最多 15 个服务。不再使用的服务可以删除,不计入服务总数。 - **可用 VPC 总数**: 同一账号最多可用到 5 个 VPC。若存量服务已用到 5 个不同 VPC,您再次新建服务并选择第 6 个未被云托管使用过的 VPC 时,会报错配额不足。 --- ## 通过 Git 仓库部署 # 通过 Git 仓库部署 云托管支持通过绑定 GitHub、GitLab 等个人或私有 Git 仓库进行应用部署,也支持直接通过公开 Git 仓库地址进行部署。两者适用场景和操作流程略有不同: ## 公开仓库部署 - 直接填写公开 Git 仓库地址(无需授权),如 GitHub/Gitee 等开源项目。 - 适合开源项目、无需私密性和权限控制的场景。 - 操作方式与私有仓库类似,但无需账号授权,适合快速体验和分享。 ### 操作流程 1. 在云托管控制台选择“通过公开 Git 仓库地址部署”。 2. 填写公开仓库的地址和分支,配置访问端口等参数。 3. 保存并启动部署。 --- ## 私有仓库部署 - 需授权绑定 GitHub、GitLab 等账号,支持私有和个人仓库。 - 支持分支选择、构建参数配置、自动化触发部署(如 push、PR 合并等)。 - 适合团队协作、持续集成(CI/CD)、自动化部署等场景。 - 可结合 Webhook、CI 工具实现更复杂的自动化流程。 ### 操作流程 1. 在云托管控制台选择“通过 Git 仓库部署”。 2. 绑定您的 GitHub、GitLab 等代码仓库账号。 3. 选择需要部署的私有或个人仓库及分支,配置构建参数。 4. 配置自动化触发规则(如 push、PR 合并等)。 5. 保存并启动部署。 ### 启用自动部署 私有仓库的最大优势是支持自动部署功能: 1. 在服务创建或更新页面启用"自动部署"选项 2. 系统会自动在 Git 平台配置 Webhook 3. 此后,当指定分支有新的代码提交时: - Webhook 会自动触发云托管的部署流程 - 系统拉取最新代码并构建新版本 - 自动发布新版本到生产环境 配置完成后,后续每次代码变更(如 push、PR 合并)都会自动触发新的构建和部署,极大提升开发效率。 ### 持续部署最佳实践 ### 分支策略 - **开发分支**:用于日常开发工作,不触发自动部署 - **测试分支**:可配置自动部署到测试环境 - **主分支**:配置自动部署到生产环境,通常是 `master` 或 `main` ### 流程建议 1. 在开发分支进行功能开发和单元测试 2. 通过 Pull Request/Merge Request 将代码合并到测试分支 3. 自动部署到测试环境并进行集成测试 4. 测试通过后,将代码合并到主分支 5. 自动部署到生产环境 ### 部署安全 - 启用自动部署前,确保 `Dockerfile` 已经过充分测试 - 配置适当的构建超时时间,避免异常构建占用资源 - 定期检查部署日志,确保部署过程正常 - 保留多个历史版本,以便在新版本出现问题时快速回滚 ### 故障处理 - 如果自动部署后服务异常,可在云托管控制台快速回退到之前的稳定版本 - 检查构建日志和应用日志,定位问题原因 - 修复问题后,重新提交代码触发新的部署 > **注意**:首次使用自动部署功能时,建议先在非关键业务上测试,熟悉整个流程后再应用到核心服务。 --- ## 开源项目示例 | 项目(GitHub) | 简介 | 一键部署链接 | | :------------------------------------------------------- | :----------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [AI Gateway](https://github.com/Portkey-AI/gateway) | Portkey AI Gateway,开源 AI 网关,支持多模型路由与安全管控。 | [一键部署](https://tcb.cloud.tencent.com/dev#/platform-run/service/create?type=git&repoUrl=https://github.com/Portkey-AI/gateway&repoBranch=main&serverName=ai-gateway&port=8787) | | [jsoncrack](https://github.com/AykutSarac/jsoncrack.com) | 可视化 JSON 结构的开源工具,支持交互式编辑与分享。 | [一键部署](https://tcb.cloud.tencent.com/dev#/platform-run/service/create?type=git&repoUrl=https://github.com/AykutSarac/jsoncrack.com&repoBranch=main&serverName=jsoncrack&port=8080) | 如需详细操作指引,请参考云托管平台相关文档或联系技术支持。 --- ## 部署容器镜像 # 部署容器镜像 本页面介绍如何将容器镜像部署到新的云托管服务或现有的云托管服务的新版本。 ## 支持的容器镜像仓库 您可以直接使用存储在以下容器镜像仓库中的镜像: 1. **腾讯云容器镜像服务 (Tencent Cloud Container Registry, TCR)** - 提供稳定、高效的镜像托管服务。 - 支持私有和公有镜像仓库。 - 访问地址:[腾讯云容器镜像服务](https://console.cloud.tencent.com/tcr/)。 2. **Docker Hub** - 全球最大的公共容器镜像仓库。 - 提供丰富的开源镜像资源。 - 访问地址:[Docker Hub](https://hub.docker.com/)。 您也可以使用其他厂商提供的容器镜像服务。我们建议您优先使用腾讯云容器镜像服务,以获得更好的本地化支持。(注意:目前仅支持公有云的镜像,关于镜像仓库登录注册功能,我们正在加紧开发中,敬请期待。) ## 创建镜像仓库 进入 [腾讯云容器镜像服务](https://console.cloud.tencent.com/tcr/),如果是首次使用,可以创建一个个人实例,该实例是免费的,不收取任何费用。 进入 [命名空间](https://console.cloud.tencent.com/tcr/namespace) 页面,新建命名空间,比如 `my-project`。 进入[镜像仓库](https://console.cloud.tencent.com/tcr/repository) 页面,新建镜像仓库,填写服务名称,比如 `gintest`, 类型选择为`公有`, 命名空间选择刚刚创建的 `my-project` 命名空间,点击创建完成。 点击刚刚创建的镜像名称,在`操作`一栏中点击快捷指令,按照要求完成镜像上传即可。 ## 获取镜像下载地址 ### 从腾讯云容器镜像服务 (TCR) 获取镜像地址 1. **登录腾讯云控制台** - 访问 [腾讯云容器镜像服务](https://console.cloud.tencent.com/tcr/) 并登录您的账号。 2. **进入目标镜像仓库** - 在控制台中选择目标镜像仓库,点击进入详情页。 3. **查找镜像** - 在镜像列表中,找到所需的镜像及其版本标签。 4. **复制拉取命令** - 点击镜像名称,进入详情页后,复制显示的拉取命令(例如 `docker pull ccr.ccs.tencentyun.com/namespace/repository:tag`)。 ### 从 Docker Hub 获取镜像地址 1. **访问 Docker Hub** - 打开 [Docker Hub](https://hub.docker.com/) 并搜索所需的镜像。 2. **选择镜像版本** - 在镜像详情页中,切换到 `Tags` 选项卡,选择所需的版本标签。 3. **复制拉取命令** - 页面会显示拉取命令(例如 `docker pull repository:tag`),直接复制即可。 ## 示例:获取 nginx 镜像 ### 从腾讯云容器镜像服务 (TCR) 获取 nginx 镜像 1. **登录腾讯云控制台** - 访问 [腾讯云容器镜像服务](https://console.cloud.tencent.com/tcr/) 并登录您的账号。 2. **搜索 nginx 镜像** - 在镜像仓库中搜索 `nginx`,选择官方或自定义的 nginx 镜像。 3. **复制拉取命令** - 点击镜像名称,进入详情页后,复制显示的拉取命令(例如 `docker pull ccr.ccs.tencentyun.com/namespace/nginx:latest`)。 4. **拉取镜像** - 在本地终端运行复制的命令,完成镜像拉取。 ### 从 Docker Hub 获取 nginx 镜像 1. **访问 Docker Hub** - 打开 [Docker Hub](https://hub.docker.com/) 并搜索 `nginx`。 2. **选择官方镜像** - 在搜索结果中选择 `nginx` 官方镜像。 3. **复制拉取命令** - 页面会显示拉取命令(例如 `docker pull nginx:latest`),直接复制即可。 4. **拉取镜像** - 在本地终端运行复制的命令,完成镜像拉取。 ## 部署新服务 准备: - 容器像下载地址: 上一步获取到的镜像下载地址中 `docker pull` 之后片段为下载地址, 即(`ccr.ccs.tencentyun.com/namespace/repository:tag`, `repository:tag` 部分), 首次部署到服务时会创建第一个版本。请注意,版本是不可变的。 要部署容器进行请进行如下操作: - 1、进入[云托管从容器部署](https://tcb.cloud.tencent.com/dev#/platform-run/service/create?type=image) - 2、镜像地址中填写需要指定的`容器镜像下载地址`,填写服务名称和端口 - 3、点击创建,等待部署完成即可。 - 4、部署完成之后,在概述页,获取默认访问域名进行访问测试。 ## 常见镜像部署开源项目示例 | 项目(GitHub) | 简介 | 一键部署链接 | | :------------------------------------------------------------- | :----------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------- | | [Nextcloud](https://github.com/nextcloud/all-in-one) | 开源的自托管云存储与协作平台,支持文件同步、共享、在线协作办公等。 | [一键部署](https://tcb.cloud.tencent.com/dev#/platform-run/service/create?type=image&image=nextcloud&serverName=nextcloud) | | [n8n](https://github.com/n8n-io/n8n) | 开源自动化与集成平台,支持可视化拖拽构建工作流,集成 500+ 应用。 | [一键部署](https://tcb.cloud.tencent.com/dev#/platform-run/service/create?type=image&image=n8nio/n8n&serverName=n8n&port=5678) | | [code-server](https://github.com/coder/code-server) | 在浏览器中运行 VS Code 的开源项目,实现云端开发环境。 | [一键部署](https://tcb.cloud.tencent.com/dev#/platform-run/service/create?type=image&image=codercom/code-server&serverName=code-server&port=8080) | | [Stirling-pdf](https://github.com/Stirling-Tools/Stirling-PDF) | 本地部署的 PDF 工具,支持合并、拆分、转换、OCR 等多种 PDF 操作。 | [一键部署](https://tcb.cloud.tencent.com/dev#/platform-run/service/create?type=image&image=stirlingtools/stirling-pdf&serverName=stirling-pdf&port=8080) | | [Excalidraw](https://github.com/excalidraw/excalidraw) | 开源虚拟白板,支持手绘风格图表协作,适合头脑风暴与原型设计。 | [一键部署](https://tcb.cloud.tencent.com/dev#/platform-run/service/create?type=image&image=excalidraw/excalidraw&serverName=excalidraw) | | [Crawl4ai](https://github.com/unclecode/crawl4ai) | 开源高性能异步网页爬虫,专为 AI 数据采集和 LLM 集成优化。 | [一键部署](https://tcb.cloud.tencent.com/dev#/platform-run/service/create?type=image&image=unclecode/crawl4ai&serverName=crawl4ai&port=11235) | --- ## 从源代码部署 # 从源代码部署 本页面介绍如何通过源代码部署到云托管服务。 部署要求: * 源代码中必须包含 Dockerfile 文件 各个语言及框架 Dockerfile 编写请参考: * [Python 快速开始](../../quick-start/dockerize-python) * [Node.js 快速开始](../../quick-start/dockerize-node) * [Go 快速开始](../../quick-start/dockerize-go) * [Java 快速开始](../../quick-start/dockerize-java) * [.NET 快速开始](../../quick-start/dockerize-dotnet) * [PHP 快速开始](../../quick-start/dockerize-php) * [创建一个 Express 应用](../../develop/languages-frameworks/express) * [创建一个 Nest 应用](../../develop/languages-frameworks/nest) * [创建一个 Gin 应用](../../develop/languages-frameworks/gin) * [创建一个 Django 应用](../../develop/languages-frameworks/django) * [创建一个 Flask 应用](../../develop/languages-frameworks/flask) * [创建一个 Spring Boot 应用](../../develop/languages-frameworks/springboot) * [创建一个 FastAPI 应用](../../develop/languages-frameworks/fastapi) * [创建一个 Laravel 应用](../../develop/languages-frameworks/laravel) ## 部署 如需从源代码进行部署,请执行以下操作: 进入[云托管通过本地代码部署](https://tcb.cloud.tencent.com/dev#/platform-run/service/create?type=package) 进入配置页, 填写如下配置: * 代码包类型,选择文件夹 * 代码包选择源代码目录进行上传 * 端口配置服务真实端口 * Dockerfile 目录填写 Dockerfile 真实所在目录,如果在根目录下,可不填写 * 填写真实 Dockerfile 名称 配置填写完成之后,点击部署按钮等待部署完成。 部署完成之后,点击切换到```概览``` 页,使用默认域名完成测试验证。 --- ## 部署方式 # 部署方式 云托管为开发者提供多种灵活的部署方式,满足不同类型项目的上线需求。 ## 部署方式一览 - [容器镜像部署 🐳](./deploying-image),直接拉取自定义或官方镜像,适合有独立构建流程或特殊环境需求的项目。 - [本地代码部署 💻](./deploying-source-code),上传本地代码,平台自动构建镜像,适合快速迭代和小型项目。 - [Git 仓库部署 🔗](./deploying-git),从 git 仓库部署,支持绑定 GitHub、GitLab 等私有仓库,支持自动化触发部署,适合团队协作和 CI/CD。也支持直接填写公开仓库地址,无需授权,适合开源项目和快速体验。 - [CLI 部署 🛠️](/cli-v1/cloudrun/deploy),使用命令行工具一键上传、构建和部署,适合自动化脚本和高级用户。 不同的部署方式可根据项目需求灵活选择,云托管平台为每种方式都提供了详细的文档和操作指引,助力您的应用高效上线。 ## 通用部署参数说明 无论采用哪种部署方式,均可配置以下常用参数: - **端口**:指定服务监听的端口,平台会自动将该端口暴露为外部访问入口。例如:`8080` 或 `3000`。 - **环境变量**:可自定义环境变量(如 `NODE_ENV=production`、`API_KEY=your_key` 等),用于配置应用运行环境。支持多组键值对。 - **ENTRYPOINT**:自定义容器启动命令(覆盖镜像默认 ENTRYPOINT )。例如:`["npm", "start"]`。 - **CMD**:自定义容器启动参数(覆盖镜像默认 cmd)。例如:`["--port", "3000"]`。 - **目标目录**:指定 Dockerfile 所在的目录路径(如 `./app`),默认为项目根目录。适用于多阶段构建或子目录部署的场景。 - **Dockerfile 名称**:自定义 Dockerfile 文件名(如 `Dockerfile.prod`),默认为 `Dockerfile`。适用于多环境配置的场景。 - **资源限制**:可配置 CPU 和内存资源限制(如 `1 CPU` 和 `2GB 内存`),确保服务稳定运行。 - **网络配置**:支持配置服务间网络互通、外部访问策略等。 如需详细参数说明和最佳实践,请参考各部署方式详情页或平台官方文档。 --- ## 部署服务 # 部署服务 ## 概念说明 - 版本是承载访问流量的实体,对应着一组配置信息相同的容器集合;也是一次部署所需信息的集合,包括镜像地址、服务端口、环境变量、自动扩缩容设置等。 - 每一次升级服务,可选择通过新建版本升级,或者在原版编辑配置并重新部署。两种方式的区别和操作指南,详情请参见 [升级服务](https://cloud.tencent.com/document/product/1243/46128)。 ## 操作流程 登录 [CloudBase 云托管控制台](https://console.cloud.tencent.com/tcb/env/overview),选择您需要部署的服务,单击服务名称进入服务详情页面: ![](https://main.qcloudimg.com/raw/74b7c4c1c429fe3bdf22d91609d7cb46.png) :::tip 提示 如果您还没有任何服务,请先单击「新建服务」,详情参考 [新建服务](/run/deploy/create-service)。 ::: 单击「新建版本」,在新建版本窗口中,继续填写版本所需配置信息,详情请参考 [版本配置说明](/run/deploy/version-setting): ![](https://main.qcloudimg.com/raw/59549c4e30b83d0d8152ba308ba436ec.png) 填写完版本配置信息后,单击「开始部署」,部署成功则状态变为“正常”。若有报错,会变为具体的错误状态。 ![](https://main.qcloudimg.com/raw/42a8b25f4a9cadf973286f93c6c60d30.png) :::tip 提示 - 若在新建版本时流量策略选择“部署完成后自动开启 100%流量”,则流量会从 0%变为 100%。 - 若选择了“部署完成后保持流量为 0 稍后再手动调整流量”,或者选择了“部署完成后自动开启 100%流量”但还想再次调整流量,可以进行手动配置,详情请参考 [流量配置](/run/deploy/traffic-setting)。 ::: 完成了部署和流量配置后,您可能希望能够快速访问自己的服务查看效果。云托管自动为您的服务分配了一个默认域名,您可以直接单击「访问服务」,通过这个默认域名访问您的服务页面。 :::tip 提示 - 您访问服务产生的即为真实业务流量。 - 如您配置流量时选择的模式为“按百分比”,则点击“访问服务”将按您设定的百分比概率随机访问某个版本; - 如您配置流量时选择的模式为“按 URL 参数”,则点击“访问服务”产生的是一个无参数的 HTTP 请求,会访问到您设置的默认版本上。您可自行构建含参数的请求进一步验证。 ::: ## 使用限制 - 一个服务可同时存在最多 10 个版本。 - 版本名由系统自动生成,格式为“服务名”+“序号”,序号按照创建顺序依次递增,不支持修改(举例:testservice-001, testservice-002 等)。 - 不再使用的版本可以手动删除,已删除的版本不计入版本总数,但不会影响新建版本的序号。(举例:删除掉版本 "testservice-002",再次新建的版本仍然会是 "testservice-003"。) ## 资源消耗说明 无论采用哪种副本模式,**部署过程本身都会产生一定的资源消耗**。 ### 低成本模式 虽然副本个数最小值为 0(无流量时缩容到 0 个实例不产生资源消耗和费用),但在部署过程中会先创建出 1 个实例,待部署成功后再触发缩容到 0。 例如:副本模式为“低成本”,规格为“1 核 1G”,流量策略为“部署完成后自动开启 100%流量”,部署耗时 5 分钟,部署成功后一直无任何业务流量。因为缩容到 0 的观测期为半小时,故会产生 CPU 使用量 35(核 x 分钟)以及内存使用量 35(GiB x 分钟)。 ### 高可用模式 部署开始即会创建出最小个数的实例,产生资源消耗。 例如: 副本模式为“高可用”,规格为“1 核 1G”,最小副本个数为 5,流量策略为“部署完成后保持流量为 0 稍后再手动调整流量”,部署耗时 5 分钟,部署成功后一直无任何业务流量。则会产生 CPU 使用量 25(核 x 分钟)以及内存使用量 25(GiB x 分钟)。 --- ## 查看或删除版本 # 查看或删除版本 当您向服务执行部署或更改服务配置时,系统会创建一个不可变的修订版本。 以下注意事项适用于修订版本: * 您不需要手动删除修订版本,但可以根据需要这样做。 * 未提供的修订版本不会使用任何资源,也不会产生费用。 * 统会自动分配修订版本号。 ## 查看版本列表 您可以在 ```服务详情``` -> ```部署记录``` 中查看服务的版本记录,如需了解版本的详细信息,可点击查看版本详情。 ## 删除版本 删除修订版本的一个常见使用场景是,您想要确保特定修订版本不会被意外使用。 在以下情况下,您无法删除修订版本: * 它能够接收流量, * 它是服务的唯一修订版本, * 它是该服务的最新修订版本。 当您删除某个修订版本后,该修订版本使用的容器映像不会自动从镜像仓库中删除。 您无法撤消修订版本删除操作。 您可以在 ```服务详情``` -> ```部署记录``` 中选择对应的版本进行删除。 ## 版本回退 要回滚到先前的版本,您可以在 ```服务详情``` -> ```部署记录``` 中选择相应的版本进行回退操作。 --- ## 配置自定义域名 # 配置自定义域名 本页介绍如何为服务配置公网自定义访问域名。 默认情况下,云托管会为每个云托管服务分配一个默认域名,但是该域名仅可用户开发和测试使用,且该域名不具有任何的鉴权策略,如果服务本身没有实现任何的鉴权策略,则有时候将服务暴露到公网是相对危险的,所以对于需要暴露到公网的服务,我们建议配置自定义域名,同时开启鉴权访问。 ## 准备 * 域名及 SSL 证书, 您也可以在[腾讯云SSL证书](https://console.cloud.tencent.com/ssl)进行购买, 购买单域名证书即可。 * 或者在[腾讯云SSL证书](https://console.cloud.tencent.com/ssl)上传您已有的证书。 ## 配置域名 * 进入[腾讯云托管环境配置](https://tcb.cloud.tencent.com/dev#/env/http-access) * 选择 ```HTTP 访问服务``` * 在```自定义域名```部分选择```添加域名``` * 填写准备好的域名及证书,点击确认完成域名配置 ## 域名关联资源 * 进入[腾讯云托管环境配置](https://tcb.cloud.tencent.com/dev#/env/http-access) * 选择 ```HTTP 访问服务``` * 在 ```域名关联资源``` 部分点击```新建```按钮 * 填写配置信息: * 关联资源: 云托管 * 资源实例: 资源实例选择需要访问的云托管服务 * 域名: 域名选择刚添加的自定义域名 * 触发路径: 默认为 /, 可根据实际情况填写需要暴露的路径 * 鉴权开关: 默认为关闭状态,如果需要使用[云开发鉴权](../../../authentication-v2/auth/introduce) * 路基透传: 默认为关闭状态,我们设置为开启状态 * 填写完配置信息,点击确认创建等待创建完成 * 创建完成之后,即可通过自定义域名访问云托管服务。 --- ## 内网互联 # 内网互联 本页面介绍云托管服务如何访问您的腾讯云账号的其它资源(如: cvm, mysql, redis 等)。 :::tip - 当前内网互联功能仅 ```标准版及以上套餐支持```,个人版暂不支持改功能。 - 个人版如需使用该功能,请前往[套餐管理](https://tcb.cloud.tencent.com/dev?#/env/package-usage/basic)升级您的套餐。 ::: 默认情况下,云托管服务和您的腾讯云账号下的其它资源(如: cvm, mysql, redis 等)内网网络无法互通。如果需要需要访问其它资源,需要为服务开启内网互联功能。 ### 开通内网互联功能 开通前提: * 您需要[腾讯云私有网络](https://console.cloud.tencent.com/vpc/vpc?rid=4)创建 VPC 网段。 * 区域需选择上海区域。 * VPC 网段子网掩码尽量使用``` >= 22```。 * 子网子网掩码尽量 ```<= 28```,该子网将被云托管服务占用,请尽量不要在该子网中创建其它资源,以免云托管服务被影响。 开通: * 1、登录[腾讯云托管](https://tcb.cloud.tencent.com/dev?#/platform-run)。 * 2、选择你要开启网络互联功能的服务,点击```服务详情```。 * 3、点击```服务设置```。 * 4、在```访问配置``` 点击编辑功能。 * 5、打开```私有网络```开关。 * 6、选择你新建的 VPC, 及其子网。 * 7、点击保存,等待服务更新完成。 * 8、服务更新完成之后,云托管服务即可访问 VPC 下的资源了。在创建 mysql, redis 等资源时,选择该 VPC 即可。 ## 使用注意事项 * 确保 VPC 网络中具有可分配的 IP 地址,否则可能会由于无法分配 IP,导致云托管服务实例启动失败。 * 如果需要接入 VPC 的服务访问外网,需要确保 VPC 中具备 NAT 网关,且路由配置正确。更多内容可见[NAT 网关说明](https://cloud.tencent.com/document/product/552/83056)。 --- ## 内网访问 # 内网访问 本页介绍如何使用内网访问。 默认情况下,云托管服务的内网访问是关闭状态。开通内网访问主要有以下场景: - 服务之间的相互访问 - 服务之间通过非 HTTP 协议进行相互访问 具体可参考[使用 gRPC 连接到其它服务](/run/develop/access/internal) ## 开通内网访问 您可以在创建服务时,在服务创建页面选择开启内网访问。 您也可以在服务创建之后,在 `服务详情` -> `服务设置` 中选择开启/关闭内网访问。 --- ## 公网访问 # 公网访问 本页介绍如何使用公网访问。 默认情况下,云托管服务公网访问时开通状态。公网访问会提供一个默认域名,该默认域名不会伴随服务的版本变化而变化。我们强烈建议您配置自己的[自定义域名](./custom-domains), 以免存在被封的风险。 默认情况下,云托管服务不会提供任何的鉴权操作,如需鉴权操作,请按照以下进行: * 服务本身自己实现鉴权操作 * 绑定自定义域名,在自定义域名侧开启鉴权操作 使用公网访问有如下场景: * 通过 web 网页访问云托管服务(通过小程序,微信公众号h5 ```callContainer``` 方法访问,不需要开通公网访问) * 使用 curl 命令测试服务请求状态 ## 开通/关闭公网访问 您可以在创建服务时,在服务创建页面选择开启/关闭公网访问。 您也可以在服务创建之后,在 ```服务详情``` -> ```服务设置``` 中选择开启/关闭公网访问。 --- ## 固定公网出口 IP # 固定公网出口 IP 在部分需要 IP 白名单验证的业务场景,需要云托管服务能够绑定固定公网出口 IP,例如微信支付、企业微信、公网访问数据库等。 ## 功能介绍 在启用固定公网 IP 功能后,云托管服务在请求外网时,会从一个固定公网 IP 请求到公网上。此时可以在需要绑定 IP 白名单的业务场景中,将云托管服务的公网 IP 添加到 IP 白名单中以便放通请求。 ## 配置方法 在云托管服务的“环境设置”中,编辑并启用“固定公网 IP”能力。 :::tip - 当前固定公网出口 IP 功能仅 ```标准版及以上套餐支持```,个人版暂不支持改功能。 - 个人版如需使用该功能,请前往[套餐管理](https://tcb.cloud.tencent.com/dev?#/env/package-usage/basic)升级您的套餐。 ::: ## 注意事项 - 如果服务同时启用了 VPC 私有网络,此时公网请求将被默认路由到私有网络中,此时需要在 VPC 私有网络中配置 NAT 网关,并使用 NAT 网关上的出口 IP 作为固定出口 IP。更多可见[公网网关](https://cloud.tencent.com/document/product/215/20078) 或 [NAT 网关](https://cloud.tencent.com/document/product/215/4975) 说明。 --- ## 服务设置 # 服务设置 ## 服务名称 环境下服务的唯一标识。创建成功后**不支持修改服务名称**。 如果您有多个环境,不同环境之间服务可以重名。(例如:开发环境和测试环境可以同时存在服务 "testservice")。 ## 网络相关设置 * 公网开关及域名:开启后,云托管服务会具备相关公网域名;公网域名可以通过 HTTPS 协议经过公网访问;公网域名可以用于前端小程序、APP、Web 应用通过域名访问云托管服务。关闭后将不再提供域名,且无法通过公网 HTTPS 协议访问服务,但是不影响小程序中通过 callContainer 方法访问到服务。 * 内网开关及域名:开启后,云托管服务将会具备内网域名;内网域名用于相同环境中的其他服务通过内网域名访问到当前服务。内网域名不限制访问协议,根据服务具体暴露的端口和协议,内网均可以访问通。 :::tip 提示 在小程序中使用 callContainer 方法调用服务,使用了微信与腾讯云间的特殊私有链路,不受公网开关影响;同时私有链路上具备更多特色能力。 ::: ## 运行规格配置 设置服务实例的 CPU、内存相关规格;当前 CPU、内存规格按 1:2 比例固定,即 1 核 CPU:2GiB 内存。当前最小可以设置到 0.25核 0.5GiB 规格,最大可以设置到 16 核 32 GiB 规格。 服务对应的实例规格根据设置固定扩缩容,即扩容时均为增加 1 个或多个按配置规格的实例。 ## 环境变量 设置服务环境变量,并且在设置后可以在服务实例内读取到。 环境变量可以通过两种方式设置:Key-Value 方式,或 JSON 方式。Key-Value 方式为分别设置环境变量的 Key 和 Value,例如:`"MyEnvKey":"MyEnvValue"`;JSON 方式需要编写合规 JSON,JSON 中的 Key 将对应环境变量的 Key,具体值将作为环境变量 Value,例如: ```json { "DATABASE_URL": "postgresql://user:password@host:port/database", "API_KEY": "your_api_key", "NODE_ENV": "development" } ``` ## 日志设置 日志设置配置如何采集服务实例中的日志。日志默认配置为 stdout,即采集标准输出日志。日志设置支持采集多种日志,包括标准输出、日志文件,其中日志文件配置支持使用 ` * ` 的通配路径。多个配置间使用英文逗号 `,` 分割。 配置日志后,后续可以在服务日志中查询采集到的日志内容。 日志配置示例: ``` stdout //仅采集标准输出日志 stdout,/path/to/logfile //采集标准输出日志和配置路径上的日志文件 stdout,/path/to/log/* //采集标准输出日志和配置路径上的所有日志文件 /path/to/log/logfile* //采集 logfile 开头的多个日志文件 ``` --- ## 流量配置说明 # 流量配置说明 CloudBase 云托管支持「按百分比」和「按 URL 参数」进行流量分配,开发者可以基于此实现**灰度发布、蓝绿发布**等功能、 ## 按百分比(随机)分配流量 - 单击「流量配置」。 - 模式采用默认「按百分比」。 - 选中刚部署完的最新版本和当前运行中的旧版本,并为每个版本指定流量百分比。所有百分比加起来需要等于 100%或 0%,否则无法完成。未在流量配置窗口中添加的版本,将统一将流量百分比变为 0%。 - 单击「完成」,系统立刻开始按百分比随机分配流量,将部分流量从旧版本引向新版本。 >/> 成功后,可以看到对应版本的流量百分比已经变化。 ![](https://main.qcloudimg.com/raw/e6e391e040d237444bb47bac24982e3c.png) ## 按 URL 参数(定向)分配流量 - 单击「流量配置」。 - 模式选择「按 URL 参数」。 - 添加部署完的最新版本,设定 URL 参数 key 和 value(支持 Glob 表达式)。符合条件的请求将路由到新版本。 - 再添加当前运行中的旧版本和对应的 URL 参数。 - 将旧版本设置为默认版本。 - 在“匹配结果预测”中输入 URL 参数模拟请求,点击「预测」查看对应版本,调试配置。 - 单击「完成」,系统立刻开始将部分流量从旧版本引向新版本。 >/> 成功后,可以看到对应版本的流量条件已经变化。 >/> --- ## 版本配置说明 # 版本配置说明 ## 基础配置说明 ### 上传方式 支持本地代码/代码库拉取/镜像拉取三种方式。 #### 方式 1:本地代码 上传代码工程文件夹或 zip 压缩包,系统解析成功后先将代码构建为镜像、将镜像推送到服务绑定的镜像仓库储存,然后基于该镜像进行部署。 **此方式需要您自行编写 Dockerfile 并包含在代码文件夹或 zip 压缩包中。** :::tip 提示 我们提供 [Java](https://clooudbaserun-1258016615.cos.ap-shanghai.myqcloud.com/java_helloworld.zip)、[PHP](https://clooudbaserun-1258016615.cos.ap-shanghai.myqcloud.com/php_helloworld.zip)、[Node.js](https://clooudbaserun-1258016615.cos.ap-shanghai.myqcloud.com/nodejs_helloworld.zip)、[Golang](https://clooudbaserun-1258016615.cos.ap-shanghai.myqcloud.com/go_helloworld.zip)、[Python](https://clooudbaserun-1258016615.cos.ap-shanghai.myqcloud.com/python_helloworld.zip) 语言的示例代码包下载用于 Demo。除此之外的任意开发语言也都可支持。 如需更多语言的 Demo 代码包资源,请[联系我们](https://cloud.tencent.com/act/event/connect-service)。 ::: #### 方式 2:代码库拉取 获得您的授权后,从您的 GitHub / GitLab / 码云 Gitee 仓库拉取代码后,先将代码构建为镜像、将镜像推送到服务绑定的镜像仓库储存,然后基于该镜像进行部署。 **此方式需要您自行编写 Dockerfile 并包含在代码库中。** :::tip 提示 首次使用需要您先进行授权。授权成功后,当前环境任意服务新建版本都不再需要再次授权。 ::: #### 方式 3:镜像拉取 无需系统提供从代码构建镜像的服务,由您自行采用任意方式构建好镜像后,手动将镜像上传至服务所绑定的镜像仓库中,然后系统基于您选定的镜像进行部署。 :::tip 提示 1. 如何上传镜像,请查看本文档“相关操作”中的“手动上传镜像”部分。 2. 使用 Demo 镜像可快速体验部署过程。选择 Demo 镜像后无需修改任何配置,直接开始部署。 ::: ### 监听端口 应用监听端口。默认为 80。 ### 流量策略 部署完成后,如何开启流量。目前有如下两种选择: - 部署完成后保持流量为 0 稍后再手动调整流量:希望部署完后先手动验证再开流量,或只希望引入部分流量进行灰度升级。 - 部署完成后自动开启 100%流量:首次部署完成后立刻开流量,或升级时进行全量升级。 ### 备注信息 选填,会展示在版本列表页面中,对部署不产生任何影响。 ## 自动扩缩容配置说明 ### 副本模式 支持低成本/高可用两种模式。 #### 模式 1:低成本 适合对成本敏感,对冷启动相对不敏感的业务。 - 副本个数最小值为 0,当没有流量打到版本上时,版本将缩容到 0,不保留任何实例,不产生任何费用。 - 连续半个小时无流量才将实际缩容到 0(避免流量偶然波动带来的误判)。再次冷启动时,可能有 30 秒服务延迟。 - 默认推荐规格为最小规格 0.25 核 0.5G,**单价最低**。您也可按需调整规格。 - 虽然没有业务流量,部署过程中仍然会先产生一个实例,部署完成后再缩容到 0,因此**部署过程本身会产生一定的资源消耗。** :::tip 提示 将版本流量百分比设置为 0 并不是触发缩容到 0 的充要条件。低成本模式下,版本流量百分比设置为 0,一定会触发缩容到 0。但如果版本流量百分比不为 0,需要连续半小时的观测期,期间版本没有产生真实业务流量,才会触发缩容到 0。 ::: #### 模式 2:高可用 适合对成本相对不敏感,对服务常驻有诉求,或无法接受冷启动的业务。 - 副本个数最小值不能为 0,可以设置为 1 ~ 50 间的任意整数。即便没有流量打到版本上,仍会保持最小个数的实例数,也会**持续产生费用**。 - 默认推荐规格为 1 核 1G。您也可以按需调整规格。 - 部署过程中即开始按最小副本个数和规格产生实例,**部署过程本身会产生一定的资源消耗。** ### 规格 指集群中每个容器实例的配置。自动扩容时,新创建的实例将使用这个规格。同一个版本下所有容器实例规格都会保持一致。 ### 副本个数 指当前版本在自动扩缩容时可达到的最大实例数及最小实例数。最小值下限为 0,最大值上限为 50。 如需将最小值修改为 0,请先切换副本模式至“低成本”。 如需将最小值修改为大于 0 的整数,请先切换副本模式至“高可用”。 ### 扩缩容条件 当达到某个条件时,云托管会自动会创建/删除实例,然后检测是否再次达到条件,如果满足条件则继续扩缩容,如此反复直至实例数量达到副本个数的最小值/最大值,或不再满足扩缩容条件时停止自动扩缩容。 目前仅支持 CPU 使用率作为扩缩容条件,更多扩缩容指标敬请期待。 :::tip 提示 - 自动扩容到副本个数最大值后若仍不足以承载业务流量,即便再次达到扩缩容条件,也不会继续创建新的实例,可能导致您的业务受影响,请您评估好业务指标后合理设定副本个数最大值。 - 若希望提升最大值限额(大于 50),请提交工单联系我们单独处理。 ::: ## 高级配置说明 高级配置可不做任何修改直接使用默认值开始部署。 ### InitialDelaySeconds 实例创建完成后,等待一定的时间后开始进行健康检查。若健康检查失败,将重试 3 次,依然失败则判定服务版本异常。请将此值设定为大于应用启动的时间,否则版本可能持续处于异常状态。默认值为 2 秒。 ### 日志采集路径 可设置目录或文件,支持设置多个路径。采集到的日志可以在 [日志管理](https://console.cloud.tencent.com/tcb/log) 中查看。支持标准输出(stdout)以及 \* 通配路径(例:/logs/\*),使用 ,(半角逗号)分割,留空将采集标准输出。 ### 环境变量 用户所需的环境变量,直接传入容器中。以 key value 的形式可配置多个。 --- ## 通过 HTTP 访问 # 通过 HTTP 访问 创建云托管服务之后, 云托管会为您提供该服务的 HTTPS 访问域名。您可以通过该域名,来访问您部署的服务。 所有的云托管服务都会提供一个默认域名,不过正式环境场景下,我们强烈建议您通过 [HTTP 访问服务](/service/introduce)配置[自定义自定义域名](../../deploy/networking/custom-domains),通过 HTTP 访问服务访问服务时,可以开启服务鉴权、自定义域名等能力。 ## 创建服务 在云托管上创建服务需要满足以下条件: - 通过公共互联网访问 - 供公众使用的网址 云托管默认为用户提供公共互联网访问,且默认域名不会有任何的鉴权操作,如需关闭公网域名访问,请在部署服务之后,在`服务设置` -> `网络访问` 中关闭公网开关。 ## 服务域名 ### 公网域名 云托管会为每个服务分配一个公网域名,您可以通过该域名访问您的云托管服务。您也可以在 `服务设置` -> `网络访问` 中关闭公网开关。 我们假设创建的服务默认域名为: `https://demo.ap-shanghai.run.tcloudbase.com` ### 内网域名 云托管也会为每个服务分配一个内网域名,该内网域名默认是关闭状态。您可以在 `服务设置` -> `网络访问` 中开启公网开关。 内网域名有以下场景: - 服务之间通过 HTTP 相互访问 - 复制直接通过 gRPC 相互访问 - 服务间通过其它 4 层协议相互访问等等 ### 通过 CURL 访问 ```sh curl --location --request GET 'https://demo.ap-shanghai.run.tcloudbase.com' ``` ### 通过 PHP-CURL 访问 ```php 'https://demo.ap-shanghai.run.tcloudbase.com', CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => '', CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 0, CURLOPT_FOLLOWLOCATION => true, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => 'GET', )); $response = curl_exec($curl); curl_close($curl); echo $response; ``` ### 通过 fetch 访问 ```js fetch("https://demo.ap-shanghai.run.tcloudbase.com", { method: "GET", redirect: "follow", }) .then((response) => response.text()) .then((result) => console.log(result)) .catch((error) => console.log("error", error)); ``` ### 通过浏览器 JS-XHR 访问 ```js const xhr = new XMLHttpRequest(); xhr.withCredentials = true; xhr.addEventListener("readystatechange", function () { if (this.readyState === 4) { console.log(this.responseText); } }); xhr.open("GET", "https://demo.ap-shanghai.run.tcloudbase.com"); xhr.send(); ``` ### 通过 QQ 小程序访问 ```js qq.request({ url: "https://demo.ap-shanghai.run.tcloudbase.com", success(res) { console.log(res.data); }, }); ``` ### 通过 UNI-APP 访问 ```js uni.request({ url: "https://demo.ap-shanghai.run.tcloudbase.com", success: function (res) { console.log(res.data); }, }); ``` --- ## 内网访问 # 内网访问 云托管支持服务间[内网访问](/run/deploy/networking/private),允许您在云托管服务之间进行高效的通信。内网调用可以提高服务间通信的速度和安全性,避免了公共互联网的延迟和潜在风险。 ## 使用 gRPC 连接到其它服务 本页面向希望使用 gRPC 将云托管服务与其它服务连接起来(例如在内部服务直接提供高性能通信)的开发者介绍特定于云托管服务的详细信息。您将可以将[所有 gRPC 类型](https://grpc.io/docs/what-is-grpc/core-concepts/#rpc-life-cycle)(流式传输或一元)与云托管结合使用。 可能使用的场景包括: - 内部微服务之间的相互通信 - 在 gRPC 服务器中使用流式传输 gRPC 来构建响应更快的应用和 API。 如需将您的服务与 gRPC 集成,请执行以下操作: - `服务设置` -> `网络访问` 中开启内网开关,并通过内网域名进行相互访问。 - 如果使用流式传输 gRPC,将服务配置为使用 HTTP/2。 HTTP/2 是 gRPC 流式传输的传输方法。 - 在 proto 文件中定义请求消息和响应,并对其进行编译。 - 创建一个客户端,用于发送请求并处理来自 gRPC 服务器的响应。 - 构建和部署服务。 ### 监听云托管服务中的 gRPC 请求 云托管中运行的 gRPC 服务器的唯一特殊要求是监听 PORT 环境变量指定的端口,如以下代码所示: ```go func main() { log.Printf("grpc-ping: starting server...") port := os.Getenv("PORT") if port == "" { port = "8080" log.Printf("Defaulting to port %s", port) } listener, err := net.Listen("tcp", ":"+port) if err != nil { log.Fatalf("net.Listen: %v", err) } grpcServer := grpc.NewServer() pb.RegisterPingServiceServer(grpcServer, &pingService{}) if err = grpcServer.Serve(listener); err != nil { log.Fatal(err) } } ``` ### 打开与服务的 gRPC 连接 要打开与服务的 gRPC 连接以便发送 gRPC 消息,需要打开服务的内网开关,获取到内网域名,同时通过 PORT 环境变量只能的端口进行访问, 如下代码所示: ```go import ( "crypto/tls" "crypto/x509" "google.golang.org/grpc" "google.golang.org/grpc/credentials" ) // NewConn creates a new gRPC connection. // host should be of the form domain:port, e.g., example.com:443 func NewConn(host string, insecure bool) (*grpc.ClientConn, error) { var opts []grpc.DialOption if host != "" { opts = append(opts, grpc.WithAuthority(host)) } if insecure { opts = append(opts, grpc.WithInsecure()) } else { // Note: On the Windows platform, use of x509.SystemCertPool() requires // Go version 1.18 or higher. systemRoots, err := x509.SystemCertPool() if err != nil { return nil, err } cred := credentials.NewTLS(&tls.Config{ RootCAs: systemRoots, }) opts = append(opts, grpc.WithTransportCredentials(cred)) } return grpc.Dial(host, opts...) } ``` ### 发送请求 以下示例展示了如何使用按之前所述方法配置的 gRPC 连接来发送服务请求: ```go import ( "context" "time" pb "github.com/GoogleCloudPlatform/golang-samples/run/grpc-ping/pkg/api/v1" "google.golang.org/grpc" ) // pingRequest sends a new gRPC ping request to the server configured in the connection. func pingRequest(conn *grpc.ClientConn, p *pb.Request) (*pb.Response, error) { ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() client := pb.NewPingServiceClient(conn) return client.Send(ctx, p) } ``` --- ## 微信小程序 # 微信小程序 微信小程序中可以通过内置的 `wx.cloud.callContainer` 方法来访问云托管服务。使用该方法之前,需要确保腾讯云账号和小程序已经完成[关联操作](/quick-start/create-env#%E9%99%84%E5%A6%82%E4%BD%95%E5%85%B3%E8%81%94%E5%BE%AE%E4%BF%A1%E5%B0%8F%E7%A8%8B%E5%BA%8F)。 ```js // 确认已经在 onLaunch 中调用过 wx.cloud.init 初始化环境(任意环境均可,可以填空) const res = await wx.cloud.callContainer({ config: { env: "填入云环境ID", // 微信云托管的环境ID }, path: "/xxx", // 填入业务自定义路径和参数,根目录,就是 / method: "POST", // 按照自己的业务开发,选择对应的方法 header: { "X-WX-SERVICE": "xxx", // xxx中填入服务名称(微信云托管 - 服务管理 - 服务列表 - 服务名称) // 其他header参数 }, // dataType:'text', // 默认不填是以JSON形式解析返回结果,若不想让SDK自己解析,可以填text // 其余参数同 wx.request }); console.log(res); ``` 如上使用前,需要在小程序 app.js 中,执行 `wx.init`,如下代码: ```js App({ async onLaunch() { // 使用callContainer前一定要init一下,全局执行一次即可 wx.cloud.init(); // 下面的请求可以在页面任意一处使用 const result = await wx.cloud.callContainer({ config: { env: "prod-01", // 微信云托管的环境ID }, path: "/", // 填入业务自定义路径和参数,根目录,就是 / method: "GET", // 按照自己的业务开发,选择对应的方法 header: { "X-WX-SERVICE": "xxx", // xxx中填入服务名称(微信云托管 - 服务管理 - 服务列表 - 服务名称) }, // dataType:'text', // 默认不填是以JSON形式解析返回结果,若不想让SDK自己解析,可以填text }); console.log(result); }, }); ``` 小程序中使用 callContainer 访问云托管更多的信息参见: - [微信小程序-访问云托管服务](https://developers.weixin.qq.com/miniprogram/dev/wxcloudservice/wxcloudrun/src/development/call/mini.html) - [callContainer](https://developers.weixin.qq.com/miniprogram/dev/wxcloudservice/wxcloudrun/src/practice/call.html) ## 使用优势(wx.cloud.callContainer VS wx.request) 1. 不耗费任何公网流量,前后端通信走内网; 2. 天然免疫 DDoS 攻击,仅授权小程序/公众号可访问后端,其他人即便拿到环境 id 和服务名也无法访问; 3. 通过微信就近接入节点加速,无视后端服务地域影响,没有跨地域延迟,后端无需多地部署; 4. 无需在小程序后台配置「服务器域名」; 5. 后端可直接获取用户信息,无需调接口即可以获取 opneid 等(仅适用微信云托管、腾讯云侧的云托管暂无)。 6. 因此,如果云托管服务只有微信小程序/公众号会调用,建议在服务设置中关闭公网访问。 --- ## 通过 SDK/API 访问 # 通过 SDK/API 访问 一些仅把云托管当做 API server 的应用场景,可以通过开放 SDK/API 访问云托管服务。类似微信小程序内置 callContainer 方法,通过开放 SDK/API 也不需要开启公网访问即可访问云托管服务。通过开放 SDK/API 访问云托管服务,可以根据 access_token 对服务访问进行精细话的[权限控制](/run/deploy/authenticating/end-users)。 如果是 web 应用,需要先进行[安全域名配置](/faq/allowed_domain) 来支持 CORS 跨域。 ## JS-SDK 访问 ```js import cloudbase from "@cloudbase/js-sdk"; //初始化SDK实例 const app = cloudbase.init({ env: "xxxx-yyy", }); app .callContainer({ name: "helloworld", method: "POST", path: "/abc", header: { "Content-Type": "application/json; charset=utf-8", }, data: { key1: "test value 1", key2: "test value 2", }, }) .then((res) => { console.log(res); }); ``` 更多信息请参考 [JS-SDK 文档](/api-reference/webv3/cloudrun)。 ## Node.js SDK 访问 如在云函数中访问云托管服务: ```js import tcb from '@cloudbase/node-sdk' exports.main = async (event, context) => { const { httpContext } = context const { url, httpMethod } = httpContext console.log(`[${httpMethod}][${url}]`) const tcbapp = tcb.init({ context }) const result = await tcbapp.callContainer({ name: 'helloworld', method: 'POST', path: '/abc', data: { key1: 'test value 1', key2: 'test value 2' }, { timeout: 5000 } }) console.log(result) } ``` 更多信息请参考 [Node.js SDK 文档](/api-reference/server/node-sdk/cloudrun)。 ## HTTP API 访问 通过[云托管 HTTP API](/http-api/cloudrun/云托管) 访问云托管服务,您需要先获取访问令牌(Token),然后使用该令牌进行 API 调用。 ```sh curl -L 'https://your-envId.api.tcloudbasegateway.com/v1/cloudrun/:name' \ -H 'Content-Type: application/json' \ -H 'Accept: application/json' \ -H 'Authorization: Bearer ' \ -d '{}' ``` 针对可能存在的合规封禁风险,HTTP API 对请求和响应均有所封装: - 所有的请求都需要携带 `Authorization: Bearer ` 形式的访问令牌; - 对于所有的 `GET` 请求返回的响应,响应头添加 `Content-Disposition: attachment`; - 对于非文本类型(文本类型包括响应头 `Content-Type` 中值是`application/json`、`application/x-www-form-urlencoded`、`text/plain` 类型的返回内容)的响应,响应头添加 `Content-Disposition: attachment`; - Server-sent Event 和 WebSocket 请求不受到上述限制。 --- ## 使用 Websocket # 使用 Websocket [WebSocket](https://developer.mozilla.org/zh-CN/docs/Web/API/WebSockets_API) 是一种网络通信协议,它提供了在单个 TCP 连接上进行全双工通信的能力。与传统的 HTTP 请求-响应模式不同,WebSocket 允许服务器主动向客户端推送数据,实现了真正的双向通信。 主要特点: - 全双工通信:客户端和服务器可以同时发送和接收数据 - 低延迟:建立连接后,数据传输的开销很小 - 实时性:服务器可以主动推送数据,无需客户端轮询 - 持久连接:一次握手后保持连接状态,避免重复建立连接 WebSocket 协议以 `ws://` 或 `wss://`(安全连接)开头,使用标准的 HTTP 握手过程建立连接,之后升级为 WebSocket 协议进行通信。 本文介绍如何使用云托管(容器型和函数型)实现 Websocket 收发消息,并在客户端访问这些服务。 ## 使用函数型云托管 在本地创建一个目录 `websocket-demo`,在目录中新建一个 `index.js` 文件,并编写以下代码: ```js exports.main = function (event, context) { console.log({ event, context }); if (context.ws) { const ws = context.ws; ws.on("close", (msg) => { console.log("close: ", msg); ws.send("bye!"); }); ws.on("message", (msg) => { console.log("message: ", msg); ws.send(`echo: ${msg?.data}`); }); } }; exports.main.handleUpgrade = async function (upgradeContext) { console.log(upgradeContext, "upgradeContext"); if (upgradeContext.httpContext.url === "/reject-upgrade") { return { allowWebSocket: false, statusCode: 403, body: JSON.stringify({ code: "code", message: "message" }), contentType: "appliaction/json; charset=utf-8", }; } return { allowWebSocket: true }; }; ``` 这段代码实现了以下功能: - main 函数处理 WebSocket 连接后的消息交互: - 监听 close 事件,在连接关闭时发送告别消息 - 监听 message 事件,收到消息时回复当前时间和消息内容 - handleUpgrade 函数控制 WebSocket 连接的建立: - 当访问 /reject-upgrade 时拒绝连接 - 其他路径允许建立 WebSocket 连接 ### 部署调试 推荐使用 [云开发 CLI](/cli-v1/intro) 进行部署。 安装 CLI 并登录后,进入项目根目录,执行以下命令: ```bash # 部署函数型云托管实例 tcb cloudrunfuntion deploy ``` 实例部署完成以后,前往 [云开发控制台](https://tcb.cloud.tencent.com/dev)。 在左侧导航栏选择【云托管】, 在【服务列表】页面可以找到刚刚部署的实例,点击进入【服务详情】页面,在详情页可以找到默认域名。 将默认域名开头的 `https://` 替换为 `ws://` 或者 `wss://` ,在 Postman 等工具中进行 WebSocket 连接测试。 ## 使用容器型云托管 你可以使用代码示例,[示例代码仓库地址](https://github.com/TencentCloudBase/awesome-cloudbase-examples/tree/master/cloudbaserun/websocket-demo)。 克隆代码仓库后,进入项目根目录,目录结构如下: ```bash ├── Dockerfile ├── app │   └── server.js └── package.json ``` 其中 `app/server.js` 是使用 `express` 和 `express-ws` 实现的服务,云托管会根据 `Dockerfile` 来构建容器。 关于容器型云托管的更多信息,可以参考 [服务开发说明](/run/develop/developing-guide)。 ### 部署调试 推荐使用 [云开发 CLI](/cli-v1/intro) 进行部署。 安装 CLI 并登录后,进入项目根目录,执行以下命令: ```bash # 部署容器型云托管实例 tcb cloudrun deploy ``` 实例部署完成以后,前往 [云开发控制台](https://tcb.cloud.tencent.com/dev)。 在左侧导航栏选择【云托管】, 在【服务列表】页面可以找到刚刚部署的实例,点击进入【服务详情】页面,在详情页可以找到默认域名,我们假设创建的服务默认域名为:,将默认域名开头的 `https://` 替换为 `ws://` 或者 `wss://` 如:,在 Postman 等工具中进行 WebSocket 连接测试。 ## 访问 websocket 服务 ### 微信小程序 ```js wx.cloud.init({ env: "xxxx-yyy", // 替换为你的环境 ID }); const { socketTask } = await wx.cloud.connectContainer({ service: "websocket-demo", // 替换自己的服务名 path: "/", // 不填默认根目录 }); socketTask.onMessage(function (res) { console.log("【WEBSOCKET】", res.data); }); socketTask.onOpen(function (res) { console.log("【WEBSOCKET】", "链接成功!"); socketTask.send({ data: "这是小程序消息", }); }); socketTask.onClose(function (res) { console.log("【WEBSOCKET】链接关闭!"); }); ``` 更新信息可以查看[微信云托管文档](https://developers.weixin.qq.com/miniprogram/dev/wxcloudservice/wxcloudrun/src/development/websocket/miniprogram.html)。 ### 浏览器 ```js const ws = new WebSocket("wss://demo.ap-shanghai.run.tcloudbase.com"); // 替换为你的服务地址 ws.onopen = function () { console.log("链接建立成功"); ws.send("微信云托管测试信息"); // 发送消息 }; ws.onmessage = function (evt) { console.log(evt.data); }; ws.onclose = function () { console.log("链接已经关闭"); }; ``` ### Node.js Node.js 中可以使用 [ws](https://www.npmjs.com/package/ws) 模块来实现 WebSocket 客户端。 ```js import WebSocket from "ws"; function run() { const ws = new WebSocket("wss://demo.ap-shanghai.run.tcloudbase.com"); // 替换为你的服务地址 ws.on("close", (code, reason) => { console.log("close:", code, `${reason}`); }); ws.on("error", (err) => { console.error("error: ", err); }); ws.on("upgrade", () => { console.log("upgrade"); }); ws.on("ping", () => { console.log("recv ping message"); }); ws.on("pong", () => { console.log("recv pong message"); setTimeout(() => { ws.ping(); }, 1000); }); ws.on("unexpected-response", (ws, req, res) => { // 非 upgrade 响应和 3xx 重定向响应认为是 unexpected-response console.log("recv unexpected-response message"); }); ws.on("message", (data) => { console.log("received: %s", data); }); ws.on("open", () => { ws.ping(); ws.send("string data"); ws.send(Buffer.from("buffer data")); }); } run(); ``` --- ## 从 Dockerfile 构建 # 从 Dockerfile 构建 ```Dockerfile``` 如果存在,我们将在服务的根目录下寻找和使用。 当腾云云托管 ```Dockerfile``` 在构建过程中使用时,它会在部署日志中通知您构建过程: ![](img/docker_build.jpg) ## 自定义 Dockerfile 路径 默认情况下,我们会根据根目录中查找名为 ```Dockerfile``` 的文件。如果您想使用自定义文件名称, 客户在部署时指定 Dockerfile 的名称。如下: ![](img/dockerfile_path.jpg) --- ## MySQL 数据库集成 # MySQL 数据库集成 ## 概述 云托管提供了多种方式连接和操作 MySQL 数据库,满足不同场景下的应用需求。本文档将详细介绍以下几种连接方式: | 连接方式 | 适用场景 | 优势 | |---------|---------|------| | 云开发 MySQL 数据库 | 同一云开发环境内的应用 | 内网直连,安全高效 | | 公网连接 | 连接任意可公网访问的 MySQL 实例 | 灵活性高,适用范围广 | | 内网互联 | 连接腾讯云上海区域的 MySQL 实例 | 安全性高,性能好 | | 数据模型 OpenAPI | 需要高级数据模型功能的应用 | 简化数据操作,提供权限控制 | > **注意**:本文示例基于[Express 应用框架](../languages-frameworks/express)构建,您可以根据自己的技术栈选择相应的数据库驱动和连接方式。 ## 连接云开发 MySQL 数据库 ### 开通云开发 MySQL 数据库 1. 登录[腾讯云开发控制台](https://tcb.cloud.tencent.com/dev),进入您的云开发环境 2. 在左侧导航栏选择**数据库** > **MySQL数据库** 3. 选择**数据库管理**选项卡 4. 根据您的情况选择: - **已有数据模型**:如直连数据库能力未开通,需升级和迁移数据库后才可提供,可提交工单,技术支持人员将协助您升级数据库 - **首次使用**:系统将提示您初始化新的数据库 - 选择所需的 MySQL 版本 - 设置数据库管理员密码(请妥善保存) - 点击确认,等待数据库初始化完成 5. 初始化完成后,在**数据库管理**页面可以查看数据库的连接信息,包括: - 内网连接地址 - 端口 - 用户名 ### 在云托管服务中使用云开发 MySQL 数据库 云托管服务可以直接通过内网地址连接云开发 MySQL 数据库,无需额外配置: 1. 获取云开发 MySQL 数据库的连接信息(内网地址、端口、用户名和密码) 2. 在云托管服务的环境变量中配置这些连接信息 3. 使用下文[通过公网连接数据库](#通过公网连接数据库)章节中的代码示例,将连接参数替换为云开发 MySQL 数据库的内网连接信息 > **优势**:内网连接速度快、安全性高,无需暴露数据库到公网 ## 通过公网连接数据库 ### 准备工作 1. 确保您的 MySQL 数据库已开启公网访问,并设置了合适的访问控制规则 2. 准备好数据库连接信息(主机地址、端口、用户名、密码、数据库名) ### 实现步骤 #### 1. 创建数据库和表 首先,在您的 MySQL 数据库中创建一个名为 `express_dev` 的数据库,并创建用户表: ```sql CREATE DATABASE IF NOT EXISTS express_dev; USE express_dev; CREATE TABLE persons ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(100) NOT NULL, age INT NOT NULL ); -- 可选:插入一些测试数据 INSERT INTO persons (name, age) VALUES ('张三', 25), ('李四', 30), ('王五', 35); ``` **表结构说明**: - `id`:自增主键,唯一标识每条记录 - `name`:人名,VARCHAR 类型,最长 100 个字符,不允许为空 - `age`:年龄,INT 类型,不允许为空 #### 2. 安装数据库驱动 在您的 Express 项目中安装 MySQL 驱动: ```bash npm install mysql2 --save ``` > 推荐使用 `mysql2` 而非 `mysql`,因为前者支持 Promise API 和更好的性能 #### 3. 编写数据库连接代码 打开 `routes/index.js` 文件,修改为以下内容: ```js const express = require('express'); const mysql = require('mysql2/promise'); const router = express.Router(); // 创建 MySQL 连接池 const pool = mysql.createPool({ host: process.env.DB_HOST, user: process.env.DB_USER, password: process.env.DB_PASSWORD, database: process.env.DB_NAME, port: process.env.DB_PORT ? Number(process.env.DB_PORT) : 3306, waitForConnections: true, connectionLimit: 10, queueLimit: 0 }); /* GET home page. */ router.get('/', async function(req, res, next) { try { const connection = await pool.getConnection(); try { const [rows] = await connection.query('SELECT * FROM persons LIMIT 10'); res.json({ success: true, data: rows }); } finally { // 确保连接返回到池中 connection.release(); } } catch (err) { console.error('数据库查询错误:', err); res.status(500).json({ success: false, error: '数据库查询失败' }); } }); module.exports = router; ``` #### 4. 配置环境变量并部署 在云托管服务中配置以下环境变量: | 环境变量 | 说明 | 示例值 | |---------|------|-------| | `DB_HOST` | 数据库主机地址 | `mysql-example.mysql.database.tencentcloud.com` | | `DB_USER` | 数据库用户名 | `root` | | `DB_PASSWORD` | 数据库密码 | `your_password` | | `DB_NAME` | 数据库名称 | `express_dev` | | `DB_PORT` | 数据库端口 | `3306` | > **安全提示**:敏感信息如数据库密码应使用云托管的环境变量功能存储,避免硬编码在代码中 #### 5. 测试连接 部署完成后,访问云托管服务的根路径,如果一切正常,您将看到从数据库中查询的用户数据。 ## 通过内网互联连接腾讯数据库 ### 适用场景 该方式适用于连接在腾讯云上海区域购买的 MySQL 数据库实例,通过内网互联可以实现更高效、更安全的数据库访问。 ### 配置步骤 1. **购买腾讯云 MySQL 实例** - 登录[腾讯云控制台](https://console.cloud.tencent.com/) - 选择**数据库 MySQL**服务 - 购买时选择**上海**地域 - 完成购买并初始化数据库 2. **配置内网互联** - 在云托管控制台中,选择**网络配置** > **内网互联** - 点击**配置 VPC 连接** - 选择目标 VPC 网络(您的 MySQL 实例所在的 VPC) - 保存配置 3. **使用内网地址连接** - 获取 MySQL 实例的内网地址(可在腾讯云 MySQL 控制台查看) - 在云托管服务的环境变量中配置数据库连接信息,使用内网地址 - 使用与[公网连接](#通过公网连接数据库)相同的代码,但连接地址改为内网地址 ### 优势 - **安全性**:数据库流量不经过公网,降低安全风险 - **性能**:内网连接延迟低,吞吐量高 - **成本**:避免公网流量费用 > **注意**:内网互联功能仅支持连接同一账号、同一地域的资源。如需跨地域连接,请考虑使用公网连接方式。 ## 通过数据模型 OpenAPI 操作数据库 数据模型 OpenAPI 提供了一种更高级的方式来操作数据库,它封装了底层的数据库操作,提供了权限控制、数据验证等功能。 ### 相关资源 - [数据库/数据模型介绍](/database/introduce) - [数据模型 HTTP API 文档](/http-api/model/%E6%95%B0%E6%8D%AE%E6%A8%A1%E5%9E%8B-openapi) ### 实现步骤 #### 1. 创建数据模型 1. 登录[云开发控制台](https://tcb.cloud.tencent.com/dev#/data-model/datasource) 2. 点击**创建数据模型**,配置如下: - **创建模式**:创建数据库并配置数据模型 - **创建方式**:从空白创建 - **写入到数据库**:数据库(MySQL 型) - **模型名称**:用户 - **模型标识**:users 3. 添加字段: - 字段 1: - **字段名称**:姓名 - **字段标识**:name - **类型**:文本类型 - 字段 2: - **字段名称**:年龄 - **字段标识**:age - **类型**:数字 4. 点击**确认**完成创建 #### 2. 创建用户并授权 1. 进入**腾讯云开发** > **扩展能力** > [**云后台管理**](https://tcb.cloud.tencent.com/dev#/cloud-admin) 2. 选择**用户管理** > **创建用户**,填写用户信息并创建 3. 选择**权限控制** > **系统角色** > **超级管理员** > **添加成员** 4. 将刚才创建的用户添加为超级管理员 #### 3. 创建 Express 路由处理数据模型 API 调用 1. 安装必要的依赖: ```bash npm install axios express --save ``` 2. 在 `routes` 目录下创建 `users.js`: ```js const express = require("express"); const router = express.Router(); const axios = require("axios"); // 从环境变量读取配置 const envId = process.env.ENV_ID; const username = process.env.USERNAME; const password = process.env.PASSWORD; const modelName = process.env.MODEL_NAME || "users"; // 用户登录获取 token async function signin(envId, username, password) { const url = `https://${envId}.api.tcloudbasegateway.com/auth/v1/signin`; try { const response = await axios.post( url, { username, password, verification_token: "" }, { headers: { "Content-Type": "application/json", Accept: "application/json", }, } ); const data = response.data; if (!data.token_type || !data.access_token) { throw new Error("返回数据缺少 token_type 或 access_token"); } return `${data.token_type} ${data.access_token}`; } catch (error) { console.error("登录失败:", error.response?.data || error.message); throw error.response?.data || error; } } // 获取数据模型列表 async function getModelList(envId, modelName, token) { const url = `https://${envId}.api.tcloudbasegateway.com/v1/model/prod/${encodeURIComponent( modelName )}/list`; try { const response = await axios.get(url, { headers: { Accept: "application/json", Authorization: token, }, }); return response.data.data; } catch (error) { console.error("获取模型列表失败:", error.response?.data || error.message); throw error.response?.data || error; } } // 获取用户列表路由 router.get("/", async (req, res) => { if (!envId || !username || !password) { return res.status(400).json({ success: false, error: "缺少必要的环境变量配置" }); } try { // 先登录获取 token const token = await signin(envId, username, password); // 使用 token 获取模型列表 const data = await getModelList(envId, modelName, token); res.json({ success: true, data }); } catch (err) { res.status(500).json({ success: false, error: err.message || "未知错误" }); } }); module.exports = router; ``` 3. 在主应用文件 `app.js` 中注册路由: ```js const usersRouter = require('./routes/users'); app.use('/api/users', usersRouter); ``` #### 4. 配置环境变量 在云托管服务中配置以下环境变量: | 环境变量 | 说明 | 示例值 | |---------|------|-------| | `ENV_ID` | 云开发环境 ID | `your-env-id` | | `USERNAME` | 已创建的用户名 | `admin` | | `PASSWORD` | 用户密码 | `your-password` | | `MODEL_NAME` | 数据模型标识 | `users` | #### 5. 部署和测试 1. 部署应用到云托管 2. 访问 `/api/users` 端点,如果配置正确,将返回数据模型中的用户列表 ### 数据模型 API 的优势 - **权限控制**:基于角色的访问控制 - **数据验证**:自动验证数据格式和类型 - **简化开发**:无需编写复杂的 SQL 查询 - **统一接口**:标准化的 RESTful API ## 最佳实践 ### 连接池管理 - 使用连接池而非单一连接,提高性能和可靠性 - 合理设置连接池大小,通常为 `容器实例数 × 5-10` - 确保正确释放连接,避免连接泄漏 ### 安全性 - 使用环境变量存储敏感信息,避免硬编码 - 为数据库用户设置最小权限 - 定期更新数据库密码 - 使用参数化查询防止 SQL 注入 ### 性能优化 - 为频繁查询的字段创建索引 - 优化查询语句,避免全表扫描 - 使用适当的数据类型和表结构 - 考虑使用读写分离提高性能 ### 错误处理 - 实现完善的错误处理和日志记录 - 设置连接超时和重试机制 - 监控数据库连接状态和性能指标 ## 常见问题排查 | 问题 | 可能原因 | 解决方案 | |------|---------|---------| | 连接超时 | 网络问题或数据库负载高 | 检查网络配置,增加连接超时时间 | | 连接数过多 | 连接未正确释放或连接池配置不当 | 确保释放连接,调整连接池大小 | | 认证失败 | 用户名或密码错误 | 检查环境变量配置是否正确 | | 查询性能差 | 缺少索引或查询未优化 | 添加适当的索引,优化查询语句 | --- ## 服务开发说明 # 服务开发说明 本文介绍开发云托管服务时需要了解的一些事项。 ## 编程语言支持 您可以使用任何语言、任何框架编写应用,甚至直接使用公共的容器镜像。 快速入门文档中提供了以多种主流语言编写的示例,但暂不在示例范围内的语言也均可支持。 ## 代码要求 ### 监听 HTTP 请求 服务必须监听 HTTP 请求,您可以自行配置发送请求的端口,并在部署服务时正确填写监听端口。在云托管的容器实例内部,`PORT` 环境变量的值始终反映请求发送到的端口。您的代码应检查是否存在此 `PORT` 环境变量,如果存在,则应侦听该变量以最大限度地提高可移植性。 ### 无状态服务 服务必须是无状态服务,不能依赖永久性本地状态。这是为了能够进行水平的自动扩缩容。 无状态服务(stateless service)指的是对单次请求的处理,不依赖其他请求。处理一次请求所需的全部信息必须都包含在这个请求里,或者可以从数据库、文件存储等外部获取,实例本身不存储任何信息。 有状态服务(stateful service)则相反,它会在自身保存一些数据,先后的请求是有关联的。 ### 避免后台活动 服务处理完请求后,对应的容器实例无法再访问 CPU。因此,代码中请不要在请求处理程序范围之外启动后台线程或进程,并确保在传送响应之前完成所有异步操作。强行运行后台线程可能会导致异常。 如果您怀疑服务中可能存在并不明显的后台活动,可以在日志查找在 HTTP 请求条目后记录的任何内容。 ## 代码容器化 基于容器部署服务,您需要提供一个容器镜像,或者提供代码由云托管在线构建镜像。容器镜像是一种封装格式,其中包含您的代码、代码软件包、所需的全部二进制依赖项、要使用的操作系统以及运行服务所需的其他任何内容。因此,镜像一旦构建完成,以上所有信息就都被固化,云托管不会感知镜像具体内容,容器实例运行过程中镜像内容也不会变化。 如您需要修改任何内容,则需要重新构建镜像。 通常,您可以使用名为 Dockerfile 的文件来声明如何构建镜像。快速入门文档中提供的示例,也包含多种主流语言的 Dockerfile 参考。 :::tip 提示 Dockerfile 背景知识:查看 [Dockerfile 官方文档](https://docs.docker.com/engine/reference/builder)了解语法,并查看[编写 Dockerfile 的最佳做法](https://docs.docker.com/develop/develop-images/dockerfile_best-practices/)中的提示了解如何将这些语法整合在一起。 ::: Dockerfile 通常从基础镜像(例如 `FROM golang:1.11`)开始。您可以在 [Docker Hub](https://hub.docker.com/) 上找到由操作系统和语言作者维护的基础镜像。 ### 谨慎使用依赖项 如果您使用具有依赖项库的动态语言,例如导入 Node.js 模块,那么在冷启动期间加载这些模块会增加延迟时间。 您可以通过以下方式缩短启动延迟时间: - 最大限度地减少依赖项的数量和大小,以构建精简服务。 - 惰性加载不常用的代码(如果您所用的语言支持此方式)。 - 使用代码加载优化技术。 ### 控制镜像大小 镜像较大会造成以下影响: - 增加安全漏洞; - 降低镜像的构建速度,增加构建时长,甚至引发构建超时; - 降低服务的部署速度。 :::tip 提示 镜像的大小不会影响请求处理时间,但过大的镜像会消耗更多构建时长,拉长的部署时间也会消耗更多 CPU 和内存资源,从而产生更多费用。 ::: 如何优化镜像请参阅:[优化容器镜像](/run/develop/image-optimization) --- ## 优化容器镜像 # 优化容器镜像 CloudBase 云托管支持托管任意镜像,但我们建议您**尽可能地优化您的镜像**,以获得更快的启动速度、更快的构建速度、更小的容器体积、更优的服务性能。 以下是一些推荐做法: ## 选择更小的基础镜像 同样一种语言的运行时容器,由于选择的基础容器不同,体积也会有很大的差异,**对于大多数业务,我们推荐您使用更小的基础镜像**。 以 Node.js 为例,[官方镜像仓库](https://hub.docker.com/_/node) 提供了以下不同体积的基础镜像: ``` REPOSITORY TAG IMAGE ID CREATED SIZE node 15 ca36fba5ad66 2 days ago 941MB node 15-slim 922b09b21278 2 days ago 165MB node 15-buster 36754275e286 2 days ago 910MB node 15-buster-slim eda2c7e487ff 2 days ago 179MB node 15-alpine 1e8b781248bb 2 days ago 115MB ``` 可以注意到 `15-slim`、`15-buster-slim`、`15-alpine` 的体积明显较小,这是由于它们使用了经过裁剪的底层操作系统镜像。使用这些裁剪、优化后的镜像通常不会影响您服务的运行。 ## 减少镜像层数 Dockerfile 中的每一行指令,都会生成一个层,镜像的层数会直接影响镜像的体积大小。 我们推荐您**将多个指令合并串联,以减少层的数量**。例如,您可以将以下的指令合并为同一个: ```docker RUN cd my-app RUN make RUN make install RUN rm -rf /tmp ``` 合并后: ```docker RUN cd my-app && \ make && \ make install && \ rm -rf /tmp ``` ## 充分利用层的缓存 Docker 会对镜像的每一层单独进行缓存,如果层的内容没有变化,那么会直接使用之前的缓存,以提高构建、上传镜像的速度。为了能尽量复用这一机制,我们推荐您**将镜像变动不大的层独立出来**。 例如,您的应用可能存在诸多依赖,通常来说,这些依赖在开发过程中变动较小,所以依赖的拷贝最好独立成为一层指令: ```docker COPY ./deps deps RUN make && make install ``` 以上的做法将 COPY 语句独立出来,每次构建、推送镜像时,只要依赖的文件内容没有变化,那么都可以复用之前的缓存,以提高构建、推送速度。 ## 清理不必要的文件 您可以使用 [.dockerignore](https://docs.docker.com/engine/reference/builder/#dockerignore-file) 在容器构建时忽略文件,以减少非必要文件的导入,同时也可以提高安全性,避免将一些本地敏感文件打包到镜像中。 ## 多阶段构建 以 Java 服务为例,实际运行的过程中只需要最后编译生成的 jar 文件即可,而构建期使用的依赖、扩展包以及源代码文件都是不必要的。 此时我们可以使用多阶段构建的方式,**分离构建环境和运行环境**,从而精简运行时容器的体积,例如以下的 Dockerfile: ```docker # 使用官方 maven/Java 8 镜像作为构建环境 # https://hub.docker.com/_/maven FROM maven:3.6-jdk-11 as builder # 将代码复制到容器内 WORKDIR /app COPY pom.xml . COPY src ./src # 构建项目 RUN mvn package -DskipTests # 使用 AdoptOpenJDK 作为基础镜像 # https://hub.docker.com/r/adoptopenjdk/openjdk8 # https://docs.docker.com/develop/develop-images/multistage-build/#use-multi-stage-builds FROM adoptopenjdk/openjdk11:alpine-slim # 将 jar 放入容器内 COPY --from=builder /app/target/helloworld-*.jar /helloworld.jar # 启动服务 CMD ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/helloworld.jar"] ``` --- ## Django # Django [Django](https://www.djangoproject.com/) 是一个功能强大的 Python Web 框架,遵循 "Batteries-included" 理念,提供开箱即用的全栈解决方案。它以高效开发和安全稳定著称,内置 ORM、Admin 后台、用户认证等模块,大幅减少重复代码。Django 采用清晰的 MVC(MTV)架构,支持高扩展性,适合从快速原型到企业级应用开发,其自动化的管理界面和详尽的文档进一步提升了开发效率。 本指南介绍如何通过多种方式在腾讯[云托管](https://tcb.cloud.tencent.com/dev#/platform-run)上部署[示例 Django 应用程序](https://github.com/TencentCloudBase/tcbr-templates/tree/main/cloudrun-django): ## 创建一个 Django 应用 Note: 如果你已经存在一个 Django 应用,你可以跳过该步骤。 要创建新的 Django 应用程序,请确保你的机器上安装了[Python](https://www.python.org/downloads/)和 Django。 按照以下步骤在目录中设置项目。 创建虚拟环境 ```sh python -m venv env ``` 激活虚拟环境 ```sh source env/bin/activate ``` 安装 Django ```sh python -m pip install django ``` 一切设置完成后,在终端运行以下命令来配置新的 Django 项目: ```sh django-admin startproject cloudrun-django ``` 此命令将创建一个名为`cloudrun-django`的新项目。 接下来,`cd` 进入目录并运行`python manage.py runserver`以启动项目。 打开浏览器并查看`http://127.0.0.1:8000`, 您将看到 Django 欢迎页面。 ### 配置依赖项 创建 `requirements.txt` 文件: 要跟踪部署的所有依赖项,请创建一个`requirements.txt`文件: ```sh pip freeze > requirements.txt ``` Note: 只有在虚拟环境中运行上述命令才是安全的,否则它将生成系统上所有安装的 python 包。可能导致云托管上无法启动该应用程序。 ## 配置 Dockerfile 在 Django 应用程序的跟目录中创建一个 `Dockerfile` 文件, 内容如下: ```dockerfile FROM alpine:3.21.3 # 容器默认时区为UTC,如需使用上海时间请启用以下时区设置命令 RUN apk add tzdata && cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo Asia/Shanghai > /etc/timezone # 选用国内镜像源以提高下载速度 RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.tencent.com/g' /etc/apk/repositories \ && apk add --update --no-cache python3 py3-pip gcc python3-dev linux-headers musl-dev \ && rm -rf /var/cache/apk/* # 使用 HTTPS 协议访问容器云调用证书安装 RUN apk add ca-certificates # 拷贝当前项目到/app目录下(.dockerignore中文件除外) COPY . /app # 设定当前的工作目录 WORKDIR /app # 安装依赖到指定的/install文件夹 # 选用国内镜像源以提高下载速度 RUN pip config set global.index-url http://mirrors.cloud.tencent.com/pypi/simple \ && pip config set global.trusted-host mirrors.cloud.tencent.com \ && pip install --upgrade pip --break-system-packages \ # pip install scipy 等数学包失败,可使用 apk add py3-scipy 进行, 参考安装 https://pkgs.alpinelinux.org/packages?name=py3-scipy&branch=v3.13 && pip install --user -r requirements.txt --break-system-packages # 执行启动命令 # 写多行独立的CMD命令是错误写法!只有最后一行CMD命令会被执行,之前的都会被忽略,导致业务报错。 # 请参考[Docker官方文档之CMD命令](https://docs.docker.com/engine/reference/builder/#cmd) CMD ["python3", "manage.py", "runserver","0.0.0.0:8080"] ``` 通过上面更改,你的 Django 程序将可以部署到腾讯云托管了! ## 部署到云托管 云托管提供了多种部署方式来部署你的应用: ### [控制台部署](https://tcb.cloud.tencent.com/dev#/platform-run/service/create?type=package) 打开[腾讯云托管](https://tcb.cloud.tencent.com/dev#/platform-run), 点击`通过本地代码部署` -> 填写服务名称 -> 部署方式选择`上传代码包` -> 代码包类型选择`文件夹` -> 选择 cloudrun-django 目录进行上传 -> 端口填写 8080 -> 点击创建并等待创建完成即可。 ### 通过 cli 部署 如果您已经安装了 [CloudBase CLI](/cli-v1/intro),可以在项目目录下使用以下命令将应用部署到 CloudBase 云托管: ``` tcb cloudrun deploy -p 8080 ``` 输入环境和服务名称后,CLI 会自动打包应用像并部署到云托管。 除了手动部署外,你也可以一键安装上述应用: ### 一键从模版部署 [![](https://main.qcloudimg.com/raw/67f5a389f1ac6f3b4d04c7256438e44f.svg)](https://tcb.cloud.tencent.com/dev#/platform-run/service/create?type=template&templateId=a6ec3048681b19c70291abb521d307bc) ### 一键从 github 部署 [![](https://main.qcloudimg.com/raw/67f5a389f1ac6f3b4d04c7256438e44f.svg)](https://tcb.cloud.tencent.com/dev#/platform-run/service/create?type=git&repoUrl=https://github.com/TencentCloudBase/tcbr-templates&repoBranch=main&serverName=example-django&port=8080&buildDir=cloudrun-django) --- ## Express # Express [Express](https://expressjs.com/) 是一个轻量级、灵活的 Node.js Web 框架,以其简单易用和高度可扩展著称。它提供了简洁的 API 设计,支持中间件机制,能快速构建 RESTful API 或全栈应用。Express 拥有丰富的插件生态(如 `body-parser`、`cors`),可轻松集成数据库、身份验证等功能,同时保持高性能和低学习成本,是 Node.js 开发者的首选框架之一。 本指南介绍如何通过多种方式在[腾讯云托管](https://tcb.cloud.tencent.com/dev#/platform-run)上部署[示例 Express 应用程序](https://github.com/TencentCloudBase/tcbr-templates/tree/main/cloudrun-express): ## 创建一个 Express App Note: 如果你已经有了一个 Express 应用,可以跳过这个步骤。 创建一个新的 Express 应用,首先需要保证在你记得机器上安装 Node.js 8.2.0 及以上版本。 创建一个目录 `cloudrun-express`, 然后 `cd` 进入该目录。 执行如下命令在 `cloudrun-express` 目录: ```sh npx express-generator --view=pug ``` `cloudrun-express` 将在目录中使用 pug 作为视图引擎创建一个新的 Express 应用程序。 ### 在本地运行 Express App 运行 `npm install` 安装所有依赖项。 接下来,通过运行以下命令启动应用程序: ```sh npm start ``` 启动浏览器并导航至 `http://localhost:3000` 以查看该应用程序。 ### 添加新路由 我们来增加一个`/apis/users`的路由其返回结果如下: ```json { "total": 2, "items": [ { "id": 0, "name": "zhangsan" }, { "id": 1, "name": "lisi" } ] } ``` 首先在`cloudrun-express/routes`目录下新增一个`users.js`文件,内容如下: ```js var express = require("express"); var router = express.Router(); /* GET users listing. */ router.get("", function (req, res, next) { const data = { total: 1, items: [ { id: 0, name: "zhangsan", }, { id: 1, name: "lisi", }, ], }; res.send(JSON.stringify(data)); }); module.exports = router; ``` 然后在`cloudrun-express`目录下 app.js 中新增: ```js var usersRouter = require("./routes/users"); app.use("/api/users", usersRouter); ``` 最后执行`npm start`启动服务,访问`http://localhost:3000/apis/users`即可返回相应结果。 ## 配置 Dockerfile 在`cloudrun-express`目录下创建一个名称为`Dockerfile`的新文件,内容如下: ```dockerfile FROM alpine:3.13 RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.tencent.com/g' /etc/apk/repositories \ && apk add --update --no-cache nodejs npm # 容器默认时区为UTC,如需使用上海时间请启用以下时区设置命令 RUN apk add tzdata && cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo Asia/Shanghai > /etc/timezone # 使用 HTTPS 协议访问容器云调用证书安装 RUN apk add ca-certificates # # 指定工作目录 WORKDIR /app # 拷贝包管理文件 COPY package*.json /app/ # npm 源,选用国内镜像源以提高下载速度 RUN npm config set registry https://mirrors.cloud.tencent.com/npm/ # RUN npm config set registry https://registry.npm.taobao.org/ # npm 安装依赖 RUN npm install # 将当前目录(dockerfile所在目录)下所有文件都拷贝到工作目录下(.dockerignore中文件除外) COPY . /app # 执行启动命令 # 写多行独立的CMD命令是错误写法!只有最后一行CMD命令会被执行,之前的都会被忽略,导致业务报错。 # 请参考[Docker官方文档之CMD命令](https://docs.docker.com/engine/reference/builder/#cmd) CMD ["npm", "start"] ``` 通过上面更改,你的 express 程序将可以部署到腾讯云托管了! ## 部署到云托管 云托管提供了多种部署方式来部署你的应用: ### [控制台部署](https://tcb.cloud.tencent.com/dev#/platform-run/service/create?type=package) 打开[腾讯云托管](https://tcb.cloud.tencent.com/dev#/platform-run), 点击`通过本地代码部署` -> 填写服务名称 -> 部署方式选择`上传代码包` -> 代码包类型选择`文件夹` -> 选择 cloudrun-express 目录进行上传 -> 端口填写 3000 -> 点击创建并等待创建完成即可。 ### 通过 cli 部署 如果您已经安装了 [CloudBase CLI](/cli-v1/intro),可以在项目目录下使用以下命令将应用部署到 CloudBase 云托管: ``` tcb cloudrun deploy -p 3000 ``` 输入环境和服务名称后,CLI 会自动打包应用像并部署到云托管。 除了手动部署外,你也可以一键安装上述应用: ### 一键从模版部署 [![](https://main.qcloudimg.com/raw/67f5a389f1ac6f3b4d04c7256438e44f.svg)](https://tcb.cloud.tencent.com/dev#/platform-run/service/create?type=template&templateId=6a580dc9681b1afa028e99e2458fce1d) ### 一键从 github 部署 [![](https://main.qcloudimg.com/raw/67f5a389f1ac6f3b4d04c7256438e44f.svg)](https://tcb.cloud.tencent.com/dev#/platform-run/service/create?type=git&repoUrl=https://github.com/TencentCloudBase/tcbr-templates&repoBranch=main&serverName=example-express&port=3000&buildDir=cloudrun-express) --- ## FastAPI # FastAPI [FastAPI](https://fastapi.tiangolo.com/) 是一个用于构建 API 的现代、快速(高性能)的 web 框架,使用 Python 并基于标准的 Python 类型提示。具有以下特性: - 快速:可与 NodeJS 和 Go 并肩的极高性能(归功于 Starlette 和 Pydantic)。最快的 Python web 框架之一。 - 高效编码:提高功能开发速度约 200% 至 300%。 - 更少 bug:减少约 40% 的人为(开发者)导致错误。 - 智能:极佳的编辑器支持。处处皆可自动补全,减少调试时间。 - 简单:设计的易于使用和学习,阅读文档的时间更短。 本文档介绍使用多种方式在云托管(容器型)部署[示例 FastAPI 应用](ttps://github.com/TencentCloudBase/tcbr-templates/tree/main/cloudrun-fastapi): ## 创建一个 FastAPI 项目 NOTE: 如果已经存在 FastAPI 项目,可以跳过该阶段。 1. 新建一个 fastapi-app 目录 2. 在 fastapi-app 目录中,新建一个 app.py 文件,内容如下: ```python from fastapi import FastAPI app = FastAPI() @app.get("/") async def root(): return {"greeting": "Hello, World!", "message": "Welcome to FastAPI!"} ``` 这个 app.py 文件定义了一个 FastAPI 应用,它包含一个根路径("/")和一个 GET 请求处理函数(root)。当用户访问根路径时,应用会返回一个包含问候语和欢迎信息的 JSON 响应。 3. 在 fastapi-app 目录中,新建一个 requirements.txt 文件,内容如下: ``` fastapi==0.100.0 hypercorn==0.14.4 ``` 这个 requirements.txt 文件定义了 FastAPI 应用所需的依赖项。其中 [hypercorn](https://github.com/pgjones/hypercorn) 是 FastAPI 运行时需要的 ASGI 服务器。 4. 安装依赖启动服务 使用 pip 安装依赖: ```bash pip install -r requirements.txt ``` 推荐使用虚拟环境安装依赖: ```bash python -m venv venv source venv/bin/activate pip install -r requirements.txt ``` 安装完成后,使用 hypercorn 启动服务: ```bash hypercorn main:app --bind 0.0.0.0:80 ``` 访问`http://127.0.0.1:80`即可返回相应结果。 在开发阶段,还可以使用 `fastapi-cli` 启动服务: 首先安装 fastapi-cli: ```bash pip install fastapi-cli ``` 然后启动服务: ```bash fastapi dev main.py ``` ## 配置 Dockerfile 在 fastapi-app 目录中,新建一个 Dockerfile 文件,内容如下: ```dockerfile FROM python:3-alpine # 设定当前的工作目录 WORKDIR /app # 拷贝当前项目到容器中 COPY . . # 安装依赖 RUN pip install --no-cache-dir -r requirements.txt # 启动服务 CMD ["hypercorn", "main:app", "--bind", "0.0.0.0:80"] ``` 通过上面更改,你的 express 程序将可以部署到腾讯云托管了! ## 部署到云托管 云托管提供了多种部署方式来部署你的应用: ### [控制台部署](https://tcb.cloud.tencent.com/dev#/platform-run/service/create?type=package) 打开[腾讯云托管](https://tcb.cloud.tencent.com/dev#/platform-run), 点击`通过本地代码部署` -> 填写服务名称 -> 部署方式选择`上传代码包` -> 代码包类型选择`文件夹` -> 选择 cloudrun-fastapi 目录进行上传 -> 端口填写 80 -> 点击创建并等待创建完成即可。 ### 通过 cli 部署 如果您已经安装了 [CloudBase CLI](/cli-v1/intro),可以在项目目录下使用以下命令将应用部署到 CloudBase 云托管: ``` tcb cloudrun deploy ``` 输入环境和服务名称后,CLI 会自动打包应用像并部署到云托管。 除了手动部署外,你也可以一键安装上述应用: ### 一键从模版部署 [![](https://main.qcloudimg.com/raw/67f5a389f1ac6f3b4d04c7256438e44f.svg)](https://tcb.cloud.tencent.com/dev#/platform-run/service/create?type=template&templateId=82bba809682f142500d7a00f116bd852) ### 一键从 github 部署 [![](https://main.qcloudimg.com/raw/67f5a389f1ac6f3b4d04c7256438e44f.svg)](https://tcb.cloud.tencent.com/dev#/platform-run/service/create?type=git&repoUrl=https://github.com/TencentCloudBase/tcbr-templates&repoBranch=main&serverName=example-fastapi&port=80&buildDir=cloudrun-fastapi) --- ## Flask # Flask [Flask](https://flask.palletsprojects.com/en/stable/) Flask 是一个轻量级、灵活的 Python Web 框架,以简洁和可扩展性为核心设计理念。它不强制依赖特定库或架构,仅提供核心功能(如路由、模板渲染),开发者可自由选配数据库、表单验证等组件(如 SQLAlchemy、WTForms)。这种“微框架”特性使其学习成本极低,同时能通过扩展轻松构建复杂应用,特别适合快速开发小型项目或作为微服务基础。 本指南介绍如何通过多种方式在腾讯[云托管](https://tcb.cloud.tencent.com/dev#/platform-run)上部署 [Flask 应用程序](https://github.com/TencentCloudBase/tcbr-templates/tree/main/cloudrun-flask): ## 创建一个 Flask 应用 Note: 如果你已经有 Flask 应用程序,则可以跳过该步骤。 要创建新的 Flask 应用程序,需要机器上安装[Python](https://www.python.org/downloads/)和 Flask。 按照以下步骤在目录中设置项目。 创建一个`cloudrun-flask`目录, `cd`进入该目录。 创建虚拟环境 ```sh python -m venv env ``` 激活虚拟环境 ```sh source env/bin/activate ``` 安装 Flask ```sh python -m pip install flask ``` 在`cloudrun-flask`目录中创建一个新文件 `manage.py`, 内容如下: ```py import os from flask import Flask app = Flask(__name__) @app.route('/') def hello(): return 'Hello world!' ``` 1、`from flask import Flask` - 此行从 Flask 框架导入 Flask 类,用于创建和管理 Web 应用程序。 2、`app = Flask(__name__)` - 此行创建 Flask 类的实例并将其分配给 app 变量。 - 该**name**参数帮助 Flask 识别应用程序的位置。它对于确定资源路径和错误报告很有用。 3、`@app.route('/')` - 该`@app.route('/')`装饰器为应用设置了 URL 路由。当(/)访问根 URL 时,Flask 将执行紧接着该装饰器下方的函数。 4、`def hello()` - 该 hello 函数返回一条纯文本消息“Hello world!”,当访问应用程序的根 URL 时,该消息将显示在浏览器中。 在`cloudrun-flask`目录下执行`python3 manage.py runserver 0.0.0.0:8080` 启动服务, 打开浏览器并查看`http://127.0.0.1:8080`查看返回结果。 ### 配置依赖项 创建 `requirements.txt` 文件: 要跟踪部署的所有依赖项,请创建一个`requirements.txt`文件: ```sh pip freeze > requirements.txt ``` Note: 只有在虚拟环境中运行上述命令才是安全的,否则它将生成系统上所有安装的 python 包。可能导致云托管上无法启动该应用程序。 通过上面更改,你的 Flask 程序将可以部署到腾讯云托管了! ## 配置 Dockerfile 在`cloudrun-flask`目录中创建一个 `Dockerfile` 文件,内容如下: ```dockerfile FROM alpine # 容器默认时区为UTC,如需使用上海时间请启用以下时区设置命令 RUN apk add tzdata && cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo Asia/Shanghai > /etc/timezone # 选用国内镜像源以提高下载速度 RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.tencent.com/g' /etc/apk/repositories \ && apk add --update --no-cache python3 py3-pip gcc python3-dev linux-headers musl-dev \ && rm -rf /var/cache/apk/* # 使用 HTTPS 协议访问容器云调用证书安装 RUN apk add ca-certificates # 拷贝当前项目到/app目录下(.dockerignore中文件除外) COPY . /app # 设定当前的工作目录 WORKDIR /app # 安装依赖到指定的/install文件夹 # 选用国内镜像源以提高下载速度 RUN pip config set global.index-url http://mirrors.cloud.tencent.com/pypi/simple \ && pip config set global.trusted-host mirrors.cloud.tencent.com \ && pip install --upgrade pip --break-system-packages \ # pip install scipy 等数学包失败,可使用 apk add py3-scipy 进行, 参考安装 https://pkgs.alpinelinux.org/packages?name=py3-scipy&branch=v3.13 && pip install --user -r requirements.txt --break-system-packages # 执行启动命令 # 写多行独立的CMD命令是错误写法!只有最后一行CMD命令会被执行,之前的都会被忽略,导致业务报错。 # 请参考[Docker官方文档之CMD命令](https://docs.docker.com/engine/reference/builder/#cmd) CMD ["python3", "manage.py", "runserver","0.0.0.0:8080"] ``` 通过上面更改,你的 flask 程序将可以部署到腾讯云托管了! ## 部署到云托管 云托管提供了多种部署方式来部署你的应用: ### [控制台部署](https://tcb.cloud.tencent.com/dev#/platform-run/service/create?type=package) 打开[腾讯云托管](https://tcb.cloud.tencent.com/dev#/platform-run), 点击`通过本地代码部署` -> 填写服务名称 -> 部署方式选择`上传代码包` -> 代码包类型选择`文件夹` -> 选择 cloudrun-flask 目录进行上传 -> 端口填写 8080 -> 点击创建并等待创建完成即可。 ### 通过 cli 部署 如果您已经安装了 [CloudBase CLI](/cli-v1/intro),可以在项目目录下使用以下命令将应用部署到 CloudBase 云托管: ``` tcb cloudrun deploy -p 8080 ``` 输入环境和服务名称后,CLI 会自动打包应用像并部署到云托管。 除了手动部署外,你也可以一键安装上述应用: ### 一键从模版部署 [![](https://main.qcloudimg.com/raw/67f5a389f1ac6f3b4d04c7256438e44f.svg)](https://tcb.cloud.tencent.com/dev#/platform-run/service/create?type=template&templateId=6a580dc9681b1a2c028e8ce5429f939d) ### 一键从 github 部署 [![](https://main.qcloudimg.com/raw/67f5a389f1ac6f3b4d04c7256438e44f.svg)](https://tcb.cloud.tencent.com/dev#/platform-run/service/create?type=git&repoUrl=https://github.com/TencentCloudBase/tcbr-templates&repoBranch=main&serverName=example-flask&port=8080&buildDir=cloudrun-flask) --- ## Gin # Gin [Gin](https://gin-gonic.com/) 是一个高性能的 Go Web 框架,以其简洁、高效和易用性著称。它基于`httprouter`实现快速路由匹配,支持中间件机制,能轻松构建 RESTful API 或微服务。 本指南介绍如何通过多种方式在腾讯[云托管](https://tcb.cloud.tencent.com/dev#/platform-run)上部署 [Gin 应用程序](https://github.com/TencentCloudBase/tcbr-templates/tree/main/cloudrun-flask): ## 创建一个 Gin 应用 Note: 如果你已经有了一个 Gin 应用,且确保 Dockerfile 文件和 main.go 文件都在根目录下,可以跳过这个步骤。 创建一个新的 Gin 应用,首先需要确保机器上安装 Go 服务程序。 创建一个目录``cloudrun-gin`, 然后`cd`进入该目录。 执行如下命令在`cloudrun-gin`目录: ```sh go mod init cloudrun-gin go get -u github.com/gin-gonic/gin ``` 在`cloudrun-gin`目录下创建 main.go 文件,内容如下: ```go func main() { router := gin.Default() router.GET("/json", func(c *gin.Context) { data := map[string]interface{}{ "id": 0, "name": "zhangsan", } c.JSON(http.StatusOK, data) }) // 监听并在 0.0.0.0:8080 上启动服务 router.Run(":8080") } ``` 执行 `go run main.go` 启动服务,访问`http://localhost:8080/json`可查看访问结果 ## 配置 Dockerfile 1、在`cloudrun-gin`目录下创建一个`Dockerfile` 文件,内容如下(根据真实情况修改 FROM 行 golang 版本): ```dockerfile FROM golang:1.22.3-alpine as builder # 指定构建过程中的工作目录 WORKDIR /app # 将当前目录(dockerfile所在目录)下所有文件都拷贝到工作目录下(.dockerignore中文件除外) COPY . /app/ # 执行代码编译命令。操作系统参数为linux,编译后的二进制产物命名为main,并存放在当前目录下。 RUN GOOS=linux go build -o main . # 选用运行时所用基础镜像(GO语言选择原则:尽量体积小、包含基础linux内容的基础镜像) FROM alpine:latest # 容器默认时区为UTC,我们使用以下时区设置命令启用上海时区 # RUN apk add tzdata && cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo Asia/Shanghai > /etc/timezone # 使用 HTTPS 协议访问容器云调用证书安装 RUN apk add ca-certificates # 指定运行时的工作目录 WORKDIR /app # 将构建产物/app/main拷贝到运行时的工作目录中 COPY --from=builder /app/main /app/ # 执行启动命令 # 写多行独立的CMD命令是错误写法!只有最后一行CMD命令会被执行,之前的都会被忽略,导致业务报错。 # 请参考[Docker官方文档之CMD命令](https://docs.docker.com/engine/reference/builder/#cmd) CMD ["/app/main"] ``` 通过上面更改,你的 gin 程序将可以部署到腾讯云托管了! ## 部署到云托管 云托管提供了多种部署方式来部署你的应用: ### [控制台部署](https://tcb.cloud.tencent.com/dev#/platform-run/service/create?type=package) 打开[腾讯云托管](https://tcb.cloud.tencent.com/dev#/platform-run), 点击`通过本地代码部署` -> 填写服务名称 -> 部署方式选择`上传代码包` -> 代码包类型选择`文件夹` -> 选择 cloudrun-gin 目录进行上传 -> 端口填写 8080 -> 点击创建并等待创建完成即可。 ### 通过 cli 部署 如果您已经安装了 [CloudBase CLI](/cli-v1/intro),可以在项目目录下使用以下命令将应用部署到 CloudBase 云托管: ``` tcb cloudrun deploy -p 8080 ``` 输入环境和服务名称后,CLI 会自动打包应用像并部署到云托管。 除了手动部署外,你也可以一键安装上述应用: ### 一键从模版部署 [![](https://main.qcloudimg.com/raw/67f5a389f1ac6f3b4d04c7256438e44f.svg)](https://tcb.cloud.tencent.com/dev#/platform-run/service/create?type=template&templateId=6a580dc9681b0da3028d8b8710becbaf) ### 一键从 github 部署 [![](https://main.qcloudimg.com/raw/67f5a389f1ac6f3b4d04c7256438e44f.svg)](https://tcb.cloud.tencent.com/dev#/platform-run/service/create?type=git&repoUrl=https://github.com/TencentCloudBase/tcbr-templates&repoBranch=main&serverName=example-gin&port=8080&buildDir=cloudrun-gin) --- ## 总览 # 总览 ### JavaScript/TypeScript - [Express](./express) - [Nest.js](./nest) - [Next.js](./next) ### Python - [Django](./django) - [Flask](./flask) - [FastAPI](./fastapi) ### Go - [Gin](./gin) ### Java - [Spring Boot](./springboot) ### PHP - [Laravel](./laravel) --- ## Laravel # Laravel Laravel 是一个 Web 应用框架, 有着表现力强、语法优雅的特点。Laravel 致力于提供出色的开发体验,同时提供强大的特性,例如完全的依赖注入,富有表现力的数据库抽象层,队列和计划任务,单元和集成测试等等。 本指南介绍如何通过多种方式在腾讯[云托管](https://tcb.cloud.tencent.com/dev#/platform-run)上部署 [Laravel 应用程序](https://github.com/TencentCloudBase/tcbr-templates/tree/main/cloudrun-laravel): ## 创建一个 Laravel 应用 Note: 如果你已经有一个 Laravel 应用,且确保 Dockerfile 文件在根目录下,可跳过这个步骤。 创建一个 Laravel 应用,请确保本地已安装 PHP 和 [Composer](https://getcomposer.org/)。 安装好 PHP 和 Composer 后,可以通过 Composer 的 `create-project` 命令创建一个新的 Laravel 项目: ``` composer create-project laravel/laravel cloudrun-laravel ``` ### 启动 php 服务 执行 `php-fpm` 启动 php cgi 服务, 服务访问地址为 `127.0.0.1:9000`。 ### 配置 Nginx `default.conf` ``` server { listen 80; index index.php index.html; server_name localhost; root /var/www/html/public; location / { try_files $uri $uri/ /index.php?$query_string; } location ~ \.php$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; } location ~ /\.ht { deny all; } } ``` 将 default.conf 放到 nginc `conf.d` 目录下,执行 `nginx -s reload`, 启动 nginx 服务,即可通过 `http://127.0.0.1` 访问 php 服务。 ### 从 Dockerfile 部署 1、在 `cloudrun-laravel` 项目下创建 nginx 目录,在 nginx 目录下分别添加 `default.conf` 和 `supervisord.conf` 文件,内容如下: #### default.conf ``` server { listen 80; index index.php index.html; server_name localhost; root /var/www/html/public; location / { try_files $uri $uri/ /index.php?$query_string; } location ~ \.php$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; } location ~ /\.ht { deny all; } } ``` #### supervisord.conf ``` [supervisord] nodaemon=true [program:php-fpm] command=/usr/local/sbin/php-fpm [program:nginx] command=/usr/sbin/nginx -g "daemon off;" ``` 2、在 `cloudrun-laravel` 项目下创建 Dockerfile, 内容如下: ```dockerfile # 1. 构建阶段,安装依赖,composer install FROM php:8.2-fpm-alpine AS build # 安装系统依赖和 PHP 扩展 RUN apk add --no-cache \ bash \ git \ unzip \ libzip-dev \ oniguruma-dev \ curl \ && docker-php-ext-install pdo_mysql mbstring zip bcmath # 安装 composer COPY --from=composer:2 /usr/bin/composer /usr/bin/composer WORKDIR /var/www/html # 复制项目代码 COPY . . RUN composer install --no-dev --optimize-autoloader --no-interaction # 生成优化的自动加载文件 RUN composer dump-autoload -o # 2. 运行阶段,PHP-FPM 镜像 FROM php:8.2-fpm-alpine # 安装 PHP 扩展 RUN apk add --no-cache libzip oniguruma-dev libpng libjpeg-turbo libwebp freetype \ && apk add --no-cache --virtual .build-deps $PHPIZE_DEPS libzip-dev oniguruma-dev \ && docker-php-ext-configure zip \ && docker-php-ext-install pdo_mysql mbstring zip bcmath gd \ && apk del .build-deps WORKDIR /var/www/html # 复制 build 阶段的代码和依赖 COPY --from=build /var/www/html /var/www/html # 设置权限(根据需要调整) RUN chown -R www-data:www-data /var/www/html/storage /var/www/html/bootstrap/cache # 3. 安装并配置 supervisord 以同时启动 php-fpm 和 nginx RUN apk add --no-cache supervisor nginx # 复制 nginx 配置 COPY nginx/default.conf /etc/nginx/conf.d/default.conf # 复制 supervisord 配置 COPY nginx/supervisord.conf /etc/supervisord.conf # 暴露端口 EXPOSE 80 # 启动 supervisord,管理 php-fpm 和 nginx CMD ["/usr/bin/supervisord", "-c", "/etc/supervisord.conf"] ``` 通过上面更改,你的 laravel 程序将可以部署到腾讯云托管了! ## 部署到云托管 云托管提供了多种部署方式来部署你的应用: ### [控制台部署](https://tcb.cloud.tencent.com/dev#/platform-run/service/create?type=package) 打开[腾讯云托管](https://tcb.cloud.tencent.com/dev#/platform-run), 点击`通过本地代码部署` -> 填写服务名称 -> 部署方式选择`上传代码包` -> 代码包类型选择`文件夹` -> 选择 cloudrun-laravel 目录进行上传 -> 端口填写 8080 -> 点击创建并等待创建完成即可。 ### 通过 cli 部署 如果您已经安装了 [CloudBase CLI](/cli-v1/intro),可以在项目目录下使用以下命令将应用部署到 CloudBase 云托管: ``` tcb cloudrun deploy ``` 输入环境和服务名称后,CLI 会自动打包应用像并部署到云托管。 除了手动部署外,你也可以一键安装上述应用: ### 一键从 github 部署 [![](https://main.qcloudimg.com/raw/67f5a389f1ac6f3b4d04c7256438e44f.svg)](https://tcb.cloud.tencent.com/dev#/platform-run/service/create?type=git&repoUrl=https://github.com/TencentCloudBase/tcbr-templates&repoBranch=main&serverName=example-laravel&port=80&buildDir=cloudrun-laravel) --- ## Nest # Nest [Nest](https://nestjs.com/) 是一个基于 TypeScript/Node.js 的企业级后端框架,采用模块化设计,融合了 OOP(面向对象)、FP(函数式)和微服务架构。它底层支持 Express/Fastify,提供依赖注入、装饰器路由、GraphQL 集成等特性,适合构建高效、可维护的服务器端应用,尤其契合全栈 TypeScript 开发。 本指南介绍如何通过多种方式在腾讯[云托管](https://tcb.cloud.tencent.com/dev#/platform-run)上部署[示例 Nest 应用程序](https://github.com/TencentCloudBase/tcbr-templates/tree/main/cloudrun-nestjs): ## 创建 Nest 应用 Note: 如果你在本地已经有 Nest 应用,客户忽略该步骤。 要创建 Nest 应用程序,你确保机器上安装 Node 和 NestJS。 在终端中运行以下命令来创建新的 Nest 应用: ```sh nest new cloudrun-nest ``` 目录中将为你创建一个新的 Nest 应用`Nest`。 ### 在本地运行 Nest 应用 通过运行以下命令在本地启动应用程序: ```sh npm run start ``` 启动浏览器访问`http://localhost:3000`查看返回结果。 ## 配置 Dockerfile 在 Nest 应用程序的跟目录中创建一个 `Dockerfile` 文件, 内容如下: ```dockerfile FROM alpine:latest # 安装依赖包,如需其他依赖包,请到alpine依赖包管理(https://pkgs.alpinelinux.org/packages?name=php8*imagick*&branch=v3.13)查找。 # 选用国内镜像源以提高下载速度 RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.tencent.com/g' /etc/apk/repositories \ && apk add --update --no-cache nodejs npm # 容器默认时区为UTC,如需使用上海时间请启用以下时区设置命令 RUN apk add tzdata && cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo Asia/Shanghai > /etc/timezone # 使用 HTTPS 协议访问容器云调用证书安装 RUN apk add ca-certificates # # 指定工作目录 WORKDIR /app # 拷贝包管理文件 COPY package*.json /app/ # npm 源,选用国内镜像源以提高下载速度 RUN npm config set registry https://mirrors.cloud.tencent.com/npm/ # RUN npm config set registry https://registry.npm.taobao.org/ # npm 安装依赖 RUN npm install # 将当前目录(dockerfile所在目录)下所有文件都拷贝到工作目录下(.dockerignore中文件除外) COPY . /app # 执行启动命令 # 写多行独立的CMD命令是错误写法!只有最后一行CMD命令会被执行,之前的都会被忽略,导致业务报错。 # 请参考[Docker官方文档之CMD命令](https://docs.docker.com/engine/reference/builder/#cmd) CMD ["npm", "start"] ``` 通过上面更改,你的 nestjs 程序将可以部署到腾讯云托管了! ## 部署到云托管 云托管提供了多种部署方式来部署你的应用: ### [控制台部署](https://tcb.cloud.tencent.com/dev#/platform-run/service/create?type=package) 打开[腾讯云托管](https://tcb.cloud.tencent.com/dev#/platform-run), 点击`通过本地代码部署` -> 填写服务名称 -> 部署方式选择`上传代码包` -> 代码包类型选择`文件夹` -> 选择 cloudrun-nest 目录进行上传 -> 端口填写 3000 -> 点击创建并等待创建完成即可。 ### 通过 cli 部署 如果您已经安装了 [CloudBase CLI](/cli-v1/intro),可以在项目目录下使用以下命令将应用部署到 CloudBase 云托管: ``` tcb cloudrun deploy -p 3000 ``` 输入环境和服务名称后,CLI 会自动打包应用像并部署到云托管。 除了手动部署外,你也可以一键安装上述应用: ### 一键从模版部署 [![](https://main.qcloudimg.com/raw/67f5a389f1ac6f3b4d04c7256438e44f.svg)](https://tcb.cloud.tencent.com/dev#/platform-run/service/create?type=template&templateId=dcffa824681b1b3c0293ad2261cd674a) ### 一键从 github 部署 [![](https://main.qcloudimg.com/raw/67f5a389f1ac6f3b4d04c7256438e44f.svg)](https://tcb.cloud.tencent.com/dev#/platform-run/service/create?type=git&repoUrl=https://github.com/TencentCloudBase/tcbr-templates&repoBranch=main&serverName=example-nestjs&port=3000&buildDir=cloudrun-nestjs) --- ## Next # Next [Next.js](https://nextjs.org/) 是一个基于 React 的现代前端开发框架,由 Vercel 团队开发和维护,提供了开箱即用的功能,如服务器端渲染(SSR)、静态站点生成(SSG)、路由、API 路由等,帮助开发者快速构建高性能的 Web 应用。 本指南介绍如何通过多种方式在[腾讯云托管](https://tcb.cloud.tencent.com/dev#/platform-run)上部署[示例 Next.js 应用程序](https://github.com/TencentCloudBase/tcbr-templates/tree/main/cloudrun-nextjs): ## 创建 Next.js Note: 如果已有 Next.js 应用,可以跳过此步骤。 创建 Next.js 应用,需要安装 Node.js 18.18 及以上版本。 在 Terminal 运行如下命令,使用官方 cli 创建 Next.js 应用。 > 建议在常用的文件夹中运行命令,以避免创建完成后找不到项目文件夹 ```sh npx create-next-app@latest ``` ## 本地运行 Next.js 使用 VS Code 等 IDE 打开 cli 创建的项目,运行 `npm install` 安装所有依赖项。 运行以下命令启动应用程序: ```sh npm run dev ``` 启动浏览器并导航至 `http://localhost:3000` 以查看该应用程序。 ## 配置 Dockerfile 使用云托管部署项目需要添加 docker 配置文件。 在项目根目录下创建一个名称为 `Dockerfile` 的新文件,内容如下: ```dockerfile # 使用 Node.js 镜像作为构建环境 FROM node:22-alpine AS builder # 设置工作目录 WORKDIR /app # 复制包管理文件以利用 Docker 缓存层 COPY package.json package-lock.json* ./ # 安装依赖(包括 devDependencies,因为需要构建) RUN npm install # 复制项目文件 COPY . . # 构建应用 RUN npm run build # 使用更小的基础镜像来运行应用 FROM node:22-alpine AS runner # 设置工作目录 WORKDIR /app # 从构建阶段复制构建输出和依赖,减小镜像体积 COPY --from=builder /app/.next ./.next COPY --from=builder /app/node_modules ./node_modules COPY --from=builder /app/package.json ./package.json COPY --from=builder /app/public ./public # 环境变量 ENV NODE_ENV=production # 使用非 root 用户端口 EXPOSE 3000 # 启动命令 CMD ["npm", "start"] ``` 通过上述更改,你的 Next.js 程序即可部署到腾讯云托管了! ## 部署到云托管 云托管提供了多种部署方式来部署你的应用: ### [控制台部署](https://tcb.cloud.tencent.com/dev#/platform-run/service/create?type=package) 打开[腾讯云托管](https://tcb.cloud.tencent.com/dev#/platform-run), 点击 `通过本地代码部署` -> 填写服务名称 -> 部署方式选择 `上传代码包` -> 代码包类型选择 `文件夹` -> 选择项目目录进行上传 -> 端口填写 3000 -> 点击创建并等待创建完成即可。 ### 通过 cli 部署 如果您已经安装了 [CloudBase CLI](/cli-v1/intro),可以在项目目录下使用以下命令将应用部署到 CloudBase 云托管: ``` tcb cloudrun deploy -p 3000 ``` 输入环境和服务名称后,CLI 会自动打包应用并部署到云托管。 除了手动部署外,你也可以一键安装上述应用: ### 一键从模版部署 [![](https://main.qcloudimg.com/raw/67f5a389f1ac6f3b4d04c7256438e44f.svg)](https://tcb.cloud.tencent.com/dev#/platform-run/service/create?type=template&templateId=6c670e5d6870c72e0507fcb560b1ec48) ### 一键从 GitHub 部署 [![](https://main.qcloudimg.com/raw/67f5a389f1ac6f3b4d04c7256438e44f.svg)](https://tcb.cloud.tencent.com/dev#/platform-run/service/create?type=git&repoUrl=https://github.com/TencentCloudBase/tcbr-templates&repoBranch=main&serverName=example-nextjs&port=3000&buildDir=cloudrun-nextjs) --- ## Spring Boot # Spring Boot [Spring Boot](https://spring.io/projects/spring-boot) 是一个开箱即用的 Java 框架,基于 Spring 生态,简化企业级应用开发。它内置 Web 服务器、自动配置和起步依赖(Starter),无需复杂 XML 配置即可快速构建独立、可部署的微服务或单体应用,大幅提升开发效率,适合现代云原生和分布式系统。 本指南介绍如何通过多种方式在腾讯[云托管](https://tcb.cloud.tencent.com/dev#/platform-run)上部署 [Spring Boot 应用程序](https://github.com/TencentCloudBase/tcbr-templates/tree/main/cloudrun-nestjs): ## 创建 Spring Boot 应用 Note: 如果本次已经有 Spring Boot 应用程序则可以跳过该步骤。 要创建 Spring Boot 应用程序,请确保你的机器上安装了[JDK](https://www.oracle.com/java/technologies/downloads/)。 前往[start.spring.io](https://start.spring.io/)初始化新的 Spring Boot 应用。选择以下选项来自定并生成你的应用。 - Project: Maven - 语言: Java - Spring Boot: 3.3.4 - 项目元数据: - Group: com.tencent - Artifact: cloudrun - Name: cloudrun - Description: Demo project for Spring Boot - Package name: com.tencent.cloudrun - Packaging: Jar - Java: 17 - 依赖项: - 点击"添加依赖项"按钮并搜索 Spring Boot。选择它。 单击"CREATE"按钮,下载压缩文件并解压到你机器的文件夹中。 ## 配置 Dockerfile 在 Spring Boot 应用程序的跟目录中创建一个 `Dockerfile` 文件, 文件内容如下: Note: maven 版本和 jre 版本需要根据实际情况进行修改。`cloudrun-1.0-SNAPSHOT.jar`名称根据实际情况修改。根目录下需要`settings.xml`文件 ```dockerfile FROM maven:3.6.0-jdk-17-slim as build # 指定构建过程中的工作目录 WORKDIR /app # 将src目录下所有文件,拷贝到工作目录中src目录下(.gitignore/.dockerignore中文件除外) COPY src /app/src # 将pom.xml文件,拷贝到工作目录下 COPY settings.xml pom.xml /app/ # 执行代码编译命令 # 自定义settings.xml, 选用国内镜像源以提高下载速度 RUN mvn -s /app/settings.xml -f /app/pom.xml clean package # 选择运行时基础镜像 FROM alpine:3.13 # 安装依赖包,如需其他依赖包,请到alpine依赖包管理(https://pkgs.alpinelinux.org/packages?name=php8*imagick*&branch=v3.13)查找。 # 选用国内镜像源以提高下载速度 RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.tencent.com/g' /etc/apk/repositories \ && apk add --update --no-cache openjdk17-jre-base \ && rm -f /var/cache/apk/* # 容器默认时区为UTC,如需使用上海时间请启用以下时区设置命令 # RUN apk add tzdata && cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo Asia/Shanghai > /etc/timezone # 使用 HTTPS 协议访问容器云调用证书安装 RUN apk add ca-certificates # 指定运行时的工作目录 WORKDIR /app # 将构建产物jar包拷贝到运行时目录中 COPY --from=build /app/target/*.jar . # 暴露端口 # 此处端口必须与「服务设置」-「流水线」以及「手动上传代码包」部署时填写的端口一致,否则会部署失败。 EXPOSE 80 # 执行启动命令. # 写多行独立的CMD命令是错误写法!只有最后一行CMD命令会被执行,之前的都会被忽略,导致业务报错。 # 请参考[Docker官方文档之CMD命令](https://docs.docker.com/engine/reference/builder/#cmd) CMD ["java", "-jar", "/app/cloudrun-1.0-SNAPSHOT.jar"] ``` 通过上面更改,你的 springboot 程序将可以部署到腾讯云托管了! ## 部署到云托管 云托管提供了多种部署方式来部署你的应用: ### [控制台部署](https://tcb.cloud.tencent.com/dev#/platform-run/service/create?type=package) 打开[腾讯云托管](https://tcb.cloud.tencent.com/dev#/platform-run), 点击`通过本地代码部署` -> 填写服务名称 -> 部署方式选择`上传代码包` -> 代码包类型选择`文件夹` -> 选择 cloudrun-springboot 目录进行上传 -> 端口填写 80 -> 点击创建并等待创建完成即可。 ### 通过 cli 部署 如果您已经安装了 [CloudBase CLI](/cli-v1/intro),可以在项目目录下使用以下命令将应用部署到 CloudBase 云托管: ``` tcb cloudrun deploy ``` 输入环境和服务名称后,CLI 会自动打包应用像并部署到云托管。 除了手动部署外,你也可以一键安装上述应用: ### 一键从模版部署 [![](https://main.qcloudimg.com/raw/67f5a389f1ac6f3b4d04c7256438e44f.svg)](https://tcb.cloud.tencent.com/dev#/platform-run/service/create?type=template&templateId=e23fc3b2681b1a8b028c85d423b7d6c5) ### 一键从 github 部署 [![](https://main.qcloudimg.com/raw/67f5a389f1ac6f3b4d04c7256438e44f.svg)](https://tcb.cloud.tencent.com/dev#/platform-run/service/create?type=git&repoUrl=https://github.com/TencentCloudBase/tcbr-templates&repoBranch=main&serverName=example-springboot&port=80&buildDir=cloudrun-springboot) --- ## 构建失败相关 # 构建失败相关 构建阶段问题多数为 docker 报错,绝大部分是因为没有正确配置 Dockerfile。 可参见优化容器镜像,或在网上搜索 docker 相关解决方案及教程。 ### 遇到报错信息“network connection aborted.”如何处理? 因为访问国外网络不稳定的不可抗力因素,建议尽量选用国内站作为镜像源下载依赖和扩展。 ### 缺少依赖报错如何处理?例如:java.lang.NoClassDefFoundError: Could not initialize class xxx Dockerfile 中缺少对应的依赖安装命令。 建议优先换用更完整的构建基础镜像而非直接增加依赖安装命令(RUN apk xxx),更加简单方便,且可以提高构建速度。 请到 GitHub-Containers 的 dockerhub 官方仓库 自行选择合适的基础镜像(默认已包含了所有您需要的依赖),然后在 Dockerfile 中替换“FROM xxxxx as build” 命令。 ### 遇到报错信息“xxxxxx: no such file or directory”如何处理? * 确保代码仓库/代码包中确实存在该文件且路径正确。 * 确保 .gitignore 或者 .dockerignore 中,没有包含这个文件。如果包含将会被构建忽略。去除即可。 * 确保 Dockerfile 中的 COPY 命令,拷贝文件的时候没有修改原有的文件路径。 ### 无报错日志显示空白该如何处理? 大概率是构建超时(> 10分钟)。请优化容器镜像,提高构建速度,防止超时。 --- ## 部署失败相关 # 部署失败相关 ### 本地运行正常,部署到云托管后却部署失败? 本地调试请尽量基于本地 Docker 进行,如果本地开发调试未基于 Docker,直接转到云托管部署时可能遇到以下情况: * 本地运行的时候,各种依赖组件、扩展在本地都是齐全的,但是没有在 Dockerfile 正确添加依赖安装命令,所以本地运行时不缺依赖没问题,部署到云托管上时就会因为缺乏依赖导致报错。 * 本地运行的时候,连接的是本地数据库(地址为本机 IP 或 localhost),部署到云托管上时没有将数据库地址改为云上的数据库地址。导致因为数据库无法连接而部署失败。 * 本地使用的运行时环境(JDK/python 版本等),与 Dockerfile 中定义的运行时环境不一致。 ### 遇到报错信息“Readiness probe failed: dial tcp xx.xx.xx.xx:xxx: connect: connection refused”如何处理? 无法通过健康检查/端口调用不通。 * 服务启动正常,但是端口填写错误,真实端口与发布时填写端口不符,导致系统误认为部署失败。 * 服务启动成功,但反复重启,进程不稳定,导致端口无法稳定调通,无法通过健康检查。请自行结合日志排查代码问题,或考虑是否因为所选容器规格过小导致内存 OOM。 * 如果您的 Dockerfile 中包含了多行独立的 CMD 命令,请注意这是错误的写法,只有最后一行 CMD 命令会被执行,之前的都会被忽略,导致业务报错。请参见 Docker 官方文档之 CMD 命令。 ### 部署失败但看业务日志已经在正常运行? 检查服务设置中端口与真实项目端口是否一致。如果服务启动正常,但是**端口填写错误**,真实端口与发布时填写端口不符,会导致系统误认为部署失败,调用服务也会报错。 ### 遇到报错信息“check pod status is not ok”如何处理? * 服务因代码原因反复重启,状态不稳定。请自行排查代码问题。 * 若服务并未反复重启,请提工单联系我们排查。 ### 遇到报错信息“Back-off restarting failed container”如何处理? 代码原因导致服务启动失败,请借助服务日志自行排查代码问题。没有采集到服务日志,请检查服务的日志采集路径是否配置正确。 ### 为什么部署 eggjs 服务,运行 npm run start 不停重复启动? 需要去掉进程守护参数 --daemon。 * 更改前:"start": "egg-scripts start --daemon --title=node-server", * 更改后:"start": "egg-scripts start --title=node-server" ### 为什么 Dockerfile 中引用了环境变量不生效? 构建或部署阶段,服务还未就绪,此时无法引用环境变量。 ### Dockerfile 中引用了 MySQL/Redis 等其他云产品的内网地址不生效? 构建/部署阶段,服务还未就绪,此时无法通过内网地址访问其他云产品。 ### 遇到报错信息“err=[ResourceUnavailable.ClusterInAbnormalState][err=cloudrun cluster state is invalid(cluster state is deleted)]”如何处理? 底层异常,请提工单联系我们处理。 ### 小程序内嵌 webview 的方式,是否支持云托管内网地址调用? 不支持,小程序的客户端内网和云托管服务端内网不是一个网络空间,不能相互调用。 ### 流水线执行正常,但是服务无法启动如何自行排查? - 查看服务启动日志是否有明显报错 - 客户可在本地使用 docker 部署验证程序启动是否有问题 ### 访问服务报错 CERTIFICATE_VERIFY_FAILED 参考 [使用注意事项](https://developers.weixin.qq.com/minigame/dev/wxcloudrun/src/guide/weixin/open.html#%E4%BD%BF%E7%94%A8%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9),需要客户服务Dockerfile、客户代码中信任证书 ### 本地监听 127.0.0.1:80 服务正常,部署到云托管无法启动 修改 0.0.0.0:80 监听端口后,重新部署服务。 --- ## 计费相关 # 计费相关 ### 云托管如何收费 云托管如今在两个不同环境中提供服务: * 微信云托管 * 云开发中的云托管 微信云托管服务采用按量计费,根据实例启动后占用的 CPU 及 内存进行计量,并根据计量情况,每日进行结算并在次日产生账单并扣费。 具体的定价信息可见[微信云托管计费说明](https://developers.weixin.qq.com/miniprogram/dev/wxcloudservice/wxcloudrun/src/Billing/price.html)。 云开发中的云托管同样根据实例启动后的 CPU 及内存使用进行计量,但是目前会换算为云开发中统一的计算资源使用量。计算资源使用量按:环境套餐-资源包-按量 的方式扣量。 具体的信息可见[计算资源使用量计量说明](https://cloud.tencent.com/document/product/876/120342)。 --- ## HTTP 访问相关 # HTTP 访问相关 ### HTTP 访问报错如何排查 判断http状态码是云托管网关返回的,还是业务服务返回的。可以查看请求返回头是否有 X-Cloudbase-Upstream-Status-Code 头,如果有该头并且值和http状态码一致,说明状态码是业务服务返回。 另外如果返回报有具体的错误码,可通过云开发http访问错误码文档排查具体原因。 具体的错误码可见[HTTP 访问服务错误码](https://docs.cloudbase.net/error-code/service)。 ### websocket 连接中断问题排查 网关层会对空闲连接进行回收,因次 websocket 连接建立后如果长时间没有数据传输,网关会主动关闭非活跃的连接,建议客户端或者服务端每隔10s发送一个心跳包; 另外客户端需要做断线重连,防止网络波动或者网关层服务重启导致的中断。如果已经做了心跳保持机制并且 websocket 连接频繁中断,可以联系我们工程师进行排查。 --- ## 概述 # 概述 - [计费相关](./fee.md) - [构建失败相关](./build.md) - [部署失败相关](./deploy.md) - [服务相关](./server.md) - [http访问相关](./gw.md) --- ## 服务相关 # 服务相关 ### 创建服务报错镜像仓库数量超限或镜像仓库命名空间数量超限 需要用户登录腾讯云tcr控制台-选择广州地域-个人版共享实例(首次登录需要根据提示初始化个人镜像仓库账户),删除不必要的镜像仓库或者命名空间,删除后重试创建云托管服务即可 --- ## 概述 # 概述 云托管(Tencent CloudBase Run)是新一代云原生应用引擎,支持托管用任意语言和框架编写的容器化应用,为开发者提供高可用、自动弹性伸缩的云服务,避免应用开发过程中繁琐的服务器搭建及运维,使开发者可以专注于业务逻辑的实现,开发门槛更低,效率更高。 云托管支持两种模式: * 容器模式:适合部署任何语言、框架的容器化应用。 * 函数模式:适合托管云函数代码,开发更简单高效。👉 详细介绍见:[函数型云托管](../cbrf/intro) 如果您是首次使用云托管,建议先阅读 [快速开始](/run/quick-start/introduce) 文档,快速体验云托管的基本功能。 ## 产品特性 | 优势 | 说明 | | -------------------- | ------------------------------------------------------ | | 🚀 免服务器运维 | 无需购买、管理、维护服务器,节省运维成本 | | 📈 自动弹性伸缩 | 实例数量随流量自动调整,支持缩容到 0,按需扩容 | | 💰 按量计费 | 只为实际用到的资源付费,最小粒度 0.25 核,避免资源浪费 | | 🏁 上手门槛低 | 无需集群运维、无需写 YAML 配置,专注业务开发 | | 🛠️ 支持多种语言框架 | 支持 Java、PHP、Go 等多种主流语言和框架 | | 🔄 迁移成本低 | 现有应用无需重构即可迁移到云托管 | | 🖼️ 镜像/代码部署灵活 | 支持上传镜像或直接上传/拉取代码自动构建 | ## 资源模型 云托管的资源模型分为三层:服务 → 版本 → 实例。 * 服务:你的业务单元,每个服务有独立的访问域名。 * 版本:服务的不同部署版本,可用于灰度发布、A/B 测试等。 * 实例:实际运行的容器,数量随流量自动伸缩。 ![](https://main.qcloudimg.com/raw/3227b80bcd9de2a1c546c6973d1a8e0a.png) 上图展示了三个示例服务 TestA、TestB、TestC。每个服务都包含了两个版本,每个版本对应着一组 0 ~ N 个实例(容器)资源。 ## 访问与流量分配 * 每个服务有一个系统分配的默认域名(可自定义)。 * 用户访问服务时,系统会根据流量分配规则,将请求路由到对应的版本。 * 实例数量会根据请求量自动调整,无请求时可缩容到 0,不产生费用。 --- ## 使用限制 # 使用限制 ## 按量使用 云托管服务由于目前使用的按量计费模式,相关 CPU、MEM 用量未包含在云开发环境的套餐中。因此在使用云托管服务时,需要开启环境的超限按量服务,以便云托管可以通过按量模式计量及计费。如果关闭了环境的超限按量,会导致被停止服务。 ## 环境隔离 云开发多个环境之间所有资源都互相隔离; 云托管环境内的服务之间可以通过内网调用; 不同环境的资源之间只能使用公网调用; ## 服务及实例相关数量限制 当前在一个云开发环境下,可以创建 15 个服务。 当前在一个云开发环境下,可以最大启动运行 28 个实例。这些数量包含了所有服务启动的实例。达到最大值后无法自动扩容出更多实例。 当前如果需要提升限制,可以[提交工单](https://console.cloud.tencent.com/workorder/category?level1_id=536&level2_id=821&source=14&data_title=%E4%BA%91%E5%BC%80%E5%8F%91%20CloudBase&step=1)进行申请。 ## QPS 限制 云开发环境下的云托管所有服务,同样受限于环境维度的总 QPS(每秒并发请求数)限制。具体环境的 QPS 限制值,可以通过套餐规格查询。 ## 云托管请求超时时间:60s ## 云托管请求包体大小:20M --- ## 日志 # 日志 本文介绍如何在开发平台上配置及查询日志。 ## 日志采集 云托管服务默认采集容器中的标准输出内容,但采集内容可以配置。 通过修改服务设置中的日志采集路径,可以采集多种内容: * stdout : 仅采集标准输出 * stdout,stderr :采集标准输出和错误输出 * stdout,/path/to/file :采集标准输出和指定路径的日志文件 ## 日志检索 1. 进入[开发平台](https://tcb.cloud.tencent.com/dev),按需要切换到指定的环境。 2. 进入`计算` - `云托管` 服务。 3. 选择您需要查看的服务,单击服务名称进入服务详情页面。 4. 单击「日志」切换到日志选项卡,即可查看当前服务、服务下所有版本的日志数据。 ## 日志说明 ### 服务访问日志、访问产生的业务日志 服务访问日志包含了请求服务时的请求日志,以及请求时带来的业务日志。 服务请求日志使用 accesslog 的 logType 进行标识,内容包含了请求路径、请求方法、请求开始时间、响应时间、耗时、响应状态等信息 跟随请求日志的有相关业务日志,即在业务代码中打印的内容;通常如果是在请求处理中增加的日志打印,将会出现在业务日志中。 通过点击服务请求日志操作中的业务日志,即可以查看到当前请求对应的业务日志。 ### 标准输出日志 未跟随服务访问日志打印的,例如服务启动时、或在后台运行时产生的日志,均可以再标准输出日志中查询到。 切换到标准输出日志分类,即可查询到具体日志内容。 ### 服务版本的日志区分 服务版本实际运行的实例均会带有版本标识,类似 001、002、003。 在日志中同样可以根据版本标识进行筛选,查询具体版本的日志。 --- ## 监控 # 监控 本文介绍如何查看服务相关的监控数据。 ## 操作步骤 1. 进入云托管后,通过服务列表,选择需要查询的服务。 2. 在服务页面可以查询到基础监控概览。可以通过`更多详情`,进入运维管理的监控页面。通过直接选择环境的运维管理,也可以切换到监控界面查询云托管监控信息。 3. 在运维管理的运维仪表盘中,监控项目选择云托管,展开选择具体需要查询的服务。 4. 可以在下拉选择列表中,选择具体服务维度的监控,也可以进一步选择具体服务的版本,查询到版本监控。 ## 监控字段说明 - 在服务/版本维度监控选项卡中,顶部时间筛选器对页面内所有监控数据生效。例如:在顶部选择时间"7 天",则统计卡片、统计曲线,均展示过去 7 天的数据。 - 监控曲线图中的“粒度”指每个监控数据对应的单位时间,会随着所选时间区间变化,时间跨度长则粒度粗。**曲线图上所有数值需配合粒度解读**。 ### 服务监控 - **调用次数**:单位时间内服务收到的请求次数总和(包括通过服务域名、HTTP 访问服务产生的请求)。 - **响应时间(毫秒)**:单位时间内服务收到的所有请求的响应时间取平均值。 - **QPS**:单位时间内服务平均每秒处理的请求数。 - **错误响应**:单位时间内请求服务失败,返回 404、500 的 HTTP 错误的次数。 - **CPU 用量**:单位时间内服务所有版本 CPU 资源消耗之和,单位为(核 x 小时)。 - **内存用量**:单位时间内服务所有版本内存资源消耗之和,单位为(GiB x 小时)。 - **实例个数**:服务所有版本的实时实例个数之和,在单位时间内取平均值。 - **异常实例个数**:服务所有版本的实时实例状态不正常个数之和,在单位时间内取平均值。非正常运行的实例均会标记为异常实例,其中也会包括启动中的实例。 ### 版本监控 - **调用次数**:单位时间内版本收到的请求次数总和(包括通过服务域名、HTTP 访问服务产生的请求)。 - **响应时间(毫秒)**:单位时间内版本收到的所有请求的响应时间取平均值。 - **QPS**:单位时间内版本平均每秒处理的请求数。 - **HTTP 错误**:单位时间内请求版本失败返回 HTTP 错误的次数。 - **CPU 用量**:单位时间内版本 CPU 资源消耗,单位为(核 x 小时)。 - **内存用量**:单位时间内版本内存资源消耗之和,单位为(GiB x 小时)。 - **CPU 使用率**:版本所有实例 CPU 使用率平均值,在单位时间内再取平均值。可作为设置扩缩容条件的参考值。 - **内存使用率**:版本所有实例内存使用率平均值,在单位之间内再取平均值。 - **实例个数**:版本的实时实例个数,在单位时间内取平均值。 - **异常实例个数**:版本的实时实例状态不正常个数,在单位时间内取平均值。非正常运行的实例均会标记为异常实例,其中也会包括启动中的实例。 --- ## 使用 Webshell 登录实例 # 使用 Webshell 登录实例 本文为您介绍云托管的 Webshell 功能,以及如何使用 Webshell 完成基本的运维需求。 ## 操作背景 容器是一个暂态的、供服务运行的环境,您在使用云托管时只需关注自己的服务,不需要涉及对容器的直接操作,包括创建、配置、更新、重启、销毁等等。但为了方便进行线上问题定位、排查,特别是调试关于代码本身的问题,云托管在控制台提供了简易版 Webshell,供您查看并调试自己的容器。 :::caution 注意 通过 Webshell 直接操作容器可能会带来风险。云托管只是为您提供了一个直达容器的途径,您在 Webshell 中做的一切操作,云托管都无法感知、无法管控。 - 若您在 Webshell 中的操作引起容器 OOM,可能会带来服务中断。 - 若您在 Webshell 中直接修改了容器配置,可能会导致与云托管中记录的容器配置不一致,引起后续操作混乱。 ::: ## 步骤 1:进入开发平台 进入[开发平台](https://tcb.cloud.tencent.com/dev),按需要切换到指定的环境。 进入`计算` - `云托管` 服务。 ## 步骤 2:进入服务详情页面 单击服务名称进入服务详情页面。 ## 步骤 3:进入实例详情页 单击服务基本信息中的实例详情查看,打开实例详情列表。 ## 步骤 4:进入 Webshell 页面 单击需要调试的容器对应的「Webshell」,进入 Webshell 管理页面。 :::tip 提示 根据版本的“副本个数”、“扩缩容条件”和当前版本流量情况,您的版本下可能有多个实例(容器)。同一个版本下所有的容器都是根据“版本配置”创建出来的,配置信息完全一致,因此绝大多数情况下您任意选择一个容器进入 Webshell 都可对当前版本进行调试和问题定位。但不排除某些特殊情况下,仅有个别容器状态异常。 ::: :::caution 注意 如果采用的是精简容器,容器内没有 `sh` 或 `bash` 工具,会导致启动 shell 失败。您可以更新包含了 shell 能力的基础镜像,或在 dockerfile 中增加 shell 安装。 ::: ## 步骤 5:调试操作 您可以开始对自己的服务进行调试。 --- ## .NET 快速开始 # .NET 快速开始 本文档介绍从零开始手动将一个 .NET 应用容器化,并部署到腾讯云托管(CloudBase Run)。 ## 第 1 步:编写基础应用 安装 [.NET Core SDK 3.1](https://www.microsoft.com/net/core)。在 Console 中,使用 dotnet 命令新建一个空 Web 项目: ```sh dotnet new web -o helloworld-csharp cd helloworld-csharp ``` 更新 `Program.cs` 中的 `CreateHostBuilder` 定义,侦听 `80` 端口: ```cs using System; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Hosting; namespace helloworld_csharp { public class Program { public static void Main(string[] args) { CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) { string port = "80"; string url = String.Concat("http://0.0.0.0:", port); return Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup().UseUrls(url); }); } } } ``` 将 `Startup.cs` 的内容更新为如下: ```cs using System; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; namespace helloworld_csharp { public class Startup { // This method gets called by the runtime. Use this method to add services to the container. // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 public void ConfigureServices(IServiceCollection services) { } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseRouting(); app.UseEndpoints(endpoints => { endpoints.MapGet("/", async context => { await context.Response.WriteAsync("Hello World!\n"); }); }); } } } ``` 以上代码会创建一个基本的 Web 服务器,并监听 `80` 端口。 ## 第 2 步:将应用容器化 在项目根目录下,创建一个名为 `Dockerfile` 的文件,内容如下: ```dockerfile # 使用微软官方 .NET 镜像作为构建环境 # https://hub.docker.com/_/microsoft-dotnet-core-sdk/ FROM mcr.microsoft.com/dotnet/core/sdk:3.1-alpine AS build WORKDIR /app # 安装依赖 COPY *.csproj ./ RUN dotnet restore # 将本地代码拷贝到容器内 COPY . ./ WORKDIR /app # 构建项目 RUN dotnet publish -c Release -o out # 使用微软官方 .NET 镜像作为运行时镜像 # https://hub.docker.com/_/microsoft-dotnet-core-aspnet/ FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-alpine AS runtime WORKDIR /app COPY --from=build /app/out ./ # 启动服务 ENTRYPOINT ["dotnet", "helloworld-csharp.dll"] ``` 添加一个 `.dockerignore` 文件,以从容器映像中排除文件: ``` **/obj/ **/bin/ ``` ## 第 3 步(可选):本地构建镜像 如果您本地已经安装了 Docker,可以运行以下命令,在本地构建 Docker 镜像: ```sh docker build -t helloworld-csharp . ``` 构建成功后,运行 `docker images`,可以看到构建出的镜像: ``` REPOSITORY TAG IMAGE ID CREATED SIZE helloworld-csharp latest 1c8dfb88c823 8 seconds ago 105MB ``` 随后您可以将此镜像上传至您的镜像仓库。 执行以下命令来运行容器: ```sh docker run -p 80:80 helloworld-csharp ``` 访问 `http://localhost`,您应该能看到 "Hello World!" 的输出。 ## 第 4 步:部署到 CloudBase 云托管 如果您已经安装了 [CloudBase CLI](/cli-v1/intro),可以在项目目录下使用以下命令将应用部署到 CloudBase 云托管: ``` tcb cloudrun deploy ``` 输入环境和服务名称后,CLI 会自动打包应用像并部署到云托管。更多部署方式请参考 [部署服务](/run/quick-start/introduce)。 --- ## Go 快速开始 # Go 快速开始 本文档介绍从零开始手动将一个 Go 应用容器化,并部署到腾讯云托管(CloudBase Run)。 代码示例: [https://github.com/TencentCloudBase/cloudbase-examples/tree/master/cloudbaserun/go](https://github.com/TencentCloudBase/cloudbase-examples/tree/master/cloudbaserun/go) 或者一键部署到云托管: [![](https://main.qcloudimg.com/raw/67f5a389f1ac6f3b4d04c7256438e44f.svg)](https://tcb.cloud.tencent.com/dev#/platform-run/service/create?type=git&repoUrl=https://github.com/TencentCloudBase/cloudbase-examples&repoBranch=master&serverName=example-go&port=80&buildDir=cloudbaserun/go) ## 第 1 步:编写基础应用 创建名为 `helloworld` 的新目录,并转到此目录中: ```sh mkdir helloworld cd helloworld ``` 创建一个包含以下内容的 `go.mod` 文件: ```go module helloworld go 1.24 ``` 在同一目录中,创建一个 `main.go` 文件,并将以下代码行复制到其中: ```go package main import ( "fmt" "log" "net/http" ) func main() { http.HandleFunc("/", handler) port := "80" if err := http.ListenAndServe(":"+port, nil); err != nil { log.Fatal(err) } } func handler(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello World!\n") } ``` 此代码会创建一个基本的 Web 服务器,侦听 `80` 端口。 ## 第 2 步:将应用容器化 在项目根目录下,创建一个名为 `Dockerfile` 的文件,内容如下: ```dockerfile # 使用官方 Golang 镜像作为构建环境 FROM golang:1.24-alpine as builder # 设置工作目录 WORKDIR /app # 复制源代码 COPY . . RUN go mod download # 构建二进制文件 RUN CGO_ENABLED=0 GOOS=linux go build -mod=readonly -ldflags="-s -w" -v -o server # 选用运行时所用基础镜像(GO语言选择原则:尽量体积小、包含基础linux内容的基础镜像) # https://hub.docker.com/_/alpine FROM alpine:latest # 安装基本工具和时区数据 RUN apk add --no-cache tzdata ca-certificates && \ cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \ echo "Asia/Shanghai" > /etc/timezone && \ apk del tzdata # 设置工作目录 WORKDIR /app # 将构建好的二进制文件拷贝进镜像 COPY --from=builder /app/server /app/server EXPOSE 80 # 启动 Web 服务 CMD ["/app/server"] ``` 添加一个 `.dockerignore` 文件,以从容器映像中排除文件: ``` vendor/ Dockerfile README.md .dockerignore .gcloudignore .gitignore ``` ## 第 3 步(可选):本地构建和运行 如果您本地已经安装了 Docker,可以运行以下命令,在本地构建 Docker 镜像: ```sh docker build -t helloworld-go . ``` 构建成功后,运行 `docker images`,可以看到构建出的镜像: ``` REPOSITORY TAG IMAGE ID CREATED SIZE helloworld-go latest 6948f1ebee94 8 seconds ago 15 MB ``` 随后您可以将此镜像上传至您的镜像仓库。 执行以下命令来运行容器: ```sh docker run -p 80:80 helloworld-python ``` 访问 `http://localhost`,您应该能看到 "Hello World!" 的输出。 ## 第 4 步:部署到 CloudBase 云托管 如果您已经安装了 [CloudBase CLI](/cli-v1/intro),可以在项目目录下使用以下命令将应用部署到 CloudBase 云托管: ``` tcb cloudrun deploy ``` 输入环境和服务名称后,CLI 会自动打包应用像并部署到云托管。更多部署方式请参考 [部署服务](/run/quick-start/introduce)。 Go 框架项目的示例可参考: - [创建一个 Gin 应用](../develop/languages-frameworks/gin) --- ## Java 快速开始 # Java 快速开始 本文档介绍从零开始,如何将一个 Java 应用容器化,并部署到 CloudBase 云托管。 代码示例: [https://github.com/TencentCloudBase/cloudbase-examples/tree/master/cloudbaserun/java](https://github.com/TencentCloudBase/cloudbase-examples/tree/master/cloudbaserun/java) 或者一键部署到云托管: [![](https://main.qcloudimg.com/raw/67f5a389f1ac6f3b4d04c7256438e44f.svg)](https://tcb.cloud.tencent.com/dev#/platform-run/service/create?type=git&repoUrl=https://github.com/TencentCloudBase/cloudbase-examples&repoBranch=master&serverName=example-java&port=80&buildDir=cloudbaserun/java) ## 第 1 步:编写基础应用(创建 Spring Boot 项目) 请确保已安装 curl 和 unzip。在终端执行以下命令,快速生成一个 Spring Boot Web 项目: ```sh curl https://start.spring.io/starter.zip \ -d type=maven-project \ -d dependencies=web \ -d javaVersion=1.8 \ -d bootVersion=2.3.3.RELEASE \ -d name=helloworld \ -d artifactId=helloworld \ -d baseDir=helloworld \ -o helloworld.zip unzip helloworld.zip cd helloworld ``` 上述命令将创建一个 Spring Boot 项目。 :::tip 提示 如需在 Windows 系统上使用上述 curl 命令,您需要以下命令行之一: - [WSL(推荐)](https://docs.microsoft.com/en-us/windows/wsl/install-win10) - [cygwin](https://cygwin.com/install.html) 或者选择性地使用 [Spring Initializr(预加载配置)](https://start.spring.io/#!type=maven-project&language=java&platformVersion=2.3.3.RELEASE&packaging=jar&jvmVersion=1.8&groupId=com.example&artifactId=helloworld&name=helloworld&description=&packageName=com.example.helloworld&dependencies=web) 生成项目: ::: 将 `src/main/java/com/example/helloworld/HelloworldApplication.java` 内容更新如下: ```java package com.example.helloworld; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @SpringBootApplication public class HelloworldApplication { @RestController class HelloworldController { @GetMapping("/") String hello() { return "Hello World!"; } } public static void main(String[] args) { SpringApplication.run(HelloworldApplication.class, args); } } ``` 在 `src/main/resources/application.properties` 中,将服务器端口设置成 `80`: ``` server.port=80 ``` 以上代码会创建一个基本的 Web 服务器,并监听 `80` 端口。 ## 第 2 步:将应用容器化 在项目根目录下,创建一个名为 `Dockerfile` 的文件,内容如下: ```dockerfile # 使用官方 maven/Java 8 镜像作为构建环境 # https://hub.docker.com/_/maven FROM maven:3.6-jdk-11 as builder # 将代码复制到容器内 WORKDIR /app COPY pom.xml . COPY src ./src # 构建项目 RUN mvn package -DskipTests # 使用 AdoptOpenJDK 作为基础镜像 # https://hub.docker.com/r/adoptopenjdk/openjdk8 # https://docs.docker.com/develop/develop-images/multistage-build/#use-multi-stage-builds FROM adoptopenjdk/openjdk11:alpine-slim # 将 jar 放入容器内 COPY --from=builder /app/target/helloworld-*.jar /helloworld.jar # 启动服务 CMD ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/helloworld.jar"] ``` 添加一个 `.dockerignore` 文件,以从容器映像中排除文件: ``` Dockerfile .dockerignore target/ README.md HELP.md ``` ## 第 3 步(可选):本地构建和运行 如果您本地已经安装了 Docker,可以运行以下命令,在本地构建 Docker 镜像: ```sh docker build -t helloworld-java . ``` 构建成功后,运行 `docker images`,可以看到构建出的镜像: ``` REPOSITORY TAG IMAGE ID CREATED SIZE helloworld-java latest c994813b495b 8 seconds ago 271MB ``` 随后您可以将此镜像上传至您的镜像仓库。 执行以下命令来运行容器: ```sh docker run -p 80:80 helloworld-python ``` 访问 `http://localhost`,您应该能看到 "Hello World!" 的输出。 ## 第 4 步:部署到 CloudBase 云托管 如果您已经安装了 [CloudBase CLI](/cli-v1/intro),可以在项目目录下使用以下命令将应用部署到 CloudBase 云托管: ```sh tcb cloudrun deploy ``` 输入环境和服务名称后,CLI 会自动打包应用像并部署到云托管。更多部署方式请参考 [部署服务](/run/quick-start/introduce)。 Java 框架项目示例可以参考: - [创建一个 Spring Boot Web 应用](../develop/languages-frameworks/springboot) --- ## Node.js 快速开始 # Node.js 快速开始 本文档介绍从零开始手动将一个 Node.js 应用容器化,并部署到 CloudBase 云托管服务。 代码示例: [https://github.com/TencentCloudBase/cloudbase-examples/tree/master/cloudbaserun/node](https://github.com/TencentCloudBase/cloudbase-examples/tree/master/cloudbaserun/node) 或者一键部署到云托管: [![](https://main.qcloudimg.com/raw/67f5a389f1ac6f3b4d04c7256438e44f.svg)](https://tcb.cloud.tencent.com/dev#/platform-run/service/create?type=git&repoUrl=https://github.com/TencentCloudBase/cloudbase-examples&repoBranch=master&serverName=example-node&port=80&buildDir=cloudbaserun/node) ## 第 1 步:编写基础应用 创建名为 `helloworld` 的新目录,并转到此目录中: ```sh mkdir helloworld cd helloworld ``` 创建一个包含以下内容的 `package.json` 文件: ```json { "name": "helloworld", "description": "Simple hello world sample in Node", "version": "1.0.0", "type": "module", "main": "index.js", "scripts": { "start": "node index.js" }, "author": "Tencent CloudBase", "license": "Apache-2.0" } ``` 在同一目录中,创建一个 `index.js` 文件,并将以下代码行复制到其中: ```js import { createServer } from "node:http"; import { Readable } from "node:stream"; const server = createServer(async (req, res) => { if (req.url === "/") { res.writeHead(200); res.end("Hello World!"); } else if (req.url === "/myip") { // 设置 CORS 头,允许跨域请求 res.setHeader("Access-Control-Allow-Origin", "*"); try { // 使用 fetch 获取远程数据(这里使用 ipinfo.io 作为示例) const response = await fetch("https://ipinfo.io", { headers: { Accept: "application/json", }, }); Readable.fromWeb(response.body).pipe(res); } catch (error) { console.error(error); res.writeHead(500); res.end(JSON.stringify({ error: "Failed to fetch remote data" })); } } else { res.writeHead(404); res.end(JSON.stringify({ error: "Not Found" })); } }); const port = 80; server.listen(port, () => { console.log(`Server running at http://localhost:${port}/`); console.log( `Try accessing http://localhost:${port}/myip to see your IP info` ); }); ``` 此代码会创建一个基本的 Web 服务器,侦听 `80` 端口。 ## 第 2 步:将应用容器化 在项目根目录下,创建一个名为 `Dockerfile` 的文件,内容如下: ```dockerfile # 使用官方 Node.js 轻量级镜像. # https://hub.docker.com/_/node FROM node:22-alpine # 设置时区 RUN apk add tzdata && \ cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \ echo Asia/Shanghai > /etc/timezone && \ apk del tzdata # 定义工作目录 WORKDIR /app # 将依赖定义文件拷贝到工作目录下 COPY package*.json ./ # 使用国内镜像源安装依赖 # RUN npm config set registry https://mirrors.cloud.tencent.com/npm/ && \ # npm install --only=production && \ # npm cache clean --force # 将本地代码复制到工作目录内 COPY . . # 暴露端口 EXPOSE 80 # 启动服务 CMD [ "node", "index.js" ] ``` 添加一个 `.dockerignore` 文件,以从容器映像中排除文件: ``` Dockerfile .dockerignore node_modules npm-debug.log ``` ## 第 3 步(可选):本地构建和运行 如果您本地已经安装了 Docker,可以运行以下命令,在本地构建 Docker 镜像: ```sh docker build -t helloworld-nodejs . ``` 构建成功后,运行 `docker images`,可以看到构建出的镜像: ``` REPOSITORY TAG IMAGE ID CREATED SIZE helloworld-nodejs latest 1c8dfb88c823 8 seconds ago 163MB ``` 随后您可以将此镜像上传至您的镜像仓库。 ```sh docker run -p 80:80 helloworld-nodejs ``` 访问 `http://localhost`,您应该能看到 "Hello World!" 的输出,访问 `http://localhost/myip`,您应该能看到您的 IP 信息。 ## 第 4 步:部署到 CloudBase 云托管 如果您已经安装了 [CloudBase CLI](/cli-v1/intro),可以在项目目录下使用以下命令将应用部署到 CloudBase 云托管: ``` tcb cloudrun deploy ``` 输入环境和服务名称后,CLI 会自动打包应用像并部署到云托管。更多部署方式请参考 [部署服务](/run/quick-start/introduce)。 ## 配置规范 - 配置一般放到项目目录中,或者使用环境变量配置 - 服务部署时,在云托管上指定服务的启动端口即可 - 建议使用环境变量来管理不同环境的配置 ## 最佳实践 1. 只安装生产环境依赖以减小镜像体积 2. 使用国内镜像源加速依赖安装 3. 合理设置容器时区 4. 使用 .dockerignore 排除不必要的文件 Nodejs 框架项目示例可以参考: - [创建一个 express 应用](../develop/languages-frameworks/express) - [创建一个 nest.js 应用](../develop/languages-frameworks/nest) --- ## PHP 快速开始 # PHP 快速开始 代码示例: [https://github.com/TencentCloudBase/cloudbase-examples/tree/master/cloudbaserun/php](https://github.com/TencentCloudBase/cloudbase-examples/tree/master/cloudbaserun/php) 或者一键部署到云托管: [![](https://main.qcloudimg.com/raw/67f5a389f1ac6f3b4d04c7256438e44f.svg)](https://tcb.cloud.tencent.com/dev#/platform-run/service/create?type=git&repoUrl=https://github.com/TencentCloudBase/cloudbase-examples&repoBranch=master&serverName=example-php&port=80&buildDir=cloudbaserun/php) ## 第 1 步:编写基础应用 创建名为 `helloworld-php` 的新目录,并转到此目录中: ```sh mkdir helloworld-php cd helloworld-php ``` 创建名为 `index.php` 的文件,并将以下代码粘贴到其中: ```php requirements.txt ``` :::tip 提示 使用 `pip freeze` 生成 requirements.txt 文件必须在 python 虚拟环境下进行,否则生成的 requirements.txt 中会包含机器下的所有依赖,可能会导致部署失败。 ::: ## 第 3 步:将应用容器化 在项目根目录下,创建一个名为 `Dockerfile` 的文件,内容如下: ```dockerfile # 使用官方 Python 轻量级镜像 # https://hub.docker.com/_/python FROM python:3-alpine # 容器默认时区为UTC,如需使用上海时间请启用以下时区设置命令 # 设置时区,容器默认时区为UTC RUN apk add tzdata && \ cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \ echo Asia/Shanghai > /etc/timezone ENV APP_HOME /app WORKDIR $APP_HOME # 将本地代码拷贝到容器内 COPY . . # 设置环境变量 ENV PYTHONUNBUFFERED=1 ENV GUNICORN_WORKERS=1 ENV GUNICORN_THREADS=4 ENV GUNICORN_TIMEOUT=60 # 安装依赖到指定的/install文件夹 # 选用国内镜像源以提高下载速度 RUN pip config set global.index-url http://mirrors.cloud.tencent.com/pypi/simple && \ pip config set global.trusted-host mirrors.cloud.tencent.com && \ pip install --no-cache-dir --upgrade pip && \ pip install --no-cache-dir -r requirements.txt EXPOSE 80 # 启动 Web 服务 # 如果您的容器实例拥有多个 CPU 核心,我们推荐您把线程数设置为与 CPU 核心数一致 CMD exec gunicorn --bind :80 --workers ${GUNICORN_WORKERS} --threads ${GUNICORN_THREADS} --timeout ${GUNICORN_TIMEOUT} main:app ``` 添加一个 `.dockerignore` 文件,以从容器映像中排除文件: ``` Dockerfile README.md *.pyc *.pyo *.pyd __pycache__ .pytest_cache env/ ``` ## 第 4 步(可选):本地构建和运行 如果您本地已经安装了 Docker,可以运行以下命令,在本地构建 Docker 镜像: ```sh docker build -t helloworld-python . ``` 构建成功后,运行 `docker images`,可以看到构建出的镜像: ``` REPOSITORY TAG IMAGE ID CREATED SIZE helloworld-python latest df1440c18b5c 8 seconds ago 75.9 MB ``` 随后您可以将此镜像上传至您的镜像仓库。 执行以下命令来运行容器: ```sh docker run -p 80:80 helloworld-python ``` 访问 `http://localhost`,您应该能看到 "Hello World!" 的输出。 ## 第 5 步:部署到 CloudBase 云托管 如果您已经安装了 [CloudBase CLI](/cli-v1/intro),可以在项目目录下使用以下命令将应用部署到 CloudBase 云托管: ``` tcb cloudrun deploy ``` 输入环境和服务名称后,CLI 会自动打包应用像并部署到云托管。更多部署方式请参考 [部署服务](/run/quick-start/introduce)。 ## 配置规范 - 配置一般放到项目目录中,或者使用环境变量配置 - 服务部署时,在云托管上指定服务的启动端口即可 - 建议使用环境变量来管理不同环境的配置 ## 最佳实践 1. 使用虚拟环境管理依赖 2. 使用国内镜像源加速依赖安装 3. 合理设置容器时区 4. 使用 .dockerignore 排除不必要的文件 5. 使用 gunicorn 作为生产环境的 WSGI 服务器 Python 框架项目示例可以参考: - [创建一个 Flask 应用](../develop/languages-frameworks/flask) - [创建一个 Django 应用](../develop/languages-frameworks/django) - [创建一个 FastAPI 应用](../develop/languages-frameworks/fastapi) --- ## 概述 # 概述 云托管支持丰富的部署方式,你可以使用[应用模板](https://tcb.cloud.tencent.com/dev#/platform-run/service/create?type=template)、[容器镜像](/run/deploy/deploy/deploying-image)、[Git 仓库](run/deploy/deploy/continuous-deployment-with-cloud-build)、[cli](/cli-v1/run/deploy) 等方式部署应用。无论你选择哪种方式,云托管都能为你提供一个完整的应用运行环境。 如果你需要了解从零手动根据源码部署一个云托管服务可以请根据需要,选择适合您的快速开始文档: - [Python](./dockerize-python) - [Node.js](./dockerize-node) - [Go](./dockerize-go) - [Java](./dockerize-java) - [PHP](./dockerize-php) - [.NET](./dockerize-dotnet) 服务部署完成后,你可以在各端直接通过 HTTP 域名访问服务,也可以通过 SDK 访问接口数据。 比如可以通过微信小程序内置 SDK 访问云托管服务,这样可以避免公网访问,直接通过内网访问云托管服务。 ```js // 确认已经在 onLaunch 中调用过 wx.cloud.init 初始化环境(任意环境均可,可以填空) const res = await wx.cloud.callContainer({ config: { env: "填入云环境ID", // 微信云托管的环境ID }, path: "/xxx", // 填入业务自定义路径和参数,根目录,就是 / method: "POST", // 按照自己的业务开发,选择对应的方法 header: { "X-WX-SERVICE": "xxx", // xxx中填入服务名称(微信云托管 - 服务管理 - 服务列表 - 服务名称) // 其他header参数 }, // dataType:'text', // 默认不填是以JSON形式解析返回结果,若不想让SDK自己解析,可以填text // 其余参数同 wx.request }); console.log(res); ``` 以下是一些常见的访问方式: - [HTTP](../develop/access/client) - [微信小程序](../develop/access/mini) - [SDK/API](../develop/access/sdk-api) - [内网访问](../develop/access/internal) - [WebSocket](../develop/access/websocket) --- ## 概念说明 # 概念说明 ## 私有网络/云托管服务网络 ### 背景知识 关于什么是私有网络(VPC)及子网,请参见[私有网络](https://cloud.tencent.com/document/product/215) 文档。 云托管服务同样在独立的私有网络中。 ### 使用限制 - 同一个环境中的云托管服务,处于独立的私有网络中,可以**通过内网域名相互调用**,不产生公网流量费用,时延更短。 - 不同环境之间的服务无法通过内网互通,仅可以通过公网地址互相访问。 - 云托管服务所在的私有网络,与对应的腾讯云账号中的私有网络隔离。需要使用私有网络配置来打通云托管服务的私有网络与腾讯云账号中的私有网络。 ## 域名备案 ### 背景知识 关于什么是域名备案及如何进行域名备案,请参见[备案](https://cloud.tencent.com/document/product/243) 文档。 ### 使用限制 - 云开发环境、或云托管服务需要绑定的自定义域名,均需要完成域名备案; - 如果不是在腾讯云上完成的备案,需要在腾讯云上进行接入备案; ## 镜像仓库 ### 背景知识 云托管使用的是容器镜像服务(TCR)个人版,没有费用。 您可以在服务详情页面中的「镜像」选项卡中,快速查看当前服务所绑定的镜像仓库中所有镜像和它们的使用情况。 更多关于腾讯云镜像仓库的介绍,请参见 [容器镜像服务](https://cloud.tencent.com/document/product/1141) 文档。 ### 使用限制 - 服务在创建时会绑定一个唯一的腾讯云镜像仓库,管理该服务下的所有版本的相关镜像。 - 不支持同一服务绑定多个镜像仓库,使得不同版本的镜像分散在多个不同的镜像仓库里。 - 所有由云托管创建的镜像仓库都会统一存放于以 “tcb” 开头的同一个命名空间之下,并以环境 id\_ 服务名的格式命名。您可以在 [容器镜像服务控制台](https://console.cloud.tencent.com/tcr) 上看到由云托管创建的这个镜像仓库并对它进行管理。 ### 用法推荐 “使用默认仓库(推荐)”:云托管将使用容器镜像服务个人版,在创建服务时自动为您创建一个与服务同名的私有仓库并与您的服务进行绑定。 “绑定已有腾讯云镜像仓库”适用以下场景: 1. 跨场景复用 在云托管的场景之外,您已经使用了腾讯云的镜像仓库,并希望里面的镜像继续用于云托管的某个服务。此时,在创建服务时,可以选择 “绑定已有腾讯云镜像仓库” ,指定任意您账户下的私人镜像仓库。 请注意,若如此做,则您通过云托管产生的镜像(手动上传或自动构建推送),可能也会影响您在其他场景下的镜像使用。 2. 容量限制 个人版容器镜像服务存在相关仓库数限制,当触碰到此限制且不方便进行个人版清理时,可以切换为使用已有的企业版仓库;企业版仓库相关限制可以查询具体镜像仓库说明。 ## 服务域名 - 公网域名:公网任意来源可以用来对服务进行 HTTPS 调用,会产生相应的公网流量费用。 - 内网域名:仅同一环境内其他云托管服务访问,不产生公网流量费用。 - 允许公网通过服务域名访问服务:关闭后,通过默认公网域名/自定义公网域名访问服务将报错。当您希望服务仅内网可访问,可选择关闭。无论是否开启,不影响通过内网域名访问服务。 :::tip 提示 - 关闭“允许公网通过服务域名访问服务”后,若内网域名也同时没有被调用,则从任何角度都没有流量会打到当前服务,会引发服务下所有版本缩容至最小副本个数。 - 同一环境内,通过内网域名访问速度会高于通过公网域名访问。 ::: ### HTTP 访问服务配置 在服务域名之外,可选择启用 HTTP 访问服务。 #### 背景知识 关于云开发 HTTP 访问服务的介绍,请参见[HTTP 访问服务文档](/service/introduce)。 #### 使用限制 - 是否启用、如何配置 HTTP 访问服务,均不影响对服务域名的使用。 - 关闭“允许公网通过服务域名访问服务”开关,不影响公网通过在 HTTP 访问服务中配置的地址访问服务。 - 公网通过在 HTTP 访问服务中配置的地址访问服务,会产生相应的公网流量费用。 ## 资源互联 ### 应用场景 需要跟自己账号vpc下资源网络打通 ### 使用限制 - 环境纬度支持同地域 - 带宽限制 5Gbps - 授权遇到:Error:InvalidParameter,vpc cidr conflict with others 时说明 cidr 冲突,需要更换自己 vpc 的 cidr 再次尝试 --- ## HTTP 访问云函数 # HTTP 访问云函数 开发者可以通过 HTTP 调用云函数,并且将云函数的返回值变为 HTTP 响应体。云开发中[云函数](/cloud-function/introduce)的入出参一般都要求是 JSON 对象,需要一定的映射规则对应到 HTTP 的请求和响应中。 ## 跨域处理 HTTP 访问服务天然支持跨域请求,将域名添加至 [安全域名](https://tcb.cloud.tencent.com/dev?#/env/safety-source) 中,此域名下网页便可以跨域访问 HTTP 服务。 ## 云函数的入参 使用 HTTP 调用云函数时,HTTP 请求会被转化为特殊的结构体,称之为**集成请求**,结构如下: ```js { path: 'HTTP请求路径,如 /hello', httpMethod: 'HTTP请求方法,如 GET', headers: { // HTTP请求头 }, queryStringParameters: { // HTTP请求的Query, 键值对形式 }, requestContext: { // 云开发相关信息 }, body: 'HTTP请求体', isBase64Encoded: 'true or false,表示body是否为Base64编码' } ``` 下面是一个示例: ```js { path: '/', httpMethod: 'GET', headers: { 'host': 'env-id.service.tcloudbase.com', 'connection': 'close', 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36', 'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9', 'accept-encoding': 'gzip, deflate, br', 'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8' }, requestContext: { requestId: 'cdbb96328072184d19d3fcd243e8cc4d', envId: 'env-id', appId: 123456789, uin: 123456789 }, isBase64Encoded: false, body: '' } ``` --- ## 云函数的返回值 云函数可以返回 `string` 、 `object` 、 `number` 等类型的数据,或者返回[集成响应](#返回集成响应),随后返回值会被转化为正常的 HTTP 响应。 ### 返回字符串或数字 云函数返回字符串,那么 ```js exports.main = async function() { return "hello gateway"; }; ``` 最终 HTTP 响应为: ``` HTTP/1.1 200 OK date: Mon, 16 Dec 2019 08:35:31 GMT content-type: text/plain; charset=utf-8 content-length: 13 hello gateway ``` ### 返回 Object 返回的 `Object` 会被转换为 JSON,同时 HTTP 响应的 `content-type` 会被设置为 `application/json` ): ```js exports.main = async function() { return { foo: "bar", }; }; ``` 最终 HTTP 响应为: ``` HTTP/1.1 200 OK date: Mon, 16 Dec 2019 08:35:31 GMT content-type: application/json; charset=utf-8 content-length: 13 {"foo":"bar"} ``` ### 返回集成响应 云函数可以返回如下这样特殊结构的**集成响应**,来自由地控制响应体: ```json { "isBase64Encoded": true|false, "statusCode": httpStatusCode, "headers": { "headerName": "headerValue", ... }, "body": "..." } ``` #### 使用集成响应返回 HTML 将 `content-type` 设置为 `text/html` ,即可在 `body` 中返回 HTML,会被浏览器自动解析: ```js exports.main = async function() { return { statusCode: 200, headers: { "content-type": "text/html", }, body: "Hello", }; }; ``` 最终 HTTP 响应为: ``` HTTP/1.1 200 OK date: Mon, 16 Dec 2019 08:35:31 GMT content-type: text/html; charset=utf-8 content-length: 14 Hello ``` #### 使用集成响应返回 JS 文件 将 `content-type` 设置为 `application/javascript` ,即可在 `body` 中返回 JavaScript 文件: ```js exports.main = async function() { return { statusCode: 200, headers: { "content-type": "application/javascript", }, body: 'console.log("Hello!")', }; }; ``` 最终 HTTP 响应为: ``` HTTP/1.1 200 OK date: Mon, 16 Dec 2019 08:35:31 GMT content-type: application/javascript; charset=utf-8 content-length: 21 console.log("Hello!") ``` #### 使用集成响应返回二进制文件 如果返回体是诸如图片、音视频这样的二进制文件,那么可以将 `isBase64Encoded` 设置为 `true` ,并且将二进制文件内容转为 Base64 编码的字符串,例如: ```js exports.main = async function() { return { isBase64Encoded: true, statusCode: 200, headers: { "content-type": "image/png", }, body: "iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAY...", }; }; ``` 最终 HTTP 响应为一张 PNG 图片: ``` HTTP/1.1 200 OK date: Mon, 16 Dec 2019 08:35:31 GMT content-type: image/png content-length: 9897 ``` #### 使用集成响应完成 302 重定向 假设相对某个 URL 路径下所有路径做 302 的中转代理 ```js exports.main = async function(event) { const { path } = event; return { statusCode: 302, headers: { location: `https://tcb.cloud.tencent.com${path}`, }, }; }; ``` --- ## 身份认证 # 身份认证 云开发 HTTP 访问服务支持开启身份认证功能,确保只有经过身份验证的合法用户才能访问您的服务。本文档将指导您如何开启身份认证并在不同平台的请求中正确使用鉴权信息。 ## 什么是 HTTP 身份认证 HTTP 身份认证是一种安全机制,用于验证访问 HTTP 服务的用户身份。通过开启此功能,您可以: * 保护您的 HTTP 服务不被未授权用户访问 * 跟踪和记录用户访问行为 * 根据用户身份提供个性化的服务内容 ## 开启 HTTP 身份认证 1. 登录云开发控制台,进入 [HTTP 访问服务管理页面](https://tcb.cloud.tencent.com/dev#/env/http-access) 2. 在域名关联资源列表中,找到需要身份认证的路径 3. 点击对应路径的「身份认证」开关,启用鉴权功能 ![HTTP身份认证设置](https://qcloudimg.tencent-cloud.cn/raw/eb37a023f97898307720ca82f17a0b4c.png) :::warning 重要提示 开启身份认证后: * **浏览器访问**:系统会自动跳转到登录页,用户登录成功后会自动跳转回原页面 * **API 调用**:未携带有效鉴权信息的请求会返回 `401 Unauthorized` 错误 * **小程序/移动应用**:需要通过 SDK 获取并携带鉴权信息 ::: ## 在 HTTP 请求中使用鉴权信息 ### 使用 axios 发起请求 ```js const axios = require("axios"); const cloudbase = require("@cloudbase/js-sdk"); // 初始化 SDK const app = cloudbase.init({ env: "您的环境ID" // 替换为您的云开发环境ID }); const auth = app.auth(); // 用户登录(示例使用账号密码登录) await auth.signIn({ username: "your username", password: "your password" }); // 获取token const { accessToken } = await auth.getAccessToken(); // 发起带鉴权的 HTTP 请求 axios({ url: "自定义路径", method: "post", headers: { 'Authorization': `Bearer ${accessToken}`, 'Content-Type': 'application/json' }, data: { name: "云开发", action: "测试鉴权" } }) .then(response => { console.log("请求成功:", response.data); }) .catch(error => { console.error("请求失败:", error); }); ``` ### 使用 fetch API 发起请求 ```js // 获取鉴权Token const { accessToken } = await auth.getAccessToken(); // 使用fetch发起请求 fetch("自定义路径", { method: "POST", headers: { 'Authorization': `Bearer ${accessToken}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ name: "云开发", action: "测试鉴权" }) }) .then(response => response.json()) .then(data => console.log("请求成功:", data)) .catch(error => console.error("请求失败:", error)); ``` ### HTTP 请求示例 ```http POST /api/function HTTP/1.1 Host: 您的环境ID.service.tcloudbase.com Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... Content-Type: application/json { "name": "云开发", "action": "测试鉴权" } ``` --- ## 接入自定义 CDN # 接入自定义 CDN HTTP 访问服务默认提供中国大陆地区的 CDN 加速能力,如果此不能满足您的需求(例如您需要对站点进行全球加速),那么可以接入云上的自定义 CDN。 ## 准备工作 1. 一个用于访问的自定义域名(需要**未在云开发进行绑定**) ## 操作步骤 ### 第 1 步:购买 CDN 前往 [腾讯云 CDN 控制台](https://console.cloud.tencent.com/cdn),进入 [域名管理页面](https://console.cloud.tencent.com/cdn/domains),点击添加域名: ![](https://main.qcloudimg.com/raw/7a382222df8e34154c77ee3674941b71.png) 改动配置如下: 1. 「加速区域」根据您的需要进行选择 2. 「加速域名」填入您准备的**自定义域名** 3. 「业务类型」为**静态加速** 4. 「源站类型」为**自有源** 5. 「回源协议」为**协议跟随** 6. 「源站地址」填入 `gw-prod..service.tcloudbase.com`,其中``为您的云开发环境所在地域,如 `ap-shanghai`、`ap-guangzhou` 7. 「回源 Host」填入您的**云开发环境默认域名** 随后点击「确认提交」创建 CDN,等待一段时间成功: ![](https://main.qcloudimg.com/raw/767b1d0d10ddc4114ec1af6cb5187686.png) ### 第 2 步:配置域名 DNS 将您的自定义域名的 CNAME 记录,改为 CDN 控制台上展示的域名,具体配置方法可参照下文附录: ![](https://main.qcloudimg.com/raw/8ae21686ad798ed54884c1d4e25ab7c7.png) ### 第 3 步(可选):配置 HTTPS 证书 如果您的域名需要配置 HTTPS,可前往 CDN 控制台配置 HTTPS 证书,具体操作可参见 [腾讯云 CDN 文档](https://cloud.tencent.com/document/product/228/41687)。 ## 附:CNAME 配置方法 ### 腾讯云设置方法 若您的 DNS 服务商为腾讯云,您可通过如下步骤添加 CNAME 记录。 1. 登录 [域名服务](https://console.cloud.tencent.com/domain) 控制台,在列表中,找到需要添加 CNAME 记录的域名所在行,单击操作栏的「解析」。 ![CNAME配置](https://main.qcloudimg.com/raw/12eba66e1d073aade459318d6e9c53ef.png) 2. 在跳转到的页面中,单击「添加记录」。 ![](https://main.qcloudimg.com/raw/88a0cda619aeaf1a88120ad5294250fa.png) 3. 在 **主机记录** 处填写域名前缀(例如:www),将 **记录类型** 设置为 CNAME,在 **记录值** 处填写 CNAME 域名,单击「保存」,即可添加 CNAME 记录。 ![](https://main.qcloudimg.com/raw/24ee35e7bba9d181abbdaf65fe7fc3cb.png) :::tip 提示 域名解析各种记录类型之间是有优先级差异的,在主机记录相同的情况下,同一条线路有几种不同的记录类型不能共存,否则将会提示冲突。CNAME 记录与除 CNAME 记录以外的任何记录类型都冲突,需要先删除掉其他记录,再进行配置。详情请参见 [为什么添加解析记录的时候提示 "记录有冲突" ](https://cloud.tencent.com/document/product/302/3468#.E4.B8.BA.E4.BB.80.E4.B9.88.E6.B7.BB.E5.8A.A0.E8.A7.A3.E6.9E.90.E8.AE.B0.E5.BD.95.E7.9A.84.E6.97.B6.E5.80.99.E6.8F.90.E7.A4.BA-.26quot.3B.E8.AE.B0.E5.BD.95.E6.9C.89.E5.86.B2.E7.AA.81.26quot.3B-.EF.BC.9F)。 ::: ### DNSPod 设置方法 若您的 DNS 服务商为 DNSPod,登录 [DNSPod 域名服务控制台](https://console.dnspod.cn/dns/list),在列表中,找到需要添加 CNAME 记录的域名所在行,单击对应域名名称,跳转至“添加记录”界面,通过如下步骤添加 CNAME 记录。 ![](https://main.qcloudimg.com/raw/c5e256fcc42261105b674151aa6561a3.png) 1. 主机记录处填子域名(例如需要添加`www.123.com`的解析,只需要在主机记录处填写`www`即可。如果只是想添加`123.com`的解析,主机记录直接留空,系统会自动填一个“@”到输入框内,@的 CNAME 会影响到 MX 记录的正常解析,添加时慎重考虑)。 2. 记录类型为 CNAME。 3. 线路类型(默认为必填项,否则会导致部分用户无法解析。在上图中,默认的作用为:除了联通用户之外的所有用户,都会指向 1.com)。 4. 记录值为 CNAME 指向的域名,只可以填写域名,记录生成后会自动在域名后面补一个“.”,这是正常现象。 5. MX 优先级不需要填写。 6. TTL 不需要填写,添加时系统会自动生成,默认为 600 秒(TTL 为缓存时间,数值越小,修改记录各地生效时间越快)。 ### 万网设置方法 若您的 DNS 服务商为万网,您可通过如下步骤添加 CNAME 记录。 1. 登录万网会员中心。 2. 单击会员中心左侧导航栏中的「产品管理」> 「我的云解析」进入万维网云解析列表页。 3. 单击要解析的域名,进入解析记录页。 4. 进入解析记录页后,单击新增解析按钮,开始设置解析记录。 ![](https://main.qcloudimg.com/raw/54825b2a66e6752cd451d79d72929833.png) 5. 若要设置 CNAME 解析记录,将记录类型选择为 CNAME。主机记录即域名前缀,可任意填写(如:`www`)。记录值填写为当前域名指向的另一个域名。解析线路,TTL 默认即可。 ![](https://main.qcloudimg.com/raw/b321d20332ca1b93eb78376cac43683b.png) 6. 填写完成后,单击「保存」,完成解析设置。 ### 新网设置方法 若您的 DNS 服务商为新网,您可通过如下步骤添加 CNAME 记录。 **设置别名(CNAME 记录)** 即:别名记录。这种记录允许您将多个名字映射到同一台计算机。通常用于同时提供 WWW 和 MAIL 服务的计算机。例如,有一台计算机名为`host.mydomain.com`(A 记录)。它同时提供 WWW 和 MAIL 服务,为了便于用户访问服务。可以为该计算机设置两个别名(CNAME):WWW 和 MAIL 。如下图: ![](https://main.qcloudimg.com/raw/2e93d51c7fe8502670475d71bbfb20cb.png) ## 验证 CNAME 是否生效 不同的 DNS 服务商,CNAME 生效的时间略有不同,一般会在半个小时之内生效。您也可以通过 dig 的方式来查询 CNAME 是否生效,如果 dig 到后缀为 `.cdn.dnsv1.com` 的域名,表示域名 CNAME 已生效。 --- ## 自定义域名 # 自定义域名 CloudBase HTTP 访问服务默认提供自动生成的域名,您也可以将您的自定义域名绑定至 CloudBase HTTP 访问服务。 > **前提条件**:自定义域名需要您提前完成域名的 ICP 备案,推荐您使用 [腾讯云网站备案](https://cloud.tencent.com/product/ba)。 ## 第 1 步:添加域名 进入 [CloudBase云开发/HTTP访问服务](https://tcb.cloud.tencent.com/dev?#/env/http-access),点击「添加域名」,填写自定义域名以及配置 SSL 证书。 ## 第 2 步:配置域名 CNAME 解析记录 前往您的域名服务商后台,找到域名解析记录页面,添加 CNAME 记录。 CNAME 记录值为 HTTP 访问服务提供的 CNAME。 ### 腾讯云设置方法 若您的 DNS 服务商为腾讯云,您可通过如下步骤添加 CNAME 记录。 1. 登录 [域名服务](https://console.cloud.tencent.com/domain) 控制台,在列表中,找到需要添加 CNAME 记录的域名所在行,单击操作栏的解析。 2. 在跳转到的页面中,单击 **添加记录** 3. 在 主机记录 处填写域名前缀(例如:@),将 记录类型 设置为 CNAME,在 记录值 处填写 CNAME 域名,单击保存,即可添加 CNAME 记录。 :::tip 域名解析各种记录类型之间是有优先级差异的,在主机记录相同的情况下,同一条线路有几种不同的记录类型不能共存,否则将会提示冲突。CNAME 记录与除 CNAME 记录以外的任何记录类型都冲突,需要先删除掉其他记录,再进行配置。详情请参见 [为什么添加解析记录的时候提示 "记录有冲突"](https://cloud.tencent.com/document/product/302/3468) 。 ::: ## 第 3 步:等待域名生效 添加 CNAME 记录后,通常需要等待一段时间(约 5-30 分钟)让 DNS 解析生效。您可以通过以下命令检查域名解析是否已生效: ```bash nslookup 您的自定义域名 ``` 如果返回结果中显示了 CloudBase 提供的 CNAME 域名,则表示解析已生效。 ## 使用限制 * 每个 CloudBase 环境最多可绑定 5 个自定义域名 * 自定义域名必须已完成 ICP 备案 * 域名解析生效可能需要一定时间,请耐心等待 ## 常见问题 ### 为什么我的自定义域名无法访问? 1. 检查域名是否已完成 ICP 备案 2. 确认 CNAME 解析记录是否配置正确 3. 检查 DNS 解析是否已生效(可使用 nslookup 命令) 4. 确认 SSL 证书是否配置正确(如使用 HTTPS) ### 如何更新已绑定域名的 SSL 证书? 在 CloudBase 控制台的 HTTP 访问服务中,找到已绑定的域名,点击"编辑",然后更新 SSL 证书配置。 ### 如何删除已绑定的自定义域名? 在 CloudBase 控制台的 HTTP 访问服务中,找到需要删除的域名,点击"删除"按钮即可。删除后,该域名将无法再访问您的 CloudBase 服务。 --- ## 托管 Next.js 应用 # 托管 Next.js 应用 [Next.js](https://nextjs.org/) 是一款 React 框架,支持服务端渲染(SSR),本文将介绍如何将 Next.js 应用托管至云开发。 ## 第 1 步:初始化项目 使用 CLI 工具初始化一个云开发项目 ```sh cloudbase init ``` 语言选择 `Node`,模板选择 `Hello World` ```sh cloudbase init ? 选择关联环境 xxx - [xxx-xxx] ? 请输入项目名称 cloudbase-next ? 选择模板语言 Node ? 选择云开发模板 Hello World ✔ 创建项目 cloudbase-next 成功! ``` 进入项目根目录: ```sh cd cloudbase-next ``` 然后创建一个 next 应用到 `functions/next` 内: ```sh npm init next-app functions/next ``` ## 第 2 步:配置项目 我们接下来对 next 项目进行一些改造,让它满足云函数内部署的要求。 进入 next 根目录 ```sh cd functions/next ``` 安装 `serverless-http` ```sh npm install --save serverless-http ``` 然后把以下文件添加至 `functions/next/index.js` ```js // index.js const next = require("next"); const serverless = require("serverless-http"); const app = next({ dev: false }); const handle = app.getRequestHandler(); exports.main = async function (...args) { await app.prepare(); return serverless((req, res) => { handle(req, res); })(...args); }; ``` 以下文件添加至 `functions/next/next.config.js`: ```js // next.config.js module.exports = { assetPrefix: "/next" }; ``` ## 第 3 步:构建与发布 我们在 `functions/next` 目录下,运行 ```sh npm run build ``` 然后回到**项目根目录**,运行 ```sh cloudbase fn deploy next ``` 发布时,使用默认配置即可 ``` cloudbase fn deploy next ? 未找到函数发布配置,使用默认配置? Yes ✔ [next] 函数部署成功! ``` 然后我们建立一条 HTTP 服务路由: ```sh cloudbase service create -f next -p next ``` 随后我们便可以通过 URL 访问 Next.js 应用。 ```sh cloudbase service create -f next -p next ✔ 云函数 HTTP service 创建成功! https://${env-id}.service.tcloudbase.com/next ``` --- ## 托管 Node.js Server # 托管 Node.js Server 使用 HTTP 访问 + 云函数,可以很轻松地托管 Node.js 服务端程序。 ## 准备工作 1. 准备一个基础项目目录,参考 [快速开始 - 初始化目录](/service/quick-start#初始化目录) ## 创建简单的 Hello World 我们在工作目录下执行以下命令,创建一个最简单的 Node.js Server: ```sh mkdir functions/server && touch functions/server/index.js && touch functions/server/package.json ``` `functions/server/index.js` 的内容如下: ```js // functions/server/index.js const serverless = require("serverless-http"); exports.main = serverless((req, res) => { res.statusCode = 200; res.setHeader("Content-Type", "text/plain"); res.end("Hello World\n"); }); ``` :::tip 提示 我们此处使用了 [serverless-http](https://github.com/dougmoscrop/serverless-http),把[集成请求](/service/access-cloud-function#云函数的入参)转化为 Node.js Server 能接收的 [IncommingMessage](https://nodejs.org/dist/latest-v13.x/docs/api/http.html#http_class_http_incomingmessage),同时把返回的 [ServerResponse](https://nodejs.org/dist/latest-v13.x/docs/api/http.html#http_class_http_serverresponse) 转化为[集成请求](/service/access-cloud-function.md#返回集成响应) ::: `functions/server/package.json` 的内容如下: ```json { "name": "my-serverless-server", "version": "1.0.0", "main": "index.js", "dependencies": { "serverless-http": "^2.3.0" } } ``` ## 发布 发布云函数: ```sh cloudbase fn deploy server ``` 创建路由: ```sh cloudbase service create -p server -f server ``` 随后便可以通过 `https://${env}.service.tcloudbase.com/server` 访问到 Node.js Server: ```sh curl https://${env}.service.tcloudbase.com/server Hello World ``` --- ## 概述 # 概述 CloudBase 提供统一的 [HTTP 访问服务](https://tcb.cloud.tencent.com/dev#/env/http-access),让开发者能够通过标准的 HTTP 协议便捷访问环境内的各种云资源,无需复杂的 SDK 集成即可实现后端云资源的调用与管理。 HTTP 访问服务支持丰富的自定义配置,包括资源访问路径(URL Path)定制、访问服务域名(CNAME)配置等高级能力,全方位满足不同开发场景的个性化需求。 ## 核心功能与优势 * **免费默认域名**:每个环境自动分配免费的默认域名,并原生支持 HTTPS 安全协议,确保数据传输安全 * **高性能访问体验**:基于优化的 HTTP 协议实现,提供低延迟、高并发的资源访问能力 * **灵活路由配置**:支持针对域名和访问路径进行精细化路由规则配置,实现请求的智能分发 * **自定义域名管理**:支持自定义绑定/解绑域名,通过个性化域名访问环境服务,提升品牌识别度 * **多协议支持**:完整支持 HTTP/HTTPS 协议标准,兼容各类客户端和浏览器 ## 自定义域名 详情请参考[自定义域名配置](/service/custom-domain) CloudBase 为每个环境默认提供免费域名,但基于安全合规要求,默认域名仅适用于开发测试阶段,存在以下限制: * 访问频率限制 * 部分高级功能不可用 * 可能存在稳定性风险 **最佳实践**:生产环境强烈建议绑定**已完成备案的自定义域名**,以获得完整的服务能力和稳定性保障。 完成自定义域名设置后,您可以通过该域名无缝访问云函数、云托管及静态网站托管等多种云服务,实现统一的访问入口管理。 ## 域名关联资源能力 HTTP 访问服务支持将多种云资源绑定到域名下,包括: * 云函数(CloudFunction) * 云托管(CloudRun) * 静态网站托管(Hosting) * 企业工作台 * 自定义应用 通过资源关联配置,您可以实现通过统一的 HTTP 方式访问不同类型的云资源,简化应用架构设计。 ### 高级配置选项 HTTP 访问服务提供丰富的高级配置能力: * **触发路径选择**:自定义资源的访问路径,实现 RESTful API 风格的接口设计 * **身份认证**:为敏感资源启用访问控制,确保数据安全 * **路径透传**:支持将完整的请求路径传递给后端服务,便于实现复杂的路由逻辑 * **请求参数配置**:自定义请求参数处理规则,满足不同业务场景需求 * **响应头管理**:配置自定义响应头,优化前端交互体验 通过这些高级配置,您可以灵活控制资源访问方式和安全策略,打造符合业务需求的专业云服务架构。 --- ## 快速开始 # 快速开始 本文将指导您如何通过 HTTP 访问服务来调用云函数,让您的云函数能够通过 HTTP 请求被访问。 ## 步骤一:创建云函数 首先,我们需要创建一个简单的云函数作为示例: 1. 进入[云开发控制台](https://console.cloud.tencent.com/tcb),选择您的环境 2. 在左侧菜单栏选择「云函数」,点击「新建云函数」 3. 创建一个名为 `helloWorld` 的云函数 4. 编写以下代码: ```js exports.main = async function() { return "Hello World!"; }; ``` 5. 点击「保存并安装依赖」完成云函数部署 > 💡 提示:您也可以参考[云函数快速开始](/cloud-function/quick-start)获取更详细的云函数创建指南。 ## 步骤二:配置 HTTP 访问路由 接下来,为云函数配置 HTTP 访问路由: 1. 进入[云开发 HTTP 访问服务](https://console.cloud.tencent.com/tcb/service)页面 2. 点击「新建」按钮,创建一个「域名关联资源」 3. 按照以下信息填写配置: - **关联资源**:选择「云函数」,然后选择刚创建的 `helloWorld` 函数 - **域名**:选择默认域名(也可以选择您已配置的自定义域名) - **触发路径**:填写 `/hello` (这将成为访问路径) ![HTTP服务配置示例](https://qcloudimg.tencent-cloud.cn/raw/342a027d8d10805110608dce3f914b04.png) 4. 点击「确定」,系统将开始创建 HTTP 服务 5. 等待 3-5 分钟,HTTP 服务将配置完成并生效 ## 步骤三:访问您的 HTTP 服务 HTTP 服务创建完成后,您可以通过以下方式访问: 1. **通过命令行访问**: ```sh curl https://{您的域名}/hello # 返回结果:Hello World! ``` 2. **通过浏览器访问**: 直接在浏览器地址栏输入 `https://{您的域名}/hello` ![浏览器访问效果](https://qcloudimg.tencent-cloud.cn/raw/9144a724e4fa6a106ed3449c0124f5ce.png) > 📝 注意:HTTP 服务的完整地址由「域名」+「触发路径」组成。如果您使用了自定义域名,请确保已完成域名备案和 HTTPS 证书配置。 更多访问云函数相关细节请参考:[HTTP 访问云函数](/service/access-cloud-function)。 --- ## 路由配置 # 路由配置 CloudBase HTTP 访问服务提供灵活的路由配置能力,让您可以将请求精准路由至云托管、云函数、静态托管等多种后端资源,实现统一的请求分发管理。 ## 路由匹配规则 路由配置由两个核心要素组成:**域名(domain)**和**路径(path)**。系统根据这两个要素按照特定优先级进行匹配。 ### 匹配优先级 1. **域名匹配**: - 精确匹配(如 `example.com` )优先级高于通配符匹配(如 `*` ) - 支持使用通配符 `*` 匹配任意域名 2. **路径匹配**: - 遵循**最长匹配原则**,系统会优先选择与请求路径重合度最高的规则 - 路径匹配是前缀匹配,如 `/bar` 可以匹配 `/bar/xxx` ### 匹配流程图 ![路由匹配流程](https://main.qcloudimg.com/raw/0604cace255dfb9a717c50a26318509a.jpg) ## 路由匹配示例 以下表格展示了一组路由规则配置: | 域名 | 路径 | 关联资源 | |------|------|----------| | * | / | FunctionA | | * | /bar | FunctionB | | | /bar | FunctionC | | foo.com | / | FunctionD | | foo.com | /bar | FunctionE | | foo.com | /bar/baz | FunctionF | ### 请求匹配结果 根据上述配置,不同的请求会被路由到不同的资源: | 访问地址 | 匹配的资源 | 匹配原因 | |---------|-----------|---------| | /xxx | FunctionA | 域名通过通配符 `*` 匹配,路径 `/xxx` 匹配前缀 `/` | | /bar | FunctionC | 精确匹配默认域名,路径精确匹配 `/bar` | | /bar/xxx | FunctionC | 精确匹配默认域名,路径 `/bar/xxx` 匹配前缀 `/bar` | | foo.com/xxx | FunctionD | 精确匹配域名 foo.com,路径 `/xxx` 匹配前缀 `/` | | foo.com/bar | FunctionE | 精确匹配域名 foo.com,路径精确匹配 `/bar` | | foo.com/bar/xxx | FunctionE | 精确匹配域名 foo.com,路径 `/bar/xxx` 匹配前缀 `/bar` | | foo.com/bar/baz | FunctionF | 精确匹配域名 foo.com,路径精确匹配 `/bar/baz` (最长匹配原则) | --- ## 自定义CDN # 自定义CDN 进入[环境配置/自定义CDN](https://tcb.cloud.tencent.com/dev?#/env/customize-cdn), 进行自定义CDN配置 允许您将云存储中的静态资源(如图片、视频、文档)通过自定义CDN网络快速分发到全球用户。相比默认CDN,此方案可结合云存储低成本特性与CDN精准缓存能力,实现更低延迟、更高性价比的资源加速。 ### 核心优势 * **灵活控制** 如云开发默认的CDN无法满足个性化需求,可以根据实际应用场景,灵活定制 * **极速访问** 全球CDN节点就近响应用户请求,降低延迟。 * **成本优化** 减少源站带宽消耗,云存储流量费用下降。 * **高可用性** CDN自动处理故障节点切换,保障服务连续性。 :::tip 目前仅支持腾讯云CDN ::: ### 配置指南 #### 前置条件 * 已有一个完成备案的自定义域名。 * 确保存储桶已配置公开访问权限。 * 已开通腾讯云CDN服务。 #### 操作步骤 1. 访问云开发平台,进入系统设置-自定义CDN页面 2. 绑定云存储与自定义域名 3. 自动为您创建一个可用的CDN域名 4. 确认CNAME状态是否正常 5. 点击开启自定义CDN域名 6. 上传内容至云存储 7. 测试CDN是否生效 ### 注意事项 #### CDN配置 您可前往[CDN控制台](https://console.cloud.tencent.com/cdn/domains)修改自动创建的域名配置。 #### CNAME配置 若CNAME校验未通过,将无法开启自定义CDN。请先参考文档[配置CNAME](https://cloud.tencent.com/document/product/228/3121)。 #### 计费 配置自定义CDN后,相关费用由腾讯云CDN收取,您可根据自己的实际情况购买相关套餐。参考[计费概述](https://cloud.tencent.com/document/product/228/2949)。 #### 小程序使用 小程序用户需配置request合法域名后使用。 * 登录微信公众平台,进入小程序管理后台。 * 在“管理”-“开发管理”中找到“服务器域名”选项。 * 在“request合法域名”中添加自定义CDN域名。 * 添加完成后,点击“确定”保存设置。 ![](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/0906ac62-6978-4f9e-b234-0464c14e6e64.png) #### 权限设置 如果您的云存储权限设置为**公有读**,请确认自定义CDN的高级设置中,防盗链功能为**关闭**状态,否则将会导致文件无法访问。 ![](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/48dea873-f32a-4080-887f-b9768a04a196.png) ![](https://cloudcache.tencent-cloud.com/qcloud/ui/static/static_source_business/c1a55333-8518-4f5b-90f7-b2c4bd474299.png) --- ## 图片处理 # 图片处理 云开发提供图片处理能力,目前可支持图片格式转换、缩略、缩放、裁剪功能。 :::tip 提示 该能力正在内测中,您可单击 [**立即申请**](https://cloud.tencent.com/apply/p/8jv0oyqg9uo) 开通使用。 ::: ## 使用方式 ### 步骤1:新建样式 进入**云存储** > [**图片处理**](https://console.cloud.tencent.com/tcb/storage/index?tabId=ci) 页面,开通图片处理能力,单击**新建样式**,创建您所需要的样式,目前可供选择四种基本样式处理: #### 不缩略 该处理能力可以进行图片格式转换,支持的图片转换格式有:JPG、BMP、GIF、PNG、WEBP。 ![](https://main.qcloudimg.com/raw/8f5e93efe2fa86483889345a2de4fe21.png) #### 缩略和裁剪 该处理能力可以进行图片缩略后再进行裁剪,同时支持支持图片格式转换,图片转换格式有:JPG、BMP、GIF、PNG、WEBP。 ![](https://main.qcloudimg.com/raw/eaf5a1c9fe9384f98717984903590431.png) #### 只裁剪 该处理能力可以指定裁剪图片的位置区域,同时支持支持图片格式转换,图片转换格式有:JPG、BMP、GIF、PNG、WEBP。 ![](https://main.qcloudimg.com/raw/e1fa501f0678962b66cc54ad5d9f04f8.png) #### 只缩略 该处理能力可以进行图片缩略,同时支持支持图片格式转换,图片转换格式有:JPG、BMP、GIF、PNG、WEBP。 ![](https://main.qcloudimg.com/raw/7e63441b588f51e82f4280e3186c0e78.png) ### 步骤2:样式拼接 通过云存储内图片的下载链接拼接设定好的样式,从而实现基础图片处理。 1. 进入**云存储** > [**文件管理**](https://console.cloud.tencent.com/tcb/storage/index?tabId=file) 页面,单击**复制临时链接**进行图片链接的复制。 ![](https://main.qcloudimg.com/raw/a96cb0ac82da5144e982fba366576333.png) 1. 进行样式拼接,可以有两种拼接方式: - URL + '?' + 样式描述,即 **https://域名/文件名称 + '?' + 样式描述**。 例如:`https://XX.tcb.qcloud.la/demo.png?imageMogr2/thumbnail/!50px` 或者:`https://XX.tcb.qcloud.la/demo.png?imageMogr2/thumbnail/!50px&sign=3e63ac&t=1629` - URL + '/' + 样式名,即 **https://域名/文件名称 + '/' + 处理样式名**。 例如:`https://XX.tcb.qcloud.la/demo.png/style` 或者:`https://XX.tcb.qcloud.la/demo.png/style?sign=3e63ac&t=1629` > 注意:该方式仅适用于存储权限配置为公有读时有效。 1. 在浏览器中输入拼接后的 URL,即可访问处理后的图片,也可直接使用拼接后的 URL,实现客户端访问处理后的图片。 --- ## CLI 工具管理文件 # CLI 工具管理文件 您可以使用 CloudBase CLI 命令行界面交互工具,非常方便地管理项目的云存储资源,例如批量上传/下载文件/文件夹,获取文件访问链接与信息,设置/获取云存储的权限等。 ## 使用 CLI 工具管理云存储 CloudBase CLI 工具提供了一系列的命令,帮助您高效地管理云存储资源。 ### 命令概览 * `download`: 下载云存储中的文件或文件夹到本地。 * `upload`: 将本地文件或文件夹上传到云存储。 * `delete`: 删除云存储中的文件或文件夹。 * `list`: 列出云存储中的文件或文件夹信息。 :::tip tcb 命令需要指定环境ID,因此命令后需要加上 `-e envId` 。 ::: ### 下载文件/文件夹 * `cloudPath` 为云存储内的相对根目录的路径,需要写完整路径 * `localPath` 为相对当前目录的本地文件夹路径 ```bash tcb storage download cloudPath localPath -e envId # 下载文件夹时,需要指定 --dir 参数 tcb storage download cloudPath localPath --dir -e envId ``` 例如以下命令,会将云存储根目录下的 **cloudbase** 目录中的所有文件,下载到本地执行命令所在目录的 **download** 目录中: ```bash tcb storage download cloudbase ./download --dir -e envId ``` ### 上传文件/文件夹 ```bash tcb storage upload localPath cloudPath -e envId ``` 当 CLI 检测到 **localPath** 为文件夹时,会自动上传文件内的所有文件,如果重复上传会覆盖。 当不传入 cloudPath,文件会上传到云端的根目录下,同时文件夹的层次结构会被保留,例如下面的命令会把项目根目录的 download 文件夹里的内容直接上传到云存储的根目录里,download 的子文件夹会成为云存储的二级目录。 ```bash tcb storage upload ./download -e envId ``` ### 删除文件/文件夹 ```bash # 删除文件 tcb storage delete cloudPath -e envId # 删除文件夹 tcb storage delete cloudPath --dir -e envId ``` ### 列出文件/文件夹信息 在不打开云开发控制台或网页控制台的情况下,您也可以通过 CloudBase CLI 工具了解云存储里的文件夹或文件的信息。 ```bash tcb storage list cloudPath -e envId ``` 例如您可以直接使用以下命令打印云存储根目录里的所有文件,其中二级目录里的文件会用路径的方式显示。 ## 更多信息 要获取更多关于 CloudBase CLI 工具的信息,请访问 [CloudBase CLI 命令行工具](/cli-v1/intro)。 --- ## COSBrowser 管理文件 # COSBrowser 管理文件 ## 说明 **COSBrowser** 是cos提供的对象存储本地化工具。使用 **COSBrowser** 可以对对象存储里面的内容方便的进行批量管理。 详细的 **COSBrowser** 说明可以见 [cos文档](https://cloud.tencent.com/document/product/436/11366) ## 第一步:获取密钥参数 1. 登录环境对应的腾讯云账号 2. 获取腾讯云账号的 **SecretId、SecretKey、appid** 在腾讯云控制台 [账号/访问管理/访问密钥](https://console.cloud.tencent.com/cam/capi) 中,创建新的api密钥,并记录保存好。另外注意使用的账号,是管理员账号、或者具备cos 管理权限的账号。 同时记录好 **appid** ![](https://qcloudimg.tencent-cloud.cn/raw/0c473e1fe3bdb2eab5c136ef7487478d.png) ## 第二步:获取桶参数 3. 登录 [云开发/云存储](https://tcb.cloud.tencent.com/dev?#/storage) 获取桶名 ![](https://qcloudimg.tencent-cloud.cn/raw/e5367e412e9dc083c2540a66c2097ee6.png) 4. 将获取到的桶名,拼接上 “-appid”,例如: ``` 桶名 test-8glifaws3cbexxxx appid 1255690679 ------------------------- 拼接后的桶名为 test-8glifaws3cbexxxx-1255690679 ``` ## 第三步:登录 COSBrowser 5. 登录 [COSBrowser](https://cosbrowser.cloud.tencent.com/login) 地域固定为 `ap-shanghai` ![](https://qcloudimg.tencent-cloud.cn/raw/f1b3c482fe1cf0fa12103dda717725bd.png) 6. 进入 COSBrowser 管理页面即可操作文件 ![](https://qcloudimg.tencent-cloud.cn/raw/b93168e48b70054517459b3f9ff54842.png) --- ## 云调用拓展 import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # 云调用拓展 云存储可以与云开发提供的云调用拓展服务产生联动,提供「存储+处理」一体化解决方案,您可以结合实际需要安装云开发相应的云调用能力,如图像处理、图像标签、图像盲水印、图像安全审核等。 您可以通过以下两种方式处理图片:为图像 URL 拼接参数进行单次处理、客户端和云函数端持久化图像处理。 ## 图像 URL 拼接参数 例如在安装了图像处理拓展能力的情况下,您可以直接拿云存储的 https 链接 (下载地址或临时链接)进行拼接,拼接之后的链接我们既可以在小程序、Web 网页里使用,也可以用于图床,例如原始图片下载地址为: ```xml https://786c-xly-xrlur-1300446086.tcb.qcloud.la/hehe.jpg?sign=b8ac757538940ead8eed4786449b4cd7&t=1591752049 ``` 下载地址后面拼接参数`&imageMogr2/thumbnail/!20p`,就可以将图片等比例缩小到原来的 20% 。 ```javascript //将图片等比例缩小到原来的20% https://786c-xly-xrlur-1300446086.tcb.qcloud.la/hehe.jpg?sign=b8ac757538940ead8eed4786449b4cd7&t=1591752049&imageMogr2/thumbnail/!20p ``` 更多案例如下: ```js const download_url = "https://786c-xly-xrlur-1300446086.tcb.qcloud.la/hehe.jpg?sign=b8ac757538940ead8eed4786449b4cd7&t=1591752049" //缩放宽度,高度不变,下面案例为宽度为原图50%,高度不变 download_url&imageMogr2/thumbnail/!50px //缩放高度,宽度不变,下面案例为高度为原图50%,宽度不变 download_url&imageMogr2/thumbnail/!x50p //指定目标图片的宽度(单位为px),高度等比压缩,注意下面的是x,不是px,p与x在拼接里代表着不同的意思 download_url&imageMogr2/thumbnail/640x //指定目标图片的高度(单位为px),宽度等比压缩: download_url&imageMogr2/thumbnail/x355 //限定缩略图的宽度和高度的最大值分别为 Width 和 Height,进行等比缩放 download_url&imageMogr2/thumbnail/640x355 //限定缩略图的宽度和高度的最小值分别为 Width 和 Height,进行等比缩放 download_url&imageMogr2/thumbnail/640x355r //忽略原图宽高比例,指定图片宽度为 Width,高度为 Height ,强行缩放图片,可能导致目标图片变形 download_url&imageMogr2/thumbnail/640x355! //等比缩放图片,缩放后的图像,总像素数量不超过 Area download_url&imageMogr2/thumbnail/150000@ //取半径为300,进行内切圆裁剪 download_url&imageMogr2/iradius/300 //取半径为100px,进行圆角裁剪 download_url&imageMogr2/rradius/100 //顺时针旋转90度 download_url&imageMogr2/rotate/90 //将jpg格式的原图片转换为 png 格式 download_url&imageMogr2/format/png //模糊半径取8,sigma 值取5,进行高斯模糊处理 download_url&imageMogr2/blur/8x5 //获取图片的基础信息,返回的是json格式,我们可以使用https请求来查看图片的format格式,width宽度、height高度,size大小,photo_rgb主色调 download_url&imageInfo ``` ## 持久化图像处理 安装拓展 SDK 到项目 ```js //Web端、管理端、云函数端等需安装 cloudbase/extension-ci 到项目 npm install --save @cloudbase/extension-ci@latest //微信小程序需要安装 cloudbase/extension-ci-wxmp 到项目 npm install --save @cloudbase/extension-ci-wxmp@latest ``` - 可能你的开发者工具会报以下错误:`https://786c-xly-xrlur-1300446086.pic.ap-shanghai.myqcloud.com 不在以下 request 合法域名列表中,请参考文档:https://developers.weixin.qq.com/miniprogram/dev/framework/ability/network.html`,这个要按照参考文档将链接加入到合法域名当中,不然不会生成图片; - `action` 是操作类型,它的值可以为:ImageProcess 图像处理,DetectType 图片安全审核,WaterMark 图片盲水印、DetectLabel 图像标签等; - `operations` 是图像处理参数。 ```js const extCi = require("@cloudbase/extension-ci"); const tcb = require("tcb-js-sdk"); const readFile = async function(file) { let reader = new FileReader(); let res = await new Promise(resolve => { reader.onload = function(e) { let arrayBuffer = new Uint8Array(e.target.result); resolve(arrayBuffer); }; reader.readAsArrayBuffer(file); }); return res; }; let file = document.getElementById("selectFile").files[0]; let fileContent = await readFile(file); ``` ```js const tcb = require("@cloudbase/node-sdk"); const app = tcb.init(); const extCi = require("@cloudbase/extension-ci"); tcb.registerExtension(extCi); async function process() { try { const opts = { rules: [ { fileid: "/image_process/tcbdemo.jpeg", rule: "imageMogr2/format/png", }, ], }; const res = await app.invokeExtension("CloudInfinite", { action: "ImageProcess", cloudPath: "tcbdemo.jpg", fileContent, operations: opts, }); console.log(res); return res; } catch (err) { console.log(err); } } ``` ## 参考 更多详细信息请参考: [云调用拓展能力](https://docs.cloudbase.net/extension/introduce.html) --- ## 概述 # 概述 CloudBase 云存储提供稳定、安全、低成本、简单易用的云端存储服务,支持任意数量和形式的非结构化数据存储,如图片、文档、音频、视频、文件等。 您可以通过控制台、CloudBase CLI、HTTP API、SDK 等方式将文件上传到云端存储空间内,并对云端文件进行**文件管理**、**权限管理**和**缓存设置**等。 ## 管理方式 CloudBase 云存储提供多种管理方式,您可以根据自己的需求选择最适合的方式: | 管理方式 | 特点 | 适用场景 | 优势 | | --- | --- | --- | --- | | [**控制台管理**](/storage/manage) | 图形化界面,可配置权限、缓存设置 | 日常管理 | 上手快速,可视化操作 | | [**SDK 管理**](/storage/sdk) | 可集成到应用中 | 应用程序集成 | 灵活性高,可定制化程度高,适合集成到应用中 | | [**CLI 工具管理**](/storage/cli) | 命令行操作,支持批量处理 | 自动化脚本、批量处理 | 高效批量操作,适合自动化部署 | | [**cosBrowser**](/storage/cosbrowser) | 图形化界面,支持批量处理 | 频繁文件管理 | 结合了图形界面的便捷性和批量操作的高效性 | 根据您的具体需求和使用场景,选择合适的管理方式可以显著提高工作效率。例如,开发阶段可以使用 SDK,运维阶段可以使用 CLI 工具,而日常管理则可以使用控制台或 cosBrowser。 ## 主要特性 ### 默认支持 CDN 加速 云存储无需进行繁杂的配置,默认支持 CDN 加速,并提供免费的 CDN 域名。CDN 会将云存储的内容分发至最接近用户的节点,直接由服务节点快速响应,可以有效降低用户访问延迟。 ### 身份验证集成 CloudBase 云存储与 CloudBase 用户身份验证无缝集成,您可以结合用户身份认证和安全规则对云存储里的文件设置访问权限,例如云存储的文件只对已登录用户公开或仅限使用微信登录的用户访问等。 ### 高可扩展性 CloudBase 云存储可以与 CloudBase 其它多种服务配合使用,例如: * 将文件的 fileID 存储到数据库; * 配合 CloudBase 扩展能力使用,如图像安全审核、图像处理、图像标签、图像盲水印等。 --- ## 控制台管理文件 # 控制台管理文件 本文档将指导您如何通过云开发控制台对云存储进行全面管理,包括文件管理、权限设置和缓存配置等核心功能。 ## 快速访问 您可以通过 [云开发控制台-云存储](https://tcb.cloud.tencent.com/dev?#/storage) 页面进行所有云存储相关操作。 ## 文件管理 通过文件管理功能,您可以方便地查看和管理云存储中的所有文件: 1. 进入**文件管理**页面,您可以查看云存储空间中的所有文件列表 2. 单击文件名或「详情」按钮,即可查看文件的详细信息 ![文件管理界面](https://qcloudimg.tencent-cloud.cn/raw/6776fc43907bfc49c91deb61f676f47f.png) ## 权限设置 云存储权限设置允许您控制谁可以访问您的文件: 1. 访问 [权限设置](https://tcb.cloud.tencent.com/dev#/storage?tab=auth) 页面 2. 根据您的业务需求,选择合适的存储权限并保存 3. 您还可以通过 [自定义安全规则](/storage/security-rules) 实现更精细的权限控制 ![权限设置界面](https://qcloudimg.tencent-cloud.cn/raw/29f12cda7344ba59d4ce3dc1a3a7e83d.png) ## 缓存配置 ### 缓存配置概述 云存储的缓存配置功能可以帮助您优化文件访问性能和节省带宽成本: - 云存储内的文件默认启用 CDN 加速,您可以通过缓存配置控制 CDN 的过期规则 - 合理配置缓存时间可以有效提升命中率,降低回源率,节省带宽成本 - CDN 缓存资源的工作原理: - **未过期资源**:用户请求直接从 CDN 节点返回,提高访问速度 - **已过期资源**:CDN 节点需要向源站重新获取内容,然后缓存并返回给用户 ### 配置缓存规则 按照以下步骤配置云存储的缓存规则: 1. 访问 [缓存配置](https://tcb.cloud.tencent.com/dev?#/storage?tab=cache) 页面 2. 单击「编辑缓存配置」按钮,在默认配置基础上添加自定义缓存规则 > 默认配置为:所有文件缓存 2 分钟 3. 选择以下三种配置方式之一: | 配置方式 | 说明 | 示例 | |---------|------|------| | **按文件类型** | 针对特定后缀名的文件设置缓存时间 | `.png`、`.jpg`、`.php` | | **按文件夹** | 针对特定文件夹下的所有文件设置缓存时间 | `/images/`、`/static/` | | **按文件** | 针对特定文件或文件模式设置缓存时间 | `/test/abc/*.jpg` | 4. 配置规则说明: - 可填入多项配置,每项用分号(`;`)隔开 - 内容区分大小写 - 文件类型必须以`.`开头,文件夹必须以`/`开头 - 缓存时间设置为 0 时表示不缓存,所有请求将转发至源站 - 缓存时间最大值不能超过 365 天 5. 单击「保存」按钮完成配置,部署过程需等待约 5 分钟 :::tip 重要提示 配置部署过程中,若再次编辑缓存配置,将覆盖之前的配置。系统以最后一次部署结果为准。 ::: ### 缓存策略优先级 在配置多条缓存策略时,需要注意以下优先级规则: - 配置列表中**底部**的策略优先级高于**顶部**的策略 - 您可以通过拖动列表前的移动图标调整各策略的优先级 - 当多条策略同时匹配一个资源时,将以最后一次匹配的策略为准 #### 优先级示例 假设某域名配置了以下缓存规则: | 优先级 | 目标 | 缓存时长 | |-------|------|---------| | 5(最低) | 所有文件 | 2 分钟 | | 4 | .php .jsp .aspx | 0 秒 | | 3 | .jpg .png .gif | 300 秒 | | 2 | /test/*.jpg | 400 秒 | | 1(最高) | /test/abc.jpg | 200 秒 | 当访问资源 `www.test.com/test/abc.jpg` 时,匹配过程如下: 1. 匹配"所有文件"规则 → 命中,缓存时间为 2 分钟 2. 匹配".php .jsp .aspx"规则 → 未命中 3. 匹配".jpg .png .gif"规则 → 命中,缓存时间更新为 300 秒 4. 匹配"/test/*.jpg"规则 → 命中,缓存时间更新为 400 秒 5. 匹配"/test/abc.jpg"规则 → 命中,缓存时间最终确定为 200 秒 **最终结果**:该资源的缓存时间为 200 秒,因为最后一次匹配的规则优先级最高。 --- ## 管理端 SDK 管理 # 管理端 SDK 管理 您可以将管理端 manager-node SDK 部署在本地、云端服务器甚至云函数里对云存储空间内的文件进行批量上传、下载、删除、获取文件信息、获取临时链接以及设置文件权限等。 ## 上传文件 在管理端调用 uploadFile 方法进行单个文件的上传。 ```js const CloudBase = require("@cloudbase/manager-node"); const path = require("path"); const { storage } = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId" // 云开发环境ID,可在腾讯云云开发控制台获取 }); async function uploadFile() { await storage.uploadFile({ localPath: path.resolve("./data.txt"), cloudPath: "files/data.txt", onProgress: (data) => {} }); } uploadFile(); ``` ## 上传文件夹 在管理端调用 uploadDirectory 可以将文件夹内的文件批量上传到云存储空间。 ```js const CloudBase = require("@cloudbase/manager-node"); const path = require("path"); const { storage } = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId" // 云开发环境ID,可在腾讯云云开发控制台获取 }); async function uploadDirectory() { await storage.uploadDirectory({ localPath: path.resolve("./files"), cloudPath: "", onProgress: (data) => {} }); } uploadDirectory(); ``` ## 下载文件 在管理端调用 downloadFile 方法进行单个文件的下载。 ```js const CloudBase = require("@cloudbase/manager-node"); const path = require("path"); const { storage } = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId" // 云开发环境ID,可在腾讯云云开发控制台获取 }); async function downloadFile() { await storage.downloadFile({ cloudPath: "files/data.txt", localPath: path.resolve("./data.txt") }); } downloadFile(); ``` ## 下载文件夹 在管理端调用 downloadDirectory 方法可以将云存储空间内指定文件夹下载到管理端指定文件夹。 ```js const CloudBase = require("@cloudbase/manager-node"); const path = require("path"); const { storage } = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId" // 云开发环境ID,可在腾讯云云开发控制台获取 }); async function downloadDirectory() { await storage.downloadDirectory({ cloudPath: "files/music", localPath: path.resolve("./music") }); } downloadDirectory(); ``` ## 删除文件 在管理端调用 deleteFile 方法进行单个或多个文件的批量删除。 ```js const CloudBase = require("@cloudbase/manager-node"); const { storage } = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId" // 云开发环境ID,可在腾讯云云开发控制台获取 }); async function deleteFile() { await storage.deleteFile(["files/data.txt", "uploads/logo.png"]); } deleteFile(); ``` ## 删除文件夹 在管理端调用 deleteDirectory 方法可以删除云存储空间内整个文件夹。 ```js const CloudBase = require("@cloudbase/manager-node"); const { storage } = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId" // 云开发环境ID,可在腾讯云云开发控制台获取 }); async function deleteDirectory() { await storage.deleteDirectory("files/"); } deleteDirectory(); ``` ## 获取文件信息 在管理端调用 getFileInfo 方法可以获取文件的大小、类型、修改时间、对象的实体标签 ETag 。 ```js const CloudBase = require("@cloudbase/manager-node"); const { storage } = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId" // 云开发环境ID,可在腾讯云云开发控制台获取 }); async function getFileInfo() { const info = await storage.getFileInfo("files/data.txt"); console.log(info); } getFileInfo(); ``` ## 列出文件夹内文件列表 在管理端调用 listDirectoryFiles 列出云存储空间内指定文件夹下的所有文件以及文件信息。 ```js const CloudBase = require("@cloudbase/manager-node"); const { storage } = new CloudBase({ secretId: "Your SecretId", secretKey: "Your SecretKey", envId: "Your envId" // 云开发环境ID,可在腾讯云云开发控制台获取 }); async function listDirectoryFiles() { const res1 = await storage.listDirectoryFiles("dir/data"); const res2 = await storage.listDirectoryFiles("dir/data", 20); const res3 = await storage.listDirectoryFiles("dir/data", 20, "dir/dat"); for (let item in res1) { console.log(item); } } listDirectoryFiles(); ``` ## 参考 管理端 SDK 还可以获取文件临时链接、获取/设置文件存储权限,更多详细信息请参考: [管理端 manager-node sdk ](http://localhost:5000/api-reference/manager/node/introduction.html) --- ## SDK 管理文件 import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # SDK 管理文件 CloudBase 云存储提供了完整的文件管理功能,包括上传、下载、删除、复制文件以及获取临时链接等操作。本文将详细介绍如何使用这些功能以及相关注意事项。 ## 上传文件 您可以上传任意数量、格式的文件至 CloudBase 云存储,也可以自定义文件、目录的路径和名字。 默认情况下,只有通过了 [CloudBase 身份验证](/authentication-v2/auth/introduce) 的用户才可以向云存储空间上传/删除文件,因此在用户端上传文件时需先进行登录认证。 :::tip 提示 您也可以使用 [自定义安全规则](/storage/security-rules),为云存储设置更宽松或更严格的读写权限。 ::: 使用 SDK 可以向云存储空间上传文件,并返回该文件全局唯一标识 **fileID**。 ```js //第一步,引入 Web SDK, import tcb from "@cloudbase/js-sdk"; //第二步,初始化 const app = tcb.init({ env: "your-env-id", }); /** 第三步,登录认证流程,此处代码略,请参考: https://docs.cloudbase.net/authentication-v2/auth/introduce */ app .uploadFile({ // 云存储的路径 cloudPath: "dirname/filename", // 需要上传的文件,File 类型 filePath: document.getElementById("file").files[0], }) .then((res) => { // 返回文件 ID console.log(res.fileID); }); ``` ```js //需先使用 wx.cloud.init 初始化,小程序端无需再引入 SDK ,且免鉴权 wx.cloud .uploadFile({ cloudPath: "example.png", // 上传至云端的路径 filePath: "", // 小程序临时文件路径,需结合小程序相关 API 获取 }) .then((res) => { // 返回文件 ID console.log(res.fileID); }); ``` ```js const tcb = require("@cloudbase/node-sdk"); const fs = require("fs"); const app = tcb.init(); app .uploadFile({ cloudPath: "path/test.jpg", fileContent: fs.createReadStream("test.jpg"), }) .then((res) => { // 返回文件 ID console.log(res.fileID); }); ``` :::tip 提示 - 上传时文件名需要符合 [文件名规范](#文件名命名限制); - cloudPath 为云存储文件或文件夹的相对根目录的路径,为 **目录/文件名** 的形式,cloudPath 不需要以 `/` 开头; - 如果将文件上传至同一路径则是覆盖写,默认情况下,不允许 A 用户覆盖写 B 用户的文件。 ::: ## 下载文件 默认情况下,CloudBase 云存储内的文件对所有用户公开可读。 :::tip 提示 您也可以使用 [自定义安全规则](/storage/security-rules),为云存储设置更宽松或更严格的读写权限。 ::: 使用 SDK 可以下载云存储空间里的文件,调用时只需传入云存储文件全网唯一的 fileID 。 ```js //第一步,引入 Web SDK, import tcb from "@cloudbase/js-sdk"; //第二步,初始化 const app = tcb.init({ env: "your-env-id", }); /** 第三步,登录认证流程,此处代码略,请参考: https://docs.cloudbase.net/authentication-v2/auth/introduce */ app .downloadFile({ fileID: "cloud://a/b/c", }) .then((res) => { console.log(res); }); ``` ```js // 需先使用 wx.cloud.init 初始化,小程序端无需再引入 SDK ,且免鉴权 wx.cloud .downloadFile({ fileID: "cloud://a/b/c", // 文件 ID }) .then((res) => { // 返回临时文件路径 console.log(res.tempFilePath); }); ``` ```js const tcb = require("@cloudbase/node-sdk"); const app = tcb.init({ env: "your-env-id", }); app .downloadFile({ fileID: "cloud://a/b/c", }) .then((res) => { // fileContent 类型为 Buffer console.log(res.fileContent); }); ``` :::tip 提示 如果您需要在浏览器中可以直接下载云存储里的文件,或将云存储作为图床,可以使用文件的**下载地址**或[获取文件临时链接](#获取临时链接)。 ::: ## 删除文件 默认情况下,只有通过了 [CloudBase 身份验证](/authentication-v2/auth/introduce) 的用户才可以向云存储空间上传/删除文件,因此在用户端删除文件时需先进行登录认证。 :::tip 提示 - 单次调用最多可以删除 50 个文件,更多需分批处理; - 默认情况下,只有该文件的上传创建者和管理员才有权删除相应的文件,不允许 A 用户删除 B 用户的文件; - 您也可以使用 [自定义安全规则](/storage/security-rules),为云存储设置更宽松或更严格的读写权限。 ::: 使用 SDK 调用 deleteFile 方法可以删除云存储空间单个或多个指定文件。 ```js //第一步,引入 Web SDK, import tcb from "@cloudbase/js-sdk"; //第二步,初始化 const app = tcb.init({ env: "your-env-id", }); //第三步,登录认证,下面非完整代码,需选择登录方式,具体可以参考「快速开始」-「登录与用户案例」 const auth = app.auth({ persistence: "local", //用户显式退出或更改密码之前的30天一直有效 }); app .deleteFile({ fileList: ["cloud://a/b/c", "cloud://d/e/f"], }) .then((res) => { console.log(res.fileList); }); ``` ```js //需先使用 wx.cloud.init 初始化,小程序端无需再引入 SDK ,且免鉴权 wx.cloud .deleteFile({ fileList: ["cloud://a/b/c", "cloud://d/e/f"], }) .then((res) => { console.log(res.fileList); }); ``` ```js const tcb = require("@cloudbase/node-sdk"); const app = tcb.init(); app .deleteFile({ fileList: ["cloud://a/b/c", "cloud://d/e/f"], }) .then((res) => { console.log(res.fileList); }); ``` ## 复制文件 您可以通过 Node.js SDK 和 Open API 将云存储空间中的文件复制到指定路径,并通过参数设置达到移动文件的效果,该 API 支持批量复制。API 文档参考: - [Node.js SDK 复制文件](https://docs.cloudbase.net/api-reference/server/node-sdk/storage#copyfile) - [Open API 复制文件](https://docs.cloudbase.net/api-reference/openapi/storage#batchcopyfile) :::tip 说明 - 目标文件路径不能和源文件路径一致 - 不支持复制的过程中重命名,即复制前后文件名应保持一致 - 复制操作的执行受到存储桶权限、源文件和路径权限、目标文件和路径权限影响,执行复制操作不会改变文件原有权限 - 单次操作的文件数量不超过 50 个,更多需分批处理 ::: ```js // 初始化 sdk const tcb = require("@cloudbase/node-sdk"); const app = tcb.init({ env: "xxx", // 填入环境 ID }); const path = "a.png"; // 填入源文件路径 const fileList = [ { srcPath: path, dstPath: `dst/${path}`, // 填入目标文件路径 removeOriginal: true, // 复制后删除源文件,等效为移动文件 }, ]; const result = await app.copyFile({ fileList, }); ``` ## 文件名命名限制 在使用 CloudBase 云存储时,文件名需要遵循以下规则: - 不能为空 - 不能以/开头 - 不能出现连续/ - 编码长度最大为 850 个字节 - 推荐使用大小写英文字母、数字,即[a-z,A-Z,0-9]和符号 -,!,\_,.,\* 及其组合 - 不支持 ASCII 控制字符中的字符上(↑),字符下(↓),字符右(→),字符左(←),分别对应 CAN(24),EM(25),SUB(26),ESC(27) - 如果用户上传的文件或文件夹的名字带有中文,在访问和请求这个文件或文件夹时,中文部分将按照 URL Encode 规则转化为百分号编码。 - 不建议使用的特殊字符: ` ^ " \ { } [ ] ~ % # \ > ```js //第一步,引入 Web SDK, import tcb from "@cloudbase/js-sdk"; //第二步,初始化 const app = tcb.init({ env: "your-env-id", }); //第三步,登录认证,下面非完整代码,需选择登录方式,具体可以参考「快速开始」-「登录与用户案例」 const auth = app.auth({ persistence: "local", //用户显式退出或更改密码之前的30天一直有效 }); app .getTempFileURL({ fileList: ["cloud://a/b/c", "cloud://d/e/f"], }) .then((res) => { // fileList 是一个有如下结构的对象数组 // [{ // fileID: 'cloud://webtestjimmy-5328c3.7765-webtestjimmy-5328c3-1251059088/腾讯云.png', // 文件 ID // tempFileURL: '', // 临时文件网络链接 // maxAge: 120 * 60 * 1000, // 有效期 // }] console.log(res.fileList); }); ``` ```js //需先使用 wx.cloud.init 初始化,小程序端无需再引入 SDK ,且免鉴权 wx.cloud .getTempFileURL({ fileList: ["cloud://a/b/c", "cloud://d/e/f"], }) .then((res) => { // fileList 是一个有如下结构的对象数组 // [{ // fileID: 'cloud://webtestjimmy-5328c3.7765-webtestjimmy-5328c3-1251059088/腾讯云.png', // 文件 ID // tempFileURL: '', // 临时文件网络链接 // maxAge: 120 * 60 * 1000, // 有效期 // }] console.log(res.fileList); }); ``` ```js const tcb = require("@cloudbase/node-sdk"); const app = tcb.init(); app .getTempFileURL({ fileList: ["cloud://a/b/c", "cloud://d/e/f"], }) .then((res) => { // fileList 是一个有如下结构的对象数组 // [{ // fileID: 'cloud://webtestjimmy-5328c3.7765-webtestjimmy-5328c3-1251059088/腾讯云.png', // 文件 ID // tempFileURL: '', // 临时文件网络链接 // maxAge: 120 * 60 * 1000, // 有效期 // }] console.log(res.fileList); }); ``` --- ## 基于用户的安全控制 # 基于用户的安全控制 存储安全规则结合用户身份验证可以实现身份校验能力,开发者可以根据用户身份信息进行精准的资源访问控制。 ## 用户身份认证 经过身份认证的用户发起请求时,系统会使用用户唯一 id `uid` 及用户登录方式 `loginType` 填充 `auth` 变量。当未经身份验证的用户发出请求时,`auth` 变量值为 `null`。 通过 `auth` 变量,可以用以下常用方式来根据身份对文件访问进行控制: - 公开:不判断 `auth` 值。 - 只对已登录用户公开:检查 `auth` 不为 `null`。 - 用户私有:检查 `auth.uid` 是否等于资源 `openid`。 - 仅对某种特殊的登录方式进行判断,限制匿名登录用户访问,检查 `auth.loginType` 不为 `ANONYMOUS` ### 公开 任何不考虑 `auth` 的规则均可被视为 `public` 规则,因为他不考虑用户的身份验证上下文,这些规则在呈现公开数据(静态资源内容)的场景下是很适用。 ```json { "read": "resource.openid != null" } ``` ### 对登录的用户开放 在某些情况下,您可能希望限制只有登录用户在可以访问用户数据。例如,登录用户才可以查看论坛中的讨论。由于所有未登录用户的 `auth` 变量为 `null`,因此可以设置如下规则: ```json { "read": "auth != null" } ``` ### 用户私有 `auth` 最常见的使用场景在为个人用户资源提供精细的访问控制,例如上传私人照片等。云存储文件中包含了文件所有者信息(用户唯一 id),在规则中可以如此限制: ```json { "read": "auth.uid == resource.openid", "write": "auth.uid == resource.openid" } ``` ### 对等不方式进行验证,限制匿名登录用户访问 在应用中可能希望对于不同登录方式的用户展现不同的内容,此时可以对 `auth.loginType` 进行验证,其值在以下枚举中取: | 枚举值 | 登录方式说明 | | ------------- | ------------ | | WECHAT_PUBLIC | 微信公众号 | | WECHAT_OPEN | 微信开放平台 | | ANONYMOUS | 匿名登录 | | EMAIL | 邮箱登录 | | CUSTOM | 自定义登录 | 若希望对匿名登录的用户展示有限的内容,则可通过如下规则限制: ```json { "read": "auth.loginType !== 'ANONYMOUS'" } ``` ### 完整示例 综上,在一个相册应用中,希望所有登录用户都可以上传,浏览广场图片,不允许未登录用户访问,单可以使用匿名登录访问,匿名身份下只可以浏览,不可上传,则可以对存储设置如下规则。 ```json { "read": "auth != null", "write": "auth.loginType != 'ANONYMOUS' && auth.openid == resource.openid" } ``` --- ## 云存储安全规则 # 云存储安全规则 安全规则是在基础权限控制基础上,更高级、灵活、可扩展的一种权限控制方式,由**身份验证**、**授权**和**安全规则表达式**三部分构成。 云存储安全规则可用于确定哪些人对云存储桶中存储的文件拥有读取和写入权限,也可用于文件中包含的元数据校验。 :::tip 提示 - 您可以在云开发控制台对云存储进行安全规则权限的设置,具体可以参考[控制台可视化管理](https://docs.cloudbase.net/storage/manage.html); - 云开发控制台和服务端始终有所有文件读写权限,安全规则的配置仅对客户端(小程序端、Web 等)发起的请求有效; - 修改更新安全规则,权限生效需要 1- 3 分钟,请耐心等待; - 发布之前,请务必评估您的规则,确保它们可以为您的应用提供所需的最高级别的安全性。如果发布应用时设置的是 public 规则,可能会导致您存储的数据遭到意外访问或未经授权的访问。 ::: ## 基础权限控制与云存储安全规则 云存储提供基础的权限控制,默认为“所有用户可读,仅创建者可读写”,基础权限控制都可以通过安全规则权限控制得到。 #### 所有用户可读,仅创建者及管理员可写 ```js { "read": true, "write": "resource.openid == auth.openid", // 登录方式为微信 "write": "resource.openid == auth.uid" // 登录方式为非微信 } ``` #### 仅创建者及管理员可读写 ```js { "read": "resource.openid == auth.openid", //登录方式为微信 "read": "resource.openid == auth.uid", // 登录方式为非微信 "write": "resource.openid == auth.openid", //登录方式为微信 "write": "resource.openid == auth.uid" // 登录方式为非微信 } ``` #### 所有用户可读,仅管理员可写 ```js { "read": true, "write": false } ``` #### 仅管理员可读写 ```js { "read": false, "write": false } ``` ## 身份验证 云存储安全规则结合集成的用户身份验证可以实现身份校验能力,开发者可以根据用户身份信息进行精准的资源访问控制。 当 C 端用户登录后,安全规则中 `auth` 变量会变成一个包含该用户唯一 ID(`auth.uid`)和登录方式(`auth.loginType`)的对象。反之用户未登录,则`auth`的值为 null。通过 `auth` 规则可以实现对每个用户的数据访问控制。 经过身份认证的用户发起请求时,系统会使用用户唯一 id `uid` 及用户登录方式 `loginType` 填充 `auth` 变量。 通过 `auth` 变量,可以用以下常用方式来根据身份对文件访问进行控制: - 公开:不判断 `auth` 值。 - 只对已登录用户公开:检查 `auth` 不为 `null`。 - 用户私有:检查 `auth.uid` 是否等于资源 `openid`。 - 仅对某种特殊的登录方式进行判断,限制匿名登录用户访问,检查 `auth.loginType` 不为 `ANONYMOUS` ## 授权 识别用户身份只是安全工作的一部分。在知道用户的身份后,开发者需要一种方法来控制该用户对云存储中的文件的访问权限。 云存储支持存储桶级别的授权规则,通过设置安全规则表达式可以对云存储空间内的所有文件的读写操作进行限制。 ## 安全规则表达式 安全规则表达式通过 `json` 来描述,允许在满足条件时执行 `read` 及 `write` 操作,示例配置如下: ```js { "read": boolean | condition expression string, } ``` `json` 配置的 `key`,是用户的**操作类型**,`value` 是一个表达式。当表达式执行结果的值是 `true` 的时候,用户的操作允许执行;否则,用户的操作则不被允许。 | 操作类型 | 说明 | 默认值 | | :------- | :----------------------- | :----- | | read | 读取文件,例如:download | false | | write | 上传/覆盖文件,删除文件 | false | 规则验证所依据的上下文通过 `auth`、`resource` 对象获得,其提供可验证身份的上下文信息(`auth.uid`)和对象所有权(`resource.openid`)等信息。 ```json { "read": "auth.uid == resource.openid", "write": "auth != null" } ``` ## 示例 #### 公开 任何不考虑 `auth` 的规则均可被视为 `public` 规则,因为他不考虑用户的身份验证上下文,这些规则在呈现公开数据(静态资源内容)的场景下是很适用。 ```json { "read": "resource.openid != null" } ``` #### 对登录的用户开放 在某些情况下,您可能希望限制只有登录用户在可以访问用户数据。例如,登录用户才可以查看论坛中的讨论。由于所有未登录用户的 `auth` 变量为 `null`,因此可以设置如下规则: ```json { "read": "auth != null" } ``` #### 用户私有 `auth` 最常见的使用场景在为个人用户资源提供精细的访问控制,例如上传私人照片等。云存储文件中包含了文件所有者信息(用户唯一 id),在规则中可以如此限制: ```json { "read": "auth.uid == resource.openid", "write": "auth.uid == resource.openid" } ``` #### 实际案例 在一个相册应用中,希望所有登录用户都可以上传,浏览广场图片,不允许未登录用户访问,单可以使用匿名登录访问,匿名身份下只可以浏览,不可上传,则可以对存储设置如下规则。 ```json { "read": "auth != null", "write": "auth.loginType != 'ANONYMOUS' && auth.openid == resource.openid" } ``` ## 参考 更多详细信息请参考: [安全规则](/rule/introduce)