文件
yjyf/yjyf-app/pages/message/message.vue
YuanWen 9ae2b976a8 feat: 重构首页与全局UI,新增服务选择抽屉与统一导航组件
新增统一导航栏组件YjyfNavBar,替换各页面原生导航
新增服务选择抽屉组件GoodsPickerDrawer,实现分类选品流程
新增tabbar图标矢量资源,优化底部导航样式
新增后端运力统计接口与多商品下单逻辑
修复页面跳转逻辑,统一使用switchTab/redirectTo
优化订单创建与评价页的UI组件化,提升一致性
2026-11-02 18:27:37 +08:00

98 行
3.7 KiB
Vue

此文件含有模棱两可的 Unicode 字符

此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。

<template>
<view class="page">
<!-- 统一顶部导航栏(安全距离自适应) -->
<YjyfNavBar theme="white" title="消息中心" :border="true" />
<view class="head">
<view class="cats">
<view v-for="c in cats" :key="c.key" class="cat" :class="{ on: category === c.key }" @tap="switchCat(c.key)">{{ c.name }}</view>
</view>
<text class="read-all" @tap="readAll">全部已读</text>
</view>
<view class="list">
<view class="msg" :class="{ unread: !m.is_read }" v-for="m in list" :key="m.id" @tap="open(m)">
<view class="msg-top">
<view class="dot" v-if="!m.is_read"></view>
<text class="title">{{ m.title }}</text>
<text class="time">{{ m.time_text }}</text>
</view>
<text class="content">{{ m.content }}</text>
<text class="go" v-if="m.order_id">查看订单 ›</text>
</view>
<view class="empty" v-if="!loading && !list.length">暂无消息</view>
</view>
<YjyfTabBar :current="2" />
</view>
</template>
<script setup>
import { ref } from 'vue';
import YjyfTabBar from '@/components/YjyfTabBar.vue';
import { onShow, onPullDownRefresh } from '@dcloudio/uni-app';
import api from '@/utils/api.js';
import { isLogin, toLogin } from '@/utils/request.js';
const list = ref([]);
const loading = ref(false);
const category = ref('all');
const cats = [
{ key: 'all', name: '全部' },
{ key: 'order', name: '订单' },
{ key: 'system', name: '系统' },
{ key: 'remind', name: '提醒' }
];
async function load() {
if (!isLogin()) { toLogin(); return; }
loading.value = true;
try {
const res = await api.messageList({ category: category.value, limit: 30 });
list.value = res.list || [];
} catch (e) {
} finally {
loading.value = false;
}
}
function switchCat(k) { category.value = k; load(); }
async function open(m) {
if (!m.is_read) {
try { await api.messageRead({ id: m.id }); m.is_read = 1; } catch (e) {}
}
if (m.order_id) {
uni.navigateTo({ url: '/pages/order/detail?id=' + m.order_id });
}
}
async function readAll() {
try {
const res = await api.messageReadAll({});
uni.showToast({ title: '已全部标记已读(' + res.count + ' 条)', icon: 'none' });
load();
} catch (e) {}
}
onShow(() => load());
onPullDownRefresh(() => { load().then(() => uni.stopPullDownRefresh()); });
</script>
<style scoped>
.page { min-height: 100vh; background: #F5F6F8; padding-bottom: 40rpx; }
.head { display: flex; align-items: center; background: #fff; padding: 20rpx 24rpx; box-shadow: 0 4rpx 12rpx rgba(0,0,0,.03); }
.cats { flex: 1; display: flex; }
.cat { margin-right: 14rpx; padding: 0 22rpx; line-height: 54rpx; border-radius: 27rpx; background: #F5F5F5; font-size: 24rpx; color: #666; }
.cat.on { background: #FFF3E6; color: #E36B0C; font-weight: 600; }
.read-all { font-size: 24rpx; color: #F0710D; }
.list { padding: 22rpx 28rpx; }
.msg { background: #fff; border-radius: 20rpx; padding: 22rpx 24rpx; margin-bottom: 18rpx; box-shadow: 0 6rpx 20rpx rgba(240,129,31,.06); }
.msg.unread { border-left: 6rpx solid #F0710D; }
.msg-top { display: flex; align-items: center; }
.dot { width: 12rpx; height: 12rpx; border-radius: 50%; background: #F0710D; margin-right: 10rpx; }
.title { flex: 1; min-width: 0; font-size: 28rpx; font-weight: 600; color: #1F1F1F; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.time { flex-shrink: 0; margin-left: 12rpx; font-size: 22rpx; color: #AAAAAA; }
.content { display: block; margin-top: 10rpx; font-size: 24rpx; color: #666; line-height: 34rpx; }
.go { display: block; margin-top: 10rpx; font-size: 22rpx; color: #4A7CFF; }
.empty { padding: 110rpx 0; text-align: center; font-size: 24rpx; color: #9A9A9A; }
</style>