feat: 完成前端业务闭环与后端联调
This commit is contained in:
@@ -1,20 +1,20 @@
|
||||
<template>
|
||||
<view class="message-page">
|
||||
<ModulePageBackground module="notification" />
|
||||
<view class="page-header"><PageHeader root title="消息中心" :action="unreadCount > 0 ? '设为已读' : ''" @action="requestMarkAllRead" /></view>
|
||||
<view class="page-header"><PageHeader :root="!sourceKey" :custom-back="Boolean(sourceKey)" title="消息中心" :action="unreadCount > 0 ? '设为已读' : ''" @back="returnToSource" @action="requestMarkAllRead" /></view>
|
||||
<view class="page-content">
|
||||
<view v-if="notificationListState === 'loading'" class="state-card"><AppLoading text="正在读取消息通知" /></view>
|
||||
<view v-else-if="notificationListState === 'error'" class="state-card">
|
||||
<text>暂时无法读取消息状态</text>
|
||||
<text>{{ notificationListError || "请检查网络后重新加载。" }}</text>
|
||||
<AppButton block type="secondary" label="重新加载" @click="loadNotifications" />
|
||||
<AppButton block label="返回我的" @click="returnToProfile" />
|
||||
<AppButton block :label="returnLabel" @click="returnToSource" />
|
||||
</view>
|
||||
<view v-else-if="!notifications.length" class="state-card message-status-card">
|
||||
<text>当前没有通知</text>
|
||||
<text>新的家谱动态、审核和活动消息会在这里展示。</text>
|
||||
<text v-if="markAllReadError" class="message-operation-error">{{ markAllReadError }}</text>
|
||||
<AppButton block type="secondary" label="返回我的" @click="returnToProfile" />
|
||||
<AppButton block type="secondary" :label="returnLabel" @click="returnToSource" />
|
||||
</view>
|
||||
<view v-else class="message-list">
|
||||
<view
|
||||
@@ -39,7 +39,7 @@
|
||||
</view>
|
||||
</view>
|
||||
<AppPromotionStrip placement="message_bottom" title="消息页推荐" />
|
||||
<AppTabbar active="profile" />
|
||||
<AppTabbar :active="sourceTab" />
|
||||
<AppDialog
|
||||
:visible="markAllVisible"
|
||||
eyebrow="消息状态"
|
||||
@@ -56,8 +56,8 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from "vue";
|
||||
import { onLoad, onShow, onUnload } from "@dcloudio/uni-app";
|
||||
import { computed, ref } from "vue";
|
||||
import { onBackPress, onLoad, onShow, onUnload } from "@dcloudio/uni-app";
|
||||
import AppButton from "@/components/AppButton.vue";
|
||||
import AppDialog from "@/components/AppDialog.vue";
|
||||
import AppLoading from "@/components/AppLoading.vue";
|
||||
@@ -71,7 +71,7 @@ import {
|
||||
} from "@/services/api/request-controller.js";
|
||||
import { notificationApi } from "@/services/api/notification-service.js";
|
||||
import { getRequestErrorMessage } from "@/services/api/request-error-message.js";
|
||||
import { goRoot, openPage } from "@/utils/navigation/gateway.js";
|
||||
import { goBack, goRoot, handleBackPress, openPage } from "@/utils/navigation/gateway.js";
|
||||
|
||||
const unreadCount = ref(0);
|
||||
const notifications = ref([]);
|
||||
@@ -82,8 +82,12 @@ const markAllReadController = createRequestController();
|
||||
const markAllVisible = ref(false);
|
||||
const markAllSubmitting = ref(false);
|
||||
const markAllReadError = ref("");
|
||||
const sourceKey = ref("");
|
||||
let isPageActive = true;
|
||||
|
||||
const returnLabel = computed(() => (sourceKey.value ? "返回上一页" : "返回我的"));
|
||||
const sourceTab = computed(() => (sourceKey.value === "G01" ? "genealogy" : "profile"));
|
||||
|
||||
const loadNotifications = async () => {
|
||||
notificationListController.abort();
|
||||
notificationListState.value = "loading";
|
||||
@@ -126,12 +130,23 @@ const confirmMarkAllRead = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
const returnToProfile = () => goRoot("M01");
|
||||
const returnToSource = () => (sourceKey.value ? goBack() : goRoot("M01"));
|
||||
const closeMarkAllDialog = () => {
|
||||
if (markAllSubmitting.value) return false;
|
||||
markAllVisible.value = false;
|
||||
return true;
|
||||
};
|
||||
const openNotification = (item) => openPage("N02", { id: item.notificationId });
|
||||
onLoad(loadNotifications);
|
||||
onLoad((query) => {
|
||||
sourceKey.value = String(query?.sourceKey || "");
|
||||
loadNotifications();
|
||||
});
|
||||
onShow(() => {
|
||||
if (notificationListState.value !== "loading") loadNotifications();
|
||||
});
|
||||
onBackPress((event) =>
|
||||
markAllVisible.value ? handleBackPress(event, closeMarkAllDialog) : false,
|
||||
);
|
||||
onUnload(() => {
|
||||
isPageActive = false;
|
||||
notificationListController.abort();
|
||||
@@ -153,7 +168,7 @@ onUnload(() => {
|
||||
}
|
||||
.page-content {
|
||||
flex: 1;
|
||||
padding: 18rpx 24rpx 190rpx;
|
||||
padding: 18rpx 24rpx calc(190rpx + env(safe-area-inset-bottom));
|
||||
}
|
||||
.state-card {
|
||||
box-sizing: border-box;
|
||||
@@ -182,7 +197,9 @@ onUnload(() => {
|
||||
}
|
||||
.message-list {
|
||||
display: grid;
|
||||
gap: 16rpx;
|
||||
gap: 20rpx;
|
||||
box-sizing: border-box;
|
||||
padding: 28rpx 24rpx;
|
||||
@include adaptive-notification-content;
|
||||
}
|
||||
.message-row {
|
||||
@@ -192,7 +209,7 @@ onUnload(() => {
|
||||
padding: 24rpx;
|
||||
border: 1rpx solid rgba(128, 89, 49, 0.26);
|
||||
border-radius: 12rpx;
|
||||
background: rgba(255, 252, 245, 0.78);
|
||||
background: rgba($paper, 0.9);
|
||||
}
|
||||
.message-row__body { min-width: 0; flex: 1; }
|
||||
.message-row__title-line { display: flex; gap: 12rpx; align-items: center; }
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
:action="notificationDetail.readStatus === '0' ? (markReadSubmitting ? '正在设置' : '设为已读') : ''"
|
||||
custom-back
|
||||
@action="requestMarkRead"
|
||||
@back="backToMessages"
|
||||
@back="requestBack"
|
||||
/></view>
|
||||
<view class="page-content">
|
||||
<view v-if="notificationDetailState === 'loading'" class="state-card"
|
||||
@@ -80,7 +80,7 @@
|
||||
|
||||
<script setup>
|
||||
import { computed, ref } from "vue";
|
||||
import { onLoad, onUnload } from "@dcloudio/uni-app";
|
||||
import { onBackPress, onLoad, onUnload } from "@dcloudio/uni-app";
|
||||
import AppButton from "@/components/AppButton.vue";
|
||||
import AppDialog from "@/components/AppDialog.vue";
|
||||
import AppLoading from "@/components/AppLoading.vue";
|
||||
@@ -92,7 +92,7 @@ import {
|
||||
} from "@/services/api/request-controller.js";
|
||||
import { notificationApi } from "@/services/api/notification-service.js";
|
||||
import { getRequestErrorMessage } from "@/services/api/request-error-message.js";
|
||||
import { openNoticeTarget, returnTo } from "@/utils/navigation/gateway.js";
|
||||
import { handleBackPress, openNoticeTarget, returnTo } from "@/utils/navigation/gateway.js";
|
||||
|
||||
const notificationId = ref("");
|
||||
const notificationDetail = ref({});
|
||||
@@ -172,6 +172,14 @@ const confirmMarkRead = async () => {
|
||||
if (isPageActive) markReadSubmitting.value = false;
|
||||
}
|
||||
};
|
||||
const requestBack = () => {
|
||||
if (markReadSubmitting.value) return true;
|
||||
if (markReadVisible.value) {
|
||||
markReadVisible.value = false;
|
||||
return true;
|
||||
}
|
||||
return backToMessages();
|
||||
};
|
||||
|
||||
onLoad((options) => {
|
||||
notificationId.value = String(options?.id || "");
|
||||
@@ -186,6 +194,7 @@ onUnload(() => {
|
||||
notificationDetailController.abort();
|
||||
markReadController.abort();
|
||||
});
|
||||
onBackPress((event) => handleBackPress(event, requestBack));
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@@ -202,12 +211,13 @@ onUnload(() => {
|
||||
}
|
||||
.page-content {
|
||||
flex: 1;
|
||||
padding: 18rpx 24rpx 72rpx;
|
||||
padding: 18rpx 24rpx calc(72rpx + env(safe-area-inset-bottom));
|
||||
}
|
||||
.state-card,
|
||||
.detail-card {
|
||||
box-sizing: border-box;
|
||||
@include adaptive-notification-content;
|
||||
background-color: rgba($paper, 0.82);
|
||||
}
|
||||
.state-card {
|
||||
min-height: 340rpx;
|
||||
@@ -239,6 +249,8 @@ onUnload(() => {
|
||||
.detail-title,
|
||||
.detail-time {
|
||||
display: block;
|
||||
min-width: 0;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
.detail-time {
|
||||
margin-top: 16rpx;
|
||||
@@ -250,6 +262,7 @@ onUnload(() => {
|
||||
color: $ink;
|
||||
font-size: clamp(16px, 29rpx, 20px);
|
||||
line-height: 1.8;
|
||||
overflow-wrap: anywhere;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
.detail-meta {
|
||||
@@ -269,8 +282,10 @@ onUnload(() => {
|
||||
flex: 0 0 116rpx;
|
||||
}
|
||||
.detail-meta__row text:last-child {
|
||||
min-width: 0;
|
||||
flex: 1;
|
||||
color: $ink;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
.detail-operation-error {
|
||||
display: block;
|
||||
|
||||
Reference in New Issue
Block a user