Bläddra i källkod

添加通知功能

Yue 2 år sedan
förälder
incheckning
e4bdb12479
2 ändrade filer med 164 tillägg och 333 borttagningar
  1. 0 10
      src/layouts/main-layout/header/Navbar.vue
  2. 164 323
      src/layouts/main-layout/menus/NotificationsMenu.vue

+ 0 - 10
src/layouts/main-layout/header/Navbar.vue

@@ -26,16 +26,6 @@
     </div>
     <!--begin::Notifications-->
     <div class="app-navbar-item ms-1 ms-lg-3">
-      <div
-        class="btn btn-icon btn-custom btn-icon-muted btn-active-light btn-active-color-primary w-30px h-30px w-md-40px h-md-40px"
-        data-kt-menu-trigger="click"
-        data-kt-menu-attach="parent"
-        data-kt-menu-placement="bottom-end"
-      >
-        <span class="svg-icon svg-icon-1">
-          <inline-svg :src="getAssetPath('media/icons/duotune/general/gen022.svg')" />
-        </span>
-      </div>
       <KTNotificationMenu />
     </div>
     <!--end::Notifications-->

+ 164 - 323
src/layouts/main-layout/menus/NotificationsMenu.vue

@@ -1,335 +1,176 @@
+<script lang="ts" setup>
+import { ref, onMounted, computed, watch } from "vue"
+import { getAssetPath } from "@/core/helpers/assets"
+import Rs from "@/core/services/RequestService"
+import appStore from "@/stores"
+import router from "@/router"
+const total = ref(0)
+const curPage = ref(0)
+const perPage = ref(10)
+const params = computed(() => {
+  return {
+    pageIndex: curPage.value,
+    pageSize: perPage.value,
+    params: { readFlag: false },
+  }
+})
+let reLoadTimre: any
+const listBox = ref<HTMLElement>()
+const dataList = ref<Array<any>>([])
+function jump(item: any) {
+  read(item.id)
+  switch (appStore.authStore.user?.userType) {
+    case "2": //企业账号
+      if (item.eventType == "000100003" || item.eventType == "000100005" || item.eventType == "000100007") {
+        router.push({
+          path: "/Abnormal/AbnormalList/strongWarn",
+          query: {
+            id: item.warn_id,
+            type: item.eventType,
+          },
+        })
+      } else if (item.eventType == "000100006") {
+        router.push({
+          path: "/Abnormal/AbnormalList/disConnect",
+          query: {
+            id: item.warn_id,
+            type: item.eventType,
+          },
+        })
+      } else {
+        router.push({
+          path: "/Abnormal/AbnormalList/overdueWarn",
+          query: {
+            id: item.warn_id,
+            type: item.eventType,
+          },
+        })
+      }
+      break
+    case "0": //系统管理员
+    case "1": //政府账号
+    default:
+      if (item.eventType == "000100003" || item.eventType == "000100005" || item.eventType == "000100007") {
+        router.push({
+          path: "/warn/warnList/concentrationWarn",
+          query: {
+            id: item.warn_id,
+            type: item.eventType,
+          },
+        })
+      } else if (item.eventType == "000100006") {
+        router.push({
+          path: "/warn/warnList/offlineWarn",
+          query: {
+            id: item.warn_id,
+            type: item.eventType,
+          },
+        })
+      } else {
+        router.push({
+          path: "/warn/warnList/overdueWarn",
+          query: {
+            id: item.warn_id,
+            type: item.eventType,
+          },
+        })
+      }
+      break
+  }
+}
+function read(id: string) {
+  Rs.get(`sys/pushEvent/read?noticeId=${id}`).then(() => {
+    clearTimeout(reLoadTimre)
+    reLoad()
+  })
+}
+function readAll() {
+  Rs.get(`sys/pushEvent/clear`).then(() => {
+    clearTimeout(reLoadTimre)
+    reLoad()
+  })
+}
+function load() {
+  curPage.value++
+  Rs.post("sys/pushEvent/getList", { data: params.value, successAlert: false }).then((res: any) => {
+    console.log("NOTIFI", res.data)
+    dataList.value.push(...res.data)
+    total.value = res.total
+  })
+}
+function reLoad() {
+  curPage.value = 0
+  load()
+  dataList.value = []
+  reLoadTimre = setTimeout(reLoad, 1000 * 60 * 3)
+}
+const onScroll = () => {
+  if (listBox.value) {
+    const diff = listBox.value.scrollHeight - (listBox.value.scrollTop + listBox.value.clientHeight)
+    //console.log("TOP", diff, listBox.value?.scrollTop, listBox.value?.scrollHeight, listBox.value?.clientHeight)
+    if (diff <= 0) {
+      load()
+    }
+  }
+}
+watch(listBox, () => {
+  if (listBox.value) {
+    listBox.value.removeEventListener("scroll", onScroll, true)
+    listBox.value.addEventListener("scroll", onScroll, true)
+  }
+})
+onMounted(() => {
+  reLoad()
+})
+</script>
+
 <template>
-  <!--begin::Menu-->
-  <div class="menu menu-sub menu-sub-dropdown menu-column w-350px w-lg-375px" data-kt-menu="true">
-    <!--begin::Heading-->
+  <div
+    class="btn btn-icon btn-custom btn-icon-muted btn-active-light btn-active-color-primary w-30px h-30px w-md-40px h-md-40px position-relative"
+    data-kt-menu-trigger="click"
+    data-kt-menu-attach="parent"
+    data-kt-menu-placement="bottom-end"
+  >
+    <span class="svg-icon svg-icon-1">
+      <inline-svg :src="getAssetPath('media/icons/duotune/general/gen022.svg')" />
+    </span>
+    <span
+      v-if="total > 0"
+      class="bullet bullet-dot bg-warning h-6px w-6px position-absolute translate-middle top-0 start-50 animation-blink"
+    ></span>
+  </div>
+  <div class="menu menu-sub menu-sub-dropdown menu-column w-350px w-lg-400px" data-kt-menu="true">
     <div
       class="d-flex flex-column bgi-no-repeat rounded-top"
       :style="`background-image: url('${getAssetPath('/media/misc/menu-header-bg.jpg')}')`"
     >
-      <!--begin::Title-->
-      <h3 class="text-white fw-semobold px-9 mt-10 mb-6">
-        Notifications
-        <span class="fs-8 opacity-75 ps-3">24 reports</span>
+      <h3 class="text-white fw-semobold px-9 mt-10 mb-6 d-flex align-items-center justify-content-between">
+        <span>
+          消息通知
+          <span class="fs-8 opacity-75 ps-3" v-if="total > 0">{{ total }} 条</span>
+        </span>
+        <span class="svg-icon svg-icon-1 btn p-1" @click="readAll" v-tooltip title="清空通知">
+          <inline-svg :src="getAssetPath('media/icons/duotune/general/gen064.svg')" />
+        </span>
       </h3>
-      <!--end::Title-->
-
-      <!--begin::Tabs-->
-      <ul class="nav nav-line-tabs nav-line-tabs-2x nav-stretch fw-semobold px-9">
-        <li class="nav-item">
-          <a
-            class="nav-link text-white opacity-75 opacity-state-100 pb-4"
-            data-bs-toggle="tab"
-            href="#kt_topbar_notifications_1"
-          >
-            Alerts
-          </a>
-        </li>
-
-        <li class="nav-item">
-          <a
-            class="nav-link text-white opacity-75 opacity-state-100 pb-4 active"
-            data-bs-toggle="tab"
-            href="#kt_topbar_notifications_2"
-          >
-            Updates
-          </a>
-        </li>
-
-        <li class="nav-item">
-          <a
-            class="nav-link text-white opacity-75 opacity-state-100 pb-4"
-            data-bs-toggle="tab"
-            href="#kt_topbar_notifications_3"
-          >
-            Logs
-          </a>
-        </li>
-      </ul>
-      <!--end::Tabs-->
     </div>
-    <!--end::Heading-->
-
-    <!--begin::Tab content-->
-    <div class="tab-content">
-      <!--begin::Tab panel-->
-      <div class="tab-pane fade" id="kt_topbar_notifications_1" role="tabpanel">
-        <!--begin::Items-->
-        <div class="scroll-y mh-325px my-5 px-8">
-          <template v-for="(item, index) in data1" :key="index">
-            <!--begin::Item-->
-            <div class="d-flex flex-stack py-4">
-              <!--begin::Section-->
-              <div class="d-flex align-items-center">
-                <!--begin::Symbol-->
-                <div class="symbol symbol-35px me-4">
-                  <span :class="`bg-light-${item.state}`" class="symbol-label">
-                    <span :class="`svg-icon-${item.state}`" class="svg-icon svg-icon-2">
-                      <inline-svg :src="item.icon" />
-                    </span>
-                  </span>
-                </div>
-                <!--end::Symbol-->
-
-                <!--begin::Title-->
-                <div class="mb-0 me-2">
-                  <a href="#" class="fs-6 text-gray-800 text-hover-primary fw-bold">{{ item.title }}</a>
-                  <div class="text-gray-400 fs-7">
-                    {{ item.description }}
-                  </div>
-                </div>
-                <!--end::Title-->
-              </div>
-              <!--end::Section-->
-
-              <!--begin::Label-->
-              <span class="badge badge-light fs-8">{{ item.time }}</span>
-              <!--end::Label-->
-            </div>
-            <!--end::Item-->
-          </template>
-        </div>
-        <!--end::Items-->
-
-        <!--begin::View more-->
-        <div class="py-3 text-center border-top">
-          <a href="#" class="btn btn-color-gray-600 btn-active-color-primary">
-            View All
-            <span class="svg-icon svg-icon-5">
-              <inline-svg :src="getAssetPath('media/icons/duotune/arrows/arr064.svg')" />
-            </span>
-          </a>
-        </div>
-        <!--end::View more-->
-      </div>
-      <!--end::Tab panel-->
-
-      <!--begin::Tab panel-->
-      <div class="tab-pane fade show active" id="kt_topbar_notifications_2" role="tabpanel">
-        <!--begin::Wrapper-->
-        <div class="d-flex flex-column px-9">
-          <!--begin::Section-->
-          <div class="pt-10 pb-0">
-            <!--begin::Title-->
-            <h3 class="text-dark text-center fw-bold">Get Pro Access</h3>
-            <!--end::Title-->
-
-            <!--begin::Text-->
-            <div class="text-center text-gray-600 fw-semobold pt-1">
-              Outlines keep you honest. They stoping you from amazing poorly about drive
-            </div>
-            <!--end::Text-->
-
-            <!--begin::Action-->
-            <div class="text-center mt-5 mb-9">
-              <a
-                href="#"
-                class="btn btn-sm btn-primary px-6"
-                data-bs-toggle="modal"
-                data-bs-target="#kt_modal_upgrade_plan"
-              >
-                Upgrade
-              </a>
-            </div>
-            <!--end::Action-->
+    <div ref="listBox" v-if="dataList.length" class="h-500px overflow-auto p-2">
+      <template v-for="(v, i) in dataList" :key="i">
+        <div class="d-flex px-3 align-items-center" @click="jump(v)" style="cursor: pointer">
+          <span class="svg-icon svg-icon-1 svg-icon-warning ps-2 pe-5">
+            <inline-svg :src="getAssetPath('media/icons/duotune/abstract/abs038.svg')" />
+          </span>
+          <div class="d-flex flex-column">
+            <span class="text-gray-700">{{ v.content }}</span>
+            <span class="text-gray-600">{{ v.time }}</span>
           </div>
-          <!--end::Section-->
-
-          <!--begin::Illustration-->
-          <img class="mw-100 mh-200px" alt="metronic" :src="getIllustrationsPath('1.png')" />
-          <!--end::Illustration-->
-        </div>
-        <!--end::Wrapper-->
-      </div>
-      <!--end::Tab panel-->
-
-      <!--begin::Tab panel-->
-      <div class="tab-pane fade" id="kt_topbar_notifications_3" role="tabpanel">
-        <!--begin::Items-->
-        <div class="scroll-y mh-325px my-5 px-8">
-          <template v-for="(item, index) in data2" :key="index">
-            <!--begin::Item-->
-            <div class="d-flex flex-stack py-4">
-              <!--begin::Section-->
-              <div class="d-flex align-items-center me-2">
-                <!--begin::Code-->
-                <span class="w-70px badge me-4" :class="`badge-light-${item.state}`">{{ item.code }}</span>
-                <!--end::Code-->
-
-                <!--begin::Title-->
-                <a href="#" class="text-gray-800 text-hover-primary fw-semobold">{{ item.message }}</a>
-                <!--end::Title-->
-              </div>
-              <!--end::Section-->
-
-              <!--begin::Label-->
-              <span class="badge badge-light fs-8">{{ item.time }}</span>
-              <!--end::Label-->
-            </div>
-            <!--end::Item-->
-          </template>
-        </div>
-        <!--end::Items-->
-
-        <!--begin::View more-->
-        <div class="py-3 text-center border-top">
-          <a href="#" class="btn btn-color-gray-600 btn-active-color-primary">
-            View All
-            <span class="svg-icon-svg-icon-5">
-              <inline-svg :src="getAssetPath('media/icons/duotune/arrows/arr064.svg')" />
-            </span>
-          </a>
         </div>
