Commit 1679c991 by wxl

fix calling

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