学习页面逻辑调整

This commit is contained in:
yanghang
2025-07-06 18:01:31 +08:00
parent 42587bf2b4
commit 250b2f52fe
9 changed files with 436 additions and 159 deletions
+1 -1
View File
@@ -7,7 +7,7 @@ ENV = 'development'
# 苗扬
# VITE_APP_BASE_API_Url = 'http://25.64.16.133:9786'
VITE_APP_BASE_API_Url = 'https://aitstest.jlbank.com.cn:7002'
VITE_APP_BASE_API_Url = 'https://aitstest.jlbank.com.cn:7001'
# http://25.18.122.65:7001/download/dev-jax.apk
# app入口
#VITE_APP_BASE_API_Url = 'http://25.18.122.65:7001'
+1 -1
View File
@@ -3,4 +3,4 @@ ENV = 'production'
# base api
VITE_APP_BASE_API_Url = 'https://aitstest.jlbank.com.cn:7002'
VITE_APP_BASE_API_Url = 'https://aitstest.jlbank.com.cn:7001'
+1
View File
@@ -93,6 +93,7 @@ export const commonUploadVoiceFile = (file, url, data = {}, fileKey='voice') =>
}
},
fail(error) {
console.log(error)
reject(new Error('Upload failed'));
}
});
+3 -1
View File
@@ -63,7 +63,9 @@ export default class WebSocketUtil {
if(res.data){
const { rtnCode } = JSON.parse(res.data)
console.log('收到WebSocket消息', JSON.parse(res.data) );
if(['0005', 'QQ0005'].includes(res.rtnCode)) {
if(['0005', 'QQ0005'].includes(rtnCode)) {
clearInterval(this.reconnectTimer);
this.close()
goto_login_fun();
return
}
+36 -10
View File
@@ -1,5 +1,6 @@
import request from '@/api/request'
import { getToken } from '@/common/common.js'
import { get_base_url } from '@/api/request'
const base_url = '/trastudy'
// 获取课程学习信息接口
@@ -31,6 +32,15 @@ export const deleteTraStdyInfoByIdApi = (data) => {
});
};
// 重新学习
export const afreshStudyCourseApi = (data) => {
return request({
url: base_url + '/traStdyInfo/afreshStudyCourse',
method: 'post',
toastErrors: true,
data
});
};
// 学习段落完成
export const studyParagraphOverApi = (data) => {
return request({
@@ -94,6 +104,17 @@ export const waitMakeEvaluateApi = (data) => {
data
});
};
// 查询问题评价
// /traStdyInfo/queryQuestionEvalate
export const queryQuestionEvalateApi = (data) => {
return request({
url: base_url + '/traStdyInfo/queryQuestionEvalate',
method: 'post',
toastErrors: true,
data
});
};
// /trastudy/intgask/askAbout
// 流式获取文本
@@ -111,25 +132,19 @@ export const getAskAboutRawApi = (data) => {
// toastErrors: false,
// data
// });
return new Promise((resolve, reject) => {
request({
return request({
url: base_url + '/intgask/askAbout',
header: {
'Accept':'text/event-stream',
'content-type': 'application/json; charset=UTF-8',
'content-type': 'text/event-stream; charset=UTF-8',
},
responseType: 'arrayBuffer',
method: 'get',
isStream: true,
timeout: 30000,
toastErrors: false,
data
}).then(res=>{
console.log(res.data)
let _str = `[${ res.data.split('}{').join('},{')}]`
console.log(JSON.parse(_str))
})
});
// return request({
// url: base_url + '/intgask/askAbout',
// header: {
@@ -142,4 +157,15 @@ export const getAskAboutRawApi = (data) => {
// toastErrors: false,
// data
// });
};
// 学习 对话
export const textChartApi = (data) => {
return request({
url: base_url + '/traStdychat/textChart',
method: 'post',
toastErrors: true,
data
});
};
+31 -20
View File
@@ -13,12 +13,12 @@
改进建议
</view>
<view class="total-score">
<view class="score-num">57</view>
<view class="score-num">{{props.score}}</view>
<img class="total-score-icon" src="@/static/images/course/score.png" alt="" />
</view>
<view v-for="item,index in 4" :class="['score-item', 'score-item'+(index + 1)]">
<view class="score-item-name">词命中率</view>
<view class="score-item-score">98</view>
<view v-for="item,index in props.dataList" :class="['score-item', 'score-item'+(index+1)]">
<view class="score-item-name">{{ item.gradeDimensName }}</view>
<view class="score-item-score">{{ item.anlyGrade }}</view>
</view>
</view>
</template>
@@ -26,15 +26,22 @@
<script setup>
import { ref, computed} from "vue"
const props = defineProps({
data:{
default:() => [60,70,80,90],
dataList:{
default:() => [],
type: Array
},
score:{
default: 0,
type: [Number,String]
},
size:{
default: 262,
type: [Number,String]
}
})
const dataValue = computed(() => {
return props.dataList.map(t=>t.anlyGrade)
})
const chartWidth = computed(() => props.size + 'rpx')
const chartHeight = computed(() => props.size + 'rpx')
const scoreMarginX = computed(() => {
@@ -51,16 +58,20 @@
})
const styleFour = ref('polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%)')
const styleFourResult = computed(()=>{
let score = props.data
let _tx = 50
let _ty = 50 - Math.floor((score[0]/100)*50)
let _rx = 50 + Math.floor((score[1]/100)*50)
let _ry = 50
let _bx = 50
let _by = 50 + Math.floor((score[2]/100)*50)
let _lx = 50 - Math.floor((score[3]/100)*50)
let _ly = 50
return `polygon(${_tx}% ${_ty}%, ${_rx}% ${_ry}%, ${_bx}% ${_by}%, ${_lx}% ${_ly}%)`
let score = dataValue.value
if(score.length>=4){
let _tx = 50
let _ty = 50 - Math.floor((score[0]/100)*50)
let _rx = 50 + Math.floor((score[1]/100)*50)
let _ry = 50
let _bx = 50
let _by = 50 + Math.floor((score[2]/100)*50)
let _lx = 50 - Math.floor((score[3]/100)*50)
let _ly = 50
return `polygon(${_tx}% ${_ty}%, ${_rx}% ${_ry}%, ${_bx}% ${_by}%, ${_lx}% ${_ly}%)`
}else{
return `polygon(${0}% ${50}%, ${50}% ${100}%, ${100}% ${50}%, ${50}% ${0}%)`
}
})
</script>
@@ -225,9 +236,9 @@
transform: translateY(v-bind(scoreMarginAbsY));
}
&.score-item2{
left: 0%;
right: 0%;
top: 50%;
transform: translate(calc(v-bind(scoreMarginX) - 60rpx), calc(-50% + 25rpx));
transform: translate(calc(v-bind(scoreMarginAbsX) + 60rpx), calc(-50% + 25rpx));
}
&.score-item3{
left: 50%;
@@ -236,9 +247,9 @@
transform: translateY(v-bind(scoreMarginY));
}
&.score-item4{
right: 0%;
left: 0%;
top: 50%;
transform: translate(calc(v-bind(scoreMarginAbsX) + 60rpx), calc(-50% + 25rpx));
transform: translate(calc(v-bind(scoreMarginX) - 60rpx), calc(-50% + 25rpx));
}
}
}
+28 -16
View File
@@ -16,12 +16,12 @@
改进建议
</view>
<view class="total-score">
<view class="score-num">57</view>
<view class="score-num">{{props.score}}</view>
<img class="total-score-icon" src="@/static/images/course/score.png" alt="" />
</view>
<view v-for="item,index in 3" :class="['score-item', 'score-item'+(index + 1)]">
<view class="score-item-name">词命中率</view>
<view class="score-item-score">98</view>
<view v-for="item,index in props.dataList" :class="['score-item', 'score-item'+(index+1)]">
<view class="score-item-name">{{ item.gradeDimensName }}</view>
<view class="score-item-score">{{ item.anlyGrade }}</view>
</view>
</view>
</template>
@@ -29,15 +29,22 @@
<script setup>
import { ref, computed} from "vue"
const props = defineProps({
data:{
default:() => [60,70,80,90],
dataList:{
default:() => [],
type: Array
},
score:{
default: 0,
type: [Number,String]
},
size:{
default: 262,
type: [Number,String]
}
})
const dataValue = computed(() => {
return props.dataList.map(t=>t.anlyGrade)
})
let _scale = .9
const chartWidth = computed(() => props.size / _scale + 'rpx')
const chartHeight = computed(() => props.size / _scale + 'rpx')
@@ -49,8 +56,8 @@
return '-' + (props.size/2 - 40) + 'rpx'
})
const scoreMarginPercentY = computed(() => {
let score = props.data
return setPercent(score[2], Math.round(100 * 1.732 / 6 * _scale * 100)/100) + '%'
let score = dataValue.value
return setPercent(80, Math.round(100 * 1.732 / 6 * _scale * 100)/100) + '%'
})
@@ -66,14 +73,19 @@
return `polygon(${_tx}% ${_ty}%, ${_rx}% ${_ry}%, ${_bx}% ${_by}%)`
})
const styleFourResult = computed(()=>{
let score = props.data
let _tx = 50
let _ty = 50 - setPercent(score[0], Math.round(100 * 1.732 / 3 * _scale * 100)/100)
let _rx = 50 + setPercent(score[1], Math.round(50 *_scale * 100)/100)
let _ry = 50 + setPercent(score[1], Math.round(100 * 1.732 / 6 * _scale * 100)/100)
let _bx = 50 - setPercent(score[2], Math.round(50 *_scale * 100)/100)
let _by = 50 + setPercent(score[2], Math.round(100 * 1.732 / 6 * _scale * 100)/100)
return `polygon(${_tx}% ${_ty}%, ${_rx}% ${_ry}%, ${_bx}% ${_by}%)`
let score = dataValue.value
if(score.length >= 3){
let _tx = 50
let _ty = 50 - setPercent(score[0], Math.round(100 * 1.732 / 3 * _scale * 100)/100)
let _rx = 50 + setPercent(score[1], Math.round(50 *_scale * 100)/100)
let _ry = 50 + setPercent(score[1], Math.round(100 * 1.732 / 6 * _scale * 100)/100)
let _bx = 50 - setPercent(score[2], Math.round(50 *_scale * 100)/100)
let _by = 50 + setPercent(score[2], Math.round(100 * 1.732 / 6 * _scale * 100)/100)
return `polygon(${_tx}% ${_ty}%, ${_rx}% ${_ry}%, ${_bx}% ${_by}%)`
}else{
return styleFour.value
}
})
const setPercent = (precent, show) => {
return Math.floor((precent/100) * show)
+143 -43
View File
@@ -11,24 +11,25 @@
</view>
</view>
<view :class="['talking-info', [4].indexOf(type) >= 0 ? 'talking-info-less':''] ">
<view :class="['talking-gif', !voiceLoading && (activeVoiceId === dataInfo.id)?'is-play':'']">
<view :class="['talking-gif', !voiceLoading && (activeVoiceId === dataInfo.id)?'is-play':'']" v-if="type !== 5">
<CommonLoading color="#06f" v-show="voiceLoading"/>
</view>
<view class="talking-cont">
<view class="talking-text" v-if="[3, 5, 6].indexOf(type) >= 0">
{{ dataInfo.pgrphContent }}
<CommonLoading color="#06f" v-show="dataInfo.isLoading"/>
<view 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">
请您思考并作答:<br>
{{ dataInfo.qnsContent }}
<!-- 请您思考并作答:<br> -->
{{ showContent }}
</view>
<view v-show="type === 3">
<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>
</view>
<view v-show="type === 5">
<ChartFour/>
<ChartThree/>
<view v-if="type === 5 && !dataInfo.isLoading">
<ChartFour v-if="dataInfo.evalDimens.length === 4" :dataList="dataInfo.evalDimens" :score="dataInfo.intrctGrade"/>
<ChartThree v-if="dataInfo.evalDimens.length === 3" :dataList="dataInfo.evalDimens" :score="dataInfo.intrctGrade"/>
</view>
</view>
<!-- <view class="talking-cont">
@@ -36,16 +37,16 @@
阿列克山大是快乐的你艾德卡省的mask安东拉森扣篮大赛了快递那里是啊克里斯蒂娜老师的阿萨是看
</view>
</view> -->
<view class="btns-cont">
<view class="replay-btn" @click="restartPlay">
<view class="btns-cont" v-show="!dataInfo.isLoading">
<view class="replay-btn" @click.stop="restartPlay" v-if="!([5].indexOf(type) >= 0)">
<image class="icon" src="@/static/images/course/replay.png" style="width: 100%;height: 100%;"></image>
</view>
<view class="play-btn">
<view class="play-btn" v-if="!([5].indexOf(type) >= 0)">
<image
class="icon"
src="@/static/images/course/play.png"
style="width: 100%;height: 100%;"
@click="playVoice()"
@click.stop="playVoice()"
v-show="!isPlaying"
></image>
<image
@@ -53,12 +54,27 @@
v-show="isPlaying"
src="@/static/images/course/pause.png"
style="width: 100%;height: 100%;"
@click="pauseVoice"
@click.stop="pauseVoice"
></image>
</view>
<!-- <view class="next-learn-btn">继续学<image class="icon icon-iamge" src="@/static/images/course/goon.png" ></image></view>
<view class="replay-study-btn"><image class="icon icon-iamge" src="@/static/images/course/restudy.png" ></image></view> -->
<view class="next-btn" @click="goOnGetQues" v-if="showNextBtn && [3, 5, 6].indexOf(type) >= 0 && isLast">继续
<view
class="next-learn-btn"
v-if="showNextBtn && [5].indexOf(type) >= 0 && isLast"
@click.stop="goOnGetQues"
>
继续学
<image class="icon icon-iamge" src="@/static/images/course/goon.png" ></image>
</view>
<view
class="next-learn-btn restart"
v-if="showNextBtn && [5].indexOf(type) >= 0 && isLast"
@click.stop="goOnRestart"
>
重新学
<image class="icon icon-iamge" src="@/static/images/course/restart.png" ></image>
</view>
<!-- <view class="replay-study-btn" v-if="showNextBtn && [5].indexOf(type) >= 0 && isLast"><image class="icon icon-iamge" src="@/static/images/course/restudy.png" ></image></view> -->
<view class="next-btn" @click.stop="goOnGetQues" v-if="showNextBtn && [3, 6].indexOf(type) >= 0 && isLast">继续
<image class="icon icon-iamge" src="@/static/images/course/goon.png" ></image></view>
</view>
</view>
@@ -75,36 +91,36 @@
</view>
<view class="talking-info">
<view :class="['talking-gif', !voiceLoading && (activeVoiceId === dataInfo.id) ? 'is-play' : '']">
<CommonLoading color="#fff" v-show="voiceLoading"/>
<view :class="['talking-gif', !voiceLoading && (activeVoiceId === dataInfo.id) ? 'is-play' : '']">
<CommonLoading color="#fff" v-show="voiceLoading || dataInfo.isLoading"/>
</view>
<view class="talking-cont">
<view class="talking-cont" v-show="!dataInfo.isLoading">
<view class="talking-text">
<CommonLoading color="#fff" v-show="translateLoading"/>
{{ dataInfo.talkingContent }}
{{ showContent }}
</view>
</view>
<view class="btns-cont">
<view class="btns-cont" v-show="!dataInfo.isLoading">
<!-- <view class="replay-btn">
<image class="icon" src="@/static/images/course/replay.png" style="width: 100%;height: 100%;"></image>
</view> -->
<view class="play-btn">
<image class="icon"
@click="playQnsVoice('qns', dataInfo)"
@click.stop="playQnsVoice('qns', dataInfo)"
v-show="!isPlaying"
src="@/static/images/course/play-blue.png"
style="width: 100%;height: 100%;"
></image>
<image class="icon"
v-show="isPlaying"
@click="pauseVoice"
@click.stop="pauseVoice"
src="@/static/images/course/stop-blue.png"
style="width: 100%;height: 100%;"
></image>
</view>
<view class="icon text-btn" v-if="type === 1" @click="translateVoice(dataInfo)"></view>
<view class="icon text-right-btn" @click="finishQuestion(dataInfo)" v-if="isLast">完成</view>
<view class="icon text-right-btn" @click="withdraw(dataInfo)">撤回</view>
<view class="icon text-btn" v-if="type === 1" @click.stop="translateVoice(dataInfo)"></view>
<view class="icon text-right-btn" @click.stop="finishQuestion(dataInfo)" v-if="isLast">完成</view>
<view class="icon text-right-btn" @click.stop="withdraw(dataInfo)">撤回</view>
</view>
</view>
</view>
@@ -120,7 +136,7 @@
</view>
<view class="talking-info-less">
<view class="talking-text" v-if="type === 0">
{{ dataInfo.talkingContent }}
{{ showContent }}
</view>
<view class="talking-text" v-if="type === 6">
<CommonLoading color="#fff"/>
@@ -141,6 +157,7 @@ import ChartThree from "./chartThree.vue"
import common from '@/common/common';
import { getUserInfo } from '@/common/common';
import { useStorageStore } from "@/store/storage.js"
import { demoUsage } from "@/api/arraybuffer.js"
const storageStore = useStorageStore()
const audioCacheObj = computed(() => storageStore.audioObj)
@@ -200,18 +217,85 @@ const audioCacheObj = computed(() => storageStore.audioObj)
const transformContent = ref('')
const showContent = computed(() => {
return props.isTransform
? transformContent.value
: unref(dataInfo)?.pgrphContent || unref(dataInfo)?.qnsContent || unref(dataInfo)?.talkingContent || ''
if(props.isTransform){
return transformContent.value
}else{
if(props.type === 1) return unref(dataInfo)?.chatContent || unref(dataInfo)?.talkingContent
else if(props.type === 2) return unref(dataInfo)?.chatContent || unref(dataInfo)?.talkingContent
else if(props.type === 3) return unref(dataInfo)?.chatContent || unref(dataInfo)?.pgrphContent
else if(props.type === 4) return unref(dataInfo)?.chatContent || unref(dataInfo)?.qnsContent
else if(props.type === 5) return unref(dataInfo)?.chatContent || unref(dataInfo)?.evalContent
else if(props.type === 0) return unref(dataInfo)?.chatContent || unref(dataInfo)?.talkingContent
}
})
onMounted(()=>{
// demoUsage({
// question: unref(dataInfo)?.pgrphContent,
// streaming: true
// })
// getAskAboutRawApi({
// question: unref(dataInfo)?.pgrphContent,
// streaming: true
// }).then(res=>{
// }).then(async res=>{
// console.log(res)
// const reader = res.body.getReader();
// const textDecoder = new TextDecoder();
// let result = true;
// let output = "";
// while (result) {
// const { done, value } = await reader.read();
// console.log(done, value);
// let _resStr = textDecoder.decode(value);
// console.log(_resStr, 1111);
// if (_resStr.indexOf("[DONE]") < 0) {
// let _resItem = JSON.parse(_resStr);
// output += _resItem.data;
// if (_resItem.event === "end") {
// result = false;
// break;
// }
// } else {
// break;
// }
// }
// })
// let _params = new URLSearchParams({
// question: "Hey, how are you?",
// streaming: true,
// });
// fetch("/trastudy/intgask/askAbout?" + _params, {
// method: "GET",
// headers: {
// // Accept: "text/event-stream",
// "Content-Type": "text/event-stream",
// summary:
// "3D072C9D242C96EA3F0FD647CB14A6F495E1C5D01D88EB84369DC9A26309FE4F1058926C9BE6466D06AB10DAAC7D849D",
// },
// }).then(async (res) => {
// const reader = res.body.getReader();
// const textDecoder = new TextDecoder();
// let result = true;
// let output = "";
// while (result) {
// const { done, value } = await reader.read();
// console.log(done, value);
// let _resStr = textDecoder.decode(value);
// console.log(_resStr, 1111);
// if (_resStr.indexOf("[DONE]") < 0) {
// let _resItem = JSON.parse(_resStr);
// output += _resItem.data;
// if (_resItem.event === "end") {
// result = false;
// break;
// }
// } else {
// break;
// }
// }
// console.log(output);
// });
if(props.isTransform){}
})
@@ -242,7 +326,7 @@ const audioCacheObj = computed(() => storageStore.audioObj)
}
const itemVoice = ref('')
const playVoice = (readType = 'pgth') =>{
let _content = unref(dataInfo)?.pgrphContent || unref(dataInfo)?.qnsContent || unref(dataInfo)?.talkingContent || ''
let _content = showContent.value
if(!_content){
common.msg('没有可以播放的文字信息!')
return
@@ -276,7 +360,6 @@ const audioCacheObj = computed(() => storageStore.audioObj)
talkVoiceObj.value.play()
}else{
downloadVoiceFile(_url).then(res=>{
console.log(res)
if(res?.data){
common.msg(res.data.message)
return
@@ -331,7 +414,7 @@ const audioCacheObj = computed(() => storageStore.audioObj)
translateLoading.value = true
uploadVoiceFile(item.talkingVoice,{}).then(res=>{
let _data = JSON.parse(res.data)
item.talkingContent = _data.body
item.talkingContent = _data.body.text
translateLoading.value = false
}).catch(()=>{
translateLoading.value = false
@@ -339,13 +422,21 @@ const audioCacheObj = computed(() => storageStore.audioObj)
}
const showNextBtn = ref(true)
const goOnGetQues = () => {
studyParagraphOverApi({
pgrphId:unref(dataInfo)?.pgrphId,
logId:unref(dataInfo)?.logId,
}).then(res=>{
showNextBtn.value = false
if(props.type === 5){
emit('nextQuestion', unref(dataInfo))
})
}else if(props.type === 3){
// studyParagraphOverApi({
// pgrphId:unref(dataInfo)?.pgrphId,
// logId:unref(dataInfo)?.logId,
// }).then(res=>{
// showNextBtn.value = false
// })
emit('nextQuestion', unref(dataInfo), 'overGraph')
}
}
const goOnRestart = () => {
emit('nextQuestion', unref(dataInfo), 'reStart')
}
// 撤回
const withdraw = (data) => {
@@ -404,7 +495,6 @@ const audioCacheObj = computed(() => storageStore.audioObj)
height: 38rpx;
background: url(@/static/images/course/voice-gray.png) no-repeat;
background-size: contain;
margin-bottom: 16rpx;
padding-left: 168rpx;
&.is-play{
background: url(@/static/images/course/voice-gif.gif) no-repeat;
@@ -412,11 +502,15 @@ const audioCacheObj = computed(() => storageStore.audioObj)
}
}
.talking-cont{
margin-top: 16rpx;
overflow: hidden;
min-height: 48rpx;
.talking-text{
font-size: 28rpx;
line-height: 48rpx;
margin-bottom: 20rpx;
word-break: break-all;
white-space: pre-line;
}
.cont-img-box{
width: 433rpx;
@@ -458,6 +552,10 @@ const audioCacheObj = computed(() => storageStore.audioObj)
margin-top: 16rpx;
margin-right: 16rpx;
position: relative;
&.restart{
background-color: #eaf2ff;
color: #06f;
}
.icon-iamge{
width: 25rpx;
height: 25rpx;
@@ -568,7 +666,6 @@ const audioCacheObj = computed(() => storageStore.audioObj)
height: 38rpx;
background: url(@/static/images/course/voice-gray.png) no-repeat;
background-size: contain;
margin-bottom: 16rpx;
padding-left: 168rpx;
&.is-play{
background: url(@/static/images/course/voice-white.gif) no-repeat;
@@ -576,11 +673,14 @@ const audioCacheObj = computed(() => storageStore.audioObj)
}
}
.talking-cont{
margin-top: 16rpx;
overflow: hidden;
.talking-text{
font-size: 28rpx;
line-height: 48rpx;
margin-bottom: 20rpx;
word-break: break-all;
white-space: pre-line;
}
}
.btns-cont{
+192 -67
View File
@@ -5,7 +5,7 @@
<view class="course-study-body" v-show="step === 1">
<view class="seek-setting" @click="showSeekModel = true">
{{chooseRate}}
<image src="@/static/images/course/setting.png" alt=""/>
<image src="@/static/images/course/setting.png" alt="" class="image-icon"></image>
</view>
<view class="body-title">
<uv-icon class="arrow-icon" name="arrow-left" @click="common.navigateBack()"/>
@@ -39,11 +39,11 @@
<view class="course-study-body" v-show="step === 2" @click="playRecord">
<view class="seek-setting" @click="showSeekModel = true">
{{chooseRate}}
<img src="@/static/images/course/setting.png" alt="">
<image src="@/static/images/course/setting.png" alt="" class="image-icon"></image>
</view>
<view class="body-title" @click="scrollToBottomNow">
<uv-icon class="arrow-icon" name="arrow-left" @click="common.navigateBack()"/>
课程学习{{scrollTop}}
课程学习
</view>
<scroll-view
class="talking-list"
@@ -90,7 +90,8 @@
</uv-input>
</view>
<view class="talk-btn-box" @click.stop="showKeyboard">
<image class="talk-btn-icon" src="/src/static/images/course/jianpan.png" mode=""></image>
<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>
</view>
@@ -149,10 +150,13 @@ import {
queryTraStdyBatchWaitParagraphInfoApi,
audioTranscriptionsApi,
deleteTraStdyInfoByIdApi,
afreshStudyCourseApi,
queryTraStdyBatchWaitQuestionInfoApi,
studyAnswerTextUpApi,
withdrawalAnswerApi,
waitMakeEvaluateApi
waitMakeEvaluateApi,
queryQuestionEvalateApi,
textChartApi
} from "@/api/study.js"
import common from '@/common/common';
import TalkingItem from '@/pages/course/components/talkingItem.vue'
@@ -207,9 +211,9 @@ const getData = async () => {
step.value = 2
}else{
// 重新开始
// 删除学习信息
deleteTraStdyInfoByIdApi({
id:''
// 重新学习
afreshStudyCourseApi({
crsId: crsId.value,
}).then(res=>{
step.value = 1
teacherList.value = body.teacheList.map(t=>({
@@ -306,25 +310,35 @@ const pgrphNum = ref(1)
const showOrder = ref(0)
// 获取段落
const getGraphInfoUnStudy = () => {
queryTraStdyBatchWaitParagraphInfoApi({
crsId: crsId.value,
stdyId: unref(stdyId),
stdyBatch: unref(stdyBatch)
textChartApi({
processType: 'PRGH-STDY',
requestBody: JSON.stringify({
crsId: crsId.value,
stdyId: unref(stdyId),
stdyBatch: unref(stdyBatch)
})
}).then(res=>{
let _id = new Date().getTime() + 'id'
lastTalkingInfo.value = {
...res.body,
type: 3,
let _body = res.body|| {}
// if(_body.chatContent.haveNext === 'N'){}
talkingList.value.push({
crsId: crsId.value,
qstLogId: _body.chatBody,
pgrphId: _body.pgrphId,
logId:_body.chatBody.logId || '',
talkingContent: _body.chatContent,
userInfo: {...choiceTeacherInfo.value},
..._body.chatBody,
type: Number(_body.bodyTyp) || 0,
id: _id
}
talkingList.value.push(lastTalkingInfo.value)
pgrphNum.value = res.body.pgrphNum
showOrder.value = res.body.showOrder
logId.value = res.body.logId || ''
})
pgrphNum.value = _body.chatBody.pgrphNum
showOrder.value = _body.chatBody.showOrder
logId.value = _body.chatBody.logId || ''
scrollToBottomNow()
})
// common.msg('您已学完当前课程的全部内容!')
}
const lastTalkingInfo = ref({})
const qstLogId = ref('')
@@ -337,36 +351,78 @@ const getQuestionInfoUnStudy = (pgrphId) => {
logId: unref(logId),
pgrphId
}).then(res=>{
let _id = new Date().getTime() + 'id'
lastTalkingInfo.value = {
...res.body,
type: 4,
userInfo: {...choiceTeacherInfo.value},
id: _id
if(res.body.stdyStat !== 'N'){
let _id = new Date().getTime() + 'id'
lastTalkingInfo.value = {
...res.body,
type: 4,
userInfo: {...choiceTeacherInfo.value},
id: _id
}
talkingList.value.push(lastTalkingInfo.value)
qstLogId.value = res.body.qstLogId
scrollToBottomNow()
}else{
getGraphInfoUnStudy()
}
talkingList.value.push(lastTalkingInfo.value)
qstLogId.value = res.body.qstLogId
scrollToBottomNow()
})
}
// 继续 执行方法
const nextQuestionSuccess = (info) => {
const nextQuestionSuccess = (info, type='next') => {
let _id = new Date().getTime() + 'id'
talkingList.value.push({
crsId: info.crsId,
pgrphId: info.pgrphId,
talkingContent: '继续',
type: 0,
id: _id
})
scrollToBottomNow()
// getGraphInfoUnStudy()
getQuestionInfoUnStudy(info.pgrphId)
if(type === 'next'){
talkingList.value.push({
crsId: info.crsId,
pgrphId: info.pgrphId,
talkingContent: '继续',
type: 0,
id: _id
})
scrollToBottomNow(0)
getQuestionInfoUnStudy(info.pgrphId)
}else if( type = 'overGraph'){
textChartApi({
processType: 'PRGH-OVER',
requestBody: JSON.stringify({
pgrphId: info?.pgrphId,
logId: info?.logId,
})
}).then(res=>{
talkingList.value.push({
crsId: info.crsId,
pgrphId: info.pgrphId,
talkingContent: '继续',
type: 0,
id: _id
})
scrollToBottomNow(0)
getQuestionInfoUnStudy(info.pgrphId)
})
}else if( type = 'reStart'){
// 重新回答
textChartApi({
processType: 'NEW-ANSER',
requestBody: info.qstLogId
}).then(res=>{
let _body = res.body|| {}
talkingList.value.push({
crsId: info.crsId,
qstLogId: _body.chatBody,
pgrphId: info.pgrphId,
talkingContent: _body.chatContent,
userInfo: {...choiceTeacherInfo.value},
..._body.chatBody,
type: Number(_body.bodyTyp) || 0,
id: _id
})
scrollToBottomNow()
})
}
}
const scrollBoxRef = ref()
const scrollTop = ref(99999)
const scrollToBottomNow = () => {
const scrollToBottomNow = (time = 500) => {
nextTick(()=>{
setTimeout(() => {
scrollTop.value += 1
@@ -379,7 +435,7 @@ const scrollToBottomNow = () => {
duration: 300
})
}
},200)
},time)
})
}
@@ -518,9 +574,9 @@ const hideOverlayTalking = (obj) => {
stdyBatch: stdyBatch.value,// 学习批次 必输项:true 类型:String
ansterContent: '',// 回答文本内容 必输项:false 类型:String
}
let _id = new Date().getTime() + 'id'
//#ifndef APP-PLUS
// h5 假数据
let _id = new Date().getTime() + 'id'
talkingList.value.push({
crsId: crsId.value,
pgrphId: unref(lastTalkingInfo).pgrphId,
@@ -534,26 +590,59 @@ const hideOverlayTalking = (obj) => {
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'){
let _id = new Date().getTime() + 'id'
talkingList.value.push({
crsId: crsId.value,
pgrphId: unref(lastTalkingInfo).pgrphId,
qnsId: unref(lastTalkingInfo).qnsId,
talkingContent: '',
talkingVoice: audioPath.value,
intrctId: res.body||'',
type: 1,
userInfo: {...choiceTeacherInfo.value},
id: _id
// 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: err||'系统异常,请联系管理员',
title: '系统异常,请联系管理员',
icon: "none",
duration:1000
});
@@ -587,9 +676,9 @@ const showKeyboard = () => {
let _id = new Date().getTime() + 'id'
talkingList.value.push({
crsId: crsId.value,
pgrphId: unref(lastTalkingInfo).pgrphId,
qstLogId: unref(lastTalkingInfo).qstLogId,
qnsId: unref(lastTalkingInfo).qnsId,
pgrphId: _data.pgrphId,
qstLogId: _data.qstLogId,
qnsId: _data.qnsId,
talkingContent: answerValue.value,
talkingVoice: '',
intrctId: res.body||'',
@@ -626,19 +715,55 @@ const withdrawNow = (data) => {
talkingList.value = talkingList.value.filter(t => t.intrctId !== data.intrctId)
})
}
const loadingQstLogId = ref('')
// 完成
const finishQuestionNow = (data) => {
waitMakeEvaluateApi({
qstLogId: data.qstLogId
}).then(res=> {
console.log(res.body.processStat)
common.msg('完成成功,开始获取评分维度数据!')
// qstLogId 问题日志ID String
// qnsId 问题ID String
// processStat 状态 String
// message 处理消息 String
// common.msg('完成成功,开始获取评分维度数据!')
loadingQstLogId.value = res.body.qstLogId
let _id = new Date().getTime() + 'id'
talkingList.value.push({
isLoading: true,
id: _id,
userInfo: {...choiceTeacherInfo.value},
type: 5
})
scrollToBottomNow(0)
getQuestionEvalateRequest(_id,data)
})
}
// 查询问题回答评分
const getQuestionEvalateRequest = (id, data) => {
if(loadingQstLogId.value){
queryQuestionEvalateApi({
qstLogId:loadingQstLogId.value
}).then(res=>{
if(res.body && res.body.evalOver === 'Y'){
let _body = res.body
talkingList.value = talkingList.value.map(t=>{
if(t.id === id){
return {
..._body,
pgrphId: data.pgrphId,
id,
userInfo: {...choiceTeacherInfo.value},
type: 5
}
}else{
return t
}
})
scrollToBottomNow()
}else{
setTimeout(()=>{
getQuestionEvalateRequest(id, data)
}, 2 * 1000)
}
})
}
}
const showSeekModel = ref(false)
const rateList = ref(['0.5', '0.8', '1.0', '1.5', '2.0'])
@@ -680,7 +805,7 @@ const chooseRateNow = (item) => {
text-align: right;
padding-right: 48rpx;
img{
.image-icon{
width: 30rpx;
height: 32rpx;
position: absolute;