Sfoglia il codice sorgente

完成服务器通知的功能了

DESKTOP-MINPJAU\Administrator 3 anni fa
parent
commit
dcec135cc4

+ 1 - 1
index.html

@@ -8,7 +8,7 @@
     <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
 
     <script type="text/javascript"
-            src="https://api.map.baidu.com/api?v=2.0&ak=rQxHPQX1ua21rWnXzTbUh5KSSUbnefxR"></script>
+            src="https://api.map.baidu.com/api?v=2.0&ak=B74ya3RGhwWIdc8dwN2SfZOYD9G8kXiu"></script>
     <script src="https://mapv.baidu.com/build/mapv.min.js"></script>
 
 

+ 6 - 0
src/App.vue

@@ -51,6 +51,12 @@ export default defineComponent({
           store.commit('app/setUnreadMessageCount', newCount)
         }
 
+        if (data.refreshDelay) {
+          sleep(data.refreshDelay).then(() => {
+            location.reload();
+          })
+        }
+
         ElNotification({
           title: typeof data.title === 'undefined' ? '新消息' : data.title,
           message: data.message,

+ 9 - 1
src/api/public-api.js

@@ -140,4 +140,12 @@ export function idVerificationApi(idCard) {
         method: 'get',
         params: {idCard}
     });
-}
+}
+
+
+export function getSystemAnnouncement() {
+    return request({
+        url: '/getSystemAnnouncement',
+        method: 'get',
+    });
+}

+ 25 - 9
src/api/settings/send-notification.js

@@ -1,16 +1,32 @@
 import request from '../../utils/request'
 
 export function getOnlineCount() {
-  return request({
-    url: '/notification/getOnlineCount',
-    method: 'get',
-  })
+    return request({
+        url: '/notification/getOnlineCount',
+        method: 'get',
+    })
 }
 
 export function sendMessageToAll(data) {
-  return request({
-    url: '/notification/sendMessageToAll',
-    method: 'post',
-    data,
-  })
+    return request({
+        url: '/notification/sendMessageToAll',
+        method: 'post',
+        data,
+    })
+}
+
+export function sendSystemUpdatesMessage(message) {
+    return request({
+        url: '/sendSystemUpdatesMessage',
+        method: 'get',
+        params: {message}
+    })
+}
+
+export function sendScrollingMessages(message) {
+    return request({
+        url: '/sendScrollingMessages',
+        method: 'get',
+        params: {message}
+    })
 }

+ 0 - 1
src/components/progress/Index.vue

