背景
实现如上图效果:点击小铃铛,从右侧展示通知,点击其中一条跳,转到一个新页面;小铃铛数目减少;
实现
index.vue
<template><el-drawerv-if="visible":visible.sync="visible":destroy-on-close="true":size="width"direction="rtl"custom-class="drawer__custom"@close="onClosed"><!-- 公告通知 --><template slot="title"><div class="header"><d2-icon-svg name="icon_status" /><span>{{ language == 'cn'? name : nameEn }}</span></div></template><!-- 工单内容 --><div class="content"><notice-contentv-if="noticeList && Object.keys(noticeList)":notices="noticeList"@viewDetail="onViewDetail"@loadMore="loadMore" /></div></el-drawer>
</template><script>
import { mapState } from 'vuex';
import NoticeContent from './NoticeContent.vue';
import { readNoticeService } from '@/api/notice';
import { updateMessageStatus, getUnreadMessageList } from '@/api/workOrder';export default {name: 'NoticeDrawer',components: { NoticeContent },data() {return {name: '通知',nameEn: 'Notification',visible: false,width: 480,pageNum: 1,pageSize: 5,currentViewNotice: {},noticeList: [],loadingInstance: null,};},computed: {...mapState('d2admin/profile', ['language']),...mapState('d2admin/user', ['info']),},methods: {open(list) {this.visible = true;this.noticeList = Object.assign([], list);},loadMore() {// 分页累加this.pageNum += 1;this.showLoading();getUnreadMessageList({ pageNum: this.pageNum, pageSize: this.pageSize }).then(response => {const { data } = response.data;const { rows } = data;this.noticeList = [...this.noticeList, ...rows];}).finally(() => {this.loadingInstance.close();});},onViewDetail(notice, idx) {// 未读状态下才更新文章状态// if (!notice.readFlag) {// this.readNotice(notice.noticeNo);// }this.visible = false;const params = {formNo: notice.formNo,direction: 'T'};updateMessageStatus(params).then((response) => {const result = (response.data || {}).data || {};this.$emit('updateReadCount');const routePath = `/work-order/dialogue?formNo=${notice.formNo}`;window.open(this.$router.resolve(routePath).href, '_blank');});console.log(notice, 'notice, idxnotice, idx');},readNotice(noticeNo) {readNoticeService({ noticeNo, operator: this.info.name }).then(response => {// 文档已读,更新数据,把当前数据的readFlag置为已读this.noticeList = this.noticeList.map(item => {if (item.noticeNo === noticeNo) {item.readFlag = true;}return item;});});},showLoading() {this.loadingInstance = this.$loading({lock: true,text: 'Loading',spinner: 'el-icon-loading',background: 'rgba(256,256,256,.7)',target: document.querySelector('.content')});},onClosed() {this.visible = false;this.$emit('updateReadCount');Object.assign(this.$data, this.$options.data());},},
};
</script><style scoped lang="scss">
/deep/ .el-drawer {padding-right: 0 !important;.el-drawer__header {padding-right: 30px;}
}
.drawer__custom {.header {span {margin-left: 8px;}}.content {display: flex;//height: calc(100vh - 80px);}
}
</style>
NoticeContent.vue
<template><div ref="notice" class="notice_wrapper" @scroll="onScrollNotice($event)"><divv-for="(notice, index) of notices":key="index":class="['notice_item', active === index ? 'active' : '']"@click="onViewDetails(notice, index)"><header class="header"><span class="date">{{$util.string.betterDisplay($util.datetime.formatUtcToZoneTime(notice.createTime))}}</span><el-tag v-if="!notice.readFlag" color="#FFB8BB">NEW</el-tag></header><div class="content"><div class="title">{{ language == 'cn'? name : nameEn }}:{{ notice.formNo }}</div><div v-if="notice.type == 'system_contact'" ref="content" class="message">{{ language == 'cn' ? parerFont(notice.content).cn : parerFont(notice.content).en }}</div><div v-else ref="content" class="message">{{ notice.content }}</div></div></div></div>
</template><script>
import { mapState } from 'vuex';export default {name: 'NoticeContent',props: {notices: {type: Array,default: () => [],required: true,},},data() {return {active: '',name: '工单单号',nameEn: 'Ticket Number'};},computed: {...mapState('d2admin/profile', ['language']),},methods: {onScrollNotice(evt) {const { scrollTop, offsetHeight, scrollHeight } = evt.target;// 滑到底部if ((scrollTop + offsetHeight) === scrollHeight) {this.$emit('loadMore');}},onViewDetails(notice, idx) {this.active = idx;this.$emit('viewDetail', notice);},parerFont(text) {return JSON.parse(text);}},
};
</script><style scoped lang="scss">
.notice_wrapper {width: 420px;height: calc(100vh - 80px);overflow-y: auto;padding-right:4px;margin-right: 26px;box-sizing: border-box;.notice_item {padding: 24px;min-height: 120px;border: 1px solid $color-neutral-light-100;border-radius: $common-radius_12;background-color: #ffffff;cursor: pointer;margin-bottom: 16px;&:hover {background-color: $color-neutral-light-50;}&.active {background-color: $color-active-100;}.header {display: flex;justify-content: space-between;align-items: center;.date {color: $color-neutral-light-400;font-size: 12px;font-weight: 400;line-height: 18px;}/deep/ .el-tag {color: #1a1c21;border-style: none;border-radius: 14px;font-size: 12px;line-height: 18px;padding: 2px 8px;height: 100%;}}.content {.title {margin: 14px 0 8px;color: $color-neutral-light-500;font-size: 16px;font-weight: 600;line-height: 24px;}.message {color: #727880;font-weight: 400;line-height: 21px;overflow: hidden;/* 溢出用省略号显示 */text-overflow: ellipsis;/* 作为弹性伸缩盒子模型显示 */display: -webkit-box;/* 设置伸缩盒子的子元素排列方式:从上到下垂直排列 */-webkit-box-orient:vertical;/* 显示的行数 */-webkit-line-clamp: 2;}}}
}
</style>
引入使用
<notice-drawer ref="noticeDrawers" @updateReadCount="queryNoticeCountTotal" />import { getUnreadMessageList } from '@/api/workOrder';export default {name: 'WorkOrder',components: {NoticeDrawer,},data() {return {noticeTotal: 0,noticeList: [],};},created() {this.queryNoticeCountTotal();},methods: {queryNoticeCountTotal() {getUnreadMessageList({ pageSize: 5, pageNum: 1 }).then(response => {if (response.data) {const { data } = response.data;const { rows, total } = data;this.noticeList = rows;this.noticeTotal = total;}});},}}
接口
const hostType = 'BASIC_GATE';
export const getUnreadMessageList = (data = {}) => {const extraData = {hostType};return post('/myNotice/getUnreadMessageList', data, extraData);
};