import { Prop, Component } from 'vue-property-decorator';
import { IPSControl, IPSPanelButton, IPSPanelContainer, IPSPanelItem, IPSPanelRawItem, IPSPanelTabPage, IPSPanelTabPanel, IPSSysPanelButton, IPSSysPanelField, IPSViewLayoutPanel } from '@ibiz/dynamic-model-api';
import { Util, ThirdPartyService, PanelButtonModel, PanelTabPanelModel, PanelTabPageModel, PanelContainerModel, PanelFieldModel, PanelRawitemModel, PanelControlModel, PanelUserControlModel, PanelCtrlPosModel, appEngineService, AppServiceBase, ModelTool } from 'ibiz-core';
import { PluginService } from '../../../../app-service/common-service/plugin-service';
import { AppViewLogicService, ContainerLoadingService, LayoutLoadingService } from '../../../../app-service';
import { ControlContainer } from '../../../../control-container/control-container';
import { Subject } from 'rxjs';

/**
 * 视图基础布局
 *
 * @export
 * @class AppDefaultViewLayout
 * @extends {Vue}
 */
@Component({})
export class AppDefaultViewLayout extends ControlContainer {

    /**
     * 视图模型数据
     * 
     * @memberof AppDefaultViewLayout
     */
    @Prop() public viewInstance!: any;

    /**
     * 模型服务对象
     * 
     * @memberof AppDefaultViewLayout
     */
    @Prop() public modelService: any;

    /**
     * 使用视图头
     *
     * @type {boolean}
     * @memberof AppDefaultViewLayout
     */
    @Prop({ default: true }) public showCaptionBar?: boolean;

    /**
     * 初始化完成
     *
     * @type {boolean}
     * @memberof AppDefaultViewLayout
     */
    public viewIsInit: boolean = false;

    /**
     * 视图布局面板
     * 
     * @memberof AppDefaultViewLayout
     */
    public viewLayoutPanel?: IPSViewLayoutPanel | null;

    /**
     * 视图代理模式(默认为false)
     *
     * @type {boolean}
     * @memberof AppDefaultViewLayout
     */
    public viewProxyMode: boolean = false;

    /**
     * 视图布局模型
     *
     * @type {*}
     * @memberof AppDefaultViewLayout
     */
    public layoutDetailsModel: any = {};

    /**
     * 面板数据
     *
     * @type {*}
     * @memberof AppDefaultViewLayout
     */
    public layoutData: any = {};

    /**
     * 状态传递对象
     *
     * @type {(Subject<any> | undefined)}
     * @memberof AppDefaultViewLayout
     */
    public viewState: Subject<any> | undefined = undefined;

    /**
     * 视图标识
     *
     * @type {string}
     * @memberof AppDefaultViewLayout
     */
    public viewtag: string = '';

    /**
     * 视图名称
     *
     * @type {string}
     * @memberof AppDefaultViewLayout
     */
    public viewCodeName: string = '';

    /**
     * 面板加载服务
     *
     * @type {LayoutLoadingService}
     * @memberof AppDefaultViewLayout
     */
    public layoutLoadingService: LayoutLoadingService = new LayoutLoadingService();

    /**
     * 绘制参数
     *
     * @readonly
     * @memberof AppDefaultViewLayout
     */
    public renderOptions: any = {
        viewClassNames: {}
    };

    /**
     * Vue生命周期,实例创建完成
     *
     * @memberof AppDefaultViewLayout
     */
    created() {
        this.initViewSpecificData();
        this.initViewLayOutContainer();
    }

    /**
     * 初始化视图特有参数
     *
     * @memberof AppDefaultViewLayout
     */
    public initViewSpecificData() { }

    /**
     * 初始化面板容器
     *
     * @memberof AppDefaultViewLayout
     */
    public async initViewLayOutContainer() {
        this.viewLayoutPanel = this.viewInstance?.getPSViewLayoutPanel();
        if (this.viewLayoutPanel && this.viewLayoutPanel.viewProxyMode) {
            this.viewProxyMode = this.viewLayoutPanel.viewProxyMode;
        }
        // 初始化容器
        this.initUIContainerModel('VIEWLAYOUT', this.viewLayoutPanel);
        // 初始化基础数据
        if (this.viewProxyMode) {
            const parentRef: any = this.$parent;
            this.viewState = parentRef.viewState;
            this.viewtag = parentRef.viewtag;
            this.viewCodeName = parentRef.viewCodeName;
            this.engine = appEngineService.getEngine(this.viewInstance.viewType);
        }
        await this.initUIContainerBeforeCtx();
        this.initViewLayoutCtx();
        await this.initUIContainerAfterCtx();
        await this.initViewLayOut();
        // 初始化视图容器样式
        this.initRenderOptions();
        if (this.viewProxyMode) {
            setTimeout(() => {
                this.setContainerIsMounted();
            }, 0);
        }
    }

    /**
     * 初始化视图的绘制参数
     *
     * @memberof AppDefaultViewLayout
     */
    public initRenderOptions(opts: any = {}) {
        this.renderOptions = {};
        const { viewType, viewStyle, codeName } = this.viewInstance;
        const viewClassNames: any = {
            'view-container': true
        };
        if (viewType) {
            Object.assign(viewClassNames, { [viewType?.toLowerCase()]: true });
        }
        if (viewStyle) {
            Object.assign(viewClassNames, { [`view-style-${viewStyle.toLowerCase()}`]: true });
        } else {
            Object.assign(viewClassNames, { [`view-style-default`]: true });
        }
        if (codeName) {
            Object.assign(viewClassNames, { [Util.srfFilePath2(codeName)]: true });
        }
        if (this.viewInstance?.getPSSysCss?.()?.cssName) {
            Object.assign(viewClassNames, { [this.viewInstance.getPSSysCss()?.cssName]: true });
        }
        if (this.viewProxyMode) {
            Object.assign(viewClassNames, { 'isproxy': true });
        }
        Object.assign(viewClassNames, opts);
        this.$set(this.renderOptions, 'viewClassNames', viewClassNames);
    }

