diff --git a/docs/uniCloud/admin.md b/docs/uniCloud/admin.md index deb7da6caf3cfc586534c891e1d0d1b424d61d00..2efaed15b080a29c9a89a65476e43ece9b001b9c 100644 --- a/docs/uniCloud/admin.md +++ b/docs/uniCloud/admin.md @@ -1,5 +1,24 @@ # uniCloud Admin +## 文档修改 + +- 看完文档,还是不知道作为插件作者,怎么开发一个插件。作为用户,怎么导入一个插件 + >把你们之前做的某个功能,比如权限管理,作为插件,发布到市场。以这个例子为例,说明怎么开发插件,怎么导入插件 + +- 用表格表示菜单配置 + +新增页面,要讲清楚: +1. 可以新增普通的页面,在前端callfunction,后台搭配云函数操作 +2. 可以使用uni-clientdb,在前端直接操作数据库,后台配置db schema进行权限和格式校验 +3. 可以使用云函数单文件路由,在项目中默认包含了一个uni-cloud-router的单文件路由,也可以使用插件市场的其他单文件路由 + + +## 代码 + +1. 这里不应该是输入时校验,改成失焦时校验 +2. 这个界面不响应回车键 +3. 这里需要验证码啊,不然怎么商用? + ### 什么是uniCloud Admin uniCloud Admin,是基于uni-app和uniCloud的应用后台管理框架。 @@ -16,8 +35,7 @@ uniCloud Admin,是基于uni-app和uniCloud的应用后台管理框架。 - 顶部topWindow的设置:比如logo更换、右上角部分连接更换。详见项目根目录的`admin.config.js`文件 - 左侧leftWindow的菜单设置:菜单包括两类,一类是动态菜单,具备业务和权限功能,在数据库的`opendb-admin-menu`表中增加删除菜单;另一类是静态菜单,不会根据登录用户角色变化,在项目根目录的`admin.config.js`文件中配置 - 开发模式下的 debug 功能,帮助开发者及时发现报错和搜索错误信息,可在`admin.config.js`文件中配置 - -### PC 宽屏和移动端上的 UI 表现 +g### PC 宽屏和移动端上的 UI 表现
@@ -115,17 +133,50 @@ $top-window-text-color: #999; /* 文字颜色 */ 1. 通过 [admin.config.js](https://github.com/dcloudio/uni-template-admin/blob/master/admin.config.js) 配置侧边栏内容,侧边栏的菜单包括根据用户角色动态显示的动态菜单,和所有用户都能看到静态菜单。 +*菜单的属性* + +| 字段 | 类型 | 必填 | 描述 | +|:-|:-|:-|:-| +| \_id | Object ID | 是 | Id保持唯一 | +| name | String | 是 | 菜单文字 | +| icon | String | 否 | 菜单图标 | +| url | String | 否 | 菜单对应的页面链接(只有没有子菜单的菜单项可以配置) | +| children | Array | 否 | 子菜单,重复它的父菜单的数据结构 | + +静态菜单 secondaryMenus 配置如下: + ```js export default { // 侧边栏 sideBar: { // 配置静态菜单列表(放置在用户被授权的菜单列表下边) - secondaryMenus: [ - { - name: "404页面", - url: "/pages/error/404", - }, - ], + secondaryMenus: [{ + _id: 'demo', + name: '系统设置', + icon: 'el-icon-menu', + children: [{ + _id: 'table', + name: '用户', + url: '/pages/demo/table/table' + },{ + _id: 'table', + name: '角色', + url: '/pages/demo/table/table' + },{ + _id: 'table', + name: '权限', + url: '/pages/demo/table/table' + }] + }, { + _id: 'app', + name: '应用管理', + icon: 'el-icon-menu', + children: [{ + _id: 'table', + name: '表格', + url: '/pages/demo/table/table' + }] + }], }, }; ``` @@ -161,7 +212,7 @@ $menu-text-color-actived: #409eff; /* 菜单激活前景色 */ > [详情](https://uniapp.dcloud.io/uniCloud/uni-id?id=%e6%9d%83%e9%99%90%e8%a1%a8) 3. 菜单表 `opendb-admin-menu` | 字段 | 类型 | 必填 | 描述 | - | ---------- | --------- | ---- | ------- | + |:-|:-|:-|:-| | \_id | Object ID | 是 | 系统自动生成的 Id | | name | String | 是 | 菜单文字 | | icon | String | 否 | 菜单图标 | @@ -192,9 +243,13 @@ $menu-text-color-actived: #409eff; /* 菜单激活前景色 */ ### 新增页面 -在框架搭建好后,接下来就需要增加页面,实现功能,建议页面统一放在 ``pages`` 目录,以便管理。由于是云端一体的开发模式,简单的理解为,在前端实现页面和 *api 接口*,这里需要转换一下观念,api 也是在前端实现的。 +- 可以新增普通的页面,在前端callfunction,后台搭配云函数操作 +- 可以使用uni-clientdb,在前端直接操作数据库,后台配置db schema进行权限和格式校验 +- 可以使用云函数单文件路由,在项目中默认包含了一个uni-cloud-router的单文件路由,也可以使用插件市场的其他单文件路由 + +建议页面统一放在 ``pages`` 目录,以便管理。由于是云端一体的开发模式,简单的理解为,在前端实现页面和 *api 接口*,这里需要转换一下观念,api 也是在前端实现的。 -以登录功能为例,以下是代码片段,完整代码见项目源码: +以登录功能为例,这里使用的是 `可以新增普通的页面,在前端callfunction,后台搭配云函数操作` 和 `项目中默认的 uni-cloud-router 的单文件路由` 的方式新增页面,以下是代码片段,完整代码见项目源码: 1. 新增前端 vue 页面 @@ -282,9 +337,9 @@ module.exports = class UserService extends Service { ``` -### 关于uni-cloud-router的用法 - +### 关于 uni-cloud-router 的用法 +> [详情](https://uniapp.dcloud.io/uniCloud/uni-cloud-router) ### 云函数 @@ -292,13 +347,6 @@ module.exports = class UserService extends Service { > [详情](https://uniapp.dcloud.io/uniCloud/uni-clientDB) -### admin 自带的组件 - -- sidebar-item - - -### 怎么开发一个插件 - ### 使用三方组件库 uniCloud Admin支持所有三方的Vue UI库,包括elementUI等非uni-app的UI库,但注意这些for h5的ui库只能在浏览器中使用,无法适配App和小程序,按如下操作。 diff --git a/docs/uniCloud/uni-cloud-router.md b/docs/uniCloud/uni-cloud-router.md new file mode 100644 index 0000000000000000000000000000000000000000..1c9c74f2a27140687a8aa57a47a2f1f9e669ae8e --- /dev/null +++ b/docs/uniCloud/uni-cloud-router.md @@ -0,0 +1,270 @@ +# uni-cloud-router + +> 基于 koa 风格的 uniCloud 云函数路由库,同时支持 uniCloud 客户端及 URL 化访问 + +--- + +- [云函数端](#云函数端) + - [安装](#安装) + - [目录结构](#目录结构) + - [控制器(Controller)](#控制器controller) + - [如何编写 Controller](#如何编写-controller) + - [获取请求参数](#获取请求参数) + - [调用 Service](#调用-service) + - [定制 URL 化返回的状态码](#定制-url-化返回的状态码) + - [服务(Service)](#服务service) + - [使用场景](#使用场景) + - [如何编写 Service](#如何编写-service) + - [使用 Service](#使用-service) + - [中间件(Middleware)](#中间件middleware) + - [开发中间件](#开发中间件) + - [使用中间件](#使用中间件) + - [Context](#context) + - [获取方式](#获取方式) +- [客户端](#客户端) + - [发送请求](#发送请求) + - [返回结果](#返回结果) + +## 云函数端 + +### 安装 + +```bash +npm install --save uni-cloud-router +``` + +### 目录结构 + +```bash +├── package.json +├── index.js // 云函数入口文件 +├── config.js // 用于配置 router 应用根目录、中间件等 +├── controller // 用于解析用户的输入,处理后返回相应的结果 +| ├── user.js +├── service (可选) //用于编写业务逻辑层,建议使用 +| ├── user.js +``` + +```js +// index.js (通常无需改动) +const Router = require('uni-cloud-router').Router // 引入 Router +const router = new Router(require('./config.js')) // 根据 config 初始化 Router +exports.main = async (event, context) => { + return router.serve(event, context) // 由 Router 接管云函数 +} +``` + +```js +// config.js +module.exports = { + debug: true, // 调试模式时,将返回 stack 错误堆栈 + baseDir: __dirname, // 必选,应用根目录 + middleware: [], // 自定义中间件 +} +``` + +```js +// controller/user.js +const uniID = require('uni-id') +const Controller = require('uni-cloud-router').Controller +// 必须继承 Controller +module.exports = class UserController extends Controller { + async login() { + const { username, password } = this.ctx.data // 获取请求参数 + // 使用 uni-id 登录 + return uniID.login({ + username, + password, + }) + } +} +``` + +### 控制器(Controller) + +负责解析用户的输入,处理后返回相应的结果。 + +推荐 Controller 层主要对用户的请求参数进行处理(校验、转换),然后调用对应的 service 方法处理业务,得到业务结果后封装并返回: + +1. 获取用户传递过来的请求参数。 +2. 校验、组装参数。 +3. 调用 Service 进行业务处理,必要时处理转换 Service 的返回结果,让它适应用户的需求。 +4. 将结果响应给用户。 + +#### 如何编写 Controller + +所有的 Controller 文件都必须放在 `controller` 目录下,可以支持多级目录,访问的时候可以通过目录名级联访问。 + +```js +// controller/post.js +const Controller = require('uni-cloud-router').Controller +// 必须继承 Controller 类 +module.exports = class PostController extends Controller { + async create() { + const { ctx, service } = this + // 校验参数 + ctx.validate({ + title: { type: 'string' }, + content: { type: 'string' }, + }) + // 组装参数 + const author = ctx.auth.uid + const post = Object.assign(ctx.data, { author }) + // 调用 Service 进行业务处理 + return service.post.create(post) + } +} +``` + +定义的 Controller 类,会在每一个请求访问时实例化一个全新的对象,会有下面几个属性挂在 `this` 上。 + +- `this.ctx`:当前请求的上下文对象的实例,通过它我们可以拿到各种便捷属性和方法。 +- `this.service`:应用定义的 service,通过它我们可以访问到抽象出的业务层,等同于 `this.ctx.service`。 +- `this.db`:等同于 `uniCloud.database()`。 +- `this.curl`:等同于 `uniCloud.httpclient.request`。 +- `this.throw`:抛出异常信息,等同于 `this.ctx.throw`。 + +#### 获取请求参数 + +通过在 Controller 上绑定的 Context 实例的 data 属性,获取请求发送过来的参数 + +```js +class PostController extends Controller { + async listPosts() { + const data = this.ctx.data + // { + // username: 'demo', + // password: 'demo', + // } + } +} +``` + +#### 调用 Service + +通过 Service 层进行业务逻辑的封装,不仅能提高代码的复用性,同时可以让业务逻辑更好测试。 + +Controller 中可以调用任何一个 Service 上的任何方法,同时 Service 是懒加载的,只有当访问到它的时候才会去实例化它。 + +```js +class PostController extends Controller { + async create() { + const { ctx, service } = this + const author = ctx.auth.uid + const post = Object.assign(ctx.data, { author }) + // 调用 service 进行业务处理 + return service.post.create(post) + } +} +``` + +Service 的具体写法,请查看 [Service](#服务service) 章节。 + +#### 定制 URL 化返回的状态码 + +```js +class PostController extends Controller { + async create() { + // 设置状态码为 201 + this.ctx.status = 201 // 仅当使用 HTTP/HTTPS 请求时生效 + } +} +``` + +### 服务(Service) + +业务逻辑封装的一个抽象层,有以下几个好处: + +- 保持 Controller 中的逻辑更加简洁。 +- 保持业务逻辑的独立性,抽象出来的 Service 可以被多个 Controller 重复调用。 +- 将逻辑和展现分离,更容易编写测试用例。 + +#### 使用场景 + +- 复杂数据的处理,比如要展现的信息需要从数据库获取,还要经过一定的规则计算,才能返回用户显示。或者计算完成后,更新到数据库。 +- 第三方服务的调用,比如 微信模板消息推送 等。 + +#### 如何编写 Service + +所有的 Service 文件都必须放在 `service` 目录下,可以支持多级目录,访问的时候可以通过目录名级联访问。 + +```js +// service/post.js +const Service = require('uni-cloud-router').Service +// 必须继承 Service +module.exports = class PostService extends Service { + async create(data) { + return this.db.add(data) + } +} +``` + +定义的 Service 类是懒加载的,只有当访问到它的时候才会去实例化它,会有下面几个属性挂在 `this` 上。 + +- `this.ctx`:当前请求的上下文对象的实例,通过它我们可以拿到各种便捷属性和方法。 +- `this.service`:应用定义的 service,通过它我们可以访问到抽象出的业务层,等同于 `this.ctx.service`。 +- `this.db`:等同于 `uniCloud.database()`。 +- `this.curl`:等同于 `uniCloud.httpclient.request`。 +- `this.throw`:抛出异常信息,等同于 `this.ctx.throw`。 + +#### 使用 Service + +[在 Controller 中调用 Service](#调用-service) + +### 中间件(Middleware) + +在路由请求前,后添加处理逻辑,实现一些特定功能,如:用户登录,权限校验等 + +#### 开发中间件 + +与 koa 保持一致,参考:[koa 中间件](https://demopark.github.io/koa-docs-Zh-CN/guide.html) + +```js +// middleware/auth.js +const uniID = require('uni-id') +module.exports = (options) => { + // 初始化 uniID 配置 + uniID.init(options) + // 返回中间件函数 + return async function auth(ctx, next) { + // 校验 token + const auth = uniID.checkToken(ctx.event.uniIdToken) + if (auth.code) { + // 校验失败,抛出错误信息 + throw { code: auth.code, message: auth.message } + } + ctx.auth = auth // 设置当前请求的 auth 对象 + await next() // 执行后续中间件 + } +} +``` + +示例: + +- [uni-id 校验 token 中间件](https://github.com/dcloudio/uni-template-admin/blob/master/cloudfunctions-aliyun/uni-admin/middleware/auth.js) +- [uni-id 校验 permission 中间件](https://github.com/dcloudio/uni-template-admin/blob/master/cloudfunctions-aliyun/uni-admin/middleware/permission.js) +- [云函数 URL 化中间件](https://github.com/fxy060608/uni-cloud-router/blob/master/src/middleware/http.ts) + +#### 使用中间件 + +1. 通过 config.js 配置 + +```js +const auth = require('./middleware/auth.js') // 引入 auth 中间件 +module.exports = { + debug: true, // 调试模式时,将返回 stack 错误堆栈 + baseDir: __dirname, // 指定应用根目录 + middleware: [ + [ + //数组格式,第一个元素为中间件,第二个元素为中间件生效规则配置 + auth({ tokenSecret: 'tokenSecret-demo' }), // 注册中间件 + { enable: true, ignore: /\/login$/ }, // 配置当前中间件生效规则,该规则表示以`/login`结尾的路由不会执行 auth 中间件校验 token + ], + ], +} +``` + +2. 中间件配置项 + +- enable 控制中间件是否开启。 +- match 设置 \ No newline at end of file