- 1. 前端表达式是什么
- 应用范围
- 2. 变量规则
- 2.1
${字段}是一个整体变量 - 2.2 普通字段和复杂路径
- 2.3 字段值的常见类型
- 2.4 判空和兜底
- 3. 基础运算符
- 4. 比较和逻辑判断
- 4.1 比较运算符
- 4.2 逻辑运算符
- 5. 条件表达式
- 5.1 三元表达式
- 5.2 普通表达式的适用范围
- 6. 内部函数
- 6.1 数字函数
- 6.2 字符串函数
- 6.3 日期函数
- 6.4 校验函数
- 6.5 从表聚合函数
- 7. 内部对象
this - 7.1 自执行函数格式
- 8. 常用业务示例
- 8.1 计算总价
- 8.2 金额大于 10000 必须填写原因
- 8.3 开始日期不能大于结束日期
- 8.4 生成申请标题
- 8.5 身份证号取出生日期
- 8.6 校验身份证号格式
- 8.7 校验手机号格式
- 8.8 从表金额合计必须等于主表金额
- 8.9 从表至少有一行金额大于 0
- 9. 报错排查
- 9.1 先检查表达式语法
- 9.2 再检查空值
- 9.3 日期为空
- 9.4 数字计算结果异常
- 10. 编写建议
1. 前端表达式是什么
简单来说,前端表达式的写法 就是 JavaScript **(简称“JS”)**的语法。lczCreater前台表达式是在JavaScript的基础上,扩充了对变量的定义及一些业务函数的扩充,表达式编辑器输入框可以当作 JS 文件去写,能写运算、判断、字符串拼接等内容。
用于在页面上做字段取值、运算、判断、拼接、校验和少量业务计算。
** 注意: 如果 js 函数方法跟我们内部方法封装的同名就无法使用,优先使用内部函数 普通表达式和自执行函数里都 优先使用这些内部函数。**
我们内部扩展了 ${字段} 这种变量写法:
${字段}例如:
${a}
${b}
${姓名}
${入职日期}这里的 ${a}、${b}、${姓名} 是一个整体,表示系统字段变量。表达式执行前,系统会把它们替换成对应字段的值。
应用范围
1)跨设备表单中的表达式->公式计算;
2)跨设备表单中的表达式->动态属性;
3)跨设备表单中的表达式->保存校验;

