瀏覽代碼

feat: 批量打分

zhangjie 1 月之前
父節點
當前提交
6f5b531252

+ 12 - 0
src/api.js

@@ -370,6 +370,18 @@ export const paperLeaderSelectScore = (workId, paperId, score, stage) => {
 export const paperSelectLevelBatch = (taskIds, result, stage) => {
   return $patch(`/api/marktasks/batch`, { taskIds, result, stage }, "json");
 };
+export const paperSelectScoreBatch = (
+  taskIds,
+  result,
+  stage,
+  manualScore = 0
+) => {
+  return $patch(
+    `/api/marktasks/batch`,
+    { taskIds, result, stage, manualScore },
+    "json"
+  );
+};
 export const paperTaskPass = (taskId) => {
   return $post(`/api/marktasks/${taskId}/skip`, {});
 };

+ 4 - 1
src/assets/styles/marker.less

@@ -709,8 +709,11 @@
 
   .ribbon-list {
     font-size: 0;
-    text-align: right;
     height: 30px;
+
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
   }
 
   .ribbon-item {

+ 17 - 0
src/modules/grading/components/GradeRibbon.vue

@@ -1,6 +1,16 @@
 <template>
   <div class="grade-ribbon">
     <div class="ribbon-list">
+      <div
+        v-if="ribbonSet.listHandleRefresh"
+        class="ribbon-item"
+        title="刷新"
+        @click="toRefresh"
+      >
+        <Icon type="md-refresh" />
+      </div>
+      <div v-else></div>
+
       <div class="ribbon-item" title="设置" @click="toSet">
         <Icon type="md-settings" />
       </div>
@@ -12,6 +22,7 @@
 </template>
 
 <script>
+import { mapState } from "vuex";
 import RibbonSetDialog from "./RibbonSetDialog";
 
 export default {
@@ -22,6 +33,9 @@ export default {
   data() {
     return {};
   },
+  computed: {
+    ...mapState("marker", ["ribbonSet"]),
+  },
   methods: {
     toNotice() {
       this.$refs.NoticeDialog.open();
@@ -29,6 +43,9 @@ export default {
     toSet() {
       this.$refs.RibbonSetDialog.open();
     },
+    toRefresh() {
+      this.$emit("on-refresh");
+    },
   },
 };
 </script>

+ 1 - 1
src/modules/grading/components/RibbonSetDialog.vue

@@ -10,7 +10,7 @@
       ref="modalFormComp"
       class="ribbon-set-form"
       :model="ribbonSetModal"
-      :label-width="160"
+      :label-width="170"
     >
       <FormItem label="显示快捷档位导航">
         <i-switch v-model="ribbonSetModal.fastLevelNav"></i-switch>

+ 16 - 5
src/modules/grading/marker/MarkerGrading.vue

@@ -15,7 +15,7 @@
         'marker-action',
         { 'marker-action-fullscreen': isFullscreenMarking },
       ]"
-      v-show="!multipleGradingList.length"
+      v-show="!isMultipleSelection"
     >
       <grade-action
         :cur-paper-or-task="curPaper"
@@ -27,10 +27,13 @@
         ref="GradeAction"
         v-if="curPaper.id"
       ></grade-action>
-      <grade-ribbon ref="GradeRibbon"></grade-ribbon>
+      <grade-ribbon
+        ref="GradeRibbon"
+        @on-refresh="toRefreshPage"
+      ></grade-ribbon>
     </div>
     <!-- multiple grading action -->
-    <div class="marker-action" v-show="multipleGradingList.length">
+    <div class="marker-action" v-show="isMultipleSelection">
       <div class="grade-action">
         <div class="action-paper-state">
           <p class="paper-state-cont">批量分档</p>
@@ -58,7 +61,7 @@
         </div>
       </div>
     </div>
-
+    <!-- marker body -->
     <div
       :class="['marker-body', { 'marker-body-low': ribbonSet.fastLevelNav }]"
     >
@@ -79,8 +82,8 @@
             <marker-image-view
               :data="paper"
               @to-review="toReview(index)"
+              @to-switch="toSwitch(index)"
               @to-select="selectMultiplePaper"
-              @to-switch="selectPaper(index)"
             ></marker-image-view>
           </div>
         </div>
@@ -485,6 +488,10 @@ export default {
       this.selectPaper(this.curPaperIndex);
     },
     // paper view action
+    toSwitch(index) {
+      this.clearMultiplePaper();
+      this.selectPaper(index);
+    },
     toReview(index) {
       this.isFullscreenMarking = true;
       this.clearMultiplePaper();
@@ -591,6 +598,10 @@ export default {
       await paperTaskPass(this.curPaper.id);
       this.toActionNextPaper(true);
     },
+    async toRefreshPage() {
+      await this.getList();
+      this.selectPaper(0);
+    },
     // paper carousel
     toViewCarouselPaper(paperIndex, papers, type) {
       this.carouselType = type;

+ 14 - 1
src/modules/grading/marker/MarkerImageView.vue

@@ -26,6 +26,18 @@
         <div v-else class="image-info">
           <div v-if="image.level" class="image-level">{{ image.level }}</div>
           <div v-if="image.score" class="image-level">{{ image.score }}</div>
+          <div
+            v-if="canSelect"
+            :class="[
+              'image-checkbox',
+              {
+                'image-selected': image.selected,
+              },
+            ]"
+            @click="toSelect"
+          >
+            <Icon v-if="image.selected" type="md-checkmark" />
+          </div>
         </div>
         <div
           v-if="IS_LEVEL"
@@ -90,6 +102,7 @@ export default {
       handler() {
         this.initData();
       },
+      deep: true,
     },
   },
   data() {
@@ -147,7 +160,7 @@ export default {
       this.image.mark = !this.image.mark;
     },
     toSelect() {
-      if (this.image.sample || !this.IS_LEVEL) return;
+      if (this.image.sample) return;
       this.image.selected = !this.image.selected;
       this.$emit("to-select", this.image);
     },

+ 2 - 1
src/modules/mark/components/MarkAction.vue

@@ -124,11 +124,12 @@
         :model="manualScoreModel"
         :rules="manualScoreModelRules"
         inline
+        @submit.native.prevent="toInputScore"
       >
         <FormItem prop="score" label="分数" :show-message="false">
           <InputNumber
-            :precision="0"
             v-model="manualScoreModel.score"
+            :precision="0"
           ></InputNumber>
         </FormItem>
         <FormItem class="mark-input-confirm">

+ 1 - 0
src/modules/mark/leader/LeaderMarking.vue

@@ -52,6 +52,7 @@
             <marker-image-view
               :data="paper"
               :stage="stage"
+              :can-select="false"
               @to-review="toReview(index)"
             ></marker-image-view>
           </div>

+ 145 - 2
src/modules/mark/marker/MarkerMarking.vue

@@ -16,6 +16,7 @@
         'marker-action',
         { 'marker-action-fullscreen': isFullscreenMarking },
       ]"
+      v-show="!isMultipleSelection"
     >
       <mark-action
         :cur-paper-or-task="curPaper"
@@ -29,9 +30,42 @@
         ref="GradeAction"
         v-if="curPaper.id"
       ></mark-action>
-      <grade-ribbon ref="GradeRibbon"></grade-ribbon>
+      <grade-ribbon
+        ref="GradeRibbon"
+        @on-refresh="toRefreshPage"
+      ></grade-ribbon>
     </div>
 
+    <!-- multiple grading action -->
+    <div class="marker-action" v-show="isMultipleSelection">
+      <div class="mark-action grade-action">
+        <div class="action-paper-state">
+          <p class="paper-state-cont">批量打分</p>
+        </div>
+        <div class="action-paper-info">
+          <p><span>任务密号:</span><span>--</span></p>
+        </div>
+        <div class="action-mark-list">
+          <div
+            class="action-mark-item"
+            v-for="(score, index) in scores"
+            :key="index"
+          >
+            <div
+              :class="[
+                'action-mark-item-content',
+                { 'action-item-content-disabled': multiplebtnClicked },
+              ]"
+              @click="multipleSelectScore(score)"
+            >
+              <p>{{ score }}</p>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- marker body -->
     <div
       :class="['marker-body', { 'marker-body-low': ribbonSet.fastLevelNav }]"
     >
@@ -53,7 +87,8 @@
               :data="paper"
               :stage="stage"
               @to-review="toReview(index)"
-              @to-switch="selectPaper(index)"
+              @to-switch="toSwitch(index)"
+              @to-select="selectMultiplePaper"
             ></marker-image-view>
           </div>
         </div>
@@ -132,6 +167,7 @@ import {
   markerManualScorePaperList,
   markerMarkPaperList,
   paperTaskPass,
+  paperSelectScoreBatch,
 } from "@/api";
 
 export default {
@@ -187,6 +223,7 @@ export default {
       curPaperIndex: 0,
       paramsSetReady: false,
       cacheUpdateLevelInfos: null,
+      scores: [],
       // multiple grading
       multiplebtnClicked: false,
       multipleGradingList: [],
@@ -277,6 +314,7 @@ export default {
         paper.key = this.$randomCode();
         paper.title = `NO.${paper.sn}`;
         paper.score = paper.result;
+        paper.selected = false;
         return paper;
       });
       this.setPage({
@@ -473,6 +511,107 @@ export default {
       await this.getStepLevels();
       this.toPage(1);
     },
+    // selectMultiplePaper
+    selectMultiplePaper(paper) {
+      if (paper.sample) return;
+      const curPaper = this.papers.find((p) => p.id === paper.id);
+      curPaper.selected = paper.selected;
+      if (this.multipleGradingList.length === 0 && paper.selected) {
+        console.log(curPaper);
+
+        this.updateScoreList(curPaper.level);
+      } else if (this.multipleGradingList.length > 1 && paper.selected) {
+        if (this.multipleGradingList.some((p) => p.level !== curPaper.level)) {
+          this.$Message.error("批量打分只能选择同一档的试卷");
+          curPaper.selected = false;
+          return;
+        }
+      }
+      this.multipleGradingList = this.papers.filter((paper) => paper.selected);
+    },
+    clearMultiplePaper() {
+      this.multipleGradingList = [];
+      this.papers.forEach((paper) => {
+        paper.selected = false;
+      });
+    },
+    updateScoreList(level) {
+      let scores = [];
+      const curLevel = this.levels.find((item) => item.name === level);
+      if (curLevel.levelType === "ADMITED") {
+        const { minScore, maxScore, intervalScore } = curLevel;
+        for (let i = minScore; i <= maxScore; i += intervalScore) {
+          scores.push(i);
+        }
+      } else {
+        scores = curLevel.scoreList.split(",").map((item) => item * 1);
+      }
+
+      this.scores = scores;
+    },
+    async multipleSelectScore(score) {
+      if (!this.multipleGradingList.length) return;
+      if (this.multiplebtnClicked) return;
+      this.multiplebtnClicked = true;
+      const multipleGradingListCount = this.multipleGradingList.length;
+      const curPaperlevel = this.multipleGradingList[0].level;
+
+      let result = true;
+      const paperIds = this.multipleGradingList.map((item) => item.id).join();
+      await paperSelectScoreBatch(
+        paperIds, // is taskId
+        score,
+        "SCORE"
+      ).catch(() => {
+        result = false;
+      });
+
+      this.multiplebtnClicked = false;
+      if (!result) return;
+
+      this.updateStepLevel(
+        this.curStep,
+        {
+          curLevel: curPaperlevel,
+          manualScore: 0,
+        },
+        multipleGradingListCount,
+        paperIds
+      );
+
+      if (this.ribbonSet.listHandleRefresh) {
+        this.multipleGradingList.forEach((paper) => {
+          paper.level = score;
+          paper.result = score;
+        });
+        this.clearMultiplePaper();
+        const nextPaperIndex = this.papers.findIndex(
+          (paper) => !paper.score && paper.score !== 0
+        );
+        this.selectPaper(
+          nextPaperIndex === -1 ? this.papers.length - 1 : nextPaperIndex
+        );
+        return;
+      }
+
+      this.clearMultiplePaper();
+      // update paper list
+      if (
+        this.page.current > 1 &&
+        this.page.current === this.page.totalPage &&
+        this.papers.length === multipleGradingListCount
+      ) {
+        this.setPage({ current: this.page.current - 1 });
+      }
+
+      await this.getList();
+      this.selectPaper(this.curPaperIndex);
+    },
+    // select paper
+    toSwitch(index) {
+      this.clearMultiplePaper();
+      this.selectPaper(index);
+    },
     toReview(index) {
       this.isFullscreenMarking = true;
       this.selectPaper(index);
@@ -622,6 +761,10 @@ export default {
       await paperTaskPass(this.curPaper.id);
       this.toActionNextPaper(false, true);
     },
+    async toRefreshPage() {
+      await this.getList();
+      this.selectPaper(0);
+    },
     // paper carousel
     toViewCarouselPaper(paperIndex, papers, type) {
       this.carouselType = type;