瀏覽代碼

feat: 评卷参数设置-分班阅以及客观题标答

zhangjie 3 月之前
父節點
當前提交
945ec881bb

+ 86 - 20
src/modules/mark/components/markParam/MarkParamClass.vue

@@ -1,15 +1,35 @@
 <template>
 <template>
   <div class="mark-param-class">
   <div class="mark-param-class">
-    <div class="part-box part-box-pad">
-      <div>
-        <!-- <el-switch
+    <div class="part-box part-box-pad box-justify">
+      <el-form inline>
+        <el-form-item
           v-if="checkPrivilege('button', 'OpenClassReading', 'MarkSetting')"
           v-if="checkPrivilege('button', 'OpenClassReading', 'MarkSetting')"
-          v-model="markClassIsOpen"
-          active-text="分班阅卷"
-          @change="markClassChange"
-        ></el-switch> -->
+          label="是否开启分班阅卷:"
+        >
+          <el-radio-group v-model="markClassIsOpen" @change="markClassChange">
+            <el-radio-button :label="true">开启</el-radio-button>
+            <el-radio-button :label="false">关闭</el-radio-button>
+          </el-radio-group>
+
+          <el-breadcrumb class="el-space" separator="|">
+            <el-breadcrumb-item
+              >班级数:{{ stat.classCount }}个</el-breadcrumb-item
+            >
+            <el-breadcrumb-item
+              >未分配评卷员班级数:{{
+                stat.unsignClassCount
+              }}个</el-breadcrumb-item
+            >
+            <el-breadcrumb-item
+              >设置完成进度:{{ stat.completeRate }}%</el-breadcrumb-item
+            >
+          </el-breadcrumb>
+        </el-form-item>
+      </el-form>
+      <div>
+        <el-button type="primary" @click="toPrev">上一步</el-button>
+        <el-button type="primary" @click="toNext">下一步</el-button>
       </div>
       </div>
-      <div></div>
     </div>
     </div>
     <div class="part-box part-box-pad">
     <div class="part-box part-box-pad">
       <el-table :data="dataList" border>
       <el-table :data="dataList" border>
@@ -39,7 +59,7 @@
         </el-table-column>
         </el-table-column>
       </el-table>
       </el-table>
       <div class="tips-info tips-error">
       <div class="tips-info tips-error">
-        <template v-if="groupInfo.length <= 1">
+        <template v-if="subjectiveTaskList.length <= 1">
           <p v-if="unsignData.length">
           <p v-if="unsignData.length">
             未分配班级:{{ unsignData.map((item) => item.className).join() }}
             未分配班级:{{ unsignData.map((item) => item.className).join() }}
           </p>
           </p>
@@ -79,8 +99,10 @@ import {
   markClassMarkerSave,
   markClassMarkerSave,
   markClassStatusUpdate,
   markClassStatusUpdate,
 } from "../../api";
 } from "../../api";
-import { mapState } from "vuex";
+import { mapState, mapMutations } from "vuex";
 import SelectClassByCourse from "./SelectClassByCourse.vue";
 import SelectClassByCourse from "./SelectClassByCourse.vue";
