修改完成
This commit is contained in:
@@ -1,5 +1,153 @@
|
||||
<!-- 页面编号:F-03;用途:动态详情、评论、点赞与删除确认。 -->
|
||||
<template><ModulePage page-id="f03" /></template>
|
||||
<!-- 页面编号:F-03;用途:动态详情、评论与内容失效状态。 -->
|
||||
<template>
|
||||
<view class="feed-detail-page" :class="{ 'feed-state--expired': feedState === 'expired', 'feed-state--error': feedState === 'error', 'feed-state--ready': feedState === 'ready' }">
|
||||
<ModulePageBackground module="family" />
|
||||
<view class="feed-detail-header"><PageHeader title="动态详情" /></view>
|
||||
|
||||
<view v-if="feedState === 'loading'" class="feed-detail-loading">
|
||||
<AppLoading text="正在读取家族动态" description="请稍候,正在整理正文与家人评论。" />
|
||||
</view>
|
||||
|
||||
<view v-else class="feed-detail-content">
|
||||
<template v-if="feedState === 'ready'">
|
||||
<view class="feed-article-card">
|
||||
<text class="feed-article-card__meta">{{ currentFeed.tag }} · {{ currentFeed.time }}</text>
|
||||
<text class="feed-article-card__title">{{ currentFeed.title }}</text>
|
||||
<text class="feed-article-card__body">{{ currentFeed.content }}</text>
|
||||
<text class="feed-article-card__author">发布人:{{ currentFeed.author }}</text>
|
||||
</view>
|
||||
|
||||
<view class="feed-comments-panel">
|
||||
<view class="feed-comments-heading">
|
||||
<text>家人评论</text><text>{{ feedComments.length }} 条</text>
|
||||
</view>
|
||||
<view v-for="comment in feedComments" :key="comment.id" class="feed-comment-card">
|
||||
<view><text>{{ comment.author }}</text><text>{{ comment.time }}</text></view>
|
||||
<text>{{ comment.content }}</text>
|
||||
</view>
|
||||
<view v-if="!feedComments.length" class="feed-comments-empty">
|
||||
<text>还没有评论</text><text>写下第一句祝福或共同记忆。</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="feed-comment-form" :class="{ 'comment-state--saving': commentState === 'saving', 'comment-state--error': commentState === 'error' }">
|
||||
<text>写下评论</text>
|
||||
<textarea v-model="commentDraft" auto-height maxlength="240" placeholder="对家人说点什么" />
|
||||
<text v-if="commentError" class="feed-comment-error">{{ commentError }}</text>
|
||||
<AppButton block :disabled="commentState === 'saving'" :label="commentState === 'saving' ? '正在发送' : '发送评论'" @click="submitComment" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<view v-else class="feed-state-card">
|
||||
<text>{{ feedState === 'expired' ? '动态已失效' : '动态暂不可用' }}</text>
|
||||
<text>{{ feedState === 'expired' ? '这条动态可能已被发布人删除,请返回家族圈查看其他内容。' : '请稍后重新查看,已有家族记录不会受到影响。' }}</text>
|
||||
<AppButton :type="feedState === 'error' ? 'secondary' : 'primary'" block :label="feedState === 'error' ? '重新查看' : '返回家族圈'" @click="feedState === 'error' ? restoreFeed() : backToFamily()" />
|
||||
</view>
|
||||
</view>
|
||||
<AppToast :visible="toastVisible" message="评论已发送" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import ModulePage from "@/components/ModulePage.vue";
|
||||
import { onUnmounted, ref } from "vue";
|
||||
import { onLoad } from "@dcloudio/uni-app";
|
||||
import AppButton from "@/components/AppButton.vue";
|
||||
import AppLoading from "@/components/AppLoading.vue";
|
||||
import AppToast from "@/components/AppToast.vue";
|
||||
import ModulePageBackground from "@/components/ModulePageBackground.vue";
|
||||
import PageHeader from "@/components/PageHeader.vue";
|
||||
|
||||
const feedRecords = [
|
||||
{ id: "1", tag: "团圆记忆", time: "今天 10:24", title: "端午家宴", content: "今年端午全家相聚,长辈讲起祖居旧事,孩子们也为大家拍下了新的全家福。饭后我们把照片和口述片段整理进家族档案,让这份热闹成为往后仍能翻看的共同记忆。", author: "汤正国" },
|
||||
{ id: "2", tag: "家族通知", time: "昨天 18:02", title: "修谱资料征集", content: "请家人补充老照片中的人物姓名、拍摄时间和地点。无法确认的信息也可以先写下线索,由熟悉往事的长辈共同核对。", author: "谱主" },
|
||||
];
|
||||
const feedId = ref("1");
|
||||
const currentFeed = ref(feedRecords[0]);
|
||||
const feedState = ref("loading");
|
||||
const commentState = ref("idle");
|
||||
const commentDraft = ref("");
|
||||
const commentError = ref("");
|
||||
const toastVisible = ref(false);
|
||||
const forceCommentFailure = ref(false);
|
||||
const feedComments = ref([
|
||||
{ id: 1, author: "汤淑华", time: "今天 10:42", content: "一家人能常常相聚,就是最珍贵的福气。" },
|
||||
{ id: 2, author: "汤文清", time: "今天 11:08", content: "照片已经整理好了,晚些时候放进春节团圆相册。" },
|
||||
]);
|
||||
let submitTimer = null;
|
||||
let toastTimer = null;
|
||||
|
||||
onLoad((query) => {
|
||||
feedId.value = String(query.feedId || "1");
|
||||
const selected = feedRecords.find((item) => item.id === feedId.value);
|
||||
currentFeed.value = selected || feedRecords[0];
|
||||
forceCommentFailure.value = query.commentResult === "error";
|
||||
feedState.value = ["loading", "error", "expired"].includes(query.state)
|
||||
? query.state
|
||||
: selected
|
||||
? "ready"
|
||||
: "expired";
|
||||
});
|
||||
|
||||
const submitComment = () => {
|
||||
if (commentState.value === "saving") return;
|
||||
const content = commentDraft.value.trim();
|
||||
if (!content) {
|
||||
commentError.value = "请先写下评论内容";
|
||||
return;
|
||||
}
|
||||
commentError.value = "";
|
||||
commentState.value = "saving";
|
||||
submitTimer = setTimeout(() => {
|
||||
if (forceCommentFailure.value) {
|
||||
commentState.value = "error";
|
||||
commentError.value = "评论发送失败,请保留文字后重试";
|
||||
forceCommentFailure.value = false;
|
||||
return;
|
||||
}
|
||||
feedComments.value.push({ id: Date.now(), author: "我", time: "刚刚", content });
|
||||
commentDraft.value = "";
|
||||
commentState.value = "idle";
|
||||
toastVisible.value = true;
|
||||
toastTimer = setTimeout(() => { toastVisible.value = false; }, 1800);
|
||||
}, 320);
|
||||
};
|
||||
const restoreFeed = () => { feedState.value = "ready"; };
|
||||
const backToFamily = () => uni.redirectTo({ url: "/pages/family/f01-family-feed" });
|
||||
|
||||
onUnmounted(() => {
|
||||
if (submitTimer) clearTimeout(submitTimer);
|
||||
if (toastTimer) clearTimeout(toastTimer);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.feed-detail-page { display: flex; min-height: 100vh; flex-direction: column; background: $paper; }
|
||||
.feed-detail-header, .feed-detail-loading, .feed-detail-content { z-index: 1; }
|
||||
.feed-detail-loading { min-height: calc(100vh - 100rpx); }
|
||||
.feed-detail-content { padding: 18rpx 24rpx 72rpx; }
|
||||
.feed-article-card, .feed-comments-panel, .feed-comment-form, .feed-state-card { width: 100%; box-sizing: border-box; background: url("/static/assets/modules/family/transparent/module-content-frame.png") center / 100% 100% no-repeat; }
|
||||
.feed-article-card { padding: 46rpx 48rpx 42rpx; }
|
||||
.feed-article-card text, .feed-state-card > text { display: block; }
|
||||
.feed-article-card__meta, .feed-article-card__author { color: $ink-muted; font-size: 22rpx; }
|
||||
.feed-article-card__title { margin-top: 12rpx; color: $ink; font-family: STKaiti, KaiTi, serif; font-size: 36rpx; font-weight: 700; }
|
||||
.feed-article-card__body { margin-top: 18rpx; color: $ink; font-size: 25rpx; line-height: 1.75; }
|
||||
.feed-article-card__author { margin-top: 22rpx; }
|
||||
.feed-comments-panel { margin-top: 18rpx; padding: 38rpx 38rpx 34rpx; }
|
||||
.feed-comments-heading { display: flex; align-items: center; justify-content: space-between; color: $brand-red; font-size: 24rpx; font-weight: 700; }
|
||||
.feed-comments-heading text:last-child { color: $ink-muted; font-size: 21rpx; font-weight: 400; }
|
||||
.feed-comment-card { margin-top: 16rpx; padding: 20rpx 22rpx; background: url("/static/assets/modules/family/transparent/module-field-frame.png") center / 100% 100% no-repeat; }
|
||||
.feed-comment-card > view { display: flex; justify-content: space-between; gap: 18rpx; color: $ink-muted; font-size: 20rpx; }
|
||||
.feed-comment-card > text { display: block; margin-top: 9rpx; color: $ink; font-size: 24rpx; line-height: 1.55; }
|
||||
.feed-comments-empty { padding: 34rpx 10rpx 20rpx; text-align: center; }
|
||||
.feed-comments-empty text { display: block; color: $ink-muted; font-size: 23rpx; line-height: 1.6; }
|
||||
.feed-comments-empty text:first-child { color: $ink; font-size: 28rpx; font-weight: 700; }
|
||||
.feed-comment-form { margin-top: 18rpx; padding: 38rpx 40rpx 42rpx; }
|
||||
.feed-comment-form > text:first-child { color: $ink; font-family: STKaiti, KaiTi, serif; font-size: 30rpx; font-weight: 700; }
|
||||
.feed-comment-form textarea { width: auto; min-width: 0; min-height: 126rpx; margin-top: 16rpx; padding: 20rpx 22rpx; box-sizing: border-box; color: $ink; font-size: 24rpx; line-height: 1.55; background: url("/static/assets/modules/family/transparent/module-field-frame.png") center / 100% 100% no-repeat; }
|
||||
.feed-comment-error { display: block; margin-top: 10rpx; color: $brand-red; font-size: 22rpx; }
|
||||
.feed-comment-form .app-button { margin-top: 22rpx; }
|
||||
.feed-state-card { min-height: 340rpx; margin-top: 36rpx; padding: 78rpx 52rpx 50rpx; text-align: center; }
|
||||
.feed-state-card > text:first-child { color: $ink; font-family: STKaiti, KaiTi, serif; font-size: 35rpx; font-weight: 700; }
|
||||
.feed-state-card > text:nth-child(2) { margin-top: 18rpx; color: $ink-muted; font-size: 24rpx; line-height: 1.65; }
|
||||
.feed-state-card .app-button { margin-top: 30rpx; }
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user