Unicloud的初始化
点击关联云服务空间
点击新建
先要实名认证
到 uni-Cloud 里面:新建服务空间
最后关联
云服务空间初始化
点击
下一步。
全选。其实就是把云函数和数据库上传的服务器上面
云函数:也可以手动一个一个上传
数据库:上传之后,还需要初始化。
-
记得使用正则表达式,除掉注释
生成创建默认匿名用户名的钩子函数
// 钩子函数示例 hooks/index.js https://blog.csdn.net/qq_18798149/article/details/149302312 function beforeRegister({ userRecord, clientInfo } = {}) { if(!userRecord.nickname) { /* Math.random() 生成随机数,例如:0.734628923 .toString(36):把数字转为 36进制字符串, 可能变成:0.k3j4ls9 .substring(3,9) 截取字符串的一部分。例如:k3j4ls 最终得到:匿名k3j4ls */ userRecord.nickname = "匿名"+Math.random().toString(36).substring(3,9) } return userRecord } module.exports = { beforeRegister }运行项目。之后先注册管理员账户
然他通过创建的管理员账户登录
客户端绑定相同的服务空间

UniCloud引入Element-Plus
安装
npm install element-plus --save在main.js里面导入和使用
// #ifdef VUE3 import { createSSRApp } from 'vue' import { createI18n } from 'vue-i18n' import ElementPlus from 'element-plus' // 导入element-plus import 'element-plus/dist/index.css' // 导入css样式 export function createApp() { const app = createSSRApp(App) const i18n = createI18n({ locale: lang, messages }) app.use(i18n) app.use(plugin) app.use(store) app.use(ElementPlus) // 使用 element-plus return { app } } // #endif设置语言模式为中文,因为Element Plus 组件默认使用英文
// #ifdef VUE3 import { createSSRApp } from 'vue' import { createI18n } from 'vue-i18n' import ElementPlus from 'element-plus' // 导入element-plus import 'element-plus/dist/index.css' // 导入css样式 import zhCn from 'element-plus/es/locale/lang/zh-cn' // 引入中文 export function createApp() { const app = createSSRApp(App) const i18n = createI18n({ locale: lang, messages }) app.use(i18n) app.use(plugin) app.use(store) // 使用 element-plus app.use(ElementPlus, { locale: zhCn, // 使用中文 }) return { app } } // #endif
开启多端运营数据统计
找到manifext.json,找到uni统计配置,开启2.0版本。前端上报周期默认是10秒,如果觉得太短,可以改成60秒。可以点击启动所有平台。也可以按需选取。
UniCloud admin 后台管理添加页面
创建新闻列表页面:
/pages/activity/news/list.vue在
Pages.json文件里面要确保有路径{ "path": "pages/activity/news/list", "style": { "navigationBarTitleText": "新闻列表" } }在 admin 后台管理里面添加这个页面
添加子菜单的时候需要添加路径

