前言:本书怎么用¶
本章是「iScript 场景指南」的入口,不包含业务场景,而是全书共用的契约与差异速查。后续每个场景页都会回链到这里的 GraalVM 差异 一节。
本书怎么用¶
「iScript 场景指南」是一本按**业务目标**组织的 cookbook:每个章节是一个具体的开发目标(如「根据当前用户自动填字段」「按 SQL 过滤视图数据」),给出**写在哪儿、返回值契约、可直接复制的示例代码、常见坑**。
阅读建议:
- 已具备 iScript 基础语法(变量、
if、for、函数)的读者,按业务目标翻目录即可对号入座。 - 每个场景的示例代码都是 **GraalVM JS 合法**写法,可直接粘贴到
.form/.view/.flow/.activity/.task/.api/.chart/.widget/.excelconfig对应脚本属性中。 - 写之前先看一眼 GraalVM 差异,避免照搬旧 Java/Rhino 写法(
.equals、.length()等)。
本书与同仓库其它 iScript 文档的分工:
| 文档 | 定位 | 关系 |
|---|---|---|
iscript-guid/basic |
入门语法、运算子、函数定义 | 看完它再来读本书 |
iscript-guid/functions |
函数参考(按字母/类别) | 本书示例中每个函数都可在此查签名 |
iscript-guid/api |
顶层 API 对象参考($CURDOC/getWebUser/queryBySQL 等) |
本书链接到具体函数页 |
common-script-collection |
历史常用脚本片段集合 | 主题式速查;本书按业务目标重组并补充契约说明 |
本书 iscript-guid/scene |
按业务目标编排的场景 cookbook | 场景契约 + 可运行示例 + GraalVM 合规 |
边界:场景级**返回值契约、属性名、Label** 以本书为准;具体函数签名/参数细节以
iscript-guid/functions与iscript-guid/api为准;引擎差异以本书 GraalVM 差异 为准。
默认包装与返回值契约通则¶
平台在不同位置执行 iScript(值脚本、隐藏脚本、校验脚本、选项脚本、操作前后置等),每种位置的**返回值会被平台按固定契约消费**。下表是各场景的通用契约;具体场景页会再细化。
默认包装:IIFE + return¶
所有"需要返回值"的脚本一律用 IIFE(立即执行函数)包起来,并在末尾 return:
纯副作用脚本(如操作后置写日志、刷数据)可不
return,但仍建议包成 IIFE,避免变量泄漏到全局。
返回值契约一览¶
| 脚本类型 | 触发时机 | 返回值契约 |
|---|---|---|
值脚本(valueScript) |
字段值计算时 | 任意值(字符串/数字/对象),赋给当前字段 |
隐藏脚本 / 只读脚本(hiddenScript / readonlyScript) |
表单渲染时 | Boolean:true = 隐藏 / 只读;false = 显示 / 可编辑 |
校验脚本(validateScript) |
提交前 | String:非空串 = 失败提示;""(空串)= 校验通过 |
选项脚本(optionsScript) |
下拉/单选/多选渲染时 | Options(createOptions() 返回),或字符串 "值:文本;值:文本" / "文本;文本" |
| 操作前置 | 点击操作按钮时 | Boolean / 字符串提示;false 或非空串通常阻断后续动作 |
| 操作后置 | 操作提交后 | 通常无返回值,做副作用(写日志、调外部接口) |
三类典型返回值写法¶
布尔(隐藏 / 只读)——true 表示生效:
校验(成功空串 / 失败提示):
(function () {
var amount = getItemValueAsString("金额");
if (amount === "" || Number(amount) <= 0) {
return "金额必须大于 0"; // 失败:返回提示
}
return ""; // 成功:空串
})()
选项(Options 或 "值:文本;..." 串):
// 方式 A:Options 对象
(function () {
var opts = createOptions();
opts.add("01", "待审");
opts.add("02", "已审");
return opts;
})()
// 方式 B:字符串(值:文本;...)
(function () {
return "01:待审;02:已审";
})()
GraalVM 差异¶
当前运行时为 GraalVM JavaScript(非 Rhino)。JS 字面量与变量是原生 JS 类型——同名成员下 JS 属性优先于 Java 方法。本节是全书回链锚点(
#graalvm-差异),写任何 iScript 前先看一遍。
字符串相等:用 === / !==,禁用 .equals()¶
| 错误(Java/Rhino 习惯) | 正确(GraalVM JS) |
|---|---|
"x".equals(v) |
v === "x" |
"".equals(v) |
v === "" |
v.equals("x") |
v === "x" |
!v.equals("x") |
v !== "x" |
!"02".equals(status) |
status !== "02" |
// 错误:GraalVM 下字符串字面量没有 .equals 方法
if ("".equals(v)) { /* ... */ }
if ("02".equals(status)) { /* ... */ }
// 正确
if (v == null || v === "") { /* ... */ }
if (status === "02") { /* ... */ }
字符串长度:用 .length 属性,禁用 .length()¶
| 错误 | 正确 |
|---|---|
s.length() |
s.length |
s.trim().length() |
s.trim().length |
v.trim().length() === 0 |
v.trim().length === 0 |
// 错误:JS 字符串的 length 是属性,不是方法
if (v != null && v.trim().length() === 0) { /* ... */ }
// 正确
if (v != null && v.trim().length === 0) { /* ... */ }
例外:
org.json.JSONArray等真实 **Java 对象**仍用方法jsonArray.length(),不要改成属性——只要它真的是 Java 类型即可。
取 Java 类:用 Java.type(...),禁用裸 java.util.X¶
| 错误(旧习惯) | 正确(GraalVM 推荐) |
|---|---|
直接写 java.util.HashMap |
Java.type('java.util.HashMap') |
importClass(...) / importPackage(...) / JavaImporter |
GraalVM 默认常不可用,改用 Java.type |
Packages.cn.myapps... |
仍可用(兼容),新建脚本优先 Java.type |
// 推荐
var HashMap = Java.type('java.util.HashMap');
var map = new HashMap();
// 兼容(现存旧示例常见,可读但新代码不优先)
var Security = new Packages.cn.myapps.common.util.Security();
Java List .size() vs JS 数组 .length¶
平台 API(如 queryBySQL)常返回 java.util.List;JS 数组(如 getParameterAsArray)是原生 Array。两者长度与遍历写法不同:
| 类型 | 长度 | 取元素 | 遍历 |
|---|---|---|---|
java.util.List / Collection |
.size() |
.get(i) |
.iterator() |
JS Array |
.length |
arr[i] |
for (... of ...) / 下标 for |
// 错误:把 JS 数组当 Java List
var selects = getParameterAsArray("_selects");
println("共 " + selects.size() + " 条"); // ❌
// 正确
var selects = getParameterAsArray("_selects");
println("共 " + selects.length + " 条");
// 错误:把 Java List 当 JS 数组
var rows = queryBySQL("select id from tlk_xxx");
println(rows.length); // ❌(若返回 java.util.List)
// 正确
var rows = queryBySQL("select id from tlk_xxx");
println(rows.size());
速查对照表¶
| 场景 | 错误 | 正确 |
|---|---|---|
| 相等 | "a".equals(b) |
b === "a" |
| 不等 | !b.equals("a") |
b !== "a" |
| 空串 | "".equals(v) |
v === "" |
| 字符串长度 | v.length() |
v.length |
| 取 Java 类 | 裸 java.util.X / importClass |
Java.type('java.util.X') |
| Java List 长度 | list.length |
list.size() |
| JS 数组长度 | arr.size() / arr.length() |
arr.length |
| 判空 | v === null \|\| v === undefined(冗余) |
v == null(同时覆盖两者) |
现代 JS 语法(
const/let、箭头函数、模板字符串)在 GraalVM 下可用;旧示例里的var+function也能跑。
7 个高频函数速览¶
写场景时最常碰到的 7 个函数——一句话 + 链接到权威文档:
| # | 函数 | 一句话 | 文档 |
|---|---|---|---|
| 1 | getCurrentDocument() |
取当前文档对象(表单/视图上下文中的 Document),是读字段、写字段的入口 |
iscript-guid/api → doc |
| 2 | getItemValueAsString("字段名") |
按字段名取当前文档某字段的字符串值 | iscript-guid/functions → doc-functions |
| 3 | getWebUser() |
取当前登录用户对象(含登录名、角色、部门等) | iscript-guid/api → curruser |
| 4 | queryBySQL(sql) / queryByDSName(dsName, sql) |
按 SQL(可指定数据源)查询,返回结果集 | iscript-guid/api → database |
| 5 | doc.findItem("字段名").setValue(value) |
修改当前文档某字段的值(操作前后置 / 计算脚本常用) | iscript-guid/functions → curdoc-functions |
| 6 | getParameter("name") |
取平台注入的参数(如视图 _selects、URL 参数、上下文参数) |
iscript-guid/functions → system-functions |
| 7 | format(date, pattern) |
按模式串格式化日期,如 format(new Date(), "yyyy-MM-dd") |
iscript-guid/functions → date-functions |
函数签名/参数细节请点对应链接;具体怎么组合使用,见后续各业务场景章节。