import Vue from 'vue' import {componentFactory} from './YvanRender' import webix from 'webix' export type VJson = any export type ViewExtendType = { [P in keyof T]?: Partial } /** * 业务模块接口 */ export interface Module { viewResolver(): VJson viewIntercept?(vjson: VJson, inParamter?: INP): void viewExtend?(inParamter?: INP): ViewExtendType onLoad?(): void } function getDisplay(viewId: string): any { let view:any = webix.$$(viewId).$view; let display = ''; let tag = true; while (tag) { display = view.style.display; if (display === 'none') { tag = false } view = view.parentNode if(!view || view === document.body) { tag = false } } return display; } export abstract class BaseModule extends Vue implements Module { /** * 组件对象引用 */ refs!: Refs /** * showDialog 带来的参数 */ inParamter!: INP /** * 是否为设计模式 */ isDesignMode!: boolean _webixId: any /** * 模块实例 ID (运行时自动创建) */ instanceId!: string /** * 模块是否加载完毕 */ loadFinished!: boolean /** * 模块被渲染完成之后调用 */ onLoad(): void { } /** * 每次从隐藏状态换显出来后调用 */ onShow(): void { } abstract viewResolver(): VJson /** * 根据名称,获取空白区域操作句柄 */ getPlace(placeId: string): any { return webix.$$(_.get(this, 'instanceId') + '$' + placeId) } /** * 从外部设置输入参数 */ setInParamter!: (inParamter: INP) => void /** * 获取实体类到控件的绑定对象 */ getEntityCtlMapping(entityName: string): any { return _.get(this, '_entityCtlMapping.' + entityName) } /** * 根据实体路径,获取 {metaId:value} */ getEntityWithMeta(entityName: string, entity: any): any { const result: any = {} const metas = this.getEntityCtlMapping(entityName) _.forOwn(metas, (value, key) => { if (metas[key].vjson && metas[key].vjson.metaId) { result[metas[key].vjson.metaId] = entity[key] } }) return result; } setEntity(entityName: string, entity: any) { const a = _.get(this, entityName); _.merge(a, entity); } /** * 根据实体路径,设置 */ setEntityWithMeta(entityName: string, entity: any) { const a = _.get(this, entityName); _.merge(a, entity); } validate(entityName: string): Promise { return new Promise((resolver, reject) => { const ctlMappings: any = _.get(this, '_entityCtlMapping.' + entityName); /** * 校验的时候需要知道组件当前的状态 */ const result = {}; if (_.get(ctlMappings, '_required') === true || _.has(ctlMappings, 'onValidate')) { /** * 根据id(computed的方法名 == id)获取 组件的方法拿到结果 判断是否需要校验 */ //@ts-ignore // const f = ctlMappings._module[ctlMappings.id.replace(ctlMappings._module.instanceId + '_',"")] const display = ctlMappings.id ? getDisplay(ctlMappings.id) : ""; if (!(_.get(ctlMappings, 'hidden') === true) && !(display === 'none')) { const validateResult = ctlMappings._resultToShowOrHide(); if (validateResult) { ctlMappings._showTootip(validateResult) ctlMappings._showValidateError() ctlMappings.focus() _.set(result, ctlMappings.entityName, validateResult) } } } else { let isShow = false; _.forEach(ctlMappings, (ctl, key) => { if (_.get(ctl, '_required') === true || _.has(ctl, 'onValidate')) { /** * 根据id(computed的方法名 == id)获取 组件的方法拿到结果 判断是否需要校验 */ //@ts-ignore // const f = ctl._module[ctl.id.replace(ctl._module.instanceId + '_',"")] const display = ctlMappings.id ? getDisplay(ctlMappings.id) : ""; if (!(_.get(ctl, 'hidden') === true) && !(display === 'none')) { const validateResult = ctl._resultToShowOrHide(); if (validateResult) { ctl._showValidateError() _.set(result, key, validateResult) if (!isShow) { isShow = true ctl._showTootip(validateResult) ctl.focus() } } } } }); } if (_.size(result) > 0) { reject(result) } else { resolver(_.get(this, entityName)); } }); } /** * 获取或设置 window 标题 */ set title(v: string) { if (this._webixId && _.has(this, '_titleLabel')) { // webix 对象已经出现 this._webixId.define('title', v) const _titleLabel = _.get(this, '_titleLabel'); _titleLabel.define('label', v) _titleLabel.refresh() return } console.error('无法设置 title') } get title(): string { if (this._webixId) { // webix 对象已经出现 return this._webixId.config.title; } return '无法获取'; } vjsonExtend?: (vJson: VJson) => any; } export abstract class BaseDialog extends BaseModule { /** * 对话框 DOM 对象 */ layero: any /** * 组件对象引用 */ refs!: Refs /** * 显示对话框 * @param inParamter 输入参数 * @param container 父容器 */ showDialog!: ( inParamter: INP, parent: any, isFromSearchBox?: boolean ) => void /** * 关闭对话框 */ closeDialog!: () => void /** * 按下 ESC 键 */ onEsc() { this.closeDialog() } /** * 按下 Enter 键 */ onEnter() { // debugger } /** * 关闭后触发 */ onClose() { } /** * 对话框的父亲(打开者) */ dialogParent!: any /** * 显示进行中的状态 */ showLoading() { webix.extend(this._webixId, webix.OverlayBox) //this._webix.showOverlay("
There is no data
"); this._webixId.showOverlay('Loading...') } /** * 关闭进行中的状态 */ closeLoading() { this._webixId.hideOverlay() } } export type BaseModuleType = typeof BaseModule /** * 装饰业务模块 * @param options */ export function BizModule(option?: any): Function { return function (Component: BaseModule) { return componentFactory(Component, option) } // const option = { // ...createOption, // template: ``, // ...createMixins(createOption) // } // return VueComponent>(option) } export interface BizWatch { /** * 监听的表达式 */ expr: string /** * 深度监听 */ deep: boolean /** * 是否立刻执行 */ immediate: boolean /** * 执行的方法 */ handler: any } /** * 装饰字段(监听某个属性值变化) */ export function Watch( propName: string, deep: boolean = false, immediate: boolean = false ) { if (typeof deep === 'undefined') { deep = false } if (typeof immediate === 'undefined') { immediate = false } return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) { if (typeof target.watches === 'undefined') { target.watches = [] } const watch: BizWatch = { expr: propName, deep, immediate, handler: descriptor.value } target.watches.push(watch) } }