    /**
     * 初始化视图面板应用上下文、视图参数和ctx
     *
     * @memberof AppDefaultViewLayout
     */
    public initViewLayoutCtx() {
        const parentRef: any = this.$parent;
        // 处理应用上下文
        this.context = parentRef?.context ? parentRef.context : {};
        // 处理视图参数
        this.viewparams = parentRef?.viewparams ? parentRef.viewparams : {};
        if (this.viewProxyMode) {
            // 处理ctx
            const tempViewCtx = parentRef?.viewCtx ? parentRef?.viewCtx : {};
            tempViewCtx['view'] = this;
            // 顶层路由视图
            if (!Object.is(parentRef.viewDefaultUsage, 'INCLUDEDVIEW')) {
                if (AppServiceBase.getInstance() && AppServiceBase.getInstance().getAppStore()) {
                    AppServiceBase.getInstance().getAppStore().commit('addView', { tag: this.context.srfsessionid, param: this });
                }
                tempViewCtx['topview'] = this;
            }
            // 处理父级视图
            if (this.viewInstance && this.viewInstance.modelPath) {
                if (AppServiceBase.getInstance() && AppServiceBase.getInstance().getAppStore()) {
                    AppServiceBase.getInstance().getAppStore().commit('addView', { tag: this.viewInstance.modelPath, param: this });
                }
            }
            this.viewCtx = tempViewCtx;
        }
    }

    /**
     * 初始化视图布局
     *
     * @memberof AppDefaultViewLayout
     */
    public async initViewLayOut() {
        this.viewLayoutPanel = this.viewInstance?.getPSViewLayoutPanel();
        if (this.viewLayoutPanel && !this.viewLayoutPanel.useDefaultLayout) {
            await this.initDetailsModel(null, this.viewLayoutPanel?.getRootPSPanelItems());
            this.viewIsInit = true;
        } else {
            this.viewIsInit = true;
        }
    }

    /**
     * 容器挂载完成(重写)
     *
     * @memberof AppDefaultViewLayout
     */
    public containerMounted() {
        if (this.viewProxyMode) {
            const _this: any = this;
            super.containerMounted();
            this.$emit('view-event', { viewname: this.viewInstance.name, action: 'viewIsMounted', data: true })
            this.handleContainerPreEvent('onViewMounted').then((result: boolean) => {
                if (!result) {
                    return;
                }
                if (this.engine) {
                    this.engineInit();
                }
                this.$emit('view-event', { viewName: this.viewInstance.codeName, action: 'viewIsInited', data: null });
            })
        }
    }

    /**
     * 计算目标部件所需参数(重写)
     *
     * @memberof AppDefaultViewLayout
     */
    public computeTargetCtrlData(controlInstance: any, args?: any) {
        let { targetCtrlName, targetCtrlParam, targetCtrlEvent } = super.computeTargetCtrlData(controlInstance, args);
        Object.assign(targetCtrlParam.staticProps, { viewState: this.viewState, viewtag: this.viewtag, viewIsProxyMode: this.viewProxyMode });
        Object.assign(targetCtrlEvent, {
            closeView: ($event: any) => {
                this.$emit('view-event', { viewName: this.viewInstance.codeName, action: 'viewClosed', data: $event });
            }
        })
        return { targetCtrlName, targetCtrlParam, targetCtrlEvent };
    }

    /**
     * 执行挂载部件事件拦截(重写)
     *
     * @param {string} eventName 事件名称
     * @param {*} data 数据
     * @memberof ControlContainer
     */
    public exeMountedCtrlEvent(eventName: string, data: any) {
        // 识别导航区占位
        if (eventName && Object.is(eventName, 'selectionchange') && data && data.srfnavdata) {
            const navPos: any = Object.values(this.layoutDetailsModel).find((item: any) => {
                return item.panelItemModel.M?.getPSRawItem?.predefinedType === "NAV_POS";
            })
            if (navPos && navPos.setNavData instanceof Function) {
                navPos.setNavData(data.srfnavdata);
                this.$forceUpdate();
            }
        }
    }

    /**
     * 初始化面板成员模型
     *
     * @param {*} parentItem 父面板成员
     * @param {(IPSPanelItem[] | undefined | null)} [panelItems] 成员集合
     * @param {number} [dataIndex=0] 数据下标
     * @param {boolean} [hasMulParent=false] 是否存在父多数据容器父级成员
     * @memberof AppDefaultViewLayout
     */
    public async initDetailsModel(parentItem: any, panelItems?: IPSPanelItem[] | undefined | null, dataIndex: number = 0, hasMulParent: boolean = false) {
        if (panelItems && panelItems.length > 0) {
            //  父面板成员为多项数据容器时,构建多份子面板成员
            if (parentItem && parentItem.dataRegionType === 'MULTIDATA' && parentItem.getData()?.length > 0) {
                for (let index = 0; index <= parentItem.getData().length - 1; index++) {
                    await this.initDetailsModelItem(parentItem, panelItems, index, true);
                }
            } else {
                await this.initDetailsModelItem(parentItem, panelItems, dataIndex, hasMulParent);
            }
        }
    }

