Files
2026-09-24 16:25:22 +08:00

192 lines
5.5 KiB
Plaintext
Raw Permalink 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="hr-page" style="background-color:#F3F4F6">
<hr-statusbar bg="#FFFFFF"></hr-statusbar>
<view class="ms-nav">
<text class="ms-nav-t">消息</text>
<view class="ms-nav-a" @click="onReadAll">
<x-icon name="check-double-line" color="#6B7280" font-size="16"></x-icon>
<text class="ms-nav-a-t">全部已读</text>
</view>
</view>
<view class="hr-flow">
<scroll-view class="hr-scroll" :scroll-y="true" :show-scrollbar="false">
<view class="hr-body">
<!-- 消息分类筛选(组件库 xRadioButton 分段切换) -->
<view style="margin-bottom:8rpx">
<x-radio-button v-model="chipId" :list="chipTabs" height="64rpx" space="4rpx" round="22rpx"
text-style="font-weight:bold;" bg-color="#E5E7EB" active-color="#2563EB"
active-font-color="#FFFFFF" font-color="#6B7280" font-size="22rpx"></x-radio-button>
</view>
<view v-for="(g, gi) in groups" :key="gi">
<hr-sec :title="g.title" :more="g.count > 0 ? g.count.toString() + ' 条' : ''"></hr-sec>
<hr-card :variant="g.danger ? 'danger' : 'list'">
<hr-lrow v-for="(m, i) in g.items" :key="i" :icon="m.icon" :theme="m.theme" :title="m.title"
:sub="m.sub" :value="m.action" :value-theme="m.theme == 'red' ? 'red' : 'pri'"
:value-bold="true" :is-last="i == g.items.length - 1" @click="onMsgClick(m, gi, i)">
<template v-slot:right>
<view v-if="isUnread(gi, i, m.unread)" class="hr-badge">
<text class="hr-badge-t">{{ m.unread }}</text>
</view>
</template>
</hr-lrow>
</hr-card>
</view>
<hr-empty v-if="groups.length == 0" icon="✉" title="暂无消息"
sub="库存预警、借用审批与系统通知会汇总到这里"></hr-empty>
<view style="height:28rpx"></view>
</view>
</scroll-view>
<!-- 加载中覆盖层(组件库 xLoading -->
<view v-if="loading" class="hr-loading-mask">
<x-loading label="加载中…" :icon-size="'44rpx'" :text-size="'26rpx'" :vertical="true" color="#2563EB"
text-color="#6B7280"></x-loading>
</view>
</view>
<hr-tabbar :active="3"></hr-tabbar>
</view>
</template>
<script lang="uts" setup>
import { ref, computed } from 'vue'
import { keeperMsgGroups } from '@/mock/index.uts'
import { HrMsg, HrMsgGroup } from '@/mock/types.uts'
import { navTo } from '@/utils/nav.uts'
import { mockRequest } from '@/utils/request.uts'
import { markMessagesRead } from '@/utils/unread.uts'
import { RADIO_BUTTON } from '@/uni_modules/tmx-ui/interface.uts'
/**
* s33 消息中心 · 物资端(仓管 Tab「消息」)
* 库存预警自动置顶;借用审批「去审批」直达设备借出台账。
* 角标 = 未读数,阅读后消失:整页查看清 tabbar/入口角标,点开单条清该条角标。
*/
/**
* 消息分类筛选(组件库 xRadioButton 分段切换,替代原 hr-chip 横向滚动)
* ⚠ RADIO_BUTTON 的 id 是 string:统一用下标字符串,选中值即筛选序号。
*/
const chipTabs : RADIO_BUTTON[] = [
{ id: '0', title: '全部 9' } as RADIO_BUTTON,
{ id: '1', title: '库存预警 4' } as RADIO_BUTTON,
{ id: '2', title: '借用审批 3' } as RADIO_BUTTON,
{ id: '3', title: '系统 2' } as RADIO_BUTTON
]
const chipId = ref('0')
/** 由字符串 id 换算分类序号,供分组筛选使用 */
const chip = computed(() : number => {
const i = parseInt(chipId.value)
return isNaN(i) ? 0 : i
})
/** 已读的条目(key = 分组下标-条目下标) */
const readKeys = ref<string[]>([])
const loading = ref(true)
onLoad(() => {
mockRequest(() => {
loading.value = false
})
})
onPageShow(() => {
markMessagesRead()
})
function keyOf(gi : number, i : number) : string {
return gi.toString() + '-' + i.toString()
}
function isRead(gi : number, i : number) : boolean {
return readKeys.value.indexOf(keyOf(gi, i)) > -1
}
function isUnread(gi : number, i : number, n : number) : boolean {
if (n <= 0) { return false }
return !isRead(gi, i)
}
function markRead(gi : number, i : number) : void {
const k = keyOf(gi, i)
if (readKeys.value.indexOf(k) > -1) { return }
const arr = readKeys.value
arr.push(k)
readKeys.value = arr
}
const groups = computed(() : HrMsgGroup[] => {
if (chip.value == 1) {
return [keeperMsgGroups[0]]
}
if (chip.value == 2) {
return [keeperMsgGroups[1]]
}
if (chip.value == 3) {
return [keeperMsgGroups[2]]
}
return keeperMsgGroups
})
function onMsgClick(m : HrMsg, gi : number, i : number) : void {
markRead(gi, i)
if (m.action == '去审批 ') {
navTo('/pages/warehouse/devices')
return
}
uni.showModal({ title: m.title, content: m.sub, showCancel: false })
}
function onReadAll() : void {
// 全部标记已读 → 所有条目角标一并消失
const arr : string[] = []
for (let gi = 0; gi < groups.value.length; gi++) {
const g = groups.value[gi]
for (let i = 0; i < g.items.length; i++) {
arr.push(keyOf(gi, i))
}
}
readKeys.value = arr
markMessagesRead()
uni.showToast({ title: '已全部标记为已读', icon: 'success' })
}
</script>
<style>
.ms-nav {
height: 96rpx;
display: flex;
flex-direction: row;
align-items: center;
padding-left: 32rpx;
padding-right: 32rpx;
background-color: #FFFFFF;
border-bottom: 2rpx solid #F3F4F6;
}
.ms-nav-t {
font-size: 33.6rpx;
font-weight: bold;
color: #1F2937;
}
.ms-nav-a {
margin-left: auto;
display: flex;
flex-direction: row;
align-items: center;
}
.ms-nav-a-t {
font-size: 29.2rpx;
color: #6B7280;
margin-left: 8rpx;
}
</style>