Files
jiapuapp/pages/notification/n02-message-detail.vue
T

206 lines
5.4 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.
<!-- 页面编号N-02用途按通知 ID 读取服务端通知详情 -->
<template>
<view class="message-detail-page">
<ModulePageBackground module="notification" />
<view class="page-header"
><PageHeader title="消息详情" custom-back @back="backToMessages"
/></view>
<view class="page-content">
<view v-if="state === 'loading'" class="state-card"
><AppLoading text="正在读取消息详情"
/></view>
<view v-else-if="state === 'error'" class="state-card">
<text>暂时无法读取消息详情</text>
<text>{{ loadError || "请稍后重试。" }}</text>
<AppButton
block
type="secondary"
label="重新加载"
@click="loadDetail"
/>
<AppButton block label="返回消息中心" @click="backToMessages" />
</view>
<view v-else-if="state === 'invalid'" class="state-card">
<text>消息不存在或链接已失效</text>
<text>请返回消息中心查看最新通知</text>
<AppButton block label="返回消息中心" @click="backToMessages" />
</view>
<view v-else class="detail-card">
<text class="detail-title">{{ detail.noticeTitle || "通知消息" }}</text>
<text v-if="detail.publishTime" class="detail-time">{{
detail.publishTime
}}</text>
<view class="detail-content"
><text>{{ detail.noticeContent || "暂无通知正文" }}</text></view
>
<view
v-if="
detail.noticeType ||
detail.genealogyName ||
detail.senderNickName ||
detail.bizSummary
"
class="detail-meta"
>
<view v-if="detail.noticeType" class="detail-meta__row"
><text>通知类型</text><text>{{ detail.noticeType }}</text></view
>
<view v-if="detail.genealogyName" class="detail-meta__row"
><text>所属家谱</text><text>{{ detail.genealogyName }}</text></view
>
<view v-if="detail.senderNickName" class="detail-meta__row"
><text>发送人</text><text>{{ detail.senderNickName }}</text></view
>
<view v-if="detail.bizSummary" class="detail-meta__row"
><text>关联事项</text><text>{{ detail.bizSummary }}</text></view
>
</view>
</view>
</view>
</view>
</template>
<script setup>
import { ref } from "vue";
import { onLoad, onUnload } 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 {
appApi,
createRequestController,
isRequestCancelled,
} from "@/utils/api.js";
import { returnTo } from "@/utils/navigation.js";
const notificationId = ref("");
const detail = ref({});
const state = ref("loading");
const loadError = ref("");
const controller = createRequestController();
let active = true;
const loadDetail = async () => {
if (!/^[1-9]\d*$/.test(notificationId.value)) {
state.value = "invalid";
return;
}
controller.abort();
state.value = "loading";
loadError.value = "";
try {
detail.value = await appApi.getNotificationDetail(notificationId.value, {
requestController: controller,
});
if (!active) return;
state.value = "ready";
} catch (error) {
if (!active || isRequestCancelled(error)) return;
loadError.value = error?.message || "请稍后重试。";
state.value = "error";
}
};
const backToMessages = () => returnTo("N01");
onLoad((options) => {
notificationId.value = String(options?.id || "");
if (!/^[1-9]\d*$/.test(notificationId.value)) {
state.value = "invalid";
return;
}
loadDetail();
});
onUnload(() => {
active = false;
controller.abort();
});
</script>
<style scoped lang="scss">
@import "../../styles/adaptive-frame-profiles.scss";
.message-detail-page {
display: flex;
min-height: 100vh;
flex-direction: column;
background: $paper;
}
.page-header,
.page-content {
z-index: 1;
}
.page-content {
flex: 1;
padding: 18rpx 24rpx 72rpx;
}
.state-card,
.detail-card {
box-sizing: border-box;
@include adaptive-family-content;
}
.state-card {
min-height: 340rpx;
padding: 78rpx 52rpx 50rpx;
text-align: center;
}
.state-card text {
display: block;
}
.state-card text:first-child,
.detail-title {
color: $ink;
font-family: STKaiti, KaiTi, serif;
font-size: clamp(19px, 35rpx, 24px);
font-weight: 700;
}
.state-card text:nth-child(2) {
margin-top: 18rpx;
color: $ink-muted;
font-size: clamp(15px, 24rpx, 18px);
line-height: 1.65;
}
.state-card .app-button {
margin-top: 28rpx;
}
.detail-card {
padding: 44rpx 38rpx;
}
.detail-title,
.detail-time {
display: block;
}
.detail-time {
margin-top: 16rpx;
color: $ink-muted;
font-size: clamp(15px, 24rpx, 18px);
}
.detail-content {
margin-top: 36rpx;
color: $ink;
font-size: clamp(16px, 29rpx, 20px);
line-height: 1.8;
white-space: pre-wrap;
}
.detail-meta {
margin-top: 42rpx;
padding-top: 24rpx;
border-top: 1rpx solid rgba(91, 70, 42, 0.16);
}
.detail-meta__row {
display: flex;
gap: 22rpx;
padding: 10rpx 0;
color: $ink-muted;
font-size: clamp(15px, 24rpx, 18px);
line-height: 1.5;
}
.detail-meta__row text:first-child {
flex: 0 0 116rpx;
}
.detail-meta__row text:last-child {
flex: 1;
color: $ink;
}
</style>