Files
xk-client-wx/components/MessageNotification/MessageNotification.vue
2026-05-15 16:42:32 +08:00

237 lines
5.9 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 v-if="visible" class="notification-wrapper" :class="{ 'slide-in': visible }" :style="{ paddingTop: notificationTop + 'px' }">
<view class="notification" @click="handleClick">
<!-- 头像 -->
<image class="avatar" :src="avatar || 'https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk-client-wx/static/xx/ysxx.png'" mode="aspectFill" />
<!-- 内容区域 -->
<view class="content">
<text class="title">{{ title || '新消息' }}</text>
<text class="message">{{ displayMessage }}</text>
</view>
<!-- 关闭按钮 -->
<view class="close" @click.stop="handleClose">
<text class="close-icon">×</text>
</view>
</view>
</view>
</template>
<script>
export default {
name: 'MessageNotification',
data() {
return {
visible: false,
avatar: '',
title: '',
message: '',
roomId: '',
roomData: null,
autoHideTimer: null,
notificationTop: 50 // 默认值
}
},
created() {
// 获取胶囊按钮位置,计算通知的安全位置
this.calculateSafeTop();
},
computed: {
displayMessage() {
// 限制消息长度超过30个字符显示省略号
if (this.message && this.message.length > 30) {
return this.message.substring(0, 30) + '...';
}
return this.message || '您有一条新消息';
}
},
mounted() {
// 监听显示通知事件
uni.$on('show-message-notification', this.showNotification);
// 监听隐藏通知事件
uni.$on('hide-message-notification', this.hideNotification);
},
beforeDestroy() {
// 移除事件监听
uni.$off('show-message-notification', this.showNotification);
uni.$off('hide-message-notification', this.hideNotification);
// 清除定时器
if (this.autoHideTimer) {
clearTimeout(this.autoHideTimer);
}
},
methods: {
/**
* 计算通知的安全顶部位置(避开胶囊按钮)
*/
calculateSafeTop() {
try {
// #ifdef MP-WEIXIN
// 获取胶囊按钮的位置信息
const menuButtonInfo = wx.getMenuButtonBoundingClientRect();
// 通知顶部 = 胶囊底部 + 10px 安全边距
this.notificationTop = menuButtonInfo.bottom + 10;
// #endif
// #ifndef MP-WEIXIN
// 非微信小程序环境,使用状态栏高度 + 安全边距
const systemInfo = uni.getSystemInfoSync();
this.notificationTop = (systemInfo.statusBarHeight || 44) + 10;
// #endif
} catch (e) {
// 获取失败时使用默认值
this.notificationTop = 50;
}
},
/**
* 显示通知
* @param {Object} data 通知数据
* @param {string} data.avatar 头像
* @param {string} data.title 标题(发送者昵称)
* @param {string} data.message 消息内容
* @param {string} data.roomId 房间ID
* @param {Object} data.roomData 房间数据(用于跳转)
*/
showNotification(data) {
// 清除之前的定时器
if (this.autoHideTimer) {
clearTimeout(this.autoHideTimer);
}
// 设置通知数据
this.avatar = data.avatar || '';
this.title = data.title || '新消息';
this.message = data.message || '您有一条新消息';
this.roomId = data.roomId || '';
this.roomData = data.roomData || null;
// 显示通知
this.visible = true;
// 3秒后自动隐藏
this.autoHideTimer = setTimeout(() => {
this.hideNotification();
}, 3000);
},
/**
* 隐藏通知
*/
hideNotification() {
this.visible = false;
if (this.autoHideTimer) {
clearTimeout(this.autoHideTimer);
this.autoHideTimer = null;
}
},
/**
* 点击通知,跳转到聊天页面
*/
handleClick() {
this.hideNotification();
if (this.roomId && this.roomData) {
uni.navigateTo({
url: `/subPackages/chat/chat?room_id=${this.roomId}&nick_name=${this.roomData.nick_name || ''}&user_id=${this.roomData.user_id || ''}&avatar=${encodeURIComponent(this.roomData.avatar || '')}`
});
} else if (this.roomId) {
// 如果只有 roomId也尝试跳转
uni.navigateTo({
url: `/subPackages/chat/chat?room_id=${this.roomId}`
});
}
},
/**
* 关闭通知
*/
handleClose() {
this.hideNotification();
}
}
}
</script>
<style lang="scss" scoped>
.notification-wrapper {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 9999;
padding-left: 20rpx;
padding-right: 20rpx;
padding-bottom: 20rpx;
// padding-top 通过 :style 动态设置,避开胶囊按钮
transform: translateY(-100%);
transition: transform 0.3s ease-out;
&.slide-in {
transform: translateY(0);
}
}
.notification {
display: flex;
align-items: center;
background: #ffffff;
border-radius: 20rpx;
padding: 24rpx;
box-shadow: 0 8rpx 30rpx rgba(0, 0, 0, 0.15);
.avatar {
width: 80rpx;
height: 80rpx;
border-radius: 50%;
flex-shrink: 0;
background-color: #f5f5f5;
}
.content {
flex: 1;
margin-left: 20rpx;
overflow: hidden;
.title {
display: block;
font-size: 30rpx;
font-weight: 600;
color: #333333;
margin-bottom: 8rpx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.message {
display: block;
font-size: 26rpx;
color: #666666;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
.close {
flex-shrink: 0;
width: 48rpx;
height: 48rpx;
display: flex;
align-items: center;
justify-content: center;
margin-left: 16rpx;
.close-icon {
font-size: 40rpx;
color: #999999;
line-height: 1;
}
}
}
</style>