Quellcode durchsuchen

1.新增消息通知页面
2.首页菜单权限控制

GouGengquan vor 1 Monat
Ursprung
Commit
b157868a71
4 geänderte Dateien mit 156 neuen und 14 gelöschten Zeilen
  1. 16 0
      src/api/message.js
  2. 108 5
      src/views/home/components/NavBar.vue
  3. 25 7
      src/views/home/home.vue
  4. 7 2
      src/views/home/index.vue

+ 16 - 0
src/api/message.js

@@ -0,0 +1,16 @@
+import request from '@/utils/request'
+
+// 获取未读消息
+export function notRead() {
+    return request.get(`message/notRead`)
+}
+
+// 更新消息已读状态
+export function updateRead(params) {
+    return request.get(`message/updateRead/${params}`)
+}
+
+// 一键已读全部消息
+export function allRead() {
+    return request.get(`message/allRead`)
+}

+ 108 - 5
src/views/home/components/NavBar.vue

@@ -4,8 +4,11 @@
       <img class="logclass" src="@/assets/images/logo.png" />
     </div>
     <div class="loginUser" v-if="userStore.userInfo">
-      <div style="margin-right: 10px;display: inline-block">
-        <van-icon name="envelop-o" size="28" />
+      <div style="margin-right: 10px;display: inline-block" @click="showMessage = true">
+        <van-badge dot v-if="hasNotReadMes">
+          <van-icon name="envelop-o" size="28" />
+        </van-badge>
+        <van-icon name="envelop-o" size="28" v-else />
       </div>
       <span class="nameSpan">{{ userStore.userInfo.name }}</span>
       <svg @click="logout()" t="1748245580960" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5746" width="28" height="28">
@@ -21,6 +24,23 @@
         />
       </svg>
     </div>
+    <van-popup v-model:show="showMessage" round position="bottom" :style="{ height: '80%' }">
+      <div class="control">
+        <div class="button-read" @click="setAllRead()">全部已读</div>
+        <div class="button-close" @click="showMessage = false">关闭窗口</div>
+      </div>
+      <van-empty v-if="!hasNotReadMes" image="search" description="还没有新消息" />
+      <div class="messageDiv" v-else>
+        <div v-for="item in messages" :key="item.id">
+          <div style="height: 25px">
+            <div class="messageTitle">{{ item.title }}</div>
+            <div class="messageTime">{{ item.created }}</div>
+          </div>
+          <div class="messageContent">{{ item.message }}</div>
+          <van-divider />
+        </div>
+      </div>
+    </van-popup>
   </div>
 </template>
   
@@ -28,12 +48,19 @@
 import { mapStores } from 'pinia';
 import { useUserStore } from '@/stores/useUserStore';
 import { removeToken } from '@/utils/auth';
