|
|
|
@ -23,11 +23,7 @@
|
|
|
|
|
</n-tabs>
|
|
|
|
|
</div>
|
|
|
|
|
<n-list-item v-if="post.id > 0">
|
|
|
|
|
<compose-comment
|
|
|
|
|
:lock="post.is_lock"
|
|
|
|
|
:post-id="post.id"
|
|
|
|
|
@post-success="loadComments(true)"
|
|
|
|
|
/>
|
|
|
|
|
<compose-comment :lock="post.is_lock" :post-id="post.id" @post-success="loadComments(true)" />
|
|
|
|
|
</n-list-item>
|
|
|
|
|
|
|
|
|
|
<div v-if="post.id > 0">
|
|
|
|
@ -36,26 +32,24 @@
|
|
|
|
|
</div>
|
|
|
|
|
<div v-else>
|
|
|
|
|
<div class="empty-wrap" v-if="comments.length === 0">
|
|
|
|
|
<n-empty
|
|
|
|
|
size="large"
|
|
|
|
|
description="暂无评论,快来抢沙发"
|
|
|
|
|
/>
|
|
|
|
|
<n-empty size="large" description="暂无评论,快来抢沙发" />
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<n-list-item v-for="comment in comments" :key="comment.id">
|
|
|
|
|
<comment-item
|
|
|
|
|
:comment="comment"
|
|
|
|
|
@reload="loadComments"
|
|
|
|
|
/>
|
|
|
|
|
<comment-item :comment="comment" @reload="loadComments" />
|
|
|
|
|
</n-list-item>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="load-more-ele" v-if="!noMore" ref="bottomElement">
|
|
|
|
|
加载更多...
|
|
|
|
|
</div>
|
|
|
|
|
</n-list>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
|
|
import { ref, watch, onMounted, computed, Ref } from 'vue';
|
|
|
|
|
import { ref, watch, onMounted, onUnmounted, computed, Ref } from 'vue';
|
|
|
|
|
import { useRoute } from 'vue-router';
|
|
|
|
|
import { getPost, getPostComments } from '@/api/post';
|
|
|
|
|
|
|
|
|
@ -66,6 +60,9 @@ const commentLoading = ref(false);
|
|
|
|
|
const comments = ref<Item.CommentProps[]>([]);
|
|
|
|
|
const postId = computed(() => +(route.query.id as string));
|
|
|
|
|
const sortStrategy = ref<"default" | "newest">('default');
|
|
|
|
|
const bottomElement = ref<HTMLElement | null>(null);
|
|
|
|
|
const page = ref<number>(1);
|
|
|
|
|
const noMore = ref(false);
|
|
|
|
|
|
|
|
|
|
const commentTab = (tab: "default" | "newest") => {
|
|
|
|
|
sortStrategy.value = tab;
|
|
|
|
@ -98,9 +95,19 @@ const loadComments = (scrollToBottom: boolean = false) => {
|
|
|
|
|
getPostComments({
|
|
|
|
|
id: post.value.id as number,
|
|
|
|
|
sort_strategy: sortStrategy.value,
|
|
|
|
|
page: page.value,
|
|
|
|
|
page_size: 20
|
|
|
|
|
})
|
|
|
|
|
.then((res) => {
|
|
|
|
|
if (res.list.length === 0) {
|
|
|
|
|
noMore.value = true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (page.value === 1) {
|
|
|
|
|
comments.value = res.list;
|
|
|
|
|
} else {
|
|
|
|
|
comments.value = comments.value.concat(res.list);
|
|
|
|
|
}
|
|
|
|
|
commentLoading.value = false;
|
|
|
|
|
|
|
|
|
|
if (scrollToBottom) {
|
|
|
|
@ -113,9 +120,38 @@ const loadComments = (scrollToBottom: boolean = false) => {
|
|
|
|
|
commentLoading.value = false;
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const loadMoreComments = () => {
|
|
|
|
|
if (!commentLoading.value && comments.value.length > 0) {
|
|
|
|
|
page.value = page.value + 1;
|
|
|
|
|
loadComments();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const observer = new IntersectionObserver((entries: IntersectionObserverEntry[]) => {
|
|
|
|
|
entries.forEach(entry => {
|
|
|
|
|
if (entry.isIntersecting) {
|
|
|
|
|
loadMoreComments();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}, {
|
|
|
|
|
root: null,
|
|
|
|
|
rootMargin: '0px',
|
|
|
|
|
threshold: 1
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
if (bottomElement.value) {
|
|
|
|
|
observer.observe(bottomElement.value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
loadPost();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
onUnmounted(() => {
|
|
|
|
|
observer.disconnect()
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
watch(postId, () => {
|
|
|
|
|
if (postId.value > 0 && route.name === 'post') {
|
|
|
|
|
loadPost();
|
|
|
|
@ -127,19 +163,32 @@ watch(postId, () => {
|
|
|
|
|
.detail-wrap {
|
|
|
|
|
min-height: 100px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.comment-opts-wrap {
|
|
|
|
|
padding-top: 6px;
|
|
|
|
|
padding-left: 16px;
|
|
|
|
|
padding-right: 16px;
|
|
|
|
|
opacity: 0.75;
|
|
|
|
|
|
|
|
|
|
.comment-title-item {
|
|
|
|
|
padding-top: 4px;
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
text-align: center;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.load-more-ele {
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
height: 40px;
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: center;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.dark {
|
|
|
|
|
.main-content-wrap, .skeleton-wrap {
|
|
|
|
|
|
|
|
|
|
.main-content-wrap,
|
|
|
|
|
.skeleton-wrap {
|
|
|
|
|
background-color: rgba(16, 16, 20, 0.75);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|