d-render
Version:
数据渲染库 - form、table、search-form
177 lines (162 loc) • 6.66 kB
text/typescript
// 执行器放到执行器内部
// 作用执行其
import { IAnyObject, IRenderConfigDependOn, TFormConfig, IRenderConfigDependOnEffect } from '@d-render/shared'
import { IKey } from './util'
type TEffectFn = ((...args: unknown[])=> unknown | Promise<unknown>) | boolean
interface IPrivateParam {
keys: Array<string>
oldValues: Array<unknown>
}
type TEffect = [
TEffectFn,
IPrivateParam
]
export type IEffects = Array<TEffect>
export type IExecutor = (values: IAnyObject, outValues: IAnyObject|undefined, effects: IEffects) => void | Promise<void>
interface IGlobalParam {
values: IAnyObject
outValues?: IAnyObject
keys: Array<IKey>
oldValues: Array<unknown>
executeChangeValueEffect: boolean
}
interface IEffectExecutorConfig {
executor: IExecutor
condition?: (effects: IEffects, executeChangeValueEffect: boolean) => boolean
// eslint-disable-next-line @typescript-eslint/ban-types
transformStrEffect?: (effectStr: string) => Function
}
export interface IEffectExecutorConfigs{
[propname: string]: IEffectExecutorConfig
}
interface IEffectConfig {
[propname: string]: IEffects
}
interface IEffectParam {
keys?: Array<string>
effect?: IRenderConfigDependOn['effect'] // Record<string, Array<IFun>|IFun|boolean> | boolean
oldValues?: Array<unknown>
}
// IEffectParam 全局模式时为空对象
type IEffectParams = Array<IEffectParam>
export class EffectExecutor {
config: IEffectExecutorConfigs
types: Array<string>
executeChangeValueEffect?: boolean
values?: IAnyObject
outValues?: IAnyObject
effectsConfig?: IEffectConfig
constructor (config: IEffectExecutorConfigs = {}) {
this.config = config
this.types = Object.keys(this.config)
}
setExecutor (type: string, executor: IExecutor) {
this.config[type] = {} as IEffectExecutorConfig
this.config[type].executor = executor
this.types = Object.keys(this.config)
}
// 处理数组及字符型数据
compatibleEffect (effectConfig: IRenderConfigDependOnEffect, type: string, param: IPrivateParam|IGlobalParam) {
const transformStrEffect = this.config[type].transformStrEffect
const effect = transformStrEffect
? effectConfig[type] || effectConfig[`${type}Str`]
: effectConfig[type]
return ([] as Array<string|TEffectFn>).concat(effect as TEffectFn).map(e => {
let fn: TEffectFn = e as TEffectFn
// 当transformStrEffect不存在时 string无法转换为函数
if (typeof e === 'string') {
if (typeof transformStrEffect === 'function') {
fn = transformStrEffect(e) as TEffectFn
} else {
fn = () => {
console.warn(`[transformStrEffect warn]: ${type}未配置字符串转函数的方法`)
}
}
}
return [fn, param]
})
}
getGlobalEffect (fieldConfig: TFormConfig, type: string) {
return this.config[type].transformStrEffect
? (fieldConfig[type] || fieldConfig[`${type}Str`])
: fieldConfig[type]
}
getExecuteEffect (params: IEffectParams, fieldConfig: TFormConfig, globalParam: IGlobalParam) {
console.log('params', params)
const analysisEffects = this.types
// 初始化
const executeObject = analysisEffects.reduce((acc: { [key: string]: Array<unknown> }, key) => {
acc[key] = []
return acc
}, {})
const globalEffectSign = analysisEffects.reduce((acc:{ [key: string]: boolean }, key) => {
acc[key] = false
return acc
}, {})
// 获取到
const globalParams = params.filter(param => {
return param.effect === undefined || param.effect === true
})
if (globalParams.length > 0) {
// 存在时从global中需要执行的effect
analysisEffects.forEach(key => {
if (this.getGlobalEffect(fieldConfig, key)) globalEffectSign[key] = true
})
params = params.filter(param => {
return !(param.effect === undefined || param.effect === true)
})
}
// 此时的params均为局部处理 分析effect
(params as Array<Required<Omit<IEffectParam, 'effect'> & {effect: Exclude<IEffectParam['effect'], boolean | undefined>}>>).forEach(param => {
const { effect, ...privateParam } = param // 入参数抛弃effect
analysisEffects.forEach(key => {
// resetValue 具有一定的特殊性, 其存在局部时,不需要触发global的 但是允许存在global的reset
if (typeof effect[key] === 'function') {
if (key !== 'resetValue') globalEffectSign[key] = true
executeObject[key].push(...this.compatibleEffect(effect, key, privateParam))
} else if (effect[key] === true) {
if (key !== 'resetValue') {
globalEffectSign[key] = true
} else {
executeObject[key].push(...this.compatibleEffect(effect, key, privateParam))
}
}
})
})
// 此处的入参数需要再商讨
analysisEffects.forEach(key => {
if (globalEffectSign[key] && this.getGlobalEffect(fieldConfig, key)) {
executeObject[key].unshift(...this.compatibleEffect(fieldConfig as IRenderConfigDependOnEffect, key, globalParam))
} else {
// if (!globalEffectSign[key]) console.log(`不需要${key}全局effect`)
// if (!config[key]) console.log(`没有${key}全局effect`)
}
})
console.log('executeObject', executeObject)
return executeObject as IEffectConfig
}
analysisEffects (effectParams: IEffectParams, config: TFormConfig, globalParam: IGlobalParam) {
console.log('effectParams', effectParams)
this.executeChangeValueEffect = globalParam.executeChangeValueEffect
this.values = globalParam.values
this.outValues = globalParam.outValues
this.effectsConfig = this.getExecuteEffect(effectParams, config, globalParam)
}
execute (type: string, logKey: string, ...args: [effects: IEffects, executeChangeValueEffect: boolean]) {
const condition = this.config[type].condition
if (args[0].length > 0) {
if (!condition || (condition && condition(...args))) {
this.config[type].executor(this.values!, this.outValues, args[0])
console.log(`%c[d-render]%c执行%c${logKey}.${type}`, 'color: #e6a23c', 'color: normal', 'color: #67c23a')
} else {
console.log(`%c[d-render]%c不符合%c${logKey}.${type}%c执行条件`, 'color: #e6a23c', 'color: normal', 'color: red', 'color: normal', args[0])
}
}
}
executeAll (logKey: string) {
// 是否让xx按顺序执行
Object.keys(this.effectsConfig as IEffectConfig).forEach((type) => {
this.execute(type, logKey, this.effectsConfig![type], this.executeChangeValueEffect!)
})
}
}