Jelajahi Sumber

leaderGrading over

zhangjie 3 tahun lalu
induk
melakukan
a73e655d96

+ 15 - 0
src/assets/styles/base.less

@@ -269,6 +269,21 @@ h2.part-box-head-left {
       padding-right: 18px;
     }
   }
+
+  &.table-dark {
+    tr {
+      background-color: @color-background-light;
+      td,
+      th {
+        color: @color-text;
+        padding: 8px 15px;
+      }
+      .td-nopad {
+        padding-left: 0;
+        padding-right: 0;
+      }
+    }
+  }
 }
 .table .td-th {
   font-weight: 600;

+ 4 - 2
src/assets/styles/mark.less

@@ -830,8 +830,10 @@
         float: left;
       }
       p:last-child {
-        padding: 0 8px;
-        border-radius: 8px;
+        min-width: 26px;
+        padding: 0 5px;
+        text-align: center;
+        border-radius: 5px;
         background-color: @white;
         font-size: 14px;
         float: right;

+ 92 - 15
src/assets/styles/marker.less

@@ -311,6 +311,9 @@
     z-index: 10000;
   }
 
+  .action-search {
+    border-top: 1px dashed @color-text;
+  }
   .action-paper-state {
     color: @color-text;
     .paper-state-cont {
@@ -324,6 +327,10 @@
       color: @color-text-act;
     }
   }
+  .action-grade-change {
+    background-color: @color-background;
+    color: @color-text;
+  }
   .action-grade-info {
     background-color: @color-act1;
     color: @color-text;
@@ -350,6 +357,17 @@
     background: shade(@color-background-light, 30%) !important;
     color: @color-background-light!important;
   }
+  .action-grade-history {
+    .grade-history-item {
+      background-color: @color-background;
+      color: @color-text;
+
+      p:last-child {
+        background-color: @color-act1;
+        color: @color-text-act;
+      }
+    }
+  }
   .action-grade-pass {
     background: @color-background;
     color: @color-text;
@@ -358,6 +376,43 @@
       background-color: shade(@color-background, 20%);
     }
   }
+
+  // element-ui
+  .ivu-btn-primary {
+    color: @color-text;
+    background-color: @color-act1;
+    border-color: @color-act1;
+
+    &:hover {
+      background-color: shade(@color-act1, 10%);
+      border-color: shade(@color-act1, 10%);
+      color: @color-text-act;
+    }
+  }
+  .ivu-input {
+    background-color: @color-background!important;
+    border-color: @color-background;
+    color: @color-text;
+    box-shadow: none !important;
+  }
+  .ivu-select-selection {
+    background-color: @color-background;
+    color: @color-text;
+    border-color: @color-background;
+  }
+  .ivu-select-dropdown {
+    background-color: @color-background;
+    color: @color-text;
+
+    .ivu-select-item {
+      color: @color-text;
+      border-top: 1px solid @color-background-light;
+      &:hover,
+      &-focus {
+        background-color: @color-act1;
+      }
+    }
+  }
 }
 
 // marker-history
@@ -369,6 +424,10 @@
     height: 26px;
     padding-left: 5px;
   }
