Files
tra-app/src/pages/sparring/tip.vue
T

969 lines
28 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="sparring-detail max_page">
<view class="sparring-detail-loading" v-show="showLoading">
<view class="loading-img"></view>
</view>
<view class="sparring-detail-body">
<view class="top-box">
<view class="top-title">
<view class="back-icon" @click="goBack()"></view>
{{ detailInfo.traName }}
</view>
<view class="top-desc">内容由AI生成</view>
</view>
<scroll-view :class="[' body-content index-dialog-body', detailInfo.traInterTyp === '01' ? 'talking-type1' : '']" :scroll-y="true" refresher-default-style="none" :scroll-top="scrollTop" :show-scrollbar="false" :scroll-with-animation="false">
<view :class="['body-content-role', showRoleInfo ? '' : 'hide-info']">
<view :class="['role-title']">
<ImagePreview class="role-title-avatar" :src="detailInfo.ossAddr" :isCache="true"></ImagePreview>
<view class="role-title-info" @click="showRoleInfo = !showRoleInfo">
<view class="arrow-r-icon"></view>
<view class="role-name card-title">
<text class="card-title-name">{{ detailInfo.chaName }}</text>
<text class="card-title-age">{{ detailInfo.chaAge }}</text>
<text class="card-title-img">
<image class="card-title-icon" v-if="detailInfo.gender === 'm' || detailInfo.gender === '01'" src="@/static/images/me/man.png"></image>
<image class="card-title-icon" v-if="detailInfo.gender === 'f' || detailInfo.gender === '02'" src="@/static/images/me/wuman.png"></image>
</text>
</view>
<view class="role-desc"> 预计时长 {{ detailInfo.traStartLimit }} ~ {{ detailInfo.traEndLimit }} 分钟 </view>
</view>
</view>
<view class="role-content">
<view class="role-content-item">
<!-- 身份情况 -->
{{ detailInfo.occupation }}
</view>
<view class="role-content-item">
<!-- 性格特点 -->
{{ detailInfo.personality }}
</view>
<view class="role-content-item">
<!-- 提问思路 -->
{{ detailInfo.thoughtProcess }}
</view>
<view class="role-content-item">
<!-- 人物描述 -->
{{ detailInfo.chaDesc }}
</view>
</view>
</view>
<view class="body-scene">
<view class="body-scene-title">场景描述</view>
<!-- sceneDesc -->
{{ detailInfo.sceneDesc }}
</view>
<view class="talking-desc"> 陪练角色不具备主动终止场景陪练的功能当用户完成预设陪练目标时需由用户手动发起结束陪练操作 </view>
<view class="talking-box" v-if="detailInfo.traInterTyp !== '01'">
<view class="tip-text">-请点击下方按钮开始{{ detailInfo.traInterTypDesc }}</view>
</view>
<view class="talking-box" v-else>
<TalkingItem
v-for="(item, index) in talkingList"
:talkingType="item.type"
:talkingInfo="item"
:roleInfo="detailInfo"
:traId="traId"
:execId="execId"
:isExam="talkingType === '02'"
:isLast="index + 1 === talkingList.length"
:isAnswering="!answerIsOver"
:activeVoiceId="activeVoiceTalkingItemId"
@handleEvents="talkItemEvents"></TalkingItem>
</view>
</scroll-view>
<view class="over-btn-box" v-if="detailInfo.traInterTyp === '01'">
<view class="over-btn" @click="overTalking">结束陪练</view>
</view>
<TouchBtn class="body-bottom" @uploadVoice="uploadRecordNow" @startRecord="changePlayItemId('')" formatType="wav" :isLoading="!answerIsOver" :isDisabled="false" v-if="detailInfo.traInterTyp === '01'" />
<view class="body-bottom" v-else>
<view class="body-bottom-btn" @click="beforeToTalking">
<view class="center-text">
<image class="type-icon" src="@/static/images/sparring/video-icon.png" v-if="detailInfo.traInterTyp === '03'"></image>
<image class="type-icon" src="@/static/images/sparring/phone-icon.png" v-else-if="detailInfo.traInterTyp === '02'"></image>
<image v-else class="type-icon" src="@/static/images/sparring/talk-icon.png"></image>
{{ detailInfo.traInterTypDesc }}
</view>
</view>
</view>
</view>
<badge ref="badgeRef"></badge>
<points ref="pointsRef"></points>
</view>
</template>
<script setup>
import { ref, unref, onMounted, computed, nextTick } from 'vue'
import { onShow, onHide, onLoad, onUnload, onLaunch, onBackPress } from '@dcloudio/uni-app'
import common from '@/common/common'
import { getPhoneEnvBool } from '@/common/common'
import TouchBtn from './components/touchBtn.vue'
import ImagePreview from '@/components/image-preview/image-preview.vue'
import { commonUploadVoiceFile } from '@/api/common.js'
import { queryTraPartnerCharacterInfoById, partnerChatReportTrigger, checkTraPartnerInfoById } from '@/api/sparring.js'
import { useSocketStore } from '@/store/socket.js'
import { useStorageStore } from '@/store/storage.js'
import { storeToRefs } from 'pinia'
import TalkingItem from './components/talking-item.vue'
import badge from '@/components/points-and-badge/badge'
import points from '@/components/points-and-badge/points'
import usePointsAndBadge from '@/components/points-and-badge/usePointsAndBadge'
import { initRecord } from '@/composables/useExamSubject.js'
import permissionApi from '@/common/permission'
const { pointAndBadgesRun, badgeRef, pointsRef } = usePointsAndBadge()
const socketStore = useSocketStore()
const { SocketObj } = storeToRefs(socketStore)
const traId = ref('')
const chaId = ref('')
const talkingType = ref('')
// const badgeRef = ref(null);
// const pointsRef = ref(null);
const isPreview = ref(false)
const detailInfo = ref({})
const currentIndex = ref(0)
const showRoleInfo = ref(false)
const showLoading = ref(true)
const talkingList = ref([])
// {
// type: 'answer',
// talkingText: 'asad我是回答内容',
// isLoading: false,
// id: new Date().getTime(),
// },
const askData = ref({})
const execId = ref('')
const answerIsOver = ref(true)
const getDetailInfo = () => {
queryTraPartnerCharacterInfoById({
traId: traId.value,
chaId: chaId.value
}).then(res => {
console.log(res)
detailInfo.value = {
...res.body
}
if (detailInfo.value.traInterTyp === '01') {
initsocketTask()
}
setTimeout(() => {
showLoading.value = false
}, Math.random() * 1000 + 500)
})
}
const scrollTop = ref(99999)
const scrollToBottomNow = (time = 100) => {
nextTick(() => {
setTimeout(() => {
scrollTop.value += 100
scrollTop.value += 100
}, time)
})
}
const uploadRecordNow = (voicePath, voiceTime) => {
console.log(voicePath, voiceTime)
if (!execId.value) {
common.show('提示', '网络连接失败,请重新加载', false).then(res => {
if (res) {
common.redirectTo('/pages/sparring/tip?traId=' + traId.value + '&chaId=' + chaId.value + '&type=' + talkingType.value + '&isPreview=' + (isPreview.value ? '1' : ''))
}
})
return
}
//#ifndef APP-PLUS
// h5 假数据
// #endif
//#ifdef APP-PLUS
talkingList.value.push({
type: 'question',
talkingText: '',
isLoading: true
})
scrollToBottomNow()
// 设为提问中状态
answerIsOver.value = false
commonUploadVoiceFile(voicePath, '/trapractice/traPartnerChat/voiceTrans', {})
.then(_res => {
if (!!(_res.body.transContent || '').trim()) {
askData.value = {
execId: execId.value,
intrctWay: '02', //01-文本;02-语音;03-图片
intrctContent: _res.body.transContent,
fileId: _res.body.fileId,
ossFileAddr: _res.body.ossFileAddr,
talkingVoice: voicePath,
voiceTime: voiceTime
}
sendMessage({
commond: 'ASK',
body: askData.value
})
} else {
answerIsOver.value = true
talkingList.value.pop()
uni.showToast({
title: '未识别到文字',
icon: 'none',
duration: 1000
})
}
})
.catch(err => {
answerIsOver.value = true
talkingList.value.pop()
uni.showToast({
title: err?.message || '网络异常,请联系管理员',
icon: 'none',
duration: 1000
})
})
// #endif
}
const beforeToTalking = () => {
if (isPreview.value) {
toTalking()
return
}
checkTraPartnerInfoById({
traId: traId.value
}).then(res => {
if (res.body.inRange) {
toTalking()
} else {
common.show('提示', res.body.message, false)
}
})
}
const toTalking = async () => {
try {
//#ifdef APP-PLUS
console.log('申请权限')
try {
await permissionApi.judgeIosPermission('record')
if (detailInfo.value.traInterTyp === '03') {
await permissionApi.judgeIosPermission('camera')
}
} catch (e) {
console.error('摄像头或者麦克风权限申请失败:', e)
return
}
//#endif
common.setPageCache('tipMsgsceneDesc', {
ossAddr: detailInfo.value.ossAddr,
chaName: detailInfo.value.chaName,
traInterTyp: detailInfo.value.traInterTyp,
traInterTypDesc: detailInfo.value.traInterTypDesc
})
let _gotUrl
if (detailInfo.value.traInterTyp === '02') {
_gotUrl = '/pages/sparring/talk'
} else if (detailInfo.value.traInterTyp === '03') {
_gotUrl = '/pages/sparring/talk' // 没改好,暂时跳到一个页
}
common.redirectTo(_gotUrl + '?traId=' + traId.value + '&chaId=' + chaId.value + '&type=' + talkingType.value + '&traInterTyp=' + detailInfo.value.traInterTyp + '&isPreview=' + (isPreview.value ? '1' : '0'))
} catch (err) {
console.error('申请权限失败')
}
}
const activeVoiceTalkingItemId = ref('')
// 关闭播放状态
const changePlayItemId = (id = '') => {
activeVoiceTalkingItemId.value = id
}
const talkItemEvents = ({ type, data, id, info = {} }) => {
switch (type) {
case 'changePlay':
activeVoiceTalkingItemId.value = id
break
case 'scrollToBottom':
scrollToBottomNow()
break
default:
break
}
}
const watchFlag = ref(1)
const showModelComfirm = ref(false)
const reconcatNum = ref(0)
const answerText = ref('')
const touchBtnCallBack = ref(null)
const stopAnswerCallBack = ref(false)
let isLeave = false
const initsocketTask = () => {
let _src = isPreview.value ? '/trapractice/previewsocket/open' : '/trapractice/partnersocket/open'
socketStore.creatSocket(_src + '?summary=')
// unref(SocketObj).on('open', (res)=>{
// if(!answerIsOver.value){
// sendMessage({
// "commond" : 'ASK-RE-START',
// "body" : {
// execId: execId.value,
// seqNo: seqNo.value,
// answerContent: answerText.value
// }
// })
// }
// })
unref(SocketObj).on('error', () => {
if (watchFlag.value === 1 || showModelComfirm.value) return
if (reconcatNum.value === 5) {
common.msg('系统网络异常,请稍后再试!')
common.reLaunch(`/pages/index/dialog`)
return
}
showModelComfirm.value = true
reconcatNum.value += 1
common
.show('提示信息', '网络环境不稳定,请重试!', false, '', '确认')
.then(res => {
overNow(() => {
reconcatNum.value += 1
// common.redirectTo(`/pages/index/dialog`);
socketStore?.closeSocket()
common.redirectTo('/pages/sparring/result?isOver=1&traId=' + traId.value + '&execId=' + execId.value + '&type=' + talkingType.value + '&isPreview=' + (isPreview.value ? '1' : ''))
})
})
.finally(() => {
showModelComfirm.value = false
})
})
unref(SocketObj).on('message', res => {
const { rtnCode, body, commond } = JSON.parse(res.data)
let _id = new Date().getTime() + 'id'
if (rtnCode === '0000') {
if (commond === 'ASK-OPEN') {
console.log('ASK-OPEN', body)
// 新连接
sendMessage({
commond: 'ASK-START',
body: {
traId: traId.value,
chaId: chaId.value,
traTyp: talkingType.value,
execId: execId.value || ''
}
})
sendMessage({
commond: 'ASK-PING',
body: {
execId: execId.value || ''
}
})
return
}
if (commond === 'ASK-START') {
console.log('开启对话!', body)
execId.value = body.execId
return
}
if (commond === 'ASK') {
console.log('发送问题成功!')
console.log(body)
console.log(talkingList.value[talkingList.value.length - 1].isLoading)
if (talkingList.value.length > 0 && talkingList.value[talkingList.value.length - 1].isLoading) {
talkingList.value = talkingList.value.filter(t => {
return !(t.type === 'question' && t.isLoading)
})
}
// seqNo.value = body.seqNo;
// touchBtnCallBack.value && touchBtnCallBack.value();
// touchBtnCallBack.value = null;
talkingList.value.push({
type: 'question',
talkingText: body.content,
isLoading: false,
intrctWay: '02',
id: _id + 'qns',
...body,
talkingVoice: askData.value.talkingVoice
})
talkingList.value.push({
type: 'answer',
isLoading: true,
id: _id + 'loading'
})
scrollToBottomNow()
return
}
if (commond === 'ASK-STOP') {
console.log('停止回答标记!')
stopAnswerCallBack.value && stopAnswerCallBack.value(askData.value)
setTimeout(() => {
stopAnswerCallBack.value = null
answerIsOver.value = true
}, 10)
return
}
if (commond === 'ASK-ANSWER') {
if (body.event === 'start') {
answerIsOver.value = false
answerText.value = ''
// talkingList.value.pop();
talkingList.value = talkingList.value.filter(t => {
return !(t.type === 'answer' && t.isLoading)
})
talkingList.value.push({
type: 'answer',
talkingText: answerText.value,
isLoading: false,
execLogId: body.execLogId || '',
id: _id + 'ans',
...body,
askData: {
...askData.value
}
})
} else if (body.event === 'token') {
answerIsOver.value = false
answerText.value += body.data
talkingList.value[talkingList.value.length - 1].talkingText = answerText.value
} else if (body.event === 'end') {
answerIsOver.value = true
} else if (body.event === 'recordAi') {
talkingList.value[talkingList.value.length - 1].execLogId = body.execLogId
}
scrollToBottomNow()
return
}
if (commond === 'ASK-RE-ANSWER') {
// console.log('开始继续回答!')
if (body.event === 'start') {
answerIsOver.value = false
answerText.value = ''
} else if (body.event === 'token') {
answerIsOver.value = false
answerText.value = body.data
} else if (body.event === 'end') {
answerIsOver.value = true
}
return
}
if (commond === 'ASK-ERR') {
console.log('提问失败,系统异常!')
return
}
if (commond === 'ASK-OVER') {
console.log(body)
console.log('陪练已结束,去结果页面!')
socketStore?.closeSocket()
common.redirectTo('/pages/sparring/result?isOver=1&traId=' + traId.value + '&execId=' + execId.value + '&type=' + talkingType.value + '&isPreview=' + (isPreview.value ? '1' : ''))
return
}
if (commond === 'ASK-PONG') {
console.log('PONG')
if (isLeave) return
setTimeout(() => {
sendMessage({
commond: 'ASK-PING',
body: {
execId: execId.value || ''
}
})
}, 30000)
}
} else {
if (['0005', 'QQ0005'].includes(res.rtnCode)) {
goto_login_fun()
}
}
})
watchFlag.value += 1
}
const goBack = () => {
console.log(222,detailInfo.value.traInterTyp === '01')
if (detailInfo.value.traInterTyp === '01') {
overTalking()
} else {
common.navigateBack()
}
}
const overTalking = () => {
if (!execId.value) {
common.show('提示', '网络连接失败,请重新加载', false).then(res => {
if (res) {
common.redirectTo('/pages/sparring/tip?traId=' + traId.value + '&chaId=' + chaId.value + '&type=' + talkingType.value + '&isPreview=' + (isPreview.value ? '1' : ''))
}
})
return
}
common.show('提示', '确定结束陪练吗?').then(res => {
if (res) {
overNow()
}
})
}
const overNow = (cb = () => {}) => {
watchFlag.value = 1
sendMessage({
commond: 'ASK-STOP',
body: {
execId: execId.value || ''
}
})
socketStore?.closeSocket()
changePlayItemId('')
common.redirectTo('/pages/sparring/result?isOver=1&traId=' + traId.value + '&execId=' + execId.value + '&type=' + talkingType.value + '&isPreview=' + (isPreview.value ? '1' : ''))
// partnerChatReportTrigger({
// execId: execId.value,
// traId: traId.value,
// talkingType: isPreview.value ? 'preview' : 'practice'
// })
// .then(res => {
// watchFlag.value = 1
// sendMessage({
// commond: 'ASK-STOP',
// body: {
// execId: execId.value || ''
// }
// })
// socketStore?.closeSocket()
// changePlayItemId('')
// common.redirectTo('/pages/sparring/result?isOver=1&traId=' + traId.value + '&execId=' + execId.value + '&type=' + talkingType.value + '&isPreview=' + (isPreview.value ? '1' : ''))
// })
// .catch(() => {
// cb()
// })
}
const sendMessage = data => {
unref(SocketObj).send(data)
if (data.commond == 'ASK-PING') {
console.log('PING')
}
}
// let timer = null
//#ifdef APP-PLUS
onShow(() => {
isLeave = false
// timer = setInterval(() => {
// sendMessage({
// commond: 'ASK-PING',
// body: {
// execId: execId.value || ''
// }
// }, 1000)
// })
})
onHide(() => {
isLeave = true
// clearInterval(timer)
// timer = null
})
// #endif
onLoad(params => {
execId.value = ''
traId.value = params.traId
chaId.value = params.chaId
talkingType.value = params.type
isPreview.value = params.isPreview === '1'
getDetailInfo()
console.log('onLoad')
//#ifdef APP-PLUS
plus.screen.lockOrientation('portrait-primary')
// #endif
})
onUnload(() => {
console.log('onUnload')
watchFlag.value = 1
sendMessage({
commond: 'ASK-STOP',
body: {
execId: execId.value || ''
}
})
if (detailInfo.value.traInterTyp === '01') {
socketStore?.closeSocket()
}
execId.value = ''
})
onLaunch(() => {
console.log('onLaunch')
})
onMounted(() => {
// getDetailInfo()
})
onBackPress(res => {
console.log(1111)
if (res.from === 'backbutton') {
goBack()
return true
}
})
</script>
<style lang="scss" scoped>
.sparring-detail {
position: relative;
overflow-x: hidden;
overflow-y: auto;
flex-direction: column;
background-image: url(@/static/images/sparring/bg.png);
background-size: cover;
// background-color: #f2f6fd;
.sparring-detail-loading {
position: fixed;
z-index: 20;
height: 100vh;
width: 100vw;
background-image: url(@/static/images/sparring/bg.png);
.loading-img {
position: absolute;
width: 380rpx;
height: 590rpx;
top: 40%;
transform: translateY(-50%) translateX(-50%);
left: 50%;
padding-top: 540rpx;
line-height: 50rpx;
box-sizing: border-box;
text-align: center;
background-image: url(@/static/images/sparring/waiting.png);
background-repeat: no-repeat;
background-size: cover;
}
}
.sparring-detail-body {
position: absolute;
overflow-x: hidden;
overflow-y: hidden;
left: 0;
top: 0;
height: 100vh;
width: 100%;
box-sizing: border-box;
// background-color: #f6f8ff;
z-index: 1;
padding: calc(var(--status-bar-height) + 90rpx) 0 180rpx;
.top-box {
height: 90rpx;
width: 100%;
position: fixed;
top: var(--status-bar-height);
left: 0;
z-index: 2;
.top-desc {
position: absolute;
bottom: 0;
font-size: 18rpx;
color: #999;
left: 50%;
transform: translateX(-50%);
}
.top-title {
height: 90rpx;
// background-color: red;
text-align: center;
font-size: 33rpx;
padding: 10rpx 100rpx 0;
line-height: 46rpx;
box-sizing: border-box;
font-weight: 500;
color: #000;
position: relative;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
// margin-bottom: 23rpx;
.arrow-icon {
position: absolute;
left: 36rpx;
top: 20rpx;
color: #fff !important;
}
.back-icon {
position: absolute;
width: 40rpx;
height: 40rpx;
cursor: pointer;
left: 50rpx;
top: 33rpx;
transform: translateY(-50%);
}
.back-icon::before,
.back-icon::after {
content: '';
position: absolute;
transition: all 0.3s ease;
}
.back-icon::after {
top: 25%;
left: 25%;
width: 40%;
height: 40%;
border-top: 4rpx solid #000;
border-left: 4rpx solid #000;
transform: rotate(-45deg);
}
}
}
.body-content {
height: 100%;
padding: 10rpx 24rpx 20rpx;
box-sizing: border-box;
overflow-y: auto;
&.talking-type1 {
padding: 10rpx 24rpx 140rpx;
}
.body-content-role {
background-color: #fff;
border-radius: 16rpx;
overflow: hidden;
margin-bottom: 30rpx;
&.hide-info {
.arrow-r-icon::after {
transform: rotate(225deg) !important;
}
.role-content {
max-height: 0rpx !important;
padding-bottom: 0rpx !important;
}
}
.role-title {
min-height: 154rpx;
position: relative;
padding-left: 180rpx;
&-avatar {
width: 92rpx;
height: 92rpx;
position: absolute;
top: 50%;
left: 42rpx;
transform: translateY(-50%);
border-radius: 50%;
overflow: hidden;
}
&-info {
position: relative;
min-height: 154rpx;
box-sizing: border-box;
// padding-top: 34rpx;
padding: 16rpx 0;
display: flex;
flex-direction: column;
justify-content: space-evenly;
.role-name {
width: 100%;
&.card-title {
display: flex;
font-size: 29rpx;
line-height: 44rpx;
font-weight: 500;
color: #000;
overflow: hidden;
text-align: left;
justify-content: start;
margin-bottom: 8rpx;
.card-title-name {
margin-right: 20rpx;
line-height: 44rpx;
max-width: 300rpx;
}
.card-title-age {
margin-right: 20rpx;
line-height: 44rpx;
}
.card-title-img {
height: 44rpx;
width: 30rpx;
padding: 5rpx 0;
box-sizing: border-box;
}
.card-title-icon {
height: 30rpx;
width: 30rpx;
}
}
}
.role-desc {
width: 100%;
font-size: 25rpx;
color: #666;
}
.arrow-r-icon {
position: absolute;
width: 36rpx;
height: 36rpx;
cursor: pointer;
right: 50rpx;
top: 50%;
transform: translateY(-50%);
}
.arrow-r-icon::before,
.arrow-r-icon::after {
content: '';
position: absolute;
transition: all 0.3s ease;
}
.arrow-r-icon::after {
top: 25%;
left: 25%;
width: 40%;
height: 40%;
border-top: 2rpx solid #000;
border-left: 2rpx solid #000;
transform: rotate(135deg);
}
}
}
.role-content {
max-height: 800rpx;
transition: all 0.3s ease;
padding-bottom: 12rpx;
&-item {
position: relative;
padding: 8rpx 46rpx 8rpx 76rpx;
line-height: 42rpx;
font-size: 29rpx;
&::before {
content: '';
display: block;
background-color: #000;
width: 12rpx;
height: 12rpx;
border-radius: 50%;
position: absolute;
left: 46rpx;
top: 22rpx;
}
}
}
}
.body-scene {
background: linear-gradient(209deg, #fefeff 0%, #d7dfff 100%);
border: 2rpx solid rgba(255, 255, 255, 0.65);
position: relative;
line-height: 42rpx;
font-size: 29rpx;
border-radius: 16rpx;
overflow: hidden;
padding: 108rpx 46rpx 30rpx;
.body-scene-title {
position: absolute;
left: 0;
top: 0;
background-color: #06f;
border-radius: 0 0 36rpx 0;
width: 170rpx;
height: 78rpx;
line-height: 78rpx;
color: #fff;
text-align: center;
}
}
.talking-desc {
// padding-top: 24rpx;
padding: 24rpx 20rpx 0;
font-size: 24rpx;
// text-align: center;
color: #999;
}
.talking-box {
padding-top: 24rpx;
.tip-text {
color: #7295cb;
text-align: center;
font-size: 29rpx;
}
}
}
.over-btn-box {
position: absolute;
bottom: 180rpx;
height: 140rpx;
padding: 0 23rpx;
width: 100%;
.over-btn {
float: right;
width: 194rpx;
height: 76rpx;
line-height: 72rpx;
border: 2rpx solid #06f;
border-radius: 15rpx;
text-align: center;
color: #06f;
margin-top: 34rpx;
}
}
.body-bottom {
height: 180rpx;
background-color: #fff;
padding: 36rpx 23rpx 0;
position: fixed;
width: 100vw;
bottom: 0;
left: 0;
&-btn {
width: 100%;
height: 92rpx;
line-height: 92rpx;
background-color: #06f;
text-align: center;
color: #fff;
font-size: 29rpx;
border-radius: 23rpx;
position: relative;
.center-text {
height: 35rpx;
line-height: 35rpx;
width: 100%;
position: absolute;
top: 50%;
transform: translateY(-50%);
display: flex;
justify-content: center;
}
.type-icon {
width: 35rpx;
height: 35rpx;
margin-right: 10rpx;
}
}
}
}
}
</style>