添加语音通话挂起功能
This commit is contained in:
parent
5a939bc811
commit
293fc78c6a
256
src/App.vue
256
src/App.vue
@ -6,10 +6,55 @@
|
|||||||
</keep-alive>
|
</keep-alive>
|
||||||
</transition>
|
</transition>
|
||||||
</router-view>
|
</router-view>
|
||||||
|
|
||||||
|
<div class="call-float"
|
||||||
|
v-if="isSmall"
|
||||||
|
:style="callFloatStyle"
|
||||||
|
@touchmove="touchmove"
|
||||||
|
@touchend="touchend"
|
||||||
|
@click="isSmall = false">
|
||||||
|
<img src="@/assets/img/icon/message/chat/call-float.png" alt="">
|
||||||
|
<span>呼叫中</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<transition name="scale">
|
||||||
|
<div class="audio-call"
|
||||||
|
:style="isSmall ? callFloatStyle : {zIndex:10}"
|
||||||
|
:class="isSmall?'small':''"
|
||||||
|
v-if="isShowAudioCall">
|
||||||
|
<div class="float">
|
||||||
|
<div class="header">
|
||||||
|
<img @click="isSmall = true" src="@/assets/img/icon/message/chat/narrow.png" alt=""
|
||||||
|
class="left">
|
||||||
|
<div class="center">
|
||||||
|
<img src="@/assets/img/icon/avatar/2.png" alt="" class="avatar">
|
||||||
|
<span>等待对方接听...</span>
|
||||||
|
</div>
|
||||||
|
<div class="right">
|
||||||
|
<div class="option">
|
||||||
|
<img src="@/assets/img/icon/message/chat/disabled-camera.png" alt="">
|
||||||
|
<span>摄像头</span>
|
||||||
|
</div>
|
||||||
|
<div class="option">
|
||||||
|
<img src="@/assets/img/icon/message/chat/able-volume.png" alt="">
|
||||||
|
<span>免提</span>
|
||||||
|
</div>
|
||||||
|
<div class="option">
|
||||||
|
<back mode="light" img="back" class="shrink"/>
|
||||||
|
<!-- <img src="@/assets/img/icon/message/chat/narrow.png" alt="">-->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<img src="@/assets/img/icon/avatar/2.png" alt="" class="big-avatar">
|
||||||
|
<div class="footer">
|
||||||
|
<img @click="isShowAudioCall = false" src="@/assets/img/icon/message/chat/call-end.png">
|
||||||
|
<span>挂断</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</transition>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* try {navigator.control.gesture(false);} catch (e) {} //UC浏览器关闭默认手势事件
|
* try {navigator.control.gesture(false);} catch (e) {} //UC浏览器关闭默认手势事件
|
||||||
try {navigator.control.longpressMenu(false);} catch (e) {} //关闭长按弹出菜单
|
try {navigator.control.longpressMenu(false);} catch (e) {} //关闭长按弹出菜单
|
||||||
@ -17,6 +62,7 @@ try {navigator.control.longpressMenu(false);} catch (e) {} //关闭长按弹出
|
|||||||
import Mask from "./components/Mask";
|
import Mask from "./components/Mask";
|
||||||
import {mapState} from "vuex";
|
import {mapState} from "vuex";
|
||||||
import routes from "./router/routes";
|
import routes from "./router/routes";
|
||||||
|
import {inject} from "_vue@3.2.20@vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'App',
|
name: 'App',
|
||||||
@ -25,13 +71,42 @@ export default {
|
|||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
isSmall: false,
|
||||||
|
isShowAudioCall: false,
|
||||||
transitionName: 'go',
|
transitionName: 'go',
|
||||||
|
callFloatTransitionTime: 0,
|
||||||
|
callFloatLeft: 15,
|
||||||
|
callFloatTop: 100,
|
||||||
|
height: 0,
|
||||||
|
width: 0,
|
||||||
|
mitt: inject('mitt'),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapState(['excludeRoutes'])
|
...mapState(['excludeRoutes']),
|
||||||
|
callFloatStyle() {
|
||||||
|
return {
|
||||||
|
'transition-duration': this.callFloatTransitionTime + 'ms',
|
||||||
|
left: this.callFloatLeft + 'px',
|
||||||
|
top: this.callFloatTop + 'px',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
touchmove(e) {
|
||||||
|
this.callFloatTransitionTime = 0
|
||||||
|
this.callFloatLeft = e.touches[0].pageX - 35
|
||||||
|
this.callFloatTop = e.touches[0].pageY - 40
|
||||||
|
},
|
||||||
|
touchend(e) {
|
||||||
|
this.callFloatTransitionTime = 300
|
||||||
|
if (this.callFloatLeft < this.width / 2) {
|
||||||
|
this.callFloatLeft = 15
|
||||||
|
} else {
|
||||||
|
this.callFloatLeft = this.width - 15 - 70
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
methods: {},
|
|
||||||
// watch $route 决定使用哪种过渡
|
// watch $route 决定使用哪种过渡
|
||||||
watch: {
|
watch: {
|
||||||
'$route'(to, from) {
|
'$route'(to, from) {
|
||||||
@ -49,6 +124,15 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
this.mitt.on('showAudioCall', () => {
|
||||||
|
if (this.isShowAudioCall) {
|
||||||
|
this.isSmall = false
|
||||||
|
} else {
|
||||||
|
this.isShowAudioCall = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.height = document.body.clientHeight
|
||||||
|
this.width = document.body.clientWidth
|
||||||
// this.$store.dispatch('getFriends')
|
// this.$store.dispatch('getFriends')
|
||||||
try {
|
try {
|
||||||
navigator.control.gesture(false);
|
navigator.control.gesture(false);
|
||||||
@ -62,13 +146,165 @@ export default {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.scale-enter-active,
|
||||||
|
.scale-leave-active {
|
||||||
|
transition: transform .2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scale-enter-from,
|
||||||
|
.scale-leave-to {
|
||||||
|
transform: scale(0);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
//
|
@import "./assets/less/index";
|
||||||
//.base-slide-item {
|
|
||||||
// min-width: 100vw;
|
.call-float {
|
||||||
// min-height: 100vh;
|
transition-property: all;
|
||||||
// position: relative;
|
z-index: 9;
|
||||||
//}
|
width: 7rem;
|
||||||
|
height: 8rem;
|
||||||
|
position: fixed;
|
||||||
|
top: 20vh;
|
||||||
|
left: @padding-page;
|
||||||
|
background: white;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
border-radius: .6rem;
|
||||||
|
justify-content: center;
|
||||||
|
flex-direction: column;
|
||||||
|
color: #14BF5F;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 3rem;
|
||||||
|
margin-bottom: .2rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.audio-call {
|
||||||
|
color: white;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
position: fixed;
|
||||||
|
z-index: 8;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
//background: black;
|
||||||
|
background: linear-gradient(to bottom, #262626, black);
|
||||||
|
transition: all .3s;
|
||||||
|
|
||||||
|
.float {
|
||||||
|
transition: all .3s;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
> .header {
|
||||||
|
width: 100vw;
|
||||||
|
padding: @padding-page;
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 2.4rem;
|
||||||
|
height: 2.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.center {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 2rem;
|
||||||
|
height: 2rem;
|
||||||
|
background: white;
|
||||||
|
padding: .2rem;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
margin-left: .5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.right {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
font-size: 1rem;
|
||||||
|
|
||||||
|
.option {
|
||||||
|
margin-bottom: 2.4rem;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
span {
|
||||||
|
margin-top: 1rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.shrink {
|
||||||
|
transform: rotate(90deg) scale(.6) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.big-avatar {
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
top: 50%;
|
||||||
|
transform: translate3d(-50%, -50%, 0);
|
||||||
|
width: 10rem;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
margin-bottom: 4rem;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 5rem;
|
||||||
|
margin-bottom: .5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.small {
|
||||||
|
//opacity: 0;
|
||||||
|
width: 7rem;
|
||||||
|
height: 8rem;
|
||||||
|
position: fixed;
|
||||||
|
top: 20vh;
|
||||||
|
left: @padding-page;
|
||||||
|
border-radius: .6rem;
|
||||||
|
|
||||||
|
.float {
|
||||||
|
width: 7rem;
|
||||||
|
height: 8rem;
|
||||||
|
transform: scale(0);
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#app {
|
#app {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|||||||
@ -8,7 +8,7 @@
|
|||||||
<span>zzzz</span>
|
<span>zzzz</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="right">
|
<div class="right">
|
||||||
<img @click="isShowAudioCall = true" style="transform: scale(1.1)"
|
<img @click="mitt.emit('showAudioCall')" style="transform: scale(1.1)"
|
||||||
src="../../../assets/img/icon/message/video-white.png" alt="">
|
src="../../../assets/img/icon/message/video-white.png" alt="">
|
||||||
<img src="../../../assets/img/icon/menu-white.png" alt="" @click="$nav('/message/chat/detail')">
|
<img src="../../../assets/img/icon/menu-white.png" alt="" @click="$nav('/message/chat/detail')">
|
||||||
</div>
|
</div>
|
||||||
@ -161,53 +161,11 @@
|
|||||||
</transition>
|
</transition>
|
||||||
|
|
||||||
<Loading v-if="loading"/>
|
<Loading v-if="loading"/>
|
||||||
|
|
||||||
<div class="call-float">
|
|
||||||
<!-- <span>对方手机可能不在身边,建议稍后再试</span>-->
|
|
||||||
<!-- <span>对方无应答</span>-->
|
|
||||||
<img src="@/assets/img/icon/message/chat/call-float.png" alt="">
|
|
||||||
<span>呼叫中</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<transition name="scale">
|
|
||||||
<div class="audio-call" v-if="isShowAudioCall">
|
|
||||||
<div class="float">
|
|
||||||
<div class="header">
|
|
||||||
<img @click="isShowAudioCall = false" src="../../../assets/img/icon/message/chat/narrow.png" alt=""
|
|
||||||
class="left">
|
|
||||||
<div class="center">
|
|
||||||
<img src="../../../assets/img/icon/avatar/2.png" alt="" class="avatar">
|
|
||||||
<span>等待对方接听...</span>
|
|
||||||
</div>
|
|
||||||
<div class="right">
|
|
||||||
<div class="option">
|
|
||||||
<img src="../../../assets/img/icon/message/chat/disabled-camera.png" alt="">
|
|
||||||
<span>摄像头</span>
|
|
||||||
</div>
|
|
||||||
<div class="option">
|
|
||||||
<img src="../../../assets/img/icon/message/chat/able-volume.png" alt="">
|
|
||||||
<span>免提</span>
|
|
||||||
</div>
|
|
||||||
<div class="option">
|
|
||||||
<back mode="light" img="back" class="shrink"/>
|
|
||||||
<!-- <img src="../../../assets/img/icon/message/chat/narrow.png" alt="">-->
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<img src="../../../assets/img/icon/avatar/2.png" alt="" class="big-avatar">
|
|
||||||
<div class="footer">
|
|
||||||
<img @click="isShowAudioCall = false" src="@/assets/img/icon/message/chat/call-end.png">
|
|
||||||
<span>挂断</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</transition>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import ChatMessage from "../components/ChatMessage";
|
import ChatMessage from "../components/ChatMessage";
|
||||||
import {nextTick} from "vue";
|
import {inject, nextTick} from "vue";
|
||||||
import Mask from "../../../components/Mask";
|
import Mask from "../../../components/Mask";
|
||||||
import {mapState} from "vuex";
|
import {mapState} from "vuex";
|
||||||
import Loading from "../../../components/Loading";
|
import Loading from "../../../components/Loading";
|
||||||
@ -491,7 +449,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
isShowAudioCall: false,
|
|
||||||
typing: false,
|
typing: false,
|
||||||
loading: false,
|
loading: false,
|
||||||
opening: false,
|
opening: false,
|
||||||
@ -500,7 +458,8 @@ export default {
|
|||||||
showOption: false,
|
showOption: false,
|
||||||
isShowOpenRedPacket: false,
|
isShowOpenRedPacket: false,
|
||||||
tooltipTop: -1,
|
tooltipTop: -1,
|
||||||
tooltipTopLocation: ''
|
tooltipTopLocation: '',
|
||||||
|
mitt: inject('mitt'),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -934,126 +893,6 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.audio-call {
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100vw;
|
|
||||||
height: 100vh;
|
|
||||||
//background: black;
|
|
||||||
background: linear-gradient(to bottom, #262626, black);
|
|
||||||
|
|
||||||
.float {
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100vw;
|
|
||||||
height: 100vh;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
|
|
||||||
> .header {
|
|
||||||
width: 100vw;
|
|
||||||
padding: @padding-page;
|
|
||||||
box-sizing: border-box;
|
|
||||||
display: flex;
|
|
||||||
align-items: flex-start;
|
|
||||||
justify-content: space-between;
|
|
||||||
|
|
||||||
img {
|
|
||||||
width: 2.4rem;
|
|
||||||
height: 2.4rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.center {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
img {
|
|
||||||
width: 2rem;
|
|
||||||
height: 2rem;
|
|
||||||
background: white;
|
|
||||||
padding: .2rem;
|
|
||||||
border-radius: 50%;
|
|
||||||
}
|
|
||||||
|
|
||||||
span {
|
|
||||||
margin-left: .5rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.right {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
font-size: 1rem;
|
|
||||||
|
|
||||||
.option {
|
|
||||||
margin-bottom: 2.4rem;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
flex-direction: column;
|
|
||||||
|
|
||||||
span {
|
|
||||||
margin-top: 1rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.shrink {
|
|
||||||
transform: rotate(90deg) scale(.6) !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.big-avatar {
|
|
||||||
position: absolute;
|
|
||||||
left: 50%;
|
|
||||||
top: 50%;
|
|
||||||
transform: translate3d(-50%, -50%, 0);
|
|
||||||
width: 10rem;
|
|
||||||
border-radius: 50%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
font-size: 1.2rem;
|
|
||||||
margin-bottom: 4rem;
|
|
||||||
|
|
||||||
img {
|
|
||||||
width: 5rem;
|
|
||||||
margin-bottom: .5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.call-float {
|
|
||||||
position: fixed;
|
|
||||||
top: 20vh;
|
|
||||||
left: @padding-page;
|
|
||||||
background: white;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
border-radius: .6rem;
|
|
||||||
justify-content: center;
|
|
||||||
flex-direction: column;
|
|
||||||
color: #14BF5F;
|
|
||||||
padding: 1rem;
|
|
||||||
|
|
||||||
img {
|
|
||||||
width: 3rem;
|
|
||||||
margin-bottom: .2rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
Loading…
Reference in New Issue
Block a user