+import { showNotify } from 'vant';
+import { notRead, updateRead, allRead } from '@/api/message';
 
 export default {
   props: {},
   data() {
     return {
       navBarFixed: false,
+      showMessage: false,
+      // 消息
+      messages: [],
+      // 是否有未读消息
+      hasNotReadMes: false,
     };
   },
   mounted() {
@@ -43,6 +70,9 @@ export default {
   computed: {
     ...mapStores(useUserStore),
   },
+  created() {
+    this.getNotRead();
+  },
   methods: {
     async logout() {
       // 移除token
@@ -60,6 +90,28 @@ export default {
         this.navBarFixed = false;
       }
     },
+    // 获取未读消息
+    getNotRead() {
+      notRead().then((res) => {
+        this.messages = res.data;
+        if (this.messages.length > 0) {
+          this.hasNotReadMes = true;
+        } else {
+          this.hasNotReadMes = false;
+        }
+      });
+    },
+    // 全部已读
+    setAllRead() {
+      if (this.hasNotReadMes) {
+        allRead().then((res) => {
+          if (res.code === 200) {
+            this.getNotRead();
+            showNotify({ type: 'success', message: '请求成功' });
+          }
+        });
+      }
+    },
   },
 };
 </script>
@@ -68,15 +120,15 @@ export default {
 .navbarRelative {
   width: 100%;
   height: 60px;
-  position: relative; 
-  background-color: #F7F8FA;
+  position: relative;
+  background-color: #f7f8fa;
   border-bottom: 1px #d7d7d7 solid;
 }
 
 .navbarFixed {
   width: 100%;
   height: 60px;
-  background-color: #F7F8FA;
+  background-color: #f7f8fa;
   border-bottom: 1px #d7d7d7 solid;
   position: fixed;
   top: 0;
@@ -107,4 +159,55 @@ export default {
 .nameSpan {
   padding-right: 5px;
 }
+
+.messageDiv {
+  margin: 10px;
+  max-height: 92.4%;
+  overflow: auto;
+}
+
+.control {
+  margin-top: 10px;
+  margin-bottom: 35px;
+}
+
+.button-read {
+  margin-left: 12px;
+  font-size: 14px;
+  display: inline-block;
+  float: left;
+  color: #1989fa;
+}
+
+.button-close {
+  margin-right: 12px;
+  font-size: 14px;
+  display: inline-block;
+  float: right;
+  color: #1989fa;
+}
+
+.messageTitle {
+  font-weight: bold;
+  margin-bottom: 5px;
+  display: inline-block;
+  float: left;
+  font-size: 14px;
+}
+
+.messageTime {
+  margin-bottom: 5px;
+  display: inline-block;
+  float: right;
+  font-size: 12px;
+  color: #c8c9cc;
+}
+
+.messageContent {
+  width: 100%;
+  margin-bottom: 5px;
+  display: flex;
+  font-size: 13px;
+  color: #ed6a0c;
+}
 </style>

+ 25 - 7
src/views/home/home.vue

@@ -1,6 +1,6 @@
 <template>
   <div class="bottom-layer">
-    <div class="card">
+    <div class="card" v-if="meunNames.includes('个贷业务')">
       <div class="businessTitle">个贷业务</div>
       <div class="icon-area" @click="goBench('/index/personal/pendingOrder')">
         <svg t="1713838252300" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5893" width="42" height="42">
@@ -50,7 +50,7 @@
         <div class="icon-word">我的订单</div>
       </div>
     </div>
-    <div class="card">
+    <div class="card" v-if="meunNames.includes('大中型业务')">
       <div class="businessTitle">大中型业务</div>
       <div class="icon-area" @click="goBench('/index/major/pendingOrder')">
         <svg t="1713838139679" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5142" width="42" height="42">
@@ -95,7 +95,7 @@
         <div class="icon-word">我的订单</div>
       </div>
     </div>
-    <div class="card">
+    <div class="card" v-if="meunNames.includes('资产业务')">
       <div class="businessTitle">资产业务</div>
       <div class="icon-area" @click="goBench('/index/assets/pendingOrder')">
         <svg t="1713838525654" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6320" width="42" height="42">
@@ -160,7 +160,7 @@
         <div class="icon-word">我的订单</div>
       </div>
     </div>
-    <div class="card">
+    <div class="card" v-if="meunNames.includes('土地规划市场')">
       <div class="businessTitle">土地规划业务</div>
       <div class="icon-area" @click="goBench('/index/land/pendingOrder')">
         <svg t="1713920171367" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1903" width="42" height="42">
@@ -209,9 +209,27 @@
 </template>
 
 <script>
+import { mapStores } from 'pinia';
+import { menuStore } from '@/stores/menuStore';
+
 export default {
+  props: {
+    parentLoaded: Boolean,
+  },
+  watch: {
+    parentLoaded(newVal) {
+      if (newVal) {
+        this.meunNames = this.menuStore.menuInfo.map((item) => item.name); // 父组件加载完成后执行
+      }
+    },
+  },
   data() {
-    return {};
+    return {
+      meunNames: [],
+    };
+  },
+  computed: {
+    ...mapStores(menuStore),
   },
   methods: {
     goBench(route) {
@@ -222,7 +240,7 @@ export default {
 </script>
 
 <style scoped>
-.bottom-layer{
+.bottom-layer {
   height: 550px;
 }
 .card {
@@ -233,7 +251,7 @@ export default {
   width: 89%;
 }
 
-.icon-word{
+.icon-word {
   font-size: 14px;
 }
 

+ 7 - 2
src/views/home/index.vue

@@ -4,7 +4,7 @@
       <router-view v-slot="{ Component }">
       <transition>
         <keep-alive>
-          <component :is="Component" />
+          <component :is="Component" :parent-loaded="parentLoaded" />
         </keep-alive>
       </transition>
     </router-view>
@@ -23,7 +23,10 @@ import { Tabbar, NavBar } from './components';
 
 export default {
   data() {
-    return {};
+    return {
+      // 父组件加载状态
+      parentLoaded: false
+    };
   },
   components: {
     Tabbar,
@@ -45,6 +48,8 @@ export default {
         this.userStore.setUserInfo(res.data);
         userMenus().then((res) => { // 获取菜单权限
           this.menuStore.setMenuInfo(res.data);
+          // 方法执行完成后传递父组件状态
+          this.parentLoaded = true;
         });
       });
     },