panhui пре 2 година
родитељ
комит
649b3e79b1

+ 2 - 2
src/components/common/CommentInfo.vue

@@ -12,8 +12,8 @@
                 <div class="flex mt-1 items-center">
                     <span class="text-xs text-[#797A8A]">16:00</span>
                     <span class="flex-1"></span>
-                    <img src="@/assets/icon_pingjia.png" class="w-[24px]" alt="" />
-                    <like-btn class="ml-[10px]"></like-btn>
+                    <!-- <img src="@/assets/icon_pingjia.png" class="w-[24px]" alt="" /> -->
+                    <like-btn class="ml-[10px]">{{ info.commentLikeCount }}</like-btn>
                 </div>
             </template>
         </n-thing>

+ 3 - 1
src/components/common/LikeBtn.vue

@@ -1,6 +1,8 @@
 <template>
     <div class="flex items-center">
         <img class="w-[24px]" src="@/assets/icon_dianzhan.png" alt="" />
-        <span class="text-[#797A8A] text-xs">1</span>
+        <span class="text-[#797A8A] text-xs">
+            <slot></slot>
+        </span>
     </div>
 </template>

+ 21 - 6
src/components/common/MomentInfo.vue

@@ -1,16 +1,20 @@
 <template>
     <n-thing @click="goDetail">
         <template #avatar>
-            <n-avatar v-if="chatRole.pic" class="!block" round :size="88" :src="chatRole.pic"> </n-avatar>
-            <n-avatar v-else class="!block" round :size="88"> {{ chatRole.name?.[0] }} </n-avatar>
+            <n-avatar v-if="chatRole.pic" class="!block" round :size="size === 'mini' ? 40 : 88" :src="chatRole.pic">
+            </n-avatar>
+            <n-avatar v-else class="!block" round :size="size === 'mini' ? 40 : 88">
+                {{ chatRole.name?.[0] }}
+            </n-avatar>
         </template>
         <template #header>
-            <div class="text-lg font-semibold">{{ chatRole.name }}</div>
+            <div class="text-lg font-semibold" :class="{ '!text-base': size === 'mini' }">{{ chatRole.name }}</div>
         </template>
         <template #header-extra> </template>
         <template #description>
-            <div class="text-xs text-[#797A8A]">1.5w+人聊过|20个动态</div>
-            <n-space size="small" class="mt-2">
+            <div class="text-xs text-[#797A8A]" v-if="size == 'mini'">{{ timeStr }}</div>
+            <div class="text-xs text-[#797A8A]" v-else>1.5w+人聊过|20个动态</div>
+            <n-space size="small" class="mt-2" v-if="size !== 'mini'">
                 <n-tag
                     :bordered="false"
                     :color="{
@@ -38,7 +42,7 @@
         </template> -->
         <template #action>
             <div class="flex text-[#939599] text-xs">
-                <div>{{ timeStr }}</div>
+                <div v-if="size !== 'mini'">{{ timeStr }}</div>
                 <div class="flex1"></div>
                 <div></div>
             </div>
@@ -62,6 +66,10 @@ const props = defineProps({
         default: () => {
             return {}
         }
+    },
+    size: {
+        type: String,
+        default: 'medium'
     }
 })
 
@@ -89,3 +97,10 @@ function goDetail() {
     emit('goDetail', props.info.id)
 }
 </script>
+<style lang="less" scoped>
+:deep(.n-thing-header-wrapper) {
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+}
+</style>

+ 132 - 5
src/views/page/AgentView.vue

@@ -66,12 +66,25 @@
 
                 <div class="title px-5 py-4 flex items-center relative">
                     <span class="text-base font-medium">全部动态</span>
-                    <span class="text-xs text-[#797A8A] ml-[2px]">(1356)</span>
+                    <span class="text-xs text-[#797A8A] ml-[2px]">({{ totals }}个)</span>
                     <img class="absolute bottom-2 left-[38px] w-[28px]" src="@/assets/png-xian.png" alt="" />
                 </div>
 
-                <div>
-                    <comment-info v-for="i in 10" :key="i"></comment-info>
+                <div class="px-5 moment-list ">
+                    <div class="empty py-6" v-if="!loading && !totals">
+                        <img class="w-3/5 block mx-[auto]" :src="isDark ? emptyDarkImg : emptyImg" alt="" />
+                        <div class="text-sm text-[#939599] text-center py-3">暂无评论</div>
+                    </div>
+                    <div
+                        ref="target"
+                        v-for="(item, index) in list"
+                        :key="index"
+                        class="moment-box bg-white mt-[12px] p-4 rounded-lg"
+                        :class="{ 'moment-center': showList[index] }"
+                    >
+                        <moment-info size="mini" @goDetail="goDetail" :info="item"></moment-info>
+                    </div>
+                    <div class="loading flex items-center justify-center opacity-0" ref="loadingRef">加载中</div>
                 </div>
             </div>
         </div>
