更新页面

This commit is contained in:
2025-12-11 18:12:51 +08:00
parent c38109a171
commit 4036c036a9
403 changed files with 14407 additions and 18 deletions

View File

@ -0,0 +1,351 @@
<template>
<div class="mt20 flex align-center">
<el-input style="width:200px" class="mr10" v-model="keyWoed" placeholder="输入编号"></el-input>
<el-button @click="handleBtn('无人机视频')">无人机视频</el-button>
<el-button @click="handleBtn('音频')">音频</el-button>
</div>
<DraggableResizableVue id="call_div" v-model:x="element.x" v-model:y="element.y" v-model:h="element.height" v-model:w="element.width" v-model:active="element.isActive" class="container">
<div>
<el-row justify="space-around">
<a-tag v-for="item in speakers" :key="item.number" bordered color="green">{{ item.alias || item.number }}</a-tag>
</el-row>
<div id="voice_wave" class="wave"></div>
<audio ref="audioRef" :volume="80 / 100" autoplay controls hidden />
<video id="video" ref="videoRef" autoplay playsinline :hidden="!showVideo" class="video"/>
<video id="localvideo" ref="localvideoRef" autoplay playsinline :hidden="!showlocalVideo" class="video"/>
<video id="pushVideo" ref="pushVideoRef" autoplay playsinline :hidden="!showPushlVideo" class="video" />
<el-row class="buttonContainer" justify="space-around">
<el-button :type="selfGranted ? 'success' : 'pramary'" shape="round" @click="applayFloor">话权</el-button>
<el-button type="danger" shape="round" @click="hangup">挂断</el-button>
</el-row>
</div>
</DraggableResizableVue>
</template>
<script setup>
import useCallModule from '@/sdk/call';
import useRecorder from '@/hooks/recorder';
import DraggableResizableVue from "draggable-resizable-vue3";
import { nextTick, onMounted, onUnmounted, ref } from "vue";
import SiriWave from "siriwave";
import { init } from "echarts";
let waveContainer;
let audioWave = SiriWave || undefined;
const element = ref({
x: 0,
y: 0,
width: 200,
height: 200,
isActive: false
});
let rootView;
let streamCbId;
let hangupCbId;
let grantCbId;
// 本端视频流 local video stream
let localVideoStream;
// 远端视频流 remote video stream
let remoteVideoStream;
const selfGranted = ref(false);
// 54040254001310305009 视频
// 38467417 音频
const keyWoed = ref('38467417') //关键字
// 是否 半双工用一个Video来显示远端流和本地流。 true 为 共用一个video。 false 为 2个video分别显示。
const useOneVideoShow = true;
const useMedia = useRecorder();
const CALL = useCallModule();
const audioRef = ref();
// 远端流和Video。
const videoRef = ref();
const showVideo = ref(false);
const localvideoRef = ref(); // 本端Video
const showlocalVideo = ref(false); // 显示本端流
const pushVideoRef = ref();
// 显示推送流 show push video
const showPushlVideo = ref(false);
const showPanel = ref(false);
const speakers = ref([]);
const codeId = ref(null)
// 处理按钮
const handleBtn = (type) =>{
if(!keyWoed.value) return;
let params = { page_size:10,page_index:1,org_id:"",key_word:keyWoed.value}
lemon.basedata.fetchDeviceList(params).then(resp => {
if(resp.device_list[0].basedata_id){
let basedata_id = resp.device_list[0].basedata_id
debugger
switch(type){
case '无人机视频':
let obj = { basedata_id , video_frame_size: 3, hook_flag: 0 }
window.lemon.call.makeVideoCall(obj)?.then((resp) => {
console.log('无人机视频', resp);
codeId.value = resp.call_id
});
break;
case '音频':
let obj1 = { basedata_id,"hook_flag":0 }
window.lemon.call.makeVoiceCall(obj1)?.then((resp) => {
console.log('音频', resp);
codeId.value = resp.call_id
});
break;
}
}
}).catch(err => {})
}
// register media stream callbackinclude audio and video stream
const registerStream = () => {
streamCbId = window.lemon.call.addMediaStream((call_id, stream, type) => {
console.log(type,'============监听播放类型');
showPanel.value = true;
rootView.style.display = 'unset';
if (type === 'audio_dst') {
setAudio(stream);
} else if (type === 'video_dst') {
if (useOneVideoShow) {
remoteVideoStream = stream;
showVideo.value = true;
videoRef.value.srcObject = stream;
remoteVideoStream = stream;
} else {
showVideo.value = true;
showlocalVideo.value = false;
videoRef.value.srcObject = stream;
}
} else if (type === 'video_src') {
if (useOneVideoShow) {
// 一般全双工显示远端的画面。 拥有话权的时候,才显示自己的画面,所以流赋值到话权模块处理。
showVideo.value = false;
localVideoStream = stream;
} else {
showlocalVideo.value = true;
showVideo.value = false;
localvideoRef.value.srcObject = stream;
localVideoStream = stream;
}
}
});
};
const setAudio = (stream) => {
if (audioRef.value) {
audioRef.value.srcObject = stream;
} else {
nextTick(() => {
setAudio();
});
}
};
const registerhangupEvent = () => {
hangupCbId = window.lemon.call.addHangupEvt(() => {
speakers.value.length = 0;
selfGranted.value = false;
showVideo.value = false;
showlocalVideo.value = false;
showPanel.value = false;
try {
videoRef.value.pause();
} catch (error) {
console.error('on hangup,video stop error', error);
}
videoRef.value.srcObject = null;
close();
});
};
const registerGrantEvent = () => {
grantCbId = window.lemon.floor.addGrantEvt((event) => {
speakers.value = event.speaker;
selfGranted.value = event.speaker.findIndex((item) => item.number === sessionStorage.getItem('user_id')) >= 0;
if (!localVideoStream && !remoteVideoStream) return;
switch (event.grant_status) {
case '0':
// 话权空闲,本端和对端都不显示画面
if (useOneVideoShow) {
videoRef.value.srcObject = null;
} else {
showVideo.value = false;
showlocalVideo.value = false;
}
break;
case '3':
// 远端有话权设置video 为远端流
if (useOneVideoShow) {
videoRef.value.srcObject = remoteVideoStream;
} else {
showVideo.value = true;
showlocalVideo.value = false;
}
break;
case '4':
// 自己有话权显示本端设置video 为本地流,此时对端是没有画面的
if (useOneVideoShow) {
videoRef.value.srcObject = localVideoStream;
} else {
showVideo.value = false;
showlocalVideo.value = true;
}
break;
}
});
};
const close = () => {
if (rootView) {
rootView.style.display = 'none';
}
};
const applayFloor = () => {
const self = sessionStorage.getItem('user_id');
const index = speakers.value?.findIndex((item) => item.number === self);
if (index >= 0) {
CALL.releaseFloor();
} else {
CALL.applyFloor();
}
};
const hangup = () => {
CALL.hangup(codeId.value);
};
const Init = () => {
let token = window.localStorage.getItem("rhToken");
if (!token) {
let userInfo = {
username: "sgxtcs",
password: "123456",
realm: "puc.com",
webpucUrl: "https://89.40.9.95:16888"
};
lemon.login.login(userInfo).then((esacpe) => {
token = esacpe.token;
window.localStorage.setItem("rhToken", esacpe.token);
});
} else {
ConnectWebsocket(token);
}
};
const ConnectWebsocket = (token) => {
lemon.login.reConnectWebsocket({
username: "sgxtcs",
realm: "puc.com",
webpucUrl: "https://89.40.9.95:16888",
token: token
}).then((resp) => {
console.log(resp,"ConnectWebsocket")
window.lemon.call.addMediaStream((call_id, stream, type) => {
console.log(call_id, stream, type);
});
});
};
const initWave = () => {
if (!waveContainer) {
waveContainer = document.getElementById('voice_wave');
}
audioWave = new SiriWave({
container: waveContainer,
autostart: false,
width: element.value.width,
});
audioWave.start();
};
// 如果要用到录音功能绑定的video 不能切流。 如果半双工要显示本端流和远端流需要用两个Video。
const initVideo = () => {
if (!useOneVideoShow) {
useMedia.init(videoRef.value, audioRef.value);
}
};
onMounted(() => {
nextTick(() => {
Init();
registerStream();
registerhangupEvent();
registerGrantEvent();
videoRef.value.onloadedmetadata = initVideo;
initWave();
});
rootView = document.getElementById('call_div');
window.video = pushVideoRef.value;
window.showVideo = showPushlVideo;
window.videoViewRoot = rootView;
});
onUnmounted(() => {
window.lemon.call.removeMediaStream(streamCbId);
window.lemon.call.removeHangupEvt(hangupCbId);
window.lemon.floor.removeGrantEvt(grantCbId);
});
</script>
<style scoped>
.container {
position: absolute;
display: flex;
flex-direction: column;
justify-content: center;
margin: 2px;
background: #000;
border: 2px dashed #ccc;
border-radius: 16px;
cursor: pointer;
top: 30%;
left: 40%;
}
.video {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: scale-down;
}
.buttonContainer {
position: absolute;
bottom: 0;
width: 96%;
margin: 8px;
}
.speaks {
align-items: center;
}
.wave {
top: 0;
width: 100%;
height: 100px;
}
.close {
position: absolute;
top: 0;
right: 0;
margin: 5px;
}
</style>