    /**
     * 初始化面板模型项
     *
     * @param {*} parentItem 父面板项
     * @param {(IPSPanelItem[] | undefined | null)} [panelItems] 面板项成员
     * @param {number} [index=0] 数据下标
     * @param {boolean} [hasMulParent=false] 是否存在父多数据容器父级成员
     * @memberof AppDefaultViewLayout
     */
    public async initDetailsModelItem(parentItem: any, panelItems?: IPSPanelItem[] | undefined | null, index: number = 0, hasMulParent: boolean = false) {
        if (panelItems && panelItems.length > 0) {
            for (let i = 0; i < panelItems.length; i++) {
                const panelItem: IPSPanelItem = panelItems[i];
                let detailModel: any = {
                    context: Util.deepCopy(this.context),
                    viewparams: Util.deepCopy(this.viewparams),
                    panel: this,
                    disabled: false,
                    name: panelItem.name,
                    caption: panelItem.caption,
                    itemType: panelItem.itemType,
                    visible: true,
                    model: panelItem,
                    parentItem: parentItem,
                    $index: index,
                    hasMulParent: hasMulParent
                };
                let panelItemModel: any;
                switch (panelItem.itemType) {
                    case 'BUTTON':
                        const panelButtomItem = panelItem as IPSSysPanelButton
                        Object.assign(detailModel, {
                            uiaction: {
                                type: panelButtomItem.getPSUIAction()?.uIActionType,
                                tag: panelButtomItem.getPSUIAction()?.uIActionTag,
                                actiontarget: panelButtomItem.getPSUIAction()?.actionTarget,
                                noprivdisplaymode: panelButtomItem.getPSUIAction()?.uIActionMode,
                                dataaccaction: panelButtomItem.getPSUIAction()?.dataAccessAction,
                                visible: true,
                                disabled: false
                            }
                        });
                        panelItemModel = new PanelButtonModel(detailModel);
                        break;
                    case 'TABPANEL':
                        const tabPages: IPSPanelTabPage[] = (panelItem as IPSPanelTabPanel).getPSPanelTabPages() || [];
                        const pageNames: any[] = [];
                        if (tabPages.length > 0) {
                            tabPages.forEach((page: IPSPanelTabPage) => {
                                pageNames.push({ name: page.name });
                            })
                        }
                        Object.assign(detailModel, {
                            tabPages: pageNames
                        });
                        panelItemModel = new PanelTabPanelModel(detailModel);
                        break;
                    case 'TABPAGE':
                        panelItemModel = new PanelTabPageModel(detailModel);
                        break;
                    case 'CONTAINER':
                        const dataRegionType = (panelItem as IPSPanelContainer).dataRegionType;
                        if (dataRegionType === 'MULTIDATA' || dataRegionType === 'SINGLEDATA') {
                            new ContainerLoadingService(hasMulParent ? `${panelItem.name}_${index}` : panelItem.name, this.layoutLoadingService);
                        }
                        panelItemModel = new PanelContainerModel(detailModel);
                        break;
                    case 'FIELD':
                        panelItemModel = new PanelFieldModel(detailModel);
                        break;
                    case 'RAWITEM':
                        panelItemModel = new PanelRawitemModel(detailModel);
                        break;
                    case 'CONTROL':
                        panelItemModel = new PanelControlModel(detailModel);
                        break;
                    case 'CTRLPOS':
                        panelItemModel = new PanelCtrlPosModel(detailModel);
                        break;
                    case 'USERCONTROL':
                        panelItemModel = new PanelUserControlModel(detailModel);
                        break;
                }
                await panelItemModel.loaded();
                // 设置面板模型 (父成员存在多数据容器时拼接下标)
                if (hasMulParent) {
                    this.$set(this.layoutDetailsModel, `${panelItem.name}_${index}`, panelItemModel);
                } else {
                    this.$set(this.layoutDetailsModel, panelItem.name, panelItemModel);
                }
                // 设置面板数据 (父成员存在多数据容器时拼接下标)
                if (hasMulParent) {
                    this.$set(this.layoutData, `${panelItem.name}_${index}`, this.layoutDetailsModel[`${panelItem.name}_${index}`].getData());
                } else {
                    this.$set(this.layoutData, panelItem.name, this.layoutDetailsModel[panelItem.name].getData());
                }
                if ((panelItem as any).getPSPanelItems?.()?.length > 0) {
                    await this.initDetailsModel(panelItemModel, (panelItem as any)?.getPSPanelItems?.(), index, hasMulParent);
                }
                if ((panelItem as any).getPSPanelTabPages?.()?.length > 0) {
                    await this.initDetailsModel(panelItemModel, (panelItem as any)?.getPSPanelTabPages?.(), index, hasMulParent);
                }
            }
        }
    }

    /**
     * Vue生命周期,实例销毁完成
     *
     * @memberof AppDefaultViewLayout
     */
    public destroyed() {
        if (this.viewProxyMode) {
            this.handleContainerPreEvent('onViewDestroyed').then((result: boolean) => {
                // 非嵌入模式下
                const parentRef: any = this.$parent;
                if (!Object.is(parentRef.viewDefaultUsage, 'INCLUDEDVIEW')) {
                    let localStoreLength = Object.keys(localStorage);
                    if (localStoreLength.length > 0) {
                        localStoreLength.forEach((item: string) => {
                            if (item.startsWith(this.context.srfsessionid)) {
                                localStorage.removeItem(item);
                            }
                        })
                    }
                    if (AppServiceBase.getInstance() && AppServiceBase.getInstance().getAppStore()) {
                        // 清除顶层路由参数
                        AppServiceBase.getInstance().getAppStore().commit('removeRouteViewGlobal', this.context.srfsessionid);
                        // 清除顶层视图
                        AppServiceBase.getInstance().getAppStore().commit('removeView', this.context.srfsessionid);
                    }
                }
            });
        }
        this.destroyUIContainer();
    }

    /**
     * 绘制头部内容
     * 
     * @memberof AppDefaultViewLayout
     */
    public renderViewHeader() {
        return [
            <ion-toolbar class="view-header__top">
                <div class="view-header__top__captionbar">
                    {this.$slots.captionbar}
                </div>
                {/*  不能额外加容器 否则影响布局 */}
                {this.$slots.mobnavrightmenu}
                {this.$slots.mobnavleftmenu}
            </ion-toolbar>,
            <div class="view-header__body">
                {this.$slots.quicksearch}
                {this.$slots.quickGroupSearch}
            </div>,
        ]

    }

    /**
     * 是否为嵌入视图视图
     * 
     * @memberof AppDefaultViewLayout
     */
    get isViewDefaultUsage() {
        const parentRef: any = this.$parent;
        return parentRef.viewDefaultUsage == 'INCLUDEDVIEW' ? true : false
    }

    /**
     * 是否为部件视图
     * 
     * @memberof AppDefaultViewLayout
     */
    get isEmbedView() {
        return this.viewInstance.viewType.indexOf('VIEW9') != -1
    }


