This commit is contained in:
lcw
2025-11-27 14:27:59 +08:00
parent 93c49dff27
commit 85f1f3a6f7
75 changed files with 1321 additions and 360 deletions

180
src/utils/audioPlayer.js Normal file
View File

@ -0,0 +1,180 @@
// 音频播放器工具类
/**
* 音频播放器类
*/
class AudioPlayerClass {
constructor() {
this.audioPlayer = null;
this.isLoaded = false;
this.isPlaying = false;
}
/**
* 初始化音频播放器
* @param {string} audioPath - 音频文件路径
* @param {boolean} loop - 是否循环播放
* @returns {Promise} - 初始化结果
*/
init(audioPath, loop = true) {
return new Promise((resolve, reject) => {
try {
// 创建Audio对象并加载音频文件
this.audioPlayer = new Audio(audioPath);
this.audioPlayer.loop = loop; // 设置循环播放
// 监听音频加载完成事件
this.audioPlayer.addEventListener('canplaythrough', () => {
console.log('音频加载完成,可以播放');
this.isLoaded = true;
resolve(true);
});
// 监听错误事件
this.audioPlayer.addEventListener('error', (error) => {
console.error('音频加载错误:', error);
console.error('错误代码:', error.code);
console.error('音频网络状态:', this.audioPlayer.networkState);
console.error('音频就绪状态:', this.audioPlayer.readyState);
reject(error);
});
// 预加载音频
console.log('开始预加载音频...');
this.audioPlayer.load();
console.log('音频预加载请求已发送');
} catch (error) {
console.error('初始化音频播放器失败:', error);
console.error('错误详情:', error.stack);
reject(error);
}
});
}
/**
* 播放音频
* @param {boolean} autoUnmute - 是否自动取消静音
* @returns {Promise} - 播放结果
*/
play(autoUnmute = true) {
return new Promise((resolve, reject) => {
if (!this.audioPlayer) {
reject(new Error('音频播放器未初始化'));
return;
}
if (!this.isLoaded) {
reject(new Error('音频未加载完成'));
return;
}
try {
// 严格模式下的播放策略:先设置静音,再取消静音,最后播放
if (autoUnmute) {
this.audioPlayer.muted = true;
// 使用setTimeout确保时序正确
setTimeout(() => {
this.audioPlayer.muted = false;
this.audioPlayer.play()
.then(() => {
this.isPlaying = true;
console.log('音频播放成功');
resolve(true);
})
.catch(error => {
if (error.name === 'NotAllowedError') {
console.error('播放被浏览器自动播放策略阻止,需要用户交互后才能播放');
}
reject(error);
});
}, 0);
} else {
this.audioPlayer.play()
.then(() => {
this.isPlaying = true;
console.log('音频播放成功');
resolve(true);
})
.catch(error => {
if (error.name === 'NotAllowedError') {
console.error('播放被浏览器自动播放策略阻止,需要用户交互后才能播放');
}
reject(error);
});
}
} catch (error) {
console.error('音频播放失败:', error);
reject(error);
}
});
}
/**
* 暂停音频
*/
pause() {
if (this.audioPlayer) {
this.audioPlayer.pause();
this.isPlaying = false;
console.log('音频已暂停');
}
}
/**
* 设置音量
* @param {number} volume - 音量值0-1
*/
setVolume(volume) {
if (this.audioPlayer) {
this.audioPlayer.volume = Math.max(0, Math.min(1, volume));
}
}
/**
* 设置是否静音
* @param {boolean} muted - 是否静音
*/
setMuted(muted) {
if (this.audioPlayer) {
this.audioPlayer.muted = muted;
}
}
/**
* 获取音频播放状态
* @returns {boolean} - 是否正在播放
*/
getIsPlaying() {
return this.isPlaying;
}
/**
* 获取音频加载状态
* @returns {boolean} - 是否已加载完成
*/
getIsLoaded() {
return this.isLoaded;
}
/**
* 销毁音频播放器
*/
destroy() {
if (this.audioPlayer) {
this.audioPlayer.pause();
this.audioPlayer.remove();
this.audioPlayer = null;
this.isLoaded = false;
this.isPlaying = false;
console.log('音频播放器已销毁');
}
}
}
// 导出单例实例
const audioPlayerInstance = new AudioPlayerClass();
export default audioPlayerInstance;
// 导出类(可选,用于创建多个实例)
export { AudioPlayerClass };

View File

