抽离组件按住说话

This commit is contained in:
yanghang
2025-07-07 13:53:35 +08:00
parent f4d0153f34
commit e9cc0a10ce
6 changed files with 454 additions and 262 deletions
+1
View File
@@ -70,6 +70,7 @@ export default class WebSocketUtil {
return
}
}else{
clearInterval(this.reconnectTimer); // 清除重连计时器
goto_login_fun();
return
}
+1 -1
View File
@@ -9,7 +9,7 @@
</view>
</view>
<view class="title">
<img class="title-icon" src="@/static/images/course/edit.png" alt="" />
<image class="title-icon" src="@/static/images/course/edit.png" alt=""> </image>
改进建议
</view>
<view class="total-score">
+1 -1
View File
@@ -12,7 +12,7 @@
</view>
</view>
<view class="title">
<img class="title-icon" src="@/static/images/course/edit.png" alt="" />
<image class="title-icon" src="@/static/images/course/edit.png" alt=""> </image>
改进建议
</view>
<view class="total-score">
+33 -15
View File
@@ -16,13 +16,13 @@
</view>
<view class="talking-cont">
<CommonLoading color="#06f" v-show="dataInfo.isLoading"/>
<view class="talking-text" v-if="[3, 5, 6].indexOf(type) >= 0 && !dataInfo.isLoading">
<text class="talking-text" v-if="[3, 5, 6].indexOf(type) >= 0 && !dataInfo.isLoading">
{{ showContent }}
</view>
<view class="talking-text" v-if="[4].indexOf(type) >= 0">
</text>
<text class="talking-text" v-if="[4].indexOf(type) >= 0">
<!-- 请您思考并作答:<br> -->
{{ showContent }}
</view>
</text>
<view v-if="type === 3">
<ImagePreview class="cont-img-box" v-if="(dataInfo.imageAddrs||[]).length>0" :imgId="dataInfo.imageAddrs[0]"></ImagePreview>
<VideoPreview class="cont-img-box" v-if="(dataInfo.vidoAddrs||[]).length>0" :imgId="dataInfo.vidoAddrs[0]"></VideoPreview>
@@ -82,8 +82,9 @@
<view class="user-answer" v-else-if="[1, 2].indexOf(type) >= 0">
<view class="user-info">
<view class="avatar-box">
<!-- <ImagePreview class="img-box" :imgId="''"></ImagePreview> -->
<img class="img-box" :src="userInfo.imagePath" alt="" fit="contain" style="width: 100%; height: 100%;"/>
<image v-if="userInfo.imagePath" class="img-box" :src="userInfo.imagePath" style="width: 100%; height: 100%;"></image>
<ImagePreview v-else-if="userInfo.imageAddr" class="img-box" :src="userInfo.imageAddr" style="width: 100%; height: 100%;"></ImagePreview>
<image v-else class="img-box" src="/static/images/me/default_user_avatar.png" style="width: 100%; height: 100%;"></image>
</view>
<view class="ai-name">
{{ userInfo.userName }}
@@ -95,10 +96,10 @@
<CommonLoading color="#fff" v-show="voiceLoading || dataInfo.isLoading"/>
</view>
<view class="talking-cont" v-show="!dataInfo.isLoading">
<view class="talking-text">
<text :class="['talking-text', translateLoading?'loading':'']">
<CommonLoading color="#fff" v-show="translateLoading"/>
{{ showContent }}
</view>
</text>
</view>
<view class="btns-cont" v-show="!dataInfo.isLoading">
<!-- <view class="replay-btn">
@@ -127,18 +128,19 @@
<view class="user-answer" v-else-if="[0, 6].indexOf(type) >= 0">
<view class="user-info">
<view class="avatar-box">
<!-- <ImagePreview class="img-box" :imgId="''"></ImagePreview> -->
<img class="img-box" :src="userInfo.imagePath" alt="" fit="contain" style="width: 100%; height: 100%;"/>
<image v-if="userInfo.imagePath" class="img-box" :src="userInfo.imagePath" style="width: 100%; height: 100%;"></image>
<ImagePreview v-else-if="userInfo.imageAddr" class="img-box" :src="userInfo.imageAddr" style="width: 100%; height: 100%;"></ImagePreview>
<image v-else class="img-box" src="/static/images/me/default_user_avatar.png" style="width: 100%; height: 100%;"></image>
</view>
<view class="ai-name">
{{ userInfo.userName }}
</view>
</view>
<view class="talking-info-less">
<view class="talking-text" v-if="type === 0">
<text class="talking-text" v-if="type === 0">
{{ showContent }}
</view>
<view class="talking-text" v-if="type === 6">
</text>
<view class="talking-text loading" v-if="type === 6">
<CommonLoading color="#fff"/>
</view>
</view>
@@ -202,7 +204,7 @@ const audioCacheObj = computed(() => storageStore.audioObj)
const voiceLoading = ref(false)
watch(() => props.isPlaying,(val) => {
if(!val){
talkVoiceObj.value?.stop()
talkVoiceObj.value?.pause()
}
},{
deep: true,
@@ -216,7 +218,7 @@ const audioCacheObj = computed(() => storageStore.audioObj)
})
const transformContent = ref('')
const showContent = computed(() => {
const showContentBase = computed(() => {
if(props.isTransform){
return transformContent.value
}else{
@@ -228,6 +230,9 @@ const audioCacheObj = computed(() => storageStore.audioObj)
else if(props.type === 0) return unref(dataInfo)?.chatContent || unref(dataInfo)?.talkingContent
}
})
const showContent = computed(() => {
return showContentBase.value.replace(/\/n/g,"\n")
})
onMounted(()=>{
// demoUsage({
@@ -333,6 +338,10 @@ const audioCacheObj = computed(() => storageStore.audioObj)
}
// readType 阅读内容类型pgrh段落/qns问题
emit('changePlay', unref(dataInfo)?.id)
if(talkVoiceObj.value.src === itemVoice.value) {
talkVoiceObj.value.play()
return
}
if(itemVoice.value){
setTimeout(()=>{
talkVoiceObj.value.src = itemVoice.value
@@ -486,9 +495,11 @@ const audioCacheObj = computed(() => storageStore.audioObj)
border-radius: 15rpx;
background-color: #fff;
overflow: hidden;
padding-bottom: 40rpx;
&.talking-info-less{
float: left;
min-width: 400rpx;
padding-bottom: 20rpx;
}
.talking-gif{
width: 200rpx;
@@ -508,9 +519,13 @@ const audioCacheObj = computed(() => storageStore.audioObj)
.talking-text{
font-size: 28rpx;
line-height: 48rpx;
min-height: 48rpx;
margin-bottom: 20rpx;
word-break: break-all;
white-space: pre-line;
&.loading{
min-height: 68rpx;
}
}
.cont-img-box{
width: 433rpx;
@@ -681,6 +696,9 @@ const audioCacheObj = computed(() => storageStore.audioObj)
margin-bottom: 20rpx;
word-break: break-all;
white-space: pre-line;
&.loading{
min-height: 68rpx;
}
}
}
.btns-cont{
+297
View File
@@ -0,0 +1,297 @@
<template>
<view class="talk-btns" ref="talkBtnRef">
<view
class="touch-btn"
@touchstart="showOverlayTalking"
@touchend="hideOverlayTalking"
@touchmove="handleMove"
v-if="!keyboardIsShow"
>按住说话
</view>
<view class="touch-btn" v-if="keyboardIsShow">
<uv-input class="input-box" ref="inputRef" v-model.trim="answerValue" maxlength="1000"
placeholderStyle='color:#999999;font-size:26rpx' placeholder="请输入答案">
</uv-input>
</view>
<view class="talk-btn-box" @click.stop="showKeyboard">
<image class="talk-btn-icon" v-show="!keyboardIsShow" src="/src/static/images/course/jianpan.png" mode=""></image>
<image class="talk-btn-icon" v-show="keyboardIsShow" src="/src/static/images/course/send.png" mode=""></image>
</view>
<uv-overlay :show="showTalkingModel" opacity=".9" @click="showTalkingModel = false">
<view class="overlay-box">
<view class="circle-bg-box">
<view class="icon-box">
<image src="/src/static/images/course/talk-icon.png" mode=""></image>
</view>
</view>
<view class="tips-box">松开发送</view>
<view class="btns-box">
<view :class="['close-btn',isOut?'is-out':'']" >取消
<image class="btn-box" v-if="!isOut" src="/src/static/images/course/close.png" mode=""></image>
<image class="btn-box" v-else src="/src/static/images/course/close-active.png" mode=""></image>
</view>
</view>
</view>
</uv-overlay>
</view>
</template>
<script setup>
import { toRefs, ref, computed, unref, onMounted, onUnmounted, defineEmits, nextTick } from 'vue';
const emit = defineEmits(['uploadVoice', 'submitAnswer','startRecord'])
const props = defineProps({
answerType:{
default: 0,
type: Number
}
})
const { answerType } = toRefs(props)
const showTalkingModel = ref(false)
const keyboardIsShow = ref(false)
const answerValue = ref('')
const talkBtnRef = ref()
// 录音
const audioPath = ref('')
const audioObj = uni.createInnerAudioContext()
//#ifdef APP-PLUS
// app端
const recordObjCom = uni.getRecorderManager()
const initRecord = () => {
unref(recordObjCom)?.onStop((res, duration)=>{
audioPath.value = res.tempFilePath
})
}
const startRecord = () => {
unref(recordObjCom).start({format:'mp3'})
}
const stopRecord = () => {
unref(recordObjCom)?.stop?.()
}
// #endif
//#ifndef APP-PLUS
const recordObjCom = {}
const initRecord = () => {}
// #endif
onMounted(()=>{
initRecord?.()
})
onUnmounted(()=>{
teacherVoiceObj?.stop?.()
teacherVoiceObj.src = ''
})
// const playRecord = () => {
// audioObj.src = audioPath.value
// unref(audioObj).play()
// }
// 录音结束
// 记录 按下移动位置
const touchX = ref(0)
const touchY = ref(0)
const baseY = ref(0)
const windowInfo = uni.getWindowInfo()
// 计算是否超出按下盒子位置
const isOut = computed(() => {
let _btnHeight = windowInfo.screenWidth/750 * 234
let moveVal = (windowInfo.screenHeight - touchY.value) > _btnHeight
return moveVal
})
const showOverlayTalking = (obj) => {
emit('startRecord')
if(answerType.value === 4){
showTalkingModel.value = true
touchX.value = obj.changedTouches[0].pageX
touchY.value = obj.changedTouches[0].pageY
baseY.value = obj.currentTarget.offsetTop
//#ifdef APP-PLUS
startRecord()
// #endif
}else{
uni.showToast({
title: '请先获取问题信息!',
icon: "none",
duration:1000
})
}
}
const hideOverlayTalking = (obj) => {
showTalkingModel.value = false
//#ifdef APP-PLUS
stopRecord()
// #endif
if(!isOut.value){
setTimeout(()=>{
emit('uploadVoice', audioPath.value)
},1000)
}
}
const handleMove = (obj) => {
touchX.value = obj.changedTouches[0].pageX
touchY.value = obj.changedTouches[0].pageY
}
// 发送文本
const showKeyboard = () => {
if(answerType.value === 4){
if(keyboardIsShow.value){
if(answerValue.value){
emit(
'submitAnswer',
answerValue.value,
() => {
keyboardIsShow.value = !keyboardIsShow.value
answerValue.value = ''
}
)
}else{
keyboardIsShow.value = !keyboardIsShow.value
}
}else{
keyboardIsShow.value = !keyboardIsShow.value
}
}else{
uni.showToast({
title: '请先获取问题信息!',
icon: "none",
duration:1000
})
}
}
</script>
<style lang="scss" scoped>
.talk-btns{
height: 150rpx;
background-color: #fff;
padding: 25rpx 30rpx 0;
position: relative;
.touch-btn{
height: 92rpx;
box-shadow: 0 8rpx 20rpx 0 rgba(0,0,0,.06);
text-align: center;
line-height: 92rpx;
color: #000;
font-weight: 400;
position: relative;
.input-box{
width: 100%;
height: 92rpx;
line-height: 92rpx;
text-align: left;
box-sizing: border-box;
padding:0 40rpx 0 40rpx;
}
}
.talk-btn-box{
position: absolute;
height: 100%;
width: 120rpx;
right: 0;
top:0;
.talk-btn-icon{
width: 40rpx;
height: 40rpx;
position: absolute;
right: 60rpx;
top: 50%;
margin-top: -20rpx;
}
}
}
.overlay-box{
display: flex;
flex-direction: column-reverse;
// justify-content: flex-end;
width: 100%;
height: 100%;
.circle-bg-box{
height: 234rpx;
background: url(@/static/images/course/talking.png) no-repeat;
background-size: cover;
position: relative;
.icon-box{
position: absolute;
left:50%;
top: 50%;
margin-left: -17rpx;
margin-top: -24rpx;
width: 34rpx;
height: 48rpx;
image{
width: 100%;
height: 100%;
}
}
}
.tips-box{
height: 40rpx;
line-height: 40rpx;
color:#c0c0c0;
text-align: center;
margin: 12rpx 0 24rpx;
}
.btns-box{
height: 270rpx;
// padding: 0 120rpx;
width: 154rpx;
margin: 0 auto 100rpx;
overflow: hidden;
font-size: 28rpx;
text-align: center;
line-height: 116rpx;
.close-btn{
float: left;
height: 100%;
width: 154rpx;
overflow: hidden;
color:#999;
&.is-out{
color:#fff;
}
}
.translate-btn{
float: right;
height: 100%;
width: 154rpx;
overflow: hidden;
color:#999;
}
.btn-box{
width: 100%;
height: 154rpx;
}
}
.talk-dialog{
width: 506rpx;
height: 234rpx;
margin: 0 auto;
background-color: #06f;
}
.white-bg-box{
height: 365rpx;
background-color: #fff;
overflow: hidden;
border-radius: 32rpx 32rpx 0 0;
padding: 58rpx 36rpx;
.box-title{
font-size: 32rpx;
font-weight: bold;
line-height: 46rpx;
margin-bottom: 46rpx;
}
.box-btns{
height: 46rpx;
line-height: 46rpx;
display: flex;
justify-content: space-between;
color: #999;
.is-active{
color: #06f;
}
}
}
}
</style>
+121 -245
View File
@@ -3,7 +3,7 @@
<view class="top-bg"></view>
<view class="bot-bg"></view>
<view class="course-study-body" v-show="step === 1">
<view class="seek-setting" @click="showSeekModel = true">
<view class="seek-setting" @click="showChangeSeekModelNow">
{{chooseRate}}
<image src="@/static/images/course/setting.png" alt="" class="image-icon"></image>
</view>
@@ -36,8 +36,8 @@
</view>
</view>
</view>
<view class="course-study-body" v-show="step === 2" @click="playRecord">
<view class="seek-setting" @click="showSeekModel = true">
<view class="course-study-body" v-show="step === 2">
<view class="seek-setting" @click="showChangeSeekModelNow">
{{chooseRate}}
<image src="@/static/images/course/setting.png" alt="" class="image-icon"></image>
</view>
@@ -75,46 +75,14 @@
<!-- <video v-if="videoUrlShow" :src="videoUrlShow" controls></video> -->
<!-- </view> -->
</scroll-view>
<view class="talk-btns">
<view
class="touch-btn"
@touchstart="showOverlayTalking"
@touchend="hideOverlayTalking"
@touchmove="handleMove"
v-if="!keyboardIsShow"
>按住说话
</view>
<view class="touch-btn" v-if="keyboardIsShow">
<uv-input class="input-box" ref="inputRef" v-model.trim="answerValue" maxlength="1000"
placeholderStyle='color:#999999;font-size:26rpx' placeholder="请输入答案">
</uv-input>
</view>
<view class="talk-btn-box" @click.stop="showKeyboard">
<image class="talk-btn-icon" v-show="!keyboardIsShow" src="/src/static/images/course/jianpan.png" mode=""></image>
<image class="talk-btn-icon" v-show="keyboardIsShow" src="/src/static/images/course/send.png" mode=""></image>
</view>
</view>
<TouchBtn
class="talk-btns"
@uploadVoice="uploadRecordNow"
@submitAnswer="submitAnswerNow"
@startRecord="changePlayItemId('')"
:answerType="lastTalkingInfo.type||0"
/>
</view>
<uv-overlay :show="showTalkingModel" opacity=".9" @click="showTalkingModel = false">
<view class="overlay-box">
<view class="circle-bg-box">
<view class="icon-box">
<image src="/src/static/images/course/talk-icon.png" mode=""></image>
</view>
</view>
<view class="tips-box">松开发送</view>
<view class="btns-box">
<view :class="['close-btn',isOut?'is-out':'']" >取消
<image class="btn-box" v-if="!isOut" src="/src/static/images/course/close.png" mode=""></image>
<image class="btn-box" v-else src="/src/static/images/course/close-active.png" mode=""></image>
</view>
</view>
<!-- <view class="talk-dialog">
<view class="voice-gif"></view>
</view> -->
</view>
</uv-overlay>
<uv-overlay :show="showSeekModel" opacity=".6" @click="showSeekModel = false">
<view class="overlay-box">
<view class="white-bg-box">
@@ -161,6 +129,7 @@ import {
import common from '@/common/common';
import TalkingItem from '@/pages/course/components/talkingItem.vue'
import ImagePreview from '@/components/image-preview/image-preview.vue'
import TouchBtn from '@/pages/course/components/touchBtn.vue'
import { useSocketStore } from "@/store/socket.js"
import { useStorageStore } from "@/store/storage.js"
@@ -240,8 +209,12 @@ const getData = async () => {
// })
};
const showChangeSeekModelNow = () => {
// changePlayItemId()
showSeekModel.value = true
}
// 关闭播放状态
const changePlayItemId = (id) => {
const changePlayItemId = (id = '') => {
if(activeVoiceTalkingItemId.value === id){
activeVoiceTalkingItemId.value = ''
}else{
@@ -321,18 +294,18 @@ const getGraphInfoUnStudy = () => {
}).then(res=>{
let _id = new Date().getTime() + 'id'
let _body = res.body|| {}
// if(_body.chatContent.haveNext === 'N'){}
talkingList.value.push({
lastTalkingInfo.value = {
crsId: crsId.value,
qstLogId: _body.chatBody,
pgrphId: _body.pgrphId,
logId:_body.chatBody.logId || '',
talkingContent: _body.chatContent,
chatContent: _body.chatContent,
userInfo: {...choiceTeacherInfo.value},
..._body.chatBody,
type: Number(_body.bodyTyp) || 0,
id: _id
})
}
talkingList.value.push(lastTalkingInfo.value)
pgrphNum.value = _body.chatBody.pgrphNum
showOrder.value = _body.chatBody.showOrder
logId.value = _body.chatBody.logId || ''
@@ -372,16 +345,17 @@ const getQuestionInfoUnStudy = (pgrphId) => {
const nextQuestionSuccess = (info, type='next') => {
let _id = new Date().getTime() + 'id'
if(type === 'next'){
talkingList.value.push({
lastTalkingInfo.value = {
crsId: info.crsId,
pgrphId: info.pgrphId,
talkingContent: '继续',
type: 0,
id: _id
})
}
talkingList.value.push(lastTalkingInfo.value)
scrollToBottomNow(0)
getQuestionInfoUnStudy(info.pgrphId)
}else if( type = 'overGraph'){
}else if( type === 'overGraph'){
textChartApi({
processType: 'PRGH-OVER',
requestBody: JSON.stringify({
@@ -389,33 +363,37 @@ const nextQuestionSuccess = (info, type='next') => {
logId: info?.logId,
})
}).then(res=>{
talkingList.value.push({
lastTalkingInfo.value = {
crsId: info.crsId,
pgrphId: info.pgrphId,
talkingContent: '继续',
type: 0,
id: _id
})
}
talkingList.value.push(lastTalkingInfo.value)
scrollToBottomNow(0)
getQuestionInfoUnStudy(info.pgrphId)
})
}else if( type = 'reStart'){
}else if( type === 'reStart'){
console.log( 'qstLogId',info.qstLogId)
// 重新回答
textChartApi({
processType: 'NEW-ANSER',
requestBody: info.qstLogId
}).then(res=>{
let _body = res.body|| {}
talkingList.value.push({
lastTalkingInfo.value = {
crsId: info.crsId,
qstLogId: _body.chatBody,
pgrphId: info.pgrphId,
talkingContent: _body.chatContent,
chatContent: _body.chatContent,
userInfo: {...choiceTeacherInfo.value},
..._body.chatBody,
type: Number(_body.bodyTyp) || 0,
id: _id
})
}
talkingList.value.push(lastTalkingInfo.value)
scrollToBottomNow()
})
}
@@ -491,219 +469,113 @@ const showTalkingModel = ref(false)
// 录音
const audioPath = ref('')
const audioObj = uni.createInnerAudioContext()
//#ifdef APP-PLUS
// app端
const recordObj = uni.getRecorderManager()
const initRecord = () => {
unref(recordObj)?.onStop((res, duration)=>{
audioPath.value = res.tempFilePath
})
}
const startRecord = () => {
unref(recordObj).start({format:'mp3'})
}
const stopRecord = () => {
unref(recordObj)?.stop?.()
}
// #endif
//#ifndef APP-PLUS
const recordObj = {}
const initRecord = () => {}
// #endif
onMounted(()=>{
getData();
initRecord?.()
})
onShow(()=>{
// getData();
})
// onHide(()=>{
// teacherVoiceObj.stop()
// teacherVoiceObj.src = ''
// })
onUnmounted(()=>{
teacherVoiceObj?.stop?.()
teacherVoiceObj.src = ''
})
const playRecord = () => {
audioObj.src = audioPath.value
unref(audioObj).play()
}
// 录音结束
// 记录 按下移动位置
const touchX = ref(0)
const touchY = ref(0)
const baseY = ref(0)
const systemInfo = uni.getSystemInfoSync()
const widowHeight = systemInfo.windowHeight
// 计算是否超出按下盒子位置
const isOut = computed(() => {
let moveVal = (widowHeight - baseY.value)/140 * 234
return (widowHeight - moveVal) > touchY.value
})
const showOverlayTalking = (obj) => {
if(lastTalkingInfo.value.type === 4){
//#ifdef APP-PLUS
showTalkingModel.value = true
touchX.value = obj.changedTouches[0].pageX
touchY.value = obj.changedTouches[0].pageY
baseY.value = obj.currentTarget.offsetTop
startRecord()
// #endif
}else{
uni.showToast({
title: '请先获取问题信息!',
icon: "none",
duration:1000
})
}
}
const hideOverlayTalking = (obj) => {
showTalkingModel.value = false
//#ifdef APP-PLUS
stopRecord()
// #endif
if(!isOut.value){
setTimeout(()=>{
let _data = {
qnsId: unref(lastTalkingInfo).qnsId,// 问题ID 必输项:true 类型:String
pgrphId: unref(lastTalkingInfo).pgrphId,// 段落ID 必输项:true 类型:String
qstLogId: unref(qstLogId),// 段落ID 必输项:true 类型:String
crsId: crsId.value,// 课程ID 必输项:true 类型:String
stdyBatch: stdyBatch.value,// 学习批次 必输项:true 类型:String
ansterContent: '',// 回答文本内容 必输项:false 类型:String
}
let _id = new Date().getTime() + 'id'
//#ifndef APP-PLUS
// h5 假数据
talkingList.value.push({
crsId: crsId.value,
pgrphId: unref(lastTalkingInfo).pgrphId,
qnsId: unref(lastTalkingInfo).qnsId,
talkingContent: '',
talkingVoice: audioPath.value,
type: 1,
userInfo: {...choiceTeacherInfo.value},
id: _id
})
scrollToBottomNow()
// #endif
//#ifdef APP-PLUS
const uploadRecordNow = (voicePath) => {
let _data = {
qnsId: unref(lastTalkingInfo).qnsId,// 问题ID 必输项:true 类型:String
pgrphId: unref(lastTalkingInfo).pgrphId,// 段落ID 必输项:true 类型:String
qstLogId: unref(qstLogId),// 段落ID 必输项:true 类型:String
crsId: crsId.value,// 课程ID 必输项:true 类型:String
stdyBatch: stdyBatch.value,// 学习批次 必输项:true 类型:String
ansterContent: '',// 回答文本内容 必输项:false 类型:String
}
let _id = new Date().getTime() + 'id'
//#ifndef APP-PLUS
// h5 假数据
talkingList.value.push({
crsId: crsId.value,
pgrphId: unref(lastTalkingInfo).pgrphId,
qnsId: unref(lastTalkingInfo).qnsId,
talkingContent: '',
talkingVoice: audioPath.value,
intrctId: '',
isLoading: true,
type: 1,
userInfo: {...choiceTeacherInfo.value},
id: _id
})
scrollToBottomNow()
commonUploadVoiceFile(audioPath.value, '/trastudy/traStdyInfo/studyAnswerVoiceUp', _data).then(res=>{
let _res = JSON.parse(res.data)
if(_res.rtnCode === '0000'){
// talkingList.value.pop()
// talkingList.value.push({
// crsId: crsId.value,
// pgrphId: _data.pgrphId,
// qstLogId: _data.qstLogId,
// qnsId: _data.qnsId,
// talkingContent: '',
// talkingVoice: audioPath.value,
// intrctId: res.body||'',
// type: 1,
// userInfo: {...choiceTeacherInfo.value},
// id: _id
// })
talkingList.value = talkingList.value.map(t=>{
if(t.id === _id){
return {
crsId: crsId.value,
pgrphId: _data.pgrphId,
qstLogId: _data.qstLogId,
qnsId: _data.qnsId,
talkingContent: '',
talkingVoice: audioPath.value,
intrctId: res.body||'',
type: 1,
userInfo: {...choiceTeacherInfo.value},
id: _id
}
}else{
return t
}
})
scrollToBottomNow()
}else{}
}).catch(err=>{
talkingList.value = talkingList.value.filter(t=>t.id !== _id)
uni.showToast({
title: '系统异常,请联系管理员',
icon: "none",
duration:1000
});
})
// #endif
},1000)
}
}
const handleMove = (obj) => {
touchX.value = obj.changedTouches[0].pageX
touchY.value = obj.changedTouches[0].pageY
}
const keyboardIsShow = ref(false)
// 发送文本
const showKeyboard = () => {
if(lastTalkingInfo.value.type === 4){
if(keyboardIsShow.value){
if(answerValue.value){
let _data = {
qnsId: unref(lastTalkingInfo).qnsId,// 问题ID 必输项:true 类型:String
pgrphId: unref(lastTalkingInfo).pgrphId,// 段落ID 必输项:true 类型:String
qstLogId: unref(qstLogId),// 段落ID 必输项:true 类型:String
crsId: crsId.value,// 课程ID 必输项:true 类型:String
stdyBatch: stdyBatch.value,// 学习批次 必输项:true 类型:String
ansterContent: answerValue.value // 回答文本内容 必输项:false 类型:String
}
studyAnswerTextUpApi(_data).then(res=>{
if(res.rtnCode === '0000'){
let _id = new Date().getTime() + 'id'
talkingList.value.push({
scrollToBottomNow()
// #endif
//#ifdef APP-PLUS
talkingList.value.push({
crsId: crsId.value,
pgrphId: unref(lastTalkingInfo).pgrphId,
qnsId: unref(lastTalkingInfo).qnsId,
talkingContent: '',
talkingVoice: audioPath.value,
intrctId: '',
isLoading: true,
type: 1,
userInfo: {...choiceTeacherInfo.value},
id: _id
})
scrollToBottomNow()
commonUploadVoiceFile(audioPath.value, '/trastudy/traStdyInfo/studyAnswerVoiceUp', _data).then(res=>{
let _res = JSON.parse(res.data)
if(_res.rtnCode === '0000'){
talkingList.value = talkingList.value.map(t=>{
if(t.id === _id){
return {
crsId: crsId.value,
pgrphId: _data.pgrphId,
qstLogId: _data.qstLogId,
qnsId: _data.qnsId,
talkingContent: answerValue.value,
talkingVoice: '',
talkingContent: '',
talkingVoice: audioPath.value,
intrctId: res.body||'',
type: 2,
type: 1,
userInfo: {...choiceTeacherInfo.value},
id: _id
})
scrollToBottomNow()
answerValue.value = ''
keyboardIsShow.value = !keyboardIsShow.value
}
}else{
return t
}
})
}else{
keyboardIsShow.value = !keyboardIsShow.value
}
}else{
keyboardIsShow.value = !keyboardIsShow.value
}
}else{
uni.showToast({
title: '请先获取问题信息!',
icon: "none",
duration:1000
scrollToBottomNow()
}else{}
}).catch(err=>{
talkingList.value = talkingList.value.filter(t=>t.id !== _id)
uni.showToast({
title: '系统异常,请联系管理员',
icon: "none",
duration:1000
});
})
// #endif
}
// 发送文本
const submitAnswerNow = (val, cb) => {
let _data = {
qnsId: unref(lastTalkingInfo).qnsId,// 问题ID 必输项:true 类型:String
pgrphId: unref(lastTalkingInfo).pgrphId,// 段落ID 必输项:true 类型:String
qstLogId: unref(qstLogId),// 段落ID 必输项:true 类型:String
crsId: crsId.value,// 课程ID 必输项:true 类型:String
stdyBatch: stdyBatch.value,// 学习批次 必输项:true 类型:String
ansterContent: val // 回答文本内容 必输项:false 类型:String
}
studyAnswerTextUpApi(_data).then(res=>{
if(res.rtnCode === '0000'){
let _id = new Date().getTime() + 'id'
talkingList.value.push({
crsId: crsId.value,
pgrphId: _data.pgrphId,
qstLogId: _data.qstLogId,
qnsId: _data.qnsId,
talkingContent: val,
talkingVoice: '',
intrctId: res.body||'',
type: 2,
userInfo: {...choiceTeacherInfo.value},
id: _id
})
scrollToBottomNow()
cb && cb()
}
})
}
// 撤回
const withdrawNow = (data) => {
@@ -724,18 +596,20 @@ const finishQuestionNow = (data) => {
// common.msg('完成成功,开始获取评分维度数据!')
loadingQstLogId.value = res.body.qstLogId
let _id = new Date().getTime() + 'id'
talkingList.value.push({
lastTalkingInfo.value = {
isLoading: true,
id: _id,
userInfo: {...choiceTeacherInfo.value},
type: 5
})
}
talkingList.value.push(lastTalkingInfo.value)
scrollToBottomNow(0)
getQuestionEvalateRequest(_id,data)
})
}
// 查询问题回答评分
const getQuestionEvalateRequest = (id, data) => {
console.log( 'qstLogId',data.qstLogId)
if(loadingQstLogId.value){
queryQuestionEvalateApi({
qstLogId:loadingQstLogId.value
@@ -744,13 +618,15 @@ const getQuestionEvalateRequest = (id, data) => {
let _body = res.body
talkingList.value = talkingList.value.map(t=>{
if(t.id === id){
return {
lastTalkingInfo.value = {
..._body,
pgrphId: data.pgrphId,
qstLogId: loadingQstLogId.value,
id,
userInfo: {...choiceTeacherInfo.value},
type: 5
}
return lastTalkingInfo.value
}else{
return t
}