feat: init commit
This commit is contained in:
189
src/socket/onlineSocket.js
Normal file
189
src/socket/onlineSocket.js
Normal file
@@ -0,0 +1,189 @@
|
||||
import { ref } from "vue";
|
||||
import { userInfoStore } from "@/store/store";
|
||||
import { messagePointStore } from "@/store/store";
|
||||
import {
|
||||
messageStore,
|
||||
messageSignStore,
|
||||
groupMessageStore,
|
||||
} from "@/store/message";
|
||||
import { ElMessage } from "element-plus";
|
||||
|
||||
// userinfo 实例
|
||||
const userinfo = userInfoStore();
|
||||
// message 实例
|
||||
const message = messageStore();
|
||||
// groupMessage 实例
|
||||
const groupMessage = groupMessageStore();
|
||||
// messageSignStoregn 实例
|
||||
const messageSign = messageSignStore();
|
||||
// WebSocket 实例
|
||||
const socket = ref(null);
|
||||
//messagePoint 实例
|
||||
const messagePoint = messagePointStore();
|
||||
|
||||
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 protocol = window.location.protocol === "https:" ? "wss://" : "ws://";
|
||||
const host = window.location.host;
|
||||
const socketUrl = `${protocol}${host}/online?u_id=${userinfo.user.u_id}&u_name=${userinfo.user.u_name}`;
|
||||
|
||||
// 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);
|
||||
|
||||
socket.value.onopen = (event) => {
|
||||
console.log("WebSocket连接已建立", event);
|
||||
setReconnectScheduled(false);
|
||||
setIsManualClose(false);
|
||||
resetRetryCount();
|
||||
};
|
||||
|
||||
//处理消息逻辑
|
||||
socket.value.onmessage = (event) => {
|
||||
console.log("从服务器收到消息:", event.data);
|
||||
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) => {
|
||||
console.error("WebSocket发生错误:", 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连接已关闭", 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未连接,无法发送消息");
|
||||
}
|
||||
};
|
||||
|
||||
//没有错误的重连,只是浏览器在后台断开了连接
|
||||
document.addEventListener("visibilitychange", () => {
|
||||
if (document.hidden) {
|
||||
} else {
|
||||
if (!getIsManualClose() && socket.value.readyState === WebSocket.CLOSED) {
|
||||
if (getReconnectScheduled()) {
|
||||
return;
|
||||
}
|
||||
reConnectWebSocket();
|
||||
}
|
||||
}
|
||||
});
|
||||
0
src/socket/roomSocket.js
Normal file
0
src/socket/roomSocket.js
Normal file
287
src/socket/voiceSocket.js
Normal file
287
src/socket/voiceSocket.js
Normal file
@@ -0,0 +1,287 @@
|
||||
import { ref } from "vue";
|
||||
import { userInfoStore } from "@/store/store";
|
||||
import { onCallStore } from "@/store/VoiceTarget";
|
||||
import { ElMessage } from "element-plus";
|
||||
|
||||
// userinfo 实例
|
||||
const userinfo = userInfoStore();
|
||||
// oncall 实例
|
||||
const oncall = onCallStore();
|
||||
// WebSocket 实例
|
||||
const socket = ref(null);
|
||||
|
||||
const isManualClose = ref(false);
|
||||
const reconnectScheduled = ref(false);
|
||||
const retryCount = ref(0);
|
||||
|
||||
const getRetryCount = () => {
|
||||
return retryCount.value;
|
||||
};
|
||||
const addRetryCount = () => {
|
||||
retryCount.value = retryCount.value + 1;
|
||||
};
|
||||
const resetRetryCount = () => {
|
||||
retryCount.value = 0;
|
||||
};
|
||||
const setReconnectScheduled = (value) => {
|
||||
reconnectScheduled.value = value;
|
||||
};
|
||||
const getReconnectScheduled = () => {
|
||||
return reconnectScheduled.value;
|
||||
};
|
||||
const setIsManualClose = (value) => {
|
||||
isManualClose.value = value;
|
||||
};
|
||||
const getIsManualClose = () => {
|
||||
return isManualClose.value;
|
||||
};
|
||||
|
||||
const iceserver = {
|
||||
iceServers: [
|
||||
{
|
||||
// urls: "stun:stun.l.google.com:19302"
|
||||
urls: "stun:8.134.92.199:3478",
|
||||
},
|
||||
{
|
||||
urls: "turn:8.134.92.199:3478",
|
||||
username: "test",
|
||||
credential: "123456",
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
// 连接WebSocket
|
||||
export const connectVoicesocket = () => {
|
||||
const protocol = window.location.protocol === "https:" ? "wss://" : "ws://";
|
||||
const host = window.location.host;
|
||||
const socketUrl = `${protocol}${host}/voice?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);
|
||||
|
||||
socket.value.onopen = (event) => {
|
||||
console.log("Voice连接已建立", event);
|
||||
setReconnectScheduled(false);
|
||||
setIsManualClose(false);
|
||||
resetRetryCount();
|
||||
};
|
||||
|
||||
// 处理消息逻辑
|
||||
socket.value.onmessage = async (event) => {
|
||||
try {
|
||||
const data = JSON.parse(event.data);
|
||||
if (data.type === "status") {
|
||||
ElMessage.error("对方已离线");
|
||||
oncall.panelOff();
|
||||
oncall.callingOff();
|
||||
} else if (data.type === "incomingcall") {
|
||||
// 通话请求处理
|
||||
oncall.setTarget(data.from, data.from_name, data.from_avatar);
|
||||
oncall.panelOn();
|
||||
oncall.callingOn();
|
||||
oncall.fromOff();
|
||||
oncall.statusOff();
|
||||
} else if (data.type === "pickup") {
|
||||
ElMessage.success("对方已接听,等待连接中...");
|
||||
try {
|
||||
await initRTCconnection();
|
||||
RTCpeerConnection.value.onicecandidate = (event) => {
|
||||
if (event.candidate) {
|
||||
console.log("发送candidate", event.candidate);
|
||||
const message = {
|
||||
type: "single",
|
||||
content: "candidate",
|
||||
from: userinfo.user.u_id,
|
||||
to: oncall.target.u_id,
|
||||
candidate: event.candidate,
|
||||
};
|
||||
sendMessage(JSON.stringify(message));
|
||||
}
|
||||
};
|
||||
|
||||
RTCpeerConnection.value.ontrack = (event) => {
|
||||
console.log("收到对方音频流", event);
|
||||
oncall.setRemoteStream(event.streams[0]);
|
||||
};
|
||||
} catch (e) {
|
||||
console.log("webRTC初始化失败", e);
|
||||
}
|
||||
|
||||
const offer = await RTCpeerConnection.value.createOffer({
|
||||
offerToReceiveAudio: 1,
|
||||
});
|
||||
|
||||
await RTCpeerConnection.value.setLocalDescription(offer);
|
||||
|
||||
// 发送offer
|
||||
const message = {
|
||||
type: "single",
|
||||
content: "offer",
|
||||
from: userinfo.user.u_id,
|
||||
to: oncall.target.u_id,
|
||||
offer: offer,
|
||||
};
|
||||
sendMessage(JSON.stringify(message));
|
||||
} else if (data.type === "hangup") {
|
||||
ElMessage.success("对方已挂断");
|
||||
oncall.panelOff();
|
||||
oncall.callingOff();
|
||||
oncall.fromOff();
|
||||
oncall.statusOff();
|
||||
RTCpeerConnection.value.close();
|
||||
RTCpeerConnection.value = null;
|
||||
oncall.resetStream();
|
||||
} else if (data.content === "offer") {
|
||||
ElMessage.success("收到对方offer");
|
||||
console.log("收到对方offer", data);
|
||||
|
||||
try {
|
||||
await initRTCconnection();
|
||||
|
||||
RTCpeerConnection.value.onicecandidate = (event) => {
|
||||
if (event.candidate) {
|
||||
console.log("发送candidate", event.candidate);
|
||||
const message = {
|
||||
type: "single",
|
||||
content: "candidate",
|
||||
from: userinfo.user.u_id,
|
||||
to: oncall.target.u_id,
|
||||
candidate: event.candidate,
|
||||
};
|
||||
sendMessage(JSON.stringify(message));
|
||||
}
|
||||
};
|
||||
|
||||
RTCpeerConnection.value.ontrack = (event) => {
|
||||
console.log("收到对方音频流", event);
|
||||
oncall.setRemoteStream(event.streams[0]);
|
||||
};
|
||||
} catch (e) {
|
||||
console.log("webRTC初始化失败", e);
|
||||
}
|
||||
|
||||
await RTCpeerConnection.value.setRemoteDescription(data.offer);
|
||||
const answer = await RTCpeerConnection.value.createAnswer();
|
||||
await RTCpeerConnection.value.setLocalDescription(answer);
|
||||
|
||||
// 发送answer
|
||||
const message = {
|
||||
type: "single",
|
||||
content: "answer",
|
||||
from: userinfo.user.u_id,
|
||||
to: oncall.target.u_id,
|
||||
answer: answer,
|
||||
};
|
||||
sendMessage(JSON.stringify(message));
|
||||
} else if (data.content === "answer") {
|
||||
ElMessage.success("对方已接受");
|
||||
console.log("对方已接受", data);
|
||||
await RTCpeerConnection.value.setRemoteDescription(data.answer);
|
||||
} else if (data.content === "candidate") {
|
||||
console.log("收到candidate", data);
|
||||
await RTCpeerConnection.value.addIceCandidate(data.candidate);
|
||||
}
|
||||
} catch (e) {
|
||||
console.log("VoiceSocket消息格式错误", e);
|
||||
}
|
||||
};
|
||||
|
||||
socket.value.onerror = (error) => {
|
||||
console.error("Voicesocket发生错误:", error);
|
||||
setReconnectScheduled(true);
|
||||
socket.value.close();
|
||||
};
|
||||
|
||||
socket.value.onclose = (event) => {
|
||||
if (!getIsManualClose()) {
|
||||
if (getReconnectScheduled()) {
|
||||
socket.value = null;
|
||||
addRetryCount();
|
||||
setTimeout(reConnectVoicesocket, 5000);
|
||||
setReconnectScheduled(false);
|
||||
} else {
|
||||
console.log("Voicesocket因为浏览器省电设置断开");
|
||||
console.log("Voicesocket连接已关闭", event);
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// 断开Voicesocket连接
|
||||
export const disconnectVoicesocket = () => {
|
||||
if (socket.value && socket.value.readyState === WebSocket.OPEN) {
|
||||
socket.value.close();
|
||||
}
|
||||
};
|
||||
|
||||
// 重连机制
|
||||
export const reConnectVoicesocket = () => {
|
||||
connectVoicesocket();
|
||||
};
|
||||
|
||||
// 发送消息
|
||||
export const sendMessage = (message) => {
|
||||
if (socket.value && socket.value.readyState === WebSocket.OPEN) {
|
||||
socket.value.send(message);
|
||||
} else {
|
||||
console.warn("Voicesocket未连接,无法发送消息");
|
||||
}
|
||||
};
|
||||
|
||||
//没有错误的重连,只是浏览器在后台断开了连接
|
||||
document.addEventListener("visibilitychange", () => {
|
||||
if (document.hidden) {
|
||||
} else {
|
||||
if (!getIsManualClose() && socket.value.readyState === WebSocket.CLOSED) {
|
||||
if (getReconnectScheduled()) {
|
||||
return;
|
||||
}
|
||||
reConnectVoicesocket();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
//WebRTC连接相关代码
|
||||
const RTCpeerConnection = ref(null);
|
||||
|
||||
export const getlocalStream = async () => {
|
||||
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
||||
console.log("获取本地音频流成功", stream);
|
||||
return stream;
|
||||
// // 获取音频和视频轨道
|
||||
// const audioTrack = stream.getAudioTracks()[0];
|
||||
// // 将轨道添加到 RTCPeerConnection
|
||||
// peerConnection.addTrack(audioTrack, stream);
|
||||
};
|
||||
|
||||
const initRTCconnection = async () => {
|
||||
RTCpeerConnection.value = new RTCPeerConnection(iceserver);
|
||||
const stream = await getlocalStream();
|
||||
RTCpeerConnection.value.addTrack(stream.getAudioTracks()[0], stream);
|
||||
};
|
||||
|
||||
export const hangup = () => {
|
||||
oncall.panelOff();
|
||||
oncall.callingOff();
|
||||
oncall.fromOff();
|
||||
oncall.statusOff();
|
||||
oncall.resetStream();
|
||||
RTCpeerConnection.value.close();
|
||||
RTCpeerConnection.value = null;
|
||||
|
||||
const message = {
|
||||
type: "hangup",
|
||||
from: userinfo.user.u_id,
|
||||
to: oncall.target.u_id,
|
||||
};
|
||||
sendMessage(JSON.stringify(message));
|
||||
};
|
||||
Reference in New Issue
Block a user