修改不缓存问答题,修改百禄形象不重新设置的问题

This commit is contained in:
田岩
2025-09-22 14:56:47 +08:00
parent aa7d58ebed
commit 9adeba89d5
12 changed files with 1944 additions and 2009 deletions
+2 -2
View File
@@ -91,11 +91,11 @@ export const commonUploadVoiceFile = (file, url, data = {}, fileKey = 'voice') =
try {
const res = JSON.parse(result.data);
if (res.rtnCode === '0000') {
return resolve(result);
return resolve(res);
} else if (REQUES_ERROR_CODES['NO_LOGIN'].includes(res.rtnCode)) {
goto_login_fun()
return reject('NO_LOGIN');
}else if(res.rtnCode === '0004') {
} else if (res.rtnCode === '0004') {
return reject('N');
}
return reject('Other');
+5 -7
View File
@@ -80,8 +80,6 @@
<script setup>
import { computed, unref, ref, toRefs, watch, onMounted, nextTick } from 'vue';
import { onUnload } from '@dcloudio/uni-app';
// import { useinnerAudio, useAudioFun } from '@/store/innerAudio';
import { useAudio } from './useAudio.js';
import { downloadFile } from '@/api/common.js';
const props = defineProps({
@@ -128,7 +126,7 @@
});
const innerAudio = useAudio();
const status = computed(() => props.status);
watch(
() => props.status,
@@ -213,22 +211,22 @@
watch(
() => props.dataInfo.voicePath,
(newVal) => {
console.log('去下载oss内容333', props.dataInfo);
if (newVal === '' && props.dataInfo.ossKey) {
// 去下载oss内容
console.log('去下载oss内容');
downloadFile(props.dataInfo.ossKey).then((res) => {
voiceTime.value = '';
innerAudio.setAudioSrc(res.tempFilePath);
});
} else if (newVal === undefined) {
innerAudio.stopAudio();
// innerAudio.stopAudio();
} else {
voiceTime.value = '';
innerAudio.setAudioSrc(newVal);
}
},
{ deep: true, immediate: true }
{ immediate: true }
);
});
onUnload(() => {
+3 -1
View File
@@ -187,7 +187,9 @@
(newVal) => {
console.log('modelValue', newVal);
item_answer.value = typeof newVal === 'string' ? newVal.split(',') : newVal;
}
},
{ deep: true }
);
// watch(
// item_answer,
+62 -75
View File
@@ -7,10 +7,7 @@
v-for="(cols, col) in colCount"
:key="col"
:style="{
left: `${col * itemWidth}px`,
transform: `rotate(${rotate}deg)`,
fontSize: `${fontSize}px`,
color: color
left: `${col * itemWidth}px`
}"
>
{{ textValue }}
@@ -20,82 +17,69 @@
</KeepAlive>
</template>
<script>
<script setup>
import { ref, onMounted } from 'vue';
import { getUserInfo } from '@/common/common';
export default {
name: 'Watermark',
props: {
text: {
type: String,
default: '李想 0613',
validator: (val) => typeof val === 'string' && val.trim() !== ''
},
// 单个水印宽度(px
itemWidth: {
type: Number,
default: 180
},
// 单个水印高度(px
itemHeight: {
type: Number,
default: 120
},
// 旋转角度(度)
rotate: {
type: Number,
default: -30
},
// 字体大小(px
fontSize: {
type: Number,
default: 16
},
// 字体颜色
color: {
type: String,
default: 'rgba(30, 30, 70, 0.1)'
},
// 是否显示
showWatermark: {
type: Boolean,
default: true
}
// 定义props
const props = defineProps({
// 单个水印宽度(px
itemWidth: {
type: Number,
default: 180
},
data() {
return {
rowCount: 0, // 行数
colCount: 0, // 列数
windowWidth: 0, // 屏幕宽度
windowHeight: 0, // 屏幕高度
textValue: ''
};
// 单个水印高度(px
itemHeight: {
type: Number,
default: 120
},
mounted() {
// 获取屏幕尺寸(App端兼容方式)
this.getWindowInfo();
const userInfo = getUserInfo();
this.textValue = (userInfo?.userName??'') + ' ' + (userInfo?.loginName??'');
},
methods: {
getWindowInfo() {
uni.getSystemInfo({
success: (res) => {
this.windowWidth = res.windowWidth;
this.windowHeight = res.windowHeight;
this.calcGridCount(); // 计算需要多少行列覆盖屏幕
}
});
},
// 计算水印网格的行列数(确保完全覆盖屏幕)
calcGridCount() {
// 列数 = 屏幕宽度 / 单个水印宽度 + 2(冗余1列避免边缘空白)
this.colCount = Math.ceil(this.windowWidth / this.itemWidth) + 2;
// 行数 = 屏幕高度 / 单个水印高度 + 2(冗余1行避免边缘空白)
this.rowCount = Math.ceil(this.windowHeight / this.itemHeight) + 2;
}
// 是否显示
showWatermark: {
type: Boolean,
default: true
}
});
// 响应式变量(替代原data
const rowCount = ref(0); // 行数
const colCount = ref(0); // 列数
const windowWidth = ref(0); // 屏幕宽度
const windowHeight = ref(0); // 屏幕高度
const textValue = ref('');
// 计算水印网格的行列数(确保完全覆盖屏幕)
const calcGridCount = () => {
// 列数 = 屏幕宽度 / 单个水印宽度 + 2(冗余1列避免边缘空白)
colCount.value = Math.ceil(windowWidth.value / props.itemWidth) + 2;
// 行数 = 屏幕高度 / 单个水印高度 + 2(冗余1行避免边缘空白)
rowCount.value = Math.ceil(windowHeight.value / props.itemHeight) + 2;
};
// 获取屏幕尺寸(App端兼容方式)
const getWindowInfo = () => {
uni.getSystemInfo({
success: (res) => {
windowWidth.value = res.windowWidth;
windowHeight.value = res.windowHeight;
calcGridCount(); // 计算需要多少行列覆盖屏幕
}
});
};
// 组件挂载时执行(替代原mounted)
onMounted(() => {
getWindowInfo();
updateWatermarkText();
});
// 提取更新文字的方法
const updateWatermarkText = () => {
const userInfo = getUserInfo();
textValue.value = `${userInfo?.userName ?? ''} ${userInfo?.loginName ?? ''}`;
};
defineExpose({
updateWatermarkText
});
</script>
<style scoped>
@@ -123,5 +107,8 @@
white-space: nowrap; /* 避免文本换行 */
user-select: none; /* 禁止选中 */
/* letter-spacing: 2px; */
color: rgba(30, 30, 70, 0.1);
font-size: 16px;
transform: rotate(-30deg);
}
</style>
+83
View File
@@ -0,0 +1,83 @@
import {
reactive,
ref,
computed,
nextTick
} from 'vue';
import {
uploadFile
} from '@/api/common';
import {
queryCurrentUser
} from '@/api/login.js';
import common from '@/common/common';
import {
updateDfSysUserExtandInfoImageAddr
} from '@/api/user.js';
export default function useUpdateAvatar({
success = () => {}
}) {
const avatarCropperUrl = ref('');
const avatarCropperStatus = ref(true);
// 点击修改头像
const click_update_avatar = () => {
uni.chooseImage({
count: 1,
sizeType: ['compressed'],
success: (resPicture) => {
uni.getFileInfo({
filePath: resPicture.tempFilePaths[0],
success: function(resSize) {
if (resSize.size > 10 * 1024 * 1024) return common.msg(
'图片过大,请重新选择');
avatarCropperUrl.value = resPicture.tempFilePaths[0];
avatarCropperStatus.value = true;
},
fail: function(err) {
common.msg('获取图片失败,请选择其他图片');
}
});
}
});
};
// 选择头像取消
const avatarOnCancel = (value) => {
avatarCropperStatus.value = false;
};
// 选择头像确定
const avatarOnConfirm = (file) => {
avatarCropperStatus.value = false;
nextTick(async () => {
common.loading('更新头像中');
try {
const data = {
bizScen: 'S3007',
thumbnailFlag: true,
thumbImgSize: 100
};
// 上传图片
const res = await uploadFile(file.tempFilePath, data);
// 更新个人信息
await updateDfSysUserExtandInfoImageAddr({
imageAddr: res.thumbFileId
});
// 更新个人信息
const userData = await queryCurrentUser();
common.msg('修改成功');
success(userData)
} catch {
common.msg('修改失败');
}
common.hideLoading();
});
};
return {
avatarCropperUrl,
avatarCropperStatus,
click_update_avatar,
avatarOnCancel,
avatarOnConfirm,
};
}
+249 -235
View File
@@ -8,32 +8,38 @@
<!-- <image src="@/static/images/course/setting.png" alt="" class="image-icon" @click.stop="showChangeBgModelNow"></image> -->
</view>
<view class="body-title">
<uv-icon class="arrow-icon" name="arrow-left" @click="backRouter()" />
<uv-icon class="arrow-icon" name="arrow-left" @click="backRouter()"/>
语言选择开启学习之旅
</view>
<view class="voice-list">
<uv-radio-group v-model="choiceTeacher">
<view class="voice-item" v-for="item in teacherList" :key="item.teacherNo" @click="choiceTeacher = item.teacherNo">
<view class="voice-item" v-for="item in teacherList" :key="item.teacherNo"
@click="choiceTeacher = item.teacherNo">
<view class="avatar-box">
<ImagePreview class="img-box" :src="item.imgAddr" :isCache="true" :width="120" :height="160"> </ImagePreview>
<ImagePreview class="img-box" :src="item.imgAddr" :isCache="true" :width="120"
:height="160"></ImagePreview>
</view>
<view class="right-cont">
<view class="right-name">{{ item.teacherName }}</view>
<view class="right-desc">描述{{ item.voiceDesc || '--' }}</view>
<view class="audio-box">
<view :class="['talking-gif', activeVoiceTeachNo === item.teacherNo && !loadingTeacherVoice ? 'is-play' : '']"> </view>
<CommonLoading color="#06f" v-show="activeVoiceTeachNo === item.teacherNo && loadingTeacherVoice" style="float: left" />
<view
:class="['talking-gif', activeVoiceTeachNo === item.teacherNo && !loadingTeacherVoice ? 'is-play' : '']"></view>
<CommonLoading color="#06f" v-show="activeVoiceTeachNo === item.teacherNo && loadingTeacherVoice"
style="float: left"/>
<view class="play-btn" @click="playTeacherVoice(item)">
<image class="icon" v-if="activeVoiceTeachNo !== item.teacherNo" src="@/static/images/course/play-blue.png" style="width: 100%; height: 100%"></image>
<image class="icon" v-else src="@/static/images/course/stop-blue.png" style="width: 100%; height: 100%"></image>
<image class="icon" v-if="activeVoiceTeachNo !== item.teacherNo"
src="@/static/images/course/play-blue.png" style="width: 100%; height: 100%"></image>
<image class="icon" v-else src="@/static/images/course/stop-blue.png"
style="width: 100%; height: 100%"></image>
</view>
</view>
</view>
<uv-radio :name="item.teacherNo" class="radio-box" @click.stop />
<uv-radio :name="item.teacherNo" class="radio-box" @click.stop/>
</view>
</uv-radio-group>
</view>
<view class="start-btns" @click="nextStep"> 开启学习之旅 </view>
<view class="start-btns" @click="nextStep"> 开启学习之旅</view>
</view>
<view :class="['course-study-body', !IsAndEnv ? 'isIos' : 'isAnd']" v-show="step === 2">
<view class="seek-setting">
@@ -43,46 +49,48 @@
</view>
</view>
<view class="body-title" @click="scrollToBottomNow">
<uv-icon class="arrow-icon" name="arrow-left" @click="backRouter()" />
<uv-icon class="arrow-icon" name="arrow-left" @click="backRouter()"/>
课程学习
</view>
<view class="study-num">
<view class="color-blue">{{ showOrder }}</view> / {{ pgrphNum }}
<view class="color-blue">{{ showOrder }}</view>
/ {{ pgrphNum }}
</view>
<scroll-view class="talking-list" :scroll-y="true" :scroll-top="scrollTop" :show-scrollbar="false" :scroll-with-animation="true">
<scroll-view class="talking-list" :scroll-y="true" :scroll-top="scrollTop" :show-scrollbar="false"
:scroll-with-animation="true">
<!-- <view class="talking-list-cont" id="scroll-box" ref="scrollBoxRef"> -->
<TalkingItem
class="talking-item"
v-for="(item, index) in talkingList"
:key="'item' + item.id"
:type="item.type"
:dataInfo="item"
:activeVoiceId="activeVoiceTalkingItemId"
:isPlaying="activeVoiceTalkingItemId === item.id"
:voiceRate="chooseRate"
:lastQuestionInfo="lastTalkingInfo"
:teacherInfo="choiceTeacherInfo"
@changePlay="changePlayItemId"
@nextQuestion="nextQuestionSuccess"
@withdraw="withdrawNow"
@answerQuestion="answerQuestionNow"
@finishQuestion="finishQuestionNow"
:id="'item' + item.id"
:isLast="talkingList.length === index + 1"></TalkingItem>
class="talking-item"
v-for="(item, index) in talkingList"
:key="'item' + item.id"
:type="item.type"
:dataInfo="item"
:activeVoiceId="activeVoiceTalkingItemId"
:isPlaying="activeVoiceTalkingItemId === item.id"
:voiceRate="chooseRate"
:lastQuestionInfo="lastTalkingInfo"
:teacherInfo="choiceTeacherInfo"
@changePlay="changePlayItemId"
@nextQuestion="nextQuestionSuccess"
@withdraw="withdrawNow"
@answerQuestion="answerQuestionNow"
@finishQuestion="finishQuestionNow"
:id="'item' + item.id"
:isLast="talkingList.length === index + 1"></TalkingItem>
<!-- <video v-if="videoUrlShow" :src="videoUrlShow" controls></video> -->
<!-- </view> -->
</scroll-view>
<TouchBtn
class="talk-btns"
@uploadVoice="uploadRecordNow"
@submitAnswer="submitAnswerNow"
@startRecord="changePlayItemId('')"
:isLoading="isUploadingVoice"
:onlyVoice="answerOnlyVoice"
:canAnswer="testAnswer"
:adjustPosition="true"
:canAnswerText="canAnswerText"
:isDisabled="(lastTalkingInfo.type || 0) !== 4 || ['SN', 'MU', 'JD'].includes(lastTalkingInfo.qnsTyp)" />
class="talk-btns"
@uploadVoice="uploadRecordNow"
@submitAnswer="submitAnswerNow"
@startRecord="changePlayItemId('')"
:isLoading="isUploadingVoice"
:onlyVoice="answerOnlyVoice"
:canAnswer="testAnswer"
:adjustPosition="true"
:canAnswerText="canAnswerText"
:isDisabled="(lastTalkingInfo.type || 0) !== 4 || ['SN', 'MU', 'JD'].includes(lastTalkingInfo.qnsTyp)"/>
</view>
<uv-overlay :show="showSeekModel" opacity=".6" @click="showSeekModel = false">
<view class="overlay-box">
@@ -99,17 +107,19 @@
<uv-overlay :show="showBgModel" opacity=".6" @click="showBgModel = false">
<view class="overlay-box">
<view class="white-bg-box-setting white-bg-box">
<view class="box-title">设置 </view>
<view class="box-title">设置</view>
<view class="box-items" @click.stop>
<view class="box-item">
<view class="box-item-title">音色</view>
<uv-radio-group v-model="choiceTeacher" class="box-item-cont">
<view class="overlay-voice-item" v-for="item in teacherList" :key="item.teacherNo" @click="changeTeacherVoiceNow(item)">
<view class="overlay-voice-item" v-for="item in teacherList" :key="item.teacherNo"
@click="changeTeacherVoiceNow(item)">
<view class="overlay-avatar-box">
<ImagePreview class="overlay-img-box" :src="item.imgAddr" :isCache="true" :width="120" :height="160"></ImagePreview>
<ImagePreview class="overlay-img-box" :src="item.imgAddr" :isCache="true" :width="120"
:height="160"></ImagePreview>
</view>
<view class="overlay-teacher-name">{{ item.teacherName }}</view>
<uv-radio :name="item.teacherNo" class="overlay-radio-box" @click.stop />
<uv-radio :name="item.teacherNo" class="overlay-radio-box" @click.stop/>
</view>
</uv-radio-group>
</view>
@@ -121,37 +131,37 @@
</template>
<script setup>
import { reactive, ref, computed, unref, onMounted, onUnmounted, getCurrentInstance, nextTick } from 'vue'
import { onLoad, onShow, onUnload, onHide } from '@dcloudio/uni-app'
import { previewFile, downloadFile, commonUploadVoiceFile, downloadVoiceFile, uploadVoiceFile } from '@/api/common.js'
import { getToken, getPhoneEnvBool } from '@/common/common.js'
import { get_base_url, goto_login_fun } from '@/api/request'
import {
getCourseStudyInfoApi,
afreshStudyCourseApi,
queryQuestionEvalateApi,
textChartApi,
setStudyTeacherApi,
textChartPreviewApi,
previewAfreshStudyCourse,
studyEndApi,
studyStartApi
import {reactive, ref, computed, unref, onMounted, onUnmounted, getCurrentInstance, nextTick} from 'vue'
import {onLoad, onShow, onUnload, onHide} from '@dcloudio/uni-app'
import {previewFile, downloadFile, commonUploadVoiceFile, downloadVoiceFile, uploadVoiceFile} from '@/api/common.js'
import {getToken, getPhoneEnvBool} from '@/common/common.js'
import {get_base_url, goto_login_fun} from '@/api/request'
import {
getCourseStudyInfoApi,
afreshStudyCourseApi,
queryQuestionEvalateApi,
textChartApi,
setStudyTeacherApi,
textChartPreviewApi,
previewAfreshStudyCourse,
studyEndApi,
studyStartApi
} from '@/api/study.js'
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'
import { storeToRefs } from 'pinia'
import {useSocketStore} from '@/store/socket.js'
import {useStorageStore} from '@/store/storage.js'
import {storeToRefs} from 'pinia'
const socketStore = useSocketStore()
const storageStore = useStorageStore()
const { SocketObj } = storeToRefs(socketStore)
const {SocketObj} = storeToRefs(socketStore)
const audioCacheObj = computed(() => storageStore.audioObj)
const { proxy } = getCurrentInstance()
const {proxy} = getCurrentInstance()
const crsNum = ref('')
const crsId = ref('')
const step = ref(0)
@@ -169,7 +179,7 @@ const IsAndEnv = ref(getPhoneEnvBool('AND'))
const ajaxApi = computed(() => (isPreview.value ? textChartPreviewApi : textChartApi))
const { statusBarHeight } = uni.getWindowInfo()
const {statusBarHeight} = uni.getWindowInfo()
const pageTopPadding = computed(() => statusBarHeight + 'px')
@@ -178,7 +188,7 @@ const isContinue = ref('N')
const getData = async flag => {
isContinue.value = 'N'
try {
const { body } = await getCourseStudyInfoApi({
const {body} = await getCourseStudyInfoApi({
crsId: crsId.value
})
teacherList.value = body.teacheList.map(t => ({
@@ -211,29 +221,30 @@ const getData = async flag => {
return
}
common
.show('提示', '系统检测到您已存在学习记录,要继续学习吗?', true, '重新学习', '继续学习')
.then(res => {
if (res) {
// 继续学习 获取学习历史接口
// 滚动到最下面
scrollToBottomNow()
isContinue.value = 'Y'
sendMessage({
commond: 'STDY',
body: {
crsId: crsId.value,
teacherNo: choiceTeacher.value,
studyType: isPreview.value ? 'P' : 'S',
isContinue: isContinue.value
}
})
step.value = 2
} else {
// 重新学习
resStartStudyNow(body.teacheList)
}
})
.finally(() => {})
.show('提示', '系统检测到您已存在学习记录,要继续学习吗?', true, '重新学习', '继续学习')
.then(res => {
if (res) {
// 继续学习 获取学习历史接口
// 滚动到最下面
scrollToBottomNow()
isContinue.value = 'Y'
sendMessage({
commond: 'STDY',
body: {
crsId: crsId.value,
teacherNo: choiceTeacher.value,
studyType: isPreview.value ? 'P' : 'S',
isContinue: isContinue.value
}
})
step.value = 2
} else {
// 重新学习
resStartStudyNow(body.teacheList)
}
})
.finally(() => {
})
}
}
} catch {
@@ -242,15 +253,16 @@ const getData = async flag => {
}
}
const startStudy = (data) => {
studyStartApi(data).then(res=>{
const { body } = res
stdyId.value = body.stdyId || ''
stdyBatch.value = body.stdyBatch || ''
oldStdyId.value = body.oldStdyId || ''
logId.value = body.logId || ''
getGraphInfoUnStudy(1)
step.value = 2
}).catch(err=>{})
studyStartApi(data).then(res => {
const {body} = res
stdyId.value = body.stdyId || ''
stdyBatch.value = body.stdyBatch || ''
oldStdyId.value = body.oldStdyId || ''
logId.value = body.logId || ''
getGraphInfoUnStudy(1)
step.value = 2
}).catch(err => {
})
}
// 重新学习
const resStartStudyNow = ($list = []) => {
@@ -259,22 +271,22 @@ const resStartStudyNow = ($list = []) => {
_ajax({
crsId: crsId.value
})
.then(res => {
step.value = 1
teacherList.value = $list.map(t => ({
...t,
voicePath: '',
voiceObj: null
}))
})
.catch(e => {
step.value = 1
teacherList.value = $list.map(t => ({
...t,
voicePath: '',
voiceObj: null
}))
})
.then(res => {
step.value = 1
teacherList.value = $list.map(t => ({
...t,
voicePath: '',
voiceObj: null
}))
})
.catch(e => {
step.value = 1
teacherList.value = $list.map(t => ({
...t,
voicePath: '',
voiceObj: null
}))
})
}
const showChangeSeekModelNow = () => {
@@ -419,26 +431,28 @@ const getGraphInfoUnStudy = (flag = 0) => {
uni.$emit('refresh_course_list', crsId.value)
if (isPreview.value) {
common
.show('提示', '您已学完全部知识点', false)
.then(res => {
common.navigateBack()
// common.redirectTo(`/pages/courseDetail/index?crsId=${crsId.value}&crsNum=${crsNum.value}&from=study&isPreview=true`)
})
.finally(() => {})
.show('提示', '您已学完全部知识点', false)
.then(res => {
common.navigateBack()
// common.redirectTo(`/pages/courseDetail/index?crsId=${crsId.value}&crsNum=${crsNum.value}&from=study&isPreview=true`)
})
.finally(() => {
})
} else {
common
.show('恭喜你已学完全部知识点', '有什么心得跟我们分享吗?', true, '取消', '去评论')
.then(res => {
if (res) {
// 去评论
common.redirectTo(`/pages/courseDetail/submit?crsId=${crsId.value}&crsNum=${crsNum.value}&from=study&imgId=${imageId.value}`)
} else {
// 取消
common.navigateBack()
// common.redirectTo(`/pages/courseDetail/index?crsId=${crsId.value}&crsNum=${crsNum.value}&from=study`)
}
})
.finally(() => {})
.show('恭喜你已学完全部知识点', '有什么心得跟我们分享吗?', true, '取消', '去评论')
.then(res => {
if (res) {
// 去评论
common.redirectTo(`/pages/courseDetail/submit?crsId=${crsId.value}&crsNum=${crsNum.value}&from=study&imgId=${imageId.value}`)
} else {
// 取消
common.navigateBack()
// common.redirectTo(`/pages/courseDetail/index?crsId=${crsId.value}&crsNum=${crsNum.value}&from=study`)
}
})
.finally(() => {
})
}
return
@@ -680,7 +694,7 @@ const logId = ref('')
const initsocketTask = () => {
socketStore.creatSocket()
unref(SocketObj).on('message', res => {
const { rtnCode, body, commond } = JSON.parse(res.data)
const {rtnCode, body, commond} = JSON.parse(res.data)
if (rtnCode === '0000') {
if (commond === 'STDYBTH' && !stdyId.value) {
stdyId.value = body.stdyId || ''
@@ -702,7 +716,7 @@ const reconnect = () => {
}
const sendMessage = data => {
// unref(SocketObj).send(data)
startStudy(data.body)
startStudy(data.body)
}
// ws 结束
const startPgrphId = ref('')
@@ -744,15 +758,15 @@ const changeAppHeightBottom = height => {
// #endif
}
const closeStudy = () => {
return studyEndApi({
stdyId: stdyId.value
})
return studyEndApi({
stdyId: stdyId.value
})
}
onHide(() => {
changePlayItemId('')
if(isPreview.value === 'S'){
closeStudy()
}
if (isPreview.value === 'S') {
closeStudy()
}
// socketStore.closeSocket()
//#ifdef APP-PLUS
uni.offKeyboardHeightChange(setHeight)
@@ -769,29 +783,30 @@ onShow(() => {
if (watchFlag.value === 1) return
// getData('2');
// initsocketTask()
if(isPreview.value === 'S'){
studyStartApi({
crsId: crsId.value,
teacherNo: choiceTeacher.value,
studyType: isPreview.value ? 'P' : 'S',
isContinue: isContinue.value,
stdyId: stdyId.value
}).then(res=>{
const { body } = res
stdyId.value = body.stdyId || ''
stdyBatch.value = body.stdyBatch || ''
oldStdyId.value = body.oldStdyId || ''
logId.value = body.logId || ''
step.value = 2
}).catch(err=>{})
}
if (isPreview.value === 'S') {
studyStartApi({
crsId: crsId.value,
teacherNo: choiceTeacher.value,
studyType: isPreview.value ? 'P' : 'S',
isContinue: isContinue.value,
stdyId: stdyId.value
}).then(res => {
const {body} = res
stdyId.value = body.stdyId || ''
stdyBatch.value = body.stdyBatch || ''
oldStdyId.value = body.oldStdyId || ''
logId.value = body.logId || ''
step.value = 2
}).catch(err => {
})
}
})
const watchFlag = ref(1)
onUnload(() => {
console.log('onUnload')
if(isPreview.value === 'S'){
closeStudy()
}
if (isPreview.value === 'S') {
closeStudy()
}
// socketStore.closeSocket()
changePlayItemId('')
console.log(typeof teacherVoiceObj)
@@ -799,7 +814,8 @@ onUnload(() => {
teacherVoiceObj?.stop()
teacherVoiceObj.src = ''
// 0910杨航叫我这么改的
} catch {}
} catch {
}
})
const testAnswer = computed(() => {
if (talkingList.value.length < 5) return true
@@ -862,10 +878,7 @@ const uploadRecordNow = voicePath => {
processType: 'ANSER-VOICE',
requestBody: JSON.stringify(_data)
})
.then(res => {
let _res = JSON.parse(res.data)
console.log(_res)
if (_res.rtnCode === '0000') {
.then(_res => {
talkingList.value = talkingList.value.map(t => {
if (t.id === _id) {
return {
@@ -890,20 +903,19 @@ const uploadRecordNow = voicePath => {
})
console.log(11111, _res.body.chatBody)
scrollToBottomNow()
} else {
}
setIsUploadingVoice()
})
.catch(err => {
console.log('err', err)
setIsUploadingVoice()
talkingList.value = talkingList.value.filter(t => t.id !== _id)
uni.showToast({
title: err.message || '系统异常,请联系管理员',
icon: 'none',
duration: 1000
setIsUploadingVoice()
})
.catch(err => {
console.log('err', err)
setIsUploadingVoice()
talkingList.value = talkingList.value.filter(t => t.id !== _id)
uni.showToast({
title: err.message || '系统异常,请联系管理员',
icon: 'none',
duration: 1000
})
})
})
// #endif
}
const setIsUploadingVoice = (flag = false) => {
@@ -936,33 +948,33 @@ const submitAnswerNow = (val, cb) => {
processType: 'ANSER-TEXT',
requestBody: JSON.stringify(_data)
})
.then(res => {
setIsUploadingVoice()
let _id = new Date().getTime() + 'id'
let _body = res.body || {}
if (!_body.chatBody) {
return
}
talkingList.value.push({
..._data,
chatContent: _body.chatContent,
recordId: _body.chatBody.recordId,
stdyPgrphId: _body.chatBody.stdyPgrphId,
talkingContent: val,
talkingVoice: '',
type: 2,
userInfo: {
...choiceTeacherInfo.value
},
qstLogId: qstLogId.value,
id: _id
.then(res => {
setIsUploadingVoice()
let _id = new Date().getTime() + 'id'
let _body = res.body || {}
if (!_body.chatBody) {
return
}
talkingList.value.push({
..._data,
chatContent: _body.chatContent,
recordId: _body.chatBody.recordId,
stdyPgrphId: _body.chatBody.stdyPgrphId,
talkingContent: val,
talkingVoice: '',
type: 2,
userInfo: {
...choiceTeacherInfo.value
},
qstLogId: qstLogId.value,
id: _id
})
scrollToBottomNow()
cb && cb()
})
.catch(() => {
setIsUploadingVoice()
})
scrollToBottomNow()
cb && cb()
})
.catch(() => {
setIsUploadingVoice()
})
}
// 撤回
const withdrawNow = data => {
@@ -1038,40 +1050,40 @@ const finishQuestionNow = data => {
asrStartTm: data.asrStartTm
})
})
.then(res => {
// common.msg('完成成功,开始获取评分维度数据!')
let _state = res.body.chatBody.isWait
if (_state !== 'Y') {
common.msg('提交答案失败!')
return
}
let _id1 = new Date().getTime() + '3d'
talkingList.value.push({
id: _id1,
talkingContent: '完成',
userInfo: {
...choiceTeacherInfo.value
},
type: 0
.then(res => {
// common.msg('完成成功,开始获取评分维度数据!')
let _state = res.body.chatBody.isWait
if (_state !== 'Y') {
common.msg('提交答案失败!')
return
}
let _id1 = new Date().getTime() + '3d'
talkingList.value.push({
id: _id1,
talkingContent: '完成',
userInfo: {
...choiceTeacherInfo.value
},
type: 0
})
loadingExecLogId.value = res.body.chatBody.execLogId
qstLogId.value = loadingExecLogId.value
let _id = new Date().getTime() + 'id'
lastTalkingInfo.value = {
isLoading: true,
id: _id,
userInfo: {
...choiceTeacherInfo.value
},
type: 5
}
talkingList.value.push(JSON.parse(JSON.stringify(lastTalkingInfo.value)))
scrollToBottomNow(0)
getQuestionEvalateRequest(_id, data, 1)
})
.catch(err => {
console.log(err)
})
loadingExecLogId.value = res.body.chatBody.execLogId
qstLogId.value = loadingExecLogId.value
let _id = new Date().getTime() + 'id'
lastTalkingInfo.value = {
isLoading: true,
id: _id,
userInfo: {
...choiceTeacherInfo.value
},
type: 5
}
talkingList.value.push(JSON.parse(JSON.stringify(lastTalkingInfo.value)))
scrollToBottomNow(0)
getQuestionEvalateRequest(_id, data, 1)
})
.catch(err => {
console.log(err)
})
}
// 查询问题回答评分
const getQuestionEvalateRequest = (id, data, num) => {
@@ -1198,9 +1210,11 @@ const chooseRateNow = item => {
display: flex;
flex-direction: column;
padding-top: v-bind(pageTopPadding);
&.isAnd {
height: calc(100% - v-bind(totalBotHeight));
}
.body-title {
height: 90rpx;
text-align: center;
+31 -29
View File
@@ -162,6 +162,7 @@
import { commonUploadVoiceFile } from '@/api/common.js';
import { optionErrorIcon, examinationSheetIcon, practiceExitIcon } from '@/common/imgSvg';
import { commitPaperExam, commitCrsExam, commitPaperCache } from '@/api/examination.js';
const answerIsOver = ref(true);
const feedbackRef = ref(null);
const dialogRef = ref(null);
@@ -307,24 +308,20 @@
topic.es_status = '00'; // 00转圈
const voicePath = submitObj;
commonUploadVoiceFile(voicePath, '/traask/traAskchat/voiceTrans', {})
.then((res) => {
let _res = JSON.parse(res.data);
console.log('voicePath_res_res_res', _res);
if (_res.rtnCode === '0000') {
const _content = _res.body.transContent.trim();
if (_content === '') {
topic.es_status = ''; // 取消转圈
return common.msg('未识别到文字');
} else {
topic.es_status = '02';
topic.my_answer = {
anserResult: _res.body.transContent,
ossKey: _res.body.fileId,
ossAddr: _res.body.ossFileAddr,
voicePath: voicePath
};
hand_in_paper_cache();
}
.then((_res) => {
const _content = _res.body.transContent.trim();
if (_content === '') {
topic.es_status = ''; // 取消转圈
return common.msg('未识别到文字');
} else {
topic.es_status = '02';
topic.my_answer = {
anserResult: _res.body.transContent,
ossKey: _res.body.fileId,
ossAddr: _res.body.ossFileAddr,
voicePath: voicePath
};
hand_in_paper_cache();
}
})
.catch((error) => {
@@ -344,7 +341,6 @@
const answerCacheList = ref({});
const setAnswerCacheList = (value) => {
console.log('触发变化', value);
answerCacheList.value = value;
common.setValue(examinationAnswerCacheKey, value);
};
@@ -390,9 +386,10 @@
paperData.flagQueryDetail = examination.flagQueryDetail || 'Y';
mode = paperData.examId ? 'PAPERS' : 'CRS'; // 课程考试CRS,考试中心考试PAPERS
// 设置缓存的键的名称
const suffix = mode === 'PAPERS' ? paperData.examId : paperData.crsId;
examinationAnswerCacheKey = 'examinationAnswerCache' + suffix;
examinationAnswerCacheKey = 'examinationAnswerCache' + paperData.execId;
answerCacheList.value = common.getValue(examinationAnswerCacheKey);
console.log('assaasas', answerCacheList.value);
if (typeof answerCacheList.value !== 'object') {
answerCacheList.value = {};
paperData.isCacheExam = 'N';
@@ -437,18 +434,18 @@
return [];
}
// 校验缓存列表是否存在且为对象类型
if (!answerCacheList?.value || typeof answerCacheList.value !== 'object') {
return [];
}
// if (!answerCacheList.value || typeof answerCacheList.value !== 'object') {
// return [];
// }
// 校验问题ID是否有效
if (!res || typeof res.qnsId === 'undefined') {
return [];
}
// if (!res || typeof res.qnsId === 'undefined') {
// return [];
// }
// 检查缓存中是否存在该问题的答案
if (res.qnsId in answerCacheList.value) {
const cachedAnswer = answerCacheList.value[res.qnsId];
// 确保返回值是数组类型(根据原逻辑推测应该返回数组)
return Array.isArray(cachedAnswer) ? cachedAnswer : [];
return cachedAnswer;
}
// 缓存中不存在时返回空数组
return [];
@@ -611,7 +608,6 @@
const hand_in_paper_cache = () => {
// 获取当前题目
addTopicAnswerCache();
const answerDtoList = getAnswerDtoList();
console.log('answerDtoList', answerDtoList);
commitPaperCache({
@@ -724,11 +720,13 @@
height: 30rpx;
}
}
.sheet_table_scroll {
max-height: calc(80vh - 180rpx);
// background-color: red;
width: calc(100vw - 108rpx);
}
.sheet_table {
width: 100%;
@@ -910,12 +908,15 @@
align-items: center;
width: 242rpx;
flex-wrap: nowrap;
.grey {
margin-right: 8rpx;
}
.countdown_time {
white-space: nowrap;
}
:deep(.uv-count-down__text) {
color: #ffffff !important;
font-weight: 600;
@@ -959,6 +960,7 @@
display: flex;
align-items: center;
justify-content: flex-end;
.img {
width: 32rpx;
height: 32rpx;
+29 -28
View File
@@ -1,7 +1,5 @@
<template>
<view class="index-dialog-page">
<watermark></watermark>
<!-- <MarkdownPreview/> -->
<view class="top-bg"></view>
<view class="bot-bg"></view>
@@ -134,9 +132,12 @@
<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" /> -->
<!-- 水印组件 -->
<watermark ref="watermarkRef"></watermark>
</template>
<script setup>
@@ -171,6 +172,7 @@
const { SocketObj } = storeToRefs(socketStore);
const feedbackRef = ref();
const watermarkRef = ref();
const userInfo = ref(getUserInfo());
const questionList = ref([
// '对公小程序开户流程?',
@@ -660,32 +662,28 @@
});
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 {
}
.then((_res) => {
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
});
}
})
.catch((err) => {
talkingList.value.pop();
@@ -842,6 +840,9 @@
});
onShow(() => {
uni.onKeyboardHeightChange(setHeight);
nextTick(() => {
watermarkRef.value?.updateWatermarkText();
});
});
// #endif
onUnload(() => {
+9 -62
View File
@@ -137,8 +137,8 @@
:width="500"
:height="500"
:delay="150"
@cancel="onCancel"
@confirm="onConfirm"
@cancel="avatarOnCancel"
@confirm="avatarOnConfirm"
></avatar-cropper>
</view>
</template>
@@ -157,6 +157,13 @@
import { setMascot } from '@/common/mascot.js';
import { queryCurrentUser } from '@/api/login.js';
import { defaultAvatar } from '@/enum.js';
import useUpdateAvatar from '@/composables/useUpdateAvatar';
const { avatarCropperUrl, click_update_avatar, avatarCropperStatus, avatarOnCancel, avatarOnConfirm } = useUpdateAvatar({
success: (userData) => {
user_info.imageAddr = userData.imageAddr;
user_info.imagePath = '';
}
});
const badgeList = [
{
name: '黑铁',
@@ -209,7 +216,6 @@
const click_loginout = () => {
common.show('确定退出登录?').then(async (res) => {
console.log(res);
if (!res) return;
try {
common.loading('正在退出登录');
@@ -221,7 +227,6 @@
common.reLaunch('/pages/login/login');
});
};
onLoad(() => {});
onShow(() => {
setMascot();
Object.assign(user_info, getUserInfo());
@@ -229,64 +234,6 @@
onPullDownRefresh(() => {
uni.stopPullDownRefresh();
});
//
const avatarCropperStatus = ref(true);
const avatarCropperUrl = ref('');
//
const click_update_avatar = () => {
uni.chooseImage({
count: 1,
sizeType: ['compressed'],
success: (resPicture) => {
uni.getFileInfo({
filePath: resPicture.tempFilePaths[0],
success: function (resSize) {
if (resSize.size > 10 * 1024 * 1024) return common.msg('图片过大,请重新选择');
avatarCropperUrl.value = resPicture.tempFilePaths[0];
avatarCropperStatus.value = true;
},
fail: function (err) {
common.msg('获取图片失败,请选择其他图片');
}
});
}
});
};
//
const onCancel = (value) => {
avatarCropperStatus.value = false;
};
//
const onConfirm = (file) => {
avatarCropperStatus.value = false;
nextTick(async () => {
common.loading('更新头像中');
try {
const data = {
bizScen: 'S3007',
thumbnailFlag: true,
thumbImgSize: 100
};
//
const res = await uploadFile(file.tempFilePath, data);
//
await updateDfSysUserExtandInfoImageAddr({
imageAddr: res.thumbFileId
});
//
const userData = await queryCurrentUser();
console.log('userData', userData);
common.msg('修改成功');
user_info.imageAddr = userData.imageAddr;
user_info.imagePath = '';
} catch (e) {
console.log('sss', e);
common.msg('修改失败');
}
common.hideLoading();
});
};
</script>
<style scoped lang="scss">
File diff suppressed because it is too large Load Diff
+14 -120
View File
@@ -20,37 +20,8 @@
</view>
</template>
</uv-cell>
<!-- <uv-cell name="sex" isLink title="性别">
<template #title>
<text class="font_pf">性别</text>
</template>
<template #value>
<picker
mode="selector"
:value="index"
range-key="label"
style="width: 100%"
:range="sexOptions"
@change="sexChange"
>
<view style="text-align: right">{{ showGenderText }}</view>
</picker>
</template>
</uv-cell> -->
<uv-cell title="性别" @click="sexPicker.open()" :isLink="true" :value="showGenderText"></uv-cell>
<uv-cell title="百禄形象" @click="gotoMascot()" :isLink="true" :border="false" :value="mascotName"></uv-cell>
<!-- <uv-cell :isLink="true" :border="false">
<template #title>
<text class="font_pf">竞赛是否匿名</text>
</template>
<template #value>
<picker mode="selector" :value="index" range-key="label" style="width: 100%"
:range="anonymousOptions" @change="anonymousChange">
<view style="text-align: right">{{showAnonymousText}}</view>
</picker>
</template>
</uv-cell> -->
</uv-cell-group>
</view>
<avatar-cropper
@@ -60,8 +31,8 @@
:width="500"
:height="500"
:delay="150"
@cancel="onCancel"
@confirm="onConfirm"
@cancel="avatarOnCancel"
@confirm="avatarOnConfirm"
></avatar-cropper>
<uv-picker ref="sexPicker" :columns="[sexOptions]" keyName="label" @confirm="sexConfirm"></uv-picker>
</view>
@@ -69,26 +40,31 @@
<script setup>
import { reactive, ref, computed, nextTick } from 'vue';
import { onLoad } from '@dcloudio/uni-app';
import { onLoad, onShow } from '@dcloudio/uni-app';
import { uploadFile } from '@/api/common';
import { queryCurrentUser } from '@/api/login.js';
import common from '@/common/common';
import { getUserInfo } from '@/common/common';
import { GENDER } from '@/enum.js';
import { updateDfSysUserExtandInfoGender, updateDfSysUserExtandInfoImageAddr } from '@/api/user.js';
import { updateDfSysUserExtandInfoGender } from '@/api/user.js';
import { queryValidTraMascotInfo } from '@/api/mascot.js';
import { get_base_url } from '@/api/request.js';
const index = ref(0);
const sexPicker = ref(null);
const avatarCropperUrl = ref('');
const userInfo = ref({
gender: '',
imagePath: '',
imageAddr: '',
mascotInfo: null
});
const avatarCropperStatus = ref(true);
import useUpdateAvatar from '@/composables/useUpdateAvatar';
const { avatarCropperUrl, click_update_avatar, avatarCropperStatus, avatarOnCancel, avatarOnConfirm } = useUpdateAvatar({
success: (userData) => {
userInfo.value.imageAddr = userData.imageAddr;
userInfo.value.imagePath = '';
}
});
const mascotName = computed(() => userInfo.value.mascotInfo?.mascotName || '');
const sexOptions = GENDER;
const anonymousOptions = [
@@ -106,7 +82,7 @@
const gotoMascot = () => {
common.navigateTo('/pages/mascot/mascot_select_list?from=setting');
};
//
const showGenderText = computed(() => {
const item = sexOptions.find((item) => item.value === userInfo.value.gender);
@@ -117,67 +93,6 @@
}
});
//
const showAnonymousText = computed(() => {
const item = anonymousOptions.find((item) => item.value === userInfo.value?.anonymous);
if (item) {
return item.label;
} else {
return '否';
}
});
//
const click_update_avatar = () => {
uni.chooseImage({
count: 1,
sizeType: ['compressed'],
success: (resPicture) => {
uni.getFileInfo({
filePath: resPicture.tempFilePaths[0],
success: function (resSize) {
if (resSize.size > 10 * 1024 * 1024) return common.msg('图片过大,请重新选择');
avatarCropperUrl.value = resPicture.tempFilePaths[0];
avatarCropperStatus.value = true;
},
fail: function (err) {
common.msg('获取图片失败,请选择其他图片');
}
});
}
});
};
//
const onCancel = (value) => {
avatarCropperStatus.value = false;
};
//
const onConfirm = (file) => {
avatarCropperStatus.value = false;
nextTick(async () => {
common.loading('更新头像中');
try {
const data = {
bizScen: 'S3007',
thumbnailFlag: true,
thumbImgSize: 100
};
//
const res = await uploadFile(file.tempFilePath, data);
//
await updateDfSysUserExtandInfoImageAddr({
imageAddr: res.thumbFileId
});
//
const userData = await queryCurrentUser();
common.msg('修改成功');
userInfo.value.imageAddr = userData.imageAddr;
userInfo.value.imagePath = '';
} catch {
common.msg('修改失败');
}
common.hideLoading();
});
};
//
const sexConfirm = (e) => {
userInfo.value.gender = e.value[0].value;
@@ -193,29 +108,8 @@
common.hideLoading();
});
};
// const sexChange = (e) => {
// userInfo.value.gender = sexOptions[e.detail.value].value;
// console.log('userInfo.value.gender', userInfo.value.gender);
// common.loading('');
// updateDfSysUserExtandInfoGender({
// gender: userInfo.value.gender
// })
// .then(async () => {
// await queryCurrentUser();
// common.msg('');
// })
// .finally(() => {
// common.hideLoading();
// });
// };
const anonymousChange = (e) => {
userInfo.value.anonymous = anonymousOptions[e.detail.value].value;
common.msg('修改成功');
};
onLoad((params) => {
onShow((params) => {
userInfo.value = getUserInfo();
console.log('userInfo.value', userInfo.value);
});
File diff suppressed because it is too large Load Diff