    /**
     * 绘制视图标题
     * @param renderMode 文本绘制模式
     * @return {*}  {*}
     * @memberof AppDefaultViewLayout
     */
    public renderViewCaption(renderMode?: any): any {
        switch (renderMode) {
            case 'TEXT':
                return (this.viewInstance.showCaptionBar ? <span class='view-header__caption'>{this.viewInstance.caption ? this.viewInstance.caption : this.viewInstance.title}</span> : null);
            case 'HEADING1':
            case 'HEADING2':
            case 'HEADING3':
            case 'HEADING4':
            case 'HEADING5':
            case 'HEADING6':
                return this.$createElement(`h${renderMode.charAt(renderMode.length - 1)}`,
                    {},
                    this.viewInstance.caption ? this.viewInstance.caption : this.viewInstance.title
                );
            case 'PARAGRAPH':
                return this.viewInstance.showCaptionBar ? <p>{this.viewInstance.title}</p> : null
            default:
                return (this.viewInstance.showCaptionBar ? <span class='view-header__caption'>{this.viewInstance.caption ? this.viewInstance.caption : this.viewInstance.title}</span> : null);
        }
    }

    /**
     * 绘制视图内容
     * 
     * @memberof AppDefaultViewLayout
     */
    public renderViewContent() {
        return [
            this.$slots.topMessage || (this.$slots.searchForm) ? <div class="view-content__top">
                {this.$slots.topMessage}
            </div> : null,
            <div class="view-content__body">
                {this.$slots.bodyMessage}
                {this.$slots.default}
            </div>,
            this.$slots.bottomMessage ? <div class="view-content__bottom">
                {this.$slots.bottomMessage}
            </div> : null
        ]
    }

    /**
     * 绘制底部
     * 
     * @memberof AppDefaultViewLayout
     */
    public renderViewFooter() {
        return [
            this.$slots.mobbottommenu,
            this.$slots.footer,
        ]
    }

    /**
     * 绘制内容
     * 
     * @memberof AppDefaultViewLayout
     */
    public renderContent() {
        return [
            (this.showCaptionBar && !this.isEmbedView) ? <ion-header class='view-header'>
                {this.renderViewHeader()}
            </ion-header> : null,
            <div class='view-content'>
                {this.renderViewContent()}
            </div>,
            (this.$slots.footer || this.$slots.mobbottommenu) && (
                <ion-footer class="view-footer">
                    {this.renderViewFooter()}
                </ion-footer>
            )
        ];
    }

    /**
     * 绘制布局
     * 
     * @memberof AppDefaultViewLayout
     */
    public render(h: any): any {
        const { viewClassNames } = this.renderOptions;
        return (
            (this.isEmbedView || this.isViewDefaultUsage) ? <div class={viewClassNames}>
                {this.viewIsInit ? (this.viewLayoutPanel && this.viewLayoutPanel.useDefaultLayout) ? this.renderContent() : this.renderViewLayoutPanel() : this.renderInitLoading()}
            </div> :
                <ion-page className={viewClassNames}>
                    {this.viewIsInit ? (this.viewLayoutPanel && this.viewLayoutPanel.useDefaultLayout) ? this.renderContent() : this.renderViewLayoutPanel() : this.renderInitLoading()}
                </ion-page>
        );
    }

    /**
     * 渲染初始化loading效果
     *
     * @return {*} 
     * @memberof AppDefaultViewLayout
     */
    public renderInitLoading() {
        return <app-loading-mask maskElement={Util.srfFilePath2(this.viewInstance.codeName)}></app-loading-mask>
    }

    /**
     * 绘制视图布局面板
     *
     * @memberof AppDefaultViewLayout
     */
    public renderViewLayoutPanel() {
        if ((this.viewLayoutPanel as any)?.layoutBodyOnly) {
            return this.renderLayoutBodyOnly();
        } else {
            return this.renderRootPSPanelItems();
        }

    }

    /**
     * 绘制顶级面板成员集合
     *
     * @memberof AppDefaultViewLayout
     */
    public renderRootPSPanelItems() {
        let rootStyle = { height: '100%', width: '100%' };
        let layoutMode = this.viewLayoutPanel?.getPSLayout()?.layout;
        if (layoutMode && layoutMode == 'FLEX') {
            Object.assign(rootStyle, { 'display': 'flex', 'flex-direction': 'column' });
        } else {
            Object.assign(rootStyle, { overflow: 'auto' });
        }
        return this.viewLayoutPanel?.getRootPSPanelItems()?.map((container: any, index: number) => {
            return this.renderByDetailType(container);
        })
    }

    /**
    * 仅布局内容区模式绘制
    *
    * @memberof AppDefaultViewLayout
    */
    public renderLayoutBodyOnly() {
        return [(this.showCaptionBar && !this.isEmbedView && !this.isViewDefaultUsage) ? <ion-header>
            {!ThirdPartyService.getInstance().platform ? this.$slots.captionbar && !this.viewInstance.isPartsView ? this.$slots['layout-captionbar'] || this.$slots.captionbar : null : null}
            {this.$slots.toolbar}
            {this.$slots.quicksearch}
            {this.$slots.quickGroupSearch}
            {this.$slots.topMessage}
        </ion-header> : null,
        this.renderLayoutContent(),
        (this.$slots.mobbottommenu || this.$slots.footer || this.$slots.bottomMessage) ? <ion-footer class="view-footer">
            {this.$slots.mobbottommenu}
            {this.$slots.footer}
            {this.$slots.bottomMessage}
        </ion-footer> : null
        ];
    }

    /**
     * 绘制布局内容区
     *
     * @memberof AppDefaultViewLayout
     */
    public renderLayoutContent() {
        const content = [this.$slots.bodyMessage, this.renderRootPSPanelItems()]
        return <div class="view-content">
            {[...content]}
        </div>
    }


    /**
     * 根据detailType绘制对应detail
     *
     * @param {*} modelJson
     * @memberof AppDefaultViewLayout
     */
    public renderByDetailType(modelJson: any, parent?: any, index?: number) {
        if (modelJson.getPSSysPFPlugin()) {
            const pluginInstance: any = PluginService.getInstance().getPluginInstance("CONTROLITEM", modelJson.getPSSysPFPlugin().pluginCode);
            if (pluginInstance) {
                return pluginInstance.renderCtrlItem(this.$createElement, modelJson, this, this.context);
            }
        }
        switch (modelJson.itemType) {
            case 'CONTAINER':
                return this.renderContainer(modelJson, parent, index);
            case 'TABPANEL':
                return this.renderTabPanel(modelJson, parent, index);
            case 'TABPAGE':
                return this.renderTabPage(modelJson, index);
            case 'FIELD':
                return this.renderField(modelJson, index);
            case 'RAWITEM':
                return this.renderRawitem(modelJson, index);
            case 'BUTTON':
                return this.renderButton(modelJson, index);
            case 'CTRLPOS':
                return this.renderCtrlPos(modelJson, parent, index);
            case 'USERCONTROL':
                return this.renderUserControl(modelJson, parent, index);
            default:
                return <span>{`${modelJson.itemType} 类型未支持`}</span>
        }
    }

    /**
     * 绘制面板Container
     *
     * @memberof AppDefaultViewLayout
     */
    public renderContainer(container: IPSPanelContainer, parent?: any, index?: number) {
        const panelItems: IPSPanelItem[] = container.getPSPanelItems() || [];
        let name: string = container.name;
        //  父容器为多数据容器
        let hasMulParent: boolean = false;
        if (parent && parent.dataRegionType === 'MULTIDATA' && this.layoutDetailsModel[parent.name]?.getData()?.length > 0) {
            hasMulParent = true;
            name += `_${index}`;
        }
        if (!this.layoutDetailsModel[name]) {
            return null;
        }
        const layout = container.getPSLayout()?.layout;
        // 容器样式
        const detailStyle = {};
        // 获取布局设置(约束子,如:flex布局及相关设置)
        const boxLayoutStyle = this.layoutDetailsModel[name].getBoxLayoutStyle();
        Object.assign(detailStyle, boxLayoutStyle);
        // 获取盒子宽高/间隔模式
        const boxStyle = this.layoutDetailsModel[name].getBoxStyle();
        Object.assign(detailStyle, boxStyle);
        // 获取盒子样式表
        const detailClass = this.layoutDetailsModel[name]?.getDetailClass();

        if (layout && Object.is(layout, 'BORDER')) {
            return (
                <van-col style={detailStyle} class={[detailClass,'app-view-layout__container']} nativeOn={{ 'click': (event: any) => { this.handlePanelItemEvent(container.name, name, 'onclick', { hasMulParent, index, event }) } }} >
                    {container.dataRegionType === 'MULTIDATA' && this.layoutDetailsModel[name]?.getData()?.length > 0 ?
                        // this.layoutDetailsModel[name]?.getData().map((data: any, index: number) => {
                        //     return <app-scroll-container panelItems={panelItems}>{this.renderChildItems(container, panelItems, index)}</app-scroll-container>;
                        // }) 
                        <div>多数据容器下不能嵌入边缘布局容器</div> : hasMulParent ?
                            <app-scroll-container panelItems={panelItems}>{this.renderChildItems(container, panelItems, index)}</app-scroll-container> :
                            <app-scroll-container panelItems={panelItems}>{this.renderChildItems(container, panelItems)}</app-scroll-container>}
                </van-col>
            );
        } else if (layout && (Object.is(layout, 'FLEX'))) {
            //  存在三种情况(1:该容器为多数据容器; 2: 父容器为多数据容器; 3: 正常容器)
            return (
                <van-row style={container.showCaption ? "" : detailStyle} class={[detailClass,'app-view-layout__container']} nativeOn={{ 'click': (event: any) => { this.handlePanelItemEvent(container.name, name, 'onclick', { hasMulParent, index, event }) } }} >
                    {container.showCaption ? <div class="app-view-layout__container__header">
                        <span>{this.$tl(container.getCapPSLanguageRes?.()?.lanResTag, container.caption)}</span>
                    </div> : null}
                    {container.showCaption ? <div class="app-view-layout__container__content" style={detailStyle}>
                        {
                            container.dataRegionType === 'MULTIDATA' && this.layoutDetailsModel[name]?.getData()?.length > 0 ?
                                this.layoutDetailsModel[name]?.getData().map((data: any, index: number) => {
                                    return this.renderChildItems(container, panelItems, index);
                                }) : hasMulParent ? this.renderChildItems(container, panelItems, index) : this.renderChildItems(container, panelItems)
                        }
                    </div> : container.dataRegionType === 'MULTIDATA' && this.layoutDetailsModel[name]?.getData()?.length > 0 ?
                        this.layoutDetailsModel[name]?.getData().map((data: any, index: number) => {
                            return this.renderChildItems(container, panelItems, index);
                        }) : hasMulParent ? this.renderChildItems(container, panelItems, index) : this.renderChildItems(container, panelItems)}
                </van-row>
            );
        } else if (layout && Object.is(layout, 'SIMPLEFLEX')) {
            //  存在三种情况(1:该容器为多数据容器; 2: 父容器为多数据容器; 3: 正常容器)
            return (
                <van-row style={container.showCaption ? "" : detailStyle} class={[detailClass,'app-view-layout__container']}  nativeOn={{ 'click': (event: any) => { this.handlePanelItemEvent(container.name, name, 'onclick', { hasMulParent, index, event }) } }} >
                    {container.showCaption ? <div class="app-view-layout__container__header">
                        <span>{this.$tl(container.getCapPSLanguageRes?.()?.lanResTag, container.caption)}</span>
                    </div> : null}
                    {container.showCaption ? <div class="app-view-layout__container__content" style={detailStyle}>
                        {
                            container.dataRegionType === 'MULTIDATA' && this.layoutDetailsModel[name]?.getData()?.length > 0 ?
                                this.layoutDetailsModel[name]?.getData().map((data: any, index: number) => {
                                    return <app-simpleflex-container panelItems={panelItems} index={index} renderCallBack={this.renderByDetailType.bind(this)}></app-simpleflex-container>;
                                }) : hasMulParent ? <app-simpleflex-container panelItems={panelItems} index={index} renderCallBack={this.renderByDetailType.bind(this)}></app-simpleflex-container> : <app-simpleflex-container panelItems={panelItems} renderCallBack={this.renderByDetailType.bind(this)}></app-simpleflex-container>
                        }
                    </div> : container.dataRegionType === 'MULTIDATA' && this.layoutDetailsModel[name]?.getData()?.length > 0 ?
                        this.layoutDetailsModel[name]?.getData().map((data: any, index: number) => {
                            return <app-simpleflex-container panelItems={panelItems} index={index} renderCallBack={this.renderByDetailType.bind(this)}></app-simpleflex-container>
                        }) : hasMulParent ? <app-simpleflex-container panelItems={panelItems} index={index} renderCallBack={this.renderByDetailType.bind(this)}></app-simpleflex-container> : <app-simpleflex-container panelItems={panelItems} renderCallBack={this.renderByDetailType.bind(this)}></app-simpleflex-container>}
                </van-row>
            );
        } else {
            //  存在三种情况(1:该容器为多数据容器; 2: 父容器为多数据容器; 3: 正常容器)
            return (
                <van-row style={detailStyle} class={[detailClass,'app-view-layout__container']}  nativeOn={{ 'click': (event: any) => { this.handlePanelItemEvent(container.name, name, 'onclick', { hasMulParent, index, event }) } }} >
                    {container.showCaption ? <div class="app-view-layout__container__header">
                        <span>{this.$tl(container.getCapPSLanguageRes?.()?.lanResTag, container.caption)}</span>
                    </div> : null}
                    {container.dataRegionType === 'MULTIDATA' && this.layoutDetailsModel[name]?.getData()?.length > 0 ?
                        this.layoutDetailsModel[name]?.getData().map((data: any, index: number) => {
                            return this.renderChildItems(container, panelItems, index);
                        }) : hasMulParent ? this.renderChildItems(container, panelItems, index) : this.renderChildItems(container, panelItems)}
                </van-row>

            );
        }
    }

