<#ibizinclude>
../../@MACRO/LANG_FUN.ftl
</#ibizinclude>
<#ibizinclude>
../@MACRO/CONTROL/LANGBASE.vue.ftl
</#ibizinclude>
<template>
<#if ctrl.render??>
${ctrl.render.code}
<#else>
    <div :class='calendarClass<#if ctrl.getPSSysCss?? && ctrl.getPSSysCss()??><#assign singleCss = ctrl.getPSSysCss()> ${singleCss.getCssName()}</#if>'>
      <context-menu-container>
<#if ctrl.getCalendarStyle?? && ctrl.getCalendarStyle() == 'TIMELINE'>
        <template v-if="events.length >0">
            <el-timeline>
            <el-timeline-item
                v-for="(item, index) in events"
                :key="item.title+index"
                :color="item.color"
                :timestamp="item.start" 
                placement="top">
                <context-menu :contextMenuStyle="{width: '100%'}" :data="item" :renderContent="renderContextMenu">
                    <el-card @click.native="onEventClick(item,true,$event)" :class="item.className">
                    <#if ctrl.getPSSysCalendarItems()?? >
                    <#list ctrl.getPSSysCalendarItems() as calendarItem>
                        <div v<#if calendarItem_index != 0>-else</#if>-if="<#if calendarItem.getPSLayoutPanel()??>true<#else>false</#if> && item.itemType == '${calendarItem.getItemType()}'">
                        <#if calendarItem.getPSLayoutPanel()??>
                        <#assign panel = calendarItem.getPSLayoutPanel()>
                        <@ibizindent blank=18>
                        ${P.getCtrlCode(panel, 'CONTROL.html').code}
                        </@ibizindent>
                        </#if>
                        </div>
                    </#list>
                        <div v-else>
                            <h4>{{item.title}}</h4>
                            <p>{{$t('app.calendar.from')}} {{item.start}} {{$t('app.calendar.to')}} {{item.end}}</p>
                        </div>
                    </#if>
                    </el-card>
                </context-menu>
            </el-timeline-item>
            </el-timeline>
        </template>
        <template v-else>
            <span class="app-data-empty">{{ $t('<#if langbase??>${langbase}.nodata</#if>') }}</span>
            <#if ctrl.getQuickPSDEToolbar?? && ctrl.getQuickPSDEToolbar()??>
            <span class="quick-toolbar">
                <#assign quickToolbar = ctrl.getQuickPSDEToolbar()/>
                <@ibizindent blank=12>
                ${P.getCtrlCode(quickToolbar, 'CONTROL.html').code}
                </@ibizindent>
            </span>
            </#if>
        </template>
<#else>
        <template>
        <div class="event-legends">
<#if ctrl.getPSSysCalendarItems()??>
  <#list ctrl.getPSSysCalendarItems() as calendarItem>
          <div :class="{'event-lengend':true, '${calendarItem.getItemType()}':true, 'event-disabled':!isShowlegend.${calendarItem.getItemType()}}" @click="legendTrigger('${calendarItem.getItemType()}')">
            <div class="lengend-icon" style="background:${calendarItem.getBKColor()};"></div>
            <span style="color:${calendarItem.getColor()};">${calendarItem.getName()}</span>
          </div>
  </#list>
</#if>
        </div>
        <FullCalendar
          ref="calendar"
          :locale="$i18n.locale"
          height="parent"
          :firstDay="1"
          :eventLimit="true"
          :editable="!isSelectFirstDefault && true"
          :buttonText="buttonText" 
          :header="header"
          :plugins="calendarPlugins"
          :events="searchEvents"
          :displayEventTime="displayEventTime"
          :customButtons="customButtons"
          :validRange="validRange"
          :defaultDate="defaultDate"
          :eventRender="eventRender"
        <#if ctrl.getQuickPSDEToolbar?? && ctrl.getQuickPSDEToolbar()??>
          :navLinks="true"
          :navLinkDayClick ="onDayClick"
        </#if>
          @dateClick="onDateClick"
          @eventClick="onEventClick"
          @eventDrop="onEventDrop"
          defaultView="dayGridMonth"/>
          <modal v-model="modalVisible" width="250px" :title="$t('app.calendar.dateSelectModalTitle')" class-name='date-select-modal' @on-ok="gotoDate">
            <el-date-picker style="width: 200px;" v-model="selectedGotoDate" type="date"></el-date-picker>
          </modal>
        </template>
</#if>
      </context-menu-container>
    <#if ctrl.getBatchPSDEToolbar?? && ctrl.getBatchPSDEToolbar()??>
    <span v-if="selections.length > 0" class="batch-toolbar">
      <#assign batchToolbar = ctrl.getBatchPSDEToolbar()/>
      <@ibizindent blank=12>
      ${P.getCtrlCode(batchToolbar, 'CONTROL.html').code}
      </@ibizindent>
    </span>
    </#if>
    </div>
