Files

237 lines
5.9 KiB
Vue
Raw Permalink Normal View History

2026-01-07 14:21:29 +08:00
<template>
<view v-if="visible" class="notification-wrapper" :class="{ 'slide-in': visible }" :style="{ paddingTop: notificationTop + 'px' }">
<view class="notification" @click="handleClick">
<!-- 头像 -->
2026-05-15 16:42:32 +08:00
<image class="avatar" :src="avatar || 'https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk-client-wx/static/xx/ysxx.png'" mode="aspectFill" />
2026-01-07 14:21:29 +08:00
<!-- 内容区域 -->
<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>