前端通知组件封装

背景

实现如上图效果:点击小铃铛,从右侧展示通知,点击其中一条跳,转到一个新页面;小铃铛数目减少;

实现 

index.vue

<template>
  <el-drawer
    v-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-content
        v-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)">
    <div
      v-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);
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/631886.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C#知识|上位机子窗体嵌入主窗体方法(实例)

哈喽,你好啊,我是雷工! 上位机开发中,经常会需要将子窗体嵌入到主窗体, 本节练习C#中在主窗体的某个容器中打开子窗体的方法。 01 需求说明 本节练习将【账号管理】子窗体在主窗体的panelMain容器中打开。 账号管理子窗体如下: 主窗体的panelMain容器位置如图: 02 实现…

【找到所有数组中消失的数字】leetcode,python

很菜的写法&#xff1a; class Solution:def findDisappearedNumbers(self, nums: List[int]) -> List[int]:nlen(nums)#存1-Nnum_1[i for i in range(1,n1)]#预存数num_2[]nums.sort()for i in nums:num_1[i-1]0for i in num_1:if i!0:num_2.append(i)return num_2能过但是…

计算机毕业设计hadoop+hive+hbase学情分析 在线教育大数据 课程推荐系统 机器学习 深度学习 人工智能 大数据毕业设计 知识图谱

毕 业 设 计&#xff08;论 文&#xff09;开 题 报 告 1&#xff0e;结合毕业设计&#xff08;论文&#xff09;课题情况&#xff0c;根据所查阅的文献资料&#xff0c;每人撰写不少于1000字的文献综述&#xff1a; 一、研究背景和意义 “互联网”和大数据带来了网络教育的蓬…

Java入门——异常

异常的背景 初识异常 我们曾经的代码中已经接触了一些 "异常" 了. 例如: //除以 0 System.out.println(10 / 0); // 执行结果 Exception in thread "main" java.lang.ArithmeticException: / by zero //数组下标越界 int[] arr {1, 2, 3}; System.out.…

C语言之指针初阶

目录 前言 一、内存与地址的关系 二、指针变量 三、野指针 四、const 五、传值调用与传址调用 总结 前言 本文主要介绍C语言指针的一些基础知识&#xff0c;为后面深入理解指针打下基础&#xff0c;因此本文内容主要包括内存与地址的关系&#xff0c;指针的基本语法&…

LiveGBS流媒体平台GB/T28181用户手册-服务器概览:通道信息、负载信息、CPU使用、存储使用、带宽使用(Mbps)、内存使用

LiveGBS用户手册-服务器概览&#xff1a;通道信息、负载信息、CPU使用、存储使用、带宽使用&#xff08;Mbps&#xff09;、内存使用 1、服务器概览1.1、通道信息1.2、负载信息1.2.1、信息说明1.2.2、会话列表 1.3、CPU使用1.4、存储使用1.5、带宽使用&#xff08;Mbps&#xf…

视频下载器 - 网页视频自动嗅探2.2.4

【应用名称】&#xff1a;视频下载器 - 网页视频自动嗅探 【适用平台】&#xff1a;#Android 【软件标签】&#xff1a;#Video #Downloader 【应用版本】&#xff1a;2.2.4 【应用大小】&#xff1a;33MB 【软件说明】&#xff1a;软件升级更新。支持多种格式的看片神器&am…

java入门详细教程之集合的理解与应用

一、Collenction集合 数组和集合的区别 长度 数组的长度是不可变的,集合的长度是可变的 数据类型 数组可以存基本数据类型和引用数据类型 集合只能存引用数据类型,如果要存基本数据类型,需要存对应的包装类 Collection 集合概述和使用 Collection集合概述​&#xff1a; 是单…

MacOS下载安装JDK8

一、前言 今天给苹果电脑安装JDK环境&#xff0c;后续打算把Mac系统也用起来&#xff0c;也体验一把用苹果系统开发。 JDK就不过多介绍了&#xff0c;大家都是JAVA开发&#xff0c;JDK就是JAVA开发的必要环境。目前已经更新到JDK20了&#xff0c;不过我是不会更新的&#xff0…

微服务中的鉴权怎么做?