@@ -50,7 +50,6 @@ export default {
   setup() {
     const store = useStore()
     const jdt = computed(() => {
-      console.log(store.state.app.jdt, '监听')
       return store.state.app.jdt
     })
     const cptUpldRsTxt = computed(() => {

+ 7 - 3
src/icons/iconfont.css

@@ -1,8 +1,8 @@
 @font-face {
   font-family: "iconfont"; /* Project id 2473230 */
-  src: url('iconfont.woff2?t=1658450215671') format('woff2'),
-       url('iconfont.woff?t=1658450215671') format('woff'),
-       url('iconfont.ttf?t=1658450215671') format('truetype');
+  src: url('iconfont.woff2?t=1663978653146') format('woff2'),
+       url('iconfont.woff?t=1663978653146') format('woff'),
+       url('iconfont.ttf?t=1663978653146') format('truetype');
 }
 
 .iconfont {
@@ -13,6 +13,10 @@
   -moz-osx-font-smoothing: grayscale;
 }
 
+.icon-tongzhi:before {
+  content: "\e64b";
+}
+
 .icon-mobanweihu:before {
   content: "\e6d6";
 }

BIN
src/icons/iconfont.ttf


BIN
src/icons/iconfont.woff


BIN
src/icons/iconfont.woff2


+ 164 - 0
src/layout/Header/functionList/ScrollNotifications.vue

@@ -0,0 +1,164 @@
+<template>
+  <transition name="el-zoom-in-center">
+    <div class="announcement" v-show="isShow">
+      <el-popover :width="500">
+        <div v-if="data.systemUpdatesMessage">
+          系统更新通知:
+          <span style="color: red">
+          {{ data.systemUpdatesMessage }}
+          </span>
+          <br>
+          <span style="color: red">
+          <span class="red-point">
+            注意
+          </span>
+            系统更新期间请勿操作
+          </span>
+        </div>
+        {{ data.scrollingMessages }}
+        <template #reference>
+          <div class='ad' ref="adRef">
+            <i class="iconfont icon-tongzhi"/>
+            <div id="wrap" class="wrap" ref="wrapRef">
+              <p class="txt" ref="txtRef">
+                {{
+                  data.systemUpdatesMessage ? '系统更新通知:' + data.systemUpdatesMessage : data.systemUpdatesMessage
+                }}
+                {{ data.scrollingMessages }}
+                &nbsp;&nbsp;&nbsp;&nbsp;
+              </p>
+              <p class="txt" v-show="whetherToScroll">
+                {{
+                  data.systemUpdatesMessage ? '系统更新通知:' + data.systemUpdatesMessage : data.systemUpdatesMessage
+                }}
+                {{ data.scrollingMessages }}
+                &nbsp;&nbsp;&nbsp;&nbsp;
+              </p>
+            </div>
+          </div>
+        </template>
+      </el-popover>
+    </div>
+  </transition>
+</template>
+
+<script setup name='ScrollNotifications'>
+
+import {setCallback} from "@/utils/websocket";
+import {getSystemAnnouncement} from "@/api/public-api";
+
+let data = $ref({
+  systemUpdatesMessage: '',
+  scrollingMessages: ''
+})
+
+let isShow = $ref(false)
+
+const wrapRef = ref()
+const txtRef = ref()
+const adRef = ref()
+
+let whetherToScroll = $ref(false)
+
+let timer = null;
+
+watch(() => data, () => {
+  isShow = (data.systemUpdatesMessage || data.scrollingMessages)
+  nextTick(() => {
+    if (isShow) {
+      wrapRef.value.style.width = adRef.value.clientWidth - 20 + 'px'
+      if (wrapRef.value.offsetWidth < txtRef.value.offsetWidth) {
+        let p_w = txtRef.value.offsetWidth;
+        whetherToScroll = true
+        timer = setInterval(() => {
+          if (p_w > wrapRef.value.scrollLeft) {
+            wrapRef.value.scrollLeft++;
+          } else {
+            wrapRef.value.scrollLeft = 0
+          }
+        }, 30)
+      } else {
+        clearInterval(timer)
+        wrapRef.value.scrollLeft = 0
+        whetherToScroll = false
+      }
+    } else {
+      clearInterval(timer)
+    }
+
+  })
+
+}, {deep: true, immediate: true})
+
+
+onMounted(() => {
+  setCallback("systemAnnouncement", ({data: res}) => {
+    data = res
+  })
+
+  getSystemAnnouncement().then((res) => {
+    data = res
+  })
+
+})
+</script>
+
+<style scoped lang="scss">
+
+.red-point {
+  position: relative;
+}
+
+.red-point::before {
+  content: "*";
+  position: absolute;
+  color: red;
+  z-index: 1000;
+  right: 0;
+  top: -5px;
+
+  //margin-right: -8px;
+}
+
+.announcement {
+  display: flex;
+  justify-content: center;
+  overflow: hidden;
+  padding: 5px;
+
+  .ad {
+    width: 70%;
+    background-color: #e6a23c;
+    align-items: center;
+    display: flex;
+    border-radius: 8px;
+    box-sizing: border-box;
+    justify-content: flex-start;
+    font-size: 16px;
+    color: #353535;
+    cursor: pointer;
+    box-shadow: 2px 1px 8px 1px rgb(228, 232, 235);
+    padding: 5px;
+
+    i {
+      color: white;
+    }
+
+    .wrap {
+      margin-left: 3px;
+      font-size: 14px;
+      color: #333;
+      white-space: nowrap;
+      overflow: hidden;
+
+      p {
+        color: white;
+        margin: 0;
+        padding: 0;
+        display: inline-block;
+      }
+    }
+  }
+}
+
+</style>

+ 49 - 55
src/layout/Header/index.vue

@@ -3,27 +3,34 @@
     <div class="left-box">
       <!-- 收缩按钮 -->
       <div class="menu-icon" @click="opendStateChange">
-        <el-icon><Expand v-if="isCollapse" /><Fold v-else /></el-icon>
+        <el-icon>
+          <Expand v-if="isCollapse"/>
+          <Fold v-else/>
+        </el-icon>
       </div>
-      <Breadcrumb />
+      <Breadcrumb/>
+    </div>
+
+    <div style="flex: 1">
+      <scroll-notifications/>
     </div>
     <div class="right-box">
       <!-- 快捷功能按钮 -->
       <div class="function-list">
         <div class="function-list-item">
-          <Download />
+          <Download/>
         </div>
         <div class="function-list-item">
-          <Message />
+          <Message/>
         </div>
         <div class="function-list-item">
-          <Full-screen />
+          <Full-screen/>
         </div>
         <div class="function-list-item">
-          <SizeChange />
+          <SizeChange/>
         </div>
         <div class="function-list-item">
-          <Theme />
+          <Theme/>
         </div>
       </div>
       <!-- 用户信息 -->
@@ -32,7 +39,7 @@
         <el-dropdown>
           <span class="el-dropdown-link">
             {{ username }}
-            <el-icon><ArrowDown /></el-icon>
+            <el-icon><ArrowDown/></el-icon>
           </span>
           <template #dropdown>
             <el-dropdown-menu>
@@ -42,14 +49,14 @@
           </template>
         </el-dropdown>
       </div>
-      <password-layer v-if="layer.show" :layer="layer" />
+      <password-layer v-if="layer.show" :layer="layer"/>
     </div>
   </header>
 </template>
 
-<script>
-import { computed, defineComponent, reactive } from 'vue'
-import { useStore } from 'vuex'
+<script setup>
+import {computed, reactive} from 'vue'
+import {useStore} from 'vuex'
 import Download from './functionList/download.vue'
 import Message from './functionList/message.vue'
 import FullScreen from './functionList/fullscreen.vue'
@@ -57,53 +64,35 @@ import SizeChange from './functionList/sizeChange.vue'
 import Theme from './functionList/theme.vue'
 import Breadcrumb from './Breadcrumb.vue'
 import PasswordLayer from './passwordLayer.vue'
+import ScrollNotifications from "@/layout/Header/functionList/ScrollNotifications.vue";
 
-export default defineComponent({
-  components: {
-    Download,
-    Message,
-    FullScreen,
-    Breadcrumb,
-    SizeChange,
-    Theme,
-    PasswordLayer,
-  },
-  setup() {
-    const store = useStore()
-    const username = computed(() => {
-      return store.getters['user/info'].name
-    })
-
-    const ybCode = computed(() => {
-      return store.getters['user/info'].ybCode
-    })
-    const layer = reactive({
-      show: false,
-      showButton: true,
-    })
-    const isCollapse = computed(() => store.state.app.isCollapse)
-    const opendStateChange = () => {
-      store.commit('app/isCollapseChange', !isCollapse.value)
-    }
 
-    const loginOut = () => {
-      store.dispatch('user/loginOut')
-    }
+const store = useStore()
+const username = computed(() => {
+  return store.getters['user/info'].name
+})
 
-    const showPasswordLayer = () => {
-      layer.show = true
-    }
-    return {
-      isCollapse,
-      layer,
-      username,
-      opendStateChange,
-      loginOut,
-      showPasswordLayer,
-      ybCode,
-    }
-  },
+const ybCode = computed(() => {
+  return store.getters['user/info'].ybCode
+})
+const layer = reactive({
+  show: false,
+  showButton: true,
 })
+const isCollapse = computed(() => store.state.app.isCollapse)
+const opendStateChange = () => {
+  store.commit('app/isCollapseChange', !isCollapse.value)
+}
+
+const loginOut = () => {
+  store.dispatch('user/loginOut')
+}
+
+const showPasswordLayer = () => {
+  layer.show = true
+}
+
+
 </script>
 
 <style scoped>
@@ -116,6 +105,8 @@ export default defineComponent({
 </style>
 
 <style lang="scss" scoped>
+
+
 header {
   display: flex;
   justify-content: space-between;
@@ -151,11 +142,13 @@ header {
   }
 }
 
+
 .right-box {
   display: flex;
   justify-content: center;
   align-items: center;
 
+
   .function-list {
     display: flex;
 
@@ -164,6 +157,7 @@ header {
       display: flex;
       justify-content: center;
       align-items: center;
+
       :hover {
         cursor: pointer;
       }

+ 17 - 0
src/utils/request.js

@@ -6,6 +6,21 @@ import {startLoading, endLoading} from './loading'
 
 let loginBox = null
 
+let popUps = null
+
+const createAPopup = (message = '错误信息') => {
+    if (popUps !== null) {
+        return
+    }
+    popUps = ElMessageBox.alert(message, '提示', {
+        type: "error",
+    }).then(() => {
+        popUps = null
+    }).catch(() => {
+        popUps = null
+    })
+}
+
 const service = axios.create({
     baseURL: import.meta.env.VITE_BASE_URL,
     withCredentials: true,
@@ -89,6 +104,8 @@ service.interceptors.response.use(
                     router.push('/login')
                 })
             }
+        } else if (response.data.code === 5001) {
+            createAPopup(response.data.message)
         }
         if (response.data.data) {
             return Promise.reject(response.data)

+ 128 - 66
src/views/settings/SendNotification.vue

@@ -1,92 +1,154 @@
 <template>
   <el-container>
     <el-main>
-      <div style="width: 300px; padding: 20px">
-        <div style="font-size: 14px; font-weight: bold; padding: 8px 0"><i class="el-icon-user"></i>当前在线人数:{{ onlineCount }}</div>
-        <div class="dj-center-box-content">
-          <el-input type="textarea" :rows="3" v-model="param.message" placeholder="在此输入要发送的消息。"></el-input>
-          <div style="height: 10px"></div>
-          <el-input type="number" size="small" v-model="param.refreshDelay" style="width: 150px" placeholder="不刷新请勿填写"></el-input>&nbsp;秒后刷新全体连接
-        </div>
-        <div style="margin-top: 12px">
-          <el-button type="primary" icon="Upload2" @click="beforeSend">发送消息</el-button>
-        </div>
-      </div>
+
+      <el-row :gutter="4">
+        <el-col :span="12">
+          <el-card>
+            <template #header>
+              <div class="card-header">
+            <span>
+              发送全体通知
+            </span>
+                <span>
+               当前在线人数:{{ onlineCount }}
+            </span>
+              </div>
+            </template>
+            <el-input type="textarea" :rows="3" v-model="param.message" placeholder="在此输入要发送的消息。"></el-input>
+            <div style="height: 10px"></div>
+            <el-input type="number" size="small" v-model="param.refreshDelay" style="width: 150px"
+                      placeholder="不刷新请勿填写"></el-input>&nbsp;秒后刷新全体连接
+            <div style="margin-top: 12px">
+              <el-button type="primary" icon="Upload" @click="beforeSend">发送消息</el-button>
+            </div>
+          </el-card>
+        </el-col>
+        <el-col :span="12">
+          <el-card>
+            <template #header>
+              发送系统更新消息
+            </template>
+            <el-input type="textarea" :rows="3" v-model="systemUpdatesMessage"
+                      clearable
+                      placeholder="在此输入要发送的消息,如果不填写就是清空消息。"/>
+            <div style="margin-top: 12px">
+              <el-button type="primary" icon="Upload" @click="clickSendUpdateMessage">发送消息</el-button>
+            </div>
+          </el-card>
+        </el-col>
+        <el-col :span="12" style="margin-top: 10px">
+          <el-card>
+            <template #header>
+              发送滚动通知
+            </template>
+            <el-input type="textarea" :rows="3" v-model="scrollingMessage"
+                      clearable
+                      placeholder="在此输入要发送的消息,如果不填写就是清空消息。"/>
+            <div style="margin-top: 12px">
+              <el-button type="primary" icon="Upload" @click="clickSendScrollingMessages">发送消息</el-button>
+            </div>
+          </el-card>
+        </el-col>
+      </el-row>
+
     </el-main>
   </el-container>
 </template>
 
-<script>
-import { onMounted, ref, computed, reactive } from 'vue'
-import { getOnlineCount, sendMessageToAll } from '@/api/settings/send-notification'
-import { ElMessage, ElMessageBox } from 'element-plus'
+<script setup>
+import {onMounted, ref, computed, reactive} from 'vue'
+import {
+  getOnlineCount,
+  sendMessageToAll,
+  sendScrollingMessages,
+  sendSystemUpdatesMessage
+} from '@/api/settings/send-notification'
+import {ElMessage, ElMessageBox} from 'element-plus'
 import store from '@/store'
-export default {
-  setup() {
-    const isCollapse = computed(() => {
-      return store.state.isCollapse
-    })
-    const left = computed(() => {
-      return isCollapse.value ? '65px' : '220px'
+import {getSystemAnnouncement} from "@/api/public-api";
+
+const isCollapse = computed(() => {
+  return store.state.isCollapse
+})
+const left = computed(() => {
+  return isCollapse.value ? '65px' : '220px'
+})
+const onlineCount = ref(10)
+const param = reactive({
+  message: null,
+  refreshDelay: null,
+})
+
+const beforeSend = () => {
+  if (!param.message) {
+    ElMessage({
+      message: '消息体不能为空!',
+      type: 'warning',
+      duration: 2500,
+      showClose: true,
     })
-    const onlineCount = ref(10)
-    const param = reactive({
-      message: null,
-      refreshDelay: null,
+  } else {
+    ElMessageBox.confirm('确定要发送以下消息吗:' + param.message, '提示', {
+      type: 'info',
+      confirmButtonText: '发送',
+      cancelButtonText: '取消',
     })
-
-    const beforeSend = () => {
-      if (!param.message) {
-        ElMessage({
-          message: '消息体不能为空!',
-          type: 'warning',
-          duration: 2500,
-          showClose: true,
-        })
-      } else {
-        ElMessageBox.confirm('确定要发送以下消息吗:' + param.message, '提示', {
-          type: 'info',
-          confirmButtonText: '发送',
-          cancelButtonText: '取消',
-        })
-          .then(() => {
-            sendMessageToAll(param).then(() => {
-              ElMessage({
-                message: '发送成功。',
-                type: 'success',
-                duration: 2500,
-                showClose: true,
-              })
+        .then(() => {
+          sendMessageToAll(param).then(() => {
+            ElMessage({
+              message: '发送成功。',
+              type: 'success',
+              duration: 2500,
+              showClose: true,
             })
           })
-          .catch(() => {})
-      }
-    }
-    const dialogVisible = true
-    onMounted(() => {
-      getOnlineCount().then((res) => {
-        onlineCount.value = res
-      })
-    })
-    return {
-      left,
-      dialogVisible,
-      onlineCount,
-      param,
-      beforeSend,
-    }
-  },
+        })
+        .catch(() => {
+        })
+  }
 }
+const dialogVisible = true
+
+const systemUpdatesMessage = ref('')
+const clickSendUpdateMessage = () => {
+  sendSystemUpdatesMessage(systemUpdatesMessage.value)
+}
+
+const scrollingMessage = ref('')
+const clickSendScrollingMessages = () => {
+  sendScrollingMessages(scrollingMessage.value)
+}
+
+onMounted(() => {
+  getOnlineCount().then((res) => {
+    onlineCount.value = res
+  })
+  getSystemAnnouncement().then((res) => {
+    systemUpdatesMessage.value = res.systemUpdatesMessage
+    scrollingMessage.value = res.scrollingMessages
+  })
+})
+
 </script>
 
 <style scoped>
+.card-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
+
+
 /* 去掉input number的上下箭头 */
 :deep(input::-webkit-outer-spin-button) {
   -webkit-appearance: none !important;
 }
+
 :deep(input::-webkit-inner-spin-button) {
   -webkit-appearance: none !important;
 }
+
 :deep(input[type='number']) {
   -moz-appearance: textfield !important;
 }