-        <!--end::View more-->
-      </div>
-      <!--end::Tab panel-->
+        <div class="separator my-2"></div>
+      </template>
+    </div>
+    <div v-else class="h-150px d-flex justify-content-center flex-column align-items-center">
+      <img class="mb-2" :src="getAssetPath('media/table/empty.svg')" />
+      <span class="text-gray-500">暂无消息通知</span>
     </div>
-    <!--end::Tab content-->
   </div>
-  <!--end::Menu-->
 </template>
-
-<script lang="ts">
-import { getAssetPath } from "@/core/helpers/assets"
-import { defineComponent } from "vue"
-import { getIllustrationsPath } from "@/core/helpers/assets"
-
-export default defineComponent({
-  name: "notifications-menu",
-  components: {},
-  setup() {
-    const data1 = [
-      {
-        title: "Project Alice",
-        description: "Phase 1 development",
-        time: "1 hr",
-        icon: getAssetPath("media/icons/duotune/technology/teh008.svg"),
-        state: "primary",
-      },
-      {
-        title: "HR Confidential",
-        description: "Confidential staff documents",
-        time: "2 hrs",
-        icon: getAssetPath("media/icons/duotune/general/gen044.svg"),
-        state: "danger",
-      },
-      {
-        title: "Company HR",
-        description: "Corporeate staff profiles",
-        time: "5 hrs",
-        icon: getAssetPath("media/icons/duotune/finance/fin006.svg"),
-        state: "warning",
-      },
-      {
-        title: "Project Redux",
-        description: "New frontend admin theme",
-        time: "2 days",
-        icon: getAssetPath("media/icons/duotune/files/fil023.svg"),
-        state: "success",
-      },
-      {
-        title: "Project Breafing",
-        description: "Product launch status update",
-        time: "21 Jan",
-        icon: getAssetPath("media/icons/duotune/maps/map001.svg"),
-        state: "primary",
-      },
-      {
-        title: "Banner Assets",
-        description: "Collection of banner images",
-        time: "21 Jan",
-        icon: getAssetPath("media/icons/duotune/general/gen006.svg"),
-        state: "info",
-      },
-      {
-        title: "Icon Assets",
-        description: "Collection of SVG icons",
-        time: "20 March",
-        icon: getAssetPath("media/icons/duotune/art/art002.svg"),
-        state: "warning",
-      },
-    ]
-
-    const data2 = [
-      {
-        code: "200 OK",
-        state: "success",
-        message: "New order",
-        time: "Just now",
-      },
-      {
-        code: "500 ERR",
-        state: "danger",
-        message: "New customer",
-        time: "2 hrs",
-      },
-      {
-        code: "200 OK",
-        state: "success",
-        message: "Payment process",
-        time: "5 hrs",
-      },
-      {
-        code: "300 WRN",
-        state: "warning",
-        message: "Search query",
-        time: "2 days",
-      },
-      {
-        code: "200 OK",
-        state: "success",
-        message: "API connection",
-        time: "1 week",
-      },
-      {
-        code: "200 OK",
-        state: "success",
-        message: "Database restore",
-        time: "Mar 5",
-      },
-      {
-        code: "300 WRN",
-        state: "warning",
-        message: "System update",
-        time: "May 15",
-      },
-      {
-        code: "300 WRN",
-        state: "warning",
-        message: "Server OS update",
-        time: "Apr 3",
-      },
-      {
-        code: "300 WRN",
-        state: "warning",
-        message: "API rollback",
-        time: "Jun 30",
-      },
-      {
-        code: "500 ERR",
-        state: "danger",
-        message: "Refund process",
-        time: "Jul 10",
-      },
-      {
-        code: "500 ERR",
-        state: "danger",
-        message: "Withdrawal process",
-        time: "Sep 10",
-      },
-      {
-        code: "500 ERR",
-        state: "danger",
-        message: "Mail tasks",
-        time: "Dec 10",
-      },
-    ]
-
-    return {
-      data1,
-      data2,
-      getIllustrationsPath,
-      getAssetPath,
-    }
-  },
-})
-</script>