- 新增 000071 数据库迁移:notifications 表支持 distribution_site_id 并自动回填历史分销订单通知 - 通知自动归属:在事务内根据订单或申诉自动关联当前分销站点 ID - 隔离查询与已读控制:列表、未读统计与批量已读均严格按站点隔离,防止主站与分站交叉泄漏 - 前台界面联动:消息中心通知 Tab 及移动端/PC端站内信页面展示分站专属标识与精准过滤
132 lines
3.8 KiB
Vue
132 lines
3.8 KiB
Vue
<script setup lang="ts">
|
|
import { ElMessage } from 'element-plus'
|
|
import { onMounted, ref } from 'vue'
|
|
|
|
import {
|
|
fetchNotifications,
|
|
markNotificationRead,
|
|
type NotificationItem,
|
|
} from '@/features/auth/api/notifications'
|
|
import { notificationUnreadChangedEvent } from '@/features/auth/composables/useNotificationUnreadCount'
|
|
import { formatDateTime } from '@/shared/utils/time'
|
|
import { useDistributionSiteStore } from '@/stores/distributionSite'
|
|
|
|
const distributionStore = useDistributionSiteStore()
|
|
const loading = ref(false)
|
|
const notifications = ref<NotificationItem[]>([])
|
|
const currentPage = ref(1)
|
|
const currentPageSize = ref(20)
|
|
const total = ref(0)
|
|
|
|
onMounted(loadNotifications)
|
|
|
|
async function loadNotifications() {
|
|
loading.value = true
|
|
try {
|
|
const siteCode = distributionStore.isDistribution ? distributionStore.siteCode : undefined
|
|
const result = await fetchNotifications(currentPage.value, currentPageSize.value, siteCode)
|
|
notifications.value = result.items
|
|
total.value = result.total
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
function handleSizeChange() {
|
|
currentPage.value = 1
|
|
loadNotifications()
|
|
}
|
|
|
|
async function markRead(id: number) {
|
|
const siteCode = distributionStore.isDistribution ? distributionStore.siteCode : undefined
|
|
await markNotificationRead(id, siteCode)
|
|
window.dispatchEvent(new Event(notificationUnreadChangedEvent))
|
|
ElMessage.success('已标记为已读')
|
|
await loadNotifications()
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<section class="page">
|
|
<div class="page-header">
|
|
<p class="eyebrow">
|
|
Notifications
|
|
<el-tag
|
|
v-if="distributionStore.isDistribution"
|
|
type="warning"
|
|
effect="light"
|
|
size="small"
|
|
class="distribution-site-tag"
|
|
>
|
|
{{ distributionStore.siteName }}专属分站
|
|
</el-tag>
|
|
</p>
|
|
<h1>
|
|
{{ distributionStore.isDistribution ? `${distributionStore.siteName} · 站内信` : '站内信' }}
|
|
</h1>
|
|
<p>
|
|
{{
|
|
distributionStore.isDistribution
|
|
? `接收【${distributionStore.siteName}】专属分站订单交易、交接、申诉和客服通知。`
|
|
: '接收审核、交接、归还、申诉和仲裁结果通知。'
|
|
}}
|
|
</p>
|
|
</div>
|
|
|
|
<el-empty
|
|
v-if="!loading && notifications.length === 0"
|
|
:description="
|
|
distributionStore.isDistribution
|
|
? `暂无【${distributionStore.siteName}】专属站内信`
|
|
: '暂无站内信'
|
|
"
|
|
/>
|
|
<div v-else v-loading="loading" class="notification-list">
|
|
<div
|
|
v-for="item in notifications"
|
|
:key="item.id"
|
|
class="notification-item"
|
|
:class="{ unread: !item.read_at }"
|
|
>
|
|
<div>
|
|
<span>{{ item.type }}</span>
|
|
<h2>{{ item.title }}</h2>
|
|
<p>{{ item.content }}</p>
|
|
<small>{{ formatDateTime(item.created_at) }}</small>
|
|
</div>
|
|
<div class="notification-actions">
|
|
<RouterLink
|
|
v-if="item.biz_type === 'order' && item.biz_id"
|
|
:to="`/orders/${item.biz_id}`"
|
|
>
|
|
<el-button size="small">查看订单</el-button>
|
|
</RouterLink>
|
|
<el-button v-if="!item.read_at" size="small" type="primary" @click="markRead(item.id)"
|
|
>已读</el-button
|
|
>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="pagination-wrap" v-if="total > 0">
|
|
<el-pagination
|
|
v-model:current-page="currentPage"
|
|
v-model:page-size="currentPageSize"
|
|
:total="total"
|
|
:page-sizes="[10, 20, 50, 100]"
|
|
layout="total, sizes, prev, pager, next"
|
|
@current-change="loadNotifications"
|
|
@size-change="handleSizeChange"
|
|
/>
|
|
</div>
|
|
</section>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.distribution-site-tag {
|
|
margin-left: 8px;
|
|
vertical-align: middle;
|
|
font-weight: 500;
|
|
}
|
|
</style>
|