练习-联调

This commit is contained in:
binbin_pan 2024-08-23 20:10:40 +08:00
parent 191ec2e84c
commit cca07aa193
6 changed files with 369 additions and 185 deletions

View File

@ -72,7 +72,6 @@ export function getExamRankById(params) {
})
}
// 练习-列表 /personalCenter/getStudentPracticeList
export function getStudentPracticeList(params) {
return request({
@ -81,3 +80,75 @@ export function getStudentPracticeList(params) {
data: params
})
}
// 练习-总览 /studentPractice/getPracticeQuestionRate
export function getPracticeQuestionRate(params) {
return request({
url: '/studentPractice/getPracticeQuestionRate',
method: 'post',
data: params
})
}
// 练习-聚合数据 /studentPractice/getPracticeItData
export function getPracticeItData(params) {
return request({
url: '/studentPractice/getPracticeItData',
method: 'post',
data: params
})
}
// 练习-题目 studentPractice/getPracticeQuestion
export function getPracticeQuestion(params) {
return request({
url: '/studentPractice/getPracticeQuestion',
method: 'post',
data: params
})
}
// 练习-答题 studentPractice/insertPracticeAnswerById
export function insertPracticeAnswerById(params) {
return request({
url: '/studentPractice/insertPracticeAnswerById',
method: 'post',
data: params
})
}
// 练习-前后题-跳题 studentPractice/changeQuestion
export function changeQuestion(params) {
return request({
url: '/studentPractice/changeQuestion',
method: 'post',
data: params
})
}
// 练习-弹框序号跳题 /studentPractice/getPracticeQuestionList
export function getPracticeQuestionList(params) {
return request({
url: '/studentPractice/getPracticeQuestionList',
method: 'post',
data: params
})
}
// 练习-保存练习时长 /studentPractice/savePracticeDuration
export function savePracticeDuration(params) {
return request({
url: '/studentPractice/savePracticeDuration',
method: 'post',
data: params
})
}
// 练习-错题消除 studentPractice/updateRemoveRecordData
export function updateRemoveRecordData(params) {
return request({
url: '/studentPractice/updateRemoveRecordData',
method: 'post',
data: params
})
}

View File

@ -2,7 +2,7 @@
module.exports = {
// baseUrl:'/prod-api',
// baseUrl:'http://112.29.103.165:1616/ynuw',
baseUrl:'http://192.168.0.32:2900/exam-student',
baseUrl:'http://192.168.0.137:2900/exam-student',
// 上传文件地址
uploadUrl: 'http://192.168.0.137:2909/exam-file/file/uploadBase64',
bmwUrl: 'http://192.168.0.137:2911/exam-bmw',

View File

@ -4,25 +4,25 @@
<div class="num-wrapper">
<div class="correct">
<u-icon name="/static/images/true.png" size="15" />
<div class="num">{{ correctNum }}</div>
<div class="num">{{ trueNum }}</div>
</div>
<div class="error">
<u-icon name="/static/images/error.png" size="15" />
<div class="num">{{ errorNum }}</div>
<div class="num">{{ falseNum }}</div>
</div>
<div class="total" @click="openSelect">
<u-icon name="/static/images/quanbufenlei.png" size="15" />
<div class="num">{{ currentIndex + 1 }}/{{ questionList.length }}</div>
<div class="num">{{ allNum }}</div>
</div>
</div>
<div class="question-wrapper" v-for="(item, index) in questionList" :key="index" v-show="index == currentIndex">
<div v-if="item.type !== 2">
<div class="title">{{ index + 1 }}. {{ item.title }}{{ item.type == 3 ? '(判断题)' : '(单选题)' }}</div>
<div class="question-wrapper" v-for="(item, index) in questionList" :key="index">
<div v-if="item.examType !== 2">
<div class="title">{{ item.paperTopic }}{{ item.examType == 1 ? '(单选题)' : '(判断题)' }}</div>
<u--image
v-if="item.img"
v-if="item.analyUrl"
:showLoading="true"
:src="item.img"
:src="item.analyUrl"
width="60px"
height="60px"
style="margin-bottom: 10px"
@ -31,39 +31,39 @@
<div class="options">
<div
class="option"
v-for="(option, index) in item.options"
v-for="(option, index) in item.listOption"
:key="index"
@click="handleOption(option, index)"
:class="{ active: option.isCorrect || option.isError }"
>
<div class="label">{{ option.value }}.{{ option.label }}</div>
<div class="label">{{ option.optionIdent }}.{{ option.optionContent }}</div>
<u-icon v-if="option.isCorrect" name="/static/images/对.png" size="25" />
<u-icon v-if="option.isError" name="/static/images/错.png" size="25" />
</div>
</div>
<div v-if="item.isSelect">
<div>正确答案{{ item.answer }}</div>
<div>正确答案{{ item.correctGrade }}</div>
<div>你的答案{{ item.select }}</div>
<div v-if="item.analysis">
<div class="analysis">答案解析</div>
<div class="analysis-container">{{ item.analysis }}</div>
<div class="analysis-container">{{ item.answerAnaly }}</div>
</div>
</div>
</div>
<!-- 多选 -->
<div v-else-if="item.type === 2">
<div class="title">{{ index + 1 }}. {{ item.title }}多选题</div>
<div v-else-if="item.examType === 2">
<div class="title">{{ index + 1 }}. {{ item.paperTopic }}多选题</div>
<div class="options">
<div
class="option"
v-for="(option, index) in item.options"
v-for="(option, index) in item.listOption"
:key="index"
@click="handleCheckbox(option, index)"
:class="{ active: option.isCheck }"
>
<div class="label">{{ option.value }}.{{ option.label }}</div>
<div class="label">{{ option.optionIdent }}.{{ option.optionContent }}</div>
<u-icon v-if="option.isCorrect" name="/static/images/对.png" size="25" />
<u-icon v-if="option.isError" name="/static/images/错.png" size="25" />
</div>
@ -71,7 +71,7 @@
<div class="btn">
<u-button
v-show="item.options.some(option => option.isCheck)"
v-show="item.listOption.some(option => option.isCheck)"
text="选好了"
shape="circle"
size="small"
@ -81,11 +81,11 @@
</div>
<div v-if="item.isSelect">
<div>正确答案{{ item.answer.join('、') }}</div>
<div>正确答案{{ item.correctGrade.join('、') }}</div>
<div>你的答案{{ item.select.join('、') }}</div>
<div class="analysis">知识点</div>
<div class="analysis-container">{{ item.knowledge }}</div>
<div class="analysis-container">{{ item.answerAnaly }}</div>
</div>
</div>
</div>
@ -104,24 +104,22 @@
</div>
<div class="btn">
<u-button
v-show="currentIndex !== 0"
type="primary"
size="small"
shape="circle"
text="上一题"
color="linear-gradient(to right, rgba(47, 195, 255, 1), rgba(5, 70, 173, 1))"
@click="currentIndex--"
@click="handleJump('prev')"
/>
</div>
<div class="btn">
<u-button
v-show="currentIndex !== questionList.length - 1"
type="primary"
size="small"
shape="circle"
text="下一题"
color="linear-gradient(to right, rgba(47, 195, 255, 1), rgba(5, 70, 173, 1))"
@click="currentIndex++"
@click="handleJump('next')"
/>
</div>
</div>
@ -144,7 +142,7 @@
<div>答题数</div>
</div>
<div class="item">
<div class="num">{{ correctNum }}</div>
<div class="num">{{ trueNum }}</div>
<div>正确数</div>
</div>
<div class="item">
@ -160,11 +158,11 @@
<view class="slot-content">
<div class="topic-content">
<div
v-for="(item, index) in questionList"
v-for="(item, index) in questionListSelect"
:key="index"
class="topic-wrapper"
:class="{ correct: item.isCorrect, error: item.isError }"
@click="currentIndex = index"
@click="handleJump(null, index)"
>
<div v-if="currentIndex == index">*</div>
<div class="topic">{{ index + 1 }}</div>
@ -176,9 +174,24 @@
</template>
<script>
import {
getPracticeItData, //
getPracticeQuestion, //
insertPracticeAnswerById, //
changeQuestion, //
getPracticeQuestionList, // -
getPracticeQuestionRate, //
savePracticeDuration, //
updateRemoveRecordData //
} from '@/api/eduApp'
export default {
data() {
return {
practiceId: '', // id
recordId: '', // id
isNew: 1, //
isOutOfOrder: 1, //
isError: false, //
showModal: false,
showModalSelect: false,
//
@ -186,126 +199,89 @@ export default {
// - - 00:00:00
usedTime: '00:00:00',
//
correctNum: 0,
trueNum: 0,
//
errorNum: 0,
falseNum: 0,
allNum: 0, //
//
answerNum: 0,
//
currentIndex: 0,
//
questionList: [
//
{
type: 1,
title: '只有发生在短路事故时或者在负荷电流较大时,变流器中才会有足够的二次电流作为继电保护跳闸之用。',
options: [
{ label: '变流器供给操作电源', value: 'A' },
{ label: '交流电压供给操作电源', value: 'B' },
{ label: '直流操作电源', value: 'C' },
{ label: '选项4', value: 'D' }
],
answer: 'A',
//
analysis: '这是答案解析'
},
//
{
type: 2,
title:
'只有发生在短路事故时或者在负荷电流较大时,变流器中才会有足够的二次电流作为继电保护跳闸之用。(多选题)',
options: [
{ label: '变流器供给操作电源', value: 'A' },
{ label: '交流电压供给操作电源', value: 'B' },
{ label: '直流操作电源', value: 'C' },
{ label: '选项4', value: 'D' }
],
answer: ['A', 'B'],
//
knowledge: '这是知识点'
},
//
{
type: 3,
title:
'只有发生在短路事故时或者在负荷电流较大时,变流器中才会有足够的二次电流作为继电保护跳闸之用。(判断题)',
options: [
{ label: '正确', value: 'A' },
{ label: '错误', value: 'B' }
],
answer: 'A'
},
//
{
type: 4,
title:
'只有发生在短路事故时或者在负荷电流较大时,变流器中才会有足够的二次电流作为继电保护跳闸之用。(单选题)',
img: '/static/images/题目-bg.png',
options: [
{ label: '变流器供给操作电源', value: 'A' },
{ label: '交流电压供给操作电源', value: 'B' },
{ label: '直流操作电源', value: 'C' },
{ label: '选项4', value: 'D' }
],
answer: 'A'
},
{
id: 5
},
{
id: 6
},
{
id: 6
},
{
id: 6
},
{
id: 6
},
{
id: 6
},
{
id: 6
},
{
id: 6
},
{
id: 6
},
{
id: 6
},
{
id: 6
},
{
id: 6
},
{
id: 6
},
{
id: 6
},
{
id: 6
}
]
questionList: [],
// -
questionListSelect: []
}
},
onLoad(opt) {
opt = JSON.parse(opt.params)
this.practiceId = opt.practiceId
this.recordId = opt.recordId
this.isNew = opt.isNew
this.isOutOfOrder = opt.isOutOfOrder
this.isError = opt.isError
console.log('🚀 ~ onLoad ~ opt:', opt)
},
mounted() {
//
this.startTimer()
this.getPracticeItData()
this.getPracticeQuestion()
},
unmounted() {
//
clearInterval()
},
methods: {
// -
async getPracticeItData() {
const params = {
practiceId: this.practiceId,
recordId: this.recordId,
isNew: this.isNew
}
const res = await getPracticeItData(params)
this.trueNum = res.data.trueNum
this.falseNum = res.data.falseNum
this.allNum = res.data.allNum
console.log('🚀 ~ getPracticeItData ~ res:', res)
},
//
async getPracticeQuestion() {
this.questionList = []
const params = {
practiceId: this.practiceId,
recordId: this.recordId,
isNew: this.isNew,
isOutOfOrder: this.isOutOfOrder
}
const res = await getPracticeQuestion(params)
// this.questionList = res.data
this.questionList.push(res.data)
console.log('🚀 ~ getPracticeQuestion ~ res:', res)
console.log('🚀 ~ getPracticeQuestion ~ this.questionList:', this.questionList)
},
//
async handleJump(item, index) {
this.currentIndex = index
this.questionList = []
const params = {
recordId: this.recordId,
operate: item || '',
sort: index + 1 || ''
}
const res = await changeQuestion(params)
this.questionList.push(res.data)
console.log('🚀 ~ handleJump ~ res:', res)
},
// -
async getPracticeQuestionList() {
const params = {
id: this.practiceId
}
const res = await getPracticeQuestionList(params)
console.log('🚀 ~ getPracticeQuestionList ~ res:', res)
},
// -
startTimer() {
setInterval(() => {
@ -329,44 +305,54 @@ export default {
},
clickImg() {
uni.previewImage({
urls: [this.questionList[this.currentIndex].img]
urls: [this.questionList[0].img]
})
},
//
handleOption(option, index) {
console.log(option, index)
console.log(option, index, this.questionList[0])
//
if (this.questionList[this.currentIndex].isSelect) {
if (this.questionList[0].isSelect) {
return
} else {
//
this.questionList[this.currentIndex].isSelect = true
this.questionList[0].isSelect = true
//
if (option.value === this.questionList[this.currentIndex].answer) {
if (option.optionIdent === this.questionList[0].correctGrade) {
//
this.questionList[this.currentIndex].select = option.value
this.questionList[0].select = option.optionIdent
//
this.questionList[this.currentIndex].isCorrect = true
this.questionList[0].isCorrect = true
// -
this.questionList[this.currentIndex].options[index].isCorrect = true
this.questionList[0].listOption[index].isCorrect = true
// +1
this.correctNum++
// this.trueNum++
} else {
//
this.questionList[this.currentIndex].select = option.value
this.questionList[0].select = option.optionIdent
//
this.questionList[this.currentIndex].isError = true
this.questionList[0].isError = true
// -
this.questionList[this.currentIndex].options[index].isError = true
this.questionList[0].listOption[index].isError = true
//
this.questionList[this.currentIndex].options.forEach(item => {
if (item.value === this.questionList[this.currentIndex].answer) {
this.questionList[0].listOption.forEach(item => {
if (item.optionIdent === this.questionList[0].correctGrade) {
item.isCorrect = true
}
})
// +1
this.errorNum++
// this.falseNum++
}
const params = {
practiceId: this.practiceId,
recordId: this.recordId,
questionId: this.questionList[0].questionId,
selectAnswer: option.optionIdent,
isTrue: option.optionIdent == this.questionList[0].correctGrade ? 1 : 0
}
console.log('🚀 ~ handleOption ~ params:', params)
//
insertPracticeAnswerById(params)
}
},
//
@ -374,53 +360,50 @@ export default {
console.log('🚀 ~ handleCheckbox ~ option, index:', option, index)
//
if (!option.isCheck) {
this.questionList[this.currentIndex].options[index].isCheck = !option.isCheck
this.questionList[0].listOption[index].isCheck = !option.isCheck
} else {
this.questionList[this.currentIndex].options[index].isCheck = false
this.questionList[0].listOption[index].isCheck = false
}
// isCheck: true value select
this.questionList[this.currentIndex].select = this.questionList[this.currentIndex].options
this.questionList[0].select = this.questionList[0].listOption
.filter(item => item.isCheck)
.map(item => item.value)
console.log(
'🚀 ~ handleCheckbox ~ this.questionList[this.currentIndex].select:',
this.questionList[this.currentIndex].select
)
.map(item => item.optionIdent)
console.log('🚀 ~ handleCheckbox ~ this.questionList[0].select:', this.questionList[0].select)
},
handleOk() {
//
if (this.questionList[this.currentIndex].isSelect) {
if (this.questionList[0].isSelect) {
return
} else {
//
this.questionList[this.currentIndex].isSelect = true
const select = this.questionList[this.currentIndex].select
const answer = this.questionList[this.currentIndex].answer
this.questionList[0].isSelect = true
const select = this.questionList[0].select
const correctGrade = this.questionList[0].correctGrade
//
const isCorrect = select.sort().toString() === answer.sort().toString()
const isCorrect = select.sort().toString() === correctGrade.sort().toString()
if (isCorrect) {
// +1
this.correctNum++
// this.trueNum++
//
this.questionList[this.currentIndex].options.forEach(item => {
this.questionList[0].listOption.forEach(item => {
if (item.isCheck) {
item.isCorrect = true
}
})
//
this.questionList[this.currentIndex].options.forEach(item => {
if (answer.includes(item.value)) {
this.questionList[0].listOption.forEach(item => {
if (correctGrade.includes(item.value)) {
item.isCorrect = true
}
})
} else {
// +1
this.errorNum++
// this.falseNum++
//
this.questionList[this.currentIndex].isError = true
this.questionList[0].isError = true
//
this.questionList[this.currentIndex].options.forEach(item => {
if (answer.includes(item.value)) {
this.questionList[0].listOption.forEach(item => {
if (correctGrade.includes(item.value)) {
item.isCorrect = true
} else if (item.isCheck) {
item.isError = true
@ -430,9 +413,20 @@ export default {
}
},
//
handleSubmit() {
async handleSubmit() {
console.log('提交')
this.showModal = true
const params = {
id: this.practiceId
}
const res = await getPracticeQuestionRate(params)
// trueRate
this.correctRate = res.data.trueRate
// allQuestionNum
this.answerNum = res.data.allQuestionNum
// trueQuestionNum
this.trueNum = res.data.trueQuestionNum
console.log('🚀 ~ handleSubmit ~ res:', res)
},
handleConfirm() {
console.log('确认')
@ -440,12 +434,29 @@ export default {
},
//
handleClose() {
//
clearInterval()
console.log('结束')
//
savePracticeDuration({
id: this.practiceId,
practiceDuration: Math.ceil(this.usedTime.split(':')[0] * 60 + this.usedTime.split(':')[1] / 60)
})
if (this.isError) {
//
updateRemoveRecordData({
practiceId: this.practiceId
})
}
this.showModal = false
uni.navigateBack()
},
//
openSelect() {
async openSelect() {
this.showModalSelect = true
const res = await this.getPracticeQuestionList()
console.log('🚀 ~ openSelect ~ res:', res)
this.questionListSelect = res.data
}
}
}

View File

@ -22,7 +22,7 @@
<div class="bt-wrapper">
<div class="score">完成率{{ item.completionRate }}</div>
<div class="btn-wrapper">
<div class="btn" @click="handleExercise(item.id)">开始练习</div>
<div class="btn" @click="handleExercise(item)">开始练习</div>
<div class="btn" @click="handleError(item)">错题消除({{ item.missNum }})</div>
</div>
</div>
@ -68,7 +68,7 @@ export default {
// alreadyNum
this.waitList = res.data.filter(item => item.alreadyNum === 0)
this.alreadyList = res.data.filter(item => item.alreadyNum > 0)
console.log('🚀 ~ getList ~ res:', res)
// console.log('🚀 ~ getList ~ res:', res)
},
handleTab(item, index) {
this.activeIndex = index
@ -81,9 +81,13 @@ export default {
}
},
//
handleExercise(id) {
handleExercise(item) {
const params = {
practiceId: item.id,
title: item.name,
}
uni.navigateTo({
url: '/pages/YNEduApp/prac/pracDetail?id=' + id
url: '/pages/YNEduApp/prac/pracDetail?params=' + JSON.stringify(params)
})
uni.removeStorageSync('from')
uni.setStorageSync('from', '/pages/YNEduApp/prac/prac')
@ -95,8 +99,15 @@ export default {
},
//
handleError(item) {
const params = {
practiceId: item.id,
recordId: item.recordId,
isNew: 0,
isOutOfOrder: 1,
isError: true
}
uni.navigateTo({
url: '/pages/YNEduApp/prac/exercises?id=' + item.id
url: '/pages/YNEduApp/prac/exercises?params=' + JSON.stringify(params)
})
}
}

View File

@ -31,13 +31,53 @@
</div>
</div>
<div class="right">
<div class="right-top" @click="handleExercises(1)">
<div class="right-top">
<div class="right-text">顺序练习</div>
<u-icon class="top-icon" name="/static/images/顺序练习.png" width="84" height="73" />
<!-- <u-icon class="top-icon" name="/static/images/顺序练习.png" width="84" height="73" /> -->
<div class="btn">
<u-button
type="primary"
plain
shape="circle"
text="继续上次练习"
size="small"
@click="handleExercises(1)"
></u-button>
</div>
<div class="right-bottom" @click="handleExercises(2)">
<div class="btn">
<u-button
type="primary"
plain
shape="circle"
text="开始新的练习"
size="small"
@click="handleExercises(2)"
></u-button>
</div>
</div>
<div class="right-bottom">
<div class="right-text">随机练习</div>
<u-icon class="bottom-icon" name="/static/images/随机练习.png" width="84" height="73" />
<!-- <u-icon class="bottom-icon" name="/static/images/随机练习.png" width="84" height="73" /> -->
<div class="btn">
<u-button
type="primary"
plain
shape="circle"
text="继续上次练习"
size="small"
@click="handleExercises(3)"
></u-button>
</div>
<div class="btn">
<u-button
type="primary"
plain
shape="circle"
text="开始新的练习"
size="small"
@click="handleExercises(4)"
></u-button>
</div>
</div>
</div>
</div>
@ -50,28 +90,72 @@
</template>
<script>
import { getPracticeQuestionRate } from '@/api/eduApp'
export default {
data() {
return {
practiceId: '', // id
recordId: '', // id
//
avatar: 'https://cdn.uviewui.com/uview/album/1.jpg',
avatar: '/static/images/user.png',
//
name: '张三',
//
title: '送配电线路架设(初级)',
title: '',
//
correctRate: '80%',
correctRate: '',
//
totalAnswer: 100,
totalAnswer: 0,
//
totalCorrect: 80
totalCorrect: 0
}
},
onLoad(opt) {
opt = JSON.parse(opt.params)
console.log('🚀 ~ onLoad ~ opt:', opt)
this.practiceId = opt.practiceId
this.title = opt.title
},
mounted() {
this.getData()
},
methods: {
async getData() {
const params = {
id: this.practiceId
}
const res = await getPracticeQuestionRate(params)
this.title = res.data.name
this.correctRate = res.data.trueRate
this.totalAnswer = res.data.allQuestionNum
this.totalCorrect = res.data.trueQuestionNum
this.recordId = res.data.recordId
console.log('🚀 ~ getData ~ res:', res)
},
handleExercises(type) {
console.log('type', type)
const params = {
practiceId: this.practiceId,
recordId: this.recordId,
isError: false
}
if (type === 1) {
params.isOutOfOrder = 0
params.isNew = 0
} else if (type === 2) {
params.isOutOfOrder = 0
params.isNew = 1
} else if (type === 3) {
params.isOutOfOrder = 1
params.isNew = 0
} else if (type === 4) {
params.isOutOfOrder = 1
params.isNew = 1
}
console.log('params', params)
uni.navigateTo({
url: `/pages/YNEduApp/prac/exercises?type=${type}`
url: `/pages/YNEduApp/prac/exercises?params=${JSON.stringify(params)}`
})
},
leftClick() {
@ -154,9 +238,16 @@ export default {
flex-direction: column;
justify-content: space-between;
.btn {
width: 60%;
margin: 5px auto;
}
.right-top {
height: 98px;
background: #e7ac67;
// background: #e7ac67;
background: url('/static/images/顺序练习.png') no-repeat;
background-size: 100% 98px;
border-radius: 8px;
position: relative;
// top-icon -

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB