介绍
该文档用于外部组件开发和功能集成
SDK 版本跟随 CMS 产品版本
此文档会一直更新为最新版本,版本差异详见【版本升级】
指南
cms 基于 vue3 (3.2.31) 开发,必须使用 vue3 才能兼容使用,且应保持版本一致
安装
安装 cms sdk
npm install syc-cms
通过脚手架创建外部组件项目
请查看《使用模板进行前端开发》文档
使用
引入 cms sdk
import sdk from 'syc-cms'
import 'syc-cms/sdk/style.css'
console.log(sdk.version)
cms 前端模块主要分为两大类,模型(models)、视图(views),详见 【API】
教程
外部组件
独立开发 cms 组件
1. 使用脚手架创建项目
npm init cms-widgets
2. 安装 npm 依赖
npm install
3. 运行
npm run dev
4. 基于示例组件开发新组件。见【组件开发】
src/widgets/
Widget1/index.ts
Widget2/index.ts
index.ts # 打包入口
5. 打包
npm run build
dist/widgets/
Widget1/index.js
Widget2/index.js
6. 将打包结果放置 cms 服务器 wwwroot/widgets 下
wwwroot/widgets/
Widget1/index.js
Widget2/index.js
7. 运行 cms
8. 在组件库中看到自己写的组件即成功
组件开发
组件模型 models/Widget
画布节点模型 models/CanvasNode
用户将组件 Widget 拖拽到画布上时,基座会创建一个画布节点 CanvasNode 添加到 app.current.project.current.page.document.body.children 下
WidgetX/index.ts
// 编写两个 vue 组件
// 一个是画布视图
import X from '../X/X.vue'
// 另一个是设置视图
import XSettings from '../X/X.settings.vue'
// 当 Widget 被拖拽出来时
// 基座创建一个 CanvasNode 实例
// 基座会给两者共享一个 canvasNode , prop 名为 node
// 设置视图主要负责修改 canvasNode.props
// 画布视图则主要使用 canvasNode.props
// 注册组件
// 引用 Widget 模型
const { Widget } = sdk.import('@/models/Widget')
// 创建一个新 Widget
new Widget({
is: 'X',
category: Widget.categories.base.type,
canvasView: X,
settingsView: XSettings,
props: {},
})
// 注册成功
console.log(Widget.store['X'])
功能集成
复用 cms 的能力,将 cms 的功能集成到自己的项目中
1. 创建 vue3 项目
2. 安装 cms
npm install syc-cms
3. 引用 cms
import sdk from 'syc-cms'
4. 修改 cms
const { X } = sdk.import('@/models/X')X
5. 渲染 cms
Your.vue
<template></template>
<script>
// 导入你需要的视图
const VueComponent = sdk.import('@/views/X.vue')
</script>
API
sdk
mount(selector: string)
挂载整个 cms ,如果只需要集成部分功能,则不要调用
selector: css 选择器
sdk.mount('#app')
import(module: string)
导入 cms 模块
复用 npm 包
const X = sdk.import('X')
使用模型
const { X } = sdk.import('@/models/X')
使用视图
const X = sdk.import('@/views/.../X.vue')
version: string
cms 版本号
console.log(sdk.version)
NPM 包
sdk 会提供 cms 使用的主要的 npm 包以复用。开发外部组件时,必须先使用 sdk 提供的包以避免冗余或出错
const X = sdk.import('X')
示例
const { isEmpty } = sdk.import('lodash')
✧ axios
✧ crypto-js
✧ element-plus
✧ echarts
✧ html2canvas
✧ jszip
✧ lodash
✧ vue (是否要排除,待定)
✧ vue-router(是否要排除,待定)
✧ vuex(是否要排除,待定)
模型(M)
模型指 MVC 中的 M ,是对应用结构的描述,是一系列类
models/App
app: App
App 的实例,单例,是整个系统的数据中心
const { app, App, createApp, getApp } = sdk.import('@/models/App')
console.log(app.mode)
// 单例
app === new App() === createApp() === getApp()
class App
construnctor()
初始化应用程序
mode: "editing" | "running"
当前模式,编辑模式(开发版),运行模式(运行版)。组件渲染时在两种模式中可能有区别,取决于组件自身逻辑
editing: boolean
是否编辑模式
running: boolean
是否运行模式
current.project: Project
包含一个 Project 实例,工程项目实例
projectList: Project[]
工程项目列表,每一项都是一个 Project 实例
createApp()
创建应用程序,sdk 已自动创建
getApp()
获取应用程序
models/Project
class Project
对项目工程进行管理和操作,包括变量、页面、语言等内容
constructor(object: any = {})
创建项目
id
项目的 ID
name
项目的名称
pageList: Page[]
项目中的页面列表,存储 Page 类的实例数组
languageList: Language[]
项目中的语言列表,存储 Language 类的实例数组
variableMap: { [name: Variable['name']]: Variable }
以变量名称为键的对象,存储项目中的变量信息,每个变量是 Variable 类的实例
variableValueMap
以变量名称为键的对象,存储项目中的变量值信息。通过 Proxy,实现了对 variableMap 的值的自动获取和设置
variableOldValueMap
以变量名称为键的对象,存储项目中的变量旧值信息。通过 Proxy,实现了对 variableMap 的旧值的自动获取
current.page: Page
当前页面
current.language: Language
当前语言
current.user: User
当前用户
current.homePageId: string
首页 ID 字符串
blocks: Block[]
全局事件列表,存储 Block 类的实例数组
variableEventConfigList
变量事件配置列表,存储变量事件的配置信息
timerEventConfigList
定时器事件配置列表,存储定时器事件的配置信息
remove()
从 app.projectList 中移除当前项目实例
toast(...args: Parameters<typeof toast>)
显示提示信息。参数与 toast 函数的参数相同
setVariable(name: string, value: string|number|boolean)
设置变量值。参数 name 是变量名,value 是变量值
waiting(time = 0)
等待指定时长。参数 time 是等待的时长(毫秒)。返回一个解析为 true 的 Promise
openVirtualKeyboard()
开启虚拟键盘。通过触发名为 openVirtualKeyboard 的事件实现
closeVirtualKeyboard()
关闭虚拟键盘。通过触发名为 closeVirtualKeyboard 的事件实现
models/Page
class Page
页面管理,它包含了页面的基本属性和方法,以及与其他页面进行交互的功能。
constructor(object: Partial<Page> = {})
创建页面
id
表示页面的唯一标识符
name
表示页面的名称
children: Page[]
表示页面的子页面
document: {body: CanvasNode}
表示页面文档数据,body 是页面渲染在画布上时的根节点
type: number
表示页面的类型。0 表示文件夹,1 表示画面
updateTime: string
表示页面的更新时间
sort: number|null
表示页面在父级页面中的下标(用于排序)。值为 null 时,默认排序将页面追加到父级的最后一个
parent: Page
表示页面的父节点
variableEventConfigList: Map
表示页面的变量事件配置列表
timerEventConfigList: Map
表示页面的定时器事件配置列表
permissions: Array
表示页面的权限控制配置。包含多个具有 id、name 和 subs 属性的对象,id 和 name 分别表示 CanvasNode 的 id 和 name,subs 是一个包含多个具有 id 和 name 属性的对象的数组
static getPageById(id: string)
根据给定的 id 在项目的页面列表中查找页面
static appendPageList(child: Page, sort: number | null = null)
静态方法,将给定的子页面添加到项目的页面列表中
appendChild(child: Page, sort: number | null = null)
向当前页面的子页面列表中添加一个子页面
remove()
从父页面的子页面列表中移除当前页面
getSort()
获取当前页面在父页面子页面列表中的下标
save()
保存当前页面的内容和权限配置
models/PageManager
class PageManager
一个页面控制器,主要用于管理页面的弹窗、页面跳转、导出、打印等功能。
construnctor()
初始化页面控制器
id
类的唯一标识,值为 'PageManager'
name
类的名称,值为 '页面控制器'
topPageZIndex: string
页面顶部的 z-index 属性值,默认为 '99'
dialogPages: Array
存储弹窗页面的数组
miniPagesId: Array<MiniPages>
存储最小化窗口的 id 的数组
currentDialogPageUUID: string
当前选中的弹窗的 UUID
static lastDialogInfo: { timestamp: number, pageId: string }
记录最后一次弹窗的信息,包括时间戳和 pageId
currentPage: any
获取当前选中的弹窗
getDialogPageById(id: string)
根据 id 获取对应的弹窗页面
removeMiniPagesById(id: string)
根据 id 移除最小化窗口
removeDialogPagesById(id: string)
根据 id 移除最大化窗口
jumpRoute(pageId: number)
跳转到指定的页面,支持弹窗内跳转和主体页面跳转
reloadRoute()
刷新当前页面
backRoute()
返回上一个页面
closeRoute()
关闭所有弹窗页面
alertRoute(targetPageId: number | string, title: string, fixedSize: boolean, width: number, height: number, target: string, closeBtn: boolean)
弹出指定页面,包括相关参数(如:目标页面 id、标题、固定尺寸、宽度、高度、目标、关闭按钮等)
exportCurrentPage(pageInfo: any, type: string, filename: string, format: string, orientation: string, specifiedSavePath: string | null, timeout: number = 2000)
导出页面中的图表数据,支持导出为 Excel 格式
printCurrentPage(pageInfo: any, timeout: number = 2000)
打印当前页面
exportChartsData(pageComponent: any, filename: string, type: string, exportContent: Array<string>, specifiedSavePath: string, timeout: number = 1000)
导出页面图表数据
models/CanvasNode
class CanvasNode
用于表示和管理一个画布上的图形元素,每个独立的图形元素都可以看作是一个 CanvasNode 实例。它包含了许多属性和方法,用于描述元素的形状、位置、颜色等特征,以及实现元素的绘制、移动、缩放等操作。
constructor(object: Partial<CanvasNode> = {})
初始化节点
id
节点的唯一标识符,使用日期的 JSON 字符串表示
name
节点的名称,默认为空字符串
tagName: string | undefined
节点的 HTML 标签名,可以是 undefined
style: Partial<CSSStyleDeclaration>
节点根元素的样式数据,是一个包含 CSS 样式声明的对象
langStyleMap: Record<string,Partial<CSSStyleDeclaration>>
一个记录不同语言样式的对象,键值对形式
computedStyle: Partial<CSSStyleDeclaration>
节点根元素已计算的样式,通过 Proxy 进行操作
static computedStyleCache: Record<string,Partial<CSSStyleDeclaration>>
针对 computedStyle 计算样式进行缓存,用于子节点修改样式后能及时反馈给父节点
styleProxy: Partial<CSSStyleDeclaration>
节点根元素样式转换器,将 computedStyle 转换为样式字符串。
is: string
表示一个组件类型,类似于 Vue 的 is 属性
props: Record<string, any>
组件的 props,组件应允许所有 prop 为空
blocks: OnBlocks[]
包含 OnBlock 类型的数组
methods: { [name: string]: Function }
包含方法的对象,方法名作为键,方法作为值
permission: boolean
表示节点是否具有权限,默认为 false
selected: boolean
选中状态的 getter 和 setter,用于判断节点是否被选中
locked: boolean
表示节点是否被锁定,默认为 false
aspectRatioLocked: boolean
表示节点的宽高比是否被锁定,默认为 false
dom: HTMLElement
返回 DOM 元素,根据 id 获取
parentNode: CanvasNode
返回节点的父节点,可能是 undefined
childNodes: CanvasNode[]
节点的子节点数组
children: CanvasNode
返回 childNodes 属性,用于获取子节点
static readonly selectedList: CanvasNode
选中的节点列表,响应式数组
static readonly styleProxy: Partial<CSSStyleDeclaration>
读写当前选中节点的样式的代理对象
static getSelectedOrBodyList()
获取选中的节点或页面主体节点列表
static getUnlockedSelectedList()
获取未锁定的选中节点列表
static getSameStyleProxyValue(nodes: CanvasNode[], key: string)
获取具有相同样式代理值的节点数组
static setSameStyleProxyValue(nodes: CanvasNode[], key: string, value: any)
为具有相同样式代理值的节点数组设置样式值
static getById(id: string)
根据给定的 id 获取 CanvasNode 实例。
static getBody()
获取页面主体节点
toJSON()
返回一个 JSON 对象,包含节点的属性
remove()
从父节点中移除当前节点
appendChild(child: CanvasNode)
将给定的子节点添加到当前节点的 childNodes 数组中
cloneNode()
克隆当前节点及其子节点,返回克隆得到的新节点
isGroup()
判断当前节点是否为组节点
getVariableEvent()
获取变量事件相关的块
setDefaultProps(defaultProps: any)
设置默认的 props
toggleVisible(visibleState: 'show' | 'hide' | '' = '')
切换节点的可见性
addClass(className: string)
给节点添加类名
removeClass(className: string)
移除节点的类名
hasClass(className: string)
判断节点是否具有指定的类名
toggleClass(className: string)
切换节点的类名
toggleEnable(enableState: 'enable' | 'disable' | '' = '')
切换节点的可用性
setOpacity(opacity: number)
设置节点的不透明度
toggleBling(isStarted: boolean, speed: 'slow' | 'medium' | 'fast' = 'fast')
切换节点的闪烁效果
setWidthHeight(mode: 'absolute' | 'percentage', w: number, h: number)
设置节点的宽度和高度
setLetTop(mode: 'relative' | 'absolute', x: number, y: number)
设置节点的左和顶部位置
setRotate(mode: 'relative' | 'absolute', deg: number, originX: number, originY: number)
设置节点的旋转角度和旋转中心点
setTextStyle(color: string, fontSize: number, bold: boolean, italic: boolean, underline: boolean, textAlign: string, letterSpacing: number, lineHeight: number)
设置文本样式
setTextContent(content: string)
设置文本内容
setBackgroundColor(color: string)
设置背景颜色
setBorder(color: string, width: number, style: string)
设置边框样式
setBorderRadius(borderRadius: number)
设置边框圆角
setBoxShadow(mode: 'outset' | 'inset', horizontal: number, vertical: number, blur: number, spread: number, color: string)
设置盒阴影样式
models/Widget
class Widget
表示应用中的可视化组件,这些组件可以在画布上进行组合和编辑,从而实现各种自定义的功能。Widget 类包含了组件的一些基本属性和方法,以及与其他组件进行交互的功能。
constructor(object: Widget)
创建新组件
is: string
组件的唯一标识,类比 vue is 。如果相同将会覆盖。内部组件自动使用文件名
name: string
表示组件的名称
category: string
表示组件所属的分类
icon: string
表示组件的图标
permission: boolean
表示组件是否可以进行权限控制
canvasView: unknown
表示组件在画布上的视图
settingsView: unknown
表示组件的设置视图(如:Name.settings.vue)
props: object
表示组件的默认属性
style: Record<string, boolean>
表示组件可以配置的样式,如果某个样式被禁用,则对应值为 false
onCreate(node: CanvasNode)
当组件实例化为 CanvasNode 时,会调用此函数
static loadExternalWidgets(externalWidgetsAPI: string)
加载外部组件,从给定的 API 获取组件列表并加载
static importExternalWidgets(url: string)
导入外部组件。从给定的 URL 加载外部组件并实例化
static store
以组件类型为键,Widget 实例为值。用于存储所有已创建的 Widget 实例
static get list
获取 store 中的所有 Widget 实例
static sortInfo
指定组件的排序
static categories: {[key:string]: {type:string, label:string}}
组件分类
models/Variable
class Variable
对项目中的变量进行变量管理。它包含了与变量相关的一系列操作,例如获取和设置变量值,发送变量值到后端等。还提供了一些静态方法和属性,以方便访问和操作当前项目中的变量。
constructor(object: any = {}, project = app.current.project)
构造函数,创建变量实例。同一工程多次创建同名变量会复用
project: Project
该变量所属的项目实例
name: string
变量名
dataQuality: number
变量的数据质量
_value
变量的私有值
oldValue
变量的旧值
value
getter 和 setter 用于获取和设置变量值。setter 设置新值时,会自动下发新值
get()
返回变量的值
set(newValue: any)
设置变量值并同步更新本地值
post(newValue: any)
仅下发变量值,不立即更新本地值
static postBufferMap
合并所有变量变更,统一下发
static applyPost(variable: Variable, newValue: any, oldValue: any)
收集变量的变化
static post(map: typeof Variable.postBufferMap)
下发变量值,如果失败则恢复旧值
remove()
从项目中删除此变量
static map
获取当前项目中的变量映射
static valueMap
获取当前项目中的变量值映射
static oldValueMap
获取当前项目中的旧变量值映射
static getByName(name: string, project = app.current.project)
根据变量名和项目获取变量实例
static store
读写变量,仅下发,不更新本地值
static _store
读写变量,不下发,仅更新本地值
static store
读写变量,下发,且同步更新本地值
static start()
启动变量监听
static convertRemoteValue(value: any)
转换推送的值类型
static isVarName(name: string)
判断给定字符串是否为一个合法的变量名
static getExpVars(code: string)
获取给定表达式中的变量名
static expFnCache: Map<string, Function>
用于缓存表达式求值函数的静态属性
static exp(code: string)
通过表达式求值
static watchExp(code: string, callback: (value: any, oldValue: any) => void)
监听表达式的值变化
static expTitleTip: string
表达式输入框 tooltip 提示
models/Language
class Language
用于管理多语言,用于实现在应用中切换不同的语言环境。其属性和方法主要负责获取、设置和翻译文本,以及订阅和触发当前语言环境的变化。
constructor({ lang, running = false }: { lang: Lang; running?: boolean }, project = app.current.project )
初始化语言包
project: Project
存储项目信息
lang: "original" | "auto" | "zh-CN" | "en-US"
存储当前设置的语言
followLang: "original" | "auto" | "zh-CN" | "en-US"
存储实际应用的语言,如果设置为 'auto',则跟随系统的语言设置
map
存储动态语言包的映射,键为原始文本,值为翻译后的文本
staticMap
存储静态(内置)语言包的映射
static isOriginal()
判断当前语言状态是否为原始文本
setLang(lang: "original" | "auto" | "zh-CN" | "en-US")
保存当前设置的语言到本地 localStorage
fetch()
获取当前项目对应语言的翻译数据
handleMap(maps: LangMapItem[])
转换处理后端返回的翻译文本
static initDefautLangInRun(running?: boolean)
在运行时设置默认语言
static t(rawText: string | null | undefined)
收集并翻译动态语言,将原始文本替换为对应的翻译文本
static _t(rawText: string)
翻译内置语言包的文本
static saveRawText(pageId: string)
保存原始文本
static resetStore()
重置状态
static useChange(fn: Function)
订阅当前语言状态的变化,收集监听函数
static trigger(lang: Language)
触发通知订阅函数当前语言状态改变
static remove(fn: Function)
移除订阅
static triggerRenderFn()
改变状态,使 CanvasNode 组件重新渲染并调用 t 函数收集文本依赖
static useElementPlusI18n()
获取当前语言的 element-plus 内置语言包
static getLangReqHeader()
获取当前语言请求头
models/Block
class Block
Block 类是所有具有类别的对象的基类。它提供了一些共享的基本方法和属性,以及一些用于子类继承的基础接口。
constructor(object: any = {})
class: string
每个 Block 实例都有一个 class 属性,其值为构造函数的 class 属性。这用于区分不同类型的块
children: Block[]
存储该 Block 实例的子块数组
id
每个 Block 实例都有一个唯一的 id
createArray(objectArray: any[])
用于将对象数组转换为 Block 实例数组
codeToValue(code: string)
用于将字符串形式的代码转换为 JavaScript 值
valueToCode(value: any)
用于将 JavaScript 值转换为字符串形式的代码
fixValue(value: any)
用于将可能是字符串形式的代码的值转换为 JavaScript 值
toCode()
用于将 Block 实例转换为字符串形式的代码
class OnBlock
OnBlock 类表示注册事件块
constructor(object: any = {})
static class: string
类标识符,对于 OnBlock 实例,其值为 'OnBlock'
event: EventBlock
EventBlock 实例,表示该 OnBlock 实例的事件
isEnable: boolean
布尔值,表示该 OnBlock 实例是否启用
toCode()
用于将 OnBlock 实例及其子块转换为字符串形式的代码
getCallback()
用于获取 OnBlock 实例的回调函数
getCallbackCatch()
用于获取 OnBlock 实例的错误处理回调函数
getOnProp()
用于获取 OnBlock 实例的事件属性
getOnPropList(onBlockList: Block[])
用于从给定的 OnBlock 实例数组中获取事件属性列表
getBlockById(id: string)
用于通过 id 从当前项目的页面中查找 OnBlock 实例
class EventBlock
EventBlock 类表示事件块
constructor(object: any = {})
static class
类标识符,对于 EventBlock 实例,其值为 'EventBlock'
static types
列出了所有可能的事件类型
type: string
字符串,表示该 EventBlock 实例的事件类型
name: string
字符串,表示该 EventBlock 实例的名称
detail
表示该 EventBlock 实例的详细信息
toCode()
用于将 EventBlock 实例转换为字符串形式的代码
class IfBlock
IfBlock 类表示条件块
constructor(object: any = {})
static class
类标识符,对于 IfBlock 实例,其值为 'IfBlock'
expression: string
字符串,表示该 IfBlock 实例的条件表达式
toCode()
用于将 IfBlock 实例及其子块转换为字符串形式的代码
class CallBlock
CallBlock 类可以调用某个方法或函数
constructor(object: any = {})
static class
类标识符,对于 IfBlock 实例,其值为 'CallBlock'
object: ObjectBlock
表示调用的目标对象
method: string
表示被调用的方法的名称
name: string
表示此调用块的名称
arguments: ArgumentBlock[]
表示调用的方法的参数
toCode()
将当前的 CallBlock 实例转化为 JavaScript 代码
static call(blockClass: any, id: string, method: string, args: any[])
用于执行函数调用
static checkCallError()
卡死检测
class MethodBlock
MethodBlock 类表示一个方法块,包含一个方法的信息
constructor(object: any = {})
object: string
表示方法所属的对象的名称
type: string
表示方法的类型
name: string
表示此方法块的名称
method: string
表示方法的名称
arguments: ArgumentBlock[]
表示方法的参数
cloneNode()
克隆当前 MethodBlock 实例的方法
class ArgumentBlock
ArgumentBlock 类表示一个参数块,包含一个参数的信息
constructor(object: any = {})
static class
'ArgumentBlock':表示这是一个 ArgumentBlock 类
name: string
表示此参数块的名称
expression: string
表示参数的表达式
type: string
表示参数的类型,默认为字符串
view: string
表示参数的视视类型,默认为文本输入框
unit: string
表示参数的单位
min: number
表示参数的最小值(数字类型)
max: number
表示参数的最大值(数字类型)
step: number
表示参数的步长(数字类型)
appendVariableEvent: boolean
表示是否附加变量事件
options:{ name: string; expression: string; value: any; [key: string]: any }[]
表示参数的选项列表
toCode()
将当前的 ArgumentBlock 实例转化为 JavaScript 代码
static convertOptions()
用于将参数选项列表转换为特定格式的数据结构
class ObjectBlock
ObjectBlock 类表示对象块,用于存储对象的信息
constructor(object: any = {})
static class
用于标识该类的类型
id
表示对象的标识符
name
表示对象的名称
static privateConfig
{
eventList:存储了 EventBlock 实例
methodList:存储了 MethodBlock 实例
}
static findModel()
根据传入的 blockClass 类型和标识符 id 查找对应的模型。根据不同的 blockClass 类型,返回相应的模型对象
static getMethodInfo()
根据传入的方法名 method 获取方法信息,目前该方法只返回方法名本身
class ProjectBlock
ProjectBlock 类主要用于描述系统对象块
constructor(object: any = {})
static class
'ProjectBlock',用于标识该类的类型
name: string
表示项目的名称,可以在构造函数中进行设置
static eventList
[
{mounted:表示项目启动时的事件},
{unmounted:表示项目退出时的事件},
{variable:表示变量满足某个条件时触发的事件,需要设置条件表达式和条件值},
{timer:表示定时执行的事件,需要设置开始时间、执行频率、结束时间等参数}
{alarm:表示报警触发的事件,需要设置报警点和已选列表}
]
static methodList: MethodBlock[]
私有方法
class PageBlock
页面对象块 对应 Page 配置页面动作信息(Page 中的方法)
constructor(object: any = {})
static class
'PageBlock',用于标识该类的类型
static methodList: MethodBlock[]
私有方法
class PageManagerBlock
PageManagerBlock 类主要用于描述页面管理器模块
constructor(object: any = {})
static class
'PageManagerBlock',用于标识该类的类型
static eventList
事件列表
static methodList: MethodBlock[]
私有方法
class CanvasNodeBlock
组件对象块 对应 CanvasNode 配置组件动作信息(CanvasNode 中的方法)
constructor(object: any = {})
static class
'CanvasNodeBlock',用于标识该类的类型
static privateConfig
私有配置
static eventList
事件列表
static methodList: MethodBlock[]
私有方法
models/Socket
class Socket
基于 SignalR 的 WebSocket 客户端,用于与服务器建立和维护实时双向通信。这个类封装了 SignalR 库的相关方法,提供了一些额外的功能,如事件注册、调用方法、连接管理等。
constructor(object: Partial<Socket> = {})
创建连接
url: string
表示 WebSocket 服务器的 URL 地址
name: string
表示 Socket 类的名称
connection: [signalR.HubConnection](signalR.HubConnection)
表示 SignalR 的 HubConnection 对象,用于与服务器建立和维护连接
callbackMap
用于保存事件回调信息的 Map 对象。当连接断开并重新连接时,会重新注册这些事件
call(...args: Parameters<signalR.HubConnection['invoke']>)
调用服务器端的方法,接受任意数量的参数。这个方法将参数传递给 SignalR 的 invoke 方法
on(type: string, callback: (...args: any[]) => void, params: Record<string, any>)
用于注册事件。接收事件类型(type)、回调函数(callback)和参数(params)作为输入。当事件触发时,会调用回调函数。此方法返回一个用于注销事件的函数
useOn(...args: Parameters<Socket['on']>)
用于 Vue 组件中自动注销事件。当组件卸载时,会自动调用 off 方法注销事件。此方法返回一个用于注销事件的函数
off(type: string, callback: Parameters<Socket['on']>[1])
用于注销事件。接收事件类型(type)和回调函数(callback)作为输入。它会从 callbackMap 中删除指定的回调信息,并取消 SignalR 的事件监听
startCount
表示重新连接的次数
start()
启动 WebSocket 服务。这个方法会尝试建立连接,如果连接失败,会根据重试次数等待一定时间后再次尝试。当首次连接成功时,会返回一个 Promise 对象
static lockWS()
静态方法,使用 Navigator.locks API 请求 WebSocket 锁。这可以确保在同一页面上同时只有一个 WebSocket 连接
static createConnection(url: string)
静态方法,根据给定的 URL 创建一个 SignalR 的 HubConnection 对象
models/Resource
class Resource
表示一个资源对象,如一个设计套件。它包含了与该资源相关的信息,如 id、名称、封面图片以及包含的 CanvasNode(画布节点)对象。
constructor(object: any = {})
id
资源的唯一标识符
name
资源的名称
cover: string
资源的封面图片 URL
canvasNode: CanvasNode
资源包含的画布节点(CanvasNode 对象)。一个资源通常包含一个根画布节点,根节点的子节点表示实际的设计元素
static getImages: string[]
接收一个 CanvasNode 对象作为参数,从中提取图片 URL。它会将 CanvasNode 对象转换为 JSON 字符串,然后使用正则表达式匹配所有的图片 URL。返回一个包含所有图片 URL 的数组,如果没有找到任何图片,则返回 null
models/Request
class Request
AJAX 请求
static get(url: string, config?: RequestConfig)
static post(url: string, data?: any, config?: RequestConfig)
static put(url: string, data?: any, config?: RequestConfig)
static delete(url: string, config?: RequestConfig)
static request(config: AxiosRequestConfig)
static baseURL: string
models/Dialog (TODO)
class Dialog
弹窗基类,仅定义结构,无功能实现
static Component: VueComponent
static async prompt(...args: unkown): Promise<unkown>
class VariableDialog extends Dialog
变量选择弹窗
static Component: VueComponent
vue 组件,覆盖它可实现自定义弹窗
新组件与原组件参数一致时直接覆盖此属性即可,否则需要重写 prompt
static async prompt(options: Record<string, any>): Promise<Variable>
创建弹窗并等待返回一个 Variable 实例
通过 this.Component 创建一个弹窗并等待返回一个结果。类比 window.prompt
class ExpressionDialog extends Dialog
表达式编写弹窗
static Component: VueComponent
同上
static async prompt(options: Record<string, any>): Promise<string>
同上
创建弹窗并等待返回一个表达式字符串
class AlarmDialog extends Dialog
告警点选择弹窗
static Component: VueComponent
同上
static async prompt(options: Record<string, any>): Promise<Alarm>
同上
创建弹窗并等待返回报警点对象
视图(V)
视图是 MVC 中的 V ,是用户界面,是 vue 组件
views/Project/Project.vue
该组件由以下几部分组成:Header.vue(头部)、Pages.vue(页面)
views/Project/Pages/Pages.vue
该组件由以下几部分组成:Sidebar.vue(侧边栏)、Editor.vue(编辑器)
views/Project/Pages/Sidebar/Sidebar.vue
该组件由以下几部分组成:PageList.vue(页面列表)、CanvasNodeList.vue(对象列表)
views/Project/Pages/Sidebar/PageList/PageList.vue
views/Project/Pages/Sidebar/CanvasNodeList/CanvasNodeList.vue
views/Project/Pages/Editor/Editor.vue
该组件由以下几部分组成:Board.vue(画板)、Settings.vue(配置栏)
events
hightLightPages(): 高亮页面功能区
views/Project/Pages/Editor/Board/Board.vue
画板
views/Project/Pages/Editor/Board/Canvas/Canvas.vue
画布
views/Project/Pages/Editor/Board/Canvas/CanvasNode.vue
画布节点
props
{
node: CanvasNode, // 这是要处理的CanvasNode
mode: string, // 模式
editing: boolean, // 是否处于编辑模式
running: boolean, // 是否处于运行模式
collect: boolean, // 是否需要清空收集多语言文本,一般由根节点清空,其他禁止清空(eg:画面容器嵌套)
}
views/Project/Pages/Editor/Board/Selector/Resizer.vue
控制拖动调整大小
views/Project/Pages/Editor/Board/Toolbar/Toolbar.vue
工具栏
views/Project/Pages/Editor/Board/WidgetLib/WidgetLib.vue
部件
views/Project/Pages/Editor/Board/Zoom/Zoom.vue
缩放
props
{
props: {
zoom:表示当前的缩放级别,默认值是1
initialZoom:表示初始化的缩放级别,默认值是1
maxZoom:表示最大的缩放级别,默认值是2
minZoom:表示最小的缩放级别,默认值是0.2
step:表示每次增加或减少的缩放级别的步长,默认值是0.1
}
}
views/Project/Pages/Editor/Board/History/History.vue
历史记录
views/Project/Pages/Editor/Board/Toolbar/LanguageSelect.vue
多语言
views/Project/Pages/Editor/Settings/Settings.vue
右侧栏,该组件由以下几部分组成:Style.vue(样式)、WidgetSettings.vue(控件设置)、Events.vue(事件)
views/Project/Pages/Editor/Settings/Style/Style.vue
样式
views/Project/Pages/Editor/Settings/WidgetSettings/WidgetSettings.vue
控件设置
views/Project/Pages/Editor/Settings/WidgetSettings/Permission.vue
权限控制
props
{
props: {
node: 要处理的CanvasNode
}
}
views/Project/Pages/Editor/Settings/Events/Events.vue
事件
views/Project/Pages/Viewer/Viewer.vue
页面文档渲染器
props
mode: App['mode'] = 'running' // 默认运行模式
document: Page['document'] = app.current.project.current.page.document // 默认渲染当前页面
events
示例
具体场景的使用示例
注入指令和多语言
初始化mount
前,需要进行指令、埋点和多语言的初始化
import { sdk } from 'syc-cms'
import { createApp } from 'vue'
import App from './App.vue'
import 'syc-cms/sdk/style.css'
const directives = sdk.import('@/directive/waves/index.ts').default
const track = sdk.import('@/directive/track/index').default
const { Language } = sdk.import('@/models/Language')
const app = createApp(App)
app.use(directives)
app.use(track)
Language.setVueGlobal(app)
挂载整个 CMS
挂载并渲染整个 CMS ,开发外部组件时使用,其它修改应该在渲染前处理。集成部分功能时不要使用
sdk.mount('#app')
移除某个组件
须在视图渲染前
const { Widget } = sdk.import('@/models/Widget') // 移除线条组件
delete Widget.store['Line'] // Widget.store 包含了所有组件信息
获取当前用户信息
用户在工程之下,不同工程用户不同
const { app } = sdk.import('@/models/App')
console.log(app.current.project.current.user)
发送请求
详见 models/Request
const { Request } = sdk.import('@/models/Request')
Request.post('url', { data })
如何只显示红色选中区域效果
需通过引入不同的组件来进行组装
新建 Pages.vue
<template>
<main
class="pages"
v-track:page="{
moduleType: '标准模块',
moduleCode: '自定义画面',
pageCode: '画面编辑',
}"
>
<Sidebar ref="sidebar"></Sidebar>
<Editor @hightLightPages="hightLightPages"></Editor>
</main>
</template>
<script setup lang="ts">
import { ref } from 'vue'
// 侧边栏
const Sidebar = sdk.import('@/views/Project/Pages/Sidebar/Sidebar.vue')
// 编辑区
const Editor = sdk.import('@/views/Project/Pages/Editor/Editor.vue')
const sidebar = ref()
const hightLightPages = () => {
sidebar.value.hightLight(true)
}
</script>
<style lang="scss" scoped>
.pages {
display: flex;
width: 100%;
height: 100%;
background: #101010;
}
</style>
选择指定模块拼接页面
例如这里不想将页面给添加到页面中,只显示如下图所示内容:
新建文件:Siderbar.vue
// Siderbar.vue
<template>
<aside class="sidebar" :class="{ 'active-page': isHightLight }">
<!-- 对象列表 -->
<CanvasNodeList class="CanvasNodeList"> </CanvasNodeList>
</aside>
</template>
<script setup lang="ts">
import { ref } from 'vue' // 对象列表
const CanvasNodeList = sdk.import(
'@/views/Project/Pages/Sidebar/CanvasNodeList/CanvasNodeList.vue'
)
// 高亮
const isHightLight = ref<boolean>(false)
const hightLight = (isActive: boolean) => {
isHightLight.value = isActive
if (isActive) {
setTimeout(() => {
isHightLight.value = false
}, 1500)
}
}
// 暴露出去,供父组件掉用
defineExpose({ hightLight })
</script>
<style lang="scss" scoped>
.sidebar {
flex: none;
width: 230px;
height: 100%;
background: #202020;
& > .CanvasNodeList,
& > .PageList {
width: 100%;
height: 50%;
}
}
.active-page {
border: 1px solid #3d6eff;
background: #252d46;
}
</style>
重新将改造后的 Siderbar.vue 引入到案例一中的 Pages.vue 中,即可实现效果
屏蔽工具栏多语言
通过 css 实现
.editor .toolbar .operation-btn:nth-last-child(2){ display: none;}
如何禁用事件方法和类型和新增事件方法或覆盖
import sdk from 'syc-cms'
import 'syc-cms/sdk/style.css'
const {
PageManagerBlock,
ProjectBlock,
CanvasNodeBlock,
MethodBlock,
ArgumentBlock,
} = sdk.import('@/models/Block.ts')
{
PageManagerBlock: 页面管理器对象块(目标)
ProjectBlock: 系统对象块(目标)
CanvasNodeBlock: 组件对象块(目标)
MethodBlock: 方法块(动作)
ArgumentBlock: 参数块(动作配置)}
禁用事件方法:
PageManagerBlock.methodList.splice(index, 1) // index为想要禁用事件方法的索引
禁用事件类型:
PageManagerBlock.eventList.splice(index, 1) // index为想要禁用事件类型的索引
新增事件方法:
每个动作都是一个 MethodBlock 实例,并可以通过 ArgumentBlock 实例进行配置。如果 arguments 数组为空,则该动作无需配置;如果 arguments 数组不为空,则每个 ArgumentBlock 实例表示一个配置项,用于指定不同的参数值。
PageManagerBlock.methodList.push(
new MethodBlock({
method: 'exportCurrentPage',
name: '导出画面',
arguments: [
new ArgumentBlock({
name: '目标页面',
view: ArgumentBlock.views.currentPage,
// options: exportData.exportTypeList1.map((e: any) => ({ ...e, value: `"${e.value}"` })),
}),
new ArgumentBlock({
name: '格式',
view: ArgumentBlock.views.radio,
options: exportData.exportTypeList1.map((e: any) => ({
...e,
value: `"${e.value}"`,
})),
}),
new ArgumentBlock({
name: '文件命名',
type: ArgumentBlock.types.string,
expression: '""',
}),
new ArgumentBlock({
name: '纸张大小',
view: ArgumentBlock.views.select,
options: paperTypeList().map((e: any) => ({
...e,
value: `"${e.value}"`,
})),
}),
new ArgumentBlock({
name: '布局',
view: ArgumentBlock.views.radio,
options: exportData.layoutList.map((e: any) => ({
...e,
value: `"${e.value}"`,
})),
}),
new ArgumentBlock({
name: '保存路径',
type: ArgumentBlock.types.string,
expression: '""',
}),
],
})
)
覆盖事件方法:
PageManagerBlock.methodList[index] = new MethodBlock({
method: 'reloadRoute',
name: '重载画面',
arguments: [],
})
弹窗替换
详见 models/Dialog
自定义页面保存逻辑
const { Page } = sdk.import('@/models/Page')
Page.prototype.save = function () {
// 当前页面的文档数据
console.log(this.document)
}
使用页面渲染器
<template>
<Viewer :mode="app.mode" :document="document" ></Viewer>
</template>
<script setup lang="ts">
const { app } = sdk.import('@/models/App')
const { Viewer } = sdk.import('@/views/Project/Pages/Viewer/Viewer.vue')
const document = app.current.project.current.page.document
</script>
...
注意
iconfont
cms 使用了 iconfont , css 类名为 .iconfont ,如果需要使用额外的 iconfont 图标库,则 css 类名不能再命名为 .iconfont
版本升级
版本升级会保持外部组件的兼容,功能集成则尽可能保持兼容但仍可能需手动修改小部分使用代码
示例版本 x
models/X
class X
newMethod()
views/.../X.vue
新增
views/path1/Y.vue
移至 views/path2/Y.vue
以下为版本差异部分的文档
2.0.2
起始版本
2.0.3
models/Widget
props
新建 CanvasNode 时作为 canvasNode 的默认 props