| New file |
| | |
| | | <template> |
| | | <view class="message-container"> |
| | | <view class="message-header"> |
| | | <view class="header-title">消息中心</view> |
| | | </view> |
| | | |
| | | <scroll-view class="message-list-scroll" scroll-y="true"> |
| | | <view class="message-list"> |
| | | <!-- 未读消息在前 --> |
| | | <view |
| | | class="message-item" |
| | | v-for="message in sortedMessages" |
| | | :key="message.messageId" |
| | | @click="viewMessageDetail(message)" |
| | | > |
| | | <view class="message-main"> |
| | | <view class="message-title"> |
| | | <text class="title-text">{{ getMessageTypeText(message.messageType) }}</text> |
| | | <view class="unread-dot" v-if="message.isRead === '0'"></view> |
| | | </view> |
| | | <view class="message-content">{{ message.messageContent }}</view> |
| | | <view class="message-time">{{ message.createTime }}</view> |
| | | </view> |
| | | </view> |
| | | |
| | | <view class="no-data" v-if="sortedMessages.length === 0"> |
| | | <uni-icons type="info" size="40" color="#ccc"></uni-icons> |
| | | <text>暂无消息</text> |
| | | </view> |
| | | </view> |
| | | </scroll-view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import { getMyMessages, markAsRead } from '@/api/message' |
| | | |
| | | export default { |
| | | data() { |
| | | return { |
| | | // 消息列表 |
| | | messages: [], |
| | | loading: false |
| | | } |
| | | }, |
| | | computed: { |
| | | // 按未读/已读排序,未读的在前面 |
| | | sortedMessages() { |
| | | return [...this.messages].sort((a, b) => { |
| | | if (a.isRead === b.isRead) { |
| | | // 相同状态按时间倒序 |
| | | return new Date(b.createTime) - new Date(a.createTime); |
| | | } |
| | | // 未读的排在前面 |
| | | return a.isRead === '0' ? -1 : 1; |
| | | }); |
| | | } |
| | | }, |
| | | onLoad() { |
| | | this.loadMessages() |
| | | }, |
| | | onShow() { |
| | | // 每次显示页面时刷新消息 |
| | | this.loadMessages() |
| | | // 更新TabBar徽标 |
| | | this.updateTabBarBadge() |
| | | }, |
| | | onPullDownRefresh() { |
| | | this.loadMessages().then(() => { |
| | | uni.stopPullDownRefresh() |
| | | }) |
| | | }, |
| | | methods: { |
| | | // 加载消息列表 |
| | | async loadMessages() { |
| | | try { |
| | | this.loading = true |
| | | const response = await getMyMessages() |
| | | if (response.code === 200) { |
| | | this.messages = response.data || [] |
| | | } else { |
| | | this.$modal.showToast(response.msg || '加载消息失败') |
| | | } |
| | | } catch (error) { |
| | | console.error('加载消息失败:', error) |
| | | this.$modal.showToast('加载消息失败') |
| | | } finally { |
| | | this.loading = false |
| | | } |
| | | }, |
| | | |
| | | // 获取消息类型文本 |
| | | getMessageTypeText(type) { |
| | | const typeMap = { |
| | | 'CREATE': '创建成功', |
| | | 'PUSH': '任务推送', |
| | | 'STATUS': '状态变更', |
| | | 'ASSIGN': '任务分配' |
| | | } |
| | | return typeMap[type] || '系统消息'; |
| | | }, |
| | | |
| | | // 查看消息详情(跳转到任务详情) |
| | | async viewMessageDetail(message) { |
| | | try { |
| | | // 校验消息对象 |
| | | if (!message || !message.messageId) { |
| | | console.error('消息数据异常:', message) |
| | | this.$modal.showToast('消息数据异常') |
| | | return |
| | | } |
| | | |
| | | // 标记为已读 |
| | | if (message.isRead === '0') { |
| | | await markAsRead(message.messageId) |
| | | message.isRead = '1' |
| | | // 更新徽标 |
| | | this.updateTabBarBadge() |
| | | } |
| | | |
| | | // 跳转到任务详情页面 |
| | | if (message.taskId) { |
| | | this.$tab.navigateTo(`/pages/task/detail?id=${message.taskId}`) |
| | | } else { |
| | | this.$modal.showToast('无法找到关联任务') |
| | | } |
| | | } catch (error) { |
| | | console.error('标记消息已读失败:', error) |
| | | // 即使标记失败,也允许跳转 |
| | | if (message && message.taskId) { |
| | | this.$tab.navigateTo(`/pages/task/detail?id=${message.taskId}`) |
| | | } |
| | | } |
| | | }, |
| | | |
| | | // 更新TabBar徽标 |
| | | updateTabBarBadge() { |
| | | const unreadCount = this.messages.filter(msg => msg.isRead === '0').length |
| | | console.log('未读消息数量:', unreadCount) |
| | | |
| | | if (unreadCount > 0) { |
| | | uni.setTabBarBadge({ |
| | | index: 3, // 消息页面在tabBar中的索引 |
| | | text: unreadCount > 99 ? '99+' : unreadCount.toString() |
| | | }) |
| | | } else { |
| | | uni.removeTabBarBadge({ |
| | | index: 3 |
| | | }) |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss"> |
| | | .message-container { |
| | | padding: 20rpx; |
| | | background-color: #f5f5f5; |
| | | height: 100vh; |
| | | display: flex; |
| | | flex-direction: column; |
| | | // 隐藏滚动条但保持滚动功能 |
| | | ::-webkit-scrollbar { |
| | | display: none; |
| | | width: 0 !important; |
| | | height: 0 !important; |
| | | background: transparent; |
| | | } |
| | | |
| | | // Firefox滚动条隐藏 |
| | | * { |
| | | scrollbar-width: none; /* Firefox */ |
| | | } |
| | | |
| | | // IE/Edge滚动条隐藏 |
| | | * { |
| | | -ms-overflow-style: none; /* IE 10+ */ |
| | | } |
| | | } |
| | | |
| | | .message-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | padding: 20rpx 0; |
| | | flex-shrink: 0; // 防止收缩 |
| | | |
| | | .header-title { |
| | | font-size: 36rpx; |
| | | font-weight: bold; |
| | | } |
| | | } |
| | | |
| | | .message-list-scroll { |
| | | flex: 1; |
| | | // 隐藏滚动条但保持滚动功能 |
| | | ::-webkit-scrollbar { |
| | | display: none; |
| | | width: 0 !important; |
| | | height: 0 !important; |
| | | background: transparent; |
| | | } |
| | | |
| | | // Firefox滚动条隐藏 |
| | | * { |
| | | scrollbar-width: none; /* Firefox */ |
| | | } |
| | | |
| | | // IE/Edge滚动条隐藏 |
| | | * { |
| | | -ms-overflow-style: none; /* IE 10+ */ |
| | | } |
| | | } |
| | | |
| | | .message-list { |
| | | .message-item { |
| | | background-color: white; |
| | | border-radius: 15rpx; |
| | | margin-bottom: 20rpx; |
| | | padding: 30rpx; |
| | | box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05); |
| | | |
| | | .message-main { |
| | | .message-title { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 20rpx; |
| | | |
| | | .title-text { |
| | | font-size: 32rpx; |
| | | font-weight: bold; |
| | | color: #333; |
| | | } |
| | | |
| | | .unread-dot { |
| | | width: 16rpx; |
| | | height: 16rpx; |
| | | border-radius: 50%; |
| | | background-color: #ff4d4f; |
| | | } |
| | | } |
| | | |
| | | .message-content { |
| | | font-size: 28rpx; |
| | | color: #666; |
| | | margin-bottom: 20rpx; |
| | | line-height: 1.5; |
| | | } |
| | | |
| | | .message-time { |
| | | font-size: 24rpx; |
| | | color: #999; |
| | | text-align: right; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .no-data { |
| | | text-align: center; |
| | | padding: 100rpx 0; |
| | | color: #999; |
| | | |
| | | text { |
| | | display: block; |
| | | margin-top: 20rpx; |
| | | } |
| | | } |
| | | } |
| | | </style> |