Commit 1679c991 by wxl

fix calling

parent 92b5c4ae
......@@ -25,6 +25,7 @@ export function useAgoraClient() {
client = new sdk.Client() as AgoraSdkClient;
subscribeRemoteStream();
client.init(appid, () => {
// client.setRole('audience');
client.join(
token,
cid,
......
......@@ -19,6 +19,7 @@ export function useCallCenter() {
const { sendMsg, currentMsg } = useInjector(useNetSocketStore);
const { authData } = useInjector(useAuthData);
const [, changeCallingState] = useRequest('/updateUsersCallState', {auto: false});
let timer;
......@@ -28,8 +29,8 @@ export function useCallCenter() {
const {currentChannel, channelMembers, isEmpty, createChannel, getTokenByChannel, updateMembers, clearChannel} = useInjector(useChannelStore);
const callContact = (user: UserData) => {
setTarget({...user, action: 'none'}); //保存呼叫目标的信息
setCallState('calling'); //主动呼叫别人时将自己的呼叫状态更改为‘calling’
createChannel().then( data => {
setCallState('calling'); //主动呼叫别人时将自己的呼叫状态更改为‘calling’
sendMsg({
toID: user.id,
toName: user.nickname,
......@@ -50,19 +51,18 @@ export function useCallCenter() {
/** 回应呼叫功能 */
const answerCaller = (subFlag: AnyRemoteSubFlag, user?: UserData) => {
if(subFlag === 'Connect') {
setCallState('call_accepted');
getTokenByChannel(caller.value.channel);
getTokenByChannel(caller.value.channel).then( _ => setCallState('call_accepted'));
updateMembers(caller.value.members, 'join');
};
const target = user || caller.value
const target = user || caller.value;
sendMsg({
toID: target.id,
toName: target.nickname,
msgMainFlag: 'CallAnswer',
msgSubFlag: subFlag
})
clearTimeout(timer)
clearTimeout(timer);
}
/** 呼叫监听功能 */
......@@ -126,7 +126,7 @@ export function useCallCenter() {
})
/** 呼叫挂断功能 */
const [, changeCallingState] = useRequest('/updateUsersCallState', {auto: false});
const hangup = (type?: 'leave' | 'cancel') => {
let flag: AnyRemoteMainFlag, toID: string;
switch(myCallState.value) {
......@@ -168,7 +168,10 @@ export function useCallCenter() {
toID: '0'
})
}
changeCallingState({userIDs: JSON.stringify([{userID: authData.value.id, callState: state==='free' ? 'idle' : 'calling'}])});
changeCallingState({channel_id: currentChannel.value?.channel_id, userIDs: JSON.stringify([
{userID: authData.value.id, callState: state==='free' ? 'idle' : 'callout'},
{userID: target.value?.id || caller.value?.id, callState: state==='free' ? 'idle' : 'callin'}
])});
})
return {
......
......@@ -29,7 +29,7 @@ export function useChannelStore() {
const getTokenByChannel = (cid: string) => {
console.log('根据对方呼叫人的频道获取token');
updateMembers([authData.value.id], 'join');
request({channel_id: cid});
return request({channel_id: cid});
}
......
......@@ -23,7 +23,7 @@ interface MeetingMember {
/** 会议中心功能, 该功能在呼叫功能生效后使用,此模块会将其他即时交互模块集中到一起,如:音视频通讯模块、文本聊天模块等(目前只有音视频通讯) */
export function useMeetingCenter() {
const {hangup, myCallState} = useInjector(useCallCenter);
const {streamList, localPushurl, voiceMute, mode, stopVideoConference, switchLocalMicState, switchVideoOrAudio} = useInjector(useVideoConference);
const {streamList, localPushurl, voiceMute, mode, join, stopVideoConference, switchLocalMicState, switchVideoOrAudio} = useInjector(useVideoConference);
/** 离开会议(分两步:1.挂断当前呼叫, 2.停止音视频功能) */
const leave = () => {
......@@ -68,6 +68,7 @@ export function useMeetingCenter() {
localPushurl,
voiceMute,
mode,
join,
leave,
switchLocalMicState,
switchVideoOrAudio
......
......@@ -22,18 +22,22 @@ export function useVideoConference() {
/** 监听频道模块,频道被创建、更新后自动将agora的音视频通讯功能载入频道 */
watch(currentChannel, channel => {
if(!channel) return;
join();
})
const join = () => {
joinChannelWithAgora(
channel.agora_token,
channel.channel_id,
currentChannel.value.agora_token,
currentChannel.value.channel_id,
parseInt(authData.value.peer_id)
)
})
}
/** 切换麦克风使用状态 */
const [voiceMute, setVoiceMute] = useState(false);
const switchLocalMicState = () => {
if(!voiceMute.value) {
setVoiceMute(true)
setVoiceMute(true);
muteLocalStream('audio');
} else {
setVoiceMute(false);
......@@ -69,6 +73,7 @@ export function useVideoConference() {
localPushurl,
voiceMute,
mode,
join,
switchLocalMicState,
switchVideoOrAudio,
stopVideoConference
......
......@@ -25,8 +25,10 @@ export function useContacts() {
const roleContacts = computed( () => {
const contactHome = {} as {[props: string]: UserData[]}
contacts.value?.forEach( item => {
if(['3','4'].includes(item.permission) ) {
if(!contactHome[item.group_name]) contactHome[item.group_name] = [];
contactHome[item.group_name].push(item);
};
})
return contactHome
})
......
......@@ -40,8 +40,8 @@
<style lang="less">
.contact-item{
margin: 30px 0;
padding: 30px 0;
margin-bottom: 30px;
// padding: 30px 0;
border-bottom: 1px solid #f8f8f8;
display: flex;
align-items: center;
......
......@@ -14,5 +14,4 @@
height: auto;
}
}
</style>
\ No newline at end of file
......@@ -17,7 +17,6 @@
})
onBeforeUnmount(() => {
hangup();
console.log('leave')
})
......@@ -51,7 +50,8 @@ page{
background:#333;
width:100%;
height:100%;
background-image: url(https://platserver.anyremote.cn/static/img/small_routine/1.gif);
// background-image: url(https://platserver.anyremote.cn/static/img/small_routine/1.gif);
background-image: url(https://platserver.anyremote.cn/static/img/small_routine/bg3.png);
background-size: 100% 100%;
background-repeat: no-repeat;
.call-box{
......
......@@ -9,7 +9,7 @@ import { useInjector, useState } from 'vue-vulcan';
const { getContactById } = useInjector(useContacts);
const { callContact } = useInjector(useCallCenter);
const [currentContact, setContact] = useState<UserData>(null)
const [currentContact, setContact] = useState<UserData>(null);
onMounted( () => {
const ins = getCurrentInstance();
......@@ -42,6 +42,7 @@ onMounted( () => {
<view class="call-btn" @tap="callContact(currentContact)" v-if="currentContact.is_signin==='1'">
<image class="call-icon" src="../../assets/call-small2x.png"></image>
&nbsp;&nbsp;
<text>视频通话</text>
</view>
</view>
......
......@@ -5,10 +5,11 @@
import { navigateTo, showToast } from '@tarojs/taro';
import { useAppInitInfo } from 'src/hooks/common/useAppInitInfo';
import { UserData } from 'any-hooks/types/user';
import { reactive } from '@vue/reactivity';
const { callContact, myCallState } = useInjector(useCallCenter);
const { contacts, roleContacts } = useInjector(useContacts);
const { checkCamearSetting } = useInjector(useAppInitInfo)
const { checkCamearSetting } = useInjector(useAppInitInfo);
const gotoDetail = (id: string) => {
navigateTo({url: '/pages/contact-detail/index?id='+ id})
......@@ -24,18 +25,24 @@
})
}
}
// 联系人折叠隐藏功能
const hideConfig = reactive({});
const toggleHideByIndex = (index: number) => {
hideConfig[index] = !hideConfig[index]
}
</script>
<template>
<view class="contact-list">
<view class="contact-role-group" v-for="(group, key, index) in roleContacts" :key="index">
<view class="role-name pd-2">{{key}}</view>
<view class="white-box">
<view class="contact-item pd-2" v-for="(item, i) in group" :key="i" @tap="gotoDetail(item.id)">
<view class="role-name pd-2" :class="{hide: hideConfig[index]}" @tap="toggleHideByIndex(index)">{{key}}</view>
<view class="white-box" :style="{display: hideConfig[index] ? 'none' : 'block'}">
<view class="contact-item" v-for="(item, i) in group" :key="i" @tap="gotoDetail(item.id)">
<image class="avatar" :src="item.avatar" />
<view class="info">
<view>{{item.nickname}}</view>
<text>{{item.group_name}}</text>
<text style="color:#999">{{item.group_name}}</text>
</view>
<image v-if="item.is_signin === '1'" @tap.stop="onTapCall(item)" class="call" src="../../assets/call3x.png" mode="widthFix"/>
<image v-else class="call" src="../../assets/call-no3x.png" mode="widthFix"/>
......@@ -51,7 +58,23 @@
.contact-role-group{
background-color: #fff;
.role-name{
background-color: #f5f5f5;
// background-color: #f5f5f5;
position: relative;
padding-left: 60px;
&.hide::before{
transform: rotate(-90deg);
}
&::before{
content: '';
width: 0;
height: 0;
position: absolute;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-top: 16px solid #aaa;
left:25px;
top:37px;
}
}
}
}
......
......@@ -47,7 +47,6 @@
</template>
<style lang="less" >
.search-box{
display: flex;
align-items: center;
......@@ -95,11 +94,14 @@
}
.contact-list{
.contact-item{
margin: 30px 0;
padding: 30px 0;
border-bottom: 1px solid #f8f8f8;
margin-bottom: 65px;
// padding: 25px 0;
// border-bottom: 1px solid #f8f8f8;
display: flex;
align-items: center;
&:last-child{
margin-bottom: 15px;
}
.avatar{
width: 80px;
height: 80px;
......
......@@ -3,7 +3,6 @@
import { useContacts } from 'any-hooks/contacts/useContacts';
import { useInjector } from 'vue-vulcan';
const { filterGroups } = useInjector(useContacts);
const gotoGroupContacts = (id: string) => {
navigateTo({url: `/pages/group-contacts/index?id=${id}`})
......
......@@ -9,11 +9,17 @@
import Invite from './invite.vue';
import { useCallCenter } from 'any-hooks/communication/useCallCenter';
import { UserData } from 'any-hooks/types/user';
import { useChannelStore } from 'any-hooks/communication/useChannelStore';
const { target } = useInjector(useCallCenter);
const { currentChannel } = useInjector(useChannelStore);
const { streamList, localPushurl, voiceMute, mode, switchLocalMicState, switchVideoOrAudio, leave } = useInjector(useMeetingCenter);
const { topDistance, rect } = useAppInitInfo();
// onMounted(() => {
// join();
// })
/* 监听流的数量,自动退出会议 */
watch(streamList, (current, last) => {
if(current.length > last.length) return;
......@@ -23,10 +29,10 @@
}
})
const context = createLivePusherContext()
const context = createLivePusherContext();
watch(localPushurl, url => {
url && context.start()
url && context.start();
})
/* 用户主动退出会议 */
......@@ -73,18 +79,18 @@
<template>
<image class="navi-back" src="../../assets/arrow_left.png" mode="widthFix" :style="{top: rect.top+'px'}" @tap="navigateBack()"></image>
<view class ="meeting-container page col-page" :style="{paddingTop: topDistance+'px'}">
<invite v-if="inviting" @choose="onInvite($event)" @cancel="setInviting(false)"></invite>
<!-- <view class="c-info" style="color:#fff">
<view class ="meeting-container page col-page" @tap="setInviting(false)">
<view class="c-info" style="color:#fff">
{{currentChannel?.channel_id}}
</view> -->
</view>
<view class="videos">
<stream-player
class="video-item"
v-for="(item, key) in streamList"
:key="key"
:stream="item"
:class="{active: activeVideo===key, hide: activeVideo!==-2, mini: streamList.length > 5}"
:class="{active: activeVideo===key, hide: activeVideo!==-2, mini: streamList.length > 5, big: streamList.length < 3}"
@tap="toggleActive(key)"
>
</stream-player>
......@@ -92,7 +98,7 @@
class="video-item"
v-if="localPushurl"
:url="localPushurl"
:class="{active: activeVideo===-1, hide: activeVideo!==-2, mini: streamList.length > 5}"
:class="{active: activeVideo===-1, hide: activeVideo!==-2, mini: streamList.length > 5, big: streamList.length < 3}"
@tap="toggleActive(-1)"
>
</stream-pusher>
......@@ -101,7 +107,7 @@
<text>等待中...</text>
</view>
<view class="add-operator" @tap="setInviting(true)">
<view class="add-operator" @tap.stop="setInviting(true)">
<image class="add-icon" src="../../assets/add.png" mode="widthFix"></image>
<text>添加联系人</text>
</view>
......@@ -148,7 +154,6 @@
}
.meeting-container{
background: #333;
.videos{
flex:1;
text-align: center;
......@@ -162,6 +167,10 @@
display: inline-block;
background: #000;
color: #fff;
&.big{
width: 100%;
height: 400px;
}
&.mini{
width: 33.3%;
height: 200px;
......
......@@ -2,13 +2,13 @@
import { useContacts } from "any-hooks/contacts/useContacts";
import { UserData } from "any-hooks/types/user";
import { useAppInitInfo } from "src/hooks/common/useAppInitInfo";
import { defineEmit } from "vue";
import { defineEmit, reactive } from "vue";
import { useInjector } from "vue-vulcan";
const { topDistance } = useAppInitInfo();
/* 获取在线且空闲的联系人 */
const { freeContacts } = useInjector(useContacts);
const { freeContacts, roleContacts } = useInjector(useContacts);
const emit = defineEmit();
const onChoose = (user: UserData) => {
......@@ -17,18 +17,31 @@
const cancelChoose = () => {
emit('cancel');
}
// 联系人折叠隐藏功能
const hideConfig = reactive({});
const toggleHideByIndex = (index: number) => {
hideConfig[index] = !hideConfig[index]
}
</script>
<template>
<view class="invite-container page" :style="{paddingTop: topDistance+'px'}" @tap="cancelChoose()">
<view class="contacts">
<view class="contact-item" v-for="(item, key) in freeContacts" :key="key" @tap.stop="onChoose(item)">
<image class="avatar" :src="item.avatar"></image>
<view class="name">{{item.nickname}}</view>
<scroll-view :scrollY="true" class="invite-container page" :style="{top: topDistance+'px'}" >
<view class="contact-role-group" v-for="(group, key, index) in roleContacts" :key="index">
<view class="role-name pd-2" :class="{hide: hideConfig[index]}" @tap="toggleHideByIndex(index)">{{key}}</view>
<view class="white-box" :style="{display: hideConfig[index] ? 'none' : 'block'}">
<view class="contact-item" v-for="(item, i) in group" :key="i" >
<image class="avatar" :src="item.avatar" />
<view class="info">
<view>{{item.nickname}}</view>
<text style="color:#999">{{item.group_name}}</text>
</view>
<button class="call invite-btn" @tap.stop="onChoose(item)">邀请</button>
</view>
</view>
<data-empty v-if="!freeContacts?.length"></data-empty>
</view>
<data-empty v-if="!roleContacts?.length"></data-empty>
</scroll-view>
</template>
<style lang="less">
......@@ -37,9 +50,61 @@
z-index: 1000;
top: 0;
left: 0;
bottom: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.65);
z-index: 10000;
.contact-role-group{
background-color: #fff;
.role-name{
// background-color: #f5f5f5;
position: relative;
padding-left: 60px;
&.hide::before{
transform: rotate(-90deg);
}
&::before{
content: '';
width: 0;
height: 0;
position: absolute;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-top: 16px solid #aaa;
left:25px;
top:37px;
}
}
.contact-item{
margin-bottom: 65px;
// padding: 25px 0;
// border-bottom: 1px solid #f8f8f8;
display: flex;
align-items: center;
&:last-child{
margin-bottom: 15px;
}
.avatar{
width: 80px;
height: 80px;
border-radius: 50%;
overflow:hidden;
}
.info{
flex: 1;
padding: 0 20px;
}
.invite-btn{
display: inline-block;
background: #2b91e2;
color: #fff;
padding: 6px 12px;
}
}
}
.contacts{
display: flex;
padding: 0 30px;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment