简单跳页、单值写入、变量切换和打开诊断窗,优先使用插件提供的标准行为。只有动作需要条件判断、多个输入组合、连续步骤或动态目标计算时,再使用脚本。
脚本方法使用说明 | HQ VISU Designer
脚本用于处理配置行为无法直接覆盖的计算、校验、组合动作和页面联动。能够通过 Page Script 变量、Tag 绑定、模板配置和内置行为表达的内容,应优先使用标准配置。
使用前说明
脚本用于处理配置行为无法直接覆盖的计算、校验、组合动作和页面联动。能够通过 Page Script 变量、Tag 绑定、模板配置和内置行为表达的内容,应优先使用标准配置。
脚本适合承载条件组合、页面联动和复杂动作,不适合替代所有标准行为。页面应优先通过可见配置表达动作意图,让后续维护人员能直接理解对象职责。
建议先了解 Page Script、Definition、Click Script 和 Hover Script 的入口差异,再阅读 Tag 读写方法,最后参考页面对象方法和常见组合。
先决定脚本入口
同一段逻辑放在不同入口,运行时机和可用上下文不同。先明确入口职责,再编写具体方法。
当前 PPT 导出按页面独立维护脚本文档。页面内初始化、表格数据、标题和局部联动优先放在当前页 Page Script;确实需要复用的能力,优先由宿主 runtime 或模板本身提供,不再依赖一个全局脚本文档承载所有页面逻辑。
- 页面逻辑放当前页 Page Script
- 跨页复用优先交给宿主 runtime 或模板
- 单页流程不应作为全局公共逻辑维护
function openAlarmPage() {
qtedit.openPage("Alarm");
} 页面脚本只属于当前页。适合页面初始化、页面内局部变量、当前页专用数据整理,以及当前页的表格、模板和展示逻辑。确定逻辑只服务当前页时,优先放在 Page Script。
- 适合页面打开后的初始化
- 适合当前页数据整理
- 适合当前页表格和局部交互逻辑
window.qteditPageReady = function(ctx) {
var rows = window.tableRows || [];
qtedit.setComponentText("RowCountText", String(rows.length));
}; Definition 负责提前准备后续字段需要使用的值。它适合进行标签读取、条件拆分和中间变量整理。通常不在这里直接完成最终动作,而是将最终结果留给 Condition、Value、Text 或后续动作字段。
- 先在这里读 Tag 和计算中间量
- 让后面的 Condition / Value 更短更清楚
- 最终逻辑不宜全部集中在 Definition
var running = ReadTagInteger("PLC1.PUMP.RUN", 0);
var alarm = ReadTagBoolean("PLC1.PUMP.ALARM", false);
var ready = running === 1 && !alarm; Click Script 适合按钮点击、确认动作、打开页面、写值、弹窗;Hover Script 适合鼠标移入提示、预览和样式变化。它们都是对象级逻辑,不适合承载整页初始化代码。
- 点击动作优先放 Click Script
- 悬停反馈优先放 Hover Script
- 对象脚本不承担页面初始化职责
// Click Script
qtedit.openPage("Alarm");
// Hover Script -> Mouse Over
object.style.opacity = "0.75"; Condition、Active、Value、Text、Fill、Stroke、Move、Rotate、Scale 这类字段属于表达式位置,需要立即返回布尔值、数字、颜色或文本。`fetch`、`Promise`、定时器和批量页面修改应放在 Page Script、Click Script、Hover Script 或 `qteditPageReady` 中处理,再把结果写入变量或 Tag。
- 布尔字段:返回 true / false
- 数值字段:返回 number
- 文本和颜色字段:返回 string
- 异步逻辑不直接作为表达式返回值
// Page Script
var pressure = ReadTagDouble("Device.PRESSURE", 0);
function pressureColor() {
return pressure > 8 ? "#dc2626" : "#16a34a";
}
// Script Color / Fill
pressureColor()
页面级逻辑优先放入 Page Script,避免分散在大量对象脚本中。
按钮或对象动作优先放点击脚本,职责会更清晰。
悬停类交互和提示行为更适合放在这里。
页面与项目配置方法:优先从配置读取数据
当前页的数据优先来自 Page Script 变量、函数、内部 JSON Tag 和默认 alarm.js。它们适合保存页面参数、表格数据、显示规则和报警范围。
当前页专属数据直接放在 Page Script 里,例如表格行、默认筛选条件、当前页显示开关、局部标题和局部阈值。表格模板的 Rows 字段可以填写变量名或函数名,这些数据不宜拆成单独 JSON 文档。
- 适合当前页独有配置
- 常用于表格数据和局部规则
- Rows 可填变量名或函数名
var tableRows = [
["Pump 1", "Running"],
["Pump 2", "Stop"]
];
var panelTitle = "未命名面板"; Python 或宿主侧脚本需要返回结构化数据时,优先写入内部 JSON Tag,PPT 页面用 `ReadTagJson(...)` 读取。这样报表、分页数据和查询结果仍然走统一 Tag 读写链,不需要页面直接调用 Python。
- 适合报表行、分页结果和结构化状态
- 由 Python 写内部 Tag
- PPT 页面只负责 ReadTagJson 读取
var rows = ReadTagJson("Device.ReportRows", []);
var updatedAt = ReadTagDateTime("Device.ReportUpdatedAt", null); 每页默认有一个受保护的 alarm.js,用来维护当前页报警窗口开关和范围。编辑核心对象 `HQVISU_PAGE_ALARM` 即可。
- 适合当前页报警窗口开关
- 适合当前页报警范围
- 每页独立,跟随页面导出
HQVISU_PAGE_ALARM = {
showWindow: true,
tags: [],
deviceCodes: [],
objectIdentifiers: [],
groupCodes: [],
areaCodes: []
}; 读取当前页的 PPT 报警设置。它不是运行端报警规则本身,而是当前页面随导出包携带的报警窗口开关和报警范围配置。当前页没有 alarm 配置时,会返回传入的回退值或默认结构。
- 适合读取当前页是否允许显示报警窗口
- 适合读取页面携带的报警范围
- 导出后来自 HQVISU_PAGE_ALARM
- 没有配置时要给回退值,避免空对象报错
var alarmConfig = getPageAlarm({
showWindow: true,
tags: [],
deviceCodes: [],
objectIdentifiers: [],
groupCodes: [],
areaCodes: []
});
if (alarmConfig.showWindow) {
qtedit.setComponentVisible("PageAlarmPanel", true);
} `showWindow` 表示当前页是否允许显示报警窗口;`tags` 是完整 Tag 点名范围;`deviceCodes` 是设备或 PLC 编码范围;`objectIdentifiers` 是对象或设备单元标识;`groupCodes` 是信号分组;`areaCodes` 是区域、产线、工段或系统范围。数组为空表示该维度不附加范围条件,不表示自动选择全部点位。
- 只指定几个点位时,优先填 tags
- 按设备收口时,填 deviceCodes
- 按对象或设备单元收口时,填 objectIdentifiers
- 按信号类别收口时,填 groupCodes
- 按区域或产线收口时,填 areaCodes
{
"showWindow": true,
"tags": [],
"deviceCodes": [],
"objectIdentifiers": [],
"groupCodes": [],
"areaCodes": []
} 读取当前宿主用户。它适合做轻量级个性化显示,例如页面欢迎语、当前操作人展示和当前用户标记。它不是权限系统本身,权限判断应以宿主机规则为准。
- 适合欢迎语和当前用户显示
- 适合轻量日志标记
- 权限校验仍然应以宿主机规则为准
var username = GetCurrentUsername();
qtedit.setComponentText("CurrentUser", username || "Guest");
页面配置读取、报警读取和局部逻辑通常会集中出现在这里。
标签读写方法:先明确类型,再决定写入方式
Tag 方法可以分成三组:读值、读质量、写值。理解这三组后,大多数对象逻辑都能按职责连接起来。
`ReadTagBoolean(name, fallback)` 用于读取开关量、启停反馈、允许状态、报警位和状态字中的单个位。第二个参数是回退值,通常填写 `false`。当 Tag 尚无值或数据不可用时,页面返回该回退值。
- 适合开关量、启停反馈和允许状态
- 位读取也使用该方法
- 回退值只用于页面兜底显示,不代表真实采集值
var running = ReadTagBoolean("Device.RUN", false);
var ready = ReadTagBoolean("Device.STATUS[0]", false); `ReadTagInteger(name, fallback)` 用于读取状态码、模式号、步骤号、计数值和整型设定值。第二个参数是回退值,通常填写 `0`。需要按状态码映射颜色或文本时,应优先使用整数读取。
- 适合模式号、状态码、步骤号和计数
- 适合 Discrete Color 和 Multi-State Color 的输入
- 不要把状态码先读成字符串再自行转换
var mode = ReadTagInteger("Device.MODE", 0);
var count = ReadTagInteger("Device.COUNT", 0); `ReadTagDouble(name, fallback)` 用于读取温度、压力、液位、流量、转速、电流、比例和连续设定值。第二个参数是回退值,通常填写 `0.0`。Move、Rotate、Scale、Range Color 等数值行为优先使用该方法。
- 适合连续数值和工程量
- 适合几何动画和区间颜色输入
- 显示单位和格式化建议在文本表达中处理
var pressure = ReadTagDouble("Device.PRESSURE", 0.0);
var level = ReadTagDouble("Device.LEVEL", 0); `ReadTagString(name, fallback)` 用于读取配方名、批次号、模式文案、设备名称和备注。第二个参数是回退值,通常填写空字符串。它适合直接进入文本显示或参与 Script Text 拼接。
- 适合名称、模式文案、批次号和备注
- 文本为空时应准备清晰回退显示
- 不建议用字符串读取替代布尔、整数或浮点读取
var recipe = ReadTagString("Device.RECIPE", "");
var batchNo = ReadTagString("Device.BATCH_NO", ""); `ReadTagJson(name, fallback)` 用于读取结构化对象或数组,适合报表行、配方参数、页面表格、分页结果和聚合状态。第二个参数应提供与页面渲染匹配的默认结构,例如空数组或空对象。
- JSON 数组:表格行、趋势摘要、分页结果
- JSON 对象:页面配置、设备摘要、统计结果
- 默认值应与页面使用方式一致
var rows = ReadTagJson("Device.ReportRows", []);
var config = ReadTagJson("Device.PageConfig", {}); `ReadTagDateTime(name, fallback)` 用于读取更新时间、确认时间、批次开始时间、事件时间和设备状态时间。第二个参数可填写 `null` 或默认时间值。显示时应按页面语言和项目习惯格式化。
- 适合更新时间、确认时间和事件时间
- 无时间值时可以返回 null
- 格式化应放在文本表达或页面函数中
var updatedAt = ReadTagDateTime("Device.UpdatedAt", null);
var confirmedAt = ReadTagDateTime("Device.CONFIRMED_AT", null); Host Tag 使用完整点名格式 `device.tag`,点名中不包含空格。读取整数 Tag 的某一位时,可在完整点名后追加 `[0]` 到 `[31]`,例如 `Device.STATUS[0]`。通用语法可以记成 `TAG[bit]`,其中 `TAG` 是父级完整点名,`bit` 是 0 到 31 的位号,`[0]` 表示最低位。位读取可配合 `ReadTagBoolean`、State Color 或布尔表达式使用。
- 完整点名:`Device.STATUS`
- 语法模板:`TAG[bit]` / `Device.TAG[0]`
- 读取最低位:`Device.STATUS[0]`
- 读取第 31 位:`Device.STATUS[31]`
- 模板写法:`'<PLC>.<STATUS_TAG>[3]'`
- 位索引范围为 0 到 31
var ready = ReadTagBoolean("Device.STATUS[0]", false);
var fault = ReadTagBoolean("Device.STATUS[3]", false); `ReadTagQuality(name, fallback)` 用于读取 Tag 当前质量文本。质量状态用于判断数据可信度,不代表业务状态,也不等同于报警状态。页面可根据质量状态显示灰态、边框、提示或隐藏对象。
- 质量状态不是工艺值
- 质量异常不等同于业务报警
- fallback 可填写 pending 或 bad
- 质量文本适合用于提示和诊断显示
var quality = ReadTagQuality("Device.PRESSURE", "pending");
var text = quality === "good" ? "在线" : "数据待确认"; `ReadTagQualityGood(name)` 用于直接判断质量是否为 good。它适合写在 Condition、Active、Script Color、Quality Border 或按钮 Enabled 中。质量不是 good 时,应避免把回退值继续作为正常实时值强化展示。
- 返回 true / false
- 适合控制显隐、禁用、颜色和边框
- 质量不是 good 时,应按数据不可确认处理
var qualityGood = ReadTagQualityGood("Device.PRESSURE");
var displayText = qualityGood ? ReadTagDouble("Device.PRESSURE", 0).toFixed(1) : "--"; `WriteTagBoolean(name, value)` 用于写入启停、允许、复位、确认等布尔命令。该方法适合简单脚本写值;关键设备动作仍建议使用标准 Write Tag 行为或 `qtedit.writeTag(payload)` 携带权限、确认和审计上下文。
- 适合启停、允许、复位和确认
- value 应为 true / false
- 最终写入结果由运行端和宿主机确认
WriteTagBoolean("Device.START", true);
WriteTagBoolean("Device.RESET", true); `WriteTagInteger(name, value)` 用于写入模式号、步骤号、枚举值和整型设定值。写入值应与目标 Tag 类型和现场约定一致,不建议用字符串承载状态码。
- 适合模式号、步骤号和枚举值
- value 应为整数
- 写入前应确认目标 Tag 支持该取值范围
WriteTagInteger("Device.MODE", 2);
WriteTagInteger("Device.STEP", 10); `WriteTagDouble(name, value)` 用于写入设定值、比例、速度、温度、压力等连续数值。页面输入值应先完成范围、单位和格式处理,再提交写入。
- 适合设定值和连续工程量
- value 应为数字
- 输入框写值前应处理单位、上下限和空值
WriteTagDouble("Device.SETPOINT", 12.5);
WriteTagDouble("Device.SPEED_SET", 80); `WriteTagString(name, value)` 用于写入配方名、批次号、备注和文本参数。写入前应确认文本长度、允许字符和目标系统处理方式,避免把显示文案误写为设备控制值。
- 适合配方名、批次号和备注
- value 应为字符串
- 文本输入应先处理空值和长度
WriteTagString("Device.RECIPE", "RCP-001");
WriteTagString("Device.REMARK", "READY"); `WriteTagJson(name, value)` 用于写入结构化参数、组合输入结果、页面配置或报表条件。结构应保持稳定,字段名应与运行端或脚本约定一致。
- 适合结构化参数和组合输入
- value 可以是对象或数组
- 字段结构应稳定,便于运行端处理
WriteTagJson("Device.PARAMS", {
speed: 80,
enabled: true
}); `WriteTagDateTime(name, value)` 用于写入确认时间、操作时间、批次时间和事件时间。value 可使用 `new Date()` 或运行端认可的时间值。时间写入应与项目时区和运行端记录规则保持一致。
- 适合确认时间、操作时间和批次时间
- value 可使用 Date 对象
- 关键记录仍应由运行端审计链路确认
WriteTagDateTime("Device.CONFIRMED_AT", new Date());
WriteTagDateTime("Device.BATCH_START", new Date()); 当写入动作需要携带权限码、确认信息、审计动作或宿主上下文时,优先使用 qtedit.writeTag(payload)。它比简单的 WriteTag* 更适合正式项目,因为它能把写入背景一起带给宿主机。
- 适合权限、确认、审计类写入
- 适合正式项目关键操作
- 字段越明确,宿主机越容易按规则接管
qtedit.writeTag({
TagName: "Device.CMD",
Value: 1,
PermissionCode: "io:write",
RequireConfirm: true,
ConfirmText: "确认发送启动命令?"
}); 复杂写值应把运行端需要接管的上下文写清楚。页面侧负责提供 `TagName`、`Value`、`PermissionCode`、`RequireConfirm`、`ConfirmText`、`RequireReason`、`AuditAction` 等字段;运行端负责最终权限、确认、原因输入、审计和异步写入结果。关键写值应由用户点击或明确操作触发,不应在页面加载时自动下发。
- TagName:目标完整 Tag 点名
- Value:要写入的值
- PermissionCode:运行端权限码
- RequireConfirm / ConfirmText:确认提示
- RequireReason:要求填写原因
- AuditAction:审计动作名称
qtedit.writeTag({
TagName: "Device.CMD_START",
Value: true,
PermissionCode: "io:write",
RequireConfirm: true,
ConfirmText: "确认启动设备?",
RequireReason: true,
AuditAction: "device-start"
});
文本类对象往往同时会配到读值方法和脚本文本逻辑。
如果动作是通过行为编辑器配置的,底层仍然会走统一写入链。
页面对象修改:文字、颜色、显隐和跳转
读到 Tag 或输入值以后,页面通常要改文字、颜色、边框、显隐或跳转。这里按常用动作看,不要求先研究底层结构。
findComponent(nameOrId) 返回页面上的真实 DOM;getComponentData(nameOrId) 返回导出时的组件数据。前者适合直接改样式,后者适合读组件原始位置、宽高、角度和元信息。
- 想直接改样式时先用 findComponent
- 想读导出数据时再用 getComponentData
- 对象名建议尽量稳定,方便脚本查找
var titleEl = qtedit.findComponent("Title 1");
var titleData = qtedit.getComponentData("Title 1");
if (titleEl && titleData) {
titleEl.style.color = "#e11d48";
qtedit.setComponentLayout("Title 1", { width: titleData.width });
} 这是最常用的一组页面修改方法。它们适合在页面脚本、点击脚本和质量判断中快速改变对象显示效果,而不需要自行处理 DOM 细节。
- 改字用 setComponentText
- 改填充用 setComponentFill
- 改边框用 setComponentBorder
- 显隐控制用 setComponentVisible
qtedit.setComponentText("Title 1", "READY");
qtedit.setComponentFill("PumpBody", "#16a34a");
qtedit.setComponentBorder("PumpBody", "#166534");
qtedit.setComponentVisible("AlarmIcon", false); 这是高阶但非常实用的方法。当目标组件的新位置、新尺寸或新角度已经明确时,可以直接用它补布局。适合拖动结果回写、特殊定位、页面初始化纠偏和不适合用固定行为表达的复杂布局。
- x / y 控位置
- width / height 控尺寸
- angle 控角度
- 只改局部字段时也可以只传需要修改的字段
qtedit.setComponentLayout("Rectangle 1", {
x: 120,
y: 80,
width: 260,
height: 100,
angle: 0
}); 页面跳转、跨包跳转、外链打开、语言切换和强制刷新都在这一组中。同包页面优先使用 openPage,跨包页面优先使用 openScreen,外部站点优先使用 openWebsite,语言切换后可配合 notifyLanguageChange 或 refreshView。
- 同包跳转用 openPage
- 跨包跳转用 openScreen
- 外部网址用 openWebsite
- 语言和标签变更后可通知运行时刷新
qtedit.openPage("Alarm");
qtedit.openScreen("PUMP_OVERVIEW");
qtedit.useLanguage("zh-CN");
qtedit.notifyLanguageChange();
qtedit.refreshView(); 页面需要记录当前 tab、当前选中设备或最近一次交互动作时,可以写入页面变量。该方法只适合页面联动,不等同于写 PLC,也不应代替正式 Tag 写值。
- 适合切换 tab、筛选状态和当前选择
- 不适合设备控制
- 正式设备写入仍应使用 Write Tag 或写值动作
qtedit.writeVariable("currentTab", "alarm");
qtedit.writeVariable("selectedDevice", "Pump01"); `ReadBrowserStorage`、`WriteBrowserStorage` 和 `RemoveBrowserStorage` 用于保存页面偏好,例如上次选择的区域、折叠状态或显示模式。浏览器存储受运行环境影响,不应用作设备控制、关键业务状态或长期审计记录。
- 适合界面偏好和当前选择
- 不适合作为设备控制链路
- 不适合保存关键业务记录
var area = ReadBrowserStorage("selectedArea", "A01", "local");
WriteBrowserStorage("selectedArea", area, "local");
RemoveBrowserStorage("selectedArea", "local"); 常用组合写法:按业务动作组合方法
实际项目中很少只调用一个方法。通常需要将读取配置、读取 Tag、修改页面、写变量和跳转组合起来,形成完整业务动作。
这是典型页面脚本组合:先从当前页 Page Script 准备好的变量取值,再直接更新页面标题对象。相比将标题固定在 PPT 对象中,该方式更便于按页面上下文维护。
window.qteditPageReady = function() {
var title = window.panelTitle || "未命名页面";
qtedit.setComponentText("PageTitle", title);
}; 这个组合适合设备状态提示。先用 ReadTagQualityGood 判断质量,再同时修改边框和提示图标显隐。
var qualityGood = ReadTagQualityGood("Device.RUN");
qtedit.setComponentBorder("PumpBody", qualityGood ? "#0f172a" : "#f97316");
qtedit.setComponentVisible("QualityBadge", !qualityGood); 部分动作除了写 Tag,还需要页面同步记录本次操作已经触发。此时可以先写页面变量,再调用写值方法。
qtedit.writeVariable("lastAction", "start");
WriteTagBoolean("Device.START", true); 如果页面中用了输入模板和按键模板,脚本里可以先读输入模板当前值,再决定是否写 Tag 或跳转。template.getValue(...) 的参数填输入模板实例名,例如 Input Template;这是脚本字符串参数,所以要加引号。
var inputValue = template.getValue("Input Template");
if (inputValue !== "") {
WriteTagString("Device.RECIPE", inputValue);
}
导航类脚本通常会和页面级方法一起组合使用。
语言切换通常也会和页面刷新、脚本初始化配合使用。