十六、编辑器服务端基础API开发
1、技术方案设计和基本功能开发
* 引言
- 需求指导设计,设计指导开发。无设计不开发。
* 标题
- 服务端技术方案设计 & 基础功能开发
* 将收获什么
- 服务端技术方案设计的方法
- B端和编辑器基本功能API
* 主要内容
- 技术方案设计
- 基本功能开发
* 关键词
- 技术方案设计文档(架构设计、接口设计、数据库设计)
* 学习方法
- 亲自写出来,无论是代码还是文档
* 注意事项
- 业务代码不会一行一行写
- 回顾一下之前的“整体架构设计”,各个项目之间的关系,以及和数据库之间的关系。
2、技术方案设计
* 引言
- 领导技术方案设计、评审技术方案设计,这就是架构师和基层程序员的区别之一。
* 主要产出
- 《biz-editor-server端技术方案》文档
* 主要内容
- 接口设计
- 选择Restful API,不是GraphQL
- 数据库设计
- server整体设计
* 注意事项
- 正视技术方案设计,设计不会浪费时间,只会节约时间
- GraphQL不是课程主线,不要跑偏
3、接口设计
* 引言
- 把server端当做一个黑盒,它将怎样与前端通讯?
* 功能范围
- B端,用户注册,作品管理,模板
- 编辑器,单个作品的内容获取、修改、预览和发布
* 功能拆分
- 用户信息
- 作品管理
- 模板
- 编辑器(发布和渠道,可以单独设计)
- 工具类
* 用户信息
- 获取手机短信验证码
- 登录(包含注册)
- 获取用户信息
- 修改用户信息
* 模板
- 首页推荐模板列表(搜索,分页)--不需要登录校验
- 获取单个模板信息--不需要登录校验
- 我的模板列表(搜索,分页)
* 作品管理
- 创建空白作品
- 复制作品(通过模板创建)PS:模板即作品,只是有一个标志而已,数据库设计时可以看出来
- 删除作品
- 恢复作品
- 转赠作品
- 我的作品列表(搜索,分页)
- 我的回收站列表(搜索,分页)
* 编辑器
- 设计时分开,但代码中可能会和作品管理写在一起,因为都是针对作品的。
~ 查询单个作品信息
~ 保存作品
~ 预览作品
~ 发布作品
~ 发布为模板
* 渠道
- 创建渠道
- 删除渠道
- 修改渠道名称
- 获取单个作品的所有渠道
* 工具类
- 上传图片
* 统一的输出格式
########
{
errno: 0, // 错误码,无错误则返回0
data: {...}, // 或者[...]
message: 'xxx'
}
########
- 留作业,设计每个接口的输入和输出,可使用第三方工具YAPI。
* 其他
- 作品统计,会用到单独的统计服务,不在这里出数据
- 预览作品,在h5-server中
* 小结
- 功能拆分
- 详细的接口设计
- 统一输出格式
4、Restful API vs GraphQL
* 引言
- 默认所有同学都已非常熟悉Restful API。而GraphQL大家可能比较陌生,会放慢节奏。
- 而GraphQL是和Restful API完全不同的两种设计和实现方式,
两者也尽量不要混用(虽然混用也能做到无bug)
* 什么是GraphQL
- GraphQL-Graph Query Language图查询语言。意思是擅长处理“图”数据结构的查询,
即多个数据对象,各个之间还有关联关系。
- 核心概念:
~ schema - 数据规范
~ rootValue - 数据源
- 代码演示,可参考中文官网。注意,在此不要深入进去,还是沿着课程主线走。
########
var express = require('express');
var graphqlHTTP = require('express-graphql');
var { buildSchema } = require('graphql');
// 使用GraphQL Schema Language创建一个schema
var schema = buildSchema(`
type Query {
hello: String,
}
`)
// root提供所有API入口端点相应的解析器函数
var rootValue = {
hello: () => {
return 'Hello world';
},
};
var app = express();
app.use('/graphql', graphqlHTTP({
schema: schema,
rootValue: rootValue,
graphiql: true,
}));
app.listen(4000);
console.log('Running a GraphQL API server at http://localhost:4000/graphql');
########
- 另外,虽然GraphQL主要用于查询,但它也支持输入和更新,参考官网input和Mutation。
课程就不在继续扩展了。
* GraphQL的应用场景
- 数据关系比较复杂。PS:和我们正好相反,我们是作品的数据结构复杂(前端编辑器复杂),
而数据实体之间的关系比较清晰。
- 前端查询需求多变,如果用Restful API会导致频繁地修改API,不灵活。
- 有一个独立的数据提供方,对接很多使用方,不能一一定制开发
* 如何选择
- 选择使用Restful API,放弃GraphQL。
- 并不匹配它的使用场景
- 考虑它的缺点:
~ 学习使用成本高,不如Restful API普及
~ 当数据结构复杂时,效率较低
~ 维护数据源和schema也比较复杂
* 小结
- GraphQL介绍
- 应用场景
- 选择Restful API
5、数据库设计
* 需要存储的数据
- 用户
- 项目/模板(包含项目内容,组件信息)
- 渠道
* 数据之间的关系
* 数据表设计
- 注意,使用sequelize和mongoose,会自动创建id、createdAt和updatedAt,无需再自己手动创建。
* 用户
* 作品/模板
* 渠道
* 作品内容
- 未发布
- 发布
########
{
// 页面的组件列表
components: [Object],
// 页面的属性,如页面背景图片
props: Object,
// 配置信息,如微信分享配置
setting: Object,
}
########
* 代码演示
- sequelize Model以及关联关系
- mongoose Schema和Model
* 小结
- 数据表设计
- 数据表的关系
- 代码演示
列 |
类型 |
注释 |
username |
varchar |
用户名,唯一 |
password |
varchar |
密码,保留字段,暂时用不到 |
phoneNumber |
varchar |
手机号 |
nickName |
varchar |
昵称 |
gender |
int |
性别(1男性,2女性,0保密) |
picture |
varchar |
用户头像 |
latestLoginAt |
date |
最后登录时间 |
isFrozen |
boolean |
用户是否冻结 |
列 |
类型 |
注释 |
uuid |
varchar |
uuid,h5 url中使用,隐藏真正的id,避免被爬 |
title |
varchar |
标题 |
desc |
varchar |
副标题 |
contentId |
varchar |
未发布内容id,内容存储在mongodb中 |
publishContentId |
varchar |
发布内容id,内容存储在mongodb中,未发布的为空 |
author |
varchar |
作者username,和用户表关联 |
coverImg |
varchar |
封面图片url |
isTemplate |
boolean |
是否模板 |
status |
int |
状态:0-删除,1-未发布,2-发布,3-强制下线 |
copiedCount |
int |
模板被使用的次数 |
lastestPublishAt |
date |
最近一次发布的时间 |
isHot |
boolean |
hot标签,模板使用 |
isNew |
boolean |
new标签,模板使用 |
orderIndex |
int |
排序参数 |
isPublic |
boolean |
模板是否公开显示 |
列 |
类型 |
注释 |
name |
varchar |
渠道名称 |
workId |
int |
作品id |
status |
int |
状态:0-删除,1-正常 |
6、server架构设计
* 引言
- 回顾egg.js的代码结构。
* 整体架构图
* 写文档
- 在语雀中新建文档《biz-editor-server端技术方案》,目录
~ 范围(以及和其他项目的关系)
~ 技术选型
~ 整体架构设计
~ 接口设计
~ 数据库设计
* 小结
- 架构设计图
- 写文档
7、技术方案设计
* 引言
- 领导技术方案设计、评审技术方案设计,这就是架构师和基层程序员的区别之一。
* 主要产出
- 《biz-editor-server端技术方案》文档
* 主要内容
- 接口设计
- 选择Restful API,不是GraphQL
- 数据库设计
- server整体设计
* 注意事项
- 正视技术方案设计,设计不会浪费时间,只会节约时间
- GraphQL不是课程主线,不要跑偏
8、基本功能开发
* 主要产出
- 基础功能的接口,并发布到测试机
* 主要内容
- 登录功能
- 用户信息接口
- 作品接口
- 模板接口
* 注意事项
- 发布相关的接口和渠道接口,会在下一周讲解
- 发送短信功能还没有,先模拟
- 简单的代码不在从0手写
- 注意规范的研发流程,如git分支规范、commit规范、合并代码等
9、登录功能
* 引言
- 回顾JWT的登录校验过程
* 短信验证过程
* 初次获取验证码
- request - 输入手机号,请求短信验证码
- server - 生成4位随机数,缓存2min
- res
~ 发短信验证码
~ 返回给前端{ errno: 0 }
* 再次获取验证码
- request - 输入手机号,请求短信验证码
- server - 检查缓存,无则生成,并再次缓存
- res
~ 有缓存,则返回错误:不能频繁获取
~ 发送短信验证码,并返回给前端{ errno: 0 }
* 登录验证
- request - 书记好、验证码,请求登录验证
- server - 匹配缓存
- res
~ 匹配成功,则验证通过
~ 匹配失败,则验证不通过
* 重点考虑
- 费用
~ 缓存,禁止频繁发送
~ 短信服务的提示和报警(后面会讲)
- 用户体验
~ 短信发送失败,不会缓存,可以立马重新生成验证码
- 稳定性
~ 如果server缓存失败,那就允许用户重复调用。情况较少,没关系
~ 短信服务挂掉,报警(后面会讲)
- 注意事项
~ 发送短信,暂时模拟
~ 可以写个文档,虽然已经经过了技术方案设计,但有些写在开发前如果感觉复杂,
可以写个设计文档再评审一下。及时发现问题,及时沟通。
* 小结
- 短信验证过程
~ 生成验证码
~ 验证
- 重点关注
10、用户信息接口
* 研发过程
- 研发规范的细节,会在课程最后总结,先实践起来。
~ 拉新分支feature-xxx fix-xxx hotfix-xxx
~ 修改代码
~ commit,参考.cz-config.js
~ 往dev分支提交pr Pull Request(gitlal中是mr Merge Request)
~ 代码走查
~ 合并代码到dev
~ 等待发布上线
* 接口
- 获取手机短信验证码
- 登录(包含注册)
- 获取用户信息
- 修改用户信息
* 代码演示
- routes/users.js
- controller/users/
- service/users.js
- cache/users/
- __test__/apis/users.js接口测试
* 测试
- npm run test:local
- 使用postman手动测试
* 小结
- 注意研发过程
- 接口
- 代码演示
- 测试
11、作品管理接口
* 接口
- 创建空白作品
- 复制作品(通过模板创建)
- 删除作品
- 恢复作品
- 转赠作品
- 我的作品列表(搜索,分页)
- 我的回收站列表(搜索,分页)
- 查询单个作品信息
- 保存作品
* 代码演示
- routes/works.js
- controller/works/
- service/works.js
- __test__/apis/works.js
- PS:发布相关的,下周再讲解
* 测试
- npm run test:local
- 使用postman手动测试
* 小结
- 接口
- 代码演示
- 测试
12、模板接口
* 接口
- 首页推荐模板列表(搜索,分页)--不需要登录校验
- 获取单个模板信息--不需要登录校验
- 我的模板列表(搜索,分页)
* 代码演示
- routes/templates.js
- controller/works/findTemplate
- cache/works/templates
- __test__/apis/template.js
* 测试
- npm run test:local
- 使用postman手动测试
* 小结
- 接口
- 代码演示
- 测试
十七、编辑器服务端调用第三方服务
1、重要功能 & 第三方服务
* 引言
- 根据2/8原则,关键的一小部分功能,将花费大部分设计和开发成本。
* 将收获什么
- 完整的发布功能(考虑线上业务闭环)
- 新技术/第三方服务调研(初次使用的,并非新发明的)
* 主要内容
- 发布相关的功能
- 接入短信服务
- 上传图片到阿里云oss
- 内容安全检查
* 关键词
- 第三方服务
- 新技术调研
* 学习方法
- 自己去申请第三方服务,一般可试用或费用很低
- 第一次使用一个新技术,要写一个单独的demo去体验一下,别直接拿到项目中
* 注意事项
- 业务代码不会一行一行写
- 课程中会隐藏第三方服务的秘钥,请理解
- 第三方服务的价格、控制台、文档、API都可能会有调整
- 特别是内容安全检查,可能会频繁调整(制作课程期间,就遇到了一次调整)
2、发布相关的功能
* 引言
- 发布,是一个作品的生命周期里,最重要的一个环节。有很多事情需要考虑。
* 主要产出
- 完成发布功能相关的接口
* 主要内容
- 发布功能的设计
- 如何强制下线?
- 功能开发
* 注意事项
- 考虑业务闭环,如重新发布时链接不能变
- 分渠道的重要性!
3、发布功能的设计
* 引言
- 发布,即获取一个url,能外网访问该作品。
* 功能范围
- 发布作品
- 支持多渠道
- 发布为模板
* 划重点
- url不能太长,因为要生成二维码。
- 作品发布之后,重新编辑,保存,未发布。此时不能在线上生效。
- 再次发布时,url不能变,渠道号也不能变。
- 用户访问url时必须带有渠道号,否则无法分渠道统计。
- 注意数据保密,防爬。
- 发布时进行内容安全检查--本周后续的课程会讲。
- PS:此时也能体现出,真实线上业务和demo是不一样的,业务闭环。
* 发布作品
- 回顾:多个项目公用一个数据库。
* url
- 发布作品,就是拼接一个url,其中有作品的id。可让h5-server访问该作品数据,并渲染出页面。
- 例如http:127.0.0.1:3002/p/100,其中p发布作品(预览时可以改为preview),100是作品id。
* 标记
- 未发布的作品,不能通过该url访问到。因此发布的作品要加一个标志。
- 数据库设计,作品数据表status“0-删除,1-未发布,2-发布,3-强制下线”
* url加uuid
- 还要防爬,所以要加上uuid,如http:127.0.0.1:3002/p/100-xxx。
- 所以,这就是为何在设计数据表时要增加一个uuid。
- 这就要求h5-server,必须同时匹配id uuid status。如有一条不满足,则返回404。
* 重新修改作品
- 作品发布了,重新编辑,重新保存,尚未重新发布。
- 此时访问作品,应该是原来发布的内容。
- 所以,mongodb中作品内容和发布内容,要分开。
- 参考数据库设计时的关系图。
* 多渠道
- 回顾:多渠道统计需求,对于运营人员的重要性。
- 渠道就是一个url参数,如http:127.0.0.1:3002/p/100-xxx?channel=1。
- 一个作品可以对应对应多个渠道,至少要有一个渠道。回顾数据库设计时的关系。
- 从技术角度,一个作品就是一个资源实体一个url,渠道仅仅是一个参数。
- 但从用户使用角度,一个作品就可以发布出多个页面,多个二维码。
- PS:直接访问一个无渠道的作品,也是可以的,但不建议这样做,h5-server应该做限制。
* 发布为模板
- 模板就是作品,一个标记isTemplate而已。使用模板创建,其实就是复制。
- 发布模板也是拼接一个url http:127.0.0.1:3002/p/100-xxx,然后修改status。
- 但是,模板没有渠道,也不需要渠道。
* 小结
- 发布为作品,以及重新修改
- 多渠道
- 发布为模板
- PS:发布功能,是biz-editor-server和h5-server的共同功能,所以要两者都要考虑。
4、如何强制下线
* 引言
- 这是一个必要的需求,用于人工保障内容安全,后台管理的重要功能。
- 这个功能也影响了设计方案,原本是想要将作品发布到CDN上的。
* 发布项目到CDN
- 直接将组件内容渲染成一个html,然后上传到oss,然后绑定CDN,可自定义域名。
- 优点:
~ 不用专门搭建h5-server
~ CDN访问速度快(比现在h5-server的SSR速度还要快)
~ 不用担心“重新编辑,但未发布”的情况
- 缺点
~ 后端渲染并发布CDN,导致biz-editor-server逻辑过于复杂(或者单独弄一个服务,
渲染页面,上传CND)
~ 无法紧急下线
~ CDN一般用于存储静态资源,做强缓存,只增不减
~ 如果强行对一个资源做替换,不符合CDN的使用习惯,“反习惯”不可取
- 结论,因为无法紧急下线,弃用CDN的发布方式。
* 紧急下线
- 采用当前h5-server的方式。作品加一个标记status,即可实现紧急下线。
- PS:h5-server不会每次都访问数据库,也是有缓存机智的,这个到时候再说。
* 小结
- 发布项目到CDN
- 紧急下线
- PS:CDN还会用于其他地方
5、功能开发
* 引言
- 功能要点搞明白,写代码就简单了。
* 发布作品和模板
- routes/works.js发布相关的路由
- controller/works/publishWorks.js
- service/works.js发布功能
- cache/works/publish.js
- __test__/apis/works.js发布功能
* 渠道接口
- routes/channel.js
- controller/channel/
- service/channel.js
- __test__/apis/channel.js
* 测试
- 接口测试
- postman测试
* 小结
- 发布作品和模板
- 渠道接口
- PS:预览功能,在h5-server开发,到时再讲。
6、发布相关的功能
* 引言
- 发布,是一个作品的生命周期里,最重要的一个环节。有很多事情需要考虑。
* 主要产出
- 完成发布功能相关的接口
* 主要内容
- 发布功能的设计
- 如何强制下线?
- 功能开发
* 注意事项
- 考虑业务闭环,如重新发布时链接不能变
- 分渠道的重要性!
7、短信服务
* 引言
- 真实项目项目,考虑用户体验。
* 主要产出
- 《短信服务调研》文档
- 登录验证码对接短信服务
* 主要内容
- 短信服务调研
- 配置短信服务
- 实验demo
- 代码演示
* 注意事项
- 开通短信服务很容易,但使用短信服务需要审核(如需要域名备案的截图信息)
- 课程中用到的手机号都是临时的。学习时,可以改用你自己的手机号。
8、短信服务调研
* 调研新技术方案的一般步骤
- 列出所有竟品,根据品牌、功能、价格,选择一个最合适的
- 购买或试用服务
- 查阅文档和配置
- 要单独写一个demo,体验一下
* 竟品对比
- 已写到语雀文档中
~ 七牛云
~ 阿里云
~ 网易云
~ 腾讯云
- 最后因为品牌、价格的原因,选择了腾讯云。
* 购买服务
- 学习用,买最便宜的即可,少买。关注等待营销活动。
* 小结
- 调研步骤
- 竟品对比
- 购买服务
9、配置短信服务
* 引言
- 登录控制台:https://console.cloud.tencent.com/smsv2
* 基本配置
- 创建签名
- 创建模板
- 群发测试
- 配置成功后注意下面几个地方
- appId-应用管理,应用列表
- 签名的ID和名称-国内短信,签名管理
- 模板ID和内容-国内短信,正文模板管理
* 安全配置
- 防刷接口,导致短信调用量过大。
* 小结
- 基本配置
- 安全配置
10、实验demo
* 引言
- 参考文档:https://cloud.tencent.com/document/product/382/43197
* 获取密钥
- 右上角个人名称-->访问管理-->左侧菜单“访问密钥”:https://console.cloud.tencent.com/cam/capi
* demo
- 先不要直接用于项目,先做一个单独的demo体验一下用法。
- 抛开复杂的项目环境,才能获得最真实的体验。
- 代码演示,注意判断发送是否成功。
* SDK升级
- 在课程制作过程中tencentcloud-sdk-nodejs就升级过。导致安装了最新版本,之前的代码运行报错。
- 而且,SDK升级了,但腾讯云的文档并没有更新,npm上的文档更新了。
- 但是,目前npm文档还不全,没有写如何发短信。所以对于这种情况,我们没法使用最新版,还是依然使用之前的v3.0.263版本。
- 待文档都更新了,再切换到新版本。
* 小结
- 获取密钥(注意保密)
- demo
- 注意升级
11、功能开发
* 代码修改
- vendor/sendMsg.js
- controller/users/sendVeriCode.js(看相关代码,不用做演示)
- __test__/vendor.test.js
* 测试
- 单元测试
- postman测试
* 小结
- 代码修改
- 测试
12、上传图片到阿里云OSS
* 引言
- 文件存储交给OSS,我们只做server的业务逻辑。
* 主要产出
- 开发上传接口
* 主要内容
- 配置阿里云OSS
- 实验demo
- 代码演示
* 注意事项
- 阿里云OSS要配置CDN,Sam老师会讲
13、配置阿里云OSS
* 引言
- 文件存储使用阿里云OSS这是业界的最常见选择,不用再做技术调研。
- PS:我还用过腾讯云的COS,不过配置操作和使用细节,跟阿里云OSS肯定不一样。作为参考吧。
* 购买
* 寻找折扣套餐
- 此时OSS首页有一个折扣活动,非常便宜。
- PS:折扣活动是有期限的,仅做为参考。
* 按量付费
- 学习用,按量付费也很便宜。例如此时的几种价格,仅作为参考。具体的自己去官网看。
* 配置OSS
- 购买之后,登录进入控制台
~ 创建Bucket。Bucket就像是你电脑里的硬盘。文档是以Bucket为单位来管理和存储的,可以创建多个Bucket。
~ 外网访问权限:公共读
* 小结
- 购买
- 配置
- PS:配置CDN和自定义域名,Sam老师会讲解
14、实验demo
* 引言
- 文档:https:/help.aliyun.com/document_detail/32068.html?spm=a2c4g.11186623.6.1382.42de2cc69fJBTZ
* 获取密钥
* demo
- put
- putStream
- 存储到某个文件夹
- isExist
- 其他API,可以继续查阅文档。
* 小结
- 获取密钥
- demo
- PS:参考你当前的文档,SDK和接口都可能发生变化。
15、代码演示
* 实现思路
- 上传文件到服务器
- 服务器上传到OSS
* 代码修改
- routes/utils.js
- controller/utils/uploadImg.js
- vendor/uploadOSS.js
- __test__/vendor.test.js OSS部分
- PS:config线上环境和测试环境,两个bucket
* 测试
- 单元测试
- postman测试(需发布到测试机)
* 小结
- 实现思路
- 代码修改
- 测试
16、内容安全检查
* 引言
- 真实线上服务,内容安全非常重要,要能识别出:黄色、暴力、敏感内容。
* 主要产出
- 《内容审查服务调研》调研
- 发布作品接入内容安全检查
* 主要内容
- 内容审查服务调研
- 实验demo
- 代码演示
* 注意事项
- 内容安全检查,可能会随时调整
- 偏重用户体验,还是偏重内容安全,自己抉择
17、内容审核服务调研
* 引言
- 内容安全审查,不像OSS存储那样用的那么频繁,了解的不多,所以需要调研一下。
* 为何需要第三方服务
- 内容审核为何非得用第三方服务?自己做一个敏感词检查不行吗?
- 答案是:不合适,因为成本太高了。
~ 需要维护和更新词库
~ 自己用简单的indexOf做判断,时间复杂度太高了。如果词库长度m字符串长度n,那么时间复杂度
就是O(m * (m + n)) (KMP算法时间复杂度是O(m + n))
~ 需要判断作弊行为,如敏感词之间加空格
~ 扩展性:审核图片、音频、小视频等
* 调研
- 参考语雀文档。
~ 百度云
~ 网易云盾
* 创建应用
* 小结
- 原因
- 调研
- 创建应用
18、实验demo
* 引言
- 参考文档:https://ai.baidu.com/ai-doc/ANTIPORN/Lk3h6xev0
- 审核数据数据类型
~ 文本
~ 图片
- PS:某些不合规的、敏感内容,我们就不演示了,希望理解。但返回结果我会讲清楚。
* 审核文本
* 内容合规
- { conclusion: '合规', conclusionType: 1, log_id: 159920000460984 }
* 内容不合规
- 特别注意,有些内容返回words而有些words为空。
- 为此,我专门咨询过百度云的技术人员,得到的答案是“未命中他们的词库”,但我觉得不是这个原因。
########
{
conclusion: '不合规',
conclusionType: 2,
log_id: 159920000460984,
data: [
{
msg: '存在政治敏感不合规',
conclusion: '不合规',
hits: [
{
datasetName: '百度默认黑词库',
words: ['xxx', 'yyy']
}
],
subType: 3,
conclusionType: 2,
type: 12
}
]
}
########
* 审核图片
* 图片合规
- { conclusionType: 1, conclusion: '合规', log_id: 159920000682630 }
* 图片不合规
- 注意,有些不合规的就没有stars,如血腥图片。
- 我觉得这是合理的,血腥图片没有特别的关键字,也不好头像识别。
########
{
conclusionType: 2,
conclusion: '不合规',
log_id: 159920000682630,
data: [
{
msg: '存在政治敏感不合规',
conclusion: '不合规',
subType: 0,
conclusionType: 2,
type: 5,
// 有些不合规的就没有stars,如血腥图片
stars: [
{
"probability": 0.94308,
"name": "xxx"
},
{
"probability": 0.44308,
"name": "yyy"
}
],
}
]
}
########
* 如何判断审核失败?
- 你有两种选择,但选择了,就要负责。所以要认真考虑。
* 以用户体验为主
- 提示内容审核失败时,一定要提示关键字,哪里失败了。
- 这样用户就能快速修改,再次发起审核。
- 但是,有些审核失败是没有关键字提示的。
* 以内容安全为主
- 不管有没有关键字,只看审核结果。
- 但这样用户有时候很迷茫,只知道什么失败,但不知道失败在哪里,只能猜测、重拾。
- 掘进博客的内容审核,就不提示关键字。
* 小结
- 审核文本
- 审核图片
- 如何判断审核失败?
- PS:一切以你当前的文档为主,文档可能就有调整
19、代码演示
* 引言
- 线上环境,作品发布时,才出发内容审核,其他时候不需要。
* 代码修改
- vendor/contentSensor.js
- controller/works/publishWorks.js接入内容审核
- __test__/vendor.test.js内容审核部分
* 测试
- 单元测试
- postman测试
* 小结
- 代码修改
- 测试