lcw
This commit is contained in:
180
src/utils/audioPlayer.js
Normal file
180
src/utils/audioPlayer.js
Normal 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 };
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user