Skip to content

组态脚本开发

概述

用户可以通过编写 javascript 脚本实现以下功能:

  • 对整个图纸的数据模型进行操作
  • 对图元进行操作,包括获取属性、修改属性、设置图元的可见性
  • 监听实时数据变化
  • 查询实时数据
  • 查询历史数据
  • 实时数据绑定
  • 自定义数据绑定

数据模型(图元容器)

每张图纸都会有一个数据模型,它是一个图元容器,用于管理所有图元。 在图纸的初始化脚本中提供了数据模型的变量 dm。 image.png

javascript
// 获取图纸视图对应的数据模型
const dm = gv.dm()
// 获取该图元对象所属的数据模型
const dm = data.dm()

对数据模型属性进行取值和赋值

示例:

javascript
// 赋值操作
dm.a('myvalue', 100)
// 取值操作
var myvalue = dm.a('myvalue')
// 批量赋值操作
dm.a({
	myvalue1: 101,
  myvalue2: 102
})

参数说明:

名称类型允许为空说明
nameString | Object属性名 | 属性键值对对象
valueObject属性值
  1. 一个参数:
    • 当参数为 String 时相当于取值操作;
    • 当参数为 Object 时,则会遍历该 Object 中的字段,设置属性值;
  2. 两个参数: 相当于赋值操作

根据标签快速查找图元对象

数据模型内部维护着一个“标签”->“图元”的映射表,因此可以通过“标签”快速找到对应的“图元”对象。 image.png 示例:

javascript
// dm 为数据模型对象
const data = dm.getDataByTag('1vdk3x9ips0')

遍历图元对象

示例:

javascript
// 遍历所有图元对象
dm.each(function(data) {
  // your code here
})

获取实时数据绑定对象

数据模型中提供了一个“自定义数据绑定对象”以方便用户实现自定义的数据绑定功能。关于自定义数据绑定对象的使用请参考第 5 章,关于“自定义数据绑定对象”中的说明。 示例:

javascript
// 获取实时数据绑定对象
const rtdb = dm.db()
// 单测点数据绑定
rtdb.singleBind('mydevice1.t1', function(point) {
  const value = point.value
  const timestamp = point.timestamp
  const quality = point.quality
  // 你的代码写在这里
  console.log(value)
})

获取自定义数据绑定对象

数据模型中提供了一个“自定义数据绑定对象”以方便用户实现自定义的数据绑定功能。 示例:

javascript
// 获取自定义数据绑定对象
const customDB = dm.customDB()
// 自定义数据绑定
customDB.bind('mydevice1.t1', function(newValue, oldValue) {
  // 数据更新时会执行这里面的代码
  console.log(newValue, oldValue)
})
// 更新自定义数据
customDB.update('mydevice1.t1', 100)

画面对象

画面对象是对应组态画面的操作对象,类名为 GraphView。在组态脚本中一般以 view 或 gv 命名。图纸初始化函数function(dm, gv),以及图元初始化函数function(data,gv),中的 gv 就是画面对象。

获取整个画面对应的数据模型

示例:gv.dm()

遍历所有图元对象

javascript
gv.each(function(data) {
  console.log(data);
});

画面适配

javascript
// 重置画面以适配屏幕
gv.fitContent()
// 重置画面以适配某个元素
gv.fitData(data) // data 为某个图元对象

画面缩放

javascript
// 放大
zoomIn(anim, point) 
// 缩小
zoomOut(anim, point) 
// 设置缩放值为1
zoomReset(anim, point) 
//获取和设置缩放比例(1 表示原始比例)
getZoom()和setZoom(value, anim, point)

画面平移

javascript
setTranslate(x, y, anim) // 设置新的水平平移和垂直平移值,anim代表是否启用动画
getTranslateX()和setTranslateX(10) // 获取和设置当前水平平移值,简写为tx()和tx(10)
getTranslateY()和setTranslateY(10) // 获取和设置当前垂直平移值,简写为ty()和ty(10)
translate(tx, ty) // 在当前值基础上增加水平和垂直平移值
adjustTranslateX(value) // 该函数传入即将设置的水平平移值,返回最终设置值,可重载限制水平平移范围
adjustTranslateY(value) // 该函数传入即将设置的垂直平移值,返回最终设置值,可重载限制垂直平移范围

图层操作

获取已定义的图层

javascript
// 以数组的方式返回所有图层
var layers = gv.getLayers()
// 以对象方式返回所有图层,对象的key为图层的名称,value为图层对象具体的配置属性
var layersInfo = gv.getLayersInfo()

图层对象示例如下:

typescript
{
    name: "layer1",
    visible: true, // 图层可见性
    selectable: true, // 图层元素是否可远
    movable: true, // 图层元素是否可移动
}

修改图层配置

获取到具体某个图层的配置对象之后,可以直接修改这个配置对象具体的属性,但是要值得注意的是,如果是直接修改layer对象的属性,是没有事件派发,这种情况下需要调用下GraphView#iv()强制更新下。

下面是一个控制图层是否可见的示例:

javascript
var layersInfo = gv.getLayersInfo()
var layer1 = layersInfo['layer1']
// 将 layer1 设置为不可见
layer1.visible = false
// 手动触发整个画面重绘
gv.iv()

弹出趋势曲线图

弹出相应测点的趋势图窗口,可重复调用添加多个测点。

javascript
var option = {
  deviceID: '',  // 设备标识
  pointID: '',   // 测点标识
  grid: '0,0',   // 曲线所属的网格坐标,最大可以划分为 3X3 的网格。
  yname: '',     // Y轴名称:同一个网格下,允许出现多个 Y 轴,通过名称进行区分。
  ypos: 'left',  // Y轴位置:Y轴默认在左侧显示,可设置为右侧显示或不显示,可选值为:left, right, hide
}
// 弹出趋势窗口并追加测点
gv.pageHandler.showTrends(option)
// 弹出趋势窗口不追加测点
gv.pageHandler.showTrends()
// 弹出趋势窗口并清空之前的测点
gv.pageHandler.showNewTrends(option)

趋势图窗口默认只显示一个网格,最大可以划分为 3X3 的网格,使用时可通过 grid 参数设置网格坐标,网格划分:

序号123
10,00,10,2
21,01,11,2
32,02,12,2

下面是一个 2X2 网格界面: image.png

切换到指定的图纸

图纸地址可以在编辑器中查看,如下图所示: image.png

javascript
gv.loadUrl('displays/cid86ghmn3di2j1lf21g.json')
// 切换指定的图纸,并追加附加参数(extraParams)
gv.loadUrl('displays/cid86ghmn3di2j1lf21g.json', {
  p1: '...',
  p2: '...',
})

弹窗显示指定图纸

javascript
gv.showPopup({
  displayUrl: 'displays/cid86ghmn3di2j1lf21g.json',
  popupWidth: 500,
  popupHeight: 500,
  popupTitle: '',
  popupShowModal: false,
}, extraParams)

在指定节点上显示工具提示

typescript
// 函数定义
gv.showTooltips = (
    data: ht.Node,
    content: string,
    option?: {
        placement?: 'top' | 'bottom' | 'left' | 'right'
    	html?: boolean
    }
) => void

// 使用示例
gv.showTooltips(targetNode, 'Hello World!')
gv.showTooltips(targetNode, '<bold>Hello World!</bold>', { html: true })

画面销毁回调

如果用户通过脚本启动了一个定时器,可以在画面销毁时关闭该定时器,画面对象提供了一个画面销毁时的一个回调函数,方便用户调用。

javascript
var timer = setInterval(function() {
  console.log(new Date())
}, 1000)
gv.dm().onDestroy(function() {
  clearInterval(timer)
})

图元对象

图元对象在组态脚本中一般以 data 命名,支持对图元的属性和样式进行取值或赋值。 鼠标放在绑定按钮上,可以查看相应的属性或样式名称,如下图所示: image.png

“a:value”表示属性名为“value” “s:value”表示样式名为“value”

对图元对象属性进行取值和赋值

示例:

javascript
// 赋值操作
data.a('myvalue', 100)
// 取值操作
var myvalue = data.a('myvalue')
// 批量赋值操作
data.a({
	myvalue1: 101,
  myvalue2: 102
})

参数说明:

名称类型允许为空说明
nameString | Object属性名 | 属性键值对对象
valueObject属性值
  1. 一个参数:
    • 当参数为 String 时相当于取值操作;
    • 当参数为 Object 时,则会遍历该 Object 中的字段,设置属性值;
  2. 两个参数: 相当于赋值操作

对图元对象样式进行取值和赋值

示例:

javascript
// 赋值操作
data.s('2d.visible', true)
// 取值操作
var myvalue = data.s('2d.visible')
// 批量赋值操作
data.s({
	'2d.visible': true,
  'label': '设备' 
})

