topfans/frontend/pages/mailbox/index.vue

177 lines
4.7 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.

<template>
<view class="mailbox-list">
<!-- 背景图片 -->
<image class="bg-image" src="/static/square/squearbj.png" mode="aspectFill"></image>
<!-- <Header title="收件箱" :showBack="true" /> -->
<view class="toolbar">
<view class="nav-back" @tap="goBack">
<text class="nav-back-icon"></text>
</view>
<button class="btn-mark-all" @click="onMarkAllRead">[+全部已读]</button>
<button class="btn-delete-all" @click="onClearAll">[+全部删除]</button>
</view>
<scroll-view scroll-y="true" class="list-scroll" @scrolltolower="onScrollLower">
<MailboxGroup v-for="grp in GROUPS" :key="grp.type" :groupKey="grp.type" :label="grp.label"
:collapsed="isCollapsed(grp.type)" :items="itemsByType[grp.type]" :unreadCount="unreadByType[grp.type] || 0"
@toggle="toggleCollapse(grp.type)" @select="onSelectItem" @long-press="onLongPress" />
<!-- <view v-if="!hasAny && !loading" class="empty">暂无通知</view> -->
<view v-if="loading" class="loading">加载中...</view>
<view v-if="hasAny && !hasMore" class="no-more">没有更多了</view>
</scroll-view>
</view>
</template>
<script setup>
import { onLoad, onShow, onHide, onPullDownRefresh } from '@dcloudio/uni-app'
import { useStore } from 'vuex'
// import Header from '../components/Header.vue'
import MailboxGroup from './components/MailboxGroup.vue'
import { useMailboxCenter } from './composables/useMailboxCenter.js'
const {
GROUPS, itemsByType, unreadByType,
loading, hasAny, hasMore,
loadAll, onScrollLower,
onMarkAllRead, onClearAll,
onSelectItem, onLongPress,
isCollapsed, toggleCollapse,
onMarkRead,
} = useMailboxCenter()
const store = useStore()
const goBack = () => {
// 获取页面栈
const pages = getCurrentPages();
if (pages.length > 1) {
// 有上一页,执行返回
uni.navigateBack();
} else {
// 没有上一页跳转到square页面
uni.reLaunch({
url: '/pages/square/square'
});
}
};
// P1-5 fix:App.vue 推送 click 带 ?focus=mailbox&nid=N&type=T 跳进来,
// 这里读 query → 标记已读 → 跳到详情。让"点推送"直达具体消息,不再只是"进收件箱"。
// 用 composable 已有的 onMarkRead(nid, type),不走 store 的同名 action(不存在)。
let focusHandled = false
onLoad((options) => {
if (!options || focusHandled) return
const nid = Number(options.nid)
const type = options.type || ''
if (nid && type) {
focusHandled = true
// fire-and-forget:失败仅 warn,不影响用户进站
onMarkRead(nid, type).catch((e) => {
console.warn('[mailbox/index] markAsRead from push failed:', e)
})
uni.navigateTo({ url: `/pages/mailbox/detail?nid=${nid}&type=${encodeURIComponent(type)}` })
}
})
// P1-2 fix:用户停留在收件箱页时,推送来要 PREPEND_ITEM(否则只剩角标更新、列表无新条目)。
// onShow 置 SET_IS_IN_PAGE=true,onHide=false。App.vue 走 mailbox/applyPushPayload 时,
// mailbox store 的 applyPushPayload 会读 rootState.mailbox.isInMailboxPage 决定是否 PREPEND_ITEM。
onShow(() => {
store.commit('mailbox/SET_IS_IN_PAGE', true)
loadAll()
})
onHide(() => {
store.commit('mailbox/SET_IS_IN_PAGE', false)
})
// 下拉刷新:补 trigger loadAll + 收尾 stopPullDownRefresh
// (pages.json 配了 enablePullDownRefresh: true 才有效)
onPullDownRefresh(async () => {
try {
await loadAll()
} finally {
uni.stopPullDownRefresh()
}
})
</script>
<style lang="scss" scoped>
.mailbox-list {
display: flex;
flex-direction: column;
height: 100vh;
background: #f8f8f8;
/* 背景图片 */
.bg-image {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 120%;
z-index: 0;
pointer-events: none;
}
.toolbar {
display: flex;
gap: 16rpx;
padding: 96rpx 24rpx 16rpx;
// background: #fff;
// border-bottom: 1rpx solid #f0f0f0;
position: relative;
.nav-back {
width: 80rpx;
height: 80rpx;
display: flex;
align-items: center;
justify-content: center;
/* background: rgba(255,255,255,0.5);
border-radius: 50%; */
}
.nav-back-icon {
font-size: 48rpx;
font-weight: bold;
color: #fff;
}
button {
flex: 1;
font-size: 26rpx;
padding: 12rpx 0;
border-radius: 8rpx;
&::after {
border: 0;
}
}
.btn-mark-all {
background: #e8f4ff;
color: #5C40FF;
}
.btn-delete-all {
background: #fff1f0;
color: #f5222d;
}
}
.list-scroll {
flex: 1;
overflow: hidden;
padding: 16rpx 24rpx;
}
.empty,
.loading,
.no-more {
text-align: center;
color: #999;
font-size: 26rpx;
padding: 48rpx 0;
}
}
</style>