4 files modified
13 files added
| New file |
| | |
| | | /* |
| | | * @Author: Morpheus |
| | | * @Date: 2021-05-09 15:17:44 |
| | | * @Last Modified by: Morpheus |
| | | * @Last Modified time: 2021-12-24 11:26:04 |
| | | */ |
| | | // 校区 |
| | | import request from '@/common/axios' |
| | | |
| | | export const enterExam = (params) => { |
| | | return request({ |
| | | url: '/simulateExamRecord/beginExam', |
| | | method: 'POST', |
| | | data: params |
| | | }) |
| | | } |
| New file |
| | |
| | | import store from '@/store/index.js'; //需要引入store |
| | | |
| | | // Text页面对考题列表questionList数据预处理 |
| | | const unique = (arr) => { |
| | | return Array.from(new Set(arr)); |
| | | } |
| | | |
| | | export const ModifyQuesList = function(quesModules) { |
| | | // store.state.questionList = [] |
| | | let questionList = [] |
| | | |
| | | let queTypeArr = [] |
| | | |
| | | quesModules.forEach((item, index) => { |
| | | |
| | | let quesType = item.choicesType |
| | | |
| | | queTypeArr.push(quesType) |
| | | |
| | | item.template = item.choicesType |
| | | |
| | | item.tempAnswer = "" |
| | | |
| | | item.options = item.examSubjectOptions |
| | | |
| | | item.options.forEach(it => { |
| | | it.newOptLetter = it.optionName |
| | | it.optContent = it.optionContent |
| | | it.optLetter = it.newOptLetter |
| | | }) |
| | | |
| | | questionList.push(item) |
| | | |
| | | }) |
| | | |
| | | store.state.queTypeArr = unique(queTypeArr) |
| | | |
| | | store.state.questionList = questionList |
| | | |
| | | } |
| | | |
| | | export const topicOptions = (options) => { |
| | | |
| | | var questionList = store.state.questionList |
| | | |
| | | questionList.forEach((item, index) => { |
| | | |
| | | }) |
| | | |
| | | store.state.questionList = questionList |
| | | |
| | | // for (let j = 0; j < quesModules[i].examSubjectOptions.length; j++) { |
| | | // // 解决theoryExamAnswer可能为null的问题,把它赋值为字符串 |
| | | // quesModules[i].examSubjectOptions[j].tempAnswer = "" //暂存每题的答案 |
| | | // quesModules[i].examSubjectOptions[j].template = quesModules[i].choicesType //防止template初始值是null |
| | | // quesModules[i].examSubjectOptions[j].recordId = store.state.examDetail |
| | | // .id //搬移recordId的位置 |
| | | // quesModules[i].examSubjectOptions[j].blankArr = [] //新建blankArr属性,临时保存填空题答案 |
| | | // quesModules[i].examSubjectOptions[j].dualChooseArr = [] //新建blankArr属性,临时保存填空题答案 |
| | | // questionList.push(quesModules[i].examSubjectOptions[j]) |
| | | // } |
| | | } |
| New file |
| | |
| | | /** |
| | | * 全站http配置 |
| | | * |
| | | * axios参数说明 |
| | | * isSerialize是否开启form表单提交 |
| | | * isToken是否需要token |
| | | */ |
| | | import axios from "axios"; |
| | | |
| | | const service = axios.create({ |
| | | baseURL: "http://192.168.0.198:81", //正常接口 |
| | | timeout: 600000, // request timeout |
| | | }); |
| | | |
| | | // 返回其他状态码 |
| | | service.defaults.validateStatus = function (status) { |
| | | return status >= 200 && status <= 500; |
| | | }; |
| | | |
| | | // 跨域请求,允许保存cookie |
| | | service.defaults.withCredentials = true; |
| | | |
| | | // http request拦截 |
| | | service.interceptors.request.use( |
| | | (config) => { |
| | | return config; |
| | | }, |
| | | (error) => { |
| | | return Promise.reject(error); |
| | | } |
| | | ); |
| | | |
| | | // http response 拦截 |
| | | service.interceptors.response.use( |
| | | (res) => { |
| | | return res; |
| | | }, |
| | | (error) => { |
| | | return Promise.reject(new Error(error)); |
| | | } |
| | | ); |
| | | |
| | | export default service; |
| New file |
| | |
| | | <template> |
| | | <cover-view class="clock"> |
| | | <cover-view>{{hour}}:</cover-view> |
| | | <cover-view>{{minute}}:</cover-view> |
| | | <cover-view>{{second}}</cover-view> |
| | | </cover-view> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | data(){ |
| | | return { |
| | | count: 0, |
| | | hour:"00", |
| | | minute:"00", |
| | | second:"00", |
| | | // totalCount:0, |
| | | timer:null |
| | | }; |
| | | }, |
| | | computed:{ |
| | | |
| | | }, |
| | | props:{ |
| | | timeOrigin:{ |
| | | type:Number, |
| | | default:0 |
| | | } |
| | | }, |
| | | methods:{ |
| | | end(){ |
| | | this.is_show = false; |
| | | clearInterval(this.timer); |
| | | // this.$emit('clockend',this.totalCount); |
| | | }, |
| | | showNum(num) { |
| | | if (num < 10) { |
| | | return '0' + num |
| | | } |
| | | return num |
| | | }, |
| | | start(){ |
| | | let _this = this; |
| | | // let count = 0; |
| | | _this.timer = setInterval(function(){ |
| | | _this.count++; |
| | | _this.second = _this.showNum(_this.count % 60); |
| | | _this.hour = _this.showNum(parseInt(_this.count / 60 / 60)); |
| | | _this.minute = _this.showNum(parseInt(_this.count / 60) % 60); |
| | | // _this.totalCount = _this.count; |
| | | },1000); |
| | | // this.is_show = true; |
| | | } |
| | | }, |
| | | onLoad() { |
| | | this.count = this.timeOrigin |
| | | // let _this = this; |
| | | // // let count = 0; |
| | | // _this.timer = setInterval(function(){ |
| | | // _this.count++; |
| | | // _this.second = _this.showNum(_this.count % 60); |
| | | // _this.hour = _this.showNum(parseInt(_this.count / 60 / 60)); |
| | | // _this.minute = _this.showNum(parseInt(_this.count / 60) % 60); |
| | | // // _this.totalCount = _this.count; |
| | | // },1000); |
| | | // this.is_show = true; |
| | | }, |
| | | onReady() { |
| | | // this.start() |
| | | |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss"> |
| | | .clock{ |
| | | display: flex; |
| | | } |
| | | </style> |
| New file |
| | |
| | | <template> |
| | | <!-- 此组件用于显示整套试卷· |
| | | 试卷类型包含 |
| | | exam 理论考试 |
| | | paper 模拟考试 知识点练习 --> |
| | | <view> |
| | | <!-- 大标题 --> |
| | | <view class="header" id="header"> |
| | | <!-- <span class="header-button" @click='leave' v-if='!isReviewed && examType=='know' '>暂离</span> --> |
| | | <span v-if="examType=='exam'"> {{examDetail.exam.name}}</span> |
| | | <span v-if="(examType=='paper' )|| (examType=='know') || (examType=='course')"> |
| | | {{examDetail.paper.name}}</span> |
| | | <span class="header-button" @click='handleSubmit(1)' v-if='!isReviewed'>交卷</span> |
| | | <!-- <span class="scoreText" v-else>得分:{{examDetail.score}}</span> --> |
| | | </view> |
| | | <!-- 小标题栏 --> |
| | | <view id="subHeader"> |
| | | <view class="sub-header" v-if='questionList.length>0'> |
| | | <u-tag class="typeTag" :text="answerStatusName" mode="dark" shape="circle" /> |
| | | <view v-if="examDetail.exam.examTime<=0">不限时</view> |
| | | <u-count-down v-if="(!isReviewed)&&(examType=='exam')&& (examDetail.exam.examTime>0)" |
| | | :timestamp="examDetail.exam.examTime*60" :show-days="false" @end="end" @change="change"> |
| | | </u-count-down> |
| | | <clock v-if="(!isReviewed)&&(examType=='paper' || (examType=='course'))" ref="myClock" |
| | | :timeOrigin="parseInt(examDetail.time)"> |
| | | </clock> |
| | | <span v-if="examType=='exam'">第 |
| | | {{currentIndex+1}}/{{examDetail.exam.totalQuestion}} 题</span> |
| | | <span v-if="(examType=='paper' )|| (examType=='know')">第 |
| | | {{currentIndex+1}}/{{examDetail.totalQuestion}} 题</span> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 答题区域 --> |
| | | <swiper class="content" :duration='duration' :current=currentIndex @change='handleSwiperChanged' |
| | | v-if='questionList.length>0' :style="{'height':swiperHeight}"> |
| | | <template v-for='item in questionList'> |
| | | <swiper-item class="content-item"> |
| | | <scroll-view scroll-y :style="{'height':swiperHeight}"> |
| | | <!-- 显示题目的题干 --> |
| | | <view class="content-title"> |
| | | <rich-text :nodes="item.subjectName"></rich-text> |
| | | </view> |
| | | <!-- 以下显示选项 --> |
| | | <!-- type == 0 单选题 --> |
| | | <view class="content-solutions" v-if='item.template == 0'> |
| | | <template v-for='subItem in item.options'> |
| | | <view |
| | | :class="[isReviewed && subItem.optAnswer == 1 ? 'right': '',isReviewed && (item.wrongArr.indexOf(subItem.optLetter) >-1) ? 'wrong': '']" |
| | | class="content-solutions-item" @click='chooseSolution(item,subItem)'> |
| | | <view v-if="(!isReviewed) && (examType=='exam') " |
| | | class="content-solutions-item-single"> |
| | | {{subItem.newOptLetter}} |
| | | </view> |
| | | <view v-else class="content-solutions-item-single">{{subItem.optLetter}}</view> |
| | | <!-- 此处注意optLetter与newOptLetter的区别,newOptLetter是ABCD顺序的,而optLetter乱序的,两者无直接关系 --> |
| | | <view |
| | | :class="item.tempAnswer == subItem.optLetter? 'content-solutions-item-select' : ''" |
| | | class="content-solutions-item-content">{{subItem.optContent}}</view> |
| | | </view> |
| | | </template> |
| | | </view> |
| | | |
| | | <!-- type == 1 多选题 --> |
| | | <view class="content-solutions" v-if='item.template == 1'> |
| | | <template v-for='subItem in item.options'> |
| | | <view |
| | | :class="[isReviewed && subItem.optAnswer == 1 ? 'right': '',isReviewed && (item.wrongArr.indexOf(subItem.optLetter) >-1) ? 'wrong': '']" |
| | | class="content-solutions-item" @click='chooseMutiSolution(item,subItem)'> |
| | | <view v-if="(!isReviewed) && (examType=='exam') " |
| | | class="content-solutions-item-single"> |
| | | {{subItem.newOptLetter}} |
| | | </view> |
| | | <view v-else class="content-solutions-item-single">{{subItem.optLetter}}</view> |
| | | <!-- TODO 是否被选中的条件判断不对 --> |
| | | <view |
| | | :class="item.tempAnswer.indexOf(subItem.optLetter) >-1 ? 'content-solutions-item-select' : ''" |
| | | class="content-solutions-item-content">{{subItem.optContent}} |
| | | </view> |
| | | </view> |
| | | </template> |
| | | </view> |
| | | |
| | | <!-- type == 2 判断题 --> |
| | | <view class="content-solutions" v-if='item.template == 2'> |
| | | <template v-for='subItem in item.options'> |
| | | <view class="content-solutions-judge"> |
| | | <view v-for="(judgeItem,judgeIndex) in judgeArr" |
| | | :class="[item.tempAnswer == judgeItem.value? 'content-solutions-item-select' : '',isReviewed && (item.rightAnswer==judgeItem.name) ? 'right': '',isReviewed && (item.wrongArr ==judgeItem.value) ? 'wrong': '']" |
| | | class="content-solutions-judge-item" |
| | | @click='judgeSolution(item,judgeItem.value)'>{{judgeItem.name}}</view> |
| | | </view> |
| | | </template> |
| | | </view> |
| | | |
| | | <!-- type == 4 填空题 --> |
| | | <view class="content-solutions" v-if='item.template == 4'> |
| | | <template v-if="!isReviewed"> |
| | | <view class="content-solutions-item" v-for='(subItem,subIndex) in item.options' |
| | | :keys="subIndex" |
| | | :class="[isReviewed && item.answerStatus!=4 &&(item.blankString != item.rightAnswer)? 'wrong':'']"> |
| | | <view class="content-solutions-item-single">{{subIndex+1}}</view> |
| | | <input :disabled="isReviewed" type="text" class="content-solutions-blank" |
| | | v-model="item.blankArr[subIndex]" placeholder="请在此处输入答案" /> |
| | | </view> |
| | | </template> |
| | | <template v-else> |
| | | <view class="content-solutions-item"> |
| | | <view class="content-solutions-item-single"></view> |
| | | <!-- TODOvalue的绑定值不对 :value="item.blankArr[subIndex].replace(/"\;/g, '')" --> |
| | | <input :disabled="isReviewed" :value="(item.blankArr).join(',')" type="text" |
| | | class="content-solutions-blank" /> |
| | | </view> |
| | | </template> |
| | | </view> |
| | | <!-- type == 5 简答题 --> |
| | | <view class="content-solutions" v-if='item.template == 5'> |
| | | <textarea v-if="!isReviewed" @input="textInput" :disabled="isReviewed" placeholder="请输入您的答案" |
| | | auto-height /> |
| | | <textarea v-else :disabled="isReviewed" :value="item.tempAnswer.replace(/"\;/g, '')" |
| | | auto-height /> |
| | | </view> |
| | | |
| | | <view class="explain" v-if='isReviewed'> |
| | | <u-tag v-show="item.answerStatus==1" text="未答" type="error" /> |
| | | <u-tag v-show="item.answerStatus==2" text="正确" type="success" /> |
| | | <u-tag v-show="item.answerStatus==3" text="错误" type="error" /> |
| | | <u-tag v-show="item.answerStatus==4" text="未评分" type="warning" /> |
| | | <u-tag v-show="item.answerStatus==5" text="已评分" type="warning" /> |
| | | <u-tag v-show="item.answerStatus==6" text="已答" type="warning" /> |
| | | <view class="explain-title">正确答案:</view> |
| | | <!-- <span class="text">{{item.rightAnswer}}</span> --> |
| | | <u-parse :html="item.rightAnswer"></u-parse> |
| | | <view class="explain-title">试题解析:</view> |
| | | <!-- <view class="explain-content">{{item.queAnalysis | analysisFilter }}</view> --> |
| | | <u-parse :html="item.queAnalysis?item.queAnalysis:'暂无'"></u-parse> |
| | | <view class="noteArea"> |
| | | <view class="noteAreaTitle"> |
| | | <view class="explain-title">我的笔记:</view> |
| | | <view v-if="eidtOrFinishValue=='编辑笔记'" class="funcGroup" @click="editBtnFunc(item)"> |
| | | <u-icon class="funcBtn" name="edit-pen"></u-icon> |
| | | <span>编辑笔记</span> |
| | | </view> |
| | | <view v-else class="funcGroup" @click="finishBtnFunc(item)"> |
| | | <u-icon class="funcBtn" name="edit-pen"></u-icon> |
| | | <span>完成</span> |
| | | </view> |
| | | </view> |
| | | <!-- 只有回答过的题目才能编辑笔记!!! --> |
| | | <text-editor :noteId="item.id" :textContent="item.theoryExamAnswer.queNote" |
| | | :isreadOnly="isreadOnly" @editorInput='updateEditorText'> |
| | | </text-editor> |
| | | </view> |
| | | </view> |
| | | </scroll-view> |
| | | </swiper-item> |
| | | </template> |
| | | </swiper> |
| | | |
| | | <!-- 底部栏 --> |
| | | <view class="footer" id="footer"> |
| | | <view class="footer-back" @click='handleChangeCurrentSwiper(-1)'>上一题</view> |
| | | <view class="footer-card" @click="showQuestion = !showQuestion">答题卡</view> |
| | | <view class="footer-right" @click='handleChangeCurrentSwiper(1)'>下一题</view> |
| | | </view> |
| | | |
| | | <!-- 答题卡弹出层 --> |
| | | <modal v-model="showQuestion"> |
| | | <view class='question-modal' :style="{'height': modalHeight}"> |
| | | <view class="question-modal-header" id="questionHeader"> |
| | | 答题卡 |
| | | </view> |
| | | <scroll-view scroll-y class="question-modal-body" :style="{'height': modalContentHeight}"> |
| | | <template v-for="(subItem,subIndex) in queTypeArr"> |
| | | <view class="queTypeName" v-show="queTypeStore[subIndex]>0">{{subItem.name}}</view> |
| | | <!-- <u-tag :text="subItem.name" v-show="queTypeStore[subIndex]>0" mode="dark" /> --> |
| | | <view class="queTypeArea"> |
| | | |
| | | <template v-for="(item, index) in questionList"> |
| | | <view v-show="item.template == subItem.value"> |
| | | |
| | | <!-- 1.复习状态且回答正确 --> |
| | | <!-- <view v-if='item.tempAnswer && item.answer==item.tempAnswer && isReviewed' --> |
| | | <view v-if='isReviewed && item.answerStatus == "2"' |
| | | class="question-modal-body-item question-modal-body-item-right" |
| | | @click="handleJumpSwiper(index)">{{index + 1 }}</view> |
| | | <!-- 2.复习状态且回答错误 --> |
| | | <view |
| | | v-else-if='isReviewed && (item.answerStatus == "1" ||item.answerStatus == "3" )' |
| | | class="question-modal-body-item question-modal-body-item-failed" |
| | | @click="handleJumpSwiper(index)">{{index + 1 }}</view> |
| | | <!-- 3.复习状态且简答题未评分或者已评分 --> |
| | | <view |
| | | v-else-if='isReviewed && (item.answerStatus == "4" ||item.answerStatus == "5")' |
| | | class="question-modal-body-item question-modal-body-item-unScored" |
| | | @click="handleJumpSwiper(index)">{{index + 1 }}</view> |
| | | <!-- 3.非复习状态且已经作答 --> |
| | | <view v-else-if='!isReviewed && item.tempAnswer && item.tempAnswer.length != 0' |
| | | class="question-modal-body-item question-modal-body-item-select" |
| | | @click="handleJumpSwiper(index)">{{index + 1 }}</view> |
| | | <!-- 4.非复习状态且未作答 --> |
| | | <view v-else class="question-modal-body-item question-modal-body-item-unselect" |
| | | @click="handleJumpSwiper(index)"> |
| | | {{index + 1 }} |
| | | </view> |
| | | <!-- <u-line color="red" border-style="info"></u-line> --> |
| | | </view> |
| | | </template> |
| | | </view> |
| | | </template> |
| | | </scroll-view> |
| | | <view class="question-modal-foot" id="questionHeader"> |
| | | <view v-if="!isReviewed" class="ansBlock"> |
| | | <view class="blockItem"> |
| | | <view class="block-ansed"></view> |
| | | <view class="">已答</view> |
| | | </view> |
| | | <view class="blockItem"> |
| | | <view class="block-unansed"></view> |
| | | <view class="">未答</view> |
| | | </view> |
| | | </view> |
| | | |
| | | <view v-else class="ansBlock"> |
| | | <view class="blockItem"> |
| | | <view class="block-right"></view> |
| | | <view class="">答对</view> |
| | | </view> |
| | | <view class="blockItem"> |
| | | <view class="block-wrong"></view> |
| | | <view class="">答错</view> |
| | | </view> |
| | | <view class="blockItem"> |
| | | <view class="block-unScored"></view> |
| | | <view class="">未评分</view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </modal> |
| | | <u-toast ref="uToast" /> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import Modal from './modal.vue' |
| | | import clock from '@/components/clock/clock.vue'; |
| | | export default { |
| | | data() { |
| | | return { |
| | | isreadOnly: true, |
| | | quesModules: [], |
| | | areaText: ``, //保存简答题答案 |
| | | judgeArr: [{ |
| | | name: '正确', |
| | | value: '1' |
| | | }, |
| | | { |
| | | name: '错误', |
| | | value: '0' |
| | | } |
| | | ], |
| | | queTypeArr: [{ |
| | | name: '单选题', |
| | | value: '1', |
| | | be: false, |
| | | }, |
| | | { |
| | | name: '多选题', |
| | | value: '2', |
| | | be: false, |
| | | }, |
| | | { |
| | | name: '判断题', |
| | | value: '3', |
| | | be: false, |
| | | }, |
| | | { |
| | | name: '填空题', |
| | | value: '4', |
| | | be: false, |
| | | }, |
| | | { |
| | | name: '简答题', |
| | | value: '5', |
| | | be: false, |
| | | } |
| | | ], |
| | | currentIndex: 0, |
| | | swiperHeight: '667px', |
| | | modalHeight: '500px', |
| | | modalContentHeight: '400px', |
| | | showQuestion: false, |
| | | articleEditorValue: '', |
| | | eidtOrFinishValue: '编辑笔记', |
| | | // eidtOrFinish: true, |
| | | editorText: '', |
| | | editor: 'editor', |
| | | } |
| | | }, |
| | | filters: { |
| | | // 判断答案状态 |
| | | analysisFilter(item) { |
| | | if (item == null) { |
| | | return "暂无解析" |
| | | } else { |
| | | return item |
| | | } |
| | | } |
| | | }, |
| | | watch: { |
| | | // 监听currentIndex的变化,改变则提交答案 相同 |
| | | currentIndex(newVal, oldVal) { |
| | | let that = this |
| | | if (!this.isReviewed) { |
| | | // 对各题型的答案进行处理 |
| | | switch (that.questionList[oldVal].template) { |
| | | case 1: |
| | | // 选择题 |
| | | break; |
| | | case 2: |
| | | // 多选题 |
| | | // that.questionList[that.currentIndex].tempAnswer = that.questionList[that.currentIndex] |
| | | // .dualChooseArr.join(',') |
| | | break; |
| | | case 3: |
| | | // 判断题 |
| | | break; |
| | | case 4: |
| | | // 填空题 |
| | | that.questionList[oldVal].tempAnswer = that.questionList[oldVal].blankArr.join( |
| | | '||~||') // 数组拼接为字符串 |
| | | break; |
| | | case 5: |
| | | that.questionList[oldVal].tempAnswer = JSON.stringify(that.areaText) |
| | | // console.log('000:',that.questionList[oldVal].tempAnswer); |
| | | break; |
| | | default: |
| | | } |
| | | |
| | | if (this.examType == 'exam') { |
| | | // 保存答案 |
| | | var answerObj = { |
| | | examRecordId: this.questionList[oldVal].recordId, |
| | | paperQueId: this.questionList[oldVal].id, |
| | | answer: this.questionList[oldVal].tempAnswer, |
| | | template: this.questionList[oldVal].template |
| | | } |
| | | |
| | | // 进行答题的api请求 |
| | | console.log('answerObj:', oldVal, answerObj); |
| | | this.$api.answerExam(answerObj) |
| | | .then(res => { |
| | | console.log(res); |
| | | }) |
| | | } else if (this.examType == 'paper' || this.examType == 'know') { |
| | | var answerObj = { |
| | | exerciseId: this.examDetail.exerciseId, |
| | | paperQueId: this.questionList[oldVal].id, |
| | | answer: this.questionList[oldVal].tempAnswer, |
| | | template: this.questionList[oldVal].template |
| | | } |
| | | |
| | | // 进行答题的api请求 |
| | | console.log('answerObj:', oldVal, answerObj); |
| | | this.$api.answerPaper(answerObj) |
| | | .then(res => { |
| | | console.log(res); |
| | | }) |
| | | } else { |
| | | return |
| | | } |
| | | // immediate: true, |
| | | } |
| | | } |
| | | }, |
| | | computed: { |
| | | // swiperHeight(){ |
| | | // uni.getSystemInfo({ |
| | | // success(res) { |
| | | // console.log(res); |
| | | // return res.windowHeight+'px' |
| | | // } |
| | | // }) |
| | | // }, |
| | | examDetail() { |
| | | return this.$store.state.examDetail |
| | | }, |
| | | questionList() { |
| | | console.log(this.$store.state.questionList, 77777) |
| | | return |
| | | this.$store.state.questionList |
| | | }, |
| | | queTypeStore() { |
| | | return this.$store.state.queTypeArr |
| | | }, |
| | | max() { |
| | | return this.questionList.length - 1 |
| | | }, |
| | | answerStatusName() { |
| | | switch (this.questionList[this.currentIndex].template) { |
| | | case 1: |
| | | return '单选题' |
| | | break; |
| | | case 2: |
| | | return '多选题' |
| | | break; |
| | | case 3: |
| | | return '判断题' |
| | | break; |
| | | case 4: |
| | | return '填空题' |
| | | break; |
| | | case 5: |
| | | return '简答题' |
| | | break; |
| | | default: |
| | | return '考试题' |
| | | } |
| | | } |
| | | }, |
| | | props: { |
| | | isReviewed: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | examType: { |
| | | type: String, |
| | | default: "exam" |
| | | }, |
| | | duration: { |
| | | type: [String, Number], |
| | | default: 300 |
| | | }, |
| | | }, |
| | | mounted() { |
| | | var that = this |
| | | this.setAnswerHeight() |
| | | if ((!this.isReviewed) && ((this.examType == 'paper') || (this.examType == 'course'))) { |
| | | this.$refs.myClock.start(); |
| | | } |
| | | }, |
| | | components: { |
| | | Modal, |
| | | clock |
| | | }, |
| | | methods: { |
| | | /*设置题目的高度*/ |
| | | setAnswerHeight() { |
| | | let that = this |
| | | let tempHeight = 0 |
| | | uni.getSystemInfo({ |
| | | //获取手机屏幕高度信息,让swiper的高度和手机屏幕一样高 |
| | | success: function(res) { |
| | | tempHeight = res.windowHeight; |
| | | that.modalHeight = res.windowHeight - uni.upx2px(200) + 'px'; |
| | | that.modalContentHeight = res.windowHeight - uni.upx2px(380) + 'px'; |
| | | uni.createSelectorQuery().in(that).select("#header").fields({ |
| | | size: true, |
| | | scrollOffset: true |
| | | }, (data) => { |
| | | console.log('data', data); |
| | | tempHeight -= data.height; |
| | | uni.createSelectorQuery().in(that).select("#subHeader").fields({ |
| | | size: true, |
| | | scrollOffset: true |
| | | }, (data) => { |
| | | tempHeight -= data.height; |
| | | uni.createSelectorQuery().in(that).select("#footer").fields({ |
| | | size: true, |
| | | scrollOffset: true |
| | | }, (data) => { |
| | | tempHeight -= data.height; |
| | | that.swiperHeight = tempHeight + 'px'; |
| | | }).exec(); |
| | | }).exec(); |
| | | }).exec(); |
| | | } |
| | | }); |
| | | }, |
| | | /* 跳转指定题目 */ |
| | | handleJumpSwiper(index) { |
| | | this.currentIndex = index |
| | | this.showQuestion = false |
| | | }, |
| | | change(timestamp) { |
| | | // var that = this |
| | | if (timestamp == 30) { |
| | | this.$refs.uToast.show({ |
| | | title: '考试只剩余30s,请注意时间', |
| | | type: 'warning', |
| | | duration: 2000, |
| | | position: 'top' |
| | | }) |
| | | } |
| | | // this.$forceUpdate() |
| | | }, |
| | | end() { |
| | | this.$refs.uToast.show({ |
| | | title: '考试时间结束,已自动交卷', |
| | | type: 'warning' |
| | | }) |
| | | setTimeout(() => { |
| | | this.handleSubmit(0) |
| | | }, 2000) |
| | | }, |
| | | textInput(e) { |
| | | this.areaText = e.detail.value |
| | | // console.log(e.detail.value) |
| | | }, |
| | | /* 滑动题目 */ |
| | | handleSwiperChanged(event) { |
| | | this.currentIndex = event.detail.current |
| | | }, |
| | | /* 调用上一页,下一页 */ |
| | | handleChangeCurrentSwiper(operation) { |
| | | let max = this.questionList.length - 1 |
| | | let min = 0 |
| | | // 进行翻页 |
| | | if ((this.currentIndex > min && operation < 0) || (this.currentIndex < max && operation > 0)) { |
| | | this.currentIndex += operation |
| | | // console.log(this.currentIndex) |
| | | } |
| | | }, |
| | | /* 选择答案(单选)*/ |
| | | chooseSolution(item, subItem) { |
| | | if (!this.isReviewed) { |
| | | // tempAnswer为学生答案 |
| | | item.tempAnswer = subItem.optLetter |
| | | // 强制刷新更新视图 |
| | | this.$forceUpdate() |
| | | // this.questionList[this.currentIndex].tempAnswer = subItem.optLetter |
| | | if (this.currentIndex < this.max) { |
| | | setTimeout(() => { |
| | | this.currentIndex += 1 |
| | | }, 300) |
| | | } |
| | | // this.onAnswerChange(item) |
| | | } |
| | | }, |
| | | /* 选择答案(多选)*/ |
| | | chooseMutiSolution(item, subItem) { |
| | | if (!this.isReviewed) { |
| | | let answerIndex = item.dualChooseArr.indexOf(subItem.optLetter) |
| | | if (answerIndex > -1) { |
| | | // 该选项已经在数组中了 |
| | | item.dualChooseArr.splice(answerIndex, 1) |
| | | } else { |
| | | // 该选项不在数组中 |
| | | item.dualChooseArr.push(subItem.optLetter) |
| | | } |
| | | item.tempAnswer = item.dualChooseArr.join(',') |
| | | // this.onAnswerChange(answerIndex) |
| | | // 强制刷新更新视图 |
| | | this.$forceUpdate() |
| | | } |
| | | }, |
| | | /* 判断题答案 */ |
| | | judgeSolution(item, value) { |
| | | if (!this.isReviewed) { |
| | | // tempAnswer为学生答案 |
| | | item.tempAnswer = value |
| | | // 强制刷新更新视图 |
| | | this.$forceUpdate() |
| | | if (this.currentIndex < this.max) { |
| | | setTimeout(() => { |
| | | this.currentIndex += 1 |
| | | }, 300) |
| | | } |
| | | // this.onAnswerChange(item) |
| | | } |
| | | }, |
| | | |
| | | /* 题目答案变化 */ |
| | | onAnswerChange(item) { |
| | | let result = JSON.parse(JSON.stringify(item)) |
| | | this.$emit('onChange', item) |
| | | }, |
| | | /* 交卷 相同 */ |
| | | handleSubmit(submitORimeEnd) { |
| | | /*submitORimeEnd == 1,submit |
| | | submitORimeEnd == 0,stimeEnd*/ |
| | | if (this.currentIndex == 0) { |
| | | this.currentIndex++ |
| | | } else { |
| | | this.currentIndex = 0 |
| | | } |
| | | if (submitORimeEnd) { |
| | | // this.$emit('submit', this.questionList) |
| | | this.$emit('submit') |
| | | } else { |
| | | this.$emit('timeEnd') |
| | | } |
| | | }, |
| | | |
| | | // 点击编辑笔记 |
| | | editBtnFunc(item) { |
| | | if (item.theoryExamAnswer.id == undefined) { |
| | | this.$refs.uToast.show({ |
| | | title: '未作答的题目不可编辑笔记!', |
| | | type: 'error', |
| | | // url: '/pages/user/index' |
| | | }) |
| | | return |
| | | } |
| | | this.isreadOnly = !this.isreadOnly |
| | | this.eidtOrFinishValue = '完成' |
| | | }, |
| | | // 完成编辑 |
| | | finishBtnFunc(item) { |
| | | var that = this |
| | | this.isreadOnly = !this.isreadOnly |
| | | this.eidtOrFinishValue = '编辑笔记' |
| | | console.log('保存笔记内容', item, that.editorText); |
| | | this.$api.examNote(item.theoryExamAnswer.id, that.editorText) |
| | | .then(res => { |
| | | console.log('更新笔记成功', res) |
| | | }) |
| | | }, |
| | | updateEditorText(text) { |
| | | // 从子组件获取输入框输入内容 |
| | | this.editorText = text |
| | | }, |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss"> |
| | | page { |
| | | background-color: #FFFFFF; |
| | | } |
| | | |
| | | #header, |
| | | #subHeader { |
| | | height: 100rpx; |
| | | } |
| | | |
| | | .header { |
| | | width: 750rpx; |
| | | // position: fixed; |
| | | margin-top: 30rpx; |
| | | position: relative; |
| | | text-align: center; |
| | | line-height: 100rpx; |
| | | font-size: 36rpx; |
| | | font-weight: 600; |
| | | color: #103289; |
| | | letter-spacing: 10rpx; |
| | | background-color: #FFFFFF; |
| | | |
| | | &-button { |
| | | width: 80rpx; |
| | | height: 40rpx; |
| | | line-height: 40rpx; |
| | | position: absolute; |
| | | top: 20rpx; |
| | | right: 40rpx; |
| | | padding: 10rpx 20rpx; |
| | | border-radius: 15rpx; |
| | | letter-spacing: 2rpx; |
| | | font-weight: 500; |
| | | color: #FFFFFF; |
| | | background-color: #103289; |
| | | } |
| | | |
| | | .scoreText { |
| | | color: #00b060; |
| | | font-size: 35rpx; |
| | | } |
| | | } |
| | | |
| | | .sub-header { |
| | | width: 750rpx; |
| | | // position: fixed; |
| | | // margin-top: 130rpx; |
| | | padding: 30rpx 20rpx; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | color: #000; |
| | | font-size: 33rpx; |
| | | font-weight: bold; |
| | | background-color: #FFFFFF; |
| | | } |
| | | |
| | | .content { |
| | | // margin-top: 130rpx; |
| | | letter-spacing: 3rpx; |
| | | |
| | | .typeTag { |
| | | margin-right: 20rpx; |
| | | } |
| | | |
| | | &-item-explain { |
| | | padding-bottom: 20rpx; |
| | | font-size: 30rpx; |
| | | color: #8799a3; |
| | | letter-spacing: 5rpx; |
| | | border-top: 1px solid rgba(0, 0, 0, 0.1); |
| | | |
| | | &-result { |
| | | padding: 20rpx 0; |
| | | |
| | | span { |
| | | padding-left: 20rpx; |
| | | color: #39b54a; |
| | | } |
| | | } |
| | | |
| | | &-content { |
| | | padding: 20rpx 0; |
| | | } |
| | | } |
| | | |
| | | &-item { |
| | | padding: 0 20rpx; |
| | | box-sizing: border-box; |
| | | } |
| | | |
| | | &-title { |
| | | margin-bottom: 30rpx; |
| | | font-size: 32rpx; |
| | | line-height: 55rpx; |
| | | color: #000 |
| | | } |
| | | |
| | | &-solutions { |
| | | width: 100%; |
| | | padding-bottom: 20rpx; |
| | | |
| | | &-item { |
| | | margin: 40rpx 0; |
| | | border: 5rpx solid #103289; |
| | | border-radius: 20rpx; |
| | | display: flex; |
| | | align-items: center; |
| | | font-size: 30rpx; |
| | | background-color: #103289; |
| | | |
| | | &-check-content { |
| | | padding: 35rpx 20rpx; |
| | | width: 100%; |
| | | border-radius: 15rpx; |
| | | color: #103289; |
| | | background-color: #FFFFFF; |
| | | } |
| | | |
| | | &-single { |
| | | width: 80rpx; |
| | | text-align: center; |
| | | color: #FFFFFF; |
| | | } |
| | | |
| | | &-content { |
| | | padding: 35rpx 20rpx; |
| | | width: 630rpx; |
| | | border-top-right-radius: 15rpx; |
| | | border-bottom-right-radius: 15rpx; |
| | | color: #000; |
| | | background-color: #FFFFFF; |
| | | } |
| | | |
| | | &-select { |
| | | color: #FFFFFF; |
| | | background-color: #103289; |
| | | } |
| | | } |
| | | |
| | | &-judge { |
| | | display: flex; |
| | | justify-content: space-around; |
| | | background-color: #FFFFFF; |
| | | padding: 20rpx; |
| | | text-align: center; |
| | | font-size: 30rpx; |
| | | |
| | | .content-solutions-judge-item { |
| | | border: 5rpx solid #103289; |
| | | border-radius: 60rpx; |
| | | width: 300rpx; |
| | | padding: 35rpx 20rpx; // 控制单元格的高度 |
| | | } |
| | | |
| | | .content-solutions-judge-select { |
| | | color: #FFFFFF; |
| | | background-color: #103289; |
| | | } |
| | | |
| | | } |
| | | |
| | | &-blank { |
| | | // border: 5rpx solid #103289; |
| | | height: 60rpx; |
| | | width: 90%; |
| | | // border-radius: 20rpx; |
| | | background-color: #FFFFFF; |
| | | padding: 20rpx; |
| | | } |
| | | |
| | | &-fillItem { |
| | | border: 5rpx solid #103289; |
| | | border-radius: 20rpx; |
| | | background-color: #FFFFFF; |
| | | padding: 20rpx; |
| | | } |
| | | } |
| | | |
| | | .explain { |
| | | border-top: solid #999999 1px; |
| | | padding-top: 10rpx; |
| | | font-size: 28rpx; |
| | | color: #666666; |
| | | |
| | | .explainResult { |
| | | color: #103289; |
| | | } |
| | | |
| | | .explain-title { |
| | | font-weight: bold; |
| | | } |
| | | |
| | | .noteArea { |
| | | border-top: 2rpx solid #103289; |
| | | padding-top: 10rpx; |
| | | |
| | | // background-color: #0077AA; |
| | | .noteAreaTitle { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .footer { |
| | | width: 750rpx; |
| | | height: 100rpx; |
| | | padding: 30rpx 20rpx; |
| | | position: fixed; |
| | | bottom: 0; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | font-size: 30rpx; |
| | | box-sizing: border-box; |
| | | color: #4c8af3; |
| | | box-shadow: 0 0 5px 1px #eee; |
| | | background-color: #FFFFFF; |
| | | |
| | | &-card { |
| | | padding: 10rpx 20rpx; |
| | | border: 1px solid #103289; |
| | | border-radius: 15rpx; |
| | | color: #FFFFFF; |
| | | background-color: #103289; |
| | | } |
| | | } |
| | | |
| | | .question-modal { |
| | | width: 700rpx; |
| | | padding: 40rpx; |
| | | background-color: #FFFFFF; |
| | | |
| | | &-header { |
| | | height: 80rpx; |
| | | line-height: 80rpx; |
| | | text-align: center; |
| | | font-size: 35rpx; |
| | | color: #333333; |
| | | border-bottom: 1rpx solid #F0F0F0; |
| | | } |
| | | |
| | | &-body { |
| | | |
| | | // margin-bottom: 100rpx; |
| | | .queTypeName { |
| | | font-size: 32rpx; |
| | | font-weight: bold; |
| | | |
| | | } |
| | | |
| | | .queTypeArea { |
| | | display: flex; |
| | | flex-direction: row; |
| | | flex-wrap: wrap; |
| | | margin-bottom: 20rpx; |
| | | |
| | | .question-modal-body-item { |
| | | width: 80rpx; |
| | | height: 80rpx; |
| | | margin: 10rpx 22rpx; |
| | | line-height: 80rpx; |
| | | font-size: 35rpx; |
| | | text-align: center; |
| | | border-radius: 50%; |
| | | color: #ffffff; |
| | | // background-color: #0077AA; |
| | | } |
| | | } |
| | | |
| | | &-item-unselect { |
| | | // color: #FFFFFF; |
| | | background-color: #bbbbbb; |
| | | } |
| | | |
| | | &-item-select { |
| | | // color: #FFFFFF; |
| | | background-color: #103289; |
| | | } |
| | | |
| | | &-item-failed { |
| | | color: #FFFFFF; |
| | | background-color: #982121; |
| | | } |
| | | |
| | | &-item-right { |
| | | color: #FFFFFF; |
| | | background-color: #39b54a; |
| | | } |
| | | |
| | | &-item-unScored { |
| | | color: #FFFFFF; |
| | | background-color: #ff9f73; |
| | | } |
| | | } |
| | | |
| | | .question-modal-foot { |
| | | height: 100rpx; |
| | | border-top: 1rpx solid #F0F0F0; |
| | | // position: fixed; |
| | | // margin-bottom: 0rpx; |
| | | margin-top: -60rpx; |
| | | |
| | | .ansBlock { |
| | | display: flex; |
| | | justify-content: center; |
| | | |
| | | // align-items: center; |
| | | .blockItem { |
| | | display: flex; |
| | | align-items: center; |
| | | margin: 20rpx; |
| | | } |
| | | |
| | | .block-ansed { |
| | | width: 80rpx; |
| | | height: 80rpx; |
| | | border-radius: 50%; |
| | | background: #103289; |
| | | margin: 0 10rpx; |
| | | } |
| | | |
| | | .block-unansed { |
| | | width: 80rpx; |
| | | height: 80rpx; |
| | | border-radius: 50%; |
| | | // border: solid #ffffff 1px; |
| | | background: #bbbbbb; |
| | | margin: 0 10rpx; |
| | | } |
| | | |
| | | .block-right { |
| | | width: 80rpx; |
| | | height: 80rpx; |
| | | border-radius: 50%; |
| | | background: #39b54a; |
| | | margin: 0 10rpx; |
| | | } |
| | | |
| | | .block-wrong { |
| | | width: 80rpx; |
| | | height: 80rpx; |
| | | border-radius: 50%; |
| | | background: #982121; |
| | | margin: 0 10rpx; |
| | | } |
| | | |
| | | .block-unScored { |
| | | width: 80rpx; |
| | | height: 80rpx; |
| | | border-radius: 50%; |
| | | background: #ff9f73; |
| | | margin: 0 10rpx; |
| | | } |
| | | } |
| | | |
| | | } |
| | | } |
| | | |
| | | .right { |
| | | border: 8rpx solid #39b54a; |
| | | } |
| | | |
| | | .wrong { |
| | | border: 8rpx solid #d81717; |
| | | } |
| | | </style> |
| New file |
| | |
| | | <template> |
| | | <!-- 此组件用于显示整套试卷· |
| | | 试卷类型包含 |
| | | exam 理论考试 |
| | | paper 模拟考试 知识点练习 --> |
| | | <view> |
| | | <!-- 大标题 --> |
| | | <view class="header" id="header"> |
| | | <!-- <span class="header-button" @click='leave' v-if='!isReviewed && examType=='know' '>暂离</span> --> |
| | | <span v-if="examType=='exam'"> {{examDetail.exam.name}}</span> |
| | | <span v-if="(examType=='paper' )|| (examType=='know') || (examType=='course')"> |
| | | {{examDetail.paper.name}}</span> |
| | | <span class="header-button" @click='handleSubmit(1)' v-if='!isReviewed'>交卷</span> |
| | | <!-- <span class="scoreText" v-else>得分:{{examDetail.score}}</span> --> |
| | | </view> |
| | | <!-- 小标题栏 --> |
| | | <view id="subHeader"> |
| | | <view class="sub-header" v-if='questionList.length > 0'> |
| | | <u-tag class="typeTag" :text="answerStatusName" mode="dark" shape="circle" /> |
| | | <view v-if="examDetail.exam.examTime<=0">不限时</view> |
| | | <u-count-down v-if="(!isReviewed)&&(examType=='exam')&& (examDetail.exam.examTime>0)" |
| | | :timestamp="examDetail.exam.examTime / 1000" :show-days="false" @end="end" @change="change"> |
| | | </u-count-down> |
| | | <clock v-if="(!isReviewed)&&(examType=='paper' || (examType=='course'))" ref="myClock" |
| | | :timeOrigin="parseInt(examDetail.time)"> |
| | | </clock> |
| | | <span v-if="examType=='exam'">第 |
| | | {{currentIndex+1}}/{{examDetail.exam.totalQuestion}} 题</span> |
| | | <span v-if="(examType=='paper' )|| (examType=='know')">第 |
| | | {{currentIndex+1}}/{{examDetail.totalQuestion}} 题</span> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 答题区域 --> |
| | | <swiper class="content" :duration='duration' :current=currentIndex @change='handleSwiperChanged' |
| | | v-if='questionList.length > 0' :style="{'height':swiperHeight}"> |
| | | <template v-for='item in questionList'> |
| | | <swiper-item class="content-item"> |
| | | <scroll-view scroll-y :style="{'height':swiperHeight}"> |
| | | <!-- 显示题目的题干 --> |
| | | <view class="content-title"> |
| | | <rich-text :nodes="item.subjectName"></rich-text> |
| | | </view> |
| | | <!-- 以下显示选项 --> |
| | | <!-- type == 0 单选题 --> |
| | | <view class="content-solutions" v-if='item.template == 0'> |
| | | <template v-for='subItem in item.options'> |
| | | <view |
| | | :class="[isReviewed && subItem.optAnswer == 1 ? 'right': '',isReviewed && (item.wrongArr.indexOf(subItem.optLetter) >-1) ? 'wrong': '']" |
| | | class="content-solutions-item" @click='chooseSolution(item,subItem)'> |
| | | <view v-if="(!isReviewed) && (examType=='exam') " |
| | | class="content-solutions-item-single"> |
| | | {{subItem.newOptLetter}} |
| | | </view> |
| | | <view v-else class="content-solutions-item-single">{{subItem.optLetter}}</view> |
| | | <!-- 此处注意optLetter与newOptLetter的区别,newOptLetter是ABCD顺序的,而optLetter乱序的,两者无直接关系 --> |
| | | <view |
| | | :class="item.tempAnswer == subItem.optLetter? 'content-solutions-item-select' : ''" |
| | | class="content-solutions-item-content">{{subItem.optContent}}</view> |
| | | </view> |
| | | </template> |
| | | </view> |
| | | |
| | | <!-- type == 1 多选题 --> |
| | | <view class="content-solutions" v-if='item.template == 1'> |
| | | <template v-for='subItem in item.options'> |
| | | <view |
| | | :class="[isReviewed && subItem.optAnswer == 1 ? 'right': '',isReviewed && (item.wrongArr.indexOf(subItem.optLetter) >-1) ? 'wrong': '']" |
| | | class="content-solutions-item" @click='chooseMutiSolution(item,subItem)'> |
| | | <view v-if="(!isReviewed) && (examType=='exam') " |
| | | class="content-solutions-item-single"> |
| | | {{subItem.newOptLetter}} |
| | | </view> |
| | | <view v-else class="content-solutions-item-single">{{subItem.optLetter}}</view> |
| | | <!-- TODO 是否被选中的条件判断不对 --> |
| | | <view |
| | | :class="item.tempAnswer.indexOf(subItem.optLetter) >-1 ? 'content-solutions-item-select' : ''" |
| | | class="content-solutions-item-content">{{subItem.optContent}} |
| | | </view> |
| | | </view> |
| | | </template> |
| | | </view> |
| | | |
| | | <!-- type == 2 判断题 --> |
| | | <view class="content-solutions" v-if='item.template == 2'> |
| | | <template v-for='subItem in item.options'> |
| | | <view class="content-solutions-judge"> |
| | | <view v-for="(judgeItem,judgeIndex) in judgeArr" |
| | | :class="[item.tempAnswer == judgeItem.value? 'content-solutions-item-select' : '',isReviewed && (item.rightAnswer==judgeItem.name) ? 'right': '',isReviewed && (item.wrongArr ==judgeItem.value) ? 'wrong': '']" |
| | | class="content-solutions-judge-item" |
| | | @click='judgeSolution(item,judgeItem.value)'>{{judgeItem.name}}</view> |
| | | </view> |
| | | </template> |
| | | </view> |
| | | |
| | | <!-- type == 4 填空题 --> |
| | | <view class="content-solutions" v-if='item.template == 4'> |
| | | <template v-if="!isReviewed"> |
| | | <view class="content-solutions-item" v-for='(subItem,subIndex) in item.options' |
| | | :keys="subIndex" |
| | | :class="[isReviewed && item.answerStatus!=4 &&(item.blankString != item.rightAnswer)? 'wrong':'']"> |
| | | <view class="content-solutions-item-single">{{subIndex+1}}</view> |
| | | <input :disabled="isReviewed" type="text" class="content-solutions-blank" |
| | | v-model="item.blankArr[subIndex]" placeholder="请在此处输入答案" /> |
| | | </view> |
| | | </template> |
| | | <template v-else> |
| | | <view class="content-solutions-item"> |
| | | <view class="content-solutions-item-single"></view> |
| | | <!-- TODOvalue的绑定值不对 :value="item.blankArr[subIndex].replace(/"\;/g, '')" --> |
| | | <input :disabled="isReviewed" :value="(item.blankArr).join(',')" type="text" |
| | | class="content-solutions-blank" /> |
| | | </view> |
| | | </template> |
| | | </view> |
| | | <!-- type == 5 简答题 --> |
| | | <view class="content-solutions" v-if='item.template == 5'> |
| | | <textarea v-if="!isReviewed" @input="textInput" :disabled="isReviewed" placeholder="请输入您的答案" |
| | | auto-height /> |
| | | <textarea v-else :disabled="isReviewed" :value="item.tempAnswer.replace(/"\;/g, '')" |
| | | auto-height /> |
| | | </view> |
| | | |
| | | <view class="explain" v-if='isReviewed'> |
| | | <u-tag v-show="item.answerStatus==1" text="未答" type="error" /> |
| | | <u-tag v-show="item.answerStatus==2" text="正确" type="success" /> |
| | | <u-tag v-show="item.answerStatus==3" text="错误" type="error" /> |
| | | <u-tag v-show="item.answerStatus==4" text="未评分" type="warning" /> |
| | | <u-tag v-show="item.answerStatus==5" text="已评分" type="warning" /> |
| | | <u-tag v-show="item.answerStatus==6" text="已答" type="warning" /> |
| | | <view class="explain-title">正确答案:</view> |
| | | <!-- <span class="text">{{item.rightAnswer}}</span> --> |
| | | <u-parse :html="item.rightAnswer"></u-parse> |
| | | <view class="explain-title">试题解析:</view> |
| | | <!-- <view class="explain-content">{{item.queAnalysis | analysisFilter }}</view> --> |
| | | <u-parse :html="item.queAnalysis?item.queAnalysis:'暂无'"></u-parse> |
| | | <view class="noteArea"> |
| | | <view class="noteAreaTitle"> |
| | | <view class="explain-title">我的笔记:</view> |
| | | <view v-if="eidtOrFinishValue=='编辑笔记'" class="funcGroup" @click="editBtnFunc(item)"> |
| | | <u-icon class="funcBtn" name="edit-pen"></u-icon> |
| | | <span>编辑笔记</span> |
| | | </view> |
| | | <view v-else class="funcGroup" @click="finishBtnFunc(item)"> |
| | | <u-icon class="funcBtn" name="edit-pen"></u-icon> |
| | | <span>完成</span> |
| | | </view> |
| | | </view> |
| | | <!-- 只有回答过的题目才能编辑笔记!!! --> |
| | | <text-editor :noteId="item.id" :textContent="item.theoryExamAnswer.queNote" |
| | | :isreadOnly="isreadOnly" @editorInput='updateEditorText'> |
| | | </text-editor> |
| | | </view> |
| | | </view> |
| | | </scroll-view> |
| | | </swiper-item> |
| | | </template> |
| | | </swiper> |
| | | |
| | | <!-- 底部栏 --> |
| | | <view class="footer" id="footer"> |
| | | <view class="footer-back" @click='handleChangeCurrentSwiper(-1)'>上一题</view> |
| | | <view class="footer-card" @click="showQuestion = !showQuestion">答题卡</view> |
| | | <view class="footer-right" @click='handleChangeCurrentSwiper(1)'>下一题</view> |
| | | </view> |
| | | |
| | | <!-- 答题卡弹出层 --> |
| | | <modal v-model="showQuestion"> |
| | | <view class='question-modal' :style="{'height': modalHeight}"> |
| | | <view class="question-modal-header" id="questionHeader"> |
| | | 答题卡 |
| | | </view> |
| | | <scroll-view scroll-y class="question-modal-body" :style="{'height': modalContentHeight}"> |
| | | <template v-for="(subItem,subIndex) in queTypeArr"> |
| | | <view class="queTypeName" v-show="queTypeStore[subIndex]>=0">{{subItem.name}}</view> |
| | | <!-- <u-tag :text="subItem.name" v-show="queTypeStore[subIndex]>0" mode="dark" /> --> |
| | | <view class="queTypeArea"> |
| | | |
| | | <template v-for="(item, index) in questionList"> |
| | | <view v-show="item.template == subItem.value"> |
| | | |
| | | <!-- 1.复习状态且回答正确 --> |
| | | <!-- <view v-if='item.tempAnswer && item.answer==item.tempAnswer && isReviewed' --> |
| | | <view v-if='isReviewed && item.answerStatus == "2"' |
| | | class="question-modal-body-item question-modal-body-item-right" |
| | | @click="handleJumpSwiper(index)">{{index + 1 }}</view> |
| | | <!-- 2.复习状态且回答错误 --> |
| | | <view |
| | | v-else-if='isReviewed && (item.answerStatus == "1" ||item.answerStatus == "3" )' |
| | | class="question-modal-body-item question-modal-body-item-failed" |
| | | @click="handleJumpSwiper(index)">{{index + 1 }}</view> |
| | | <!-- 3.复习状态且简答题未评分或者已评分 --> |
| | | <view |
| | | v-else-if='isReviewed && (item.answerStatus == "4" ||item.answerStatus == "5")' |
| | | class="question-modal-body-item question-modal-body-item-unScored" |
| | | @click="handleJumpSwiper(index)">{{index + 1 }}</view> |
| | | <!-- 3.非复习状态且已经作答 --> |
| | | <view v-else-if='!isReviewed && item.tempAnswer && item.tempAnswer.length != 0' |
| | | class="question-modal-body-item question-modal-body-item-select" |
| | | @click="handleJumpSwiper(index)">{{index + 1 }}</view> |
| | | <!-- 4.非复习状态且未作答 --> |
| | | <view v-else class="question-modal-body-item question-modal-body-item-unselect" |
| | | @click="handleJumpSwiper(index)"> |
| | | {{index + 1 }} |
| | | </view> |
| | | <!-- <u-line color="red" border-style="info"></u-line> --> |
| | | </view> |
| | | </template> |
| | | </view> |
| | | </template> |
| | | </scroll-view> |
| | | <view class="question-modal-foot" id="questionHeader"> |
| | | <view v-if="!isReviewed" class="ansBlock"> |
| | | <view class="blockItem"> |
| | | <view class="block-ansed"></view> |
| | | <view class="">已答</view> |
| | | </view> |
| | | <view class="blockItem"> |
| | | <view class="block-unansed"></view> |
| | | <view class="">未答</view> |
| | | </view> |
| | | </view> |
| | | |
| | | <view v-else class="ansBlock"> |
| | | <view class="blockItem"> |
| | | <view class="block-right"></view> |
| | | <view class="">答对</view> |
| | | </view> |
| | | <view class="blockItem"> |
| | | <view class="block-wrong"></view> |
| | | <view class="">答错</view> |
| | | </view> |
| | | <view class="blockItem"> |
| | | <view class="block-unScored"></view> |
| | | <view class="">未评分</view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </modal> |
| | | <u-toast ref="uToast" /> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import Modal from './modal.vue' |
| | | import clock from '@/components/clock/clock.vue'; |
| | | export default { |
| | | data() { |
| | | return { |
| | | isreadOnly: true, |
| | | quesModules: [], |
| | | areaText: ``, //保存简答题答案 |
| | | judgeArr: [{ |
| | | name: '正确', |
| | | value: '1' |
| | | }, |
| | | { |
| | | name: '错误', |
| | | value: '0' |
| | | } |
| | | ], |
| | | queTypeArr: [{ |
| | | name: '单选题', |
| | | value: '0', |
| | | be: false, |
| | | }, |
| | | { |
| | | name: '多选题', |
| | | value: '1', |
| | | be: false, |
| | | }, |
| | | { |
| | | name: '判断题', |
| | | value: '2', |
| | | be: false, |
| | | }, |
| | | { |
| | | name: '填空题', |
| | | value: '4', |
| | | be: false, |
| | | }, |
| | | { |
| | | name: '简答题', |
| | | value: '5', |
| | | be: false, |
| | | } |
| | | ], |
| | | currentIndex: 0, |
| | | swiperHeight: '667px', |
| | | modalHeight: '500px', |
| | | modalContentHeight: '400px', |
| | | showQuestion: false, |
| | | articleEditorValue: '', |
| | | eidtOrFinishValue: '编辑笔记', |
| | | // eidtOrFinish: true, |
| | | editorText: '', |
| | | editor: 'editor', |
| | | } |
| | | }, |
| | | filters: { |
| | | // 判断答案状态 |
| | | analysisFilter(item) { |
| | | if (item == null) { |
| | | return "暂无解析" |
| | | } else { |
| | | return item |
| | | } |
| | | } |
| | | }, |
| | | watch: { |
| | | // 监听currentIndex的变化,改变则提交答案 相同 |
| | | currentIndex(newVal, oldVal) { |
| | | let that = this |
| | | if (!this.isReviewed) { |
| | | // 对各题型的答案进行处理 |
| | | switch (that.questionList[oldVal].template) { |
| | | case 0: |
| | | // 选择题 |
| | | break; |
| | | case 1: |
| | | // 多选题 |
| | | // that.questionList[that.currentIndex].tempAnswer = that.questionList[that.currentIndex] |
| | | // .dualChooseArr.join(',') |
| | | break; |
| | | case 2: |
| | | // 判断题 |
| | | break; |
| | | case 4: |
| | | // 填空题 |
| | | that.questionList[oldVal].tempAnswer = that.questionList[oldVal].blankArr.join( |
| | | '||~||') // 数组拼接为字符串 |
| | | break; |
| | | case 5: |
| | | that.questionList[oldVal].tempAnswer = JSON.stringify(that.areaText) |
| | | // console.log('000:',that.questionList[oldVal].tempAnswer); |
| | | break; |
| | | default: |
| | | } |
| | | |
| | | if (this.examType == 'exam') { |
| | | // 保存答案 |
| | | var answerObj = { |
| | | examRecordId: this.questionList[oldVal].recordId, |
| | | paperQueId: this.questionList[oldVal].id, |
| | | answer: this.questionList[oldVal].tempAnswer, |
| | | template: this.questionList[oldVal].template |
| | | } |
| | | |
| | | // 进行答题的api请求 |
| | | console.log('answerObj:', oldVal, answerObj); |
| | | this.$api.answerExam(answerObj) |
| | | .then(res => { |
| | | console.log(res); |
| | | }) |
| | | } else if (this.examType == 'paper' || this.examType == 'know') { |
| | | var answerObj = { |
| | | exerciseId: this.examDetail.exerciseId, |
| | | paperQueId: this.questionList[oldVal].id, |
| | | answer: this.questionList[oldVal].tempAnswer, |
| | | template: this.questionList[oldVal].template |
| | | } |
| | | |
| | | // 进行答题的api请求 |
| | | console.log('answerObj:', oldVal, answerObj); |
| | | this.$api.answerPaper(answerObj) |
| | | .then(res => { |
| | | console.log(res); |
| | | }) |
| | | } else { |
| | | return |
| | | } |
| | | // immediate: true, |
| | | } |
| | | } |
| | | }, |
| | | computed: { |
| | | // swiperHeight(){ |
| | | // uni.getSystemInfo({ |
| | | // success(res) { |
| | | // console.log(res); |
| | | // return res.windowHeight+'px' |
| | | // } |
| | | // }) |
| | | // }, |
| | | examDetail() { |
| | | return this.$store.state.examDetail |
| | | }, |
| | | questionList() { |
| | | console.log(this.$store.state.questionList, 77777) |
| | | return this.$store.state.questionList |
| | | }, |
| | | queTypeStore() { |
| | | return this.$store.state.queTypeArr |
| | | }, |
| | | max() { |
| | | return this.questionList.length - 1 |
| | | }, |
| | | answerStatusName() { |
| | | console.log(this.questionList[this.currentIndex].template, 63636636366) |
| | | switch (this.questionList[this.currentIndex].template) { |
| | | case 0: |
| | | return '单选题' |
| | | break; |
| | | case 1: |
| | | return '多选题' |
| | | break; |
| | | case 2: |
| | | return '判断题' |
| | | break; |
| | | case 4: |
| | | return '填空题' |
| | | break; |
| | | case 5: |
| | | return '简答题' |
| | | break; |
| | | default: |
| | | return '考试题' |
| | | } |
| | | } |
| | | }, |
| | | props: { |
| | | isReviewed: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | examType: { |
| | | type: String, |
| | | default: "exam" |
| | | }, |
| | | duration: { |
| | | type: [String, Number], |
| | | default: 300 |
| | | }, |
| | | }, |
| | | mounted() { |
| | | var that = this |
| | | this.setAnswerHeight() |
| | | if ((!this.isReviewed) && ((this.examType == 'paper') || (this.examType == 'course'))) { |
| | | this.$refs.myClock.start(); |
| | | } |
| | | }, |
| | | components: { |
| | | Modal, |
| | | clock |
| | | }, |
| | | methods: { |
| | | /*设置题目的高度*/ |
| | | setAnswerHeight() { |
| | | let that = this |
| | | let tempHeight = 0 |
| | | uni.getSystemInfo({ |
| | | //获取手机屏幕高度信息,让swiper的高度和手机屏幕一样高 |
| | | success: function(res) { |
| | | console.log(res, '010101010') |
| | | tempHeight = res.windowHeight; |
| | | that.modalHeight = res.windowHeight - uni.upx2px(200) + 'px'; |
| | | that.modalContentHeight = res.windowHeight - uni.upx2px(380) + 'px'; |
| | | uni.createSelectorQuery().in(that).select("#header").fields({ |
| | | size: true, |
| | | scrollOffset: true |
| | | }, (data) => { |
| | | console.log('data', data); |
| | | tempHeight -= data.height; |
| | | uni.createSelectorQuery().in(that).select("#subHeader").fields({ |
| | | size: true, |
| | | scrollOffset: true |
| | | }, (data) => { |
| | | tempHeight -= data.height; |
| | | uni.createSelectorQuery().in(that).select("#footer").fields({ |
| | | size: true, |
| | | scrollOffset: true |
| | | }, (data) => { |
| | | tempHeight -= data.height; |
| | | that.swiperHeight = tempHeight + 'px'; |
| | | }).exec(); |
| | | }).exec(); |
| | | }).exec(); |
| | | } |
| | | }); |
| | | }, |
| | | /* 跳转指定题目 */ |
| | | handleJumpSwiper(index) { |
| | | this.currentIndex = index |
| | | this.showQuestion = false |
| | | }, |
| | | change(timestamp) { |
| | | // var that = this |
| | | if (timestamp == 30) { |
| | | this.$refs.uToast.show({ |
| | | title: '考试只剩余30s,请注意时间', |
| | | type: 'warning', |
| | | duration: 2000, |
| | | position: 'top' |
| | | }) |
| | | } |
| | | // this.$forceUpdate() |
| | | }, |
| | | end() { |
| | | this.$refs.uToast.show({ |
| | | title: '考试时间结束,已自动交卷', |
| | | type: 'warning' |
| | | }) |
| | | setTimeout(() => { |
| | | this.handleSubmit(0) |
| | | }, 2000) |
| | | }, |
| | | textInput(e) { |
| | | this.areaText = e.detail.value |
| | | // console.log(e.detail.value) |
| | | }, |
| | | /* 滑动题目 */ |
| | | handleSwiperChanged(event) { |
| | | this.currentIndex = event.detail.current |
| | | }, |
| | | /* 调用上一页,下一页 */ |
| | | handleChangeCurrentSwiper(operation) { |
| | | let max = this.questionList.length - 1 |
| | | let min = 0 |
| | | // 进行翻页 |
| | | if ((this.currentIndex > min && operation < 0) || (this.currentIndex < max && operation > 0)) { |
| | | this.currentIndex += operation |
| | | // console.log(this.currentIndex) |
| | | } |
| | | }, |
| | | /* 选择答案(单选)*/ |
| | | chooseSolution(item, subItem) { |
| | | if (!this.isReviewed) { |
| | | // tempAnswer为学生答案 |
| | | item.tempAnswer = subItem.optLetter |
| | | // 强制刷新更新视图 |
| | | this.$forceUpdate() |
| | | // this.questionList[this.currentIndex].tempAnswer = subItem.optLetter |
| | | if (this.currentIndex < this.max) { |
| | | setTimeout(() => { |
| | | this.currentIndex += 1 |
| | | }, 300) |
| | | } |
| | | // this.onAnswerChange(item) |
| | | } |
| | | }, |
| | | /* 选择答案(多选)*/ |
| | | chooseMutiSolution(item, subItem) { |
| | | if (!this.isReviewed) { |
| | | let answerIndex = item.dualChooseArr.indexOf(subItem.optLetter) |
| | | if (answerIndex > -1) { |
| | | // 该选项已经在数组中了 |
| | | item.dualChooseArr.splice(answerIndex, 1) |
| | | } else { |
| | | // 该选项不在数组中 |
| | | item.dualChooseArr.push(subItem.optLetter) |
| | | } |
| | | item.tempAnswer = item.dualChooseArr.join(',') |
| | | // this.onAnswerChange(answerIndex) |
| | | // 强制刷新更新视图 |
| | | this.$forceUpdate() |
| | | } |
| | | }, |
| | | /* 判断题答案 */ |
| | | judgeSolution(item, value) { |
| | | if (!this.isReviewed) { |
| | | // tempAnswer为学生答案 |
| | | item.tempAnswer = value |
| | | // 强制刷新更新视图 |
| | | this.$forceUpdate() |
| | | if (this.currentIndex < this.max) { |
| | | setTimeout(() => { |
| | | this.currentIndex += 1 |
| | | }, 300) |
| | | } |
| | | // this.onAnswerChange(item) |
| | | } |
| | | }, |
| | | |
| | | /* 题目答案变化 */ |
| | | onAnswerChange(item) { |
| | | let result = JSON.parse(JSON.stringify(item)) |
| | | this.$emit('onChange', item) |
| | | }, |
| | | /* 交卷 相同 */ |
| | | handleSubmit(submitORimeEnd) { |
| | | /*submitORimeEnd == 1,submit |
| | | submitORimeEnd == 0,stimeEnd*/ |
| | | if (this.currentIndex == 0) { |
| | | this.currentIndex++ |
| | | } else { |
| | | this.currentIndex = 0 |
| | | } |
| | | if (submitORimeEnd) { |
| | | // this.$emit('submit', this.questionList) |
| | | this.$emit('submit') |
| | | } else { |
| | | this.$emit('timeEnd') |
| | | } |
| | | }, |
| | | |
| | | // 点击编辑笔记 |
| | | editBtnFunc(item) { |
| | | if (item.theoryExamAnswer.id == undefined) { |
| | | this.$refs.uToast.show({ |
| | | title: '未作答的题目不可编辑笔记!', |
| | | type: 'error', |
| | | // url: '/pages/user/index' |
| | | }) |
| | | return |
| | | } |
| | | this.isreadOnly = !this.isreadOnly |
| | | this.eidtOrFinishValue = '完成' |
| | | }, |
| | | // 完成编辑 |
| | | finishBtnFunc(item) { |
| | | var that = this |
| | | this.isreadOnly = !this.isreadOnly |
| | | this.eidtOrFinishValue = '编辑笔记' |
| | | console.log('保存笔记内容', item, that.editorText); |
| | | this.$api.examNote(item.theoryExamAnswer.id, that.editorText) |
| | | .then(res => { |
| | | console.log('更新笔记成功', res) |
| | | }) |
| | | }, |
| | | updateEditorText(text) { |
| | | // 从子组件获取输入框输入内容 |
| | | this.editorText = text |
| | | }, |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss"> |
| | | page { |
| | | background-color: #FFFFFF; |
| | | } |
| | | |
| | | #header, |
| | | #subHeader { |
| | | height: 100rpx; |
| | | } |
| | | |
| | | .header { |
| | | width: 750rpx; |
| | | // position: fixed; |
| | | margin-top: 30rpx; |
| | | position: relative; |
| | | text-align: center; |
| | | line-height: 100rpx; |
| | | font-size: 36rpx; |
| | | font-weight: 600; |
| | | color: #103289; |
| | | letter-spacing: 10rpx; |
| | | background-color: #FFFFFF; |
| | | |
| | | &-button { |
| | | width: 80rpx; |
| | | height: 40rpx; |
| | | line-height: 40rpx; |
| | | position: absolute; |
| | | top: 20rpx; |
| | | right: 40rpx; |
| | | padding: 10rpx 20rpx; |
| | | border-radius: 15rpx; |
| | | letter-spacing: 2rpx; |
| | | font-weight: 500; |
| | | color: #FFFFFF; |
| | | background-color: #103289; |
| | | } |
| | | |
| | | .scoreText { |
| | | color: #00b060; |
| | | font-size: 35rpx; |
| | | } |
| | | } |
| | | |
| | | .sub-header { |
| | | width: 750rpx; |
| | | // position: fixed; |
| | | // margin-top: 130rpx; |
| | | padding: 30rpx 20rpx; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | color: #000; |
| | | font-size: 33rpx; |
| | | font-weight: bold; |
| | | background-color: #FFFFFF; |
| | | } |
| | | |
| | | .content { |
| | | // margin-top: 130rpx; |
| | | letter-spacing: 3rpx; |
| | | |
| | | .typeTag { |
| | | margin-right: 20rpx; |
| | | } |
| | | |
| | | &-item-explain { |
| | | padding-bottom: 20rpx; |
| | | font-size: 30rpx; |
| | | color: #8799a3; |
| | | letter-spacing: 5rpx; |
| | | border-top: 1px solid rgba(0, 0, 0, 0.1); |
| | | |
| | | &-result { |
| | | padding: 20rpx 0; |
| | | |
| | | span { |
| | | padding-left: 20rpx; |
| | | color: #39b54a; |
| | | } |
| | | } |
| | | |
| | | &-content { |
| | | padding: 20rpx 0; |
| | | } |
| | | } |
| | | |
| | | &-item { |
| | | padding: 0 20rpx; |
| | | box-sizing: border-box; |
| | | } |
| | | |
| | | &-title { |
| | | margin-bottom: 30rpx; |
| | | font-size: 32rpx; |
| | | line-height: 55rpx; |
| | | color: #000 |
| | | } |
| | | |
| | | &-solutions { |
| | | width: 100%; |
| | | padding-bottom: 20rpx; |
| | | |
| | | &-item { |
| | | margin: 40rpx 0; |
| | | border: 5rpx solid #103289; |
| | | border-radius: 20rpx; |
| | | display: flex; |
| | | align-items: center; |
| | | font-size: 30rpx; |
| | | background-color: #103289; |
| | | |
| | | &-check-content { |
| | | padding: 35rpx 20rpx; |
| | | width: 100%; |
| | | border-radius: 15rpx; |
| | | color: #103289; |
| | | background-color: #FFFFFF; |
| | | } |
| | | |
| | | &-single { |
| | | width: 80rpx; |
| | | text-align: center; |
| | | color: #FFFFFF; |
| | | } |
| | | |
| | | &-content { |
| | | padding: 35rpx 20rpx; |
| | | width: 630rpx; |
| | | border-top-right-radius: 15rpx; |
| | | border-bottom-right-radius: 15rpx; |
| | | color: #000; |
| | | background-color: #FFFFFF; |
| | | } |
| | | |
| | | &-select { |
| | | color: #FFFFFF; |
| | | background-color: #103289; |
| | | } |
| | | } |
| | | |
| | | &-judge { |
| | | display: flex; |
| | | justify-content: space-around; |
| | | background-color: #FFFFFF; |
| | | padding: 20rpx; |
| | | text-align: center; |
| | | font-size: 30rpx; |
| | | |
| | | .content-solutions-judge-item { |
| | | border: 5rpx solid #103289; |
| | | border-radius: 60rpx; |
| | | width: 300rpx; |
| | | padding: 35rpx 20rpx; // 控制单元格的高度 |
| | | } |
| | | |
| | | .content-solutions-judge-select { |
| | | color: #FFFFFF; |
| | | background-color: #103289; |
| | | } |
| | | |
| | | } |
| | | |
| | | &-blank { |
| | | // border: 5rpx solid #103289; |
| | | height: 60rpx; |
| | | width: 90%; |
| | | // border-radius: 20rpx; |
| | | background-color: #FFFFFF; |
| | | padding: 20rpx; |
| | | } |
| | | |
| | | &-fillItem { |
| | | border: 5rpx solid #103289; |
| | | border-radius: 20rpx; |
| | | background-color: #FFFFFF; |
| | | padding: 20rpx; |
| | | } |
| | | } |
| | | |
| | | .explain { |
| | | border-top: solid #999999 1px; |
| | | padding-top: 10rpx; |
| | | font-size: 28rpx; |
| | | color: #666666; |
| | | |
| | | .explainResult { |
| | | color: #103289; |
| | | } |
| | | |
| | | .explain-title { |
| | | font-weight: bold; |
| | | } |
| | | |
| | | .noteArea { |
| | | border-top: 2rpx solid #103289; |
| | | padding-top: 10rpx; |
| | | |
| | | // background-color: #0077AA; |
| | | .noteAreaTitle { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .footer { |
| | | width: 750rpx; |
| | | height: 100rpx; |
| | | padding: 30rpx 20rpx; |
| | | position: fixed; |
| | | bottom: 0; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | font-size: 30rpx; |
| | | box-sizing: border-box; |
| | | color: #4c8af3; |
| | | box-shadow: 0 0 5px 1px #eee; |
| | | background-color: #FFFFFF; |
| | | |
| | | &-card { |
| | | padding: 10rpx 20rpx; |
| | | border: 1px solid #103289; |
| | | border-radius: 15rpx; |
| | | color: #FFFFFF; |
| | | background-color: #103289; |
| | | } |
| | | } |
| | | |
| | | .question-modal { |
| | | width: 700rpx; |
| | | padding: 40rpx; |
| | | background-color: #FFFFFF; |
| | | |
| | | &-header { |
| | | height: 80rpx; |
| | | line-height: 80rpx; |
| | | text-align: center; |
| | | font-size: 35rpx; |
| | | color: #333333; |
| | | border-bottom: 1rpx solid #F0F0F0; |
| | | } |
| | | |
| | | &-body { |
| | | |
| | | // margin-bottom: 100rpx; |
| | | .queTypeName { |
| | | font-size: 32rpx; |
| | | font-weight: bold; |
| | | |
| | | } |
| | | |
| | | .queTypeArea { |
| | | display: flex; |
| | | flex-direction: row; |
| | | flex-wrap: wrap; |
| | | margin-bottom: 20rpx; |
| | | |
| | | .question-modal-body-item { |
| | | width: 80rpx; |
| | | height: 80rpx; |
| | | margin: 10rpx 22rpx; |
| | | line-height: 80rpx; |
| | | font-size: 35rpx; |
| | | text-align: center; |
| | | border-radius: 50%; |
| | | color: #ffffff; |
| | | // background-color: #0077AA; |
| | | } |
| | | } |
| | | |
| | | &-item-unselect { |
| | | // color: #FFFFFF; |
| | | background-color: #bbbbbb; |
| | | } |
| | | |
| | | &-item-select { |
| | | // color: #FFFFFF; |
| | | background-color: #103289; |
| | | } |
| | | |
| | | &-item-failed { |
| | | color: #FFFFFF; |
| | | background-color: #982121; |
| | | } |
| | | |
| | | &-item-right { |
| | | color: #FFFFFF; |
| | | background-color: #39b54a; |
| | | } |
| | | |
| | | &-item-unScored { |
| | | color: #FFFFFF; |
| | | background-color: #ff9f73; |
| | | } |
| | | } |
| | | |
| | | .question-modal-foot { |
| | | height: 100rpx; |
| | | border-top: 1rpx solid #F0F0F0; |
| | | // position: fixed; |
| | | // margin-bottom: 0rpx; |
| | | margin-top: -60rpx; |
| | | |
| | | .ansBlock { |
| | | display: flex; |
| | | justify-content: center; |
| | | |
| | | // align-items: center; |
| | | .blockItem { |
| | | display: flex; |
| | | align-items: center; |
| | | margin: 20rpx; |
| | | } |
| | | |
| | | .block-ansed { |
| | | width: 80rpx; |
| | | height: 80rpx; |
| | | border-radius: 50%; |
| | | background: #103289; |
| | | margin: 0 10rpx; |
| | | } |
| | | |
| | | .block-unansed { |
| | | width: 80rpx; |
| | | height: 80rpx; |
| | | border-radius: 50%; |
| | | // border: solid #ffffff 1px; |
| | | background: #bbbbbb; |
| | | margin: 0 10rpx; |
| | | } |
| | | |
| | | .block-right { |
| | | width: 80rpx; |
| | | height: 80rpx; |
| | | border-radius: 50%; |
| | | background: #39b54a; |
| | | margin: 0 10rpx; |
| | | } |
| | | |
| | | .block-wrong { |
| | | width: 80rpx; |
| | | height: 80rpx; |
| | | border-radius: 50%; |
| | | background: #982121; |
| | | margin: 0 10rpx; |
| | | } |
| | | |
| | | .block-unScored { |
| | | width: 80rpx; |
| | | height: 80rpx; |
| | | border-radius: 50%; |
| | | background: #ff9f73; |
| | | margin: 0 10rpx; |
| | | } |
| | | } |
| | | |
| | | } |
| | | } |
| | | |
| | | .right { |
| | | border: 8rpx solid #39b54a; |
| | | } |
| | | |
| | | .wrong { |
| | | border: 8rpx solid #d81717; |
| | | } |
| | | </style> |
| New file |
| | |
| | | <template> |
| | | <!-- 此组件用于题库练习的单题展示 --> |
| | | <view> |
| | | <!-- 大标题 --> |
| | | <view class="header" id="header"> |
| | | <span v-if="type=='store'" > {{storeInfo.storeName}}题库练习</span> |
| | | <span v-if="type=='error'" > {{storeInfo.storeName}}错题练习</span> |
| | | <!-- <span class="header-button" @click='handleSubmit(1)' v-if='!isReviewed'>提交</span> --> |
| | | </view> |
| | | <!-- 小标题栏 --> |
| | | <!-- <view id="subHeader"> |
| | | <view class="sub-header" v-if='questionList.length>0'> |
| | | <clock v-if="(!isReviewed)&&examType=='paper'" ref="myClock" :timeOrigin="parseInt(examDetail.time)"></clock> |
| | | <clock @clockend="clockend" ref="myClock"></clock> |
| | | <u-toast ref="uToast" /> |
| | | <span class='sub-header-number' v-if="(examType=='paper' )|| (examType=='know')">第 |
| | | {{currentIndex+1}}/{{examDetail.totalQuestion}} 题</span> |
| | | </view> |
| | | </view> --> |
| | | |
| | | <!-- 答题区域 --> |
| | | <swiper class="content" :duration='duration' :current=currentIndex @change='handleSwiperChanged' |
| | | v-if='questionList.length>0' :style="{'height':swiperHeight}"> |
| | | <template v-for='item in questionList'> |
| | | <swiper-item class="content-item"> |
| | | <scroll-view scroll-y :style="{'height':swiperHeight}"> |
| | | <!-- 显示题目的题干 --> |
| | | <view class="content-title"> |
| | | <u-tag v-if="item.template == 1" class="typeTag" text="单选题" mode="dark" shape="circle" /> |
| | | <u-tag v-if="item.template == 2" class="typeTag" text="多选题" mode="dark" shape="circle" /> |
| | | <u-tag v-if="item.template == 3" class="typeTag" text="判断题" mode="dark" shape="circle" /> |
| | | <u-tag v-if="item.template == 4" class="typeTag" text="填空题" mode="dark" shape="circle" /> |
| | | <u-tag v-if="item.template == 5" class="typeTag" text="简答题" mode="dark" shape="circle" /> |
| | | <rich-text :nodes="item.queContent"></rich-text> |
| | | </view> |
| | | <!-- 以下显示选项 --> |
| | | <!-- type == 1 单选题 --> |
| | | <view class="content-solutions" v-if='item.template == 1'> |
| | | <template v-for='subItem in item.toptions'> |
| | | <view |
| | | :class="[item.isReviewed && subItem.optAnswer == 1 ? 'right': '',item.isReviewed && (item.wrongArr.indexOf(subItem.optLetter) >-1) ? 'wrong': '']" |
| | | class="content-solutions-item" @click='chooseSolution(item,subItem)'> |
| | | <view class="content-solutions-item-single">{{subItem.optLetter}}</view> |
| | | <view |
| | | :class="item.tempAnswer == subItem.optLetter? 'content-solutions-item-select' : ''" |
| | | class="content-solutions-item-content">{{subItem.optContent}}</view> |
| | | </view> |
| | | </template> |
| | | </view> |
| | | <!-- type == 2 多选题 --> |
| | | <view class="content-solutions" v-if='item.template == 2'> |
| | | <template v-for='subItem in item.toptions'> |
| | | <view |
| | | :class="[item.isReviewed && subItem.optAnswer == 1 ? 'right': '',item.isReviewed && (item.wrongArr.indexOf(subItem.optLetter) >-1) ? 'wrong': '']" |
| | | class="content-solutions-item" @click='chooseMutiSolution(item,subItem)'> |
| | | <view class="content-solutions-item-single">{{subItem.optLetter}}</view> |
| | | <view |
| | | :class="item.tempAnswer.indexOf(subItem.optLetter) >-1 ? 'content-solutions-item-select' : ''" |
| | | class="content-solutions-item-content">{{subItem.optContent}} |
| | | </view> |
| | | </view> |
| | | </template> |
| | | </view> |
| | | |
| | | <!-- type == 3 判断题 --> |
| | | <view class="content-solutions" v-if='item.template == 3'> |
| | | <template v-for='(subItem,subIndex) in item.toptions' :keys="subIndex"> |
| | | <view class="content-solutions-judge"> |
| | | <view v-for="(judgeItem,judgeIndex) in judgeArr" |
| | | :class="[item.tempAnswer == judgeItem.value? 'content-solutions-item-select' : '',item.isReviewed && (item.rightAnswer==judgeItem.name) ? 'right': '',item.isReviewed && (item.wrongArr ==judgeItem.value) ? 'wrong': '']" |
| | | class="content-solutions-judge-item" |
| | | @click='judgeSolution(item,judgeItem.value)'>{{judgeItem.name}}</view> |
| | | </view> |
| | | </template> |
| | | </view> |
| | | |
| | | <!-- type == 4 填空题 --> |
| | | <view class="content-solutions" v-if='item.template == 4'> |
| | | <template> |
| | | <view class="content-solutions-item" v-for='(subItem,subIndex) in item.toptions' |
| | | :keys="subIndex" |
| | | :class="[item.isReviewed && item.blankString != item.rightAnswer ? 'wrong':'']"> |
| | | <view class="content-solutions-item-single">{{subIndex+1}}</view> |
| | | <input :disabled="item.isReviewed" type="text" class="content-solutions-blank" |
| | | v-model="item.blankArr[subIndex]" placeholder="请在此处输入答案" /> |
| | | <!-- TODOvalue的绑定值不对 :value="item.blankArr[subIndex].replace(/"\;/g, '')" --> |
| | | <!-- <input v-else :disabled="isReviewed" :value="item.blankArr" |
| | | type="text" class="content-solutions-blank" /> --> |
| | | </view> |
| | | </template> |
| | | </view> |
| | | <!-- type == 5 简答题 --> |
| | | <view class="content-solutions" v-if='item.template == 5'> |
| | | <textarea v-if="!item.isReviewed" @input="textInput" :disabled="isReviewed" |
| | | placeholder="请输入您的答案" auto-height /> |
| | | <textarea v-else :disabled="item.isReviewed" |
| | | :value="item.tempAnswer.replace(/"\;/g, '')" auto-height /> |
| | | </view> |
| | | <view class="explain" v-if='item.isReviewed'> |
| | | |
| | | <u-tag v-show="item.isRight==1" text="正确" type="success" /> |
| | | <u-tag v-show="item.isRight==2" text="错误" type="error" /> |
| | | <u-tag v-show="item.isRight==3" text="自行核对" type="warning" /> |
| | | |
| | | <view class="explain-title">正确答案:</view> |
| | | <!-- <span class="text">{{item.rightAnswer}}</span> --> |
| | | <u-parse :html="item.rightAnswer"></u-parse> |
| | | <view class="explain-title">试题解析:</view> |
| | | <view class="explain-content"> |
| | | <u-parse :html="item.queAnalysis?item.queAnalysis:'暂无'"></u-parse> |
| | | </view> |
| | | <view class="noteArea"> |
| | | <view class="noteAreaTitle"> |
| | | <view class="explain-title">我的笔记:</view> |
| | | <view v-if="eidtOrFinishValue=='编辑笔记'" class="funcGroup" @click="editBtnFunc(item)"> |
| | | <u-icon class="funcBtn" name="edit-pen"></u-icon> |
| | | <span>编辑笔记</span> |
| | | </view> |
| | | <view v-else class="funcGroup" @click="finishBtnFunc(item)"> |
| | | <u-icon class="funcBtn" name="edit-pen"></u-icon> |
| | | <span>完成</span> |
| | | </view> |
| | | </view> |
| | | <!-- 只有回答过的题目才能编辑笔记!!! --> |
| | | <text-editor :noteId="item.id" |
| | | :textContent="item.notes.length>0? item.notes[0].noteContent:''" |
| | | :isreadOnly="isreadOnly" @editorInput='updateEditorText'> |
| | | </text-editor> |
| | | </view> |
| | | </view> |
| | | </scroll-view> |
| | | </swiper-item> |
| | | </template> |
| | | </swiper> |
| | | |
| | | <!-- 底部栏 --> |
| | | <view class="footer" id="footer"> |
| | | <u-button type="success" shape="circle" @click="submitAns">提交</u-button> |
| | | <u-button type="primary" shape="circle" @click="changeQues">换一题</u-button> |
| | | <!-- <view class="footer-back" @click='handleChangeCurrentSwiper(-1)'>上一题</view> |
| | | <view class="footer-card" @click="showQuestion = !showQuestion">答题卡</view> |
| | | <view class="footer-right" @click='handleChangeCurrentSwiper(1)'>下一题</view> --> |
| | | </view> |
| | | <u-toast ref="uToast" /> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import Modal from './modal.vue' |
| | | import clock from '@/components/clock/clock.vue'; |
| | | export default { |
| | | data() { |
| | | return { |
| | | isreadOnly: true, |
| | | // isReviewed: false, |
| | | quesModules: [], |
| | | areaText: ``, //保存简答题答案 |
| | | judgeArr: [{ |
| | | name: '正确', |
| | | value: '1' |
| | | }, |
| | | { |
| | | name: '错误', |
| | | value: '0' |
| | | } |
| | | ], |
| | | currentIndex: 0, |
| | | swiperHeight: '800px', |
| | | modalHeight: '400px', |
| | | modalContentHeight: '300px', |
| | | showQuestion: false, |
| | | articleEditorValue: '', |
| | | eidtOrFinishValue: '编辑笔记', |
| | | editor: 'editor', |
| | | editorText: '' |
| | | } |
| | | }, |
| | | filters: { |
| | | // 判断答案状态 |
| | | answerStatusFilter(item) { |
| | | switch (item) { |
| | | case 1: |
| | | return '未答' |
| | | break; |
| | | case 2: |
| | | return '答题正确' |
| | | break; |
| | | case 3: |
| | | return '答题错误' |
| | | break; |
| | | case 4: |
| | | return '未评分' |
| | | break; |
| | | case 5: |
| | | return '已评分' |
| | | break; |
| | | case 6: |
| | | return '已答' |
| | | break; |
| | | default: |
| | | // ad |
| | | } |
| | | }, |
| | | |
| | | analysisFilter(item) { |
| | | if (item == null) { |
| | | return "暂无解析" |
| | | } else { |
| | | return item |
| | | } |
| | | } |
| | | }, |
| | | watch: { |
| | | |
| | | }, |
| | | computed: { |
| | | storeInfo() { |
| | | return this.$store.state.storeInfo |
| | | }, |
| | | questionList() { |
| | | return this.$store.state.questionList |
| | | }, |
| | | max() { |
| | | return this.questionList.length - 1 |
| | | }, |
| | | }, |
| | | props: { |
| | | type: { |
| | | type: String, |
| | | default: 'error' |
| | | }, |
| | | duration: { |
| | | type: [String, Number], |
| | | default: 300 |
| | | }, |
| | | // isReviewed: { |
| | | // type: Boolean, |
| | | // default: false |
| | | // }, |
| | | |
| | | }, |
| | | |
| | | onReady() { |
| | | this.$refs.myClock.start(); |
| | | // console.log('examDetail',this.examDetail); |
| | | }, |
| | | components: { |
| | | Modal, |
| | | clock |
| | | }, |
| | | methods: { |
| | | /* 跳转指定题目 */ |
| | | handleJumpSwiper(index) { |
| | | this.currentIndex = index |
| | | this.showQuestion = false |
| | | }, |
| | | end() { |
| | | this.$refs.uToast.show({ |
| | | title: '考试时间结束,已自动交卷', |
| | | type: 'warning' |
| | | }) |
| | | setTimeout(() => { |
| | | this.handleSubmit(0) |
| | | }, 2000) |
| | | }, |
| | | textInput(e) { |
| | | this.areaText = e.detail.value |
| | | // console.log(e.detail.value) |
| | | }, |
| | | /* 滑动题目 */ |
| | | handleSwiperChanged(event) { |
| | | this.currentIndex = event.detail.current |
| | | }, |
| | | /* 调用上一页,下一页 */ |
| | | handleChangeCurrentSwiper(operation) { |
| | | let max = this.questionList.length - 1 |
| | | let min = 0 |
| | | // 进行翻页 |
| | | if ((this.currentIndex > min && operation < 0) || (this.currentIndex < max && operation > 0)) { |
| | | this.currentIndex += operation |
| | | // console.log(this.currentIndex) |
| | | } |
| | | }, |
| | | /* 选择答案(单选)*/ |
| | | chooseSolution(item, subItem) { |
| | | if (!item.isReviewed) { |
| | | // tempAnswer为学生答案 |
| | | item.tempAnswer = subItem.optLetter |
| | | // if (this.currentIndex < this.max) { |
| | | // setTimeout(() => { |
| | | // this.currentIndex += 1 |
| | | // }, 300) |
| | | // } |
| | | } |
| | | }, |
| | | /* 选择答案(多选)*/ |
| | | chooseMutiSolution(item, subItem) { |
| | | if (!item.isReviewed) { |
| | | let answerIndex = item.dualChooseArr.indexOf(subItem.optLetter) |
| | | if (answerIndex > -1) { |
| | | // 该选项已经在数组中了 |
| | | item.dualChooseArr.splice(answerIndex, 1) |
| | | } else { |
| | | // 该选项不在数组中 |
| | | item.dualChooseArr.push(subItem.optLetter) |
| | | } |
| | | item.tempAnswer = item.dualChooseArr.join(',') |
| | | // this.onAnswerChange(answerIndex) |
| | | } |
| | | }, |
| | | /* 判断题答案 */ |
| | | judgeSolution(item, value) { |
| | | if (!item.isReviewed) { |
| | | // tempAnswer为学生答案 |
| | | item.tempAnswer = value |
| | | // if (this.currentIndex < this.max) { |
| | | // setTimeout(() => { |
| | | // this.currentIndex += 1 |
| | | // }, 300) |
| | | // } |
| | | } |
| | | }, |
| | | changeQues() { |
| | | if (this.currentIndex < this.max) { |
| | | this.currentIndex += 1 |
| | | } else { |
| | | this.$refs.uToast.show({ |
| | | title: '已无更多试题', |
| | | type: 'warning', |
| | | }) |
| | | } |
| | | }, |
| | | submitAns() { |
| | | //-------------- |
| | | // 对各题型的答案进行处理 |
| | | let that = this |
| | | switch (that.questionList[that.currentIndex].template) { |
| | | case 1: |
| | | // 选择题 |
| | | if (that.questionList[that.currentIndex].rightAnswer == that.questionList[that.currentIndex] |
| | | .tempAnswer) { |
| | | // 回答正确 |
| | | that.questionList[that.currentIndex].isRight = 1 |
| | | } else { |
| | | // 回答错误 |
| | | that.questionList[that.currentIndex].isRight = 2 |
| | | } |
| | | var rightArr = that.questionList[that.currentIndex].rightAnswer.split(',') |
| | | var userArr = that.questionList[that.currentIndex].tempAnswer.split(',') |
| | | that.questionList[that.currentIndex].wrongArr = [] // 保存选中的错误的选项 |
| | | |
| | | for (var item of userArr) { |
| | | // 用户的该答案不在正确答案数组在 |
| | | if (rightArr.indexOf(item) < 0) { |
| | | that.questionList[that.currentIndex].wrongArr.push(item) |
| | | } |
| | | } |
| | | break; |
| | | case 2: |
| | | var rightArr = that.questionList[that.currentIndex].rightAnswer.split(',').sort() |
| | | var userArr = that.questionList[that.currentIndex].tempAnswer.split(',').sort() |
| | | // that.questionList[that.currentIndex].wrongArr = [] // 保存选中的错误的选项 |
| | | |
| | | for (var i = 0; i < rightArr.length; i++) { |
| | | if (rightArr.length != userArr.length) { |
| | | // 回答错误,漏选了 |
| | | that.questionList[that.currentIndex].isRight = 2 |
| | | } else { |
| | | if (rightArr[i] != userArr[i]) { |
| | | // 回答错误 |
| | | that.questionList[that.currentIndex].isRight = 2 |
| | | } |
| | | // 回答正确 |
| | | that.questionList[that.currentIndex].isRight = 1 |
| | | } |
| | | } |
| | | for (var item of userArr) { |
| | | // 用户的该答案不在正确答案数组在 |
| | | if (rightArr.indexOf(item) < 0) { |
| | | that.questionList[that.currentIndex].wrongArr.push(item) |
| | | } |
| | | } |
| | | break; |
| | | case 3: |
| | | if (that.questionList[that.currentIndex].rightAnswer == that.questionList[that |
| | | .currentIndex] |
| | | .tempAnswer) { |
| | | // 回答正确 |
| | | that.questionList[that.currentIndex].isRight = 1 |
| | | } else { |
| | | // 回答错误 |
| | | that.questionList[that.currentIndex].isRight = 2 |
| | | } |
| | | // 判断题 |
| | | if (that.questionList[that.currentIndex].tempAnswer != that.questionList[that.currentIndex] |
| | | .toptions[0].optAnswer) { |
| | | that.questionList[that.currentIndex].wrongArr = that.questionList[that.currentIndex] |
| | | .tempAnswer |
| | | } |
| | | break; |
| | | case 4: |
| | | // 填空题 |
| | | that.questionList[that.currentIndex].tempAnswer = that.questionList[that.currentIndex] |
| | | .blankArr.join('||~||') // 数组拼接为字符串 |
| | | that.questionList[that.currentIndex].isRight = 3 // 自行核对 |
| | | break; |
| | | case 5: |
| | | that.questionList[that.currentIndex].isRight = 3 // 自行核对 |
| | | that.questionList[that.currentIndex].tempAnswer = JSON.stringify(that.areaText) |
| | | break; |
| | | default: |
| | | } |
| | | console.log('提交题库的信息', that.questionList[that.currentIndex].id, that.$store.state.storeInfo |
| | | .storeId); |
| | | |
| | | if(that.type == 'store'){ |
| | | that.$api.storeSave(that.questionList[that.currentIndex].id, that.$store.state.storeInfo.storeId) |
| | | .then(res => { |
| | | that.questionList[that.currentIndex].isReviewed = !that.questionList[that.currentIndex] |
| | | .isReviewed |
| | | if (res.status == 1) { |
| | | console.log('保存题库练习记录失败', res); |
| | | uni.showToast({ |
| | | title: '提交失败', |
| | | duration: 2000, |
| | | image: '../../static/error.png' |
| | | }); |
| | | } else { |
| | | console.log('保存题库练习记录成功', res); |
| | | // this.isReviewed = !this.isReviewed |
| | | } |
| | | }) |
| | | .catch(res => { |
| | | uni.showToast({ |
| | | title: '提交失败', |
| | | duration: 2000, |
| | | image: '../../static/error.png' |
| | | }); |
| | | console.log("提交失败"); |
| | | }) |
| | | |
| | | } |
| | | // ------------------------ |
| | | }, |
| | | |
| | | // 点击编辑笔记 |
| | | editBtnFunc(item) { |
| | | // if (item.theoryExamAnswer.id == undefined) { |
| | | // this.$refs.uToast.show({ |
| | | // title: '未作答的题目不可编辑笔记!', |
| | | // type: 'error', |
| | | // // url: '/pages/user/index' |
| | | // }) |
| | | // return |
| | | // } |
| | | this.isreadOnly = !this.isreadOnly |
| | | this.eidtOrFinishValue = '完成' |
| | | }, |
| | | // 完成编辑 |
| | | finishBtnFunc(item) { |
| | | var that = this |
| | | this.isreadOnly = !this.isreadOnly |
| | | this.eidtOrFinishValue = '编辑笔记' |
| | | console.log('保存笔记内容', item, that.editorText); |
| | | this.$api.addNote(item.id, that.editorText) |
| | | .then(res => { |
| | | console.log('更新笔记成功', res) |
| | | }) |
| | | }, |
| | | updateEditorText(text) { |
| | | // 从子组件获取输入框输入内容 |
| | | this.editorText = text |
| | | }, |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss"> |
| | | page { |
| | | background-color: #FFFFFF; |
| | | } |
| | | |
| | | #header, |
| | | #subHeader { |
| | | height: 100rpx; |
| | | } |
| | | |
| | | .header { |
| | | position: relative; |
| | | text-align: center; |
| | | line-height: 100rpx; |
| | | font-size: 36rpx; |
| | | font-weight: 600; |
| | | color: $theme-color; |
| | | letter-spacing: 10rpx; |
| | | |
| | | &-button { |
| | | width: 80rpx; |
| | | height: 40rpx; |
| | | line-height: 40rpx; |
| | | position: absolute; |
| | | top: 20rpx; |
| | | right: 40rpx; |
| | | padding: 10rpx 20rpx; |
| | | border-radius: 15rpx; |
| | | letter-spacing: 2rpx; |
| | | font-weight: 500; |
| | | color: #FFFFFF; |
| | | background-color: $theme-color; |
| | | } |
| | | |
| | | .scoreText { |
| | | color: #00b060; |
| | | font-size: 35rpx; |
| | | } |
| | | } |
| | | |
| | | .sub-header { |
| | | padding: 30rpx 20rpx; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | color: #000; |
| | | font-size: 33rpx; |
| | | font-weight: bold; |
| | | } |
| | | |
| | | .content { |
| | | letter-spacing: 3rpx; |
| | | |
| | | .typeTag { |
| | | margin-right: 20rpx; |
| | | } |
| | | |
| | | &-item-explain { |
| | | padding-bottom: 20rpx; |
| | | font-size: 30rpx; |
| | | color: #8799a3; |
| | | letter-spacing: 5rpx; |
| | | border-top: 1px solid rgba(0, 0, 0, 0.1); |
| | | |
| | | &-result { |
| | | padding: 20rpx 0; |
| | | |
| | | span { |
| | | padding-left: 20rpx; |
| | | color: #39b54a; |
| | | } |
| | | } |
| | | |
| | | &-content { |
| | | padding: 20rpx 0; |
| | | } |
| | | } |
| | | |
| | | &-item { |
| | | padding: 0 20rpx; |
| | | box-sizing: border-box; |
| | | } |
| | | |
| | | &-title { |
| | | margin-bottom: 30rpx; |
| | | font-size: 32rpx; |
| | | line-height: 55rpx; |
| | | color: #000 |
| | | } |
| | | |
| | | &-solutions { |
| | | width: 100%; |
| | | padding-bottom: 20rpx; |
| | | |
| | | &-item { |
| | | margin: 40rpx 0; |
| | | border: 5rpx solid $theme-color; |
| | | border-radius: 20rpx; |
| | | display: flex; |
| | | align-items: center; |
| | | font-size: 30rpx; |
| | | background-color: $theme-color; |
| | | |
| | | &-check-content { |
| | | padding: 35rpx 20rpx; |
| | | width: 100%; |
| | | border-radius: 15rpx; |
| | | color: $theme-color; |
| | | background-color: #FFFFFF; |
| | | } |
| | | |
| | | &-single { |
| | | width: 80rpx; |
| | | text-align: center; |
| | | color: #FFFFFF; |
| | | } |
| | | |
| | | &-content { |
| | | padding: 35rpx 20rpx; |
| | | width: 630rpx; |
| | | border-top-right-radius: 15rpx; |
| | | border-bottom-right-radius: 15rpx; |
| | | color: #000; |
| | | background-color: #FFFFFF; |
| | | } |
| | | |
| | | &-select { |
| | | color: #FFFFFF; |
| | | background-color: $theme-color; |
| | | } |
| | | } |
| | | |
| | | &-judge { |
| | | display: flex; |
| | | justify-content: space-around; |
| | | background-color: #FFFFFF; |
| | | padding: 20rpx; |
| | | text-align: center; |
| | | font-size: 30rpx; |
| | | |
| | | .content-solutions-judge-item { |
| | | border: 5rpx solid $theme-color; |
| | | border-radius: 60rpx; |
| | | width: 300rpx; |
| | | padding: 35rpx 20rpx; // 控制单元格的高度 |
| | | } |
| | | |
| | | .content-solutions-judge-select { |
| | | color: #FFFFFF; |
| | | background-color: $theme-color; |
| | | } |
| | | |
| | | } |
| | | |
| | | &-blank { |
| | | // border: 5rpx solid $theme-color; |
| | | height: 60rpx; |
| | | width: 90%; |
| | | // border-radius: 20rpx; |
| | | background-color: #FFFFFF; |
| | | padding: 20rpx; |
| | | } |
| | | |
| | | &-fillItem { |
| | | border: 5rpx solid $theme-color; |
| | | border-radius: 20rpx; |
| | | background-color: #FFFFFF; |
| | | padding: 20rpx; |
| | | } |
| | | } |
| | | |
| | | .explain { |
| | | border-top: solid #999999 1px; |
| | | padding-top: 10rpx; |
| | | font-size: 28rpx; |
| | | color: #666666; |
| | | |
| | | .explainResult { |
| | | color: $theme-color; |
| | | } |
| | | |
| | | .explain-title { |
| | | font-weight: bold; |
| | | } |
| | | |
| | | .noteArea { |
| | | border-top: 2rpx solid $theme-color; |
| | | padding-top: 10rpx; |
| | | |
| | | // background-color: #0077AA; |
| | | .noteAreaTitle { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .footer { |
| | | width: 750rpx; |
| | | height: 100rpx; |
| | | padding: 30rpx 20rpx; |
| | | position: fixed; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | bottom: 0; |
| | | font-size: 30rpx; |
| | | box-sizing: border-box; |
| | | color: #4c8af3; |
| | | box-shadow: 0 0 5px 1px #eee; |
| | | background-color: #FFFFFF; |
| | | |
| | | &-card { |
| | | padding: 10rpx 20rpx; |
| | | border: 1px solid $theme-color; |
| | | border-radius: 15rpx; |
| | | color: #FFFFFF; |
| | | background-color: $theme-color; |
| | | } |
| | | } |
| | | |
| | | .question-modal { |
| | | width: 700rpx; |
| | | padding: 40rpx; |
| | | background-color: #FFFFFF; |
| | | |
| | | &-header { |
| | | height: 100rpx; |
| | | text-align: center; |
| | | font-size: 35rpx; |
| | | line-height: 100rpx; |
| | | color: #333333; |
| | | border-bottom: 1rpx solid #F0F0F0; |
| | | } |
| | | |
| | | &-body { |
| | | |
| | | &-item { |
| | | width: 80rpx; |
| | | margin: 10rpx 22rpx; |
| | | height: 80rpx; |
| | | line-height: 80rpx; |
| | | font-size: 35rpx; |
| | | display: inline-block; |
| | | text-align: center; |
| | | border-radius: 50%; |
| | | color: #8799a3; |
| | | // background-color: #0077AA; |
| | | } |
| | | |
| | | &-item-failed { |
| | | color: #FFFFFF; |
| | | background-color: #982121; |
| | | } |
| | | |
| | | &-item-right { |
| | | color: #FFFFFF; |
| | | background-color: #39b54a; |
| | | } |
| | | |
| | | &-item-select { |
| | | color: #FFFFFF; |
| | | background-color: $theme-color; |
| | | } |
| | | } |
| | | |
| | | .question-modal-foot { |
| | | height: 100rpx; |
| | | border-top: 1rpx solid #F0F0F0; |
| | | margin-top: -60rpx; |
| | | |
| | | .ansBlock { |
| | | display: flex; |
| | | justify-content: center; |
| | | |
| | | // align-items: center; |
| | | .blockItem { |
| | | display: flex; |
| | | align-items: center; |
| | | margin: 20rpx; |
| | | } |
| | | |
| | | .block-ansed { |
| | | width: 80rpx; |
| | | height: 80rpx; |
| | | border-radius: 50%; |
| | | background: $theme-color; |
| | | margin: 0 10rpx; |
| | | } |
| | | |
| | | .block-unansed { |
| | | width: 80rpx; |
| | | height: 80rpx; |
| | | border-radius: 50%; |
| | | border: solid #999999 1px; |
| | | // background: $font-color-ps ; |
| | | margin: 0 10rpx; |
| | | } |
| | | |
| | | .block-right { |
| | | width: 80rpx; |
| | | height: 80rpx; |
| | | border-radius: 50%; |
| | | background: #39b54a; |
| | | margin: 0 10rpx; |
| | | } |
| | | |
| | | .block-wrong { |
| | | width: 80rpx; |
| | | height: 80rpx; |
| | | border-radius: 50%; |
| | | background: #982121; |
| | | margin: 0 10rpx; |
| | | } |
| | | } |
| | | |
| | | } |
| | | } |
| | | |
| | | .right { |
| | | border: 8rpx solid #39b54a; |
| | | } |
| | | |
| | | .wrong { |
| | | border: 8rpx solid #d81717; |
| | | } |
| | | </style> |
| New file |
| | |
| | | <template> |
| | | <!-- escloud --> |
| | | <view> |
| | | <view :class="[value? 'show': '']" class="yy-modal" id="show" @click="closeModal"> |
| | | <!-- click.stop 阻止<slot>中的点击事件继续向外传播, |
| | | 避免触发最外层closeModal点击事件 --> |
| | | <div @click.stop class='content'> |
| | | <slot></slot> |
| | | </div> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | data() { |
| | | return { |
| | | show: false |
| | | }; |
| | | }, |
| | | props:{ |
| | | value: { |
| | | type: [Boolean, String], |
| | | default: false |
| | | } |
| | | }, |
| | | watch: { |
| | | value(val) { |
| | | if (val) { |
| | | this.show = val |
| | | } else { |
| | | this.handleHidden() |
| | | } |
| | | } |
| | | }, |
| | | methods:{ |
| | | closeModal(e){ |
| | | this.$emit('input', false) |
| | | }, |
| | | handleHidden(){ |
| | | setTimeout(()=> { |
| | | this.show = false |
| | | }, 300) |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .yy-modal{ |
| | | position: fixed; |
| | | top: 0; |
| | | left: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | z-index: 1000; |
| | | opacity: 0; |
| | | transform: scale(1.185); |
| | | pointer-events: none; |
| | | transition: all 0.3s ease-in-out 0s; |
| | | background: rgba(0,0,0,0.6); |
| | | } |
| | | .show{ |
| | | opacity: 1; |
| | | transition-duration: 0.3s; |
| | | transform: scale(1); |
| | | overflow-x: hidden; |
| | | overflow-y: auto; |
| | | pointer-events: auto; |
| | | |
| | | } |
| | | .content{ |
| | | position: fixed; |
| | | top: 50%; |
| | | left: 50%; |
| | | transform: translate(-50%,-50%); |
| | | border-radius: 15rpx; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | </style> |
| New file |
| | |
| | | ## 答题组件 |
| | | |
| | | #### 调用方法 |
| | | ``` |
| | | <template> |
| | | <view> |
| | | <Answer :questtionList='questtionList' @submit='handleSubmit' @onChange='onChange'></Answer> |
| | | </view> |
| | | |
| | | </template> |
| | | <script> |
| | | import Answer from '@/components/dyw-answer/answer.vue' |
| | | export default { |
| | | data() { |
| | | return { |
| | | questtionList: [], |
| | | } |
| | | }, |
| | | components:{ |
| | | Answer |
| | | }, |
| | | methods: { |
| | | /* 提交答案 |
| | | */ |
| | | handleSubmit(answerList){ |
| | | console.log(answerList) |
| | | }, |
| | | /* 题目答案变化 |
| | | */ |
| | | onChange(answer){ |
| | | console.log(answer) |
| | | } |
| | | |
| | | |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | ``` |
| | | |
| | | #### 参数 |
| | | questtionList: 题目列表,组件中有列表格式 格式: Array |
| | | |
| | | currentSwiperItem: 设置默认题目,默认为第一道题目,从0开始。 格式: Number |
| | | |
| | | duration: swiper滑动事件,默认300 格式: String/Number |
| | | |
| | | | 参数名 | 默认值 | 描述 | 格式 | |
| | | | ---- | ---- | ---- | ---- | |
| | | | questtionList | - | 题目列表,组件中有列表格式案例。 | Array | |
| | | | currentSwiperItem | 0 | 设置默认题目,默认为第一道题目,从0开始。 | Number | |
| | | | duration | 300 | swiper滑动事件 | Number | |
| | | |
| | | #### 方法 |
| | | #### |
| | | | 方法名 | 返回值 | 描述 | 返回格式 | |
| | | | ---- | ---- | ---- | ---- | |
| | | | submit | questtionList | 点击提交时,调用该方法 | Array | |
| | | | onChange | 当前修改的题目对象 | 当用户选择答案时触发该方法 | Object | |
| | | |
| | | |
| | |
| | | "navigationBarTextStyle": "white" |
| | | } |
| | | |
| | | }, { |
| | | "path": "pages/voting/votRanking", |
| | | "style": { |
| | | "navigationBarTitleText": "投票排名", |
| | | "navigationBarBackgroundColor": "#103289", |
| | | "navigationBarTextStyle": "white" |
| | | } |
| | | |
| | | }, { |
| | | "path": "pages/registerUser/agreement", |
| | | "style": { |
| | | "navigationBarTitleText": "", |
| | | "navigationBarBackgroundColor": "#103289", |
| | | "navigationBarTextStyle": "white" |
| | | } |
| | | |
| | | }, { |
| | | "path": "pages/exam/startexam", |
| | | "name": "startexam", |
| | | "style": { |
| | | "navigationBarTitleText": "开始考试", |
| | | "navigationBarBackgroundColor": "#103289", |
| | | "navigationBarTextStyle": "white" |
| | | } |
| | | }, { |
| | | "path": "pages/exam/examTextPage", |
| | | "name": "examTextPage", |
| | | "style": { |
| | | "navigationStyle": "custom", |
| | | "navigationBarTitleText": "", |
| | | "enablePullDownRefresh": false |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/exam/examReviewPage", |
| | | "name": "examReviewPage", |
| | | "style": { |
| | | "navigationStyle": "custom", |
| | | "navigationBarTitleText": "", |
| | | "enablePullDownRefresh": false |
| | | } |
| | | |
| | | } |
| | | ,{ |
| | | "path" : "pages/voting/votRanking", |
| | | "style" : |
| | | { |
| | | "navigationBarTitleText": "投票排名", |
| | | "navigationBarBackgroundColor": "#103289", |
| | | "navigationBarTextStyle": "white" |
| | | } |
| | | |
| | | } |
| | | ,{ |
| | | "path" : "pages/registerUser/agreement", |
| | | "style" : |
| | | { |
| | | "navigationBarTitleText": "", |
| | | "navigationBarBackgroundColor": "#103289", |
| | | "navigationBarTextStyle": "white" |
| | | } |
| | | |
| | | } |
| | | ], |
| | | ], |
| | | "globalStyle": { //将组件安装在项目的components目录下,并符合components/组件名称/组件名称.vue目录结构。可以不用引用、注册,直接在页面中使用。 |
| | | "autoscan": true |
| | | }, |
| | |
| | | <view class="list"> |
| | | <u-grid :col="4" :border="false"> |
| | | <u-grid-item bg-color="transparent" v-for="(item, index) in dataTwo" :key="index"> |
| | | <navigator hover-class="none" class="nav-item" @click="goTwoPage(item.url,index)"> |
| | | <navigator hover-class="none" url="" class="nav-item" @click="goTwoPage(item.url,index)"> |
| | | <image :src="item.img" mode="widthFix" class="nav-item-img"></image> |
| | | <view class="nav-item-name">{{item.title}}</view> |
| | | </navigator> |
| | |
| | | title:'电子证件', |
| | | img:'../../static/workbench/task9.png', |
| | | url:'' |
| | | }], |
| | | } |
| | | // ,{ |
| | | // title:'模拟考试', |
| | | // img:'../../static/workbench/exam.png', |
| | | // url:'/pages/exam/startexam' |
| | | // } |
| | | ], |
| | | dataTwo:[{ |
| | | title:'参与投票', |
| | | img:'../../static/workbench/task5.png', |
| New file |
| | |
| | | <template> |
| | | <view> |
| | | <nav-bar-sub></nav-bar-sub> |
| | | <!-- 用于提示是否确认退出考试 --> |
| | | <!-- <u-modal v-model="show" :content="content" :show-cancel-button="true" @confirm="handleConfirm"></u-modal> --> |
| | | <!-- 渲染题目 --> |
| | | <Answer :isReviewed='isReview' examType="exam" @submit='handleCommit' @timeEnd='handleConfirm' |
| | | @onChange='onChange'></Answer> |
| | | </view> |
| | | |
| | | </template> |
| | | |
| | | <script> |
| | | import Answer from '@/components/dyw-answer/answer.vue'; |
| | | export default { |
| | | data() { |
| | | return { |
| | | // show: false, |
| | | // content: '是否确认交卷', |
| | | isReview: true, |
| | | confirmSubmitContent: '', |
| | | questionList: [], |
| | | examType: '', //考试类型 |
| | | } |
| | | }, |
| | | onLoad(option) { |
| | | var that = this |
| | | this.$api.checkGrade(option.recordId) |
| | | .then(res => { |
| | | console.log(res.values); |
| | | that.$store.state.examDetail = res.values |
| | | var quesModules = res.values.modules |
| | | // 提取出所有的题目 |
| | | for (let i = 0; i < quesModules.length; i++) { |
| | | for (let j = 0; j < quesModules[i].questions.length; j++) { |
| | | // 解决theoryExamAnswer可能为null的问题,把它赋值为字符串 |
| | | if (quesModules[i].questions[j].theoryExamAnswer == null) { |
| | | quesModules[i].questions[j].unAnswered = true //标记此题未答 |
| | | } |
| | | quesModules[i].questions[j].template = quesModules[i].template //防止template初始值是null |
| | | quesModules[i].questions[j].tempAnswer = '' |
| | | quesModules[i].questions[j].rightAnswer = '' |
| | | // quesModules[i].questions[j].recordId = that.$store.state.examDetail.recordId //搬移recordId的位置 |
| | | // 遍历选项得出正确答案和用户答案 |
| | | if (quesModules[i].questions[j].template == 1 || quesModules[i].questions[j].template == |
| | | 2) { |
| | | // 单选题与多选题 |
| | | if (quesModules[i].questions[j].unAnswered) { |
| | | quesModules[i].questions[j].theoryExamAnswer = { |
| | | optAnswer: "未作答" |
| | | } |
| | | } |
| | | |
| | | // 用户答案 |
| | | quesModules[i].questions[j].tempAnswer = quesModules[i].questions[j] |
| | | .theoryExamAnswer.optAnswer |
| | | |
| | | // 赋值选择题正确答案 |
| | | for (let k = 0; k < quesModules[i].questions[j].options.length; k++) { |
| | | // 获取选择题的正确答案 |
| | | if (quesModules[i].questions[j].options[k].optAnswer == 1) { |
| | | if (quesModules[i].questions[j].rightAnswer == '') { |
| | | quesModules[i].questions[j].rightAnswer = quesModules[i].questions[j] |
| | | .options[k].optLetter |
| | | } else { |
| | | quesModules[i].questions[j].rightAnswer += ',' + quesModules[i] |
| | | .questions[j].options[k].optLetter |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 判断题目错选了哪一项 |
| | | var rightArr = quesModules[i].questions[j].rightAnswer.split(',') |
| | | var userArr = quesModules[i].questions[j].tempAnswer.split(',') |
| | | quesModules[i].questions[j].wrongArr = [] // 保存选中的错误的选项 |
| | | |
| | | for (var item of userArr) { |
| | | // 用户的该答案不在正确答案数组在 |
| | | if (rightArr.indexOf(item) < 0) { |
| | | quesModules[i].questions[j].wrongArr.push(item) |
| | | } |
| | | } |
| | | |
| | | } else if (quesModules[i].questions[j].template == 3) { |
| | | // 3.判断题 |
| | | quesModules[i].questions[j].wrongArr = '' |
| | | if (quesModules[i].questions[j].unAnswered) { |
| | | quesModules[i].questions[j].theoryExamAnswer = { |
| | | optAnswer: "未作答" |
| | | } |
| | | } |
| | | // 题目已经作答 获取用户判断题答案 0错误 1正确 |
| | | quesModules[i].questions[j].tempAnswer = quesModules[i].questions[j] |
| | | .theoryExamAnswer.optAnswer |
| | | |
| | | // 为判断题的答案赋值 |
| | | if (quesModules[i].questions[j].options[0].optAnswer == 0) { |
| | | quesModules[i].questions[j].rightAnswer = "错误" |
| | | } else { |
| | | quesModules[i].questions[j].rightAnswer = "正确" |
| | | } |
| | | |
| | | // 判断题目错选了哪一项 |
| | | if (quesModules[i].questions[j].tempAnswer != quesModules[i].questions[j].options[0] |
| | | .optAnswer) { |
| | | quesModules[i].questions[j].wrongArr = quesModules[i].questions[j].tempAnswer |
| | | } |
| | | |
| | | } else if (quesModules[i].questions[j].template == 4) { |
| | | // 4.填空题 |
| | | if (!quesModules[i].questions[j].unAnswered) { |
| | | // 题目已经作答 获取用户填空题答案 |
| | | quesModules[i].questions[j].blankArr = quesModules[i].questions[j] |
| | | .theoryExamAnswer |
| | | .shortAnswer.split("||~||") |
| | | quesModules[i].questions[j].blankString = quesModules[i].questions[j].blankArr.join(',') |
| | | } else { |
| | | // 题目未作答 |
| | | quesModules[i].questions[j].blankArr = [] //新建blankArr属性,临时保存填空题答案 |
| | | quesModules[i].questions[j].blankString = '' //新建blankArr属性,临时保存填空题答案 |
| | | quesModules[i].questions[j].theoryExamAnswer = {} |
| | | for (let m = 0; m < quesModules[i].questions[j].options.length; m++) { |
| | | quesModules[i].questions[j].theoryExamAnswer.shortAnswer += "暂未作答||~||" |
| | | } |
| | | } |
| | | |
| | | // 为填空题附上正确答案 |
| | | for (let k = 0; k < quesModules[i].questions[j].options.length; k++) { |
| | | // 把null赋值为空字符串 |
| | | if (quesModules[i].questions[j].rightAnswer == '') { |
| | | quesModules[i].questions[j].rightAnswer = quesModules[i].questions[j] |
| | | .options[ |
| | | k].optContent |
| | | } else { |
| | | quesModules[i].questions[j].rightAnswer += ',' + quesModules[i].questions[ |
| | | j] |
| | | .options[k].optContent |
| | | } |
| | | } |
| | | } else { |
| | | // 5.简答题 |
| | | if (!quesModules[i].questions[j].unAnswered) { |
| | | // 题目已经作答 获取用户的简答题答案 |
| | | quesModules[i].questions[j].tempAnswer = quesModules[i].questions[j] |
| | | .theoryExamAnswer |
| | | .shortAnswer |
| | | } else { |
| | | quesModules[i].questions[j].theoryExamAnswer = {} |
| | | quesModules[i].questions[j].theoryExamAnswer.shortAnswer = "暂未作答" |
| | | } |
| | | |
| | | // 正确答案 |
| | | quesModules[i].questions[j].rightAnswer = quesModules[i].questions[j].queAnswer |
| | | } |
| | | that.questionList.push(quesModules[i].questions[j]) |
| | | } |
| | | } |
| | | that.$store.state.questionList = that.questionList |
| | | console.log('questionList:', that.questionList); |
| | | }) |
| | | console.log('考题列表:', this.questionList); |
| | | }, |
| | | components: { |
| | | Answer |
| | | }, |
| | | methods: { |
| | | /* 提交答案 显示再次确认*/ |
| | | handleCommit(questionList) { |
| | | // 显示是否确认交卷 |
| | | this.show = true; |
| | | }, |
| | | |
| | | // 已确认进行答案提交 |
| | | handleConfirm() { |
| | | // uni.setStorageSync('questionList', questionList) |
| | | // 进行交卷的api请求 |
| | | this.$api.commitExam(this.$store.state.examDetail.exam.id, this.$store.state.examDetail.recordId) |
| | | .then(res => { |
| | | console.log('交卷:', res); |
| | | }) |
| | | |
| | | uni.redirectTo({ |
| | | url: '/pages/exam/examResultPage', |
| | | }) |
| | | }, |
| | | /* 题目答案变化 |
| | | */ |
| | | onChange(answer) { |
| | | console.log(answer) |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss"> |
| | | page { |
| | | background-color: #FFFFFF; |
| | | } |
| | | </style> |
| New file |
| | |
| | | <template> |
| | | <view> |
| | | <!-- <nav-bar-sub></nav-bar-sub> --> |
| | | <!-- 用于提示是否确认退出考试 --> |
| | | <u-modal v-model="show" :content="content" :show-cancel-button="true" @confirm="handleConfirm"></u-modal> |
| | | |
| | | <!-- 渲染题目 --> |
| | | <Answer :isReviewed='isReview' :examType="examType" @submit='handleCommit' @timeEnd='handleConfirm' |
| | | @onChange='onChange'></Answer> |
| | | |
| | | <u-toast ref="uToast" /> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import Answer from '@/components/dyw-answer/answer.vue'; |
| | | import { |
| | | enterExam |
| | | } from '@/common/api/exam' |
| | | import { |
| | | ModifyQuesList |
| | | } from '@/common/api/examFunc' |
| | | export default { |
| | | data() { |
| | | return { |
| | | show: false, |
| | | content: '是否确认交卷', |
| | | isReview: false, |
| | | questionList: [], |
| | | examType: 'exam', //考试类型 |
| | | } |
| | | }, |
| | | onLoad(option) { |
| | | |
| | | this.examType = option.examType |
| | | |
| | | var that = this |
| | | if (option.examType == 'exam') { |
| | | // 理论考试 |
| | | enterExam({ |
| | | idCardNo: option.id |
| | | }).then(res => { |
| | | var examObj = res.data.data.simulateExamRecord |
| | | |
| | | examObj.exam = { |
| | | name: '测试考试', |
| | | examScore: 100, |
| | | examTime: res.data.data.simulateExamRecord.answerTime, |
| | | checkFace: 1, |
| | | ...option |
| | | } |
| | | |
| | | |
| | | |
| | | examObj.exam.totalQuestion = res.data.data.examSubjectInfo.length |
| | | examObj.totalQuestion = res.data.data.examSubjectInfo.length |
| | | that.$store.state.examDetail = examObj |
| | | |
| | | // 提取出所有的题目 |
| | | ModifyQuesList(res.data.data.examSubjectInfo) |
| | | }) |
| | | } else if (option.examType == 'paper') { |
| | | // 模拟考试 |
| | | this.$api.paperStart(option.paperId) |
| | | .then(res => { |
| | | console.log('paperStart:', res); |
| | | that.$store.state.examDetail = res.values |
| | | console.log('paper examDetail:', res.values); |
| | | var quesModules = res.values.modules |
| | | that.$api.ModifyQuesList(quesModules) |
| | | console.log(that.$store.state.pracDetail); |
| | | console.log(that.$store.state.pracQuesList); |
| | | }) |
| | | } else if (option.examType == 'know') { |
| | | // 知识点练习 |
| | | const knowSearch = JSON.parse(decodeURIComponent(option.knowSearch)); |
| | | console.log(knowSearch); |
| | | this.$api.startKnow(knowSearch) |
| | | .then(res => { |
| | | if (res.status == 1) { |
| | | // 获取知识点失败 |
| | | this.$refs.uToast.show({ |
| | | title: res.message, |
| | | type: 'error', |
| | | // icon: false, |
| | | url: '/pages/exam/pracIndexKnow' |
| | | }) |
| | | } else { |
| | | console.log('开始知识点练习的请求结果:', res); |
| | | that.$store.state.examDetail = res.values |
| | | var quesModules = res.values.modules |
| | | that.$api.ModifyQuesList(quesModules) |
| | | console.log(that.$store.state.pracDetail); |
| | | console.log(that.$store.state.pracQuesList); |
| | | } |
| | | }) |
| | | } else if (option.examType == 'course') { |
| | | this.$api.startTheory(that.$store.state.access_token, option.paperId) |
| | | .then(res => { |
| | | that.$store.state.examDetail = res.values |
| | | var quesModules = res.values.modules |
| | | that.$api.ModifyQuesList(quesModules) |
| | | }) |
| | | } else { |
| | | console.log("考试类型错误,请输入正确的类型"); |
| | | // return false |
| | | } |
| | | |
| | | console.log('考题列表:', this.questionList); |
| | | }, |
| | | components: { |
| | | Answer |
| | | }, |
| | | methods: { |
| | | /* 提交答案 显示再次确认*/ |
| | | handleCommit(questionList) { |
| | | // 显示是否确认交卷 |
| | | this.show = true; |
| | | }, |
| | | |
| | | // 已确认进行答案提交 |
| | | handleConfirm() { |
| | | // 进行交卷的api请求 |
| | | let that = this |
| | | if (this.examType == 'exam') { |
| | | this.$api.commitExam(this.$store.state.examDetail.exam.id, this.$store.state.examDetail.recordId) |
| | | .then(res => { |
| | | console.log('交卷:', res); |
| | | that.$u.route('/pages/exam/examResultPage', { |
| | | recordId: that.$store.state.examDetail.recordId, |
| | | examType: 'exam' |
| | | }) |
| | | }) |
| | | } else if ((this.examType == 'paper') || (this.examType == 'know')) { |
| | | this.$api.commitPaper(this.$store.state.examDetail.exerciseId) |
| | | .then(res => { |
| | | console.log('交卷:', res); |
| | | that.$u.route('/pages/exam/examResultPage', { |
| | | exerciseId: that.$store.state.examDetail.exerciseId, |
| | | examType: 'paper', |
| | | }) |
| | | }) |
| | | } else if (this.examType == 'store') { |
| | | this.$api.commitExam(this.$store.state.examDetail.exam.id, this.$store.state.examDetail.recordId) |
| | | .then(res => { |
| | | console.log('交卷:', res); |
| | | that.$u.route('/pages/exam/examResultPage', { |
| | | recordId: that.$store.state.examDetail.recordId, |
| | | examType: 'exam' |
| | | }) |
| | | }) |
| | | } else if (this.examType == 'course') { |
| | | this.$api.commitCourse(this.$store.state.access_token, this.$store.state.examDetail.exerciseId) |
| | | .then(res => { |
| | | console.log('交卷:', res); |
| | | that.$u.route('/pages/exam/examResultPage', { |
| | | exerciseId: that.$store.state.examDetail.exerciseId, |
| | | examType: 'course', |
| | | }) |
| | | }) |
| | | } else { |
| | | console.log("提交的考试类型出错"); |
| | | } |
| | | }, |
| | | /* 题目答案变化 |
| | | */ |
| | | onChange(answer) { |
| | | console.log(answer) |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | page { |
| | | background-color: #FFFFFF; |
| | | } |
| | | </style> |
| New file |
| | |
| | | <template> |
| | | <view> |
| | | <view class="subTitle"> |
| | | 考试信息 |
| | | </view> |
| | | <view class="examContent"> |
| | | <view>考试名称:<text>{{examItem.name}}</text> </view> |
| | | <view>考试总分:<text>{{examItem.examScore}}</text>分</view> |
| | | <view v-if="examItem.examTime>0">考试时长:<text>{{examItem.examTime}}</text>分钟</view> |
| | | <view v-else>考试时长:<text>不限时长</text></view> |
| | | </view> |
| | | <view class="subTitle">考试须知</view> |
| | | <view class="tipsArea"> |
| | | <ul> |
| | | <li>1、答题时要注意“剩余时间”提示,当剩余时间为0时,系统将自动交卷。</li> |
| | | <li>2、答题完成后,点击“我要交卷”按钮进行交卷,否则考试无效。</li> |
| | | <li>3、如果你准备好了,就点击“进入考场”吧,预祝取得好的成绩。</li> |
| | | </ul> |
| | | </view> |
| | | <view class="btnArea"> |
| | | <!-- checkFace==1 不需要人脸识别,checkFace==2 需要人脸识别 --> |
| | | <u-button v-if="needCheckFace==2 && !passFace " class="btnClass" type="primary" :ripple="true" |
| | | shape="circle" @click="checkFace">开始人脸识别</u-button> |
| | | <u-button v-if="needCheckFace==1 || passFace" class="btnClass" type="success" :ripple="true" shape="circle" |
| | | @click="enterExam">进入考试</u-button> |
| | | <u-button class="btnClass" type="error" :ripple="true" shape="circle" @click="exitExam">退出考试</u-button> |
| | | </view> |
| | | <u-toast ref="uToast" /> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | data() { |
| | | return { |
| | | examItem: {}, |
| | | examNote: ` |
| | | 1、答题时要注意“剩余时间”提示,当剩余时间为0时,系统将自动交卷。 |
| | | 2、答题完成后,点击“我要交卷”按钮进行交卷,否则考试无效。 |
| | | 3、如果你准备好了,就点击“进入考场”吧,预祝取得好的成绩。`, |
| | | passFace: false, |
| | | |
| | | } |
| | | }, |
| | | methods: { |
| | | enterExam() { |
| | | // 进入考试 |
| | | // uni.navigateTo({ |
| | | // url: '/pages/exam/examTextPage' |
| | | // }) |
| | | |
| | | this.$u.route('/pages/exam/examTextPage', { |
| | | id: this.examItem.id, |
| | | examType: 'exam', |
| | | }) |
| | | |
| | | }, |
| | | exitExam() { |
| | | // 退出考试 |
| | | uni.navigateBack({ |
| | | delta: 1 |
| | | }) |
| | | }, |
| | | checkFace() { |
| | | var that = this |
| | | this.$api.uploadImg2('face') |
| | | .then(res => { |
| | | console.log('faceRes', res) |
| | | if (res.data.indexOf('操作成功') >= 0) { |
| | | this.passFace = true |
| | | } |
| | | }) |
| | | }, |
| | | }, |
| | | computed: { |
| | | needCheckFace: function() { |
| | | // checkFace==1 不需要人脸识别,checkFace==2 需要人脸识别 |
| | | // H5 平台不需要检测人脸 |
| | | // #ifdef H5 |
| | | return 1 |
| | | // #endif |
| | | |
| | | // #ifdef APP-PLUS || MP-WEIXIN |
| | | return this.examItem.checkFace |
| | | // #endif |
| | | } |
| | | }, |
| | | onLoad(options) { |
| | | // 页面跳转 传递对象 传对象 |
| | | options = { |
| | | id: '360198198812130014', |
| | | name: '测试考试', |
| | | examScore: 100, |
| | | examTime: 90, |
| | | checkFace: 1 |
| | | } |
| | | this.examItem = options |
| | | console.log("考试信息:", this.examItem); |
| | | |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss"> |
| | | page { |
| | | font-size: 31rpx; |
| | | |
| | | ul li { |
| | | list-style: none; |
| | | } |
| | | } |
| | | |
| | | .tipsArea { |
| | | padding: 0 40rpx; |
| | | margin-left: -30rpx; |
| | | } |
| | | |
| | | .subTitle { |
| | | font-size: $uni-font-size-title; |
| | | font-weight: bold; |
| | | color: #103289; |
| | | text-align: center; |
| | | margin: 40rpx auto 20rpx auto; |
| | | } |
| | | |
| | | .examContent { |
| | | line-height: 50rpx; |
| | | margin-left: 180rpx; |
| | | |
| | | text { |
| | | font-weight: bold; |
| | | } |
| | | } |
| | | |
| | | ol { |
| | | // padding: 80rpx; |
| | | // background-color: #0077AA; |
| | | margin: 0 30rpx; |
| | | line-height: 50rpx; |
| | | } |
| | | |
| | | .btnArea { |
| | | display: flex; |
| | | margin-top: 50rpx; |
| | | |
| | | .btnClass { |
| | | width: 300rpx; |
| | | } |
| | | } |
| | | </style> |
| | |
| | | var api = 'http://223.82.109.183:2082/api/'; |
| | | var wsapi = 'ws://223.82.109.183:2082/wss/websocket'; |
| | | } else { |
| | | var api = 'http://192.168.0.108:83/'; |
| | | var api = 'http://192.168.0.198/'; |
| | | var wsapi = 'ws://192.168.0.108:9034/websocket'; |
| | | } |
| | | |
| | |
| | | import positions from "./positions.js" |
| | | import apis from "./apiConfig.js" |
| | | const state = { |
| | | examDetail: {}, // 考试详情 |
| | | questionList: [], // 考试考题列表 |
| | | queTypeArr:[0,0,0,0,0], |
| | | loging: false, |
| | | message: { |
| | | useName: '过客', |