Przeglądaj źródła

后台任务socket

xiaochan 4 miesięcy temu
rodzic
commit
881ed1a934

+ 2 - 0
src/App.vue

@@ -3,6 +3,7 @@
   <SocketDialog v-if="socketErrDialog" />
   <progress-bar />
   <CyDialogV2 />
+  <BackgroundTask />
 </template>
 
 <script setup lang="jsx">
@@ -20,6 +21,7 @@ import { useUserStore } from "@/pinia/user-store";
 import { useSystemStore } from "@/pinia/system-store";
 import useChangeToken from "@/utils/cy-use/useChangeToken";
 import CyDialogV2 from "@/components/cy/CyDialog/index.vue";
+import BackgroundTask from "@/layout/HeaderV2/BackgroundTask.vue";
 
 const progressBarStore = useProgressBarStore();
 const systemStore = useSystemStore();

+ 84 - 0
src/layout/HeaderV2/BackgroundTask.vue

@@ -0,0 +1,84 @@
+<script setup lang="ts">
+import { setCallback } from "@/utils/websocket";
+
+type TaskValue = {
+  percentage?: number;
+  status?: "success" | "exception" | "warning";
+  name?: string;
+  textInside?: boolean;
+  strokeWidth?: number;
+  id: string;
+};
+
+const store: {
+  [key: string]: TaskValue;
+} = reactive({
+  test: {
+    name: "TaskValue",
+    id: "test",
+    percentage: 10,
+  },
+});
+
+function handleClose(data: TaskValue) {
+  const key = data.id || data.name;
+  delete store[key];
+}
+
+onMounted(() => {
+  setCallback("backgroundTask", data => {
+    data = JSON.parse(data);
+    const key = data.id || data.name;
+    if (store[key]) {
+      store[key] = data;
+    } else {
+      store[data.id || data.name] = data;
+    }
+  });
+});
+</script>
+
+<template>
+  <teleport to="body">
+    <div class="system_background-task">
+      <div v-for="item in store" class="system_background-task-item">
+        <div style="font-size: 18px; margin-bottom: 5px">{{ item.name }}:</div>
+        <div class="system_background-task-item_progress">
+          <el-progress
+            style="width: 240px"
+            striped
+            :percentage="item.percentage"
+            :status="item.status || ''"
+            :text-inside="item.textInside || false"
+            :stroke-width="item.strokeWidth || 15"
+          />
+          <div>
+            <el-button
+              icon="CircleClose"
+              circle
+              @click="handleClose(item)"
+            ></el-button>
+          </div>
+        </div>
+      </div>
+    </div>
+  </teleport>
+</template>
+
+<style lang="scss">
+.system_background-task {
+  position: fixed;
+  right: 10px;
+  bottom: 10px;
+  box-shadow: var(--el-box-shadow);
+  background-color: white;
+  padding: 10px;
+  border-radius: 10px;
+
+  .system_background-task-item_progress {
+    height: 100%;
+    display: flex;
+    align-items: center;
+  }
+}
+</style>

+ 68 - 67
src/layout/HeaderV2/Notice.vue

@@ -1,25 +1,27 @@
 <template>
   <transition name="notice_an">
-    <div class="notice__content"
-         :title="msg.msg"
-         v-show="isShow"
-         @mouseout="mouseEvent(false)"
-         @mouseover="mouseEvent(true)">
+    <div
+      class="notice__content"
+      :title="msg.msg"
+      v-show="isShow"
+      @mouseout="mouseEvent(false)"
+      @mouseover="mouseEvent(true)"
+    >
       <div class="notice__img">
-        <el-avatar shape="square" size="large" :src="msg.avatar"/>
+        <el-avatar shape="square" size="large" :src="msg.avatar" />
       </div>
       <div class="notice__main">
         <div class="notice__name">
-        <span style="color: #E6A23C">
-          {{ msg.title }}
-        </span>
-          <br>
+          <span style="color: #e6a23c">
+            {{ msg.title }}
+          </span>
+          <br />
           <span style="color: red">
-          {{ msg.deptName }}
-        </span>
-          <span style="color: #0a84fd;margin-left: 3px">
-         {{ msg.name }}
-        </span>
+            {{ msg.deptName }}
+          </span>
+          <span style="color: #0a84fd; margin-left: 3px">
+            {{ msg.name }}
+          </span>
         </div>
         <div class="notice__msg">
           {{ msg.msg }}
@@ -30,94 +32,94 @@
 </template>
 
 <script setup lang="ts">
-import {onMounted, ref} from 'vue'
+import { onMounted, ref } from "vue";
 import sleep from "@/utils/sleep";
-import {setCallback} from '@/utils/websocket'
-import {isDev} from '@/utils/public'
+import { setCallback } from "@/utils/websocket";
+import { isDev } from "@/utils/public";
 import Queue from "@/utils/my-queue";
-import {useSystemStore} from "@/pinia/system-store";
+import { useSystemStore } from "@/pinia/system-store";
 
