Ver Fonte

公告弹出框

Michael Wang há 6 anos atrás
pai
commit
a2fa1886f2

+ 11 - 2
src/components/MainLayout/MainLayout.vue

@@ -77,7 +77,9 @@
         </li>
         <li>
           <router-link class="link" to="/site-message">
-            公告通知
+            <Badge :count="messageUnread" :offset="[20, -20]">
+              公告通知
+            </Badge>
           </router-link>
         </li>
         <li>
@@ -88,12 +90,15 @@
       </ul>
     </nav>
     <footer class="footer">©️2019 启明泰和</footer>
+
+    <SiteMessagePopup />
   </div>
 </template>
 
 <script>
 import { mapState } from "vuex";
 import VueQrcode from "@chenfengyuan/vue-qrcode";
+import SiteMessagePopup from "./SiteMessagePopup.vue";
 
 export default {
   name: "MainLayout",
@@ -106,7 +111,10 @@ export default {
     },
   },
   computed: {
-    ...mapState(["user"]),
+    ...mapState(["user", "siteMessages"]),
+    messageUnread() {
+      return this.siteMessages.filter(v => v.hasRead === false).length;
+    },
     qrValue() {
       const { rootOrgId, studentCode, identityNumber } = this.user;
       return JSON.stringify({ rootOrgId, studentCode, identityNumber });
@@ -118,6 +126,7 @@ export default {
   },
   components: {
     qrcode: VueQrcode,
+    SiteMessagePopup,
   },
 };
 </script>

+ 91 - 0
src/components/MainLayout/SiteMessagePopup.vue

@@ -0,0 +1,91 @@
+<template>
+  <div v-if="unreadMessage" class="popup">
+    <h5
+      style=" padding: 5px; background:rgba(19,187,138,1);
+              border-radius:6px 6px 0px 0px; font-size:14px;
+              font-weight:500;
+              color:rgba(255,255,255,1);
+              line-height:20px;"
+    >
+      {{ unreadMessage.title }}
+    </h5>
+
+    <p
+      style="text-overflow: ellipsis; text-indent: 2em; text-align: left; height: 100px; overflow: hidden; margin: 20px;"
+    >
+      {{ unreadMessageContent }}
+    </p>
+    <div style="text-align: left; margin-left: 20px; margin-bottom: 10px;">
+      <router-link :to="'/site-message/' + unreadMessage.id">
+        详情 >>>
+      </router-link>
+      <span
+        @click="ignoreMessage"
+        style="display: inline-block; margin-left: 20px; cursor: pointer;"
+        >忽略</span
+      >
+    </div>
+  </div>
+</template>
+
+<script>
+import { mapState } from "vuex";
+
+export default {
+  name: "SiteMessagePopup",
+  data() {
+    let ignoreMessageIds = window.sessionStorage.getItem("ignoreMessageIds");
+    if (ignoreMessageIds) {
+      ignoreMessageIds = JSON.parse(ignoreMessageIds);
+    } else {
+      ignoreMessageIds = [];
+    }
+    return {
+      ignoreMessageIds,
+    };
+  },
+  methods: {
+    ignoreMessage() {
+      this.ignoreMessageIds.push(this.unreadMessage.id);
+      window.sessionStorage.setItem(
+        "ignoreMessageIds",
+        JSON.stringify(this.ignoreMessageIds)
+      );
+    },
+  },
+  computed: {
+    ...mapState(["siteMessages"]),
+    unreadMessage() {
+      const unreadMessages = this.siteMessages
+        .filter(v => v.hasRead === false)
+        .filter(v => this.ignoreMessageIds.includes(v.id) === false)
+        .reverse();
+      if (unreadMessages.length > 0) {
+        return unreadMessages[0];
+      } else {
+        return null;
+      }
+    },
+    unreadMessageContent() {
+      const div = document.createElement("div");
+      div.innerHTML = this.unreadMessage.content;
+      const text = div.textContent || div.innerText || "";
+      return text.slice(0, 90) + (text.length > 90 ? "..." : "");
+    },
+  },
+};
+</script>
+
+<style scoped>
+.popup {
+  position: absolute;
+  bottom: 20px;
+  right: 20px;
+  width: 320px;
+  height: 200px;
+  background: rgba(255, 255, 255, 1);
+  box-shadow: 0px 2px 10px 0px rgba(0, 0, 0, 0.1);
+  border-radius: 6px;
+  border: 1px solid rgba(221, 221, 221, 1);
+}
+</style>

+ 1 - 0
src/features/Login/Login.vue

@@ -211,6 +211,7 @@ export default {
       this.productName = "远程教育网络考试";
     }
     window.sessionStorage.removeItem("token");
+    window.sessionStorage.clear();
     window.localStorage.removeItem("key");
     if (localStorage.getItem("user-for-reload")) {
       this.loginForm.accountValue = JSON.parse(

+ 35 - 10
src/features/SiteMessage/SiteMessageDetail.vue

@@ -40,20 +40,45 @@ import { mapState, mapMutations } from "vuex";
 export default {
   name: "SiteMessageDetail",
   async mounted() {
-    if (!this.message.hasRead) {
-      await this.$http.post(
-        "/api/ecs_exam_work/notice/updateNoticeReadStatus?noticeId=" +
-          this.message.id
-      );
-      window._hmt.push(["_trackEvent", "站内消息详情页面", "发送已读成功"]);
-      this.updateSiteMessagesTimeStamp(Date.now());
-    }
+    await this.getList();
+    await this.prepareData();
+  },
+  async beforeUpdate() {
+    await this.prepareData();
   },
   methods: {
-    ...mapMutations(["updateSiteMessagesTimeStamp"]),
+    ...mapMutations(["updateSiteMessages", "updateSiteMessagesTimeStamp"]),
+    async getList() {
+      try {
+        const noticeRes = (await this.$http.get(
+          "/api/ecs_exam_work/notice/getUserNoticeList?" +
+            this.user.id +
+            this.siteMessagesTimeStamp
+        )).data;
+        this.updateSiteMessages(noticeRes);
+      } catch (error) {
+        console.log(error);
+        this.$Message.error({
+          content: "获取公告通知异常",
+          duration: 15,
+          closable: true,
+        });
+      }
+    },
+    async prepareData() {
+      if (!this.message.hasRead) {
+        await this.$http.post(
+          "/api/ecs_exam_work/notice/updateNoticeReadStatus?noticeId=" +
+            this.message.id
+        );
+        window._hmt.push(["_trackEvent", "站内消息详情页面", "发送已读成功"]);
+        this.updateSiteMessagesTimeStamp(Date.now());
+        await this.getList();
+      }
+    },
   },
   computed: {
-    ...mapState(["siteMessages"]),
+    ...mapState(["user", "siteMessages", "siteMessagesTimeStamp"]),
     message() {
       if (this.siteMessages) {
         return this.siteMessages.find(v => v.id === +this.$route.params.id);

+ 2 - 0
src/plugins/iview.js

@@ -20,6 +20,7 @@ import {
   Progress,
   Alert,
   Table,
+  Badge,
 } from "iview";
 Vue.component("Button", Button);
 Vue.component("Form", Form);
@@ -39,6 +40,7 @@ Vue.component("Option", Option);
 Vue.component("Progress", Progress);
 Vue.component("Alert", Alert);
 Vue.component("Table", Table);
+Vue.component("Badge", Badge);
 
 Vue.prototype.$Message = Message;
 Vue.prototype.$Modal = Modal;