+  .ivu-modal {
+    width: 100% !important;
+    top: 0 !important;
+  }
 }
 .history-image-list {
   height: 360px;
@@ -424,16 +483,6 @@
 // marker-statistics
 .marker-statistics {
   color: @color-text;
-  &-table {
-    tr {
-      background-color: @color-background-light;
-      td,
-      th {
-        color: @color-text;
-        padding: 8px 15px;
-      }
-    }
-  }
   &-chart {
     > h3 {
       font-size: 16px;
@@ -537,17 +586,33 @@
   }
 }
 
+// leader-progress
+.leader-progress {
+  .ivu-modal {
+    width: 600px !important;
+  }
+  .progress-line {
+    color: @color-text;
+    background-color: tint(@color-background, 5%);
+
+    .progress-rate {
+      background-color: @color-act1;
+      color: @color-text-act;
+    }
+  }
+}
+
+// custom element ui ----------------->
 // marker-modal
 .marker-modal {
+  color: @color-text;
   .ivu-modal-mask {
-    background-color: rgba(55, 55, 55, 0.8);
-  }
-  .ivu-modal {
-    width: 100% !important;
-    top: 0 !important;
+    background-color: rgba(55, 55, 55, 0.6);
   }
+
   .ivu-modal-content {
     background-color: @color-background;
+    border-radius: 0;
   }
   .ivu-modal-header {
     border-color: @color-background-light;
@@ -591,3 +656,15 @@
     box-shadow: 0 1px 10px rgba(0, 0, 0, 0.5);
   }
 }
+// btn
+.marker-btn-primary {
+  color: @color-text;
+  background-color: @color-act1;
+  border-color: @color-act1;
+
+  &:hover {
+    background-color: shade(@color-act1, 10%);
+    border-color: shade(@color-act1, 10%);
+    color: @color-text-act;
+  }
+}

+ 9 - 9
src/constants/authority.js

@@ -187,14 +187,14 @@ export const inspection = [
   }
 ];
 
-const getLeadRouter = () => {
-  let leadGrade = grading.map(item => item.name);
-  leadGrade.splice(3, 2);
-  let leadMark = mark.map(item => item.name);
-  leadMark.splice(1, 1);
-  leadMark.splice(2, 1);
-  return [...leadGrade, ...leadMark];
-};
+// const getLeadRouter = () => {
+//   let leadGrade = grading.map(item => item.name);
+//   leadGrade.splice(3, 2);
+//   let leadMark = mark.map(item => item.name);
+//   leadMark.splice(1, 1);
+//   leadMark.splice(2, 1);
+//   return [...leadGrade, ...leadMark];
+// };
 
 const getAdminRouter = isSuper => {
   let leadGrade = grading.map(item => item.name).slice(0, -1);
@@ -216,7 +216,7 @@ export const checkRouterValid = (roleCode, routerName) => {
     SUPER_ADMIN: () => getAdminRouter(1),
     ADMIN: getAdminRouter,
     MARKER: () => ["GradingOperation", "MarkOperation", "MarkerGrading"],
-    MARK_LEADER: getLeadRouter,
+    MARK_LEADER: () => ["LeaderGrading", "leaderMark"],
     INSPECTION: () => inspection.map(item => item.name),
     QC: () => ["Quality"]
   };

+ 183 - 143
src/modules/grading/leader/LeaderGrading.vue

@@ -4,8 +4,10 @@
       @area-change="areaChange"
       @step-change="stepChange"
       @page-set-change="pageSetChange"
+      @to-progress="toProgress"
       @to-history="toHistory"
       @to-standard="toStandard"
+      @to-statistics="toStatistics"
     ></marker-header>
 
     <div
@@ -19,8 +21,8 @@
         :cur-paper-or-task="curPaper"
         :levels="levels"
         :params-set="paramsSet"
-        @on-select-level="gradeCurPaper"
-        @on-pass="passCurPaper"
+        @on-leader-level="leaderSelectLevel"
+        @on-code-search="serachPaperByCode"
         ref="GradeAction"
         v-if="curPaper.id"
       ></grade-action>
@@ -29,7 +31,7 @@
     <div class="marker-action" v-show="multipleGradingList.length">
       <div class="grade-action">
         <div class="action-paper-state">
-          <p class="paper-state-cont">批量分档</p>
+          <p class="paper-state-cont">批量操作</p>
         </div>
         <div class="action-paper-info">
           <p><span>任务密号:</span><span>--</span></p>
@@ -79,6 +81,13 @@
       <div v-else class="marker-image-none">暂无数据</div>
     </div>
 
+    <!-- LeaderStatistics -->
+    <leader-statistics
+      :question-id="filter.questionId"
+      ref="LeaderStatistics"
+    ></leader-statistics>
+    <!-- LeaderProgress -->
+    <leader-progress ref="LeaderProgress"></leader-progress>
     <!-- MarkerHistory -->
     <marker-history
       :question-id="filter.questionId"
@@ -101,6 +110,13 @@
       ref="MarkerStandard"
       v-if="levels.length && filter.questionId && paramsSet.showSample"
     ></marker-standard>
+    <!-- modify-leader-grading -->
+    <modify-leader-grading
+      :level-info="levelInfo"
+      :markers="markers"
+      @modified="leaderGradingSuccess"
+      ref="ModifyLeaderGrading"
+    ></modify-leader-grading>
     <!-- image-preview -->
     <simple-image-preview
       class="grading-operation-image-preview"
@@ -110,7 +126,6 @@
       @on-close="isFullscreenMarking = false"
       ref="SimpleImagePreview"
     ></simple-image-preview>
-
     <!-- carousel paper review -->
     <simple-image-preview
       class="grading-operation-image-preview"
@@ -125,21 +140,25 @@
 
 <script>
 import { mapState, mapMutations } from "vuex";
-import MarkerHeader from "./MarkerHeader";
-import MarkerImageView from "./MarkerImageView";
-import MarkerHistory from "./MarkerHistory";
-import MarkerStandard from "./MarkerStandard";
+import MarkerHeader from "../marker/MarkerHeader";
+import MarkerImageView from "../marker/MarkerImageView";
+import MarkerHistory from "../marker/MarkerHistory";
+import MarkerStandard from "../marker/MarkerStandard";
+import LeaderProgress from "./LeaderProgress";
+import LeaderStatistics from "./LeaderStatistics";
 import GradeAction from "../components/GradeAction";
 import SimpleImagePreview from "@/components/SimpleImagePreview";
+import ModifyLeaderGrading from "../components/ModifyLeaderGrading";
 
 import {
-  markerTaskList,
-  markerLevelTotalStatData,
+  paperList,
+  levelStatData,
   workLevelList,
-  paperSelectLevelOrScore,
-  paperSelectLevelBatch,
-  paperTaskPass,
-  getParamsSet
+  taskSnSearch,
+  subjectDetail,
+  markHistoryList,
+  getParamsSet,
+  leaderGradingPaper
 } from "@/api";
 
 export default {
@@ -149,58 +168,62 @@ export default {
     MarkerImageView,
     MarkerHistory,
     MarkerStandard,
+    LeaderProgress,
+    LeaderStatistics,
     GradeAction,
-    SimpleImagePreview
+    SimpleImagePreview,
+    ModifyLeaderGrading
   },
   data() {
     return {
       filter: {
-        markerId: this.$ls.get("user").id,
         questionId: "",
-        sort: "randomSeq,asc",
-        stage: "LEVEL"
+        sort: "secretNumber"
       },
       typeFilter: {
         done: {
           level: ""
         },
-        undo: {},
         reject: {
           reject: true
+        },
+        arbitrate: {
+          arbi: true
         }
       },
       workId: this.$route.params.workId,
       subjectId: this.$route.params.subjectId,
-      subject: "",
-      workSubject: {},
-      curStandardGradeId: "",
       levels: [],
-      curArea: {},
       papers: [],
       curPaper: {},
       curPaperIndex: 0,
-      // multiple grading
-      multiplebtnClicked: false,
-      multipleGradingList: [],
+      // leader-grade
+      levelInfo: {},
+      markers: [],
       // carousel paper review,
       carouselType: "",
       carouselPapers: [],
       curCarouselPaperIndex: 0,
-      isFullscreenMarking: false
+      isFullscreenMarking: false,
+      // multiple grading
+      multiplebtnClicked: false,
+      multipleGradingList: []
     };
   },
   computed: {
-    ...mapState("marker", ["paramsSet", "page", "steps", "curStep"]),
+    ...mapState("marker", [
+      "paramsSet",
+      "page",
+      "steps",
+      "curStep",
+      "curArea",
+      "curSubject"
+    ]),
     markerImageListClasses() {
       return ["marker-image-list", `marker-image-list-${this.page.size}`];
     }
   },
   created() {
-    this.subject = this.subjectId.split("-")[1];
-    this.workSubject = {
-      workId: this.workId,
-      subject: this.subject
-    };
     this.initData();
   },
   methods: {
@@ -208,36 +231,41 @@ export default {
       "setParamSet",
       "setPage",
       "setSteps",
-      "setCurStep"
+      "setCurStep",
+      "setCurArea",
+      "setCurSubject",
+      "clearState"
     ]),
     async initData() {
       await this.getParamsSetInfo();
+      await this.getSubjectDetail();
       await this.getWorkLevels();
     },
     async getParamsSetInfo() {
       const data = await getParamsSet(this.workId);
       this.setParamSet(data || {});
     },
+    async getSubjectDetail() {
+      const curSubject = await subjectDetail(this.subjectId);
+      this.setCurSubject(curSubject || {});
+    },
     async getList() {
       this.multipleGradingList = [];
       const datas = {
         ...this.filter,
         ...this.typeFilter[this.curStep.type],
-        workId: this.workId,
         page: this.page.current - 1,
         size: this.page.size
       };
-      if (this.curStep.type === "done") {
-        datas.level = this.curStep.name;
-        datas.sort = "updatedOn,desc";
-      }
+      if (this.curStep.type === "done") datas.level = this.curStep.name;
 
-      const data = await markerTaskList(datas);
+      const data = await paperList(datas);
       this.papers = data.data.map(paper => {
         paper.title = `NO.${paper.sn}`;
         paper.selected = false;
         return paper;
       });
+
       this.setPage({
         total: data.totalCount,
         totalPage: data.pageCount
@@ -251,34 +279,38 @@ export default {
       this.selectPaper(this.curPaperIndex);
     },
     async getStepLevels() {
-      const data = await markerLevelTotalStatData(
-        this.filter.markerId,
-        this.filter.questionId
-      );
+      const data = await levelStatData(this.subjectId, this.filter.questionId);
       const undoIndex = data.findIndex(item => item.id === null);
       let otherStep = [];
       let undo = {
         count: 0,
-        rejected: 0
+        rejected: 0,
+        arbitrated: 0
       };
       if (undoIndex !== -1) {
         undo = { ...data[undoIndex] };
         data.splice(undoIndex, 1);
       }
 
-      otherStep.push({
-        name: "待评",
-        count: undo.count,
-        type: "undo"
-      });
+      if (this.IS_MARK_LEADER && this.IS_TEST) {
+        otherStep.push({
+          name: "待评",
+          count: undo.count,
+          type: "undo"
+        });
+      }
       otherStep.push({
         name: "打回",
         count: undo.rejected,
         type: "reject"
       });
+      otherStep.push({
+        name: "仲裁",
+        count: undo.arbitrated,
+        type: "arbitrate"
+      });
+
       let levelStep = data.map(item => {
-        // 评卷员不展示kdpt
-        item.kdpt = null;
         return {
           ...item,
           name: item.id,
@@ -288,13 +320,7 @@ export default {
       this.setSteps({ levelStep, otherStep });
 
       if (!this.curStep.name) {
-        let curStep = {};
-        if (undoIndex === -1) {
-          curStep = levelStep[0];
-        } else {
-          curStep = otherStep[0];
-        }
-        this.setCurStep(curStep);
+        this.setCurStep(levelStep[0]);
       } else {
         const curStep = [...levelStep, ...otherStep].find(
           item => item.name === this.curStep.name
@@ -302,32 +328,6 @@ export default {
         this.setCurStep(curStep);
       }
     },
-    updateStepLevel(curStep, curLevel, count) {
-      if (curStep.type === "done") {
-        const lpos = this.steps.levelStep.findIndex(
-          item => item.name === curStep.name
-        );
-        this.steps.levelStep[lpos].count -= count;
-      } else {
-        const opos = this.steps.otherStep.findIndex(
-          item => item.type === curStep.type
-        );
-        this.steps.otherStep[opos].count -= count;
-      }
-
-      const pos = this.steps.levelStep.findIndex(
-        item => item.name === curLevel
-      );
-      this.steps.levelStep[pos].count += count;
-
-      this.steps.levelStep.forEach(item => {
-        item.percent =
-          item.finalKdTotal && item.count
-            ? ((100 * item.count) / item.finalKdTotal).toFixed(3)
-            : 0;
-      });
-      this.setSteps(this.steps);
-    },
     async getWorkLevels() {
       const data = await workLevelList(this.workId);
       this.levels = data.map(item => {
@@ -348,7 +348,7 @@ export default {
       this.setPage({ current: 1 });
       this.isFullscreenMarking = false;
       await this.getList();
-      this.getStepLevels();
+      // this.getStepLevels();
       if (this.papers.length) {
         this.selectPaper(0);
       } else {
@@ -356,7 +356,7 @@ export default {
       }
     },
     async areaChange(curArea) {
-      this.curArea = curArea;
+      this.setCurArea(curArea);
       this.filter.questionId = curArea.id;
       await this.getStepLevels();
       this.toPage(1);
@@ -367,41 +367,32 @@ export default {
       const curPaper = this.papers.find(p => p.id === paper.id);
       curPaper.selected = paper.selected;
       this.multipleGradingList = this.papers.filter(paper => paper.selected);
-      console.log(this.multipleGradingList);
     },
     async multipleSelectLevel(level) {
       if (!this.multipleGradingList.length) return;
       if (this.multiplebtnClicked) return;
+
       this.multiplebtnClicked = true;
-      const multipleGradingListCount = this.multipleGradingList.length;
 
-      let result = true;
-      await paperSelectLevelBatch(
-        this.multipleGradingList.map(item => item.id).join(), // is taskId
-        level.name,
+      const data = await markHistoryList(
+        this.multipleGradingList[0].id,
         "LEVEL"
-      ).catch(() => {
-        result = false;
-      });
-
+      ).catch(() => {});
       this.multiplebtnClicked = false;
-      if (!result) return;
-
-      this.multipleGradingList = [];
-      // this.getStepLevels();
-      this.updateStepLevel(this.curStep, level.name, multipleGradingListCount);
+      if (!data) return;
 
-      // update paper list
-      if (
-        this.current > 1 &&
-        this.current === this.pageCount &&
-        this.papers.length === multipleGradingListCount
-      ) {
-        this.current--;
-      }
-
-      await this.getList();
-      this.selectPaper(this.curPaperIndex);
+      this.markers = data.map(item => {
+        return {
+          id: item.markerId,
+          name: item.marker
+        };
+      });
+      this.levelInfo = {
+        paperIds: this.multipleGradingList.map(item => item.id).join(),
+        curLevel: this.curStep.name,
+        selectedLevel: level.name
+      };
+      this.$refs.ModifyLeaderGrading.open();
     },
     // paper view action
     toReview(index) {
@@ -424,9 +415,9 @@ export default {
     },
     async toPrevPaper() {
       if (this.curPaperIndex === 0) {
-        if (this.current > 1) {
-          this.current--;
-          this.curPaperIndex = this.size - 1;
+        if (this.page.current > 1) {
+          this.setPage({ current: this.page.current - 1 });
+          this.curPaperIndex = this.page.size - 1;
           await this.getList();
         } else {
           this.$Message.warning("当前已经是第一条数据了");
@@ -440,11 +431,11 @@ export default {
     },
     async toNextPaper() {
       if (this.curPaperIndex === this.papers.length - 1) {
-        if (this.current === this.totalPage) {
+        if (this.page.current === this.page.totalPage) {
           this.$Message.warning("当前已经是最后一条数据了");
           return;
         } else {
-          this.current++;
+          this.setPage({ current: this.page.current + 1 });
           this.curPaperIndex = 0;
           await this.getList();
         }
@@ -455,28 +446,79 @@ export default {
       this.selectPaper(this.curPaperIndex);
     },
     async toActionNextPaper() {
-      if (this.current > 1 && this.papers.length === 1) {
-        this.current--;
-        this.curPaperIndex = this.size;
+      if (this.page.current > 1 && this.papers.length === 1) {
+        this.setPage({ current: this.page.current - 1 });
+        this.curPaperIndex = this.page.size;
       }
 
       await this.getList();
       if (!this.papers.length) this.$refs.SimpleImagePreview.cancel();
       this.selectPaper(this.curPaperIndex);
     },
-    async gradeCurPaper(level) {
-      const paper = await paperSelectLevelOrScore(
-        this.curPaper.id, // is taskId
-        level.name,
-        "LEVEL"
+    async serachPaperByCode(params) {
+      const data = await taskSnSearch(
+        params.codeType,
+        params.code,
+        this.filter.questionId
       );
-      if (!paper) return;
-      this.updateStepLevel(this.curStep, level.name, 1);
-      this.toActionNextPaper();
+      if (!data) {
+        this.$Message.error("没有查找到结果!");
+        return;
+      }
+      data.title = `NO.${data.sn}`;
+      this.papers = [data];
+      this.setPage({ current: 1, total: 1, totalPage: 1 });
+      this.selectPaper(0);
     },
-    async passCurPaper() {
-      await paperTaskPass(this.curPaper.id);
-      this.toActionNextPaper();
+    async leaderSelectLevel(levelInfo, markers) {
+      // 唯一权限时,直接操作
+      if (levelInfo.markLeaderOnlyRight && !this.paramsSet.leaderConfirm) {
+        const datas = {
+          action: levelInfo.markLeaderOnlyRight.action,
+          level: levelInfo.selectedLevel,
+          originLevel: levelInfo.curLevel,
+          paperIds: levelInfo.paperIds
+        };
+        if (datas.action === "reject") {
+          datas.range = markers.map(item => item.id).join();
+        }
+        let result = true;
+        const paper = await leaderGradingPaper(datas).catch(() => {
+          result = false;
+        });
+        if (!result) return;
+
+        this.leaderGradingSuccess(datas, paper);
+        return;
+      }
+
+      this.levelInfo = levelInfo;
+      this.markers = markers;
+      this.$refs.ModifyLeaderGrading.open();
+    },
+    async leaderGradingSuccess(datas, paper) {
+      if (datas.action === "sampling" && this.$refs.MarkerStandard) {
+        this.$refs.MarkerStandard.updateLevelPapers(datas.level);
+      }
+      this.getStepLevels();
+
+      if (this.multipleGradingList && this.multipleGradingList.length) {
+        // 批量处理逻辑
+        if (
+          this.page.current > 1 &&
+          this.page.current === this.page.totalPage &&
+          this.papers.length === this.multipleGradingList.length
+        ) {
+          this.setPage({ current: this.page.current - 1 });
+        }
+
+        this.multipleGradingList = [];
+        await this.getList();
+        this.selectPaper(this.curPaperIndex);
+      } else {
+        // 单张处理逻辑
+        this.toActionNextPaper();
+      }
     },
     // paper carousel
     toViewCarouselPaper(paperIndex, papers, type) {
@@ -493,10 +535,6 @@ export default {
       this.curPaper = { ...this.carouselPapers[index] };
     },
     toCarousePaper(type) {
-      // if (this.carouselType === "sample") {
-      //   this.toSampleCarousePaper(type);
-      //   return;
-      // }
       if (type === "prev" && this.curCarouselPaperIndex > 0) {
         this.curCarouselPaperIndex--;
       } else if (
@@ -507,13 +545,6 @@ export default {
       }
       this.selectCarouselPaper(this.curCarouselPaperIndex);
     },
-    toSampleCarousePaper(type) {
-      if (type === "prev") {
-        this.$refs.GradeStandardPaper.$refs.PaperCarousel.handleLeft();
-      } else if (type === "next") {
-        this.$refs.GradeStandardPaper.$refs.PaperCarousel.handleRight();
-      }
-    },
     carouseImagePreviewClose() {
       this.isFullscreenMarking = false;
       this.carouselType = "";
@@ -525,7 +556,16 @@ export default {
     },
     toStandard() {
       this.$refs.MarkerStandard.open();
+    },
+    toProgress() {
+      this.$refs.LeaderProgress.open();
+    },
+    toStatistics() {
+      this.$refs.LeaderStatistics.open();
     }
+  },
+  beforeDestroy() {
+    this.clearState();
   }
 };
 </script>

+ 176 - 0
src/modules/grading/leader/LeaderProgress.vue

@@ -0,0 +1,176 @@
+<template>
+  <Modal
+    v-model="modalIsShow"
+    class="leader-progress marker-modal"
+    title="分档进度"
+    footer-hide
+    fullscreen
+    :transition-names="['slide-left', 'fade']"
+    @on-visible-change="visibleChange"
+  >
+    <div class="leader-progress-part">
+      <h3>总体</h3>
+      <table class="table table-dark">
+        <colgroup>
+          <col width="120" />
+          <col width="390" />
+          <col width="60" />
+        </colgroup>
+        <tr>
+          <th>区域</th>
+          <th>进度</th>
+          <th></th>
+        </tr>
+        <tr v-for="(item, aindex) in areaProgress" :key="aindex">
+          <td>{{ item.areaName }}</td>
+          <td>
+            <progress-line
+              :sum="item.totalCount"
+              :current="item.successCount"
+              :show-count="showPaperRelateCount"
+            ></progress-line>
+          </td>
+          <td class="td-nopad">{{ item.progress }}%</td>
+        </tr>
+      </table>
+    </div>
+
+    <div class="leader-progress-part">
+      <div colspan="3" style="text-align:left">
+        仲裁:{{ kzzInfo.arbitrated }}
+      </div>
+      <table class="table table-dark" v-if="IS_LEVEL && markerProgress.length">
+        <colgroup>
+          <col width="120" />
+          <col width="310" />
+          <col width="60" />
+          <col width="80" />
+        </colgroup>
+        <tr>
+          <th>评卷员</th>
+          <th>进度</th>
+          <th></th>
+          <th>打回</th>
+        </tr>
+        <tr v-for="(item, aindex) in markerProgress" :key="aindex">
+          <td>{{ item.loginName }}</td>
+          <td>
+            <progress-line
+              :sum="item.totalCount"
+              :current="item.successCount"
+              :show-count="showPaperRelateCount"
+            ></progress-line>
+          </td>
+          <td class="td-nopad">{{ item.progress }}%</td>
+          <td>{{ item.rejectedCount }}</td>
+        </tr>
+      </table>
+
+      <table class="table table-dark" v-if="IS_SCORE">
+        <colgroup>
+          <col width="120" />
+          <col width="210" />
+          <col width="60" />
+          <col width="80" />
+          <col width="100" />
+        </colgroup>
+        <tr>
+          <th>评卷员</th>
+          <th>进度</th>
+          <th></th>
+          <th>改档</th>
+          <th>改档打分</th>
+        </tr>
+        <tr v-for="(item, aindex) in markerProgress" :key="aindex">
+          <td>{{ item.loginName }}</td>
+          <td>
+            <progress-line
+              :sum="item.totalCount"
+              :current="item.successCount"
+              :show-count="showPaperRelateCount"
+            ></progress-line>
+          </td>
+          <td>{{ item.progress }}</td>
+          <td>{{ item.shiftCount }}</td>
+          <td>{{ item.shiftScoreCount }}</td>
+        </tr>
+      </table>
+    </div>
+  </Modal>
+</template>
+
+<script>
+import { mapState } from "vuex";
+import { gradingProgressDetail } from "@/api";
+import ProgressLine from "../components/ProgressLine";
+
+export default {
+  name: "leader-progress",
+  components: { ProgressLine },
+  data() {
+    return {
+      modalIsShow: false,
+      kzzInfo: {},
+      totalProgress: {},
+      areaProgress: [],
+      markerProgress: []
+    };
+  },
+  computed: {
+    ...mapState("marker", ["paramsSet", "curSubject"]),
+    IS_LEVEL() {
+      return this.curSubject.stage === "LEVEL";
+    },
+    IS_SCORE() {
+      return this.curSubject.stage === "SCORE";
+    },
+    showPaperRelateCount() {
+      return !!this.paramsSet["showPaperCount"];
+    }
+  },
+  methods: {
+    visibleChange(visible) {
+      if (visible) {
+        this.initData();
+      }
+    },
+    async initData() {
+      const subjectId = this.$route.params.subjectId.split("-");
+      const data = await gradingProgressDetail({
+        workId: subjectId[0],
+        subject: subjectId[1]
+      });
+      this.kzzInfo = data.kzz || {};
+      this.totalProgress = data.totalProgress;
+      const totalInfo = {
+        successCount: data.totalProgress.successCount,
+        totalCount: data.totalProgress.totalCount,
+        progress: data.totalProgress.progress.toFixed(2),
+        areaName: "总体进度"
+      };
+      if (this.curSubject.stage === "INIT") {
+        this.areaProgress = [totalInfo];
+        this.markerProgress = [];
+      } else {
+        this.areaProgress = [totalInfo, ...this.addProgress(data.areaProgress)];
+        this.markerProgress = this.addProgress(data.markerProgress);
+      }
+    },
+    addProgress(data) {
+      return data.map(item => {
+        item.successCount = item.totalCount - item.leftCount;
+        item.progress = item.totalCount
+          ? ((100 * item.successCount) / item.totalCount).toFixed(2)
+          : "0.00";
+        return item;
+      });
+    },
+    cancel() {
+      this.modalIsShow = false;
+    },
+    open() {
+      this.modalIsShow = true;
+    }
+  }
+};
+</script>

+ 163 - 0
src/modules/grading/leader/LeaderStatistics.vue

@@ -0,0 +1,163 @@
+<template>
+  <Modal
+    v-model="modalIsShow"
+    class="leader-statistics marker-modal"
+    title="统计分析"
+    footer-hide
+    fullscreen
+    @on-visible-change="visibleChange"
+  >
+    <div class="part-box-head">
+      <div class="part-box-head-right">
+        <Button
+          class="marker-btn-primary"
+          type="primary"
+          @click="toExport"
+          :load="isDownload"
+          >导出表格</Button
+        >
+      </div>
+    </div>
+    <div class="marker-statistics-table">
+      <table class="table table-dark">
+        <tr>
+          <th>科目</th>
+          <th>档位</th>
+          <th>范围</th>
+          <th>数量</th>
+          <th>占比</th>
+          <th>预设占比</th>
+          <th>差值</th>
+          <th>累计数量</th>
+          <th>累计占比</th>
+          <th>调整</th>
+        </tr>
+        <tr v-for="(level, sindex) in levelData" :key="sindex">
+          <td>{{ level.subjectName }}</td>
+          <td>{{ level.code }}</td>
+          <td>{{ level.minScore }}~{{ level.maxScore }}</td>
+          <td>{{ level.levelCount }}</td>
+          <td>{{ level.levelProp }}%</td>
+          <td>{{ level.examLevelProp }}%</td>
+          <td>{{ level.diffProp }}%</td>
+          <td>{{ level.cumulateCount }}</td>
+          <td>{{ level.cumulateProp }}%</td>
+          <td>{{ level.adjustmentCount }}</td>
+        </tr>
+      </table>
+    </div>
+    <div class="marker-statistics-chart">
+      <h3>数量统计</h3>
+      <echart-render
+        :chart-data="lineChartData"
+        chart-type="darkLine"
+        v-if="lineChartData"
+      ></echart-render>
+    </div>
+
+    <!-- GradeAnalysisExport -->
+    <grade-analysis-export
+      ref="GradeAnalysisExport"
+      :chart-data="renderChartData"
+      :page-info="renderPageInfo"
+      @on-exported="exportOver"
+      v-if="renderExportPage"
+    ></grade-analysis-export>
+  </Modal>
+</template>
+
+<script>
+import { mapState } from "vuex";
+import { gradingStatData } from "@/api";
+import EchartRender from "@/components/EchartRender";
+import GradeAnalysisExport from "../components/GradeAnalysisExport";
+
+export default {
+  name: "leader-statistics",
+  components: { EchartRender, GradeAnalysisExport },
+  props: {
+    questionId: {
+      type: [Number, String],
+      required: true
+    }
+  },
+  data() {
+    return {
+      modalIsShow: false,
+      levelData: [],
+      lineChartData: null,
+      // export
+      renderExportPage: false,
+      renderChartData: {},
+      renderPageInfo: {},
+      isDownload: false
+    };
+  },
+  computed: {
+    ...mapState("marker", ["paramsSet", "curSubject", "curArea"]),
+    showPaperRelateCount() {
+      return !!this.paramsSet["showPaperCount"];
+    }
+  },
+  methods: {
+    visibleChange(visible) {
+      if (visible) {
+        this.initData();
+      } else {
+        this.lineChartData = null;
+      }
+    },
+    async initData() {
+      const subs = this.$route.params.subjectId.split("-");
+      this.levelData = await gradingStatData({
+        questionId: this.questionId,
+        workId: subs[0],
+        subject: subs[1]
+      });
+      this.levelData = this.levelData.map(item => {
+        item.levelCount = this.showPaperRelateCount ? item.levelCount : "";
+        item.cumulateCount = this.showPaperRelateCount
+          ? item.cumulateCount
+          : "";
+        item.adjustmentCount = this.showPaperRelateCount
+          ? item.adjustmentCount
+          : "";
+        return item;
+      });
+
+      this.lineChartData = this.levelData.map(item => {
+        return {
+          name: item.code,
+          value: item.levelProp
+        };
+      });
+    },
+    // export
+    toExport() {
+      this.isDownload = true;
+      this.renderPageInfo = {
+        subjectName: this.curSubject.name,
+        areaName: this.curArea.areaName
+      };
+      this.renderChartData = {
+        levelData: this.levelData,
+        lineChartData: this.lineChartData
+      };
+      this.renderExportPage = true;
+    },
+    exportOver(result) {
+      if (!result) {
+        this.$Message.error("导出失败,请重新尝试!");
+      }
+      this.renderExportPage = false;
+      this.isDownload = false;
+    },
+    cancel() {
+      this.modalIsShow = false;
+    },
+    open() {
+      this.modalIsShow = true;
+    }
+  }
+};
+</script>

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

@@ -213,7 +213,8 @@ export default {
       "setParamSet",
       "setPage",
       "setSteps",
-      "setCurStep"
+      "setCurStep",
+      "clearState"
     ]),
     async initData() {
       await this.getParamsSetInfo();
@@ -398,11 +399,11 @@ export default {
 
       // update paper list
       if (
-        this.current > 1 &&
-        this.current === this.pageCount &&
+        this.page.current > 1 &&
+        this.page.current === this.page.totalPage &&
         this.papers.length === multipleGradingListCount
       ) {
-        this.current--;
+        this.setPage({ current: this.page.current - 1 });
       }
 
       await this.getList();
@@ -429,9 +430,9 @@ export default {
     },
     async toPrevPaper() {
       if (this.curPaperIndex === 0) {
-        if (this.current > 1) {
-          this.current--;
-          this.curPaperIndex = this.size - 1;
+        if (this.page.current > 1) {
+          this.setPage({ current: this.page.current - 1 });
+          this.curPaperIndex = this.page.size - 1;
           await this.getList();
         } else {
           this.$Message.warning("当前已经是第一条数据了");
@@ -445,11 +446,11 @@ export default {
     },
     async toNextPaper() {
       if (this.curPaperIndex === this.papers.length - 1) {
-        if (this.current === this.totalPage) {
+        if (this.page.current === this.page.totalPage) {
           this.$Message.warning("当前已经是最后一条数据了");
           return;
         } else {
-          this.current++;
+          this.setPage({ current: this.page.current + 1 });
           this.curPaperIndex = 0;
           await this.getList();
         }
@@ -460,9 +461,9 @@ export default {
       this.selectPaper(this.curPaperIndex);
     },
     async toActionNextPaper() {
-      if (this.current > 1 && this.papers.length === 1) {
-        this.current--;
-        this.curPaperIndex = this.size;
+      if (this.page.current > 1 && this.papers.length === 1) {
+        this.setPage({ current: this.page.current - 1 });
+        this.curPaperIndex = this.page.size;
       }
 
       await this.getList();
@@ -534,6 +535,9 @@ export default {
     toStatistics() {
       this.$refs.MarkerStatistics.open();
     }
+  },
+  beforeDestroy() {
+    this.clearState();
   }
 };
 </script>

+ 12 - 1
src/modules/grading/marker/MarkerHeader.vue

@@ -122,6 +122,9 @@
           </DropdownMenu>
         </Dropdown>
       </div>
+      <div v-if="IS_MARK_LEADER" class="header-part" @click="toProgress">
+        <p>分档进度 <Icon type="ios-arrow-down"></Icon></p>
+      </div>
       <div class="header-part" @click="toStandard">
         <p>标准卷 <Icon type="ios-arrow-down"></Icon></p>
       </div>
@@ -171,6 +174,7 @@ export default {
         workId: "",
         subject: ""
       },
+      curUserRoleType: "",
       username: this.$ls.get("user", { loginName: "" }).loginName,
       areas: [],
       curArea: { areaName: "校区" },
@@ -180,12 +184,16 @@ export default {
     };
   },
   computed: {
-    ...mapState("marker", ["page", "curStep", "steps"])
+    ...mapState("marker", ["page", "curStep", "steps"]),
+    IS_MARK_LEADER() {
+      return this.curUserRoleType === "MARK_LEADER";
+    }
   },
   mounted() {
     const subjectId = this.$route.params.subjectId.split("-");
     this.filter.workId = subjectId[0];
     this.filter.subject = subjectId[1];
+    this.curUserRoleType = this.$ls.get("user", { role: "" }).role;
     this.getAreaList();
   },
   methods: {
@@ -215,6 +223,9 @@ export default {
       );
       this.$emit("step-change", curStep);
     },
+    toProgress() {
+      this.$emit("to-progress");
+    },
     toHistory() {
       this.$emit("to-history");
     },

+ 2 - 1
src/modules/grading/marker/MarkerHistory.vue

@@ -7,7 +7,7 @@
     :transition-names="['slide-up', 'fade']"
     @on-visible-change="visibleChange"
   >
-    <div class="history-image-list marker-image-list">
+    <div class="history-image-list marker-image-list" v-if="papers.length">
       <div
         v-for="(paper, index) in papers"
         :key="paper.id"
@@ -26,6 +26,7 @@
         </div>
       </div>
     </div>
+    <div v-else class="history-image-list marker-image-none">暂无数据</div>
   </Modal>
 </template>
 

+ 6 - 6
src/modules/grading/marker/MarkerStatistics.vue

@@ -8,23 +8,23 @@
     @on-visible-change="visibleChange"
   >
     <div class="marker-statistics-table">
-      <table class="table">
+      <table class="table table-dark">
         <tr>
           <th>档位</th>
-          <th v-if="showCount">考区定档数量</th>
+          <th v-if="showPaperRelateCount">考区定档数量</th>
           <th>考区内试卷总数</th>
           <th>考区阈值</th>
-          <th v-if="showCount">当前批次评卷员分档数量</th>
+          <th v-if="showPaperRelateCount">当前批次评卷员分档数量</th>
           <th>当前批次试卷总数</th>
           <!-- <th>当前批次阈值</th> -->
           <!-- <th>操作</th> -->
         </tr>
         <tr v-for="(step, sindex) in steps.levelStep" :key="sindex">
           <td>{{ step.name }}</td>
-          <td v-if="showCount">{{ step.gcount }}</td>
+          <td v-if="showPaperRelateCount">{{ step.gcount }}</td>
           <td>{{ step.gpercent }}%</td>
           <td>{{ step.pt }}%</td>
-          <td v-if="showCount">{{ step.count }}</td>
+          <td v-if="showPaperRelateCount">{{ step.count }}</td>
           <td>{{ step.percent }}%</td>
           <!-- <td>{{ step.kdpt !== null ? step.kdpt + "%" : "" }}</td> -->
           <!-- <td><p @click="stepClick(step)">进入评卷</p></td> -->
@@ -57,7 +57,7 @@ export default {
   },
   computed: {
     ...mapState("marker", ["paramsSet", "steps"]),
-    showCount() {
+    showPaperRelateCount() {
       return !!this.paramsSet["showPaperCount"];
     }
   },

+ 22 - 1
src/modules/grading/marker/store.js

@@ -7,7 +7,9 @@ const state = {
     totalPage: 1
   },
   steps: {},
-  curStep: { name: "", count: 0 }
+  curStep: { name: "", count: 0 },
+  curArea: {},
+  curSubject: {}
 };
 const mutations = {
   setParamSet(state, paramsSet) {
@@ -21,6 +23,25 @@ const mutations = {
   },
   setCurStep(state, curStep) {
     state.curStep = curStep;
+  },
+  setCurArea(state, curArea) {
+    state.curArea = curArea;
+  },
+  setCurSubject(state, curSubject) {
+    state.curSubject = curSubject;
+  },
+  clearState(state) {
+    state.paramsSet = {};
+    state.page = {
+      current: 1,
+      size: 12,
+      total: 0,
+      totalPage: 1
+    };
+    state.steps = {};
+    state.curStep = { name: "", count: 0 };
+    state.curArea = {};
+    state.curSubject = {};
   }
 };
 

+ 1 - 1
src/modules/login/LoginHome.vue

@@ -93,7 +93,7 @@ export default {
           router: "MarkOperation"
         },
         MARK_LEADER_LEVEL: {
-          router: "Grading"
+          router: "LeaderGrading"
         },
         MARK_LEADER_SCORE: {
           router: "Mark"

+ 9 - 0
src/routers/grading.js

@@ -11,6 +11,7 @@ import GradingStandardPaperManage from "../modules/grading/GradingStandardPaperM
 // 阅卷员分档
 import GradingOperation from "../modules/grading/GradingOperation";
 import MarkerGrading from "../modules/grading/marker/MarkerGrading";
+import LeaderGrading from "../modules/grading/leader/LeaderGrading";
 
 const gradingRoutes = [
   {
@@ -95,5 +96,13 @@ export default [
     meta: {
       title: "阅卷员分档"
     }
+  },
+  {
+    path: "/leader-grading/:workId(\\d+)/:subjectId",
+    name: "LeaderGrading",
+    component: LeaderGrading,
+    meta: {
+      title: "科组长分档"
+    }
   }
 ];