303 lines
9.7 KiB
Vue
303 lines
9.7 KiB
Vue
|
||
// 移动端不支持自定义表达式设置的默认值
|
||
import {http} from "@/utils/http";
|
||
import {useUserStore} from "@/store";
|
||
import * as CustomExpression from './customExpression';
|
||
import dayjs from "dayjs";
|
||
|
||
// 获取所有用户自定义表达式的Key
|
||
const ceKeys = Object.keys(CustomExpression)
|
||
// 将key用逗号拼接,可以拼接成方法参数,例:a,b,c --> function(a,b,c){}
|
||
const ceJoin = ceKeys.join(',')
|
||
// 将用户自定义的表达式按key的顺序放到数组中,可以使用 apply 传递给方法直接调用
|
||
const $CE$ = ceKeys.map(key => CustomExpression[key])
|
||
|
||
/** 普通规则表达式 #{...} */
|
||
const normalRegExp = /#{([^}]+)?}/g
|
||
/** 用户自定义规则表达式 {{...}} */
|
||
const customRegExp = /{{([^}]+)?}}/g
|
||
/** 填值规则表达式 ${...} */
|
||
const fillRuleRegExp = /\${([^}]+)?}/g
|
||
|
||
/** action 类型 */
|
||
export const ACTION_TYPES = { ADD: 'add', EDIT: 'edit', DETAIL: 'detail', RELOAD: 'reload' }
|
||
|
||
/**
|
||
* 获取单个字段的默认值-通过回调函数返回值
|
||
* @param {Object} defVal
|
||
* @param {Object} type
|
||
* @param {Object} callback
|
||
*/
|
||
export async function loadOneFieldDefVal(defVal, type, callback) {
|
||
if(hasEffectiveValue(defVal)){
|
||
let value = await handleDefaultValue(defVal, ACTION_TYPES.ADD, {});
|
||
if ('number' === type && value) {
|
||
value = Number.parseFloat(value)
|
||
}
|
||
callback(value)
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 判断给定的值是不是有效的
|
||
*/
|
||
function hasEffectiveValue(val) {
|
||
if(val || val === 0){
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* 获取默认值
|
||
* @param {Object} defVal
|
||
* @param {Object} action
|
||
* @param {Object} getFormData
|
||
*/
|
||
async function handleDefaultValue(defVal, action, getFormData) {
|
||
if (defVal != null) {
|
||
// 检查类型,如果类型错误则不继续运行
|
||
if (checkExpressionType(defVal)) {
|
||
let value = await getDefaultValue(defVal, action, getFormData)
|
||
if (value != null) {
|
||
return value
|
||
}
|
||
}
|
||
}
|
||
return defVal;
|
||
}
|
||
|
||
/**
|
||
* 加载form组件默认值
|
||
* @param form Form对象
|
||
* @param properties 字段配置
|
||
* @param action 操作类型(ACTION_TYPES),除填值规则外,其他表达式只在add下才执行
|
||
* @param getFormData 获取数据的方法,用于填值规则向后台传值
|
||
*/
|
||
export function loadFieldDefVal({ form, properties, action, getFormData }) {
|
||
if (Array.isArray(properties) && properties.length > 0) {
|
||
properties.forEach(async prop => {
|
||
let { defVal, type } = prop._formSchem
|
||
// key取值错误导致 树形表 表单默认值未生效 【online】树列表不支持控件默认值表达式配置 (博威)
|
||
let key = prop.key
|
||
// 2021年5月21日 Tree类型表单,系统编码不生效。【issues/I3NR39】
|
||
if (!key) {
|
||
key = prop._propertyId
|
||
}
|
||
eachHandler(key, defVal, action, (value) => {
|
||
// 处理数字类型,如果type=number并且value有值
|
||
if ('number' === type && value) {
|
||
// parseFloat() 可以直接处理字符串、整数、小数、null和undefined,
|
||
// 非数字类型直接返回NaN,不必担心报错
|
||
value = Number.parseFloat(value)
|
||
}
|
||
form.setFieldsValue({ [key]: value })
|
||
}, getFormData)
|
||
})
|
||
}
|
||
}
|
||
|
||
/** 加载JEditableTable组件默认值 */
|
||
export function loadFieldDefValForSubTable({ subForms, subTable, row, action, getFormData }) {
|
||
if (subTable && Array.isArray(subTable.columns) && subTable.columns.length > 0) {
|
||
subTable.columns.forEach(async column => {
|
||
let { key, fieldDefaultValue: defVal } = column
|
||
eachHandler(key, defVal, action, (value) => {
|
||
if (subForms.form) {
|
||
subForms.form.setFieldsValue({ [key]: value })
|
||
} else {
|
||
// update-begin---author:sunjianlei Date:20200725 for:online功能测试,行操作切换成新的行编辑-----------
|
||
let v = [{rowKey: row.id, values: {[key]: value}}];
|
||
(subForms.jvt || subForms.jet).setValues(v)
|
||
// update-end---author:sunjianlei Date:20200725 for:online功能测试,行操作切换成新的行编辑------------
|
||
}
|
||
}, getFormData)
|
||
})
|
||
}
|
||
}
|
||
|
||
async function eachHandler(key, defVal, action, callback, getFormData) {
|
||
if (defVal != null) {
|
||
// 检查类型,如果类型错误则不继续运行
|
||
if (checkExpressionType(defVal)) {
|
||
let value = await getDefaultValue(defVal, action, getFormData)
|
||
if (value != null) {
|
||
callback(value)
|
||
}
|
||
} else {
|
||
// 不合法的表达式直接返回不解析
|
||
callback(defVal)
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 检查表达式类型是否合法,规则:
|
||
* 1、填值规则表达式不能和其他表达式混用
|
||
* 2、每次只能填写一个填值规则表达式
|
||
* 3、普通表达式和用户自定义表达式可以混用
|
||
*/
|
||
export function checkExpressionType(defVal) {
|
||
// 获取各个表达式的数量
|
||
let normalCount = 0, customCount = 0, fillRuleCount = 0
|
||
defVal.replace(fillRuleRegExp, () => fillRuleCount++)
|
||
if (fillRuleCount > 1) {
|
||
logWarn(`表达式[${defVal}]不合法:只能同时填写一个填值规则表达式!`)
|
||
return false
|
||
}
|
||
defVal.replace(normalRegExp, () => normalCount++)
|
||
defVal.replace(customRegExp, () => customCount++)
|
||
// 除填值规则外其他规则的数量
|
||
let fillRuleOtherCount = normalCount + customCount
|
||
if (fillRuleCount > 0 && fillRuleOtherCount > 0) {
|
||
logWarn(`表达式[${defVal}]不合法:填值规则表达式不能和其他表达式混用!`)
|
||
return false
|
||
}
|
||
return true
|
||
}
|
||
|
||
/** 获取所有匹配的表达式 */
|
||
function getRegExpMap(text, exp) {
|
||
let map = new Map()
|
||
if(text && text.length>0){
|
||
text.replace(exp, function (match, param, offset, string) {
|
||
map.set(match, param.trim())
|
||
return match
|
||
})
|
||
}
|
||
return map
|
||
}
|
||
|
||
/** 获取默认值,可以执行表达式,可以执行用户自定义方法,可以异步获取用户信息等 */
|
||
async function getDefaultValue(defVal, action, getFormData) {
|
||
// 只有在 add 和 reload 模式下才执行填值规则
|
||
if (action === ACTION_TYPES.ADD || action === ACTION_TYPES.RELOAD) {
|
||
// 判断是否是填值规则表达式,如果是就执行填值规则
|
||
if (fillRuleRegExp.test(defVal)) {
|
||
return await executeRegExp(defVal, fillRuleRegExp, executeFillRuleExpression, [getFormData])
|
||
}
|
||
}
|
||
// 只有在 add 模式下才执行其他表达式
|
||
if (action === ACTION_TYPES.ADD) {
|
||
// 获取并替换所有常规表达式
|
||
defVal = await executeRegExp(defVal, normalRegExp, executeNormalExpression)
|
||
// 获取并替换所有用户自定义表达式
|
||
defVal = await executeRegExp(defVal, customRegExp, executeCustomExpression)
|
||
return defVal
|
||
}
|
||
return null
|
||
}
|
||
|
||
async function executeRegExp(defVal, regExp, execFun, otherParams = []) {
|
||
let map = getRegExpMap(defVal, regExp)
|
||
// @ts-ignore
|
||
for (let origin of map.keys()) {
|
||
let exp = map.get(origin)
|
||
let result = await execFun.apply(null, [exp, origin, ...otherParams])
|
||
// 如果只有一个表达式,那么就不替换(因为一旦替换,类型就会被转成String),直接返回执行结果,保证返回的类型不变
|
||
if (origin === defVal) {
|
||
return result
|
||
}
|
||
defVal = replaceAll(defVal, origin, result)
|
||
}
|
||
return defVal
|
||
}
|
||
|
||
/** 执行【普通表达式】#{xxx} */
|
||
async function executeNormalExpression(expression, origin) {
|
||
switch (expression) {
|
||
case 'date':
|
||
return dayjs().format('YYYY-MM-DD');
|
||
case 'time':
|
||
return dayjs().format('HH:mm:ss');
|
||
case 'datetime':
|
||
return dayjs().format('YYYY-MM-DD HH:mm:ss');
|
||
default:
|
||
// 获取当前登录用户的信息
|
||
let result = getUserInfoByExpression(expression)
|
||
if (result != null) {
|
||
return result
|
||
}
|
||
// 没有符合条件的表达式,返回原始值
|
||
return origin
|
||
}
|
||
}
|
||
|
||
/** 根据表达式获取相应的用户信息 */
|
||
function getUserInfoByExpression(expression) {
|
||
let userInfo:any = useUserStore().userInfo;
|
||
if (userInfo) {
|
||
switch (expression) {
|
||
case 'sysUserId':
|
||
return userInfo.id
|
||
// 当前登录用户登录账号
|
||
case 'sysUserCode':
|
||
return userInfo.username
|
||
// 当前登录用户真实名称
|
||
case 'sysUserName':
|
||
return userInfo.realname
|
||
// 当前登录用户部门编号
|
||
case 'sysOrgCode':
|
||
return userInfo.orgCode
|
||
}
|
||
}
|
||
return null
|
||
}
|
||
/**
|
||
* 2023-09-04
|
||
* liaozhiyang
|
||
* 用new Function替换eval
|
||
*/
|
||
function _eval(str: string) {
|
||
return new Function(`return ${str}`)();
|
||
}
|
||
/** 执行【用户自定义表达式】 {{xxx}} 移动端不支持 */
|
||
async function executeCustomExpression(expression, origin) {
|
||
// 利用 eval 生成一个方法,这个方法的参数就是用户自定义的所有的表达式
|
||
let fn = _eval(`(function (${ceJoin}){ return ${expression} })`);
|
||
try {
|
||
// 然后调用这个方法,并把表达式传递进去,从而完成表达式的执行
|
||
return fn.apply(null, $CE$)
|
||
} catch (e) {
|
||
// 执行失败,输出错误并返回原始值
|
||
logWarn(e)
|
||
return origin
|
||
}
|
||
}
|
||
|
||
/** 执行【填值规则表达式】 ${xxx} */
|
||
async function executeFillRuleExpression(expression, origin, getFormData) {
|
||
let url = `/sys/fillRule/executeRuleByCode/${expression}`
|
||
let formData = {}
|
||
if (typeof getFormData === 'function') {
|
||
formData = getFormData()
|
||
}
|
||
let res:any = await http.put(url, formData)
|
||
let { success, message, result } = res;
|
||
console.log(success, message, result)
|
||
if (success) {
|
||
return result
|
||
} else {
|
||
logError(`填值规则(${expression})执行失败:${message}`)
|
||
return origin
|
||
}
|
||
}
|
||
|
||
function logWarn(message) {
|
||
console.warn('[loadFieldDefVal]:', message)
|
||
}
|
||
|
||
function logError(message) {
|
||
console.error('[loadFieldDefVal]:', message)
|
||
}
|
||
|
||
function replaceAll(text, checker, replacer) {
|
||
let lastText = text
|
||
text = text.replace(checker, replacer)
|
||
if (lastText !== text) {
|
||
return replaceAll(text, checker, replacer)
|
||
}
|
||
return text
|
||
}
|
||
|