English
uni-cms是全端的、云端一体的开源CMS内容管理系统。
它提供了完善的内容管理,文章编辑、全端渲染。甚至还内置了付费内容看广告解锁和AI生成文章等功能。
即帮助开发者提高开发效率,更提高了内容生产效率和变现效率。
uni-cms包括管理端和用户端。
客户端插件之所以起名为 uni-cms-article 。是因为未来可能还会拓展 uni-cms-image、uni-cms-video 等插件,实现对富媒体内容的管理。
需求建议、bug反馈请点击加入uni-cms交流群反馈与交流。
uni-ai
生成、润色、续写文章内容。此功能需HBuilderX 3.7.13+。详见 uni-ai总结一下就是:
万事俱备,就等你来运营了!
演示体验系统:
支持文章保存草稿、发布、编辑、下架、删除、阅读量统计等功能。
创建文章时支持保存为草稿或者直接发布,当保存为草稿时,文章可以再次编辑,直到文章发布成功。 已发布的文章可以编辑,但是编辑后需要更新文章,才能生效。 当已发布的文章出现侵权或者一些原因需要隐藏时,可在文章列表中对该篇文章进行下架操作,下架后的文章将不会在前端展示,同时文章状态会变为“草稿”状态。
阅读量统计(PV):每次打开文章详情页,都会向后端发送请求,在schema扩展中(uni-cms-articles.schema.ext.js)会对文章的阅读量进行加一统计。
使用观看广告解锁全文功能需要在uni-ad后台开通激励视频广告。
目前H5端不支持广告,所以在H5端无法使用观看广告解锁全文功能
观看广告解锁全文功能,是uni-cms的核心功能之一。它可以帮助开发者快速变现,提高内容生产效率。
如何开通使用广告功能,请参考。
用户端截图如下:
在文章未发布时可以通过文章预览功能,预览文章的渲染效果。
当使用文章预览功能时,需要部署uni-cms-article插件来实现文章预览功能。
预览密钥: 用于文章预览时的身份验证,防止文章被恶意预览。每个密钥有效期为2小时,过期后需要重新生成。
预览页面地址: 文章预览是访问的页面地址,固定为uni_modules/uni-cms-article/pages/detail/preview
小程序/APP预览: 打开uni-cms-article列表页面,点击顶部搜索文章,在输入框右侧点击扫一扫按钮,扫描预览二维码,即可在小程序/APP中预览文章。
网页预览: 输入部署uni-cms-article插件的网页地址,如果部署的路由是hash模式,需要在地址后面加上#
,如:http://localhost:8080/#
如果部署的路由是history模式,直接写地址,如:http://localhost:8080/
。
使用方式简单,只需导入对应的插件至项目中即可。
在插件市场中找到uni-cms,将插件导入至uni-admin项目中。
如果还未使用过uni-admin,请先在HBuilderX新建项目时选择uni-admin项目。并需要了解uni-admin的相关知识。
导入uni-cms后,运行启动uni-admin,在web管理后台,点击左侧菜单栏的菜单管理,添加“内容管理”菜单。
如下图所示:
导入后刷新页面,在uni-admin左侧菜单,可看到内容管理的菜单项,点击即可进入相关页面。
管理端编辑的内容,在用户端呈现。注意管理端和用户端是两个项目,但是连接同一个服务空间。
在插件市场中找到uni-cms-article,将插件导入至uni-app用户端项目中。
注意
uni-cms-article
,需要在unCloud/database
目录上点击“创建Schema”来创建uni-cms-articles
与uni-cms-categories
表后运行项目。uni-id-pages
插件导入至项目中,要了解uni-id-pages
详见。如果您使用了uni-starter项目,那么其已经内置了 uni-id-pages
插件。如果您的cms内容管理涉及多名作者登录。有2种处理方式。
首先作者们需要在uni-admin中注册账户。
然后系统管理员在uni-admin中新建一个文章作者角色。在 系统管理 - 角色管理 中操作,如下图所示:
然后系统管理员在 系统管理 - 用户管理 中,为已注册用户赋予作者角色。
如果作者属于外部人员,比如合作的自媒体。则不适合让外部人员登录你的admin系统。
此时合适的做法是新建一个项目做为作者端。也就是整个cms大系统,分为管理端、读者端、作者端。
目前uni-cms没有提供独立的作者端。有需求的开发者需自行改造uni-cms插件。
AI功能基于
uni-ai-chat
实现,uni-ai-chat
文档请参考uni-ai-chat。
uni-ai-chat
支持 stream 流式响应,stream 流式响应基于uni-push2.0
实现,uni-push2.0
文档请参考uni-push。
如果开通了 uni-push 后将默认使用 stream 流式响应返回 AI 结果,如果未开通 uni-push 将使用普通响应返回 AI 结果。
开通 uni-push2.0 步骤
注意
uni-cms版本大于等于1.0.4时,无需在App.vue内初始化uni-im,uni-cms已经内置了初始化操作。
<script>
//1. 导入统一身份信息管理模块
import uniIdPagesInit from '@/uni_modules/uni-id-pages/init.js';
//2. 导入uniIm的Utils工具类
import uniImUtils from '@/uni_modules/uni-cms/components/ai/common/utils.js';
export default {
onLaunch: async function() {
console.log('App Launch');
//3. 初始化uni身份信息管理模块
uniIdPagesInit();
//4. 初始化uniIm
uniImUtils.init();
},
onShow: function() {
console.log('App Show');
},
onHide: function() {
console.log('App Hide');
}
};
</script>
注意
如果目前的 uni-CMS 不能满足你的需求,你可以基于 uni-CMS 进行二次开发。
uni-cms // uni-cms 插件
├── common // 公共文件
│ ├── font // 字体文件
│ │ └── editor-iconfont.ttf // 富文本编辑器的 toolbar 的 icon 字体文件
│ ├── load-script.js // 加载第三方脚本
│ ├── style // 样式文件
│ │ ├── article-detail.scss // 文章详情页样式
│ │ └── editor-icon.css // 富文本编辑器 toolbar icon 样式
│ ├── translate-content.js // 转换富文本编辑器 Quill Delta格式兼容微信小程序
│ └── validator // 表单验证
│ ├── uni-cms-articles.js // 文章表单验证
│ └── uni-cms-categories.js // 分类表单验证
├── components // 组件
│ ├── ai // uni-ai组件
│ │ ├── chat.nvue // 聊天组件
│ │ ├── common
│ │ │ ├── appEvent.js
│ │ │ ├── initIndexDB.js
│ │ │ ├── md5.js
│ │ │ ├── sqlite.js
│ │ │ ├── timestampToString.js
│ │ │ └── utils.js
│ │ ├── components
│ │ │ ├── uni-im-control
│ │ │ │ └── uni-im-control.vue
│ │ │ ├── uni-im-icons
│ │ │ │ ├── uni-im-icons.ttf
│ │ │ │ └── uni-im-icons.vue
│ │ │ ├── uni-im-msg
│ │ │ │ ├── html-parser.js
│ │ │ │ └── uni-im-msg.vue
│ │ │ └── uni-im-msg-list
│ │ │ ├── components
│ │ │ │ ├── uni-im-list
│ │ │ │ │ └── uni-im-list.vue
│ │ │ │ └── uni-im-list-item
│ │ │ │ └── uni-im-list-item.vue
│ │ │ └── uni-im-msg-list.vue
│ │ ├── lib
│ │ │ ├── MsgManager.js
│ │ │ ├── createObservable.js
│ │ │ └── main.js
│ │ └── static
│ │ ├── avatarUrl.png
│ │ ├── iconfont.css
│ │ ├── iconfont.ttf
│ │ ├── qrCode.png
│ │ └── sound-ing.gif
│ └── editor // 富文本编辑器 (兼容H5, 微信小程序, App, 基于Quill, 详见https://quilljs.com/)
│ ├── app.scss
│ ├── editor.vue // 富文本编辑器组件
│ ├── h5.scss
│ ├── tools // 富文本编辑器工具栏
│ │ ├── align.vue // 对齐
│ │ ├── background.vue // 背景颜色
│ │ ├── base.vue // 基础工具
│ │ ├── bold.vue // 加粗
│ │ ├── color-picker.vue // 颜色选择器
│ │ ├── color.vue // 字体颜色
│ │ ├── format-clear.vue // 清除格式
│ │ ├── header.vue // 标题
│ │ ├── hr.vue // 分割线
│ │ ├── image.vue // 图片
│ │ ├── italic.vue // 斜体
│ │ ├── letter-space.vue // 字间距
│ │ ├── line-height.vue // 行高
│ │ ├── line-indent.vue // 缩进
│ │ ├── link.vue // 超链接
│ │ ├── list.vue // 列表
│ │ ├── redo.vue // 重做
│ │ ├── space-both.vue // 两端对齐
│ │ ├── strike.vue // 删除线
│ │ ├── underline.vue // 下划线
│ │ ├── undo.vue // 撤销
│ │ └── unlock-content.vue // 解锁全文
│ └── web // 富文本编辑器web端 (微信小程序与App使用内置的editor组件)
│ ├── editor.vue // 富文本编辑器组件
│ ├── formats // 富文本编辑器格式
│ │ ├── align.js // 对齐
│ │ ├── box.js // 背景颜色
│ │ ├── divider.css // 分割线样式
│ │ ├── divider.js // 分割线
│ │ ├── font.js // 字体
│ │ ├── image.js // 图片
│ │ ├── index.js // 富文本编辑器格式入口
│ │ ├── link.js // 超链接
│ │ ├── list.js // 列表
│ │ ├── text.js // 文本
│ │ ├── unlock-content.css // 解锁全文样式
│ │ └── unlock-content.js // 解锁全文
│ └── modules
│ ├── clipboard.js // 剪切板
│ ├── image-extend.js // 图片扩展
│ ├── image-uploading.css // 图片上传样式
│ └── index.js // 富文本编辑器模块入口
├── menu.json // 菜单初始化配置
├── package.json
├── changelog.md
├── readme.md
├── pages // 页面
│ ├── article // 文章
│ │ ├── add // 添加文章
│ │ │ └── add.vue
│ │ ├── edit // 编辑文章
│ │ │ └── edit.vue
│ │ └── list // 文章列表
│ │ └── list.vue
│ └── categories // 分类
│ ├── add // 添加分类
│ │ └── add.vue
│ ├── edit // 编辑分类
│ │ └── edit.vue
│ └── list // 分类列表
│ └── list.vue
└── uniCloud // 云函数
├── cloudfunctions
│ ├── uni-cms-co // uni-cms 云对象
│ │ ├── index.obj.js // 云对象入口
│ │ ├── package.json
│ │ └── utils.js // uni-cms云对象工具
│ └── uni-im-co // uni-im 云对象
│ ├── index.obj.js // 云对象入口
│ └── package.json
└── database // 数据库
├── db_init.json // 数据库初始化配置,初始化uni-ai用户
├── uni-cms-articles.schema.ext.js // uni-cms-articles 云函数扩展
├── uni-cms-articles.schema.json // uni-cms-articles 数据库表
├── uni-cms-categories.schema.json // uni-cms-categories 数据库表
├── uni-im-conversation.schema.ext.js // uni-im-conversation 云函数扩展
├── uni-im-conversation.schema.json // uni-im-conversation 数据库表
├── uni-im-friend.schema.json // uni-im-friend 数据库表
├── uni-im-group-member.schema.json // uni-im-group-member 数据库表
├── uni-im-group.schema.json // uni-im-group 数据库表
├── uni-im-msg.schema.ext.js // uni-im-msg 云函数扩展
├── uni-im-msg.schema.json // uni-im-msg 数据库表
└── uni-im-notification.schema.json // uni-im-notification 数据库表
数据库表说明
uni-cms-articles
cms文章表,schema 结构详见uni-cms-categories
cms分类表,schema 结构详见uni-im-conversation
im会话表,schema 结构详见uni-im-friend
im好友表,schema 结构详见uni-im-group-member
im群成员表uni-im-group
im群表uni-im-msg
im消息表,schema 结构详见uni-cms-article // uni-cms-article 插件
├── changelog.md
├── common // 公共文件
│ └── publish-time.js // 格式化发布时间
├── components // 组件
│ └── render-article-detail // 渲染文章详情
│ ├── index.vue // 渲染文章详情组件
│ └── unlock-content.vue // 解锁全文组件
├── package.json
├── pages // 页面
│ ├── detail // 文章详情
│ │ └── detail.vue
│ ├── list // 文章列表
│ │ └── list.nvue
│ ├── search // 搜索
│ │ └── search.nvue
│ └── webview // 加载文章详情中的外链
│ └── webview.vue
├── pages_init.json // 页面初始化配置
├── readme.md
└── uniCloud // 云函数
├── cloudfunctions // 云函数
│ └── uni-cms-unlock-callback // 内容解锁回调
│ └── index.js
└── database // 数据库
├── db_init.json // 数据库初始化配置
└── uni-cms-unlock-record.schema.json // 内容解锁记录表
数据表说明
uni-cms-unlock-record
内容解锁记录表,schema 结构详见负责处理与创建、更新和读取文章相关的各种逻辑
主要功能如下:
在创建(beforeCreate)和更新(beforeUpdate)文章之前,检测文章的标题、摘要、内容和封面图片是否包含敏感信息。若包含敏感信息,则抛出错误,提示用户修改。
在读取文章(afterRead)时,根据用户的阅读情况更新文章的阅读次数(view_count)。同时处理文章内容的解锁逻辑。如果文章包含解锁内容,根据用户的登录状态和解锁记录返回相应的内容。
代码中还包含一些辅助函数:
checkContentSec
:检测文本内容是否包含敏感信息。
checkImageSec
:检测图片是否违规。
checkContentSecurityEnable
:检查内容安全开关是否启用。
safeRequire
:安全地引入模块,如果模块不存在,则抛出错误。
uni-cms的云端的配置文件统一使用uni-config-center。
云函数
uni-cms
、uni-cms-unlock-callback
都使用同一个配置文件
新建配置文件,路径为 uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center/uni-cms/config.json
,用于配置uni-cms相关信息,完整配置如下:
{
"clientAppIds": ["__UNI__XXXxx"], // 配置用户端appId,目前用于看广告解锁全文,可配置多个appId。
"contentSecurity": { // 内容安全配置
"allowCheckType": ["content", "image"] // 配置可检测的内容;可选值仅为 content 或 image,content 表示检测文字,image 表示检测图片
},
"adConfig": { // 广告解锁相关配置
"securityKey": "Xxxxxxxxxxxxxxxxxxxxxxxxxx", // 广告位 Security key
"watchAdUniqueType": "device" // 观看广告的唯一标识类型,可选值为 user 或者 device,user 表示用户唯一,device 表示设备唯一
}
}
说明
watchAdUniqueType
为 device
时,表示按设备解锁。同一设备只需观看一次广告,如果该设备观看过广告已解锁该文章,再次浏览该文章将无需再观看广告。如果应用的本机缓存被清理,则解锁失效。watchAdUniqueType
为 user
时,表示按用户解锁。此用户为uni-id用户,如果该用户已解锁该文章,再次浏览该文章将无需再观看广告。按用户解锁,需应用中加载uni-id-pages插件。管理端云对象,提供内容安全检测服务
接口
接口名称 | 接口地址 | 接口描述 |
---|---|---|
图片安全检测 | imageCheckSec | 对指定的图片进行安全检测,违规的图片将删除 |
客户端云函数,用于看广告解锁内容后的回调
目前富文本编辑器支持Web、微信小程序、App。不支持其他平台。底层基于Quill.js,详见https://quilljs.com/
如果编辑器在微信小程序或App使用,将不支持插件扩展,仅支持基本的富文本编辑功能
如果需要开发插件,将不能发布至微信小程序或者App,否则会出现编辑器无法使用的情况
多端不一致表现说明
Web端:支持插件开发,支持所有Quill.js的功能
小程序端/App端:不支持插件开发,仅支持基本的富文本编辑功能,超链接插入将被转换为MarkDown格式,如插入广告解锁ToolBar,将会转会为图片,但不影响前端正常渲染,仅需编辑时注意
例子:添加图片格式
由于自定义了 toolbar 的配置,所以需要在 uni_modules/uni-cms/components/editor/web/formats
目录下添加对应的格式文件,例如 image.js
文件,用于处理图片标签格式,代码如下:
const ATTRIBUTES = [
'alt',
'height',
'width',
'data-custom',
'class',
'data-local'
]
export default function (Quill) {
const Image = Quill.import('formats/image')
class ExtendImageFormat extends Image {
static formats (domNode) {
return ATTRIBUTES.reduce(function (formats, attribute) {
if (domNode.hasAttribute(attribute)) {
formats[attribute] = domNode.getAttribute(attribute)
}
return formats
}, {})
}
static sanitize (url) {
return url
}
format (name, value) {
if (ATTRIBUTES.indexOf(name) > -1) {
if (value) {
this.domNode.setAttribute(name, value)
} else {
this.domNode.removeAttribute(name)
}
} else {
super.format(name, value)
}
}
}
return {
'formats/image': ExtendImageFormat
}
}
每一个格式或者模块都必须导出一个方法, 参数接收 Quill
对象,该方法必须返回一个对象,对象的 key 为格式或者模块的名称,value 为对应的格式或者模块,例如:
export default function (Quill) {
return {
'formats/image': ImageFormat
}
}
在 uni_modules/uni-cms/components/editor/web/index.js
文件中引入image.js
文件,例如:
import image from './image'
export function register (Quill) {
const formats = {
image,
}
const options = {}
Object.values(formats).forEach(value => Object.assign(options, value(Quill)))
Quill.register(options, true)
}
在 uni_modules/uni-cms/components/editor/editor.vue
中找到 toolbar H5的条件编译区块,添加插入图片按钮,例如:
<template>
<view @click="insertImage">
<uni-icons type="image" size="50rpx"></uni-icons>
</view>
</template>
<script>
export default {
methods: {
insertImage () {
this.editorCtx.insertImage({
src: "https://xxxxx",
alt: "图片",
})
}
}
}
</script>
uni-cms-unlock-callback
Security key
与adp id
,复制 Security key
与 adp id
uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center
目录中创建 uni-cms/config.json
配置文件,配置文件如下:{
"clientAppIds": ["__UNI__XXXxx"],
"adConfig": {
"securityKey": "xxxxxxxxxxxxxxxxxxxxx",
"watchAdUniqueType": "device"
}
}
注意
clientAppIds
为客户端appId,用于校验客户端请求,如不配置可能导致无法使用广告解锁功能,需要与客户端配置的appId保持一致securityKey
为广告位的 Security key
,用于校验广告回调的合法性watchAdUniqueType
为观看广告的唯一标识类型,可选值为 user
或者 device
,user
表示用户唯一,device
表示设备唯一watchAdUniqueType
为 device
时,表示按设备解锁。同一设备只需观看一次广告,如果该设备观看过广告已解锁该文章,再次浏览该文章将无需再观看广告。如果应用的本机缓存被清理,则解锁失效。watchAdUniqueType
为 user
时,表示按用户解锁。此用户为uni-id用户,如果该用户已解锁该文章,再次浏览该文章将无需再观看广告。按用户解锁,需应用中加载uni-id-pages插件。uni_modules/uni-cms-article/pages/detail/detail.vue
文件中找到 data.adpId
与 data.watchAdUniqueType
字段,根据自己的广告位ID进行修改,例如:{
adpId: "000000000",
watchAdUniqueType: "device" //注意前端也需要配置解锁方式,是按设备解锁还是按uni-id的用户解锁。
}
解锁逻辑说明
当用户端浏览文章时,查询文章详情会触发在uni-cms-articles.schema.ext.js
(schema扩展库)中定义的数据库读取触发器,在这段js中验证用户/设备是否已解锁,已解锁的用户将会直接展示全文,未解锁的用户将会展示解锁全文按钮。
用户点击解锁全文按钮后,将会弹出激励视频广告,
uni-cms-unlock-callback
,云函数uni-cms-unlock-callback
进行验证,验证通过后,为用户解锁内容,保存在uni-cms-unlock-record
数据表中,使用字段unique_id
来标记用户已解锁。其他
uni_modules/uni-cms/components/render-article-detail/unlock-content.vue
文件中的代码。uni_modules/uni-cms-article/components/render-article-detail/index.vue
文件中注释或者删除unlockContent
组件。文章内容对外发布时,需避免发布内容包含违法内容。否则轻则导致应用下架,重则承担刑事责任。
所以需在发布前调用三方的内容验证接口,如果内容涉及敏感词或者不合规的图片,则接口会提示异常。
内容安全功能由uni-sec-check提供,默认未开启。
注意:uni-sec-check
模块使用了微信的内容安全接口,所以依赖uni-open-bridge
管理微信凭据,使用前需要在uni-config-center
内添加uni-id
配置,
具体配置参考uni-sec-check文档
如开启了uni-cms的内容安全校验,会在发布前使用 uni-sec-check 检测用户输入的文字与上传的图片,如果检测到违规内容,内容将无法发布。
您可以根据自己需求开启或关闭内容安全检测,在 uni-cms
云端配置文件中配置 contentSecurity
字段,例如:
// 开启
{
"contentSecurity": {
"allowCheckType": ["content", "image"] // 可选值仅为 content 或 image;content 表示检测文字,image 表示检测图片
}
}
// 关闭
{
"contentSecurity": false
}
说明
allowCheckType
存在content
值时;内容安全将会对文章标题、文章内容、文章摘要进行检测。allowCheckType
存在image
值时;内容安全将会对上传的封面图片、文章内容中的图片进行检测。uni-cms
配置文件参考uni-cms配置发布视频
增加更多列表页模板,包括顶部分类、列表大图、小图、多图样式
内容分享
支持 Markdown 编辑
支持内容标签
支持点赞
支持评论
支持收藏