<template> <!-- 消息弹出框绘制开始 --> <el-badge :is-dot="showIsDot" :hidden="badgeIsHidden" class="app-message-popover" @click="OpenPopover"> <el-popover placement="bottom" popper-class="message-popover-container" v-model="showPopover" trigger="click" width="400" @show="initTabCnt" @hide="initTabCnt" > <el-tabs :value="default_tab_pane" :stretch="true"> <!-- 待办 --> <el-tab-pane :label=" this.$t('components.appmessagepopover.myTasksLabel') + (myTasks.length == 0 ? '' : '(' + myTasks.length + ')') " name="first" style="height: 300px; overflow: auto" :draggable="false" > <template v-for="(myTask, index) in myTasks"> <template v-if="index < taskShowCnt"> <el-row class="popover__content" :key="index" :draggable="false"> <el-col :span="3" class="popover__content__avatar" :draggable="false"> <el-avatar icon="el-icon-s-check" size="small" :draggable="false" style="color: white; background-color: #409eff" ></el-avatar> </el-col> <el-col :span="21" class="popover__content__caption" :draggable="false"> <el-row :draggable="false"> <el-col :span="16" :draggable="false" style="width: 65%"> <div class="process-definition-name" :draggable="false" @click="handleTag(myTask)" > <strong>{{ myTask.usertaskname }}</strong> </div> <!-- <div class="description" :draggable="false">{{myTask.description}}</div> <div class="createtime" :draggable="false">{{ formatDate(myTask.createTime, 'MM-DD hh:mm') }}</div> --> </el-col> <!-- <el-col :span="5" :draggable="false" style="display: flex; align-items: center"> <el-tag :type="'success'" size="small" style="overflow: hidden; text-overflow: ellipsis" :draggable="false" > 成功 </el-tag> </el-col> --> </el-row> </el-col> </el-row> </template> </template> <template> <div class="popover__show-more" @click="showMore('taskShowCnt')"> <label v-if="taskShowCnt < myTasks.length">{{ this.$t('components.appmessagepopover.loadmore') }}</label> <label v-else>{{ this.$t('components.appmessagepopover.nomore') }}</label> </div> </template> </el-tab-pane> <!-- 通知 --> <el-tab-pane :label=" myMsgs.length == 0 ? this.$t('components.appmessagepopover.myNotificationsLabel') : this.$t('components.appmessagepopover.myNotificationsLabel') + '(' + myMsgs.length + ')' " name="second" :style="{ height: '300px', overflow: 'auto' }" :draggable="false" > <template v-for="(myMsg, index) in myMsgs"> <template v-if="index < msgShowCnt"> <el-row class="popover__content" style="position:relative;" :key="index" :draggable="false"> <el-col :span="3" class="popover__content__avatar" :draggable="false"> <i class="fa fa-tasks" style="color: #409eff;font-size: 24px;"></i> </el-col> <el-col :span="21" class="popover__content__caption" :draggable="false"> <el-row :draggable="false"> <el-col :span="24" :draggable="false"> <div :draggable="false" style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;" > <strong>{{ myMsg.name }}</strong> </div> <div :draggable="false" style="display: flex;justify-content: space-between;align-items: center;" > <div v-if="myMsg.state !== 20">{{ myMsg.begintime }}</div> <div v-if="myMsg.state === 20">{{ `${myMsg.stepinfo}(${myMsg.completionrate}%)` }}</div> <div> <el-tag :type=" myMsg.state === 40 ? 'danger' : myMsg.state === 30 ? 'success' : myMsg.state === 20 ? 'info' : '-' " size="small" style="overflow: hidden;text-overflow: ellipsis;" :draggable="false" > {{ myMsg.stateText }} </el-tag> </div> </div> </el-col> </el-row> </el-col> <div :style="getProgressStyle(myMsg)"></div> </el-row> </template> </template> <template> <div class="popover__show-more" @click="showMore('msgShowCnt')"> <label v-if="msgShowCnt < myMsgs.length">{{ this.$t('components.appmessagepopover.loadmore') }}</label> <label v-else>{{ this.$t('components.appmessagepopover.nomore') }}</label> </div> </template> </el-tab-pane> </el-tabs> <i id="bell-btn" size="20" slot="reference" class="el-icon-bell"></i> </el-popover> </el-badge> <!-- 消息弹出框绘制结束 --> </template> <script lang="ts"> import { Vue, Component } from 'vue-property-decorator'; import { Subscription } from 'rxjs'; import { AppServiceBase, LogUtil } from 'ibiz-core'; import { ActionState, AppCenterService, AppNoticeService, NotificationFactory, SubType } from 'ibiz-vue'; import moment from 'moment'; @Component({}) export default class AppMessagePopover extends Vue { // 是否显示Popover public showPopover: boolean = false; // 是否显示小圆点 public showIsDot: any = false; // 默认显示的tab页 public default_tab_pane: any = 'first'; // 待办列表 public myTasks: any = []; // 待办面板显示条数 public taskShowCnt: number = 0; // 消息列表 public myMsgs: any = []; // 信息面板显示条数 public msgShowCnt: number = 0; // 环境配置对象 public environment: any = AppServiceBase.getInstance().getAppEnvironment(); // 应用状态事件 public appStateEvent: Subscription | undefined; // 标记是否隐藏 public badgeIsHidden = false; // 标记计数器 public bellTimer: any; /** * 获取进度条样式 * * @param item */ public getProgressStyle(item: any) { const itemStyle = { position: 'absolute', height: '100%', background: 'linear-gradient(to right, #fff, #409eff)', 'z-index': -100, }; Object.assign(itemStyle, { width: item.state === 20 ? `${item.completionrate}%` : '0' }); return itemStyle; } /** * vue创建 */ created(): void { // 全局刷新通知 if (AppCenterService.getMessageCenter()) { this.appStateEvent = AppCenterService.getMessageCenter().subscribe( ({ name, action, data }: { name: string; action: string; data: any }) => { if (Object.is(name, 'SysTodo') && Object.is(action, 'appRefresh')) { if (!this.environment.workflow) { return; } this.getMyTasks(); return; } if ( Object.is(name, 'Notification') && (Object.is(action, 'AddItem') || Object.is(action, 'InitItem')) ) { this.getMyMsgs(); this.handleAsyncActionNotification(name, action, data); } }, ); } } /** * vue挂载 */ mounted(): void { if (this.environment.workflow) { // 首次获取待办列表 this.getMyTasks(); // 定时器:每隔1分钟重新获取待办列表 const timer = setInterval(() => { this.getMyTasks(); }, 60000); // 监听定时器,在vue销毁前清除定时器 this.$once('hook:beforeDestroy', () => { // 清除定时器 clearInterval(timer); }); } } /** * 处理异步作业通知 */ public handleAsyncActionNotification(name: string, action: string, data: any) { if (Object.is(action, 'AddItem') && data && data.subtype === SubType.ASYNCACTION) { const targetData = data.data; // 已经执行完成 if (targetData.actionstate === ActionState.CREATED) { AppNoticeService.getInstance().success(`${targetData.asyncacitonname}异步作业执行成功`, { duration: 0, showClose: true, position: 'top-right', }); } // 执行失败 if (targetData.actionstate === ActionState.FAILED) { AppNoticeService.getInstance().error(`${targetData.asyncacitonname}异步作业执行异常`, { duration: 0, showClose: true, position: 'top-right', }); } this.badgeIsHidden = true; if(this.bellTimer){ clearTimeout(this.bellTimer); } this.bellTimer = setTimeout(() => { this.badgeIsHidden = false; }, 500); } } /** * 获取待办列表 */ public getMyTasks() { let url: any = '/wfcore/mytasks'; this.$http .get(url) .then((response: any) => { if (response && response.status == 200) { const data: any = response.data; if (data && data.length > 0) { this.myTasks = data; this.showIsDot = true; } else { this.myTasks = []; this.showIsDot = false; } } }) .catch((error: any) => { LogUtil.warn(this.$t('components.appmessagepopover.error')); }); } /** * 获取消息列表 */ public getMyMsgs() { this.myMsgs = NotificationFactory.getInstance().getItems(true); if (this.myMsgs && this.myMsgs.length > 0) { this.showIsDot = true; this.$forceUpdate(); } } /** * 点击标签事件 */ public handleTag(data: any) { if (!data) return this.$throw(this.$t('components.appmessagepopover.geterror'), 'handleTag'); this.$http .post(`/systodos/${data.usertaskid}/getlinkurl`, { todourltype: 'RouterUrl', todosubtype: 'Todo', srfapptype: 'pc', srfapp: AppServiceBase.getInstance().getAppModelDataObject().codeName, }) .then((response: any) => { if (response && response.status == 200 && response.data && response.data.linkurl) { this.showPopover = false; let targetUrl: string = response.data.linkurl; if (targetUrl.indexOf('/') != 0) { targetUrl = '/' + targetUrl; } targetUrl = `${targetUrl.slice(0, targetUrl.indexOf(';srffullscreen=true'))}`; targetUrl += `;srfwf=Todo`; this.$router.push('/index' + targetUrl); } else { if (response) { this.$throw(response); } } }) .catch((response: any) => { this.$throw(response); }); } /** * 销毁之前 */ beforeDestroy(): void { // 清空数据 this.showIsDot = false; this.myTasks = []; this.myMsgs = []; } /** * 组件销毁 */ destroyed() { if (this.appStateEvent) { this.appStateEvent.unsubscribe(); } } /** * 时间格式转换 */ public formatDate(date: string, format: string) { if (date && format) { return moment(date).format(format); } return date; } /** * 加载更多 */ public showMore(cnt: string) { if (Object.is('taskShowCnt', cnt)) { this.taskShowCnt + 10 < this.myTasks.length ? (this.taskShowCnt += 10) : (this.taskShowCnt += this.myTasks.length - this.taskShowCnt); } if (Object.is('msgShowCnt', cnt)) { this.msgShowCnt + 10 < this.myMsgs.length ? (this.msgShowCnt += 10) : (this.msgShowCnt += this.myMsgs.length - this.msgShowCnt); } } /** * 弹出框 显示/隐藏 时显示条数初始化 */ public initTabCnt() { this.taskShowCnt = this.myTasks.length >= 10 ? 10 : this.myTasks.length; this.msgShowCnt = this.myMsgs.length >= 10 ? 10 : this.myMsgs.length; } /** * 弹出框显示处理 */ public OpenPopover() { this.showPopover = !this.showPopover; } } </script>