|
@@ -0,0 +1,588 @@
|
|
|
|
+<template>
|
|
|
|
+ <div class="paper-score-container">
|
|
|
|
+ <Loading :top="200" type="1" style="text-align:center" v-show="dataLoading"></Loading>
|
|
|
|
+ <div class="scoring-paper-header">
|
|
|
|
+ <div>
|
|
|
|
+ <span class="base-info-item">
|
|
|
|
+ {{$t('learnActivity.score.stuName')}}
|
|
|
|
+ <span class="analysis-info">{{studentAnswer.name}}</span>
|
|
|
|
+ </span>
|
|
|
|
+ <span class="base-info-item">
|
|
|
|
+ {{$t('learnActivity.score.score')}}
|
|
|
|
+ <span class="analysis-info">
|
|
|
|
+ {{scoreTotal}}{{$t('learnActivity.score.scoreUnit')}}
|
|
|
|
+ </span>
|
|
|
|
+ </span>
|
|
|
|
+ <!-- 保存分数 -->
|
|
|
|
+ <span :class="['base-info-btn', isUpd ? 'base-info-btn-active' : '']" type="success" @click="saveScore">
|
|
|
|
+ <Icon type="ios-albums-outline" />
|
|
|
|
+ {{$t('learnActivity.score.saveScore')}}
|
|
|
|
+ </span>
|
|
|
|
+ <!-- 未阅满分 -->
|
|
|
|
+ <span class="base-info-btn" @click="batchScore('zero')">
|
|
|
|
+ <Icon type="ios-create" />
|
|
|
|
+ {{$t('learnActivity.score.fastScore4')}}
|
|
|
|
+ </span>
|
|
|
|
+ <!-- 未阅零分 -->
|
|
|
|
+ <span class="base-info-btn" @click="batchScore('full')">
|
|
|
|
+ <Icon type="ios-create" />
|
|
|
|
+ {{$t('learnActivity.score.fastScore5')}}
|
|
|
|
+ </span>
|
|
|
|
+ <span v-show="examInfo.source === '2'" class="base-info-btn" type="success" @click="viewOriginal">
|
|
|
|
+ <Icon type="md-eye" />
|
|
|
|
+ {{$t('learnActivity.score.viewOrigin')}}
|
|
|
|
+ </span>
|
|
|
|
+ <span class="base-info-btn" @click="config.showAnswer = !config.showAnswer">
|
|
|
|
+ <Icon :type="config.showAnswer ? 'md-eye-off':'md-eye'" />
|
|
|
|
+ {{ config.showAnswer ? $t('learnActivity.score.hideAns') : $t('learnActivity.score.showAns')}}
|
|
|
|
+ </span>
|
|
|
|
+ <span class="base-info-btn" @click="config.showQu = !config.showQu">
|
|
|
|
+ <Icon :type="config.showQu ? 'md-eye-off':'md-eye'" />
|
|
|
|
+ {{ config.showQu ? $t('learnActivity.score.hideQu') : $t('learnActivity.score.showQu')}}
|
|
|
|
+ </span>
|
|
|
|
+ </div>
|
|
|
|
+ <!-- 题号 -->
|
|
|
|
+ <div class="question-index-box" v-if="studentAnswer.scores">
|
|
|
|
+ <div class="base-info-item" style="white-space: nowrap;">{{$t('learnActivity.score.quIndex')}}</div>
|
|
|
|
+ <div>
|
|
|
|
+ <span v-for="quNoItem in quNoList" :key="quNoItem.label" :class="studentAnswer.scores[quNoItem.index] >= 0 ? 'qu-order-tag':'qu-order-tag-def'">
|
|
|
|
+ {{quNoItem.label}}
|
|
|
|
+ </span>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ <!-- 渲染题目和打分相关UI -->
|
|
|
|
+ <template v-if="!isComplete && studentAnswer.stuAnswers && studentAnswer.stuAnswers.length">
|
|
|
|
+ <!-- 默认题目顺序 -->
|
|
|
|
+ <template v-if="itemSort == 1">
|
|
|
|
+ <div v-for="(quItem) in defaultList" :key="quItem.quNo" ref="mathJaxContainer">
|
|
|
|
+ <template v-if="quItem.children && quItem.children.length">
|
|
|
|
+ <QuAndScore :ref="'QuAndScore'+ child.index" :stuMark="studentAnswer.mark[child.index]" @click.native="config.activeIndex = child.index" v-model="studentAnswer.scores[child.index]" v-for="(child) in quItem.children" :key="child.quNo" :stuAnswer="studentAnswer.stuAnswers[child.index]" :questionItem="child" :config="config" @on-save-mark="saveMark" @on-del-mark="delMark"></QuAndScore>
|
|
|
|
+ </template>
|
|
|
|
+ <template v-else>
|
|
|
|
+ <QuAndScore :ref="'QuAndScore'+ quItem.index" :stuMark="studentAnswer.mark[quItem.index]" @click.native="config.activeIndex = quItem.index" v-model="studentAnswer.scores[quItem.index]" :questionItem="quItem" :config="config" :stuAnswer="studentAnswer.stuAnswers[quItem.index]" @on-save-mark="saveMark" @on-del-mark="delMark"></QuAndScore>
|
|
|
|
+ </template>
|
|
|
|
+ </div>
|
|
|
|
+ </template>
|
|
|
|
+ <!-- 按题型排序 -->
|
|
|
|
+ <template v-else>
|
|
|
|
+ <div v-for="(typeItem) in groupList" :key="typeItem.type" ref="mathJaxContainer">
|
|
|
|
+ <p class="type-name">
|
|
|
|
+ {{ $tools.getChineseByNum(getLatestTypeIndex(typeItem.type) + 1) }}
|
|
|
|
+ {{ exersicesType[typeItem.type] }}
|
|
|
|
+ ({{ typeItem.score || 0 }} {{$t('learnActivity.score.scoreUnit')}})
|
|
|
|
+ </p>
|
|
|
|
+ <div v-for="(quItem) in typeItem.list" :key="quItem.quNo">
|
|
|
|
+ <template v-if="quItem.children && quItem.children.length">
|
|
|
|
+ <QuAndScore :ref="'QuAndScore'+ child.index" :stuMark="studentAnswer.mark[child.index]" @click.native="config.activeIndex = child.index" v-model="studentAnswer.scores[child.index]" v-for="(child) in quItem.children" :key="child.quNo" :stuAnswer="studentAnswer.stuAnswers[child.index]" :questionItem="child" :config="config" @on-save-mark="saveMark" @on-del-mark="delMark"></QuAndScore>
|
|
|
|
+ </template>
|
|
|
|
+ <template v-else>
|
|
|
|
+ <QuAndScore :ref="'QuAndScore'+ quItem.index" :stuMark="studentAnswer.mark[quItem.index]" @click.native="config.activeIndex = quItem.index" v-model="studentAnswer.scores[quItem.index]" :questionItem="quItem" :config="config" :stuAnswer="studentAnswer.stuAnswers[quItem.index]" @on-save-mark="saveMark" @on-del-mark="delMark"></QuAndScore>
|
|
|
|
+ </template>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </template>
|
|
|
|
+ </template>
|
|
|
|
+ <div v-show="isComplete" class="complete-score-box">
|
|
|
|
+ <Icon class="complete-icon" type="md-checkmark-circle" />
|
|
|
|
+ <p class="complete-stu-info">{{studentAnswer.name}} ({{scoreTotal}}{{$t('learnActivity.score.scoreUnit')}})</p>
|
|
|
|
+ <p class="complete-next" @click="nextStu">{{$t('learnActivity.score.nextStu')}}</p>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ <Modal v-model="originalStatus" :title="$t('learnActivity.score.viewOrigin')" :width="900" footer-hide>
|
|
|
|
+ <img v-for="item in sourceList" :src="item.url" :key="item.name" width="850">
|
|
|
|
+ <EmptyData v-show="!sourceList.length"></EmptyData>
|
|
|
|
+ </Modal>
|
|
|
|
+ </div>
|
|
|
|
+</template>
|
|
|
|
+
|
|
|
|
+<script>
|
|
|
|
+import QuAndScore from "./QuAndScore.vue"
|
|
|
|
+import BlobTool from '@/utils/blobTool.js'
|
|
|
|
+export default {
|
|
|
|
+ components: {
|
|
|
|
+ QuAndScore
|
|
|
|
+ },
|
|
|
|
+ props: {
|
|
|
|
+ examId: {
|
|
|
|
+ type: String,
|
|
|
|
+ default: '',
|
|
|
|
+ required: true
|
|
|
|
+ },
|
|
|
|
+ examInfo: {
|
|
|
|
+ type: Object,
|
|
|
|
+ default: () => {
|
|
|
|
+ return {}
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ subjectId: {
|
|
|
|
+ type: String,
|
|
|
|
+ default: '',
|
|
|
|
+ required: true
|
|
|
|
+ },
|
|
|
|
+ paper: {
|
|
|
|
+ type: Object,
|
|
|
|
+ default: () => { }
|
|
|
|
+ },
|
|
|
|
+ studentInfo: {
|
|
|
|
+ type: Object,
|
|
|
|
+ default: () => { }
|
|
|
|
+ },
|
|
|
|
+ defaultIndex: {
|
|
|
|
+ type: Number,
|
|
|
|
+ default: 0
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ data() {
|
|
|
|
+ let _this = this
|
|
|
|
+ return {
|
|
|
|
+ originalStatus: false,
|
|
|
|
+ isComplete: false,
|
|
|
|
+ exersicesType: this.$GLOBAL.EXERCISE_TYPES(),
|
|
|
|
+ typeList: ['single', 'multiple', 'judge', 'complete', 'subjective', 'connector', 'correct', 'compose'],
|
|
|
|
+ itemSort: 1,
|
|
|
|
+ quNoList: [],
|
|
|
|
+ sourceList: [],
|
|
|
|
+ dataLoading: false,
|
|
|
|
+ paperScore: [],
|
|
|
|
+ groupList: [],
|
|
|
|
+ defaultList: [],
|
|
|
|
+ studentAnswer: {},
|
|
|
|
+ config: {
|
|
|
|
+ showAnswer: false,
|
|
|
|
+ showQu: false,
|
|
|
|
+ activeIndex: -1,
|
|
|
|
+ examInfo: _this.examInfo,
|
|
|
|
+ stuInfo: _this.studentInfo,
|
|
|
|
+ subjectId: _this.subjectId,
|
|
|
|
+ },
|
|
|
|
+ isUpd: false
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ computed: {
|
|
|
|
+ scoreTotal() {
|
|
|
|
+ if (this.studentAnswer && this.studentAnswer.scores) {
|
|
|
|
+ let s = this.studentAnswer.scores.reduce((prev, cur) => {
|
|
|
|
+ cur = cur < 0 ? 0 : cur
|
|
|
|
+ return prev + cur
|
|
|
|
+ }, 0)
|
|
|
|
+ return s
|
|
|
|
+ }
|
|
|
|
+ return 0
|
|
|
|
+ },
|
|
|
|
+ },
|
|
|
|
+ watch: {
|
|
|
|
+ examInfo: {
|
|
|
|
+ immediate: true,
|
|
|
|
+ handler(n, o) {
|
|
|
|
+ if (n) {
|
|
|
|
+ this.config.examInfo = n
|
|
|
|
+ this.config.subjectId = this.subjectId
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ paper: {
|
|
|
|
+ handler(newPaper, oldValue) {
|
|
|
|
+ this.handleInitPaper(newPaper)
|
|
|
|
+ },
|
|
|
|
+ deep: true,
|
|
|
|
+ immediate: true
|
|
|
|
+ },
|
|
|
|
+ studentInfo: {
|
|
|
|
+ async handler(newValue, oldValue) {
|
|
|
|
+ this.studentAnswer = {}
|
|
|
|
+ this.studentAnswer = this._.cloneDeep(newValue || {})
|
|
|
|
+ this.isComplete = false
|
|
|
|
+ //处理默认显示批注
|
|
|
|
+ this.markFlag = {}
|
|
|
|
+ if (this.studentAnswer.mark) {
|
|
|
|
+ //后端阅卷批注数据异常,暂时这里过滤处理
|
|
|
|
+ for (let i = 0; i < this.studentAnswer.mark.length; i++) {
|
|
|
|
+ if (this.studentAnswer.mark[i]) {
|
|
|
|
+ this.studentAnswer.mark[i] = this.studentAnswer.mark[i].filter(m => {
|
|
|
|
+ return !!m.mark
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (!this.studentAnswer.status && this.studentAnswer.answers && this.studentAnswer.scores) {
|
|
|
|
+ if (this.studentAnswer.answers.length) {
|
|
|
|
+ let sourceBlob = this.studentAnswer.answers[0].replace('ans.json', 'source')
|
|
|
|
+ this.$set(this.studentAnswer, 'sourceBlob', sourceBlob)
|
|
|
|
+ try {
|
|
|
|
+ let sas = this.examInfo.scope == 'school' ? this.$store.state.user.schoolProfile.blob_sas : this.$store.state.user.userProfile.blob_sas
|
|
|
|
+ let blobUrl = this.examInfo.scope == 'school' ? JSON.parse(decodeURIComponent(localStorage.school_profile, "utf-8")).blob_uri : JSON.parse(decodeURIComponent(localStorage.user_profile, "utf-8")).blob_uri
|
|
|
|
+ /**
|
|
|
|
+ * 1、批注逻辑调整,每个题目的批注单独保存成图片;
|
|
|
|
+ * 2、这里就直接读取原始作答数据;
|
|
|
|
+ * 3、在渲染的时候再判断当前题目是否有批注数据。
|
|
|
|
+ */
|
|
|
|
+ let urlPrefix = `${blobUrl}/exam/${this.studentAnswer.answers[0].replace('/ans.json', '')}`
|
|
|
|
+ let fullUrl = `${blobUrl}/exam/${this.studentAnswer.answers[0]}?${sas}`
|
|
|
|
+ let ansRes = await this.$jsFn.handleStudentAnswer(fullUrl, urlPrefix, sas)
|
|
|
|
+ // 问答题:课中的地址需截取文件名称重新拼接地址,因此统一重新拼接处理
|
|
|
|
+ ansRes = ansRes.map((item, index) => {
|
|
|
|
+ if(this.quNoList[index].type === 'subjective' && this.quNoList[index].answerType && this.quNoList[index].answerType != 'text' && item.length) {
|
|
|
|
+ let name = item[0].substr(item[0].lastIndexOf(`/${this.studentInfo.id}/`) + (this.studentInfo.id.length + 2))
|
|
|
|
+ // 暂时处理切换学生带来的字符串重复拼接问题
|
|
|
|
+ if(name.includes('/')){
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ item = this.quNoList[index].answerType === 'file' ? [name] : [`${blobUrl}/exam/${this.examId}/${this.subjectId}/${this.studentInfo.id}/${name}?${sas}`]
|
|
|
|
+ }
|
|
|
|
+ return item
|
|
|
|
+ })
|
|
|
|
+ this.$set(this.studentAnswer, 'stuAnswers', ansRes)
|
|
|
|
+ } catch (e) {
|
|
|
|
+ let full = []
|
|
|
|
+ let i = 0
|
|
|
|
+ while (i < this.paperInfo.item.length) {
|
|
|
|
+ full.push(`<p style="color:red">${this.$t('learnActivity.score.ansErr')}</p>`)
|
|
|
|
+ i++
|
|
|
|
+ }
|
|
|
|
+ this.$set(this.studentAnswer, 'stuAnswers', full)
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ let a = this.studentAnswer.scores.map(item => {
|
|
|
|
+ return []
|
|
|
|
+ })
|
|
|
|
+ this.$set(this.studentAnswer, 'stuAnswers', a)
|
|
|
|
+ }
|
|
|
|
+ this.studentAnswer.status = true
|
|
|
|
+ }
|
|
|
|
+ // 切换学生后,上面步骤会触发studentAnswer.scores的监控事件,需重置编辑(isUpd)状态,否则会下一次切换学生时保存成绩
|
|
|
|
+ this.isUpd = false
|
|
|
|
+ },
|
|
|
|
+ deep: true,
|
|
|
|
+ immediate: true
|
|
|
|
+ },
|
|
|
|
+ "studentAnswer.scores": {
|
|
|
|
+ handler(n, o) {
|
|
|
|
+ if (n && o && n.length === o.length) {
|
|
|
|
+ this.isUpd = true
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ 'config.showQu' : {
|
|
|
|
+ handler(n, o) {
|
|
|
|
+ if(n) {
|
|
|
|
+ window.MathJax.startup.promise.then(() => {
|
|
|
|
+ window.MathJax.typesetPromise([this.$refs.mathJaxContainer])
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ },
|
|
|
|
+ methods: {
|
|
|
|
+ handleInitPaper(newPaper) {
|
|
|
|
+ this.paperInfo = this._.cloneDeep(newPaper)
|
|
|
|
+ let that = this
|
|
|
|
+ this.groupList = []
|
|
|
|
+ this.defaultList = []
|
|
|
|
+ this.paperScore = []
|
|
|
|
+ this.quNoList = []
|
|
|
|
+ this.itemSort = newPaper?.itemSort
|
|
|
|
+ if (newPaper && newPaper.item) {
|
|
|
|
+ this.dataLoading = true
|
|
|
|
+ if (newPaper.item.length) {
|
|
|
|
+ let index = 0 //题目索引
|
|
|
|
+ let quIndex = 1 // 题号
|
|
|
|
+ newPaper.item.forEach((i) => {
|
|
|
|
+ //记录题目原始位置
|
|
|
|
+ if (i.type == 'compose') {
|
|
|
|
+ i.children.forEach((cItem, cIndex) => {
|
|
|
|
+ cItem.quNo = `${quIndex}-${cIndex + 1}`
|
|
|
|
+ cItem.index = index++
|
|
|
|
+ this.paperScore.push(cItem.score || 0)
|
|
|
|
+ })
|
|
|
|
+ quIndex++
|
|
|
|
+ } else {
|
|
|
|
+ i.quNo = (quIndex++).toString()
|
|
|
|
+ i.index = index++
|
|
|
|
+ this.paperScore.push(i.score || 0)
|
|
|
|
+ }
|
|
|
|
+ if (!i.score) i.score = 0
|
|
|
|
+ })
|
|
|
|
+ //默认排序
|
|
|
|
+ if (this.itemSort == 1) {
|
|
|
|
+ this.defaultList = newPaper.item
|
|
|
|
+ this.defaultList.forEach(item => {
|
|
|
|
+ if (item.children && item.children.length) {
|
|
|
|
+ item.children.forEach(child => {
|
|
|
|
+ this.quNoList.push({
|
|
|
|
+ label: child.quNo,
|
|
|
|
+ index: child.index,
|
|
|
|
+ type: child.type,
|
|
|
|
+ answerType: child?.answerType || undefined
|
|
|
|
+ })
|
|
|
|
+ })
|
|
|
|
+ } else {
|
|
|
|
+ this.quNoList.push({
|
|
|
|
+ label: item.quNo,
|
|
|
|
+ index: item.index,
|
|
|
|
+ type: item.type,
|
|
|
|
+ answerType: item?.answerType || undefined
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 处理试卷内题目按照题型排序
|
|
|
|
+ else {
|
|
|
|
+ this.typeList.forEach(item => {
|
|
|
|
+ this._.mapKeys(this._.groupBy(newPaper.item, 'type'), function (value, key) {
|
|
|
|
+ if (key === item) { /* 按照题型排序,并且计算每种题型的总分 */
|
|
|
|
+ that.groupList.push({
|
|
|
|
+ type: key,
|
|
|
|
+ list: value,
|
|
|
|
+ score: value.reduce((p, e) => parseFloat(p) + parseFloat(e.score), 0)
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ })
|
|
|
|
+ this.groupList.forEach((typeItem, typeIndex) => {
|
|
|
|
+ if (typeItem.list) {
|
|
|
|
+ typeItem.list.forEach((quItem, quIndex) => {
|
|
|
|
+ if (quItem.children && quItem.children.length) {
|
|
|
|
+ quItem.children.forEach(child => {
|
|
|
|
+ this.quNoList.push({
|
|
|
|
+ label: child.quNo,
|
|
|
|
+ index: child.index,
|
|
|
|
+ type: child.type,
|
|
|
|
+ answerType: child?.answerType || undefined
|
|
|
|
+ })
|
|
|
|
+ })
|
|
|
|
+ } else {
|
|
|
|
+ this.quNoList.push({
|
|
|
|
+ label: quItem.quNo,
|
|
|
|
+ index: quItem.index,
|
|
|
|
+ type: quItem.type,
|
|
|
|
+ answerType: quItem?.answerType || undefined
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ this.dataLoading = false
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ getLatestTypeIndex(type) {
|
|
|
|
+ let arr = []
|
|
|
|
+ this.groupList.forEach(i => {
|
|
|
|
+ if (i.list.length) {
|
|
|
|
+ arr.push(i.type)
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ return arr.indexOf(type)
|
|
|
|
+ },
|
|
|
|
+ //点评下一位学生
|
|
|
|
+ nextStu() {
|
|
|
|
+ this.$emit('nextStu')
|
|
|
|
+ },
|
|
|
|
+ // 查阅原卷
|
|
|
|
+ viewOriginal() {
|
|
|
|
+ console.log(`output->this.studentAnswer`, this.studentAnswer)
|
|
|
|
+ if (!this.studentAnswer.sourceBlob) {
|
|
|
|
+ this.$Message.warning(this.$t('learnActivity.score.noStuAnswer'))
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ let sas = this.examInfo.scope == 'school' ? this.$store.state.user.schoolProfile.blob_sas : this.$store.state.user.userProfile.blob_sas
|
|
|
|
+ let blobUrl = this.examInfo.scope == 'school' ? JSON.parse(decodeURIComponent(localStorage.school_profile, "utf-8")).blob_uri : JSON.parse(decodeURIComponent(localStorage.user_profile, "utf-8")).blob_uri
|
|
|
|
+ let host = blobUrl.substring(0, blobUrl.lastIndexOf('/'))
|
|
|
|
+ let cont = blobUrl.substring(blobUrl.lastIndexOf('/') + 1)
|
|
|
|
+ let blobTool = new BlobTool(host, cont, '?' + sas, this.examInfo.scope)
|
|
|
|
+ let path = `exam/${this.studentAnswer.sourceBlob}` //原卷路径
|
|
|
|
+ this.sourceList = []
|
|
|
|
+ blobTool.listBlob({
|
|
|
|
+ prefix: path
|
|
|
|
+ }).then(
|
|
|
|
+ res => {
|
|
|
|
+ if (res.blobList && res.blobList.length) {
|
|
|
|
+ res.blobList.forEach(item => {
|
|
|
|
+ item.url = item.url + '?' + sas
|
|
|
|
+ })
|
|
|
|
+ this.sourceList = res.blobList
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ err => {
|
|
|
|
+ console.log(`output->err`, err)
|
|
|
|
+ }
|
|
|
|
+ )
|
|
|
|
+ console.log(`output->sourceList`, this.sourceList)
|
|
|
|
+ this.originalStatus = true
|
|
|
|
+ },
|
|
|
|
+ /**
|
|
|
|
+ * type full未阅满分 zero未阅零分
|
|
|
|
+ */
|
|
|
|
+ batchScore(type) {
|
|
|
|
+ if (!this.studentAnswer.scores.includes(-1)) {
|
|
|
|
+ this.$Message.warning({
|
|
|
|
+ content: this.$t('learnActivity.score.noQuMark'),
|
|
|
|
+ duration: 2
|
|
|
|
+ })
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ if (type === 'full') {
|
|
|
|
+ for (let i = 0; i < this.studentAnswer.scores.length; i++) {
|
|
|
|
+ if (this.studentAnswer.scores[i] === -1) {
|
|
|
|
+ this.$set(this.studentAnswer.scores, i, this.paperScore[i] || 0)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ } else if (type === 'zero') {
|
|
|
|
+ for (let i = 0; i < this.studentAnswer.scores.length; i++) {
|
|
|
|
+ if (this.studentAnswer.scores[i] === -1) {
|
|
|
|
+ this.$set(this.studentAnswer.scores, i, 0)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ //保存学生分数
|
|
|
|
+ saveScore() {
|
|
|
|
+ if (!this.isUpd) {
|
|
|
|
+ this.$Message.warning(this.$t('learnActivity.score.noUpd'))
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ let d = this._.cloneDeep(this.studentAnswer)
|
|
|
|
+ this.examInfo.stuLists
|
|
|
|
+ let requestData = {
|
|
|
|
+ "id": this.examId,
|
|
|
|
+ "code": this.examInfo.owner == 'school' ? this.$store.state.userInfo.schoolCode : this.$store.state.userInfo.TEAMModelId,
|
|
|
|
+ "point": [this.studentAnswer.scores],
|
|
|
|
+ "studentId": [{
|
|
|
|
+ id: this.studentAnswer.id,
|
|
|
|
+ type: this.studentAnswer.type
|
|
|
|
+ }],
|
|
|
|
+ "classId": this.studentAnswer.classId,
|
|
|
|
+ "school": this.examInfo.scope == 'school' ? this.$store.state.userInfo.schoolCode : this.$store.state.userInfo.TEAMModelId,
|
|
|
|
+ // "school": this.$store.state.userInfo.schoolCode,
|
|
|
|
+ "subjectId": this.subjectId
|
|
|
|
+ }
|
|
|
|
+ this.$api.learnActivity.UpsertAllRecord(requestData).then(res => {
|
|
|
|
+ if (!res.error) {
|
|
|
|
+ this.$Message.success(this.$t('learnActivity.score.saveScoreOk'))
|
|
|
|
+ this.isUpd = false
|
|
|
|
+ this.$emit('updScore', [d])
|
|
|
|
+ // 切换学生时保存成绩,不需要展示下一位学生页面
|
|
|
|
+ if (!this.studentAnswer.scores.includes(-1) && this.studentInfo.id === requestData.studentId[0].id) {
|
|
|
|
+ this.isComplete = true
|
|
|
|
+ }
|
|
|
|
+ if (res.isScore) this.$EventBus.$emit('onStatusChange')
|
|
|
|
+ } else {
|
|
|
|
+ this.$Message.error(this.$t('learnActivity.score.saveSocreErr'))
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ },
|
|
|
|
+ delMark(index) {
|
|
|
|
+ this.$Modal.confirm({
|
|
|
|
+ title: this.$t('learnActivity.score.delMark'),
|
|
|
|
+ content: this.$t('learnActivity.score.delMarkContent'),
|
|
|
|
+ onOk: () => {
|
|
|
|
+ let mark = this.studentAnswer.mark[index]?.find(item => {
|
|
|
|
+ return item.tmdId == this.$store.state.userInfo.TEAMModelId
|
|
|
|
+ })
|
|
|
|
+ let blob = mark ? mark.mark : ""
|
|
|
|
+ //保存批注数据
|
|
|
|
+ this.$api.learnActivity.delAnswer({
|
|
|
|
+ "id": this.examId,
|
|
|
|
+ "studentId": this.studentAnswer.id,
|
|
|
|
+ "subjectId": this.subjectId,
|
|
|
|
+ "classId": this.studentAnswer.classId,
|
|
|
|
+ "code": this.examInfo.scope == 'school' ? this.$store.state.userInfo.schoolCode : this.$store.state.userInfo.TEAMModelId,
|
|
|
|
+ "tmdId": this.$store.state.userInfo.TEAMModelId,
|
|
|
|
+ "index": index,//题号
|
|
|
|
+ "blob": blob
|
|
|
|
+ }).then(
|
|
|
|
+ res => {
|
|
|
|
+ this.$Message.success(this.$t('learnActivity.mark.deleteOk'))
|
|
|
|
+ let i = this.studentAnswer.mark[index].findIndex(item => item.tmdId === this.$store.state.userInfo.TEAMModelId)
|
|
|
|
+ if (i > -1) {
|
|
|
|
+ this.studentAnswer.mark[index].splice(i, 1)
|
|
|
|
+ this.$set(this.studentAnswer.mark, index, this._.cloneDeep(this.studentAnswer.mark[index]))
|
|
|
|
+ }
|
|
|
|
+ console.log('**********', this.studentAnswer)
|
|
|
|
+ },
|
|
|
|
+ err => {
|
|
|
|
+ this.$Message.error(this.$t('learnActivity.mark.deleteErr'))
|
|
|
|
+ }
|
|
|
|
+ )
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ },
|
|
|
|
+ // 保存批注
|
|
|
|
+ // data: {markInfo,quIndex}
|
|
|
|
+ saveMark(data) {
|
|
|
|
+ let { markInfo, quIndex } = data
|
|
|
|
+ let fileName, hasMarked
|
|
|
|
+ if (this.studentAnswer.mark && this.studentAnswer.mark[quIndex]) {
|
|
|
|
+ let d = this._.cloneDeep(this.studentAnswer.mark[quIndex])
|
|
|
|
+ let markData = d.find(item => {
|
|
|
|
+ return item.tmdId == this.$store.state.userInfo.TEAMModelId
|
|
|
|
+ })
|
|
|
|
+ if (markData) {
|
|
|
|
+ let blob = markData.mark
|
|
|
|
+ fileName = blob.substring(blob.lastIndexOf('/') + 1, blob.length)
|
|
|
|
+ hasMarked = true
|
|
|
|
+ } else {
|
|
|
|
+ fileName = this.$jsFn.uuid() + '.png'
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ fileName = this.$jsFn.uuid() + '.png'
|
|
|
|
+ }
|
|
|
|
+ let markPng = this.$jsFn.dataURLtoFile(markInfo.base64, fileName)
|
|
|
|
+ //保存批注图片
|
|
|
|
+ let sas = this.examInfo.scope == 'school' ? this.$store.state.user.schoolProfile.blob_sas : this.$store.state.user.userProfile.blob_sas
|
|
|
|
+ let blobUrl = this.examInfo.scope == 'school' ? JSON.parse(decodeURIComponent(localStorage.school_profile, "utf-8")).blob_uri : JSON.parse(decodeURIComponent(localStorage.user_profile, "utf-8")).blob_uri
|
|
|
|
+ let host = blobUrl.substring(0, blobUrl.lastIndexOf('/'))
|
|
|
|
+ let cont = blobUrl.substring(blobUrl.lastIndexOf('/') + 1)
|
|
|
|
+ let blobTool = new BlobTool(host, cont, '?' + sas, this.examInfo.scope)
|
|
|
|
+ let path = `exam/${this.examId}/${this.subjectId}/${this.studentAnswer.id}`
|
|
|
|
+ blobTool.upload(markPng, { path }).then(
|
|
|
|
+ res => {
|
|
|
|
+ if (!hasMarked) {
|
|
|
|
+ this.studentAnswer.mark[quIndex].push({
|
|
|
|
+ mark: path + '/' + fileName,
|
|
|
|
+ tmdId: this.$store.state.userInfo.TEAMModelId
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ //保存批注数据
|
|
|
|
+ this.$api.learnActivity.upsertAnswer({
|
|
|
|
+ "id": this.examId,
|
|
|
|
+ "studentId": this.studentAnswer.id,
|
|
|
|
+ "subjectId": this.subjectId,
|
|
|
|
+ "classId": this.studentAnswer.classId,
|
|
|
|
+ "code": this.examInfo.scope == 'school' ? this.$store.state.userInfo.schoolCode : this.$store.state.userInfo.TEAMModelId,
|
|
|
|
+ "tmdId": this.$store.state.userInfo.TEAMModelId,
|
|
|
|
+ "index": quIndex,//题号
|
|
|
|
+ "mark": {
|
|
|
|
+ sc: 0,//分数
|
|
|
|
+ tmdId: this.$store.state.userInfo.TEAMModelId,
|
|
|
|
+ mark: path + '/' + fileName,//批注BLOB地址
|
|
|
|
+ identity: 'admin',//老师身份,这是是固定管理员身份
|
|
|
|
+ index: quIndex //题号
|
|
|
|
+ }
|
|
|
|
+ }).then(
|
|
|
|
+ res => {
|
|
|
|
+ this.$Message.success(this.$t('learnActivity.score.markOk'))
|
|
|
|
+ let r = 'QuAndScore' + quIndex
|
|
|
|
+ console.log(this.$refs['QuAndScore5'])
|
|
|
|
+ console.log(this.$refs[r])
|
|
|
|
+ this.$refs[r][0]?.saveMarkOk()
|
|
|
|
+ },
|
|
|
|
+ err => {
|
|
|
|
+ this.$Message.error(this.$t('learnActivity.score.markErr'))
|
|
|
|
+ }
|
|
|
|
+ )
|
|
|
|
+ },
|
|
|
|
+ err => {
|
|
|
|
+ this.$Message.error(this.$t('learnActivity.mark.saveErr'))
|
|
|
|
+ }
|
|
|
|
+ )
|
|
|
|
+ },
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+</script>
|
|
|
|
+
|
|
|
|
+<style scoped lang="less">
|
|
|
|
+@import "./ByStuMark.less";
|
|
|
|
+</style>
|