大家好&#xff0c;我是苍何呀。 现在出去找工作&#xff0c;简历上不写上微服务的技术&#xff0c;仿佛自己跟不上时代了&#xff0c;面试官更是喜欢盯着微服务项目来提问。 但其实虽说微服务是主流&#xff0c;随着云原生架构的发展&#xff0c;微服务也是趋势&#xff0c;…

DOS学习-目录与文件应用操作经典案例-dir

欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一.前言 二.使用 三.练习 一.前言 dir是"directory"&#xff08;目录&#xff09;的缩写&#xff0c;它主要用于展示某个磁盘上的全部或特定文件目录。在DOS操作系统中&#…

ES6中数组新增了哪些扩展?

​&#x1f308;个人主页&#xff1a;前端青山 &#x1f525;系列专栏&#xff1a;JavaScript篇 &#x1f516;人终将被年少不可得之物困其一生 依旧青山,本期给大家带来JavaScript篇专栏内容:ES6中数组新增了哪些扩展&#xff1f; 目录 一、扩展运算符的应用 二、构造函数新…

Web3与物联网:构建智能连接的数字世界

引言 随着互联网的不断发展&#xff0c;物联网&#xff08;Internet of Things, IoT&#xff09;作为一种新兴的信息技术&#xff0c;正在逐渐渗透到我们的生活和工作中。而随着Web3的兴起&#xff0c;物联网将迎来新的发展机遇。本文将探讨Web3与物联网的结合&#xff0c;如何…

全面解析防静电措施:保障工业安全,预防静电危害

静电是一种常见的物理现象&#xff0c;由于电荷的不平衡而产生。在特定的环境中&#xff0c;静电可能会带来危害&#xff0c;如损坏电子设备、引起火灾等。因此&#xff0c;采取适当的防静电措施是非常重要的。以下是一些常见的防静电方法&#xff1a; 增加环境湿度&#xff1a…

崆峒酥饼:佳节馈赠的美味之选

崆峒酥饼&#xff1a;佳节馈赠的美味之选 在即将到来的端午节&#xff0c;人们开始忙碌地准备着走亲访友的礼物。而崆峒酥饼&#xff0c;作为一种传统的美食&#xff0c;不仅是节日里的美味享受&#xff0c;更是传递情谊的佳品。 崆峒酥饼&#xff0c;以其酥脆的口感和独特的风…

使用httpx异步获取高校招生信息:一步到位的代理配置教程

概述 随着2024年中国高考的临近&#xff0c;考生和家长对高校招生信息的需求日益增加。了解各高校的专业、课程设置和录取标准对于高考志愿填报至关重要。通过爬虫技术&#xff0c;可以高效地从各高校官网获取这些关键信息。然而&#xff0c;面对大量的请求和反爬机制的挑战&a…

【Python】语句与众所周知【自我维护版】

各位大佬好 &#xff0c;这里是阿川的博客 &#xff0c; 祝您变得更强 个人主页&#xff1a;在线OJ的阿川 大佬的支持和鼓励&#xff0c;将是我成长路上最大的动力 阿川水平有限&#xff0c;如有错误&#xff0c;欢迎大佬指正 本篇博客是在之前的基础上进行的维护 目录 条…

HP6V18、HP6V65电比例功率控制泵放大器

HP6V18、HP6V65电比例压力负控制&#xff0c;电比例功率控制泵通过由BEUEC比例放大器控制改变阀的输入电流&#xff0c;将泵设置为一定压力。改变负载压力&#xff0c;为使调订压力恒定&#xff0c;泵摆角会增大或减小&#xff0c;从而改变流量。因此泵只能输出执行器可以接受的…

ubuntu下gcc编译器的安装

.gcc编译器的安装 一般linux下是覆盖含有的&#xff0c;如果没有执行更新命令 sudo apt update gcc安装成功&#xff0c;可以检查一下版本 可以看出我的gcc是9.4.0版本的

地表最强ChatGPT爆了!我来告诉你,它都有什么用

OpenAI刚刚发布了全新的 "GPT-4o"&#xff0c;它不仅可以通过语音、视觉和文本进行推理&#xff0c;还在速度和价格上有了巨大的突破。它的速度提高了2倍&#xff0c;价格却降低了50%&#xff0c;而且生成速率比GPT-4 Turbo高出5倍。最令人惊喜的是&#xff0c;它将对…