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 字段值的常见类型

类型 示例值 常见用途
数字 1003.14 金额、数量、比例计算
字符串 '张三''A001' 拼接、截取、校验
日期字符串 '2026-07-08' 日期比较、计算天数
布尔值 truefalse 条件判断
空值 nullundefined'' 判空、兜底
数组 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) > 0

6.3 日期函数

函数 说明 示例
now() 当前日期时间 now()
toDay(format) 当前日期,按格式返回 toDay('yyyy-MM-dd')
year(date) 获取年份 year(${入职日期})
quarter(date) 获取季度 quarter(${入职日期})
month(date) 获取月份 month(${入职日期})
day(date) 获取日期 day(${入职日期})
weekDay(date) 获取星期,返回 06 weekDay(${入职日期})
timeMillis(date) 转时间戳 timeMillis(${开始日期})
daysBetween(date1, date2) 两个日期相差天数,取绝对值 daysBetween(${开始日期}, ${结束日期})
dateDif(start, end, unit) 两个日期相差值,支持 smhDMY 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) 是否为 nullundefined isnull(${审批人})
isnotnull(value) 是否不是 nullundefined 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.amount

7.1 自执行函数格式

自执行函数适合普通表达式不好处理的场景,例如:

  1. 从表循环校验。
  2. 多个条件组合判断。
  3. 需要定义临时变量。
  4. 需要先判断对象或数组是否存在。

基本格式:

(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,不要使用箭头函数、letconst、可选链 ?.、空值合并 ??

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(${结束日期}) : false

8.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') === 0

9. 报错排查

9.1 先检查表达式语法

问题 错误示例 正确示例
少括号 (${a} + ${b} (${a} + ${b})
字符串没加引号 ${状态} === 已通过 ${状态} === '已通过'
等号写错 ${状态} = '已通过' ${状态} === '已通过'
中文符号 ${金额} > 100 ${金额} > 100
使用原生函数 直接写原生转数字函数 `number(${金额}

9.2 再检查空值

错误示例:

this.employee_ext1[0].id
${employee_ext1[0].employee_id}

这类报错通常不是字段名写错,而是中间某一层不存在:

  1. employee_ext1 不存在,继续取 [0] 会报错。
  2. employee_ext1 存在,但是没有第 1 行,employee_ext1[0]undefined
  3. 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(${结束日期}) : false

9.4 数字计算结果异常

错误示例:

number(${金额}) * number(${数量})

当金额或数量为空时,内部 number() 可能拿不到可转换的值。建议先兜底:

number(${金额} || 0) * number(${数量} || 0)

10. 编写建议

  1. 普通表达式优先点击字段树生成 ${字段},减少字段名写错。
  2. 简单表达式直接写,例如 ${a} + ${b}
  3. 需要函数时优先使用内部函数,例如 number()len()find()timeMillis()
  4. 数字计算前用 number(${字段} || 0) 兜底。
  5. 字符串处理前用 ${字段} || '' 兜底。
  6. 日期比较前先用 isnotempty() 判断日期是否已填。
  7. 从表汇总优先用 $[从表.字段] 配合 sum()count() 等聚合函数。
  8. 自执行函数适合从表循环、多条件、多步骤处理。
  9. 自执行函数里处理从表前,用 this.xxx || [] 兜底。
  10. 访问数组某一行之前,先判断这一行是否存在。
  11. 校验表达式要明确返回 truefalse
作者:管理员  创建时间:2026-07-09 08:40
最后编辑:管理员  更新时间:2026-08-14 18:00