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:
@@ -1,5 +1,6 @@
|
|||||||
import { http } from '@/http/alova'
|
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'
|
const EndpointBase = '/apis/api.halo.run/v1alpha1/comments'
|
||||||
|
|
||||||
@@ -35,7 +36,7 @@ export function createReply(data: CommentV1alpha1PublicApiCreateReply1Request) {
|
|||||||
* @returns 获取评论列表响应参数
|
* @returns 获取评论列表响应参数
|
||||||
*/
|
*/
|
||||||
export function listComments(params: CommentV1alpha1PublicApiListComments1Request) {
|
export function listComments(params: CommentV1alpha1PublicApiListComments1Request) {
|
||||||
return http.Get<CommentWithReplyVoList>(`${EndpointBase}`, {
|
return http.Get<IHaloListResponseBase<CommentWithReplyVo>>(`${EndpointBase}`, {
|
||||||
params,
|
params,
|
||||||
meta: {
|
meta: {
|
||||||
isHalo: true,
|
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>
|
||||||
<view v-if="loading || error || finished">
|
<view v-if="loading || error || finished">
|
||||||
<wd-loading v-if="loading" text="加载中..." direction="horizontal" color="#1A1A1A" :size="16" />
|
<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">
|
<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" /> 加载失败,点击刷新试试
|
<wd-icon name="refresh" :size="14" /> 加载失败,点击重试
|
||||||
</view>
|
</view>
|
||||||
<view v-else-if="finished" class="text-xs text-gray-900">
|
<view v-else-if="finished" class="text-xs text-gray-900">
|
||||||
数据已全部加载
|
数据已全部加载
|
||||||
|
|||||||
@@ -153,6 +153,24 @@ onShareAppMessage(() => {
|
|||||||
path: `/subpkg-blog/post-detail/post-detail?metadataName=${postName}`,
|
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>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -313,7 +331,7 @@ onShareAppMessage(() => {
|
|||||||
</view>
|
</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">
|
<view class="center rounded-full bg-transparent">
|
||||||
<wd-icon name="message" color="#6B7280" :size="18" />
|
<wd-icon name="message" color="#6B7280" :size="18" />
|
||||||
</view>
|
</view>
|
||||||
@@ -338,6 +356,9 @@ onShareAppMessage(() => {
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
<!-- 评论面板 -->
|
||||||
|
<uh-post-comment-panel v-if="commentPanel.show" :post="commentPanel.post" @close="handleCloseCommentPanel" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|||||||
Reference in New Issue
Block a user