Răsfoiți Sursa

Merge branch 'dev' of United_Software/k_online_ui into test

Jack Zhou 7 luni în urmă
părinte
comite
0fce0e761b

+ 1 - 0
package.json

@@ -40,6 +40,7 @@
     "vue-draggable-plus": "^0.5.3",
     "vue-router": "^4.3.3",
     "vue3-puzzle-vcode": "^1.1.7",
+    "vue3-virtual-scroller": "^0.2.3",
     "vuedraggable": "^2.24.3",
     "vxe-pc-ui": "^4.1.7",
     "vxe-table": "^4.7.70",

+ 2 - 1
src/auto-imports.d.ts

@@ -3,6 +3,7 @@
 // @ts-nocheck
 // noinspection JSUnusedGlobalSymbols
 // Generated by unplugin-auto-import
+// biome-ignore lint: disable
 export {}
 declare global {
   const $api: typeof import('@/api/index')['default']
@@ -68,6 +69,6 @@ declare global {
 // for type re-export
 declare global {
   // @ts-ignore
-  export type { Component, ComponentPublicInstance, ComputedRef, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, VNode, WritableComputedRef } from 'vue'
+  export type { Component, ComponentPublicInstance, ComputedRef, DirectiveBinding, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, MaybeRef, MaybeRefOrGetter, VNode, WritableComputedRef } from 'vue'
   import('vue')
 }

+ 73 - 28
src/components/NotificationMessageCard/src/NotificationMessageCard.vue

@@ -4,17 +4,23 @@ import PasswordCard from './components/PasswordCard.vue'
 import FeatureUpdateCard from './components/FeatureUpdateCard.vue'
 import { useNotificationMessage } from '@/stores/modules/notificationMessage'
 import { cloneDeep } from 'lodash'
+import { DynamicScroller, DynamicScrollerItem } from 'vue3-virtual-scroller'
+import 'vue3-virtual-scroller/dist/vue3-virtual-scroller.css'
 
 const notificationMsgStore = useNotificationMessage()
 const props = withDefaults(
   defineProps<{
     data: any
     isObserver?: boolean // 是否开启监听
+    isScrollPadding?: boolean // 是否有padding
     updateReadCardsOnChange?: boolean // 是否在数据变化时请求接口更新已读卡片
+    topOffset?: number // 应减去高度
   }>(),
   {
     isObserver: true,
-    updateReadCardsOnChange: true
+    isScrollPadding: false,
+    updateReadCardsOnChange: true,
+    topOffset: 220
   }
 )
 const pageData = ref<any[]>([])
@@ -101,14 +107,19 @@ const compareIdsInArrays = (arr1, arr2) => {
   return true
 }
 
+const handleData = (data) => {
+  data.map((item) => {
+    item.id = String(Math.random()).slice(-10)
+  })
+  return data
+}
 const initData = () => {
   const watchOptions = { deep: true, immediate: true }
-
   const handleDataChange = (newData, oldData) => {
     // 如果id相等,则不需要更新页面数据
     if (compareIdsInArrays(oldData || [], newData || [])) return
 
-    pageData.value = cloneDeep(newData)
+    pageData.value = handleData(cloneDeep(newData))
 
     // 清除旧数据中的卡片监听
     clearReadData(oldData)
@@ -120,22 +131,26 @@ const initData = () => {
 
     // 重新监听新数据中的卡片
     nextTick(() => {
-      watchCards()
+      setTimeout(() => {
+        watchCards()
+      }, 500)
     })
   }
+  // 需要监听卡片已读未读状态
   if (props.isObserver) {
     watch(
       () => props.data,
-      (newData, oldData) => {
-        handleDataChange(newData, oldData)
+      (newVal, oldVal) => {
+        handleDataChange(newVal, oldVal)
       },
       watchOptions
     )
   } else {
+    // 不需要监听
     watch(
       () => props.data,
       (newVal) => {
-        pageData.value = cloneDeep(newVal)
+        pageData.value = handleData(cloneDeep(newVal))
       },
       watchOptions
     )
@@ -172,30 +187,60 @@ onUnmounted(() => {
 const handleViewMore = () => {
   emit('viewMore')
 }
+const parentHeight = computed(() => {
+  return (window.innerHeight || document.documentElement.clientHeight) - props.topOffset
+})
+const scrollParentBoxStyle = computed(() => {
+  console.log(props.topOffset, 'value')
+  return props.topOffset ? { height: `${parentHeight.value}px` } : {}
+})
 </script>
 
 <template>
-  <div
-    class="notification-message-card"
-    :data-card-id="item.info.id"
-    :data-card-isread="item.info.isRead"
-    v-for="item in pageData"
-    :key="item.info.id || Math.random()"
+  <DynamicScroller
+    class="scroller"
+    :style="scrollParentBoxStyle"
+    :items="pageData"
+    :min-item-size="100"
+    key-field="id"
   >
-    <EventCard
-      @seeAll="handleSeeAll"
-      @jump-tracking="emit('jumpTracking')"
-      v-if="item.notificationType === 'event'"
-      :data="item.info"
-    />
-    <PasswordCard v-else-if="item.notificationType === 'password'" :data="item.info" />
-    <FeatureUpdateCard
-      @view-more="handleViewMore"
-      v-else-if="item.notificationType === 'feature'"
-      :data="item.info"
-    />
-    <slot></slot>
-  </div>
+    <template v-slot="{ item, index, active }">
+      <DynamicScrollerItem
+        :class="{ 'scroll-padding': props.isScrollPadding }"
+        :item="item"
+        :active="active"
+        :size-dependencies="[item.info.isRead]"
+      >
+        <div
+          class="notification-message-card"
+          :data-card-id="item.info.id"
+          :data-card-isread="item.info.isRead"
+        >
+          <EventCard
+            @seeAll="handleSeeAll"
+            @jump-tracking="emit('jumpTracking')"
+            v-if="item.notificationType === 'event'"
+            :data="item.info"
+          />
+          <PasswordCard v-else-if="item.notificationType === 'password'" :data="item.info" />
+          <FeatureUpdateCard
+            @view-more="handleViewMore"
+            v-else-if="item.notificationType === 'feature'"
+            :data="item.info"
+          />
+          <slot></slot>
+        </div>
+      </DynamicScrollerItem>
+    </template>
+  </DynamicScroller>
 </template>
 
-<style lang="scss" scoped></style>
+<style lang="scss" scoped>
+.scroller {
+  width: 100%;
+  overflow-y: auto;
+  .scroll-padding {
+    padding: 10px 140px 0px 16px;
+  }
+}
+</style>

+ 2 - 0
src/views/Layout/src/components/Header/components/NotificationDrawer.vue

@@ -133,6 +133,7 @@ const notificationMessageCardsRef = ref()
             @view-more="drawerRef.handleClose()"
             @jump-tracking="drawerRef.handleClose()"
             :data="notificationList"
+            :topOffset="185"
             ref="notificationMessageCardsRef"
           />
         </div>
@@ -143,6 +144,7 @@ const notificationMessageCardsRef = ref()
 <style lang="scss" scoped>
 div.layout-toolbar {
   .notification-content {
+    height: calc(100% - 40px);
     padding: 16px;
     background-color: var(--color-dialog-body-bg);
   }

+ 2 - 2
src/views/Layout/src/components/Header/components/TrainingCard.vue

@@ -118,8 +118,6 @@ const closeMessage = () => {
   if (result) {
     trainingIntervalId = setInterval(nextNotification, 2000)
   }
-  // 将当前消息标记为已读
-  // notificationMsgStore.setReadCardMap(curCard.value?.info?.id)
 }
 </script>
 
@@ -136,6 +134,7 @@ const closeMessage = () => {
       :isObserver="false"
       v-if="curCard"
       :data="[curCard]"
+      :topOffset="0"
     ></NotificationMessageCard>
   </div>
 </template>
@@ -160,6 +159,7 @@ const closeMessage = () => {
     padding-bottom: 0px;
     font-size: 18px;
     cursor: pointer;
+    z-index: 3000;
   }
 }
 </style>

+ 6 - 2
src/views/SystemMessage/src/SystemMessage.vue

@@ -171,11 +171,12 @@ onMounted(() => {
             <template #label>
               <span style="margin-right: 4px">All Notifications</span>
             </template>
-            <div style="padding: 10px 140px 0px 16px" v-if="activeTabName === 'All Notifications'">
+            <div style="padding-bottom: 20px" v-if="activeTabName === 'All Notifications'">
               <NotificationMessageCard
                 v-if="activeTabName === 'All Notifications'"
                 :data="notificationList"
                 @hasCardRead="changeCardRead"
+                :isScrollPadding="true"
                 :updateReadCardsOnChange="false"
               ></NotificationMessageCard>
             </div>
@@ -195,6 +196,7 @@ onMounted(() => {
               <NotificationMessageCard
                 v-if="activeTabName === 'Unread'"
                 :data="unreadNotificationList"
+                :isScrollPadding="true"
                 :updateReadCardsOnChange="false"
               ></NotificationMessageCard>
             </div>
@@ -205,6 +207,7 @@ onMounted(() => {
               <NotificationMessageCard
                 v-if="activeTabName === 'Read'"
                 :updateReadCardsOnChange="false"
+                :isScrollPadding="true"
                 :data="readNotificationList"
               >
               </NotificationMessageCard>
@@ -313,9 +316,10 @@ onMounted(() => {
     }
   }
   :deep(.el-tabs) {
-    height: calc(100%);
+    height: 100%;
     .el-tabs__content {
       overflow-y: auto;
+      height: 100%;
     }
   }
 }

+ 2 - 1
src/views/SystemMessage/src/components/SystemMessageDetail.vue

@@ -144,12 +144,13 @@ const handleIframeLoaded = () => {
       width: 8px;
       height: 8px;
       border-radius: 50%;
-      background-color: var(--color-theme);
+      background-color: var(--color-border);
       margin-right: 10px;
     }
     .title {
       font-weight: 700;
       font-size: 24px;
+      color: #b5b9bf;
     }
   }
   .total-tips {