@@ -84,21 +97,42 @@ import { useRouter, useRoute } from 'vue-router'
 import { AgentPannel } from '@/components/common'
 import bgImg from '@/assets/png-beij.png'
 import { useWindowScroll } from '@vueuse/core'
-import { computed, ref } from 'vue'
+import { computed, ref, watch, nextTick } from 'vue'
 import { useTheme } from '@/hooks/useTheme'
 import { MomentInfo, CommentInfo } from '@/components/common'
-import { fetchGetChatRole } from '@/api'
+import { fetchGetChatRole, fetchGetMoments } from '@/api'
+import { useIntersectionObserver, useWindowSize, useElementBounding } from '@vueuse/core'
+import emptyImg from '@/assets/empty.png'
+import emptyDarkImg from '@/assets/empty-dark.png'
 
 const router = useRouter()
 function handleBack() {
     router.back()
 }
+function goDetail(id: any) {
+    router.push({
+        path: '/momentsDetail',
+        query: {
+            id: id
+        }
+    })
+}
+
 const { y } = useWindowScroll()
 
 const scrollY = computed(() => {
     return y.value
 })
 
+const target = ref([])
+const showList = ref(<any>[])
+const { width, height } = useWindowSize()
+watch(y, () => {
+    showList.value = target.value.map((item: any) => {
+        return useElementBounding(item).top.value < height.value - 50
+    })
+})
+
 const { isDark } = useTheme()
 
 const route = useRoute()
@@ -115,6 +149,58 @@ fetchGetChatRole(route.query.id).then((res: any) => {
 const labels = computed(() => {
     return chatRole.value?.labels
 })
+
+const list = ref(<any>[])
+const page = ref(1)
+const finish = ref(false)
+const loading = ref(false)
+const totals = ref(0)
+
+function getMoments() {
+    loading.value = true
+    let data = {
+        page: {
+            page: page.value,
+            limit: 20
+        },
+        search: {
+            order: {
+                createdAt: 'DESC'
+            }
+        }
+    }
+    fetchGetMoments(data)
+        .then((res: any) => {
+            list.value = [...list.value, ...res.items]
+            if (res.meta.totalPages <= res.meta.currentPage) {
+                finish.value = true
+            } else {
+                finish.value = false
+                page.value = page.value + 1
+            }
+            totals.value = res.meta.totalItems
+        })
+        .finally(() => {
+            loading.value = false
+        })
+}
+
+const loadingRef = ref(null)
+const isBottom = ref(false)
+useIntersectionObserver(loadingRef, ([{ isIntersecting }]) => {
+    if (isIntersecting && !loading.value && !finish.value) {
+        getMoments()
+    }
+    isBottom.value = isIntersecting
+})
+
+watch(list, () => {
+    nextTick(() => {
+        showList.value = target.value.map((item: any) => {
+            return useElementBounding(item).top.value < height.value - 50
+        })
+    })
+})
 </script>
 
 <style lang="less" scoped>
@@ -149,4 +235,45 @@ const labels = computed(() => {
 .title {
     background: linear-gradient(180deg, #ffffff 0%, #f5f6f8 100%);
 }
+
+:deep(.n-thing-header-wrapper) {
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+}
+
+.moment-list {
+    :nth-child(n) {
+        &.moment-box {
+            transition: transform ease-in-out 0.3s;
+        }
+    }
+    :nth-child(2n + 1) {
+        &.moment-box {
+            transform: translateX(200%);
+        }
+    }
+
+    :nth-child(2n) {
+        &.moment-box {
+            transform: translateX(-200%);
+        }
+    }
+    .moment-box {
+        &.moment-center {
+            transform: translateX(0);
+        }
+    }
+
+    .targe {
+        position: absolute;
+        width: 100%;
+        height: 50px;
+        // background-color: red;
+        bottom: 0;
+        left: 0;
+        z-index: 0;
+    }
+}
+
 </style>

+ 1 - 1
src/views/page/LoginView.vue

@@ -9,7 +9,7 @@
         <n-el class="text-xs mt-2 text-gray-400 dark:text-gray-500">未注册手机验证后自动注册登录</n-el>
 
         <div class="py-9">
-            <login-form @success="$router.replace({ name: 'Chat' })"></login-form>
+            <login-form @success="$router.replace({ name: 'moments' })"></login-form>
         </div>
     </n-el>
 </template>