+import { toPrecision } from "@/plugins/utils";
+import { MD5 } from "@/plugins/md5";
 
 
 export default {
 export default {
   name: "mark-param-class",
   name: "mark-param-class",
@@ -88,6 +110,7 @@ export default {
   data() {
   data() {
     return {
     return {
       dataList: [],
       dataList: [],
+      cacheDataMd5: "",
       curRow: {},
       curRow: {},
       classList: [],
       classList: [],
       selectedClassIds: [],
       selectedClassIds: [],
@@ -97,12 +120,27 @@ export default {
     };
     };
   },
   },
   computed: {
   computed: {
-    ...mapState("markParam", ["basicInfo", "groupInfo", "openMarkClass"]),
+    ...mapState("markParam", [
+      "basicInfo",
+      "subjectiveTaskList",
+      "openMarkClass",
+    ]),
+    stat() {
+      return {
+        classCount: this.classList.length,
+        unsignClassCount: this.unsignData.length,
+        completeRate: toPrecision(
+          (100 * this.unsignData.length) / this.classList.length,
+          2
+        ),
+      };
+    },
   },
   },
   mounted() {
   mounted() {
     this.initData();
     this.initData();
   },
   },
   methods: {
   methods: {
+    ...mapMutations("markParam", ["setOpenMarkClass"]),
     async initData() {
     async initData() {
       this.markClassIsOpen = this.openMarkClass;
       this.markClassIsOpen = this.openMarkClass;
 
 
@@ -115,9 +153,13 @@ export default {
       this.classList = res.classNames || [];
       this.classList = res.classNames || [];
 
 
       this.updateUnsignData();
       this.updateUnsignData();
+      this.updateCacheDataMd5();
+    },
+    updateCacheDataMd5() {
+      this.cacheDataMd5 = MD5(JSON.stringify(this.dataList));
     },
     },
     async markClassChange() {
     async markClassChange() {
-      const name = this.markClassIsOpen ? "开启" : "取消";
+      const name = this.markClassIsOpen ? "开启" : "关闭";
       const confirm = await this.$confirm(`确定要${name}分班阅卷吗?`, "提示", {
       const confirm = await this.$confirm(`确定要${name}分班阅卷吗?`, "提示", {
         type: "warning",
         type: "warning",
       }).catch(() => {});
       }).catch(() => {});
@@ -135,6 +177,7 @@ export default {
       });
       });
       if (!res) return;
       if (!res) return;
       this.setOpenMarkClass(this.markClassIsOpen);
       this.setOpenMarkClass(this.markClassIsOpen);
+      this.initData();
     },
     },
     toSelectClass(row) {
     toSelectClass(row) {
       this.curRow = row;
       this.curRow = row;
@@ -153,7 +196,7 @@ export default {
             .filter((row) => row.markerClassList.includes(className))
             .filter((row) => row.markerClassList.includes(className))
             .map((row) => row.marker.userId);
             .map((row) => row.marker.userId);
 
 
-          const unsignGroups = this.groupInfo
+          const unsignGroups = this.subjectiveTaskList
             .filter(
             .filter(
               (group) =>
               (group) =>
                 !group.markers.some((marker) => markIds.includes(marker.userId))
                 !group.markers.some((marker) => markIds.includes(marker.userId))
@@ -161,10 +204,7 @@ export default {
             .map((group) => {
             .map((group) => {
               return {
               return {
                 id: group.id,
                 id: group.id,
-                groupNumber: group.groupNumber,
-                question: group.questions
-                  .map((q) => `${q.mainNumber}-${q.subNumber}`)
-                  .join(),
+                question: `${group.mainNumber}-${group.subNumber}`,
               };
               };
             });
             });
 
 
@@ -202,13 +242,39 @@ export default {
       const res = await markClassMarkerSave({
       const res = await markClassMarkerSave({
         examId: this.basicInfo.examId,
         examId: this.basicInfo.examId,
         paperNumber: this.basicInfo.paperNumber,
         paperNumber: this.basicInfo.paperNumber,
-        groupMarkerClass: this.dataList,
+        questionMarkerClass: this.dataList,
       }).catch(() => {});
       }).catch(() => {});
       if (!res) return;
       if (!res) return;
       this.$message.success("保存成功!");
       this.$message.success("保存成功!");
+      this.updateCacheDataMd5();
+      return true;
     },
     },
-    cancel() {
-      this.$emit("cancel");
+    async toPrev() {
+      if (this.cacheDataMd5 === MD5(JSON.stringify(this.dataList))) {
+        this.$emit("prev");
+        return;
+      }
+
+      const confirm = await this.$confirm(
+        `存在未保存的数据,是否保存后返回上一步?`,
+        "提示",
+        {
+          type: "warning",
+        }
+      ).catch(() => {});
+      if (confirm !== "confirm") {
+        this.$emit("prev");
+        return;
+      }
+
+      const res = await this.submit();
+      if (!res) return;
+      this.$emit("prev");
+    },
+    async toNext() {
+      const res = await this.submit();
+      if (!res) return;
+      this.$emit("next");
     },
     },
   },
   },
 };
 };

+ 2 - 1
src/modules/mark/components/markParam/MarkParamGroup.vue

@@ -319,7 +319,8 @@ export default {
       this.updateSubjectiveTaskItem(datas);
       this.updateSubjectiveTaskItem(datas);
     },
     },
     toSetMarkType(row) {
     toSetMarkType(row) {
-      console.log(row);
+      this.curRow = row;
+      this.$refs.ModifyMarkType.open();
     },
     },
     async markTypeModified(row) {
     async markTypeModified(row) {
       const pos = this.subjectiveTaskList.findIndex(
       const pos = this.subjectiveTaskList.findIndex(

+ 61 - 40
src/modules/mark/components/markParam/MarkParamObjectiveAnswer.vue

@@ -1,39 +1,41 @@
 <template>
 <template>
   <div class="mark-param-objective-answer">
   <div class="mark-param-objective-answer">
-    <div class="part-box part-box-pad">
-      <div>
-        <p class="tips-info">
-          1.如果已经扫描了答题卡,客观题标答提交后请到成绩检查菜单点击客观题统分按钮进行统分;
+    <div class="part-box part-box-pad box-justify">
+      <div class="tips-info">
+        <p>
+          如果已经扫描了答题卡,客观题标答提交后请到成绩检查菜单点击客观题统分按钮进行统分;
         </p>
         </p>
-      </div>
-    </div>
-
-    <div class="part-box part-box-pad">
-      <div class="box-justify mb-1">
         <p style="font-weight: bold">
         <p style="font-weight: bold">
           <i class="el-icon-warning"></i> 客观题标答只能输入大写字母ABCDE...
           <i class="el-icon-warning"></i> 客观题标答只能输入大写字母ABCDE...
           ,判断题正确请输入A,错误输入B
           ,判断题正确请输入A,错误输入B
         </p>
         </p>
+      </div>
 
 
-        <div>
-          <el-select
-            v-if="paperTypes.length > 1"
-            v-model="curPaperType"
-            placeholder="选择卷型"
-            :clearable="false"
-            style="width: 100px; margin-right: 10px"
-            @change="paperTypeChange"
-          >
-            <el-option
-              v-for="item in paperTypes"
-              :key="item"
-              :value="item"
-              :label="`${item}卷`"
-            ></el-option>
-          </el-select>
-          <el-button type="primary" @click="toImport">导入标答</el-button>
-        </div>
+      <div>
+        <el-select
+          v-if="paperTypes.length > 1"
+          v-model="curPaperType"
+          placeholder="选择卷型"
+          :clearable="false"
+          style="width: 100px; margin-right: 10px"
+          @change="paperTypeChange"
+        >
+          <el-option
+            v-for="item in paperTypes"
+            :key="item"
+            :value="item"
+            :label="`${item}卷`"
+          ></el-option>
+        </el-select>
+        <el-button type="primary" @click="toImport">导入标答</el-button>
+        <el-button type="primary" :disabled="loading" @click="submit"
+          >提交</el-button
+        >
+        <el-button type="primary" @click="toPrev">上一步</el-button>
       </div>
       </div>
+    </div>
+
+    <div class="part-box part-box-pad">
       <el-table
       <el-table
         ref="TableList"
         ref="TableList"
         :data="tableData"
         :data="tableData"
@@ -181,14 +183,6 @@
         </el-table-column>
         </el-table-column>
       </el-table>
       </el-table>
     </div>
     </div>
-
-    <div class="text-center">
-      <el-button type="primary" :disabled="loading" @click="submit"
-        >提交</el-button
-      >
-      <el-button @click="cancel">取消</el-button>
-    </div>
-
     <!-- ImportFile -->
     <!-- ImportFile -->
     <import-file
     <import-file
       ref="ImportFile"
       ref="ImportFile"
@@ -216,6 +210,7 @@ import { downloadByApi } from "@/plugins/download";
 
 
 import { mapState } from "vuex";
 import { mapState } from "vuex";
 import { omit } from "lodash";
 import { omit } from "lodash";
+import { MD5 } from "@/plugins/md5";
 
 
 export default {
 export default {
   name: "mark-param-objective-answer",
   name: "mark-param-objective-answer",
@@ -225,6 +220,7 @@ export default {
       loading: false,
       loading: false,
       tableDict: {},
       tableDict: {},
       tableData: [],
       tableData: [],
+      cacheDataMd5: "",
       QUESTION_SCORE_TYPE,
       QUESTION_SCORE_TYPE,
       abc: "abcdefghijklmnopqrstuvwxyz".toUpperCase(),
       abc: "abcdefghijklmnopqrstuvwxyz".toUpperCase(),
       QUESTION_SCORE_TYPE_SIMPLE: {
       QUESTION_SCORE_TYPE_SIMPLE: {
@@ -299,6 +295,11 @@ export default {
           : this.paperTypes[0];
           : this.paperTypes[0];
       this.prevPaperType = this.curPaperType;
       this.prevPaperType = this.curPaperType;
       this.tableData = this.tableDict[this.curPaperType];
       this.tableData = this.tableDict[this.curPaperType];
+
+      this.updateCacheDataMd5();
+    },
+    updateCacheDataMd5() {
+      this.cacheDataMd5 = MD5(JSON.stringify(this.tableDict));
     },
     },
     paperTypeChange() {
     paperTypeChange() {
       if (!this.checkData()) {
       if (!this.checkData()) {
@@ -435,14 +436,11 @@ export default {
       this.loading = false;
       this.loading = false;
       if (!data) return;
       if (!data) return;
 
 
+      this.updateCacheDataMd5();
       this.$message.success(
       this.$message.success(
         "保存成功,请到成绩检查菜单点击客观题统分按钮进行统分!"
         "保存成功,请到成绩检查菜单点击客观题统分按钮进行统分!"
       );
       );
-
-      // this.$emit("confirm");
-    },
-    cancel() {
-      this.$emit("cancel");
+      return true;
     },
     },
     // toImport
     // toImport
     async downloadHandle() {
     async downloadHandle() {
@@ -466,6 +464,29 @@ export default {
       this.$message.success("导入成功!");
       this.$message.success("导入成功!");
       this.initData(this.curPaperType);
       this.initData(this.curPaperType);
     },
     },
+    // step change
+    async toPrev() {
+      if (MD5(JSON.stringify(this.tableDict)) === this.cacheDataMd5) {
+        this.$emit("prev");
+        return;
+      }
+
+      const confirm = await this.$confirm(
+        `存在未保存的数据,是否保存后返回上一步?`,
+        "提示",
+        {
+          type: "warning",
+        }
+      ).catch(() => {});
+      if (confirm !== "confirm") {
+        this.$emit("prev");
+        return;
+      }
+
+      const res = await this.submit();
+      if (!res) return;
+      this.$emit("prev");
+    },
   },
   },
 };
 };
 </script>
 </script>

+ 8 - 3
src/modules/mark/components/markParam/ModifyMarkParams.vue

@@ -41,8 +41,8 @@
     <div v-if="dataReady">
     <div v-if="dataReady">
       <component
       <component
         :is="currentComponent"
         :is="currentComponent"
-        @cancel="cancel"
-        @confirm="confirm"
+        @next="nextHandler"
+        @prev="prevHandler"
       ></component>
       ></component>
     </div>
     </div>
     <div slot="footer"></div>
     <div slot="footer"></div>
@@ -197,7 +197,7 @@ export default {
       if (ind === this.curStepIndex) return;
       if (ind === this.curStepIndex) return;
       this.curStepIndex = ind;
       this.curStepIndex = ind;
     },
     },
-    confirm() {
+    nextHandler() {
       if (this.isLastStep && this.curStep.status === "process") {
       if (this.isLastStep && this.curStep.status === "process") {
         this.close();
         this.close();
         return;
         return;
@@ -216,6 +216,11 @@ export default {
         item.disabled = item.status === "wait";
         item.disabled = item.status === "wait";
       });
       });
     },
     },
+    prevHandler() {
+      if (this.isFirstStep) return;
+      this.curStepIndex -= 1;
+      this.steps[this.curStepIndex].status = "process";
+    },
     async cancel() {
     async cancel() {
       const res = await this.$confirm("确定要退出阅卷参数编辑吗?", "提示", {
       const res = await this.$confirm("确定要退出阅卷参数编辑吗?", "提示", {
         type: "warning",
         type: "warning",