开发完错题本

This commit is contained in:
田岩
2025-08-30 20:31:58 +08:00
parent 859248fc6a
commit 05b89f91ca
20 changed files with 396 additions and 232 deletions
+1 -3
View File
@@ -23,15 +23,13 @@ VITE_APP_BASE_API_Url = 'https://aitstest.jlbank.com.cn:7001'
# VITE_APP_BASE_H5_API_Url = 'http://25.64.16.130:9602' # VITE_APP_BASE_H5_API_Url = 'http://25.64.16.130:9602'
# 线上 # 线上
# VITE_APP_BASE_H5_API_Url = 'https://aitstest.jlbank.com.cn:7001' # VITE_APP_BASE_H5_API_Url = 'https://aitstest.jlbank.com.cn:7002'
VITE_APP_BASE_H5_API_Url = 'http://25.18.122.65:7001' VITE_APP_BASE_H5_API_Url = 'http://25.18.122.65:7001'
#VITE_APP_BASE_H5_API_Url = 'http://25.18.122.116:7001' #VITE_APP_BASE_H5_API_Url = 'http://25.18.122.116:7001'
# VITE_APP_BASE_H5_API_Url_TRAAPP = 'http://25.64.16.130:9601' # VITE_APP_BASE_H5_API_Url_TRAAPP = 'http://25.64.16.130:9601'
# VITE_APP_BASE_H5_API_Url_TRASTUDY = 'http://25.64.16.130:9602' # VITE_APP_BASE_H5_API_Url_TRASTUDY = 'http://25.64.16.130:9602'
# VITE_APP_BASE_H5_API_Url_TRAASK = 'http://25.64.16.144:9605' # VITE_APP_BASE_H5_API_Url_TRAASK = 'http://25.64.16.144:9605'
+9 -4
View File
@@ -97,13 +97,18 @@ export default function request({
const res = response.data const res = response.data
if (res?.rtnCode === '0000') { if (res?.rtnCode === '0000') {
return resolve(res) return resolve(res)
} else if (toastErrors) { } else if (res?.rtnCode === '0001') { // 为前后端约定不公共拦截的码值(王洋洋20250830定)
// common.msg(res?.message) return reject(res)
} else if (res?.rtnCode === '0002' && res?.message) {
if (toastErrors) {
common.msg(res.message)
}
return reject(response)
} }
//到这里下面全是异常的处理 //到这里下面全是异常的处理
if (suppressErrors) { // 静默的接口,报错也不处理,因为下面有公共处理 if (suppressErrors) { // 静默的接口,报错也不处理,因为下面有公共处理
return reject() return reject(response)
} }
if (!res) { if (!res) {
common.msg("系统异常.") common.msg("系统异常.")
+1 -1
View File
@@ -37,7 +37,7 @@ export const queryMistakesAnswerByMisId = (data) => {
return request({ return request({
url: base_url + '/traMistakesCollection/queryMistakesAnswerByMisId ', url: base_url + '/traMistakesCollection/queryMistakesAnswerByMisId ',
method: 'post', method: 'post',
toastErrors: true, toastErrors: false,
data data
}); });
}; };
+36 -23
View File
@@ -51,13 +51,13 @@
<view class="back-icon"></view> <view class="back-icon"></view>
</view> </view>
<view class="fl1"></view> <view class="fl1"></view>
<view class="num-item" @click="collect_click(form.collectId)"> <view class="num-item" @click="collect_click(form.collectId)">
<image <image
class="collect-icon" class="collect-icon"
:src="form.collectId ? collectedImg : notCollectedImg" :src="form.collectId ? collectedImg : notCollectedImg"
mode="widthFix" mode="widthFix"
></image> ></image>
</view> </view>
</view> </view>
</view> </view>
<view class="body-box"> <view class="body-box">
@@ -92,15 +92,18 @@
</view> </view>
</scroll-view> </scroll-view>
<view class="btn-box btn-box-height font_pf"> <view class="btn-box btn-box-height font_pf">
<template v-if="[0, 1].includes(tabAct)" > <template v-if="[0, 1].includes(tabAct)">
<uv-button <view class="fl1">
type="primary" <uv-button type="primary" @click="goto_study()">去学习</uv-button>
@click="common.navigateTo(`/pages/course/study?crsId=${crsId}&isPreview=${isPreview}&imgId=${form.imgId}`)" </view>
> <view class="fl1" @click="goto_practice()">
<uv-button type="primary" :disabled="practiceButtonDisabled" ></uv-button>
</uv-button> </view>
<uv-button type="primary" :disabled="isPreview === 'preview'" @click="goto_practice()">去练习</uv-button> <view class="fl1" @click="goto_examination()">
<uv-button type="primary" :disabled="isPreview === 'preview'" @click="goto_examination()">去考试</uv-button> <uv-button type="primary" :disabled="examinationButtonDisabled" >
去考试
</uv-button>
</view>
</template> </template>
<template v-if="tabAct === 2"> <template v-if="tabAct === 2">
<uv-button <uv-button
@@ -133,7 +136,6 @@
const statusBarHeight = uni.getSystemInfoSync().statusBarHeight; const statusBarHeight = uni.getSystemInfoSync().statusBarHeight;
// tab栏 // tab栏
const tabList = ref([{ name: '课程介绍' }, { name: '知识点' }, { name: '评价' }]); const tabList = ref([{ name: '课程介绍' }, { name: '知识点' }, { name: '评价' }]);
const commentRef = ref(null); const commentRef = ref(null);
const form = ref({}); const form = ref({});
const crsId = ref(''); const crsId = ref('');
@@ -141,6 +143,9 @@
const isPreview = ref(''); // 记录是否是预览 const isPreview = ref(''); // 记录是否是预览
const tabAct = ref(0); const tabAct = ref(0);
const scrollTop = ref(0); const scrollTop = ref(0);
const practiceButtonDisabled = computed(() => isPreview.value === 'preview' || form.value.examStat === '02');
const examinationButtonDisabled = computed(() => isPreview.value === 'preview' || form.value.examStat !== '00');
const tabSwitch = (item) => { const tabSwitch = (item) => {
tabAct.value = item.index; tabAct.value = item.index;
}; };
@@ -150,7 +155,7 @@
commentRef.value?.getData(); commentRef.value?.getData();
} }
}; };
const getData = async () => { const getData = async () => {
const { body } = await getCourseDetailApi({ const { body } = await getCourseDetailApi({
crsId: crsId.value crsId: crsId.value
@@ -175,8 +180,7 @@
const opacity = Math.min(1, (scrollTop.value - 20) / 80); const opacity = Math.min(1, (scrollTop.value - 20) / 80);
return `rgba(255,255,255,${opacity})`; return `rgba(255,255,255,${opacity})`;
}); });
const scroll_fun = (e) => { const scroll_fun = (e) => {
scrollTop.value = e.detail.scrollTop; scrollTop.value = e.detail.scrollTop;
}; };
@@ -184,10 +188,12 @@
const swiper_change = (res) => { const swiper_change = (res) => {
tabAct.value = res.detail.current; tabAct.value = res.detail.current;
}; };
// 去考试 // 去考试
const goto_examination = async () => { const goto_examination = async () => {
if(isPreview.value === 'preview') return common.msg('预览课程不允许考试'); if (isPreview.value === 'preview') return common.msg('预览课程不允许考试');
if (form.value.examStat === '01') return common.msg('该课程下暂无试题');
if (form.value.examStat === '02') return common.msg('该课程下的试题未设置考试规则');
common.loading(); common.loading();
startExamByCrs({ startExamByCrs({
crsId: crsId.value crsId: crsId.value
@@ -204,9 +210,16 @@
common.hideLoading(); common.hideLoading();
}); });
}; };
// 去学习
const goto_study = async () => {
common.navigateTo(
'/pages/course/study?crsId=' + crsId.value + '&isPreview=' + isPreview.value + '&imgId=' + form.value.imgId
);
};
// 去练习 // 去练习
const goto_practice = async () => { const goto_practice = async () => {
if(isPreview.value === 'preview') return common.msg('预览课程不允许练习'); if (isPreview.value === 'preview') return common.msg('预览课程不允许练习');
if (form.value.examStat !== '00') return common.msg('该课程下暂无试题');
common.loading(); common.loading();
startPracticeByCrs({ startPracticeByCrs({
crsId: crsId.value crsId: crsId.value
@@ -97,11 +97,12 @@
}; };
// 跳转到详情 // 跳转到详情
const click_list_item = (list_item) => { const click_list_item = (list_item) => {
console.log('list_item', list_item);
const examLenTm = 666; const examLenTm = 666;
const papersName = item.value.examName; const papersName = item.value.examName;
common.navigateTo( common.navigateTo(
`/pages/examination/result?execId=${list_item.execId}&examLenTm=${examLenTm}&papersName=${papersName}&mode=record` `/pages/examination/result?execId=${list_item.execId}&papersName=${papersName}&mode=record`
); );
}; };
</script> </script>
@@ -43,7 +43,6 @@
</template> </template>
<script setup> <script setup>
console.log('反馈组件');
import { ref, reactive, computed, onMounted, onUnmounted, nextTick } from 'vue'; import { ref, reactive, computed, onMounted, onUnmounted, nextTick } from 'vue';
import { optionErrorIcon } from '@/common/imgSvg'; import { optionErrorIcon } from '@/common/imgSvg';
import { saveTraQnsFeedback } from '@/api/examination.js'; import { saveTraQnsFeedback } from '@/api/examination.js';
@@ -130,7 +129,6 @@
// 组件挂载时设置监听 // 组件挂载时设置监听
let removeListener = () => {}; let removeListener = () => {};
onMounted(() => { onMounted(() => {
console.log('组件挂载时设置监听');
removeListener = setupKeyboardHeightListener((height) => { removeListener = setupKeyboardHeightListener((height) => {
feedback_popup_bottom.value = `${height}px`; feedback_popup_bottom.value = `${height}px`;
}); });
+7 -5
View File
@@ -223,6 +223,7 @@
// 倒计时结束 // 倒计时结束
const finish = (item) => { const finish = (item) => {
console.log('倒计时结束自动交卷'); console.log('倒计时结束自动交卷');
}; };
@@ -293,7 +294,7 @@
}; };
} }
}; };
// 初始化时检查 // 初始化时检查
onLoad(() => { onLoad(() => {
const examination = getPageCache('examination'); const examination = getPageCache('examination');
@@ -303,7 +304,6 @@
} }
// 记录起始时间 // 记录起始时间
examinationStartTime = new Date().getTime(); examinationStartTime = new Date().getTime();
paperData.crsId = examination.crsId; paperData.crsId = examination.crsId;
paperData.execId = examination.execId; paperData.execId = examination.execId;
paperData.examId = examination.examId; paperData.examId = examination.examId;
@@ -432,7 +432,10 @@
}); });
console.log('提交的', answerDtoList); console.log('提交的', answerDtoList);
console.log('answerDtoList', answerDtoList); console.log('answerDtoList', answerDtoList);
// 计算当前时间与开始时间的毫秒差值,再转换为整数秒
const examLenTm = Math.floor((new Date().getTime() - examinationStartTime) / 1000);
dialogRef.value.close(); dialogRef.value.close();
console.log('examLenTm', examLenTm);
common.loading('正在提交'); common.loading('正在提交');
// 这里通过是否存在examId来判断是考试中心的考试还是课程的考试 // 这里通过是否存在examId来判断是考试中心的考试还是课程的考试
let func; let func;
@@ -442,14 +445,14 @@
papersId: paperData.papersId, papersId: paperData.papersId,
examId: paperData.examId, examId: paperData.examId,
execId: paperData.execId, execId: paperData.execId,
examLenTm: 1200, examLenTm: examLenTm,
answerDtoStr: JSON.stringify(answerDtoList) answerDtoStr: JSON.stringify(answerDtoList)
}); });
} else { } else {
func = commitCrsExam({ func = commitCrsExam({
papersId: paperData.papersId, papersId: paperData.papersId,
execId: paperData.execId, execId: paperData.execId,
examLenTm: 1200, examLenTm: examLenTm,
answerDtoStr: JSON.stringify(answerDtoList) answerDtoStr: JSON.stringify(answerDtoList)
}); });
} }
@@ -458,7 +461,6 @@
// 判断是否需要查分 // 判断是否需要查分
if (res.body.flagQuery === 'Y') { if (res.body.flagQuery === 'Y') {
// 需要查分 // 需要查分
const examLenTm = 678;
common.redirectTo( common.redirectTo(
`/pages/examination/result?execId=${res.body.execId}&examLenTm=${examLenTm}&papersName=${paperData.papersName}&papersId=${paperData.papersId}&mode=${mode}&crsId=${paperData.crsId}` `/pages/examination/result?execId=${res.body.execId}&examLenTm=${examLenTm}&papersName=${paperData.papersName}&papersId=${paperData.papersId}&mode=${mode}&crsId=${paperData.crsId}`
); );
+114 -81
View File
@@ -24,6 +24,9 @@
<text v-if="pass_status === -1" class="no-pass">{{ result.examGrade }}</text> <text v-if="pass_status === -1" class="no-pass">{{ result.examGrade }}</text>
<text v-if="pass_status === 1" class="pass">{{ result.examGrade }}</text> <text v-if="pass_status === 1" class="pass">{{ result.examGrade }}</text>
</view> </view>
<view class="bottom" v-if="result.passGrade">
<text class="">通过分数{{ result.passGrade }}</text>
</view>
<view class="bottom"> <view class="bottom">
<text v-if="pass_status === -1">失败乃成功之母继续努力</text> <text v-if="pass_status === -1">失败乃成功之母继续努力</text>
<text v-if="pass_status === 1">考的不错啊继续加油</text> <text v-if="pass_status === 1">考的不错啊继续加油</text>
@@ -78,7 +81,7 @@
</view> </view>
<view class="time"> <view class="time">
<!-- 12 15 --> <!-- 12 15 -->
时长{{ result.examLenTm }} 时长{{ formatSecondsToText(result.examLenTm) }}
</view> </view>
<view class="fl1"></view> <view class="fl1"></view>
<view class="examination" @click="goExamRanking" v-if="result.mode === 'examination'"> <view class="examination" @click="goExamRanking" v-if="result.mode === 'examination'">
@@ -101,7 +104,7 @@
<swiper-item v-for="(group, groupIndex) in groupedTopicList" :key="groupIndex"> <swiper-item v-for="(group, groupIndex) in groupedTopicList" :key="groupIndex">
<uv-grid :col="5" class="sheet_table" @click="sheet_click"> <uv-grid :col="5" class="sheet_table" @click="sheet_click">
<uv-grid-item v-for="(item, index) in group" :key="index"> <uv-grid-item v-for="(item, index) in group" :key="index">
<view class="circle"> <view class="circle" :class="{ current: index === sheet_index }">
{{ groupIndex * 10 + index + 1 }} {{ groupIndex * 10 + index + 1 }}
</view> </view>
</uv-grid-item> </uv-grid-item>
@@ -110,13 +113,17 @@
</swiper> </swiper>
<view class="swiper-dots"></view> <view class="swiper-dots"></view>
</view> </view>
<!-- 获取答题结果时候的图片 --> <!-- 获取答题结果时候的图片 -->
<view class="loading-pass-image-div" v-if="pass_status === 0"> <view class="loading-pass-image-div" v-if="pass_status === 0">
<image src="@/static/images/examination/getting_robot.png" mode="widthFix" class="img"></image> <image src="@/static/images/examination/getting_robot.png" mode="widthFix" class="img"></image>
<view class="tip">你的等待会有更精确的结果要耐心哦~</view> <view class="tip">你的等待会有更精确的结果要耐心哦~</view>
</view> </view>
<view class="" :id="'id_' + index" :class="getStatusClass(index)" v-for="(item, index) in topicList"> <view
class=""
v-show="index === sheet_index"
:class="getStatusClass(index)"
v-for="(item, index) in topicList"
>
<Subject :item="item" mode="settlement" :clearResult="false" :isPreview="true"></Subject> <Subject :item="item" mode="settlement" :clearResult="false" :isPreview="true"></Subject>
</view> </view>
</view> </view>
@@ -137,11 +144,12 @@
execId: '', execId: '',
papersId: '', papersId: '',
mode: '', mode: '',
passGrade: '',
papersName: '', papersName: '',
examLenTm: '', examLenTm: '',
examGrade: '' examGrade: ''
}); });
const sheet_swiper_change = (event) => { const sheet_swiper_change = (event) => {
sheet_swiper_index.value = event.detail.current; sheet_swiper_index.value = event.detail.current;
}; };
@@ -161,25 +169,27 @@
return groups; return groups;
}); });
const scrollTop = ref(0); const scrollTop = ref(0);
const topic = ref();
const sheet_index = ref(-1);
// 答题卡点击 // 答题卡点击
const sheet_click = (index) => { const sheet_click = (index) => {
scrollTop.value = index * 200; // console.log('topicList', topicList[index]);
// topic.value = topicList[index]
sheet_index.value = index;
// scrollTop.value = index * 200;
}; };
const scroll = (event) => { const scroll = (event) => {};
};
// 跳转到去考试页面 // 跳转到去考试页面
const goExamRanking = () => { const goExamRanking = () => {
// 首先判断是课程跳入还是考试中心跳入 // 首先判断是课程跳入还是考试中心跳入
if(result.crsId !== '') { if (result.crsId !== '') {
common.navigateTo('/pages/examRanking/index?crsId=' + result.crsId) common.navigateTo('/pages/examRanking/index?crsId=' + result.crsId);
} else { } else {
common.navigateTo('/pages/examRanking/index?papersId=' + result.papersId) common.navigateTo('/pages/examRanking/index?papersId=' + result.papersId);
} }
} };
const getStatusClass = (index) => { const getStatusClass = (index) => {
const remainder = index % 3; const remainder = index % 3;
@@ -190,53 +200,59 @@
const animationfinish = (event) => { const animationfinish = (event) => {
console.log('event', event); console.log('event', event);
}; };
// 定义请求计数器和定时器引用 // 定义请求计数器和定时器引用
const requestCount = ref(0); const requestCount = ref(0);
const timerId = ref(null); const timerId = ref(null);
const get_result = () => { const get_result = () => {
// 重置计数器(首次调用时) // 重置计数器(首次调用时)
if (requestCount.value === 0) { if (requestCount.value === 0) {
requestCount.value = 0; requestCount.value = 0;
} }
// 检查是否已达到最大请求次数 // 检查是否已达到最大请求次数
if (requestCount.value >= 15) { if (requestCount.value >= 15) {
console.log('已达到最大请求次数(15次),停止请求'); console.log('已达到最大请求次数(15次),停止请求');
return; return;
} }
timerId.value = setTimeout(() => { timerId.value = setTimeout(() => {
// 每次请求前计数器+1 // 每次请求前计数器+1
requestCount.value++; requestCount.value++;
queryPaperExamScore({
queryPaperExamScore({ execId: result.execId
execId: result.execId })
}).then(({ body }) => { .then(({ body }) => {
console.log(`${requestCount.value}次请求返回`, body); console.log(`${requestCount.value}次请求返回`, body);
if (body.isWait === 'Y') { if (body.isWait === 'Y') {
// 未完成且未达上限,继续请求 // 未完成且未达上限,继续请求
if (requestCount.value < 15) { if (requestCount.value < 15) {
get_result(); get_result();
} else { } else {
console.log('已达到最大请求次数,停止等待'); console.log('已达到最大请求次数,停止等待');
} }
} else if (body.isWait === 'N') { } else if (body.isWait === 'N') {
// 完成请求,处理结果 // 完成请求,处理结果
pass_status.value = body.examResult === 'P' ? 1 : -1; pass_status.value = body.examResult === 'P' ? 1 : -1;
result.examGrade = body.examGrade; result.examGrade = body.examGrade;
topicList.push(...body.qnsInfoVo); result.passGrade = body.passGrade || '';
}
}).catch(err => { if (result.examLenTm === undefined) {
console.error('请求失败', err); result.examLenTm = body.examLenTm;
// 请求失败也计入次数,避免无限重试 }
if (requestCount.value < 15) { topicList.push(...body.qnsInfoVo);
get_result(); }
} })
}); .catch((err) => {
}, 2000); console.error('请求失败', err);
// 请求失败也计入次数,避免无限重试
if (requestCount.value < 15) {
get_result();
}
});
}, 2000);
}; };
// 初始化时检查 // 初始化时检查
@@ -246,23 +262,55 @@
result.papersName = e.papersName; result.papersName = e.papersName;
result.examLenTm = e.examLenTm; result.examLenTm = e.examLenTm;
result.mode = e.mode || ''; result.mode = e.mode || '';
result.papersId = e.papersId; result.papersId = e.papersId;
get_result(); get_result();
}); });
// 页面卸载时清除定时器,终止请求 // 页面卸载时清除定时器,终止请求
onUnload(() => { onUnload(() => {
if (timerId.value) { if (timerId.value) {
clearTimeout(timerId.value); clearTimeout(timerId.value);
timerId.value = null; timerId.value = null;
} }
}); });
const formatSecondsToText = (milliseconds) => {
console.log('milliseconds', milliseconds);
if (milliseconds === undefined) return '--';
// 尝试将输入转换为数字(处理字符串形式的数字)
const num = Number(milliseconds);
// 验证是否为有效数字且非负数
if (isNaN(num) || num < 0) {
return '0秒';
}
// 将毫秒转换为秒(取整)
const seconds = num;
// 计算小时、分钟、秒
const hours = Math.floor(seconds / 3600);
const minutes = Math.floor((seconds % 3600) / 60);
const secs = Math.floor(seconds % 60);
console.log('secs', secs);
// 存储各部分文本
const parts = [];
if (hours > 0) {
parts.push(`${hours}小时`);
}
if (minutes > 0) {
parts.push(`${minutes}`);
}
// 确保至少显示秒数,即使为0
parts.push(`${secs}`);
// 拼接结果
return parts.join('');
};
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
$bg-margin-left: 30rpx; $bg-margin-left: 30rpx;
.current {
background-color: rgba(0, 102, 255, 0.6);
border-color: #0066ff;
color: #ffffff;
}
.scroll-Y { .scroll-Y {
// max-height: calc(100vh - var(--status-bar-height) - 70rpx - 70rpx - 40rpx - 64rpx - 68rpx - 60rpx); // max-height: calc(100vh - var(--status-bar-height) - 70rpx - 70rpx - 40rpx - 64rpx - 68rpx - 60rpx);
height: calc(100vh - var(--status-bar-height) - 70rpx - 10rpx); height: calc(100vh - var(--status-bar-height) - 70rpx - 10rpx);
@@ -330,25 +378,10 @@
} }
} }
.sticky {
}
.sheet_table_div_fixed {
position: absolute;
top: calc(var(--status-bar-height) + 70rpx);
left: 0;
z-index: 600;
height: 230rpx;
width: calc(100% - 56rpx);
margin: 0 28rpx 0 28rpx;
background-color: #fff;
// opacity: .5;
}
.sheet_table_div { .sheet_table_div {
position: sticky; position: sticky;
left: 0; left: 0;
top: 0; top: -2rpx;
width: 100%; width: 100%;
z-index: 600; z-index: 600;
background-color: #fff; background-color: #fff;
-1
View File
@@ -7,7 +7,6 @@
</view> </view>
<view class="title font_pf">考试记录</view> <view class="title font_pf">考试记录</view>
</view> </view>
<view class="detail-body"> <view class="detail-body">
<examRecordList ref="listItemRef"></examRecordList> <examRecordList ref="listItemRef"></examRecordList>
@@ -208,7 +208,7 @@
border: 2rpx solid #ffa150; border: 2rpx solid #ffa150;
font-family: PingFangSC; font-family: PingFangSC;
font-weight: 500; font-weight: 500;
font-size: 23rpx; font-size: 22rpx;
color: #ffa150; color: #ffa150;
display: flex; display: flex;
justify-content: center; justify-content: center;
@@ -220,12 +220,12 @@
display: flex; display: flex;
font-family: PingFangSC; font-family: PingFangSC;
font-weight: 400; font-weight: 400;
font-size: 24rpx; font-size: 22rpx;
color: #666; color: #666;
margin-bottom: 16rpx; margin-bottom: 16rpx;
line-height: 23rpx; line-height: 24rpx;
flex-wrap: nowrap; flex-wrap: nowrap;
height: 23rpx; height: 24rpx;
overflow: hidden; overflow: hidden;
} }
} }
@@ -256,11 +256,11 @@
.time_div { .time_div {
font-family: Arial; font-family: Arial;
font-weight: 400; font-weight: 400;
font-size: 23rpx; font-size: 22rpx;
color: #666; color: #666;
line-height: 23rpx; line-height: 24rpx;
flex-wrap: nowrap; flex-wrap: nowrap;
height: 23rpx; height: 24rpx;
overflow: hidden; overflow: hidden;
} }
@@ -268,13 +268,13 @@
display: flex; display: flex;
font-family: PingFangSC; font-family: PingFangSC;
font-weight: 400; font-weight: 400;
font-size: 23rpx; font-size: 22rpx;
color: #666; color: #666;
margin-bottom: 23rpx; margin-bottom: 22rpx;
line-height: 23rpx; line-height: 24rpx;
flex-wrap: nowrap; flex-wrap: nowrap;
height: 23rpx; height: 24rpx;
overflow: hidden; overflow: hidden;
} }
} }
+1
View File
@@ -82,6 +82,7 @@
</view> </view>
<TouchBtn class="talk-btns" @uploadVoice="uploadRecordNow" @submitAnswer="submitAnswerNow" <TouchBtn class="talk-btns" @uploadVoice="uploadRecordNow" @submitAnswer="submitAnswerNow"
@startRecord="startRecordCallback" :loadingText="sendLoadingText" :isLoading="!answerIsOver" @startRecord="startRecordCallback" :loadingText="sendLoadingText" :isLoading="!answerIsOver"
:adjustPosition="true"
:isDisabled="false" /> :isDisabled="false" />
<!-- 反馈组件 --> <!-- 反馈组件 -->
<Feedback ref="feedbackRef" @feedbackAnswer="feedbackAnswer"></Feedback> <Feedback ref="feedbackRef" @feedbackAnswer="feedbackAnswer"></Feedback>
+2 -2
View File
@@ -16,7 +16,7 @@
:readonly="true" :readonly="true"
></uv-input> ></uv-input>
</view> </view>
<view class="message_div"> <view class="message_div" @click="common.navigateTo('/pages/messageNotification/index')">
<image src="@/static/images/index/message_b.png" class="message_img"></image> <image src="@/static/images/index/message_b.png" class="message_img"></image>
<view class="message_text">消息</view> <view class="message_text">消息</view>
<view class="message_num message_num_font">30</view> <view class="message_num message_num_font">30</view>
@@ -39,7 +39,7 @@
:suffixIconStyle="suffixIconStyle" :suffixIconStyle="suffixIconStyle"
:readonly="true" :readonly="true"
></uv-input> ></uv-input>
<view class="message_div"> <view class="message_div" @click="common.navigateTo('/pages/messageNotification/index')">
<image src="@/static/images/index/message.png" class="message_img"></image> <image src="@/static/images/index/message.png" class="message_img"></image>
<view class="message_text">消息</view> <view class="message_text">消息</view>
<view class="message_num message_num_font">30</view> <view class="message_num message_num_font">30</view>
@@ -143,27 +143,26 @@
.time_div { .time_div {
font-family: PingFangSC; font-family: PingFangSC;
font-weight: 400; font-weight: 400;
font-size: 23rpx; font-size: 22rpx;
color: #666; color: #666;
line-height: 23rpx; line-height: 24rpx;
flex-wrap: nowrap; flex-wrap: nowrap;
height: 23rpx; height: 24rpx;
overflow: hidden; overflow: hidden;
white-space: nowrap; white-space: nowrap;
} }
.people_progress_div { .people_progress_div {
display: flex; display: flex;
font-family: PingFangSC;
font-weight: 400; font-weight: 400;
font-size: 23rpx; font-size: 22rpx;
color: #666; color: #666;
margin-bottom: 23rpx; margin-bottom: 23rpx;
white-space: nowrap; white-space: nowrap;
line-height: 23rpx; line-height: 24rpx;
flex-wrap: nowrap; flex-wrap: nowrap;
height: 23rpx; height: 24rpx;
overflow: hidden; // overflow: hidden;
} }
} }
} }
+4 -2
View File
@@ -97,7 +97,7 @@
:src="passTheExamIcon(item.isFinishStudy === '02' ? '#0066FF' : '#999999')" :src="passTheExamIcon(item.isFinishStudy === '02' ? '#0066FF' : '#999999')"
></image> ></image>
<view class="button_text" :class="item.isFinishStudy === '02' ? 'success' : 'error'"> <view class="button_text" :class="item.isFinishStudy === '02' ? 'success' : 'error'">
完成 完成
</view> </view>
</template> </template>
<template v-if="item.isFinishExam !== '01'"> <template v-if="item.isFinishExam !== '01'">
@@ -303,7 +303,9 @@
.circle_div { .circle_div {
width: 20rpx; width: 20rpx;
height: 20rpx; height: 20rpx;
border-radius: 100%; border-radius: 50%;
overflow: hidden;
box-sizing: border-box;
} }
.line_div { .line_div {
height: calc(100% - 20rpx); height: calc(100% - 20rpx);
+15 -6
View File
@@ -197,6 +197,7 @@
const submitProblem = (answer) => { const submitProblem = (answer) => {
console.log('答题内容', answer); console.log('答题内容', answer);
console.log('答单题', topic); console.log('答单题', topic);
common.loading('答题中'); common.loading('答题中');
practiceAnswer({ practiceAnswer({
exrId: paperData.exrId, exrId: paperData.exrId,
@@ -245,7 +246,11 @@
judgeResultStatus && // 条件1.答题正确 judgeResultStatus && // 条件1.答题正确
topic.value.qnsTyp !== 'ES' // 问答题答对打答错都不切换 topic.value.qnsTyp !== 'ES' // 问答题答对打答错都不切换
) { ) {
questionNumber.value++; nextTick(() => {
setTimeout(() => {
questionNumber.value++;
}, 200);
});
} else { } else {
console.log('为什么不跳转2', judgeResultStatus); console.log('为什么不跳转2', judgeResultStatus);
console.log('为什么不跳转3', topic.value.qnsTyp !== 'ES'); console.log('为什么不跳转3', topic.value.qnsTyp !== 'ES');
@@ -365,10 +370,12 @@
// 中途退出 // 中途退出
dialogRef.value.close(); dialogRef.value.close();
common.loading(); common.loading();
await practiceCommit({ exrId: paperData.exrId, examLenTm: practiceTime.value, stat: 'U' }); try{
await practiceCommit({ exrId: paperData.exrId, examLenTm: practiceTime.value, stat: 'U' });
common.navigateBack();
}catch(e){
}
common.hideLoading(); common.hideLoading();
await nextTick();
common.navigateBack();
} else if (key === 'revert') { } else if (key === 'revert') {
// 返回 // 返回
dialogRef.value.close(); dialogRef.value.close();
@@ -391,9 +398,11 @@
// 交卷按钮点击,打开交卷确认框 // 交卷按钮点击,打开交卷确认框
const hand_in_paper_button_click = async () => { const hand_in_paper_button_click = async () => {
console.log('交卷按钮'); console.log('交卷按钮');
const stat = 'P' const stat = 'P';
// 都做完弹窗了,产品说改成跳页,说客户觉得奇怪 // 都做完弹窗了,产品说改成跳页,说客户觉得奇怪
common.redirectTo(`/pages/practice/result?name=${paperData.name}&exrId=${paperData.exrId}&crsId=${paperData.crsId}&examLenTm=${practiceTime.value}&stat=${stat}`); common.redirectTo(
`/pages/practice/result?name=${paperData.name}&exrId=${paperData.exrId}&crsId=${paperData.crsId}&examLenTm=${practiceTime.value}&stat=${stat}`
);
// 完成 // 完成
// dialogRef.value.open({ // dialogRef.value.open({
// // type: 'complete', // // type: 'complete',
+2 -1
View File
@@ -31,7 +31,7 @@
</view> </view>
<view class="title-note"> <view class="title-note">
考试时长 考试时长
<text class="bold">{{ detailData.limitTm }}</text> <text class="bold">{{ detailData.limitTm / 60 }}</text>
分钟 分钟
</view> </view>
<view class="title-table"> <view class="title-table">
@@ -154,6 +154,7 @@
}, 0) }, 0)
); );
const goto_examination = async () => { const goto_examination = async () => {
if(detailData.limitTyp === 'SG' && detailData.examStatText === 'Y') return common.msg('考试已完成');
common.loading(); common.loading();
startTraExamPapersInfo({ startTraExamPapersInfo({
examId: detailData.examId examId: detailData.examId
+108 -74
View File
@@ -42,7 +42,12 @@
<view class="content"> <view class="content">
<view class="expose_shadow"></view> <view class="expose_shadow"></view>
<scroll-view :scroll-y="true" class="scroll-Y" :show-scrollbar="false" :refresher-threshold="0"> <scroll-view :scroll-y="true" class="scroll-Y" :show-scrollbar="false" :refresher-threshold="0">
<view class="" v-if="item === '00'">加载中</view>
<view class="" v-if="item === '01'">加载失败</view>
<view class="" v-if="item === '02'">加载失败</view>
<Subject <Subject
v-else
:item="item" :item="item"
:mode="mode" :mode="mode"
:isPreview="item.isPreview" :isPreview="item.isPreview"
@@ -93,32 +98,29 @@
const dialogRef = ref(null); const dialogRef = ref(null);
const touchBtnRef = ref(null); const touchBtnRef = ref(null);
const mode = ref('practice'); // 考试 examination 练习practice const mode = ref('practice'); // 考试 examination 练习practice
const paperData = reactive({ const paperData = reactive({
name: '' // 名称 name: '' // 名称
}); // 试卷信息 }); // 试卷信息
const topicList = reactive([]); // 问题列表 const topicList = reactive([]); // 问题列表
const storageIdList = ref([]); // 所有题ID列表 const storageIdList = ref([]); // 所有题ID列表
const storageIdDict = ref({}); // 所有题ID为键的字典
const popup_input_bottom = ref('0px'); const popup_input_bottom = ref('0px');
const questionNumber = ref(0); // 题号 const questionNumber = ref(0); // 题号
// 根据课程ID获取课程的题目 undefined为没有, 00为加载中, 02为加载失败
const topic = computed({ const topic = computed({
get: () => topicList[questionNumber.value], get: () => topicList[questionNumber.value],
set: (val) => (topicList[questionNumber.value] = val) set: (val) => (topicList[questionNumber.value] = val)
}); });
const showTouchBtn = computed(() => { const showTouchBtn = computed(() => {
return topic.value?.qnsTyp === 'ES'; return topic.value?.qnsTyp === 'ES';
}); });
// 下面语音组件的禁用状态判断 // 下面语音组件的禁用状态判断
const touchIsDisabled = computed(() => { const touchIsDisabled = computed(() => topic.value?.es_status !== '' && topic.value?.es_status !== undefined);
console.log('下面语音组件的禁用状态判断', topic.value?.es_status !== '' && topic.value?.es_status !== undefined);
return topic.value?.es_status !== '' && topic.value?.es_status !== undefined;
});
const progress = computed(() => { const progress = computed(() => {
// 计算进度百分比(保留两位小数) // 计算进度百分比(保留两位小数)
@@ -147,13 +149,12 @@
const transition = (event) => { const transition = (event) => {
if (isTriggered.value) return; if (isTriggered.value) return;
const dx = event.detail.dx; const dx = event.detail.dx;
if (dx > 50 && dx < 200 && isLastTopic.value && ['P', 'U'].includes(topic.value.judgeResult)) { if (dx > 90 && dx < 250 && isLastTopic.value && ['P', 'U'].includes(topic.value.judgeResult)) {
// 如果是最后一题并且右滑动大于50,并且这题已经答了,就触发练习完成 // 如果是最后一题并且右滑动大于50,并且这题已经答了,就触发练习完成
isTriggered.value = true; isTriggered.value = true;
hand_in_paper_button_click(); hand_in_paper_button_click();
} }
}; };
const subject_click = (type, params) => { const subject_click = (type, params) => {
if (type === 'feedback') { if (type === 'feedback') {
// 反馈 // 反馈
@@ -220,29 +221,32 @@
topic.value.judgeResult = traQnsInfoVo.judgeResult; // 正确答案字符串分割 topic.value.judgeResult = traQnsInfoVo.judgeResult; // 正确答案字符串分割
const judgeResultStatus = traQnsInfoVo.judgeResult === 'P'; // P为正确U为错误 const judgeResultStatus = traQnsInfoVo.judgeResult === 'P'; // P为正确U为错误
// 加载下一题 // 加载下一题
addProblem(questionNumber.value + 1) if (!addProblem(questionNumber.value + 1)) {
// 返回false说明到了最后一题
// if (!addProblem()) { console.log('最后一题', topic.value.qnsTyp, !judgeResultStatus);
// // 返回false说明到了最后一题 if (topic.value.qnsTyp === 'ES' || !judgeResultStatus) {
// console.log('最后一题', topic.value.qnsTyp, !judgeResultStatus); // 最后一题是问答题,或者答错了,都不自动弹出
// if (topic.value.qnsTyp === 'ES' || !judgeResultStatus) { return;
// // 最后一题是问答题,或者答错了,都不自动弹出 } else {
// return; await hand_in_paper_button_click();
// } else { }
// await hand_in_paper_button_click(); } else {
// } addRequestProblem(questionNumber.value + 1);
// } else { // 自动切换下一题的条件
// // 自动切换下一题的条件 if (
// if ( judgeResultStatus && // 条件1.答题正确
// judgeResultStatus && // 条件1.答题正确 topic.value.qnsTyp !== 'ES' // 问答题答对打答错都不切换
// topic.value.qnsTyp !== 'ES' // 问答题答对打答错都不切换 ) {
// ) { nextTick(() => {
// questionNumber.value++; setTimeout(() => {
// } else { questionNumber.value++;
// console.log('为什么不跳转2', judgeResultStatus); }, 200);
// console.log('为什么不跳转3', topic.value.qnsTyp !== 'ES'); });
// } } else {
// } console.log('为什么不跳转2', judgeResultStatus);
console.log('为什么不跳转3', topic.value.qnsTyp !== 'ES');
}
}
}) })
.catch(() => { .catch(() => {
common.hideLoading(); common.hideLoading();
@@ -283,6 +287,7 @@
return Promise.reject(error); return Promise.reject(error);
}); });
}; };
// 录音组件提交 // 录音组件提交
const touchBtnSubmit = (type, submitObj) => { const touchBtnSubmit = (type, submitObj) => {
const old_text = touchBtnRef.value?.clearinputText(); // 清除发送框数据 const old_text = touchBtnRef.value?.clearinputText(); // 清除发送框数据
@@ -316,27 +321,77 @@
}; };
} }
}; };
// 添加一道题 // 添加一道题
const addProblem = async (index, isLoading) => { const addProblem = async (index) => {
// index 要加载的题号 isLoading是否显示loading // index 要加载的题号
if(index < topicList.length) return true; // 说明此题已经加载 if (index < topicList.length) return true; // 说明此题已经加载
if (topicList.length >= storageIdList.value.length) return false; // 说明已经 if (topicList.length >= storageIdList.value.length) return false; // 说明已经加载所有题了
if (isLoading) common.loading('加载题目中');
const id = storageIdList.value[index]; // 找到id
if (storageIdDict.value[id] === undefined) {
//尚未加载(几乎不可能)
return true;
} else if (storageIdDict.value[id].state === '00') {
//加载中
} else if (storageIdDict.value[id].state === '01') {
// 已经加载
// console.log('增加已经加载的数据', storageIdDict.value[id].topic);
topicList.push(storageIdDict.value[id].topic);
return true;
} else if (storageIdDict.value[id].state === '02') {
//加载失败
}
topicList.push(storageIdDict.value[id].state);
return true;
};
// 网络加载题,并且放在
const addRequestProblem = async (index, success = () => {}) => {
const id = storageIdList.value[index]; const id = storageIdList.value[index];
const preload = () => {
nextTick(() => {
// 最多只预加载当前题号的后两道题(questionNumber.value是当前题号)
// 修正索引判断:确保 index + 1 是有效的数组索引(< 数组长度)
if (index + 1 === storageIdList.value.length) return; // 防止下标越界
if (index + 1 > questionNumber.value + 2) return; // 防止加载太多
const last_id = storageIdList.value[index + 1];
// 判断是否加载
if (last_id in storageIdDict.value) {
return;
}else {
addRequestProblem(index + 1, success);
}
});
};
if (storageIdDict.value[id] && storageIdDict.value[id].state === '01') {
preload();
return;
}
storageIdDict.value[id] = { state: '00' };
queryMistakesAnswerByMisId({ misId: id }) queryMistakesAnswerByMisId({ misId: id })
.then(({ body }) => { .then(({ body }) => {
console.log('加载了一道题', body); const topic_item = {
topicList.push({
...body, ...body,
isPreview: false, isPreview: false,
clearResult: true, clearResult: true,
es_status: '', // 预设一下问答题的状态,'' 空为没有 00 转圈 01 播放,其他暂定 es_status: '', // 预设一下问答题的状态,'' 空为没有 00 转圈 01 播放,其他暂定
my_answer: [] my_answer: []
}); };
storageIdDict.value[id] = {
state: '01',
topic: topic_item
};
success(topic_item);
preload();
})
.catch(() => {
storageIdDict.value[id] = { state: '02' };
}) })
.finally(() => { .finally(() => {
if (isLoading) common.hideLoading(); // if (isLoading) common.hideLoading();
}); });
}; };
// 初始化时检查 // 初始化时检查
@@ -347,14 +402,19 @@
} }
paperData.name = correct.name; paperData.name = correct.name;
storageIdList.value = correct.list; storageIdList.value = correct.list;
// 记录练习起始时间
setupKeyboardHeightListener((height) => { setupKeyboardHeightListener((height) => {
popup_input_bottom.value = `${height}px`; popup_input_bottom.value = `${height}px`;
}); });
setTimeout(() => { setTimeout(() => {
addProblem(0, true); addRequestProblem(0, () => {
addProblem(0);
});
// addProblem(0, true);
}, 10); }, 10);
}); });
const result_click = async ({ key }) => { const result_click = async ({ key }) => {
isTriggered.value = false; // 恢复 isTriggered.value = false; // 恢复
if (key === 'return') { if (key === 'return') {
@@ -392,34 +452,8 @@
// 交卷按钮点击,打开交卷确认框 // 交卷按钮点击,打开交卷确认框
const hand_in_paper_button_click = async () => { const hand_in_paper_button_click = async () => {
console.log('交卷按钮'); console.log('交卷按钮');
common.loading(); const stat = 'P';
try { common.redirectTo(`/pages/wrongQuestionRecord/result?stat=${stat}`);
await practiceCommit({ exrId: paperData.exrId, stat: 'P' });
} catch (e) {}
common.hideLoading();
console.log('点击交卷', paperData);
// 完成
dialogRef.value.open({
// type: 'complete',
title: '恭喜你,已完成全部练习!',
buttonList: [
{
key: 'goto_test',
name: '去考试',
style: style_button_1
},
{
key: 'again',
name: '重新练',
style: style_button_2
},
{
key: 'return',
name: '返回',
style: style_button_2
}
]
});
}; };
// 中途退出 // 中途退出
+75 -4
View File
@@ -1,11 +1,82 @@
<template> <template>
<view class="max_page"> <view class="max_page">
<image src="@/static/images/common/wc.png" class="img"></image> <image src="@/static/images/common/wc.png" class="show_img"></image>
<view class="show_msg">完成错题练习</view>
<view class="fl1"></view>
<view class="show_button">
<uv-button
type="primary"
class="button"
color="#FFFFFF"
:throttleTime="100"
text="返回"
@click="back_page"
:custom-style="customStyle2"
></uv-button>
</view>
</view> </view>
</template> </template>
<script> <script setup>
import common from '@/common/common';
const customStyle1 = {
borderRadius: '12rpx',
color: '#FFFFFF',
fontWeight: '600',
fontSize: '28rpx',
border: '1px solid #E0E0E0',
height: '92rpx'
};
const customStyle2 = {
borderRadius: '12rpx',
color: '#333333',
fontWeight: '600',
fontSize: '28rpx',
border: '1px solid #E0E0E0',
height: '92rpx'
};
const customStyle3 = {
color: '#333333',
fontWeight: '600',
fontSize: '28rpx',
border: 'none',
backgroundColor: '#fff',
height: '92rpx'
};
// 返回上一页
const back_page = () => {
common.navigateBack();
};
</script> </script>
<style> <style scoped lang="scss">
</style> .max_page {
display: flex;
align-items: center;
flex-direction: column;
}
.show_img {
margin-top: 300rpx;
width: 231rpx;
height: 231rpx;
}
.show_msg {
margin-top: 38rpx;
font-weight: 700;
font-size: 46rpx;
color: #000000;
line-height: 62rpx;
text-align: center;
font-style: normal;
}
.show_button {
width: 80%;
margin-bottom: 180rpx;
.button:nth-child(2) {
margin-top: 38rpx;
margin-bottom: 38rpx;
}
}
</style>
+1 -3
View File
@@ -68,7 +68,7 @@ export const useAudioStore = defineStore('audioStore', {
// 音频可以播放时触发(此时通常能获取到时长) // 音频可以播放时触发(此时通常能获取到时长)
this.audioInstance.onCanplay(() => { this.audioInstance.onCanplay(() => {
// 尝试获取时长(部分环境需要延迟一点) // 尝试获取时长(部分环境需要延迟一点)
console.log('尝试获取时长(部分环境需要延迟一点)'); // console.log('尝试获取时长(部分环境需要延迟一点)');
setTimeout(() => { setTimeout(() => {
const duration = this.audioInstance.duration || 0; const duration = this.audioInstance.duration || 0;
console.log('尝试获duration', duration); console.log('尝试获duration', duration);
@@ -208,7 +208,6 @@ export const useAudioStore = defineStore('audioStore', {
}, },
// 注册播放完成回调 // 注册播放完成回调
onAudioEnded(callback) { onAudioEnded(callback) {
console.log('onAudioEnded');
if (typeof callback === 'function') { if (typeof callback === 'function') {
this.callbacks.onEnded = callback; this.callbacks.onEnded = callback;
} }
@@ -216,7 +215,6 @@ export const useAudioStore = defineStore('audioStore', {
// 注册播放错误回调 // 注册播放错误回调
onAudioError(callback) { onAudioError(callback) {
console.log('注册播放错误回调');
if (typeof callback === 'function') { if (typeof callback === 'function') {
this.callbacks.onError = callback; this.callbacks.onError = callback;
} }