@ -1,41 +1,131 @@
const url = "ws://80.155.0.82:8006/mosty-api/mosty-websocket/socket/"; //线上
const url = "ws://89.40.9.89:2109/mosty-api/mosty-websocket/socket/"; //线上
import {
getItem
} from "@/utils/storage";
import {
getUserInfoToId
} from "@/api/user-manage";
import emitter from "@/utils/eventBus.js"; // 导入事件总线
class WebSoketClass {
constructor(props) {}
ws = null;
static getInstance() {
if (!this.ws) this.ws = new WebSoketClass();
return this.ws;
constructor(props) {
this.ws = null;
this.state = null;
this.reconnectCount = 0;
this.maxReconnectCount = 10;
this.reconnectInterval = 6000;
this.uuid = null; // 保存UUID用于重连时复用
this.sfzh = null; // 保存身份证号,用于重连时复用
this.fullUrl = null; // 保存完整连接URL用于重连时复用
}
static getInstance() {
if (!this.instance) this.instance = new WebSoketClass();
return this.instance;
}
//关闭连接
static close() {
this.ws.ws.close();
if (this.instance) {
this.instance.closeConnection();
}
}
// 关闭连接的实例方法
closeConnection() {
if (this.ws) {
this.ws.close();
this.ws = null;
}
if (this.state) {
clearInterval(this.state);
this.state = null;
}
this.reconnectCount = 0;
// 重置UUID下次连接时生成新的
this.uuid = null;
this.fullUrl = null;
}
// 创建连接
connect(fun) {
let uuid = this.getUUid()
let id = getItem("USERID");
getUserInfoToId(id).then((res) => {
let sfzh = res.idEntityCard
this.ws = new WebSocket(url + sfzh + '/' + uuid);
this.ws.onopen = (e) => { fun(true);};
});
// 首次连接时获取并保存连接参数
if (!this.sfzh) {
this.sfzh = getItem("idEntityCard");
}
// 首次连接时生成并保存UUID
if (!this.uuid) {
this.uuid = this.getUUid();
}
if (this.sfzh) {
try {
// 如果还没有完整URL或需要更新重新构建
if (!this.fullUrl || this.maxReconnectCount == 10) {
this.fullUrl = url + this.sfzh + '/' + this.uuid;
this.reconnectCount = 0;
}
console.log('尝试连接WebSocket:', this.fullUrl);
this.ws = new WebSocket(this.fullUrl);
console.log(this.ws);
this.ws.onopen = (e) => {
console.log('WebSocket连接已打开');
// 只有在非重连状态下才重置重连计数
// 避免短暂连接成功后又关闭导致计数重置
if (this.reconnectCount === 0) {
console.log('首次连接成功');
} else {
console.log('重连成功');
// 重连成功后重置计数
// this.reconnectCount = 0;
}
this.heartCheck();
this.getMessage();
if (fun) fun(true);
};
this.ws.onclose = (e) => {
console.log(e);
console.log('WebSocket连接已关闭关闭码:', e.code, '原因:', e.reason);
// 如果是正常关闭(1000)或手动关闭(1001),不进行重连
if (e.code !== 1000 && e.code !== 1001) {
this.handleReconnect(fun);
} else {
console.log('WebSocket正常关闭不进行重连');
}
};
this.ws.onerror = (e) => {
console.error('WebSocket连接错误:', e);
this.handleReconnect(fun);
};
} catch (error) {
console.error('创建WebSocket连接失败:', error);
this.handleReconnect(fun);
}
} else {
console.error('获取用户身份证号失败无法建立WebSocket连接');
if (fun) fun(false);
}
}
// 心跳机制
heartCheck() {
const _that = this;
if (this.state) {
clearInterval(this.state);
}
this.state = setInterval(() => {
if (this.ws.readyState === 1) {
this.ws.send("/heart");
} else {
this.closeHandle(); //重新连接
try {
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
this.ws.send("/heart");
} else {
console.log('WebSocket未连接停止心跳');
clearInterval(this.state);
this.state = null;
}
} catch (error) {
console.error('心跳发送失败:', error);
clearInterval(this.state);
this.state = null;
}
}, 6e3);
}, 6000);
}
// 获取uuid
@ -52,21 +142,54 @@ class WebSoketClass {
return uuid
}
closeHandle() {
if (this.state) {
clearInterval(this.state);
this.connect();
} else {
// 处理重连
handleReconnect(fun) {
if (this.reconnectCount >= this.maxReconnectCount) {
console.log('达到最大重连次数,停止重连');
if (fun) fun(false);
return;
}
this.reconnectCount++;
console.log(`尝试第${this.reconnectCount}次重连...`);
setTimeout(() => {
this.connect(fun);
}, this.reconnectInterval);
}
// 接收发送消息
getMessage() {
this.ws.onmessage = (e) => {
if (e.data) {
let newsDate = JSON.parse(e.data);
this.newVal = newsDate;
//接收的数据
console.log(e);
try {
if (e.data) {
let newsDate = JSON.parse(e.data);
// 根据消息类型发射相应的事件
if (newsDate.type === '01') {
// 触发音频播放
console.log('触发音频播放');
emitter.emit('openYp', newsDate.data); // 传递消息数据
}
// else if (newsDate.type === 'ALARM_STOP' || newsDate.type === 'warning_stop') {
// // 触发音频停止
// emitter.emit('closeYp');
// } else if (newsDate.type === 'POSITION_UPDATE') {
// // 位置更新事件
// emitter.emit('positionUpdate', newsDate.data);
// } else if (newsDate.type === 'STATUS_UPDATE') {
// // 状态更新事件
// emitter.emit('statusUpdate', newsDate.data);
// }
// // 通用消息事件
// emitter.emit('webSocketMessage', newsDate);
}
} catch (error) {
console.error('处理WebSocket消息失败:', error);
// 如果是心跳响应,不报错
if (e.data !== '/heart') {
console.error('消息内容:', e.data);
}
}
};
}