1
0
mirror of https://github.com/ialley-workshop-open/uni-halo.git synced 2026-07-27 04:20:43 +08:00

feat(blog,comment): add post comment panel and optimize tips

1. 新增文章评论弹窗组件uh-post-comment-panel
2. 给文章详情页评论按钮绑定打开评论面板事件
3. 优化图片画廊和评论加载失败的提示文案与样式
4. 修复评论列表接口返回类型适配问题
This commit is contained in:
小莫唐尼
2026-06-15 18:53:48 +08:00
parent c4fc9c930e
commit a86baa9641
4 changed files with 115 additions and 5 deletions
+3 -2
View File
@@ -1,5 +1,6 @@
import { http } from '@/http/alova'
import type { Comment, CommentV1alpha1PublicApiCreateComment1Request, CommentV1alpha1PublicApiCreateReply1Request, CommentV1alpha1PublicApiGetCommentRequest, CommentV1alpha1PublicApiListCommentRepliesRequest, CommentV1alpha1PublicApiListComments1Request, CommentVoList, CommentWithReplyVoList, Reply, ReplyVoList } from '@halo-dev/api-client'
import type { Comment, CommentV1alpha1PublicApiCreateComment1Request, CommentV1alpha1PublicApiCreateReply1Request, CommentV1alpha1PublicApiGetCommentRequest, CommentV1alpha1PublicApiListCommentRepliesRequest, CommentV1alpha1PublicApiListComments1Request, CommentVoList, CommentWithReplyVo, Reply, ReplyVoList } from '@halo-dev/api-client'
import type { IHaloListResponseBase } from '../types/halo'
const EndpointBase = '/apis/api.halo.run/v1alpha1/comments'
@@ -35,7 +36,7 @@ export function createReply(data: CommentV1alpha1PublicApiCreateReply1Request) {
* @returns 获取评论列表响应参数
*/
export function listComments(params: CommentV1alpha1PublicApiListComments1Request) {
return http.Get<CommentWithReplyVoList>(`${EndpointBase}`, {
return http.Get<IHaloListResponseBase<CommentWithReplyVo>>(`${EndpointBase}`, {
params,
meta: {
isHalo: true,
@@ -0,0 +1,88 @@
<script setup lang="ts">
import { listComments } from '@/api/halo-base/comment'
import { completeUrl } from '@/utils/url'
import { useHaloScroll } from '@/hooks/useHaloScroll'
import type { CommentV1alpha1PublicApiListComments1Request, CommentWithReplyVo, PostVo } from '@halo-dev/api-client'
interface IProps {
post: PostVo | undefined
}
const props = defineProps<IProps>()
const emits = defineEmits<{
(e: 'close'): void
}>()
const {
response, // 响应式的原始数据响应
list, // 响应式的数据列表
loading, // 是否加载中
finished, // 是否已全部加载
error, // 是否加载失败
refresh, // 刷新数据的函数
loadMore, // 加载更多数据的函数
} = useHaloScroll<CommentWithReplyVo, CommentV1alpha1PublicApiListComments1Request>({
fetchData: listComments,
params: {
version: 'v1alpha1',
kind: 'Comment',
page: 1,
size: 12,
name: props.post?.metadata?.name ?? undefined,
},
})
</script>
<template>
<!-- 评论面板根据分组显示 -->
<view
class="uh-backdrop-blur-xs fixed inset-0 z-110 flex items-end justify-center bg-black/20"
@click.stop="emits('close')"
>
<wd-transition :show="true" :lazy-render="true" :duration="150" name="fade-up">
<view class="box-border w-screen rounded-2xl bg-white p-4" @click.stop>
<view class="box-border w-full flex shrink-0 items-center justify-between gap-x-4">
<view class="text-gray-900 font-bold">
记录点什么
</view>
<view class="shrink-0">
<wd-icon name="close-circle" size="24px" color="#1A1A1A" @click="emits('close')" />
</view>
</view>
<view class="mt-2 w-full">
<scroll-view
v-if="list.length > 0" class="h-[60vh] w-full" scroll-y :refresher-enabled="true"
:refresher-triggered="loading" @scrolltolower="loadMore" @refresherrefresh="refresh"
>
<view class="box-border w-full">
这里是评论记录
</view>
</scroll-view>
<view v-else class="h-[60vh] flex items-center justify-center">
<wd-empty tip="暂无数据">
<template #image>
<wd-icon name="empty" color="#1A1A1A" :size="52" />
</template>
</wd-empty>
</view>
<view class="mt-4 w-full flex flex-col items-center justify-center gap-y-2 text-xs text-gray-900">
<view class="text-xs text-gray-900">
{{ response?.total || 0 }} 条记录 已加载 {{ list.length }} 条记录
</view>
<view v-if="loading || error || finished">
<wd-loading v-if="loading" text="加载中..." direction="horizontal" color="#1A1A1A" :size="16" />
<view v-else-if="error" class="w-full rounded-lg bg-gray-900 px-2 py-1.5 text-center text-xs text-white">
<wd-icon name="refresh" :size="14" /> 加载失败点击重试
</view>
<view v-else-if="finished" class="text-xs text-gray-900">
数据已全部加载
</view>
</view>
</view>
</view>
</view>
</wd-transition>
</view>
</template>
@@ -90,8 +90,8 @@ function handlePreview(item: IPhoto) {
</view>
<view v-if="loading || error || finished">
<wd-loading v-if="loading" text="加载中..." direction="horizontal" color="#1A1A1A" :size="16" />
<view v-else-if="error" class="w-full rounded-lg bg-gray-900 py-1.5 text-center text-xs text-white">
<wd-icon name="refresh" :size="14" /> 加载失败点击刷新试
<view v-else-if="error" class="w-full rounded-lg bg-gray-900 px-2 py-1.5 text-center text-xs text-white">
<wd-icon name="refresh" :size="14" /> 加载失败点击
</view>
<view v-else-if="finished" class="text-xs text-gray-900">
数据已全部加载
+22 -1
View File
@@ -153,6 +153,24 @@ onShareAppMessage(() => {
path: `/subpkg-blog/post-detail/post-detail?metadataName=${postName}`,
}
})
const commentPanel = reactive<{
show: boolean
post: PostVo | undefined
}>({
show: false,
post: undefined,
})
function handleOpenCommentPanel(post: PostVo) {
commentPanel.show = true
commentPanel.post = post
}
function handleCloseCommentPanel() {
commentPanel.show = false
commentPanel.post = undefined
}
</script>
<template>
@@ -313,7 +331,7 @@ onShareAppMessage(() => {
</view>
<!-- 评论 -->
<view class="flex flex-1 items-center justify-center gap-x-1">
<view class="flex flex-1 items-center justify-center gap-x-1" @click="handleOpenCommentPanel(post)">
<view class="center rounded-full bg-transparent">
<wd-icon name="message" color="#6B7280" :size="18" />
</view>
@@ -338,6 +356,9 @@ onShareAppMessage(() => {
</view>
</view>
</view>
<!-- 评论面板 -->
<uh-post-comment-panel v-if="commentPanel.show" :post="commentPanel.post" @close="handleCloseCommentPanel" />
</template>
<style scoped>