完成70%
This commit is contained in:
@@ -1,33 +1,13 @@
|
||||
<!-- 页面编号:F-05;用途:谱文正文、收藏、编辑与受控状态。 -->
|
||||
<!-- 页面编号:F-05;用途:谱文详情。详情 DTO 未声明时不展示本地正文。 -->
|
||||
<template>
|
||||
<view class="article-detail-page" :class="articleStateClasses">
|
||||
<view class="article-detail-page">
|
||||
<ModulePageBackground module="family" />
|
||||
<view class="article-detail-header"><PageHeader title="谱文详情" /></view>
|
||||
|
||||
<view v-if="articleState === 'loading'" class="article-detail-loading">
|
||||
<AppLoading text="正在读取谱文" description="请稍候,正在整理正文与收录信息。" />
|
||||
</view>
|
||||
|
||||
<view v-else class="article-detail-content">
|
||||
<template v-if="articleState === 'ready'">
|
||||
<view class="article-paper">
|
||||
<text class="article-paper__category">{{ article.category }}</text>
|
||||
<text class="article-paper__title">{{ article.title }}</text>
|
||||
<view class="article-paper__meta"><text>{{ article.author }}</text><text>{{ article.updatedAt }}</text></view>
|
||||
<view class="article-paper__body">
|
||||
<text v-for="(paragraph, index) in articleParagraphs" :key="index">{{ paragraph }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="article-actions">
|
||||
<AppButton block disabled label="收藏暂未开放" />
|
||||
<AppButton type="secondary" block label="编辑谱文" @click="editArticle" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<view v-else class="article-state-card">
|
||||
<view class="article-detail-header"><PageHeader title="谱文详情" custom-back @back="backToArticles" /></view>
|
||||
<view class="article-detail-content">
|
||||
<view class="article-state-card">
|
||||
<text>{{ stateCopy.title }}</text>
|
||||
<text>{{ stateCopy.copy }}</text>
|
||||
<AppButton :type="articleState === 'error' ? 'secondary' : 'primary'" block :label="stateCopy.action" @click="handleStateAction" />
|
||||
<AppButton block :label="stateCopy.action" @click="backToArticles" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -37,86 +17,42 @@
|
||||
import { computed, ref } from "vue";
|
||||
import { onLoad } from "@dcloudio/uni-app";
|
||||
import AppButton from "@/components/AppButton.vue";
|
||||
import AppLoading from "@/components/AppLoading.vue";
|
||||
import ModulePageBackground from "@/components/ModulePageBackground.vue";
|
||||
import PageHeader from "@/components/PageHeader.vue";
|
||||
import { findFamilyArticleFixture } from "@/data/mock.js";
|
||||
import { goBack, openPage, returnTo } from "@/utils/navigation.js";
|
||||
import { goBack, returnTo } from "@/utils/navigation.js";
|
||||
|
||||
const genealogyId = ref("");
|
||||
const articleId = ref("");
|
||||
const article = ref(null);
|
||||
const articleState = ref("loading");
|
||||
const articleParagraphs = computed(() => article.value?.paragraphs || []);
|
||||
const articleStateClasses = computed(() => ({
|
||||
[`article-state--${articleState.value}`]: true,
|
||||
"article-state--expired": articleState.value === "expired",
|
||||
"article-state--privacy": articleState.value === "privacy",
|
||||
"article-state--error": articleState.value === "error",
|
||||
}));
|
||||
const stateCopy = computed(() => ({
|
||||
expired: { title: "这篇谱文已无法查看", copy: "当前家谱中不存在这篇谱文,页面不会回退到其他文章。", action: genealogyId.value ? "返回谱文列表" : "返回上一页" },
|
||||
privacy: { title: "这篇谱文暂未公开", copy: "作者仅向有权限的家人开放正文,请返回谱文列表查看其他内容。", action: "返回谱文列表" },
|
||||
error: { title: "谱文暂不可用", copy: "请稍后重新查看,已有谱文不会受到影响。", action: "重新查看" },
|
||||
}[articleState.value] || {}));
|
||||
|
||||
onLoad((query) => {
|
||||
genealogyId.value = String(query.genealogyId || "");
|
||||
articleId.value = String(query.articleId || "");
|
||||
const selected = findFamilyArticleFixture(genealogyId.value, articleId.value);
|
||||
article.value = selected;
|
||||
articleState.value = ["loading", "error", "expired", "privacy"].includes(query.state)
|
||||
? selected
|
||||
? query.state
|
||||
: "expired"
|
||||
: selected
|
||||
? "ready"
|
||||
: "expired";
|
||||
});
|
||||
|
||||
const editArticle = () =>
|
||||
openPage(
|
||||
"F06",
|
||||
{
|
||||
genealogyId: genealogyId.value,
|
||||
mode: "edit",
|
||||
articleId: articleId.value,
|
||||
const hasValidContext = computed(() => /^[1-9]\d*$/.test(genealogyId.value) && /^[1-9]\d*$/.test(articleId.value));
|
||||
const stateCopy = computed(() => hasValidContext.value
|
||||
? {
|
||||
title: "谱文正文待后端字段合同",
|
||||
copy: "详情接口没有声明文章标题、分类、作者、更新时间或正文段落字段;页面已停止读取本地文章,不能猜测这些字段。",
|
||||
action: "返回谱文列表",
|
||||
}
|
||||
: {
|
||||
title: "谱文入口无效",
|
||||
copy: "没有取得有效家谱或文章标识,页面不会回退到其他文章。",
|
||||
action: "返回上一页",
|
||||
},
|
||||
"F05",
|
||||
);
|
||||
const backToArticles = () =>
|
||||
genealogyId.value
|
||||
? returnTo("F04", { genealogyId: genealogyId.value })
|
||||
: goBack();
|
||||
const handleStateAction = () => {
|
||||
if (articleState.value === "error" && article.value) {
|
||||
articleState.value = "ready";
|
||||
return;
|
||||
}
|
||||
return backToArticles();
|
||||
};
|
||||
);
|
||||
onLoad((query) => {
|
||||
genealogyId.value = String(query?.genealogyId || "");
|
||||
articleId.value = String(query?.articleId || "");
|
||||
});
|
||||
const backToArticles = () => /^[1-9]\d*$/.test(genealogyId.value)
|
||||
? returnTo("F04", { genealogyId: genealogyId.value })
|
||||
: goBack();
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@use "../../styles/adaptive-frame-profiles.scss" as adaptive;
|
||||
|
||||
.article-detail-page { display: flex; min-height: 100vh; flex-direction: column; background: $paper; }
|
||||
.article-detail-header, .article-detail-loading, .article-detail-content { z-index: 1; }
|
||||
.article-detail-loading { min-height: calc(100vh - 100rpx); }
|
||||
.article-detail-header, .article-detail-content { z-index: 1; }
|
||||
.article-detail-content { padding: 18rpx 24rpx 72rpx; }
|
||||
.article-paper, .article-state-card { @include adaptive.adaptive-family-content; width: 100%; }
|
||||
.article-paper { padding: 50rpx 48rpx 54rpx; }
|
||||
.article-paper > text { display: block; }
|
||||
.article-paper__category { color: $brand-red; font-size: 22rpx; font-weight: 700; letter-spacing: 3rpx; }
|
||||
.article-paper__title { margin-top: 12rpx; color: $ink; font-family: STKaiti, KaiTi, serif; font-size: 39rpx; font-weight: 700; line-height: 1.35; }
|
||||
.article-paper__meta { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 6rpx 18rpx; margin-top: 16rpx; color: $ink-muted; font-size: 21rpx; }
|
||||
.article-paper__body { margin-top: 28rpx; }
|
||||
.article-paper__body text { display: block; margin-top: 18rpx; color: $ink; font-size: 25rpx; line-height: 1.85; text-align: justify; }
|
||||
.article-actions { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 14rpx; margin-top: 18rpx; }
|
||||
.article-state-card { min-height: 350rpx; margin-top: 36rpx; padding: 78rpx 52rpx 50rpx; text-align: center; }
|
||||
.article-state-card { @include adaptive.adaptive-family-content; width: 100%; min-height: 350rpx; margin-top: 36rpx; padding: 78rpx 52rpx 50rpx; text-align: center; }
|
||||
.article-state-card > text { display: block; }
|
||||
.article-state-card > text:first-child { color: $ink; font-family: STKaiti, KaiTi, serif; font-size: 35rpx; font-weight: 700; }
|
||||
.article-state-card > text:nth-child(2) { margin-top: 18rpx; color: $ink-muted; font-size: 24rpx; line-height: 1.65; }
|
||||
.article-state-card .app-button { margin-top: 30rpx; }
|
||||
@media (max-width: 340px) { .article-actions { grid-template-columns: minmax(0, 1fr); } }
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user