From b793920097892da6d47c01ca279a219954327caf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E8=8E=AB=E5=94=90=E5=B0=BC?= Date: Wed, 9 Sep 2026 18:40:14 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E6=8A=BD=E7=A6=BB=E7=82=B9?= =?UTF-8?q?=E8=B5=9Ehook=E5=B9=B6=E7=BB=9F=E4=B8=80=E7=82=B9=E8=B5=9E?= =?UTF-8?q?=E9=80=BB=E8=BE=91=EF=BC=8C=E4=BC=98=E5=8C=96=E8=AF=84=E8=AE=BA?= =?UTF-8?q?=E5=88=97=E8=A1=A8=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 新增useUpvote点赞hook,统一文章、瞬间的点赞逻辑与本地缓存 2. 重构文章详情、瞬间详情页的点赞代码,移除重复实现 3. 为评论列表组件添加kind参数支持动态类型,新增refresh暴露方法与全局刷新监听 4. 优化瞬间列表页的点赞、评论交互与样式 --- .../uh-comment-list/uh-comment-list.vue | 25 ++++++- src/hooks/useUpvote.ts | 60 ++++++++++++++++ .../article-detail/article-detail.vue | 48 +++++-------- .../moment-detail/moment-detail.vue | 60 ++++++++-------- src/pages/tabbar/moments/moments.vue | 68 +++++++++++++++++-- 5 files changed, 192 insertions(+), 69 deletions(-) create mode 100644 src/hooks/useUpvote.ts diff --git a/src/components/uh-comment-list/uh-comment-list.vue b/src/components/uh-comment-list/uh-comment-list.vue index 30c2cf0..6d63f44 100644 --- a/src/components/uh-comment-list/uh-comment-list.vue +++ b/src/components/uh-comment-list/uh-comment-list.vue @@ -1,5 +1,5 @@ @@ -135,7 +154,7 @@ - {{disallowComment ? '暂无评论' : '暂无评论'}} + 暂无评论 文章已开启禁止评论 diff --git a/src/hooks/useUpvote.ts b/src/hooks/useUpvote.ts new file mode 100644 index 0000000..47bb886 --- /dev/null +++ b/src/hooks/useUpvote.ts @@ -0,0 +1,60 @@ +/** + * 点赞交互(文章详情 / 瞬间详情 / 瞬间列表共用) + * 已点赞名单本地持久化(刷新/重进后仍防重复);支持单目标(详情页)与多目标(列表页)。 + */ +import { ref } from 'vue' +import { submitUpvote } from '@/api/halo' +import { getCache, setCache } from '@/utils/storage' + +const UPVOTE_CACHE_KEY = 'uh_upvoted_names' + +function readUpvotedNames(): string[] { + const list = getCache(UPVOTE_CACHE_KEY) + return Array.isArray(list) ? list : [] +} + +export function useUpvote(plural: 'posts' | 'moments', getName: () => string | undefined) { + const upvotedNames = ref(readUpvotedNames()) + + /** 判断是否已点赞(可指定 name;缺省用单目标 getName) */ + function hasUpvoted(name?: string): boolean { + const n = name ?? getName() + return !!n && upvotedNames.value.includes(n) + } + + /** 按 name 点赞(列表多目标场景;成功后持久化 + 回调) */ + async function likeByName(name: string, onSuccess?: (name: string) => void) { + if (!name) + return + if (upvotedNames.value.includes(name)) { + uni.showToast({ icon: 'none', title: '已经点过赞啦!' }) + return + } + try { + await submitUpvote({ group: 'content.halo.run', plural, name }) + uni.showToast({ icon: 'none', title: '点赞成功!' }) + upvotedNames.value.push(name) + setCache(UPVOTE_CACHE_KEY, upvotedNames.value) + onSuccess?.(name) + } + catch (err) { + console.error('点赞失败', err) + uni.showToast({ icon: 'none', title: '点赞失败' }) + } + } + + /** 点赞当前目标(详情页单目标场景) */ + async function handleDoLikes(onSuccess?: (name: string) => void) { + const name = getName() + if (!name) + return + await likeByName(name, onSuccess) + } + + return { + upvotedNames, + hasUpvoted, + handleDoLikes, + likeByName, + } +} diff --git a/src/pages-blog/article-detail/article-detail.vue b/src/pages-blog/article-detail/article-detail.vue index 6499222..179d10d 100644 --- a/src/pages-blog/article-detail/article-detail.vue +++ b/src/pages-blog/article-detail/article-detail.vue @@ -1,7 +1,8 @@