Files
qhmes/JeecgUniapp-master/src/components/online/defaultVal.ts
2026-07-20 14:10:39 +08:00

303 lines
9.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 移动端不支持自定义表达式设置的默认值
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 foronline功能测试行操作切换成新的行编辑-----------
let v = [{rowKey: row.id, values: {[key]: value}}];
(subForms.jvt || subForms.jet).setValues(v)
// update-end---author:sunjianlei Date:20200725 foronline功能测试行操作切换成新的行编辑------------
}
}, 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
}