Files
jiapuapp/pages/records/r05-ritual-list.vue
T
2026-07-23 08:24:07 +08:00

217 lines
5.9 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!-- 页面编号R-05用途当前家谱的礼仪活动列表与本地创建预览入口 -->
<template>
<view class="ritual-page" :class="stateClasses">
<ModulePageBackground module="records" />
<view class="page-header">
<PageHeader
title="礼仪活动"
:action="hasValidContext ? '填写预览' : ''"
@action="createCeremonyPreview"
/>
</view>
<view v-if="ceremonyState === 'loading'" class="page-loading">
<AppLoading
text="正在整理礼仪活动"
description="请稍候,正在核对当前家谱的活动记录。"
/>
</view>
<view v-else class="page-content">
<template v-if="ceremonyState === 'ready' && ceremonies.length">
<view
v-for="ceremony in ceremonies"
:key="ceremony.ceremonyId"
class="record-card"
role="button"
:aria-label="`查看${ceremony.ceremonyTitle}`"
@click="openCeremony(ceremony)"
>
<text>{{ ceremony.ceremonyType }}</text>
<text>{{ ceremony.ceremonyTitle }}</text>
<text>
{{ ceremony.ceremonyTime }} ·
{{ ceremony.location || "地点待定" }}
</text>
<text>查看活动与受邀信息</text>
</view>
<AppButton block label="填写礼仪预览" @click="createCeremonyPreview" />
</template>
<view v-else class="state-card">
<text>{{ stateCopy.title }}</text>
<text>{{ stateCopy.copy }}</text>
<AppButton
:type="ceremonyState === 'empty' ? 'primary' : 'secondary'"
block
:label="stateCopy.action"
@click="handleStateAction"
/>
</view>
</view>
</view>
</template>
<script setup>
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 {
getGenealogyFixtureAccess,
listCeremonyFixtures,
} from "@/data/mock.js";
import { goBack, openPage } from "@/utils/navigation.js";
const genealogyId = ref("");
const ceremonies = ref([]);
const ceremonyState = ref("loading");
const hasValidContext = computed(() =>
["ready", "empty"].includes(ceremonyState.value),
);
const stateClasses = computed(() => ({
"ceremony-state--loading": ceremonyState.value === "loading",
"ceremony-state--empty": ceremonyState.value === "empty",
"ceremony-state--error": ceremonyState.value === "error",
"ceremony-state--invalid": ceremonyState.value === "invalid",
}));
const stateCopy = computed(() => ({
error: {
title: "礼仪活动暂不可用",
copy: "请稍后重新查看,已有活动不会受到影响。",
action: "重新查看",
},
invalid: {
title: "礼仪活动入口无效",
copy: "没有找到可访问的成员家谱,页面不会展示其他家谱活动。",
action: "返回上一页",
},
empty: {
title: "还没有礼仪活动",
copy: "可以先填写一份本地预览;正式创建仍需等待线上写接口启用。",
action: "填写礼仪预览",
},
})[ceremonyState.value] || {
title: "礼仪活动暂不可用",
copy: "请返回上一页重新进入。",
action: "返回上一页",
});
onLoad((query) => {
genealogyId.value = String(query.genealogyId || "");
const access = getGenealogyFixtureAccess(genealogyId.value);
if (!["owner", "member"].includes(access.accessRole)) {
ceremonies.value = [];
ceremonyState.value = "invalid";
return;
}
ceremonies.value = listCeremonyFixtures(genealogyId.value);
ceremonyState.value = ["loading", "empty", "error"].includes(query.state)
? query.state
: ceremonies.value.length
? "ready"
: "empty";
});
const openCeremony = (ceremony) =>
openPage(
"R06",
{
genealogyId: genealogyId.value,
ceremonyId: String(ceremony.ceremonyId),
},
"R05",
);
const createCeremonyPreview = () =>
hasValidContext.value
? openPage(
"R07",
{ genealogyId: genealogyId.value, mode: "create" },
"R05",
)
: Promise.resolve(false);
const restoreCeremonies = () => {
ceremonies.value = listCeremonyFixtures(genealogyId.value);
ceremonyState.value = ceremonies.value.length ? "ready" : "empty";
};
const handleStateAction = () => {
if (ceremonyState.value === "invalid") return goBack();
if (ceremonyState.value === "error") return restoreCeremonies();
return createCeremonyPreview();
};
</script>
<style scoped lang="scss">
@use "../../styles/adaptive-frame-profiles.scss" as adaptive;
.ritual-page {
display: flex;
min-height: 100vh;
flex-direction: column;
background: $paper;
}
.page-header,
.page-loading,
.page-content {
z-index: 1;
}
.page-loading {
min-height: calc(100vh - 100rpx);
}
.page-content {
display: flex;
flex-direction: column;
gap: 16rpx;
padding: 18rpx 24rpx 72rpx;
}
.record-card,
.state-card {
box-sizing: border-box;
@include adaptive.adaptive-records-content;
}
.record-card {
min-height: 190rpx;
padding: 32rpx 46rpx;
}
.record-card > text,
.state-card > text {
display: block;
}
.record-card > text:first-child {
color: $brand-red;
font-size: 21rpx;
}
.record-card > text:nth-child(2) {
margin-top: 6rpx;
color: $ink;
font-size: 31rpx;
font-weight: 700;
}
.record-card > text:nth-child(3) {
margin-top: 9rpx;
color: $ink-muted;
font-size: 23rpx;
line-height: 1.5;
}
.record-card > text:last-child {
margin-top: 9rpx;
color: $brand-red;
font-size: 21rpx;
}
.state-card {
min-height: 340rpx;
padding: 78rpx 52rpx 50rpx;
text-align: center;
}
.state-card > text:first-child {
color: $ink;
font-size: 35rpx;
font-weight: 700;
}
.state-card > text:nth-child(2) {
margin-top: 18rpx;
color: $ink-muted;
font-size: 24rpx;
line-height: 1.65;
}
.state-card .app-button {
margin-top: 28rpx;
}
</style>