    /**
     * 绘制子容器
     *
     * @param {IPSPanelContainer} parent 父容器模型
     * @param {IPSPanelItem[]} panelItems 父容器下所有子项
     * @param {number} [index] 多数据域下标
     * @return {*} 
     * @memberof AppDefaultViewLayout
     */
    public renderChildItems(parent: IPSPanelContainer, panelItems: IPSPanelItem[], index?: number) {
        if (!parent || !panelItems || (panelItems.length === 0)) {
            return null;
        }
        const layout = parent.getPSLayout()?.layout;
        return panelItems.map((item: any) => {
            const name = `${item.name}${index === undefined || index === null ? '' : '_' + index}`;
            const childDetailStyle: any = {};
            if (Object.is(layout, 'BORDER')) {
                Object.assign(childDetailStyle, this.layoutDetailsModel[name]?.getBorderLayoutStyle());
            } else {
                Object.assign(childDetailStyle, this.layoutDetailsModel[name]?.getBoxLayoutPosStyle());
            }
            // 多数据容器下多数据部件只绘制一个
            if (this.layoutDetailsModel[name]?.isEnableMount === false) {
                return null;
            }
            if (Object.is(layout, 'BORDER')) {
                return (
                    <div style={childDetailStyle} slot={item.name} class={'app-view-layout__container__item'}>
                        {this.renderByDetailType(item, parent, index)}
                    </div>
                );
            } else if (Object.is(layout, 'FLEX')) {
                return (
                    <div style={childDetailStyle} class={'app-view-layout__container__item'} >
                        {this.renderByDetailType(item, parent, index)}
                    </div>
                );
            } else if (Object.is(layout, 'TABLE_12COL') || Object.is(layout, 'TABLE_24COL')) {
                const attrs = this.layoutDetailsModel[name]?.getGridLayoutProps(item, layout);
                return (
                    <van-col {...{ props: attrs.md }} style={childDetailStyle} class={'app-view-layout__container__item'}>
                        {this.renderByDetailType(item, parent, index)}
                    </van-col>
                );
            }
        })

    }

    /**
     * 绘制面板TabPanel
     *
     * @memberof AppDefaultViewLayout
     */
    public renderTabPanel(modelJson: IPSPanelTabPanel, parent?: any, index?: number) {
        const name: string = !this.layoutDetailsModel[`${modelJson.name}_${index}`] ? modelJson.name : `${modelJson.name}_${index}`;
        if (!this.layoutDetailsModel[name]) {
            return null;
        }
        const tabPages: IPSPanelTabPage[] = modelJson.getPSPanelTabPages() || [];
        const activedTabPage: any = this.layoutDetailsModel[name]?.activatedPage;
        const detailClass = this.layoutDetailsModel[name].getDetailClass();
        const detailStyle = this.layoutDetailsModel[name].getBoxStyle();
        return (
            <van-tabs
                type="card"
                animated={true}
                swipeable={true}
                scrollspy={true}
                value={activedTabPage}
                class={detailClass}
                style={parent ? {} : detailStyle}
                on-click={(event: any) => { this.handlePanelItemEvent(modelJson.name, name, 'onclick', { index, event }) }}
            >
                {tabPages.length > 0 ?
                    tabPages.map((item: IPSPanelTabPage) => {
                        return this.renderTabPage(item, index);
                    }) : null}
            </van-tabs>
        );
    }

    /**
     * 绘制面板TabPage
     *
     * @memberof AppDefaultViewLayout
     */

    public renderTabPage(modelJson: IPSPanelTabPage, index?: number) {
        const name: string = !this.layoutDetailsModel[`${modelJson.name}_${index}`] ? modelJson.name : `${modelJson.name}_${index}`;
        if (!this.layoutDetailsModel[name]) {
            return null;
        }
        const detailClass = this.layoutDetailsModel[name]?.getDetailClass();
        const label = this.$tl(modelJson.getCapPSLanguageRes?.()?.lanResTag, modelJson.caption);
        const panelItems: IPSPanelItem[] = modelJson.getPSPanelItems() || [];
        return (
            <van-tab title={label} name={modelJson.name} class={detailClass}>
                {this.renderChildItems(modelJson, panelItems, index)}
            </van-tab>
        );
    }

