Ver Fonte

feat: 评卷参数设置-结构和主观题

zhangjie há 3 meses atrás
pai
commit
a011bf4ad6

+ 9 - 11
src/modules/mark/api.js

@@ -30,21 +30,19 @@ export const markStructureSave = (datas) => {
   return $post("/api/admin/mark/question/save", datas);
 };
 // group
-export const markGroupList = (datas) => {
-  return $postParam("/api/admin/mark/group/list", datas);
+export const markSubjectiveList = (datas) => {
+  return $postParam("/api/admin/mark/subjective/list", datas);
 };
-export const markGroupItemSave = (datas) => {
-  return $post("/api/admin/mark/group/save", datas);
+export const markSubjectiveBindMarker = (datas) => {
+  return $post("/api/admin/mark/question/bind_marker", datas);
 };
-export const markGroupItemUpdate = (datas) => {
-  return $post("/api/admin/mark/group/update", datas);
+export const markSubjectiveUpdateMarkType = (datas) => {
+  return $post("/api/admin/mark/question/update_double_marking", datas);
 };
-export const markGroupAreaSave = (datas) => {
-  return $post("/api/admin/mark/group/update_picture_config", datas);
-};
-export const markGroupItemDelete = (datas) => {
-  return $postParam("/api/admin/mark/group/delete", datas);
+export const markSubjectiveUpdateMarkArea = (datas) => {
+  return $post("/api/admin/mark/question/update_picture_config", datas);
 };
+
 // class
 export const markClassStatusUpdate = (datas) => {
   return $postParam("/api/admin/mark/group/update_open_mark_class", datas);

+ 40 - 2
src/modules/mark/components/markParam/MarkParamClass.vue

@@ -1,5 +1,16 @@
 <template>
   <div class="mark-param-class">
+    <div class="part-box part-box-pad">
+      <div>
+        <!-- <el-switch
+          v-if="checkPrivilege('button', 'OpenClassReading', 'MarkSetting')"
+          v-model="markClassIsOpen"
+          active-text="分班阅卷"
+          @change="markClassChange"
+        ></el-switch> -->
+      </div>
+      <div></div>
+    </div>
     <div class="part-box part-box-pad">
       <el-table :data="dataList" border>
         <el-table-column type="index" width="50"> </el-table-column>
@@ -63,7 +74,11 @@
 </template>
 
 <script>
-import { markClassMarkerList, markClassMarkerSave } from "../../api";
+import {
+  markClassMarkerList,
+  markClassMarkerSave,
+  markClassStatusUpdate,
+} from "../../api";
 import { mapState } from "vuex";
 import SelectClassByCourse from "./SelectClassByCourse.vue";
 
@@ -78,16 +93,19 @@ export default {
       selectedClassIds: [],
       loading: false,
       unsignData: [],
+      markClassIsOpen: false,
     };
   },
   computed: {
-    ...mapState("markParam", ["basicInfo", "groupInfo"]),
+    ...mapState("markParam", ["basicInfo", "groupInfo", "openMarkClass"]),
   },
   mounted() {
     this.initData();
   },
   methods: {
     async initData() {
+      this.markClassIsOpen = this.openMarkClass;
+
       const params = {
         examId: this.basicInfo.examId,
         paperNumber: this.basicInfo.paperNumber,
@@ -98,6 +116,26 @@ export default {
 
       this.updateUnsignData();
     },
+    async markClassChange() {
+      const name = this.markClassIsOpen ? "开启" : "取消";
+      const confirm = await this.$confirm(`确定要${name}分班阅卷吗?`, "提示", {
+        type: "warning",
+      }).catch(() => {});
+      if (confirm !== "confirm") {
+        this.markClassIsOpen = !this.markClassIsOpen;
+        return;
+      }
+
+      const res = await markClassStatusUpdate({
+        examId: this.basicInfo.examId,
+        paperNumber: this.basicInfo.paperNumber,
+        openMarkClass: this.markClassIsOpen,
+      }).catch(() => {
+        this.markClassIsOpen = !this.markClassIsOpen;
+      });
+      if (!res) return;
+      this.setOpenMarkClass(this.markClassIsOpen);
+    },
     toSelectClass(row) {
       this.curRow = row;
       this.selectedClassIds = row.markerClassList;

+ 112 - 234
src/modules/mark/components/markParam/MarkParamGroup.vue

@@ -2,28 +2,23 @@
   <div class="mark-param-group">
     <div class="box-justify part-box part-box-pad">
       <div>
-        <p class="tips-info">
-          1.如果采用整卷批阅,请将全部主观题选上。如果采用分题阅卷,请将需要在一个评阅任务里评阅的题目勾选在一起;
+        <p v-if="unsetQuestionNos.length" class="tips-info tips-error">
+          试题{{
+            unsetQuestionNos.join(",")
+          }}未设置评卷员,请点击列表里设置评卷员选择评卷员
         </p>
-        <p class="tips-info">
-          2.如果采用分班阅卷,每个班都将按设置的评卷任务进行评卷,请给每个班级选择对应评卷老师;
-        </p>
-        <p class="tips-info tips-error">3.开始阅卷后不允许删除评卷分组!</p>
       </div>
       <div>
-        <el-switch
-          v-if="checkPrivilege('button', 'OpenClassReading', 'MarkSetting')"
-          v-model="markClassIsOpen"
-          active-text="分班阅卷"
-          @change="markClassChange"
-        ></el-switch>
-        <el-button class="ml-2" type="primary" @click="toAdd">新增</el-button>
+        <el-button type="primary" @click="toPrev">上一步</el-button>
+        <el-button type="primary" @click="toNext">下一步</el-button>
       </div>
     </div>
 
     <div class="part-box part-box-pad">
-      <el-table :data="groupList" border>
-        <el-table-column type="index" width="50"> </el-table-column>
+      <el-table :data="subjectiveTaskList" border>
+        <el-table-column label="大题名称" prop="mainTitle"> </el-table-column>
+        <el-table-column label="大题号" prop="mainNumber"> </el-table-column>
+        <el-table-column label="小题号" prop="subNumber"> </el-table-column>
         <el-table-column label="评卷员">
           <template slot-scope="scope">
             <el-tag
@@ -31,9 +26,15 @@
               :key="user.id"
               class="tag-spin tag-wrap"
               size="medium"
+              effect="dark"
+              closable
+              @close="toDeleteMarker(scope.row, user)"
             >
               {{ user.name }}({{ user.loginName }})
             </el-tag>
+            <el-button type="text" @click="toSetMarker(scope.row)">
+              设置评卷员
+            </el-button>
           </template>
         </el-table-column>
         <el-table-column label="评卷方式" width="100">
@@ -56,11 +57,6 @@
             {{ scope.row.doubleRate }}%
           </template>
         </el-table-column>
-        <el-table-column label="评阅题目">
-          <template slot-scope="scope">
-            {{ scope.row.questions | questionsFilter }}
-          </template>
-        </el-table-column>
         <el-table-column label="评卷区" width="80" align="center">
           <template slot-scope="scope">
             <i
@@ -74,8 +70,8 @@
             <el-button
               class="btn-primary"
               type="text"
-              @click="toEdit(scope.row)"
-              >编辑</el-button
+              @click="toSetMarkType(scope.row)"
+              >评卷方式设置</el-button
             >
             <el-button
               class="btn-primary"
@@ -84,35 +80,30 @@
               @click="toSetArea(scope.row)"
               >评卷区</el-button
             >
-            <el-button
-              class="btn-danger"
-              type="text"
-              @click="toDelete(scope.row)"
-              >删除</el-button
-            >
           </template>
         </el-table-column>
       </el-table>
-      <p v-if="unsetQuestionNos.length" class="tips-info tips-error">
-        未设置试题:{{ unsetQuestionNos.join(",") }}
-      </p>
     </div>
 
-    <!-- ModifyMarkGroup -->
-    <modify-mark-group
-      ref="ModifyMarkGroup"
+    <!-- ModifyMarkType -->
+    <modify-mark-type
+      ref="ModifyMarkType"
+      :instance="curRow"
+      @modified="markTypeModified"
+    ></modify-mark-type>
+    <!-- ModifyMarkMarker -->
+    <modify-mark-marker
+      ref="ModifyMarkMarker"
+      :instance="curRow"
       :course-id="basicInfo.courseId"
-      :instance="curGroupInfo"
-      :disabled-question-nos="disabledQuestionNos"
-      :paper-structure="subjectiveQuestionList"
-      @modified="groupModified"
-      @cancel="updateDisableQuestionNos"
-    ></modify-mark-group>
+      :question-list="curRowQuestions"
+      @modified="markMarkerModified"
+    ></modify-mark-marker>
     <!-- ModifyMarkArea -->
     <modify-mark-area
       ref="ModifyMarkArea"
       :base-info="basicInfo"
-      :group="curGroupInfo"
+      :group="curRow"
       :paper-list="paperList"
       @modified="areaModified"
     ></modify-mark-area>
@@ -121,41 +112,33 @@
 
 <script>
 import { mapState, mapMutations } from "vuex";
-import ModifyMarkGroup from "./ModifyMarkGroup.vue";
+import ModifyMarkType from "./ModifyMarkType.vue";
 import ModifyMarkArea from "./ModifyMarkArea.vue";
+import ModifyMarkMarker from "./ModifyMarkMarker.vue";
+
 import {
   examStructureFindJpg,
-  markGroupItemSave,
-  markGroupItemUpdate,
-  markGroupItemDelete,
-  markGroupAreaSave,
-  markClassStatusUpdate,
+  markSubjectiveBindMarker,
+  markSubjectiveUpdateMarkType,
+  markSubjectiveUpdateMarkArea,
 } from "../../api";
 import { cardDetail } from "../../../card/api";
-import { deepCopy, maxNum } from "@/plugins/utils";
 import { SCORE_POLICY_TYPE } from "@/constants/enumerate";
-import { omit, pick } from "lodash";
 
 export default {
   name: "mark-param-group",
   components: {
-    ModifyMarkGroup,
+    ModifyMarkType,
     ModifyMarkArea,
+    ModifyMarkMarker,
   },
   data() {
     return {
-      markClassIsOpen: false,
       SCORE_POLICY_TYPE,
       questionCount: 0,
-      groupQuestionCount: 0,
-      groupList: [],
-      fullDisabledQuestionNos: [],
-      disabledQuestionNos: [],
-      unsetQuestionNos: [],
-      curGroupInfo: {},
+      curRow: {},
       subjectiveQuestionList: [],
-      subjectiveQuestionCount: 0,
-      objectiveQuestionCount: 0,
+      curRowQuestions: [],
       MARK_TYPE: {
         0: "单评",
         1: "双评",
@@ -170,24 +153,20 @@ export default {
     ...mapState("markParam", [
       "basicInfo",
       "paperStructureInfo",
-      "openMarkClass",
-      "groupInfo",
+      "openMergeMarker",
+      "subjectiveTaskList",
     ]),
   },
-  filters: {
-    questionsFilter(val) {
-      return val
-        .map((item) => `${item.mainNumber}-${item.subNumber}`)
-        .join(",");
-    },
-  },
   mounted() {
     this.initData();
     this.getPaperList();
     this.getCardPages();
   },
   methods: {
-    ...mapMutations("markParam", ["setGroupInfo", "setOpenMarkClass"]),
+    ...mapMutations("markParam", [
+      "setSubjectiveTaskList",
+      "updateSubjectiveTaskItem",
+    ]),
     async getPaperList() {
       this.paperList = [];
       const data = await examStructureFindJpg({
@@ -211,10 +190,6 @@ export default {
       this.cardPages = cardContent.pages;
     },
     initData() {
-      this.markClassIsOpen = this.openMarkClass;
-      this.groupList = this.groupInfo.map((item) => {
-        return { ...deepCopy(item), id: this.$randomCode() };
-      });
       this.questionCount = this.paperStructureInfo.length;
       this.subjectiveQuestionList = this.paperStructureInfo
         .filter((item) => !item.objective)
@@ -227,115 +202,82 @@ export default {
       this.subjectiveQuestionCount = this.subjectiveQuestionList.length;
       this.objectiveQuestionCount =
         this.questionCount - this.subjectiveQuestionCount;
-      this.updateDisableQuestionNos();
 
       this.dataReady = true;
     },
-    updateDisableQuestionNos(filterId) {
-      let groupList = this.groupList;
-      if (filterId)
-        groupList = groupList.filter((item) => item.id !== filterId);
-      let disabledQuestionNos = [];
-      groupList.forEach((item) => {
-        disabledQuestionNos = [
-          ...disabledQuestionNos,
-          ...item.questions.map(
-            (item) => `${item.mainNumber}-${item.subNumber}`
-          ),
-        ];
-      });
-      this.disabledQuestionNos = disabledQuestionNos;
-      if (!filterId) {
-        this.groupQuestionCount = disabledQuestionNos.length;
-        this.fullDisabledQuestionNos = [...disabledQuestionNos];
-      }
-      this.updateUnsetQuestionNos();
-    },
-    updateUnsetQuestionNos() {
-      this.unsetQuestionNos = this.subjectiveQuestionList
-        .filter((q) => !this.fullDisabledQuestionNos.includes(q.qno))
-        .map((q) => q.qno);
+    toSetMarker(row) {
+      this.curRow = row;
+      this.curRowQuestions = [
+        {
+          mainNumber: row.mainNumber,
+          subNumber: row.subNumber,
+        },
+      ];
+      this.$refs.ModifyMarkMarker.open();
     },
-    toAdd() {
-      this.updateDisableQuestionNos();
-      if (this.groupQuestionCount === this.subjectiveQuestionCount) {
-        this.$message.error("当前已经没有主观题目可供设置!");
-        return;
-      }
-
-      this.curGroupInfo = {
-        id: this.$randomCode(),
-        groupNumber: maxNum(this.groupList.map((item) => item.groupNumber)) + 1,
-        doubleEnable: false,
-        doubleRate: 100,
-        arbitrateThreshold: 1,
-        scorePolicy: "AVG",
-        markers: [],
-        pictureConfigs: [],
-        questions: [],
-        isNew: true,
+    async markMarkerModified(row) {
+      const datas = {
+        questionId: row.questionId,
+        markers: row.markers,
       };
-      this.$refs.ModifyMarkGroup.open();
-    },
-    toEdit(row) {
-      this.curGroupInfo = row;
-      this.updateDisableQuestionNos(row.id);
-      this.$refs.ModifyMarkGroup.open();
+      await markSubjectiveBindMarker({
+        examId: this.basicInfo.examId,
+        paperNumber: this.basicInfo.paperNumber,
+        ...datas,
+      });
+      this.updateSubjectiveTaskItem(datas);
     },
     toSetArea(row) {
-      this.curGroupInfo = row;
+      this.curRow = row;
       this.$refs.ModifyMarkArea.open();
     },
-    async toDelete(row) {
-      if (this.deleting) return;
-
-      const confirm = await this.$confirm(
-        `删除分组会清理评卷任务,确定要删除当前分组吗?`,
-        "提示",
-        {
-          type: "warning",
-        }
-      ).catch(() => {});
+    async areaModified(row) {
+      const pos = this.subjectiveTaskList.findIndex(
+        (item) => item.questionId === row.questionId
+      );
+      if (pos === -1) return;
+      const datas = {
+        questionId: row.questionId,
+        pictureConfigs: row.pictureConfigs,
+      };
+      await markSubjectiveUpdateMarkArea(datas);
+      this.updateSubjectiveTaskItem(datas);
+    },
+    async toDeleteMarker(row, marker) {
+      const confirm = await this.$confirm(`确定要删除当前评卷员吗?`, "提示", {
+        type: "warning",
+      }).catch(() => {});
       if (confirm !== "confirm") return;
 
-      this.deleting = true;
-      const res = await markGroupItemDelete({
+      const markers = row.markers.filter((item) => item.id !== marker.id);
+      const datas = {
+        questionId: row.questionId,
+        markers,
+      };
+      await markSubjectiveBindMarker({
         examId: this.basicInfo.examId,
         paperNumber: this.basicInfo.paperNumber,
-        groupNumber: row.groupNumber,
-      }).catch(() => {});
-      this.deleting = false;
-      if (!res) return;
-
-      const pos = this.groupList.findIndex((item) => item.id === row.id);
-      this.groupList.splice(pos, 1);
-      this.updateDisableQuestionNos();
-      this.updateData();
+        ...datas,
+      });
+      this.updateSubjectiveTaskItem(datas);
     },
-    async groupModified(row) {
-      const pos = this.groupList.findIndex((item) => item.id === row.id);
-      if (!row.pictureConfigs.length) {
-        row.pictureConfigs = this.autoParsePictureConfigList(row.questions);
-      }
-
-      const data = await this.updateMarkGroup(row, pos === -1);
-      row.pictureConfigs = data.pictureConfigList;
-      if (pos === -1) {
-        this.groupList.push(row);
-      } else {
-        this.groupList.splice(pos, 1, row);
-      }
-      this.updateDisableQuestionNos();
-      this.updateData();
+    toSetMarkType(row) {
+      console.log(row);
     },
-    async updateMarkGroup(row, isAdd) {
-      const data = {
-        examId: this.basicInfo.examId,
-        paperNumber: this.basicInfo.paperNumber,
-        groupInfo: omit(row, ["id"]),
+    async markTypeModified(row) {
+      const pos = this.subjectiveTaskList.findIndex(
+        (item) => item.questionId === row.questionId
+      );
+      if (pos === -1) return;
+      const datas = {
+        questionId: row.questionId,
+        doubleEnable: row.doubleEnable,
+        doubleRate: row.doubleRate,
+        arbitrateThreshold: row.arbitrateThreshold,
+        scorePolicy: row.scorePolicy,
       };
-      const updateApi = isAdd ? markGroupItemSave : markGroupItemUpdate;
-      return await updateApi(data);
+      await markSubjectiveUpdateMarkType(datas);
+      this.updateSubjectiveTaskItem(datas);
     },
     autoParsePictureConfigList(questions) {
       if (!questions.length) return [];
@@ -410,75 +352,11 @@ export default {
       // console.log(combinePictureConfigList);
       return combinePictureConfigList;
     },
-    async areaModified(row) {
-      const pos = this.groupList.findIndex((item) => item.id === row.id);
-      if (pos === -1) return;
-
-      await markGroupAreaSave({
-        examId: this.basicInfo.examId,
-        paperNumber: this.basicInfo.paperNumber,
-        groupNumber: row.groupNumber,
-        pictureConfigs: row.pictureConfigs,
-      });
-      this.groupList.splice(pos, 1, row);
-      this.updateData();
-    },
-    async markClassChange() {
-      const name = this.markClassIsOpen ? "开启" : "取消";
-      const confirm = await this.$confirm(`确定要${name}分班阅卷吗?`, "提示", {
-        type: "warning",
-      }).catch(() => {});
-      if (confirm !== "confirm") {
-        this.markClassIsOpen = !this.markClassIsOpen;
-        return;
-      }
-
-      const res = await markClassStatusUpdate({
-        examId: this.basicInfo.examId,
-        paperNumber: this.basicInfo.paperNumber,
-        openMarkClass: this.markClassIsOpen,
-      }).catch(() => {
-        this.markClassIsOpen = !this.markClassIsOpen;
-      });
-      if (!res) return;
-      this.setOpenMarkClass(this.markClassIsOpen);
-    },
-    checkData() {
-      let errorMessages = [];
-
-      if (this.subjectiveQuestionCount > this.groupQuestionCount) {
-        errorMessages.push("当前还有题目未设置分组");
-      }
-
-      this.groupList.forEach((item, index) => {
-        if (item.doubleRate === 1 && !item.arbitrateThreshold) {
-          errorMessages.push(`序号${index + 1}设置中,仲裁阀值不能为空`);
-        }
-      });
-
-      if (errorMessages.length) {
-        this.$message.error(errorMessages.join("。"));
-        return;
-      }
-    },
-    getData() {
-      return this.groupList.map((item) => {
-        const group = omit(item, ["id"]);
-        group.questions = group.questions.map((item) =>
-          pick(item, [
-            "id",
-            "mainNumber",
-            "mainTitle",
-            "subNumber",
-            "questionType",
-            "qno",
-          ])
-        );
-        return group;
-      });
+    toPrev() {
+      this.$emit("prev");
     },
-    updateData() {
-      this.setGroupInfo(this.getData());
+    toNext() {
+      this.$emit("next");
     },
   },
 };

+ 90 - 87
src/modules/mark/components/markParam/MarkParamStructure.vue

@@ -1,26 +1,39 @@
 <template>
   <div class="mark-param-structure">
     <div class="part-box part-box-pad box-justify">
-      <div>
-        <p class="tips-info">
-          1.请确认展示的试卷结构与提交的试卷、答题卡是否一致?
-        </p>
-        <p class="tips-info">2.请补充所有题目的小题分值,并确认试卷总分!</p>
-        <p class="tips-info tips-error">
-          3.开始阅卷后不允许修改试卷结构,请确认清楚后再提交!
-        </p>
-      </div>
+      <el-breadcrumb class="el-space" separator="|">
+        <el-breadcrumb-item
+          >本试卷大题:{{ paperStat.mainQuestionCount }}道</el-breadcrumb-item
+        >
+        <el-breadcrumb-item
+          >小题:{{ paperStat.questionCount }}道</el-breadcrumb-item
+        >
+        <el-breadcrumb-item
+          >客观题:{{ paperStat.objectiveQuestionCount }}道</el-breadcrumb-item
+        >
+        <el-breadcrumb-item
+          >主观题:{{ paperStat.subjectiveQuestionCount }}道</el-breadcrumb-item
+        >
+        <el-breadcrumb-item
+          >总分:{{ paperStat.paperTotalScore }}分</el-breadcrumb-item
+        >
+      </el-breadcrumb>
 
-      <div v-if="checkPrivilege('link', 'EditPaperStruct', 'MarkSetting')">
-        <el-switch v-model="editOpen" active-text="开启编辑"></el-switch>
+      <div>
+        <el-button type="primary" @click="submit">下一步</el-button>
       </div>
     </div>
 
     <div class="part-box part-box-pad mb-0">
-      <div v-if="structureEditable" class="box-justify mb-2">
-        <div></div>
-        <el-button type="primary" @click="toAddMain">新增大题</el-button>
+      <div class="box-justify">
+        <el-button v-if="structureEditable" type="primary" @click="toAddMain"
+          >新增大题</el-button
+        >
+        <div v-if="checkPrivilege('link', 'EditPaperStruct', 'MarkSetting')">
+          <el-switch v-model="editOpen" active-text="开启编辑"></el-switch>
+        </div>
       </div>
+
       <el-table
         ref="TableList"
         :data="tableData"
@@ -160,24 +173,7 @@
             ></el-input-number>
           </template>
         </el-table-column>
-        <el-table-column label="每题间隔分" width="120">
-          <template slot="header">
-            <span>每题间隔分</span>
-            <el-tooltip effect="dark" placement="top">
-              <div slot="content" class="tooltip-area">
-                <p>间隔分是评卷中每题最小给分间隔,详见样例。</p>
-                <p>
-                  如小题总分为5分的题目,间隔分设置为1,则可以给0,1,2,3,4,5分。
-                </p>
-                <p>
-                  如间隔分设置为0.5分,则可以给0.5,1,1.5,2,2.5,3,3.5,4,4.5,5分。
-                </p>
-                <p>如果间隔分设置为5分,则只能给0分和5分。</p>
-                <p>每题间隔分是只用设置1次,系统会自动设置每个小题的间隔分</p>
-              </div>
-              <i class="el-icon-info ml-1 tooltip-info-icon"></i>
-            </el-tooltip>
-          </template>
+        <el-table-column label="每题最小分" width="120">
           <template
             slot-scope="scope"
             v-if="scope.row.mainFirstSub && !scope.row.objective"
@@ -191,12 +187,29 @@
               :step="0.1"
               step-strictly
               :controls="false"
-              placeholder="每题间隔分"
+              placeholder="每题最小分"
               @change="(val) => intervalScorePerTopicChange(val, scope.row)"
             ></el-input-number>
           </template>
         </el-table-column>
-        <el-table-column prop="intervalScore" label="间隔分" width="120">
+        <el-table-column prop="intervalScore" label="最小分" width="120">
+          <template slot="header">
+            <span>最小分</span>
+            <el-tooltip effect="dark" placement="top">
+              <div slot="content" class="tooltip-area">
+                <p>最小分是评卷中每题最小给分间隔,详见样例。</p>
+                <p>
+                  如小题总分为5分的题目,最小分设置为1,则可以给0,1,2,3,4,5分。
+                </p>
+                <p>
+                  如最小分设置为0.5分,则可以给0.5,1,1.5,2,2.5,3,3.5,4,4.5,5分。
+                </p>
+                <p>如果最小分设置为5分,则只能给0分和5分。</p>
+                <p>每题最小分是只用设置1次,系统会自动设置每个小题的最小分</p>
+              </div>
+              <i class="el-icon-info ml-1 tooltip-info-icon"></i>
+            </el-tooltip>
+          </template>
           <template slot-scope="scope" v-if="!scope.row.objective">
             <el-input-number
               v-model="scope.row.intervalScore"
@@ -207,7 +220,7 @@
               :step="0.1"
               step-strictly
               :controls="false"
-              placeholder="小题间隔分"
+              placeholder="小分"
             ></el-input-number>
           </template>
         </el-table-column>
@@ -236,17 +249,18 @@
           </template>
         </el-table-column>
       </el-table>
-    </div>
-    <div class="total-info">
-      试卷总分:<span>{{ paperTotalScore }}</span
-      >分
-    </div>
-
-    <div class="mark-footer">
-      <el-button type="primary" :disabled="loading" @click="submit"
-        >提交</el-button
-      >
-      <el-button @click="cancel">取消</el-button>
+      <!-- tips -->
+      <div>
+        <p class="tips-info">
+          1.请确认展示的试卷结构与提交的试卷、答题卡是否一致?
+        </p>
+        <p class="tips-info">
+          2.请补充所有题目的小题分值,并确认试卷总分。主观题设置间隔分,间隔分的具体说明见列表帮助提示。
+        </p>
+        <p class="tips-info tips-error">
+          3.开始阅卷后不允许修改试卷结构,请确认清楚后再提交!
+        </p>
+      </div>
     </div>
   </div>
 </template>
@@ -278,19 +292,39 @@ export default {
       "basicInfo",
       "structureCanEdit",
       "paperStructureInfo",
-      "groupInfo",
+      "subjectiveTaskList",
     ]),
-    paperTotalScore() {
-      const count = calcSum(this.tableData.map((item) => item.totalScore || 0));
-      return toPrecision(count, 1);
+    paperStat() {
+      const questionCount = this.tableData.length;
+
+      const mainQuestionCount = this.tableData.filter(
+        (item) => item.mainFirstSub
+      ).length;
+
+      const subjectiveQuestionCount = this.tableData.filter(
+        (item) => !item.objective
+      ).length;
+
+      const paperTotalScore = toPrecision(
+        calcSum(this.tableData.map((item) => item.totalScore || 0)),
+        1
+      );
+
+      return {
+        questionCount,
+        mainQuestionCount,
+        paperTotalScore,
+        subjectiveQuestionCount,
+        objectiveQuestionCount: questionCount - subjectiveQuestionCount,
+      };
     },
     structureEditable() {
       return this.structureCanEdit || this.editOpen;
     },
-    groupQuestions() {
-      return this.groupInfo
-        .map((group) => {
-          return group.questions.map((q) => `${q.mainNumber}-${q.subNumber}`);
+    subjectiveTaskList() {
+      return this.subjectiveTaskList
+        .map((task) => {
+          return task.questions.map((q) => `${q.mainNumber}-${q.subNumber}`);
         })
         .flat();
     },
@@ -594,7 +628,7 @@ export default {
           errorFields.push("小题满分");
         }
         if (!item.intervalScore && !item.objective) {
-          errorFields.push("评卷间隔分");
+          errorFields.push("评卷最小分");
         }
         if (errorFields.length) {
           errorMsg += `第${item.subNumber}小题,${errorFields.join(
@@ -620,40 +654,12 @@ export default {
         return omit(item, ["key", "mainId", "expandSub"]);
       });
     },
-    statPaperStructure() {
-      const questionCount = this.tableData.length;
-
-      const subjectiveQuestionCount = this.tableData.filter(
-        (item) => !item.objective
-      ).length;
-
-      return {
-        questionCount,
-        paperTotalScore: toPrecision(
-          calcSum(this.tableData.map((item) => item.totalScore || 0)),
-          1
-        ),
-        subjectiveQuestionCount,
-        objectiveQuestionCount: questionCount - subjectiveQuestionCount,
-      };
-    },
     async submit() {
       if (this.loading) return;
       if (!this.checkData()) return;
 
-      const questions = this.getData();
-      const paperStat = this.statPaperStructure();
-      let tipsContent = `本试卷共${paperStat.questionCount}道小题,客观题${paperStat.objectiveQuestionCount}道,主观题${paperStat.subjectiveQuestionCount}道,总分为${paperStat.paperTotalScore}分。`;
-      const confirm = await this.$confirm(
-        `${tipsContent}确定要提交吗?`,
-        "提示",
-        {
-          type: "warning",
-        }
-      ).catch(() => {});
-      if (confirm !== "confirm") return;
-
       this.loading = true;
+      const questions = this.getData();
       const res = await markStructureSave({
         examId: this.basicInfo.examId,
         paperNumber: this.basicInfo.paperNumber,
@@ -665,9 +671,6 @@ export default {
       this.setPaperStructureInfo(questions);
       this.$emit("confirm");
     },
-    cancel() {
-      this.$emit("cancel");
-    },
   },
 };
 </script>

+ 10 - 302
src/modules/mark/components/markParam/ModifyMarkGroup.vue → src/modules/mark/components/markParam/ModifyMarkMarker.vue

@@ -5,65 +5,12 @@
     append-to-body
     top="10vh"
     width="94%"
-    title="分组设置"
+    title="评卷员设置"
     :close-on-click-modal="false"
     :close-on-press-escape="false"
     :show-close="false"
     @opened="visibleChange"
   >
-    <!-- <div slot="title"></div> -->
-    <el-form ref="rowInfoFormRef" :model="rowInfo" :rules="rowInfoRules" inline>
-      <el-form-item label="评卷方式:" label-width="80px">
-        <el-radio-group
-          v-model="rowInfo.doubleEnable"
-          @change="doubleEnableChange"
-        >
-          <el-radio :label="false">单评</el-radio>
-          <el-radio v-if="openDoubleMarking" :label="true">双评</el-radio>
-        </el-radio-group>
-      </el-form-item>
-      <br />
-      <template v-if="rowInfo.doubleEnable">
-        <el-form-item label="仲裁阈值:" prop="arbitrateThreshold">
-          <el-input-number
-            v-model="rowInfo.arbitrateThreshold"
-            class="width-80"
-            size="small"
-            :min="0"
-            :max="999999"
-            :step="0.01"
-            step-strictly
-            :controls="false"
-          >
-          </el-input-number>
-        </el-form-item>
-        <el-form-item label="合分策略:" prop="scorePolicy">
-          <el-select v-model="rowInfo.scorePolicy">
-            <el-option
-              v-for="(val, key) in SCORE_POLICY_TYPE"
-              :key="key"
-              :label="val"
-              :value="key"
-            ></el-option>
-          </el-select>
-        </el-form-item>
-        <el-form-item label="双评比例:" prop="doubleRate">
-          <el-input-number
-            v-model="rowInfo.doubleRate"
-            class="width-80"
-            size="small"
-            :min="1"
-            :max="100"
-            :step="1"
-            step-strictly
-            :controls="false"
-          >
-          </el-input-number>
-          <span style="margin-left: 5px">%</span>
-        </el-form-item>
-      </template>
-    </el-form>
-
     <el-row type="flex" :gutter="10">
       <el-col :span="12">
         <div class="marker-box">
@@ -144,56 +91,11 @@
                 {{ user.name }}({{ user.loginName }})
               </el-tag>
             </el-form-item>
-            <el-form-item
-              prop="questions"
-              :label="canSelectQuestion ? '选择评卷题目:' : '评卷题目:'"
-            >
+            <el-form-item prop="questions" label="评卷题目:">
               <div class="marker-paper-struct">
-                <div
-                  v-for="mainItem in paperStructs"
-                  :key="mainItem.mainNumber"
-                  class="struct-item"
+                <el-tag v-for="(question, qindex) in questionList" :key="qindex"
+                  >{{ question.mainNumber }}-{{ question.subNumber }}</el-tag
                 >
-                  <div class="struct-header box-justify">
-                    <h4>{{ mainItem.mainNumber }}、{{ mainItem.mainTitle }}</h4>
-                    <el-checkbox
-                      v-if="
-                        canSelectQuestion &&
-                        mainItem.children &&
-                        mainItem.children.length
-                      "
-                      v-model="mainItem.selected"
-                      :disabled="mainItem.disabled"
-                      title="全选"
-                      @change="
-                        (checked) => selectQuestionAll(checked, mainItem)
-                      "
-                    ></el-checkbox>
-                  </div>
-                  <div
-                    v-if="mainItem.children && mainItem.children.length"
-                    class="struct-questions"
-                  >
-                    <template v-if="canSelectQuestion">
-                      <el-checkbox
-                        v-for="question in mainItem.children"
-                        :key="question.id"
-                        v-model="question.selected"
-                        :disabled="question.disabled"
-                        @change="questionChange"
-                      >
-                        {{ question.subNumber }}
-                      </el-checkbox>
-                    </template>
-                    <template v-else>
-                      <template v-for="question in mainItem.children">
-                        <el-tag v-if="question.selected" :key="question.id">{{
-                          question.subNumber
-                        }}</el-tag>
-                      </template>
-                    </template>
-                  </div>
-                </div>
               </div>
             </el-form-item>
           </el-form>
@@ -213,9 +115,6 @@
 <script>
 import { deepCopy } from "../../../../plugins/utils";
 import { organizationList } from "../../../base/api";
-import { SCORE_POLICY_TYPE } from "@/constants/enumerate";
-import { mapState } from "vuex";
-import { omit } from "lodash";
 
 export default {
   name: "modify-mark-group",
@@ -226,13 +125,7 @@ export default {
         return {};
       },
     },
-    disabledQuestionNos: {
-      type: Array,
-      default() {
-        return [];
-      },
-    },
-    paperStructure: {
+    questionList: {
       type: Array,
       default() {
         return [];
@@ -242,10 +135,6 @@ export default {
       type: String,
       default: "",
     },
-    canSelectQuestion: {
-      type: Boolean,
-      default: true,
-    },
   },
   data() {
     const usersValidator = (rule, value, callback) => {
@@ -265,7 +154,6 @@ export default {
 
     return {
       modalIsShow: false,
-      SCORE_POLICY_TYPE,
       filterLabel: "",
       userType: "org",
       courseUsers: [],
@@ -274,9 +162,6 @@ export default {
       userList: [],
       selectedUsers: [],
       selectedUserIds: [],
-      selectedQuestions: [],
-      selectedQuestionNos: [],
-      paperStructs: [],
       userOrgKeys: [],
       defaultProps: {
         children: "children",
@@ -298,35 +183,9 @@ export default {
           },
         ],
       },
-      instRow: {},
-      rowInfo: {},
-      rowInfoRules: {
-        doubleRate: [
-          {
-            required: true,
-            message: "双评比例必填",
-            trigger: "change",
-          },
-        ],
-        arbitrateThreshold: [
-          {
-            required: true,
-            message: "仲裁阀值必填",
-            trigger: "change",
-          },
-        ],
-        scorePolicy: [
-          {
-            required: true,
-            message: "合分策略必选",
-            trigger: "change",
-          },
-        ],
-      },
     };
   },
   computed: {
-    ...mapState("markParam", ["openDoubleMarking"]),
     isEdit() {
       return !this.instance.isNew;
     },
@@ -340,29 +199,13 @@ export default {
   },
   methods: {
     visibleChange() {
-      this.parseStructs();
       this.filterLabel = "";
       this.userType = "org";
-      this.selectedQuestions = this.instance.questions;
-      this.selectedQuestionNos = this.selectedQuestions.map((item) => item.id);
       this.selectedUsers = this.instance.markers.map((item) => {
         return { ...item, id: item.userId };
       });
       this.selectedUserIds = this.instance.markers.map((item) => item.userId);
       this.labelChange();
-      this.rowInfo = this.$objAssign(
-        {
-          doubleEnable: false,
-          doubleRate: null,
-          arbitrateThreshold: null,
-          scorePolicy: "AVG",
-        },
-        this.instance
-      );
-      this.rowInfo.doubleRate = this.rowInfo.doubleRate || undefined;
-      this.rowInfo.arbitrateThreshold =
-        this.rowInfo.arbitrateThreshold || undefined;
-      this.instRow = { ...this.rowInfo };
     },
     cancel() {
       this.modalIsShow = false;
@@ -371,10 +214,6 @@ export default {
     open() {
       this.modalIsShow = true;
     },
-    doubleEnableChange() {
-      this.rowInfo.arbitrateThreshold = undefined;
-      this.rowInfo.doubleRate = undefined;
-    },
     // user
     switchUserType(type) {
       this.filterLabel = "";
@@ -524,11 +363,6 @@ export default {
       this.$refs.UserTree.setCheckedKeys(this.selectedUserIds);
       this.$refs.modalFormRef.validateField("users");
     },
-    updateSelectedUsersFromUserIds() {
-      this.selectedUsers = this.userList.filter((user) =>
-        this.selectedUserIds.includes(user.id)
-      );
-    },
     userChange(checked, user) {
       if (checked) {
         this.selectedUsers.push(user);
@@ -547,126 +381,12 @@ export default {
       this.$refs.UserTree.setCheckedKeys(this.selectedUserIds);
       this.$refs.modalFormRef.validateField("users");
     },
-    // question
-    parseStructs() {
-      this.selectedQuestionNos = this.instance.questions.map((q) => q.qno);
-      let paperStructs = [];
-      let struct = null;
-      this.paperStructure.forEach((item) => {
-        if (item.mainFirstSub) {
-          if (struct) paperStructs.push(struct);
-          struct = {
-            mainTitle: item.mainTitle,
-            mainNumber: item.mainNumber,
-            questionType: item.questionType,
-            selected: false,
-            disabled: false,
-            children: [],
-          };
-        }
-        struct.children.push({
-          ...item,
-          disabled: this.disabledQuestionNos.includes(item.qno),
-          selected: this.selectedQuestionNos.includes(item.qno),
-        });
-      });
-      if (struct) paperStructs.push(struct);
-      paperStructs.forEach((item) => {
-        item.disabled = !item.children.some((elem) => !elem.disabled);
-      });
-      this.paperStructs = paperStructs;
-    },
-    selectQuestionAll(checked, mainItem) {
-      mainItem.children.forEach((q) => {
-        if (!q.disabled) q.selected = checked;
-      });
-      this.questionChange();
-    },
-    updateSelectedQuestions() {
-      let selectedQuestions = [];
-      let selectedQuestionNos = [];
-      this.paperStructs.forEach((s) => {
-        s.children.forEach((q) => {
-          if (q.selected && !q.disabled) {
-            selectedQuestions.push(q);
-            selectedQuestionNos.push(q.qno);
-          }
-        });
-      });
-      this.selectedQuestions = selectedQuestions;
-      this.selectedQuestionNos = selectedQuestionNos;
-    },
-    questionChange() {
-      this.updateSelectedQuestions();
-      this.$refs.modalFormRef.validateField("questions");
-    },
-    getQuestionStruct(questions) {
-      let structs = questions.map((item) => {
-        return {
-          mainNumber: item.mainNumber,
-          subNumber: item.subNumber,
-        };
-      });
-      structs.sort(
-        (a, b) => a.mainNumber - b.mainNumber || a.subNumber - b.subNumber
-      );
-      return structs
-        .map((item) => `${item.mainNumber}_${item.subNumber}`)
-        .join();
-    },
-    equalArr(arr1, arr2) {
-      arr1.sort((a, b) => {
-        return a > b ? -1 : 1;
-      });
-      arr2.sort((a, b) => {
-        return a > b ? -1 : 1;
-      });
-      // console.log(arr1, arr2);
-      return JSON.stringify(arr1) === JSON.stringify(arr2);
-    },
-    checkDataChange() {
-      const fields = ["doubleEnable", "arbitrateThreshold", "doubleRate"];
-      let changed = fields.some(
-        (field) => this.rowInfo[field] !== this.instRow[field]
-      );
-      if (changed) return true;
-
-      const prevQnos = this.instance.questions.map(
-        (item) => `${item.mainNumber}-${item.subNumber}`
-      );
-      const curQnos = this.selectedQuestions.map(
-        (item) => `${item.mainNumber}-${item.subNumber}`
-      );
-      changed = !this.equalArr(prevQnos, curQnos);
-      return changed;
-
-      // const prevUserIds = this.instance.markers.map((item) => item.userId);
-      // const curUserIds = this.selectedUsers.map((item) => item.id);
-      // changed = !this.equalArr(prevUserIds, curUserIds);
-      // return changed;
-    },
     // confirm
     async confirm() {
-      const valid1 = await this.$refs.rowInfoFormRef.validate().catch(() => {});
-      const valid2 = await this.$refs.modalFormRef.validate().catch(() => {});
-      if (!valid1 || !valid2) return;
-
-      if (this.isEdit) {
-        const changed = this.checkDataChange();
-        if (changed) {
-          const confirm = await this.$confirm(
-            `保存后分组关联所有评卷任务都将删除,并生成新的分组任务!`,
-            "提示",
-            {
-              type: "warning",
-            }
-          ).catch(() => {});
-          if (confirm !== "confirm") return;
-        }
-      }
+      const valid = await this.$refs.modalFormRef.validate().catch(() => {});
+      if (!valid) return;
 
-      let datas = Object.assign({}, this.instance, this.rowInfo);
-      datas.markers = this.selectedUsers.map((item) => {
+      const markers = this.selectedUsers.map((item) => {
         return {
           id: item.id,
           userId: item.id,
@@ -675,20 +395,8 @@ export default {
           orgName: item.orgName,
         };
       });
-      datas.questions = this.selectedQuestions.map((item) => {
-        let nitem = { ...item };
-        delete nitem.disabled;
-        delete nitem.selected;
-        return nitem;
-      });
-      // 评卷题目变动时,清空评卷区
-      if (
-        this.getQuestionStruct(this.instance.questions) !==
-        this.getQuestionStruct(datas.questions)
-      ) {
-        datas.pictureConfigs = [];
-      }
-      this.$emit("modified", omit(datas, ["isNew"]));
+      const datas = Object.assign({}, this.instance, { markers });
+      this.$emit("modified", datas);
       this.modalIsShow = false;
     },
   },

+ 106 - 76
src/modules/mark/components/markParam/ModifyMarkParams.vue

@@ -19,16 +19,23 @@
       <button class="el-dialog__headerbtn" @click="cancel"></button>
     </div>
 
-    <div class="mb-4 tab-btns">
-      <el-button
-        v-for="tab in tabs"
-        :key="tab.val"
-        size="medium"
-        :type="curTab == tab.val ? 'primary' : 'default'"
-        :disabled="checkTabValid(tab)"
-        @click="selectMenu(tab.val)"
-        >{{ tab.name }}
-      </el-button>
+    <div v-if="dataReady" class="part-box part-box-pad">
+      <el-steps :active="curStepIndex" align-center finish-status="success">
+        <el-step
+          v-for="(item, ind) in steps"
+          :key="item.val"
+          :status="item.status"
+        >
+          <el-button
+            slot="title"
+            :class="['step-title', { 'is-active': curStepIndex === ind }]"
+            type="text"
+            :disabled="item.disabled"
+            @click="changeStep(ind)"
+            >{{ item.name }}</el-button
+          >
+        </el-step>
+      </el-steps>
     </div>
 
     <div v-if="dataReady">
@@ -49,7 +56,34 @@ import MarkParamGroup from "./MarkParamGroup.vue";
 import MarkParamClass from "./MarkParamClass.vue";
 import MarkParamObjectiveAnswer from "./MarkParamObjectiveAnswer.vue";
 import MarkParamSubjectiveAnswer from "./MarkParamSubjectiveAnswer.vue";
-import { markStructureList, markGroupList } from "../../api";
+import { markStructureList, markSubjectiveList } from "../../api";
+
+const steps = [
+  {
+    name: "第一步:设置试卷结构",
+    val: "structure",
+    disabled: false,
+    status: "process",
+  },
+  {
+    name: "第二步:主观题评卷设置",
+    val: "group",
+    disabled: false,
+    status: "wait",
+  },
+  {
+    name: "第三步:分班阅卷设置",
+    val: "class",
+    disabled: false,
+    status: "wait",
+  },
+  {
+    name: "第四步:客观题标答设置",
+    val: "objective-answer",
+    disabled: false,
+    status: "wait",
+  },
+];
 
 export default {
   name: "modify-mark-params",
@@ -73,46 +107,27 @@ export default {
       modalIsShow: false,
       dataReady: false,
       // step
-      curTab: "structure",
-      tabs: [
-        {
-          name: "试卷结构设置",
-          val: "structure",
-        },
-        {
-          name: "评卷任务设置",
-          val: "group",
-        },
-        {
-          name: "分班阅卷设置",
-          val: "class",
-        },
-        {
-          name: "客观题标答设置",
-          val: "objective-answer",
-        },
-        {
-          name: "主观题标答设置",
-          val: "subjective-answer",
-        },
-      ],
-      current: 0,
+      steps,
+      curStepIndex: 0,
       questionSubmit: false,
     };
   },
   computed: {
     ...mapState("markParam", ["openMarkClass"]),
     currentComponent() {
-      return `mark-param-${this.curTab}`;
+      return `mark-param-${this.curStep.val}`;
+    },
+    curStep() {
+      return this.steps[this.curStepIndex];
     },
     isFirstStep() {
-      return this.current === 0;
+      return this.curStepIndex === 0;
     },
     isLastStep() {
-      return this.current === this.lastStep;
+      return this.curStepIndex === this.lastStep;
     },
     lastStep() {
-      return this.tabs.length - 1;
+      return this.steps.length - 1;
     },
   },
   methods: {
@@ -120,9 +135,10 @@ export default {
       "setBasicInfo",
       "setPaperStructureInfo",
       "setStructureCanEdit",
-      "setGroupInfo",
-      "setOpenMarkClass",
+      "setSubjectiveTaskList",
+      "setOpenMergeMarker",
       "setOpenDoubleMarking",
+      "setOpenMarkClass",
       "initStore",
     ]),
     async initData() {
@@ -130,7 +146,6 @@ export default {
       const params = {
         examId: this.instance.examId,
         paperNumber: this.instance.paperNumber,
-        paperType: this.instance.paperType,
       };
 
       // structure
@@ -150,38 +165,67 @@ export default {
       this.setPaperStructureInfo(questions || []);
       this.setStructureCanEdit(structRes.canCreate);
       this.questionSubmit = structRes.questionSubmit;
+      if (questions && questions.length) {
+        // TODO:这里的判断需要调整
+        this.curStepIndex = 1;
+      }
       // group
-      const groupRes = await markGroupList(params);
-      if (groupRes.groups && groupRes.groups.length) {
-        groupRes.groups.forEach((item) => {
-          item.questions.forEach((q) => {
-            q.qno = `${q.mainNumber}-${q.subNumber}`;
-          });
-        });
+      const subjectRes = await markSubjectiveList(params);
+      this.setSubjectiveTaskList(subjectRes.questionsList || []);
+      this.setOpenMergeMarker(!!subjectRes.openMergeMarker);
+      this.setOpenDoubleMarking(!!subjectRes.openDoubleMarking);
+      this.setOpenMarkClass(!!subjectRes.openMarkClass);
+      if (subjectRes.questionsList && subjectRes.questionsList.length) {
+        // TODO:这里的判断需要调整
+        this.curStepIndex = 2;
       }
-      this.setGroupInfo(groupRes.groups || []);
-      this.setOpenMarkClass(!!groupRes.openMarkClass);
-      this.setOpenDoubleMarking(!!groupRes.openDoubleMarking);
 
-      this.selectMenu("structure");
+      this.initSteps();
       this.dataReady = true;
     },
-    checkTabValid(tab) {
-      return (
-        (!this.questionSubmit && tab.val !== "structure") ||
-        (tab.val === "class" && !this.openMarkClass)
-      );
+    initSteps() {
+      this.steps = steps.map((step, index) => {
+        step.status =
+          index === this.curStepIndex
+            ? "process"
+            : index < this.curStepIndex
+            ? "success"
+            : "wait";
+        step.disabled = step.status === "wait";
+        return step;
+      });
+    },
+    changeStep(ind) {
+      if (ind === this.curStepIndex) return;
+      this.curStepIndex = ind;
     },
-    selectMenu(val) {
-      this.curTab = val;
-      this.current = this.tabs.findIndex((item) => item.val === val);
+    confirm() {
+      if (this.isLastStep && this.curStep.status === "process") {
+        this.close();
+        return;
+      }
+
+      this.steps[this.curStepIndex].status = "success";
+      if (
+        this.curStepIndex !== this.steps.length - 1 &&
+        this.steps[this.curStepIndex + 1].status === "wait"
+      ) {
+        this.curStepIndex += 1;
+        this.steps[this.curStepIndex].status = "process";
+      }
+
+      this.steps.forEach((item) => {
+        item.disabled = item.status === "wait";
+      });
     },
     async cancel() {
       const res = await this.$confirm("确定要退出阅卷参数编辑吗?", "提示", {
         type: "warning",
       }).catch(() => {});
       if (res !== "confirm") return;
-
+      this.close();
+    },
+    close() {
       this.initStore();
       this.dataReady = false;
       this.$emit("modified");
@@ -190,20 +234,6 @@ export default {
     open() {
       this.modalIsShow = true;
     },
-    confirm() {
-      if (this.isLastStep) {
-        this.selectMenu(this.tabs[0].val);
-      } else {
-        if (this.curTab === "structure") {
-          this.questionSubmit = true;
-        }
-        if (this.curTab === "group" && !this.openMarkClass) {
-          this.selectMenu(this.tabs[this.current + 2].val);
-        } else {
-          this.selectMenu(this.tabs[this.current + 1].val);
-        }
-      }
-    },
   },
 };
 </script>

+ 158 - 0
src/modules/mark/components/markParam/ModifyMarkType.vue

@@ -0,0 +1,158 @@
+<template>
+  <el-dialog
+    class="modify-mark-type"
+    :visible.sync="modalIsShow"
+    append-to-body
+    top="10vh"
+    width="600px"
+    title="评卷方式设置"
+    :close-on-click-modal="false"
+    :close-on-press-escape="false"
+    :show-close="false"
+    @opened="visibleChange"
+  >
+    <el-form
+      ref="modalFormRef"
+      :model="modalForm"
+      :rules="rules"
+      label-width="100px"
+    >
+      <el-form-item label="评卷方式:">
+        <el-radio-group
+          v-model="modalForm.doubleEnable"
+          @change="doubleEnableChange"
+        >
+          <el-radio :label="false">单评</el-radio>
+          <el-radio v-if="openDoubleMarking" :label="true">双评</el-radio>
+        </el-radio-group>
+      </el-form-item>
+      <template v-if="modalForm.doubleEnable">
+        <el-form-item label="仲裁阈值:" prop="arbitrateThreshold">
+          <el-input-number
+            v-model="modalForm.arbitrateThreshold"
+            class="width-80"
+            size="small"
+            :min="0"
+            :max="999999"
+            :step="0.01"
+            step-strictly
+            :controls="false"
+          >
+          </el-input-number>
+        </el-form-item>
+        <el-form-item label="合分策略:" prop="scorePolicy">
+          <el-select v-model="modalForm.scorePolicy">
+            <el-option
+              v-for="(val, key) in SCORE_POLICY_TYPE"
+              :key="key"
+              :label="val"
+              :value="key"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="双评比例:" prop="doubleRate">
+          <el-input-number
+            v-model="modalForm.doubleRate"
+            class="width-80"
+            size="small"
+            :min="1"
+            :max="100"
+            :step="1"
+            step-strictly
+            :controls="false"
+          >
+          </el-input-number>
+          <span style="margin-left: 5px">%</span>
+        </el-form-item>
+      </template>
+    </el-form>
+
+    <div slot="footer">
+      <el-button type="primary" @click="confirm">确认</el-button>
+      <el-button @click="cancel">取消</el-button>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import { SCORE_POLICY_TYPE } from "@/constants/enumerate";
+import { mapState } from "vuex";
+
+const initModalForm = {
+  doubleEnable: false,
+  doubleRate: null,
+  arbitrateThreshold: null,
+  scorePolicy: "AVG",
+};
+
+export default {
+  name: "modify-mark-type",
+  props: {
+    instance: {
+      type: Object,
+      default() {
+        return {};
+      },
+    },
+  },
+  data() {
+    return {
+      modalIsShow: false,
+      SCORE_POLICY_TYPE,
+      modalForm: {},
+      rules: {
+        doubleRate: [
+          {
+            required: true,
+            message: "双评比例必填",
+            trigger: "change",
+          },
+        ],
+        arbitrateThreshold: [
+          {
+            required: true,
+            message: "仲裁阀值必填",
+            trigger: "change",
+          },
+        ],
+        scorePolicy: [
+          {
+            required: true,
+            message: "合分策略必选",
+            trigger: "change",
+          },
+        ],
+      },
+    };
+  },
+  computed: {
+    ...mapState("markParam", ["openDoubleMarking"]),
+  },
+  methods: {
+    visibleChange() {
+      this.modalForm = this.$objAssign(initModalForm, this.instance);
+      this.modalForm.doubleRate = this.modalForm.doubleRate || undefined;
+      this.modalForm.arbitrateThreshold =
+        this.modalForm.arbitrateThreshold || undefined;
+    },
+    cancel() {
+      this.modalIsShow = false;
+    },
+    open() {
+      this.modalIsShow = true;
+    },
+    doubleEnableChange() {
+      this.modalForm.arbitrateThreshold = undefined;
+      this.modalForm.doubleRate = undefined;
+    },
+    // confirm
+    async confirm() {
+      const valid = await this.$refs.modalFormRef.validate().catch(() => {});
+      if (!valid) return;
+
+      this.$emit("modified", Object.assign({}, this.instance, this.modalForm));
+      this.modalIsShow = false;
+    },
+  },
+};
+</script>

+ 40 - 5
src/modules/mark/components/markParam/store.js

@@ -1,11 +1,29 @@
 const state = {
-  basicInfo: {},
+  // 基本信息
+  basicInfo: {
+    // "examId": "考试ID",
+    // "courseCode": "课程代码",
+    // "courseName": "课程名称",
+    // "paperNumber": "试卷编号",
+    // "groupStatus": true,
+    // "markMode": "评卷模式",
+    // "cardId":"题卡ID"
+  },
+  // 试卷结构是否可编辑
   structureCanEdit: false,
+  // 试卷结构
   paperStructureInfo: [],
-  groupInfo: [],
+  // 主观题任务列表
+  subjectiveTaskList: [],
+  // 是否开启分班阅
   openMarkClass: false,
+  // 填空题是否合并设置评卷员
+  openMergeMarker: false,
+  // 是否开启双评
   openDoubleMarking: false,
+  // 分班阅卷班级信息
   classInfo: [],
+  // 客观题结构
   objectiveStructure: [],
 };
 
@@ -19,12 +37,27 @@ const mutations = {
   setStructureCanEdit(state, structureCanEdit) {
     state.structureCanEdit = structureCanEdit;
   },
-  setGroupInfo(state, groupInfo) {
-    state.groupInfo = groupInfo;
+  setSubjectiveTaskList(state, subjectiveTaskList) {
+    state.subjectiveTaskList = subjectiveTaskList;
+  },
+  updateSubjectiveTaskItem(state, subjectiveTaskItem) {
+    const pos = state.subjectiveTaskList.findIndex(
+      (item) => item.questionId === subjectiveTaskItem.questionId
+    );
+    if (pos === -1) return;
+
+    state.subjectiveTaskList.splice(
+      pos,
+      1,
+      Object.assign({}, state.subjectiveTaskList[pos], subjectiveTaskItem)
+    );
   },
   setOpenMarkClass(state, openMarkClass) {
     state.openMarkClass = openMarkClass;
   },
+  setOpenMergeMarker(state, openMergeMarker) {
+    state.openMergeMarker = openMergeMarker;
+  },
   setOpenDoubleMarking(state, openDoubleMarking) {
     state.openDoubleMarking = openDoubleMarking;
   },
@@ -38,8 +71,10 @@ const mutations = {
     state.basicInfo = {};
     state.structureCanEdit = false;
     state.paperStructureInfo = [];
-    state.groupInfo = [];
+    state.subjectiveTaskList = [];
     state.openMarkClass = false;
+    state.openMergeMarker = false;
+    state.openDoubleMarking = false;
     state.classInfo = [];
     state.objectiveStructure = [];
   },