-const isShow = ref(false)
-const displaySeconds = 1000 * 2
-const isMouse = ref(false)
+const isShow = ref(false);
+const displaySeconds = 1000 * 2;
+const isMouse = ref(false);
 
 interface Msg {
-  avatar: string
-  deptName: string
-  name: string
-  msg: string
-  title: string
-  countDown: number,
+  avatar: string;
+  deptName: string;
+  name: string;
+  msg: string;
+  title: string;
+  countDown: number;
 }
 
 const msg = ref<Msg>({
-  avatar: '',
-  deptName: '',
-  name: '',
-  msg: '',
-  title: '',
+  avatar: "",
+  deptName: "",
+  name: "",
+  msg: "",
+  title: "",
   countDown: 2,
-})
+});
 
-let queue = new Queue<Msg>()
+let queue = new Queue<Msg>();
 const fillData = async () => {
-  let temp = queue.poll()
+  let temp = queue.poll();
   if (temp === null) {
-    return
+    return;
   }
-  isShow.value = true
+  isShow.value = true;
   msg.value = temp;
   // 显示时间
   await sleep(displaySeconds);
   // 鼠标移入等待
   do {
-    await sleep(100)
-  } while (isMouse.value)
+    await sleep(100);
+  } while (isMouse.value);
   // 关闭
   isShow.value = false;
   // 等待关闭动画结束
   await sleep(500);
   // 如果还有数据就执行自己,没有数据的结束
   if (queue.size() > 0) {
-    await fillData()
+    await fillData();
   } else {
-    open = true
+    open = true;
   }
-}
+};
 
-const mouseEvent = (flag) => {
-  isMouse.value = flag
-}
+const mouseEvent = flag => {
+  isMouse.value = flag;
+};
 
 const test = () => {
   if (isDev) {
     let value = {
-      avatar: 'https://wework.qpic.cn/wwpic/116107_NK-ZuOg-RDW8Cej_1690480036/0',
-      deptName: '测试',
-      name: '测试发送',
-      msg: '阿三发射点',
-      title: 'title',
+      avatar:
+        "https://wework.qpic.cn/wwpic/116107_NK-ZuOg-RDW8Cej_1690480036/0",
+      deptName: "测试",
+      name: "测试发送",
+      msg: "阿三发射点",
+      title: "title",
       countDown: 2,
-    }
-    queue.enqueue(value)
-    fillData()
+    };
+    queue.enqueue(value);
+    fillData();
   }
-}
+};
 
 // 是否开启显示通知
-let open = true
+let open = true;
 onMounted(() => {
-  setCallback('avatarNotification', async (value) => {
-    useSystemStore().addUnreadMessageCount(value.count)
+  setCallback("avatarNotification", async value => {
+    useSystemStore().addUnreadMessageCount(value.count);
     // 把消息放到队列中
-    queue.enqueue(value)
+    queue.enqueue(value);
     if (open) {
-      open = false
-      await fillData()
+      open = false;
+      await fillData();
     }
-  })
-})
-
+  });
+});
 </script>
 
 <style scoped lang="scss">
@@ -139,7 +141,6 @@ $img_size: 50px;
   z-index: 99;
   box-shadow: var(--el-box-shadow-dark);
 
