Files
tra-app/src/pages/index/dialog.vue
T
2025-09-08 11:13:48 +08:00

963 lines
27 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="index-dialog-page">
<!-- <MarkdownPreview/> -->
<view class="top-bg"></view>
<view class="bot-bg"></view>
<scroll-view class="index-dialog-body" :scroll-y="true" upper-threshold="0" refresher-enabled="true" refresher-default-style="none" @refresherrefresh="scrolltolower">
<view class="body-title">
<!-- <uv-icon class="arrow-icon" name="arrow-left" @click="common.navigateBack()"/> -->
AI问答
<view class="seek-setting">
<image src="@/static/images/dialog/new-dialog.png" alt="" class="image-icon-new" @click="createNewDialog"> </image>
<image src="@/static/images/dialog/history.png" alt="" class="image-icon" @click="showMenuList = !showMenuList"></image>
<view :class="['more-list', showMenuList ? 'show' : '']">
<view class="more-item" @click.stop="showHistory">历史</view>
<view class="more-item" @click.stop="toMessage">消息</view>
<view class="more-item" @click.stop="toMePage">我的</view>
</view>
</view>
</view>
<view class="ai-info">
<!-- <image src="@/static/images/dialog/pet-3.png" alt="" class="image-pet-bg"></image> -->
<image src="@/static/images/dialog/pet-bg-base.png" alt="" class="image-pet-bg"></image>
<image :src="userInfo?.mascotInfo?.imgAddr || ''" alt="" class="image-pet" mode="widthFix"></image>
<view class="ai-info-bg-box">
<view class="hello-text">{{ userInfo ? 'Hi,我是' + userInfo?.mascotInfo?.mascotName : 'Hi' }}</view>
<view class="info-text">工作学习我都能帮你</view>
<view class="info-btn">试试他的能力</view>
</view>
</view>
<view class="questions-view">
<scroll-view :scroll-x="true" :show-scrollbar="false">
<view class="question-row">
<view class="question-item" v-for="item in Math.ceil(questionList.length / 2)" @click="sendText(questionList[item - 1].hotContent)">{{ questionList[item - 1].hotContent }} </view>
</view>
<view class="question-row">
<view class="question-item" v-for="item in questionList.length - Math.ceil(questionList.length / 2)" @click="sendText(questionList[item + Math.ceil(questionList.length / 2) - 1].hotContent)">
{{ questionList[item + Math.ceil(questionList.length / 2) - 1].hotContent }}
</view>
</view>
</scroll-view>
</view>
<view class="talking-list">
<scroll-view class="talking-scroll-list" :scroll-y="true" :scroll-top="scrollTop" :show-scrollbar="false" :scroll-with-animation="false">
<TalkingItem v-for="(item, index) in talkingList" :talkingType="item.type" :talkingInfo="item" :isLast="index + 1 === talkingList.length" :isAnswering="!answerIsOver" :activeVoiceId="activeVoiceTalkingItemId" @handleEvents="talkItemEvents"> </TalkingItem>
</scroll-view>
</view>
<view class="router-list">
<scroll-view class="" :scroll-x="true" :show-scrollbar="false">
<view class="btns-item" @click="routerTo('AI学')">
<image src="@/static/images/dialog/icons/study.png" alt="" class="image-icon"></image>
{{ 'AI学' }}
</view>
<view class="btns-item" @click="routerTo('AI练')">
<image src="@/static/images/dialog/icons/test.png" alt="" class="image-icon"></image>
{{ 'AI练' }}
</view>
<view class="btns-item" @click="routerTo('AI考')">
<image src="@/static/images/dialog/icons/exam.png" alt="" class="image-icon"></image>
{{ 'AI考' }}
</view>
<view class="btns-item" @click="routerTo('去PK')">
<image src="@/static/images/dialog/icons/PK.png" alt="" class="image-icon"></image>
{{ '去PK' }}
</view>
<view class="btns-item" @click="routerTo('任务')">
<image src="@/static/images/dialog/icons/task.png" alt="" class="image-icon"></image>
{{ '任务' }}
</view>
<view class="btns-item" @click="routerTo('错题')">
<image src="@/static/images/dialog/icons/wrong.png" alt="" class="image-icon"></image>
{{ '错题' }}
</view>
<view class="btns-item" @click="routerTo('分析')">
<image src="@/static/images/dialog/icons/static.png" alt="" class="image-icon"></image>
{{ '分析' }}
</view>
</scroll-view>
</view>
<TouchBtn class="talk-btns" @uploadVoice="uploadRecordNow" @submitAnswer="submitAnswerNow" @startRecord="startRecordCallback" :loadingText="sendLoadingText" :isLoading="!answerIsOver" :adjustPosition="true" :isDisabled="isHistory" />
<History ref="historyRef" @showDetail="showHistoryDetail"></History>
<PreviewVue ref="previewRef" />
</scroll-view>
</view>
<!-- 反馈组件 -->
<Feedback ref="feedbackRef" @feedbackAnswer="feedbackAnswer"></Feedback>
<!-- <file-preview ref="previewFileRef" :file-id="'603058d8-88e0-43d2-8242-3132b85bc91c'" v-model="showPreview" /> -->
</template>
<script setup>
import { ref, unref, onMounted, watch, nextTick, computed, onActivated } from 'vue'
import common from '@/common/common'
import { setupKeyboardHeightListener } from '@/common/common'
import TouchBtn from '@/pages/course/components/touchBtn.vue'
import TalkingItem from './components/talking-item.vue'
import PreviewVue from './components/preview.vue'
import { useSocketStore } from '@/store/socket.js'
import { useStorageStore } from '@/store/storage.js'
import { storeToRefs } from 'pinia'
import { onLoad, onShow, onUnload, onHide, onBackPress } from '@dcloudio/uni-app'
import { get_base_url, goto_login_fun } from '@/api/request'
import { getUserInfo } from '@/common/common'
import { commonUploadVoiceFile } from '@/api/common.js'
import { queryHotQuestionApi, insertTraAskFeedback, queryAskHisByBatchIdPaging, updateLikeStat } from '@/api/dialog.js'
import Feedback from './components/feedback.vue'
import History from './components/history.vue'
const { statusBarHeight } = uni.getWindowInfo()
const pageTopPadding = computed(() => statusBarHeight + 'px')
const socketStore = useSocketStore()
const { SocketObj } = storeToRefs(socketStore)
const feedbackRef = ref()
const userInfo = ref(getUserInfo())
const questionList = ref([
// '对公小程序开户流程?',
// '厅堂服务经理2025年管理办法?',
// '厅堂服务经理2025年考核表单?',
// '吉林银行重要空白凭证调微业务操作规程?',
// '协助有权机关查询冻结扣划业务操作规程?',
// '柜面个人账户操作规程?',
// '久悬未取款账户如何办理销户?',
// '境外来华人员个人账户业务开户如何办理?',
// '营业机构日间管理风险防控要点有哪些?',
// '现金管理平台柜面业务操作?'
])
const scrollBoxRef = ref()
const scrollTop = ref(99999)
const scrollToBottomNow = (time = 100) => {
nextTick(() => {
setTimeout(() => {
scrollTop.value += 100
scrollTop.value += 100
}, time)
})
}
const activeVoiceTalkingItemId = ref('')
// ws 初始化逻辑
const reconnectTimer = null // 重连timer
const isManualClose = ref(false) // 是否手动关闭
const reqBatch = ref('')
const seqNo = ref('')
const mascotId = computed(() => {
return unref(userInfo)?.mascotInfo?.mascotId || 'Tst00001'
})
const answerText = ref('')
const answerFileList = ref('')
const answerIsOver = ref(true)
const talkingList = ref([])
const createNewDialog = () => {
if (talkingList.value.length === 0) {
common.msg('已经是最新对话')
}
common.redirectTo(`/pages/index/dialog`)
}
const showModelComfirm = ref(false)
const reconcatNum = ref(1)
const initsocketTask = () => {
isHistory.value = false
socketStore.creatSocket('/traask/asksocket/open?summary=')
// unref(SocketObj).on('open', (res)=>{
// if(!answerIsOver.value){
// sendMessage({
// "commond" : 'ASK-RE-START',
// "body" : {
// reqBatch: reqBatch.value,
// seqNo: seqNo.value,
// answerContent: answerText.value
// }
// })
// }
// })
unref(SocketObj).on('error', () => {
if (watchFlag.value === 1 || showModelComfirm.value) return
if (reconcatNum.value === 5) {
common.msg('系统网络异常,请稍后再试!')
return
}
showModelComfirm.value = true
common
.show('提示信息', '网络环境不稳定,请重试!', false, '', '确认')
.then(res => {
reconcatNum.value += 1
common.redirectTo(`/pages/index/dialog`)
})
.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') {
if (!answerIsOver.value) {
// 问题没完成, 重新尝试回答
sendMessage({
commond: 'ASK-RE-START',
body: {
reqBatch: reqBatch.value,
seqNo: seqNo.value,
answerContent: answerText.value
}
})
} else {
// 新连接
sendMessage({
commond: 'ASK-START',
body: {
mascotId: mascotId.value,
deviceImei: ''
}
})
}
return
}
if (commond === 'ASK-START') {
// console.log('开启对话!')
reqBatch.value = body.reqBatch
return
}
if (commond === 'ASK') {
console.log('发送问题成功!')
if (talkingList.value.length > 0 && talkingList.value[talkingList.value.length - 1].isLoading) {
talkingList.value.pop()
}
seqNo.value = body.seqNo
touchBtnCallBack.value && touchBtnCallBack.value()
touchBtnCallBack.value = null
talkingList.value.push({
type: 'question',
talkingText: body.intrctContent,
isLoading: false,
id: _id,
...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') {
console.log('开始回答!')
answerIsOver.value = false
answerText.value = ''
talkingList.value.pop()
talkingList.value.push({
type: 'answer',
talkingText: answerText.value,
isLoading: false,
id: _id,
...body,
askData: {
...askData.value
},
talkingFiles: [],
talkingCrsList: []
})
} else if (body.event === 'token') {
answerIsOver.value = false
answerText.value += body.data
} else if (body.event === 'end') {
console.log('完成回答!')
answerIsOver.value = true
} else if (body.event === 'sourceDocuments') {
console.log('回答返回文件列表!')
console.log('body: ', body)
if (talkingList.value.length === 0) return
let _data = body.data
talkingList.value[talkingList.value.length - 1].talkingFiles = _data.knowledgeList || []
talkingList.value[talkingList.value.length - 1].talkingCrsList = _data.crsList || []
}
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
}
} else {
if (['0005', 'QQ0005'].includes(res.rtnCode)) {
goto_login_fun()
}
}
})
watchFlag.value += 1
}
const sendLoadingText = ref('问题回答中,请在问题回答结束后重试!')
const reconnect = () => {
if (reconnectTimer || isManualClose.value) return
reconnectTimer = setTimeout(() => {
initsocketTask()
}, 3000)
}
const sendMessage = data => {
unref(SocketObj).send(data)
}
watch(
() => answerText.value,
val => {
if (val) {
changeText(val)
scrollToBottomNow()
}
}
)
const changeText = () => {
if (talkingList.value.length === 0) return
talkingList.value[talkingList.value.length - 1].talkingText = answerText.value
}
const stopAnswerCallBack = ref(null)
const talkItemEvents = ({ type, data, id, info = {} }) => {
switch (type) {
case 'reAnswer':
console.log('重新提问回答')
// 停止获取
sendMessage({
commond: 'ASK-STOP',
body: {
reqBatch: reqBatch.value,
seqNo: seqNo.value
}
})
sendMessage({
commond: 'ASK',
body: data.askData
})
// // 设置停止回调
// stopAnswerCallBack.value = ($data) => {
// sendMessage({
// "commond": 'ASK',
// "body": $data
// })
// }
break
case 'stop':
console.log('停止获取数据')
stopAnswerCallBack.value = null
// ASK-STOP
sendMessage({
commond: 'ASK-STOP',
body: {
reqBatch: reqBatch.value,
seqNo: seqNo.value
}
})
break
case 'changePlay':
activeVoiceTalkingItemId.value = id
break
case 'feedback':
feedbackRef.value.open(data)
break
case 'great':
let _status = data.likeStat === 'Y' ? 'N' : 'Y'
let _id = data.seqNo || data.askId
updateLikeStat({
askId: _id,
stat: _status
}).then(res => {
talkingList.value.forEach(t => {
if (t.seqNo === _id || t.askId === _id) {
t.likeStat = _status
if(_status === 'Y'){
t.downvoteStat = 'N'
}
}
})
})
break
case 'preview':
common.navigateTo('/pages/index/preview?fileId=' + info.docId)
break
case 'toCourse':
console.log(type, data, id)
break
default:
break
}
}
const feedbackAnswer = params => {
talkingList.value.forEach(t => {
if (t.seqNo === params.askId) {
t.downvoteStat = 'Y'
t.likeStat = 'N'
}
})
}
const historyRef = ref(null)
const showMenuList = ref(false)
const showHistory = () => {
showMenuList.value = false
historyRef.value.open()
}
const toMessage = () => {
showMenuList.value = false
common.navigateTo('/pages/messageNotification/index')
}
const toMePage = () => {
showMenuList.value = false
common.switchTab('/pages/me/index')
}
const isHistory = ref(false)
const showHistoryDetail = item => {
isHistory.value = true
queryAskHisByBatchIdPaging({
batchId: item.reqBatch,
page: 1,
limit: 100
}).then(res => {
talkingList.value = (res.body || []).map((t, index) => {
// let _obj = JSON.parse( t.respContent)
// console.log(_obj,0)
// if(t.chatRole === 'TCH'){
// console.log(JSON.parse(_obj),1)
// }
let _text
let _talkingCrsList
let _talkingFiles
if (t.chatRole === 'TCH') {
_text = t.respContentVo?.messageBuileder || ''
_talkingCrsList = t.respContentVo?.resultMap?.crsList || []
_talkingFiles = t.respContentVo?.resultMap?.knowledgeList || []
} else {
_text = t.respContent
}
return {
type: t.chatRole === 'TCH' ? 'answer' : 'question',
talkingText: _text,
isLoading: false,
askId: t.askId,
seqNo: t.askId,
id: t.askId + index,
talkingVoice: '',
reqBatch: item.reqBatch,
intrctWay: '01', //01-文本;02-语音;03-图片
intrctContent: _text,
bucketKey: '',
downvoteStat: t.downvoteStat,
likeStat: t.likeStat,
talkingCrsList: _talkingCrsList,
talkingFiles: _talkingFiles,
isHistory: true
}
})
historyRef.value.close()
})
}
const routerTo = type => {
switch (type) {
case 'AI学':
common.switchTab('/pages/course/index')
break
case 'AI考':
common.navigateTo('/pages/testingHall/index')
break
case '任务':
common.navigateTo('/pages/learningTasks/index')
break
case '错题':
common.navigateTo('/pages/wrongQuestionRecord/index')
break
default:
common.msg('页面建设中,敬请期待!')
break
}
}
const scrolltolower = () => {
const pages = getCurrentPages()
const pageCount = pages?.length || 0
// 处理页面数量不足的情况,此为调试时候异常情况
if (pageCount <= 1) {
common.switchTab('/pages/index/index')
return
}
const prevPage = pages[pageCount - 2] // 获取上一页实例并验证
// 根据上一页路由决定跳转方式
if (prevPage.route === 'pages/login/login') {
// 登录页特殊处理,如果刚好等于2说明书刚启动,里面只有登录页和当前页,这样直接返回老首页
pageCount === 2 ? common.switchTab('/pages/index/index') : common.navigateBack(2)
} else {
// 普通页面返回上一页
common.navigateBack()
}
}
const touchBtnCallBack = ref(null)
const askData = ref({})
const sendText = item => {
submitAnswerNow(item)
}
// 发送语音
const uploadRecordNow = voicePath => {
// /traask/traAskchat/voiceTrans
//#ifndef APP-PLUS
// h5 假数据
// #endif
//#ifdef APP-PLUS
talkingList.value.push({
type: 'question',
talkingText: '',
isLoading: true
})
scrollToBottomNow()
commonUploadVoiceFile(voicePath, '/traask/traAskchat/voiceTrans', {})
.then(res => {
let _res = JSON.parse(res.data)
if (_res.rtnCode === '0000') {
if (!!(_res.body.transContent || '').trim()) {
askData.value = {
reqBatch: reqBatch.value,
intrctWay: '02', //01-文本;02-语音;03-图片
intrctContent: _res.body.transContent,
bucketKey: _res.body.fileId,
ossFileAddr: _res.body.ossFileAddr,
talkingVoice: voicePath
}
sendMessage({
commond: 'ASK',
body: askData.value
})
} else {
talkingList.value.pop()
uni.showToast({
title: '未识别到文字',
icon: 'none',
duration: 1000
})
}
} else {
}
})
.catch(err => {
talkingList.value.pop()
uni.showToast({
title: '系统异常,请联系管理员',
icon: 'none',
duration: 1000
})
})
// #endif
}
// 发送文本
const submitAnswerNow = (val, cb = null) => {
if (!answerIsOver.value) {
// 问题回答中
return
}
touchBtnCallBack.value = cb
askData.value = {
reqBatch: reqBatch.value,
intrctWay: '01', //01-文本;02-语音;03-图片
intrctContent: val,
bucketKey: ''
}
sendMessage({
commond: 'ASK',
body: askData.value
})
}
const startRecordCallback = () => {
// 开始录音回调
}
const watchFlag = ref(1)
onBackPress(options => {
const from = options.from
if (from === 'backbutton') {
// 判断上一级是否是登录,是登录就返回两层跳过登录页
const pages = getCurrentPages()
if (pages && pages.length > 1) {
const page = pages[pages.length - 2]
if (page.route === 'pages/login/login') {
if (pages.length == 2) {
common.switchTab('/pages/index/index')
} else {
common.navigateBack(2)
}
return true
}
}
}
return false
})
const getQuestionList = () => {
queryHotQuestionApi().then(res => {
console.log(res)
questionList.value = res.body
.map(t => {
return {
...t,
hotContent: t.refineContent
}
})
.filter(t => t.refineContent)
})
}
const loadData = async () => {
userInfo.value = getUserInfo()
getQuestionList()
initsocketTask()
}
onLoad(() => {
changeAppHeightBottom()
if (!common.isLogin()) {
common.navigateTo('/pages/login/login')
return
}
// 判断下如果没有设置吉祥物就跳转到吉祥物页面
if (userInfo.value?.mascotInfo.mascotId === null) {
//说明这人在上次选吉祥物的时候退出了,没有选到吉祥物
common.redirectTo('/pages/mascot/mascot_select_list')
return
}
loadData()
})
const previewRef = ref()
const previewFileRef = ref()
const showPreview = ref(false)
onMounted(() => {
// previewFileRef.value.open({
// fileId: '0006e7f7-a332-4c81-9802-ac4e2d971c71'
// })
})
const refreshData = () => {
loadData()
}
const keyboardHeight = ref('0px')
const setHeight = res => {
keyboardHeight.value = (res.height || 0) + 'px'
}
const keyBoardIsHide = computed(() => {
return parseInt(keyboardHeight.value) == 0
})
const bottomHeight = ref('0px')
const totalBotHeight = computed(() => {
return keyBoardIsHide.value ? 0 + 'px' : parseInt(keyboardHeight.value) - parseInt(bottomHeight.value) + 'px'
})
const changeAppHeightBottom = height => {
//#ifdef APP-PLUS
// 获取系统信息
const systemInfo = uni.getSystemInfoSync()
// 计算安全区域底部高度
bottomHeight.value = systemInfo.screenHeight - systemInfo.safeArea.bottom + 'px'
// #endif
}
//#ifdef APP-PLUS
onHide(() => {
uni.offKeyboardHeightChange(setHeight)
})
onShow(() => {
uni.onKeyboardHeightChange(setHeight)
})
// #endif
onUnload(() => {
watchFlag.value = 1
socketStore?.closeSocket()
// setupKeyboardHeightListener(changeAppHeightBottom)
})
defineExpose({
refreshData
})
</script>
<style scoped lang="scss">
.index-dialog-page {
position: relative;
display: flex;
flex-direction: column;
height: 100vh;
overflow: hidden;
}
.top-bg {
background: linear-gradient(0deg, rgba(234, 246, 255, 0) 0%, #e6eafd 100%);
height: 480rpx;
width: 100%;
}
.bot-bg {
// background-color: #F6F8FF;
background: linear-gradient(136deg, rgba(234, 246, 255, 0) 0%, #fff 100%);
width: 100%;
flex: 1;
}
.index-dialog-body {
position: absolute;
overflow: hidden;
height: calc(100% - v-bind(totalBotHeight));
width: 100%;
padding: 0;
bottom: 0;
left: 0;
box-sizing: border-box;
padding-top: v-bind(pageTopPadding);
// padding-bottom: v-bind(bottomHeight);
// display: flex;
// flex-direction: column;
.body-title {
height: 90rpx;
text-align: center;
font-size: 33rpx;
padding-top: 20rpx;
line-height: 46rpx;
box-sizing: border-box;
font-weight: 500;
color: #000;
position: relative;
// margin-bottom: 23rpx;
.arrow-icon {
position: absolute;
left: 36rpx;
top: 30rpx;
color: #000;
}
}
.seek-setting {
position: absolute;
z-index: 13;
right: 45rpx;
top: 8rpx;
font-size: 26rpx;
width: 140rpx;
height: 52rpx;
padding: 10rpx 0;
// overflow: hidden;
line-height: 32rpx;
text-align: right;
padding-right: 48rpx;
.more-list {
position: absolute;
top: 100%;
right: 0;
width: 100rpx;
text-align: center;
background-color: #fff;
border-radius: 12rpx;
padding: 16rpx 0;
display: none;
z-index: 21;
&.show {
display: block;
}
.more-item {
line-height: 60rpx;
font-size: 29rpx;
color: #333;
position: relative;
z-index: 22;
}
}
.image-icon {
width: 30rpx;
height: 32rpx;
position: absolute;
right: 0;
top: 10rpx;
}
.image-icon-new {
right: 50rpx;
width: 30rpx;
height: 32rpx;
position: absolute;
top: 10rpx;
}
}
.ai-info {
padding: 0 24rpx;
height: 250rpx;
overflow: hidden;
padding-top: 72rpx;
margin-bottom: 24rpx;
position: relative;
box-sizing: border-box;
.image-pet {
width: 230rpx;
// height: 235rpx;
position: absolute;
right: 24rpx;
top: -20rpx;
z-index: 2;
}
.image-pet-bg {
position: absolute;
padding: 0 24rpx;
box-sizing: border-box;
width: 100%;
height: 230rpx;
left: 0;
bottom: 0;
z-index: 2;
}
.ai-info-bg-box {
position: absolute;
z-index: 3;
left: 0;
top: 68rpx;
width: 100%;
// background-color: #ccc;
padding: 0 64rpx;
height: 178rpx;
.hello-text {
height: 54rpx;
line-height: 44rpx;
font-size: 28rpx;
color: #666;
}
.info-text {
height: 44rpx;
line-height: 44rpx;
font-size: 32rpx;
color: #000;
font-weight: 600;
}
.info-btn {
width: 220rpx;
font-size: 29rpx;
height: 54rpx;
color: #fff;
background: linear-gradient(104deg, #5547f3 0%, #4e86f4 100%);
line-height: 54rpx;
text-align: center;
border-radius: 15rpx 15rpx 0 0;
position: absolute;
left: 68rpx;
bottom: 0;
}
}
}
.questions-view {
padding-left: 24rpx;
padding-right: 24rpx;
height: 184rpx;
box-sizing: border-box;
.question-row {
white-space: nowrap;
margin-bottom: 16rpx;
}
.question-item {
white-space: nowrap;
height: 66rpx;
line-height: 66rpx;
background-color: #fff;
border: 2rpx solid #e0dede;
padding: 0 16rpx;
border-radius: 11rpx;
margin-right: 16rpx;
display: inline-block;
font-size: 26rpx;
&:last-child {
margin-right: 0;
}
}
}
.router-list {
height: 84rpx;
padding: 20rpx 30rpx 0;
background-color: #fff;
border-radius: 15rpx 15rpx 0 0;
white-space: nowrap;
box-sizing: border-box;
.btns-item {
display: inline-block;
box-sizing: border-box;
height: 62rpx;
border: 2rpx solid #e0dede;
border-radius: 15rpx;
margin-right: 16rpx;
padding: 0 20rpx 0 64rpx;
line-height: 58rpx;
font-size: 29rpx;
position: relative;
.image-icon {
position: absolute;
width: 31rpx;
height: 31rpx;
top: 50%;
transform: translateY(-50%);
left: 24rpx;
}
&:last-child {
margin-right: 0;
}
}
}
.talking-list {
height: calc(100% - 772rpx);
padding: 12rpx 24rpx;
box-sizing: border-box;
.talking-scroll-list {
height: 100%;
}
}
}
// .talking-list {
// height: calc(100% - 832rpx);
// padding: 12rpx 24rpx;
// box-sizing: border-box;
// .talking-scroll-list {
// height: 100%;
// }
// }
</style>