参数说明:

名称类型允许为空说明
nameString | Object样式名 | 样式键值对对象
valueObject样式值
  1. 一个参数:
    • 当参数为 String 时相当于取值操作;
    • 当参数为 Object 时,则会遍历该 Object 中的字段,设置样式值;
  2. 两个参数: 相当于赋值操作

从图元对象中获取数据模型对象

示例:

javascript
const dm = data.dm()

遍历图元子对象

对该图元对象下的所有子元素进行遍历

javascript
data.eachChild(function(child) {
  console.log(child);
});

设备图标

用户可以通过以下方式将图元绑定到设备: 绑定设备后,可以通过脚本获取绑定的设备信息:

javascript
const deviceInfo = data.a('deviceInfo')
const id = deviceInfo.id // 设备标识

创建动画

javascript
const animat = data.startAnimat({
  duration: 1000,// 持续时长
  // autoReverse: true, // 是否自动返回
  repeat: true,// 是否重复执行
  easing: 'linear', // 缓动函数
  onUpdate: function(val, t) {
    // val和t为 0-1 之间变化的数值,t 为线性变化,val 基于缓动函数线性变化
    data.setScaleX(0.5 + 0.5 * val)
    data.setScaleY(0.5 + 0.5 * val)
  },
  onFinished: function() {
    // 动画结束时执行
  }
})
// 暂停动画
// animat.pause()
// 恢复动画
// animat.resume()
// 停止动画
// animat.stop()
// 启动动画
// animat.start()

默认缓动函数为 linear(线性变化),其它非线性变化如下:

TypeInOutIn-Out
backeaseInBackeaseOutBackeaseInOutBack
bounceeaseInBounceeaseOutBounceeaseInOutBounce
circeaseInCirceaseOutCirceaseInOutCirc
cubiceaseInCubiceaseOutCubiceaseInOutCubic
elasticeaseInElasticeaseOutElasticeaseInOutElastic
expoeaseInExpoeaseOutExpoeaseInOutExpo
quadeaseInQuadeaseOutQuadeaseInOutQuad
quarteaseInQuarteaseOutQuarteaseInOutQuart
quinteaseInQuinteaseOutQuinteaseInOutQuint
sineeaseInSineeaseOutSineeaseInOutSine

其它操作

javascript
// 获取父节点对象
const parent = data.getParent()
// 遍历子节点
data.eachChild(child => {})
// 设置可见性
data.s('2d.visible', true)

数据接口

监听点位实时数据变化

javascript
// 监听数据
const listener = window.iotopo.ws.subscribe('rtdb.mydevice1.t1', function(point) {
    const value = point.value
    const timestamp = point.timestamp
    const quality = point.quality
})
// 取消监听
gv.ws.unsubscribe(listener)

查询实时数据

单点查询

javascript
const deviceID = 'mydevice1'
const pointID = 't1'
window.iotopo.api.data.findLast({
  deviceID: deviceID,
  pointID: pointID
}).then(function (point) {
  const value = point.value
  const timestamp = point.timestamp
  const quality = point.quality
})

批量查询

javascript
const deviceID = 'mydevice1'
const pointID = 't1'
window.iotopo.api.data.findLastBatch([
  {
    deviceID: deviceID,
    pointID: 't1'
  },
  {
    deviceID: deviceID,
    pointID: 't2'
  }
]).then(points => {
  if (points) {
    points.forEach(point => {
      const value = point.value
      const timestamp = point.timestamp
      const quality = point.quality
    })
  }
})

查询历史数据

用于查询多个点位在某时间范围内的时序数据,示例:

javascript
window.iotopo.api.data.query({
  points: [
    {
      deviceID: 'mydevice1',
  		pointID: 't1',
    },
    {
      deviceID: 'mydevice1',
  		pointID: 't2',
    }
  ],
  start: '',
  end: '',
  aggregation: 'last', // first,last,min,max,mean
  interval: '5s', // 支持 s/m/h/d/w
  offset: 0,
  limit: 5000
}).then(resp => {
	const results = resp.results
  if (Array.isArray(results)) {
  	results.forEach(result => {
    	const deviceID = result.deviceID
      const pointID = result.pointID
      const values = result.values
      
      values.forEach(item => {
      	const value = item.value
        const time = item.time

      })
    })
  }
})

请求参数

名称类型是否必选说明
pointsobject[]查询的数据点
startstring起始时间。ISO 8601格式: YYYY-MM-DDTHH:MM:SSZ。如2021-04-22T22:02:46+08:00。
endstring结束时间。ISO 8601格式: YYYY-MM-DDTHH:MM:SSZ。如2021-04-22T22:02:46+08:00。
aggregationstring聚合方式。
intervalstring分组时间间隔。格式为数字+单位,如1ns|u|ms|s|m|h|d|w。指定时必须指定 aggregation。可通过fill指定没有数据点时的返回值。
fillstring指定时必须同时指定interval,表示分组时间间隔未查询到数据点时的填充值。
offsetint数据偏移量。默认值为0,表示不偏移。
limitint返回数据量。默认值为0,表示不限制。
aggregation 聚合方式可选值:
  • last:最新值。
  • first:最旧值。
  • min:最⼩值。
  • max:最⼤值。
  • mean:平均值。

fill 可选值:

  • 任意数值:⽤这个数字返回没有数据点的时间间隔的数据。

  • linear:返回没有数据点的时间间隔的线性插值的结果。

  • none:不返回在时间间隔⾥没有点的数据。

  • previous:返回时间间隔的前⼀个间隔的数据。

返回参数

名称类型说明
results[i].deviceIDstring数据项[i]的设备标识。
results[i].pointIDstring数据项[i]的点位标识。
results[i].values[j].valueany点位值。
results[i].values[j].timestring点位值对应的时间戳。

查询累计量变化值

用于查询某累计量测点,在一定时间范围内,连续多个时间单位内的变化量,返回结果为 json 对象数组,示例:

javascript
window.iotopo.api.data.queryAcc({
  deviceID: 'ROOM1',
  pointID: 'RunningEnergyAcc',
  start: '2024-10-31T16:00:00.000Z',
  end: '2024-11-30T16:00:00.000Z',
  type: 'hourly'
}).then(resp => {
  let sum = 0 // 用于计算该每小时能耗之和(kWh)
  resp.forEach(item => {
    const time = item.time
    const value = item.value
    if (value > 0) {
      sum += value
    }
  })
})

请求参数

请求参数为 json 对象,支持的字段如下:

名称类型是否必选说明
deviceIDstring设备标识
pointIDstring点位标识
startstring起始时间。ISO 8601格式: YYYY-MM-DDTHH:MM:SSZ。如2021-04-22T22:02:46+08:00。
endstring结束时间。ISO 8601格式: YYYY-MM-DDTHH:MM:SSZ。如2021-04-22T22:02:46+08:00。
typestring统计方式:hourly daily monthly

统计方式:

  • hourly:计算每小时的变化值
  • daily:计算每天的变化值
  • monthly:计算每月的变化值

返回参数

返回结果为 json 对象数组。json 对象字段如下:

名称类型说明
timestring|Date数据项[i]对应的时间,ISO 8601格式: YYYY-MM-DDTHH:MM:SSZ。
valuenumber数据项[i]对应该时间的变化值。

修改点位值

示例:

javascript
const deviceID = 'mydevice1'
const pointID = 't1'
const value = '100' // 必须是字符串类型
window.iotopo.api.data.setValue({
	deviceID: deviceID,
  pointID: pointID,
  value: value
}).then(() => {
  // 操作成功
})

批量修改点位值(废弃)

批量修改多个点位的值,可以指定多个设备,但要确保是同一个网关下的设备。 示例:

javascript
window.iotopo.api.data.batchSetValue({
  'mydevice1': {
    't1': '1',
    't2': '1',
    't3': '0'
  },
  'mydevice2': {
    't1': '1',
    't2': '1',
    't3': '0'
  }
})

监听设备状态变化

javascript
const deviceID = 'mydeviceid'
const listener = window.iotopo.ws.subscribe('deviceState.'+deviceID, function(item){
  const state = item.state // 1 表示在线,0 表示离线
  const timestamp = item.timestamp 
  // timestamp 为 ISO 8601格式: YYYY-MM-DDTHH:MM:SSZ。如2021-04-22T22:02:46+08:00
  // 你的业务代码
  console.log(state)
})
// 取消监听
window.iotopo.ws.unsubscribe(listener)

监听通道状态变化

javascript
const channelID = 'xxxxxxx'
const listener = window.iotopo.ws.subscribe('channelState.'+channelID, function(item){
  const connected = item.connected // true 表示连接,false 表示断开
  const timestamp = item.timestamp 
  // timestamp 为 ISO 8601格式: YYYY-MM-DDTHH:MM:SSZ。如2021-04-22T22:02:46+08:00
  // 你的业务代码
  console.log(connected)
})
// 取消监听
window.iotopo.ws.unsubscribe(listener)

