You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
208 lines
5.4 KiB
208 lines
5.4 KiB
// import { VueConstructor } from 'vue'; |
|
import { cloneDeep, isArray, isFunction, isNumber, uniqueId } from 'lodash-es' |
|
import type { IFormConfig, IVFormComponent, IValidationRule } from '../typings/v-form-component' |
|
|
|
// import { del } from '@vue/composition-api'; |
|
// import { withInstall } from '@/utils'; |
|
|
|
/** |
|
* 组件install方法 |
|
* @param comp 需要挂载install方法的组件 |
|
*/ |
|
// export function withInstall<T extends { name: string }>(comp: T) { |
|
// return Object.assign(comp, { |
|
// install(Vue: VueConstructor) { |
|
// Vue.component(comp.name, comp); |
|
// }, |
|
// }); |
|
// } |
|
|
|
/** |
|
* 生成key |
|
* @param [formItem] 需要生成 key 的控件,可选,如果不传,默认返回一个唯一 key |
|
* @returns {string|boolean} 返回一个唯一 id 或者 false |
|
*/ |
|
export function generateKey(formItem?: IVFormComponent): string | boolean { |
|
if (formItem && formItem.component) { |
|
const key = uniqueId(`${toLine(formItem.component)}_`) |
|
formItem.key = key |
|
formItem.field = key |
|
|
|
return true |
|
} |
|
return uniqueId('key_') |
|
} |
|
|
|
/** |
|
* 移除数组中指定元素,value可以是一个数字下标,也可以是一个函数,删除函数第一个返回true的元素 |
|
* @param array {Array<T>} 需要移除元素的数组 |
|
* @param value {number | ((item: T, index: number, array: Array<T>) => boolean} |
|
* @returns {T} 返回删除的数组项 |
|
*/ |
|
export function remove<T>( |
|
array: Array<T>, |
|
value: number | ((item: T, index: number, array: Array<T>) => boolean), |
|
): T | undefined { |
|
let removeVal: Array<T | undefined> = [] |
|
if (!isArray(array)) |
|
return undefined |
|
if (isNumber(value)) { |
|
removeVal = array.splice(value, 1) |
|
} |
|
else { |
|
const index = array.findIndex(value) |
|
if (index !== -1) |
|
removeVal = array.splice(index, 1) |
|
} |
|
return removeVal.shift() |
|
} |
|
|
|
/** |
|
* 判断数据类型 |
|
* @param value |
|
*/ |
|
export function getType(value: any): string { |
|
return Object.prototype.toString.call(value).slice(8, -1) |
|
} |
|
|
|
/** |
|
* 生成唯一guid |
|
* @returns {string} 唯一id标识符 |
|
*/ |
|
export function randomUUID(): string { |
|
function S4() { |
|
return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1) |
|
} |
|
return `${S4() + S4()}-${S4()}-${S4()}-${S4()}-${S4() + S4() + S4()}` |
|
} |
|
|
|
/** |
|
* 驼峰转下划线 |
|
* @param str |
|
*/ |
|
export function toLine(str: string) { |
|
return str.replace(/([A-Z])/g, '_$1').toLowerCase() |
|
} |
|
|
|
/** |
|
* 遍历表单项 |
|
* @param array |
|
* @param cb |
|
*/ |
|
export function formItemsForEach(array: IVFormComponent[], cb: (item: IVFormComponent) => void) { |
|
if (!isArray(array)) |
|
return |
|
const traverse = (schemas: IVFormComponent[]) => { |
|
schemas.forEach((formItem: IVFormComponent) => { |
|
if (['Grid'].includes(formItem.component)) { |
|
// 栅格布局 |
|
formItem.columns?.forEach(item => traverse(item.children)) |
|
} |
|
else { |
|
cb(formItem) |
|
} |
|
}) |
|
} |
|
traverse(array) |
|
} |
|
|
|
/** |
|
* 查找表单项 |
|
*/ |
|
export const findFormItem: ( |
|
schemas: IVFormComponent[], |
|
cb: (formItem: IVFormComponent) => boolean, |
|
) => IVFormComponent | undefined = (schemas, cb) => { |
|
let res |
|
const traverse = (schemas: IVFormComponent[]): boolean => { |
|
return schemas.some((formItem: IVFormComponent) => { |
|
const { component: type } = formItem |
|
// 处理栅格 |
|
if (['Grid'].includes(type)) |
|
return formItem.columns?.some(item => traverse(item.children)) |
|
|
|
if (cb(formItem)) |
|
res = formItem |
|
return cb(formItem) |
|
}) |
|
} |
|
traverse(schemas) |
|
return res |
|
} |
|
|
|
/** |
|
* 打开json模态框时删除当前项属性 |
|
* @param formConfig {IFormConfig} |
|
* @returns {IFormConfig} copyFormConfig |
|
*/ |
|
export function removeAttrs(formConfig: IFormConfig): IFormConfig { |
|
const copyFormConfig = cloneDeep(formConfig) |
|
delete copyFormConfig.currentItem |
|
delete copyFormConfig.activeKey |
|
copyFormConfig.schemas |
|
&& formItemsForEach(copyFormConfig.schemas, (item) => { |
|
delete item.icon |
|
delete item.key |
|
}) |
|
return copyFormConfig |
|
} |
|
|
|
/** |
|
* 处理异步选项属性,如 select treeSelect 等选项属性如果传递为函数并且返回Promise对象,获取异步返回的选项属性 |
|
* @param {(() => Promise<any[]>) | any[]} options |
|
* @return {Promise<any[]>} |
|
*/ |
|
export async function handleAsyncOptions(options: (() => Promise<any[]>) | any[]): Promise<any[]> { |
|
try { |
|
if (isFunction(options)) |
|
return await options() |
|
return options |
|
} |
|
catch { |
|
return [] |
|
} |
|
} |
|
|
|
/** |
|
* 格式化表单项校验规则配置 |
|
* @param {IVFormComponent[]} schemas |
|
*/ |
|
export function formatRules(schemas: IVFormComponent[]) { |
|
formItemsForEach(schemas, (item) => { |
|
if ('required' in item) { |
|
!isArray(item.rules) && (item.rules = []) |
|
item.rules.push({ required: true, message: item.message }) |
|
delete item.required |
|
delete item.message |
|
} |
|
}) |
|
} |
|
|
|
/** |
|
* 将校验规则中的正则字符串转换为正则对象 |
|
* @param {IValidationRule[]} rules |
|
* @return {IValidationRule[]} |
|
*/ |
|
export function strToReg(rules: IValidationRule[]) { |
|
const newRules = cloneDeep(rules) |
|
return newRules.map((item) => { |
|
if (item.pattern) |
|
item.pattern = runCode(item.pattern) |
|
return item |
|
}) |
|
} |
|
|
|
/** |
|
* 执行一段字符串代码,并返回执行结果,如果执行出错,则返回该参数 |
|
* @param code |
|
* @return {any} |
|
*/ |
|
export function runCode<T>(code: any): T { |
|
try { |
|
// eslint-disable-next-line no-new-func |
|
return new Function(`return ${code}`)() |
|
} |
|
catch { |
|
return code |
|
} |
|
}
|
|
|