Forráskód Böngészése

评卷参数修改

zhangjie 3 éve
szülő
commit
d9c73cca46

+ 11 - 0
src/assets/styles/pages.scss

@@ -850,6 +850,17 @@
       background-color: #ebeffc;
     }
   }
+  .total-info {
+    text-align: right;
+    padding-top: 10px;
+    padding-right: 210px;
+    > span {
+      color: $--color-danger;
+      font-weight: 600;
+      font-size: 16px;
+      margin: 0 2px;
+    }
+  }
   .row-unexpand-sub {
     display: none;
   }

+ 11 - 0
src/modules/exam/views/StatisticsManage.vue

@@ -2,6 +2,15 @@
   <div class="exam-statistics">
     <div class="part-box part-box-filter part-box-flex">
       <el-form ref="FilterForm" label-position="left" label-width="90px" inline>
+        <el-form-item label="学期:">
+          <semester-select v-model="filter.semesterId"></semester-select>
+        </el-form-item>
+        <el-form-item label="考试:">
+          <exam-select
+            v-model="filter.examId"
+            :semester-id="filter.semesterId"
+          ></exam-select>
+        </el-form-item>
         <el-form-item label="开课学院:">
           <college-select
             v-model.trim="filter.collegeId"
@@ -159,6 +168,8 @@ export default {
   data() {
     return {
       filter: {
+        semesterId: "",
+        examId: "",
         collegeId: "",
         teachingRoomId: "",
         courseName: "",

+ 4 - 2
src/modules/stmms/api.js

@@ -6,6 +6,9 @@ export const examStructureListPage = datas => {
 export const examStructureUpload = datas => {
   return $post("/api/admin/exam/structure/upload", datas);
 };
+export const examStructureUploadAnswer = datas => {
+  return $post("/api/admin/exam/structure/upload_answer", datas);
+};
 export const examStructurePreviewStructure = id => {
   return $postParam("/api/admin/exam/structure/preview_structure", { id });
 };
@@ -16,7 +19,7 @@ export const examStructureSubmit = datas => {
   return $post("/api/admin/exam/structure/submit", datas);
 };
 export const updateObjectiveAnswer = datas => {
-  return $post("/api/admin/exam/answer/submit", datas);
+  return $post("/api/admin/exam/structure/update_objective_answer", datas);
 };
 
 // score-archive
@@ -60,6 +63,5 @@ export const syncResultListPage = datas => {
   return $postParam("/api/admin/data/sync/query", datas);
 };
 export const syncResync = id => {
-  // objectId
   return $postParam("/api/admin/data/sync/resync", { id });
 };

+ 27 - 117
src/modules/stmms/components/UploadPaperAnswerDialog.vue

@@ -2,36 +2,24 @@
   <el-dialog
     class="upload-paper-answer-dialog"
     :visible.sync="modalIsShow"
-    title="上传试卷结构文档/标答PDF文档"
+    title="上传试卷标答PDF文档"
     top="10vh"
-    width="740px"
+    width="600px"
     :close-on-click-modal="false"
     :close-on-press-escape="false"
     append-to-body
     destroy-on-close
     @open="visibleChange"
   >
-    <el-form ref="modalFormComp" :model="infos" label-width="130px">
-      <div v-for="paperType in paperTypes" :key="paperType" class="part-box">
-        <h3 class="mb-2">卷型{{ paperType }}</h3>
-        <el-form-item
-          v-for="(val, key) in fileTypes"
-          :key="key"
-          :prop="`${paperType}.${key}`"
-          :label="`${val.name}:`"
-        >
+    <el-form ref="modalFormComp" :model="infos" label-width="50px">
+      <div class="part-box">
+        <h3 class="mb-2">卷型{{ instance.paperType }}</h3>
+        <el-form-item prop="file" label="标答:">
           <select-file
-            :format="val.format"
+            :format="fileFormat"
             :disabled="isSubmit"
-            @file-change="data => fileChange(paperType, key, data)"
+            @file-change="fileChange"
           ></select-file>
-          <el-button
-            v-if="val.downloadUrl"
-            type="success"
-            icon="el-icon-download"
-          >
-            <a :href="val.downloadUrl" :download="val.downloadName">模板下载</a>
-          </el-button>
         </el-form-item>
       </div>
     </el-form>
@@ -45,7 +33,7 @@
 </template>
 
 <script>
-import { examStructureUpload } from "../api";
+import { examStructureUploadAnswer } from "../api";
 import SelectFile from "./SelectFile.vue";
 
 export default {
@@ -63,52 +51,13 @@ export default {
     return {
       modalIsShow: false,
       isSubmit: false,
-      infos: {},
-      paperTypes: [],
-      fileTypes: {
-        objectiveQuestion: {
-          name: "客观题试卷结构",
-          downloadUrl: "/temps/objectiveQuestionTemplate.xlsx",
-          downloadName: "客观题导入模板.xlsx",
-          format: ["xlsx", "xls"]
-        },
-        subjectiveQuestion: {
-          name: "主观题试卷结构",
-          downloadUrl: "/temps/subjectiveQuestionTemplate.xlsx",
-          downloadName: "主观题导入模板.xlsx",
-          format: ["xlsx", "xls"]
-        },
-        standardAnswer: {
-          name: "标答",
-          format: ["pdf"]
-        }
-      },
-      fileTypeSerial: [
-        "objectiveQuestion",
-        "subjectiveQuestion",
-        "standardAnswer"
-      ]
+      infos: { file: null, md5: null, errorMsg: null },
+      fileFormat: ["pdf"]
     };
   },
   methods: {
-    initData() {
-      this.paperTypes = this.instance.paperType.split(",");
-      let infos = {};
-      this.paperTypes.forEach(paperType => {
-        let item = {};
-        Object.keys(this.fileTypes).map(typeKey => {
-          item[typeKey] = {
-            file: null,
-            md5: null,
-            errorMsg: null
-          };
-        });
-        infos[paperType] = item;
-      });
-      this.infos = infos;
-    },
     visibleChange() {
-      this.initData();
+      this.infos = { file: null, md5: null, errorMsg: null };
     },
     cancel() {
       this.modalIsShow = false;
@@ -116,70 +65,31 @@ export default {
     open() {
       this.modalIsShow = true;
     },
-    fileChange(paperType, typeKey, data) {
+    fileChange(data) {
       if (data.errorMsg) {
-        this.infos[paperType][typeKey].file = null;
-        this.infos[paperType][typeKey].md5 = null;
-        this.infos[paperType][typeKey].errorMsg = data.errorMsg;
+        this.infos.file = null;
+        this.infos.md5 = null;
+        this.infos.errorMsg = data.errorMsg;
       } else {
-        this.infos[paperType][typeKey].file = data.file;
-        this.infos[paperType][typeKey].md5 = data.md5;
-        this.infos[paperType][typeKey].errorMsg = null;
+        this.infos.file = data.file;
+        this.infos.md5 = data.md5;
+        this.infos.errorMsg = null;
       }
-      // this.$refs.modalFormComp.validateField(`${paperType}.${typeKey}`);
-    },
-    fileValidator(rule, value, callback) {
-      // const [paperType, typeKey] = rule.field.split(".");
-      // const val = this.infos[paperType][typeKey];
-
-      // if (val.errorMsg) {
-      //   return callback(new Error(val.errorMsg));
-      // } else {
-      //   if (!val.file) {
-      //     return callback(new Error("请选择文件"));
-      //   }
-      // }
-      const [paperType] = rule.field.split(".");
-      const paperTypeVals = this.infos[paperType];
-      const kvs = Object.vals(paperTypeVals);
-      const valid = kvs.some(val => !!val.file);
-      if (!valid) {
-        return callback(new Error(`卷型${paperType}至少要上传一种文件`));
-      }
-
-      callback();
     },
     async submit() {
-      const valid = await this.$refs.modalFormComp.validate().catch(() => {});
-      if (!valid) return;
+      if (!this.infos.file) {
+        this.$message.error("请选择标答文件");
+        return;
+      }
 
       if (this.isSubmit) return;
       this.isSubmit = true;
 
       let formData = new FormData();
-      formData.append("examPaperStructure", JSON.stringify(this.instance));
-      let md5s = [];
-      let keys = [];
-      Object.entries(this.infos).forEach(([paperType, vals]) => {
-        this.fileTypeSerial.forEach(typeKey => {
-          if (!vals[typeKey].file) return;
-          formData.append(`files`, vals[typeKey].file);
-          md5s.push(vals[typeKey].md5);
-          keys.push(`${paperType}-${typeKey}`);
-        });
-      });
-      formData.append(`md5`, md5s.join());
-      formData.append(`keys`, keys.join());
-
-      // Object.entries(this.infos).forEach(([paperType, vals], index) => {
-      //   const indexName = `files[${index}]`;
-      //   formData.append(`${indexName}.paperType`, paperType);
-      //   this.fileTypeSerial.forEach(typeKey => {
-      //     formData.append(`${indexName}.${typeKey}File`, vals[typeKey].file);
-      //     formData.append(`${indexName}.${typeKey}Md5`, vals[typeKey].md5);
-      //   });
-      // });
-      const data = await examStructureUpload(formData).catch(() => {});
+      formData.append("id", this.instance.id);
+      formData.append(`file`, this.infos.file);
+      formData.append(`md5`, this.infos.md5);
+      const data = await examStructureUploadAnswer(formData).catch(() => {});
       this.isSubmit = false;
       if (!data) return;
 

+ 10 - 8
src/modules/stmms/components/markParam/AnswerPopover.vue

@@ -43,18 +43,20 @@ export default {
     };
   },
   watch: {
-    value(val) {
-      if (val === this.answerStr) return;
+    value: {
+      immediate: true,
+      handler(val) {
+        if (val === this.answerStr) return;
 
-      if (this.radioList.includes(val)) {
-        this.bAnswer = val;
-      } else {
-        this.oAnswer = val.split("");
+        if (this.radioList.includes(val)) {
+          this.bAnswer = val;
+        } else {
+          this.oAnswer = val.split("");
+        }
+        this.updateAnswerStr();
       }
-      this.updateAnswerStr();
     }
   },
-  computed: {},
   methods: {
     oAnswerChange(val) {
       if (val) this.bAnswer = null;

+ 21 - 8
src/modules/stmms/components/markParam/MarkPaperStructure.vue

@@ -75,7 +75,6 @@
             :step="0.5"
             step-strictly
             :controls="false"
-            @change="questionScoreChange"
           ></el-input-number>
         </template>
       </el-table-column>
@@ -103,6 +102,10 @@
         </template>
       </el-table-column>
     </el-table>
+    <div class="total-info">
+      试卷总分:<span>{{ paperTotalScore }}</span
+      >分
+    </div>
   </div>
 </template>
 
@@ -132,6 +135,11 @@ export default {
       }
     };
   },
+  computed: {
+    paperTotalScore() {
+      return calcSum(this.tableData.map(item => item.totalScore || 0));
+    }
+  },
   mounted() {
     this.initData();
   },
@@ -252,11 +260,6 @@ export default {
         .filter(item => item.mainId === row.mainId && !item.isMainFirstSub)
         .forEach(item => (item.qType = row.qType));
     },
-    questionScoreChange() {
-      this.paperTotalScore = calcSum(
-        this.tableData.map(item => item.totalScore || 0)
-      );
-    },
     checkData() {
       if (
         this.tableData.some(item => item.qType === "objective") &&
@@ -317,8 +320,18 @@ export default {
         return;
       }
 
-      this.updateData();
-      this.$emit("next-step");
+      this.$confirm(
+        `当前试卷总分为${this.paperTotalScore}分, 确定要下一步吗?`,
+        "提示",
+        {
+          type: "warning"
+        }
+      )
+        .then(() => {
+          this.updateData();
+          this.$emit("next-step");
+        })
+        .catch(() => {});
     },
     getData() {
       return this.tableData.map(item => {

+ 2 - 1
src/modules/stmms/components/markParam/ModifyMarkParams.vue

@@ -290,7 +290,8 @@ export default {
 
       this.$message.success("提交成功!");
       this.$emit("modified");
-      this.cancel();
+      this.modalIsShow = false;
+      this.dataReady = false;
     }
   }
 };

+ 1 - 1
src/modules/stmms/components/markParam/ModifyMarkerQuestion.vue

@@ -213,7 +213,7 @@ export default {
     },
     // user
     async getOrgData() {
-      const data = await organizationList();
+      const data = await organizationList({ specialPrivilege: "MARKER" });
       this.parseUserData(data);
       this.getUserList();
     },

+ 25 - 2
src/modules/stmms/components/markParam/ModifyObjectiveAnswer.vue

@@ -8,6 +8,7 @@
     :show-close="false"
     append-to-body
     fullscreen
+    destroy-on-close
     @open="visibleChange"
   >
     <div class="box-justify" slot="title">
@@ -99,11 +100,31 @@ export default {
   },
   methods: {
     initData() {
-      const objectiveStructure = JSON.parse(
+      let objectiveStructure = JSON.parse(
         this.instance.objectiveStructure || "[]"
       );
+      objectiveStructure.sort((a, b) => {
+        if (a.mainNumber === b.mainNumber) {
+          return a.subNumber - b.subNumber;
+        } else {
+          return a.mainNumber - b.mainNumber;
+        }
+      });
+
+      let curMainNumber = null,
+        curMainId = null;
       this.tableData = objectiveStructure.map(item => {
-        return { ...item, answer: item.answer || "" };
+        let nitem = { ...item };
+        if (nitem.mainNumber !== curMainNumber) {
+          curMainId = this.$randomCode();
+          curMainNumber = nitem.mainNumber;
+          nitem.isMainFirstSub = true;
+        }
+        nitem.id = this.$randomCode();
+        nitem.mainId = curMainId;
+        nitem.expandSub = true;
+        nitem.answer = item.answer || "";
+        return nitem;
       });
     },
     visibleChange() {
@@ -150,6 +171,8 @@ export default {
       return true;
     },
     async submit() {
+      if (!this.checkData()) return;
+
       if (this.isSubmit) return;
       this.isSubmit = true;
       const datas = {

+ 1 - 1
src/modules/stmms/views/SyncManage.vue

@@ -176,7 +176,7 @@ export default {
       if (this.loading) return;
 
       this.loading = true;
-      const res = await syncResync(row.objectId).catch(() => false);
+      const res = await syncResync(row.id).catch(() => false);
       this.loading = false;
 
       if (!res) return;

+ 17 - 4
src/modules/stmms/views/UploadStructure.vue

@@ -60,8 +60,20 @@
               v-if="checkPrivilege('link', 'Upload')"
               class="btn-primary"
               type="text"
+              :disabled="!scope.row.paperInfoJson"
               @click="toUpload(scope.row)"
-              >上传标答</el-button
+              >上传标答文件</el-button
+            >
+            <el-button
+              v-if="
+                checkPrivilege('link', 'Preview') &&
+                  scope.row.status === 'FINISH'
+              "
+              class="btn-primary"
+              type="text"
+              :disabled="!scope.row.paperAnswer"
+              @click="toViewAnswer(scope.row, scope.row.paperType)"
+              >查看标答文件</el-button
             >
           </template>
         </el-table-column>
@@ -91,7 +103,7 @@
     />
     <ModifyObjectiveAnswer
       ref="ModifyObjectiveAnswer"
-      :datas="curTask"
+      :instance="curTask"
       @modified="getList"
     />
   </div>
@@ -165,12 +177,13 @@ export default {
       this.$refs.UploadPaperAnswerDialog.open();
     },
     toViewAnswer(row, paperType) {
-      if (!row.paperAnswer || !row.paperAnswer.length) {
+      if (!row.paperAnswer) {
         this.$message.error("暂时还没有标答可预览!");
         return;
       }
 
-      const paper = row.paperAnswer.find(item => item.paperType === paperType);
+      const paperAnswer = JSON.parse(row.paperAnswer);
+      const paper = paperAnswer.find(item => item.paperType === paperType);
       if (!paper) {
         this.$message.error("标答文件不存在!");
         return;