监听网关状态变化

javascript
const gatewayID = 'xxxxxxx'// 网关标识
const listener = window.iotopo.ws.subscribe('gatewayState.'+gatewayID, function(item){
  const state = item.state // 1 表示在线,0 表示离线
  const timestamp = item.timestamp 
  // timestamp 为 ISO 8601格式: YYYY-MM-DDTHH:MM:SSZ。如2021-04-22T22:02:46+08:00
  // 你的业务代码
  console.log(state)
})
// 取消监听
window.iotopo.ws.unsubscribe(listener)

监听实时告警消息

javascript

const listener = window.iotopo.ws.subscribe('alert',  function(item){
  // item 下包含的字段如下
  // status: string;// 状态: unhandled(未处理),handled(已处理), ignored(已忽略)
  // createdAt: string;// 发生告警的时间,ISO 8601格式: YYYY-MM-DDTHH:MM:SSZ
  // recoveredAt: string;// 解除告警的时间,ISO 8601格式: YYYY-MM-DDTHH:MM:SSZ
  // alertTypeName: string;// 告警类型
  // alertLevelLabel: string;// 告警等级
  // alertLevelColor: string;// 告警颜色
  // deviceGroupName: string;// 设备分组名称
  // deviceName: string;// 设备名称
  // deviceID: string;// 设备标识
  // pointName: string;// 测点名称
  // pointID: string;// 测点标识
  // compareValue: string;//比较值
  // inputValue: string;// 告警值
})
// 取消监听
window.iotopo.ws.unsubscribe(listener)

查询告警记录

javascript
window.iotopo.api.alert.query({
    pageNum: 1,
    pageSize: 10,
    actived: true, // true 表示只显示活动告警
    start: '',// 起始时间,ISO 8601格式: YYYY-MM-DDTHH:MM:SSZ,可以为空
    end: '', // 结束时间,ISO 8601格式: YYYY-MM-DDTHH:MM:SSZ,可以为空
    deviceName: '', // 设备名称搜索,可以为空
}).then(resp => {
  const rows = resp.records // 告警记录数组(json 对象数组)
  const total = resp.total // 告警记录总数
})

告警记录字段说明:

名称类型说明
idstring告警记录标识
statusstring告警状态:unhandled/handled/ignored
createdAtstring告警发生时间,ISO8601 格式
recoveredAtstring告警解除时间,ISO8601 格式,空表示新产生的告警,不为空表示告警解除或者状态更新。
handledAtstring确认告警时间
handlerstring告警确认人
remarkstring确认信息备注
titlestring告警标题
contentstring告警内容
deviceIDstring设备标识
pointIDstring测点标识
inputValuestring告警值
durationnumber持续时长(秒)
modestring触发方式
compareModestring比较方式
compareValuestring告警阈值
deadBandnumber死区值
diffnumber偏差值

状态说明:

  • unhandled 未确认
  • handled 已确认
  • ignored 已忽略

触发方式:

  • point:单测点
  • not_upload:长时间不上传
  • not_change:长时间数据不变化
  • offline:设备离线
  • expression:表达式

比较方式:

  • >
  • >=
  • <
  • <=
  • =
  • !=
  • 区间内(between):测点值处于区间外时,触发告警。区间格式:(100, 200), [100,200]
  • 区间外(not_between):测点值处于区间内时,触发告警。
  • 数值偏差(diff):测点值与阈值的差值大于偏差值时,触发告警。

查询数据集

javascript
window.iotopo.api.dataset.query({
  id: '<数据集标识>', // 数据集标识
  params: {} // 变量参数 json 对象
}).then(resp => {
  const rows = resp.rows // 结果集数组(json 对象数组)
  const total = resp.total // 结果集总数(分页查询时有效)
})

数据绑定

单测点数据绑定

函数名称:singleBind 示例:

javascript
// 获取实时数据绑定对象
const rtdb = dm.db()
// 单测点数据绑定
const bind = rtdb.singleBind('mydevice1.t1', function(point) {
  const value = point.value
  const timestamp = point.timestamp
  const quality = point.quality
})
// 消除绑定
bind.unbind()

参数说明:

名称类型说明
bindingIDString数据绑定ID,格式为设备标识和点位标识的组合,中间用 “.”拼接,如设备标识为 dev1,点位标识为 p1,绑定ID 为 "dev1.p1"
callbackFunction回调函数,当订阅的数据发生变化时,触发回调函数的执行,并将测点当作参数传入回调函数中,测点对象包括的字段如下:
value:测点当前值
quality:测点数据质量,0 表示正常,1 表示离线,2 表示无效
timestamp:时间戳

多测点数据绑定

函数名称:multiBind

DANGER

当其中一个测点数据发生变化时就会触发回调函数的执行,所以回调函数中的测点值有可能是 null。

javascript
// 从数据模型对象中获取数据绑定对象
const rtdb = dm.db()
// 调用数据绑定对的多测点绑定方法
const bind = rtdb.multiBind(['mydevice1.t1', 'mydevice1.t2', 'mydevice1.t3'], function(t1, t2, t3) {
  if (t1 !== null && t2 !== null && t3 !== null) {
    const avg = (t1 + t2 + t3) / 3
    console.log(avg)
  }
})
// 消除绑定
bind.unbind()

数据集绑定

用于通过脚本方式触发【数据集绑定】的数据更新。

javascript
// 更新指定标识的数据集
dm.db().updateDataset(id)

HTTP 绑定

用于通过脚本方式触发【HTTP 绑定】的数据更新。

javascript
// 触发绑定的 HTTP 请求
dm.db().updateHTTP('此处为标识')

本地变量绑定

获取数据容器的本地变量管理对象:dm.localDB()

更新本地变量值:dm.localDB().setValue('mydevice1.t1', 100) 获取本地变量值:dm.localDB().getValue('mydevice1.t1') 监听本地变量:

javascript
dm.localDB().on('mydevice1.t1', function(event) {
  var newValue = event.newValue
  var oldValue = event.oldValue
})

全局变量(5.6.0)

本地变量只在当前浏览器页面中有效,无法在多个浏览器终端中共享。我们可以通过定义全局变量,实现在多个浏览器终端中共享数据。

typescript
/**
 * 订阅全局变量
 * @varName 命名空间名称
 * @callback  回调函数,当监测到有变量值发生变化时调用
 */
subscribe: (varName: string, callback: (value: any, varName: string) => void) => (listener: any)

/**
 * 取消订阅
 */
unsubscribe: (listener: any)
  
/**
 * 更新全局变量
 * @namespace 命名空间名称
 * @payload   更新的变量,包括变量名和变量值
 */
publish: (varName: string, value: any) => void

订阅全局变量

可以在每个页面的初始化脚本里订阅某命名空间下的全局变量,初次订阅会自动将该变量的当前值推送过来。

javascript
// 获取或创建命名空间为 default 的全局变量操作对象
const sd = dm.globalDB('default')
// 订阅 default 命名空间下的 v1 变量
const listener = sd.subscribe('v1', function(value, varName) {
  // 此处可以对接收到的变量名和变量值进行判断,然后执行其它脚本
})
// 取消订阅
// sd.unsbscribe(listener)

更新全局变量

执行更新全局变量脚本后,将向所有监听该变量的页面推送数据。

javascript
// 获取或创建命名空间为 default 的全局变量操作对象
const sd = dm.globalDB('default')
// 将 default 命名空间下的 v1 变量的值设置为 true
sd.publish('v1', true)

工具类

日期时间

系统内置了 dayjs 日期时间库,具体使用方法可以参考 dayjs 文档。 操作对象: window.iotopo.utils.dayjs

javascript
const dayjs = window.iotopo.utils.dayjs
dayjs('2019-01-25').format('DD/MM/YYYY') // '25/01/2019'
dayjs('1999-01-01').fromNow() // 22 年前
// 返回增加一定时间的复制的 Day.js 对象。
dayjs().add(7, 'day')
// 返回复制的 Day.js 对象,并设置到一个时间的开始。
dayjs().startOf('year')

HTTP 请求

系统内置了 axios 库,用于发送 http 请求,具体使用访求可以参考 axios 文档 。 操作对象:window.iotopo.utils.axios

javascript
window.iotopo.utils.axios.get('/user?ID=12345')
.then(function (response) {
  // 处理成功情况
  console.log(response);
})
.catch(function (error) {
  // 处理错误情况
  console.log(error);
})
.then(function () {
  // 总是会执行
});

数值格式化

操作对象:window.iotopo.utils.numeral

