更新页面
This commit is contained in:
@ -5,6 +5,9 @@
|
||||
<el-icon style="vertical-align: middle"><CirclePlus /></el-icon>
|
||||
<span style="vertical-align: middle">新增</span>
|
||||
</el-button>
|
||||
<el-button type="primary" @click="openDemo">
|
||||
<span style="vertical-align: middle">DEMO</span>
|
||||
</el-button>
|
||||
</PageTitle>
|
||||
</div>
|
||||
<div ref="searchBox">
|
||||
@ -21,7 +24,6 @@
|
||||
<div class="info h20 ellipsis">会商处置意见:{{ item.czyj }}</div>
|
||||
<div class="info h20 ellipsis">会议时间:{{ item.hskssj }} - {{ item.hsjssj }}</div>
|
||||
</div>
|
||||
|
||||
<div class="mid">
|
||||
<div class="left">
|
||||
<div class="title ellipsis">参会人员:{{ item.chry }}</div>
|
||||
@ -67,10 +69,15 @@
|
||||
<DetailForm ref="detailDiloag" @updateDate="getList" />
|
||||
<RoomDetail />
|
||||
<ConferenceRoom v-model="conferenceRoomVisible" titleValue="会议详情" />
|
||||
|
||||
<!-- 音视频会议窗口 -->
|
||||
<MeetingView v-model="openMeeting" v-if="openMeeting" ></MeetingView>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ElMessageBox } from "element-plus";
|
||||
import * as MOSTY from "@/components/MyComponents/index";
|
||||
import MeetingView from "@/views/consultation/components/meetingView.vue";
|
||||
import PageTitle from "@/components/aboutTable/PageTitle.vue";
|
||||
import Pages from "@/components/aboutTable/Pages.vue";
|
||||
import Search from "@/components/aboutTable/Search.vue";
|
||||
@ -78,13 +85,14 @@
|
||||
import RoomDetail from "./components/roomDetail.vue";
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import { qcckGet, qcckPost, qcckDelete } from "@/api/qcckApi.js";
|
||||
import { reactive, ref, onMounted, getCurrentInstance } from "vue";
|
||||
import { reactive, ref, onMounted, getCurrentInstance,nextTick } from "vue";
|
||||
import ConferenceRoom from "./components/Communications/conferenceRoom.vue";
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const { proxy } = getCurrentInstance();
|
||||
const detailDiloag = ref();
|
||||
const searchBox = ref(); //搜索框
|
||||
|
||||
const openMeeting = ref(false); // 打开会议窗口
|
||||
const searchConfiger = ref([
|
||||
{
|
||||
label: "会议主题",
|
||||
@ -109,12 +117,81 @@ import { reactive, ref, onMounted, getCurrentInstance } from "vue";
|
||||
pageCurrent: 1
|
||||
},
|
||||
});
|
||||
|
||||
const jsonData = ref('')
|
||||
onMounted(() => {
|
||||
jsonData.value = require('@/views/consultation/components/zh_CN.json');
|
||||
nextTick(()=>{
|
||||
Init();
|
||||
})
|
||||
getList();
|
||||
tabHeightFn();
|
||||
});
|
||||
|
||||
const Init = () => {
|
||||
let token = window.localStorage.getItem("rhToken");
|
||||
if (!token) {
|
||||
let userInfo = {
|
||||
username: "linzhigongan2",
|
||||
password: "linzhigongan2",
|
||||
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);
|
||||
getLoginAccountInfo();
|
||||
fetchConferences()
|
||||
// 注册会议管理相关事件
|
||||
useConfernceEvent()
|
||||
});
|
||||
} else {
|
||||
ConnectWebsocket(token);
|
||||
}
|
||||
};
|
||||
|
||||
const ConnectWebsocket = (token) => {
|
||||
lemon.login.reConnectWebsocket({
|
||||
username: "linzhigongan2",
|
||||
realm: "puc.com",
|
||||
webpucUrl: "https://89.40.9.95:16888",
|
||||
token: token
|
||||
}).then((resp) => {
|
||||
if(resp.result != 0){
|
||||
ElMessage.error(jsonData.value['errorCode'][resp.result]);
|
||||
exsit()
|
||||
}else{
|
||||
getLoginAccountInfo()
|
||||
fetchConferences()
|
||||
// 注册会议管理相关事件
|
||||
useConfernceEvent()
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const getLoginAccountInfo =() =>{
|
||||
lemon.login.getLoginAccountInfo().then(res => {
|
||||
let info = JSON.stringify(res.account_info)
|
||||
window.localStorage.setItem("rhInfo",info);
|
||||
window.localStorage.setItem("user_basedata_id",res.account_info.basedata_id);
|
||||
}).catch(err => {
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
const exsit = () =>{
|
||||
lemon.login.logout().then(res=> {
|
||||
|
||||
}).catch(err=> {
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function openDemo() {
|
||||
const NPShref = router.resolve({ path: '/consultation', query: {}});
|
||||
window.open(NPShref.href, "_blank");
|
||||
}
|
||||
|
||||
// 搜索
|
||||
const onSearch = (val) => {
|
||||
queryFrom.value = { ...val };
|
||||
@ -122,8 +199,8 @@ import { reactive, ref, onMounted, getCurrentInstance } from "vue";
|
||||
queryFrom.value.startTime = val.daterange[0];
|
||||
queryFrom.value.endTime = val.daterange[1];
|
||||
} else {
|
||||
queryFrom.value.startTime = '';
|
||||
queryFrom.value.endTime = '';
|
||||
delete queryFrom.value.startTime;
|
||||
delete queryFrom.value.endTime;
|
||||
}
|
||||
pageData.pageConfiger.pageCurrent = 1;
|
||||
getList();
|
||||
@ -167,8 +244,30 @@ import { reactive, ref, onMounted, getCurrentInstance } from "vue";
|
||||
})
|
||||
};
|
||||
// 加入会议
|
||||
const joinMeeting = (item) => {
|
||||
conferenceRoomVisible.value = true;
|
||||
const joinMeeting = (item) => {
|
||||
console.log(item.hybh,'===========00');
|
||||
|
||||
ElMessageBox.confirm('确定开始会议?','提示',{ confirmButtonText:'确定', cancelButtonText:'取消', type:'warning' }).then(res=>{
|
||||
openMeeting.value = true;
|
||||
nextTick(()=>{
|
||||
let params = {
|
||||
"number": it.number,
|
||||
"nick": it.subject,
|
||||
"mute_status": it.status,
|
||||
"microphone_status": 1,
|
||||
"camera_status": 1
|
||||
}
|
||||
// lemon.conference.enterConferenceByNumber(params).then(res=> {
|
||||
// console.log(res,'加入会议......');
|
||||
// }).catch(err=> {
|
||||
// console.log(err,' 加入会议失败......');
|
||||
// })
|
||||
})
|
||||
}).catch(()=>{
|
||||
|
||||
})
|
||||
|
||||
// conferenceRoomVisible.value = true;
|
||||
// qcckPost({id:item.id},'/mosty-gsxt/wshs/addWshyRy').then((res)=>{
|
||||
// getList();
|
||||
// })
|
||||
@ -222,7 +321,7 @@ const conferenceRoomVisible = ref(false);
|
||||
padding: 10px 20px;
|
||||
}
|
||||
.list {
|
||||
height: calc(100% - 40px);
|
||||
height: calc(100% - 10px);
|
||||
gap: 10px;
|
||||
margin: 0 15px;
|
||||
overflow: auto;
|
||||
|
||||
BIN
src/views/consultation/SDK中文文档/Web-Client-API接口文档.docx
Normal file
BIN
src/views/consultation/SDK中文文档/Web-Client-API接口文档.docx
Normal file
Binary file not shown.
BIN
src/views/consultation/SDK中文文档/demo_readme_zh_CN.docx
Normal file
BIN
src/views/consultation/SDK中文文档/demo_readme_zh_CN.docx
Normal file
Binary file not shown.
BIN
src/views/consultation/SDK中文文档/webPUC SDK 使用说明.docx
Normal file
BIN
src/views/consultation/SDK中文文档/webPUC SDK 使用说明.docx
Normal file
Binary file not shown.
BIN
src/views/consultation/SDK中文文档/~$I错误码参考表.docx
Normal file
BIN
src/views/consultation/SDK中文文档/~$I错误码参考表.docx
Normal file
Binary file not shown.
BIN
src/views/consultation/SDK中文文档/~$bPUC SDK 使用说明.docx
Normal file
BIN
src/views/consultation/SDK中文文档/~$bPUC SDK 使用说明.docx
Normal file
Binary file not shown.
140
src/views/consultation/components/audioAndVoice.vue
Normal file
140
src/views/consultation/components/audioAndVoice.vue
Normal file
@ -0,0 +1,140 @@
|
||||
<template>
|
||||
<el-dialog v-model="props.modelValue" title="新增音视频会议" width="600px" @close="handleClose" :close-on-click-modal="false">
|
||||
<!-- 常规表单部分 -->
|
||||
<el-form ref="formRef" :model="formData" layout="vertical">
|
||||
<el-row :gutter="24">
|
||||
<el-col :span="12">
|
||||
<!-- 主题 -->
|
||||
<el-form-item label="会议主题">
|
||||
<el-input v-model="formData.subject" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="12">
|
||||
<!-- 开始时间 -->
|
||||
<el-form-item label="开始时间">
|
||||
<el-date-picker v-model="formData.appointment" type="datetime" unlink-panels value-format="YYYY-MM-DD HH:mm:ss"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="12">
|
||||
<!-- 会议时长 -->
|
||||
<el-form-item label="会议时长">
|
||||
<el-select v-model="formData.duration" >
|
||||
<el-option value="30" label="30 分钟"></el-option>
|
||||
<el-option value="60" label="60 分钟"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="12">
|
||||
<!-- 提醒时间 -->
|
||||
<el-form-item label="提醒时间">
|
||||
<el-select v-model="formData.alarm" >
|
||||
<el-option :value="1">1 分钟前</el-option>
|
||||
<el-option :value="5">5 分钟前</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="24">
|
||||
<!-- 备注 -->
|
||||
<el-form-item label="备注">
|
||||
<el-input type="textarea" v-model="formData.remark" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
|
||||
<!-- 设备选择穿梭框部分 -->
|
||||
<div class="groupTransfer">
|
||||
<div class="head flex just-between align-center">
|
||||
<span>成员</span>
|
||||
<span><el-icon><Delete/></el-icon></span>
|
||||
</div>
|
||||
<ul class="peolist">
|
||||
<li v-for="(it,idx) in formData.members" :key="idx" class="flex just-between align-center">
|
||||
<div class="flex align-center"> <img class="mr5" src="@/assets/images/webPuc/svgs/avatar_call_online_small.svg" alt="">{{it.alias}} ( {{ it.number }})</div>
|
||||
<span><el-icon><Delete/></el-icon></span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="tc mt10">
|
||||
<el-button @click="handleClose">取消</el-button>
|
||||
<el-button @click="okBtn">确定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { timeValidate } from '@/utils/tools'
|
||||
import { ref,defineEmits, onMounted } from 'vue'
|
||||
const props = defineProps({
|
||||
modelValue:Boolean,
|
||||
})
|
||||
const emit = defineEmits(['update:modelValue','save'])
|
||||
const baseInfo = localStorage.getItem('rhInfo') ? JSON.parse(localStorage.getItem('rhInfo')) : {};
|
||||
const formData = ref({
|
||||
alarm:1,
|
||||
duration:'30',
|
||||
})
|
||||
const remarkModal = ref({})
|
||||
onMounted(()=>{
|
||||
formData.value.subject = baseInfo.dispatcher_name +' 预约的会议';
|
||||
formData.value.appointment = timeValidate( getRecentTime(10));
|
||||
formData.value.members = [
|
||||
{
|
||||
alias:baseInfo.dispatcher_name,
|
||||
basedata_id:baseInfo.basedata_id,
|
||||
guid:baseInfo.user_guid,
|
||||
number:baseInfo.user_id,
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
const getRecentTime = (n) => {
|
||||
var currentDate = new Date();
|
||||
var preDate = new Date(currentDate.getTime() + n * 60 * 1000)
|
||||
return preDate
|
||||
}
|
||||
|
||||
|
||||
// 关闭
|
||||
const handleClose = () =>{
|
||||
emit('update:modelValue',false)
|
||||
};
|
||||
|
||||
// 保存
|
||||
const okBtn = () =>{
|
||||
let obj = { ...formData.value }
|
||||
obj.appointment = new Date(obj.appointment).toISOString();
|
||||
emit('save',obj)
|
||||
emit('update:modelValue',false)
|
||||
};
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.groupTransfer{
|
||||
border: 1px solid #ccc;
|
||||
.head{
|
||||
background: rgb(85,89,93);
|
||||
line-height: 40px;
|
||||
color: #fff;
|
||||
padding: 0 10px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.peolist{
|
||||
height: 200px;
|
||||
overflow: hidden;
|
||||
overflow-y: auto;
|
||||
li{
|
||||
line-height: 40px;
|
||||
color: #fff;
|
||||
padding: 0 10px;
|
||||
box-sizing: border-box;
|
||||
background: rgb(28,32,41);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
94
src/views/consultation/components/content.vue
Normal file
94
src/views/consultation/components/content.vue
Normal file
@ -0,0 +1,94 @@
|
||||
<template>
|
||||
<div class="callingNotification_content">
|
||||
<div class="left">
|
||||
<div class="icon">
|
||||
<img :src="currentIcon" width="32" height="32" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="right">
|
||||
<div class="name">
|
||||
{{ getName }}
|
||||
</div>
|
||||
<div class="fixed">
|
||||
<div class="icon">
|
||||
<img
|
||||
v-if="call_mode === 0"
|
||||
src="@/assets/images/webPuc/svgs/phone_off_small.svg"
|
||||
width="12"
|
||||
height="12"
|
||||
/>
|
||||
<img
|
||||
v-if="call_mode > 0"
|
||||
src="@/assets/images/webPuc/svgs/video_off_small.svg"
|
||||
width="12"
|
||||
height="9"
|
||||
/>
|
||||
</div>
|
||||
<div class="text">
|
||||
{{ calling }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed, toRef } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
callInfo: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
calling: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
getName: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
const callInfo = toRef(props, 'callInfo');
|
||||
const calling = toRef(props, 'calling');
|
||||
const getName = toRef(props, 'getName');
|
||||
|
||||
const {
|
||||
attribute: { call_mode },
|
||||
} = callInfo.value;
|
||||
|
||||
const currentIcon = computed(() => {
|
||||
return require('@/assets/images/webPuc/svgs/avatar_call_online_small.svg');
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.callingNotification_content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 10px;
|
||||
.left {
|
||||
margin-right: 8px;
|
||||
}
|
||||
.right {
|
||||
.name {
|
||||
margin-bottom: 5px;
|
||||
font-size: 14px;
|
||||
}
|
||||
.fixed {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.icon {
|
||||
margin-right: 5px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.text {
|
||||
font-size: 12px;
|
||||
color: var(--color-text-2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
74
src/views/consultation/components/footer.vue
Normal file
74
src/views/consultation/components/footer.vue
Normal file
@ -0,0 +1,74 @@
|
||||
<template>
|
||||
<div class="callingNotification_footer">
|
||||
<Button type="primary" status="success" @click="handleAnswer">
|
||||
<template #icon>
|
||||
<img src="@/assets/images/webPuc/svgs/callingNotification_answer.svg" />
|
||||
</template>
|
||||
{{ answerText }}
|
||||
</Button>
|
||||
<Button type="primary" status="danger" @click="handleHangUp">
|
||||
<template #icon>
|
||||
<img src="@/assets/images/webPuc/svgs/callingNotification_hang_up.svg" />
|
||||
</template>
|
||||
{{ hangUp }}
|
||||
</Button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { toRef } from 'vue';
|
||||
import { Button } from 'element-plus';
|
||||
import useCallModule from '@/views/consultation/sdk/call';
|
||||
|
||||
const props = defineProps({
|
||||
answer: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
hangUp: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
callInfo: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
const answerText = toRef(props, 'answer');
|
||||
const hangUp = toRef(props, 'hangUp');
|
||||
const callInfo = toRef(props, 'callInfo');
|
||||
|
||||
const CALL = useCallModule();
|
||||
|
||||
const {
|
||||
call_id,
|
||||
attribute: { call_mode },
|
||||
} = callInfo.value;
|
||||
|
||||
const handleAnswer = () => {
|
||||
CALL.answerCall();
|
||||
};
|
||||
|
||||
const handleHangUp = () => {
|
||||
CALL.hangup();
|
||||
};
|
||||
|
||||
defineExpose({
|
||||
handleHangUp,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.callingNotification_footer {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
.arco-btn {
|
||||
width: 100px;
|
||||
:deep(.arco-btn-icon) {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
460
src/views/consultation/components/js/useConfernceControlEvent.js
Normal file
460
src/views/consultation/components/js/useConfernceControlEvent.js
Normal file
@ -0,0 +1,460 @@
|
||||
import { ref, onUnmounted } from 'vue';
|
||||
import { ElNotification } from 'element-plus';
|
||||
import emitter from "@/utils/eventBus.js";
|
||||
import useConferenceControlModule from '@/views/consultation/sdk/conferenceControl';
|
||||
import store from '@/store'
|
||||
|
||||
const sdkConfernceControlModule = useConferenceControlModule();
|
||||
|
||||
// 通知时长
|
||||
const duration = 5 * 1000;
|
||||
|
||||
const lockCallbackId = ref('');
|
||||
const activeConfigChangeCallbackId = ref('');
|
||||
const memberJoinCallbackId = ref('');
|
||||
const memberLeftCallbackId = ref('');
|
||||
const updateSubjecCallbackId = ref('');
|
||||
const updateMemberNickCallbackId = ref('');
|
||||
const inviteMemberCallbackId = ref('');
|
||||
const memberCameraCallbackId = ref('');
|
||||
const memberProhibitionCallbackId = ref('');
|
||||
const allMemberProhibitionCallbackId = ref('');
|
||||
const memberMuteCallbackId = ref('');
|
||||
const memberSpeakCallbackId = ref('');
|
||||
const voiceStimulationCallbackId = ref('');
|
||||
const memberSpeakingStateCallbackId = ref('');
|
||||
const setLayoutTypenCallbackId = ref('');
|
||||
const setMemberRoleCallbackId = ref('');
|
||||
const cancelMemberSpeakCallbackId = ref('');
|
||||
const addMemberCallbackId = ref('');
|
||||
const deleteMemberCallbackId = ref('');
|
||||
const screenSharingCallbackId = ref('');
|
||||
const deviceListChangegCallbackId = ref('');
|
||||
|
||||
// 移除事件注册
|
||||
const unRegisterConferenceControldata = () => {
|
||||
sdkConfernceControlModule.removeLockListener(lockCallbackId.value);
|
||||
sdkConfernceControlModule.removeActiveConfigChangeListener(
|
||||
activeConfigChangeCallbackId.value
|
||||
);
|
||||
sdkConfernceControlModule.removeMemberJoinListener(
|
||||
memberJoinCallbackId.value
|
||||
);
|
||||
sdkConfernceControlModule.removeMemberLeftListener(
|
||||
memberLeftCallbackId.value
|
||||
);
|
||||
sdkConfernceControlModule.removeUpdateSubjectListener(
|
||||
updateSubjecCallbackId.value
|
||||
);
|
||||
sdkConfernceControlModule.removeModifyMemberNickListener(
|
||||
updateMemberNickCallbackId.value
|
||||
);
|
||||
sdkConfernceControlModule.removeInviteMemberListener(
|
||||
inviteMemberCallbackId.value
|
||||
);
|
||||
sdkConfernceControlModule.removeMemberCameraListener(
|
||||
memberCameraCallbackId.value
|
||||
);
|
||||
sdkConfernceControlModule.removeMemberProhibitionListener(
|
||||
memberProhibitionCallbackId.value
|
||||
);
|
||||
sdkConfernceControlModule.removeAllMemberProhibitionListener(
|
||||
allMemberProhibitionCallbackId.value
|
||||
);
|
||||
sdkConfernceControlModule.removeMemberMuteListener(
|
||||
memberMuteCallbackId.value
|
||||
);
|
||||
sdkConfernceControlModule.removeAssignMemberSpeakListener(
|
||||
memberSpeakCallbackId.value
|
||||
);
|
||||
sdkConfernceControlModule.removeVoiceStimulationListener(
|
||||
voiceStimulationCallbackId.value
|
||||
);
|
||||
sdkConfernceControlModule.removeMemberSpeakingStateListener(
|
||||
memberSpeakingStateCallbackId.value
|
||||
);
|
||||
sdkConfernceControlModule.removeSetLayoutTypeListener(
|
||||
setLayoutTypenCallbackId.value
|
||||
);
|
||||
sdkConfernceControlModule.removeSetMemberRoleListener(
|
||||
setMemberRoleCallbackId.value
|
||||
);
|
||||
sdkConfernceControlModule.removeCancelMemberSpeakListener(
|
||||
cancelMemberSpeakCallbackId.value
|
||||
);
|
||||
sdkConfernceControlModule.removeAddMemberListener(addMemberCallbackId.value);
|
||||
sdkConfernceControlModule.removeDeleteMemberListener(
|
||||
deleteMemberCallbackId.value
|
||||
);
|
||||
sdkConfernceControlModule.removeScreenSharingListener(
|
||||
screenSharingCallbackId.value
|
||||
);
|
||||
sdkConfernceControlModule.removeDeviceListChangeListener(
|
||||
deviceListChangegCallbackId.value
|
||||
);
|
||||
};
|
||||
|
||||
/* 会控管理相关 */
|
||||
export default ({ onDeviceListChange }) => {
|
||||
// 初始化清除回调事件,避免外部重复调用注册方法导致事件重复
|
||||
unRegisterConferenceControldata();
|
||||
const globalStore = store.state.useGlobalStore;
|
||||
|
||||
// 事件注册方便任意位置调用
|
||||
emitter.on('unRegisterConferenceControldata', unRegisterConferenceControldata);
|
||||
|
||||
// 组件卸载时自动移除
|
||||
onUnmounted(() => {
|
||||
unRegisterConferenceControldata();
|
||||
});
|
||||
|
||||
/**
|
||||
* 当前进行中会议配置信息变化通知
|
||||
* */
|
||||
activeConfigChangeCallbackId.value =
|
||||
sdkConfernceControlModule.addActiveConfigChangeListener((config) => {
|
||||
store.dispatch("setActiveConfig",config);
|
||||
});
|
||||
|
||||
/**
|
||||
* 会议室锁定通知
|
||||
* */
|
||||
lockCallbackId.value = sdkConfernceControlModule.addLockListener((data) => {
|
||||
console.log('+++++++++ 会议室锁定通知 ++++++++++', data);
|
||||
|
||||
const descMap = {
|
||||
0: '解锁',
|
||||
1: '锁定',
|
||||
};
|
||||
|
||||
ElNotification.info({
|
||||
id: `${Date.now()}`,
|
||||
title: '会议室锁定通知',
|
||||
message: `【${data.operator.alias}】${descMap[data.status]}会议室`,
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* 增加会议成员通知
|
||||
* */
|
||||
addMemberCallbackId.value = sdkConfernceControlModule.addAddMemberListener(
|
||||
(data) => {
|
||||
console.log('+++++++++ 【会控】增加会议成员通知 ++++++++++', data);
|
||||
|
||||
const name = data.members.map((v) => v.alias || v.number).join('; ');
|
||||
|
||||
ElNotification.info({
|
||||
id: `${Date.now()}`,
|
||||
title: '【会控】增加会议成员通知',
|
||||
message: `【${name}】已成为【会议:${data.meeting.number}】的会议成员!`,
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* 删除会议成员通知
|
||||
* */
|
||||
deleteMemberCallbackId.value =
|
||||
sdkConfernceControlModule.addDeleteMemberListener((data) => {
|
||||
console.log('+++++++++ 【会控】删除会议成员通知 ++++++++++', data);
|
||||
|
||||
const name = data.member.alias || data.member.number;
|
||||
|
||||
ElNotification.info({
|
||||
id: `${Date.now()}`,
|
||||
title: '【会控】删除会议成员通知',
|
||||
message: `【${name}】已不属于【会议:${data.meeting.number}】的会议成员!`,
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* 成员入会通知
|
||||
* */
|
||||
memberJoinCallbackId.value = sdkConfernceControlModule.addMemberJoinListener(
|
||||
(data) => {
|
||||
console.log('+++++++++ 成员入会通知 ++++++++++', data);
|
||||
|
||||
const name = data.member.alias || data.member.number;
|
||||
|
||||
ElNotification.info({
|
||||
id: `${Date.now()}`,
|
||||
title: '成员入会通知',
|
||||
message: `【${name}】加入了【会议:${data.meeting.number}】!`,
|
||||
});
|
||||
|
||||
// 自己入会,展示会议面板
|
||||
if (
|
||||
data.member.basedata_id === sessionStorage.getItem('user_basedata_id')
|
||||
) {
|
||||
// 展示会议面板
|
||||
globalStore.setShowConfencePanel(true);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* 成员离会通知
|
||||
* */
|
||||
memberLeftCallbackId.value = sdkConfernceControlModule.addMemberLeftListener(
|
||||
(data) => {
|
||||
console.log('+++++++++ 成员离会通知 ++++++++++', data);
|
||||
|
||||
const name = data.member.alias || data.member.number;
|
||||
|
||||
ElNotification.info({
|
||||
id: `${Date.now()}`,
|
||||
title: '成员离会通知',
|
||||
message: `【${name}】离开了【会议:${data.meeting.number}】!`,
|
||||
});
|
||||
|
||||
// 不是自己,不需处理
|
||||
if (
|
||||
data.member.basedata_id !== sessionStorage.getItem('user_basedata_id')
|
||||
) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* 更新会议主题通知
|
||||
* */
|
||||
updateSubjecCallbackId.value =
|
||||
sdkConfernceControlModule.addUpdateSubjectListener((data) => {
|
||||
console.log('+++++++++ 更新会议主题通知 ++++++++++', data);
|
||||
|
||||
ElNotification.info({
|
||||
id: `${Date.now()}`,
|
||||
title: '更新会议主题通知',
|
||||
message: `【${data.operator.alias}】修改了会议主题!`,
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* 设置成员角色通知
|
||||
* */
|
||||
setMemberRoleCallbackId.value =
|
||||
sdkConfernceControlModule.addSetMemberRoleListener((data) => {
|
||||
console.log('+++++++++ 设置成员角色通知 ++++++++++', data);
|
||||
|
||||
const roleDesc = {
|
||||
0: '成员',
|
||||
1: '主席',
|
||||
2: '创建者',
|
||||
};
|
||||
|
||||
ElNotification.info({
|
||||
id: `${Date.now()}`,
|
||||
title: '设置成员角色通知',
|
||||
message: `${data.operator.alias} 将 ${data.member.alias} 设置为了【${
|
||||
roleDesc[data.member_role]
|
||||
}】`,
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* 修改会议成员昵称通知
|
||||
* */
|
||||
updateMemberNickCallbackId.value =
|
||||
sdkConfernceControlModule.addModifyMemberNickListener((data) => {
|
||||
console.log('+++++++++ 修改会议成员昵称通知 ++++++++++', data);
|
||||
|
||||
ElNotification.info({
|
||||
id: `${Date.now()}`,
|
||||
title: '修改会议成员昵称通知',
|
||||
message: `【${data.operator.alias}】修改了会议成员昵称为【${data.nickname}】!`,
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* 呼叫未入会成员通知
|
||||
* */
|
||||
inviteMemberCallbackId.value =
|
||||
sdkConfernceControlModule.addInviteMemberListener((data) => {
|
||||
console.log('+++++++++ 呼叫未入会成员通知 ++++++++++', data);
|
||||
|
||||
ElNotification.info({
|
||||
id: `${Date.now()}`,
|
||||
title: '呼叫未入会成员通知',
|
||||
message: `收到会议号【${data.meeting.number}】的入会通知!`,
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* 摄像头开关通知
|
||||
* */
|
||||
memberCameraCallbackId.value =
|
||||
sdkConfernceControlModule.addMemberCameraListener((data) => {
|
||||
console.log('+++++++++ 摄像头开关通知 ++++++++++', data);
|
||||
|
||||
const cameraDesc = {
|
||||
0: '已关闭',
|
||||
1: '已开启',
|
||||
2: '无',
|
||||
};
|
||||
|
||||
ElNotification.info({
|
||||
id: `${Date.now()}`,
|
||||
title: '摄像头开关通知',
|
||||
message: `${data.operator.alias}【${cameraDesc[data.status]}】${
|
||||
data.member.alias
|
||||
} 的摄像头`,
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* 禁言通知
|
||||
* */
|
||||
memberProhibitionCallbackId.value =
|
||||
sdkConfernceControlModule.addMemberProhibitionListener((data) => {
|
||||
console.log('+++++++++ 禁言通知 ++++++++++', data);
|
||||
|
||||
const prohibitioDesc = {
|
||||
0: '解除禁言',
|
||||
1: '禁言',
|
||||
};
|
||||
const name = data.member.alias || data.member.number;
|
||||
ElNotification.info({
|
||||
id: `${Date.now()}`,
|
||||
title: '禁言通知',
|
||||
message: `${data.operator.alias} 对【${name}】${
|
||||
prohibitioDesc[data.status]
|
||||
}!`,
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* 全部禁言通知
|
||||
* */
|
||||
allMemberProhibitionCallbackId.value =
|
||||
sdkConfernceControlModule.addAllMemberProhibitionListener((data) => {
|
||||
console.log('+++++++++ 全部禁言通知 ++++++++++', data);
|
||||
|
||||
const prohibitioDesc = {
|
||||
0: '解除全部禁言',
|
||||
1: '开启全部禁言',
|
||||
};
|
||||
|
||||
ElNotification.info({
|
||||
id: `${Date.now()}`,
|
||||
title: '全部禁言通知',
|
||||
message: `${data.operator.alias} ${prohibitioDesc[data.status]}!`,
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* 静音通知
|
||||
* */
|
||||
memberMuteCallbackId.value = sdkConfernceControlModule.addMemberMuteListener(
|
||||
(data) => {
|
||||
console.log('+++++++++ 静音通知 ++++++++++', data);
|
||||
|
||||
const muteDesc = {
|
||||
0: '取消静音',
|
||||
1: '静音',
|
||||
2: '无音频',
|
||||
};
|
||||
const name = data.member.alias || data.member.number;
|
||||
|
||||
ElNotification.info({
|
||||
id: `${Date.now()}`,
|
||||
title: '静音通知',
|
||||
message: `${data.operator.alias} 对【${name}】${
|
||||
muteDesc[data.status]
|
||||
}!`,
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* 设备列表变化通知
|
||||
* */
|
||||
deviceListChangegCallbackId.value =
|
||||
sdkConfernceControlModule.addDeviceListChangeListener((data) => {
|
||||
console.log('+++++++++ 设备列表变化通知 ++++++++++', data);
|
||||
if (onDeviceListChange) {
|
||||
onDeviceListChange(data);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* 指定成员讲话通知
|
||||
* */
|
||||
memberSpeakCallbackId.value =
|
||||
sdkConfernceControlModule.addAssignMemberSpeakListener((data) => {
|
||||
console.log('+++++++++ 指定成员讲话通知 ++++++++++', data);
|
||||
|
||||
const name = data.member.alias || data.member.number;
|
||||
|
||||
ElNotification.info({
|
||||
id: `${Date.now()}`,
|
||||
title: '指定成员讲话通知',
|
||||
message: `${data.operator.alias} 指定【${name}】讲话!`,
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* 取消指定成员讲话通知
|
||||
* */
|
||||
cancelMemberSpeakCallbackId.value =
|
||||
sdkConfernceControlModule.addCancelMemberSpeakListener((data) => {
|
||||
console.log('+++++++++ 取消成员讲话通知 ++++++++++', data);
|
||||
|
||||
const name = data.member.alias || data.member.number;
|
||||
|
||||
ElNotification.info({
|
||||
id: `${Date.now()}`,
|
||||
title: '取消成员讲话通知',
|
||||
message: `${data.operator.alias} 取消【${name}】讲话!`,
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* 成员讲话状态通知
|
||||
* */
|
||||
memberSpeakingStateCallbackId.value =
|
||||
sdkConfernceControlModule.addMemberSpeakingStateListener((data) => {
|
||||
console.log('+++++++++ 成员讲话状态通知 ++++++++++', data);
|
||||
});
|
||||
|
||||
/**
|
||||
* 语音激励成员讲话状态通知
|
||||
* */
|
||||
voiceStimulationCallbackId.value =
|
||||
sdkConfernceControlModule.addVoiceStimulationListener((data) => {
|
||||
console.log('+++++++++ 语音激励成员讲话状态通知 ++++++++++', data);
|
||||
});
|
||||
|
||||
/**
|
||||
* 修改布局通知
|
||||
* */
|
||||
setLayoutTypenCallbackId.value =
|
||||
sdkConfernceControlModule.addSetLayoutTypeListener((data) => {
|
||||
console.log('+++++++++ 修改布局通知 ++++++++++', data);
|
||||
|
||||
ElNotification.info({
|
||||
id: `${Date.now()}`,
|
||||
title: '修改布局通知',
|
||||
message: `修改布局通知`,
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* 屏幕共享通知
|
||||
* */
|
||||
screenSharingCallbackId.value =
|
||||
sdkConfernceControlModule.addScreenSharingListener((data) => {
|
||||
console.log('+++++++++ 屏幕共享通知 ++++++++++', data);
|
||||
|
||||
const descMap = {
|
||||
0: '取消共享', //(未共享)
|
||||
1: '共享屏幕', //(已共享)
|
||||
};
|
||||
|
||||
ElNotification.info({
|
||||
id: `${Date.now()}`,
|
||||
title: '屏幕共享通知',
|
||||
message: `【${data.member.alias}】${descMap[data.sharing_status]}`,
|
||||
});
|
||||
});
|
||||
};
|
||||
234
src/views/consultation/components/js/useConfernceEvent.js
Normal file
234
src/views/consultation/components/js/useConfernceEvent.js
Normal file
@ -0,0 +1,234 @@
|
||||
import { ref, getCurrentInstance, onUnmounted } from 'vue';
|
||||
import { ElNotification } from 'element-plus';
|
||||
import { ConferenceCallingNotification } from '@/views/consultation/hooks/callingNotification';
|
||||
import useConfernceModule from '@/views/consultation/sdk/conference';
|
||||
import store from '@/store'
|
||||
import emitter from "@/utils/eventBus.js";
|
||||
|
||||
const sdkConfernceModule = useConfernceModule();
|
||||
|
||||
// 通知时长
|
||||
const duration = 10 * 1000;
|
||||
|
||||
const createCallbackId = ref('');
|
||||
const reminCallbackId = ref('');
|
||||
const deleteCallbackId = ref('');
|
||||
const updateCallbackId = ref('');
|
||||
const addMemberCallbackId = ref('');
|
||||
const deleteMemberCallbackId = ref('');
|
||||
const mediaStreamCallbackId = ref('');
|
||||
const answerAckCallbackId = ref('');
|
||||
const hangupCallbackId = ref('');
|
||||
const incomingCallbackId = ref('');
|
||||
const stateCallbackId = ref('');
|
||||
|
||||
// 移除事件注册
|
||||
const unRegisterConferenceEvent = () => {
|
||||
sdkConfernceModule.removeCreateListener(createCallbackId.value);
|
||||
sdkConfernceModule.removeRemindListener(reminCallbackId.value);
|
||||
sdkConfernceModule.removeDeleteListener(deleteCallbackId.value);
|
||||
sdkConfernceModule.removeUpdateListener(updateCallbackId.value);
|
||||
sdkConfernceModule.removeAddMemberListener(addMemberCallbackId.value);
|
||||
sdkConfernceModule.removeDeleteMemberListener(deleteMemberCallbackId.value);
|
||||
sdkConfernceModule.removeMediaStream(mediaStreamCallbackId.value);
|
||||
sdkConfernceModule.removeAnswerAckEvt(answerAckCallbackId.value);
|
||||
sdkConfernceModule.removeHangupEvt(hangupCallbackId.value);
|
||||
sdkConfernceModule.removeIncomingEvt(incomingCallbackId.value);
|
||||
sdkConfernceModule.removeStateChangeListener(stateCallbackId.value);
|
||||
};
|
||||
|
||||
/* 会议管理相关 */
|
||||
export default () => {
|
||||
const globalStore = store.state.useGlobalStore;
|
||||
|
||||
// 初始化清除回调事件,避免外部重复调用注册方法导致事件重复
|
||||
unRegisterConferenceEvent();
|
||||
|
||||
// 事件注册方便任意位置调用
|
||||
emitter.on('unRegisterConferenceEvent',unRegisterConferenceEvent)
|
||||
|
||||
// 组件卸载时自动移除
|
||||
onUnmounted(() => {
|
||||
unRegisterConferenceEvent();
|
||||
});
|
||||
|
||||
/**
|
||||
* 添加创建通知,事件分发中心会自动过滤【创建者】
|
||||
* */
|
||||
createCallbackId.value = sdkConfernceModule.addCreateListener((data) => {
|
||||
console.log('+++++++++ 会议创建通知 ++++++++++', data);
|
||||
|
||||
ElNotification.info({
|
||||
id: `${Date.now()}`,
|
||||
title: '会议创建通知',
|
||||
message: `收到来自【${ data.creator.alias }】创建的会议提醒,会议开始时间为【${data.appointment}】,参会者 ${ data.members.length } 人【${data.members.map((v) => v.alias).join('; ')}】`,
|
||||
});
|
||||
|
||||
// 拉取会议列表
|
||||
emitter.emit('fetchConfence');
|
||||
});
|
||||
|
||||
/**
|
||||
* 添加会议提醒通知
|
||||
*/
|
||||
reminCallbackId.value = sdkConfernceModule.addRemindListener((data) => {
|
||||
console.log('+++++++++ 会议开始提醒 ++++++++++', data);
|
||||
|
||||
ElNotification.info({
|
||||
id: `${Date.now()}`,
|
||||
title: '会议开始提醒',
|
||||
message: `收到来自【${data.creator.alias}】创建的会议提醒,会议主题【${ data.subject }】,会议开始时间为【${data.appointment}】,参会者 ${ data.members.length } 人【${data.members.map((v) => v.alias).join('; ')}】`,
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* 会议删除通知(注:服务端目前只修改成员会议的状态,不会真正删除,即不会派发 evt 通知)
|
||||
*/
|
||||
deleteCallbackId.value = sdkConfernceModule.addDeleteListener((data) => {
|
||||
console.log('+++++++++ 会议删除通知 ++++++++++', data);
|
||||
|
||||
ElNotification.info({
|
||||
id: `${Date.now()}`,
|
||||
title: '会议删除通知',
|
||||
message: `由【${data.creator.alias}】创建的【${data.appointment}】【${data.subject}】的会议已被删除!`,
|
||||
});
|
||||
|
||||
// 拉取会议列表
|
||||
emitter.emit('fetchConfence');
|
||||
});
|
||||
|
||||
/**
|
||||
* 会议修改通知
|
||||
* */
|
||||
updateCallbackId.value = sdkConfernceModule.addUpdateListener((data) => {
|
||||
console.log('+++++++++ 会议修改通知 ++++++++++', data);
|
||||
|
||||
ElNotification.info({
|
||||
id: `${Date.now()}`,
|
||||
title: '会议修改通知',
|
||||
message: `由【${data.creator.alias}】创建的【${data.appointment}】【${data.subject}】的会议发生调整!`,
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* 增加会议成员通知
|
||||
* */
|
||||
addMemberCallbackId.value = sdkConfernceModule.addAddMemberListener(
|
||||
(data) => {
|
||||
console.log('+++++++++ 增加会议成员通知 ++++++++++', data);
|
||||
|
||||
const name = data.members.map((v) => v.alias || v.number).join('; ');
|
||||
|
||||
ElNotification.info({
|
||||
id: `${Date.now()}`,
|
||||
title: '增加会议成员通知',
|
||||
message: `【${name}】已成为【会议:${data.meeting.number}】的会议成员!`,
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* 删除会议成员通知
|
||||
* */
|
||||
deleteMemberCallbackId.value = sdkConfernceModule.addDeleteMemberListener(
|
||||
(data) => {
|
||||
console.log('+++++++++ 删除会议成员通知 ++++++++++', data);
|
||||
const name = data.member.alias || data.member.number;
|
||||
|
||||
ElNotification.info({
|
||||
id: `${Date.now()}`,
|
||||
title: '删除会议成员通知',
|
||||
message: `【${name}】已不属于【会议:${data.meeting.number}】的会议成员!`,
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* 来电通知
|
||||
* */
|
||||
incomingCallbackId.value = sdkConfernceModule.addIncomingEvt((data) => {
|
||||
console.log('+++++++++ 来电通知 ++++++++++', data);
|
||||
|
||||
// 显示来电弹窗
|
||||
ConferenceCallingNotification({
|
||||
conference: data.conference,
|
||||
call_id: data.call_id,
|
||||
text: {
|
||||
calling: '来电',
|
||||
title:'会议已经开始',
|
||||
answer: '立即进入',
|
||||
hangUp: '暂不进入',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* 来电接听通知
|
||||
* */
|
||||
answerAckCallbackId.value = sdkConfernceModule.addAnswerAckEvt((data) => {
|
||||
console.log('+++++++++ 来电接听通知 ++++++++++', data);
|
||||
});
|
||||
|
||||
/**
|
||||
* 挂断通知:来电挂断 或 离开会议
|
||||
* */
|
||||
hangupCallbackId.value = sdkConfernceModule.addHangupEvt((data) => {
|
||||
console.log('+++++++++ 挂断通知 ++++++++++', data);
|
||||
|
||||
emitter.emit('onHangup', data);
|
||||
});
|
||||
|
||||
/**
|
||||
* 媒体流通知
|
||||
* */
|
||||
mediaStreamCallbackId.value = sdkConfernceModule.addMediaStream(
|
||||
(call_id, stream, type) => {
|
||||
console.log('+++++++++ 媒体流通知 ++++++++++');
|
||||
emitter.emit('onMediaStream', { call_id, stream, type });
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* 会议状态变更通知
|
||||
*/
|
||||
stateCallbackId.value = sdkConfernceModule.addStateChangeListener((data) => {
|
||||
console.log('+++++++++ 会议状态变更通知 ++++++++++', data);
|
||||
|
||||
// state 0=未开始,1=进行中,2=已取消,3=已结束,三方网关 上报会议开始 为 1,上报会议结束 为 3
|
||||
switch (data.state) {
|
||||
case 0: // 未开始
|
||||
break;
|
||||
|
||||
case 1: // 进行中
|
||||
ElNotification.info({
|
||||
id: `${Date.now()}`,
|
||||
title: '会议开始通知',
|
||||
message: `会议号为【${data.meeting.number}】的会议正在进行中!`,
|
||||
});
|
||||
break;
|
||||
|
||||
case 2: // 已取消
|
||||
ElNotification.info({
|
||||
id: `${Date.now()}`,
|
||||
title: '会议取消通知',
|
||||
message: `会议号为【${data.meeting.number}】的会议已被取消!`,
|
||||
});
|
||||
break;
|
||||
|
||||
case 3: // 已结束
|
||||
ElNotification.info({
|
||||
id: `${Date.now()}`,
|
||||
title: '会议结束通知',
|
||||
message: `会议号为【${data.meeting.number}】的会议已结束!`,
|
||||
});
|
||||
|
||||
// window.video.src = undefined;
|
||||
// window.showVideo.value = false;
|
||||
// window.videoViewRoot.style.display = 'none';
|
||||
break;
|
||||
}
|
||||
|
||||
// 拉取会议列表
|
||||
emitter.emit('fetchConfence');
|
||||
});
|
||||
};
|
||||
842
src/views/consultation/components/meetingView.vue
Normal file
842
src/views/consultation/components/meetingView.vue
Normal file
@ -0,0 +1,842 @@
|
||||
<template>
|
||||
<DraggableResizableVue v-if="props.modelValue"
|
||||
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 ref="mainContentRef" class="conference-box">
|
||||
<!-- 会议主题 -->
|
||||
<div v-show="displaySubject" class="subject">
|
||||
<h3 v-if="!editSubject" @click="editSubject = true">
|
||||
{{ displaySubject }} ({{ activeMeetingConfig?.meeting.number }})
|
||||
</h3>
|
||||
<el-input v-else v-model="subject" autofocus allow-clear @blur="updateSubject"/>
|
||||
</div>
|
||||
|
||||
<div class="top-box">
|
||||
<!-- 当前正在讲话 -->
|
||||
<el-row justify="space-around">
|
||||
<el-tag v-for="name in speakingMemberNames" :key="name" bordered color="green" >{{ name }}</el-tag>
|
||||
</el-row>
|
||||
|
||||
<!-- 共享者 -->
|
||||
<el-tag v-if="activeMeetingConfig?.sharingMember" bordered color="orange">
|
||||
{{ activeMeetingConfig?.sharingMember?.alias}}正在共享屏幕
|
||||
</el-tag>
|
||||
</div>
|
||||
|
||||
<!-- 会议音视频 -->
|
||||
<audio id="conference_audio" ref="audioRef" :volume="80 / 100" :muted="audioOuputStatus !== 0" autoplay controls hidden />
|
||||
<video id="conference_video" ref="videoRef" autoplay playsinline :hidden="!showVideo" class="video"/>
|
||||
|
||||
<!-- 广播相关(此处借用 video 标签获取对应的流) -->
|
||||
<video id="conference_localvideo" ref="localVideoRef" autoplay playsinline :hidden="!showlocalVideo" class="video" />
|
||||
<img v-if="isMicEnable" v-show="activeMeetingConfig?.broadcast" @click="stopBroadcast" src="@/assets/images/webPuc/svgs/img_broadcast.svg" alt="">
|
||||
<el-upload
|
||||
v-show="false"
|
||||
:show-file-list="false"
|
||||
draggable
|
||||
accept=".mp4"
|
||||
:multiple="false"
|
||||
:auto-upload="false"
|
||||
:show-remove-button="false"
|
||||
:show-cancel-button="false"
|
||||
@change="onFileChanged"
|
||||
@before-upload="beforeUpload"
|
||||
/>
|
||||
|
||||
<video id="conference_pushVideo" ref="pushVideoRef" autoplay playsinline :hidden="!showPushlVideo" class="video"/>
|
||||
|
||||
<audio ref="fileAudioRef" autoplay :hidden="true" />
|
||||
|
||||
<el-row class="buttonContainer" justify="space-around">
|
||||
<!-- 锁定 -->
|
||||
|
||||
<el-button circle @click="lockConference">
|
||||
<el-icon size="20px" v-if="activeMeetingConfig?.lockStatus == 1"><Lock/></el-icon>
|
||||
<el-icon size="20px" v-else ><Unlock/></el-icon>
|
||||
</el-button>
|
||||
|
||||
<!-- 麦克风 -->
|
||||
<el-button circle @click="setMuteMic">
|
||||
<img v-if="isMicEnable" src="@/assets/images/webPuc/svgs/microphone.svg" alt="">
|
||||
<img v-else src="@/assets/images/webPuc/svgs/microphone_mute.svg" alt="">
|
||||
</el-button>
|
||||
|
||||
<el-popover title="选择麦克风" trigger="click" position="bottom-end">
|
||||
<template #reference>
|
||||
<el-icon style="align-self: flex-end" color="#000"><ArrowDown/></el-icon>
|
||||
</template>
|
||||
<MicPop @changeDevice="changeDevice" />
|
||||
</el-popover>
|
||||
|
||||
<!-- 扬声器 -->
|
||||
<el-button circle @click="setMuteEar">
|
||||
<img v-if="audioOuputStatus == 1" src="@/assets/images/webPuc/svgs/earpiece.svg" alt="">
|
||||
<img v-else src="@/assets/images/webPuc/svgs/trumpet_mute.svg" alt="">
|
||||
</el-button>
|
||||
<el-popover title="选择扬声器" trigger="click" position="bottom-end">
|
||||
<template #reference>
|
||||
<el-icon style="align-self: flex-end" color="#000"><ArrowDown/></el-icon>
|
||||
</template>
|
||||
<!-- <AudioPop @changeDevice="changeDevice" /> -->
|
||||
</el-popover>
|
||||
|
||||
<!-- 摄像头 -->
|
||||
<el-button circle @click="setCamera">
|
||||
<img v-if="userInfo?.camera_status === CAMERA_STATUS_OPEN" src="@/assets/images/webPuc/svgs/camera.svg" alt="">
|
||||
<img v-else src="@/assets/images/webPuc/svgs/camera_mute.svg" alt="">
|
||||
</el-button>
|
||||
<el-popover title="选择摄像头" trigger="click" position="bottom-end">
|
||||
<template #reference>
|
||||
<el-icon style="align-self: flex-end" color="#000"><ArrowDown/></el-icon>
|
||||
</template>
|
||||
<!-- <CameraPop @changeDevice="changeDevice" /> -->
|
||||
</el-popover>
|
||||
|
||||
<!-- 屏幕共享 -->
|
||||
<el-button circle @click="setShareScreenStatus(1)">
|
||||
<img src="@/assets/images/webPuc/svgs/share_video.svg" alt="">
|
||||
</el-button>
|
||||
|
||||
<!-- 成员管理 -->
|
||||
<el-button circle @click="showMembers">
|
||||
<el-icon color="#84888E" size="20"><Auatar/></el-icon>
|
||||
</el-button>
|
||||
|
||||
<!-- 语音激励 -->
|
||||
<el-button circle @click="setVoiceStimulation()">
|
||||
<img v-if="activeMeetingConfig?.voiceStimulation" src="@/assets/images/webPuc/svgs/icon_embrave.svg" alt="">
|
||||
<img v-else src="@/assets/images/webPuc/svgs/conference_icom_cancel_voice_stimulation.svg" alt="">
|
||||
</el-button>
|
||||
|
||||
<!-- 布局 -->
|
||||
<!-- <LaoutType @setConfernceLayoutType="setConfernceLayoutType" /> -->
|
||||
|
||||
<!-- 画面抓取-截图 -->
|
||||
<el-button circle @click="startScreenshot">
|
||||
<el-icon color="#84888E" size="20"><Scissor/></el-icon>
|
||||
</el-button>
|
||||
|
||||
<!-- 视频广播 -->
|
||||
<el-button circle @click="broadcastAction">
|
||||
<img src="@/assets/images/webPuc/svgs/icon_broadcast.svg" alt="">
|
||||
</el-button>
|
||||
|
||||
<!-- 录屏 -->
|
||||
<el-button circle @click="!isRecording ? mediaRecorder.start() : mediaRecorder.stop()">
|
||||
<el-icon v-if="!isRecording"><Camera/></el-icon>
|
||||
<el-icon v-else style="color: red"><Videopause/></el-icon>
|
||||
</el-button>
|
||||
|
||||
<!-- 结束共享 -->
|
||||
<el-button v-if="activeMeetingConfig?.sharingMember?.basedata_id === userInfo?.basedata_id"
|
||||
type="danger"
|
||||
shape="round"
|
||||
status="danger"
|
||||
@click="setShareScreenStatus(0)">
|
||||
结束共享
|
||||
</el-button>
|
||||
|
||||
<template v-else>
|
||||
<!-- 结束会议 v-if="globalStore.IS_CURRENT_MEETING_OWNER"-->
|
||||
<el-button
|
||||
type="danger"
|
||||
shape="round"
|
||||
@click="endConference">
|
||||
结束会议
|
||||
</el-button>
|
||||
|
||||
<!-- 退出会议 -->
|
||||
<!-- <el-button
|
||||
v-else
|
||||
type="danger"
|
||||
shape="round"
|
||||
@click="hangupCall"
|
||||
>退出会议</el-button
|
||||
> -->
|
||||
</template>
|
||||
</el-row>
|
||||
|
||||
<!-- 关闭按钮 -->
|
||||
<el-button class="close" type="primary" icon="Close" circle @click="close"></el-button>
|
||||
</div>
|
||||
|
||||
<!-- 成员管理面板 暂时未改-->
|
||||
<!-- <MemberMangerModal ref="memberRef" /> -->
|
||||
</DraggableResizableVue>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import MicPop from './micPop.vue';
|
||||
import emitter from "@/utils/eventBus.js";
|
||||
// import MemberMangerModal from '../memberMangerModal/index.vue';
|
||||
import { nextTick, onMounted,defineEmits,defineExpose,onUnmounted,defineProps, ref, getCurrentInstance, computed, watch } from 'vue';
|
||||
import useConferenceControlModule, { CONFERENCE_ROLE_NORMAL, CONFERENCE_ROLE_HOST, MICROPHONE_STATUS_NO, MICROPHONE_STATUS_OPEN, MICROPHONE_STATUS_CLOSE, MUTE_STATUS_Y, PROHIBITION_STATUS_Y, PROHIBITION_STATUS_N, MUTE_STATUS_N, CAMERA_STATUS_NO, CAMERA_STATUS_OPEN, CAMERA_STATUS_CLOSE } from '@/views/consultation/sdk/conferenceControl';
|
||||
import { ElMessage} from "element-plus";
|
||||
import DraggableResizableVue from 'draggable-resizable-vue3';
|
||||
import useConferenceModule from '@/views/consultation/sdk/conference';
|
||||
import useConfernceControlEvent from './js/useConfernceControlEvent';
|
||||
import { useStore } from "vuex";
|
||||
const props = defineProps({
|
||||
modelValue:Boolean
|
||||
})
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const store = useStore();
|
||||
const element = ref({
|
||||
x: 500,
|
||||
y: -600,
|
||||
width: 500,
|
||||
height: 500,
|
||||
isActive: false,
|
||||
});
|
||||
const globalStore = store.state.useGlobalStore;
|
||||
// 音视频会议-会控管理模块
|
||||
const confernceControlModule = useConferenceControlModule();
|
||||
|
||||
// 赋初始值,后续可更改
|
||||
const subject = ref('');
|
||||
const editSubject = ref(false);
|
||||
|
||||
const confernceModule = useConferenceModule();
|
||||
const memberRef = ref();
|
||||
const jsonData = ref('');
|
||||
/* 录制 */
|
||||
const isRecording = ref(false); // 是否录制中
|
||||
|
||||
const locked = ref(false);
|
||||
|
||||
const audioRef = ref();
|
||||
// remote stream video
|
||||
// 远端流和Video。
|
||||
const videoRef = ref();
|
||||
const showVideo = ref(false);
|
||||
|
||||
// local stream video
|
||||
// 本端Video
|
||||
const localVideoRef = ref();
|
||||
// 显示本端流
|
||||
const showlocalVideo = ref(false);
|
||||
|
||||
// 由于视频推送的是静态文件流,不是实时流,播放方式与其他呼叫的流不一样,所以不建议放到同一个video 播放。
|
||||
// 推送Video push video
|
||||
const pushVideoRef = ref();
|
||||
|
||||
const fileAudioRef = ref();
|
||||
// 显示推送流 show push video
|
||||
const showPushlVideo = ref(false);
|
||||
|
||||
// 本端视频流 local video stream
|
||||
let localVideoStream;
|
||||
// 远端视频流 remote video stream
|
||||
let remoteVideoStream;
|
||||
|
||||
// 是否 半双工用一个Video来显示远端流和本地流。 true 为 共用一个video。 false 为 2个video,分别显示。
|
||||
const useOneVideoShow = true;
|
||||
const mainContentRef = ref(null);
|
||||
const speakers = ref([]);
|
||||
const selfGranted = ref(false);
|
||||
|
||||
const displaySubject = computed(() => {
|
||||
const text = globalStore.activeMeetingConfig?.subject || '';
|
||||
subject.value = text;
|
||||
return text;
|
||||
});
|
||||
|
||||
// 0=关闭,1=打开,2=无扬声器
|
||||
const audioOuputStatus = computed(() => {
|
||||
return globalStore.activeMeetingConfig?.audioOuputStatus;
|
||||
});
|
||||
|
||||
const activeMeetingConfig = computed(() => {
|
||||
return globalStore.activeMeetingConfig;
|
||||
});
|
||||
|
||||
const audioInputList = computed(() => {
|
||||
return globalStore.activeMeetingConfig.audioInputList;
|
||||
});
|
||||
|
||||
const userInfo = computed(() => {
|
||||
const user_basedata_id = localStorage.getItem('user_basedata_id');
|
||||
return globalStore.activeMeetingConfig?.members.find(
|
||||
(v) => v.basedata_id === user_basedata_id
|
||||
);
|
||||
});
|
||||
|
||||
const isMicEnable = computed(() => {
|
||||
return (
|
||||
userInfo.value?.prohibition_status === PROHIBITION_STATUS_N &&
|
||||
userInfo.value?.mute_status === MUTE_STATUS_N
|
||||
);
|
||||
});
|
||||
|
||||
// 正在讲话成员姓名
|
||||
const speakingMemberNames = computed(() => {
|
||||
return globalStore.activeMeetingConfig ? globalStore.activeMeetingConfig.members.filter((v) => {
|
||||
if (
|
||||
v.microphone_status === MICROPHONE_STATUS_CLOSE ||
|
||||
v.mute_status === MUTE_STATUS_Y ||
|
||||
v.prohibition_status === PROHIBITION_STATUS_Y ) {
|
||||
return false;
|
||||
}
|
||||
return v.speaking_state === 1;
|
||||
}).map((item) => item.nick || item.alias || item.number) : [];
|
||||
});
|
||||
|
||||
// 更新会议主题
|
||||
const updateSubject = () => {
|
||||
editSubject.value = false;
|
||||
const { members, meeting, callId, subject: oldSubject } = globalStore.activeMeetingConfig;
|
||||
if (subject.value === oldSubject) return;
|
||||
confernceControlModule.updateConferenceSubject({ guid: meeting?.guid, basedata_id: meeting?.basedata_id,subject: subject.value }).then((resp) => {
|
||||
if (resp.result === 0) {
|
||||
} else {
|
||||
subject.value = oldSubject;
|
||||
ElMessage.error(jsonData.value['errorCode'][resp.result]);
|
||||
}
|
||||
}).catch((error) => {
|
||||
subject.value = oldSubject;
|
||||
ElMessage.warning('操作失败');
|
||||
});
|
||||
};
|
||||
|
||||
const onRecordStart = () => {
|
||||
isRecording.value = true;
|
||||
};
|
||||
|
||||
const onRecordStop = () => {
|
||||
isRecording.value = false;
|
||||
};
|
||||
|
||||
const mediaRecorder = confernceControlModule.createMediaRecorder({
|
||||
onstart: onRecordStart,
|
||||
onstop: onRecordStop,
|
||||
});
|
||||
|
||||
// 开关语音激励
|
||||
const setVoiceStimulation = () => {
|
||||
if (activeMeetingConfig.value) {
|
||||
confernceControlModule.setVoiceStimulation(!activeMeetingConfig.value.voiceStimulation);
|
||||
ElMessage.success( !activeMeetingConfig.value.voiceStimulation ? '语音激励已开启' : '语音激励已关闭');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 上传文件方法
|
||||
*/
|
||||
const onFileChanged = (fileList, fileItem ) => {
|
||||
console.log('broadcast onFileChanged fileList', fileList);
|
||||
console.log('broadcast onFileChanged fileItem', fileItem);
|
||||
const fileName = fileItem.name;
|
||||
if (fileName.indexOf('.mp4') === -1) {
|
||||
ElMessage.error('选择上传文件,MP4格式!');
|
||||
return;
|
||||
}
|
||||
|
||||
localVideoRef.value.src = window.URL.createObjectURL(fileItem.file);
|
||||
fileList.length = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* 上传前校验
|
||||
* @param file
|
||||
*/
|
||||
const beforeUpload = (file) => {
|
||||
console.log('beforeUpload', file);
|
||||
const isLt5M = file.size / 1024 / 1024 < 200;
|
||||
// <boolean | File>
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!isLt5M) {
|
||||
ElMessage.error('上传文件大小不能超过20MB!');
|
||||
reject(new Error('上传文件超过限制大小!'));
|
||||
} else if (file.name.indexOf('.mp4') === -1) {
|
||||
ElMessage.error('选择上传文件,MP4格式!');
|
||||
reject(new Error('选择上传文件,MP4格式!'));
|
||||
} else {
|
||||
resolve(true);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 触发文件上传
|
||||
const pickFile = () => {
|
||||
// const span: HTMLSpanElement | undefined = mainContentRef.value.querySelector('.arco-upload');
|
||||
// span.click();
|
||||
};
|
||||
|
||||
// 广播文件选择
|
||||
const broadcastAction = () => {
|
||||
pickFile();
|
||||
};
|
||||
|
||||
// 停止广播
|
||||
const stopBroadcast = () => {
|
||||
console.log('broadcast stop');
|
||||
localVideoRef.value.pause();
|
||||
localVideoRef.value.src = null;
|
||||
confernceControlModule.stopBroadcast();
|
||||
};
|
||||
|
||||
// 视频广播入口
|
||||
const onLocalVideoCanPlay = () => {
|
||||
console.log('broadcast onLocalVideoCanPlay');
|
||||
const videoStream = localVideoRef.value.captureStream();
|
||||
confernceControlModule.broadcastVideo(videoStream);
|
||||
};
|
||||
|
||||
const onLocalVideoPlayEnd = () => {
|
||||
console.log('broadcast onLocalVideoPlayEnd');
|
||||
};
|
||||
|
||||
const addBroadcastVideoListener = () => {
|
||||
if (localVideoRef.value) {
|
||||
console.log('addBroadcastVideoListener trigger...');
|
||||
localVideoRef.value.addEventListener('canplay', onLocalVideoCanPlay);
|
||||
localVideoRef.value.addEventListener('ended', onLocalVideoPlayEnd);
|
||||
}
|
||||
};
|
||||
|
||||
const removeBroadcastVideoListener = () => {
|
||||
if (localVideoRef.value) {
|
||||
console.log('addBroadcastVideoListener trigger...');
|
||||
localVideoRef.value.removeEventListener(onLocalVideoCanPlay);
|
||||
localVideoRef.value.removeEventListener(onLocalVideoPlayEnd);
|
||||
}
|
||||
};
|
||||
|
||||
// 截屏操作
|
||||
const startScreenshot = () => {
|
||||
confernceControlModule.startScreenshot({
|
||||
videoSelector: '#conference_video',
|
||||
fileName: '截图',
|
||||
});
|
||||
};
|
||||
|
||||
// 锁定会议室
|
||||
const lockConference = () => {
|
||||
const { members, meeting, callId } = globalStore.activeMeetingConfig;
|
||||
|
||||
confernceControlModule
|
||||
.lockConference({
|
||||
guid: meeting?.guid,
|
||||
basedata_id: meeting?.basedata_id,
|
||||
lock: Number(!locked.value),
|
||||
})
|
||||
.then((res) => {
|
||||
if (res.result === 0) {
|
||||
locked.value = !locked.value;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 切换设备
|
||||
const changeDevice = ({ deviceId, type }) => {
|
||||
const { members, meeting, callId } = globalStore.activeMeetingConfig;
|
||||
|
||||
switch (type) {
|
||||
case 'AudioInput': // 麦克风
|
||||
confernceControlModule
|
||||
.changeAudioInputDevice({ deviceId, call_id: callId })
|
||||
.then((res) => {
|
||||
if (res.result === 0) {
|
||||
ElMessage.success('修改成功');
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log('audioInput err ', err);
|
||||
});
|
||||
break;
|
||||
|
||||
case 'AudioOutput': // 喇叭
|
||||
confernceControlModule.changeAudioOutputDevice({
|
||||
audioOuputSelector: '#conference_audio',
|
||||
deviceId,
|
||||
});
|
||||
break;
|
||||
|
||||
case 'VideoInput': // 摄像头
|
||||
confernceControlModule
|
||||
.changeVideoInputDevice({ deviceId, call_id: callId })
|
||||
.then((res) => {
|
||||
if (res.result === 0) {
|
||||
ElMessage.success('修改成功');
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log('videoInput err ', err);
|
||||
});
|
||||
break;
|
||||
|
||||
// no default
|
||||
}
|
||||
};
|
||||
|
||||
// 重置当前会议信息
|
||||
const resetCurrentConferenceInfo = () => {
|
||||
memberRef.value.closeAllModal();
|
||||
window.calling_conference = undefined;
|
||||
globalStore.setShowConfencePanel(false);
|
||||
globalStore.setActiveConfig(null);
|
||||
};
|
||||
|
||||
// 离开会议
|
||||
const hangupCall = () => {
|
||||
if (!globalStore.activeMeetingConfig) return;
|
||||
|
||||
const { callId } = globalStore.activeMeetingConfig;
|
||||
|
||||
confernceModule
|
||||
.hangupCall({
|
||||
call_id: callId,
|
||||
})
|
||||
.then((resp) => {
|
||||
console.log('hangupCall resp ', resp);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log('hangupCall error ', error);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
// 结束会议
|
||||
const endConference = () => {
|
||||
console.log(confernceModule.endConference,'=====confernceModule');
|
||||
const { meeting, callId } = globalStore.activeMeetingConfig;
|
||||
confernceModule.endConference({
|
||||
guid: meeting?.guid,
|
||||
basedata_id: meeting?.basedata_id,
|
||||
call_id: callId,
|
||||
})
|
||||
.then((resp) => {
|
||||
emit('update:modelValue',false)
|
||||
console.log('结束会议 ', resp);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log('结束会议失败 ', error);
|
||||
});
|
||||
};
|
||||
// 展示会议成员
|
||||
const showMembers = () => {
|
||||
memberRef.value.visible = true;
|
||||
};
|
||||
|
||||
// 通用方法
|
||||
const muteAction = (mute , type = 'audio') => {
|
||||
const user_basedata_id = sessionStorage.getItem('user_basedata_id');
|
||||
|
||||
let setMuteAction = () => {};
|
||||
|
||||
const { members, meeting, callId } = globalStore.activeMeetingConfig;
|
||||
const member = members.find((v) => v.basedata_id === user_basedata_id);
|
||||
|
||||
const params = {
|
||||
guid: meeting?.guid,
|
||||
basedata_id: meeting?.basedata_id,
|
||||
call_id: callId,
|
||||
member,
|
||||
};
|
||||
|
||||
switch (type) {
|
||||
case 'mic':
|
||||
setMuteAction = confernceControlModule.setMemberMute;
|
||||
params.mute = mute;
|
||||
break;
|
||||
|
||||
case 'audio':
|
||||
break;
|
||||
|
||||
case 'video':
|
||||
setMuteAction = confernceControlModule.setMemberCamera;
|
||||
params.camera_status = mute;
|
||||
break;
|
||||
|
||||
// no default
|
||||
}
|
||||
|
||||
return setMuteAction(params);
|
||||
};
|
||||
|
||||
// 开关自己的麦克风
|
||||
const setMuteMic = () => {
|
||||
// 被禁言就不能自己控制麦克风
|
||||
if (userInfo.value.prohibition_status === 1) {
|
||||
ElMessage.warning('您已被禁言');
|
||||
return;
|
||||
}
|
||||
|
||||
const status = !userInfo.value.mute_status;
|
||||
|
||||
muteAction(Number("status"), 'mic').then((resp) => {
|
||||
console.log('mute mic result ', resp);
|
||||
});
|
||||
};
|
||||
|
||||
// 开关自己的扬声器
|
||||
const setMuteEar = () => {
|
||||
if (!audioInputList.value.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { callId } = globalStore.activeMeetingConfig;
|
||||
|
||||
confernceControlModule.setMuteCall({
|
||||
call_id: callId,
|
||||
is_mute: !!audioOuputStatus.value,
|
||||
});
|
||||
};
|
||||
|
||||
// 开关自己的摄像头
|
||||
const setCamera = () => {
|
||||
const status = !userInfo.value.camera_status;
|
||||
muteAction(Number(status), 'video').then((resp) => {
|
||||
console.log('mute camera result ', resp);
|
||||
});
|
||||
};
|
||||
const setAudio = (stream) => {
|
||||
if (audioRef.value) {
|
||||
audioRef.value.srcObject = stream;
|
||||
} else {
|
||||
nextTick(() => {
|
||||
setAudio(stream);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const close = () => {
|
||||
hangupCall();
|
||||
emit('update:modelValue',false)
|
||||
};
|
||||
|
||||
// 设置屏幕共享状态
|
||||
const setShareScreenStatus = (sharing_status) => {
|
||||
const user_basedata_id = sessionStorage.getItem('user_basedata_id');
|
||||
const { members, meeting, callId } = globalStore.activeMeetingConfig;
|
||||
|
||||
confernceControlModule
|
||||
.setShareScreenStatus({
|
||||
sharing_status,
|
||||
call_id: callId,
|
||||
guid: meeting?.guid,
|
||||
basedata_id: meeting?.basedata_id,
|
||||
member: members.find((v) => v.basedata_id === user_basedata_id),
|
||||
})
|
||||
.then((resp) => {
|
||||
if (resp.result === 0) {
|
||||
} else {
|
||||
ElMessage.error(jsonData.value['errorCode'][resp.result]);
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
ElMessage.error(jsonData.value['errorCode'][error.result]);
|
||||
});
|
||||
};
|
||||
|
||||
// 注册音视频流事件
|
||||
const onMediaStream = (data) => {
|
||||
const { call_id, stream, type } = data;
|
||||
// 音频流
|
||||
if (type === 'audio_dst') {
|
||||
setAudio(stream);
|
||||
} else if (type === 'video_dst') {
|
||||
// 视频流
|
||||
console.log('onMediaStream,is video play =', !videoRef.value.paused);
|
||||
|
||||
// 单画面
|
||||
if (useOneVideoShow) {
|
||||
showVideo.value = true;
|
||||
videoRef.value.srcObject = stream;
|
||||
} else {
|
||||
showVideo.value = true;
|
||||
showlocalVideo.value = false;
|
||||
videoRef.value.srcObject = stream;
|
||||
}
|
||||
|
||||
remoteVideoStream = stream;
|
||||
} else if (type === 'video_src') {
|
||||
if (useOneVideoShow) {
|
||||
// 一般全双工显示远端的画面。 拥有话权的时候,才显示自己的画面,所以流赋值到话权模块处理。
|
||||
showVideo.value = false;
|
||||
} else {
|
||||
showlocalVideo.value = true;
|
||||
showVideo.value = false;
|
||||
localVideoRef.value.srcObject = stream;
|
||||
}
|
||||
|
||||
localVideoStream = stream;
|
||||
}
|
||||
};
|
||||
|
||||
// 挂断呼叫时
|
||||
const onHangup = (data) => {
|
||||
// 若挂断的不是当前进行中的会议,则不执行后续操作
|
||||
if (data.call_id !== globalStore.activeMeetingConfig?.callId) return;
|
||||
resetCurrentConferenceInfo();
|
||||
speakers.value.length = 0;
|
||||
selfGranted.value = false;
|
||||
showVideo.value = false;
|
||||
showlocalVideo.value = false;
|
||||
try {
|
||||
videoRef.value.pause();
|
||||
} catch (error) {
|
||||
console.error('on hangup,video stop error', error);
|
||||
}
|
||||
|
||||
videoRef.value.srcObject = null;
|
||||
};
|
||||
|
||||
// 切换布局类型
|
||||
const setConfernceLayoutType = (type) => {
|
||||
const { members, meeting, callId } = globalStore.activeMeetingConfig;
|
||||
|
||||
confernceControlModule
|
||||
.setLayoutType({
|
||||
guid: meeting?.guid,
|
||||
basedata_id: meeting?.basedata_id,
|
||||
call_id: callId,
|
||||
layout_type: type,
|
||||
})
|
||||
.then((res) => {
|
||||
if (res.result === 0) {
|
||||
}
|
||||
});
|
||||
};
|
||||
// 在视频的元数据加载后执行
|
||||
const addVideoOnLoadedMetadataEvnt = () => {
|
||||
nextTick(() => {
|
||||
videoRef.value.onloadedmetadata = () => {
|
||||
// 初始化录屏对象
|
||||
mediaRecorder.init(videoRef.value, audioRef.value);
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
// 设备列表变化时
|
||||
const onDeviceListChange = (mediaDeviceInfo) => {
|
||||
if (!activeMeetingConfig.value?.audioInputDeviceId) {
|
||||
nextTick(() => {
|
||||
confernceControlModule.changeAudioOutputDevice({
|
||||
audioOuputSelector: '#conference_audio',
|
||||
deviceId: mediaDeviceInfo.audioOutputList[0]?.deviceId,
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
onMounted(()=>{
|
||||
console.log(globalStore,'=====0000000000000');
|
||||
jsonData.value = require('./zh_CN.json');
|
||||
// 注册媒体流事件
|
||||
emitter.on('onMediaStream',onMediaStream)
|
||||
// 注册会议挂断事件
|
||||
emitter.on('onHangup',onHangup)
|
||||
|
||||
// 注册会控管理相关事件
|
||||
useConfernceControlEvent({
|
||||
onDeviceListChange,
|
||||
});
|
||||
// 注册视频广播事件
|
||||
addBroadcastVideoListener();
|
||||
|
||||
// 初始化录屏媒体对象
|
||||
addVideoOnLoadedMetadataEvnt();
|
||||
});
|
||||
|
||||
|
||||
onUnmounted(() => {
|
||||
emitter.off('onMediaStream');
|
||||
emitter.off('onHangup');
|
||||
removeBroadcastVideoListener();
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.container {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
margin: 2px;
|
||||
background: rgb(28,32,41);
|
||||
border: 2px dashed #e8e8e8;
|
||||
border-radius: 16px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.video {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: scale-down;
|
||||
}
|
||||
|
||||
.buttonContainer {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 96%;
|
||||
margin: 8px;
|
||||
padding: 5px 3px;
|
||||
background: #fff;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.speaks {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.wave {
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
.close {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
.subject {
|
||||
position: absolute;
|
||||
top: -53px;
|
||||
padding: 0 5px;
|
||||
color: #ffff;
|
||||
background: #1c2029;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.subject .arco-input-wrapper {
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
||||
.icon_broadcast {
|
||||
fill: #fff;
|
||||
}
|
||||
|
||||
.img_broadcast {
|
||||
position: absolute;
|
||||
right: 20px;
|
||||
bottom: 60px;
|
||||
}
|
||||
|
||||
.top-box {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
}
|
||||
|
||||
.top-box .arco-tag {
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
::v-deep .el-button.is-circle{
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
</style>
|
||||
50
src/views/consultation/components/micPop.vue
Normal file
50
src/views/consultation/components/micPop.vue
Normal file
@ -0,0 +1,50 @@
|
||||
<template>
|
||||
<div class="menuPopContent">
|
||||
<!-- <a-list
|
||||
:data="activeMeetingConfig.audioInputList"
|
||||
hoverable size="small" :bordered="false" :split="false"
|
||||
class="micPopList">
|
||||
<a-list-item v-for="(item, index) in activeMeetingConfig.audioInputList" :key="index"
|
||||
@click="changeDevice(item.deviceId)">
|
||||
<div class="micPopListItem">
|
||||
<span class="micType">
|
||||
{{ item.label }}
|
||||
</span>
|
||||
<icon-check class="icon-checked" v-show="item.deviceId === activeMeetingConfig.audioInputDeviceId" />
|
||||
</div>
|
||||
</a-list-item>
|
||||
</a-list> -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed } from "vue";
|
||||
import { useStore } from "vuex";
|
||||
const store = useStore();
|
||||
const emit = defineEmits(['changeDevice']);
|
||||
|
||||
const globalStore = store.state.useGlobalStore;
|
||||
|
||||
const activeMeetingConfig = computed(() => {
|
||||
return globalStore.activeMeetingConfig;
|
||||
});
|
||||
|
||||
const changeDevice = (deviceId) => {
|
||||
emit('changeDevice', {
|
||||
deviceId,
|
||||
type: 'AudioInput',
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.micPopListItem{
|
||||
cursor: pointer;
|
||||
}
|
||||
.icon-checked {
|
||||
color: rgba(12, 162, 255, 1);
|
||||
vertical-align: sub;
|
||||
margin-left: 20px;
|
||||
font-size: 20px;
|
||||
}
|
||||
</style>
|
||||
3203
src/views/consultation/components/zh_CN.json
Normal file
3203
src/views/consultation/components/zh_CN.json
Normal file
File diff suppressed because it is too large
Load Diff
359
src/views/consultation/demo.vue
Normal file
359
src/views/consultation/demo.vue
Normal file
@ -0,0 +1,359 @@
|
||||
|
||||
<template>
|
||||
<div class="meeting-box">
|
||||
<ul class="meun">
|
||||
<li class="item">
|
||||
<span>会商</span>
|
||||
<span class="edg"></span>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="list-box">
|
||||
<div class="tr">
|
||||
<el-popover placement="bottom" :width="80" trigger="click">
|
||||
<template #reference>
|
||||
<el-button>新增</el-button>
|
||||
</template>
|
||||
<div class="lh30 f12 pointer" v-for="item in LIST_DATA" :key="item.value" @click="chooseItem(item)">
|
||||
{{item.label}}
|
||||
</div>
|
||||
</el-popover>
|
||||
</div>
|
||||
<div class="list">
|
||||
<!-- 调度台、临时组 -->
|
||||
<el-collapse v-model="activeName">
|
||||
<el-collapse-item v-for="item in LIST_DATA_TREE" :key="item.value" :title="item.label" :name="item.label">
|
||||
<ul>
|
||||
<li class="lh30" v-for="(it,idx) in meetList" :key="idx" @click="joinMeeting(it)">{{ it.subject }}</li>
|
||||
</ul>
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cnt"></div>
|
||||
</div>
|
||||
<!-- 音视频会议 -->
|
||||
<AudioAndVoice v-model="showDailog" v-if="showDailog" @save="saveData"></AudioAndVoice>
|
||||
<!-- 音视频会议窗口 -->
|
||||
<MeetingView v-model="openMeeting" v-if="openMeeting" ></MeetingView>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import useConfernceEvent from './components/js/useConfernceEvent';
|
||||
import { ElMessage,ElMessageBox,ElNotification } from "element-plus";
|
||||
import AudioAndVoice from './components/audioAndVoice.vue'
|
||||
import MeetingView from './components/meetingView.vue'
|
||||
import { computed , nextTick, onMounted, ref} from 'vue';
|
||||
import { useStore } from "vuex";
|
||||
const store = useStore();
|
||||
const showDailog = ref(false)
|
||||
const openMeeting = ref(false) //打开会议
|
||||
const activeName = ref('音视频会议')
|
||||
const tempModalType = ref('') //点击类型
|
||||
const jsonData = ref('');
|
||||
const meetList = ref([
|
||||
{
|
||||
"basedata_id": "8180e3882a0c27f4d3ba998b3dc95c0d280d8e2e7a9d53e4ac36c7ade2c76653",
|
||||
"guid": "2a7931e2-5fe6-493b-b918-cd4f220ee62e",
|
||||
"number": "908479232",
|
||||
"puc_id": "00001",
|
||||
"realm": "puc.com",
|
||||
"subject": "sgxtcs 预约的会议",
|
||||
"type": 1,
|
||||
"duration": 30,
|
||||
"pre_alarm_time": 1,
|
||||
"remark": "",
|
||||
"start_date_time": "2025-12-11T02:01:19Z",
|
||||
"end_date_time": "2025-12-11T02:01:19Z",
|
||||
"create_date_time": "2025-12-11T02:01:19Z",
|
||||
"status": 0,
|
||||
"lock": 0,
|
||||
"emergency_flag": 0,
|
||||
"appointment": "2025-12-10T14:57:24Z",
|
||||
"creator": {
|
||||
"basedata_id": "8180e3882a0c27f4cc200f7987d695ff3ce5274244ba3974e0064423dfe70f71",
|
||||
"guid": "Dispatcher::sgxtcs@puc.com",
|
||||
"alias": "sgxtcs",
|
||||
"nick": "sgxtcs",
|
||||
"role": 2
|
||||
},
|
||||
"members": [
|
||||
{
|
||||
"basedata_id": "8180e3882a0c27f4cc200f7987d695ff3ce5274244ba3974e0064423dfe70f71",
|
||||
"guid": "Dispatcher::sgxtcs@puc.com",
|
||||
"alias": "sgxtcs",
|
||||
"nick": "sgxtcs",
|
||||
"role": 2,
|
||||
"joined": 0,
|
||||
"speaking_state": 0,
|
||||
"member_state": 0,
|
||||
"microphone_status": 1,
|
||||
"camera_status": 1,
|
||||
"prohibition_status": 0,
|
||||
"mute_status": 0,
|
||||
"device_type": 0,
|
||||
"terminal_model": "",
|
||||
"full_duplex": 1,
|
||||
"raise_hand": 0,
|
||||
"removed_flag": 0,
|
||||
"join_date_time": "",
|
||||
"left_date_time": "",
|
||||
"member_remark": "",
|
||||
"e2ee_flag": 0,
|
||||
"emergency_flag": 0,
|
||||
"voice_value": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
])
|
||||
|
||||
|
||||
// 临时组类别列表
|
||||
const LIST_DATA = computed(() => {
|
||||
return [
|
||||
// 音视频会议
|
||||
{
|
||||
label: '音视频会议',
|
||||
value: 8,
|
||||
// component: AdvancedConference,
|
||||
isOpenRoot: ref(false),
|
||||
isLoading: ref(false),
|
||||
},
|
||||
// 拨号入会
|
||||
{
|
||||
label: '进入会议',
|
||||
value: 9,
|
||||
component: null,
|
||||
isOpenRoot: ref(false),
|
||||
isLoading: ref(false),
|
||||
},
|
||||
// 快速会议
|
||||
{
|
||||
label: '快速会议',
|
||||
value: 10,
|
||||
component: null,
|
||||
isOpenRoot: ref(false),
|
||||
isLoading: ref(false),
|
||||
},
|
||||
];
|
||||
});
|
||||
|
||||
const LIST_DATA_TREE = computed(() => {
|
||||
return LIST_DATA.value.filter((v) => ![9, 10].includes(v.value));
|
||||
});
|
||||
|
||||
|
||||
function chooseItem (val) {
|
||||
tempModalType.value = val.value;
|
||||
switch(val.label){
|
||||
case '音视频会议':
|
||||
showDailog.value = true
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function saveData (data){
|
||||
switch(tempModalType.value){
|
||||
case 8:
|
||||
console.info('-----------音视频会议-----------');
|
||||
conferenceActionSDK(data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* create or update conference
|
||||
*/
|
||||
const conferenceActionSDK = async (record ) => {
|
||||
// 创建会议
|
||||
const createRes = await lemon.conference.createConference({
|
||||
subject: record.subject, //主题
|
||||
type: 1, //会议类型 0=即时会议,1=预约会议
|
||||
emergency_flag: 0, //会议紧急标识 0 = 非紧急会议,1 = 紧急会议
|
||||
duration: Number(record.duration), //预计时长 (分钟)
|
||||
pre_alarm_time: record.alarm, //提前通知时间(分钟)
|
||||
remark: record.remark,
|
||||
appointment: '2025-12-10T14:57:24Z', // start_date 和 start_time 对应的 UTC 时间
|
||||
members:record.members,
|
||||
});
|
||||
if (createRes.result === 0) {
|
||||
ElMessage.success(jsonData.value['data']['conference.book.result.ok']);
|
||||
fetchConferences()
|
||||
} else {
|
||||
ElMessage.error(jsonData.value['errorCode'][createRes?.result]);
|
||||
}
|
||||
};
|
||||
|
||||
// 加入会议
|
||||
const joinMeeting = (it) =>{
|
||||
ElMessageBox.confirm('确定开始会议?','提示',{
|
||||
confirmButtonText:'确定',
|
||||
cancelButtonText:'取消',
|
||||
type:'warning',
|
||||
}).then(res=>{
|
||||
openMeeting.value = true;
|
||||
nextTick(()=>{
|
||||
let params = {
|
||||
"number": it.number,
|
||||
"nick": it.subject,
|
||||
"mute_status": it.status,
|
||||
"microphone_status": 1,
|
||||
"camera_status": 1
|
||||
}
|
||||
lemon.conference.enterConferenceByNumber(params).then(res=> {
|
||||
console.log(res,'加入会议......');
|
||||
}).catch(err=> {
|
||||
console.log(err,' 加入会议失败......');
|
||||
})
|
||||
})
|
||||
}).catch(()=>{
|
||||
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
// 获取会议
|
||||
const fetchConferences = () =>{
|
||||
lemon.conference.fetchConferences().then(res=> {
|
||||
console.log(res.conferenceList,'获取会议');
|
||||
meetList.value = res.conferenceList;
|
||||
activeName.value = '音视频会议'
|
||||
}).catch(err=> {})
|
||||
}
|
||||
|
||||
|
||||
const Init = () => {
|
||||
let token = window.localStorage.getItem("rhToken");
|
||||
if (!token) {
|
||||
let userInfo = {
|
||||
username: "linzhigongan2",
|
||||
password: "linzhigongan2",
|
||||
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);
|
||||
getLoginAccountInfo();
|
||||
fetchConferences()
|
||||
// 注册会议管理相关事件
|
||||
useConfernceEvent()
|
||||
});
|
||||
} else {
|
||||
ConnectWebsocket(token);
|
||||
}
|
||||
};
|
||||
|
||||
const ConnectWebsocket = (token) => {
|
||||
lemon.login.reConnectWebsocket({
|
||||
username: "linzhigongan2",
|
||||
realm: "puc.com",
|
||||
webpucUrl: "https://89.40.9.95:16888",
|
||||
token: token
|
||||
}).then((resp) => {
|
||||
if(resp.result != 0){
|
||||
ElMessage.error(jsonData.value['errorCode'][resp.result]);
|
||||
exsit()
|
||||
}else{
|
||||
getLoginAccountInfo()
|
||||
fetchConferences()
|
||||
// 注册会议管理相关事件
|
||||
useConfernceEvent()
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const getLoginAccountInfo =() =>{
|
||||
lemon.login.getLoginAccountInfo().then(res => {
|
||||
let info = JSON.stringify(res.account_info)
|
||||
window.localStorage.setItem("rhInfo",info);
|
||||
window.localStorage.setItem("user_basedata_id",res.account_info.basedata_id);
|
||||
}).catch(err => {
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
const exsit = () =>{
|
||||
lemon.login.logout().then(res=> {
|
||||
|
||||
}).catch(err=> {
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
function changeCooll () {
|
||||
|
||||
}
|
||||
|
||||
onMounted(()=>{
|
||||
jsonData.value = require('./components/zh_CN.json');
|
||||
nextTick(()=>{
|
||||
Init();
|
||||
})
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.meeting-box{
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(15,30,52,1);
|
||||
.meun{
|
||||
width: 80px;
|
||||
height: 100%;
|
||||
background: rgba(0, 40, 108,1);
|
||||
border-right: 1px solid #0072ff;
|
||||
.item{
|
||||
width: 80px;
|
||||
height: 74px;
|
||||
line-height: 74px;
|
||||
background: linear-gradient(90deg,rgba(12,162,255,1) 0% , rgba(162, 247, 255,0) 100%);
|
||||
filter: drop-shadow(0 16px 16px rgba(0,0,0,.25));
|
||||
text-align: center;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
.edg{
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 4px;
|
||||
height: 100%;
|
||||
border-top-right-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
background-color:rgba(172,249,255,1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
.list-box{
|
||||
width: 200px;
|
||||
background: rgba(0, 53, 123,1);
|
||||
padding: 4px 10px;
|
||||
box-sizing: border-box;
|
||||
.list{
|
||||
margin-top: 10px;
|
||||
height: calc(100% - 30px);
|
||||
}
|
||||
}
|
||||
.cnt{
|
||||
flex: 1 0 0;
|
||||
}
|
||||
}
|
||||
::v-deep .el-collapse-item__header{
|
||||
background: transparent;
|
||||
color: #fff;
|
||||
border-bottom: 1px solid #2e4b6e;
|
||||
}
|
||||
::v-deep .el-collapse-item__wrap{
|
||||
background-color: transparent;
|
||||
border-bottom: none;
|
||||
}
|
||||
::v-deep .el-collapse-item__content{
|
||||
color: #fff;
|
||||
}
|
||||
::v-deep .el-collapse{
|
||||
border-top: none;
|
||||
border-bottom: none;
|
||||
}
|
||||
</style>
|
||||
351
src/views/consultation/draggerAble.vue
Normal file
351
src/views/consultation/draggerAble.vue
Normal 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 callback,include 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>
|
||||
46
src/views/consultation/hooks/axios.ts
Normal file
46
src/views/consultation/hooks/axios.ts
Normal file
@ -0,0 +1,46 @@
|
||||
import axios from 'axios';
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
import { showErrorMsgDesc } from '@/hooks/error';
|
||||
|
||||
const $axios = axios.create();
|
||||
|
||||
$axios.defaults.timeout = 50000;
|
||||
let options = {};
|
||||
$axios.interceptors.request.use(
|
||||
(config) => {
|
||||
options = config;
|
||||
// const { headers } = config;
|
||||
|
||||
return config;
|
||||
},
|
||||
(error) => {
|
||||
console.info('request error', error);
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
$axios.interceptors.response.use(
|
||||
(response) => {
|
||||
const { result, desc, msg } = response.data;
|
||||
// @ts-ignore
|
||||
const { isCatch } = options;
|
||||
if (isCatch) return response.data;
|
||||
if (result && result !== 0) {
|
||||
showErrorMsgDesc(result, desc || msg);
|
||||
return {};
|
||||
}
|
||||
return response.data;
|
||||
},
|
||||
(error) => {
|
||||
// eslint-disable-next-line consistent-return
|
||||
return new Promise((resolve, reject) => {
|
||||
// @ts-ignore
|
||||
const { isCatch } = options;
|
||||
console.info('response error', JSON.stringify(error), isCatch);
|
||||
if (isCatch) return reject(error);
|
||||
Message.error(error.message);
|
||||
resolve('');
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
export default $axios;
|
||||
27
src/views/consultation/hooks/callingNotification.js
Normal file
27
src/views/consultation/hooks/callingNotification.js
Normal file
@ -0,0 +1,27 @@
|
||||
import { h } from 'vue';
|
||||
import { ElNotification} from "element-plus";
|
||||
import { IconClose } from "element-plus"
|
||||
import Content from '@/views/consultation/components/content.vue';
|
||||
import Footer from '@/views/consultation/components/footer.vue';
|
||||
import { formatShowNameFin } from '@/views/consultation/utils/format-show-name';
|
||||
|
||||
export default function handleCallingNotification(propsObj) {
|
||||
const { callInfo, text } = propsObj;
|
||||
const { calling, answer = 'answer', hangUp = 'hang up' } = text;
|
||||
ElNotification.info({
|
||||
id: callInfo.call_id,
|
||||
position: 'bottom-left',
|
||||
closable: true,
|
||||
closeIconElement: () => {
|
||||
return h(IconClose);
|
||||
},
|
||||
title: () =>h(Content, {
|
||||
callInfo,
|
||||
calling,
|
||||
getName: formatShowNameFin( callInfo.caller_alias, callInfo.caller_number),
|
||||
}),
|
||||
message: () =>h(Footer, { callInfo, answer, hangUp }),
|
||||
duration: 0,
|
||||
style: { width: '260px' },
|
||||
});
|
||||
}
|
||||
57
src/views/consultation/hooks/error.ts
Normal file
57
src/views/consultation/hooks/error.ts
Normal file
@ -0,0 +1,57 @@
|
||||
import { h } from 'vue';
|
||||
import { Notification } from '@arco-design/web-vue';
|
||||
import { Random } from 'mockjs';
|
||||
import { $i18n } from '@/locale';
|
||||
|
||||
/*
|
||||
* 使用示例:
|
||||
* import { showErrorMsgDesc } from '@/hooks/error';
|
||||
* showErrorMsgDesc('2101006', 'HBP service run error', '出错了');
|
||||
* showErrorMsgDesc('2101006', 'HBP service run error');
|
||||
* showErrorMsgDesc('2101006');
|
||||
* showErrorMsgDesc('77778888');
|
||||
* */
|
||||
|
||||
export const showErrorMsgDesc = (code = '', desc = '', msg = '') => {
|
||||
const id = `note_msg_${Random.guid()}`;
|
||||
const existI18nMsg = $i18n.global.t(`errorCode.${code}`);
|
||||
Notification.error({
|
||||
id,
|
||||
class: 'notification-center-message',
|
||||
closable: true,
|
||||
duration: 15000,
|
||||
showIcon: true,
|
||||
style: {
|
||||
'width': '500px',
|
||||
'padding': '10px 20px',
|
||||
'align-items': 'center',
|
||||
},
|
||||
title: () => {
|
||||
const titTxt = msg || existI18nMsg;
|
||||
return h('span', [
|
||||
h('span', titTxt),
|
||||
h(
|
||||
'a',
|
||||
{
|
||||
style: {
|
||||
'margin-left': '16px',
|
||||
'font-size': '14px',
|
||||
'color': '#f53f3f',
|
||||
},
|
||||
onClick: () => {
|
||||
Notification.error({
|
||||
id,
|
||||
title: titTxt,
|
||||
content: desc,
|
||||
});
|
||||
},
|
||||
},
|
||||
desc ? $i18n.global.t('error.code.detail') : ''
|
||||
),
|
||||
]);
|
||||
},
|
||||
content: () => h('div'),
|
||||
});
|
||||
};
|
||||
|
||||
export default null;
|
||||
16
src/views/consultation/hooks/loading.ts
Normal file
16
src/views/consultation/hooks/loading.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import { ref } from 'vue';
|
||||
|
||||
export default function useLoading(initValue = false) {
|
||||
const loading = ref(initValue);
|
||||
const setLoading = (value: boolean) => {
|
||||
loading.value = value;
|
||||
};
|
||||
const toggle = () => {
|
||||
loading.value = !loading.value;
|
||||
};
|
||||
return {
|
||||
loading,
|
||||
setLoading,
|
||||
toggle,
|
||||
};
|
||||
}
|
||||
21
src/views/consultation/hooks/locale.ts
Normal file
21
src/views/consultation/hooks/locale.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import { computed } from 'vue';
|
||||
import { $i18n, loadLocaleMessages, setI18nLanguage } from '@/locale';
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
|
||||
export default function useLocale() {
|
||||
const currentLocale = computed(() => {
|
||||
return $i18n.global.locale;
|
||||
});
|
||||
const changeLocale = (value: string) => {
|
||||
localStorage.setItem('arco-locale-webPuc', value);
|
||||
loadLocaleMessages($i18n, value).then(() => {
|
||||
setI18nLanguage($i18n, value);
|
||||
|
||||
Message.success($i18n.global.t('navbar.action.locale'));
|
||||
});
|
||||
};
|
||||
return {
|
||||
currentLocale,
|
||||
changeLocale,
|
||||
};
|
||||
}
|
||||
138
src/views/consultation/hooks/recorder.js
Normal file
138
src/views/consultation/hooks/recorder.js
Normal file
@ -0,0 +1,138 @@
|
||||
import { ref } from 'vue';
|
||||
import { ElMessage } from "element-plus";
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
export default function useRecorder() {
|
||||
const data = ref([]);
|
||||
const recording = ref(false)
|
||||
const paused = ref(false);
|
||||
let mediaRecorder;
|
||||
const localMicAudioStream = ref(null);
|
||||
const audioStream = ref(null);
|
||||
|
||||
// 下载视频
|
||||
const download = () => {
|
||||
const blob = new Blob(data.value, { type: 'video/webm' });
|
||||
const url = URL.createObjectURL(blob);
|
||||
const a = document.createElement('a');
|
||||
const name = dayjs().format('YYYYMMDDHHmmss');
|
||||
a.href = url;
|
||||
a.download = `video${name}.webm`;
|
||||
a.click();
|
||||
window.URL.revokeObjectURL(url);
|
||||
data.value = [];
|
||||
};
|
||||
const muteRecorderAudio = (type, isMute) => {
|
||||
let stream = null;
|
||||
if (type === 'mic') {
|
||||
stream = localMicAudioStream.value;
|
||||
}
|
||||
if (type === 'audio') {
|
||||
stream = audioStream.value;
|
||||
}
|
||||
if (stream) {
|
||||
stream.getAudioTracks().forEach((track) => {
|
||||
track.enabled = !isMute;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 初始化:创建mediaRecorder对象,获取音视频流,处理混流,定义mediaRecorder相关事件操作
|
||||
const init = async (video, audio) => {
|
||||
let mediaStream = await video.captureStream();
|
||||
if (audio) {
|
||||
const [videoCaptureStream, audioCaptureStream, localMicStream] =
|
||||
await Promise.all([
|
||||
video.captureStream(),
|
||||
audio.captureStream(),
|
||||
navigator.mediaDevices.getUserMedia({ audio: true }),
|
||||
]);
|
||||
localMicAudioStream.value = localMicStream;
|
||||
audioStream.value = audioCaptureStream;
|
||||
const videoTrack = videoCaptureStream.getVideoTracks()[0];
|
||||
/* 音频输入输出混流 */
|
||||
const audioContext = new AudioContext();
|
||||
if (localMicStream.getAudioTracks().length && audioCaptureStream.getAudioTracks().length) {
|
||||
const localMicStreamNode = audioContext.createMediaStreamSource(localMicStream);
|
||||
const audioCaptureStreamNode = audioContext.createMediaStreamSource(audioCaptureStream);
|
||||
const mixedAudio = audioContext.createMediaStreamDestination();
|
||||
localMicStreamNode.connect(mixedAudio);
|
||||
audioCaptureStreamNode.connect(mixedAudio);
|
||||
const mixedAudioTrack = mixedAudio.stream.getTracks()[0];
|
||||
mediaStream = new MediaStream([mixedAudioTrack, videoTrack]);
|
||||
}
|
||||
}
|
||||
mediaRecorder = await new MediaRecorder(mediaStream, {
|
||||
mimeType: 'video/webm;codecs=vp8',
|
||||
});
|
||||
|
||||
mediaRecorder.ondataavailable = (e) => {
|
||||
if (e?.data?.size > 0) {
|
||||
data.value.push(e.data);
|
||||
}
|
||||
};
|
||||
mediaRecorder.onstart = () => {
|
||||
startTime = Date.now();
|
||||
recording.value = true;
|
||||
paused.value = false;
|
||||
ElMessage.success('开始录制');
|
||||
};
|
||||
mediaRecorder.onstop = () => {
|
||||
endTime = Date.now();
|
||||
recording.value = false;
|
||||
paused.value = true;
|
||||
ElMessage.success('结束录制');
|
||||
download();
|
||||
};
|
||||
};
|
||||
|
||||
// 异常处理
|
||||
const validateMedia = (cbName, cb) => {
|
||||
if (mediaRecorder && mediaRecorder[cbName]) {
|
||||
cb();
|
||||
} else {
|
||||
ElMessage.warning('录屏失败,未获取到媒体流');
|
||||
}
|
||||
};
|
||||
// 开始录制
|
||||
const start = () => {
|
||||
mediaRecorder.start(100);
|
||||
};
|
||||
// 暂停
|
||||
const pause = () => {
|
||||
paused.value = true;
|
||||
mediaRecorder.pause();
|
||||
};
|
||||
|
||||
// 继续
|
||||
const resume = () => {
|
||||
paused.value = false;
|
||||
mediaRecorder.resume();
|
||||
};
|
||||
|
||||
// 结束录制
|
||||
const stop = () => {
|
||||
mediaRecorder.stop();
|
||||
};
|
||||
|
||||
// 录制控制
|
||||
const handleRecordVideo = async () => {
|
||||
if (!recording.value) {
|
||||
validateMedia('start', start);
|
||||
} else {
|
||||
validateMedia('stop', stop);
|
||||
}
|
||||
};
|
||||
return {
|
||||
init,
|
||||
start,
|
||||
pause,
|
||||
resume,
|
||||
stop,
|
||||
download,
|
||||
handleRecordVideo,
|
||||
recording,
|
||||
paused,
|
||||
muteRecorderAudio,
|
||||
};
|
||||
}
|
||||
149
src/views/consultation/hooks/static.ts
Normal file
149
src/views/consultation/hooks/static.ts
Normal file
@ -0,0 +1,149 @@
|
||||
/* eslint-disable no-bitwise */
|
||||
|
||||
import { DEVICE_STATE, DEVICE_TYPE } from '@/utils/contants';
|
||||
|
||||
/* 获取执法记录仪数据 如果以后基础数据变多,可以考虑用pinia在页面加载是进行初始化控制 */
|
||||
const rvmTypes = [];
|
||||
|
||||
export default function useStaticData() {
|
||||
/**
|
||||
* 获取设备状态值方法(第三版本)以v2逻辑为主,整合v1业务逻辑
|
||||
* @param deviceInfo
|
||||
* @returns
|
||||
*/
|
||||
const getDeviceStatusNumberV3 = (deviceInfo): number => {
|
||||
const {
|
||||
status,
|
||||
conference_guid,
|
||||
number,
|
||||
device_type,
|
||||
basedata_id,
|
||||
latitude,
|
||||
longitude,
|
||||
terminal_model,
|
||||
} = deviceInfo;
|
||||
|
||||
let deviceState = 0;
|
||||
// console.debug('getDeviceStatusNumberV3--->', deviceInfo);
|
||||
const number_type = window.lemon.basedata.getNumberType(basedata_id);
|
||||
/* 会议类型 */
|
||||
if (conference_guid) return DEVICE_STATE.DEVICE_STATE_TYPE_CONFERENCE;
|
||||
/* PSTN电话 */
|
||||
if (number_type === DEVICE_STATE.DEVICE_STATE_TYPE_EXTERNAL)
|
||||
return DEVICE_STATE.DEVICE_STATE_TYPE_EXTERNAL;
|
||||
|
||||
/* 设备类型 */
|
||||
if (
|
||||
number_type === window.lemon.NUMBER_TYPE.INDIVIDUAL ||
|
||||
number_type === window.lemon.NUMBER_TYPE.ROIP_INDIVIDUAL
|
||||
) {
|
||||
// 判断是否是执法记录仪
|
||||
const isRvm = rvmTypes.includes(terminal_model);
|
||||
// 判断是否是摄像头
|
||||
const isCamera = device_type === DEVICE_TYPE.DEVICE_TYPE_CAMERA;
|
||||
// 设备号码类型
|
||||
// 执法记录仪
|
||||
if (isRvm) {
|
||||
deviceState |= DEVICE_STATE.DEVICE_STATE_TYPE_RVM;
|
||||
}
|
||||
// 摄像头
|
||||
else if (isCamera) {
|
||||
deviceState |= DEVICE_STATE.DEVICE_STATE_TYPE_CAMERA;
|
||||
} else {
|
||||
deviceState |= number_type;
|
||||
}
|
||||
|
||||
// 设备号码状态(是否遥晕遥毙..)
|
||||
switch (status?.lock_state) {
|
||||
case 0: // 遥醒
|
||||
deviceState |= DEVICE_STATE.DEVICE_STATE_LOCK_REVICE;
|
||||
break;
|
||||
case 1: // 遥晕
|
||||
deviceState |= DEVICE_STATE.DEVICE_STATE_LOCK_STUN;
|
||||
break;
|
||||
case 3: // 遥毙
|
||||
deviceState |= DEVICE_STATE.DEVICE_STATE_LOCK_KILL;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
/* 在线状态 */
|
||||
// 摄像头设备
|
||||
if (isCamera) {
|
||||
if (status?.online === 1) {
|
||||
// 根据经纬度数据确认是否上报GPS数据
|
||||
deviceState |=
|
||||
latitude !== 0 || longitude !== 0
|
||||
? DEVICE_STATE.DEVICE_STATE_GPS_REPORT_Y
|
||||
: DEVICE_STATE.DEVICE_STATE_GPS_REPORT_N;
|
||||
// 上线状态
|
||||
deviceState |= DEVICE_STATE.DEVICE_STATE_ONLINE_ALL;
|
||||
} else {
|
||||
deviceState |= DEVICE_STATE.DEVICE_STATE_ONLINE_NULL;
|
||||
}
|
||||
}
|
||||
// 多模设备
|
||||
else if (
|
||||
number_type === DEVICE_STATE.DEVICE_STATE_TYPE_ROIP_GROUP ||
|
||||
number_type === DEVICE_STATE.DEVICE_STATE_TYPE_ROIP_INDIVIDUAL
|
||||
) {
|
||||
// 窄带在线
|
||||
if (status.narrowband === window.lemon.ONLINE_STATE.ON) {
|
||||
deviceState |= DEVICE_STATE.DEVICE_STATE_ONLINE_NARROW;
|
||||
}
|
||||
// 宽带在线
|
||||
if (status.broadband === window.lemon.ONLINE_STATE.ON) {
|
||||
deviceState |= DEVICE_STATE.DEVICE_STATE_ONLINE_BROAD;
|
||||
}
|
||||
}
|
||||
// 单模设备 || 执法记录仪
|
||||
else if (
|
||||
number_type === DEVICE_STATE.DEVICE_STATE_TYPE_INDIVIDUAL ||
|
||||
number_type === DEVICE_STATE.DEVICE_STATE_TYPE_GROUP ||
|
||||
isRvm
|
||||
) {
|
||||
// 单模只要有一个模式在线就可以认为是在线了
|
||||
if (
|
||||
status?.narrowband === window.lemon.ONLINE_STATE.ON ||
|
||||
status?.broadband === window.lemon.ONLINE_STATE.ON
|
||||
) {
|
||||
deviceState |= DEVICE_STATE.DEVICE_STATE_ONLINE_ALL;
|
||||
}
|
||||
}
|
||||
|
||||
// 订阅
|
||||
if (deviceInfo.is_subscribe === 1) {
|
||||
deviceState |= DEVICE_STATE.DEVICE_STATE_SUBSCRIBE_Y;
|
||||
}
|
||||
|
||||
// console.debug(
|
||||
// 'getDeviceStatusNumberV3--->',
|
||||
// number,
|
||||
// deviceState.toString(2)
|
||||
// );
|
||||
return deviceState;
|
||||
}
|
||||
|
||||
/* 组类型 */
|
||||
if (
|
||||
number_type === window.lemon.NUMBER_TYPE.GROUP ||
|
||||
number_type === window.lemon.NUMBER_TYPE.ROIP_GROUP
|
||||
) {
|
||||
// roip组在线图标
|
||||
if (number_type === 23) {
|
||||
return DEVICE_STATE.DEVICE_STATE_TYPE_ROIP_GROUP;
|
||||
}
|
||||
// 全呼组类型图标
|
||||
if (number_type === 3) {
|
||||
return DEVICE_STATE.DEVICE_STATE_TYPE_ALL_CALL;
|
||||
}
|
||||
// 其他组类型暂时返回默认组图标
|
||||
return DEVICE_STATE.DEVICE_STATE_TYPE_GROUP;
|
||||
}
|
||||
return deviceState;
|
||||
};
|
||||
|
||||
return {
|
||||
getDeviceStatusNumberV3,
|
||||
};
|
||||
}
|
||||
@ -0,0 +1,5 @@
|
||||
<template>
|
||||
<div>list</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup></script>
|
||||
390
src/views/consultation/memberMangerModal/components/UserItem.vue
Normal file
390
src/views/consultation/memberMangerModal/components/UserItem.vue
Normal file
@ -0,0 +1,390 @@
|
||||
<template lang="pug">
|
||||
div(
|
||||
:class="{user_item: true, user_item_active, [`user_item_${props.index}`]: true}"
|
||||
@mouseenter="mouseEnterItem(props.index)"
|
||||
@mouseleave="mouseLeaveItem"
|
||||
)
|
||||
|
||||
.user_item_info
|
||||
tableColAvatar(:style='{width: "36px", height: "36px"}' :name="''" :record="props.userInfo")
|
||||
div.user_item_info_name
|
||||
.name {{ getName(props.userInfo) }}
|
||||
.type(v-if="getUserType") {{ getUserType }}
|
||||
|
||||
div(
|
||||
v-if="props.meetingType === 'noMeet' && userInfo.member_state === CONFERENCE_MEMBER_STATE_CALLING"
|
||||
style="color: rgba(12, 162, 255, 1);"
|
||||
) {{ $t('conference.control.calling') }}
|
||||
|
||||
div
|
||||
.user_item_opration(v-if="props.meetingType === 'meeting'")
|
||||
div.user_mask()
|
||||
div.icon_box
|
||||
WebPucSvgIcon(
|
||||
v-show="userInfo.microphone_status !== MICROPHONE_STATUS_NO"
|
||||
:name="isMicEnable ? 'microphone' : 'microphone_mute'")
|
||||
WebPucSvgIcon(
|
||||
v-show="userInfo.camera_status !== CAMERA_STATUS_NO"
|
||||
:name="userInfo.camera_status === CAMERA_STATUS_OPEN ? 'camera' : 'camera_mute'")
|
||||
|
||||
a-dropdown(
|
||||
v-if="globalStore.IS_CURRENT_MEETING_OWNER"
|
||||
@select="(val) => reliveSelect(val)"
|
||||
:popup-max-height="false"
|
||||
v-model:popup-visible="reliveVisible"
|
||||
position='br'
|
||||
trigger="hover"
|
||||
)
|
||||
a-button {{ $t('meeting.modal.release_text') }}
|
||||
icon-down
|
||||
template(#content)
|
||||
a-doption(
|
||||
v-for="item in getReliveList"
|
||||
:value="item.value"
|
||||
:key="item.value") {{ item.label }}
|
||||
|
||||
a-dropdown(
|
||||
@select="(val) => controlSelect(val)"
|
||||
:popup-max-height="false"
|
||||
v-model:popup-visible="controlVisible"
|
||||
trigger="hover"
|
||||
position='br')
|
||||
a-button {{ $t('meeting.modal.control_text') }}
|
||||
icon-down
|
||||
template(#content)
|
||||
a-doption(
|
||||
v-for="item in getControlList"
|
||||
:value="item.value"
|
||||
:disabled="item.disabled"
|
||||
:key="item.value") {{ item.label }}
|
||||
|
||||
.user_item_opration(v-if="props.meetingType === 'noMeet'")
|
||||
div.user_mask()
|
||||
a-dropdown(
|
||||
@select="(val) => controlSelect(val)"
|
||||
:popup-max-height="false"
|
||||
v-model:popup-visible="reliveVisible"
|
||||
position='br'
|
||||
trigger="hover"
|
||||
)
|
||||
a-button {{ $t('report.tab.call') }}
|
||||
icon-down
|
||||
template(#content)
|
||||
a-doption(
|
||||
v-for="item in getNoMeetOperate"
|
||||
:value="item.value"
|
||||
:key="item.value") {{ item.label }}
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import tableColAvatar from '@/views/webPuc/org/components/tableColAvatarByNumType.vue';
|
||||
import { computed, ref, watch } from 'vue';
|
||||
import { formatShowNameFin } from '@/views/consultation/utils/format-show-name';
|
||||
import { $t } from '@/locale';
|
||||
import { useGlobalStore } from '@/store';
|
||||
import {
|
||||
MICROPHONE_STATUS_NO,
|
||||
MICROPHONE_STATUS_OPEN,
|
||||
MICROPHONE_STATUS_CLOSE,
|
||||
MUTE_STATUS_Y,
|
||||
MUTE_STATUS_N,
|
||||
CAMERA_STATUS_NO,
|
||||
CAMERA_STATUS_OPEN,
|
||||
CAMERA_STATUS_CLOSE,
|
||||
CONFERENCE_MEMBER_STATE_CALLING,
|
||||
PROHIBITION_STATUS_N,
|
||||
} from '@/views/consultation/sdk/conferenceControl';
|
||||
|
||||
const globalStore = useGlobalStore();
|
||||
|
||||
const props = defineProps({
|
||||
meetingType: {
|
||||
type: String,
|
||||
default: 'meeting',
|
||||
},
|
||||
userInfo: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
index: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
currentIndex: {
|
||||
type: Number,
|
||||
default: -1,
|
||||
},
|
||||
isShowType: {
|
||||
// 是否显示人员类型
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
// eslint-disable-next-line vue/prop-name-casing
|
||||
dispatcher_account: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
});
|
||||
|
||||
const reliveVisible = ref(false);
|
||||
const controlVisible = ref(false);
|
||||
|
||||
const isMicEnable = computed(() => {
|
||||
return (
|
||||
props.userInfo.prohibition_status === PROHIBITION_STATUS_N &&
|
||||
props.userInfo.mute_status === MUTE_STATUS_N
|
||||
);
|
||||
});
|
||||
|
||||
const emit = defineEmits([
|
||||
'changeCurrentIndex',
|
||||
'controlSelect',
|
||||
'reliveSelect',
|
||||
]);
|
||||
|
||||
// 获取资源名称\
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const getName = (record: Record<string, any>) => {
|
||||
const rolemap = {
|
||||
0: 'conference.role.common', // 参会者
|
||||
1: 'conference.role.host', // 主持人(仅用户或硬件终端)
|
||||
2: 'conference.role.creator', // 组织者(仅创建人)
|
||||
};
|
||||
|
||||
let type = '';
|
||||
|
||||
if (props.meetingType === 'meeting') {
|
||||
type = $t(rolemap[record.role]);
|
||||
}
|
||||
|
||||
return formatShowNameFin(record.nick || record.alias, type);
|
||||
};
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const getUserType = computed(() => {
|
||||
let personType: any = '';
|
||||
if (props.userInfo.basedata_id === sessionStorage.getItem('basedata_id')) {
|
||||
personType = $t('meeting.modal.personType');
|
||||
} else {
|
||||
personType = false;
|
||||
}
|
||||
return personType;
|
||||
});
|
||||
|
||||
// 未入会成员-呼叫操作
|
||||
const getNoMeetOperate = computed(() => {
|
||||
return [
|
||||
{
|
||||
value: 'FullDuplexCall',
|
||||
label: $t('conference.fullDuplex_call'),
|
||||
},
|
||||
// {
|
||||
// value: 'HalfDuplexCall',
|
||||
// label: $t('conference.halfDuplex_call'),
|
||||
// },
|
||||
{
|
||||
value: 'AllCall',
|
||||
label: $t('conference.control.allCall'),
|
||||
},
|
||||
];
|
||||
});
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
// 已入会-解除操作
|
||||
const getReliveList = computed(() => {
|
||||
return [
|
||||
{
|
||||
value: 'ReleaseProhibition',
|
||||
label: $t('meeting.modal.release_voice_text'),
|
||||
}, // 解除禁言
|
||||
{
|
||||
value: 'CancelSpeech',
|
||||
label: $t('conference.cancel_speak'),
|
||||
}, // 取消发言
|
||||
{
|
||||
value: 'UnMute',
|
||||
label: $t('conference.control.unmute'),
|
||||
}, // 解除静音
|
||||
{
|
||||
value: 'OpenCamera',
|
||||
label: $t('conference.control.openCamera'),
|
||||
}, // 打开摄像头
|
||||
{
|
||||
value: 'AsMember',
|
||||
label: $t('conference.control.setAsMember'),
|
||||
}, // 设置为成员
|
||||
// {
|
||||
// value: 'CancelImage',
|
||||
// label: $t('conference.control.cancel.image'),
|
||||
// },// 取消指定
|
||||
];
|
||||
});
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
// 已入会-管控操作
|
||||
const getControlList = computed(() => {
|
||||
const operations = [
|
||||
{
|
||||
value: 'Prohibition',
|
||||
label: $t('meeting.modal.control_voice_text'),
|
||||
}, // 禁言
|
||||
{
|
||||
value: 'Mute',
|
||||
label: $t('conference.control.muteMember'),
|
||||
}, // 静音
|
||||
{
|
||||
value: 'CloseCamera',
|
||||
label: $t('conference.control.closeCamera'),
|
||||
}, // 关闭摄像头
|
||||
{
|
||||
value: 'AsHost',
|
||||
label: $t('conference.control.setAsHost'),
|
||||
}, // 设置为主席
|
||||
{
|
||||
value: 'Speech',
|
||||
label: $t('conference.control.designatedSpeech'),
|
||||
}, // 指定发言
|
||||
{
|
||||
value: 'ReName',
|
||||
label: $t('conference.control.reName'),
|
||||
}, // 修改昵称
|
||||
{
|
||||
value: 'Remove',
|
||||
label: $t('meeting.modal.control_move_text'),
|
||||
}, // 移除会议
|
||||
// {
|
||||
// value: 'AppointImage',
|
||||
// label: $t('conference.control.appoint.image'),
|
||||
// },// 指定画面
|
||||
];
|
||||
|
||||
return globalStore.IS_CURRENT_MEETING_OWNER
|
||||
? operations
|
||||
: operations.filter((v) => v.value === 'ReName');
|
||||
});
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const activeStatus = computed(() => {
|
||||
return true;
|
||||
});
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const mouseEnterItem = (index: number) => {
|
||||
if (reliveVisible.value || controlVisible.value) {
|
||||
return;
|
||||
}
|
||||
emit('changeCurrentIndex', index);
|
||||
};
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const mouseLeaveItem = () => {
|
||||
if (reliveVisible.value || controlVisible.value) {
|
||||
return;
|
||||
}
|
||||
emit('changeCurrentIndex', -1);
|
||||
};
|
||||
|
||||
// 解除选择
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const reliveSelect = (val) => {
|
||||
emit('reliveSelect', {
|
||||
val,
|
||||
record: props.userInfo,
|
||||
});
|
||||
};
|
||||
|
||||
// 控制选择
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const controlSelect = (val, index) => {
|
||||
emit('controlSelect', {
|
||||
val,
|
||||
record: props.userInfo,
|
||||
});
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.currentIndex,
|
||||
() => {
|
||||
reliveVisible.value = false;
|
||||
controlVisible.value = false;
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.user_item {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 12px 16px;
|
||||
border-bottom: 1px solid #3c4046;
|
||||
|
||||
&.user_item_active {
|
||||
background: #353b43;
|
||||
}
|
||||
|
||||
.user_item_info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.user_item_info_name {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
margin-left: 5px;
|
||||
line-height: 18px;
|
||||
|
||||
.type {
|
||||
min-width: 200px;
|
||||
color: #80848b;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.avatar {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
}
|
||||
}
|
||||
|
||||
.user_item_opration {
|
||||
img {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
cursor: pointer;
|
||||
|
||||
&:nth-child(2) {
|
||||
margin: 0 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.no_meeting_btn {
|
||||
img {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.user_mask {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 10px;
|
||||
background: #353b43;
|
||||
transform: translateY(-50%);
|
||||
|
||||
> button {
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.icon_box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-evenly;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
834
src/views/consultation/memberMangerModal/index.vue
Normal file
834
src/views/consultation/memberMangerModal/index.vue
Normal file
@ -0,0 +1,834 @@
|
||||
<template lang="pug">
|
||||
a-modal(
|
||||
v-model:visible="visible"
|
||||
title-align="start"
|
||||
class="userMangeModal"
|
||||
width="648px"
|
||||
:title="`${$t('meeting.modal.user.title')} (${userList.length})`"
|
||||
popup-container=".arco-layout-content"
|
||||
:mask="false"
|
||||
unmount-on-close
|
||||
draggable
|
||||
@close="closeFn"
|
||||
@open="fetchMemberList")
|
||||
a-space(direction="vertical" fill)
|
||||
a-space(direction="vertical" fill)
|
||||
a-button(@click="invitVisible = true") {{ $t('conference.components.media.footer.defaultBtns.invitingAttendees') }}
|
||||
|
||||
a-tabs(
|
||||
default-active-key="1"
|
||||
class="userMange_tab"
|
||||
v-model:active-key="tabVal")
|
||||
|
||||
a-tab-pane(key="1" :title="`${$t('conference.member.present')} (${meetingMembers.length})`")
|
||||
.user_list
|
||||
user-item(
|
||||
v-for="(item, index) in meetingMembers"
|
||||
:key="`present_${item.basedata_id}`"
|
||||
:userInfo="item"
|
||||
:index="index"
|
||||
:currentIndex="currentIndex"
|
||||
:isShowType="true"
|
||||
meetingType="meeting"
|
||||
@reliveSelect="(params) => meetingControlSelect(params, 0)"
|
||||
@controlSelect="(params) => meetingControlSelect(params, 1)"
|
||||
@changeCurrentIndex="changeCurrentIndex")
|
||||
div.footer_btn
|
||||
a-button.btn(@click="() => setAllMemberProhibition(MICROPHONE_STATUS_OPEN)") {{ $t('conference.control.allBan') }}
|
||||
a-button.btn(@click="() => setAllMemberProhibition(MICROPHONE_STATUS_CLOSE)") {{ $t('conference.control.openAllBan') }}
|
||||
|
||||
a-tab-pane(key="2" :title="`${$t('conference.member.absent')} (${notMeetingMembers.length})`")
|
||||
.user_list
|
||||
user-item(
|
||||
v-for="(item, index) in notMeetingMembers"
|
||||
:key="`absent_${item.basedata_id}`"
|
||||
:userInfo="item"
|
||||
:index="index"
|
||||
:currentIndex="currentIndex"
|
||||
:isShowType="true"
|
||||
meetingType="noMeet"
|
||||
@reliveSelect="(params) => noMeetControlSelect(params, 0)"
|
||||
@controlSelect="(params) => noMeetControlSelect(params, 1)"
|
||||
@changeCurrentIndex="changeCurrentIndex")
|
||||
.user_footer
|
||||
|
||||
|
||||
a-modal(
|
||||
v-model:visible="invitVisible"
|
||||
title-align="start"
|
||||
width="648px"
|
||||
:title="`${$t('conference.components.media.footer.defaultBtns.invitingAttendees')} (${tableData.length})`"
|
||||
:mask="false"
|
||||
popup-container=".arco-layout-content"
|
||||
unmount-on-close
|
||||
@close="onInvitModalClose"
|
||||
@ok="addMember")
|
||||
a-space(fill style="margin-bottom: 10px")
|
||||
a-input-search(v-model="memberNumber")
|
||||
a-button(
|
||||
shape="circle"
|
||||
@click="addMemberByNumber")
|
||||
template(#icon)
|
||||
icon-plus
|
||||
|
||||
a-table(
|
||||
v-model:selectedKeys="selectedKeys"
|
||||
row-key="rowKey"
|
||||
:data="tableData"
|
||||
:columns="rightColumns"
|
||||
:pagination="false"
|
||||
:scroll="{ y: '100%' }"
|
||||
@dragover="(e) => e.preventDefault()"
|
||||
@drop="handleDrop")
|
||||
template(#name="{ record }") {{ record.alias || record.number }}
|
||||
template(#optional="{ record }")
|
||||
icon-close(class="iconClose"
|
||||
@click="() => deleteSelection(record)")
|
||||
|
||||
a-modal(
|
||||
v-model:visible="reNnameVisible"
|
||||
title-align="start"
|
||||
width="648px"
|
||||
:title="`${$t('conference.control.reName')}`"
|
||||
:mask="true"
|
||||
popup-container=".arco-layout-content"
|
||||
unmount-on-close
|
||||
@ok="modifyMemberNickname")
|
||||
<a-input v-model="nickname" :style="{width:'320px'}" allow-clear />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {
|
||||
ref,
|
||||
computed,
|
||||
getCurrentInstance,
|
||||
h,
|
||||
onMounted,
|
||||
onBeforeMount,
|
||||
} from 'vue';
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
import { IconDelete } from '@arco-design/web-vue/es/icon';
|
||||
|
||||
import ResultModal from '@/views/webPuc/resourcesAndGroup/group/components/resultModal.vue';
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
import AddGroup from '@/views/webPuc/resourcesAndGroup/group/components/addGroupNew.vue';
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
import { $t } from '@/locale';
|
||||
import useCallModule from '@/sdk/call';
|
||||
import useConferenceControlModule, {
|
||||
CONFERENCE_ROLE_NORMAL,
|
||||
CONFERENCE_ROLE_HOST,
|
||||
MICROPHONE_STATUS_NO,
|
||||
MICROPHONE_STATUS_OPEN,
|
||||
MICROPHONE_STATUS_CLOSE,
|
||||
MUTE_STATUS_Y,
|
||||
MUTE_STATUS_N,
|
||||
CAMERA_STATUS_NO,
|
||||
CAMERA_STATUS_OPEN,
|
||||
CAMERA_STATUS_CLOSE,
|
||||
} from '@/views/consultation/sdk/conferenceControl';
|
||||
import useConferencModule from '@/views/consultation/sdk/conferenceControl';
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
import UserItem from './components/UserItem.vue';
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
import SearchList from './components/SearchList.vue';
|
||||
import tableColAvatar from '@/views/webPuc/org/components/tableColAvatarByNumType.vue';
|
||||
|
||||
import { useGlobalStore, resourcesStore } from '@/store';
|
||||
|
||||
const globalStore = useGlobalStore();
|
||||
|
||||
const props = defineProps({
|
||||
cptCurrentConference: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
});
|
||||
|
||||
const Modal = getCurrentInstance().appContext.config.globalProperties.$modal;
|
||||
const bus: any = getCurrentInstance().appContext.config.globalProperties.$bus;
|
||||
|
||||
// 新的成员昵称
|
||||
const reNnameVisible = ref(false);
|
||||
const currentMember = ref(null);
|
||||
const nickname = ref('');
|
||||
|
||||
// 会议信息
|
||||
const conference_info = ref<any>({});
|
||||
const visible = ref(false);
|
||||
const invitVisible = ref(false);
|
||||
const currentIndex = ref(-1);
|
||||
const searchCurrentIndex = ref(-1);
|
||||
const searchBoxStatus = ref(false);
|
||||
const searchContent = ref('');
|
||||
const tabVal = ref('1');
|
||||
const searchCollapse = ref(['1', '2']);
|
||||
const tempModalVisible = ref(false);
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const editData = ref<Record<string, any> | undefined>({});
|
||||
/** 临时组modal编辑传入数据 */
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const hideData = ref(['alias', 'number', 'timeInterval', 'autoDelete']);
|
||||
|
||||
const userList = computed(
|
||||
() => globalStore.activeMeetingConfig?.members || []
|
||||
);
|
||||
|
||||
const storeResources = resourcesStore();
|
||||
|
||||
// 入会成员
|
||||
const meetingMembers = computed(() => {
|
||||
return userList.value.filter((v) => v.member_state === 1); // member_state 成员会议中的状态 0=未入会,1=已入会,2=呼叫中
|
||||
});
|
||||
|
||||
// 未入会成员
|
||||
const notMeetingMembers = computed(() => {
|
||||
return userList.value.filter((v) => v.member_state !== 1);
|
||||
});
|
||||
|
||||
const searchMeetingList = ref([]);
|
||||
const searchNoMeetList = ref([]);
|
||||
|
||||
const CALL = useCallModule();
|
||||
|
||||
const conferenceControlModule = useConferenceControlModule();
|
||||
const conferenceModule = useConferencModule();
|
||||
|
||||
// 邀请会议成员相关
|
||||
const addMember = () => {
|
||||
console.log('邀请成员入会 = ', tableData.value);
|
||||
const { members, meeting, callId } = globalStore.activeMeetingConfig;
|
||||
|
||||
conferenceModule
|
||||
.addConferenceMember({
|
||||
guid: meeting?.guid,
|
||||
basedata_id: meeting?.basedata_id,
|
||||
members: tableData.value,
|
||||
})
|
||||
.then((resp) => {
|
||||
if (resp.result === 0) {
|
||||
Message.success($t(`public.use.success`));
|
||||
} else {
|
||||
Message.error($t(`errorCode.${resp.result}`));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const memberNumber = ref('');
|
||||
|
||||
// 拨号添加会议成员
|
||||
const addMemberByNumber = () => {
|
||||
const isError =
|
||||
!memberNumber.value || Number.isNaN(Number(memberNumber.value));
|
||||
|
||||
if (isError) {
|
||||
Message.error($t('common.number.invalid'));
|
||||
return;
|
||||
}
|
||||
|
||||
// 走通用的拖放逻辑
|
||||
storeResources.setActiveResource({
|
||||
number: memberNumber.value,
|
||||
});
|
||||
|
||||
storeResources.setResourceListAuto();
|
||||
|
||||
// 重置数据
|
||||
memberNumber.value = '';
|
||||
};
|
||||
|
||||
const selectedKeys = ref<string[]>([]);
|
||||
|
||||
const tableData = computed<any[]>(() => {
|
||||
const data = storeResources.getResourceList.map((item) => {
|
||||
return {
|
||||
...item,
|
||||
rowKey: item.basedata_id || item.number,
|
||||
};
|
||||
});
|
||||
console.info('table data ', data);
|
||||
return data;
|
||||
});
|
||||
|
||||
const rightColumns = computed<any[]>(() => {
|
||||
const columns: any[] = [
|
||||
{
|
||||
title: `${$t(`groupList.columns.member`)}(${tableData.value.length})`,
|
||||
dataIndex: 'alias',
|
||||
slotName: 'name',
|
||||
align: 'left',
|
||||
width: 250,
|
||||
},
|
||||
];
|
||||
|
||||
let extraColumns: any[] = [];
|
||||
|
||||
const operation: any = {
|
||||
slotName: 'optional',
|
||||
align: 'right',
|
||||
fixed: 'right',
|
||||
width: 100,
|
||||
title: () => {
|
||||
return h(IconDelete, {
|
||||
style: { cursor: 'pointer' },
|
||||
onClick: () => {
|
||||
const newList = storeResources.getResourceList.filter(
|
||||
(item) => item.device_guid === sessionStorage.getItem('user_guid')
|
||||
);
|
||||
storeResources.setResourceList(newList);
|
||||
},
|
||||
});
|
||||
},
|
||||
};
|
||||
return columns.concat(extraColumns, operation);
|
||||
});
|
||||
|
||||
const rowSelection = computed<any>(() => {
|
||||
return {
|
||||
// type: 'checkbox',
|
||||
showCheckedAll: true,
|
||||
};
|
||||
});
|
||||
|
||||
// 穿梭框-右侧-删除选择行事件
|
||||
const deleteSelection = (record: any) => {
|
||||
console.info('deleteSelection', record);
|
||||
// 会议主持人不允许删掉
|
||||
if (record.guid === sessionStorage.getItem('user_guid')) {
|
||||
Message.warning($t('meeting.tip.no_can_del'));
|
||||
} else {
|
||||
// dgna_guid是唯一标识符
|
||||
const filterData = tableData.value.filter((item) => {
|
||||
return item?.rowKey !== record.rowKey;
|
||||
});
|
||||
storeResources.setResourceList(filterData);
|
||||
selectedKeys.value = selectedKeys.value.filter((selected) =>
|
||||
tableData.value.some((data) => data.rowKey === selected)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
// 拖拽
|
||||
const beforeDropdown = (
|
||||
record: Record<string, any>
|
||||
// allRecords: Record<string, any>[]
|
||||
) => {
|
||||
const result = {
|
||||
success: true,
|
||||
message: 'success',
|
||||
formattedData: {},
|
||||
};
|
||||
|
||||
console.info('----sdf->>>>>', record);
|
||||
|
||||
// 错误的数据格式或过滤已有userlist
|
||||
if (
|
||||
!record.guid ||
|
||||
tableData.value?.some((item) => item.guid === record.guid)
|
||||
) {
|
||||
result.success = false;
|
||||
result.message = $t(`${$t('meeting.modal.userExit')}`);
|
||||
return result;
|
||||
}
|
||||
|
||||
result.formattedData = {
|
||||
...record,
|
||||
};
|
||||
return result;
|
||||
};
|
||||
|
||||
// 拖拽置入table事件 dropdown
|
||||
const handleDrop = async () => {
|
||||
const emitResult = beforeDropdown(storeResources.getActiveResource);
|
||||
|
||||
if (!emitResult) {
|
||||
storeResources.setResourceListAuto();
|
||||
} else if (emitResult.success) {
|
||||
if (emitResult.formattedData) {
|
||||
storeResources.setActiveResource(emitResult.formattedData);
|
||||
}
|
||||
storeResources.setResourceListAuto();
|
||||
} else {
|
||||
Message.error(emitResult.message);
|
||||
}
|
||||
};
|
||||
|
||||
// 弹窗关闭时
|
||||
const onInvitModalClose = () => {
|
||||
storeResources.setResourceList([]);
|
||||
};
|
||||
|
||||
// 踢出会议成员
|
||||
const kickoutMember = (record) => {
|
||||
const { members, meeting, callId } = globalStore.activeMeetingConfig;
|
||||
|
||||
conferenceControlModule
|
||||
.kickoutMember({
|
||||
guid: meeting?.guid,
|
||||
basedata_id: meeting?.basedata_id,
|
||||
members: [record],
|
||||
})
|
||||
.then((resp) => {
|
||||
if (resp.result === 0) {
|
||||
Message.success($t('meeting.deleteUser.success'));
|
||||
} else {
|
||||
Message.error($t(`errorCode.${resp.result}`));
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
Message.warning($t('meeting.deleteUser.fail'));
|
||||
});
|
||||
};
|
||||
|
||||
// 呼叫未入会成员
|
||||
const inviteMember = (record) => {
|
||||
const { meeting, callId } = globalStore.activeMeetingConfig;
|
||||
|
||||
conferenceControlModule
|
||||
.inviteMember({
|
||||
guid: meeting?.guid,
|
||||
basedata_id: meeting?.basedata_id,
|
||||
call_id: callId,
|
||||
members: [record],
|
||||
})
|
||||
.then((resp) => {
|
||||
if (resp.result === 0) {
|
||||
Message.success($t(`public.use.success`));
|
||||
} else {
|
||||
Message.warning($t(`errorCode.${resp.result}`));
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
Message.error($t('gis.cross.delResult1'));
|
||||
});
|
||||
};
|
||||
|
||||
// 呼叫全部未入会成员
|
||||
const inviteAllMember = () => {
|
||||
const { meeting, callId } = globalStore.activeMeetingConfig;
|
||||
|
||||
conferenceControlModule
|
||||
.inviteAllMember({
|
||||
guid: meeting?.guid,
|
||||
basedata_id: meeting?.basedata_id,
|
||||
call_id: callId,
|
||||
})
|
||||
.then((resp) => {
|
||||
if (resp.result === 0) {
|
||||
Message.success($t(`public.use.success`));
|
||||
} else {
|
||||
Message.error($t(`errorCode.${resp.result}`));
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
Message.warning($t('gis.cross.delResult1'));
|
||||
});
|
||||
};
|
||||
|
||||
// 修改成员昵称
|
||||
const modifyMemberNickname = () => {
|
||||
if (nickname.value === currentMember.value.nick) return;
|
||||
|
||||
const { members, meeting, callId } = globalStore.activeMeetingConfig;
|
||||
|
||||
conferenceControlModule
|
||||
.modifyMemberNickname({
|
||||
guid: meeting?.guid,
|
||||
basedata_id: meeting?.basedata_id,
|
||||
call_id: callId,
|
||||
member: currentMember.value,
|
||||
nickname: nickname.value,
|
||||
})
|
||||
.then((resp) => {
|
||||
if (resp.result === 0) {
|
||||
nickname.value = '';
|
||||
} else {
|
||||
Message.error($t(`errorCode.${resp.result}`));
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
Message.warning($t('gis.cross.delResult1'));
|
||||
});
|
||||
};
|
||||
|
||||
// 设置会员成员角色
|
||||
const setMemberRole = (role: number) => {
|
||||
const { members, meeting, callId } = globalStore.activeMeetingConfig;
|
||||
|
||||
conferenceControlModule
|
||||
.setMemberRole({
|
||||
guid: meeting?.guid,
|
||||
basedata_id: meeting?.basedata_id,
|
||||
member: currentMember.value,
|
||||
role,
|
||||
})
|
||||
.then((resp) => {
|
||||
if (resp.result === 0) {
|
||||
} else {
|
||||
Message.error($t(`errorCode.${resp.result}`));
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
Message.warning($t('gis.cross.delResult1'));
|
||||
});
|
||||
};
|
||||
|
||||
// 禁言会议成员
|
||||
const setMemberProhibition = (prohibition: number) => {
|
||||
const { members, meeting, callId } = globalStore.activeMeetingConfig;
|
||||
|
||||
conferenceControlModule
|
||||
.setMemberProhibition({
|
||||
guid: meeting?.guid,
|
||||
basedata_id: meeting?.basedata_id,
|
||||
call_id: callId,
|
||||
member: currentMember.value,
|
||||
prohibition,
|
||||
})
|
||||
.then((resp) => {
|
||||
if (resp.result === 0) {
|
||||
} else {
|
||||
Message.error($t(`errorCode.${resp.result}`));
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
Message.warning($t('gis.cross.delResult1'));
|
||||
});
|
||||
};
|
||||
|
||||
// 禁言全部会议成员
|
||||
const setAllMemberProhibition = (prohibition: number) => {
|
||||
const { members, meeting, callId } = globalStore.activeMeetingConfig;
|
||||
|
||||
conferenceControlModule
|
||||
.setAllMemberProhibition({
|
||||
guid: meeting?.guid,
|
||||
basedata_id: meeting?.basedata_id,
|
||||
call_id: callId,
|
||||
prohibition,
|
||||
})
|
||||
.then((resp) => {
|
||||
if (resp.result === 0) {
|
||||
} else {
|
||||
Message.error($t(`errorCode.${resp.result}`));
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
Message.warning($t('gis.cross.delResult1'));
|
||||
});
|
||||
};
|
||||
|
||||
// 静音会议成员
|
||||
const setMemberMute = (mute: number) => {
|
||||
const { members, meeting, callId } = globalStore.activeMeetingConfig;
|
||||
|
||||
conferenceControlModule
|
||||
.setMemberMute({
|
||||
guid: meeting.guid,
|
||||
basedata_id: meeting.basedata_id,
|
||||
call_id: callId,
|
||||
member: currentMember.value,
|
||||
mute,
|
||||
})
|
||||
.then((resp) => {
|
||||
if (resp.result === 0) {
|
||||
} else {
|
||||
Message.error($t(`errorCode.${resp.result}`));
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
Message.warning($t('gis.cross.delResult1'));
|
||||
});
|
||||
};
|
||||
|
||||
// 开关会议成员摄像头
|
||||
const setMemberCamera = (camera_status: number) => {
|
||||
const { members, meeting, callId } = globalStore.activeMeetingConfig;
|
||||
|
||||
conferenceControlModule
|
||||
.setMemberCamera({
|
||||
guid: meeting.guid,
|
||||
basedata_id: meeting.basedata_id,
|
||||
call_id: callId,
|
||||
member: currentMember.value,
|
||||
camera_status,
|
||||
})
|
||||
.then((resp) => {
|
||||
if (resp.result === 0) {
|
||||
} else {
|
||||
Message.error($t(`errorCode.${resp.result}`));
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
Message.warning($t('gis.cross.delResult1'));
|
||||
});
|
||||
};
|
||||
|
||||
// 指定成员发言
|
||||
const assignMemberSpeaker = () => {
|
||||
const { members, meeting, callId } = globalStore.activeMeetingConfig;
|
||||
|
||||
conferenceControlModule
|
||||
.assignMemberSpeaker({
|
||||
guid: meeting?.guid,
|
||||
basedata_id: meeting?.basedata_id,
|
||||
call_id: callId,
|
||||
member: currentMember.value,
|
||||
})
|
||||
.then((resp) => {
|
||||
if (resp.result === 0) {
|
||||
} else {
|
||||
Message.error($t(`errorCode.${resp.result}`));
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
Message.warning($t('gis.cross.delResult1'));
|
||||
});
|
||||
};
|
||||
|
||||
// 取消指定成员发言
|
||||
const cancelMemberSpeak = () => {
|
||||
const { members, meeting, callId } = globalStore.activeMeetingConfig;
|
||||
|
||||
conferenceControlModule
|
||||
.cancelMemberSpeak({
|
||||
guid: meeting?.guid,
|
||||
basedata_id: meeting?.basedata_id,
|
||||
call_id: callId,
|
||||
member: currentMember.value,
|
||||
})
|
||||
.then((resp) => {
|
||||
if (resp.result === 0) {
|
||||
} else {
|
||||
Message.error($t(`errorCode.${resp.result}`));
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
Message.warning($t('gis.cross.delResult1'));
|
||||
});
|
||||
};
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const meetingControlSelect = ({ val, record }, type) => {
|
||||
console.info('meetingControlSelect', val, record);
|
||||
|
||||
currentMember.value = record;
|
||||
|
||||
switch (val) {
|
||||
case 'Remove': // 移除会议成员
|
||||
kickoutMember(record);
|
||||
break;
|
||||
|
||||
case 'AsMember': // 设置为成员
|
||||
setMemberRole(CONFERENCE_ROLE_NORMAL);
|
||||
break;
|
||||
|
||||
case 'AsHost': // 设置为主席
|
||||
setMemberRole(CONFERENCE_ROLE_HOST);
|
||||
break;
|
||||
|
||||
case 'Prohibition': // 禁言
|
||||
setMemberProhibition(MICROPHONE_STATUS_OPEN);
|
||||
break;
|
||||
|
||||
case 'ReleaseProhibition': // 解除禁言
|
||||
setMemberProhibition(MICROPHONE_STATUS_CLOSE);
|
||||
break;
|
||||
|
||||
case 'Mute': // 静音
|
||||
setMemberMute(MUTE_STATUS_Y);
|
||||
break;
|
||||
|
||||
case 'UnMute': // 解除静音
|
||||
setMemberMute(MUTE_STATUS_N);
|
||||
break;
|
||||
|
||||
case 'OpenCamera': // 打开摄像头
|
||||
setMemberCamera(CAMERA_STATUS_OPEN);
|
||||
break;
|
||||
|
||||
case 'CloseCamera': // 关闭摄像头
|
||||
setMemberCamera(CAMERA_STATUS_CLOSE);
|
||||
break;
|
||||
|
||||
case 'ReName': // 修改昵称
|
||||
reNnameVisible.value = true;
|
||||
nickname.value = record.nick || '';
|
||||
break;
|
||||
|
||||
case 'Speech': // 指定成员发言
|
||||
assignMemberSpeaker();
|
||||
break;
|
||||
|
||||
case 'CancelSpeech': // 取消指定成员发言
|
||||
cancelMemberSpeak();
|
||||
break;
|
||||
|
||||
case 'AppointImage': // 指定画面
|
||||
break;
|
||||
|
||||
case 'CancelImage': // 取消指定画面
|
||||
break;
|
||||
|
||||
default:
|
||||
console.info(val);
|
||||
}
|
||||
};
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const noMeetControlSelect = ({ val, record }, type) => {
|
||||
console.info('noMeetControlSelect', record);
|
||||
|
||||
switch (val) {
|
||||
case 'FullDuplexCall': // 全双工呼叫
|
||||
inviteMember(record);
|
||||
break;
|
||||
|
||||
case 'HalfDuplexCall': // 半双工呼叫
|
||||
inviteMember(record);
|
||||
break;
|
||||
|
||||
case 'AllCall': // 呼叫所有未入会成员
|
||||
inviteAllMember();
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
const init = () => {
|
||||
currentIndex.value = -1;
|
||||
searchCurrentIndex.value = -1;
|
||||
searchBoxStatus.value = false;
|
||||
searchContent.value = '';
|
||||
tabVal.value = '1';
|
||||
searchCollapse.value = ['1', '2'];
|
||||
};
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const closeFn = () => {
|
||||
init();
|
||||
};
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const changeCurrentIndex = (index) => {
|
||||
currentIndex.value = index;
|
||||
};
|
||||
|
||||
const closeAllModal = () => {
|
||||
visible.value = false;
|
||||
invitVisible.value = false;
|
||||
reNnameVisible.value = false;
|
||||
};
|
||||
|
||||
defineExpose({
|
||||
visible,
|
||||
closeAllModal,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
.userMangeModal {
|
||||
.arco-modal-footer {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.search_result_box {
|
||||
.user_list {
|
||||
.user_item_info {
|
||||
.avatar {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
.user_item_opration {
|
||||
img {
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
}
|
||||
|
||||
.no_meeting_btn {
|
||||
font-size: 12px;
|
||||
|
||||
img {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<style scoped lang="less">
|
||||
.userMangeModal {
|
||||
.search_box {
|
||||
position: relative;
|
||||
|
||||
.search_result_box {
|
||||
position: absolute;
|
||||
top: 34px;
|
||||
left: 0;
|
||||
z-index: 2;
|
||||
width: 320px;
|
||||
height: 224px;
|
||||
overflow-y: scroll;
|
||||
background: #2d3238;
|
||||
border: 1px solid #3c4046;
|
||||
border-radius: 4px;
|
||||
// padding: 22px 16px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.5);
|
||||
|
||||
/deep/.arco-collapse-item {
|
||||
border: none;
|
||||
}
|
||||
|
||||
/deep/.arco-collapse-item-header {
|
||||
background: transparent;
|
||||
border: none;
|
||||
}
|
||||
|
||||
/deep/.arco-collapse-item-content {
|
||||
padding: 0;
|
||||
background: transparent;
|
||||
border: none;
|
||||
}
|
||||
|
||||
/deep/.arco-collapse-item-content-box {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.userMange_tab {
|
||||
.arco-tabs-content {
|
||||
padding: 0;
|
||||
|
||||
.user_list {
|
||||
min-height: 367px;
|
||||
max-height: 367px;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
.user_footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
width: 100%;
|
||||
margin-top: 20px;
|
||||
|
||||
/deep/.arco-btn {
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.footer_btn {
|
||||
margin-top: 30px;
|
||||
|
||||
.btn {
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
562
src/views/consultation/sdk/baseData.js
Normal file
562
src/views/consultation/sdk/baseData.js
Normal file
@ -0,0 +1,562 @@
|
||||
|
||||
export default function useBaseDataModule() {
|
||||
/**
|
||||
*
|
||||
* @param param
|
||||
* @returns
|
||||
*/
|
||||
const getSystemOrg = (param) => {
|
||||
return window.lemon.basedata.fetchSystemOrg(param);
|
||||
};
|
||||
/**
|
||||
* request devices in special organization
|
||||
* @param param
|
||||
* @returns
|
||||
*/
|
||||
const getDeviceList = (param)=> {
|
||||
return window.lemon.basedata.fetchDeviceList(param);
|
||||
};
|
||||
/**
|
||||
* request common groups in special organization,if key_word is not undefind,search common groups with key_word
|
||||
* @param param
|
||||
* @returns
|
||||
*/
|
||||
const getGroupList = (param)=> {
|
||||
return window.lemon.basedata.fetchGroupList(param);
|
||||
};
|
||||
/**
|
||||
* get all members in static group
|
||||
*/
|
||||
const getGroupMembers = (group_basedata_id) => {
|
||||
return window.lemon.basedata.fetchGroupMember({
|
||||
basedata_id: group_basedata_id,
|
||||
});
|
||||
};
|
||||
/**
|
||||
* request all dispatchers
|
||||
* @param filterSelf if exclude self,default true
|
||||
* @returns
|
||||
*/
|
||||
const getDispatcherList = (filterSelf)=> {
|
||||
return window.lemon.basedata.fetchDispatcherList(filterSelf);
|
||||
};
|
||||
|
||||
/**
|
||||
* request all cross patch group from server
|
||||
* @returns
|
||||
*/
|
||||
const getCrosspatchList = ()=> {
|
||||
return window.lemon.basedata.fetchCrosspatch();
|
||||
};
|
||||
/**
|
||||
* create crosspatch,member could froms different system
|
||||
* @param number new crosspatch's number
|
||||
* @param alias new crosspatch's alias
|
||||
* @param member_list new crosspatch's mmebers
|
||||
* @returns
|
||||
*/
|
||||
const createCrosspatch = (
|
||||
number,
|
||||
alias,
|
||||
member_list
|
||||
) => {
|
||||
return window.lemon.basedata.createCrosspatch({
|
||||
number,
|
||||
alias,
|
||||
member_list,
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param record crosspatch's info
|
||||
* @returns
|
||||
*/
|
||||
const updateCrosspatch = (record) => {
|
||||
return window.lemon.basedata.updateCrosspatch(record);
|
||||
};
|
||||
/**
|
||||
*
|
||||
* @param guid
|
||||
* @param enable 1 enbale,0 disenable
|
||||
*/
|
||||
const setCrosspatchEnabled = (guid, enable) => {
|
||||
return window.lemon.basedata.updateCrosspatchActiveStatus({
|
||||
guid,
|
||||
active: enable ? 1 : 0,
|
||||
});
|
||||
};
|
||||
/**
|
||||
*
|
||||
* @param guid crosspatch's guid
|
||||
* @returns
|
||||
*/
|
||||
const deleteCrosspatch = (guid) => {
|
||||
return window.lemon.basedata.deleteCrosspatch({ guid });
|
||||
};
|
||||
/**
|
||||
*
|
||||
* @returns
|
||||
*/
|
||||
const getDynamicGroupList = ()=> {
|
||||
return window.lemon.basedata.fetchDynamicGroupList();
|
||||
};
|
||||
/**
|
||||
*
|
||||
* @param param
|
||||
* @returns
|
||||
*/
|
||||
const createDynamicGroup = (param)=> {
|
||||
return window.lemon.basedata.createDynamicGroup({
|
||||
alias: param.alias,
|
||||
member_list: param.members,
|
||||
encryption: 1,
|
||||
});
|
||||
};
|
||||
/**
|
||||
*
|
||||
* @param record
|
||||
* @returns
|
||||
*/
|
||||
const getDynamicGroupMember = (record) => {
|
||||
// return window.lemon.basedata.fetchDynamicGroupMember(record);
|
||||
return window.lemon.basedata.fetchDynamicGroupMember({
|
||||
guid: record.guid,
|
||||
number: record.number,
|
||||
basedata_id: record.basedata_id,
|
||||
alias: record.alias,
|
||||
});
|
||||
};
|
||||
/**
|
||||
*
|
||||
* @param basedata_id
|
||||
* @returns
|
||||
*/
|
||||
const isConference = (basedata_id) => {
|
||||
return window.lemon.basedata.getNumberType(basedata_id);
|
||||
};
|
||||
/**
|
||||
* remove conference'memnber
|
||||
* @param conference_guid
|
||||
* @param member_guid
|
||||
* @returns
|
||||
*/
|
||||
const removeConferenceMember = (
|
||||
conference_guid,
|
||||
member_guid
|
||||
) => {
|
||||
return window.lemon.basedata.removeConferenceMember({
|
||||
conference_guid,
|
||||
member_guid,
|
||||
});
|
||||
};
|
||||
/**
|
||||
*
|
||||
* @param param
|
||||
* @returns
|
||||
*/
|
||||
const updateDynamicGroup = (param) => {
|
||||
return window.lemon.basedata.updateDynamicGroup(param);
|
||||
};
|
||||
/**
|
||||
* @param data
|
||||
* @param data.guid gorup's guid
|
||||
* @param data.basedata_id gorup's basedata_id
|
||||
* @returns
|
||||
*/
|
||||
const deleteDynamicGroup = (data) => {
|
||||
return window.lemon.basedata.deleteDynamicGroup({
|
||||
guid: data.guid,
|
||||
basedata_id: data.basedata_id,
|
||||
});
|
||||
};
|
||||
/**
|
||||
* add member to dynamic group
|
||||
* @param group_guid
|
||||
* @param mmeber_guid
|
||||
* @param member_basedata_id
|
||||
* @param member_number
|
||||
* @returns
|
||||
*/
|
||||
const addDynamicGroupMember = (
|
||||
group_guid,
|
||||
mmeber_guid,
|
||||
member_basedata_id,
|
||||
member_number
|
||||
) => {
|
||||
return window.lemon.basedata.addDynamicGroupMember({
|
||||
dgna_guid: group_guid,
|
||||
target_guid: mmeber_guid,
|
||||
target_basedata_id: member_basedata_id,
|
||||
target_number: member_number,
|
||||
});
|
||||
};
|
||||
/**
|
||||
* remove dynamic group's member
|
||||
* @param group_guid
|
||||
* @param mmeber_guid guid of member in group,not guid of member object
|
||||
* @param member_basedata_id
|
||||
* @returns
|
||||
*/
|
||||
const removeDynamicGroupMember = (
|
||||
group_guid,
|
||||
mmeber_guid,
|
||||
member_basedata_id
|
||||
) => {
|
||||
return window.lemon.basedata.removeDynamicGroupMember({
|
||||
guid: group_guid,
|
||||
member_guid: mmeber_guid,
|
||||
basedata_id: member_basedata_id,
|
||||
});
|
||||
};
|
||||
/**
|
||||
* create a conference
|
||||
* @param number conference'number
|
||||
* @param alias conference'alias
|
||||
* @param member_list conference'members
|
||||
*/
|
||||
const createConference = (
|
||||
number,
|
||||
alias,
|
||||
member_list
|
||||
) => {
|
||||
return window.lemon.basedata.createConference({
|
||||
number,
|
||||
alias,
|
||||
member_list,
|
||||
});
|
||||
};
|
||||
/**
|
||||
* update conference info,
|
||||
* @param record conference object
|
||||
* @returns
|
||||
*/
|
||||
const updateConference = (record) => {
|
||||
return window.lemon.basedata.updateConference(record);
|
||||
};
|
||||
|
||||
/**
|
||||
* get all member of conference
|
||||
* @param guid
|
||||
* @returns
|
||||
*/
|
||||
const getConferenceMember = (guid) => {
|
||||
return window.lemon.basedata.fetchConferenceMember({ guid });
|
||||
};
|
||||
|
||||
/**
|
||||
* get all ThirdConference
|
||||
* @returns
|
||||
*/
|
||||
const getThirdConference = () => {
|
||||
return window.lemon.basedata.fetchThirdConference();
|
||||
};
|
||||
/**
|
||||
*
|
||||
* @param number new number
|
||||
* @param alias
|
||||
* @param system_id
|
||||
*/
|
||||
const createThirdConference = (
|
||||
number,
|
||||
alias,
|
||||
system_id
|
||||
) => {
|
||||
return window.lemon.basedata.createThirdConference({
|
||||
number,
|
||||
alias,
|
||||
system_id,
|
||||
});
|
||||
};
|
||||
/**
|
||||
*
|
||||
* @param record ThirdConference object
|
||||
* @returns
|
||||
*/
|
||||
const updateThirdConference = (record) => {
|
||||
return window.lemon.basedata.updateThirdConference(record);
|
||||
};
|
||||
|
||||
/**
|
||||
* delete Third Conference
|
||||
* 删除第三方会议
|
||||
* @param guid
|
||||
* @param basedata_id
|
||||
* @param number
|
||||
* @returns
|
||||
*/
|
||||
const deleteThirdConference = (
|
||||
guid,
|
||||
basedata_id,
|
||||
number
|
||||
) => {
|
||||
return window.lemon.basedata.deleteThirdConference({
|
||||
guid,
|
||||
basedata_id,
|
||||
number,
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* get systemPatch List
|
||||
* 获取系统派接列表
|
||||
* @returns
|
||||
*/
|
||||
const getSystemPatchList = () => {
|
||||
return window.lemon.basedata.fetchSystemPatchList();
|
||||
};
|
||||
/**
|
||||
* get systemPatch List
|
||||
* 获取系统派接列表
|
||||
* @returns
|
||||
*/
|
||||
const getSystemPatchMember = (record) => {
|
||||
return window.lemon.basedata.fetchSystemPatchMember({
|
||||
syspatch_guid: record.guid,
|
||||
number: record.number,
|
||||
basedata_id: record.basedata_id,
|
||||
alias: record.alias,
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* create system patch
|
||||
* 创建派接组
|
||||
* @param param
|
||||
* @returns
|
||||
*/
|
||||
const createSystemPatch = (param)=> {
|
||||
return window.lemon.basedata.createSystemPatch({
|
||||
alias: param.alias,
|
||||
member_list: param.members,
|
||||
encryption: 1,
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 删除派接组
|
||||
* delete SystemPatch
|
||||
* @param guid
|
||||
* @param basedata_id
|
||||
* @param number
|
||||
* @returns
|
||||
*/
|
||||
const deleteSystemPatch = (guid, basedata_id) => {
|
||||
return window.lemon.basedata.deleteSystemPatch({
|
||||
syspatch_guid: guid,
|
||||
basedata_id,
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param param
|
||||
* @returns
|
||||
*/
|
||||
const updateSystemPatch = (param) => {
|
||||
return window.lemon.basedata.updateSystemPatch({
|
||||
syspatch_guid: param.guid,
|
||||
number: param.number,
|
||||
basedata_id: param.basedata_id,
|
||||
alias: param.alias,
|
||||
encryption: param.encryption,
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* add member to system patch
|
||||
* 系统派接组添加成员
|
||||
* @param group_guid
|
||||
* @param mmeber_guid
|
||||
* @param member_basedata_id
|
||||
* @param member_number
|
||||
* @returns
|
||||
*/
|
||||
const addSystemPatchMember = (
|
||||
group_guid,
|
||||
mmeber_guid,
|
||||
member_basedata_id,
|
||||
member_number
|
||||
) => {
|
||||
return window.lemon.basedata.addSystemPatchMember({
|
||||
syspatch_guid: group_guid,
|
||||
target_guid: mmeber_guid,
|
||||
target_basedata_id: member_basedata_id,
|
||||
target_number: member_number,
|
||||
});
|
||||
};
|
||||
/**
|
||||
* remove system patch member
|
||||
* 系统派接组移除成员
|
||||
* @param group_guid
|
||||
* @param mmeber_guid guid of member in group,not guid of member object
|
||||
* @param member_basedata_id
|
||||
* @returns
|
||||
*/
|
||||
const removeSystemPatchMember = (
|
||||
group_guid,
|
||||
mmeber_guid,
|
||||
member_basedata_id
|
||||
) => {
|
||||
return window.lemon.basedata.removeSystemPatchMember({
|
||||
syspatch_guid: group_guid,
|
||||
member_guid: mmeber_guid,
|
||||
basedata_id: member_basedata_id,
|
||||
});
|
||||
};
|
||||
|
||||
// 模糊查询
|
||||
const fuzzyQuery = (param = { key_word }) => {
|
||||
return window.lemon.basedata.fuzzyQuery(param);
|
||||
};
|
||||
|
||||
const getOnlineInfo = (org_id) => {
|
||||
return window.lemon.basedata.queryDeviceOnlineInfo(org_id);
|
||||
};
|
||||
|
||||
const addCrosspatchChangeListener = (updateCallBackFn) => {
|
||||
return window.lemon.basedata.addCrosspatchChangeListener(updateCallBackFn);
|
||||
};
|
||||
|
||||
const removeCrosspatchChangeListener = (callbackUpdateCrosspatchGuid) => {
|
||||
return window.lemon.basedata.removeCrosspatchChangeListener(
|
||||
callbackUpdateCrosspatchGuid
|
||||
);
|
||||
};
|
||||
|
||||
const addCrosspatchMemberChangeListener = (onMemberChange) => {
|
||||
return window.lemon.basedata.addCrosspatchMemberChangeListener(
|
||||
onMemberChange
|
||||
);
|
||||
};
|
||||
|
||||
const removeCrosspatchMemberChangeListener = (membercbid) => {
|
||||
return window.lemon.basedata.removeCrosspatchMemberChangeListener(
|
||||
membercbid
|
||||
);
|
||||
};
|
||||
|
||||
const addThirdConferenceChangeListener = (onThirdConferenceChange) => {
|
||||
return window.lemon.basedata.addThirdConferenceChangeListener(
|
||||
onThirdConferenceChange
|
||||
);
|
||||
};
|
||||
|
||||
const removeThirdConferenceChangeListener = (callbackUpdate3rdConfGuid) => {
|
||||
return window.lemon.basedata.removeThirdConferenceChangeListener(
|
||||
callbackUpdate3rdConfGuid
|
||||
);
|
||||
};
|
||||
const addSystemPatchChangeListener = (onSystemPatchChange) => {
|
||||
return window.lemon.basedata.addSystemPatchChangeListener(
|
||||
onSystemPatchChange
|
||||
);
|
||||
};
|
||||
|
||||
const removeSystemPatchChangeListener = (callbackSystemPatchGuid) => {
|
||||
return window.lemon.basedata.removeThirdConferenceChangeListener(
|
||||
callbackSystemPatchGuid
|
||||
);
|
||||
};
|
||||
|
||||
// 遥晕
|
||||
const deviceStun = (record) => {
|
||||
return window.lemon.basedata.deviceStun({
|
||||
basedata_id: record.basedata_id,
|
||||
device_guid: record.guid,
|
||||
});
|
||||
};
|
||||
// 遥醒
|
||||
const deviceRevive = (record) => {
|
||||
return window.lemon.basedata.deviceRevive({
|
||||
basedata_id: record.basedata_id,
|
||||
device_guid: record.guid,
|
||||
});
|
||||
};
|
||||
// 遥毙
|
||||
const deviceKill = (record) => {
|
||||
return window.lemon.basedata.deviceKill({
|
||||
basedata_id: record.basedata_id,
|
||||
device_guid: record.guid,
|
||||
});
|
||||
};
|
||||
|
||||
// PTZ camera
|
||||
// 云台控制
|
||||
const deviceCtl = (record) => {
|
||||
// start left move
|
||||
window.lemon.basedata.deviceCtl({
|
||||
basedata_id: record.basedata_id,
|
||||
operate_type: 1,
|
||||
operate_action: 1,
|
||||
});
|
||||
|
||||
// stop left move
|
||||
setTimeout(() => {
|
||||
window.lemon.basedata.deviceCtl({
|
||||
basedata_id: record.basedata_id,
|
||||
operate_type: 2,
|
||||
operate_action: 1,
|
||||
});
|
||||
}, 2000);
|
||||
};
|
||||
|
||||
const getPucList = () => {
|
||||
return window.lemon.basedata.fetchPucList();
|
||||
};
|
||||
const setBasedataPucId = (basedataPucId) => {
|
||||
return window.lemon.basedata.setBasedataPucId({ puc_id: basedataPucId });
|
||||
};
|
||||
|
||||
return {
|
||||
getSystemOrg,
|
||||
getDeviceList,
|
||||
getGroupList,
|
||||
getGroupMembers,
|
||||
getDispatcherList,
|
||||
getCrosspatchList,
|
||||
fuzzyQuery,
|
||||
getDynamicGroupList,
|
||||
getDynamicGroupMember,
|
||||
createDynamicGroup,
|
||||
updateDynamicGroup,
|
||||
deleteDynamicGroup,
|
||||
isConference,
|
||||
removeConferenceMember,
|
||||
addDynamicGroupMember,
|
||||
removeDynamicGroupMember,
|
||||
createCrosspatch,
|
||||
updateCrosspatch,
|
||||
setCrosspatchEnabled,
|
||||
deleteCrosspatch,
|
||||
createConference,
|
||||
updateConference,
|
||||
getConferenceMember,
|
||||
getThirdConference,
|
||||
createThirdConference,
|
||||
updateThirdConference,
|
||||
deleteThirdConference,
|
||||
getOnlineInfo,
|
||||
addCrosspatchChangeListener,
|
||||
addCrosspatchMemberChangeListener,
|
||||
removeCrosspatchChangeListener,
|
||||
removeCrosspatchMemberChangeListener,
|
||||
addThirdConferenceChangeListener,
|
||||
removeThirdConferenceChangeListener,
|
||||
getSystemPatchList,
|
||||
getSystemPatchMember,
|
||||
deleteSystemPatch,
|
||||
updateSystemPatch,
|
||||
createSystemPatch,
|
||||
addSystemPatchMember,
|
||||
removeSystemPatchMember,
|
||||
addSystemPatchChangeListener,
|
||||
removeSystemPatchChangeListener,
|
||||
deviceStun,
|
||||
deviceRevive,
|
||||
deviceKill,
|
||||
getPucList,
|
||||
setBasedataPucId,
|
||||
deviceCtl,
|
||||
};
|
||||
}
|
||||
558
src/views/consultation/sdk/call.js
Normal file
558
src/views/consultation/sdk/call.js
Normal file
@ -0,0 +1,558 @@
|
||||
|
||||
import { ElMessage } from "element-plus";
|
||||
import mitt from 'mitt';
|
||||
import handleCallingNotification from '../hooks/callingNotification';
|
||||
|
||||
let call_id;
|
||||
let hangup_event_cb_id;
|
||||
let force_hangup_event_cb_id;
|
||||
let answer_ack_cb_id;
|
||||
let incoming_cb_id;
|
||||
let floor_grant_cb_id;
|
||||
|
||||
// Whether it is a pushVideoFile call
|
||||
// 是否为视频推送的呼叫
|
||||
let pushing_video = false;
|
||||
// monitor call list
|
||||
// 值守呼叫列表
|
||||
const monitor_call_list = [];
|
||||
|
||||
const emitter = mitt();
|
||||
|
||||
export default function useCallModule() {
|
||||
// we allow only one call exist in demo.but actually,sdk supports more
|
||||
|
||||
/**
|
||||
* make private vioce call,return nothing,receive result in callback
|
||||
* This interface has been expanded to support makeGroupVoiceCall、makeDispatcherVoiceCall、makeConferenceVoiceCall、makeCrosspatchVoiceCall
|
||||
* 这个接口已扩展,除了支持语音单呼外,还支持语音组呼、语音呼叫调度员、语音会议、群组呼叫。
|
||||
* @param record who you wanna call
|
||||
* @returns
|
||||
*/
|
||||
const makeVoiceCall = (record ) => {
|
||||
if (call_id) return;
|
||||
|
||||
window.lemon.call.makeVoiceCall({ basedata_id: record.basedata_id, hook_flag: 0 })?.then((resp) => {
|
||||
call_id = resp.call_id;
|
||||
});
|
||||
};
|
||||
/**
|
||||
* make private video call,call with vioce and video,return nothing,receive result in callback
|
||||
* This interface has been expanded to support makeGroupVideoCall、makeDispatcherVideoCall、makeConferenceVideoCall
|
||||
* 这个接口已扩展,除了支持视频单呼外,还支持视频组呼、视频呼叫调度员、视频会议
|
||||
* @param record who you wanna call
|
||||
* @returns
|
||||
*/
|
||||
const makeVideoCall = (record) => {
|
||||
if (call_id) return;
|
||||
window.lemon.call.makeVideoCall({ basedata_id: record.basedata_id, video_frame_size: 3 })?.then((resp) => {
|
||||
call_id = resp.call_id;
|
||||
});
|
||||
};
|
||||
const makeGroupVideoCall = (record) => {
|
||||
if (call_id) return;
|
||||
window.lemon.call.makeGroupVideoCall({ basedata_id: record.basedata_id, video_frame_size: 3 })?.then((resp) => {
|
||||
call_id = resp.call_id;
|
||||
});
|
||||
};
|
||||
const makeGroupVoiceCall = (record) => {
|
||||
if (call_id) return;
|
||||
window.lemon.call.makeGroupVoiceCall({
|
||||
basedata_id: record.basedata_id,
|
||||
})?.then((resp) => {
|
||||
call_id = resp.call_id;
|
||||
});
|
||||
};
|
||||
|
||||
const makeCrosspatchVoiceCall = (record) => {
|
||||
window.lemon.call.makeCrosspatchVoiceCall({ basedata_id: record.basedata_id })?.then((resp) => {
|
||||
call_id = resp.call_id;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 视频上拉
|
||||
* make pure video call,only video, no voice
|
||||
* @param record who you wanna call
|
||||
* @returns
|
||||
*/
|
||||
const pureVideoCall = (record) => {
|
||||
if (call_id) return;
|
||||
window.lemon.call.pullVideo({ basedata_id: record.basedata_id, hook_flag: 0 })?.then((resp) => {
|
||||
call_id = resp.call_id;
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 环境监听
|
||||
* @param record
|
||||
*/
|
||||
const voiceDetect = (record) => {
|
||||
window.lemon.call
|
||||
.makeCall({
|
||||
callee_guid: record.basedata_id,
|
||||
attribute: {
|
||||
call_type: 0,
|
||||
call_mode: 0,
|
||||
duplex_flag: 0,
|
||||
ambience_flag: 1,
|
||||
},
|
||||
})
|
||||
?.then((resp) => {
|
||||
call_id = resp.call_id;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 环境监视
|
||||
* @param record
|
||||
*/
|
||||
const videoDetect = (record) => {
|
||||
window.lemon.call.makeCall({
|
||||
callee_guid: record.basedata_id,
|
||||
attribute: { call_type: 11, call_mode: 2, duplex_flag: 0, ambience_flag: 1 },
|
||||
})?.then((resp) => {
|
||||
call_id = resp.call_id;
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 音频会议
|
||||
* @param record
|
||||
*/
|
||||
const makeConferenceVoiceCall = (record) => {
|
||||
window.lemon.call.makeConferenceVoiceCall({ basedata_id: record.basedata_id })?.then((resp) => {
|
||||
call_id = resp.call_id;
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 音视频会议
|
||||
* @param record
|
||||
*/
|
||||
const makeConferenceVideoCall = (record) => {
|
||||
window.lemon.callmakeConferenceVideoCall({basedata_id: record.basedata_id})?.then((resp) => {
|
||||
call_id = resp.call_id;
|
||||
});
|
||||
};
|
||||
|
||||
// 广播呼叫
|
||||
// Broadcast Call
|
||||
const makeBroadcastCall = (record) => {
|
||||
window.lemon.call.makeCall({ callee_guid: record.basedata_id,attribute: { call_type: 3,call_mode: 0,},})?.then((resp) => {
|
||||
call_id = resp.call_id;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* hangup call
|
||||
*/
|
||||
const hangup = (id) => {
|
||||
console.log(id,'=====挂断');
|
||||
window.lemon.call.hangupCall({ call_id: id || call_id })?.then(() => {
|
||||
console.log('00000000000=====挂断');
|
||||
call_id = undefined;
|
||||
window.calling_conference = undefined;
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('hangup call error,', err);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 接听呼叫
|
||||
* answer call
|
||||
*/
|
||||
const answerCall = () => {
|
||||
// Notification.remove(call_id);
|
||||
window.lemon.call.answerCall({ call_id })?.then(() => {
|
||||
// Notification.remove(call_id);
|
||||
}).catch((err) => {
|
||||
console.error('answer call error,', err);
|
||||
});
|
||||
};
|
||||
|
||||
// 禁麦
|
||||
// mute the microphone
|
||||
const setMuteMic = (mute) => {
|
||||
return window.lemon.call.muteMic({
|
||||
call_id,
|
||||
is_mute: mute,
|
||||
});
|
||||
};
|
||||
|
||||
// 禁摄像头
|
||||
// disable the camera
|
||||
const setMuteCamera = (mute) => {
|
||||
return window.lemon.call.muteCamera({
|
||||
call_id,
|
||||
is_mute: mute,
|
||||
});
|
||||
};
|
||||
// 静音
|
||||
// mute call
|
||||
const setMuteCall = (mute) => {
|
||||
return window.lemon.call.muteCall({
|
||||
call_id,
|
||||
is_mute: mute,
|
||||
});
|
||||
};
|
||||
|
||||
const removeMonitorCall = (callId) => {
|
||||
const index = monitor_call_list.findIndex(
|
||||
(item) => item.call_id === callId
|
||||
);
|
||||
if (index >= 0) {
|
||||
monitor_call_list.splice(index, 1);
|
||||
emitter.emit('monitorUpdate');
|
||||
}
|
||||
};
|
||||
|
||||
const getMonitorCallList = () => {
|
||||
return monitor_call_list;
|
||||
};
|
||||
|
||||
// 添加 挂断 回调
|
||||
// After hanging up the call, you can receive a notification and process the style of the current page based on the notification
|
||||
const registerhangupEvent = () => {
|
||||
if (hangup_event_cb_id !== undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
hangup_event_cb_id = window.lemon.call.addHangupEvt((data) => {
|
||||
if (data.call_id === call_id) {
|
||||
// Notification.remove(call_id);
|
||||
call_id = undefined;
|
||||
window.calling_conference = undefined;
|
||||
}
|
||||
|
||||
// pushVideoFile uninit
|
||||
// 如果是视频推送的,挂断是反初始化一些东西。
|
||||
if (pushing_video) {
|
||||
window.video.src = undefined;
|
||||
window.showVideo.value = false;
|
||||
pushing_video = false;
|
||||
window.videoViewRoot.style.display = 'none';
|
||||
}
|
||||
removeMonitorCall(data.call_id);
|
||||
});
|
||||
};
|
||||
|
||||
// 添加强拆事件
|
||||
const registerForceHangupEvent = () => {
|
||||
if (force_hangup_event_cb_id !== undefined) {
|
||||
return;
|
||||
}
|
||||
force_hangup_event_cb_id = window.lemon.call.addForceHangupEvt((data) => {
|
||||
// 目前强拆成功,都是走挂断通知事件。 当失败了,才走强拆事件通知。
|
||||
if (data.result === 0) {
|
||||
if (data.call_id === call_id) {
|
||||
// Notification.remove(call_id);
|
||||
call_id = undefined;
|
||||
window.calling_conference = undefined;
|
||||
}
|
||||
removeMonitorCall(data.call_id);
|
||||
} else {
|
||||
// 强拆失败 fail
|
||||
ElMessage.error(`errorCode.${data.result}`);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 添加接听回调通知 代表呼叫建立
|
||||
// receive the answer acknowledgement asynchronously after the call is established
|
||||
const registerCallEstablishEvent = () => {
|
||||
if (answer_ack_cb_id !== undefined) {
|
||||
return;
|
||||
}
|
||||
answer_ack_cb_id = window.lemon.call.addAnswerAckEvt((data) => {
|
||||
call_id = data.call_id;
|
||||
// 接通后,视频推送的文件开始播放
|
||||
if (pushing_video) {
|
||||
window.videoViewRoot.style.display = 'unset';
|
||||
window.showVideo.value = true;
|
||||
window.video.play();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 注册来电通知回调
|
||||
// add the incoming call callback
|
||||
const registerReceiveCallEvent = () => {
|
||||
if (incoming_cb_id !== undefined) {
|
||||
return;
|
||||
}
|
||||
incoming_cb_id = window.lemon.call.addIncomingEvt((session) => {
|
||||
console.log('receive call------>', session);
|
||||
call_id = session.call_id;
|
||||
const callingReq = {
|
||||
callInfo: session,
|
||||
equipment: undefined,
|
||||
text: {
|
||||
calling: '来电',
|
||||
answer: '接听',
|
||||
hangUp: '挂断',
|
||||
},
|
||||
};
|
||||
console.log('receive this------>', useCallModule());
|
||||
if (session.listen_flag) {
|
||||
// monitor call,auto answer call
|
||||
// 值守的来电呼叫,自动接听
|
||||
window.lemon.call.answerCall({ call_id: session.call_id });
|
||||
monitor_call_list.push(session);
|
||||
|
||||
emitter.emit('monitorUpdate');
|
||||
} else {
|
||||
// normal call
|
||||
// 正常来电,弹框询问接听
|
||||
handleCallingNotification(callingReq);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 申请话权
|
||||
// apply floor
|
||||
const applyFloor = ()=> {
|
||||
console.info('try applyFloor,call_id=', call_id);
|
||||
if (!call_id) {
|
||||
console.warn('no call exits');
|
||||
return undefined;
|
||||
}
|
||||
return window.lemon.floor
|
||||
.applySpeak({ call_id })
|
||||
?.then((resp) => {
|
||||
if (resp.result === 0) {
|
||||
console.log('applyFloor request sucess');
|
||||
} else {
|
||||
ElMessage.error(`errorCode.${resp.result}`);
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('applyFloor error,', err);
|
||||
});
|
||||
};
|
||||
|
||||
// 释放话权
|
||||
// release floor
|
||||
const releaseFloor = () => {
|
||||
console.info('try releaseFloor,call_id=', call_id);
|
||||
return window.lemon.floor
|
||||
.releaseSpeak({ call_id })
|
||||
?.then((resp) => {
|
||||
if (resp.result === 0) {
|
||||
console.log('releaseSpeak request sucess');
|
||||
} else {
|
||||
ElMessage.error(`errorCode.${resp.result}`);
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('releaseSpeak error,', err);
|
||||
});
|
||||
};
|
||||
|
||||
// add floor event
|
||||
// 添加话权通知事件
|
||||
const registerFloorGrantEvent = () => {
|
||||
if (floor_grant_cb_id !== undefined) {
|
||||
return;
|
||||
}
|
||||
floor_grant_cb_id = window.lemon.floor.addGrantEvt((grantInfo) => {
|
||||
console.log('registerFloorGrantEvent', grantInfo);
|
||||
if (grantInfo.result !== 0) {
|
||||
ElMessage.error(`errorCode.${grantInfo.result}`);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 强拆
|
||||
// override the call
|
||||
const forceHangupCall = (callId) => {
|
||||
return window.lemon.call
|
||||
.forceHangupCall({ call_id: callId || call_id })
|
||||
?.then((resp) => {
|
||||
if (resp.result === 0) {
|
||||
console.log('forceHangupCall request sucess');
|
||||
} else {
|
||||
ElMessage.error(`errorCode.${resp.result}`);
|
||||
}
|
||||
call_id = undefined;
|
||||
window.calling_conference = undefined;
|
||||
// console.log('2222233registerCallEstablishEven');
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('forceHangupCall error,', err);
|
||||
});
|
||||
};
|
||||
// 强插
|
||||
// interrupt the call during monitoring
|
||||
const forceApplySpeak = (callId) => {
|
||||
return window.lemon.floor
|
||||
.forceApplySpeak({ call_id: callId || call_id })
|
||||
?.then((resp) => {
|
||||
if (resp.result === 0) {
|
||||
console.log('forceApplySpeak request sucess');
|
||||
call_id = callId;
|
||||
} else {
|
||||
ElMessage.error(`errorCode.${resp.result}`);
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('forceApplySpeak error,', err);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 会议成员禁言
|
||||
* mute or unmute a conference member
|
||||
* @param param
|
||||
* @param param.conference_basedata_id
|
||||
*/
|
||||
const muteMemberInConference = ( conference_basedata_id, member_basedata_id, mute) => {
|
||||
return window.lemon.call.conferenceMemberSpeakSet({
|
||||
conference_call_id: call_id,
|
||||
conference_basedata_id,
|
||||
member_setting: {
|
||||
member_basedata_id,
|
||||
forbid: mute ? 1 : 0,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 视频推送
|
||||
* select a local video file and play then push the stream to remote
|
||||
* @param record
|
||||
* @param file
|
||||
* @returns
|
||||
*/
|
||||
const pushVideoFile = (record, url) => {
|
||||
if (call_id) return;
|
||||
if (window.video) {
|
||||
const canPlayListener = () => {
|
||||
window.video.removeEventListener('canplay', canPlayListener);
|
||||
// capture stream
|
||||
const stream = (window.video)?.captureStream();
|
||||
console.info('pushVideoFile,inited stream=', stream);
|
||||
// register hook listner ,play the video when remote hooked
|
||||
registerCallEstablishEvent();
|
||||
// init the call
|
||||
window.lemon.call
|
||||
.pushVideoFile({
|
||||
basedata_id: record?.basedata_id,
|
||||
stream,
|
||||
})
|
||||
?.then((resp) => {
|
||||
pushing_video = true;
|
||||
call_id = resp.call_id;
|
||||
});
|
||||
};
|
||||
|
||||
const endListener = () => {
|
||||
console.info('pushVideoFile,video play end');
|
||||
window.video.removeEventListener('ended', endListener);
|
||||
hangup();
|
||||
};
|
||||
window.video.removeEventListener('ended', endListener);
|
||||
console.info('pushVideoFile,add canplay Event Listener', canPlayListener);
|
||||
window.video.addEventListener('canplay', canPlayListener);
|
||||
console.info('pushVideoFile,add ended Event Listener', endListener);
|
||||
window.video.addEventListener('ended', endListener);
|
||||
window.video.autoplay = false;
|
||||
window.video.src = url;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 视频转发
|
||||
* share a exist call to another device
|
||||
* @param record
|
||||
* @param stop
|
||||
* @returns
|
||||
*/
|
||||
const forwardVideoCall = (record, stop) => {
|
||||
console.info('try forwardVideoCall,call_id=', call_id);
|
||||
if (!call_id) {
|
||||
console.warn('no call exits,can not forward');
|
||||
ElMessage.warning('no call exits');
|
||||
return undefined;
|
||||
}
|
||||
return window.lemon.call
|
||||
.forwardVideoCall({
|
||||
basedata_id: record?.basedata_id,
|
||||
call_id,
|
||||
action: stop ? 1 : 0,
|
||||
})
|
||||
?.then((resp) => {
|
||||
if (resp.result === 0) {
|
||||
console.log('forwardVideoCall request sucess');
|
||||
} else {
|
||||
ElMessage.error((`errorCode.${resp.result}`));
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('forwardVideoCall error,', err);
|
||||
});
|
||||
};
|
||||
|
||||
const getEmitter = () => {
|
||||
return emitter;
|
||||
};
|
||||
|
||||
// call sdk unInit
|
||||
const unInit = () => {
|
||||
call_id = undefined;
|
||||
|
||||
if (hangup_event_cb_id) {
|
||||
window.lemon.call.removeHangupEvt(hangup_event_cb_id);
|
||||
hangup_event_cb_id = undefined;
|
||||
}
|
||||
if (force_hangup_event_cb_id) {
|
||||
window.lemon.call.removeForceHangupEvt(force_hangup_event_cb_id);
|
||||
force_hangup_event_cb_id = undefined;
|
||||
}
|
||||
if (answer_ack_cb_id) {
|
||||
window.lemon.call.removeAnswerAckEvt(answer_ack_cb_id);
|
||||
answer_ack_cb_id = undefined;
|
||||
}
|
||||
if (incoming_cb_id) {
|
||||
window.lemon.call.removeIncomingEvt(incoming_cb_id);
|
||||
incoming_cb_id = undefined;
|
||||
}
|
||||
if (floor_grant_cb_id) {
|
||||
window.lemon.floor.removeGrantEvt(floor_grant_cb_id);
|
||||
floor_grant_cb_id = undefined;
|
||||
}
|
||||
monitor_call_list.length = 0;
|
||||
};
|
||||
|
||||
return {
|
||||
makeVoiceCall,
|
||||
makeVideoCall,
|
||||
pureVideoCall,
|
||||
registerhangupEvent,
|
||||
registerReceiveCallEvent,
|
||||
answerCall,
|
||||
makeGroupVoiceCall,
|
||||
makeGroupVideoCall,
|
||||
makeBroadcastCall,
|
||||
hangup,
|
||||
voiceDetect,
|
||||
videoDetect,
|
||||
applyFloor,
|
||||
releaseFloor,
|
||||
setMuteCamera,
|
||||
setMuteMic,
|
||||
setMuteCall,
|
||||
muteMemberInConference,
|
||||
makeConferenceVoiceCall,
|
||||
makeConferenceVideoCall,
|
||||
makeCrosspatchVoiceCall,
|
||||
registerCallEstablishEvent,
|
||||
pushVideoFile,
|
||||
forwardVideoCall,
|
||||
forceHangupCall,
|
||||
getMonitorCallList,
|
||||
getEmitter,
|
||||
forceApplySpeak,
|
||||
registerFloorGrantEvent,
|
||||
registerForceHangupEvent,
|
||||
unInit,
|
||||
};
|
||||
}
|
||||
302
src/views/consultation/sdk/conference.js
Normal file
302
src/views/consultation/sdk/conference.js
Normal file
@ -0,0 +1,302 @@
|
||||
|
||||
|
||||
export default function useConfernceModule() {
|
||||
/**
|
||||
* 创建会议
|
||||
*/
|
||||
const createConference = (data) => {
|
||||
return window.lemon.conference.createConference(data);
|
||||
};
|
||||
|
||||
/**
|
||||
* 根据会议号获取会议信息
|
||||
*/
|
||||
const getConferenceInfo = (data) => {
|
||||
return window.lemon.conference.getConferenceInfo(data);
|
||||
};
|
||||
|
||||
/**
|
||||
* 更新会议
|
||||
*/
|
||||
const updateConference = (data) => {
|
||||
return window.lemon.conference.updateConference(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新会议备注
|
||||
*/
|
||||
const updateConferenceRemark = (data) => {
|
||||
return window.lemon.conference.updateConferenceRemark(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除会议
|
||||
*/
|
||||
const deleteConference = (callback) => {
|
||||
return window.lemon.conference.deleteConference(callback)
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消会议
|
||||
*/
|
||||
const cancelConference = (callback) => {
|
||||
return window.lemon.conference.cancelConference(callback)
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加创建会议通知回调
|
||||
*/
|
||||
const addCreateListener = (callback) => {
|
||||
return window.lemon.conference.addCreateListener(callback)
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除创建会议通知回调
|
||||
*/
|
||||
const removeCreateListener = (callback_id) => {
|
||||
return window.lemon.conference.removeCreateListener(callback_id)
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加会议开始前提醒回调
|
||||
*/
|
||||
const addRemindListener = (callback) => {
|
||||
return window.lemon.conference.addRemindListener(callback)
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除会议开始前提醒回调
|
||||
*/
|
||||
const removeRemindListener = (callback_id) => {
|
||||
return window.lemon.conference.removeRemindListener(callback_id)
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加删除会议通知回调
|
||||
*/
|
||||
const addDeleteListener = (callback) => {
|
||||
return window.lemon.conference.addDeleteListener(callback)
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除删除会议通知回调
|
||||
*/
|
||||
const removeDeleteListener = (callback_id) => {
|
||||
return window.lemon.conference.removeDeleteListener(callback_id)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取会议列表
|
||||
*/
|
||||
const fetchConferences = (data) => {
|
||||
return window.lemon.conference.fetchConferences(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加会议成员
|
||||
*/
|
||||
const addConferenceMember = (data) => {
|
||||
return window.lemon.conference.addConferenceMember(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除会议成员
|
||||
*/
|
||||
const deleteConferenceMember = (data) => {
|
||||
return window.lemon.conference.deleteConferenceMember(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取会议成员列表
|
||||
*/
|
||||
const fetchConferenceMembers = (data) => {
|
||||
return window.lemon.conference.fetchConferenceMembers(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加新增会议成员回调
|
||||
*/
|
||||
const addAddMemberListener = (callback) => {
|
||||
return window.lemon.conference.addAddMemberListener(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除新增会议成员回调
|
||||
*/
|
||||
const removeAddMemberListener = (callback) => {
|
||||
return window.lemon.conference.removeAddMemberListener(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除删除会议成员回调
|
||||
*/
|
||||
const addDeleteMemberListener = (callback) => {
|
||||
return window.lemon.conference.addDeleteMemberListener(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除删除会议成员回调
|
||||
*/
|
||||
const removeDeleteMemberListener = (callback) => {
|
||||
return window.lemon.conference.removeDeleteMemberListener(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加修改会议回调
|
||||
*/
|
||||
const addUpdateListener = (callback) => {
|
||||
return window.lemon.conference.addUpdateListener(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除修改会议回调
|
||||
*/
|
||||
const removeUpdateListener = (callback_id) => {
|
||||
return window.lemon.conference.removeUpdateListener(callback_id)
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加媒体流获取回调
|
||||
*/
|
||||
const addMediaStream = (callback) => {
|
||||
return window.lemon.conference.addMediaStream(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除媒体流获取回调
|
||||
*/
|
||||
const removeMediaStream = (callback_id) => {
|
||||
return window.lemon.conference.removeMediaStream(callback_id)
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加接听回调
|
||||
*/
|
||||
const addAnswerAckEvt = (callback) => {
|
||||
return window.lemon.conference.addAnswerAckEvt(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除接听回调
|
||||
*/
|
||||
const removeAnswerAckEvt = (callback_id) => {
|
||||
return window.lemon.conference.removeAnswerAckEvt(callback_id)
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加挂断回调
|
||||
*/
|
||||
const addHangupEvt = (callback) => {
|
||||
return window.lemon.conference.addHangupEvt(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除挂断回调
|
||||
*/
|
||||
const removeHangupEvt = (callback_id) => {
|
||||
return window.lemon.conference.removeHangupEvt(callback_id)
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加来电回调
|
||||
*/
|
||||
const addIncomingEvt = (callback) => {
|
||||
return window.lemon.conference.addIncomingEvt(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除来电回调
|
||||
*/
|
||||
const removeIncomingEvt = (callback_id) => {
|
||||
return window.lemon.conference.removeIncomingEvt(callback_id)
|
||||
}
|
||||
|
||||
/**
|
||||
* 拨号进入会议
|
||||
*/
|
||||
const enterConferenceByNumber = (data) => {
|
||||
return window.lemon.conference.enterConferenceByNumber(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 主动开始会议
|
||||
*/
|
||||
const enterConference = (data) => {
|
||||
return window.lemon.conference.enterConference(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 结束会议
|
||||
*/
|
||||
const endConference = (data) => {
|
||||
return window.lemon.conference.endConference(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 接到呼叫,进入会议
|
||||
*/
|
||||
const answerCall = (data) => {
|
||||
return window.lemon.conference.answerCall(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 离开会议
|
||||
*/
|
||||
const hangupCall = (data) => {
|
||||
return window.lemon.conference.hangupCall(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加会议状态变更回调
|
||||
*/
|
||||
const addStateChangeListener = (callback) => {
|
||||
return window.lemon.conference.addStateChangeListener(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除会议状态变更
|
||||
*/
|
||||
const removeStateChangeListener = (callback_id) => {
|
||||
return window.lemon.conference.removeStateChangeListener(callback_id);
|
||||
}
|
||||
|
||||
return {
|
||||
createConference,
|
||||
removeCreateListener,
|
||||
addRemindListener,
|
||||
removeRemindListener,
|
||||
deleteConference,
|
||||
addCreateListener,
|
||||
addDeleteListener,
|
||||
removeDeleteListener,
|
||||
fetchConferences,
|
||||
fetchConferenceMembers,
|
||||
cancelConference,
|
||||
updateConference,
|
||||
addUpdateListener,
|
||||
removeUpdateListener,
|
||||
addConferenceMember,
|
||||
addAddMemberListener,
|
||||
removeAddMemberListener,
|
||||
addDeleteMemberListener,
|
||||
removeDeleteMemberListener,
|
||||
deleteConferenceMember,
|
||||
getConferenceInfo,
|
||||
updateConferenceRemark,
|
||||
addMediaStream,
|
||||
removeMediaStream,
|
||||
addAnswerAckEvt,
|
||||
removeAnswerAckEvt,
|
||||
addHangupEvt,
|
||||
removeHangupEvt,
|
||||
addIncomingEvt,
|
||||
removeIncomingEvt,
|
||||
enterConferenceByNumber,
|
||||
enterConference,
|
||||
endConference,
|
||||
hangupCall,
|
||||
answerCall,
|
||||
addStateChangeListener,
|
||||
removeStateChangeListener,
|
||||
};
|
||||
}
|
||||
690
src/views/consultation/sdk/conferenceControl.js
Normal file
690
src/views/consultation/sdk/conferenceControl.js
Normal file
@ -0,0 +1,690 @@
|
||||
// 会议状态-未开始
|
||||
export const CONFERENCE_STATUS_DEFAULT = 0;
|
||||
// 会议状态-进行中
|
||||
export const CONFERENCE_STATUS_PROGRESS = 1;
|
||||
// 会议状态-已结束
|
||||
export const CONFERENCE_STATUS_ENDED = 3;
|
||||
// 会议状态-已取消
|
||||
export const CONFERENCE_STATUS_CANCELED = 2;
|
||||
|
||||
// 成员是否参加过会议-否(在历史记录中有效)
|
||||
export const CONFERENCE_MEMBER_ABSENT = 0;
|
||||
// 成员是否参加过会议-是(在历史记录中有效)
|
||||
export const CONFERENCE_MEMBER_PRESENT = 1;
|
||||
|
||||
// 成员在会议中的状态-未入会
|
||||
export const CONFERENCE_MEMBER_STATE_OUT = 0;
|
||||
// 成员在会议中的状态-已入会
|
||||
export const CONFERENCE_MEMBER_STATE_IN = 1;
|
||||
// 成员在会议中的状态-呼叫中
|
||||
export const CONFERENCE_MEMBER_STATE_CALLING = 2;
|
||||
|
||||
// 成员角色-普通成员
|
||||
export const CONFERENCE_ROLE_NORMAL = 0;
|
||||
// 成员角色-主持人
|
||||
export const CONFERENCE_ROLE_HOST = 1;
|
||||
// 成员角色-创建者
|
||||
export const CONFERENCE_ROLE_CREATOR = 2;
|
||||
|
||||
// 会议类型-预约会议
|
||||
export const CONFERENCE_TYPE_BOOK = 1;
|
||||
// 会议类型-即时会议
|
||||
export const CONFERENCE_TYPE_SHORTCUT = 0;
|
||||
|
||||
// 会议主题最大长度
|
||||
export const CONFERENCE_SUBJECT_MAX_LENGTH = 64;
|
||||
|
||||
// 麦克风关闭
|
||||
export const MICROPHONE_STATUS_CLOSE = 0;
|
||||
// 麦克风打开
|
||||
export const MICROPHONE_STATUS_OPEN = 1;
|
||||
// 没有麦克风
|
||||
export const MICROPHONE_STATUS_NO = 2;
|
||||
|
||||
// 摄像头关闭
|
||||
export const CAMERA_STATUS_CLOSE = 0;
|
||||
// 摄像头打开
|
||||
export const CAMERA_STATUS_OPEN = 1;
|
||||
// 没有摄像头
|
||||
export const CAMERA_STATUS_NO = 2;
|
||||
|
||||
// 未禁言
|
||||
export const PROHIBITION_STATUS_N = 0;
|
||||
// 禁言
|
||||
export const PROHIBITION_STATUS_Y = 1;
|
||||
|
||||
// 未静音
|
||||
export const MUTE_STATUS_N = 0;
|
||||
// 静音
|
||||
export const MUTE_STATUS_Y = 1;
|
||||
|
||||
// 没有讲话
|
||||
export const SPEAKING_STATUS_N = 0;
|
||||
// 正在讲话
|
||||
export const SPEAKING_STATUS_Y = 1;
|
||||
|
||||
// 半双工模式
|
||||
export const HALFDUPLEX_CALL = 0;
|
||||
// 全双工
|
||||
export const FULLDUPLEX_CALL = 1;
|
||||
|
||||
// 未举手
|
||||
export const RAISE_HAND_N = 0;
|
||||
// 未举手
|
||||
export const RAISE_HAND_Y = 1;
|
||||
|
||||
// 举手同意发言
|
||||
export const RAISE_HAND_ALLOW = 2;
|
||||
// 举手同意拒绝
|
||||
export const RAISE_HAND_DENY = 3;
|
||||
// 举手同意忽略
|
||||
export const RAISE_HAND_IGNORE = 4;
|
||||
|
||||
export default function useConfernceModule() {
|
||||
/**
|
||||
* 是否锁定会议
|
||||
*/
|
||||
const lockConference = (data) => {
|
||||
return window.lemon.conferenceControl.lockConference(data);
|
||||
};
|
||||
|
||||
/**
|
||||
* 更新会议主题
|
||||
*/
|
||||
const updateConferenceSubject = (data) => {
|
||||
return window.lemon.conferenceControl.updateConferenceSubject(data);
|
||||
};
|
||||
|
||||
/**
|
||||
* 设置成员角色
|
||||
*/
|
||||
const setMemberRole = (data) => {
|
||||
return window.lemon.conferenceControl.setMemberRole(data);
|
||||
};
|
||||
|
||||
/**
|
||||
* 添加设置成员角色回调
|
||||
*/
|
||||
const addSetMemberRoleListener = (callback) => {
|
||||
return window.lemon.conferenceControl.addSetMemberRoleListener(callback);
|
||||
};
|
||||
|
||||
/**
|
||||
* 移除设置成员角色回调
|
||||
*/
|
||||
const removeSetMemberRoleListener = (callback) => {
|
||||
return window.lemon.conferenceControl.removeSetMemberRoleListener(callback);
|
||||
};
|
||||
|
||||
/**
|
||||
* 添加成员入会回调
|
||||
*/
|
||||
const addMemberJoinListener = (callback) => {
|
||||
return window.lemon.conferenceControl.addMemberJoinListener(callback);
|
||||
};
|
||||
|
||||
/**
|
||||
* 移除成员入会回调
|
||||
*/
|
||||
const removeMemberJoinListener = (callback_id) => {
|
||||
return window.lemon.conferenceControl.removeMemberJoinListener(callback_id);
|
||||
};
|
||||
|
||||
/**
|
||||
* 添加成员离会回调
|
||||
*/
|
||||
const addMemberLeftListener = (callback) => {
|
||||
return window.lemon.conferenceControl.addMemberLeftListener(callback);
|
||||
};
|
||||
|
||||
/**
|
||||
* 移除成员离会回调
|
||||
*/
|
||||
const removeMemberLeftListener = (callback_id) => {
|
||||
return window.lemon.conferenceControl.removeMemberLeftListener(callback_id);
|
||||
};
|
||||
|
||||
/**
|
||||
* 添加修改会议主题回调
|
||||
*/
|
||||
const addUpdateSubjectListener = (callback) => {
|
||||
return window.lemon.conferenceControl.addUpdateSubjectListener(callback);
|
||||
};
|
||||
|
||||
/**
|
||||
* 移除修改会议主题回调
|
||||
*/
|
||||
const removeUpdateSubjectListener = (callback_id) => {
|
||||
return window.lemon.conferenceControl.removeUpdateSubjectListener(
|
||||
callback_id
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* 修改会议成员昵称
|
||||
*/
|
||||
const modifyMemberNickname = (data) => {
|
||||
return window.lemon.conferenceControl.modifyMemberNickname(data);
|
||||
};
|
||||
|
||||
/**
|
||||
* 添加修改会议成员昵称回调
|
||||
*/
|
||||
const addModifyMemberNickListener = (callback) => {
|
||||
return window.lemon.conferenceControl.addModifyMemberNickListener(callback);
|
||||
};
|
||||
|
||||
/**
|
||||
* 移除修改会议成员昵称回调
|
||||
*/
|
||||
const removeModifyMemberNickListener = (callback_id) => {
|
||||
return window.lemon.conferenceControl.removeModifyMemberNickListener(
|
||||
callback_id
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* 呼叫全部未入会成员
|
||||
*/
|
||||
const inviteMember = (data) => {
|
||||
return window.lemon.conferenceControl.inviteMember(data);
|
||||
};
|
||||
|
||||
/**
|
||||
* 呼叫全部未入会成员
|
||||
*/
|
||||
const inviteAllMember = (data) => {
|
||||
return window.lemon.conferenceControl.inviteAllMember(data);
|
||||
};
|
||||
|
||||
/**
|
||||
* 添加呼叫未入会成员回调
|
||||
*/
|
||||
const addInviteMemberListener = (callback) => {
|
||||
return window.lemon.conferenceControl.addInviteMemberListener(callback);
|
||||
};
|
||||
|
||||
/**
|
||||
* 移除呼叫未入会成员回调
|
||||
*/
|
||||
const removeInviteMemberListener = (callback_id) => {
|
||||
return window.lemon.conferenceControl.removeInviteMemberListener(
|
||||
callback_id
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* 踢出会议中成员
|
||||
*/
|
||||
const kickoutMember = (data) => {
|
||||
return window.lemon.conferenceControl.kickoutMember(data);
|
||||
};
|
||||
|
||||
/**
|
||||
* 设置麦克风设备
|
||||
*/
|
||||
const changeAudioInputDevice = (data) => {
|
||||
return window.lemon.conferenceControl.changeAudioInputDevice(data);
|
||||
};
|
||||
|
||||
/**
|
||||
* 设置麦克风设备
|
||||
*/
|
||||
const changeVideoInputDevice = (data) => {
|
||||
return window.lemon.conferenceControl.changeVideoInputDevice(data);
|
||||
};
|
||||
|
||||
/**
|
||||
* 摄像头开关
|
||||
*/
|
||||
const setMemberCamera = (data) => {
|
||||
return window.lemon.conferenceControl.setMemberCamera(data);
|
||||
};
|
||||
|
||||
/**
|
||||
* 添加摄像头开关回调
|
||||
*/
|
||||
const addMemberCameraListener = (callback) => {
|
||||
return window.lemon.conferenceControl.addMemberCameraListener(callback);
|
||||
};
|
||||
|
||||
/**
|
||||
* 移除摄像头开关回调
|
||||
*/
|
||||
const removeMemberCameraListener = (callback_id) => {
|
||||
return window.lemon.conferenceControl.removeMemberCameraListener(
|
||||
callback_id
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* 静音成员
|
||||
*/
|
||||
const setMemberMute = (data) => {
|
||||
return window.lemon.conferenceControl.setMemberMute(data);
|
||||
};
|
||||
|
||||
/**
|
||||
* 禁言成员
|
||||
*/
|
||||
const setMemberProhibition = (data) => {
|
||||
return window.lemon.conferenceControl.setMemberProhibition(data);
|
||||
};
|
||||
|
||||
/**
|
||||
* 禁言全部成员
|
||||
*/
|
||||
const setAllMemberProhibition = (data) => {
|
||||
return window.lemon.conferenceControl.setAllMemberProhibition(data);
|
||||
};
|
||||
|
||||
/**
|
||||
* 添加禁言回调
|
||||
*/
|
||||
const addMemberProhibitionListener = (callback) => {
|
||||
return window.lemon.conferenceControl.addMemberProhibitionListener(
|
||||
callback
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* 移除禁言回调
|
||||
*/
|
||||
const removeMemberProhibitionListener = (callback_id) => {
|
||||
return window.lemon.conferenceControl.removeMemberProhibitionListener(
|
||||
callback_id
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* 添加全部禁言回调
|
||||
*/
|
||||
const addAllMemberProhibitionListener = (callback) => {
|
||||
return window.lemon.conferenceControl.addAllMemberProhibitionListener(
|
||||
callback
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* 移除全部禁言回调
|
||||
*/
|
||||
const removeAllMemberProhibitionListener = (callback_id) => {
|
||||
return window.lemon.conferenceControl.removeAllMemberProhibitionListener(
|
||||
callback_id
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* 添加静音回调
|
||||
*/
|
||||
const addMemberMuteListener = (callback) => {
|
||||
return window.lemon.conferenceControl.addMemberMuteListener(callback);
|
||||
};
|
||||
|
||||
/**
|
||||
* 移除静音回调
|
||||
*/
|
||||
const removeMemberMuteListener = (callback_id) => {
|
||||
return window.lemon.conferenceControl.removeMemberMuteListener(callback_id);
|
||||
};
|
||||
|
||||
/**
|
||||
* 指定成员讲话
|
||||
*/
|
||||
const assignMemberSpeaker = (data) => {
|
||||
return window.lemon.conferenceControl.assignMemberSpeaker(data);
|
||||
};
|
||||
|
||||
/**
|
||||
* 添加指定成员讲话回调
|
||||
*/
|
||||
const addAssignMemberSpeakListener = (callback) => {
|
||||
return window.lemon.conferenceControl.addAssignMemberSpeakListener(
|
||||
callback
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* 移除指定成员讲话回调
|
||||
*/
|
||||
const removeAssignMemberSpeakListener = (callback_id) => {
|
||||
return window.lemon.conferenceControl.removeAssignMemberSpeakListener(
|
||||
callback_id
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* 取消指定成员讲话
|
||||
*/
|
||||
const cancelMemberSpeak = (data) => {
|
||||
return window.lemon.conferenceControl.cancelMemberSpeak(data);
|
||||
};
|
||||
|
||||
/**
|
||||
* 添加取消成员讲话回调
|
||||
*/
|
||||
const addCancelMemberSpeakListener = (callback) => {
|
||||
return window.lemon.conferenceControl.addCancelMemberSpeakListener(
|
||||
callback
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* 移除取消成员讲话回调
|
||||
*/
|
||||
const removeCancelMemberSpeakListener = (callback_id) => {
|
||||
return window.lemon.conferenceControl.removeCancelMemberSpeakListener(
|
||||
callback_id
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* 添加成员讲话状态回调
|
||||
*/
|
||||
const addMemberSpeakingStateListener = (callback) => {
|
||||
return window.lemon.conferenceControl.addMemberSpeakingStateListener(
|
||||
callback
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* 移除成员讲话状态回调
|
||||
*/
|
||||
const removeMemberSpeakingStateListener = (callback_id) => {
|
||||
return window.lemon.conferenceControl.removeMemberSpeakingStateListener(
|
||||
callback_id
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* 添加语音激励回调
|
||||
*/
|
||||
const addVoiceStimulationListener = (callback) => {
|
||||
return window.lemon.conferenceControl.addVoiceStimulationListener(callback);
|
||||
};
|
||||
|
||||
/**
|
||||
* 移除语音激励回调
|
||||
*/
|
||||
const removeVoiceStimulationListener = (callback_id) => {
|
||||
return window.lemon.conferenceControl.removeVoiceStimulationListener(
|
||||
callback_id
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* 指定显示某路流
|
||||
*/
|
||||
const specifyMemberMediaStream = (data) => {
|
||||
return window.lemon.conferenceControl.specifyMemberMediaStream(data);
|
||||
};
|
||||
|
||||
/**
|
||||
* 指定显示多路流
|
||||
*/
|
||||
const specifyMembersMediaStream = (data) => {
|
||||
return window.lemon.conferenceControl.specifyMembersMediaStream(data);
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取布局类型
|
||||
*/
|
||||
const getLayoutType = (data) => {
|
||||
return window.lemon.conferenceControl.getLayoutType(data);
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取布局信息
|
||||
*/
|
||||
const getLayoutInfo = () => {
|
||||
return window.lemon.conferenceControl.getLayoutInfo();
|
||||
};
|
||||
|
||||
/**
|
||||
* 切换布局信息
|
||||
*/
|
||||
const setLayoutType = (data) => {
|
||||
return window.lemon.conferenceControl.setLayoutType(data);
|
||||
};
|
||||
|
||||
/**
|
||||
* 添加修改布局回调
|
||||
*/
|
||||
const addSetLayoutTypeListener = (callback) => {
|
||||
return window.lemon.conferenceControl.addSetLayoutTypeListener(callback);
|
||||
};
|
||||
|
||||
/**
|
||||
* 移除修改布局回调
|
||||
*/
|
||||
const removeSetLayoutTypeListener = (callback_id) => {
|
||||
return window.lemon.conferenceControl.removeSetLayoutTypeListener(
|
||||
callback_id
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* 添加新增会议成员回调
|
||||
*/
|
||||
const addAddMemberListener = (callback) => {
|
||||
return window.lemon.conferenceControl.addAddMemberListener(callback);
|
||||
};
|
||||
|
||||
/**
|
||||
* 移除新增会议成员回调
|
||||
*/
|
||||
const removeAddMemberListener = (callback) => {
|
||||
return window.lemon.conferenceControl.removeAddMemberListener(callback);
|
||||
};
|
||||
|
||||
/**
|
||||
* 移除删除会议成员回调
|
||||
*/
|
||||
const addDeleteMemberListener = (callback) => {
|
||||
return window.lemon.conferenceControl.addDeleteMemberListener(callback);
|
||||
};
|
||||
|
||||
/**
|
||||
* 移除删除会议成员回调
|
||||
*/
|
||||
const removeDeleteMemberListener = (callback) => {
|
||||
return window.lemon.conferenceControl.removeDeleteMemberListener(callback);
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取本地设备列表
|
||||
*/
|
||||
const getLocalDeviceList = () => {
|
||||
return window.lemon.conferenceControl.getLocalDeviceList();
|
||||
};
|
||||
|
||||
/**
|
||||
* 移除设备列表变化回调
|
||||
*/
|
||||
const addDeviceListChangeListener = (callback) => {
|
||||
return window.lemon.conferenceControl.addDeviceListChangeListener(callback);
|
||||
};
|
||||
|
||||
/**
|
||||
* 移除设备列表变化回调
|
||||
*/
|
||||
const removeDeviceListChangeListener = (callback) => {
|
||||
return window.lemon.conferenceControl.removeDeviceListChangeListener(
|
||||
callback
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* 屏幕共享
|
||||
*/
|
||||
const setShareScreenStatus = (data) => {
|
||||
return window.lemon.conferenceControl.setShareScreenStatus(data);
|
||||
};
|
||||
|
||||
/**
|
||||
* 移除屏幕共享回调
|
||||
*/
|
||||
const addScreenSharingListener = (callback) => {
|
||||
return window.lemon.conferenceControl.addScreenSharingListener(callback);
|
||||
};
|
||||
|
||||
/**
|
||||
* 移除屏幕共享回调
|
||||
*/
|
||||
const removeScreenSharingListener = (callback) => {
|
||||
return window.lemon.conferenceControl.removeScreenSharingListener(callback);
|
||||
};
|
||||
|
||||
/**
|
||||
* 截屏操作
|
||||
*/
|
||||
const startScreenshot = (data) => {
|
||||
return window.lemon.conferenceControl.startScreenshot(data);
|
||||
};
|
||||
|
||||
/**
|
||||
* 创建录屏媒体对象
|
||||
*/
|
||||
const createMediaRecorder = (data) => {
|
||||
return window.lemon.conferenceControl.createMediaRecorder(data);
|
||||
};
|
||||
|
||||
/**
|
||||
* 开始视频广播
|
||||
*/
|
||||
const broadcastVideo = (data) => {
|
||||
return window.lemon.conferenceControl.broadcastVideo(data);
|
||||
};
|
||||
|
||||
/**
|
||||
* 停止视频广播
|
||||
*/
|
||||
const stopBroadcast = () => {
|
||||
return window.lemon.conferenceControl.stopBroadcast();
|
||||
};
|
||||
|
||||
/**
|
||||
* 设置语音激励开关
|
||||
*/
|
||||
const setVoiceStimulation = (data) => {
|
||||
return window.lemon.conferenceControl.setVoiceStimulation(data);
|
||||
};
|
||||
|
||||
/**
|
||||
* 扬声器流开关
|
||||
*/
|
||||
const setMuteCall = (data) => {
|
||||
return window.lemon.conferenceControl.setMuteCall(data);
|
||||
};
|
||||
|
||||
/**
|
||||
* 切换扬声器设备
|
||||
*/
|
||||
const changeAudioOutputDevice = (data) => {
|
||||
return window.lemon.conferenceControl.changeAudioOutputDevice(data);
|
||||
};
|
||||
|
||||
/**
|
||||
* 添加当前进行中会议数据变更回调
|
||||
*/
|
||||
const addActiveConfigChangeListener = (callback) => {
|
||||
return window.lemon.conferenceControl.addActiveConfigChangeListener(
|
||||
callback
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* 移除当前进行中会议数据变更回调
|
||||
*/
|
||||
const removeActiveConfigChangeListener = (data) => {
|
||||
return window.lemon.conferenceControl.removeActiveConfigChangeListener(data);
|
||||
};
|
||||
|
||||
/**
|
||||
* 添加会议室锁定回调
|
||||
*/
|
||||
const addLockListener = (callback) => {
|
||||
return window.lemon.conferenceControl.addLockListener(callback);
|
||||
};
|
||||
|
||||
/**
|
||||
* 移除会议室锁定回调
|
||||
*/
|
||||
const removeLockListener = (data) => {
|
||||
return window.lemon.conferenceControl.removeLockListener(data);
|
||||
};
|
||||
|
||||
return {
|
||||
lockConference,
|
||||
addLockListener,
|
||||
removeLockListener,
|
||||
removeMemberJoinListener,
|
||||
addMemberJoinListener,
|
||||
removeMemberLeftListener,
|
||||
addMemberLeftListener,
|
||||
updateConferenceSubject,
|
||||
addUpdateSubjectListener,
|
||||
removeUpdateSubjectListener,
|
||||
addModifyMemberNickListener,
|
||||
removeModifyMemberNickListener,
|
||||
addInviteMemberListener,
|
||||
removeInviteMemberListener,
|
||||
inviteMember,
|
||||
inviteAllMember,
|
||||
kickoutMember,
|
||||
setMemberCamera,
|
||||
addMemberCameraListener,
|
||||
removeMemberCameraListener,
|
||||
addMemberProhibitionListener,
|
||||
removeMemberProhibitionListener,
|
||||
addAllMemberProhibitionListener,
|
||||
removeAllMemberProhibitionListener,
|
||||
setMemberMute,
|
||||
setMemberProhibition,
|
||||
setAllMemberProhibition,
|
||||
addMemberMuteListener,
|
||||
removeMemberMuteListener,
|
||||
assignMemberSpeaker,
|
||||
cancelMemberSpeak,
|
||||
addAssignMemberSpeakListener,
|
||||
removeAssignMemberSpeakListener,
|
||||
addMemberSpeakingStateListener,
|
||||
removeMemberSpeakingStateListener,
|
||||
addVoiceStimulationListener,
|
||||
removeVoiceStimulationListener,
|
||||
specifyMemberMediaStream,
|
||||
specifyMembersMediaStream,
|
||||
getLayoutType,
|
||||
getLayoutInfo,
|
||||
setLayoutType,
|
||||
addSetLayoutTypeListener,
|
||||
removeSetLayoutTypeListener,
|
||||
modifyMemberNickname,
|
||||
setMemberRole,
|
||||
addSetMemberRoleListener,
|
||||
removeSetMemberRoleListener,
|
||||
changeAudioInputDevice,
|
||||
changeVideoInputDevice,
|
||||
addCancelMemberSpeakListener,
|
||||
removeCancelMemberSpeakListener,
|
||||
addAddMemberListener,
|
||||
removeAddMemberListener,
|
||||
addDeleteMemberListener,
|
||||
getLocalDeviceList,
|
||||
removeDeleteMemberListener,
|
||||
addDeviceListChangeListener,
|
||||
removeDeviceListChangeListener,
|
||||
setShareScreenStatus,
|
||||
addScreenSharingListener,
|
||||
removeScreenSharingListener,
|
||||
startScreenshot,
|
||||
createMediaRecorder,
|
||||
stopBroadcast,
|
||||
broadcastVideo,
|
||||
setVoiceStimulation,
|
||||
removeActiveConfigChangeListener,
|
||||
addActiveConfigChangeListener,
|
||||
setMuteCall,
|
||||
changeAudioOutputDevice,
|
||||
};
|
||||
}
|
||||
390
src/views/consultation/sdk/gis.ts
Normal file
390
src/views/consultation/sdk/gis.ts
Normal file
@ -0,0 +1,390 @@
|
||||
/**
|
||||
* 通用返回对象
|
||||
* @typedef {object} RetReslut
|
||||
* @property {number} result 响应码,0成功,其他失败
|
||||
*/
|
||||
|
||||
/**
|
||||
* GPS上报数据
|
||||
* @typedef {object} GpsData
|
||||
* @property {string} basedata_id 能根据这个信息定位到设备、组、群组等identifier
|
||||
* @property {string} long_we 经度标识 取值:E:东经 W:西经
|
||||
* @property {number} longitude 经度
|
||||
* @property {string} lat_ns 纬度标识 取值:S:南纬 N:北纬
|
||||
* @property {number} latitude 纬度
|
||||
* @property {number} speed 速度 单位是海里/小时
|
||||
* @property {number} direction 方向(360度)
|
||||
* @property {string} receive_time 接收时间(UTC 时间)
|
||||
* @property {string} electricity 电量等级
|
||||
* @property {number} current_interval_time 当前的上拉周期(秒)
|
||||
* @property {string} device_alias 上报设备名称
|
||||
* @property {string} device_staff_name 上报设备实名制名称 (PDT 系统才有)
|
||||
* @property {string} device_number 上报设备号码
|
||||
*/
|
||||
|
||||
/**
|
||||
* GPS上报对象
|
||||
* @typedef {object} GpsReportInfo
|
||||
* @property {string} user_id 用户账号
|
||||
* @property {Array.<GpsData>} gps_list 上报GPS数据列表
|
||||
*/
|
||||
|
||||
/**
|
||||
* 单次上拉的 GPS信息对象
|
||||
* @typedef {object} GpsInfo
|
||||
* @property {number} result 响应码,0成功,其他失败
|
||||
* @property {string} user_id 用户账号
|
||||
* @property {GpsData} gps_data GPS数据
|
||||
*/
|
||||
|
||||
/**
|
||||
* 订阅参数对象
|
||||
* @typedef {object} Subscriber
|
||||
* @property {string} basedata_id 基础数据对象id,必填项
|
||||
* @property {number} interval_time 订阅间隔时间(s),必填项
|
||||
* @property {number} distance 订阅距离,选填项 default 0
|
||||
* @property {number} speed 订阅速度,选填项 default 0
|
||||
* @property {number} sub_type 订阅类型,选填。 1:标识只启用按距离上传 2: 标识只启用按时间上传 3:标识启用按时间与距离上传 4: 标识启用按时间或距离上传
|
||||
*/
|
||||
|
||||
/**
|
||||
* 取消订阅参数对象
|
||||
* @typedef {object} UnSubscriber
|
||||
* @property {string} basedata_id 基础数据对象id
|
||||
*/
|
||||
|
||||
/**
|
||||
* 历史轨迹查询参数对象
|
||||
* @typedef {object} RecordGpsParams
|
||||
* @property {string} basedata_id 基础数据对象id,必填项
|
||||
* @property {string} start_time 查询开始时间 必填项 ,时间格式参考示例,UTC时间 "2021-05-13T09:45:41Z"
|
||||
* @property {string} end_time 查询结束时间 必填项 ,时间格式 如 "2021-05-13T09:45:41Z"
|
||||
* @property {number} max_number 返回最多的轨迹点数,选填项 不能超过 10000. 取值范围 1000-10000。如果不填就默认10000个点。
|
||||
*/
|
||||
|
||||
/**
|
||||
* 轨迹点信息 对象
|
||||
* @typedef {object} GpsRecord
|
||||
* @property {string} long_we 经度标识 取值:E:东经 W:西经
|
||||
* @property {number} longitude 经度
|
||||
* @property {string} lat_ns 纬度标识 取值:S:南纬 N:北纬
|
||||
* @property {number} latitude 纬度
|
||||
* @property {number} speed 速度 单位是海里/小时
|
||||
* @property {number} direction 方向
|
||||
* @property {string} gps_datetime : GPS时间(UTC 时间)
|
||||
* @property {string} receive_time 接收时间(UTC 时间)
|
||||
*/
|
||||
|
||||
/**
|
||||
* 历史轨迹查询结果 对象
|
||||
* @typedef {object} GpsRecordResult
|
||||
* @property {number} result 响应码,0成功 其他是失败
|
||||
* @property {boolean} exceeded_the_maximum 是否超出最大值的轨迹点数,超出最大值,只返回最大值的点数。
|
||||
* @property {Array.<GpsRecord>} gps_record_list 轨迹点列表
|
||||
*/
|
||||
|
||||
/**
|
||||
* 分页获取订阅列表数据参数结构
|
||||
* @typedef {object} SubDeviecesParams
|
||||
* @property {number} page_index 当前页码 必填项
|
||||
* @property {number} page_size 单页容量 必填项
|
||||
* @property {string} filter_key 通过这个关键字去匹配设备号码 非必填项
|
||||
*/
|
||||
|
||||
/**
|
||||
* 分页获取订阅列表返回 对象
|
||||
* @typedef {object} SubDeviecesResult
|
||||
* @property {number} result 响应码,0成功 其他是失败
|
||||
* @property {number} total_number 总的订阅数据
|
||||
* @property {Array.<SubDevieceInfo>} sub_device_list 订阅设备列表
|
||||
*/
|
||||
|
||||
/**
|
||||
* 订阅设备信息
|
||||
* @typedef {object} SubDevieceInfo
|
||||
* @property {String} basedata_id 基础数据对象id,必填项
|
||||
* @property {string} alias 被订阅设备名称
|
||||
* @property {string} number 被订阅设备号码
|
||||
* @property {string} staff_name 被订阅设备实名制名称 (PDT 系统才有)
|
||||
* @property {number} actual_report_cycle 实际上报周期,当前上拉周期
|
||||
* @property {number} min_cycle 允许最小订阅周期
|
||||
*/
|
||||
|
||||
/**
|
||||
* 获取订阅设备的订阅关系参数
|
||||
* @typedef {object} SubDeviceRelationParams
|
||||
* @property {string} basedata_id 基础数据对象id
|
||||
*/
|
||||
|
||||
/**
|
||||
* 获取订阅设备的订阅关系 返回结果
|
||||
* @typedef {object} SubDeviceRelationResult
|
||||
* @property {number} result 响应码,0成功 其他是失败
|
||||
* @property {string} basedata_id 基础数据对象id
|
||||
* @property {Array.<SubscriberRelation>} subscriber_list 订阅关系列表
|
||||
*/
|
||||
|
||||
/**
|
||||
* 订阅关系对象
|
||||
* @typedef {object} SubscriberRelation
|
||||
* @property {string} dispatcher_id 调度台id
|
||||
* @property {number} interval_time 订阅周期
|
||||
*/
|
||||
|
||||
/**
|
||||
* 取消调度员订阅参数对象
|
||||
* @typedef {object} UnSubDispatcher
|
||||
* @property {string} basedata_id 基础数据对象id
|
||||
*/
|
||||
|
||||
/**
|
||||
* 调度员取消订阅通知信息
|
||||
* @typedef {object} DispatcherCancelSubNofify
|
||||
* @property {string} user_id 用户账号,被取消订阅的用户账号,一般是当前账号,因为只能收到自己被取消订阅的通知
|
||||
* @property {string} realm 用户账号登录域名
|
||||
* @property {string} handle_dispatcher 取消订阅操作的调度员
|
||||
* @property {string} handle_time 取消订阅操作的时间
|
||||
*/
|
||||
|
||||
/**
|
||||
* 设备被取消订阅通知信息
|
||||
* @typedef {object} DeviceCancelSubInfo
|
||||
* @property {string} number 设备号码
|
||||
* @property {string} basedata_id 设备的basedata id
|
||||
* @property {string} handle_dispatcher 取消订阅操作的调度员
|
||||
* @property {string} handle_time 取消订阅操作的时间
|
||||
*/
|
||||
/**
|
||||
* 设备被取消订阅通知信息
|
||||
* @typedef {object} DeviceCancelSubNofify
|
||||
* @property {string} user_id 用户账号,被取消订阅的用户账号,一般是当前账号,因为只能收到自己被取消订阅的通知
|
||||
* @property {string} realm 用户账号登录域名
|
||||
* @property {Array.<DeviceCancelSubInfo>} cancel_sub_list 设备取消订阅列表
|
||||
*/
|
||||
|
||||
/**
|
||||
* 全网订阅参数
|
||||
* @typedef {object} WholeNetSubParams
|
||||
* @property {number} sub_pull_mode 订阅拉取模式 0:禁止;1:全网上拉2:部分上拉
|
||||
* @property {number} whole_net_sub_cycle 订阅拉取周期
|
||||
* @property {number} recovery_time 恢复时间
|
||||
* @property {number} min_sub_cycle 全网允许最小订阅周期
|
||||
*/
|
||||
/**
|
||||
* 全网订阅参数结果
|
||||
* @typedef {object} WholeNetSubParamsResult
|
||||
* @property {number} result 响应码,0成功 其他是失败
|
||||
* @property {string} min_sub_cycle_setter 全网允许最小订阅周期设置者
|
||||
* @property {WholeNetSubParams} whole_net_sub_params 全网订阅参数
|
||||
*/
|
||||
|
||||
/**
|
||||
* 取消调度员订阅参数对象
|
||||
* @typedef {object} Device
|
||||
* @property {string} basedata_id 基础数据对象id
|
||||
*/
|
||||
|
||||
/**
|
||||
* 设置设备最小订阅周期 请求参数
|
||||
* @typedef {object} DeviceMinSubCycleParams
|
||||
* @property {number} min_sub_cycle 终端允许最小订阅周期,该值必须必须大于或等于全网最小订阅周期
|
||||
* @property {Array.<Device>} device_list 终端的basedata id 列表
|
||||
*/
|
||||
export default function useGisModule() {
|
||||
/**
|
||||
* 发起GPS订阅(支持批量)
|
||||
* @param {object} subscriberListParam 订阅列表
|
||||
* @param {Array.<Subscriber} subscriberListParam.subscriber_list 订阅列表
|
||||
* @returns
|
||||
*/
|
||||
const startSubscribeGps = (subscriberListParam) => {
|
||||
return window.lemon.gis.startSubscribeGps(subscriberListParam);
|
||||
};
|
||||
|
||||
/**
|
||||
* 取消对该设备(调用者的)订阅 (支持批量),但是不影响其他人的订阅关系
|
||||
* @param {Array.<UnSubscriber>} unSubscribeListParam
|
||||
* @param {Array.<UnSubscriber>} unSubscribeListParam.cancel_subscribe_list
|
||||
* @returns
|
||||
*/
|
||||
const stopSubscribeGps = (unSubscribeListParam) => {
|
||||
return window.lemon.gis.stopSubscribeGps(unSubscribeListParam);
|
||||
};
|
||||
|
||||
/**
|
||||
* 取消该设备的全部订阅,连同其他的人对该设备的订阅也将取消去掉 (支持批量)
|
||||
* @param {object} unSubscribeListParam
|
||||
* @param {Array.<UnSubscriber>} unSubscribeListParam.cancel_subscribe_list
|
||||
* @returns
|
||||
*/
|
||||
const cancelDeviceAllGpsSub = (unSubscribeListParam) => {
|
||||
return window.lemon.gis.cancelDeviceAllGpsSub(unSubscribeListParam);
|
||||
};
|
||||
|
||||
/**
|
||||
* 单次获取位置信息
|
||||
* @param {object} gpsInfoParam 基础数据对象id,必填项
|
||||
* @param {string} gpsInfoParam.basedata_id 基础数据对象id,必填项
|
||||
* @param {boolean} gpsInfoParam.is_encryption 是否加密, 选填。 默认加密
|
||||
* @returns {Promise.<GpsInfo>}
|
||||
*/
|
||||
const getGpsInfo = (gpsInfoParam) => {
|
||||
return window.lemon.gis.getGpsInfo(gpsInfoParam);
|
||||
};
|
||||
|
||||
/**
|
||||
* 添加GPS 上报回调
|
||||
* @param {GpsCallback} callback 回调函数
|
||||
* @returns {string} callbackId {@link removeGPSReportListener } 需要根据这个id找到对应的回调函数
|
||||
*/
|
||||
const addGPSReportListener = (callback) => {
|
||||
return window.lemon.gis.addGPSReportListener(callback);
|
||||
};
|
||||
|
||||
/**
|
||||
* 根据callbackId删除之前注册的回调
|
||||
*
|
||||
* @param {string} callbackId
|
||||
*/
|
||||
const removeGPSReportListener = (callbackId) => {
|
||||
return window.lemon.gis.removeGPSReportListener(callbackId);
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取已订阅列表
|
||||
* @param {SubDeviecesParams} subDeviecesParams 订阅列表参数对象
|
||||
* @returns {Promise.<SubDeviecesResult>}
|
||||
*/
|
||||
const fetchSubDeviceList = (subDeviecesParams) => {
|
||||
return window.lemon.gis.fetchSubDeviceList(subDeviecesParams);
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取订阅设备的订阅关系
|
||||
* @param {SubDeviceRelationParams} subDeviceRelationParams 订阅列表参数对象
|
||||
* @returns {Promise.<SubDeviceRelationResult>}
|
||||
*/
|
||||
const fetchSubDeviceRelation = (subDeviceRelationParams) => {
|
||||
return window.lemon.gis.fetchSubDeviceRelation(subDeviceRelationParams);
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取全网订阅参数
|
||||
* @returns {Promise.<WholeNetSubParamsResult>}
|
||||
*/
|
||||
const getWholeNetSubParams = () => {
|
||||
return window.lemon.gis.getWholeNetSubParams();
|
||||
};
|
||||
/**
|
||||
* 设置全网订阅参数
|
||||
* @param {WholeNetSubParams} wholeNetSubParams
|
||||
* @returns {Promise.<RetReslut>}
|
||||
*/
|
||||
const setWholeNetSubParams = (wholeNetSubParams) => {
|
||||
return window.lemon.gis.setWholeNetSubParams(wholeNetSubParams);
|
||||
};
|
||||
|
||||
/**
|
||||
* 同步订阅功能
|
||||
* @returns {Promise.<RetReslut>}
|
||||
*/
|
||||
const syncSubscribeList = () => {
|
||||
return window.lemon.gis.syncSubscribeList();
|
||||
};
|
||||
|
||||
/**
|
||||
* 设置终端最小订阅周期
|
||||
* @param {DeviceMinSubCycleParams} deviceMinSubCycleParams
|
||||
* @returns {Promise.<RetReslut>}
|
||||
*/
|
||||
const setDeviceMinSubCycle = (deviceMinSubCycleParams) => {
|
||||
return window.lemon.gis.setDeviceMinSubCycle(deviceMinSubCycleParams);
|
||||
};
|
||||
|
||||
/**
|
||||
* 取消终端允许最小订阅周期
|
||||
* @param {object} cancelDeviceParam
|
||||
* @param {Array.<Device>} cancelDeviceParam.cancel_device_list
|
||||
* @returns {Promise.<RetReslut>}
|
||||
*/
|
||||
const cancelDeviceMinSubCycle = (cancelDeviceParam) => {
|
||||
return window.lemon.gis.cancelDeviceMinSubCycle(cancelDeviceParam);
|
||||
};
|
||||
|
||||
/**
|
||||
* 取消调度员的全部订阅操作
|
||||
* @param {object>} dispatcherListParam
|
||||
* @param {Array.<UnSubDispatcher>} dispatcherListParam.cancel_subscribe_list
|
||||
* @returns
|
||||
*/
|
||||
const cancelDispatcherAllGpsSub = (dispatcherListParam) => {
|
||||
return window.lemon.gis.cancelDispatcherAllGpsSub(dispatcherListParam);
|
||||
};
|
||||
|
||||
/**
|
||||
* 添加 调度台取消订阅通知回调
|
||||
* @param {DeviceCallback} callback 回调函数
|
||||
* @returns {string} callbackId {@link removeGPSReportListener } 需要根据这个id找到对应的回调函数
|
||||
*/
|
||||
const addCXLDispatcherSubListener = (callback) => {
|
||||
return window.lemon.gis.addCXLDispatcherSubListener(callback);
|
||||
};
|
||||
|
||||
/**
|
||||
* 根据callbackId删除之前注册的回调
|
||||
*
|
||||
* @param {string} callbackId
|
||||
*/
|
||||
const removeCXLDispatcherSubListener = (callbackId) => {
|
||||
return window.lemon.gis.removeCXLDispatcherSubListener(callbackId);
|
||||
};
|
||||
|
||||
/**
|
||||
* 添加 设备取消订阅通知回调
|
||||
* @param {DeviceCallback} callback 回调函数
|
||||
* @returns {string} callbackId {@link removeCXLDeviceSubListener } 需要根据这个id找到对应的回调函数
|
||||
*/
|
||||
const addCXLDeviceSubListener = (callback) => {
|
||||
return window.lemon.gis.addCXLDeviceSubListener(callback);
|
||||
};
|
||||
|
||||
/**
|
||||
* 根据callbackId删除之前注册的回调
|
||||
*
|
||||
* @param {string} callbackId
|
||||
*/
|
||||
const removeCXLDeviceSubListener = (callbackId) => {
|
||||
return window.lemon.gis.removeCXLDispatcherSubListener(callbackId);
|
||||
};
|
||||
|
||||
/**
|
||||
* 查询历史轨迹
|
||||
* @param {RecordGpsParams} recordGpsParams 历史轨迹查询参数对象
|
||||
* @returns {Promise.<GpsRecordResult>}
|
||||
*/
|
||||
const queryRecordGPS = (recordGpsParams) => {
|
||||
return window.lemon.gis.queryRecordGPS(recordGpsParams);
|
||||
};
|
||||
|
||||
return {
|
||||
startSubscribeGps,
|
||||
stopSubscribeGps,
|
||||
cancelDeviceAllGpsSub,
|
||||
getGpsInfo,
|
||||
addGPSReportListener,
|
||||
removeGPSReportListener,
|
||||
fetchSubDeviceList,
|
||||
fetchSubDeviceRelation,
|
||||
getWholeNetSubParams,
|
||||
setWholeNetSubParams,
|
||||
syncSubscribeList,
|
||||
setDeviceMinSubCycle,
|
||||
cancelDeviceMinSubCycle,
|
||||
addCXLDispatcherSubListener,
|
||||
removeCXLDispatcherSubListener,
|
||||
addCXLDeviceSubListener,
|
||||
removeCXLDeviceSubListener,
|
||||
cancelDispatcherAllGpsSub,
|
||||
queryRecordGPS,
|
||||
};
|
||||
}
|
||||
23
src/views/consultation/sdk/log.ts
Normal file
23
src/views/consultation/sdk/log.ts
Normal file
@ -0,0 +1,23 @@
|
||||
export default function useLogModule() {
|
||||
/**
|
||||
* set log level
|
||||
* 0 : no log
|
||||
* 1 : error
|
||||
* 2 : warn
|
||||
* 3 : info
|
||||
* 4 : debug
|
||||
* @param {日志级别 int} level
|
||||
*/
|
||||
const setLevel = (level) => {
|
||||
window.lemon.log.setLevel(level);
|
||||
};
|
||||
|
||||
const getLevel = () => {
|
||||
return window.lemon.log.getLevel();
|
||||
};
|
||||
|
||||
return {
|
||||
setLevel,
|
||||
getLevel,
|
||||
};
|
||||
}
|
||||
73
src/views/consultation/sdk/login.ts
Normal file
73
src/views/consultation/sdk/login.ts
Normal file
@ -0,0 +1,73 @@
|
||||
export interface UserInfo {
|
||||
username: string;
|
||||
password: string;
|
||||
realm: string;
|
||||
webpucUrl: string;
|
||||
}
|
||||
|
||||
export default function useLoginModule() {
|
||||
/**
|
||||
* login
|
||||
* @returns
|
||||
*/
|
||||
const login = (userInfo: UserInfo) => {
|
||||
return window.lemon.login.login(userInfo);
|
||||
};
|
||||
|
||||
/**
|
||||
* logout
|
||||
* @returns
|
||||
*/
|
||||
const logout = () => {
|
||||
return window.lemon.login.logout();
|
||||
};
|
||||
|
||||
/**
|
||||
* get login account infomation
|
||||
* @returns
|
||||
*/
|
||||
const getLoginAccountInfo = () => {
|
||||
return window.lemon.login.getLoginAccountInfo();
|
||||
};
|
||||
|
||||
/**
|
||||
* Connect Websocket
|
||||
* @returns
|
||||
*/
|
||||
const reConnectWebsocket = (reConnectInfo) => {
|
||||
return window.lemon.login.reConnectWebsocket(reConnectInfo);
|
||||
};
|
||||
|
||||
/**
|
||||
* get the account login status
|
||||
* @returns ture is login in, false is not logged in
|
||||
*/
|
||||
const isLogin = () => {
|
||||
return window.lemon.login.isLogin();
|
||||
};
|
||||
|
||||
/**
|
||||
* add login status change listener
|
||||
* @returns callbackid
|
||||
*/
|
||||
const addLoginStatusChangeListener = (onLoginStatusChange) => {
|
||||
return window.lemon.login.addLoginStatusChangeListener(onLoginStatusChange);
|
||||
};
|
||||
|
||||
/**
|
||||
* remove login status change listener
|
||||
*/
|
||||
const removeLoginStatusChangeListener = (loginStatusGuid: string) => {
|
||||
window.lemon.login.removeLoginStatusChangeListener(loginStatusGuid);
|
||||
};
|
||||
|
||||
return {
|
||||
login,
|
||||
logout,
|
||||
reConnectWebsocket,
|
||||
getLoginAccountInfo,
|
||||
isLogin,
|
||||
addLoginStatusChangeListener,
|
||||
removeLoginStatusChangeListener,
|
||||
};
|
||||
}
|
||||
86
src/views/consultation/sdk/message.ts
Normal file
86
src/views/consultation/sdk/message.ts
Normal file
@ -0,0 +1,86 @@
|
||||
export interface FormatedMsg {
|
||||
sender: {
|
||||
number: string;
|
||||
alias: string;
|
||||
basedata_id: string;
|
||||
};
|
||||
recipient: {
|
||||
number: string;
|
||||
alias: string;
|
||||
basedata_id: string;
|
||||
};
|
||||
|
||||
file_parm: string;
|
||||
sds_type: string;
|
||||
sds_content: string;
|
||||
time_stamp: string;
|
||||
times: number;
|
||||
sds_text: string;
|
||||
}
|
||||
|
||||
export default function useMessageModule() {
|
||||
/**
|
||||
* download message File
|
||||
* @returns
|
||||
*/
|
||||
const downloadFile = (downloadParams: { url: string }) => {
|
||||
return window.lemon.message.downloadFile(downloadParams);
|
||||
};
|
||||
const dateTimeFormat = () => {
|
||||
const date = new Date();
|
||||
|
||||
const hour = String(date.getHours()).padStart(2, '0');
|
||||
const minute = String(date.getMinutes()).padStart(2, '0');
|
||||
const second = String(date.getSeconds()).padStart(2, '0');
|
||||
return `${[hour, minute, second].join(':')}`;
|
||||
};
|
||||
const formatMessage = (message: any): FormatedMsg => {
|
||||
const resInfo: FormatedMsg = {
|
||||
sender: {
|
||||
number: message.caller.number,
|
||||
alias: message.caller.number_alias,
|
||||
basedata_id: message.caller.basedata_id,
|
||||
},
|
||||
recipient: {
|
||||
number: message.callee.number,
|
||||
alias: message.callee.number_alias,
|
||||
basedata_id: message.callee.basedata_id,
|
||||
},
|
||||
file_parm: message.file_parm,
|
||||
sds_type: message.sds_type,
|
||||
sds_content: message.sds_content,
|
||||
time_stamp: dateTimeFormat(),
|
||||
times: new Date().getTime(),
|
||||
sds_text: message.sds_text,
|
||||
};
|
||||
return resInfo;
|
||||
};
|
||||
/**
|
||||
* send text message
|
||||
* @param basedata_id target send to
|
||||
* @param content message content
|
||||
* @returns
|
||||
*/
|
||||
const sendTxtMessage = (basedata_id: string, content: string) => {
|
||||
return window.lemon.message.sendMessageText({
|
||||
basedata_id,
|
||||
message_content: content,
|
||||
});
|
||||
};
|
||||
|
||||
const addCallback = (callback: (data) => void) => {
|
||||
return window.lemon.message.addMessageReportListener(callback);
|
||||
};
|
||||
|
||||
const removeCallback = (id: string) => {
|
||||
return window.lemon.message.removeMessageReportListener(id);
|
||||
};
|
||||
|
||||
return {
|
||||
downloadFile,
|
||||
formatMessage,
|
||||
sendTxtMessage,
|
||||
addCallback,
|
||||
removeCallback,
|
||||
};
|
||||
}
|
||||
76
src/views/consultation/sdk/monitor.ts
Normal file
76
src/views/consultation/sdk/monitor.ts
Normal file
@ -0,0 +1,76 @@
|
||||
// cache all monitor data
|
||||
const monitorData = new Map<string, object>();
|
||||
|
||||
let callback_id;
|
||||
|
||||
export default function useMonitorModule() {
|
||||
/**
|
||||
* recover history monitor relationship,callback will receive results
|
||||
* @returns
|
||||
*/
|
||||
const recoverHistory = () => {
|
||||
return window.lemon.monitor.initQueue();
|
||||
};
|
||||
|
||||
/**
|
||||
* cancel or monitor a object,like deivce、gorup or something else
|
||||
* @param basedata_id
|
||||
* @param alias
|
||||
* @returns
|
||||
*/
|
||||
const monitor = (basedata_id: string, alias: string) => {
|
||||
const has = monitorData.has(basedata_id);
|
||||
console.log('try monitor->', has);
|
||||
return window.lemon.monitor.change({
|
||||
basedata_id,
|
||||
name: alias,
|
||||
monitor_type: has ? 0 : 1,
|
||||
});
|
||||
};
|
||||
|
||||
const removeCallback = (id?: string) => {
|
||||
let inner;
|
||||
if (!id) {
|
||||
id = callback_id;
|
||||
inner = true;
|
||||
}
|
||||
window.lemon.monitor.removeChangeListener(id);
|
||||
if (inner) {
|
||||
callback_id = undefined;
|
||||
}
|
||||
};
|
||||
|
||||
const addCallback = (callback: (data) => void) => {
|
||||
return window.lemon.monitor.addChangeListener(callback);
|
||||
};
|
||||
|
||||
const registerResultCallback = () => {
|
||||
console.log('try register monitor ');
|
||||
if (callback_id) {
|
||||
console.log('there is already a callback,remove first');
|
||||
removeCallback();
|
||||
}
|
||||
callback_id = addCallback((data) => {
|
||||
if (data.result !== 0) {
|
||||
return;
|
||||
}
|
||||
// if not in list
|
||||
if (data.monitor_type === 0) {
|
||||
const deleteFlag = monitorData.delete(data.basedata_id);
|
||||
|
||||
console.log('deleteFlag', deleteFlag);
|
||||
}
|
||||
if (data.monitor_type === 1) {
|
||||
monitorData.set(data.basedata_id, data);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
recoverHistory,
|
||||
monitor,
|
||||
registerResultCallback,
|
||||
addCallback,
|
||||
removeCallback,
|
||||
};
|
||||
}
|
||||
80
src/views/consultation/sdk/reportForm.ts
Normal file
80
src/views/consultation/sdk/reportForm.ts
Normal file
@ -0,0 +1,80 @@
|
||||
export default function useReportFormModule() {
|
||||
/**
|
||||
* query Call Record
|
||||
* @returns
|
||||
*/
|
||||
const queryCallRecord = (callRecordParams) => {
|
||||
return window.lemon.reportForm.queryCallRecord(callRecordParams);
|
||||
};
|
||||
|
||||
/**
|
||||
* fetch Call Recording File Url
|
||||
* @returns
|
||||
*/
|
||||
const fetchCallRecordingFileUrl = (param: { sound_file: string }) => {
|
||||
return window.lemon.reportForm.fetchCallRecordingFileUrl(param);
|
||||
};
|
||||
|
||||
/**
|
||||
* query message Record
|
||||
* @returns
|
||||
*/
|
||||
const queryMsgRecord = (msgRecordParams) => {
|
||||
return window.lemon.reportForm.queryMsgRecord(msgRecordParams);
|
||||
};
|
||||
|
||||
/**
|
||||
* query rrs Record
|
||||
* @returns
|
||||
*/
|
||||
const queryRrsRecord = (rrsRecordParams) => {
|
||||
return window.lemon.reportForm.queryRrsRecord(rrsRecordParams);
|
||||
};
|
||||
|
||||
/**
|
||||
* query emg alarm Record
|
||||
* @returns
|
||||
*/
|
||||
const queryEmgAlarmRecord = (emgAlarmRecordParams) => {
|
||||
return window.lemon.reportForm.queryEmgAlarmRecord(emgAlarmRecordParams);
|
||||
};
|
||||
|
||||
/**
|
||||
* query Geofencing alarm Record
|
||||
* @returns
|
||||
*/
|
||||
const queryGeofencingAlarmRecord = (geofencingAlarmRecordParams) => {
|
||||
return window.lemon.reportForm.queryGeofencingAlarmRecord(
|
||||
geofencingAlarmRecordParams
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* query speed alarm Record
|
||||
* @returns
|
||||
*/
|
||||
const querySpeedAlarmRecord = (speedAlarmRecordParams) => {
|
||||
return window.lemon.reportForm.querySpeedAlarmRecord(
|
||||
speedAlarmRecordParams
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* query CallBack Record
|
||||
* @returns
|
||||
*/
|
||||
const queryCallBackRecord = (callBackRecordParams) => {
|
||||
return window.lemon.reportForm.queryCallBackRecord(callBackRecordParams);
|
||||
};
|
||||
|
||||
return {
|
||||
queryCallRecord,
|
||||
fetchCallRecordingFileUrl,
|
||||
queryMsgRecord,
|
||||
queryRrsRecord,
|
||||
queryEmgAlarmRecord,
|
||||
queryGeofencingAlarmRecord,
|
||||
querySpeedAlarmRecord,
|
||||
queryCallBackRecord,
|
||||
};
|
||||
}
|
||||
14
src/views/consultation/utils/format-show-name.js
Normal file
14
src/views/consultation/utils/format-show-name.js
Normal file
@ -0,0 +1,14 @@
|
||||
/**
|
||||
* 按个性化设置格式化显示的名称,当3K时去掉前5位的直客ID
|
||||
* @param name 别名(为空时返回号码)
|
||||
* @param number 用户号码
|
||||
* @returns 格式化后用户看到的名称
|
||||
*/
|
||||
export function formatShowNameFin(name, number) {
|
||||
if (name) {
|
||||
return `${name}(${number})`;
|
||||
}
|
||||
return number;
|
||||
}
|
||||
|
||||
export default null;
|
||||
Reference in New Issue
Block a user