-
   .notice__img {
     width: $img_size;
     height: $img_size;
@@ -171,11 +172,11 @@ $img_size: 50px;
 }
 
 .notice_an-leave-active {
-  animation: notice .2s reverse;
+  animation: notice 0.2s reverse;
 }
 
 .notice_an-enter-active {
-  animation: notice .2s;
+  animation: notice 0.2s;
 }
 
 @keyframes notice {

+ 63 - 68
src/layout/HeaderV2/ScrollNotifications.vue

@@ -3,23 +3,21 @@
     <el-popover :width="220">
       <div v-if="data.systemUpdatesMessage">
         系统更新通知:
-        <span style="color: red;text-decoration: underline">
+        <span style="color: red; text-decoration: underline">
           {{ data.systemUpdatesMessage }}
-          </span>
-        <br>
+        </span>
+        <br />
         <span style="color: red">
-          <span class="red-point">
-            注意
-          </span>
-            系统更新期间请勿操作
-          </span>
+          <span class="red-point"> 注意 </span>
+          系统更新期间请勿操作
+        </span>
       </div>
       普通通知: {{ data.scrollingMessages }}
       <template #reference>
         <div class="scroll_system_box">
-          <i class="iconfont icon-tongzhi"/>
+          <i class="iconfont icon-tongzhi" />
           <transition name="el-zoom-in-top">
-            <div class='ad' ref="adRef"/>
+            <div class="ad" ref="adRef" />
           </transition>
         </div>
       </template>
@@ -27,68 +25,69 @@
   </div>
 </template>
 
-<script setup name='ScrollNotifications' lang="ts">
-import {ref, onMounted, Ref, nextTick, watch} from "vue";
-import {setCallback} from "@/utils/websocket";
-import {getSystemAnnouncement} from "@/api/public-api";
+<script setup name="ScrollNotifications" lang="ts">
+import { ref, onMounted, Ref, nextTick, watch } from "vue";
+import { setCallback } from "@/utils/websocket";
+import { getSystemAnnouncement } from "@/api/public-api";
 
 const props = defineProps({
-  data: Object
-})
-const adRef: Ref<HTMLElement> = ref(null)
+  data: Object,
+});
+const adRef: Ref<HTMLElement> = ref(null);
 
 const scrollStyle: object = ref({
-  '--xc-translateX': 0,
-  '--xc-width': 40,
-})
-let marginRight = 40
-
+  "--xc-translateX": 0,
+  "--xc-width": 40,
+});
+let marginRight = 40;
 
 const data = ref({
-  systemUpdatesMessage: '',
-  scrollingMessages: ''
-})
-
-watch(() => data.value, async () => {
-  await nextTick()
-  if (data.value.systemUpdatesMessage || data.value.scrollingMessages) {
-    adRef.value.style.display = null
-    scrollStyle.value['--xc-width'] = 'max-content'
-  } else {
-    adRef.value.style.display = 'none'
-    scrollStyle.value['--xc-width'] = '30px'
-  }
-  adRef.value.innerHTML = null
-  let div1 = document.createElement('div')
-  let html = `
-    <span style="color: red">${data.value.systemUpdatesMessage ? data.value.systemUpdatesMessage : ''}</span>
-    <span style="color: #0a84fd">${data.value.scrollingMessages ? data.value.scrollingMessages : ''}</span>
-  `
-  div1.innerHTML = html
-  adRef.value.append(div1)
-  let width = div1.clientWidth
-  if (width >= 220) {
-    div1.style.marginRight = '40px'
-    div1.className = 'scroll_system_message'
-    await nextTick()
-    scrollStyle.value['--xc-translateX'] = -(width + marginRight) + 'px'
-    let div2 = document.createElement('div')
-    div2.innerHTML = html
-    div2.className = 'scroll_system_message'
-    adRef.value.append(div2)
-  }
-}, {immediate: true})
-
+  systemUpdatesMessage: "",
+  scrollingMessages: "",
+});
+
+watch(
+  () => data.value,
+  async () => {
+    await nextTick();
+    if (data.value.systemUpdatesMessage || data.value.scrollingMessages) {
+      adRef.value.style.display = null;
+      scrollStyle.value["--xc-width"] = "max-content";
+    } else {
+      adRef.value.style.display = "none";
+      scrollStyle.value["--xc-width"] = "30px";
+    }
+    adRef.value.innerHTML = null;
+    let div1 = document.createElement("div");
+    let html = `
+    <span style="color: red">${data.value.systemUpdatesMessage ? data.value.systemUpdatesMessage : ""}</span>
+    <span style="color: #0a84fd">${data.value.scrollingMessages ? data.value.scrollingMessages : ""}</span>
+  `;
+    div1.innerHTML = html;
+    adRef.value.append(div1);
+    let width = div1.clientWidth;
+    if (width >= 220) {
+      div1.style.marginRight = "40px";
+      div1.className = "scroll_system_message";
+      await nextTick();
+      scrollStyle.value["--xc-translateX"] = -(width + marginRight) + "px";
+      let div2 = document.createElement("div");
+      div2.innerHTML = html;
+      div2.className = "scroll_system_message";
+      adRef.value.append(div2);
+    }
+  },
+  { immediate: true }
+);
 
 onMounted(() => {
-  setCallback("systemAnnouncement", async ({data: res}) => {
-    data.value = res
-  })
-  getSystemAnnouncement().then((res) => {
-    data.value = res
-  })
-})
-
+  setCallback("systemAnnouncement", async ({ data: res }) => {
+    data.value = res;
+  });
+  getSystemAnnouncement().then(res => {
+    data.value = res;
+  });
+});
 </script>
 <style lang="scss">
 @keyframes move {
@@ -107,7 +106,6 @@ onMounted(() => {
 </style>
 
 <style scoped lang="scss">
-
 .scroll_system_box {
   display: flex;
   justify-content: center;
@@ -153,8 +151,5 @@ onMounted(() => {
     overflow: hidden;
     margin-left: 5px;
   }
-
-
 }
-
 </style>

+ 2 - 10
src/views/settings/permissions/RoleMenuSettings.vue

@@ -35,10 +35,7 @@
               ref="tree"
               :data="menus"
               :props="defaultProps"
-              :style="{
-                height: tableHeight - 40 - 15 + 'px',
-                overflowY: 'scroll',
-              }"
+              style="height: 100%; overflow: auto"
               show-checkbox
               node-key="id"
               default-expand-all
@@ -51,10 +48,7 @@
               default-expand-all
               node-key="id"
               ref="reportFormsTree"
-              :style="{
-                height: tableHeight - 40 - 15 + 'px',
-                overflowY: 'scroll',
-              }"
+              style="height: 100%; overflow: auto"
             >
               <template #default="{ node, data }">
                 <div :id="'report_forms-' + data.id">
@@ -90,8 +84,6 @@ import {
 import { Document, Folder } from "@element-plus/icons-vue";
 import { useCompRef } from "@/utils/useCompRef";
 
-const tableHeight = window.innerHeight - 10;
-
 const searchRoleContent = ref("");
 const roles = ref([]);
 const reportForms = ref([]);