import { injectable } from 'inversify'; import { IDisposable, IInital, KV } from 'ts-toolset'; import { IPropGroupEntity } from '../../../models/base'; import { IEditorOption, EditorOption } from './editorOption'; import { getPartialProperty } from 'ts-toolset/dist/common/object'; import { IInstanceFactory, InstanceFactory } from '../../../common/instanceFactory'; import { EditorOptionlMaterial, EditorValue, EditorHookParam, EditorOptionHookNames, EditorOptionGroup, IEditorOptionGroup } from './types'; export type InitialOptions = { data?: any, propGroups?: IPropGroupEntity[] }; export interface IEditor extends IInital, IDisposable { readonly isInitial: boolean; readonly editorOptions: IEditorOption[]; readonly editorOptionMap: Map; readonly editorOptionGroups: IEditorOptionGroup[]; readonly changeEditorOptions: KV; getValues(): any; getChangeValues(): any; importValues(values: any, ...params: any[]): void; setValues(values: EditorValue | EditorValue[], once?: boolean): void; callHooks(editorParams: EditorHookParam | EditorHookParam[]): void; } @injectable() export abstract class Editor implements IEditor { private _options: any = {}; // 内部对象被外部间接饮用水时,不能直接改变对象的指向,而要在原本的实例对象进行修改 protected _editorOptionInstances: IInstanceFactory;; protected _editorOptions: EditorOption[]; protected _editorOptionMap: Map; protected _editorOptionGroups: EditorOptionGroup[] = []; protected _isInitial: boolean = false; protected _changeEditorOptions: KV constructor() { this._editorOptionInstances = new InstanceFactory(); this._editorOptions = []; this._editorOptionGroups = []; this._editorOptionMap = new Map(); this._changeEditorOptions = {}; } get isInitial() { return this._isInitial; } get editorOptions() { return this._editorOptions; } get editorOptionMap() { return this._editorOptionMap; } get editorOptionGroups() { return this._editorOptionGroups; } get changeEditorOptions() { return this._changeEditorOptions; } protected _mergeValue(editorOption: EditorOption, value: any) { if (editorOption.propEntity.combination) { value = { ...value, ...editorOption.realValue }; } else { value[editorOption.propKey] = editorOption.realValue; } } /** 编辑器设置值 */ protected _setValue({ defaultHooks = true, ...value }: EditorValue) { if ('data' in value) { value.editorOption.setData(value.data); defaultHooks && this._callHook({ hookName: EditorOptionHookNames.setData, editorOption: value.editorOption }); } if ('visible' in value) { value.editorOption.setVisible(value.visible!); defaultHooks && this._callHook({ hookName: EditorOptionHookNames.setVisible, editorOption: value.editorOption }); } if ('value' in value) { value.reserve ? value.editorOption.setRealValue(value.value, value.matchData) : value.editorOption.setValue(value.value, value.matchData); // setValue 只能用在纯净的绑定值上,不要有太多附加流程,不然撤销恢复会出现联动改变,会有问题?? defaultHooks && this._callHook({ hookName: EditorOptionHookNames.setValue, editorOption: value.editorOption }); } value.hooks && this.callHooks(value.hooks); this._changeEditorOptions[value.editorOption.propKey] = value.editorOption; } protected _getEditorOptionInstance(material: EditorOptionlMaterial, data: any) { let editorOption = this._editorOptionInstances.getInstance(EditorOption) as EditorOption; material.prop.combination && (material.value = getPartialProperty(data, material.prop.combination, true)); editorOption.initial(material); return editorOption; } /** 调用编辑器项钩子 */ protected _callHook(param: EditorHookParam) { let hook = param.editorOption.getHook(param.hookName); hook && hook(param.editorOption, this._editorOptionMap); } /** 初始化编辑器 */ initial(materials: EditorOptionlMaterial[], { data = {}, propGroups }: InitialOptions = { data: {} }) { this._isInitial && this.dispose(); /** 初始化编辑项 */ let groups: any = {}; this._editorOptions = materials.map(material => { let editorOption = this._getEditorOptionInstance(material, data); this._editorOptionMap.set(material.prop.key, editorOption); if (editorOption.propEntity.group) { groups[editorOption.propEntity.group] ? groups[editorOption.propEntity.group].push(editorOption) : groups[editorOption.propEntity.group] = [editorOption]; } return editorOption; }); propGroups && (this._editorOptionGroups = propGroups.map(group => ({ ...group, editorOptions: groups[group.key] || [] }))); groups = undefined; this.abstractInitial(); this._isInitial = true; } protected abstract abstractInitial(): void; // memorize getValues() { let value: any = {}; this._editorOptionMap.forEach(eo => this._mergeValue(eo, value)); return value; } getChangeValues() { let values: any = {}; for (let key in this._changeEditorOptions) values[key] = this._changeEditorOptions[key].realValue; return values; } importValues(values: any, ...params: any[]) { values = values || {}; // 导入 编辑项的值 this._editorOptionMap.forEach(editorOption => { let value = editorOption.propEntity.combination === undefined ? values[editorOption.propKey] : getPartialProperty(values, editorOption.propEntity.combination, true); this._setValue({ editorOption, value, reserve: true }); }); this.abstractImportValues(values, ...params); } protected abstract abstractImportValues(values: any, ...params: any[]): void; setValues(values: EditorValue | EditorValue[], once: boolean = true) { Array.isArray(values) ? values.forEach(v => this._setValue(v)) : this._setValue(values); once && this.abstractChangeValues(); } protected abstract abstractChangeValues(): void; callHooks(editorParams: EditorHookParam | EditorHookParam[]) { Array.isArray(editorParams) ? editorParams.forEach(v => this._callHook(v)) : this._callHook(editorParams); } dispose() { this._editorOptionInstances.recycle(); this._editorOptionMap.clear(); this._editorOptions.splice(0, -1); this._editorOptionGroups.splice(0, -1); this._changeEditorOptions = {}; this.abstractDestroy(); this._isInitial = false; } protected abstract abstractDestroy(): void; }