2. 变量规则
2.1 ${字段} 是一个整体变量
在普通表达式里,推荐通过字段树点击字段,让系统自动生成 ${字段}。这样最不容易写错字段名。
正确写法:
${a} + ${b}
${姓名} + '-' + ${工号}
${年龄} >= 18
${login_name}错误写法:
${a + b}
${姓名 + 工号}
${年龄 >= 18}
${a}z| 错误写法 | 问题 | 正确写法 |
|---|---|---|
${a + b} |
${} 里面只能写字段名,不能写运算 |
${a} + ${b} |
${姓名 + 工号} |
系统会把 姓名 + 工号 当成一个字段名 |
${姓名} + ${工号} |
${年龄 >= 18} |
判断条件要写在 ${} 外面 |
${年龄} >= 18 |
${a}z |
拼接普通文本要加引号 | ${a} + 'z' |
不要把 ${a} 理解成 JavaScript 模板字符串。这里它是系统扩展的字段占位符。
2.2 普通字段和复杂路径
普通字段变量通常这样写:
${login_name}
${employee_id}
${department_code}从表路径也可以写,但风险更高:
${employee_ext1[0].employee_id}如果 employee_ext1 不存在,或者第 1 行不存在,再取 .employee_id 就容易报错。从表读取、循环、汇总、重复校验,建议使用后面的自执行函数,先判空再处理。
2.3 字段值的常见类型
| 类型 | 示例值 | 常见用途 |
|---|---|---|
| 数字 | 100、3.14 |
金额、数量、比例计算 |
| 字符串 | '张三'、'A001' |
拼接、截取、校验 |
| 日期字符串 | '2026-07-08' |
日期比较、计算天数 |
| 布尔值 | true、false |
条件判断 |
| 空值 | null、undefined、'' |
判空、兜底 |
| 数组 | this.employee_ext1 |
自执行函数中处理从表、明细表 |
2.4 判空和兜底
字段没填时,建议先做兜底处理。
字符串兜底:
(${姓名} || '无姓名') + '-' + (${工号} || '无工号')数字兜底:
(number(${单价} || 0)) * (number(${数量} || 0))判空:
isempty(${姓名})
isnotempty(${姓名})3. 基础运算符
| 运算 | 符号 | 示例 |
|---|---|---|
| 加 | + |
${a} + ${b} |
| 减 | - |
${a} - ${b} |
| 乘 | * |
${a} * ${b} |
| 除 | / |
${a} / ${b} |
| 求余 | % |
${a} % ${b} |
金额计算:
(number(${单价} || 0)) * (number(${数量} || 0))保留两位小数:
round((number(${单价} || 0)) * (number(${数量} || 0)), 2)4. 比较和逻辑判断
4.1 比较运算符
| 含义 | 符号 | 示例 |
|---|---|---|
| 等于 | == / === (全等数据类型也得相等) |
${状态} === '已通过' |
| 不等于 | != / !== |
${状态} !== '已驳回' |
| 大于 | > |
${金额} > 1000 |
| 大于等于 | >= |
${年龄} >= 18 |
| 小于 | < |
${库存} < 10 |
| 小于等于 | <= |
${折扣} <= 1 |
4.2 逻辑运算符
| 含义 | 符号 | 示例 |
|---|---|---|
| 与 (并且) | && |
${年龄} >= 18 && ${状态} === '正常' |
| 或 (或者) | ||
| 非 (取反) | ! |
!${姓名} |
必填校验:
isempty(${姓名})手机号或邮箱至少填一个:
isempty(${手机号}) && isempty(${邮箱})5. 条件表达式
5.1 三元表达式
格式:
条件 ? 条件成立的值 : 条件不成立的值示例:
${分数} >= 60 ? '通过' : '不通过'根据金额返回审批等级:
number(${金额} || 0) > 10000 ? '高额审批' : '普通审批'多条件判断:
${分数} >= 90 ? '优秀' : (${分数} >= 60 ? '合格' : '不合格')5.2 普通表达式的适用范围
普通表达式适合一行能写清楚的逻辑,例如计算、拼接、比较和简单条件判断。
number(${金额} || 0) > 1000
(${姓名} || '') + '-' + (${工号} || '')
${分数} >= 60 ? '通过' : '不通过'如果要处理从表循环、多行校验、对象为空再取下级字段等复杂逻辑,建议使用后面“内部对象 this”章节里的自执行函数。
6. 内部函数
表达式执行前,系统会把内部函数自动绑定到当前表达式对象上。写表达式时直接写函数名即可,例如:
number(${金额} || 0)
len(${手机号} || '')
timeMillis(${开始日期})6.1 数字函数
| 函数 | 说明 | 示例 |
|---|---|---|
number(value) |
转数字 | `number(${金额} |
round(value, n) |
四舍五入,保留 n 位小数 |
`round(number(${金额} |
roundDown(value, n) |
向下保留 n 位小数 |
`roundDown(number(${金额} |
abs(value) |
绝对值 | `abs(number(${差额} |
sqrt(value) |
平方根 | `sqrt(number(${面积} |
random(min, max) |
随机整数 | random(1, 100) |
折扣价:
round((number(${原价} || 0)) * (number(${折扣} || 1)), 2)金额不能小于 0:
number(${金额} || 0) < 0 ? 0 : number(${金额} || 0)6.2 字符串函数
| 函数 | 说明 | 示例 |
|---|---|---|
len(str) |
获取字符串长度 | `len(${手机号} |
find(str, keyword, start) |
查找文本,找到返回位置,找不到返回 0 |
`find(${备注} |
left(str, n) |
取左侧 n 位 |
`left(${身份证号} |
right(str, n) |
取右侧 n 位 |
`right(${手机号} |
mid(str, begin, length) |
从第 begin 位开始取 length 位,begin 从 1 开始 |
`mid(${身份证号} |
replace(str, oldText, newText) |
替换文本 | `replace(${编码} |
split(str, separator) |
按分隔符拆成数组 | `split(${标签} |
校验手机号长度不是 11 位:
len(${手机号} || '') !== 11判断备注是否包含“加急”:
find(${备注} || '', '加急', 0) > 0取手机号后四位:
right(${手机号} || '', 4)身份证号取出生日期:
len(${身份证号} || '') === 18 ? mid(${身份证号} || '', 7, 4) + '-' + mid(${身份证号} || '', 11, 2) + '-' + mid(${身份证号} || '', 13, 2) : ''隐藏手机号中间四位:
replace(${手机号} || '', '^(\\d{3})\\d{4}(\\d{4})$', '$1****$2')判断标签里是否包含“重要”:
find(',' + (${标签} || '') + ',', ',重要,', 0) > 06.3 日期函数
| 函数 | 说明 | 示例 |
|---|---|---|
now() |
当前日期时间 | now() |
toDay(format) |
当前日期,按格式返回 | toDay('yyyy-MM-dd') |
year(date) |
获取年份 | year(${入职日期}) |
quarter(date) |
获取季度 | quarter(${入职日期}) |
month(date) |
获取月份 | month(${入职日期}) |
day(date) |
获取日期 | day(${入职日期}) |
weekDay(date) |
获取星期,返回 0 到 6 |
weekDay(${入职日期}) |
timeMillis(date) |
转时间戳 | timeMillis(${开始日期}) |
daysBetween(date1, date2) |
两个日期相差天数,取绝对值 | daysBetween(${开始日期}, ${结束日期}) |
dateDif(start, end, unit) |
两个日期相差值,支持 s、m、h、D、M、Y |
dateDif(${开始日期}, ${结束日期}, 'D') |
dateAdd(date, unit, count) |
日期加减 | dateAdd(${开始日期}, 'dd', 7) |
formatDatetime(date, format) |
日期格式化 | formatDatetime(${申请日期}, 'yyyy-MM-dd') |
判断开始日期是否晚于结束日期:
isnotempty(${开始日期}) && isnotempty(${结束日期}) ? timeMillis(${开始日期}) > timeMillis(${结束日期}) : false计算相差天数:
isnotempty(${开始日期}) && isnotempty(${结束日期}) ? dateDif(${开始日期}, ${结束日期}, 'D') : 0校验请假天数是否超过 3 天:
isnotempty(${开始日期}) && isnotempty(${结束日期}) ? dateDif(${开始日期}, ${结束日期}, 'D') > 3 : false开始日期加 7 天:
isnotempty(${开始日期}) ? dateAdd(${开始日期}, 'dd', 7) : ''6.4 校验函数
| 函数 | 说明 | 示例 |
|---|---|---|
isempty(value) |
是否为空 | isempty(${姓名}) |
isnotempty(value) |
是否不为空 | isnotempty(${姓名}) |
isnull(value) |
是否为 null 或 undefined |
isnull(${审批人}) |
isnotnull(value) |
是否不是 null 或 undefined |
isnotnull(${审批人}) |
ismatch(str, pattern) |
是否匹配正则 | `ismatch(${手机号} |
isnotmatch(str, pattern) |
是否不匹配正则 | `isnotmatch(${手机号} |
校验身份证号格式:
isnotmatch(${身份证号} || '', '^\\d{17}[\\dXx]$')校验手机号格式:
isnotmatch(${手机号} || '', '^1\\d{10}$')6.5 从表聚合函数
从表字段可以用 $[从表名.字段名] 取出一组值,再交给聚合函数处理。
| 函数 | 说明 | 示例 |
|---|---|---|
sum(array, filter) |
求和 | sum($[detailList.amount]) |
avg(array, filter) |
平均值 | avg($[detailList.amount]) |
count(array, filter) |
计数 | count($[detailList.amount]) |
max(array, filter) |
最大值 | max($[detailList.amount]) |
min(array, filter) |
最小值 | min($[detailList.amount]) |
从表金额合计:
sum($[detailList.amount])从表金额合计必须等于主表金额:
sum($[detailList.amount]) !== number(${总金额} || 0)只汇总类型为“差旅”的明细金额:
sum($[detailList.amount], '${detailList.type} === "差旅"')统计金额大于 0 的明细行数:
count($[detailList.amount], 'number(${detailList.amount} || 0) > 0')7. 内部对象 this
this 主要用于自执行函数这种复杂表达式。普通表达式里通过 ${字段} 取值;进入自执行函数后,字段取值改成 this.字段、this.从表名。
| 场景 | 取值方式 | 示例 |
|---|---|---|
| 普通表达式 | ${字段} |
${login_name} |
| 自执行函数 | this.字段 |
this.login_name |
| 自执行函数访问从表 | this.从表名 |
this.employee_ext1 |
普通表达式:
${login_name}
${employee_id}
number(${金额} || 0) > 1000自执行函数里:
this.login_name
this.employee_id
this.amount7.1 自执行函数格式
自执行函数适合普通表达式不好处理的场景,例如:
- 从表循环校验。
- 多个条件组合判断。
- 需要定义临时变量。
- 需要先判断对象或数组是否存在。
基本格式:
(function () {
console.log(this,'this指向了表达式执行的内部对象')
return false;
}).call(this)自执行函数里也使用内部函数,直接写函数名即可:
(function () {
var amount = number(this.amount || 0);
var type = this.reimburse_type || '';
return type === '差旅' && amount > 5000;
}).call(this)从表取第一行字段:
(function () {
var table = this.employee_ext1 || [];
if (!table[0]) {
return '';
}
return table[0].employee_id || '';
}).call(this)从表循环校验重复:
es5写法
(function () {
var table = this.employee_ext1 || [];
for (var i = 0; i < table.length; i++) {
var curVal = table[i].emergency_contact_name;
if (!curVal) {
continue;
}
for (var j = i + 1; j < table.length; j++) {
if (table[j].emergency_contact_name === curVal) {
return true;
}
}
}
return false;
}).call(this)注意:如果环境要求 ES5,复杂表达式里尽量使用 var 和普通 function,不要使用箭头函数、let、const、可选链 ?.、空值合并 ??。
es6+写法
(function () {
const names = new Set();
return this.employee_ext1.some(item => {
const name = item.emergency_contact_name;
if (names.has(name)) {
return true;
}
names.add(name);
return false;
});
}).call(this);8. 常用业务示例
8.1 计算总价
round((number(${单价} || 0)) * (number(${数量} || 0)), 2)8.2 金额大于 10000 必须填写原因
number(${金额} || 0) > 10000 && isempty(${原因})8.3 开始日期不能大于结束日期
isnotempty(${开始日期}) && isnotempty(${结束日期}) ? timeMillis(${开始日期}) > timeMillis(${结束日期}) : false8.4 生成申请标题
(${申请人} || '') + '-' + (${申请类型} || '') + '-' + (${申请日期} || '')8.5 身份证号取出生日期
len(${身份证号} || '') === 18 ? mid(${身份证号} || '', 7, 4) + '-' + mid(${身份证号} || '', 11, 2) + '-' + mid(${身份证号} || '', 13, 2) : ''8.6 校验身份证号格式
isnotmatch(${身份证号} || '', '^\\d{17}[\\dXx]$')8.7 校验手机号格式
isnotmatch(${手机号} || '', '^1\\d{10}$')8.8 从表金额合计必须等于主表金额
sum($[detailList.amount]) !== number(${总金额} || 0)8.9 从表至少有一行金额大于 0
count($[detailList.amount], 'number(${detailList.amount} || 0) > 0') === 09. 报错排查
9.1 先检查表达式语法
| 问题 | 错误示例 | 正确示例 |
|---|---|---|
| 少括号 | (${a} + ${b} |
(${a} + ${b}) |
| 字符串没加引号 | ${状态} === 已通过 |
${状态} === '已通过' |
| 等号写错 | ${状态} = '已通过' |
${状态} === '已通过' |
| 中文符号 | ${金额} > 100 |
${金额} > 100 |
| 使用原生函数 | 直接写原生转数字函数 | `number(${金额} |
9.2 再检查空值
错误示例:
this.employee_ext1[0].id
${employee_ext1[0].employee_id}这类报错通常不是字段名写错,而是中间某一层不存在:
employee_ext1不存在,继续取[0]会报错。employee_ext1存在,但是没有第 1 行,employee_ext1[0]是undefined。employee_ext1[0]不存在时,继续取.id或.employee_id会报错。
推荐写法:
${employee_ext1[0]?.emergency_contact_name}(function () {
var table = this.employee_ext1 || [];
if (!table[0]) {
return '';
}
return table[0].employee_id || '';
}).call(this)9.3 日期为空
日期函数使用前先判断日期字段是否为空:
isnotempty(${开始日期}) && isnotempty(${结束日期}) ? timeMillis(${开始日期}) > timeMillis(${结束日期}) : false9.4 数字计算结果异常
错误示例:
number(${金额}) * number(${数量})当金额或数量为空时,内部 number() 可能拿不到可转换的值。建议先兜底:
number(${金额} || 0) * number(${数量} || 0)10. 编写建议
- 普通表达式优先点击字段树生成
${字段},减少字段名写错。 - 简单表达式直接写,例如
${a} + ${b}。 - 需要函数时优先使用内部函数,例如
number()、len()、find()、timeMillis()。 - 数字计算前用
number(${字段} || 0)兜底。 - 字符串处理前用
${字段} || ''兜底。 - 日期比较前先用
isnotempty()判断日期是否已填。 - 从表汇总优先用
$[从表.字段]配合sum()、count()等聚合函数。 - 自执行函数适合从表循环、多条件、多步骤处理。
- 自执行函数里处理从表前,用
this.xxx || []兜底。 - 访问数组某一行之前,先判断这一行是否存在。
- 校验表达式要明确返回
true或false。
最后编辑:Eric 更新时间:2026-08-14 18:00