创建数据库表(Schema)
如何创建
创建Schema
选择模版
讲Schema上传至服务器,创建新的表格
去
https://unicloud.dcloud.net.cn/查看数据库表
Schema 内容解读
{
"bsonType": "object", // 声明这个Schema描述的是一个文档对象,这个值通常是固定的 "object",因为MongoDB的文档本身就是BSON对象
"required": [ // 必填字段
"user_id",
"title",
"content"
],
"permission": { // 数据库权限控制
"read": "doc.article_status == 1", // 只有发布的文章可以被读取,article_status=1 表示已发布
"create": false, // 客户端不能直接创建
"update": "doc.user_id == auth.uid", // 只能修改自己的文章
"delete": "doc.user_id == auth.uid" // 只能删除自己的文章
},
"properties": { // 表字段结构
"_id": { // MongoDB / uniCloud 自动生成, 不用手动写。
"description": "存储文档 ID(用户 ID),系统自动生成"
},
"user_id": {
"bsonType": "string", // 字段类型
"description": "文章作者ID, 参考`uni-id-users` 表", // 字段的 说明文字。不会影响数据库逻辑。
"foreignKey": "uni-id-users._id", // 表示 外键关系(关联表)。集合名.字段名。user_id 对应 uni-id-users 表的 _id
"defaultValue": { // 指定 字段的默认值。
"$env": "uid" // 当前登录用户ID
}
},
"title": {
"bsonType": "string",
"title": "标题",
"description": "标题",
"label": "标题",
"trim": "both"
},
"content": {
"bsonType": "string",
"title": "文章内容",
"description": "文章内容",
"label": "文章内容",
"trim": "right"
},
"excerpt": {
"bsonType": "string",
"title": "文章摘录",
"description": "文章摘录",
"label": "摘要",
"trim": "both"
},
"article_status": {
"bsonType": "int",
"title": "文章状态",
"description": "文章状态:0 草稿箱 1 已发布",
"defaultValue": 1,
"enum": [
{
"value": 0,
"text": "草稿箱"
},
{
"value": 1,
"text": "已发布"
}
]
},
"view_count": {
"bsonType": "int",
"title": "阅读数量",
"description": "阅读数量",
"defaultValue":50
},
"is_sticky": {
"bsonType": "bool",
"title": "是否置顶",
"description": "是否置顶",
"defaultValue":false
},
"avatar": {
"bsonType": "string",
"title": "封面大图",
"description": "缩略图地址",
"label": "封面大图",
"trim": "both",
"defaultValue":""
},
"publish_date": {
"bsonType": "timestamp",
"title": "发表时间",
"description": "发表时间",
"defaultValue": {
"$env": "now"
}
},
"publish_ip": {
"bsonType": "string",
"title": "发布文章时IP地址",
"description": "发表时 IP 地址",
"forceDefaultValue": {
"$env": "clientIP"
}
},
"last_modify_date": {
"bsonType": "timestamp",
"title": "最后修改时间",
"description": "最后修改时间",
"defaultValue": {
"$env": "now"
}
},
"last_modify_ip": {
"bsonType": "string",
"description": "最后修改时 IP 地址",
"forceDefaultValue": {
"$env": "clientIP" // 客户端ip
}
}
},
"version": "0.0.1" // schema版本
}
permission
在 uniCloud Schema 里,permission 用来定义 客户端访问数据库的权限规则。 它控制客户端能否对集合执行 CRUD(增删改查) 操作。
"permission": {
"read": "...",
"create": "...",
"update": "...",
"delete": "..."
}
权限值可以是:
true(允许)false(禁止)- 表达式(按条件控制)
对应四种操作:
| 权限 | 对应数据库操作 | 含义 |
|---|---|---|
| read | 查询数据 | 是否允许读取 |
| create | 新增数据 | 是否允许创建 |
| update | 修改数据 | 是否允许更新 |
| delete | 删除数据 | 是否允许删除 |
这些规则 只限制客户端(小程序 / H5 / App)。
云函数和**管理后台(admin)**默认不受限制。
read(读取权限)
控制 是否允许查询数据。
例如:"read": "doc.article_status == 1"
意思是:只有 article_status = 1 的文章可以被读取。
假设数据库:
{
"title": "文章1",
"article_status": 1
}
客户端查询:db.collection("article").get()
可以返回。但如果:
{
"title": "草稿",
"article_status": 0
}
客户端查询 不会返回这条数据。
常见 read 规则
只允许读取自己的数据:"read": "doc.user_id == auth.uid"
只允许登录用户读取:"read": "auth != null"
完全开放读取:"read": true
create(创建权限)
控制 客户端是否能新增数据。
例如:"create": true
客户端可以直接创建:
db.collection("article").add({
title:"hello",
content:"world"
})
如果是:"create": false
客户端创建会失败:permission denied
必须通过 云函数 创建。
常见 create 规则
只允许登录用户创建:"create": "auth != null"
只允许管理员创建:"create": "auth.role == 'admin'"
update(修改权限)
控制 客户端是否可以修改数据。
例如:"update": "doc.user_id == auth.uid"
意思是:只能修改自己创建的数据。
假设数据库:
{
"user_id": "1001",
"title": "文章"
}
如果当前用户:auth.uid = 1001
就可以执行:
db.collection("article").doc(id).update({
title:"新标题"
})
但如果用户:auth.uid = 2002
就会失败。
常见 update 规则
只允许作者修改:"update": "doc.user_id == auth.uid"
只允许管理员修改:"update": "auth.role == 'admin'"
禁止修改:"update": false
delete(删除权限)
控制 客户端是否可以删除数据。
例如:"delete": "doc.user_id == auth.uid"
- 意思:只能删除自己的数据。
如果文章作者是:user_id = 1001
- 只有
auth.uid = 1001的用户才能删除。
常见 delete 规则
只允许作者删除:"delete": "doc.user_id == auth.uid"
只允许管理员删除:"delete": "auth.role == 'admin'"
禁止删除:"delete": false
权限表达式中的常见变量
| 变量 | 含义 |
|---|---|
| doc | 当前数据库记录 |
| auth | 当前登录用户信息 |
| auth.uid | 当前用户ID |
| auth.role | 用户角色 |
| $env | 系统环境变量 |
例如:"update": "doc.user_id == auth.uid"
含义:当前用户 ID 必须等于 文档里的 user_id。
Uni-Cloud的访问来源
客户端(App / 小程序 / H5)
运行在 用户设备上的前端代码。
const db = uniCloud.database()
db.collection("article").get()
| 特点 | 说明 |
|---|---|
| 运行位置 | 用户设备 |
| 可信度 | 不可信 |
| 权限 | 受 permission 限制 |
| 身份 | 用户 token(auth.uid) |
云函数
运行在 uniCloud 云服务器上的后端代码。
exports.main = async (event, context) => {
const db = uniCloud.database()
return db.collection("article").add({
title: event.title
})
}
| 特点 | 说明 |
|---|---|
| 运行位置 | 云服务器 |
| 可信度 | 可信 |
| 权限 | 不受 permission 限制 |
| 身份 | 服务器身份 |
Admin 后台
uniCloud 提供的 管理后台系统,用于管理员管理数据库。
通常是:uni-admin、管理系统、运维后台
| 特点 | 说明 |
|---|---|
| 运行位置 | 服务器 / 管理系统 |
| 可信度 | 可信 |
| 权限 | 不受 permission 限制 |
| 身份 | 管理员 |
两种访问模式
模式 1:客户端直接访问数据库:这种方式会校验permission
客户端
↓
数据库
模式 2:客户端/Admin通过云函数访问数据库
客户端/Admin
↓
云函数
↓
数据库
身份不一样
直接访问数据库和通过云函数访问云数据库的本质区别:身份(身份上下文)不一样。
访问数据库的代码都是:
const db = uniCloud.database()
db.collection("article").get()
但是,运行的环境不一样
客户端运行时,代码码运行在:浏览器、小程序、App
请求流程:
客户端代码
↓
uniCloud 客户端 SDK
↓
uniCloud 网关
↓
数据库
请求里会自动带上:用户 token 和 client 标识
数据库识别为:source = client
于是执行:permission 校验
云函数运行时,代码运行在:uniCloud 服务器 ,环境是云函数 runtime
请求流程:
云函数代码
↓
uniCloud Server SDK
↓
数据库
请求里带的是:server 签名和云函数上下文
数据库识别为:source = server
于是:permission 不执行
bsonType
"bsonType": "" 指定 字段的数据类型。
因为 uniCloud 使用的是 MongoDB 数据库,MongoDB 存储的是 BSON(Binary JSON),所以这里用 bsonType。
常见类型:
| 类型 | 说明 | 示例 |
|---|---|---|
| string | 字符串 | “hello” |
| int | 整数 | 100 |
| double | 浮点数 | 3.14 |
| bool | 布尔 | true / false |
| object | 对象 | {name:”Tom”} |
| array | 数组 | [1,2,3] |
| timestamp | 时间戳 | 时间 |
| date | 日期 | Date |
$env
$env 表示 环境变量。uniCloud 会自动提供一些系统值。常见 $env:
| 变量 | 含义 |
|---|---|
| uid | 当前登录用户ID |
| now | 当前时间 |
| clientIP | 客户端IP |
| appid | 应用ID |
label 和title 属性
作用:label和title 是用于前端界面显示的字段标签,相当于字段的“显示名称”。
使用场景
"title": {
"bsonType": "string",
"title": "标题", // 主要用于表单显示
"label": "标题", // 主要用于表单显示
"description": "标题" // 详细说明
}
当您使用 uniCloud 的 schema2code 功能(自动生成前端页面)时,label 会被用于:
表单输入框的标签:
<!-- 自动生成的表单可能类似 --> <form> <label>标题</label> <!-- 这里显示的就是 label 的值 --> <input type="text" v-model="formData.title" /> </form>表格列的标题:
<!-- 列表页面中 --> <table> <thead> <tr> <th>标题</th> <!-- 这里也使用 label 的值 --> <th>作者</th> <th>发布时间</th> </tr> </thead> </table>搜索条件的名称:
<!-- 搜索区域 --> <div class="search"> <span>标题:</span> <!-- 搜索字段的显示名称 --> <input type="text" placeholder="请输入标题" /> </div>
| 属性名 | 核心作用 | 使用场景 |
|---|---|---|
title |
字段的显示名称,用于自动生成的表单标签和内部文档 。 | 告诉阅读 Schema 的人这个字段代表什么;在自动生成代码时,作为输入框前面的提示文字。 |
label |
与 title 功能几乎相同,也是用于前端的显示标签 。 |
在 schema2code 中,其优先级高于 title,但目标一致。 |
description |
字段的详细说明,用于开发者文档或作为输入框的占位提示 。 | 在自动生成的表单中,如果输入框没有专门配置,这里的描述通常会作为输入框内部的灰色提示文字。 |
trim 属性
作用:trim 用于自动处理字符串两端的空白字符(空格、制表符、换行符等)。这是一个数据清洗功能,在数据保存到数据库前自动执行。
可选值
"both":去除字符串两端的空白字符"left":只去除字符串左侧(开头)的空白字符"right":只去除字符串右侧(结尾)的空白字符- 不设置或不包含此属性:不进行任何trim操作
enum 的基本作用
enum 是 Schema 中一个非常实用的属性,它用于定义字段的“枚举类型”,即限定该字段只能取一组预定义的值。
数据验证
限制 article_status 字段只能取两个值:0(草稿箱)或 1(已发布),其他任何值都会被拒绝。
// ✅ 允许的值
{ article_status: 0 } // 草稿
{ article_status: 1 } // 已发布
// ❌ 不允许的值
{ article_status: 2 } // 错误,不在枚举范围内
{ article_status: "1" } // 错误,类型必须是 int
{ article_status: true } // 错误,类型错误
值-文本映射
"enum": [
{
"value": 0, // 实际存储在数据库中的值
"text": "草稿箱" // 对应的显示文本
},
{
"value": 1, // 实际存储在数据库中的值
"text": "已发布" // 对应的显示文本
}
]
当使用 uniCloud 的 schema2code 功能自动生成前端页面时,enum 属性会被智能地转换成合适的 UI 组件:
<!-- 根据 enum 自动生成的下拉选择框 -->
<template>
<view class="form-item">
<text class="label">文章状态</text>
<picker @change="onStatusChange" :value="statusIndex" :range="statusOptions" range-key="text">
<view class="picker">
{{ statusOptions[statusIndex].text || '请选择' }}
</view>
</picker>
</view>
</template>
<script>
export default {
data() {
return {
statusOptions: [
{ value: 0, text: '草稿箱' },
{ value: 1, text: '已发布' }
]
}
}
}
</script>
添加云对象
点击创建
点击云对象
编写云对象
let dbJQL = uniCloud.databaseForJQL() // databaseForJQL() 是 UniCloud 提供的 JQL(JavaScript Query Language)数据库引用 let {result} = require("utils"); module.exports = { /* 作用:在每个云函数方法执行前自动运行 功能:获取客户端信息(如用户IP、设备信息等)并重新初始化数据库连接 这样可以确保数据库操作能正确识别客户端上下文(如用户身份) */ _before: function() { // 通用预处理器 const clientInfo = this.getClientInfo(); dbJQL = uniCloud.databaseForJQL({ clientInfo }) }, async add(params = {}) { try { // 1. 生成随机浏览量 (50-100之间的随机数) const randomInt = Math.floor(Math.random() * 51) + 50; params.view_count = randomInt; // 2. 执行数据库添加操作 let { errCode, errMsg, id // 这里的 await 会等待数据库操作完成 } = await dbJQL.collection("zai-news-articles").add(params) // 只有等待上面的操作完成后,才会执行这里的代码 // 3. 检查返回结果 if (errCode !== 0) return result({ errCode: 400, errMsg: "error", custom: errMsg }); // 4. 成功返回 return result({ errCode: 0, errMsg: "success", data: { id } }); } catch (err) { return result({ errCode: 500, errMsg: "bug", custom: err }) } }, }点击运行本地云对象,生成测试
会有一个
admin-news.param.js的文件在admin的后台,找到uni-id的Token。如果不输入这个Token,无法校验通过数据库的permission。

