packages/data-render/src/widgets/utils/common.ts (224 lines of code) (raw):

import { message } from 'antd'; import classnames from 'classnames'; import dayjs from 'dayjs'; import timezone from 'dayjs/plugin/timezone'; import utc from 'dayjs/plugin/utc'; import { isNumber, isObject, isString, get } from 'lodash-es'; dayjs.extend(utc); dayjs.extend(timezone); export const combineClass = (name: any, data: any, extra = {}) => { let result: any = {}; if (typeof data === 'string') { result = { [data]: true }; } if (Array.isArray(data)) { data.forEach((item) => { result[item] = true; }); } return classnames(name, { ...result, ...extra }); }; /** * * @param string * @returns */ export const parseString = (string: string) => Function('"use strict";return (' + string + ')')(); /** * @param path // 对应数据的路径,例如:'a.b.c' * @param defaultValue // 默认值 * @param data // 数据 * @param addons // 渲染器方法集,访问 getSourceData * @returns value */ export const getValueFromKey = (props: { path: string; data?: any; defaultValue?: any; addons: any; valueType?: string; }): string | boolean => { const { data, path = '', defaultValue = '', addons, valueType } = props; let result: any = null; let negation: any = null; // 否定标识 ! let dataPath = path; if (path.substring(0, 2) === '!!') { negation = '!!'; dataPath = path.substring(2); } else if (path.substring(0, 1) === '!') { negation = '!'; dataPath = path.substring(1); } // 带 source 标识,表示从顶层获取数据 if (dataPath.includes('source:')) { const [_, sourcePath]: any = dataPath.split('source:'); const sourceData = addons.getSourceData(); result = get(sourceData, sourcePath); } else { result = get(data, dataPath); } if (!result && result !== 0 && typeof result !== 'boolean') { result = defaultValue; } // 根据 negation 取反, 返回结果 if (negation === '!') { return !result; } if (negation === '!!') { return !!result; } if (result && valueType === '!object' && typeof result === 'object') { return ''; } return result; }; /** * 数据格式转换 */ export const transformData = (value: any, format: any, parentData?: any, addons?: any) => { if (!format || (!value && value !== 0 && format.type !== 'dateTime-range')) { return value; } const getValue = (value: any, item: any) => { const { type, config }: any = item; let result = value; if (type === 'dateTime-range') { const { startKey, endKey }: any = config; let startTime: any = getValueFromKey({ data: parentData, path: startKey, addons }); if (startTime) { startTime = dayjs.tz(startTime).format(config.format || 'YYYY-MM-DD HH:mm:ss'); } let endTime: any = getValueFromKey({ data: parentData, path: endKey, addons }); if (endTime) { endTime = dayjs.tz(endTime).format(config.format || 'YYYY-MM-DD HH:mm:ss'); } if (startTime !== 'Invalid Date') { result = startTime; } if (endTime !== 'Invalid Date') { result += ' ~ ' + endTime; } } // 日期 if (type === 'date') { result = dayjs.tz(value).format(config || 'YYYY-MM-DD'); } // 时间 if (type === 'dateTime') { result = dayjs.tz(value).format(config || 'YYYY-MM-DD HH:mm:ss'); } // 枚举 if (type === 'enum' && typeof config === 'object') { result = config[value] || config.default || value; } // 单位: 左边 if (type === 'leftUnit' && config) { if (config.includes('dataKey:')) { result = `${getValueFromKey({ data: parentData, path: config.split('dataKey:')[1], addons, defaultValue: '', })} ${value}`; } else { result = `${config} ${value}`; } } // 单位: 右边 if (type === 'rightUnit' && config) { if (config.includes('dataKey:')) { result = `${value} ${getValueFromKey({ data: parentData, path: config.split('dataKey:')[1], addons, defaultValue: '', })}`; } else { result = `${value} ${config}`; } } // 一分 if (type === 'penny') { result = (value * 100).toFixed(config || 2); } // 分转元 if (type === 'spunYuan') { result = value / 100; } // 百分比 if (type === 'percent') { result = (value * 100).toFixed(config || 2) + '%'; } // 浮点数转换 if (type === 'float') { result = (value * 1).toFixed(config || 2); } // 函数 if (type === 'function') { result = parseString(config)(value); } if (result === 'Invalid Date') { result = ''; console.warn('日期转换错误'); } if (result === 'NaN%') { result = ''; console.warn('百分率转换错误'); } return result; }; return Array.isArray(format) ? format.reduce((preValue, item) => getValue(preValue, item), value) : getValue(value, format); }; // 是否是数组 export function isArray(input: any): input is any[] { return Array.isArray(input); } // 获取请求参数 export const getRequestParams = (cond: any, data: any, insideData?: any) => { if (!cond) { return {}; } let params: any = {}; for (let key in cond) { let value = get(data, cond[key], null); if (cond[key].includes('dataKey:')) { value = get(insideData, cond[key].split(':')[1], null); } params[key] = value; } return params; }; // 复制 export const clipboardCopy = (url: string) => { navigator.clipboard.writeText(url).then( function () { /* clipboard successfully set */ message.success('复制成功'); }, function () { /* clipboard write failed */ message.error('复制失败'); }, ); }; // 判断数据为空 export const isDataEmpty = (data: any, level: 1 | 2) => { if ( Object.prototype.toString.call(data) === '[object Object]' && Object.keys(data).length === 0 ) { return true; } if (isArray(data) && data.length === 0) { return true; } if (level === 1 && (!data || data === '0')) { return true; } if (level === 2 && !data && data !== 0) { return true; } }; // 判断是否是子协议 export const isReactNodeSchema = (schema: any = {}) => { return JSON.stringify(schema).includes('widget'); }; export const startsWith = (str: string, startStr: string) => { const reg = new RegExp('^' + startStr); return reg.test(str); }; export const isThenable = (func: any) => { return Boolean(func && typeof func.then === 'function'); }; const validatorMap = { string: isString, number: isNumber, object: isObject, array: isArray, }; export const isType = (val: any, types: Array<keyof typeof validatorMap>) => { return types.some((t) => { const func = validatorMap[t]; return func(val); }); }; export const transDataKeyToData = (object: any, { data, addons }: any) => { // 进行动态数据绑定 Object.keys(object).forEach((key) => { const item = object[key]; if (typeof item !== 'string') { return; } if (startsWith(item, 'source:')) { object[key] = getValueFromKey({ path: item, data, addons }); return; } if (startsWith(item, 'data:')) { const path = item.split('data:')[1]?.trim(); object[key] = getValueFromKey({ path, data, addons }); } }); }; export const renderString = (str: any) => { if (isObject(str)) { return ''; } return str; }