</#if>
</template>
// 基于 @CONTROL/日历部件/CONTROL-BASE.vue.ftl 生成
<#assign import_block>
import FullCalendar from '@fullcalendar/vue'
import dayGridPlugin from '@fullcalendar/daygrid'
import timeGridPlugin from '@fullcalendar/timegrid';
import listPlugin from '@fullcalendar/list';
import interactionPlugin from '@fullcalendar/interaction';
import ContextMenu from '@components/context-menu/context-menu';
import UIService from '@/uiservice/ui-service';
</#assign>

<#assign component_block>
FullCalendar,
</#assign>

<#ibizinclude>
../@MACRO/CONTROL/CONTROL_HEADER-BASE.vue.ftl
</#ibizinclude>

    /**
     * 是否默认选中第一条数据
     *
     * @type {boolean}
     * @memberof ${srfclassname('${ctrl.codeName}')}Base
     */
    @Prop({ default: false }) public isSelectFirstDefault!: boolean;

    /**
     * 显示处理提示
     *
     * @type {boolean}
     * @memberof ${srfclassname('${ctrl.codeName}')}Base
     */
    @Prop({ default: true }) public showBusyIndicator?: boolean;

    /**
     * 部件行为--load
     *
     * @type {string}
     * @memberof ${srfclassname('${ctrl.codeName}')}Base
     */
    @Prop() public loadAction!: string;

<#if view.getPSAppViewLogics?? && view.getPSAppViewLogics()??>
  <#list view.getPSAppViewLogics() as logic>
    <#if logic.getPFLogicCodeType() == 'APP_NEWDATA'>
    /**
     * 打开新建数据视图
     *
     * @type {any}
     * @memberof ${srfclassname('${ctrl.codeName}')}Base
     */
    @Prop() public newdata: any;
    </#if>
    <#if logic.getPFLogicCodeType() == 'APP_OPENDATA'>
    /**
     * 打开编辑数据视图
     *
     * @type {any}
     * @memberof ${srfclassname('${ctrl.codeName}')}Base
     */
    @Prop() public opendata: any;
    </#if>
  </#list>
</#if>

    /**
     * 日历部件样式名
     *
     * @public
     * @type {any[]}
     * @memberof ${srfclassname('${ctrl.codeName}')}Base
     */
    public calendarClass: string = "calendar";

    /**
     * this引用
     *
     * @type {any}
     * @memberof ${srfclassname('${ctrl.codeName}')}Base
     */
    public thisRef: any = this;

    /**
     * 选中事件element元素
     *
     * @public
     * @type {any[]}
     * @memberof ${srfclassname('${ctrl.codeName}')}Base
     */
    public selectedEventElement:any;

    /**
     * 是否显示事件时也显示时间
     *
     * @public
     * @type {boolean}
     * @memberof ${srfclassname('${ctrl.codeName}')}Base
     */
    public displayEventTime: boolean = <#if ctrl.getCtrlParamNames?? && ctrl.getCtrlParamNames()??><#list ctrl.getCtrlParamNames() as ctrlparam><#if ctrlparam == 'NODISPLAYTIME'>false<#else>true</#if></#list><#else>true</#if>;

    /**
     * 引用插件集合
     *
     * @public
     * @type {any[]}
     * @memberof ${srfclassname('${ctrl.codeName}')}Base
     */
    public calendarPlugins: any[] = [
        dayGridPlugin, 
        timeGridPlugin, 
        listPlugin, 
        interactionPlugin
    ];

    /**
     * 设置头部显示
     *
     * @public
     * @type {}
     * @memberof ${srfclassname('${ctrl.codeName}')}Base
     */
    public header: any = {
        left: 'prev,next today gotoDate',
        center: 'title',
        right: 'dayGridMonth,timeGridWeek,timeGridDay,listWeek'
    };

    /**
     * 按钮文本集合
     *
     * @public
     * @type {}
     * @memberof ${srfclassname('${ctrl.codeName}')}Base
     */
    public buttonText: any = {
        today: '今天',
        month: '月',
        week: '周',
        day: '天',
        list: '列'
    };

    /**
     * 自定义按钮集合
     *
     * @public
     * @type {}
     * @memberof ${srfclassname('${ctrl.codeName}')}Base
     */
    public customButtons: any = {
        gotoDate: {
          text: "跳转",
          click: this.openDateSelect
        }
    };

    /**
     * 模态显示控制变量
     *
     * @public
     * @type boolean
     * @memberof ${srfclassname('${ctrl.codeName}')}Base
     */
    public modalVisible: boolean = false;

    /**
     * 跳转日期
     *
     * @public
     * @type Date
     * @memberof ${srfclassname('${ctrl.codeName}')}Base
     */
    public selectedGotoDate: Date = new Date();

    /**
     * 打开时间选择模态
     *
     * @public
     * @memberof ${srfclassname('${ctrl.codeName}')}Base
     */
    public openDateSelect(){
        this.modalVisible = true;
    }

    /**
     * 跳转到指定时间
     *
     * @public
     * @memberof ${srfclassname('${ctrl.codeName}')}Base
     */
    public gotoDate(){
        let appCalendar: any = this.$refs.calendar;
        let api = appCalendar.getApi();
        api.gotoDate(this.selectedGotoDate);
    }

    /**
     * 有效日期范围
     *
     * @public
     * @type {}
     * @memberof ${srfclassname('${ctrl.codeName}')}Base
     */
    public validRange: any = {
        start:"0000-01-01",
        end:"9999-12-31"
    };

    /**
     * 默认加载日期
     *
     * @public
     * @type {}
     * @memberof ${srfclassname('${ctrl.codeName}')}Base
     */
    public defaultDate: any = this.$util.dateFormat(new Date());

    /**
     * 设置按钮文本
     *
     * @public
     * @memberof ${srfclassname('${ctrl.codeName}')}Base
     */
    public setButtonText(){
        this.buttonText.today = this.$t('app.calendar.today'),
        this.buttonText.month = this.$t('app.calendar.month'),
        this.buttonText.week = this.$t('app.calendar.week'),
        this.buttonText.day = this.$t('app.calendar.day'),
        this.buttonText.list = this.$t('app.calendar.list')
        this.customButtons.gotoDate.text = this.$t('app.calendar.gotoDate')
    }

    /**
     * 监听语言变化
     *
     * @public
     * @memberof ${srfclassname('${ctrl.codeName}')}Base
     */
    @Watch('$i18n.locale')
    public onLocaleChange(newval: any, val: any) {
        this.setButtonText();
    }

    /**
     * 日程事件集合
     *
     * @public
     * @type {any[]}
     * @memberof ${srfclassname('${ctrl.codeName}')}Base
     */
    public events: any[] = [];

    /**
     * 日历项上下文菜单集合
     *
     * @type {string[]}
     * @memberof ${srfclassname('${ctrl.codeName}')}Base
     */
     public actionModel: any = {
        <#if ctrl.getPSControls()??>
            <#list ctrl.getPSControls() as childCtrl>
                <#if childCtrl.getControlType() == "CONTEXTMENU">
                    <#if childCtrl.getPSDEToolbarItems()??>
                        <#list childCtrl.getPSDEToolbarItems() as item>
        ${childCtrl.getOwner().getItemType()}_${item.name}: {name:'${item.name}',nodeOwner:'${childCtrl.getOwner().getItemType()}',<#if item.getPSUIAction?? && item.getPSUIAction()??><#assign uiaction=item.getPSUIAction()>type: '${uiaction.getUIActionType()}', tag: '${uiaction.getUIActionTag()}'<#if (uiaction.getActionTarget()!="")>, actiontarget: '${uiaction.getActionTarget()}'</#if><#if uiaction.getNoPrivDisplayMode(view)??>, noprivdisplaymode:${uiaction.getNoPrivDisplayMode(view)}</#if><#if uiaction.getDataAccessAction()??>, dataaccaction:'${uiaction.getDataAccessAction()}'</#if>, visabled: true, disabled: false</#if>},
                        </#list> 
                    </#if>
                </#if>
            </#list>
        </#if>
    }

    /**
     * 备份日历项上下文菜单
     *
     * @type {string[]}
     * @memberof ${srfclassname('${ctrl.codeName}')}Base
     */
     public copyActionModel: any;

    /**
     * 日历样式类型
     *
     * @public
     * @type {string}
     * @memberof ${srfclassname('${ctrl.codeName}')}Base
     */
    public calendarType: string = "${ctrl.getCalendarStyle()}";

    /**
     * 图例显示控制
     *
     * @public
     * @type {any}
     * @memberof ${srfclassname('${ctrl.codeName}')}Base
     */
    public isShowlegend: any = {
<#if ctrl.getPSSysCalendarItems()??>
  <#list ctrl.getPSSysCalendarItems() as calendarItem>
        ${calendarItem.getItemType()}:true,
  </#list>
</#if>
    };

    /**
     * 图例点击事件
     *
     * @public
     * @memberof ${srfclassname('${ctrl.codeName}')}Base
     */
    legendTrigger(itemType:string){
        this.isShowlegend[itemType] = !this.isShowlegend[itemType];
        this.refresh();
    }

    /**
     * 查询参数缓存
     *
     * @public
     * @type {any}
     * @memberof ${srfclassname('${ctrl.codeName}')}Base
     */
    public searchArgCache: any = {};

<#if ctrl.getPSSysCalendarItems()?? >
    <#assign itemPanel = false />
    <#list ctrl.getPSSysCalendarItems() as calendarItem>
        <#if calendarItem.getPSLayoutPanel()??>
        <#assign itemPanel = true />
        </#if>
    </#list>
    <#if itemPanel>
    /**
     * 面板数据变化处理事件
     * @param {any} item 当前数据
     * @param {any} $event 面板事件数据
     *
     * @memberof ${srfclassname('${ctrl.codeName}')}Base
     */
    public onPanelDataChange(item:any,$event:any) {
        Object.assign(item, $event, {rowDataState:'update'});
    }
    </#if>
</#if>

    /**
     * 搜索获取日程事件
     *
     * @param {*} $event 日期信息
     * @memberof ${srfclassname('${ctrl.codeName}')}Base
     */
    public searchEvents(fetchInfo?:any, successCallback?:any, failureCallback?:any ) {
        // 处理请求参数
        let start = (fetchInfo && fetchInfo.start) ? this.$util.dateFormat(fetchInfo.start) : null;
        let end = (fetchInfo && fetchInfo.end) ? this.$util.dateFormat(fetchInfo.end) : null;
        let arg = { start: start, end: end };
        if(fetchInfo && fetchInfo.query){
            Object.assign(arg,{query : fetchInfo.query});
        }
        const parentdata: any = {};
        this.$emit('beforeload', parentdata);
        Object.assign(arg, parentdata);
        let tempViewParams: any = parentdata.viewparams ? parentdata.viewparams : {};
        Object.assign(tempViewParams, JSON.parse(JSON.stringify(this.viewparams)));
        Object.assign(arg, { viewparams: tempViewParams });
        // 处理events数据
        let _this = this;
        let handleEvents = () => {
            if(_this.isSelectFirstDefault){
                // 模拟$event数据
                let tempEvent = JSON.parse(JSON.stringify(_this.events.length > 0?_this.events[0]:{}));
                _this.onEventClick(tempEvent,true);
                if(_this.events.length > 0){
                    _this.events[0].className = "select-first-event";
                }
                _this.calendarClass = "calendar select-first-calendar";
            }
            let filterEvents = this.events.filter((event:any)=>{
                return _this.isShowlegend[event.itemType];
            });

            if(successCallback){
                successCallback(filterEvents);
            }
            // 刷新日历的大小(仅fullcalendar组件使用)
            if(!Object.is(_this.calendarType,"TIMELINE")){
                let appCalendar: any = _this.$refs.calendar;
                let api = appCalendar.getApi();
                api.updateSize();
            }
        }
        if (JSON.stringify(arg) === JSON.stringify(this.searchArgCache)) {
            handleEvents();
            return;
        } else {
            this.searchArgCache = arg;
        }
        this.handleCtrlEvents('onbeforeload', { viewparams: arg }).then((beforeLoadRes: boolean) => {
            if (!beforeLoadRes) {
                return;
            }
            const post: Promise<any> = this.service.search(this.loadAction, JSON.parse(JSON.stringify(this.context)), arg, this.showBusyIndicator);
            post.then((response: any) => {
                if (!response || response.status !== 200) {
                    this.handleCtrlEvents('onloaderror', { viewparams: arg }).then((loadErrorRes: boolean) => {
                        if (!loadErrorRes) {
                            return;
                        }
                        if (response.data && response.data.message) {
                            this.$Notice.error({ title: (this.$t('app.commonWords.wrong') as string), desc: response.data.message });
                        }
                    });
                    return;
                }
                this.handleCtrlEvents('onloadsuccess', { data: response.data }).then((loadSuccessRes: boolean) => {
                    if (!loadSuccessRes) {
                        return;
                    }
                    // 默认选中第一项
                    this.events = response.data;
                    handleEvents();
                })
            }, (response: any) => {
                this.handleCtrlEvents('onloaderror', { viewparams: arg }).then((loadErrorRes: boolean) => {
                    if (!loadErrorRes) {
                        return;
                    }
                    if (response && response.status === 401) {
                        return;
                    }
                    this.$Notice.error({ title: (this.$t('app.commonWords.wrong') as string), desc: response.data && response.data.message ? response.data.message : "" });
                });
            });
        })
    }

    /**
     * 日期点击事件
     *
     * @param {*} $event 日期信息
     * @memberof ${srfclassname('${ctrl.codeName}')}Base
     */
    public onDateClick($event: any) {
        let date = $event.date;
        let datestr = $event.dateStr;
    }

    /**
     * 获取编辑视图信息
     *
     * @param {*} $event 事件信息
     * @memberof ${srfclassname('${ctrl.codeName}')}Base
     */
    public getEditView(deName: string) {
        let view: any = {};
        switch(deName){
<#if view.getAllRelatedPSAppViews?? && view.getAllRelatedPSAppViews()??>
  <#list view.getAllRelatedPSAppViews() as editview>
            case "${editview.getPSAppDataEntity().getCodeName()?lower_case}": 
                view = {
                    viewname: '${srffilepath2(editview.getCodeName())}', 
                    height: ${editview.getHeight()?c}, 
                    width: ${editview.getWidth()?c},
                    title: this.<@getViewLanguageTitle editview />,
                    placement: '${editview.getOpenMode()}',
                    deResParameters: <#rt>
    <#if editview.isPSDEView()>
      [<#t>
      <#if editview.getPSAppDERSPathCount() gt 0>
        <#list editview.getPSAppDERSPath(editview.getPSAppDERSPathCount() - 1) as deRSPath>
        <#assign majorPSAppDataEntity = deRSPath.getMajorPSAppDataEntity()/><#t>
          { pathName: '${srfpluralize(majorPSAppDataEntity.codeName)?lower_case}', parameterName: '${majorPSAppDataEntity.getCodeName()?lower_case}' }, <#t>
        </#list>
      </#if>
      ],<#lt>
    <#else>
      [],<#lt>
    </#if>
                    parameters: <#rt>
    [<#t>
    <#if editview.isPSDEView()>
      <#assign appDataEntity = editview.getPSAppDataEntity()/>
      { pathName: '${srfpluralize(appDataEntity.codeName)?lower_case}', parameterName: '${appDataEntity.getCodeName()?lower_case}' }, <#t>
      { pathName: '${editview.getPSDEViewCodeName()?lower_case}', parameterName: '${editview.getPSDEViewCodeName()?lower_case}' } <#t>
    <#else>
      { pathName: '${editview.getCodeName()?lower_case}', parameterName: '${editview.getCodeName()?lower_case}' } <#t>
    </#if>
    ],<#lt>
                };
                break;
  </#list>
</#if>
        }
        return view;
    }

    /**
     * 日程点击事件
     *
     * @param {*} $event calendar事件对象或event数据
     * @param {*} isOriginData true:$event是原始event数据,false:是组件
     * @param {*} $event timeline事件对象
     * @memberof ${srfclassname('${ctrl.codeName}')}Base
     */
    public onEventClick($event: any, isOriginData:boolean = false, $event2?: any) {
        this.handleCtrlEvents('onselectionchange', { data: $event }).then((res: boolean) => {
            if (!res) {
                return;
            }
            // 处理event数据
            let event: any = {};
            if(isOriginData){
                event = JSON.parse(JSON.stringify($event));
            }else{
                event = Object.assign({title: $event.event.title, start: $event.event.start, end: $event.event.end}, $event.event.extendedProps);
            }
            // 点击选中样式
            let JSelement:any = null;
            if(!isOriginData && $event.el){
                JSelement = $event.el;
            }else if(isOriginData && $event2 && $event2.currentTarget){
                JSelement = $event2.currentTarget;
            }
            if(JSelement){
                this.calendarClass = "calendar";
                if(this.selectedEventElement){
                    this.selectedEventElement.classList.remove("selected-event");
                }
                this.selectedEventElement = JSelement;
                this.selectedEventElement.classList.add("selected-event");
            }
            // 处理上下文数据
            let _this = this;
            let view: any = {};
            let _context: any = Object.assign({},this.context);
            let _viewparams:any = Object.assign({start:event.start,end:event.end},this.viewparams);
            switch(event.itemType) {
<#if ctrl.getPSSysCalendarItems()??>
    <#list ctrl.getPSSysCalendarItems() as calendarItem>
        <#if calendarItem.getPSAppDataEntity()??>
        <#assign _appde = calendarItem.getPSAppDataEntity() />
                case "${calendarItem.getItemType()}":
                    _context.${_appde.getCodeName()?lower_case} = event.${_appde.getCodeName()?lower_case};
                    view = this.getEditView("${_appde.getCodeName()?lower_case}");
                    break;
        </#if>
    </#list>
</#if>
            }
            this.selections = [event];
            // 导航栏中不需要打开视图,只要抛出选中数据
            if(this.isSelectFirstDefault){
                this.$emit("selectionchange",this.selections);
                return;
            }
            // 根据打开模式打开视图
            if(!view.viewname){
                return;
            } else if (Object.is(view.placement, 'INDEXVIEWTAB') || Object.is(view.placement, '')) {
                const routePath = this.$viewTool.buildUpRoutePath(this.$route, this.context, view.deResParameters, view.parameters, [JSON.parse(JSON.stringify(_context))] , _viewparams);
                this.$router.push(routePath);
            } else {
                let container: Subject<any> = new Subject();
                if (Object.is(view.placement, 'POPOVER')) {
                    container = this.$apppopover.openPop(isOriginData ? $event2 : $event.jsEvent, view,JSON.parse(JSON.stringify(_context)), _viewparams);
                } else if (Object.is(view.placement, 'POPUPMODAL')) {
                    container = this.$appmodal.openModal(view,  JSON.parse(JSON.stringify(_context)), _viewparams);
                } else if (view.placement.startsWith('DRAWER')) {
                    container = this.$appdrawer.openDrawer(view,  JSON.parse(JSON.stringify(_context)),  _viewparams);
                }
                container.subscribe((result: any) => {
                    if (!result || !Object.is(result.ret, 'OK')) {
                        return;
                    }
                    // 刷新日历
                    _this.refresh();
                });
            }
        })

    }

    /**
     * 日历刷新
     *
     * @memberof ${srfclassname('${ctrl.codeName}')}Base
     */
    public refresh(args?:any) {
        if(Object.is(this.calendarType,"TIMELINE")){
            this.searchEvents();
        } else {
            let calendarApi = (this.$refs.calendar as any).getApi();
            calendarApi.refetchEvents();
        }
    }

    /**
     * 日程拖动事件
     *
     * @param {*} $event 事件信息
     * @memberof ${srfclassname('${ctrl.codeName}')}Base
     */
    public onEventDrop($event: any) {
        if(this.isSelectFirstDefault){
          return;
        }
        let arg: any = {};
        let _context: any = Object.assign({},this.context);
        arg.start = this.$util.dateFormat($event.event.start);
        arg.end = this.$util.dateFormat($event.event.end);
        let itemType = $event.event._def.extendedProps.itemType;
        switch(itemType) {
<#if ctrl.getPSSysCalendarItems()??>
  <#list ctrl.getPSSysCalendarItems() as calendarItem>
    <#if calendarItem.getPSAppDataEntity()??>
      <#assign _appde = calendarItem.getPSAppDataEntity() />
            case "${calendarItem.getItemType()}":
                arg.${_appde.getCodeName()?lower_case} = $event.event._def.extendedProps.${_appde.getCodeName()?lower_case};
                _context.${_appde.getCodeName()?lower_case} = $event.event._def.extendedProps.${_appde.getCodeName()?lower_case};
                break;
    </#if>
  </#list>
</#if>
        }
        Object.assign(arg, { viewparams: this.viewparams} );
        this.handleCtrlEvents('onbeforedrop', { viewparams: arg }).then((beforeDropRes: boolean) => {
            if (!beforeDropRes) {
                return;
            }
            const post: Promise<any> = this.service.update(itemType, JSON.parse(JSON.stringify(_context)), arg, this.showBusyIndicator);
            post.then((response: any) => {
                if (!response || response.status !== 200) {
                    this.handleCtrlEvents('ondroperror', { data: response && response.data ? response.data : [] }).then((res: boolean) => {
                        if (!res) {
                            return;
                        }
                        if (response.data && response.data.message) {
                            this.$Notice.error({ title: (this.$t('app.commonWords.wrong') as string), desc: response.data.message });
                        }
                        return;
                    })
                }
                this.handleCtrlEvents('ondropsuccess', { data: response.data }).then((res: boolean) => {
                    if (!res) {
                        return;
                    }
                })
            }, (response: any) => {
                this.handleCtrlEvents('ondroperror', { data: response && response.data ? response.data : [] }).then((res: boolean) => {
                    if (!res) {
                        return;
                    }
                    if (response && response.status === 401) {
                        return;
                    }
                    this.$Notice.error({ title: (this.$t('app.commonWords.wrong') as string), desc: response.data && response.data.message ? response.data.message : "" });
                })
            })
        });
    }

    /**
     * 选中的数据
     *
     * @returns {any[]}
     * @memberof ${srfclassname('${ctrl.codeName}')}Base
     */
    public selections: any[] = [];

    /**
     * 应用状态事件
     *
     * @public
     * @type {(Subscription | undefined)}
     * @memberof ${srfclassname('${ctrl.codeName}')}Base
     */
    public appStateEvent: Subscription | undefined;

    /**
     * 获取多项数据
     *
     * @returns {any[]}
     * @memberof ${srfclassname('${ctrl.codeName}')}Base
     */
    public getDatas(): any[] {
        return this.selections;
    }

    /**
     * 获取单项数据
     *
     * @returns {*}
     * @memberof ${srfclassname('${ctrl.codeName}')}Base
     */
    public getData(): any {
        return null;
    }
             
    /**
     * vue 生命周期
     *
     * @returns
     * @memberof ${srfclassname('${ctrl.codeName}')}Base
     */
    public created() {
<#if ctrl.getCalendarStyle?? && ctrl.getCalendarStyle() == 'TIMELINE'>
        this.searchEvents();
<#else>
        this.setButtonText();
</#if>
        this.afterCreated();
    }

    /**
     * 执行created后的逻辑
     *
     *  @memberof ${srfclassname('${ctrl.codeName}')}Base
     */    
    public afterCreated(){
        if (this.viewState) {
            this.viewStateEvent = this.viewState.subscribe(({ tag, action, data }) => {
                if (!Object.is(tag, this.name)) {
                    return;
                }
            });
        }
        if(AppCenterService && AppCenterService.getMessageCenter()){
            this.appStateEvent = AppCenterService.getMessageCenter().subscribe(({ name, action, data }) =>{
                if(!Object.is(name,"${ctrl.getPSAppDataEntity().getCodeName()}")){
                    return;
                }
                if(Object.is(action,'appRefresh')){
                    this.refresh();
                }
            })
        }
    }


    /**
     * vue 生命周期
     *
     * @memberof ${srfclassname('${ctrl.codeName}')}Base
     */
    public mounted(){
        this.afterMounted();
    }

    /**
     * 执行mounted后的逻辑
     *
     * @memberof ${srfclassname('${ctrl.codeName}')}Base
     */
    public afterMounted(){
        let appCalendar: any = this.$refs.calendar;
        if(appCalendar){
            let api = appCalendar.getApi();
            api.updateSize()
        }
    }

    /**
     * vue 生命周期
     *
     * @memberof ${srfclassname('${ctrl.codeName}')}Base
     */
    public destroyed() {
        this.afterDestroy();
    }

    /**
     * 执行destroyed后的逻辑
     *
     * @memberof ${srfclassname('${ctrl.codeName}')}Base
     */
    public afterDestroy() {
        if (this.viewStateEvent) {
            this.viewStateEvent.unsubscribe();
        }
        if(this.appStateEvent){
            this.appStateEvent.unsubscribe();
        }
        <#if destroyed_block??>
        ${destroyed_block}
        </#if>       
    }

    <#if ctrl.getQuickPSDEToolbar?? && ctrl.getQuickPSDEToolbar()??>
      <#assign quickToolbar = ctrl.getQuickPSDEToolbar()/>
      ${P.getCtrlCode(quickToolbar, 'CONTROL.vue').code}
    </#if>

    <#if ctrl.getBatchPSDEToolbar?? && ctrl.getBatchPSDEToolbar()??>
      <#assign batchToolbar = ctrl.getBatchPSDEToolbar()/>
      ${P.getCtrlCode(batchToolbar, 'CONTROL.vue').code}
    </#if>

    /**
     * 计算节点右键权限
     *
     * @param {*} data 日历项数据
     * @param {*} appEntityName 应用实体名称  
     * @returns
     * @memberof ${srfclassname('${ctrl.codeName}')}Base
     */
    public async computeNodeState(data:any,appEntityName:string) {
        let service:any = await this.appEntityService.getService(appEntityName);
        if(this.copyActionModel && Object.keys(this.copyActionModel).length > 0) {
            if(service['Get'] && service['Get'] instanceof Function){
                let tempContext:any = Util.deepCopy(this.context);
                tempContext[appEntityName] = data[appEntityName];
                let targetData = await service.Get(tempContext,{}, false);
                let uiservice:any = await new UIService().getService(appEntityName);
                let result: any[] = ViewTool.calcActionItemAuthState(targetData.data,this.copyActionModel,uiservice);
                return this.copyActionModel;
            }else{
                console.warn("获取数据异常");
                return this.copyActionModel;
            }
        }
    }

    /**
     * 事件绘制回调
     *
     * @param {*} info 信息
     * @memberof ${srfclassname('${ctrl.codeName}')}Base
     */
    public eventRender(info?:any,) {
        let data = Object.assign({title: info.event.title, start: info.event.start, end: info.event.end}, info.event.extendedProps);
        info.el.addEventListener('contextmenu', (event: MouseEvent) => {
            this.copyActionModel = {};
            Object.values(this.actionModel).forEach((item:any) =>{
                if(Object.is(item.nodeOwner,data.itemType)){
                    this.copyActionModel[item.name] = item;
                }
            })
            if(Object.keys(this.copyActionModel).length === 0){
                return;
            }
            let dataMapping:any ={<#if ctrl.getPSSysCalendarItems()??><#list ctrl.getPSSysCalendarItems() as calendarItem>'${calendarItem.getItemType()}':'${calendarItem.getPSAppDataEntity().getCodeName()?lower_case}'<#if calendarItem_has_next>,</#if></#list></#if>};
            this.computeNodeState(data,dataMapping[data.itemType]).then((result:any) => {
                let flag:boolean = false;
                if(Object.values(result).length>0){
                    flag =Object.values(result).some((item:any) =>{
                        return item.visabled === true;
                    })
                }
                if(flag){
                    let props = { data: data, renderContent: this.renderContextMenu };
                    let component = ContextMenu;
                    const vm:any = new Vue({
                        render(h) {
                            return h(component, { props });
                        }
                    }).$mount();
                    document.body.appendChild(vm.$el);
                    const comp: any = vm.$children[0];
                    comp.showContextMenu(event.clientX, event.clientY);
                }
            });
        });
    }

    /**
     * 绘制右键菜单
     *
     * @param {*} event
     * @returns
     * @memberof ${srfclassname('${ctrl.codeName}')}Base
     */
    public renderContextMenu(event: any) {
        let content;
        if (event && event.itemType) {
            const data: any = JSON.parse(JSON.stringify(event));
            this.selections = [event];
            switch(event.itemType){
<#if ctrl.getPSControls()??>
<#list ctrl.getPSControls() as childCtrl>
<#if childCtrl.getControlType() == "CONTEXTMENU">
            case "${childCtrl.getOwner().getItemType()}":
                content = this.renderContextMenu${srfclassname(childCtrl.getOwner().getItemType()?lower_case)}();
                break;
</#if>
</#list>
</#if>
            }
        }
        return content;
    }
<#if ctrl.getPSControls()??>
<#list ctrl.getPSControls() as childCtrl>
<#if childCtrl.getControlType() == "CONTEXTMENU">

    /**
     * 绘制${childCtrl.getOwner().getItemType()}类型右键菜单
     *
     * @returns
     * @memberof ${srfclassname('${ctrl.codeName}')}Base
     */
    public renderContextMenu${srfclassname(childCtrl.getOwner().getItemType()?lower_case)}() {
        return (
          <@ibizindent blank=12>
          ${P.getCtrlCode(childCtrl, 'CONTROL.html').code}
          </@ibizindent>
        );
    }
</#if>
</#list>
</#if>

<#if ctrl.getQuickPSDEToolbar?? && ctrl.getQuickPSDEToolbar()??>

<#if ctrl.getQuickPSDEToolbar().getCodeName?? && ctrl.getQuickPSDEToolbar().getCodeName()??>
  <#assign ModelsName>${ctrl.getQuickPSDEToolbar().getCodeName()?lower_case}Models</#assign>
<#else>
  <#assign ModelsName = 'toolBarModels' />
</#if>

<#assign heightIndex = 0>
<#if ctrl.getQuickPSDEToolbar().getPSDEToolbarItems?? && ctrl.getQuickPSDEToolbar().getPSDEToolbarItems()??>
    <#list ctrl.getQuickPSDEToolbar().getPSDEToolbarItems() as item>
      <#if item.getItemType()?? && item.getItemType() == 'DEUIACTION' && item.getPSUIAction?? && item.getPSUIAction()??>
        <#assign heightIndex += 1>
      </#if>
    </#list>
</#if>
    /**
     * 时间点击
     *
     * @param {*} $event 当前时间
     * @param {*} jsEvent 原生事件对象  
     * @returns
     * @memberof ${srfclassname('${ctrl.codeName}')}Base
     */
    public onDayClick($event: any, jsEvent: any) {
        let content: any = this.renderBarMenu;
        const height = ${heightIndex} * 34;
        const container = this.$apppopover.openPopover(jsEvent, content, "left-end", true, 103, height);
    }

    /**
     * 绘制快速工具栏项
     * 
     * @returns
     * @memberof ${srfclassname('${ctrl.codeName}')}Base
     */
    public renderBarMenu() {
        return (
            <div id="calendar-popover">
                <dropdown class="tree-right-menu" trigger="custom" visible={true} on-on-click={($event: any) => this.${ctrl.getQuickPSDEToolbar().getName()}_click({tag: $event})}>
                    <dropdown-menu slot="list">
                    <#if ctrl.getQuickPSDEToolbar().getPSDEToolbarItems?? && ctrl.getQuickPSDEToolbar().getPSDEToolbarItems()??>
                        <#list ctrl.getQuickPSDEToolbar().getPSDEToolbarItems() as item>
                        <#if item.getItemType()?? && item.getItemType() == 'DEUIACTION' && item.getPSUIAction?? && item.getPSUIAction()??>
                        <dropdown-item name="${item.name}" v-show={this.${ModelsName}.${item.getName()?lower_case}.visabled} disabled={this.${ModelsName}.${item.getName()?lower_case}.disabled}>
                            <#if item.isShowIcon()><#if item.getPSSysImage()??><#assign img=item.getPSSysImage()><i class="<#if img.getCssClass()?? && (img.getCssClass()?length gt 0)>${img.getCssClass()}</#if>"></i></#if></#if>
                            <#if item.isShowCaption()>${item.getCaption()}</#if>
                        </dropdown-item>
                        </#if>
                        </#list>
                    </#if>
                    </dropdown-menu>
                </dropdown>
            </div>
        )
    }
</#if>
<#ibizinclude>
../@MACRO/CONTROL/CONTROL_BOTTOM-BASE.vue.ftl
</#ibizinclude>

<#ibizinclude>
../@MACRO/CONTROL/CONTROL-BASE.style.ftl
</#ibizinclude>