创建课程记录三个列表,创建练习页
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
import request from '@/api/request'
|
||||
const base_url = '/traexam'
|
||||
|
||||
|
||||
|
||||
// 学习列表页
|
||||
|
||||
|
||||
/**练习*/
|
||||
// 练习列表页
|
||||
export const queryPracticeRecordPaging = (data) => {
|
||||
return request({
|
||||
url: base_url + '/traRecord/queryPracticeRecordPaging',
|
||||
method: 'post',
|
||||
toastErrors: true,
|
||||
data
|
||||
});
|
||||
};
|
||||
// 练习每一项列表
|
||||
export const queryPracticeHis = (data) => {
|
||||
return request({
|
||||
url: base_url + '/traRecord/queryPracticeHis',
|
||||
method: 'post',
|
||||
toastErrors: true,
|
||||
data
|
||||
});
|
||||
};
|
||||
|
||||
/**考试*/
|
||||
// 考试列表页
|
||||
export const queryExamRecordPaging = (data) => {
|
||||
return request({
|
||||
url: base_url + '/traRecord/queryExamRecordPaging',
|
||||
method: 'post',
|
||||
toastErrors: true,
|
||||
data
|
||||
});
|
||||
};
|
||||
// 考试每一项列表
|
||||
export const queryExamHisByExamId = (data) => {
|
||||
return request({
|
||||
url: base_url + '/traRecord/queryExamHisByExamId',
|
||||
method: 'post',
|
||||
toastErrors: true,
|
||||
data
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
import request from '@/api/request'
|
||||
const base_url = '/traexam'
|
||||
|
||||
// 1.开始练习(课程练习)
|
||||
export const startPracticeByCrs = (data) => {
|
||||
return request({
|
||||
url: base_url + '/traCrsPractice/startPracticeByCrs',
|
||||
method: 'post',
|
||||
toastErrors: true,
|
||||
data
|
||||
});
|
||||
};
|
||||
|
||||
// 2.课程练习答题
|
||||
export const practiceAnswer = (data) => {
|
||||
return request({
|
||||
url: base_url + '/traCrsPractice/practiceAnswer',
|
||||
method: 'post',
|
||||
toastErrors: true,
|
||||
data
|
||||
});
|
||||
};
|
||||
|
||||
// 3.课程练习状态变更
|
||||
export const practiceCommit = (data) => {
|
||||
return request({
|
||||
url: base_url + '/traCrsPractice/practiceCommit',
|
||||
method: 'post',
|
||||
toastErrors: true,
|
||||
data
|
||||
});
|
||||
};
|
||||
|
||||
// 4.课程练习记录
|
||||
export const queryPracticeRecordByExrId = (data) => {
|
||||
return request({
|
||||
url: base_url + '/traCrsPractice/queryPracticeRecordByExrId',
|
||||
method: 'post',
|
||||
toastErrors: true,
|
||||
data
|
||||
});
|
||||
};
|
||||
@@ -57,3 +57,27 @@ export const lockIcon = (color: string) : string => {
|
||||
return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svgXml)}`;
|
||||
};
|
||||
|
||||
|
||||
// 学习时长
|
||||
export const studyDurationIcon = (color: string='#62A1FF') : string => {
|
||||
const svgXml = `
|
||||
<svg t="1755844236249" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6935" width="64" height="64"><path d="M512 64.8C265 64.8 64.8 265.1 64.8 512c0 247 200.3 447.2 447.2 447.2 247 0 447.2-200.3 447.2-447.2C959.3 265 759 64.8 512 64.8z m177.1 546.4H465.5c-20.5 0-37.2-16.7-37.2-37.2V307.1c0-20.5 16.7-37.2 37.2-37.2s37.2 16.7 37.2 37.2v229.6H689c20.4 0 37.3 16.8 37.3 37.3 0 20.5-16.7 37.2-37.2 37.2z" fill="${color}" p-id="6936"></path></svg>
|
||||
`.trim();
|
||||
return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svgXml)}`;
|
||||
};
|
||||
|
||||
// 学习次数
|
||||
export const studyFrequencyIcon = (color: string='#62A1FF') : string => {
|
||||
const svgXml = `
|
||||
<svg t="1755844236249" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6935" width="64" height="64"><path d="M512 64.8C265 64.8 64.8 265.1 64.8 512c0 247 200.3 447.2 447.2 447.2 247 0 447.2-200.3 447.2-447.2C959.3 265 759 64.8 512 64.8z m177.1 546.4H465.5c-20.5 0-37.2-16.7-37.2-37.2V307.1c0-20.5 16.7-37.2 37.2-37.2s37.2 16.7 37.2 37.2v229.6H689c20.4 0 37.3 16.8 37.3 37.3 0 20.5-16.7 37.2-37.2 37.2z" fill="${color}" p-id="6936"></path></svg>
|
||||
`.trim();
|
||||
return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svgXml)}`;
|
||||
};
|
||||
|
||||
// 学习时间
|
||||
export const studyTimeIcon = (color: string='#958DFF') : string => {
|
||||
const svgXml = `
|
||||
<svg t="1755844179673" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6630" width="64" height="64"><path d="M329.7792 282.7776c-17.2032 0-31.1808-13.9264-31.1808-31.1808V144.9472c0-17.2032 13.9264-31.1808 31.1808-31.1808 17.2032 0 31.1808 13.9264 31.1808 31.1808v106.6496c0 17.2544-13.9776 31.1808-31.1808 31.1808zM710.2976 282.7776c-17.2032 0-31.1808-13.9264-31.1808-31.1808V144.9472c0-17.2032 13.9264-31.1808 31.1808-31.1808 17.2032 0 31.1808 13.9264 31.1808 31.1808v106.6496c0 17.2544-13.9776 31.1808-31.1808 31.1808z" fill="${color}" p-id="6631"></path><path d="M800.0512 179.7632v59.4944c0 50.0224-40.5504 90.5728-90.5728 90.5728s-90.5728-40.5504-90.5728-90.5728V174.1824H420.608v65.0752c0 50.0224-40.5504 90.5728-90.5728 90.5728S239.4624 289.28 239.4624 239.2576V178.3808c-72.4992 16.64-126.6176 81.5104-126.6176 159.0784V727.04c0 90.1632 73.1136 163.2768 163.2768 163.2768H757.76c90.1632 0 163.2768-73.1136 163.2768-163.2768V337.4592c0-75.52-51.3024-139.0592-120.9856-157.696z m-204.4928 517.376h-286.72c-18.176 0-32.9216-14.7456-32.9216-32.9216s14.7456-32.9216 32.9216-32.9216h286.72c18.176 0 32.9216 14.7456 32.9216 32.9216s-14.7456 32.9216-32.9216 32.9216z m140.5952-166.7072H308.8384c-18.176 0-32.9216-14.7456-32.9216-32.9216s14.7456-32.9216 32.9216-32.9216h427.3152c18.176 0 32.9216 14.7456 32.9216 32.9216s-14.7456 32.9216-32.9216 32.9216z" fill="${color}" p-id="6632" data-spm-anchor-id="a313x.manage_type_myprojects.0.i0.46df3a81DkdazW" class=""></path></svg>
|
||||
`.trim();
|
||||
return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svgXml)}`;
|
||||
};
|
||||
@@ -40,7 +40,6 @@
|
||||
if (props.analysisVo.correctFlag === 'R') return 'success';
|
||||
// 是错误答案但是被用户错误选中的为红
|
||||
const my_answer_array = props.my_answer;
|
||||
console.log('my_answer_array', my_answer_array);
|
||||
if(my_answer_array.includes(props.analysisVo.itemId) && props.analysisVo.correctFlag === 'E') return 'error';
|
||||
|
||||
// 只有被我选中,不知是正确还是错误的为蓝
|
||||
|
||||
@@ -244,6 +244,24 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/courseRecord/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "课程记录页",
|
||||
"app-plus": {
|
||||
"titleNView": false
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/examinationRecord/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "考试记录页",
|
||||
"app-plus": {
|
||||
"titleNView": false
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/course/index",
|
||||
"style": {
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
<template>
|
||||
<view class="max_page">
|
||||
<nav-bar :is_seat="false" :backgroundColor="bgOpacity"></nav-bar>
|
||||
<scroll-view :scroll-y="true" class="scroll detail-main" @scroll="scroll_fun" @scrolltolower="scrolltolower" :show-scrollbar="false">
|
||||
<scroll-view
|
||||
:scroll-y="true"
|
||||
class="scroll detail-main"
|
||||
@scroll="scroll_fun"
|
||||
@scrolltolower="scrolltolower"
|
||||
:show-scrollbar="false"
|
||||
>
|
||||
<view class="bg_div">
|
||||
<image-preview class="img_100" :imgId="form.imgId" mode="widthFix"></image-preview>
|
||||
</view>
|
||||
@@ -32,7 +38,10 @@
|
||||
<view class="mr-10">已学</view>
|
||||
<view class="c-000">{{ form.styParaGraphNum || 0 }}</view>
|
||||
</view>
|
||||
<view class="num-item examination" @click="common.navigateTo('/pages/examRanking/index?crsId=' + crsId)">
|
||||
<view
|
||||
class="num-item examination"
|
||||
@click="common.navigateTo('/pages/examRanking/index?crsId=' + crsId)"
|
||||
>
|
||||
<image
|
||||
class="title-icon"
|
||||
src="/src/static/images/courseDetail/charts.png"
|
||||
@@ -93,11 +102,15 @@
|
||||
<template v-if="[0, 1].includes(tabAct)">
|
||||
<uv-button
|
||||
type="primary"
|
||||
@click="common.navigateTo('/pages/course/study?crsNum=' + form.crsNum + '&crsId=' + crsId + '&imgId=' + form.imgId)"
|
||||
@click="
|
||||
common.navigateTo(
|
||||
'/pages/course/study?crsNum=' + form.crsNum + '&crsId=' + crsId + '&imgId=' + form.imgId
|
||||
)
|
||||
"
|
||||
>
|
||||
去学习
|
||||
</uv-button>
|
||||
<uv-button type="primary">去练习</uv-button>
|
||||
<uv-button type="primary" @click="goto_practice()">去练习</uv-button>
|
||||
<uv-button type="primary" @click="goto_examination()">去考试</uv-button>
|
||||
</template>
|
||||
<template v-if="tabAct == 2">
|
||||
@@ -119,7 +132,9 @@
|
||||
import { getCourseDetailApi } from '@/api/courseDetail.js';
|
||||
import { startExamByCrs } from '@/api/examination.js';
|
||||
import { insertTraPersonalCollectionTask, deleteTraPersonalCollectionById } from '@/api/favorites.js';
|
||||
import { startPracticeByCrs } from '@/api/practice.js';
|
||||
import common from '@/common/common';
|
||||
import { setPageCache } from '@/common/common';
|
||||
import introduceVue from './components/introduce.vue';
|
||||
import knowledge from './components/knowledge.vue';
|
||||
import comment from './components/comment.vue';
|
||||
@@ -181,13 +196,14 @@
|
||||
const goto_examination = async () => {
|
||||
common.loading();
|
||||
startExamByCrs({
|
||||
crsId : crsId.value
|
||||
crsId: crsId.value
|
||||
// crsId: 'CRS0250181220722025070408313900000018729'
|
||||
})
|
||||
.then((res) => {
|
||||
setPageCache('examination', {
|
||||
...res.body,
|
||||
examId: detailData.examId
|
||||
name: form.value.crsName,
|
||||
crsId: crsId.value
|
||||
});
|
||||
common.navigateTo('/pages/examination/index');
|
||||
})
|
||||
@@ -195,6 +211,25 @@
|
||||
common.hideLoading();
|
||||
});
|
||||
};
|
||||
// 去练习
|
||||
const goto_practice = async () => {
|
||||
common.loading();
|
||||
startPracticeByCrs({
|
||||
crsId: crsId.value
|
||||
})
|
||||
.then((res) => {
|
||||
console.log('res', res);
|
||||
setPageCache('practice', {
|
||||
...res.body,
|
||||
name: form.value.crsName,
|
||||
crsId: crsId.value,
|
||||
});
|
||||
common.navigateTo('/pages/practice/index');
|
||||
})
|
||||
.finally(() => {
|
||||
common.hideLoading();
|
||||
});
|
||||
};
|
||||
|
||||
const collect_click = async (collectId) => {
|
||||
try {
|
||||
@@ -318,7 +353,7 @@
|
||||
padding-bottom: 24rpx;
|
||||
min-height: 158rpx;
|
||||
justify-content: space-between;
|
||||
}
|
||||
}
|
||||
|
||||
.title-text {
|
||||
font-size: 34rpx;
|
||||
@@ -340,6 +375,7 @@
|
||||
|
||||
.title-num {
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
|
||||
.examination {
|
||||
color: #0066ff;
|
||||
@@ -431,7 +467,7 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 30rpx;
|
||||
margin-right: 30rpx;
|
||||
margin-right: 26rpx;
|
||||
color: #666666;
|
||||
height: 30rpx;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
<template>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
@@ -0,0 +1,257 @@
|
||||
<template>
|
||||
<view class="scroll_div">
|
||||
<scroll-view scroll-y="true" class="scroll-Y" @scrolltolower="scrolltolower" :show-scrollbar="false">
|
||||
<view
|
||||
class="item"
|
||||
:class="getStatusClass(item.isFinish)"
|
||||
v-for="(item, index) in data_list"
|
||||
@click="click_item(item)"
|
||||
>
|
||||
<view class="img_div">
|
||||
<image-preview class="img" :src="item.ossAddr" mode="scaleToFill"></image-preview>
|
||||
</view>
|
||||
<view class="right_div">
|
||||
<view class="title">
|
||||
{{
|
||||
item.crsName
|
||||
}}阿斯顿萨达萨达阿斯顿萨达萨达萨达萨达萨达萨达
|
||||
</view>
|
||||
<view class="prompt_div">
|
||||
<image :src="studyDurationIcon()" class="img"></image>
|
||||
<view class="prompt">答题正确率:30</view>
|
||||
</view>
|
||||
<view class="prompt_div">
|
||||
<image :src="studyTimeIcon()" class="img"></image>
|
||||
<view class="prompt">练习记录:2条</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<list-no-data v-if="total == 0 && status == 'nomore'"></list-no-data>
|
||||
<uv-load-more v-if="total != 0" :status="status" loadmore-text="轻轻上拉加载" :height="30"></uv-load-more>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</template>
|
||||
<script setup>
|
||||
const status = ref('loading'); // loadmore - 加载前,loading - 加载中,nomore - 没有数据
|
||||
const limit = 15;
|
||||
const total = ref(-1);
|
||||
const page = ref(0);
|
||||
const data_list = reactive([]);
|
||||
import { setPageCache } from '@/common/common';
|
||||
import common from '@/common/common';
|
||||
import { ref, reactive, onMounted, nextTick } from 'vue';
|
||||
|
||||
import { queryPracticeRecordPaging, queryPracticeHis } from '@/api/courseRecord.js';
|
||||
import { studyDurationIcon, studyTimeIcon } from '@/common/imgSvg';
|
||||
const props = defineProps({});
|
||||
|
||||
const getData = (from = '', searchText = '') => {
|
||||
if (from == 'first') {
|
||||
if (total.value !== -1) {
|
||||
return;
|
||||
}
|
||||
status.value = 'loading';
|
||||
total.value = -1;
|
||||
page.value = 1;
|
||||
data_list.length = 0;
|
||||
} else {
|
||||
if (status.value !== 'loadmore' && status.value !== '') return;
|
||||
status.value = 'loading';
|
||||
page.value++;
|
||||
}
|
||||
setTimeout(() => {
|
||||
queryPracticeRecordPaging({
|
||||
page: page.value,
|
||||
limit: limit
|
||||
})
|
||||
.then((res) => {
|
||||
total.value = res.total;
|
||||
data_list.push(...res.body);
|
||||
})
|
||||
.finally(() => {
|
||||
if (data_list.length >= total.value) {
|
||||
status.value = 'nomore';
|
||||
} else {
|
||||
status.value = 'loadmore';
|
||||
}
|
||||
});
|
||||
}, 200);
|
||||
};
|
||||
const getStatusClass = (isFinish) => {
|
||||
// 00进行中、01已完成、02已超时
|
||||
if (isFinish === '00') return 'in_progress';
|
||||
if (isFinish === '01') return 'completed';
|
||||
return 'expired';
|
||||
};
|
||||
|
||||
// 跳转到详情
|
||||
const click_item = (item) => {
|
||||
if (item.isTimeOut === '00') {
|
||||
common.msg('任务已结束');
|
||||
return;
|
||||
}
|
||||
setPageCache('learning_tasks_details', item);
|
||||
common.navigateTo('/pages/learningTasks/details');
|
||||
};
|
||||
const scrolltolower = (item) => {
|
||||
getData();
|
||||
};
|
||||
const search = (value) => {
|
||||
total.value = -1;
|
||||
console.log('value', value);
|
||||
getData('first', value);
|
||||
};
|
||||
defineExpose({
|
||||
getData,
|
||||
search
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.scroll_div {
|
||||
background-color: #f1f5fa;
|
||||
}
|
||||
|
||||
.scroll-Y {
|
||||
height: calc(100vh - var(--status-bar-height) - 88rpx - 88rpx);
|
||||
}
|
||||
|
||||
.scroll-Y {
|
||||
.item.in_progress {
|
||||
// 进行中
|
||||
.subscript {
|
||||
color: #0066ff;
|
||||
background-color: #daf0ff;
|
||||
}
|
||||
|
||||
.blod_color {
|
||||
color: #0066ff;
|
||||
}
|
||||
}
|
||||
|
||||
.item.completed {
|
||||
// 已完成
|
||||
.subscript {
|
||||
color: #ffffff;
|
||||
background-color: #33c583 !important;
|
||||
}
|
||||
|
||||
.blod_color {
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
|
||||
.item.expired {
|
||||
// 已超时
|
||||
.subscript {
|
||||
color: #ffffff;
|
||||
background-color: #ef5705;
|
||||
}
|
||||
|
||||
.blod_color {
|
||||
color: #d70c18;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.scroll-Y .item {
|
||||
margin: 17rpx 20rpx;
|
||||
display: flex;
|
||||
|
||||
background-color: #fff;
|
||||
border-radius: 16rpx;
|
||||
padding: 32rpx 22rpx;
|
||||
.img_div {
|
||||
position: relative;
|
||||
width: 224rpx;
|
||||
height: 168rpx;
|
||||
overflow: hidden;
|
||||
border-radius: 22rpx;
|
||||
|
||||
.img {
|
||||
width: 226rpx;
|
||||
height: 168rpx;
|
||||
}
|
||||
|
||||
.subscript {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
width: 92rpx;
|
||||
height: 46rpx;
|
||||
border-radius: 0px 0px 0px 22rpx;
|
||||
font-family: PingFangSC;
|
||||
font-weight: 400;
|
||||
font-size: 22rpx;
|
||||
line-height: 32px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
.right_div {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
margin-left: 24rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
|
||||
.title {
|
||||
font-family: PingFangSC;
|
||||
color: #333333;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-size: 28rpx; /* 字体大小30rpx */
|
||||
display: -webkit-box; /* 启用弹性盒模型 */
|
||||
-webkit-box-orient: vertical; /* 设置盒子内子元素的排列方向为垂直 */
|
||||
-webkit-line-clamp: 2; /* 限制最多显示2行 */
|
||||
overflow: hidden; /* 超出部分隐藏 */
|
||||
text-overflow: ellipsis; /* 超出部分显示省略号(多行时可能不显示,但建议保留) */
|
||||
line-height: 1.5; /* 可选:设置行高,优化多行显示效果 */
|
||||
}
|
||||
|
||||
.prompt_div {
|
||||
font-family: PingFangSC;
|
||||
font-weight: 400;
|
||||
font-size: 23rpx;
|
||||
color: #666;
|
||||
line-height: 23rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
.img{
|
||||
width: 33rpx;
|
||||
height: 33rpx;
|
||||
}
|
||||
.prompt{
|
||||
margin-left: 14rpx;
|
||||
font-weight: 400;
|
||||
font-size: 22rpx;
|
||||
color: #666666;
|
||||
line-height: 32rpx;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.people_progress_div {
|
||||
display: flex;
|
||||
font-family: PingFangSC;
|
||||
font-weight: 400;
|
||||
font-size: 23rpx;
|
||||
color: #666;
|
||||
margin-bottom: 23rpx;
|
||||
|
||||
line-height: 23rpx;
|
||||
flex-wrap: nowrap;
|
||||
height: 23rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,8 @@
|
||||
<template>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
@@ -0,0 +1,198 @@
|
||||
<template>
|
||||
<view class="max_page detail-main">
|
||||
<nav-bar :is_seat="false"></nav-bar>
|
||||
<view class="fixed_search_div">
|
||||
<view class="back_div" @click="common.navigateBack()">
|
||||
<view class="back-icon"></view>
|
||||
</view>
|
||||
<view class="title font_pf">课程记录</view>
|
||||
</view>
|
||||
|
||||
<view class="detail-body">
|
||||
<view class="body-tab">
|
||||
<uv-tabs
|
||||
class="font_pf my_tabs"
|
||||
:current="tabAct"
|
||||
:list="tabList"
|
||||
@change="tabChange"
|
||||
:scrollable="false"
|
||||
line-color="#0066FF"
|
||||
:inactive-style="{ color: '#333333', fontSize: '30rpx', fontWeight: '600' }"
|
||||
:activeStyle="{ color: '#0066FF', fontSize: '30rpx', fontWeight: '600' }"
|
||||
:lineColor="`url(${LineBg}) 10% 10%`"
|
||||
></uv-tabs>
|
||||
</view>
|
||||
<view class="uni-margin-wrap no-overflow">
|
||||
<swiper class="swiper" :current="tabAct" :indicator-dots="false" @change="swiperChange">
|
||||
<swiper-item>
|
||||
<studyRecordItem :ref="(el) => (listItemRefs[0] = el)"></studyRecordItem>
|
||||
</swiper-item>
|
||||
<swiper-item>
|
||||
<practiceRecordItem :ref="(el) => (listItemRefs[1] = el)"></practiceRecordItem>
|
||||
</swiper-item>
|
||||
<swiper-item>
|
||||
<examRecordItem :ref="(el) => (listItemRefs[2] = el)"></examRecordItem>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { LineBg } from '@/enum.js';
|
||||
|
||||
import studyRecordItem from './components/studyRecordItem.vue';
|
||||
import practiceRecordItem from './components/practiceRecordItem.vue';
|
||||
import examRecordItem from './components/examRecordItem.vue';
|
||||
import { reactive, ref, computed, nextTick, onMounted, watch } from 'vue';
|
||||
import common from '@/common/common.js';
|
||||
const listItemRefs = ref([]);
|
||||
const taskRef = ref(null);
|
||||
const tabAct = ref(1);
|
||||
const tabList = ref([
|
||||
{
|
||||
name: '学习记录'
|
||||
},
|
||||
{
|
||||
name: '练习记录'
|
||||
},
|
||||
{
|
||||
name: '考试记录'
|
||||
}
|
||||
]);
|
||||
|
||||
const tabChange = (item) => {
|
||||
tabAct.value = item.index;
|
||||
};
|
||||
const swiperChange = (item) => {
|
||||
tabAct.value = item.detail.current;
|
||||
};
|
||||
const search = (value) => {
|
||||
listItemRefs.value[tabAct.value]?.search(value);
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
watch(
|
||||
tabAct,
|
||||
(newValue, oldValue) => {
|
||||
typeof listItemRefs.value[newValue]?.getData === 'function' &&
|
||||
listItemRefs.value[newValue]?.getData('first');
|
||||
},
|
||||
{
|
||||
immediate: true
|
||||
}
|
||||
); // 这里的immediate会在onMounted之后执行
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
$bg-margin-left: 50rpx;
|
||||
|
||||
.my_tabs {
|
||||
// 解决这个圆角的图片,开穿透
|
||||
:deep(.uv-tabs__wrapper__nav__line) {
|
||||
height: 26rpx !important;
|
||||
left: 60rpx;
|
||||
background-size: 28rpx !important;
|
||||
background-repeat: no-repeat !important;
|
||||
}
|
||||
}
|
||||
|
||||
.swiper {
|
||||
/*
|
||||
状态栏 var(--status-bar-height)
|
||||
标题高度88rpx
|
||||
搜索栏高度80rpx
|
||||
tab切换栏高度88rpx
|
||||
下方滑动区域上下边距各10共20rpx
|
||||
**/
|
||||
|
||||
height: calc(100vh - var(--status-bar-height) - 88rpx - 80rpx - 88rpx - 20rpx);
|
||||
}
|
||||
|
||||
.swiper-item {
|
||||
display: block;
|
||||
height: 100%;
|
||||
line-height: 300rpx;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.detail-body {
|
||||
background: #ffffff;
|
||||
border-radius: 15rpx;
|
||||
z-index: 101;
|
||||
overflow: hidden;
|
||||
|
||||
.body-tab {
|
||||
height: 88rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.detail-main {
|
||||
background-color: #f6f8ff;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.title {
|
||||
color: #000000;
|
||||
font-size: 34rpx;
|
||||
height: 34rpx;
|
||||
font-weight: 600;
|
||||
line-height: 34rpx;
|
||||
}
|
||||
.fixed_search_input_div {
|
||||
width: 100%;
|
||||
height: 80rpx;
|
||||
padding: 0 22rpx;
|
||||
// background-color: red;
|
||||
background-color: #fff;
|
||||
:deep(.uv-input.uv-input--radius) {
|
||||
border-radius: 16rpx !important;
|
||||
}
|
||||
}
|
||||
.fixed_search_div {
|
||||
padding: calc(20rpx + var(--status-bar-height)) 15rpx 34rpx 30rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
background-color: #fff;
|
||||
// background-color: red;
|
||||
// height: 180rpx;
|
||||
position: relative;
|
||||
|
||||
.back_div {
|
||||
position: absolute;
|
||||
left: 20rpx;
|
||||
top: var(--status-bar-height);
|
||||
padding: 10rpx;
|
||||
|
||||
.back-icon {
|
||||
position: relative;
|
||||
width: 50rpx;
|
||||
height: 50rpx;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.back-icon::before,
|
||||
.back-icon::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.back-icon::after {
|
||||
top: 25%;
|
||||
left: 25%;
|
||||
width: 40%;
|
||||
height: 40%;
|
||||
border-top: 4rpx solid #000000;
|
||||
border-left: 4rpx solid #000000;
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -218,6 +218,7 @@
|
||||
const clikc_sheet_item = (index) => {
|
||||
questionNumber.value = index;
|
||||
};
|
||||
|
||||
const subject_click = (type, params) => {
|
||||
if (type === 'mark') {
|
||||
topicList[questionNumber.value]['mark'] = !topicList[questionNumber.value]['mark'];
|
||||
@@ -236,6 +237,7 @@
|
||||
} else if (type === 'text') {
|
||||
}
|
||||
};
|
||||
|
||||
// 发送语音
|
||||
const uploadRecordNow = (voicePath) => {
|
||||
commonUploadVoiceFile(voicePath, '/traask/traAskchat/voiceTrans', {})
|
||||
|
||||
@@ -0,0 +1,249 @@
|
||||
<template>
|
||||
<view class="scroll_div">
|
||||
<scroll-view scroll-y="true" class="scroll-Y" @scrolltolower="scrolltolower" :show-scrollbar="false">
|
||||
<view
|
||||
class="item"
|
||||
:class="getStatusClass(item.isFinish)"
|
||||
v-for="(item, index) in data_list"
|
||||
@click="click_item(item)"
|
||||
>
|
||||
<view class="img_div">
|
||||
<image-preview class="img" :src="item.ossAddr" mode="scaleToFill"></image-preview>
|
||||
<view class="subscript" v-if="item.isFinish === '00'">未完成</view>
|
||||
<view class="subscript" v-if="item.isFinish === '01'">已完成</view>
|
||||
</view>
|
||||
<view class="right_div">
|
||||
<view class="title ellipsis-text">
|
||||
{{ item.taskName }}
|
||||
</view>
|
||||
<view class="time_div" v-if="item.limitTyp === '02'">
|
||||
起止时间:
|
||||
<text class="blod_color">{{ item.startTm?.substr(0, 10) }}至{{ item.endTm?.substr(0, 10) }}</text>
|
||||
</view>
|
||||
<view class="people_progress_div">
|
||||
<view class="mr-10">
|
||||
完成人数:
|
||||
<text class="">{{ item.taskFinishSums ?? 0 }}/{{ item.taskSums ?? 0 }}</text>
|
||||
</view>
|
||||
<view>
|
||||
进度:
|
||||
<text class="">{{ item.finishCrs ?? 0 }}/{{ item.sumCrs ?? 0 }}门课程</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<list-no-data v-if="total == 0 && status == 'nomore'"></list-no-data>
|
||||
<uv-load-more v-if="total != 0" :status="status" loadmore-text="轻轻上拉加载" :height="30"></uv-load-more>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</template>
|
||||
<script setup>
|
||||
const status = ref('loading'); // loadmore - 加载前,loading - 加载中,nomore - 没有数据
|
||||
const limit = 15;
|
||||
const total = ref(-1);
|
||||
const page = ref(0);
|
||||
const data_list = reactive([]);
|
||||
import { setPageCache } from '@/common/common';
|
||||
import common from '@/common/common';
|
||||
import { ref, reactive, onMounted, nextTick } from 'vue';
|
||||
|
||||
import { queryAllTraTaskInfoByUserId } from '@/api/learningTasks.js';
|
||||
const props = defineProps({
|
||||
state: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
});
|
||||
|
||||
const getData = (from = '', searchText = '') => {
|
||||
if (from == 'first') {
|
||||
if (total.value !== -1) {
|
||||
return;
|
||||
}
|
||||
status.value = 'loading';
|
||||
total.value = -1;
|
||||
page.value = 1;
|
||||
data_list.length = 0;
|
||||
} else {
|
||||
if (status.value !== 'loadmore' && status.value !== '') return;
|
||||
status.value = 'loading';
|
||||
page.value++;
|
||||
}
|
||||
setTimeout(() => {
|
||||
queryAllTraTaskInfoByUserId({
|
||||
state: props.state,
|
||||
page: page.value,
|
||||
limit: limit,
|
||||
taskName: searchText
|
||||
})
|
||||
.then((res) => {
|
||||
total.value = res.total;
|
||||
data_list.push(...res.body);
|
||||
})
|
||||
.finally(() => {
|
||||
if (data_list.length >= total.value) {
|
||||
status.value = 'nomore';
|
||||
} else {
|
||||
status.value = 'loadmore';
|
||||
}
|
||||
});
|
||||
}, 200);
|
||||
};
|
||||
const getStatusClass = (isFinish) => {
|
||||
// 00进行中、01已完成、02已超时
|
||||
if (isFinish === '00') return 'in_progress';
|
||||
if (isFinish === '01') return 'completed';
|
||||
return 'expired';
|
||||
};
|
||||
|
||||
// 跳转到详情
|
||||
const click_item = (item) => {
|
||||
if(item.isTimeOut === '00') {
|
||||
common.msg('任务已结束')
|
||||
return ;
|
||||
}
|
||||
setPageCache('learning_tasks_details', item);
|
||||
common.navigateTo('/pages/learningTasks/details');
|
||||
};
|
||||
const scrolltolower = (item) => {
|
||||
getData();
|
||||
};
|
||||
const search = (value) => {
|
||||
total.value = -1;
|
||||
console.log('value', value);
|
||||
getData('first', value);
|
||||
};
|
||||
defineExpose({
|
||||
getData,
|
||||
search
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.scroll_div {
|
||||
background-color: #f1f5fa;
|
||||
padding: 22rpx;
|
||||
}
|
||||
|
||||
.scroll-Y {
|
||||
height: calc(100vh - var(--status-bar-height) - 88rpx - 80rpx - 88rpx - 20rpx - 30rpx);
|
||||
// height: calc(100vh - var(--status-bar-height) - 54rpx - 88rpx - 20rpx - 44rpx);
|
||||
background-color: #fff;
|
||||
border-radius: 16rpx;
|
||||
}
|
||||
|
||||
.scroll-Y {
|
||||
.item.in_progress {
|
||||
// 进行中
|
||||
.subscript {
|
||||
color: #0066ff;
|
||||
background-color: #daf0ff;
|
||||
}
|
||||
|
||||
.blod_color {
|
||||
color: #0066ff;
|
||||
}
|
||||
}
|
||||
|
||||
.item.completed {
|
||||
// 已完成
|
||||
.subscript {
|
||||
color: #ffffff;
|
||||
background-color: #33c583 !important;
|
||||
}
|
||||
|
||||
.blod_color {
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
|
||||
.item.expired {
|
||||
// 已超时
|
||||
.subscript {
|
||||
color: #ffffff;
|
||||
background-color: #ef5705;
|
||||
}
|
||||
|
||||
.blod_color {
|
||||
color: #d70c18;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.scroll-Y .item {
|
||||
height: 170rpx;
|
||||
margin: 32rpx 22rpx;
|
||||
display: flex;
|
||||
|
||||
.img_div {
|
||||
position: relative;
|
||||
width: 224rpx;
|
||||
height: 168rpx;
|
||||
overflow: hidden;
|
||||
border-radius: 22rpx;
|
||||
|
||||
.img {
|
||||
width: 226rpx;
|
||||
height: 168rpx;
|
||||
}
|
||||
|
||||
.subscript {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
width: 92rpx;
|
||||
height: 46rpx;
|
||||
border-radius: 0px 0px 0px 22rpx;
|
||||
font-family: PingFangSC;
|
||||
font-weight: 400;
|
||||
font-size: 22rpx;
|
||||
line-height: 32px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
.right_div {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
margin-left: 24rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
|
||||
.title {
|
||||
font-family: PingFangSC;
|
||||
font-size: 30rpx;
|
||||
font-weight: 600;
|
||||
color: #333333;
|
||||
line-height: 44rpx;
|
||||
}
|
||||
|
||||
.time_div {
|
||||
font-family: PingFangSC;
|
||||
font-weight: 400;
|
||||
font-size: 23rpx;
|
||||
color: #666;
|
||||
line-height: 23rpx;
|
||||
flex-wrap: nowrap;
|
||||
height: 23rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.people_progress_div {
|
||||
display: flex;
|
||||
font-family: PingFangSC;
|
||||
font-weight: 400;
|
||||
font-size: 23rpx;
|
||||
color: #666;
|
||||
margin-bottom: 23rpx;
|
||||
|
||||
line-height: 23rpx;
|
||||
flex-wrap: nowrap;
|
||||
height: 23rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,197 @@
|
||||
<template>
|
||||
<view class="max_page detail-main">
|
||||
<nav-bar :is_seat="false"></nav-bar>
|
||||
<view class="fixed_search_div">
|
||||
<view class="back_div" @click="common.navigateBack()">
|
||||
<view class="back-icon"></view>
|
||||
</view>
|
||||
<view class="title font_pf">学习任务</view>
|
||||
</view>
|
||||
<view class="fixed_search_input_div">
|
||||
<search-input placeholder="请输入任务名" @search="search"></search-input>
|
||||
</view>
|
||||
<view class="detail-body">
|
||||
<view class="body-tab">
|
||||
<uv-tabs
|
||||
class="font_pf my_tabs"
|
||||
:current="tabAct"
|
||||
:list="tabList"
|
||||
@change="tabChange"
|
||||
:scrollable="false"
|
||||
line-color="#0066FF"
|
||||
:inactive-style="{ color: '#333333', fontSize: '30rpx', fontWeight: '600' }"
|
||||
:activeStyle="{ color: '#0066FF', fontSize: '30rpx', fontWeight: '600' }"
|
||||
:lineColor="`url(${LineBg}) 10% 10%`"
|
||||
></uv-tabs>
|
||||
</view>
|
||||
<view class="uni-margin-wrap no-overflow">
|
||||
<swiper class="swiper" :current="tabAct" :indicator-dots="false" @change="swiperChange">
|
||||
<swiper-item>
|
||||
<listItem :ref="(el) => (listItemRefs[0] = el)" state="01"></listItem>
|
||||
</swiper-item>
|
||||
<swiper-item>
|
||||
<listItem :ref="(el) => (listItemRefs[1] = el)" state="02"></listItem>
|
||||
</swiper-item>
|
||||
<swiper-item>
|
||||
<listItem :ref="(el) => (listItemRefs[2] = el)" state="03"></listItem>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { LineBg } from '@/enum.js';
|
||||
import listItem from './components/list-item.vue';
|
||||
import { reactive, ref, computed, nextTick, onMounted, watch } from 'vue';
|
||||
import common from '@/common/common.js';
|
||||
const listItemRefs = ref([]);
|
||||
const taskRef = ref(null);
|
||||
const tabAct = ref(0);
|
||||
const tabList = ref([
|
||||
{
|
||||
name: '全 部'
|
||||
},
|
||||
{
|
||||
name: '已完成'
|
||||
},
|
||||
{
|
||||
name: '未完成'
|
||||
}
|
||||
]);
|
||||
|
||||
const tabChange = (item) => {
|
||||
tabAct.value = item.index;
|
||||
};
|
||||
const swiperChange = (item) => {
|
||||
tabAct.value = item.detail.current;
|
||||
};
|
||||
const search = (value) => {
|
||||
listItemRefs.value[tabAct.value]?.search(value);
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
watch(
|
||||
tabAct,
|
||||
(newValue, oldValue) => {
|
||||
typeof listItemRefs.value[newValue]?.getData === 'function' &&
|
||||
listItemRefs.value[newValue]?.getData('first');
|
||||
},
|
||||
{
|
||||
immediate: true
|
||||
}
|
||||
); // 这里的immediate会在onMounted之后执行
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
$bg-margin-left: 50rpx;
|
||||
|
||||
.my_tabs {
|
||||
// 解决这个圆角的图片,开穿透
|
||||
:deep(.uv-tabs__wrapper__nav__line) {
|
||||
height: 26rpx !important;
|
||||
left: 60rpx;
|
||||
background-size: 28rpx !important;
|
||||
background-repeat: no-repeat !important;
|
||||
}
|
||||
}
|
||||
|
||||
.swiper {
|
||||
/*
|
||||
状态栏 var(--status-bar-height)
|
||||
标题高度88rpx
|
||||
搜索栏高度80rpx
|
||||
tab切换栏高度88rpx
|
||||
下方滑动区域上下边距各10共20rpx
|
||||
**/
|
||||
|
||||
height: calc(100vh - var(--status-bar-height) - 88rpx - 80rpx - 88rpx - 20rpx);
|
||||
}
|
||||
|
||||
.swiper-item {
|
||||
display: block;
|
||||
height: 100%;
|
||||
line-height: 300rpx;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.detail-body {
|
||||
background: #ffffff;
|
||||
border-radius: 15rpx;
|
||||
z-index: 101;
|
||||
overflow: hidden;
|
||||
|
||||
.body-tab {
|
||||
height: 88rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.detail-main {
|
||||
background-color: #f6f8ff;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.title {
|
||||
color: #000000;
|
||||
font-size: 34rpx;
|
||||
height: 34rpx;
|
||||
font-weight: 600;
|
||||
line-height: 34rpx;
|
||||
}
|
||||
.fixed_search_input_div {
|
||||
width: 100%;
|
||||
height: 80rpx;
|
||||
padding: 0 22rpx;
|
||||
// background-color: red;
|
||||
background-color: #fff;
|
||||
:deep(.uv-input.uv-input--radius) {
|
||||
border-radius: 16rpx !important;
|
||||
}
|
||||
}
|
||||
.fixed_search_div {
|
||||
padding: calc(20rpx + var(--status-bar-height)) 15rpx 34rpx 30rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
background-color: #fff;
|
||||
// background-color: red;
|
||||
// height: 180rpx;
|
||||
position: relative;
|
||||
|
||||
.back_div {
|
||||
position: absolute;
|
||||
left: 20rpx;
|
||||
top: var(--status-bar-height);
|
||||
padding: 10rpx;
|
||||
|
||||
.back-icon {
|
||||
position: relative;
|
||||
width: 50rpx;
|
||||
height: 50rpx;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.back-icon::before,
|
||||
.back-icon::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.back-icon::after {
|
||||
top: 25%;
|
||||
left: 25%;
|
||||
width: 40%;
|
||||
height: 40%;
|
||||
border-top: 4rpx solid #000000;
|
||||
border-left: 4rpx solid #000000;
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
+5
-11
@@ -66,19 +66,13 @@
|
||||
<view class="navigation_div">
|
||||
<scroll-view class="scroll-view" scroll-x="true" :show-scrollbar="false">
|
||||
<view class="scroll-view-item">
|
||||
<view class="item">
|
||||
|
||||
<view class="item" @click="common.navigateTo('/pages/courseRecord/index')">
|
||||
<image class="icon" src="@/static/images/me/study.png"></image>
|
||||
<view class="title">学习记录</view>
|
||||
<view class="title">课程记录</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="scroll-view-item">
|
||||
<view class="item">
|
||||
<image class="icon" src="@/static/images/me/todo.png"></image>
|
||||
<view class="title">练习记录</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="scroll-view-item">
|
||||
|
||||
<view class="scroll-view-item" @click="common.navigateTo('/pages/examinationRecord/index')">
|
||||
<view class="item">
|
||||
<image class="icon" src="@/static/images/me/examination.png"></image>
|
||||
<view class="title">考试记录</view>
|
||||
@@ -92,7 +86,7 @@
|
||||
</view>
|
||||
<view class="scroll-view-item">
|
||||
<view class="item">
|
||||
<image class="icon" src="@/static/images/me/report.png"></image>
|
||||
<image class="icon" src="@/static/images/me/todo.png"></image>
|
||||
<view class="title">AI陪练记录</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -1,8 +1,648 @@
|
||||
<template>
|
||||
<view class="main_div max_page">
|
||||
<nav-bar :is_seat="true"></nav-bar>
|
||||
<view class="nav-div">
|
||||
<view class="title ellipsis-text" @click="hand_in_paper_button_click()">
|
||||
{{ paperData.name }}
|
||||
</view>
|
||||
<view class="back_div"></view>
|
||||
</view>
|
||||
<view class="countdown-and-question-number-div">
|
||||
<view class="top">
|
||||
<view class="countdown">
|
||||
<text class="grey">答题进度</text>
|
||||
<text class="bold">{{ questionNumber + 1 }}</text>
|
||||
<text class="grey">/{{ storageTopicList.length }}</text>
|
||||
</view>
|
||||
<view class="question">
|
||||
<view class="grey">剩余时间</view>
|
||||
<uv-count-down :time="100 * 1000" format="HH:mm:ss"></uv-count-down>
|
||||
</view>
|
||||
</view>
|
||||
<view class="progress">
|
||||
<uv-line-progress
|
||||
:percentage="progress"
|
||||
:showText="false"
|
||||
activeColor="#FFFFFF"
|
||||
inactiveColor="#89B8FF"
|
||||
:height="8"
|
||||
></uv-line-progress>
|
||||
</view>
|
||||
</view>
|
||||
<view class="scroll_div">
|
||||
<swiper
|
||||
class="swiper"
|
||||
:indicator-dots="false"
|
||||
@change="swiperChange"
|
||||
:current="questionNumber"
|
||||
easing-function="linear"
|
||||
>
|
||||
<swiper-item v-for="(item, index) in topicList">
|
||||
<view class="content">
|
||||
<view class="expose_shadow"></view>
|
||||
<scroll-view :scroll-y="true" class="scroll-Y" :show-scrollbar="false" :refresher-threshold="0">
|
||||
<Subject
|
||||
:item="item"
|
||||
:mode="mode"
|
||||
:isPreview="item.isPreview"
|
||||
:clearResult="item.clearResult"
|
||||
@subject_click="subject_click"
|
||||
v-model="item.my_answer"
|
||||
></Subject>
|
||||
<!-- <CharactersSubject :item="item" v-if="item.qnsTyp === 'ES'" :mode="mode"
|
||||
:activeVoiceId="activeVoiceId" :voicePathValue="voicePathValue"
|
||||
@subject_click="subject_click">
|
||||
</CharactersSubject> -->
|
||||
</scroll-view>
|
||||
</view>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
</view>
|
||||
<view class="fixed-box font_pf" :style="{ marginBottom: popup_input_bottom }">
|
||||
<view class="touch-btn-div" :class="{ show: showTouchBtn }">
|
||||
<TouchBtn
|
||||
class="talk-btns"
|
||||
@submit="touchBtnSubmit"
|
||||
loadingText="问题回答中,请在问题回答结束后重试!"
|
||||
:isLoading="!answerIsOver"
|
||||
:isDisabled="false"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 反馈组件 -->
|
||||
<Feedback ref="feedbackRef"></Feedback>
|
||||
<!-- 结尾弹出层 -->
|
||||
<!-- <Dialog ref="dialogRef" :dialogConfiguration="dialogConfiguration" @button_click="result_click"></Dialog> -->
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup>
|
||||
import Feedback from '@/pages/examination/components/feedback.vue';
|
||||
// import Dialog from './components/dialog.vue';
|
||||
import Subject from '@/components/examination/subject.vue';
|
||||
import CharactersSubject from '@/components/examination/characters-subject.vue';
|
||||
import TouchBtn from '@/components/examination/touchBtn.vue';
|
||||
import { ref, reactive, computed, onMounted, nextTick } from 'vue';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import common from '@/common/common';
|
||||
import { getPageCache } from '@/common/common';
|
||||
import { commonUploadVoiceFile } from '@/api/common.js';
|
||||
import { optionErrorIcon, examinationSheetIcon } from '@/common/imgSvg';
|
||||
import { practiceAnswer,practiceCommit } from '@/api/practice.js';
|
||||
const answerIsOver = ref(true);
|
||||
const feedbackRef = ref(null);
|
||||
const dialogRef = ref(null);
|
||||
const popupRef = ref(null);
|
||||
|
||||
const mode = ref('practice'); // 考试 examination 练习practice
|
||||
const paperData = reactive({
|
||||
exrId: '',
|
||||
crsId: '',
|
||||
name: '' // 名称
|
||||
}); // 试卷信息
|
||||
const topicList = reactive([]); // 问题列表
|
||||
const storageTopicList = ref([]); // 所有题列表
|
||||
const popup_input_bottom = ref('0px');
|
||||
const questionNumber = ref(0); // 题号
|
||||
const systemInfo = uni.getSystemInfoSync();
|
||||
const showTouchBtn = computed(() => {
|
||||
return topicList[questionNumber.value]['qnsTyp'] === 'ES';
|
||||
});
|
||||
|
||||
const progress = computed(() => {
|
||||
// 计算进度百分比(保留两位小数)
|
||||
const total = storageTopicList.value.length;
|
||||
if (total === 0) return 0;
|
||||
const completed = questionNumber.value + 1;
|
||||
return Math.min(Math.round((completed / total) * 10000) / 100, 100);
|
||||
});
|
||||
// 弹出框配置
|
||||
const dialogConfiguration = reactive({});
|
||||
|
||||
const activeVoiceId = ref('');
|
||||
|
||||
const swiperChange = (item) => {
|
||||
questionNumber.value = item.detail.current;
|
||||
};
|
||||
|
||||
const subject_click = (type, params) => {
|
||||
// 反馈
|
||||
if (type === 'feedback') {
|
||||
feedbackRef.value.open();
|
||||
} else if (type === 'answer') {
|
||||
console.log('answer', params);
|
||||
} else if (type === 'choose') {
|
||||
if (params.qnsTyp === 'SN') {
|
||||
submitProblem(params.answer)
|
||||
}
|
||||
console.log('choose', params);
|
||||
}
|
||||
};
|
||||
|
||||
// 答单题
|
||||
const submitProblem = (answer) => {
|
||||
console.log('答单题');
|
||||
const topic = topicList[questionNumber.value]
|
||||
console.log(topic);
|
||||
console.log(answer);
|
||||
common.loading('答题中')
|
||||
practiceAnswer({
|
||||
exrId:paperData.exrId,
|
||||
anserResult:answer.join(','),
|
||||
ossKey:'',
|
||||
qnsId:topic.qnsId
|
||||
}).then(res => {
|
||||
common.hideLoading()
|
||||
const body = res.body
|
||||
topic.isPreview = true // 不能在点击了,打开预览模式
|
||||
topic.clearResult = false // 不清除正确答案了
|
||||
// topic.correctFlag = body
|
||||
|
||||
console.log('答题结果', res);
|
||||
})
|
||||
}
|
||||
const voicePathValue = ref('');
|
||||
|
||||
// 录音按钮提交
|
||||
const touchBtnSubmit = (type, submitObj) => {
|
||||
if (type === 'voice') {
|
||||
uploadRecordNow(submitObj);
|
||||
} else if (type === 'text') {
|
||||
}
|
||||
};
|
||||
// 发送语音
|
||||
const uploadRecordNow = (voicePath) => {
|
||||
commonUploadVoiceFile(voicePath, '/traask/traAskchat/voiceTrans', {})
|
||||
.then((res) => {
|
||||
let _res = JSON.parse(res.data);
|
||||
voicePathValue.value = voicePath;
|
||||
console.log('_res', _res, voicePath);
|
||||
if (_res.rtnCode === '0000') {
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
uni.showToast({
|
||||
title: '系统异常,请联系管理员',
|
||||
icon: 'none',
|
||||
duration: 1000
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// 发送文本
|
||||
const submitAnswerNow = (val, cb = null) => {};
|
||||
|
||||
// 添加一道题
|
||||
const addProblem = () => {
|
||||
if (topicList.length >= storageTopicList.value.length) return false;
|
||||
topicList.push(storageTopicList.value[topicList.length]);
|
||||
return true;
|
||||
};
|
||||
// 初始化时检查
|
||||
onLoad(() => {
|
||||
const practice = getPageCache('practice');
|
||||
if (!practice) {
|
||||
common.navigateBack();
|
||||
return;
|
||||
}
|
||||
paperData.crsId = practice.crsId;
|
||||
paperData.name = practice.name;
|
||||
paperData.exrId = practice.exrId;
|
||||
storageTopicList.value = practice.qnsInfoVos.map((res) => ({
|
||||
...res,
|
||||
isPreview: false,
|
||||
clearResult: true,
|
||||
my_answer: []
|
||||
}));
|
||||
addProblem();
|
||||
// #ifdef APP-PLUS
|
||||
// 安全区域底部到屏幕底部的高度(即底部安全区域高度)
|
||||
const safeAreaBottomHeight = systemInfo.screenHeight - systemInfo.safeArea.bottom;
|
||||
uni.onKeyboardHeightChange((res) => {
|
||||
let keyboardHeight = res.height;
|
||||
// 仅在iOS端补偿安全区域高度
|
||||
if (systemInfo.platform === 'ios') {
|
||||
keyboardHeight = Math.max(0, keyboardHeight - safeAreaBottomHeight); // 避免负数
|
||||
}
|
||||
popup_input_bottom.value = `${keyboardHeight}px`;
|
||||
console.log('端补偿安全区域高度', popup_input_bottom.value);
|
||||
});
|
||||
// #endif
|
||||
});
|
||||
|
||||
const result_click = ({ key }) => {
|
||||
console.log('res', key);
|
||||
if (key === 'hand_in_paper') {
|
||||
// 现在交卷
|
||||
hand_in_paper();
|
||||
} else if (key === 'continue') {
|
||||
// 继续考试
|
||||
dialogRef.value.close();
|
||||
}
|
||||
};
|
||||
|
||||
// 交卷按钮点击,打开交卷确认框
|
||||
const hand_in_paper_button_click = () => {
|
||||
console.log('点击交卷', paperData);
|
||||
// console.log('点击交卷topicList', topicList);
|
||||
// return;
|
||||
// 判断是否完成所有题目
|
||||
const completeList = topicList
|
||||
.filter((res) => !!(Array.isArray(res.my_answer) ? res.my_answer.length : res.my_answer))
|
||||
.map((res) => ({
|
||||
a: res.qnsId,
|
||||
b: res.my_answer,
|
||||
c: !!res.my_answer
|
||||
}));
|
||||
dialogConfiguration.title = '确认现在交卷吗?';
|
||||
const style_button_1 = {
|
||||
color: '#FFFFFF',
|
||||
fontSize: '30rpx',
|
||||
backgroundColor: '#0066FF',
|
||||
borderRadius: '8rpx'
|
||||
};
|
||||
const style_button_2 = {
|
||||
color: '#0066FF',
|
||||
fontSize: '30rpx',
|
||||
backgroundColor: '#E2EDFF',
|
||||
borderRadius: '8rpx'
|
||||
};
|
||||
const incompleteNumber = topicList.length - completeList.length;
|
||||
if (incompleteNumber === 0) {
|
||||
// 完成
|
||||
dialogConfiguration.type = 'complete';
|
||||
dialogConfiguration.title = '确认现在交卷吗?';
|
||||
dialogConfiguration.buttonList = [
|
||||
{
|
||||
key: 'hand_in_paper',
|
||||
name: '现在交卷',
|
||||
style: style_button_1
|
||||
},
|
||||
{
|
||||
key: 'continue',
|
||||
name: '继续考试',
|
||||
style: style_button_2
|
||||
}
|
||||
];
|
||||
} else {
|
||||
dialogConfiguration.type = 'incomplete'; // 未完成
|
||||
dialogConfiguration.html = `当前考试进度:<text style="color:#0066FF;font-weight:bold;">${completeList.length}/${topicList.length}</text> 题 还有<text style="color:#0066FF;font-weight:bold;">${incompleteNumber}</text>道题未作答,确认交卷吗?`;
|
||||
dialogConfiguration.buttonList = [
|
||||
{
|
||||
key: 'continue',
|
||||
name: '继续考试',
|
||||
style: style_button_1
|
||||
},
|
||||
{
|
||||
key: 'hand_in_paper',
|
||||
name: '现在交卷',
|
||||
style: style_button_2
|
||||
}
|
||||
];
|
||||
}
|
||||
dialogRef.value.open();
|
||||
};
|
||||
// 执行交卷
|
||||
const hand_in_paper = () => {
|
||||
const answerDtoList = topicList.map((res) => {
|
||||
let answerItem = {
|
||||
examId: paperData.examId,
|
||||
papersId: paperData.papersId,
|
||||
qnsId: res.qnsId,
|
||||
ossKey: '',
|
||||
anserResult: ''
|
||||
};
|
||||
if (res.qnsTyp === 'ES') {
|
||||
// 问答题特殊处理
|
||||
return {
|
||||
...answerItem,
|
||||
anserResult: ''
|
||||
};
|
||||
} else {
|
||||
//其他题
|
||||
return {
|
||||
...answerItem,
|
||||
anserResult: res.my_answer.join(',')
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
console.log('answerDtoList', answerDtoList);
|
||||
dialogRef.value.close();
|
||||
common.loading('正在提交');
|
||||
commitPaperExam({
|
||||
examId: paperData.examId,
|
||||
execId: paperData.execId || '1',
|
||||
examLenTm: 1200,
|
||||
answerDtoStr: JSON.stringify(answerDtoList)
|
||||
})
|
||||
.then((res) => {
|
||||
console.log('提交成功', res);
|
||||
// 判断是否需要查分
|
||||
if (res.body.flagQuery === 'Y') {
|
||||
// 需要查分
|
||||
const examLenTm = 678;
|
||||
common.redirectTo(
|
||||
`/pages/examination/result?execId=${res.body.execId}&examLenTm=${examLenTm}&papersName=${paperData.papersName}`
|
||||
);
|
||||
} else {
|
||||
// todo 此处应该有个弹窗交代下结果
|
||||
common.navigateBack();
|
||||
}
|
||||
})
|
||||
.catch((res) => {
|
||||
console.log('error', res);
|
||||
})
|
||||
.finally(() => {
|
||||
common.hideLoading().body;
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
<style scoped lang="scss">
|
||||
$bg-margin-left: 30rpx;
|
||||
|
||||
.popup_title_text {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.popup {
|
||||
//答题卡
|
||||
z-index: 1800;
|
||||
padding: 0 38rpx;
|
||||
|
||||
.sheet_popup_div {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #ffffff;
|
||||
padding: 10rpx 34rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
border-radius: 16rpx 16rpx 0px 0px;
|
||||
position: relative;
|
||||
|
||||
.title_div {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
padding: 30rpx 0;
|
||||
font-family: PingFangSC;
|
||||
font-weight: 600;
|
||||
font-size: 34rpx;
|
||||
color: #000000;
|
||||
text-align: center;
|
||||
font-style: normal;
|
||||
border-bottom: 2rpx solid #efefef;
|
||||
}
|
||||
|
||||
.popup_back_div {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
position: absolute;
|
||||
top: 30rpx;
|
||||
right: 30rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.img {
|
||||
width: 30rpx;
|
||||
height: 30rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.sheet_table {
|
||||
margin-top: 48rpx;
|
||||
margin-bottom: 48rpx;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
width: calc(100vw - 108rpx);
|
||||
align-content: space-between;
|
||||
|
||||
.sheet_table_item {
|
||||
width: calc((100vw - 108rpx) / 5 - 16rpx);
|
||||
height: calc((100vw - 108rpx) / 5 - 16rpx);
|
||||
margin: 8rpx;
|
||||
border: 2rpx solid #e5e5e5;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 32rpx;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
.current {
|
||||
background-color: rgba(0, 102, 255, 0.6);
|
||||
border-color: #0066ff;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.completed {
|
||||
// 已完成
|
||||
background-color: rgba(0, 102, 255, 0.1);
|
||||
border-color: #0066ff;
|
||||
color: #0066ff;
|
||||
}
|
||||
|
||||
.mark,
|
||||
.completed.mark {
|
||||
background-color: rgba(232, 181, 49, 0.1);
|
||||
color: #e8b531;
|
||||
border-color: #e8b531;
|
||||
}
|
||||
|
||||
.current.mark {
|
||||
// 已完成
|
||||
background-color: rgba(0, 102, 255, 0.6);
|
||||
color: #ffffff;
|
||||
border-color: #e8b531;
|
||||
}
|
||||
}
|
||||
|
||||
.sheet_button {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.fixed-box {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
border-radius: 16rpx 16rpx 0px 0px;
|
||||
border: 2rpx solid #e5e5e5;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.touch-btn-div {
|
||||
height: 0;
|
||||
overflow: hidden;
|
||||
transition: height 0.2s ease-out;
|
||||
}
|
||||
|
||||
.touch-btn-div.show {
|
||||
height: 150rpx;
|
||||
}
|
||||
|
||||
.fixed-btn-box {
|
||||
height: 154rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0 20rpx 20rpx 20rpx;
|
||||
|
||||
.sheet_button {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
margin: 0 70rpx;
|
||||
|
||||
.img {
|
||||
width: 38rpx;
|
||||
height: 40rpx;
|
||||
}
|
||||
|
||||
.sheet_text {
|
||||
margin-top: 8rpx;
|
||||
font-family: PingFangSC;
|
||||
font-weight: 500;
|
||||
font-size: 24rpx;
|
||||
color: #000000;
|
||||
}
|
||||
}
|
||||
|
||||
.button_div {
|
||||
flex: 1;
|
||||
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
.button {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.scroll-Y {
|
||||
max-height: calc(100vh - var(--status-bar-height) - 70rpx - 70rpx - 40rpx - 64rpx - 68rpx - 60rpx);
|
||||
min-height: calc(100vh - var(--status-bar-height) - 70rpx - 70rpx - 40rpx - 64rpx - 68rpx - 60rpx - 380rpx);
|
||||
// background-color: yellow;
|
||||
}
|
||||
|
||||
.swiper {
|
||||
// 状态栏 var(--status-bar-height)
|
||||
// 标题栏 70rpx
|
||||
// 进度时间栏 70rpx
|
||||
// 进度时间栏上下间距 40rpx = 20rpx + 20rpx
|
||||
// 正文上下间距 64rpx
|
||||
height: calc(100vh - var(--status-bar-height) - 70rpx - 70rpx - 40rpx - 64rpx);
|
||||
// background-color: red;
|
||||
}
|
||||
|
||||
.content {
|
||||
position: relative;
|
||||
margin: 32rpx $bg-margin-left;
|
||||
border-radius: 16rpx;
|
||||
padding: 34rpx 30rpx 34rpx 36rpx;
|
||||
background-color: #fff;
|
||||
|
||||
.expose_shadow {
|
||||
margin-left: 36rpx;
|
||||
position: absolute;
|
||||
bottom: -26rpx;
|
||||
left: 0%;
|
||||
width: calc(100% - 66rpx);
|
||||
height: 28rpx;
|
||||
background-color: #ffffff;
|
||||
border-radius: 0 0 14rpx 14rpx;
|
||||
opacity: 0.4;
|
||||
z-index: 0;
|
||||
// background-color: red;
|
||||
}
|
||||
}
|
||||
|
||||
.countdown-and-question-number-div {
|
||||
margin: 20rpx $bg-margin-left;
|
||||
height: 70rpx;
|
||||
// background-color: red;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
z-index: 10;
|
||||
|
||||
.top {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
font-family: PingFangSC;
|
||||
font-size: 26rpx;
|
||||
color: #ffffff;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
.question {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
// background-color: red;
|
||||
width: 242rpx;
|
||||
color: red;
|
||||
|
||||
.grey {
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
|
||||
:deep(.uv-count-down__text) {
|
||||
color: #ffffff !important;
|
||||
font-weight: 600;
|
||||
font-size: 26rpx !important;
|
||||
}
|
||||
}
|
||||
|
||||
.grey {
|
||||
color: #b6e2ff;
|
||||
}
|
||||
|
||||
.bold {
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-div {
|
||||
position: relative;
|
||||
|
||||
.title {
|
||||
// padding-top:var(--status-bar-height);
|
||||
// padding: 0 30rpx;
|
||||
margin: 0 calc($bg-margin-left + 70rpx);
|
||||
height: 70rpx;
|
||||
font-family: PingFangSC;
|
||||
font-weight: 500;
|
||||
font-size: 34rpx;
|
||||
color: #ffffff;
|
||||
text-align: center;
|
||||
font-style: normal;
|
||||
line-height: 70rpx;
|
||||
}
|
||||
|
||||
.back_div {
|
||||
position: absolute;
|
||||
right: $bg-margin-left;
|
||||
top: 0;
|
||||
width: 70rpx;
|
||||
height: 70rpx;
|
||||
// background-color: red;
|
||||
}
|
||||
}
|
||||
|
||||
.main_div {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: linear-gradient(to top, #3480ff, #0066ff);
|
||||
/* 确保背景占满整个视口高度 */
|
||||
min-height: 100vh;
|
||||
margin: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -179,6 +179,24 @@
|
||||
"titleNView": false
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/courseRecord/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "课程记录页",
|
||||
"app-plus": {
|
||||
"titleNView": false
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/examinationRecord/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "考试记录页",
|
||||
"app-plus": {
|
||||
"titleNView": false
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user