115 lines
5.8 KiB
Vue
115 lines
5.8 KiB
Vue
<!-- 页面编号:F-01;用途:家族动态入口。列表 DTO 缺失时不展示 fixture 条目。 -->
|
||
<template>
|
||
<view class="family-page" :class="`feed-state--${feedState}`">
|
||
<ModulePageBackground module="family" />
|
||
<view class="family-page__header"><PageHeader root title="家族动态" :action="hasValidContext ? '发布' : ''" @action="toPublish" /></view>
|
||
<view class="feed-content">
|
||
<view class="feed-heading"><text>家族圈</text><text>家宴、通知与共同记忆</text></view>
|
||
<template v-if="hasValidContext">
|
||
<view class="feed-source-note"><text>动态列表接口当前没有声明条目 DTO;页面不猜测标题、正文、发布人或时间,已停止展示本地动态。</text></view>
|
||
<view class="feed-shortcuts">
|
||
<view v-for="item in shortcuts" :key="item.key" class="feed-shortcut" @click="openSection(item.key)"><text>{{ item.label }}</text></view>
|
||
</view>
|
||
</template>
|
||
<view class="feed-state-card">
|
||
<view class="feed-state-card__copy"><text>{{ stateCopy.title }}</text><text>{{ stateCopy.copy }}</text></view>
|
||
</view>
|
||
<view class="feed-action" @click="handlePrimaryAction"><text>{{ stateCopy.action }}</text></view>
|
||
</view>
|
||
<AppTabbar active="family" />
|
||
</view>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { computed, ref } from "vue";
|
||
import { onLoad } from "@dcloudio/uni-app";
|
||
import AppTabbar from "@/components/AppTabbar.vue";
|
||
import ModulePageBackground from "@/components/ModulePageBackground.vue";
|
||
import PageHeader from "@/components/PageHeader.vue";
|
||
import { genealogyContext } from "@/utils/genealogy-context.js";
|
||
import { goRoot, openPage } from "@/utils/navigation.js";
|
||
|
||
const genealogyId = ref("");
|
||
const hasValidContext = ref(false);
|
||
const feedState = ref("unavailable");
|
||
const stateCopy = computed(() => {
|
||
if (!hasValidContext.value) {
|
||
return {
|
||
title: "请先选择有效家谱",
|
||
copy: "家族动态必须归属明确家谱,页面不会展示其他家谱的内容。",
|
||
action: "返回我的家谱",
|
||
};
|
||
}
|
||
return {
|
||
title: "动态列表待后端字段合同",
|
||
copy: "已找到动态列表 operation,但响应只声明通用对象数组;待后端提供动态 ID、标题、正文、发布人和时间字段后再恢复列表与详情入口。",
|
||
action: "发布家族动态",
|
||
};
|
||
});
|
||
const shortcuts = [
|
||
{ key: "articles", label: "谱文" },
|
||
{ key: "albums", label: "相册" },
|
||
{ key: "rituals", label: "礼仪" },
|
||
{ key: "memos", label: "备忘" },
|
||
{ key: "people", label: "人物录" },
|
||
{ key: "gifts", label: "贺礼簿" },
|
||
{ key: "merits", label: "功德录" },
|
||
{ key: "videos", label: "家族视频" },
|
||
];
|
||
|
||
onLoad((query) => {
|
||
const hasRouteIdentity = Object.prototype.hasOwnProperty.call(query || {}, "genealogyId");
|
||
const resolvedGenealogyId = hasRouteIdentity
|
||
? String(query?.genealogyId || "")
|
||
: String(genealogyContext.getCurrentGenealogyId() || "");
|
||
genealogyId.value = resolvedGenealogyId;
|
||
hasValidContext.value = /^[1-9]\d*$/.test(resolvedGenealogyId);
|
||
feedState.value = hasValidContext.value ? "unavailable" : "error";
|
||
if (!hasRouteIdentity && hasValidContext.value) {
|
||
goRoot("F01", { genealogyId: resolvedGenealogyId }).catch(() => {
|
||
hasValidContext.value = false;
|
||
feedState.value = "error";
|
||
});
|
||
}
|
||
});
|
||
const toPublish = () => hasValidContext.value
|
||
? openPage("F02", { genealogyId: genealogyId.value }, "F01")
|
||
: goRoot("G01");
|
||
const openSection = (key) => {
|
||
const routes = {
|
||
articles: "F04",
|
||
albums: "F07",
|
||
rituals: "R05",
|
||
memos: "R10",
|
||
people: "R01",
|
||
gifts: "R03",
|
||
merits: "R11",
|
||
videos: "F10",
|
||
};
|
||
return openPage(routes[key], { genealogyId: genealogyId.value }, "F01");
|
||
};
|
||
const handlePrimaryAction = () => hasValidContext.value ? toPublish() : goRoot("G01");
|
||
</script>
|
||
|
||
<style scoped lang="scss">
|
||
@use "../../styles/adaptive-frame-profiles.scss" as adaptive;
|
||
.family-page { display: flex; min-height: 100vh; flex-direction: column; background: $paper; }
|
||
.family-page__header, .feed-content { z-index: 1; }
|
||
.feed-content { flex: 1; padding: 24rpx 24rpx 190rpx; }
|
||
.feed-heading text { display: block; }
|
||
.feed-heading text:first-child { color: $ink; font-family: STKaiti, KaiTi, serif; font-size: 31rpx; font-weight: 700; }
|
||
.feed-heading text:last-child { margin-top: 6rpx; color: $ink-muted; font-size: 23rpx; }
|
||
.feed-source-note { margin-top: 10rpx; padding: 12rpx 16rpx; border: 1rpx solid rgba(128, 106, 81, .22); border-radius: 10rpx; background: rgba(255, 255, 255, .56); }
|
||
.feed-source-note text { display: block; color: $ink-muted; font-size: 20rpx; line-height: 1.5; }
|
||
.feed-shortcuts { @include adaptive.adaptive-scroll-button(secondary); display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); width: 100%; min-height: 48px; margin-top: 15rpx; }
|
||
.feed-shortcut { width: 100%; height: 48px; min-height: 44px; }
|
||
.feed-shortcut text { display: flex; align-items: center; justify-content: center; height: 100%; color: $ink; font-size: 22rpx; font-weight: 700; }
|
||
.feed-state-card { @include adaptive.adaptive-family-letter; display: flex; width: 100%; min-height: 230rpx; flex-direction: column; justify-content: center; margin-top: 70rpx; box-sizing: border-box; }
|
||
.feed-state-card__copy { padding: 23% 10%; box-sizing: border-box; text-align: center; }
|
||
.feed-state-card text { display: block; }
|
||
.feed-state-card text:first-child { color: $ink; font-family: STKaiti, KaiTi, serif; font-size: 31rpx; font-weight: 700; }
|
||
.feed-state-card text:last-child { margin-top: 13rpx; color: $ink-muted; font-size: 23rpx; line-height: 1.45; }
|
||
.feed-action { @include adaptive.adaptive-scroll-button(primary); width: 514rpx; max-width: 100%; min-height: 76rpx; margin: 19rpx auto 0; }
|
||
.feed-action text { display: flex; align-items: center; justify-content: center; height: 100%; color: #fff9ed; font-size: 24rpx; font-weight: 700; }
|
||
</style>
|