From e9cc0a10ce91763c24052babb9c714576ba92941 Mon Sep 17 00:00:00 2001 From: yanghang Date: Mon, 7 Jul 2025 13:53:35 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8A=BD=E7=A6=BB=E7=BB=84=E4=BB=B6=E6=8C=89?= =?UTF-8?q?=E4=BD=8F=E8=AF=B4=E8=AF=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/socket.js | 1 + src/pages/course/components/chartFour.vue | 2 +- src/pages/course/components/chartThree.vue | 2 +- src/pages/course/components/talkingItem.vue | 48 ++- src/pages/course/components/touchBtn.vue | 297 ++++++++++++++++ src/pages/course/study.vue | 366 +++++++------------- 6 files changed, 454 insertions(+), 262 deletions(-) create mode 100644 src/pages/course/components/touchBtn.vue diff --git a/src/api/socket.js b/src/api/socket.js index 927cc195..71b84695 100644 --- a/src/api/socket.js +++ b/src/api/socket.js @@ -70,6 +70,7 @@ export default class WebSocketUtil { return } }else{ + clearInterval(this.reconnectTimer); // 清除重连计时器 goto_login_fun(); return } diff --git a/src/pages/course/components/chartFour.vue b/src/pages/course/components/chartFour.vue index 03559c0b..2c930ba6 100644 --- a/src/pages/course/components/chartFour.vue +++ b/src/pages/course/components/chartFour.vue @@ -9,7 +9,7 @@ - + 改进建议: diff --git a/src/pages/course/components/chartThree.vue b/src/pages/course/components/chartThree.vue index 34d51e49..d5889b59 100644 --- a/src/pages/course/components/chartThree.vue +++ b/src/pages/course/components/chartThree.vue @@ -12,7 +12,7 @@ - + 改进建议: diff --git a/src/pages/course/components/talkingItem.vue b/src/pages/course/components/talkingItem.vue index c3eb529b..a77f8ef3 100644 --- a/src/pages/course/components/talkingItem.vue +++ b/src/pages/course/components/talkingItem.vue @@ -16,13 +16,13 @@ - + {{ showContent }} - - + + {{ showContent }} - + @@ -82,8 +82,9 @@ - + {{ showContent }} - - + + @@ -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{ diff --git a/src/pages/course/components/touchBtn.vue b/src/pages/course/components/touchBtn.vue new file mode 100644 index 00000000..8105040a --- /dev/null +++ b/src/pages/course/components/touchBtn.vue @@ -0,0 +1,297 @@ + + + + + diff --git a/src/pages/course/study.vue b/src/pages/course/study.vue index ee2a14b5..6674a71a 100644 --- a/src/pages/course/study.vue +++ b/src/pages/course/study.vue @@ -3,7 +3,7 @@ - + {{chooseRate}}倍 @@ -36,8 +36,8 @@ - - + + {{chooseRate}} 倍 @@ -75,46 +75,14 @@ - - 按住说话 - - - - - - - - - - + - - - - - - - - 松开发送 - - 取消 - - - - - - - - @@ -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 }