    /**
     * 绘制面板Field
     *
     * @memberof AppDefaultViewLayout
     */
    public renderField(modelJson: IPSSysPanelField, index?: number) {
        const { caption, hidden, showCaption } = modelJson;
        //  存在多份属性模型时根据下标获取对应 name
        const name: string = !this.layoutDetailsModel[`${modelJson.name}_${index}`] ? modelJson.name : `${modelJson.name}_${index}`;
        if (!this.layoutDetailsModel[name]) {
            return null;
        }
        const detailClass = this.layoutDetailsModel[name].getDetailClass();
        Object.assign(detailClass, { 'item-field': true });
        const detailStyle = this.layoutDetailsModel[name].getBoxStyle();
        const editor: any = modelJson.getPSEditor();
        const labelClass = {
            'item-field-label': true,
            [modelJson.getPSSysCss()?.cssName || '']: true
        }
        return (
            !hidden && (
                <div class={detailClass} style={detailStyle}>
                    {showCaption && caption ? <ion-label class={labelClass} >{caption}</ion-label> : null}
                    {editor && (
                        <app-default-editor
                            value={this.layoutData[name]}
                            editorInstance={editor}
                            containerComponent={this}
                            containerCtrl={this.viewInstance}
                            parentItem={modelJson}
                            contextData={this.layoutData}
                            context={this.context}
                            viewparams={this.viewparams}
                            disabled={false}
                            on-change={(event: any) => {
                                this.onValueChange(modelJson.name, event);
                            }}
                            on-enter={(event: any) => {
                                this.onEditorEnter(modelJson.name, event);
                            }}
                            on-leave={(event: any) => {
                                this.onEditorLeave(modelJson.name, event);
                            }}
                            on-error={(event: string) => {
                                this.onError(event);
                            }}
                        />
                    )}
                </div>
            )
        );
    }

    /**
     * 值变化
     *
     * @param {*} $event
     * @memberof AppDefaultViewLayout
     */
    public async onValueChange(tag: string, event: any) {
        const { name, value } = event;
        console.log(tag, 'change', value);
        const result = await this.handlePanelItemEvent(tag, name, 'onchange', { oldvalue: this.layoutData[name], value });
        if (result && result?.hasOwnProperty('srfret') && !result.srfret) {
            return;
        }
        this.layoutData[name] = value;
        if (this.layoutDetailsModel && this.layoutDetailsModel[name]) {
            this.layoutDetailsModel[name].setData(value);
        }
    }

    /**
     * 值获取焦点
     *
     * @param {*} $event
     * @memberof AppDefaultViewLayout
     */
    public async onEditorEnter(tag: string, event: any) {
        const { name, value } = event;
        console.log(tag, 'enter', value);
        const result = await this.handlePanelItemEvent(tag, name, 'onenter', { oldvalue: this.layoutData[name], value });
        if (result && result?.hasOwnProperty('srfret') && !result.srfret) {
            return;
        }
    }

    /**
     * 值失去焦点
     *
     * @param {*} $event
     * @memberof AppDefaultViewLayout
     */
    public async onEditorLeave(tag: string, event: any) {
        const { name, value } = event;
        console.log(tag, 'leave', value);
        const result = await this.handlePanelItemEvent(tag, name, 'onleave', { oldvalue: this.layoutData[name], value });
        if (result && result?.hasOwnProperty('srfret') && !result.srfret) {
            return;
        }
    }

    /**
     * 处理错误信息事件
     *
     * @param {*} $event
     * @memberof AppDefaultViewLayout
     */
    public onError(errorMsg: string) {
        let errorMsgItemName = '';
        Object.keys(this.layoutDetailsModel).forEach((key: string) => {
            if (this.layoutDetailsModel[key]?.itemType === 'FIELD' && this.layoutDetailsModel[key]?.isErrorMsgItem) {
                errorMsgItemName = this.layoutDetailsModel[key].name;
            }
        })
        if (errorMsgItemName) {
            this.onValueChange(errorMsgItemName, { name: errorMsgItemName, value: errorMsg });
            return;
        }
        this.$Notice.error(errorMsg);
    }

    /**
     * 绘制面板Rawitem
     *
     * @memberof AppDefaultViewLayout
     */
    public renderRawitem(modelJson: IPSPanelRawItem, index?: number) {
        const { contentType } = modelJson;
        const name: string = !this.layoutDetailsModel[`${modelJson.name}_${index}`] ? modelJson.name : `${modelJson.name}_${index}`;
        if (!this.layoutDetailsModel[name]) {
            return null;
        }
        const rawItemDetail = modelJson.M.getPSRawItem;
        if (rawItemDetail.predefinedType) {
            return this.renderPredefinedRawItem(name, modelJson, index);
        }
        const detailClass = this.layoutDetailsModel[name].getDetailClass();
        const detailStyle = this.layoutDetailsModel[name].getBoxStyle();
        const imageDetail = { imageClass: modelJson.getPSSysImage()?.cssClass, imagePath: modelJson.getPSSysImage()?.imagePath };
        const content = this.layoutData[name];
        return (
            <app-rawitem
                class={detailClass}
                style={detailStyle}
                context={this.context}
                viewparams={this.viewparams}
                contentType={contentType}
                rawItemDetail={rawItemDetail}
                imageDetail={imageDetail}
                content={content}
                nativeOn={{ 'click': (event: any) => { this.handlePanelItemEvent(modelJson.name, name, 'onclick', { index, event }) } }}
            >
            </app-rawitem>
        );
    }

