完成80%

This commit is contained in:
2026-07-27 06:50:07 +08:00
parent 8475bbd19a
commit 1eae3bbef4
63 changed files with 13664 additions and 280 deletions
+33
View File
@@ -18,6 +18,15 @@
<text>发布{{ feed.publisher }}</text>
<text>{{ feed.likeCount }} 次点赞 · {{ feed.commentCount }} 条评论</text>
</view>
<AppButton
compact
type="secondary"
:disabled="isTogglingLike || !hasLikeState"
:label="isTogglingLike ? '正在提交' : (hasLikeState ? (feed.likedByMe ? '取消点赞' : '点赞') : '点赞状态不可用')"
@click="toggleLike"
/>
<text v-if="!hasLikeState" class="like-note">点赞状态暂不可用页面不会猜测下一次操作</text>
<text v-if="likeError" class="like-error">{{ likeError }}</text>
</view>
<view class="comment-section">
@@ -82,6 +91,8 @@ const comments = ref([]);
const commentDraft = ref("");
const commentError = ref("");
const isSubmittingComment = ref(false);
const isTogglingLike = ref(false);
const likeError = ref("");
const controller = createRequestController();
let pageActive = true;
const feedTypeLabel = (type) => String(type || "").trim().toLowerCase() === "text" ? "文字动态" : "家族动态";
@@ -89,6 +100,7 @@ const feedTypeLabel = (type) => String(type || "").trim().toLowerCase() === "tex
const hasValidContext = computed(() =>
/^[1-9]\d*$/.test(genealogyId.value) && /^[1-9]\d*$/.test(feedId.value),
);
const hasLikeState = computed(() => typeof feed.value?.likedByMe === "boolean");
const stateCopy = computed(() => {
if (!hasValidContext.value) {
return {
@@ -151,6 +163,23 @@ const refresh = async () => {
if (feedState.value === "ready") await loadComments();
};
const toggleLike = async () => {
if (isTogglingLike.value || !hasValidContext.value || !feed.value || !hasLikeState.value) return;
const nextLiked = !feed.value.likedByMe;
isTogglingLike.value = true;
likeError.value = "";
try {
await appApi.setFeedLike(genealogyId.value, feedId.value, nextLiked, { requestController: controller });
if (!pageActive) return;
await loadFeed();
} catch (error) {
if (!pageActive || isRequestCancelled(error)) return;
likeError.value = error?.message || "点赞操作失败,请稍后重试";
} finally {
if (pageActive) isTogglingLike.value = false;
}
};
const submitComment = async () => {
if (isSubmittingComment.value || !hasValidContext.value) return;
const commentContent = commentDraft.value.trim();
@@ -208,6 +237,10 @@ onBackPress((event) => handleBackPress(event, requestBack));
.feed-card__heading text:last-child, .comment-card__heading text:last-child { color: $ink-muted; font-size: 21rpx; text-align: right; }
.feed-card__content { display: block; margin-top: 20rpx; color: $ink; font-size: 29rpx; line-height: 1.7; white-space: pre-wrap; }
.feed-card__meta { margin-top: 22rpx; color: $ink-muted; font-size: 21rpx; }
.feed-card .app-button { margin-top: 18rpx; }
.like-note, .like-error { display: block; margin-top: 10rpx; font-size: 22rpx; }
.like-note { color: $ink-muted; }
.like-error { color: $brand-red; }
.comment-section { margin-top: 18rpx; padding: 28rpx; }
.section-title { display: block; color: $ink; font-family: STKaiti, KaiTi, serif; font-size: 32rpx; font-weight: 700; }
.comment-list { margin-top: 18rpx; }