javascript
var string1 = window.iotopo.utils.numeral(1000).format('0,0'); // '1,000'
var string2 = window.iotopo.utils.numeral(1).format('0000.0'); // '0001.0'

获取URL参数值

获取组态画面所在浏览器或 iframe 中的 url 参数值

javascript
var value = window.iotopo.utils.getQueryString('paramName')

导出 CSV 文件(V5.2.x)

javascript
var lines = [
    ['index', 'name', 'value'],
    [1, '温度', 20],
    [2, '湿度', 80]
]
window.iotopo.utils.csvExport(lines, '设备数据.csv')

TTS 语音合成

// 语音播放指定文本内容,重复执行会依次播放相应内容 
window.iotopo.tts.speak('你好,现在播放的是一段测试内容。')
// 暂停播放
window.iotopo.tts.pause()
// 恢复播放
window.iotopo.tts.resume()

消息提示

可显示 info、warning、sucess、error 4 种级别的消息提示。更多使用方法请参考:ElementPlus 文档 操作对象:window.iotopo.Message

javascript
const Message = window.iotopo.Message
Message.info('消息内容')
Message.warning('消息内容')
Message.success('消息内容')
Message.error('消息内容')

消息弹框

模拟系统的消息提示框而实现的一套模态对话框组件,用于消息提示、确认消息和提交内容。更多使用方法请参考:ElementPlus 文档 操作对象:window.iotopo.MessageBox

javascript
window.iotopo.MessageBox.alert('This is a message', 'Title', {
  // if you want to disable its autofocus
  // autofocus: false,
  callback: (action) => {
    //
  }
})
javascript
window.iotopo.MessageBox.confirm(
  'proxy will permanently delete the file. Continue?',
  'Warning',
  {
    type: 'warning',
    draggable: true
  }
).then(() => {
  // 确认
}).catch(() => {
  // 取消
})
javascript
window.iotopo.MessageBox.prompt('请输入邮件地址', '提示').then((data) => {
  console.log('输入内容为:', data.value)
}).catch(() => {
  console.log('取消')
})

消息通知

悬浮出现在页面角落,显示全局的通知提醒消息,可显示 info、warning、sucess、error 4 种级别。更多使用方法请参考:ElementPlus 文档 操作对象:window.iotopo.Notification

javascript
window.iotopo.Notification({
  title: 'Prompt',
  message: 'This is a message that does not automatically close',
  duration: 0, // 显示时间, 单位为毫秒。 值为 0 则不会自动关闭
  position: 'top-right', // 支持四个选项:top-right、top-left、bottom-right 和 bottom-left, 默认为 top-right
})
window.iotopo.Notification({
  title: 'Success',
  message: 'This is a success message',
  type: 'success', // 通知的类型: success/warning/info/error
})

移动端支持

基于 ElementPlus 提供的消息提示、消息弹框、消息通知仅适用于桌面应用,TopStack 针对移动端应用引入了 weui ,如果制作移动应用,可以使用 weui 实现类似的功能。

DANGER

部分功能的调用方式与 ElementPlus做了兼容处理,具体可以参考各项功能的调用示例。

下面是 weui 相关的示例。

消息提示框

image.png

javascript
weui.alert('自定义标题的alert', function () {
    console.log('ok')
}, {
    title: '自定义标题'
});
// 移动端运行环境下,下面的调用方式是等价的
window.iotopo.MessageBox.alert('自定义标题的alert', '自定义标题', {
  callback: () => {
    //
  }
})

消息确认框

image.png

javascript
weui.confirm('自定义内容的confirm', function () {
    console.log('yes')
}, function () {
    console.log('no')
});
// 移动端运行环境下,下面的调用方式是等价的
window.iotopo.MessageBox.confirm('自定义内容的confirm?').then(() => {
  // 确认
  console.log('yes')
}).catch(() => {
  // 取消
  console.log('no')
})

吐司提示(Toast)

image.png

javascript
weui.toast('操作成功', {
    duration: 3000,
    className: "bears"
});
// 移动端运行环境下,下面的调用方式是等价的
window.iotopo.Notification({
  duration: 3000, // 显示时间, 单位为毫秒。 值为 0 则不会自动关闭
  message: '操作成功'
})

加载指示(Loading)

image.png

javascript
var loading = weui.loading('loading');
setTimeout(function () {
    loading.hide();
}, 3000);

动作面板(ActionSheet)

image.png

