跳转至

前言:本书怎么用

本章是「iScript 场景指南」的入口,不包含业务场景,而是全书共用的契约与差异速查。后续每个场景页都会回链到这里的 GraalVM 差异 一节。

本书怎么用

「iScript 场景指南」是一本按**业务目标**组织的 cookbook:每个章节是一个具体的开发目标(如「根据当前用户自动填字段」「按 SQL 过滤视图数据」),给出**写在哪儿、返回值契约、可直接复制的示例代码、常见坑**。

阅读建议:

  • 已具备 iScript 基础语法(变量、iffor、函数)的读者,按业务目标翻目录即可对号入座。
  • 每个场景的示例代码都是 **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/functionsiscript-guid/api 为准;引擎差异以本书 GraalVM 差异 为准。

默认包装与返回值契约通则

平台在不同位置执行 iScript(值脚本、隐藏脚本、校验脚本、选项脚本、操作前后置等),每种位置的**返回值会被平台按固定契约消费**。下表是各场景的通用契约;具体场景页会再细化。

默认包装:IIFE + return

所有"需要返回值"的脚本一律用 IIFE(立即执行函数)包起来,并在末尾 return

(function () {
  // 业务逻辑
  var user = getWebUser();
  var name = user.getName(); // 字符串
  return name;
})()

纯副作用脚本(如操作后置写日志、刷数据)可不 return,但仍建议包成 IIFE,避免变量泄漏到全局。

返回值契约一览

脚本类型 触发时机 返回值契约
值脚本valueScript 字段值计算时 任意值(字符串/数字/对象),赋给当前字段
隐藏脚本 / 只读脚本hiddenScript / readonlyScript 表单渲染时 Booleantrue = 隐藏 / 只读;false = 显示 / 可编辑
校验脚本validateScript 提交前 String非空串 = 失败提示""(空串)= 校验通过
选项脚本optionsScript 下拉/单选/多选渲染时 OptionscreateOptions() 返回),或字符串 "值:文本;值:文本" / "文本;文本"
操作前置 点击操作按钮时 Boolean / 字符串提示;false 或非空串通常阻断后续动作
操作后置 操作提交后 通常无返回值,做副作用(写日志、调外部接口)

三类典型返回值写法

布尔(隐藏 / 只读)——true 表示生效:

(function () {
  var user = getWebUser();
  // 角色名包含"管理员"时不隐藏
  return user.getName() !== "admin";
})()

校验(成功空串 / 失败提示)

(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

函数签名/参数细节请点对应链接;具体怎么组合使用,见后续各业务场景章节。