|
@@ -420,7 +420,7 @@
|
|
|
:rows="4"
|
|
|
resize="none"
|
|
|
maxlength="200"
|
|
|
- @keyup.enter.native="sendUserMessageToFriend"
|
|
|
+ @keyup.enter.native="sendUserMessage"
|
|
|
>
|
|
|
</el-input>
|
|
|
</div>
|
|
@@ -619,7 +619,7 @@
|
|
|
</div>
|
|
|
</div>
|
|
|
</el-dialog>
|
|
|
- <el-dialog :visible.sync="groupWindowStatus" :modal="false" :close-on-click-modal="false" width="1028px">
|
|
|
+ <el-dialog :visible.sync="groupWindowStatus" :modal="false" :close-on-click-modal="false" width="1028px" :inert="!groupWindowStatus">
|
|
|
<div class="searchWindow">
|
|
|
<div class="searchWindowLeft">
|
|
|
<div class="searchUserWindowBox">
|
|
@@ -706,7 +706,7 @@
|
|
|
</div>
|
|
|
</el-dialog>
|
|
|
<!--分享群聊 start------------------------------------------------------------>
|
|
|
- <el-dialog :visible.sync="shareGroupWindowStatus" :modal="false" title="分享群聊" :close-on-click-modal="false" width="420px">
|
|
|
+ <el-dialog :visible.sync="shareGroupWindowStatus" :modal="false" title="分享群聊" :close-on-click-modal="false" width="420px" :inert="!shareGroupWindowStatus">
|
|
|
<div>
|
|
|
<div class="shareCardWindowBox">
|
|
|
<el-tabs v-model="shareGroupActive" type="card" @tab-click="handleClickShareGroupCard">
|
|
@@ -762,7 +762,7 @@
|
|
|
</div>
|
|
|
</el-dialog>
|
|
|
<!--聊天记录弹出框 start------------------------------------------------------------>
|
|
|
- <el-dialog :visible.sync="fileWindowStatus" title="聊天记录" :model="false" :close-on-click-modal="false" width="757px">
|
|
|
+ <el-dialog :visible.sync="fileWindowStatus" title="聊天记录" :model="false" :close-on-click-modal="false" width="757px" :inert="!fileWindowStatus">
|
|
|
<div class="fileWindow">
|
|
|
<div class="fileWindowHeader">
|
|
|
<el-input
|
|
@@ -958,7 +958,7 @@
|
|
|
<!--聊天记录弹出框 end------------------------------------------------------------>
|
|
|
<!--编辑群成员弹出框 start------------------------------------------------------------>
|
|
|
<!--编辑时 左侧显示的是好友列表 右侧显示的是群成员-->
|
|
|
- <el-dialog :visible.sync="groupEditWindowStatus" :model="false" :close-on-click-modal="false" width="1028px" @closed="cancelEditGroupMember">
|
|
|
+ <el-dialog :visible.sync="groupEditWindowStatus" :model="false" :close-on-click-modal="false" width="1028px" @closed="cancelEditGroupMember" :inert="!groupEditWindowStatus">
|
|
|
<div class="searchWindow">
|
|
|
<div class="searchWindowLeft">
|
|
|
<div class="searchUserWindowBox">
|
|
@@ -1053,7 +1053,7 @@
|
|
|
</el-dialog>
|
|
|
<!--编辑群成员弹出框 end------------------------------------------------------------>
|
|
|
<!--群名称弹出框 start------------------------------------------------------------>
|
|
|
- <el-dialog :visible.sync="editGroupNameWindow" title="编辑群名称" :model="false" :close-on-click-modal="false" width="420px">
|
|
|
+ <el-dialog :visible.sync="editGroupNameWindow" title="编辑群名称" :model="false" :close-on-click-modal="false" width="420px" :inert="!editGroupNameWindow">
|
|
|
<div>
|
|
|
<div>
|
|
|
<el-input type="textarea" resize="none" v-model="editMessageTitle" placeholder="请输入" maxlength="20"></el-input>
|
|
@@ -1066,7 +1066,7 @@
|
|
|
</el-dialog>
|
|
|
<!--群名称弹出框 end------------------------------------------------------------>
|
|
|
<!--群公告弹出框 start------------------------------------------------------------>
|
|
|
- <el-dialog :visible.sync="editGroupNoticeWindow" title="编辑群公告" :model="false" :close-on-click-modal="false" width="420px">
|
|
|
+ <el-dialog :visible.sync="editGroupNoticeWindow" title="编辑群公告" :model="false" :close-on-click-modal="false" width="420px" :inert="!editGroupNoticeWindow">
|
|
|
<div>
|
|
|
<div>
|
|
|
<el-input type="textarea" resize="none" v-model="editGroupProfile" placeholder="请输入" rows="10" maxlength="500"></el-input>
|
|
@@ -1137,7 +1137,7 @@
|
|
|
<!--分享名片 end------------------------------------------------------------>
|
|
|
|
|
|
<!--发送好友申请弹出框 start------------------------------------------------------------>
|
|
|
- <el-dialog :visible.sync="addFriendWindowStatus" title="朋友申请" :model="false" :close-on-click-modal="false" width="420px">
|
|
|
+ <el-dialog :visible.sync="addFriendWindowStatus" title="朋友申请" :model="false" :close-on-click-modal="false" width="420px" :inert="!addFriendWindowStatus">
|
|
|
<div>
|
|
|
<div>
|
|
|
<el-form :model="form" ref="form" autocomplete="off" label-position="left">
|
|
@@ -1157,7 +1157,7 @@
|
|
|
<!--发送好友申请弹出框 end------------------------------------------------------------>
|
|
|
|
|
|
<!--加入群聊弹出框 start------------------------------------------------------------>
|
|
|
- <el-dialog :visible.sync="addGroupWindow" title="加入群聊" :model="false" :close-on-click-modal="false" width="420px">
|
|
|
+ <el-dialog :visible.sync="addGroupWindow" title="加入群聊" :model="false" :close-on-click-modal="false" width="420px" :inert="!addGroupWindow">
|
|
|
<div class="addGroupWindow">
|
|
|
<div class="addGroupWindowImg">
|
|
|
<img src="@/assets/chat/user/group.jpg" alt="">
|
|
@@ -1202,7 +1202,7 @@
|
|
|
</div>
|
|
|
</el-dialog>
|
|
|
<!--请求验证弹出框 start------------------------------------------------------------>
|
|
|
- <el-dialog :visible.sync="friendWindowStatus" title="通过朋友验证" :model="false" :close-on-click-modal="false" width="420px">
|
|
|
+ <el-dialog :visible.sync="friendWindowStatus" title="通过朋友验证" :model="false" :close-on-click-modal="false" width="420px" :inert="!friendWindowStatus">
|
|
|
<div>
|
|
|
<div class="friendWindowText">
|
|
|
确定要添加<span>{{friendInfo.user_name}}</span>为好友吗?
|
|
@@ -1215,7 +1215,7 @@
|
|
|
</el-dialog>
|
|
|
<!--请求验证弹出框 end------------------------------------------------------------>
|
|
|
<!--修改备注弹出框 start------------------------------------------------------------>
|
|
|
- <el-dialog :visible.sync="editWindowStatus" title="修改备注" :modal="false" :close-on-click-modal="false" width="420px">
|
|
|
+ <el-dialog :visible.sync="editWindowStatus" title="修改备注" :modal="false" :close-on-click-modal="false" width="420px" :inert="!editWindowStatus">
|
|
|
<div>
|
|
|
<div>
|
|
|
<el-form :model="form" ref="form" autocomplete="off" label-position="left">
|
|
@@ -1233,7 +1233,7 @@
|
|
|
</div>
|
|
|
</el-dialog>
|
|
|
<!--修改备注弹出框 end------------------------------------------------------------>
|
|
|
- <el-dialog :visible.sync="searchWindowStatus" title="聊天记录" :close-on-click-modal="false" width="420px" :modal="false">
|
|
|
+ <el-dialog :visible.sync="searchWindowStatus" title="聊天记录" :close-on-click-modal="false" width="420px" :modal="false" :inert="!searchWindowStatus">
|
|
|
<div class="searchFriendBox">
|
|
|
<div class="searchFriendItem">
|
|
|
<div class="searchFriendAvatar">
|
|
@@ -1273,6 +1273,8 @@
|
|
|
name: "ChatPanel",
|
|
|
data() {
|
|
|
return {
|
|
|
+ userInteracted: false,
|
|
|
+ pendingAudio: null,
|
|
|
newMessage: {},
|
|
|
token:'',
|
|
|
ones:0,
|
|
@@ -1447,10 +1449,48 @@
|
|
|
}
|
|
|
},
|
|
|
methods: {
|
|
|
+ checkNotificationEnv() {
|
|
|
+ // 检查 Notification API 支持
|
|
|
+ if (!('Notification' in window)) {
|
|
|
+ this.$notify({
|
|
|
+ title: '浏览器不支持通知',
|
|
|
+ message: '请使用支持 Notification 的现代浏览器',
|
|
|
+ type: 'warning',
|
|
|
+ duration: 8000
|
|
|
+ });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // 检查安全环境
|
|
|
+ const isSecure = location.protocol === 'https:' ||
|
|
|
+ location.hostname === 'localhost' ||
|
|
|
+ location.hostname === '127.0.0.1';
|
|
|
+ if (!isSecure) {
|
|
|
+ this.$notify({
|
|
|
+ title: '通知功能受限',
|
|
|
+ message: '请用 localhost 或 https 访问以启用浏览器通知',
|
|
|
+ type: 'warning',
|
|
|
+ duration: 8000
|
|
|
+ });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // 主动请求权限
|
|
|
+ if (Notification.permission === 'default') {
|
|
|
+ Notification.requestPermission().catch(() => {});
|
|
|
+ }
|
|
|
+ },
|
|
|
+ showMessage(item){
|
|
|
+ console.log("showMessage走没走",item)
|
|
|
+ this.notificationShowMessage(item);
|
|
|
+ this.playVoice();
|
|
|
+ },
|
|
|
clickShowMessage(item) {
|
|
|
// this.newMessage = item;
|
|
|
// 先关闭所有旧消息
|
|
|
this.$message.closeAll();
|
|
|
+ // 检查通知权限
|
|
|
+ // 检查 Notification 支持和安全环境
|
|
|
+ this.notificationMessage(item);
|
|
|
+ this.playVoice();
|
|
|
this.$message({
|
|
|
dangerouslyUseHTMLString: true,
|
|
|
message: `
|
|
@@ -1474,6 +1514,109 @@
|
|
|
}
|
|
|
}, 50);
|
|
|
},
|
|
|
+ playVoice(){
|
|
|
+ //http://img.bjzxtw.org.cn/master/video/mp3/11302.mp3 播放这段音频
|
|
|
+ const audio = new Audio('http://img.bjzxtw.org.cn/master/video/mp3/xxxtx.mp3');
|
|
|
+
|
|
|
+ if (this.userInteracted) {
|
|
|
+ audio.play().catch(e => console.error('Audio play failed:', e));
|
|
|
+ } else {
|
|
|
+ // Store audio to play after first interaction
|
|
|
+ this.pendingAudio = audio;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ notificationShowMessage(item) {
|
|
|
+ const iconList = {
|
|
|
+ 2:'http://img.bjzxtw.org.cn/master/www/icon/zixun.png',
|
|
|
+ 3:'http://img.bjzxtw.org.cn/master/www/icon/sahngpin.png',
|
|
|
+ 4:'http://img.bjzxtw.org.cn/master/www/icon/keti.png',//课题
|
|
|
+ 5:'http://img.bjzxtw.org.cn/master/www/icon/tongzhi.png',//通知
|
|
|
+ 6:'http://img.bjzxtw.org.cn/master/www/icon/tousu.png',//投诉
|
|
|
+ 7:'http://img.bjzxtw.org.cn/master/www/icon/zhaopin.png',
|
|
|
+ 8:'http://img.bjzxtw.org.cn/master/www/icon/zhaopin.png',
|
|
|
+ 9:'http://img.bjzxtw.org.cn/master/www/icon/zhaopin.png',
|
|
|
+ 10:'http://img.bjzxtw.org.cn/master/www/icon/zhaopin.png',
|
|
|
+ 11:'http://img.bjzxtw.org.cn/master/www/icon/zhaopin.png',
|
|
|
+ }
|
|
|
+ if (!('Notification' in window)) {
|
|
|
+ this.$notify({
|
|
|
+ title: '浏览器不支持通知',
|
|
|
+ message: '请使用最新版 Chrome、Edge、Firefox 或 Safari 浏览器',
|
|
|
+ type: 'error',
|
|
|
+ duration: 8000
|
|
|
+ });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // console.log("===============:notificationMessage",window)
|
|
|
+ if (!('Notification' in window)) return;
|
|
|
+ const isSecure = location.protocol === 'https:' ||
|
|
|
+ location.hostname === 'localhost' ||
|
|
|
+ location.hostname === '127.0.0.1';
|
|
|
+ if (!isSecure) return;
|
|
|
+
|
|
|
+ if (Notification.permission === 'granted') {
|
|
|
+ console.log("===============:Notification.permission === 'granted'",item)
|
|
|
+ const notification = new Notification(item.title, {
|
|
|
+ icon: iconList[item.messageType],
|
|
|
+ body: item.content,
|
|
|
+ requireInteraction: true, // 需要用户交互才能关闭
|
|
|
+ renotify: true, // 每次新消息都提醒
|
|
|
+ tag: 'message'
|
|
|
+ });
|
|
|
+ notification.onclick = () => {
|
|
|
+ try { window.focus(); } catch (e) {}
|
|
|
+ this.scorllBottom && this.scorllBottom();
|
|
|
+ notification.close();
|
|
|
+ };
|
|
|
+ } else if (Notification.permission === 'denied') {
|
|
|
+ this.$notify({
|
|
|
+ title: '通知权限已禁用',
|
|
|
+ message: '请在浏览器设置中启用通知权限以接收新消息提醒',
|
|
|
+ type: 'warning',
|
|
|
+ duration: 5000
|
|
|
+ });
|
|
|
+ }
|
|
|
+ },
|
|
|
+ notificationMessage(item) {
|
|
|
+ if (!('Notification' in window)) {
|
|
|
+ this.$notify({
|
|
|
+ title: '浏览器不支持通知',
|
|
|
+ message: '请使用最新版 Chrome、Edge、Firefox 或 Safari 浏览器',
|
|
|
+ type: 'error',
|
|
|
+ duration: 8000
|
|
|
+ });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // console.log("===============:notificationMessage",window)
|
|
|
+ if (!('Notification' in window)) return;
|
|
|
+ const isSecure = location.protocol === 'https:' ||
|
|
|
+ location.hostname === 'localhost' ||
|
|
|
+ location.hostname === '127.0.0.1';
|
|
|
+ if (!isSecure) return;
|
|
|
+
|
|
|
+ if (Notification.permission === 'granted') {
|
|
|
+ console.log("===============:Notification.permission === 'granted'",item)
|
|
|
+ const notification = new Notification(item.user_name, {
|
|
|
+ icon: 'http://img.bjzxtw.org.cn/master/www/icon/group.png',
|
|
|
+ body: item.content,
|
|
|
+ requireInteraction: true, // 需要用户交互才能关闭
|
|
|
+ renotify: true, // 每次新消息都提醒
|
|
|
+ tag: 'message'
|
|
|
+ });
|
|
|
+ notification.onclick = () => {
|
|
|
+ try { window.focus(); } catch (e) {}
|
|
|
+ this.scorllBottom && this.scorllBottom();
|
|
|
+ notification.close();
|
|
|
+ };
|
|
|
+ } else if (Notification.permission === 'denied') {
|
|
|
+ this.$notify({
|
|
|
+ title: '通知权限已禁用',
|
|
|
+ message: '请在浏览器设置中启用通知权限以接收新消息提醒',
|
|
|
+ type: 'warning',
|
|
|
+ duration: 5000
|
|
|
+ });
|
|
|
+ }
|
|
|
+ },
|
|
|
onCustomMessageClick(item) {
|
|
|
|
|
|
// 通知父组件显示ChatPanel,并把 item 作为参数传递
|
|
@@ -2485,7 +2628,7 @@
|
|
|
}else{
|
|
|
console.log("当前消息为群消息,但是用户未开启此聊天窗口!")
|
|
|
}
|
|
|
- }else{
|
|
|
+ }else if(message.talk_type==1){
|
|
|
//当前的单聊消息是自己发的,回显到聊天框中
|
|
|
if(Number(this.receiverId)==Number(message.receiver_id)){
|
|
|
//如果message的receiverId和会话的receiverId一致,说明这条信息是自己发的回显
|
|
@@ -2555,6 +2698,9 @@
|
|
|
|
|
|
|
|
|
}
|
|
|
+ }else{
|
|
|
+ //其它消息提醒全走这里
|
|
|
+ this.showMessage(message);
|
|
|
}
|
|
|
},
|
|
|
// 5.2 发送消息
|
|
@@ -2568,7 +2714,7 @@
|
|
|
};
|
|
|
// console.log("websocket发送消息:",wsService.getReadyState,WebSocket.OPEN)
|
|
|
//发送消息
|
|
|
- console.log("发送消息前的状态:",wsService.getReadyState() ,"==========" ,WebSocket.OPEN)
|
|
|
+ console.log("发送消息前的状态:",wsService.getReadyState() ,"==========" ,WebSocket.OPEN,message)
|
|
|
if (wsService.getReadyState() === WebSocket.OPEN) {
|
|
|
wsService.send(message);
|
|
|
}
|
|
@@ -3115,6 +3261,22 @@
|
|
|
}
|
|
|
},
|
|
|
mounted() {
|
|
|
+ this.checkNotificationEnv();
|
|
|
+ // Add user interaction listeners
|
|
|
+ const handleInteraction = () => {
|
|
|
+ this.userInteracted = true;
|
|
|
+ // Play pending audio if exists
|
|
|
+ if (this.pendingAudio) {
|
|
|
+ this.pendingAudio.play().catch(e => console.error('Audio play failed:', e));
|
|
|
+ this.pendingAudio = null;
|
|
|
+ }
|
|
|
+ // Remove listeners after first interaction
|
|
|
+ document.removeEventListener('click', handleInteraction);
|
|
|
+ document.removeEventListener('keydown', handleInteraction);
|
|
|
+ };
|
|
|
+
|
|
|
+ document.addEventListener('click', handleInteraction);
|
|
|
+ document.addEventListener('keydown', handleInteraction);
|
|
|
// console.log("用户头像信息:",this.$store.state.user.avatar)
|
|
|
// //开启websocket连接 start---------------------------------------->
|
|
|
// //1.获取admin-token
|