javascript
weui.actionSheet([
    {
        label: '拍照',
        onClick: function () {
            console.log('拍照');
        }
    }, {
        label: '从相册选择',
        onClick: function () {
            console.log('从相册选择');
        }
    }, {
        label: '其他',
        onClick: function () {
            console.log('其他');
        }
    }
], [
    {
        label: '取消',
        onClick: function () {
            console.log('取消');
        }
    }
], {
    title: 'actionTitle',
    onClose: function(){
        console.log('关闭');
    },
    onClickMask: function() {
        console.log('点击mask');
    },
});

顶部消息提示(TopTips)

image.png

javascript
weui.topTips('请填写正确的字段', {
    duration: 3000,
    callback: function () {
        console.log('close');
    }
});
// 移动端运行环境下,下面的调用方式可产生相同效果
window.iotopo.Message({
  type: 'error',
  duration: 3000, // 显示时间, 单位为毫秒。 值为 0 则不会自动关闭
  message: '请填写正确的字段',
  'on-close': function () {
      console.log('close');
  }
})

普通选择器

image.png

javascript
weui.picker([{
        label: '飞机票',
        value: 0
    }, {
        label: '火车票(disabled)',
        disabled: true,
        value: 1
    }, {
        label: '的士票',
        value: 2
    }, {
        label: '住宿费',
        value: 3
    }, {
        label: '礼品费(disabled)',
        value: 4,
        disabled: true,
    }, {
        label: '活动费',
        value: 5
    }, {
        label: '通讯费',
        value: 6
    }, {
        label: '补助',
        value: 7
    }, {
        label: '通讯费',
        value: 8
    }, {
        label: '其他',
        value: 9
    }], {
        defaultValue: [2],
        className: 'custom-classname',
        confirmText: 'OK',
        closeText: 'close',
        onChange: function (result) {
            //console.log(item, index);
            console.log(result);
        },
        onConfirm: function (result) {
            console.log('confirm');
            console.log(result);
        },
        id: 'picker',
        title: '单列选择器',
        desc: '单列选择器描述',
    });

日期选择器

image.png

javascript
weui.datePicker({
    start: '2016-12-29',
    end: '2030-12-29',
    defaultValue: [2017, 7, 9],
    onChange: function (result) {
        console.log(result);
    },
    onConfirm: function (result) {
        console.log(result);
    },
    id: 'datePicker',
    title: '日期选择器'
});

多列选择器

image.png

javascript
weui.picker([
    {
        label: '1',
        value: '1'
    }, {
        label: '2',
        value: '2'
    }, {
        label: '3',
        value: '3'
    }
], [
    {
        label: 'A',
        value: 'A'
    }, {
        label: 'B',
        value: 'B'
    }, {
        label: 'C',
        value: 'C'
    }
], {
    defaultValue: ['3', 'A'],
    onChange: function (result) {
        console.log(result);
    },
    onConfirm: function (result) {
        console.log(result);
    },
    id: 'multiPickerBtn',
    onClose: function(){
        console.log('onClose');
    },
    title: '多列选择器'
});

级联选择器

image.png

javascript
weui.picker([
    {
        label: '广东',
        value: 0,
        children: [
            {
                label: '广州',
                value: 0,
                children: [
                    {
                        label: '海珠',
                        value: 0
                    }, {
                        label: '番禺',
                        value: 1
                    }
                ]
            }, {
                label: '佛山',
                value: 1,
                children: [
                    {
                        label: '禅城',
                        value: 0
                    }, {
                        label: '南海',
                        value: 1
                    }
                ]
            }
        ]
    }, {
        label: '广西',
        value: 1,
        children: [
            {
                label: '南宁',
                value: 0,
                children: [
                    {
                        label: '青秀',
                        value: 0
                    }, {
                        label: '兴宁',
                        value: 1
                    }
                ]
            }, {
                label: '桂林',
                value: 1,
                children: [
                    {
                        label: '象山',
                        value: 0
                    }, {
                        label: '秀峰',
                        value: 1
                    }
                ]
            }
        ]
    }
], {
    depth: 3,
    defaultValue: [0, 1, 1],
    onChange: function (result) {
        console.log(result);
    },
    onConfirm: function (result) {
        console.log(result);
    },
    id: 'cascadePicker',
    title: '嵌套选择器'
});

其它

将当前图纸导出为图片(Base64格式)

javascript
const imageSize = 256
const rect = gv.getContentRect();
const zoom = Math.min(1, imageSize / Math.max(rect.width, rect.height));
const base64 = gv.toDataURL(undefined, undefined, zoom)