    /**
     * 绘制预定义直接内容
     *
     * @param {string} name
     * @param {IPSPanelRawItem} modelJson
     * @param {number} [index]
     * @return {*} 
     * @memberof AppDefaultViewLayout
     */
    public renderPredefinedRawItem(name: string, modelJson: IPSPanelRawItem, index?: number) {
        const detailClass = this.layoutDetailsModel[name]?.getDetailClass();
        const detailStyle = this.layoutDetailsModel[name]?.getBoxStyle();
        const imageDetail = { imageClass: modelJson.getPSSysImage()?.cssClass, imagePath: modelJson.getPSSysImage()?.imagePath };
        return (
            <app-preset-rawitem
                key={name}
                class={detailClass}
                style={detailStyle}
                detailModel={this.layoutDetailsModel[name]}
                navData={this.layoutDetailsModel[name]?.getNavData()}
                context={this.context}
                viewparams={this.viewparams}
                rawItemDetail={modelJson.M.getPSRawItem}
                imageDetail={imageDetail}
                type={modelJson.M.getPSRawItem.predefinedType}
                nativeOn={{ 'click': (event: any) => { this.handlePanelItemEvent(modelJson.name, name, 'onclick', { index, event }) } }}
            ></app-preset-rawitem>
        )
    }


    /**
     * 绘制按钮
     *
     * @param {IPSPanelButton} modelJson
     * @return {*} 
     * @memberof AppDefaultViewLayout
     */
    public renderButton(modelJson: IPSPanelButton, index?: number) {
        const { caption, showCaption } = modelJson;
        const name: string = !this.layoutDetailsModel[`${modelJson.name}_${index}`] ? modelJson.name : `${modelJson.name}_${index}`;
        if (!this.layoutDetailsModel[name]) {
            return null;
        }
        const detailClass = this.layoutDetailsModel[name].getDetailClass();
        const detailStyle = this.layoutDetailsModel[name].getBoxStyle();
        if (modelJson?.M?.buttonCssStyle) {
            Object.assign(detailStyle, this.getContentStyle(modelJson?.M?.buttonCssStyle))
        }
        return (
            <app-mob-button
                id={name}
                modelJson={modelJson}
                style={detailStyle}
                text={showCaption ? caption : ''}
                disabled={this.layoutDetailsModel[name]?.disabled}
                class={detailClass}
                showDefaultIcon={false}
                on-click={(event: any) => {
                    this.handleButtonClick(modelJson.name, name, event);
                }}
            ></app-mob-button>
        );
    }

    /**
      * 处理按钮点击
      *
      * @memberof AppDefaultViewLayout
      */
    public async handleButtonClick(tag: string, name: string, event: any) {
        const data = this.layoutDetailsModel[name].getData() ? this.layoutDetailsModel[name].getData() : {};
        const result = await this.handlePanelItemEvent(tag, name, 'onclick', { value: data, event });
        if (result && result?.hasOwnProperty('srfret') && !result.srfret) {
            return;
        }
        AppViewLogicService.getInstance().executeViewLogic(`layoutpanel_${tag}_click`, event, this, data, (this.viewLayoutPanel as any)?.getPSAppViewLogics());
    }

    /**
     * 绘制控件占位
     *
     * @memberof AppDefaultViewLayout
     */
    public renderCtrlPos(modelJson: any, parent?: any, index?: any) {
        const tag = modelJson.name;
        const name: string = !this.layoutDetailsModel[`${modelJson.name}_${index}`] ? modelJson.name : `${modelJson.name}_${index}`;
        if (!this.layoutDetailsModel[name] || (this.layoutDetailsModel[name]?.isEnableMount === false)) {
            return null;
        }
        const detailClass = this.layoutDetailsModel[name].getDetailClass();
        const detailStyle = this.layoutDetailsModel[name].getBoxStyle();
        if (this.viewProxyMode) {
            const appControls = this.viewLayoutPanel?.getPSControls() as (IPSControl[] | null);
            const targetControl = ModelTool.findPSControlByName(tag, appControls);
            const args = { staticProps: { localSourceTag: this.layoutDetailsModel[name].dataSourceTag }, dynamicProps: { context: this.layoutDetailsModel[name].context } };
            if (targetControl) {
                return <div class={detailClass} style={detailStyle}>
                    {this.renderTargetControl(targetControl, false, args)}
                </div>
            }
        } else {
            return <div class={detailClass} style={detailStyle}>
                {this.$slots[`layout-${tag}`]}
            </div>
        }
    }

    /**
   * @description 获取按钮内容样式
   * @param {*} data
   * @return {*}
   */
    getContentStyle(data: any) {
        if (data) {
            const res = data.split('\n');
            const target: string[] = [];
            res.forEach((item: any) => {
                target.push(...item.split(';').filter((value: any) => value));
            });
            let btnstyle = target.filter((value: string) => {
                return value.split(':').length === 2;
            })
            let detail = {}
            btnstyle.forEach(item => {
                let obj = item.split(":")
                Object.assign(detail, { [obj[0]]: obj[1] })
            })
            return detail;
        }
    }

    /**
    * 绘制用户部件
    *
    * @param {*} modelJson 模型
    * @memberof AppDefaultViewLayout
    */
    public renderUserControl(modelJson: any, parent?: any, index?: any) {
        return (<app-user-control modelJson={modelJson} layoutData={this.layoutData} on-valueChange={(data: any) => this.onValueChange(modelJson.name, data)} />)
    }


    /**
     * 处理面板项事件
     *
     * @param {string} tag 标识
     * @param {string} name 项名称
     * @param {string} eventName 事件名称
     * @param {*} args 附加参数
     * @memberof AppDefaultViewLayout
     */
    public async handlePanelItemEvent(tag: string, name: string, eventName: string, args?: any) {
        const tempTag: string = `${tag.toLowerCase()}-${eventName.toLowerCase()}`;
        if (this.containerTriggerLogicMap.get(tempTag)) {
            const data = { value: this.layoutDetailsModel[name].getData(), data: this.layoutData };
            if (args && (Object.keys(args).length > 0)) {
                Object.assign(data, args);
            }
            const result = await this.containerTriggerLogicMap.get(tempTag).executeAsyncUILogic({ arg: { sender: this, navContext: this.context, navParam: this.viewparams, navData: this.navdatas, data: data, args: args }, utils: this.viewCtx, app: this.viewCtx.app, view: this });
            return result;
        }
    }
}