在
admin-news.param.js的文件里面,模拟在admin后台发出请求const clientInfo = { clientIP: '127.0.0.1', uniIdToken: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiI2OWIwNGQyNmVlOTdlZjJlMzE3YmM3ZWYiLCJyb2xlIjpbImFkbWluIl0sInBlcm1pc3Npb24iOltdLCJ1bmlJZFZlcnNpb24iOiIxLjAuMTgiLCJpYXQiOjE3NzMzOTAyNTksImV4cCI6MTc3MzM5NzQ1OX0.6lAOesZa3WTJXQfsJAK5xwVRDhFiJnBl_Ig6PYO4SVI' } add({ title:"test123", content:"test123", })点击运行本地云对象,这个时候就可以执行了。
创建公共模块
创建公共模块
在
index.js文件里面写公共方法或者公共对象要使用公共模块的时候,需要进行关联
使用
require引入模块let {result} = require("utils"); // 引入公共模块对象
Client 客户端关联后台服务空间
关联后台服务空间
这个时候Client的服务空间就是admin的服务空间

跨域问题
启动的时候会有这么一条提示:
当前项目使用了uniCloud,为避免云函数调用跨域问题,建议在HBuilderX内置浏览器里调试。如使用外部浏览器需处理跨域,请将访问页面对应的IP或域名配置在要访问的云函数所在的服务空间的跨域配置内,详见:https://uniapp.dcloud.net.cn/uniCloud/publish.html#useinh5
但是,我实际操作是,如果在浏览器登录了uniCloud的账号,是完全不需要配置跨域的。