fix: update dependences
This commit is contained in:
2816
package-lock.json
generated
2816
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -10,9 +10,9 @@
|
|||||||
"proxy": "node proxy.js"
|
"proxy": "node proxy.js"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^1.12.0",
|
"axios": "^1.13.6",
|
||||||
"crypto-js": "^4.2.0",
|
"crypto-js": "^4.2.0",
|
||||||
"dplayer": "^1.27.0",
|
"dplayer": "^1.27.1",
|
||||||
"element-plus": "^2.9.4",
|
"element-plus": "^2.9.4",
|
||||||
"express": "^4.21.2",
|
"express": "^4.21.2",
|
||||||
"hls.js": "^1.5.20",
|
"hls.js": "^1.5.20",
|
||||||
|
|||||||
@@ -1,186 +0,0 @@
|
|||||||
import { defineStore } from "pinia";
|
|
||||||
import {
|
|
||||||
saveMessages,
|
|
||||||
loadMessages,
|
|
||||||
deleteMessages,
|
|
||||||
} from "@/functions/historyMessages";
|
|
||||||
import {
|
|
||||||
saveGroupMessages,
|
|
||||||
loadGroupMessages,
|
|
||||||
deleteGroupMessages,
|
|
||||||
} from "@/functions/groupHistoryMessage";
|
|
||||||
import { toRaw } from "vue";
|
|
||||||
|
|
||||||
export const messageStore = defineStore("messageStore", {
|
|
||||||
// 定义一个响应式数组来存储聊天消息
|
|
||||||
state: () => ({
|
|
||||||
historymessages: [],
|
|
||||||
messages: [],
|
|
||||||
sender: "", //选择的聊天用户id
|
|
||||||
target: "", //用户自己的id
|
|
||||||
corresponding: [],
|
|
||||||
}),
|
|
||||||
|
|
||||||
// 定义操作消息的函数
|
|
||||||
actions: {
|
|
||||||
// 添加消息到数组
|
|
||||||
addMessage(message) {
|
|
||||||
this.messages.push(message);
|
|
||||||
},
|
|
||||||
|
|
||||||
// 清空所有消息
|
|
||||||
clearMessages() {
|
|
||||||
this.messages = [];
|
|
||||||
},
|
|
||||||
|
|
||||||
setCorresponding() {
|
|
||||||
// 过滤出当前聊天中的消息
|
|
||||||
this.corresponding = this.messages.filter(
|
|
||||||
(msg) =>
|
|
||||||
(msg.sender === this.sender && msg.target === this.target) ||
|
|
||||||
(msg.sender === this.target && msg.target === this.sender)
|
|
||||||
);
|
|
||||||
const historymessages = this.historymessages.filter(
|
|
||||||
(msg) =>
|
|
||||||
(msg.sender === this.sender && msg.target === this.target) ||
|
|
||||||
(msg.sender === this.target && msg.target === this.sender)
|
|
||||||
);
|
|
||||||
this.corresponding = [...historymessages, ...this.corresponding];
|
|
||||||
},
|
|
||||||
// 清楚当前登录的聊天数据,保存到本地
|
|
||||||
async saveMessagesHistory(id) {
|
|
||||||
const messages = toRaw(this.messages);
|
|
||||||
await saveMessages(id, messages);
|
|
||||||
},
|
|
||||||
// 加载本地聊天数据
|
|
||||||
async loadMessagesHistory(u_id) {
|
|
||||||
try {
|
|
||||||
this.historymessages = await loadMessages(u_id);
|
|
||||||
|
|
||||||
// 确保历史消息是数组类型
|
|
||||||
if (!Array.isArray(this.historymessages)) {
|
|
||||||
console.error("历史消息数据无效:", this.historymessages);
|
|
||||||
this.historymessages = []; // 如果数据无效,设置为空数组
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.log("加载历史消息时出错" + error);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
async deleteMessagesHistory(u_id, f_id) {
|
|
||||||
this.historymessages = this.historymessages.filter(
|
|
||||||
(msg) =>
|
|
||||||
!(
|
|
||||||
(msg.sender === f_id && msg.target === u_id) ||
|
|
||||||
(msg.sender === u_id && msg.target === f_id)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
this.messages = this.messages.filter(
|
|
||||||
(msg) =>
|
|
||||||
!(
|
|
||||||
(msg.sender === f_id && msg.target === u_id) ||
|
|
||||||
(msg.sender === u_id && msg.target === f_id)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
if (f_id === this.sender) {
|
|
||||||
console.log("清除对应聊天数据展示栈");
|
|
||||||
this.corresponding = [];
|
|
||||||
}
|
|
||||||
const messages = JSON.parse(JSON.stringify(toRaw(this.historymessages)));
|
|
||||||
try {
|
|
||||||
await deleteMessages(u_id, messages);
|
|
||||||
} catch (error) {
|
|
||||||
console.log("删除历史消息时出错" + error);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
// 定义计算属性(可选)
|
|
||||||
getters: {
|
|
||||||
// 获取消息数量
|
|
||||||
messageCount: (state) => state.messages.length,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const messageSignStore = defineStore("messageSignStore", {
|
|
||||||
state: () => ({
|
|
||||||
sign: [],
|
|
||||||
}),
|
|
||||||
actions: {
|
|
||||||
addSign(sign) {
|
|
||||||
// 检查是否已经存在相同的值
|
|
||||||
const exists = this.sign.some(
|
|
||||||
(item) =>
|
|
||||||
item.sender === sign.sender && item.sender_name === sign.sender_name
|
|
||||||
);
|
|
||||||
if (!exists) {
|
|
||||||
this.sign.push(sign);
|
|
||||||
} else {
|
|
||||||
console.warn(`Sign "${sign}" already exists and will not be added.`);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
clearSign() {
|
|
||||||
this.sign = [];
|
|
||||||
},
|
|
||||||
removeSign(sign) {
|
|
||||||
// 找到相同值的索引
|
|
||||||
const index = this.sign.indexOf(sign);
|
|
||||||
if (index !== -1) {
|
|
||||||
// 如果存在,删除该值
|
|
||||||
this.sign.splice(index, 1);
|
|
||||||
} else {
|
|
||||||
console.warn(`Sign "${sign}" not found.`);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const groupMessageStore = defineStore("groupMessageStore", {
|
|
||||||
state: () => ({
|
|
||||||
g_id: "",
|
|
||||||
historymessages: [],
|
|
||||||
messages: [],
|
|
||||||
corresponding: [],
|
|
||||||
}),
|
|
||||||
actions: {
|
|
||||||
addMessage(message) {
|
|
||||||
this.messages.push(message);
|
|
||||||
},
|
|
||||||
clearMessages() {
|
|
||||||
this.messages = [];
|
|
||||||
},
|
|
||||||
async initMessages() {
|
|
||||||
this.historymessages = [...this.historymessages, ...this.messages];
|
|
||||||
this.messages = [];
|
|
||||||
},
|
|
||||||
async getHistoryMessages(u_id, g_id) {
|
|
||||||
this.g_id = g_id;
|
|
||||||
const key = `${u_id}-${g_id}`;
|
|
||||||
try {
|
|
||||||
this.historymessages = await loadGroupMessages(key);
|
|
||||||
console.log("缓存到历史消息:");
|
|
||||||
console.log(this.historymessages);
|
|
||||||
// 确保历史消息是数组类型
|
|
||||||
if (!Array.isArray(this.historymessages)) {
|
|
||||||
console.error("历史消息数据无效:", this.historymessages);
|
|
||||||
this.historymessages = []; // 如果数据无效,设置为空数组
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.log("加载历史消息时出错" + error);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
async saveMessagesHistory(u_id, g_id) {
|
|
||||||
const key = `${u_id}-${g_id}`;
|
|
||||||
console.log(key);
|
|
||||||
const messages = toRaw(this.messages);
|
|
||||||
this.messages = [];
|
|
||||||
this.historymessages = [];
|
|
||||||
await saveGroupMessages(key, messages);
|
|
||||||
},
|
|
||||||
async deleteMessagesHistory(u_id, g_id) {
|
|
||||||
const key = `${u_id}-${g_id}`;
|
|
||||||
this.historymessages = [];
|
|
||||||
this.messages = [];
|
|
||||||
await deleteGroupMessages(key, []);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
|
import { connectWebSocket, disconnectWebSocket, sendMessage, setIsManualClose } from '@/websocket/roomSocket'
|
||||||
|
|
||||||
interface PlayroomState {
|
interface PlayroomState {
|
||||||
id: number
|
id: number
|
||||||
@@ -20,6 +21,14 @@ export const PlayroomStore = defineStore("PlayroomStore",
|
|||||||
currentPlayroom.value = playroom;
|
currentPlayroom.value = playroom;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getCurrentPlayroom = () =>{
|
||||||
|
return currentPlayroom.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
const getCurrentId = () =>{
|
||||||
|
return currentPlayroom.value?.r_id;
|
||||||
|
}
|
||||||
|
|
||||||
const setCurrentUrl = (url: string) => {
|
const setCurrentUrl = (url: string) => {
|
||||||
currentUrl.value = url;
|
currentUrl.value = url;
|
||||||
}
|
}
|
||||||
@@ -30,9 +39,35 @@ export const PlayroomStore = defineStore("PlayroomStore",
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
currentPlayroom,
|
getCurrentPlayroom,
|
||||||
|
getCurrentId,
|
||||||
setCurrentPlayroom,
|
setCurrentPlayroom,
|
||||||
setCurrentUrl,
|
setCurrentUrl,
|
||||||
clearPlayroom,
|
clearPlayroom,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
export const videoSocketStore = defineStore("videoSocketStore",{
|
||||||
|
state: () => ({
|
||||||
|
isConnected: false,
|
||||||
|
hasGotMessage: false,
|
||||||
|
id: 0
|
||||||
|
}),
|
||||||
|
|
||||||
|
actions: {
|
||||||
|
connect(id: number) {
|
||||||
|
this.id = id;
|
||||||
|
if (this.isConnected === true) return
|
||||||
|
connectWebSocket();
|
||||||
|
this.isConnected = true;
|
||||||
|
},
|
||||||
|
disconnect() {
|
||||||
|
setIsManualClose(true);
|
||||||
|
disconnectWebSocket();
|
||||||
|
this.isConnected = false;
|
||||||
|
},
|
||||||
|
send(message: string) {
|
||||||
|
sendMessage(JSON.stringify(message));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|||||||
@@ -99,58 +99,38 @@ export const connectWebSocket = () => {
|
|||||||
|
|
||||||
// TODO: 需要使用groupId进行消息标记
|
// TODO: 需要使用groupId进行消息标记
|
||||||
break;
|
break;
|
||||||
|
case "VIDEO_SYNC":
|
||||||
|
console.log("视频同步消息", MessageData);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// 语音通话相关:
|
||||||
|
case "VOICE_CALL_REQUEST":
|
||||||
|
ElMessage.info("您有一个新的语音通话请求");
|
||||||
|
break;
|
||||||
|
case "VOICE_CALL_RESPONSE":
|
||||||
|
console.log("收到语音通话响应消息");
|
||||||
|
break;
|
||||||
|
case "VOICE_CALL_DENY":
|
||||||
|
ElMessage.info("对方拒绝了您的语音通话请求");
|
||||||
|
break;
|
||||||
|
case "VOICE_CALL_END":
|
||||||
|
ElMessage.info("语音通话已结束");
|
||||||
|
break;
|
||||||
|
case "VOICE_ICE_CANDIDATE":
|
||||||
|
console.log("收到新的ICE候选", MessageData.candidate);
|
||||||
|
break;
|
||||||
|
case "VOICE_SDP_OFFER":
|
||||||
|
console.log("收到SDP Offer", MessageData.sdp);
|
||||||
|
break;
|
||||||
|
case "VOICE_SDP_ANSWER":
|
||||||
|
console.log("收到SDP Answer", MessageData.sdp);
|
||||||
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
}catch(error){
|
}catch(error){
|
||||||
console.error("解析 JSON 失败:", error);
|
console.error("解析 JSON 失败:", error);
|
||||||
}
|
}
|
||||||
// try {
|
|
||||||
// const MessageData = JSON.parse(event.data);
|
|
||||||
// //是否为上下线消息(三类消息)
|
|
||||||
// if (!MessageData.system) {
|
|
||||||
// //是否为新消息
|
|
||||||
// if (MessageData.message) {
|
|
||||||
// messagePoint.hasNewMessage = true;
|
|
||||||
// if (MessageData.group) {
|
|
||||||
// //四类消息,群聊消息
|
|
||||||
// console.log("有新群消息");
|
|
||||||
// groupMessage.addMessage(MessageData);
|
|
||||||
// console.log(groupMessage.messages);
|
|
||||||
// messageSign.addSign({
|
|
||||||
// sender_name: MessageData.sender_name,
|
|
||||||
// g_id: MessageData.g_id,
|
|
||||||
// g_name: MessageData.g_name,
|
|
||||||
// });
|
|
||||||
// } else {
|
|
||||||
// //一类消息,私聊消息
|
|
||||||
// console.log("有新消息");
|
|
||||||
// message.addMessage(MessageData);
|
|
||||||
// console.log(message.messages);
|
|
||||||
// messageSign.addSign({
|
|
||||||
// sender: MessageData.sender,
|
|
||||||
// sender_name: MessageData.sender_name,
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// if (MessageData.engaged) {
|
|
||||||
// // 五类消息,账号重复登录逻辑
|
|
||||||
// setIsManualClose(true);
|
|
||||||
// disconnectWebSocket();
|
|
||||||
// ElMessage("账号重复登录,请注意密码泄露");
|
|
||||||
// console.log("账号重复登陆");
|
|
||||||
// window.location.replace("/");
|
|
||||||
// } else {
|
|
||||||
// //三类消息,指示用户上下线
|
|
||||||
// if (MessageData.status === "online")
|
|
||||||
// ElMessage("用户:" + MessageData.u_name + "上线");
|
|
||||||
// else {
|
|
||||||
// ElMessage("用户:" + MessageData.u_name + "下线");
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// } catch (error) {
|
|
||||||
// console.error("解析 JSON 失败:", error);
|
|
||||||
// }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
socket.value.onerror = (error) => {
|
socket.value.onerror = (error) => {
|
||||||
|
|||||||
@@ -0,0 +1,149 @@
|
|||||||
|
import { ref } from "vue";
|
||||||
|
import { userInfoStore } from "@/store/user";
|
||||||
|
import { ElMessage } from "element-plus";
|
||||||
|
import { PlayroomStore } from "@/store/playroom";
|
||||||
|
|
||||||
|
// userinfo 实例
|
||||||
|
const userinfo = userInfoStore();
|
||||||
|
|
||||||
|
// 延迟获取 playroom 实例,避免循环依赖
|
||||||
|
const getPlayroom = () => {
|
||||||
|
return PlayroomStore();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// WebSocket 实例
|
||||||
|
const socket = ref(null);
|
||||||
|
|
||||||
|
const isManualClose = ref(false);
|
||||||
|
|
||||||
|
const reconnectScheduled = ref(false);
|
||||||
|
|
||||||
|
const retryCount = ref(0);
|
||||||
|
|
||||||
|
export const getRetryCount = () => {
|
||||||
|
return retryCount.value;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const addRetryCount = () => {
|
||||||
|
retryCount.value = retryCount.value + 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const resetRetryCount = () => {
|
||||||
|
retryCount.value = 0;
|
||||||
|
};
|
||||||
|
export const setReconnectScheduled = (value) => {
|
||||||
|
reconnectScheduled.value = value;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getReconnectScheduled = () => {
|
||||||
|
return reconnectScheduled.value;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const setIsManualClose = (value) => {
|
||||||
|
isManualClose.value = value;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getIsManualClose = () => {
|
||||||
|
return isManualClose.value;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 连接WebSocket
|
||||||
|
export const connectWebSocket = () => {
|
||||||
|
const playroom = getPlayroom();
|
||||||
|
const protocol = window.location.protocol === "https:" ? "wss://" : "ws://";
|
||||||
|
const host = window.location.host;
|
||||||
|
const socketUrl = `${protocol}${host}/ws/video?r_id=${playroom.getCurrentId()}`;
|
||||||
|
|
||||||
|
// const socketUrl = `ws://localhost:8080/online?u_id=${userinfo.user.u_id}&u_name=${userinfo.user.u_name}`;
|
||||||
|
if (socket.value && socket.value.readyState !== WebSocket.CLOSED) {
|
||||||
|
console.log("还在重连中...");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const retrytime = getRetryCount();
|
||||||
|
if (retrytime >= 10) {
|
||||||
|
console.log("重连失败,请稍后再试");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log(retrytime);
|
||||||
|
socket.value = new WebSocket(socketUrl, "token-"+ userinfo.token);
|
||||||
|
|
||||||
|
socket.value.onopen = (event) => {
|
||||||
|
console.log("WebSocket for video 连接已建立", event);
|
||||||
|
setReconnectScheduled(false);
|
||||||
|
setIsManualClose(false);
|
||||||
|
resetRetryCount();
|
||||||
|
};
|
||||||
|
|
||||||
|
//处理消息逻辑
|
||||||
|
socket.value.onmessage = (event) => {
|
||||||
|
console.log("从服务器收到消息:", event.data);
|
||||||
|
try{
|
||||||
|
const MessageData = JSON.parse(event.data);
|
||||||
|
const cmd = MessageData.cmd;
|
||||||
|
switch(cmd){
|
||||||
|
case "VIDEO_SYNC":
|
||||||
|
console.log("视频同步消息", MessageData);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}catch(error){
|
||||||
|
console.error("解析 JSON 失败:", error);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
socket.value.onerror = (error) => {
|
||||||
|
console.error("WebSocket for video 发生错误:", error);
|
||||||
|
// console.log(error);
|
||||||
|
setReconnectScheduled(true);
|
||||||
|
socket.value.close();
|
||||||
|
};
|
||||||
|
|
||||||
|
socket.value.onclose = (event) => {
|
||||||
|
if (!getIsManualClose()) {
|
||||||
|
if (getReconnectScheduled()) {
|
||||||
|
socket.value = null;
|
||||||
|
addRetryCount();
|
||||||
|
setTimeout(reConnectWebSocket, 5000);
|
||||||
|
setReconnectScheduled(false);
|
||||||
|
} else {
|
||||||
|
// console.log("websocket因为浏览器省电设置断开");
|
||||||
|
console.log("WebSocket for video 连接已关闭", event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// 断开WebSocket连接
|
||||||
|
export const disconnectWebSocket = () => {
|
||||||
|
if (socket.value && socket.value.readyState === WebSocket.OPEN) {
|
||||||
|
socket.value.close();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 重连机制
|
||||||
|
export const reConnectWebSocket = () => {
|
||||||
|
connectWebSocket();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 发送消息
|
||||||
|
export const sendMessage = (message) => {
|
||||||
|
if (socket.value && socket.value.readyState === WebSocket.OPEN) {
|
||||||
|
socket.value.send(message);
|
||||||
|
} else {
|
||||||
|
console.warn("WebSocket for video 未连接,无法发送消息");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//没有错误的重连,只是浏览器在后台断开了连接
|
||||||
|
document.addEventListener("visibilitychange", () => {
|
||||||
|
if (document.hidden) {
|
||||||
|
} else {
|
||||||
|
if (!getIsManualClose() && socket.value.readyState === WebSocket.CLOSED) {
|
||||||
|
if (getReconnectScheduled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
reConnectWebSocket();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|||||||
@@ -32,6 +32,8 @@ export default defineConfig({
|
|||||||
// ws: true,
|
// ws: true,
|
||||||
// }
|
// }
|
||||||
},
|
},
|
||||||
|
host: '0.0.0.0',
|
||||||
|
port: 5173,
|
||||||
},
|
},
|
||||||
// server: {
|
// server: {
|
||||||
// https:{
|
// https:{
|
||||||
|
|||||||
Reference in New Issue
Block a user